Skip to content

Commit

Permalink
- Switched to readonly properties (where possible)
Browse files Browse the repository at this point in the history
  • Loading branch information
mathielen authored Feb 4, 2025
1 parent 1e6069b commit e39471a
Show file tree
Hide file tree
Showing 112 changed files with 1,101 additions and 1,249 deletions.
Binary file removed docs/cXMLReferenceGuide.pdf
Binary file not shown.
53 changes: 41 additions & 12 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,6 @@
>
> cXML Reference Guide (PDF): http://xml.cxml.org/current/cXMLReferenceGuide.pdf
# Status

| CXML Version | Status Test |
|--------------|-------------|
| 1.2.050 | OK |
| 1.2.053 | OK |

# Getting Started

## Installation
Expand Down Expand Up @@ -112,10 +105,10 @@ $cXmlProcessor->process($cXml);

```php
$credentialRegistry = new \CXml\Credential\Registry();
//TODO register...
//TODO register credentials...

$handlerRegistry = new \CXml\Handler\HandlerRegistry();
//TODO register...
//TODO register handler...

$builder = \CXml\Builder::create();

Expand All @@ -127,9 +120,11 @@ $cXmlProcessor = new \CXml\Processor\Processor(
);

$pathToDtd = '.'; //point the directory with extracted contents of zip-file with the DTDs, downloaded from cxml.org
$dtdValidator = new \CXml\Validation\DtdValidator($pathToDtd);
$dtdValidator = \CXml\Validation\DtdValidator::fromDtdDirectory($pathToDtd);
$serializer = \CXml\Serializer::create();

$endpoint = new \CXml\Endpoint(
$serializer,
$dtdValidator,
$cXmlProcessor
);
Expand Down Expand Up @@ -167,5 +162,39 @@ value.
When parsing a date-property from a cXML document, the `CXml\Model\Date` will be instantiated **if** a date-only
value was discovered (Y-m-d).

# Credits
- Markus Thielen (https://github.com/mathielen)
## Extending cXML

### Add custom elements

The definition of cXML is open for extension. There are ways to extend the DTD with overriding existing variables and
therefore adding custom elements. With version 2.1.0 we introduced a way to add custom elements to the cXML model.

To make this happen, we have to build our own DTD file and import the original DTD file in it. We can then add our own
elements and attributes in the variables that are defined in the original DTD file.

TODO this is only really implemented for the Payment node at the moment.

#### Example
An example of a custom DTD file that adds a custom element to the `PaymentReference` element:

```dtd
<!ENTITY % cxml.payment "( PCard | PaymentToken | PaymentReference* )">
<!ENTITY % elements SYSTEM "http://xml.cxml.org/schemas/cXML/1.2.063/cXML.dtd">
%elements;
<!ELEMENT PaymentReference (Money, IdReference*, Extrinsic*)>
<!ATTLIST PaymentReference
method CDATA #REQUIRED
provider CDATA #IMPLIED
>
```

To use this DTD file for validation as well as for serialization and deserialization, you could save the file next to the
other DTD files from cXML and use `DtdValidator::fromDtdDirectory` just as you would with the original DTD files. Or you
could explicitly load only the new DTD file with `new DtdValidator($arrayOfDtdFilepaths)`.

Also you would probably want newly generated cXML files to point to your DTD file. You can do this by telling the
serializer to use your DTD file: `Serializer::create('http://...publicUrlToYourDtd')`.

Now the new element also has to be known by the serializer. Usually the model classes can be found in `CXml\Model`.
4 changes: 2 additions & 2 deletions src/CXml/Authentication/SimpleSharedSecretAuthenticator.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ public function __construct(private string $sharedSecret)

public function authenticate(Header $header, Context $context): void
{
if ($this->sharedSecret !== $header->getSender()->getCredential()->getSharedSecret()) {
throw new CXmlAuthenticationInvalidException($header->getSender()->getCredential());
if ($this->sharedSecret !== $header->sender->credential->getSharedSecret()) {
throw new CXmlAuthenticationInvalidException($header->sender->credential);
}
}
}
47 changes: 34 additions & 13 deletions src/CXml/Builder/OrderRequestBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
use CXml\Model\Message\PunchOutOrderMessage;
use CXml\Model\MoneyWrapper;
use CXml\Model\MultilanguageString;
use CXml\Model\Payment;
use CXml\Model\PaymentTerm;
use CXml\Model\Phone;
use CXml\Model\PostalAddress;
use CXml\Model\PriceBasisQuantity;
Expand Down Expand Up @@ -57,6 +59,10 @@ class OrderRequestBuilder

private array $businessPartners = [];

private ?Payment $payment = null;

private ?PaymentTerm $paymentTerm = null;

private function __construct(
private readonly string $orderId,
private readonly DateTimeInterface $orderDate,
Expand All @@ -83,12 +89,12 @@ public static function fromPunchOutOrderMessage(
?DateTimeInterface $orderDate = null,
string $language = 'en',
): self {
if (($supplierOrderInfo = $punchOutOrderMessage->getPunchOutOrderMessageHeader()->getSupplierOrderInfo()) instanceof SupplierOrderInfo) {
$orderId ??= $supplierOrderInfo->getOrderId();
$orderDate ??= $supplierOrderInfo->getOrderDate();
if (($supplierOrderInfo = $punchOutOrderMessage->punchOutOrderMessageHeader->getSupplierOrderInfo()) instanceof SupplierOrderInfo) {
$orderId ??= $supplierOrderInfo->orderId;
$orderDate ??= $supplierOrderInfo->orderDate;
}

$currency ??= $punchOutOrderMessage->getPunchOutOrderMessageHeader()->getTotal()->getMoney()->getCurrency();
$currency ??= $punchOutOrderMessage->punchOutOrderMessageHeader->total->money->currency;

if (null === $orderId) {
throw new LogicException('orderId should either be given or present in the PunchOutOrderMessage');
Expand All @@ -106,15 +112,15 @@ public static function fromPunchOutOrderMessage(
null,
);

$orb->setShipTo($punchOutOrderMessage->getPunchOutOrderMessageHeader()->getShipTo());
$orb->setShipTo($punchOutOrderMessage->punchOutOrderMessageHeader->getShipTo());

foreach ($punchOutOrderMessage->getPunchoutOrderMessageItems() as $item) {
$orb->addItem(
$item->getQuantity(),
$item->getItemId(),
$item->getItemDetail()->getDescription()->getValue(),
$item->getItemDetail()->getUnitOfMeasure(),
$item->getItemDetail()->getUnitPrice()->getMoney()->getValueCent(),
$item->quantity,
$item->itemId,
$item->itemDetail->description->value,
$item->itemDetail->unitOfMeasure,
$item->itemDetail->unitPrice->money->getValueCent(),
[
new Classification('custom', '0'), // TODO make this configurable
],
Expand Down Expand Up @@ -156,6 +162,7 @@ public function shipTo(
array $carrierIdentifiers = [],
?string $carrierAccountNo = null,
?string $carrierShippingMethod = null,
array $idReferences = [],
): self {
$transportInformation = null;
if (null !== $carrierAccountNo || null != $carrierShippingMethod) {
Expand All @@ -174,6 +181,10 @@ public function shipTo(
$this->shipTo->addCarrierIdentifier($domain, $identifier);
}

foreach ($idReferences as $domain => $identifier) {
$this->shipTo->addIdReference($domain, $identifier);
}

return $this;
}

Expand Down Expand Up @@ -249,13 +260,13 @@ public function addItem(
$priceBasisQuantity,
),
$requestDeliveryDate,
$parent instanceof ItemOut ? $parent->getLineNumber() : null,
$parent instanceof ItemOut ? $parent->lineNumber : null,
);

$this->items[] = $item;

if ($priceBasisQuantity instanceof PriceBasisQuantity && $priceBasisQuantity->getQuantity() > 0) {
$this->total += (int)round($quantity * ($priceBasisQuantity->getConversionFactor() / $priceBasisQuantity->getQuantity()) * $unitPrice);
if ($priceBasisQuantity instanceof PriceBasisQuantity && $priceBasisQuantity->quantity > 0) {
$this->total += (int)round($quantity * ($priceBasisQuantity->conversionFactor / $priceBasisQuantity->quantity) * $unitPrice);
} else {
$this->total += ($quantity * $unitPrice);
}
Expand Down Expand Up @@ -308,6 +319,8 @@ private function buildOrderRequestHeader(): OrderRequestHeader
$this->contacts,
)
->setShipping($this->shipping)
->setPayment($this->payment)
->setPaymentTerm($this->paymentTerm)
->setTax($this->tax);

foreach ($this->comments as $comment) {
Expand Down Expand Up @@ -359,4 +372,12 @@ public function addBusinessPartner(string $role, string $name, array $idReferenc

$this->businessPartners[] = $bp;
}

public function setPayment(?Payment $payment, ?PaymentTerm $paymentTerm): self
{
$this->payment = $payment;
$this->paymentTerm = $paymentTerm;

return $this;
}
}
12 changes: 6 additions & 6 deletions src/CXml/Builder/PunchOutOrderMessageBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -165,15 +165,15 @@ public function addItem(ItemIn $itemIn): self
{
$this->punchoutOrderMessageItems[] = $itemIn;

$moneyValueCent = $itemIn->getItemDetail()->getUnitPrice()->getMoney()->getValueCent();
$itemQty = $itemIn->getQuantity();
$moneyValueCent = $itemIn->itemDetail->unitPrice->money->getValueCent();
$itemQty = $itemIn->quantity;

if (
$itemIn->getItemDetail()->getPriceBasisQuantity() instanceof PriceBasisQuantity
&& $itemIn->getItemDetail()->getPriceBasisQuantity()->getQuantity() > 0
$itemIn->itemDetail->priceBasisQuantity instanceof PriceBasisQuantity
&& $itemIn->itemDetail->priceBasisQuantity->quantity > 0
) {
$priceBasisQuantity = $itemIn->getItemDetail()->getPriceBasisQuantity();
$this->total += (int)round($itemQty * ($priceBasisQuantity->getConversionFactor() / $priceBasisQuantity->getQuantity()) * $moneyValueCent);
$priceBasisQuantity = $itemIn->itemDetail->priceBasisQuantity;
$this->total += (int)round($itemQty * ($priceBasisQuantity->conversionFactor / $priceBasisQuantity->quantity) * $moneyValueCent);
} else {
$this->total += $moneyValueCent * $itemQty;
}
Expand Down
6 changes: 3 additions & 3 deletions src/CXml/Context.php
Original file line number Diff line number Diff line change
Expand Up @@ -61,12 +61,12 @@ public function getSenderUserAgent(): ?string
return null;
}

$header = $cxml->getHeader();
$header = $cxml->header;
if (!$header instanceof Header) {
return null;
}

return $header->getSender()->getUserAgent();
return $header->sender->userAgent;
}

public function getPayloadId(): ?string
Expand All @@ -76,6 +76,6 @@ public function getPayloadId(): ?string
return null;
}

return $cxml->getPayloadId();
return $cxml->payloadId;
}
}
14 changes: 7 additions & 7 deletions src/CXml/Credential/Registry.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,11 @@ public function registerCredential(Credential $credential): void
public function getCredentialByDomainAndId(string $domain, string $identity): Credential
{
foreach ($this->registeredCredentials as $registeredCredential) {
if ($registeredCredential->getDomain() !== $domain) {
if ($registeredCredential->domain !== $domain) {
continue;
}

if ($registeredCredential->getIdentity() !== $identity) {
if ($registeredCredential->identity !== $identity) {
continue;
}

Expand All @@ -51,11 +51,11 @@ public function getCredentialByDomainAndId(string $domain, string $identity): Cr
*/
public function authenticate(Header $header, Context $context): void
{
$senderCredential = $header->getSender()->getCredential();
$senderCredential = $header->sender->credential;

$baseCredential = $this->getCredentialByDomainAndId(
$senderCredential->getDomain(),
$senderCredential->getIdentity(),
$senderCredential->domain,
$senderCredential->identity,
);

if ($baseCredential->getSharedSecret() !== $senderCredential->getSharedSecret()) {
Expand All @@ -70,8 +70,8 @@ public function validate(Credential $credential): void
{
// provoke an exception if credential was not found
$this->getCredentialByDomainAndId(
$credential->getDomain(),
$credential->getIdentity(),
$credential->domain,
$credential->identity,
);
}
}
Loading

0 comments on commit e39471a

Please sign in to comment.