Skip to content

Commit

Permalink
Merge pull request #3292 from acrobat/nested_subentity_deletes
Browse files Browse the repository at this point in the history
[PagePartBundle] Allow deleting nested sub-entities
  • Loading branch information
acrobat authored Dec 20, 2023
2 parents be94916 + 3d11ac7 commit e92e3ce
Show file tree
Hide file tree
Showing 2 changed files with 101 additions and 19 deletions.
40 changes: 40 additions & 0 deletions src/Kunstmaan/PagePartBundle/Dto/PagePartDeleteInfo.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?php

namespace Kunstmaan\PagePartBundle\Dto;

/**
* @internal
*/
final class PagePartDeleteInfo
{
private string $name;
private string $id;
private ?PagePartDeleteInfo $nestedDeleteInfo;

public function __construct(string $name, string $id, ?self $nestedDeleteInfo)
{
$this->name = $name;
$this->id = $id;
$this->nestedDeleteInfo = $nestedDeleteInfo;
}

public function getName(): string
{
return $this->name;
}

public function getId(): string
{
return $this->id;
}

public function getNestedDeleteInfo(): ?PagePartDeleteInfo
{
return $this->nestedDeleteInfo;
}

public function hasNestedDeleteInfo(): bool
{
return null !== $this->nestedDeleteInfo;
}
}
80 changes: 61 additions & 19 deletions src/Kunstmaan/PagePartBundle/PagePartAdmin/PagePartAdmin.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@

namespace Kunstmaan\PagePartBundle\PagePartAdmin;

use Doctrine\ORM\EntityManager;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\EntityManagerInterface;
use Kunstmaan\AdminBundle\Entity\EntityInterface;
use Kunstmaan\PagePartBundle\Dto\PagePartDeleteInfo;
use Kunstmaan\PagePartBundle\Entity\PagePartRef;
use Kunstmaan\PagePartBundle\Event\Events;
use Kunstmaan\PagePartBundle\Event\PagePartEvent;
Expand All @@ -15,10 +16,8 @@
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\PropertyAccess\PropertyAccess;

/**
* PagePartAdmin
*/
class PagePartAdmin
{
/**
Expand All @@ -27,7 +26,7 @@ class PagePartAdmin
protected $configurator;

/**
* @var EntityManager|EntityManagerInterface
* @var EntityManagerInterface
*/
protected $em;

Expand Down Expand Up @@ -142,19 +141,24 @@ public function getPage()

public function preBindRequest(Request $request)
{
// Fetch all sub-entities that should be removed
/** @var array<string, list<PagePartDeleteInfo>> $subPagePartsToDelete */
$subPagePartsToDelete = [];
// Fetch all sub-entities that should be removed
foreach (array_keys($request->request->all()) as $key) {
// Example value: delete_pagepartadmin_74_tags_3
if (preg_match('/^delete_pagepartadmin_(\\d+)_(\\w+)_(\\d+)$/i', $key, $matches)) {
$subPagePartsToDelete[$matches[1]][] = ['name' => $matches[2], 'id' => $matches[3]];
if (!str_starts_with($key, 'delete_pagepartadmin_')) {
continue;
}

preg_match('#^delete_pagepartadmin_(\d+)_(.*)#', $key, $ppInfo);
preg_match_all('#([a-zA-Z0-9]+)_(\\d+)#', $ppInfo[2], $matches, PREG_SET_ORDER);

$subPagePartsToDelete[$ppInfo[1]][] = $this->getDeleteInfo($matches);
}

$doFlush = false;
foreach ($this->pagePartRefs as $pagePartRef) {
// Remove pageparts
if ('true' == $request->request->get($pagePartRef->getId() . '_deleted')) {
if ('true' === $request->request->get($pagePartRef->getId() . '_deleted')) {
$pagePart = $this->pageParts[$pagePartRef->getId()];
$this->em->remove($pagePart);
$this->em->remove($pagePartRef);
Expand All @@ -167,14 +171,12 @@ public function preBindRequest(Request $request)
if (\array_key_exists($pagePartRef->getId(), $subPagePartsToDelete)) {
$pagePart = $this->pageParts[$pagePartRef->getId()];
foreach ($subPagePartsToDelete[$pagePartRef->getId()] as $deleteInfo) {
/** @var EntityInterface[] $objects */
$objects = \call_user_func([$pagePart, 'get' . ucfirst($deleteInfo['name'])]);

foreach ($objects as $object) {
if ($object->getId() == $deleteInfo['id']) {
$this->em->remove($object);
$doFlush = true;
}
/** @var EntityInterface $deleteObject */
$deleteObject = $this->getObjectForDeletion($pagePart, $deleteInfo);

if (null !== $deleteObject) {
$this->em->remove($deleteObject);
$doFlush = true;
}
}
}
Expand All @@ -197,7 +199,7 @@ public function preBindRequest(Request $request)

// Sort pageparts again
$sequences = $request->request->all($this->context . '_sequence');
if (!\is_null($sequences)) {
if ($sequences !== []) {
$tempPageparts = $this->pageParts;
$this->pageParts = [];
foreach ($sequences as $sequence) {
Expand Down Expand Up @@ -366,4 +368,44 @@ public function getClassName($pagepart)
{
return \get_class($pagepart);
}

private function getDeleteInfo(array $deleteKeyMatches): ?PagePartDeleteInfo
{
$currentItem = array_shift($deleteKeyMatches);
if (null === $currentItem) {
return null;
}

return new PagePartDeleteInfo($currentItem[1], $currentItem[2], $this->getDeleteInfo($deleteKeyMatches));
}

private function getObjectForDeletion($obj, PagePartDeleteInfo $deleteInfo): ?object
{
$propertyAccessor = PropertyAccess::createPropertyAccessor();

/** @var Collection<EntityInterface> $objects */
$objects = $propertyAccessor->getValue($obj, $deleteInfo->getName());
$object = null;
if ($deleteInfo->hasNestedDeleteInfo()) {
// When a nested item is deleted the id passed is the collection array key instead of the entity id.
$object = $objects->get($deleteInfo->getId());
} else {
foreach ($objects as $data) {
if ($data->getId() == $deleteInfo->getId()) {
$object = $data;
break;
}
}
}

if ($object === null) {
return null;
}

if (!$deleteInfo->hasNestedDeleteInfo()) {
return $object;
}

return $this->getObjectForDeletion($object, $deleteInfo->getNestedDeleteInfo());
}
}

0 comments on commit e92e3ce

Please sign in to comment.