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

Creator::createXsd()   B

Complexity

Conditions 7
Paths 6

Size

Total Lines 59
Code Lines 49

Duplication

Lines 0
Ratio 0 %

Importance

Changes 8
Bugs 0 Features 5
Metric Value
c 8
b 0
f 5
dl 0
loc 59
rs 7.5346
cc 7
eloc 49
nc 6
nop 3

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * Contains Creator class.
4
 *
5
 * PHP version 5.4
6
 *
7
 * LICENSE:
8
 * This file is part of Yet Another Php Eve Api Library also know as Yapeal which can be used to access the Eve Online
9
 * API data and place it into a database.
10
 * Copyright (C) 2015-2016 Michael Cummings
11
 *
12
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General
13
 * Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option)
14
 * any later version.
15
 *
16
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
17
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
18
 * details.
19
 *
20
 * You should have received a copy of the GNU Lesser General Public License along with this program. If not, see
21
 * <http://www.gnu.org/licenses/>.
22
 *
23
 * You should be able to find a copy of this license in the LICENSE.md file. A copy of the GNU GPL should also be
24
 * available in the GNU-GPL.md file.
25
 *
26
 * @copyright 2015-2016 Michael Cummings
27
 * @license   http://www.gnu.org/copyleft/lesser.html GNU LGPL
28
 * @author    Michael Cummings <[email protected]>
29
 */
30
namespace Yapeal\Xsd;
31
32
use Yapeal\Console\Command\EveApiCreatorTrait;
33
use Yapeal\Event\EveApiEventInterface;
34
use Yapeal\Event\MediatorInterface;
35
use Yapeal\Log\Logger;
36
37
/**
38
 * Class Creator
39
 */
40
class Creator
41
{
42
    use EveApiCreatorTrait;
43
    /**
44
     * Creator constructor.
45
     *
46
     * @param \Twig_Environment $twig
47
     * @param string            $dir
48
     */
49
    public function __construct(\Twig_Environment $twig, $dir = __DIR__)
50
    {
51
        $this->setDir($dir);
52
        $this->setTwig($twig);
53
    }
54
    /**
55
     * @param EveApiEventInterface $event
56
     * @param string               $eventName
57
     * @param MediatorInterface    $yem
58
     *
59
     * @return EveApiEventInterface
60
     * @throws \DomainException
61
     * @throws \InvalidArgumentException
62
     * @throws \LogicException
63
     */
64
    public function createXsd(EveApiEventInterface $event, $eventName, MediatorInterface $yem)
65
    {
66
        $this->setYem($yem);
67
        $data = $event->getData();
68
        $this->getYem()
69
            ->triggerLogEvent('Yapeal.Log.log',
70
                Logger::DEBUG,
71
                $this->getReceivedEventMessage($data, $eventName, __CLASS__));
72
        // Only work with raw unaltered XML data.
73
        if (false !== strpos($data->getEveApiXml(), '<?yapeal.parameters.json')) {
74
            return $event->setHandledSufficiently();
75
        }
76
        $outputFile = sprintf('%1$s%2$s/%3$s.xsd',
77
            $this->getDir(),
78
            $data->getEveApiSectionName(),
79
            $data->getEveApiName());
80
        // Nothing to do if NOT overwriting and file exists.
81
        if (false === $this->isOverwrite() && is_file($outputFile)) {
82
            return $event;
83
        }
84
        $this->sectionName = $data->getEveApiSectionName();
85
        $xml = $data->getEveApiXml();
86
        if (false === $xml) {
87
            return $event->setHandledSufficiently();
88
        }
89
        $sxi = new \SimpleXMLIterator($xml);
90
        $this->tables = [];
91
        $this->processValueOnly($sxi, lcfirst($data->getEveApiName()));
92
        $this->processRowset($sxi);
93
        list($mSec, $sec) = explode(' ', microtime());
94
        $vars = [
95
            'className' => lcfirst($data->getEveApiName()),
96
            'tables' => $this->tables,
97
            'sectionName' => lcfirst($this->sectionName),
98
            'version' => gmdate('YmdHis', $sec) . sprintf('.%0-3s', floor($mSec * 1000))
99
        ];
100
        try {
101
            $contents = $this->getTwig()
102
                ->render('xsd.twig', $vars);
103
        } catch (\Twig_Error $exc) {
104
            $this->getYem()
105
                ->triggerLogEvent('Yapeal.Log.log', Logger::ERROR, 'Twig error', ['exception' => $exc]);
106
            $this->getYem()
107
                ->triggerLogEvent('Yapeal.Log.log',
108
                    Logger::WARNING,
109
                    $this->getFailedToWriteFile($data, $eventName, $outputFile));
110
            return $event;
111
        }
112
        $contents = $this->getTidy()
113
            ->repairString($contents);
114
        if (false === $this->saveToFile($outputFile, $contents)) {
115
            $this->getYem()
116
                ->triggerLogEvent($eventName,
117
                    Logger::WARNING,
118
                    $this->getFailedToWriteFile($data, $eventName, $outputFile));
119
            return $event;
120
        }
121
        return $event->setHandledSufficiently();
122
    }
123
    /**
124
     * Used to infer(choose) type from element or attribute's name.
125
     *
126
     * @param string $name     Name of the element or attribute.
127
     * @param bool   $forValue Determines if returned type is going to be used for element or an attribute.
128
     *
129
     * @return string Returns the inferred type from the name.
130
     */
131
    protected function inferTypeFromName($name, $forValue = false)
132
    {
133
        if ('ID' === substr($name, -2)) {
134
            return 'eveIDType';
135
        }
136
        $name = strtolower($name);
137
        foreach ([
138
                     'descr' => 'xs:string',
139
                     'name' => 'eveNameType',
140
                     'balance' => 'eveISKType',
141
                     'isk' => 'eveISKType',
142
                     'tax' => 'eveISKType',
143
                     'timeefficiency' => 'xs:unsignedByte',
144
                     'date' => 'eveNEDTType',
145
                     'time' => 'eveNEDTType',
146
                     'until' => 'eveNEDTType',
147
                     'errorcode' => 'xs:unsignedShort',
148
                     'level' => 'xs:unsignedShort'
149
                 ] as $search => $replace) {
150
            if (false !== strpos($name, $search)) {
151
                return $replace;
152
            }
153
        }
154
        return $forValue ? 'xs:string' : 'xs:token';
155
    }
156
    /**
157
     * @param \SimpleXMLIterator $sxi
158
     * @param string             $xpath
159
     */
160
    protected function processRowset(\SimpleXMLIterator $sxi, $xpath = '//result/rowset')
161
    {
162
        $items = $sxi->xpath($xpath);
163
        if (0 === count($items)) {
164
            return;
165
        }
166
        $tables = [];
167
        foreach ($items as $ele) {
168
            $tableName = (string)$ele['name'];
169
            /**
170
             * @var string[] $colNames
171
             */
172
            $colNames = explode(',', (string)$ele['columns']);
173
            /**
174
             * @var string[] $keyNames
175
             */
176
            $keyNames = explode(',', (string)$ele['key']);
177
            $columns = [];
178
            foreach ($keyNames as $keyName) {
179
                $columns[$keyName] = $this->inferTypeFromName($keyName);
180
            }
181
            foreach ($colNames as $colName) {
182
                $columns[$colName] = $this->inferTypeFromName($colName);
183
            }
184
            uksort($columns,
185
                function ($alpha, $beta) {
186
                    $alpha = strtolower($alpha);
187
                    $beta = strtolower($beta);
188
                    if ($alpha < $beta) {
189
                        return -1;
190
                    } elseif ($alpha > $beta) {
191
                        return 1;
192
                    }
193
                    return 0;
194
                });
195
            $tables[$tableName] = ['attributes' => $columns];
196
        }
197
        uksort($tables,
198
            function ($alpha, $beta) {
199
                $alpha = strtolower($alpha);
200
                $beta = strtolower($beta);
201
                if ($alpha < $beta) {
202
                    return -1;
203
                } elseif ($alpha > $beta) {
204
                    return 1;
205
                }
206
                return 0;
207
            });
208
        $this->tables = array_merge($this->tables, $tables);
209
    }
210
    /**
211
     * @param \SimpleXMLIterator $sxi
212
     *
213
     * @param string             $tableName
214
     * @param string             $xpath
215
     */
216
    protected function processValueOnly(
217
        \SimpleXMLIterator $sxi,
218
        $tableName,
219
        $xpath = '//result/child::*[not(*|@*|self::dataTime)]'
220
    ) {
221
        $items = $sxi->xpath($xpath);
222
        if (0 === count($items)) {
223
            return;
224
        }
225
        $columns = [];
226
        /**
227
         * @var \SimpleXMLElement $ele
228
         */
229
        foreach ($items as $ele) {
230
            $name = (string)$ele->getName();
231
            $columns[$name] = $this->inferTypeFromName($name, true);
232
        }
233
        uksort($columns,
234
            function ($alpha, $beta) {
235
                $alpha = strtolower($alpha);
236
                $beta = strtolower($beta);
237
                if ($alpha < $beta) {
238
                    return -1;
239
                } elseif ($alpha > $beta) {
240
                    return 1;
241
                }
242
                return 0;
243
            });
244
        $this->tables[$tableName] = ['values' => $columns];
245
    }
246
    /**
247
     * @var string $sectionName
248
     */
249
    protected $sectionName;
250
    /**
251
     * @var array $tables
252
     */
253
    protected $tables;
254
    /**
255
     * @return \tidy
256
     */
257
    private function getTidy()
258
    {
259
        if (null === $this->tidy) {
260
            $tidyConfig = [
261
                'indent' => true,
262
                'indent-spaces' => 4,
263
                'input-xml' => true,
264
                'newline' => 'LF',
265
                'output-xml' => true,
266
                'wrap' => '120'
267
            ];
268
            $this->tidy = new \tidy(null, $tidyConfig, 'utf8');
269
        }
270
        return $this->tidy;
271
    }
272
    /**
273
     * @var \tidy $tidy
274
     */
275
    private $tidy;
276
}
277