]> git.mxchange.org Git - friendica.git/blob - include/template_processor.php
saved searches on search page, templates: Invalid argument supplied for foreach(...
[friendica.git] / include / template_processor.php
1 <?php
2
3
4         class Template {
5                 var $r;
6                 var $search;
7                 var $replace;
8                 var $stack = array();
9                 var $nodes = array();
10                 var $done = false;
11                 var $d = false;
12                 var $lang = null;
13                 
14                 
15                 private function _preg_error(){
16                         switch(preg_last_error()){
17                             case PREG_INTERNAL_ERROR: die('PREG_INTERNAL_ERROR'); break;
18                             case PREG_BACKTRACK_LIMIT_ERROR: die('PREG_BACKTRACK_LIMIT_ERROR'); break;
19                             case PREG_RECURSION_LIMIT_ERROR: die('PREG_RECURSION_LIMIT_ERROR'); break;
20                             case PREG_BAD_UTF8_ERROR: die('PREG_BAD_UTF8_ERROR'); break;
21                             case PREG_BAD_UTF8_OFFSET_ERROR: die('PREG_BAD_UTF8_OFFSET_ERROR'); break;
22                             default:
23                                         //die("Unknown preg error.");
24                                         return;
25                         }
26                 }
27                 
28                 private function _build_replace($r, $prefix){
29         
30                         if(is_array($r) && count($r)) {
31                                 foreach ($r as $k => $v ) {
32                                         if (is_array($v))
33                                                 $this->_build_replace($v, "$prefix$k.");
34                                         if (is_object($v))
35                                                 $this->_build_replace($v->getKeys(), "$prefix$k.");
36                                         
37                                         $this->search[] =  $prefix . $k;
38                                         $this->replace[] = $v;
39                                 }
40                         }
41                 } 
42                 
43                 private function _push_stack(){
44                         $this->stack[] = array($this->r, $this->search, $this->replace, $this->nodes);
45                 }
46                 private function _pop_stack(){
47                         list($this->r, $this->search, $this->replace, $this->nodes) = array_pop($this->stack);
48                         
49                 }
50                 
51                 private function _get_var($name){
52                         $keys = array_map('trim',explode(".",$name));           
53                         $val = $this->r;
54                         foreach($keys as $k) {
55                                 $val = $val[$k];
56                         }
57                         return $val;
58                 }
59                 
60                 /**
61                  * IF node
62                  * 
63                  * {{ if <$var> }}...[{{ else }} ...] {{ endif }}
64                  * {{ if <$var>==<val|$var> }}...[{{ else }} ...]{{ endif }}
65                  * {{ if <$var>!=<val|$var> }}...[{{ else }} ...]{{ endif }}
66                  */
67                 private function _replcb_if($args){
68                         if (strpos($args[2],"==")>0){
69                                 list($a,$b) = array_map("trim",explode("==",$args[2]));
70                                 $a = $this->_get_var($a);
71                                 if ($b[0]=="$") $b =  $this->_get_var($b);
72                                 $val = ($a == $b);
73                         } else if (strpos($args[2],"!=")>0){
74                                 list($a,$b) = explode("!=",$args[2]);
75                                 $a = $this->_get_var($a);
76                                 if ($b[0]=="$") $b =  $this->_get_var($b);
77                                 $val = ($a != $b);
78                         } else {
79                                 $val = $this->_get_var($args[2]);
80                         }
81                         list($strue, $sfalse)= preg_split("|{{ *else *}}|", $args[3]);
82                         return ($val?$strue:$sfalse);
83                 }
84                 
85                 /**
86                  * FOR node
87                  * 
88                  * {{ for <$var> as $name }}...{{ endfor }}
89                  * {{ for <$var> as $key=>$name }}...{{ endfor }}
90                  */
91                 private function _replcb_for($args){
92                         $m = array_map('trim', explode(" as ", $args[2]));
93                         list($keyname, $varname) = explode("=>",$m[1]);
94                         if (is_null($varname)) { $varname=$keyname; $keyname=""; }
95                         if ($m[0]=="" || $varname=="" || is_null($varname)) die("template error: 'for ".$m[0]." as ".$varname."'") ;
96                         //$vals = $this->r[$m[0]];
97                         $vals = $this->_get_var($m[0]);
98                         $ret="";
99                         if (!is_array($vals)) return $ret; 
100                         foreach ($vals as $k=>$v){
101                                 $this->_push_stack();
102                                 $r = $this->r;
103                                 $r[$varname] = $v;
104                                 if ($keyname!='') $r[$keyname] = $k;
105                                 $ret .=  $this->replace($args[3], $r);
106                                 $this->_pop_stack();
107                         }
108                         return $ret;
109                 }
110
111                 /**
112                  * INC node
113                  * 
114                  * {{ inc <templatefile> [with $var1=$var2] }}{{ endinc }}
115                  */
116                 private function _replcb_inc($args){
117                         list($tplfile, $newctx) = array_map('trim', explode("with",$args[2]));
118                         $this->_push_stack();
119                         $r = $this->r;
120                         if (!is_null($newctx)) {
121                                 list($a,$b) = array_map('trim', explode("=",$newctx));
122                                 $r[$a] = $this->_get_var($b); 
123                         }
124                         $this->nodes = Array();
125                         $tpl = get_markup_template($tplfile);
126                         $ret = $this->replace($tpl, $r);
127                         $this->_pop_stack();
128                         return $ret;
129                         
130                 }
131
132                 private function _replcb_node($m) {
133                         $node = $this->nodes[$m[1]];
134                         if (method_exists($this, "_replcb_".$node[1])){
135                                 $s = call_user_func(array($this, "_replcb_".$node[1]),  $node);
136                         } else {
137                                 $s = "";
138                         }
139                         $s = preg_replace_callback('/\|\|([0-9]+)\|\|/', array($this, "_replcb_node"), $s);
140                         return $s;
141                 }
142                                                 
143                 private function _replcb($m){
144                         //var_dump(array_map('htmlspecialchars', $m));
145                         $this->done = false;    
146                         $this->nodes[] = (array) $m;
147                         return "||". (count($this->nodes)-1) ."||";
148                 }
149                 
150                 private function _build_nodes($s){
151                         $this->done = false;
152                         while (!$this->done){
153                                 $this->done=true;
154                                 $s = preg_replace_callback('|{{ *([a-z]*) *([^}]*)}}([^{]*({{ *else *}}[^{]*)?){{ *end\1 *}}|', array($this, "_replcb"), $s);
155                                 if ($s==Null) $this->_preg_error();
156                         }
157                         //({{ *else *}}[^{]*)?
158                         krsort($this->nodes);
159                         return $s;
160                 }
161
162                 private function _get_lang(){
163                         if ($this->lang!=null) return $this->lang;
164                         
165                         $a = get_app();
166                         $this->lang=array();
167                         if(is_array($a->strings) && count($a->strings)) {
168                                 foreach ($a->strings as $k=>$v){
169                                         $k =  preg_replace("/[^a-z0-9-]/", "", str_replace(" ","-", strtolower($k)));
170                                         $this->lang[$k] = $v;
171                                 }
172                         }
173                         return $this->lang;
174                 }
175
176                 
177                 public function replace($s, $r) {
178                         if (!x($r,'$lang')){
179                                 $r['$lang'] = &$this->_get_lang();
180                         }
181                         $this->r = $r;
182                         $this->search = array();
183                         $this->replace = array();
184                         $this->_build_replace($r, "");
185                         #$s = str_replace(array("\n","\r"),array("§n§","§r§"),$s);
186                         $s = $this->_build_nodes($s);
187                         $s = preg_replace_callback('/\|\|([0-9]+)\|\|/', array($this, "_replcb_node"), $s);
188                         if ($s==Null) $this->_preg_error();
189                         
190                         // remove comments block
191                         $s = preg_replace('/{#[^#]*#}/', "" , $s);
192                                                 
193                         // replace strings recursively (limit to 10 loops)
194                         $os = ""; $count=0;
195                         while($os!=$s && $count<10){
196                                 $os=$s; $count++;
197                                 $s = str_replace($this->search,$this->replace, $s);
198                         }
199                         return $s;
200                 }
201         }
202         
203         $t = new Template;