RenderGzipFileStream   A
last analyzed

Complexity

Total Complexity 16

Size/Duplication

Total Lines 155
Duplicated Lines 38.71 %

Coupling/Cohesion

Components 1
Dependencies 7

Test Coverage

Coverage 92.45%

Importance

Changes 0
Metric Value
wmc 16
lcom 1
cbo 7
dl 60
loc 155
ccs 49
cts 53
cp 0.9245
rs 10
c 0
b 0
f 0

7 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 11 4
A getFilename() 0 4 1
A open() 23 23 3
A close() 17 17 2
A push() 20 20 4
A count() 0 4 1
A write() 0 5 1

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

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\CompressionLevelException;
14
use GpsLab\Component\Sitemap\Stream\Exception\FileAccessException;
15
use GpsLab\Component\Sitemap\Stream\Exception\LinksOverflowException;
16
use GpsLab\Component\Sitemap\Stream\Exception\SizeOverflowException;
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 RenderGzipFileStream implements FileStream
22
{
23
    /**
24
     * @var SitemapRender
25
     */
26
    private $render;
27
28
    /**
29
     * @var StreamState
30
     */
31
    private $state;
32
33
    /**
34
     * @var resource|null
35
     */
36
    private $handle;
37
38
    /**
39
     * @var string
40
     */
41
    private $filename = '';
42
43
    /**
44
     * @var string
45
     */
46
    private $tmp_filename = '';
47
48
    /**
49
     * @var int
50
     */
51
    private $compression_level = 9;
52
53
    /**
54
     * @var int
55
     */
56
    private $counter = 0;
57
58
    /**
59
     * @var string
60
     */
61
    private $end_string = '';
62
63
    /**
64
     * @var int
65
     */
66
    private $used_bytes = 0;
67
68
    /**
69
     * @param SitemapRender $render
70
     * @param string        $filename
71
     * @param int           $compression_level
72
     */
73 15
    public function __construct(SitemapRender $render, $filename, $compression_level = 9)
74
    {
75 15
        if (!is_numeric($compression_level) || $compression_level < 1 || $compression_level > 9) {
76 4
            throw CompressionLevelException::invalid($compression_level, 1, 9);
77
        }
78
79 15
        $this->render = $render;
80 15
        $this->state = new StreamState();
81 15
        $this->filename = $filename;
82 15
        $this->compression_level = $compression_level;
83 15
    }
84
85
    /**
86
     * @return string
87
     */
88 1
    public function getFilename()
89
    {
90 1
        return $this->filename;
91
    }
92
93 8 View Code Duplication
    public function open()
94
    {
95 8
        $this->state->open();
96
97 8
        $tmp_filename = tempnam(sys_get_temp_dir(), 'sitemap');
98
99 8
        if ($tmp_filename === false) {
100
            throw FileAccessException::failedCreateUnique(sys_get_temp_dir(), 'sitemap');
101
        }
102
103 8
        $handle = @gzopen($tmp_filename, 'wb'.$this->compression_level);
104
105 8
        if ($handle === false) {
106
            throw FileAccessException::notWritable($tmp_filename);
107
        }
108
109 8
        $this->tmp_filename = $tmp_filename;
110 8
        $this->handle = $handle;
111
112 8
        $this->write($this->render->start());
113
        // render end string only once
114 8
        $this->end_string = $this->render->end();
115 8
    }
116
117 15 View Code Duplication
    public function close()
118
    {
119 15
        $this->state->close();
120 8
        $this->write($this->end_string);
121 8
        gzclose($this->handle);
122
123 8
        if (!rename($this->tmp_filename, $this->filename)) {
124
            unlink($this->tmp_filename);
125
126
            throw FileAccessException::failedOverwrite($this->tmp_filename, $this->filename);
127
        }
128
129 8
        $this->handle = null;
130 8
        $this->tmp_filename = '';
131 8
        $this->counter = 0;
132 8
        $this->used_bytes = 0;
133 8
    }
134
135
    /**
136
     * @param Url $url
137
     */
138 6 View Code Duplication
    public function push(Url $url)
139
    {
140 6
        if (!$this->state->isReady()) {
141 2
            throw StreamStateException::notReady();
142
        }
143
144 4
        if ($this->counter >= self::LINKS_LIMIT) {
145 1
            throw LinksOverflowException::withLimit(self::LINKS_LIMIT);
146
        }
147
148 4
        $render_url = $this->render->url($url);
149
150 4
        $expected_bytes = $this->used_bytes + strlen($render_url) + strlen($this->end_string);
151 4
        if ($expected_bytes > self::BYTE_LIMIT) {
152 1
            throw SizeOverflowException::withLimit(self::BYTE_LIMIT);
153
        }
154
155 4
        $this->write($render_url);
156 4
        ++$this->counter;
157 4
    }
158
159
    /**
160
     * @return int
161
     */
162 2
    public function count()
163
    {
164 2
        return $this->counter;
165
    }
166
167
    /**
168
     * @param string $string
169
     */
170 8
    private function write($string)
171
    {
172 8
        gzwrite($this->handle, $string);
173 8
        $this->used_bytes += strlen($string);
174 8
    }
175
}
176