PHP Classes
Icontem

File: class-block_template.php


  Search   All class groups All class groups   Latest entries Latest entries   Top 10 charts Top 10 charts   Newsletter Newsletter   Blog Blog   Forums Forums   Help FAQ Help FAQ  
  Login   Register  
Recommend this page to a friend! ReTweet ReTweet Stumble It! Stumble It! Bookmark in del.icio.us Bookmark in del.icio.us
  Classes of jonathan gotti  >  Block template  >  class-block_template.php  
File: class-block_template.php
Role: Class source
Content type: text/plain
Description: main class file
Class: Block template
Template engine based in the concept of blocks
 

Contents

Class file image Download
<?php
/**
* manage the HTML output.
* block_template is a template parser/renderer see the template sample for more info on the way the template work
* @changelog 2005-12-07 - bugfixes _templatize didn't correctly send content parameter to _emit_signal method 
*            2005-09-30 - remove no more used footer property 
*                       - reset_ method now reset _sections property too
*                       - clean the box method
*            2005-09-28 - new parameter include_vars for method get_section_vars
*            2005-07-13 - new predefined tag parameter 'require' for required vars in section includes
*            2005-06-18 - new reset_ method
*            2005-06-17 - new predefined tag parameter 'tagcontent' for open/close tags
*                       - new predefined tag parameter 'preparse' to enable preparsing of parameter value
*            2005-06-07 - now register_callback() will return a pointer 
*                       - add new method unregister_callback()
*                       - new methods highlight_str() & highlight_template_file()
*            2005-06-01 - add callback support on 'on-output' signal 
*                       - output can return var or file
*                       - new set_safe_output method to protect block_template tags
*                       - bugfixes no more problem on file finishing on a sectioname (@#sectioname)
*            2005-05-24 - add new get_sections_select() method
*            2005-05-18 - add comment line support (with #)
*                       - new method choose_section
*                       - bugfix to avoid infinite loop problem when including section into themselves
*            2005-04-29 - removed some unused properties and method regarding sitename and page_title
*                         clean some error notice
*            2005-04-12 - add_css now support alternate stylesheets and direct css rules inputs, idem for js
*            2005-03-14 - remove some deprecated methods (no more menu related methods)
*                       - replace some deprecated method by some more logical ones
*            2005-03-10 - *NEW callback support 
*                       - tags can now be closed with a / or by a closing tag and %= are replaced with @=
*            2005-02-27 - add the content-type meta tag support and betterify the meta management
*                       - add support for parameters in template tags ie: %=tagname param='value'=%
*                       - menu entrys can now be passed as a full html by setting the URL to null
*/
class block_template{
  /** where all the body content will go */
  var $content;
  var $header;
  /** string favicon link tag */
  var $favicon;
  /** array of css link tags */
  var $css       = array();
  /** array of js link tags */
  var $js        = array(); 
  /** string css definition that will go in the <style></style> tags inside the header */
  var $_css;
  /** string javascript code that will go in the <script></script> tags inside the header */
  var $_js;
  /** @private metas tags parameters */
  var $metas     = array();
  
  /**
  * @param str $page_title 
  * @param str $template_name (the directory containing the template must have the same name (case sensitive))
  * @param str $template_dir  directory containing templates subdirs
  */
  function block_template($page_title,$template_name='default',$template_dir='template'){
    $this->template_dir = $template_dir.(substr($template_dir,-1)=='/'?'':'/');
    $this->template     = $template_name?$template_name:'default';
    $this->set_title($page_title);
    # essaie de charger le fichier de template
    $this->parse_template();
    # ajoute les css par defaut
    if(is_file($css = $this->template_dir.$this->template.'/css.css'))
      $this->add_css($css);
    elseif(is_file($css = $this->template_dir.$this->template.'/'.$this->template.'.css'))
      $this->add_css($css);
  }
  /**
  * send the rendered html code to STD-OUT (browser)
  * cette fonction emetra le signal on-output voici prototype de rappelle callback(&$block_template,$vars,$return)
  *       si la fonction de rapelle renvoie autrechose que FALSE alors la sortie sera remplacé 
  *       par la valeur retourné par la fonction de rappelle
  *@param array $vars same as setcionvars in *templatize* methods
  *@param mixed $return FALSE as default it will print the output to STDOUT as always
  *                     you can set it to true to get the output page return as a function returned value
  *                     and at last but not least you can pass a filename to save the document to.
  *@return void (if $return=FALSE)| string HTML code of the page (if $return=TRUE) | bool (if $return='/path/to/filesave');
  */
  function output($vars=null,$return=FALSE){
    $out = $this->_emit_signal('on-output',$vars,$return); # return callback value if any
    
    if(! $return){ # DEFAULT CASE PRINT ON STDOUT
      if($out){
        print($out);
      }else{
        print("<html>\n");
        print($this->_header());
        print($this->_body($vars));
        print('</html>');
      }
    }elseif(is_string($return)){
      if(! $fout = fopen($return,'w'))
        return FALSE;
      fwrite($fout,$out?$out:"<html>\n".$this->_header().$this->_body($vars).'</html>');
      fclose($fout);
      return TRUE;
    }else{
      return $out?$out:"<html>\n".$this->_header().$this->_body($vars).'</html>';
    }
  }
  /*
  * You will probably never use this one but if you need to display block_template tags (@=tagname/=@) in the output
  * you can use this method to set the output safe.
  * WARNING: this method won't work when the output mode is value (block_template::output(null,TRUE)).
  * other way to say the same: it will only work in STDOUT and file output mode.
  * @param bool $set set it either true or false
  * @return handler | bool
  */
  function set_safe_output($set=TRUE){
    static $handle;
    if($set){ # renvoie le pointeur de callback
      if(isset($handle))
        return $handle;
      else
        return $handle = $this->register_callback('on-output',array($this,'_safe_output')); # no need to work with reference as the emit_signal will send only a reference
    }elseif($handle){ # libere le pointeur de callback si existant
      $ret = $this->unregister_callback($handle);
      unset($handle);
      return TRUE;
    }
    return FALSE;
  }
  /**
  * internally used as callback to protect eventual block_template tags in the output
  * @see set_safe_output 
  * @private
  */
  function _safe_output($block_template,$vars,$return){
    if($return && !is_string($return) )
      return FALSE; # avoid inifnite loop so kill if not in stdout or file output mode
    # protect tags
    $block_template->content = str_replace('@=','@=__SAFE__',$block_template->content);
    if(! substr_count($block_template->content,'@=__SAFE__')) # no replacement so continue as always
      return FALSE;
    # some vars have been protected so we clean them
    return str_replace("@=__SAFE__","@=",$block_template->output($vars,1));
}
  /**
  *
  */
  /**
  * parse a template file 
  * @param string $template_file filepath to the template file
  * @param bool $overwrite will overwrite any previously loaded sections if a new one have the same name
  * @param bool $halt_on_error will stop the script execution on error else will return FALSE
  * @return bool
  * @todo add dynamic include support
  */
  function parse_template($template_file=null,$overwrite=TRUE,$halt_on_error=TRUE){
    if(! $template_file)
      $template_file = $this->template_dir.$this->template.'/template.php';
    elseif( (! file_exists($template_file)) && file_exists($this->template_dir.$this->template.'/'.$template_file) )
      $template_file = $this->template_dir.$this->template.'/'.$template_file;
    if(! ($template = @file_get_contents($template_file)) ){
      if(! $halt_on_error){
        return FALSE;
      }else{
        echo "<b style='color:red;'>[TEMPLATE ERROR] can't open '$this->template' template files</b>";
        exit();
      }
    }
    # suppression des lignes de commentaires
    $template = preg_replace("!^\s*#[^\n]*$!m",'',$template);
    if(! preg_match_all("!(?:@#(\w+)\s*((?:[^@]+|@[^#])+)+)!",$template."\n",$m,PREG_SET_ORDER)) # add \n to correct a bug on last empty section loading
      return FALSE;
    foreach($m as $v){
      if( (!$overwrite) && $this->section_exists($v[1]))
        continue;
      $this->_sections[$v[1]] = trim($v[2]);
    }
    return TRUE;
  }
  /**
  * clean all read template sections,all css rules and the template name.
  * @param string $template_name if passed then will load the new template files;
  * @param bool $full if set to true then will also clean page_title, favicon, content, js, metas, _header
  */
  function reset_($template_name=null,$full=FALSE){
    $this->_css       = null;
    $this->css        = array();
    $this->template   = null;
    $this->_sections  = array();
    if($full){ # reset others vars
      $this->_js = $this->favicon = $this->page_title = $this->content = $this->_header = null;
      $this->js = $this->metas = array();
    }
    if(is_string($template_name))
      $this->block_template($this->page_title,$template_name);
    
  }
  ##### SETTINGS METHODS#####
  /**
  * set the page title
  * @param string $title
  */
  function set_title($title){
    $this->page_title = strip_tags($title);
  }
  ###### ADD HEAD CONTENT METHODS #####
  /**
  * add a favicon to the page
  */
  function add_favicon($favicon){
    $this->favicon = '<link rel="shortcut icon" href="'.$favicon.'" type="image/'.substr($favicon,strrpos('.',$favicon)+1).'">';
  }
  /**
  * add an external css stylesheet or css header definition
  * @param string $css path to css file or css rules
  * @param string $title optionnal title for the stylesheet
  * @param bool   $alternate set to true for alternate stylesheet
  */
  function add_css($css,$title=null,$alternate=FALSE){
    if(preg_match('!{[^}]+}!',$css)) # in this case we consider that we received a css string
      @$this->_css .= $css."\n";
    else
      $this->css[] = '<link href="'.$css.'" rel="'.($alternate?'alternate ':'').'stylesheet" type="text/css" '
                      .(is_string($title)?"title=\"$title\" ":'').'/>';
  }
  /**
  * add a javascript file or function in the header
  * @param string $js path to js file or javascript code to include in the header
  */
  function add_js($js){
    if(substr_count($js,';')) # in this case we consider that we received a js string
      @$this->_js .= $js."\n";
    else
      $this->js[] = '<script src="'.$js.'" type="text/javascript" language="javascript"></script>';
  }
  /**
  * prepare meta tags
  * be aware that multiple calls to this methods for the same type will only append to the previous setted tag.
  * in a word you can only set asingle meta tag for each type (so you can add keywords by successives call of this method usefull 
  * when you want to dinamicly set it form your content)
  * @param string $content
  * @param string $type (publisher,keywords,robots,description,author,copyright,...) New refresh,no-cache
  */
  function add_meta($content,$type='description',$lang=null){
      $type = strtolower($type);
      if(! isset($this->metas[$type]))
        $this->metas[$type] = $content.($lang?"\" lang=\"$lang":'');
      else
        $this->metas[$type] .= $content.($lang?"\" lang=\"$lang":'');
  }
  /**
  * add a string to the header
  * @param string $str string to hadd in the <head></head> HTML tags
  */
  function add_header($str){
    @$this->_header .= "$str\n";
  }
  ###### ADD BODY CONTENT METHODS #####
  /**
  * ajoute du contenu dans la page
  */
  function add_content($content){
    if( func_num_args()>1) # @todo supprimer cette ligne # this is for old stuff detection you can safely delete those 2 lines
      show(print_r(func_get_args(),1).print_r(debug_backtrace(),1),red,1,1);
    $this->content .= $content;
  }
  /**
  * add content by calling the templatize method
  */
  function add_templatize_content($vars,$sectioname){
    if(! $this->section_exists($sectioname)){
      $this->content .= '<b style="color:red;">Missing section '.$sectioname.'</b>';
    }else{
      $this->content .= $this->templatize($vars,$sectioname);
    }
  }
  function add_templatize_string_content($string,$sectionvars=null){
    $this->content .= $this->templatize_string($string,$sectionvars=null);
  }
  /**
  * easy way to add a box to content, that's only a quick way of doing block_template::add_content(block_template::box($content,$title,$boxname))
  * see box for more details
  */
  function add_box_content($content,$title=null,$boxname=''){
    if($str = $this->box($content,$title,$boxname))
      $this->add_content($str);
  }
  /**
  * return a 'BOX_*' section in a more common way
  * BOX_* sections are section containings 2 vars boxtitle and boxcontent
  * this function is the same as calling block_template::templatize(array('boxtitle'=>'title','boxcontent'=>'content'),'BOX_NAME');
  * @param string $content
  * @param string $title may be ommit
  * @param string $boxname the BOX_ section to use
  */
  function box($content,$title='',$boxname=''){
    if(! $boxname)
      $boxname = 'BOX';
    if( substr($boxname,0,3) != 'BOX' )
      $boxname = 'BOX_'.$boxname;
    # maintenant la boite
    if( $boxname = $this->choose_section(array($boxname,'BOX')) )
      $out = $this->templatize(array('boxtitle'=>$title,'boxcontent'=>$content),$boxname);
    else
      $out = "<div id=\"$boxname\"'>".($title?"$title ":'')."$content</div>";
    return $out;
  }
  /**
  * add some attribute to the body tag, an onload  event for example
  * @param string $paramname name of the attribute
  * @param mixed  $paramvalue value of the attribute
  */
  function add_body_param($paramname,$paramvalue,$overwrite=FALSE){
    if($overwrite)
      $this->body_params[$paramname] = $paramvalue;
    else
      $this->body_params[$paramname] .= $paramvalue;
  }
  
  ##### GESTION DES SIGNAUX #####
  /**
  * enregistre une fonction de callback qui sera appelé lors de certains signaux.
  * @param string $signame nom du signal (on-load, on-output, on-templatize)
  * @param mixed $callback nom de la fonction de callback (peut prendre un tableau array($object,$method))
  * @param string $tagtype type de tag sur lequel on applique le callback 
  *                         0|3|  applique le callback sur tout les types de tag 
  *                         1|    applique le callback uniquement au tag unique
  *                         2|    applique le callback sur des tags disposant de tag de fermeture
  * @param string $sectioname null par defaut, contraint le callback a la section précisé, ou toutes les sections si null
  * @see _emit_signal pour le prototype de rappelle
  * @return int callback handler id
  */
  function register_callback($signame,$callback,$tagtype=3,$sectioname=null){
    static $handlers=array() ,$hid=0; # gestion de pointeurs sur les signaux
    # dereferencement d'un signal pé-éxistant
    if( $signame=='-unregister-' && is_int($callback)){ # on detruit le pointeur sur ce signal
      if( count($handlers) <1  || ! is_array($h=$handlers[$callback]) ) # pointeur invalide
        return FALSE;
      unset($this->callbacks[$h[0]][$h[1]][$h[2]][$callback]);
      unset($handlers[$callback]);
      return TRUE;
    }
    # referencement du signal
    if($tagtype != 1 && $tagtype !=2)
      $tagtype = 3;
    if(! $sectioname>0)
      $sectioname = 'ALL';
    $hid++;
    $this->callbacks[$signame][$tagtype][$sectioname][$hid] = $callback;
    $handlers[$hid] = array($signame,$tagtype,$sectioname);
    return $hid;
  }
  /**
  * permet de dereferencer un callback associé a un signal par le biais de la methode register_callback()
  * @param int $cb_handler pointeur de callback renvoyé par la methode register_callback()
  * @see register_callback()
  * @return bool
  */
  function unregister_callback($cb_handler){
    return $this->register_callback('-unregister-',$cb_handler);
  }
  
  /**
  * le prototype de la fonction de rappelle sera function callback(block_template object,$section,$tagname,$params,$content)
  * @private
  * cette methode est utilisé par l'objet en interne afin de gerer les signaux 
  * @param string $signame nom du signal emis (on-templatize,on-output);
  * @see _templatize output
  */
  function _emit_signal($signame,$params=null,$tagname=null,$content=null,$section=null){
    $tagtype = (strlen($content)?2:1);
    if(! isset($this->callbacks[$signame]))
      return FALSE;
    # on test d'abord les callbacks restreint a cette section et a ce type de tag
    if(@is_array($this->callbacks[$signame][$tagtype][$section])){
      foreach($this->callbacks[$signame][$tagtype][$section] as $cb){
        $res = call_user_func($cb,&$this,$section,$tagname,$params,$content);
        if($res !== FALSE && $res !==null )
          return $res;
      }
    }
    # ensuite ceux restreint a cette section quel que soit le type de tag
    if(@is_array($this->callbacks[$signame][3][$section])){
      foreach($this->callbacks[$signame][3][$section] as $cb){
        $res = call_user_func($cb,&$this,$section,$tagname,$params,$content);
        if($res !== FALSE && $res !==null )
          return $res;
      }
    }
    # puis ceux restreint a ce type de tag
    if(@is_array($this->callbacks[$signame][$tagtype]['ALL'])){
      foreach($this->callbacks[$signame][$tagtype]['ALL'] as $cb){
        $res = call_user_func($cb,&$this,$section,$tagname,$params,$content);
        if($res !== FALSE && $res !==null )
          return $res;
      }
    }
    # puis enfin les generalistes qui se foutent de la section ou du type de tag
    if(@is_array($this->callbacks[$signame][3]['ALL'])){
      foreach($this->callbacks[$signame][3]['ALL'] as $cb){
        $res = call_user_func($cb,&$this,$section,$tagname,$params,$content);
        if($res !== FALSE && $res !==null )
          return $res;
      }
    }
    return FALSE;
  }
  
  ##### TEMPLATIZE METHODS #####
  /*
  * will templatize your datas you can have as much vars as you like
  *   optionnal sub section tag can be used by adding a * to the sectioname (ie: sectioname*) 
  *   if so thoose sections will be checked that there's either subsection or at least one not null (null or false but not 0) value in it
  * @param array $sectionvars is an indexed array with index in $sectionkey giving the correspoding datas
  * @param string $sectioname self explain
  * @param bool $section_optional (used in internal for optionnal sub section you'll normally never use this one by your own)
  */
  function templatize($sectionvars,$sectioname,$section_optional=FALSE){
    $sectioname = strtoupper($sectioname);
    if(! $this->section_exists($sectioname) )
      return FALSE;
    $section      = $this->_sections[$sectioname]; # recupere le contenu de la section
#    $section_keys = $this->get_section_vars($sectioname); # recupere les tags de la section
    return $this->_templatize($section,$sectionvars,$sectioname,$section_optional);
  }
  /** 
  * parse la chaine $string comme une section de template. 
  * Cela permet au programmeur de parser une chaine recue d'une base de données ou encore généré dynamiquement.
  * @note Cette méthode à été ajouter car elle me parassait apporter une certaine souplesse dans l'utilisation de block_template,
  *       cependant n'en ayant jamais fait usage, je serais tres interresser d'etre informé de l'utilisation que vous pouriez en faire.
  */
  function templatize_string($string,$sectionvars=null){
#    $section_tags = $this->get_string_vars($string);
    return $this->_templatize($string,$sectionvars);
  }
  /**
  * methode interne pour les methodes 'templatize'
  * @see templatize,templatize_string
  * @private
  * @param string $section     contenu de la section (ou chaine si on a appeller templatize_string)
  * @param array  $sectionvars variables en provenance du programmeur
  * @param string $sectioname  le nom de la section sur laquelle on travaille
  * @param bool   $section_optional flag pour le traitement des sections incluse (par un tag)
  * @return string
  */
  function _templatize($section,$sectionvars,$sectioname=null,$section_optional=FALSE){
    # recuperation des variables 
    if($sectioname && ($keys = $this->get_section_vars($sectioname)) )
      $section_keys = &$keys;
    elseif($section && ($keys = $this->get_string_vars($section)) )
      $section_keys = &$keys;

    if( @is_array($section_keys) ){ # ne traite les variables que si il y en a
      # on verifie que les sections optionnelles recoivent au moins une variable non null
      if( $section_optional){
        if(isset($sectionvars['require'])){ # verifie les prérequis
          $required = explode(',',$sectionvars['require']);
          foreach($required as $req){
            if(! (@$sectionvars[$req] || $this->section_exists($req)))
              return FALSE;
          }
        }else{
          foreach($section_keys as $key){
            if( $this->section_exists($key['tagname']) || (isset($sectionvars[$key['tagname']]) && $sectionvars[$key['tagname']]!='') ){ $vars=TRUE;break; }
          }
          if(! isset($vars))
            return FALSE;
        }
      }
      
      if(! is_array($sectionvars)) $sectionvars = array();
      
      # on remplace les tags
      foreach($section_keys as $var){
        #preparation des parametres de la fonction de callback
        $_params = array_merge((array) @$var['params'],$sectionvars);
        
        # peparsing des parametre si demandé
        if(isset($_params['preparse'])){
          if($preparse = explode(',',$_params['preparse'])){
            unset($_params['preparse']);
            foreach($preparse as $k){
              $_params[$k] = $this->templatize_string($_params[$k],$_params);
            }
          }
        }
        
        # emission du signal on-templatize sur ce tag
        $tmp_str = $this->_emit_signal('on-templatize',$_params,$var['tagname'] ,@$_params['tagcontent'],$sectioname);
        if($tmp_str!==FALSE){
          $section = str_replace($var['str_replace'],$tmp_str,$section);
          continue;
        }
        
        # si le tag porte le nom d'une section on l'inclus
        if(isset($this->_sections[$var['tagname']])){
          if( (! $var['is_optionnal']) && isset($_params['require'])) $var['is_optionnal']=TRUE;
          $section = str_replace($var['str_replace'],$this->templatize($_params,$var['tagname'],$var['is_optionnal']),$section);
          continue;
        }
        # prepare la valeur de remplacement 
        if( isset($_params[$var['tagname']]) ){ # cherche un parametre du meme nom
          $value = $_params[$var['tagname']];
          # on verifie que ce n'est pas une reference vers un autre parametre
          if( $value && $value[0]=='@' && isset($_params[substr($value,1)]) ){
            $value = $_params[substr($value,1)];
          }
        }elseif( isset($_params['default']) ){ # sinon prend la valeur par defaut
          $value = $_params['default'];
        }else{
          $value = '' ;
        }
        # si c'est le nom d'une section on remplace par la section (pas d'inclusion optionnelle ici)
        if($this->section_exists($value) && $value !== $sectioname)
          $section = str_replace($var['str_replace'],$this->templatize($_params,$value),$section);
        else # sinon on remplace par sa valeur
          $section = str_replace($var['str_replace'],$value,$section);
      }
    }
    
    return $section;
  }
  ##### GETTING VARS #####
  /**
  * renvoie les variables attendus par la section $sectioname du template
  * @param string $sectioname le nom de la section
  * @param bool $nocache  par defaut vaut false ainsi les resultats sont gardé en cache de facon a accellerer les futures requetes.
  *                       il peut s'averer utile de ne pas caché ses resultats (pour une section appeller une seule fois par exemple)
  *                       auquel cas il suffit de passer cette option a TRUE
  * @param bool $include_vars par defaut vaut FALSE si passer a TRUE alors retourne aussi les variables attendu par les sections incluses ou imbriqués.
  * @return array or FALSE if none 
  *         the array will contain arrays(tagname,params,str_replace,is_optionnal[,content]) for complex vars,
  *         where sectionvarname is equal to the sting return for single vars, params is an array of parameter array('paramname or int'=>'value',...)
  *         and finally the original_tag which is the complete tag as it is in the template (will be use for string replacement)
  */
  function get_section_vars($sectioname,$nocache=FALSE,$include_vars=FALSE){
    static $sectionvars,$fullsectionvars;
    
    if(! $this->section_exists($sectioname)) # first of all check that the section exists
      return FALSE;
    
    if($include_vars){ # recursively append all included sections vars to the result
      if( (!$nocache) && @is_array($fullsectionvars[$sectioname]) ) # return cached datas if exists according to $nocache
        return $fullsectionvars[$sectioname];
      # get first level sectionvars using or not cached datas
      if(! is_array($svars = $this->get_section_vars($sectioname,$nocache,FALSE)) )
        return FALSE;
      # walk thru sectionvars to get vars of included sections.
      foreach($svars as $var){ 
        if($this->section_exists($var['tagname']) && is_array($vars_ = $this->get_section_vars($var['tagname'],$nocache,TRUE)) )
          foreach($vars_ as $vars__) $svars[] = $vars__; 
      }
      if($nocache)
        return $svars;
      else
        return $fullsectionvars[$sectioname] = $svars;
    }
    
    if($nocache) # no cache so give the result as is
      return $this->get_string_vars($this->_sections[$sectioname]);
    
    # return cached content and create it if needed
    if(isset($sectionvars[$sectioname]) && is_array($sectionvars[$sectioname]))
      return $sectionvars[$sectioname];
    else
      return $sectionvars[$sectioname] = $this->get_string_vars($this->_sections[$sectioname]);
  }
  /**
  * renvoie les variables contenue dans la chaine $string comme si c'était une section de template
  * @param string string
  * @todo devrait fonctionner selon un principe de 'pile' afin de permettre la lecture de tags imbriqués
  */
  function get_string_vars($string){
    # $tagexp = "!@=(\w+)(\*)?" # tagname
              # ."((?:[^@]+|[^=]@)+)?" # params
              #// ."(/)?=@((?(4)(.*?)@=/\\1=@))!s" ;
              # ."(?:/=@|=@(.*?)@=/\\2=@)!s" ;
    $tagexp = "!@=(\w+)(\*)?((?:\s+\w+(?:\s*=\s*([\"']).*?\\4))+)?\s*(?:/=@|=@(.*?)@=/\\1=@)!s";
    # check single vars as needed
    if(! preg_match_all($tagexp,$string,$m,PREG_SET_ORDER)){
      $vars =  FALSE;
    }else{
      foreach($m as $k=>$tagdata){
        $vars[$k]['tagname']       = $tagdata[1];
        $vars[$k]['is_optionnal']  = (bool) @$tagdata[2];
        # $vars[$k]['is_optionnal']  = (bool) (substr($tagdata[1],-1)==='*');
        if(isset($tagdata[3])){
          preg_match_all("!\s+(\w+)(?:\s*=\s*(([\"'])?(?(3).*?\\3|[^\s=]+)))?!s",$tagdata[3],$m2,PREG_SET_ORDER);
          unset($params);
          foreach($m2 as $k2=>$v2){
            if(! isset($v2[2])){
              $params[] = $v2[1];
            }else{
              if(! isset($v2[3]))
                $params[$v2[1]] = $v2[2];
              else
                eval('$params[$v2[1]] = '.$v2[2].';');
            }
          }
          $vars[$k]['params'] = @$params;
        }
        if(isset($tagdata[5])){
          # $vars[$k]['content']     = $tagdata[5];
          # $vars[$k]['params']['tagcontent'] = $vars[$k]['content']; # Quick and dirty hack to enable the 'tagcontent' parameter
          $vars[$k]['params']['tagcontent'] = $tagdata[5];
        }
        $vars[$k]['str_replace'] = $tagdata[0];
      }
    }
    return $vars;
  }
  ##### MANIPULATION DES SECTIONS #####
  /**
  * renvoie un tableau contenant le nom des sections disponibles dans le template
  * @return array or FALSE si pas de sections
  */
  function get_sections(){
    if(! is_array($this->_sections)) return FALSE;
    return array_keys($this->_sections);
  }
  /**
  * retourne le code html d'un element select contenant la liste des sections du template.
  * @param string $name     nom de l'element de formulaire (valeur de l'attribut name de la balise select)
  * @param string $selected nom de la section preselectionnée (si null alors essaie de trouver une occurence dans _POST ou _GET)
  * @param bool   $autoselect si oui alors ajoute un submit onchange
  * @param string $id attribut id optionnel de la balise select.
  * @return string HTML code
  */
  function get_sections_select($name='template_section',$selected=null,$autoselect=TRUE,$id=null){
    if(! $sections = $this->get_sections())
      return "<b style='color:silver;'>Aucune section disponible</b>";
    # try to find the selected value
    if(is_null($selected) && (isset($_GET[$name])||isset($_POST[$name])) )
      $selected = (@$_POST[$name]?$_POST[$name]:(@$_GET[$name]?$_GET[$name]:null));
    # make option list
    $opts[] = "<option value=\"\">- Sections du template $this->template -</option>";
    foreach($sections as $sec){
      $opts[] = "<option value=\"$sec\"".(($selected && $sec==$selected)?' selected="selected"':'')." >$sec</option>";
    }
    return "\n\t<select name=\"$name\"".($autoselect?' onchange="if(this.value!=\'\')this.form.submit();"':'').(is_string($id)?" id=\"$id\"":'')." >\n\t\t".implode("\n\t\t",$opts)."\n\t</select>";
  }
  /**
  * retourne le contenue d'une section de template tel quel sans le parser
  * @param string $sectioname
  * @return string
  */
  function get_section($sectioname){
    return $this->section_exists($sectioname)?$this->_sections[$sectioname]:FALSE;
  }
  /**
  * verifie qu'une section existe
  * @param string $sectioname nom de la section dont on veut verifier l'existence
  * @param bool   $returnname si passer a TRUE alors la fonction retournera le nom de la section en cas de succes au lieu de TRUE
  * @return bool
  */
  function section_exists($sectioname,$returnname=FALSE){
    $ret = isset($this->_sections[$sectioname]);
    if($returnname && $ret)
      return $sectioname;
    return $ret;
  }
  /**
  * prend une liste de nom de section sous forme de tableau ou de chaine et retourne la premiere qui est trouvé.
  * cette fonction peut etre utile si votre application veut permettre l'utilisation de section par defaut au cas ou le
  * template ne fournirais pas la section données par exemple: block_template->choose_section('SEC1|SEC2|SEC3) testera successivement
  * les sections passé en arguments et retournera la premiere section existante.
  * @param mixed $section_list string('SEC1|SEC2...') ou array(SEC1,SEC2..)
  * @return string first section name matching an existing section or '' if no section match and false on input error
  */
  function choose_section($section_list){
    if(is_string($section_list))
      $section_list = explode('|',$section_list);
    if(! is_array($section_list))
      return FALSE;
    foreach($section_list as $v){
      if($this->section_exists($v) )
        return $v;
    }
    return '';
  }
  
  /**
  * permet l'ajout dynamique de section par le programmeur 
  * @param string $sectioname le nom de la section
  * @param string $section_content le contenu de la section
  * @param bool   $overwrite si passe a TRUE alors ecrasera une eventuelle section existante au lieu de renvoyer FALSE
  */
  function add_section($sectioname,$section_content='',$overwrite=FALSE){
    if($overwrite || !$this->section_exists($sectioname) )
      $this->_sections[$sectioname] = $section_content;
    else
      return FALSE;
  }
  /**
  * ajoute du contenu a la fin d'une section
  * @param string $sectioname le nom de la section
  * @param string $section_content contenu a ajouter
  * @param bool   $autocreate TRUE par defaut, si FALSE ne creera pas la section si elle n'existe pas
  */
  function append_section($sectioname,$section_content,$autocreate=TRUE){
    if( (!$this->section_exists($sectioname)) && !$autocreate )
      return FALSE;
    $this->_sections[$sectioname] = ($this->section_exists($sectioname)?$this->_sections[$sectioname]:'').$section_content;
  }
  /**
  * ajoute du contenu au debut d'une section
  * @param string $sectioname le nom de la section
  * @param string $section_content contenu a ajouter
  * @param bool   $autocreate TRUE par defaut, si FALSE ne creera pas la section si elle n'existe pas
  */
  function prepend_section($sectioname,$section_content,$autocreate=TRUE){
    if( (!$this->section_exists($sectioname)) && !$autocreate )
      return FALSE;
    $this->_sections[$sectioname] = $section_content.($this->section_exists($sectioname)?$this->_sections[$sectioname]:'');
  }
  ##### PREPARATION DES SORIES #####
  /**
  *Prepare the header to output
  *@access Private
  */
  function _header(){
    $this->header  = "<head>\n";
    $this->header .= "<title>$this->page_title</title>\n";
    # add the meta tags
    if($this->metas){
      $equivs = array('content-type','refresh','pragma','expires');
      foreach($this->metas as $name=>$value){
        if(in_array($name ,$equivs))
          $this->header .= "<meta http-equiv='$name' content='$value' />\n";
        else
          $this->header .= "<meta name=\"$name\" content=\"$value\" />\n";
      }
    }
    # add favicon
    if(is_string($this->favicon))
      $this->header .= $this->favicon."\n";
    # add css 
    if(is_array($this->css))
      $this->header .= implode("\n",$this->css);
    if(is_string($this->_css))
      $this->header .= '<style type="text/css">'.$this->_css.'</style>';
    # add js
    if(is_array($this->js))
        $this->header .= implode("\n",$this->js);
    if(is_string($this->_js))
      $this->header .= "<script type=\"text/javascript\" language=\"javascript\">\n<!--\n".$this->_js."\n//-->\n</script>";
    # add user specific content
    $this->header .= (isset($this->_header)?$this->_header:'')."\n</head>\n";
    return $this->header;
  }
  
  /**
  *Prepare the body content to output
  *@access Private
  *@todo supprimer les variables logo et consorts
  */
  function _body($bodyvars=null){
    if(! is_array($bodyvars)) $bodyvars = array();
    # prepare les parametres du tag body
    if(@is_array($this->body_params)){
      foreach($this->body_params as $paramname=>$paramvalue)
        $bodytag .= " $paramname=\"$paramvalue\"";
      $bodyvars['bodyparams'] = $bodytag;
    }
    $bodyvars['content'] = isset($this->content)?$this->content:'';
    return $this->body = $this->templatize($bodyvars,'BODY');
  }
  /**
  * retourne le code de la chaine comme un code source de template avec coloration syntaxique au format html
  * @param str $str chaine de caractere a colorer
  * @param str $outfile nom de fichier de sortie optionnel, si fournis alors la sortie sera sauvegarder dans un fichier.
  */
  function highlight_str($str,$outfile=null){
    if(! is_string($str))
      return FALSE;
      
    $str = htmlspecialchars($str);
    $str = preg_replace('!(@#\w+)!',"<b style='color:#3333cc;'>$1</b>",$str);
    $str = preg_replace('!(@=\w+)!',"<b style='color:#33cc33;'>$1",$str);
    $str = preg_replace('!(=@)!',"$1</b>",$str);
    
    # return "$str";
    return "<code><pre>$str</pre></code>";
  }
  function highlight_section($sectioname,$outfile=null){
    return $this->highlight_str($this->_sections[$sectioname],$outfile);
  }
  function highlight_template_file($file=null,$outfile=null){
    if(is_null($file))
      $file = $this->template_dir.$this->template.DIRECTORY_SEPARATOR.'template.php';
    return $this->highlight_str(join('',file($file)),$outfile);
  }
}
?>

 
  Advertise on this site Advertise on this site   Site map Site map   Statistics Statistics   Site tips Site tips   Privacy policy Privacy policy   Contact Contact  

For more information send a message to :
info at phpclasses dot org.
Copyright (c) Icontem 1999-2009 PHP Classes - PHP Class Scripts
  PHP Book Reviews - Reviews of books and other products