Completed
Push — master ( ecd0f8...3ad52b )
by ignace nyamagana
29:57 queued 15:08
created

XMLConverter::fieldElement()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 1

Importance

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