Skip to content

Commit 56f3fb8

Browse files
committed
[PHPMD] Add phpmd rule with ignoring of unused required parameters in the plugins
Signed-off-by: Denis Kopylov <[email protected]>
1 parent 21aa619 commit 56f3fb8

File tree

7 files changed

+158
-7
lines changed

7 files changed

+158
-7
lines changed

app/code/Magento/Catalog/Plugin/CategoryAuthorization.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,12 @@
1212
use Magento\Catalog\Api\CategoryRepositoryInterface;
1313
use Magento\Catalog\Model\Category\Authorization;
1414
use Magento\Framework\Exception\LocalizedException;
15+
use Magento\Framework\Interception\PluginInterface;
1516

1617
/**
1718
* Perform additional authorization for category operations.
1819
*/
19-
class CategoryAuthorization
20+
class CategoryAuthorization implements PluginInterface
2021
{
2122
/**
2223
* @var Authorization
@@ -38,7 +39,6 @@ public function __construct(Authorization $authorization)
3839
* @param CategoryInterface $category
3940
* @throws LocalizedException
4041
* @return array
41-
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
4242
*/
4343
public function beforeSave(CategoryRepositoryInterface $subject, CategoryInterface $category): array
4444
{

app/code/Magento/Catalog/Plugin/ProductAuthorization.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,12 @@
1212
use Magento\Catalog\Api\ProductRepositoryInterface;
1313
use Magento\Catalog\Model\Product\Authorization;
1414
use Magento\Framework\Exception\LocalizedException;
15+
use Magento\Framework\Interception\PluginInterface;
1516

1617
/**
1718
* Perform additional authorization for product operations.
1819
*/
19-
class ProductAuthorization
20+
class ProductAuthorization implements PluginInterface
2021
{
2122
/**
2223
* @var Authorization
@@ -39,7 +40,6 @@ public function __construct(Authorization $authorization)
3940
* @param bool $saveOptions
4041
* @throws LocalizedException
4142
* @return array
42-
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
4343
*/
4444
public function beforeSave(
4545
ProductRepositoryInterface $subject,

app/code/Magento/Catalog/Plugin/RemoveImagesFromGalleryAfterRemovingProduct.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,12 @@
1212
use Magento\Catalog\Api\ProductRepositoryInterface;
1313
use Magento\Catalog\Model\Product\Gallery\ReadHandler;
1414
use Magento\Catalog\Model\ResourceModel\Product\Gallery;
15+
use Magento\Framework\Interception\PluginInterface;
1516

1617
/**
1718
* Responsible for deleting images from media gallery after deleting product
1819
*/
19-
class RemoveImagesFromGalleryAfterRemovingProduct
20+
class RemoveImagesFromGalleryAfterRemovingProduct implements PluginInterface
2021
{
2122
/**
2223
* @var Gallery
@@ -45,7 +46,6 @@ public function __construct(Gallery $galleryResource, ReadHandler $mediaGalleryR
4546
* @param callable $proceed
4647
* @param ProductInterface $product
4748
* @return bool
48-
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
4949
*/
5050
public function aroundDelete(
5151
ProductRepositoryInterface $subject,
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
<?php
2+
declare(strict_types=1);
3+
/**
4+
* Copyright © Magento, Inc. All rights reserved.
5+
* See COPYING.txt for license details.
6+
*/
7+
8+
namespace Magento\CodeMessDetector\Rule\UnusedCode;
9+
10+
use Magento\Framework\Interception\PluginInterface;
11+
use PDepend\Source\AST\ASTParameter;
12+
use PHPMD\AbstractNode;
13+
use PHPMD\Node\ClassNode;
14+
use PHPMD\Node\MethodNode;
15+
use PHPMD\Rule\UnusedFormalParameter as PhpmdUnusedFormalParameter;
16+
17+
class UnusedFormalParameter extends PhpmdUnusedFormalParameter
18+
{
19+
/**
20+
* This method collects all local variables in the body of the currently
21+
* analyzed method or function and removes those parameters that are
22+
* referenced by one of the collected variables.
23+
*
24+
* @param AbstractNode $node
25+
* @return void
26+
*/
27+
protected function removeUsedParameters(AbstractNode $node)
28+
{
29+
parent::removeUsedParameters($node);
30+
$this->removeVariablesUsedInPlugins($node);
31+
}
32+
33+
/**
34+
* Remove required method variables used in plugins from given node
35+
*
36+
* @param AbstractNode $node
37+
*/
38+
private function removeVariablesUsedInPlugins(AbstractNode $node)
39+
{
40+
if ($node instanceof MethodNode) {
41+
/** @var ClassNode $classNode */
42+
$classNode = $node->getParentType();
43+
$implementInterfaces = class_implements($classNode->getFullQualifiedName());
44+
if (array_key_exists(PluginInterface::class, $implementInterfaces)) {
45+
/**
46+
* Around and After plugins has 2 required params $subject and $proceed or $result
47+
* that should be ignored
48+
*/
49+
foreach (['around', 'after'] as $pluginMethodPrefix) {
50+
if ($this->isFunctionNameStartingWith($node, $pluginMethodPrefix)) {
51+
$this->removeVariablesByCount($node, 2);
52+
53+
break;
54+
}
55+
}
56+
57+
/**
58+
* Before plugins has 1 required params $subject
59+
* that should be ignored
60+
*/
61+
if ($this->isFunctionNameStartingWith($node, 'before')) {
62+
$this->removeVariablesByCount($node, 1);
63+
}
64+
}
65+
}
66+
}
67+
68+
/**
69+
* Check if the first part of function fully qualified name is equal to $name
70+
*
71+
* @param MethodNode $node
72+
* @param string $name
73+
* @return boolean
74+
*/
75+
private function isFunctionNameStartingWith(MethodNode $node, string $name): bool
76+
{
77+
return (0 === strpos($node->getImage(), $name));
78+
}
79+
80+
/**
81+
* Get first $numberOfParams parameters of method
82+
*
83+
* @param MethodNode $node
84+
* @param int $numberOfParams
85+
* @return array
86+
*/
87+
private function getMethodParametersByLength(MethodNode $node, int $numberOfParams): array
88+
{
89+
return array_slice($node->getNode()->getParameters(), 0, $numberOfParams);
90+
}
91+
92+
/**
93+
* Remove first $countOfRemovingVariables from given node
94+
*
95+
* @param MethodNode $node
96+
* @param int $countOfRemovingVariables
97+
*/
98+
private function removeVariablesByCount(MethodNode $node, int $countOfRemovingVariables)
99+
{
100+
$methodParameters = $this->getMethodParametersByLength($node, $countOfRemovingVariables);
101+
/** @var ASTParameter $methodParameter */
102+
foreach ($methodParameters as $methodParameter) {
103+
unset($this->nodes[$methodParameter->getName()]);
104+
}
105+
}
106+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?xml version="1.0"?>
2+
3+
<ruleset name="Unused Code Rules"
4+
xmlns="http://pmd.sf.net/ruleset/1.0.0"
5+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
6+
xsi:schemaLocation="http://pmd.sf.net/ruleset/1.0.0 http://pmd.sf.net/ruleset_xml_schema.xsd"
7+
xsi:noNamespaceSchemaLocation="http://pmd.sf.net/ruleset_xml_schema.xsd">
8+
9+
<rule name="UnusedFormalParameter"
10+
message="Avoid unused parameters such as '{0}'."
11+
class="Magento\CodeMessDetector\Rule\UnusedCode\UnusedFormalParameter">
12+
<description><![CDATA[Avoid passing parameters to methods or constructors and then not using those parameters except on plugins]]></description>
13+
<example>
14+
<![CDATA[
15+
class Foo
16+
{
17+
private function bar($howdy)
18+
{
19+
// $howdy is not used
20+
}
21+
}
22+
]]>
23+
</example>
24+
</rule>
25+
26+
</ruleset>

dev/tests/static/testsuite/Magento/Test/Php/_files/phpmd/ruleset.xml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,9 @@
2626
</rule>
2727

2828
<!-- Unused code rules -->
29-
<rule ref="rulesets/unusedcode.xml" />
29+
<rule ref="rulesets/unusedcode.xml">
30+
<exclude name="UnusedFormalParameter"/>
31+
</rule>
3032

3133
<!-- Code design rules -->
3234
<rule ref="rulesets/design.xml/NumberOfChildren" />
@@ -45,5 +47,6 @@
4547
<!-- Magento Specific Rules -->
4648
<rule ref="Magento/CodeMessDetector/resources/rulesets/design.xml/AllPurposeAction" />
4749
<rule ref="Magento/CodeMessDetector/resources/rulesets/design.xml/CookieAndSessionMisuse" />
50+
<rule ref="Magento/CodeMessDetector/resources/rulesets/unusedcode.xml/UnusedFormalParameter" />
4851

4952
</ruleset>
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?php
2+
declare(strict_types=1);
3+
/**
4+
* Copyright © Magento, Inc. All rights reserved.
5+
* See COPYING.txt for license details.
6+
*/
7+
8+
namespace Magento\Framework\Interception;
9+
10+
/**
11+
* Interface for any plugin classes
12+
*/
13+
interface PluginInterface
14+
{
15+
16+
}

0 commit comments

Comments
 (0)