Completed
Push — master ( 879880...c8790f )
by Martijn
01:39 queued 11s
created

AbstractType::toArray()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 6
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
1
<?php
2
3
namespace SwaggerGen\Swagger\Type;
4
5
/**
6
 * Abstract foundation of all type definitions.
7
 *
8
 * @package    SwaggerGen
9
 * @author     Martijn van der Lee <[email protected]>
10
 * @copyright  2014-2015 Martijn van der Lee
11
 * @license    https://opensource.org/licenses/MIT MIT
12
 */
13
abstract class AbstractType extends \SwaggerGen\Swagger\AbstractObject
14
{
15
16
	const REGEX_START = '/^';
17
	const REGEX_FORMAT = '([a-z][a-z0-9]*)';
18
	const REGEX_CONTENT = '(?:\((.*)\))?';
19
	const REGEX_RANGE = '(?:([[<])(\\d*),(\\d*)([\\]>]))?';
20
	const REGEX_DEFAULT = '(?:=(.+))?';
21
	const REGEX_END = '$/i';
22
23
	private static $classTypes = array(
24
		'integer' => 'Integer',
25
		'int' => 'Integer',
26
		'int32' => 'Integer',
27
		'int64' => 'Integer',
28
		'long' => 'Integer',
29
		'float' => 'Number',
30
		'double' => 'Number',
31
		'string' => 'String',
32
		'uuid' => 'StringUuid',
33
		'byte' => 'String',
34
		'binary' => 'String',
35
		'password' => 'String',
36
		'enum' => 'String',
37
		'boolean' => 'Boolean',
38
		'bool' => 'Boolean',
39
		'array' => 'Array',
40
		'csv' => 'Array',
41
		'ssv' => 'Array',
42
		'tsv' => 'Array',
43
		'pipes' => 'Array',
44
		'date' => 'Date',
45
		'datetime' => 'Date',
46
		'date-time' => 'Date',
47
		'object' => 'Object',
48
		'refobject' => 'ReferenceObject',
49
		'allof' => 'AllOf',
50
	);
51
52
	private $example = null;
53
54
	/**
55
	 * Swap values of two variables.
56
	 * Used for sorting.
57
	 * @param mixed $a
58
	 * @param mixed $b
59
	 */
60
	protected static function swap(&$a, &$b)
61
	{
62
		$tmp = $a;
63
		$a = $b;
64
		$b = $tmp;
65
	}
66
67
	/**
68
	 * @param string $list
69
	 * @return array
70
	 */
71
	protected static function parseList($list)
72
	{
73
		$ret = array();
74
		while ($item = self::parseListItem($list)) {
75
			$ret[] = $item;
76
		}
77
		return $ret;
78
	}
79
	
80
	/**
81
	 * Extract an item from a comma-separated list of items.
82
	 *
83
	 * i.e. `a(x(x,x)),b(x)` returns `a(x(x,x))` and changes `$list` into `b(x)`.
84
	 * Note: brace nesting is not checked, e.g. `a{b(})` is a valid list item.
85
	 *
86
	 * @param string $list the list to parse
87
	 * @return string the extracted item
88
	 */
89
	protected static function parseListItem(&$list)
90
	{
91
		$item = '';
92
93
		$depth = 0;
94
		$index = 0;
95
		while ($index < strlen($list)) {
96
			$c = $list{$index++};
97
98
			if (strpos('{([<', $c) !== false) {
99
				++$depth;
100
			} elseif (strpos('})]>', $c) !== false) {
101
				--$depth;
102
			} elseif ($c === ',' && $depth === 0) {
103
				break;
104
			}
105
106
			$item .= $c;
107
		}
108
		$list = substr($list, $index);
109
110
		return $item;
111
	}
112
113
	/**
114
	 * @var string $definition
115
	 */
116
	public function __construct(\SwaggerGen\Swagger\AbstractObject $parent, $definition)
117
	{
118
		parent::__construct($parent);
119
120
		$this->parseDefinition($definition);
121
	}
122
123
	abstract protected function parseDefinition($definition);
124
125
	/**
126
	 * Overwrites default AbstractObject parser, since Types should not handle
127
	 * extensions themselves.
128
	 *
129
	 * @param string $command
130
	 * @param string $data
131
	 * @return \SwaggerGen\Swagger\Type\AbstractType|boolean
132
	 */
133
	public function handleCommand($command, $data = null)
134
	{
135
		switch (strtolower($command)) {
136
			case 'example':
137
				if ($data === '') {
138
					throw new \SwaggerGen\Exception("Missing content for type example");
139
				}
140
				$json = preg_replace_callback('/([^{}:,]+)/', function($match) {
141
					json_decode($match[1]);
142
					return json_last_error() === JSON_ERROR_NONE ? $match[1] : json_encode($match[1]);
143
				}, trim($data));
144
				$this->example = json_decode($json, true);
145
146
				// In case input contains special chars, the above preg_replace would fail
147
				//   Input could be a well-formed json already though
148
				if ($this->example === null) {
149
					$this->example = json_decode($data, true);
150
				}
151
				// If all fails, use input as-is
152
				if ($this->example === null) {
153
					$this->example = $data;
154
				}
155
156
				return $this;
157
		}
158
159
		return false;
160
	}
161
162
	public function toArray()
163
	{
164
		return self::arrayFilterNull(array_merge(array(
165
					'example' => $this->example,
166
								), parent::toArray()));
167
	}
168
169
	/**
170
	 * @param \SwaggerGen\Swagger\AbstractObject $parent
171
	 * @param string $definition
172
	 * @param string $error
173
	 * @return self
174
	 */
175
	public static function typeFactory($parent, $definition, $error = "Unparseable schema type definition: '%s'")
176
	{
177
		// Parse regex
178
		$match = array();
179
		if (preg_match('/^([a-z]+)/i', $definition, $match) === 1) {
180
			// recognized format
181
		} elseif (preg_match('/^(\[)(?:.*?)\]$/i', $definition, $match) === 1) {
182
			$match[1] = 'array';
183
		} elseif (preg_match('/^(\{)(?:.*?)\}$/i', $definition, $match) === 1) {
184
			$match[1] = 'object';
185
		} else {
186
			throw new \SwaggerGen\Exception(sprintf($error, $definition));
187
		}
188
		$format = strtolower($match[1]);
189
		// Internal type if type known and not overwritten by definition
190
		if ($parent->getTypeRegistry()->has($format)) {
191
			$class = $parent->getTypeRegistry()->get($format);
192
			return new $class($parent, $definition);
193
		} elseif (isset(self::$classTypes[$format])) {
194
			$type = self::$classTypes[$format];
195
			$class = "\\SwaggerGen\\Swagger\\Type\\{$type}Type";
196
			return new $class($parent, $definition);
197
		} else {
198
			return new ReferenceObjectType($parent, $definition);
199
		}
200
	}
201
202
}
203