Passed
Pull Request — master (#10)
by Wilmer
13:55 queued 27s
created

FragmentCache::getCachedContent()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 15
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 7
c 1
b 0
f 0
nc 2
nop 0
dl 0
loc 15
ccs 3
cts 3
cp 1
crap 2
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
        if ($this->getCachedContent() !== null) {
62
            return $this->getCachedContent();
63
        }
64
65
        $this->webView->popDynamicContent();
66
67
        $content = ob_get_clean();
68
69
        if ($content === false || $content === '') {
70
            return '';
71 5
        }
72
73 5
        $data = [$content, $this->getDynamicPlaceholders()];
74 5
75 5
        $this->cache->set($this->calculateKey(), $data, $this->duration, $this->dependency);
76
77
        return $this->updateDynamicContent($content, $this->getDynamicPlaceholders());
78
    }
79
80 5
    /**
81
     * Returns the cached content if available.
82 5
     *
83 5
     * @return string|null the cached content. False is returned if valid content is not found in the cache.
84 5
     */
85 5
    public function getCachedContent(): ?string
86
    {
87 5
        $key = $this->calculateKey();
88
89
        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

89
        if (!$this->cache->has(/** @scrutinizer ignore-type */ $key)) {
Loading history...
90
            return null;
91
        }
92
93
        $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

93
        $data = $this->cache->get(/** @scrutinizer ignore-type */ $key);
Loading history...
94
95
        [$this->content, $placeholders] = $data;
96
97
        $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

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