Completed
Pull Request — master (#348)
by
unknown
12:57
created

XMLConverter::overrideRecordFieldElement()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 2
dl 0
loc 6
ccs 0
cts 0
cp 0
crap 2
rs 10
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * League.Csv (https://csv.thephpleague.com)
5
 *
6
 * (c) Ignace Nyamagana Butera <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
declare(strict_types=1);
13
14
namespace League\Csv;
15
16
use DOMAttr;
17
use DOMDocument;
18
use DOMElement;
19
use DOMException;
20
use Traversable;
21
use TypeError;
22
use function gettype;
23
use function is_iterable;
24
use function sprintf;
25
26
/**
27
 * Converts tabular data into a DOMDOcument object.
28
 */
29
class XMLConverter
30
{
31
    /**
32
     * XML Root name.
33
     *
34
     * @var string
35
     */
36
    protected $root_name = 'csv';
37
38
    /**
39
     * XML Node name.
40
     *
41
     * @var string
42
     */
43
    protected $record_name = 'row';
44
45
    /**
46
     * XML Item name.
47
     *
48
     * @var string
49
     */
50
    protected $field_name = 'cell';
51
52
    /**
53
     * A list of overrides for the field name based on the the record count.
54
     *
55
     * @var array
56
     */
57
    protected $field_name_overrides = [];
58
59
    /**
60
     * XML column attribute name.
61
     *
62
     * @var string
63
     */
64
    protected $column_attr = '';
65
66
    /**
67
     * XML offset attribute name.
68
     *
69
     * @var string
70
     */
71
    protected $offset_attr = '';
72
73
    /**
74
     * Conversion method list.
75
     *
76
     * @var array
77
     */
78
    protected $encoder = [
79
        'field' => [
80
            true => 'fieldToElementWithAttribute',
81
            false => 'fieldToElement',
82
        ],
83
        'record' => [
84
            true => 'recordToElementWithAttribute',
85
            false => 'recordToElement',
86
        ],
87 6
    ];
88
89 6
    /**
90 3
     * Convert an Record collection into a DOMDocument.
91
     *
92
     * @param array|Traversable $records the CSV records collection
93 3
     */
94 3
    public function convert($records): DOMDocument
95 3
    {
96 3
        if (!is_iterable($records)) {
97 3
            throw new TypeError(sprintf('%s() expects argument passed to be iterable, %s given', __METHOD__, gettype($records)));
98 3
        }
99 3
100
        $field_encoder = $this->encoder['field']['' !== $this->column_attr];
101 3
        $record_encoder = $this->encoder['record']['' !== $this->offset_attr];
102
        $doc = new DOMDocument('1.0');
103 3
        $root = $doc->createElement($this->root_name);
104
        $count = 0;
105
        foreach ($records as $offset => $record) {
106
            $node = $this->$record_encoder($doc, $record, $field_encoder, $offset, $count++);
107
            $root->appendChild($node);
108
        }
109
        $doc->appendChild($root);
110 3
111
        return $doc;
112
    }
113
114
    /**
115
     * Convert a CSV record into a DOMElement and
116 3
     * adds its offset as DOMElement attribute.
117 3
     */
118
    protected function recordToElementWithAttribute(
119 3
        DOMDocument $doc,
120
        array $record,
121
        string $field_encoder,
122
        int $offset,
123
        int $count = 0
124
    ): DOMElement {
125 3
        $node = $this->recordToElement($doc, $record, $field_encoder, $count);
126
        $node->setAttribute($this->offset_attr, (string) $offset);
127 3
128 3
        return $node;
129 3
    }
130 3
131
    /**
132
     * Convert a CSV record into a DOMElement.
133 3
     */
134
    protected function recordToElement(DOMDocument $doc, array $record, string $field_encoder, int $count = 0): DOMElement
135
    {
136
        $node = $doc->createElement($this->record_name);
137
        $field_override = $this->field_name_overrides[$count] ?? null;
138
        foreach ($record as $node_name => $value) {
139
            $item = $this->$field_encoder($doc, (string) $value, $node_name, $field_override);
140
            $node->appendChild($item);
141
        }
142
143
        return $node;
144 3
    }
145
146 3
    /**
147 3
     * Convert Cell to Item.
148
     *
149 3
     * Convert the CSV item into a DOMElement and adds the item offset
150
     * as attribute to the returned DOMElement
151
     *
152
     * @param int|string $node_name
153
     * @param string $field_override Override the field type
0 ignored issues
show
Bug introduced by
There is no parameter named $field_override. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
154
     */
155
    protected function fieldToElementWithAttribute(DOMDocument $doc, string $value, $node_name, string $type_override = null): DOMElement
156
    {
157 3
        $item = $this->fieldToElement($doc, $value, $type_override);
158
        $item->setAttribute($this->column_attr, (string) $node_name);
159 3
160 3
        return $item;
161
    }
162 3
163
    /**
164
     * Convert Cell to Item.
165
     *
166
     * @param string $value Record item value
167
     * @param string $field_override Override the field type
0 ignored issues
show
Bug introduced by
There is no parameter named $field_override. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
168 6
     */
169
    protected function fieldToElement(DOMDocument $doc, string $value, string $type_override = null): DOMElement
170 6
    {
171 6
        $item = $doc->createElement($type_override ?? $this->field_name);
172
        $item->appendChild($doc->createTextNode($value));
173 3
174
        return $item;
175
    }
176
177
    /**
178
     * XML root element setter.
179
     */
180
    public function rootElement(string $node_name): self
181 6
    {
182
        $clone = clone $this;
183 6
        $clone->root_name = $this->filterElementName($node_name);
184
185
        return $clone;
186
    }
187
188
    /**
189 3
     * Filter XML element name.
190
     *
191 3
     * @throws DOMException If the Element name is invalid
192 3
     */
193 3
    protected function filterElementName(string $value): string
194
    {
195 3
        return (new DOMElement($value))->tagName;
196
    }
197
198
    /**
199
     * XML Record element setter.
200
     */
201
    public function recordElement(string $node_name, string $record_offset_attribute_name = ''): self
202
    {
203
        $clone = clone $this;
204
        $clone->record_name = $this->filterElementName($node_name);
205 6
        $clone->offset_attr = $this->filterAttributeName($record_offset_attribute_name);
206
207 6
        return $clone;
208 3
    }
209
210
    /**
211 3
     * Filter XML attribute name.
212
     *
213
     * @param string $value Element name
214
     *
215
     * @throws DOMException If the Element attribute name is invalid
216
     */
217 3
    protected function filterAttributeName(string $value): string
218
    {
219 3
        if ('' === $value) {
220 3
            return $value;
221 3
        }
222
223 3
        return (new DOMAttr($value))->name;
224
    }
225
226
    /**
227
     * XML Field element setter.
228
     */
229
    public function fieldElement(string $node_name, string $fieldname_attribute_name = ''): self
230
    {
231
        $clone = clone $this;
232
        $clone->field_name = $this->filterElementName($node_name);
233
        $clone->column_attr = $this->filterAttributeName($fieldname_attribute_name);
234
235
        return $clone;
236
    }
237
238
    /**
239
     * Override the field type to use for the first record
240
     *
241
     * @param int $element_index
242
     * @param string $node_name
243
     *
244
     * @return XMLConverter
245
     *
246
     * @throws DOMException
247
     */
248
    public function overrideRecordFieldElement(int $element_index, string $node_name): self
249
    {
250
        $clone = clone $this;
251
        $clone->field_name_overrides[$element_index] = $this->filterElementName($node_name);
252
        return $clone;
253
    }
254
}
255