Completed
Push — master ( 7fe6b0...d8a5ea )
by Paweł
02:19
created

XMLWriter::addElementArrayAssoc()   B

Complexity

Conditions 10
Paths 9

Size

Total Lines 27
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 13
CRAP Score 10.2368

Importance

Changes 0
Metric Value
cc 10
eloc 17
c 0
b 0
f 0
nc 9
nop 3
dl 0
loc 27
ccs 13
cts 15
cp 0.8667
crap 10.2368
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
 * @method getXMLWriter(): \XMLWriter
25
 */
26
class XMLWriter extends AbstractXML
27
{
28
    /**
29
     * XMLWriter constructor.
30
     *
31
     * @param array $config
32
     *
33
     * @throws \InvalidArgumentException
34
     */
35 18
    public function __construct(array $config)
36
    {
37 18
        if (!isset($config['domain'])) {
38 2
            throw new \InvalidArgumentException('Domain is not set.');
39
        }
40
41 18
        $this->XMLWriter = new \XMLWriter();
42 18
        $this->setDomain($config['domain']);
43 18
    }
44
45
    /**
46
     * @param string $sitemap
47
     * @param array  $extensions
48
     */
49 4
    public function openSitemap(string $sitemap, array $extensions = []): void
50
    {
51 4
        $this->setCurrentSitemap($sitemap);
52 4
        $this->getXMLWriter()->openMemory();
53 4
        $this->getXMLWriter()->startDocument('1.0', 'UTF-8');
54 4
        $this->getXMLWriter()->setIndent(true);
55 4
        $this->getXMLWriter()->startElement('urlset');
56 4
        $this->getXMLWriter()->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 4
        $this->getXMLWriter()->endElement();
71 4
        $this->getXMLWriter()->endDocument();
72 4
        $this->flushData();
73 4
        $this->endFile();
74 4
    }
75
76
    /**
77
     * @return int
78
     */
79 6
    public function getSitemapSize(): int
80
    {
81 6
        clearstatcache(true, $this->getSitemapFileFullPath());
82
83 6
        return file_exists($this->getSitemapFileFullPath()) ? filesize($this->getSitemapFileFullPath()) : 0;
84
    }
85
86
    /**
87
     * @param array $element
88
     */
89 2
    public function addUrl(array $element): void
90
    {
91 2
        foreach ($element as $el => $val) {
92 2
            $this->addElement($el, $val);
93
        }
94
95 2
        $this->flushData();
96 2
    }
97
98
    /**
99
     * @param string $sitemap
100
     */
101 2
    public function openSitemapIndex(string $sitemap): void
102
    {
103 2
        $this->setCurrentSitemap($sitemap);
104 2
        $this->getXMLWriter()->openMemory();
105 2
        $this->getXMLWriter()->startDocument('1.0', 'UTF-8');
106 2
        $this->getXMLWriter()->setIndent(true);
107 2
        $this->getXMLWriter()->startElement('sitemapindex');
108 2
        $this->getXMLWriter()->writeAttribute('xmlns', Sitemap::SCHEMA);
109 2
        $this->flushData();
110 2
    }
111
112
    /**
113
     * @throws \Exception
114
     */
115 2
    public function closeSitemapIndex(): void
116
    {
117 2
        $this->getXMLWriter()->endElement();
118 2
        $this->getXMLWriter()->endDocument();
119 2
        $this->flushData();
120 2
        $this->endFile();
121 2
    }
122
123
    /**
124
     * @param string      $sitemap
125
     * @param null|string $lastmod
126
     */
127 2
    public function addSitemap(string $sitemap, string $lastmod = null): void
128
    {
129 2
        $this->getXMLWriter()->startElement('sitemap');
130 2
        $this->getXMLWriter()->writeElement('loc', $sitemap);
131 2
        if (isset($lastmod)) {
132 2
            $this->getXMLWriter()->writeElement('lastmod', $lastmod);
133
        }
134 2
        $this->getXMLWriter()->endElement();
135 2
        $this->flushData();
136 2
    }
137
138
    /**
139
     * Save from buffer to file.
140
     *
141
     * @return void
142
     */
143 6
    private function flushData(): void
144
    {
145 6
        file_put_contents($this->getSitemapFileFullPath(), $this->getXMLWriter()->flush(true), FILE_APPEND);
146 6
    }
147
148
    /**
149
     * Remove whitespace chars from end of file (Google don't like them).
150
     *
151
     * @throws Exception
152
     *
153
     * @return void
154
     */
155 6
    private function endFile(): void
156
    {
157 6
        $sitemapFile = fopen($this->getSitemapFileFullPath(), 'r+');
158
159 6
        fseek($sitemapFile, -1, SEEK_END);
0 ignored issues
show
Bug introduced by
It seems like $sitemapFile can also be of type false; however, parameter $handle of fseek() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

159
        fseek(/** @scrutinizer ignore-type */ $sitemapFile, -1, SEEK_END);
Loading history...
160 6
        $truncate = 0;
161 6
        $length = $this->getSitemapSize();
162 6
        $end = false;
163
164
        do {
165 6
            $s = fread($sitemapFile, 1);
0 ignored issues
show
Bug introduced by
It seems like $sitemapFile can also be of type false; however, parameter $handle of fread() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

165
            $s = fread(/** @scrutinizer ignore-type */ $sitemapFile, 1);
Loading history...
166 6
            if (ctype_space($s)) {
167 6
                ++$truncate;
168 6
                fseek($sitemapFile, -2, SEEK_CUR);
169
            } else {
170 6
                $end = true;
171
            }
172 6
        } while (!$end);
173
174 6
        ftruncate($sitemapFile, $length - $truncate);
0 ignored issues
show
Bug introduced by
It seems like $sitemapFile can also be of type false; however, parameter $handle of ftruncate() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

174
        ftruncate(/** @scrutinizer ignore-type */ $sitemapFile, $length - $truncate);
Loading history...
175 6
        fclose($sitemapFile);
0 ignored issues
show
Bug introduced by
It seems like $sitemapFile can also be of type false; however, parameter $handle of fclose() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

175
        fclose(/** @scrutinizer ignore-type */ $sitemapFile);
Loading history...
176 6
    }
177
178
    /**
179
     * @param string      $element
180
     * @param             $value
181
     * @param null|string $namespace
182
     */
183 2
    private function addElement(string $element, $value, ?string $namespace = null): void
184
    {
185 2
        if (!is_array($value)) {
186 2
            $this->getXMLWriter()->writeElement(($namespace ? $namespace . ':' : '') . $element, (string) $value);
187
        } else {
188 2
            if (isset($value['_namespace'])) {
189 2
                $this->addElement($value['_element'], $value[$value['_element']], $value['_namespace']);
190
            } else {
191 2
                $this->addElementArray($element, $value, $namespace);
192
            }
193
        }
194 2
    }
195
196
    /**
197
     * @param string      $element
198
     * @param             $value
199
     * @param null|string $namespace
200
     */
201 2
    private function addElementArray(string $element, $value, ?string $namespace = null): void
202
    {
203 2
        if (!$this->isAssoc($value)) {
204 2
            if (!empty($value)) {
205 2
                $this->addElementArrayNonAssoc($element, $value, $namespace);
206
            } else {
207 2
                $this->getXMLWriter()->writeElement(($namespace ? $namespace . ':' : '') . $element);
208
            }
209
        } else {
210 2
            $this->addElementArrayAssoc($element, $value, $namespace);
211
        }
212 2
    }
213
214 2
    private function addElementArrayAssoc(string $element, $value, ?string $namespace = null): void
215
    {
216 2
        $this->getXMLWriter()->startElement(($namespace ? $namespace . ':' : '') . $element);
217 2
        if (isset($value['_attributes'])) {
218 2
            foreach ($value['_attributes'] as $attribute => $val) {
219 2
                $this->getXMLWriter()->writeAttribute($attribute, $val);
220
            }
221
222 2
            if (isset($value['_value'])) {
223 2
                if (is_array($value['_value'])) {
224
                    foreach ($value['_value'] as $el => $val) {
225
                        $this->addElement($el, $val);
226
                    }
227
                } else {
228 2
                    $this->getXMLWriter()->text((string) $value['_value']);
229
                }
230
            }
231
        } else {
232 2
            foreach ($value as $el => $val) {
233 2
                if (is_array($val)) {
234 2
                    $this->addElement($el, $val, $namespace);
235
                } else {
236 2
                    $this->getXMLWriter()->writeElement(($namespace ? $namespace . ':' : '') . $el, (string) $val);
237
                }
238
            }
239
        }
240 2
        $this->getXMLWriter()->endElement();
241 2
    }
242
243
    /**
244
     * @param string      $element
245
     * @param             $value
246
     * @param null|string $namespace
247
     */
248 2
    private function addElementArrayNonAssoc(string $element, $value, ?string $namespace = null): void
249
    {
250 2
        foreach ($value as $val) {
251 2
            $this->addElement($element, $val, $namespace);
252
        }
253 2
    }
254
}
255