From 3ed95b7571f82004d4c7d645032c4eb30da18477 Mon Sep 17 00:00:00 2001 From: Carl Schwan Date: Wed, 19 Aug 2026 13:03:01 +0200 Subject: [PATCH 1/4] feat: Add support for NC 35 DBAL changes Signed-off-by: Carl Schwan --- .../nextcloud-35-deprecations.php | 67 ++++++++++++++++ src/Set/NextcloudSets.php | 2 +- .../Nextcloud35/Fixture/test_fixture.php.inc | 77 +++++++++++++++++++ .../Fixture/test_fixture_types.php.inc | 63 +++++++++++++++ tests/Set/Nextcloud35/Nextcloud35SetTest.php | 28 +++++++ tests/Set/Nextcloud35/config/config.php | 11 +++ 6 files changed, 247 insertions(+), 1 deletion(-) create mode 100644 config/nextcloud-35/nextcloud-35-deprecations.php create mode 100644 tests/Set/Nextcloud35/Fixture/test_fixture.php.inc create mode 100644 tests/Set/Nextcloud35/Fixture/test_fixture_types.php.inc create mode 100644 tests/Set/Nextcloud35/Nextcloud35SetTest.php create mode 100644 tests/Set/Nextcloud35/config/config.php diff --git a/config/nextcloud-35/nextcloud-35-deprecations.php b/config/nextcloud-35/nextcloud-35-deprecations.php new file mode 100644 index 0000000..33e25ea --- /dev/null +++ b/config/nextcloud-35/nextcloud-35-deprecations.php @@ -0,0 +1,67 @@ +sets([NextcloudSets::NEXTCLOUD_34]); + $rectorConfig->ruleWithConfiguration( + RenameClassRector::class, + [ + 'Doctrine\DBAL\Schema\Table' => 'OCP\DB\Schema\ITable', + 'Doctrine\DBAL\Schema\Column' => 'OCP\DB\Schema\IColumn', + 'Doctrine\DBAL\Schema\Index' => 'OCP\DB\Schema\IIndex', + 'Doctrine\DBAL\Schema\ForeignKeyConstraint' => 'OCP\DB\Schema\IForeignKeyConstraint', + 'Doctrine\DBAL\Schema\SchemaException' => 'OCP\DB\Schema\SchemaException', + ], + ); + $rectorConfig->ruleWithConfiguration( + RenameClassConstFetchRector::class, + [ + new RenameClassAndConstFetch('OCP\DB\Types', 'BIGINT', 'OCP\DB\Schema\ColumnType', 'Bigint'), + new RenameClassAndConstFetch('OCP\DB\Types', 'BINARY', 'OCP\DB\Schema\ColumnType', 'Binary'), + new RenameClassAndConstFetch('OCP\DB\Types', 'BLOB', 'OCP\DB\Schema\ColumnType', 'Blob'), + new RenameClassAndConstFetch('OCP\DB\Types', 'BOOLEAN', 'OCP\DB\Schema\ColumnType', 'Boolean'), + new RenameClassAndConstFetch('OCP\DB\Types', 'DATE', 'OCP\DB\Schema\ColumnType', 'Date'), + new RenameClassAndConstFetch( + 'OCP\DB\Types', + 'DATE_IMMUTABLE', + 'OCP\DB\Schema\ColumnType', + 'DateImmutable', + ), + new RenameClassAndConstFetch('OCP\DB\Types', 'DATETIME', 'OCP\DB\Schema\ColumnType', 'Datetime'), + new RenameClassAndConstFetch( + 'OCP\DB\Types', + 'DATETIME_IMMUTABLE', + 'OCP\DB\Schema\ColumnType', + 'DatetimeImmutable', + ), + new RenameClassAndConstFetch('OCP\DB\Types', 'DATETIME_TZ', 'OCP\DB\Schema\ColumnType', 'DatetimeTz'), + new RenameClassAndConstFetch( + 'OCP\DB\Types', + 'DATETIME_TZ_IMMUTABLE', + 'OCP\DB\Schema\ColumnType', + 'DatetimeTzImmutable', + ), + new RenameClassAndConstFetch('OCP\DB\Types', 'DECIMAL', 'OCP\DB\Schema\ColumnType', 'Decimal'), + new RenameClassAndConstFetch('OCP\DB\Types', 'FLOAT', 'OCP\DB\Schema\ColumnType', 'Float'), + new RenameClassAndConstFetch('OCP\DB\Types', 'INTEGER', 'OCP\DB\Schema\ColumnType', 'Integer'), + new RenameClassAndConstFetch('OCP\DB\Types', 'SMALLINT', 'OCP\DB\Schema\ColumnType', 'Smallint'), + new RenameClassAndConstFetch('OCP\DB\Types', 'STRING', 'OCP\DB\Schema\ColumnType', 'String'), + new RenameClassAndConstFetch('OCP\DB\Types', 'TEXT', 'OCP\DB\Schema\ColumnType', 'Text'), + new RenameClassAndConstFetch('OCP\DB\Types', 'TIME', 'OCP\DB\Schema\ColumnType', 'Time'), + new RenameClassAndConstFetch( + 'OCP\DB\Types', + 'TIME_IMMUTABLE', + 'OCP\DB\Schema\ColumnType', + 'TimeImmutable', + ), + new RenameClassAndConstFetch('OCP\DB\Types', 'JSON', 'OCP\DB\Schema\ColumnType', 'Json'), + ], + ); +}; diff --git a/src/Set/NextcloudSets.php b/src/Set/NextcloudSets.php index 904510e..43e2ed6 100644 --- a/src/Set/NextcloudSets.php +++ b/src/Set/NextcloudSets.php @@ -27,5 +27,5 @@ final class NextcloudSets /** @psalm-api */ public const NEXTCLOUD_34 = self::NEXTCLOUD_33; /** @psalm-api */ - public const NEXTCLOUD_35 = self::NEXTCLOUD_34; + public const NEXTCLOUD_35 = __DIR__ . '/../../config/nextcloud-35/nextcloud-35-deprecations.php'; } diff --git a/tests/Set/Nextcloud35/Fixture/test_fixture.php.inc b/tests/Set/Nextcloud35/Fixture/test_fixture.php.inc new file mode 100644 index 0000000..19d521c --- /dev/null +++ b/tests/Set/Nextcloud35/Fixture/test_fixture.php.inc @@ -0,0 +1,77 @@ +getTable('my_table'); + $this->doSomething($table); + + return $schema; + } + + private function doSomething(Table $table): void + { + $table->addColumn('col', 'integer'); + } +} + +?> +----- +getTable('my_table'); + $this->doSomething($table); + + return $schema; + } + + private function doSomething(\OCP\DB\Schema\ITable $table): void + { + $table->addColumn('col', 'integer'); + } +} + +?> diff --git a/tests/Set/Nextcloud35/Fixture/test_fixture_types.php.inc b/tests/Set/Nextcloud35/Fixture/test_fixture_types.php.inc new file mode 100644 index 0000000..150e8de --- /dev/null +++ b/tests/Set/Nextcloud35/Fixture/test_fixture_types.php.inc @@ -0,0 +1,63 @@ +createTable('my_table'); + $table->addColumn('id', Types::INTEGER, ['autoincrement' => true, 'notnull' => true]); + $table->addColumn('name', Types::STRING, ['length' => 64]); + $table->addColumn('created', Types::DATETIME_IMMUTABLE); + + return $schema; + } +} + +?> +----- +createTable('my_table'); + $table->addColumn('id', \OCP\DB\Schema\ColumnType::Integer, ['autoincrement' => true, 'notnull' => true]); + $table->addColumn('name', \OCP\DB\Schema\ColumnType::String, ['length' => 64]); + $table->addColumn('created', \OCP\DB\Schema\ColumnType::DatetimeImmutable); + + return $schema; + } +} + +?> diff --git a/tests/Set/Nextcloud35/Nextcloud35SetTest.php b/tests/Set/Nextcloud35/Nextcloud35SetTest.php new file mode 100644 index 0000000..6f046b1 --- /dev/null +++ b/tests/Set/Nextcloud35/Nextcloud35SetTest.php @@ -0,0 +1,28 @@ +doTestFile($filePath); + } + + public static function provideData(): Iterator + { + return self::yieldFilesFromDirectory(__DIR__ . '/Fixture'); + } + + public function provideConfigFilePath(): string + { + return __DIR__ . '/config/config.php'; + } +} diff --git a/tests/Set/Nextcloud35/config/config.php b/tests/Set/Nextcloud35/config/config.php new file mode 100644 index 0000000..985a880 --- /dev/null +++ b/tests/Set/Nextcloud35/config/config.php @@ -0,0 +1,11 @@ +withSets([ + NextcloudSets::NEXTCLOUD_35, + ]); From 88754aaffa19e9b0f17968e4534c88932e9721b1 Mon Sep 17 00:00:00 2001 From: Carl Schwan Date: Wed, 19 Aug 2026 13:10:37 +0200 Subject: [PATCH 2/4] fix(phpstan): Silence unrelated error reported Signed-off-by: Carl Schwan --- src/Rector/LegacyGetterToOcpServerGetRector.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Rector/LegacyGetterToOcpServerGetRector.php b/src/Rector/LegacyGetterToOcpServerGetRector.php index c38712d..7880c26 100644 --- a/src/Rector/LegacyGetterToOcpServerGetRector.php +++ b/src/Rector/LegacyGetterToOcpServerGetRector.php @@ -113,7 +113,6 @@ public function configure(array $configuration): void } /** * @psalm-suppress MixedPropertyTypeCoercion - * @phpstan-ignore assign.propertyType */ $this->legacyGetterToOcpServerGet = $configuration; } From 1af6e4aa1dd4110802c7b797d39025c837bd85f3 Mon Sep 17 00:00:00 2001 From: Carl Schwan Date: Wed, 19 Aug 2026 13:28:01 +0200 Subject: [PATCH 3/4] feat: Add refactor for Type::lookupName Assisted-by: ClaudeCode:claude-sonnet-5 Signed-off-by: Carl Schwan --- .../nextcloud-35-deprecations.php | 10 + src/Rector/TypeLookupNameToGetNameRector.php | 217 ++++++++++++++++++ .../Fixture/test_fixture_lookup_name.php.inc | 85 +++++++ .../TypeLookupNameToGetNameRectorTest.php | 33 +++ .../config/config.php | 16 ++ 5 files changed, 361 insertions(+) create mode 100644 src/Rector/TypeLookupNameToGetNameRector.php create mode 100644 tests/Rector/TypeLookupNameToGetNameRector/Fixture/test_fixture_lookup_name.php.inc create mode 100644 tests/Rector/TypeLookupNameToGetNameRector/TypeLookupNameToGetNameRectorTest.php create mode 100644 tests/Rector/TypeLookupNameToGetNameRector/config/config.php diff --git a/config/nextcloud-35/nextcloud-35-deprecations.php b/config/nextcloud-35/nextcloud-35-deprecations.php index 33e25ea..5528518 100644 --- a/config/nextcloud-35/nextcloud-35-deprecations.php +++ b/config/nextcloud-35/nextcloud-35-deprecations.php @@ -2,6 +2,7 @@ declare(strict_types=1); +use Nextcloud\Rector\Rector\TypeLookupNameToGetNameRector; use Nextcloud\Rector\Set\NextcloudSets; use Rector\Config\RectorConfig; use Rector\Renaming\Rector\ClassConstFetch\RenameClassConstFetchRector; @@ -10,6 +11,15 @@ return static function (RectorConfig $rectorConfig): void { $rectorConfig->sets([NextcloudSets::NEXTCLOUD_34]); + $rectorConfig->rule(TypeLookupNameToGetNameRector::class); + $rectorConfig->skip([ + // These are the server-internal classes implementing the OCP\DB\Schema wrapper itself, + // they still work with the raw Doctrine\DBAL\Types\Type and must not be rewritten. + TypeLookupNameToGetNameRector::class => [ + 'lib/private/DB/MigrationService.php', + 'lib/private/DB/Schema/Column.php', + ], + ]); $rectorConfig->ruleWithConfiguration( RenameClassRector::class, [ diff --git a/src/Rector/TypeLookupNameToGetNameRector.php b/src/Rector/TypeLookupNameToGetNameRector.php new file mode 100644 index 0000000..132f199 --- /dev/null +++ b/src/Rector/TypeLookupNameToGetNameRector.php @@ -0,0 +1,217 @@ +getName()` MethodCall as one we created from a `Type::lookupName()` static call, + * so the comparison rewrite below can safely recognize it without re-matching by shape. + */ + private const IS_COLUMN_TYPE_GET_NAME = 'nextcloud_is_column_type_get_name'; + + private const CONST_NAME_TO_CASE = [ + 'BIGINT' => 'Bigint', + 'BINARY' => 'Binary', + 'BLOB' => 'Blob', + 'BOOLEAN' => 'Boolean', + 'DATE' => 'Date', + 'DATE_IMMUTABLE' => 'DateImmutable', + 'DATETIME' => 'Datetime', + 'DATETIME_IMMUTABLE' => 'DatetimeImmutable', + 'DATETIME_TZ' => 'DatetimeTz', + 'DATETIME_TZ_IMMUTABLE' => 'DatetimeTzImmutable', + 'DECIMAL' => 'Decimal', + 'FLOAT' => 'Float', + 'INTEGER' => 'Integer', + 'SMALLINT' => 'Smallint', + 'STRING' => 'String', + 'TEXT' => 'Text', + 'TIME' => 'Time', + 'TIME_IMMUTABLE' => 'TimeImmutable', + 'JSON' => 'Json', + ]; + + private const VALUE_TO_CASE = [ + 'bigint' => 'Bigint', + 'binary' => 'Binary', + 'blob' => 'Blob', + 'boolean' => 'Boolean', + 'date' => 'Date', + 'date_immutable' => 'DateImmutable', + 'datetime' => 'Datetime', + 'datetime_immutable' => 'DatetimeImmutable', + 'datetimetz' => 'DatetimeTz', + 'datetimetz_immutable' => 'DatetimeTzImmutable', + 'decimal' => 'Decimal', + 'float' => 'Float', + 'integer' => 'Integer', + 'smallint' => 'Smallint', + 'string' => 'String', + 'text' => 'Text', + 'time' => 'Time', + 'time_immutable' => 'TimeImmutable', + 'json' => 'Json', + ]; + + public function getRuleDefinition(): RuleDefinition + { + return new RuleDefinition( + 'Replace \Doctrine\DBAL\Types\Type::lookupName($column->getType()) with $column->getType()->getName(), ' + . 'or directly with the \OCP\DB\Schema\ColumnType enum case when compared against a known column type', + [ + new CodeSample( + <<<'CODE_SAMPLE' +use Doctrine\DBAL\Types\Type; +use OCP\DB\Types; + +Type::lookupName($column->getType()); +Type::lookupName($column->getType()) === Types::STRING; +CODE_SAMPLE, + <<<'CODE_SAMPLE' +use OCP\DB\Schema\ColumnType; + +$column->getType()->getName(); +$column->getType() === ColumnType::String; +CODE_SAMPLE, + ), + ], + ); + } + + /** + * @return array> + */ + #[Override] + public function getNodeTypes(): array + { + return [StaticCall::class, Identical::class, NotIdentical::class, Equal::class, NotEqual::class]; + } + + #[Override] + public function refactor(Node $node): ?Node + { + if ($node instanceof StaticCall) { + return $this->refactorStaticCall($node); + } + + if ($node instanceof BinaryOp) { + return $this->refactorComparison($node); + } + + return null; + } + + private function refactorStaticCall(StaticCall $staticCall): ?MethodCall + { + if (!$this->isName($staticCall->class, 'Doctrine\DBAL\Types\Type')) { + return null; + } + + if (!$this->isName($staticCall->name, 'lookupName')) { + return null; + } + + $args = $staticCall->getArgs(); + if (count($args) !== 1) { + return null; + } + + $methodCall = new MethodCall($args[0]->value, 'getName'); + $methodCall->setAttribute(self::IS_COLUMN_TYPE_GET_NAME, true); + + return $methodCall; + } + + /** + * If one side is a `->getName()` call we created above and the other side is a recognizable + * column type (a `Types::*`/`ColumnType::*` constant or a matching string literal), compare + * the `ColumnType` enum instances directly instead of going through their string names. + */ + private function refactorComparison(BinaryOp $binaryOp): ?BinaryOp + { + if ($this->isColumnTypeGetNameCall($binaryOp->left)) { + $caseName = $this->resolveColumnTypeCaseName($binaryOp->right); + if ($caseName === null) { + return null; + } + + /** @var MethodCall $left */ + $left = $binaryOp->left; + $binaryOp->left = $left->var; + $binaryOp->right = new ClassConstFetch(new FullyQualified('OCP\DB\Schema\ColumnType'), $caseName); + + return $binaryOp; + } + + if ($this->isColumnTypeGetNameCall($binaryOp->right)) { + $caseName = $this->resolveColumnTypeCaseName($binaryOp->left); + if ($caseName === null) { + return null; + } + + /** @var MethodCall $right */ + $right = $binaryOp->right; + $binaryOp->right = $right->var; + $binaryOp->left = new ClassConstFetch(new FullyQualified('OCP\DB\Schema\ColumnType'), $caseName); + + return $binaryOp; + } + + return null; + } + + private function isColumnTypeGetNameCall(Expr $expr): bool + { + return $expr instanceof MethodCall && $expr->getAttribute(self::IS_COLUMN_TYPE_GET_NAME) === true; + } + + private function resolveColumnTypeCaseName(Expr $expr): ?string + { + if ($expr instanceof String_) { + return self::VALUE_TO_CASE[strtolower($expr->value)] ?? null; + } + + if (!($expr instanceof ClassConstFetch) || !($expr->name instanceof Identifier)) { + return null; + } + + if ($this->isName($expr->class, 'OCP\DB\Schema\ColumnType')) { + return $expr->name->toString(); + } + + if ($this->isName($expr->class, 'OCP\DB\Types')) { + return self::CONST_NAME_TO_CASE[$expr->name->toString()] ?? null; + } + + return null; + } +} diff --git a/tests/Rector/TypeLookupNameToGetNameRector/Fixture/test_fixture_lookup_name.php.inc b/tests/Rector/TypeLookupNameToGetNameRector/Fixture/test_fixture_lookup_name.php.inc new file mode 100644 index 0000000..3bd8bee --- /dev/null +++ b/tests/Rector/TypeLookupNameToGetNameRector/Fixture/test_fixture_lookup_name.php.inc @@ -0,0 +1,85 @@ +getType()); + + // Comparison against the legacy OCP\DB\Types constant. + if (Type::lookupName($column->getType()) === Types::BOOLEAN) { + return; + } + + // Comparison against a plain string literal, constant on the left. + if ('string' !== Type::lookupName($sourceColumn->getType())) { + return; + } + + // Comparison against the already migrated ColumnType enum. + if (Type::lookupName($column->getType()) !== ColumnType::Text) { + return; + } + + // Unrecognized comparison value, must fall back to the plain ->getName() call. + if (Type::lookupName($column->getType()) === 'notatype') { + return; + } + } +} + +?> +----- +getType()->getName(); + + // Comparison against the legacy OCP\DB\Types constant. + if ($column->getType() === \OCP\DB\Schema\ColumnType::Boolean) { + return; + } + + // Comparison against a plain string literal, constant on the left. + if (\OCP\DB\Schema\ColumnType::String !== $sourceColumn->getType()) { + return; + } + + // Comparison against the already migrated ColumnType enum. + if ($column->getType() !== \OCP\DB\Schema\ColumnType::Text) { + return; + } + + // Unrecognized comparison value, must fall back to the plain ->getName() call. + if ($column->getType()->getName() === 'notatype') { + return; + } + } +} + +?> diff --git a/tests/Rector/TypeLookupNameToGetNameRector/TypeLookupNameToGetNameRectorTest.php b/tests/Rector/TypeLookupNameToGetNameRector/TypeLookupNameToGetNameRectorTest.php new file mode 100644 index 0000000..5b04656 --- /dev/null +++ b/tests/Rector/TypeLookupNameToGetNameRector/TypeLookupNameToGetNameRectorTest.php @@ -0,0 +1,33 @@ +doTestFile($filePath); + } + + public static function provideData(): Iterator + { + return self::yieldFilesFromDirectory(__DIR__ . '/Fixture'); + } + + public function provideConfigFilePath(): string + { + return __DIR__ . '/config/config.php'; + } +} diff --git a/tests/Rector/TypeLookupNameToGetNameRector/config/config.php b/tests/Rector/TypeLookupNameToGetNameRector/config/config.php new file mode 100644 index 0000000..1d01b71 --- /dev/null +++ b/tests/Rector/TypeLookupNameToGetNameRector/config/config.php @@ -0,0 +1,16 @@ +withRules([ + TypeLookupNameToGetNameRector::class, + ]); From 87c7c7aeaf34b24bdd54daf9108f791c0b851d0e Mon Sep 17 00:00:00 2001 From: Carl Schwan Date: Wed, 19 Aug 2026 13:29:09 +0200 Subject: [PATCH 4/4] feat(nextcloud35): Port 'asc' string to SortDirection Signed-off-by: Carl Schwan Assisted-By: ClaudeCode claude-sonnet-5 --- .../nextcloud-35-deprecations.php | 2 + src/Rector/OrderBySortDirectionRector.php | 120 ++++++++++++++++++ .../Fixture/test_fixture_order_by.php.inc | 57 +++++++++ .../OrderBySortDirectionRectorTest.php | 33 +++++ .../config/config.php | 16 +++ 5 files changed, 228 insertions(+) create mode 100644 src/Rector/OrderBySortDirectionRector.php create mode 100644 tests/Rector/OrderBySortDirectionRector/Fixture/test_fixture_order_by.php.inc create mode 100644 tests/Rector/OrderBySortDirectionRector/OrderBySortDirectionRectorTest.php create mode 100644 tests/Rector/OrderBySortDirectionRector/config/config.php diff --git a/config/nextcloud-35/nextcloud-35-deprecations.php b/config/nextcloud-35/nextcloud-35-deprecations.php index 5528518..9ee8306 100644 --- a/config/nextcloud-35/nextcloud-35-deprecations.php +++ b/config/nextcloud-35/nextcloud-35-deprecations.php @@ -2,6 +2,7 @@ declare(strict_types=1); +use Nextcloud\Rector\Rector\OrderBySortDirectionRector; use Nextcloud\Rector\Rector\TypeLookupNameToGetNameRector; use Nextcloud\Rector\Set\NextcloudSets; use Rector\Config\RectorConfig; @@ -11,6 +12,7 @@ return static function (RectorConfig $rectorConfig): void { $rectorConfig->sets([NextcloudSets::NEXTCLOUD_34]); + $rectorConfig->rule(OrderBySortDirectionRector::class); $rectorConfig->rule(TypeLookupNameToGetNameRector::class); $rectorConfig->skip([ // These are the server-internal classes implementing the OCP\DB\Schema wrapper itself, diff --git a/src/Rector/OrderBySortDirectionRector.php b/src/Rector/OrderBySortDirectionRector.php new file mode 100644 index 0000000..ea3be78 --- /dev/null +++ b/src/Rector/OrderBySortDirectionRector.php @@ -0,0 +1,120 @@ +orderBy('name', 'ASC'); +$query->addOrderBy('name', 'DESC'); +CODE_SAMPLE, + <<<'CODE_SAMPLE' +$query->orderBy('name', \SortDirection::Ascending); +$query->addOrderBy('name', \SortDirection::Descending); +CODE_SAMPLE, + ), + ], + ); + } + + /** + * @return array> + */ + #[Override] + public function getNodeTypes(): array + { + return [MethodCall::class]; + } + + #[Override] + public function refactor(Node $node): ?Node + { + if (!($node instanceof MethodCall)) { + return null; + } + + if (!$this->isNames($node->name, ['orderBy', 'addOrderBy'])) { + return null; + } + + if (!$this->isObjectType($node->var, new ObjectType('OCP\DB\QueryBuilder\IQueryBuilder'))) { + return null; + } + + $orderArg = $this->resolveOrderArg($node->getArgs()); + if (!$orderArg instanceof Arg) { + return null; + } + + if (!$orderArg->value instanceof String_) { + return null; + } + + $enumCase = match (strtolower($orderArg->value->value)) { + 'asc' => 'Ascending', + 'desc' => 'Descending', + default => null, + }; + + if ($enumCase === null) { + return null; + } + + $orderArg->value = new ClassConstFetch(new FullyQualified('SortDirection'), $enumCase); + + return $node; + } + + /** + * @param Arg[] $args + */ + private function resolveOrderArg(array $args): ?Arg + { + $position = 0; + foreach ($args as $arg) { + if ($arg->name !== null) { + if ($this->isName($arg->name, 'order')) { + return $arg; + } + + continue; + } + + if ($position === 1) { + return $arg; + } + + ++$position; + } + + return null; + } +} diff --git a/tests/Rector/OrderBySortDirectionRector/Fixture/test_fixture_order_by.php.inc b/tests/Rector/OrderBySortDirectionRector/Fixture/test_fixture_order_by.php.inc new file mode 100644 index 0000000..687bda3 --- /dev/null +++ b/tests/Rector/OrderBySortDirectionRector/Fixture/test_fixture_order_by.php.inc @@ -0,0 +1,57 @@ +getQueryBuilder(); + $qb->select('*') + ->from('pages') + ->orderBy('name', 'ASC') + ->addOrderBy('id', 'desc'); + + $qb->orderBy('name', order: 'DESC'); + $qb->orderBy('name'); + $qb->orderBy('name', 'notadirection'); + } +} + +?> +----- +getQueryBuilder(); + $qb->select('*') + ->from('pages') + ->orderBy('name', \SortDirection::Ascending) + ->addOrderBy('id', \SortDirection::Descending); + + $qb->orderBy('name', order: \SortDirection::Descending); + $qb->orderBy('name'); + $qb->orderBy('name', 'notadirection'); + } +} + +?> diff --git a/tests/Rector/OrderBySortDirectionRector/OrderBySortDirectionRectorTest.php b/tests/Rector/OrderBySortDirectionRector/OrderBySortDirectionRectorTest.php new file mode 100644 index 0000000..197d517 --- /dev/null +++ b/tests/Rector/OrderBySortDirectionRector/OrderBySortDirectionRectorTest.php @@ -0,0 +1,33 @@ +doTestFile($filePath); + } + + public static function provideData(): Iterator + { + return self::yieldFilesFromDirectory(__DIR__ . '/Fixture'); + } + + public function provideConfigFilePath(): string + { + return __DIR__ . '/config/config.php'; + } +} diff --git a/tests/Rector/OrderBySortDirectionRector/config/config.php b/tests/Rector/OrderBySortDirectionRector/config/config.php new file mode 100644 index 0000000..ed16dcc --- /dev/null +++ b/tests/Rector/OrderBySortDirectionRector/config/config.php @@ -0,0 +1,16 @@ +withRules([ + OrderBySortDirectionRector::class, + ]);