Pour ajouter une fonctionnalité de duplication d’objet sur une liste CRUD, il faut modifier la liste en ajoutant le bouton, configurer une route, et exécuter un code de duplication d’objet, et pour finir, référencer le controller qui accueillera notre fonction dans notre interface, via son service.
Ajouter le bouton :
Dans votre controller ajouter le bouton en donnant en référence le template du bouton.
Ici nous mettons le path ‘Admin/list__action_clone.html.twig’. Le système ira donc chercher le fichier : /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'
]
]
]);
}
Le contenu de notre fichier twig est très simple. C’est juste l’affichage d’une icône.
<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>
Il faut ensuite créer la route dans notre controller :
protected function configureRoutes(RouteCollection $collection)
{
$collection->add('clone', $this->getRouterIdParameter().'/clone');
}
Et dernière étape, cloner notre objet ainsi que l’ensemble de sa configuration. Pour cela nous allons créer un controller spécialement dédié à la gestion de nos fonctions additionnelles et l’ajouter à notre service pour qu’il soit disponible.
Dans App/Admin nous allons créé un fichier CustomAction.php qui va contenir notre function cloneAction().
Celui-ci doit être étendu par CRUDController et non AbstractAdmin comme nos interfaces. C’est ce qui explique que nous mettons notre fonction dans un nouveau fichier. Mais cela nous permet aussi de réutiliser cette fonction au besoin.
Dans 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()]));
}
}
Comme vous pouvez le constater, notre fonction clone se charge de cloner notre objet mais aussi de cloner l’ensemble de ses relations OneToMany.
La ligne $clonedConf->setWconfTypcont($clonedObject); permet de mettre l’id de la relation parent dans le champ de la relation enfant. Sinon tous les objets garderaient leurs relations avec l’objet initial.
Dernière étape, il faut référencer notre nouveau controller dans le service de notre interface.
Avant :
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
Aprè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