From 969c71aa8e3cf1ec17121f00bfdd6190e6ab0880 Mon Sep 17 00:00:00 2001 From: "t.munk (workhorse)" Date: Thu, 8 Oct 2026 11:57:12 +0000 Subject: [PATCH 1/3] feat(metadata): generate order parameters for collection operations (spike) [*] Opt-in auto_order: a metadata factory decorating with priority 1100 adds one SortFilter QueryParameter per sortable scalar field and per to-one relation label, skipping properties with an explicit OrderFilter. Co-Authored-By: Claude Opus 5.5 --- config/services_auto_order.yaml | 20 ++ .../ApiPlatformUtilsExtension.php | 10 +- src/DependencyInjection/Configuration.php | 13 +- ...OrderResourceMetadataCollectionFactory.php | 255 ++++++++++++++++++ 4 files changed, 296 insertions(+), 2 deletions(-) create mode 100644 config/services_auto_order.yaml create mode 100644 src/Metadata/AutoOrderResourceMetadataCollectionFactory.php diff --git a/config/services_auto_order.yaml b/config/services_auto_order.yaml new file mode 100644 index 0000000..3360ecc --- /dev/null +++ b/config/services_auto_order.yaml @@ -0,0 +1,20 @@ +# file generated with AI assistance: Claude Code - 2026-10-08 12:00:00 UTC + +services: + _defaults: + autowire: false + autoconfigure: false + public: false + + # Auto-generated order[] query parameters (SortFilter) for + # GetCollection operations of Doctrine ORM resources. Priority 1100 runs + # before API Platform's parameter factory (1000), which completes schema, + # OpenAPI and nested_properties_info of the generated parameters. + Dmstr\ApiPlatformUtils\Metadata\AutoOrderResourceMetadataCollectionFactory: + decorates: 'api_platform.metadata.resource.metadata_collection_factory' + decoration_priority: 1100 + arguments: + $decorated: '@.inner' + $managerRegistry: '@doctrine' + $labelPropertyCandidates: '%dmstr_api_platform_utils.relation_field_decorator.label_property_candidates%' + $orderParameterName: '%api_platform.collection.order_parameter_name%' diff --git a/src/DependencyInjection/ApiPlatformUtilsExtension.php b/src/DependencyInjection/ApiPlatformUtilsExtension.php index f20687d..9597791 100644 --- a/src/DependencyInjection/ApiPlatformUtilsExtension.php +++ b/src/DependencyInjection/ApiPlatformUtilsExtension.php @@ -1,5 +1,5 @@ setParameter('dmstr_api_platform_utils.partial_uuid_item_provider.enabled', $config['partial_uuid_item_provider']['enabled']); + $container->setParameter('dmstr_api_platform_utils.auto_order.enabled', $config['auto_order']['enabled']); + // Load service definitions $loader = new YamlFileLoader($container, new FileLocator(__DIR__ . '/../../config')); $loader->load('services.yaml'); @@ -52,6 +54,12 @@ public function load(array $configs, ContainerBuilder $container): void if ($config['partial_uuid_item_provider']['enabled']) { $loader->load('services_partial_uuid.yaml'); } + + // Conditionally load the auto-order metadata factory. Off by default: + // it adds query parameters to every Doctrine GetCollection operation. + if ($config['auto_order']['enabled']) { + $loader->load('services_auto_order.yaml'); + } } public function getAlias(): string diff --git a/src/DependencyInjection/Configuration.php b/src/DependencyInjection/Configuration.php index 2aea5d2..ec719e7 100644 --- a/src/DependencyInjection/Configuration.php +++ b/src/DependencyInjection/Configuration.php @@ -1,5 +1,5 @@ end() ->end() + // Auto-generated order[] parameters + ->arrayNode('auto_order') + ->addDefaultsIfNotSet() + ->children() + ->booleanNode('enabled') + ->defaultFalse() + ->info('Generate order[] query parameters (SortFilter) for the GetCollection operations of Doctrine ORM resources: sortable scalar fields and to-one relations via their label property (relation_field_decorator.label_property_candidates). Properties with an explicit #[ApiFilter(OrderFilter::class)] are left alone.') + ->end() + ->end() + ->end() + // Partial UUID Item Provider ->arrayNode('partial_uuid_item_provider') ->addDefaultsIfNotSet() diff --git a/src/Metadata/AutoOrderResourceMetadataCollectionFactory.php b/src/Metadata/AutoOrderResourceMetadataCollectionFactory.php new file mode 100644 index 0000000..78f0f48 --- /dev/null +++ b/src/Metadata/AutoOrderResourceMetadataCollectionFactory.php @@ -0,0 +1,255 @@ +]` query parameters (backed by API Platform's + * {@see SortFilter}) for the GetCollection operations of Doctrine ORM + * resources, so that every sortable column is declared by the backend + * without a hand-written `#[ApiFilter(OrderFilter::class, ...)]`. + * + * Generated parameters: + * - scalar Doctrine fields whose DBAL type is in {@see SORTABLE_TYPES} + * (identifiers, text, json, binary, vector etc. are skipped); + * - to-one associations (ManyToOne, owning OneToOne) as `.