1 <?php
2
3 4 5 6 7 8 9 10
11
12 namespace Patron;
13
14 class ControlNode extends Node
15 {
16 public $name;
17 public $args;
18 public $nodes;
19
20 public function __construct($name, array $args, $nodes)
21 {
22 $this->name = $name;
23
24 foreach ($nodes as $i => $node)
25 {
26 if (!($node instanceof self) || $node->name != 'with-param')
27 {
28 continue;
29 }
30
31 $args[$node->args['name']] = $node;
32
33 unset($nodes[$i]);
34 }
35
36 $this->args = $args;
37 $this->nodes = $nodes;
38 }
39
40 public function __invoke(Engine $engine, $context)
41 {
42 $name = $this->name;
43
44 try
45 {
46 $hook = Hook::find('patron.markups', $name);
47 }
48 catch (\Exception $e)
49 {
50 $engine->error('Unknown markup %name', array('%name' => $name));
51
52 return;
53 }
54
55 $args = $this->args;
56
57 $missing = array();
58 $binding = empty($hook->tags['no-binding']);
59
60 foreach ($hook->params as $param => $options)
61 {
62 if (is_array($options))
63 {
64
65
66
67
68 if (isset($options['default']) && !array_key_exists($param, $args))
69 {
70 $args[$param] = $options['default'];
71 }
72
73 if (array_key_exists($param, $args))
74 {
75 $value = $args[$param];
76
77 if (isset($options['expression']))
78 {
79 $silent = !empty($options['expression']['silent']);
80
81
82
83 if ($value{0} == ':')
84 {
85 $args[$param] = substr($value, 1);
86 }
87 else
88 {
89 $args[$param] = $engine->evaluate($value, $silent);
90 }
91 }
92 }
93 else if (isset($options['required']))
94 {
95 $missing[$param] = true;
96 }
97 }
98 else
99 {
100
101
102 if (!array_key_exists($param, $args))
103 {
104 $args[$param] = $options;
105 }
106 }
107
108 if (!isset($args[$param]))
109 {
110 $args[$param] = null;
111 }
112 }
113
114 if ($missing)
115 {
116 throw new \ICanBoogie\Exception
117 (
118 'The %param parameter is required for the %markup markup, given %args', array
119 (
120 '%param' => implode(', ', array_keys($missing)),
121 '%markup' => $name,
122 '%args' => json_encode($args)
123 )
124 );
125 }
126
127
128
129
130
131 foreach ($args as &$arg)
132 {
133 if ($arg instanceof ControlNode)
134 {
135 if (isset($arg->args['select']))
136 {
137 $arg = $engine->evaluate($arg->args['select']);
138 }
139 else
140 {
141 $arg = $engine($arg->nodes);
142 }
143 }
144 }
145
146 unset($arg);
147
148
149
150
151
152 $engine->trace_enter(array('markup', $name));
153
154 if ($binding)
155 {
156 array_push($engine->context_markup, array($engine->context['self'], $engine->context['this']));
157
158 $engine->context['self'] = array
159 (
160 'name' => $name,
161 'arguments' => $args
162 );
163 }
164
165 $rc = null;
166
167 try
168 {
169 $rc = $hook($args, $engine, $this->nodes);
170 }
171 catch (\Exception $e)
172 {
173 $engine->handle_exception($e);
174 }
175
176 if ($binding)
177 {
178 $a = array_pop($engine->context_markup);
179
180 $engine->context['self'] = $a[0];
181 $engine->context['this'] = $a[1];
182 }
183
184 $engine->trace_exit();
185
186 return $rc;
187 }
188 }
189