├── .gitignore
├── .travis.yml
├── .travis
└── deploy_rsa_encrypted
├── Extdn
├── Samples
│ ├── Blocks
│ │ ├── DeprecatedFormContainerParent.php
│ │ ├── DeprecatedFormGenericParent.php
│ │ └── SetTemplateInBlock.php
│ ├── Classes
│ │ └── StrictTypes.php
│ └── Templates
│ │ └── objectmanager.phtml
├── Sniffs
│ ├── Blocks
│ │ ├── DeprecatedParentsSniff.md
│ │ ├── DeprecatedParentsSniff.php
│ │ ├── SetTemplateInBlockSniff.md
│ │ └── SetTemplateInBlockSniff.php
│ ├── Classes
│ │ ├── StrictTypesSniff.md
│ │ └── StrictTypesSniff.php
│ └── Templates
│ │ ├── TemplateObjectManagerSniff.md
│ │ └── TemplateObjectManagerSniff.php
├── Tests
│ ├── Blocks
│ │ ├── SetTemplateInBlockUnitTest.inc
│ │ └── SetTemplateInBlockUnitTest.php
│ ├── Classes
│ │ ├── StrictTypesUnitTest.1.inc
│ │ ├── StrictTypesUnitTest.2.inc
│ │ ├── StrictTypesUnitTest.3.inc
│ │ └── StrictTypesUnitTest.php
│ └── Templates
│ │ ├── TemplateObjectManagerUnitTest.1.phtml
│ │ ├── TemplateObjectManagerUnitTest.2.phtml
│ │ └── TemplateObjectManagerUnitTest.php
├── Utils
│ ├── Reflection.php
│ └── TestPattern.php
└── ruleset.xml
├── ISSUE_TEMPLATE.md
├── MEQP2
└── Sniffs
│ └── Templates
│ └── ThisInTemplateSniff.md
├── PULL_REQUEST_TEMPLATE.md
├── README.md
├── composer.json
├── docs
└── rule-documentation-template.md
├── grumphp.yml
├── phpcs.xml.dist
├── phpunit-vendor.xml
└── phpunit.xml.dist
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea
2 | .php_cs.cache
3 | /phpunit.xml
4 | /vendor
5 | /composer.lock
6 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: php
2 | php:
3 | - 7.0
4 | - 7.1
5 | - 7.2
6 | env:
7 | matrix:
8 | - COMPOSER_PREF="--prefer-lowest"
9 | - COMPOSER_PREF=""
10 | before_install:
11 | - ssh-keygen -N "" -f ~/.ssh/id_rsa
12 | # - openssl aes-256-cbc -K $encrypted_2b7e0505597a_key -iv $encrypted_2b7e0505597a_iv -in .travis/deploy_rsa_encrypted -out ~/.ssh/id_rsa -d
13 | - chmod 600 ~/.ssh/id_rsa
14 | install: composer update --no-interaction --prefer-source $COMPOSER_PREF
15 | script:
16 | - vendor/bin/phpunit
17 |
--------------------------------------------------------------------------------
/.travis/deploy_rsa_encrypted:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/extdn/extdn-phpcs/f5209244131d82be9b6b7621bf89aa95039d408b/.travis/deploy_rsa_encrypted
--------------------------------------------------------------------------------
/Extdn/Samples/Blocks/DeprecatedFormContainerParent.php:
--------------------------------------------------------------------------------
1 | setTemplate('foobar.phtml');
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/Extdn/Samples/Classes/StrictTypes.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/Extdn/Sniffs/Blocks/DeprecatedParentsSniff.md:
--------------------------------------------------------------------------------
1 | # Rule: Do not extend from deprecated block parents
2 | ## Background
3 | Some parent classes have been deprecated in Magento 2.2 and should therefore no longer be used in code:
4 | - `Magento\Backend\Block\Widget\Form\Generic`
5 | - `Magento\Backend\Block\Widget\Grid\Container`
6 |
7 | ## Reasoning
8 | Once a Block class is extending upon one of these deprecated parents, they should be refactored into something else instead. Ideally, this is a uiComponent.
9 | The main reason why a uiComponent is preferred over a regular Block-driven output, is that a uiComponent is much more extensible than Blocks.
10 |
11 | ## How it works
12 | This rule uses PHP Reflection to determine the class its parent and then checks whether the parent matches a deprecated parent.
13 |
14 | ## How to fix
15 | The Block class should ideally be removed. Instead, a uiComponent should be created instead, consisting of an XML file in the `ui_component` folder plus PHP sources.
16 |
--------------------------------------------------------------------------------
/Extdn/Sniffs/Blocks/DeprecatedParentsSniff.php:
--------------------------------------------------------------------------------
1 | getFilename());
48 | }
49 |
50 | $class = Reflection::getClass($className);
51 | $parentClass = $class->getParentClass();
52 |
53 | if (!$parentClass) {
54 | return;
55 | }
56 |
57 | foreach ($this->getDeprecatedClasses() as $deprecatedClass) {
58 | if ($parentClass->getName() !== $deprecatedClass['class']) {
59 | continue;
60 | }
61 |
62 | $warning = sprintf('Block parent "%s" is deprecated. %s', $deprecatedClass['class'], $deprecatedClass['advice']);
63 | $phpcsFile->addWarning($warning, null, 'deprecated-parent');
64 | }
65 | }
66 |
67 | /**
68 | * @return array
69 | */
70 | private function getDeprecatedClasses(): array
71 | {
72 | $url = 'https://github.com/extdn/extdn-phpcs/blob/master/Extdn/Sniffs/Blocks/DeprecatedParentsSniff.md';
73 |
74 | return [
75 | [
76 | 'class' => 'Magento\Backend\Block\Widget\Form\Generic',
77 | 'advice' => 'See '.$url
78 | ],
79 | [
80 | 'class' => 'Magento\Backend\Block\Widget\Grid\Container',
81 | 'advice' => 'See '.$url
82 | ]
83 | ];
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/Extdn/Sniffs/Blocks/SetTemplateInBlockSniff.md:
--------------------------------------------------------------------------------
1 | # Rule: Do not use setTemplate in Block classes
2 | ## Background
3 | When creating a Block class, a Block class could set its PHTML template in multiple ways: Through XML layout, through a
4 | call to `$this->setTemplate()` and through a variable `$_template`. The new design of Block classes is to configure them
5 | at constructor time, meaning that configuration options (like the template) are added using constructor arguments. This
6 | allows for the XML layout to change the template. The template in the Block class is then only defined as a default value,
7 | if the XML layout is not overriding the template: This default value is best defined via a protected variable
8 | `$_template`.
9 |
10 | ## Reasoning
11 |
12 | If `$this->setTemplate()` is used instead, this could lead to potential issues: First of all, setters are deprecated in
13 | Block classes (because constructor arguments should be preferred instead). Second, if `$this->setTemplate()` is added to
14 | the constructor *after* calling upon the parent constructor, it would undo the configuration via XML layout. Simply put:
15 | It is outdated and leads to issues quickly.
16 |
17 | ## How it works
18 | This rule checks whether a Block class uses `$this->setTemplate()`.
19 |
20 | ## How to fix
21 |
22 | If there is a match, the preferred way of optimizing your code would be as follows:
23 |
24 | class MyBlock extends Template
25 | {
26 | protected $_template = 'foobar.phtml';
27 | }
28 |
29 |
--------------------------------------------------------------------------------
/Extdn/Sniffs/Blocks/SetTemplateInBlockSniff.php:
--------------------------------------------------------------------------------
1 | setTemplate() in Block classes.';
23 |
24 | /**
25 | * @var array
26 | */
27 | public $supportedTokenizers = ['PHP'];
28 |
29 | /**
30 | * @return array|int[]
31 | */
32 | public function register()
33 | {
34 | return [T_CLASS];
35 | }
36 |
37 | /**
38 | * @param File $phpcsFile
39 | * @param int $stackPtr
40 | * @return int|void
41 | */
42 | public function process(File $phpcsFile, $stackPtr)
43 | {
44 | $tokens = $phpcsFile->getTokens();
45 |
46 | foreach ($tokens as $line => $token) {
47 | if ($this->hasTokenMatch($token) === false) {
48 | continue;
49 | }
50 |
51 | $error = $this->message . ' Found: %s';
52 | $phpcsFile->addWarning($error, $line, 'Found', $token);
53 | }
54 | }
55 |
56 | private function hasTokenMatch(array $token): bool
57 | {
58 | if ($token['content'] !== 'setTemplate') {
59 | return false;
60 | }
61 |
62 | return true;
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/Extdn/Sniffs/Classes/StrictTypesSniff.md:
--------------------------------------------------------------------------------
1 | # Rule: Add `declare(strict_types=1)` to your PHP files
2 | ## Background
3 | With PHP 7, it is possible to add type hinting to your code. However, this doesn't mean that types are actually enforced, unless strict typing is
4 | enabled by adding `declare(strict_types=1)` to the top of each PHP file.
5 |
6 | ## Reasoning
7 | PHP code becomes more robust when type hinting (argument types, return types) are added. With the `declare(strict_types=1)` added, there is less
8 | chance for bugs that related to type casting.
9 |
10 | ## How it works
11 | This rule scans the source code to see whether a line `declare(strict_type=1)` occurs or not.
12 |
13 | ## How to fix
14 | Simply add a statement `declare(strict_types=1)` to the top of your files:
15 |
16 | getTokens();
45 | $hasDeclareStrictTypes = false;
46 |
47 | $declarePosition = $phpcsFile->findNext([T_DECLARE], 0);
48 | if ($declarePosition !== false) {
49 | $lineEnd = $phpcsFile->findNext([T_SEMICOLON], $declarePosition);
50 |
51 | // extract all tokens between declare and line end
52 | $tokens = \array_slice($tokens, $declarePosition, $lineEnd - 1);
53 | $hasDeclareStrictTypes = $this->hasDeclareStrictTypes($tokens);
54 | }
55 |
56 | if ($hasDeclareStrictTypes === false) {
57 | $error = $this->message . ' Not Found';
58 | $phpcsFile->addWarning($error, null, 'NotFound');
59 | }
60 | }
61 |
62 | /**
63 | * Checks has the File with strict_types=1
64 | *
65 | * @param array $tokens
66 | * @param $start
67 | * @return bool
68 | */
69 | private function hasDeclareStrictTypes(array $tokens): bool
70 | {
71 | $containsStrictType = false;
72 | $isEnabled = false;
73 |
74 | foreach ($tokens as $token) {
75 | if ($token['code'] === T_STRING && $token['content'] === 'strict_types') {
76 | $containsStrictType = true;
77 | }
78 |
79 | if ($token['code'] === T_LNUMBER && $token['content'] === '1') {
80 | $isEnabled = true;
81 | }
82 | }
83 |
84 | return $containsStrictType && $isEnabled;
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/Extdn/Sniffs/Templates/TemplateObjectManagerSniff.md:
--------------------------------------------------------------------------------
1 | # Rule: Do not use the object manager in templates
2 | ## Background
3 | The Object Manager is responsible to create concrete objects for a required interface, and to generate code e.g. for adding plugins, factories, proxies.
4 | It is used transparently by requesting a class/interface name as constructor dependency or in layout XML.
5 |
6 | You can use it directly with `ObjectManager::getInstance()->get(SomeInterface::class)` and `ObjectManager::getInstance()->create(SomeInterface::class)`, but this is not encouraged.
7 |
8 | ## Reasoning
9 | Magento offers an extensive system for dependency injection which allows us to access and create objects. It also makes it
10 | very clear, which classes or interfaces are needed by a particular piece of code and forces the developer to re-evaluate
11 | the design if there are too many.
12 |
13 | This dependency injection system uses the object manager, but it is an implementation detail that should stay hidden.
14 | Bypassing this system leads to hidden dependencies and potentially to too many of them.
15 |
16 | Besides, for separation of appearance and logic, a template should contain as little and uncomplex PHP code as possible.
17 |
18 | ## How it works
19 | For all PHTML files, the sniff looks for string tokens "ObjectManager".
20 |
21 | ## How to fix
22 | Given, your template contains code like this:
23 |
24 | ```php
25 | get(\Choo\Choo::class);
27 | ```
28 |
29 | 1. if the template is accompanied by a custom block, you can add the dependency to the block:
30 |
31 | ```php
32 | choo = $choo;
45 | }
46 |
47 | public function getChoo(): Choo\Choo
48 | {
49 | return $this->choo;
50 | }
51 |
52 | }
53 | ```
54 |
55 | and change the template to
56 |
57 | ```php
58 | getChoo();
60 | ```
61 | 2. Starting with Magento 2.2, **view models** are considered a better alternative to blocks. Add a view model, or use an existing one,
62 | and add the dependency there:
63 |
64 | ```php
65 | choo = $choo;
78 | }
79 |
80 | public function getChoo(): Choo\Choo
81 | {
82 | return $this->choo;
83 | }
84 |
85 | }
86 | ```
87 |
88 | The view model is added to the block via layout XML:
89 |
90 | ```xml
91 |
92 |
93 | Extdn\Example\TheViewModel
94 |
95 |
96 | ```
97 |
98 | and can be used in the template like this:
99 |
100 | ```php
101 | getData('the_view_model');
103 | $choo = $theViewModel->getChoo();
104 | ```
105 |
--------------------------------------------------------------------------------
/Extdn/Sniffs/Templates/TemplateObjectManagerSniff.php:
--------------------------------------------------------------------------------
1 | getTokens();
41 | $fileName = $phpcsFile->getFileName();
42 | $extension = substr($fileName, strrpos($fileName, '.'));
43 |
44 | if (\in_array($extension, $this->templateExtensionList, false) === false) {
45 | return;
46 | }
47 |
48 | foreach ($tokens as $line => $token) {
49 | if ($this->hasTokenMatch($token) === false) {
50 | continue;
51 | }
52 |
53 | $error = $this->message . ' Found: %s';
54 | $phpcsFile->addError($error, $line, 'Found', $token);
55 | }
56 | }
57 |
58 |
59 | public function hasTokenMatch($token)
60 | {
61 | if ($token['content'] !== 'ObjectManager') {
62 | return false;
63 | }
64 |
65 | return true;
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/Extdn/Tests/Blocks/SetTemplateInBlockUnitTest.inc:
--------------------------------------------------------------------------------
1 | setTemplate('foobar.phtml');
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/Extdn/Tests/Blocks/SetTemplateInBlockUnitTest.php:
--------------------------------------------------------------------------------
1 | 1];
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/Extdn/Tests/Classes/StrictTypesUnitTest.1.inc:
--------------------------------------------------------------------------------
1 | 1];
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/Extdn/Tests/Templates/TemplateObjectManagerUnitTest.1.phtml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
--------------------------------------------------------------------------------
/Extdn/Tests/Templates/TemplateObjectManagerUnitTest.2.phtml:
--------------------------------------------------------------------------------
1 | get(\Magento\Customer\Model\Session::class);
--------------------------------------------------------------------------------
/Extdn/Tests/Templates/TemplateObjectManagerUnitTest.php:
--------------------------------------------------------------------------------
1 | 1];
20 | }
21 |
22 | /**
23 | * @inheritdoc
24 | */
25 | protected function getWarningList()
26 | {
27 | return [];
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/Extdn/Utils/Reflection.php:
--------------------------------------------------------------------------------
1 | getConstructor();
38 | if (empty($constructor)) {
39 | return [];
40 | }
41 |
42 | $parameters = $constructor->getParameters();
43 | if (empty($parameters)) {
44 | return [];
45 | }
46 |
47 | $dependencyClasses = [];
48 | foreach ($parameters as $parameter) {
49 | $dependencyClass = $parameter->getClass();
50 | if (empty($dependencyClass)) {
51 | continue;
52 | }
53 |
54 | $dependencyClasses[] = $dependencyClass;
55 | }
56 |
57 | return $dependencyClasses;
58 |
59 | } catch (ReflectionException $reflectionException) {
60 | return [];
61 | }
62 | }
63 |
64 | /**
65 | * @param File $phpcsFile
66 | *
67 | * @return string
68 | */
69 | static public function findClassName(File $phpcsFile): string
70 | {
71 | $tokens = $phpcsFile->getTokens();
72 |
73 | $namespaceParts = [];
74 | $namespaceFound = false;
75 | $className = '';
76 | $classFound = false;
77 |
78 | foreach ($tokens as $token) {
79 | if (!is_array($token)) {
80 | continue;
81 | }
82 |
83 | if ($token['type'] == 'T_NAMESPACE') {
84 | $namespaceFound = true;
85 | continue;
86 | } else if ($namespaceFound && $token['type'] == 'T_STRING') {
87 | $namespaceParts[] = $token['content'];
88 | continue;
89 | } else if ($namespaceFound && $token['type'] == 'T_SEMICOLON') {
90 | $namespaceFound = false;
91 | continue;
92 | }
93 |
94 | if ($token['type'] == 'T_CLASS') {
95 | $classFound = true;
96 | continue;
97 | } else if ($classFound && $token['type'] == 'T_STRING') {
98 | $className = $token['content'];
99 | $classFound = false;
100 | continue;
101 | }
102 | }
103 |
104 | if (!$className) {
105 | return '';
106 | }
107 |
108 | $className = implode('\\', $namespaceParts) . "\\$className";
109 |
110 | return $className;
111 | }
112 | }
113 |
--------------------------------------------------------------------------------
/Extdn/Utils/TestPattern.php:
--------------------------------------------------------------------------------
1 |
2 |
3 | Magento 2 Additional Rules by ExtDN
4 |
5 |
6 |
7 | *.php
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/ISSUE_TEMPLATE.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | ### Rule
5 |
6 |
7 | ### Reason
8 |
9 |
10 | ### Implementation
11 |
12 |
--------------------------------------------------------------------------------
/MEQP2/Sniffs/Templates/ThisInTemplateSniff.md:
--------------------------------------------------------------------------------
1 | # Rule: Do not use `$this` in templates
2 | ## Background
3 | In PHTML templates, the current block is available as `$this` and `$block`. The alternative with `$this` has been deprecated and should not be used anymore.
4 |
5 | ## Reasoning
6 | `$this` in templates is a legacy from Magento 1. It still works, however this can change any time, should templates and blocks be further decoupled. That's why for new code you should always use `$block` and restrict it to public methods.
7 |
8 | ## How it works
9 | Any occurence of `$this` in PHTML files (via file pattern in ruleset.xml) raises a warning.
10 |
11 | ## How to fix
12 |
13 | Replace `$this` with `$block`. If you use private or protected methods, make them public.
--------------------------------------------------------------------------------
/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | ### Description
2 |
3 |
4 | ### Related issues
5 |
6 | 1. extdn/extdn-phpcs#: Issue title
7 | 2. ...
8 |
9 |
10 | ### Sniff checklist
11 | - [ ] Sniff is accompanied by unit test
12 | - [ ] Sniff is documented using the [documentation template](docs/rule-documentation-template.md) (FooSniff.md next to FooSniff.php)
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ExtDN PHP_CodeSniffer rules for Magento 2
2 |
3 | [](https://travis-ci.org/extdn/extdn-phpcs)
4 |
5 | ### Introduction
6 | There are already many PHP CodeSniffer rules out there to aid in Magento 2 development:
7 | - Magento core ruleset (in folder `dev/tests/static/framework/Magento`)
8 | - [Magento Extension Quality Program](https://github.com/magento/marketplace-eqp) (in short: MEQP)
9 | - [Magento Expert Consultancy Group](https://github.com/magento-ecg/coding-standard) (in short: ECG)
10 | - PSR-1, PSR-2, possibly PSR-12
11 |
12 | However, some best practices still need to be integrated and/or some rules do need to be improved. This
13 | repository forms an effort to come up with more advanced rulesets than there currently are. Additionally, one of the underlying goals is to create rules that fit Magento core, Magento third party extensions and Magento implements, while they all have different needs.
14 |
15 | ### Usage
16 | To install this package, go to your Magento 2 root and use the following:
17 |
18 | composer require extdn/phpcs:dev-master
19 |
20 | If this fails because the dependency with `magento/marketplace-eqp` fails to load, first add the EQP repo to your configuration and then repeat:
21 |
22 | composer config repositories.magento-marketplace-eqp vcs https://github.com/magento/marketplace-eqp
23 | composer require magento/marketplace-eqp:dev-master
24 | composer require extdn/phpcs:dev-master
25 |
26 | Once installed, you can run PHPCS from the command-line to analyse your code `XYZ`:
27 |
28 | vendor/bin/phpcs --standard=./vendor/extdn/phpcs/Extdn app/code/XYZ
29 | vendor/bin/phpcs --standard=./vendor/extdn/phpcs/Extdn vendor/XYZ
30 |
31 | If you have a Composer Installer Plugin for PHPCS coding standards (such as https://github.com/Dealerdirect/phpcodesniffer-composer-installer) configured in the project, you can refer to this standard simply by its name:
32 |
33 | vendor/bin/phpcs --standard=Extdn app/code/XYZ
34 | vendor/bin/phpcs --standard=Extdn vendor/XYZ
35 |
36 | ## Where to contribute
37 | We need help in the following areas:
38 | - Documentation of existing EQP rules (where each EQP rule could be included in this repository its `ruleset.xml`)
39 | - Creation of new PHPCS rules (see below **How to contribute**)
40 | - Braindumps on where PHPCS lacks and other tools might come in more handy (PhpStan, Phan)
41 | - Discussions on new rules (through periodic hangouts or discussions per GitHub Issue)
42 |
43 | Please note that you are also welcome to contribute to the Magento rulesets directly (core, MEQP, ECG - see links above). Likewise, we will try to get ExtDN rules into Magento rulesets as well, which is part of this ExtDN project.
44 |
45 | ## How to contribute
46 | Any contribution is welcome. However, don't start coding just yet. Make sure first that the work is worth the effort.
47 |
48 | 1) Add a new issue under **Issues** to address new rulesets that are needed or report other issues.
49 |
50 | 2) Once the creation of the new rule has been accepted by adding a label `Accepted` under **Issues**, we're good to go.
51 |
52 | 3) If a similar rule already exists in the core or MEQP or ECG, simply try to include this rule within the ExtDN ruleset.
53 |
54 | 4) If no rule exists yet, let's create it. As an example, you can use the `SetTemplateInBlockSniff` within the folder `Extdn/Sniffs/Blocks`. It can be tested upon a sample file under `Extdn/Samples/Blocks`:
55 |
56 | ```bash
57 | vendor/bin/phpcs --standard=./vendor/extdn/phpcs/Extdn vendor/extdn/phpcs/Extdn/Samples
58 | ```
59 |
60 | 5) Once this all works, feel free to create a Pull Request (PR) including the addition of this rule to the `ruleset.xml` file.
61 |
62 |
63 | ### Using labels with GitHub issues
64 | Some important labels, used for Github issues:
65 |
66 | - `accepted`: The rule is accepted by extdn. If nobody claimed it yet, you may start working on it
67 | - `experimental`: The rule can be implemented as well, but we will try it out with a low severity first before integrating it into the official ruleset
68 | - `non-PHPCS`: The rule is not feasibly implementable with phpcs, will need additional tools. We keep it for later.
69 | - `organizational`: Non-code related issues
70 | - `on agenda of hangout`: The rule/issue will be discussed in the next community hangout
71 |
72 | ## How to create a Sniffer Rule
73 | We recommend to get started by creating a couple of sniffs for your own. The official [PHPCS wiki](https://github.com/squizlabs/PHP_CodeSniffer/wiki) already gives good information. Likewise, the other sniffs in our repos (and the repos of Magento) will give lots of samples anyway.
74 |
75 | ## Testing
76 | All rules should be accompanied with tests.
77 |
78 | ### Within a Magento installation
79 | To run the sniff unit tests from a main repository, where the rules are installed via `composer`, first configure `phpcs` to find the rules:
80 |
81 | vendor/bin/phpcs --config-set installed_paths vendor/extdn/phpcs/Extdn,vendor/magento/marketplace-eqp/MEQP2
82 |
83 | Then tests can be run like this:
84 |
85 | phpunit -c vendor/extdn/phpcs/phpunit-vendor.xml vendor/extdn/phpcs/Extdn/Tests
86 |
87 | ### In a standalone installation
88 | If you have cloned this GitHub repository on its own for development, use `composer` to install things and run the tests:
89 |
90 | composer install
91 | composer test
92 |
93 | Each `Test.php` class should be accompanied by a `Test.inc` file to allow for unit testing based upon the PHPCS parent class `AbstractSniffUnitTest`. Make sure to include a `Test.md` Markdown description which addresses the issue at hand, explains what the rule check for and then also suggests the improvement to be made.
94 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "extdn/phpcs",
3 | "description": "A set of PHP_CodeSniffer rules and sniffs.",
4 | "homepage": "https://github.com/extdn/extdn-phpcs",
5 | "license": "MIT",
6 | "type": "phpcodesniffer-standard",
7 | "authors": [
8 | {
9 | "name": "ExtDN",
10 | "homepage": "https://extdn.org/",
11 | "role": "Maintainer"
12 | }
13 | ],
14 | "require": {
15 | "php": ">=7.0.0",
16 | "squizlabs/php_codesniffer": "^3.1.0",
17 | "magento/marketplace-eqp": "dev-master"
18 | },
19 | "autoload": {
20 | "psr-4": {
21 | "Extdn\\": "Extdn/"
22 | }
23 | },
24 | "require-dev": {
25 | "phpunit/phpunit": "^6.0",
26 | "phpro/grumphp": "^0.14.0",
27 | "friendsofphp/php-cs-fixer": "^2.11",
28 | "infection/infection": "^0.8.2",
29 | "jakub-onderka/php-parallel-lint": "^1.0",
30 | "phpstan/phpstan": "^0.9.2"
31 | },
32 | "scripts": {
33 | "post-install-cmd": "\"vendor/bin/phpcs\" --config-set installed_paths ../../..",
34 | "post-update-cmd": "\"vendor/bin/phpcs\" --config-set installed_paths ../../..",
35 | "test": "vendor/bin/phpunit"
36 | },
37 | "repositories": {
38 | "meqp": {
39 | "type": "git",
40 | "url": "https://github.com/magento/marketplace-eqp.git"
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/docs/rule-documentation-template.md:
--------------------------------------------------------------------------------
1 | # Rule: The headline contains the rule title
2 | ## Background
3 | A paragraph that briefly describes the context of the rule.
4 |
5 | ## Reasoning
6 | Explanation why the rule has been created. The reader should understand the reasons.
7 |
8 | ## How it works
9 | Technical details, what exactly is checked. This may help determine false positives.
10 |
11 | ## How to fix
12 | Description how to resolve a found violation. Should contain example code and explain why it is a better alternative.
--------------------------------------------------------------------------------
/grumphp.yml:
--------------------------------------------------------------------------------
1 | parameters:
2 | git_dir: .
3 | bin_dir: vendor/bin
4 | tasks:
5 | # infection: ~
6 | phpcs: ~
7 | phplint: ~
8 | phpstan:
9 | autoload_file: vendor/squizlabs/php_codesniffer/autoload.php
10 | ignore_patterns: [Extdn/Samples]
11 | phpunit: ~
12 | phpversion: ~
13 | xmllint: ~
14 | yamllint: ~
15 |
--------------------------------------------------------------------------------
/phpcs.xml.dist:
--------------------------------------------------------------------------------
1 |
2 |
3 | The coding standard for PHP_CodeSniffer itself.
4 |
5 | Extdn
6 |
7 | */Standards/*/Tests/*\.(inc|css|js)
8 | Extdn/Samples/*
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 | error
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/phpunit-vendor.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | ../../../vendor/squizlabs/php_codesniffer/tests/Standards/AllSniffs.php
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/phpunit.xml.dist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | vendor/squizlabs/php_codesniffer/tests/Standards/AllSniffs.php
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------