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) |
|
|
|
|
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) |
|
|
|
|
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) |
|
|
|
|
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) |
|
|
|
|
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
|
|
|
|
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.