Completed
Push — master ( 31b5db...524ecf )
by Michael
03:26
created

Creator::processRowset()   C

Complexity

Conditions 7
Paths 18

Size

Total Lines 31
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 56

Importance

Changes 3
Bugs 0 Features 0
Metric Value
c 3
b 0
f 0
dl 0
loc 31
ccs 0
cts 30
cp 0
rs 6.7272
cc 7
eloc 22
nc 18
nop 3
crap 56
1
<?php
2
declare(strict_types = 1);
3
/**
4
 * Contains Creator class.
5
 *
6
 * PHP version 7.0+
7
 *
8
 * LICENSE:
9
 * This file is part of Yet Another Php Eve Api Library also know as Yapeal
10
 * which can be used to access the Eve Online API data and place it into a
11
 * database.
12
 * Copyright (C) 2015-2016 Michael Cummings
13
 *
14
 * This program is free software: you can redistribute it and/or modify it
15
 * under the terms of the GNU Lesser General Public License as published by the
16
 * Free Software Foundation, either version 3 of the License, or (at your
17
 * option) any later version.
18
 *
19
 * This program is distributed in the hope that it will be useful, but WITHOUT
20
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
22
 * for more details.
23
 *
24
 * You should have received a copy of the GNU Lesser General Public License
25
 * along with this program. If not, see
26
 * <http://spdx.org/licenses/LGPL-3.0.html>.
27
 *
28
 * You should be able to find a copy of this license in the COPYING-LESSER.md
29
 * file. A copy of the GNU GPL should also be available in the COPYING.md file.
30
 *
31
 * @copyright 2015-2016 Michael Cummings
32
 * @license   http://www.gnu.org/copyleft/lesser.html GNU LGPL
33
 * @author    Michael Cummings <[email protected]>
34
 */
35
namespace Yapeal\EveApi;
36
37
use Yapeal\Console\Command\EveApiCreatorTrait;
38
use Yapeal\Event\EveApiEventInterface;
39
use Yapeal\Event\MediatorInterface;
40
use Yapeal\Log\Logger;
41
42
/**
43
 * Class Creator
44
 */
45
class Creator
46
{
47
    use EveApiCreatorTrait;
48
    /**
49
     * Creator constructor.
50
     *
51
     * @param \Twig_Environment $twig
52
     * @param string            $dir
53
     */
54
    public function __construct(\Twig_Environment $twig, string $dir = __DIR__)
55
    {
56
        $this->setDir($dir);
57
        $this->setTwig($twig);
58
    }
59
    /**
60
     * @param EveApiEventInterface $event
61
     * @param string               $eventName
62
     * @param MediatorInterface    $yem
63
     *
64
     * @return EveApiEventInterface
65
     * @throws \DomainException
66
     * @throws \InvalidArgumentException
67
     * @throws \LogicException
68
     */
69
    public function createEveApi(
70
        EveApiEventInterface $event,
71
        string $eventName,
72
        MediatorInterface $yem
73
    ): EveApiEventInterface
74
    {
75
        $this->setYem($yem);
76
        $data = $event->getData();
77
        $yem->triggerLogEvent('Yapeal.Log.log',
78
            Logger::DEBUG,
79
            $this->getReceivedEventMessage($data, $eventName, __CLASS__));
80
        // Only work with raw unaltered XML data.
81
        if (false !== strpos($data->getEveApiXml(), '<?yapeal.parameters.json')) {
82
            return $event->setHandledSufficiently();
83
        }
84
        $outputFile = sprintf('%1$s%2$s/%3$s.php',
85
            $this->getDir(),
86
            $data->getEveApiSectionName(),
87
            $data->getEveApiName());
88
        // Nothing to do if NOT overwriting and file exists.
89
        if (false === $this->isOverwrite() && is_file($outputFile)) {
90
            return $event;
91
        }
92
        $this->sectionName = $data->getEveApiSectionName();
93
        $sxi = new \SimpleXMLIterator($data->getEveApiXml());
94
        $this->tables = [];
95
        $this->processValueOnly($sxi, $data->getEveApiName());
96
        $this->processRowset($sxi, $data->getEveApiName());
97
        $tCount = count($this->tables);
98
        if (0 === $tCount) {
99
            $mess = 'No SQL tables to create for';
100
            $yem->triggerLogEvent('Yapeal.Log.log', Logger::NOTICE, $this->createEveApiMessage($mess, $data));
101
        }
102
        ksort($this->tables);
103
        $vars = [
104
            'className' => ucfirst($data->getEveApiName()),
105
            'tables' => $this->tables,
106
            'hasOwner' => $this->hasOwner(),
107
            'mask' => $data->getEveApiArgument('mask'),
108
            'namespace' => $this->getNamespace(),
109
            'sectionName' => $this->sectionName,
110
            'tableNames' => array_keys($this->tables)
111
        ];
112
        $templateName = $this->getTemplateName('php',
113
            ucfirst($this->sectionName),
114
            $data->getEveApiName());
115
        if (false === $templateName) {
116
            $mess = 'Failed to find usable xsd template file during';
117
            $yem->triggerLogEvent('Yapeal.Log.log',
118
                Logger::WARNING,
119
                $this->createEventMessage($mess, $data, $eventName));
120
            return $event;
121
        }
122
        try {
123
            $contents = $this->getTwig()
124
                ->render($templateName, $vars);
125
        } catch (\Twig_Error $exp) {
126
            $yem->triggerLogEvent('Yapeal.Log.log', Logger::ERROR, 'Twig error', ['exception' => $exp]);
127
            $yem->triggerLogEvent('Yapeal.Log.log',
128
                Logger::WARNING,
129
                $this->getFailedToWriteFile($data, $eventName, $outputFile));
130
            return $event;
131
        }
132
        if (false === $this->safeFileWrite($contents, $outputFile, $this->getYem())) {
133
            $yem->triggerLogEvent($eventName,
134
                Logger::WARNING,
135
                $this->getFailedToWriteFile($data, $eventName, $outputFile));
136
            return $event;
137
        }
138
        return $event->setHandledSufficiently();
139
    }
140
    /**
141
     * @param \SimpleXMLIterator $sxi
142
     * @param string             $apiName
143
     * @param string             $xPath
144
     */
145
    protected function processRowset(\SimpleXMLIterator $sxi, $apiName, $xPath = '//result/rowset')
146
    {
147
        $items = $sxi->xpath($xPath);
148
        if (0 === count($items)) {
149
            return;
150
        }
151
        foreach ($items as $ele) {
152
            $rsName = ucfirst((string)$ele['name']);
153
            $colNames = explode(',', (string)$ele['columns']);
154
            $keyNames = explode(',', (string)$ele['key']);
155
            $attributes = [];
156
            foreach ($keyNames as $keyName) {
157
                $attributes[$keyName] = $this->inferDefaultFromName($keyName);
158
            }
159
            foreach ($colNames as $colName) {
160
                $attributes[$colName] = $this->inferDefaultFromName($colName);
161
            }
162
            if ($this->hasOwner()) {
163
                $attributes['ownerID'] = '$ownerID';
164
            }
165
            uksort($attributes,
166
                function ($alpha, $beta) {
167
                    return strtolower($alpha) <=> strtolower($beta);
168
                });
169
            if (0 === count($this->tables)) {
170
                $this->tables[$apiName] = ['attributes' => $attributes, 'xpath' => $rsName];
171
            } else {
172
                $this->tables[$rsName] = ['attributes' => $attributes, 'xpath' => $rsName];
173
            }
174
        }
175
    }
176
    /**
177
     * @param \SimpleXMLIterator $sxi
178
     * @param string             $tableName
179
     * @param string             $xpath
180
     */
181
    protected function processValueOnly(
182
        \SimpleXMLIterator $sxi,
183
        string $tableName,
184
        string $xpath = '//result/child::*[not(*|@*|self::dataTime)]'
185
    ) {
186
        $items = $sxi->xpath($xpath);
187
        if (0 === count($items)) {
188
            return;
189
        }
190
        $values = [];
191
        /**
192
         * @var \SimpleXMLElement $ele
193
         */
194
        foreach ($items as $ele) {
195
            $name = (string)$ele->getName();
196
            $values[$name] = $this->inferDefaultFromName($name);
197
        }
198
        if ($this->hasOwner()) {
199
            $values['ownerID'] = '$ownerID';
200
        }
201
        uksort($values,
202
            function ($alpha, $beta) {
203
                return strtolower($alpha) <=> strtolower($beta);
204
            });
205
        $this->tables[$tableName] = ['values' => $values];
206
    }
207
    /**
208
     * @return string
209
     */
210
    private function getNamespace(): string
211
    {
212
        return 'Yapeal\EveApi\\' . ucfirst($this->sectionName);
213
    }
214
    /**
215
     * Used to determine if API is in section that has an owner.
216
     *
217
     * @return bool
218
     */
219
    private function hasOwner(): bool
220
    {
221
        return in_array(strtolower($this->sectionName), ['account', 'char', 'corp'], true);
222
    }
223
    /**
224
     * Used to infer(choose) default value from element or attribute's name.
225
     *
226
     * @param string $name Name of the element or attribute.
227
     *
228
     * @return string Returns the inferred value from the name.
229
     */
230
    private function inferDefaultFromName(string $name): string
231
    {
232
        $name = strtolower($name);
233
        $column = 'null';
234
        foreach ([
235
                     'descr' => '\'\'',
236
                     'name' => '\'\'',
237
                     'balance' => '\'0.0\'',
238
                     'isk' => '\'0.0\'',
239
                     'tax' => '\'0.0\'',
240
                     'timeefficiency' => 'null',
241
                     'date' => '\'1970-01-01 00:00:01\'',
242
                     'time' => '\'1970-01-01 00:00:01\'',
243
                     'until' => '\'1970-01-01 00:00:01\''
244
                 ] as $search => $replace) {
245
            if (false !== strpos($name, $search)) {
246
                return $replace;
247
            }
248
        }
249
        return $column;
250
    }
251
    /**
252
     * @var string $sectionName
253
     */
254
    private $sectionName;
255
    /**
256
     * @var array $tables
257
     */
258
    private $tables;
259
}
260