Skip to content

Commit

Permalink
[OrderByKeyToClassConstRector] Add rule
Browse files Browse the repository at this point in the history
  • Loading branch information
JohJohan committed Aug 22, 2023
1 parent c0ab738 commit aaeff43
Show file tree
Hide file tree
Showing 10 changed files with 257 additions and 1 deletion.
3 changes: 3 additions & 0 deletions config/sets/doctrine-code-quality.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
declare(strict_types=1);

use Rector\Config\RectorConfig;
use Rector\Doctrine\CodeQuality\Rector\Attribute\OrderByKeyToClassConstRector;
use Rector\Doctrine\CodeQuality\Rector\Class_\InitializeDefaultEntityCollectionRector;
use Rector\Doctrine\CodeQuality\Rector\Class_\MoveCurrentDateTimeDefaultInEntityToConstructorRector;
use Rector\Doctrine\CodeQuality\Rector\Class_\RemoveEmptyTableAttributeRector;
Expand Down Expand Up @@ -34,6 +35,8 @@
TypedPropertyFromToOneRelationTypeRector::class,
TypedPropertyFromToManyRelationTypeRector::class,
TypedPropertyFromDoctrineCollectionRector::class,

OrderByKeyToClassConstRector::class,
]);

$rectorConfig->ruleWithConfiguration(AttributeKeyToClassConstFetchRector::class, [
Expand Down
22 changes: 21 additions & 1 deletion docs/rector_rules_overview.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# 14 Rules Overview
# 15 Rules Overview

## ChangeBigIntEntityPropertyToIntTypeRector

Expand Down Expand Up @@ -217,6 +217,26 @@ Move default value for entity property to constructor, the safest place

<br>

## OrderByKeyToClassConstRector

Replace OrderBy Attribute ASC/DESC with class constant from Criteria

- class: [`Rector\Doctrine\CodeQuality\Rector\Attribute\OrderByKeyToClassConstRector`](../rules/CodeQuality/Rector/Attribute/OrderByKeyToClassConstRector.php)

```diff
use Doctrine\ORM\Mapping as ORM;

class ReplaceOrderByAscWithClassConstant
{
- #[ORM\OrderBy(['createdAt' => 'ASC'])]
+ #[ORM\OrderBy(['createdAt' => \Doctrine\Common\Collections\Criteria::ASC])]
protected \DateTimeInterface $messages;
}
?>
```

<br>

## RemoveEmptyTableAttributeRector

Remove empty Table attribute on entities because it's useless
Expand Down
1 change: 1 addition & 0 deletions phpunit.xml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
<testsuites>
<testsuite name="main">
<directory>tests</directory>
<directory>rules-tests</directory>
</testsuite>
</testsuites>
</phpunit>
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

namespace Rector\Doctrine\Tests\CodeQuality\Rector\Attribute\OrderByKeyToClassConstRector\Fixture;

use Doctrine\ORM\Mapping as ORM;

class ReplaceOrderByAscWithClassConstant
{
#[ORM\OrderBy(['createdAt' => 'asc'])]
protected \DateTimeInterface $messages;
}
?>
-----
<?php

namespace Rector\Doctrine\Tests\CodeQuality\Rector\Attribute\OrderByKeyToClassConstRector\Fixture;

use Doctrine\ORM\Mapping as ORM;

class ReplaceOrderByAscWithClassConstant
{
#[ORM\OrderBy(['createdAt' => \Doctrine\Common\Collections\Criteria::ASC])]
protected \DateTimeInterface $messages;
}
?>
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

namespace Rector\Doctrine\Tests\CodeQuality\Rector\Attribute\OrderByKeyToClassConstRector\Fixture;

use Doctrine\ORM\Mapping as ORM;

class ReplaceOrderByAscWithClassConstant
{
#[ORM\OrderBy(['createdAt' => 'ASC'])]
protected \DateTimeInterface $messages;
}
?>
-----
<?php

namespace Rector\Doctrine\Tests\CodeQuality\Rector\Attribute\OrderByKeyToClassConstRector\Fixture;

use Doctrine\ORM\Mapping as ORM;

class ReplaceOrderByAscWithClassConstant
{
#[ORM\OrderBy(['createdAt' => \Doctrine\Common\Collections\Criteria::ASC])]
protected \DateTimeInterface $messages;
}
?>
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

namespace Rector\Doctrine\Tests\CodeQuality\Rector\Attribute\OrderByKeyToClassConstRector\Fixture;

use Doctrine\ORM\Mapping as ORM;

class ReplaceOrderByAscWithClassConstant
{
#[ORM\OrderBy(['createdAt' => 'desc'])]
protected \DateTimeInterface $messages;
}
?>
-----
<?php

namespace Rector\Doctrine\Tests\CodeQuality\Rector\Attribute\OrderByKeyToClassConstRector\Fixture;

use Doctrine\ORM\Mapping as ORM;

class ReplaceOrderByAscWithClassConstant
{
#[ORM\OrderBy(['createdAt' => \Doctrine\Common\Collections\Criteria::DESC])]
protected \DateTimeInterface $messages;
}
?>
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

namespace Rector\Doctrine\Tests\CodeQuality\Rector\Attribute\OrderByKeyToClassConstRector\Fixture;

use Doctrine\Common\Collections\Criteria;
use Doctrine\ORM\Mapping as ORM;

class SkipAlreadyUsingConst
{
#[ORM\OrderBy(['createdAt' => Criteria::ASC])]
protected \DateTimeInterface $messages;
}
?>
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

declare(strict_types=1);

namespace Rector\Doctrine\Tests\CodeQuality\Rector\Attribute\OrderByKeyToClassConstRector;

use Iterator;
use PHPUnit\Framework\Attributes\DataProvider;
use Rector\Testing\PHPUnit\AbstractRectorTestCase;

final class OrderByKeyToClassConstRectorTest extends AbstractRectorTestCase
{
#[DataProvider('provideData')]
public function test(string $filePath): void
{
$this->doTestFile($filePath);
}

public static function provideData(): Iterator
{
return self::yieldFilesFromDirectory(__DIR__ . '/Fixture');
}

public function provideConfigFilePath(): string
{
return __DIR__ . '/config/configured_set.php';
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php

declare(strict_types=1);

use Rector\Config\RectorConfig;

use Rector\Doctrine\CodeQuality\Rector\Attribute\OrderByKeyToClassConstRector;

return static function (RectorConfig $rectorConfig): void {
$rectorConfig->rule(OrderByKeyToClassConstRector::class);
};
105 changes: 105 additions & 0 deletions rules/CodeQuality/Rector/Attribute/OrderByKeyToClassConstRector.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
<?php

declare(strict_types=1);

namespace Rector\Doctrine\CodeQuality\Rector\Attribute;

use Doctrine\Common\Collections\Criteria;
use PhpParser\Node;
use PhpParser\Node\Attribute;
use PhpParser\Node\Expr\Array_;
use PhpParser\Node\Scalar\String_;
use Rector\Core\Rector\AbstractRector;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;

/**
* @see \Rector\Doctrine\Tests\CodeQuality\Rector\Attribute\OrderByKeyToClassConstRector\OrderByKeyToClassConstRectorTest
*/
final class OrderByKeyToClassConstRector extends AbstractRector
{
public function getRuleDefinition(): RuleDefinition
{
return new RuleDefinition(
'Replace OrderBy Attribute ASC/DESC with class constant from Criteria',
[
new CodeSample(
<<<'CODE_SAMPLE'
use Doctrine\ORM\Mapping as ORM;
class ReplaceOrderByAscWithClassConstant
{
#[ORM\OrderBy(['createdAt' => 'ASC'])]
protected \DateTimeInterface $messages;
}
?>
CODE_SAMPLE

,
<<<'CODE_SAMPLE'
use Doctrine\ORM\Mapping as ORM;
class ReplaceOrderByAscWithClassConstant
{
#[ORM\OrderBy(['createdAt' => \Doctrine\Common\Collections\Criteria::ASC])]
protected \DateTimeInterface $messages;
}
?>
CODE_SAMPLE
),
]
);
}

/**
* @return array<class-string<Node>>
*/
public function getNodeTypes(): array
{
return [Attribute::class];
}

/**
* @param Attribute $node
*/
public function refactor(Node $node): ?Node
{
// If Attribute is not OrderBy, return null
if ($node->name->toString() !== 'Doctrine\ORM\Mapping\OrderBy') {
return null;
}

if (!isset($node->args[0])) {
return null;
}

if (!$node->args[0]->value instanceof Array_){
return null;
}

if (!isset($node->args[0]->value->items[0])) {
return null;
}

if (!$node->args[0]->value->items[0] instanceof Node\Expr\ArrayItem) {
return null;
}

if (!$node->args[0]->value->items[0]->value instanceof String_) {
return null;
}

// If Attribute value from key is not `ASC` or `DESC`, return null
if (! in_array($node->args[0]->value->items[0]->value->value, ['ASC', 'asc', 'DESC', 'desc'])) {
return null;
}

$upper = strtoupper($node->args[0]->value->items[0]->value->value);
$node->args[0]->value->items[0]->value = $this->nodeFactory->createClassConstFetch(
Criteria::class,
$upper
);

return $node;
}
}

0 comments on commit aaeff43

Please sign in to comment.