toolshed-8.x-1.x-dev/src/Entity/EntityBundleBase.php
src/Entity/EntityBundleBase.php
<?php
namespace Drupal\toolshed\Entity;
use Drupal\Component\Render\MarkupInterface;
use Drupal\Component\Utility\Html;
use Drupal\Core\Config\Entity\ConfigEntityBundleBase;
use Drupal\Core\Entity\EntityStorageException;
use Drupal\Core\Entity\EntityStorageInterface;
/**
* A bundle entity which checks for content using the bundle before deleting.
*/
abstract class EntityBundleBase extends ConfigEntityBundleBase {
/**
* Check if this bundle has content data.
*
* New config entities cannot have any content created for them yet, so will
* always return FALSE.
*
* @return bool
* TRUE if there is content using the type as a bundle, or FALSE is there
* is no data of this type.
*/
public function hasData(): bool {
$bundleOf = $this->getEntityType()->getBundleOf();
if (!$this->isNew() && $bundleOf) {
$entityTypeManager = \Drupal::entityTypeManager();
$bundleKey = $entityTypeManager
->getDefinition($bundleOf)
->getKey('bundle');
return (bool) $entityTypeManager->getStorage($bundleOf)
->getQuery()
->accessCheck(FALSE)
->condition($bundleKey, $this->id())
->range(0, 1)
->execute();
}
return FALSE;
}
/**
* {@inheritdoc}
*/
public static function preDelete(EntityStorageInterface $storage, array $entities): void {
$entityTypeManager = \Drupal::entityTypeManager();
// Sort the entities by their entity type. This should only ever be
// one entity type, but it's worth doing this safely, by checking first.
$byBundleOf = [];
foreach ($entities as $entity) {
if ($bundleOf = $entity->getEntityType()->getBundleOf()) {
$label = $entity->label();
$byBundleOf[$bundleOf][$entity->id()] = $label instanceof MarkupInterface ? $label : Html::escape($label);
}
}
foreach ($byBundleOf as $contentTypeId => $bundles) {
$contentEntityType = $entityTypeManager->getDefinition($contentTypeId);
$query = $entityTypeManager
->getStorage($contentTypeId)
->getQuery()
->accessCheck(FALSE)
->range(0, 1);
$bundleIds = array_keys($bundles);
if (count($bundles) === 1) {
$query->condition($contentEntityType->getKey('bundle'), reset($bundleIds));
}
else {
$query->condition($contentEntityType->getKey('bundle'), $bundleIds, 'IN');
}
if ((bool) $query->execute()) {
$msg = count($bundles)
? 'The %s bundle contains data and can not be deleted.'
: 'The some or all of the following %s bundles contain data and cannot be delete.';
// Use the 409 (Conflict) status code to indicate that the deletion
// could not be completed due to a conflict with the current state of
// the target resource.
$msg = sprintf($msg, implode(', ', $bundles));
throw new EntityStorageException($msg, 409);
}
}
parent::preDelete($storage, $entities);
}
}
