From 85d77c48d09420dc86bf4aaa86e1a1b7b03bfd40 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Sat, 27 Jun 2026 09:34:11 +0700 Subject: [PATCH 1/3] chore: fix to use ClassConst namespace on AddPublicConstantVisibilityVisitor --- .../AddPublicConstantVisibilityVisitor.php | 58 -------------- .../MustDeclareConstantVisibilityRule.php | 2 +- .../MustDeclareConstantVisibilityRuleTest.php | 2 +- ...AddPublicConstantVisibilityVisitorTest.php | 80 ------------------- 4 files changed, 2 insertions(+), 140 deletions(-) delete mode 100644 src/Rule/Fixer/PhpParser/ClassConstant/AddPublicConstantVisibilityVisitor.php delete mode 100644 tests/Rule/Fixer/PhpParser/ClassConstant/AddPublicConstantVisibilityVisitorTest.php diff --git a/src/Rule/Fixer/PhpParser/ClassConstant/AddPublicConstantVisibilityVisitor.php b/src/Rule/Fixer/PhpParser/ClassConstant/AddPublicConstantVisibilityVisitor.php deleted file mode 100644 index cc317f9..0000000 --- a/src/Rule/Fixer/PhpParser/ClassConstant/AddPublicConstantVisibilityVisitor.php +++ /dev/null @@ -1,58 +0,0 @@ -namespacedName?->toString() !== $this->className) { - return null; - } - - foreach ($node->getConstants() as $classConstant) { - if (! $this->containsConstant($classConstant)) { - continue; - } - - if (($classConstant->flags & Modifiers::VISIBILITY_MASK) !== 0) { - return null; - } - - $classConstant->flags |= Modifiers::PUBLIC; - - return $node; - } - - return null; - } - - private function containsConstant(ClassConst $classConst): bool - { - foreach ($classConst->consts as $constant) { - if ($constant->name->toString() === $this->constantName) { - return true; - } - } - - return false; - } -} diff --git a/src/Rule/Rules/Class_/MustDeclareConstantVisibilityRule.php b/src/Rule/Rules/Class_/MustDeclareConstantVisibilityRule.php index ff8e920..fa7aa2a 100644 --- a/src/Rule/Rules/Class_/MustDeclareConstantVisibilityRule.php +++ b/src/Rule/Rules/Class_/MustDeclareConstantVisibilityRule.php @@ -6,7 +6,7 @@ use Boundwize\StructArmed\Analyser\ClassNode; use Boundwize\StructArmed\Rule\Fixer\PhpParser\AbstractPhpParserFixableRule as PhpParserFixableRule; -use Boundwize\StructArmed\Rule\Fixer\PhpParser\ClassConstant\AddPublicConstantVisibilityVisitor; +use Boundwize\StructArmed\Rule\Fixer\PhpParser\ClassConst\AddPublicConstantVisibilityVisitor; use Boundwize\StructArmed\Rule\MultipleRuleViolationInterface as MultipleViolations; use Boundwize\StructArmed\Rule\RuleViolation; diff --git a/tests/Rule/Class_/MustDeclareConstantVisibilityRuleTest.php b/tests/Rule/Class_/MustDeclareConstantVisibilityRuleTest.php index 110e426..8fac61f 100644 --- a/tests/Rule/Class_/MustDeclareConstantVisibilityRuleTest.php +++ b/tests/Rule/Class_/MustDeclareConstantVisibilityRuleTest.php @@ -7,7 +7,7 @@ use Boundwize\StructArmed\Analyser\ClassNode; use Boundwize\StructArmed\Analyser\ConstantNode; use Boundwize\StructArmed\Rule\FixableInterface; -use Boundwize\StructArmed\Rule\Fixer\PhpParser\ClassConstant\AddPublicConstantVisibilityVisitor; +use Boundwize\StructArmed\Rule\Fixer\PhpParser\ClassConst\AddPublicConstantVisibilityVisitor; use Boundwize\StructArmed\Rule\Rules\Class_\MustDeclareConstantVisibilityRule; use Boundwize\StructArmed\Rule\RuleViolation; use PHPUnit\Framework\Attributes\CoversClass; diff --git a/tests/Rule/Fixer/PhpParser/ClassConstant/AddPublicConstantVisibilityVisitorTest.php b/tests/Rule/Fixer/PhpParser/ClassConstant/AddPublicConstantVisibilityVisitorTest.php deleted file mode 100644 index ca1bfd9..0000000 --- a/tests/Rule/Fixer/PhpParser/ClassConstant/AddPublicConstantVisibilityVisitorTest.php +++ /dev/null @@ -1,80 +0,0 @@ - [$classConst]]); - $addPublicConstantVisibilityVisitor = new AddPublicConstantVisibilityVisitor('App\\Order', 'VERSION'); - $class->namespacedName = new Name('App\\Order'); - - (new NodeTraverser($addPublicConstantVisibilityVisitor))->traverse([$class]); - - $this->assertSame(Modifiers::PUBLIC | Modifiers::FINAL, $classConst->flags); - } - - public function testDoesNotChangeAlreadyVisibleConstant(): void - { - $classConst = new ClassConst([new Const_('VERSION', new Int_(1))], Modifiers::PUBLIC); - $class = new Class_('Order', ['stmts' => [$classConst]]); - $addPublicConstantVisibilityVisitor = new AddPublicConstantVisibilityVisitor('Order', 'VERSION'); - $class->namespacedName = new Name('Order'); - - (new NodeTraverser($addPublicConstantVisibilityVisitor))->traverse([$class]); - - $this->assertSame(Modifiers::PUBLIC, $classConst->flags); - } - - public function testDoesNotChangeConstantInDifferentClass(): void - { - $classConst = new ClassConst([new Const_('VERSION', new Int_(1))]); - $class = new Class_('Order', ['stmts' => [$classConst]]); - $addPublicConstantVisibilityVisitor = new AddPublicConstantVisibilityVisitor('App\\Order', 'VERSION'); - $class->namespacedName = new Name('App\\Invoice'); - - (new NodeTraverser($addPublicConstantVisibilityVisitor))->traverse([$class]); - - $this->assertSame(0, $classConst->flags); - } - - public function testDoesNotChangeDifferentConstant(): void - { - $classConst = new ClassConst([new Const_('STATUS', new Int_(1))]); - $class = new Class_('Order', ['stmts' => [$classConst]]); - $addPublicConstantVisibilityVisitor = new AddPublicConstantVisibilityVisitor('App\\Order', 'VERSION'); - $class->namespacedName = new Name('App\\Order'); - - (new NodeTraverser($addPublicConstantVisibilityVisitor))->traverse([$class]); - - $this->assertSame(0, $classConst->flags); - } - - public function testDoesNotChangeAnonymousClassConstant(): void - { - $classConst = new ClassConst([new Const_('VERSION', new Int_(1))]); - $class = new Class_(null, ['stmts' => [$classConst]]); - $addPublicConstantVisibilityVisitor = new AddPublicConstantVisibilityVisitor('App\\Missing', 'VERSION'); - - (new NodeTraverser(new NameResolver(), $addPublicConstantVisibilityVisitor))->traverse([$class]); - - $this->assertSame(0, $classConst->flags); - } -} From a1a214c628665bb8faba371aa217492f0eaa5ae9 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Sat, 27 Jun 2026 09:34:14 +0700 Subject: [PATCH 2/3] chore: fix to use ClassConst namespace on AddPublicConstantVisibilityVisitor --- .../AddPublicConstantVisibilityVisitor.php | 58 ++++++++++++++ ...AddPublicConstantVisibilityVisitorTest.php | 80 +++++++++++++++++++ 2 files changed, 138 insertions(+) create mode 100644 src/Rule/Fixer/PhpParser/ClassConst/AddPublicConstantVisibilityVisitor.php create mode 100644 tests/Rule/Fixer/PhpParser/ClassConst/AddPublicConstantVisibilityVisitorTest.php diff --git a/src/Rule/Fixer/PhpParser/ClassConst/AddPublicConstantVisibilityVisitor.php b/src/Rule/Fixer/PhpParser/ClassConst/AddPublicConstantVisibilityVisitor.php new file mode 100644 index 0000000..12fc849 --- /dev/null +++ b/src/Rule/Fixer/PhpParser/ClassConst/AddPublicConstantVisibilityVisitor.php @@ -0,0 +1,58 @@ +namespacedName?->toString() !== $this->className) { + return null; + } + + foreach ($node->getConstants() as $classConstant) { + if (! $this->containsConstant($classConstant)) { + continue; + } + + if (($classConstant->flags & Modifiers::VISIBILITY_MASK) !== 0) { + return null; + } + + $classConstant->flags |= Modifiers::PUBLIC; + + return $node; + } + + return null; + } + + private function containsConstant(ClassConst $classConst): bool + { + foreach ($classConst->consts as $constant) { + if ($constant->name->toString() === $this->constantName) { + return true; + } + } + + return false; + } +} diff --git a/tests/Rule/Fixer/PhpParser/ClassConst/AddPublicConstantVisibilityVisitorTest.php b/tests/Rule/Fixer/PhpParser/ClassConst/AddPublicConstantVisibilityVisitorTest.php new file mode 100644 index 0000000..3665c55 --- /dev/null +++ b/tests/Rule/Fixer/PhpParser/ClassConst/AddPublicConstantVisibilityVisitorTest.php @@ -0,0 +1,80 @@ + [$classConst]]); + $addPublicConstantVisibilityVisitor = new AddPublicConstantVisibilityVisitor('App\\Order', 'VERSION'); + $class->namespacedName = new Name('App\\Order'); + + (new NodeTraverser($addPublicConstantVisibilityVisitor))->traverse([$class]); + + $this->assertSame(Modifiers::PUBLIC | Modifiers::FINAL, $classConst->flags); + } + + public function testDoesNotChangeAlreadyVisibleConstant(): void + { + $classConst = new ClassConst([new Const_('VERSION', new Int_(1))], Modifiers::PUBLIC); + $class = new Class_('Order', ['stmts' => [$classConst]]); + $addPublicConstantVisibilityVisitor = new AddPublicConstantVisibilityVisitor('Order', 'VERSION'); + $class->namespacedName = new Name('Order'); + + (new NodeTraverser($addPublicConstantVisibilityVisitor))->traverse([$class]); + + $this->assertSame(Modifiers::PUBLIC, $classConst->flags); + } + + public function testDoesNotChangeConstantInDifferentClass(): void + { + $classConst = new ClassConst([new Const_('VERSION', new Int_(1))]); + $class = new Class_('Order', ['stmts' => [$classConst]]); + $addPublicConstantVisibilityVisitor = new AddPublicConstantVisibilityVisitor('App\\Order', 'VERSION'); + $class->namespacedName = new Name('App\\Invoice'); + + (new NodeTraverser($addPublicConstantVisibilityVisitor))->traverse([$class]); + + $this->assertSame(0, $classConst->flags); + } + + public function testDoesNotChangeDifferentConstant(): void + { + $classConst = new ClassConst([new Const_('STATUS', new Int_(1))]); + $class = new Class_('Order', ['stmts' => [$classConst]]); + $addPublicConstantVisibilityVisitor = new AddPublicConstantVisibilityVisitor('App\\Order', 'VERSION'); + $class->namespacedName = new Name('App\\Order'); + + (new NodeTraverser($addPublicConstantVisibilityVisitor))->traverse([$class]); + + $this->assertSame(0, $classConst->flags); + } + + public function testDoesNotChangeAnonymousClassConstant(): void + { + $classConst = new ClassConst([new Const_('VERSION', new Int_(1))]); + $class = new Class_(null, ['stmts' => [$classConst]]); + $addPublicConstantVisibilityVisitor = new AddPublicConstantVisibilityVisitor('App\\Missing', 'VERSION'); + + (new NodeTraverser(new NameResolver(), $addPublicConstantVisibilityVisitor))->traverse([$class]); + + $this->assertSame(0, $classConst->flags); + } +} From 7fa9a4f745c2f398088702518d04b8f7afd6d4a5 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Sat, 27 Jun 2026 09:35:36 +0700 Subject: [PATCH 3/3] update screenshot --- docs/assets/no-violation.svg | 2 +- docs/assets/structarmed-showoff.svg | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/assets/no-violation.svg b/docs/assets/no-violation.svg index d439da8..80814e7 100644 --- a/docs/assets/no-violation.svg +++ b/docs/assets/no-violation.svg @@ -14,7 +14,7 @@ prj-ddd vendor/bin/structarmed analyze - StructArmed 0.14.2 — Architecture Enforcement + StructArmed 0.14.3 — Architecture Enforcement =============================================== diff --git a/docs/assets/structarmed-showoff.svg b/docs/assets/structarmed-showoff.svg index 0011c09..d61c269 100644 --- a/docs/assets/structarmed-showoff.svg +++ b/docs/assets/structarmed-showoff.svg @@ -15,7 +15,7 @@ prj-ddd vendor/bin/structarmed analyze - StructArmed 0.14.2 — Architecture Enforcement + StructArmed 0.14.3 — Architecture Enforcement ===============================================