Completed
Push — master ( a259cb...23b0fa )
by
unknown
20:01
created

SearchViewTest::xmlProvider()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 50
Code Lines 29

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 29
nc 1
nop 0
dl 0
loc 50
rs 9.3333
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * File containing the Functional\SearchViewTest class.
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
namespace eZ\Bundle\EzPublishRestBundle\Tests\Functional;
10
11
use DOMDocument;
12
use DOMElement;
13
use eZ\Bundle\EzPublishRestBundle\Tests\Functional\TestCase as RESTFunctionalTestCase;
14
use eZ\Publish\API\Repository\Values\Content\Query\Criterion\Operator;
15
16
class SearchViewTest extends RESTFunctionalTestCase
17
{
18
    /**
19
     * @var string
20
     */
21
    protected $contentTypeHref;
22
23
    /**
24
     * @var string[]
25
     */
26
    protected $contentHrefList;
27
28
    protected function setUp()
29
    {
30
        parent::setUp();
31
        $this->contentTypeHref = $this->createTestContentType();
32
        $this->contentHrefList[] = $this->createTestContentWithTags('test-name', ['foo', 'bar']);
33
        $this->contentHrefList[] = $this->createTestContentWithTags('fancy-name', ['baz', 'foobaz']);
34
        $this->contentHrefList[] = $this->createTestContentWithTags('even-fancier', ['bar', 'bazfoo']);
35
    }
36
37
    protected function tearDown()
38
    {
39
        parent::tearDown();
40
        array_map([$this, 'deleteContent'], $this->contentHrefList);
41
        $this->deleteContent($this->contentTypeHref);
42
    }
43
44
    /**
45
     * @dataProvider xmlProvider
46
     * Covers POST with ContentQuery Logic on /api/ezp/v2/views.
47
     */
48
    public function testSimpleContentQuery(string $xmlQueryBody, int $expectedCount)
49
    {
50
        $request = $this->createHttpRequest('POST', '/api/ezp/v2/views', 'ViewInput+xml; version=1.1', 'ContentInfo+json');
51
        $body = <<< XML
52
<?xml version="1.0" encoding="UTF-8"?>
53
<ViewInput>
54
<identifier>your-query-id</identifier>
55
<public>false</public>
56
<ContentQuery>
57
  <Query>
58
    $xmlQueryBody
59
  </Query>  
60
  <limit>10</limit>  
61
  <offset>0</offset> 
62
</ContentQuery>
63
</ViewInput>
64
XML;
65
66
        $request->setContent($body);
67
68
        $response = $this->sendHttpRequest($request);
69
        self::assertHttpResponseCodeEquals($response, 200);
70
        $jsonResponse = json_decode($response->getContent());
71
        self::assertEquals($expectedCount, $jsonResponse->View->Result->count);
72
    }
73
74 View Code Duplication
    private function createTestContentType(): string
75
    {
76
        $body = <<< XML
77
<?xml version="1.0" encoding="UTF-8"?>
78
<ContentTypeCreate>
79
  <identifier>tags-test</identifier>
80
  <names>
81
    <value languageCode="eng-GB">testContentQueryWithTags</value>
82
  </names>
83
  <remoteId>testContentQueryWithTags</remoteId>
84
  <urlAliasSchema>&lt;title&gt;</urlAliasSchema>
85
  <nameSchema>&lt;title&gt;</nameSchema>
86
  <isContainer>true</isContainer>
87
  <mainLanguageCode>eng-GB</mainLanguageCode>
88
  <defaultAlwaysAvailable>true</defaultAlwaysAvailable>
89
  <defaultSortField>PATH</defaultSortField>
90
  <defaultSortOrder>ASC</defaultSortOrder>
91
  <FieldDefinitions>
92
    <FieldDefinition>
93
      <identifier>title</identifier>
94
      <fieldType>ezstring</fieldType>
95
      <fieldGroup>content</fieldGroup>
96
      <position>1</position>
97
      <isTranslatable>true</isTranslatable>
98
      <isRequired>true</isRequired>
99
      <isInfoCollector>false</isInfoCollector>
100
      <defaultValue>New Title</defaultValue>
101
      <isSearchable>true</isSearchable>
102
      <names>
103
        <value languageCode="eng-GB">Title</value>
104
      </names>
105
      <descriptions>
106
        <value languageCode="eng-GB">This is the title</value>
107
      </descriptions>
108
    </FieldDefinition>
109
    <FieldDefinition>
110
      <identifier>tags</identifier>
111
      <fieldType>ezkeyword</fieldType>
112
      <fieldGroup>content</fieldGroup>
113
      <position>2</position>
114
      <isTranslatable>true</isTranslatable>
115
      <isRequired>true</isRequired>
116
      <isInfoCollector>false</isInfoCollector>
117
      <isSearchable>true</isSearchable>
118
      <names>
119
        <value languageCode="eng-GB">Tags</value>
120
      </names>
121
      <descriptions>
122
        <value languageCode="eng-GB">Those are searchable tags</value>
123
      </descriptions>
124
    </FieldDefinition>
125
   </FieldDefinitions>
126
</ContentTypeCreate>
127
XML;
128
129
        $request = $this->createHttpRequest(
130
            'POST',
131
            '/api/ezp/v2/content/typegroups/1/types?publish=true',
132
            'ContentTypeCreate+xml',
133
            'ContentType+json'
134
        );
135
        $request->setContent($body);
136
        $response = $this->sendHttpRequest($request);
137
138
        return $response->getHeader('Location');
139
    }
140
141 View Code Duplication
    private function createTestContentWithTags(string $name, array $tags): string
142
    {
143
        $request = $this->createHttpRequest('POST', '/api/ezp/v2/content/objects', 'ContentCreate+xml', 'ContentInfo+json');
144
        $tagsString = implode(',', $tags);
145
        $body = <<< XML
146
<?xml version="1.0" encoding="UTF-8"?>
147
<ContentCreate>
148
  <ContentType href="$this->contentTypeHref" />
149
  <mainLanguageCode>eng-GB</mainLanguageCode>
150
  <LocationCreate>
151
    <ParentLocation href="/api/ezp/v2/content/locations/1" />
152
    <priority>0</priority>
153
    <hidden>false</hidden>
154
    <sortField>PATH</sortField>
155
    <sortOrder>ASC</sortOrder>
156
  </LocationCreate>
157
  <Section href="/api/ezp/v2/content/sections/1" />
158
  <alwaysAvailable>true</alwaysAvailable>
159
  <remoteId>$name</remoteId>
160
  <User href="/api/ezp/v2/user/users/14" />
161
  <modificationDate>2018-01-30T18:30:00</modificationDate>
162
  <fields>
163
    <field>
164
      <fieldDefinitionIdentifier>title</fieldDefinitionIdentifier>
165
      <languageCode>eng-GB</languageCode>
166
      <fieldValue>$name</fieldValue>
167
    </field>
168
    <field>
169
      <fieldDefinitionIdentifier>tags</fieldDefinitionIdentifier>
170
      <languageCode>eng-GB</languageCode>
171
      <fieldValue>$tagsString</fieldValue>
172
    </field>
173
    </fields>
174
</ContentCreate>
175
XML;
176
        $request->setContent($body);
177
178
        $response = $this->sendHttpRequest($request);
179
        $href = $response->getHeader('Location');
180
        $this->sendHttpRequest(
181
            $this->createHttpRequest('PUBLISH', "$href/versions/1")
182
        );
183
184
        return $href;
185
    }
186
187
    private function deleteContent($href)
188
    {
189
        $this->sendHttpRequest(
190
            $this->createHttpRequest('DELETE', $href)
191
        );
192
    }
193
194
    public function xmlProvider()
195
    {
196
        $fooTag = $this->buildFieldXml('tags', Operator::CONTAINS, 'foo');
197
        $barTag = $this->buildFieldXml('tags', Operator::CONTAINS, 'bar');
198
        $bazTag = $this->buildFieldXml('tags', Operator::CONTAINS, 'baz');
199
        $foobazTag = $this->buildFieldXml('tags', Operator::CONTAINS, 'foobaz');
200
        $foobazInTag = $this->buildFieldXml('tags', Operator::IN, ['foobaz']);
201
        $bazfooInTag = $this->buildFieldXml('tags', Operator::IN, ['bazfoo']);
202
        $fooAndBarInTag = $this->buildFieldXml('tags', Operator::IN, ['foo', 'bar']);
203
204
        return [
205
            [
206
                $this->getXmlString(
207
                    $this->wrapIn('AND', [$fooTag, $barTag])
208
                ),
209
                1,
210
            ],
211
            [
212
                $this->getXmlString(
213
                    $this->wrapIn('OR', [
214
                        $this->wrapIn('AND', [$fooTag, $barTag]),
215
                        $this->wrapIn('AND', [$bazTag, $foobazTag]),
216
                    ])
217
                ),
218
                2,
219
            ],
220
            [
221
                $this->getXmlString(
222
                    $this->wrapIn('AND', [
223
                        $this->wrapIn('NOT', [$fooTag]),
224
                        $barTag,
225
                    ])
226
                ),
227
                1,
228
            ],
229
            [
230
                $this->getXmlString(
231
                    $this->wrapIn('OR', [
232
                        $foobazInTag,
233
                        $bazfooInTag,
234
                    ])
235
                ),
236
                2,
237
            ],
238
            [
239
                $this->getXmlString($fooAndBarInTag),
240
                2,
241
            ],
242
        ];
243
    }
244
245
    /**
246
     * @param string $name
247
     * @param string $operator
248
     * @param string|string[] $value
249
     * @return DOMElement
250
     */
251
    private function buildFieldXml(string $name, string $operator, $value): DOMElement
252
    {
253
        $xml = new DOMDocument();
254
        $element = $xml->createElement('Field');
255
        $element->appendChild(new DOMElement('name', $name));
256
        $element->appendChild(new DOMElement('operator', $operator));
257
258
        //Force xml array with one value
259
        if (is_array($value)) {
260
            if (count($value) === 1) {
261
                $valueWrapper = $xml->createElement('value');
262
                $valueWrapper->appendChild(new DOMElement('value', $value[0]));
263
                $element->appendChild($valueWrapper);
264
            } else {
265
                foreach ($value as $key => $singleValue) {
266
                    $element->appendChild(new DOMElement('value', $singleValue));
267
                }
268
            }
269
        } else {
270
            $element->appendChild(new DOMElement('value', $value));
271
        }
272
273
        return $element;
274
    }
275
276
    private function wrapIn(string $logicalOperator, array $toWrap): DOMElement
277
    {
278
        $xml = new DOMDocument();
279
        $wrapper = $xml->createElement($logicalOperator);
280
281
        foreach ($toWrap as $key => $field) {
282
            $innerWrapper = $xml->createElement($logicalOperator);
283
            $innerWrapper->appendChild($xml->importNode($field, true));
284
            $wrapper->appendChild($innerWrapper);
285
        }
286
287
        return $wrapper;
288
    }
289
290
    private function getXmlString(DOMElement $simpleXMLElement): string
291
    {
292
        return $simpleXMLElement->ownerDocument->saveXML($simpleXMLElement);
293
    }
294
}
295