Para agregar una función de duplicación de objetos a una
lista CRUD, necesitas modificar la lista añadiendo el botón,
configurar una ruta, ejecutar el código de duplicación de objeto
y, finalmente, referenciar el controlador que alojará nuestra
función en nuestra interfaz, a través de su
servicio.
Añadiendo el botón:
En tu controlador, añade
el botón haciendo referencia a la plantilla del botón.
Aquí
establecemos la ruta 'Admin/list__action_clone.html.twig'. El
sistema buscará el archivo en:
/templates/Admin/list__action_clone.html.twig
protected function configureListFields(ListMapper $listMapper)
{
$listMapper->addIdentifier('id', null, ['label' => 'id']);
$listMapper->addIdentifier('label', null, ['label' => 'type']);
$listMapper->addIdentifier('description', null, ['label' => 'Label']);
$listMapper->add('actif', null, ['editable' => true]);
$listMapper->add('_action', null, [
'actions' => [
'clone' => [
'template' => 'Admin/list__action_clone.html.twig'
]
]
]);
}
El contenido de nuestro archivo twig es muy simple. Es solo la visualización de un ícono.
<a class="btn btn-sm btn-default"
href="{{ admin.generateObjectUrl('clone', object) }}"
title="{{ 'Clone'|trans({}, 'default') }}"
alt="{{ 'Clone'|trans({}, 'default') }}">
<i class="fa fa-clone"></i>
</a>
El siguiente paso es crear la ruta en nuestro controlador:
protected function configureRoutes(RouteCollection $collection)
{
$collection->add('clone', $this->getRouterIdParameter().'/clone');
}
Y el último paso, clonar nuestro objeto junto con todas sus
configuraciones. Para hacer esto, crearemos un controlador
específicamente dedicado a administrar nuestras funciones
adicionales y lo añadiremos a nuestro servicio para que se vuelva
disponible.
En App/Admin vamos a crear un archivo llamado
CustomAction.php que contendrá nuestra función
cloneAction().
Esta debe extenderse de CRUDController y no de
AbstractAdmin como con nuestras interfaces. Es por eso que ponemos
nuestra función en un archivo nuevo. Pero también nos permite
reutilizar esta función si es necesario.
En src/Admin/CustomAction.php:
<?php
namespace App\Admin;
use Sonata\AdminBundle\Controller\CRUDController;
use Symfony\Component\HttpFoundation\RedirectResponse;
class CustomAction extends CRUDController
{
/**
* @param $id
*/
public function cloneAction($id)
{
$object = $this->admin->getObject($id);
$objectConf=$object->getWtypeWconf()->toArray();
if (!$object) {
throw new NotFoundHttpException(sprintf('unable to find the object with id: %s', $id));
}
$clonedObject = clone $object;
$clonedObject->unsetId();
$clonedObject->setLabel($object->getLabel().' clone('.uniqid().')');
$this->admin->create($clonedObject);
if(!empty($objectConf)){
foreach($objectConf as $c){
$clonedConf=clone $c;
$clonedConf->setWconfTypcont($clonedObject);
$this->admin->create($clonedConf);
}
}
$this->addFlash('sonata_flash_success', 'L\'élément a correctement été dupliqué.');
return new RedirectResponse($this->admin->generateUrl('list'));
// if you have a filtered list and want to keep your filters after the redirect
// return new RedirectResponse($this->admin->generateUrl('list', ['filter' => $this->admin->getFilterParameters()]));
}
}
Como puedes ver, nuestra función de clonación es responsable de
clonar nuestro objeto así como todas sus relaciones
OneToMany.
La línea
$clonedConf->setWconfTypcont($clonedObject); se usa para poner el
id de la relación padre en el campo de la relación hijo. De lo
contrario, todos los objetos mantendrían sus relaciones con el
objeto inicial.
Último paso, necesitamos referenciar
nuestro nuevo controlador en el servicio de nuestra
interfaz.
Antes:
admin.wtype:
class: App\Admin\WtypeAdmin
arguments: [~, App\Entity\Wtype, ~]
calls:
- [addChild, ["@admin.wconf"]]
tags:
- { name: sonata.admin, manager_type: orm, label: "Types de contrats" }
public: true
Después:
admin.wtype:
class: App\Admin\WtypeAdmin
arguments: [~, App\Entity\Wtype, App\Admin\CustomAction]
calls:
- [addChild, ["@admin.wconf"]]
tags:
- { name: sonata.admin, manager_type: orm, label: "Types de contrats" }
public: true