-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #38 from akeneo/rule-builder
Introduce rule builder and enhance documentation
- Loading branch information
Showing
5 changed files
with
222 additions
and
129 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 | ||
<?php | ||
|
||
$finder = new \Symfony\Component\Finder\Finder(); | ||
$finder | ||
->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 | ||
<?php | ||
|
||
$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, | ||
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 | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
<?php | ||
|
||
namespace spec\Akeneo\CouplingDetector; | ||
|
||
use Akeneo\CouplingDetector\Domain\Rule; | ||
use Akeneo\CouplingDetector\Domain\RuleInterface; | ||
use Akeneo\CouplingDetector\RuleBuilder; | ||
use PhpSpec\ObjectBehavior; | ||
|
||
class RuleBuilderSpec extends ObjectBehavior | ||
{ | ||
function it_is_initializable() | ||
{ | ||
$this->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(); | ||
}, | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
<?php | ||
|
||
namespace Akeneo\CouplingDetector; | ||
|
||
use Akeneo\CouplingDetector\Domain\Rule; | ||
use Akeneo\CouplingDetector\Domain\RuleInterface; | ||
|
||
/** | ||
* Builds a rule simply. Usage examples: | ||
* | ||
* $builder = new RuleBuilder(); | ||
* $rule1 = $builder->forbids(['foo', 'bar'])->in('baz'); | ||
* $rule2 = $builder->discouraged(['toto'])->in('titi'); | ||
* $rule3 = $builder->only(['tik'])->in('tak'); | ||
* | ||
* @author Julien Janvier <[email protected]> | ||
* @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); | ||
} | ||
} |