Completed
Pull Request — master (#89)
by Peter
02:19
created

RenderBzip2FileStream::close()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 17

Duplication

Lines 17
Ratio 100 %

Code Coverage

Tests 3
CRAP Score 3.6875

Importance

Changes 0
Metric Value
dl 17
loc 17
c 0
b 0
f 0
ccs 3
cts 12
cp 0.25
rs 9.7
cc 2
nc 2
nop 0
crap 3.6875
1
<?php
2
/**
3
 * GpsLab component.
4
 *
5
 * @author    Peter Gribanov <[email protected]>
6
 * @copyright Copyright (c) 2011, Peter Gribanov
7
 * @license   http://opensource.org/licenses/MIT
8
 */
9
10
namespace GpsLab\Component\Sitemap\Stream;
11
12
use GpsLab\Component\Sitemap\Render\SitemapRender;
13
use GpsLab\Component\Sitemap\Stream\Exception\FileAccessException;
14
use GpsLab\Component\Sitemap\Stream\Exception\LinksOverflowException;
15
use GpsLab\Component\Sitemap\Stream\Exception\SizeOverflowException;
16
use GpsLab\Component\Sitemap\Stream\Exception\StreamStateException;
17
use GpsLab\Component\Sitemap\Stream\State\StreamState;
18
use GpsLab\Component\Sitemap\Url\Url;
19
20
class RenderBzip2FileStream implements FileStream
21
{
22
    /**
23
     * @var SitemapRender
24
     */
25
    private $render;
26
27
    /**
28
     * @var StreamState
29
     */
30
    private $state;
31
32
    /**
33
     * @var resource|null
34
     */
35
    private $handle;
36
37
    /**
38
     * @var string
39
     */
40
    private $filename;
41
42
    /**
43
     * @var string
44
     */
45
    private $tmp_filename = '';
46
47
    /**
48
     * @var int
49
     */
50
    private $counter = 0;
51
52
    /**
53
     * @var string
54
     */
55
    private $end_string = '';
56
57
    /**
58
     * @var int
59
     */
60
    private $used_bytes = 0;
61
62
    /**
63
     * @param SitemapRender $render
64
     * @param string        $filename
65
     */
66 11
    public function __construct(SitemapRender $render, $filename)
67
    {
68 11
        $this->render = $render;
69 11
        $this->state = new StreamState();
70 11
        $this->filename = $filename;
71 11
    }
72
73
    /**
74
     * @return string
75
     */
76 1
    public function getFilename()
77
    {
78 1
        return $this->filename;
79
    }
80
81
    /**
82
     * @return void
83
     */
84 8
    public function open()
85
    {
86 8
        $this->state->open();
87
88 8
        $tmp_filename = tempnam(sys_get_temp_dir(), 'sitemap');
89
90 8
        if ($tmp_filename === false) {
91
            throw FileAccessException::failedCreateUnique(sys_get_temp_dir(), 'sitemap');
92
        }
93
94 8
        if ((file_exists($this->filename) && !is_writable($this->filename))) {
95
            throw FileAccessException::notWritable($this->filename);
96
        }
97
98 8
        $handle = @bzopen($this->tmp_filename, 'w');
99
100 8
        if ($handle === false) {
101 8
            throw FileAccessException::notWritable($this->filename);
102
        }
103
104
        $this->tmp_filename = $tmp_filename;
105
        $this->handle = $handle;
106
107
        $this->write($this->render->start());
108
        // render end string only once
109
        $this->end_string = $this->render->end();
110
    }
111
112
    /**
113
     * @return void
114
     */
115 11 View Code Duplication
    public function close()
116
    {
117 11
        $this->state->close();
118 8
        $this->write($this->end_string);
119
        bzclose($this->handle);
120
121
        if (!rename($this->tmp_filename, $this->filename)) {
122
            unlink($this->tmp_filename);
123
124
            throw FileAccessException::failedOverwrite($this->tmp_filename, $this->filename);
125
        }
126
127
        $this->handle = null;
128
        $this->tmp_filename = '';
129
        $this->counter = 0;
130
        $this->used_bytes = 0;
131
    }
132
133
    /**
134
     * @param Url $url
135
     *
136
     * @return void
137
     */
138 1 View Code Duplication
    public function push(Url $url)
139
    {
140 1
        if (!$this->state->isReady()) {
141 1
            throw StreamStateException::notReady();
142
        }
143
144
        if ($this->counter >= self::LINKS_LIMIT) {
145
            throw LinksOverflowException::withLimit(self::LINKS_LIMIT);
146
        }
147
148
        $render_url = $this->render->url($url);
149
150
        $expected_bytes = $this->used_bytes + strlen($render_url) + strlen($this->end_string);
151
        if ($expected_bytes > self::BYTE_LIMIT) {
152
            throw SizeOverflowException::withLimit(self::BYTE_LIMIT);
153
        }
154
155
        $this->write($render_url);
156
        ++$this->counter;
157
    }
158
159
    /**
160
     * @return int
161
     */
162
    public function count()
163
    {
164
        return $this->counter;
165
    }
166
167
    /**
168
     * @param string $string
169
     *
170
     * @return void
171
     */
172 8
    private function write($string)
173
    {
174 8
        bzwrite($this->handle, $string);
175
        $this->used_bytes += strlen($string);
176
    }
177
}
178