Skip to content
Closed
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
4 changes: 3 additions & 1 deletion app/code/Magento/Vault/Plugin/PaymentVaultAttributesLoad.php
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,9 @@ public function aroundGetExtensionAttributes(
$paymentToken = $paymentExtension->getVaultPaymentToken();
if ($paymentToken === null) {
$paymentToken = $this->paymentTokenManagement->getByPaymentId($payment->getEntityId());
$paymentExtension->setVaultPaymentToken($paymentToken);
if ($paymentToken instanceof \Magento\Vault\Api\Data\PaymentTokenInterface) {
$paymentExtension->setVaultPaymentToken($paymentToken);
}
$payment->setExtensionAttributes($paymentExtension);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@ class ExtensionAttributesGenerator extends \Magento\Framework\Code\Generator\Ent
*/
protected $config;

/**
* @var \Magento\Framework\Reflection\TypeProcessor
*/
protected $typeProcessor;

/**
* @var array
*/
Expand All @@ -33,6 +38,7 @@ class ExtensionAttributesGenerator extends \Magento\Framework\Code\Generator\Ent
* Initialize dependencies.
*
* @param \Magento\Framework\Api\ExtensionAttribute\Config $config
* @param \Magento\Framework\Reflection\TypeProcessor $typeProcessor,
* @param string|null $sourceClassName
* @param string|null $resultClassName
* @param Io $ioObject
Expand All @@ -41,6 +47,7 @@ class ExtensionAttributesGenerator extends \Magento\Framework\Code\Generator\Ent
*/
public function __construct(
\Magento\Framework\Api\ExtensionAttribute\Config $config,
\Magento\Framework\Reflection\TypeProcessor $typeProcessor,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In order to preserve constructor signature and do not introduce backward incompatible changes in Magento 2 we are using this approach:

`class ExistingClass

{
/** @var \New\Dependency\Class */
private $newDependency;

/**
 * The getter function to get the new dependency for real application code
 *
 * @return \New\Dependency\Class
 *
 * @deprecated
 */
private function getNewDependency()
{
    if ($this->newDependency === null) {
        $this->newDependency = \Magento\Framework\App\ObjectManager::getInstance()->get(\New\Dependency\Class::class);
    }
    return $this->newDependency;
}

public function existingFunction()
{
    // Existing functionality
    ...
    ...

    // Use $this->getNewDependency() wherever the new dependency is needed
    ...
    ...
}

}`

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about adding a @TODO comment to clean that mess up with the next backward compatibility breaking upgrade?

$sourceClassName = null,
$resultClassName = null,
Io $ioObject = null,
Expand All @@ -49,6 +56,7 @@ public function __construct(
) {
$sourceClassName .= 'Interface';
$this->config = $config;
$this->typeProcessor = $typeProcessor;
parent::__construct(
$sourceClassName,
$resultClassName,
Expand Down Expand Up @@ -90,9 +98,15 @@ protected function _getClassMethods()
'body' => "return \$this->_get('{$attributeName}');",
'docblock' => ['tags' => [['name' => 'return', 'description' => $attributeType . '|null']]],
];
$parameters = ['name' => $propertyName];
// If the attribute type is a valid type declaration (e.g., interface, class, array) then use it to enforce
// constraints on the generated setter methods
if ($this->typeProcessor->isValidTypeDeclaration($attributeType)) {
$parameters['type'] = $attributeType;
}
$methods[] = [
'name' => $setterName,
'parameters' => [['name' => $propertyName]],
'parameters' => [$parameters],
'body' => "\$this->setData('{$attributeName}', \${$propertyName});" . PHP_EOL . "return \$this;",
'docblock' => [
'tags' => [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ class ExtensionAttributesInterfaceGenerator extends \Magento\Framework\Api\Code\
* Initialize dependencies.
*
* @param \Magento\Framework\Api\ExtensionAttribute\Config $config
* @param \Magento\Framework\Reflection\TypeProcessor $typeProcessor
* @param string|null $sourceClassName
* @param string|null $resultClassName
* @param Io $ioObject
Expand All @@ -29,6 +30,7 @@ class ExtensionAttributesInterfaceGenerator extends \Magento\Framework\Api\Code\
*/
public function __construct(
\Magento\Framework\Api\ExtensionAttribute\Config $config,
\Magento\Framework\Reflection\TypeProcessor $typeProcessor,
$sourceClassName = null,
$resultClassName = null,
Io $ioObject = null,
Expand All @@ -40,6 +42,7 @@ public function __construct(
}
parent::__construct(
$config,
$typeProcessor,
$sourceClassName,
$resultClassName,
$ioObject,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ class ExtensionAttributesGeneratorTest extends \PHPUnit_Framework_TestCase
*/
protected $configMock;

/**
* @var \Magento\Framework\Reflection\TypeProcessor|\PHPUnit_Framework_MockObject_MockObject
*/
protected $typeProcessorMock;

/**
* @var \Magento\Framework\Api\Code\Generator\ExtensionAttributesGenerator|\PHPUnit_Framework_MockObject_MockObject
*/
Expand All @@ -26,11 +31,17 @@ protected function setUp()
->disableOriginalConstructor()
->getMock();

$this->typeProcessorMock = $this->getMockBuilder('Magento\Framework\Reflection\TypeProcessor')
->disableOriginalConstructor()
->setMethods(null)
->getMock();

$objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this);
$this->model = $objectManager->getObject(
'Magento\Framework\Api\Code\Generator\ExtensionAttributesGenerator',
[
'config' => $this->configMock,
'typeProcessor' => $this->typeProcessorMock,
'sourceClassName' => '\Magento\Catalog\Api\Data\Product',
'resultClassName' => '\Magento\Catalog\Api\Data\ProductExtension',
'classGenerator' => null
Expand All @@ -55,6 +66,11 @@ public function testGenerate()
Converter::DATA_TYPE => '\Magento\Bundle\Api\Data\OptionInterface[]',
Converter::RESOURCE_PERMISSIONS => [],
],
// Ensure type declaration is added to argument of setter
'complex_object_attribute_with_type_declaration' => [
Converter::DATA_TYPE => '\Magento\Bundle\Api\Data\BundleOptionInterface',
Converter::RESOURCE_PERMISSIONS => [],
],
],
'Magento\Catalog\Api\Data\Product' => [
'should_not_include' => [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ public function testGenerate()
Converter::DATA_TYPE => '\Magento\Bundle\Api\Data\OptionInterface[]',
Converter::RESOURCE_PERMISSIONS => [],
],
// Ensure type declaration is added to argument of setter
'complex_object_attribute_with_type_declaration' => [
Converter::DATA_TYPE => '\Magento\Bundle\Api\Data\BundleOptionInterface',
Converter::RESOURCE_PERMISSIONS => [],
],
],
'Magento\Catalog\Api\Data\Product' => [
'should_not_include' => [
Expand All @@ -38,12 +43,17 @@ public function testGenerate()
],
]
);
$typeProcessorMock = $this->getMockBuilder('Magento\Framework\Reflection\TypeProcessor')
->disableOriginalConstructor()
->setMethods(null)
->getMock();

/** @var \Magento\Framework\Api\Code\Generator\ExtensionAttributesInterfaceGenerator $model */
$model = $objectManager->getObject(
'Magento\Framework\Api\Code\Generator\ExtensionAttributesInterfaceGenerator',
[
'config' => $configMock,
'typeProcessor' => $typeProcessorMock,
'sourceClassName' => '\Magento\Catalog\Api\Data\Product',
'resultClassName' => '\Magento\Catalog\Api\Data\ProductExtensionInterface',
'classGenerator' => null
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,23 @@ class ProductExtension extends \Magento\Framework\Api\AbstractSimpleObject imple
$this->setData('complex_object_attribute', $complexObjectAttribute);
return $this;
}

/**
* @return \Magento\Bundle\Api\Data\BundleOptionInterface|null
*/
public function getComplexObjectAttributeWithTypeDeclaration()
{
return $this->_get('complex_object_attribute_with_type_declaration');
}

/**
* @param \Magento\Bundle\Api\Data\BundleOptionInterface
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

param annotation should looks like:

  • @param \Magento\Bundle\Api\Data\BundleOptionInterface $complexObjectAttributeWithTypeDeclaration

but this is not issue of this PR

* $complexObjectAttributeWithTypeDeclaration
* @return $this
*/
public function setComplexObjectAttributeWithTypeDeclaration(\Magento\Bundle\Api\Data\BundleOptionInterface $complexObjectAttributeWithTypeDeclaration)
{
$this->setData('complex_object_attribute_with_type_declaration', $complexObjectAttributeWithTypeDeclaration);
return $this;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,16 @@ interface ProductExtensionInterface extends \Magento\Framework\Api\ExtensionAttr
* @return $this
*/
public function setComplexObjectAttribute($complexObjectAttribute);

/**
* @return \Magento\Bundle\Api\Data\BundleOptionInterface|null
*/
public function getComplexObjectAttributeWithTypeDeclaration();

/**
* @param \Magento\Bundle\Api\Data\BundleOptionInterface
* $complexObjectAttributeWithTypeDeclaration
* @return $this
*/
public function setComplexObjectAttributeWithTypeDeclaration(\Magento\Bundle\Api\Data\BundleOptionInterface $complexObjectAttributeWithTypeDeclaration);
}
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,26 @@ public function testIsArrayType()
$this->assertTrue($this->_typeProcessor->isArrayType('string[]'));
}

public function testIsValidTypeDeclaration()
{
$this->assertTrue($this->_typeProcessor->isValidTypeDeclaration('Traversable')); // Interface
$this->assertTrue($this->_typeProcessor->isValidTypeDeclaration('stdObj')); // Class
$this->assertTrue($this->_typeProcessor->isValidTypeDeclaration('array'));
$this->assertTrue($this->_typeProcessor->isValidTypeDeclaration('callable'));
$this->assertTrue($this->_typeProcessor->isValidTypeDeclaration('self'));
$this->assertTrue($this->_typeProcessor->isValidTypeDeclaration('self'));
$this->assertFalse($this->_typeProcessor->isValidTypeDeclaration('string'));
$this->assertFalse($this->_typeProcessor->isValidTypeDeclaration('string[]'));
$this->assertFalse($this->_typeProcessor->isValidTypeDeclaration('int'));
$this->assertFalse($this->_typeProcessor->isValidTypeDeclaration('float'));
$this->assertFalse($this->_typeProcessor->isValidTypeDeclaration('double'));
$this->assertFalse($this->_typeProcessor->isValidTypeDeclaration('boolean'));
$this->assertFalse($this->_typeProcessor->isValidTypeDeclaration('[]'));
$this->assertFalse($this->_typeProcessor->isValidTypeDeclaration('mixed[]'));
$this->assertFalse($this->_typeProcessor->isValidTypeDeclaration('stdObj[]'));
$this->assertFalse($this->_typeProcessor->isValidTypeDeclaration('Traversable[]'));
}

public function getArrayItemType()
{
$this->assertEquals('string', $this->_typeProcessor->getArrayItemType('str[]'));
Expand Down
13 changes: 13 additions & 0 deletions lib/internal/Magento/Framework/Reflection/TypeProcessor.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
* Type processor of config reader properties
*
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
* @SuppressWarnings(PHPMD.ExcessiveClassComplexity)
*/
class TypeProcessor
{
Expand Down Expand Up @@ -419,6 +420,18 @@ public function isArrayType($type)
return (bool)preg_match('/(\[\]$|^ArrayOf)/', $type);
}

/**
* Check if given type is valid to use as an argument type declaration
*
* @see http://php.net/manual/en/functions.arguments.php#functions.arguments.type-declaration
* @param string $type
* @return bool
*/
public function isValidTypeDeclaration($type)
{
return !($this->isTypeSimple($type) || $this->isTypeAny($type) || $this->isArrayType($type));
}

/**
* Get item type of the array.
*
Expand Down