Skip to content

Commit 53c72a2

Browse files
committed
Merge branch 'develop' of github.com:magento/magento2ce into MAGETWO-62334
2 parents 58e4a0c + 2d2d18d commit 53c72a2

File tree

16 files changed

+312
-25
lines changed

16 files changed

+312
-25
lines changed

app/code/Magento/Braintree/Model/Ui/ConfigProvider.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
/**
1414
* Class ConfigProvider
1515
*/
16-
final class ConfigProvider implements ConfigProviderInterface
16+
class ConfigProvider implements ConfigProviderInterface
1717
{
1818
const CODE = 'braintree';
1919

app/code/Magento/Vault/Model/Method/Vault.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
* @SuppressWarnings(PHPMD.ExcessivePublicCount)
2929
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
3030
*/
31-
final class Vault implements VaultPaymentInterface
31+
class Vault implements VaultPaymentInterface
3232
{
3333
/**
3434
* @deprecated

app/code/Magento/Vault/Model/Ui/Adminhtml/TokensConfigProvider.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
* @api
2828
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
2929
*/
30-
final class TokensConfigProvider
30+
class TokensConfigProvider
3131
{
3232
/**
3333
* @var PaymentTokenRepositoryInterface

app/code/Magento/Vault/Model/Ui/TokensConfigProvider.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
* Class ConfigProvider
1616
* @api
1717
*/
18-
final class TokensConfigProvider implements ConfigProviderInterface
18+
class TokensConfigProvider implements ConfigProviderInterface
1919
{
2020
/**
2121
* @var string

dev/tests/integration/testsuite/Magento/Framework/Code/GeneratorTest/ParentClassWithNamespace.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,9 @@ public static function publicParentStatic()
7878
{
7979
}
8080

81+
/**
82+
* @SuppressWarnings(PHPMD.FinalImplementation) Suppressed as is a fixture but not a real code
83+
*/
8184
final public function publicParentFinal()
8285
{
8386
}

dev/tests/integration/testsuite/Magento/Framework/Code/GeneratorTest/SourceClassWithNamespace.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,9 @@ public static function publicChildStatic()
104104
{
105105
}
106106

107+
/**
108+
* @SuppressWarnings(PHPMD.FinalImplementation) Suppressed as is a fixture but not a real code
109+
*/
107110
final public function publicChildFinal()
108111
{
109112
}

dev/tests/integration/testsuite/Magento/Framework/Interception/Fixture/Intercepted.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ public function D($param1)
4848

4949
/**
5050
* @SuppressWarnings(PHPMD.ShortMethodName)
51+
* @SuppressWarnings(PHPMD.FinalImplementation) Suppressed as is a fixture but not a real code
5152
*/
5253
final public function E($param1)
5354
{
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<?php
2+
/**
3+
* Copyright © 2013-2017 Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
namespace Magento\CodeMessDetector\Rule\Design;
8+
9+
use PHPMD\AbstractNode;
10+
use PHPMD\AbstractRule;
11+
use PHPMD\Rule\ClassAware;
12+
use PHPMD\Rule\MethodAware;
13+
14+
/**
15+
* Magento is a highly extensible and customizable platform.
16+
* Usage of final classes and methods is prohibited.
17+
*/
18+
class FinalImplementation extends AbstractRule implements ClassAware, MethodAware
19+
{
20+
21+
/**
22+
* @inheritdoc
23+
*/
24+
public function apply(AbstractNode $node)
25+
{
26+
if ($node->isFinal()) {
27+
$this->addViolation($node, [$node->getType(), $node->getFullQualifiedName()]);
28+
}
29+
}
30+
}
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
<?php
2+
/**
3+
* Copyright © 2013-2017 Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
namespace Magento\CodeMessDetector\Test\Unit\Rule\Design;
8+
9+
use PHPUnit_Framework_TestCase as TestCase;
10+
use PHPUnit_Framework_MockObject_MockObject as MockObject;
11+
use PHPUnit_Framework_MockObject_Matcher_InvokedRecorder as InvokedRecorder;
12+
use PHPUnit_Framework_MockObject_Builder_InvocationMocker as InvocationMocker;
13+
use Magento\CodeMessDetector\Rule\Design\FinalImplementation;
14+
use PHPMD\Report;
15+
use PHPMD\AbstractNode;
16+
use PHPMD\Node\ClassNode;
17+
use PHPMD\Node\MethodNode;
18+
use BadMethodCallException;
19+
20+
class FinalImplementationTest extends TestCase
21+
{
22+
/**
23+
* @param string $nodeType
24+
*
25+
* @dataProvider finalizableNodeTypesProvider
26+
*/
27+
public function testRuleNotAppliesToNotFinalFinalizable($nodeType)
28+
{
29+
$finalizableNode = $this->createFinalizableNodeMock($nodeType);
30+
$finalizableNode->method('isFinal')->willReturn(false);
31+
32+
$rule = new FinalImplementation();
33+
$this->expectsRuleViolation($rule, $this->never());
34+
$rule->apply($finalizableNode);
35+
}
36+
37+
/**
38+
* @param string $nodeType
39+
*
40+
* @dataProvider finalizableNodeTypesProvider
41+
*/
42+
public function testRuleAppliesToFinalFinalizable($nodeType)
43+
{
44+
$finalizableNode = $this->createFinalizableNodeMock($nodeType);
45+
$finalizableNode->method('isFinal')->willReturn(true);
46+
47+
$rule = new FinalImplementation();
48+
$this->expectsRuleViolation($rule, $this->once());
49+
$rule->apply($finalizableNode);
50+
}
51+
52+
/**
53+
* @param string $nodeType
54+
*
55+
* @dataProvider finalizableNodeTypesProvider
56+
*/
57+
public function testRuleVerifiesFinalizableNodes($nodeType)
58+
{
59+
$finalizableNode = $this->createFinalizableNodeMock($nodeType);
60+
61+
$finalizableNode->expects($this->atLeastOnce())
62+
->method('isFinal');
63+
64+
$rule = new FinalImplementation();
65+
$rule->apply($finalizableNode);
66+
}
67+
68+
/**
69+
* @expectedException BadMethodCallException
70+
*/
71+
public function testRuleFailsOnNotFinalizableNodes()
72+
{
73+
$someNode = $this->getMockBuilder(AbstractNode::class)
74+
->disableOriginalConstructor()
75+
->getMockForAbstractClass();
76+
77+
$rule = new FinalImplementation();
78+
$rule->apply($someNode);
79+
}
80+
81+
/**
82+
* "final" keyword may be applied only to classes and methods
83+
*
84+
* @return array
85+
*/
86+
public function finalizableNodeTypesProvider()
87+
{
88+
return [
89+
[ClassNode::class],
90+
[MethodNode::class],
91+
];
92+
}
93+
94+
/**
95+
* If node is finalizable it has "isFinal" magic PHP method
96+
*
97+
* @param string $nodeType
98+
* @return ClassNode|MethodNode|MockObject
99+
*/
100+
private function createFinalizableNodeMock($nodeType)
101+
{
102+
$finalizableNode = $this->getMockBuilder($nodeType)
103+
->disableOriginalConstructor()
104+
->disableProxyingToOriginalMethods()
105+
->setMethods([
106+
'isFinal',
107+
// disable name lookup from AST artifact
108+
'getNamespaceName',
109+
'getParentName',
110+
'getName',
111+
])
112+
->getMock();
113+
return $finalizableNode;
114+
}
115+
116+
/**
117+
* @param FinalImplementation $rule
118+
* @param InvokedRecorder $violationExpectation
119+
* @return InvocationMocker
120+
*/
121+
private function expectsRuleViolation(FinalImplementation $rule, InvokedRecorder $violationExpectation)
122+
{
123+
$report = $this->getMockBuilder(Report::class)->getMock();
124+
$invokation = $report->expects($violationExpectation)->method('addRuleViolation');
125+
$rule->setReport($report);
126+
return $invokation;
127+
}
128+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<?xml version="1.0"?>
2+
<!--
3+
/**
4+
* Copyright © 2013-2017 Magento, Inc. All rights reserved.
5+
* See COPYING.txt for license details.
6+
*/
7+
-->
8+
<ruleset name="Magento Specific Design Rules"
9+
xmlns="http://pmd.sf.net/ruleset/1.0.0"
10+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
11+
xsi:schemaLocation="http://pmd.sf.net/ruleset/1.0.0 http://pmd.sf.net/ruleset_xml_schema.xsd"
12+
xsi:noNamespaceSchemaLocation="http://pmd.sf.net/ruleset_xml_schema.xsd">
13+
<rule name="FinalImplementation"
14+
class="Magento\CodeMessDetector\Rule\Design\FinalImplementation"
15+
message= "The {0} {1} declared as final.">
16+
<description>
17+
<![CDATA[
18+
Final keyword is prohibited in Magento as this decreases extensibility and customizability.
19+
Final classes and method are not compatible with plugins and proxies.
20+
]]>
21+
</description>
22+
<priority>1</priority>
23+
<properties />
24+
<example>
25+
<![CDATA[
26+
final class Foo
27+
{
28+
public function bar() {}
29+
}
30+
class Baz {
31+
final public function bad() {}
32+
}
33+
]]>
34+
</example>
35+
</rule>
36+
</ruleset>

dev/tests/static/framework/autoload.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
$testsBaseDir . '/../integration/framework/Magento/TestFramework/',
1919
]
2020
);
21+
$autoloadWrapper->addPsr4('Magento\\CodeMessDetector\\', $testsBaseDir . '/framework/Magento/CodeMessDetector');
2122

2223
$generatedCode = DirectoryList::getDefaultConfig()[DirectoryList::GENERATED_CODE][DirectoryList::PATH];
2324
$autoloadWrapper->addPsr4('Magento\\', $baseDir . '/' . $generatedCode . '/Magento/');

0 commit comments

Comments
 (0)