Completed
Pull Request — master (#48)
by Andreas
01:36
created

CfpPersistenceLayer::insert()   B

Complexity

Conditions 5
Paths 10

Size

Total Lines 48
Code Lines 36

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 48
c 0
b 0
f 0
rs 8.551
cc 5
eloc 36
nc 10
nop 1
1
<?php
2
3
/**
4
 * Copyright (c) 2016-2016} Andreas Heigl<[email protected]>
5
 *
6
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7
 * of this software and associated documentation files (the "Software"), to deal
8
 * in the Software without restriction, including without limitation the rights
9
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
 * copies of the Software, and to permit persons to whom the Software is
11
 * furnished to do so, subject to the following conditions:
12
 *
13
 * The above copyright notice and this permission notice shall be included in
14
 * all copies or substantial portions of the Software.
15
 *
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
 * THE SOFTWARE.
23
 *
24
 * @author    Andreas Heigl<[email protected]>
25
 * @copyright 2016-2016 Andreas Heigl
26
 * @license   http://www.opensource.org/licenses/mit-license.php MIT-License
27
 * @version   0.0
28
 * @since     19.01.2016
29
 * @link      http://github.com/joindin/callingallpapers-api
30
 */
31
32
namespace Callingallpapers\Api\PersistenceLayer;
33
34
use function array_filter;
35
use Callingallpapers\Api\Entity\Cfp;
36
use Camel\CaseTransformer;
37
use Camel\Format\CamelCase;
38
use Camel\Format\SnakeCase;
39
use DateTime;
40
use Monolog\Logger;
41
use Org_Heigl\PdoTimezoneHelper\Handler\PdoTimezoneHandlerInterface;
42
43
class CfpPersistenceLayer
44
{
45
    protected $pdo;
46
47
    private $timezoneHelper;
48
49
    public function __construct(\PDO $pdo, PdoTimezoneHandlerInterface $timezoneHelper)
50
    {
51
        $this->pdo = $pdo;
52
        $this->timezoneHelper = $timezoneHelper;
53
    }
54
55
    public function insert(Cfp $cfp)
56
    {
57
        try {
58
            $this->select($cfp->getHash());
59
            $cfpExists = true;
60
        } catch (\UnexpectedValueException $e) {
61
            $cfpExists = false;
62
        }
63
64
        if ($cfpExists) {
65
            throw new \UnexpectedValueException(sprintf(
66
                'There is already a CFP with URL "%1$s".',
67
                $cfp->getEventUri()
68
            ), 400);
69
        }
70
71
        if ($cfp->getDateCfpStart()->getTimestamp() < 10000) {
72
            $cfp->setDateCfpStart(new \DateTimeImmutable());
73
        }
74
        $statement = 'INSERT into `cfp`(`dateCfpStart`, `dateCfpEnd`, `dateEventStart`, `dateEventEnd`, `name`, `uri`, `hash`, `timezone`, `description`, `eventUri`, `iconUri`, `latitude`, `longitude`, `location`, `tags`, `source`, `lastUpdate`) ' .
75
                     'VALUES (:dateCfpStart, :dateCfpEnd, :dateEventStart, :dateEventEnd, :name, :uri, :hash, :timezone, :description, :eventUri, :iconUri, :latitude, :longitude, :location, :tags, :source, :lastUpdate);';
76
        $statement = $this->pdo->prepare($statement);
77
78
        $values = [
79
            'dateCfpStart'   => $cfp->getDateCfpStart()->format('c'),
80
            'dateCfpEnd'     => $cfp->getDateCfpEnd()->format('c'),
81
            'dateEventStart' => $cfp->getDateEventStart()->format('c'),
82
            'dateEventEnd'   => $cfp->getDateEventEnd()->format('c'),
83
            'name'           => $cfp->getName(),
84
            'uri'            => $cfp->getUri(),
85
            'hash'           => $cfp->getHash(),
86
            'timezone'       => $cfp->getTimezone()->getName(),
87
            'description'    => $cfp->getDescription(),
88
            'eventUri'       => $cfp->getEventUri(),
89
            'iconUri'        => $cfp->getIconUri(),
90
            'latitude'       => $cfp->getLatitude(),
91
            'longitude'      => $cfp->getLongitude(),
92
            'location'       => $cfp->getLocation(),
93
            'tags'           => implode(',', $cfp->getTags()),
94
            'source'         => implode(',', array_filter(array_unique($cfp->getSource())),
95
            'lastUpdate'     => (new \DateTime('now', new \DateTimezone('UTC')))->format('c'),
0 ignored issues
show
Bug introduced by
This code did not parse for me. Apparently, there is an error somewhere around this line:

Syntax error, unexpected T_DOUBLE_ARROW, expecting ',' or ')'
Loading history...
96
        ];
97
98
        if ($statement->execute($values)) {
99
            return $values['hash'];
100
        }
101
102
        throw new \UnexpectedValueException('The CfP could not be stored', 400);
103
    }
104
105
    public function update(Cfp $cfp, $fetchHash)
106
    {
107
        if (! $fetchHash) {
108
            throw new \UnexpectedValueException('No Hash given', 400);
109
        }
110
        $oldValues = $this->select($fetchHash);
111
        if ($oldValues->count() != 1) {
112
            throw new \UnexpectedValueException('There is no CFP with this URL.', 404);
113
        }
114
        $statementElements = [];
115
        $values = [];
116
        $oldValues = $oldValues->current();
117
        $options = [
118
            'dateCfpStart',
119
            'dateCfpEnd',
120
            'name',
121
            'uri',
122
            'hash',
123
            'timezone',
124
            'dateEventStart',
125
            'dateEventEnd',
126
            'description',
127
            'eventUri',
128
            'iconUri',
129
            'latitude',
130
            'longitude',
131
            'location',
132
            'tags',
133
            'source',
134
        ];
135
136
        foreach ($options as $option) {
137
            $method = 'get' . $option;
138
           // Merge values from tags and source before comparing!
139
            if (in_array($option, ['tags', 'source'])) {
140
                $setter = 'set' . $option;
141
                $cfp->$setter(array_merge($oldValues->$method(), $cfp->$method()));
142
            }
143
            if ($cfp->$method() !== $oldValues->$method()) {
144
                if ($option == 'dateCfpStart' && $cfp->$method()->getTimestamp() < 100000) {
145
                    continue;
146
                }
147
                $statementElements[] = '`' . $option . '` = :' . $option;
148
                $values[$option]     = $cfp->$method();
149
                if ($values[$option] instanceof \DateTimeInterface) {
150
                    $values[$option] = $values[$option]->format('c');
151
                }
152
                if ($values[$option] instanceof \DateTimeZone) {
153
                    $values[$option] = $values[$option]->getName();
154
                }
155
                if (is_array($values[$option])) {
156
                    $values[$option] = implode(',', array_unique($values[$option]));
157
                }
158
            }
159
        }
160
161
        // No values to update, just, return
162
        if (empty($values)) {
163
            return $cfp->getHash();
164
        }
165
166
        $statement = 'UPDATE `cfp` SET '
167
                   . implode(',', $statementElements) . ','
168
                   . '`lastUpdate` = :lastUpdate '
169
                   . 'WHERE `hash` = :fetchHash';
170
        $statement = $this->pdo->prepare($statement);
171
        $values['fetchHash']  = $fetchHash;
172
        $values['lastUpdate'] = (new \DateTime('now', new \DateTimezone('UTC')))->format('c');
173
174
        if ($statement->execute($values)) {
175
            return $cfp->getHash();
176
        }
177
178
        throw new \UnexpectedValueException('The CfP could not be updated', 400);
179
    }
180
181
182
    public function select($hash = null)
183
    {
184
        $statement = 'SELECT * FROM `cfp`';
185
        $values = [];
186
        if ($hash !== null) {
187
            $statement .= ' WHERE `hash`= :hash';
188
            $values['hash'] = $hash;
189
        }
190
191
        $statement = $this->pdo->prepare($statement);
192
193
        $list = new \Callingallpapers\Api\Entity\CfpList();
194
        $statement->execute($values);
195
        $content = $statement->fetchAll();
196
        if (count($content) < 1) {
197
            throw new \UnexpectedValueException('No CFPs found', 404);
198
        }
199
200
        foreach ($content as $item) {
201
            $cfp = new \Callingallpapers\Api\Entity\Cfp();
202
            $cfp->setName($item['name']);
203
            $cfp->setDateCfpEnd(new \DateTimeImmutable($item['dateCfpEnd']));
204
            $cfp->setDateCfpStart(new \DateTimeImmutable($item['dateCfpStart']));
205
            $cfp->setUri($item['uri']);
206
            $cfp->setTimezone(new \DateTimeZone($item['timezone']));
207
            $cfp->setDateEventStart(new \DateTimeImmutable($item['dateEventStart']));
208
            $cfp->setDateEventEnd(new \DateTimeImmutable($item['dateEventEnd']));
209
            $cfp->setDescription($item['description']);
210
            $cfp->setEventUri($item['eventUri']);
211
            $cfp->setIconUri($item['iconUri']);
212
            $cfp->setLatitude($item['latitude']);
213
            $cfp->setLongitude($item['longitude']);
214
            $cfp->setLocation($item['location']);
215
            $cfp->setTags(explode(',', $item['tags']));
216
            $cfp->setLastUpdated(new \DateTimeImmutable($item['lastUpdate']));
217
            $cfp->setSource(explode(',', $item['source']));
218
219
            $list->add($cfp);
220
        }
221
222
        return $list;
223
    }
224
225
    public function delete($hash)
226
    {
227
        $statement = 'DELETE FROM `cfp` WHERE `hash` = :hash';
228
229
        $statement = $this->pdo->prepare($statement);
230
231
        return $statement->execute(['hash' => $hash]);
232
    }
233
234
    public function getCurrent(\DateTimeInterface $startDate = null, \DateTimeInterface $endDate = null)
235
    {
236
        $statement = 'SELECT * FROM `cfp` WHERE dateCfpEnd > :end AND dateCfpStart < :start';
237
238
        $statement = $this->pdo->prepare($statement);
239
240
        $now = new \DateTime();
241
        if (null === $startDate) {
242
            $startDate = $now;
243
        }
244
        if (null === $endDate) {
245
            $endDate = $now;
246
        }
247
248
        $list = new \Callingallpapers\Api\Entity\CfpList();
249
        $statement->execute([
250
            'end'   => $endDate->format('c'),
251
            'start' => $startDate->format('c'),
252
        ]);
253
254
        $content = $statement->fetchAll();
255
        if (count($content) < 1) {
256
            throw new \UnexpectedValueException('No CFPs found', 404);
257
        }
258
259
        foreach ($content as $item) {
260
            $cfp = new \Callingallpapers\Api\Entity\Cfp();
261
            $cfp->setName($item['name']);
262
            $cfp->setDateCfpEnd(new \DateTimeImmutable($item['dateCfpEnd']));
263
            $cfp->setDateCfpStart(new \DateTimeImmutable($item['dateCfpStart']));
264
            $cfp->setUri($item['uri']);
265
            $cfp->setTimezone(new \DateTimeZone($item['timezone']));
266
            $cfp->setDateEventStart(new \DateTimeImmutable($item['dateEventStart']));
267
            $cfp->setDateEventEnd(new \DateTimeImmutable($item['dateEventEnd']));
268
            $cfp->setDescription($item['description']);
269
            $cfp->setEventUri($item['eventUri']);
270
            $cfp->setIconUri($item['iconUri']);
271
            $cfp->setLatitude($item['latitude']);
272
            $cfp->setLongitude($item['longitude']);
273
            $cfp->setLocation($item['location']);
274
            $cfp->setTags(explode(',', $item['tags']));
275
            $cfp->setLastUpdated(new \DateTimeImmutable($item['lastUpdate']));
276
            $cfp->setSource(explode(',', $item['source']));
277
278
            $list->add($cfp);
279
        }
280
281
        return $list;
282
    }
283
284
    public function search(array $parameters)
285
    {
286
        $fields = [
287
            'name',
288
            'tags',
289
            'date_cfp_end',
290
            'date_cfp_start',
291
            'date_event_end',
292
            'date_event_start',
293
            'latitude',
294
            'longitude',
295
296
        ];
297
        $transformer = new CaseTransformer(new SnakeCase(), new CamelCase());
298
299
        $statement = 'SELECT * FROM `cfp` WHERE ';
300
        $values    = [];
301
        $where = [];
302
        foreach ($parameters as $key => $value) {
303
            if (! in_array($key, $fields)) {
304
                continue;
305
            }
306
            if (! is_array($value)) {
307
                $value = [$value];
308
            }
309
            foreach ($value as $itemkey => $item) {
310
                $compare = '=';
311
                if (in_array($key, [
312
                    'date_cfp_end',
313
                    'date_cfp_start',
314
                    'date_event_end',
315
                    'date_event_start'
316
                ])) {
317
                    if (array_key_exists($key . '_compare', $parameters) && isset($parameters[$key . '_compare'][$itemkey]) && in_array($parameters[$key . '_compare'][$itemkey], ['=', '<', '>', '<>'])) {
318
                        $compare = $parameters[$key . '_compare'][$itemkey];
319
                    }
320
                    $where[] = $this->timezoneHelper->getUtcDateTime($transformer->transform($key)) . ' ' . $compare . ' :' . $key . '_' . $itemkey;
321
                    $value = (new DateTime($item))->setTimezone(new \DateTimeZone('UTC'))->format('c');
322
                } else {
323
                    $where[] = '`' . $transformer->transform($key) . '` ' . $compare . ' :' . $key;
324
                }
325
                $values[$key . '_' . $itemkey] = $value;
326
            }
327
        }
328
        if (! $where) {
329
            throw new \UnexpectedValueException('No CFPs found', 404);
330
        }
331
332
        $statement .= implode(' AND ', $where) . ' ORDER BY dateCfpEnd ASC';
333
334
        $statement = $this->pdo->prepare($statement);
335
336
        $statement->execute($values);
337
        $content = $statement->fetchAll();
338
        if (count($content) < 1) {
339
            throw new \UnexpectedValueException('No CFPs found', 404);
340
        }
341
342
        $list = new \Callingallpapers\Api\Entity\CfpList();
343
        foreach ($content as $item) {
344
            $cfp = new \Callingallpapers\Api\Entity\Cfp();
345
            $cfp->setName($item['name']);
346
            $cfp->setDateCfpEnd(new \DateTimeImmutable($item['dateCfpEnd']));
347
            $cfp->setDateCfpStart(new \DateTimeImmutable($item['dateCfpStart']));
348
            $cfp->setUri($item['uri']);
349
            $cfp->setTimezone(new \DateTimeZone($item['timezone']));
350
            $cfp->setDateEventStart(new \DateTimeImmutable($item['dateEventStart']));
351
            $cfp->setDateEventEnd(new \DateTimeImmutable($item['dateEventEnd']));
352
            $cfp->setDescription($item['description']);
353
            $cfp->setEventUri($item['eventUri']);
354
            $cfp->setIconUri($item['iconUri']);
355
            $cfp->setLatitude($item['latitude']);
356
            $cfp->setLongitude($item['longitude']);
357
            $cfp->setLocation($item['location']);
358
            $cfp->setTags(explode(',', $item['tags']));
359
            $cfp->setLastUpdated(new \DateTimeImmutable($item['lastUpdate']));
360
         //   $cfp->setSource(explode(',', $item['source']));
361
362
            $list->add($cfp);
363
        }
364
365
        return $list;
366
    }
367
}
368