Completed
Push — development ( daed94...13a157 )
by Thomas
18s
created

GeoCacheRepository   A

Complexity

Total Complexity 24

Size/Duplication

Total Lines 334
Duplicated Lines 31.44 %

Coupling/Cohesion

Components 1
Dependencies 8

Importance

Changes 0
Metric Value
dl 105
loc 334
rs 10
c 0
b 0
f 0
wmc 24
lcom 1
cbo 8

10 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A fetchAll() 21 21 3
B fetchOneBy() 23 23 4
B fetchBy() 28 28 5
A fetchGCWaypoint() 0 23 3
A create() 0 17 2
A update() 18 18 2
A remove() 15 15 2
B getDatabaseArrayFromEntity() 0 40 1
B getEntityFromDatabaseArray() 0 41 1

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php
2
3
namespace Oc\GeoCache\Persistence\GeoCache;
4
5
use DateTime;
6
use Doctrine\DBAL\Connection;
7
use Oc\GeoCache\Enum\WaypointType;
8
use Oc\Repository\Exception\RecordAlreadyExistsException;
9
use Oc\Repository\Exception\RecordNotFoundException;
10
use Oc\Repository\Exception\RecordNotPersistedException;
11
use Oc\Repository\Exception\RecordsNotFoundException;
12
13
class GeoCacheRepository
14
{
15
    /**
16
     * Database table name that this repository maintains.
17
     *
18
     * @var string
19
     */
20
    const TABLE = 'caches';
21
22
    /**
23
     * @var Connection
0 ignored issues
show
introduced by
Connection => \Doctrine\DBAL\Connection
Loading history...
24
     */
25
    private $connection;
26
27
    /**
28
     * GeoCacheRepository constructor.
29
     *
30
     * @param Connection $connection
0 ignored issues
show
introduced by
Connection => \Doctrine\DBAL\Connection
Loading history...
31
     */
32
    public function __construct(Connection $connection)
33
    {
34
        $this->connection = $connection;
35
    }
36
37
    /**
38
     * Fetches all GeoCaches.
39
     *
40
     * @return GeoCacheEntity[]
0 ignored issues
show
introduced by
GeoCacheEntity[] => \Array\GeoCacheEntity[]
Loading history...
41
     *
42
     * @throws RecordsNotFoundException Thrown when no records are found
0 ignored issues
show
introduced by
RecordsNotFoundException => \Oc\Repository\Exception\RecordsNotFoundException
Loading history...
Coding Style introduced by
@throws tag comment must end with a full stop
Loading history...
43
     */
44 View Code Duplication
    public function fetchAll()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
45
    {
46
        $statement = $this->connection->createQueryBuilder()
47
            ->select('*')
48
            ->from(self::TABLE)
49
            ->execute();
50
51
        $result = $statement->fetchAll();
52
53
        if ($statement->rowCount() === 0) {
54
            throw new RecordsNotFoundException('No records found');
55
        }
56
57
        $records = [];
58
59
        foreach ($result as $item) {
60
            $records[] = $this->getEntityFromDatabaseArray($item);
61
        }
62
63
        return $records;
64
    }
65
66
    /**
67
     * Fetches a GeoCache by given where clause.
68
     *
69
     * @param array $where
70
     *
71
     * @return null|GeoCacheEntity
0 ignored issues
show
introduced by
GeoCacheEntity => \Array\GeoCacheEntity
Loading history...
72
     *
73
     * @throws RecordNotFoundException Thrown when no record is found
0 ignored issues
show
introduced by
RecordNotFoundException => \Oc\Repository\Exception\RecordNotFoundException
Loading history...
Coding Style introduced by
@throws tag comment must end with a full stop
Loading history...
74
     */
75 View Code Duplication
    public function fetchOneBy(array $where = [])
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
76
    {
77
        $queryBuilder = $this->connection->createQueryBuilder()
78
             ->select('*')
79
             ->from(self::TABLE)
80
             ->setMaxResults(1);
81
82
        if (count($where) > 0) {
83
            foreach ($where as $column => $value) {
84
                $queryBuilder->andWhere($column . ' = ' .  $queryBuilder->createNamedParameter($value));
0 ignored issues
show
introduced by
Expected 1 space after ., but 2 found
Loading history...
85
            }
86
        }
87
88
        $statement = $queryBuilder->execute();
89
90
        $result = $statement->fetch();
91
92
        if ($statement->rowCount() === 0) {
93
            throw new RecordNotFoundException('Record with given where clause not found');
94
        }
95
96
        return $this->getEntityFromDatabaseArray($result);
97
    }
98
99
    /**
100
     * Fetches all GeoCaches by given where clause.
101
     *
102
     * @param array $where
103
     *
104
     * @return GeoCacheEntity[]
0 ignored issues
show
introduced by
GeoCacheEntity[] => \Array\GeoCacheEntity[]
Loading history...
105
     *
106
     * @throws RecordsNotFoundException Thrown when no records are found
0 ignored issues
show
introduced by
RecordsNotFoundException => \Oc\Repository\Exception\RecordsNotFoundException
Loading history...
Coding Style introduced by
@throws tag comment must end with a full stop
Loading history...
107
     */
108 View Code Duplication
    public function fetchBy(array $where = [])
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
109
    {
110
        $queryBuilder = $this->connection->createQueryBuilder()
111
             ->select('*')
112
             ->from(self::TABLE);
113
114
        if (count($where) > 0) {
115
            foreach ($where as $column => $value) {
116
                $queryBuilder->andWhere($column . ' = ' .  $queryBuilder->createNamedParameter($value));
0 ignored issues
show
introduced by
Expected 1 space after ., but 2 found
Loading history...
117
            }
118
        }
119
120
        $statement = $queryBuilder->execute();
121
122
        $result = $statement->fetchAll();
123
124
        if ($statement->rowCount() === 0) {
125
            throw new RecordsNotFoundException('No records with given where clause found');
126
        }
127
128
        $geoCaches = [];
129
130
        foreach ($result as $item) {
131
            $geoCaches[] = $this->getEntityFromDatabaseArray($item);
132
        }
133
134
        return $geoCaches;
135
    }
136
137
    /**
138
     * Fetches a GeoCache by given where clause.
139
     *
140
     * @param string $waypoint
141
     *
142
     * @return null|GeoCacheEntity
0 ignored issues
show
introduced by
GeoCacheEntity => \Array\GeoCacheEntity
Loading history...
143
     *
144
     * @throws RecordNotFoundException Thrown when no record is found
0 ignored issues
show
introduced by
RecordNotFoundException => \Oc\Repository\Exception\RecordNotFoundException
Loading history...
Coding Style introduced by
@throws tag comment must end with a full stop
Loading history...
145
     */
146
    public function fetchGCWaypoint($waypoint)
147
    {
148
        if (WaypointType::guess($waypoint) !== WaypointType::GC) {
149
            throw new RecordNotFoundException('Record by given gc waypoint not found');
150
        }
151
152
        $queryBuilder = $this->connection->createQueryBuilder()
153
            ->select('*')
154
            ->from(self::TABLE)
155
            ->where("IFELSE(wp_gc_maintained = '', wp_gc, g.wp_gc_maintained) = :waypoint")
156
            ->setParameter(':waypoint', $waypoint)
157
            ->setMaxResults(1);
158
159
        $statement = $queryBuilder->execute();
160
161
        $result = $statement->fetch();
162
163
        if ($statement->rowCount() === 0) {
164
            throw new RecordNotFoundException('Record by given gc waypoint not found');
165
        }
166
167
        return $this->getEntityFromDatabaseArray($result);
168
    }
169
170
    /**
171
     * Creates a GeoCache in the database.
172
     *
173
     * @param GeoCacheEntity $entity
0 ignored issues
show
introduced by
GeoCacheEntity => \Array\GeoCacheEntity
Loading history...
174
     *
175
     * @return GeoCacheEntity
0 ignored issues
show
introduced by
GeoCacheEntity => \Array\GeoCacheEntity
Loading history...
176
     *
177
     * @throws RecordAlreadyExistsException
0 ignored issues
show
introduced by
RecordAlreadyExistsException => \Oc\Repository\Exception\RecordAlreadyExistsException
Loading history...
178
     */
179
    public function create(GeoCacheEntity $entity)
180
    {
181
        if (!$entity->isNew()) {
182
            throw new RecordAlreadyExistsException('The entity does already exist.');
183
        }
184
185
        $databaseArray = $this->getDatabaseArrayFromEntity($entity);
186
187
        $this->connection->insert(
188
            self::TABLE,
189
            $databaseArray
190
        );
191
192
        $entity->cacheId = $this->connection->lastInsertId();
0 ignored issues
show
Documentation Bug introduced by
The property $cacheId was declared of type integer, but $this->connection->lastInsertId() is of type string. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
193
194
        return $entity;
195
    }
196
197
    /**
198
     * Update a GeoCache in the database.
199
     *
200
     * @param GeoCacheEntity $entity
0 ignored issues
show
introduced by
GeoCacheEntity => \Array\GeoCacheEntity
Loading history...
201
     *
202
     * @return GeoCacheEntity
0 ignored issues
show
introduced by
GeoCacheEntity => \Array\GeoCacheEntity
Loading history...
203
     *
204
     * @throws RecordNotPersistedException
0 ignored issues
show
introduced by
RecordNotPersistedException => \Oc\Repository\Exception\RecordNotPersistedException
Loading history...
205
     */
206 View Code Duplication
    public function update(GeoCacheEntity $entity)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
207
    {
208
        if ($entity->isNew()) {
209
            throw new RecordNotPersistedException('The entity does not exist.');
210
        }
211
212
        $databaseArray = $this->getDatabaseArrayFromEntity($entity);
213
214
        $this->connection->update(
215
            self::TABLE,
216
            $databaseArray,
217
            ['cache_id' => $entity->cacheId]
218
        );
219
220
        $entity->cacheId = $this->connection->lastInsertId();
0 ignored issues
show
Documentation Bug introduced by
The property $cacheId was declared of type integer, but $this->connection->lastInsertId() is of type string. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
221
222
        return $entity;
223
    }
224
225
    /**
226
     * Removes a GeoCache from the database.
227
     *
228
     * @param GeoCacheEntity $entity
0 ignored issues
show
introduced by
GeoCacheEntity => \Array\GeoCacheEntity
Loading history...
229
     *
230
     * @return GeoCacheEntity
0 ignored issues
show
introduced by
GeoCacheEntity => \Array\GeoCacheEntity
Loading history...
231
     *
232
     * @throws RecordNotPersistedException
0 ignored issues
show
introduced by
RecordNotPersistedException => \Oc\Repository\Exception\RecordNotPersistedException
Loading history...
233
     */
234 View Code Duplication
    public function remove(GeoCacheEntity $entity)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
235
    {
236
        if ($entity->isNew()) {
237
            throw new RecordNotPersistedException('The entity does not exist.');
238
        }
239
240
        $this->connection->delete(
241
            self::TABLE,
242
            ['cache_id' => $entity->cacheId]
243
        );
244
245
        $entity->cacheId = null;
246
247
        return $entity;
248
    }
249
250
    /**
251
     * Maps the given entity to the database array.
252
     *
253
     * @param GeoCacheEntity $entity
0 ignored issues
show
introduced by
GeoCacheEntity => \Array\GeoCacheEntity
Loading history...
254
     *
255
     * @return array
256
     */
257
    public function getDatabaseArrayFromEntity(GeoCacheEntity $entity)
258
    {
259
        return [
260
            'cache_id' => $entity->cacheId,
261
            'uuid' => $entity->uuid,
262
            'node' => $entity->node,
263
            'date_created' => $entity->dateCreated->format(DateTime::ATOM),
264
            'is_publishdate' => $entity->isPublishdate,
265
            'last_modified' => $entity->lastModified->format(DateTime::ATOM),
266
            'okapi_syncbase' => $entity->okapiSyncbase,
267
            'listing_last_modified' => $entity->listingLastModified->format(DateTime::ATOM),
268
            'meta_last_modified' => $entity->metaLastModified->format(DateTime::ATOM),
269
            'user_id' => $entity->userId,
270
            'name' => $entity->name,
271
            'longitude' => $entity->longitude,
272
            'latitude' => $entity->latitude,
273
            'type' => $entity->type,
274
            'status' => $entity->status,
275
            'country' => $entity->country,
276
            'date_hidden' => $entity->dateHidden->format(DateTime::ATOM),
277
            'size' => $entity->size,
278
            'difficulty' => $entity->difficulty,
279
            'terrain' => $entity->terrain,
280
            'logpw' => $entity->logpw,
281
            'search_time' => $entity->searchTime,
282
            'way_length' => $entity->wayLength,
283
            'wp_gc' => $entity->wpGc,
284
            'wp_gc_maintained' => $entity->wpGcMaintained,
285
            'wp_oc' => $entity->wpOc,
286
            'desc_languages' => $entity->descLanguages,
287
            'default_desclang' => $entity->defaultDesclang,
288
            'date_activate' => $entity->dateActivate->format(DateTime::ATOM),
289
            'need_npa_recalc' => $entity->needNpaRecalc,
290
            'show_cachelists' => $entity->showCachelists,
291
            'protect_old_coords' => $entity->protectOldCoords,
292
            'needs_maintenance' => $entity->needsMaintenance,
293
            'listing_outdated' => $entity->listingOutdated,
294
            'flags_last_modified' => $entity->flagsLastModified->format(DateTime::ATOM)
295
        ];
296
    }
297
298
    /**
299
     * Prepares database array from properties.
300
     *
301
     * @param array $data
302
     *
303
     * @return GeoCacheEntity
0 ignored issues
show
introduced by
GeoCacheEntity => \Array\GeoCacheEntity
Loading history...
304
     */
305
    public function getEntityFromDatabaseArray(array $data)
306
    {
307
        $entity = new GeoCacheEntity();
308
        $entity->cacheId = $data['cache_id'];
309
        $entity->uuid = $data['uuid'];
310
        $entity->node = (int) $data['node'];
0 ignored issues
show
introduced by
No whitespace should be between cast and variable.
Loading history...
311
        $entity->dateCreated = new DateTime($data['date_created']);
312
        $entity->isPublishdate = (bool) $data['is_publishdate'];
0 ignored issues
show
introduced by
No whitespace should be between cast and variable.
Loading history...
313
        $entity->lastModified = new DateTime($data['last_modified']);
314
        $entity->okapiSyncbase = (int) $data['okapi_syncbase'];
0 ignored issues
show
introduced by
No whitespace should be between cast and variable.
Loading history...
315
        $entity->listingLastModified = new DateTime($data['listing_last_modified']);
316
        $entity->metaLastModified = new DateTime($data['meta_last_modified']);
317
        $entity->userId = (int) $data['user_id'];
0 ignored issues
show
introduced by
No whitespace should be between cast and variable.
Loading history...
318
        $entity->name = $data['name'];
319
        $entity->longitude = (double) $data['longitude'];
0 ignored issues
show
introduced by
No whitespace should be between cast and variable.
Loading history...
320
        $entity->latitude = (double) $data['latitude'];
0 ignored issues
show
introduced by
No whitespace should be between cast and variable.
Loading history...
321
        $entity->type = (int) $data['type'];
0 ignored issues
show
introduced by
No whitespace should be between cast and variable.
Loading history...
322
        $entity->status = (int) $data['status'];
0 ignored issues
show
introduced by
No whitespace should be between cast and variable.
Loading history...
323
        $entity->country = $data['country'];
324
        $entity->dateHidden = new DateTime($data['date_hidden']);
325
        $entity->size = (int) $data['size'];
0 ignored issues
show
introduced by
No whitespace should be between cast and variable.
Loading history...
326
        $entity->difficulty = (int) $data['difficulty'];
0 ignored issues
show
introduced by
No whitespace should be between cast and variable.
Loading history...
327
        $entity->terrain = (int) $data['terrain'];
0 ignored issues
show
introduced by
No whitespace should be between cast and variable.
Loading history...
328
        $entity->logpw = $data['logpw'];
329
        $entity->searchTime = (float) $data['search_time'];
0 ignored issues
show
introduced by
No whitespace should be between cast and variable.
Loading history...
330
        $entity->wayLength = (float) $data['way_length'];
0 ignored issues
show
introduced by
No whitespace should be between cast and variable.
Loading history...
331
        $entity->wpGc = $data['wp_gc'];
332
        $entity->wpGcMaintained = $data['wp_gc_maintained'];
333
        $entity->wpOc = $data['wp_oc'];
334
        $entity->descLanguages = $data['desc_languages'];
335
        $entity->defaultDesclang = $data['default_desclang'];
336
        $entity->dateActivate = new DateTime($data['date_activate']);
337
        $entity->needNpaRecalc = (bool) $data['need_npa_recalc'];
0 ignored issues
show
introduced by
No whitespace should be between cast and variable.
Loading history...
Documentation Bug introduced by
The property $needNpaRecalc was declared of type integer, but (bool) $data['need_npa_recalc'] is of type boolean. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
338
        $entity->showCachelists = (bool) $data['show_cachelists'];
0 ignored issues
show
introduced by
No whitespace should be between cast and variable.
Loading history...
Documentation Bug introduced by
The property $showCachelists was declared of type integer, but (bool) $data['show_cachelists'] is of type boolean. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
339
        $entity->protectOldCoords = (bool) $data['protect_old_coords'];
0 ignored issues
show
introduced by
No whitespace should be between cast and variable.
Loading history...
Documentation Bug introduced by
The property $protectOldCoords was declared of type integer, but (bool) $data['protect_old_coords'] is of type boolean. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
340
        $entity->needsMaintenance = (bool) $data['needs_maintenance'];
0 ignored issues
show
introduced by
No whitespace should be between cast and variable.
Loading history...
Documentation Bug introduced by
The property $needsMaintenance was declared of type integer, but (bool) $data['needs_maintenance'] is of type boolean. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
341
        $entity->listingOutdated = (bool) $data['listing_outdated'];
0 ignored issues
show
introduced by
No whitespace should be between cast and variable.
Loading history...
Documentation Bug introduced by
The property $listingOutdated was declared of type integer, but (bool) $data['listing_outdated'] is of type boolean. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
342
        $entity->flagsLastModified = new DateTime($data['flags_last_modified']);
343
344
        return $entity;
345
    }
346
}
347