diff --git a/README.md b/README.md index 6709896..bbf5551 100644 --- a/README.md +++ b/README.md @@ -28,6 +28,10 @@ new PHPFileBuilder(app_path('Models/User.php')) ### Features +#### setNamespace + +Set or replace the namespace declaration in a PHP file. If the file has no namespace, it will be added. If the namespace is already the same, no changes are made. + #### setProperty Add new class property with the passed value and passed access level in case property does not exist in the class. Otherwise diff --git a/src/Builders/PHPFileBuilder.php b/src/Builders/PHPFileBuilder.php index 0f9128e..5644de7 100644 --- a/src/Builders/PHPFileBuilder.php +++ b/src/Builders/PHPFileBuilder.php @@ -16,6 +16,7 @@ use RonasIT\Larabuilder\Visitors\PropertyVisitors\AddArrayPropertyItem; use RonasIT\Larabuilder\Visitors\PropertyVisitors\RemoveArrayPropertyItem; use RonasIT\Larabuilder\Visitors\PropertyVisitors\SetProperty; +use RonasIT\Larabuilder\Visitors\SetNamespace; class PHPFileBuilder { @@ -41,6 +42,13 @@ public function __construct( $this->traverser = new NodeTraverser(); } + public function setNamespace(string $namespace): self + { + $this->traverser->addVisitor(new SetNamespace($namespace)); + + return $this; + } + public function setProperty(string $name, mixed $value, AccessModifierEnum $accessModifier = AccessModifierEnum::Public): self { $this->traverser->addVisitor(new SetProperty($name, $value, $accessModifier)); diff --git a/src/Visitors/SetNamespace.php b/src/Visitors/SetNamespace.php new file mode 100644 index 0000000..b3ddf90 --- /dev/null +++ b/src/Visitors/SetNamespace.php @@ -0,0 +1,44 @@ + $node) { + if ($node instanceof Namespace_) { + return $this->updateNamespace($node); + } + + if ($node instanceof Declare_) { + $declares[] = $node; + + unset($nodes[$key]); + } + } + + return [...$declares, new Namespace_(new Name($this->namespace), array_values($nodes))]; + } + + protected function updateNamespace(Namespace_ $node): ?array + { + if ($node->name->toString() !== $this->namespace) { + $node->name = new Name($this->namespace); + } + + return null; + } +} diff --git a/tests/PHPFileBuilderTest.php b/tests/PHPFileBuilderTest.php index d6148d1..b834d08 100644 --- a/tests/PHPFileBuilderTest.php +++ b/tests/PHPFileBuilderTest.php @@ -17,6 +17,48 @@ class PHPFileBuilderTest extends TestCase { use PHPFileBuilderTestMockTrait; + public function testSetNamespaceOnFileWithoutNamespace(): void + { + $file = $this->generateOriginalStructurePath('class_empty.php'); + + $this->mockNativeFunction( + 'RonasIT\Larabuilder\Builders', + $this->callFilePutContent($file, 'namespace_set.php'), + ); + + new PHPFileBuilder($file) + ->setNamespace('App\\Models') + ->save(); + } + + public function testSetNamespaceReplacesExistingNamespace(): void + { + $file = $this->generateOriginalStructurePath('enum.php'); + + $this->mockNativeFunction( + 'RonasIT\Larabuilder\Builders', + $this->callFilePutContent($file, 'namespace_update.php'), + ); + + new PHPFileBuilder($file) + ->setNamespace('App\\Models') + ->save(); + } + + public function testSetNamespaceDoesNothingWhenSameNamespace(): void + { + $file = $this->generateOriginalStructurePath('class.php'); + + $this->mockNativeFunction( + 'RonasIT\Larabuilder\Builders', + $this->callFilePutContent($file, 'class_unchanged.php'), + ); + + new PHPFileBuilder($file) + ->setNamespace('RonasIT\Larabuilder\Tests\Support') + ->save(); + } + public function testSetProperty(): void { $file = $this->generateOriginalStructurePath('class_with_properties.php'); diff --git a/tests/Support/OriginStructures/class_empty.php b/tests/Support/OriginStructures/class_empty.php new file mode 100644 index 0000000..0cf3f47 --- /dev/null +++ b/tests/Support/OriginStructures/class_empty.php @@ -0,0 +1,7 @@ +