XmlReader   A
last analyzed

Complexity

Total Complexity 20

Size/Duplication

Total Lines 121
Duplicated Lines 0 %

Test Coverage

Coverage 95.65%

Importance

Changes 2
Bugs 0 Features 0
Metric Value
wmc 20
eloc 42
c 2
b 0
f 0
dl 0
loc 121
ccs 44
cts 46
cp 0.9565
rs 10

12 Methods

Rating   Name   Duplication   Size   Complexity  
A key() 0 3 1
A rewind() 0 3 1
A current() 0 7 2
A isDenormalizable() 0 3 1
A getDto() 0 3 1
A count() 0 3 1
A transformToArray() 0 9 3
A __construct() 0 35 6
A index() 0 3 1
A valid() 0 3 1
A next() 0 4 1
A getFile() 0 3 1
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the DataImporter package.
7
 *
8
 * (c) Loïc Sapone <[email protected]>
9
 *
10
 * For the full copyright and license information, please view the LICENSE
11
 * file that was distributed with this source code.
12
 */
13
14
namespace IQ2i\DataImporter\Reader;
15
16
class XmlReader implements ReaderInterface
17
{
18
    /**
19
     * @var string
20
     */
21
    final public const CONTEXT_XPATH = 'xml_xpath';
22
23
    private readonly \SplFileInfo $file;
24
25
    private \SimpleXMLIterator $iterator;
26
27
    private int $index = 1;
28
29
    private array $defaultContext = [
30
        self::CONTEXT_XPATH => null,
31
    ];
32
33 6
    public function __construct(
34
        string $filePath,
35
        private readonly ?string $dto = null,
36
        array $defaultContext = [],
37
    ) {
38 6
        $this->file = new \SplFileInfo($filePath);
0 ignored issues
show
Bug introduced by
The property file is declared read-only in IQ2i\DataImporter\Reader\XmlReader.
Loading history...
39 6
        if (!$this->file->isReadable()) {
40 1
            throw new \InvalidArgumentException('The file '.$this->file->getFilename().' is not readable.');
41
        }
42
43 5
        $this->defaultContext = \array_merge($this->defaultContext, $defaultContext);
44
45 5
        if (null === $this->defaultContext[self::CONTEXT_XPATH]) {
46 1
            $this->iterator = new \SimpleXMLIterator($this->file->getPathname(), 0, true);
47
        } else {
48 4
            $element = new \SimpleXMLElement($this->file->getPathname(), 0, true);
49
50 4
            $nodes = \explode('/', (string) $this->defaultContext[self::CONTEXT_XPATH]);
51 4
            $rootNode = \array_shift($nodes);
52 4
            if ($rootNode !== $element->getName()) {
53 1
                throw new \InvalidArgumentException('The path "'.$this->defaultContext[self::CONTEXT_XPATH].'" is incorrect.');
54
            }
55
56 3
            foreach ($nodes as $node) {
57 3
                if (!isset($element->{$node})) {
58 1
                    throw new \InvalidArgumentException('The path "'.$this->defaultContext[self::CONTEXT_XPATH].'" is incorrect.');
59
                }
60
61 2
                $element = $element->{$node};
62
            }
63
64 2
            $this->iterator = new \SimpleXMLIterator($element->asXML());
65
        }
66
67 3
        $this->rewind();
68
    }
69
70
    public function getDto(): ?string
71
    {
72
        return $this->dto;
73
    }
74
75 3
    public function isDenormalizable(): bool
76
    {
77 3
        return null !== $this->dto;
78
    }
79
80 1
    public function getFile(): \SplFileInfo
81
    {
82 1
        return $this->file;
83
    }
84
85 3
    public function index(): mixed
86
    {
87 3
        return $this->index;
88
    }
89
90 3
    public function current(): array
91
    {
92 3
        if (!$this->valid()) {
93 2
            return [];
94
        }
95
96 3
        return self::transformToArray($this->iterator->current());
97
    }
98
99 3
    public function next(): void
100
    {
101 3
        $this->iterator->next();
102 3
        ++$this->index;
103
    }
104
105 2
    public function key(): mixed
106
    {
107 2
        return $this->iterator->key();
108
    }
109
110 3
    public function valid(): bool
111
    {
112 3
        return $this->iterator->valid();
113
    }
114
115 3
    public function rewind(): void
116
    {
117 3
        $this->iterator->rewind();
118
    }
119
120 3
    public function count(): int
121
    {
122 3
        return $this->iterator->count();
123
    }
124
125
    /**
126
     * Transform SimpleXMLIterator into array.
127
     */
128 3
    private static function transformToArray(\SimpleXMLIterator $iterator): array
129
    {
130 3
        $result = [];
131
132 3
        foreach ((array) $iterator as $index => $node) {
133 3
            $result[$index] = \is_object($node) ? self::transformToArray($node) : $node;
134
        }
135
136 3
        return $result;
137
    }
138
}
139