Completed
Push — master ( 0b53cc...a259cb )
by
unknown
26:05
created

SearchViewTest::wrapIn()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 13
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

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