25 $invoker = new \Magento\Framework\App\Utility\AggregateInvoker($this);
30 function ($filename) {
34 . str_replace(
'\\',
'\\\\', self::EXTENSIBLE_DATA_INTERFACE)
36 $extendsFromExtensibleDataInterface = preg_match(
$pattern, $fileContent);
37 $namespacePattern =
'/namespace ([\w\\\\]+).*interface ([\w\\\\]+)/s';
38 if ($extendsFromExtensibleDataInterface
39 && preg_match($namespacePattern, $fileContent, $matches)
41 $namespace = $matches[1];
42 $interfaceName = $matches[2];
43 $fullInterfaceName =
'\\' . $namespace .
'\\' . $interfaceName;
44 $interfaceReflection = new \ReflectionClass($fullInterfaceName);
45 if ($interfaceReflection->isSubclassOf(self::EXTENSIBLE_DATA_INTERFACE)) {
46 $interfaceName =
'\\' . $interfaceReflection->getName();
47 $extensionClassName = substr($interfaceName, 0, -strlen(
'Interface')) .
'Extension';
48 $extensionInterfaceName = $extensionClassName .
'Interface';
51 $errors = $this->checkGetExtensionAttributes(
53 $extensionInterfaceName,
60 $this->checkSetExtensionAttributes(
62 $extensionInterfaceName,
71 "Error validating $filename\n" . print_r(
$errors,
true)
86 private function checkGetExtensionAttributes(
87 \ReflectionClass $interfaceReflection,
88 $extensionInterfaceName,
93 $methodReflection = $interfaceReflection->getMethod(
'getExtensionAttributes');
95 $methodDocBlock = $methodReflection->getDocComment();
96 $pattern =
"/@return\s+" . str_replace(
'\\',
'\\\\', $extensionInterfaceName) .
"/";
97 if (!preg_match(
$pattern, $methodDocBlock)) {
99 "'{$fullInterfaceName}::getExtensionAttributes()' must be declared " 100 .
"with a return type of '{$extensionInterfaceName}'.";
102 }
catch (\ReflectionException $e) {
103 $errors[] =
"The following method should be declared in " 104 .
"'{$extensionInterfaceName}'. '{$extensionInterfaceName}' must be specified as" 105 .
" a return type for '{$fullInterfaceName}::getExtensionAttributes()'";
119 private function checkSetExtensionAttributes(
120 \ReflectionClass $interfaceReflection,
121 $extensionInterfaceName,
126 $methodReflection = $interfaceReflection->getMethod(
'setExtensionAttributes');
128 $methodParameters = $methodReflection->getParameters();
130 if (empty($methodParameters)) {
131 $errors[] =
"'{$extensionInterfaceName}' must be specified as the parameter type " 132 .
"in '{$fullInterfaceName}::setExtensionAttributes()'.";
136 preg_match(
'/\[\s<\w+?>\s([\w]+)/s', $methodParameters[0]->__toString(), $matches);
137 $isCorrectParameter =
false;
138 if (isset($matches[1]) &&
'\\' . $matches[1] != $extensionInterfaceName) {
139 $isCorrectParameter =
true;
142 if (!$isCorrectParameter) {
143 $errors[] =
"'{$extensionInterfaceName}' must be specified as the parameter type " 144 .
"in '{$fullInterfaceName}::setExtensionAttributes()'.";
147 }
catch (\ReflectionException $e) {
148 $errors[] =
"'{$fullInterfaceName}::setExtensionAttributes()' must be declared " 149 .
"with a '{$extensionInterfaceName}' parameter type.";
160 $invoker = new \Magento\Framework\App\Utility\AggregateInvoker($this);
165 function ($filename) {
168 $extensibleClassPattern =
'class [^\{]+extends[^\{]+AbstractExtensible';
169 $abstractExtensibleClassPattern =
'abstract ' . $extensibleClassPattern;
170 if (preg_match(
'/' . $extensibleClassPattern .
'/', $fileContent) &&
171 !preg_match(
'/' . $abstractExtensibleClassPattern .
'/', $fileContent)
173 $fileReflection = new \Zend\Code\Reflection\FileReflection($filename,
true);
174 foreach ($fileReflection->getClasses() as $classReflection) {
175 if ($classReflection->isSubclassOf(self::EXTENSIBLE_DATA_INTERFACE)) {
176 $methodsToCheck = [
'setExtensionAttributes',
'getExtensionAttributes'];
177 foreach ($methodsToCheck as $methodName) {
179 $classReflection->getMethod($methodName);
180 }
catch (\ReflectionException $e) {
182 $errors[] =
"'{$className}::{$methodName}()' must be declared or " 183 .
"'{$className}' should not be inherited from extensible class.";
192 "Error validating $filename\n" . print_r(
$errors,
true)
206 $codeInterfaceFiles = $this->
getFiles(
BP .
'/app',
'*Interface.php');
207 $libInterfaceFiles = $this->
getFiles(
BP .
'/lib/Magento',
'*Interface.php');
209 $filesToCheck = $this->
blacklistFilter(array_merge($codeInterfaceFiles, $libInterfaceFiles));
210 foreach ($filesToCheck as $file) {
211 $interfaces[substr($file, strlen(
BP))] = [$file];
223 $codeFiles = $this->
getFiles(
BP .
'/app',
'*.php');
224 $libFiles = $this->
getFiles(
BP .
'/lib/Magento',
'*.php');
226 $filesToCheck = $this->
blacklistFilter(array_merge($codeFiles, $libFiles));
227 foreach ($filesToCheck as $file) {
228 $phpFiles[substr($file, strlen(
BP))] = [$file];
243 foreach (glob($dir .
'/*', GLOB_ONLYDIR | GLOB_NOSORT) as $newDir) {
258 $blacklist =
Files::init()->readLists(
__DIR__ .
'/_files/ExtensibleInterfacesTest/blacklist*');
259 foreach ($preFilter as $file) {
260 if (!in_array($file, $blacklist)) {
261 $postFilter[] = $file;
testGetSetExtensionAttributes()
defined('TESTS_BP')||define('TESTS_BP' __DIR__
blacklistFilter($preFilter)
const EXTENSIBLE_DATA_INTERFACE
testExtensibleClassesWithMissingInterface()
foreach($appDirs as $dir) $files