Completed
Push — master ( b7f6ee...046fb8 )
by ignace nyamagana
04:55 queued 03:20
created

XMLConverter::filterNodeName()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 3
nc 1
nop 1
dl 0
loc 6
ccs 3
cts 3
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
     * Conversion method list
71
     *
72
     * @var array
73
     */
74
    protected $encoder = [
75
        'field' => [
76
            true => 'fieldToElementWithAttribute',
77
            false => 'fieldToElement',
78
        ],
79
        'record' => [
80
            true => 'recordToElementWithAttribute',
81
            false => 'recordToElement',
82
        ],
83
    ];
84
85
    /**
86
     * XML root element setter
87
     *
88
     * @param string $node_name
89
     *
90
     * @return self
91
     */
92 4
    public function rootElement(string $node_name): self
93
    {
94 4
        $clone = clone $this;
95 4
        $clone->root_name = $this->filterNodeName($node_name);
96
97 2
        return $clone;
98
    }
99
100
    /**
101
     * Filter XML element name
102
     *
103
     * @param string $value Element name
104
     *
105
     * @throws DOMException If the Element name is invalid
106
     *
107
     * @return string
108
     */
109 6
    protected function filterNodeName(string $value): string
110
    {
111 6
        new DOMElement($value);
112
113 4
        return $value;
114
    }
115
116
    /**
117
     * XML Record element setter
118
     *
119
     * @param string $node_name
120
     * @param string $record_offset_attribute_name
121
     *
122
     * @return self
123
     */
124 4
    public function recordElement(string $node_name, string $record_offset_attribute_name = ''): self
125
    {
126 4
        $clone = clone $this;
127 4
        $clone->record_name = $this->filterNodeName($node_name);
128 4
        $clone->offset_attr = $this->filterAttributeName($record_offset_attribute_name);
129
130 4
        return $clone;
131
    }
132
133
    /**
134
     * Filter XML attribute name
135
     *
136
     * @param string $value Element name
137
     *
138
     * @throws DOMException If the Element attribute name is invalid
139
     *
140
     * @return string
141
     */
142 4
    protected function filterAttributeName(string $value): string
143
    {
144 4
        if ('' === $value) {
145 2
            return $value;
146
        }
147
148 4
        new DOMAttr($value);
149
150 4
        return $value;
151
    }
152
153
    /**
154
     * XML Field element setter
155
     *
156
     * @param string $node_name
157
     * @param string $fieldname_attribute_name
158
     *
159
     * @return self
160
     */
161 2
    public function fieldElement(string $node_name, string $fieldname_attribute_name = ''): self
162
    {
163 2
        $clone = clone $this;
164 2
        $clone->field_name = $this->filterNodeName($node_name);
165 2
        $clone->column_attr = $this->filterAttributeName($fieldname_attribute_name);
166
167 2
        return $clone;
168
    }
169
170
    /**
171
     * Convert an Record collection into a DOMDocument
172
     *
173
     * @param array|Traversable $records the CSV records collection
174
     *
175
     * @return DOMDocument
176
     */
177 4
    public function convert($records)
178
    {
179 4
        $field_encoder = $this->encoder['field']['' !== $this->column_attr];
180 4
        $record_encoder = $this->encoder['record']['' !== $this->offset_attr];
181 4
        $doc = new DOMDocument('1.0', 'UTF-8');
182 4
        $root = $doc->createElement($this->root_name);
183 4
        foreach ($this->filterIterable($records, __METHOD__) as $offset => $record) {
184 4
            $node = $this->{$record_encoder}($doc, $record, $field_encoder, $offset);
185 4
            $root->appendChild($node);
186
        }
187 4
        $doc->appendChild($root);
188
189 4
        return $doc;
190
    }
191
192
    /**
193
     * Convert a CSV record into a DOMElement and
194
     * adds its offset as DOMElement attribute
195
     *
196
     * @param DOMDocument $doc
197
     * @param array       $record        CSV record
198
     * @param string      $field_encoder CSV Cell encoder method name
199
     * @param int         $offset        CSV record offset
200
     *
201
     * @return DOMElement
202
     */
203 4
    protected function recordToElementWithAttribute(
204
        DOMDocument $doc,
205
        array $record,
206
        string $field_encoder,
207
        int $offset
208
    ): DOMElement {
209 4
        $node = $this->recordToElement($doc, $record, $field_encoder);
210 4
        $node->setAttribute($this->offset_attr, (string) $offset);
211
212 4
        return $node;
213
    }
214
215
    /**
216
     * Convert a CSV record into a DOMElement
217
     *
218
     * @param DOMDocument $doc
219
     * @param array       $record        CSV record
220
     * @param string      $field_encoder CSV Cell encoder method name
221
     *
222
     * @return DOMElement
223
     */
224 4
    protected function recordToElement(DOMDocument $doc, array $record, string $field_encoder): DOMElement
225
    {
226 4
        $node = $doc->createElement($this->record_name);
227 4
        foreach ($record as $node_name => $value) {
228 4
            $item = $this->{$field_encoder}($doc, $value, $node_name);
229 4
            $node->appendChild($item);
230
        }
231
232 4
        return $node;
233
    }
234
235
    /**
236
     * Convert Cell to Item.
237
     *
238
     * Convert the CSV item into a DOMElement and adds the item offset
239
     * as attribute to the returned DOMElement
240
     *
241
     * @param DOMDocument $doc
242
     * @param string      $value     Record item value
243
     * @param int|string  $node_name Record item offset
244
     *
245
     * @return DOMElement
246
     */
247 2
    protected function fieldToElementWithAttribute(DOMDocument $doc, string $value, $node_name): DOMElement
248
    {
249 2
        $item = $this->fieldToElement($doc, $value);
250 2
        $item->setAttribute($this->column_attr, (string) $node_name);
251
252 2
        return $item;
253
    }
254
255
    /**
256
     * Convert Cell to Item
257
     *
258
     * @param DOMDocument $doc
259
     * @param string      $value Record item value
260
     *
261
     * @return DOMElement
262
     */
263 4
    protected function fieldToElement(DOMDocument $doc, string $value): DOMElement
264
    {
265 4
        $item = $doc->createElement($this->field_name);
266 4
        $item->appendChild($doc->createTextNode($value));
267
268 4
        return $item;
269
    }
270
}
271