Completed
Push — master ( 9ef25d...153ee0 )
by Paweł
03:23
created

XMLWriter::addElementArrayAssoc()   B

Complexity

Conditions 10
Paths 9

Size

Total Lines 31
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 14
CRAP Score 10.1953

Importance

Changes 0
Metric Value
cc 10
eloc 18
c 0
b 0
f 0
nc 9
nop 3
dl 0
loc 31
ccs 14
cts 16
cp 0.875
crap 10.1953
rs 7.6666

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
declare(strict_types=1);
4
5
/**
6
 * This file is part of Wszetko Sitemap.
7
 *
8
 * (c) Paweł Kłopotek-Główczewski <[email protected]>
9
 *
10
 * This source file is subject to the MIT license that is bundled
11
 * with this source code in the file LICENSE.
12
 */
13
14
namespace Wszetko\Sitemap\Drivers\XML;
15
16
use Exception;
17
use Wszetko\Sitemap\Sitemap;
18
19
/**
20
 * Class XMLWriter.
21
 *
22
 * @package Wszetko\Sitemap\Drivers\XML
23
 */
24
class XMLWriter extends AbstractXML
25
{
26
    /**
27
     * XMLWriter constructor.
28
     *
29
     * @param array $config
30
     *
31
     * @throws \InvalidArgumentException
32
     */
33 18
    public function __construct(array $config)
34
    {
35 18
        if (!isset($config['domain'])) {
36 2
            throw new \InvalidArgumentException('Domain is not set.');
37
        }
38
39 18
        $this->XMLWriter = new \XMLWriter();
40 18
        $this->setDomain($config['domain']);
41 18
    }
42
43
    /**
44
     * @param string $sitemap
45
     * @param array  $extensions
46
     */
47 4
    public function openSitemap(string $sitemap, array $extensions = []): void
48
    {
49 4
        $this->setCurrentSitemap($sitemap);
50
        /* @var \XMLWriter $XMLWriter */
51 4
        $XMLWriter = $this->getXMLWriter();
52 4
        $XMLWriter->openMemory();
53 4
        $XMLWriter->startDocument('1.0', 'UTF-8');
54 4
        $XMLWriter->setIndent(true);
55 4
        $XMLWriter->startElement('urlset');
56 4
        $XMLWriter->writeAttribute('xmlns', Sitemap::SCHEMA);
57
58 4
        foreach ($extensions as $extension => $urlset) {
59 2
            $this->getXMLWriter()->writeAttribute('xmlns:' . $extension, $urlset);
60
        }
61
62 4
        $this->flushData();
63 4
    }
64
65
    /**
66
     * @throws \Exception
67
     */
68 4
    public function closeSitemap(): void
69
    {
70
        /* @var \XMLWriter $XMLWriter */
71 4
        $XMLWriter = $this->getXMLWriter();
72 4
        $XMLWriter->endElement();
73 4
        $XMLWriter->endDocument();
74 4
        $this->flushData();
75 4
        $this->endFile();
76 4
    }
77
78
    /**
79
     * @return int
80
     */
81 6
    public function getSitemapSize(): int
82
    {
83 6
        clearstatcache(true, $this->getSitemapFileFullPath());
84
85 6
        return file_exists($this->getSitemapFileFullPath()) ? (int) filesize($this->getSitemapFileFullPath()) : 0;
86
    }
87
88
    /**
89
     * @param array $element
90
     */
91 2
    public function addUrl(array $element): void
92
    {
93 2
        foreach ($element as $el => $val) {
94 2
            $this->addElement($el, $val);
95
        }
96
97 2
        $this->flushData();
98 2
    }
99
100
    /**
101
     * @param string $sitemap
102
     */
103 2
    public function openSitemapIndex(string $sitemap): void
104
    {
105 2
        $this->setCurrentSitemap($sitemap);
106
        /* @var \XMLWriter $XMLWriter */
107 2
        $XMLWriter = $this->getXMLWriter();
108 2
        $XMLWriter->openMemory();
109 2
        $XMLWriter->startDocument('1.0', 'UTF-8');
110 2
        $XMLWriter->setIndent(true);
111 2
        $XMLWriter->startElement('sitemapindex');
112 2
        $XMLWriter->writeAttribute('xmlns', Sitemap::SCHEMA);
113 2
        $this->flushData();
114 2
    }
115
116
    /**
117
     * @throws \Exception
118
     */
119 2
    public function closeSitemapIndex(): void
120
    {
121
        /* @var \XMLWriter $XMLWriter */
122 2
        $XMLWriter = $this->getXMLWriter();
123 2
        $XMLWriter->endElement();
124 2
        $XMLWriter->endDocument();
125 2
        $this->flushData();
126 2
        $this->endFile();
127 2
    }
128
129
    /**
130
     * @param string      $sitemap
131
     * @param null|string $lastmod
132
     */
133 2
    public function addSitemap(string $sitemap, string $lastmod = null): void
134
    {
135
        /* @var \XMLWriter $XMLWriter */
136 2
        $XMLWriter = $this->getXMLWriter();
137 2
        $XMLWriter->startElement('sitemap');
138 2
        $XMLWriter->writeElement('loc', $sitemap);
139 2
        if (isset($lastmod)) {
140 2
            $XMLWriter->writeElement('lastmod', $lastmod);
141
        }
142 2
        $XMLWriter->endElement();
143 2
        $this->flushData();
144 2
    }
145
146
    /**
147
     * Save from buffer to file.
148
     *
149
     * @return void
150
     */
151 6
    private function flushData(): void
152
    {
153 6
        file_put_contents($this->getSitemapFileFullPath(), $this->getXMLWriter()->flush(true), FILE_APPEND);
154 6
    }
155
156
    /**
157
     * Remove whitespace chars from end of file (Google don't like them).
158
     *
159
     * @throws Exception
160
     *
161
     * @return void
162
     */
163 6
    private function endFile(): void
164
    {
165 6
        if ($sitemapFile = fopen($this->getSitemapFileFullPath(), 'r+')) {
166 6
            fseek($sitemapFile, -1, SEEK_END);
167 6
            $truncate = 0;
168 6
            $length = $this->getSitemapSize();
169 6
            $end = false;
170
171
            do {
172 6
                $s = fread($sitemapFile, 1);
173 6
                if (is_string($s) && ctype_space($s)) {
174 6
                    ++$truncate;
175 6
                    fseek($sitemapFile, -2, SEEK_CUR);
176
                } else {
177 6
                    $end = true;
178
                }
179 6
            } while (!$end);
180
181 6
            ftruncate($sitemapFile, $length - $truncate);
182 6
            fclose($sitemapFile);
183
        }
184 6
    }
185
186
    /**
187
     * @param string      $element
188
     * @param mixed       $value
189
     * @param null|string $namespace
190
     */
191 2
    private function addElement(string $element, $value, ?string $namespace = null): void
192
    {
193 2
        if (!is_array($value)) {
194
            /* @var \XMLWriter $XMLWriter */
195 2
            $XMLWriter = $this->getXMLWriter();
196 2
            $XMLWriter->writeElement(($namespace ? $namespace . ':' : '') . $element, (string) $value);
197
        } else {
198 2
            if (isset($value['_namespace'])) {
199 2
                $this->addElement($value['_element'], $value[$value['_element']], $value['_namespace']);
200
            } else {
201 2
                $this->addElementArray($element, $value, $namespace);
202
            }
203
        }
204 2
    }
205
206
    /**
207
     * @param string      $element
208
     * @param mixed       $value
209
     * @param null|string $namespace
210
     */
211 2
    private function addElementArray(string $element, $value, ?string $namespace = null): void
212
    {
213 2
        if (!$this->isAssoc($value)) {
214 2
            if (!empty($value)) {
215 2
                $this->addElementArrayNonAssoc($element, $value, $namespace);
216
            } else {
217
                /* @var \XMLWriter $XMLWriter */
218
                $XMLWriter = $this->getXMLWriter();
219 2
                $XMLWriter->writeElement(($namespace ? $namespace . ':' : '') . $element);
220
            }
221
        } else {
222 2
            $this->addElementArrayAssoc($element, $value, $namespace);
223
        }
224 2
    }
225
226 2
    private function addElementArrayAssoc(string $element, $value, ?string $namespace = null): void
227
    {
228
        /* @var \XMLWriter $XMLWriter */
229 2
        $XMLWriter = $this->getXMLWriter();
230 2
        $XMLWriter->startElement(($namespace ? $namespace . ':' : '') . $element);
231
232 2
        if (isset($value['_attributes'])) {
233 2
            foreach ($value['_attributes'] as $attribute => $val) {
234 2
                $XMLWriter->writeAttribute($attribute, $val);
235
            }
236
237 2
            if (isset($value['_value'])) {
238 2
                if (is_array($value['_value'])) {
239
                    foreach ($value['_value'] as $el => $val) {
240
                        $this->addElement($el, $val);
241
                    }
242
                } else {
243 2
                    $XMLWriter->text((string) $value['_value']);
244
                }
245
            }
246
        } else {
247 2
            foreach ($value as $el => $val) {
248 2
                if (is_array($val)) {
249 2
                    $this->addElement($el, $val, $namespace);
250
                } else {
251 2
                    $XMLWriter->writeElement(($namespace ? $namespace . ':' : '') . $el, (string) $val);
252
                }
253
            }
254
        }
255
256 2
        $XMLWriter->endElement();
257 2
    }
258
259
    /**
260
     * @param string      $element
261
     * @param mixed       $value
262
     * @param null|string $namespace
263
     */
264 2
    private function addElementArrayNonAssoc(string $element, $value, ?string $namespace = null): void
265
    {
266 2
        foreach ($value as $val) {
267 2
            $this->addElement($element, $val, $namespace);
268
        }
269 2
    }
270
}
271