REPO-66: [EQP][Sniffs Consolidation] Deliver Magento Coding Standard to magento2ce

This commit is contained in:
Lena Orobei committed 2019-03-27 12:14:03 -05:00
1 parent 212a5339bb
commit 7421dfb0a2
66 files changed
+206 -2375

No files matched your search

@@ -7,6 +7,9 @@ namespace Magento\Config\Observer\Config\Backend\Admin;
use Magento\Framework\Event\ObserverInterface;
/**
* Class AfterCustomUrlChangedObserver
*/
class AfterCustomUrlChangedObserver implements ObserverInterface
{
/**
@@ -56,7 +59,6 @@ class AfterCustomUrlChangedObserver implements ObserverInterface
*
* @param \Magento\Framework\Event\Observer $observer
* @return void
* @SuppressWarnings(PHPMD.ExitExpression)
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
public function execute(\Magento\Framework\Event\Observer $observer)
@@ -68,6 +70,7 @@ class AfterCustomUrlChangedObserver implements ObserverInterface
$this->_authSession->destroy();
$adminUrl = $this->_backendData->getHomePageUrl();
$this->_response->setRedirect($adminUrl)->sendResponse();
// phpcs:ignore Magento2.Security.LanguageConstruct.ExitUsage
exit(0);
}
}
@@ -17,6 +17,7 @@ use Magento\Framework\App\Filesystem\DirectoryList;
use Magento\Framework\DataObjectFactory;
/**
* Class Viewfile
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
*/
class Viewfile extends \Magento\Customer\Controller\Adminhtml\Index
@@ -127,8 +128,6 @@ class Viewfile extends \Magento\Customer\Controller\Adminhtml\Index
*
* @return \Magento\Framework\Controller\ResultInterface|void
* @throws NotFoundException
*
* @SuppressWarnings(PHPMD.ExitExpression)
*/
public function execute()
{
@@ -146,6 +145,7 @@ class Viewfile extends \Magento\Customer\Controller\Adminhtml\Index
}
if ($plain) {
// phpcs:ignore Magento2.Functions.DiscouragedFunction
$extension = pathinfo($path, PATHINFO_EXTENSION);
switch (strtolower($extension)) {
case 'gif':
@@ -175,6 +175,7 @@ class Viewfile extends \Magento\Customer\Controller\Adminhtml\Index
$resultRaw->setContents($directory->readFile($fileName));
return $resultRaw;
} else {
// phpcs:ignore Magento2.Functions.DiscouragedFunction
$name = pathinfo($path, PATHINFO_BASENAME);
$this->_fileFactory->create(
$name,
+26 -4
View File
@@ -125,6 +125,8 @@ class Queue
}
/**
* Adds deployment package.
*
* @param Package $package
* @param Package[] $dependencies
* @return bool true on success
@@ -140,6 +142,8 @@ class Queue
}
/**
* Returns packages array.
*
* @return Package[]
*/
public function getPackages()
@@ -162,6 +166,7 @@ class Queue
$this->assertAndExecute($name, $packages, $packageJob);
}
$this->logger->info('.');
// phpcs:ignore Magento2.Functions.DiscouragedFunction
sleep(3);
foreach ($this->inProgress as $name => $package) {
if ($this->isDeployed($package)) {
@@ -209,6 +214,8 @@ class Queue
}
/**
* Executes deployment package.
*
* @param Package $package
* @param string $name
* @param array $packages
@@ -244,6 +251,7 @@ class Queue
}
}
$this->logger->info('.');
// phpcs:ignore Magento2.Functions.DiscouragedFunction
sleep(5);
}
if ($this->isCanBeParalleled()) {
@@ -253,6 +261,8 @@ class Queue
}
/**
* Checks if can be parallel.
*
* @return bool
*/
private function isCanBeParalleled()
@@ -261,9 +271,11 @@ class Queue
}
/**
* Executes the process.
*
* @param Package $package
* @return bool true on success for main process and exit for child process
* @SuppressWarnings(PHPMD.ExitExpression)
* @throws \RuntimeException
*/
private function execute(Package $package)
{
@@ -291,6 +303,7 @@ class Queue
);
if ($this->isCanBeParalleled()) {
// phpcs:ignore Magento2.Functions.DiscouragedFunction
$pid = pcntl_fork();
if ($pid === -1) {
throw new \RuntimeException('Unable to fork a new process');
@@ -305,6 +318,7 @@ class Queue
// process child process
$this->inProgress = [];
$this->deployPackageService->deploy($package, $this->options, true);
// phpcs:ignore Magento2.Security.LanguageConstruct.ExitUsage
exit(0);
} else {
$this->deployPackageService->deploy($package, $this->options);
@@ -313,6 +327,8 @@ class Queue
}
/**
* Checks if package is deployed.
*
* @param Package $package
* @return bool
*/
@@ -320,11 +336,13 @@ class Queue
{
if ($this->isCanBeParalleled()) {
if ($package->getState() === null) {
// phpcs:ignore Magento2.Functions.DiscouragedFunction
$pid = pcntl_waitpid($this->getPid($package), $status, WNOHANG);
if ($pid === $this->getPid($package)) {
$package->setState(Package::STATE_COMPLETED);
unset($this->inProgress[$package->getPath()]);
// phpcs:ignore Magento2.Functions.DiscouragedFunction
return pcntl_wexitstatus($status) === 0;
}
return false;
@@ -334,17 +352,19 @@ class Queue
}
/**
* Returns process ID or null if not found.
*
* @param Package $package
* @return int|null
*/
private function getPid(Package $package)
{
return isset($this->processIds[$package->getPath()])
? $this->processIds[$package->getPath()]
: null;
return isset($this->processIds[$package->getPath()]) ?? null;
}
/**
* Checks timeout.
*
* @return bool
*/
private function checkTimeout()
@@ -357,11 +377,13 @@ class Queue
*
* Protect against zombie process
*
* @throws \RuntimeException
* @return void
*/
public function __destruct()
{
foreach ($this->inProgress as $package) {
// phpcs:ignore Magento2.Functions.DiscouragedFunction
if (pcntl_waitpid($this->getPid($package), $status) === -1) {
throw new \RuntimeException(
'Error while waiting for package deployed: ' . $this->getPid($package) . '; Status: ' . $status
@@ -1,6 +1,5 @@
<?php
/**
*
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
@@ -10,6 +9,9 @@ use Magento\Downloadable\Helper\Download as DownloadHelper;
use Magento\Downloadable\Model\Link\Purchased\Item as PurchasedLink;
use Magento\Framework\App\ResponseInterface;
/**
* Class Link
*/
class Link extends \Magento\Downloadable\Controller\Download
{
/**
@@ -29,7 +31,6 @@ class Link extends \Magento\Downloadable\Controller\Download
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
* @SuppressWarnings(PHPMD.NPathComplexity)
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
* @SuppressWarnings(PHPMD.ExitExpression)
*/
public function execute()
{
@@ -117,6 +118,7 @@ class Link extends \Magento\Downloadable\Controller\Download
$linkPurchasedItem->setStatus(PurchasedLink::LINK_STATUS_EXPIRED);
}
$linkPurchasedItem->save();
// phpcs:ignore Magento2.Security.LanguageConstruct.ExitUsage
exit(0);
} catch (\Exception $e) {
$this->messageManager->addError(__('Something went wrong while getting the requested content.'));
@@ -1,6 +1,5 @@
<?php
/**
*
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
@@ -9,13 +8,15 @@ namespace Magento\Downloadable\Controller\Download;
use Magento\Downloadable\Helper\Download as DownloadHelper;
use Magento\Framework\App\ResponseInterface;
/**
* Class LinkSample
*/
class LinkSample extends \Magento\Downloadable\Controller\Download
{
/**
* Download link's sample action
*
* @return ResponseInterface
* @SuppressWarnings(PHPMD.ExitExpression)
*/
public function execute()
{
@@ -39,6 +40,7 @@ class LinkSample extends \Magento\Downloadable\Controller\Download
}
try {
$this->_processDownload($resource, $resourceType);
// phpcs:ignore Magento2.Security.LanguageConstruct.ExitUsage
exit(0);
} catch (\Exception $e) {
$this->messageManager->addError(
@@ -1,6 +1,5 @@
<?php
/**
*
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
@@ -9,13 +8,15 @@ namespace Magento\Downloadable\Controller\Download;
use Magento\Downloadable\Helper\Download as DownloadHelper;
use Magento\Framework\App\ResponseInterface;
/**
* Class Sample
*/
class Sample extends \Magento\Downloadable\Controller\Download
{
/**
* Download sample action
*
* @return ResponseInterface
* @SuppressWarnings(PHPMD.ExitExpression)
*/
public function execute()
{
@@ -36,6 +37,7 @@ class Sample extends \Magento\Downloadable\Controller\Download
}
try {
$this->_processDownload($resource, $resourceType);
// phpcs:ignore Magento2.Security.LanguageConstruct.ExitUsage
exit(0);
} catch (\Exception $e) {
$this->messageManager->addError(
@@ -71,6 +71,7 @@ class ProcessManager
private function simpleThreadExecute($userFunctions)
{
foreach ($userFunctions as $userFunction) {
// phpcs:ignore Magento2.Functions.DiscouragedFunction
call_user_func($userFunction);
}
}
@@ -79,6 +80,7 @@ class ProcessManager
* Execute user functions in multiThreads mode
*
* @param \Traversable $userFunctions
* @throws \RuntimeException
* @SuppressWarnings(PHPMD.UnusedLocalVariable)
*/
private function multiThreadsExecute($userFunctions)
@@ -86,6 +88,7 @@ class ProcessManager
$this->resource->closeConnection(null);
$threadNumber = 0;
foreach ($userFunctions as $userFunction) {
// phpcs:ignore Magento2.Functions.DiscouragedFunction
$pid = pcntl_fork();
if ($pid == -1) {
throw new \RuntimeException('Unable to fork a new process');
@@ -95,6 +98,7 @@ class ProcessManager
$this->startChildProcess($userFunction);
}
}
// phpcs:ignore Magento2.CodeAnalysis.EmptyBlock,Magento2.Functions.DiscouragedFunction
while (pcntl_waitpid(0, $status) != -1) {
//Waiting for the completion of child processes
}
@@ -128,12 +132,13 @@ class ProcessManager
* Start child process
*
* @param callable $userFunction
* @SuppressWarnings(PHPMD.ExitExpression)
*/
private function startChildProcess(callable $userFunction)
{
// phpcs:ignore Magento2.Functions.DiscouragedFunction
$status = call_user_func($userFunction);
$status = is_integer($status) ? $status : 0;
$status = is_int($status) ? $status : 0;
// phpcs:ignore Magento2.Security.LanguageConstruct.ExitUsage
exit($status);
}
@@ -146,8 +151,10 @@ class ProcessManager
{
$threadNumber++;
if ($threadNumber >= $this->threadsCount) {
// phpcs:disable Magento2.Functions.DiscouragedFunction
pcntl_wait($status);
if (pcntl_wexitstatus($status) !== 0) {
// phpcs:enable
$this->failInChildProcess = true;
}
$threadNumber--;
@@ -46,7 +46,6 @@ class CallbackInvoker implements CallbackInvokerInterface
/**
* @inheritdoc
* @SuppressWarnings(PHPMD.ExitExpression)
*/
public function invoke(QueueInterface $queue, $maxNumberOfMessages, $callback)
{
@@ -54,9 +53,11 @@ class CallbackInvoker implements CallbackInvokerInterface
for ($i = $maxNumberOfMessages; $i > 0; $i--) {
do {
$message = $queue->dequeue();
// phpcs:ignore Magento2.Functions.DiscouragedFunction
} while ($message === null && (sleep(1) === 0));
if (false === $this->poisonPillCompare->isLatestVersion($this->poisonPillVersion)) {
$queue->reject($message);
// phpcs:ignore Magento2.Security.LanguageConstruct.ExitUsage
exit(0);
}
$callback($message);
@@ -73,7 +73,6 @@ class Index extends \Magento\Framework\App\Action\Action implements CsrfAwareAct
* Instantiate IPN model and pass IPN request to it
*
* @return void
* @SuppressWarnings(PHPMD.ExitExpression)
*/
public function execute()
{
@@ -95,6 +94,7 @@ class Index extends \Magento\Framework\App\Action\Action implements CsrfAwareAct
$this->_logger->critical($e);
$this->getResponse()->setStatusHeader(503, '1.1', 'Service Unavailable')->sendResponse();
/** @todo eliminate usage of exit statement */
// phpcs:ignore Magento2.Security.LanguageConstruct.ExitUsage
exit;
} catch (\Exception $e) {
$this->_logger->critical($e);
@@ -121,10 +121,10 @@ class DownloadCustomOption extends \Magento\Framework\App\Action\Action implemen
* Ends execution process
*
* @return void
* @SuppressWarnings(PHPMD.ExitExpression)
*/
protected function endExecute()
{
// phpcs:ignore Magento2.Security.LanguageConstruct.ExitUsage
exit(0);
}
}
@@ -51,7 +51,6 @@ class DownloadCustomOption extends \Magento\Wishlist\Controller\AbstractIndex im
*
* @return \Magento\Framework\Controller\Result\Forward
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
* @SuppressWarnings(PHPMD.ExitExpression)
*/
public function execute()
{
+3 -2
View File
@@ -82,15 +82,16 @@
"zendframework/zend-view": "~2.10.0"
},
"require-dev": {
"allure-framework/allure-phpunit": "~1.2.0",
"friendsofphp/php-cs-fixer": "~2.13.0",
"lusitanian/oauth": "~0.8.10",
"magento/magento-coding-standard": "~1.0.0",
"magento/magento2-functional-testing-framework": "~2.3.14",
"pdepend/pdepend": "2.5.2",
"phpmd/phpmd": "@stable",
"phpunit/phpunit": "~6.5.0",
"sebastian/phpcpd": "~3.0.0",
"squizlabs/php_codesniffer": "3.3.1",
"allure-framework/allure-phpunit": "~1.2.0"
"squizlabs/php_codesniffer": "3.3.1"
},
"suggest": {
"ext-pcntl": "Need for run processes in parallel mode"
Generated
+31 -1
View File
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "60007664938710edf52eadddd7551867",
"content-hash": "825a03a040f3eff4ea6ea537b7530f15",
"packages": [
{
"name": "braintree/braintree_php",
@@ -6618,6 +6618,36 @@
],
"time": "2018-02-14T22:37:14+00:00"
},
{
"name": "magento/magento-coding-standard",
"version": "1.0.0",
"source": {
"type": "git",
"url": "https://github.com/magento/magento-coding-standard.git",
"reference": "b79055fdd16e0657c95ee214ebb81466c5f08745"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/magento/magento-coding-standard/zipball/b79055fdd16e0657c95ee214ebb81466c5f08745",
"reference": "b79055fdd16e0657c95ee214ebb81466c5f08745",
"shasum": ""
},
"require": {
"php": ">=5.6.0",
"squizlabs/php_codesniffer": "~3.3.0"
},
"require-dev": {
"phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0"
},
"type": "phpcodesniffer-standard",
"notification-url": "https://packagist.org/downloads/",
"license": [
"OSL-3.0",
"AFL-3.0"
],
"description": "A set of Magento specific PHP CodeSniffer rules.",
"time": "2019-03-27T14:17:16+00:00"
},
{
"name": "magento/magento2-functional-testing-framework",
"version": "2.3.14",
@@ -10,8 +10,8 @@ use Magento\Mtf\ObjectManager;
/**
* Class EntryPoint
* Application entry point, used to bootstrap and run application
*
* Application entry point, used to bootstrap and run application
*/
class EntryPoint
{
@@ -36,7 +36,6 @@ class EntryPoint
* @param string $rootDir
* @param array $parameters
* @param ObjectManager $objectManager
* @SuppressWarnings(PHPMD.ExitExpression)
*/
public function __construct(
$rootDir,
@@ -51,7 +50,7 @@ class EntryPoint
/**
* Run a Mtf application
*
* @param $applicationName
* @param string $applicationName
* @param array $arguments
* @return mixed
* @throws \DomainException
@@ -7,6 +7,11 @@ namespace Magento\Framework\Code\GeneratorTest;
use Zend\Code\Generator\DocBlockGenerator;
/**
* Class ParentClassWithNamespace
*
* phpcs:ignoreFile
*/
class ParentClassWithNamespace
{
/**
@@ -78,9 +83,6 @@ class ParentClassWithNamespace
{
}
/**
* @SuppressWarnings(PHPMD.FinalImplementation) Suppressed as is a fixture but not a real code
*/
final public function publicParentFinal()
{
}
@@ -9,6 +9,7 @@ use Zend\Code\Generator\ClassGenerator;
/**
* Class SourceClassWithNamespace
* phpcs:ignoreFile
*/
class SourceClassWithNamespace extends ParentClassWithNamespace
{
@@ -115,8 +116,6 @@ class SourceClassWithNamespace extends ParentClassWithNamespace
/**
* Test method
*
* @SuppressWarnings(PHPMD.FinalImplementation) Suppressed as is a fixture but not a real code
*/
final public function publicChildFinal()
{
@@ -8,7 +8,7 @@
namespace Magento\Framework\Interception\Fixture;
/**
* @codingStandardsIgnoreStart
* phpcs:ignoreFile
*/
class Intercepted extends InterceptedParent implements InterceptedInterface
{
@@ -49,7 +49,6 @@ class Intercepted extends InterceptedParent implements InterceptedInterface
/**
* @SuppressWarnings(PHPMD.ShortMethodName)
* @SuppressWarnings(PHPMD.FinalImplementation) Suppressed as is a fixture but not a real code
*/
final public function E($param1)
{
@@ -1,29 +0,0 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Magento\CodeMessDetector\Rule\Design;
use PHPMD\AbstractNode;
use PHPMD\AbstractRule;
use PHPMD\Rule\ClassAware;
use PHPMD\Rule\MethodAware;
/**
* Magento is a highly extensible and customizable platform.
* Usage of final classes and methods is prohibited.
*/
class FinalImplementation extends AbstractRule implements ClassAware, MethodAware
{
/**
* @inheritdoc
*/
public function apply(AbstractNode $node)
{
if ($node->isFinal()) {
$this->addViolation($node, [$node->getType(), $node->getFullQualifiedName()]);
}
}
}
@@ -1,128 +0,0 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Magento\CodeMessDetector\Test\Unit\Rule\Design;
use PHPUnit\Framework\TestCase as TestCase;
use PHPUnit_Framework_MockObject_MockObject as MockObject;
use PHPUnit\Framework\MockObject\Matcher\InvokedRecorder as InvokedRecorder;
use PHPUnit\Framework\MockObject\Builder\InvocationMocker as InvocationMocker;
use Magento\CodeMessDetector\Rule\Design\FinalImplementation;
use PHPMD\Report;
use PHPMD\AbstractNode;
use PHPMD\Node\ClassNode;
use PHPMD\Node\MethodNode;
use BadMethodCallException;
class FinalImplementationTest extends TestCase
{
/**
* @param string $nodeType
*
* @dataProvider finalizableNodeTypesProvider
*/
public function testRuleNotAppliesToNotFinalFinalizable($nodeType)
{
$finalizableNode = $this->createFinalizableNodeMock($nodeType);
$finalizableNode->method('isFinal')->willReturn(false);
$rule = new FinalImplementation();
$this->expectsRuleViolation($rule, $this->never());
$rule->apply($finalizableNode);
}
/**
* @param string $nodeType
*
* @dataProvider finalizableNodeTypesProvider
*/
public function testRuleAppliesToFinalFinalizable($nodeType)
{
$finalizableNode = $this->createFinalizableNodeMock($nodeType);
$finalizableNode->method('isFinal')->willReturn(true);
$rule = new FinalImplementation();
$this->expectsRuleViolation($rule, $this->once());
$rule->apply($finalizableNode);
}
/**
* @param string $nodeType
*
* @dataProvider finalizableNodeTypesProvider
*/
public function testRuleVerifiesFinalizableNodes($nodeType)
{
$finalizableNode = $this->createFinalizableNodeMock($nodeType);
$finalizableNode->expects($this->atLeastOnce())
->method('isFinal');
$rule = new FinalImplementation();
$rule->apply($finalizableNode);
}
/**
* @expectedException BadMethodCallException
*/
public function testRuleFailsOnNotFinalizableNodes()
{
$someNode = $this->getMockBuilder(AbstractNode::class)
->disableOriginalConstructor()
->getMockForAbstractClass();
$rule = new FinalImplementation();
$rule->apply($someNode);
}
/**
* "final" keyword may be applied only to classes and methods
*
* @return array
*/
public function finalizableNodeTypesProvider()
{
return [
[ClassNode::class],
[MethodNode::class],
];
}
/**
* If node is finalizable it has "isFinal" magic PHP method
*
* @param string $nodeType
* @return ClassNode|MethodNode|MockObject
*/
private function createFinalizableNodeMock($nodeType)
{
$finalizableNode = $this->getMockBuilder($nodeType)
->disableOriginalConstructor()
->disableProxyingToOriginalMethods()
->setMethods([
'isFinal',
// disable name lookup from AST artifact
'getNamespaceName',
'getParentName',
'getName',
])
->getMock();
return $finalizableNode;
}
/**
* @param FinalImplementation $rule
* @param InvokedRecorder $violationExpectation
* @return InvocationMocker
*/
private function expectsRuleViolation(FinalImplementation $rule, InvokedRecorder $violationExpectation)
{
$report = $this->getMockBuilder(Report::class)->getMock();
$invokation = $report->expects($violationExpectation)->method('addRuleViolation');
$rule->setReport($report);
return $invokation;
}
}
@@ -10,29 +10,6 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://pmd.sf.net/ruleset/1.0.0 http://pmd.sf.net/ruleset_xml_schema.xsd"
xsi:noNamespaceSchemaLocation="http://pmd.sf.net/ruleset_xml_schema.xsd">
<rule name="FinalImplementation"
class="Magento\CodeMessDetector\Rule\Design\FinalImplementation"
message= "The {0} {1} declared as final.">
<description>
<![CDATA[
Final keyword is prohibited in Magento as this decreases extensibility and customizability.
Final classes and method are not compatible with plugins and proxies.
]]>
</description>
<priority>1</priority>
<properties />
<example>
<![CDATA[
final class Foo
{
public function bar() {}
}
class Baz {
final public function bad() {}
}
]]>
</example>
</rule>
<rule name="AllPurposeAction"
class="Magento\CodeMessDetector\Rule\Design\AllPurposeAction"
message= "The class {0} does not restrict processed HTTP methods by implementing a Http*Method name*ActionInterface">
@@ -1,35 +0,0 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Magento\Sniffs\Arrays;
use PHP_CodeSniffer\Files\File;
use PHP_CodeSniffer\Sniffs\Sniff;
/**
* Validate short array syntax is used.
*/
class ShortArraySyntaxSniff implements Sniff
{
/**
* @inheritdoc
*/
public function register()
{
return [T_ARRAY];
}
/**
* @inheritdoc
*/
public function process(File $sourceFile, $stackPtr)
{
$sourceFile->addError(
'Short array syntax must be used; expected "[]" but found "array()"',
$stackPtr,
'ShortArraySyntax'
);
}
}
@@ -1,47 +0,0 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Magento\Sniffs\EchoTags;
use PHP_CodeSniffer\Sniffs\Sniff;
use PHP_CodeSniffer\Files\File;
use PHP_CodeSniffer\Util\Tokens;
/**
* Validate short echo syntax is used.
*/
class ShortEchoSyntaxSniff implements Sniff
{
/**
* @inheritdoc
*/
public function register()
{
return [T_OPEN_TAG];
}
/**
* @inheritdoc
*/
public function process(File $phpcsFile, $stackPtr)
{
$tokens = $phpcsFile->getTokens();
$openTag = $tokens[$stackPtr];
// HHVM Will classify <?= as a T_OPEN_TAG
if ($openTag['content'] === '<?=') {
return;
}
$nextToken = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true);
if ($tokens[$nextToken]['code'] == T_ECHO) {
$phpcsFile->addError(
'Short echo tag syntax must be used; expected "<?=" but found "<?php echo"',
$stackPtr,
'ShortEchoTag'
);
}
}
}
@@ -1,36 +0,0 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Magento\Sniffs\Files;
use PHP_CodeSniffer\Standards\Generic\Sniffs\Files\LineLengthSniff as FilesLineLengthSniff;
/**
* Line length sniff which ignores long lines in case they contain strings intended for translation.
*/
class LineLengthSniff extends FilesLineLengthSniff
{
/**
* Having previous line content allows to ignore long lines in case of multi-line declaration.
*
* @var string
*/
protected $previousLineContent = '';
/**
* @inheritdoc
*/
protected function checkLineLength($phpcsFile, $stackPtr, $lineContent)
{
$previousLineRegexp = '~__\($|\bPhrase\($~';
$currentLineRegexp = '~__\(.+\)|\bPhrase\(.+\)~';
$currentLineMatch = preg_match($currentLineRegexp, $lineContent) !== 0;
$previousLineMatch = preg_match($previousLineRegexp, $this->previousLineContent) !== 0;
$this->previousLineContent = $lineContent;
if (! $currentLineMatch && !$previousLineMatch) {
parent::checkLineLength($phpcsFile, $stackPtr, $lineContent);
}
}
}
@@ -1,31 +0,0 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Magento\Sniffs\Functions;
/**
* Sniff prohibiting usage of output buffering functions.
*/
class OutputBufferingSniff extends \PHP_CodeSniffer\Standards\Generic\Sniffs\PHP\ForbiddenFunctionsSniff
{
public $forbiddenFunctions = ['ob_start' => null];
/**
* @inheritdoc
*/
protected function addError($phpcsFile, $stackPtr, $function, $pattern = null)
{
$data = [$function];
$error = 'The usage of %s() is forbidden';
$type = 'Found';
if ($this->error === true) {
$phpcsFile->addError($error, $stackPtr, $type, $data);
} else {
$phpcsFile->addWarning($error, $stackPtr, $type, $data);
}
}
}
@@ -1,77 +0,0 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Magento\Sniffs\LanguageConstructs;
use PHP_CodeSniffer\Sniffs\Sniff;
use PHP_CodeSniffer\Files\File;
/**
* Detects possible usage of discouraged language constructs. Is not applicable to *.phtml files.
*
* Examples:
* echo 'echo text';
* print('print text');
* $string = `back quotes`;
*/
class LanguageConstructsSniff implements Sniff
{
/**
* String representation of error.
*
* @var string
*/
protected $errorMessage = 'Use of %s language construct is discouraged.';
/**
* String representation of backtick error.
*
* @var string
*/
// @codingStandardsIgnoreLine
protected $errorMessageBacktick = 'Incorrect usage of back quote string constant. Back quotes should be always inside strings.';
/**
* Backtick violation code.
*
* @var string
*/
protected $backtickCode = 'WrongBackQuotesUsage';
/**
* Direct output code.
*
* @var string
*/
protected $directOutput = 'DirectOutput';
/**
* @inheritdoc
*/
public function register()
{
return [
T_ECHO,
T_PRINT,
T_BACKTICK,
];
}
/**
* @inheritdoc
*/
public function process(File $phpcsFile, $stackPtr)
{
$tokens = $phpcsFile->getTokens();
if ($tokens[$stackPtr]['code'] === T_BACKTICK) {
if ($phpcsFile->findNext(T_BACKTICK, $stackPtr + 1)) {
return;
}
$phpcsFile->addError($this->errorMessageBacktick, $stackPtr, $this->backtickCode);
return;
}
$phpcsFile->addError($this->errorMessage, $stackPtr, $this->directOutput, [$tokens[$stackPtr]['content']]);
}
}
@@ -1,75 +0,0 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Magento\Sniffs\LiteralNamespaces;
use PHP_CodeSniffer\Sniffs\Sniff;
use PHP_CodeSniffer\Files\File;
/**
* Custom phpcs sniff to detect usages of literal class and interface names.
*/
class LiteralNamespacesSniff implements Sniff
{
/**
* @var string
*/
private $literalNamespacePattern = '/^[\\\]{0,2}[A-Z][A-Za-z]+([\\\]{1,2}[A-Z][A-Za-z]+){2,}(?!\\\+)$/';
/**
* @var array
*/
private $classNames = [];
/**
* @inheritdoc
*/
public function register()
{
return [
T_CONSTANT_ENCAPSED_STRING,
T_DOUBLE_QUOTED_STRING,
];
}
/**
* @inheritdoc
*/
public function process(File $sourceFile, $stackPtr)
{
$tokens = $sourceFile->getTokens();
if ($sourceFile->findPrevious(T_STRING_CONCAT, $stackPtr, $stackPtr - 3) ||
$sourceFile->findNext(T_STRING_CONCAT, $stackPtr, $stackPtr + 3)
) {
return;
}
$content = trim($tokens[$stackPtr]['content'], "\"'");
// replace double slashes from class name for avoiding problems with class autoload
if (strpos($content, '\\') !== false) {
$content = preg_replace('|\\\{2,}|', '\\', $content);
}
if (preg_match($this->literalNamespacePattern, $content) === 1 && $this->classExists($content)) {
$sourceFile->addError(
"Use ::class notation instead.",
$stackPtr,
'LiteralClassUsage'
);
}
}
/**
* @param string $className
* @return bool
*/
private function classExists($className)
{
if (!isset($this->classNames[$className])) {
$this->classNames[$className] = class_exists($className) || interface_exists($className);
}
return $this->classNames[$className];
}
}
@@ -1,40 +0,0 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Magento\Sniffs\MicroOptimizations;
use PHP_CodeSniffer\Sniffs\Sniff;
use PHP_CodeSniffer\Files\File;
class IsNullSniff implements Sniff
{
/**
* @var string
*/
protected $blacklist = 'is_null';
/**
* @inheritdoc
*/
public function register()
{
return [T_STRING];
}
/**
* @inheritdoc
*/
public function process(File $sourceFile, $stackPtr)
{
$tokens = $sourceFile->getTokens();
if ($tokens[$stackPtr]['content'] === $this->blacklist) {
$sourceFile->addError(
"is_null must be avoided. Use strict comparison instead.",
$stackPtr,
'IsNullUsage'
);
}
}
}
@@ -1,49 +0,0 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Magento\Sniffs\NamingConventions;
use PHP_CodeSniffer\Sniffs\Sniff;
use PHP_CodeSniffer\Files\File;
/**
* Validates that interface name ends with "Interface" suffix.
*/
class InterfaceNameSniff implements Sniff
{
const INTERFACE_SUFFIX = 'Interface';
/**
* @inheritdoc
*/
public function register()
{
return [T_INTERFACE];
}
/**
* @inheritdoc
*/
public function process(File $sourceFile, $stackPtr)
{
$tokens = $sourceFile->getTokens();
$declarationLine = $tokens[$stackPtr]['line'];
$suffixLength = strlen(self::INTERFACE_SUFFIX);
// Find first T_STRING after 'interface' keyword in the line and verify it
while ($tokens[$stackPtr]['line'] == $declarationLine) {
if ($tokens[$stackPtr]['type'] == 'T_STRING') {
if (substr($tokens[$stackPtr]['content'], 0 - $suffixLength) != self::INTERFACE_SUFFIX) {
$sourceFile->addError(
'Interface should have name that ends with "Interface" suffix.',
$stackPtr,
'WrongInterfaceName'
);
}
break;
}
$stackPtr++;
}
}
}
@@ -1,116 +0,0 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Magento\Sniffs\NamingConventions;
use PHP_CodeSniffer\Sniffs\Sniff;
use PHP_CodeSniffer\Files\File;
/**
* Validates that class name is not reserved word.
*/
class ReservedWordsSniff implements Sniff
{
/**
* The following words cannot be used to name a class, interface or trait,
* and they are also prohibited from being used in namespaces.
*
* @link http://php.net/manual/en/reserved.other-reserved-words.php
*
* @var string[]
*/
protected $reservedWords = [
'int' => '7',
'float' => '7',
'bool' => '7',
'string' => '7',
'true' => '7',
'false' => '7',
'null' => '7',
'void' => '7.1',
'iterable' => '7.1',
'resource' => '7',
'object' => '7',
'mixed' => '7',
'numeric' => '7',
];
/**
* @inheritdoc
*/
public function register()
{
return [T_CLASS, T_INTERFACE, T_TRAIT, T_NAMESPACE];
}
/**
* Check all namespace parts
*
* @param File $sourceFile
* @param int $stackPtr
* @return void
*/
protected function validateNamespace(File $sourceFile, $stackPtr)
{
$stackPtr += 2;
$tokens = $sourceFile->getTokens();
while ($stackPtr < $sourceFile->numTokens && $tokens[$stackPtr]['code'] !== T_SEMICOLON) {
if ($tokens[$stackPtr]['code'] === T_WHITESPACE || $tokens[$stackPtr]['code'] === T_NS_SEPARATOR) {
$stackPtr++; //skip "namespace" and whitespace
continue;
}
$namespacePart = $tokens[$stackPtr]['content'];
if (isset($this->reservedWords[strtolower($namespacePart)])) {
$sourceFile->addError(
'Cannot use "%s" in namespace as it is reserved since PHP %s',
$stackPtr,
'Namespace',
[$namespacePart, $this->reservedWords[strtolower($namespacePart)]]
);
}
$stackPtr++;
}
}
/**
* Check class name not having reserved words
*
* @param File $sourceFile
* @param int $stackPtr
* @return void
*/
protected function validateClass(File $sourceFile, $stackPtr)
{
$tokens = $sourceFile->getTokens();
$stackPtr += 2; //skip "class" and whitespace
$className = strtolower($tokens[$stackPtr]['content']);
if (isset($this->reservedWords[$className])) {
$sourceFile->addError(
'Cannot use "%s" as class name as it is reserved since PHP %s',
$stackPtr,
'Class',
[$className, $this->reservedWords[$className]]
);
}
}
/**
* @inheritdoc
*/
public function process(File $sourceFile, $stackPtr)
{
$tokens = $sourceFile->getTokens();
switch ($tokens[$stackPtr]['code']) {
case T_CLASS:
case T_INTERFACE:
case T_TRAIT:
$this->validateClass($sourceFile, $stackPtr);
break;
case T_NAMESPACE:
$this->validateNamespace($sourceFile, $stackPtr);
break;
}
}
}
@@ -1,87 +0,0 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Magento\Sniffs\Security;
use PHP_CodeSniffer\Sniffs\Sniff;
use PHP_CodeSniffer\Files\File;
use PHP_CodeSniffer\Util\Tokens;
/**
* Detects executable regular expressions.
*
* Example: echo preg_replace('|^(.*)$|ei', '"\1"', 'get_input');
*/
class ExecutableRegExSniff implements Sniff
{
/**
* String representation of error.
*
* @var string
*/
// @codingStandardsIgnoreLine
protected $errorMessage = "Possible executable regular expression in %s. Make sure that the pattern doesn't contain 'e' modifier";
/**
* Error violation code.
*
* @var string
*/
protected $errorCode = 'PossibleExecutableRegEx';
/**
* Observed function.
*
* @var array
*/
protected $function = 'preg_replace';
/**
* List of ignored tokens.
*
* @var array
*/
protected $ignoreTokens = [
T_DOUBLE_COLON,
T_OBJECT_OPERATOR,
T_FUNCTION,
T_CONST,
T_CLASS,
];
/**
* @inheritdoc
*/
public function register()
{
return [T_STRING];
}
/**
* @inheritdoc
*/
public function process(File $phpcsFile, $stackPtr)
{
$tokens = $phpcsFile->getTokens();
if ($tokens[$stackPtr]['content'] !== $this->function) {
return;
}
$prevToken = $phpcsFile->findPrevious(T_WHITESPACE, $stackPtr - 1, null, true);
if (in_array($tokens[$prevToken]['code'], $this->ignoreTokens)) {
return;
}
$nextToken = $phpcsFile->findNext([T_WHITESPACE, T_OPEN_PARENTHESIS], $stackPtr + 1, null, true);
if (in_array($tokens[$nextToken]['code'], Tokens::$stringTokens)
&& preg_match('/[#\/|~\}\)][imsxADSUXJu]*e[imsxADSUXJu]*.$/', $tokens[$nextToken]['content'])
) {
$phpcsFile->addError(
$this->errorMessage,
$stackPtr,
$this->errorCode,
[$tokens[$stackPtr]['content']]
);
}
}
}
@@ -1,168 +0,0 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Magento\Sniffs\Strings;
use PHP_CodeSniffer\Sniffs\Sniff;
use PHP_CodeSniffer\Files\File;
/**
* Detects misusing of IS_IDENTICAL operators when `strpos` and `stripos` functions are used in a condition.
*
* Examples:
* if (!strpos($haystack, $needle)) {}
* if (stripos($haystack, $needle) == false) {}
*/
class StringPositionSniff implements Sniff
{
/**
* String representation of error.
*
* @var string
*/
protected $errorMessage = 'Identical operator === is not used for testing the return value of %s function';
/**
* Error violation code.
*
* @var string
*/
protected $errorCode = 'ImproperValueTesting';
/**
* Searched functions.
*
* @var array
*/
protected $functions = [
'strpos',
'stripos',
];
/**
* All tokens from current file.
*
* @var array
*/
protected $tokens = [];
/**
* PHP_CodeSniffer file.
*
* @var File
*/
protected $file;
/**
* Left limit for search of identical operators.
*
* @var int
*/
protected $leftLimit;
/**
* Right limit for search of identical operators.
*
* @var int
*/
protected $rightLimit;
/**
* List of tokens which declares left bound of current scope.
*
* @var array
*/
protected $leftRangeTokens = [
T_IS_IDENTICAL,
T_IS_NOT_IDENTICAL,
T_OPEN_PARENTHESIS,
T_BOOLEAN_AND,
T_BOOLEAN_OR,
];
/**
* List of tokens which declares right bound of current scope.
*
* @var array
*/
protected $rightRangeTokens = [
T_IS_IDENTICAL,
T_IS_NOT_IDENTICAL,
T_CLOSE_PARENTHESIS,
T_BOOLEAN_AND,
T_BOOLEAN_OR,
];
/**
* List of tokens which declares identical operators.
*
* @var array
*/
protected $identical = [
T_IS_IDENTICAL,
T_IS_NOT_IDENTICAL,
];
/**
* @inheritdoc
*/
public function register()
{
return [T_IF, T_ELSEIF];
}
/**
* @inheritdoc
*/
public function process(File $phpcsFile, $stackPtr)
{
$this->tokens = $phpcsFile->getTokens();
$this->file = $phpcsFile;
$this->leftLimit = $open = $this->tokens[$stackPtr]['parenthesis_opener'];
$this->rightLimit = $close = $this->tokens[$stackPtr]['parenthesis_closer'];
for ($i = ($open + 1); $i < $close; $i++) {
if (($this->tokens[$i]['code'] === T_STRING && in_array($this->tokens[$i]['content'], $this->functions))
&& (!$this->findIdentical($i - 1, $this->findFunctionParenthesisCloser($i) + 1))
) {
$foundFunctionName = $this->tokens[$i]['content'];
$phpcsFile->addError($this->errorMessage, $i, $this->errorCode, [$foundFunctionName]);
}
}
}
/**
* Recursively finds identical operators in current scope.
*
* @param int $leftCurrentPosition
* @param int $rightCurrentPosition
* @return bool
*/
protected function findIdentical($leftCurrentPosition, $rightCurrentPosition)
{
$leftBound = $this->file->findPrevious($this->leftRangeTokens, $leftCurrentPosition, $this->leftLimit - 1);
$rightBound = $this->file->findNext($this->rightRangeTokens, $rightCurrentPosition, $this->rightLimit + 1);
$leftToken = $this->tokens[$leftBound];
$rightToken = $this->tokens[$rightBound];
if ($leftToken['code'] === T_OPEN_PARENTHESIS && $rightToken['code'] === T_CLOSE_PARENTHESIS) {
return $this->findIdentical($leftBound - 1, $rightBound + 1);
} else {
return (
in_array($leftToken['code'], $this->identical) || in_array($rightToken['code'], $this->identical)
) ?: false;
}
}
/**
* Finds the position of close parenthesis of detected function.
*
* @param int $currentPosition
* @return mixed
*/
protected function findFunctionParenthesisCloser($currentPosition)
{
$nextOpenParenthesis = $this->file->findNext(T_OPEN_PARENTHESIS, $currentPosition, $this->rightLimit);
return $nextOpenParenthesis ? $this->tokens[$nextOpenParenthesis]['parenthesis_closer'] : false;
}
}
@@ -1,99 +0,0 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Magento\Sniffs\Translation;
use PHP_CodeSniffer\Files\File;
use PHP_CodeSniffer\Sniffs\Sniff;
/**
* Make sure that constants are not used as the first argument of translation function.
*/
class ConstantUsageSniff implements Sniff
{
/**
* Having previous line content allows to process multi-line declaration.
*
* @var string
*/
protected $previousLineContent = '';
/**
* @inheritdoc
*/
public function register()
{
return [T_OPEN_TAG];
}
/**
* Copied from \Generic_Sniffs_Files_LineLengthSniff, minor changes made
*
* {@inheritdoc}
*
* @param \PHP_CodeSniffer\Files\File $phpcsFile
* @param int $stackPtr
* @return void|int
*/
public function process(File $phpcsFile, $stackPtr)
{
$tokens = $phpcsFile->getTokens();
// Make sure this is the first open tag
$previousOpenTag = $phpcsFile->findPrevious(T_OPEN_TAG, ($stackPtr - 1));
if ($previousOpenTag !== false) {
return;
}
$tokenCount = 0;
$currentLineContent = '';
$currentLine = 1;
for (; $tokenCount < $phpcsFile->numTokens; $tokenCount++) {
if ($tokens[$tokenCount]['line'] === $currentLine) {
$currentLineContent .= $tokens[$tokenCount]['content'];
} else {
$this->checkIfFirstArgumentConstant($phpcsFile, ($tokenCount - 1), $currentLineContent);
$currentLineContent = $tokens[$tokenCount]['content'];
$currentLine++;
}
}
$this->checkIfFirstArgumentConstant($phpcsFile, ($tokenCount - 1), $currentLineContent);
}
/**
* Checks if first argument of \Magento\Framework\Phrase or translation function is a constant
*
* @param File $phpcsFile
* @param int $stackPtr
* @param string $lineContent
* @return void
*/
private function checkIfFirstArgumentConstant(
File $phpcsFile,
$stackPtr,
$lineContent
) {
$previousLineRegexp = '/(__|Phrase)\($/im';
$currentLineRegexp = '/(__|Phrase)\(.+\)/';
$currentLineMatch = preg_match($currentLineRegexp, $lineContent) !== 0;
$previousLineMatch = preg_match($previousLineRegexp, $this->previousLineContent) !== 0;
$this->previousLineContent = $lineContent;
$error = 'Constants are not allowed as the first argument of translation function, use string literal instead';
$constantRegexp = '[^\$\'"]+::[A-Z_0-9]+.*';
if ($currentLineMatch) {
$variableRegexp = "/(__|Phrase)\({$constantRegexp}\)/";
if (preg_match($variableRegexp, $lineContent) !== 0) {
$phpcsFile->addError($error, $stackPtr, 'VariableTranslation');
}
} elseif ($previousLineMatch) {
$variableRegexp = "/^{$constantRegexp}/";
if (preg_match($variableRegexp, $lineContent) !== 0) {
$phpcsFile->addError($error, $stackPtr, 'VariableTranslation');
}
}
}
}
@@ -1,40 +0,0 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Magento\Sniffs\Variables;
use PHP_CodeSniffer\Sniffs\Sniff;
use PHP_CodeSniffer\Files\File;
/**
* Sniff prohibiting usage of global variables.
*/
class GlobalVariablesSniff implements Sniff
{
/**
* @inheritdoc
*/
public function register()
{
return [T_VARIABLE];
}
/**
* @inheritdoc
*/
public function process(File $phpcsFile, $stackPtr)
{
$tokens = $phpcsFile->getTokens();
if (preg_match('/^\$[_A-Z0-9]+$/', $tokens[$stackPtr]['content'])) {
$phpcsFile->addError(
'Usage of global variables is not allowed: ' . $tokens[$stackPtr]['content'],
$stackPtr,
'ERROR'
);
return;
}
}
}
@@ -1,68 +0,0 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Magento\Sniffs\Whitespace;
use PHP_CodeSniffer\Sniffs\Sniff;
use PHP_CodeSniffer\Files\File;
/**
* Class EmptyLineMissedSniff
*/
class EmptyLineMissedSniff implements Sniff
{
/**
* @inheritdoc
*/
public function register()
{
return [T_DOC_COMMENT];
}
/**
* @inheritdoc
*/
public function process(File $phpcsFile, $stackPtr)
{
$tokens = $phpcsFile->getTokens();
if ($this->doCheck($phpcsFile, $stackPtr, $tokens)) {
$previous = $phpcsFile->findPrevious(T_WHITESPACE, $stackPtr - 1, null, true);
if ($tokens[$stackPtr]['line'] - $tokens[$previous]['line'] < 2) {
$error = 'Empty line missed';
$phpcsFile->addError($error, $stackPtr, '', null);
}
}
}
/**
* Execute empty line missed check.
*
* @param File $phpcsFile
* @param int $stackPtr
* @param array $tokens
* @return bool
*/
private function doCheck(File $phpcsFile, $stackPtr, $tokens)
{
$result = false;
if ($phpcsFile->hasCondition($stackPtr, T_CLASS) || $phpcsFile->hasCondition($stackPtr, T_INTERFACE)) {
$result = true;
}
if ($phpcsFile->hasCondition($stackPtr, T_FUNCTION)) {
$result = false;
}
$previous = $phpcsFile->findPrevious(T_WHITESPACE, $stackPtr - 1, null, true);
if ($tokens[$previous]['type'] === 'T_OPEN_CURLY_BRACKET') {
$result = false;
}
if (strpos($tokens[$stackPtr]['content'], '/**') === false) {
$result = false;
}
return $result;
}
}
@@ -1,49 +0,0 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Magento\Sniffs\Whitespace;
use PHP_CodeSniffer\Sniffs\Sniff;
use PHP_CodeSniffer\Files\File;
/**
* Class MultipleEmptyLinesSniff
*/
class MultipleEmptyLinesSniff implements Sniff
{
/**
* @inheritdoc
*/
public function register()
{
return [T_WHITESPACE];
}
/**
* @inheritdoc
*/
public function process(File $phpcsFile, $stackPtr)
{
$tokens = $phpcsFile->getTokens();
if ($phpcsFile->hasCondition($stackPtr, T_FUNCTION)
|| $phpcsFile->hasCondition($stackPtr, T_CLASS)
|| $phpcsFile->hasCondition($stackPtr, T_INTERFACE)
) {
if ($tokens[($stackPtr - 1)]['line'] < $tokens[$stackPtr]['line']
&& $tokens[($stackPtr - 2)]['line'] === $tokens[($stackPtr - 1)]['line']
) {
// This is an empty line and the line before this one is not
// empty, so this could be the start of a multiple empty line block
$next = $phpcsFile->findNext(T_WHITESPACE, $stackPtr, null, true);
$lines = $tokens[$next]['line'] - $tokens[$stackPtr]['line'];
if ($lines > 1) {
$error = 'Code must not contain multiple empty lines in a row; found %s empty lines';
$data = [$lines];
$phpcsFile->addError($error, $stackPtr, 'MultipleEmptyLines', $data);
}
}
}
}
}
@@ -54,6 +54,7 @@ class CodeSniffer implements ToolInterface, ExtensionInterface
public function __construct($rulesetDir, $reportFile, Wrapper $wrapper)
{
$this->rulesetDir = $rulesetDir;
// phpcs:ignore Magento2.Functions.DiscouragedFunction
if (!file_exists($rulesetDir) && file_exists($fullPath = realpath(__DIR__ . '/../../../../' . $rulesetDir))) {
$this->rulesetDir = $fullPath;
}
@@ -62,7 +63,7 @@ class CodeSniffer implements ToolInterface, ExtensionInterface
}
/**
* {@inheritdoc}
* @inheritdoc
*/
public function setExtensions(array $extensions)
{
@@ -80,7 +81,7 @@ class CodeSniffer implements ToolInterface, ExtensionInterface
}
/**
* {@inheritdoc}
* @inheritdoc
*/
public function run(array $whiteList)
{
@@ -97,10 +98,10 @@ class CodeSniffer implements ToolInterface, ExtensionInterface
$settings['files'] = $whiteList;
$settings['standards'] = [$this->rulesetDir];
$settings['extensions'] = $this->extensions;
$settings['warningSeverity'] = 0;
$settings['reports']['full'] = $this->reportFile;
$this->wrapper->setSettings($settings);
// phpcs:ignore Magento2.Functions.DiscouragedFunction
ob_start();
$result = $this->wrapper->runPHPCS();
ob_end_clean();
@@ -1,441 +0,0 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Magento\TestFramework\Utility;
/**
* A helper find not escaped output in phtml templates
*/
class XssOutputValidator
{
const ESCAPE_NOT_VERIFIED_PATTERN = '/\* @escapeNotVerified \*/';
const ESCAPED_PATTERN = '/\* @noEscape \*/';
/**
* Store origin for replacements
*
* @var array
*/
private $origins = [];
/**
* Store replacements
*
* @var array
*/
private $replacements = [];
/**
* Array of escape functions
*
* @var string[]
*/
private $escapeFunctions = ['escapeHtml', 'escapeHtmlAttr', 'escapeUrl', 'escapeJs', 'escapeCss'];
/**
*
* @param string $file
* @return string
*/
public function getLinesWithXssSensitiveOutput($file)
{
$fileContent = file_get_contents($file);
$xssUnsafeBlocks = $this->getXssUnsafeBlocks($fileContent);
$lines = [];
foreach ($xssUnsafeBlocks as $block) {
$lines = array_merge($lines, $this->findBlockLineNumbers($block, $fileContent));
}
if (count($lines)) {
$lines = array_unique($lines);
sort($lines);
return implode(',', $lines);
}
return '';
}
/**
* Find block line numbers
*
* @param string $block
* @param string $content
* @return array
*/
private function findBlockLineNumbers($block, $content)
{
$results = [];
$pos = strpos($content, $block, 0);
while ($pos !== false) {
$contentBeforeString = substr($content, 0, $pos);
if ($this->isNotEscapeMarkedBlock($contentBeforeString)
&& $this->isNotInCommentBlock($contentBeforeString)
) {
$results[] = count(explode(PHP_EOL, $contentBeforeString));
}
$pos = strpos($content, $block, $pos + 1);
}
return $results;
}
/**
* Get XSS unsafe output blocks
*
* @param string $fileContent
* @return array
*/
public function getXssUnsafeBlocks($fileContent)
{
$results = [];
$fileContent = $this->replacePhpQuoteWithPlaceholders($fileContent);
$fileContent = $this->replacePhpCommentsWithPlaceholders($fileContent);
$this->addOriginReplacement('\'\'', "'-*=single=*-'");
$this->addOriginReplacement('""', '"-*=double=*-"');
if (preg_match_all('/<[?](php|=)(.*?)[?]>/sm', $fileContent, $phpBlockMatches)) {
foreach ($phpBlockMatches[2] as $index => $phpBlock) {
$phpCommands = explode(';', $phpBlock);
if ($phpBlockMatches[1][$index] == 'php') {
$echoCommands = preg_grep('#( |^|/\*.*?\*/)echo[\s(]+.*#sm', $phpCommands);
} else {
$echoCommands[] = $phpBlockMatches[0][$index];
}
$results = array_merge(
$results,
$this->getEchoUnsafeCommands($echoCommands)
);
}
}
$this->clearOriginReplacements();
$results = array_unique($results);
return $results;
}
/**
* @param array $echoCommands
* @return array
*/
private function getEchoUnsafeCommands(array $echoCommands)
{
$results = [];
foreach ($echoCommands as $echoCommand) {
if ($this->isNotEscapeMarkedCommand($echoCommand)) {
$echoCommand = preg_replace('/^(.*?)echo/sim', 'echo', $echoCommand);
$preparedEchoCommand = $this->prepareEchoCommand($echoCommand);
$isEscapeFunctionArgument = preg_match(
'/->(' . implode('|', $this->escapeFunctions) . ')\(.*?\)$/sim',
$preparedEchoCommand
);
$xssUnsafeCommands = array_filter(
$isEscapeFunctionArgument ? [$preparedEchoCommand] : explode('.', $preparedEchoCommand),
[$this, 'isXssUnsafeCommand']
);
if (count($xssUnsafeCommands)) {
$results[] = str_replace(
$this->getReplacements(),
$this->getOrigins(),
$echoCommand
);
}
}
}
return $results;
}
/**
* @param string $command
* @return string
*/
private function prepareEchoCommand($command)
{
$command = preg_replace('/<[?]=(.*?)[?]>/sim', '\1', $command);
return trim(ltrim(explode(';', $command)[0], 'echo'));
}
/**
* @param string $contentBeforeString
* @return bool
*/
private function isNotEscapeMarkedBlock($contentBeforeString)
{
return !preg_match(
'%(' . self::ESCAPE_NOT_VERIFIED_PATTERN . '|' . self::ESCAPED_PATTERN . ')$%sim',
trim($contentBeforeString)
);
}
/**
* @param string $contentBeforeString
* @return bool
*/
private function isNotInCommentBlock($contentBeforeString)
{
$contentBeforeString = explode('<?php', $contentBeforeString);
$contentBeforeString = preg_replace(
'%/\*.*?\*/%si',
'',
end($contentBeforeString)
);
return (strpos($contentBeforeString, '/*') === false);
}
/**
* @param string $command
* @return bool
*/
private function isNotEscapeMarkedCommand($command)
{
return !preg_match(
'%' . self::ESCAPE_NOT_VERIFIED_PATTERN . '|' . self::ESCAPED_PATTERN . '%sim',
$command
);
}
/**
* Check if command is xss unsafe
*
* @param string $command
* @return bool
*/
public function isXssUnsafeCommand($command)
{
$command = trim($command);
switch (true) {
case preg_match(
'/->(' . implode('|', $this->escapeFunctions) . '|.*html.*)\(/simU',
$this->getLastMethod($command)
):
return false;
case preg_match('/^\((int|bool|float)\)/sim', $command):
return false;
case preg_match('/^count\(/sim', $command):
return false;
case preg_match("/^'.*'$/sim", $command):
return false;
case preg_match('/^".*?"$/sim', $command, $matches):
return $this->isContainPhpVariables($this->getOrigin($matches[0]));
default:
return true;
}
}
/**
* @param string $command
* @return string
*/
private function getLastMethod($command)
{
if (preg_match_all(
'/->.*?\(.*?\)/sim',
$this->clearMethodBracketContent($command),
$matches
)) {
$command = end($matches[0]);
$command = substr($command, 0, strpos($command, '(') + 1);
}
return $command;
}
/**
* @param string $command
* @return string
*/
private function clearMethodBracketContent($command)
{
$bracketInterval = [];
$bracketOpenPos = [];
$command = str_split($command);
foreach ($command as $index => $character) {
if ($character == '(') {
array_push($bracketOpenPos, $index);
}
if (count($bracketOpenPos)) {
if ($character == ')') {
$lastOpenPos = array_pop($bracketOpenPos);
if (count($bracketOpenPos) == 0) {
$bracketInterval[] = [$lastOpenPos, $index];
}
}
}
}
foreach ($bracketInterval as $interval) {
for ($i = $interval[0] + 1; $i < $interval[1]; $i++) {
unset($command[$i]);
}
}
$command = implode('', $command);
return $command;
}
/**
* @param string $content
* @return int
*/
private function isContainPhpVariables($content)
{
return preg_match('/[^\\\\]\$[a-z_\x7f-\xff]/sim', $content);
}
/**
* @param string $fileContent
* @return string
*/
private function replacePhpQuoteWithPlaceholders($fileContent)
{
$origins = [];
$replacements = [];
if (preg_match_all('/<[?](php|=)(.*?)[?]>/sm', $fileContent, $phpBlockMatches)) {
foreach ($phpBlockMatches[2] as $phpBlock) {
$phpBlockQuoteReplaced = preg_replace(
['/([^\\\\])\'\'/si', '/([^\\\\])""/si'],
["\1'-*=single=*-'", '\1"-*=double=*-"'],
$phpBlock
);
$this->addQuoteOriginsReplacements(
$phpBlockQuoteReplaced,
[
'/([^\\\\])([\'])(.*?)([^\\\\])([\'])/sim'
]
);
$this->addQuoteOriginsReplacements(
$phpBlockQuoteReplaced,
[
'/([^\\\\])(["])(.*?)([^\\\\])(["])/sim',
]
);
$origins[] = $phpBlock;
$replacements[] = str_replace(
$this->getOrigins(),
$this->getReplacements(),
$phpBlockQuoteReplaced
);
}
}
return str_replace($origins, $replacements, $fileContent);
}
/**
* @param string $fileContent
* @return string
*/
private function replacePhpCommentsWithPlaceholders($fileContent)
{
$origins= [];
$replacements = [];
if (preg_match_all('%/\*.*?\*/%simu', $fileContent, $docCommentMatches, PREG_SET_ORDER)) {
foreach ($docCommentMatches as $docCommentMatch) {
if ($this->isNotEscapeMarkedCommand($docCommentMatch[0])
&& !$this->issetOrigin($docCommentMatch[0])) {
$origin = $docCommentMatch[0];
$replacement = '-*!' . count($this->getOrigins()) . '!*-';
$origins[] = $origin;
$replacements[] = $replacement;
$this->addOriginReplacement(
$origin,
$replacement
);
}
}
}
return str_replace($origins, $replacements, $fileContent);
}
/**
* Add replacements for expressions in single and double quotes
*
* @param string $phpBlock
* @param array $patterns
* @return void
*/
private function addQuoteOriginsReplacements($phpBlock, array $patterns)
{
foreach ($patterns as $pattern) {
if (preg_match_all($pattern, $phpBlock, $quoteMatches, PREG_SET_ORDER)) {
foreach ($quoteMatches as $quoteMatch) {
$origin = $quoteMatch[2] . $quoteMatch[3] . $quoteMatch[4] . $quoteMatch[5];
if (!$this->issetOrigin($origin)) {
$this->addOriginReplacement(
$origin,
$quoteMatch[2] . '-*=' . count($this->getOrigins()) . '=*-' . $quoteMatch[5]
);
}
}
}
}
}
/**
* @param string $origin
* @param string $replacement
* @return void
*/
private function addOriginReplacement($origin, $replacement)
{
$this->origins[$replacement] = $origin;
$this->replacements[$replacement] = $replacement;
}
/**
* Clear origins and replacements
*
* @return void
*/
private function clearOriginReplacements()
{
$this->origins = [];
$this->replacements = [];
}
/**
* @return array
*/
private function getOrigins()
{
return $this->origins;
}
/**
* @param string $key
* @return string|null
*/
private function getOrigin($key)
{
return array_key_exists($key, $this->origins) ? $this->origins[$key] : null;
}
/**
* @param string $origin
* @return bool
*/
private function issetOrigin($origin)
{
return in_array($origin, $this->origins);
}
/**
* @return array
*/
private function getReplacements()
{
return $this->replacements;
}
}
+3 -74
View File
@@ -7,83 +7,12 @@
-->
<ruleset name="Magento">
<description>Custom Magento coding standard.</description>
<rule ref="./../../../../../vendor/magento/magento-coding-standard/Magento2"/>
<rule ref="PSR2"/>
<rule ref="PSR2.Files.ClosingTag">
<exclude-pattern>*.phtml</exclude-pattern>
</rule>
<rule ref="Magento.Files.LineLength">
<properties>
<property name="lineLimit" value="120"/>
<property name="absoluteLineLimit" value="120"/>
</properties>
</rule>
<rule ref="Magento.LanguageConstructs.LanguageConstructs">
<include-pattern>*/app/code/*\.(?!phtml)</include-pattern>
</rule>
<rule ref="Magento.LiteralNamespaces.LiteralNamespaces">
<exclude-pattern>*/_files/*</exclude-pattern>
</rule>
<rule ref="Magento.Annotation.MethodArguments">
<!-- ToDo: Improve Annotation sniffs in magento/magento-coding-standard and remove from here. -->
<rule ref="Magento.Annotation">
<exclude-pattern>*/_files/*</exclude-pattern>
<exclude-pattern>*/Test/*</exclude-pattern>
<exclude-pattern>*Test.php</exclude-pattern>
<exclude-pattern>*/Magento/Inventory*/*</exclude-pattern>
</rule>
<rule ref="Magento.Annotation.MethodAnnotationStructure">
<include-pattern>*\.(php)</include-pattern>
<exclude-pattern>*/Test/*</exclude-pattern>
<exclude-pattern>*Test.php</exclude-pattern>
<exclude-pattern>*/_files/*</exclude-pattern>
<exclude-pattern>*/Magento/Inventory*/*</exclude-pattern>
</rule>
<rule ref="Magento.Annotation.ClassAnnotationStructure">
<include-pattern>*\.(php)</include-pattern>
<exclude-pattern>*/Test/*</exclude-pattern>
<exclude-pattern>*Test.php</exclude-pattern>
<exclude-pattern>*/_files/*</exclude-pattern>
<exclude-pattern>*/Magento/Inventory*/*</exclude-pattern>
</rule>
<rule ref="Magento.Functions.OutputBuffering">
<include-pattern>*/(app/code|vendor|setup/src|lib/internal/Magento)/*</include-pattern>
<exclude-pattern>*/lib/internal/Magento/Framework/Image/Adapter/Gd2.php</exclude-pattern>
<exclude-pattern>*/lib/internal/Magento/Framework/View/Result/Page.php</exclude-pattern>
<exclude-pattern>*/lib/internal/Magento/Framework/View/TemplateEngine/Php.php</exclude-pattern>
<exclude-pattern>*/Test/Unit/*</exclude-pattern>
</rule>
<rule ref="Magento.Variables.GlobalVariables">
<include-pattern>*/(app/code|vendor|setup/src)/*</include-pattern>
<exclude-pattern>*/setup/src/Magento/Setup/Controller/WebConfiguration.php</exclude-pattern>
<exclude-pattern>*/setup/src/Magento/Setup/Mvc/Bootstrap/InitParamListener.php</exclude-pattern>
<exclude-pattern>*/app/code/Magento/Eav/Model/Attribute/Data/File.php</exclude-pattern>
<exclude-pattern>*/app/code/Magento/Config/Model/Config/Reader/Source/Deployed/SettingChecker.php</exclude-pattern>
<exclude-pattern>*/app/code/Magento/Backend/App/Area/FrontNameResolver.php</exclude-pattern>
<exclude-pattern>*/app/code/Magento/Indexer/Console/Command/AbstractIndexerCommand.php</exclude-pattern>
<exclude-pattern>*/app/code/Magento/Catalog/Model/Product/Option/Type/File/ValidatorFile.php</exclude-pattern>
<exclude-pattern>*/app/code/Magento/Cron/Console/Command/CronCommand.php</exclude-pattern>
<exclude-pattern>*/app/code/Magento/ImportExport/Controller/Adminhtml/Import/Validate.php</exclude-pattern>
<exclude-pattern>*/app/code/Magento/OfflineShipping/Model/ResourceModel/Carrier/Tablerate.php</exclude-pattern>
<exclude-pattern>*/app/code/Magento/Store/Model/Store.php</exclude-pattern>
<exclude-pattern>*/app/code/Magento/Config/Model/Config/Processor/EnvironmentPlaceholder.php</exclude-pattern>
<exclude-pattern>*/app/code/Magento/Config/Model/Config/Backend/Email/Logo.php</exclude-pattern>
<exclude-pattern>*/app/code/Magento/Config/Model/Config/Backend/File/RequestData.php</exclude-pattern>
<exclude-pattern>*/app/code/Magento/Config/App/Config/Source/EnvironmentConfigSource.php</exclude-pattern>
<exclude-pattern>*/app/code/Magento/Theme/Controller/Adminhtml/Design/Config/FileUploader/Save.php</exclude-pattern>
<exclude-pattern>*/app/code/Magento/Customer/Model/Metadata/Form/File.php</exclude-pattern>
<exclude-pattern>*/app/code/Magento/Customer/Model/FileUploader.php</exclude-pattern>
<exclude-pattern>*/app/code/Magento/Customer/Controller/Adminhtml/File/Address/Upload.php</exclude-pattern>
<exclude-pattern>*/app/code/Magento/Customer/Controller/Adminhtml/File/Customer/Upload.php</exclude-pattern>
<exclude-pattern>*/Test/Unit/*</exclude-pattern>
</rule>
<rule ref="Generic.PHP.CharacterBeforePHPOpeningTag"/>
<rule ref="Generic.Functions.CallTimePassByReference"/>
<rule ref="Generic.PHP.DeprecatedFunctions"/>
<rule ref="Squiz.Commenting.DocCommentAlignment"/>
<rule ref="Squiz.Functions.GlobalFunction"/>
<rule ref="Squiz.Operators.ValidLogicalOperators"/>
<rule ref="Squiz.WhiteSpace.LogicalOperatorSpacing"/>
</ruleset>
@@ -1,82 +0,0 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Magento\Sniffs\EchoTags;
class ShortEchoSyntaxSniffTest extends \PHPUnit\Framework\TestCase
{
/**
* @var \PHP_CodeSniffer_File|\PHPUnit_Framework_MockObject_MockObject
*/
private $fileMock;
/**
* @var ShortEchoSyntaxSniff
*/
private $shortEchoUsageSniff;
protected function setUp()
{
$this->fileMock = $this->getMock(\PHP_CodeSniffer_File::class, [], [], '', false);
$this->shortEchoUsageSniff = new ShortEchoSyntaxSniff();
}
/**
* @param string $file
* @param int $incorrectUsages
* @dataProvider processDataProvider
*/
public function testEchoTagSniff($file, $stackPtr, $incorrectUsages)
{
$fileContent = file_get_contents(__DIR__ . '/_files/' . $file);
$tokens = $this->tokenizeString($fileContent);
$this->fileMock->expects($this->any())
->method('findNext')
->with([T_WHITESPACE, T_COMMENT, T_DOC_COMMENT], $stackPtr + 1, null, true)
->willReturn($stackPtr + 1);
$this->fileMock->expects($this->once())
->method('getTokens')
->willReturn($tokens);
$this->fileMock->expects($this->exactly($incorrectUsages))
->method('addError')
->with('Short echo tag syntax must be used; expected "<?=" but found "<?php echo"');
$this->shortEchoUsageSniff->process($this->fileMock, $stackPtr);
}
/**
* Get tokens for a string
*
* @param string $fileContent
* @return array
*/
private function tokenizeString($fileContent)
{
$tokens = token_get_all($fileContent);
$snifferTokens = [];
for ($i = 0; $i < count($tokens); $i++) {
$code = is_array($tokens[$i]) ? $tokens[$i][0] : $tokens[$i];
$content = is_array($tokens[$i]) ? $tokens[$i][1] : $tokens[$i];
$snifferTokens[$i]['code'] = $code;
$snifferTokens[$i]['content'] = $content;
}
return $snifferTokens;
}
/**
* @return array
*/
public function processDataProvider()
{
return [
['incorrect_echotag.txt', 1, 1],
['correct_noecho.txt', 1, 0],
['correct_echotag.txt', 1, 0]
];
}
}
@@ -1,6 +0,0 @@
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
<?= "foo" ?>
@@ -1,6 +0,0 @@
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
<?php $foo = bar; ?>
@@ -1,6 +0,0 @@
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
<?php echo "foo" ?>
@@ -1,98 +0,0 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Magento\Sniffs\Translation;
use PHP_CodeSniffer\Files\File;
class ConstantUsageSniffTest extends \PHPUnit\Framework\TestCase
{
/**
* @var File|\PHPUnit_Framework_MockObject_MockObject
*/
private $fileMock;
/**
* @var ConstantUsageSniff
*/
private $constantUsageSniff;
protected function setUp()
{
$this->fileMock = $this->createMock(File::class);
$this->constantUsageSniff = new ConstantUsageSniff();
}
/**
* @param string $file
* @param int $numIncorrectUsages
* @dataProvider processDataProvider
*/
public function testProcessIncorrectArguments($file, $numIncorrectUsages)
{
$stackPtr = 10;
$fileContent = file_get_contents(__DIR__ . '/_files/' . $file);
$tokens = $this->tokenizeString($fileContent);
$this->fileMock->expects($this->once())
->method('findPrevious')
->with(
T_OPEN_TAG,
$stackPtr - 1
)
->willReturn(false);
$this->fileMock->expects($this->once())
->method('getTokens')
->willReturn($tokens);
$this->fileMock->numTokens = count($tokens);
$this->fileMock->expects($this->exactly($numIncorrectUsages))
->method('addError')
->with(
'Constants are not allowed as the first argument of translation function, use string literal instead',
$this->anything(),
'VariableTranslation'
);
$this->constantUsageSniff->process($this->fileMock, $stackPtr);
}
/**
* Get tokens for a string
*
* @param string $fileContent
* @return array
*/
private function tokenizeString($fileContent)
{
$lineNumber = 1;
$tokens = token_get_all($fileContent);
$snifferTokens = [];
for ($i = 0, $count = count($tokens); $i < $count; $i++) {
$content = is_array($tokens[$i]) ? $tokens[$i][1] : $tokens[$i];
$snifferTokens[$i]['line'] = $lineNumber;
$snifferTokens[$i]['content'] = $content;
$trimmedContent = trim($content, ' ');
if ($trimmedContent == PHP_EOL || $trimmedContent == PHP_EOL . PHP_EOL) {
$lineNumber++;
}
}
return $snifferTokens;
}
/**
* @return array
*/
public function processDataProvider()
{
return [
[
'incorrect_arguments.txt',
9
],
[
'correct_arguments.txt',
0
]
];
}
}
@@ -1,29 +0,0 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
__($variable)
__($variable[Class::CONSTANT])
__($variable[\Namespace\Class::CONSTANT])
__($variable['value'])
__(
$variable
)
Phrase($variable)
Phrase($variable[Class::CONSTANT])
Phrase($variable[\Namespace\Class::CONSTANT])
\Magento\Framework\Phrase($variable['value'])
\Magento\Framework\Phrase(
$variable[Class::CONSTANT]
)
@@ -1,27 +0,0 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
__(Class::CONSTANT)
__(self::CONSTANT)
__(\Namespace\Class::CONSTANT)
__(
Class::CONSTANT
)
Phrase(Class::CONSTANT)
Phrase(self::CONSTANT)
Phrase(\Namespace\Class::CONSTANT)
\Magento\Framework\Phrase(Class::CONSTANT)
\Magento\Framework\Phrase(
Class::CONSTANT
)
@@ -7,6 +7,9 @@ namespace Magento\TestFramework\CodingStandard\Tool;
use PHP_CodeSniffer\Runner;
/**
* Unit test to check CodeSniffer tool.
*/
class CodeSnifferTest extends \PHPUnit\Framework\TestCase
{
/**
@@ -48,7 +51,6 @@ class CodeSnifferTest extends \PHPUnit\Framework\TestCase
'files' => $whiteList,
'standards' => [self::RULE_SET],
'extensions' => $extensions,
'warningSeverity' => 0,
'reports' => ['full' => self::REPORT_FILE],
];
@@ -1,33 +0,0 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Magento\TestFramework\Utility;
class XssOutputValidatorTest extends \PHPUnit\Framework\TestCase
{
/**
* @param string $file
* @param string $expectedResults
* @dataProvider getLinesWithXssSensitiveOutputDataProvider
*/
public function testGetLinesWithXssSensitiveOutput($file, $expectedResults)
{
$xssOutputValidator = new XssOutputValidator();
$lines = $xssOutputValidator->getLinesWithXssSensitiveOutput($file);
static::assertEquals($expectedResults, $lines);
}
/**
* @return array
*/
public function getLinesWithXssSensitiveOutputDataProvider()
{
$fixturePath = __DIR__ . '/_files/';
return [
'xss_safe' => [$fixturePath . 'xss_safe.phtml', ''],
'xss_unsafe' => [$fixturePath . 'xss_unsafe.phtml', '9,10,11,12,13,14,15,16,18,22,23'],
];
}
}
@@ -1,48 +0,0 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
// @codingStandardsIgnoreFile
?>
<?= /* @escapeNotVerified */ $block->getSomeData() ?>
<?= /* @noEscape */ $block->getSomeData() ?>
<input name="form_key" type="hidden" value="<?= $block->escapeUrl($var) ?>" />
<input name="form_key" type="hidden" value="<?= $block->escapeHtmlAttr('value') ?>" />
<input name="form_key" type="hidden" value="<?= $block->escapeJs('value') ?>" />
<?= $block->escapeCss('value') ?>
echo $var;
<?= $block->getHtmlId("some value") ?>
<?= $block->getIdHtml("some value") ?>
<?= $block->getIdHtml("some value") ?>
<?= "\$var1" ?>
<?= '$var' ?>
<?= "value" ?>
<?= 'value' ?>
<?= (int)$var ?>
<?= (bool)$var ?>
<?= count($var) ?>
<?= $object->methodHtml() ?>
<?php pecho($var);?>
<?= $object->methodHtml() .
(bool)$var .
$block->escapeUrl("some value");
?>
<?= /* @noEscape */ '\'' . $code . '\',\'' . $block->escapeHtml($data['parentSymbol']) . '\'' ?>
<?= $block->getExtendedElement($switchAttributeCode)->toHtml() ?>
<?= $block->escapeHtml($_filter->getFilter()->getClearLinkText()) ?>
<?php
/**
* echo $someVar;
*/
?>
<?php
/* This part is commented to remove all <col> tags from the code. */
/* foreach ($block->getColumns() as $_column): ?>
<col <?= $_column->getProperty() ?> />
<?php endforeach; */ ?>
<?= $block->escapeHtmlAttr($block->getParamValue('title_' . $store['value'])) ?>
@@ -1,29 +0,0 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
// @codingStandardsIgnoreFile
?>
<?= $block->getSomeData() ?>
<?= $block->getTitle() ?>
<?= $object->getSomeMethod($block->getHtmlId()) ?>
<?= "Title: $title" ?>
<?= $block->escapeUrl($var) . $var . 'value' ?>
<?= $var ?>
<?= $someVar ?>
<?= __("value") ?>
<?= $object->methodHtml() .
$var .
$block->getSomeData();
?>
<?= '\'' . $code . '\',\'' . $block->escapeHtml($data['parentSymbol']) . '\'' ?>
<?= "\"" . $code . "\",\"" . $block->escapeHtml($data['parentSymbol']) . "\"" ?>
<?php
/* This part is commented to remove all <col> tags from the code. */
/* foreach ($block->getColumns() as $_column): ?>
<col <?= $_column->getProperty() ?> />
<?php endforeach; */ ?>
-3
View File
@@ -24,9 +24,6 @@
<testsuite name="Code Integrity Tests">
<directory>testsuite/Magento/Test/Integrity</directory>
</testsuite>
<testsuite name="Xss Unsafe Output Test">
<file>testsuite/Magento/Test/Php/XssPhtmlTemplateTest.php</file>
</testsuite>
</testsuites>
<php>
<ini name="date.timezone" value="America/Los_Angeles"/>
@@ -42,7 +42,6 @@ class UnsecureFunctionsUsageTest extends \PHPUnit\Framework\TestCase
*/
public static function setUpBeforeClass()
{
self::loadData(self::$phpUnsecureFunctions, 'unsecure_php_functions*.php');
self::loadData(self::$jsUnsecureFunctions, 'unsecure_js_functions*.php');
}
@@ -1,87 +0,0 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
/**
* Functions that are not secure to use.
* A <replacement> will be suggested to be used instead.
* Use <exclude> to specify files and directories that are allowed to use function.
*
* Format: [
* <class_name> => [
* 'replacement' => <replacement>,
* 'exclude' => [
* <exclude>,
* <exclude>,
* ]
* ]
*/
return [
'unserialize' => [
'replacement' => '\Magento\Framework\Serialize\SerializerInterface::unserialize',
'exclude' => [
['type' => 'library', 'name' => 'magento/framework', 'path' => 'DB/Adapter/Pdo/Mysql.php'],
['type' => 'library', 'name' => 'magento/framework', 'path' => 'Serialize/Serializer/Serialize.php'],
]
],
'serialize' => [
'replacement' => '\Magento\Framework\Serialize\SerializerInterface::serialize',
'exclude' => [
['type' => 'library', 'name' => 'magento/framework', 'path' => 'DB/Adapter/Pdo/Mysql.php'],
['type' => 'library', 'name' => 'magento/framework', 'path' => 'Serialize/Serializer/Serialize.php'],
]
],
'eval' => [
'replacement' => '',
'exclude' => []
],
'md5' => [
'replacement' => '',
'exclude' => [
/*
* Usage of md5 in MessageQueue key generation algorithm
* added to exclude list to avoid backward incompatible changes
*/
[
'type' => 'library',
'name' => 'magento/framework',
'path' => 'MessageQueue/Rpc/Publisher.php',
],
[
'type' => 'library',
'name' => 'magento/framework',
'path' => 'MessageQueue/MessageController.php',
],
[
'type' => 'library',
'name' => 'magento/framework',
'path' => 'MessageQueue/Publisher.php',
],
[
'type' => 'module',
'name' => 'Magento_AsynchronousOperations',
'path' => 'Model/ResourceModel/System/Message/Collection/Synchronized/Plugin.php'
],
[
'type' => 'module',
'name' => 'Magento_AuthorizenetAcceptjs',
'path' => 'Gateway/Validator/TransactionHashValidator.php'
],
[
'type' => 'module',
'name' => 'Magento_Authorizenet',
'path' => 'Model/Directpost/Response.php'
]
]
],
'srand' => [
'replacement' => '',
'exclude' => []
],
'mt_srand' => [
'replacement' => '',
'exclude' => []
],
];
@@ -77,7 +77,8 @@ class LiveCodeTest extends \PHPUnit\Framework\TestCase
$changedFilesBaseDir = '',
$baseFilesFolder = '',
$whitelistFile = '/_files/whitelist/common.txt'
) {
)
{
$changedFiles = self::getChangedFilesList($changedFilesBaseDir);
if (empty($changedFiles)) {
return [];
@@ -116,8 +117,10 @@ class LiveCodeTest extends \PHPUnit\Framework\TestCase
'changed_files*',
function () {
// if no list files, probably, this is the dev environment
// phpcs:disable Generic.PHP.NoSilencedErrors,Magento2.Security.InsecureFunction
@exec('git diff --name-only', $changedFiles);
@exec('git diff --cached --name-only', $addedFiles);
// phpcs:enable
$changedFiles = array_unique(array_merge($changedFiles, $addedFiles));
return $changedFiles;
}
@@ -137,6 +140,7 @@ class LiveCodeTest extends \PHPUnit\Framework\TestCase
'changed_files*.added.*',
function () {
// if no list files, probably, this is the dev environment
// phpcs:ignore Generic.PHP.NoSilencedErrors,Magento2.Security.InsecureFunction
@exec('git diff --cached --name-only', $addedFiles);
return $addedFiles;
}
@@ -158,7 +162,7 @@ class LiveCodeTest extends \PHPUnit\Framework\TestCase
$globFilesListPattern = ($listsBaseDir ?: self::getChangedFilesBaseDir())
. '/_files/' . $listFilePattern;
$listFiles = glob($globFilesListPattern);
if (count($listFiles)) {
if (!empty($listFiles)) {
foreach ($listFiles as $listFile) {
$filesDefinedInList = array_merge(
$filesDefinedInList,
@@ -1,89 +0,0 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Magento\Test\Php;
use Magento\Framework\App\Utility\Files;
use Magento\TestFramework\Utility\XssOutputValidator;
use Magento\Framework\Component\ComponentRegistrar;
/**
* Find not escaped output in phtml templates
*/
class XssPhtmlTemplateTest extends \PHPUnit\Framework\TestCase
{
/**
* @return void
*/
public function testXssSensitiveOutput()
{
$invoker = new \Magento\Framework\App\Utility\AggregateInvoker($this);
$xssOutputValidator = new XssOutputValidator();
$invoker(
/**
* Static test will cover the following cases:
*
* 1. /\* @noEscape \*\/ before output. Output doesn't require escaping. Test is green.
* 2. Methods which contains "html" in their names (e.g. echo $object->{suffix}Html{postfix}() ).
* Data is ready for the HTML output. Test is green.
* 3. AbstractBlock methods escapeHtml, escapeUrl, escapeQuote, escapeXssInUrl are allowed. Test is green.
* 4. Type casting and php function count() are allowed
* (e.g. echo (int)$var, echo (float)$var, echo (bool)$var, echo count($var)). Test is green.
* 5. Output in single quotes (e.g. echo 'some text'). Test is green.
* 6. Output in double quotes without variables (e.g. echo "some text"). Test is green.
* 7. Other of p.1-6. Output is not escaped. Test is red.
*
* @param string $file
*/
function ($file) use ($xssOutputValidator) {
$lines = $xssOutputValidator->getLinesWithXssSensitiveOutput($file);
$this->assertEmpty(
$lines,
"Potentially XSS vulnerability. " .
"Please verify that output is escaped at lines " . $lines
);
},
Files::init()->getPhtmlFiles()
);
}
/**
* @return void
*/
public function testAbsenceOfEscapeNotVerifiedAnnotationInRefinedModules()
{
$componentRegistrar = new ComponentRegistrar();
$exemptModules = [];
foreach (array_diff(scandir(__DIR__ . '/_files/whitelist/exempt_modules'), ['..', '.']) as $file) {
$exemptModules = array_merge(
$exemptModules,
include(__DIR__ . '/_files/whitelist/exempt_modules/' . $file)
);
}
$result = "";
foreach ($componentRegistrar->getPaths(ComponentRegistrar::MODULE) as $moduleName => $modulePath) {
if (in_array($moduleName, $exemptModules)) {
continue;
}
foreach (Files::init()->getFiles([$modulePath], '*.phtml') as $file) {
$fileContents = file_get_contents($file);
$pattern = "/\\/* @escapeNotVerified \\*\\/ echo (?!__).+/";
$instances = preg_grep($pattern, explode("\n", $fileContents));
if (!empty($instances)) {
foreach (array_keys($instances) as $line) {
$result .= $file . ':' . ($line + 1) . "\n";
}
}
}
}
$this->assertEmpty(
$result,
"@escapeNotVerified annotation detected.\n" .
"Please use the correct escape strategy and remove annotation at:\n" . $result
);
}
}
@@ -29,9 +29,6 @@
<rule ref="rulesets/unusedcode.xml" />
<!-- Code design rules -->
<rule ref="rulesets/design.xml/ExitExpression" />
<rule ref="rulesets/design.xml/EvalExpression" />
<rule ref="rulesets/design.xml/GotoStatement" />
<rule ref="rulesets/design.xml/NumberOfChildren" />
<rule ref="rulesets/design.xml/DepthOfInheritance">
<properties>
@@ -46,7 +43,6 @@
<rule ref="rulesets/naming.xml/BooleanGetMethodName" />
<!-- Magento Specific Rules -->
<rule ref="Magento/CodeMessDetector/resources/rulesets/design.xml/FinalImplementation" />
<rule ref="Magento/CodeMessDetector/resources/rulesets/design.xml/AllPurposeAction" />
<rule ref="Magento/CodeMessDetector/resources/rulesets/design.xml/CookieAndSessionMisuse" />
@@ -244,7 +244,10 @@ class Bootstrap
* Runs an application
*
* @param \Magento\Framework\AppInterface $application
* @throws \Exception
* @return void
*
* phpcs:disable Magento2.Exceptions
*/
public function run(AppInterface $application)
{
@@ -267,13 +270,15 @@ class Bootstrap
} catch (\Exception $e) {
$this->terminate($e);
}
}
} // phpcs:enable
/**
* Asserts maintenance mode
*
* @return void
* @throws \Exception
*
* phpcs:disable Magento2.Exceptions
*/
protected function assertMaintenance()
{
@@ -299,7 +304,7 @@ class Bootstrap
$this->errorCode = self::ERR_MAINTENANCE;
throw new \Exception('Unable to proceed: the maintenance mode must be enabled first. ');
}
}
} // phpcs:enable
/**
* Asserts whether application is installed
@@ -316,10 +321,12 @@ class Bootstrap
$isInstalled = $this->isInstalled();
if (!$isInstalled && $isExpected) {
$this->errorCode = self::ERR_IS_INSTALLED;
// phpcs:ignore Magento2.Exceptions.DirectThrow
throw new \Exception('Error: Application is not installed yet. ');
}
if ($isInstalled && !$isExpected) {
$this->errorCode = self::ERR_IS_INSTALLED;
// phpcs:ignore Magento2.Exceptions.DirectThrow
throw new \Exception('Error: Application is already installed. ');
}
}
@@ -412,12 +419,13 @@ class Bootstrap
* Display an exception and terminate program execution
*
* @param \Exception $e
* @throws \DomainException
* @return void
* @SuppressWarnings(PHPMD.ExitExpression)
*/
protected function terminate(\Exception $e)
{
if ($this->isDeveloperMode()) {
// phpcs:ignore Magento2.Security.LanguageConstruct.DirectOutput
echo $e;
} else {
$message = "An error has happened during application run. See exception log for details.\n";
@@ -429,8 +437,10 @@ class Bootstrap
} catch (\Exception $e) {
$message .= "Could not write error message to log. Please use developer mode to see the message.\n";
}
// phpcs:ignore Magento2.Security.LanguageConstruct.DirectOutput
echo $message;
}
// phpcs:ignore Magento2.Security.LanguageConstruct.ExitUsage
exit(1);
}
}
@@ -6,7 +6,7 @@
namespace Magento\Framework\App\Console;
/**
* @SuppressWarnings(PHPMD.ExitExpression)
* Class Response
*/
class Response implements \Magento\Framework\App\ResponseInterface
{
@@ -53,9 +53,11 @@ class Response implements \Magento\Framework\App\ResponseInterface
public function sendResponse()
{
if (!empty($this->body)) {
// phpcs:ignore Magento2.Security.LanguageConstruct.DirectOutput
echo $this->body;
}
if ($this->terminateOnSend) {
// phpcs:ignore Magento2.Security.LanguageConstruct.ExitUsage
exit($this->code);
}
return $this->code;
@@ -1,6 +1,5 @@
<?php
/**
*
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
@@ -8,6 +7,9 @@ namespace Magento\Framework\App\Response\Http;
use Magento\Framework\App\Filesystem\DirectoryList;
/**
* Class FileFactory
*/
class FileFactory
{
/**
@@ -47,7 +49,6 @@ class FileFactory
*
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
* @SuppressWarnings(PHPMD.NPathComplexity)
* @SuppressWarnings(PHPMD.ExitExpression)
*/
public function create(
$fileName,
@@ -68,6 +69,7 @@ class FileFactory
$isFile = true;
$file = $content['value'];
if (!$dir->isFile($file)) {
// phpcs:ignore Magento2.Exceptions.DirectThrow
throw new \Exception((string)new \Magento\Framework\Phrase('File not found'));
}
$contentLength = $dir->stat($file)['size'];
@@ -86,6 +88,7 @@ class FileFactory
if ($isFile) {
$stream = $dir->openFile($file, 'r');
while (!$stream->eof()) {
// phpcs:ignore Magento2.Security.LanguageConstruct.DirectOutput
echo $stream->read(1024);
}
} else {
@@ -93,6 +96,7 @@ class FileFactory
$file = $fileName;
$stream = $dir->openFile($fileName, 'r');
while (!$stream->eof()) {
// phpcs:ignore Magento2.Security.LanguageConstruct.DirectOutput
echo $stream->read(1024);
}
}
@@ -346,7 +346,6 @@ class Base implements \Magento\Framework\App\RouterInterface
* @param \Magento\Framework\App\RequestInterface $request
* @param string $path
* @return void
* @SuppressWarnings(PHPMD.ExitExpression)
*/
protected function _checkShouldBeSecure(\Magento\Framework\App\RequestInterface $request, $path = '')
{
@@ -361,6 +360,7 @@ class Base implements \Magento\Framework\App\RouterInterface
}
$this->_responseFactory->create()->setRedirect($url)->sendResponse();
// phpcs:ignore Magento2.Security.LanguageConstruct.ExitUsage
exit;
}
}
@@ -7,6 +7,11 @@ namespace Magento\Framework\Code\Test\Unit\Generator\TestAsset;
use Zend\Code\Generator\DocBlockGenerator;
/**
* Class ParentClass
*
* phpcs:ignoreFile
*/
class ParentClass
{
/**
@@ -78,9 +83,6 @@ class ParentClass
{
}
/**
* @SuppressWarnings(PHPMD.FinalImplementation) Suppressed as is a fixture but not a real code
*/
final public function publicParentFinal()
{
}
@@ -7,6 +7,11 @@ namespace Magento\Framework\Code\Test\Unit\Generator\TestAsset;
use Zend\Code\Generator\ClassGenerator;
/**
* Class SourceClass
*
* phpcs:ignoreFile
*/
class SourceClass extends ParentClass
{
/**
@@ -111,10 +116,7 @@ class SourceClass extends ParentClass
public static function publicChildStatic()
{
}
/**
* @SuppressWarnings(PHPMD.FinalImplementation) Suppressed as is a fixture but not a real code
*/
final public function publicChildFinal()
{
}
@@ -22,9 +22,10 @@ use Magento\Framework\Config\ConfigOptionsListConstants;
/**
* Magento 2 CLI Application.
*
* This is the hood for all command line tools supported by Magento.
*
* {@inheritdoc}
* @inheritdoc
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
*/
class Cli extends Console\Application
@@ -61,11 +62,11 @@ class Cli extends Console\Application
/**
* @param string $name the application name
* @param string $version the application version
* @SuppressWarnings(PHPMD.ExitExpression)
*/
public function __construct($name = 'UNKNOWN', $version = 'UNKNOWN')
{
try {
// phpcs:ignore Magento2.Security.IncludeFile
$configuration = require BP . '/setup/config/application.config.php';
$bootstrapApplication = new Application();
$application = $bootstrapApplication->bootstrap($configuration);
@@ -78,7 +79,7 @@ class Cli extends Console\Application
$output->writeln(
'<error>' . $exception->getMessage() . '</error>'
);
// phpcs:ignore Magento2.Security.LanguageConstruct.ExitUsage
exit(static::RETURN_FAILURE);
}
@@ -93,7 +94,7 @@ class Cli extends Console\Application
}
/**
* {@inheritdoc}
* @inheritdoc
*
* @throws \Exception The exception in case of unexpected error
*/
@@ -109,7 +110,7 @@ class Cli extends Console\Application
}
/**
* {@inheritdoc}
* @inheritdoc
*/
protected function getDefaultCommands()
{
@@ -217,8 +218,7 @@ class Cli extends Console\Application
}
/**
* Provides updated configuration in
* accordance to document root settings.
* Provides updated configuration in accordance to document root settings.
*
* @param array $config
* @return array
+1 -4
View File
@@ -15,6 +15,7 @@ use Magento\Framework\Phrase;
* Magento Library
*
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
* phpcs:ignoreFile
*
* @deprecated Not used anymore.
*/
@@ -300,7 +301,6 @@ class Tree
* @param string|int $nodeId
* @param array $data
* @return false|string
* @SuppressWarnings(PHPMD.ExitExpression)
*
* @deprecated Not used anymore.
*/
@@ -477,7 +477,6 @@ class Tree
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
* @SuppressWarnings(PHPMD.ExitExpression)
*
* @deprecated Not used anymore.
*/
@@ -814,7 +813,6 @@ class Tree
* @SuppressWarnings(PHPMD.NPathComplexity)
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
* @SuppressWarnings(PHPMD.UnusedLocalVariable)
* @SuppressWarnings(PHPMD.ExitExpression)
*
* @deprecated Not used anymore.
*/
@@ -1041,7 +1039,6 @@ class Tree
* @param int $startLevel
* @param int $endLevel
* @return NodeSet
* @SuppressWarnings(PHPMD.ExitExpression)
*
* @deprecated Not used anymore.
*/
@@ -27,63 +27,63 @@ use Magento\Framework\Data\Collection;
class Filesystem extends \Magento\Framework\Data\Collection
{
/**
* Target directory
* Target directory.
*
* @var string
*/
protected $_targetDirs = [];
/**
* Whether to collect files
* Whether to collect files.
*
* @var bool
*/
protected $_collectFiles = true;
/**
* Whether to collect directories before files
* Whether to collect directories before files.
*
* @var bool
*/
protected $_dirsFirst = true;
/**
* Whether to collect recursively
* Whether to collect recursively.
*
* @var bool
*/
protected $_collectRecursively = true;
/**
* Whether to collect dirs
* Whether to collect dirs.
*
* @var bool
*/
protected $_collectDirs = false;
/**
* \Directory names regex pre-filter
* \Directory names regex pre-filter.
*
* @var string
*/
protected $_allowedDirsMask = '/^[a-z0-9\.\-\_]+$/i';
/**
* Filenames regex pre-filter
* Filenames regex pre-filter.
*
* @var string
*/
protected $_allowedFilesMask = '/^[a-z0-9\.\-\_]+\.[a-z0-9]+$/i';
/**
* Disallowed filenames regex pre-filter match for better versatility
* Disallowed filenames regex pre-filter match for better versatility.
*
* @var string
*/
protected $_disallowedFilesMask = '';
/**
* Filter rendering helper variable
* Filter rendering helper variable.
*
* @var int
* @see Collection::$_filter
@@ -92,7 +92,7 @@ class Filesystem extends \Magento\Framework\Data\Collection
private $_filterIncrement = 0;
/**
* Filter rendering helper variable
* Filter rendering helper variable.
*
* @var array
* @see Collection::$_filter
@@ -101,7 +101,7 @@ class Filesystem extends \Magento\Framework\Data\Collection
private $_filterBrackets = [];
/**
* Filter rendering helper variable
* Filter rendering helper variable.
*
* @var string
* @see Collection::$_filter
@@ -110,22 +110,21 @@ class Filesystem extends \Magento\Framework\Data\Collection
private $_filterEvalRendered = '';
/**
* Collecting items helper variable
* Collecting items helper variable.
*
* @var array
*/
protected $_collectedDirs = [];
/**
* Collecting items helper variable
* Collecting items helper variable.
*
* @var array
*/
protected $_collectedFiles = [];
/**
* Allowed dirs mask setter
* Set empty to not filter
* Allowed dirs mask setter. Set empty to not filter.
*
* @param string $regex
* @return $this
@@ -137,8 +136,7 @@ class Filesystem extends \Magento\Framework\Data\Collection
}
/**
* Allowed files mask setter
* Set empty to not filter
* Allowed files mask setter. Set empty to not filter.
*
* @param string $regex
* @return $this
@@ -150,8 +148,7 @@ class Filesystem extends \Magento\Framework\Data\Collection
}
/**
* Disallowed files mask setter
* Set empty value to not use this filter
* Disallowed files mask setter. Set empty value to not use this filter.
*
* @param string $regex
* @return $this
@@ -163,7 +160,7 @@ class Filesystem extends \Magento\Framework\Data\Collection
}
/**
* Set whether to collect dirs
* Set whether to collect dirs.
*
* @param bool $value
* @return $this
@@ -175,7 +172,7 @@ class Filesystem extends \Magento\Framework\Data\Collection
}
/**
* Set whether to collect files
* Set whether to collect files.
*
* @param bool $value
* @return $this
@@ -187,7 +184,7 @@ class Filesystem extends \Magento\Framework\Data\Collection
}
/**
* Set whether to collect recursively
* Set whether to collect recursively.
*
* @param bool $value
* @return $this
@@ -199,7 +196,7 @@ class Filesystem extends \Magento\Framework\Data\Collection
}
/**
* Target directory setter. Adds directory to be scanned
* Target directory setter. Adds directory to be scanned.
*
* @param string $value
* @return $this
@@ -209,6 +206,7 @@ class Filesystem extends \Magento\Framework\Data\Collection
{
$value = (string)$value;
if (!is_dir($value)) {
// phpcs:ignore Magento2.Exceptions.DirectThrow
throw new \Exception('Unable to set target directory.');
}
$this->_targetDirs[$value] = $value;
@@ -216,8 +214,7 @@ class Filesystem extends \Magento\Framework\Data\Collection
}
/**
* Set whether to collect directories before files
* Works *before* sorting.
* Set whether to collect directories before files. Works *before* sorting.
*
* @param bool $value
* @return $this
@@ -229,7 +226,7 @@ class Filesystem extends \Magento\Framework\Data\Collection
}
/**
* Get files from specified directory recursively (if needed)
* Get files from specified directory recursively (if needed).
*
* @param string|array $dir
* @return void
@@ -281,7 +278,7 @@ class Filesystem extends \Magento\Framework\Data\Collection
}
/**
* Lauch data collecting
* Launch data collecting.
*
* @param bool $printQuery
* @param bool $logQuery
@@ -295,6 +292,7 @@ class Filesystem extends \Magento\Framework\Data\Collection
return $this;
}
if (empty($this->_targetDirs)) {
// phpcs:disable Magento2.Exceptions.DirectThrow
throw new \Exception('Please specify at least one target directory.');
}
@@ -364,25 +362,22 @@ class Filesystem extends \Magento\Framework\Data\Collection
}
/**
* Callback for sorting items
* Currently supports only sorting by one column
* Callback for sorting items. Currently supports only sorting by one column.
*
* @param array $a
* @param array $b
* @return int|void
* @return int
*/
protected function _usort($a, $b)
{
foreach ($this->_orders as $key => $direction) {
$result = $a[$key] > $b[$key] ? 1 : ($a[$key] < $b[$key] ? -1 : 0);
return self::SORT_ORDER_ASC === strtoupper($direction) ? $result : -$result;
break;
}
}
/**
* Set select order
* Currently supports only sorting by one column
* Set select order. Currently supports only sorting by one column.
*
* @param string $field
* @param string $direction
@@ -395,7 +390,7 @@ class Filesystem extends \Magento\Framework\Data\Collection
}
/**
* Generate item row basing on the filename
* Generate item row basing on the filename.
*
* @param string $filename
* @return array
@@ -433,13 +428,11 @@ class Filesystem extends \Magento\Framework\Data\Collection
}
/**
* The filters renderer and caller
* Applies to each row, renders once.
* The filters renderer and caller. Applies to each row, renders once.
*
* @param array $row
* @return bool
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
* @SuppressWarnings(PHPMD.EvalExpression)
*/
protected function _filterRow($row)
{
@@ -469,14 +462,14 @@ class Filesystem extends \Magento\Framework\Data\Collection
}
$result = false;
if ($this->_filterEvalRendered) {
// phpcs:ignore Squiz.PHP.Eval
eval('$result = ' . $this->_filterEvalRendered . ';');
}
return $result;
}
/**
* Invokes specified callback
* Skips, if there is no filtered key in the row
* Invokes specified callback. Skips, if there is no filtered key in the row.
*
* @param callback $callback
* @param array $callbackParams
@@ -493,7 +486,7 @@ class Filesystem extends \Magento\Framework\Data\Collection
}
/**
* Fancy field filter
* Fancy field filter.
*
* @param string $field
* @param mixed $cond
@@ -626,7 +619,7 @@ class Filesystem extends \Magento\Framework\Data\Collection
}
/**
* Prepare a bracket into filters
* Prepare a bracket into filters.
*
* @param string $bracket
* @param bool $isAnd
@@ -643,7 +636,7 @@ class Filesystem extends \Magento\Framework\Data\Collection
}
/**
* Render condition sign before element, if required
* Render condition sign before element, if required.
*
* @param int $increment
* @param bool $isAnd
@@ -666,7 +659,8 @@ class Filesystem extends \Magento\Framework\Data\Collection
}
/**
* Does nothing. Intentionally disabled parent method
* Does nothing. Intentionally disabled parent method.
*
* @param string $field
* @param string $value
* @param string $type
@@ -679,7 +673,7 @@ class Filesystem extends \Magento\Framework\Data\Collection
}
/**
* Get all ids of collected items
* Get all ids of collected items.
*
* @return array
*/
@@ -689,7 +683,7 @@ class Filesystem extends \Magento\Framework\Data\Collection
}
/**
* Callback method for 'like' fancy filter
* Callback method for 'like' fancy filter.
*
* @param string $field
* @param mixed $filterValue
@@ -708,7 +702,7 @@ class Filesystem extends \Magento\Framework\Data\Collection
}
/**
* Callback method for 'eq' fancy filter
* Callback method for 'eq' fancy filter.
*
* @param string $field
* @param mixed $filterValue
@@ -723,7 +717,7 @@ class Filesystem extends \Magento\Framework\Data\Collection
}
/**
* Callback method for 'in' fancy filter
* Callback method for 'in' fancy filter.
*
* @param string $field
* @param mixed $filterValue
@@ -738,7 +732,7 @@ class Filesystem extends \Magento\Framework\Data\Collection
}
/**
* Callback method for 'isnull' fancy filter
* Callback method for 'isnull' fancy filter.
*
* @param string $field
* @param mixed $filterValue
@@ -754,7 +748,7 @@ class Filesystem extends \Magento\Framework\Data\Collection
}
/**
* Callback method for 'moreq' fancy filter
* Callback method for 'moreq' fancy filter.
*
* @param string $field
* @param mixed $filterValue
@@ -769,7 +763,7 @@ class Filesystem extends \Magento\Framework\Data\Collection
}
/**
* Callback method for 'lteq' fancy filter
* Callback method for 'lteq' fancy filter.
*
* @param string $field
* @param mixed $filterValue
@@ -172,7 +172,6 @@ class ErrorProcessor
* @param \Exception $exception
* @param int $httpCode
* @return void
* @SuppressWarnings(PHPMD.ExitExpression)
*/
public function renderException(\Exception $exception, $httpCode = self::DEFAULT_ERROR_HTTP_CODE)
{
@@ -188,6 +187,7 @@ class ErrorProcessor
$httpCode
);
}
// phpcs:ignore Magento2.Security.LanguageConstruct.ExitUsage
exit;
}
@@ -232,6 +232,7 @@ class ErrorProcessor
header('HTTP/1.1 ' . ($httpCode ? $httpCode : self::DEFAULT_ERROR_HTTP_CODE));
header('Content-Type: ' . $mimeType . '; charset=' . self::DEFAULT_RESPONSE_CHARSET);
}
// phpcs:ignore Magento2.Security.LanguageConstruct.DirectOutput
echo $output;
}
+1 -1
View File
@@ -11,6 +11,7 @@ use Magento\Framework\Serialize\Serializer\Json;
* Error processor
*
* @SuppressWarnings(PHPMD.TooManyFields)
* phpcs:ignoreFile
*/
class Processor
{
@@ -501,7 +502,6 @@ class Processor
*
* @param int $reportId
* @return void
* @SuppressWarnings(PHPMD.ExitExpression)
*/
public function loadReport($reportId)
{