danielebarchiesi@4
|
1 <?php
|
danielebarchiesi@4
|
2 /**
|
danielebarchiesi@4
|
3 * ARC2 SPARQLScript Processor
|
danielebarchiesi@4
|
4 *
|
danielebarchiesi@4
|
5 * @author Benjamin Nowack <bnowack@semsol.com>
|
danielebarchiesi@4
|
6 * @license http://arc.semsol.org/license
|
danielebarchiesi@4
|
7 * @package ARC2
|
danielebarchiesi@4
|
8 * @version 2010-11-16
|
danielebarchiesi@4
|
9 */
|
danielebarchiesi@4
|
10
|
danielebarchiesi@4
|
11 ARC2::inc('Class');
|
danielebarchiesi@4
|
12
|
danielebarchiesi@4
|
13 class ARC2_SPARQLScriptProcessor extends ARC2_Class {
|
danielebarchiesi@4
|
14
|
danielebarchiesi@4
|
15 function __construct($a, &$caller) {
|
danielebarchiesi@4
|
16 parent::__construct($a, $caller);
|
danielebarchiesi@4
|
17 }
|
danielebarchiesi@4
|
18
|
danielebarchiesi@4
|
19 function __init() {
|
danielebarchiesi@4
|
20 parent::__init();
|
danielebarchiesi@4
|
21 $this->max_operations = $this->v('sparqlscript_max_operations', 0, $this->a);
|
danielebarchiesi@4
|
22 $this->max_queries = $this->v('sparqlscript_max_queries', 0, $this->a);
|
danielebarchiesi@4
|
23 $this->return = 0;
|
danielebarchiesi@4
|
24 $this->script_hash = '';
|
danielebarchiesi@4
|
25 $this->env = array(
|
danielebarchiesi@4
|
26 'endpoint' => '',
|
danielebarchiesi@4
|
27 'vars' => array(),
|
danielebarchiesi@4
|
28 'output' => '',
|
danielebarchiesi@4
|
29 'operation_count' => 0,
|
danielebarchiesi@4
|
30 'query_count' => 0,
|
danielebarchiesi@4
|
31 'query_log' => array()
|
danielebarchiesi@4
|
32 );
|
danielebarchiesi@4
|
33 }
|
danielebarchiesi@4
|
34
|
danielebarchiesi@4
|
35 function reset() {
|
danielebarchiesi@4
|
36 $this->__init();
|
danielebarchiesi@4
|
37 }
|
danielebarchiesi@4
|
38
|
danielebarchiesi@4
|
39 /* */
|
danielebarchiesi@4
|
40
|
danielebarchiesi@4
|
41 function processScript($s) {
|
danielebarchiesi@4
|
42 $this->script_hash = abs(crc32($s));
|
danielebarchiesi@4
|
43 $parser = $this->getParser();
|
danielebarchiesi@4
|
44 $parser->parse($s);
|
danielebarchiesi@4
|
45 $blocks = $parser->getScriptBlocks();
|
danielebarchiesi@4
|
46 if ($parser->getErrors()) return 0;
|
danielebarchiesi@4
|
47 foreach ($blocks as $block) {
|
danielebarchiesi@4
|
48 $this->processBlock($block);
|
danielebarchiesi@4
|
49 if ($this->return) return 0;
|
danielebarchiesi@4
|
50 if ($this->getErrors()) return 0;
|
danielebarchiesi@4
|
51 }
|
danielebarchiesi@4
|
52 }
|
danielebarchiesi@4
|
53
|
danielebarchiesi@4
|
54 function getResult() {
|
danielebarchiesi@4
|
55 if ($this->return) {
|
danielebarchiesi@4
|
56 return $this->getVarValue('__return_value__');
|
danielebarchiesi@4
|
57 }
|
danielebarchiesi@4
|
58 else {
|
danielebarchiesi@4
|
59 return $this->env['output'];
|
danielebarchiesi@4
|
60 }
|
danielebarchiesi@4
|
61 }
|
danielebarchiesi@4
|
62
|
danielebarchiesi@4
|
63 /* */
|
danielebarchiesi@4
|
64
|
danielebarchiesi@4
|
65 function getParser() {
|
danielebarchiesi@4
|
66 ARC2::inc('SPARQLScriptParser');
|
danielebarchiesi@4
|
67 return new ARC2_SPARQLScriptParser($this->a, $this);
|
danielebarchiesi@4
|
68 }
|
danielebarchiesi@4
|
69
|
danielebarchiesi@4
|
70 /* */
|
danielebarchiesi@4
|
71
|
danielebarchiesi@4
|
72 function setVar($name, $val, $type = 'literal', $meta = '') {
|
danielebarchiesi@4
|
73 /* types: literal, var, rows, bool, doc, http_response, undefined, ? */
|
danielebarchiesi@4
|
74 $this->env['vars'][$name] = array(
|
danielebarchiesi@4
|
75 'value_type' => $type,
|
danielebarchiesi@4
|
76 'value' => $val,
|
danielebarchiesi@4
|
77 'meta' => $meta ? $meta : array()
|
danielebarchiesi@4
|
78 );
|
danielebarchiesi@4
|
79 }
|
danielebarchiesi@4
|
80
|
danielebarchiesi@4
|
81 function getVar($name) {
|
danielebarchiesi@4
|
82 return isset($this->env['vars'][$name]) ? $this->env['vars'][$name] : '';
|
danielebarchiesi@4
|
83 }
|
danielebarchiesi@4
|
84
|
danielebarchiesi@4
|
85 function getVarValue($name) {
|
danielebarchiesi@4
|
86 return ($v = $this->getVar($name)) ? (isset($v['value']) ? $v['value'] : $v ) : '';
|
danielebarchiesi@4
|
87 }
|
danielebarchiesi@4
|
88
|
danielebarchiesi@4
|
89 /* */
|
danielebarchiesi@4
|
90
|
danielebarchiesi@4
|
91 function replacePlaceholders($val, $context = '', $return_string = 1, $loop = 0) {
|
danielebarchiesi@4
|
92 do {
|
danielebarchiesi@4
|
93 $old_val = $val;
|
danielebarchiesi@4
|
94 if (preg_match_all('/(\{(?:[^{}]+|(?R))*\})/', $val, $m)) {
|
danielebarchiesi@4
|
95 foreach ($m[1] as $match) {
|
danielebarchiesi@4
|
96 if (strpos($val, '$' . $match) === false) {/* just some container brackets, recurse */
|
danielebarchiesi@4
|
97 $val = str_replace($match, '{' . $this->replacePlaceholders(substr($match, 1, -1), $context, $return_string, $loop + 1) . '}', $val);
|
danielebarchiesi@4
|
98 }
|
danielebarchiesi@4
|
99 else {
|
danielebarchiesi@4
|
100 $ph = substr($match, 1, -1);
|
danielebarchiesi@4
|
101 $sub_val = $this->getPlaceholderValue($ph);
|
danielebarchiesi@4
|
102 if (is_array($sub_val)) {
|
danielebarchiesi@4
|
103 $sub_val = $this->getArraySerialization($sub_val, $context);
|
danielebarchiesi@4
|
104 }
|
danielebarchiesi@4
|
105 $val = str_replace('${' . $ph . '}', $sub_val, $val);
|
danielebarchiesi@4
|
106 }
|
danielebarchiesi@4
|
107 }
|
danielebarchiesi@4
|
108 }
|
danielebarchiesi@4
|
109 } while (($old_val != $val) && ($loop < 10));
|
danielebarchiesi@4
|
110 return $val;
|
danielebarchiesi@4
|
111 }
|
danielebarchiesi@4
|
112
|
danielebarchiesi@4
|
113 function getPlaceholderValue($ph) {
|
danielebarchiesi@4
|
114 /* simple vars */
|
danielebarchiesi@4
|
115 if (isset($this->env['vars'][$ph])) {
|
danielebarchiesi@4
|
116 return $this->v('value', $this->env['vars'][$ph], $this->env['vars'][$ph]);
|
danielebarchiesi@4
|
117 }
|
danielebarchiesi@4
|
118 /* GET/POST */
|
danielebarchiesi@4
|
119 if (preg_match('/^(GET|POST)\.([^\.]+)(.*)$/', $ph, $m)) {
|
danielebarchiesi@4
|
120 $vals = strtoupper($m[1]) == 'GET' ? $_GET : $POST;
|
danielebarchiesi@4
|
121 $r = isset($vals[$m[2]]) ? $vals[$m[2]] : '';
|
danielebarchiesi@4
|
122 return $m[3] ? $this->getPropertyValue(array('value' => $r, 'value_type' => '?'), ltrim($m[3], '.')) : $r;
|
danielebarchiesi@4
|
123 }
|
danielebarchiesi@4
|
124 /* NOW */
|
danielebarchiesi@4
|
125 if (preg_match('/^NOW(.*)$/', $ph, $m)) {
|
danielebarchiesi@4
|
126 $rest = $m[1];
|
danielebarchiesi@4
|
127 /* may have sub-phs */
|
danielebarchiesi@4
|
128 $rest = $this->replacePlaceholders($rest);
|
danielebarchiesi@4
|
129 $r_struct = array(
|
danielebarchiesi@4
|
130 'y' => date('Y'),
|
danielebarchiesi@4
|
131 'mo' => date('m'),
|
danielebarchiesi@4
|
132 'd' => date('d'),
|
danielebarchiesi@4
|
133 'h' => date('H'),
|
danielebarchiesi@4
|
134 'mi' => date('i'),
|
danielebarchiesi@4
|
135 's' => date('s')
|
danielebarchiesi@4
|
136 );
|
danielebarchiesi@4
|
137 if (preg_match('/(\+|\-)\s*([0-9]+)(y|mo|d|h|mi|s)[a-z]*(.*)/is', trim($rest), $m2)) {
|
danielebarchiesi@4
|
138 eval('$r_struct[$m2[3]] ' . $m2[1] . '= (int)' . $m2[2] . ';');
|
danielebarchiesi@4
|
139 $rest = $m2[4];
|
danielebarchiesi@4
|
140 }
|
danielebarchiesi@4
|
141 $uts = mktime($r_struct['h'], $r_struct['mi'], $r_struct['s'], $r_struct['mo'], $r_struct['d'], $r_struct['y']);
|
danielebarchiesi@4
|
142 $uts -= date('Z', $uts); /* timezone offset */
|
danielebarchiesi@4
|
143 $r = date('Y-m-d\TH:i:s\Z', $uts);
|
danielebarchiesi@4
|
144 if (preg_match('/^\.(.+)$/', $rest, $m)) {
|
danielebarchiesi@4
|
145 return $this->getPropertyValue(array('value' => $r), $m[1]);
|
danielebarchiesi@4
|
146 }
|
danielebarchiesi@4
|
147 return $r;
|
danielebarchiesi@4
|
148 }
|
danielebarchiesi@4
|
149 /* property */
|
danielebarchiesi@4
|
150 if (preg_match('/^([^\.]+)\.(.+)$/', $ph, $m)) {
|
danielebarchiesi@4
|
151 list($var, $path) = array($m[1], $m[2]);
|
danielebarchiesi@4
|
152 if (isset($this->env['vars'][$var])) {
|
danielebarchiesi@4
|
153 return $this->getPropertyValue($this->env['vars'][$var], $path);
|
danielebarchiesi@4
|
154 }
|
danielebarchiesi@4
|
155 }
|
danielebarchiesi@4
|
156 return '';
|
danielebarchiesi@4
|
157 }
|
danielebarchiesi@4
|
158
|
danielebarchiesi@4
|
159 function getPropertyValue($obj, $path) {
|
danielebarchiesi@4
|
160 $val = isset($obj['value']) ? $obj['value'] : $obj;
|
danielebarchiesi@4
|
161 $path = $this->replacePlaceholders($path, 'property_value', 0);
|
danielebarchiesi@4
|
162 /* reserved */
|
danielebarchiesi@4
|
163 if ($path == 'size') {
|
danielebarchiesi@4
|
164 if ($obj['value_type'] == 'rows') return count($val);
|
danielebarchiesi@4
|
165 if ($obj['value_type'] == 'literal') return strlen($val);
|
danielebarchiesi@4
|
166 }
|
danielebarchiesi@4
|
167 if (preg_match('/^replace\([\'\"](\/.*\/[a-z]*)[\'\"],\s*[\'\"](.*)[\'\"]\)$/is', $path, $m)) {
|
danielebarchiesi@4
|
168 return @preg_replace($m[1], str_replace('$', '\\', $m[2]), $val);
|
danielebarchiesi@4
|
169 }
|
danielebarchiesi@4
|
170 if (preg_match('/^match\([\'\"](\/.*\/[a-z]*)[\'\"]\)$/is', $path, $m)) {
|
danielebarchiesi@4
|
171 return @preg_match($m[1], $val, $m) ? $m : '';
|
danielebarchiesi@4
|
172 }
|
danielebarchiesi@4
|
173 if (preg_match('/^urlencode\([\'\"]?(get|post|.*)[\'\"]?\)$/is', $path, $m)) {
|
danielebarchiesi@4
|
174 return (strtolower($m[1]) == 'post') ? rawurlencode($val) : urlencode($val);
|
danielebarchiesi@4
|
175 }
|
danielebarchiesi@4
|
176 if (preg_match('/^toDataURI\([^\)]*\)$/is', $path, $m)) {
|
danielebarchiesi@4
|
177 return 'data:text/plain;charset=utf-8,' . rawurlencode($val);
|
danielebarchiesi@4
|
178 }
|
danielebarchiesi@4
|
179 if (preg_match('/^fromDataURI\([^\)]*\)$/is', $path, $m)) {
|
danielebarchiesi@4
|
180 return rawurldecode(str_replace('data:text/plain;charset=utf-8,', '', $val));
|
danielebarchiesi@4
|
181 }
|
danielebarchiesi@4
|
182 if (preg_match('/^toPrettyDate\([^\)]*\)$/is', $path, $m)) {
|
danielebarchiesi@4
|
183 $uts = strtotime(preg_replace('/(T|\+00\:00)/', ' ', $val));
|
danielebarchiesi@4
|
184 return date('D j M H:i', $uts);
|
danielebarchiesi@4
|
185 }
|
danielebarchiesi@4
|
186 if (preg_match('/^render\(([^\)]*)\)$/is', $path, $m)) {
|
danielebarchiesi@4
|
187 $src_format = trim($m[1], '"\'');
|
danielebarchiesi@4
|
188 return $this->render($val, $src_format);
|
danielebarchiesi@4
|
189 }
|
danielebarchiesi@4
|
190 /* struct */
|
danielebarchiesi@4
|
191 if (is_array($val)) {
|
danielebarchiesi@4
|
192 if (isset($val[$path])) return $val[$path];
|
danielebarchiesi@4
|
193 $exp_path = $this->expandPName($path);
|
danielebarchiesi@4
|
194 if (isset($val[$exp_path])) return $val[$exp_path];
|
danielebarchiesi@4
|
195 if (preg_match('/^([^\.]+)\.(.+)$/', $path, $m)) {
|
danielebarchiesi@4
|
196 list($var, $path) = array($m[1], $m[2]);
|
danielebarchiesi@4
|
197 if (isset($val[$var])) {
|
danielebarchiesi@4
|
198 return $this->getPropertyValue(array('value' => $val[$var]), $path);
|
danielebarchiesi@4
|
199 }
|
danielebarchiesi@4
|
200 /* qname */
|
danielebarchiesi@4
|
201 $exp_var = $this->expandPName($var);
|
danielebarchiesi@4
|
202 if (isset($val[$exp_var])) {
|
danielebarchiesi@4
|
203 return $this->getPropertyValue(array('value' => $val[$exp_var]), $path);
|
danielebarchiesi@4
|
204 }
|
danielebarchiesi@4
|
205 return '';
|
danielebarchiesi@4
|
206 }
|
danielebarchiesi@4
|
207 }
|
danielebarchiesi@4
|
208 /* meta */
|
danielebarchiesi@4
|
209 if (preg_match('/^\_/', $path) && isset($obj['meta']) && isset($obj['meta'][substr($path, 1)])) {
|
danielebarchiesi@4
|
210 return $obj['meta'][substr($path, 1)];
|
danielebarchiesi@4
|
211 }
|
danielebarchiesi@4
|
212 return '';
|
danielebarchiesi@4
|
213 }
|
danielebarchiesi@4
|
214
|
danielebarchiesi@4
|
215 function render($val, $src_format = '') {
|
danielebarchiesi@4
|
216 if ($src_format) {
|
danielebarchiesi@4
|
217 $mthd = 'render' . $this->camelCase($src_format);
|
danielebarchiesi@4
|
218 if (method_exists($this, $mthd)) {
|
danielebarchiesi@4
|
219 return $this->$mthd($val);
|
danielebarchiesi@4
|
220 }
|
danielebarchiesi@4
|
221 else {
|
danielebarchiesi@4
|
222 return 'No rendering method found for "' . $src_format. '"';
|
danielebarchiesi@4
|
223 }
|
danielebarchiesi@4
|
224 }
|
danielebarchiesi@4
|
225 /* try RDF */
|
danielebarchiesi@4
|
226 return $this->getArraySerialization($val);
|
danielebarchiesi@4
|
227 }
|
danielebarchiesi@4
|
228
|
danielebarchiesi@4
|
229 function renderObjects($os) {
|
danielebarchiesi@4
|
230 $r = '';
|
danielebarchiesi@4
|
231 foreach ($os as $o) {
|
danielebarchiesi@4
|
232 $r .= $r ? ', ' : '';
|
danielebarchiesi@4
|
233 $r .= $o['value'];
|
danielebarchiesi@4
|
234 }
|
danielebarchiesi@4
|
235 return $r;
|
danielebarchiesi@4
|
236 }
|
danielebarchiesi@4
|
237
|
danielebarchiesi@4
|
238 /* */
|
danielebarchiesi@4
|
239
|
danielebarchiesi@4
|
240 function getArraySerialization($v, $context) {
|
danielebarchiesi@4
|
241 $v_type = ARC2::getStructType($v);/* string|array|triples|index */
|
danielebarchiesi@4
|
242 $pf = ARC2::getPreferredFormat();
|
danielebarchiesi@4
|
243 /* string */
|
danielebarchiesi@4
|
244 if ($v_type == 'string') return $v;
|
danielebarchiesi@4
|
245 /* simple array (e.g. from SELECT) */
|
danielebarchiesi@4
|
246 if ($v_type == 'array') {
|
danielebarchiesi@4
|
247 return join(', ', $v);
|
danielebarchiesi@4
|
248 $m = method_exists($this, 'toLegacy' . $pf) ? 'toLegacy' . $pf : 'toLegacyXML';
|
danielebarchiesi@4
|
249 }
|
danielebarchiesi@4
|
250 /* rdf */
|
danielebarchiesi@4
|
251 if (($v_type == 'triples') || ($v_type == 'index')) {
|
danielebarchiesi@4
|
252 $m = method_exists($this, 'to' . $pf) ? 'to' . $pf : ($context == 'query' ? 'toNTriples' : 'toRDFXML');
|
danielebarchiesi@4
|
253 }
|
danielebarchiesi@4
|
254 /* else */
|
danielebarchiesi@4
|
255 return $this->$m($v);
|
danielebarchiesi@4
|
256 }
|
danielebarchiesi@4
|
257
|
danielebarchiesi@4
|
258 /* */
|
danielebarchiesi@4
|
259
|
danielebarchiesi@4
|
260 function processBlock($block) {
|
danielebarchiesi@4
|
261 if ($this->max_operations && ($this->env['operation_count'] >= $this->max_operations)) return $this->addError('Number of ' . $this->max_operations . ' allowed operations exceeded.');
|
danielebarchiesi@4
|
262 if ($this->return) return 0;
|
danielebarchiesi@4
|
263 $this->env['operation_count']++;
|
danielebarchiesi@4
|
264 $type = $block['type'];
|
danielebarchiesi@4
|
265 $m = 'process' . $this->camelCase($type) . 'Block';
|
danielebarchiesi@4
|
266 if (method_exists($this, $m)) {
|
danielebarchiesi@4
|
267 return $this->$m($block);
|
danielebarchiesi@4
|
268 }
|
danielebarchiesi@4
|
269 return $this->addError('Unsupported block type "' . $type . '"');
|
danielebarchiesi@4
|
270 }
|
danielebarchiesi@4
|
271
|
danielebarchiesi@4
|
272 /* */
|
danielebarchiesi@4
|
273
|
danielebarchiesi@4
|
274 function processEndpointDeclBlock($block) {
|
danielebarchiesi@4
|
275 $this->env['endpoint'] = $block['endpoint'];
|
danielebarchiesi@4
|
276 return $this->env;
|
danielebarchiesi@4
|
277 }
|
danielebarchiesi@4
|
278
|
danielebarchiesi@4
|
279 /* */
|
danielebarchiesi@4
|
280
|
danielebarchiesi@4
|
281 function processQueryBlock($block) {
|
danielebarchiesi@4
|
282 if ($this->max_queries && ($this->env['query_count'] >= $this->max_queries)) return $this->addError('Number of ' . $this->max_queries . ' allowed queries exceeded.');
|
danielebarchiesi@4
|
283 $this->env['query_count']++;
|
danielebarchiesi@4
|
284 $ep_uri = $this->replacePlaceholders($this->env['endpoint'], 'endpoint');
|
danielebarchiesi@4
|
285 /* q */
|
danielebarchiesi@4
|
286 $prologue = 'BASE <' . $block['base']. '>';
|
danielebarchiesi@4
|
287 $q = $this->replacePlaceholders($block['query'], 'query');
|
danielebarchiesi@4
|
288 /* prefixes */
|
danielebarchiesi@4
|
289 $ns = isset($this->a['ns']) ? array_merge($this->a['ns'], $block['prefixes']) : $block['prefixes'];
|
danielebarchiesi@4
|
290 $q = $prologue . "\n" . $this->completeQuery($q, $ns);
|
danielebarchiesi@4
|
291 $this->env['query_log'][] = '(' . $ep_uri . ') ' . $q;
|
danielebarchiesi@4
|
292 if ($store = $this->getStore($ep_uri)) {
|
danielebarchiesi@4
|
293 $sub_r = $this->v('is_remote', '', $store) ? $store->query($q, '', $ep_uri) : $store->query($q);
|
danielebarchiesi@4
|
294 /* ignore socket errors */
|
danielebarchiesi@4
|
295 if (($errs = $this->getErrors()) && preg_match('/socket/', $errs[0])) {
|
danielebarchiesi@4
|
296 $this->warnings[] = $errs[0];
|
danielebarchiesi@4
|
297 $this->errors = array();
|
danielebarchiesi@4
|
298 $sub_r = array();
|
danielebarchiesi@4
|
299 }
|
danielebarchiesi@4
|
300 return $sub_r;
|
danielebarchiesi@4
|
301 }
|
danielebarchiesi@4
|
302 else {
|
danielebarchiesi@4
|
303 return $this->addError("no store (" . $ep_uri . ")");
|
danielebarchiesi@4
|
304 }
|
danielebarchiesi@4
|
305 }
|
danielebarchiesi@4
|
306
|
danielebarchiesi@4
|
307 function getStore($ep_uri) {
|
danielebarchiesi@4
|
308 /* local store */
|
danielebarchiesi@4
|
309 if ((!$ep_uri || $ep_uri == ARC2::getScriptURI()) && ($this->v('sparqlscript_default_endpoint', '', $this->a) == 'local')) {
|
danielebarchiesi@4
|
310 if (!isset($this->local_store)) $this->local_store = ARC2::getStore($this->a);/* @@todo error checking */
|
danielebarchiesi@4
|
311 return $this->local_store;
|
danielebarchiesi@4
|
312 }
|
danielebarchiesi@4
|
313 elseif ($ep_uri) {
|
danielebarchiesi@4
|
314 ARC2::inc('RemoteStore');
|
danielebarchiesi@4
|
315 $conf = array_merge($this->a, array('remote_store_endpoint' => $ep_uri, 'reader_timeout' => 10));
|
danielebarchiesi@4
|
316 return new ARC2_RemoteStore($conf, $this);
|
danielebarchiesi@4
|
317 }
|
danielebarchiesi@4
|
318 return 0;
|
danielebarchiesi@4
|
319 }
|
danielebarchiesi@4
|
320
|
danielebarchiesi@4
|
321 /* */
|
danielebarchiesi@4
|
322
|
danielebarchiesi@4
|
323 function processAssignmentBlock($block) {
|
danielebarchiesi@4
|
324 $sub_type = $block['sub_type'];
|
danielebarchiesi@4
|
325 $m = 'process' . $this->camelCase($sub_type) . 'AssignmentBlock';
|
danielebarchiesi@4
|
326 if (!method_exists($this, $m)) return $this->addError('Unknown method "' . $m . '"');
|
danielebarchiesi@4
|
327 return $this->$m($block);
|
danielebarchiesi@4
|
328 }
|
danielebarchiesi@4
|
329
|
danielebarchiesi@4
|
330 function processQueryAssignmentBlock($block) {
|
danielebarchiesi@4
|
331 $qr = $this->processQueryBlock($block['query']);
|
danielebarchiesi@4
|
332 if ($this->getErrors() || !isset($qr['query_type'])) return 0;
|
danielebarchiesi@4
|
333 $qt = $qr['query_type'];
|
danielebarchiesi@4
|
334 $vts = array('ask' => 'bool', 'select' => 'rows', 'desribe' => 'doc', 'construct' => 'doc');
|
danielebarchiesi@4
|
335 $r = array(
|
danielebarchiesi@4
|
336 'value_type' => isset($vts[$qt]) ? $vts[$qt] : $qt . ' result',
|
danielebarchiesi@4
|
337 'value' => ($qt == 'select') ? $this->v('rows', array(), $qr['result']) : $qr['result'],
|
danielebarchiesi@4
|
338 );
|
danielebarchiesi@4
|
339 $this->env['vars'][$block['var']['value']] = $r;
|
danielebarchiesi@4
|
340 }
|
danielebarchiesi@4
|
341
|
danielebarchiesi@4
|
342 function processStringAssignmentBlock($block) {
|
danielebarchiesi@4
|
343 $r = array('value_type' => 'literal', 'value' => $this->replacePlaceholders($block['string']['value']));
|
danielebarchiesi@4
|
344 $this->env['vars'][$block['var']['value']] = $r;
|
danielebarchiesi@4
|
345 }
|
danielebarchiesi@4
|
346
|
danielebarchiesi@4
|
347 function processVarAssignmentBlock($block) {
|
danielebarchiesi@4
|
348 if (isset($this->env['vars'][$block['var2']['value']])) {
|
danielebarchiesi@4
|
349 $this->env['vars'][$block['var']['value']] = $this->env['vars'][$block['var2']['value']];
|
danielebarchiesi@4
|
350 }
|
danielebarchiesi@4
|
351 else {
|
danielebarchiesi@4
|
352 $this->env['vars'][$block['var']['value']] = array('value_type' => 'undefined', 'value' => '');
|
danielebarchiesi@4
|
353 }
|
danielebarchiesi@4
|
354 }
|
danielebarchiesi@4
|
355
|
danielebarchiesi@4
|
356 function processPlaceholderAssignmentBlock($block) {
|
danielebarchiesi@4
|
357 $ph_val = $this->getPlaceholderValue($block['placeholder']['value']);
|
danielebarchiesi@4
|
358 $this->env['vars'][$block['var']['value']] = array('value_type' => 'undefined', 'value' => $ph_val);
|
danielebarchiesi@4
|
359 }
|
danielebarchiesi@4
|
360
|
danielebarchiesi@4
|
361 function processVarMergeAssignmentBlock($block) {
|
danielebarchiesi@4
|
362 $val1 = isset($this->env['vars'][$block['var2']['value']]) ? $this->env['vars'][$block['var2']['value']] : array('value_type' => 'undefined', 'value' => '');
|
danielebarchiesi@4
|
363 $val2 = isset($this->env['vars'][$block['var3']['value']]) ? $this->env['vars'][$block['var3']['value']] : array('value_type' => 'undefined', 'value' => '');
|
danielebarchiesi@4
|
364 if (is_array($val1) && is_array($val2)) {
|
danielebarchiesi@4
|
365 $this->env['vars'][$block['var']['value']] = array('value_type' => $val2['value_type'], 'value' => array_merge($val1['value'], $val2['value']));
|
danielebarchiesi@4
|
366 }
|
danielebarchiesi@4
|
367 elseif (is_numeric($val1) && is_numeric($val2)) {
|
danielebarchiesi@4
|
368 $this->env['vars'][$block['var']['value']] = $val1 + $val2;
|
danielebarchiesi@4
|
369 }
|
danielebarchiesi@4
|
370 }
|
danielebarchiesi@4
|
371
|
danielebarchiesi@4
|
372 function processFunctionCallAssignmentBlock($block) {
|
danielebarchiesi@4
|
373 $sub_r = $this->processFunctionCallBlock($block['function_call']);
|
danielebarchiesi@4
|
374 if ($this->getErrors()) return 0;
|
danielebarchiesi@4
|
375 $this->env['vars'][$block['var']['value']] = $sub_r;
|
danielebarchiesi@4
|
376 }
|
danielebarchiesi@4
|
377
|
danielebarchiesi@4
|
378 /* */
|
danielebarchiesi@4
|
379
|
danielebarchiesi@4
|
380 function processReturnBlock($block) {
|
danielebarchiesi@4
|
381 $sub_type = $block['sub_type'];
|
danielebarchiesi@4
|
382 $m = 'process' . $this->camelCase($sub_type) . 'AssignmentBlock';
|
danielebarchiesi@4
|
383 if (!method_exists($this, $m)) return $this->addError('Unknown method "' . $m . '"');
|
danielebarchiesi@4
|
384 $sub_r = $this->$m($block);
|
danielebarchiesi@4
|
385 $this->return = 1;
|
danielebarchiesi@4
|
386 return $sub_r;
|
danielebarchiesi@4
|
387 }
|
danielebarchiesi@4
|
388
|
danielebarchiesi@4
|
389 /* */
|
danielebarchiesi@4
|
390
|
danielebarchiesi@4
|
391 function processIfblockBlock($block) {
|
danielebarchiesi@4
|
392 if ($this->testCondition($block['condition'])) {
|
danielebarchiesi@4
|
393 $blocks = $block['blocks'];
|
danielebarchiesi@4
|
394 }
|
danielebarchiesi@4
|
395 else {
|
danielebarchiesi@4
|
396 $blocks = $block['else_blocks'];
|
danielebarchiesi@4
|
397 }
|
danielebarchiesi@4
|
398 foreach ($blocks as $block) {
|
danielebarchiesi@4
|
399 $sub_r = $this->processBlock($block);
|
danielebarchiesi@4
|
400 if ($this->getErrors()) return 0;
|
danielebarchiesi@4
|
401 }
|
danielebarchiesi@4
|
402 }
|
danielebarchiesi@4
|
403
|
danielebarchiesi@4
|
404 function testCondition($cond) {
|
danielebarchiesi@4
|
405 $m = 'test' . $this->camelCase($cond['type']) . 'Condition';
|
danielebarchiesi@4
|
406 if (!method_exists($this, $m)) return $this->addError('Unknown method "' . $m . '"');
|
danielebarchiesi@4
|
407 return $this->$m($cond);
|
danielebarchiesi@4
|
408 }
|
danielebarchiesi@4
|
409
|
danielebarchiesi@4
|
410 function testVarCondition($cond) {
|
danielebarchiesi@4
|
411 $r = 0;
|
danielebarchiesi@4
|
412 $vn = $cond['value'];
|
danielebarchiesi@4
|
413 if (isset($this->env['vars'][$vn])) $r = $this->env['vars'][$vn]['value'];
|
danielebarchiesi@4
|
414 $op = $this->v('operator', '', $cond);
|
danielebarchiesi@4
|
415 if ($op == '!') $r = !$r;
|
danielebarchiesi@4
|
416 return $r ? true : false;
|
danielebarchiesi@4
|
417 }
|
danielebarchiesi@4
|
418
|
danielebarchiesi@4
|
419 function testPlaceholderCondition($cond) {
|
danielebarchiesi@4
|
420 $val = $this->getPlaceholderValue($cond['value']);
|
danielebarchiesi@4
|
421 $r = $val ? true : false;
|
danielebarchiesi@4
|
422 $op = $this->v('operator', '', $cond);
|
danielebarchiesi@4
|
423 if ($op == '!') $r = !$r;
|
danielebarchiesi@4
|
424 return $r;
|
danielebarchiesi@4
|
425 }
|
danielebarchiesi@4
|
426
|
danielebarchiesi@4
|
427 function testExpressionCondition($cond) {
|
danielebarchiesi@4
|
428 $m = 'test' . $this->camelCase($cond['sub_type']) . 'ExpressionCondition';
|
danielebarchiesi@4
|
429 if (!method_exists($this, $m)) return $this->addError('Unknown method "' . $m . '"');
|
danielebarchiesi@4
|
430 return $this->$m($cond);
|
danielebarchiesi@4
|
431 }
|
danielebarchiesi@4
|
432
|
danielebarchiesi@4
|
433 function testRelationalExpressionCondition($cond) {
|
danielebarchiesi@4
|
434 $op = $cond['operator'];
|
danielebarchiesi@4
|
435 if ($op == '=') $op = '==';
|
danielebarchiesi@4
|
436 $val1 = $this->getPatternValue($cond['patterns'][0]);
|
danielebarchiesi@4
|
437 $val2 = $this->getPatternValue($cond['patterns'][1]);
|
danielebarchiesi@4
|
438 eval('$result = ($val1 ' . $op . ' $val2) ? 1 : 0;');
|
danielebarchiesi@4
|
439 return $result;
|
danielebarchiesi@4
|
440 }
|
danielebarchiesi@4
|
441
|
danielebarchiesi@4
|
442 function testAndExpressionCondition($cond) {
|
danielebarchiesi@4
|
443 foreach ($cond['patterns'] as $pattern) {
|
danielebarchiesi@4
|
444 if (!$this->testCondition($pattern)) return false;
|
danielebarchiesi@4
|
445 }
|
danielebarchiesi@4
|
446 return true;
|
danielebarchiesi@4
|
447 }
|
danielebarchiesi@4
|
448
|
danielebarchiesi@4
|
449 function getPatternValue($pattern) {
|
danielebarchiesi@4
|
450 $m = 'get' . $this->camelCase($pattern['type']) . 'PatternValue';
|
danielebarchiesi@4
|
451 if (!method_exists($this, $m)) return '';
|
danielebarchiesi@4
|
452 return $this->$m($pattern);
|
danielebarchiesi@4
|
453 }
|
danielebarchiesi@4
|
454
|
danielebarchiesi@4
|
455 function getLiteralPatternValue($pattern) {
|
danielebarchiesi@4
|
456 return $pattern['value'];
|
danielebarchiesi@4
|
457 }
|
danielebarchiesi@4
|
458
|
danielebarchiesi@4
|
459 function getPlaceholderPatternValue($pattern) {
|
danielebarchiesi@4
|
460 return $this->getPlaceholderValue($pattern['value']);
|
danielebarchiesi@4
|
461 }
|
danielebarchiesi@4
|
462
|
danielebarchiesi@4
|
463 /* */
|
danielebarchiesi@4
|
464
|
danielebarchiesi@4
|
465 function processForblockBlock($block) {
|
danielebarchiesi@4
|
466 $set = $this->v($block['set'], array('value' => array()), $this->env['vars']);
|
danielebarchiesi@4
|
467 $entries = isset($set['value']) ? $set['value'] : $set;
|
danielebarchiesi@4
|
468 $iterator = $block['iterator'];
|
danielebarchiesi@4
|
469 $blocks = $block['blocks'];
|
danielebarchiesi@4
|
470 if (!is_array($entries)) return 0;
|
danielebarchiesi@4
|
471 $rc = count($entries);
|
danielebarchiesi@4
|
472 foreach ($entries as $i => $entry) {
|
danielebarchiesi@4
|
473 $val_type = $this->v('value_type', 'set', $set) . ' entry';
|
danielebarchiesi@4
|
474 $this->env['vars'][$iterator] = array(
|
danielebarchiesi@4
|
475 'value' => $entry,
|
danielebarchiesi@4
|
476 'value_type' => $val_type,
|
danielebarchiesi@4
|
477 'meta' => array(
|
danielebarchiesi@4
|
478 'pos' => $i,
|
danielebarchiesi@4
|
479 'odd_even' => ($i % 2) ? 'even' : 'odd'
|
danielebarchiesi@4
|
480 )
|
danielebarchiesi@4
|
481 );
|
danielebarchiesi@4
|
482 foreach ($blocks as $block) {
|
danielebarchiesi@4
|
483 $this->processBlock($block);
|
danielebarchiesi@4
|
484 if ($this->getErrors()) return 0;
|
danielebarchiesi@4
|
485 }
|
danielebarchiesi@4
|
486 }
|
danielebarchiesi@4
|
487 }
|
danielebarchiesi@4
|
488
|
danielebarchiesi@4
|
489 /* */
|
danielebarchiesi@4
|
490
|
danielebarchiesi@4
|
491 function processLiteralBlock($block) {
|
danielebarchiesi@4
|
492 $this->env['output'] .= $this->replacePlaceholders($block['value'], 'output');
|
danielebarchiesi@4
|
493 }
|
danielebarchiesi@4
|
494
|
danielebarchiesi@4
|
495 /* */
|
danielebarchiesi@4
|
496
|
danielebarchiesi@4
|
497 function processFunctionCallBlock($block) {
|
danielebarchiesi@4
|
498 $uri = $this->replacePlaceholders($block['uri'], 'function_call');
|
danielebarchiesi@4
|
499 /* built-ins */
|
danielebarchiesi@4
|
500 if (strpos($uri, $this->a['ns']['sps']) === 0) {
|
danielebarchiesi@4
|
501 return $this->processBuiltinFunctionCallBlock($block);
|
danielebarchiesi@4
|
502 }
|
danielebarchiesi@4
|
503 /* remote functions */
|
danielebarchiesi@4
|
504 }
|
danielebarchiesi@4
|
505
|
danielebarchiesi@4
|
506 function processBuiltinFunctionCallBlock($block) {
|
danielebarchiesi@4
|
507 $fnc_uri = $this->replacePlaceholders($block['uri'], 'function_call');
|
danielebarchiesi@4
|
508 $fnc_name = substr($fnc_uri, strlen($this->a['ns']['sps']));
|
danielebarchiesi@4
|
509 if (preg_match('/^(get|post)$/i', $fnc_name, $m)) {
|
danielebarchiesi@4
|
510 return $this->processHTTPCall($block, strtoupper($m[1]));
|
danielebarchiesi@4
|
511 }
|
danielebarchiesi@4
|
512 if ($fnc_name == 'eval') {
|
danielebarchiesi@4
|
513 return $this->processEvalCall($block);
|
danielebarchiesi@4
|
514 }
|
danielebarchiesi@4
|
515 }
|
danielebarchiesi@4
|
516
|
danielebarchiesi@4
|
517 function processEvalCall($block) {
|
danielebarchiesi@4
|
518 if (!$block['args']) return 0;
|
danielebarchiesi@4
|
519 $arg = $block['args'][0];
|
danielebarchiesi@4
|
520 $script = '';
|
danielebarchiesi@4
|
521 if ($arg['type'] == 'placeholder') $script = $this->getPlaceholderValue($arg['value']);
|
danielebarchiesi@4
|
522 if ($arg['type'] == 'literal') $script = $arg['value'];
|
danielebarchiesi@4
|
523 if ($arg['type'] == 'var') $script = $this->getVarValue($arg['value']);
|
danielebarchiesi@4
|
524 //echo "\n" . $script . $arg['type'];
|
danielebarchiesi@4
|
525 $this->processScript($script);
|
danielebarchiesi@4
|
526 }
|
danielebarchiesi@4
|
527
|
danielebarchiesi@4
|
528 function processHTTPCall($block, $mthd = 'GET') {
|
danielebarchiesi@4
|
529 ARC2::inc('Reader');
|
danielebarchiesi@4
|
530 $reader = new ARC2_Reader($this->a, $this);
|
danielebarchiesi@4
|
531 $url = $this->replacePlaceholders($block['args'][0]['value'], 'function_call');
|
danielebarchiesi@4
|
532 if ($mthd != 'GET') {
|
danielebarchiesi@4
|
533 $reader->setHTTPMethod($mthd);
|
danielebarchiesi@4
|
534 $reader->setCustomHeaders("Content-Type: application/x-www-form-urlencoded");
|
danielebarchiesi@4
|
535 }
|
danielebarchiesi@4
|
536 $to = $this->v('remote_call_timeout', 0, $this->a);
|
danielebarchiesi@4
|
537 $reader->activate($url, '', 0, $to);
|
danielebarchiesi@4
|
538 $format = $reader->getFormat();
|
danielebarchiesi@4
|
539 $resp = '';
|
danielebarchiesi@4
|
540 while ($d = $reader->readStream()) {
|
danielebarchiesi@4
|
541 $resp .= $d;
|
danielebarchiesi@4
|
542 }
|
danielebarchiesi@4
|
543 $reader->closeStream();
|
danielebarchiesi@4
|
544 unset($this->reader);
|
danielebarchiesi@4
|
545 return array('value_type' => 'http_response', 'value' => $resp);
|
danielebarchiesi@4
|
546 }
|
danielebarchiesi@4
|
547
|
danielebarchiesi@4
|
548 /* */
|
danielebarchiesi@4
|
549
|
danielebarchiesi@4
|
550 function extractVars($pattern, $input = '') {
|
danielebarchiesi@4
|
551 $vars = array();
|
danielebarchiesi@4
|
552 /* replace PHs, track ()s */
|
danielebarchiesi@4
|
553 $regex = $pattern;
|
danielebarchiesi@4
|
554 $vars = array();
|
danielebarchiesi@4
|
555 if (preg_match_all('/([\?\$]\{([^\}]+)\}|\([^\)]+\))/', $regex, $m)) {
|
danielebarchiesi@4
|
556 $matches = $m[1];
|
danielebarchiesi@4
|
557 $pre_vars = $m[2];
|
danielebarchiesi@4
|
558 foreach ($matches as $i => $match) {
|
danielebarchiesi@4
|
559 $vars[] = $pre_vars[$i];
|
danielebarchiesi@4
|
560 if ($pre_vars[$i]) {/* placeholder */
|
danielebarchiesi@4
|
561 $regex = str_replace($match, '(.+)', $regex);
|
danielebarchiesi@4
|
562 }
|
danielebarchiesi@4
|
563 else {/* parentheses, but may contain placeholders */
|
danielebarchiesi@4
|
564 $sub_regex = $match;
|
danielebarchiesi@4
|
565 while (preg_match('/([\?\$]\{([^\}]+)\})/', $sub_regex, $m)) {
|
danielebarchiesi@4
|
566 $sub_regex = str_replace($m[1], '(.+)', $sub_regex);
|
danielebarchiesi@4
|
567 $vars[] = $m[2];
|
danielebarchiesi@4
|
568 }
|
danielebarchiesi@4
|
569 $regex = str_replace($match, $sub_regex, $regex);
|
danielebarchiesi@4
|
570 }
|
danielebarchiesi@4
|
571 }
|
danielebarchiesi@4
|
572 /* eval regex */
|
danielebarchiesi@4
|
573 if (@preg_match('/' . $regex . '/is', $input, $m)) {
|
danielebarchiesi@4
|
574 $vals = $m;
|
danielebarchiesi@4
|
575 }
|
danielebarchiesi@4
|
576 else {
|
danielebarchiesi@4
|
577 return 0;
|
danielebarchiesi@4
|
578 }
|
danielebarchiesi@4
|
579 for ($i = 0; $i < count($vars); $i++) {
|
danielebarchiesi@4
|
580 if ($vars[$i]) {
|
danielebarchiesi@4
|
581 $this->setVar($vars[$i], isset($vals[$i + 1]) ? $vals[$i + 1] : '');
|
danielebarchiesi@4
|
582 }
|
danielebarchiesi@4
|
583 }
|
danielebarchiesi@4
|
584 return 1;
|
danielebarchiesi@4
|
585 }
|
danielebarchiesi@4
|
586 /* no placeholders */
|
danielebarchiesi@4
|
587 return ($pattern == $input) ? 1 : 0;
|
danielebarchiesi@4
|
588 }
|
danielebarchiesi@4
|
589
|
danielebarchiesi@4
|
590 /* */
|
danielebarchiesi@4
|
591
|
danielebarchiesi@4
|
592 } |