Completed
Push — v1.3.2 ( 5f6666 )
by Bradley
04:11
created

Logical::decodeLogicStatements()   C

Complexity

Conditions 20
Paths 16

Size

Total Lines 65
Code Lines 37

Duplication

Lines 0
Ratio 0 %

Importance

Changes 6
Bugs 1 Features 2
Metric Value
c 6
b 1
f 2
dl 0
loc 65
rs 5.86
cc 20
eloc 37
nc 16
nop 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php namespace Cornford\Logical;
2
3
use Cornford\Logical\Contracts\LogicalInterface;
4
use Cornford\Logical\Exceptions\LogicalDecodingException;
5
use Cornford\Logical\Exceptions\LogicalExecutionException;
6
use Cornford\Logical\Exceptions\LogicalFieldValueException;
7
use Exception;
8
9
class Logical extends LogicalAbstract implements LogicalInterface {
10
11
	/**
12
	 * The temporary logic method.
13
	 *
14
	 * @var string
15
	 */
16
	protected $tempLogic;
17
18
	/**
19
	 * The temporary logic method.
20
	 *
21
	 * @var string
22
	 */
23
	protected $tempMethod;
24
25
	/**
26
	 * The temporary logic expected.
27
	 *
28
	 * @var string|array
29
	 */
30
	protected $tempExpected;
31
32
	/**
33
	 * The temporary logic field.
34
	 *
35
	 * @var string
36
	 */
37
	protected $tempField;
38
39
	/**
40
	 * The temporary results.
41
	 *
42
	 * @var array
43
	 */
44
	protected $tempResults;
45
46
	/**
47
	 * Decode the logic string into an array of logical statements.
48
	 *
49
	 * @return boolean
50
	 */
51
	protected function decodeLogicStatements()
52
	{
53
		if (!$this->getLogic()) {
54
			return true;
55
		}
56
57
		$orStatements = preg_split("/.OR./", $this->getLogic());
58
59
		foreach ($orStatements as $orKey => $orStatement) {
60
			$andStatements = preg_split("/.AND./", $orStatement);
61
62
			foreach ($andStatements as $andStatement) {
63
				$items = preg_split("/\./", $andStatement, 2);
64
				$decodedStatement = [];
65
66
				foreach ($items as $item) {
67
					$matches = null;
68
					if (stristr($item, 'where')) {
69
						if (!preg_match("/\((?<field>.*)\)/", $item, $matches)) {
70
							return false;
71
						}
72
73
						$this->tempField = trim(trim($matches['field'], '\''), '"');
74
75
						continue;
76
					}
77
78
					if (!preg_match("/^(?<method>[a-zA-Z]{1,})\((?<expected>[\'\"]*.*[\'\"]*)\)/", $item, $matches)) {
79
						return false;
80
					} else {
81
						$this->tempMethod = trim(trim($matches['method'], '\''), '"');
82
						$this->tempExpected = trim(trim($matches['expected'], '\''), '"');
83
					}
84
85
					if (stristr($this->tempExpected, ',') && !stristr($this->tempExpected, '{') && !stristr($this->tempExpected, '}')) {
86
						$this->tempExpected = explode(', ', $this->tempExpected);
87
88
						if (is_array($this->tempExpected)) {
89
							foreach ($this->tempExpected as &$expected) {
90
								$expected = trim(trim($expected, '\''), '"');
91
							}
92
						}
93
					}
94
95
					if (!is_array($this->tempExpected) && stristr($this->tempExpected, '{') && stristr($this->tempExpected, '}')) {
96
						$this->tempExpected = eval(str_replace('{', 'return (', str_replace('}', ');', $this->tempExpected)));
97
					} elseif(is_array($this->tempExpected)) {
98
						foreach ($this->tempExpected as &$expected) {
99
							if (stristr($expected, '{') && stristr($expected, '}')) {
100
								$expected = eval(str_replace('{', 'return (', str_replace('}', ');', $expected)));
101
							}
102
						}
103
					}
104
105
					$decodedStatement[$orKey]['method'] = $this->tempMethod;
106
					$decodedStatement[$orKey]['expected'] = $this->tempExpected;
107
					$decodedStatement[$orKey]['field'] = $this->tempField;
108
				}
109
110
				$this->setDecodedLogicStatement($decodedStatement);
111
			}
112
		}
113
114
		return true;
115
	}
116
117
	/**
118
	 * Execute a logic statement method on an input value against an expected value.
119
	 *
120
	 * @param string                 $method
121
	 * @param string|integer|boolean $input
122
	 * @param string|integer|boolean $expected
123
	 *
124
	 * @throws LogicalExecutionException
125
	 *
126
	 * @return boolean
127
	 */
128
	protected function executeLogicStatement($method, $input, $expected = null)
129
	{
130
		$logicalStatementInstance = $this->getLogicalStatementInstance();
131
		$result = null;
132
133
		if (method_exists($logicalStatementInstance, $method)) {
134
			$result = $logicalStatementInstance->$method($input, $expected);
135
		}
136
137
		if ($logicalStatementInstance->customStatementExists($method)) {
138
			$result = $logicalStatementInstance->callCustomStatement($method, $input, $expected);
139
		}
140
141
		if (is_null($result)) {
142
			throw new LogicalExecutionException("Unable to execute logic statement method: {$method}().");
143
		}
144
145
		return $result;
146
	}
147
148
	/**
149
	 * Decodes logic input into statements and executes each statement removing un-matching results.
150
	 *
151
	 * @throws LogicalDecodingException
152
	 * @throws LogicalFieldValueException
153
	 *
154
	 * @return self
155
	 */
156
	public function execute()
157
	{
158
		if (!$this->decodeLogicStatements()) {
159
			throw new LogicalDecodingException('Unable to decode logic input.');
160
		}
161
162
		foreach ($this->getDecodedLogicStatements() as $orStatement) {
163
			$this->tempResults = $this->getInput();
164
165
			foreach ($this->getInput() as $key => $input) {
166
				foreach ($orStatement as $andStatement) {
167
					switch (gettype($input)) {
168
						case 'object':
169
							break;
170
						case 'array':
171
						default:
172
							$andStatement['field'] = '[' . $andStatement['field'] . ']';
173
					}
174
175
					try {
176
						$value = $this->getPropertyAccessorInstance()->getValue($input, $andStatement['field']);
177
					} catch (Exception $exception) {
178
						throw new LogicalFieldValueException('Unable to locate logical statement field value.');
179
					}
180
181
					if (!isset($value)) {
182
						throw new LogicalFieldValueException('Unable to locate logical statement field value.');
183
					}
184
185
					if (!$this->executeLogicStatement($andStatement['method'], $value, $andStatement['expected'])) {
186
						unset($this->tempResults[$key]);
187
					}
188
				}
189
			}
190
191
			$this->mergeResults($this->tempResults);
192
		}
193
194
		return $this;
195
	}
196
197
}