1<?php
2
3declare(strict_types=1);
4
5namespace Sabre\Xml\Element;
6
7use Sabre\Xml\Reader;
8use Sabre\Xml\Writer;
9
10class KeyValueTest extends \PHPUnit\Framework\TestCase
11{
12    public function testDeserialize()
13    {
14        $input = <<<BLA
15<?xml version="1.0"?>
16<root xmlns="http://sabredav.org/ns">
17  <struct>
18    <elem1 />
19    <elem2>hi</elem2>
20    <elem3>
21       <elem4>foo</elem4>
22       <elem5>foo &amp; bar</elem5>
23    </elem3>
24    <elem6>Hi<!-- ignore me -->there</elem6>
25  </struct>
26  <struct />
27  <otherThing>
28    <elem1 />
29  </otherThing>
30</root>
31BLA;
32
33        $reader = new Reader();
34        $reader->elementMap = [
35            '{http://sabredav.org/ns}struct' => 'Sabre\\Xml\\Element\\KeyValue',
36        ];
37        $reader->xml($input);
38
39        $output = $reader->parse();
40
41        $this->assertEquals([
42            'name' => '{http://sabredav.org/ns}root',
43            'value' => [
44                [
45                    'name' => '{http://sabredav.org/ns}struct',
46                    'value' => [
47                        '{http://sabredav.org/ns}elem1' => null,
48                        '{http://sabredav.org/ns}elem2' => 'hi',
49                        '{http://sabredav.org/ns}elem3' => [
50                            [
51                                'name' => '{http://sabredav.org/ns}elem4',
52                                'value' => 'foo',
53                                'attributes' => [],
54                            ],
55                            [
56                                'name' => '{http://sabredav.org/ns}elem5',
57                                'value' => 'foo & bar',
58                                'attributes' => [],
59                            ],
60                        ],
61                        '{http://sabredav.org/ns}elem6' => 'Hithere',
62                    ],
63                    'attributes' => [],
64                ],
65                [
66                    'name' => '{http://sabredav.org/ns}struct',
67                    'value' => [],
68                    'attributes' => [],
69                ],
70                [
71                    'name' => '{http://sabredav.org/ns}otherThing',
72                    'value' => [
73                        [
74                            'name' => '{http://sabredav.org/ns}elem1',
75                            'value' => null,
76                            'attributes' => [],
77                        ],
78                    ],
79                    'attributes' => [],
80                ],
81            ],
82            'attributes' => [],
83        ], $output);
84    }
85
86    /**
87     * This test was added to find out why an element gets eaten by the
88     * SabreDAV MKCOL parser.
89     */
90    public function testElementEater()
91    {
92        $input = <<<BLA
93<?xml version="1.0"?>
94<mkcol xmlns="DAV:">
95  <set>
96    <prop>
97        <resourcetype><collection /></resourcetype>
98        <displayname>bla</displayname>
99    </prop>
100  </set>
101</mkcol>
102BLA;
103
104        $reader = new Reader();
105        $reader->elementMap = [
106            '{DAV:}set' => 'Sabre\\Xml\\Element\\KeyValue',
107            '{DAV:}prop' => 'Sabre\\Xml\\Element\\KeyValue',
108            '{DAV:}resourcetype' => 'Sabre\\Xml\\Element\\Elements',
109        ];
110        $reader->xml($input);
111
112        $expected = [
113            'name' => '{DAV:}mkcol',
114            'value' => [
115                [
116                    'name' => '{DAV:}set',
117                    'value' => [
118                        '{DAV:}prop' => [
119                            '{DAV:}resourcetype' => [
120                                '{DAV:}collection',
121                            ],
122                            '{DAV:}displayname' => 'bla',
123                        ],
124                    ],
125                    'attributes' => [],
126                ],
127            ],
128            'attributes' => [],
129        ];
130
131        $this->assertEquals($expected, $reader->parse());
132    }
133
134    public function testSerialize()
135    {
136        $value = [
137            '{http://sabredav.org/ns}elem1' => null,
138            '{http://sabredav.org/ns}elem2' => 'textValue',
139            '{http://sabredav.org/ns}elem3' => [
140                '{http://sabredav.org/ns}elem4' => 'text2',
141                '{http://sabredav.org/ns}elem5' => null,
142            ],
143            '{http://sabredav.org/ns}elem6' => 'text3',
144        ];
145
146        $writer = new Writer();
147        $writer->namespaceMap = [
148            'http://sabredav.org/ns' => null,
149        ];
150        $writer->openMemory();
151        $writer->startDocument('1.0');
152        $writer->setIndent(true);
153        $writer->write([
154            '{http://sabredav.org/ns}root' => new KeyValue($value),
155        ]);
156
157        $output = $writer->outputMemory();
158
159        $expected = <<<XML
160<?xml version="1.0"?>
161<root xmlns="http://sabredav.org/ns">
162 <elem1/>
163 <elem2>textValue</elem2>
164 <elem3>
165  <elem4>text2</elem4>
166  <elem5/>
167 </elem3>
168 <elem6>text3</elem6>
169</root>
170
171XML;
172
173        $this->assertEquals($expected, $output);
174    }
175
176    /**
177     * I discovered that when there's no whitespace between elements, elements
178     * can get skipped.
179     */
180    public function testElementSkipProblem()
181    {
182        $input = <<<BLA
183<?xml version="1.0" encoding="utf-8"?>
184<root xmlns="http://sabredav.org/ns">
185<elem3>val3</elem3><elem4>val4</elem4><elem5>val5</elem5></root>
186BLA;
187
188        $reader = new Reader();
189        $reader->elementMap = [
190            '{http://sabredav.org/ns}root' => 'Sabre\\Xml\\Element\\KeyValue',
191        ];
192        $reader->xml($input);
193
194        $output = $reader->parse();
195
196        $this->assertEquals([
197            'name' => '{http://sabredav.org/ns}root',
198            'value' => [
199                '{http://sabredav.org/ns}elem3' => 'val3',
200                '{http://sabredav.org/ns}elem4' => 'val4',
201                '{http://sabredav.org/ns}elem5' => 'val5',
202            ],
203            'attributes' => [],
204        ], $output);
205    }
206}
207