From 5f7bf6004b04cb53c4a71281ff4487642eeccec3 Mon Sep 17 00:00:00 2001 From: Azareal Date: Wed, 30 Nov 2016 10:05:32 +0000 Subject: [PATCH] Added the template handler. Added the control panel templates. --- TO-DO.md | 7 +- hadron/class_language.php | 4 +- hadron/class_templates.php | 850 ++++++++ install/includes/templates_admincp.php | 2529 ++++++++++++++++++++++++ install/templates/main.html | 27 + 5 files changed, 3414 insertions(+), 3 deletions(-) create mode 100644 hadron/class_templates.php create mode 100644 install/includes/templates_admincp.php create mode 100644 install/templates/main.html diff --git a/TO-DO.md b/TO-DO.md index 4ee3212..c9e3b6a 100644 --- a/TO-DO.md +++ b/TO-DO.md @@ -5,5 +5,10 @@ Make the MCP front page super customisable. Add gadgets for displaying reports / mod actions. Add a cache_registry to make it easier for plugins to find out which ones are the HTML caches, which ones are data caches and which ones are compiled caches. Catch the errors when it fails to connect to Mysql. -Test to see if memcached works and review it. Turn memcached into a plugin? +Test to see if memcached works and review it. Add more unit tests. +Test and improve the template compilation system. +Test and complete the multi-threading system. + +Bugs: +Avatar updating is broken. diff --git a/hadron/class_language.php b/hadron/class_language.php index d1f7208..8185822 100644 --- a/hadron/class_language.php +++ b/hadron/class_language.php @@ -71,13 +71,13 @@ function load($name) function get($name) { - if(!isset($this->data[$name])) throw new \Exception("Unable to find the '{$name}' language string."); + if(!isset($this->data[$name])) return '{$lang_'.name.'}'; return $this->data[$name]; } function __get($name) { - if(!isset($this->data[$name])) throw new \Exception("Unable to find the '{$name}' language string."); + if(!isset($this->data[$name])) return '{$lang_'.name.'}'; return $this->data[$name]; } diff --git a/hadron/class_templates.php b/hadron/class_templates.php new file mode 100644 index 0000000..6bba4c3 --- /dev/null +++ b/hadron/class_templates.php @@ -0,0 +1,850 @@ +main = $main; + + $this->addCustomFunction('equals', function(array $params) { + if(!isset($params[0]) || !isset($params[1])) return false; + + if($params[0][0]=='$') $params[0] = $this->assigns[substr($params[0],1)]; + elseif(strpos($params[0],'(')!==false) + { + $res = preg_match('#([A-Za-z0-9_]+)\(([A-Za-z0-9\$_!\(\)]+)\)#isu',$params[0],$matches); + if(!$res) return null; + + $params[0] = $this->processFunction($matches[1],$matches[2]); + if($params[0]==null) return null; + } + + if($params[1][0]=='$') $params[1] = $this->assigns[substr($params[1],1)]; + elseif(strpos($params[1],'(')!==false) + { + $res = preg_match('#([A-Za-z0-9_]+)\(([A-Za-z0-9\$_!\(\)]+)\)#isu',$params[1],$matches); + if(!$res) return null; + + $params[1] = $this->processFunction($matches[1],$matches[2]); + if($params[1]==null) return null; + } + + if($params[0]==$params[1]) return true; + return false; + }); + $this->addCustomFunction('exactly', function(array $params) { + if(!isset($params[0]) || !isset($params[1])) return false; + + if($params[0][0]=='$') $params[0] = $this->assigns[substr($params[0],1)]; + elseif(strpos($params[0],'(')!==false) + { + $res = preg_match('#([A-Za-z0-9_]+)\(([A-Za-z0-9\$_!(),]+)\)#isu',$params[0],$matches); + if(!$res) return null; + + $params[0] = $this->processFunction($matches[1],$matches[2]); + if($params[0]==null) return null; + } + + if($params[1][0]=='$') $params[1] = $this->assigns[substr($params[1],1)]; + elseif(strpos($params[1],'(')!==false) + { + $res = preg_match('#([A-Za-z0-9_]+)\(([A-Za-z0-9\$_!(),]+)\)#isu',$params[1],$matches); + if(!$res) return null; + + $params[1] = $this->processFunction($matches[1],$matches[2]); + if($params[1]==null) return null; + } + + if($params[0]===$params[1]) return true; + return false; + }); + $this->addCustomFunction('empty', function(array $params) { + if(!isset($params[0])) return false; + + if($params[0][0]=='$') $params[0] = $this->assigns[substr($params[0],1)]; + elseif(strpos($params[0],'(')!==false) + { + $res = preg_match('#([A-Za-z0-9_]+)\(([A-Za-z0-9\$_!(),]+)\)#isu',$params[0],$matches); + if(!$res) return null; + + $params[0] = $this->processFunction($matches[1],$matches[2]); + if($params[0]==null) return null; + } + + if(empty($params[0])) return true; + return false; + }); + } + + /** + * + * This method is for loading a template from the database or from the cache. + * $name - The name of the template which you wish to load. + * Returns: A boolean value indicating success. + * + **/ + function load($name, $bypass_compile = false) { + $db = $this->main->getDatabase(); + if(isset($this->templates[$name])) return true; + if(!defined("IN_ADMIN") && $this->main->settings['cache_compiled_templates'] && !$bypass_compile) + { + if(file_exists(ABB_BASE.'/cache/templates/comp-'.$name.'.php')) return true; + else $comp = true; + } + //if(!defined("IN_ADMIN") && $this->main->settings['cache_templates'] && $cache->isLoaded($name,"templates") && $cache->loadCache($name,"templates")) $res = $cache->get($name,"templates"); + //else + //{ + // Load the template.. + $res = $db->get("*",$this->table,"name='{$name}' AND (tid=0 OR tid='{$this->main->settings['themeID']}' OR is_plugin=1)",1,"tid DESC"); + if(!$res) return false; + + // Cache it.. + //if(!defined("IN_ADMIN") && $this->main->settings['cache_templates']) $cache->writeCache("tmpl", $res['content'],"templates/{$name}"); + //} + $this->templates[$res['name']] = str_replace("\n","",$res['content']); + $this->assigns[$res['name']] = &$this->templates[$res['name']]; + if(isset($comp)) $this->compile_template($name); + return true; + } + + function setTable($table) + { + $db = $this->main->getDatabase(); + $this->table = $db->sanitise($table); + } + + /** + * + * This method is for forcefully loading a template from the database. + * $name - The name of the template which you wish to load. + * Returns: A boolean value indicating success. + * + **/ + function force_load($name) { + $db = $this->main->getDatabase(); + $res = $db->get("*",$this->table,"name='{$name}' AND (tid=0 OR tid='{$this->main->settings['themeID']}' OR is_plugin=1)",1,"tid DESC"); + if(!$res) return false; + $this->templates[$res['name']] = str_replace("\n","",$res['content']); + $this->assigns[$res['name']] = &$this->templates[$res['name']]; + return true; + } + + /** + * + * This method is for loading multiple templates from the database. + * $list - The comma-seperated list of templates which you wish to load. + * + **/ + function bulk_load(array $list) { + $db = $this->main->getDatabase(); + $where = ""; + $count = 0; + foreach($list as $name) if(!isset($this->templates[$name])) + { + $where .= " name='{$name}' ,"; + $count++; + } + $where = rtrim($where,','); + $where = str_replace(",", "OR", $where); + $where = "({$where}) AND (tid=0 OR tid='{$this->main->settings['themeID']}' OR is_plugin=1)"; + $res = $db->get("*",$this->table,$where,$count,"tid DESC"); + if(!$res) return false; + foreach($res as $tmpl) + { + $this->templates[$tmpl['name']] = str_replace("\n","",$tmpl['content']); + $this->assigns[$tmpl['name']] = &$this->templates[$tmpl['name']]; + } + return true; + } + + /** + * + * This method is for forcefully loading multiple templates from the database. + * $list - The comma-seperated list of templates which you wish to load. + * + **/ + function bulk_load_all(array $list) { + $db = $this->main->getDatabase(); + if(!defined("IN_ADMIN") && $this->main->settings['cache_compiled_templates']) + { + foreach($list as $key => $name) + if(file_exists(ABB_BASE.'/cache/templates/comp-'.$name.'.php')) unset($list[$key]); + } + if(count($list)==0) return true; + + $where = implode("' OR name='", $list); + $res = $db->get("*",$this->table,"(name='{$where}') AND (tid=0 OR tid='{$this->main->settings['themeID']}' OR is_plugin=1)",null,"tid ASC"); + if(!$res) return false; + foreach($res as $tmpl) + { + $this->templates[$tmpl['name']] = str_replace("\n","",$tmpl['content']); + $this->assigns[$tmpl['name']] = &$this->templates[$tmpl['name']]; + if(!defined("IN_ADMIN") && $this->main->settings['cache_compiled_templates']) $this->compile_template($name); + } + return true; + } + + /** + * + * This method is for loading a template from the database without assigning it as a + * reference to the assignments property. + * + * $name - The name of the template which you wish to load. + * Returns: A boolean value indicating success. + * + **/ + function grab($name) { + $db = $this->main->getDatabase(); + $res = $db->get("*",$this->table,"name='{$name}' AND (tid=0 OR tid='{$this->main->settings['themeID']}' OR is_plugin=1)",1,"tid DESC"); + if(!$res) return false; + $this->templates[$res['name']] = str_replace("\n","",$res['content']); + return true; + } + + /** + * + * $name = The name of the template which you wish to load and render. + * + **/ + public function build($name) + { + $db = $this->main->getDatabase(); + if(isset($this->templates[$name])) return true; + $res = $db->get("*",$this->table,"name='{$name}'",1); + if(!$res) return false; + $res['content'] = $this->sub($res['content']); + $this->templates[$res['name']] = str_replace("\n","",$res['content']); + $this->assigns[$res['name']] = &$this->templates[$res['name']]; + } + + /** + * + * $name - The name of the template which you wish to unload. + * + **/ + public function unload($name) { unset($this->templates[$name]); } + + /** + * + * $name - The name of the variable as referred to on the template side. + * $val - The data for the variable on the template side. + * + **/ + public function assign($name, $val) { + $this->assigns[$name] = $val; + } + + /** + * + * $name - The name of the variable as referred to on the template side. + * $val - The data for the variable on the template side. + * + **/ + public function append($name, $val) { + $this->assigns[$name] .= $val; + } + + public function getVar($name) { + return $this->assigns[$name]; + } + + /** + * + * $name - The name of the variable as referred to on the template side. + * $val - The reference for the variable to be used on the template side. + * + **/ + public function stick($name, &$val) { + $this->assigns[$name] = &$val; + } + + /** + * + * A method to remove a specific variable from the assignments pool. + * $name - Name of the assigned variable to unassign. + * + **/ + public function unassign($name) { + unset($tmpls->assigns[$name]); + } + + /** + * + * $name - Name of the assigned variable to check if it's empty. + * + **/ + public function isEmpty($name) { + return empty($this->assigns[$name]); + } + + /** + * + * A method for rendering the specified template. + * $name - Name of the template which you wish to render. + * + **/ + public function render($name) + { + if(!defined("IN_ADMIN") && $this->main->settings['cache_compiled_templates']) + { + if(!isset($this->compiled[$name])) + { + if(@include(ABB_BASE.'/cache/templates/comp-'.$name.'.php')) + { + $this->compiled[$name] = $tmplLambda; + return $this->compiled[$name]($name, $this); + } + $this->compile_template($name); + @include(ABB_BASE.'/cache/templates/comp-'.$name.'.php'); + + $this->compiled[$name] = $tmplLambda; + return $this->compiled[$name]($name, $this); + } + return $this->compiled[$name]($name, $this); + } + if(!isset($this->templates[$name])) $this->load($name); + return $this->sub($this->templates[$name]); + } + + protected function sub($tmpl) + { + $tmpl = preg_replace_callback($this->elseif_regex,[get_class($this),'boolelsesub'], $tmpl); + $tmpl = preg_replace_callback($this->if_regex,[get_class($this),'boolsub'],$tmpl); + $tmpl = preg_replace_callback($this->include_regex,[get_class($this),'includesub'],$tmpl); + $tmpl = preg_replace_callback($this->hook_regex,[get_class($this),'hooksub'],$tmpl); + $tmpl = preg_replace_callback($this->variable_regex,[get_class($this),'varsub'],$tmpl); + + if(count($this->events)!=0) foreach($this->events as $event) $tmpl = $event($tmpl); + return $tmpl; + } + + /** + * + * The new callback method for variable rendering. + * + **/ + protected function varsub(array $input) + { + if(strpos($input[1],'[')===false) + //if(preg_match('#(.*?)\[(.*?)\]#', $input[1])==0) + { + if(isset($this->assigns[$input[1]])) + { + if(is_array($this->assigns[$input[1]])) return array_rand($this->assigns[$input[1]]); + return $this->assigns[$input[1]]; + } + return '{$'.$input[1].'}'; + } + + // Strip quotes.. + $arrs = str_replace(["'",'"',"`"],'', $input[1]); + + // Break it down into a list.. + $arrs = str_replace(["][","["],",", $arrs); + $arrs = str_replace("]","", $arrs); + $arrs = explode(",", $arrs); + + // Only one deep? + if(($count = count($arrs))==2) + { + if(isset($this->assigns[$arrs[0]][$arrs[1]])) return $this->assigns[$arrs[0]][$arrs[1]]; + return '{$'.$input[1].'}'; + } + + // Iterate through the various depths + $base = $arrs[0]; + $target = $this->assigns[$base]; + $i = 1; + while(isset($arrs[$i]) && isset($target[$arrs[$i]])) + { + $target = $target[$arrs[$i]]; + $i++; + } + if(is_array($target)) return '{$'.$input[1].'}'; + return $target; + } + + protected function boolsub(array $input) + { + $input[1] = trim($input[1]); + + if(strtolower($input[1])=="true") return $input[2]; + elseif(strtolower($input[1])=="false") return ""; + + // Handle logical inversion + if($input[1][0]=='!') + { + $input[1] = substr($input[1],1); + $invert = true; + } + else $invert = false; + + // Is this a variable or a function..? + if($input[1][0]=='$') + { + $var = substr($input[1],1); + if(isset($this->assigns[$var]) && $this->assigns[$var]) $ret = true; + else $ret = false; + } + elseif(strpos($input[1],'(')!==false) + { + $res = preg_match('#([A-Za-z0-9_]+)\(([A-Za-z0-9\$_!(),]+)\)#isu',$input[1],$matches); + if(!$res) return $input[2]; + + $ret = $this->processFunction($matches[1],$matches[2]); + if($ret===null) return $input[0]; + } + + // Unable to recognise this.. Should we pass this off to a plugin which handles custom template grammar...? + else return $input[0]; + + if($invert) $ret = !$ret; + if($ret) return $input[2]; + return ""; // Not rendering this part.. + } + + protected function boolelsesub(array $input) + { + if(strtolower($input[1])=="true") return $input[2]; + elseif(strtolower($input[1])=="false") return $input[5]; + + // Is it a variable? + if($input[1][0]=='$') { + $var = str_replace('$','',$input[1]); + if(isset($this->assigns[$var]) && $this->assigns[$var]) return $input[2]; + return $input[5]; + } + + // Logical inversion... + elseif($input[1][0]=='!' && $input[1][1]=='$') { + $var = str_replace('!$','',$input[1]); + if(isset($this->assigns[$var]) && $this->assigns[$var]) return $input[5]; + return $input[2]; + } + if($input[1]) return $input[2]; + return $input[5]; // Not rendering this part.. + } + + protected function processFunction($function, $body) + { + if(!isset($this->customFunctions[$function])) return null; + $params = explode(',', $body); + return $this->customFunctions[$function]($params); + } + + /** + * + * A callback method for including other templates in a template. + * + **/ + protected function includesub($input) + { + $db = $this->main->getDatabase(); + $name = $db->sanitise($input[1]); + if(isset($this->templates[$name])) return $this->render($name); + $res = $db->get("*",$this->table,"name='{$name}' AND (tid=0 OR tid='{$this->main->settings['themeID']}')",1,"tid DESC"); + if(!$res) return '{include('.$input[1].')}'; + $this->templates[$res['name']] = str_replace("\n","",$res['content']); + $this->assigns[$res['name']] = &$this->templates[$res['name']]; + $tmpl = $this->templates[$res['name']]; + return $this->sub($tmpl); + } + + protected function hooksub($input) + { + $plugins = $this->main->getPlugins(); + $out = $plugins->hook("tmpls_{$input[1]}"); + if($out) return $out; + return ""; + } + + function compile_template($name) + { + $templateCache = function($name, $template) + { + $handle = fopen(ABB_BASE."/cache/templates/comp-{$name}.php",'w'); + $str = "main->getPlugins();\n\$tmpl = '';\n"; + + $tree = [$template]; + $meta = ['text']; + list($tree, $meta) = $this->templates_compile_elseif_tree($tree, $meta); + list($tree, $meta) = $this->templates_compile_if_tree($tree, $meta); + list($tree, $meta) = $this->templates_compile_include_tree($tree, $meta); + //$tmpl = preg_replace_callback($this->include_regex,[get_class($this),'includesub'],$tmpl); + list($tree, $meta) = $this->templates_compile_hook_tree($tree, $meta); + list($tree, $meta) = $this->templates_compile_variable_tree($tree, $meta); + //echo "
{$name}
";var_dump($tree);var_dump($meta);echo "
"; + $str .= $this->compile_template_parse($tree, $meta); + + $str .= "return \$tmpl;\n};\n?>"; + fwrite($handle, $str); + fclose($handle); + }; + if(!isset($this->templates[$name])) $this->load($name, true); + $templateCache($name, $this->templates[$name]); + //register_shutdown_function($templateCache, $name, $this->templates[$name]); + } + + function compile_template_parse(array $tree, array $meta) + { + $str = ''; + foreach($tree as $branchID => $branch) + { + switch($meta[$branchID]) + { + case "text": $str .= "\$tmpl .= '".str_replace("'","\'",$tree[$branchID])."';\n"; break; + case "if": + $itree = [$tree[$branchID]['body']]; + $imeta = ['text']; + list($itree, $imeta) = $this->templates_compile_variable_tree($itree, $imeta); + if(isset($itree[1])) + { + $str .= "if({$tree[$branchID]['statement']}) {"; + $str .= $this->compile_template_parse($itree, $imeta); + $str .= " }"; + } + else $str .= "if({$tree[$branchID]['statement']}) {\$tmpl .= '".str_replace("'","\'",$tree[$branchID]['body'])."'; }\n"; + break; + case "include": $str .= "\$tmpl .= \$tmpls->render('{$tree[$branchID]}');"; break; + case "hook": $str .= "\$tmpl .= \$plugins->hook('tmpls',\$name, \$tmpl);\n"; break; + case "variable": $str .= "\$tmpl .= \$tmpls->assigns{$tree[$branchID]};\n"; break; + default: + $error = $this->main->getErrors(); + $error->custom("Unknown template node type detected, aborting.", true); + $error->output(); + exit; + } + } + return $str; + } + + function templates_compile_elseif_tree(array $tree, array $meta) + { + foreach($tree as $leafID => $leaf) + { + if($meta[$leafID]!='text') continue; + if($res = preg_split($this->elseif_regex,$leaf,100,PREG_SPLIT_DELIM_CAPTURE)) + { + $state = 0; + $branch = []; + $branchMeta = []; + $data = []; + foreach($res as $slot) + { + if($state==0) + { + $branch[] = $slot; + $branchMeta[] = 'text'; + $state = 1; + } + elseif($state==1) + { + if($slot=="{/eif}") + { + $branch[] = $data; + $branchMeta[] = 'if'; + $state = 2; + } + else + { + if(!isset($data['statement'])) $data = $this->templates_compile_if_statement($slot, $data); + else $data['body'] = $slot; + } + } + else + { + if($slot=="{else}") continue; + if($slot=="{/else}") + { + $state = 0; + $branch[] = $data; + $branchMeta[] = 'if'; + $data = []; + } + else + { + $data = $this->templates_compile_if_statement($slot, $data, true, true); + $data['body'] = $slot; + } + } + } + } + array_splice($tree,$leafID,1,$branch); + array_splice($meta,$leafID,1,$branchMeta); + } + return [$tree,$meta]; + } + + function templates_compile_if_tree(array $tree, array $meta) + { + $i = 0; + $newTree = []; + $newMeta = []; + foreach($tree as $leafID => $leaf) + { + if($meta[$leafID]!='text') + { + $newTree[$i] = $leaf; + $newMeta[$i] = $meta[$leafID]; + $i++; + continue; + } + if($res = preg_split($this->if_regex,$leaf,100, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_OFFSET_CAPTURE)) + { + $text = true; + $data = []; + foreach($res as $slot) + { + if($text && isset($leaf[$slot[1] - 4]) && $leaf[$slot[1] - 4]=='{' && $leaf[$slot[1] - 3]=='i' && $text && $leaf[$slot[1] - 2]=='f') + { + $text = false; + } + + if($text) + { + $newTree[$i] = $slot[0]; + $newMeta[$i] = 'text'; + $i++; + } + elseif($slot[0]=="{/if}") + { + $newTree[$i] = $data; + $newMeta[$i] = 'if'; + $i++; + unset($data); + $data = []; + $text = true; + } + else + { + if(!isset($data['statement'])) $data = $this->templates_compile_if_statement($slot, $data); + else $data['body'] = $slot[0]; + } + } + } + } + return [$newTree,$newMeta]; + } + + function templates_compile_if_statement($slot, array $data, $force = false, $invertOver = false) + { + if(!isset($data['statement']) || $force) + { + if(is_array($slot)) $data['statement'] = $slot[0]; + else $data['statement'] = $slot; + + if(strpos($data['statement'],'(')!==false || strpos($data['statement'],')')!==false) + { + $data['statement'] = 'false'; + return $data; + } + + if($data['statement'][0]=='!') + { + $data['statement'] = ltrim($data['statement'],'!'); + $invert = true; + } + else $invert = false; + + $data['statement'] = str_replace(["'",'"',"`"],'',$data['statement']); + $varname = ltrim($data['statement'],'$'); + if($invert) $data['statement'] = "!\$tmpls->assigns['{$varname}']"; + else $data['statement'] = "\$tmpls->assigns['{$varname}']"; + if($invertOver) $data['statement'] = '!'.$data['statement']; + $data['statement'] = "isset(\$tmpls->assigns['{$varname}']) && ({$data['statement']})"; + } + return $data; + } + + function templates_compile_include_tree(array $tree, array $meta) + { + $i = 0; + $newTree = []; + $newMeta = []; + foreach($tree as $leafID => $leaf) + { + if($meta[$leafID]!='text') + { + $newTree[$i] = $leaf; + $newMeta[$i] = $meta[$leafID]; + $i++; + continue; + } + if($res = preg_split($this->include_regex,$leaf,100, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_OFFSET_CAPTURE)) + { + foreach($res as $slot) + { + if(isset($leaf[$slot[1] - 11]) && $leaf[$slot[1] - 10]=='{' && $leaf[$slot[1] - 9]=='i' && $leaf[$slot[1] - 8]=='n') + { + $newTree[$i] = str_replace("'",'',$slot[0]); + $newMeta[$i] = 'include'; + $i++; + } + else + { + $newTree[$i] = $slot[0]; + $newMeta[$i] = 'text'; + $i++; + } + } + } + } + return [$newTree, $newMeta]; + } + + function templates_compile_hook_tree(array $tree, array $meta) + { + $i = 0; + $newTree = []; + $newMeta = []; + foreach($tree as $leafID => $leaf) + { + if($meta[$leafID]!='text') + { + $newTree[$i] = $leaf; + $newMeta[$i] = $meta[$leafID]; + $i++; + continue; + } + if($res = preg_split($this->hook_regex,$leaf,100,PREG_SPLIT_DELIM_CAPTURE)) + { + $text = true; + foreach($res as $slot) + { + if($text) + { + $newTree[$i] = $slot; + $newMeta[$i] = 'text'; + $i++; + $text = false; + } + else + { + $newTree[$i] = str_replace("'",'',$slot); + $newMeta[$i] = 'hook'; + $i++; + $text = true; + } + } + } + } + return [$newTree, $newMeta]; + } + + function templates_compile_variable_tree(array $tree, array $meta) + { + $i = 0; + $newTree = []; + $newMeta = []; + foreach($tree as $leafID => $leaf) + { + if($meta[$leafID]!='text') + { + $newTree[$i] = $leaf; + $newMeta[$i] = $meta[$leafID]; + $i++; + continue; + } + if($res = preg_split($this->variable_regex,$leaf,100, PREG_SPLIT_DELIM_CAPTURE)) + { + $text = true; + foreach($res as $slot) + { + if($text) + { + $newTree[$i] = $slot; + $newMeta[$i] = 'text'; + $i++; + $text = false; + } + else + { + // Break the variable string down... + $slot = str_replace(["'",'"','`',']'],'',$slot); + $slot = str_replace(['][','['],'.',$slot); + + // Rebuild it in the correct format.. + $slot = "['".str_replace('.',"']['",$slot)."']"; + + $newTree[$i] = $slot; + $newMeta[$i] = 'variable'; + $i++; + $text = true; + } + } + } + } + return [$newTree, $newMeta]; + } + + public function addEvent($event, $name = null) + { + if($name==null) $this->events[] = $event; + else $this->events[$name] = $event; + } + + public function addCustomFunction($name, $callback) + { + $this->customFunctions[$name] = $callback; + } + + public function addEditorInstance($editorid) + { + $this->editor_instances[] = $editorid; + } + + public function getEditorInstances() + { + return $this->editor_instances; + } + + public function output($name) + { + $error = $this->main->getErrors(); + if(!defined("IN_ADMIN") && !$this->main->settings['cache_compiled_templates']) + { + $tmpl = $this->templates[$name]; + $tmpl = $this->sub($tmpl); + } + else $tmpl = $this->render($name); + $error->output(); + echo $tmpl; + } +} \ No newline at end of file diff --git a/install/includes/templates_admincp.php b/install/includes/templates_admincp.php new file mode 100644 index 0000000..d5e28a3 --- /dev/null +++ b/install/includes/templates_admincp.php @@ -0,0 +1,2529 @@ +insert('admin_templates', array( + "name" => 'header', + "content" => <<
+ +

{\$settings['site_name']}

+
+ + +header +)); + +$db->insert('admin_templates',array( + "name" => 'footer', + "content" => << + + +tem +)); + +$db->insert('admin_templates',array( + "name" => 'page', + "content" => << + + + + {\$title} - {\$settings['site_name']} + + + {\$libraries} + + {\$headers} + + + {\$deferred}{include("header")}{\$body}{include("footer")} + + +tem +)); + +$db->insert('admin_templates',array( + "name" => 'index', + "content" => << + {\$sidebar}{!admin_home_nav}
+ +
+ + + + + + + + + + + + + + + + + + + + + + +
{\$lang['module_tstats']}
{\$lang['module_tstats_users']}:{\$users}
{\$lang['module_tstats_topics']}:{\$topics}
{\$lang['module_tstats_posts']}:{\$posts}
{\$lang['module_tstats_dailyusers']}:{\$dailyusers}
{\$lang['module_tstats_uniqueusers']}:{\$uniqueusers}
+
+
+ + + +
{\$lang['module_gstats']}
{\$lang['module_gstats_desc']}
+
+
+ + + +
{\$lang['module_news']}
{\$news}
+
+tem +)); + +$db->insert('admin_templates',array( + "name" => 'users', + "content" => << + {\$sidebar}{!admin_users_nav}
+ +
{\$notice} + + + + {!admin_users_head} + + + {\$rows} +
{\$lang['users_head']}
+
{\$pages}
+
+ + +
+
+tem +)); + +$db->insert('admin_templates',array( + "name" => 'users_row', + "content" => << + {\$name} + {!admin_users_row} + + + + + + + + + +tem +)); + +$db->insert('admin_templates',array( + "name" => 'edit_user', + "content" => << + {\$sidebar}{!admin_users_nav}
+ +
{\$notice} +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + {if(\$can_edit_users_statistics)} + + + + + + + + + + + + + + + + + {/if} + {!admin_users_edit_general} +
{\$lang['edit_user_username']}:
{\$lang['edit_user_name']}:
{\$lang['edit_user_pass']}:
{\$lang['edit_user_group']}:
{\$lang['edit_user_usertitle']}:
{\$lang['edit_user_email']}:
{\$lang['edit_user_topics']}:
{\$lang['edit_user_posts']}:
{\$lang['edit_user_big_posts']}:
{\$lang['edit_user_clevel']}:
+
+
+ + + + + + {!admin_users_edit_moderation} +
{\$lang['edit_user_warnpoints']}:
+
+ {if(\$can_edit_perms)}
Coming Soon!
{/if} + {!admin_users_edit_left} +
+
+ + + {!admin_users_edit_options} + +
{\$lang['edit_user_options_head']}
+ +
+
+
+
+tem +)); + +$db->insert('admin_templates',array( + "name" => 'create_user', + "content" => << + {\$sidebar}{!admin_users_nav}
+ +
{\$notice} +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + {if(\$can_edit_users_statistics)} + + + + + + + + + + + + + + + + + {/if} + {!admin_users_create_general} +
{\$lang['create_user_username']}:
{\$lang['create_user_name']}:
{\$lang['create_user_pass']}:
{\$lang['create_user_group']}:
{\$lang['create_user_usertitle']}:
{\$lang['create_user_email']}:
{\$lang['create_user_topics']}:
{\$lang['create_user_posts']}:
{\$lang['create_user_big_posts']}:
{\$lang['create_user_clevel']}:
+
+
+ + + + + + {!admin_users_create_moderation} +
{\$lang['create_user_warnpoints']}:
+
+ {if(\$can_edit_perms)}
Coming Soon!
{/if} + {!admin_users_create_left} +
+
+ + + {!admin_users_create_options} + +
{\$lang['create_user_options_head']}
+
+
+
+tem +)); + +$db->insert('admin_templates',array( + "name" => 'groups', + "content" => << + {\$sidebar}{!admin_users_nav}
+ +
{\$notice} + + + + {!admin_groups_head} + + {\$rows} +
{\$lang['groups_head']}
+
{\$pages}
+
+ + +
+
+tem +)); + +$db->insert('admin_templates',array( + "name" => 'groups_row', + "content" => << + {\$name} + {!admin_groups_row} + + + + + + + + +tem +)); + +$db->insert('admin_templates',array( + "name" => 'edit_group', + "content" => << + {\$sidebar}{!admin_users_nav}
+ +
+ {\$notice} +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {!admin_groups_edit_general} +
{\$lang['edit_group_name']}:
{\$lang['edit_group_desc']}:
{\$lang['edit_group_isbanned']}?
{\$lang['edit_group_issuper']}?
{\$lang['edit_group_isadmin']}?
{\$lang['edit_group_style']}: + + {\$lang['edit_group_style_bit']} + +
{\$lang['edit_group_ismulti']}?
{\$lang['edit_group_level']}:
+
+
{\$fperms}
+
{\$fmodperms}
+
{\$plist}
+ {!admin_groups_edit_left} +
+
+ + + {!admin_groups_edit_options} + +
{\$lang['edit_group_options_head']}
+ +
+
+
+
+tem +)); + +$db->insert('admin_templates',array( + "name" => 'edit_group_permission', + "content" => << + {\$pname}? + + {!admin_groups_edit_perm_row} + +tem +)); + +$db->insert('admin_templates',array( + "name" => 'create_group', + "content" => << + {\$sidebar}{!admin_users_nav}
+ +
{\$notice} +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {!admin_groups_create_general} +
{\$lang['create_group_name']}:
{\$lang['create_group_desc']}:
{\$lang['create_group_isbanned']}?
{\$lang['create_group_issuper']}?
{\$lang['create_group_isadmin']}?
{\$lang['create_group_style']}: + + {\$lang['create_group_style_bit']} + +
{\$lang['create_group_ismulti']}?
{\$lang['create_group_level']}:
+
+
{\$plist}
+ {!admin_groups_create_left} +
+
+ + + {!admin_groups_create_options} + +
{\$lang['create_group_options_head']}
+ +
+
+
+
+tem +)); + +$db->insert('admin_templates',array( + "name" => 'create_group_permission', + "content" => << + {\$pname}? + + {!admin_groups_create_perm_row} + +tem +)); + +$db->insert('admin_templates',array( + "name" => 'titles', + "content" => << + {\$sidebar}{!admin_users_nav}
+ +
{\$notice} + + + + {!admin_titles_head} + {\$rows} +
+ {\$lang['titles_head']}
+
+
{\$pages}
+
+tem +)); + +$db->insert('admin_templates',array( + "name" => 'titles_row', + "content" => << + {\$title_name} + {\$title_criteria} + {!admin_titles_row} + + + + + + + +tem +)); + +$db->insert('admin_templates',array( + "name" => 'edit_title', + "content" => << +$(document).ready(function(){ + $(".texteditor").sceditor({ + plugins: "bbcode", + toolbarExclude: "table", + emoticonsRoot: "../images/smilies/", + emoticons: + { + dropdown: + { + ":)": "smile-24.png", + ":D": "smile_big-24.png", + ":angel:": "angel-24.png", + ":cool:": "cool-24.png", + ":(": "sad-24.png", + ":'(": "crying-24.png", + ":O": "surprise-24.png", + ":P": "raspberry-24.png", + ";)": "wink-24.png" + }, + more: + { + ":$": "embarrassed-24.png", + ":monkey:": "monkey-24.png", + ":|": "plain-24.png", + ":devil:": "devilish-24.png" + } + }, + style: "../js/sceditor/themes/modern.min.css" + }); +}); +
+ {\$sidebar}{!admin_forums_nav}
+
+
{\$notice} +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + {!admin_titles_edit_general} +
{\$lang['edit_title_head']}
{\$lang['edit_title_name']}:
{\$lang['edit_title_desc']}:
{\$lang['edit_title_level']}:
{\$lang['edit_title_posts']}:
{\$lang['edit_title_topics']}:
{\$lang['edit_title_upvotes']}:
+
+
+tem +)); + +$db->insert('admin_templates',array( + "name" => 'penalties', + "content" => << + {\$sidebar}{!admin_users_nav}
+ +
{\$notice} +
+ + + + {!admin_penalties_head} + + {\$rows} +
+ {\$lang['penalties_head']} + +
+
{\$pages}
+
+
+
+ + + {!admin_penalties_create_head_rows} + + + + + + + + + + + + + + + + + + + + + + + + + + {!admin_penalties_create_rows} +
{\$lang['penalties_create_head']}
{\$lang['penalties_create_langname']}:
{\$lang['penalties_create_auto_ban']} + +
{\$lang['penalties_create_banGroup']}: + +
{\$lang['penalties_create_newGroup']}: + +
{\$lang['penalties_create_duration']}:
{\$lang['penalties_create_points']}:
+ + +
+
+
+
+tem +)); + +$db->insert('admin_templates',array( + "name" => 'penalties_row', + "content" => << + + {\$pname} + + {!admin_penalties_row} + + {if(\$has_ban)}{\$banstring}{/if} + {if(\$perms_revoked)}{\$revokestring}{/if} + {\$scope} + + + + + + + + +tem +)); + +$db->insert('admin_templates',array( + "name" => 'edit_penalty', + "content" => << + {\$sidebar}{!admin_users_nav}
+ +
{\$notice} +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {!admin_edit_penalty_general_rows} +
{\$lang['edit_penalty_langstring']}:
{\$lang['edit_penalty_auto_ban']} + +
{\$lang['edit_penalty_auto_post']}: + +
{\$lang['edit_penalty_requireGroup']}: + +
{\$lang['edit_penalty_banGroup']}: + +
{\$lang['edit_penalty_newGroup']}: + +
{\$lang['edit_penalty_duration']}:
+ +
+ + + + + + + + + + + + + + + + + + {!admin_edit_penalty_auto_rows} +
{\$lang['edit_penalty_auto_head']}
{\$lang['edit_penalty_auto_switch']}: + +
{\$lang['edit_penalty_auto_manual_issue']}: + +
{\$lang['edit_penalty_auto_points']}:
+ + + + + + + + + + + + + + + + + + + + + {!admin_edit_penalty_cascade_rows} +
{\$lang['edit_penalty_global_cascade_head']}
+ {\$lang['edit_penalty_global_cascade_local_scope']}:
+ ({\$lang['edit_penalty_global_cascade_local_scope_desc']}) +
+ +
+ {\$lang['edit_penalty_global_cascade_mods_required']}:
+ ({\$lang['edit_penalty_global_cascade_mods_required_desc']}) +
{\$lang['edit_penalty_global_cascade_area_max']}:
+ +
+
+
+ {\$localPerms}
+
+
+ {\$globalPerms}
+
+ {!admin_edit_penalty_tabs_body} +
+
+
+tem +)); + +$db->insert('admin_templates',array( + "name" => 'penalty_perm_row', + "content" => << + {\$permstring} + + +tem +)); + +$db->insert('admin_templates',array( + "name" => 'create_penalty', + "content" => << + {\$sidebar}{!admin_users_nav}
+ +
{\$notice} +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {!admin_create_penalty_general_rows} +
{\$lang['create_penalty_langstring']}:
{\$lang['create_penalty_auto_ban']} + +
{\$lang['create_penalty_auto_post']}: + +
{\$lang['create_penalty_requireGroup']}: + +
{\$lang['create_penalty_banGroup']}: + +
{\$lang['create_penalty_newGroup']}: + +
{\$lang['create_penalty_duration']}:
+ +
+ + + + + + + + + + + + + + + + + + {!admin_create_penalty_auto_rows} +
{\$lang['create_penalty_auto_head']}
{\$lang['create_penalty_auto_switch']}: + +
{\$lang['create_penalty_auto_manual_issue']}: + +
{\$lang['create_penalty_auto_points']}:
+ + + + + + + + + + + + + + + + + + + + + {!admin_create_penalty_cascade_rows} +
{\$lang['create_penalty_global_cascade_head']}
+ {\$lang['create_penalty_global_cascade_local_scope']}:
+ ({\$lang['create_penalty_global_cascade_local_scope_desc']}) +
+ +
+ {\$lang['create_penalty_global_cascade_mods_required']}:
+ ({\$lang['create_penalty_global_cascade_mods_required_desc']}) +
{\$lang['create_penalty_global_cascade_area_max']}:
+ +
+
+
+ {\$localPerms}
+
+
+ {\$globalPerms}
+
+ {!admin_create_penalty_tabs_body} +
+
+
+tem +)); + +$db->insert('admin_templates',array( + "name" => 'plugins', + "content" => << + + + + + + + {!admin_plugins_nav} +
{\$lang['side_nav_head']}
+ {\$lang['side_nav_import']} +
{\$lang['side_nav_settings']}
+ +
{\$notice} + + + + {!admin_plugins_head} + + {\$rows} +
{\$lang['plugins_head']}
+
+tem +)); + +$db->insert('admin_templates',array( + "name" => 'plugins_row', + "content" => << + + + + {\$title}{\$author} + {\$version} + {\$desc} + {\$options} + {!admin_plugins_row} + + +tem +)); + +$db->insert('admin_templates',array( + "name" => 'plugins_author', + "content" => "
{\$lang['plugins_row_author']}: {\$author}" +)); + +$db->insert('admin_templates',array( + "name" => 'settings_list', + "content" => << + {\$sidebar}{!admin_settings_nav}
+ +
{\$notice}{\$rows}
+tem +)); + +$db->insert('admin_templates',array( + "name" => 'settings_block', + "content" => << + + + +
{\$sname}
{\$sdesc}
+ +tem +)); + +$db->insert('admin_templates', array( + "name" => 'edit_setting', + "content" => << + {\$sidebar}{!admin_settings_edit_nav}
+ +
{\$notice} +
+ +
+ + + + + + + {\$rows}{!admin_settings_edit_left} +
{\$lang['edit_setting_head']}
{\$lang['edit_setting_name']}:{\$fname}
+
+
+ + + + {!admin_settings_edit_options} + +
{\$lang['edit_setting_options_head']}
{\$desc}
+ +
+
+
+
+tem +)); + +$db->insert('admin_templates',array( + "name" => "edit_setting_row", + "content" => << + {\$sname} + {\$scontent} + +tem +)); + +$db->insert('admin_templates', array( + "name" => 'edit_form', + "content" => << + {\$sidebar}{!admin_edit_forms_nav}
+ +
{\$notice} +
+ +
+ + + + + + + {\$rows}{!admin_edit_forms_left} +
{\$lang['edit_form_head']}
{\$lang['edit_setting_name']}:{\$fname}
+
+
+
+tem +)); + +$db->insert('admin_templates',array( + "name" => 'forums', + "content" => << + {\$sidebar}{!admin_forums_nav}
+ +
{\$notice} +
+ + + + + {!admin_forums_head} + + + {\$rows} +
{\$lang['forums_head']} + +
+
+ + +
+
+
+tem +)); + +$db->insert('admin_templates',array( + "name" => 'forums_category_row', + "content" => << + {\$name} + {!admin_forums_category_row} + + + + + + + + +tem +)); + +$db->insert('admin_templates',array( + "name" => 'forums_forum_row', + "content" => << +   + {\$name} + {\$lang['forums_moderators']} + {!admin_forums_row} + + + + + + + + +tem +)); + +$db->insert('admin_templates',array( + "name" => 'create_forum', + "content" => << + {\$sidebar}{!admin_forums_nav}
+ +
{\$notice} +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {!admin_forums_create_general} +
{\$lang['create_forum_parent']}
{\$lang['create_forum_name']}:
{\$lang['create_forum_desc']}:
{\$lang['create_forum_active']}? + +
{\$lang['create_forum_topic_mod']}: + +
{\$lang['create_forum_post_mod']}: + +
{\$lang['create_forum_order']}:
{\$lang['create_forum_autoexpand']}:
{\$lang['create_forum_stat_counter']}:
{\$lang['create_forum_layout']}:
{\$lang['create_forum_hidden_forum']}:
{\$lang['create_forum_tag']}:
+
+ {if(\$can_edit_permissions)}
+ + + + + +
{\$lang['create_forum_presets']}:
+ + + + + {\$fgroups} + +
{/if} + {!admin_forums_create_left} +
+
+ + + {!admin_forums_create_options} + +
{\$lang['create_forum_options_head']}
+ +
+
+
+ +
+tem +)); + +$db->insert('admin_templates',array( + "name" => 'forum_permissions_group_row', + "content" => << + + {\$fgname} [{\$lang['edit_forum_permissions_groups_row_goto']}] + + + {\$fgalevel} + {\$fginherit} + + + + + + +tem +)); + +$db->insert('admin_templates',array( + "name" => 'forum_permissions_modal', + "content" => <<