From e15b03851e6a06681cb74f0213391825c2c5a5a2 Mon Sep 17 00:00:00 2001 From: stunnerparas Date: Wed, 26 Nov 2025 01:22:33 +0000 Subject: [PATCH 01/39] type fix, add pagination and new data object provider --- config/gdpr.yaml | 3 + .../Attribute/Request/GdprRequestBody.php | 18 ++ src/Gdpr/Attribute/Request/SearchTerms.php | 10 +- .../GdprStructuredSearchRequest.php | 6 +- src/Gdpr/Provider/DataObjectProvider.php | 171 ++++++++++++++++++ src/Gdpr/Provider/DataProviderInterface.php | 3 +- src/Gdpr/Provider/PimcoreUserProvider.php | 3 +- src/Gdpr/Schema/GdprSearchOptions.php | 43 +++++ src/Gdpr/Service/GdprManagerService.php | 2 +- 9 files changed, 250 insertions(+), 9 deletions(-) create mode 100644 src/Gdpr/Provider/DataObjectProvider.php create mode 100644 src/Gdpr/Schema/GdprSearchOptions.php diff --git a/config/gdpr.yaml b/config/gdpr.yaml index be17c5704..0d242a765 100644 --- a/config/gdpr.yaml +++ b/config/gdpr.yaml @@ -25,3 +25,6 @@ services: tags: ["pimcore.studio_backend.gdpr_data_provider"] arguments: $logsDir: "%kernel.logs_dir%" + + Pimcore\Bundle\StudioBackendBundle\Gdpr\Provider\DataObjectProvider: + tags: ["pimcore.studio_backend.gdpr_data_provider"] \ No newline at end of file diff --git a/src/Gdpr/Attribute/Request/GdprRequestBody.php b/src/Gdpr/Attribute/Request/GdprRequestBody.php index 52585055f..f61f079a5 100644 --- a/src/Gdpr/Attribute/Request/GdprRequestBody.php +++ b/src/Gdpr/Attribute/Request/GdprRequestBody.php @@ -49,6 +49,24 @@ public function __construct() description: 'The object containing the search values.', type: 'object' ), + + new Property( + property: 'filters', + description: 'Pagination and sorting options', + properties: [ + new Property(property: 'page', type: 'integer', example: 1), + new Property(property: 'pageSize', type: 'integer', example: 20), + new Property( + property: 'sortFilter', + type: 'object', + properties: [ + new Property(property: 'key', type: 'string', example: 'id'), + new Property(property: 'direction', type: 'string', example: 'ASC') + ] + ) + ], + type: 'object' + ) ], type: 'object', ), diff --git a/src/Gdpr/Attribute/Request/SearchTerms.php b/src/Gdpr/Attribute/Request/SearchTerms.php index b9de9525e..8edc508ba 100644 --- a/src/Gdpr/Attribute/Request/SearchTerms.php +++ b/src/Gdpr/Attribute/Request/SearchTerms.php @@ -29,11 +29,11 @@ final readonly class SearchTerms { public function __construct( - #[Property(description: 'The ID to search for.', type: 'string', nullable: true)] - #[Type('string')] - public ?string $id = null, + #[Property(description: 'The ID to search for.', type: 'int', nullable: true)] + #[Type('int')] + public ?int $id = null, - #[Property(description: 'The first name to search for.', type: 'string', nullable: true)] + #[Property(description: 'The first name to search for. ', type: 'string', nullable: true)] #[Type('string')] public ?string $firstname = null, @@ -54,7 +54,7 @@ public function __construct( } } - public function getId(): ?string + public function getId(): ?int { return $this->id; } diff --git a/src/Gdpr/MappedParameter/GdprStructuredSearchRequest.php b/src/Gdpr/MappedParameter/GdprStructuredSearchRequest.php index 32d92fb40..6d0e8f2e2 100644 --- a/src/Gdpr/MappedParameter/GdprStructuredSearchRequest.php +++ b/src/Gdpr/MappedParameter/GdprStructuredSearchRequest.php @@ -19,6 +19,7 @@ use Symfony\Component\Validator\Constraints\NotNull; use Symfony\Component\Validator\Constraints\Type; use Symfony\Component\Validator\Constraints\Valid; +use Pimcore\Bundle\StudioBackendBundle\Gdpr\Schema\GdprSearchOptions; /** * @internal @@ -35,7 +36,10 @@ public function __construct( #[Valid] #[NotNull] - public SearchTerms $searchTerms + public SearchTerms $searchTerms, + + #[Valid] + public GdprSearchOptions $filters ) { } } diff --git a/src/Gdpr/Provider/DataObjectProvider.php b/src/Gdpr/Provider/DataObjectProvider.php new file mode 100644 index 000000000..31367b9d1 --- /dev/null +++ b/src/Gdpr/Provider/DataObjectProvider.php @@ -0,0 +1,171 @@ +query->createDataObjectQuery(); + + $searchTerm = $this->buildSearchTerm($terms); + + $query->filterFullText($searchTerm); + + $this->applySearchOptions($query, $options); + + $searchResult = $this->searchService->searchDataObjects($query); + + $columns = $this->getAvailableColumns(); + + $items = $searchResult->getItems(); + + return array_map( + fn($item) => new GdprDataRow([ + 'id' => $item->getId(), + 'key' => $item->getKey(), + 'path' => $item->getPath(), + 'className' => $item->getClassName(), + 'fullPath' => $item->getFullPath(), + 'parentId' => $item->getParentId(), + 'type' => $item->getType(), + 'published' => $item->isPublished(), + 'creationDate' => date('Y-m-d H:i:s', $item->getCreationDate()), + 'modificationDate' => date('Y-m-d H:i:s', $item->getModificationDate()), + ], $columns), + $items + ); + } + + + private function applySearchOptions(QueryInterface $query, GdprSearchOptions $options): void + { + // Pagination + $query->setPage($options->page); + $query->setPageSize($options->pageSize); + + // Sorting + if ($options->sortFilter && isset($options->sortFilter['key'], $options->sortFilter['direction'])) { + $directionEnum = SortDirection::tryFrom($options->sortFilter['direction']); + if ($directionEnum) { + $query->orderByField($options->sortFilter['key'], $directionEnum); + } + } + } + + + + + private function buildSearchTerm(SearchTerms $terms): string + { + return implode(' ', array_filter([$terms->id, $terms->firstname, $terms->lastname, $terms->email])); + } + + public function getDeleteSwaggerOperationId(): string + { + return 'pimcore_studio_api_delete_data_object_grid_configuration'; //is this correct ? + } + + /** + * {@inheritdoc} + */ + public function getSingleItemForDownload(int $id): array + { + try { + $object = DataObject::getById((int)$id); + } catch (NotFoundException) { + throw new NotFoundException('Data Object Not Found', $id); + } + + return [ + 'id' => $object->getId(), + 'key' => $object->getKey(), + 'path' => $object->getPath(), + 'className' => $object->getClassName(), + 'fullPath' => $object->getFullPath(), + 'parentId' => $object->getParentId(), + 'type' => $object->getType(), + 'published' => $object->isPublished(), + 'creationDate' => date('Y-m-d H:i:s', $object->getCreationDate()), + 'modificationDate' => date('Y-m-d H:i:s', $object->getModificationDate()), + ]; + } + + public function getName(): string + { + return 'Data Objects'; + } + + public function getKey(): string + { + return 'data_objects'; + } + + public function getSortPriority(): int + { + return 10; + } + + /** + * {@inheritdoc} + */ + public function getRequiredPermissions(): array + { + return [UserPermissions::DATA_OBJECTS->value]; + } + + /** + * {@inheritdoc} + */ + public function getAvailableColumns(): array + { + return [ + new GdprDataColumn('id', 'ID'), + new GdprDataColumn('key', 'Key'), + new GdprDataColumn('fullPath', 'Full Path'), + new GdprDataColumn('path', 'Path'), + new GdprDataColumn('className', 'Class Name'), + new GdprDataColumn('parentId', 'Parent ID'), + new GdprDataColumn('type', 'Type'), + new GdprDataColumn('published', 'Published'), + new GdprDataColumn('creationDate', 'Created At'), + new GdprDataColumn('modificationDate', 'Updated At'), + ]; + } +} diff --git a/src/Gdpr/Provider/DataProviderInterface.php b/src/Gdpr/Provider/DataProviderInterface.php index d546101ad..c620d69dc 100644 --- a/src/Gdpr/Provider/DataProviderInterface.php +++ b/src/Gdpr/Provider/DataProviderInterface.php @@ -18,13 +18,14 @@ use Pimcore\Bundle\StudioBackendBundle\Gdpr\Attribute\Request\SearchTerms; use Pimcore\Bundle\StudioBackendBundle\Gdpr\Schema\GdprDataColumn; use Pimcore\Bundle\StudioBackendBundle\Gdpr\Schema\GdprDataRow; +use Pimcore\Bundle\StudioBackendBundle\Gdpr\Schema\GdprSearchOptions; interface DataProviderInterface { /** * @return GdprDataRow[] */ - public function findData(SearchTerms $terms): array; + public function findData(SearchTerms $terms, GdprSearchOptions $options): array; public function getDeleteSwaggerOperationId(): string; diff --git a/src/Gdpr/Provider/PimcoreUserProvider.php b/src/Gdpr/Provider/PimcoreUserProvider.php index d5acfd810..6388b4676 100644 --- a/src/Gdpr/Provider/PimcoreUserProvider.php +++ b/src/Gdpr/Provider/PimcoreUserProvider.php @@ -18,6 +18,7 @@ use Pimcore\Bundle\StudioBackendBundle\Gdpr\Schema\GdprDataRow; use Pimcore\Bundle\StudioBackendBundle\Security\Service\SecurityServiceInterface; use Pimcore\Bundle\StudioBackendBundle\Util\Constant\UserPermissions; +use Pimcore\Bundle\StudioBackendBundle\Gdpr\Schema\GdprSearchOptions; use Pimcore\Db; use Pimcore\Model\User; use Pimcore\Model\User\Listing; @@ -37,7 +38,7 @@ public function __construct( /** * {@inheritdoc} */ - public function findData(SearchTerms $terms): array + public function findData(SearchTerms $terms, GdprSearchOptions $options): array { $listing = new Listing(); diff --git a/src/Gdpr/Schema/GdprSearchOptions.php b/src/Gdpr/Schema/GdprSearchOptions.php new file mode 100644 index 000000000..03c92e3fb --- /dev/null +++ b/src/Gdpr/Schema/GdprSearchOptions.php @@ -0,0 +1,43 @@ + new Type('string'), + 'direction' => new Choice(['ASC', 'DESC', 'asc', 'desc']) + ], + allowMissingFields: true + )] + public ?array $sortFilter = null + ) { + } +} \ No newline at end of file diff --git a/src/Gdpr/Service/GdprManagerService.php b/src/Gdpr/Service/GdprManagerService.php index 73125fcd9..3cba06081 100644 --- a/src/Gdpr/Service/GdprManagerService.php +++ b/src/Gdpr/Service/GdprManagerService.php @@ -70,7 +70,7 @@ public function search(GdprStructuredSearchRequest $request): GdprSearchResultCo $this->checkProviderPermission($provider); - $results = $provider->findData($request->searchTerms); + $results = $provider->findData($request->searchTerms, $request->filters); if (!empty($results)) { $allResults[] = new GdprSearchResult( From 54314c437f2078cb20bd64c66c9601185699436b Mon Sep 17 00:00:00 2001 From: stunnerparas <49896041+stunnerparas@users.noreply.github.com> Date: Wed, 26 Nov 2025 02:48:38 +0000 Subject: [PATCH 02/39] Apply php-cs-fixer changes --- .../Attribute/Request/GdprRequestBody.php | 8 +-- .../GdprStructuredSearchRequest.php | 2 +- src/Gdpr/Provider/DataObjectProvider.php | 54 +++++++++---------- src/Gdpr/Provider/PimcoreUserProvider.php | 2 +- src/Gdpr/Schema/GdprSearchOptions.php | 8 +-- 5 files changed, 34 insertions(+), 40 deletions(-) diff --git a/src/Gdpr/Attribute/Request/GdprRequestBody.php b/src/Gdpr/Attribute/Request/GdprRequestBody.php index f61f079a5..32b8edc5e 100644 --- a/src/Gdpr/Attribute/Request/GdprRequestBody.php +++ b/src/Gdpr/Attribute/Request/GdprRequestBody.php @@ -49,7 +49,7 @@ public function __construct() description: 'The object containing the search values.', type: 'object' ), - + new Property( property: 'filters', description: 'Pagination and sorting options', @@ -61,12 +61,12 @@ public function __construct() type: 'object', properties: [ new Property(property: 'key', type: 'string', example: 'id'), - new Property(property: 'direction', type: 'string', example: 'ASC') + new Property(property: 'direction', type: 'string', example: 'ASC'), ] - ) + ), ], type: 'object' - ) + ), ], type: 'object', ), diff --git a/src/Gdpr/MappedParameter/GdprStructuredSearchRequest.php b/src/Gdpr/MappedParameter/GdprStructuredSearchRequest.php index 6d0e8f2e2..0dbde8963 100644 --- a/src/Gdpr/MappedParameter/GdprStructuredSearchRequest.php +++ b/src/Gdpr/MappedParameter/GdprStructuredSearchRequest.php @@ -14,12 +14,12 @@ namespace Pimcore\Bundle\StudioBackendBundle\Gdpr\MappedParameter; use Pimcore\Bundle\StudioBackendBundle\Gdpr\Attribute\Request\SearchTerms; +use Pimcore\Bundle\StudioBackendBundle\Gdpr\Schema\GdprSearchOptions; use Symfony\Component\Validator\Constraints\All; use Symfony\Component\Validator\Constraints\NotBlank; use Symfony\Component\Validator\Constraints\NotNull; use Symfony\Component\Validator\Constraints\Type; use Symfony\Component\Validator\Constraints\Valid; -use Pimcore\Bundle\StudioBackendBundle\Gdpr\Schema\GdprSearchOptions; /** * @internal diff --git a/src/Gdpr/Provider/DataObjectProvider.php b/src/Gdpr/Provider/DataObjectProvider.php index 31367b9d1..2bd254763 100644 --- a/src/Gdpr/Provider/DataObjectProvider.php +++ b/src/Gdpr/Provider/DataObjectProvider.php @@ -12,34 +12,32 @@ namespace Pimcore\Bundle\StudioBackendBundle\Gdpr\Provider; -use Pimcore\Bundle\StudioBackendBundle\Gdpr\Attribute\Request\SearchTerms; -use Pimcore\Bundle\StudioBackendBundle\Gdpr\Schema\GdprDataColumn; -use Pimcore\Bundle\StudioBackendBundle\Gdpr\Schema\GdprDataRow; -use Pimcore\Model\DataObject; +use Pimcore\Bundle\GenericDataIndexBundle\Enum\Search\SortDirection; use Pimcore\Bundle\StudioBackendBundle\DataIndex\Provider\DataObjectQueryProviderInterface; use Pimcore\Bundle\StudioBackendBundle\DataIndex\Query\QueryInterface; -use Pimcore\Bundle\StudioBackendBundle\Util\Constant\UserPermissions; -use Pimcore\Bundle\StudioBackendBundle\Gdpr\Schema\GdprSearchOptions; use Pimcore\Bundle\StudioBackendBundle\DataIndex\Service\DataObjectSearchServiceInterface; use Pimcore\Bundle\StudioBackendBundle\Exception\Api\NotFoundException; -use Pimcore\Bundle\GenericDataIndexBundle\Enum\Search\SortDirection; - +use Pimcore\Bundle\StudioBackendBundle\Gdpr\Attribute\Request\SearchTerms; +use Pimcore\Bundle\StudioBackendBundle\Gdpr\Schema\GdprDataColumn; +use Pimcore\Bundle\StudioBackendBundle\Gdpr\Schema\GdprDataRow; +use Pimcore\Bundle\StudioBackendBundle\Gdpr\Schema\GdprSearchOptions; +use Pimcore\Bundle\StudioBackendBundle\Util\Constant\UserPermissions; +use Pimcore\Model\DataObject; /** * @internal */ final readonly class DataObjectProvider implements DataProviderInterface { - public function __construct( private DataObjectQueryProviderInterface $query, private DataObjectSearchServiceInterface $searchService, - ) {} - + ) { + } /** * {@inheritdoc} - */ + */ public function findData(SearchTerms $terms, GdprSearchOptions $options): array { $query = $this->query->createDataObjectQuery(); @@ -57,7 +55,7 @@ public function findData(SearchTerms $terms, GdprSearchOptions $options): array $items = $searchResult->getItems(); return array_map( - fn($item) => new GdprDataRow([ + fn ($item) => new GdprDataRow([ 'id' => $item->getId(), 'key' => $item->getKey(), 'path' => $item->getPath(), @@ -73,7 +71,6 @@ public function findData(SearchTerms $terms, GdprSearchOptions $options): array ); } - private function applySearchOptions(QueryInterface $query, GdprSearchOptions $options): void { // Pagination @@ -89,9 +86,6 @@ private function applySearchOptions(QueryInterface $query, GdprSearchOptions $op } } - - - private function buildSearchTerm(SearchTerms $terms): string { return implode(' ', array_filter([$terms->id, $terms->firstname, $terms->lastname, $terms->email])); @@ -104,7 +98,7 @@ public function getDeleteSwaggerOperationId(): string /** * {@inheritdoc} - */ + */ public function getSingleItemForDownload(int $id): array { try { @@ -155,17 +149,17 @@ public function getRequiredPermissions(): array */ public function getAvailableColumns(): array { - return [ - new GdprDataColumn('id', 'ID'), - new GdprDataColumn('key', 'Key'), - new GdprDataColumn('fullPath', 'Full Path'), - new GdprDataColumn('path', 'Path'), - new GdprDataColumn('className', 'Class Name'), - new GdprDataColumn('parentId', 'Parent ID'), - new GdprDataColumn('type', 'Type'), - new GdprDataColumn('published', 'Published'), - new GdprDataColumn('creationDate', 'Created At'), - new GdprDataColumn('modificationDate', 'Updated At'), - ]; + return [ + new GdprDataColumn('id', 'ID'), + new GdprDataColumn('key', 'Key'), + new GdprDataColumn('fullPath', 'Full Path'), + new GdprDataColumn('path', 'Path'), + new GdprDataColumn('className', 'Class Name'), + new GdprDataColumn('parentId', 'Parent ID'), + new GdprDataColumn('type', 'Type'), + new GdprDataColumn('published', 'Published'), + new GdprDataColumn('creationDate', 'Created At'), + new GdprDataColumn('modificationDate', 'Updated At'), + ]; } } diff --git a/src/Gdpr/Provider/PimcoreUserProvider.php b/src/Gdpr/Provider/PimcoreUserProvider.php index 6388b4676..80310ae08 100644 --- a/src/Gdpr/Provider/PimcoreUserProvider.php +++ b/src/Gdpr/Provider/PimcoreUserProvider.php @@ -16,9 +16,9 @@ use Pimcore\Bundle\StudioBackendBundle\Gdpr\Attribute\Request\SearchTerms; use Pimcore\Bundle\StudioBackendBundle\Gdpr\Schema\GdprDataColumn; use Pimcore\Bundle\StudioBackendBundle\Gdpr\Schema\GdprDataRow; +use Pimcore\Bundle\StudioBackendBundle\Gdpr\Schema\GdprSearchOptions; use Pimcore\Bundle\StudioBackendBundle\Security\Service\SecurityServiceInterface; use Pimcore\Bundle\StudioBackendBundle\Util\Constant\UserPermissions; -use Pimcore\Bundle\StudioBackendBundle\Gdpr\Schema\GdprSearchOptions; use Pimcore\Db; use Pimcore\Model\User; use Pimcore\Model\User\Listing; diff --git a/src/Gdpr/Schema/GdprSearchOptions.php b/src/Gdpr/Schema/GdprSearchOptions.php index 03c92e3fb..25711c1dc 100644 --- a/src/Gdpr/Schema/GdprSearchOptions.php +++ b/src/Gdpr/Schema/GdprSearchOptions.php @@ -7,8 +7,8 @@ * Full copyright and license information is available in * LICENSE.md which is distributed with this source code. * - * @copyright Copyright (c) Pimcore GmbH (https://www.pimcore.com) - * @license Pimcore Open Core License (POCL) + * @copyright Copyright (c) Pimcore GmbH (https://www.pimcore.com) + * @license Pimcore Open Core License (POCL) */ namespace Pimcore\Bundle\StudioBackendBundle\Gdpr\Schema; @@ -33,11 +33,11 @@ public function __construct( #[Collection( fields: [ 'key' => new Type('string'), - 'direction' => new Choice(['ASC', 'DESC', 'asc', 'desc']) + 'direction' => new Choice(['ASC', 'DESC', 'asc', 'desc']), ], allowMissingFields: true )] public ?array $sortFilter = null ) { } -} \ No newline at end of file +} From d79721ccfc870cd9abd3d4367a9ced3ef015b43d Mon Sep 17 00:00:00 2001 From: stunnerparas Date: Wed, 26 Nov 2025 09:24:24 +0000 Subject: [PATCH 03/39] changes --- src/Gdpr/Provider/DataObjectProvider.php | 112 +++++++++++++---------- 1 file changed, 65 insertions(+), 47 deletions(-) diff --git a/src/Gdpr/Provider/DataObjectProvider.php b/src/Gdpr/Provider/DataObjectProvider.php index 2bd254763..4dcba2b10 100644 --- a/src/Gdpr/Provider/DataObjectProvider.php +++ b/src/Gdpr/Provider/DataObjectProvider.php @@ -12,37 +12,42 @@ namespace Pimcore\Bundle\StudioBackendBundle\Gdpr\Provider; -use Pimcore\Bundle\GenericDataIndexBundle\Enum\Search\SortDirection; -use Pimcore\Bundle\StudioBackendBundle\DataIndex\Provider\DataObjectQueryProviderInterface; -use Pimcore\Bundle\StudioBackendBundle\DataIndex\Query\QueryInterface; -use Pimcore\Bundle\StudioBackendBundle\DataIndex\Service\DataObjectSearchServiceInterface; -use Pimcore\Bundle\StudioBackendBundle\Exception\Api\NotFoundException; use Pimcore\Bundle\StudioBackendBundle\Gdpr\Attribute\Request\SearchTerms; use Pimcore\Bundle\StudioBackendBundle\Gdpr\Schema\GdprDataColumn; use Pimcore\Bundle\StudioBackendBundle\Gdpr\Schema\GdprDataRow; -use Pimcore\Bundle\StudioBackendBundle\Gdpr\Schema\GdprSearchOptions; -use Pimcore\Bundle\StudioBackendBundle\Util\Constant\UserPermissions; use Pimcore\Model\DataObject; +use Pimcore\Bundle\StudioBackendBundle\DataIndex\Provider\DataObjectQueryProviderInterface; +use Pimcore\Bundle\StudioBackendBundle\DataIndex\Query\QueryInterface; +use Pimcore\Bundle\StudioBackendBundle\Util\Constant\UserPermissions; +use Pimcore\Bundle\StudioBackendBundle\Gdpr\Schema\GdprSearchOptions; +use Pimcore\Bundle\StudioBackendBundle\DataIndex\Service\DataObjectSearchServiceInterface; +use Pimcore\Bundle\StudioBackendBundle\Exception\Api\NotFoundException; +use Pimcore\Bundle\GenericDataIndexBundle\Enum\Search\SortDirection; +use Pimcore\Bundle\StudioBackendBundle\Exception\Api\InvalidSearchException; +use Pimcore\Model\DataObject\Concrete; +use Pimcore\Bundle\StudioBackendBundle\Util\Constant\HttpResponseCodes; + /** * @internal */ final readonly class DataObjectProvider implements DataProviderInterface { + private const DATE_FORMAT = 'Y-m-d H:i:s'; + public function __construct( private DataObjectQueryProviderInterface $query, private DataObjectSearchServiceInterface $searchService, - ) { - } + ) {} /** * {@inheritdoc} - */ + */ public function findData(SearchTerms $terms, GdprSearchOptions $options): array { $query = $this->query->createDataObjectQuery(); - $searchTerm = $this->buildSearchTerm($terms); + $searchTerm = $this->buildSearchTermForSearch($terms); $query->filterFullText($searchTerm); @@ -55,40 +60,49 @@ public function findData(SearchTerms $terms, GdprSearchOptions $options): array $items = $searchResult->getItems(); return array_map( - fn ($item) => new GdprDataRow([ + fn($item) => new GdprDataRow([ 'id' => $item->getId(), 'key' => $item->getKey(), 'path' => $item->getPath(), - 'className' => $item->getClassName(), + 'className' => ($item instanceof Concrete) ? $item->getClassName() : null, 'fullPath' => $item->getFullPath(), 'parentId' => $item->getParentId(), 'type' => $item->getType(), 'published' => $item->isPublished(), - 'creationDate' => date('Y-m-d H:i:s', $item->getCreationDate()), - 'modificationDate' => date('Y-m-d H:i:s', $item->getModificationDate()), + 'creationDate' => date(self::DATE_FORMAT, $item->getCreationDate()), + 'modificationDate' => date(self::DATE_FORMAT, $item->getModificationDate()), ], $columns), $items ); } - + private function applySearchOptions(QueryInterface $query, GdprSearchOptions $options): void { - // Pagination $query->setPage($options->page); $query->setPageSize($options->pageSize); - // Sorting - if ($options->sortFilter && isset($options->sortFilter['key'], $options->sortFilter['direction'])) { - $directionEnum = SortDirection::tryFrom($options->sortFilter['direction']); - if ($directionEnum) { - $query->orderByField($options->sortFilter['key'], $directionEnum); + $filter = $options->sortFilter; + + if ($filter !== null && isset($filter['key'], $filter['direction'])) { + + $directionEnum = SortDirection::ASC; + + if (strtolower($filter['direction']) === SortDirection::DESC->value) { + $directionEnum = SortDirection::DESC; } + + $query->orderByField($filter['key'], $directionEnum); } } - private function buildSearchTerm(SearchTerms $terms): string + private function buildSearchTermForSearch(SearchTerms $terms): string { - return implode(' ', array_filter([$terms->id, $terms->firstname, $terms->lastname, $terms->email])); + return trim(preg_replace('/\s+/', ' ', implode(' ', array_filter([ + $terms->id, + $terms->firstname, + $terms->lastname, + $terms->email, + ])))); } public function getDeleteSwaggerOperationId(): string @@ -98,7 +112,7 @@ public function getDeleteSwaggerOperationId(): string /** * {@inheritdoc} - */ + */ public function getSingleItemForDownload(int $id): array { try { @@ -107,17 +121,21 @@ public function getSingleItemForDownload(int $id): array throw new NotFoundException('Data Object Not Found', $id); } + if (!$object instanceof Concrete) { + throw new NotFoundException('Requested object is not a Concrete data object', $id); + } + return [ - 'id' => $object->getId(), - 'key' => $object->getKey(), - 'path' => $object->getPath(), - 'className' => $object->getClassName(), - 'fullPath' => $object->getFullPath(), - 'parentId' => $object->getParentId(), - 'type' => $object->getType(), - 'published' => $object->isPublished(), - 'creationDate' => date('Y-m-d H:i:s', $object->getCreationDate()), - 'modificationDate' => date('Y-m-d H:i:s', $object->getModificationDate()), + 'id' => $object->getId(), + 'key' => $object->getKey(), + 'path' => $object->getPath(), + 'className' => $object->getClassName(), + 'fullPath' => $object->getFullPath(), + 'parentId' => $object->getParentId(), + 'type' => $object->getType(), + 'published' => $object->isPublished(), + 'creationDate' => date(self::DATE_FORMAT, $object->getCreationDate()), + 'modificationDate' => date(self::DATE_FORMAT, $object->getModificationDate()), ]; } @@ -149,17 +167,17 @@ public function getRequiredPermissions(): array */ public function getAvailableColumns(): array { - return [ - new GdprDataColumn('id', 'ID'), - new GdprDataColumn('key', 'Key'), - new GdprDataColumn('fullPath', 'Full Path'), - new GdprDataColumn('path', 'Path'), - new GdprDataColumn('className', 'Class Name'), - new GdprDataColumn('parentId', 'Parent ID'), - new GdprDataColumn('type', 'Type'), - new GdprDataColumn('published', 'Published'), - new GdprDataColumn('creationDate', 'Created At'), - new GdprDataColumn('modificationDate', 'Updated At'), - ]; + return [ + new GdprDataColumn('id', 'ID'), + new GdprDataColumn('key', 'Key'), + new GdprDataColumn('fullPath', 'Full Path'), + new GdprDataColumn('path', 'Path'), + new GdprDataColumn('className', 'Class Name'), + new GdprDataColumn('parentId', 'Parent ID'), + new GdprDataColumn('type', 'Type'), + new GdprDataColumn('published', 'Published'), + new GdprDataColumn('creationDate', 'Created At'), + new GdprDataColumn('modificationDate', 'Updated At'), + ]; } } From a41bbfa8f065f8964aadef2eca485b146603b62a Mon Sep 17 00:00:00 2001 From: stunnerparas <49896041+stunnerparas@users.noreply.github.com> Date: Wed, 26 Nov 2025 09:29:12 +0000 Subject: [PATCH 04/39] Apply php-cs-fixer changes --- src/Gdpr/Provider/DataObjectProvider.php | 58 ++++++++++++------------ 1 file changed, 28 insertions(+), 30 deletions(-) diff --git a/src/Gdpr/Provider/DataObjectProvider.php b/src/Gdpr/Provider/DataObjectProvider.php index 4dcba2b10..dc96f6efe 100644 --- a/src/Gdpr/Provider/DataObjectProvider.php +++ b/src/Gdpr/Provider/DataObjectProvider.php @@ -12,21 +12,18 @@ namespace Pimcore\Bundle\StudioBackendBundle\Gdpr\Provider; -use Pimcore\Bundle\StudioBackendBundle\Gdpr\Attribute\Request\SearchTerms; -use Pimcore\Bundle\StudioBackendBundle\Gdpr\Schema\GdprDataColumn; -use Pimcore\Bundle\StudioBackendBundle\Gdpr\Schema\GdprDataRow; -use Pimcore\Model\DataObject; +use Pimcore\Bundle\GenericDataIndexBundle\Enum\Search\SortDirection; use Pimcore\Bundle\StudioBackendBundle\DataIndex\Provider\DataObjectQueryProviderInterface; use Pimcore\Bundle\StudioBackendBundle\DataIndex\Query\QueryInterface; -use Pimcore\Bundle\StudioBackendBundle\Util\Constant\UserPermissions; -use Pimcore\Bundle\StudioBackendBundle\Gdpr\Schema\GdprSearchOptions; use Pimcore\Bundle\StudioBackendBundle\DataIndex\Service\DataObjectSearchServiceInterface; use Pimcore\Bundle\StudioBackendBundle\Exception\Api\NotFoundException; -use Pimcore\Bundle\GenericDataIndexBundle\Enum\Search\SortDirection; -use Pimcore\Bundle\StudioBackendBundle\Exception\Api\InvalidSearchException; +use Pimcore\Bundle\StudioBackendBundle\Gdpr\Attribute\Request\SearchTerms; +use Pimcore\Bundle\StudioBackendBundle\Gdpr\Schema\GdprDataColumn; +use Pimcore\Bundle\StudioBackendBundle\Gdpr\Schema\GdprDataRow; +use Pimcore\Bundle\StudioBackendBundle\Gdpr\Schema\GdprSearchOptions; +use Pimcore\Bundle\StudioBackendBundle\Util\Constant\UserPermissions; +use Pimcore\Model\DataObject; use Pimcore\Model\DataObject\Concrete; -use Pimcore\Bundle\StudioBackendBundle\Util\Constant\HttpResponseCodes; - /** * @internal @@ -34,15 +31,16 @@ final readonly class DataObjectProvider implements DataProviderInterface { private const DATE_FORMAT = 'Y-m-d H:i:s'; - + public function __construct( private DataObjectQueryProviderInterface $query, private DataObjectSearchServiceInterface $searchService, - ) {} + ) { + } /** * {@inheritdoc} - */ + */ public function findData(SearchTerms $terms, GdprSearchOptions $options): array { $query = $this->query->createDataObjectQuery(); @@ -60,7 +58,7 @@ public function findData(SearchTerms $terms, GdprSearchOptions $options): array $items = $searchResult->getItems(); return array_map( - fn($item) => new GdprDataRow([ + fn ($item) => new GdprDataRow([ 'id' => $item->getId(), 'key' => $item->getKey(), 'path' => $item->getPath(), @@ -75,7 +73,7 @@ public function findData(SearchTerms $terms, GdprSearchOptions $options): array $items ); } - + private function applySearchOptions(QueryInterface $query, GdprSearchOptions $options): void { $query->setPage($options->page); @@ -84,7 +82,7 @@ private function applySearchOptions(QueryInterface $query, GdprSearchOptions $op $filter = $options->sortFilter; if ($filter !== null && isset($filter['key'], $filter['direction'])) { - + $directionEnum = SortDirection::ASC; if (strtolower($filter['direction']) === SortDirection::DESC->value) { @@ -112,7 +110,7 @@ public function getDeleteSwaggerOperationId(): string /** * {@inheritdoc} - */ + */ public function getSingleItemForDownload(int $id): array { try { @@ -129,7 +127,7 @@ public function getSingleItemForDownload(int $id): array 'id' => $object->getId(), 'key' => $object->getKey(), 'path' => $object->getPath(), - 'className' => $object->getClassName(), + 'className' => $object->getClassName(), 'fullPath' => $object->getFullPath(), 'parentId' => $object->getParentId(), 'type' => $object->getType(), @@ -167,17 +165,17 @@ public function getRequiredPermissions(): array */ public function getAvailableColumns(): array { - return [ - new GdprDataColumn('id', 'ID'), - new GdprDataColumn('key', 'Key'), - new GdprDataColumn('fullPath', 'Full Path'), - new GdprDataColumn('path', 'Path'), - new GdprDataColumn('className', 'Class Name'), - new GdprDataColumn('parentId', 'Parent ID'), - new GdprDataColumn('type', 'Type'), - new GdprDataColumn('published', 'Published'), - new GdprDataColumn('creationDate', 'Created At'), - new GdprDataColumn('modificationDate', 'Updated At'), - ]; + return [ + new GdprDataColumn('id', 'ID'), + new GdprDataColumn('key', 'Key'), + new GdprDataColumn('fullPath', 'Full Path'), + new GdprDataColumn('path', 'Path'), + new GdprDataColumn('className', 'Class Name'), + new GdprDataColumn('parentId', 'Parent ID'), + new GdprDataColumn('type', 'Type'), + new GdprDataColumn('published', 'Published'), + new GdprDataColumn('creationDate', 'Created At'), + new GdprDataColumn('modificationDate', 'Updated At'), + ]; } } From 097e4030f87e8084c570998bb20c4f75b6599ce6 Mon Sep 17 00:00:00 2001 From: stunnerparas Date: Wed, 26 Nov 2025 10:10:12 +0000 Subject: [PATCH 05/39] Also add pagination in Pimcore Users --- src/Gdpr/Provider/PimcoreUserProvider.php | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/Gdpr/Provider/PimcoreUserProvider.php b/src/Gdpr/Provider/PimcoreUserProvider.php index 80310ae08..261eab546 100644 --- a/src/Gdpr/Provider/PimcoreUserProvider.php +++ b/src/Gdpr/Provider/PimcoreUserProvider.php @@ -19,6 +19,7 @@ use Pimcore\Bundle\StudioBackendBundle\Gdpr\Schema\GdprSearchOptions; use Pimcore\Bundle\StudioBackendBundle\Security\Service\SecurityServiceInterface; use Pimcore\Bundle\StudioBackendBundle\Util\Constant\UserPermissions; +use Pimcore\Bundle\GenericDataIndexBundle\Enum\Search\SortDirection; use Pimcore\Db; use Pimcore\Model\User; use Pimcore\Model\User\Listing; @@ -70,6 +71,8 @@ public function findData(SearchTerms $terms, GdprSearchOptions $options): array ); } + $this->applySearchOptions($listing, $options); + $users = $listing->getUsers(); $columns = $this->getAvailableColumns(); @@ -90,6 +93,21 @@ public function findData(SearchTerms $terms, GdprSearchOptions $options): array ); } + private function applySearchOptions(Listing $listing, GdprSearchOptions $options): void + { + $listing->setOffset(($options->page - 1) * $options->pageSize); + $listing->setLimit($options->pageSize); + + if (($filter = $options->sortFilter) && isset($filter['key'], $filter['direction'])) { + $listing->setOrderKey($filter['key']); + $listing->setOrder( + strtolower($filter['direction']) === SortDirection::DESC->value + ? SortDirection::DESC->value + : SortDirection::ASC->value + ); + } + } + public function getDeleteSwaggerOperationId(): string { return 'user_delete_by_id'; From 5f86dbe52c79760bbcd4ec65550b490adf099bd6 Mon Sep 17 00:00:00 2001 From: stunnerparas <49896041+stunnerparas@users.noreply.github.com> Date: Wed, 26 Nov 2025 10:12:04 +0000 Subject: [PATCH 06/39] Apply php-cs-fixer changes --- src/Gdpr/Provider/PimcoreUserProvider.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Gdpr/Provider/PimcoreUserProvider.php b/src/Gdpr/Provider/PimcoreUserProvider.php index 261eab546..5f13357ba 100644 --- a/src/Gdpr/Provider/PimcoreUserProvider.php +++ b/src/Gdpr/Provider/PimcoreUserProvider.php @@ -12,6 +12,7 @@ namespace Pimcore\Bundle\StudioBackendBundle\Gdpr\Provider; +use Pimcore\Bundle\GenericDataIndexBundle\Enum\Search\SortDirection; use Pimcore\Bundle\StudioBackendBundle\Exception\Api\NotFoundException; use Pimcore\Bundle\StudioBackendBundle\Gdpr\Attribute\Request\SearchTerms; use Pimcore\Bundle\StudioBackendBundle\Gdpr\Schema\GdprDataColumn; @@ -19,7 +20,6 @@ use Pimcore\Bundle\StudioBackendBundle\Gdpr\Schema\GdprSearchOptions; use Pimcore\Bundle\StudioBackendBundle\Security\Service\SecurityServiceInterface; use Pimcore\Bundle\StudioBackendBundle\Util\Constant\UserPermissions; -use Pimcore\Bundle\GenericDataIndexBundle\Enum\Search\SortDirection; use Pimcore\Db; use Pimcore\Model\User; use Pimcore\Model\User\Listing; @@ -95,8 +95,8 @@ public function findData(SearchTerms $terms, GdprSearchOptions $options): array private function applySearchOptions(Listing $listing, GdprSearchOptions $options): void { - $listing->setOffset(($options->page - 1) * $options->pageSize); - $listing->setLimit($options->pageSize); + $listing->setOffset(($options->page - 1) * $options->pageSize); + $listing->setLimit($options->pageSize); if (($filter = $options->sortFilter) && isset($filter['key'], $filter['direction'])) { $listing->setOrderKey($filter['key']); From c50f9c4f706bd9a9124d0fb1ebe737c165ef1c37 Mon Sep 17 00:00:00 2001 From: stunnerparas Date: Wed, 26 Nov 2025 10:30:13 +0000 Subject: [PATCH 07/39] ci issue fix --- src/Gdpr/Provider/DataObjectProvider.php | 22 ++++++++++++++++------ src/Gdpr/Provider/PimcoreUserProvider.php | 4 +++- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/src/Gdpr/Provider/DataObjectProvider.php b/src/Gdpr/Provider/DataObjectProvider.php index dc96f6efe..a282ae29e 100644 --- a/src/Gdpr/Provider/DataObjectProvider.php +++ b/src/Gdpr/Provider/DataObjectProvider.php @@ -95,12 +95,22 @@ private function applySearchOptions(QueryInterface $query, GdprSearchOptions $op private function buildSearchTermForSearch(SearchTerms $terms): string { - return trim(preg_replace('/\s+/', ' ', implode(' ', array_filter([ - $terms->id, - $terms->firstname, - $terms->lastname, - $terms->email, - ])))); + // Builds a normalized search term string by combining non-empty values (id, firstname, lastname, email) and collapsing multiple spaces. + return trim( + preg_replace( + '/\s+/u', + ' ', + implode( + ' ', + array_filter([ + $terms->id, + $terms->firstname, + $terms->lastname, + $terms->email, + ]) + ) + ) + ); } public function getDeleteSwaggerOperationId(): string diff --git a/src/Gdpr/Provider/PimcoreUserProvider.php b/src/Gdpr/Provider/PimcoreUserProvider.php index 5f13357ba..2d33cbc80 100644 --- a/src/Gdpr/Provider/PimcoreUserProvider.php +++ b/src/Gdpr/Provider/PimcoreUserProvider.php @@ -98,7 +98,9 @@ private function applySearchOptions(Listing $listing, GdprSearchOptions $options $listing->setOffset(($options->page - 1) * $options->pageSize); $listing->setLimit($options->pageSize); - if (($filter = $options->sortFilter) && isset($filter['key'], $filter['direction'])) { + $filter = $options->sortFilter; + + if ($filter && isset($filter['key'], $filter['direction'])) { $listing->setOrderKey($filter['key']); $listing->setOrder( strtolower($filter['direction']) === SortDirection::DESC->value From 5692ef6fefbbcb1a12b15866c2a1f6388ddc0b6f Mon Sep 17 00:00:00 2001 From: stunnerparas Date: Wed, 26 Nov 2025 10:32:27 +0000 Subject: [PATCH 08/39] ci issue fix --- src/Gdpr/Provider/DataObjectProvider.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Gdpr/Provider/DataObjectProvider.php b/src/Gdpr/Provider/DataObjectProvider.php index a282ae29e..7e62d94b9 100644 --- a/src/Gdpr/Provider/DataObjectProvider.php +++ b/src/Gdpr/Provider/DataObjectProvider.php @@ -95,7 +95,6 @@ private function applySearchOptions(QueryInterface $query, GdprSearchOptions $op private function buildSearchTermForSearch(SearchTerms $terms): string { - // Builds a normalized search term string by combining non-empty values (id, firstname, lastname, email) and collapsing multiple spaces. return trim( preg_replace( '/\s+/u', From 00544002afc440dfa326af692063a0a0118c43c2 Mon Sep 17 00:00:00 2001 From: stunnerparas Date: Wed, 26 Nov 2025 17:43:44 +0000 Subject: [PATCH 09/39] changes in export of data object and some code improvement --- .../Attribute/Request/GdprRequestBody.php | 19 +-- src/Gdpr/Attribute/Request/SearchTerms.php | 8 +- .../SearchDataProviderController.php | 4 +- ....php => GdprStructuredSearchParameter.php} | 2 +- src/Gdpr/Provider/DataObjectProvider.php | 73 ++++------- src/Gdpr/Provider/Legacy/ObjectExporter.php | 114 ++++++++++++++++++ src/Gdpr/Service/GdprManagerService.php | 4 +- .../Service/GdprManagerServiceInterface.php | 4 +- 8 files changed, 150 insertions(+), 78 deletions(-) rename src/Gdpr/MappedParameter/{GdprStructuredSearchRequest.php => GdprStructuredSearchParameter.php} (95%) create mode 100644 src/Gdpr/Provider/Legacy/ObjectExporter.php diff --git a/src/Gdpr/Attribute/Request/GdprRequestBody.php b/src/Gdpr/Attribute/Request/GdprRequestBody.php index 32b8edc5e..6bb724e66 100644 --- a/src/Gdpr/Attribute/Request/GdprRequestBody.php +++ b/src/Gdpr/Attribute/Request/GdprRequestBody.php @@ -18,6 +18,7 @@ use OpenApi\Attributes\JsonContent; use OpenApi\Attributes\Property; use OpenApi\Attributes\RequestBody; +use Pimcore\Bundle\StudioBackendBundle\Filter\Attribute\Property\FilterProperty; /** * @internal @@ -50,23 +51,7 @@ public function __construct() type: 'object' ), - new Property( - property: 'filters', - description: 'Pagination and sorting options', - properties: [ - new Property(property: 'page', type: 'integer', example: 1), - new Property(property: 'pageSize', type: 'integer', example: 20), - new Property( - property: 'sortFilter', - type: 'object', - properties: [ - new Property(property: 'key', type: 'string', example: 'id'), - new Property(property: 'direction', type: 'string', example: 'ASC'), - ] - ), - ], - type: 'object' - ), + new FilterProperty(), ], type: 'object', ), diff --git a/src/Gdpr/Attribute/Request/SearchTerms.php b/src/Gdpr/Attribute/Request/SearchTerms.php index 8edc508ba..7e2b56535 100644 --- a/src/Gdpr/Attribute/Request/SearchTerms.php +++ b/src/Gdpr/Attribute/Request/SearchTerms.php @@ -31,19 +31,19 @@ public function __construct( #[Property(description: 'The ID to search for.', type: 'int', nullable: true)] #[Type('int')] - public ?int $id = null, + private ?int $id = null, #[Property(description: 'The first name to search for. ', type: 'string', nullable: true)] #[Type('string')] - public ?string $firstname = null, + private ?string $firstname = null, #[Property(description: 'The last name to search for.', type: 'string', nullable: true)] #[Type('string')] - public ?string $lastname = null, + private ?string $lastname = null, #[Property(description: 'The email address to search for.', type: 'string', nullable: true)] #[Type('string')] - public ?string $email = null, + private ?string $email = null, ) { if ($this->id === null && $this->firstname === null && diff --git a/src/Gdpr/Controller/SearchDataProviderController.php b/src/Gdpr/Controller/SearchDataProviderController.php index a64744f32..8912506b2 100644 --- a/src/Gdpr/Controller/SearchDataProviderController.php +++ b/src/Gdpr/Controller/SearchDataProviderController.php @@ -17,7 +17,7 @@ use Pimcore\Bundle\StudioBackendBundle\Controller\AbstractApiController; use Pimcore\Bundle\StudioBackendBundle\Exception\Api\NotFoundException; use Pimcore\Bundle\StudioBackendBundle\Gdpr\Attribute\Request\GdprRequestBody; -use Pimcore\Bundle\StudioBackendBundle\Gdpr\MappedParameter\GdprStructuredSearchRequest; +use Pimcore\Bundle\StudioBackendBundle\Gdpr\MappedParameter\GdprStructuredSearchParameters; use Pimcore\Bundle\StudioBackendBundle\Gdpr\Schema\GdprSearchResultProperty; use Pimcore\Bundle\StudioBackendBundle\Gdpr\Service\GdprManagerServiceInterface; use Pimcore\Bundle\StudioBackendBundle\OpenApi\Attribute\Response\Content\CollectionJson; @@ -77,7 +77,7 @@ public function __construct( HttpResponseCodes::UNPROCESSABLE_CONTENT, ])] public function searchData( - #[MapRequestPayload] GdprStructuredSearchRequest $request + #[MapRequestPayload] GdprStructuredSearchParameters $request ): JsonResponse { $collection = $this->gdprManagerService->search($request); diff --git a/src/Gdpr/MappedParameter/GdprStructuredSearchRequest.php b/src/Gdpr/MappedParameter/GdprStructuredSearchParameter.php similarity index 95% rename from src/Gdpr/MappedParameter/GdprStructuredSearchRequest.php rename to src/Gdpr/MappedParameter/GdprStructuredSearchParameter.php index 0dbde8963..471f7c007 100644 --- a/src/Gdpr/MappedParameter/GdprStructuredSearchRequest.php +++ b/src/Gdpr/MappedParameter/GdprStructuredSearchParameter.php @@ -24,7 +24,7 @@ /** * @internal */ -final readonly class GdprStructuredSearchRequest +final readonly class GdprStructuredSearchParameters { /** * @param string[] $providers diff --git a/src/Gdpr/Provider/DataObjectProvider.php b/src/Gdpr/Provider/DataObjectProvider.php index 7e62d94b9..9da95b757 100644 --- a/src/Gdpr/Provider/DataObjectProvider.php +++ b/src/Gdpr/Provider/DataObjectProvider.php @@ -23,6 +23,7 @@ use Pimcore\Bundle\StudioBackendBundle\Gdpr\Schema\GdprSearchOptions; use Pimcore\Bundle\StudioBackendBundle\Util\Constant\UserPermissions; use Pimcore\Model\DataObject; +use Pimcore\Bundle\StudioBackendBundle\Gdpr\Provider\Legacy\ObjectExporter; use Pimcore\Model\DataObject\Concrete; /** @@ -30,8 +31,6 @@ */ final readonly class DataObjectProvider implements DataProviderInterface { - private const DATE_FORMAT = 'Y-m-d H:i:s'; - public function __construct( private DataObjectQueryProviderInterface $query, private DataObjectSearchServiceInterface $searchService, @@ -45,9 +44,9 @@ public function findData(SearchTerms $terms, GdprSearchOptions $options): array { $query = $this->query->createDataObjectQuery(); - $searchTerm = $this->buildSearchTermForSearch($terms); + $searchTerm = (string)$terms->getId(); - $query->filterFullText($searchTerm); + $query->filterFullText($searchTerm);//is this correct ? $this->applySearchOptions($query, $options); @@ -59,16 +58,10 @@ public function findData(SearchTerms $terms, GdprSearchOptions $options): array return array_map( fn ($item) => new GdprDataRow([ + 'type' => $item->getType(), 'id' => $item->getId(), - 'key' => $item->getKey(), - 'path' => $item->getPath(), - 'className' => ($item instanceof Concrete) ? $item->getClassName() : null, 'fullPath' => $item->getFullPath(), - 'parentId' => $item->getParentId(), - 'type' => $item->getType(), - 'published' => $item->isPublished(), - 'creationDate' => date(self::DATE_FORMAT, $item->getCreationDate()), - 'modificationDate' => date(self::DATE_FORMAT, $item->getModificationDate()), + 'className' => ($item instanceof Concrete) ? $item->getClassName() : null, ], $columns), $items ); @@ -93,25 +86,6 @@ private function applySearchOptions(QueryInterface $query, GdprSearchOptions $op } } - private function buildSearchTermForSearch(SearchTerms $terms): string - { - return trim( - preg_replace( - '/\s+/u', - ' ', - implode( - ' ', - array_filter([ - $terms->id, - $terms->firstname, - $terms->lastname, - $terms->email, - ]) - ) - ) - ); - } - public function getDeleteSwaggerOperationId(): string { return 'pimcore_studio_api_delete_data_object_grid_configuration'; //is this correct ? @@ -132,18 +106,23 @@ public function getSingleItemForDownload(int $id): array throw new NotFoundException('Requested object is not a Concrete data object', $id); } - return [ - 'id' => $object->getId(), - 'key' => $object->getKey(), - 'path' => $object->getPath(), - 'className' => $object->getClassName(), - 'fullPath' => $object->getFullPath(), - 'parentId' => $object->getParentId(), - 'type' => $object->getType(), - 'published' => $object->isPublished(), - 'creationDate' => date(self::DATE_FORMAT, $object->getCreationDate()), - 'modificationDate' => date(self::DATE_FORMAT, $object->getModificationDate()), + $export = [ + 'id' => $object->getId(), + 'fullPath' => $object->getFullPath(), ]; + + $properties = $object->getProperties(); + $finalProperties = []; + + foreach ($properties as $property) { + $finalProperties[] = $property->serialize(); + } + + $export['properties'] = $finalProperties; + + ObjectExporter::doExportObject($object, $export); + + return $export; } public function getName(): string @@ -175,16 +154,10 @@ public function getRequiredPermissions(): array public function getAvailableColumns(): array { return [ + new GdprDataColumn('type', 'Type'), new GdprDataColumn('id', 'ID'), - new GdprDataColumn('key', 'Key'), new GdprDataColumn('fullPath', 'Full Path'), - new GdprDataColumn('path', 'Path'), - new GdprDataColumn('className', 'Class Name'), - new GdprDataColumn('parentId', 'Parent ID'), - new GdprDataColumn('type', 'Type'), - new GdprDataColumn('published', 'Published'), - new GdprDataColumn('creationDate', 'Created At'), - new GdprDataColumn('modificationDate', 'Updated At'), + new GdprDataColumn('className', 'Class Name') ]; } } diff --git a/src/Gdpr/Provider/Legacy/ObjectExporter.php b/src/Gdpr/Provider/Legacy/ObjectExporter.php new file mode 100644 index 000000000..3c735262c --- /dev/null +++ b/src/Gdpr/Provider/Legacy/ObjectExporter.php @@ -0,0 +1,114 @@ +getClass()->getFieldDefinitions(); + + foreach ($fDefs as $fd) { + $getter = 'get' . ucfirst($fd->getName()); + $value = $object->$getter(); + + if ($fd instanceof Data\Fieldcollections && $value instanceof Fieldcollection) { + self::doExportFieldcollection($object, $result, $value, $fd); + } + elseif ($fd instanceof Data\Objectbricks && $value instanceof Objectbrick) { + self::doExportBrick($object, $result, $value, $fd); + } + else { + if ($fd instanceof NormalizerInterface + && $fd instanceof DataObject\ClassDefinition\Data) { + $marshalledValue = $fd->normalize($value); + $result[$fd->getName()] = $marshalledValue; + } + } + } + } + + private static function doExportBrick(Concrete $object, array &$result, Objectbrick $container, Data\Objectbricks $brickFieldDef): void + { + $allowedBrickTypes = $container->getAllowedBrickTypes(); + $resultContainer = []; + foreach ($allowedBrickTypes as $brickType) { + $brickDef = Objectbrick\Definition::getByKey($brickType); + $brickGetter = 'get' . ucfirst($brickType); + $brickValue = $container->$brickGetter(); + + if ($brickValue instanceof Objectbrick\Data\AbstractData) { + $resultContainer[$brickType] = []; + $fDefs = $brickDef->getFieldDefinitions(); + foreach ($fDefs as $fd) { + $getter = 'get' . ucfirst($fd->getName()); + $value = $brickValue->$getter(); + if ($fd instanceof NormalizerInterface + && $fd instanceof DataObject\ClassDefinition\Data) { + $marshalledValue = $fd->normalize($value); + $resultContainer[$brickType][$fd->getName()] = $marshalledValue; + } + } + } + } + $result[$container->getFieldname()] = $resultContainer; + } + + private static function doExportFieldcollection(Concrete $object, array &$result, Fieldcollection $container, Data\Fieldcollections $containerDef): void + { + $resultContainer = []; + + $items = $container->getItems(); + foreach ($items as $item) { + $type = $item->getType(); + + $itemValues = []; + + $itemContainerDefinition = Fieldcollection\Definition::getByKey($type); + $fDefs = $itemContainerDefinition->getFieldDefinitions(); + + foreach ($fDefs as $fd) { + $getter = 'get' . ucfirst($fd->getName()); + $value = $item->$getter(); + + if ($fd instanceof NormalizerInterface + && $fd instanceof DataObject\ClassDefinition\Data) { + $marshalledValue = $fd->normalize($value); + $itemValues[$fd->getName()] = $marshalledValue; + } + } + + $resultContainer[] = [ + 'type' => $type, + 'value' => $itemValues, + ]; + } + $result[$container->getFieldname()] = $resultContainer; + } + + +} diff --git a/src/Gdpr/Service/GdprManagerService.php b/src/Gdpr/Service/GdprManagerService.php index 3cba06081..fb1b9b532 100644 --- a/src/Gdpr/Service/GdprManagerService.php +++ b/src/Gdpr/Service/GdprManagerService.php @@ -18,7 +18,7 @@ use Pimcore\Bundle\StudioBackendBundle\Exception\Api\InvalidArgumentException; use Pimcore\Bundle\StudioBackendBundle\Gdpr\Event\PreResponse\GdprDataProviderEvent; use Pimcore\Bundle\StudioBackendBundle\Gdpr\Event\PreResponse\GdprSearchResultEvent; -use Pimcore\Bundle\StudioBackendBundle\Gdpr\MappedParameter\GdprStructuredSearchRequest; +use Pimcore\Bundle\StudioBackendBundle\Gdpr\MappedParameter\GdprStructuredSearchParameters; use Pimcore\Bundle\StudioBackendBundle\Gdpr\Provider\DataProviderInterface; use Pimcore\Bundle\StudioBackendBundle\Gdpr\Schema\GdprDataProvider; use Pimcore\Bundle\StudioBackendBundle\Gdpr\Schema\GdprSearchResult; @@ -61,7 +61,7 @@ public function getAvailableProviders(): Collection /** * {@inheritdoc} */ - public function search(GdprStructuredSearchRequest $request): GdprSearchResultCollection + public function search(GdprStructuredSearchParameters $request): GdprSearchResultCollection { $allResults = []; diff --git a/src/Gdpr/Service/GdprManagerServiceInterface.php b/src/Gdpr/Service/GdprManagerServiceInterface.php index c8531e6d7..29f6afddd 100644 --- a/src/Gdpr/Service/GdprManagerServiceInterface.php +++ b/src/Gdpr/Service/GdprManagerServiceInterface.php @@ -15,7 +15,7 @@ use Pimcore\Bundle\StudioBackendBundle\Exception\Api\ForbiddenException; use Pimcore\Bundle\StudioBackendBundle\Exception\Api\NotFoundException; -use Pimcore\Bundle\StudioBackendBundle\Gdpr\MappedParameter\GdprStructuredSearchRequest; +use Pimcore\Bundle\StudioBackendBundle\Gdpr\MappedParameter\GdprStructuredSearchParameters; use Pimcore\Bundle\StudioBackendBundle\Gdpr\Schema\GdprDataProvider; use Pimcore\Bundle\StudioBackendBundle\Gdpr\Schema\GdprSearchResultCollection; use Pimcore\Bundle\StudioBackendBundle\Response\Collection; @@ -36,7 +36,7 @@ public function getAvailableProviders(): Collection; * * @throws ForbiddenException */ - public function search(GdprStructuredSearchRequest $request): GdprSearchResultCollection; + public function search(GdprStructuredSearchParameters $request): GdprSearchResultCollection; /** * @throws ForbiddenException From 6476a45ffd20cf0f8bcb448730338a86b4140e2e Mon Sep 17 00:00:00 2001 From: stunnerparas Date: Thu, 27 Nov 2025 10:05:23 +0000 Subject: [PATCH 10/39] Data object provider fix issues and rephase and add interface --- config/gdpr.yaml | 8 ++++-- .../GdprSearchOptionsParameters.php} | 4 +-- ...php => GdprStructuredSearchParameters.php} | 4 +-- src/Gdpr/Provider/DataObjectProvider.php | 11 ++++---- src/Gdpr/Provider/DataProviderInterface.php | 4 +-- src/Gdpr/Provider/Legacy/ObjectExporter.php | 12 ++++---- .../Legacy/ObjectExporterInterface.php | 28 +++++++++++++++++++ src/Gdpr/Provider/PimcoreUserProvider.php | 22 +++++++-------- 8 files changed, 63 insertions(+), 30 deletions(-) rename src/Gdpr/{Schema/GdprSearchOptions.php => MappedParameter/GdprSearchOptionsParameters.php} (89%) rename src/Gdpr/MappedParameter/{GdprStructuredSearchParameter.php => GdprStructuredSearchParameters.php} (88%) create mode 100644 src/Gdpr/Provider/Legacy/ObjectExporterInterface.php diff --git a/config/gdpr.yaml b/config/gdpr.yaml index 0d242a765..3d2733c60 100644 --- a/config/gdpr.yaml +++ b/config/gdpr.yaml @@ -25,6 +25,10 @@ services: tags: ["pimcore.studio_backend.gdpr_data_provider"] arguments: $logsDir: "%kernel.logs_dir%" - + Pimcore\Bundle\StudioBackendBundle\Gdpr\Provider\DataObjectProvider: - tags: ["pimcore.studio_backend.gdpr_data_provider"] \ No newline at end of file + tags: ["pimcore.studio_backend.gdpr_data_provider"] + + # --- Legacy Code from the admin-ui-classic-bundle --- + Pimcore\Bundle\StudioBackendBundle\Gdpr\Provider\Legacy\ObjectExporterInterface: + class: Pimcore\Bundle\StudioBackendBundle\Gdpr\Provider\Legacy\ObjectExporter diff --git a/src/Gdpr/Schema/GdprSearchOptions.php b/src/Gdpr/MappedParameter/GdprSearchOptionsParameters.php similarity index 89% rename from src/Gdpr/Schema/GdprSearchOptions.php rename to src/Gdpr/MappedParameter/GdprSearchOptionsParameters.php index 25711c1dc..726d8eddb 100644 --- a/src/Gdpr/Schema/GdprSearchOptions.php +++ b/src/Gdpr/MappedParameter/GdprSearchOptionsParameters.php @@ -11,7 +11,7 @@ * @license Pimcore Open Core License (POCL) */ -namespace Pimcore\Bundle\StudioBackendBundle\Gdpr\Schema; +namespace Pimcore\Bundle\StudioBackendBundle\Gdpr\MappedParameter; use Symfony\Component\Validator\Constraints\Choice; use Symfony\Component\Validator\Constraints\Collection; @@ -21,7 +21,7 @@ /** * @internal */ -final readonly class GdprSearchOptions +final readonly class GdprSearchOptionsParameters { public function __construct( #[Positive] diff --git a/src/Gdpr/MappedParameter/GdprStructuredSearchParameter.php b/src/Gdpr/MappedParameter/GdprStructuredSearchParameters.php similarity index 88% rename from src/Gdpr/MappedParameter/GdprStructuredSearchParameter.php rename to src/Gdpr/MappedParameter/GdprStructuredSearchParameters.php index 471f7c007..4bba56027 100644 --- a/src/Gdpr/MappedParameter/GdprStructuredSearchParameter.php +++ b/src/Gdpr/MappedParameter/GdprStructuredSearchParameters.php @@ -14,7 +14,7 @@ namespace Pimcore\Bundle\StudioBackendBundle\Gdpr\MappedParameter; use Pimcore\Bundle\StudioBackendBundle\Gdpr\Attribute\Request\SearchTerms; -use Pimcore\Bundle\StudioBackendBundle\Gdpr\Schema\GdprSearchOptions; +use Pimcore\Bundle\StudioBackendBundle\Gdpr\MappedParameter\GdprSearchOptionsParameters; use Symfony\Component\Validator\Constraints\All; use Symfony\Component\Validator\Constraints\NotBlank; use Symfony\Component\Validator\Constraints\NotNull; @@ -39,7 +39,7 @@ public function __construct( public SearchTerms $searchTerms, #[Valid] - public GdprSearchOptions $filters + public GdprSearchOptionsParameters $filters ) { } } diff --git a/src/Gdpr/Provider/DataObjectProvider.php b/src/Gdpr/Provider/DataObjectProvider.php index 9da95b757..e8347eb41 100644 --- a/src/Gdpr/Provider/DataObjectProvider.php +++ b/src/Gdpr/Provider/DataObjectProvider.php @@ -20,11 +20,11 @@ use Pimcore\Bundle\StudioBackendBundle\Gdpr\Attribute\Request\SearchTerms; use Pimcore\Bundle\StudioBackendBundle\Gdpr\Schema\GdprDataColumn; use Pimcore\Bundle\StudioBackendBundle\Gdpr\Schema\GdprDataRow; -use Pimcore\Bundle\StudioBackendBundle\Gdpr\Schema\GdprSearchOptions; +use Pimcore\Bundle\StudioBackendBundle\Gdpr\MappedParameter\GdprSearchOptionsParameters; use Pimcore\Bundle\StudioBackendBundle\Util\Constant\UserPermissions; use Pimcore\Model\DataObject; -use Pimcore\Bundle\StudioBackendBundle\Gdpr\Provider\Legacy\ObjectExporter; use Pimcore\Model\DataObject\Concrete; +use Pimcore\Bundle\StudioBackendBundle\Gdpr\Provider\Legacy\ObjectExporterInterface; /** * @internal @@ -34,13 +34,14 @@ public function __construct( private DataObjectQueryProviderInterface $query, private DataObjectSearchServiceInterface $searchService, + private ObjectExporterInterface $objectExporter ) { } /** * {@inheritdoc} */ - public function findData(SearchTerms $terms, GdprSearchOptions $options): array + public function findData(SearchTerms $terms, GdprSearchOptionsParameters $options): array { $query = $this->query->createDataObjectQuery(); @@ -67,7 +68,7 @@ public function findData(SearchTerms $terms, GdprSearchOptions $options): array ); } - private function applySearchOptions(QueryInterface $query, GdprSearchOptions $options): void + private function applySearchOptions(QueryInterface $query, GdprSearchOptionsParameters $options): void { $query->setPage($options->page); $query->setPageSize($options->pageSize); @@ -120,7 +121,7 @@ public function getSingleItemForDownload(int $id): array $export['properties'] = $finalProperties; - ObjectExporter::doExportObject($object, $export); + $this->objectExporter->doExportObject($object, $export); return $export; } diff --git a/src/Gdpr/Provider/DataProviderInterface.php b/src/Gdpr/Provider/DataProviderInterface.php index c620d69dc..35d80a9fc 100644 --- a/src/Gdpr/Provider/DataProviderInterface.php +++ b/src/Gdpr/Provider/DataProviderInterface.php @@ -18,14 +18,14 @@ use Pimcore\Bundle\StudioBackendBundle\Gdpr\Attribute\Request\SearchTerms; use Pimcore\Bundle\StudioBackendBundle\Gdpr\Schema\GdprDataColumn; use Pimcore\Bundle\StudioBackendBundle\Gdpr\Schema\GdprDataRow; -use Pimcore\Bundle\StudioBackendBundle\Gdpr\Schema\GdprSearchOptions; +use Pimcore\Bundle\StudioBackendBundle\Gdpr\MappedParameter\GdprSearchOptionsParameters; interface DataProviderInterface { /** * @return GdprDataRow[] */ - public function findData(SearchTerms $terms, GdprSearchOptions $options): array; + public function findData(SearchTerms $terms, GdprSearchOptionsParameters $options): array; public function getDeleteSwaggerOperationId(): string; diff --git a/src/Gdpr/Provider/Legacy/ObjectExporter.php b/src/Gdpr/Provider/Legacy/ObjectExporter.php index 3c735262c..09aefb98d 100644 --- a/src/Gdpr/Provider/Legacy/ObjectExporter.php +++ b/src/Gdpr/Provider/Legacy/ObjectExporter.php @@ -26,9 +26,9 @@ * * @internal */ -final readonly class ObjectExporter +final readonly class ObjectExporter implements ObjectExporterInterface { - public static function doExportObject(Concrete $object, array &$result = []): void + public function doExportObject(Concrete $object, array &$result = []): void { $fDefs = $object->getClass()->getFieldDefinitions(); @@ -37,10 +37,10 @@ public static function doExportObject(Concrete $object, array &$result = []): vo $value = $object->$getter(); if ($fd instanceof Data\Fieldcollections && $value instanceof Fieldcollection) { - self::doExportFieldcollection($object, $result, $value, $fd); + self::doExportFieldcollection($result, $value); } elseif ($fd instanceof Data\Objectbricks && $value instanceof Objectbrick) { - self::doExportBrick($object, $result, $value, $fd); + self::doExportBrick($result, $value); } else { if ($fd instanceof NormalizerInterface @@ -52,7 +52,7 @@ public static function doExportObject(Concrete $object, array &$result = []): vo } } - private static function doExportBrick(Concrete $object, array &$result, Objectbrick $container, Data\Objectbricks $brickFieldDef): void + private function doExportBrick(array &$result, Objectbrick $container): void { $allowedBrickTypes = $container->getAllowedBrickTypes(); $resultContainer = []; @@ -78,7 +78,7 @@ private static function doExportBrick(Concrete $object, array &$result, Objectbr $result[$container->getFieldname()] = $resultContainer; } - private static function doExportFieldcollection(Concrete $object, array &$result, Fieldcollection $container, Data\Fieldcollections $containerDef): void + private function doExportFieldcollection(array &$result, Fieldcollection $container): void { $resultContainer = []; diff --git a/src/Gdpr/Provider/Legacy/ObjectExporterInterface.php b/src/Gdpr/Provider/Legacy/ObjectExporterInterface.php new file mode 100644 index 000000000..9a25046fa --- /dev/null +++ b/src/Gdpr/Provider/Legacy/ObjectExporterInterface.php @@ -0,0 +1,28 @@ + $result + */ + public function doExportObject(Concrete $object, array &$result = []): void; +} \ No newline at end of file diff --git a/src/Gdpr/Provider/PimcoreUserProvider.php b/src/Gdpr/Provider/PimcoreUserProvider.php index 2d33cbc80..216e49495 100644 --- a/src/Gdpr/Provider/PimcoreUserProvider.php +++ b/src/Gdpr/Provider/PimcoreUserProvider.php @@ -17,7 +17,7 @@ use Pimcore\Bundle\StudioBackendBundle\Gdpr\Attribute\Request\SearchTerms; use Pimcore\Bundle\StudioBackendBundle\Gdpr\Schema\GdprDataColumn; use Pimcore\Bundle\StudioBackendBundle\Gdpr\Schema\GdprDataRow; -use Pimcore\Bundle\StudioBackendBundle\Gdpr\Schema\GdprSearchOptions; +use Pimcore\Bundle\StudioBackendBundle\Gdpr\MappedParameter\GdprSearchOptionsParameters; use Pimcore\Bundle\StudioBackendBundle\Security\Service\SecurityServiceInterface; use Pimcore\Bundle\StudioBackendBundle\Util\Constant\UserPermissions; use Pimcore\Db; @@ -39,35 +39,35 @@ public function __construct( /** * {@inheritdoc} */ - public function findData(SearchTerms $terms, GdprSearchOptions $options): array + public function findData(SearchTerms $terms, GdprSearchOptionsParameters $options): array { $listing = new Listing(); - if ($terms->id !== null) { + if ($terms->getId() !== null) { $listing->addConditionParam( 'id = :id', - ['id' => $terms->id] + ['id' => $terms->getId()] ); } - if ($terms->firstname !== null) { + if ($terms->getFirstname() !== null) { $listing->addConditionParam( 'firstname LIKE :firstname', - ['firstname' => '%' . $terms->firstname . '%'] + ['firstname' => '%' . $terms->getFirstname() . '%'] ); } - if ($terms->lastname !== null) { + if ($terms->getLastname() !== null) { $listing->addConditionParam( 'lastname LIKE :lastname', - ['lastname' => '%' . $terms->lastname . '%'] + ['lastname' => '%' . $terms->getLastname() . '%'] ); } - if ($terms->email !== null) { + if ($terms->getEmail() !== null) { $listing->addConditionParam( 'email LIKE :email', - ['email' => '%' . $terms->email . '%'] + ['email' => '%' . $terms->getEmail() . '%'] ); } @@ -93,7 +93,7 @@ public function findData(SearchTerms $terms, GdprSearchOptions $options): array ); } - private function applySearchOptions(Listing $listing, GdprSearchOptions $options): void + private function applySearchOptions(Listing $listing, GdprSearchOptionsParameters $options): void { $listing->setOffset(($options->page - 1) * $options->pageSize); $listing->setLimit($options->pageSize); From cdff53f5baed24f1d51288f9e0880454f905eb07 Mon Sep 17 00:00:00 2001 From: stunnerparas <49896041+stunnerparas@users.noreply.github.com> Date: Thu, 27 Nov 2025 10:15:52 +0000 Subject: [PATCH 11/39] Apply php-cs-fixer changes --- .../GdprStructuredSearchParameters.php | 1 - src/Gdpr/Provider/DataObjectProvider.php | 8 ++++---- src/Gdpr/Provider/DataProviderInterface.php | 2 +- src/Gdpr/Provider/Legacy/ObjectExporter.php | 12 ++++-------- src/Gdpr/Provider/Legacy/ObjectExporterInterface.php | 6 +++--- src/Gdpr/Provider/PimcoreUserProvider.php | 2 +- 6 files changed, 13 insertions(+), 18 deletions(-) diff --git a/src/Gdpr/MappedParameter/GdprStructuredSearchParameters.php b/src/Gdpr/MappedParameter/GdprStructuredSearchParameters.php index 4bba56027..fa305ebc1 100644 --- a/src/Gdpr/MappedParameter/GdprStructuredSearchParameters.php +++ b/src/Gdpr/MappedParameter/GdprStructuredSearchParameters.php @@ -14,7 +14,6 @@ namespace Pimcore\Bundle\StudioBackendBundle\Gdpr\MappedParameter; use Pimcore\Bundle\StudioBackendBundle\Gdpr\Attribute\Request\SearchTerms; -use Pimcore\Bundle\StudioBackendBundle\Gdpr\MappedParameter\GdprSearchOptionsParameters; use Symfony\Component\Validator\Constraints\All; use Symfony\Component\Validator\Constraints\NotBlank; use Symfony\Component\Validator\Constraints\NotNull; diff --git a/src/Gdpr/Provider/DataObjectProvider.php b/src/Gdpr/Provider/DataObjectProvider.php index e8347eb41..3372b2458 100644 --- a/src/Gdpr/Provider/DataObjectProvider.php +++ b/src/Gdpr/Provider/DataObjectProvider.php @@ -18,13 +18,13 @@ use Pimcore\Bundle\StudioBackendBundle\DataIndex\Service\DataObjectSearchServiceInterface; use Pimcore\Bundle\StudioBackendBundle\Exception\Api\NotFoundException; use Pimcore\Bundle\StudioBackendBundle\Gdpr\Attribute\Request\SearchTerms; +use Pimcore\Bundle\StudioBackendBundle\Gdpr\MappedParameter\GdprSearchOptionsParameters; +use Pimcore\Bundle\StudioBackendBundle\Gdpr\Provider\Legacy\ObjectExporterInterface; use Pimcore\Bundle\StudioBackendBundle\Gdpr\Schema\GdprDataColumn; use Pimcore\Bundle\StudioBackendBundle\Gdpr\Schema\GdprDataRow; -use Pimcore\Bundle\StudioBackendBundle\Gdpr\MappedParameter\GdprSearchOptionsParameters; use Pimcore\Bundle\StudioBackendBundle\Util\Constant\UserPermissions; use Pimcore\Model\DataObject; use Pimcore\Model\DataObject\Concrete; -use Pimcore\Bundle\StudioBackendBundle\Gdpr\Provider\Legacy\ObjectExporterInterface; /** * @internal @@ -47,7 +47,7 @@ public function findData(SearchTerms $terms, GdprSearchOptionsParameters $option $searchTerm = (string)$terms->getId(); - $query->filterFullText($searchTerm);//is this correct ? + $query->filterFullText($searchTerm); //is this correct ? $this->applySearchOptions($query, $options); @@ -158,7 +158,7 @@ public function getAvailableColumns(): array new GdprDataColumn('type', 'Type'), new GdprDataColumn('id', 'ID'), new GdprDataColumn('fullPath', 'Full Path'), - new GdprDataColumn('className', 'Class Name') + new GdprDataColumn('className', 'Class Name'), ]; } } diff --git a/src/Gdpr/Provider/DataProviderInterface.php b/src/Gdpr/Provider/DataProviderInterface.php index 35d80a9fc..b788fbe78 100644 --- a/src/Gdpr/Provider/DataProviderInterface.php +++ b/src/Gdpr/Provider/DataProviderInterface.php @@ -16,9 +16,9 @@ use Pimcore\Bundle\StudioBackendBundle\Exception\Api\ForbiddenException; use Pimcore\Bundle\StudioBackendBundle\Exception\Api\NotFoundException; use Pimcore\Bundle\StudioBackendBundle\Gdpr\Attribute\Request\SearchTerms; +use Pimcore\Bundle\StudioBackendBundle\Gdpr\MappedParameter\GdprSearchOptionsParameters; use Pimcore\Bundle\StudioBackendBundle\Gdpr\Schema\GdprDataColumn; use Pimcore\Bundle\StudioBackendBundle\Gdpr\Schema\GdprDataRow; -use Pimcore\Bundle\StudioBackendBundle\Gdpr\MappedParameter\GdprSearchOptionsParameters; interface DataProviderInterface { diff --git a/src/Gdpr/Provider/Legacy/ObjectExporter.php b/src/Gdpr/Provider/Legacy/ObjectExporter.php index 09aefb98d..1e01e4080 100644 --- a/src/Gdpr/Provider/Legacy/ObjectExporter.php +++ b/src/Gdpr/Provider/Legacy/ObjectExporter.php @@ -13,11 +13,11 @@ namespace Pimcore\Bundle\StudioBackendBundle\Gdpr\Provider\Legacy; use Pimcore\Model\DataObject; -use Pimcore\Normalizer\NormalizerInterface; +use Pimcore\Model\DataObject\ClassDefinition\Data; use Pimcore\Model\DataObject\Concrete; use Pimcore\Model\DataObject\Fieldcollection; use Pimcore\Model\DataObject\Objectbrick; -use Pimcore\Model\DataObject\ClassDefinition\Data; +use Pimcore\Normalizer\NormalizerInterface; /** * Copied from old admin-ui-classic-bundle @@ -38,11 +38,9 @@ public function doExportObject(Concrete $object, array &$result = []): void if ($fd instanceof Data\Fieldcollections && $value instanceof Fieldcollection) { self::doExportFieldcollection($result, $value); - } - elseif ($fd instanceof Data\Objectbricks && $value instanceof Objectbrick) { + } elseif ($fd instanceof Data\Objectbricks && $value instanceof Objectbrick) { self::doExportBrick($result, $value); - } - else { + } else { if ($fd instanceof NormalizerInterface && $fd instanceof DataObject\ClassDefinition\Data) { $marshalledValue = $fd->normalize($value); @@ -109,6 +107,4 @@ private function doExportFieldcollection(array &$result, Fieldcollection $contai } $result[$container->getFieldname()] = $resultContainer; } - - } diff --git a/src/Gdpr/Provider/Legacy/ObjectExporterInterface.php b/src/Gdpr/Provider/Legacy/ObjectExporterInterface.php index 9a25046fa..3f4f11ba9 100644 --- a/src/Gdpr/Provider/Legacy/ObjectExporterInterface.php +++ b/src/Gdpr/Provider/Legacy/ObjectExporterInterface.php @@ -7,8 +7,8 @@ * Full copyright and license information is available in * LICENSE.md which is distributed with this source code. * - * @copyright Copyright (c) Pimcore GmbH (https://www.pimcore.com) - * @license Pimcore Open Core License (POCL) + * @copyright Copyright (c) Pimcore GmbH (https://www.pimcore.com) + * @license Pimcore Open Core License (POCL) */ namespace Pimcore\Bundle\StudioBackendBundle\Gdpr\Provider\Legacy; @@ -25,4 +25,4 @@ interface ObjectExporterInterface * @param array $result */ public function doExportObject(Concrete $object, array &$result = []): void; -} \ No newline at end of file +} diff --git a/src/Gdpr/Provider/PimcoreUserProvider.php b/src/Gdpr/Provider/PimcoreUserProvider.php index 216e49495..516fe1480 100644 --- a/src/Gdpr/Provider/PimcoreUserProvider.php +++ b/src/Gdpr/Provider/PimcoreUserProvider.php @@ -15,9 +15,9 @@ use Pimcore\Bundle\GenericDataIndexBundle\Enum\Search\SortDirection; use Pimcore\Bundle\StudioBackendBundle\Exception\Api\NotFoundException; use Pimcore\Bundle\StudioBackendBundle\Gdpr\Attribute\Request\SearchTerms; +use Pimcore\Bundle\StudioBackendBundle\Gdpr\MappedParameter\GdprSearchOptionsParameters; use Pimcore\Bundle\StudioBackendBundle\Gdpr\Schema\GdprDataColumn; use Pimcore\Bundle\StudioBackendBundle\Gdpr\Schema\GdprDataRow; -use Pimcore\Bundle\StudioBackendBundle\Gdpr\MappedParameter\GdprSearchOptionsParameters; use Pimcore\Bundle\StudioBackendBundle\Security\Service\SecurityServiceInterface; use Pimcore\Bundle\StudioBackendBundle\Util\Constant\UserPermissions; use Pimcore\Db; From dd914174eccc8f5544889f082e406a6971bf6e27 Mon Sep 17 00:00:00 2001 From: stunnerparas Date: Thu, 27 Nov 2025 10:29:33 +0000 Subject: [PATCH 12/39] ci fix --- src/Gdpr/Provider/Legacy/ObjectExporter.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Gdpr/Provider/Legacy/ObjectExporter.php b/src/Gdpr/Provider/Legacy/ObjectExporter.php index 1e01e4080..20b12cb77 100644 --- a/src/Gdpr/Provider/Legacy/ObjectExporter.php +++ b/src/Gdpr/Provider/Legacy/ObjectExporter.php @@ -21,9 +21,8 @@ /** * Copied from old admin-ui-classic-bundle - * https://github.com/pimcore/admin-ui-classic-bundle/blob/9258d42920dbb475badc1adea59a7552ab089ac4/src/GDPR/DataProvider/Exporter.php#L32 - * Use with caution, this is a copy from the admin-ui-classic-bundle - * + * https://github.com/pimcore/admin-ui-classic-bundle/blob/9258d42920dbb475badc1adea59a7552ab089ac4/src/GDPR/ + * DataProvider/Exporter.php#L32 * @internal */ final readonly class ObjectExporter implements ObjectExporterInterface From 812764e6930d8f1f5b717ab0dd6fb32f1ce78898 Mon Sep 17 00:00:00 2001 From: stunnerparas <49896041+stunnerparas@users.noreply.github.com> Date: Thu, 27 Nov 2025 10:30:23 +0000 Subject: [PATCH 13/39] Apply php-cs-fixer changes --- src/Gdpr/Provider/Legacy/ObjectExporter.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Gdpr/Provider/Legacy/ObjectExporter.php b/src/Gdpr/Provider/Legacy/ObjectExporter.php index 20b12cb77..dd2fda422 100644 --- a/src/Gdpr/Provider/Legacy/ObjectExporter.php +++ b/src/Gdpr/Provider/Legacy/ObjectExporter.php @@ -23,6 +23,7 @@ * Copied from old admin-ui-classic-bundle * https://github.com/pimcore/admin-ui-classic-bundle/blob/9258d42920dbb475badc1adea59a7552ab089ac4/src/GDPR/ * DataProvider/Exporter.php#L32 + * * @internal */ final readonly class ObjectExporter implements ObjectExporterInterface From b642e54fdef14e8560f8a31249263fe34fa2ab78 Mon Sep 17 00:00:00 2001 From: stunnerparas Date: Thu, 27 Nov 2025 12:55:52 +0000 Subject: [PATCH 14/39] Fix the review issue and some changes --- src/Gdpr/Attribute/Request/SearchTerms.php | 8 ++-- .../GdprSearchOptionsParameters.php | 43 ------------------- .../GdprStructuredSearchParameters.php | 3 +- src/Gdpr/Provider/DataObjectProvider.php | 32 +++++++------- src/Gdpr/Provider/DataProviderInterface.php | 4 +- src/Gdpr/Provider/Legacy/ObjectExporter.php | 6 ++- .../Legacy/ObjectExporterInterface.php | 1 - src/Gdpr/Provider/PimcoreUserProvider.php | 18 ++++---- 8 files changed, 36 insertions(+), 79 deletions(-) delete mode 100644 src/Gdpr/MappedParameter/GdprSearchOptionsParameters.php diff --git a/src/Gdpr/Attribute/Request/SearchTerms.php b/src/Gdpr/Attribute/Request/SearchTerms.php index 7e2b56535..4c5014af2 100644 --- a/src/Gdpr/Attribute/Request/SearchTerms.php +++ b/src/Gdpr/Attribute/Request/SearchTerms.php @@ -29,19 +29,19 @@ final readonly class SearchTerms { public function __construct( - #[Property(description: 'The ID to search for.', type: 'int', nullable: true)] + #[Property(description: 'The ID to search for.', type: 'int', nullable: true, example: 3)] #[Type('int')] private ?int $id = null, - #[Property(description: 'The first name to search for. ', type: 'string', nullable: true)] + #[Property(description: 'The first name to search for. ', type: 'string', nullable: true, example: 'John')] #[Type('string')] private ?string $firstname = null, - #[Property(description: 'The last name to search for.', type: 'string', nullable: true)] + #[Property(description: 'The last name to search for.', type: 'string', nullable: true, example: 'Doe')] #[Type('string')] private ?string $lastname = null, - #[Property(description: 'The email address to search for.', type: 'string', nullable: true)] + #[Property(description: 'The email address to search for.', type: 'string', nullable: true, example: 'john.doe@example.com')] #[Type('string')] private ?string $email = null, ) { diff --git a/src/Gdpr/MappedParameter/GdprSearchOptionsParameters.php b/src/Gdpr/MappedParameter/GdprSearchOptionsParameters.php deleted file mode 100644 index 726d8eddb..000000000 --- a/src/Gdpr/MappedParameter/GdprSearchOptionsParameters.php +++ /dev/null @@ -1,43 +0,0 @@ - new Type('string'), - 'direction' => new Choice(['ASC', 'DESC', 'asc', 'desc']), - ], - allowMissingFields: true - )] - public ?array $sortFilter = null - ) { - } -} diff --git a/src/Gdpr/MappedParameter/GdprStructuredSearchParameters.php b/src/Gdpr/MappedParameter/GdprStructuredSearchParameters.php index fa305ebc1..7c907bc20 100644 --- a/src/Gdpr/MappedParameter/GdprStructuredSearchParameters.php +++ b/src/Gdpr/MappedParameter/GdprStructuredSearchParameters.php @@ -13,6 +13,7 @@ namespace Pimcore\Bundle\StudioBackendBundle\Gdpr\MappedParameter; +use Pimcore\Bundle\StudioBackendBundle\Filter\MappedParameter\FilterParameter; use Pimcore\Bundle\StudioBackendBundle\Gdpr\Attribute\Request\SearchTerms; use Symfony\Component\Validator\Constraints\All; use Symfony\Component\Validator\Constraints\NotBlank; @@ -38,7 +39,7 @@ public function __construct( public SearchTerms $searchTerms, #[Valid] - public GdprSearchOptionsParameters $filters + public FilterParameter $filters ) { } } diff --git a/src/Gdpr/Provider/DataObjectProvider.php b/src/Gdpr/Provider/DataObjectProvider.php index 3372b2458..d56481787 100644 --- a/src/Gdpr/Provider/DataObjectProvider.php +++ b/src/Gdpr/Provider/DataObjectProvider.php @@ -18,7 +18,7 @@ use Pimcore\Bundle\StudioBackendBundle\DataIndex\Service\DataObjectSearchServiceInterface; use Pimcore\Bundle\StudioBackendBundle\Exception\Api\NotFoundException; use Pimcore\Bundle\StudioBackendBundle\Gdpr\Attribute\Request\SearchTerms; -use Pimcore\Bundle\StudioBackendBundle\Gdpr\MappedParameter\GdprSearchOptionsParameters; +use Pimcore\Bundle\StudioBackendBundle\Filter\MappedParameter\FilterParameter; use Pimcore\Bundle\StudioBackendBundle\Gdpr\Provider\Legacy\ObjectExporterInterface; use Pimcore\Bundle\StudioBackendBundle\Gdpr\Schema\GdprDataColumn; use Pimcore\Bundle\StudioBackendBundle\Gdpr\Schema\GdprDataRow; @@ -41,7 +41,7 @@ public function __construct( /** * {@inheritdoc} */ - public function findData(SearchTerms $terms, GdprSearchOptionsParameters $options): array + public function findData(SearchTerms $terms, FilterParameter $options): array { $query = $this->query->createDataObjectQuery(); @@ -68,23 +68,21 @@ public function findData(SearchTerms $terms, GdprSearchOptionsParameters $option ); } - private function applySearchOptions(QueryInterface $query, GdprSearchOptionsParameters $options): void + private function applySearchOptions(QueryInterface $query, FilterParameter $options): void { - $query->setPage($options->page); - $query->setPageSize($options->pageSize); - - $filter = $options->sortFilter; - - if ($filter !== null && isset($filter['key'], $filter['direction'])) { - - $directionEnum = SortDirection::ASC; - - if (strtolower($filter['direction']) === SortDirection::DESC->value) { - $directionEnum = SortDirection::DESC; - } - - $query->orderByField($filter['key'], $directionEnum); + $query->setPage($options->getPage()); + $query->setPageSize($options->getPageSize()); + + $sortFilter = $options->getSortFilter(); + + if ($sortFilter->getKey() && $sortFilter->getDirection()) { + $directionEnum = strtolower($sortFilter->getDirection()) === SortDirection::DESC->value + ? SortDirection::DESC + : SortDirection::ASC; + + $query->orderByField($sortFilter->getKey(), $directionEnum); } + } public function getDeleteSwaggerOperationId(): string diff --git a/src/Gdpr/Provider/DataProviderInterface.php b/src/Gdpr/Provider/DataProviderInterface.php index b788fbe78..42d561cfd 100644 --- a/src/Gdpr/Provider/DataProviderInterface.php +++ b/src/Gdpr/Provider/DataProviderInterface.php @@ -16,7 +16,7 @@ use Pimcore\Bundle\StudioBackendBundle\Exception\Api\ForbiddenException; use Pimcore\Bundle\StudioBackendBundle\Exception\Api\NotFoundException; use Pimcore\Bundle\StudioBackendBundle\Gdpr\Attribute\Request\SearchTerms; -use Pimcore\Bundle\StudioBackendBundle\Gdpr\MappedParameter\GdprSearchOptionsParameters; +use Pimcore\Bundle\StudioBackendBundle\Filter\MappedParameter\FilterParameter; use Pimcore\Bundle\StudioBackendBundle\Gdpr\Schema\GdprDataColumn; use Pimcore\Bundle\StudioBackendBundle\Gdpr\Schema\GdprDataRow; @@ -25,7 +25,7 @@ interface DataProviderInterface /** * @return GdprDataRow[] */ - public function findData(SearchTerms $terms, GdprSearchOptionsParameters $options): array; + public function findData(SearchTerms $terms, FilterParameter $options): array; public function getDeleteSwaggerOperationId(): string; diff --git a/src/Gdpr/Provider/Legacy/ObjectExporter.php b/src/Gdpr/Provider/Legacy/ObjectExporter.php index dd2fda422..1184acf05 100644 --- a/src/Gdpr/Provider/Legacy/ObjectExporter.php +++ b/src/Gdpr/Provider/Legacy/ObjectExporter.php @@ -22,12 +22,14 @@ /** * Copied from old admin-ui-classic-bundle * https://github.com/pimcore/admin-ui-classic-bundle/blob/9258d42920dbb475badc1adea59a7552ab089ac4/src/GDPR/ - * DataProvider/Exporter.php#L32 - * + * DataProvider/Exporter.php * @internal */ final readonly class ObjectExporter implements ObjectExporterInterface { + /** + * {@inheritdoc} + */ public function doExportObject(Concrete $object, array &$result = []): void { $fDefs = $object->getClass()->getFieldDefinitions(); diff --git a/src/Gdpr/Provider/Legacy/ObjectExporterInterface.php b/src/Gdpr/Provider/Legacy/ObjectExporterInterface.php index 3f4f11ba9..0b2835476 100644 --- a/src/Gdpr/Provider/Legacy/ObjectExporterInterface.php +++ b/src/Gdpr/Provider/Legacy/ObjectExporterInterface.php @@ -21,7 +21,6 @@ interface ObjectExporterInterface { /** - * @param Concrete $object * @param array $result */ public function doExportObject(Concrete $object, array &$result = []): void; diff --git a/src/Gdpr/Provider/PimcoreUserProvider.php b/src/Gdpr/Provider/PimcoreUserProvider.php index 516fe1480..36914cefb 100644 --- a/src/Gdpr/Provider/PimcoreUserProvider.php +++ b/src/Gdpr/Provider/PimcoreUserProvider.php @@ -15,11 +15,11 @@ use Pimcore\Bundle\GenericDataIndexBundle\Enum\Search\SortDirection; use Pimcore\Bundle\StudioBackendBundle\Exception\Api\NotFoundException; use Pimcore\Bundle\StudioBackendBundle\Gdpr\Attribute\Request\SearchTerms; -use Pimcore\Bundle\StudioBackendBundle\Gdpr\MappedParameter\GdprSearchOptionsParameters; use Pimcore\Bundle\StudioBackendBundle\Gdpr\Schema\GdprDataColumn; use Pimcore\Bundle\StudioBackendBundle\Gdpr\Schema\GdprDataRow; use Pimcore\Bundle\StudioBackendBundle\Security\Service\SecurityServiceInterface; use Pimcore\Bundle\StudioBackendBundle\Util\Constant\UserPermissions; +use Pimcore\Bundle\StudioBackendBundle\Filter\MappedParameter\FilterParameter; use Pimcore\Db; use Pimcore\Model\User; use Pimcore\Model\User\Listing; @@ -39,7 +39,7 @@ public function __construct( /** * {@inheritdoc} */ - public function findData(SearchTerms $terms, GdprSearchOptionsParameters $options): array + public function findData(SearchTerms $terms, FilterParameter $options): array { $listing = new Listing(); @@ -93,17 +93,17 @@ public function findData(SearchTerms $terms, GdprSearchOptionsParameters $option ); } - private function applySearchOptions(Listing $listing, GdprSearchOptionsParameters $options): void + private function applySearchOptions(Listing $listing, FilterParameter $options): void { - $listing->setOffset(($options->page - 1) * $options->pageSize); - $listing->setLimit($options->pageSize); + $listing->setOffset($options->getStart()); + $listing->setLimit($options->getPageSize()); - $filter = $options->sortFilter; + $sortFilter = $options->getSortFilter(); - if ($filter && isset($filter['key'], $filter['direction'])) { - $listing->setOrderKey($filter['key']); + if ($sortFilter->getKey() && $sortFilter->getDirection()) { + $listing->setOrderKey($sortFilter->getKey()); $listing->setOrder( - strtolower($filter['direction']) === SortDirection::DESC->value + strtolower($sortFilter->getDirection()) === SortDirection::DESC->value ? SortDirection::DESC->value : SortDirection::ASC->value ); From 8c469a8b3784e3132c4151ace111cd3f4a09d8af Mon Sep 17 00:00:00 2001 From: stunnerparas <49896041+stunnerparas@users.noreply.github.com> Date: Thu, 27 Nov 2025 13:11:46 +0000 Subject: [PATCH 15/39] Apply php-cs-fixer changes --- src/Gdpr/Provider/DataObjectProvider.php | 6 +++--- src/Gdpr/Provider/DataProviderInterface.php | 2 +- src/Gdpr/Provider/Legacy/ObjectExporter.php | 1 + src/Gdpr/Provider/PimcoreUserProvider.php | 2 +- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/Gdpr/Provider/DataObjectProvider.php b/src/Gdpr/Provider/DataObjectProvider.php index d56481787..fa1925c53 100644 --- a/src/Gdpr/Provider/DataObjectProvider.php +++ b/src/Gdpr/Provider/DataObjectProvider.php @@ -17,8 +17,8 @@ use Pimcore\Bundle\StudioBackendBundle\DataIndex\Query\QueryInterface; use Pimcore\Bundle\StudioBackendBundle\DataIndex\Service\DataObjectSearchServiceInterface; use Pimcore\Bundle\StudioBackendBundle\Exception\Api\NotFoundException; -use Pimcore\Bundle\StudioBackendBundle\Gdpr\Attribute\Request\SearchTerms; use Pimcore\Bundle\StudioBackendBundle\Filter\MappedParameter\FilterParameter; +use Pimcore\Bundle\StudioBackendBundle\Gdpr\Attribute\Request\SearchTerms; use Pimcore\Bundle\StudioBackendBundle\Gdpr\Provider\Legacy\ObjectExporterInterface; use Pimcore\Bundle\StudioBackendBundle\Gdpr\Schema\GdprDataColumn; use Pimcore\Bundle\StudioBackendBundle\Gdpr\Schema\GdprDataRow; @@ -72,9 +72,9 @@ private function applySearchOptions(QueryInterface $query, FilterParameter $opti { $query->setPage($options->getPage()); $query->setPageSize($options->getPageSize()); - + $sortFilter = $options->getSortFilter(); - + if ($sortFilter->getKey() && $sortFilter->getDirection()) { $directionEnum = strtolower($sortFilter->getDirection()) === SortDirection::DESC->value ? SortDirection::DESC diff --git a/src/Gdpr/Provider/DataProviderInterface.php b/src/Gdpr/Provider/DataProviderInterface.php index 42d561cfd..9feffc883 100644 --- a/src/Gdpr/Provider/DataProviderInterface.php +++ b/src/Gdpr/Provider/DataProviderInterface.php @@ -15,8 +15,8 @@ use Pimcore\Bundle\StudioBackendBundle\Exception\Api\ForbiddenException; use Pimcore\Bundle\StudioBackendBundle\Exception\Api\NotFoundException; -use Pimcore\Bundle\StudioBackendBundle\Gdpr\Attribute\Request\SearchTerms; use Pimcore\Bundle\StudioBackendBundle\Filter\MappedParameter\FilterParameter; +use Pimcore\Bundle\StudioBackendBundle\Gdpr\Attribute\Request\SearchTerms; use Pimcore\Bundle\StudioBackendBundle\Gdpr\Schema\GdprDataColumn; use Pimcore\Bundle\StudioBackendBundle\Gdpr\Schema\GdprDataRow; diff --git a/src/Gdpr/Provider/Legacy/ObjectExporter.php b/src/Gdpr/Provider/Legacy/ObjectExporter.php index 1184acf05..e33066e41 100644 --- a/src/Gdpr/Provider/Legacy/ObjectExporter.php +++ b/src/Gdpr/Provider/Legacy/ObjectExporter.php @@ -23,6 +23,7 @@ * Copied from old admin-ui-classic-bundle * https://github.com/pimcore/admin-ui-classic-bundle/blob/9258d42920dbb475badc1adea59a7552ab089ac4/src/GDPR/ * DataProvider/Exporter.php + * * @internal */ final readonly class ObjectExporter implements ObjectExporterInterface diff --git a/src/Gdpr/Provider/PimcoreUserProvider.php b/src/Gdpr/Provider/PimcoreUserProvider.php index 36914cefb..fa50032ed 100644 --- a/src/Gdpr/Provider/PimcoreUserProvider.php +++ b/src/Gdpr/Provider/PimcoreUserProvider.php @@ -14,12 +14,12 @@ use Pimcore\Bundle\GenericDataIndexBundle\Enum\Search\SortDirection; use Pimcore\Bundle\StudioBackendBundle\Exception\Api\NotFoundException; +use Pimcore\Bundle\StudioBackendBundle\Filter\MappedParameter\FilterParameter; use Pimcore\Bundle\StudioBackendBundle\Gdpr\Attribute\Request\SearchTerms; use Pimcore\Bundle\StudioBackendBundle\Gdpr\Schema\GdprDataColumn; use Pimcore\Bundle\StudioBackendBundle\Gdpr\Schema\GdprDataRow; use Pimcore\Bundle\StudioBackendBundle\Security\Service\SecurityServiceInterface; use Pimcore\Bundle\StudioBackendBundle\Util\Constant\UserPermissions; -use Pimcore\Bundle\StudioBackendBundle\Filter\MappedParameter\FilterParameter; use Pimcore\Db; use Pimcore\Model\User; use Pimcore\Model\User\Listing; From ef73aaee12518877375cfa6e4f4f68f431a876e9 Mon Sep 17 00:00:00 2001 From: stunnerparas Date: Thu, 27 Nov 2025 13:16:32 +0000 Subject: [PATCH 16/39] ci issue fix --- src/Gdpr/Attribute/Request/SearchTerms.php | 32 ++++++++++++++++++---- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/src/Gdpr/Attribute/Request/SearchTerms.php b/src/Gdpr/Attribute/Request/SearchTerms.php index 4c5014af2..2e45ef37f 100644 --- a/src/Gdpr/Attribute/Request/SearchTerms.php +++ b/src/Gdpr/Attribute/Request/SearchTerms.php @@ -29,22 +29,44 @@ final readonly class SearchTerms { public function __construct( - #[Property(description: 'The ID to search for.', type: 'int', nullable: true, example: 3)] + #[Property( + description: 'The ID to search for.', + type: 'int', + nullable: true, + example: 3 + )] #[Type('int')] private ?int $id = null, - #[Property(description: 'The first name to search for. ', type: 'string', nullable: true, example: 'John')] + #[Property( + description: 'The first name to search for.', + type: 'string', + nullable: true, + example: 'John' + )] #[Type('string')] private ?string $firstname = null, - #[Property(description: 'The last name to search for.', type: 'string', nullable: true, example: 'Doe')] + #[Property( + description: 'The last name to search for.', + type: 'string', + nullable: true, + example: 'Doe' + )] #[Type('string')] private ?string $lastname = null, - #[Property(description: 'The email address to search for.', type: 'string', nullable: true, example: 'john.doe@example.com')] + #[Property( + description: 'The email address to search for.', + type: 'string', + nullable: true, + example: 'john.doe@example.com' + )] #[Type('string')] private ?string $email = null, - ) { + ) + + { if ($this->id === null && $this->firstname === null && $this->lastname === null && From d82d6da923a48b51601dbdc9d106b554e1f9d886 Mon Sep 17 00:00:00 2001 From: stunnerparas <49896041+stunnerparas@users.noreply.github.com> Date: Thu, 27 Nov 2025 13:17:17 +0000 Subject: [PATCH 17/39] Apply php-cs-fixer changes --- src/Gdpr/Attribute/Request/SearchTerms.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/Gdpr/Attribute/Request/SearchTerms.php b/src/Gdpr/Attribute/Request/SearchTerms.php index 2e45ef37f..eca9489a0 100644 --- a/src/Gdpr/Attribute/Request/SearchTerms.php +++ b/src/Gdpr/Attribute/Request/SearchTerms.php @@ -64,9 +64,7 @@ public function __construct( )] #[Type('string')] private ?string $email = null, - ) - - { + ) { if ($this->id === null && $this->firstname === null && $this->lastname === null && From 3a348bcd0e5f42433f29b7820ae4e7b3d67f5c7a Mon Sep 17 00:00:00 2001 From: stunnerparas Date: Thu, 27 Nov 2025 16:24:33 +0000 Subject: [PATCH 18/39] filter in data object --- src/Gdpr/Provider/DataObjectProvider.php | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/Gdpr/Provider/DataObjectProvider.php b/src/Gdpr/Provider/DataObjectProvider.php index fa1925c53..19fc8b890 100644 --- a/src/Gdpr/Provider/DataObjectProvider.php +++ b/src/Gdpr/Provider/DataObjectProvider.php @@ -44,10 +44,24 @@ public function __construct( public function findData(SearchTerms $terms, FilterParameter $options): array { $query = $this->query->createDataObjectQuery(); + + $query->excludeFolders(); + + if ($terms->getId() !== null) { + $query->filterInteger('id', $terms->getId()); + } - $searchTerm = (string)$terms->getId(); + if ($terms->getFirstname() !== null) { + $query->filterFullText($terms->getFirstname()); + } - $query->filterFullText($searchTerm); //is this correct ? + if ($terms->getLastname() !== null) { + $query->filterFullText($terms->getLastname()); + } + + if ($terms->getEmail() !== null) { + $query->filterFullText($terms->getEmail()); + } $this->applySearchOptions($query, $options); From 9f05de224d69e7fb4bfcde704efacb14b7726f74 Mon Sep 17 00:00:00 2001 From: stunnerparas <49896041+stunnerparas@users.noreply.github.com> Date: Thu, 27 Nov 2025 16:25:44 +0000 Subject: [PATCH 19/39] Apply php-cs-fixer changes --- src/Gdpr/Provider/DataObjectProvider.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Gdpr/Provider/DataObjectProvider.php b/src/Gdpr/Provider/DataObjectProvider.php index 19fc8b890..490863448 100644 --- a/src/Gdpr/Provider/DataObjectProvider.php +++ b/src/Gdpr/Provider/DataObjectProvider.php @@ -44,9 +44,9 @@ public function __construct( public function findData(SearchTerms $terms, FilterParameter $options): array { $query = $this->query->createDataObjectQuery(); - + $query->excludeFolders(); - + if ($terms->getId() !== null) { $query->filterInteger('id', $terms->getId()); } From 361b9236f2f79adf835b2cf91ccc5084bcbe7696 Mon Sep 17 00:00:00 2001 From: stunnerparas Date: Thu, 27 Nov 2025 16:30:30 +0000 Subject: [PATCH 20/39] rephase --- src/Gdpr/Provider/DataObjectProvider.php | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/src/Gdpr/Provider/DataObjectProvider.php b/src/Gdpr/Provider/DataObjectProvider.php index 490863448..534ed7acc 100644 --- a/src/Gdpr/Provider/DataObjectProvider.php +++ b/src/Gdpr/Provider/DataObjectProvider.php @@ -51,17 +51,18 @@ public function findData(SearchTerms $terms, FilterParameter $options): array $query->filterInteger('id', $terms->getId()); } - if ($terms->getFirstname() !== null) { - $query->filterFullText($terms->getFirstname()); - } - - if ($terms->getLastname() !== null) { - $query->filterFullText($terms->getLastname()); - } - - if ($terms->getEmail() !== null) { - $query->filterFullText($terms->getEmail()); - } + $texts = [ + $terms->getFirstname(), + $terms->getLastname(), + $terms->getEmail(), + ]; + + foreach ($texts as $value) { + $value = trim((string)$value); + if ($value !== '') { + $query->filterFullText($value); + } + } $this->applySearchOptions($query, $options); From 503a7f35be2f1a9b983edf130ba5872fe1869991 Mon Sep 17 00:00:00 2001 From: stunnerparas <49896041+stunnerparas@users.noreply.github.com> Date: Thu, 27 Nov 2025 16:32:23 +0000 Subject: [PATCH 21/39] Apply php-cs-fixer changes --- src/Gdpr/Provider/DataObjectProvider.php | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/Gdpr/Provider/DataObjectProvider.php b/src/Gdpr/Provider/DataObjectProvider.php index 534ed7acc..8e0254104 100644 --- a/src/Gdpr/Provider/DataObjectProvider.php +++ b/src/Gdpr/Provider/DataObjectProvider.php @@ -51,18 +51,18 @@ public function findData(SearchTerms $terms, FilterParameter $options): array $query->filterInteger('id', $terms->getId()); } - $texts = [ - $terms->getFirstname(), - $terms->getLastname(), - $terms->getEmail(), - ]; - - foreach ($texts as $value) { - $value = trim((string)$value); - if ($value !== '') { - $query->filterFullText($value); - } + $texts = [ + $terms->getFirstname(), + $terms->getLastname(), + $terms->getEmail(), + ]; + + foreach ($texts as $value) { + $value = trim((string)$value); + if ($value !== '') { + $query->filterFullText($value); } + } $this->applySearchOptions($query, $options); From 41d77913a92415fb57011dd67bccc033380a2031 Mon Sep 17 00:00:00 2001 From: stunnerparas Date: Fri, 28 Nov 2025 03:43:19 +0000 Subject: [PATCH 22/39] change delete option --- src/Gdpr/Provider/DataObjectProvider.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Gdpr/Provider/DataObjectProvider.php b/src/Gdpr/Provider/DataObjectProvider.php index 8e0254104..fae2849ac 100644 --- a/src/Gdpr/Provider/DataObjectProvider.php +++ b/src/Gdpr/Provider/DataObjectProvider.php @@ -102,7 +102,7 @@ private function applySearchOptions(QueryInterface $query, FilterParameter $opti public function getDeleteSwaggerOperationId(): string { - return 'pimcore_studio_api_delete_data_object_grid_configuration'; //is this correct ? + return 'data_object_batch_delete'; } /** From 01bde69df87985c42c3b16b5b42d110add6f7430 Mon Sep 17 00:00:00 2001 From: stunnerparas Date: Fri, 28 Nov 2025 07:29:40 +0000 Subject: [PATCH 23/39] Add assets and pagination --- config/gdpr.yaml | 6 + .../ExportAssetFileParameter.php | 3 + .../SearchDataProviderController.php | 9 +- src/Gdpr/Provider/AssetsProvider.php | 173 ++++++++++++++++++ src/Gdpr/Provider/Legacy/AssetExporter.php | 50 +++++ .../Legacy/AssetExporterInterface.php | 27 +++ .../Schema/GdprSearchResultCollection.php | 15 +- src/Gdpr/Service/GdprManagerService.php | 2 +- 8 files changed, 280 insertions(+), 5 deletions(-) create mode 100644 src/Gdpr/Provider/AssetsProvider.php create mode 100644 src/Gdpr/Provider/Legacy/AssetExporter.php create mode 100644 src/Gdpr/Provider/Legacy/AssetExporterInterface.php diff --git a/config/gdpr.yaml b/config/gdpr.yaml index 3d2733c60..9e8aae2f4 100644 --- a/config/gdpr.yaml +++ b/config/gdpr.yaml @@ -29,6 +29,12 @@ services: Pimcore\Bundle\StudioBackendBundle\Gdpr\Provider\DataObjectProvider: tags: ["pimcore.studio_backend.gdpr_data_provider"] + Pimcore\Bundle\StudioBackendBundle\Gdpr\Provider\AssetsProvider: + tags: ["pimcore.studio_backend.gdpr_data_provider"] + # --- Legacy Code from the admin-ui-classic-bundle --- Pimcore\Bundle\StudioBackendBundle\Gdpr\Provider\Legacy\ObjectExporterInterface: class: Pimcore\Bundle\StudioBackendBundle\Gdpr\Provider\Legacy\ObjectExporter + + Pimcore\Bundle\StudioBackendBundle\Gdpr\Provider\Legacy\AssetExporterInterface: + class: Pimcore\Bundle\StudioBackendBundle\Gdpr\Provider\Legacy\AssetExporter diff --git a/src/Asset/MappedParameter/ExportAssetFileParameter.php b/src/Asset/MappedParameter/ExportAssetFileParameter.php index 50f106669..cc8776f39 100644 --- a/src/Asset/MappedParameter/ExportAssetFileParameter.php +++ b/src/Asset/MappedParameter/ExportAssetFileParameter.php @@ -24,6 +24,9 @@ public function __construct( ) { } + /** + * @return Asset[] + */ public function getAssets(): array { return $this->assets; diff --git a/src/Gdpr/Controller/SearchDataProviderController.php b/src/Gdpr/Controller/SearchDataProviderController.php index 8912506b2..3369ae998 100644 --- a/src/Gdpr/Controller/SearchDataProviderController.php +++ b/src/Gdpr/Controller/SearchDataProviderController.php @@ -26,6 +26,7 @@ use Pimcore\Bundle\StudioBackendBundle\OpenApi\Config\Tags; use Pimcore\Bundle\StudioBackendBundle\Util\Constant\HttpResponseCodes; use Pimcore\Bundle\StudioBackendBundle\Util\Constant\UserPermissions; +use Pimcore\Bundle\StudioBackendBundle\Util\Trait\PaginatedResponseTrait; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpKernel\Attribute\MapRequestPayload; use Symfony\Component\Routing\Attribute\Route; @@ -37,6 +38,8 @@ */ final class SearchDataProviderController extends AbstractApiController { + use PaginatedResponseTrait; + public function __construct( SerializerInterface $serializer, private readonly GdprManagerServiceInterface $gdprManagerService, @@ -82,6 +85,10 @@ public function searchData( $collection = $this->gdprManagerService->search($request); - return $this->jsonResponse($collection); + return $this->getPaginatedCollection( + $this->serializer, + $collection->getItems(), + $collection->getTotalItems() + ); } } diff --git a/src/Gdpr/Provider/AssetsProvider.php b/src/Gdpr/Provider/AssetsProvider.php new file mode 100644 index 000000000..79d60f35b --- /dev/null +++ b/src/Gdpr/Provider/AssetsProvider.php @@ -0,0 +1,173 @@ +query->createAssetQuery(); + + $query->excludeFolders(); + + if ($terms->getId() !== null) { + $query->filterInteger('id', $terms->getId()); + } + + $texts = [ + $terms->getFirstname(), + $terms->getLastname(), + $terms->getEmail(), + ]; + + foreach ($texts as $value) { + $value = trim((string)$value); + if ($value !== '') { + $query->filterFullText($value); + } + } + + $this->applySearchOptions($query, $options); + + $searchResult = $this->searchService->searchAssets($query); + + $columns = $this->getAvailableColumns(); + + $items = $searchResult->getItems(); + + return array_map( + fn ($item) => new GdprDataRow([ + 'type' => $item->getType(), + 'id' => $item->getId(), + 'fullPath' => $item->getFullPath(), + 'subType' => $item->getMimeType(), + ], $columns), + $items + ); + } + + private function applySearchOptions(QueryInterface $query, FilterParameter $options): void + { + $query->setPage($options->getPage()); + $query->setPageSize($options->getPageSize()); + + $sortFilter = $options->getSortFilter(); + + if ($sortFilter->getKey() && $sortFilter->getDirection()) { + $directionEnum = strtolower($sortFilter->getDirection()) === SortDirection::DESC->value + ? SortDirection::DESC + : SortDirection::ASC; + + $query->orderByField($sortFilter->getKey(), $directionEnum); + } + + } + + public function getDeleteSwaggerOperationId(): string + { + return 'pimcore_studio_api_assets_batch_delete'; + } + + /** + * {@inheritdoc} + */ + public function getSingleItemForDownload(int $id): array + { + try { + $asset = Asset::getById((int)$id); + + } catch (NotFoundException) { + throw new NotFoundException('Asset Not Found', $id); + } + + $export = [ + 'id' => $asset->getId(), + 'fullPath' => $asset->getFullPath(), + ]; + + $properties = $asset->getProperties(); + $finalProperties = []; + + foreach ($properties as $property) { + $finalProperties[] = $property->serialize(); + } + + $export['properties'] = $finalProperties; + + $this->assetExporter->doexportAsset($asset, $export); + + return $export; + } + + public function getName(): string + { + return 'Assets'; + } + + public function getKey(): string + { + return 'assets'; + } + + public function getSortPriority(): int + { + return 8; + } + + /** + * {@inheritdoc} + */ + public function getRequiredPermissions(): array + { + return [UserPermissions::ASSETS->value]; + } + + /** + * {@inheritdoc} + */ + public function getAvailableColumns(): array + { + return [ + new GdprDataColumn('type', 'Type'), + new GdprDataColumn('id', 'ID'), + new GdprDataColumn('fullPath', 'Full Path'), + new GdprDataColumn('subType', 'Type'), + ]; + } +} diff --git a/src/Gdpr/Provider/Legacy/AssetExporter.php b/src/Gdpr/Provider/Legacy/AssetExporter.php new file mode 100644 index 000000000..b36db6c03 --- /dev/null +++ b/src/Gdpr/Provider/Legacy/AssetExporter.php @@ -0,0 +1,50 @@ +getId(); + $webAsset['fullpath'] = $theAsset->getRealFullPath(); + $properties = $theAsset->getProperties(); + $finalProperties = []; + + foreach ($properties as $property) { + $finalProperties[] = $property->serialize(); + } + + $webAsset['properties'] = $finalProperties; + $webAsset['customSettings'] = $theAsset->getCustomSettings(); + + $resultItem = json_decode(json_encode($webAsset), true); + unset($resultItem['data']); + + return $resultItem; + } + +} diff --git a/src/Gdpr/Provider/Legacy/AssetExporterInterface.php b/src/Gdpr/Provider/Legacy/AssetExporterInterface.php new file mode 100644 index 000000000..0571e5502 --- /dev/null +++ b/src/Gdpr/Provider/Legacy/AssetExporterInterface.php @@ -0,0 +1,27 @@ + $result + */ + public function doexportAsset(Asset $theAsset): array; + +} diff --git a/src/Gdpr/Schema/GdprSearchResultCollection.php b/src/Gdpr/Schema/GdprSearchResultCollection.php index 7033a253e..ba428d2be 100644 --- a/src/Gdpr/Schema/GdprSearchResultCollection.php +++ b/src/Gdpr/Schema/GdprSearchResultCollection.php @@ -42,10 +42,14 @@ public function __construct( type: 'array', items: new Items(ref: GdprSearchResult::class) )] - private readonly array $items, - ) { - } + + #[Property( + description: 'Total number of items across all pages', + type: 'integer' + )] + private readonly int $totalItems, + ) {} /** * @return array @@ -54,4 +58,9 @@ public function getItems(): array { return $this->items; } + + public function getTotalItems(): int + { + return $this->totalItems; + } } diff --git a/src/Gdpr/Service/GdprManagerService.php b/src/Gdpr/Service/GdprManagerService.php index fb1b9b532..a88557e55 100644 --- a/src/Gdpr/Service/GdprManagerService.php +++ b/src/Gdpr/Service/GdprManagerService.php @@ -131,7 +131,7 @@ private function getDataProviderCollection(array $providers): Collection */ private function getSearchResultCollection(array $results): GdprSearchResultCollection { - $collection = new GdprSearchResultCollection($results); + $collection = new GdprSearchResultCollection($results, count($results)); $this->eventDispatcher->dispatch( new GdprSearchResultEvent($collection), From e8f3dc3c245819f1cb306ad82f5dd05d1fdeef62 Mon Sep 17 00:00:00 2001 From: stunnerparas <49896041+stunnerparas@users.noreply.github.com> Date: Fri, 28 Nov 2025 08:17:36 +0000 Subject: [PATCH 24/39] Apply php-cs-fixer changes --- src/Gdpr/Provider/Legacy/AssetExporter.php | 1 - src/Gdpr/Provider/Legacy/AssetExporterInterface.php | 2 +- src/Gdpr/Schema/GdprSearchResultCollection.php | 3 ++- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Gdpr/Provider/Legacy/AssetExporter.php b/src/Gdpr/Provider/Legacy/AssetExporter.php index b36db6c03..ef45a6be2 100644 --- a/src/Gdpr/Provider/Legacy/AssetExporter.php +++ b/src/Gdpr/Provider/Legacy/AssetExporter.php @@ -46,5 +46,4 @@ public function doexportAsset(Asset $theAsset): array return $resultItem; } - } diff --git a/src/Gdpr/Provider/Legacy/AssetExporterInterface.php b/src/Gdpr/Provider/Legacy/AssetExporterInterface.php index 0571e5502..f37afe2a3 100644 --- a/src/Gdpr/Provider/Legacy/AssetExporterInterface.php +++ b/src/Gdpr/Provider/Legacy/AssetExporterInterface.php @@ -12,6 +12,7 @@ */ namespace Pimcore\Bundle\StudioBackendBundle\Gdpr\Provider\Legacy; + use Pimcore\Model\Asset; /** @@ -23,5 +24,4 @@ interface AssetExporterInterface * @param array $result */ public function doexportAsset(Asset $theAsset): array; - } diff --git a/src/Gdpr/Schema/GdprSearchResultCollection.php b/src/Gdpr/Schema/GdprSearchResultCollection.php index ba428d2be..d4f9884ff 100644 --- a/src/Gdpr/Schema/GdprSearchResultCollection.php +++ b/src/Gdpr/Schema/GdprSearchResultCollection.php @@ -49,7 +49,8 @@ public function __construct( type: 'integer' )] private readonly int $totalItems, - ) {} + ) { + } /** * @return array From 0418b493a1118a07aa18d0480d337fb0f09c2514 Mon Sep 17 00:00:00 2001 From: stunnerparas Date: Fri, 28 Nov 2025 09:04:05 +0000 Subject: [PATCH 25/39] Update export of asset --- .../ExportAssetFileParameter.php | 3 --- src/Gdpr/Provider/AssetsProvider.php | 18 ++---------------- 2 files changed, 2 insertions(+), 19 deletions(-) diff --git a/src/Asset/MappedParameter/ExportAssetFileParameter.php b/src/Asset/MappedParameter/ExportAssetFileParameter.php index cc8776f39..50f106669 100644 --- a/src/Asset/MappedParameter/ExportAssetFileParameter.php +++ b/src/Asset/MappedParameter/ExportAssetFileParameter.php @@ -24,9 +24,6 @@ public function __construct( ) { } - /** - * @return Asset[] - */ public function getAssets(): array { return $this->assets; diff --git a/src/Gdpr/Provider/AssetsProvider.php b/src/Gdpr/Provider/AssetsProvider.php index 79d60f35b..641fa37b9 100644 --- a/src/Gdpr/Provider/AssetsProvider.php +++ b/src/Gdpr/Provider/AssetsProvider.php @@ -115,22 +115,8 @@ public function getSingleItemForDownload(int $id): array } catch (NotFoundException) { throw new NotFoundException('Asset Not Found', $id); } - - $export = [ - 'id' => $asset->getId(), - 'fullPath' => $asset->getFullPath(), - ]; - - $properties = $asset->getProperties(); - $finalProperties = []; - - foreach ($properties as $property) { - $finalProperties[] = $property->serialize(); - } - - $export['properties'] = $finalProperties; - - $this->assetExporter->doexportAsset($asset, $export); + + $export = $this->assetExporter->doexportAsset($asset); return $export; } From 7b9037becf97bdb0d7b6ebb4df35e4966cec42d9 Mon Sep 17 00:00:00 2001 From: stunnerparas <49896041+stunnerparas@users.noreply.github.com> Date: Fri, 28 Nov 2025 09:05:03 +0000 Subject: [PATCH 26/39] Apply php-cs-fixer changes --- src/Gdpr/Provider/AssetsProvider.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Gdpr/Provider/AssetsProvider.php b/src/Gdpr/Provider/AssetsProvider.php index 641fa37b9..8219dd50f 100644 --- a/src/Gdpr/Provider/AssetsProvider.php +++ b/src/Gdpr/Provider/AssetsProvider.php @@ -115,7 +115,7 @@ public function getSingleItemForDownload(int $id): array } catch (NotFoundException) { throw new NotFoundException('Asset Not Found', $id); } - + $export = $this->assetExporter->doexportAsset($asset); return $export; From b287105c900deeeeb64caf182c2487c2b968c68b Mon Sep 17 00:00:00 2001 From: stunnerparas Date: Fri, 28 Nov 2025 09:10:17 +0000 Subject: [PATCH 27/39] sonar issue fix --- src/Gdpr/Provider/AssetsProvider.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Gdpr/Provider/AssetsProvider.php b/src/Gdpr/Provider/AssetsProvider.php index 8219dd50f..ed546d0b7 100644 --- a/src/Gdpr/Provider/AssetsProvider.php +++ b/src/Gdpr/Provider/AssetsProvider.php @@ -116,9 +116,8 @@ public function getSingleItemForDownload(int $id): array throw new NotFoundException('Asset Not Found', $id); } - $export = $this->assetExporter->doexportAsset($asset); + return $this->assetExporter->doexportAsset($asset); - return $export; } public function getName(): string From cd21709d1a09a30361f30a07fac3b8aed1b6bf4b Mon Sep 17 00:00:00 2001 From: stunnerparas Date: Fri, 28 Nov 2025 09:18:07 +0000 Subject: [PATCH 28/39] changes --- src/Gdpr/Provider/Legacy/AssetExporterInterface.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Gdpr/Provider/Legacy/AssetExporterInterface.php b/src/Gdpr/Provider/Legacy/AssetExporterInterface.php index f37afe2a3..e184225e8 100644 --- a/src/Gdpr/Provider/Legacy/AssetExporterInterface.php +++ b/src/Gdpr/Provider/Legacy/AssetExporterInterface.php @@ -21,7 +21,7 @@ interface AssetExporterInterface { /** - * @param array $result + * @return array */ public function doexportAsset(Asset $theAsset): array; } From d46e66fb4083337504f7f3a73d6e401aead36df6 Mon Sep 17 00:00:00 2001 From: stunnerparas Date: Mon, 1 Dec 2025 04:42:53 +0000 Subject: [PATCH 29/39] Change the assets to zip and some improvements --- src/Gdpr/Controller/ExportController.php | 6 +-- .../GdprStructuredSearchParameters.php | 25 ++++++++++-- src/Gdpr/Provider/AssetsProvider.php | 12 ++++-- src/Gdpr/Provider/DataObjectProvider.php | 16 ++++++-- src/Gdpr/Provider/DataProviderInterface.php | 5 +-- src/Gdpr/Provider/Legacy/AssetExporter.php | 39 ++++++++++++++++++- .../Legacy/AssetExporterInterface.php | 6 +-- src/Gdpr/Provider/PimcoreUserProvider.php | 38 +++++++++--------- src/Gdpr/Service/GdprManagerService.php | 18 ++++++--- .../Service/GdprManagerServiceInterface.php | 4 +- 10 files changed, 122 insertions(+), 47 deletions(-) diff --git a/src/Gdpr/Controller/ExportController.php b/src/Gdpr/Controller/ExportController.php index 7022230a2..107a5d21f 100644 --- a/src/Gdpr/Controller/ExportController.php +++ b/src/Gdpr/Controller/ExportController.php @@ -25,7 +25,7 @@ use Pimcore\Bundle\StudioBackendBundle\OpenApi\Config\Tags; use Pimcore\Bundle\StudioBackendBundle\Util\Constant\HttpResponseCodes; use Pimcore\Bundle\StudioBackendBundle\Util\Constant\UserPermissions; -use Symfony\Component\HttpFoundation\StreamedResponse; +use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Attribute\MapQueryParameter; use Symfony\Component\Routing\Attribute\Route; use Symfony\Component\Security\Http\Attribute\IsGranted; @@ -81,7 +81,7 @@ public function __construct( public function startExport( int $id, #[MapQueryParameter] string $providerKey - ): StreamedResponse { - return $this->gdprManagerService->getExportDataAsJson($id, $providerKey); + ): Response { + return $this->gdprManagerService->getExportData($id, $providerKey); } } diff --git a/src/Gdpr/MappedParameter/GdprStructuredSearchParameters.php b/src/Gdpr/MappedParameter/GdprStructuredSearchParameters.php index 7c907bc20..4bfa7facc 100644 --- a/src/Gdpr/MappedParameter/GdprStructuredSearchParameters.php +++ b/src/Gdpr/MappedParameter/GdprStructuredSearchParameters.php @@ -32,14 +32,33 @@ public function __construct( #[NotBlank] #[All(new Type('string'))] - public array $providers, + private readonly array $providers, #[Valid] #[NotNull] - public SearchTerms $searchTerms, + private readonly SearchTerms $searchTerms, #[Valid] - public FilterParameter $filters + private readonly FilterParameter $filters ) { } + + /** + * @return string[] + */ + public function getProviders(): array + { + return $this->providers; + } + + public function getSearchTerms(): SearchTerms + { + return $this->searchTerms; + } + + public function getFilters(): FilterParameter + { + return $this->filters; + } + } diff --git a/src/Gdpr/Provider/AssetsProvider.php b/src/Gdpr/Provider/AssetsProvider.php index ed546d0b7..3c9c17856 100644 --- a/src/Gdpr/Provider/AssetsProvider.php +++ b/src/Gdpr/Provider/AssetsProvider.php @@ -23,6 +23,7 @@ use Pimcore\Bundle\StudioBackendBundle\Gdpr\Schema\GdprDataColumn; use Pimcore\Bundle\StudioBackendBundle\Gdpr\Schema\GdprDataRow; use Pimcore\Bundle\StudioBackendBundle\Util\Constant\UserPermissions; +use Symfony\Component\HttpFoundation\Response; use Pimcore\Model\Asset; /** @@ -71,7 +72,7 @@ public function findData(SearchTerms $terms, FilterParameter $options): array $items = $searchResult->getItems(); - return array_map( + $rows = array_map( fn ($item) => new GdprDataRow([ 'type' => $item->getType(), 'id' => $item->getId(), @@ -80,6 +81,11 @@ public function findData(SearchTerms $terms, FilterParameter $options): array ], $columns), $items ); + + return [ + 'totalSubItems' => $searchResult->getTotalItems(), + 'rows' => $rows, + ]; } private function applySearchOptions(QueryInterface $query, FilterParameter $options): void @@ -107,7 +113,7 @@ public function getDeleteSwaggerOperationId(): string /** * {@inheritdoc} */ - public function getSingleItemForDownload(int $id): array + public function getSingleItemForDownload(int $id): Response { try { $asset = Asset::getById((int)$id); @@ -116,7 +122,7 @@ public function getSingleItemForDownload(int $id): array throw new NotFoundException('Asset Not Found', $id); } - return $this->assetExporter->doexportAsset($asset); + return $this->assetExporter->doExportData($asset); } diff --git a/src/Gdpr/Provider/DataObjectProvider.php b/src/Gdpr/Provider/DataObjectProvider.php index fae2849ac..cc3be7de5 100644 --- a/src/Gdpr/Provider/DataObjectProvider.php +++ b/src/Gdpr/Provider/DataObjectProvider.php @@ -25,6 +25,8 @@ use Pimcore\Bundle\StudioBackendBundle\Util\Constant\UserPermissions; use Pimcore\Model\DataObject; use Pimcore\Model\DataObject\Concrete; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpFoundation\JsonResponse; /** * @internal @@ -72,7 +74,7 @@ public function findData(SearchTerms $terms, FilterParameter $options): array $items = $searchResult->getItems(); - return array_map( + $rows = array_map( fn ($item) => new GdprDataRow([ 'type' => $item->getType(), 'id' => $item->getId(), @@ -81,6 +83,12 @@ public function findData(SearchTerms $terms, FilterParameter $options): array ], $columns), $items ); + + return [ + 'totalSubItems' => $searchResult->getTotalItems(), + 'rows' => $rows, + ]; + } private function applySearchOptions(QueryInterface $query, FilterParameter $options): void @@ -108,7 +116,7 @@ public function getDeleteSwaggerOperationId(): string /** * {@inheritdoc} */ - public function getSingleItemForDownload(int $id): array + public function getSingleItemForDownload(int $id): Response { try { $object = DataObject::getById((int)$id); @@ -136,7 +144,9 @@ public function getSingleItemForDownload(int $id): array $this->objectExporter->doExportObject($object, $export); - return $export; + return new JsonResponse( + $export + ); } public function getName(): string diff --git a/src/Gdpr/Provider/DataProviderInterface.php b/src/Gdpr/Provider/DataProviderInterface.php index 9feffc883..f8133ea2d 100644 --- a/src/Gdpr/Provider/DataProviderInterface.php +++ b/src/Gdpr/Provider/DataProviderInterface.php @@ -13,12 +13,12 @@ namespace Pimcore\Bundle\StudioBackendBundle\Gdpr\Provider; -use Pimcore\Bundle\StudioBackendBundle\Exception\Api\ForbiddenException; use Pimcore\Bundle\StudioBackendBundle\Exception\Api\NotFoundException; use Pimcore\Bundle\StudioBackendBundle\Filter\MappedParameter\FilterParameter; use Pimcore\Bundle\StudioBackendBundle\Gdpr\Attribute\Request\SearchTerms; use Pimcore\Bundle\StudioBackendBundle\Gdpr\Schema\GdprDataColumn; use Pimcore\Bundle\StudioBackendBundle\Gdpr\Schema\GdprDataRow; +use Symfony\Component\HttpFoundation\Response; interface DataProviderInterface { @@ -47,7 +47,6 @@ public function getRequiredPermissions(): array; /** * @throws NotFoundException - * @throws ForbiddenException */ - public function getSingleItemForDownload(int $id): array|object; + public function getSingleItemForDownload(int $id): Response; } diff --git a/src/Gdpr/Provider/Legacy/AssetExporter.php b/src/Gdpr/Provider/Legacy/AssetExporter.php index ef45a6be2..8bafa3e68 100644 --- a/src/Gdpr/Provider/Legacy/AssetExporter.php +++ b/src/Gdpr/Provider/Legacy/AssetExporter.php @@ -12,6 +12,7 @@ namespace Pimcore\Bundle\StudioBackendBundle\Gdpr\Provider\Legacy; +use Symfony\Component\HttpFoundation\Response; use Pimcore\Model\Asset; /** @@ -26,7 +27,7 @@ /** * {@inheritdoc} */ - public function doexportAsset(Asset $theAsset): array + private function doexportAsset(Asset $theAsset): array { $webAsset = []; $webAsset['id'] = $theAsset->getId(); @@ -46,4 +47,40 @@ public function doexportAsset(Asset $theAsset): array return $resultItem; } + + public function doExportData(Asset $asset): Response + { + $exportIds = []; + $exportIds[$asset->getId()] = true; + + $file = tempnam('/tmp', 'zip'); + $zip = new \ZipArchive(); + $zip->open($file, \ZipArchive::OVERWRITE); + + foreach (array_keys($exportIds) as $id) { + $theAsset = Asset::getById($id); + + $resultItem = $this->doexportAsset($theAsset); + $resultItem = json_encode($resultItem); + + $zip->addFromString($asset->getFilename() . '.txt', $resultItem); + + if (!$theAsset instanceof Asset\Folder) { + $zip->addFromString($theAsset->getFilename(), $theAsset->getData()); + } + } + + $zip->close(); + + $size = filesize($file); + $content = file_get_contents($file); + unlink($file); + + $response = new Response($content); + $response->headers->set('Content-Type', 'application/zip'); + $response->headers->set('Content-Length', (string) $size); + $response->headers->set('Content-Disposition', 'attachment; filename="' . $asset->getFilename() . '.zip"'); + + return $response; + } } diff --git a/src/Gdpr/Provider/Legacy/AssetExporterInterface.php b/src/Gdpr/Provider/Legacy/AssetExporterInterface.php index e184225e8..3c9aaf926 100644 --- a/src/Gdpr/Provider/Legacy/AssetExporterInterface.php +++ b/src/Gdpr/Provider/Legacy/AssetExporterInterface.php @@ -13,6 +13,7 @@ namespace Pimcore\Bundle\StudioBackendBundle\Gdpr\Provider\Legacy; +use Symfony\Component\HttpFoundation\Response; use Pimcore\Model\Asset; /** @@ -20,8 +21,5 @@ */ interface AssetExporterInterface { - /** - * @return array - */ - public function doexportAsset(Asset $theAsset): array; + public function doExportData(Asset $asset): Response; } diff --git a/src/Gdpr/Provider/PimcoreUserProvider.php b/src/Gdpr/Provider/PimcoreUserProvider.php index fa50032ed..15c2357e0 100644 --- a/src/Gdpr/Provider/PimcoreUserProvider.php +++ b/src/Gdpr/Provider/PimcoreUserProvider.php @@ -23,6 +23,8 @@ use Pimcore\Db; use Pimcore\Model\User; use Pimcore\Model\User\Listing; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpFoundation\JsonResponse; /** * @internal @@ -77,7 +79,7 @@ public function findData(SearchTerms $terms, FilterParameter $options): array $columns = $this->getAvailableColumns(); - return array_map( + $rows = array_map( fn ($user) => new GdprDataRow( [ 'id' => $user->getId(), @@ -90,7 +92,12 @@ public function findData(SearchTerms $terms, FilterParameter $options): array $columns ), $users - ); + ); + + return [ + 'totalSubItems' => $listing->getTotalCount(), + 'rows' => $rows, + ]; } private function applySearchOptions(Listing $listing, FilterParameter $options): void @@ -118,29 +125,22 @@ public function getDeleteSwaggerOperationId(): string /** * {@inheritdoc} */ - public function getSingleItemForDownload(int $id): array + public function getSingleItemForDownload(int $id): Response { - $listing = new Listing(); - $listing->setCondition('id = ?', [$id]); - $listing->setLimit(1); + $user = User::getById($id); - $users = $listing->getUsers(); - - if (empty($users)) { + if (!$user) { throw new NotFoundException('Pimcore User', $id); } - $user = $users[0]; + $userData = $user->getObjectVars(); - return [ - 'id' => $user->getId(), - 'name' => $user->getName(), - 'firstname' => $user->getFirstname(), - 'lastname' => $user->getLastname(), - 'email' => $user->getEmail(), - 'versions' => $this->getVersionDataForUser($user), - 'usageLog' => $this->getUsageLogDataForUser($user), - ]; + unset($userData['password']); + + $userData['versions'] = $this->getVersionDataForUser($user); + $userData['usageLog'] = $this->getUsageLogDataForUser($user); + + return new JsonResponse($userData); } protected function getVersionDataForUser(User\AbstractUser $user): array diff --git a/src/Gdpr/Service/GdprManagerService.php b/src/Gdpr/Service/GdprManagerService.php index a88557e55..d944d7df8 100644 --- a/src/Gdpr/Service/GdprManagerService.php +++ b/src/Gdpr/Service/GdprManagerService.php @@ -28,8 +28,10 @@ use Pimcore\Bundle\StudioBackendBundle\Util\Constant\HttpResponseCodes; use Pimcore\Bundle\StudioBackendBundle\Util\Constant\HttpResponseHeaders; use Pimcore\Bundle\StudioBackendBundle\Util\Trait\StreamedResponseTrait; +use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\StreamedResponse; use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; +use Symfony\Component\HttpFoundation\JsonResponse; use function count; use function sprintf; use function strlen; @@ -65,12 +67,12 @@ public function search(GdprStructuredSearchParameters $request): GdprSearchResul { $allResults = []; - foreach ($request->providers as $providerKey) { + foreach ($request->getProviders() as $providerKey) { $provider = $this->loader->resolve($providerKey); $this->checkProviderPermission($provider); - $results = $provider->findData($request->searchTerms, $request->filters); + $results = $provider->findData($request->getSearchTerms(), $request->getFilters()); if (!empty($results)) { $allResults[] = new GdprSearchResult( @@ -86,8 +88,8 @@ public function search(GdprStructuredSearchParameters $request): GdprSearchResul /** * {@inheritdoc} - */ - public function getExportDataAsJson(int $id, string $providerKey): StreamedResponse + */ + public function getExportData(int $id, string $providerKey): Response { $provider = $this->loader->resolve($providerKey); @@ -141,10 +143,14 @@ private function getSearchResultCollection(array $results): GdprSearchResultColl return $collection; } - private function createExportResponse(mixed $data, string $providerKey, int $id): StreamedResponse + private function createExportResponse(mixed $data, string $providerKey, int $id): Response { + if (!$data instanceof JsonResponse) { + return $data; + } + try { - $jsonData = json_encode($data, JSON_THROW_ON_ERROR|JSON_PRETTY_PRINT); + $jsonData = json_encode(json_decode($data->getContent(), true), JSON_THROW_ON_ERROR | JSON_PRETTY_PRINT); } catch (JsonException $e) { throw new InvalidArgumentException( sprintf( diff --git a/src/Gdpr/Service/GdprManagerServiceInterface.php b/src/Gdpr/Service/GdprManagerServiceInterface.php index 29f6afddd..e04264b48 100644 --- a/src/Gdpr/Service/GdprManagerServiceInterface.php +++ b/src/Gdpr/Service/GdprManagerServiceInterface.php @@ -19,7 +19,7 @@ use Pimcore\Bundle\StudioBackendBundle\Gdpr\Schema\GdprDataProvider; use Pimcore\Bundle\StudioBackendBundle\Gdpr\Schema\GdprSearchResultCollection; use Pimcore\Bundle\StudioBackendBundle\Response\Collection; -use Symfony\Component\HttpFoundation\StreamedResponse; +use Symfony\Component\HttpFoundation\Response; /** * @internal @@ -42,5 +42,5 @@ public function search(GdprStructuredSearchParameters $request): GdprSearchResul * @throws ForbiddenException * @throws NotFoundException */ - public function getExportDataAsJson(int $id, string $providerKey): StreamedResponse; + public function getExportData(int $id, string $providerKey): Response; } From 5b5b85985994eefdc4213c08aa7d940def2b7c43 Mon Sep 17 00:00:00 2001 From: stunnerparas <49896041+stunnerparas@users.noreply.github.com> Date: Mon, 1 Dec 2025 04:53:09 +0000 Subject: [PATCH 30/39] Apply php-cs-fixer changes --- .../MappedParameter/GdprStructuredSearchParameters.php | 1 - src/Gdpr/Provider/AssetsProvider.php | 2 +- src/Gdpr/Provider/DataObjectProvider.php | 2 +- src/Gdpr/Provider/Legacy/AssetExporter.php | 7 ++++--- src/Gdpr/Provider/Legacy/AssetExporterInterface.php | 2 +- src/Gdpr/Provider/PimcoreUserProvider.php | 4 ++-- src/Gdpr/Service/GdprManagerService.php | 4 ++-- 7 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/Gdpr/MappedParameter/GdprStructuredSearchParameters.php b/src/Gdpr/MappedParameter/GdprStructuredSearchParameters.php index 4bfa7facc..67e23dc1b 100644 --- a/src/Gdpr/MappedParameter/GdprStructuredSearchParameters.php +++ b/src/Gdpr/MappedParameter/GdprStructuredSearchParameters.php @@ -60,5 +60,4 @@ public function getFilters(): FilterParameter { return $this->filters; } - } diff --git a/src/Gdpr/Provider/AssetsProvider.php b/src/Gdpr/Provider/AssetsProvider.php index 3c9c17856..211ec68e8 100644 --- a/src/Gdpr/Provider/AssetsProvider.php +++ b/src/Gdpr/Provider/AssetsProvider.php @@ -23,8 +23,8 @@ use Pimcore\Bundle\StudioBackendBundle\Gdpr\Schema\GdprDataColumn; use Pimcore\Bundle\StudioBackendBundle\Gdpr\Schema\GdprDataRow; use Pimcore\Bundle\StudioBackendBundle\Util\Constant\UserPermissions; -use Symfony\Component\HttpFoundation\Response; use Pimcore\Model\Asset; +use Symfony\Component\HttpFoundation\Response; /** * @internal diff --git a/src/Gdpr/Provider/DataObjectProvider.php b/src/Gdpr/Provider/DataObjectProvider.php index cc3be7de5..843daa48d 100644 --- a/src/Gdpr/Provider/DataObjectProvider.php +++ b/src/Gdpr/Provider/DataObjectProvider.php @@ -25,8 +25,8 @@ use Pimcore\Bundle\StudioBackendBundle\Util\Constant\UserPermissions; use Pimcore\Model\DataObject; use Pimcore\Model\DataObject\Concrete; -use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\JsonResponse; +use Symfony\Component\HttpFoundation\Response; /** * @internal diff --git a/src/Gdpr/Provider/Legacy/AssetExporter.php b/src/Gdpr/Provider/Legacy/AssetExporter.php index 8bafa3e68..875364e7c 100644 --- a/src/Gdpr/Provider/Legacy/AssetExporter.php +++ b/src/Gdpr/Provider/Legacy/AssetExporter.php @@ -12,8 +12,9 @@ namespace Pimcore\Bundle\StudioBackendBundle\Gdpr\Provider\Legacy; -use Symfony\Component\HttpFoundation\Response; use Pimcore\Model\Asset; +use Symfony\Component\HttpFoundation\Response; +use ZipArchive; /** * Copied from old admin-ui-classic-bundle @@ -54,8 +55,8 @@ public function doExportData(Asset $asset): Response $exportIds[$asset->getId()] = true; $file = tempnam('/tmp', 'zip'); - $zip = new \ZipArchive(); - $zip->open($file, \ZipArchive::OVERWRITE); + $zip = new ZipArchive(); + $zip->open($file, ZipArchive::OVERWRITE); foreach (array_keys($exportIds) as $id) { $theAsset = Asset::getById($id); diff --git a/src/Gdpr/Provider/Legacy/AssetExporterInterface.php b/src/Gdpr/Provider/Legacy/AssetExporterInterface.php index 3c9aaf926..4fec14d72 100644 --- a/src/Gdpr/Provider/Legacy/AssetExporterInterface.php +++ b/src/Gdpr/Provider/Legacy/AssetExporterInterface.php @@ -13,8 +13,8 @@ namespace Pimcore\Bundle\StudioBackendBundle\Gdpr\Provider\Legacy; -use Symfony\Component\HttpFoundation\Response; use Pimcore\Model\Asset; +use Symfony\Component\HttpFoundation\Response; /** * @internal diff --git a/src/Gdpr/Provider/PimcoreUserProvider.php b/src/Gdpr/Provider/PimcoreUserProvider.php index 15c2357e0..3d3c1233c 100644 --- a/src/Gdpr/Provider/PimcoreUserProvider.php +++ b/src/Gdpr/Provider/PimcoreUserProvider.php @@ -23,8 +23,8 @@ use Pimcore\Db; use Pimcore\Model\User; use Pimcore\Model\User\Listing; -use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\JsonResponse; +use Symfony\Component\HttpFoundation\Response; /** * @internal @@ -92,7 +92,7 @@ public function findData(SearchTerms $terms, FilterParameter $options): array $columns ), $users - ); + ); return [ 'totalSubItems' => $listing->getTotalCount(), diff --git a/src/Gdpr/Service/GdprManagerService.php b/src/Gdpr/Service/GdprManagerService.php index d944d7df8..10f55b3c9 100644 --- a/src/Gdpr/Service/GdprManagerService.php +++ b/src/Gdpr/Service/GdprManagerService.php @@ -28,10 +28,10 @@ use Pimcore\Bundle\StudioBackendBundle\Util\Constant\HttpResponseCodes; use Pimcore\Bundle\StudioBackendBundle\Util\Constant\HttpResponseHeaders; use Pimcore\Bundle\StudioBackendBundle\Util\Trait\StreamedResponseTrait; +use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\StreamedResponse; use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; -use Symfony\Component\HttpFoundation\JsonResponse; use function count; use function sprintf; use function strlen; @@ -88,7 +88,7 @@ public function search(GdprStructuredSearchParameters $request): GdprSearchResul /** * {@inheritdoc} - */ + */ public function getExportData(int $id, string $providerKey): Response { $provider = $this->loader->resolve($providerKey); From 28ec677466fdceeec5535875aaf51de2a9026284 Mon Sep 17 00:00:00 2001 From: stunnerparas Date: Mon, 1 Dec 2025 05:11:00 +0000 Subject: [PATCH 31/39] Ci issue fix --- src/Gdpr/Provider/AssetsProvider.php | 1 + src/Gdpr/Provider/DataObjectProvider.php | 1 + src/Gdpr/Provider/DataProviderInterface.php | 5 ++++- src/Gdpr/Provider/Legacy/AssetExporter.php | 3 ++- src/Gdpr/Provider/Legacy/ObjectExporter.php | 1 + src/Gdpr/Provider/PimcoreUserProvider.php | 1 + 6 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/Gdpr/Provider/AssetsProvider.php b/src/Gdpr/Provider/AssetsProvider.php index 211ec68e8..899b2c89a 100644 --- a/src/Gdpr/Provider/AssetsProvider.php +++ b/src/Gdpr/Provider/AssetsProvider.php @@ -1,4 +1,5 @@ getCustomSettings(); $resultItem = json_decode(json_encode($webAsset), true); - unset($resultItem['data']); + unset($resultItem['data']);declare(strict_types=1); return $resultItem; } diff --git a/src/Gdpr/Provider/Legacy/ObjectExporter.php b/src/Gdpr/Provider/Legacy/ObjectExporter.php index e33066e41..61508b67f 100644 --- a/src/Gdpr/Provider/Legacy/ObjectExporter.php +++ b/src/Gdpr/Provider/Legacy/ObjectExporter.php @@ -1,4 +1,5 @@ Date: Mon, 1 Dec 2025 05:12:12 +0000 Subject: [PATCH 32/39] Apply php-cs-fixer changes --- src/Gdpr/Provider/Legacy/AssetExporter.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Gdpr/Provider/Legacy/AssetExporter.php b/src/Gdpr/Provider/Legacy/AssetExporter.php index e83be73a3..cbbf8e4d7 100644 --- a/src/Gdpr/Provider/Legacy/AssetExporter.php +++ b/src/Gdpr/Provider/Legacy/AssetExporter.php @@ -45,7 +45,9 @@ private function doexportAsset(Asset $theAsset): array $webAsset['customSettings'] = $theAsset->getCustomSettings(); $resultItem = json_decode(json_encode($webAsset), true); - unset($resultItem['data']);declare(strict_types=1); + unset($resultItem['data']); + + declare(strict_types=1); return $resultItem; } From 5b99772f615835b9e3148606add0b9f1ccd00089 Mon Sep 17 00:00:00 2001 From: stunnerparas Date: Mon, 1 Dec 2025 05:46:52 +0000 Subject: [PATCH 33/39] fix --- src/Gdpr/Provider/Legacy/AssetExporter.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Gdpr/Provider/Legacy/AssetExporter.php b/src/Gdpr/Provider/Legacy/AssetExporter.php index cbbf8e4d7..fdcca887b 100644 --- a/src/Gdpr/Provider/Legacy/AssetExporter.php +++ b/src/Gdpr/Provider/Legacy/AssetExporter.php @@ -47,8 +47,6 @@ private function doexportAsset(Asset $theAsset): array $resultItem = json_decode(json_encode($webAsset), true); unset($resultItem['data']); - declare(strict_types=1); - return $resultItem; } From 1c8e506af89a28b376ae5490bcbc45c5259f1c8a Mon Sep 17 00:00:00 2001 From: stunnerparas Date: Mon, 1 Dec 2025 06:04:01 +0000 Subject: [PATCH 34/39] ci issue fix --- src/Gdpr/Service/GdprManagerService.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Gdpr/Service/GdprManagerService.php b/src/Gdpr/Service/GdprManagerService.php index 10f55b3c9..4f5ec86c9 100644 --- a/src/Gdpr/Service/GdprManagerService.php +++ b/src/Gdpr/Service/GdprManagerService.php @@ -74,7 +74,7 @@ public function search(GdprStructuredSearchParameters $request): GdprSearchResul $results = $provider->findData($request->getSearchTerms(), $request->getFilters()); - if (!empty($results)) { + if (!empty($results['rows'])) { $allResults[] = new GdprSearchResult( providerKey: $providerKey, results: $results From fdd93ec978f70174f44918851b560502f8b57840 Mon Sep 17 00:00:00 2001 From: stunnerparas Date: Mon, 1 Dec 2025 06:49:38 +0000 Subject: [PATCH 35/39] ci issue fix --- src/Gdpr/Schema/GdprSearchResult.php | 12 ++++++++++++ src/Gdpr/Service/GdprManagerService.php | 3 ++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/Gdpr/Schema/GdprSearchResult.php b/src/Gdpr/Schema/GdprSearchResult.php index 97ce2411b..35b8a3c77 100644 --- a/src/Gdpr/Schema/GdprSearchResult.php +++ b/src/Gdpr/Schema/GdprSearchResult.php @@ -45,6 +45,13 @@ public function __construct( items: new Items(ref: GdprDataRow::class) )] private readonly array $results, + + #[Property( + description: 'The total number of sub-items for each data providers', + type: 'integer', + example: 5 + )] + private readonly int $totalSubItems, ) { } @@ -60,4 +67,9 @@ public function getResults(): array { return $this->results; } + + public function getTotalSubItems(): int + { + return $this->totalSubItems; + } } diff --git a/src/Gdpr/Service/GdprManagerService.php b/src/Gdpr/Service/GdprManagerService.php index 4f5ec86c9..a1898c70c 100644 --- a/src/Gdpr/Service/GdprManagerService.php +++ b/src/Gdpr/Service/GdprManagerService.php @@ -77,7 +77,8 @@ public function search(GdprStructuredSearchParameters $request): GdprSearchResul if (!empty($results['rows'])) { $allResults[] = new GdprSearchResult( providerKey: $providerKey, - results: $results + results: $results['rows'], + totalSubItems: $results['totalSubItems'] ); } } From 378d169c249fe0006d7462a9fe74f1c091d54fac Mon Sep 17 00:00:00 2001 From: stunnerparas Date: Mon, 1 Dec 2025 09:23:32 +0000 Subject: [PATCH 36/39] review fixes --- src/Gdpr/Controller/ExportController.php | 4 ++-- .../GdprStructuredSearchParameters.php | 6 +++--- src/Gdpr/Provider/AssetsProvider.php | 11 ++++++----- src/Gdpr/Provider/DataObjectProvider.php | 11 ++++++----- src/Gdpr/Provider/DataProviderInterface.php | 10 ++-------- src/Gdpr/Provider/Legacy/AssetExporter.php | 2 +- src/Gdpr/Provider/PimcoreUserProvider.php | 12 ++++++------ src/Gdpr/Schema/GdprSearchResult.php | 6 +++--- src/Gdpr/Service/GdprManagerService.php | 6 +++--- 9 files changed, 32 insertions(+), 36 deletions(-) diff --git a/src/Gdpr/Controller/ExportController.php b/src/Gdpr/Controller/ExportController.php index 107a5d21f..361a134f2 100644 --- a/src/Gdpr/Controller/ExportController.php +++ b/src/Gdpr/Controller/ExportController.php @@ -69,8 +69,8 @@ public function __construct( )] #[SuccessResponse( description: 'gdpr_export_success_response', - content: new MediaType('application/json'), - headers: [new ContentDisposition('inline')] + content: [new MediaType('*/*')], + headers: [new ContentDisposition('attachment')] )] #[DefaultResponses([ HttpResponseCodes::UNAUTHORIZED, diff --git a/src/Gdpr/MappedParameter/GdprStructuredSearchParameters.php b/src/Gdpr/MappedParameter/GdprStructuredSearchParameters.php index 67e23dc1b..c56155dec 100644 --- a/src/Gdpr/MappedParameter/GdprStructuredSearchParameters.php +++ b/src/Gdpr/MappedParameter/GdprStructuredSearchParameters.php @@ -32,14 +32,14 @@ public function __construct( #[NotBlank] #[All(new Type('string'))] - private readonly array $providers, + private array $providers, #[Valid] #[NotNull] - private readonly SearchTerms $searchTerms, + private SearchTerms $searchTerms, #[Valid] - private readonly FilterParameter $filters + private FilterParameter $filters ) { } diff --git a/src/Gdpr/Provider/AssetsProvider.php b/src/Gdpr/Provider/AssetsProvider.php index 899b2c89a..66ada1609 100644 --- a/src/Gdpr/Provider/AssetsProvider.php +++ b/src/Gdpr/Provider/AssetsProvider.php @@ -26,6 +26,7 @@ use Pimcore\Bundle\StudioBackendBundle\Util\Constant\UserPermissions; use Pimcore\Model\Asset; use Symfony\Component\HttpFoundation\Response; +use Pimcore\Bundle\StudioBackendBundle\Response\Collection; /** * @internal @@ -42,7 +43,7 @@ public function __construct( /** * {@inheritdoc} */ - public function findData(SearchTerms $terms, FilterParameter $options): array + public function findData(SearchTerms $terms, FilterParameter $options): Collection { $query = $this->query->createAssetQuery(); @@ -83,10 +84,10 @@ public function findData(SearchTerms $terms, FilterParameter $options): array $items ); - return [ - 'totalSubItems' => $searchResult->getTotalItems(), - 'rows' => $rows, - ]; + return new Collection( + totalItems: $searchResult->getTotalItems(), + items: $rows + ); } private function applySearchOptions(QueryInterface $query, FilterParameter $options): void diff --git a/src/Gdpr/Provider/DataObjectProvider.php b/src/Gdpr/Provider/DataObjectProvider.php index fba45ce01..2c0e9af6a 100644 --- a/src/Gdpr/Provider/DataObjectProvider.php +++ b/src/Gdpr/Provider/DataObjectProvider.php @@ -28,6 +28,7 @@ use Pimcore\Model\DataObject\Concrete; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Response; +use Pimcore\Bundle\StudioBackendBundle\Response\Collection; /** * @internal @@ -44,7 +45,7 @@ public function __construct( /** * {@inheritdoc} */ - public function findData(SearchTerms $terms, FilterParameter $options): array + public function findData(SearchTerms $terms, FilterParameter $options): Collection { $query = $this->query->createDataObjectQuery(); @@ -85,10 +86,10 @@ public function findData(SearchTerms $terms, FilterParameter $options): array $items ); - return [ - 'totalSubItems' => $searchResult->getTotalItems(), - 'rows' => $rows, - ]; + return new Collection( + totalItems: $searchResult->getTotalItems(), + items: $rows + ); } diff --git a/src/Gdpr/Provider/DataProviderInterface.php b/src/Gdpr/Provider/DataProviderInterface.php index 5f866f1ad..9116df49e 100644 --- a/src/Gdpr/Provider/DataProviderInterface.php +++ b/src/Gdpr/Provider/DataProviderInterface.php @@ -17,18 +17,12 @@ use Pimcore\Bundle\StudioBackendBundle\Filter\MappedParameter\FilterParameter; use Pimcore\Bundle\StudioBackendBundle\Gdpr\Attribute\Request\SearchTerms; use Pimcore\Bundle\StudioBackendBundle\Gdpr\Schema\GdprDataColumn; -use Pimcore\Bundle\StudioBackendBundle\Gdpr\Schema\GdprDataRow; use Symfony\Component\HttpFoundation\Response; +use Pimcore\Bundle\StudioBackendBundle\Response\Collection; interface DataProviderInterface { - /** - * @return array{ - * totalSubItems: int, - * rows: GdprDataRow[] - * } - */ - public function findData(SearchTerms $terms, FilterParameter $options): array; + public function findData(SearchTerms $terms, FilterParameter $options): Collection; public function getDeleteSwaggerOperationId(): string; diff --git a/src/Gdpr/Provider/Legacy/AssetExporter.php b/src/Gdpr/Provider/Legacy/AssetExporter.php index fdcca887b..2513c8032 100644 --- a/src/Gdpr/Provider/Legacy/AssetExporter.php +++ b/src/Gdpr/Provider/Legacy/AssetExporter.php @@ -65,7 +65,7 @@ public function doExportData(Asset $asset): Response $resultItem = $this->doexportAsset($theAsset); $resultItem = json_encode($resultItem); - $zip->addFromString($asset->getFilename() . '.txt', $resultItem); + $zip->addFromString($asset->getFilename() . '.json', $resultItem); if (!$theAsset instanceof Asset\Folder) { $zip->addFromString($theAsset->getFilename(), $theAsset->getData()); diff --git a/src/Gdpr/Provider/PimcoreUserProvider.php b/src/Gdpr/Provider/PimcoreUserProvider.php index 5dca5c411..14bf4aab5 100644 --- a/src/Gdpr/Provider/PimcoreUserProvider.php +++ b/src/Gdpr/Provider/PimcoreUserProvider.php @@ -26,7 +26,7 @@ use Pimcore\Model\User\Listing; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Response; - +use Pimcore\Bundle\StudioBackendBundle\Response\Collection; /** * @internal */ @@ -42,7 +42,7 @@ public function __construct( /** * {@inheritdoc} */ - public function findData(SearchTerms $terms, FilterParameter $options): array + public function findData(SearchTerms $terms, FilterParameter $options): Collection { $listing = new Listing(); @@ -95,10 +95,10 @@ public function findData(SearchTerms $terms, FilterParameter $options): array $users ); - return [ - 'totalSubItems' => $listing->getTotalCount(), - 'rows' => $rows, - ]; + return new Collection( + totalItems: $listing->getTotalCount(), + items: $rows + ); } private function applySearchOptions(Listing $listing, FilterParameter $options): void diff --git a/src/Gdpr/Schema/GdprSearchResult.php b/src/Gdpr/Schema/GdprSearchResult.php index 35b8a3c77..26bb7b781 100644 --- a/src/Gdpr/Schema/GdprSearchResult.php +++ b/src/Gdpr/Schema/GdprSearchResult.php @@ -37,21 +37,21 @@ public function __construct( type: 'string', example: 'data_objects' )] - private readonly string $providerKey, + private string $providerKey, #[Property( description: 'The list of results found by this provider', type: 'array', items: new Items(ref: GdprDataRow::class) )] - private readonly array $results, + private array $results, #[Property( description: 'The total number of sub-items for each data providers', type: 'integer', example: 5 )] - private readonly int $totalSubItems, + private int $totalSubItems, ) { } diff --git a/src/Gdpr/Service/GdprManagerService.php b/src/Gdpr/Service/GdprManagerService.php index a1898c70c..09c994df2 100644 --- a/src/Gdpr/Service/GdprManagerService.php +++ b/src/Gdpr/Service/GdprManagerService.php @@ -74,11 +74,11 @@ public function search(GdprStructuredSearchParameters $request): GdprSearchResul $results = $provider->findData($request->getSearchTerms(), $request->getFilters()); - if (!empty($results['rows'])) { + if (!empty($results->getItems())) { $allResults[] = new GdprSearchResult( providerKey: $providerKey, - results: $results['rows'], - totalSubItems: $results['totalSubItems'] + results: $results->getItems(), + totalSubItems: $results->getTotalItems() ); } } From cf9f3fac65a9b957530304161cbaf26c0df39e59 Mon Sep 17 00:00:00 2001 From: stunnerparas <49896041+stunnerparas@users.noreply.github.com> Date: Mon, 1 Dec 2025 09:24:38 +0000 Subject: [PATCH 37/39] Apply php-cs-fixer changes --- src/Gdpr/Provider/AssetsProvider.php | 8 ++++---- src/Gdpr/Provider/DataObjectProvider.php | 2 +- src/Gdpr/Provider/DataProviderInterface.php | 2 +- src/Gdpr/Provider/PimcoreUserProvider.php | 3 ++- src/Gdpr/Service/GdprManagerService.php | 2 +- 5 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/Gdpr/Provider/AssetsProvider.php b/src/Gdpr/Provider/AssetsProvider.php index 66ada1609..11851fff4 100644 --- a/src/Gdpr/Provider/AssetsProvider.php +++ b/src/Gdpr/Provider/AssetsProvider.php @@ -23,10 +23,10 @@ use Pimcore\Bundle\StudioBackendBundle\Gdpr\Provider\Legacy\AssetExporterInterface; use Pimcore\Bundle\StudioBackendBundle\Gdpr\Schema\GdprDataColumn; use Pimcore\Bundle\StudioBackendBundle\Gdpr\Schema\GdprDataRow; +use Pimcore\Bundle\StudioBackendBundle\Response\Collection; use Pimcore\Bundle\StudioBackendBundle\Util\Constant\UserPermissions; use Pimcore\Model\Asset; use Symfony\Component\HttpFoundation\Response; -use Pimcore\Bundle\StudioBackendBundle\Response\Collection; /** * @internal @@ -85,9 +85,9 @@ public function findData(SearchTerms $terms, FilterParameter $options): Collecti ); return new Collection( - totalItems: $searchResult->getTotalItems(), - items: $rows - ); + totalItems: $searchResult->getTotalItems(), + items: $rows + ); } private function applySearchOptions(QueryInterface $query, FilterParameter $options): void diff --git a/src/Gdpr/Provider/DataObjectProvider.php b/src/Gdpr/Provider/DataObjectProvider.php index 2c0e9af6a..ef6696d0a 100644 --- a/src/Gdpr/Provider/DataObjectProvider.php +++ b/src/Gdpr/Provider/DataObjectProvider.php @@ -23,12 +23,12 @@ use Pimcore\Bundle\StudioBackendBundle\Gdpr\Provider\Legacy\ObjectExporterInterface; use Pimcore\Bundle\StudioBackendBundle\Gdpr\Schema\GdprDataColumn; use Pimcore\Bundle\StudioBackendBundle\Gdpr\Schema\GdprDataRow; +use Pimcore\Bundle\StudioBackendBundle\Response\Collection; use Pimcore\Bundle\StudioBackendBundle\Util\Constant\UserPermissions; use Pimcore\Model\DataObject; use Pimcore\Model\DataObject\Concrete; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Response; -use Pimcore\Bundle\StudioBackendBundle\Response\Collection; /** * @internal diff --git a/src/Gdpr/Provider/DataProviderInterface.php b/src/Gdpr/Provider/DataProviderInterface.php index 9116df49e..a7338549d 100644 --- a/src/Gdpr/Provider/DataProviderInterface.php +++ b/src/Gdpr/Provider/DataProviderInterface.php @@ -17,8 +17,8 @@ use Pimcore\Bundle\StudioBackendBundle\Filter\MappedParameter\FilterParameter; use Pimcore\Bundle\StudioBackendBundle\Gdpr\Attribute\Request\SearchTerms; use Pimcore\Bundle\StudioBackendBundle\Gdpr\Schema\GdprDataColumn; -use Symfony\Component\HttpFoundation\Response; use Pimcore\Bundle\StudioBackendBundle\Response\Collection; +use Symfony\Component\HttpFoundation\Response; interface DataProviderInterface { diff --git a/src/Gdpr/Provider/PimcoreUserProvider.php b/src/Gdpr/Provider/PimcoreUserProvider.php index 14bf4aab5..0d45aa106 100644 --- a/src/Gdpr/Provider/PimcoreUserProvider.php +++ b/src/Gdpr/Provider/PimcoreUserProvider.php @@ -19,6 +19,7 @@ use Pimcore\Bundle\StudioBackendBundle\Gdpr\Attribute\Request\SearchTerms; use Pimcore\Bundle\StudioBackendBundle\Gdpr\Schema\GdprDataColumn; use Pimcore\Bundle\StudioBackendBundle\Gdpr\Schema\GdprDataRow; +use Pimcore\Bundle\StudioBackendBundle\Response\Collection; use Pimcore\Bundle\StudioBackendBundle\Security\Service\SecurityServiceInterface; use Pimcore\Bundle\StudioBackendBundle\Util\Constant\UserPermissions; use Pimcore\Db; @@ -26,7 +27,7 @@ use Pimcore\Model\User\Listing; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Response; -use Pimcore\Bundle\StudioBackendBundle\Response\Collection; + /** * @internal */ diff --git a/src/Gdpr/Service/GdprManagerService.php b/src/Gdpr/Service/GdprManagerService.php index 09c994df2..f6adc8a31 100644 --- a/src/Gdpr/Service/GdprManagerService.php +++ b/src/Gdpr/Service/GdprManagerService.php @@ -77,7 +77,7 @@ public function search(GdprStructuredSearchParameters $request): GdprSearchResul if (!empty($results->getItems())) { $allResults[] = new GdprSearchResult( providerKey: $providerKey, - results: $results->getItems(), + results: $results->getItems(), totalSubItems: $results->getTotalItems() ); } From d7a499debeec2788620a0521665c7bd1aeb876ba Mon Sep 17 00:00:00 2001 From: stunnerparas Date: Mon, 1 Dec 2025 12:37:36 +0000 Subject: [PATCH 38/39] handle for both array and Response --- src/Gdpr/Provider/AssetsProvider.php | 10 ++++------ src/Gdpr/Provider/DataObjectProvider.php | 8 ++------ src/Gdpr/Provider/DataProviderInterface.php | 2 +- src/Gdpr/Provider/PimcoreUserProvider.php | 6 ++---- src/Gdpr/Service/GdprManagerService.php | 8 +++++--- 5 files changed, 14 insertions(+), 20 deletions(-) diff --git a/src/Gdpr/Provider/AssetsProvider.php b/src/Gdpr/Provider/AssetsProvider.php index 11851fff4..66484f4d7 100644 --- a/src/Gdpr/Provider/AssetsProvider.php +++ b/src/Gdpr/Provider/AssetsProvider.php @@ -117,15 +117,13 @@ public function getDeleteSwaggerOperationId(): string */ public function getSingleItemForDownload(int $id): Response { - try { - $asset = Asset::getById((int)$id); - - } catch (NotFoundException) { - throw new NotFoundException('Asset Not Found', $id); + $asset = Asset::getById((int)$id); + + if (!$asset) { + throw new NotFoundException('Asset Not Found', $id); } return $this->assetExporter->doExportData($asset); - } public function getName(): string diff --git a/src/Gdpr/Provider/DataObjectProvider.php b/src/Gdpr/Provider/DataObjectProvider.php index ef6696d0a..223648d7b 100644 --- a/src/Gdpr/Provider/DataObjectProvider.php +++ b/src/Gdpr/Provider/DataObjectProvider.php @@ -27,8 +27,6 @@ use Pimcore\Bundle\StudioBackendBundle\Util\Constant\UserPermissions; use Pimcore\Model\DataObject; use Pimcore\Model\DataObject\Concrete; -use Symfony\Component\HttpFoundation\JsonResponse; -use Symfony\Component\HttpFoundation\Response; /** * @internal @@ -118,7 +116,7 @@ public function getDeleteSwaggerOperationId(): string /** * {@inheritdoc} */ - public function getSingleItemForDownload(int $id): Response + public function getSingleItemForDownload(int $id): array { try { $object = DataObject::getById((int)$id); @@ -146,9 +144,7 @@ public function getSingleItemForDownload(int $id): Response $this->objectExporter->doExportObject($object, $export); - return new JsonResponse( - $export - ); + return $export; } public function getName(): string diff --git a/src/Gdpr/Provider/DataProviderInterface.php b/src/Gdpr/Provider/DataProviderInterface.php index a7338549d..cafa18d06 100644 --- a/src/Gdpr/Provider/DataProviderInterface.php +++ b/src/Gdpr/Provider/DataProviderInterface.php @@ -45,5 +45,5 @@ public function getRequiredPermissions(): array; /** * @throws NotFoundException */ - public function getSingleItemForDownload(int $id): Response; + public function getSingleItemForDownload(int $id): array|Response; } diff --git a/src/Gdpr/Provider/PimcoreUserProvider.php b/src/Gdpr/Provider/PimcoreUserProvider.php index 0d45aa106..bf1ee224a 100644 --- a/src/Gdpr/Provider/PimcoreUserProvider.php +++ b/src/Gdpr/Provider/PimcoreUserProvider.php @@ -25,8 +25,6 @@ use Pimcore\Db; use Pimcore\Model\User; use Pimcore\Model\User\Listing; -use Symfony\Component\HttpFoundation\JsonResponse; -use Symfony\Component\HttpFoundation\Response; /** * @internal @@ -127,7 +125,7 @@ public function getDeleteSwaggerOperationId(): string /** * {@inheritdoc} */ - public function getSingleItemForDownload(int $id): Response + public function getSingleItemForDownload(int $id): array { $user = User::getById($id); @@ -142,7 +140,7 @@ public function getSingleItemForDownload(int $id): Response $userData['versions'] = $this->getVersionDataForUser($user); $userData['usageLog'] = $this->getUsageLogDataForUser($user); - return new JsonResponse($userData); + return $userData; } protected function getVersionDataForUser(User\AbstractUser $user): array diff --git a/src/Gdpr/Service/GdprManagerService.php b/src/Gdpr/Service/GdprManagerService.php index f6adc8a31..b0119bf64 100644 --- a/src/Gdpr/Service/GdprManagerService.php +++ b/src/Gdpr/Service/GdprManagerService.php @@ -146,12 +146,14 @@ private function getSearchResultCollection(array $results): GdprSearchResultColl private function createExportResponse(mixed $data, string $providerKey, int $id): Response { - if (!$data instanceof JsonResponse) { - return $data; + // If $data is a Response (e.g., assets export), return it directly. + // Otherwise, assume $data is an array and encode it as pretty JSON for download. + if ($data instanceof Response) { + return $data; } try { - $jsonData = json_encode(json_decode($data->getContent(), true), JSON_THROW_ON_ERROR | JSON_PRETTY_PRINT); + $jsonData = json_encode($data, JSON_THROW_ON_ERROR|JSON_PRETTY_PRINT); } catch (JsonException $e) { throw new InvalidArgumentException( sprintf( From c3cdf6ee96020acd2e867c79accc6cafa72012cc Mon Sep 17 00:00:00 2001 From: stunnerparas <49896041+stunnerparas@users.noreply.github.com> Date: Mon, 1 Dec 2025 12:39:47 +0000 Subject: [PATCH 39/39] Apply php-cs-fixer changes --- src/Gdpr/Provider/AssetsProvider.php | 6 +++--- src/Gdpr/Provider/DataObjectProvider.php | 2 +- src/Gdpr/Service/GdprManagerService.php | 3 +-- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/Gdpr/Provider/AssetsProvider.php b/src/Gdpr/Provider/AssetsProvider.php index 66484f4d7..0c168db3b 100644 --- a/src/Gdpr/Provider/AssetsProvider.php +++ b/src/Gdpr/Provider/AssetsProvider.php @@ -117,10 +117,10 @@ public function getDeleteSwaggerOperationId(): string */ public function getSingleItemForDownload(int $id): Response { - $asset = Asset::getById((int)$id); - + $asset = Asset::getById((int)$id); + if (!$asset) { - throw new NotFoundException('Asset Not Found', $id); + throw new NotFoundException('Asset Not Found', $id); } return $this->assetExporter->doExportData($asset); diff --git a/src/Gdpr/Provider/DataObjectProvider.php b/src/Gdpr/Provider/DataObjectProvider.php index 223648d7b..924ac8bd6 100644 --- a/src/Gdpr/Provider/DataObjectProvider.php +++ b/src/Gdpr/Provider/DataObjectProvider.php @@ -144,7 +144,7 @@ public function getSingleItemForDownload(int $id): array $this->objectExporter->doExportObject($object, $export); - return $export; + return $export; } public function getName(): string diff --git a/src/Gdpr/Service/GdprManagerService.php b/src/Gdpr/Service/GdprManagerService.php index b0119bf64..3829dc0b2 100644 --- a/src/Gdpr/Service/GdprManagerService.php +++ b/src/Gdpr/Service/GdprManagerService.php @@ -28,7 +28,6 @@ use Pimcore\Bundle\StudioBackendBundle\Util\Constant\HttpResponseCodes; use Pimcore\Bundle\StudioBackendBundle\Util\Constant\HttpResponseHeaders; use Pimcore\Bundle\StudioBackendBundle\Util\Trait\StreamedResponseTrait; -use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\StreamedResponse; use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; @@ -149,7 +148,7 @@ private function createExportResponse(mixed $data, string $providerKey, int $id) // If $data is a Response (e.g., assets export), return it directly. // Otherwise, assume $data is an array and encode it as pretty JSON for download. if ($data instanceof Response) { - return $data; + return $data; } try {