Passed
Push — master ( d81bc3...4650e4 )
by Stephen
02:11
created

AbstractViewModel::render()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 10
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 4
c 1
b 0
f 0
nc 2
nop 2
dl 0
loc 10
rs 10
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\Helpers\Redis\RedisCache;
9
use Sfneal\Helpers\Strings\StringHelpers;
10
use Spatie\ViewModels\ViewModel;
11
12
abstract class AbstractViewModel extends ViewModel
13
{
14
    // todo: add isCached method
15
    // todo: make more properties private and add getters/setters
16
17
    /**
18
     * @var int Time to live
19
     */
20
    public $ttl = null;
21
22
    /**
23
     * @var string Use manually declare redis_key (warning: can cause issues with caching)
24
     */
25
    public $redis_key = null;
26
27
    /**
28
     * View Directory Prefix.
29
     */
30
    public $prefix;
31
32
    /**
33
     * @var null View name
34
     */
35
    public $view = null;
36
37
    /**
38
     * Render the View.
39
     *
40
     * @return string
41
     */
42
    private function __render(): string
43
    {
44
        return View::make($this->view, $this->toArray())->render();
45
    }
46
47
    /**
48
     * Retrieve the authenticated user's ID from the session.
49
     *
50
     *  - avoid executing database query
51
     *  // todo: make this optional, we dont always want to tag cached pages by user
52
     *
53
     * @return int
54
     */
55
    private function userId(): int
56
    {
57
        try {
58
            // Find the 'login_web' session key that holds the authenticated user_id value
59
            // If there's no key containing 'login_web' the user is not logged in
60
            $session_key = collect(request()->session()->all())->keys()->filter(function ($key) {
61
                return is_string($key) && (new StringHelpers($key))->inString('login_web');
62
            })->first();
63
        } catch (RuntimeException $runtimeException) {
64
            // request and/or session is not set (called from a job)
65
            $session_key = 0;
66
        }
67
68
        // Get the $session_key if it's not null
69
        return ! empty($session_key) ? session()->get($session_key) : 0;
70
    }
71
72
    /**
73
     * Retrieve a unique redis key for caching the view.
74
     *
75
     * // todo: add property?
76
     * @return string
77
     */
78
    public function cacheKey(): string
79
    {
80
        return 'views'.
81
            ':'.$this->view.
82
            '#'.$this->userId().
83
            '#'.(isset($this->redis_key) ? $this->redis_key : request()->fullUrl());
84
    }
85
86
    /**
87
     * Set an override Redis Key.
88
     *
89
     * @param string $redis_key
90
     * @return $this
91
     */
92
    public function setRedisKey(string $redis_key): self
93
    {
94
        $this->redis_key = $redis_key;
95
96
        return $this;
97
    }
98
99
    /**
100
     * Retrieve/render the ViewModel from/to the application cache.
101
     *
102
     * @param string|null $view
103
     * @param int|null $ttl
104
     * @return string
105
     */
106
    public function render(string $view = null, int $ttl = null): string
107
    {
108
        // Set $view if it is not null
109
        if ($view) {
110
            $this->view = $view;
0 ignored issues
show
Documentation Bug introduced by
It seems like $view of type string is incompatible with the declared type null of property $view.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
111
        }
112
113
        // Cache the View if it doesn't exist
114
        return RedisCache::remember($this->cacheKey(), $this->getTTL($ttl), function () {
115
            return $this->__render();
116
        });
117
    }
118
119
    /**
120
     * Render the ViewModel without storing or retrieving from the Cache.
121
     *
122
     * @param string|null $view
123
     * @return Response|string|mixed
124
     */
125
    public function renderNoCache(string $view = null)
126
    {
127
        // Set $view if it is not null
128
        if ($view) {
129
            $this->view = $view;
0 ignored issues
show
Documentation Bug introduced by
It seems like $view of type string is incompatible with the declared type null of property $view.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
130
        }
131
132
        return $this->__render();
133
    }
134
135
    /**
136
     * Invalidate the View Cache for this ViewModel.
137
     *
138
     * @return $this
139
     */
140
    public function invalidateCache(): self
141
    {
142
        RedisCache::delete('views:'.$this->view);
143
144
        return $this;
145
    }
146
147
    /**
148
     * Determine if the ViewModel has been cached.
149
     *
150
     * @return bool
151
     */
152
    public function isCached(): bool
153
    {
154
        return RedisCache::exists($this->cacheKey());
155
    }
156
157
    /**
158
     * Return a concatenated route or view name by using the PREFIX const.
159
     *
160
     * @param string $string
161
     * @return $this
162
     */
163
    public function viewWithPrefix(string $string): self
164
    {
165
        $this->view = $this->prefix.$string;
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->prefix . $string of type string is incompatible with the declared type null of property $view.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
166
167
        return $this;
168
    }
169
170
    /**
171
     * Extend a view name.
172
     *
173
     * @param string $string
174
     * @return $this
175
     */
176
    public function viewExtend(string $string): self
177
    {
178
        $this->view .= $string;
179
180
        return $this;
181
    }
182
183
    /**
184
     * Retrieve the time to live for the cached values
185
     *  - 1. passed $ttl parameter
186
     *  - 2. initialized $this->ttl property
187
     *  - 3. application default cache ttl.
188
     *
189
     * @param int|null $ttl
190
     * @return int
191
     */
192
    public function getTTL(int $ttl = null): int
193
    {
194
        return intval($ttl ?? $this->ttl ?? config('redis-helpers.ttl'));
195
    }
196
197
    /**
198
     * Set the $ttl property during runtime.
199
     *
200
     * @param int $ttl
201
     * @return $this
202
     */
203
    public function setTTL(int $ttl): self
204
    {
205
        $this->ttl = $ttl;
206
207
        return $this;
208
    }
209
210
    // todo: fix issues with getTTL & setTTL methods
211
}
212