Passed
Pull Request — master (#10)
by Wilmer
18:39 queued 03:39
created

FragmentCache::content()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 2
c 1
b 0
f 0
nc 1
nop 1
dl 0
loc 5
ccs 3
cts 3
cp 1
crap 1
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Yii\Widgets;
6
7
use Yiisoft\Cache\CacheInterface;
8
use Yiisoft\Cache\Dependency\Dependency;
9
use Yiisoft\View\DynamicContentAwareInterface;
10
use Yiisoft\View\DynamicContentAwareTrait;
11
use Yiisoft\View\WebView;
12
use Yiisoft\Widget\Widget;
13
14
use function array_merge;
15
use function ob_get_clean;
16
use function ob_implicit_flush;
17
use function ob_start;
18
19
final class FragmentCache extends Widget implements DynamicContentAwareInterface
20
{
21
    use DynamicContentAwareTrait;
22
23
    private string $id;
24
    private CacheInterface $cache;
25
    private int $duration = 60;
26
    private ?Dependency $dependency = null;
27
    private $variations;
28
    private ?string $content = null;
29
30
    private WebView $webView;
31
32
    public function __construct(CacheInterface $cache, WebView $webview)
33
    {
34
        $this->cache = $cache;
35
        $this->webView = $webview;
36
    }
37
38
    /**
39
     * Initializes the FragmentCache object.
40
     */
41
    public function start(): void
42
    {
43
        if ($this->getCachedContent() === null) {
44
            $this->webView->pushDynamicContent($this);
45
            ob_start();
46
            PHP_VERSION_ID >= 80000 ? ob_implicit_flush(false) : ob_implicit_flush(0);
0 ignored issues
show
Bug introduced by
false of type false is incompatible with the type integer expected by parameter $flag of ob_implicit_flush(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

46
            PHP_VERSION_ID >= 80000 ? ob_implicit_flush(/** @scrutinizer ignore-type */ false) : ob_implicit_flush(0);
Loading history...
47
        }
48
    }
49
50
    /**
51
     * Marks the end of content to be cached.
52
     *
53
     * Content displayed before this method call and after {@see init()} will be captured and saved in cache.
54
     *
55
     * This method does nothing if valid content is already found in cache.
56
     *
57
     * @return string the result of widget execution to be outputted.
58
     */
59
    public function run(): string
60
    {
61
        $content = $this->getCachedContent();
62
63
        if ($content !== null) {
64
            return $content;
65
        }
66
67
        $this->webView->popDynamicContent();
68
69
        $content = ob_get_clean();
70
71 5
        if ($content === false || $content === '') {
72
            return '';
73 5
        }
74 5
75 5
        $data = [$content, $this->getDynamicPlaceholders()];
76
77
        $this->cache->set($this->calculateKey(), $data, $this->duration, $this->dependency);
78
79
        return $this->updateDynamicContent($content, $this->getDynamicPlaceholders());
80 5
    }
81
82 5
    /**
83 5
     * Returns the cached content if available.
84 5
     *
85 5
     * @return string|null the cached content. False is returned if valid content is not found in the cache.
86
     */
87 5
    public function getCachedContent(): ?string
88
    {
89
        $key = $this->calculateKey();
90
91
        if (!$this->cache->has($key)) {
0 ignored issues
show
Bug introduced by
$key of type array is incompatible with the type string expected by parameter $key of Psr\SimpleCache\CacheInterface::has(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

91
        if (!$this->cache->has(/** @scrutinizer ignore-type */ $key)) {
Loading history...
92
            return null;
93
        }
94
95
        $data = $this->cache->get($key);
0 ignored issues
show
Bug introduced by
$key of type array is incompatible with the type string expected by parameter $key of Psr\SimpleCache\CacheInterface::get(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

95
        $data = $this->cache->get(/** @scrutinizer ignore-type */ $key);
Loading history...
96
97
        [$this->content, $placeholders] = $data;
98 5
99
        $this->content = $this->updateDynamicContent($this->content, $placeholders, true);
0 ignored issues
show
Bug introduced by
It seems like $this->content can also be of type null; however, parameter $content of Yiisoft\Yii\Widgets\Frag...:updateDynamicContent() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

99
        $this->content = $this->updateDynamicContent(/** @scrutinizer ignore-type */ $this->content, $placeholders, true);
Loading history...
100 5
101 4
        return $this->content;
102
    }
103
104 5
    /**
105
     * Generates a unique key used for storing the content in cache.
106 5
     *
107
     * The key generated depends on both {@see id} and {@see variations}.
108 5
     *
109
     * @return mixed a valid cache key
110
     */
111
    public function calculateKey()
112 5
    {
113 5
        return array_merge([__CLASS__, $this->id], (array) $this->variations);
114
    }
115 5
116
    /**
117
     * @param Dependency|null $value the dependency that the cached content depends on.
118
     *
119
     * This can be either a {@see Dependency} object or a configuration array for creating the dependency object.
120
     *
121
     * Would make the output cache depends on the last modified time of all posts. If any post has its modification time
122
     * changed, the cached content would be invalidated.
123 5
     *
124
     * @return $this
125 5
     */
126
    public function dependency(?Dependency $value): self
127 5
    {
128 5
        $this->dependency = $value;
129
130
        return $this;
131 4
    }
132
133 4
    /**
134
     * @param int $value number of seconds that the data can remain valid in cache.
135 4
     *
136
     * @return $this
137 4
     */
138
    public function duration(int $value): self
139
    {
140
        $this->duration = $value;
141
142
        return $this;
143
    }
144
145
    public function id(string $value): self
146
    {
147 5
        $this->id = $value;
148
149 5
        return $this;
150
    }
151
152
    /**
153
     * @param array|string $value list of factors that would cause the variation of the content being cached.
154
     *
155
     * Each factor is a string representing a variation (e.g. the language, a GET parameter). The following variation
156
     * setting will cause the content to be cached in different versions according to the current application language:
157
     *
158
     * @return $this
159 1
     */
160
    public function variations($value): self
161 1
    {
162
        $this->variations = $value;
163 1
164
        return $this;
165
    }
166
167
    protected function getView(): WebView
168
    {
169
        return $this->webView;
170
    }
171
}
172