Skip to content

Update composer Q2-2025 [PHPSTAN v2, Rector V2] #43

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,16 +56,16 @@ jobs:
run: vendor/bin/parallel-lint src/

- name: Run CodeStyle checks
run: composer run cs-check
run: composer run cs:check

- name: Run PHPStan
run: composer run phpstan
- name: Run PHPStan check
run: composer run phpstan:check

- name: Run Rector
run: composer run rector-check
- name: Run Rector check
run: composer run rector:check

- name: Run Tests
run: composer run test
- name: Run PhpUnit tests
run: composer run phpunit:test

- name: Run Security check
run: composer run security-check
run: composer run security:check
52 changes: 36 additions & 16 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
"ext-simplexml": "*",
"ext-dom": "*",
"ext-libxml": "*",
"beberlei/assert": "@stable",
"beberlei/assert": "^2.0 || ^3.0",
"jms/serializer": "^3.30.0",
"psr/log": "^1.0 || ^2.0 || ^3.0",
"psr/event-dispatcher": "^1.0.0"
Expand All @@ -37,18 +37,19 @@
"symfony/routing": "If you want to use SelfAwareProfileRequestHandler"
},
"require-dev": {
"phpunit/phpunit": "^11",
"phpstan/phpstan": "^1.11.0",
"phpunit/phpunit": "^11.0 || ^12.0",
"phpstan/phpstan": "^2.0",
"friendsofphp/php-cs-fixer": "*",
"php-parallel-lint/php-parallel-lint": "*",
"enlightn/security-checker": "*",
"symfony/routing": "^4.4.44 || ^5.0.0 || ^6.0.0 || ^7.0.0",
"rector/rector": "^1.1",
"phpstan/extension-installer": "^1.3",
"phpstan/phpstan-strict-rules": "^1.6",
"phpstan/phpstan-deprecation-rules": "^1.2",
"goetas/jms-serializer-phpstan-extension": "^1.0",
"tomasvotruba/type-coverage": "^0.3.0 || ^1.0.0"
"rector/rector": "^2.0",
"phpstan/extension-installer": "^1.4.0",
"phpstan/phpstan-strict-rules": "^2.0",
"phpstan/phpstan-deprecation-rules": "^2.0",
"goetas/jms-serializer-phpstan-extension": "^1.3.0",
"tomasvotruba/type-coverage": "^2.0",
"phpstan/phpstan-beberlei-assert": "^2.0"
},
"autoload": {
"psr-4": {
Expand All @@ -61,17 +62,36 @@
}
},
"scripts": {
"test": "vendor/bin/phpunit --testdox tests",
"cs-check": "PHP_CS_FIXER_IGNORE_ENV=1 vendor/bin/php-cs-fixer check --diff",
"cs-fix": "PHP_CS_FIXER_IGNORE_ENV=1 vendor/bin/php-cs-fixer fix --diff",
"phpstan": "vendor/bin/phpstan analyze",
"rector-check": "vendor/bin/rector process --dry-run",
"rector": "vendor/bin/rector process",
"security-check": "vendor/bin/security-checker security:check composer.lock"
"phpunit:test": "vendor/bin/phpunit --testdox tests",
"cs:check": "PHP_CS_FIXER_IGNORE_ENV=1 vendor/bin/php-cs-fixer check --diff",
"cs:fix": "PHP_CS_FIXER_IGNORE_ENV=1 vendor/bin/php-cs-fixer fix --diff",
"phpstan:check": "vendor/bin/phpstan analyze",
"rector:check": "vendor/bin/rector process --dry-run",
"rector:fix": "vendor/bin/rector process",
"security:check": "vendor/bin/security-checker security:check composer.lock",
"run:all": [
"@phpunit:test",
"@cs:check",
"@cs:fix",
"@phpstan:check",
"@rector:check",
"@rector:fix",
"@security:check"
],
"test:all": [
"@phpunit:test",
"@cs:check",
"@phpstan:check",
"@rector:check",
"@security:check"
]
},
"config": {
"allow-plugins": {
"phpstan/extension-installer": true
},
"platform": {
"php": "8.2.28"
}
}
}
2 changes: 1 addition & 1 deletion rector.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
])
->withFileExtensions(['php'])
->withCache(
cacheDirectory: '/tmp/rector',
cacheDirectory: '/tmp/rector-cxml-php',
cacheClass: FileCacheStorage::class,
)
->withParallel(
Expand Down
6 changes: 6 additions & 0 deletions src/CXml/Builder.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@
class Builder
{
// according to cXML reference document
/**
* @var array<class-string<CXmlException>, int>
*/
private static array $exceptionMapping = [
CXmlAuthenticationInvalidException::class => 401,
CXmlNotAcceptableException::class => 406,
Expand All @@ -42,6 +45,9 @@ class Builder
];

// TODO create enum for this?
/**
* @var array<int, string>
*/
private static array $exceptionCodeMapping = [
// cxml
450 => 'Not Implemented',
Expand Down
51 changes: 47 additions & 4 deletions src/CXml/Builder/OrderRequestBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace CXml\Builder;

use Assert\Assertion;
use CXml\Model\Address;
use CXml\Model\BillTo;
use CXml\Model\BusinessPartner;
Expand Down Expand Up @@ -39,12 +40,21 @@

class OrderRequestBuilder
{
/**
* @var ItemOut[]
*/
private array $items = [];

private int $total = 0;

/**
* @var Comment[]
*/
private array $comments = [];

/**
* @var Contact[]
*/
private array $contacts = [];

private ?ShipTo $shipTo = null;
Expand All @@ -55,8 +65,14 @@ class OrderRequestBuilder

private ?Tax $tax = null;

/**
* @var Extrinsic[]
*/
private array $extrinsics = [];

/**
* @var BusinessPartner[]
*/
private array $businessPartners = [];

private ?Payment $payment = null;
Expand Down Expand Up @@ -114,11 +130,12 @@ public static function fromPunchOutOrderMessage(

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

/** @var \CXml\Model\ItemIn $item */
foreach ($punchOutOrderMessage->getPunchoutOrderMessageItems() as $item) {
$orb->addItem(
$item->quantity,
$item->itemId,
$item->itemDetail->description->value,
$item->itemDetail->description->value ?? '',
$item->itemDetail->unitOfMeasure,
$item->itemDetail->unitPrice->money->getValueCent(),
[
Expand Down Expand Up @@ -165,7 +182,7 @@ public function shipTo(
array $idReferences = [],
): self {
$transportInformation = null;
if (null !== $carrierAccountNo || null != $carrierShippingMethod) {
if (null !== $carrierAccountNo || null !== $carrierShippingMethod) {
$transportInformation = TransportInformation::create($carrierAccountNo, $carrierShippingMethod);
}

Expand All @@ -178,10 +195,14 @@ public function shipTo(
);

foreach ($carrierIdentifiers as $domain => $identifier) {
Assertion::string($domain, 'Carrier identifier domain must be a string');
Assertion::string($identifier, 'Carrier identifier must be a string');
$this->shipTo->addCarrierIdentifier($domain, $identifier);
}

foreach ($idReferences as $domain => $identifier) {
Assertion::string($domain, 'ID reference domain must be a string');
Assertion::string($identifier, 'ID reference identifier must be a string');
$this->shipTo->addIdReference($domain, $identifier);
}

Expand Down Expand Up @@ -215,12 +236,32 @@ public function tax(int $costs, string $description, array $taxDetails = []): se
);

foreach ($taxDetails as $taxDetail) {
Assertion::isArray($taxDetail, 'Tax detail must be an array');

Assertion::keyExists($taxDetail, 'category', 'Tax detail must contain "category"');
Assertion::string($taxDetail['category'], 'Tax detail "category" must be a string');

Assertion::keyExists($taxDetail, 'amount', 'Tax detail must contain "amount"');
Assertion::integer($taxDetail['amount'], 'Tax detail "amount" must be an integer');

$rate = null;
if (isset($taxDetail['rate'])) {
Assertion::integer($taxDetail['rate'], 'Tax detail "rate" must be an integer');
$rate = $taxDetail['rate'];
}

$type = null;
if (isset($taxDetail['type'])) {
Assertion::string($taxDetail['type'], 'Tax detail "type" must be a string');
$type = $taxDetail['type'];
}

$this->tax->addTaxDetail(
new TaxDetail(
$taxDetail['category'],
new MoneyWrapper($this->currency, $taxDetail['amount']),
$taxDetail['rate'] ?? null,
$taxDetail['type'] ?? null,
$rate,
$type,
),
);
}
Expand Down Expand Up @@ -367,6 +408,8 @@ public function addBusinessPartner(string $role, string $name, array $idReferenc
);

foreach ($idReferences as $domain => $identifier) {
Assertion::string($domain, 'ID reference domain must be a string');
Assertion::string($identifier, 'ID reference identifier must be a string');
$bp->addIdReference($domain, $identifier);
}

Expand Down
3 changes: 3 additions & 0 deletions src/CXml/Builder/ProductActivityMessageBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace CXml\Builder;

use Assert\Assertion;
use CXml\Model\Contact;
use CXml\Model\Inventory;
use CXml\Model\InventoryQuantity;
Expand Down Expand Up @@ -43,6 +44,8 @@ public function addProductActivityDetail(string $sku, string $warehouseCode, int

if (null !== $extrinsics && [] !== $extrinsics) {
foreach ($extrinsics as $k => $v) {
Assertion::string($k, 'Extrinsics key must be a string');
Assertion::string($v, 'Extrinsics value must be a string');
$activityDetail->addExtrinsicAsKeyValue($k, $v);
}
}
Expand Down
7 changes: 6 additions & 1 deletion src/CXml/Builder/PunchOutOrderMessageBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace CXml\Builder;

use Assert\Assertion;
use CXml\Model\Address;
use CXml\Model\Description;
use CXml\Model\ItemDetail;
Expand Down Expand Up @@ -68,7 +69,7 @@ public function shipTo(
?string $carrierShippingMethod = null,
): self {
$transportInformation = null;
if (null !== $carrierAccountNo || null != $carrierShippingMethod) {
if (null !== $carrierAccountNo || null !== $carrierShippingMethod) {
$transportInformation = TransportInformation::create($carrierAccountNo, $carrierShippingMethod);
}

Expand All @@ -81,6 +82,8 @@ public function shipTo(
);

foreach ($carrierIdentifiers as $domain => $identifier) {
Assertion::string($domain, 'Carrier identifier domain must be a string');
Assertion::string($identifier, 'Carrier identifier must be a string');
$this->shipTo->addCarrierIdentifier($domain, $identifier);
}

Expand Down Expand Up @@ -148,6 +151,8 @@ public function addPunchoutOrderMessageItem(

if (null !== $extrinsics && [] !== $extrinsics) {
foreach ($extrinsics as $k => $v) {
Assertion::string($k, 'Extrinsics key must be a string');
Assertion::string($v, 'Extrinsics value must be a string');
$itemDetail->addExtrinsicAsKeyValue($k, $v);
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/CXml/Context.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public function setDryRun(bool $dryrun): self

public function isDryRun(): bool
{
return $this->options['dryrun'] ?? false;
return (bool)$this->getOption('dryrun');
}

public function getCXml(): ?CXml
Expand Down
18 changes: 17 additions & 1 deletion src/CXml/Jms/CXmlWrappingNodeJmsEventSubscriber.php
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,6 @@ public static function getSubscribedEvents(): array
'method' => 'onPreDeserializeCXmlMainPayload',
'format' => 'xml',
],

[
'event' => Events::POST_SERIALIZE,
'method' => 'onPostSerializePayment',
Expand Down Expand Up @@ -102,6 +101,7 @@ public function onPostSerializePayment(ObjectEvent $event): void
}

foreach ($paymentImplList as $impl) {
/** @phpstan-ignore-next-line */
$cls = (new ReflectionClass($impl))->getShortName();

$visitor->visitProperty(
Expand Down Expand Up @@ -131,6 +131,7 @@ public function onPreDeserializePayment(PreDeserializeEvent $event): void

$isArray = count($data->children()) > 1;
if ($isArray) {
$propertyMetadata->serializedName = 'PaymentReference';
$propertyMetadata->xmlEntryName = 'PaymentReference';
$propertyMetadata->xmlCollection = true;
$propertyMetadata->xmlCollectionInline = true;
Expand All @@ -146,6 +147,10 @@ public function onPreDeserializePayment(PreDeserializeEvent $event): void
]);
} else {
$payloadNode = $data->children()[0];
if (!$payloadNode instanceof SimpleXMLElement) {
return;
}

$serializedName = $payloadNode->getName();
$cls = $this->modelClassMapping->findClassForSerializedName($serializedName);

Expand All @@ -162,6 +167,11 @@ public function onPreDeserializePayment(PreDeserializeEvent $event): void
public function onPostSerializeCXmlMainPayload(ObjectEvent $event): void
{
$incomingType = $event->getType()['name'];

if (!is_string($incomingType)) {
return;
}

if (!self::isEligible($incomingType)) {
return;
}
Expand All @@ -174,6 +184,7 @@ public function onPostSerializeCXmlMainPayload(ObjectEvent $event): void
$payload = $event->getObject()->payload ?? null;

if ($payload) {
/** @phpstan-ignore-next-line */
$cls = (new ReflectionClass($payload))->getShortName();

// tell jms to add the payload value in a wrapped node
Expand All @@ -190,6 +201,11 @@ public function onPostSerializeCXmlMainPayload(ObjectEvent $event): void
public function onPreDeserializeCXmlMainPayload(PreDeserializeEvent $event): void
{
$incomingType = $event->getType()['name'];

if (!is_string($incomingType)) {
return;
}

if (!self::isEligible($incomingType)) {
return;
}
Expand Down
Loading