Completed
Pull Request — master (#13)
by Peter
03:22 queued 54s
created

RenderIndexFileStream   A

Complexity

Total Complexity 12

Size/Duplication

Total Lines 124
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 3

Test Coverage

Coverage 95.12%

Importance

Changes 0
Metric Value
wmc 12
lcom 1
cbo 3
dl 0
loc 124
ccs 39
cts 41
cp 0.9512
rs 10
c 0
b 0
f 0

7 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 7 1
A getFilename() 0 4 1
A open() 0 6 1
A close() 0 8 1
A push() 0 13 3
A addSubStreamFileToIndex() 0 20 4
A getIndexPartFilename() 0 10 1
1
<?php
2
declare(strict_types=1);
3
4
/**
5
 * GpsLab component.
6
 *
7
 * @author    Peter Gribanov <[email protected]>
8
 * @copyright Copyright (c) 2011, Peter Gribanov
9
 * @license   http://opensource.org/licenses/MIT
10
 */
11
12
namespace GpsLab\Component\Sitemap\Stream;
13
14
use GpsLab\Component\Sitemap\Render\SitemapIndexRender;
15
use GpsLab\Component\Sitemap\Stream\Exception\IndexStreamException;
16
use GpsLab\Component\Sitemap\Stream\Exception\OverflowException;
17
use GpsLab\Component\Sitemap\Stream\Exception\StreamStateException;
18
use GpsLab\Component\Sitemap\Stream\State\StreamState;
19
use GpsLab\Component\Sitemap\Url\Url;
20
21
class RenderIndexFileStream implements FileStream
22
{
23
    /**
24
     * @var SitemapIndexRender
25
     */
26
    private $render;
27
28
    /**
29
     * @var FileStream
30
     */
31
    private $substream;
32
33
    /**
34
     * @var StreamState
35
     */
36
    private $state;
37
38
    /**
39
     * @var string
40
     */
41
    private $filename = '';
42
43
    /**
44
     * @var int
45
     */
46
    private $index = 0;
47
48
    /**
49
     * @var string
50
     */
51
    private $buffer = '';
52
53
    /**
54
     * @param SitemapIndexRender $render
55
     * @param FileStream         $substream
56
     * @param string             $filename
57
     */
58 10
    public function __construct(SitemapIndexRender $render, FileStream $substream, string $filename)
59
    {
60 10
        $this->render = $render;
61 10
        $this->substream = $substream;
62 10
        $this->filename = $filename;
63 10
        $this->state = new StreamState();
64 10
    }
65
66
    /**
67
     * @return string
68
     */
69 1
    public function getFilename(): string
70
    {
71 1
        return $this->filename;
72
    }
73
74 7
    public function open(): void
75
    {
76 7
        $this->state->open();
77 7
        $this->substream->open();
78 7
        $this->buffer = $this->render->start();
79 7
    }
80
81 8
    public function close(): void
82
    {
83 8
        $this->state->close();
84 7
        $this->addSubStreamFileToIndex();
85
86 7
        file_put_contents($this->filename, $this->buffer.$this->render->end());
87 7
        $this->buffer = '';
88 7
    }
89
90
    /**
91
     * @param Url $url
92
     */
93 4
    public function push(Url $url): void
94
    {
95 4
        if (!$this->state->isReady()) {
96 2
            throw StreamStateException::notReady();
97
        }
98
99
        try {
100 2
            $this->substream->push($url);
101 1
        } catch (OverflowException $e) {
102 1
            $this->addSubStreamFileToIndex();
103 1
            $this->substream->open();
104
        }
105 2
    }
106
107 7
    private function addSubStreamFileToIndex(): void
108
    {
109 7
        $this->substream->close();
110
111 7
        $filename = $this->substream->getFilename();
112 7
        $indexed_filename = $this->getIndexPartFilename($filename, ++$this->index);
113
114 7
        if (!is_file($filename) || !($time = filemtime($filename))) {
115
            throw IndexStreamException::undefinedSubstreamFile($filename);
116
        }
117
118 7
        $last_mod = (new \DateTimeImmutable())->setTimestamp($time);
119
120
        // rename sitemap file to the index part file
121 7
        if (!rename($filename, dirname($filename).'/'.$indexed_filename)) {
122
            throw IndexStreamException::failedRename($filename, dirname($filename).'/'.$indexed_filename);
123
        }
124
125 7
        $this->buffer .= $this->render->sitemap($indexed_filename, $last_mod);
0 ignored issues
show
Security Bug introduced by
It seems like $last_mod defined by (new \DateTimeImmutable())->setTimestamp($time) on line 118 can also be of type false; however, GpsLab\Component\Sitemap...pIndexRender::sitemap() does only seem to accept null|object<DateTimeInterface>, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
126 7
    }
127
128
    /**
129
     * @param string $filename
130
     * @param int    $index
131
     *
132
     * @return string
133
     */
134 7
    private function getIndexPartFilename(string $filename, int $index): string
135
    {
136
        // use explode() for correct add index
137
        // sitemap.xml -> sitemap1.xml
138
        // sitemap.xml.gz -> sitemap1.xml.gz
139
140 7
        list($filename, $extension) = explode('.', basename($filename), 2);
141
142 7
        return sprintf('%s%s.%s', $filename, $index, $extension);
143
    }
144
}
145