DatabaseService::getWithInFromDatabase()   A
last analyzed

Complexity

Conditions 6
Paths 24

Size

Total Lines 31
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 16
CRAP Score 6

Importance

Changes 0
Metric Value
eloc 16
dl 0
loc 31
ccs 16
cts 16
cp 1
rs 9.1111
c 0
b 0
f 0
cc 6
nc 24
nop 8
crap 6

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
/**
3
 * Created by PhpStorm.
4
 * User: famoser
5
 * Date: 23.05.2016
6
 * Time: 15:25
7
 */
8
9
namespace Famoser\XKCDCache\Services;
10
11
use Famoser\XKCDCache\Entities\Base\BaseEntity;
12
use Famoser\XKCDCache\Entities\Comic;
13
use Famoser\XKCDCache\Services\Base\BaseService;
14
use Famoser\XKCDCache\Services\Interfaces\DatabaseServiceInterface;
15
use Interop\Container\ContainerInterface;
16
use PDO;
17
18
/**
19
 * the DatabaseService allows access to the database. It abstracts sql from logic, and is type safe
20
 *
21
 * @package Famoser\XKCDCache\Helpers
22
 */
23
class DatabaseService extends BaseService implements DatabaseServiceInterface
24
{
25
    /* @var PDO $database */
26
    private $database;
27
28
    /**
29
     * DatabaseHelper constructor.
30
     *
31
     * @param ContainerInterface $container
32
     */
33 19
    public function __construct(ContainerInterface $container)
34
    {
35 19
        parent::__construct($container);
36
37 19
        $this->initializeDatabase();
38 19
    }
39
40
    /**
41
     * @return PDO
42
     */
43 16
    private function getConnection()
44
    {
45 16
        return $this->database;
46
    }
47
48
    /**
49
     * initialize the database
50
     */
51 19
    private function initializeDatabase()
52
    {
53 19
        $dataPath = $this->getSettingService()->getDbPath();
54
55 19
        if (!file_exists($dataPath)) {
56 19
            $templatePath = $this->getSettingService()->getDbTemplatePath();
57 19
            copy($templatePath, $dataPath);
58
        }
59
60 19
        $this->database = $this->constructPdo($dataPath);
61 19
    }
62
63
    /**
64
     * construct a sqlite pdo object from a path
65
     *
66
     * @param string $path
67
     * @return PDO
68
     */
69 19
    private function constructPdo($path)
70
    {
71 19
        $pdo = new PDO('sqlite:' . $path);
72 19
        $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
73 19
        $pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
74 19
        return $pdo;
75
    }
76
77
    /**
78
     * creates the sql query
79
     *
80
     * @param BaseEntity $entity
81
     * @param null|string $where
82
     * @param null|string $orderBy
83
     * @param int $limit
84
     * @param string $selector
85
     * @return string
86
     */
87 15
    private function createQuery(BaseEntity $entity, $where = null, $orderBy = null, $limit = 1000, $selector = '*')
88
    {
89 15
        $sql = 'SELECT ' . $selector . ' FROM ' . $entity->getTableName();
90 15
        if ($where !== null) {
91 11
            $sql .= ' WHERE ' . $where;
92
        }
93 15
        if ($orderBy !== null) {
94 7
            $sql .= ' ORDER BY ' . $orderBy;
95
        }
96 15
        if ($limit > 0) {
97 9
            $sql .= ' LIMIT ' . $limit;
98
        }
99 15
        return $sql;
100
    }
101
102
    /**
103
     * executes query and fetches all results
104
     *
105
     * @param BaseEntity $entity
106
     * @param string $sql
107
     * @param null|array $parameters
108
     * @return false|array|null
109
     */
110 13
    private function executeAndFetch(BaseEntity $entity, $sql, $parameters = null)
111
    {
112 13
        $request = $this->getConnection()->prepare($sql);
113 13
        if (!$request->execute($parameters)) {
114
            return [];
115
        }
116 13
        return $request->fetchAll(PDO::FETCH_CLASS, get_class($entity));
117
    }
118
119
    /**
120
     * gets all entities which match the specified conditions from the database
121
     *
122
     * @param BaseEntity $entity
123
     * @param null|string $where
124
     * @param null|string $orderBy
125
     * @param null|array $parameters
126
     * @param int $limit
127
     * @param string $selector
128
     * @return Comic[]
129
     */
130 7
    public function getFromDatabase(
131
        BaseEntity $entity,
132
        $where = null,
133
        $parameters = null,
134
        $orderBy = null,
135
        $limit = -1,
136
        $selector = '*'
137
    )
138
    {
139 7
        $sql = $this->createQuery($entity, $where, $orderBy, $limit, $selector);
140 7
        $res = $this->executeAndFetch($entity, $sql, $parameters);
141 7
        return $res;
142
    }
143
144
    /**
145
     * counts the entities which match the conditions
146
     *
147
     * @param BaseEntity $entity
148
     * @param null|string $where
149
     * @param null|string $orderBy
150
     * @param null|array $parameters
151
     * @param int $limit
152
     * @return int|false
153
     */
154 2
    public function countFromDatabase(
155
        BaseEntity $entity,
156
        $where = null,
157
        $parameters = null,
158
        $orderBy = null,
159
        $limit = -1
160
    )
161
    {
162 2
        $sql = $this->createQuery($entity, $where, $orderBy, $limit, 'COUNT(*)');
163 2
        return $this->executeAndCount($sql, $parameters);
164
    }
165
166
    /**
167
     * gets all entities whose property is one of the values provided and which match the specified conditions
168
     *
169
     * @param BaseEntity $entity
170
     * @param string $property
171
     * @param array $values
172
     * @param bool $invertIn
173
     * @param null|string $where
174
     * @param null|string $orderBy
175
     * @param null|array $parameters
176
     * @param int $limit
177
     * @return Comic[]
178
     */
179 2
    public function getWithInFromDatabase(
180
        BaseEntity $entity,
181
        $property,
182
        $values,
183
        $invertIn = false,
184
        $where = null,
185
        $parameters = null,
186
        $orderBy = null,
187
        $limit = -1
188
    )
189
    {
190 2
        if ($parameters == null) {
191 1
            $parameters = [];
192
        }
193 2
        if ($where === null) {
194 1
            $where = ' ';
195
        } else {
196 1
            $where .= ' AND ';
197
        }
198 2
        $variables = [];
199 2
        $valueCount = count($values);
200 2
        for ($i = 0; $i < $valueCount; $i++) {
201 2
            $parameters[':' . $property . $i] = $values[$i];
202 2
            $variables[] = ':' . $property . $i;
203
        }
204 2
        if (count($variables)) {
205 2
            $where .= $property . (($invertIn) ? ' NOT' : '') . ' IN (' . implode(',', $variables) . ')';
206
        }
207 2
        $sql = $this->createQuery($entity, $where, $orderBy, $limit);
208 2
        $res = $this->executeAndFetch($entity, $sql, $parameters);
209 2
        return $res;
210
    }
211
212
    /**
213
     * get the first entry from the database which matches the conditions
214
     *
215
     * @param BaseEntity $entity
216
     * @param null|string $where
217
     * @param null|array $parameters
218
     * @param null|string $orderBy
219
     * @return Comic
220
     */
221 9
    public function getSingleFromDatabase(BaseEntity $entity, $where = null, $parameters = null, $orderBy = null)
222
    {
223 9
        $sql = $this->createQuery($entity, $where, $orderBy, 1);
224 9
        $res = $this->executeAndFetch($entity, $sql, $parameters);
225 9
        if (count($res) > 0) {
226 7
            return $res[0];
227
        }
228 7
        return null;
229
    }
230
231
    /**
232
     * save the entity to the database
233
     * if the entity was retrieved from the database before, it will replace the old data
234
     *
235
     * @param BaseEntity $entity
236
     * @return bool
237
     */
238 15
    public function saveToDatabase(BaseEntity $entity)
239
    {
240 15
        $properties = (array)$entity;
241 15
        unset($properties['id']);
242 15
        if ($entity->id > 0) {
243
            //update
244 1
            $sql = 'UPDATE ' . $entity->getTableName() . ' SET ';
245 1
            foreach ($properties as $key => $val) {
246 1
                $sql .= $key . '=:' . $key . ',';
247
            }
248 1
            $sql = substr($sql, 0, -1);
249 1
            $sql .= ' WHERE id=:id';
250 1
            $properties = (array)$entity;
251 1
            $request = $this->getConnection()->prepare($sql);
252 1
            if (!$request->execute($properties)) {
253 1
                return false;
254
            }
255
        } else {
256
            //create
257 15
            $sql = 'INSERT INTO ' . $entity->getTableName() . '(';
258 15
            foreach ($properties as $key => $val) {
259 15
                $sql .= $key . ',';
260
            }
261 15
            $sql = substr($sql, 0, -1);
262 15
            $sql .= ') VALUES (';
263 15
            foreach ($properties as $key => $val) {
264 15
                $sql .= ':' . $key . ',';
265
            }
266 15
            $sql = substr($sql, 0, -1);
267 15
            $sql .= ')';
268 15
            $request = $this->getConnection()->prepare($sql);
269 15
            if (!$request->execute($properties)) {
270
                return false;
271
            }
272 15
            $entity->id = (int)$this->getConnection()->lastInsertId();
273
        }
274 15
        return true;
275
    }
276
277
    /**
278
     * execute the specified sql query, return if the query was successful
279
     *
280
     * @param string $sql
281
     * @param null|array $parameters
282
     * @return bool
283
     */
284 1
    public function execute($sql, $parameters = null)
285
    {
286 1
        $prep = $this->getConnection()->prepare($sql);
287 1
        return $prep->execute($parameters);
288
    }
289
290
    /**
291
     * execute the specified sql query, return the FETCH_NUM result
292
     *
293
     * @param string $sql
294
     * @param null|array $parameters
295
     * @return false|int
296
     */
297 2
    public function executeAndCount($sql, $parameters = null)
298
    {
299 2
        $prep = $this->getConnection()->prepare($sql);
300 2
        if (!$prep->execute($parameters)) {
301
            return false;
302
        }
303 2
        $fetched = $prep->fetchAll(PDO::FETCH_NUM);
304 2
        if (!isset($fetched[0][0])) {
305
            return false;
306
        }
307 2
        return $fetched[0][0];
308
    }
309
310
    /**
311
     * deletes the entity from the database
312
     *
313
     * @param BaseEntity $entity
314
     * @return bool
315
     */
316 1
    public function deleteFromDatabase(BaseEntity $entity)
317
    {
318 1
        $sql = 'DELETE FROM ' . $entity->getTableName() . ' WHERE id=:id';
319 1
        $params = ['id' => $entity->id];
320 1
        $prep = $this->getConnection()->prepare($sql);
321 1
        return $prep->execute($params);
322
    }
323
324
    /**
325
     * frees up any resources / files locks
326
     * behaviour of service calls after disposing it is undefined
327
     */
328 18
    public function dispose()
329
    {
330 18
        $this->database = null;
331 18
    }
332
333
    /**
334
     * get the first entry from the database which matches the conditions
335
     *
336
     * @param BaseEntity $entity
337
     * @param int $entityId
338
     * @return Comic
339
     */
340 5
    public function getSingleByIdFromDatabase(BaseEntity $entity, $entityId)
341
    {
342 5
        return $this->getSingleFromDatabase($entity, 'id = :id', ['id' => $entityId]);
343
    }
344
}
345