1<?php
2
3namespace Sabre\Xml;
4
5class WriterTest extends \PHPUnit_Framework_TestCase {
6
7    protected $writer;
8
9    function setUp() {
10
11        $this->writer = new Writer();
12        $this->writer->namespaceMap = [
13            'http://sabredav.org/ns' => 's',
14        ];
15        $this->writer->openMemory();
16        $this->writer->setIndent(true);
17        $this->writer->startDocument();
18
19    }
20
21    function compare($input, $output) {
22
23        $this->writer->write($input);
24        $this->assertEquals($output, $this->writer->outputMemory());
25
26    }
27
28
29    function testSimple() {
30
31        $this->compare([
32            '{http://sabredav.org/ns}root' => 'text',
33        ], <<<HI
34<?xml version="1.0"?>
35<s:root xmlns:s="http://sabredav.org/ns">text</s:root>
36
37HI
38        );
39
40    }
41
42    /**
43     * @depends testSimple
44     */
45    function testSimpleQuotes() {
46
47        $this->compare([
48            '{http://sabredav.org/ns}root' => '"text"',
49        ], <<<HI
50<?xml version="1.0"?>
51<s:root xmlns:s="http://sabredav.org/ns">&quot;text&quot;</s:root>
52
53HI
54        );
55
56    }
57
58    function testSimpleAttributes() {
59
60        $this->compare([
61            '{http://sabredav.org/ns}root' => [
62                'value'      => 'text',
63                'attributes' => [
64                    'attr1' => 'attribute value',
65                ],
66            ],
67        ], <<<HI
68<?xml version="1.0"?>
69<s:root xmlns:s="http://sabredav.org/ns" attr1="attribute value">text</s:root>
70
71HI
72        );
73
74    }
75    function testMixedSyntax() {
76        $this->compare([
77            '{http://sabredav.org/ns}root' => [
78                '{http://sabredav.org/ns}single'   => 'value',
79                '{http://sabredav.org/ns}multiple' => [
80                    [
81                        'name'  => '{http://sabredav.org/ns}foo',
82                        'value' => 'bar',
83                    ],
84                    [
85                        'name'  => '{http://sabredav.org/ns}foo',
86                        'value' => 'foobar',
87                    ],
88                ],
89                [
90                    'name'       => '{http://sabredav.org/ns}attributes',
91                    'value'      => null,
92                    'attributes' => [
93                        'foo' => 'bar',
94                    ],
95                ],
96                [
97                    'name'       => '{http://sabredav.org/ns}verbose',
98                    'value'      => 'syntax',
99                    'attributes' => [
100                        'foo' => 'bar',
101                    ],
102                ],
103            ],
104        ], <<<HI
105<?xml version="1.0"?>
106<s:root xmlns:s="http://sabredav.org/ns">
107 <s:single>value</s:single>
108 <s:multiple>
109  <s:foo>bar</s:foo>
110  <s:foo>foobar</s:foo>
111 </s:multiple>
112 <s:attributes foo="bar"/>
113 <s:verbose foo="bar">syntax</s:verbose>
114</s:root>
115
116HI
117        );
118    }
119
120    function testNull() {
121
122        $this->compare([
123            '{http://sabredav.org/ns}root' => null,
124        ], <<<HI
125<?xml version="1.0"?>
126<s:root xmlns:s="http://sabredav.org/ns"/>
127
128HI
129        );
130
131    }
132
133    function testArrayFormat2() {
134
135        $this->compare([
136            '{http://sabredav.org/ns}root' => [
137                [
138                    'name'       => '{http://sabredav.org/ns}elem1',
139                    'value'      => 'text',
140                    'attributes' => [
141                        'attr1' => 'attribute value',
142                    ],
143                ],
144            ],
145        ], <<<HI
146<?xml version="1.0"?>
147<s:root xmlns:s="http://sabredav.org/ns">
148 <s:elem1 attr1="attribute value">text</s:elem1>
149</s:root>
150
151HI
152        );
153
154    }
155
156    function testArrayOfValues() {
157
158        $this->compare([
159            '{http://sabredav.org/ns}root' => [
160                [
161                    'name'  => '{http://sabredav.org/ns}elem1',
162                    'value' => [
163                        'foo',
164                        'bar',
165                        'baz',
166                    ],
167                ],
168            ],
169        ], <<<HI
170<?xml version="1.0"?>
171<s:root xmlns:s="http://sabredav.org/ns">
172 <s:elem1>foobarbaz</s:elem1>
173</s:root>
174
175HI
176        );
177
178    }
179
180    /**
181     * @depends testArrayFormat2
182     */
183    function testArrayFormat2NoValue() {
184
185        $this->compare([
186            '{http://sabredav.org/ns}root' => [
187                [
188                    'name'       => '{http://sabredav.org/ns}elem1',
189                    'attributes' => [
190                        'attr1' => 'attribute value',
191                    ],
192                ],
193            ],
194        ], <<<HI
195<?xml version="1.0"?>
196<s:root xmlns:s="http://sabredav.org/ns">
197 <s:elem1 attr1="attribute value"/>
198</s:root>
199
200HI
201        );
202
203    }
204
205    function testCustomNamespace() {
206
207        $this->compare([
208            '{http://sabredav.org/ns}root' => [
209                '{urn:foo}elem1' => 'bar',
210            ],
211        ], <<<HI
212<?xml version="1.0"?>
213<s:root xmlns:s="http://sabredav.org/ns">
214 <x1:elem1 xmlns:x1="urn:foo">bar</x1:elem1>
215</s:root>
216
217HI
218        );
219
220    }
221
222    function testEmptyNamespace() {
223
224        // Empty namespaces are allowed, so we should support this.
225        $this->compare([
226            '{http://sabredav.org/ns}root' => [
227                '{}elem1' => 'bar',
228            ],
229        ], <<<HI
230<?xml version="1.0"?>
231<s:root xmlns:s="http://sabredav.org/ns">
232 <elem1 xmlns="">bar</elem1>
233</s:root>
234
235HI
236        );
237
238    }
239
240    function testAttributes() {
241
242        $this->compare([
243            '{http://sabredav.org/ns}root' => [
244                [
245                    'name'       => '{http://sabredav.org/ns}elem1',
246                    'value'      => 'text',
247                    'attributes' => [
248                        'attr1'                         => 'val1',
249                        '{http://sabredav.org/ns}attr2' => 'val2',
250                        '{urn:foo}attr3'                => 'val3',
251                    ],
252                ],
253            ],
254        ], <<<HI
255<?xml version="1.0"?>
256<s:root xmlns:s="http://sabredav.org/ns">
257 <s:elem1 attr1="val1" s:attr2="val2" x1:attr3="val3" xmlns:x1="urn:foo">text</s:elem1>
258</s:root>
259
260HI
261        );
262
263    }
264
265    function testBaseElement() {
266
267        $this->compare([
268            '{http://sabredav.org/ns}root' => new Element\Base('hello')
269        ], <<<HI
270<?xml version="1.0"?>
271<s:root xmlns:s="http://sabredav.org/ns">hello</s:root>
272
273HI
274        );
275
276    }
277
278    function testElementObj() {
279
280        $this->compare([
281            '{http://sabredav.org/ns}root' => new Element\Mock()
282        ], <<<HI
283<?xml version="1.0"?>
284<s:root xmlns:s="http://sabredav.org/ns">
285 <s:elem1>hiiii!</s:elem1>
286</s:root>
287
288HI
289        );
290
291    }
292
293    function testEmptyNamespacePrefix() {
294
295        $this->writer->namespaceMap['http://sabredav.org/ns'] = null;
296        $this->compare([
297            '{http://sabredav.org/ns}root' => new Element\Mock()
298        ], <<<HI
299<?xml version="1.0"?>
300<root xmlns="http://sabredav.org/ns">
301 <elem1>hiiii!</elem1>
302</root>
303
304HI
305        );
306
307    }
308
309    function testEmptyNamespacePrefixEmptyString() {
310
311        $this->writer->namespaceMap['http://sabredav.org/ns'] = '';
312        $this->compare([
313            '{http://sabredav.org/ns}root' => new Element\Mock()
314        ], <<<HI
315<?xml version="1.0"?>
316<root xmlns="http://sabredav.org/ns">
317 <elem1>hiiii!</elem1>
318</root>
319
320HI
321        );
322
323    }
324
325    function testWriteElement() {
326
327        $this->writer->writeElement("{http://sabredav.org/ns}foo", 'content');
328
329        $output = <<<HI
330<?xml version="1.0"?>
331<s:foo xmlns:s="http://sabredav.org/ns">content</s:foo>
332
333HI;
334
335        $this->assertEquals($output, $this->writer->outputMemory());
336
337
338    }
339
340    function testWriteElementComplex() {
341
342        $this->writer->writeElement("{http://sabredav.org/ns}foo", new Element\KeyValue(['{http://sabredav.org/ns}bar' => 'test']));
343
344        $output = <<<HI
345<?xml version="1.0"?>
346<s:foo xmlns:s="http://sabredav.org/ns">
347 <s:bar>test</s:bar>
348</s:foo>
349
350HI;
351
352        $this->assertEquals($output, $this->writer->outputMemory());
353
354    }
355
356    /**
357     * @expectedException \InvalidArgumentException
358     */
359    function testWriteBadObject() {
360
361        $this->writer->write(new \StdClass());
362
363    }
364
365    function testStartElementSimple() {
366
367        $this->writer->startElement("foo");
368        $this->writer->endElement();
369
370        $output = <<<HI
371<?xml version="1.0"?>
372<foo xmlns:s="http://sabredav.org/ns"/>
373
374HI;
375
376        $this->assertEquals($output, $this->writer->outputMemory());
377
378    }
379
380    function testCallback() {
381
382        $this->compare([
383            '{http://sabredav.org/ns}root' => function(Writer $writer) {
384                $writer->text('deferred writer');
385            },
386        ], <<<HI
387<?xml version="1.0"?>
388<s:root xmlns:s="http://sabredav.org/ns">deferred writer</s:root>
389
390HI
391        );
392
393    }
394
395    /**
396     * @expectedException \InvalidArgumentException
397     */
398    function testResource() {
399
400        $this->compare([
401            '{http://sabredav.org/ns}root' => fopen('php://memory', 'r'),
402        ], <<<HI
403<?xml version="1.0"?>
404<s:root xmlns:s="http://sabredav.org/ns">deferred writer</s:root>
405
406HI
407        );
408
409    }
410
411    function testClassMap() {
412
413        $obj = (object)[
414            'key1' => 'value1',
415            'key2' => 'value2',
416        ];
417
418        $this->writer->classMap['stdClass'] = function(Writer $writer, $value) {
419
420            foreach (get_object_vars($value) as $key => $val) {
421                $writer->writeElement('{http://sabredav.org/ns}' . $key, $val);
422            }
423
424        };
425
426        $this->compare([
427            '{http://sabredav.org/ns}root' => $obj
428        ], <<<HI
429<?xml version="1.0"?>
430<s:root xmlns:s="http://sabredav.org/ns">
431 <s:key1>value1</s:key1>
432 <s:key2>value2</s:key2>
433</s:root>
434
435HI
436        );
437
438    }
439}
440