Skip to content

Commit d78fcf8

Browse files
committed
- Ability to customize cXML DTD and model
- Introduction of PaymentTerm, PCard, PaymentToken, PaymentReference (Extension) - Some refactorings - Switched to readonly properties (where possible)
1 parent 1e6069b commit d78fcf8

File tree

112 files changed

+1101
-1249
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

112 files changed

+1101
-1249
lines changed

docs/cXMLReferenceGuide.pdf

-3.92 MB
Binary file not shown.

readme.md

Lines changed: 41 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,6 @@
55
>
66
> cXML Reference Guide (PDF): http://xml.cxml.org/current/cXMLReferenceGuide.pdf
77
8-
# Status
9-
10-
| CXML Version | Status Test |
11-
|--------------|-------------|
12-
| 1.2.050 | OK |
13-
| 1.2.053 | OK |
14-
158
# Getting Started
169

1710
## Installation
@@ -112,10 +105,10 @@ $cXmlProcessor->process($cXml);
112105

113106
```php
114107
$credentialRegistry = new \CXml\Credential\Registry();
115-
//TODO register...
108+
//TODO register credentials...
116109

117110
$handlerRegistry = new \CXml\Handler\HandlerRegistry();
118-
//TODO register...
111+
//TODO register handler...
119112

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

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

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

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

170-
# Credits
171-
- Markus Thielen (https://github.com/mathielen)
165+
## Extending cXML
166+
167+
### Add custom elements
168+
169+
The definition of cXML is open for extension. There are ways to extend the DTD with overriding existing variables and
170+
therefore adding custom elements. With version 2.1.0 we introduced a way to add custom elements to the cXML model.
171+
172+
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
173+
elements and attributes in the variables that are defined in the original DTD file.
174+
175+
TODO this is only really implemented for the Payment node at the moment.
176+
177+
#### Example
178+
An example of a custom DTD file that adds a custom element to the `PaymentReference` element:
179+
180+
```dtd
181+
<!ENTITY % cxml.payment "( PCard | PaymentToken | PaymentReference* )">
182+
183+
<!ENTITY % elements SYSTEM "http://xml.cxml.org/schemas/cXML/1.2.063/cXML.dtd">
184+
%elements;
185+
186+
<!ELEMENT PaymentReference (Money, IdReference*, Extrinsic*)>
187+
<!ATTLIST PaymentReference
188+
method CDATA #REQUIRED
189+
provider CDATA #IMPLIED
190+
>
191+
```
192+
193+
To use this DTD file for validation as well as for serialization and deserialization, you could save the file next to the
194+
other DTD files from cXML and use `DtdValidator::fromDtdDirectory` just as you would with the original DTD files. Or you
195+
could explicitly load only the new DTD file with `new DtdValidator($arrayOfDtdFilepaths)`.
196+
197+
Also you would probably want newly generated cXML files to point to your DTD file. You can do this by telling the
198+
serializer to use your DTD file: `Serializer::create('http://...publicUrlToYourDtd')`.
199+
200+
Now the new element also has to be known by the serializer. Usually the model classes can be found in `CXml\Model`.

src/CXml/Authentication/SimpleSharedSecretAuthenticator.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ public function __construct(private string $sharedSecret)
1616

1717
public function authenticate(Header $header, Context $context): void
1818
{
19-
if ($this->sharedSecret !== $header->getSender()->getCredential()->getSharedSecret()) {
20-
throw new CXmlAuthenticationInvalidException($header->getSender()->getCredential());
19+
if ($this->sharedSecret !== $header->sender->credential->getSharedSecret()) {
20+
throw new CXmlAuthenticationInvalidException($header->sender->credential);
2121
}
2222
}
2323
}

src/CXml/Builder/OrderRequestBuilder.php

Lines changed: 34 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
use CXml\Model\Message\PunchOutOrderMessage;
1919
use CXml\Model\MoneyWrapper;
2020
use CXml\Model\MultilanguageString;
21+
use CXml\Model\Payment;
22+
use CXml\Model\PaymentTerm;
2123
use CXml\Model\Phone;
2224
use CXml\Model\PostalAddress;
2325
use CXml\Model\PriceBasisQuantity;
@@ -57,6 +59,10 @@ class OrderRequestBuilder
5759

5860
private array $businessPartners = [];
5961

62+
private ?Payment $payment = null;
63+
64+
private ?PaymentTerm $paymentTerm = null;
65+
6066
private function __construct(
6167
private readonly string $orderId,
6268
private readonly DateTimeInterface $orderDate,
@@ -83,12 +89,12 @@ public static function fromPunchOutOrderMessage(
8389
?DateTimeInterface $orderDate = null,
8490
string $language = 'en',
8591
): self {
86-
if (($supplierOrderInfo = $punchOutOrderMessage->getPunchOutOrderMessageHeader()->getSupplierOrderInfo()) instanceof SupplierOrderInfo) {
87-
$orderId ??= $supplierOrderInfo->getOrderId();
88-
$orderDate ??= $supplierOrderInfo->getOrderDate();
92+
if (($supplierOrderInfo = $punchOutOrderMessage->punchOutOrderMessageHeader->getSupplierOrderInfo()) instanceof SupplierOrderInfo) {
93+
$orderId ??= $supplierOrderInfo->orderId;
94+
$orderDate ??= $supplierOrderInfo->orderDate;
8995
}
9096

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

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

109-
$orb->setShipTo($punchOutOrderMessage->getPunchOutOrderMessageHeader()->getShipTo());
115+
$orb->setShipTo($punchOutOrderMessage->punchOutOrderMessageHeader->getShipTo());
110116

111117
foreach ($punchOutOrderMessage->getPunchoutOrderMessageItems() as $item) {
112118
$orb->addItem(
113-
$item->getQuantity(),
114-
$item->getItemId(),
115-
$item->getItemDetail()->getDescription()->getValue(),
116-
$item->getItemDetail()->getUnitOfMeasure(),
117-
$item->getItemDetail()->getUnitPrice()->getMoney()->getValueCent(),
119+
$item->quantity,
120+
$item->itemId,
121+
$item->itemDetail->description->value,
122+
$item->itemDetail->unitOfMeasure,
123+
$item->itemDetail->unitPrice->money->getValueCent(),
118124
[
119125
new Classification('custom', '0'), // TODO make this configurable
120126
],
@@ -156,6 +162,7 @@ public function shipTo(
156162
array $carrierIdentifiers = [],
157163
?string $carrierAccountNo = null,
158164
?string $carrierShippingMethod = null,
165+
array $idReferences = [],
159166
): self {
160167
$transportInformation = null;
161168
if (null !== $carrierAccountNo || null != $carrierShippingMethod) {
@@ -174,6 +181,10 @@ public function shipTo(
174181
$this->shipTo->addCarrierIdentifier($domain, $identifier);
175182
}
176183

184+
foreach ($idReferences as $domain => $identifier) {
185+
$this->shipTo->addIdReference($domain, $identifier);
186+
}
187+
177188
return $this;
178189
}
179190

@@ -249,13 +260,13 @@ public function addItem(
249260
$priceBasisQuantity,
250261
),
251262
$requestDeliveryDate,
252-
$parent instanceof ItemOut ? $parent->getLineNumber() : null,
263+
$parent instanceof ItemOut ? $parent->lineNumber : null,
253264
);
254265

255266
$this->items[] = $item;
256267

257-
if ($priceBasisQuantity instanceof PriceBasisQuantity && $priceBasisQuantity->getQuantity() > 0) {
258-
$this->total += (int)round($quantity * ($priceBasisQuantity->getConversionFactor() / $priceBasisQuantity->getQuantity()) * $unitPrice);
268+
if ($priceBasisQuantity instanceof PriceBasisQuantity && $priceBasisQuantity->quantity > 0) {
269+
$this->total += (int)round($quantity * ($priceBasisQuantity->conversionFactor / $priceBasisQuantity->quantity) * $unitPrice);
259270
} else {
260271
$this->total += ($quantity * $unitPrice);
261272
}
@@ -308,6 +319,8 @@ private function buildOrderRequestHeader(): OrderRequestHeader
308319
$this->contacts,
309320
)
310321
->setShipping($this->shipping)
322+
->setPayment($this->payment)
323+
->setPaymentTerm($this->paymentTerm)
311324
->setTax($this->tax);
312325

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

360373
$this->businessPartners[] = $bp;
361374
}
375+
376+
public function setPayment(?Payment $payment, ?PaymentTerm $paymentTerm): self
377+
{
378+
$this->payment = $payment;
379+
$this->paymentTerm = $paymentTerm;
380+
381+
return $this;
382+
}
362383
}

src/CXml/Builder/PunchOutOrderMessageBuilder.php

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -165,15 +165,15 @@ public function addItem(ItemIn $itemIn): self
165165
{
166166
$this->punchoutOrderMessageItems[] = $itemIn;
167167

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

171171
if (
172-
$itemIn->getItemDetail()->getPriceBasisQuantity() instanceof PriceBasisQuantity
173-
&& $itemIn->getItemDetail()->getPriceBasisQuantity()->getQuantity() > 0
172+
$itemIn->itemDetail->priceBasisQuantity instanceof PriceBasisQuantity
173+
&& $itemIn->itemDetail->priceBasisQuantity->quantity > 0
174174
) {
175-
$priceBasisQuantity = $itemIn->getItemDetail()->getPriceBasisQuantity();
176-
$this->total += (int)round($itemQty * ($priceBasisQuantity->getConversionFactor() / $priceBasisQuantity->getQuantity()) * $moneyValueCent);
175+
$priceBasisQuantity = $itemIn->itemDetail->priceBasisQuantity;
176+
$this->total += (int)round($itemQty * ($priceBasisQuantity->conversionFactor / $priceBasisQuantity->quantity) * $moneyValueCent);
177177
} else {
178178
$this->total += $moneyValueCent * $itemQty;
179179
}

src/CXml/Context.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,12 +61,12 @@ public function getSenderUserAgent(): ?string
6161
return null;
6262
}
6363

64-
$header = $cxml->getHeader();
64+
$header = $cxml->header;
6565
if (!$header instanceof Header) {
6666
return null;
6767
}
6868

69-
return $header->getSender()->getUserAgent();
69+
return $header->sender->userAgent;
7070
}
7171

7272
public function getPayloadId(): ?string
@@ -76,6 +76,6 @@ public function getPayloadId(): ?string
7676
return null;
7777
}
7878

79-
return $cxml->getPayloadId();
79+
return $cxml->payloadId;
8080
}
8181
}

src/CXml/Credential/Registry.php

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,11 @@ public function registerCredential(Credential $credential): void
3131
public function getCredentialByDomainAndId(string $domain, string $identity): Credential
3232
{
3333
foreach ($this->registeredCredentials as $registeredCredential) {
34-
if ($registeredCredential->getDomain() !== $domain) {
34+
if ($registeredCredential->domain !== $domain) {
3535
continue;
3636
}
3737

38-
if ($registeredCredential->getIdentity() !== $identity) {
38+
if ($registeredCredential->identity !== $identity) {
3939
continue;
4040
}
4141

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

5656
$baseCredential = $this->getCredentialByDomainAndId(
57-
$senderCredential->getDomain(),
58-
$senderCredential->getIdentity(),
57+
$senderCredential->domain,
58+
$senderCredential->identity,
5959
);
6060

6161
if ($baseCredential->getSharedSecret() !== $senderCredential->getSharedSecret()) {
@@ -70,8 +70,8 @@ public function validate(Credential $credential): void
7070
{
7171
// provoke an exception if credential was not found
7272
$this->getCredentialByDomainAndId(
73-
$credential->getDomain(),
74-
$credential->getIdentity(),
73+
$credential->domain,
74+
$credential->identity,
7575
);
7676
}
7777
}

0 commit comments

Comments
 (0)