Passed
Pull Request — master (#35)
by Evgeniy
02:19
created

FragmentCache::dependency()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
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 4
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 RuntimeException;
8
use Yiisoft\Cache\CacheInterface;
9
use Yiisoft\Cache\Dependency\Dependency;
10
use Yiisoft\View\Cache\CachedContent;
11
use Yiisoft\View\Cache\DynamicContent;
12
use Yiisoft\Widget\Widget;
13
14
use function ob_end_clean;
15
use function ob_get_clean;
16
use function ob_implicit_flush;
17
use function ob_start;
18
19
/**
20
 * FragmentCache caches a fragment of content.
21
 *
22
 * @see CachedContent
23
 * @see DynamicContent
24
 *
25
 * Example of use:
26
 *
27
 * ```php
28
 * $dynamicContent = new Yiisoft\View\Cache\DynamicContent('dynamic-id', static function (array $parameters): string {
29
 *     return strtoupper("{$parameters['a']} - {$parameters['b']}");
30
 * }, ['a' => 'string-a', 'b' => 'string-b']);
31
 *
32
 * FragmentCache::widget()->id('cache-id')->ttl(30)->dynamicContents($dynamicContent)->begin();
33
 *     echo 'Content to be cached ...';
34
 *     echo $dynamicContent->placeholder();
35
 *     echo 'Content to be cached ...';
36
 * FragmentCache::end();
37
 * ```
38
 */
39
final class FragmentCache extends Widget
40
{
41
    private ?string $id = null;
42
    private CacheInterface $cache;
43
    private ?Dependency $dependency = null;
44
    private int $ttl = 60;
45
    private array $variations = [];
46
47
    /**
48
     * @var array<string, DynamicContent>
49
     */
50
    private array $dynamicContents = [];
51
52 6
    public function __construct(CacheInterface $cache)
53
    {
54 6
        $this->cache = $cache;
55 6
    }
56
57
    /**
58
     * Initializes the FragmentCache object.
59
     */
60 6
    public function begin(): ?string
61
    {
62 6
        if ($this->id === null) {
63 1
            throw new RuntimeException('You must assign the "id" using the "id()" setter.');
64
        }
65
66 5
        parent::begin();
67 5
        ob_start();
68 5
        PHP_VERSION_ID >= 80000 ? ob_implicit_flush(false) : ob_implicit_flush(0);
69 5
        return null;
70
    }
71
72
    /**
73
     * Marks the end of content to be cached.
74
     *
75
     * Content displayed before this method call and after {@see init()} will be captured and saved in cache.
76
     *
77
     * This method does nothing if valid content is already found in cache.
78
     *
79
     * @return string The result of widget execution to be outputted.
80
     */
81 5
    protected function run(): string
82
    {
83 5
        $cachedContent = new CachedContent($this->id, $this->cache, $this->dynamicContents, $this->variations);
0 ignored issues
show
Bug introduced by
It seems like $this->id can also be of type null; however, parameter $id of Yiisoft\View\Cache\CachedContent::__construct() 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

83
        $cachedContent = new CachedContent(/** @scrutinizer ignore-type */ $this->id, $this->cache, $this->dynamicContents, $this->variations);
Loading history...
84 5
        $content = $cachedContent->get();
85
86 5
        if ($content !== null) {
87 4
            ob_end_clean();
88 4
            return $content;
89
        }
90
91 5
        $content = ob_get_clean();
92
93 5
        if ($content === false || $content === '') {
94
            return '';
95
        }
96
97 5
        return $cachedContent->cache($content, $this->ttl, $this->dependency);
98
    }
99
100
    /**
101
     * @param string $value The unique identifier of the cache fragment.
102
     *
103
     * @return self
104
     */
105 5
    public function id(string $value): self
106
    {
107 5
        $this->id = $value;
108 5
        return $this;
109
    }
110
111
    /**
112
     * @param Dependency $value The dependency that the cached content depends on.
113
     *
114
     * This can be either a {@see Dependency} object or a configuration array for creating the dependency object.
115
     *
116
     * Would make the output cache depends on the last modified time of all posts. If any post has its modification time
117
     * changed, the cached content would be invalidated.
118
     *
119
     * @return self
120
     */
121 1
    public function dependency(Dependency $value): self
122
    {
123 1
        $this->dependency = $value;
124 1
        return $this;
125
    }
126
127
    /**
128
     * @param int $value The number of seconds that the data can remain valid in cache.
129
     *
130
     * @return self
131
     */
132 1
    public function ttl(int $value): self
133
    {
134 1
        $this->ttl = $value;
135 1
        return $this;
136
    }
137
138
    /**
139
     * @param DynamicContent ...$value The dynamic content instances.
140
     *
141
     * @return self
142
     */
143 3
    public function dynamicContents(DynamicContent ...$value): self
144
    {
145 3
        foreach ($value as $dynamicContent) {
146 3
            $this->dynamicContents[$dynamicContent->id()] = $dynamicContent;
147
        }
148 3
        return $this;
149
    }
150
151
    /**
152
     * @param string ...$value The factors that would cause the variation of the content being cached.
153
     *
154
     * Each factor is a string representing a variation (e.g. the language, a GET parameter). The following variation
155
     * setting will cause the content to be cached in different versions according to the current application language:
156
     *
157
     * ```php
158
     * $fragmentCache->variations('en');
159
     * ```
160
     *
161
     * @return self
162
     */
163 1
    public function variations(string ...$value): self
164
    {
165 1
        $this->variations = $value;
166 1
        return $this;
167
    }
168
}
169