Skip to content
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
25 changes: 25 additions & 0 deletions src/File/Validation/ChoiceMaxOccursRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,35 @@

namespace WsdlToPhp\PackageGenerator\File\Validation;

/**
* The choice's maxOccurs attribute bounds the number of times the choice group may repeat,
* not the number of times the chosen element may occur within the group. When the element
* itself may occur more than once (its own maxOccurs is greater than 1 or unbounded), the
* element's occurrences count is constrained by its own maxOccurs rule, and applying the
* choice's bound to the element's items count would wrongly reject valid contents.
*
* @see https://github.com/WsdlToPhp/PackageGenerator/issues/340
*/
class ChoiceMaxOccursRule extends MaxOccursRule
{
public function name(): string
{
return 'choiceMaxOccurs';
}

public function testConditions(string $parameterName, $value, bool $itemType = false): string
{
$elementMaxOccurs = $this->getAttribute()->getMetaValueFirstSet([
'maxOccurs',
'maxoccurs',
'MaxOccurs',
'Maxoccurs',
], 1);

if ('unbounded' === $elementMaxOccurs || 1 < (int) $elementMaxOccurs) {
return '';
}

return parent::testConditions($parameterName, $value, $itemType);
}
}
2 changes: 1 addition & 1 deletion src/File/Validation/MaxOccursRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ public function symbol(): string
*
* @param mixed $value
*/
final public function testConditions(string $parameterName, $value, bool $itemType = false): string
public function testConditions(string $parameterName, $value, bool $itemType = false): string
{
$test = '';
if ($this->getAttribute()->isArray() && ((is_scalar($value) && 'unbounded' !== $value) || (is_array($value) && !in_array('unbounded', $value)))) {
Expand Down
21 changes: 21 additions & 0 deletions tests/File/StructTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -510,6 +510,27 @@ public function testStructValueListTypeFromUnitTests(): void
}
}

/**
* The choice elements have their own maxOccurs="5", the choice's maxOccurs (1) must
* not be applied to the elements' items count.
*
* @see https://github.com/WsdlToPhp/PackageGenerator/issues/340
*/
public function testStructItemsChoiceTypeFromUnitTests(): void
{
$generator = self::unitTestsInstance();
if (($model = $generator->getStructByName('ItemsChoiceType')) instanceof StructModel) {
$struct = new StructFile($generator, $model->getName());
$struct
->setModel($model)
->write()
;
$this->assertSameFileContent('ValidUnitTestsStructItemsChoiceType', $struct);
} else {
$this->fail('Unable to find ItemsChoiceType struct for file generation');
}
}

public function testWriteDeliveryDetails(): void
{
$generator = self::deliveryServiceInstance();
Expand Down
5 changes: 5 additions & 0 deletions tests/File/Validation/AbstractRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,11 @@ public static function getOrderContractAddressDeliveryTypeInstance(bool $reset =
return self::getClassInstance('orderContractInstance', 'AddressDelivery_Type', $reset);
}

public static function getUnitTestsItemsChoiceTypeInstance(bool $reset = false)
{
return self::getClassInstance('unitTestsInstance', 'ItemsChoiceType', $reset);
}

public static function getEwsWorkingPeriodInstance(bool $reset = false)
{
// required for validating enumeration values
Expand Down
91 changes: 91 additions & 0 deletions tests/File/Validation/ChoiceMaxOccursRuleTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
<?php

declare(strict_types=1);

namespace WsdlToPhp\PackageGenerator\Tests\File\Validation;

/**
* The ItemsChoiceType struct contains a choice (choiceMaxOccurs: 1) whose elements have
* their own maxOccurs: 5, so each property must accept up to 5 items even though the
* choice itself may only occur once.
*
* @see https://github.com/WsdlToPhp/PackageGenerator/issues/340
*
* @internal
* @coversDefaultClass
*/
final class ChoiceMaxOccursRuleTest extends AbstractRule
{
/**
* The ItemIdentifier
* Meta information extracted from the WSDL
* - choice: ItemIdentifier | ItemName
* - choiceMaxOccurs: 1
* - choiceMinOccurs: 1
* - maxOccurs: 5
* - minOccurs: 1.
*/
public function testSetItemIdentifierWithSeveralItemsMustPass(): void
{
$instance = self::getUnitTestsItemsChoiceTypeInstance(true);

$this->assertSame($instance, $instance->setItemIdentifier([1, 2, 3, 4, 5]));
}

/**
* The ItemIdentifier
* Meta information extracted from the WSDL
* - choice: ItemIdentifier | ItemName
* - choiceMaxOccurs: 1
* - choiceMinOccurs: 1
* - maxOccurs: 5
* - minOccurs: 1.
*/
public function testAddToItemIdentifierWithSeveralItemsMustPass(): void
{
$instance = self::getUnitTestsItemsChoiceTypeInstance(true);

$this->assertSame($instance, $instance->setItemIdentifier([1])->addToItemIdentifier(2)->addToItemIdentifier(3));
}

/**
* The ItemIdentifier
* Meta information extracted from the WSDL
* - choice: ItemIdentifier | ItemName
* - choiceMaxOccurs: 1
* - choiceMinOccurs: 1
* - maxOccurs: 5
* - minOccurs: 1.
*/
public function testSetItemIdentifierWithTooManyItemsMustThrowAnException(): void
{
$this->expectException(\InvalidArgumentException::class);
$this->expectExceptionMessage('Invalid count of 6, the number of elements contained by the property must be less than or equal to 5');

$instance = self::getUnitTestsItemsChoiceTypeInstance(true);

$instance->setItemIdentifier([1, 2, 3, 4, 5, 6]);
}

/**
* The ItemName
* Meta information extracted from the WSDL
* - choice: ItemIdentifier | ItemName
* - choiceMaxOccurs: 1
* - choiceMinOccurs: 1
* - maxOccurs: 5
* - minOccurs: 1.
*/
public function testSetItemNameAfterItemIdentifierMustThrowAnException(): void
{
$this->expectException(\InvalidArgumentException::class);
$this->expectExceptionMessage('The property ItemName can\'t be set as the property ItemIdentifier is already set. Only one property must be set among these properties: ItemName, ItemIdentifier.');

$instance = self::getUnitTestsItemsChoiceTypeInstance(true);

$instance
->setItemIdentifier([1, 2])
->setItemName(['one', 'two'])
;
}
}
Loading