Issue #2399219 by amateescu: Allow entity form handlers to determine the entity object they need to work with

8.0.x
Alex Pott 2015-01-05 11:50:21 +00:00
parent 28748628b4
commit eb25fabd8f
7 changed files with 104 additions and 43 deletions

View File

@ -10,6 +10,7 @@ namespace Drupal\Core\Controller;
use Drupal\Core\DependencyInjection\DependencySerializationTrait; use Drupal\Core\DependencyInjection\DependencySerializationTrait;
use Drupal\Core\Form\FormBuilderInterface; use Drupal\Core\Form\FormBuilderInterface;
use Drupal\Core\Form\FormState; use Drupal\Core\Form\FormState;
use Drupal\Core\Routing\RouteMatchInterface;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
/** /**
@ -52,13 +53,15 @@ abstract class FormController {
* *
* @param \Symfony\Component\HttpFoundation\Request $request * @param \Symfony\Component\HttpFoundation\Request $request
* The request object. * The request object.
* @param \Drupal\Core\Routing\RouteMatchInterface $route_match
* The route match.
* *
* @return array * @return array
* The render array that results from invoking the controller. * The render array that results from invoking the controller.
*/ */
public function getContentResult(Request $request) { public function getContentResult(Request $request, RouteMatchInterface $route_match) {
$form_arg = $this->getFormArgument($request); $form_arg = $this->getFormArgument($route_match);
$form_object = $this->getFormObject($request, $form_arg); $form_object = $this->getFormObject($route_match, $form_arg);
// Add the form and form_state to trick the getArguments method of the // Add the form and form_state to trick the getArguments method of the
// controller resolver. // controller resolver.
@ -88,25 +91,25 @@ abstract class FormController {
* _form: Drupal\example\Form\ExampleForm * _form: Drupal\example\Form\ExampleForm
* @endcode * @endcode
* *
* @param \Symfony\Component\HttpFoundation\Request $request * @param \Drupal\Core\Routing\RouteMatchInterface $route_match
* The request object from which to extract a form definition string. * The route match object from which to extract a form definition string.
* *
* @return string * @return string
* The form definition string. * The form definition string.
*/ */
abstract protected function getFormArgument(Request $request); abstract protected function getFormArgument(RouteMatchInterface $route_match);
/** /**
* Returns the object used to build the form. * Returns the object used to build the form.
* *
* @param \Symfony\Component\HttpFoundation\Request $request * @param \Drupal\Core\Routing\RouteMatchInterface $route_match
* The request using this form. * The route match.
* @param string $form_arg * @param string $form_arg
* Either a class name or a service ID. * Either a class name or a service ID.
* *
* @return \Drupal\Core\Form\FormInterface * @return \Drupal\Core\Form\FormInterface
* The form object to use. * The form object to use.
*/ */
abstract protected function getFormObject(Request $request, $form_arg); abstract protected function getFormObject(RouteMatchInterface $route_match, $form_arg);
} }

View File

@ -8,7 +8,7 @@
namespace Drupal\Core\Controller; namespace Drupal\Core\Controller;
use Drupal\Core\Form\FormBuilderInterface; use Drupal\Core\Form\FormBuilderInterface;
use Symfony\Component\HttpFoundation\Request; use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\DependencyInjection\ClassResolverInterface; use Drupal\Core\DependencyInjection\ClassResolverInterface;
/** /**
@ -39,24 +39,16 @@ class HtmlFormController extends FormController {
} }
/** /**
* @{inheritDoc} * {@inheritdoc}
*/ */
protected function getFormArgument(Request $request) { protected function getFormArgument(RouteMatchInterface $route_match) {
return $request->attributes->get('_form'); return $route_match->getRouteObject()->getDefault('_form');
} }
/** /**
* Returns the object used to build the form. * {@inheritdoc}
*
* @param \Symfony\Component\HttpFoundation\Request $request
* The request using this form.
* @param string $form_arg
* Either a class name or a service ID.
*
* @return \Drupal\Core\Form\FormInterface
* The form object to use.
*/ */
protected function getFormObject(Request $request, $form_arg) { protected function getFormObject(RouteMatchInterface $route_match, $form_arg) {
return $this->classResolver->getInstanceFromDefinition($form_arg); return $this->classResolver->getInstanceFromDefinition($form_arg);
} }

View File

@ -11,6 +11,7 @@ use Drupal\Core\Form\FormBase;
use Drupal\Core\Extension\ModuleHandlerInterface; use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Render\Element; use Drupal\Core\Render\Element;
use Drupal\Core\Routing\RouteMatchInterface;
/** /**
* Base class for entity forms. * Base class for entity forms.
@ -36,6 +37,13 @@ class EntityForm extends FormBase implements EntityFormInterface {
*/ */
protected $moduleHandler; protected $moduleHandler;
/**
* The entity manager.
*
* @var \Drupal\Core\Entity\EntityManagerInterface
*/
protected $entityManager;
/** /**
* The entity being used by this form. * The entity being used by this form.
* *
@ -321,6 +329,20 @@ class EntityForm extends FormBase implements EntityFormInterface {
return $this; return $this;
} }
/**
* {@inheritdoc}
*/
public function getEntityFromRouteMatch(RouteMatchInterface $route_match, $entity_type_id) {
if ($route_match->getRawParameter($entity_type_id) !== NULL) {
$entity = $route_match->getParameter($entity_type_id);
}
else {
$entity = $this->entityManager->getStorage($entity_type_id)->create([]);
}
return $entity;
}
/** /**
* Prepares the entity object before the form is built first. * Prepares the entity object before the form is built first.
*/ */
@ -362,4 +384,12 @@ class EntityForm extends FormBase implements EntityFormInterface {
return $this; return $this;
} }
/**
* {@inheritdoc}
*/
public function setEntityManager(EntityManagerInterface $entity_manager) {
$this->entityManager = $entity_manager;
return $this;
}
} }

View File

@ -10,6 +10,7 @@ namespace Drupal\Core\Entity;
use Drupal\Core\Extension\ModuleHandlerInterface; use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Form\BaseFormIdInterface; use Drupal\Core\Form\BaseFormIdInterface;
use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\StringTranslation\TranslationInterface; use Drupal\Core\StringTranslation\TranslationInterface;
/** /**
@ -40,9 +41,6 @@ interface EntityFormInterface extends BaseFormIdInterface {
* *
* The form entity which has been used for populating form element defaults. * The form entity which has been used for populating form element defaults.
* *
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The current state of the form.
*
* @return \Drupal\Core\Entity\EntityInterface * @return \Drupal\Core\Entity\EntityInterface
* The current form entity. * The current form entity.
*/ */
@ -64,6 +62,19 @@ interface EntityFormInterface extends BaseFormIdInterface {
*/ */
public function setEntity(EntityInterface $entity); public function setEntity(EntityInterface $entity);
/**
* Determines which entity will be used by this form from a RouteMatch object.
*
* @param \Drupal\Core\Routing\RouteMatchInterface $route_match
* The route match.
* @param string $entity_type_id
* The entity type identifier.
*
* @return \Drupal\Core\Entity\EntityInterface
* The entity object as determined from the passed-in route match.
*/
public function getEntityFromRouteMatch(RouteMatchInterface $route_match, $entity_type_id);
/** /**
* Builds an updated entity object based upon the submitted form values. * Builds an updated entity object based upon the submitted form values.
* *
@ -129,4 +140,14 @@ interface EntityFormInterface extends BaseFormIdInterface {
*/ */
public function setModuleHandler(ModuleHandlerInterface $module_handler); public function setModuleHandler(ModuleHandlerInterface $module_handler);
/**
* Sets the entity manager for this form.
*
* @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
* The entity manager.
*
* @return $this
*/
public function setEntityManager(EntityManagerInterface $entity_manager);
} }

View File

@ -294,6 +294,7 @@ class EntityManager extends DefaultPluginManager implements EntityManagerInterfa
$form_object $form_object
->setStringTranslation($this->translationManager) ->setStringTranslation($this->translationManager)
->setModuleHandler($this->moduleHandler) ->setModuleHandler($this->moduleHandler)
->setEntityManager($this)
->setOperation($operation); ->setOperation($operation);
$this->handlers['form'][$operation][$entity_type] = $form_object; $this->handlers['form'][$operation][$entity_type] = $form_object;
} }

View File

@ -10,7 +10,7 @@ namespace Drupal\Core\Entity;
use Drupal\Core\Controller\ControllerResolverInterface; use Drupal\Core\Controller\ControllerResolverInterface;
use Drupal\Core\Controller\FormController; use Drupal\Core\Controller\FormController;
use Drupal\Core\Form\FormBuilderInterface; use Drupal\Core\Form\FormBuilderInterface;
use Symfony\Component\HttpFoundation\Request; use Drupal\Core\Routing\RouteMatchInterface;
/** /**
* Wrapping controller for entity forms that serve as the main page body. * Wrapping controller for entity forms that serve as the main page body.
@ -22,7 +22,7 @@ class HtmlEntityFormController extends FormController {
* *
* @var \Drupal\Core\Entity\EntityManagerInterface * @var \Drupal\Core\Entity\EntityManagerInterface
*/ */
protected $manager; protected $entityManager;
/** /**
* Constructs a new \Drupal\Core\Routing\Enhancer\FormEnhancer object. * Constructs a new \Drupal\Core\Routing\Enhancer\FormEnhancer object.
@ -36,14 +36,14 @@ class HtmlEntityFormController extends FormController {
*/ */
public function __construct(ControllerResolverInterface $resolver, FormBuilderInterface $form_builder, EntityManagerInterface $manager) { public function __construct(ControllerResolverInterface $resolver, FormBuilderInterface $form_builder, EntityManagerInterface $manager) {
parent::__construct($resolver, $form_builder); parent::__construct($resolver, $form_builder);
$this->manager = $manager; $this->entityManager = $manager;
} }
/** /**
* @{inheritDoc} * {@inheritdoc}
*/ */
protected function getFormArgument(Request $request) { protected function getFormArgument(RouteMatchInterface $route_match) {
return $request->attributes->get('_entity_form'); return $route_match->getRouteObject()->getDefault('_entity_form');
} }
/** /**
@ -66,19 +66,19 @@ class HtmlEntityFormController extends FormController {
* _entity_form: 'node' * _entity_form: 'node'
* @endcode * @endcode
*/ */
protected function getFormObject(Request $request, $form_arg) { protected function getFormObject(RouteMatchInterface $route_match, $form_arg) {
// If no operation is provided, use 'default'. // If no operation is provided, use 'default'.
$form_arg .= '.default'; $form_arg .= '.default';
list ($entity_type, $operation) = explode('.', $form_arg); list ($entity_type_id, $operation) = explode('.', $form_arg);
if ($request->attributes->has($entity_type)) { $form_object = $this->entityManager->getFormObject($entity_type_id, $operation);
$entity = $request->attributes->get($entity_type);
}
else {
$entity = $this->manager->getStorage($entity_type)->create([]);
}
return $this->manager->getFormObject($entity_type, $operation)->setEntity($entity); // Allow the entity form to determine the entity object from a given route
// match.
$entity = $form_object->getEntityFromRouteMatch($route_match, $entity_type_id);
$form_object->setEntity($entity);
return $form_object;
} }
} }

View File

@ -10,14 +10,13 @@ namespace Drupal\Tests\Core\Entity {
use Drupal\Component\Plugin\Discovery\DiscoveryInterface; use Drupal\Component\Plugin\Discovery\DiscoveryInterface;
use Drupal\Component\Plugin\Exception\PluginNotFoundException; use Drupal\Component\Plugin\Exception\PluginNotFoundException;
use Drupal\Core\Config\Entity\ConfigEntityStorage; use Drupal\Core\Config\Entity\ConfigEntityStorage;
use Drupal\Core\DependencyInjection\ContainerBuilder;
use Drupal\Core\DependencyInjection\ContainerInjectionInterface; use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
use Drupal\Core\Entity\ContentEntityBase;
use Drupal\Core\Entity\ContentEntityInterface; use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\Core\Entity\EntityHandlerBase; use Drupal\Core\Entity\EntityHandlerBase;
use Drupal\Core\Entity\EntityHandlerInterface; use Drupal\Core\Entity\EntityHandlerInterface;
use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityManager; use Drupal\Core\Entity\EntityManager;
use Drupal\Core\Entity\EntityManagerInterface;
use Drupal\Core\Entity\EntityTypeInterface; use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Language\Language; use Drupal\Core\Language\Language;
use Drupal\Core\Language\LanguageInterface; use Drupal\Core\Language\LanguageInterface;
@ -1503,6 +1502,13 @@ class TestEntityHandlerInjected implements EntityHandlerInterface {
*/ */
class TestEntityForm extends EntityHandlerBase { class TestEntityForm extends EntityHandlerBase {
/**
* The entity manager.
*
* @var \Drupal\Tests\Core\Entity\TestEntityManager
*/
protected $entityManager;
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
@ -1531,6 +1537,14 @@ class TestEntityForm extends EntityHandlerBase {
return $this; return $this;
} }
/**
* {@inheritdoc}
*/
public function setEntityManager(EntityManagerInterface $entity_manager) {
$this->entityManager = $entity_manager;
return $this;
}
} }
/** /**