Magento 2 Documentation  2.3
Documentation for Magento 2 CMS v2.3 (December 2018)
Public Member Functions | Protected Member Functions
ClassesTest Class Reference
Inheritance diagram for ClassesTest:

Public Member Functions

 testPhpFiles ()
 
 testConfigFiles ()
 
 testLayoutFiles ()
 
 testClassNamespaces ()
 
 testClassReferences ()
 
 testCoversAnnotation ()
 

Protected Member Functions

 setUp ()
 

Detailed Description

@SuppressWarnings(PHPMD.ExcessiveClassComplexity)

Definition at line 17 of file ClassesTest.php.

Member Function Documentation

◆ setUp()

setUp ( )
protected

Set Up

Definition at line 44 of file ClassesTest.php.

45  {
46  $this->componentRegistrar = new ComponentRegistrar();
47  }

◆ testClassNamespaces()

testClassNamespaces ( )

Assert PHP classes have valid formal namespaces according to file locations

Parameters
array$file

Definition at line 226 of file ClassesTest.php.

227  {
228  $invoker = new \Magento\Framework\App\Utility\AggregateInvoker($this);
229  $invoker(
235  function ($file) {
236  $relativePath = str_replace(BP . "/", "", $file);
237  // exceptions made for fixture files from tests
238  if (strpos($relativePath, '/_files/') !== false) {
239  return;
240  }
241 
242  $contents = file_get_contents($file);
243 
244  $classPattern = '/^(abstract\s)?class\s[A-Z][^\s\/]+/m';
245 
246  $classNameMatch = [];
247  $className = null;
248 
249  // if no class declaration found for $file, then skip this file
250  if (preg_match($classPattern, $contents, $classNameMatch) == 0) {
251  return;
252  }
253 
254  $classParts = explode(' ', $classNameMatch[0]);
255  $className = array_pop($classParts);
256  $this->assertClassNamespace($file, $relativePath, $contents, $className);
257  },
258  Files::init()->getPhpFiles()
259  );
260  }
$contents
Definition: website.php:14
const BP
Definition: autoload.php:14
$relativePath
Definition: get.php:35
if($currentSelectedMethod==$_code) $className
Definition: form.phtml:31

◆ testClassReferences()

testClassReferences ( )
Parameters
string$file

Definition at line 307 of file ClassesTest.php.

308  {
309  $invoker = new \Magento\Framework\App\Utility\AggregateInvoker($this);
310  $invoker(
314  function ($file) {
315  $relativePath = str_replace(BP, "", $file);
316  // Due to the examples given with the regex patterns, we skip this test file itself
317  if (preg_match(
318  '/\/dev\/tests\/static\/testsuite\/Magento\/Test\/Integrity\/ClassesTest.php$/',
320  )) {
321  return;
322  }
323  $contents = file_get_contents($file);
324  $formalPattern = '/^namespace\s[a-zA-Z]+(\\\\[a-zA-Z0-9]+)*/m';
325  $formalNamespaceArray = [];
326 
327  // Skip the file if the class is not defined using formal namespace
328  if (preg_match($formalPattern, $contents, $formalNamespaceArray) == 0) {
329  return;
330  }
331  $namespacePath = str_replace('\\', '/', substr($formalNamespaceArray[0], 10));
332 
333  // Instantiation of new object, for example: "return new Foo();"
334  $newObjectPattern = '/^' .
335  '.*new\s(?<venderClass>\\\\Magento(?:\\\\[a-zA-Z0-9_]+)+)\(.*\)' .
336  '|.*new\s(?<badClass>[A-Z][a-zA-Z0-9]+[a-zA-Z0-9_\\\\]*)\(.*\)\;' .
337  '|use [A-Z][a-zA-Z0-9_\\\\]+ as (?<aliasClass>[A-Z][a-zA-Z0-9]+)' .
338  '/m';
339  $result1 = [];
340  preg_match_all($newObjectPattern, $contents, $result1);
341 
342  // Static function/variable, for example: "Foo::someStaticFunction();"
343  $staticCallPattern = '/^' .
344  '((?!Magento).)*(?<venderClass>\\\\Magento(?:\\\\[a-zA-Z0-9_]+)+)\:\:.*\;' .
345  '|[^\\\\^a-z^A-Z^0-9^_^:](?<badClass>[A-Z][a-zA-Z0-9_]+)\:\:.*\;' .
346  '|use [A-Z][a-zA-Z0-9_\\\\]+ as (?<aliasClass>[A-Z][a-zA-Z0-9]+)' .
347  '/m';
348  $result2 = [];
349  preg_match_all($staticCallPattern, $contents, $result2);
350 
351  // Annotation, for example: "* @return \Magento\Foo\Bar" or "* @throws Exception" or "* @return Foo"
352  $annotationPattern = '/^' .
353  '[\s]*\*\s\@(?:return|throws)\s(?<venderClass>\\\\Magento(?:\\\\[a-zA-Z0-9_]+)+)' .
354  '|[\s]*\*\s\@return\s(?<badClass>[A-Z][a-zA-Z0-9_\\\\]+)' .
355  '|[\s]*\*\s\@throws\s(?<exception>[A-Z][a-zA-Z0-9_\\\\]+)' .
356  '|use [A-Z][a-zA-Z0-9_\\\\]+ as (?<aliasClass>[A-Z][a-zA-Z0-9]+)' .
357  '/m';
358  $result3 = [];
359  preg_match_all($annotationPattern, $contents, $result3);
360 
361  $vendorClasses = array_unique(
362  array_merge_recursive($result1['venderClass'], $result2['venderClass'], $result3['venderClass'])
363  );
364 
365  $badClasses = array_unique(
366  array_merge_recursive($result1['badClass'], $result2['badClass'], $result3['badClass'])
367  );
368 
369  $aliasClasses = array_unique(
370  array_merge_recursive($result1['aliasClass'], $result2['aliasClass'], $result3['aliasClass'])
371  );
372 
373  $vendorClasses = array_filter($vendorClasses, 'strlen');
374  $vendorClasses = $this->referenceBlacklistFilter($vendorClasses);
375  if (!empty($vendorClasses)) {
376  $this->assertClassesExist($vendorClasses, $file);
377  }
378 
379  if (!empty($result3['exception']) && $result3['exception'][0] != "") {
380  $badClasses = array_merge($badClasses, array_filter($result3['exception'], 'strlen'));
381  }
382 
383  $badClasses = array_filter($badClasses, 'strlen');
384  if (empty($badClasses)) {
385  return;
386  }
387 
388  $aliasClasses = array_filter($aliasClasses, 'strlen');
389  if (!empty($aliasClasses)) {
390  $badClasses = $this->handleAliasClasses($aliasClasses, $badClasses);
391  }
392 
393  $badClasses = $this->referenceBlacklistFilter($badClasses);
394  $badClasses = $this->removeSpecialCases($badClasses, $file, $contents, $namespacePath);
395  $this->assertClassReferences($badClasses, $file);
396  },
397  Files::init()->getPhpFiles()
398  );
399  }
$contents
Definition: website.php:14
const BP
Definition: autoload.php:14
$relativePath
Definition: get.php:35

◆ testConfigFiles()

testConfigFiles ( )
Parameters
string$path

Definition at line 123 of file ClassesTest.php.

124  {
125  $invoker = new \Magento\Framework\App\Utility\AggregateInvoker($this);
126  $invoker(
130  function ($path) {
131  $classes = Classes::collectClassesInConfig(simplexml_load_file($path));
132  $this->assertClassesExist($classes, $path);
133  },
134  Files::init()->getMainConfigFiles()
135  );
136  }
static collectClassesInConfig(\SimpleXMLElement $xml)
Definition: Classes.php:121

◆ testCoversAnnotation()

testCoversAnnotation ( )

Definition at line 652 of file ClassesTest.php.

653  {
654  $files = Files::init();
655  $errors = [];
656  $filesToTest = $files->getPhpFiles(Files::INCLUDE_TESTS);
657 
658  if (($key = array_search(str_replace('\\', '/', __FILE__), $filesToTest)) !== false) {
659  unset($filesToTest[$key]);
660  }
661 
662  foreach ($filesToTest as $file) {
663  $code = file_get_contents($file);
664  if (preg_match('/@covers(DefaultClass)?\s+([\w\\\\]+)(::([\w\\\\]+))?/', $code, $matches)) {
665  if ($this->isNonexistentEntityCovered($matches)) {
666  $errors[] = $file . ': ' . $matches[0];
667  }
668  }
669  }
670  if ($errors) {
671  $this->fail(
672  'Nonexistent classes/methods were found in @covers annotations: ' . PHP_EOL . implode(PHP_EOL, $errors)
673  );
674  }
675  }
defined('MTF_BOOT_FILE')||define('MTF_BOOT_FILE' __FILE__
Definition: bootstrap.php:7
foreach($appDirs as $dir) $files
$errors
Definition: overview.phtml:9
$code
Definition: info.phtml:12

◆ testLayoutFiles()

testLayoutFiles ( )
Parameters
string$path

Definition at line 138 of file ClassesTest.php.

139  {
140  $invoker = new \Magento\Framework\App\Utility\AggregateInvoker($this);
141  $invoker(
145  function ($path) {
146  $xml = simplexml_load_file($path);
147 
148  $classes = Classes::getXmlNodeValues(
149  $xml,
150  '/layout//*[contains(text(), "\\\\Block\\\\") or contains(text(),
151  "\\\\Model\\\\") or contains(text(), "\\\\Helper\\\\")]'
152  );
154  $xml,
155  '/layout//@helper',
156  'helper'
157  ) as $class) {
158  $classes[] = Classes::getCallbackClass($class);
159  }
161  $xml,
162  '/layout//@module',
163  'module'
164  ) as $module) {
165  $classes[] = str_replace('_', '\\', "{$module}_Helper_Data");
166  }
167  $classes = array_merge($classes, Classes::collectLayoutClasses($xml));
168 
169  $this->assertClassesExist(array_unique($classes), $path);
170  },
171  Files::init()->getLayoutFiles()
172  );
173  }
static getCallbackClass($callbackName)
Definition: Classes.php:109
static getXmlAttributeValues(\SimpleXMLElement $xml, $xPath, $attributeName)
Definition: Classes.php:90
static collectLayoutClasses(\SimpleXMLElement $xml)
Definition: Classes.php:160
$_option $_optionId $class
Definition: date.phtml:13
static getXmlNodeValues(\SimpleXMLElement $xml, $xPath)
Definition: Classes.php:55

◆ testPhpFiles()

testPhpFiles ( )
Parameters
string$file

Definition at line 49 of file ClassesTest.php.

50  {
51  $invoker = new \Magento\Framework\App\Utility\AggregateInvoker($this);
52  $invoker(
56  function ($file) {
58  $classes = Classes::getAllMatches(
59  $contents,
60  '/
61  # ::getResourceModel ::getBlockSingleton ::getModel ::getSingleton
62  \:\:get(?:ResourceModel | BlockSingleton | Model | Singleton)?\(\s*[\'"]([a-z\d\\\\]+)[\'"]\s*[\),]
63 
64  # various methods, first argument
65  | \->(?:initReport | addBlock | createBlock
66  | setAttributeModel | setBackendModel | setFrontendModel | setSourceModel | setModel
67  )\(\s*\'([a-z\d\\\\]+)\'\s*[\),]
68 
69  # various methods, second argument
70  | \->add(?:ProductConfigurationHelper | OptionsRenderCfg)\(.+?,\s*\'([a-z\d\\\\]+)\'\s*[\),]
71 
72  # \Mage::helper ->helper
73  | (?:Mage\:\:|\->)helper\(\s*\'([a-z\d\\\\]+)\'\s*\)
74 
75  # misc
76  | function\s_getCollectionClass\(\)\s+{\s+return\s+[\'"]([a-z\d\\\\]+)[\'"]
77  | \'resource_model\'\s*=>\s*[\'"]([a-z\d\\\\]+)[\'"]
78  | (?:_parentResourceModelName | _checkoutType | _apiType)\s*=\s*\'([a-z\d\\\\]+)\'
79  | \'renderer\'\s*=>\s*\'([a-z\d\\\\]+)\'
80  /ix'
81  );
82 
83  // without modifier "i". Starting from capital letter is a significant characteristic of a class name
85  $contents,
86  '/(?:\-> | parent\:\:)(?:_init | setType)\(\s*
87  \'([A-Z][a-z\d][A-Za-z\d\\\\]+)\'(?:,\s*\'([A-Z][a-z\d][A-Za-z\d\\\\]+)\')
88  \s*\)/x',
89  $classes
90  );
91 
92  $this->collectResourceHelpersPhp($contents, $classes);
93 
94  $this->assertClassesExist($classes, $file);
95  },
96  Files::init()->getPhpFiles(
103  )
104  );
105  }
$contents
Definition: website.php:14
static getAllMatches($contents, $regex, &$result=[])
Definition: Classes.php:29

The documentation for this class was generated from the following file: