Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 73 additions & 19 deletions src/PhpFile.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,16 @@ class PhpFile extends DependencyAwareGenerator
protected string $name;
protected ?Comment $comment;

/** @var PhpClass[] */
protected array $classes = [];
/** @var OOPStructure[] */
protected array $oopStructures = [];

/** @var string[] */
protected array $declares = [];

public function __construct(string $name = '')
{
$this->name = $name;
$this->dependencyAwareChildren = [&$this->classes];
$this->dependencyAwareChildren = [&$this->oopStructures];
}

public static function new(string $name = ''): self
Expand All @@ -36,12 +36,12 @@ public static function new(string $name = ''): self
public function generate(): string
{
$namespace = $this->namespace ? "\nnamespace $this->namespace;\n" : '';
$classes = implode("\n\n", $this->classes);
$oopStructures = implode("\n\n", $this->oopStructures);

return <<<CODE
<?php
$namespace{$this->buildUseStatements()}
$classes
$oopStructures
CODE;
}

Expand All @@ -50,38 +50,92 @@ public function __toString(): string
return $this->generate();
}

public function removeOOPStructure(string $name, ?string $type = null): self
{
foreach ($this->oopStructures as $key => $oopStructure) {
if ($oopStructure->name === $name && ($type === null || $oopStructure instanceof $type)) {
unset($this->oopStructures[$key]);
}
}

return $this;
}

public function getOOPStructure(string $name, ?string $type = null): ?OOPStructure
{
foreach ($this->oopStructures as $key => $oopStructure) {
if ($oopStructure->name === $name && ($type === null || $oopStructure instanceof $type)) {
return $this->oopStructures[$key];
}
}

return null;
}

public function addClass(PhpClass $class): self
{
$this->classes[] = $class;
$this->oopStructures[] = $class;

return $this;
}

public function createClass(string $name): PhpClass
{
return $this->classes[] = PhpClass::new($name);
return $this->oopStructures[] = PhpClass::new($name);
}

public function removeClass(string $name): self
{
foreach ($this->classes as $key => $class) {
if ($class->name === $name) {
unset($this->classes[$key]);
}
}
return $this->removeOOPStructure($name, PhpClass::class);
}

public function getClass(string $name): ?PhpClass
{
return $this->getOOPStructure($name, PhpClass::class);
}

public function addTrait(PhpTrait $trait): self
{
$this->oopStructures[] = $trait;

return $this;
}

public function getClass(string $name): ?PhpClass
public function createTrait(string $name): PhpTrait
{
foreach ($this->classes as $key => $class) {
if ($class->name === $name) {
return $this->classes[$key];
}
}
return $this->oopStructures[] = PhpTrait::new($name);
}

return null;
public function removeTrait(string $name): self
{
return $this->removeOOPStructure($name, PhpTrait::class);
}

public function getTrait(string $name): ?PhpTrait
{
return $this->getOOPStructure($name, PhpTrait::class);
}

public function addInterface(PhpInterface $trait): self
{
$this->oopStructures[] = $trait;

return $this;
}

public function createInterface(string $name): PhpInterface
{
return $this->oopStructures[] = PhpInterface::new($name);
}

public function removeInterface(string $name): self
{
return $this->removeOOPStructure($name, PhpInterface::class);
}

public function getInterface(string $name): ?PhpInterface
{
return $this->getOOPStructure($name, PhpInterface::class);
}

public function getNamespace(): string
Expand Down
165 changes: 164 additions & 1 deletion tests/PhpFileTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@
use Murtukov\PHPCodeGenerator\Modifier;
use Murtukov\PHPCodeGenerator\PhpClass;
use Murtukov\PHPCodeGenerator\PhpFile;
use Murtukov\PHPCodeGenerator\PhpInterface;
use Murtukov\PHPCodeGenerator\PhpTrait;
use Murtukov\PHPCodeGenerator\Property;
use Murtukov\PHPCodeGenerator\Qualifier;
use PHPUnit\Framework\TestCase;

Expand Down Expand Up @@ -167,7 +170,7 @@ public function modifyComments(PhpFile $file): PhpFile
* @test
* @depends modifyComments
*/
public function saveFile(PhpFile $file): void
public function saveFile(PhpFile $file): PhpFile
{
$path = sys_get_temp_dir().'/PHPCodeGenerator/GeneratedFile.php';

Expand All @@ -189,5 +192,165 @@ public function saveFile(PhpFile $file): void

// @phpstan-ignore-next-line
$this->assertEquals(['status' => 200], $yetAnotherClass->getArray());

@unlink($path);

return $file;
}

/**
* @test
* @depends saveFile
*/
public function modifyFileClassToTrait(PhpFile $file): PhpFile
{
$file->removeClass('YetAnotherClass');
$file->addTrait(new PhpTrait('TAnotherTrait'));

$this->assertNull($file->getClass('NonExistentClass'));
$this->assertEquals('App\Converter', $file->getNamespace());

$this->assertNotNull($file->getTrait('TAnotherTrait'));
$this->assertNotNull($file->getOOPStructure('TAnotherTrait'));
$this->assertInstanceOf(PhpTrait::class, $file->getOOPStructure('TAnotherTrait'));
$this->assertNull($file->getClass('TAnotherTrait'));
$this->assertNull($file->getInterface('TAnotherTrait'));

$this->expectOutputString(<<<'CODE'
<?php

namespace App\Converter;

trait TAnotherTrait
{
}
CODE
);

echo $file;

return $file;
}


/**
* @test
* @depends modifyFileClassToTrait
*/
public function modifyFileAddAnotherTrait(PhpFile $file): PhpFile
{
$file->createTrait('TYetAnotherTrait')
->append(Method::new('getName'));

$this->expectOutputString(<<<'CODE'
<?php

namespace App\Converter;

trait TAnotherTrait
{
}

trait TYetAnotherTrait
{
public function getName()
{
}
}
CODE);

echo $file;

return $file;
}


/**
* @test
* @depends modifyFileClassToTrait
*/
public function modifyFileTraitToInterface(PhpFile $file): PhpFile
{
$file->removeTrait('TAnotherTrait');
$file->removeTrait('TYetAnotherTrait');
$file->addInterface(new PhpInterface('IAnotherTrait'));

$this->assertNull($file->getClass('NonExistentClass'));
$this->assertEquals('App\Converter', $file->getNamespace());

$this->assertNotNull($file->getInterface('IAnotherTrait'));
$this->assertNotNull($file->getOOPStructure('IAnotherTrait'));
$this->assertInstanceOf(PhpInterface::class, $file->getOOPStructure('IAnotherTrait'));
$this->assertNull($file->getClass('IAnotherTrait'));
$this->assertNull($file->getTrait('IAnotherTrait'));

$this->expectOutputString(<<<'CODE'
<?php

namespace App\Converter;

interface IAnotherTrait
{
}
CODE
);

echo $file;

return $file;
}


/**
* @test
* @depends modifyFileTraitToInterface
*/
public function modifyFileAddAnotherInterface(PhpFile $file): PhpFile
{
$file->createInterface('IYetAnotherTrait')
->createSignature('getName');

$this->expectOutputString(<<<'CODE'
<?php

namespace App\Converter;

interface IAnotherTrait
{
}

interface IYetAnotherTrait
{
public function getName();
}
CODE);

echo $file;

return $file;
}

/**
* @test
* @depends modifyFileAddAnotherInterface
*/
public function modifyFileARemoveInterface(PhpFile $file): PhpFile
{
$file->removeInterface('IAnotherTrait');

$this->expectOutputString(<<<'CODE'
<?php

namespace App\Converter;

interface IYetAnotherTrait
{
public function getName();
}
CODE);

echo $file;

return $file;
}
}