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

StringType   B

Complexity

Total Complexity 46

Size/Duplication

Total Lines 146
Duplicated Lines 9.59 %

Coupling/Cohesion

Components 1
Dependencies 2

Importance

Changes 0
Metric Value
wmc 46
lcom 1
cbo 2
dl 14
loc 146
rs 8.3999
c 0
b 0
f 0

9 Methods

Rating   Name   Duplication   Size   Complexity  
A parseDefinition() 14 14 2
A parseFormat() 0 8 2
A parseContent() 0 8 3
C parseRange() 0 22 16
A parseDefault() 0 4 3
C handleCommand() 0 22 7
A toArray() 0 12 4
B validateDefault() 0 20 8
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 StringType 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 StringType, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace SwaggerGen\Swagger\Type;
4
5
/**
6
 * Basic strings 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 StringType extends AbstractType
14
{
15
16
	private static $formats = array(
17
		'string' => '',
18
		'byte' => 'byte',
19
		'binary' => 'binary',
20
		'password' => 'password',
21
		'enum' => '',
22
	);
23
	private $format;
24
	private $pattern = null;
25
	private $default = null;
26
	private $maxLength = null;
27
	private $minLength = null;
28
	private $enum = array();
29
30 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...
31
	{
32
		$definition = self::trim($definition);
33
34
		$match = array();
35
		if (preg_match(self::REGEX_START . self::REGEX_FORMAT . self::REGEX_CONTENT . self::REGEX_RANGE . self::REGEX_DEFAULT . self::REGEX_END, $definition, $match) !== 1) {
36
			throw new \SwaggerGen\Exception("Unparseable string definition: '{$definition}'");
37
		}
38
39
		$this->parseFormat($definition, $match);
40
		$this->parseContent($definition, $match);
41
		$this->parseRange($definition, $match);
42
		$this->parseDefault($definition, $match);
43
	}
44
45
	private function parseFormat($definition, $match)
46
	{
47
		$type = strtolower($match[1]);
48
		if (!isset(self::$formats[$type])) {
49
			throw new \SwaggerGen\Exception("Not a string: '{$definition}'");
50
		}
51
		$this->format = self::$formats[$type];
52
	}
53
54
	private function parseContent($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...
55
	{
56
		if (strtolower($match[1]) === 'enum') {
57
			$this->enum = preg_split('/,/', $match[2]);
58
		} else {
59
			$this->pattern = empty($match[2]) ? null : $match[2];
60
		}
61
	}
62
63
	private function parseRange($definition, $match)
64
	{
65
66
		if (!empty($match[3])) {
67
			if ($match[1] === 'enum') {
68
				throw new \SwaggerGen\Exception("Range not allowed in enumeration definition: '{$definition}'");
69
			}
70
			if ($match[4] === '' && $match[5] === '') {
71
				throw new \SwaggerGen\Exception("Empty string range: '{$definition}'");
72
			}
73
			$exclusiveMinimum = isset($match[3]) ? ($match[3] == '<') : null;
74
			$this->minLength = $match[4] === '' ? null : $match[4];
75
			$this->maxLength = $match[5] === '' ? null : $match[5];
76
			$exclusiveMaximum = isset($match[6]) ? ($match[6] == '>') : null;
77
			if ($this->minLength !== null && $this->maxLength !== null && $this->minLength > $this->maxLength) {
78
				self::swap($this->minLength, $this->maxLength);
79
				self::swap($exclusiveMinimum, $exclusiveMaximum);
80
			}
81
			$this->minLength = $this->minLength === null ? null : max(0, $exclusiveMinimum ? $this->minLength + 1 : $this->minLength);
82
			$this->maxLength = $this->maxLength === null ? null : max(0, $exclusiveMaximum ? $this->maxLength - 1 : $this->maxLength);
83
		}
84
	}
85
86
	private function parseDefault($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...
87
	{
88
		$this->default = isset($match[7]) && $match[7] !== '' ? $this->validateDefault($match[7]) : null;
89
	}
90
91
	/**
92
	 * @param string $command The comment command
93
	 * @param string $data Any data added after the command
94
	 * @return \SwaggerGen\Swagger\Type\AbstractType|boolean
95
	 */
96
	public function handleCommand($command, $data = null)
97
	{
98
		switch (strtolower($command)) {
99
			case 'default':
100
				$this->default = $this->validateDefault($data);
101
				return $this;
102
103
			case 'pattern':
104
				$this->pattern = $data;
105
				return $this;
106
107
			case 'enum':
108
				if ($this->minLength !== null || $this->maxLength !== null) {
109
					throw new \SwaggerGen\Exception("Enumeration not allowed in ranged string: '{$data}'");
110
				}
111
				$words = self::wordSplit($data);
112
				$this->enum = is_array($this->enum) ? array_merge($this->enum, $words) : $words;
113
				return $this;
114
		}
115
116
		return parent::handleCommand($command, $data);
117
	}
118
119
	public function toArray()
120
	{
121
		return self::arrayFilterNull(array(
122
					'type' => 'string',
123
					'format' => empty($this->format) ? null : $this->format,
124
					'pattern' => $this->pattern,
125
					'default' => $this->default,
126
					'minLength' => $this->minLength ? intval($this->minLength) : null,
127
					'maxLength' => $this->maxLength ? intval($this->maxLength) : null,
128
					'enum' => $this->enum,
129
		));
130
	}
131
132
	private function validateDefault($value)
133
	{
134
		if (empty($value)) {
135
			throw new \SwaggerGen\Exception("Empty string default");
136
		}
137
138
		if (!empty($this->enum) && !in_array($value, $this->enum)) {
139
			throw new \SwaggerGen\Exception("Invalid enumeration default: '{$value}'");
140
		}
141
142
		if ($this->maxLength !== null && mb_strlen($value) > $this->maxLength) {
143
			throw new \SwaggerGen\Exception("Default length beyond maximum: '{$value}'");
144
		}
145
146
		if ($this->minLength !== null && mb_strlen($value) < $this->minLength) {
147
			throw new \SwaggerGen\Exception("Default length beyond minimum: '{$value}'");
148
		}
149
150
		return $value;
151
	}
152
153
	public function __toString()
154
	{
155
		return __CLASS__;
156
	}
157
158
}
159