block_editor-1.0.x-dev/src/Hook/EntityHooks.php
src/Hook/EntityHooks.php
<?php
namespace Drupal\block_editor\Hook;
use Drupal\block_editor\Service\EntityManager;
use Drupal\Core\Config\Entity\ConfigEntityInterface;
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Hook\Attribute\Hook;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\Core\Url;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Hook implementations related to entities.
*/
class EntityHooks implements ContainerInjectionInterface {
use StringTranslationTrait;
/**
* The entity manager.
*
* @var \Drupal\block_editor\Service\EntityManager
*/
protected $entityManager;
/**
* Constructs a new EntityHooks object.
*
* @param \Drupal\block_editor\Service\EntityManager $entity_manager
* The entity manager.
*/
public function __construct(EntityManager $entity_manager) {
$this->entityManager = $entity_manager;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('block_editor.entity_manager')
);
}
/**
* Implements hook_entity_operation().
*
* Adds "Manage Block Editor" operation to entity type listings.
*/
#[Hook('entity_operation')]
public function entityOperation(EntityInterface $entity) {
$operations = [];
// Only add operation for config entities that support Block Editor.
if ($entity instanceof ConfigEntityInterface && $this->entityManager->isBlockEditorEnabledForEntity($entity)) {
$entity_type_id = $entity->getEntityTypeId();
// Dynamically generate the route name.
// Route pattern: block_editor.{entity_type_id}.settings.
$route_name = 'block_editor.' . $entity_type_id . '.settings';
// Try to create the URL. If the route doesn't exist, this will fail
// gracefully and we simply won't add the operation.
try {
$url = Url::fromRoute($route_name, [$entity_type_id => $entity->id()]);
$operations['block_editor_settings'] = [
'title' => $this->t('Manage Block Editor'),
'url' => $url,
'weight' => 15,
];
}
catch (\Exception $e) {
// Route doesn't exist, skip.
}
}
return $operations;
}
/**
* Implements hook_entity_operation_alter().
*/
#[Hook('entity_operation_alter')]
public function entityOperationAlter(array &$operations, EntityInterface $entity): void {
if (!$entity instanceof ContentEntityInterface) {
return;
}
if (!$this->entityManager->isBlockEditorEnabledForContentEntity($entity)) {
return;
}
$weight = 0;
if (isset($operations['edit'])) {
$weight = $operations['edit']['weight'] ?? 0;
unset($operations['edit']);
}
$operations['block_editor_edit'] = [
'title' => $this->t('Edit'),
'url' => Url::fromRoute(
'block_editor.entity.' . $entity->getEntityTypeId() . '.edit_form',
[$entity->getEntityTypeId() => $entity->id()]
),
'weight' => $weight,
];
}
/**
* Implements hook_entity_type_alter().
*
* Adds Block Editor settings link templates to supported entity types
* and registers Block Editor form handlers.
*/
#[Hook('entity_type_alter')]
public function entityTypeAlter(array &$entity_types) {
// Dynamically get all entity types that support Block Editor.
$content_entity_mappings = $this->entityManager->getSupportedEntityTypeMappings();
foreach ($content_entity_mappings as $config_type => $content_type) {
// Add link template for the bundle entity type's settings page.
if (isset($entity_types[$config_type])) {
$config_entity_type = $entity_types[$config_type];
// Get the edit form route to derive the settings path.
$edit_route = $config_entity_type->getLinkTemplate('edit-form');
if ($edit_route) {
// Append '/block-editor-settings' to the edit form path.
$settings_path = rtrim($edit_route, '/') . '/block-editor-settings';
$config_entity_type->setLinkTemplate('block_editor_settings', $settings_path);
}
}
// Add Block Editor form handler for the content entity type.
if (isset($entity_types[$content_type])) {
$content_entity_type = $entity_types[$content_type];
$handlers = $content_entity_type->getHandlerClasses();
if (isset($handlers['form'])) {
// Add the specific block_editor form mode handled by our form.
$handlers['form']['block_editor'] = 'Drupal\block_editor\Form\EntityEditForm';
$content_entity_type->setHandlerClass('form', $handlers['form']);
}
}
}
}
/**
* Implements hook_entity_url_alter().
*
* For entity types where canonical IS the edit form (like block_content),
* redirect to the Block Editor edit form when Block Editor is enabled.
*/
#[Hook('entity_url_alter')]
public function entityUrlAlter(array &$uri_info, EntityInterface $entity, array &$options): void {
// Only alter URLs for content entities.
if (!$entity instanceof ContentEntityInterface) {
return;
}
// Check if this is the canonical or edit-form link.
$rel = $uri_info['rel'] ?? NULL;
if (!in_array($rel, ['canonical', 'edit-form'], TRUE)) {
return;
}
// Check if Block Editor is enabled for this entity.
if (!$this->entityManager->isBlockEditorEnabledForContentEntity($entity)) {
return;
}
$entity_type = $entity->getEntityType();
$entity_type_id = $entity->getEntityTypeId();
// Check if canonical and edit-form are the same for this entity type.
// This indicates the entity uses edit as canonical (e.g., block_content).
$canonical_link = $entity_type->getLinkTemplate('canonical');
$edit_form_link = $entity_type->getLinkTemplate('edit-form');
if ($canonical_link === $edit_form_link || $rel === 'edit-form') {
// Redirect to Block Editor edit form.
$uri_info['route_name'] = 'block_editor.entity.' . $entity_type_id . '.edit_form';
$uri_info['route_parameters'] = [$entity_type_id => $entity->id()];
}
}
}
