XMLConverter   A
last analyzed

Coupling/Cohesion

Components 1
Dependencies 0

Complexity

Total Complexity 14

Size/Duplication

Total Lines 239
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
dl 0
loc 239
ccs 50
cts 50
cp 1
rs 10
c 0
b 0
f 0
wmc 14
lcom 1
cbo 0

10 Methods

Rating   Name   Duplication   Size   Complexity  
A convert() 0 18 3
A recordToElementWithAttribute() 0 11 1
A recordToElement() 0 10 2
A fieldToElementWithAttribute() 0 7 1
A fieldToElement() 0 7 1
A rootElement() 0 7 1
A filterElementName() 0 4 1
A recordElement() 0 8 1
A filterAttributeName() 0 8 2
A fieldElement() 0 8 1
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
use TypeError;
23
24
/**
25
 * A class to convert CSV records into a DOMDOcument object
26
 *
27
 * @package League.csv
28
 * @since   9.0.0
29
 * @author  Ignace Nyamagana Butera <[email protected]>
30
 */
31
class XMLConverter
32
{
33
    /**
34
     * XML Root name
35
     *
36
     * @var string
37
     */
38
    protected $root_name = 'csv';
39
40
    /**
41
     * XML Node name
42
     *
43
     * @var string
44
     */
45
    protected $record_name = 'row';
46
47
    /**
48
     * XML Item name
49
     *
50
     * @var string
51
     */
52
    protected $field_name = 'cell';
53
54
    /**
55
     * XML column attribute name
56
     *
57
     * @var string
58
     */
59
    protected $column_attr = '';
60
61
    /**
62
     * XML offset attribute name
63
     *
64
     * @var string
65
     */
66
    protected $offset_attr = '';
67
68
    /**
69
     * Conversion method list
70
     *
71
     * @var array
72
     */
73
    protected $encoder = [
74
        'field' => [
75
            true => 'fieldToElementWithAttribute',
76
            false => 'fieldToElement',
77
        ],
78
        'record' => [
79
            true => 'recordToElementWithAttribute',
80
            false => 'recordToElement',
81
        ],
82
    ];
83
84
    /**
85
     * Convert an Record collection into a DOMDocument
86
     *
87
     * @param array|Traversable $records the CSV records collection
88
     *
89
     * @return DOMDocument
90
     */
91 4
    public function convert($records): DOMDocument
92
    {
93 4
        if (!is_iterable($records)) {
94 2
            throw new TypeError(sprintf('%s() expects argument passed to be iterable, %s given', __METHOD__, gettype($records)));
95
        }
96
97 2
        $field_encoder = $this->encoder['field']['' !== $this->column_attr];
98 2
        $record_encoder = $this->encoder['record']['' !== $this->offset_attr];
99 2
        $doc = new DOMDocument('1.0');
100 2
        $root = $doc->createElement($this->root_name);
101 2
        foreach ($records as $offset => $record) {
102 2
            $node = $this->$record_encoder($doc, $record, $field_encoder, $offset);
103 2
            $root->appendChild($node);
104
        }
105 2
        $doc->appendChild($root);
106
107 2
        return $doc;
108
    }
109
110
    /**
111
     * Convert a CSV record into a DOMElement and
112
     * adds its offset as DOMElement attribute
113
     *
114
     * @param DOMDocument $doc
115
     * @param array       $record        CSV record
116
     * @param string      $field_encoder CSV Cell encoder method name
117
     * @param int         $offset        CSV record offset
118
     *
119
     * @return DOMElement
120
     */
121 2
    protected function recordToElementWithAttribute(
122
        DOMDocument $doc,
123
        array $record,
124
        string $field_encoder,
125
        int $offset
126
    ): DOMElement {
127 2
        $node = $this->recordToElement($doc, $record, $field_encoder);
128 2
        $node->setAttribute($this->offset_attr, (string) $offset);
129
130 2
        return $node;
131
    }
132
133
    /**
134
     * Convert a CSV record into a DOMElement
135
     *
136
     * @param DOMDocument $doc
137
     * @param array       $record        CSV record
138
     * @param string      $field_encoder CSV Cell encoder method name
139
     *
140
     * @return DOMElement
141
     */
142 2
    protected function recordToElement(DOMDocument $doc, array $record, string $field_encoder): DOMElement
143
    {
144 2
        $node = $doc->createElement($this->record_name);
145 2
        foreach ($record as $node_name => $value) {
146 2
            $item = $this->$field_encoder($doc, $value, $node_name);
147 2
            $node->appendChild($item);
148
        }
149
150 2
        return $node;
151
    }
152
153
    /**
154
     * Convert Cell to Item.
155
     *
156
     * Convert the CSV item into a DOMElement and adds the item offset
157
     * as attribute to the returned DOMElement
158
     *
159
     * @param DOMDocument $doc
160
     * @param string      $value     Record item value
161
     * @param int|string  $node_name Record item offset
162
     *
163
     * @return DOMElement
164
     */
165 2
    protected function fieldToElementWithAttribute(DOMDocument $doc, string $value, $node_name): DOMElement
166
    {
167 2
        $item = $this->fieldToElement($doc, $value);
168 2
        $item->setAttribute($this->column_attr, (string) $node_name);
169
170 2
        return $item;
171
    }
172
173
    /**
174
     * Convert Cell to Item
175
     *
176
     * @param DOMDocument $doc
177
     * @param string      $value Record item value
178
     *
179
     * @return DOMElement
180
     */
181 2
    protected function fieldToElement(DOMDocument $doc, string $value): DOMElement
182
    {
183 2
        $item = $doc->createElement($this->field_name);
184 2
        $item->appendChild($doc->createTextNode($value));
185
186 2
        return $item;
187
    }
188
189
    /**
190
     * XML root element setter
191
     *
192
     * @param string $node_name
193
     *
194
     * @return self
195
     */
196 4
    public function rootElement(string $node_name): self
197
    {
198 4
        $clone = clone $this;
199 4
        $clone->root_name = $this->filterElementName($node_name);
200
201 2
        return $clone;
202
    }
203
204
    /**
205
     * Filter XML element name
206
     *
207
     * @param string $value Element name
208
     *
209
     * @throws DOMException If the Element name is invalid
210
     *
211
     * @return string
212
     */
213 4
    protected function filterElementName(string $value): string
214
    {
215 4
        return (new DOMElement($value))->tagName;
216
    }
217
218
    /**
219
     * XML Record element setter
220
     *
221
     * @param string $node_name
222
     * @param string $record_offset_attribute_name
223
     *
224
     * @return self
225
     */
226 2
    public function recordElement(string $node_name, string $record_offset_attribute_name = ''): self
227
    {
228 2
        $clone = clone $this;
229 2
        $clone->record_name = $this->filterElementName($node_name);
230 2
        $clone->offset_attr = $this->filterAttributeName($record_offset_attribute_name);
231
232 2
        return $clone;
233
    }
234
235
    /**
236
     * Filter XML attribute name
237
     *
238
     * @param string $value Element name
239
     *
240
     * @throws DOMException If the Element attribute name is invalid
241
     *
242
     * @return string
243
     */
244 4
    protected function filterAttributeName(string $value): string
245
    {
246 4
        if ('' === $value) {
247 2
            return $value;
248
        }
249
250 2
        return (new DOMAttr($value))->name;
251
    }
252
253
    /**
254
     * XML Field element setter
255
     *
256
     * @param string $node_name
257
     * @param string $fieldname_attribute_name
258
     *
259
     * @return self
260
     */
261 2
    public function fieldElement(string $node_name, string $fieldname_attribute_name = ''): self
262
    {
263 2
        $clone = clone $this;
264 2
        $clone->field_name = $this->filterElementName($node_name);
265 2
        $clone->column_attr = $this->filterAttributeName($fieldname_attribute_name);
266
267 2
        return $clone;
268
    }
269
}
270