Compiler   A
last analyzed

Complexity

Total Complexity 14

Size/Duplication

Total Lines 156
Duplicated Lines 0 %

Coupling/Cohesion

Components 0
Dependencies 3

Importance

Changes 4
Bugs 0 Features 0
Metric Value
c 4
b 0
f 0
dl 0
loc 156
rs 10
wmc 14
lcom 0
cbo 3

4 Methods

Rating   Name   Duplication   Size   Complexity  
A __invoke() 0 15 1
B parse_html_tree() 0 57 7
A parse_html_node() 0 19 3
B parse_expression() 0 37 3
1
<?php
2
3
/*
4
 * This file is part of the Patron package.
5
 *
6
 * (c) Olivier Laviale <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Patron;
13
14
class Compiler
15
{
16
	/**
17
	 * @param string $template
18
	 *
19
	 * @return array
20
	 */
21
	public function __invoke($template)
22
	{
23
		$parser = new HTMLParser([
24
25
			HTMLParser::T_ERROR_HANDLER => function($message, array $args) {
26
27
				throw new \Exception(\ICanBoogie\format($message, $args));
28
			}
29
30
		]);
31
32
		$tree = $parser->parse($template, Engine::PREFIX);
33
34
		return $this->parse_html_tree($tree);
35
	}
36
37
	/**
38
	 * @param array $tree
39
	 *
40
	 * @return array
41
	 */
42
	protected function parse_html_tree(array $tree)
43
	{
44
		$nodes = [];
45
46
		foreach ($tree as $node)
47
		{
48
			if (is_array($node))
49
			{
50
				$children = [];
51
52
				if (isset($node['children']))
53
				{
54
					$children = $this->parse_html_tree($node['children']);
55
				}
56
57
				$nodes[] = new ControlNode($node['name'], $node['args'], $children);
58
			}
59
			else
60
			{
61
				#
62
				# we don't resolve comments, unless they are Internet Explorer comments e.g. <!--[
63
				#
64
65
				$parts = preg_split('#(<!--(?!\[).+-->)#sU', $node, -1, PREG_SPLIT_DELIM_CAPTURE);
66
67
				if (count($parts) == 1)
68
				{
69
					$children = $this->parse_html_node($node);
70
71
					$nodes = array_merge($nodes, $children);
72
				}
73
				else
74
				{
75
					#
76
					# The comments, which are on odd position, are kept intact. The text, which is
77
					# on even position is resolved.
78
					#
79
80
					foreach ($parts as $i => $part)
81
					{
82
						if ($i % 2)
83
						{
84
							$nodes[] = new TextNode($part);
85
						}
86
						else
87
						{
88
							$children = $this->parse_html_node($part);
89
90
							$nodes = array_merge($nodes, $children);
91
						}
92
					}
93
				}
94
			}
95
		}
96
97
		return $nodes;
98
	}
99
100
	/**
101
	 * @param string $node
102
	 *
103
	 * @return array
104
	 * @throws \Exception
105
	 */
106
	protected function parse_html_node($node)
107
	{
108
		$nodes = [];
109
		$parts = preg_split(ExpressionNode::REGEX, $node, -1, PREG_SPLIT_DELIM_CAPTURE);
110
111
		foreach ($parts as $i => $part)
112
		{
113
			if ($i % 2)
114
			{
115
				$nodes[] = $this->parse_expression($part);
116
			}
117
			else
118
			{
119
				$nodes[] = new TextNode($part);
120
			}
121
		}
122
123
		return $nodes;
124
	}
125
126
	/**
127
	 * @param string $source
128
	 *
129
	 * @return object
130
	 * @throws \Exception
131
	 */
132
	protected function parse_expression($source)
133
	{
134
		$escape = true;
135
136
		if ($source{strlen($source) - 1} == '=')
137
		{
138
			$escape = false;
139
			$source = substr($source, 0, -1);
140
		}
141
142
		preg_match('/^(([a-z]+):)?(.+)$/', $source, $matches);
143
144
		$type = $matches[2];
145
		$expression = $matches[3];
146
147
		$types = [
148
149
			'' => 'Patron\EvaluateNode',
150
			't' => 'Patron\TranslateNode',
151
			'url' => 'Patron\URLNode'
152
153
		];
154
155
		if (!isset($types[$type]))
156
		{
157
			throw new \Exception(\ICanBoogie\format("Unknown expression type %type for expression %expression", [
158
159
				'type' => $type,
160
				'expression' => $expression
161
162
			]));
163
		}
164
165
		$class = $types[$type];
166
167
		return new $class($expression, $escape);
168
	}
169
}
170