Añadir columnas en listas del administrador es un tema bastante más fácil de lo que parece. Pongamos el caso de que tenemos una página en prestashop y necesitamos añadir una funcionalidad a uno de los módulos instalados en ella. A simple vista puede parecer muy complicado (desde luego, no es algo aconsejable), pero no lo es tanto.

Antes de empezar la explicación, añado un consejo: esto no debe hacerse nunca, o al menos si lo haces tienes que ser consciente de lo que haces. Peligros de esta acción:

Posibilidad de romper el módulo. Es bastante posible que al tocar una cosa, estemos afectando a varias partes del módulo. En prestashop, se aplican muchísimo los principios “divide y vencerás” y “reutilización” de código, de ahí que donde vemos una función que sirva para X propósito muy probablemente se esté reutilizando para varias funcionalidades diferentes.
Perdemos actualizaciones. Cierto que los módulos de prestashop no se actualizan con tanta frecuencia como otras plataformas, ni si quiera el core lo hace, pero aún así un módulo editado es un módulo que no podremos actualizar. Y si la actualización incluye parches de seguridad, esto es un problema, y muy gordo.
Visto esto, os cuento mi caso práctico.

Situación inicial
Tenemos un e-commerce con Prestashop en el que se instaló en su día el módulo FormBuilder Pro (muy recomendable para construir fácilmente formularios personalizados). Tiempo después de iniciar el proyecto, surge la necesidad de añadir formularios estilo ticket, en los que los usuarios de la web envían una información y debemos poder marcarla como procesada/validada.

Este módulo no permite esto, pero por lo demás es perfectamente genial para nosotros. De ahí pensar en la posibilidad de añadir una columna indicando el estado del contacto.

Planteamiento
Una vez identificado el punto de inicio y la situación final a la que buscábamos llegar, surge la pregunta: “y esto, ¿cómo lo hago?”. Pues realmente, de un modo mucho más sencillo de lo esperado.

Lo primero que hicimos fue bucear en el módulo, conocerlo a fondo. Esto era necesario para saber qué controlador/es estaría implicado en el proceso. En nuestro caso, simplemente con ir al apartado “Received Data” del plugin y observar la URL ya tuvimos una primera pista muy importante para ver por dónde iban los tiros de lo que habría que modificar. El trozo final de la url era: index.php?controller=AdminGformrequest&token=XXXXXXXXXXXXX

Marco la parte importante. El controlador. Ahí es donde deberemos tocar para añadir la funcionalidad. Si estás familiarizado con la estructura MVC, ya sabrás que estoy tardando en hablar del modelo. Tranquilo, de momento solo estamos observando dónde tocar.

Genial, imaginemos que no tenemos ni idea de cómo va la programación en prestashop. ¿Qué se me puede ocurrir? Pues lo primero y más obvio es ir al apartado “Forms” del módulo, donde tenemos la lista de todos los formularios creados y ver cómo está hecho. Vemos que hay columnas de esas que hay en la lista de productos, estilo activo/inactivo. Justo lo que queremos. Perfecto, solo tenemos que copiar.

Demasiado fácil, ¿verdad? Pues efectivamente, aquí nos encontramos con el único error que tiene el módulo. Pulses en el icono de la columna que pulses, siempre se cambia la columna “Estado” de su fila correspondiente. Vaya contrariedad. No podemos copiar, nos toca pensar cómo añadir columnas en listas del administrador…

Pero bueno, si vamos muy perdidos al menos podemos ver cómo están definidas las columnas y usarlo de base. Nosotros arrancamos de cero.

Programación
Ya sabemos que tenemos que añadir un dato a nuestras peticiones recibidas por formulario, sabemos en qué controlador hacerlo, y además en nuestro caso sabemos que necesitamos añadir un campo a la base de datos ya que más adelante querremos filtrar por este dato, y la información del formulario viene codificada en JSON, demasiado complicado para una búsqueda rápida como necesitaremos.

Debido a todo esto, optamos por añadir un campo a la tabla prefijo_gformrequest. Nosotros hemos llamado al campo approbed y lo hemos creado como tinyint(1) ya que en la práctica será un campo bool donde grabaremos un 1 o un 0 en función del estado del envío. Además lo hemos creado como UNSIGNED y con valor predeterminado 0, para que las solicitudes entren siempre como pendientes de revisión.

Esto podemos hacerlo mediante una query o directamente con phpMyAdmin:

O bien, la consulta:

ALTER TABLE `pre_gformrequest` 
ADD `approbed` TINYINT(1) UNSIGNED NOT NULL DEFAULT '0' 
AFTER `id_gformbuilderpro`;

Nosotros hemos querido añadir el campo justo detrás del campo id_gformbuilderpro, pero esto no es necesario.

Una vez tocada la base de datos, lo próximo es tocar el modelo. En este caso, el modelo está en /modules/gformbuilderpro/classes/gformrequestModel.php. Lo único que voy a hacer aquí es añadir el nuevo campo de la base de datos, para que el módulo sea capaz de trabajar con él. Copio toda la definición de todos los campos, y dejo un comentario indicando las 2 líneas que he añadido.

class gformrequestModel extends ObjectModel
{
    public $id_gformrequest;
    public $id_gformbuilderpro;
    public $user_ip;
    public $subject;
    public $sendto;
    public $approbed = 0;//msolla
    public $request;
    public $attachfiles;
    public $jsonrequest;
    public $date_add;
    public static $definition = array(
        'table' => 'gformrequest',
        'primary' => 'id_gformrequest',
        'multilang' => false,
        'fields' => array(
            //Fields
            'id_gformbuilderpro' =>  array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt'),
            'user_ip'  =>  array('type' => self::TYPE_STRING,'validate' => 'isString'),
            'sendto'  =>  array('type' => self::TYPE_STRING,'validate' => 'isString'),
            'approbed' => array('type' => self::TYPE_INT, 'validate' => 'isBool'),//msolla
            'subject'  =>  array('type' => self::TYPE_STRING,'validate' => 'isString'),
            'attachfiles' =>  array('type' => self::TYPE_STRING,'validate' => 'isString'),
            'jsonrequest' =>  array('type' => self::TYPE_HTML,'validate' => 'isCleanHtml'),
            'request' => 	array('type' => self::TYPE_HTML,'validate' => 'isCleanHtml'),
            'date_add' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'),
        )
    );

Hecho esto, toca ir al Controller, ubicado en /modules/gformbuilderpro/controllers/admin/AdminGformrequestController.php. En este caso, hay 2 cosas que tocar. Primero, añadir el campo creado al array $this->fields_list, pongo el array completo, pero solo se ha añadido el nodo ‘approbed’ del array:

$this->fields_list = array(
      'id_gformrequest' => array(
          'title' => $this->l('ID'),
          'type' => 'int',
          'width' => 'auto',
          'orderby' => false),
      'fbtitle' => array(
          'title' => $this->l('Form Title'),
          'filter_key' => 'a!id_gformbuilderpro',
          'type' => 'select',
          'list' => $titles_array,
          'filter_type' => 'int',
          'order_key' => 'fb!fbtitle'
       ), 
      'subject' => array(
          'title' => $this->l('Mail Subject'),
          'type' => 'text',
          'width' => 'auto',
          'orderby' => false,
          'filter_key' => 'a!subject'
      ),
      'sendto' => array(
          'title' => $this->l('Sent To'),
          'type' => 'text',
          'width' => 'auto',
          'orderby' => false,
          'filter_key' => 'a!sendto'),
    'approbed' => array(
          'title' => $this->l('Approbed'),
          'type' => 'bool',
          'active' => 'approbed',
          'width' => 'auto',
          'orderby' => false,
          'filter_key' => 'a!approbed'
    ),
    'date_add' => array(
         'title' => $this->l('Date'),
         'type' => 'datetime',
         'width' => 'auto',
         'orderby' => false,
         'filter_key' => 'a!date_add'),
    );
    parent::__construct();

Y añadir 2 funciones para que prestashop sea capaz de interpretar este campo.

public function initProcess()
{
   parent::initProcess();
   if (Tools::isSubmit('approbed'.$this->table) && Tools::getValue($this->identifier)) {
      $this->action = 'approbed'; 
   }
}
public function processApprobed(){
   if (Validate::isLoadedObject($object = $this->loadObject())) {
      $object->approbed = !$object->approbed;
      $object->update(false);
   }
}

Y eso es todo.

Situación final
Hechos estos sencillos cambios, tenemos nuestra lista de envíos de formulario, con el campo añadido y su correspondiente check/aspa para ser pulsada y cambiar el estado del dato guardado.

Sencillo y para todos los públicos.

Bonus track
¿Recordáis que comenté que el módulo tenía un fallo? Efectivamente, el fallo está en el controller. Lo que ocurre es que al desarrollador se le olvidó un detalle, simplemente si tienes una columna que llames status en lugar de approbed, prestashop es capaz de interpretarlo, no necesita las funciones initContent y processApprobed. En caso de que el nombre sea diferente, sí es necesario.

Además, si os fijáis, en la definición de los campos yo he puesto

'active' => 'approbed',

sin embargo él en sus 3 columnas puso

'active' => 'status',

con lo cual para prestashop las 3 columnas hacen referencia a ese campo (status) de la base de datos.

Todo lo que hay que hacer es ir al controller del administrador (/modules/gformbuilderpro/controllers/admin/AdminGformmanagerController.php) y cambiar la definición de las columnas y añadir sus funciones:

$this->fields_list = array(

            'id_gformbuilderpro' => array(
                'title' => $this->l('ID'),
                'type' => 'int',
                'width' => 'auto',
                'orderby' => false),
            'title' => array(
                'title' => $this->l('Title'),
                'width' => 'auto',
                'orderby' => false),
            'shortcode' => array(
                'title' => $this->l('Shortcode'),
                'width' => 'auto',
                'orderby' => false,
                'callback' => 'printShortcode',
            ),
            'frontlink' => array(
                'title' => $this->l('Url'),
                'width' => 'auto',
                'orderby' => false,
                'callback' => 'printFrontlink',
                'remove_onclick'=>true
            ),
            'requiredlogin' => array(
                'title' => $this->l('Required Login'),
                'width' => 'auto',
                'active' => 'requiredlogin',
                'type' => 'bool',
                'orderby' => false
			),
            'saveemail' => array(
                'title' => $this->l('Save to Database'),
                'width' => 'auto',
                'active' => 'saveemail',
                'type' => 'bool',
                'orderby' => false
			),
            'active' => array(
                'title' => $this->l('Status'),
                'width' => 'auto',
                'active' => 'status',
                'type' => 'bool',
                'orderby' => false
			),
        );

        parent::__construct()</pre>

Y las funciones:


    public function initProcess()
    {
        parent::initProcess();
        if (Tools::isSubmit('requiredlogin'.$this->table) && Tools::getValue($this->identifier)) {
            $this->action = 'requiredlogin';
        }elseif (Tools::isSubmit('saveemail'.$this->table) && Tools::getValue($this->identifier)) {
            $this->action = 'saveemail';
        }
    }
    public function processRequiredlogin(){
        if (Validate::isLoadedObject($object = $this->loadObject())) {
            $object->requiredlogin = !$object->requiredlogin;
            $object->update(false);
        }
    }
    public function processSaveemail(){
        if (Validate::isLoadedObject($object = $this->loadObject())) {
            $object->saveemail = !$object->saveemail;
            $object->update(false);
        }
    }

Y tú, ¿cómo hubieras intentando añadir columnas en listas del administrador?

HorribleMaloBlehBienGenial (2 votos, media: 4,50 de 5)
Cargando…
Miguel Solla
¡Sígueme!

Miguel Solla

Developer at Extra Software
Programador informático, especializado en web.
Apasionado de la astronomía y entusiasta de la ciencia en general.
Miguel Solla
¡Sígueme!