ExpressionValidator::checkBrackets()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 0
loc 4
rs 10
cc 1
eloc 3
nc 1
nop 1
1
<?php
2
3
namespace Asparagus;
4
5
use InvalidArgumentException;
6
7
/**
8
 * Package-private class to validate expressions like variables and IRIs.
9
 *
10
 * @license GNU GPL v2+
11
 * @author Bene* < [email protected] >
12
 */
13
class ExpressionValidator {
14
15
	/**
16
	 * Accept all expressions
17
	 */
18
	const VALIDATE_ALL = 255;
19
20
	/**
21
	 * Accept variables
22
	 */
23
	const VALIDATE_VARIABLE = 1;
24
25
	/**
26
	 * Accept IRIs
27
	 */
28
	const VALIDATE_IRI = 2;
29
30
	/**
31
	 * Accept prefixes
32
	 */
33
	const VALIDATE_PREFIX = 4;
34
35
	/**
36
	 * Accept prefixed IRIs
37
	 */
38
	const VALIDATE_PREFIXED_IRI = 8;
39
40
	/**
41
	 * Accept native values
42
	 */
43
	const VALIDATE_NATIVE = 16;
44
45
	/**
46
	 * Accepts property paths
47
	 */
48
	const VALIDATE_PATH = 32;
49
50
	/**
51
	 * Accept functions
52
	 */
53
	const VALIDATE_FUNCTION = 64;
54
55
	/**
56
	 * Accept functions with variable assignments
57
	 */
58
	const VALIDATE_FUNCTION_AS = 128;
59
60
	/**
61
	 * @var RegexHelper
62
	 */
63
	private $regexHelper;
64
65
	public function __construct() {
66
		$this->regexHelper = new RegexHelper();
67
	}
68
69
	/**
70
	 * Validates the given expression and tracks it.
71
	 * VALIDATE_PREFIX won't track prefixes.
72
	 *
73
	 * @param string $expression
74
	 * @param int $options
75
	 * @throws InvalidArgumentException
76
	 */
77
	public function validate( $expression, $options ) {
78
		if ( !is_string( $expression ) ) {
79
			throw new InvalidArgumentException( '$expression has to be a string.' );
80
		}
81
82
		if ( !$this->matches( $expression, $options ) ) {
83
			throw new InvalidArgumentException( '$expression has to be a ' .
84
				implode( ' or a ', $this->getOptionNames( $options ) ) . ', got ' . $expression
85
			);
86
		}
87
	}
88
89
	private function getOptionNames( $options ) {
90
		$names = array(
91
			'variable' => self::VALIDATE_VARIABLE,
92
			'IRI' => self::VALIDATE_IRI,
93
			'prefix' => self::VALIDATE_PREFIX,
94
			'prefixed IRI' => self::VALIDATE_PREFIXED_IRI,
95
			'native' => self::VALIDATE_NATIVE,
96
			'path' => self::VALIDATE_PATH,
97
			'function' => self::VALIDATE_FUNCTION,
98
			'function with variable assignment' => self::VALIDATE_FUNCTION_AS
99
		);
100
101
		$names = array_filter( $names, function( $key ) use ( $options ) {
102
			return $options & $key;
103
		} );
104
105
		return array_keys( $names );
106
	}
107
108
	private function matches( $expression, $options ) {
109
		return $this->isVariable( $expression, $options ) ||
110
			$this->isIRI( $expression, $options ) ||
111
			$this->isPrefix( $expression, $options ) ||
112
			$this->isPrefixedIri( $expression, $options ) ||
113
			$this->isValue( $expression, $options ) ||
114
			$this->isPath( $expression, $options ) ||
115
			$this->isFunction( $expression, $options ) ||
116
			$this->isFunctionAs( $expression, $options );
117
	}
118
119
	private function isVariable( $expression, $options ) {
120
		return $options & self::VALIDATE_VARIABLE &&
121
			$this->regexHelper->matchesRegex( '\{variable}', $expression );
122
	}
123
124
	private function isIRI( $expression, $options ) {
125
		return $options & self::VALIDATE_IRI &&
126
			$this->regexHelper->matchesRegex( '\{iri}', $expression );
127
	}
128
129
	private function isPrefix( $expression, $options ) {
130
		return $options & self::VALIDATE_PREFIX &&
131
			$this->regexHelper->matchesRegex( '\{prefix}', $expression );
132
	}
133
134
	private function isPrefixedIri( $expression, $options ) {
135
		return $options & self::VALIDATE_PREFIXED_IRI &&
136
			$this->regexHelper->matchesRegex( '\{prefixed_iri}', $expression );
137
	}
138
139
	private function isValue( $expression, $options ) {
140
		return $options & self::VALIDATE_NATIVE &&
141
			$this->regexHelper->matchesRegex( '\{native}', $expression );
142
	}
143
144
	private function isPath( $expression, $options ) {
145
		return $options & self::VALIDATE_PATH &&
146
			$this->regexHelper->matchesRegex( '\{path}', $expression );
147
	}
148
149
	private function isFunction( $expression, $options ) {
150
		// @todo this might not be complete
151
		return $options & self::VALIDATE_FUNCTION &&
152
			$this->regexHelper->matchesRegex( '\{function}', $expression ) &&
153
			$this->checkBrackets( $expression );
154
	}
155
156
	private function checkBrackets( $expression ) {
157
		$expression = $this->regexHelper->escapeSequences( $expression );
158
		return substr_count( $expression, '(' ) === substr_count( $expression, ')' );
159
	}
160
161
	private function isFunctionAs( $expression, $options ) {
162
		return $options & self::VALIDATE_FUNCTION_AS &&
163
			$this->regexHelper->matchesRegex( '\(\{function} AS \{variable}\)', $expression );
164
	}
165
166
}
167