Skip to content

Commit e6298d3

Browse files
committed
add function tests
1 parent 7ad9856 commit e6298d3

File tree

6 files changed

+239
-7
lines changed

6 files changed

+239
-7
lines changed

src/Repository/IndexQueueRepository.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -217,11 +217,10 @@ public function enqueueByItemList(array $enqueueItemList, IndexQueueOperation $o
217217
$this->connection->quote($item->getId()),
218218
$this->connection->quote($item->getElementType()),
219219
$this->connection->quote($item->getIndex()),
220-
$operation->value,
220+
$this->connection->quote($operation->value),
221221
$operationTime
222222
);
223223
}
224-
225224
$this->connection->executeQuery(
226225
sprintf($sql, IndexQueue::TABLE, implode(',', $values))
227226
);

src/Service/Search/SearchService/RequiredByElementListService.php

Lines changed: 51 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,16 @@
1616

1717
namespace Pimcore\Bundle\GenericDataIndexBundle\Service\Search\SearchService;
1818

19+
use Pimcore\Bundle\GenericDataIndexBundle\Enum\SearchIndex\FieldCategory;
20+
use Pimcore\Bundle\GenericDataIndexBundle\Enum\SearchIndex\FieldCategory\SystemField;
21+
use Pimcore\Bundle\GenericDataIndexBundle\Model\DefaultSearch\Sort\FieldSort;
22+
use Pimcore\Bundle\GenericDataIndexBundle\Model\DefaultSearch\Sort\FieldSortList;
23+
use Pimcore\Bundle\GenericDataIndexBundle\Model\Search\Element\ElementSearchInterface;
1924
use Pimcore\Bundle\GenericDataIndexBundle\Model\Search\Modifier\Filter\Dependency\RequiredByFilter;
2025
use Pimcore\Bundle\GenericDataIndexBundle\Model\SearchIndex\HitData;
26+
use Pimcore\Bundle\GenericDataIndexBundle\Model\SearchIndexAdapter\SearchResultHit;
2127
use Pimcore\Bundle\GenericDataIndexBundle\SearchIndexAdapter\DefaultSearch\Search\FetchIdsBySearchServiceInterface;
28+
use Pimcore\Bundle\GenericDataIndexBundle\SearchIndexAdapter\SearchIndexServiceInterface;
2229
use Pimcore\Bundle\GenericDataIndexBundle\Service\ElementServiceInterface;
2330
use Pimcore\Model\Element\ElementInterface;
2431

@@ -32,26 +39,67 @@ public function __construct(
3239
private FetchIdsBySearchServiceInterface $fetchIdsService,
3340
private IndexNameResolverInterface $indexNameResolver,
3441
private SearchProviderInterface $searchProvider,
42+
private SearchIndexServiceInterface $searchIndexService,
3543
private TransformToAdapterSearchServiceInterface $transformToAdapterSearchService,
3644
) {
3745
}
3846

3947
/**
4048
* @return HitData[]
4149
*/
42-
public function getDependencyList(ElementInterface $element): array
50+
public function getDependencyList(ElementInterface $element, ?ElementSearchInterface $search = null): array
4351
{
44-
$search = $this->searchProvider->createElementSearch();
52+
$sortById = false;
53+
$search = $search ?? $this->searchProvider->createElementSearch();
4554
$search->addModifier(
4655
new RequiredByFilter(
4756
$element->getId(),
4857
$this->elementService->getElementType($element)
4958
)
5059
);
60+
$adapterSearch = $this->transformToAdapterSearchService->transform($search);
61+
if ($adapterSearch->getSortList()->isEmpty()) {
62+
$sortById = true;
63+
}
5164

5265
return $this->fetchIdsService->fetchAllTypesAndIds(
53-
$this->transformToAdapterSearchService->transform($search),
66+
$adapterSearch,
67+
$this->indexNameResolver->resolveIndexName($search),
68+
$sortById
69+
);
70+
}
71+
72+
/**
73+
* @return HitData[]
74+
*/
75+
public function getDependencyListForCurrentPage(
76+
ElementInterface $element,
77+
ElementSearchInterface $search
78+
): array
79+
{
80+
$search->addModifier(
81+
new RequiredByFilter(
82+
$element->getId(),
83+
$this->elementService->getElementType($element)
84+
)
85+
);
86+
87+
$adapterSearch = $this->transformToAdapterSearchService->transform($search);
88+
$adapterSearch = clone $adapterSearch;
89+
$adapterSearch->setSource([SystemField::ELEMENT_TYPE->getPath()]);
90+
$searchResult = $this->searchIndexService->search(
91+
$adapterSearch,
5492
$this->indexNameResolver->resolveIndexName($search)
5593
);
94+
95+
return array_map(
96+
static fn (SearchResultHit $item) =>
97+
new HitData(
98+
id: $item->getId(),
99+
elementType: $item->getSource()[FieldCategory::SYSTEM_FIELDS->value][SystemField::ELEMENT_TYPE->value],
100+
index: $item->getIndex(),
101+
),
102+
$searchResult->getHits()
103+
);
56104
}
57105
}

src/Service/Search/SearchService/RequiredByElementListServiceInterface.php

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
namespace Pimcore\Bundle\GenericDataIndexBundle\Service\Search\SearchService;
1818

19+
use Pimcore\Bundle\GenericDataIndexBundle\Model\Search\Element\ElementSearchInterface;
1920
use Pimcore\Bundle\GenericDataIndexBundle\Model\SearchIndex\HitData;
2021
use Pimcore\Model\Element\ElementInterface;
2122

@@ -26,5 +27,13 @@ interface RequiredByElementListServiceInterface
2627
*
2728
* @return HitData[]
2829
*/
29-
public function getDependencyList(ElementInterface $element): array;
30+
public function getDependencyList(ElementInterface $element, ?ElementSearchInterface $search = null): array;
31+
32+
/**
33+
* @return HitData[]
34+
*/
35+
public function getDependencyListForCurrentPage(
36+
ElementInterface $element,
37+
ElementSearchInterface $search
38+
): array;
3039
}

src/Service/SearchIndex/IndexQueueService.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ private function handleQueueByOperation(
156156
if ($operation === IndexQueueOperation::DELETE->value) {
157157
$this->enqueueService->enqueueDependentItems(
158158
element: $element,
159-
operation: IndexQueueOperation::DELETE
159+
operation: IndexQueueOperation::UPDATE
160160
);
161161
}
162162
}
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
<?php
2+
3+
/**
4+
* Pimcore
5+
*
6+
* This source file is available under two different licenses:
7+
* - GNU General Public License version 3 (GPLv3)
8+
* - Pimcore Commercial License (PCL)
9+
* Full copyright and license information is available in
10+
* LICENSE.md which is distributed with this source code.
11+
*
12+
* @copyright Copyright (c) Pimcore GmbH (http://www.pimcore.org)
13+
* @license http://www.pimcore.org/license GPLv3 and PCL
14+
*/
15+
16+
namespace Pimcore\Bundle\GenericDataIndexBundle\Tests\Functional\Search\SearchService;
17+
18+
use Codeception\Test\Unit;
19+
use Pimcore\Bundle\GenericDataIndexBundle\Enum\Search\SortDirection;
20+
use Pimcore\Bundle\GenericDataIndexBundle\Model\Search\Element\ElementSearch;
21+
use Pimcore\Bundle\GenericDataIndexBundle\Model\Search\Modifier\Sort\Tree\OrderByFullPath;
22+
use Pimcore\Bundle\GenericDataIndexBundle\Model\SearchIndex\HitData;
23+
use Pimcore\Bundle\GenericDataIndexBundle\Service\Search\SearchService\RequiredByElementListServiceInterface;
24+
use Pimcore\Bundle\GenericDataIndexBundle\Service\Search\SearchService\SearchProviderInterface;
25+
use Pimcore\Bundle\GenericDataIndexBundle\Tests\IndexTester;
26+
use Pimcore\Model\Asset;
27+
use Pimcore\Model\DataObject\Concrete;
28+
use Pimcore\Tests\Support\Util\TestHelper;
29+
30+
final class RequiredByElementListServiceTest extends Unit
31+
{
32+
protected IndexTester $tester;
33+
34+
protected function _before()
35+
{
36+
$this->tester->enableSynchronousProcessing();
37+
}
38+
39+
protected function _after()
40+
{
41+
TestHelper::cleanUp();
42+
$this->tester->flushIndex();
43+
$this->tester->cleanupIndex();
44+
$this->tester->flushIndex();
45+
}
46+
47+
48+
49+
public function testSearchDependencyList(): void
50+
{
51+
$asset = TestHelper::createImageAsset()->setKey('asset1')->save();
52+
$object1 = $this->createDependencyObject('object1', $asset);
53+
$object2 = $this->createDependencyObject('object2', $asset);
54+
$object3 = $this->createDependencyObject('object3', $asset);
55+
56+
/** @var RequiredByElementListServiceInterface $dependencyService */
57+
$dependencyService = $this->tester->grabService(RequiredByElementListServiceInterface::class);
58+
59+
$dependencyList = $dependencyService->getDependencyList($asset);
60+
$this->assertIdArrayEquals(
61+
[$object1->getId(), $object2->getId(), $object3->getId()],
62+
$this->getDependencyIds($dependencyList)
63+
);
64+
65+
/** @var SearchProviderInterface $searchProvider */
66+
$searchProvider = $this->tester->grabService(SearchProviderInterface::class);
67+
$elementSearch = $searchProvider->createElementSearch();
68+
69+
$dependencyList = $dependencyService->getDependencyListForCurrentPage(
70+
$asset,
71+
($elementSearch)
72+
->addModifier(new OrderByFullPath(SortDirection::DESC))
73+
->setPage(1)
74+
->setPageSize(2)
75+
);
76+
$this->assertEquals(
77+
[$object3->getId(), $object2->getId()],
78+
$this->getDependencyIds($dependencyList)
79+
);
80+
81+
$dependencyList = $dependencyService->getDependencyList(
82+
$asset,
83+
($elementSearch)
84+
->addModifier(new OrderByFullPath(SortDirection::DESC))
85+
->setPage(1)
86+
->setPageSize(2)
87+
);
88+
$this->assertEquals(
89+
[$object3->getId(), $object2->getId(), $object1->getId()],
90+
$this->getDependencyIds($dependencyList)
91+
);
92+
}
93+
94+
private function createDependencyObject(string $key, Asset $asset): Concrete
95+
{
96+
return TestHelper::createEmptyObject()
97+
->setKey($key)
98+
->setImage($asset)
99+
->save();
100+
}
101+
102+
private function getDependencyIds(array $dependencyList): array
103+
{
104+
return array_map(fn(HitData $hit) => $hit->getId(), $dependencyList);
105+
}
106+
107+
private function assertIdArrayEquals(array $ids1, array $ids2): void
108+
{
109+
sort($ids1);
110+
sort($ids2);
111+
$this->assertEquals($ids1, $ids2);
112+
}
113+
}

tests/Functional/SearchIndex/IndexQueueTest.php

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,13 @@
1818
use Codeception\Test\Unit;
1919
use Exception;
2020
use Pimcore\Bundle\GenericDataIndexBundle\Enum\SearchIndex\ElementType;
21+
use Pimcore\Bundle\GenericDataIndexBundle\Enum\SearchIndex\FieldCategory;
2122
use Pimcore\Bundle\GenericDataIndexBundle\Enum\SearchIndex\IndexName;
2223
use Pimcore\Bundle\GenericDataIndexBundle\Enum\SearchIndex\IndexQueueOperation;
24+
use Pimcore\Bundle\GenericDataIndexBundle\Model\Search\DataObject\DataObjectSearchInterface;
2325
use Pimcore\Bundle\GenericDataIndexBundle\Repository\IndexQueueRepository;
26+
use Pimcore\Bundle\GenericDataIndexBundle\Service\Search\SearchService\DataObject\DataObjectSearchServiceInterface;
27+
use Pimcore\Bundle\GenericDataIndexBundle\Service\Search\SearchService\SearchProviderInterface;
2428
use Pimcore\Bundle\GenericDataIndexBundle\Service\SearchIndex\SearchIndexConfigServiceInterface;
2529
use Pimcore\Bundle\GenericDataIndexBundle\Tests\IndexTester;
2630
use Pimcore\Db;
@@ -37,6 +41,8 @@ class IndexQueueTest extends Unit
3741

3842
private const DOCUMENT_INDEX_NAME = 'document';
3943

44+
private const IMAGE_KEY = 'image';
45+
4046
protected function _before()
4147
{
4248
$this->searchIndexConfigService = $this->tester->grabService(
@@ -177,6 +183,40 @@ public function testDataObjectDeleteWithQueue(): void
177183
$this->tester->checkDeletedIndexEntry($object->getId(), $objectIndex);
178184
}
179185

186+
/**
187+
* @throws Exception
188+
*/
189+
public function testDependenciesWithQueue(): void
190+
{
191+
/** @var DataObjectSearchServiceInterface $searchService */
192+
$searchService = $this->tester->grabService('generic-data-index.test.service.data-object-search-service');
193+
/** @var SearchProviderInterface $searchProvider */
194+
$searchProvider = $this->tester->grabService(SearchProviderInterface::class);
195+
$dataObjectSearch = $searchProvider->createDataObjectSearch();
196+
197+
$asset = TestHelper::createImageAsset();
198+
$object = TestHelper::createEmptyObject();
199+
$object->setImage($asset);
200+
$object->save();
201+
202+
$assetIndex = $this->searchIndexConfigService->getIndexName(self::ASSET_INDEX_NAME);
203+
$objectIndex = $this->searchIndexConfigService->getIndexName($object->getClassName(), true);
204+
205+
$this->checkQueueEntry($asset->getId(), ElementType::ASSET->value);
206+
$this->checkQueueEntry($object->getId(), ElementType::DATA_OBJECT->value);
207+
$this->consume();
208+
209+
$this->tester->checkIndexEntry($object->getId(), $objectIndex);
210+
$this->assertNotNull($this->getImageValueFromIndex($searchService, $dataObjectSearch));
211+
$this->checkAndDeleteElement($asset, $assetIndex);
212+
213+
// asset is deleted, so the object should be updated as it has a dependency to asset
214+
$this->checkQueueEntry($object->getId(), ElementType::DATA_OBJECT->value);
215+
$this->consume();
216+
217+
$this->assertNull($this->getImageValueFromIndex($searchService, $dataObjectSearch));
218+
}
219+
180220
private function checkAndDeleteElement(ElementInterface $element, string $indexName): void
181221
{
182222
$this->tester->checkIndexEntry($element->getId(), $indexName);
@@ -187,4 +227,27 @@ private function consume(): void
187227
{
188228
$this->tester->runCommand('messenger:consume', ['--limit'=>2], ['pimcore_generic_data_index_queue']);
189229
}
230+
231+
private function checkQueueEntry(string $elementId, string $elementType): void
232+
{
233+
$this->assertGreaterThan(
234+
0,
235+
Db::get()->fetchOne(
236+
'select count(elementId) from generic_data_index_queue where elementId = ? and elementType=?',
237+
[$elementId, $elementType]
238+
)
239+
);
240+
}
241+
242+
private function getImageValueFromIndex(
243+
DataObjectSearchServiceInterface $searchService,
244+
DataObjectSearchInterface $dataObjectSearch
245+
): ?array
246+
{
247+
$searchResult = $searchService->search($dataObjectSearch);
248+
$this->assertCount(1, $searchResult->getItems());
249+
$data = $searchResult->getItems()[0]->getSearchIndexData();
250+
251+
return $data[FieldCategory::STANDARD_FIELDS->value][self::IMAGE_KEY];
252+
}
190253
}

0 commit comments

Comments
 (0)