55 $message =
'Duplicate patterns identified in list declarations:' . PHP_EOL . PHP_EOL;
56 foreach (
$errors as $file => $list) {
58 foreach ($list as $key) {
79 foreach (glob(
__DIR__ .
'/_files/' . $filePattern) as $file) {
80 $readList = include $file;
81 foreach ($readList as
$row) {
83 $key =
"{$item}|{$scope}";
84 if (isset($list[$key])) {
103 return array_pad(
$row, 4,
'');
113 $blacklistFiles = $this->getBlacklistFiles();
114 foreach ($blacklistFiles as $blacklistFile) {
152 $this->_assertNotRegExp(
153 '/\bMage::(\w+?)\(/iS',
155 "Static Method of 'Mage' class is obsolete." 202 foreach (self::$_classes as
$row) {
204 $this->_assertNotRegExp(
205 '/[^a-z\d_]' . preg_quote(
$class,
'/') .
'[^a-z\d_\\\\]/iS',
219 foreach (self::$_namespaces as
$row) {
221 $this->_assertNotRegExp(
222 '/namespace\s+' . preg_quote($namespace,
'/') .
';/S',
224 $this->_suggestReplacement(sprintf(
"Namespace '%s' is obsolete.", $namespace),
$replacement)
226 $this->_assertNotRegExp(
227 '/[^a-zA-Z\d_]' . preg_quote($namespace .
'\\',
'/') .
'/S',
229 $this->_suggestReplacement(sprintf(
"Namespace '%s' is obsolete.", $namespace),
$replacement)
249 foreach (self::$_methods as
$row) {
251 $quotedMethod = preg_quote(
$method,
'/');
253 $message = $this->_suggestReplacement(
254 "Method '{$class}::{$method}()' is obsolete in file '{$file}'.",
258 $this->_assertNotRegExp(
259 '/' . preg_quote(
$class,
'/') .
'::\s*' . $quotedMethod .
'[^a-z\d_]/iS',
264 if (!$isDeprecated) {
265 $this->_assertNotRegExp(
'/function\s*' . $quotedMethod .
'\s*\(/iS',
$content,
$message);
267 $this->_assertNotRegExp(
'/this->' . $quotedMethod .
'\s*\(/iS',
$content,
$message);
268 $this->_assertNotRegExp(
269 '/(self|static|parent)::\s*' . $quotedMethod .
'\s*\(/iS',
275 $message = $this->_suggestReplacement(
276 "Function or method '{$method}()' is obsolete in file '{$file}'.",
279 $this->_assertNotRegExp(
280 '/(?<!public|protected|private|static)\s+function\s*' . $quotedMethod .
'\s*\(/iS',
284 $this->_assertNotRegExp(
285 '/(?<![a-z\d_:]|->|function\s)' . $quotedMethod .
'\s*\(/iS',
303 foreach (self::$_paths as
$row) {
304 list($obsoletePath, , $replacementPath) =
$row;
306 $message = $this->_suggestReplacement(
307 "Path '{$obsoletePath}' is obsolete.",
331 if (0 === strpos($file, $modulePath)) {
333 '/[^a-z\d_]getChild\s*\(/iS',
335 'Block method getChild() is obsolete. ' .
336 'Replacement suggestion: \Magento\Framework\View\Element\AbstractBlock::getChildBlock()' 350 '/getOptions\(\)\s*->get(Base|App|Code|Design|Etc|Lib|Locale|Js|Media' .
351 '|Var|Tmp|Cache|Log|Session|Upload|Export)?Dir\(/S',
353 'The class \Magento\Core\Model\Config\Options is obsolete. ' 354 .
'Replacement suggestion: \Magento\Framework\Filesystem' 363 $this->_assertNotRegExp(
364 '/[^a-z\d_]getTypeInstance\s*\(\s*[^\)]+/iS',
366 'Backwards-incompatible change: method getTypeInstance() is not supposed to be invoked with any arguments.' 368 $this->_assertNotRegExp(
369 '/\->getUsedProductIds\(([^\)]+,\s*[^\)]+)?\)/',
371 'Backwards-incompatible change: method getUsedProductIds($product)' .
372 ' must be invoked with one and only one argument - product model object' 375 $this->_assertNotRegExp(
376 '#->_setActiveMenu\([\'"]([\w\d/_]+)[\'"]\)#Ui',
378 'Backwards-incompatible change: method _setActiveMenu()' .
379 ' must be invoked with menu item identifier than xpath for menu item' 394 $fullyQualified =
"{$class}::\${$attribute}";
398 $this->_assertNotRegExp(
399 '/[^a-z\d_]' . preg_quote(
$attribute,
'/') .
'[^a-z\d_]/iS',
401 $this->_suggestReplacement(sprintf(
"Class attribute '%s' is obsolete.", $fullyQualified),
$replacement)
411 $suggestion =
'Resizing images upon the client request is obsolete, use server-side resizing instead';
412 $this->_assertNotRegExp(
413 '#[^a-z\d_/]catalog/product/image[^a-z\d_/]#iS',
415 "Action 'catalog/product/image' is obsolete. {$suggestion}" 432 foreach (self::$_constants as
$row) {
439 $regex =
'\b' . preg_quote($constant,
'/') .
'\b';
453 private function buildRegExFromObsoleteConstant($classPartialPath,
$content, $constant)
455 $regex = preg_quote(
"{$classPartialPath}::{$constant}");
458 .
'|' . preg_quote(
"self::{$constant}",
'/')
459 .
'|' . preg_quote(
"static::{$constant}",
'/');
461 $regex .=
'|' . preg_quote(
"parent::{$constant}",
'/');
463 $regex .=
'|' . preg_quote(
"self::{$constant}",
'/') .
'|' . preg_quote(
"static::{$constant}",
'/');
480 $constantRegex = preg_quote($constant,
'/');
481 $classRegex = preg_quote(
$class);
482 $this->_checkExistenceOfObsoleteConstants(
486 "{$class}::{$constant}",
502 $classPathParts = explode(
'\\',
$class);
503 $classPartialPath =
'';
504 for (
$i = count($classPathParts) - 1;
$i >= 0;
$i--) {
505 if (
$i === (count($classPathParts) - 1)) {
506 $classPartialPath = $classPathParts[
$i] . $classPartialPath;
508 $classPartialPath = $classPathParts[
$i] .
'\\' . $classPartialPath;
510 $constantRegex = $this->buildRegExFromObsoleteConstant($classPartialPath,
$content, $constant);
511 $regexClassPartialPath = preg_replace(
'/' . preg_quote($classPartialPath) .
'$/',
'',
$class);
512 $classRegex = preg_quote($regexClassPartialPath . $classPathParts[
$i]);
513 if ($regexClassPartialPath !==
'') {
514 $classRegex .=
'|' . preg_quote(rtrim($regexClassPartialPath,
'\\'));
517 $classRegexNamespaceClass =
'/namespace\s+' . preg_quote(
'\\') .
'?(' . $classRegex .
')(\s|;)(\r?\n)+' 518 .
'class\s+' . preg_quote(
'\\') .
'?(' . preg_quote(rtrim($classPartialPath,
'\\')) .
')\s*/';
519 $matchNamespaceClass = preg_match($classRegexNamespaceClass,
$content);
520 $constantRegexPartial =
'/\b(?P<classWithConst>([a-zA-Z0-9_' . preg_quote(
'\\') .
']*))(' 521 . preg_quote(
'::') .
')*' .
'(' . preg_quote($constant,
'/') .
'\b)(\s*|;)/';
522 $matchConstantPartial = preg_match($constantRegexPartial,
$content, $match);
523 if (($matchNamespaceClass === 1) && ($matchConstantPartial === 1) && ($match[
'classWithConst'] ===
'')) {
527 $this->_suggestReplacement(sprintf(
"Constant '%s' is obsolete.", $constant),
$replacement)
530 $this->_checkExistenceOfObsoleteConstants(
534 "{$classPartialPath}::{$constant}",
552 private function _checkExistenceOfObsoleteConstants(
560 $constantRegexFull =
'/\b(?P<constPart>((?P<classWithConst>([a-zA-Z0-9_' . preg_quote(
'\\') .
']*))(' 561 . preg_quote(
'::') .
')*' .
'(' . $constantRegex .
'\b)))(\s*|;)/';
562 $matchConstant = preg_match_all($constantRegexFull,
$content, $matchConstantString);
564 if ($matchConstant === 1) {
565 if ($classRegex !==
'') {
566 $classRegexFull =
'/(?P<useOrNamespace>(use|namespace))\s+(?P<classPath>(' . preg_quote(
'\\')
567 .
'?(' . $classRegex .
')))(\s+as\s+(?P<classAlias>([\w\d_]+)))?(\s|;)/';
568 $matchClass = preg_match($classRegexFull,
$content, $matchClassString);
569 if ($matchClass === 1) {
570 if ($matchClassString[
'classAlias']) {
571 $result = $this->_checkAliasUseNamespace(
573 $matchConstantString,
578 $result = $this->_checkNoAliasUseNamespace($matchConstantString, $matchClassString,
$class);
581 foreach ($matchConstantString[
'classWithConst'] as $constantMatch) {
582 if (trim($constantMatch,
'\\') ===
$class) {
595 $this->_suggestReplacement(sprintf(
"Constant '%s' is obsolete.", $constant),
$replacement)
608 private function _checkAliasUseNamespace(
610 $matchConstantString,
614 $foundProperUse =
false;
615 $foundAsComponent =
false;
616 $asComponent = $matchClassString[
'classAlias'];
617 foreach ($matchConstantString[
'constPart'] as $constantMatch) {
618 $expectedOnlyConst =
'/' . $asComponent . preg_quote(
'::') . $constantRegex .
'/';
619 $expectedConstPartialClass =
'/' . $asComponent . preg_quote(
'\\')
620 . $constantRegex .
'/';
621 if ((preg_match($expectedOnlyConst, $constantMatch) === 1)
622 || (preg_match($expectedConstPartialClass, $constantMatch) === 1)) {
623 $foundAsComponent =
true;
625 if (strpos($constantMatch,
'::') !==
false) {
626 $foundProperUse = $this->_checkCompletePathOfClass(
633 if ($foundProperUse) {
638 if ($foundProperUse) {
653 private function _checkNoAliasUseNamespace(
654 $matchConstantString,
658 $foundProperUse =
false;
659 foreach ($matchConstantString[
'constPart'] as $constantMatch) {
660 $foundProperUse = $this->_checkCompletePathOfClass(
665 if ($foundProperUse) {
669 if ($foundProperUse) {
686 private function _checkCompletePathOfClass(
690 $foundAsComponent =
false,
693 $temp = explode(
'::', $constantMatch);
694 $pathWithConst = trim(ltrim(str_replace(
'\\\\',
'\\', $temp[0]),
'\\'));
695 if ($pathWithConst ===
$class) {
698 if ($foundAsComponent) {
699 $pathWithConst = ltrim(preg_replace(
'/^' . $asComponent .
'/',
'', $pathWithConst),
'\\');
700 if ($pathWithConst ===
'') {
704 $pathWithConstParts = explode(
'\\', $pathWithConst);
705 $pathInUseNamespace = trim($matchClassString[
'classPath'],
'\\');
706 $pathInUseNamespaceTruncated = trim(trim(
708 '/' . preg_quote($pathWithConstParts[0]) .
'$/',
714 if ($this->_checkClasspathProperDivisionNoConstantPath(
715 $pathInUseNamespaceTruncated,
723 return $this->_checkClasspathProperDivisionWithConstantPath(
724 $pathInUseNamespaceTruncated,
743 private function _checkClasspathProperDivisionNoConstantPath(
744 $pathInUseNamespaceTruncated,
750 if ($pathInUseNamespaceTruncated === $pathInUseNamespace && $pathInUseNamespaceTruncated !==
$class 751 && ($foundAsComponent || (strpos($matchClassString[
'useOrNamespace'],
'namespace') !==
false))) {
768 private function _checkClasspathProperDivisionWithConstantPath(
769 $pathInUseNamespaceTruncated,
775 if ((($pathInUseNamespaceTruncated .
'\\' . $pathWithConst ===
$class)
776 && ($pathInUseNamespaceTruncated !== $pathInUseNamespace) && !$foundAsComponent)
777 || (($pathInUseNamespaceTruncated ===
$class) && (strpos($pathWithConst,
'\\') ===
false)
778 && $foundAsComponent)) {
805 return '\bconst\s+' . preg_quote($constant,
'/') .
'\b';
813 $this->_assertNotRegExp(
814 '/[^a-z\d_]skipCalculate[^a-z\d_]/iS',
816 "Configuration property 'skipCalculate' is obsolete." 830 return (
bool)preg_match(
'/\b(?:class|interface)\s+' .
$name .
'\b[^{]*\{/iS',
$content);
843 return (
bool)preg_match(
844 '/\s+extends\s+' .
$name .
'\b|\s+implements\s+[^{]*\b' .
$name .
'\b[^{^\\\\]*\{/iS',
856 private function _suggestReplacement($original, $suggestion)
859 return "{$original} Suggested replacement: {$suggestion}";
881 $ignored = $this->getBlacklistFiles(
true);
900 $this->_assertNotRegExp(
901 '/[^a-z\d_]Mage\s*::/i',
903 '"Mage" class methods are obsolete' 916 private function processPattern($appPath,
$pattern)
919 $relativePathStart = strlen($appPath);
921 $fileSet = glob($appPath . DIRECTORY_SEPARATOR .
$pattern, GLOB_NOSORT);
922 foreach ($fileSet as $file) {
923 $files[] = ltrim(substr($file, $relativePathStart),
'/');
936 private function getBlacklistFiles($absolutePath =
false)
938 $blackList = include
__DIR__ .
'/_files/blacklist/obsolete_mage.php';
941 foreach ($blackList as $file) {
943 $ignored = array_merge($ignored, glob($appPath . DIRECTORY_SEPARATOR . $file, GLOB_NOSORT));
945 $ignored = array_merge($ignored, $this->processPattern($appPath, $file));
elseif(isset( $params[ 'redirect_parent']))
static getPhpFiles($changedFilesList, $fileTypes=0)
_testObsoletePropertySkipCalculate($content)
_testObsoleteActions($content)
_testObsoleteConstants($content)
defined('TESTS_BP')||define('TESTS_BP' __DIR__
_isClassConstantDefined($content, $constant)
static composeDataSets(array $files)
_getClassConstantDefinitionRegExp($constant)
_testObsoleteMethodArguments($content)
_testGetOptionsSpecialCase($content)
$_option $_optionId $class
_testObsoleteClasses($content)
_testObsoleteMethods($content, $file)
_testGetChildSpecialCase($content, $file)
_assertNotRegexp($regex, $content, $message)
static setUpBeforeClass()
static _populateList(array &$list, array &$errors, $filePattern, $hasScope=true)
_isDirectDescendant($content, $name)
_testObsoletePaths($file)
_testObsoleteNamespaces($content)
foreach($appDirs as $dir) $files
_isClassOrInterface($content, $name)
_testObsoleteProperties($content)
static _padRow($row, $hasScope)
testMageMethodsObsolete()
if(!isset($_GET['name'])) $name