Completed
Pull Request — master (#13)
by Peter
03:28
created

CallbackStream::push()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 20

Duplication

Lines 20
Ratio 100 %

Code Coverage

Tests 12
CRAP Score 4

Importance

Changes 0
Metric Value
dl 20
loc 20
ccs 12
cts 12
cp 1
rs 9.6
c 0
b 0
f 0
cc 4
nc 4
nop 1
crap 4
1
<?php
2
declare(strict_types=1);
3
4
/**
5
 * Lupin package.
6
 *
7
 * @author    Peter Gribanov <[email protected]>
8
 * @copyright Copyright (c) 2011, Peter Gribanov
9
 */
10
11
namespace GpsLab\Component\Sitemap\Stream;
12
13
use GpsLab\Component\Sitemap\Render\SitemapRender;
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 CallbackStream implements Stream
21
{
22
    /**
23
     * @var SitemapRender
24
     */
25
    private $render;
26
27
    /**
28
     * @var callable
29
     */
30
    private $callback;
31
32
    /**
33
     * @var StreamState
34
     */
35
    private $state;
36
37
    /**
38
     * @var int
39
     */
40
    private $counter = 0;
41
42
    /**
43
     * @var int
44
     */
45
    private $used_bytes = 0;
46
47
    /**
48
     * @var string
49
     */
50
    private $end_string = '';
51
52
    /**
53
     * @param SitemapRender $render
54
     * @param callable      $callback
55
     */
56 9
    public function __construct(SitemapRender $render, callable $callback)
57
    {
58 9
        $this->render = $render;
59 9
        $this->callback = $callback;
60 9
        $this->state = new StreamState();
61 9
    }
62
63 7
    public function open(): void
64
    {
65 7
        $this->state->open();
66 7
        $this->send($this->render->start());
67
        // render end string only once
68 7
        $this->end_string = $this->render->end();
69 7
    }
70
71 8
    public function close(): void
72
    {
73 8
        $this->state->close();
74 7
        $this->send($this->end_string);
75 7
        $this->counter = 0;
76 7
        $this->used_bytes = 0;
77 7
    }
78
79
    /**
80
     * @param Url $url
81
     */
82 5 View Code Duplication
    public function push(Url $url): void
83
    {
84 5
        if (!$this->state->isReady()) {
85 2
            throw StreamStateException::notReady();
86
        }
87
88 3
        if ($this->counter >= self::LINKS_LIMIT) {
89 1
            throw LinksOverflowException::withLimit(self::LINKS_LIMIT);
90
        }
91
92 3
        $render_url = $this->render->url($url);
93 3
        $expected_bytes = $this->used_bytes + strlen($render_url) + strlen($this->end_string);
94
95 3
        if ($expected_bytes > self::BYTE_LIMIT) {
96 1
            throw SizeOverflowException::withLimit(self::BYTE_LIMIT);
97
        }
98
99 3
        $this->send($render_url);
100 3
        ++$this->counter;
101 3
    }
102
103
    /**
104
     * @param string $content
105
     */
106 7
    private function send(string $content): void
107
    {
108 7
        call_user_func($this->callback, $content);
109 7
        $this->used_bytes += strlen($content);
110 7
    }
111
}
112