Completed
Push — master ( 14b9fa...3d5cfe )
by Josh
18:22 queued 02:33
created

FilterProcessing::executeAttributePreprocessor()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 14
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 4

Importance

Changes 0
Metric Value
dl 0
loc 14
rs 9.2
c 0
b 0
f 0
ccs 7
cts 7
cp 1
cc 4
eloc 6
nc 3
nop 4
crap 4
1
<?php
2
3
/**
4
* @package   s9e\TextFormatter
5
* @copyright Copyright (c) 2010-2017 The s9e Authors
6
* @license   http://www.opensource.org/licenses/mit-license.php The MIT License
7
*/
8
namespace s9e\TextFormatter\Parser;
9
10
use s9e\TextFormatter\Parser;
11
use s9e\TextFormatter\Parser\Logger;
12
use s9e\TextFormatter\Parser\Tag;
13
14
class FilterProcessing
15
{
16
	/**
17
	* Execute all the attribute preprocessors of given tag
18
	*
19
	* @private
20
	*
21
	* @param  Tag   $tag       Source tag
22
	* @param  array $tagConfig Tag's config
23
	* @return void
24
	*/
25 6
	public static function executeAttributePreprocessors(Tag $tag, array $tagConfig)
26
	{
27 6
		if (empty($tagConfig['attributePreprocessors']))
28
		{
29
			return;
30
		}
31
32 6
		foreach ($tagConfig['attributePreprocessors'] as list($attrName, $regexp, $map))
33
		{
34 6
			if ($tag->hasAttribute($attrName))
35
			{
36 6
				self::executeAttributePreprocessor($tag, $attrName, $regexp, $map);
37
			}
38
		}
39 6
	}
40
41
	/**
42
	* Filter the attributes of given tag
43
	*
44
	* @private
45
	*
46
	* @param  Tag    $tag            Tag being checked
47
	* @param  array  $tagConfig      Tag's config
48
	* @param  array  $registeredVars Array of registered vars for use in attribute filters
49
	* @param  Logger $logger         This parser's Logger instance
50
	* @return void
51
	*/
52 14
	public static function filterAttributes(Tag $tag, array $tagConfig, array $registeredVars, Logger $logger)
53
	{
54 14
		$attributes = [];
55 14
		foreach ($tagConfig['attributes'] as $attrName => $attrConfig)
56
		{
57 7
			$attrValue = false;
58 7
			if ($tag->hasAttribute($attrName))
59
			{
60
				$vars = [
61 6
					'attrName'       => $attrName,
62 6
					'attrValue'      => $tag->getAttribute($attrName),
63 6
					'logger'         => $logger,
64 6
					'registeredVars' => $registeredVars
65
				];
66 6
				$attrValue = self::executeAttributeFilterChain($attrConfig['filterChain'], $vars);
67
			}
68
69 7
			if ($attrValue !== false)
70
			{
71 3
				$attributes[$attrName] = $attrValue;
72
			}
73 4
			elseif (isset($attrConfig['defaultValue']))
74
			{
75 2
				$attributes[$attrName] = $attrConfig['defaultValue'];
76
			}
77 2
			elseif (!empty($attrConfig['required']))
78
			{
79 7
				$tag->invalidate();
80
			}
81
		}
82 14
		$tag->setAttributes($attributes);
83 14
	}
84
85
	/**
86
	* Execute a tag's filterChain
87
	*
88
	* @private
89
	*
90
	* @param  Tag    $tag        Tag to filter
91
	* @param  Parser $parser     Parser
92
	* @param  array  $tagsConfig Tags' config
93
	* @param  Tag[]  $openTags   List of open tags
94
	* @return void
95
	*/
96 6
	public static function filterTag(Tag $tag, Parser $parser, array $tagsConfig, array $openTags)
97
	{
98 6
		$tagName   = $tag->getName();
99 6
		$tagConfig = $tagsConfig[$tagName];
100
101
		// Record the tag being processed into the logger it can be added to the context of
102
		// messages logged during the execution
103 6
		$logger = $parser->getLogger();
104 6
		$logger->setTag($tag);
105
106
		// Prepare the variables that are accessible to filters
107
		$vars = [
108 6
			'logger'         => $logger,
109 6
			'openTags'       => $openTags,
110 6
			'parser'         => $parser,
111 6
			'registeredVars' => $parser->registeredVars,
112 6
			'tag'            => $tag,
113 6
			'tagConfig'      => $tagConfig,
114 6
			'text'           => $parser->getText()
115
		];
116 6
		foreach ($tagConfig['filterChain'] as $filter)
117
		{
118 6
			if ($tag->isInvalid())
119
			{
120 1
				break;
121
			}
122 6
			self::executeFilter($filter, $vars);
123
		}
124
125
		// Remove the tag from the logger
126 6
		$logger->unsetTag();
127 6
	}
128
129
	/**
130
	* Execute an attribute's filterChain
131
	*
132
	* @param  array $filterChain Attribute's filterChain
133
	* @param  array $vars        Callback vars
134
	* @return mixed              Filtered value
135
	*/
136 6
	protected static function executeAttributeFilterChain(array $filterChain, array $vars)
137
	{
138 6
		$vars['logger']->setAttribute($vars['attrName']);
139 6
		foreach ($filterChain as $filter)
140
		{
141 5
			$vars['attrValue'] = self::executeFilter($filter, $vars);
142 5
			if ($vars['attrValue'] === false)
143
			{
144 5
				break;
145
			}
146
		}
147 6
		$vars['logger']->unsetAttribute();
148
149 6
		return $vars['attrValue'];
150
	}
151
152
	/**
153
	* Execute an attribute preprocessor
154
	*
155
	* @param  Tag      $tag
156
	* @param  string   $attrName
157
	* @param  string   $regexp
158
	* @param  string[] $map
159
	* @return void
160
	*/
161 5
	protected static function executeAttributePreprocessor(Tag $tag, $attrName, $regexp, $map)
162
	{
163 5
		$attrValue = $tag->getAttribute($attrName);
164 5
		$captures  = self::getNamedCaptures($attrValue, $regexp, $map);
165 5
		foreach ($captures as $k => $v)
166
		{
167
			// Attribute preprocessors cannot overwrite other attributes but they can
168
			// overwrite themselves
169 4
			if ($k === $attrName || !$tag->hasAttribute($k))
170
			{
171 4
				$tag->setAttribute($k, $v);
172
			}
173
		}
174 5
	}
175
176
	/**
177
	* Execute a filter
178
	*
179
	* @see s9e\TextFormatter\Configurator\Items\ProgrammableCallback
180
	*
181
	* @param  array $filter Programmed callback
182
	* @param  array $vars   Variables to be used when executing the callback
183
	* @return mixed         Whatever the callback returns
184
	*/
185 15
	protected static function executeFilter(array $filter, array $vars)
186
	{
187
		// Add vars from the registeredVars array to the list of vars
188 15
		$vars += ['registeredVars' => []];
189 15
		$vars += $vars['registeredVars'];
190
191
		// Prepare the list of arguments
192 15
		$args = [];
193 15
		if (isset($filter['params']))
194
		{
195 15
			foreach ($filter['params'] as $k => $v)
196
			{
197 15
				$args[] = (isset($vars[$k])) ? $vars[$k] : $v;
198
			}
199
		}
200
201 15
		return call_user_func_array($filter['callback'], $args);
202
	}
203
204
	/**
205
	* Execute a regexp and return the values of the mapped captures
206
	*
207
	* @param  string   $str
208
	* @param  string   $regexp
209
	* @param  string[] $map
210
	* @return array
211
	*/
212 5
	protected static function getNamedCaptures($str, $regexp, $map)
213
	{
214 5
		if (!preg_match($regexp, $str, $m))
215
		{
216 1
			return [];
217
		}
218
219 4
		$values = [];
220 4
		foreach ($map as $i => $k)
221
		{
222 4
			if (isset($m[$i]) && $m[$i] !== '')
223
			{
224 4
				$values[$k] = $m[$i];
225
			}
226
		}
227
228 4
		return $values;
229
	}
230
}