Completed
Push — master ( 8f24e9...7bd323 )
by Martijn
02:28
created

ArrayType   B

Complexity

Total Complexity 44

Size/Duplication

Total Lines 183
Duplicated Lines 27.32 %

Coupling/Cohesion

Components 1
Dependencies 4

Importance

Changes 0
Metric Value
wmc 44
lcom 1
cbo 4
dl 50
loc 183
rs 8.3396
c 0
b 0
f 0

8 Methods

Rating   Name   Duplication   Size   Complexity  
A parseDefinition() 13 13 2
B parseFormat() 0 16 5
A parseItems() 0 6 2
C parseRange() 19 19 15
C handleCommand() 18 37 12
A toArray() 0 10 3
A validateItems() 0 19 4
A __toString() 0 4 1

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like ArrayType often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use ArrayType, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace SwaggerGen\Swagger\Type;
4
5
/**
6
 * Basic array type definition.
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
class ArrayType extends AbstractType
14
{
15
16
	private static $classTypes = array(
17
		'integer' => 'Integer',
18
		'int' => 'Integer',
19
		'int32' => 'Integer',
20
		'int64' => 'Integer',
21
		'long' => 'Integer',
22
		'float' => 'Number',
23
		'double' => 'Number',
24
		'string' => 'String',
25
		'byte' => 'String',
26
		'binary' => 'String',
27
		'password' => 'String',
28
		'enum' => 'String',
29
		'boolean' => 'Boolean',
30
		'bool' => 'Boolean',
31
		'array' => 'Array',
32
		'csv' => 'Array',
33
		'ssv' => 'Array',
34
		'tsv' => 'Array',
35
		'pipes' => 'Array',
36
		'date' => 'Date',
37
		'datetime' => 'Date',
38
		'date-time' => 'Date',
39
		'object' => 'Object',
40
	);
41
	private static $collectionFormats = array(
42
		'array' => 'csv',
43
		'csv' => 'csv',
44
		'ssv' => 'ssv',
45
		'tsv' => 'tsv',
46
		'pipes' => 'pipes',
47
		'multi' => 'multi',
48
	);
49
50
	/**
51
	 * @var AbstractType
52
	 */
53
	private $Items = null;
54
	private $minItems = null;
55
	private $maxItems = null;
56
	private $collectionFormat = null;
57
58 View Code Duplication
	protected function parseDefinition($definition)
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...
59
	{
60
		$definition = self::trim($definition);
61
62
		$match = array();
63
		if (preg_match(self::REGEX_START . self::REGEX_FORMAT . self::REGEX_CONTENT . self::REGEX_RANGE . self::REGEX_END, $definition, $match) !== 1) {
64
			throw new \SwaggerGen\Exception("Unparseable array definition: '{$definition}'");
65
		}
66
		
67
		$this->parseFormat($definition, $match);
68
		$this->parseItems($definition, $match);
69
		$this->parseRange($definition, $match);
70
	}
71
72
	private function parseFormat($definition, $match)
73
	{
74
		$type = strtolower($match[1]);
75
		if (!isset(self::$collectionFormats[$type])) {
76
			throw new \SwaggerGen\Exception("Not an array: '{$definition}'");
77
		}
78
79
		if ($type === 'multi') {
80
			$parent = $this->getParent();
81
			if (!($parent instanceof \SwaggerGen\Swagger\Parameter) || !$parent->isMulti()) {
82
				throw new \SwaggerGen\Exception("Multi array only allowed on query or form parameter: '{$definition}'");
83
			}
84
		}
85
86
		$this->collectionFormat = self::$collectionFormats[$type];
87
	}
88
89
	private function parseItems($definition, $match)
0 ignored issues
show
Unused Code introduced by
The parameter $definition is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
90
	{
91
		if (!empty($match[2])) {
92
			$this->Items = $this->validateItems($match[2]);
93
		}
94
	}
95
96 View Code Duplication
	private function parseRange($definition, $match)
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...
97
	{
98
		if (!empty($match[3])) {
99
			if ($match[4] === '' && $match[5] === '') {
100
				throw new \SwaggerGen\Exception("Empty array range: '{$definition}'");
101
			}
102
103
			$exclusiveMinimum = isset($match[3]) ? ($match[3] == '<') : null;
104
			$this->minItems = $match[4] === '' ? null : intval($match[4]);
105
			$this->maxItems = $match[5] === '' ? null : intval($match[5]);
106
			$exclusiveMaximum = isset($match[6]) ? ($match[6] == '>') : null;
107
			if ($this->minItems && $this->maxItems && $this->minItems > $this->maxItems) {
108
				self::swap($this->minItems, $this->maxItems);
109
				self::swap($exclusiveMinimum, $exclusiveMaximum);
110
			}
111
			$this->minItems = $this->minItems === null ? null : max(0, $exclusiveMinimum ? $this->minItems + 1 : $this->minItems);
112
			$this->maxItems = $this->maxItems === null ? null : max(0, $exclusiveMaximum ? $this->maxItems - 1 : $this->maxItems);
113
		}
114
	}
115
116
	/**
117
	 * @param string $command The comment command
118
	 * @param string $data Any data added after the command
119
	 * @return \SwaggerGen\Swagger\Type\AbstractType|boolean
120
	 */
121
	public function handleCommand($command, $data = null)
122
	{
123
		if ($this->Items) {
124
			$return = $this->Items->handleCommand($command, $data);
125
			if ($return) {
126
				return $return;
127
			}
128
		}
129
130
		switch (strtolower($command)) {
131 View Code Duplication
			case 'min':
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->minItems = intval($data);
133
				if ($this->minItems < 0) {
134
					throw new \SwaggerGen\Exception("Minimum less than zero: '{$data}'");
135
				}
136
				if ($this->maxItems !== null && $this->minItems > $this->maxItems) {
137
					throw new \SwaggerGen\Exception("Minimum greater than maximum: '{$data}'");
138
				}
139
				return $this;
140
141 View Code Duplication
			case 'max':
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...
142
				$this->maxItems = intval($data);
143
				if ($this->minItems !== null && $this->minItems > $this->maxItems) {
144
					throw new \SwaggerGen\Exception("Maximum less than minimum: '{$data}'");
145
				}
146
				if ($this->maxItems < 0) {
147
					throw new \SwaggerGen\Exception("Maximum less than zero: '{$data}'");
148
				}
149
				return $this;
150
151
			case 'items':
152
				$this->Items = $this->validateItems($data);
153
				return $this->Items;
154
		}
155
156
		return parent::handleCommand($command, $data);
157
	}
158
159
	public function toArray()
160
	{
161
		return self::arrayFilterNull(array(
162
					'type' => 'array',
163
					'items' => empty($this->Items) ? null : $this->Items->toArray(),
164
					'collectionFormat' => $this->collectionFormat == 'csv' ? null : $this->collectionFormat,
165
					'minItems' => $this->minItems,
166
					'maxItems' => $this->maxItems,
167
		));
168
	}
169
170
	private function validateItems($items)
171
	{
172
		if (empty($items)) {
173
			throw new \SwaggerGen\Exception("Empty items definition: '{$items}'");
174
		}
175
176
		$match = array();
177
		if (preg_match('/^([a-z]+)/i', $items, $match) !== 1) {
178
			throw new \SwaggerGen\Exception("Unparseable items definition: '{$items}'");
179
		}
180
		$format = strtolower($match[1]);
181
		if (isset(self::$classTypes[$format])) {
182
			$type = self::$classTypes[$format];
183
			$typeClass = "SwaggerGen\\Swagger\\Type\\{$type}Type";
184
			return new $typeClass($this, $items);
185
		}
186
187
		return new ReferenceObjectType($this, $items);
188
	}
189
190
	public function __toString()
191
	{
192
		return __CLASS__;
193
	}
194
195
}
196