Completed
Push — master ( b358a3...e65407 )
by ARCANEDEV
03:37
created

DatabaseStore::hasConstraint()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
cc 1
eloc 2
nc 1
nop 0
crap 1
1
<?php namespace Arcanedev\Settings\Stores;
2
3
use Arcanedev\Settings\Bases\Store;
4
use Arcanedev\Settings\Contracts\Store as StoreContract;
5
use Arcanedev\Settings\Models\Setting;
6
use Arcanedev\Settings\Utilities\Arr;
7
use Closure;
8
9
/**
10
 * Class     DatabaseStore
11
 *
12
 * @package  Arcanedev\Settings\Stores
13
 * @author   ARCANEDEV <[email protected]>
14
 */
15
class DatabaseStore extends Store implements StoreContract
16
{
17
    /* ------------------------------------------------------------------------------------------------
18
     |  Properties
19
     | ------------------------------------------------------------------------------------------------
20
     */
21
    /** @var  \Arcanedev\Settings\Models\Setting */
22
    protected $model;
23
24
    /**
25
     * Any query constraints that should be applied.
26
     *
27
     * @var Closure|null
28
     */
29
    protected $queryConstraint;
30
31
    /**
32
     * Any extra columns that should be added to the rows.
33
     *
34
     * @var array
35
     */
36
    protected $extraColumns = [];
37
38
    /* ------------------------------------------------------------------------------------------------
39
     |  Constructor
40
     | ------------------------------------------------------------------------------------------------
41
     */
42
    /**
43
     * Make the Database store instance.
44
     *
45
     * @param  string  $connection
46
     * @param  string  $table
47
     */
48 30
    public function __construct($connection, $table = null)
49
    {
50 30
        $this->model = new Setting;
51 30
        $this->setConnection($connection);
52 30
        $this->setTable($table ?: 'settings');
53 30
    }
54
55
    /* ------------------------------------------------------------------------------------------------
56
     |  Getters & Setters
57
     | ------------------------------------------------------------------------------------------------
58
     */
59
    /**
60
     * Set the database connection.
61
     *
62
     * @param  string  $connection
63
     *
64
     * @return self
65
     */
66 30
    public function setConnection($connection)
67
    {
68 30
        $this->model->setConnection($connection);
69
70 30
        return $this;
71
    }
72
73
    /**
74
     * Set the table to query from.
75
     *
76
     * @param  string  $table
77
     *
78
     * @return self
79
     */
80 30
    public function setTable($table)
81
    {
82 30
        $this->model->setTable($table);
83
84 30
        return $this;
85
    }
86
87
    /**
88
     * Set the query constraint.
89
     *
90
     * @param  \Closure  $callback
91
     *
92
     * @return self
93
     */
94 3
    public function setConstraint(Closure $callback)
95
    {
96 3
        $this->data            = [];
97 3
        $this->loaded          = false;
98 3
        $this->queryConstraint = $callback;
99
100 3
        return $this;
101
    }
102
103
    /**
104
     * Set extra columns to be added to the rows.
105
     *
106
     * @param  array  $columns
107
     *
108
     * @return self
109
     */
110 6
    public function setExtraColumns(array $columns)
111
    {
112 6
        $this->extraColumns = $columns;
113
114 6
        return $this;
115
    }
116
117
    /* ------------------------------------------------------------------------------------------------
118
     |  Main Functions
119
     | ------------------------------------------------------------------------------------------------
120
     */
121
    /**
122
     * {@inheritdoc}
123
     */
124 6
    public function forget($key)
125
    {
126 6
        parent::forget($key);
127
128
        // because the database store cannot store empty arrays, remove empty
129
        // arrays to keep data consistent before and after saving
130 6
        $segments = explode('.', $key);
131 6
        array_pop($segments);
132
133 6
        while ( ! empty($segments)) {
134 3
            $segment = implode('.', $segments);
135
136
            // non-empty array - exit out of the loop
137 3
            if ($this->get($segment)) {
138 3
                break;
139
            }
140
141
            // remove the empty array and move on to the next segment
142 3
            $this->forget($segment);
143 3
            array_pop($segments);
144 3
        }
145 6
    }
146
147
    /* ------------------------------------------------------------------------------------------------
148
     |  Other Functions
149
     | ------------------------------------------------------------------------------------------------
150
     */
151
    /**
152
     * {@inheritdoc}
153
     */
154 27
    protected function read()
155
    {
156 27
        $results  = [];
157
158 27
        foreach ($this->model()->get() as $setting) {
0 ignored issues
show
Documentation Bug introduced by
The method get does not exist on object<Arcanedev\Settings\Models\Setting>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
159
            /** @var Setting $setting */
160 18
            Arr::set($results, $setting->key, $setting->value);
161 27
        }
162
163 27
        return $results;
164
    }
165
166
    /**
167
     * {@inheritdoc}
168
     */
169 21
    protected function write(array $data)
170
    {
171 21
        list($inserts, $updates, $deletes) = $this->prepareData($data);
172
173 21
        $this->updateSettings($updates);
174 21
        $this->insertSettings($inserts);
175 21
        $this->deleteSettings($deletes);
176 21
    }
177
178
    /* ------------------------------------------------------------------------------------------------
179
     |  CRUD Functions
180
     | ------------------------------------------------------------------------------------------------
181
     */
182
    /**
183
     * Prepare settings data.
184
     *
185
     * @param  array  $data
186
     *
187
     * @return array
188
     */
189 21
    private function prepareData(array $data)
190
    {
191 21
        $inserts = array_dot($data);
192 21
        $updates = [];
193 21
        $deletes = [];
194
195 21
        foreach ($this->model()->lists('key') as $key) {
196 12
            if (isset($inserts[$key]))
197 12
                $updates[$key] = $inserts[$key];
198
            else
199 9
                $deletes[]     = $key;
200
201 12
            unset($inserts[$key]);
202 21
        }
203
204 21
        return [$inserts, $updates, $deletes];
205
    }
206
207
    /**
208
     * Update settings data.
209
     *
210
     * @param  array $updates
211
     */
212 21
    private function updateSettings($updates)
213
    {
214 21
        foreach ($updates as $key => $value) {
215 9
            $this->model()->where('key', $key)->update(compact('value'));
216 21
        }
217 21
    }
218
219
    /**
220
     * Insert settings data.
221
     *
222
     * @param  array $inserts
223
     */
224 21
    private function insertSettings(array $inserts)
225
    {
226 21
        if (empty($inserts)) {
227 9
            return;
228
        }
229
230 21
        $dbData = [];
231
232 21
        foreach ($inserts as $key => $value) {
233 21
            $data     = compact('key', 'value');
234 21
            $dbData[] = empty($this->extraColumns) ? $data : array_merge($this->extraColumns, $data);
235 21
        }
236
237 21
        $this->model(true)->insert($dbData);
238 21
    }
239
240
    /**
241
     * Delete settings data.
242
     *
243
     * @param  array  $deletes
244
     */
245 21
    private function deleteSettings(array $deletes)
246
    {
247 21
        if (empty($deletes)) {
248 21
            return;
249
        }
250
251 9
        $this->model()->whereIn('key', $deletes)->delete();
252 9
    }
253
254
    /**
255
     * Create a new query builder instance.
256
     *
257
     * @param  $insert  bool  Whether the query is an insert or not.
258
     *
259
     * @return \Arcanedev\Settings\Models\Setting
260
     */
261 27
    private function model($insert = false)
262
    {
263 27
        $model = $this->model;
264
265 27
        if ($insert === false) {
266 27
            foreach ($this->extraColumns as $key => $value) {
267 6
                $model->where($key, $value);
268 27
            }
269 27
        }
270
271 27
        if ($this->hasConstraint()) {
272
            /** @var  Closure  $callback */
273 3
            $callback = $this->queryConstraint;
274 3
            $model    = $callback($model, $insert);
275 3
        }
276
277 27
        return $model;
278
    }
279
280
    /* ------------------------------------------------------------------------------------------------
281
     |  Check Functions
282
     | ------------------------------------------------------------------------------------------------
283
     */
284
    /**
285
     * Check if has a query constraint.
286
     *
287
     * @return bool
288
     */
289 27
    public function hasConstraint()
290
    {
291 27
        return ! is_null($this->queryConstraint);
292
    }
293
}
294