From c86f2e948a5b98e9efba99a55759d0b06f060b50 Mon Sep 17 00:00:00 2001 From: Maxence Lange Date: Wed, 3 Sep 2025 13:07:55 -0100 Subject: [PATCH 1/4] feat(migration-attributes): add DataCleansing Signed-off-by: Maxence Lange --- .../Version32000Date20250620081925.php | 3 +++ .../Version32000Date20250731062008.php | 3 +++ lib/composer/composer/autoload_classmap.php | 2 ++ lib/composer/composer/autoload_static.php | 2 ++ .../Attributes/ColumnMigrationAttribute.php | 4 +-- .../Migration/Attributes/DataCleansing.php | 27 +++++++++++++++++++ .../Attributes/DataMigrationAttribute.php | 17 ++++++++++++ .../Attributes/GenericMigrationAttribute.php | 4 +-- .../Attributes/IndexMigrationAttribute.php | 4 +-- .../Attributes/TableMigrationAttribute.php | 4 +-- 10 files changed, 58 insertions(+), 12 deletions(-) create mode 100644 lib/public/Migration/Attributes/DataCleansing.php create mode 100644 lib/public/Migration/Attributes/DataMigrationAttribute.php diff --git a/core/Migrations/Version32000Date20250620081925.php b/core/Migrations/Version32000Date20250620081925.php index 13e1ac0f87dcb..a161964da6791 100644 --- a/core/Migrations/Version32000Date20250620081925.php +++ b/core/Migrations/Version32000Date20250620081925.php @@ -9,8 +9,11 @@ namespace OC\Core\Migrations; +use OCP\Migration\Attributes\DataCleansing; + /** * Run the old migration Version24000Date20211210141942 again. */ +#[DataCleansing(table: 'preferences', description: 'lowercase accounts email address')] class Version32000Date20250620081925 extends Version24000Date20211210141942 { } diff --git a/core/Migrations/Version32000Date20250731062008.php b/core/Migrations/Version32000Date20250731062008.php index 26f0d20d19cee..5976be55a5413 100644 --- a/core/Migrations/Version32000Date20250731062008.php +++ b/core/Migrations/Version32000Date20250731062008.php @@ -12,6 +12,7 @@ use Closure; use OCP\DB\ISchemaWrapper; use OCP\IDBConnection; +use OCP\Migration\Attributes\DataCleansing; use OCP\Migration\IOutput; use OCP\Migration\SimpleMigrationStep; use Override; @@ -21,6 +22,8 @@ * This migration will clean up existing duplicates. * The new unique constraint is added in @see \OC\Core\Listener\AddMissingIndicesListener */ +#[DataCleansing(table: 'vcategory', description: 'Cleanup of duplicate vcategory records')] +#[DataCleansing(table: 'vcategory_to_object', description: 'Update object references')] class Version32000Date20250731062008 extends SimpleMigrationStep { public function __construct( private IDBConnection $connection, diff --git a/lib/composer/composer/autoload_classmap.php b/lib/composer/composer/autoload_classmap.php index f591a982a390a..d73a1527b2898 100644 --- a/lib/composer/composer/autoload_classmap.php +++ b/lib/composer/composer/autoload_classmap.php @@ -678,6 +678,8 @@ 'OCP\\Migration\\Attributes\\ColumnMigrationAttribute' => $baseDir . '/lib/public/Migration/Attributes/ColumnMigrationAttribute.php', 'OCP\\Migration\\Attributes\\ColumnType' => $baseDir . '/lib/public/Migration/Attributes/ColumnType.php', 'OCP\\Migration\\Attributes\\CreateTable' => $baseDir . '/lib/public/Migration/Attributes/CreateTable.php', + 'OCP\\Migration\\Attributes\\DataCleansing' => $baseDir . '/lib/public/Migration/Attributes/DataCleansing.php', + 'OCP\\Migration\\Attributes\\DataMigrationAttribute' => $baseDir . '/lib/public/Migration/Attributes/DataMigrationAttribute.php', 'OCP\\Migration\\Attributes\\DropColumn' => $baseDir . '/lib/public/Migration/Attributes/DropColumn.php', 'OCP\\Migration\\Attributes\\DropIndex' => $baseDir . '/lib/public/Migration/Attributes/DropIndex.php', 'OCP\\Migration\\Attributes\\DropTable' => $baseDir . '/lib/public/Migration/Attributes/DropTable.php', diff --git a/lib/composer/composer/autoload_static.php b/lib/composer/composer/autoload_static.php index 649886b76cad2..6d42f2dc2ae96 100644 --- a/lib/composer/composer/autoload_static.php +++ b/lib/composer/composer/autoload_static.php @@ -719,6 +719,8 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2 'OCP\\Migration\\Attributes\\ColumnMigrationAttribute' => __DIR__ . '/../../..' . '/lib/public/Migration/Attributes/ColumnMigrationAttribute.php', 'OCP\\Migration\\Attributes\\ColumnType' => __DIR__ . '/../../..' . '/lib/public/Migration/Attributes/ColumnType.php', 'OCP\\Migration\\Attributes\\CreateTable' => __DIR__ . '/../../..' . '/lib/public/Migration/Attributes/CreateTable.php', + 'OCP\\Migration\\Attributes\\DataCleansing' => __DIR__ . '/../../..' . '/lib/public/Migration/Attributes/DataCleansing.php', + 'OCP\\Migration\\Attributes\\DataMigrationAttribute' => __DIR__ . '/../../..' . '/lib/public/Migration/Attributes/DataMigrationAttribute.php', 'OCP\\Migration\\Attributes\\DropColumn' => __DIR__ . '/../../..' . '/lib/public/Migration/Attributes/DropColumn.php', 'OCP\\Migration\\Attributes\\DropIndex' => __DIR__ . '/../../..' . '/lib/public/Migration/Attributes/DropIndex.php', 'OCP\\Migration\\Attributes\\DropTable' => __DIR__ . '/../../..' . '/lib/public/Migration/Attributes/DropTable.php', diff --git a/lib/public/Migration/Attributes/ColumnMigrationAttribute.php b/lib/public/Migration/Attributes/ColumnMigrationAttribute.php index 30b6fe008e6a3..b32d3501a0dbb 100644 --- a/lib/public/Migration/Attributes/ColumnMigrationAttribute.php +++ b/lib/public/Migration/Attributes/ColumnMigrationAttribute.php @@ -8,14 +8,12 @@ */ namespace OCP\Migration\Attributes; -use JsonSerializable; - /** * generic class related to migration attribute about column changes * * @since 30.0.0 */ -class ColumnMigrationAttribute extends MigrationAttribute implements JsonSerializable { +class ColumnMigrationAttribute extends MigrationAttribute { /** * @param string $table name of the database table * @param string $name name of the column diff --git a/lib/public/Migration/Attributes/DataCleansing.php b/lib/public/Migration/Attributes/DataCleansing.php new file mode 100644 index 0000000000000..565ed58c3e182 --- /dev/null +++ b/lib/public/Migration/Attributes/DataCleansing.php @@ -0,0 +1,27 @@ +getTable() . '\''; + } +} diff --git a/lib/public/Migration/Attributes/DataMigrationAttribute.php b/lib/public/Migration/Attributes/DataMigrationAttribute.php new file mode 100644 index 0000000000000..6fea8382e334c --- /dev/null +++ b/lib/public/Migration/Attributes/DataMigrationAttribute.php @@ -0,0 +1,17 @@ + Date: Wed, 3 Sep 2025 13:55:02 -0100 Subject: [PATCH 2/4] feat(migration-attributes): missing attributes Signed-off-by: Maxence Lange --- .../lib/Migration/Version1016Date202502262004.php | 2 ++ apps/dav/lib/Migration/Version1034Date20250605132605.php | 5 +++++ apps/dav/lib/Migration/Version1034Date20250813093701.php | 2 ++ 3 files changed, 9 insertions(+) diff --git a/apps/cloud_federation_api/lib/Migration/Version1016Date202502262004.php b/apps/cloud_federation_api/lib/Migration/Version1016Date202502262004.php index a3523d45e38ed..b582c827f91b4 100644 --- a/apps/cloud_federation_api/lib/Migration/Version1016Date202502262004.php +++ b/apps/cloud_federation_api/lib/Migration/Version1016Date202502262004.php @@ -12,9 +12,11 @@ use Closure; use OCP\DB\ISchemaWrapper; use OCP\DB\Types; +use OCP\Migration\Attributes\CreateTable; use OCP\Migration\IOutput; use OCP\Migration\SimpleMigrationStep; +#[CreateTable(table: 'federated_invites', columns: ['id', 'user_id', 'recipient_provider', 'recipient_user_id', 'recipient_name', 'recipient_email', 'token', 'accepted', 'created_at', 'expired_at', 'accepted_at'], description: 'Supporting the OCM Invitation Flow feature')] class Version1016Date202502262004 extends SimpleMigrationStep { /** * @param IOutput $output diff --git a/apps/dav/lib/Migration/Version1034Date20250605132605.php b/apps/dav/lib/Migration/Version1034Date20250605132605.php index d46892f6e5af0..2eff120c393bb 100644 --- a/apps/dav/lib/Migration/Version1034Date20250605132605.php +++ b/apps/dav/lib/Migration/Version1034Date20250605132605.php @@ -12,9 +12,14 @@ use Closure; use OCP\DB\ISchemaWrapper; use OCP\DB\Types; +use OCP\Migration\Attributes\AddColumn; +use OCP\Migration\Attributes\ColumnType; +use OCP\Migration\Attributes\CreateTable; use OCP\Migration\IOutput; use OCP\Migration\SimpleMigrationStep; +#[AddColumn(table: 'dav_shares', name: 'token', type: ColumnType::STRING)] +#[CreateTable(table: 'calendars_federated', columns: ['id', 'display_name', 'color', 'uri', 'principaluri', 'remote_Url', 'token', 'sync_token', 'last_sync', 'shared_by', 'shared_by_display_name', 'components', 'permissions'], description: 'Supporting Federated Calender')] class Version1034Date20250605132605 extends SimpleMigrationStep { /** * @param IOutput $output diff --git a/apps/dav/lib/Migration/Version1034Date20250813093701.php b/apps/dav/lib/Migration/Version1034Date20250813093701.php index 10be71f067bef..e357178104249 100644 --- a/apps/dav/lib/Migration/Version1034Date20250813093701.php +++ b/apps/dav/lib/Migration/Version1034Date20250813093701.php @@ -13,10 +13,12 @@ use OCP\DB\ISchemaWrapper; use OCP\DB\QueryBuilder\IQueryBuilder; use OCP\IDBConnection; +use OCP\Migration\Attributes\DataCleansing; use OCP\Migration\IOutput; use OCP\Migration\SimpleMigrationStep; use Override; +#[DataCleansing(table: 'properties', description: 'remove commonly used custom properties set as default')] class Version1034Date20250813093701 extends SimpleMigrationStep { public function __construct( private IDBConnection $db, From d47189831c7e28f365e6d1ae1528c374af7061e6 Mon Sep 17 00:00:00 2001 From: Maxence Lange Date: Wed, 3 Sep 2025 19:56:27 -0100 Subject: [PATCH 3/4] feat(migration-attributes): set as Consumable Signed-off-by: Maxence Lange --- lib/public/Migration/Attributes/AddColumn.php | 4 ++-- lib/public/Migration/Attributes/AddIndex.php | 4 ++-- lib/public/Migration/Attributes/ColumnMigrationAttribute.php | 5 +++-- lib/public/Migration/Attributes/ColumnType.php | 4 +++- lib/public/Migration/Attributes/CreateTable.php | 4 ++-- lib/public/Migration/Attributes/DataCleansing.php | 4 ++-- lib/public/Migration/Attributes/DataMigrationAttribute.php | 5 +++-- lib/public/Migration/Attributes/DropColumn.php | 4 ++-- lib/public/Migration/Attributes/DropIndex.php | 4 ++-- lib/public/Migration/Attributes/DropTable.php | 4 ++-- .../Migration/Attributes/GenericMigrationAttribute.php | 5 +++-- lib/public/Migration/Attributes/IndexMigrationAttribute.php | 5 +++-- lib/public/Migration/Attributes/IndexType.php | 5 +++-- lib/public/Migration/Attributes/MigrationAttribute.php | 5 ++--- lib/public/Migration/Attributes/ModifyColumn.php | 4 ++-- lib/public/Migration/Attributes/TableMigrationAttribute.php | 5 +++-- 16 files changed, 39 insertions(+), 32 deletions(-) diff --git a/lib/public/Migration/Attributes/AddColumn.php b/lib/public/Migration/Attributes/AddColumn.php index d84a0c1f60c2e..e371ec81d198d 100644 --- a/lib/public/Migration/Attributes/AddColumn.php +++ b/lib/public/Migration/Attributes/AddColumn.php @@ -9,13 +9,13 @@ namespace OCP\Migration\Attributes; use Attribute; +use OCP\AppFramework\Attribute\Consumable; /** * attribute on new column creation - * - * @since 30.0.0 */ #[Attribute(Attribute::IS_REPEATABLE | Attribute::TARGET_CLASS)] +#[Consumable(since: '30.0.0')] class AddColumn extends ColumnMigrationAttribute { /** * @return string diff --git a/lib/public/Migration/Attributes/AddIndex.php b/lib/public/Migration/Attributes/AddIndex.php index ee22fe7f12898..86b5a89c389ef 100644 --- a/lib/public/Migration/Attributes/AddIndex.php +++ b/lib/public/Migration/Attributes/AddIndex.php @@ -9,13 +9,13 @@ namespace OCP\Migration\Attributes; use Attribute; +use OCP\AppFramework\Attribute\Consumable; /** * attribute on index creation - * - * @since 30.0.0 */ #[Attribute(Attribute::IS_REPEATABLE | Attribute::TARGET_CLASS)] +#[Consumable(since: '30.0.0')] class AddIndex extends IndexMigrationAttribute { /** * @return string diff --git a/lib/public/Migration/Attributes/ColumnMigrationAttribute.php b/lib/public/Migration/Attributes/ColumnMigrationAttribute.php index b32d3501a0dbb..d3f4aa05ade08 100644 --- a/lib/public/Migration/Attributes/ColumnMigrationAttribute.php +++ b/lib/public/Migration/Attributes/ColumnMigrationAttribute.php @@ -8,11 +8,12 @@ */ namespace OCP\Migration\Attributes; +use OCP\AppFramework\Attribute\Consumable; + /** * generic class related to migration attribute about column changes - * - * @since 30.0.0 */ +#[Consumable(since: '30.0.0')] class ColumnMigrationAttribute extends MigrationAttribute { /** * @param string $table name of the database table diff --git a/lib/public/Migration/Attributes/ColumnType.php b/lib/public/Migration/Attributes/ColumnType.php index ab6044e3ae2c1..54c0365bc9e0e 100644 --- a/lib/public/Migration/Attributes/ColumnType.php +++ b/lib/public/Migration/Attributes/ColumnType.php @@ -8,12 +8,14 @@ */ namespace OCP\Migration\Attributes; +use OCP\AppFramework\Attribute\Consumable; + /** * enum ColumnType based on OCP\DB\Types * * @see \OCP\DB\Types - * @since 30.0.0 */ +#[Consumable(since: '30.0.0')] enum ColumnType : string { /** @since 30.0.0 */ case BIGINT = 'bigint'; diff --git a/lib/public/Migration/Attributes/CreateTable.php b/lib/public/Migration/Attributes/CreateTable.php index df0418fa4bc2a..c774b0aff5648 100644 --- a/lib/public/Migration/Attributes/CreateTable.php +++ b/lib/public/Migration/Attributes/CreateTable.php @@ -9,13 +9,13 @@ namespace OCP\Migration\Attributes; use Attribute; +use OCP\AppFramework\Attribute\Consumable; /** * attribute on table creation - * - * @since 30.0.0 */ #[Attribute(Attribute::IS_REPEATABLE | Attribute::TARGET_CLASS)] +#[Consumable(since: '30.0.0')] class CreateTable extends TableMigrationAttribute { /** * @return string diff --git a/lib/public/Migration/Attributes/DataCleansing.php b/lib/public/Migration/Attributes/DataCleansing.php index 565ed58c3e182..6215c8b026867 100644 --- a/lib/public/Migration/Attributes/DataCleansing.php +++ b/lib/public/Migration/Attributes/DataCleansing.php @@ -9,13 +9,13 @@ namespace OCP\Migration\Attributes; use Attribute; +use OCP\AppFramework\Attribute\Consumable; /** * attribute on new column creation - * - * @since 32.0.0 */ #[Attribute(Attribute::IS_REPEATABLE | Attribute::TARGET_CLASS)] +#[Consumable(since: '32.0.0')] class DataCleansing extends DataMigrationAttribute { /** * @return string diff --git a/lib/public/Migration/Attributes/DataMigrationAttribute.php b/lib/public/Migration/Attributes/DataMigrationAttribute.php index 6fea8382e334c..08d12a9f37b1f 100644 --- a/lib/public/Migration/Attributes/DataMigrationAttribute.php +++ b/lib/public/Migration/Attributes/DataMigrationAttribute.php @@ -8,10 +8,11 @@ */ namespace OCP\Migration\Attributes; +use OCP\AppFramework\Attribute\Consumable; + /** * generic class related to migration attribute about data migration - * - * @since 32.0.0 */ +#[Consumable(since: '32.0.0')] class DataMigrationAttribute extends MigrationAttribute { } diff --git a/lib/public/Migration/Attributes/DropColumn.php b/lib/public/Migration/Attributes/DropColumn.php index a1cd5790cc7a5..4d0568a0a4eb9 100644 --- a/lib/public/Migration/Attributes/DropColumn.php +++ b/lib/public/Migration/Attributes/DropColumn.php @@ -9,13 +9,13 @@ namespace OCP\Migration\Attributes; use Attribute; +use OCP\AppFramework\Attribute\Consumable; /** * attribute on column drop - * - * @since 30.0.0 */ #[Attribute(Attribute::IS_REPEATABLE | Attribute::TARGET_CLASS)] +#[Consumable(since: '30.0.0')] class DropColumn extends ColumnMigrationAttribute { /** * @return string diff --git a/lib/public/Migration/Attributes/DropIndex.php b/lib/public/Migration/Attributes/DropIndex.php index 2702cbed9a732..39bdd64ced7e4 100644 --- a/lib/public/Migration/Attributes/DropIndex.php +++ b/lib/public/Migration/Attributes/DropIndex.php @@ -9,13 +9,13 @@ namespace OCP\Migration\Attributes; use Attribute; +use OCP\AppFramework\Attribute\Consumable; /** * attribute on index drop - * - * @since 30.0.0 */ #[Attribute(Attribute::IS_REPEATABLE | Attribute::TARGET_CLASS)] +#[Consumable(since: '30.0.0')] class DropIndex extends IndexMigrationAttribute { /** * @return string diff --git a/lib/public/Migration/Attributes/DropTable.php b/lib/public/Migration/Attributes/DropTable.php index e90e4804a3c9e..ad18d07c8efa2 100644 --- a/lib/public/Migration/Attributes/DropTable.php +++ b/lib/public/Migration/Attributes/DropTable.php @@ -9,13 +9,13 @@ namespace OCP\Migration\Attributes; use Attribute; +use OCP\AppFramework\Attribute\Consumable; /** * attribute on table drop - * - * @since 30.0.0 */ #[Attribute(Attribute::IS_REPEATABLE | Attribute::TARGET_CLASS)] +#[Consumable(since: '30.0.0')] class DropTable extends TableMigrationAttribute { /** * @return string diff --git a/lib/public/Migration/Attributes/GenericMigrationAttribute.php b/lib/public/Migration/Attributes/GenericMigrationAttribute.php index e55591010f0da..870182b0398ca 100644 --- a/lib/public/Migration/Attributes/GenericMigrationAttribute.php +++ b/lib/public/Migration/Attributes/GenericMigrationAttribute.php @@ -8,12 +8,13 @@ */ namespace OCP\Migration\Attributes; +use OCP\AppFramework\Attribute\Consumable; + /** * generic entry, used to replace migration attribute not yet known in current version * but used in a future release - * - * @since 30.0.0 */ +#[Consumable(since: '30.0.0')] class GenericMigrationAttribute extends MigrationAttribute { /** * @param array $details diff --git a/lib/public/Migration/Attributes/IndexMigrationAttribute.php b/lib/public/Migration/Attributes/IndexMigrationAttribute.php index 0dd7194b44891..31b9e2da2778e 100644 --- a/lib/public/Migration/Attributes/IndexMigrationAttribute.php +++ b/lib/public/Migration/Attributes/IndexMigrationAttribute.php @@ -8,11 +8,12 @@ */ namespace OCP\Migration\Attributes; +use OCP\AppFramework\Attribute\Consumable; + /** * generic class related to migration attribute about index changes - * - * @since 30.0.0 */ +#[Consumable(since: '30.0.0')] class IndexMigrationAttribute extends MigrationAttribute { /** * @param string $table name of the database table diff --git a/lib/public/Migration/Attributes/IndexType.php b/lib/public/Migration/Attributes/IndexType.php index 45c88d8104192..dc3fcb9c6564b 100644 --- a/lib/public/Migration/Attributes/IndexType.php +++ b/lib/public/Migration/Attributes/IndexType.php @@ -8,11 +8,12 @@ */ namespace OCP\Migration\Attributes; +use OCP\AppFramework\Attribute\Consumable; + /** * type of index - * - * @since 30.0.0 */ +#[Consumable(since: '30.0.0')] enum IndexType : string { /** @since 30.0.0 */ case PRIMARY = 'primary'; diff --git a/lib/public/Migration/Attributes/MigrationAttribute.php b/lib/public/Migration/Attributes/MigrationAttribute.php index d5b2d52cafb7b..4df46e7a2fe58 100644 --- a/lib/public/Migration/Attributes/MigrationAttribute.php +++ b/lib/public/Migration/Attributes/MigrationAttribute.php @@ -9,10 +9,9 @@ namespace OCP\Migration\Attributes; use JsonSerializable; +use OCP\AppFramework\Attribute\Consumable; -/** - * @since 30.0.0 - */ +#[Consumable(since: '30.0.0')] class MigrationAttribute implements JsonSerializable { /** * @param string $table name of the database table diff --git a/lib/public/Migration/Attributes/ModifyColumn.php b/lib/public/Migration/Attributes/ModifyColumn.php index 6fc44ebb82478..f34c29db74a09 100644 --- a/lib/public/Migration/Attributes/ModifyColumn.php +++ b/lib/public/Migration/Attributes/ModifyColumn.php @@ -9,13 +9,13 @@ namespace OCP\Migration\Attributes; use Attribute; +use OCP\AppFramework\Attribute\Consumable; /** * attribute on column modification - * - * @since 30.0.0 */ #[Attribute(Attribute::IS_REPEATABLE | Attribute::TARGET_CLASS)] +#[Consumable(since: '30.0.0')] class ModifyColumn extends ColumnMigrationAttribute { /** * @return string diff --git a/lib/public/Migration/Attributes/TableMigrationAttribute.php b/lib/public/Migration/Attributes/TableMigrationAttribute.php index 25d0e1c2d7c52..aede981c10f36 100644 --- a/lib/public/Migration/Attributes/TableMigrationAttribute.php +++ b/lib/public/Migration/Attributes/TableMigrationAttribute.php @@ -8,11 +8,12 @@ */ namespace OCP\Migration\Attributes; +use OCP\AppFramework\Attribute\Consumable; + /** * generic class related to migration attribute about table changes - * - * @since 30.0.0 */ +#[Consumable(since: '30.0.0')] class TableMigrationAttribute extends MigrationAttribute { /** * @param string $table name of the database table From 0b82442d9403dda8c0fd93c633b03ff0135fd690 Mon Sep 17 00:00:00 2001 From: Maxence Lange Date: Wed, 3 Sep 2025 22:27:59 -0100 Subject: [PATCH 4/4] feat(since-checker): check statement for /lib/public/migration/attributes Signed-off-by: Maxence Lange --- build/psalm/OcpSinceChecker.php | 1 + 1 file changed, 1 insertion(+) diff --git a/build/psalm/OcpSinceChecker.php b/build/psalm/OcpSinceChecker.php index 38af92cf4ef44..c4e8f71782802 100644 --- a/build/psalm/OcpSinceChecker.php +++ b/build/psalm/OcpSinceChecker.php @@ -26,6 +26,7 @@ public static function afterClassLikeVisit(AfterClassLikeVisitEvent $event): voi $isTesting = str_contains($statementsSource->getFilePath(), '/lib/public/Notification/') || str_contains($statementsSource->getFilePath(), '/lib/public/Config/') + || str_contains($statementsSource->getFilePath(), '/lib/public/Migration/Attributes/') || str_contains($statementsSource->getFilePath(), 'CalendarEventStatus'); if ($isTesting) {