@@ -3,11 +3,14 @@ | |||
namespace Lc\SovBundle\Builder\User; | |||
use Doctrine\ORM\EntityManagerInterface; | |||
use Lc\CaracoleBundle\Model\Address\AddressInterface; | |||
use Lc\SovBundle\Doctrine\EntityInterface; | |||
use Lc\SovBundle\Doctrine\Extension\BlameableInterface; | |||
use Lc\SovBundle\Factory\User\UserFactory; | |||
use Lc\SovBundle\Model\Newsletter\NewsletterInterface; | |||
use Lc\SovBundle\Model\Ticket\TicketInterface; | |||
use Lc\SovBundle\Model\User\UserInterface; | |||
use Lc\SovBundle\Repository\RepositoryQueryInterface; | |||
use Lc\SovBundle\Repository\User\UserStore; | |||
use Lc\SovBundle\Solver\User\UserSolver; | |||
@@ -27,7 +30,7 @@ class UserBuilder | |||
} | |||
public function create( string $email, string $password, array $roles=[]) | |||
public function create(string $email, string $password, array $roles = []) | |||
{ | |||
$user = $this->userFactory->create(); | |||
$user->setEmail($email); | |||
@@ -84,11 +87,31 @@ class UserBuilder | |||
} | |||
} | |||
public function setLastLogin(?UserInterface $user){ | |||
public function setLastLogin(?UserInterface $user) | |||
{ | |||
if ($user instanceof UserInterface) { | |||
$user->setLastLogin(new \DateTime()); | |||
$this->entityManager->update($user); | |||
$this->entityManager->flush(); | |||
} | |||
} | |||
public function getEntitiesToDeleteForUserDelete(UserInterface $user, string $entityFqcn, RepositoryQueryInterface $repositoryQuery) | |||
{ | |||
$entitiesToDelete =array(); | |||
// if (new $entityFqcn instanceof BlameableInterface) { | |||
// //CreatedBy | |||
// $query = $repositoryQuery->create(); | |||
// $query->filterByCreatedBy($user); | |||
// $entitiesToDelete['nullify']['createdBy'] = $query->find(); | |||
// | |||
// //UpdatedBy | |||
// $query = $repositoryQuery->create(); | |||
// $query->filterByUpdatedBy($user); | |||
// $entitiesToDelete['nullify']['updatedBy'] = $query->find(); | |||
// } | |||
return $entitiesToDelete; | |||
} | |||
} |
@@ -852,12 +852,12 @@ abstract class AbstractAdminController extends EaAbstractCrudController | |||
if (!$this->isGranted(Permission::EA_EXECUTE_ACTION, ['action' => Action::DELETE, 'entity' => $context->getEntity()])) { | |||
throw new ForbiddenActionException($context); | |||
} | |||
if (!$context->getEntity()->isAccessible()) { | |||
throw new InsufficientEntityPermissionException($context); | |||
} | |||
$csrfToken = $context->getRequest()->request->get('token'); | |||
if (!$this->isCsrfTokenValid('ea-delete', $csrfToken)) { | |||
return $this->redirectToRoute($context->getDashboardRouteName()); | |||
} |
@@ -2,6 +2,8 @@ | |||
namespace Lc\SovBundle\Controller\User; | |||
use Doctrine\DBAL\Exception\ForeignKeyConstraintViolationException; | |||
use Doctrine\ORM\EntityManagerInterface; | |||
use EasyCorp\Bundle\EasyAdminBundle\Collection\EntityCollection; | |||
use EasyCorp\Bundle\EasyAdminBundle\Config\Action; | |||
use EasyCorp\Bundle\EasyAdminBundle\Config\Actions; | |||
@@ -11,6 +13,7 @@ use EasyCorp\Bundle\EasyAdminBundle\Context\AdminContext; | |||
use EasyCorp\Bundle\EasyAdminBundle\Event\AfterCrudActionEvent; | |||
use EasyCorp\Bundle\EasyAdminBundle\Event\BeforeCrudActionEvent; | |||
use EasyCorp\Bundle\EasyAdminBundle\Event\BeforeEntityDeletedEvent; | |||
use EasyCorp\Bundle\EasyAdminBundle\Exception\EntityRemoveException; | |||
use EasyCorp\Bundle\EasyAdminBundle\Exception\ForbiddenActionException; | |||
use EasyCorp\Bundle\EasyAdminBundle\Exception\InsufficientEntityPermissionException; | |||
use EasyCorp\Bundle\EasyAdminBundle\Field\ChoiceField; | |||
@@ -26,6 +29,8 @@ use Lc\SovBundle\Definition\RolesDefinitionInterface; | |||
use Lc\SovBundle\Doctrine\EntityManager; | |||
use Lc\SovBundle\Doctrine\Extension\BlameableInterface; | |||
use Lc\SovBundle\Factory\User\UserFactory; | |||
use Lc\SovBundle\Form\User\ConfirmDeleteUserFormType; | |||
use Lc\SovBundle\Translation\FlashBagTranslator; | |||
use Lc\SovBundle\Translation\TranslatorAdmin; | |||
use Symfony\Component\HttpFoundation\RequestStack; | |||
use Symfony\Component\HttpFoundation\Session\SessionInterface; | |||
@@ -89,10 +94,13 @@ abstract class UserAdminController extends AbstractAdminController | |||
public function delete(AdminContext $context) | |||
{ | |||
$entityManager = $this->getEntityManager(); | |||
$eaBeforeCrudActionEventDelete = $this->eaBeforeCrudActionEventDelete($context); | |||
if(!is_null($eaBeforeCrudActionEventDelete)){ | |||
if (!is_null($eaBeforeCrudActionEventDelete)) { | |||
return $eaBeforeCrudActionEventDelete; | |||
} | |||
$entityInstance = $context->getEntity()->getInstance(); | |||
$event = new BeforeEntityDeletedEvent($entityInstance); | |||
@@ -104,44 +112,102 @@ abstract class UserAdminController extends AbstractAdminController | |||
$user = $event->getEntityInstance(); | |||
$metas = $this->getEntityManager()->getMetadataFactory()->getAllMetadata(); | |||
$metas = $entityManager->getMetadataFactory()->getAllMetadata(); | |||
foreach ($metas as $meta) { | |||
$entityFqcnList[] = $meta->getName(); | |||
} | |||
// Creéer formulaire avec un champ confirm | |||
$confirmDeleteUserForm = $this->createForm(ConfirmDeleteUserFormType::class, null, array( | |||
'action' => $this->getAdminUrlGenerator()->generateUrl() | |||
)); | |||
$confirmDeleteUserForm->handleRequest($context->getRequest()); | |||
$entitiesWarning['reductionCart'] = $this->getReductionCartContainer()->getStore()->getByUserOutOfContext($user); | |||
$entitiesWarning['reductionCatalog'] = $this->getReductionCatalogContainer()->getStore()->getByUserOutOfContext($user); | |||
$entitiesWarning['reductionCredit'] = $this->getReductionCreditContainer()->getStore()->getReductionCreditByUserOutOfContext($user); | |||
$entitiesWarning['reductionGift'] = $this->getReductionCreditContainer()->getStore()->getReductionGiftByUserOutOfContext($user); | |||
//si clqiue suppression | |||
$entitiesToDelete = array(); | |||
foreach ($entityFqcnList as $entityFqcn){ | |||
if(!is_null($this->getApplicationDefinition()->getContainerByEntityFqcn($entityFqcn))) { | |||
$repositoryQuery = $this->get( | |||
$this->getApplicationDefinition()->getContainerByEntityFqcn($entityFqcn) | |||
foreach ($entityFqcnList as $entityFqcn) { | |||
if (!is_null($this->getApplicationDefinition()->getContainerByEntityFqcn($entityFqcn))) { | |||
$repositoryQuery = $this->container->get( | |||
$this->getApplicationDefinition()->getContainerByEntityFqcn($entityFqcn) | |||
)->getRepositoryQuery(); | |||
if (new $entityFqcn instanceof BlameableInterface) { | |||
//CreatedBy | |||
$query = $repositoryQuery->create(); | |||
$query->filterByCreatedBy($user); | |||
$entitiesToDelete[$entityFqcn]['nullify']['createdBy'] = $query->find(); | |||
$entitiesToDelete[$entityFqcn] = $this->getUserContainer()->getBuilder()->getEntitiesToDeleteForUserDelete($user, $entityFqcn, $repositoryQuery); | |||
//UpdatedBy | |||
$query = $repositoryQuery->create(); | |||
$query->filterByUpdatedBy($user); | |||
$entitiesToDelete[$entityFqcn]['nullify']['updatedBy'] = $query->find(); | |||
} | |||
} | |||
dump($entityFqcn); | |||
} | |||
$entityManager->delete($entityInstance); | |||
dump($entityManager->getUnitOfWork()->getScheduledEntityDeletions()); | |||
// dump($entityManager->getUnitOfWork()->getEntityChangeSet()); | |||
dump($entityManager->getUnitOfWork()->getScheduledEntityUpdates()); | |||
dump($entityManager->getUnitOfWork()->getScheduledEntityInsertions()); | |||
if ($confirmDeleteUserForm->isSubmitted()) { | |||
$entityManager->flush(); | |||
$this->get(FlashBagTranslator::class)->add('success', 'deleted', $this->getTranslationEntityName()); | |||
$this->deleteEntity($this->container->get('doctrine')->getManagerForClass($context->getEntity()->getFqcn()), $entityInstance); | |||
//Todo supprimer les éléments listés | |||
try { | |||
} catch (ForeignKeyConstraintViolationException $e) { | |||
throw new EntityRemoveException(['entity_name' => $context->getEntity()->getName(), 'message' => $e->getMessage()]); | |||
} | |||
return $this->redirect($this->getAdminUrlGenerator()->setAction(Crud::PAGE_INDEX)->setEntityId(null)->generateUrl()); | |||
}else{ | |||
$entitiesToDelete = $entityManager->getUnitOfWork()->getScheduledEntityDeletions(); | |||
$entitiesToUpdate = $entityManager->getUnitOfWork()->getScheduledEntityUpdates(); | |||
} | |||
// foreach ($entitiesToDelete as $entityFqcn) { | |||
// foreach ($entityFqcn as $action => $field) { | |||
// if ($action == 'nullify') { | |||
// foreach ($field as $fieldName => $entityList) { | |||
// $method = 'set' . ucfirst($fieldName); | |||
// $methodGet = 'get' . ucfirst($fieldName); | |||
// foreach ($entityList as $entity) { | |||
// $entity->$method(null); | |||
// $this->getEntityManager()->update($entity); | |||
// } | |||
// } | |||
// } | |||
// | |||
// | |||
//// if ($action == 'delete') { | |||
//// foreach ($field as $entity) { | |||
//// dump($entity); | |||
//// $this->getEntityManager()->delete($entity); | |||
//// } | |||
//// } | |||
// | |||
// } | |||
// | |||
// } | |||
//Détecter les merde | |||
//SELECT * FROM address a LEFT OUTER JOIN user u ON(u.id=a.user_id) WHERE u.id is null | |||
$responseParameters = $this->configureResponseParameters(KeyValueStore::new([ | |||
'pageName' => Crud::PAGE_DETAIL, | |||
'templatePath' => '@LcSov/adminlte/crud/delete.html.twig', | |||
'global_actions' => array(), | |||
'batch_actions' => array(), | |||
'entities_delete' => $entitiesToDelete, | |||
'pageName' => Crud::PAGE_DETAIL, | |||
'templatePath' => '@LcSov/adminlte/crud/delete.html.twig', | |||
'confirm_delete_user_form' => $confirmDeleteUserForm->createView(), | |||
'global_actions' => array(), | |||
'batch_actions' => array(), | |||
'entities_warning' => $entitiesWarning, | |||
'entities_update' => $entitiesToUpdate, | |||
])); | |||
$event = new AfterCrudActionEvent($context, $responseParameters); |
@@ -13,6 +13,7 @@ use Lc\SovBundle\Container\Ticket\TicketContainer; | |||
use Lc\SovBundle\Container\Ticket\TicketMessageContainer; | |||
use Lc\SovBundle\Container\User\GroupUserContainer; | |||
use Lc\SovBundle\Container\User\UserContainer; | |||
use function Symfony\Component\String\u; | |||
class ApplicationDefinition | |||
{ | |||
@@ -34,12 +35,32 @@ class ApplicationDefinition | |||
]; | |||
} | |||
public static function getSubscribedContainerServices(): array | |||
public function getContainerByEntityFqcn(string $entityFqcn) | |||
{ | |||
foreach (static::getContainerList() as $containerFqcn){ | |||
if($this->isContainerManageEntity($containerFqcn)){ | |||
if ($containerFqcn::getEntityFqcn() == $entityFqcn) { | |||
return $containerFqcn; | |||
} | |||
} | |||
} | |||
return null; | |||
} | |||
public function isContainerManageEntity(string $containerFqcn) | |||
{ | |||
if(method_exists($containerFqcn, 'getEntityFqcn') ){ | |||
return true; | |||
} | |||
return false; | |||
} | |||
public static function getSubscribedContainerServices(): array | |||
{ | |||
$array = []; | |||
foreach (self::getContainerList() as $container) { | |||
foreach (static::getContainerList() as $container) { | |||
$array[$container] = $container; | |||
} | |||
@@ -47,4 +68,19 @@ class ApplicationDefinition | |||
} | |||
public static function getContainerListForTwigGlobals(): array | |||
{ | |||
$array = []; | |||
foreach (static::getContainerList() as $containerNamespace) { | |||
//récupère le nom du fichier dans le namespace du container | |||
$key = u(substr($containerNamespace, strrpos($containerNamespace, '\\')))->snake(); | |||
$array[$key->toString()] = '@' . $containerNamespace; | |||
} | |||
return $array; | |||
} | |||
} |
@@ -12,14 +12,14 @@ trait BlameableTrait | |||
/** | |||
* @Gedmo\Blameable(on="create") | |||
* @ORM\ManyToOne(targetEntity="Lc\SovBundle\Model\User\UserInterface") | |||
* @ORM\JoinColumn(nullable=true) | |||
* @ORM\JoinColumn(nullable=true, onDelete="SET NULL") | |||
*/ | |||
protected $createdBy; | |||
/** | |||
* @Gedmo\Blameable(on="update") | |||
* @ORM\ManyToOne(targetEntity="Lc\SovBundle\Model\User\UserInterface") | |||
* @ORM\JoinColumn(nullable=true) | |||
* @ORM\JoinColumn(nullable=true, onDelete="SET NULL") | |||
*/ | |||
protected $updatedBy; | |||
@@ -0,0 +1,60 @@ | |||
<?php | |||
namespace Lc\SovBundle\Form\User; | |||
use Lc\SovBundle\Doctrine\EntityManager; | |||
use Lc\SovBundle\Translation\TranslatorAdmin; | |||
use Symfony\Component\Form\AbstractType; | |||
use Symfony\Component\Form\Extension\Core\Type\ButtonType; | |||
use Symfony\Component\Form\Extension\Core\Type\CheckboxType; | |||
use Symfony\Component\Form\Extension\Core\Type\SubmitType; | |||
use Symfony\Component\Form\FormBuilderInterface; | |||
use Symfony\Component\OptionsResolver\OptionsResolver; | |||
class ConfirmDeleteUserFormType extends AbstractType | |||
{ | |||
protected $em; | |||
protected $translatorAdmin; | |||
public function __construct(EntityManager $em, TranslatorAdmin $translatorAdmin) | |||
{ | |||
$this->em = $em; | |||
$this->translatorAdmin = $translatorAdmin; | |||
} | |||
/** | |||
* {@inheritdoc} | |||
*/ | |||
public function buildForm(FormBuilderInterface $builder, array $options) | |||
{ | |||
$builder->add( | |||
'confirm', | |||
CheckboxType::class, | |||
[ | |||
'translation_domain' => 'admin', | |||
] | |||
); | |||
$builder->add( | |||
'delete', | |||
SubmitType::class | |||
); | |||
} | |||
public function configureOptions(OptionsResolver $resolver): void | |||
{ | |||
$resolver->setDefaults([ | |||
// enable/disable CSRF protection for this form | |||
'csrf_protection' => true, | |||
// the name of the hidden HTML field that stores the token | |||
'csrf_field_name' => '_token', | |||
// an arbitrary string used to generate the value of the token | |||
// using a different string for each form improves its security | |||
'csrf_token_id' => 'ea-delete', | |||
]); | |||
} | |||
} |
@@ -23,7 +23,7 @@ abstract class TicketMessageModel extends AbstractLightEntity implements TicketM | |||
protected $message; | |||
/** | |||
* @ORM\ManyToOne(targetEntity="Lc\SovBundle\Model\Ticket\TicketInterface", inversedBy="ticketMessages") | |||
* @ORM\ManyToOne(targetEntity="Lc\SovBundle\Model\Ticket\TicketInterface", inversedBy="ticketMessages", cascade={"remove"}) | |||
* @ORM\JoinColumn(nullable=false) | |||
*/ | |||
protected $ticket; |
@@ -66,7 +66,7 @@ abstract class TicketModel extends AbstractLightEntity implements TicketInterfac | |||
protected $visitorToken; | |||
/** | |||
* @ORM\OneToMany(targetEntity="Lc\SovBundle\Model\Ticket\TicketMessageInterface", mappedBy="ticket", orphanRemoval=true, cascade={"persist", "remove"}) | |||
* @ORM\OneToMany(targetEntity="Lc\SovBundle\Model\Ticket\TicketMessageInterface", mappedBy="ticket",cascade={"persist", "remove"}, orphanRemoval=true) | |||
* @ORM\OrderBy({"id" = "ASC"}) | |||
*/ | |||
protected $ticketMessages; | |||
@@ -76,6 +76,7 @@ abstract class TicketModel extends AbstractLightEntity implements TicketInterfac | |||
*/ | |||
protected $user; | |||
public function __construct() | |||
{ | |||
$this->ticketMessages = new ArrayCollection(); |
@@ -73,7 +73,7 @@ abstract class UserModel implements EntityInterface, UserInterface, SovUserInter | |||
protected $groupUsers; | |||
/** | |||
* @ORM\OneToMany(targetEntity="Lc\SovBundle\Model\Ticket\TicketInterface", mappedBy="user") | |||
* @ORM\OneToMany(targetEntity="Lc\SovBundle\Model\Ticket\TicketInterface", mappedBy="user", cascade={"remove"}) | |||
*/ | |||
protected $tickets; | |||
@@ -31,25 +31,30 @@ | |||
{% block card_body_wrapper %} | |||
<div class="card-body"> | |||
{% block detail_fields %} | |||
{% for entity_fqcn, entity_actions in entities_delete %} | |||
<div class="callout callout-danger"> | |||
<h5>{{ entity_fqcn }}</h5> | |||
{% for action, entity_field_list in entity_actions %} | |||
{% for field, entity_list in entity_field_list %} | |||
<p>{{ entity_list|length }} entités à {{ action }} sur le champ {{ field }}</p> | |||
{% endfor %} | |||
{% endfor %} | |||
</div> | |||
{% endfor %} | |||
{{ dump(entities_warning) }} | |||
{{ dump(entities_update) }} | |||
{# {% for entity_fqcn, entity_actions in entities_delete %}#} | |||
{# <div class="callout callout-danger">#} | |||
{# <h5>{{ entity_fqcn }}</h5>#} | |||
{# {% for action, entity_field_list in entity_actions %}#} | |||
{# {% for field, entity_list in entity_field_list %}#} | |||
{# <p>{{ entity_list|length }} entités à {{ action }} sur le champ {{ field }}</p>#} | |||
{# {% endfor %}#} | |||
{# {% endfor %}#} | |||
{# </div>#} | |||
{# {% endfor %}#} | |||
{% endblock %} | |||
</div> | |||
{% endblock %} | |||
{% block card_footer_wrapper %} | |||
<div class="card-footer"> | |||
<div class="row"> | |||
{# {% block delete_form %} #} | |||
{# {{ include('@EasyAdmin/crud/includes/_delete_form.html.twig', { entity_id: entity.primaryKeyValue }, with_context = false) }} #} | |||
{# {% endblock delete_form %} #} | |||
{% block delete_form %} | |||
{{ form_start(confirm_delete_user_form) }} | |||
<input type="hidden" name="token" value="{{ csrf_token('ea-delete') }}" /> | |||
{{ form_end(confirm_delete_user_form) }} | |||
{% endblock delete_form %} | |||
</div> | |||
</div> | |||
{% endblock %} |