/library/scope.php

https://github.com/DeprecatedCode/Logical-HTML-PHP · PHP · 317 lines · 243 code · 52 blank · 22 comment · 115 complexity · cb35d15672091003147a258ac3a1cf78 MD5 · raw file

  1. <?php
  2. namespace Evolution\LHTML;
  3. use Exception;
  4. class Scope {
  5. public $parent;
  6. public $data;
  7. public $source;
  8. public $souce_as = false;
  9. public $iterator = false;
  10. public $pointer = false;
  11. private $count;
  12. public $timers = array();
  13. public static $hooks = array();
  14. public static function addHook($name, &$obj) {
  15. if(substr($name, 0, 1) !== ':') throw new Exception('You must prefix your LHTML hook with a colon! Error in hook $name');
  16. self::$hooks[$name] =& $obj;
  17. }
  18. public function get_data() {
  19. $s = $this->source;
  20. if($s) return $this->parent->$s;
  21. else return $this->data;
  22. }
  23. public function __construct($parent = false) {
  24. $this->timers['scope->map'] = 0;
  25. $this->timers['scope->get'] = 0;
  26. self::$hooks[':get'] =& $_GET;
  27. self::$hooks[':post'] =& $_POST;
  28. }
  29. public function get($var_map) {
  30. $tt = microtime(true);
  31. if(is_string($var_map) AND strpos($var_map, '%') === 0) $var_map = substr($var_map, 1);
  32. $allmap = is_string($var_map) ? $this->parse($var_map) : $var_map;
  33. $filters = $allmap['filters'];
  34. $map = $allmap['vars'];
  35. $flag_first = false;
  36. if(substr($map[0], 0, 1) == ':') foreach(self::$hooks as $hmap=>$hobj) {
  37. if($map[0] !== $hmap) continue;
  38. $source = $hobj;
  39. $flag_first = 1;
  40. }
  41. if(!$flag_first) {
  42. if(is_string($map[0]) && strpos($map[0],"'") === 0) return trim($map[0],"'");
  43. else if(is_string($map[0]) && is_numeric($map[0])) return $map[0];
  44. else if(is_string($map[0]) && isset($this->data[$map[0]]) && !is_object($this->data[$map[0]])) return $this->data[$map[0]];
  45. else if(is_string($map[0]) && isset($this->data[$map[0]]) && is_object($this->data[$map[0]])) { $source = $this->data[$map[0]]; $flag_first = 1;}
  46. else if(is_string($map[0]) && isset($this->data[$map[0]]) && is_array($this->data[$map[0]])) { $source = $this->data[$map[0]]; $flag_first = 1;}
  47. else if(is_string($map[0]) && !isset($this->data[$map[0]])) return $this->parent ? $this->parent->get($allmap) : false;
  48. else throw new \Exception("IXML Scope no function was called");
  49. }
  50. foreach($map as $i=>$var) {
  51. if($map[0] == ':get' && $map[1] == 'test') echo(' | i:'.$i.' | flag: '.$flag_first);
  52. if($flag_first && $i < $flag_first) continue;
  53. if(!$source) return null;
  54. if(is_array($var) && is_object($source)) {
  55. if(method_exists($source, $var['func'])) $source = call_user_func_array(array($source, $var['func']), $var['args']);
  56. else if(method_exists($source, '__call')) $source = call_user_func_array(array($source, $var['func']), $var['args']);
  57. }
  58. else if(is_object($source)) {
  59. if(isset($source->$var)) $source = $source->$var;
  60. else if(!is_null($var) && method_exists($source, $var)) $source = $source->$var();
  61. else if(!is_null($var) && method_exists($source, '__call')) $source = $source->$var();
  62. }
  63. else if(is_array($source)) {
  64. if($this->pointer !== false && $map[0] == $this->iterator && !$iterated) {
  65. $iterated = true;
  66. $source = is_object($source[$this->iterator]) ? $source[$this->iterator]->_scope_by_pos($this->pointer) : $source[$this->iterator][$this->pointer];
  67. }
  68. else $source = @$source[$var];
  69. }
  70. else $source = false;
  71. }
  72. /**
  73. * Perform Filters
  74. */
  75. if(is_array($filters)) foreach($filters as $filter) {
  76. if(is_array($filter)); //
  77. else; //
  78. }
  79. $this->timers['scope->get'] += microtime(true) - $tt;
  80. return $source;
  81. }
  82. public function parse($var) {
  83. $tt = microtime(true);
  84. $extract_vars = $this->extract_vars($var);
  85. if(!empty($extract_vars)) foreach($extract_vars as $rv) {
  86. $val = (string) $this->get($rv);
  87. $var = str_replace('{'.$rv.'}', $val, $var);
  88. }
  89. $extract_subvars = $this->extract_subvars($var);
  90. if(!empty($extract_subvars)) foreach($extract_subvars as $rv) {
  91. $val = (string) $this->get($rv);
  92. $var = str_replace('['.$rv.']', $val, $var);
  93. }
  94. if(strpos($var, ' ? ') !== false) {
  95. list($cond, $result) = explode(' ? ', $var);
  96. $else = false;
  97. if(strpos($result, ' : ') !== false) list($result, $else) = explode(' : ', $result);
  98. if(strpos($cond, ' + ') !== false) {
  99. list($cond1, $cond2) = explode(' + ', $cond);
  100. $var = $cond1 + $cond2;
  101. }
  102. else if(strpos($cond, ' - ') !== false) {
  103. list($cond1, $cond2) = explode(' - ', $cond);
  104. $var = $cond1 - $cond2;
  105. }
  106. else if(strpos($cond, ' / ') !== false) {
  107. list($cond1, $cond2) = explode(' / ', $cond);
  108. $var = $cond1 / $cond2;
  109. }
  110. else if(strpos($cond, ' * ') !== false) {
  111. list($cond1, $cond2) = explode(' * ', $cond);
  112. $var = $cond1 * $cond2;
  113. }
  114. else if(strpos($cond, ' == ') !== false) {
  115. list($cond, $compare) = explode(' == ', $cond);
  116. $val = $this->get($cond);
  117. $cval = $this->get($compare);
  118. if($val == $cval) $var = $result;
  119. else $var = $else;
  120. }
  121. else if(strpos($cond, ' != ') !== false) {
  122. list($cond, $compare) = explode(' != ', $cond);
  123. $val = $this->get($cond);
  124. $cval = $this->get($cond);
  125. if($val != $cval) $var = $result;
  126. else $var = $else;
  127. }
  128. else if(strpos($cond, ' () ') !== false) {
  129. list($cond, $compare) = explode(' () ', $cond);
  130. $val = $this->get($cond);
  131. $cval = explode(',', $this->get($cond));
  132. $retval = false;
  133. foreach($cval as $tmp) if($val == trim($tmp)) $retval = true;
  134. if($retval) $var = $result;
  135. else $var = $else;
  136. }
  137. else if(strpos($cond, ' () ') !== false) {
  138. list($cond, $compare) = explode(' () ', $cond);
  139. $val = $this->get($cond);
  140. $cval = explode(',', $this->get($cond));
  141. $retval = true;
  142. foreach($cval as $tmp) if($val == trim($tmp)) $retval = false;
  143. if($retval) $var = $result;
  144. else $var = $else;
  145. }
  146. else {
  147. $val = $this->get($cond);
  148. $val = is_string($val) ? trim($val) : $val;
  149. if($val) $var = $result;
  150. else $var = $else;
  151. }
  152. }
  153. $ef = $this->extract_funcs($var);
  154. if(is_array($ef)) foreach($ef as $k=>$f) {
  155. $ef[$k]['key'] = '%F'.$k;
  156. $var = str_replace($f['string'], '%F'.$k, $var);
  157. }
  158. if(strpos($var, '|') !== false) {
  159. $a = explode('|', $var);
  160. $var = (strlen($a[0]) > 0 ? $a[0] :false);
  161. $filters = array_slice($a, 1);
  162. }
  163. else $filters = array();
  164. $vars = explode('.', $var);
  165. foreach($vars as &$v) {
  166. if(substr($v, 0, 2) == '%F') $v = $ef[substr($v, 2)];
  167. }
  168. if(is_array($filters)) foreach($filters as $filter) {
  169. if(substr($filter, 0, 2) == '%F') $filter = $ef[substr($filter, 2)];
  170. }
  171. $this->timers['scope->map'] += microtime(true) - $tt;
  172. return array('vars' => $vars, 'filters' => $filters);
  173. }
  174. public function __get($v) {
  175. return $this->get($v);
  176. }
  177. /**
  178. * Iteration function
  179. */
  180. public function iterate($limit = false) {
  181. $this->iterator = $this->source_as;
  182. //var_dump($this->iterator, $this->data[$this->iterator]);
  183. --$limit;
  184. if($limit !== false && $limit !== NULL && $this->pointer !== false && $this->pointer >= $limit) return false;
  185. $this->pointer = $this->pointer === false ? 0 : $this->pointer + 1;
  186. return $this->pointer >= $this->count ? false : true;
  187. }
  188. /**
  189. * Load source into the scope
  190. */
  191. public function source($source_map, $as = false) {
  192. if($as) $this->source_as = $as;
  193. else $this->source_as = 'i';
  194. # if requesting query, load the query results into this scope
  195. $this->data[$this->source_as] = $this->get($source_map);
  196. $this->iterator = $this->source_as;
  197. }
  198. /**
  199. * Load a literal variable into the scope
  200. */
  201. public function __set($var, $value) {
  202. $this->data[$var] = $value;
  203. }
  204. /**
  205. * Reset Iterations
  206. */
  207. public function reset() {
  208. if(is_object($this->data[$this->iterator]) && method_exists($this->data[$this->iterator], '_scope_rewind')) {
  209. $this->data[$this->iterator]->_scope_rewind();
  210. $this->count = $this->data[$this->iterator]->count();
  211. }
  212. else $this->count = $this->data[$this->iterator] ? count($this->data[$this->iterator]) : 0;
  213. $this->pointer = false;
  214. }
  215. /**
  216. * Extract all variables Below Here
  217. */
  218. private function extract_vars($content) {
  219. if(strpos($content, '{') === false) return array();
  220. // parse out the variables
  221. preg_match_all(
  222. "/{([\w:|.\,\(\)\/\-\% \[\]\?'=]+?)}/", //regex
  223. $content, // source
  224. $matches_vars, // variable to export results to
  225. PREG_SET_ORDER // settings
  226. );
  227. foreach((array)$matches_vars as $var) {
  228. $vars[] = $var[1];
  229. }
  230. return $vars;
  231. }
  232. private function extract_subvars($content) {
  233. if(strpos($content, '[') === false) return array();
  234. // parse out the variables
  235. preg_match_all(
  236. "/\[([\w:|.\,\(\)\/\-\% \[\]\?'=]+?)\]/", //regex
  237. $content, // source
  238. $matches_vars, // variable to export results to
  239. PREG_SET_ORDER // settings
  240. );
  241. foreach((array)$matches_vars as $var) {
  242. $vars[] = $var[1];
  243. }
  244. return $vars;
  245. }
  246. private function extract_funcs($content) {
  247. if(strpos($content, '(') === false) return array();
  248. // parse out the variables
  249. preg_match_all(
  250. "/([\w]+?)\(([\w:|.\,=@\(\)\/\-\%& ]*?)\)/", //regex
  251. $content, // source
  252. $matches_vars, // variable to export results to
  253. PREG_SET_ORDER // settings
  254. );
  255. foreach((array)$matches_vars as $var) {
  256. $vars[] = array('func' => $var[1], 'string' => $var[0], 'args' => explode(',', $var[2]));
  257. }
  258. return $vars;
  259. }
  260. }