Passed
Push — master ( a44d63...e14b35 )
by Stephen
47s queued 12s
created

ViewModel::cacheKey()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 4
nc 2
nop 0
dl 0
loc 6
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Sfneal\ViewModels;
4
5
use Illuminate\Http\Response;
6
use Illuminate\Support\Facades\View;
7
use RuntimeException;
8
use Sfneal\Caching\Traits\IsCacheable;
9
use Sfneal\Helpers\Redis\RedisCache;
10
use Sfneal\Helpers\Strings\StringHelpers;
11
use Spatie\ViewModels\ViewModel as SpatieViewModel;
12
13
abstract class ViewModel extends SpatieViewModel
14
{
15
    // todo: make more properties private and add getters/setters
16
    use IsCacheable;
17
18
    /**
19
     * @var int Time to live
20
     */
21
    public $ttl = null;
22
23
    /**
24
     * @var string|null Use manually declare redis_key (warning: can cause issues with caching)
25
     */
26
    public $redis_key = null;
27
28
    /**
29
     * View Directory Prefix.
30
     */
31
    public $prefix;
32
33
    /**
34
     * @var string|null View name
35
     */
36
    public $view = null;
37
38
    /**
39
     * Render the View.
40
     *
41
     * @return string
42
     */
43
    private function __render(): string
44
    {
45
        return View::make($this->view, $this->toArray())->render();
46
    }
47
48
    /**
49
     * Retrieve the authenticated user's ID from the session.
50
     *
51
     *  - avoid executing database query
52
     *  // todo: make this optional, we dont always want to tag cached pages by user
53
     *
54
     * @return int
55
     */
56
    private function userId(): int
57
    {
58
        try {
59
            // Find the 'login_web' session key that holds the authenticated user_id value
60
            // If there's no key containing 'login_web' the user is not logged in
61
            $session_key = collect(request()->session()->all())->keys()->filter(function ($key) {
62
                return is_string($key) && (new StringHelpers($key))->inString('login_web');
63
            })->first();
64
        } catch (RuntimeException $runtimeException) {
65
            // request and/or session is not set (called from a job)
66
            $session_key = 0;
67
        }
68
69
        // Get the $session_key if it's not null
70
        return ! empty($session_key) ? session()->get($session_key) : 0;
71
    }
72
73
    /**
74
     * Retrieve a unique redis key for caching the view.
75
     *
76
     * // todo: add property?
77
     * @return string
78
     */
79
    public function cacheKey(): string
80
    {
81
        return 'views'.
82
            ':'.$this->view.
83
            ':'.$this->userId().
84
            ':'.(isset($this->redis_key) ? $this->redis_key : request()->fullUrl());
85
    }
86
87
    /**
88
     * Set an override Redis Key.
89
     *
90
     * // todo: refactor this
91
     *
92
     * @param string $redis_key
93
     * @return $this
94
     */
95
    public function setRedisKey(string $redis_key): self
96
    {
97
        $this->redis_key = $redis_key;
98
99
        return $this;
100
    }
101
102
    /**
103
     * Retrieve/render the ViewModel from/to the application cache.
104
     *
105
     * @param string|null $view
106
     * @param int|null $ttl
107
     * @return string
108
     */
109
    public function render(string $view = null, int $ttl = null): string
110
    {
111
        // Set $view if it is not null
112
        if ($view) {
113
            $this->view = $view;
114
        }
115
116
        // Cache the View if it doesn't exist
117
        return RedisCache::remember($this->cacheKey(), $this->getTTL($ttl), function () {
118
            return $this->__render();
119
        });
120
    }
121
122
    /**
123
     * Render the ViewModel without storing or retrieving from the Cache.
124
     *
125
     * @param string|null $view
126
     * @return Response|string|mixed
127
     */
128
    public function renderNoCache(string $view = null)
129
    {
130
        // Set $view if it is not null
131
        if ($view) {
132
            $this->view = $view;
133
        }
134
135
        return $this->__render();
136
    }
137
138
    /**
139
     * Invalidate the View Cache for this ViewModel.
140
     *
141
     * @param bool $children
142
     * @return $this
143
     */
144
    public function invalidateCache($children = true): self
145
    {
146
        RedisCache::delete($children ? 'views:'.$this->view : $this->cacheKey(), $children);
147
148
        return $this;
149
    }
150
151
    /**
152
     * Return a concatenated route or view name by using the PREFIX const.
153
     *
154
     * @param string $string
155
     * @return $this
156
     */
157
    public function viewWithPrefix(string $string): self
158
    {
159
        $this->view = $this->prefix.$string;
160
161
        return $this;
162
    }
163
164
    /**
165
     * Extend a view name.
166
     *
167
     * @param string $string
168
     * @return $this
169
     */
170
    public function viewExtend(string $string): self
171
    {
172
        $this->view .= $string;
173
174
        return $this;
175
    }
176
177
    /**
178
     * Retrieve the time to live for the cached values
179
     *  - 1. passed $ttl parameter
180
     *  - 2. initialized $this->ttl property
181
     *  - 3. application default cache ttl.
182
     *
183
     * @param int|null $ttl
184
     * @return int
185
     */
186
    public function getTTL(int $ttl = null): int
187
    {
188
        return intval($ttl ?? $this->ttl ?? config('redis-helpers.ttl'));
189
    }
190
191
    /**
192
     * Set the $ttl property during runtime.
193
     *
194
     * @param int $ttl
195
     * @return $this
196
     */
197
    public function setTTL(int $ttl): self
198
    {
199
        $this->ttl = $ttl;
200
201
        return $this;
202
    }
203
204
    // todo: fix issues with getTTL & setTTL methods
205
}
206