From 7d795b70052c85f453d5005338679d08c6df4b84 Mon Sep 17 00:00:00 2001 From: "Julien Janvier (jjanvier)" Date: Wed, 28 Mar 2018 15:38:09 +0200 Subject: [PATCH 1/7] Introduce a simple rule builder --- README.md | 22 +++--- .../CouplingDetector/RuleBuilderSpec.php | 72 +++++++++++++++++++ src/Akeneo/CouplingDetector/RuleBuilder.php | 62 ++++++++++++++++ 3 files changed, 145 insertions(+), 11 deletions(-) create mode 100644 spec/Akeneo/CouplingDetector/RuleBuilderSpec.php create mode 100644 src/Akeneo/CouplingDetector/RuleBuilder.php diff --git a/README.md b/README.md index 6dca5a3..788a8f1 100644 --- a/README.md +++ b/README.md @@ -56,8 +56,6 @@ The detect command detects coupling problems for a given file or directory depen ```php name('*.php') ->notPath('foo/bar/'); + $builder = new \Akeneo\CouplingDetector\RuleBuilder(); + $rules = [ - new Rule('foo', ['bar', 'baz'], RuleInterface::TYPE_FORBIDDEN), - new Rule('zoo', ['too'], RuleInterface::TYPE_DISCOURAGED), - new Rule('bli', ['bla', 'ble', 'blu'], RuleInterface::TYPE_ONLY), + $builder->forbids(['bar', 'baz'])->in('foo'), + $builder->discourages(['too'])->in('zoo'), + $builder->only(['bla', 'ble', 'blu'])->in('bli'), ]; return new \Akeneo\CouplingDetector\Configuration\Configuration($rules, $finder); @@ -80,13 +80,13 @@ The detect command detects coupling problems for a given file or directory depen ```php forbids(['bar', 'baz'])->in('foo'), + $builder->discourages(['too'])->in('zoo'), + $builder->only(['bla', 'ble', 'blu'])->in('bli'), ]; return new \Akeneo\CouplingDetector\Configuration\Configuration( diff --git a/spec/Akeneo/CouplingDetector/RuleBuilderSpec.php b/spec/Akeneo/CouplingDetector/RuleBuilderSpec.php new file mode 100644 index 0000000..d742e30 --- /dev/null +++ b/spec/Akeneo/CouplingDetector/RuleBuilderSpec.php @@ -0,0 +1,72 @@ +shouldHaveType(RuleBuilder::class); + } + + function it_does_not_create_a_rule_without_constraints() + { + $this + ->shouldThrow(new \Exception('Can not create a rule without any requirement defined previously.')) + ->during('in', ['baz']); + } + + function it_chains_the_methods_for_building_a_rule() + { + $this->forbids(['foo', 'bar'])->shouldReturn($this); + $this->only(['foo', 'bar'])->shouldReturn($this); + $this->discourages(['foo', 'bar'])->shouldReturn($this); + } + + function it_creates_a_forbidden_rule() + { + $this->forbids(['foo', 'bar']); + $actual = $this->in('baz'); + + $expected = new Rule('baz', ['foo', 'bar'], RuleInterface::TYPE_FORBIDDEN); + $actual->shouldBeAnInstanceOf(RuleInterface::class); + $actual->shouldBeLikeExpectedRule($expected); + } + + function it_creates_an_only_rule() + { + $this->only(['foo', 'bar']); + $actual = $this->in('baz'); + + $expected = new Rule('baz', ['foo', 'bar'], RuleInterface::TYPE_ONLY); + $actual->shouldBeAnInstanceOf(RuleInterface::class); + $actual->shouldBeLikeExpectedRule($expected); + } + + function it_creates_a_discouraged_rule() + { + $this->discourages(['foo', 'bar']); + $actual = $this->in('baz'); + + $expected = new Rule('baz', ['foo', 'bar'], RuleInterface::TYPE_DISCOURAGED); + $actual->shouldBeAnInstanceOf(RuleInterface::class); + $actual->shouldBeLikeExpectedRule($expected); + } + + public function getMatchers(): array + { + return array( + 'beLikeExpectedRule' => function ($actual, $expected) { + return + $actual->getSubject() === $expected->getSubject() && + $actual->getRequirements() === $expected->getRequirements() && + $actual->getType() === $expected->getType(); + }, + ); + } +} diff --git a/src/Akeneo/CouplingDetector/RuleBuilder.php b/src/Akeneo/CouplingDetector/RuleBuilder.php new file mode 100644 index 0000000..0df5791 --- /dev/null +++ b/src/Akeneo/CouplingDetector/RuleBuilder.php @@ -0,0 +1,62 @@ +forbids(['foo', 'bar'])->in('baz'); + * $rule2 = $builder->discouraged(['toto'])->in('titi'); + * $rule3 = $builder->only(['tik'])->in('tak'); + * + * @author Julien Janvier + * @license http://opensource.org/licenses/MIT MIT + */ +class RuleBuilder +{ + /** @var array */ + private $requirements = []; + + /** @var string */ + private $type; + + public function forbids(array $requirements): RuleBuilder + { + $this->requirements = $requirements; + $this->type = RuleInterface::TYPE_FORBIDDEN; + + return $this; + } + + public function only(array $requirements): RuleBuilder + { + $this->requirements = $requirements; + $this->type = RuleInterface::TYPE_ONLY; + + return $this; } + + public function discourages(array $requirements): RuleBuilder + { + $this->requirements = $requirements; + $this->type = RuleInterface::TYPE_DISCOURAGED; + + return $this; + } + + public function in(string $subject): RuleInterface + { + if (empty($this->requirements)) { + throw new \Exception('Can not create a rule without any requirement defined previously.'); + } + + if (null === $this->type) { + throw new \Exception('Can not create a rule without any type defined previously.'); + } + + return new Rule($subject, $this->requirements, $this->type); + } +} From f8b19349499b95c202a62890065afee4c4579043 Mon Sep 17 00:00:00 2001 From: "Julien Janvier (jjanvier)" Date: Wed, 28 Mar 2018 15:47:08 +0200 Subject: [PATCH 2/7] Fix typo in doc --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 788a8f1..4cfa7be 100644 --- a/README.md +++ b/README.md @@ -106,5 +106,5 @@ The detect command detects coupling problems for a given file or directory depen With the --format option you can specify the output format: ```bash - php %command.full_name% /path/to/dir --format=dot + php bin/php-coupling-detector /path/to/dir --format=dot ``` From b5c1f94c485747746556aea919697619747eae39 Mon Sep 17 00:00:00 2001 From: "Julien Janvier (jjanvier)" Date: Wed, 28 Mar 2018 16:04:21 +0200 Subject: [PATCH 3/7] Fix default finder documentation --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4cfa7be..1e5a8b1 100644 --- a/README.md +++ b/README.md @@ -91,7 +91,7 @@ The detect command detects coupling problems for a given file or directory depen return new \Akeneo\CouplingDetector\Configuration\Configuration( $rules, - \Akeneo\CouplingDetector\Configuration\DefaultFinder + new \Akeneo\CouplingDetector\Configuration\DefaultFinder() ); ?> From 0bc6145aca08069d38c894b12c33f2f875942c47 Mon Sep 17 00:00:00 2001 From: "Julien Janvier (jjanvier)" Date: Wed, 28 Mar 2018 16:06:02 +0200 Subject: [PATCH 4/7] Fix own configuration file in the doc --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 1e5a8b1..8cefe83 100644 --- a/README.md +++ b/README.md @@ -100,7 +100,7 @@ The detect command detects coupling problems for a given file or directory depen With the ``--config-file`` option you can specify the path to the ``.php_cd`` file: ```bash - php bin/php-coupling-detector detect /path/to/dir --config-file=/path/to/my/configuration.php_cd + php bin/php-coupling-detector detect /path/to/dir --config-file=/path/to/my/own_configuration_file.php ``` With the --format option you can specify the output format: From cc6ffb43035787fb6c4c1e12805990555502915d Mon Sep 17 00:00:00 2001 From: "Julien Janvier (jjanvier)" Date: Wed, 28 Mar 2018 16:12:09 +0200 Subject: [PATCH 5/7] Fix PHP required version --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8cefe83..cb6c87c 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ At the moment, 3 types of rules are supported: ## Requirements -PHP needs to be a minimum version of PHP 5.3.6. +PHP needs to be a minimum version of PHP 7.1 ## Installation From 7a9dad1598eec7f6535f4ea2f62573f9078172b1 Mon Sep 17 00:00:00 2001 From: "Julien Janvier (jjanvier)" Date: Wed, 28 Mar 2018 16:20:18 +0200 Subject: [PATCH 6/7] Extract usage of the command from README --- README.md | 71 +------------------------------------------------- doc/DETECT.md | 72 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+), 70 deletions(-) create mode 100644 doc/DETECT.md diff --git a/README.md b/README.md index cb6c87c..e3a87ae 100644 --- a/README.md +++ b/README.md @@ -38,73 +38,4 @@ you're good to go: ## Usage -The detect command detects coupling problems for a given file or directory depending on the - coupling rules that have been defined: - -```bash - php bin/php-coupling-detector detect /path/to/dir - php bin/php-coupling-detector detect /path/to/file -``` - - The exit status of the detect command can be: 0 if no violations have been raised, 10 in case of - warnings and 99 in case of errors. - - You can save the configuration in a ``.php_cd`` file in the root directory of - your project. The file must return an instance of ``Akeneo\CouplingDetector\Configuration\Configuration``, - which lets you configure the rules and the directories that need to be analyzed. - Here is an example below: - - ```php - files() - ->name('*.php') - ->notPath('foo/bar/'); - - $builder = new \Akeneo\CouplingDetector\RuleBuilder(); - - $rules = [ - $builder->forbids(['bar', 'baz'])->in('foo'), - $builder->discourages(['too'])->in('zoo'), - $builder->only(['bla', 'ble', 'blu'])->in('bli'), - ]; - - return new \Akeneo\CouplingDetector\Configuration\Configuration($rules, $finder); - ?> -``` - - You can also use the default finder implementation if you want to analyse all the PHP files - of your directory: - - ```php - forbids(['bar', 'baz'])->in('foo'), - $builder->discourages(['too'])->in('zoo'), - $builder->only(['bla', 'ble', 'blu'])->in('bli'), - ]; - - return new \Akeneo\CouplingDetector\Configuration\Configuration( - $rules, - new \Akeneo\CouplingDetector\Configuration\DefaultFinder() - ); - ?> - - ``` - - With the ``--config-file`` option you can specify the path to the ``.php_cd`` file: - -```bash - php bin/php-coupling-detector detect /path/to/dir --config-file=/path/to/my/own_configuration_file.php -``` - -With the --format option you can specify the output format: - -```bash - php bin/php-coupling-detector /path/to/dir --format=dot -``` +To discover how to use this tool, please read the usage of the [detect command](doc/DETECT.md). diff --git a/doc/DETECT.md b/doc/DETECT.md new file mode 100644 index 0000000..a94c582 --- /dev/null +++ b/doc/DETECT.md @@ -0,0 +1,72 @@ +# Detect coupling problems + +The detect command detects coupling problems for a given file or directory depending on the + coupling rules that have been defined: + +```bash + php bin/php-coupling-detector detect /path/to/directory + php bin/php-coupling-detector detect /path/to/file +``` + + The exit status of the detect command can be: 0 if no violations have been raised, 10 in case of + warnings and 99 in case of errors. + + You can save the configuration in a ``.php_cd`` file in the root directory of + your project. The file must return an instance of ``Akeneo\CouplingDetector\Configuration\Configuration``, + which lets you configure the rules and the directories that need to be analyzed. + Here is an example below: + + ```php + files() + ->name('*.php') + ->notPath('foo/bar/'); + + $builder = new \Akeneo\CouplingDetector\RuleBuilder(); + + $rules = [ + $builder->forbids(['bar', 'baz'])->in('foo'), + $builder->discourages(['too'])->in('zoo'), + $builder->only(['bla', 'ble', 'blu'])->in('bli'), + ]; + + return new \Akeneo\CouplingDetector\Configuration\Configuration($rules, $finder); + ?> +``` + + You can also use the default finder implementation if you want to analyse all the PHP files + of your directory: + + ```php + forbids(['bar', 'baz'])->in('foo'), + $builder->discourages(['too'])->in('zoo'), + $builder->only(['bla', 'ble', 'blu'])->in('bli'), + ]; + + return new \Akeneo\CouplingDetector\Configuration\Configuration( + $rules, + new \Akeneo\CouplingDetector\Configuration\DefaultFinder() + ); + ?> + + ``` + + With the ``--config-file`` option you can specify the path to the ``.php_cd`` file: + +```bash + php bin/php-coupling-detector detect /path/to/dir --config-file=/path/to/my/own_configuration_file.php +``` + +With the ``--format`` option you can specify the output format: + +```bash + php bin/php-coupling-detector /path/to/dir --format=dot +``` From 33304694d9375619a372386b4d15416ce158aec9 Mon Sep 17 00:00:00 2001 From: "Julien Janvier (jjanvier)" Date: Wed, 28 Mar 2018 17:04:05 +0200 Subject: [PATCH 7/7] Use the documentation in the help of the detect commmand --- doc/DETECT.md | 6 +- .../Console/Command/DetectCommand.php | 72 ++++--------------- 2 files changed, 17 insertions(+), 61 deletions(-) diff --git a/doc/DETECT.md b/doc/DETECT.md index a94c582..70e2da2 100644 --- a/doc/DETECT.md +++ b/doc/DETECT.md @@ -1,6 +1,6 @@ # Detect coupling problems -The detect command detects coupling problems for a given file or directory depending on the +The _detect_ command detects coupling problems for a given file or directory depending on the coupling rules that have been defined: ```bash @@ -8,8 +8,8 @@ The detect command detects coupling problems for a given file or directory depen php bin/php-coupling-detector detect /path/to/file ``` - The exit status of the detect command can be: 0 if no violations have been raised, 10 in case of - warnings and 99 in case of errors. + The exit status of the _detect_ command can be: ``0`` if no violations have been raised, ``10`` in case of + warnings and ``99`` in case of errors. You can save the configuration in a ``.php_cd`` file in the root directory of your project. The file must return an instance of ``Akeneo\CouplingDetector\Configuration\Configuration``, diff --git a/src/Akeneo/CouplingDetector/Console/Command/DetectCommand.php b/src/Akeneo/CouplingDetector/Console/Command/DetectCommand.php index 4bc62df..7162b9b 100644 --- a/src/Akeneo/CouplingDetector/Console/Command/DetectCommand.php +++ b/src/Akeneo/CouplingDetector/Console/Command/DetectCommand.php @@ -60,64 +60,7 @@ protected function configure() ) ) ->setDescription('Detect coupling rules') - ->setHelp( - <<%command.name% command detects coupling problems for a given file or directory depending on the -coupling rules that have been defined: - php %command.full_name% /path/to/dir - php %command.full_name% /path/to/file - -The exit status of the %command.name% command can be: 0 if no rules have been raised, 10 in case of -warnings and 99 in case of errors. - -You can save the configuration in a .php_cd file in the root directory of -your project. The file must return an instance of ``Akeneo\CouplingDetector\Configuration\Configuration``, -which lets you configure the rules and the directories that need to be analyzed. -Here is an example below: - files() - ->name('*.php') - ->notPath('foo/bar/'); - - \$rules = [ - new Rule('foo', ['bar', 'baz'], RuleInterface::TYPE_FORBIDDEN), - new Rule('zoo', ['too'], RuleInterface::TYPE_DISCOURAGED), - new Rule('bli', ['bla', 'ble', 'blu'], RuleInterface::TYPE_ONLY), - ]; - - return new \Akeneo\CouplingDetector\Configuration\Configuration(\$rules, \$finder); - ?> - -You can also use the default finder implementation if you want to analyse all the PHP files -of your directory: - - -With the --config-file option you can specify the path to the .php_cd file: - php %command.full_name% /path/to/dir --config-file=/path/to/my/configuration.php_cd - -With the --format option you can specify the output format: - php %command.full_name% /path/to/dir --format=dot -HELP - ) + ->setHelp($this->loadHelpContent()) ; } @@ -245,4 +188,17 @@ private function initEventDispatcher(OutputInterface $output, $formatterName, $v return $eventDispatcher; } + + private function loadHelpContent(): string + { + $content = file_get_contents(__DIR__ . '/../../../../../doc/DETECT.md'); + $content = preg_replace('/^.+\n/', '', $content); + $content = str_replace('bin/php-coupling-detector', '%command.full_name%', $content); + $content = str_replace('_detect_ command', '%command.name% command', $content); + $content = preg_replace('/```bash(.*?)```/s', '$1', $content); + $content = preg_replace('/```php(.*?)```/s', '$1', $content); + $content = preg_replace('/``(.*?)``/s', '$1', $content); + + return $content; + } }