Skip to content

Commit

Permalink
Merge pull request #10 from Lendable/merge-upstream
Browse files Browse the repository at this point in the history
  • Loading branch information
pamil authored May 29, 2024
2 parents c882099 + 55dc839 commit dd785bd
Show file tree
Hide file tree
Showing 62 changed files with 878 additions and 121 deletions.
19 changes: 19 additions & 0 deletions .github/workflows/architectural-rules.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
name: Architectural test

on:
push:

jobs:
phparkitect:
name: PHPArkitect

runs-on: ubuntu-latest

steps:
- name: "Checkout"
uses: actions/checkout@v2

- name: PHPArkitect
uses: docker://phparkitect/arkitect-github-actions:latest
with:
args: check
4 changes: 2 additions & 2 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@ jobs:
build:
runs-on: "ubuntu-22.04"
strategy:
fail-fast: false
matrix:
php-versions: [ '7.1', '7.2', '7.3', '7.4', '8.0', '8.1', '8.2']
php-versions: [ '7.1', '7.2', '7.3', '7.4', '8.0', '8.1', '8.2', '8.3']
coverage-driver: [ 'pcov' ]

steps:
Expand Down Expand Up @@ -55,4 +56,3 @@ jobs:
uses: codecov/codecov-action@v1
with:
token: ${{ secrets.CODECOV_TOKEN }}

14 changes: 10 additions & 4 deletions CONTRIBUTORS.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,30 @@ Shout out to our top contributors!

- [AlessandroMinoccheri](https://api.github.com/users/AlessandroMinoccheri)
- [fain182](https://api.github.com/users/fain182)
- [micheleorselli](https://api.github.com/users/micheleorselli)
- [pfazzi](https://api.github.com/users/pfazzi)
- [github-actions[bot]](https://api.github.com/users/github-actions%5Bbot%5D)
- [ricfio](https://api.github.com/users/ricfio)
- [micheleorselli](https://api.github.com/users/micheleorselli)
- [sebastianstucke87](https://api.github.com/users/sebastianstucke87)
- [ricfio](https://api.github.com/users/ricfio)
- [szepeviktor](https://api.github.com/users/szepeviktor)
- [JulienRAVIA](https://api.github.com/users/JulienRAVIA)
- [helyakin](https://api.github.com/users/helyakin)
- [ben-challis](https://api.github.com/users/ben-challis)
- [LuigiCardamone](https://api.github.com/users/LuigiCardamone)
- [annervisser](https://api.github.com/users/annervisser)
- [simivar](https://api.github.com/users/simivar)
- [stephpy](https://api.github.com/users/stephpy)
- [dbu](https://api.github.com/users/dbu)
- [jdomenechbLendable](https://api.github.com/users/jdomenechbLendable)
- [dbu](https://api.github.com/users/dbu)
- [stephpy](https://api.github.com/users/stephpy)
- [marmichalski](https://api.github.com/users/marmichalski)
- [hgraca](https://api.github.com/users/hgraca)
- [frankverhoeven](https://api.github.com/users/frankverhoeven)
- [hectorespert](https://api.github.com/users/hectorespert)
- [jerowork](https://api.github.com/users/jerowork)
- [jkrzefski](https://api.github.com/users/jkrzefski)
- [mloru](https://api.github.com/users/mloru)
- [nikow13](https://api.github.com/users/nikow13)
- [OskarStark](https://api.github.com/users/OskarStark)
- [smortexa](https://api.github.com/users/smortexa)
- [DonCallisto](https://api.github.com/users/DonCallisto)
- [notcgi](https://api.github.com/users/notcgi)
24 changes: 23 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,8 @@ $rules[] = Rule::allClasses()
->that(new ResideInOneOfTheseNamespaces('App\Controller'))
->should(new Extend('App\Controller\AbstractController'))
->because('we want to be sure that all controllers extend AbstractController');

You can add multiple parameters, the violation will happen when none of them match
```

### Has an attribute (requires PHP >= 8.0)
Expand Down Expand Up @@ -301,6 +303,15 @@ $rules[] = Rule::allClasses()
->because('we want to be sure that aggregates are final classes');
```

### Is readonly

```php
$rules[] = Rule::allClasses()
->that(new ResideInOneOfTheseNamespaces('App\Domain\ValueObjects'))
->should(new IsReadonly())
->because('we want to be sure that value objects are readonly classes');
```

### Is interface

```php
Expand Down Expand Up @@ -346,6 +357,15 @@ $rules[] = Rule::allClasses()
->because('we want to be sure that our adapters are not final classes');
```

### Is not readonly

```php
$rules[] = Rule::allClasses()
->that(new ResideInOneOfTheseNamespaces('App\Domain\Entity'))
->should(new IsNotReadonly())
->because('we want to be sure that there are no readonly entities');
```

### Is not interface

```php
Expand Down Expand Up @@ -380,14 +400,16 @@ $rules[] = Rule::allClasses()
->that(new ResideInOneOfTheseNamespaces('App\Controller\Admin'))
->should(new NotExtend('App\Controller\AbstractController'))
->because('we want to be sure that all admin controllers not extend AbstractController for security reasons');

You can add multiple parameters, the violation will happen when one of them match
```

### Don't have dependency outside a namespace

```php
$rules[] = Rule::allClasses()
->that(new ResideInOneOfTheseNamespaces('App\Domain'))
->should(new NotHaveDependencyOutsideNamespace('App\Domain', ['Ramsey\Uuid']))
->should(new NotHaveDependencyOutsideNamespace('App\Domain', ['Ramsey\Uuid'], true))
->because('we want protect our domain except for Ramsey\Uuid');
```

Expand Down
9 changes: 5 additions & 4 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"description": "Enforce architectural constraints in your PHP applications",
"type": "library",
"license": "MIT",
"version": "0.3.33",
"authors": [
{
"name": "Herberto Graca",
Expand All @@ -27,9 +28,9 @@
],
"require": {
"php": "^7.1|^8",
"symfony/finder": "^3.0|^4.0|^5.0|^6.0",
"symfony/event-dispatcher": "^3.0|^4.0|^5.0|^6.0",
"symfony/console": "^3.0|^4.0|^5.0|^6.0",
"symfony/finder": "^3.0|^4.0|^5.0|^6.0|^7.0",
"symfony/event-dispatcher": "^3.0|^4.0|^5.0|^6.0|^7.0",
"symfony/console": "^3.0|^4.0|^5.0|^6.0|^7.0",
"symfony/polyfill-php80": "^1.20",
"nikic/php-parser": "~4",
"webmozart/assert": "^1.9",
Expand All @@ -39,7 +40,7 @@
},
"require-dev": {
"roave/security-advisories": "dev-master",
"symfony/var-dumper": "^3.0|^4.0|^5.0|^6.0",
"symfony/var-dumper": "^3.0|^4.0|^5.0|^6.0|^7.0",
"vimeo/psalm": "^4.6",
"friendsofphp/php-cs-fixer": "^3.0",
"phpunit/phpunit": "^7.5|^9.0|^10.0",
Expand Down
10 changes: 10 additions & 0 deletions src/Analyzer/ClassDescription.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ class ClassDescription
/** @var bool */
private $final;

/** @var bool */
private $readonly;

/** @var bool */
private $abstract;

Expand Down Expand Up @@ -53,6 +56,7 @@ public function __construct(
array $interfaces,
?FullyQualifiedClassName $extends,
bool $final,
bool $readonly,
bool $abstract,
bool $interface,
bool $trait,
Expand All @@ -65,6 +69,7 @@ public function __construct(
$this->interfaces = $interfaces;
$this->extends = $extends;
$this->final = $final;
$this->readonly = $readonly;
$this->abstract = $abstract;
$this->docBlock = $docBlock;
$this->attributes = $attributes;
Expand Down Expand Up @@ -151,6 +156,11 @@ public function isFinal(): bool
return $this->final;
}

public function isReadonly(): bool
{
return $this->readonly;
}

public function isAbstract(): bool
{
return $this->abstract;
Expand Down
12 changes: 12 additions & 0 deletions src/Analyzer/ClassDescriptionBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ class ClassDescriptionBuilder
/** @var bool */
private $final = false;

/** @var bool */
private $readonly = false;

/** @var bool */
private $abstract = false;

Expand All @@ -47,6 +50,7 @@ public function clear(): void
$this->interfaces = [];
$this->extend = null;
$this->final = false;
$this->readonly = false;
$this->abstract = false;
$this->docBlock = [];
$this->attributes = [];
Expand Down Expand Up @@ -92,6 +96,13 @@ public function setFinal(bool $final): self
return $this;
}

public function setReadonly(bool $readonly): self
{
$this->readonly = $readonly;

return $this;
}

public function setAbstract(bool $abstract): self
{
$this->abstract = $abstract;
Expand Down Expand Up @@ -145,6 +156,7 @@ public function build(): ClassDescription
$this->interfaces,
$this->extend,
$this->final,
$this->readonly,
$this->abstract,
$this->interface,
$this->trait,
Expand Down
4 changes: 4 additions & 0 deletions src/Analyzer/FileVisitor.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ public function enterNode(Node $node): void
$this->classDescriptionBuilder->setFinal(true);
}

if ($node->isReadonly()) {
$this->classDescriptionBuilder->setReadonly(true);
}

if ($node->isAbstract()) {
$this->classDescriptionBuilder->setAbstract(true);
}
Expand Down
19 changes: 9 additions & 10 deletions src/Analyzer/NameResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
use PhpParser\Node\Name;
use PhpParser\Node\Name\FullyQualified;
use PhpParser\Node\Stmt;
use PhpParser\Node\Stmt\Use_;
use PhpParser\NodeAbstract;
use PhpParser\NodeVisitorAbstract;
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocNode;
Expand Down Expand Up @@ -91,7 +90,7 @@ public function enterNode(Node $node)
{
if ($node instanceof Stmt\Namespace_) {
$this->nameContext->startNamespace($node->name);
} elseif ($node instanceof Use_) {
} elseif ($node instanceof Stmt\Use_) {
foreach ($node->uses as $use) {
$this->addAlias($use, $node->type, null);
}
Expand Down Expand Up @@ -161,14 +160,14 @@ public function enterNode(Node $node)
}

if (null !== $arrayItemType) {
$node->type = $this->resolveName(new Name($arrayItemType), Use_::TYPE_NORMAL);
$node->type = $this->resolveName(new Name($arrayItemType), Stmt\Use_::TYPE_NORMAL);

return;
}
}

foreach ($phpDocNode->getVarTagValues() as $tagValue) {
$type = $this->resolveName(new Name((string) $tagValue->type), Use_::TYPE_NORMAL);
$type = $this->resolveName(new Name((string) $tagValue->type), Stmt\Use_::TYPE_NORMAL);
$node->type = $type;
break;
}
Expand All @@ -177,7 +176,7 @@ public function enterNode(Node $node)
foreach ($phpDocNode->getTags() as $tagValue) {
if ('@' === $tagValue->name[0] && !str_contains($tagValue->name, '@var')) {
$customTag = str_replace('@', '', $tagValue->name);
$type = $this->resolveName(new Name($customTag), Use_::TYPE_NORMAL);
$type = $this->resolveName(new Name($customTag), Stmt\Use_::TYPE_NORMAL);
$node->type = $type;

break;
Expand Down Expand Up @@ -207,10 +206,10 @@ public function enterNode(Node $node)
}
} elseif ($node instanceof Expr\FuncCall) {
if ($node->name instanceof Name) {
$node->name = $this->resolveName($node->name, Use_::TYPE_FUNCTION);
$node->name = $this->resolveName($node->name, Stmt\Use_::TYPE_FUNCTION);
}
} elseif ($node instanceof Expr\ConstFetch) {
$node->name = $this->resolveName($node->name, Use_::TYPE_CONSTANT);
$node->name = $this->resolveName($node->name, Stmt\Use_::TYPE_CONSTANT);
} elseif ($node instanceof Stmt\TraitUse) {
foreach ($node->traits as &$trait) {
$trait = $this->resolveClassName($trait);
Expand Down Expand Up @@ -282,7 +281,7 @@ protected function resolveName(Name $name, int $type): Name

protected function resolveClassName(Name $name): Name
{
return $this->resolveName($name, Use_::TYPE_NORMAL);
return $this->resolveName($name, Stmt\Use_::TYPE_NORMAL);
}

/**
Expand Down Expand Up @@ -339,7 +338,7 @@ private function resolveSignature($node): void
$arrayItemType = $this->getArrayItemType($phpDocParam->type);

if (null !== $arrayItemType) {
$param->type = $this->resolveName(new Name($arrayItemType), Use_::TYPE_NORMAL);
$param->type = $this->resolveName(new Name($arrayItemType), Stmt\Use_::TYPE_NORMAL);
}
}
}
Expand All @@ -356,7 +355,7 @@ private function resolveSignature($node): void
}

if (null !== $arrayItemType) {
$node->returnType = $this->resolveName(new Name($arrayItemType), Use_::TYPE_NORMAL);
$node->returnType = $this->resolveName(new Name($arrayItemType), Stmt\Use_::TYPE_NORMAL);
}
}
}
Expand Down
8 changes: 5 additions & 3 deletions src/CLI/Command/DebugExpression.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,6 @@

class DebugExpression extends Command
{
/** @var string|null */
public static $defaultName = 'debug:expression';

/** @var string|null */
public static $defaultDescription = <<< 'EOT'
Check which classes respect an expression
Expand All @@ -29,6 +26,11 @@ class DebugExpression extends Command
Check which classes respect an expression
EOT;

public function __construct()
{
parent::__construct('debug:expression');
}

protected function configure(): void
{
$this
Expand Down
8 changes: 5 additions & 3 deletions src/CLI/Command/Init.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,6 @@

class Init extends Command
{
/** @var string|null */
public static $defaultName = 'init';

/** @var string|null */
public static $defaultDescription = <<< 'EOT'
Creates a new phparkitect.php file
Expand All @@ -25,6 +22,11 @@ class Init extends Command
You can customize the directory where the file is created specifying <comment>-d /dest/path</comment>
EOT;

public function __construct()
{
parent::__construct('init');
}

protected function configure(): void
{
$this
Expand Down
2 changes: 1 addition & 1 deletion src/CLI/PhpArkitectApplication.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public function __construct()
$this->add(new DebugExpression());
}

public function getLongVersion()
public function getLongVersion(): string
{
return sprintf("%s\n\n<info>%s</info> version <comment>%s</comment>", self::$logo, $this->getName(), $this->getVersion());
}
Expand Down
Loading

0 comments on commit dd785bd

Please sign in to comment.