add threaded find

This commit is contained in:
TomasVotruba 2020-01-22 23:31:34 +01:00
parent eeed2f9114
commit 80dd29a8d3
6 changed files with 105 additions and 31 deletions

View File

@ -12,7 +12,7 @@ use PhpParser\Node\Stmt\Namespace_;
use PhpParser\NodeTraverser;
use Rector\CakePHPToSymfony\Rector\AbstractCakePHPRector;
use Rector\CakePHPToSymfony\Rector\NodeFactory\DoctrineNodeFactory;
use Rector\CakePHPToSymfony\Rector\NodeFactory\DoctrineRepositoryClassMethodFactory;
use Rector\CakePHPToSymfony\Rector\NodeManipulator\DoctrineRepositoryClassMethodManipulator;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Rector\RectorDefinition\CodeSample;
use Rector\RectorDefinition\RectorDefinition;
@ -27,9 +27,9 @@ use Symplify\SmartFileSystem\SmartFileInfo;
final class CakePHPModelToDoctrineRepositoryRector extends AbstractCakePHPRector
{
/**
* @var DoctrineRepositoryClassMethodFactory
* @var DoctrineRepositoryClassMethodManipulator
*/
private $doctrineRepositoryClassMethodFactory;
private $doctrineRepositoryClassMethodManipulator;
/**
* @var DoctrineNodeFactory
@ -37,10 +37,10 @@ final class CakePHPModelToDoctrineRepositoryRector extends AbstractCakePHPRector
private $doctrineNodeFactory;
public function __construct(
DoctrineRepositoryClassMethodFactory $doctrineRepositoryClassMethodFactory,
DoctrineRepositoryClassMethodManipulator $doctrineRepositoryClassMethodManipulator,
DoctrineNodeFactory $doctrineNodeFactory
) {
$this->doctrineRepositoryClassMethodFactory = $doctrineRepositoryClassMethodFactory;
$this->doctrineRepositoryClassMethodManipulator = $doctrineRepositoryClassMethodManipulator;
$this->doctrineNodeFactory = $doctrineNodeFactory;
}
@ -247,7 +247,7 @@ PHP
$repositoryClass->stmts[] = $this->doctrineNodeFactory->createConstructorWithGetRepositoryAssign($entityClass);
foreach ($repositoryMethods as $repositoryMethod) {
$doctrineRepositoryClassMethod = $this->doctrineRepositoryClassMethodFactory->createFromCakePHPClassMethod(
$doctrineRepositoryClassMethod = $this->doctrineRepositoryClassMethodManipulator->createFromCakePHPClassMethod(
$repositoryMethod,
$entityClass
);

View File

@ -2,7 +2,7 @@
declare(strict_types=1);
namespace Rector\CakePHPToSymfony\Rector\NodeFactory;
namespace Rector\CakePHPToSymfony\Rector\NodeManipulator;
use Nette\Utils\Strings;
use PhpParser\Node;
@ -22,7 +22,7 @@ use Rector\PhpParser\Node\Resolver\NameResolver;
use Rector\PhpParser\Node\Value\ValueResolver;
use Rector\PhpParser\NodeTraverser\CallableNodeTraverser;
final class DoctrineRepositoryClassMethodFactory
final class DoctrineRepositoryClassMethodManipulator
{
/**
* @var CallableNodeTraverser
@ -62,32 +62,37 @@ final class DoctrineRepositoryClassMethodFactory
return null;
}
$this->createMethodByKind($node, $entityClass);
$this->refactorClassMethodByKind($node, $entityClass);
}
);
return $classMethod;
}
private function createMethodByKind(MethodCall $methodCall, string $entityClass): void
private function refactorClassMethodByKind(MethodCall $methodCall, string $entityClass): void
{
$findKind = $this->valueResolver->getValue($methodCall->args[0]->value);
if ($findKind === 'all') {
$methodCall->var = new PropertyFetch(new Variable('this'), 'repository');
$methodCall->name = new Identifier('findAll');
$methodCall->args = [];
$this->refactorMethodByAll($methodCall);
} elseif ($findKind === 'first') {
$methodCall->name = new Identifier('findOneBy');
$this->refactorMethodByFirst($methodCall, $entityClass);
} elseif ($findKind === 'threaded') {
$methodCall->name = new Identifier('findBy');
unset($methodCall->args[0]);
if (! isset($methodCall->args[1])) {
return;
}
$possibleArray = $methodCall->args[1]->value;
if (! $possibleArray instanceof Array_) {
return;
}
$conditionsArrayItem = $this->getItemByKey($possibleArray, 'conditions');
if ($conditionsArrayItem === null) {
return;
}
$firstArgument = $methodCall->args[1]->value;
assert($firstArgument instanceof Array_);
$methodCall->args = $this->createFindOneByArgs($entityClass, $firstArgument);
$methodCall->args = [new Arg($conditionsArrayItem->value)];
} else {
throw new NotImplementedException();
}
@ -100,7 +105,7 @@ final class DoctrineRepositoryClassMethodFactory
continue;
}
if ($this->valueResolver->getValue($arrayItem->key) !== $key) {
if (! $this->valueResolver->isValue($arrayItem->key, $key)) {
continue;
}
@ -110,11 +115,9 @@ final class DoctrineRepositoryClassMethodFactory
return null;
}
private function clearStringFromEntityPrefix(String_ $string, string $entityClass): String_
private function clearStringFromEntityPrefix(String_ $string, string $entityClass): void
{
$string->value = Strings::replace($string->value, '#^' . $entityClass . '\.#');
return $string;
}
/**
@ -155,7 +158,29 @@ final class DoctrineRepositoryClassMethodFactory
continue;
}
$conditionArrayItem->key = $this->clearStringFromEntityPrefix($conditionArrayItem->key, $entityClass);
$this->clearStringFromEntityPrefix($conditionArrayItem->key, $entityClass);
}
}
private function refactorMethodByFirst(MethodCall $methodCall, string $entityClass): void
{
$methodCall->name = new Identifier('findOneBy');
unset($methodCall->args[0]);
if (! isset($methodCall->args[1])) {
return;
}
$firstArgument = $methodCall->args[1]->value;
assert($firstArgument instanceof Array_);
$methodCall->args = $this->createFindOneByArgs($entityClass, $firstArgument);
}
private function refactorMethodByAll(MethodCall $methodCall): void
{
$methodCall->var = new PropertyFetch(new Variable('this'), 'repository');
$methodCall->name = new Identifier('findAll');
$methodCall->args = [];
}
}

View File

@ -4,27 +4,27 @@ declare(strict_types=1);
namespace Rector\CakePHPToSymfony\Tests\Rector\Class_\CakePHPModelToDoctrineRepositoryRector;
use Iterator;
use Rector\CakePHPToSymfony\Rector\Class_\CakePHPModelToDoctrineRepositoryRector;
use Rector\Testing\PHPUnit\AbstractRectorTestCase;
final class CakePHPModelToDoctrineRepositoryRectorTest extends AbstractRectorTestCase
{
/**
* @dataProvider provideDataForTest()
*/
public function test(string $file): void
public function test(): void
{
$this->doTestFile($file);
$this->doTestFile(__DIR__ . '/Fixture/fixture.php.inc');
$repositoryFilePath = $this->getTempPath() . '/ActivityRepository.php';
$this->assertFileExists($repositoryFilePath);
$this->assertFileEquals(__DIR__ . '/Source/ExpectedActivityRepository.php', $repositoryFilePath);
}
public function provideDataForTest(): Iterator
public function testThreaded(): void
{
return $this->yieldFilesFromDirectory(__DIR__ . '/Fixture');
$this->doTestFile(__DIR__ . '/Fixture/threaded.php.inc');
$repositoryFilePath = $this->getTempPath() . '/PhoneRepository.php';
$this->assertFileExists($repositoryFilePath);
$this->assertFileEquals(__DIR__ . '/Source/ExpectedPhoneRepository.php', $repositoryFilePath);
}
protected function getRectorClass(): string

View File

@ -0,0 +1,25 @@
<?php
namespace Rector\CakePHPToSymfony\Tests\Rector\Class_\CakePHPModelToDoctrineRepositoryRector\Fixture;
class Phone extends \AppModel
{
public function getAll()
{
return $this->find('threaded', [
'conditions' => ['article_id' => 50]
]);
}
}
?>
-----
<?php
namespace Rector\CakePHPToSymfony\Tests\Rector\Class_\CakePHPModelToDoctrineRepositoryRector\Fixture;
class Phone
{
}
?>

View File

@ -0,0 +1,19 @@
<?php
namespace Rector\CakePHPToSymfony\Tests\Rector\Class_\CakePHPModelToDoctrineRepositoryRector\Fixture;
class PhoneRepository
{
/**
* @var \Doctrine\ORM\EntityRepository
*/
private $repository;
public function __construct(\Doctrine\ORM\EntityManagerInterface $entityManager)
{
$this->repository = $entityManager->getRepository(\Phone::class);
}
public function getAll()
{
return $this->findBy(['article_id' => 50]);
}
}

View File

@ -55,6 +55,11 @@ final class ValueResolver
$this->nodeTypeResolver = $nodeTypeResolver;
}
public function isValue(Expr $expr, $value): bool
{
return $this->getValue($expr) === $value;
}
/**
* @return mixed|null
*/