Passed
Push — master ( 2558e3...29b491 )
by Andreas
03:43
created

Setting::asJson()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
eloc 1
c 0
b 0
f 0
dl 0
loc 3
ccs 2
cts 2
cp 1
rs 10
cc 1
nc 1
nop 1
crap 1
1
<?php
2
3
namespace Ottosmops\Settings;
4
5
use Illuminate\Database\Eloquent\Model;
6
use Illuminate\Support\Facades\Cache;
7
use Illuminate\Support\Facades\Validator;
8
use Illuminate\Validation\ValidationException;
9
10
use Ottosmops\Settings\Exceptions\NoKeyIsFound;
11
12
class Setting extends Model
13
{
14
    protected $keyType = 'string';
15
16
    protected $guarded = [];
17
18
    public $timestamps = false;
19
20
    public $incrementing = false;
21
22
    protected $primaryKey = 'key';
23
24
    protected $table;
25
26
    protected $casts = [
27
        'editable' => 'boolean',
28
        'value' => 'array',
29
        'default' => 'array'
30
    ];
31
32 30
    protected function asJson($value)
33
    {
34 30
        return json_encode($value, JSON_UNESCAPED_UNICODE);
35
    }
36
37 51
    public function __construct(array $attributes = [])
38
    {
39 51
        $this->table = config('settings.table', 'settings');
40 51
        parent::__construct($attributes);
41 51
    }
42
43
    /**
44
     * Get the editable status
45
     *
46
     * @param  string  $value
47
     * @return bool
48
     */
49 51
    public function getEditableAttribute($value)
50
    {
51 51
        if (!isset($value)) {
52 48
            return true;
53
        }
54
55 6
        return (bool) $value;
56
    }
57
58
    /**
59
     * Check if setting is editable
60
     *
61
     * @param  string  $value
62
     * @return bool
63
     */
64 3
    public static function isEditable(string $key) : bool
65
    {
66 3
        return Setting::where('key', $key)->first()->editable;
67
    }
68
69
    /**
70
     * Cast a value to the expected type ($this->type)
71
     * Possible types: array, integer, boolean, string
72
     *
73
     * @param  mixed $value
74
     * @return mixed
75
     */
76 45
    public function getValueAttribute($value)
77
    {
78 45
        if ($value === null) {
79 33
            return null;
80
        }
81
82 27
        switch ($this->type) {
0 ignored issues
show
Bug introduced by
The property type does not seem to exist on Ottosmops\Settings\Setting. Are you sure there is no database migration missing?

Checks if undeclared accessed properties appear in database migrations and if the creating migration is correct.

Loading history...
83 27
            case 'arr':
84 27
            case 'array':
85 3
                return json_decode($value, true);
86 24
            case 'int':
87 24
            case 'integer':
88 3
                return intval($value);
89 21
            case 'bool':
90 21
            case 'boolean':
91 9
                if ($value === "false") {
92 6
                    return false;
93
                }
94 9
                return boolval($value);
95
            default:
96 12
                return trim($value, '"');
97
        }
98
    }
99
100
    /**
101
     * Get a type casted setting value
102
     *
103
     * @param  string $key
104
     * @param  mixed  $default is returned if value is empty (except boolean false)
105
     * @return mixed
106
     */
107 33
    public static function getValue(string $key, $default = null)
108
    {
109 33
        if (!self::has($key)) {
110 9
            throw new NoKeyIsFound();
111
        }
112
113 24
        if (self::hasValue($key)) {
114 24
            return \Ottosmops\Settings\Setting::allSettings()[$key]['value'];
115
        }
116
117 3
        return $default;
118
    }
119
120
    /**
121
    * Check if setting exists
122
    *
123
    * @param $key
124
    * @return bool
125
    */
126 45
    public static function has(string $key) : bool
127
    {
128 45
        return (boolean) isset(self::allSettings()[$key]);
129
    }
130
131
    /**
132
     * If a setting has a value (also boolean false, integer 0 and an empty string are values)
133
     *
134
     * @param  string  $key
135
     * @return boolean
136
     */
137 27
    public static function hasValue(string $key) : bool
138
    {
139 27
        if (self::has($key) && isset(Setting::allSettings()[$key]['value'])) {
140 27
            $value = Setting::allSettings()[$key]['value'];
141 27
            return !empty($value) || $value === false || $value === 0 || $value === '';
142
        }
143
144 6
        return false;
145
    }
146
147
    /**
148
     * Set a new value
149
     * @param string  $key
150
     * @param mixed  $value    // string, integer, boolean or array
151
     * @param boolean
152
     */
153 15
    public static function setValue(string $key, $value = null, $validate = true)
154
    {
155 15
        if (!self::has($key)) {
156
            throw new NoKeyIsFound();
157
        }
158
159 15
        $setting = self::find($key);
160
161 15
        if ($validate && !$setting->validateNewValue($value)) {
162 6
            throw new ValidationException(null);
163
        }
164
165 9
        $setting->value = $value;
0 ignored issues
show
Bug introduced by
The property value does not seem to exist on Ottosmops\Settings\Setting. Are you sure there is no database migration missing?

Checks if undeclared accessed properties appear in database migrations and if the creating migration is correct.

Loading history...
166
167 9
        return $setting->save();
168
    }
169
170
171
    /**
172
     * Remove a setting
173
     *
174
     * @param $key
175
     * @return bool
176
     */
177 6
    public static function remove(string $key)
178
    {
179 6
        if (self::has($key)) {
180 3
            return self::find($key)->delete();
181
        }
182
183 3
        throw new NoKeyIsFound();
184
    }
185
186
    /**
187
     * Get all the settings
188
     *
189
     * @return mixed
190
     */
191 45
    public static function allSettings() : array
192
    {
193
        return Cache::rememberForever('settings.all', function () {
194 45
            return $settings = self::all()->keyBy('key')->toArray();
0 ignored issues
show
Unused Code introduced by
The assignment to $settings is dead and can be removed.
Loading history...
195 45
        });
196
    }
197
198
    /**
199
     * Helper function: Validate a value against its type and its rules.
200
     * @param  mixed $value
201
     * @return bool
202
     */
203 15
    public function validateNewValue($value) : bool
204
    {
205 15
        $validator = Validator::make([$this->key => $value], self::getValidationRules());
0 ignored issues
show
Bug introduced by
The property key does not seem to exist on Ottosmops\Settings\Setting. Are you sure there is no database migration missing?

Checks if undeclared accessed properties appear in database migrations and if the creating migration is correct.

Loading history...
206 15
        return !$validator->fails();
207
    }
208
209
    /**
210
     * Get the validation rules for setting fields
211
     *
212
     * @return array
213
     */
214 24
    public static function getValidationRules() : array
215
    {
216 24
        if ('mysql' === \DB::connection()->getPDO()->getAttribute(\PDO::ATTR_DRIVER_NAME)) {
217
            return Cache::rememberForever('settings.rules', function () {
218
                return Setting::select(\DB::raw('concat_ws("|", rules, type) as rules, `key`'))
219
                            ->pluck('rules', 'key')
220
                            ->toArray();
221
            });
222
        }
223
224
225
        return Cache::rememberForever('settings.rules', function () {
226 24
            return Setting::select(\DB::raw("printf('%s|%s', rules, type) as rules, `key`"))
227 24
                            ->pluck('rules', 'key')
228 24
                            ->toArray();
229 24
        });
230
    }
231
232
    /**
233
     * Flush the cache
234
     */
235 51
    public static function flushCache()
236
    {
237 51
        Cache::forget('settings.all');
238 51
        Cache::forget('settings.rules');
239 51
    }
240
241
    /**
242
     * The "booting" method of the model.
243
     *
244
     * @return void
245
     */
246 51
    protected static function boot()
247
    {
248 51
        parent::boot();
249
250
        static::deleted(function () {
251 3
            self::flushCache();
252 51
        });
253
        static::updated(function () {
254 15
            self::flushCache();
255 51
        });
256
        static::created(function () {
257 51
            self::flushCache();
258 51
        });
259 51
    }
260
}
261