diff --git a/tests/webfiori/test/ui/LoadTemplateTest.php b/tests/webfiori/test/ui/LoadTemplateTest.php
index 630602b..8f3fa15 100644
--- a/tests/webfiori/test/ui/LoadTemplateTest.php
+++ b/tests/webfiori/test/ui/LoadTemplateTest.php
@@ -17,7 +17,8 @@ class LoadTemplateTest extends TestCase {
* @test
*/
public function test00() {
- $this->expectException('Exception');
+ $this->expectException(\InvalidArgumentException::class);
+ $this->expectExceptionMessage('Empty template path');
$compiler = new TemplateCompiler('');
}
/**
@@ -112,6 +113,28 @@ public function test07() {
$node = $compiler->getCompiled();
$this->assertEquals("
\n No posts.\n
", $node->toHTML());
}
+ /**
+ * @test
+ */
+ public function test08() {
+ $compiler = new TemplateCompiler('template.php', [
+ 'message' => 'Good Job!',
+ 'posts' => [
+ 'One',
+ 'Two',
+ 'Three'
+ ]]);
+ $this->assertEquals(""
+ . "
"
+ . "- One
"
+ . "- Two
"
+ . "- Three
"
+ . "
"
+ . "
\n"
+ . " Good Job!"
+ . "
"
+ . "
", $compiler->getCompiled()->toHTML());
+ }
/**
* @test
*/
@@ -179,7 +202,7 @@ public function testHeadTemplate04() {
*/
public function testAddChildFromTemplate00() {
$node = new HTMLNode();
- $node->component(self::TEST_TEMPLATES_PATH.'component-00.html', [
+ $node->include(self::TEST_TEMPLATES_PATH.'component-00.html', [
'base' => 'https://example.com',
'home-label' => 'Home Page',
'about-label' => 'About Us',
diff --git a/tests/webfiori/test/ui/sub-component.php b/tests/webfiori/test/ui/sub-component.php
new file mode 100644
index 0000000..1b24761
--- /dev/null
+++ b/tests/webfiori/test/ui/sub-component.php
@@ -0,0 +1,3 @@
+
+ = $message?>
+
diff --git a/tests/webfiori/test/ui/template.php b/tests/webfiori/test/ui/template.php
new file mode 100644
index 0000000..18ccbec
--- /dev/null
+++ b/tests/webfiori/test/ui/template.php
@@ -0,0 +1,18 @@
+
diff --git a/webfiori/ui/CodeSnippet.php b/webfiori/ui/CodeSnippet.php
index 581fa96..f81db5e 100644
--- a/webfiori/ui/CodeSnippet.php
+++ b/webfiori/ui/CodeSnippet.php
@@ -37,7 +37,6 @@
* @version 1.0.3
*/
class CodeSnippet extends HTMLNode {
-
private $code;
private $codeDisplay;
@@ -250,12 +249,12 @@ private function addLineHelper() {
$span = new HTMLNode('span');
$span->setClassName('line-number');
$span->setAttribute('style',
- 'font-weight: bold;'
- .'display: block;'
- .'font-family: monospace;'
- .'border-right: 1px dotted white;'
- .'padding-right: 4px;'
- .'color: #378e80;');
+ 'font-weight: bold;'
+ .'display: block;'
+ .'font-family: monospace;'
+ .'border-right: 1px dotted white;'
+ .'padding-right: 4px;'
+ .'color: #378e80;');
$span->addTextNode($this->currentLineNum);
$this->currentLineNum++;
$this->lineNumsNode->addChild($span);
diff --git a/webfiori/ui/HTMLNode.php b/webfiori/ui/HTMLNode.php
index e92955a..ef064e8 100644
--- a/webfiori/ui/HTMLNode.php
+++ b/webfiori/ui/HTMLNode.php
@@ -698,9 +698,9 @@ public function comment(string $txt) {
* @throws TemplateNotFoundException If the file that the component is
* loaded from does not exist.
*
- *
+ * @deprecated Use HTMLNode::include()
*/
- public function component(string $path, array $slotsValues) {
+ public function component(string $path, array $slotsValues = []) {
$loaded = self::fromFile($path, $slotsValues);
if (gettype($loaded) == 'array') {
@@ -719,7 +719,6 @@ public function component(string $path, array $slotsValues) {
*
* @return int The number of child nodes attached to the node.
*
- *
*/
public function count() : int {
return $this->childrenCount();
@@ -825,8 +824,9 @@ public function form(array $attributes = []) : HTMLNode {
*
* @throws TemplateNotFoundException
*/
- public static function fromFile(string $absPath, array $slotsOrVars) {
+ public static function fromFile(string $absPath, array $slotsOrVars = []) {
$compiler = new TemplateCompiler($absPath, $slotsOrVars);
+
return $compiler->getCompiled();
}
@@ -1219,6 +1219,33 @@ public function img(array $attributes = []) : HTMLNode {
return $this->addChild($img);
}
+ /**
+ * Loads HTML-like or PHP component and make it a child of current node.
+ *
+ * This method can be used to load any component that uses HTML syntax
+ * into an object and make it a child of the instance at which the method is
+ * called in. If the component file contains more than one node as a root note,
+ * all nodes will be added as children.
+ *
+ * @param string $path The location of the file that
+ * will have the HTML component.
+ *
+ * @param array $values An array that contains slots values or variables
+ * to be passed to PHP template. A slot in
+ * the component is a string which is enclosed between two curly braces (such as {{name}}).
+ * This array must be associative. The indices of the array are slots names
+ * and values of the indices are slots values. The values of the slots can be
+ * also sub-array that contains more values. For example, if we
+ * have a slot with the name {{ user-name }}, then the array can have the
+ * index 'user-name' with the value of the slot.
+ *
+ * @throws TemplateNotFoundException If the file that the component is
+ * loaded from does not exist.
+ *
+ */
+ public function include(string $path, array $values = []) {
+ $this->component($path, $values);
+ }
/**
* Adds new input (<input>, <select> or <textarea>)
* element as a child to the body of the node.
@@ -1950,7 +1977,6 @@ public function setNodeName(string $name) : bool {
*
*/
public function setStyle(array $cssStyles, bool $override = false) : HTMLNode {
-
if (!$override) {
$styleArr = $this->getStyle();
} else {
@@ -2664,8 +2690,7 @@ private function validateAttrNameHelper(string $name) : bool {
*
*
*/
- private function validateFormattingOptions(array $FO): array
- {
+ private function validateFormattingOptions(array $FO): array {
$defaultFormat = self::DEFAULT_CODE_FORMAT;
foreach ($defaultFormat as $key => $value) {
diff --git a/webfiori/ui/HeadNode.php b/webfiori/ui/HeadNode.php
index f42fc0b..d52be1c 100644
--- a/webfiori/ui/HeadNode.php
+++ b/webfiori/ui/HeadNode.php
@@ -215,27 +215,6 @@ public function addChild($node, $attrsOrChain = [], bool $chainOnParent = true)
}
- return $this;
- }
- /**
- * Add multiple CSS resources files.
- *
- * @param array $files An array that holds paths to CSS files. This also
- * can be an associative array. In this case, the indices are paths to files
- * and the value of each index is a sub associative array of attributes.
- *
- * @return HeadNode The method will return the instance at which the method
- * is called on.
- */
- public function addCSSFiles(array $files) : HeadNode {
- foreach ($files as $index => $options) {
- if (gettype($index) == 'integer') {
- $this->addCSS($options);
- } else {
- $this->addCSS($index, $options);
- }
- }
-
return $this;
}
/**
@@ -306,24 +285,24 @@ public function addCSS(string $href, array $otherAttrs = []) : HeadNode {
return $this;
}
/**
- * Add multiple JS resources files.
+ * Add multiple CSS resources files.
*
- * @param array $files An array that holds paths to JS files. This also
+ * @param array $files An array that holds paths to CSS files. This also
* can be an associative array. In this case, the indices are paths to files
* and the value of each index is a sub associative array of attributes.
*
* @return HeadNode The method will return the instance at which the method
* is called on.
*/
- public function addJSFiles(array $files) : HeadNode {
+ public function addCSSFiles(array $files) : HeadNode {
foreach ($files as $index => $options) {
if (gettype($index) == 'integer') {
- $this->addJs($options);
+ $this->addCSS($options);
} else {
- $this->addJs($index, $options);
+ $this->addCSS($index, $options);
}
}
-
+
return $this;
}
/**
@@ -396,6 +375,27 @@ public function addJs(string $loc, array $otherAttrs = []) : HeadNode {
return $this;
}
+ /**
+ * Add multiple JS resources files.
+ *
+ * @param array $files An array that holds paths to JS files. This also
+ * can be an associative array. In this case, the indices are paths to files
+ * and the value of each index is a sub associative array of attributes.
+ *
+ * @return HeadNode The method will return the instance at which the method
+ * is called on.
+ */
+ public function addJSFiles(array $files) : HeadNode {
+ foreach ($files as $index => $options) {
+ if (gettype($index) == 'integer') {
+ $this->addJs($options);
+ } else {
+ $this->addJs($index, $options);
+ }
+ }
+
+ return $this;
+ }
/**
* Adds new 'link' node.
* Note that if the 'rel' attribute value is 'canonical' or 'alternate', no node will be
@@ -451,18 +451,6 @@ public function addLink(string $rel, string $href, array $otherAttrs = []) : Hea
return $this;
}
- /**
- * Adds a set of meta tags.
- *
- * @param array $tags An associative array. The indices of the array
- * are the values of the attribute 'name' and the value of the index is
- * the value of the attribute 'content'.
- */
- public function addMetaTags(array $tags) {
- foreach ($tags as $name => $content) {
- $this->addMeta($name, $content);
- }
- }
/**
* Adds new meta tag.
*
@@ -514,6 +502,18 @@ public function addMeta(string $name, string $content, bool $override = false) :
return $this;
}
+ /**
+ * Adds a set of meta tags.
+ *
+ * @param array $tags An associative array. The indices of the array
+ * are the values of the attribute 'name' and the value of the index is
+ * the value of the attribute 'content'.
+ */
+ public function addMetaTags(array $tags) {
+ foreach ($tags as $name => $content) {
+ $this->addMeta($name, $content);
+ }
+ }
/**
* Returns a linked list of all alternate nodes that was added to the header.
*
diff --git a/webfiori/ui/Input.php b/webfiori/ui/Input.php
index 2af9d40..a7427c8 100644
--- a/webfiori/ui/Input.php
+++ b/webfiori/ui/Input.php
@@ -163,8 +163,7 @@ public function addChild($node, $attrsOrChain = [], bool $chainOnParent = true)
*
* @since 1.0.1
*/
- public function addOption(array $options = []): Input
- {
+ public function addOption(array $options = []): Input {
if ($this->getNodeName() == 'select' && gettype($options) == 'array' && isset($options['value']) && isset($options['label'])) {
$option = new HTMLNode('option');
$option->setAttribute('value', $options['value']);
@@ -202,8 +201,7 @@ public function addOption(array $options = []): Input
*
* @since 1.0.1
*/
- public function addOptions(array $arrayOfOpt): Input
- {
+ public function addOptions(array $arrayOfOpt): Input {
if (gettype($arrayOfOpt) == 'array') {
foreach ($arrayOfOpt as $value => $lblOrOptions) {
if (gettype($lblOrOptions) == 'array') {
@@ -249,8 +247,7 @@ public function addOptions(array $arrayOfOpt): Input
* is called on.
* @since 1.0.1
*/
- public function addOptionsGroup(array $optionsGroupArr): Input
- {
+ public function addOptionsGroup(array $optionsGroupArr): Input {
if ($this->getNodeName() == 'select' && gettype($optionsGroupArr) == 'array' && isset($optionsGroupArr['label']) && isset($optionsGroupArr['options'])) {
$optGroup = new HTMLNode('optgroup');
$optGroup->setAttribute('label', $optionsGroupArr['label']);
@@ -382,8 +379,7 @@ public function setMin(int $min) : Input {
*
* @since 1.0
*/
- public function setMinLength(int $length): Input
- {
+ public function setMinLength(int $length): Input {
if ($length >= 0) {
$iType = $this->getType();
@@ -426,8 +422,7 @@ public function setNodeName(string $name) : bool {
* @return Input The method will return the instance at which the method
* is called on.
*/
- public function setPlaceholder(string $text = null): Input
- {
+ public function setPlaceholder(string $text = null): Input {
if ($text !== null) {
$iType = $this->getType();
@@ -491,6 +486,7 @@ private function addOptionsToGroupHelper($optionsGroupArr, $optGroup) {
foreach ($optionsGroupArr['options'] as $value => $labelOrOptions) {
$o = new HTMLNode('option');
$o->setAttribute('value', $value);
+
if (gettype($labelOrOptions) == 'array' && isset($labelOrOptions['label'])) {
$o->addTextNode($labelOrOptions['label'],false);
diff --git a/webfiori/ui/TemplateCompiler.php b/webfiori/ui/TemplateCompiler.php
index feeac64..6250a93 100644
--- a/webfiori/ui/TemplateCompiler.php
+++ b/webfiori/ui/TemplateCompiler.php
@@ -10,6 +10,7 @@
*/
namespace webfiori\ui;
+use InvalidArgumentException;
use webfiori\collections\Queue;
use webfiori\ui\exceptions\InvalidNodeNameException;
use webfiori\ui\exceptions\TemplateNotFoundException;
@@ -50,12 +51,29 @@ class TemplateCompiler {
* @throws InvalidNodeNameException
*/
public function __construct(string $templatePath, array $vars = []) {
- if (!file_exists($templatePath)) {
- throw new TemplateNotFoundException('No file was found at "'.$templatePath.'".');
+ $trimmedPath = trim($templatePath);
+
+ if (strlen($trimmedPath) == 0) {
+ throw new InvalidArgumentException('Empty template path');
+ }
+
+ if (!file_exists($trimmedPath)) {
+ $possibleLocations = self::getCallingFilesPaths();
+
+ foreach ($possibleLocations as $dir) {
+ if (file_exists($dir.$trimmedPath)) {
+ $trimmedPath = $dir.$trimmedPath;
+ break;
+ }
+ }
+
+ if (!file_exists($trimmedPath)) {
+ throw new TemplateNotFoundException('No file was found at "'.$trimmedPath.'".');
+ }
}
- $extArr = explode('.', $templatePath);
+ $extArr = explode('.', $trimmedPath);
$this->tType = strtolower($extArr[count($extArr) - 1]);
- $this->path = $templatePath;
+ $this->path = $trimmedPath;
$this->rawOutput = '';
$this->compile($vars);
}
@@ -154,7 +172,6 @@ public static function fromHTMLText(string $text, bool $asHTMLDocObj = true) {
}
} else {
if (count($nodesArr) != 1) {
-
foreach ($nodesArr as $node) {
$asHtmlNode = self::fromHTMLTextHelper00($node);
$retVal[] = $asHtmlNode;
@@ -169,6 +186,37 @@ public static function fromHTMLText(string $text, bool $asHTMLDocObj = true) {
return null;
}
+ /**
+ * Returns an array that contains directories names of the calling files.
+ *
+ * This method is used to extract the pathes of files at which they called
+ * this method.
+ *
+ * @return array An array that contains directories names of the calling files.
+ */
+ public static function getCallingFilesPaths() : array {
+ $debugTrace = debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT, 15);
+ $retVal = [];
+
+ foreach ($debugTrace as $traceEntry) {
+ if (isset($traceEntry['file'])) {
+ $file = $traceEntry['file'];
+ $split = explode(DIRECTORY_SEPARATOR, $file);
+ $withoutFile = array_diff($split, [$split[count($split) - 1]]);
+ $dir = implode(DIRECTORY_SEPARATOR, $withoutFile);
+
+ if (strlen($dir) != 0) {
+ $dir .= DIRECTORY_SEPARATOR;
+
+ if (!in_array($dir, $retVal)) {
+ $retVal[] = $dir;
+ }
+ }
+ }
+ }
+
+ return $retVal;
+ }
/**
* Returns the compiled template.
*