Skip to content

Commit f2bb5ec

Browse files
author
Lars Roettig
committed
#49 Impl. LocalizedException SHOULD only be thrown in View
1 parent df5fc07 commit f2bb5ec

8 files changed

+217
-0
lines changed
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
<?php
2+
/**
3+
* Copyright © Magento. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
namespace Magento\Sniffs\Exceptions;
8+
9+
use PHP_CodeSniffer\Sniffs\Sniff;
10+
use PHP_CodeSniffer\Files\File;
11+
12+
/**
13+
* Detects possible direct throws of Exceptions.
14+
*/
15+
class LocalizedThrowSniff implements Sniff
16+
{
17+
18+
protected $presentationLayerKeys = ['Controller', 'Block', 'ViewModel'];
19+
20+
/**
21+
* String representation of warning.
22+
*/
23+
protected $warningMessage = 'LocalizedException SHOULD only be thrown in the Presentation layer.';
24+
25+
/**
26+
* Warning violation code.
27+
*
28+
* @var string
29+
*/
30+
protected $warningCode = 'LocalizedThrow';
31+
32+
/**
33+
* @inheritdoc
34+
*/
35+
public function register()
36+
{
37+
return [T_THROW];
38+
}
39+
40+
/**
41+
* @inheritdoc
42+
*/
43+
public function process(File $phpcsFile, $stackPtr)
44+
{
45+
$lineEnd = $phpcsFile->findNext(T_OPEN_PARENTHESIS, $stackPtr);
46+
$exceptionType = $phpcsFile->getTokensAsString($stackPtr, $lineEnd);
47+
48+
// throw is not a LocalizedException nothing to do
49+
if (strpos($exceptionType, 'LocalizedException') === false) {
50+
return;
51+
}
52+
53+
$nameSpaceTag = $phpcsFile->findPrevious(T_NAMESPACE, $stackPtr, 0);
54+
if ($nameSpaceTag === false) {
55+
// no namespace nothing to do
56+
return;
57+
}
58+
59+
$lineEnd = $phpcsFile->findNext(T_SEMICOLON, $nameSpaceTag);
60+
$nameSpaceString = $phpcsFile->getTokensAsString($nameSpaceTag, $lineEnd);
61+
62+
$isPresentationLayer = false;
63+
foreach ($this->presentationLayerKeys as $layerKey) {
64+
if (strpos($nameSpaceString, $layerKey) !== false) {
65+
$isPresentationLayer = true;
66+
break;
67+
}
68+
}
69+
70+
if (!$isPresentationLayer) {
71+
$phpcsFile->addWarning(
72+
$this->warningMessage,
73+
$stackPtr,
74+
$this->warningCode
75+
);
76+
}
77+
}
78+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?php
2+
/**
3+
*
4+
* Copyright © Magento, Inc. All rights reserved.
5+
* See COPYING.txt for license details.
6+
*/
7+
8+
namespace Magento\Catalog\Controller\Product;
9+
10+
use Magento\Framework\App\Action\HttpPostActionInterface as HttpPostActionInterface;
11+
use Magento\Framework\App\Action\HttpGetActionInterface as HttpGetActionInterface;
12+
use Magento\Framework\App\Action\Context;
13+
use Magento\Framework\View\Result\PageFactory;
14+
use Magento\Catalog\Controller\Product as ProductAction;
15+
16+
/**
17+
* View a product on storefront. Needs to be accessible by POST because of the store switching.
18+
*/
19+
class View extends ProductAction implements HttpGetActionInterface, HttpPostActionInterface
20+
{
21+
/**
22+
*
23+
*/
24+
public function execute()
25+
{
26+
throw new LocalizedException(__('%1 doesn\'t exists'));
27+
}
28+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?php
2+
/**
3+
*
4+
* Copyright © Magento, Inc. All rights reserved.
5+
* See COPYING.txt for license details.
6+
*/
7+
8+
namespace Magento\Catalog\Model\Test\SubFolder;
9+
10+
/**
11+
* Class Product
12+
*/
13+
class Product
14+
{
15+
public function execute()
16+
{
17+
// rule should find this
18+
throw new LocalizedException(__('Cant find %1 doesn\'t exists'));
19+
}
20+
}
21+
22+
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?php
2+
/**
3+
*
4+
* Copyright © Magento, Inc. All rights reserved.
5+
* See COPYING.txt for license details.
6+
*/
7+
8+
namespace Magento\Catalog\Block\Test\SubFolder;
9+
10+
11+
/**
12+
* Class Product
13+
*/
14+
class Product
15+
{
16+
public function execute()
17+
{
18+
throw new LocalizedException(__('Cant find %1 doesn\'t exists'));
19+
}
20+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?php
2+
3+
/**
4+
* Class Product
5+
*/
6+
class TestViewModel
7+
{
8+
public function execute()
9+
{
10+
throw new \Magento\Framework\Exception\LocalizedException(__('Oops'));
11+
}
12+
}
13+
14+
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?php
2+
3+
namespace Magento\Catalog\Model\Test\SubFolder;
4+
5+
class Foo
6+
{
7+
public function execute()
8+
{
9+
throw new \InvalidArgumentException(__('Oops'));
10+
}
11+
}
12+
13+
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<?php
2+
/**
3+
* Copyright © Magento. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
namespace Magento\Tests\Exceptions;
8+
9+
use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest;
10+
11+
/**
12+
* Class NamespaceUnitTest
13+
*/
14+
class LocalizedThrowUnitTest extends AbstractSniffUnitTest
15+
{
16+
/**
17+
* @inheritdoc
18+
*/
19+
public function getErrorList()
20+
{
21+
return [
22+
];
23+
}
24+
25+
/**
26+
* @inheritdoc
27+
*/
28+
public function getWarningList($testFile = '')
29+
{
30+
if ($testFile === 'LocalizedThrowUnitTest.2.inc') {
31+
return [
32+
18 => 1
33+
];
34+
}
35+
36+
return [];
37+
}
38+
}

Magento/ruleset.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,10 @@
195195
<severity>7</severity>
196196
<type>warning</type>
197197
</rule>
198+
<rule ref="Magento.Exceptions.LocalizedThrow">
199+
<severity>7</severity>
200+
<type>warning</type>
201+
</rule>
198202
<rule ref="Magento.PHP.LiteralNamespaces">
199203
<severity>7</severity>
200204
<type>warning</type>

0 commit comments

Comments
 (0)