Passed
Push — master ( 3c464a...c957c0 )
by Atanas
03:48
created

ConditionFactory   A

Complexity

Total Complexity 22

Size/Duplication

Total Lines 180
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 4

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
dl 0
loc 180
ccs 52
cts 52
cp 1
rs 10
c 0
b 0
f 0
wmc 22
lcom 1
cbo 4

11 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 3 1
A make() 0 15 4
A isNegatedCondition() 0 7 2
A parseNegatedCondition() 0 7 1
A parseConditionOptions() 0 18 4
A makeFromUrl() 0 3 1
A makeFromArray() 0 16 3
A makeFromArrayOfConditions() 0 3 1
A makeFromClosure() 0 3 1
A conditionTypeRegistered() 0 7 2
A getConditionTypeClass() 0 7 2
1
<?php
2
3
namespace WPEmerge\Routing\Conditions;
4
5
use Closure;
6
use Exception;
7
use ReflectionClass;
8
use WPEmerge\Routing\Conditions\CustomCondition;
9
use WPEmerge\Routing\Conditions\MultipleCondition;
10
use WPEmerge\Routing\Conditions\UrlCondition;
11
12
/**
13
 * Check against the current url
14
 */
15
class ConditionFactory {
16
	const NEGATE_CONDITION_PREFIX = '!';
17
18
	/**
19
	 * Registered condition types.
20
	 *
21
	 * @var array<string, string>
22
	 */
23
	protected $condition_types = [];
24
25
	/**
26
	 * Constructor.
27
	 *
28
	 * @codeCoverageIgnore
29
	 * @param array<string, string> $condition_types
30
	 */
31
	public function __construct( $condition_types ) {
32
		$this->condition_types = $condition_types;
33
	}
34
35
	/**
36
	 * Create a new condition.
37
	 *
38
	 * @throws InvalidRouteConditionException
39
	 * @param  string|array|Closure           $options
40
	 * @return ConditionInterface
41
	 */
42 13
	public function make( $options ) {
43 13
		if ( is_string( $options ) ) {
44 2
			return $this->makeFromUrl( $options );
45
		}
46
47 11
		if ( is_array( $options ) ) {
48 9
			return $this->makeFromArray( $options );
49
		}
50
51 2
		if ( $options instanceof Closure ) {
52 1
			return $this->makeFromClosure( $options );
53
		}
54
55 1
		throw new InvalidRouteConditionException( 'Invalid condition options supplied.' );
56
	}
57
58
	/**
59
	 * Get condition class for condition type.
60
	 *
61
	 * @param  string      $condition_type
62
	 * @return string|null
63
	 */
64 2
	protected function getConditionTypeClass( $condition_type ) {
65 2
		if ( ! isset( $this->condition_types[ $condition_type ] ) ) {
66 1
			return null;
67
		}
68
69 1
		return $this->condition_types[ $condition_type ];
70
	}
71
72
	/**
73
	 * Check if the passed argument is a registered condition type.
74
	 *
75
	 * @param  mixed   $condition_type
76
	 * @return boolean
77
	 */
78 6
	protected function conditionTypeRegistered( $condition_type ) {
79 6
		if ( ! is_string( $condition_type ) ) {
80 1
			return false;
81
		}
82
83 5
		return $this->getConditionTypeClass( $condition_type ) !== null;
84
	}
85
86
	/**
87
	 * Check if a condition is negated.
88
	 *
89
	 * @param  mixed   $condition
90
	 * @return boolean
91
	 */
92 1
	protected function isNegatedCondition( $condition ) {
93
		return (
94 1
			is_string( $condition )
95 1
			&&
96 1
			substr( $condition, 0, strlen( static::NEGATE_CONDITION_PREFIX ) ) === static::NEGATE_CONDITION_PREFIX
97 1
		);
98
	}
99
100
	/**
101
	 * Parse a negated condition and its arguments.
102
	 *
103
	 * @param  string $type
104
	 * @param  array  $arguments
105
	 * @return array
106
	 */
107 1
	protected function parseNegatedCondition( $type, $arguments ) {
108 1
		$negated_type = substr( $type, strlen( static::NEGATE_CONDITION_PREFIX ) );
109 1
		$arguments = array_merge( [ $negated_type ], $arguments );
110 1
		$type = 'negate';
111
112 1
		return ['type' => $type, 'arguments' => $arguments];
113
	}
114
115
	/**
116
	 * Parse the condition type and its arguments from an options array.
117
	 *
118
	 * @throws Exception
119
	 * @param  array $options
120
	 * @return array
121
	 */
122 7
	protected function parseConditionOptions( $options ) {
123 7
		$type = $options[0];
124 7
		$arguments = array_values( array_slice( $options, 1 ) );
125
126 7
		if ( $this->isNegatedCondition( $type ) ) {
127 1
			return $this->parseNegatedCondition( $type, $arguments );
128
		}
129
130 7
		if ( ! $this->conditionTypeRegistered( $type ) ) {
131 3
			if ( is_callable( $type ) ) {
132 2
				return ['type' => 'custom', 'arguments' => $options];
133
			}
134
135 1
			throw new Exception( 'Unknown condition type specified: ' . $type );
136
		}
137
138 4
		return ['type' => $type, 'arguments' => $arguments ];
139
	}
140
141
	/**
142
	 * Create a new condition from a url.
143
	 *
144
	 * @param  string             $url
145
	 * @return ConditionInterface
146
	 */
147 1
	protected function makeFromUrl( $url ) {
148 1
		return new UrlCondition( $url );
149
	}
150
151
	/**
152
	 * Create a new condition from an array.
153
	 *
154
	 * @throws Exception
155
	 * @param  array               $options
156
	 * @return ConditionInterface
157
	 */
158 9
	protected function makeFromArray( $options ) {
159 9
		if ( count( $options ) === 0 ) {
160 1
			throw new Exception( 'No condition type specified.' );
161
		}
162
163 8
		if ( is_array( $options[0] ) ) {
164 1
			return $this->makeFromArrayOfConditions( $options );
165
		}
166
167 8
		$condition_options = $this->parseConditionOptions( $options );
168 7
		$condition_class = $this->getConditionTypeClass( $condition_options['type'] );
169
170 7
		$reflection = new ReflectionClass( $condition_class );
171 7
		$condition = $reflection->newInstanceArgs( $condition_options['arguments'] );
172 7
		return $condition;
173
	}
174
175
	/**
176
	 * Create a new condition from an array of conditions.
177
	 *
178
	 * @param  array               $options
179
	 * @return ConditionInterface
180
	 */
181 1
	protected function makeFromArrayOfConditions( $options ) {
182 1
		return new MultipleCondition( $options );
183
	}
184
185
	/**
186
	 * Create a new condition from a closure.
187
	 *
188
	 * @param  Closure            $closure
189
	 * @return ConditionInterface
190
	 */
191 1
	protected function makeFromClosure( Closure $closure ) {
192 1
		return new CustomCondition( $closure );
193
	}
194
}
195