Skip to content

Commit 9af1ce3

Browse files
Merge branch '2025.4' into 2026.1
2 parents 91ee7ef + 46cb923 commit 9af1ce3

16 files changed

Lines changed: 594 additions & 9 deletions

config/search.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ services:
3333
Pimcore\Bundle\StudioBackendBundle\Search\Hydrator\DetailedConfigurationHydratorInterface:
3434
class: Pimcore\Bundle\StudioBackendBundle\Search\Hydrator\DetailedConfigurationHydrator
3535

36+
Pimcore\Bundle\StudioBackendBundle\Search\Hydrator\ListItemHydratorInterface:
37+
class: Pimcore\Bundle\StudioBackendBundle\Search\Hydrator\ListItemHydrator
38+
3639
#
3740
# Repositories
3841
#

doc/03_Extending/02_Additional_and_Custom_Attributes.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,7 @@ For more details and frontend customization options, see the
239239
- `pre_response.quantity_value.unit_list`
240240
- `pre_response.recycle_bin.item`
241241
- `pre_response.role_tree_node`
242+
- `pre_response.saved_search_configuration_list_item`
242243
- `pre_response.saved_search_configuration`
243244
- `pre_response.saved_search_detailed_configuration`
244245
- `pre_response.schedule`

src/Search/Attribute/Request/SavedSearchRequestBody.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ public function __construct()
5757
),
5858
),
5959
new Property(
60-
property: 'filters',
60+
property: 'filter',
6161
ref: Filter::class,
6262
type: 'object',
6363
nullable: true,
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
<?php
2+
declare(strict_types=1);
3+
4+
/**
5+
* This source file is available under the terms of the
6+
* Pimcore Open Core License (POCL)
7+
* Full copyright and license information is available in
8+
* LICENSE.md which is distributed with this source code.
9+
*
10+
* @copyright Copyright (c) Pimcore GmbH (https://www.pimcore.com)
11+
* @license Pimcore Open Core License (POCL)
12+
*/
13+
14+
namespace Pimcore\Bundle\StudioBackendBundle\Search\Controller\SavedSearch;
15+
16+
use OpenApi\Attributes\Delete;
17+
use Pimcore\Bundle\StudioBackendBundle\Controller\AbstractApiController;
18+
use Pimcore\Bundle\StudioBackendBundle\Exception\Api\ForbiddenException;
19+
use Pimcore\Bundle\StudioBackendBundle\Exception\Api\NotFoundException;
20+
use Pimcore\Bundle\StudioBackendBundle\OpenApi\Attribute\Parameter\Path\IdParameter;
21+
use Pimcore\Bundle\StudioBackendBundle\OpenApi\Attribute\Response\DefaultResponses;
22+
use Pimcore\Bundle\StudioBackendBundle\OpenApi\Attribute\Response\SuccessResponse;
23+
use Pimcore\Bundle\StudioBackendBundle\OpenApi\Config\Tags;
24+
use Pimcore\Bundle\StudioBackendBundle\Search\Service\SavedSearchConfigurationServiceInterface;
25+
use Pimcore\Bundle\StudioBackendBundle\Util\Constant\HttpResponseCodes;
26+
use Pimcore\Bundle\StudioBackendBundle\Util\Constant\UserPermissions;
27+
use Symfony\Component\HttpFoundation\Response;
28+
use Symfony\Component\Routing\Attribute\Route;
29+
use Symfony\Component\Security\Http\Attribute\IsGranted;
30+
use Symfony\Component\Serializer\SerializerInterface;
31+
32+
/**
33+
* @internal
34+
*/
35+
final class DeleteConfigurationController extends AbstractApiController
36+
{
37+
private const string ROUTE = '/search/saved/configuration/delete/{id}';
38+
39+
public function __construct(
40+
SerializerInterface $serializer,
41+
private readonly SavedSearchConfigurationServiceInterface $saveConfigurationService,
42+
) {
43+
parent::__construct($serializer);
44+
}
45+
46+
/**
47+
* @throws ForbiddenException
48+
* @throws NotFoundException
49+
*/
50+
#[Route(
51+
self::ROUTE,
52+
name: 'pimcore_studio_api_delete_saved_search_configuration',
53+
methods: ['DELETE'],
54+
)]
55+
#[IsGranted(UserPermissions::PIMCORE_USER->value)]
56+
#[Delete(
57+
path: self::PREFIX . self::ROUTE,
58+
operationId: 'saved_search_delete_configuration',
59+
description: 'saved_search_delete_configuration_description',
60+
summary: 'saved_search_delete_configuration_summary',
61+
tags: [Tags::Search->value]
62+
)]
63+
#[IdParameter(type: 'saved search configuration')]
64+
#[SuccessResponse(
65+
description: 'saved_search_delete_configuration_success_response',
66+
)]
67+
#[DefaultResponses([
68+
HttpResponseCodes::FORBIDDEN,
69+
HttpResponseCodes::UNAUTHORIZED,
70+
HttpResponseCodes::NOT_FOUND,
71+
])]
72+
public function deleteConfiguration(
73+
int $id
74+
): Response {
75+
$this->saveConfigurationService->deleteConfiguration($id);
76+
77+
return new Response();
78+
}
79+
}
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
<?php
2+
declare(strict_types=1);
3+
4+
/**
5+
* This source file is available under the terms of the
6+
* Pimcore Open Core License (POCL)
7+
* Full copyright and license information is available in
8+
* LICENSE.md which is distributed with this source code.
9+
*
10+
* @copyright Copyright (c) Pimcore GmbH (https://www.pimcore.com)
11+
* @license Pimcore Open Core License (POCL)
12+
*/
13+
14+
namespace Pimcore\Bundle\StudioBackendBundle\Search\Controller\SavedSearch;
15+
16+
use OpenApi\Attributes\Get;
17+
use Pimcore\Bundle\StudioBackendBundle\Controller\AbstractApiController;
18+
use Pimcore\Bundle\StudioBackendBundle\MappedParameter\CollectionParameters;
19+
use Pimcore\Bundle\StudioBackendBundle\OpenApi\Attribute\Parameter\Query\PageParameter;
20+
use Pimcore\Bundle\StudioBackendBundle\OpenApi\Attribute\Parameter\Query\PageSizeParameter;
21+
use Pimcore\Bundle\StudioBackendBundle\OpenApi\Attribute\Parameter\Query\TextFieldParameter;
22+
use Pimcore\Bundle\StudioBackendBundle\OpenApi\Attribute\Property\GenericCollection;
23+
use Pimcore\Bundle\StudioBackendBundle\OpenApi\Attribute\Response\Content\CollectionJson;
24+
use Pimcore\Bundle\StudioBackendBundle\OpenApi\Attribute\Response\DefaultResponses;
25+
use Pimcore\Bundle\StudioBackendBundle\OpenApi\Attribute\Response\SuccessResponse;
26+
use Pimcore\Bundle\StudioBackendBundle\OpenApi\Config\Tags;
27+
use Pimcore\Bundle\StudioBackendBundle\Search\Schema\ConfigurationListItem;
28+
use Pimcore\Bundle\StudioBackendBundle\Search\Service\SavedSearchConfigurationServiceInterface;
29+
use Pimcore\Bundle\StudioBackendBundle\Util\Constant\HttpResponseCodes;
30+
use Pimcore\Bundle\StudioBackendBundle\Util\Constant\UserPermissions;
31+
use Pimcore\Bundle\StudioBackendBundle\Util\Trait\PaginatedResponseTrait;
32+
use Symfony\Component\HttpFoundation\JsonResponse;
33+
use Symfony\Component\HttpKernel\Attribute\MapQueryParameter;
34+
use Symfony\Component\HttpKernel\Attribute\MapQueryString;
35+
use Symfony\Component\Routing\Attribute\Route;
36+
use Symfony\Component\Security\Http\Attribute\IsGranted;
37+
use Symfony\Component\Serializer\SerializerInterface;
38+
39+
/**
40+
* @internal
41+
*/
42+
final class ListConfigurationsController extends AbstractApiController
43+
{
44+
use PaginatedResponseTrait;
45+
46+
private const string ROUTE = '/search/saved/configuration';
47+
48+
public function __construct(
49+
SerializerInterface $serializer,
50+
private readonly SavedSearchConfigurationServiceInterface $savedSearchConfigurationService,
51+
) {
52+
parent::__construct($serializer);
53+
}
54+
55+
#[Route(
56+
self::ROUTE,
57+
name: 'pimcore_studio_api_get_saved_search_configurations',
58+
methods: ['GET'],
59+
)]
60+
#[IsGranted(UserPermissions::PIMCORE_USER->value)]
61+
#[Get(
62+
path: self::PREFIX . self::ROUTE,
63+
operationId: 'saved_search_get_configurations',
64+
description: 'saved_search_get_configurations_description',
65+
summary: 'saved_search_get_configurations_summary',
66+
tags: [Tags::Search->value]
67+
)]
68+
#[PageParameter]
69+
#[PageSizeParameter]
70+
#[TextFieldParameter(
71+
name: 'searchTerm',
72+
description: 'Optional term to filter the saved search configurations by name.',
73+
required: false
74+
)]
75+
#[SuccessResponse(
76+
description: 'saved_search_get_configurations_success_response',
77+
content: new CollectionJson(new GenericCollection(ConfigurationListItem::class))
78+
)]
79+
#[DefaultResponses([
80+
HttpResponseCodes::UNAUTHORIZED,
81+
])]
82+
public function getSavedSearchConfigurations(
83+
#[MapQueryParameter] ?string $searchTerm = null,
84+
#[MapQueryString] CollectionParameters $parameters = new CollectionParameters(),
85+
): JsonResponse {
86+
$collection = $this->savedSearchConfigurationService->listConfigurations(
87+
$parameters,
88+
$searchTerm
89+
);
90+
91+
return $this->getPaginatedCollection(
92+
$this->serializer,
93+
$collection->getItems(),
94+
$collection->getTotalItems()
95+
);
96+
}
97+
}
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
<?php
2+
declare(strict_types=1);
3+
4+
/**
5+
* This source file is available under the terms of the
6+
* Pimcore Open Core License (POCL)
7+
* Full copyright and license information is available in
8+
* LICENSE.md which is distributed with this source code.
9+
*
10+
* @copyright Copyright (c) Pimcore GmbH (https://www.pimcore.com)
11+
* @license Pimcore Open Core License (POCL)
12+
*/
13+
14+
namespace Pimcore\Bundle\StudioBackendBundle\Search\Controller\SavedSearch;
15+
16+
use OpenApi\Attributes\Put;
17+
use Pimcore\Bundle\StudioBackendBundle\Controller\AbstractApiController;
18+
use Pimcore\Bundle\StudioBackendBundle\Exception\Api\ForbiddenException;
19+
use Pimcore\Bundle\StudioBackendBundle\Exception\Api\NotFoundException;
20+
use Pimcore\Bundle\StudioBackendBundle\OpenApi\Attribute\Parameter\Path\IdParameter;
21+
use Pimcore\Bundle\StudioBackendBundle\OpenApi\Attribute\Response\DefaultResponses;
22+
use Pimcore\Bundle\StudioBackendBundle\OpenApi\Attribute\Response\SuccessResponse;
23+
use Pimcore\Bundle\StudioBackendBundle\OpenApi\Config\Tags;
24+
use Pimcore\Bundle\StudioBackendBundle\Search\Attribute\Request\SavedSearchRequestBody;
25+
use Pimcore\Bundle\StudioBackendBundle\Search\MappedParameter\SavedSearchParameter;
26+
use Pimcore\Bundle\StudioBackendBundle\Search\Service\SavedSearchConfigurationServiceInterface;
27+
use Pimcore\Bundle\StudioBackendBundle\Util\Constant\HttpResponseCodes;
28+
use Pimcore\Bundle\StudioBackendBundle\Util\Constant\UserPermissions;
29+
use Symfony\Component\HttpFoundation\Response;
30+
use Symfony\Component\HttpKernel\Attribute\MapRequestPayload;
31+
use Symfony\Component\Routing\Attribute\Route;
32+
use Symfony\Component\Security\Http\Attribute\IsGranted;
33+
use Symfony\Component\Serializer\SerializerInterface;
34+
35+
/**
36+
* @internal
37+
*/
38+
final class UpdateConfigurationController extends AbstractApiController
39+
{
40+
private const string ROUTE = '/search/saved/configuration/update/{id}';
41+
42+
public function __construct(
43+
SerializerInterface $serializer,
44+
private readonly SavedSearchConfigurationServiceInterface $saveConfigurationService,
45+
) {
46+
parent::__construct($serializer);
47+
}
48+
49+
/**
50+
* @throws ForbiddenException
51+
* @throws NotFoundException
52+
*/
53+
#[Route(
54+
self::ROUTE,
55+
name: 'pimcore_studio_api_update_saved_search_configuration',
56+
methods: ['PUT'],
57+
)]
58+
#[IsGranted(UserPermissions::PIMCORE_USER->value)]
59+
#[Put(
60+
path: self::PREFIX . self::ROUTE,
61+
operationId: 'saved_search_update_configuration',
62+
description: 'saved_search_update_configuration_description',
63+
summary: 'saved_search_update_configuration_summary',
64+
tags: [Tags::Search->value]
65+
)]
66+
#[SavedSearchRequestBody]
67+
#[IdParameter(type: 'saved search configuration')]
68+
#[SuccessResponse(
69+
description: 'saved_search_update_configuration_success_response',
70+
)]
71+
#[DefaultResponses([
72+
HttpResponseCodes::FORBIDDEN,
73+
HttpResponseCodes::UNAUTHORIZED,
74+
HttpResponseCodes::NOT_FOUND,
75+
])]
76+
public function updateConfiguration(
77+
#[MapRequestPayload] SavedSearchParameter $parameter,
78+
int $id
79+
): Response {
80+
$this->saveConfigurationService->updateConfiguration($parameter, $id);
81+
82+
return new Response();
83+
}
84+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?php
2+
declare(strict_types=1);
3+
4+
/**
5+
* This source file is available under the terms of the
6+
* Pimcore Open Core License (POCL)
7+
* Full copyright and license information is available in
8+
* LICENSE.md which is distributed with this source code.
9+
*
10+
* @copyright Copyright (c) Pimcore GmbH (https://www.pimcore.com)
11+
* @license Pimcore Open Core License (POCL)
12+
*/
13+
14+
namespace Pimcore\Bundle\StudioBackendBundle\Search\Event\PreResponse;
15+
16+
use Pimcore\Bundle\StudioBackendBundle\Event\AbstractPreResponseEvent;
17+
use Pimcore\Bundle\StudioBackendBundle\Search\Schema\ConfigurationListItem;
18+
19+
final class SavedSearchConfigurationListItemEvent extends AbstractPreResponseEvent
20+
{
21+
public const string EVENT_NAME = 'pre_response.saved_search_configuration_list_item';
22+
23+
public function __construct(
24+
private readonly ConfigurationListItem $configuration
25+
) {
26+
parent::__construct($configuration);
27+
}
28+
29+
public function getConfiguration(): ConfigurationListItem
30+
{
31+
return $this->configuration;
32+
}
33+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?php
2+
declare(strict_types=1);
3+
4+
/**
5+
* This source file is available under the terms of the
6+
* Pimcore Open Core License (POCL)
7+
* Full copyright and license information is available in
8+
* LICENSE.md which is distributed with this source code.
9+
*
10+
* @copyright Copyright (c) Pimcore GmbH (https://www.pimcore.com)
11+
* @license Pimcore Open Core License (POCL)
12+
*/
13+
14+
namespace Pimcore\Bundle\StudioBackendBundle\Search\Hydrator;
15+
16+
use Pimcore\Bundle\StudioBackendBundle\Entity\Search\SavedSearchConfiguration;
17+
use Pimcore\Bundle\StudioBackendBundle\Search\Schema\ConfigurationListItem;
18+
19+
/**
20+
* @internal
21+
*/
22+
final readonly class ListItemHydrator implements ListItemHydratorInterface
23+
{
24+
public function hydrate(SavedSearchConfiguration $data, bool $owner): ConfigurationListItem
25+
{
26+
return new ConfigurationListItem(
27+
id: $data->getId(),
28+
name: $data->getName(),
29+
description: $data->getDescription(),
30+
owner: $owner,
31+
modificationDate: $data->getModificationDate()->getTimestamp(),
32+
creationDate: $data->getCreationDate()->getTimestamp(),
33+
);
34+
}
35+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
declare(strict_types=1);
3+
4+
/**
5+
* This source file is available under the terms of the
6+
* Pimcore Open Core License (POCL)
7+
* Full copyright and license information is available in
8+
* LICENSE.md which is distributed with this source code.
9+
*
10+
* @copyright Copyright (c) Pimcore GmbH (https://www.pimcore.com)
11+
* @license Pimcore Open Core License (POCL)
12+
*/
13+
14+
namespace Pimcore\Bundle\StudioBackendBundle\Search\Hydrator;
15+
16+
use Pimcore\Bundle\StudioBackendBundle\Entity\Search\SavedSearchConfiguration;
17+
use Pimcore\Bundle\StudioBackendBundle\Search\Schema\ConfigurationListItem;
18+
19+
/**
20+
* @internal
21+
*/
22+
interface ListItemHydratorInterface
23+
{
24+
public function hydrate(SavedSearchConfiguration $data, bool $owner): ConfigurationListItem;
25+
}

0 commit comments

Comments
 (0)