Completed
Pull Request — master (#51)
by
unknown
20s
created
SwaggerGen/Swagger/Operation.php 1 patch
Indentation   +225 added lines, -225 removed lines patch added patch discarded remove patch
@@ -16,230 +16,230 @@
 block discarded – undo
16 16
 class Operation extends AbstractDocumentableObject
17 17
 {
18 18
 
19
-    private $tags = array();
20
-    private $summary;
21
-    private $description;
22
-    private $consumes = array();
23
-    private $produces = array();
24
-
25
-    /**
26
-     * @var IParameter[]
27
-     */
28
-    private $parameters = array();
29
-    private $responses = array();
30
-    private $schemes = array();
31
-    private $deprecated = false;
32
-    private $security = array();
33
-
34
-    /**
35
-     * @var string
36
-     */
37
-    private $operationId = null;
38
-
39
-    public function getConsumes(): array
40
-    {
41
-        return $this->consumes;
42
-    }
43
-
44
-    /**
45
-     * @param string $summary
46
-     */
47
-    public function __construct(AbstractObject $parent, $summary = null, ?Tag $tag = null)
48
-    {
49
-        parent::__construct($parent);
50
-        $this->summary = $summary;
51
-        if ($tag) {
52
-            $this->tags[] = $tag->getName();
53
-        }
54
-    }
55
-
56
-    /**
57
-     * @param string $command
58
-     * @param string $data
59
-     * @return AbstractObject|boolean
60
-     * @throws Exception
61
-     * @throws Exception
62
-     * @throws Exception
63
-     * @throws Exception
64
-     * @throws Exception
65
-     * @throws Exception
66
-     * @throws Exception
67
-     */
68
-    public function handleCommand($command, $data = null)
69
-    {
70
-        switch (strtolower($command)) {
71
-            // string
72
-            case 'summary':
73
-            case 'description':
74
-                $this->$command = $data;
75
-                return $this;
76
-
77
-            // string[]
78
-            case 'tags':
79
-            case 'schemes':
80
-                $this->$command = array_merge($this->$command, self::wordSplit($data));
81
-                return $this;
82
-
83
-            // MIME[]
84
-            case 'consumes':
85
-            case 'produces':
86
-                $this->$command = array_merge($this->$command, self::translateMimeTypes(self::wordSplit($data)));
87
-                return $this;
88
-
89
-            // boolean
90
-            case 'deprecated':
91
-                $this->deprecated = true;
92
-                return $this;
93
-
94
-            case 'error':
95
-                $code = self::wordShift($data);
96
-                $reasoncode = Response::getCode($code);
97
-                if ($reasoncode === null) {
98
-                    throw new Exception("Invalid error code: '$code'");
99
-                }
100
-                $description = $data;
101
-                $Error = new Error($this, $reasoncode, $description);
102
-                $this->responses[$reasoncode] = $Error;
103
-                return $Error;
104
-
105
-            case 'errors':
106
-                foreach (self::wordSplit($data) as $code) {
107
-                    $reasoncode = Response::getCode($code);
108
-                    if ($reasoncode === null) {
109
-                        throw new Exception("Invalid error code: '$code'");
110
-                    }
111
-                    $this->responses[$reasoncode] = new Error($this, $reasoncode);
112
-                }
113
-                return $this;
114
-
115
-            case 'path':
116
-            case 'query':
117
-            case 'query?':
118
-            case 'header':
119
-            case 'header?':
120
-            case 'form':
121
-            case 'form?':
122
-                $in = rtrim($command, '?');
123
-                $parameter = new Parameter($this, $in, $data, substr($command, -1) !== '?');
124
-                $this->parameters[$parameter->getName()] = $parameter;
125
-                return $parameter;
126
-
127
-            case 'body':
128
-            case 'body?':
129
-                $parameter = new BodyParameter($this, $data, substr($command, -1) !== '?');
130
-                $this->parameters[$parameter->getName()] = $parameter;
131
-                return $parameter;
132
-
133
-            case 'param':
134
-            case 'parameter':
135
-                $parameter = new ParameterReference($this, $data);
136
-                $this->parameters[$parameter->getName()] = $parameter;
137
-                return $this;
138
-
139
-            case 'response':
140
-                $code = self::wordShift($data);
141
-                $reasoncode = Response::getCode($code);
142
-                if ($reasoncode === null) {
143
-                    $reference = $code;
144
-                    $code = self::wordShift($data);
145
-                    $reasoncode = Response::getCode($code);
146
-                    if ($reasoncode === null) {
147
-                        throw new Exception("Invalid response code: '$reference'");
148
-                    }
149
-                    $this->responses[$reasoncode] = new ResponseReference($this, $reference);
150
-                    return $this;
151
-                } else {
152
-                    $definition = self::wordShift($data);
153
-                    $description = $data;
154
-                    $Response = new Response($this, $reasoncode, $definition, $description);
155
-                    $this->responses[$reasoncode] = $Response;
156
-                    return $Response;
157
-                }
158
-
159
-            case 'require':
160
-                $name = self::wordShift($data);
161
-                if (empty($name)) {
162
-                    throw new Exception('Empty security requirement name');
163
-                }
164
-                $scopes = self::wordSplit($data);
165
-                sort($scopes);
166
-                $this->security[] = array(
167
-                    $name => empty($scopes) ? array() : $scopes,
168
-                );
169
-                return $this;
170
-
171
-            case 'id':
172
-                $operationId = self::trim($data);
173
-                if ($this->getSwagger()->hasOperationId($operationId)) {
174
-                    throw new Exception("Duplicate operation id '{$operationId}'");
175
-                }
176
-                $this->operationId = $operationId;
177
-                return $this;
178
-        }
179
-
180
-        return parent::handleCommand($command, $data);
181
-    }
182
-
183
-    /**
184
-     * @throws Exception
185
-     */
186
-    public function toArray()
187
-    {
188
-        if (empty($this->responses)) {
189
-            throw new Exception('No response defined for operation');
190
-        }
191
-        ksort($this->responses);
192
-
193
-        $tags = array_unique($this->tags);
194
-        sort($tags);
195
-
196
-        $schemes = array_unique($this->schemes);
197
-        sort($schemes);
198
-
199
-        $consumes = array_unique($this->consumes);
200
-        sort($consumes);
201
-
202
-        $produces = array_unique($this->produces);
203
-        sort($produces);
204
-
205
-        foreach ($this->security as $security) {
206
-            foreach ($security as $name => $scope) {
207
-                if ($this->getSwagger()->getSecurity($name) === false) {
208
-                    throw new Exception("Required security scheme not defined: '{$name}'");
209
-                }
210
-            }
211
-        }
212
-
213
-        $parameters = $this->parameters ? array_values($this->parameters) : null;
214
-
215
-        return self::arrayFilterNull(array_merge(array(
216
-            'deprecated' => $this->deprecated ? true : null,
217
-            'tags' => $tags,
218
-            'summary' => empty($this->summary) ? null : $this->summary,
219
-            'description' => empty($this->description) ? null : $this->description,
220
-            'operationId' => $this->operationId,
221
-            'consumes' => $consumes,
222
-            'produces' => $produces,
223
-            'parameters' => $parameters ? self::objectsToArray($parameters) : null,
224
-            'schemes' => $schemes,
225
-            'responses' => $this->responses ? self::objectsToArray($this->responses) : null,
226
-            'security' => $this->security,
227
-        ), parent::toArray()));
228
-    }
229
-
230
-    /**
231
-     * Return the operation ID
232
-     *
233
-     * @return string
234
-     */
235
-    public function getId()
236
-    {
237
-        return $this->operationId;
238
-    }
239
-
240
-    public function __toString()
241
-    {
242
-        return __CLASS__ . ' ' . $this->summary;
243
-    }
19
+	private $tags = array();
20
+	private $summary;
21
+	private $description;
22
+	private $consumes = array();
23
+	private $produces = array();
24
+
25
+	/**
26
+	 * @var IParameter[]
27
+	 */
28
+	private $parameters = array();
29
+	private $responses = array();
30
+	private $schemes = array();
31
+	private $deprecated = false;
32
+	private $security = array();
33
+
34
+	/**
35
+	 * @var string
36
+	 */
37
+	private $operationId = null;
38
+
39
+	public function getConsumes(): array
40
+	{
41
+		return $this->consumes;
42
+	}
43
+
44
+	/**
45
+	 * @param string $summary
46
+	 */
47
+	public function __construct(AbstractObject $parent, $summary = null, ?Tag $tag = null)
48
+	{
49
+		parent::__construct($parent);
50
+		$this->summary = $summary;
51
+		if ($tag) {
52
+			$this->tags[] = $tag->getName();
53
+		}
54
+	}
55
+
56
+	/**
57
+	 * @param string $command
58
+	 * @param string $data
59
+	 * @return AbstractObject|boolean
60
+	 * @throws Exception
61
+	 * @throws Exception
62
+	 * @throws Exception
63
+	 * @throws Exception
64
+	 * @throws Exception
65
+	 * @throws Exception
66
+	 * @throws Exception
67
+	 */
68
+	public function handleCommand($command, $data = null)
69
+	{
70
+		switch (strtolower($command)) {
71
+			// string
72
+			case 'summary':
73
+			case 'description':
74
+				$this->$command = $data;
75
+				return $this;
76
+
77
+			// string[]
78
+			case 'tags':
79
+			case 'schemes':
80
+				$this->$command = array_merge($this->$command, self::wordSplit($data));
81
+				return $this;
82
+
83
+			// MIME[]
84
+			case 'consumes':
85
+			case 'produces':
86
+				$this->$command = array_merge($this->$command, self::translateMimeTypes(self::wordSplit($data)));
87
+				return $this;
88
+
89
+			// boolean
90
+			case 'deprecated':
91
+				$this->deprecated = true;
92
+				return $this;
93
+
94
+			case 'error':
95
+				$code = self::wordShift($data);
96
+				$reasoncode = Response::getCode($code);
97
+				if ($reasoncode === null) {
98
+					throw new Exception("Invalid error code: '$code'");
99
+				}
100
+				$description = $data;
101
+				$Error = new Error($this, $reasoncode, $description);
102
+				$this->responses[$reasoncode] = $Error;
103
+				return $Error;
104
+
105
+			case 'errors':
106
+				foreach (self::wordSplit($data) as $code) {
107
+					$reasoncode = Response::getCode($code);
108
+					if ($reasoncode === null) {
109
+						throw new Exception("Invalid error code: '$code'");
110
+					}
111
+					$this->responses[$reasoncode] = new Error($this, $reasoncode);
112
+				}
113
+				return $this;
114
+
115
+			case 'path':
116
+			case 'query':
117
+			case 'query?':
118
+			case 'header':
119
+			case 'header?':
120
+			case 'form':
121
+			case 'form?':
122
+				$in = rtrim($command, '?');
123
+				$parameter = new Parameter($this, $in, $data, substr($command, -1) !== '?');
124
+				$this->parameters[$parameter->getName()] = $parameter;
125
+				return $parameter;
126
+
127
+			case 'body':
128
+			case 'body?':
129
+				$parameter = new BodyParameter($this, $data, substr($command, -1) !== '?');
130
+				$this->parameters[$parameter->getName()] = $parameter;
131
+				return $parameter;
132
+
133
+			case 'param':
134
+			case 'parameter':
135
+				$parameter = new ParameterReference($this, $data);
136
+				$this->parameters[$parameter->getName()] = $parameter;
137
+				return $this;
138
+
139
+			case 'response':
140
+				$code = self::wordShift($data);
141
+				$reasoncode = Response::getCode($code);
142
+				if ($reasoncode === null) {
143
+					$reference = $code;
144
+					$code = self::wordShift($data);
145
+					$reasoncode = Response::getCode($code);
146
+					if ($reasoncode === null) {
147
+						throw new Exception("Invalid response code: '$reference'");
148
+					}
149
+					$this->responses[$reasoncode] = new ResponseReference($this, $reference);
150
+					return $this;
151
+				} else {
152
+					$definition = self::wordShift($data);
153
+					$description = $data;
154
+					$Response = new Response($this, $reasoncode, $definition, $description);
155
+					$this->responses[$reasoncode] = $Response;
156
+					return $Response;
157
+				}
158
+
159
+			case 'require':
160
+				$name = self::wordShift($data);
161
+				if (empty($name)) {
162
+					throw new Exception('Empty security requirement name');
163
+				}
164
+				$scopes = self::wordSplit($data);
165
+				sort($scopes);
166
+				$this->security[] = array(
167
+					$name => empty($scopes) ? array() : $scopes,
168
+				);
169
+				return $this;
170
+
171
+			case 'id':
172
+				$operationId = self::trim($data);
173
+				if ($this->getSwagger()->hasOperationId($operationId)) {
174
+					throw new Exception("Duplicate operation id '{$operationId}'");
175
+				}
176
+				$this->operationId = $operationId;
177
+				return $this;
178
+		}
179
+
180
+		return parent::handleCommand($command, $data);
181
+	}
182
+
183
+	/**
184
+	 * @throws Exception
185
+	 */
186
+	public function toArray()
187
+	{
188
+		if (empty($this->responses)) {
189
+			throw new Exception('No response defined for operation');
190
+		}
191
+		ksort($this->responses);
192
+
193
+		$tags = array_unique($this->tags);
194
+		sort($tags);
195
+
196
+		$schemes = array_unique($this->schemes);
197
+		sort($schemes);
198
+
199
+		$consumes = array_unique($this->consumes);
200
+		sort($consumes);
201
+
202
+		$produces = array_unique($this->produces);
203
+		sort($produces);
204
+
205
+		foreach ($this->security as $security) {
206
+			foreach ($security as $name => $scope) {
207
+				if ($this->getSwagger()->getSecurity($name) === false) {
208
+					throw new Exception("Required security scheme not defined: '{$name}'");
209
+				}
210
+			}
211
+		}
212
+
213
+		$parameters = $this->parameters ? array_values($this->parameters) : null;
214
+
215
+		return self::arrayFilterNull(array_merge(array(
216
+			'deprecated' => $this->deprecated ? true : null,
217
+			'tags' => $tags,
218
+			'summary' => empty($this->summary) ? null : $this->summary,
219
+			'description' => empty($this->description) ? null : $this->description,
220
+			'operationId' => $this->operationId,
221
+			'consumes' => $consumes,
222
+			'produces' => $produces,
223
+			'parameters' => $parameters ? self::objectsToArray($parameters) : null,
224
+			'schemes' => $schemes,
225
+			'responses' => $this->responses ? self::objectsToArray($this->responses) : null,
226
+			'security' => $this->security,
227
+		), parent::toArray()));
228
+	}
229
+
230
+	/**
231
+	 * Return the operation ID
232
+	 *
233
+	 * @return string
234
+	 */
235
+	public function getId()
236
+	{
237
+		return $this->operationId;
238
+	}
239
+
240
+	public function __toString()
241
+	{
242
+		return __CLASS__ . ' ' . $this->summary;
243
+	}
244 244
 
245 245
 }
Please login to merge, or discard this patch.
SwaggerGen/Swagger/Path.php 1 patch
Indentation   +97 added lines, -97 removed lines patch added patch discarded remove patch
@@ -16,102 +16,102 @@
 block discarded – undo
16 16
 class Path extends AbstractObject
17 17
 {
18 18
 
19
-    private static $methods = array(
20
-        'get',
21
-        'put',
22
-        'post',
23
-        'delete',
24
-        'options',
25
-        'head',
26
-        'patch',
27
-    );
28
-
29
-    /**
30
-     * @var Operation[] $operation
31
-     */
32
-    private $operations = array();
33
-
34
-    /**
35
-     * @var Tag|null $tag ;
36
-     */
37
-    private $tag;
38
-
39
-    public function __construct(AbstractObject $parent, ?Tag $Tag = null)
40
-    {
41
-        parent::__construct($parent);
42
-        $this->tag = $Tag;
43
-    }
44
-
45
-    /**
46
-     * @param string $command
47
-     * @param string $data
48
-     * @return AbstractObject|boolean
49
-     * @throws Exception
50
-     */
51
-    public function handleCommand($command, $data = null)
52
-    {
53
-        switch (strtolower($command)) {
54
-            case 'method': // alias
55
-            case 'operation':
56
-                $method = strtolower(self::wordShift($data));
57
-
58
-                if (!in_array($method, self::$methods)) {
59
-                    throw new Exception('Unrecognized operation method \'' . $method . '\'');
60
-                }
61
-
62
-                if (isset($this->operations[$method])) {
63
-                    $Operation = $this->operations[$method];
64
-                } else {
65
-                    $summary = $data;
66
-                    $Operation = new Operation($this, $summary, $this->tag);
67
-                    $this->operations[$method] = $Operation;
68
-                }
69
-
70
-                return $Operation;
71
-
72
-            case 'description':
73
-                if ($this->tag) {
74
-                    return $this->tag->handleCommand($command, $data);
75
-                }
76
-                break;
77
-        }
78
-
79
-        return parent::handleCommand($command, $data);
80
-    }
81
-
82
-    public function toArray()
83
-    {
84
-        $methods = self::$methods;
85
-        uksort($this->operations, function ($a, $b) use ($methods) {
86
-            return array_search($a, $methods) - array_search($b, $methods);
87
-        });
88
-
89
-        return self::arrayFilterNull(array_merge(
90
-            self::objectsToArray($this->operations)
91
-            , parent::toArray()));
92
-    }
93
-
94
-    public function __toString()
95
-    {
96
-        end($this->operations);
97
-        return __CLASS__ . ' ' . key($this->operations);
98
-    }
99
-
100
-    /**
101
-     * Check if an operation with the given id is registered to this Path.
102
-     *
103
-     * @param string $operationId
104
-     * @return boolean
105
-     */
106
-    public function hasOperationId($operationId)
107
-    {
108
-        foreach ($this->operations as $operation) {
109
-            if ($operation->getId() === $operationId) {
110
-                return true;
111
-            }
112
-        }
113
-
114
-        return false;
115
-    }
19
+	private static $methods = array(
20
+		'get',
21
+		'put',
22
+		'post',
23
+		'delete',
24
+		'options',
25
+		'head',
26
+		'patch',
27
+	);
28
+
29
+	/**
30
+	 * @var Operation[] $operation
31
+	 */
32
+	private $operations = array();
33
+
34
+	/**
35
+	 * @var Tag|null $tag ;
36
+	 */
37
+	private $tag;
38
+
39
+	public function __construct(AbstractObject $parent, ?Tag $Tag = null)
40
+	{
41
+		parent::__construct($parent);
42
+		$this->tag = $Tag;
43
+	}
44
+
45
+	/**
46
+	 * @param string $command
47
+	 * @param string $data
48
+	 * @return AbstractObject|boolean
49
+	 * @throws Exception
50
+	 */
51
+	public function handleCommand($command, $data = null)
52
+	{
53
+		switch (strtolower($command)) {
54
+			case 'method': // alias
55
+			case 'operation':
56
+				$method = strtolower(self::wordShift($data));
57
+
58
+				if (!in_array($method, self::$methods)) {
59
+					throw new Exception('Unrecognized operation method \'' . $method . '\'');
60
+				}
61
+
62
+				if (isset($this->operations[$method])) {
63
+					$Operation = $this->operations[$method];
64
+				} else {
65
+					$summary = $data;
66
+					$Operation = new Operation($this, $summary, $this->tag);
67
+					$this->operations[$method] = $Operation;
68
+				}
69
+
70
+				return $Operation;
71
+
72
+			case 'description':
73
+				if ($this->tag) {
74
+					return $this->tag->handleCommand($command, $data);
75
+				}
76
+				break;
77
+		}
78
+
79
+		return parent::handleCommand($command, $data);
80
+	}
81
+
82
+	public function toArray()
83
+	{
84
+		$methods = self::$methods;
85
+		uksort($this->operations, function ($a, $b) use ($methods) {
86
+			return array_search($a, $methods) - array_search($b, $methods);
87
+		});
88
+
89
+		return self::arrayFilterNull(array_merge(
90
+			self::objectsToArray($this->operations)
91
+			, parent::toArray()));
92
+	}
93
+
94
+	public function __toString()
95
+	{
96
+		end($this->operations);
97
+		return __CLASS__ . ' ' . key($this->operations);
98
+	}
99
+
100
+	/**
101
+	 * Check if an operation with the given id is registered to this Path.
102
+	 *
103
+	 * @param string $operationId
104
+	 * @return boolean
105
+	 */
106
+	public function hasOperationId($operationId)
107
+	{
108
+		foreach ($this->operations as $operation) {
109
+			if ($operation->getId() === $operationId) {
110
+				return true;
111
+			}
112
+		}
113
+
114
+		return false;
115
+	}
116 116
 
117 117
 }
Please login to merge, or discard this patch.
SwaggerGen/Swagger/AbstractObject.php 1 patch
Indentation   +157 added lines, -157 removed lines patch added patch discarded remove patch
@@ -16,162 +16,162 @@
 block discarded – undo
16 16
 abstract class AbstractObject
17 17
 {
18 18
 
19
-    private static $mime_types = array(
20
-        'fileform' => 'multipart/form-data',
21
-        'form' => 'application/x-www-form-urlencoded',
22
-        'json' => 'application/json',
23
-        'text' => 'text/plain',
24
-        'utf8' => 'text/plain; charset=utf-8',
25
-        'yml' => 'application/x-yaml',
26
-        'yaml' => 'application/x-yaml',
27
-        'php' => 'text/x-php',
28
-        'xml' => 'text/xml',
29
-    );
30
-
31
-    /**
32
-     * @var AbstractObject
33
-     */
34
-    private $parent;
35
-
36
-    /**
37
-     * Map of extensions and their (trimmed) values
38
-     * @var string[]
39
-     */
40
-    private $extensions = array();
41
-
42
-    public function __construct(?AbstractObject $parent = null)
43
-    {
44
-        $this->parent = $parent;
45
-    }
46
-
47
-    /**
48
-     * @return AbstractObject
49
-     */
50
-    protected function getParent()
51
-    {
52
-        return $this->parent;
53
-    }
54
-
55
-    protected function getParentClass($classname)
56
-    {
57
-        if (is_a($this, $classname)) {
58
-            return $this;
59
-        }
60
-        return $this->parent->getParentClass($classname);
61
-    }
62
-
63
-    /**
64
-     * @return Swagger
65
-     */
66
-    protected function getSwagger()
67
-    {
68
-        return $this->parent->getSwagger();
69
-    }
70
-
71
-    /**
72
-     * @return TypeRegistry
73
-     */
74
-    protected function getTypeRegistry()
75
-    {
76
-        return $this->parent->getTypeRegistry();
77
-    }
78
-
79
-    /**
80
-     * @param string $command
81
-     * @param string $data
82
-     * @return AbstractObject|boolean
83
-     */
84
-    public function handleCommand($command, $data = null)
85
-    {
86
-        if (strtolower(substr($command, 0, 2)) === 'x-') {
87
-            $this->extensions[$command] = empty($data) ? $data : trim($data);
88
-            return $this;
89
-        }
90
-
91
-        return false;
92
-    }
93
-
94
-    /**
95
-     * @return array
96
-     */
97
-    public function toArray()
98
-    {
99
-        return $this->extensions;
100
-    }
101
-
102
-    /**
103
-     * Translate consumes from shortcuts
104
-     * @param String[] $mimeTypes
105
-     * @return String[]
106
-     */
107
-    protected static function translateMimeTypes($mimeTypes)
108
-    {
109
-        foreach ($mimeTypes as &$mimeType) {
110
-            if (isset(self::$mime_types[strtolower($mimeType)])) {
111
-                $mimeType = self::$mime_types[strtolower($mimeType)];
112
-            }
113
-        }
114
-
115
-        return $mimeTypes;
116
-    }
117
-
118
-    /**
119
-     * Trim whitespace from a multibyte string
120
-     * @param string $string
121
-     * @return string
122
-     */
123
-    public static function trim($string)
124
-    {
125
-        return mb_ereg_replace('^\s*([\s\S]*?)\s*$', '\1', $string);
126
-    }
127
-
128
-    /**
129
-     * Filter all items from an array where the value is either null or an
130
-     * empty array.
131
-     * @param array $array
132
-     * @return array
133
-     */
134
-    public static function arrayFilterNull($array)
135
-    {
136
-        return array_filter($array, function ($value) {
137
-            return $value !== null && $value !== array();
138
-        });
139
-    }
140
-
141
-    /**
142
-     * Recursively call toArray() on all objects to return an array
143
-     * @param array $array
144
-     * @return array
145
-     */
146
-    public static function objectsToArray($array)
147
-    {
148
-        return array_map(function (AbstractObject $item) {
149
-            return $item->toArray();
150
-        }, $array);
151
-    }
152
-
153
-    /**
154
-     * Shifts the first word off a text line and returns it
155
-     * @param string $data
156
-     * @return string|bool Either the first word or false if no more words available
157
-     */
158
-    public static function wordShift(&$data)
159
-    {
160
-        if (preg_match('~^\s*(\S+)\s*(.*)$~s', $data, $matches) === 1) {
161
-            $data = $matches[2];
162
-            return $matches[1];
163
-        }
164
-        return false;
165
-    }
166
-
167
-    /**
168
-     * Splits a text line in all it's words
169
-     * @param string $data
170
-     * @return string[]
171
-     */
172
-    public static function wordSplit($data): array
173
-    {
174
-        return array_values(preg_grep('~\S~', preg_split('~\s+~', $data)));
175
-    }
19
+	private static $mime_types = array(
20
+		'fileform' => 'multipart/form-data',
21
+		'form' => 'application/x-www-form-urlencoded',
22
+		'json' => 'application/json',
23
+		'text' => 'text/plain',
24
+		'utf8' => 'text/plain; charset=utf-8',
25
+		'yml' => 'application/x-yaml',
26
+		'yaml' => 'application/x-yaml',
27
+		'php' => 'text/x-php',
28
+		'xml' => 'text/xml',
29
+	);
30
+
31
+	/**
32
+	 * @var AbstractObject
33
+	 */
34
+	private $parent;
35
+
36
+	/**
37
+	 * Map of extensions and their (trimmed) values
38
+	 * @var string[]
39
+	 */
40
+	private $extensions = array();
41
+
42
+	public function __construct(?AbstractObject $parent = null)
43
+	{
44
+		$this->parent = $parent;
45
+	}
46
+
47
+	/**
48
+	 * @return AbstractObject
49
+	 */
50
+	protected function getParent()
51
+	{
52
+		return $this->parent;
53
+	}
54
+
55
+	protected function getParentClass($classname)
56
+	{
57
+		if (is_a($this, $classname)) {
58
+			return $this;
59
+		}
60
+		return $this->parent->getParentClass($classname);
61
+	}
62
+
63
+	/**
64
+	 * @return Swagger
65
+	 */
66
+	protected function getSwagger()
67
+	{
68
+		return $this->parent->getSwagger();
69
+	}
70
+
71
+	/**
72
+	 * @return TypeRegistry
73
+	 */
74
+	protected function getTypeRegistry()
75
+	{
76
+		return $this->parent->getTypeRegistry();
77
+	}
78
+
79
+	/**
80
+	 * @param string $command
81
+	 * @param string $data
82
+	 * @return AbstractObject|boolean
83
+	 */
84
+	public function handleCommand($command, $data = null)
85
+	{
86
+		if (strtolower(substr($command, 0, 2)) === 'x-') {
87
+			$this->extensions[$command] = empty($data) ? $data : trim($data);
88
+			return $this;
89
+		}
90
+
91
+		return false;
92
+	}
93
+
94
+	/**
95
+	 * @return array
96
+	 */
97
+	public function toArray()
98
+	{
99
+		return $this->extensions;
100
+	}
101
+
102
+	/**
103
+	 * Translate consumes from shortcuts
104
+	 * @param String[] $mimeTypes
105
+	 * @return String[]
106
+	 */
107
+	protected static function translateMimeTypes($mimeTypes)
108
+	{
109
+		foreach ($mimeTypes as &$mimeType) {
110
+			if (isset(self::$mime_types[strtolower($mimeType)])) {
111
+				$mimeType = self::$mime_types[strtolower($mimeType)];
112
+			}
113
+		}
114
+
115
+		return $mimeTypes;
116
+	}
117
+
118
+	/**
119
+	 * Trim whitespace from a multibyte string
120
+	 * @param string $string
121
+	 * @return string
122
+	 */
123
+	public static function trim($string)
124
+	{
125
+		return mb_ereg_replace('^\s*([\s\S]*?)\s*$', '\1', $string);
126
+	}
127
+
128
+	/**
129
+	 * Filter all items from an array where the value is either null or an
130
+	 * empty array.
131
+	 * @param array $array
132
+	 * @return array
133
+	 */
134
+	public static function arrayFilterNull($array)
135
+	{
136
+		return array_filter($array, function ($value) {
137
+			return $value !== null && $value !== array();
138
+		});
139
+	}
140
+
141
+	/**
142
+	 * Recursively call toArray() on all objects to return an array
143
+	 * @param array $array
144
+	 * @return array
145
+	 */
146
+	public static function objectsToArray($array)
147
+	{
148
+		return array_map(function (AbstractObject $item) {
149
+			return $item->toArray();
150
+		}, $array);
151
+	}
152
+
153
+	/**
154
+	 * Shifts the first word off a text line and returns it
155
+	 * @param string $data
156
+	 * @return string|bool Either the first word or false if no more words available
157
+	 */
158
+	public static function wordShift(&$data)
159
+	{
160
+		if (preg_match('~^\s*(\S+)\s*(.*)$~s', $data, $matches) === 1) {
161
+			$data = $matches[2];
162
+			return $matches[1];
163
+		}
164
+		return false;
165
+	}
166
+
167
+	/**
168
+	 * Splits a text line in all it's words
169
+	 * @param string $data
170
+	 * @return string[]
171
+	 */
172
+	public static function wordSplit($data): array
173
+	{
174
+		return array_values(preg_grep('~\S~', preg_split('~\s+~', $data)));
175
+	}
176 176
 
177 177
 }
Please login to merge, or discard this patch.
SwaggerGen/Parser/Php/Parser.php 1 patch
Indentation   +366 added lines, -366 removed lines patch added patch discarded remove patch
@@ -20,376 +20,376 @@
 block discarded – undo
20 20
 class Parser extends Entity\AbstractEntity implements IParser
21 21
 {
22 22
 
23
-    const COMMENT_TAG = 'rest';
23
+	const COMMENT_TAG = 'rest';
24 24
 
25 25
 // transient
26 26
 
27
-    private $current_file = null;
28
-    private $files_queued = [];
29
-    private $files_done = [];
30
-    private $dirs = [];
27
+	private $current_file = null;
28
+	private $files_queued = [];
29
+	private $files_done = [];
30
+	private $dirs = [];
31 31
 // States
32 32
 
33
-    /** @var Statement[] */
34
-    public $statements = [];
35
-
36
-    /**
37
-     * @var Statement[]|null
38
-     */
39
-    private $lastStatements = [];
40
-
41
-    /**
42
-     * @var Entity\ParserClass[]
43
-     */
44
-    public $Classes = [];
45
-
46
-    /**
47
-     * @var Entity\ParserFunction[]
48
-     */
49
-    public $Functions = [];
50
-
51
-    /**
52
-     * @var AbstractPreprocessor
53
-     */
54
-    private $Preprocessor;
55
-
56
-    /**
57
-     * Directories available to all parse calls
58
-     *
59
-     * @var string[]
60
-     */
61
-    protected $common_dirs = [];
62
-
63
-    public function __construct(array $dirs = [])
64
-    {
65
-        foreach ($dirs as $dir) {
66
-            $this->common_dirs[] = realpath($dir);
67
-        }
68
-
69
-        $this->Preprocessor = new Preprocessor(self::COMMENT_TAG);
70
-    }
71
-
72
-    public function addDirs(array $dirs)
73
-    {
74
-        foreach ($dirs as $dir) {
75
-            $this->common_dirs[] = realpath($dir);
76
-        }
77
-    }
78
-
79
-    private function extractStatements()
80
-    {
81
-        // Core comments
82
-        $Statements = $this->statements;
83
-
84
-        // Functions
85
-        foreach ($this->Functions as $Function) {
86
-            if ($Function->hasCommand('method')) {
87
-                $Statements = array_merge($Statements, $Function->Statements);
88
-            }
89
-        }
90
-
91
-        // Classes
92
-        foreach ($this->Classes as $Class) {
93
-            $Statements = array_merge($Statements, $Class->Statements);
94
-            foreach ($Class->Methods as $Method) {
95
-                if ($Method->hasCommand('method')) {
96
-                    $Statements = array_merge($Statements, $Method->Statements);
97
-                }
98
-            }
99
-        }
100
-
101
-        return $Statements;
102
-    }
103
-
104
-    /**
105
-     * @throws Exception
106
-     */
107
-    public function parse($file, array $dirs = [], array $defines = [])
108
-    {
109
-        $this->dirs = $this->common_dirs;
110
-        foreach ($dirs as $dir) {
111
-            $this->dirs[] = realpath($dir);
112
-        }
113
-
114
-        $this->parseFiles(array($file), $defines);
115
-
116
-        // Inherit classes
117
-        foreach ($this->Classes as $Class) {
118
-            $this->inherit($Class);
119
-        }
120
-
121
-        // Expand functions with used and seen functions/methods.
122
-        foreach ($this->Classes as $Class) {
123
-            foreach ($Class->Methods as $Method) {
124
-                $Method->Statements = $this->expand($Method->Statements, $Class);
125
-            }
126
-        }
127
-
128
-        return $this->extractStatements();
129
-    }
130
-
131
-    /**
132
-     * Convert a T_*_COMMENT string to an array of Statements
133
-     * @param array $token
134
-     * @return Statement[]
135
-     */
136
-    public function tokenToStatements($token)
137
-    {
138
-        $comment = $token[1];
139
-        $commentLineNumber = $token[2];
140
-        $commentLines = [];
141
-
142
-        $match = [];
143
-        if (preg_match('~^/\*\*?\s*(.*)\s*\*\/$~sm', $comment, $match) === 1) {
144
-            $lines = preg_split('~\n~', $match[0]);
145
-            foreach ($lines as $line) {
146
-                if (preg_match('~^\s*\*?\s*(.*?)\s*$~', $line, $match) === 1) {
147
-                    if (!empty($match[1])) {
148
-                        $commentLines[] = trim($match[1]);
149
-                    }
150
-                }
151
-            }
152
-        } elseif (preg_match('~^//\s*(.*)$~', $comment, $match) === 1) {
153
-            $commentLines[] = trim($match[1]);
154
-        }
155
-        // to commands
156
-        $match = [];
157
-        $command = null;
158
-        $data = '';
159
-        $commandLineNumber = 0;
160
-        $statements = [];
161
-        foreach ($commentLines as $lineNumber => $line) {
162
-            // If new @-command, store any old and start new
163
-            if ($command !== null && chr(ord($line)) === '@') {
164
-                $statements[] = new Statement($command, $data, $this->current_file, $commentLineNumber + $commandLineNumber);
165
-                $command = null;
166
-                $data = '';
167
-            }
168
-
169
-            if (preg_match('~^@' . preg_quote(self::COMMENT_TAG) . '\\\\([a-z][-a-z]*[?!]?)\\s*(.*)$~', $line, $match) === 1) {
170
-                $command = $match[1];
171
-                $data = $match[2];
172
-                $commandLineNumber = $lineNumber;
173
-            } elseif ($command !== null) {
174
-                if ($lineNumber < count($commentLines) - 1) {
175
-                    $data .= ' ' . $line;
176
-                } else {
177
-                    $data .= preg_replace('~\s*\**\/\s*$~', '', $line);
178
-                }
179
-            }
180
-        }
181
-
182
-        if ($command !== null) {
183
-            $statements[] = new Statement($command, $data, $this->current_file, $commentLineNumber + $commandLineNumber);
184
-        }
185
-
186
-        return $statements;
187
-    }
188
-
189
-    public function queueClass($classname)
190
-    {
191
-        foreach ($this->dirs as $dir) {
192
-            $paths = array(
193
-                $dir . DIRECTORY_SEPARATOR . $classname . '.php',
194
-                $dir . DIRECTORY_SEPARATOR . $classname . '.class.php',
195
-            );
196
-
197
-            foreach ($paths as $path) {
198
-                $realpath = realpath($path);
199
-                if (in_array($realpath, $this->files_done)) {
200
-                    return;
201
-                } elseif (is_file($realpath)) {
202
-                    $this->files_queued[] = $realpath;
203
-                    return;
204
-                }
205
-            }
206
-        }
207
-
208
-        // assume it's a class;
209
-    }
210
-
211
-    /**
212
-     * Add to the queue any classes based on the commands.
213
-     * @param Statement[] $Statements
214
-     */
215
-    public function queueClassesFromComments(array $Statements)
216
-    {
217
-        foreach ($Statements as $Statement) {
218
-            if (in_array($Statement->getCommand(), array('uses', 'see'))) {
219
-                $match = [];
220
-                if (preg_match('~^(\w+)(::|->)?(\w+)?(?:\(\))?$~', $Statement->getData(), $match) === 1) {
221
-                    if (!in_array($match[1], array('self', '$this'))) {
222
-                        $this->queueClass($match[1]);
223
-                    }
224
-                }
225
-            }
226
-        }
227
-    }
228
-
229
-    private function parseTokens($source)
230
-    {
231
-        $mode = null;
232
-        $namespace = '';
233
-
234
-        $tokens = token_get_all($source);
235
-        $token = reset($tokens);
236
-        while ($token) {
237
-            switch ($token[0]) {
238
-                case T_NAMESPACE:
239
-                    $mode = T_NAMESPACE;
240
-                    break;
241
-
242
-                case T_NS_SEPARATOR:
243
-                case T_STRING:
244
-                    if ($mode === T_NAMESPACE) {
245
-                        $namespace .= $token[1];
246
-                    }
247
-                    break;
248
-
249
-                case ';':
250
-                    $mode = null;
251
-                    break;
252
-
253
-                case T_CLASS:
254
-                case T_INTERFACE:
255
-                    $Class = new Entity\ParserClass($this, $tokens, $this->lastStatements);
256
-                    $this->Classes[strtolower($Class->name)] = $Class;
257
-                    $this->lastStatements = null;
258
-                    break;
259
-
260
-                case T_FUNCTION:
261
-                    $Function = new Entity\ParserFunction($this, $tokens, $this->lastStatements);
262
-                    $this->Functions[strtolower($Function->name)] = $Function;
263
-                    $this->lastStatements = null;
264
-                    break;
265
-
266
-                case T_COMMENT:
267
-                    if ($this->lastStatements !== null) {
268
-                        $this->statements = array_merge($this->statements, $this->lastStatements);
269
-                        $this->lastStatements = null;
270
-                    }
271
-                    $Statements = $this->tokenToStatements($token);
272
-                    $this->queueClassesFromComments($Statements);
273
-                    $this->statements = array_merge($this->statements, $Statements);
274
-                    break;
275
-
276
-                case T_DOC_COMMENT:
277
-                    if ($this->lastStatements !== null) {
278
-                        $this->statements = array_merge($this->statements, $this->lastStatements);
279
-                    }
280
-                    $Statements = $this->tokenToStatements($token);
281
-                    $this->queueClassesFromComments($Statements);
282
-                    $this->lastStatements = $Statements;
283
-                    break;
284
-            }
285
-
286
-            $token = next($tokens);
287
-        }
288
-    }
289
-
290
-    private function parseFiles(array $files, array $defines = [])
291
-    {
292
-        $this->files_queued = $files;
293
-
294
-        $index = 0;
295
-        while (($file = array_shift($this->files_queued)) !== null) {
296
-            $file = realpath($file);
297
-
298
-            // @todo Test if this works
299
-            if (in_array($file, $this->files_done)) {
300
-                continue;
301
-            }
302
-
303
-            $this->current_file = $file;
304
-            $this->files_done[] = $file;
305
-            ++$index;
306
-
307
-            $this->Preprocessor->resetDefines();
308
-            $this->Preprocessor->addDefines($defines);
309
-            $source = $this->Preprocessor->preprocessFile($file);
310
-
311
-            $this->parseTokens($source);
312
-
313
-            if ($this->lastStatements !== null) {
314
-                $this->statements = array_merge($this->statements, $this->lastStatements);
315
-                $this->lastStatements = null;
316
-            }
317
-        }
318
-
319
-        $this->current_file = null;
320
-    }
321
-
322
-    /**
323
-     * Inherit the statements
324
-     * @param ParserClass $Class
325
-     */
326
-    private function inherit(Entity\ParserClass $Class)
327
-    {
328
-        $inherits = array_merge(array($Class->extends), $Class->implements);
329
-        while (($inherit = array_shift($inherits)) !== null) {
330
-            if (isset($this->Classes[strtolower($inherit)])) {
331
-                $inheritedClass = $this->Classes[strtolower($inherit)];
332
-                $this->inherit($inheritedClass);
333
-
334
-                foreach ($inheritedClass->Methods as $name => $Method) {
335
-                    if (!isset($Class->Methods[$name])) {
336
-                        $Class->Methods[$name] = $Method;
337
-                    }
338
-                }
339
-            }
340
-        }
341
-    }
342
-
343
-    /**
344
-     * Expands a set of comments with comments of methods referred to by rest\uses statements.
345
-     *
346
-     * @param Statement[] $Statements
347
-     * @return Statement[]
348
-     * @throws Exception
349
-     * @throws Exception
350
-     * @throws Exception
351
-     */
352
-    private function expand(array $Statements, ?ParserClass $Self = null)
353
-    {
354
-        $output = [];
355
-
356
-        $match = [];
357
-        foreach ($Statements as $Statement) {
358
-            if (in_array($Statement->getCommand(), array('uses', 'see'))) {
359
-                if (preg_match('/^((?:\\w+)|\$this)(?:(::|->)(\\w+))?(?:\\(\\))?$/', strtolower($Statement->getData()), $match) === 1) {
360
-                    if (count($match) >= 3) {
361
-                        $Class = null;
362
-                        if (in_array($match[1], array('$this', 'self', 'static'))) {
363
-                            $Class = $Self;
364
-                        } elseif (isset($this->Classes[$match[1]])) {
365
-                            $Class = $this->Classes[$match[1]];
366
-                        }
367
-
368
-                        if ($Class) {
369
-                            if (isset($Class->Methods[$match[3]])) {
370
-                                $Method = $Class->Methods[$match[3]];
371
-                                $Method->Statements = $this->expand($Method->Statements, $Class);
372
-                                $output = array_merge($output, $Method->Statements);
373
-                            } else {
374
-                                throw new Exception("Method '{$match[3]}' for class '{$match[1]}' not found");
375
-                            }
376
-                        } else {
377
-                            throw new Exception("Class '{$match[1]}' not found");
378
-                        }
379
-                    } elseif (isset($this->Functions[$match[1]])) {
380
-                        $Function = $this->Functions[$match[1]];
381
-                        $Function->Statements = $this->expand($Function->Statements);
382
-                        $output = array_merge($output, $Function->Statements);
383
-                    } else {
384
-                        throw new Exception("Function '{$match[1]}' not found");
385
-                    }
386
-                }
387
-            } else {
388
-                $output[] = $Statement;
389
-            }
390
-        }
391
-
392
-        return $output;
393
-    }
33
+	/** @var Statement[] */
34
+	public $statements = [];
35
+
36
+	/**
37
+	 * @var Statement[]|null
38
+	 */
39
+	private $lastStatements = [];
40
+
41
+	/**
42
+	 * @var Entity\ParserClass[]
43
+	 */
44
+	public $Classes = [];
45
+
46
+	/**
47
+	 * @var Entity\ParserFunction[]
48
+	 */
49
+	public $Functions = [];
50
+
51
+	/**
52
+	 * @var AbstractPreprocessor
53
+	 */
54
+	private $Preprocessor;
55
+
56
+	/**
57
+	 * Directories available to all parse calls
58
+	 *
59
+	 * @var string[]
60
+	 */
61
+	protected $common_dirs = [];
62
+
63
+	public function __construct(array $dirs = [])
64
+	{
65
+		foreach ($dirs as $dir) {
66
+			$this->common_dirs[] = realpath($dir);
67
+		}
68
+
69
+		$this->Preprocessor = new Preprocessor(self::COMMENT_TAG);
70
+	}
71
+
72
+	public function addDirs(array $dirs)
73
+	{
74
+		foreach ($dirs as $dir) {
75
+			$this->common_dirs[] = realpath($dir);
76
+		}
77
+	}
78
+
79
+	private function extractStatements()
80
+	{
81
+		// Core comments
82
+		$Statements = $this->statements;
83
+
84
+		// Functions
85
+		foreach ($this->Functions as $Function) {
86
+			if ($Function->hasCommand('method')) {
87
+				$Statements = array_merge($Statements, $Function->Statements);
88
+			}
89
+		}
90
+
91
+		// Classes
92
+		foreach ($this->Classes as $Class) {
93
+			$Statements = array_merge($Statements, $Class->Statements);
94
+			foreach ($Class->Methods as $Method) {
95
+				if ($Method->hasCommand('method')) {
96
+					$Statements = array_merge($Statements, $Method->Statements);
97
+				}
98
+			}
99
+		}
100
+
101
+		return $Statements;
102
+	}
103
+
104
+	/**
105
+	 * @throws Exception
106
+	 */
107
+	public function parse($file, array $dirs = [], array $defines = [])
108
+	{
109
+		$this->dirs = $this->common_dirs;
110
+		foreach ($dirs as $dir) {
111
+			$this->dirs[] = realpath($dir);
112
+		}
113
+
114
+		$this->parseFiles(array($file), $defines);
115
+
116
+		// Inherit classes
117
+		foreach ($this->Classes as $Class) {
118
+			$this->inherit($Class);
119
+		}
120
+
121
+		// Expand functions with used and seen functions/methods.
122
+		foreach ($this->Classes as $Class) {
123
+			foreach ($Class->Methods as $Method) {
124
+				$Method->Statements = $this->expand($Method->Statements, $Class);
125
+			}
126
+		}
127
+
128
+		return $this->extractStatements();
129
+	}
130
+
131
+	/**
132
+	 * Convert a T_*_COMMENT string to an array of Statements
133
+	 * @param array $token
134
+	 * @return Statement[]
135
+	 */
136
+	public function tokenToStatements($token)
137
+	{
138
+		$comment = $token[1];
139
+		$commentLineNumber = $token[2];
140
+		$commentLines = [];
141
+
142
+		$match = [];
143
+		if (preg_match('~^/\*\*?\s*(.*)\s*\*\/$~sm', $comment, $match) === 1) {
144
+			$lines = preg_split('~\n~', $match[0]);
145
+			foreach ($lines as $line) {
146
+				if (preg_match('~^\s*\*?\s*(.*?)\s*$~', $line, $match) === 1) {
147
+					if (!empty($match[1])) {
148
+						$commentLines[] = trim($match[1]);
149
+					}
150
+				}
151
+			}
152
+		} elseif (preg_match('~^//\s*(.*)$~', $comment, $match) === 1) {
153
+			$commentLines[] = trim($match[1]);
154
+		}
155
+		// to commands
156
+		$match = [];
157
+		$command = null;
158
+		$data = '';
159
+		$commandLineNumber = 0;
160
+		$statements = [];
161
+		foreach ($commentLines as $lineNumber => $line) {
162
+			// If new @-command, store any old and start new
163
+			if ($command !== null && chr(ord($line)) === '@') {
164
+				$statements[] = new Statement($command, $data, $this->current_file, $commentLineNumber + $commandLineNumber);
165
+				$command = null;
166
+				$data = '';
167
+			}
168
+
169
+			if (preg_match('~^@' . preg_quote(self::COMMENT_TAG) . '\\\\([a-z][-a-z]*[?!]?)\\s*(.*)$~', $line, $match) === 1) {
170
+				$command = $match[1];
171
+				$data = $match[2];
172
+				$commandLineNumber = $lineNumber;
173
+			} elseif ($command !== null) {
174
+				if ($lineNumber < count($commentLines) - 1) {
175
+					$data .= ' ' . $line;
176
+				} else {
177
+					$data .= preg_replace('~\s*\**\/\s*$~', '', $line);
178
+				}
179
+			}
180
+		}
181
+
182
+		if ($command !== null) {
183
+			$statements[] = new Statement($command, $data, $this->current_file, $commentLineNumber + $commandLineNumber);
184
+		}
185
+
186
+		return $statements;
187
+	}
188
+
189
+	public function queueClass($classname)
190
+	{
191
+		foreach ($this->dirs as $dir) {
192
+			$paths = array(
193
+				$dir . DIRECTORY_SEPARATOR . $classname . '.php',
194
+				$dir . DIRECTORY_SEPARATOR . $classname . '.class.php',
195
+			);
196
+
197
+			foreach ($paths as $path) {
198
+				$realpath = realpath($path);
199
+				if (in_array($realpath, $this->files_done)) {
200
+					return;
201
+				} elseif (is_file($realpath)) {
202
+					$this->files_queued[] = $realpath;
203
+					return;
204
+				}
205
+			}
206
+		}
207
+
208
+		// assume it's a class;
209
+	}
210
+
211
+	/**
212
+	 * Add to the queue any classes based on the commands.
213
+	 * @param Statement[] $Statements
214
+	 */
215
+	public function queueClassesFromComments(array $Statements)
216
+	{
217
+		foreach ($Statements as $Statement) {
218
+			if (in_array($Statement->getCommand(), array('uses', 'see'))) {
219
+				$match = [];
220
+				if (preg_match('~^(\w+)(::|->)?(\w+)?(?:\(\))?$~', $Statement->getData(), $match) === 1) {
221
+					if (!in_array($match[1], array('self', '$this'))) {
222
+						$this->queueClass($match[1]);
223
+					}
224
+				}
225
+			}
226
+		}
227
+	}
228
+
229
+	private function parseTokens($source)
230
+	{
231
+		$mode = null;
232
+		$namespace = '';
233
+
234
+		$tokens = token_get_all($source);
235
+		$token = reset($tokens);
236
+		while ($token) {
237
+			switch ($token[0]) {
238
+				case T_NAMESPACE:
239
+					$mode = T_NAMESPACE;
240
+					break;
241
+
242
+				case T_NS_SEPARATOR:
243
+				case T_STRING:
244
+					if ($mode === T_NAMESPACE) {
245
+						$namespace .= $token[1];
246
+					}
247
+					break;
248
+
249
+				case ';':
250
+					$mode = null;
251
+					break;
252
+
253
+				case T_CLASS:
254
+				case T_INTERFACE:
255
+					$Class = new Entity\ParserClass($this, $tokens, $this->lastStatements);
256
+					$this->Classes[strtolower($Class->name)] = $Class;
257
+					$this->lastStatements = null;
258
+					break;
259
+
260
+				case T_FUNCTION:
261
+					$Function = new Entity\ParserFunction($this, $tokens, $this->lastStatements);
262
+					$this->Functions[strtolower($Function->name)] = $Function;
263
+					$this->lastStatements = null;
264
+					break;
265
+
266
+				case T_COMMENT:
267
+					if ($this->lastStatements !== null) {
268
+						$this->statements = array_merge($this->statements, $this->lastStatements);
269
+						$this->lastStatements = null;
270
+					}
271
+					$Statements = $this->tokenToStatements($token);
272
+					$this->queueClassesFromComments($Statements);
273
+					$this->statements = array_merge($this->statements, $Statements);
274
+					break;
275
+
276
+				case T_DOC_COMMENT:
277
+					if ($this->lastStatements !== null) {
278
+						$this->statements = array_merge($this->statements, $this->lastStatements);
279
+					}
280
+					$Statements = $this->tokenToStatements($token);
281
+					$this->queueClassesFromComments($Statements);
282
+					$this->lastStatements = $Statements;
283
+					break;
284
+			}
285
+
286
+			$token = next($tokens);
287
+		}
288
+	}
289
+
290
+	private function parseFiles(array $files, array $defines = [])
291
+	{
292
+		$this->files_queued = $files;
293
+
294
+		$index = 0;
295
+		while (($file = array_shift($this->files_queued)) !== null) {
296
+			$file = realpath($file);
297
+
298
+			// @todo Test if this works
299
+			if (in_array($file, $this->files_done)) {
300
+				continue;
301
+			}
302
+
303
+			$this->current_file = $file;
304
+			$this->files_done[] = $file;
305
+			++$index;
306
+
307
+			$this->Preprocessor->resetDefines();
308
+			$this->Preprocessor->addDefines($defines);
309
+			$source = $this->Preprocessor->preprocessFile($file);
310
+
311
+			$this->parseTokens($source);
312
+
313
+			if ($this->lastStatements !== null) {
314
+				$this->statements = array_merge($this->statements, $this->lastStatements);
315
+				$this->lastStatements = null;
316
+			}
317
+		}
318
+
319
+		$this->current_file = null;
320
+	}
321
+
322
+	/**
323
+	 * Inherit the statements
324
+	 * @param ParserClass $Class
325
+	 */
326
+	private function inherit(Entity\ParserClass $Class)
327
+	{
328
+		$inherits = array_merge(array($Class->extends), $Class->implements);
329
+		while (($inherit = array_shift($inherits)) !== null) {
330
+			if (isset($this->Classes[strtolower($inherit)])) {
331
+				$inheritedClass = $this->Classes[strtolower($inherit)];
332
+				$this->inherit($inheritedClass);
333
+
334
+				foreach ($inheritedClass->Methods as $name => $Method) {
335
+					if (!isset($Class->Methods[$name])) {
336
+						$Class->Methods[$name] = $Method;
337
+					}
338
+				}
339
+			}
340
+		}
341
+	}
342
+
343
+	/**
344
+	 * Expands a set of comments with comments of methods referred to by rest\uses statements.
345
+	 *
346
+	 * @param Statement[] $Statements
347
+	 * @return Statement[]
348
+	 * @throws Exception
349
+	 * @throws Exception
350
+	 * @throws Exception
351
+	 */
352
+	private function expand(array $Statements, ?ParserClass $Self = null)
353
+	{
354
+		$output = [];
355
+
356
+		$match = [];
357
+		foreach ($Statements as $Statement) {
358
+			if (in_array($Statement->getCommand(), array('uses', 'see'))) {
359
+				if (preg_match('/^((?:\\w+)|\$this)(?:(::|->)(\\w+))?(?:\\(\\))?$/', strtolower($Statement->getData()), $match) === 1) {
360
+					if (count($match) >= 3) {
361
+						$Class = null;
362
+						if (in_array($match[1], array('$this', 'self', 'static'))) {
363
+							$Class = $Self;
364
+						} elseif (isset($this->Classes[$match[1]])) {
365
+							$Class = $this->Classes[$match[1]];
366
+						}
367
+
368
+						if ($Class) {
369
+							if (isset($Class->Methods[$match[3]])) {
370
+								$Method = $Class->Methods[$match[3]];
371
+								$Method->Statements = $this->expand($Method->Statements, $Class);
372
+								$output = array_merge($output, $Method->Statements);
373
+							} else {
374
+								throw new Exception("Method '{$match[3]}' for class '{$match[1]}' not found");
375
+							}
376
+						} else {
377
+							throw new Exception("Class '{$match[1]}' not found");
378
+						}
379
+					} elseif (isset($this->Functions[$match[1]])) {
380
+						$Function = $this->Functions[$match[1]];
381
+						$Function->Statements = $this->expand($Function->Statements);
382
+						$output = array_merge($output, $Function->Statements);
383
+					} else {
384
+						throw new Exception("Function '{$match[1]}' not found");
385
+					}
386
+				}
387
+			} else {
388
+				$output[] = $Statement;
389
+			}
390
+		}
391
+
392
+		return $output;
393
+	}
394 394
 
395 395
 }
Please login to merge, or discard this patch.