OutputXMLWriter   A
last analyzed

Complexity

Total Complexity 33

Size/Duplication

Total Lines 235
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
eloc 84
c 0
b 0
f 0
dl 0
loc 235
ccs 101
cts 101
cp 1
rs 9.76
wmc 33

13 Methods

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