Completed
Push — master ( fb2e0c...c99d2e )
by Michael
03:02
created

Creator::createXsd()   C

Complexity

Conditions 7
Paths 6

Size

Total Lines 74
Code Lines 59

Duplication

Lines 9
Ratio 12.16 %

Importance

Changes 5
Bugs 0 Features 4
Metric Value
c 5
b 0
f 4
dl 9
loc 74
rs 6.6374
cc 7
eloc 59
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 SimpleXMLElement;
33
use SimpleXMLIterator;
34
use tidy;
35
use Twig_Environment;
36
use Yapeal\Console\Command\EveApiCreatorTrait;
37
use Yapeal\Event\EveApiEventInterface;
38
use Yapeal\Event\MediatorInterface;
39
use Yapeal\Log\Logger;
40
41
/**
42
 * Class Creator
43
 */
44
class Creator
45
{
46
    use EveApiCreatorTrait;
47
    /**
48
     * Creator constructor.
49
     *
50
     * @param Twig_Environment $twig
51
     * @param string           $dir
52
     */
53
    public function __construct(Twig_Environment $twig, $dir = __DIR__)
54
    {
55
        $this->setDir($dir);
56
        $this->setTwig($twig);
57
    }
58
    /**
59
     * @param EveApiEventInterface $event
60
     * @param string               $eventName
61
     * @param MediatorInterface    $yem
62
     *
63
     * @return EveApiEventInterface
64
     * @throws \DomainException
65
     * @throws \InvalidArgumentException
66
     * @throws \LogicException
67
     */
68
    public function createXsd(EveApiEventInterface $event, $eventName, MediatorInterface $yem)
69
    {
70
        $this->setYem($yem);
71
        $data = $event->getData();
72
        $this->getYem()
73
            ->triggerLogEvent(
74
                'Yapeal.Log.log',
75
                Logger::DEBUG,
76
                $this->getReceivedEventMessage($data, $eventName, __CLASS__)
77
            );
78
        // Only work with raw unaltered XML data.
79
        if (false !== strpos($data->getEveApiXml(), '<?yapeal.parameters.json')) {
80
            return $event->setHandledSufficiently();
81
        }
82
        $outputFile = sprintf(
83
            '%1$s%2$s/%3$s.xsd',
84
            $this->getDir(),
85
            $data->getEveApiSectionName(),
86
            $data->getEveApiName()
87
        );
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
        $xml = $data->getEveApiXml();
94
         if (false === $xml) {
95
             return $event->setHandledSufficiently();
96
          }
97
        $sxi = new SimpleXMLIterator($xml);
98
        $this->tables = [];
99
        $this->processValueOnly($sxi, lcfirst($data->getEveApiName()));
100
        $this->processRowset($sxi);
101
        list($mSec, $sec) = explode(' ', microtime());
102
        $vars = [
103
            'className'   => lcfirst($data->getEveApiName()),
104
            'tables'      => $this->tables,
105
            'sectionName' => lcfirst($this->sectionName),
106
            'version' => gmdate('YmdHis', $sec) . sprintf('.%0-3s', floor($mSec * 1000))
107
        ];
108
        try {
109
            $contents = $this->getTwig()
110
                ->render('xsd.twig', $vars);
111
        } catch (\Twig_Error $exc) {
112
            $this->getYem()
113
                ->triggerLogEvent('Yapeal.Log.log', Logger::ERROR, 'Twig error', ['exception' => $exc]);
114
            $this->getYem()
115
                ->triggerLogEvent(
116
                    'Yapeal.Log.log',
117
                    Logger::WARNING,
118
                    $this->getFailedToWriteFile($data, $eventName, $outputFile)
119
                );
120
            return $event;
121
        }
122
        $tidyConfig = [
123
            'indent'        => true,
124
            'indent-spaces' => 4,
125
            'input-xml'     => true,
126
            'newline'       => 'LF',
127
            'output-xml'    => true,
128
            'wrap'          => '120'
129
        ];
130
        $contents = (new tidy())->repairString($contents, $tidyConfig, 'utf8');
131 View Code Duplication
        if (false === $this->saveToFile($outputFile, $contents)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
132
            $this->getYem()
133
                ->triggerLogEvent(
134
                    $eventName,
135
                    Logger::WARNING,
136
                    $this->getFailedToWriteFile($data, $eventName, $outputFile)
137
                );
138
            return $event;
139
        }
140
        return $event->setHandledSufficiently();
141
    }
142
    /**
143
     * Used to infer(choose) type from element or attribute's name.
144
     *
145
     * @param string $name     Name of the element or attribute.
146
     * @param bool   $forValue Determines if returned type is going to be used for element or an attribute.
147
     *
148
     * @return string Returns the inferred type from the name.
149
     */
150 View Code Duplication
    protected function inferTypeFromName($name, $forValue = false)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
151
    {
152
        if ('ID' === substr($name, -2)) {
153
            return 'eveIDType';
154
        }
155
        $name = strtolower($name);
156
        foreach ([
157
                     'descr'          => 'xs:string',
158
                     'name'           => 'eveNameType',
159
                     'balance'        => 'eveISKType',
160
                     'isk'            => 'eveISKType',
161
                     'tax'            => 'eveISKType',
162
                     'timeefficiency' => 'xs:unsignedByte',
163
                     'date'           => 'eveNEDTType',
164
                     'time'           => 'eveNEDTType',
165
                     'until'          => 'eveNEDTType',
166
                     'errorcode'      => 'xs:unsignedShort',
167
                     'level'          => 'xs:unsignedShort'
168
                 ] as $search => $replace) {
169
            if (false !== strpos($name, $search)) {
170
                return $replace;
171
            }
172
        }
173
        return $forValue ? 'xs:string' : 'xs:token';
174
    }
175
    /**
176
     * @param SimpleXMLIterator $sxi
177
     * @param string            $xpath
178
     */
179
    protected function processRowset(SimpleXMLIterator $sxi, $xpath = '//result/rowset')
180
    {
181
        $items = $sxi->xpath($xpath);
182
        if (0 === count($items)) {
183
            return;
184
        }
185
        $tables = [];
186
        foreach ($items as $ele) {
187
            $tableName = (string)$ele['name'];
188
            /**
189
             * @type string[] $colNames
190
             */
191
            $colNames = explode(',', (string)$ele['columns']);
192
            /**
193
             * @type string[] $keyNames
194
             */
195
            $keyNames = explode(',', (string)$ele['key']);
196
            $columns = [];
197
            foreach ($keyNames as $keyName) {
198
                $columns[$keyName] = $this->inferTypeFromName($keyName);
199
            }
200
            foreach ($colNames as $colName) {
201
                $columns[$colName] = $this->inferTypeFromName($colName);
202
            }
203
            ksort($columns);
204
            $tables[$tableName] = ['attributes' => $columns];
205
        }
206
        ksort($tables);
207
        $this->tables = array_merge($this->tables, $tables);
208
    }
209
    /**
210
     * @param SimpleXMLIterator $sxi
211
     *
212
     * @param string            $tableName
213
     * @param string            $xpath
214
     *
215
     * @return array
216
     */
217
    protected function processValueOnly(
218
        SimpleXMLIterator $sxi,
219
        $tableName,
220
        $xpath = '//result/child::*[not(*|@*|self::dataTime)]'
221
    ) {
222
        $items = $sxi->xpath($xpath);
223
        if (0 === count($items)) {
224
            return;
225
        }
226
        $columns = [];
227
        /**
228
         * @type SimpleXMLElement $ele
229
         */
230 View Code Duplication
        foreach ($items as $ele) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
231
            $name = (string)$ele->getName();
232
            $columns[$name] = $this->inferTypeFromName($name, true);
233
        }
234
        ksort($columns);
235
        $this->tables[$tableName] = ['values' => $columns];
236
    }
237
    /**
238
     * @type string $sectionName
239
     */
240
    protected $sectionName;
241
    /**
242
     * @type array $tables
243
     */
244
    protected $tables;
245
}
246