HTML_Template_Flexy
[ class tree: HTML_Template_Flexy ] [ index: HTML_Template_Flexy ] [ all elements ]

Source for file Standard.php

Documentation is available at Standard.php

  1. <?php
  2. /* vim: set expandtab tabstop=4 shiftwidth=4: */
  3. // +----------------------------------------------------------------------+
  4. // | PHP Version 4                                                        |
  5. // +----------------------------------------------------------------------+
  6. // | Copyright (c) 1997-2002 The PHP Group                                |
  7. // +----------------------------------------------------------------------+
  8. // | This source file is subject to version 2.02 of the PHP license,      |
  9. // | that is bundled with this package in the file LICENSE, and is        |
  10. // | available at through the world-wide-web at                           |
  11. // | http://www.php.net/license/2_02.txt.                                 |
  12. // | If you did not receive a copy of the PHP license and are unable to   |
  13. // | obtain it through the world-wide-web, please send a note to          |
  14. // | license@php.net so we can mail you a copy immediately.               |
  15. // +----------------------------------------------------------------------+
  16. // | Authors: Alan Knowles <alan@akbkhome.com>                            |
  17. // +----------------------------------------------------------------------+
  18. //
  19. // $Id: Standard.php,v 1.14 2004/04/03 03:02:36 alan_k Exp $
  20. //
  21. //  Base Compiler Class
  22. //  Standard 'Original Flavour' Flexy compiler
  23.  
  24.  
  25.  
  26.  
  27. require_once 'HTML/Template/Flexy/Tokenizer.php';
  28.  
  29. // cache for po files..
  30. $GLOBALS['_html_template_flexy_compiler_standard']['PO'= array();
  31.  
  32. class HTML_Template_Flexy_Compiler_Standard extends HTML_Template_Flexy_Compiler {
  33.     
  34.     
  35.     
  36.     /**
  37.     * The compile method.
  38.     * 
  39.     * @params   object HTML_Template_Flexy
  40.     * @params   string|false string to compile of false to use a file.
  41.     * @return   string   filename of template
  42.     * @access   public
  43.     */
  44.     function compile(&$flexy,$string=false
  45.     {
  46.         // read the entire file into one variable
  47.         
  48.         // note this should be moved to new HTML_Template_Flexy_Token
  49.         // and that can then manage all the tokens in one place..
  50.         global $_HTML_TEMPLATE_FLEXY_COMPILER;
  51.         
  52.         $gettextStrings &$_HTML_TEMPLATE_FLEXY_COMPILER['gettextStrings'];
  53.         $gettextStrings = array()// reset it.
  54.         
  55.         if (@$this->options['debug']{
  56.             echo "compiling template $flexy->currentTemplate<BR>";
  57.             
  58.         }
  59.          
  60.         // reset the elements.
  61.         $flexy->_elements = array();
  62.         
  63.         // replace this with a singleton??
  64.         
  65.         $GLOBALS['_HTML_TEMPLATE_FLEXY']['currentOptions'$this->options;
  66.         $GLOBALS['_HTML_TEMPLATE_FLEXY']['elements'= array();
  67.         $GLOBALS['_HTML_TEMPLATE_FLEXY']['filename'$flexy->currentTemplate;
  68.         
  69.         setlocale(LC_ALL$this->options['locale']);
  70.         
  71.         
  72.         $data $string;
  73.         if ($string === false{
  74.             $data file_get_contents($flexy->currentTemplate);
  75.         }
  76.         
  77.         $tokenizer = new HTML_Template_Flexy_Tokenizer($data);
  78.         $tokenizer->fileName = $flexy->currentTemplate;
  79.         
  80.         
  81.         //$tokenizer->debug=1;
  82.         if ($this->options['nonHTML']{
  83.             $tokenizer->ignoreHTML = true;
  84.         }
  85.         if ($this->options['allowPHP']{
  86.             $tokenizer->ignorePHP = false;
  87.         }
  88.         
  89.         $res = HTML_Template_Flexy_Token::buildTokens($tokenizer);
  90.             
  91.         // turn tokens into Template..
  92.         
  93.         $data $res->compile($this);
  94.         
  95.         
  96.         
  97.         
  98.         if (   @$this->options['debug']{
  99.             echo "<B>Result: </B><PRE>".htmlspecialchars($data)."</PRE><BR>";
  100.             
  101.         }
  102.  
  103.         if ($this->options['nonHTML']{
  104.            $data =  str_replace("?>\n","?>\n\n",$data);
  105.         }
  106.         
  107.         // at this point we are into writing stuff...
  108.         if ($this->options['compileToString']{
  109.             $flexy->elements =  $GLOBALS['_HTML_TEMPLATE_FLEXY']['elements'];
  110.             return $data;
  111.         }
  112.         
  113.         
  114.         
  115.         
  116.         // error checking?
  117.         if( ($cfp fopen$flexy->compiledTemplate 'w' )) ) {
  118.             if (@$this->options['debug']{
  119.                 echo "<B>Writing: </B>".htmlspecialchars($data)."<BR>";
  120.                 
  121.             }
  122.             fwrite($cfp,$data);
  123.             fclose($cfp);
  124.              chmod($flexy->compiledTemplate,0775);
  125.             // make the timestamp of the two items match.
  126.             clearstatcache();
  127.              touch($flexy->compiledTemplatefilemtime($flexy->currentTemplate));
  128.             
  129.         else {
  130.             PEAR::raiseError('HTML_Template_Flexy::failed to write to '.$flexy->compiledTemplate,null,PEAR_ERROR_DIE);
  131.         }
  132.         // gettext strings
  133.         if (file_exists($flexy->getTextStringsFile)) {
  134.             unlink($flexy->getTextStringsFile);
  135.         }
  136.         
  137.         if($gettextStrings && ($cfp fopen$flexy->getTextStringsFile'w') ) ) {
  138.             
  139.             fwrite($cfp,serialize(array_unique($gettextStrings)));
  140.             fclose($cfp);
  141.         }
  142.         
  143.         // elements
  144.         if (file_exists($flexy->elementsFile)) {
  145.             unlink($flexy->elementsFile);
  146.         }
  147.         
  148.         if$GLOBALS['_HTML_TEMPLATE_FLEXY']['elements'&&
  149.             ($cfp fopen$flexy->elementsFile'w') ) ) {
  150.             fwrite($cfp,serialize$GLOBALS['_HTML_TEMPLATE_FLEXY']['elements']));
  151.             fclose($cfp);
  152.             // now clear it.
  153.         
  154.         }
  155.         
  156.         return true;
  157.     }
  158.  
  159.     
  160.     
  161.     /**
  162.     * This is the base toString Method, it relays into toString{TokenName}
  163.     *
  164.     * @param    object    HTML_Template_Flexy_Token_* 
  165.     * 
  166.     * @return   string     string to build a template
  167.     * @access   public
  168.     * @see      toString*
  169.     */
  170.   
  171.  
  172.     function toString($element
  173.     {
  174.         static $len = 26; // strlen('HTML_Template_Flexy_Token_');
  175.         
  176.         $class = get_class($element);
  177.         if (strlen($class>= $len{
  178.             $type = substr($class,$len);
  179.             //echo "CALL $type";
  180.             return $this->{'toString'.$type}($element);
  181.         }
  182.         
  183.         $ret $element->value;
  184.         $ret .= $element->compileChildren($this);
  185.         if ($element->close{
  186.             $ret .= $element->close->compile($this);
  187.         }
  188.         
  189.         return $ret;
  190.         
  191.         
  192.     }
  193.  
  194.  
  195.     /**
  196.     *   HTML_Template_Flexy_Token_Else toString
  197.     *
  198.     * @param    object    HTML_Template_Flexy_Token_Else 
  199.     * 
  200.     * @return   string     string to build a template
  201.     * @access   public
  202.     * @see      toString*
  203.     */
  204.   
  205.  
  206.     function toStringElse($element
  207.      {
  208.         // pushpull states to make sure we are in an area.. - should really check to see 
  209.         // if the state it is pulling is a if...
  210.         if ($element->pullState(=== false{
  211.             return $this->appendHTML(
  212.                 "<font color=\"red\">Unmatched {else:} on line: {$element->line}</font>"
  213.                 );
  214.         }
  215.         $element->pushState();
  216.         return $this->appendPhp("} else {");
  217.     }
  218.     
  219.     /**
  220.     *   HTML_Template_Flexy_Token_End toString 
  221.     *
  222.     * @param    object    HTML_Template_Flexy_Token_Else
  223.     * 
  224.     * @return   string     string to build a template
  225.     * @access   public 
  226.     * @see      toString*
  227.     */
  228.   
  229.     function toStringEnd($element) 
  230.     {
  231.         // pushpull states to make sure we are in an area.. - should really check to see 
  232.         // if the state it is pulling is a if...
  233.         if ($element->pullState() === false) {
  234.             return $this->appendHTML(
  235.                 "<font color=\"red\">Unmatched {end:} on line: {$element->line}</font>"
  236.                 );
  237.         }
  238.          
  239.         return $this->appendPhp("}");
  240.     }
  241.  
  242.     /**
  243.     *   HTML_Template_Flexy_Token_EndTag toString 
  244.     *
  245.     * @param    object    HTML_Template_Flexy_Token_EndTag
  246.     * 
  247.     * @return   string     string to build a template
  248.     * @access   public 
  249.     * @see      toString*
  250.     */
  251.   
  252.  
  253.  
  254.     function toStringEndTag($element) 
  255.     {
  256.         return $this->toStringTag($element);
  257.     }
  258.         
  259.     
  260.     
  261.     /**
  262.     *   HTML_Template_Flexy_Token_Foreach toString 
  263.     *
  264.     * @param    object    HTML_Template_Flexy_Token_Foreach 
  265.     * 
  266.     * @return   string     string to build a template
  267.     * @access   public 
  268.     * @see      toString*
  269.     */
  270.   
  271.     
  272.     function toStringForeach($element) 
  273.     {
  274.     
  275.         
  276.     
  277.         $ret = 'if (is_array('.
  278.             $element->toVar($element->loopOn) . ")  || " .
  279.             'is_object(' . $element->toVar($element->loopOn) . ')) ' .
  280.             'foreach(' . $element->toVar($element->loopOn) . " ";
  281.             
  282.         $ret .= "as \${$element->key}";
  283.         
  284.         if ($element->value) {
  285.             $ret .=  " => \${$element->value}";
  286.         }
  287.         $ret .= ") {";
  288.         
  289.         $element->pushState();
  290.         $element->pushVar($element->key);
  291.         $element->pushVar($element->value);
  292.         return $this->appendPhp($ret);
  293.     }
  294.     /**
  295.     *   HTML_Template_Flexy_Token_If toString 
  296.     *
  297.     * @param    object    HTML_Template_Flexy_Token_If
  298.     * 
  299.     * @return   string     string to build a template
  300.     * @access   public 
  301.     * @see      toString*
  302.     */
  303.   
  304.     function toStringIf($element) 
  305.     {
  306.         $ret = "if (".$element->isNegative . $element->toVar($element->condition) .")  {";
  307.         $element->pushState();
  308.         return $this->appendPhp($ret);
  309.     }
  310.  
  311.    /**
  312.     *  get Modifier Wrapper 
  313.     *
  314.     * converts :h, :u, :r , .....
  315.     * @param    object    HTML_Template_Flexy_Token_Method|Var
  316.     * 
  317.     * @return   array prefix,suffix
  318.     * @access   public 
  319.     * @see      toString*
  320.     */
  321.  
  322.     function getModifierWrapper($element) 
  323.     {
  324.         $prefix = 'echo ';
  325.         
  326.         $suffix = '';
  327.         $modifier = $element->modifier . ' ';
  328.         switch ($modifier{0}) {
  329.             case 'h':
  330.                 break;
  331.             case 'u':
  332.                 $prefix = 'echo urlencode(';
  333.                 $suffix = ')';
  334.                 break;
  335.             case 'r':
  336.                 $prefix = 'echo \'<pre>\'; echo htmlspecialchars(print_r(';
  337.                 $suffix = ',true)); echo \'</pre>\';';
  338.                 break;                
  339.             case 'n'
  340.                 // blank or value..
  341.                 $numberformat = @$GLOBALS['_HTML_TEMPLATE_FLEXY']['currentOptions']['numberFormat'];
  342.                 $prefix = 'echo number_format(';
  343.                 $suffix = $GLOBALS['_HTML_TEMPLATE_FLEXY']['currentOptions']['numberFormat'] . ')';
  344.                 break;
  345.             case 'b'// nl2br + htmlspecialchars
  346.                 $prefix = 'echo nl2br(htmlspecialchars(';
  347.                 
  348.                 // add language ?
  349.                 $suffix = '))';
  350.                 break;
  351.             default:
  352.                 $prefix = 'echo htmlspecialchars(';
  353.                 // add language ?
  354.                 $suffix = ')';
  355.         }
  356.         
  357.         return array($prefix,$suffix);
  358.     }
  359.  
  360.  
  361.  
  362.   /**
  363.     *   HTML_Template_Flexy_Token_Var toString 
  364.     *
  365.     * @param    object    HTML_Template_Flexy_Token_Method
  366.     * 
  367.     * @return   string     string to build a template
  368.     * @access   public 
  369.     * @see      toString*
  370.     */
  371.   
  372.     function toStringVar($element) 
  373.     {
  374.         // ignore modifier at present!!
  375.         list($prefix,$suffix) = $this->getModifierWrapper($element);
  376.         return $this->appendPhp( $prefix . $element->toVar($element->value) . $suffix .';');
  377.     }
  378.    /**
  379.     *   HTML_Template_Flexy_Token_Method toString 
  380.     *
  381.     * @param    object    HTML_Template_Flexy_Token_Method
  382.     * 
  383.     * @return   string     string to build a template
  384.     * @access   public 
  385.     * @see      toString*
  386.     */
  387.   
  388.     function toStringMethod($element) 
  389.     {
  390.  
  391.               
  392.         // set up the modifier at present!!
  393.         list($prefix,$suffix) = $this->getModifierWrapper($element);
  394.         
  395.         // add the '!' to if
  396.         
  397.         if ($element->isConditional) {
  398.             $prefix = 'if ('.$element->isNegative;
  399.             $element->pushState();
  400.             $suffix = ')';
  401.         }  
  402.         
  403.         
  404.         // check that method exists..
  405.         // if (method_exists($object,'method');
  406.         $bits = explode('.',$element->method);
  407.         $method = array_pop($bits);
  408.         
  409.         $object = implode('.',$bits);
  410.         
  411.         $prefix = 'if (isset('.$element->toVar($object).
  412.             ') && method_exists('.$element->toVar($object) .",'{$method}')) " $prefix;
  413.         
  414.         
  415.         
  416.         $ret  =  $prefix;
  417.         $ret .=  $element->toVar($element->method) . "(";
  418.         $s =0;
  419.          
  420.        
  421.          
  422.         foreach($element->args as $a) {
  423.              
  424.             if ($s) {
  425.                 $ret .= ",";
  426.             }
  427.             $s =1;
  428.             if ($a{0} == '#') {
  429.                 $ret .= '"'addslashes(substr($a,1,-1)) . '"';
  430.                 continue;
  431.             }
  432.             $ret .= $element->toVar($a);
  433.             
  434.         }
  435.         $ret .= ")" . $suffix;
  436.         
  437.         if ($element->isConditional) {
  438.             $ret .= ' { ';
  439.         } else {
  440.             $ret .= ";";
  441.         }
  442.         
  443.         
  444.         
  445.         return $this->appendPhp($ret)
  446.         
  447.          
  448.  
  449.    }
  450.    /**
  451.     *   HTML_Template_Flexy_Token_Processing toString 
  452.     *
  453.     * @param    object    HTML_Template_Flexy_Token_Processing 
  454.     * 
  455.     * @return   string     string to build a template
  456.     * @access   public 
  457.     * @see      toString*
  458.     */
  459.  
  460.  
  461.     function toStringProcessing($element) 
  462.     {
  463.         // if it's XML then quote it..
  464.         if (strtoupper(substr($element->value,2,3)) == 'XML') { 
  465.             return $this->appendPhp("echo '" . str_replace("'","\\"."'", $element->value) . "';");
  466.         }
  467.         // otherwise it's PHP code - so echo it..
  468.         return $element->value;
  469.     }
  470.     
  471.     /**
  472.     *   HTML_Template_Flexy_Token_Text toString 
  473.     *
  474.     * @param    object    HTML_Template_Flexy_Token_Text
  475.     * 
  476.     * @return   string     string to build a template
  477.     * @access   public 
  478.     * @see      toString*
  479.     */
  480.  
  481.  
  482.  
  483.     function toStringText($element) 
  484.     {
  485.         // if it's XML then quote it..
  486.         
  487.         /**
  488.         * Global variable for gettext replacement
  489.         * static object vars will be nice in PHP5 :)
  490.         *
  491.         * @var array
  492.         * @access private
  493.         */
  494.         global $_HTML_TEMPLATE_FLEXY_COMPILER;
  495.         
  496.         $gettextStrings = &$_HTML_TEMPLATE_FLEXY_COMPILER['gettextStrings'];
  497.         
  498.         static $cleanArray = array(
  499.             '$' => '\$',
  500.             '"' => '\"',
  501.             "'" => '\\\'',
  502.             '\\' => '\\\\',
  503.             "\n" => '\n',
  504.             "\t" => '\t',
  505.             "\r" => '\r'
  506.         );
  507.         static $uncleanArray = false;
  508.         if (!$uncleanArray ) {
  509.             $uncleanArray = array_flip($cleanArray);
  510.         }
  511.  
  512.          
  513.         if (!strlen(trim($element->value) )) {
  514.             return $this->appendHtml($element->value);
  515.         }
  516.         // dont add comments to translation lists.
  517.          
  518.         if (substr($element->value,0,4) == '<!--') {
  519.             return $this->appendHtml($element->value);
  520.         }
  521.         if (!count($element->argTokens) && !$element->isWord()) {
  522.             return $this->appendHtml($element->value);
  523.         }
  524.         
  525.         $front = '';
  526.         $rear = '';
  527.         // trim whitespace front
  528.         for ($i=0;$i<strlen($element->value)$i++) {
  529.             if (strpos(" \n\t\r\0\x0B", $element->value{$i}) !== false) {
  530.                 $front .= $element->value{$i};
  531.                 continue;
  532.             }
  533.             break;
  534.         }
  535.         // trim whitespace rear 
  536.         for ($i=strlen($element->value)-1;$i>-1; $i--) {
  537.             if (strpos(" \n\t\r\0\x0B", $element->value{$i}) !== false) {
  538.                 $rear = $element->value{$i} . $rear;
  539.                 continue;
  540.             }
  541.             break;            
  542.         }
  543.         
  544.         $value = trim($element->value);
  545.         
  546.         
  547.         // convert to escaped chars.. (limited..)
  548.         $value = strtr($value,$cleanArray);
  549.         
  550.         
  551.         // its a simple word!
  552.         if (!count($element->argTokens)) {
  553.             $gettextStrings[] = $value;
  554.             $value = $this->translateString($value);
  555.             $value = strtr($value,$uncleanArray);
  556.         
  557.             return $this->appendHtml($front .  $value  . $rear);
  558.         }
  559.         
  560.         
  561.         // there are subtokens..
  562.         // print_r($element->argTokens );
  563.         $args = array();
  564.         $argsMake = '';
  565.         // these should only be text or vars..
  566.         foreach($element->argTokens as $i=>$token) {
  567.             $args[] = $token->compile($this);
  568.         }
  569.         
  570.         $gettextStrings[] = $value;
  571.         $value = $this->translateString($value);
  572.         $value = strtr($value,$uncleanArray);
  573.         
  574.         $bits = explode('%s',$value);
  575.         $ret = $front;
  576.         foreach($bits as $i=>$v) {
  577.             $ret.=$v.@$args[$i];
  578.         }
  579.         
  580.         return  $ret . $rear;
  581.         
  582.     }
  583.     
  584. /**    
  585.     * translateString - a gettextWrapper
  586.     *
  587.     * tries to do gettext or falls back on File_Gettext
  588.     * This has !!!NO!!! error handling - if it fails you just get english..
  589.     * no questions asked!!!
  590.     * 
  591.     * @param   string       string to translate
  592.     *
  593.     * @return   string      translated string..
  594.     * @access   public
  595.     */
  596.   
  597.     function translateString($string)
  598.     {
  599.         if (@$this->options['debug']) {
  600.             echo __CLASS__.":TRANSLATING $string<BR>";
  601.         }
  602.         if (function_exists('gettext') && !$this->options['textdomain']) {
  603.             if (@$this->options['debug']) {
  604.                 echo __CLASS__.":USING GETTEXT?<BR>";
  605.             }
  606.             return  gettext($string);
  607.         }
  608.         if (!$this->options['textdomain'] || !$this->options['textdomainDir']) {
  609.             // text domain is not set..
  610.             if (@$this->options['debug']) {
  611.                 echo __CLASS__.":MISSING textdomain settings<BR>";
  612.             }
  613.             return $string;
  614.         }
  615.         $pofile = $this->options['textdomainDir'] . 
  616.                 '/' . $this->options['locale'] . 
  617.                 '/LC_MESSAGES/' . $this->options['textdomain'] . '.po';
  618.         
  619.         
  620.         // did we try to load it already..
  621.         if (@$GLOBALS['_'.__CLASS__]['PO'][$pofile] === false) {
  622.             if (@$this->options['debug']) {
  623.                 echo __CLASS__.":LOAD failed (Cached):<BR>";
  624.             }
  625.             return $string;
  626.         }
  627.         if (!@$GLOBALS['_'.__CLASS__]['PO'][$pofile]) {
  628.             // default - cant load it..
  629.             $GLOBALS['_'.__CLASS__]['PO'][$pofile] = false;
  630.             if (!file_exists($pofile)) {
  631.                  if (@$this->options['debug']) {
  632.                 echo __CLASS__.":LOAD failed: {$pofile}<BR>";
  633.             }
  634.                 return $string;
  635.             }
  636.             
  637.             if (!@include_once 'File/Gettext.php') {
  638.                 if (@$this->options['debug']) {
  639.                     echo __CLASS__.":LOAD no File_gettext:<BR>";
  640.                 }
  641.                 return $string;
  642.             }
  643.             
  644.             $GLOBALS['_'.__CLASS__]['PO'][$pofile] = File_Gettext::factory('PO',$pofile);
  645.             $GLOBALS['_'.__CLASS__]['PO'][$pofile]->load();
  646.             //echo '<PRE>'.htmlspecialchars(print_r($GLOBALS['_'.__CLASS__]['PO'][$pofile]->strings,true));
  647.             
  648.         }
  649.         $po = &$GLOBALS['_'.__CLASS__]['PO'][$pofile];
  650.         // we should have it loaded now...
  651.         // this is odd - data is a bit messed up with CR's
  652.         $string = str_replace('\n',"\n",$string);
  653.         if (!isset($po->strings[$string])) {
  654.             if (@$this->options['debug']) {
  655.                     echo __CLASS__.":no match:<BR>";
  656.             }
  657.             return $string;
  658.         }
  659.         // finally we have a match!!!
  660.         return $po->strings[$string];
  661.         
  662.     } 
  663.      /**
  664.     *   HTML_Template_Flexy_Token_Tag toString 
  665.     *
  666.     * @param    object    HTML_Template_Flexy_Token_Tag
  667.     * 
  668.     * @return   string     string to build a template
  669.     * @access   public 
  670.     * @see      toString*
  671.     */
  672.   
  673.     function toStringTag($element) {
  674.         if (strpos($element->tag,':') === false) {
  675.             $namespace = 'Tag';
  676.         } else {
  677.             $bits =  explode(':',$element->tag);
  678.             $namespace = $bits[0];
  679.         }
  680.     if ($namespace{0} == '/') {
  681.         return '';
  682.         }
  683.         if (empty($this->tagHandlers[$namespace])) {
  684.             
  685.             require_once 'HTML/Template/Flexy/Compiler/Standard/Tag.php';
  686.             $this->tagHandlers[$namespace] = &HTML_Template_Flexy_Compiler_Standard_Tag::factory($namespace,$this);
  687.             if (!$this->tagHandlers[$namespace] ) {
  688.                 PEAR::raiseError('HTML_Template_Flexy::failed to create Namespace Handler '.$namespace . 
  689.                 ' in file ' . $flexy->compiledTemplate,null,PEAR_ERROR_DIE);
  690.             }
  691.                 
  692.         }
  693.         return $this->tagHandlers[$namespace]->toString($element);
  694.         
  695.         
  696.     }
  697.     
  698.  

Documentation generated on Mon, 11 Mar 2019 10:14:27 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.