Completed
Push — master ( 046fb8...827e43 )
by ignace nyamagana
09:07 queued 07:27
created

XMLConverter::encoding()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 4
nc 1
nop 1
dl 0
loc 7
ccs 4
cts 4
cp 1
crap 1
rs 9.4285
c 0
b 0
f 0
1
<?php
2
/**
3
* This file is part of the League.csv library
4
*
5
* @license http://opensource.org/licenses/MIT
6
* @link https://github.com/thephpleague/csv/
7
* @version 9.0.0
8
* @package League.csv
9
*
10
* For the full copyright and license information, please view the LICENSE
11
* file that was distributed with this source code.
12
*/
13
declare(strict_types=1);
14
15
namespace League\Csv;
16
17
use DOMAttr;
18
use DOMDocument;
19
use DOMElement;
20
use DOMException;
21
use Traversable;
22
23
/**
24
 * A class to convert CSV records into a DOMDOcument object
25
 *
26
 * @package League.csv
27
 * @since   9.0.0
28
 * @author  Ignace Nyamagana Butera <[email protected]>
29
 */
30
class XMLConverter implements Converter
31
{
32
    use ValidatorTrait;
33
34
    /**
35
     * XML Root name
36
     *
37
     * @var string
38
     */
39
    protected $root_name = 'csv';
40
41
    /**
42
     * XML Node name
43
     *
44
     * @var string
45
     */
46
    protected $record_name = 'row';
47
48
    /**
49
     * XML Item name
50
     *
51
     * @var string
52
     */
53
    protected $field_name = 'cell';
54
55
    /**
56
     * XML column attribute name
57
     *
58
     * @var string
59
     */
60
    protected $column_attr = '';
61
62
    /**
63
     * XML offset attribute name
64
     *
65
     * @var string
66
     */
67
    protected $offset_attr = '';
68
69
    /**
70
     * XML document encoding
71
     *
72
     * @var string
73
     */
74
    protected $encoding = 'UTF-8';
75
76
    /**
77
     * Conversion method list
78
     *
79
     * @var array
80
     */
81
    protected $encoder = [
82
        'field' => [
83
            true => 'fieldToElementWithAttribute',
84
            false => 'fieldToElement',
85
        ],
86
        'record' => [
87
            true => 'recordToElementWithAttribute',
88
            false => 'recordToElement',
89
        ],
90
    ];
91
92
    /**
93
     * XML encoding
94
     *
95
     * @param string $encoding
96
     *
97
     * @return static
98
     */
99 4
    public function encoding(string $encoding): self
100
    {
101 4
        $clone = clone $this;
102 4
        $clone->encoding = $this->filterEncoding($encoding);
103
104 4
        return $clone;
105
    }
106
107
    /**
108
     * XML root element setter
109
     *
110
     * @param string $node_name
111
     *
112
     * @return self
113
     */
114 4
    public function rootElement(string $node_name): self
115
    {
116 4
        $clone = clone $this;
117 4
        $clone->root_name = $this->filterElementName($node_name);
118
119 2
        return $clone;
120
    }
121
122
    /**
123
     * Filter XML element name
124
     *
125
     * @param string $value Element name
126
     *
127
     * @throws DOMException If the Element name is invalid
128
     *
129
     * @return string
130
     */
131 6
    protected function filterElementName(string $value): string
132
    {
133 6
        return (new DOMElement($value))->tagName;
134
    }
135
136
    /**
137
     * XML Record element setter
138
     *
139
     * @param string $node_name
140
     * @param string $record_offset_attribute_name
141
     *
142
     * @return self
143
     */
144 4
    public function recordElement(string $node_name, string $record_offset_attribute_name = ''): self
145
    {
146 4
        $clone = clone $this;
147 4
        $clone->record_name = $this->filterElementName($node_name);
148 4
        $clone->offset_attr = $this->filterAttributeName($record_offset_attribute_name);
149
150 4
        return $clone;
151
    }
152
153
    /**
154
     * Filter XML attribute name
155
     *
156
     * @param string $value Element name
157
     *
158
     * @throws DOMException If the Element attribute name is invalid
159
     *
160
     * @return string
161
     */
162 4
    protected function filterAttributeName(string $value): string
163
    {
164 4
        if ('' === $value) {
165 2
            return $value;
166
        }
167
168 4
        return (new DOMAttr($value))->name;
169
    }
170
171
    /**
172
     * XML Field element setter
173
     *
174
     * @param string $node_name
175
     * @param string $fieldname_attribute_name
176
     *
177
     * @return self
178
     */
179 2
    public function fieldElement(string $node_name, string $fieldname_attribute_name = ''): self
180
    {
181 2
        $clone = clone $this;
182 2
        $clone->field_name = $this->filterElementName($node_name);
183 2
        $clone->column_attr = $this->filterAttributeName($fieldname_attribute_name);
184
185 2
        return $clone;
186
    }
187
188
    /**
189
     * Convert an Record collection into a DOMDocument
190
     *
191
     * @param array|Traversable $records the CSV records collection
192
     *
193
     * @return DOMDocument
194
     */
195 4
    public function convert($records)
196
    {
197 4
        $field_encoder = $this->encoder['field']['' !== $this->column_attr];
198 4
        $record_encoder = $this->encoder['record']['' !== $this->offset_attr];
199 4
        $doc = new DOMDocument('1.0', $this->encoding);
200 4
        $root = $doc->createElement($this->root_name);
201 4
        foreach ($this->filterIterable($records, __METHOD__) as $offset => $record) {
202 4
            $node = $this->{$record_encoder}($doc, $record, $field_encoder, $offset);
203 4
            $root->appendChild($node);
204
        }
205 4
        $doc->appendChild($root);
206
207 4
        return $doc;
208
    }
209
210
    /**
211
     * Convert a CSV record into a DOMElement and
212
     * adds its offset as DOMElement attribute
213
     *
214
     * @param DOMDocument $doc
215
     * @param array       $record        CSV record
216
     * @param string      $field_encoder CSV Cell encoder method name
217
     * @param int         $offset        CSV record offset
218
     *
219
     * @return DOMElement
220
     */
221 4
    protected function recordToElementWithAttribute(
222
        DOMDocument $doc,
223
        array $record,
224
        string $field_encoder,
225
        int $offset
226
    ): DOMElement {
227 4
        $node = $this->recordToElement($doc, $record, $field_encoder);
228 4
        $node->setAttribute($this->offset_attr, (string) $offset);
229
230 4
        return $node;
231
    }
232
233
    /**
234
     * Convert a CSV record into a DOMElement
235
     *
236
     * @param DOMDocument $doc
237
     * @param array       $record        CSV record
238
     * @param string      $field_encoder CSV Cell encoder method name
239
     *
240
     * @return DOMElement
241
     */
242 4
    protected function recordToElement(DOMDocument $doc, array $record, string $field_encoder): DOMElement
243
    {
244 4
        $node = $doc->createElement($this->record_name);
245 4
        foreach ($record as $node_name => $value) {
246 4
            $item = $this->{$field_encoder}($doc, $value, $node_name);
247 4
            $node->appendChild($item);
248
        }
249
250 4
        return $node;
251
    }
252
253
    /**
254
     * Convert Cell to Item.
255
     *
256
     * Convert the CSV item into a DOMElement and adds the item offset
257
     * as attribute to the returned DOMElement
258
     *
259
     * @param DOMDocument $doc
260
     * @param string      $value     Record item value
261
     * @param int|string  $node_name Record item offset
262
     *
263
     * @return DOMElement
264
     */
265 2
    protected function fieldToElementWithAttribute(DOMDocument $doc, string $value, $node_name): DOMElement
266
    {
267 2
        $item = $this->fieldToElement($doc, $value);
268 2
        $item->setAttribute($this->column_attr, (string) $node_name);
269
270 2
        return $item;
271
    }
272
273
    /**
274
     * Convert Cell to Item
275
     *
276
     * @param DOMDocument $doc
277
     * @param string      $value Record item value
278
     *
279
     * @return DOMElement
280
     */
281 4
    protected function fieldToElement(DOMDocument $doc, string $value): DOMElement
282
    {
283 4
        $item = $doc->createElement($this->field_name);
284 4
        $item->appendChild($doc->createTextNode($value));
285
286 4
        return $item;
287
    }
288
}
289