From f281a053938504331a277e83a7a1152dc5143636 Mon Sep 17 00:00:00 2001 From: Riccardo Tempesta Date: Tue, 7 Aug 2018 10:11:54 +0200 Subject: [PATCH 001/171] Support for non-FQN classes on web-API interfaces. This commit provides a support for "use" statement in web-API interfaces and the usage of non-FQN class names in doctypes. It also provides a fix for MSI-1524 and MSI-1537. --- .../Test/Unit/TypeProcessorTest.php | 3 +- .../Framework/Reflection/TypeProcessor.php | 71 ++++++++++++++++++- .../Webapi/ServiceInputProcessor.php | 12 +++- 3 files changed, 80 insertions(+), 6 deletions(-) diff --git a/lib/internal/Magento/Framework/Reflection/Test/Unit/TypeProcessorTest.php b/lib/internal/Magento/Framework/Reflection/Test/Unit/TypeProcessorTest.php index 86a4693d9e5b6..b3fff04d756eb 100644 --- a/lib/internal/Magento/Framework/Reflection/Test/Unit/TypeProcessorTest.php +++ b/lib/internal/Magento/Framework/Reflection/Test/Unit/TypeProcessorTest.php @@ -8,6 +8,7 @@ use Magento\Framework\Exception\SerializationException; use Magento\Framework\Reflection\Test\Unit\Fixture\TSample; +use Magento\Framework\Reflection\Test\Unit\Fixture\TSampleInterface; use Magento\Framework\Reflection\TypeProcessor; use Zend\Code\Reflection\ClassReflection; @@ -278,7 +279,7 @@ public function arrayParamTypeDataProvider() { return [ ['method name' => 'addData', 'type' => 'array[]'], - ['method name' => 'addObjectList', 'type' => 'TSampleInterface[]'] + ['method name' => 'addObjectList', 'type' => TSampleInterface::class . '[]'] ]; } diff --git a/lib/internal/Magento/Framework/Reflection/TypeProcessor.php b/lib/internal/Magento/Framework/Reflection/TypeProcessor.php index d7206032c68c7..9bfeef83c9f6c 100644 --- a/lib/internal/Magento/Framework/Reflection/TypeProcessor.php +++ b/lib/internal/Magento/Framework/Reflection/TypeProcessor.php @@ -6,6 +6,7 @@ namespace Magento\Framework\Reflection; +use Doctrine\Common\Annotations\TokenParser; use Magento\Framework\Exception\SerializationException; use Magento\Framework\Phrase; use Zend\Code\Reflection\ClassReflection; @@ -512,7 +513,7 @@ public function processSimpleAndAnyType($value, $type) public function getParamType(ParameterReflection $param) { $type = $param->detectType(); - if ($type == 'null') { + if ($type === 'null') { throw new \LogicException(sprintf( '@param annotation is incorrect for the parameter "%s" in the method "%s:%s".' . ' First declared type should not be null. E.g. string|null', @@ -521,14 +522,78 @@ public function getParamType(ParameterReflection $param) $param->getDeclaringFunction()->name )); } - if ($type == 'array') { + if ($type === 'array') { // try to determine class, if it's array of objects $paramDocBlock = $this->getParamDocBlockTag($param); $paramTypes = $paramDocBlock->getTypes(); $paramType = array_shift($paramTypes); + + $paramType = $this->resolveFullyQualifiedClassName($param->getDeclaringClass(), $paramType); + return strpos($paramType, '[]') !== false ? $paramType : "{$paramType}[]"; } - return $type; + + return $this->resolveFullyQualifiedClassName($param->getDeclaringClass(), $type); + } + + /** + * Resolve fully qualified type name in the class alias context + * @param ClassReflection $sourceClass + * @param string $typeName + * @return string + */ + public function resolveFullyQualifiedClassName(ClassReflection $sourceClass, string $typeName): string + { + $typeName = trim($typeName); + + // Not a class, but a basic type + if ((strtolower($typeName[0])) === $typeName[0]) { + return $typeName; + } + + // Split array suffix + if (preg_match('/^(.+?)\[\]$/', $typeName, $matches)) { + $typeName = $matches[1]; + $arraySuffix = '[]'; + } else { + $arraySuffix = ''; + } + + // If class exists, then return it + try { + new ClassReflection($typeName); + return $typeName . $arraySuffix; + } catch (\ReflectionException $e) { + unset($e); + } + + // Resolve fully qualified name + $sourceFileName = $sourceClass->getDeclaringFile(); + $source = $sourceFileName->getContents(); + $parser = new TokenParser($source); + + $namespace = $sourceClass->getNamespaceName(); + $aliases = $parser->parseUseStatements($namespace); + + $pos = strpos($typeName, '\\'); + if ($pos === 0) { + return substr($typeName, 1); + } + + if ($pos === false) { + $namespacePrefix = $typeName; + $partialClassName = ''; + } else { + $namespacePrefix = substr($typeName, 0, $pos); + $partialClassName = substr($typeName, $pos); + } + + $namespacePrefix = strtolower($namespacePrefix); + if (isset($aliases[$namespacePrefix])) { + return $aliases[$namespacePrefix] . $partialClassName . $arraySuffix; + } + + return $namespace . '\\' . $typeName . $arraySuffix; } /** diff --git a/lib/internal/Magento/Framework/Webapi/ServiceInputProcessor.php b/lib/internal/Magento/Framework/Webapi/ServiceInputProcessor.php index 26102f008c7c3..f1a2e4f2bc704 100644 --- a/lib/internal/Magento/Framework/Webapi/ServiceInputProcessor.php +++ b/lib/internal/Magento/Framework/Webapi/ServiceInputProcessor.php @@ -175,7 +175,7 @@ private function getConstructorData(string $className, array $data): array $preferenceClass = $this->config->getPreference($className); $class = new ClassReflection($preferenceClass ?: $className); - $constructor = $class->getConstructor(); + $constructor = $class->getMethod('__construct'); if ($constructor === null) { return []; } @@ -184,7 +184,15 @@ private function getConstructorData(string $className, array $data): array $parameters = $constructor->getParameters(); foreach ($parameters as $parameter) { if (isset($data[$parameter->getName()])) { - $res[$parameter->getName()] = $data[$parameter->getName()]; + $parameterType = $this->typeProcessor->getParamType($parameter); + + try { + $res[$parameter->getName()] = $this->convertValue($data[$parameter->getName()], $parameterType); + } catch (\ReflectionException $e) { + // Parameter was not correclty declared or the class is uknown. + // By not returing the contructor value, we will automatically fall back to the "setters" way. + continue; + } } } From a0379a4bb36486ac26aaabaff969923b01a665f0 Mon Sep 17 00:00:00 2001 From: Riccardo Tempesta Date: Fri, 17 Aug 2018 17:34:27 +0200 Subject: [PATCH 002/171] Removed doctrine dependency --- .../Framework/Reflection/TypeProcessor.php | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/lib/internal/Magento/Framework/Reflection/TypeProcessor.php b/lib/internal/Magento/Framework/Reflection/TypeProcessor.php index 9bfeef83c9f6c..5ac88a6171b5d 100644 --- a/lib/internal/Magento/Framework/Reflection/TypeProcessor.php +++ b/lib/internal/Magento/Framework/Reflection/TypeProcessor.php @@ -6,7 +6,6 @@ namespace Magento\Framework\Reflection; -use Doctrine\Common\Annotations\TokenParser; use Magento\Framework\Exception\SerializationException; use Magento\Framework\Phrase; use Zend\Code\Reflection\ClassReflection; @@ -567,13 +566,22 @@ public function resolveFullyQualifiedClassName(ClassReflection $sourceClass, str unset($e); } - // Resolve fully qualified name + // Extract alias mapping $sourceFileName = $sourceClass->getDeclaringFile(); - $source = $sourceFileName->getContents(); - $parser = new TokenParser($source); + $aliases = []; + foreach ($sourceFileName->getUses() as $use) { + if ($use['as'] !== null) { + $aliases[$use['as']] = $use['use']; + } else { + $pos = strrpos($use['use'], '\\'); + + $aliasName = substr($use['use'], $pos + 1); + $aliases[$aliasName] = $use['use']; + } + } + // Resolve FQN $namespace = $sourceClass->getNamespaceName(); - $aliases = $parser->parseUseStatements($namespace); $pos = strpos($typeName, '\\'); if ($pos === 0) { @@ -588,7 +596,6 @@ public function resolveFullyQualifiedClassName(ClassReflection $sourceClass, str $partialClassName = substr($typeName, $pos); } - $namespacePrefix = strtolower($namespacePrefix); if (isset($aliases[$namespacePrefix])) { return $aliases[$namespacePrefix] . $partialClassName . $arraySuffix; } From 1530c69c642797ae87c68292559422b1fede627e Mon Sep 17 00:00:00 2001 From: Riccardo Tempesta Date: Mon, 8 Oct 2018 15:01:36 +0200 Subject: [PATCH 003/171] Unhandled refrelction exception when __construct method is missing --- .../Magento/Framework/Webapi/ServiceInputProcessor.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/internal/Magento/Framework/Webapi/ServiceInputProcessor.php b/lib/internal/Magento/Framework/Webapi/ServiceInputProcessor.php index f1a2e4f2bc704..45d6b8ad91e62 100644 --- a/lib/internal/Magento/Framework/Webapi/ServiceInputProcessor.php +++ b/lib/internal/Magento/Framework/Webapi/ServiceInputProcessor.php @@ -175,7 +175,12 @@ private function getConstructorData(string $className, array $data): array $preferenceClass = $this->config->getPreference($className); $class = new ClassReflection($preferenceClass ?: $className); - $constructor = $class->getMethod('__construct'); + try { + $constructor = $class->getMethod('__construct'); + } catch (\ReflectionException $e) { + $constructor = null; + } + if ($constructor === null) { return []; } From 3d0cb544198b74e1294ebc5bee1f995dcde101b1 Mon Sep 17 00:00:00 2001 From: Riccardo Tempesta Date: Tue, 9 Oct 2018 14:02:07 +0200 Subject: [PATCH 004/171] FIX CS: missing phpdoc --- lib/internal/Magento/Framework/Reflection/TypeProcessor.php | 1 + .../Magento/Framework/Webapi/ServiceInputProcessor.php | 3 +++ 2 files changed, 4 insertions(+) diff --git a/lib/internal/Magento/Framework/Reflection/TypeProcessor.php b/lib/internal/Magento/Framework/Reflection/TypeProcessor.php index 5ac88a6171b5d..ada061d933afe 100644 --- a/lib/internal/Magento/Framework/Reflection/TypeProcessor.php +++ b/lib/internal/Magento/Framework/Reflection/TypeProcessor.php @@ -537,6 +537,7 @@ public function getParamType(ParameterReflection $param) /** * Resolve fully qualified type name in the class alias context + * * @param ClassReflection $sourceClass * @param string $typeName * @return string diff --git a/lib/internal/Magento/Framework/Webapi/ServiceInputProcessor.php b/lib/internal/Magento/Framework/Webapi/ServiceInputProcessor.php index 45d6b8ad91e62..a9b553f6dd6f9 100644 --- a/lib/internal/Magento/Framework/Webapi/ServiceInputProcessor.php +++ b/lib/internal/Magento/Framework/Webapi/ServiceInputProcessor.php @@ -165,10 +165,13 @@ public function process($serviceClassName, $serviceMethodName, array $inputArray } /** + * Retrieve constructor data + * * @param string $className * @param array $data * @return array * @throws \ReflectionException + * @throws \Magento\Framework\Exception\LocalizedException */ private function getConstructorData(string $className, array $data): array { From 2232338efacc5288dcc3c0dcaa6e00f204e93762 Mon Sep 17 00:00:00 2001 From: Eugene Shakhsuvarov Date: Sun, 21 Oct 2018 16:29:46 +0200 Subject: [PATCH 005/171] FIX resolveFullyQualifiedClassName as private method Co-Authored-By: phoenix128 --- lib/internal/Magento/Framework/Reflection/TypeProcessor.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/internal/Magento/Framework/Reflection/TypeProcessor.php b/lib/internal/Magento/Framework/Reflection/TypeProcessor.php index ada061d933afe..b7db1deb131b4 100644 --- a/lib/internal/Magento/Framework/Reflection/TypeProcessor.php +++ b/lib/internal/Magento/Framework/Reflection/TypeProcessor.php @@ -542,7 +542,7 @@ public function getParamType(ParameterReflection $param) * @param string $typeName * @return string */ - public function resolveFullyQualifiedClassName(ClassReflection $sourceClass, string $typeName): string + private function resolveFullyQualifiedClassName(ClassReflection $sourceClass, string $typeName): string { $typeName = trim($typeName); From e858f36eb99de3d78129cc1916c4c2b6d64caaca Mon Sep 17 00:00:00 2001 From: Riccardo Tempesta Date: Wed, 24 Oct 2018 12:58:03 +0200 Subject: [PATCH 006/171] resolveFullyQualifiedClassName refactor and test coverage --- .../Unit/Fixture/UseClasses/SampleOne.php | 13 ++ .../UseClasses/SampleOne/SampleThree.php | 13 ++ .../Unit/Fixture/UseClasses/SampleTwo.php | 13 ++ .../UseClasses/SampleTwo/SampleFour.php | 13 ++ .../Test/Unit/Fixture/UseSample.php | 16 ++ .../Test/Unit/TypeProcessorTest.php | 167 ++++++++++++++++++ .../Framework/Reflection/TypeProcessor.php | 140 +++++++++++---- 7 files changed, 336 insertions(+), 39 deletions(-) create mode 100644 lib/internal/Magento/Framework/Reflection/Test/Unit/Fixture/UseClasses/SampleOne.php create mode 100644 lib/internal/Magento/Framework/Reflection/Test/Unit/Fixture/UseClasses/SampleOne/SampleThree.php create mode 100644 lib/internal/Magento/Framework/Reflection/Test/Unit/Fixture/UseClasses/SampleTwo.php create mode 100644 lib/internal/Magento/Framework/Reflection/Test/Unit/Fixture/UseClasses/SampleTwo/SampleFour.php create mode 100644 lib/internal/Magento/Framework/Reflection/Test/Unit/Fixture/UseSample.php diff --git a/lib/internal/Magento/Framework/Reflection/Test/Unit/Fixture/UseClasses/SampleOne.php b/lib/internal/Magento/Framework/Reflection/Test/Unit/Fixture/UseClasses/SampleOne.php new file mode 100644 index 0000000000000..6382f4b247072 --- /dev/null +++ b/lib/internal/Magento/Framework/Reflection/Test/Unit/Fixture/UseClasses/SampleOne.php @@ -0,0 +1,13 @@ +getMethod('getName'); $this->typeProcessor->getGetterReturnType($methodReflection); } + + /** + * Simple and complex data provider + * + * @return array + */ + public function simpleAndComplexDataProvider(): array + { + return [ + ['string', true], + ['array', true], + ['int', true], + ['SomeClass', false], + ['\\My\\Namespace\\Model\\Class', false], + ['Some\\Other\\Class', false], + ]; + } + + /** + * Test simple type detection method + * + * @dataProvider simpleAndComplexDataProvider + * @param string $type + * @param bool $expectedValue + */ + public function testIsSimpleType(string $type, bool $expectedValue) + { + self::assertEquals($expectedValue, $this->typeProcessor->isSimpleType($type)); + } + + /** + * Simple and complex data provider + * + * @return array + */ + public function basicClassNameProvider(): array + { + return [ + ['SomeClass[]', 'SomeClass'], + ['\\My\\Namespace\\Model\\Class[]', '\\My\\Namespace\\Model\\Class'], + ['Some\\Other\\Class[]', 'Some\\Other\\Class'], + ['SomeClass', 'SomeClass'], + ['\\My\\Namespace\\Model\\Class', '\\My\\Namespace\\Model\\Class'], + ['Some\\Other\\Class', 'Some\\Other\\Class'], + ]; + } + + /** + * Extract basic class name + * + * @dataProvider basicClassNameProvider + * @param string $type + * @param string $expectedValue + */ + public function testBasicClassName(string $type, string $expectedValue) + { + self::assertEquals($expectedValue, $this->typeProcessor->getBasicClassName($type)); + } + + /** + * Fully qualified class names data provider + * + * @return array + */ + public function isFullyQualifiedClassNamesDataProvider(): array + { + return [ + ['SomeClass', false], + ['\\My\\Namespace\\Model\\Class', true], + ['Some\\Other\\Class', false], + ]; + } + + /** + * Test fully qualified class name detector + * + * @dataProvider isFullyQualifiedClassNamesDataProvider + * @param string $type + * @param bool $expectedValue + */ + public function testIsFullyQualifiedClassName(string $type, bool $expectedValue) + { + self::assertEquals($expectedValue, $this->typeProcessor->isFullyQualifiedClassName($type)); + } + + /** + * Test alias mapping + */ + public function testGetAliasMapping() + { + $sourceClass = new ClassReflection(UseSample::class); + $aliasMap = $this->typeProcessor->getAliasMapping($sourceClass); + + self::assertEquals([ + 'SampleOne' => SampleOne::class, + 'Sample2' => SampleTwo::class, + ], $aliasMap); + } + + /** + * Resolve fully qualified class names data provider + * + * @return array + */ + public function resolveFullyQualifiedClassNamesDataProvider(): array + { + return [ + [UseSample::class, 'string', 'string'], + [UseSample::class, 'string[]', 'string[]'], + + [UseSample::class, 'SampleOne', SampleOne::class], + [UseSample::class, 'Sample2', SampleTwo::class], + [UseSample::class, '\\Magento\\Framework\\Reflection\\Test\\Unit\\Fixture\\UseClasses\\SampleOne', SampleOne::class], + [UseSample::class, '\\Magento\\Framework\\Reflection\\Test\\Unit\\Fixture\\UseClasses\\SampleTwo', SampleTwo::class], + [UseSample::class, 'UseClasses\\SampleOne', SampleOne::class], + [UseSample::class, 'UseClasses\\SampleTwo', SampleTwo::class], + + [UseSample::class, 'SampleOne[]', SampleOne::class . '[]'], + [UseSample::class, 'Sample2[]', SampleTwo::class . '[]'], + [UseSample::class, '\\Magento\\Framework\\Reflection\\Test\\Unit\\Fixture\\UseClasses\\SampleOne[]', SampleOne::class . '[]'], + [UseSample::class, '\\Magento\\Framework\\Reflection\\Test\\Unit\\Fixture\\UseClasses\\SampleTwo[]', SampleTwo::class . '[]'], + [UseSample::class, 'UseClasses\\SampleOne[]', SampleOne::class . '[]'], + [UseSample::class, 'UseClasses\\SampleTwo[]', SampleTwo::class . '[]'], + + [UseSample::class, 'SampleOne\SampleThree', SampleThree::class], + [UseSample::class, 'SampleOne\SampleThree[]', SampleThree::class . '[]'], + + [UseSample::class, 'Sample2\SampleFour', SampleFour::class], + [UseSample::class, 'Sample2\SampleFour[]', SampleFour::class . '[]'], + + [UseSample::class, 'Sample2\NotExisting', 'Sample2\NotExisting'], + [UseSample::class, 'Sample2\NotExisting[]', 'Sample2\NotExisting[]'], + + [ + UseSample::class, + '\\Magento\\Framework\\Reflection\\Test\\Unit\\Fixture\\UseClasses\\NotExisting', + 'Magento\\Framework\\Reflection\\Test\\Unit\\Fixture\\UseClasses\\NotExisting' + ], + [ + UseSample::class, + '\\Magento\\Framework\\Reflection\\Test\\Unit\\Fixture\\UseClasses\\NotExisting[]', + 'Magento\\Framework\\Reflection\\Test\\Unit\\Fixture\\UseClasses\\NotExisting[]' + ], + ]; + } + + /** + * Resolve fully qualified class names + * + * @dataProvider resolveFullyQualifiedClassNamesDataProvider + * @param string $className + * @param string $type + * @param string $expectedValue + * @throws \ReflectionException + */ + public function testResolveFullyQualifiedClassNames(string $className, string $type, string $expectedValue) + { + $sourceClass = new ClassReflection($className); + $fullyQualified = $this->typeProcessor->resolveFullyQualifiedClassName($sourceClass, $type); + + self::assertEquals($expectedValue, $fullyQualified); + } } diff --git a/lib/internal/Magento/Framework/Reflection/TypeProcessor.php b/lib/internal/Magento/Framework/Reflection/TypeProcessor.php index b7db1deb131b4..c3c44109b7849 100644 --- a/lib/internal/Magento/Framework/Reflection/TypeProcessor.php +++ b/lib/internal/Magento/Framework/Reflection/TypeProcessor.php @@ -536,38 +536,13 @@ public function getParamType(ParameterReflection $param) } /** - * Resolve fully qualified type name in the class alias context + * Get alias mapping for source class * * @param ClassReflection $sourceClass - * @param string $typeName - * @return string + * @return array */ - private function resolveFullyQualifiedClassName(ClassReflection $sourceClass, string $typeName): string + public function getAliasMapping(ClassReflection $sourceClass): array { - $typeName = trim($typeName); - - // Not a class, but a basic type - if ((strtolower($typeName[0])) === $typeName[0]) { - return $typeName; - } - - // Split array suffix - if (preg_match('/^(.+?)\[\]$/', $typeName, $matches)) { - $typeName = $matches[1]; - $arraySuffix = '[]'; - } else { - $arraySuffix = ''; - } - - // If class exists, then return it - try { - new ClassReflection($typeName); - return $typeName . $arraySuffix; - } catch (\ReflectionException $e) { - unset($e); - } - - // Extract alias mapping $sourceFileName = $sourceClass->getDeclaringFile(); $aliases = []; foreach ($sourceFileName->getUses() as $use) { @@ -581,27 +556,114 @@ private function resolveFullyQualifiedClassName(ClassReflection $sourceClass, st } } - // Resolve FQN - $namespace = $sourceClass->getNamespaceName(); + return $aliases; + } - $pos = strpos($typeName, '\\'); - if ($pos === 0) { - return substr($typeName, 1); - } + /** + * Return true if the passed type is a simple type + * + * eg.: + * Return true with; array, string, ... + * Return false with: SomeClassName + * + * @param string $typeName + * @return bool + */ + public function isSimpleType(string $typeName): bool + { + return strtolower($typeName) === $typeName; + } + + /** + * Get basic type for a class name + * + * eg.: + * SomeClassName[] => SomeClassName + * + * @param string $className + * @return string + */ + public function getBasicClassName(string $className): string + { + $pos = strpos($className, '['); + return ($pos === false) ? $className : substr($className, 0, $pos); + } + + /** + * Return true if it is a FQ class name + * + * eg.: + * SomeClassName => false + * \My\NameSpace\SomeClassName => true + * + * @param string $className + * @return bool + */ + public function isFullyQualifiedClassName(string $className): bool + { + return strpos($className, '\\') === 0; + } + /** + * Get aliased class name + * + * @param string $className + * @param string $namespace + * @param array $aliases + * @return string + */ + private function getAliasedClassName(string $className, string $namespace, array $aliases): string + { + $pos = strpos($className, '\\'); if ($pos === false) { - $namespacePrefix = $typeName; + $namespacePrefix = $className; $partialClassName = ''; } else { - $namespacePrefix = substr($typeName, 0, $pos); - $partialClassName = substr($typeName, $pos); + $namespacePrefix = substr($className, 0, $pos); + $partialClassName = substr($className, $pos); } if (isset($aliases[$namespacePrefix])) { - return $aliases[$namespacePrefix] . $partialClassName . $arraySuffix; + return $aliases[$namespacePrefix] . $partialClassName; + } + + return $namespace . '\\' . $className; + } + + /** + * Resolve fully qualified type name in the class alias context + * + * @param ClassReflection $sourceClass + * @param string $typeName + * @return string + */ + public function resolveFullyQualifiedClassName(ClassReflection $sourceClass, string $typeName): string + { + $typeName = trim($typeName); + + // Simple way to understand it is a basic type or a class name + if ($this->isSimpleType($typeName)) { + return $typeName; + } + + $basicTypeName = $this->getBasicClassName($typeName); + + // Already a FQN class name + if ($this->isFullyQualifiedClassName($basicTypeName)) { + return substr($typeName, 1); } - return $namespace . '\\' . $typeName . $arraySuffix; + $isArray = $this->isArrayType($typeName); + $aliases = $this->getAliasMapping($sourceClass); + + $namespace = $sourceClass->getNamespaceName(); + $fqClassName = $this->getAliasedClassName($basicTypeName, $namespace, $aliases); + + if (class_exists($fqClassName)) { + return $fqClassName . ($isArray ? '[]' : ''); + } + + return $typeName; } /** From 13353c84e3476a2be67521028a1b1c63a9f79cd1 Mon Sep 17 00:00:00 2001 From: Riccardo Tempesta Date: Wed, 24 Oct 2018 17:12:23 +0200 Subject: [PATCH 007/171] Missing check with interface --- lib/internal/Magento/Framework/Reflection/TypeProcessor.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/internal/Magento/Framework/Reflection/TypeProcessor.php b/lib/internal/Magento/Framework/Reflection/TypeProcessor.php index c3c44109b7849..6e99d8137f22b 100644 --- a/lib/internal/Magento/Framework/Reflection/TypeProcessor.php +++ b/lib/internal/Magento/Framework/Reflection/TypeProcessor.php @@ -657,9 +657,9 @@ public function resolveFullyQualifiedClassName(ClassReflection $sourceClass, str $aliases = $this->getAliasMapping($sourceClass); $namespace = $sourceClass->getNamespaceName(); - $fqClassName = $this->getAliasedClassName($basicTypeName, $namespace, $aliases); + $fqClassName = '\\' . $this->getAliasedClassName($basicTypeName, $namespace, $aliases); - if (class_exists($fqClassName)) { + if (interface_exists($fqClassName) || class_exists($fqClassName)) { return $fqClassName . ($isArray ? '[]' : ''); } From 25a5e5be1aac07521317ab891cfcb7eaf407fa37 Mon Sep 17 00:00:00 2001 From: Riccardo Tempesta Date: Wed, 24 Oct 2018 17:12:36 +0200 Subject: [PATCH 008/171] Missing FQ class names support for return types --- .../Webapi/ServiceOutputProcessor.php | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/lib/internal/Magento/Framework/Webapi/ServiceOutputProcessor.php b/lib/internal/Magento/Framework/Webapi/ServiceOutputProcessor.php index cdb6ed799aade..224421d6561c8 100644 --- a/lib/internal/Magento/Framework/Webapi/ServiceOutputProcessor.php +++ b/lib/internal/Magento/Framework/Webapi/ServiceOutputProcessor.php @@ -7,8 +7,11 @@ use Magento\Framework\Api\AbstractExtensibleObject; use Magento\Framework\Api\ExtensibleDataObjectConverter; +use Magento\Framework\App\ObjectManager; use Magento\Framework\Reflection\DataObjectProcessor; use Magento\Framework\Reflection\MethodsMap; +use Magento\Framework\Reflection\TypeProcessor; +use Zend\Code\Reflection\ClassReflection; /** * Data object converter @@ -27,16 +30,24 @@ class ServiceOutputProcessor implements ServicePayloadConverterInterface */ protected $methodsMapProcessor; + /** + * @var TypeProcessor|null + */ + private $typeProcessor; + /** * @param DataObjectProcessor $dataObjectProcessor * @param MethodsMap $methodsMapProcessor + * @param TypeProcessor|null $typeProcessor */ public function __construct( DataObjectProcessor $dataObjectProcessor, - MethodsMap $methodsMapProcessor + MethodsMap $methodsMapProcessor, + TypeProcessor $typeProcessor = null ) { $this->dataObjectProcessor = $dataObjectProcessor; $this->methodsMapProcessor = $methodsMapProcessor; + $this->typeProcessor = $typeProcessor ?: ObjectManager::getInstance()->get(TypeProcessor::class); } /** @@ -57,6 +68,12 @@ public function process($data, $serviceClassName, $serviceMethodName) { /** @var string $dataType */ $dataType = $this->methodsMapProcessor->getMethodReturnType($serviceClassName, $serviceMethodName); + + if (class_exists($serviceClassName) || interface_exists($serviceClassName)) { + $sourceClass = new ClassReflection($serviceClassName); + $dataType = $this->typeProcessor->resolveFullyQualifiedClassName($sourceClass, $dataType); + } + return $this->convertValue($data, $dataType); } From 229a29aff8bd66d5ad18090a7478608c7d0ab753 Mon Sep 17 00:00:00 2001 From: Riccardo Tempesta Date: Thu, 25 Oct 2018 09:45:48 +0200 Subject: [PATCH 009/171] Missing prefix "\" for FQ class names --- .../Test/Unit/TypeProcessorTest.php | 54 ++++++++++++------- .../Framework/Reflection/TypeProcessor.php | 2 +- 2 files changed, 36 insertions(+), 20 deletions(-) diff --git a/lib/internal/Magento/Framework/Reflection/Test/Unit/TypeProcessorTest.php b/lib/internal/Magento/Framework/Reflection/Test/Unit/TypeProcessorTest.php index 0036066543d37..a2f9eb5474da3 100644 --- a/lib/internal/Magento/Framework/Reflection/Test/Unit/TypeProcessorTest.php +++ b/lib/internal/Magento/Framework/Reflection/Test/Unit/TypeProcessorTest.php @@ -284,7 +284,7 @@ public function arrayParamTypeDataProvider() { return [ ['method name' => 'addData', 'type' => 'array[]'], - ['method name' => 'addObjectList', 'type' => TSampleInterface::class . '[]'] + ['method name' => 'addObjectList', 'type' => '\\' . TSampleInterface::class . '[]'] ]; } @@ -470,25 +470,41 @@ public function resolveFullyQualifiedClassNamesDataProvider(): array [UseSample::class, 'string', 'string'], [UseSample::class, 'string[]', 'string[]'], - [UseSample::class, 'SampleOne', SampleOne::class], - [UseSample::class, 'Sample2', SampleTwo::class], - [UseSample::class, '\\Magento\\Framework\\Reflection\\Test\\Unit\\Fixture\\UseClasses\\SampleOne', SampleOne::class], - [UseSample::class, '\\Magento\\Framework\\Reflection\\Test\\Unit\\Fixture\\UseClasses\\SampleTwo', SampleTwo::class], - [UseSample::class, 'UseClasses\\SampleOne', SampleOne::class], - [UseSample::class, 'UseClasses\\SampleTwo', SampleTwo::class], + [UseSample::class, 'SampleOne', '\\' . SampleOne::class], + [UseSample::class, 'Sample2', '\\' . SampleTwo::class], + [ + UseSample::class, + '\\Magento\\Framework\\Reflection\\Test\\Unit\\Fixture\\UseClasses\\SampleOne', + '\\' . SampleOne::class + ], + [ + UseSample::class, + '\\Magento\\Framework\\Reflection\\Test\\Unit\\Fixture\\UseClasses\\SampleTwo', + '\\' . SampleTwo::class + ], + [UseSample::class, 'UseClasses\\SampleOne', '\\' . SampleOne::class], + [UseSample::class, 'UseClasses\\SampleTwo', '\\' . SampleTwo::class], - [UseSample::class, 'SampleOne[]', SampleOne::class . '[]'], - [UseSample::class, 'Sample2[]', SampleTwo::class . '[]'], - [UseSample::class, '\\Magento\\Framework\\Reflection\\Test\\Unit\\Fixture\\UseClasses\\SampleOne[]', SampleOne::class . '[]'], - [UseSample::class, '\\Magento\\Framework\\Reflection\\Test\\Unit\\Fixture\\UseClasses\\SampleTwo[]', SampleTwo::class . '[]'], - [UseSample::class, 'UseClasses\\SampleOne[]', SampleOne::class . '[]'], - [UseSample::class, 'UseClasses\\SampleTwo[]', SampleTwo::class . '[]'], + [UseSample::class, 'SampleOne[]', '\\' . SampleOne::class . '[]'], + [UseSample::class, 'Sample2[]', '\\' . SampleTwo::class . '[]'], + [ + UseSample::class, + '\\Magento\\Framework\\Reflection\\Test\\Unit\\Fixture\\UseClasses\\SampleOne[]', + '\\' . SampleOne::class . '[]' + ], + [ + UseSample::class, + '\\Magento\\Framework\\Reflection\\Test\\Unit\\Fixture\\UseClasses\\SampleTwo[]', + '\\' . SampleTwo::class . '[]' + ], + [UseSample::class, 'UseClasses\\SampleOne[]', '\\' . SampleOne::class . '[]'], + [UseSample::class, 'UseClasses\\SampleTwo[]', '\\' . SampleTwo::class . '[]'], - [UseSample::class, 'SampleOne\SampleThree', SampleThree::class], - [UseSample::class, 'SampleOne\SampleThree[]', SampleThree::class . '[]'], + [UseSample::class, 'SampleOne\SampleThree', '\\' . SampleThree::class], + [UseSample::class, 'SampleOne\SampleThree[]', '\\' . SampleThree::class . '[]'], - [UseSample::class, 'Sample2\SampleFour', SampleFour::class], - [UseSample::class, 'Sample2\SampleFour[]', SampleFour::class . '[]'], + [UseSample::class, 'Sample2\SampleFour', '\\' . SampleFour::class], + [UseSample::class, 'Sample2\SampleFour[]', '\\' . SampleFour::class . '[]'], [UseSample::class, 'Sample2\NotExisting', 'Sample2\NotExisting'], [UseSample::class, 'Sample2\NotExisting[]', 'Sample2\NotExisting[]'], @@ -496,12 +512,12 @@ public function resolveFullyQualifiedClassNamesDataProvider(): array [ UseSample::class, '\\Magento\\Framework\\Reflection\\Test\\Unit\\Fixture\\UseClasses\\NotExisting', - 'Magento\\Framework\\Reflection\\Test\\Unit\\Fixture\\UseClasses\\NotExisting' + '\\Magento\\Framework\\Reflection\\Test\\Unit\\Fixture\\UseClasses\\NotExisting' ], [ UseSample::class, '\\Magento\\Framework\\Reflection\\Test\\Unit\\Fixture\\UseClasses\\NotExisting[]', - 'Magento\\Framework\\Reflection\\Test\\Unit\\Fixture\\UseClasses\\NotExisting[]' + '\\Magento\\Framework\\Reflection\\Test\\Unit\\Fixture\\UseClasses\\NotExisting[]' ], ]; } diff --git a/lib/internal/Magento/Framework/Reflection/TypeProcessor.php b/lib/internal/Magento/Framework/Reflection/TypeProcessor.php index 6e99d8137f22b..b9f8ed6050708 100644 --- a/lib/internal/Magento/Framework/Reflection/TypeProcessor.php +++ b/lib/internal/Magento/Framework/Reflection/TypeProcessor.php @@ -650,7 +650,7 @@ public function resolveFullyQualifiedClassName(ClassReflection $sourceClass, str // Already a FQN class name if ($this->isFullyQualifiedClassName($basicTypeName)) { - return substr($typeName, 1); + return '\\' . substr($typeName, 1); } $isArray = $this->isArrayType($typeName); From 42308ca83f7cf4f13ee762ff225b7f51d6cbbb4c Mon Sep 17 00:00:00 2001 From: Erik Pellikka Date: Mon, 19 Nov 2018 18:13:37 +0200 Subject: [PATCH 010/171] escape logo alt text and title --- .../Theme/view/frontend/templates/html/header/logo.phtml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Theme/view/frontend/templates/html/header/logo.phtml b/app/code/Magento/Theme/view/frontend/templates/html/header/logo.phtml index 17f8d7c70f574..70dd1a6c1cbb1 100644 --- a/app/code/Magento/Theme/view/frontend/templates/html/header/logo.phtml +++ b/app/code/Magento/Theme/view/frontend/templates/html/header/logo.phtml @@ -18,8 +18,8 @@