Passed
Push — master ( 592389...04392b )
by
unknown
01:41
created

Url::getCurrentPath()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 2
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 2
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace CarbonFramework\Routing\Conditions;
4
5
use CarbonFramework\Url as UrlUtility;
6
use CarbonFramework\Request;
7
8
/**
9
 * Check against the current url
10
 */
11
class Url implements ConditionInterface {
12
	/**
13
	 * URL to check against
14
	 * 
15
	 * @var string
16
	 */
17
	protected $url = '';
18
19
	/**
20
	 * Regex to detect parameters in urls
21
	 * 
22
	 * @var string
23
	 */
24
	protected $url_regex = '~
25
		(?:/)                     # require leading slash
26
		(?:\{)                    # require opening curly brace
27
			(?P<name>[a-z]\w*)    # require a string starting with a-z and followed by any number of word characters for the parameter name
28
			(?P<optional>\?)?     # optionally allow the user to mark the parameter as option using literal ?
29
			(?::(?P<regex>.*?))?  # optionally allow the user to supply a regex to match the argument against
30
		(?:\})                    # require closing curly brace
31
		(?=/)                     # lookahead for a slash but do not consume it as it may be used by the next match
32
	~ix';
33
34
	/**
35
	 * Regex to detect valid parameters in url segments
36
	 * 
37
	 * @var string
38
	 */
39
	protected $parameter_regex = '[^/]+';
40
41
	/**
42
	 * Constructor
43
	 * 
44
	 * @param string $url
45
	 */
46
	public function __construct( $url ) {
47
		$url = UrlUtility::addLeadingSlash( $url );
48
		$url = UrlUtility::addTrailingSlash( $url );
49
		$this->url = $url;
50
	}
51
52
	/**
53
	 * {@inheritDoc}
54
	 */
55
	public function satisfied( Request $request ) {
56
		$validation_regex = $this->getValidationRegex( $this->getUrl() );
57
		$url = UrlUtility::getCurrentPath( $request );
58
		return (bool) preg_match( $validation_regex, $url );
59
	}
60
61
	/**
62
	 * {@inheritDoc}
63
	 */
64
	public function getArguments( Request $request ) {
65
		$validation_regex = $this->getValidationRegex( $this->getUrl() );
66
		$url = UrlUtility::getCurrentPath( $request );
67
		$matches = [];
68
		$success = preg_match( $validation_regex, $url, $matches );
69
70
		if ( ! $success ) {
71
			return []; // this should not normally happen
72
		}
73
74
		$arguments = [];
75
		$parameter_names = $this->getParameterNames( $this->getUrl() );
76
		foreach ( $parameter_names as $parameter_name ) {
77
			$arguments[] = ! empty( $matches[ $parameter_name ] ) ? $matches[ $parameter_name ] : '';
78
		}
79
		
80
		return $arguments;
81
	}
82
83
	/**
84
	 * Return the url for this condition
85
	 * 
86
	 * @return string
87
	 */
88
	public function getUrl() {
89
		return $this->url;
90
	}
91
92
	/**
93
	 * Concatenate 2 url conditions into a new one
94
	 * 
95
	 * @param  Url $url
96
	 * @return Url
97
	 */
98
	public function concatenate( Url $url ) {
99
		return new static( UrlUtility::removeTrailingSlash( $this->getUrl() ) . $url->getUrl() );
100
	}
101
102
	/**
103
	 * Return parameter names as defined in the url
104
	 * 
105
	 * @param  string   $url
106
	 * @return string[]
107
	 */
108
	protected function getParameterNames( $url ) {
109
		$matches = [];
110
		preg_match_all( $this->url_regex, $url, $matches );
111
		return $matches['name'];
112
	}
113
114
	/**
115
	 * Return regex to test whether normal urls match the parameter-based one
116
	 * 
117
	 * @param  string $url
118
	 * @return string
119
	 */
120
	protected function getValidationRegex( $url ) {
121
		$parameters = [];
122
123
		// Replace all parameters with placeholders
124
		$validation_regex = preg_replace_callback( $this->url_regex, function( $matches ) use ( &$parameters ) {
125
			$name = $matches['name'];
126
			$optional = ! empty( $matches['optional'] );
127
			$regex = ! empty( $matches['regex'] ) ? $matches['regex'] : $this->parameter_regex;
128
			$replacement = '(?:/(?P<' . $name . '>' . $regex . '))';
129
			if ( $optional ) {
130
				$replacement .= '?';
131
			}
132
133
			$placeholder = '___placeholder_' . sha1( count( $parameters) . '_' . $replacement . '_' . uniqid() ) . '___';
134
			$parameters[ $placeholder ] = $replacement;
135
			return $placeholder;
136
		}, $url );
137
138
		// quote the remaining string so that it does not get evaluated as regex
139
		$validation_regex = preg_quote( $validation_regex, '~' );
140
141
		// replace the placeholders with the real parameter regexes
142
		$validation_regex = str_replace( array_keys( $parameters ), array_values( $parameters ), $validation_regex );
143
144
		// make sure that the regex matches the entire string
145
		$validation_regex = '~\A' . $validation_regex . '\z~';
146
147
		return $validation_regex;
148
	}
149
}
150