Rediseñar el EditController. La nueva versión se colocaría en la carpeta Template, de acuerdo a la nueva estructura de carpetas del Core. La versión original permanecería en Core/Lib/ExtendedController para mantener compatibilidad durante unos meses.
<?php
namespace FacturaScripts\Plugins\MyNewPlugin\Controller;
class EditProject extends \FacturaScripts\Core\Template\EditController
{
const MENU = 'sales';
const TITLE = 'project';
const ICON = 'fas fa-folder-open';
const MODEL = 'Project';
}
El uso de contantes permite al IDE autocompletar, mientras que con la función que devuelve un array te tienes que saber los nombres de los campos. Para mayor compatibilidad, la clase Controller tendrá una función getPageData() que devolverá un array usando los valores de estas constantes.
Esta sería la primera función de nuestro código que ejecute el ListController. Aquí podemos añadir las pestañas y botones y variables que necesitemos, pero también comprobar permisos. Por ejemplo, podríamos impedir la ejecución para un usuario no administrador:
protected function init()
{
if($this->user->admin === false) {
throw new KernelException('AccessDenied', 'access-denied');
}
$this->addTabProjects();
}
El flujo de ejecución del controlador sería:
ListView, EditView, EditListView, etc son realmente pestañas, por lo que es mejor llamarlos tabs. Además deberíamos implementar las funciones tab() y deleteTab(), para mayor comodidad:
// añadimos una pestaña de listado
$this->addListTab($tabName, 'Project')
->addOrderBy(['name'], 'name')
->addSearchFields(['name']);
// añadimos otra opción de ordenación a una pestaña existente
$this->tab($tabName)->addOrderBy(['creationdate'], 'date');
// desactivamos la pestaña
$this->tab($tabName)->settings('active', false);
// eliminamos la pestaña
$this->deleteTab($tabName);
Necesitamos poder añadir o mover pestañas a cierta posición (a excepción de la primera). Por ejemplo en segunda posición o en última posición. Para ello podemos añádir la función setPosition().
// añadimos una pestaña en segunda posición
$this->addEditListTab($tabName, 'Project')
->setPosition(2)
->addOrderBy(['name'], 'name')
->addSearchFields(['name']);
Podríamos crear grupos para que cuando se muestran las pestañas en el lateral. Por ejemplo, podríamos separar las pestañas de facturas, albaranes, pedidos y presupuestos del cliente en un grupo, para que visualmente se vea que están relacionados.
$this->addEditListTab($tabName, 'FacturaCliente')
->setGroup('sales')
->setPosition(1)
->addOrderBy(['name'], 'name')
->addSearchFields(['name']);
Para modificar la posición de los grupos podemos tener una función addTabGroup(string $name, string $title, int $position).
Aunque se puede asignar el título de la pestaña al hacer el addListTab(), si lo ofrecemos también en una función independiente, podemos granar expresividad.
// añadimos una pestaña al final del todo
$this->addListTab($tabName, 'Project')
->setTitle('projects')
->addOrderBy(['name'], 'name')
->addSearchFields(['name']);
Aunque se puede asignar el icono de la pestaña al hacer el addListTab(), si lo ofrecemos también en una función independiente, podemos granar expresividad.
// añadimos una pestaña al final del todo
$this->addListTab($tabName, 'Project')
->setIcon('fas fa-folders')
->addOrderBy(['name'], 'name')
->addSearchFields(['name']);
Debemos poder añadir botones a la pestaña, como ya tenemos ahora:
// añadimos el botón a la vez que la pestaña
$this->addListTab($tabName, 'Project')
->addOrderBy(['name'], 'name')
->addSearchFields(['name'])
->addButton([
'action' => 'test-action',
'icon' => 'fas fa-question',
'label' => 'test'
]);
// añadimos el botón después de añadir la pestaña
$this->tab($tabName)->addButton([
'action' => 'test-action',
'icon' => 'fas fa-question',
'label' => 'test'
]);
Pero también debemos poder añadir botones a la propia página, fuera de la pestaña.
$this->addButton([
'action' => 'test-action',
'icon' => 'fas fa-question',
'label' => 'test'
]);
Ahora mismo esta parte es un poco confusa. Los botones de imprimir y nuevo son realmente de la primera pestaña. Eso no debería ser así. Los botones de una pestaña deberían pintarse siempre en la pestaña y si los quieres fuera, defínelos fuera.
Para prevenir ataques CSRF en cualquier controlador, la clase ListController debería lanzar una excepción cuando recibe datos por POST pero no hay un token asociado o el token no es válido. De este modo nos evitamos tener que hacer esta comprobación en cada método.
Algunos widgets o filtros de las pestañas pueden necesitar enviar y recibir datos del controlador. Para estos casos lo correcto es estandarizar estas llamadas, por ejemplo que envíen siempre el action=tab-actions, y desde execPreviousAction() podemos llamar al método tabAction(), que recorrería todos los widgets y todos los filtros de la pestaña seleccionada y ejecutaría su método action().
Existen varias situaciones relacionadas con permisos que hay que tener en cuenta:
Esto es una sugerencia a debatir. Está abierta a comentarios, votación y debate en la reunión semanal. Si se aprueba pasará a estado pendiente.