Completed
Push — master ( 2cff5f...81de03 )
by Michael
03:19
created

CommonEveApiTrait::oneShot()   D

Complexity

Conditions 9
Paths 11

Size

Total Lines 35
Code Lines 26

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 0 Features 1
Metric Value
c 3
b 0
f 1
dl 0
loc 35
rs 4.909
cc 9
eloc 26
nc 11
nop 1
1
<?php
2
/**
3
 * Contains CommonEveApiTrait trait.
4
 *
5
 * PHP version 5.5
6
 *
7
 * LICENSE:
8
 * This file is part of Yet Another Php Eve Api Library also know as Yapeal
9
 * which can be used to access the Eve Online API data and place it into a
10
 * database.
11
 * Copyright (C) 2015-2016 Michael Cummings
12
 *
13
 * This program is free software: you can redistribute it and/or modify it
14
 * under the terms of the GNU Lesser General Public License as published by the
15
 * Free Software Foundation, either version 3 of the License, or (at your
16
 * option) any later version.
17
 *
18
 * This program is distributed in the hope that it will be useful, but WITHOUT
19
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
21
 * for more details.
22
 *
23
 * You should have received a copy of the GNU Lesser General Public License
24
 * along with this program. If not, see
25
 * <http://www.gnu.org/licenses/>.
26
 *
27
 * You should be able to find a copy of this license in the LICENSE.md file. A
28
 * copy of the GNU GPL should also be available in the GNU-GPL.md file.
29
 *
30
 * @copyright 2015-2016 Michael Cummings
31
 * @license   http://www.gnu.org/copyleft/lesser.html GNU LGPL
32
 * @author    Michael Cummings <[email protected]>
33
 */
34
namespace Yapeal\EveApi;
35
36
use Monolog\Logger;
37
use Yapeal\CommonToolsTrait;
38
use Yapeal\Event\EveApiEventEmitterTrait;
39
use Yapeal\Event\EveApiEventInterface;
40
use Yapeal\Event\MediatorInterface;
41
use Yapeal\Xml\EveApiReadWriteInterface;
42
43
/**
44
 * Trait CommonEveApiTrait
45
 */
46
trait CommonEveApiTrait
47
{
48
    use CommonToolsTrait, EveApiEventEmitterTrait;
49
    /**
50
     * @param EveApiReadWriteInterface $data
51
     *
52
     * @return bool
53
     * @throws \DomainException
54
     * @throws \InvalidArgumentException
55
     * @throws \LogicException
56
     * @throws \Yapeal\Exception\YapealDatabaseException
57
     */
58
    public function oneShot(EveApiReadWriteInterface $data)
0 ignored issues
show
Coding Style introduced by
function oneShot() does not seem to conform to the naming convention (^(?:is|has|should|may|supports)).

This check examines a number of code elements and verifies that they conform to the given naming conventions.

You can set conventions for local variables, abstract classes, utility classes, constant, properties, methods, parameters, interfaces, classes, exceptions and special methods.

Loading history...
59
    {
60
        if (!$this->gotApiLock($data)) {
61
            return false;
62
        }
63
        $result = true;
64
        $eventSuffixes = ['retrieve', 'transform', 'validate', 'preserve'];
65
        foreach ($eventSuffixes as $eventSuffix) {
66
            if (false === $this->emitEvents($data, $eventSuffix)) {
67
                $result = false;
68
                break;
69
            }
70
            if (false === $data->getEveApiXml()) {
71
                if ($data->hasEveApiArgument('accountKey') && '10000' === $data->getEveApiArgument('accountKey')
72
                    && 'corp' === strtolower($data->getEveApiSectionName())
73
                ) {
74
                    $mess = 'No faction warfare account data in';
75
                    $this->getYem()
76
                        ->triggerLogEvent('Yapeal.Log.log', Logger::INFO, $this->createEveApiMessage($mess, $data));
77
                    break;
78
                }
79
                $this->getYem()
80
                    ->triggerLogEvent('Yapeal.Log.log', Logger::NOTICE,
81
                        $this->getEmptyXmlDataMessage($data, $eventSuffix));
82
                $result = false;
83
                break;
84
            }
85
        }
86
        if ($result) {
87
            $this->updateCachedUntil($data);
88
            $this->emitEvents($data, 'end');
89
        }
90
        $this->releaseApiLock($data);
91
        return $result;
92
    }
93
    /**
94
     * @param EveApiEventInterface $event
95
     * @param string               $eventName
96
     * @param MediatorInterface    $yem
97
     *
98
     * @return EveApiEventInterface
99
     * @throws \DomainException
100
     * @throws \InvalidArgumentException
101
     * @throws \LogicException
102
     * @throws \Yapeal\Exception\YapealDatabaseException
103
     */
104
    public function startEveApi(EveApiEventInterface $event, $eventName, MediatorInterface $yem)
105
    {
106
        if (!$this->hasYem()) {
107
            $this->setYem($yem);
108
        }
109
        $data = $event->getData();
110
        $yem->triggerLogEvent('Yapeal.Log.log', Logger::DEBUG,
111
            $this->getReceivedEventMessage($data, $eventName, __CLASS__));
112
        // If method doesn't exist still needs array with member for count but return '0' from extractOwnerID().
113
        $active = method_exists($this, 'getActive') ? $this->getActive($data) : [[null]];
114
        if (0 === count($active)) {
115
            $mess = 'No active owners found for';
116
            $yem->triggerLogEvent('Yapeal.Log.log', Logger::INFO, $this->createEveApiMessage($mess, $data));
117
            $this->emitEvents($data, 'end');
118
            return $event->setHandledSufficiently();
119
        }
120
        $untilInterval = $data->getCacheInterval();
121
        foreach ($active as $arguments) {
122
            // Set arguments, reset interval, and clear xml data.
123
            $data->setEveApiArguments($arguments)
124
                ->setCacheInterval($untilInterval)
125
                ->setEveApiXml();
126
            /** @noinspection DisconnectedForeachInstructionInspection */
127
            foreach ($this->accountKeys as $accountKey) {
128
                $data->addEveApiArgument('accountKey', $accountKey);
129
                /** @noinspection DisconnectedForeachInstructionInspection */
130
                if (0 === strpos(strtolower($data->getEveApiName()), 'wallet')) {
131
                    $data->addEveApiArgument('rowCount', '2560');
132
                }
133
                /** @noinspection DisconnectedForeachInstructionInspection */
134
                if ($this->cachedUntilIsNotExpired($data)) {
135
                    $event->setHandledSufficiently();
136
                    continue;
137
                }
138
                /** @noinspection DisconnectedForeachInstructionInspection */
139
                if ($this->oneShot($data)) {
140
                    $event->setHandledSufficiently();
141
                }
142
            }
143
        }
144
        return $event;
145
    }
146
    /**
147
     * @param EveApiReadWriteInterface $data
148
     *
149
     * @return bool
150
     * @throws \DomainException
151
     * @throws \InvalidArgumentException
152
     * @throws \LogicException
153
     * @throws \Yapeal\Exception\YapealDatabaseException
154
     */
155
    protected function cachedUntilIsNotExpired(EveApiReadWriteInterface $data)
0 ignored issues
show
Coding Style introduced by
function cachedUntilIsNotExpired() does not seem to conform to the naming convention (^(?:is|has|should|may|supports)).

This check examines a number of code elements and verifies that they conform to the given naming conventions.

You can set conventions for local variables, abstract classes, utility classes, constant, properties, methods, parameters, interfaces, classes, exceptions and special methods.

Loading history...
156
    {
157
        $columns = [
158
            'accountKey' => $data->hasEveApiArgument('accountKey') ? $data->getEveApiArgument('accountKey') : '0',
159
            'apiName' => $data->getEveApiName(),
160
            'ownerID' => $this->extractOwnerID($data->getEveApiArguments()),
161
            'sectionName' => $data->getEveApiSectionName()
162
        ];
163
        $sql = $this->getCsq()
164
            ->getUtilCachedUntilExpires($columns);
165
        $this->getYem()
166
            ->triggerLogEvent('Yapeal.Log.log', Logger::DEBUG, $sql);
167
        try {
168
            $expires = $this->getPdo()
169
                ->query($sql)
170
                ->fetchAll(\PDO::FETCH_ASSOC);
171
        } catch (\PDOException $exc) {
172
            $mess = 'Could NOT get cache expired for';
173
            $this->getYem()
174
                ->triggerLogEvent('Yapeal.Log.log', Logger::WARNING, $this->createEveApiMessage($mess, $data),
175
                    ['exception' => $exc]);
176
            return false;
177
        }
178
        if (0 === count($expires)) {
179
            $mess = 'No UtilCachedUntil record found for';
180
            $this->getYem()
181
                ->triggerLogEvent('Yapeal.Log.log', Logger::DEBUG, $this->createEveApiMessage($mess, $data));
182
            return false;
183
        }
184
        if (1 < count($expires)) {
185
            $mess = 'Multiple UtilCachedUntil records found for';
186
            $this->getYem()
187
                ->triggerLogEvent('Yapeal.Log.log', Logger::WARNING, $this->createEveApiMessage($mess, $data));
188
            return false;
189
        }
190
        if (strtotime($expires[0]['expires'] . '+00:00') < time()) {
191
            $mess = 'Expired UtilCachedUntil record found for';
192
            $this->getYem()
193
                ->triggerLogEvent('Yapeal.Log.log', Logger::DEBUG, $this->createEveApiMessage($mess, $data));
194
            return false;
195
        }
196
        return true;
197
    }
198
    /**
199
     * @param string[] $candidates
200
     *
201
     * @return string
202
     */
203
    protected function extractOwnerID(array $candidates)
204
    {
205
        foreach (['corporationID', 'characterID', 'keyID'] as $item) {
206
            if (array_key_exists($item, $candidates)) {
207
                return (string)$candidates[$item];
208
            }
209
        }
210
        return '0';
211
    }
212
    /**
213
     * @return int
214
     */
215
    protected function getMask()
216
    {
217
        return $this->mask;
218
    }
219
    /**
220
     * @param EveApiReadWriteInterface $data
221
     *
222
     * @return bool
223
     * @throws \DomainException
224
     * @throws \InvalidArgumentException
225
     * @throws \LogicException
226
     * @throws \Yapeal\Exception\YapealDatabaseException
227
     */
228
    protected function gotApiLock(EveApiReadWriteInterface $data)
0 ignored issues
show
Coding Style introduced by
function gotApiLock() does not seem to conform to the naming convention (^(?:is|has|should|may|supports)).

This check examines a number of code elements and verifies that they conform to the given naming conventions.

You can set conventions for local variables, abstract classes, utility classes, constant, properties, methods, parameters, interfaces, classes, exceptions and special methods.

Loading history...
229
    {
230
        $sql = $this->getCsq()
231
            ->getApiLock($data->getHash());
232
        $this->getYem()
233
            ->triggerLogEvent('Yapeal.Log.log', Logger::DEBUG, $sql);
234
        $context = [];
235
        $success = false;
236
        try {
237
            $success = (bool)$this->getPdo()
238
                ->query($sql)
239
                ->fetchColumn();
240
        } catch (\PDOException $exc) {
241
            $context = ['exception' => $exc];
242
        }
243
        $mess = $success ? 'Got lock for' : 'Could NOT get lock for';
244
        $this->getYem()
245
            ->triggerLogEvent('Yapeal.Log.log', Logger::INFO, $this->createEveApiMessage($mess, $data), $context);
246
        return $success;
247
    }
248
    /**
249
     * @param EveApiReadWriteInterface $data
250
     *
251
     * @return bool
252
     * @throws \DomainException
253
     * @throws \InvalidArgumentException
254
     * @throws \LogicException
255
     * @throws \Yapeal\Exception\YapealDatabaseException
256
     */
257
    protected function releaseApiLock(EveApiReadWriteInterface $data)
0 ignored issues
show
Coding Style introduced by
function releaseApiLock() does not seem to conform to the naming convention (^(?:is|has|should|may|supports)).

This check examines a number of code elements and verifies that they conform to the given naming conventions.

You can set conventions for local variables, abstract classes, utility classes, constant, properties, methods, parameters, interfaces, classes, exceptions and special methods.

Loading history...
258
    {
259
        $sql = $this->getCsq()
260
            ->getApiLockRelease($data->getHash());
261
        $this->getYem()
262
            ->triggerLogEvent('Yapeal.Log.log', Logger::DEBUG, $sql);
263
        $context = [];
264
        $success = false;
265
        try {
266
            $success = (bool)$this->getPdo()
267
                ->query($sql)
268
                ->fetchColumn();
269
        } catch (\PDOException $exc) {
270
            $context = ['exception' => $exc];
271
        }
272
        $mess = $success ? 'Released lock for' : 'Could NOT release lock for';
273
        $this->getYem()
274
            ->triggerLogEvent('Yapeal.Log.log', Logger::INFO, $this->createEveApiMessage($mess, $data), $context);
275
        return $success;
276
    }
277
    /**
278
     * @param EveApiReadWriteInterface $data
279
     *
280
     * @return self Fluent interface.
281
     * @throws \DomainException
282
     * @throws \InvalidArgumentException
283
     * @throws \LogicException
284
     * @throws \Yapeal\Exception\YapealDatabaseException
285
     */
286
    protected function updateCachedUntil(EveApiReadWriteInterface $data)
287
    {
288
        if (false === $data->getEveApiXml()) {
289
            return $this;
290
        }
291
        /** @noinspection PhpUndefinedFieldInspection */
292
        /** @noinspection UnnecessaryParenthesesInspection */
293
        $currentTime = (string)(new \SimpleXMLElement($data->getEveApiXml()))->currentTime[0];
294
        if ('' === $currentTime) {
295
            return $this;
296
        }
297
        $dateTime = gmdate('Y-m-d H:i:s', strtotime($currentTime . '+00:00') + $data->getCacheInterval());
298
        $row = [
299
            'accountKey' => $data->hasEveApiArgument('accountKey') ? $data->getEveApiArgument('accountKey') : '0',
300
            'apiName' => $data->getEveApiName(),
301
            'expires' => $dateTime,
302
            'ownerID' => $this->extractOwnerID($data->getEveApiArguments()),
303
            'sectionName' => $data->getEveApiSectionName()
304
        ];
305
        $sql = $this->getCsq()
306
            ->getUpsert('utilCachedUntil', array_keys($row), 1);
307
        $this->getYem()
308
            ->triggerLogEvent('Yapeal.Log.log', Logger::DEBUG, $sql);
309
        $pdo = $this->getPdo();
310
        $pdo->beginTransaction();
311
        $context = [];
312
        $success = false;
313
        try {
314
            $pdo->prepare($sql)
315
                ->execute(array_values($row));
316
            $pdo->commit();
317
            $success = true;
318
        } catch (\PDOException $exc) {
319
            $pdo->rollBack();
320
            $context = ['exception' => $exc];
321
        }
322
        $mess = $success ? 'Updated cached until date/time of' : 'Could NOT update cached until date/time of';
323
        $this->getYem()
324
            ->triggerLogEvent('Yapeal.Log.log', Logger::INFO, $this->createEveApiMessage($mess, $data), $context);
325
        return $this;
326
    }
327
    /**
328
     * @var int[] $accountKey
329
     */
330
    protected $accountKeys = [0];
331
    /**
332
     * @var int $mask
333
     */
334
    protected $mask;
335
}
336