Code Coverage |
||||||||||
Classes and Traits |
Functions and Methods |
Lines |
||||||||
Total | |
0.00% |
0 / 1 |
|
0.00% |
0 / 26 |
CRAP | |
0.00% |
0 / 204 |
Template | |
0.00% |
0 / 1 |
|
0.00% |
0 / 26 |
5852 | |
0.00% |
0 / 204 |
__construct( $assoc = null, \aae\ui\ResourceManagerInterface $resourceManager = null, \aae\ui\Escapeable $escaper = null, $load = true ) | |
0.00% |
0 / 1 |
20 | |
0.00% |
0 / 7 |
|||
getTemplate($templateName) | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 3 |
|||
objectSet($object) | |
0.00% |
0 / 1 |
6 | |
0.00% |
0 / 2 |
|||
load($templateName = null) | |
0.00% |
0 / 1 |
20 | |
0.00% |
0 / 13 |
|||
loadFromFile($path) | |
0.00% |
0 / 1 |
6 | |
0.00% |
0 / 7 |
|||
setLocalizer($localizer) | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 2 |
|||
__toString() | |
0.00% |
0 / 1 |
12 | |
0.00% |
0 / 11 |
|||
getBaseDir() | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 1 |
|||
offsetSet($offset, $value) | |
0.00% |
0 / 1 |
6 | |
0.00% |
0 / 3 |
|||
offsetExists($offset) | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 1 |
|||
offsetUnset($offset) | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 2 |
|||
offsetGet($offset) | |
0.00% |
0 / 1 |
6 | |
0.00% |
0 / 1 |
|||
arraySet($array) | |
0.00% |
0 / 1 |
12 | |
0.00% |
0 / 5 |
|||
_collapseArrays() | |
0.00% |
0 / 1 |
30 | |
0.00% |
0 / 13 |
|||
_collapseArray($templateVarName) | |
0.00% |
0 / 1 |
30 | |
0.00% |
0 / 29 |
|||
_insertResourceLinks() | |
0.00% |
0 / 1 |
30 | |
0.00% |
0 / 13 |
|||
_resolveVars($string, $replacements, $escape = false) | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 1 |
|||
_resolveLocalizerVars($string) | |
0.00% |
0 / 1 |
6 | |
0.00% |
0 / 6 |
|||
_insertResources($templateName) | |
0.00% |
0 / 1 |
12 | |
0.00% |
0 / 10 |
|||
_addResource($dependencyName) | |
0.00% |
0 / 1 |
12 | |
0.00% |
0 / 6 |
|||
_getResolvedTemplateDir($templateName) | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 3 |
|||
_getTemplateConfig($templateName) | |
0.00% |
0 / 1 |
30 | |
0.00% |
0 / 10 |
|||
_setConfigConstants($assoc) | |
0.00% |
0 / 1 |
90 | |
0.00% |
0 / 25 |
|||
_buildTemplate($assoc) | |
0.00% |
0 / 1 |
12 | |
0.00% |
0 / 9 |
|||
_buildPath($path) | |
0.00% |
0 / 1 |
6 | |
0.00% |
0 / 5 |
|||
_insertChildren($templateConfig) | |
0.00% |
0 / 1 |
30 | |
0.00% |
0 / 16 |
<?php | |
/** | |
* | |
*/ | |
namespace aae\ui { | |
/** | |
* @author Axel Ancona Esselmann | |
* @package aae\ui | |
*/ | |
class Template implements \ArrayAccess, TemplateInterface { | |
private $_assoc, $_baseDir = "", $_modRewriteDocumentRoot = "", $_resourceManager, $_outputEscaper, $_htmlString = "", $_outputAssoc = [], $_outputAssocUnescaped = [], $_templateName = NULL, $_localizer = NULL, $_varResolver =NULL, $_noTemplate = false; | |
/** | |
* | |
* Template is a Document that can build itself from multiple template | |
* source files. An associative array passed in the constructor dictates | |
* the structure of the final HTML DOM. The document structure is not flat, | |
* elements can have child elements listed in an array with a "children" | |
* key. Those elements are inserted into their respective parent tags | |
* by CSS id. The parent's CSS id's are located in each child's "id" key. | |
* The template files for each element to be loaded should be provided | |
* with a "template" key. | |
* | |
* Unless a "base_dir" is present ( see load() ), paths cant be relative. | |
* Paths start one directory below the document root. | |
* | |
* | |
* The document.html file has a div with a "top" id | |
* and a div with a "main" id. | |
* <body> | |
* <div id="top"></div> | |
* <div id="top"></div> | |
* </body> | |
* | |
* Both, top.html and main.html have valid HTML inside <body> tags. | |
* | |
* { | |
* "template": "/protected/templates/document.html", | |
* "children": | |
* [ | |
* { | |
* "div": "top", | |
* "template": "/protected/templates/top.html" | |
* }, | |
* { | |
* "div": "main", | |
* "template": "/protected/templates/main.html" | |
* } | |
* ] | |
* } | |
* } | |
* | |
* (For readability the associative array is displayed in JSON) | |
* | |
* The example above builds the following document structure: | |
* | |
* <body> | |
* <div id="top"> | |
* <div>Content of child nodes of <body> tag in top.html</div> | |
* </div> | |
* <div id="top"> | |
* <div>Content of child nodes of <body> tag in main.html</div> | |
* </div> | |
* </body> | |
* | |
* | |
* @param array $assoc template configuration | |
* @param boolean $load true build the template during instantiation | |
*/ | |
public function __construct( | |
$assoc = null, | |
\aae\ui\ResourceManagerInterface $resourceManager = null, | |
\aae\ui\Escapeable $escaper = null, | |
$load = true | |
) { | |
$this->_assoc = $assoc; | |
$this->_resourceManager = $resourceManager; | |
if (!is_null($resourceManager) && array_key_exists("css_vars", $this->_assoc)) $this->_resourceManager->setReplacementVars($this->_assoc["css_vars"]); | |
$this->_outputEscaper = $escaper; | |
$this->_varResolver = new \aae\str\VarSubstituter($this->_outputEscaper); | |
if ($load) $this->load(); | |
} | |
public function getTemplate($templateName) { | |
$template = new Template($this->_assoc, $this->_resourceManager, $this->_outputEscaper, true); | |
$template->load($templateName); | |
return $template; | |
} | |
public function objectSet($object) { | |
foreach ($object->toArray() as $varName => $value) $this->_outputAssoc[$varName] = $value; | |
} | |
/** | |
* | |
* The loading of Template from a configuration file can be separated from | |
* instantiation. To take advantage of this feature, pass false as a | |
* second argument to the Template constructor. | |
* | |
* If load() is used, a specific template in the assoc array can be used | |
* to load Template. The structure of the assoc passed to the constructor | |
* should then be as follows: | |
* | |
* { | |
* "theNameOfTheTemplate": { | |
* ... | |
* } | |
* } | |
* | |
* (For readability the associative array is displayed in JSON) | |
* | |
* @param string $templateName the key name of the template to be loaded | |
*/ | |
public function load($templateName = null) { | |
if (is_array($this->_assoc)) { | |
if (is_null($this->_templateName)) { | |
$this->_templateName = $templateName; | |
} | |
$templateConfig = $this->_getTemplateConfig($templateName); | |
$this->_setConfigConstants($this->_assoc); | |
try { | |
$this->_buildTemplate($templateConfig); | |
$this->_insertResources($templateName); | |
$this->_insertChildren($templateConfig); | |
} catch (\aae\fs\FileDoesNotExistException $e) { | |
$this->_noTemplate = true; | |
} | |
} | |
} | |
public function loadFromFile($path) { | |
$extension = ".".basename(dirname($path)); | |
if (substr($path, -strlen($extension)) !== $extension) { | |
$path .= $extension; | |
} | |
$path = new \aae\fs\File($path); | |
$this->_htmlString = file_get_contents($path); | |
} | |
public function setLocalizer($localizer) { | |
$this->_localizer = $localizer; | |
} | |
public function __toString() { | |
if ($this->_noTemplate) { | |
$this->_collapseArrays(); | |
$joined = array_merge($this->_outputAssoc, $this->_outputAssocUnescaped); | |
// var_dump(json_decode(json_encode($joined))); | |
return json_encode($joined); | |
} | |
if (is_null($this->_templateName)) $this->load("DefaultView"); | |
$this->_insertResourceLinks(); | |
$this->_collapseArrays(); | |
$out = $this->_resolveVars($this->_htmlString, $this->_outputAssocUnescaped); | |
$out = $this->_resolveVars($out, $this->_outputAssoc, true); | |
$out = $this->_resolveLocalizerVars($out); | |
return $out; | |
} | |
public function getBaseDir() { | |
return $this->_baseDir; | |
} | |
public function offsetSet($offset, $value) { | |
if (is_null($offset)) throw new \Exception("Provide an offset add to the template.", 1208141630); | |
$this->_outputAssoc[$offset] = $value; | |
} | |
public function offsetExists($offset) { | |
return isset($this->_outputAssoc[$offset]); | |
} | |
public function offsetUnset($offset) { | |
unset($this->_outputAssoc[$offset]); | |
} | |
public function offsetGet($offset) { | |
return isset($this->_outputAssoc[$offset]) ? $this->_outputAssoc[$offset] : null; | |
} | |
public function arraySet($array) { | |
if (!is_array($array)) throw new \Exception("arraySet expects an array of arguments", 204151756); | |
foreach ($array as $key => $value) { | |
$this[$key] = $value; | |
} | |
} | |
private function _collapseArrays() { | |
foreach ($this->_outputAssoc as $varName => $varValue) { | |
if (is_array($varValue)) { | |
$this->_collapseArray($varName); | |
} else { | |
if (is_a($varValue, get_class($this))) { | |
$this->_outputAssoc[$varName] = new \aae\ui\encoding\IsHtml($varValue->__toString()); | |
} else if (is_subclass_of($varValue, "\\aae\\db\\Persistable")) { | |
$objAsArray = $varValue->toArray(); | |
$this->_outputAssoc[$varName] = [$objAsArray]; | |
$this->_collapseArray($varName); | |
} | |
} | |
} | |
} | |
private function _collapseArray($templateVarName) { | |
$replacementElements = []; | |
$subTemplateName = ($this->_templateName)."_".$templateVarName; | |
foreach ($this->_outputAssoc[$templateVarName] as $key => $element) { | |
if (is_subclass_of($element, "\\aae\\db\\Persistable")) { | |
$element = $element->toArray(); | |
} | |
$elementString = $this->_outputEscaper->getArrayElementOpen(); | |
$subTemplate = new Template( | |
$this->_assoc, | |
$this->_resourceManager, | |
$this->_outputEscaper, | |
false | |
); | |
$subTemplate->_baseDir = $this->_baseDir; | |
$subTemplate->load($subTemplateName); | |
if (is_array($element)) { | |
foreach ($element as $varName => $varValue) { | |
$subTemplate[$varName] = $varValue; | |
} | |
} | |
$elementString .= $subTemplate->__toString(); | |
$elementString .= $this->_outputEscaper->getArrayElementClose(); | |
$replacementElements[] = $elementString; | |
} | |
$replacement = $this->_outputEscaper->getArrayOpen(); | |
$replacement .= implode($replacementElements, $this->_outputEscaper->getArrayElementSeparator()); | |
$replacement .= $this->_outputEscaper->getArrayClose(); | |
$this->_outputAssocUnescaped[$templateVarName] = $replacement; | |
unset($this->_outputAssoc[$templateVarName]); | |
} | |
protected function _insertResourceLinks() { | |
$resourceLinks = $this->_resourceManager->getLinks(); | |
$this->_outputAssocUnescaped["cssLinks"] = ""; | |
$this->_outputAssocUnescaped["jsLinks"] = ""; | |
if (count($resourceLinks) > 0) { | |
foreach ($resourceLinks as $link) { | |
if (pathinfo($link, PATHINFO_EXTENSION) == "js") { | |
$this->_outputAssocUnescaped["jsLinks"] .= "\n<script type=\"text/javascript\" src=\"$link\"></script>"; | |
} else if (pathinfo($link, PATHINFO_EXTENSION) == "css") { | |
$this->_outputAssocUnescaped["cssLinks"] .= "\n<link rel=\"stylesheet\" type=\"text/css\" href=\"$link\" />"; | |
} | |
} | |
} | |
} | |
private function _resolveVars($string, $replacements, $escape = false) { | |
return $this->_varResolver->resolveVars($string, $replacements, $escape); | |
} | |
private function _resolveLocalizerVars($string) { | |
if (is_null($this->_localizer)) return $string; | |
return $this->_varResolver->resolveVars( | |
$string, | |
$this->_localizer->localizeAll(), | |
true, | |
"@" | |
); | |
} | |
private function _insertResources($templateName) { | |
if (!is_null($templateName)) { | |
$viewPos = strpos($templateName, "View"); | |
if ($viewPos) { | |
$jsDependencyName = substr($templateName, 0, $viewPos)."JS"; | |
$this->_addResource($jsDependencyName); | |
$cssDependencyName = substr($templateName, 0, $viewPos)."CSS"; | |
$this->_addResource($cssDependencyName); | |
} | |
} | |
} | |
private function _addResource($dependencyName) { | |
if (array_key_exists($dependencyName, $this->_assoc)) { | |
foreach ($this->_assoc[$dependencyName] as $dependency) { | |
$this->_resourceManager->addResource($dependency); | |
} | |
} | |
} | |
private function _getResolvedTemplateDir($templateName) { | |
$extension = ".".basename($this->_baseDir); | |
$path = new \aae\fs\File($this->_baseDir.$templateName.$extension); | |
return $path; | |
} | |
private function _getTemplateConfig($templateName) { | |
if (!is_null($templateName)) { | |
if (!array_key_exists($templateName, $this->_assoc)) { | |
try { | |
$path = $this->_getResolvedTemplateDir($templateName); | |
if (file_exists($path)) { | |
return ["template" => $templateName]; | |
} | |
} catch (\aae\fs\FileDoesNotExistException $e) { | |
return ["template" => false]; | |
// throw new \aae\fs\FileDoesNotExistException("No entry for template $templateName in the template configuration file.", 225141923); | |
} | |
} | |
return $this->_assoc[$templateName]; | |
} else { | |
return $this->_assoc; | |
} | |
} | |
private function _setConfigConstants($assoc) { | |
if (array_key_exists("base_dir", $assoc)) { | |
$this->_baseDir = $assoc["base_dir"]; | |
} | |
if (array_key_exists("mod_rewrite_document_root", $assoc)) { | |
$this->_modRewriteDocumentRoot = $assoc["mod_rewrite_document_root"]; | |
} | |
if (!is_null($this->_resourceManager)) { | |
if (array_key_exists("js_base_dir", $assoc)) { | |
$this->_resourceManager->addJsBaseDir($assoc["js_base_dir"]); | |
} | |
if (array_key_exists("js_model_dir", $assoc)) { | |
$this->_resourceManager->addJsBaseDir($assoc["js_model_dir"]); | |
} | |
if (array_key_exists("css_base_dir", $assoc)) { | |
$this->_resourceManager->addCssBaseDir($assoc["css_base_dir"]); | |
} | |
if (array_key_exists("css_model_dir", $assoc)) { | |
$this->_resourceManager->addCssBaseDir($assoc["css_model_dir"]); | |
} | |
} | |
if (!is_null($this->_resourceManager)) { | |
$this->_resourceManager->setBaseDir($this->_baseDir); | |
$this->_resourceManager->setModRewriteDocumentRoot($this->_modRewriteDocumentRoot); | |
} | |
} | |
private function _buildTemplate($assoc) { | |
if (array_key_exists("template", $assoc)) { | |
$templateDir = $assoc["template"]; | |
$templateDir = $this->_buildPath($templateDir); | |
$this->loadFromFile($templateDir); | |
} else if (array_key_exists("view", $assoc)) { | |
$templateConfig = $assoc["view"]; | |
$this->load($templateConfig); | |
} | |
} | |
private function _buildPath($path) { | |
if ($path[0] != "/") { | |
$path = $this->_baseDir.$path; | |
} else { | |
$path = substr($path, 1); | |
} | |
return $path; | |
} | |
private function _insertChildren($templateConfig) { | |
if (array_key_exists("children", $templateConfig)) { | |
foreach ($templateConfig["children"] as $child) { | |
$childTemplate = new Template($this->_assoc, $this->_resourceManager, $this->_outputEscaper, false); | |
if (array_key_exists("view", $child)) { | |
$childTemplate->load($child["view"]); | |
$childDiv = $child["id"]; | |
$this->_htmlString = $this->_resolveVars($this->_htmlString, [$childDiv => $childTemplate->_htmlString]); | |
} else if (array_key_exists("template", $child)) { | |
// throw new \Exception("Not implemented!!!!", 1); | |
$child["base_dir"] = $this->_baseDir; | |
$childTemplate = new Template($child, null, $this->_outputEscaper); | |
$childDiv = $child["id"]; | |
$this->_htmlString = $this->_resolveVars($this->_htmlString, [$childDiv => $childTemplate->_htmlString]); | |
//$this->insertHtmlAtId($childTemplate, $childDiv, false); | |
} | |
} | |
} | |
} | |
} | |
} |