Fake template engine added, variables can now be compiled for config entries:
[core.git] / inc / classes / main / template / class_BaseTemplateEngine.php
index c40b183c021148b0cc3fba84b297083080e53bf7..2256fab0f24879fe8c00921f4b722f8b4c349cb5 100644 (file)
@@ -4,7 +4,7 @@
  *
  * @author             Roland Haeder <webmaster@ship-simu.org>
  * @version            0.0.0
- * @copyright  Copyright (c) 2007 - 2009 Roland Haeder, this is free software
+ * @copyright  Copyright (c) 2007, 2008 Roland Haeder, 2009 Core Developer Team
  * @license            GNU GPL 3.0 or any newer version
  * @link               http://www.ship-simu.org
  *
@@ -27,7 +27,7 @@ class BaseTemplateEngine extends BaseFrameworkSystem {
         * templates are stored. We will internally determine the language plus
         * "html" for web templates or "emails" for email templates
         */
-       private $basePath = '';
+       private $templateBasePath = '';
 
        /**
         * Template type
@@ -45,9 +45,14 @@ class BaseTemplateEngine extends BaseFrameworkSystem {
        private $codeExtension = '.ctp';
 
        /**
-        * Path relative to $basePath and language code for compiled code-templates
+        * Path relative to $templateBasePath and language code for compiled code-templates
         */
-       private $compileOutputPath = 'templates/_compiled';
+       private $compileOutputPath = 'templates/_compiled/';
+
+       /**
+        * The path name for all templates
+        */
+       private $genericBasePath = 'templates/';
 
        /**
         * The raw (maybe uncompiled) template
@@ -126,6 +131,11 @@ class BaseTemplateEngine extends BaseFrameworkSystem {
         */
        private $codeEnd = '?>';
 
+       /**
+        * Language support is enabled by default
+        */
+       private $languageSupport = true;
+
        // Exception codes for the template engine
        const EXCEPTION_TEMPLATE_TYPE_IS_UNEXPECTED   = 0x110;
        const EXCEPTION_TEMPLATE_CONTAINS_INVALID_VAR = 0x111;
@@ -140,10 +150,6 @@ class BaseTemplateEngine extends BaseFrameworkSystem {
        protected function __construct ($className) {
                // Call parent constructor
                parent::__construct($className);
-
-               // Clean up a little
-               $this->removeNumberFormaters();
-               $this->removeSystemArray();
        }
 
        /**
@@ -191,13 +197,12 @@ class BaseTemplateEngine extends BaseFrameworkSystem {
                // Is the variable found?
                if ($found !== false) {
                        // Read it
-                       $found = $this->varStack[$this->currGroup][$found]['value'];
+                       $content = $this->varStack[$this->currGroup][$found]['value'];
                } // END - if
 
-               //* DEBUG: */ echo __METHOD__.": group=".$this->currGroup.",var=".$var.", found=".$found."<br />\n";
-
                // Return the current position
-               return $found;
+               //* DEBUG: */ echo __METHOD__.": group=".$this->currGroup.",var=".$var.", content[".gettype($content)."]=".$content."<br />\n";
+               return $content;
        }
 
        /**
@@ -301,7 +306,7 @@ class BaseTemplateEngine extends BaseFrameworkSystem {
         * @param       $templateType   The current template's type
         * @return      void
         */
-       private final function setTemplateType ($templateType) {
+       protected final function setTemplateType ($templateType) {
                $this->templateType = (string) $templateType;
        }
 
@@ -327,22 +332,32 @@ class BaseTemplateEngine extends BaseFrameworkSystem {
        /**
         * Setter for base path
         *
-        * @param               $basePath               The local base path for all templates
+        * @param               $templateBasePath               The relative base path for all templates
         * @return      void
         */
-       public final function setBasePath ($basePath) {
+       public final function setTemplateBasePath ($templateBasePath) {
                // And set it
-               $this->basePath = (string) $basePath;
+               $this->templateBasePath = (string) $templateBasePath;
        }
 
        /**
         * Getter for base path
         *
-        * @return      $basePath               The local base path for all templates
+        * @return      $templateBasePath               The relative base path for all templates
+        */
+       public final function getTemplateBasePath () {
+               // And set it
+               return $this->templateBasePath;
+       }
+
+       /**
+        * Getter for generic base path
+        *
+        * @return      $templateBasePath               The relative base path for all templates
         */
-       public final function getBasePath () {
+       public final function getGenericBasePath () {
                // And set it
-               return $this->basePath;
+               return $this->genericBasePath;
        }
 
        /**
@@ -459,7 +474,7 @@ class BaseTemplateEngine extends BaseFrameworkSystem {
                if ($idx !== false) {
                        // Remove this variable
                        $this->varStack->offsetUnset($idx);
-               }
+               } // END - if
        }
 
        /**
@@ -510,29 +525,62 @@ class BaseTemplateEngine extends BaseFrameworkSystem {
         * Private loader for all template types
         *
         * @param       $template       The template we shall load
+        * @param       $extOther       An other extension to use
         * @return      void
+        * @throws      FileIoException If the template was not found
         */
-       private function loadTemplate ($template) {
-               // Get extension for the template
-               $ext = $this->getRawTemplateExtension();
+       protected function loadTemplate ($template, $extOther = '') {
+               // Get extension for the template if empty
+               if (empty($extOther)) {
+                       // None provided, so get the raw one
+                       $ext = $this->getRawTemplateExtension();
+               } else {
+                       // Then use it!
+                       $ext = (string) $extOther;
+               }
 
-               // If we shall load a code-template we need to switch the file extension
-               if ($this->getTemplateType() == $this->getConfigInstance()->readConfig('code_template_type')) {
-                       // Switch over to the code-template extension
-                       $ext = $this->getCodeTemplateExtension();
-               } // END - if
+               // Is language support enabled?
+               if ($this->isLanguageSupportEnabled()) {
+                       // Construct the FQFN for the template by honoring the current language
+                       $fqfn = sprintf("%s%s%s%s/%s/%s%s",
+                               $this->getConfigInstance()->getConfigEntry('base_path'),
+                               $this->getTemplateBasePath(),
+                               $this->getGenericBasePath(),
+                               $this->getLanguageInstance()->getLanguageCode(),
+                               $this->getTemplateType(),
+                               (string) $template,
+                               $ext
+                       );
+               } else {
+                       // Construct the FQFN for the template without language
+                       $fqfn = sprintf("%s%s%s%s/%s%s",
+                               $this->getConfigInstance()->getConfigEntry('base_path'),
+                               $this->getTemplateBasePath(),
+                               $this->getGenericBasePath(),
+                               $this->getTemplateType(),
+                               (string) $template,
+                               $ext
+                       );
+               }
 
-               // Construct the FQFN for the template by honoring the current language
-               $fqfn = sprintf("%s%s/%s/%s%s",
-                       $this->getBasePath(),
-                       $this->getLanguageInstance()->getLanguageCode(),
-                       $this->getTemplateType(),
-                       (string) $template,
-                       $ext
-               );
+               // First try this
+               try {
+                       // Load the raw template data
+                       $this->loadRawTemplateData($fqfn);
+               } catch (FileIoException $e) {
+                       // If we shall load a code-template we need to switch the file extension
+                       if (($this->getTemplateType() != $this->getConfigInstance()->getConfigEntry('web_template_type')) && (empty($extOther))) {
+                               // Switch over to the code-template extension and try it again
+                               $ext = $this->getCodeTemplateExtension();
+
+                               // Try it again...
+                               $this->loadTemplate($template, $ext);
+                       } else {
+                               // Throw it again
+                               throw new FileIoException($fqfn, FrameworkFileInputPointer::EXCEPTION_FILE_NOT_FOUND);
+                       }
+               }
 
-               // Load the raw template data
-               $this->loadRawTemplateData($fqfn);
        }
 
        /**
@@ -658,10 +706,7 @@ class BaseTemplateEngine extends BaseFrameworkSystem {
                                                // Remember this template for recursion detection
                                                // RECURSIVE PROTECTION!
                                                $this->loadedTemplates[] = $template;
-                                       } catch (FileNotFoundException $e) {
-                                               // Even this is not done... :/
-                                               $this->rawTemplates[] = $template;
-                                       } catch (FilePointerNotOpenedException $e) {
+                                       } catch (FileIoException $e) {
                                                // Even this is not done... :/
                                                $this->rawTemplates[] = $template;
                                        }
@@ -760,10 +805,7 @@ class BaseTemplateEngine extends BaseFrameworkSystem {
                                        // Remember this template for recursion detection
                                        // RECURSIVE PROTECTION!
                                        $this->loadedTemplates[] = $template;
-                               } catch (FileNotFoundException $e) {
-                                       // This template was never found. We silently ignore it
-                                       unset($this->rawTemplates[$key]);
-                               } catch (FilePointerNotOpenedException $e) {
+                               } catch (FileIoException $e) {
                                        // This template was never found. We silently ignore it
                                        unset($this->rawTemplates[$key]);
                                }
@@ -895,7 +937,7 @@ class BaseTemplateEngine extends BaseFrameworkSystem {
         */
        public function loadWebTemplate ($template) {
                // Set template type
-               $this->setTemplateType($this->getConfigInstance()->readConfig('web_template_type'));
+               $this->setTemplateType($this->getConfigInstance()->getConfigEntry('web_template_type'));
 
                // Load the special template
                $this->loadTemplate($template);
@@ -910,7 +952,7 @@ class BaseTemplateEngine extends BaseFrameworkSystem {
        public function assignConfigVariable ($var) {
                // Sweet and simple...
                //* DEBUG: */ echo __METHOD__.':var={$var}<br />\n';
-               $this->varStack['config'][$var] = $this->getConfigInstance()->readConfig($var);
+               $this->varStack['config'][$var] = $this->getConfigInstance()->getConfigEntry($var);
        }
 
        /**
@@ -919,10 +961,12 @@ class BaseTemplateEngine extends BaseFrameworkSystem {
         * @param       $template       The email template we shall load which is located in
         *                                              'emails' by default
         * @return      void
+        * @deprecated
+        * @see         See loadCodeTemplate()
         */
        public function loadEmailTemplate ($template) {
                // Set template type
-               $this->setTemplateType($this->getConfigInstance()->readConfig('email_template_type'));
+               $this->setTemplateType($this->getConfigInstance()->getConfigEntry('email_template_type'));
 
                // Load the special template
                $this->loadTemplate($template);
@@ -937,12 +981,33 @@ class BaseTemplateEngine extends BaseFrameworkSystem {
         */
        public function loadCodeTemplate ($template) {
                // Set template type
-               $this->setTemplateType($this->getConfigInstance()->readConfig('code_template_type'));
+               $this->setTemplateType($this->getConfigInstance()->getConfigEntry('code_template_type'));
 
                // Load the special template
                $this->loadTemplate($template);
        }
 
+       /**
+        * Compiles configuration place-holders in all variables. This 'walks'
+        * through the variable stack 'general'. It interprets all values from that
+        * variables as configuration entries after compiling them.
+        *
+        * @return      void
+        */
+       public final function compileConfigInVariables () {
+               // Iterate through all general variables
+               foreach ($this->varStack['general'] as $idx=>$currVariable) {
+                       // Compile the value
+                       $value = $this->compileRawCode($this->readVariable($currVariable['name']), true);
+
+                       // Remove it from stack
+                       unset($this->varStack['general'][$idx]);
+
+                       // Re-assign the variable
+                       $this->assignConfigVariable($value);
+               } // END - foreach
+       }
+
        /**
         * Compile all variables by inserting their respective values
         *
@@ -951,7 +1016,7 @@ class BaseTemplateEngine extends BaseFrameworkSystem {
         */
        public final function compileVariables () {
                // Initialize the $content array
-               $validVar = $this->getConfigInstance()->readConfig('tpl_valid_var');
+               $validVar = $this->getConfigInstance()->getConfigEntry('tpl_valid_var');
                $dummy = array();
 
                // Iterate through all general variables
@@ -1015,10 +1080,10 @@ class BaseTemplateEngine extends BaseFrameworkSystem {
                        );
 
                        // Run the constructed command. This will "compile" all variables in
-                       @eval($eval);
+                       eval($eval);
 
                        // Goes something wrong?
-                       if (!isset($result)) {
+                       if ((!isset($result)) || (empty($result))) {
                                // Output eval command
                                $this->debugOutput(sprintf("Failed eval() code: <pre>%s</pre>", $this->markupCode($eval, true)), true);
 
@@ -1049,9 +1114,9 @@ class BaseTemplateEngine extends BaseFrameworkSystem {
         */
        public function compileTemplate () {
                // We will only work with template type "code" from configuration
-               if ($this->getTemplateType() != $this->getConfigInstance()->readConfig('code_template_type')) {
+               if ($this->getTemplateType() != $this->getConfigInstance()->getConfigEntry('code_template_type')) {
                        // Abort here
-                       throw new UnexpectedTemplateTypeException(array($this, $this->getTemplateType(), $this->getConfigInstance()->readConfig('code_template_type')), self::EXCEPTION_TEMPLATE_TYPE_IS_UNEXPECTED);
+                       throw new UnexpectedTemplateTypeException(array($this, $this->getTemplateType(), $this->getConfigInstance()->getConfigEntry('code_template_type')), self::EXCEPTION_TEMPLATE_TYPE_IS_UNEXPECTED);
                } // END - if
 
                // Get the raw data.
@@ -1197,16 +1262,17 @@ class BaseTemplateEngine extends BaseFrameworkSystem {
        /**
         * "Compiles" a variable by replacing {?var?} with it's content
         *
-        * @param       $rawCode        Raw code to compile
+        * @param       $rawCode                        Raw code to compile
+        * @param       $setMatchAsCode         Sets $match if readVariable() returns empty result
         * @return      $rawCode        Compile code with inserted variable value
         */
-       public function compileRawCode ($rawCode) {
+       public function compileRawCode ($rawCode, $setMatchAsCode=false) {
                // Find the variables
-               //* DEBUG: */ echo "rawCode=<pre>".htmlentities($rawCode)."</pre>\n";
+               //* DEBUG: */ echo __METHOD__.":rawCode=<pre>".htmlentities($rawCode)."</pre>\n";
                preg_match_all($this->regExpVarValue, $rawCode, $varMatches);
 
                // Compile all variables
-               //* DEBUG: */ echo "<pre>".print_r($varMatches, true)."</pre>";
+               //* DEBUG: */ echo __METHOD__.":<pre>".print_r($varMatches, true)."</pre>\n";
                foreach ($varMatches[0] as $match) {
                        // Add variable tags around it
                        $varCode = '{?' . $match . '?}';
@@ -1214,12 +1280,20 @@ class BaseTemplateEngine extends BaseFrameworkSystem {
                        // Is the variable found in code? (safes some calls)
                        if (strpos($rawCode, $varCode) !== false) {
                                // Replace the variable with it's value, if found
-                               //* DEBUG: */ echo __METHOD__.": match=".$match."<br />\n";
-                               $rawCode = str_replace($varCode, $this->readVariable($match), $rawCode);
+                               $value = $this->readVariable($match);
+                               //* DEBUG: */ echo __METHOD__.": match=".$match.",value[".gettype($value)."]=".$value."<br />\n";
+                               if (($setMatchAsCode === true) && (is_null($value))) {
+                                       // Insert match
+                                       $rawCode = str_replace($varCode, $match, $rawCode);
+                               } else {
+                                       // Insert value
+                                       $rawCode = str_replace($varCode, $value, $rawCode);
+                               }
                        } // END - if
                } // END - foreach
 
                // Return the compiled data
+               //* DEBUG: */ echo __METHOD__.":rawCode=<pre>".htmlentities($rawCode)."</pre>\n";
                return $rawCode;
        }
 
@@ -1258,42 +1332,37 @@ class BaseTemplateEngine extends BaseFrameworkSystem {
         * @return      void
         * @throws      XmlParserException      If an XML error was found
         */
-       public final function renderXmlContent ($content = null) {
+       public function renderXmlContent ($content = null) {
                // Is the content set?
                if (is_null($content)) {
                        // Get current content
                        $content = $this->getRawTemplateData();
                } // END - if
 
-               // Convert all to UTF8
-               if (function_exists('recode')) {
-                       $content = recode("html..utf8", $content);
-               } else {
-                       // @TODO We need to find a fallback solution here
-               } // END - if
-
-               // Get an XML parser
-               $xmlParser = xml_parser_create();
-
-               // Force case-folding to on
-               xml_parser_set_option($xmlParser, XML_OPTION_CASE_FOLDING, true);
-
-               // Set object
-               xml_set_object($xmlParser, $this);
+               // Get a XmlParser instance
+               $parserInstance = ObjectFactory::createObjectByConfiguredName('xml_parser_class', array($this));
 
-               // Set handler call-backs
-               xml_set_element_handler($xmlParser, 'startElement', 'endElement');
-               xml_set_character_data_handler($xmlParser, 'characterHandler');
+               // Parse the XML document
+               $parserInstance->parseXmlContent($content);
+       }
 
-               // Now parse the XML tree
-               if (!xml_parse($xmlParser, $content)) {
-                       // Error found in XML!
-                       //die('<pre>'.htmlentities($content).'</pre>');
-                       throw new XmlParserException(array($this, $xmlParser), BaseHelper::EXCEPTION_XML_PARSER_ERROR);
-               } // END - if
+       /**
+        * Enables or disables language support
+        *
+        * @param       $languageSupport        New language support setting
+        * @return      void
+        */
+       public final function enableLanguageSupport ($languageSupport = true) {
+               $this->languageSupport = (bool) $languageSupport;
+       }
 
-               // Free the parser
-               xml_parser_free($xmlParser);
+       /**
+        * Checks wether language support is enabled
+        *
+        * @return      $languageSupport        Wether language support is enabled or disabled
+        */
+       public final function isLanguageSupportEnabled () {
+               return $this->languageSupport;
        }
 }