Completed
Push — master ( ff5799...da1600 )
by André
38:04 queued 20:34
created

SearchEngineIndexingTest   C

Complexity

Total Complexity 11

Size/Duplication

Total Lines 309
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 23

Importance

Changes 2
Bugs 1 Features 0
Metric Value
c 2
b 1
f 0
dl 0
loc 309
rs 5.5
wmc 11
lcom 1
cbo 23

8 Methods

Rating   Name   Duplication   Size   Complexity  
B testCreateLocation() 0 26 1
A testMoveSubtree() 0 60 1
A testIndexContentWithNullField() 0 52 1
B testUpdateLocation() 0 33 1
B testDeleteLocation() 0 31 1
B createDeletionTestContentType() 0 31 2
A createContentWithName() 0 20 2
A assertContentIdSearch() 0 18 2
1
<?php
2
3
/**
4
 * This file is part of the eZ Publish Kernel package.
5
 *
6
 * @copyright Copyright (C) eZ Systems AS. All rights reserved.
7
 * @license For full copyright and license information view LICENSE file distributed with this source code.
8
 *
9
 * @version //autogentag//
10
 */
11
namespace eZ\Publish\API\Repository\Tests;
12
13
use eZ\Publish\API\Repository\Exceptions\NotFoundException;
14
use eZ\Publish\API\Repository\Values\Content\LocationQuery;
15
use eZ\Publish\API\Repository\Values\Content\Query;
16
use eZ\Publish\API\Repository\Values\Content\Query\Criterion;
17
use DateTime;
18
19
/**
20
 * Test case for indexing operations with a search engine.
21
 *
22
 * @group integration
23
 * @group search
24
 * @group indexing
25
 */
26
class SearchEngineIndexingTest extends BaseTest
27
{
28
    public function testCreateLocation()
29
    {
30
        $repository = $this->getRepository();
31
        $locationService = $repository->getLocationService();
32
        $contentService = $repository->getContentService();
33
        $searchService = $repository->getSearchService();
34
35
        $rootLocationId = 2;
36
        $membersContentId = 11;
37
        $membersContentInfo = $contentService->loadContentInfo($membersContentId);
38
39
        $locationCreateStruct = $locationService->newLocationCreateStruct($rootLocationId);
40
        $membersLocation = $locationService->createLocation($membersContentInfo, $locationCreateStruct);
41
42
        $this->refreshSearch($repository);
43
44
        // Found
45
        $criterion = new Criterion\LocationId($membersLocation->id);
46
        $query = new LocationQuery(array('filter' => $criterion));
47
        $result = $searchService->findLocations($query);
48
        $this->assertEquals(1, $result->totalCount);
49
        $this->assertEquals(
50
            $membersLocation->id,
51
            $result->searchHits[0]->valueObject->id
0 ignored issues
show
Documentation introduced by
The property id does not exist on object<eZ\Publish\API\Re...ory\Values\ValueObject>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
52
        );
53
    }
54
55
    public function testMoveSubtree()
56
    {
57
        $repository = $this->getRepository();
58
        $locationService = $repository->getLocationService();
59
        $contentService = $repository->getContentService();
60
        $searchService = $repository->getSearchService();
61
62
        $rootLocationId = 2;
63
        $membersContentId = 11;
64
        $adminsContentId = 12;
65
        $editorsContentId = 13;
66
        $membersContentInfo = $contentService->loadContentInfo($membersContentId);
67
        $adminsContentInfo = $contentService->loadContentInfo($adminsContentId);
68
        $editorsContentInfo = $contentService->loadContentInfo($editorsContentId);
69
70
        $locationCreateStruct = $locationService->newLocationCreateStruct($rootLocationId);
71
        $membersLocation = $locationService->createLocation($membersContentInfo, $locationCreateStruct);
72
        $editorsLocation = $locationService->createLocation($editorsContentInfo, $locationCreateStruct);
73
        $adminsLocation = $locationService->createLocation(
74
            $adminsContentInfo,
75
            $locationService->newLocationCreateStruct($membersLocation->id)
76
        );
77
78
        $this->refreshSearch($repository);
79
80
        // Not found under Editors
81
        $criterion = new Criterion\ParentLocationId($editorsLocation->id);
82
        $query = new LocationQuery(array('filter' => $criterion));
83
        $result = $searchService->findLocations($query);
84
        $this->assertEquals(0, $result->totalCount);
85
86
        // Found under Members
87
        $criterion = new Criterion\ParentLocationId($membersLocation->id);
88
        $query = new LocationQuery(array('filter' => $criterion));
89
        $result = $searchService->findLocations($query);
90
        $this->assertEquals(1, $result->totalCount);
91
        $this->assertEquals(
92
            $adminsLocation->id,
93
            $result->searchHits[0]->valueObject->id
0 ignored issues
show
Documentation introduced by
The property id does not exist on object<eZ\Publish\API\Re...ory\Values\ValueObject>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
94
        );
95
96
        $locationService->moveSubtree($adminsLocation, $editorsLocation);
97
        $this->refreshSearch($repository);
98
99
        // Found under Editors
100
        $criterion = new Criterion\ParentLocationId($editorsLocation->id);
101
        $query = new LocationQuery(array('filter' => $criterion));
102
        $result = $searchService->findLocations($query);
103
        $this->assertEquals(1, $result->totalCount);
104
        $this->assertEquals(
105
            $adminsLocation->id,
106
            $result->searchHits[0]->valueObject->id
0 ignored issues
show
Documentation introduced by
The property id does not exist on object<eZ\Publish\API\Re...ory\Values\ValueObject>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
107
        );
108
109
        // Not found under Members
110
        $criterion = new Criterion\ParentLocationId($membersLocation->id);
111
        $query = new LocationQuery(array('filter' => $criterion));
112
        $result = $searchService->findLocations($query);
113
        $this->assertEquals(0, $result->totalCount);
114
    }
115
116
    /**
117
     * Testing that content is indexed even when containing only fields with values
118
     * considered to be empty by the search engine.
119
     */
120
    public function testIndexContentWithNullField()
121
    {
122
        $repository = $this->getRepository();
123
        $contentService = $repository->getContentService();
124
        $contentTypeService = $repository->getContentTypeService();
125
        $searchService = $repository->getSearchService();
126
127
        $createStruct = $contentTypeService->newContentTypeCreateStruct('test-type');
128
        $createStruct->mainLanguageCode = 'eng-GB';
129
        $createStruct->names = array('eng-GB' => 'Test type');
130
        $createStruct->creatorId = 14;
131
        $createStruct->creationDate = new DateTime();
132
133
        $translatableFieldCreate = $contentTypeService->newFieldDefinitionCreateStruct(
134
            'integer',
135
            'ezinteger'
136
        );
137
        $translatableFieldCreate->names = array('eng-GB' => 'Simple translatable integer field');
138
        $translatableFieldCreate->fieldGroup = 'main';
139
        $translatableFieldCreate->position = 1;
140
        $translatableFieldCreate->isTranslatable = true;
141
        $translatableFieldCreate->isSearchable = true;
142
143
        $createStruct->addFieldDefinition($translatableFieldCreate);
144
145
        $contentGroup = $contentTypeService->loadContentTypeGroupByIdentifier('Content');
146
        $contentTypeDraft = $contentTypeService->createContentType(
147
            $createStruct,
148
            array($contentGroup)
149
        );
150
        $contentTypeService->publishContentTypeDraft($contentTypeDraft);
151
        $contentType = $contentTypeService->loadContentType($contentTypeDraft->id);
0 ignored issues
show
Documentation introduced by
The property $id is declared protected in eZ\Publish\API\Repositor...ContentType\ContentType. Since you implemented __get(), maybe consider adding a @property or @property-read annotation. This makes it easier for IDEs to provide auto-completion.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
152
153
        $createStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
154
        $createStruct->alwaysAvailable = false;
155
        $createStruct->mainLanguageCode = 'eng-GB';
156
157
        $draft = $contentService->createContent($createStruct);
158
        $content = $contentService->publishVersion($draft->getVersionInfo());
159
160
        $this->refreshSearch($repository);
161
162
        // Found
163
        $criterion = new Criterion\ContentId($content->id);
164
        $query = new Query(array('filter' => $criterion));
165
        $result = $searchService->findContent($query);
166
        $this->assertEquals(1, $result->totalCount);
167
        $this->assertEquals(
168
            $content->id,
169
            $result->searchHits[0]->valueObject->id
0 ignored issues
show
Documentation introduced by
The property id does not exist on object<eZ\Publish\API\Re...ory\Values\ValueObject>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
170
        );
171
    }
172
173
    public function testUpdateLocation()
174
    {
175
        $repository = $this->getRepository();
176
        $locationService = $repository->getLocationService();
177
        $searchService = $repository->getSearchService();
178
179
        $rootLocationId = 2;
180
        $locationToUpdate = $locationService->loadLocation($rootLocationId);
181
182
        $criterion = new Criterion\LogicalAnd([
183
            new Criterion\LocationId($rootLocationId),
184
            new Criterion\Location\Priority(Criterion\Operator::GT, 0),
185
        ]);
186
187
        $query = new LocationQuery(array('filter' => $criterion));
188
        $result = $searchService->findLocations($query);
189
190
        $this->assertEquals(0, $result->totalCount);
191
192
        $locationUpdateStruct = $locationService->newLocationUpdateStruct();
193
        $locationUpdateStruct->priority = 4;
194
        $locationService->updateLocation($locationToUpdate, $locationUpdateStruct);
195
196
        $this->refreshSearch($repository);
197
198
        $result = $searchService->findLocations($query);
199
200
        $this->assertEquals(1, $result->totalCount);
201
        $this->assertEquals(
202
            $locationToUpdate->id,
203
            $result->searchHits[0]->valueObject->id
0 ignored issues
show
Documentation introduced by
The property id does not exist on object<eZ\Publish\API\Re...ory\Values\ValueObject>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
204
        );
205
    }
206
207
    /**
208
     * Testing that content will be deleted with all of its subitems but subitems with additional location will stay as
209
     * they are.
210
     */
211
    public function testDeleteLocation()
212
    {
213
        $repository = $this->getRepository();
214
        $locationService = $repository->getLocationService();
215
216
        $treeContainerContent = $this->createContentWithName('Tree Container', [2]);
217
        $supposeBeDeletedSubItem = $this->createContentWithName(
218
            'Suppose to be deleted sub-item',
219
            [$treeContainerContent->contentInfo->mainLocationId]
220
        );
221
        $supposeSurviveSubItem = $this->createContentWithName(
222
            'Suppose to Survive Item',
223
            [2, $treeContainerContent->contentInfo->mainLocationId]
224
        );
225
226
        $treeContainerLocation = $locationService->loadLocation($treeContainerContent->contentInfo->mainLocationId);
227
228
        $this->refreshSearch($repository);
229
230
        $this->assertContentIdSearch($treeContainerContent->id, 1);
231
        $this->assertContentIdSearch($supposeSurviveSubItem->id, 1);
232
        $this->assertContentIdSearch($supposeBeDeletedSubItem->id, 1);
233
234
        $locationService->deleteLocation($treeContainerLocation);
235
236
        $this->refreshSearch($repository);
237
238
        $this->assertContentIdSearch($supposeSurviveSubItem->id, 1);
239
        $this->assertContentIdSearch($treeContainerContent->id, 0);
240
        $this->assertContentIdSearch($supposeBeDeletedSubItem->id, 0);
241
    }
242
243
    /**
244
     * Will create if not exists an simple content type for deletion test purpose with just and required field name.
245
     *
246
     * @return \eZ\Publish\API\Repository\Values\ContentType\ContentType
247
     */
248
    protected function createDeletionTestContentType()
249
    {
250
        $repository = $this->getRepository();
251
        $contentTypeService = $repository->getContentTypeService();
252
        try {
253
            return $contentTypeService->loadContentTypeByIdentifier('deletion-test');
254
        } catch (NotFoundException $e) {
255
            // continue creation process
256
        }
257
258
        $nameField = $contentTypeService->newFieldDefinitionCreateStruct('name', 'ezstring');
259
        $nameField->fieldGroup = 'main';
260
        $nameField->position = 1;
261
        $nameField->isTranslatable = true;
262
        $nameField->isSearchable = true;
263
        $nameField->isRequired = true;
264
265
        $contentTypeStruct = $contentTypeService->newContentTypeCreateStruct('deletion-test');
266
        $contentTypeStruct->mainLanguageCode = 'eng-GB';
267
        $contentTypeStruct->creatorId = 14;
268
        $contentTypeStruct->creationDate = new DateTime();
269
        $contentTypeStruct->names = ['eng-GB' => 'Deletion test'];
270
        $contentTypeStruct->addFieldDefinition($nameField);
271
272
        $contentTypeGroup = $contentTypeService->loadContentTypeGroupByIdentifier('Content');
273
274
        $contentTypeDraft = $contentTypeService->createContentType($contentTypeStruct, [$contentTypeGroup]);
275
        $contentTypeService->publishContentTypeDraft($contentTypeDraft);
276
277
        return $contentTypeService->loadContentTypeByIdentifier('deletion-test');
278
    }
279
280
    /**
281
     * Will create and publish an content with a filed with a given content name in location provided into
282
     * $parentLocationIdList.
283
     *
284
     * @param string $contentName
285
     * @param array $parentLocationIdList
286
     *
287
     * @return \eZ\Publish\API\Repository\Values\Content\Content
288
     */
289
    protected function createContentWithName($contentName, array $parentLocationIdList = array())
290
    {
291
        $contentService = $this->getRepository()->getContentService();
292
        $locationService = $this->getRepository()->getLocationService();
293
294
        $testableContentType = $this->createDeletionTestContentType();
295
296
        $rootContentStruct = $contentService->newContentCreateStruct($testableContentType, 'eng-GB');
297
        $rootContentStruct->setField('name', $contentName);
298
299
        $parentLocationList = [];
300
        foreach ($parentLocationIdList as $locationID) {
301
            $parentLocationList[] = $locationService->newLocationCreateStruct($locationID);
302
        }
303
304
        $contentDraft = $contentService->createContent($rootContentStruct, $parentLocationList);
305
        $publishedContent = $contentService->publishVersion($contentDraft->getVersionInfo());
306
307
        return $publishedContent;
308
    }
309
310
    /**
311
     * Asserts an content id if it exists still in the solr core.
312
     *
313
     * @param int $contentId
314
     * @param int $expectedCount
315
     */
316
    protected function assertContentIdSearch($contentId, $expectedCount)
317
    {
318
        $searchService = $this->getRepository()->getSearchService();
319
320
        $criterion = new Criterion\ContentId($contentId);
321
        $query = new Query(array('filter' => $criterion));
322
        $result = $searchService->findContent($query);
323
324
        $this->assertEquals($expectedCount, $result->totalCount);
325
        if ($expectedCount == 0) {
326
            return;
327
        }
328
329
        $this->assertEquals(
330
            $contentId,
331
            $result->searchHits[0]->valueObject->id
0 ignored issues
show
Documentation introduced by
The property id does not exist on object<eZ\Publish\API\Re...ory\Values\ValueObject>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
332
        );
333
    }
334
}
335