PluginProbe ʕ •ᴥ•ʔ
Kirki – Freeform Page Builder, Website Builder & Customizer / 6.1.0
Kirki – Freeform Page Builder, Website Builder & Customizer v6.1.0
6.1.1 6.1.0 6.0.14 6.0.13 6.0.12 6.0.11 6.0.10 6.0.9 6.0.8 6.0.7 6.0.6 6.0.5 6.0.4 6.0.3 6.0.2 6.0.1 3.1.3 3.1.4 3.1.5 3.1.6 3.1.7 3.1.8 3.1.9 4.0.19 4.0.20 4.0.21 4.0.22 4.0.23 4.0.24 4.1 4.2.0 5.0.0 5.1.0 5.1.1 5.2.0 5.2.1 5.2.2 5.2.3 6.0.0 trunk 3.0.40 3.0.41 3.0.42 3.0.43 3.0.44 3.0.45 3.1.0 3.1.1 3.1.2
kirki / libraries / framework / Database / Concerns / GuardAttributes.php
kirki / libraries / framework / Database / Concerns Last commit date
ExecuteQueries.php 3 weeks ago GuardAttributes.php 3 weeks ago HasAttributes.php 3 weeks ago HasDictionary.php 3 weeks ago HasRelationships.php 3 weeks ago HasTimestamps.php 3 weeks ago RelationshipQueries.php 3 weeks ago
GuardAttributes.php
289 lines
1 <?php
2
3 /**
4 * Trait implementing mass-assignment protection via fillable and guarded lists.
5 * Supports global unguard for seeding and per-model fillable configuration.
6 * Prevents accidental writes to protected columns during bulk attribute sets.
7 *
8 * @package Framework
9 * @subpackage Database\Concerns
10 * @since 1.0.0
11 */
12 namespace Kirki\Framework\Database\Concerns;
13
14 \defined('ABSPATH') || exit;
15 use Kirki\Framework\Database\Connection\Connection;
16 use Kirki\Framework\Supports\Facades\Schema;
17 use function Kirki\Framework\Polyfill\str_contains;
18 use function Kirki\Framework\Polyfill\str_starts_with;
19 trait GuardAttributes
20 {
21 /**
22 * The attributes that are mass assignable.
23 *
24 * @var array
25 *
26 * @since 1.0.0
27 */
28 protected $fillable = [];
29 /**
30 * The attributes that should be protected from mass assignment.
31 *
32 * @var array
33 *
34 * @since 1.0.0
35 */
36 protected $guarded = ['*'];
37 /**
38 * Indicates if all mass assignment is allowed.
39 *
40 * @var bool
41 *
42 * @since 1.0.0
43 */
44 protected static $unguarded = \false;
45 /**
46 * The guardable columns for the model.
47 *
48 * @var array<class-string, list<string>>
49 *
50 * @since 1.0.0
51 */
52 protected static $guardable_columns = [];
53 /**
54 * Get the connection for the model.
55 *
56 * @return Connection
57 *
58 * @since 1.0.0
59 */
60 protected static abstract function get_connection();
61 /**
62 * Get the fillable attributes for the model.
63 *
64 * @return array
65 *
66 * @since 1.0.0
67 */
68 public function get_fillable()
69 {
70 return $this->fillable;
71 }
72 /**
73 * Set the fillable attributes for the model.
74 *
75 * @param array $fillable The fillable.
76 *
77 * @return $this
78 *
79 * @since 1.0.0
80 */
81 public function fillable(array $fillable)
82 {
83 $this->fillable = $fillable;
84 return $this;
85 }
86 /**
87 * Merge the given fillable attributes with the existing fillable attributes.
88 *
89 * @param array $fillable The fillable.
90 *
91 * @return $this
92 *
93 * @since 1.0.0
94 */
95 public function merge_fillable(array $fillable)
96 {
97 if ($fillable === []) {
98 return $this;
99 }
100 $this->fillable = \array_values(\array_unique(\array_merge($this->fillable, $fillable)));
101 return $this;
102 }
103 /**
104 * Get the guarded attributes for the model.
105 *
106 * @return array
107 *
108 * @since 1.0.0
109 */
110 public function get_guarded()
111 {
112 return static::$unguarded ? [] : $this->guarded;
113 }
114 /**
115 * Set the guarded attributes for the model.
116 *
117 * @param array $guarded The guarded.
118 *
119 * @return $this
120 *
121 * @since 1.0.0
122 */
123 public function guard(array $guarded)
124 {
125 $this->guarded = $guarded;
126 return $this;
127 }
128 /**
129 * Merge the given guarded attributes with the existing guarded attributes.
130 *
131 * @param array $guarded The guarded.
132 *
133 * @return $this
134 *
135 * @since 1.0.0
136 */
137 public function merge_guarded(array $guarded)
138 {
139 $this->guarded = \array_values(\array_unique(\array_merge($this->guarded, $guarded)));
140 return $this;
141 }
142 /**
143 * Enable mass assignment for all attributes.
144 *
145 * @param mixed $state The state.
146 *
147 * @return void
148 *
149 * @since 1.0.0
150 */
151 public static function unguard($state = \true)
152 {
153 static::$unguarded = $state;
154 }
155 /**
156 * Disable mass assignment for all attributes.
157 *
158 * @return void
159 *
160 * @since 1.0.0
161 */
162 public static function reguard()
163 {
164 static::$unguarded = \false;
165 }
166 /**
167 * Determine if mass assignment is enabled for all attributes.
168 *
169 * @return bool
170 *
171 * @since 1.0.0
172 */
173 public static function is_unguarded()
174 {
175 return static::$unguarded;
176 }
177 /**
178 * Execute the given callback while mass assignment is enabled for all attributes.
179 *
180 * @template TReturn
181 *
182 * @param (callable(): TReturn) $callback The callback to invoke.
183 *
184 * @return mixed
185 *
186 * @since 1.0.0
187 */
188 public static function unguarded(callable $callback)
189 {
190 if (static::$unguarded) {
191 return $callback();
192 }
193 static::unguard();
194 try {
195 return $callback();
196 } finally {
197 static::reguard();
198 }
199 }
200 /**
201 * Determine if the given key is fillable.
202 *
203 * @param mixed $key The key.
204 *
205 * @return bool
206 *
207 * @since 1.0.0
208 */
209 public function is_fillable($key)
210 {
211 if (static::$unguarded) {
212 return \true;
213 }
214 if (\in_array($key, $this->get_fillable(), \true)) {
215 return \true;
216 }
217 if ($this->is_guarded($key)) {
218 return \false;
219 }
220 return empty($this->get_fillable()) && !str_contains($key, '.') && !str_starts_with($key, '_');
221 }
222 /**
223 * Determine if the given key is guarded.
224 *
225 * @param mixed $key The key.
226 *
227 * @return bool
228 *
229 * @since 1.0.0
230 */
231 public function is_guarded($key)
232 {
233 if (empty($this->get_guarded())) {
234 return \false;
235 }
236 return $this->get_guarded() === ['*'] || !empty(\preg_grep('/^' . \preg_quote($key, '/') . '$/i', $this->get_guarded())) || !$this->is_guardable_column($key);
237 }
238 /**
239 * Determine if the given key is guardable.
240 *
241 * @param mixed $key The key.
242 *
243 * @return bool
244 *
245 * @since 1.0.0
246 */
247 protected function is_guardable_column($key)
248 {
249 if ($this->has_set_mutator($key) || $this->is_class_castable($key)) {
250 return \true;
251 }
252 if (!isset(static::$guardable_columns[\get_class($this)])) {
253 $columns = Schema::get_column_listing($this->get_table());
254 if (empty($columns)) {
255 return \true;
256 }
257 static::$guardable_columns[\get_class($this)] = $columns;
258 }
259 return \in_array($key, static::$guardable_columns[\get_class($this)]);
260 }
261 /**
262 * Determine if the model is totally guarded.
263 *
264 * @return bool
265 *
266 * @since 1.0.0
267 */
268 public function totally_guarded()
269 {
270 return \count($this->get_fillable()) === 0 && $this->get_guarded() == ['*'];
271 }
272 /**
273 * Get the fillable attributes from the array.
274 *
275 * @param array $attributes The attributes.
276 *
277 * @return array
278 *
279 * @since 1.0.0
280 */
281 protected function fillable_from_array(array $attributes)
282 {
283 if (\count($this->get_fillable()) > 0 && !static::$unguarded) {
284 return \array_intersect_key($attributes, \array_flip($this->get_fillable()));
285 }
286 return $attributes;
287 }
288 }
289