Completed
Push — master ( cfdf98...14ce2a )
by ARCANEDEV
03:16
created

DatabaseStore::read()   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 2
Bugs 0 Features 0
Metric Value
dl 0
loc 4
rs 10
c 2
b 0
f 0
ccs 2
cts 2
cp 1
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\Utilities\Arr;
6
use Closure;
7
use Illuminate\Database\Connection;
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
    /**
22
     * The database connection instance.
23
     *
24
     * @var \Illuminate\Database\Connection
25
     */
26
    protected $connection;
27
28
    /**
29
     * The table to query from.
30
     *
31
     * @var string
32
     */
33
    protected $table;
34
35
    /**
36
     * Any query constraints that should be applied.
37
     *
38
     * @var Closure|null
39
     */
40
    protected $queryConstraint;
41
42
    /**
43
     * Any extra columns that should be added to the rows.
44
     *
45
     * @var array
46
     */
47
    protected $extraColumns = [];
48
49
    /* ------------------------------------------------------------------------------------------------
50
     |  Constructor
51
     | ------------------------------------------------------------------------------------------------
52
     */
53
    /**
54
     * Make the Database store instance.
55
     *
56
     * @param  \Illuminate\Database\Connection  $connection
57
     * @param  string                           $table
58
     */
59 24
    public function __construct(Connection $connection, $table = null)
60
    {
61 24
        $this->setConnection($connection);
62 24
        $this->setTable($table ?: 'settings');
63 24
    }
64
65
    /* ------------------------------------------------------------------------------------------------
66
     |  Getters & Setters
67
     | ------------------------------------------------------------------------------------------------
68
     */
69
    /**
70
     * Set the database connection.
71
     *
72
     * @param  \Illuminate\Database\Connection  $connection
73
     *
74
     * @return self
75
     */
76 24
    public function setConnection(Connection $connection)
77
    {
78 24
        $this->connection = $connection;
79
80 24
        return $this;
81
    }
82
83
    /**
84
     * Set the table to query from.
85
     *
86
     * @param  string  $table
87
     *
88
     * @return self
89
     */
90 24
    public function setTable($table)
91
    {
92 24
        $this->table = $table;
93
94 24
        return $this;
95
    }
96
97
    /**
98
     * Set the query constraint.
99
     *
100
     * @param  \Closure  $callback
101
     *
102
     * @return self
103
     */
104
    public function setConstraint(Closure $callback)
105
    {
106
        $this->data            = [];
107
        $this->loaded          = false;
108
        $this->queryConstraint = $callback;
109
110
        return $this;
111
    }
112
113
    /**
114
     * Set extra columns to be added to the rows.
115
     *
116
     * @param  array  $columns
117
     *
118
     * @return self
119
     */
120
    public function setExtraColumns(array $columns)
121
    {
122
        $this->extraColumns = $columns;
123
124
        return $this;
125
    }
126
127
    /* ------------------------------------------------------------------------------------------------
128
     |  Main Functions
129
     | ------------------------------------------------------------------------------------------------
130
     */
131
    /**
132
     * {@inheritdoc}
133
     */
134 6
    public function forget($key)
135
    {
136 6
        parent::forget($key);
137
138
        // because the database store cannot store empty arrays, remove empty
139
        // arrays to keep data consistent before and after saving
140 6
        $segments = explode('.', $key);
141 6
        array_pop($segments);
142
143 6
        while ( ! empty($segments)) {
144 3
            $segment = implode('.', $segments);
145
146
            // non-empty array - exit out of the loop
147 3
            if ($this->get($segment)) {
148 3
                break;
149
            }
150
151
            // remove the empty array and move on to the next segment
152 3
            $this->forget($segment);
153 3
            array_pop($segments);
154 3
        }
155 6
    }
156
157
    /* ------------------------------------------------------------------------------------------------
158
     |  Other Functions
159
     | ------------------------------------------------------------------------------------------------
160
     */
161
    /**
162
     * {@inheritdoc}
163
     */
164 21
    protected function read()
165
    {
166 21
        return $this->parseReadData($this->newQuery()->get());
167
    }
168
169
    /**
170
     * {@inheritdoc}
171
     */
172 15
    protected function write(array $data)
173
    {
174 15
        $keys       = $this->newQuery()->lists('key');
175 15
        $insertData = array_dot($data);
176 15
        $updateData = [];
177 15
        $deleteKeys = [];
178
179 15
        foreach ($keys as $key) {
180 9
            if (isset($insertData[$key]))
181 9
                $updateData[$key] = $insertData[$key];
182
            else
183 9
                $deleteKeys[] = $key;
184
185 9
            unset($insertData[$key]);
186 15
        }
187
188 15
        foreach ($updateData as $key => $value) {
189 6
            $this->newQuery()
190 6
                ->where('key', '=', $key)
191 6
                ->update(array('value' => $value));
192 15
        }
193
194 15
        if ( ! empty($insertData)) {
195 15
            $this->newQuery(true)
196 15
                ->insert($this->prepareInsertData($insertData));
197 15
        }
198
199 15
        if ( ! empty($deleteKeys)) {
200 9
            $this->newQuery()
201 9
                ->whereIn('key', $deleteKeys)
202 9
                ->delete();
203 9
        }
204 15
    }
205
206
    /**
207
     * Parse data coming from the database.
208
     *
209
     * @param  array $data
210
     *
211
     * @return array
212
     */
213 21
    protected function parseReadData($data)
214
    {
215 21
        $results = [];
216
217 21
        foreach ($data as $row) {
218 15
            if (is_array($row)) {
219
                $key   = $row['key'];
220
                $value = $row['value'];
221
            }
222 15
            elseif (is_object($row)) {
223 15
                $key   = $row->key;
224 15
                $value = $row->value;
225 15
            }
226
            else {
227
                throw new \UnexpectedValueException(
228
                    'Expected array or object, got ' . gettype($row)
229
                );
230
            }
231
232 15
            Arr::set($results, $key, $value);
233 21
        }
234
235 21
        return $results;
236
    }
237
238
    /**
239
     * Transforms settings data into an array ready to be insterted into the
240
     * database. Call array_dot on a multidimensional array before passing it
241
     * into this method!
242
     *
243
     * @param  array $data Call array_dot on a multidimensional array before passing it into this method!
244
     *
245
     * @return array
246
     */
247 15
    protected function prepareInsertData(array $data)
248
    {
249 15
        $dbData = [];
250
251 15
        foreach ($data as $key => $value) {
252 15
            $dbData[] = empty($this->extraColumns)
253 15
                ? compact('key', 'value')
254 15
                : array_merge($this->extraColumns, compact('key', 'value'));
255 15
        }
256
257 15
        return $dbData;
258
    }
259
260
    /**
261
     * Create a new query builder instance.
262
     *
263
     * @param  $insert  boolean  Whether the query is an insert or not.
264
     *
265
     * @return \Illuminate\Database\Query\Builder
266
     */
267 21
    protected function newQuery($insert = false)
268
    {
269 21
        $query = $this->connection->table($this->table);
270
271 21
        if ( ! $insert) {
272 21
            foreach ($this->extraColumns as $key => $value) {
273
                $query->where($key, '=', $value);
274 21
            }
275 21
        }
276
277 21
        if ($this->queryConstraint !== null) {
278
            /** @var  Closure  $callback */
279
            $callback = $this->queryConstraint;
280
            $callback($query, $insert);
281
        }
282
283 21
        return $query;
284
    }
285
}
286