Completed
Pull Request — master (#89)
by Peter
05:26 queued 30s
created

RenderFileStream   A

Complexity

Total Complexity 13

Size/Duplication

Total Lines 144
Duplicated Lines 41.67 %

Coupling/Cohesion

Components 1
Dependencies 6

Test Coverage

Coverage 92%

Importance

Changes 0
Metric Value
wmc 13
lcom 1
cbo 6
dl 60
loc 144
ccs 46
cts 50
cp 0.92
rs 10
c 0
b 0
f 0

7 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 6 1
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\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 RenderFileStream 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 22
    public function __construct(SitemapRender $render, $filename)
67
    {
68 22
        $this->render = $render;
69 22
        $this->state = new StreamState();
70 22
        $this->filename = $filename;
71 22
    }
72
73
    /**
74
     * @return string
75
     */
76 9
    public function getFilename()
77
    {
78 9
        return $this->filename;
79
    }
80
81 16 View Code Duplication
    public function open()
82
    {
83 16
        $this->state->open();
84
85 16
        $tmp_filename = tempnam(sys_get_temp_dir(), 'sitemap');
86
87 16
        if ($tmp_filename === false) {
88
            throw FileAccessException::failedCreateUnique(sys_get_temp_dir(), 'sitemap');
89
        }
90
91 16
        $handle = @fopen($tmp_filename, 'wb');
92
93 16
        if ($handle === false) {
94
            throw FileAccessException::notWritable($tmp_filename);
95
        }
96
97 16
        $this->tmp_filename = $tmp_filename;
98 16
        $this->handle = $handle;
99
100 16
        $this->write($this->render->start());
101
        // render end string only once
102 16
        $this->end_string = $this->render->end();
103 16
    }
104
105 19 View Code Duplication
    public function close()
106
    {
107 19
        $this->state->close();
108 16
        $this->write($this->end_string);
109 16
        fclose($this->handle);
110
111 16
        if (!rename($this->tmp_filename, $this->filename)) {
112
            unlink($this->tmp_filename);
113
114
            throw FileAccessException::failedOverwrite($this->tmp_filename, $this->filename);
115
        }
116
117 16
        $this->handle = null;
118 16
        $this->tmp_filename = '';
119 16
        $this->counter = 0;
120 16
        $this->used_bytes = 0;
121 16
    }
122
123
    /**
124
     * @param Url $url
125
     */
126 10 View Code Duplication
    public function push(Url $url)
127
    {
128 10
        if (!$this->state->isReady()) {
129 2
            throw StreamStateException::notReady();
130
        }
131
132 8
        if ($this->counter >= self::LINKS_LIMIT) {
133 2
            throw LinksOverflowException::withLimit(self::LINKS_LIMIT);
134
        }
135
136 8
        $render_url = $this->render->url($url);
137
138 8
        $expected_bytes = $this->used_bytes + strlen($render_url) + strlen($this->end_string);
139 8
        if ($expected_bytes > self::BYTE_LIMIT) {
140 1
            throw SizeOverflowException::withLimit(self::BYTE_LIMIT);
141
        }
142
143 8
        $this->write($render_url);
144 8
        ++$this->counter;
145 8
    }
146
147
    /**
148
     * @return int
149
     */
150 2
    public function count()
151
    {
152 2
        return $this->counter;
153
    }
154
155
    /**
156
     * @param string $string
157
     */
158 16
    private function write($string)
159
    {
160 16
        fwrite($this->handle, $string);
161 16
        $this->used_bytes += strlen($string);
162 16
    }
163
}
164