Fix for double inserting of template code
[shipsimu.git] / inc / classes / main / template / class_TemplateEngine.php
index 74542634f7466235ec2e3b87e8a5547df81c6ce3..20984c2fe181ddb40b6f309525060fc04aaec9b2 100644 (file)
@@ -4,10 +4,10 @@
  * and emails.
  *
  * @author             Roland Haeder <webmaster@mxchange.org>
- * @version            0.3.0
+ * @version            0.0.0
  * @copyright  Copyright(c) 2007, 2008 Roland Haeder, this is free software
  * @license            GNU GPL 3.0 or any newer version
- * @link               http://www.mxchange.org
+ * @link               http://www.ship-simu.org
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -20,7 +20,7 @@
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 class TemplateEngine extends BaseFrameworkSystem implements CompileableTemplate {
        /**
@@ -71,11 +71,6 @@ class TemplateEngine extends BaseFrameworkSystem implements CompileableTemplate
         */
        private $configVariables = array();
 
-       /**
-        * The language instance which should link to an object of LanguageSystem
-        */
-       private $langInstance = null;
-
        /**
         * Loaded templates for recursive protection and detection
         */
@@ -108,21 +103,27 @@ class TemplateEngine extends BaseFrameworkSystem implements CompileableTemplate
         */
        private $regExpCodeTags = '/\{\?([a-z_]+)(:("[^"]+"|[^?}]+)+)?\?\}/';
 
+       /**
+        * Loaded helpers
+        */
+       private $helpers = array();
+
        // Exception codes for the template engine
        const EXCEPTION_TEMPLATE_TYPE_IS_UNEXPECTED   = 0xa00;
-       const TEMPLATE_CONTAINS_INVALID_VAR_EXCEPTION = 0xa01;
+       const EXCEPTION_TEMPLATE_CONTAINS_INVALID_VAR = 0xa01;
+       const EXCEPTION_INVALID_VIEW_HELPER           = 0xa02;
 
        /**
-        * Private constructor
+        * Protected constructor
         *
         * @return      void
         */
-       private final function __construct () {
+       protected function __construct () {
                // Call parent constructor
-               parent::constructor(__CLASS__);
+               parent::__construct(__CLASS__);
 
                // Set part description
-               $this->setPartDescr("Template-Engine");
+               $this->setObjectDescription("Template-Engine");
 
                // Create unique ID number
                $this->createUniqueID();
@@ -135,18 +136,18 @@ class TemplateEngine extends BaseFrameworkSystem implements CompileableTemplate
        /**
         * Creates an instance of the class TemplateEngine and prepares it for usage
         *
-        * @param               $basePath               The local base path for all templates
-        * @param               $langInstance   An instance of LanguageSystem (default)
-        * @param               $ioInstance     An instance of FileIOHandler (default, middleware!)
+        * @param       $basePath               The local base path for all templates
+        * @param       $langInstance   An instance of LanguageSystem (default)
+        * @param       $ioInstance             An instance of FileIOHandler (default, middleware!)
         * @return      $tplInstance    An instance of TemplateEngine
         * @throws      BasePathIsEmptyException                If the provided $basePath is empty
         * @throws      InvalidBasePathStringException  If $basePath is no string
         * @throws      BasePathIsNoDirectoryException  If $basePath is no
-        *                                                                              directory or not found
+        *                                                                                      directory or not found
         * @throws      BasePathReadProtectedException  If $basePath is
-        *                                                                              read-protected
+        *                                                                                      read-protected
         */
-       public final static function createTemplateEngine ($basePath, $langInstance, $ioInstance) {
+       public final static function createTemplateEngine ($basePath, ManageableLanguage  $langInstance, FileIOHandler $ioInstance) {
                // Get a new instance
                $tplInstance = new TemplateEngine();
 
@@ -176,7 +177,7 @@ class TemplateEngine extends BaseFrameworkSystem implements CompileableTemplate
 
                // Set the language and IO instances
                $tplInstance->setLanguageInstance($langInstance);
-               $tplInstance->setIOInstance($ioInstance);
+               $tplInstance->setFileIOInstance($ioInstance);
 
                // Set template extensions
                $tplInstance->setRawTemplateExtension($cfgInstance->readConfig("raw_template_extension"));
@@ -193,7 +194,7 @@ class TemplateEngine extends BaseFrameworkSystem implements CompileableTemplate
         * Search for a variable in the stack
         *
         * @param               $var            The variable we are looking for
-        * @return      $idx            FALSE means not found, > 0 means found on a specific index
+        * @return      $idx            FALSE means not found, >=0 means found on a specific index
         */
        private function isVariableAlreadySet ($var) {
                // First everything is not found
@@ -216,6 +217,33 @@ class TemplateEngine extends BaseFrameworkSystem implements CompileableTemplate
                return $found;
        }
 
+       /**
+        * Return a content of a variable or null if not found
+        *
+        * @param       $var            The variable we are looking for
+        * @return      $content        Content of the variable or null if not found
+        */
+       private function readVariable ($var) {
+               // First everything is not found
+               $content = null;
+
+               // Now search for it
+               for ($idx = $this->varStack->getIterator(); $idx->valid(); $idx->next()) {
+                       // Get current item
+                       $currEntry = $idx->current();
+
+                       // Is the entry found?
+                       if ($currEntry['name'] == $var) {
+                               // Found!
+                               $content = $currEntry['value'];
+                               break;
+                       }
+               }
+
+               // Return the current position
+               return $content;
+       }
+
        /**
         * Add a variable to the stack
         *
@@ -265,35 +293,6 @@ class TemplateEngine extends BaseFrameworkSystem implements CompileableTemplate
                $this->varStack = new FrameworkArrayObject();
        }
 
-       /**
-        * Setter for language instance which should be LanguageSystem
-        *
-        * @param               $langInstance           The language instance
-        * @return      void
-        */
-       public final function setLanguageInstance (ManageableLanguage $langInstance) {
-               $this->langInstance = $langInstance;
-       }
-
-       /**
-        * Setter for file I/O instance which should be FileIOHandler
-        *
-        * @param               $ioInstance             The file I/O instance
-        * @return      void
-        */
-       public final function setIOInstance (FileIOHandler $ioInstance) {
-               $this->ioInstance = $ioInstance;
-       }
-
-       /**
-        * Getter for file I/O instance which should be FileIOHandler
-        *
-        * @return      $ioInstance             The file I/O instance
-        */
-       public final function getIOInstance () {
-               return $this->ioInstance;
-       }
-
        /**
         * Setter for base path
         *
@@ -527,7 +526,7 @@ class TemplateEngine extends BaseFrameworkSystem implements CompileableTemplate
                // Construct the FQFN for the template by honoring the current language
                $fqfn = sprintf("%s%s/%s/%s%s",
                        $this->getBasePath(),
-                       $this->langInstance->getLanguageCode(),
+                       $this->getLanguageInstance()->getLanguageCode(),
                        $this->getTemplateType(),
                        $template,
                        $ext
@@ -556,7 +555,7 @@ class TemplateEngine extends BaseFrameworkSystem implements CompileableTemplate
                ));
 
                // Get a input/output instance from the middleware
-               $ioInstance = $this->getIOInstance();
+               $ioInstance = $this->getFileIOInstance();
 
                // Validate the instance
                if (is_null($ioInstance)) {
@@ -608,11 +607,11 @@ class TemplateEngine extends BaseFrameworkSystem implements CompileableTemplate
        /**
         * Extract variables from a given raw data stream
         *
-        * @param               $rawData                The raw template data we shall analyze
+        * @param       $rawData        The raw template data we shall analyze
         * @return      void
         * @throws      InvalidTemplateVariableNameException    If a variable name
-        *                                                                                      in a template is
-        *                                                                                      invalid
+        *                                                                                                      in a template is
+        *                                                                                                      invalid
         */
        private function extractVariablesFromRawData ($rawData) {
                // Cast to string
@@ -628,7 +627,7 @@ class TemplateEngine extends BaseFrameworkSystem implements CompileableTemplate
                                // Is the variable name valid?
                                if (($variableMatches[1][$key] != $this->getConfigInstance()->readConfig("tpl_valid_var")) && ($variableMatches[1][$key] != "config")) {
                                        // Invalid variable name
-                                       throw new InvalidTemplateVariableNameException(array($this, $this->getLastTemplate(), $variableMatches[1][$key], $this->getConfigInstance()), self::TEMPLATE_CONTAINS_INVALID_VAR_EXCEPTION);
+                                       throw new InvalidTemplateVariableNameException(array($this, $this->getLastTemplate(), $variableMatches[1][$key], $this->getConfigInstance()), self::EXCEPTION_TEMPLATE_CONTAINS_INVALID_VAR);
                                }
 
                                // Try to assign it, empty strings are being ignored
@@ -651,7 +650,7 @@ class TemplateEngine extends BaseFrameworkSystem implements CompileableTemplate
         * [2] => Array - An array with right part of a match including ":"
         * [3] => Array - An array with right part of a match excluding ":"
         */
-       private function analyzeTemplate ($templateMatches) {
+       private function analyzeTemplate (array $templateMatches) {
                // Backup raw template data
                $backup = $this->getRawTemplateData();
 
@@ -675,8 +674,17 @@ class TemplateEngine extends BaseFrameworkSystem implements CompileableTemplate
                                        // RECURSIVE PROTECTION!
                                        $this->loadedTemplates[] = $template;
                                } catch (FilePointerNotOpenedException $e) {
-                                       // Template not found!
-                                       $this->rawTemplates[] = $template;
+                                       // Template not found, but maybe variable assigned?
+                                       if ($this->isVariableAlreadySet($template) !== false) {
+                                               // Use that content here
+                                               $this->loadedRawData[$template] = $this->readVariable($template);
+
+                                               // Recursive protection:
+                                               $this->loadedTemplates[] = $template;
+                                       } else {
+                                               // Even this is not done... :/
+                                               $this->rawTemplates[] = $template;
+                                       }
                                }
 
                        } // if ((!isset( ...
@@ -729,15 +737,15 @@ class TemplateEngine extends BaseFrameworkSystem implements CompileableTemplate
         * @param               $templateMatches        See method analyzeTemplate()
         * @return      void
         */
-       private function insertAllTemplates ($templateMatches) {
+       private function insertAllTemplates (array $templateMatches) {
                // Run through all loaded codes
-               foreach ($this->loadedRawData as $template => $code) {
+               foreach ($this->loadedRawData as $template=>$code) {
 
                        // Search for the template
                        $foundIndex = array_search($template, $templateMatches[1]);
 
                        // Lookup the matching template replacement
-                       if (isset($templateMatches[0][$foundIndex])) {
+                       if (($foundIndex !== false) && (isset($templateMatches[0][$foundIndex]))) {
 
                                // Get the current raw template
                                $rawData = $this->getRawTemplateData();
@@ -747,8 +755,10 @@ class TemplateEngine extends BaseFrameworkSystem implements CompileableTemplate
 
                                // Set the new raw data
                                $this->setRawTemplateData($rawData);
-                       }
-               }
+
+                       } // END - if
+
+               } // END - foreach
        }
 
        /**
@@ -788,7 +798,7 @@ class TemplateEngine extends BaseFrameworkSystem implements CompileableTemplate
         * @param               $varMatches     An array full of variable/value pairs.
         * @return      void
         */
-       private function assignAllVariables ($varMatches) {
+       private function assignAllVariables (array $varMatches) {
                // Search for all variables
                foreach ($varMatches[1] as $key=>$var) {
 
@@ -804,6 +814,7 @@ class TemplateEngine extends BaseFrameworkSystem implements CompileableTemplate
                                $this->assignVariable($var, $varMatches[3][$key]);
                        } else {
                                // Non-string found so we need some deeper analysis...
+                               // @TODO Unfinished work or don't die here.
                                die("Deeper analysis not yet implemented!");
                        }
 
@@ -815,21 +826,27 @@ class TemplateEngine extends BaseFrameworkSystem implements CompileableTemplate
         * @param               $templateMatches        See method analyzeTemplate() for details
         * @return      void
         */
-       private function compileRawTemplateData ($templateMatches) {
+       private function compileRawTemplateData (array $templateMatches) {
                // Are some code-templates found which we need to compile?
                if (count($this->loadedRawData) > 0) {
 
                        // Then compile all!
-                       foreach ($this->loadedRawData as $template => $code) {
+                       foreach ($this->loadedRawData as $template=>$code) {
+
+                               // Is this template already compiled?
+                               if (in_array($template, $this->compiledTemplates)) {
+                                       // Then skip it
+                                       continue;
+                               }
 
                                // Search for the template
                                $foundIndex = array_search($template, $templateMatches[1]);
 
                                // Lookup the matching variable data
-                               if (isset($templateMatches[3][$foundIndex])) {
+                               if (($foundIndex !== false) && (isset($templateMatches[3][$foundIndex]))) {
 
                                        // Split it up with another reg. exp. into variable=value pairs
-                                       @preg_match_all($this->regExpVarValue, $templateMatches[3][$foundIndex], $varMatches);
+                                       preg_match_all($this->regExpVarValue, $templateMatches[3][$foundIndex], $varMatches);
 
                                        // Assign all variables
                                        $this->assignAllVariables($varMatches);
@@ -978,7 +995,7 @@ class TemplateEngine extends BaseFrameworkSystem implements CompileableTemplate
                $this->extractVariablesFromRawData($rawData);
 
                // Search for code-tags which are {? ?}
-               @preg_match_all($this->regExpCodeTags, $rawData, $templateMatches);
+               preg_match_all($this->regExpCodeTags, $rawData, $templateMatches);
 
                // Analyze the matches array
                if ((is_array($templateMatches)) && (count($templateMatches) == 4) && (count($templateMatches[0]) > 0)) {
@@ -1034,6 +1051,61 @@ class TemplateEngine extends BaseFrameworkSystem implements CompileableTemplate
                        break;
                }
        }
+
+       /**
+        * Loads a given view helper (by name)
+        *
+        * @param       $helperName     The helper's name
+        * @return      void
+        * @throws      ViewHelperNotFoundException     If the given view helper was not found
+        */
+       protected function loadViewHelper ($helperName) {
+               // Make first character upper case, rest low
+               $helperName = ucfirst($helperName);
+
+               // Is this view helper loaded?
+               if (!isset($this->helpers[$helperName])) {
+                       // Create a class name
+                       $className = "{$helperName}ViewHelper";
+
+                       // Does this class exists?
+                       if (!class_exists($className)) {
+                               // Abort here!
+                               throw new ViewHelperNotFoundException(array($this, $helperName), self::EXCEPTION_INVALID_VIEW_HELPER);
+                       }
+
+                       // Generate new instance
+                       $eval = sprintf("\$this->helpers[%s] = %s::create%s();",
+                               $helperName,
+                               $className,
+                               $className
+                       );
+
+                       // Run the code
+                       @eval($eval);
+               }
+
+               // Return the requested instance
+               return $this->helpers[$helperName];
+       }
+
+       /**
+        * Assigns the last loaded raw template content with a given variable
+        *
+        * @param       $templateName   Name of the template we want to assign
+        * @param       $variableName   Name of the variable we want to assign
+        * @return      void
+        */
+       public function assignTemplateWithVariable ($templateName, $variableName) {
+               // Get the content from last loaded raw template
+               $content = $this->getRawTemplateData();
+
+               // Assign the variable
+               $this->assignVariable($variableName, $content);
+
+               // Purge raw content
+               $this->setRawTemplateData("");
+       }
 }
 
 // [EOF]