Commit fe61b43d authored by alexpott's avatar alexpott

Issue #2183923 by tim.plunkett: Break the circular dependency in EntityManager.

parent 1939de98
......@@ -188,6 +188,9 @@ services:
entity.manager:
class: Drupal\Core\Entity\EntityManager
arguments: ['@container.namespaces', '@service_container', '@module_handler', '@cache.cache', '@language_manager', '@string_translation']
entity.form_builder:
class: Drupal\Core\Entity\EntityFormBuilder
arguments: ['@entity.manager', '@form_builder']
plugin.manager.field.field_type:
class: Drupal\Core\Field\FieldTypePluginManager
arguments: ['@container.namespaces', '@cache.field', '@language_manager', '@module_handler']
......
......@@ -442,31 +442,6 @@ function entity_access_controller($entity_type) {
->getAccessController($entity_type);
}
/**
* Returns the built and processed entity form for the given entity.
*
* @param \Drupal\Core\Entity\EntityInterface $entity
* The entity to be created or edited.
* @param string $operation
* (optional) The operation identifying the form variation to be returned.
* @param array $form_state
* (optional) An associative array containing the current state of the form.
* Use this to pass additional information to the form, such as the langcode.
* @code
* $form_state['langcode'] = $langcode;
* $form = entity_get_form($entity, 'default', $form_state);
* @endcode
*
* @return array
* The processed form for the given entity and operation.
*
* @deprecated Use \Drupal::entityManager()->getForm() or _entity_form from a
* routing.yml file instead of a page callback.
*/
function entity_get_form(EntityInterface $entity, $operation = 'default', array $form_state = array()) {
return \Drupal::entityManager()->getForm($entity, $operation, $form_state);
}
/**
* Returns an entity list controller for a given entity type.
*
......
......@@ -39,6 +39,13 @@ abstract class ControllerBase implements ContainerInjectionInterface {
*/
protected $entityManager;
/**
* The entity form builder.
*
* @var \Drupal\Core\Entity\EntityFormBuilderInterface
*/
protected $entityFormBuilder;
/**
* The language manager.
*
......@@ -122,6 +129,19 @@ protected function entityManager() {
return $this->entityManager;
}
/**
* Retrieves the entity form builder.
*
* @return \Drupal\Core\Entity\EntityFormBuilderInterface
* The entity form builder.
*/
protected function entityFormBuilder() {
if (!$this->entityFormBuilder) {
$this->entityFormBuilder = $this->container()->get('entity.form_builder');
}
return $this->entityFormBuilder;
}
/**
* Returns the requested cache bin.
*
......
<?php
/**
* @file
* Contains \Drupal\Core\Entity\EntityFormBuilder.
*/
namespace Drupal\Core\Entity;
use Drupal\Core\Form\FormBuilderInterface;
/**
* Builds entity forms.
*/
class EntityFormBuilder implements EntityFormBuilderInterface {
/**
* The entity manager.
*
* @var \Drupal\Core\Entity\EntityManagerInterface
*/
protected $entityManager;
/**
* The form builder.
*
* @var \Drupal\Core\Form\FormBuilderInterface
*/
protected $formBuilder;
/**
* Constructs a new EntityFormBuilder.
*
* @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
* The entity manager.
* @param \Drupal\Core\Form\FormBuilderInterface $form_builder
* The form builder.
*/
public function __construct(EntityManagerInterface $entity_manager, FormBuilderInterface $form_builder) {
$this->entityManager = $entity_manager;
$this->formBuilder = $form_builder;
}
/**
* {@inheritdoc}
*/
public function getForm(EntityInterface $entity, $operation = 'default', array $form_state = array()) {
$controller = $this->entityManager->getFormController($entity->getEntityTypeId(), $operation);
$controller->setEntity($entity);
$form_state['build_info']['callback_object'] = $controller;
$form_state['build_info']['base_form_id'] = $controller->getBaseFormID();
$form_state['build_info'] += array('args' => array());
return $this->formBuilder->buildForm($controller->getFormId(), $form_state);
}
}
<?php
/**
* @file
* Contains \Drupal\Core\Entity\EntityFormBuilderInterface.
*/
namespace Drupal\Core\Entity;
/**
* Builds entity forms.
*/
interface EntityFormBuilderInterface {
/**
* Returns the built and processed entity form for the given entity.
*
* @param \Drupal\Core\Entity\EntityInterface $entity
* The entity to be created or edited.
* @param string $operation
* (optional) The operation identifying the form variation to be returned.
* Defaults to 'default'.
* @param array $form_state
* (optional) An associative array containing the current state of the form.
* Use this to pass additional information to the form, such as the
* langcode. Defaults to an empty array.
*
* @code
* $form_state['langcode'] = $langcode;
* $form = \Drupal::service('entity.form_builder')->getForm($entity, 'default', $form_state);
* @endcode
*
* @return array
* The processed form for the given entity and operation.
*/
public function getForm(EntityInterface $entity, $operation = 'default', array $form_state = array());
}
......@@ -279,22 +279,6 @@ public function getController($entity_type, $controller_type, $controller_class_
return $this->controllers[$controller_type][$entity_type];
}
/**
* {@inheritdoc}
*/
public function getForm(EntityInterface $entity, $operation = 'default', array $form_state = array()) {
$form_state['build_info'] = isset($form_state['build_info']) ? $form_state['build_info'] : array();
$controller = $this->getFormController($entity->getEntityTypeId(), $operation);
$controller->setEntity($entity);
$form_state['build_info'] += array(
'callback_object' => $controller,
'base_form_id' => $controller->getBaseFormID(),
'args' => array(),
);
$form_id = $controller->getFormID();
return \Drupal::formBuilder()->buildForm($form_id, $form_state);
}
/**
* {@inheritdoc}
*/
......
......@@ -185,30 +185,6 @@ public function hasController($entity_type, $controller_type);
*/
public function getController($entity_type, $controller_type);
/**
* Returns the built and processed entity form for the given entity.
*
* @param \Drupal\Core\Entity\EntityInterface $entity
* The entity to be created or edited.
* @param string $operation
* (optional) The operation identifying the form variation to be returned.
* Defaults to 'default'.
* @param array $form_state
* (optional) An associative array containing the current state of the form.
* Use this to pass additional information to the form, such as the
* langcode. Defaults to an empty array.
*
* @code
* $form_state['langcode'] = $langcode;
* $manager = \Drupal::entityManager();
* $form = $manager->getForm($entity, 'default', $form_state);
* @endcode
*
* @return array
* The processed form for the given entity and operation.
*/
public function getForm(EntityInterface $entity, $operation = 'default', array $form_state = array());
/**
* Get the bundle info of an entity type.
*
......
......@@ -55,12 +55,11 @@ public static function create(ContainerInterface $container) {
* A form array as expected by drupal_render().
*/
public function feedAdd() {
$entity_manager = $this->entityManager();
$feed = $entity_manager->getStorageController('aggregator_feed')
$feed = $this->entityManager()->getStorageController('aggregator_feed')
->create(array(
'refresh' => 3600,
));
return $entity_manager->getForm($feed);
return $this->entityFormBuilder()->getForm($feed);
}
/**
......
......@@ -16,13 +16,6 @@
class CustomBlockController extends ControllerBase {
/**
* The entity manager.
*
* @var \Drupal\Component\Plugin\PluginManagerInterface
*/
protected $entityManager;
/**
* The custom block storage controller.
*
......@@ -43,7 +36,6 @@ class CustomBlockController extends ControllerBase {
public static function create(ContainerInterface $container) {
$entity_manager = $container->get('entity.manager');
return new static(
$entity_manager,
$entity_manager->getStorageController('custom_block'),
$entity_manager->getStorageController('custom_block_type')
);
......@@ -52,17 +44,14 @@ public static function create(ContainerInterface $container) {
/**
* Constructs a CustomBlock object.
*
* @param \Drupal\Component\Plugin\PluginManagerInterface $entity_manager
* The entity manager.
* @param \Drupal\Core\Entity\EntityStorageControllerInterface $custom_block_storage
* The custom block storage controller.
* @param \Drupal\Core\Entity\EntityStorageControllerInterface $custom_block_type_storage
* The custom block type storage controller.
*/
public function __construct(PluginManagerInterface $entity_manager, EntityStorageControllerInterface $custom_block_storage, EntityStorageControllerInterface $custom_block_type_storage) {
public function __construct(EntityStorageControllerInterface $custom_block_storage, EntityStorageControllerInterface $custom_block_type_storage) {
$this->customBlockStorage = $custom_block_storage;
$this->customBlockTypeStorage = $custom_block_type_storage;
$this->entityManager = $entity_manager;
}
/**
......@@ -107,7 +96,7 @@ public function addForm(CustomBlockTypeInterface $custom_block_type, Request $re
// newly created block in the given theme.
$block->setTheme($theme);
}
return $this->entityManager->getForm($block);
return $this->entityFormBuilder()->getForm($block);
}
/**
......
......@@ -30,7 +30,7 @@ public function blockAddConfigureForm($plugin_id, $theme) {
// Create a block entity.
$entity = $this->entityManager()->getStorageController('block')->create(array('plugin' => $plugin_id, 'theme' => $theme));
return $this->entityManager()->getForm($entity);
return $this->entityFormBuilder()->getForm($entity);
}
}
......@@ -603,7 +603,7 @@ function comment_add(EntityInterface $entity, $field_name = 'comment', $pid = NU
'pid' => $pid,
);
$comment = entity_create('comment', $values);
return \Drupal::entityManager()->getForm($comment);
return \Drupal::service('entity.form_builder')->getForm($comment);
}
/**
......
......@@ -270,7 +270,7 @@ public function getReplyForm(Request $request, $entity_type, $entity_id, $field_
'entity_type' => $entity->getEntityTypeId(),
'field_id' => $entity->getEntityTypeId() . '__' . $field_name,
));
$build['comment_form'] = $this->entityManager()->getForm($comment);
$build['comment_form'] = $this->entityFormBuilder()->getForm($comment);
return $build;
}
......
......@@ -28,7 +28,7 @@ class ConfigTestController extends ControllerBase {
* A form array as expected by drupal_render().
*/
public function edit(ConfigTest $config_test) {
$form = $this->entityManager()->getForm($config_test);
$form = $this->entityFormBuilder()->getForm($config_test);
$form['#title'] = String::format('Edit %label', array('%label' => $config_test->label()));
return $form;
}
......
......@@ -90,7 +90,7 @@ public function contactSitePage(CategoryInterface $contact_category = NULL) {
'category' => $contact_category->id(),
));
$form = $this->entityManager()->getForm($message);
$form = $this->entityFormBuilder()->getForm($message);
$form['#title'] = String::checkPlain($contact_category->label());
return $form;
}
......@@ -115,7 +115,7 @@ public function contactPersonalPage(UserInterface $user) {
'recipient' => $user->id(),
));
$form = $this->entityManager()->getForm($message);
$form = $this->entityFormBuilder()->getForm($message);
$form['#title'] = $this->t('Contact @username', array('@username' => $user->getUsername()));
return $form;
}
......
......@@ -189,7 +189,7 @@ function content_translation_add_page(EntityInterface $entity, Language $source
$form_state['content_translation']['source'] = $source;
$form_state['content_translation']['target'] = $target;
$form_state['content_translation']['translation_form'] = !$entity->access('update');
return \Drupal::entityManager()->getForm($entity, 'default', $form_state);
return \Drupal::service('entity.form_builder')->getForm($entity, 'default', $form_state);
}
/**
......@@ -210,7 +210,7 @@ function content_translation_edit_page(EntityInterface $entity, Language $langua
$language = !empty($language) ? $language : language(Language::TYPE_CONTENT);
$form_state['langcode'] = $language->id;
$form_state['content_translation']['translation_form'] = TRUE;
return \Drupal::entityManager()->getForm($entity, 'default', $form_state);
return \Drupal::service('entity.form_builder')->getForm($entity, 'default', $form_state);
}
/**
......
......@@ -157,7 +157,7 @@ public function addForum() {
'vid' => $vid,
'forum_controller' => 0,
));
return $this->entityManager()->getForm($taxonomy_term, 'forum');
return $this->entityFormBuilder()->getForm($taxonomy_term, 'forum');
}
/**
......@@ -172,7 +172,7 @@ public function addContainer() {
'vid' => $vid,
'forum_container' => 1,
));
return $this->entityManager()->getForm($taxonomy_term, 'container');
return $this->entityFormBuilder()->getForm($taxonomy_term, 'container');
}
}
......@@ -54,7 +54,7 @@ public function addLink(MenuInterface $menu) {
'plid' => 0,
'menu_name' => $menu->id(),
));
return $this->entityManager()->getForm($menu_link);
return $this->entityFormBuilder()->getForm($menu_link);
}
/**
......
......@@ -72,7 +72,7 @@ public function add(NodeTypeInterface $node_type) {
'langcode' => $langcode ? $langcode : $this->languageManager()->getCurrentLanguage()->id,
));
$form = $this->entityManager()->getForm($node);
$form = $this->entityFormBuilder()->getForm($node);
return $form;
}
......
......@@ -35,7 +35,7 @@ public static function getInfo() {
function testUpdateAllowedValues() {
// All three options appear.
$entity = entity_create('entity_test');
$form = \Drupal::entityManager()->getForm($entity);
$form = \Drupal::service('entity.form_builder')->getForm($entity);
$this->assertTrue(!empty($form[$this->fieldName]['widget'][1]), 'Option 1 exists');
$this->assertTrue(!empty($form[$this->fieldName]['widget'][2]), 'Option 2 exists');
$this->assertTrue(!empty($form[$this->fieldName]['widget'][3]), 'Option 3 exists');
......@@ -61,7 +61,7 @@ function testUpdateAllowedValues() {
$this->field->settings['allowed_values'] = array(2 => 'Two');
$this->field->save();
$entity = entity_create('entity_test');
$form = \Drupal::entityManager()->getForm($entity);
$form = \Drupal::service('entity.form_builder')->getForm($entity);
$this->assertTrue(empty($form[$this->fieldName]['widget'][1]), 'Option 1 does not exist');
$this->assertTrue(!empty($form[$this->fieldName]['widget'][2]), 'Option 2 exists');
$this->assertTrue(empty($form[$this->fieldName]['widget'][3]), 'Option 3 does not exist');
......@@ -72,7 +72,7 @@ function testUpdateAllowedValues() {
// The entity holds an outdated field object with the old allowed values
// setting, so we need to reintialize the entity object.
$entity = entity_create('entity_test');
$form = \Drupal::entityManager()->getForm($entity);
$form = \Drupal::service('entity.form_builder')->getForm($entity);
$this->assertTrue(empty($form[$this->fieldName]['widget'][1]), 'Option 1 does not exist');
$this->assertTrue(empty($form[$this->fieldName]['widget'][2]), 'Option 2 does not exist');
$this->assertTrue(empty($form[$this->fieldName]['widget'][3]), 'Option 3 does not exist');
......@@ -93,7 +93,7 @@ function testUpdateAllowedValues() {
))
->save();
$entity = entity_create('entity_test');
$form = \Drupal::entityManager()->getForm($entity);
$form = \Drupal::service('entity.form_builder')->getForm($entity);
$this->assertTrue(!empty($form[$this->fieldName]['widget'][1]), 'Option 1 exists');
$this->assertTrue(!empty($form[$this->fieldName]['widget'][2]), 'Option 2 exists');
$this->assertTrue(!empty($form[$this->fieldName]['widget'][3]), 'Option 3 exists');
......
......@@ -87,7 +87,7 @@ public function view(Request $request, SearchPageInterface $entity, $keys = '')
}
}
// The form may be altered based on whether the search was run.
$build['search_form'] = $this->entityManager()->getForm($entity, 'search');
$build['search_form'] = $this->entityFormBuilder()->getForm($entity, 'search');
$build['search_results'] = $results;
return $build;
}
......
......@@ -31,7 +31,7 @@ public function addForm(ShortcutSetInterface $shortcut_set) {
if ($this->moduleHandler()->moduleExists('language')) {
$shortcut->langcode = language_get_default_langcode('shortcut', $shortcut_set->id());
}
return $this->entityManager()->getForm($shortcut, 'add');
return $this->entityFormBuilder()->getForm($shortcut, 'add');
}
}
......@@ -78,7 +78,7 @@ function testEntityFormLanguage() {
// Explicitly set form langcode.
$langcode = $this->langcodes[0];
$form_state['langcode'] = $langcode;
\Drupal::entityManager()->getForm($node, 'default', $form_state);
\Drupal::service('entity.form_builder')->getForm($node, 'default', $form_state);
$form_langcode = \Drupal::state()->get('entity_test.form_langcode') ?: FALSE;
$this->assertTrue($langcode == $form_langcode, 'Form language is the same as the language parameter.');
......
......@@ -287,7 +287,7 @@ function entity_test_form_node_form_alter(&$form, &$form_state, $form_id) {
function entity_test_add($entity_type) {
drupal_set_title(t('Create an @type', array('@type' => $entity_type)));
$entity = entity_create($entity_type);
return \Drupal::entityManager()->getForm($entity);
return \Drupal::service('entity.form_builder')->getForm($entity);
}
/**
......@@ -305,7 +305,7 @@ function entity_test_add($entity_type) {
*/
function entity_test_edit(EntityInterface $entity) {
drupal_set_title($entity->label(), PASS_THROUGH);
return \Drupal::entityManager()->getForm($entity);
return \Drupal::service('entity.form_builder')->getForm($entity);
}
/**
......
......@@ -30,8 +30,8 @@ public function twoFormInstances() {
);
$node1 = $this->entityManager()->getStorageController('node')->create($values);
$node2 = clone($node1);
$return['node_form_1'] = $this->entityManager()->getForm($node1);
$return['node_form_2'] = $this->entityManager()->getForm($node2);
$return['node_form_1'] = $this->entityFormBuilder()->getForm($node1);
$return['node_form_2'] = $this->entityFormBuilder()->getForm($node2);
return $return;
}
......
......@@ -32,7 +32,7 @@ public function addForm(VocabularyInterface $taxonomy_vocabulary) {
if ($this->moduleHandler()->moduleExists('language')) {
$term->langcode = language_get_default_langcode('taxonomy_term', $taxonomy_vocabulary->id());
}
return $this->entityManager()->getForm($term);
return $this->entityFormBuilder()->getForm($term);
}
/**
......
......@@ -8,7 +8,6 @@
namespace Drupal\views_ui\Controller;
use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\Entity\EntityManagerInterface;
use Drupal\views\ViewExecutable;
use Drupal\views\ViewStorageInterface;
use Drupal\views_ui\ViewUI;
......@@ -24,13 +23,6 @@
*/
class ViewsUIController extends ControllerBase {
/**
* Stores the Entity manager.
*
* @var \Drupal\Core\Entity\EntityManagerInterface
*/
protected $entityManager;
/**
* Stores the Views data cache object.
*
......@@ -41,13 +33,10 @@ class ViewsUIController extends ControllerBase {
/**
* Constructs a new \Drupal\views_ui\Controller\ViewsUIController object.
*
* @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
* The Entity manager.
* @param \Drupal\views\ViewsData views_data
* The Views data cache object.
*/
public function __construct(EntityManagerInterface $entity_manager, ViewsData $views_data) {
$this->entityManager = $entity_manager;
public function __construct(ViewsData $views_data) {
$this->viewsData = $views_data;
}
......@@ -56,7 +45,6 @@ public function __construct(EntityManagerInterface $entity_manager, ViewsData $v
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('entity.manager'),
$container->get('views.views_data')
);
}
......@@ -68,7 +56,7 @@ public static function create(ContainerInterface $container) {
* The Views fields report page.
*/
public function reportFields() {
$views = $this->entityManager->getStorageController('view')->loadMultiple();
$views = $this->entityManager()->getStorageController('view')->loadMultiple();
// Fetch all fieldapi fields which are used in views
// Therefore search in all views, displays and handler-types.
......@@ -164,7 +152,7 @@ public function ajaxOperation(ViewStorageInterface $view, $op, Request $request)
// If the request is via AJAX, return the rendered list as JSON.
if ($request->request->get('js')) {
$list = $this->entityManager->getListController('view')->render();
$list = $this->entityManager()->getListController('view')->render();
$response = new AjaxResponse();
$response->addCommand(new ReplaceCommand('#views-entity-list', drupal_render($list)));
return $response;
......@@ -187,7 +175,7 @@ public function autocompleteTag(Request $request) {
$matches = array();
$string = $request->query->get('q');
// Get matches from default views.
$views = $this->entityManager->getStorageController('view')->loadMultiple();
$views = $this->entityManager()->getStorageController('view')->loadMultiple();
foreach ($views as $view) {
$tag = $view->get('tag');
if ($tag && strpos($tag, $string) === 0) {
......@@ -222,8 +210,8 @@ public function edit(ViewUI $view, $display_id = NULL) {
}
$build['#title'] = $name;
$build['edit'] = $this->entityManager->getForm($view, 'edit', array('display_id' => $display_id));
$build['preview'] = $this->entityManager->getForm($view, 'preview', array('display_id' => $display_id));
$build['edit'] = $this->entityFormBuilder()->getForm($view, 'edit', array('display_id' => $display_id));
$build['preview'] = $this->entityFormBuilder()->getForm($view, 'preview', array('display_id' => $display_id));
return $build;
}
......
......@@ -64,16 +64,7 @@ protected function setUp() {
$this->cid = $this->randomName();
$this->collector = new CacheCollectorHelper($this->cid, $this->cache, $this->lock);
$container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface');
$container->expects($this->any())
->method('getParameter')
->with('cache_bins')
->will($this->returnValue(array('cache.test' => 'test')));
$container->expects($this->any())
->method('get')
->with('cache.test')
->will($this->returnValue($this->cache));
\Drupal::setContainer($container);
$this->getContainerWithCacheBins($this->cache);
}
......
<?php
namespace Drupal\Tests\Core\Entity;
use Drupal\Core\Entity\EntityFormBuilder;
use Drupal\Tests\UnitTestCase;
/**
* @coversDefaultClass \Drupal\Core\Entity\EntityFormBuilder
*/
class EntityFormBuilderTest extends UnitTestCase {
/**
* The entity manager.
*
* @var \Drupal\Core\Entity\EntityManagerInterface|\PHPUnit_Framework_MockObject_MockObject
*/
protected $entityManager;
/**
* The form builder.
*
* @var \Drupal\Core\Form\FormBuilderInterface|\PHPUnit_Framework_MockObject_MockObject
*/
protected $formBuilder;
/**
* The entity form builder.
*
* @var \Drupal\Core\Entity\EntityFormBuilderInterface
*/
protected $entityFormBuilder;
/**
* {@inheritdoc}
*/
public static function getInfo() {
return array(
'name' => 'Entity Form Builder test',
'description' => 'Unit test the entity form builder.',
'group' => 'Entity',
);
}
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->formBuilder = $this->getMock('Drupal\Core\Form\FormBuilderInterface');
$this->entityManager = $this->getMock('Drupal\Core\Entity\EntityManagerInterface');
$this->entityFormBuilder = new EntityFormBuilder($this->entityManager, $this->formBuilder);
}
/**
* Tests the getForm() method.
*
* @covers ::getForm()
*/
public function testGetForm() {
$this->formBuilder->expects($this->once())
->method('buildForm')
->with('the_form_id', $this->isType('array'))
->will($this->returnValue('the form contents'));
$form_controller = $this->getMock('Drupal\Core\Entity\EntityFormControllerInterface');
$form_controller->expects($this->any())
->method('getFormId')
->will($this->returnValue('the_form_id'));
$this->entityManager->expects($this->any())
->method('getFormController')
->with('the_entity_type', 'default')
->