Herramientas Documentacin http doc prestashop comdashboard action https
Herramientas - Documentación * http: //doc. prestashop. com/dashboard. action * https: //www. prestashop. com/forums/
Herramientas - Git (colaborar en el proyecto prestashop) - Jira (sistema de seguimiento de bugs. Prestashop forge) - Generador de módulos - Validador de módulos
Herramientas - Herramientas de desarrollo * Netbeans * Xdebug * Firebug * Presta. Shop norm validator (PHP_Code. Sniffer) https: //github. com/Presta. Shop-norm-validator https: //github. com/squizlabs/PHP_Code. Sniffer * Standard coding hook (git) https: //github. com/Presta. Shop/standard_coding_hook * Testing framework (PHPUnit) https: //phpunit. de/ https: //github. com/sebastianbergmann/phpunit * Go to validator in the FAQ module 1. 4. 0 https: //www. prestashop. com/forums/topic/113050 -module-faq-gratuit-ps-14 -et-ps-132/
Desarrollando módulos - Ficheros * Directorio del módulo (nombre_del_módulo) * Fichero “hook” (nombre_del_módulo. php) * Ficheros de idioma (en 1. 6 van dentro del directorio. /translations/) * Fichero cache de configuración (config. xml) * Controladores. /controllers/ * Clases* sobreescritas. /override/ * Ficheros de vistas (en 1. 6 van dentro del directorio. /views/). “. /views/css”, “. /views/sass”, “. /views/js”, “. /views/templates/front” (vistas usadas por el controlador), “. /views/templates/hooks” (vistas usadas por los hooks del módulo) * Logos (16 x 16 gif / 32 x 32 png) * Readme. md * Para versiones superiores a 1. 6. 0. 11 puede haber un directorio. /test con los ficheros de testeo
Desarrollando módulos Fichero “hook” <? php if (!defined('_PS_VERSION_')) exit; class Hello. World extends Module { }
Desarrollando módulos La función de inicialización: public function __construct() { $this->name = 'helloworld'; $this->tab = 'front_office_features'; $this->version = '1. 0. 0'; $this->author = 'Me'; $this->bootstrap = true; // New 1. 6 $this->ps_versions_compliancy = array('min' => '1. 5', 'max' => '1. 6'); // required Prestashop 1. 5 $this->dependencies = array('blockcart'); // need blockcart module. . } Desde este momento el módulo es visible en el backoffice
Desarrollando módulos La función de inicialización: public function __construct() { . . . parent: : __construct(); $this->display. Name = $this->l('Hello World'); $this->description = $this->l('This is an example module'); $this->confirm. Uninstall = $this->l('Are you sure you want to uninstall? '); if (!Configuration: : get('HELLO_WORLD_NAME')) $this->warning = $this->l('No name provided'); } Desde este momento el módulo es visible en el backoffice
Desarrollando módulos Ejemplo 'blockcategories' (La función de inicialización) public function __construct() { $this->name = 'blockcategories'; $this->tab = 'front_office_features'; $this->version = '2. 9. 4'; $this->author = 'Presta. Shop'; $this->bootstrap = true; parent: : __construct(); $this->display. Name = $this->l('Categories block'); $this->description = $this->l('Adds a block featuring product categories. '); $this->ps_versions_compliancy = array('min' => '1. 6', 'max' => _PS_VERSION_); }
Desarrollando módulos El fichero cache: El fichero cache lo puede crear automáticamente Prestashop, y se va a utilizar para que se generen las listas de módulos de forma más rápida en el backoffice. <? xml version="1. 0" encoding="UTF-8" ? > <module> <name>helloworld</name> <display. Name>Hello World></display. Name> <version>1. 0></version> <description>This is an example module></description> <author>Moi</author> . . . </module>
Desarrollando módulos El fichero cache: El fichero cache lo puede crear automáticamente Prestashop, y se va a utilizar para que se generen las listas de módulos de forma más rápida en el backoffice. <? xml version="1. 0" encoding="UTF-8" ? > <module> . . . <tab>front_office_features></tab> <confirm. Uninstall>Are you sure you want to uninstall? </confirm. Uninstall> <is_configurable>1</is_configurable> <need_instance>1</need_instance> <limited_countries></limited_countries> </module>
Desarrollando módulos Ejemplo 'blockbanner' (El fichero cache) <? xml version="1. 0" encoding="UTF-8" ? > <module> <name>blockbanner</name> <display. Name><![CDATA[Banner block]]></display. Name> <version><![CDATA[1. 4. 0]]></version> <description><![CDATA[Displays a banner at the top of the store. ]]></description> <author><![CDATA[Presta. Shop]]></author> <tab><![CDATA[front_office_features]]></tab> <is_configurable>1</is_configurable> <need_instance>0</need_instance> <limited_countries></limited_countries> </module>
Desarrollando módulos La función de instalación: public function install() { if (Shop: : is. Feature. Active()) Shop: : set. Context(Shop: : CONTEXT_ALL); if (!parent: : install() OR !$this->register. Hook('left. Column') OR !$this->register. Hook('header') OR !Configuration: : update. Value('HELLO_WORLD_NAME', 'World')) return false; return true; }
Desarrollando módulos Ejemplo 'blockcategories' (La función de instalación) public function install() { // Prepare tab $tab = new Tab(); $tab->active = 1; $tab->class_name = 'Admin. Block. Categories'; $tab->name = array(); foreach (Language: : get. Languages(true) as $lang) $tab->name[$lang['id_lang']] = 'Block. Categories'; $tab->id_parent = -1; $tab->module = $this->name; … }
Desarrollando módulos Ejemplo 'blockcategories' (La función de instalación) public function install() { . . . if (!$tab->add() || !parent: : install() || !$this->register. Hook('footer') || !$this->register. Hook('header') || !$this->register. Hook('left. Column') || … }
Desarrollando módulos Ejemplo 'blockcategories' (La función de instalación) public function install() { . . . // Temporary hooks. Do NOT hook any module on it. Some CRUD hook will replace them as soon as possible. !$this->register. Hook('category. Addition') || !$this->register. Hook('category. Update') || !$this->register. Hook('category. Deletion') || !$this->register. Hook('action. Admin. Meta. Controller. Update_options. Before') || !$this->register. Hook('action. Admin. Languages. Controller. Status. Before') || !$this->register. Hook('display. Back. Office. Category') || !Configuration: : update. Value('BLOCK_CATEG_MAX_DEPTH', 4) || !Configuration: : update. Value('BLOCK_CATEG_DHTML', 1) || !Configuration: : update. Value('BLOCK_CATEG_ROOT_CATEGORY', 1)) return false; return true; }
Desarrollando módulos La función de desinstalación: public function uninstall() { if (!parent: : uninstall() || !Configuration: : delete. By. Name('HELLO_WORLD_NAME') ) return false; return true; }
Desarrollando módulos Ejemplo 'blockcategories' (La función de desinstalación) public function uninstall() { if (!parent: : uninstall() || !Configuration: : delete. By. Name('HELLO_WORLD_NAME') ) return false; return true; }
Desarrollando módulos Función para mostrar algo en algún hook: public function hook. Display. Left. Column($params) { $this->context->smarty->assign(array( 'name' => Configuration: : get('HELLO_WORLD_NAME') )); return $this->display(__FILE__, 'helloworld. tpl'); }
Desarrollando módulos Función para mostrar algo en algún hook (Cont. ) Podemos reutilizar el código para otro hook: public function hook. Display. Right. Column($params) { return $this->hook. Display. Left. Column($params); }
Desarrollando módulos Función para mostrar algo en algún hook (Cont. ) Si queremos añadir archivos css o js utilizaremos: public function hook. Display. Header($params) { $this->context->controller->add. CSS($this->_path. 'views/css/helloworld. css', 'all'); }
Desarrollando módulos Función para mostrar algo en algún hook (Cont. ) Hook. Display. . . : Para usar un Hook en un Template usamos Smarty, {hook h='Name. Of. Hook'} Ejemplo: <div> {hook h = "display. Banner"} </div> Para usar un Hook en un Controller, Hook: : exec('Name. Of. Hook') Ejemplo: $this->context->smarty->assign('HOOK_LEFT_COLUMN', Hook: : exec('left. Column'));
Desarrollando módulos Función para mostrar algo en algún hook (Cont. ) Hook. Display. . . (Cont. ) Para usar un Hook en un Módulo debemos crear un método no estático y publico, cuyo nombre comience por "hook", seuido de "Display" o "Action" (según el hook en el queramos mostrar o ejecutar código), y el nombre del hook queramos. Al metodo le pasaremos un solo argumento, con información del objeto context. public function hook. Display. Name. Of. Hook($params) { }
Desarrollando módulos Función para mostrar algo en algún hook (Cont. ) Hook. Display. . . (Cont. ) Para responder a la llamada de un hook en el módulo, este hook debe estar registrado en Presta. Shop. El registro se realiza con la función "register. Hook". El registro* se crea durante la instalación del módulo. public function install() { return parent: : install() && $this->register. Hook('Name. Of. Hook'); }
Desarrollando módulos Función para mostrar algo en algún hook (Cont. ) Hook. Display. . . (Cont. ) Podemos crear un nuevo hook, añadiendo un nuevo registro a la tabla "ps_hook"*, y teniendo en cuenta que vamos a tener que incorporar este hook a nuestro tema. . . $my. Hook = new Hook() $my. Hook->name = 'name. Of. Hook'; $my. Hook->title = 'Title of Hook'; $my. Hook->description = 'It is a custom hook !'; $my. Hook->active = true; $my. Hook->save(); Desde la versión 1. 5, se añaden automaticamente los hook a la tabla 'ps_hook', cuando llamamos a la función register. Hook('name. Of. Hook') en la clase del módulo.
Desarrollando módulos Configurar nuestro módulo: public function get. Content() { $output = ''; if (Tools: : is. Submit('submit'. $this->name)) { $HELLO_WORLD_NAME = strval(Tools: : get. Value('HELLO_WORLD_NAME')); if (!$HELLO_WORLD_NAME OR empty($HELLO_WORLD_NAME) OR !Validate: : is. Generic. Name($HELLO_WORLD_NAME)) $output. = $this->display. Error( $this->l('Invalid Configuration value') ); else . . . }
Desarrollando módulos Configurar nuestro módulo (Cont. ) public function get. Content() { . . . else { Configuration: : update. Value('HELLO_WORLD_NAME', $HELLO_WORLD_NAME); $output. = $this->display. Confirmation($this->l('Settings updated')); } } return $output. $this->display. Form(); }
Desarrollando módulos Configurar nuestro módulo (Cont. ) Para mostrar nuestra página de configuración: public function display. Form() { }
Desarrollando módulos Configurar nuestro módulo (Cont. ) Para mostrar nuestra página de configuración: public function display. Form() { $default_lang = (int)Configuration: : get('PS_LANG_DEFAULT'); // Get default Language $fields_form[0]['form'] = array( // Init Fields form array 'legend' => array( 'title' => $this->l('Settings') ), 'input' => array( … }
Desarrollando módulos Configurar nuestro módulo (Cont. ) public function display. Form() { . . . 'input' => array( 'type' => 'text', 'label' => $this->l('Configuration value'), 'name' => 'HELLO_WORLD_NAME', 'class' => 'fixed-width-xs', // extra small 'required' => true ) ), 'submit' => array( … }
Desarrollando módulos Configurar nuestro módulo (Cont. ) public function display. Form() { . . . 'submit' => array( 'title' => $this->l('Save'), 'class' => 'button' ) ); … }
Desarrollando módulos Configurar nuestro módulo (Cont. ) public function display. Form() { … $helper = new Helper. Form(); $helper->module = $this; // Module, Token and current. Index $helper->name_controller = $this->name; $helper->token = Tools: : get. Admin. Token. Lite('Admin. Modules'); $helper->current. Index = Admin. Controller: : $current. Index. '&configure='. $this->name; . . . }
Desarrollando módulos Configurar nuestro módulo (Cont. ) public function display. Form() { … $helper->default_form_language = $default_lang; // Language $helper->allow_employee_form_lang = $default_lang; $helper->title = $this->display. Name; // title and Toolbar $helper->show_toolbar = true; // false -> remove toolbar $helper->toolbar_scroll = true; // true- > Toolbar is always visible on the top of the screen. $helper->submit_action = 'submit'. $this->name; … }
Desarrollando módulos Configurar nuestro módulo (Cont. ) public function display. Form() { … $helper->toolbar_btn = array( 'save' => array( 'desc' => $this->l('Save'), 'href' => Admin. Controller: : $current. Index. '&configure='. $this->name. '&save'. $this- >name. '&token='. Tools: : get. Admin. Token. Lite('Admin. Modules' ), ), 'back' => array( 'desc' => $this->l('Back to list'), 'href' =>Admin. Controller: : $current. Index. '&token='. Tools: : get. Admin. Token. Lite('Admin. Modules') ) ); . . . }
Desarrollando módulos Configurar nuestro módulo (Cont. ) Para mostrar nuestra página de configuración: public function display. Form() { … $helper->fields_value['HELLO_WORLD_NAME'] = Configuration: : get('HELLO_WORLD_NAME'); // Load current value return $helper->generate. Form($fields_form); }
Desarrollando módulos - Ficheros * Directorio del módulo (nombre_del_módulo) * Fichero “hook” (nombre_del_módulo. php) * Ficheros de idioma (en 1. 6 van dentro del directorio. /translations/) * Fichero cache de configuración (config. xml) * Controladores. /controllers/ * Clases* sobreescritas. /override/ * Ficheros de vistas (en 1. 6 van dentro del directorio. /views/). “. /views/css”, “. /views/sass”, “. /views/js”, “. /views/templates/front” (vistas usadas por el controlador), “. /views/templates/hooks” (vistas usadas por los hooks del módulo) * Logos (16 x 16 gif / 32 x 32 png) * Readme. md * Para versiones superiores a 1. 6. 0. 11 puede haber un directorio. /test con los ficheros de testeo
Desarrollando módulos Mecanismo automático de actualización del módulo: Creamos un subdirectorio. /upgrade/ dentro del directorio de nuestro módulo. En la función de inicialización debemos definir cual va a ser la nueva versión de nuestro módulo ($this>version = '1. 1'; ) Creamos un script en php para cada nueva versión (/upgrade/install-1. 1. php) /* * File /upgrade/install-1. 1. php */ function upgrade_module_1_1($ module) { //Process Module upgrade to 1. 1 //. . return true; // Return true if successful. }
Desarrollando módulos Modelo: Dentro de nuestro módulo podemos crear nuestro Object. Model, para acceder a nuestra tabla, incluso podemos crear tantos como tablas. Los métodos principales son: public __construct( integer $id = null, integer $id_lang = null, integer $id_shop = null ) // Build object public boolean add( boolean $autodate = true, boolean $null_values= false ) // Add current object to database public boolean delete( ) // Delete current object from database public new duplicate. Object( ) // Duplicate current object to database public array get. Fields( ) // Fill an object with given data. Data must be an array with this syntax: array(obj. Property => value, obj. Property 2 => value, etc. ) . . .
Desarrollando módulos Modelo (Cont. ) Dentro de nuestro módulo podemos crear nuestro Object. Model, para acceder a nuestra tabla, incluso podemos crear tantos como tablas. Los métodos principales son (Cont. ). . . public hydrate( array $data, integer $id_lang = null) // Fill (hydrate) a list of objects in order to get a collection of these objects public static array hydrate. Collection( string $class, array $datas, integer $id_lang = null ) public boolean save( boolean $null_values = false, boolean $autodate = true) // Save current object to database (add or update) public boolean toggle. Status( ) // Toggle object status in database public boolean update( boolean $null_values = false ) // Update current object to database // Prepare fields for Object. Model class (add, update) All fields are verified (p. SQL, intval. . . )
Desarrollando módulos Modelo (Cont. ) La definición: /** * Example for the CMS Template( CMSCore) */ public static$definition= array( 'table' => 'cms', 'primary' => 'id_cms', 'multilang' => true, //'multilang_shop' => true [multi-idioma + multi-tienda] 'fields' => array(. . .
Desarrollando módulos Modelo (Cont. ) La definición (Cont. ) /** * Example for the CMS Template( CMSCore) */ public static$definition= array( … 'fields' => array( 'id_cms_category' =>array('type' => self: : TYPE_INT, 'validate'=> 'is. Unsigned. Int'), 'position' => array('type' => self: : TYPE_INT), 'active' => array ('type' => self: : TYPE_BOOL), // Lang fields. . .
Desarrollando módulos Modelo (Cont. ) La definición (Cont. ) public static$definition= array( … // Lang fields 'meta_description' =>array('type'=>self: : TYPE_STRING, 'lang'=>true, 'validate'=>'is. Generic. Name', 'size'=>255), 'meta_keywords' => array('type'=>self: : TYPE_STRING, 'lang'=>true, 'validate'=>'is. Generic. Name', 'size'=>255), 'meta_title' => array('type' =>self: : TYPE_STRING, 'lang'=>true, 'validate'=>'is. Generic. Name', 'required'=>true, 'size'=>128), 'link_rewrite' => array('type' => self: : TYPE_STRING, 'lang'=>true, 'validate'=>'is. Link. Rewrite', 'required'=>true, 'size'=>128), 'content' => array ('type' => self: : TYPE_HTML, 'lang' => true, 'validate' => 'is. String', 'size' => 3999999), ) );
Desarrollando módulos Modelo (Cont. ) Tipos de campos para la definición: * TYPE_BOOL * TYPE_DATE * TYPE_FLOAT * TYPE_HTML * TYPE_INT * TYPE_NOTHING * TYPE_STRING
Desarrollando módulos La clase DBQuery: public __to. String( ): Generate and get the query public string build( ): Generate and get the query public from( string $table, mixed $alias= null ): Set table for FROM clause public group. By( string $fields ): Add a GROUP BY restriction public having( string $restriction ): Add a restriction in HAVING clause( each restriction will be separated by AND statement) public inner. Join( string $table, string $alias = null, string $on = null ): Add INNER JOIN clause, E. g. $this>inner. Join('product p ON. . . ') . . .
Desarrollando módulos La clase DBQuery (Cont. ) … public join( string $join ): Add JOIN clause, E. g. $this->join('RIGHT JOIN '. _DB_PREFIX_. 'product p ON . . . '); public left. Join( string $table, string $alias= null, string $on= null ): Add LEFT JOIN clause public left. Outer. Join( string $table, string $alias = null, string $on = null ): Add LEFT OUTER JOIN clause public limit( string $limit, mixed $offset= 0 ): Limit results in query public natural. Join( string $table, string $alias = null ): Add NATURAL JOIN clause publicorder. By( string $fields ): Add an ORDER B restriction public select( string $fields ): Add fields in query selection public where( string $restriction ): Add a restriction in WHERE clause (each restriction will be separated by AND statement)
Desarrollando módulos La clase DBQuery (Cont. ) $sql = new Db. Query(); $sql->select('*'); $sql->from('cms', 'c'); $sql->inner. Join('cms_lang', 'l', 'c. id_cms = l. id_cms AND l. id_lang = '. (int)$id_lang); $sql->where('c. active = 1'); $sql->order. By('position'); return Db: : get. Instance()->execute. S($sql);
Desarrollando módulos Helpers Continuaremos. . .
- Slides: 46