Mercurial > SimpleWebPresenter
view InputParser.inc @ 107:d5f3efba33e2
Support for common files between languages.
| author | Tom Fredrik "BFG" Klaussen <bfg@blenning.no> |
|---|---|
| date | Mon, 07 Mar 2016 20:44:15 +0100 |
| parents | b6381903122e |
| children | adf7b11921f4 b9668126e52e |
line wrap: on
line source
<?php /// @cond $baseDir = dirname(__FILE__); $cache = ScriptIncludeCache::instance(__FILE__); $cache->includeOnce('Page.inc', dirname(__FILE__)); /// @endcond /** * Functionality for translating an XML configuration document into a webpage */ class InputParser extends Page { private $options; private $master; /** * Constructs a new InputParser object * * @param $name name of file to read configuration from * * @param $masterCache CacheTimeCheck cache object to use as parent * for this inputParsercache */ function __construct($name, $masterCache) { $this->master = new DOMDocument(); $cache = new CacheTimeCheck($name); $cache->addParent($masterCache); parent::setCache($cache); $this->master->load($name); $this->options = new Options($this->master); $this->options->setCache($cache); $this->options->setBasePath(basePath()); $this->options->setCacheable(true); $this->options->setUrlParams(array('name', 'lang')); if(array_key_exists('lang', $_GET) && $_GET['lang']) { $this->options->setLang($_GET['lang']); } else { if (count($this->options->getAcceptedLanguages()) > 1) $this->addVariant('Accept-Language'); $this->options->setLang($this->options->getDefaultLang()); } if(array_key_exists('name', $_GET) && $_GET['name']) { $this->options->setName($_GET['name']); } $params = $this->master->getElementsByTagName("param"); foreach ($params as $param) { if ($param->getAttribute("type") == "input") { $doc = self::getInput($this->master, $param, $this->options); $parent = $param->parentNode; foreach ($doc->firstChild->childNodes as $child) { $clonedChild = $this->master->importNode($child, true); $parent->insertBefore($clonedChild, $param); } $parent->removeChild($param); } } $this->master = self::getFiles($this->master, $this->options); $cache->setMaxAge(20); } function cacheCheck() { return $this->options->getCacheable(); } /** * Generate an appropriate response for this page, eg. 302 NOT * MODIFIED or the actual page */ function generateContent() { //We may need to set and check the contenttype and replace //saveHTML with saveXML $retVal = new PageContent($this->master->saveHTML($this->master)); $retVal->setHeader('Content-Language', $this->options->getLang()); return $retVal; } /** * Extracts data from a @<param@> tag. * * @param $param the param tag * * @return if the type is array, return an array, otherwise return a * scalar */ static function getParam($param) { $param_type = $param->getAttribute("type"); $param_value; if (! $param_type) $param_type = "scalar"; if($param_type == "scalar") { $param_subst = $param->getAttribute("subst"); $param_value = $param->getAttribute("value"); if ($param_subst) { /* $param_value=preg_replace("/name/", $name, $param_subst); $param_value=preg_replace('/lang/', $lang, $param_value); */ } } elseif($param_type == "array") { $params = $param->getElementsByTagName("param"); $param_value = array(); foreach ($param->childNodes as $param) { if ($param->nodeType == XML_ELEMENT_NODE) { array_push($param_value, self::getParam($param)); } } } return $param_value; } /** * This is the last processing stage for generating a file. * * @param $doc the document to be worked upon * @param $options an Options object for this file. * * @return This is the same as the input document, fully processed */ static function getFiles($doc, $options) { $lang = $options->getLang(); $conf = $options->getName(); $toRemove = array(); $topLevelTags = $doc->getElementsByTagName("toplevel"); foreach ($topLevelTags as $topLevel) { $topLevel->parentNode->removeChild($topLevel); } $valueDict = array(); $fragments = array(); $setters = $doc->getElementsByTagName("set"); foreach ($setters as $setTag) { $key = $setTag->getAttribute("id"); $type = $setTag->getAttribute("type"); if ($type == "fragment") { $fragments[$key] = $setTag; } else { $value = $setTag->getAttribute("value"); if ($key && $value) { $valueDict[$key] = $value; } } //We need to iterate in the opposite direction when removing, //so best shifting. array_unshift($toRemove, $setTag); } $params = $doc->getElementsByTagName("param"); foreach ($params as $param) { if ($param->getAttribute("type")=="input_config") { $id = $param->getAttribute("id"); if (array_key_exists($id, $valueDict)) { $value = $valueDict[$id]; $tmp = new DOMDocument(); $tmp->loadXml("<xml>${value}</xml>"); $parent = $param->parentNode; $parent->insertBefore(new DOMText($tmp->textContent), $param); //We need to iterate in the opposite direction when removing, //so best shifting. array_unshift($toRemove, $param); } elseif (array_key_exists($id, $fragments)) { $fragment = $fragments[$id]; $cloneFragment = $fragment->cloneNode(true); $insNode = $param; for ($i = $cloneFragment->childNodes->length - 1; $i >= 0; $i--) { $child = $cloneFragment->childNodes->item($i); $child = $child->parentNode->removeChild($child); $insNode = $insNode->parentNode->insertBefore($child, $insNode); } //We need to iterate in the opposite direction when removing, //so best shifting. array_unshift($toRemove, $param); } } } foreach($toRemove as $param) { $parent = $param->parentNode; $parent->removeChild($param); } $body = getElementByTagName($doc,"body"); $files = $body->getElementsByTagName("file"); $toRemove = array(); foreach ($files as $file) { $script = $file->getAttribute("script"); if ($script) { $options->setCacheable(false); $src=""; $cwd = getcwd(); $matches=array(); preg_match('/(.*\/)/', $script, $matches); $dirname=$matches[0]; preg_match('/([^\/]*)$/', $script, $matches); $filename=$matches[0]; chdir("${lang}/${dirname}"); $pipe=popen("php ${filename}","r"); $file_content = stream_get_contents($pipe); chdir("${cwd}"); } else { $src = $file->getAttribute("src"); $fname = $options->getBasePath() . "/${lang}/${src}"; if (!file_exists($fname) ) { $fname = $options->getBasePath() . "/common/${src}"; } $file_content = $options->getCache()->loadFile($fname); } if(floatval($file_content)<0) { errorPage("Resource not found '${lang}/${src}'"); } $filters = $file->getElementsByTagName("filter"); foreach($filters as $filter) { $func = $filter->getAttribute("function"); $params = $filter->getElementsByTagName("param"); $callString = "\$file_content = ${func}(\$file_content, \$options"; $param_values = array(); $i = 0; foreach ($filter->childNodes as $param) { if ($param->nodeType == XML_ELEMENT_NODE) { $param_value[$i] = self::getParam($param); $callString .= ",\$param_value[$i]"; $i++; } } $callString .= ");"; eval($callString); } $ndoc = new DOMDocument(); $ndoc->loadXml("<xml>${file_content}</xml>"); $parent = $file->parentNode; foreach ($ndoc->firstChild->childNodes as $child) { $clonedChild = $doc->importNode($child, true); $parent->insertBefore($clonedChild, $file); } //We need to iterate in the opposite direction when removing, //so best shifting. array_unshift($toRemove, $file); } foreach($toRemove as $param) { $parent = $param->parentNode; $parent->removeChild($param); } return $doc; } /** * Follows all include directives recursively for the specified * $param an generates an xml file. * * This function may be used to generate a file which has all the * necessary information to determine wether or not we may cache. * * @param $master The master document to be processed * @param $param the input tag to resolve * @param $options the options object for this file */ function getInput($master, $param, $options) { $lang = $options->getLang(); $name = $param->getAttribute("id"); $conf = $options->getName(); if (!$conf) $conf = $param->getAttribute("default"); $confFile = $options->getBasePath() . "/${lang}/${conf}.xml"; if (! file_exists($confFile) ) { $confFile = $options->getBasePath() . "/common/${conf}.xml"; } $options->getCache()->cache_time($confFile); $doc = new DOMDocument(); $doc->load($confFile); $toplevel = $doc->getElementsByTagName("toplevel"); if(! $toplevel->length) { errorPage("Resource '${conf}' is not available", 500); } $includes = $doc->getElementsByTagName("include"); $recurse = 0; while($includes->length > 0) { if(++$recurse > MAX_RECURSE) { errorPage('Recursion limit exceeded', 500); } foreach ($includes as $include) { $src = $include->getAttribute("src"); $subdoc = new DOMDocument(); $subfile = $options->getBasePath() . "/${lang}/${src}"; if (! file_exists($subfile) ) { $subfile = $options->getBasePath() . "/common/${src}"; } $subdoc->load("$subfile"); $options->getCache()->cache_time($subfile); $parent = $include->parentNode; $xml = getElementByTagName($subdoc,"xml"); foreach($xml->childNodes as $child) { $text = $subdoc->saveHTML($child); $clonedChild = $doc->importNode($child,true); $parent->insertBefore($clonedChild,$include); } $parent->removeChild($include); } $includes = $doc->getElementsByTagName("include"); } return $doc; } } ?>
