Código 4 min de lectura 738 palabras

Implementar Haanga como sistema de plantillas para OpenCart

EN
Implementar Haanga como sistema de plantillas para OpenCart

OpenCart es una plataforma de comercio electrónica hecha en php, con un desarrollo impecable, 100% MVC. Como prueba de concepto he reescrito el sistema de plantillas de OpenCart a Haanga (plantillas “Django” para PHP, über eficiente) de César Rodas.

¿ Por que Haanga ?, simplemente porque me gusta.

¿ Por qué OpenCart ?, simplemente porque me gusta como está desarrollado.

Implementación, he creado una clase TemplateEngine con el siguiente código:

class TemplateEngine {
 		public $template = null ;
 		public $default = array();
 		public $config = array();

 		function __construct( $templateDir = null  ) {
 			$this->loadDefaults( $templateDir);
 		}
 		

 		protected function loadDefaults( $templateDir) {
 			$this->default = array();
 				$this->config = array(
				'template_dir' => (( is_null( $templateDir )) ? Settings::getInstance()->getValue('Web.root') .'templates' : $templateDir),
				'cache_dir' =>  Settings::getInstance()->getValue('Web.root'). 'cache.templates',
				'compiler' => array(  
					'if_empty' => FALSE,
					'autoescape' => FALSE,
					'strip_whitespace' => TRUE, 
 					'allow_exec'  => TRUE,
					'global' => array(	),
					'use_hash_filename' => FALSE   
				)
			);
 		}	
	
		function loadEngine() {
			// incluimos Haanga		
 			require_once Settings::getInstance()->getValue('Web.root') . 'lib/vendors/Haanga.php';
 	 		Haanga::configure($this->config); 

		
		
		}
 		 function loadTemplate( $name ) {
 			$this->template =   $name  ;
 		}
 		 function display( $vars = array()) {
 			$this->loadEngine();
 	 		$vars = array_merge( $this->default, $vars);
  			Haanga::Load( $this->template , $vars);
  		
 		}
	
	}

Ahora sólo queda indicarle al opencart que haga uso de esta clase:

en /system/engine/controller.php

Modificando los métodos render y fetch, renombrando el antiguo fetch a __fetch

[...]
protected function render($return = FALSE) {
		foreach ($this->children as $child) {
			$action = new Action($child);
			$file   = $action->getFile();
			$class  = $action->getClass();
			$method = $action->getMethod();
			$args   = $action->getArgs();
		
			if (file_exists($file)) {
				require_once($file);

				$controller = new $class($this->registry);
				
				$controller->index();
				$this->data[$controller->id] =  $controller->output;
				
				$this->addToModule( $controller->id, $controller->output );
				} else {
				exit('Error: Could not load controller ' . $child . '!');
			}
		}
		
		if ($return) {
			return $this->fetch($this->template);
		} else {
			$this->output = $this->fetch($this->template);
		}
	}
	
		protected function addToModule( $module , $output ) {
			$i = 0 ;
			if ( !isset( $this->data['modules'] )) { return ;}
			foreach( $this->data['modules'] as $item ) {
				if ( $item['code'] == $module ) {
					$this->data['modules'][$i]['output'] = $output;
					return ;
				
				}
				$i++;
			}
		
		}
	
		protected function fetch($filename) {
			if ( substr( $_SERVER['REQUEST_URI'], 0, 7) == '/admin/') {
				return $this->__fetch( $filename);
			
			} else {
        		ob_start();
     		$this->templateEngine->loadTemplate( $filename );
     		$this->templateEngine->display( $this->data); 
	  		$content = ob_get_contents();
      		ob_end_clean();
      		return $content;
      		}
    }
protected function __fetch($filename) {
		$file = DIR_TEMPLATE . $filename;
    		if (file_exists($file)) {
			extract($this->data);
  		ob_start();
      
	  		require($file);
      
	  		$content = ob_get_contents();

      		ob_end_clean();

      		return $content;
    	} else {
      		exit('Error: Could not load template ' . $file . '!');
    	}
	}

[...]

Para evitar utilizar Haanga en la administración se comprueba que la url no sea de la administración, de ser así se utiliza el motor de plantillas original.

[...]
			if ( substr( $_SERVER['REQUEST_URI'], 0, 7) == '/admin/') {
				return $this->__fetch( $filename);
[...]

Una de las particularidades de las plantillas es que hacen uso de $$variable a la hora de mostrar la salida de los módulos, y es por esto (imposible, por lo que parece, en Haanga) que he añadido un método y comprobación para que cada módulo devuelva a la plantilla su salida en un elemento “output” de la matriz y es el que mostraremos.

Así, al final, una plantilla como la de la visualización de las categorías queda en algo como los siguientes ejemplos:

/catalog/view/theme/default/common/column_right.tpl

<div id="column_right">
  {% for module in modules %}
    
      {{ module.output }}
    
    {% endfor %}
  
  
</div>

/catalog/view/theme/default/product/category.tpl

{% extends "layout/default.html" %}
{% block content %}


<div id="content">
  <div class="top">
    <div class="left">
      
    </div>  
        
    
    <div class="right">
      
    </div>
        
    
    <div class="center">
      <h1>
        {{ heading_title }}
      </h1>
          
    </div> 
      
  </div> 
    
  
  <div class="middle">
    <table style="padding-bottom:10px;">
      <tr>
        {% if thumb %}
                
        
        <td>
          <img src="{{ thumb }}" alt="{{ heading_title }}" />
        </td>	  
        	{% endif %}
                {% if description %}
         	    
        
        <td>
          {{ description }}
        </td>
        	{% endif %} 
        	  
      </tr>     
      	
    </table>
    	
    	{% if  !categories  &#038;&#038;   !products %}
    
    <div class="content">
      {{ text_error|default:"" }}
    </div>{% endif %}
         
        {% if categories %}
      
      	
    
    <table>
      {% for category in categories %}
           
        		
                <a href="{{ category['href'] }}"><img src="{{ category['thumb'] }}" title="{{ category['name'] }}" alt="{{ category['name'] }}" style="margin-bottom: 3px;" /></a><br />
                <a href="{{ category['href'] }}">{{ category['name'] }}</a>
       
          
    </table>
        {% endfor %}
      
    	{% endif %}
    	 
    	
    	
        {% if products %} 
        
    
    <div class="sort">
      <div class="div1">
        <select name="sort" onchange="location = this.value">
                	{% buffer sort_order %}{{sort}}-{{order}}{% endbuffer %}
        
                	{% for sort  in sorts %}
                   &lt;option value="{{ sort['href'] }}" {% if sort_order == sort['value'] %} selected="selected"{% endif %}>{{ sort['text'] }}&lt;/option>
                  {% endfor %}
                </select>
              
      </div>
            
      
      <div class="div2">
        {{ text_sort }}
      </div>
          
    </div>
       
       
       {% inline "elements/lista_productos.html" %}
        
        	
        	
        
    
    <div class="pagination">
      {{ pagination }}
    </div>
    
    	{% endif %}
    
      
  </div>
    
  
  <div class="bottom">
    <div class="left">
      
    </div>
        
    
    <div class="right">
      
    </div>
        
    
    <div class="center">
      
    </div>
      
  </div>
  
</div>
{% endblock %}