Skip to content
Snippets Groups Projects
Commit 76e99c5e authored by Alexandre Mallet's avatar Alexandre Mallet Committed by Alexandre Mallet
Browse files

Issue #2929439 by woprrr, sallakane: Make Form Mode Manager compatible with...

Issue #2929439 by woprrr, sallakane: Make Form Mode Manager compatible with entities not using bundles
parent fa02529c
No related branches found
No related tags found
No related merge requests found
Showing
with 1013 additions and 303 deletions
......@@ -4,5 +4,5 @@ type: module
core: 8.x
configure: form_mode_manager.admin_settings
dependencies:
- field
- field_ui
- drupal:field
- drupal:field_ui
......@@ -6,8 +6,6 @@
*/
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Link;
use Drupal\Core\Url;
use Drupal\form_mode_manager\EntityTypeInfo;
/**
......@@ -45,50 +43,3 @@ function form_mode_manager_entity_operation_alter(array &$operations, EntityInte
->getInstanceFromDefinition(EntityTypeInfo::class)
->entityOperationAlter($operations, $entity);
}
/**
* Implements hook_theme().
*/
function form_mode_manager_theme() {
return [
'form_mode_manager_add_list' => [
'variables' => [
'content' => NULL,
'form_mode' => NULL,
'entity_type' => NULL,
],
],
];
}
/**
* Prepares variables for list of available entity type templates.
*
* Default template: form-mode-manager-add-list.html.twig.
*
* @param array $variables
* An associative array containing:
* - content: An array of content types.
*
* @see \Drupal\form_mode_manager\Controller\EntityFormModeController::addPage()
*/
function template_preprocess_form_mode_manager_add_list(array &$variables) {
$variables['types'] = [];
$entity_type_id = $variables['entity_type'];
/** @var \Drupal\form_mode_manager\EntityRoutingMapBase $entity_operation_mapping */
$entity_operation_mapping = \Drupal::service("plugin.manager.entity_routing_map")
->createInstance($entity_type_id, ['entityTypeId' => $entity_type_id]);
if (!empty($variables['content'])) {
/** @var \Drupal\Core\Config\Entity\ConfigEntityBundleBase $type */
foreach ($variables['content'] as $type) {
$route_name = $entity_operation_mapping->getOperation('add_form') . ".{$variables['form_mode']}";
$variables['types'][$type->id()] = [
'type' => $type->id(),
'add_link' => Link::fromTextAndUrl($type->label(), new Url($route_name, [$type->getEntityTypeId() => $type->id()])),
'description' => [
'#markup' => (method_exists($type, 'getDescription')) ? $type->getDescription() : $type->label(),
],
];
}
}
}
\ No newline at end of file
......@@ -7,6 +7,7 @@ form_mode_manager.admin_settings:
_permission: 'administer site configuration'
options:
_admin_route: TRUE
form_mode_manager.admin_settings_links_task:
path: '/admin/config/content/form_mode_manager/links-task'
defaults:
......@@ -16,5 +17,3 @@ form_mode_manager.admin_settings_links_task:
_permission: 'administer site configuration'
options:
_admin_route: TRUE
options:
_admin_route: TRUE
......@@ -4,21 +4,11 @@ services:
arguments: ['@entity_type.manager', '@entity_display.repository', '@form_mode.manager', '@plugin.manager.entity_routing_map']
tags:
- { name: event_subscriber }
form_mode_manager.user_route_subscriber:
class: Drupal\form_mode_manager\Routing\EventSubscriber\UserFormModesSubscriber
arguments: ['@entity_type.manager', '@entity_display.repository', '@form_mode.manager', '@plugin.manager.entity_routing_map']
tags:
- { name: event_subscriber }
form_mode_manager.default_routes_subscriber:
class: Drupal\form_mode_manager\Routing\EventSubscriber\DefaultRouteSubscriber
arguments: ['@entity_type.manager', '@form_mode.manager', '@plugin.manager.entity_routing_map']
tags:
- { name: event_subscriber }
form_mode_manager.param_converter:
class: Drupal\form_mode_manager\ParamConverter\FormModeManagerConverter
arguments: ['@form_mode.manager']
tags:
- { name: paramconverter }
form_mode.manager:
class: Drupal\form_mode_manager\FormModeManager
arguments: ['@entity_type.manager', '@config.factory', '@entity_display.repository', '@entity_type.bundle.info', '@plugin.manager.entity_routing_map']
......
......@@ -3,9 +3,9 @@ type: module
description: Form Mode Manager allows to use form_mode implement on Drupal 8 on each Entity.
core: 8.x
dependencies:
- node
- image
- user
- form_mode_manager
- drupal:node
- drupal:image
- drupal:user
- drupal:form_mode_manager
theme:
- bartik
......@@ -56,7 +56,7 @@ class FormModeManagerExamplesTest extends BrowserTestBase {
// Add test for form mode manager actions.
$this->drupalLogin($this->rootUser);
$this->drupalGet('');
$this->assertSession()->linkExists('Add node as Contributor');
$this->assertSession()->linkExists('Add content as Contributor');
}
}
<?php
namespace Drupal\form_mode_manager;
use Drupal\Core\Cache\Cache;
use Drupal\Core\Link;
use Drupal\Core\Routing\RouteMatchInterface;
/**
* Route controller factory specific for each entities using bundles.
*
* This Factory are specific to work with entities using bundles and need more,
* specific code to implement it. The best example of that specific things are,
* "type" keys or add pages to chooses what kind of entity we need to create.
* This controller can be a good base to implement our custom things in our,
* custom entities using bundles.
*/
class ComplexEntityFormModes extends AbstractEntityFormModesFactory {
/**
* {@inheritdoc}
*
* @return array|\Symfony\Component\HttpFoundation\RedirectResponse
* A render array for a list of the entity types that can be added; however,
* if there is only one entity type defined for the site, the function
* will return a RedirectResponse to the entity add page for that one entity
* type.
*/
public function addPage(RouteMatchInterface $route_match) {
$entity_type_id = $route_match
->getRouteObject()
->getOption('_form_mode_manager_entity_type_id');
$entity_bundle_name = $route_match
->getRouteObject()
->getOption('_form_mode_manager_bundle_entity_type_id');
$form_mode_name = $route_match->getParameter('form_mode_name');
$entity_routes_infos = $this->entityRoutingMap
->createInstance($entity_type_id, ['entityTypeId' => $entity_type_id])
->getPluginDefinition();
$entity_type_cache_tags = $this->entityTypeManager
->getDefinition($entity_bundle_name)
->getListCacheTags();
$build = [
'#theme' => 'entity_add_list',
'#bundles' => [],
'#add_bundle_message' => $this->t('There is no @entity_type yet.', ['@entity_type' => $entity_type_id]),
'#cache' => [
'tags' => Cache::mergeTags($entity_type_cache_tags, $this->formModeManager->getListCacheTags()),
],
];
$entity_type_definitions = $this->entityTypeManager
->getStorage($entity_bundle_name)
->loadMultiple();
$entity_add_form = $entity_routes_infos['operations']['add_form'] . ".$form_mode_name";
foreach ($entity_type_definitions as $bundle) {
$bundle_name = $bundle->id();
if ($access = $this->accessIsAllowed($entity_type_id, $bundle_name, $form_mode_name)) {
$description = (method_exists($bundle, 'getDescription')) ? $bundle->getDescription() : '';
$build['#bundles'][$bundle_name] = [
'label' => $bundle->label(),
'description' => $description,
'add_link' => Link::createFromRoute($bundle->label(), $entity_add_form, [$entity_bundle_name => $bundle->id()]),
];
$this->renderer->addCacheableDependency($build, $access);
}
}
// Bypass the entity/add listing if only one content type is available.
if (1 == count($build['#bundles'])) {
$bundle = current($build['#bundles']);
return $this->redirect($entity_add_form, $bundle['add_link']->getUrl()->getRouteParameters());
}
return $build;
}
/**
* Evaluate if current user has access to this bundle AND form mode.
*
* @param string $entity_type_id
* The id of current entity.
* @param string $bundle_name
* The name of current bundle need to access.
* @param string $form_mode_name
* The form mode name to use.
*
* @return bool
* True if you can access to this entity type as given form mode.
*/
public function accessIsAllowed($entity_type_id, $bundle_name, $form_mode_name) {
$access = $this->entityTypeManager
->getAccessControlHandler($entity_type_id)
->createAccess($bundle_name, $this->account, [], TRUE);
return $access->isAllowed() && $this->formModeManager->isActive($entity_type_id, $bundle_name, $form_mode_name);
}
/**
* {@inheritdoc}
*
* @return \Drupal\Core\Entity\EntityInterface
* The entity loaded form route_match.
*
* @throws \Exception
* If an invalid entity is retrieving from the route object.
*/
public function getEntity(RouteMatchInterface $route_match) {
/* @var \Drupal\Core\Entity\EntityInterface $entity */
$entity = $this->getEntityFromRouteMatch($route_match);
// If we can't retrieve the entity from the route match get load,
// it by their storage with correct route bundle key.
if (empty($entity)) {
$route_entity_type_info = $this->getEntityTypeFromRouteMatch($route_match);
/* @var \Drupal\Core\Entity\EntityInterface $entity */
$entity = $this->entityTypeManager->getStorage($route_entity_type_info['entity_type_id'])->create([
$route_entity_type_info['entity_key'] => $route_entity_type_info['bundle'],
]);
}
return $entity;
}
/**
* {@inheritdoc}
*
* @return \Drupal\Core\Entity\EntityInterface
* A new entity object build with given route_match.
*/
public function getEntityFromRouteMatch(RouteMatchInterface $route_match) {
$entity_type_id = $route_match->getRouteObject()
->getOption('_form_mode_manager_entity_type_id');
$bundle_entity_type_id = $route_match->getRouteObject()
->getOption('_form_mode_manager_bundle_entity_type_id');
$entity = $route_match->getParameter($entity_type_id);
if (empty($entity)) {
$entity = $this->entityTypeManager->getStorage($entity_type_id)->create([
'type' => $route_match->getParameter($bundle_entity_type_id),
]);
}
return $entity;
}
/**
* {@inheritdoc}
*
* @return array
* The entity object as determined from the passed-in route match.
*/
public function getEntityTypeFromRouteMatch(RouteMatchInterface $route_match) {
$route = $route_match->getRouteObject();
$entity_type_id = $route->getOption('_form_mode_manager_entity_type_id');
$bundle_entity_type_id = $route->getOption('_form_mode_manager_bundle_entity_type_id');
$form_mode = $this->formModeManager->getFormModeMachineName($route->getDefault('_entity_form'));
$bundle = $route_match->getParameter($bundle_entity_type_id);
$form_mode_definition = $this->formModeManager->getActiveDisplaysByBundle($entity_type_id, $bundle);
$entity_type_key = $this->entityTypeManager
->getDefinition($entity_type_id)
->getKey('bundle');
return [
'bundle' => $bundle,
'bundle_entity_type' => $bundle_entity_type_id,
'entity_key' => $entity_type_key,
'entity_type_id' => $entity_type_id,
'form_mode' => isset($form_mode_definition[$entity_type_id][$form_mode]) ? $form_mode_definition[$entity_type_id][$form_mode] : NULL,
];
}
}
<?php
namespace Drupal\form_mode_manager\Controller;
/**
* Controller for entity form mode support.
*
* @see \Drupal\form_mode_manager\Routing\RouteSubscriber
* @see \Drupal\form_mode_manager\Plugin\Derivative\FormModeManagerLocalAction
* @see \Drupal\form_mode_manager\Plugin\Derivative\FormModeManagerLocalTasks
*/
class EntityFormModeController extends EntityFormModeBase {
}
<?php
namespace Drupal\form_mode_manager\Controller;
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
use Drupal\Core\Entity\EntityFormBuilderInterface;
use Drupal\Core\Entity\EntityStorageInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Form\FormBuilderInterface;
use Drupal\Core\Render\RendererInterface;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\form_mode_manager\ComplexEntityFormModes;
use Drupal\form_mode_manager\EntityFormModeManagerInterface;
use Drupal\form_mode_manager\MediaEntityFormModes;
use Drupal\form_mode_manager\SimpleEntityFormModes;
use Drupal\form_mode_manager\EntityRoutingMapManager;
use Drupal\form_mode_manager\FormModeManagerInterface;
use Drupal\form_mode_manager\TaxonomyEntityFormModes;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Generic Controller for entity using form mode manager routing.
*
* This controller are very transverse and use an Abstract Factory to build,
* objects compatible with all ContentEntities. This controller are linked by,
* Abstract Factory by EntityFormModeManagerInterface each methods in that,
* interface are called by routing.
*/
class FormModeManagerEntityController implements EntityFormModeManagerInterface, ContainerInjectionInterface {
/**
* The date formatter service.
*
* @var \Drupal\Core\Datetime\DateFormatterInterface
*/
protected $dateFormatter;
/**
* The renderer service.
*
* @var \Drupal\Core\Render\RendererInterface
*/
protected $renderer;
/**
* The current user.
*
* @var \Drupal\Core\Session\AccountInterface
*/
protected $account;
/**
* The entity display repository.
*
* @var \Drupal\form_mode_manager\FormModeManagerInterface
*/
protected $formModeManager;
/**
* The entity form builder service.
*
* @var \Drupal\Core\Entity\EntityFormBuilderInterface
*/
protected $entityFormBuilder;
/**
* The Routes Manager Plugin.
*
* @var \Drupal\form_mode_manager\EntityRoutingMapManager
*/
protected $entityRoutingMap;
/**
* The form builder.
*
* @var \Drupal\Core\Form\FormBuilderInterface
*/
protected $formBuilder;
/**
* The entity type manager service.
*
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
*/
protected $entityTypeManager;
/**
* Constructs a EntityFormModeController object.
*
* @param \Drupal\Core\Render\RendererInterface $renderer
* The renderer service.
* @param \Drupal\Core\Session\AccountInterface $account
* The current user.
* @param \Drupal\form_mode_manager\FormModeManagerInterface $form_mode_manager
* The form mode manager.
* @param \Drupal\Core\Entity\EntityFormBuilderInterface $entity_form_builder
* The entity form builder service.
* @param \Drupal\form_mode_manager\EntityRoutingMapManager $plugin_routes_manager
* Plugin EntityRoutingMap to retrieve entity form operation routes.
* @param \Drupal\Core\Form\FormBuilderInterface $form_builder
* The form builder.
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
* The entity type manager.
*/
public function __construct(RendererInterface $renderer, AccountInterface $account, FormModeManagerInterface $form_mode_manager, EntityFormBuilderInterface $entity_form_builder, EntityRoutingMapManager $plugin_routes_manager, FormBuilderInterface $form_builder, EntityTypeManagerInterface $entity_type_manager) {
$this->renderer = $renderer;
$this->account = $account;
$this->formModeManager = $form_mode_manager;
$this->entityFormBuilder = $entity_form_builder;
$this->entityRoutingMap = $plugin_routes_manager;
$this->formBuilder = $form_builder;
$this->entityTypeManager = $entity_type_manager;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('renderer'),
$container->get('current_user'),
$container->get('form_mode.manager'),
$container->get('entity.form_builder'),
$container->get('plugin.manager.entity_routing_map'),
$container->get('form_builder'),
$container->get('entity_type.manager')
);
}
/**
* {@inheritdoc}
*/
public function addPage(RouteMatchInterface $route_match) {
return $this->getEntityControllerResponse(__FUNCTION__, $route_match);
}
/**
* {@inheritdoc}
*/
public function addPageTitle(RouteMatchInterface $route_match) {
return $this->getEntityControllerResponse(__FUNCTION__, $route_match);
}
/**
* {@inheritdoc}
*/
public function checkAccess(RouteMatchInterface $route_match) {
return $this->getEntityControllerResponse(__FUNCTION__, $route_match);
}
/**
* {@inheritdoc}
*/
public function editPageTitle(RouteMatchInterface $route_match) {
return $this->getEntityControllerResponse(__FUNCTION__, $route_match);
}
/**
* {@inheritdoc}
*/
public function entityAdd(RouteMatchInterface $route_match) {
return $this->getEntityControllerResponse(__FUNCTION__, $route_match);
}
/**
* {@inheritdoc}
*/
public function entityEdit(RouteMatchInterface $route_match) {
return $this->getEntityControllerResponse(__FUNCTION__, $route_match);
}
/**
* Instantiate correct objects depending entities.
*
* Contain all the logic to use the abstract factory and call,
* correct entityFormMode object depending entity_type using bundles,
* or if the entity need to be processed specifically like Taxonomy.
*
* All of children object share EntityFormModeManagerInterface to make sure,
* methods are used by factory.
*
* @param string $method
* Name of the method we need to build.
* @param \Drupal\Core\Routing\RouteMatchInterface $route_match
* The current route match.
*
* @return \Drupal\form_mode_manager\EntityFormModeManagerInterface
* An instance of correct controller object.
*
* @throws \Exception
* Thrown when specified method was not found.
*/
public function getEntityControllerResponse($method, RouteMatchInterface $route_match) {
$entity_type_id = $route_match->getRouteObject()
->getOption('_form_mode_manager_entity_type_id');
$entity_storage = $this->entityTypeManager->getStorage($entity_type_id);
// Entities without bundles need to be flagged 'unbundled_entity'.
$entity_type_id = $this->bundledEntity($entity_storage) ? $entity_type_id : 'unbundled_entity';
$controller_object = $this->getEntityControllerObject($entity_type_id);
if (!method_exists($controller_object, $method)) {
throw new \Exception('Specified ' . $method . ' method not found.');
}
return $controller_object->{$method}($route_match);
}
/**
* Get the correct controller object Factory depending kind of entity.
*
* @param string $entity_type_id
* The name of entity type.
*
* @return \Drupal\form_mode_manager\EntityFormModeManagerInterface
* An instance of correct controller object.
*/
public function getEntityControllerObject($entity_type_id) {
switch ($entity_type_id) {
case 'unbundled_entity':
$object = new SimpleEntityFormModes(
$this->renderer,
$this->account,
$this->formModeManager,
$this->entityFormBuilder,
$this->entityRoutingMap,
$this->formBuilder,
$this->entityTypeManager
);
break;
case 'taxonomy_term':
$object = new TaxonomyEntityFormModes(
$this->renderer,
$this->account,
$this->formModeManager,
$this->entityFormBuilder,
$this->entityRoutingMap,
$this->formBuilder,
$this->entityTypeManager
);
break;
case 'media':
$object = new MediaEntityFormModes(
$this->renderer,
$this->account,
$this->formModeManager,
$this->entityFormBuilder,
$this->entityRoutingMap,
$this->formBuilder,
$this->entityTypeManager
);
break;
default:
$object = new ComplexEntityFormModes(
$this->renderer,
$this->account,
$this->formModeManager,
$this->entityFormBuilder,
$this->entityRoutingMap,
$this->formBuilder,
$this->entityTypeManager
);
break;
}
return $object;
}
/**
* Evaluate if current entity have bundles or not.
*
* @param \Drupal\Core\Entity\EntityStorageInterface $entity_storage
* The entity storage.
*
* @return string
* The bundle key if entity has bundles or empty.
*/
public function bundledEntity(EntityStorageInterface $entity_storage) {
return $entity_storage->getEntityType()->getKey('bundle');
}
}
<?php
namespace Drupal\form_mode_manager\Controller;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Routing\RouteMatchInterface;
/**
* Controller for specific User entity form mode support.
*
* @see \Drupal\form_mode_manager\Routing\RouteSubscriber
* @see \Drupal\form_mode_manager\Plugin\Derivative\FormModeManagerLocalAction
* @see \Drupal\form_mode_manager\Plugin\Derivative\FormModeManagerLocalTasks
*/
class UserFormModeController extends EntityFormModeBase {
/**
* Provides the entity submission form.
*
* @param \Drupal\Core\Routing\RouteMatchInterface $route_match
* The current route match.
*
* @return array
* A User submission form.
*
* @throws \Exception
* If invalid entity type or form mode not exist.
*/
public function entityAdd(RouteMatchInterface $route_match) {
/* @var \Drupal\Core\Entity\EntityInterface $entity */
$entity = $this->getEntityFromRouteMatch($route_match);
if (empty($entity)) {
$route_entity_type_info = $this->getEntityTypeFromRouteMatch($route_match);
/* @var \Drupal\Core\Entity\EntityInterface $entity */
$entity = $this->entityTypeManager->getStorage($route_entity_type_info['entity_type_id'])->create([
$route_entity_type_info['entity_key'] => $route_entity_type_info['bundle'],
]);
}
$form_mode_id = $this->formModeManager->getFormModeMachineName($route_match->getRouteObject()->getOption('parameters')['form_mode']['id']);
$operation = empty($form_mode_id) ? 'register' : $form_mode_id;
if ($entity instanceof EntityInterface) {
return $this->entityFormBuilder->getForm($entity, $operation);
}
}
/**
* Provides the entity 'edit' form.
*
* @param \Drupal\Core\Routing\RouteMatchInterface $route_match
* The current route match.
*
* @return array
* The entity edit Form.
*/
public function entityEdit(RouteMatchInterface $route_match) {
/* @var \Drupal\Core\Entity\EntityInterface $entity */
$entity = $this->getEntityFromRouteMatch($route_match);
$form_mode_id = $this->formModeManager->getFormModeMachineName($route_match->getRouteObject()->getOption('parameters')['form_mode']['id']);
$operation = empty($form_mode_id) ? 'register' : 'edit_' . $form_mode_id;
if ($entity instanceof EntityInterface) {
return $this->getForm($entity, $operation);
}
}
/**
* The _title_callback for the entity.add routes.
*
* @param \Drupal\Core\Routing\RouteMatchInterface $route_match
* The current route match.
* @param string $operation
* Name of current context operation to display title (create/edit).
*
* @return string
* The page title.
*/
public function pageTitle(RouteMatchInterface $route_match, $operation) {
$form_mode_label = $route_match->getRouteObject()
->getOption('parameters')['form_mode']['label'];
return $this->t('@op @name as @form_mode_label', [
'@name' => 'User',
'@form_mode_label' => $form_mode_label,
'@op' => $operation,
]);
}
/**
* The _title_callback for the entity.add routes.
*
* @param \Drupal\Core\Routing\RouteMatchInterface $route_match
* The current route match.
*
* @return string
* The page title.
*/
public function addPageTitle(RouteMatchInterface $route_match) {
return $this->pageTitle($route_match, $this->t('Create'));
}
/**
* The _title_callback for the entity.add routes.
*
* @param \Drupal\Core\Routing\RouteMatchInterface $route_match
* The current route match.
*
* @return string
* The page title.
*/
public function editPageTitle(RouteMatchInterface $route_match) {
return $this->pageTitle($route_match, $this->t('Edit'));
}
/**
* Retrieves entity from route match.
*
* @param \Drupal\Core\Routing\RouteMatchInterface $route_match
* The route match.
*
* @return array
* The entity object as determined from the passed-in route match.
*/
protected function getEntityTypeFromRouteMatch(RouteMatchInterface $route_match) {
$parametters = parent::getEntityTypeFromRouteMatch($route_match);
$form_mode = $this->formModeManager->getFormModeMachineName($route_match->getRouteObject()->getOption('parameters')['form_mode']['id']);
$form_mode_definition = $this->formModeManager->getActiveDisplays($parametters['entity_type_id']);
$parametters['form_mode'] = $form_mode_definition[$form_mode];
return $parametters;
}
}
<?php
namespace Drupal\form_mode_manager;
use Drupal\Core\Routing\RouteMatchInterface;
/**
* Interface EntityFormModeManagerInterface.
*/
interface EntityFormModeManagerInterface {
/**
* Displays add content links for available entity types.
*
* Redirects to entity/add/[bundle] if only one content type is available.
*/
public function addPage(RouteMatchInterface $route_match);
/**
* The _title_callback for the entity.add routes.
*
* @param \Drupal\Core\Routing\RouteMatchInterface $route_match
* The current route match.
*/
public function addPageTitle(RouteMatchInterface $route_match);
/**
* Checks access for the Form Mode Manager routes.
*
* @param \Drupal\Core\Routing\RouteMatchInterface $route_match
* The current route match.
*/
public function checkAccess(RouteMatchInterface $route_match);
/**
* The _title_callback for the entity.add routes.
*
* @param \Drupal\Core\Routing\RouteMatchInterface $route_match
* The current route match.
*/
public function editPageTitle(RouteMatchInterface $route_match);
/**
* Provides the entity add submission form.
*
* @param \Drupal\Core\Routing\RouteMatchInterface $route_match
* The current route match.
*/
public function entityAdd(RouteMatchInterface $route_match);
/**
* Provides the entity 'edit' form.
*
* @param \Drupal\Core\Routing\RouteMatchInterface $route_match
* The current route match.
*/
public function entityEdit(RouteMatchInterface $route_match);
}
......@@ -9,6 +9,14 @@ use Drupal\Core\StringTranslation\StringTranslationTrait;
/**
* Base class for form mode manager entity routing plugin.
*
* This plugin are used to abstract the concepts implemented by EntityPlugin.
* In Entity API we have possibilitity to linked entity form 'handlers' to a,
* specific FormClass, but the operation name and routes linked with her are,
* very arbitrary and unpredictable specially in custom entities cases.
* In that plugin you have the possibility to map operation and,
* others useful information about entity to reduce complexity of,
* retrieving each possible cases.
*/
abstract class EntityRoutingMapBase extends PluginBase implements EntityRoutingMapInterface, ContainerFactoryPluginInterface {
use StringTranslationTrait;
......@@ -72,6 +80,9 @@ abstract class EntityRoutingMapBase extends PluginBase implements EntityRoutingM
/**
* {@inheritdoc}
*
* @param string $operation_name
* The name of needed operation to retrieve.
*/
public function getOperation($operation_name) {
if (isset($this->pluginDefinition['operations'][$operation_name])) {
......
......@@ -161,7 +161,7 @@ class EntityTypeInfo implements ContainerInjectionInterface {
*
* @see entityOperationAlter()
*/
public function grantAccessToEditOperation($operations, EntityInterface $entity) {
public function grantAccessToEditOperation(array $operations, EntityInterface $entity) {
return isset($operations['edit']) && !$this->currentUser->hasPermission("use {$entity->getEntityTypeId()}.default form mode");
}
......
......@@ -91,7 +91,7 @@ class FormModeManager implements FormModeManagerInterface {
$ids = $this->configFactory->listAll($config_prefix . '.' . $entity_type_id . '.');
foreach ($ids as $id) {
$config_id = str_replace($config_prefix . '.', '', $id);
list(, , $form_mode_name) = explode('.', $config_id);
list(,, $form_mode_name) = explode('.', $config_id);
if ($form_mode_name != 'default') {
$load_ids[] = $config_id;
}
......@@ -226,6 +226,7 @@ class FormModeManager implements FormModeManagerInterface {
* {@inheritdoc}
*/
public function isActive($entity_type_id, $bundle_id, $form_mode_machine_name) {
$bundle_id = isset($bundle_id) ? $bundle_id : $entity_type_id;
$form_mode_active = array_keys($this->entityDisplayRepository->getFormModeOptionsByBundle($entity_type_id, $bundle_id));
return in_array($form_mode_machine_name, $form_mode_active);
}
......
......@@ -135,7 +135,7 @@ interface FormModeManagerInterface {
* @param string $entity_type_id
* The entity type id.
* @param string $bundle_id
* Name of bundle for current entity.
* (Optional) Name of bundle for current entity.
* @param string $form_mode_machine_name
* Machine name of form mode.
*
......
<?php
namespace Drupal\form_mode_manager;
use Drupal\Core\Routing\RouteMatchInterface;
/**
* Route controller factory specific for Media (core) entities.
*
* This Factory are inherited from ComplexEntityFormModes because this entity,
* implement some specific things proper to Media like 'type' => 'bundle'.
*/
class MediaEntityFormModes extends ComplexEntityFormModes {
/**
* {@inheritdoc}
*/
public function getEntityFromRouteMatch(RouteMatchInterface $route_match) {
$entity_type_id = $route_match->getRouteObject()
->getOption('_form_mode_manager_entity_type_id');
$bundle_entity_type_id = $route_match->getRouteObject()
->getOption('_form_mode_manager_bundle_entity_type_id');
$entity = $route_match->getParameter($entity_type_id);
if (empty($entity)) {
$entity = $this->entityTypeManager->getStorage($entity_type_id)->create([
'bundle' => $route_match->getParameter($bundle_entity_type_id),
]);
}
return $entity;
}
}
<?php
namespace Drupal\form_mode_manager\ParamConverter;
use Drupal\Core\ParamConverter\ParamConverterInterface;
use Drupal\form_mode_manager\FormModeManagerInterface;
use Symfony\Component\Routing\Route;
/**
* Converter for form_mode_manager routes.
*
* This Converter is only used in add_page context.
*
* @see \Drupal\form_mode_manager\Controller\EntityFormModeBase::addPage
*/
class FormModeManagerConverter implements ParamConverterInterface {
/**
* The entity display repository.
*
* @var \Drupal\form_mode_manager\FormModeManagerInterface
*/
protected $formModeManager;
/**
* Constructs a new FormModeManagerConverter.
*
* @param \Drupal\form_mode_manager\FormModeManagerInterface $form_mode_manager
* The form mode manager.
*/
public function __construct(FormModeManagerInterface $form_mode_manager) {
$this->formModeManager = $form_mode_manager;
}
/**
* {@inheritdoc}
*/
public function convert($value, $definition, $name, array $defaults) {
$entity_type_id = $defaults['_route_object']->getOption('_form_mode_manager_entity_type_id');
$form_mode_id = $entity_type_id . '.' . $value;
if ($form_mode_id === $defaults['_entity_form'] && $entity_type_id) {
return $this->formModeManager->getFormModesByEntity($entity_type_id)[$value];
}
return $value;
}
/**
* {@inheritdoc}
*/
public function applies($definition, $name, Route $route) {
if ('form_mode_name' === $name && (!empty($definition['type']) && 0 != preg_match('/^.*\./', $definition['type']))) {
return TRUE;
}
return FALSE;
}
/**
* Get the entity loaded into current route.
*
* If we are in classic case _entity_form are always here,
* but in custom "list_page" route provide by FormModeManager,
* We need to retrive the entity_type in "_route_object".
*
* @param array $defaults
* The route defaults array.
* @param array $definition
* The parameter definition provided in the route options.
*
* @return string|false
* Extract the entity_type_id of current entity.
*/
protected function getEntityForm(array $defaults, array $definition) {
$entity_form = $defaults['_entity_form'];
$form_mode_id = $defaults['_route_object']->getOption('_form_mode_manager_entity_type_id') . '.' . $defaults['form_mode_name'];
if ($entity_form === $form_mode_id) {
return explode('.', $defaults['_entity_form'])[0];
}
return FALSE;
}
}
......@@ -3,8 +3,10 @@
namespace Drupal\form_mode_manager\Plugin\Derivative;
use Drupal\Component\Plugin\Derivative\DeriverBase;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Plugin\Discovery\ContainerDeriverInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\form_mode_manager\EntityRoutingMapManager;
use Drupal\form_mode_manager\FormModeManagerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
......@@ -22,14 +24,34 @@ class FormModeManagerLocalAction extends DeriverBase implements ContainerDeriver
*/
protected $formModeManager;
/**
* The entity type manager service.
*
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
*/
protected $entityTypeManager;
/**
* The Routes Manager Plugin.
*
* @var \Drupal\form_mode_manager\EntityRoutingMapManager
*/
protected $entityRoutingMap;
/**
* Constructs a FormModeManagerLocalAction object.
*
* @param \Drupal\form_mode_manager\FormModeManagerInterface $form_mode_manager
* The form mode manager.
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_manager
* The entity type manager.
* @param \Drupal\form_mode_manager\EntityRoutingMapManager $plugin_routes_manager
* Plugin EntityRoutingMap to retrieve entity form operation routes.
*/
public function __construct(FormModeManagerInterface $form_mode_manager) {
public function __construct(FormModeManagerInterface $form_mode_manager, EntityTypeManagerInterface $entity_manager, EntityRoutingMapManager $plugin_routes_manager) {
$this->formModeManager = $form_mode_manager;
$this->entityTypeManager = $entity_manager;
$this->entityRoutingMap = $plugin_routes_manager;
}
/**
......@@ -37,7 +59,10 @@ class FormModeManagerLocalAction extends DeriverBase implements ContainerDeriver
*/
public static function create(ContainerInterface $container, $base_plugin_id) {
return new static(
$container->get('form_mode.manager')
$container->get('form_mode.manager'),
$container->get('entity_type.manager'),
$container->get('plugin.manager.entity_routing_map')
);
}
......@@ -53,6 +78,8 @@ class FormModeManagerLocalAction extends DeriverBase implements ContainerDeriver
$this->setDefaultLocalTask($form_mode, $entity_type_id, $form_mode_name);
// @TODO Use EntityRoutingMap to retrieve route_name,
// of admin_create operation.
if ($this->isUserEntityType($entity_type_id)) {
$this->derivatives[$form_mode['id']]['route_name'] = "user.admin_create.$form_mode_name";
unset($this->derivatives[$form_mode['id']]['route_parameters']);
......@@ -79,18 +106,29 @@ class FormModeManagerLocalAction extends DeriverBase implements ContainerDeriver
* An entity type id.
* @param string $form_mode_name
* A form mode name.
*
* @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
*/
public function setDefaultLocalTask(array $form_mode, $entity_type_id, $form_mode_name) {
$entity_storage = $this->entityTypeManager->getStorage($entity_type_id);
$this->derivatives[$form_mode['id']] = [
'route_name' => "form_mode_manager.$entity_type_id.add_page.$form_mode_name",
'title' => $this->t('Add @entity_label as @form_mode', [
'@form_mode' => $form_mode['label'],
'@entity_label' => $entity_type_id,
'@entity_label' => strtolower($entity_storage->getEntityType()->getLabel()),
]),
'route_parameters' => ['form_mode_name' => $form_mode_name],
// @TODO Use EntityRoutingMap to retrieve generic appears_on.
'appears_on' => ["entity.{$entity_type_id}.collection"],
'cache_tags' => $this->formModeManager->getListCacheTags(),
];
// In unbundled entity we change route to directly use add_form.
if (empty($entity_storage->getEntityType()->getKey('bundle'))) {
$entity_routes_infos = $this->entityRoutingMap->createInstance($entity_type_id, ['entityTypeId' => $entity_type_id])->getPluginDefinition();
$this->derivatives[$form_mode['id']]['route_name'] = $entity_routes_infos['operations']['add_form'] . ".$form_mode_name";
unset($this->derivatives[$form_mode['id']]['route_parameters']);
}
}
/**
......@@ -113,6 +151,8 @@ class FormModeManagerLocalAction extends DeriverBase implements ContainerDeriver
* A form mode.
* @param string $entity_type_id
* An entity type id.
*
* @TODO Use EntityRoutingMap to retrieve appears_on.
*/
public function setNodeEntityType(array $form_mode, $entity_type_id) {
if ('node' === $entity_type_id) {
......@@ -127,6 +167,8 @@ class FormModeManagerLocalAction extends DeriverBase implements ContainerDeriver
* A form mode.
* @param string $entity_type_id
* An entity type id.
*
* @TODO Use EntityRoutingMap to retrieve appears_on.
*/
public function setMediaEntityType(array $form_mode, $entity_type_id) {
if ('media' === $entity_type_id) {
......@@ -141,6 +183,8 @@ class FormModeManagerLocalAction extends DeriverBase implements ContainerDeriver
* A form mode.
* @param string $entity_type_id
* An entity type id.
*
* @TODO Use EntityRoutingMap to retrieve appears_on.
*/
public function setTaxonomyTermEntityType(array $form_mode, $entity_type_id) {
if ('taxonomy_term' === $entity_type_id) {
......
......@@ -92,6 +92,9 @@ class FormModeManagerLocalTasks extends DeriverBase implements ContainerDeriverI
* The definition of block_content tasks.
* @param bool $is_default_task
* Determine context of tasks (defaults or form mode manager) derivative.
*
* @TODO Use EntityRoutingMap to format an entity generic route_name.
* @TODO Use EntityRoutingMap to retrieve parent_id route_name.
*/
private function blockContentEnhancer($element_name, $entity_type_id, $is_default_task = TRUE) {
if ('block_content' === $entity_type_id) {
......@@ -108,6 +111,9 @@ class FormModeManagerLocalTasks extends DeriverBase implements ContainerDeriverI
*
* @param string $entity_type_id
* The entity type ID.
*
* @TODO Use EntityRoutingMap to format an entity generic route_name.
* @TODO Use EntityRoutingMap to retrieve parent_id route_name.
*/
private function setDefaultTasks($entity_type_id) {
$this->derivatives["form_mode_manager.$entity_type_id.default.task_tab"] = [
......@@ -152,6 +158,10 @@ class FormModeManagerLocalTasks extends DeriverBase implements ContainerDeriverI
* An associative array represent a DisplayForm entity.
* @param string $entity_type_id
* The entity type ID.
*
* @TODO Use EntityRoutingMap to format an entity generic route_name.
* @TODO Use EntityRoutingMap to retrieve base_route.
* @TODO Make this part more generic now.
*/
private function setUserRegisterTasks(array $form_mode, $entity_type_id) {
if ('user' === $entity_type_id) {
......@@ -170,6 +180,9 @@ class FormModeManagerLocalTasks extends DeriverBase implements ContainerDeriverI
* An associative array represent a DisplayForm entity.
* @param string $entity_type_id
* The entity type ID.
*
* @TODO Use EntityRoutingMap to format an entity generic route_name.
* @TODO Use EntityRoutingMap to retrieve parent_id route_name.
*/
private function setFormModesTasksBase(array $form_mode, $entity_type_id) {
$this->derivatives["form_mode_manager.{$form_mode['id']}.task_tab"] = [
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment