DefinitionParser::getPropertyType()   A
last analyzed

Complexity

Conditions 5
Paths 7

Size

Total Lines 22
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 5
eloc 11
c 1
b 0
f 0
nc 7
nop 1
dl 0
loc 22
rs 9.6111
1
<?php
2
/**
3
 * This file is part of graze/unicontroller-client.
4
 *
5
 * Copyright (c) 2016 Nature Delivered Ltd. <https://www.graze.com>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 *
10
 * @license https://github.com/graze/unicontroller-client/blob/master/LICENSE.md
11
 * @link https://github.com/graze/unicontroller-client
12
 */
13
namespace Graze\UnicontrollerClient\ClassGenerator\Definition;
14
15
use League\CLImate\CLImate;
16
use Graze\UnicontrollerClient\ClassGenerator\Definition\Definition;
17
use Graze\UnicontrollerClient\ClassGenerator\Definition\DefinitionProperty;
18
19
class DefinitionParser
20
{
21
    const PATTERN_STRING = '/\[(STX|ETX)\]/';
22
23
    /**
24
     * @var CLImate
25
     */
26
    private $cli;
27
28
    /**
29
     * @param CLImate $cli
30
     */
31
    public function __construct(CLImate $cli)
32
    {
33
        $this->cli = $cli;
34
    }
35
36
    /**
37
     * @param string $definitionString
38
     * @return Definition
39
     */
40
    public function parse($definitionString)
41
    {
42
        $definitionString = $this->removeControlCharacters($definitionString);
43
        $name = $this->getName($definitionString);
44
        $definitionString = $this->removeName($definitionString, $name);
45
46
        $properties = [];
47
        foreach (explode(',', $definitionString) as $propertyName) {
48
            $propertyType = $this->getPropertyType($propertyName);
49
50
            if ($propertyType == DefinitionProperty::PROPERTY_TYPE_STRING) {
51
                $propertyName = $this->cleanString($propertyName);
52
            }
53
54
            $arrayElementName = null;
55
            if ($propertyType == DefinitionProperty::PROPERTY_TYPE_ARRAY) {
56
                $arrayElementName = $this->getArrayElementName($propertyName);
57
            }
58
59
            $properties[] = new DefinitionProperty(
60
                $propertyName,
61
                $propertyType,
62
                $arrayElementName
63
            );
64
        }
65
66
        return new Definition($name, $properties);
67
    }
68
69
    /**
70
     * @param string $definitionString
71
     * @return string
72
     */
73
    private function removeControlCharacters($definitionString)
74
    {
75
        $pattern = [
76
            '/\[(SOH|ETB|)\]| /',
77
            '/Heigth/' // common typo in documentation
78
        ];
79
        $replacements = [
80
            '',
81
            'Height'
82
        ];
83
84
        return preg_replace($pattern, $replacements, $definitionString);
85
    }
86
87
    /**
88
     * @param string $definitionString
89
     * @return string
90
     */
91
    private function getName($definitionString)
92
    {
93
        $pattern = '/^(?<name>[a-z]+)=/i';
94
        $matches = [];
95
        preg_match($pattern, $definitionString, $matches);
96
97
        // return name
98
        return $matches['name'];
99
    }
100
101
    /**
102
     * @param string $definitionString
103
     * @param string $name
104
     * @return string
105
     */
106
    private function removeName($definitionString, $name)
107
    {
108
        return substr($definitionString, strlen($name)+1);
109
    }
110
111
    /**
112
     * @param string $propertyName
113
     * @return string
114
     */
115
    private function getPropertyType($propertyName)
116
    {
117
        if (strpos($propertyName, 'Data') !== false) {
118
            $isBinaryData = $this->cli->confirm(sprintf(
119
                'is [%s] of type BinaryData?',
120
                $propertyName
121
            ));
122
123
            if ($isBinaryData->confirmed()) {
124
                return DefinitionProperty::PROPERTY_TYPE_BINARY_DATA;
125
            }
126
        }
127
128
        if (stripos($propertyName, 'array') !== false) {
129
            return DefinitionProperty::PROPERTY_TYPE_ARRAY;
130
        };
131
132
        if (preg_match(self::PATTERN_STRING, $propertyName)) {
133
            return DefinitionProperty::PROPERTY_TYPE_STRING;
134
        }
135
136
        return DefinitionProperty::PROPERTY_TYPE_INT;
137
    }
138
139
    /**
140
     * @param string $propertyName
141
     * @return string
142
     */
143
    private function cleanString($propertyName)
144
    {
145
        return preg_replace(self::PATTERN_STRING, '', $propertyName);
146
    }
147
148
    /**
149
     * @param string $propertyName
150
     * @return string
151
     */
152
    private function getArrayElementName($propertyName)
153
    {
154
        $elementName = str_ireplace('array', '', $propertyName);
155
156
        $elementNameItem = sprintf('%sItem', $elementName);
157
        $elementNameVar = sprintf('Var%s', $elementName);
158
159
        $input = $this->cli->input(sprintf(
160
            'enter array element name for [%s] array (1 for %s, 2 for %s, or custom)',
161
            $elementName,
162
            $elementNameItem,
163
            $elementNameVar
164
        ));
165
166
        $arrayElementName = $input->prompt() ?: 1;
167
        switch ($arrayElementName) {
168
            case 1:
169
                $arrayElementName = $elementNameItem;
170
                break;
171
172
            case 2:
173
                $arrayElementName = $elementNameVar;
174
                break;
175
        }
176
177
        $this->cli->out(sprintf('using [%s]', $arrayElementName));
178
179
        return $arrayElementName;
180
    }
181
}
182