Skip to content
2 changes: 2 additions & 0 deletions config/pimcore/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,8 @@ pimcore_generic_data_index:
sort:
type: keyword
normalizer: generic_data_index_sort_normalizer
classDefinitionIcon:
type: keyword
asset:
mimetype:
type: keyword
Expand Down
5 changes: 5 additions & 0 deletions config/services/search-index-adapter/open-search.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -72,3 +72,8 @@ services:
Pimcore\Bundle\GenericDataIndexBundle\SearchIndexAdapter\OpenSearch\QueryLanguage\FieldNameValidator\:
resource: '../../../src/SearchIndexAdapter/OpenSearch/QueryLanguage/FieldNameValidator'
tags: ['pimcore.generic_data_index.pql_field_name_validator']

Pimcore\Bundle\GenericDataIndexBundle\SearchIndexAdapter\DataObject\IndexIconUpdateServiceInterface:
class: Pimcore\Bundle\GenericDataIndexBundle\SearchIndexAdapter\OpenSearch\DataObject\IndexIconUpdateService
arguments:
$openSearchClient: '@generic-data-index.opensearch-client'
1 change: 1 addition & 0 deletions src/Enum/SearchIndex/FieldCategory/SystemField.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ enum SystemField: string
case PARENT_TAGS = 'parentTags';
case MIME_TYPE = 'mimetype';
case CLASS_NAME = 'className';
case CLASS_DEFINITION_ICON = 'classDefinitionIcon';
case CHECKSUM = 'checksum';
case USER_OWNER = 'userOwner';
case USER_MODIFICATION = 'userModification';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ class DataObjectSearchResultItem implements ElementSearchResultItemInterface

private string $className;

private ?string $classDefinitionIcon;

private bool $workflowWithPermissions;

private bool $hasChildren;
Expand Down Expand Up @@ -234,6 +236,18 @@ public function setClassName(string $className): DataObjectSearchResultItem
return $this;
}

public function getClassDefinitionIcon(): ?string
{
return $this->classDefinitionIcon;
}

public function setClassDefinitionIcon(?string $classDefinitionIcon): DataObjectSearchResultItem
{
$this->classDefinitionIcon = $classDefinitionIcon;

return $this;
}

public function isHasWorkflowWithPermissions(): bool
{
if (!isset($this->workflowWithPermissions)) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php
declare(strict_types=1);

/**
* Pimcore
*
* This source file is available under two different licenses:
* - GNU General Public License version 3 (GPLv3)
* - Pimcore Commercial License (PCL)
* Full copyright and license information is available in
* LICENSE.md which is distributed with this source code.
*
* @copyright Copyright (c) Pimcore GmbH (http://www.pimcore.org)
* @license http://www.pimcore.org/license GPLv3 and PCL
*/

namespace Pimcore\Bundle\GenericDataIndexBundle\SearchIndexAdapter\DataObject;

/**
* @internal
*/
interface IndexIconUpdateServiceInterface
{
public function updateIcon(string $indexName, string $icon): void;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
<?php
declare(strict_types=1);

/**
* Pimcore
*
* This source file is available under two different licenses:
* - GNU General Public License version 3 (GPLv3)
* - Pimcore Commercial License (PCL)
* Full copyright and license information is available in
* LICENSE.md which is distributed with this source code.
*
* @copyright Copyright (c) Pimcore GmbH (http://www.pimcore.org)
* @license http://www.pimcore.org/license GPLv3 and PCL
*/

namespace Pimcore\Bundle\GenericDataIndexBundle\SearchIndexAdapter\OpenSearch\DataObject;

use OpenSearch\Client;
use Pimcore\Bundle\GenericDataIndexBundle\Enum\SearchIndex\FieldCategory\SystemField;
use Pimcore\Bundle\GenericDataIndexBundle\SearchIndexAdapter\DataObject\IndexIconUpdateServiceInterface;

/**
* @internal

*/
final readonly class IndexIconUpdateService implements IndexIconUpdateServiceInterface
{
public function __construct(private Client $openSearchClient)
{
}

public function updateIcon(string $indexName, ?string $icon): void
{
$query = $icon === null ? $this->getQueryForNullIcon() : $this->getQueryForIconString($icon);

$params = [
'index' => $indexName,
'refresh' => true,
'body' => [
'script' => [
'source' => 'ctx._source.system_fields.classDefinitionIcon = params.icon',
'lang' => 'painless',
'params' => [
'icon' => $icon,
],
],
'query' => $query,
],
];
$this->openSearchClient->updateByQuery($params);
}

private function getQueryForNullIcon(): array
{
return [
'bool' => [
'filter' => [
'exists' => ['field' => SystemField::CLASS_DEFINITION_ICON->getPath()],
],
],
];
}

private function getQueryForIconString(string $icon): array
{
return [
'bool' => [
'should' => [
[
'bool' => [
'must_not' => [
'exists' => ['field' => SystemField::CLASS_DEFINITION_ICON->getPath()],
],
],
],
[
'bool' => [
'must_not' => [
'term' => [SystemField::CLASS_DEFINITION_ICON->getPath() => $icon],
],
],
],
],
'minimum_should_match' => 1,
],
];
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

use Exception;
use Pimcore\Bundle\GenericDataIndexBundle\Exception\ClassDefinitionIndexUpdateFailedException;
use Pimcore\Bundle\GenericDataIndexBundle\SearchIndexAdapter\DataObject\IndexIconUpdateServiceInterface;
use Pimcore\Bundle\GenericDataIndexBundle\Service\SearchIndex\IndexQueue\EnqueueServiceInterface;
use Pimcore\Bundle\GenericDataIndexBundle\Service\SearchIndex\IndexService\IndexHandler\DataObjectIndexHandler;
use Pimcore\Bundle\GenericDataIndexBundle\Service\SettingsStoreServiceInterface;
Expand All @@ -32,6 +33,7 @@ public function __construct(
private DataObjectIndexHandler $dataObjectIndexHandler,
private EnqueueServiceInterface $enqueueService,
private SettingsStoreServiceInterface $settingsStoreService,
private IndexIconUpdateServiceInterface $indexIconUpdateService,
) {
}

Expand All @@ -41,13 +43,14 @@ public function reindexClassDefinition(
bool $enqueueItems = false,
): bool {
try {
$changed = $this->reindexMapping($classDefinition, $skipIfClassNotChanged);
$mappingChanged = $this->reindexMapping($classDefinition, $skipIfClassNotChanged);
$this->changeIcon($classDefinition);

if ($changed && $enqueueItems) {
if ($mappingChanged && $enqueueItems) {
$this->enqueueService->enqueueByClassDefinition($classDefinition);
}

return $changed;
return $mappingChanged;
} catch (Exception $exception) {
throw new ClassDefinitionIndexUpdateFailedException(
message: $exception->getMessage(),
Expand All @@ -56,6 +59,14 @@ public function reindexClassDefinition(
}
}

private function changeIcon(ClassDefinition $classDefinition): void
{
$this->indexIconUpdateService->updateIcon(
$this->dataObjectIndexHandler->getCurrentFullIndexName($classDefinition),
$classDefinition->getIcon() ?: null
);
}

/**
* @throws Exception
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ public function denormalize(
$searchResultItem
->setId(SystemField::ID->getData($data))
->setClassName(SystemField::CLASS_NAME->getData($data) ?? '')
->setClassDefinitionIcon(SystemField::CLASS_DEFINITION_ICON->getData($data))
->setParentId(SystemField::PARENT_ID->getData($data))
->setType(SystemField::TYPE->getData($data))
->setPublished($published)
Expand Down
4 changes: 4 additions & 0 deletions src/Service/Serializer/Normalizer/DataObjectNormalizer.php
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,9 @@ private function normalizeDataObject(Concrete $dataObject, bool $skipLazyLoadedF
];
}

/**
* @throws Exception
*/
private function normalizeSystemFields(AbstractObject $dataObject, bool $skipLazyLoadedFields): array
{
$pathLevels = $this->extractPathLevels($dataObject);
Expand All @@ -115,6 +118,7 @@ private function normalizeSystemFields(AbstractObject $dataObject, bool $skipLaz
if ($dataObject instanceof Concrete) {
$result = array_merge($result, [
SystemField::CLASS_NAME->value => $dataObject->getClassName(),
SystemField::CLASS_DEFINITION_ICON->value => $dataObject->getClass()->getIcon() ?: null,
SystemField::PUBLISHED->value => $dataObject->getPublished(),
]);
}
Expand Down
25 changes: 25 additions & 0 deletions tests/Functional/SearchIndex/DataObjectBasicTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,31 @@ public function testClassDefinitionMapping(): void
$this->assertArrayNotHasKey('mappingTest', $standardFields);
}

public function testClassDefinitionIconChange(): void
{
$object = TestHelper::createEmptyObject();

$this->classDefinitionIconChangeTest($object, '/my-icon.svg');
$this->classDefinitionIconChangeTest($object, '/my-new-icon.svg');
$this->classDefinitionIconChangeTest($object, null);
$this->classDefinitionIconChangeTest($object, '/my-final-icon.svg');
}

private function classDefinitionIconChangeTest(Concrete $object, ?string $newIcon): void
{
$class = $object->getClass();
$class->setIcon($newIcon);
$class->save();

$this->tester->runCommand('messenger:consume', ['--limit'=>1], ['pimcore_generic_data_index_queue']);

$indexName = $this->tester->getIndexName($object->getClassName());
$response = $this->tester->checkIndexEntry($object->getId(), $indexName);
$updatedIcon = $response['_source']['system_fields']['classDefinitionIcon'];

$this->assertEquals($newIcon, $updatedIcon);
}

private function assertIdArrayEquals(array $ids1, array $ids2)
{
sort($ids1);
Expand Down