diff --git a/core/includes/menu.inc b/core/includes/menu.inc index e59615c..485bca9 100644 --- a/core/includes/menu.inc +++ b/core/includes/menu.inc @@ -2744,7 +2744,7 @@ function _menu_navigation_links_rebuild($menu) { else { // The Menu link module is not available at install time, so we need to // hardcode the default storage controller. - $menu_link_controller = new MenuLinkStorageController('menu_link'); + $menu_link_controller = new MenuLinkStorageController('menu_link', Drupal::service('database')); } // Add normal and suggested items as links. diff --git a/core/lib/Drupal/Core/CoreBundle.php b/core/lib/Drupal/Core/CoreBundle.php index ee63bfa..4dc1e80 100644 --- a/core/lib/Drupal/Core/CoreBundle.php +++ b/core/lib/Drupal/Core/CoreBundle.php @@ -152,7 +152,8 @@ public function build(ContainerBuilder $container) { // Register the EntityManager. $container->register('plugin.manager.entity', 'Drupal\Core\Entity\EntityManager') - ->addArgument('%container.namespaces%'); + ->addArgument('%container.namespaces%') + ->addArgument(new Reference('service_container')); // The 'request' scope and service enable services to depend on the Request // object and get reconstructed when the request object changes (e.g., diff --git a/core/lib/Drupal/Core/Entity/DatabaseStorageController.php b/core/lib/Drupal/Core/Entity/DatabaseStorageController.php index e57f4bb..02619c2 100644 --- a/core/lib/Drupal/Core/Entity/DatabaseStorageController.php +++ b/core/lib/Drupal/Core/Entity/DatabaseStorageController.php @@ -11,7 +11,10 @@ use Drupal\Core\Entity\Query\QueryInterface; use Drupal\Component\Uuid\Uuid; use Drupal\Component\Utility\NestedArray; +use Drupal\Core\Database\Connection; +use Drupal\Core\Entity\EntityHandlerInterface; +use Symfony\Component\DependencyInjection\ContainerInterface; /** * Defines a base entity controller class. @@ -21,7 +24,7 @@ * This class can be used as-is by most simple entity types. Entity types * requiring special handling can extend the class. */ -class DatabaseStorageController implements EntityStorageControllerInterface { +class DatabaseStorageController implements EntityStorageControllerInterface, EntityHandlerInterface{ /** * Static cache of entities. @@ -112,14 +115,33 @@ class DatabaseStorageController implements EntityStorageControllerInterface { */ protected $cache; + /** + * Active database connection. + * + * @var \Drupal\Core\Database\Connection + */ + protected $database; + + /** + * Implements \Drupal\Core\Entity\EntityHandlerInterface::createInstance(). + */ + public static function createInstance(ContainerInterface $container, array $arguments) { + return new static( + $arguments['entity_type'], + $container->get('database') + ); + } /** * Constructs a DatabaseStorageController object. * * @param string $entityType * The entity type for which the instance is created. + * @param \Drupal\Core\Database\Connection $database + * The database connection to be used. */ - public function __construct($entityType) { + public function __construct($entityType, Connection $database) { + $this->database = $database; $this->entityType = $entityType; $this->entityInfo = entity_get_info($entityType); $this->entityCache = array(); @@ -278,7 +300,7 @@ public function deleteRevision($revision_id) { throw new EntityStorageException('Default revision can not be deleted'); } - db_delete($this->revisionTable) + $this->database->delete($this->revisionTable) ->condition($this->revisionKey, $revision->getRevisionId()) ->execute(); $this->invokeHook('revision_delete', $revision); @@ -332,7 +354,7 @@ protected function buildPropertyQuery(QueryInterface $entity_query, array $value * A SelectQuery object for loading the entity. */ protected function buildQuery($ids, $revision_id = FALSE) { - $query = db_select($this->entityInfo['base_table'], 'base'); + $query = $this->database->select($this->entityInfo['base_table'], 'base'); $query->addTag($this->entityType . '_load_multiple'); @@ -474,7 +496,7 @@ public function delete(array $entities) { // If no IDs or invalid IDs were passed, do nothing. return; } - $transaction = db_transaction(); + $transaction = $this->database->startTransaction(); try { $this->preDelete($entities); @@ -483,12 +505,12 @@ public function delete(array $entities) { } $ids = array_keys($entities); - db_delete($this->entityInfo['base_table']) + $this->database->delete($this->entityInfo['base_table']) ->condition($this->idKey, $ids, 'IN') ->execute(); if ($this->revisionKey) { - db_delete($this->revisionTable) + $this->database->delete($this->revisionTable) ->condition($this->idKey, $ids, 'IN') ->execute(); } @@ -514,7 +536,7 @@ public function delete(array $entities) { * Implements \Drupal\Core\Entity\EntityStorageControllerInterface::save(). */ public function save(EntityInterface $entity) { - $transaction = db_transaction(); + $transaction = $this->database->startTransaction(); try { // Load the stored entity, if any. if (!$entity->isNew() && !isset($entity->original)) { @@ -592,7 +614,7 @@ protected function saveRevision(EntityInterface $entity) { if ($entity->isNewRevision()) { drupal_write_record($this->revisionTable, $record); if ($entity->isDefaultRevision()) { - db_update($this->entityInfo['base_table']) + $this->database->update($this->entityInfo['base_table']) ->fields(array($this->revisionKey => $record[$this->revisionKey])) ->condition($this->idKey, $entity->id()) ->execute(); diff --git a/core/lib/Drupal/Core/Entity/DatabaseStorageControllerNG.php b/core/lib/Drupal/Core/Entity/DatabaseStorageControllerNG.php index e18edbd..0c50b33 100644 --- a/core/lib/Drupal/Core/Entity/DatabaseStorageControllerNG.php +++ b/core/lib/Drupal/Core/Entity/DatabaseStorageControllerNG.php @@ -14,6 +14,7 @@ use Drupal\Core\Entity\DatabaseStorageController; use Drupal\Core\Entity\EntityStorageException; use Drupal\Component\Uuid\Uuid; +use Drupal\Core\Database\Connection; /** * Implements Field API specific enhancements to the DatabaseStorageController class. @@ -51,8 +52,8 @@ class DatabaseStorageControllerNG extends DatabaseStorageController { /** * Overrides DatabaseStorageController::__construct(). */ - public function __construct($entityType) { - parent::__construct($entityType); + public function __construct($entityType, Connection $database) { + parent::__construct($entityType, $database); $this->bundleKey = !empty($this->entityInfo['entity_keys']['bundle']) ? $this->entityInfo['entity_keys']['bundle'] : FALSE; $this->entityClass = $this->entityInfo['class']; @@ -225,7 +226,7 @@ protected function mapFromStorageRecords(array $records, $load_revision = FALSE) */ protected function attachPropertyData(array &$entities, $load_revision = FALSE) { if ($this->dataTable) { - $query = db_select($this->dataTable, 'data', array('fetch' => PDO::FETCH_ASSOC)) + $query = $this->database->select($this->dataTable, 'data', array('fetch' => PDO::FETCH_ASSOC)) ->fields('data') ->condition($this->idKey, array_keys($entities)) ->orderBy('data.' . $this->idKey); @@ -273,7 +274,7 @@ protected function attachPropertyData(array &$entities, $load_revision = FALSE) * Added mapping from entities to storage records before saving. */ public function save(EntityInterface $entity) { - $transaction = db_transaction(); + $transaction = $this->database->startTransaction(); try { // Ensure we are dealing with the actual entity. $entity = $entity->getOriginalEntity(); @@ -366,7 +367,7 @@ protected function saveRevision(EntityInterface $entity) { if ($entity->isNewRevision()) { drupal_write_record($this->revisionTable, $record); if ($entity->isDefaultRevision()) { - db_update($this->entityInfo['base_table']) + $this->database->update($this->entityInfo['base_table']) ->fields(array($this->revisionKey => $record->{$this->revisionKey})) ->condition($this->idKey, $record->{$this->idKey}) ->execute(); @@ -389,11 +390,11 @@ protected function saveRevision(EntityInterface $entity) { */ protected function savePropertyData(EntityInterface $entity) { // Delete and insert to handle removed values. - db_delete($this->dataTable) + $this->database->delete($this->dataTable) ->condition($this->idKey, $entity->id()) ->execute(); - $query = db_insert($this->dataTable); + $query = $this->database->insert($this->dataTable); foreach ($entity->getTranslationLanguages() as $langcode => $language) { $record = $this->mapToDataStorageRecord($entity, $langcode); @@ -500,7 +501,7 @@ public function delete(array $entities) { return; } - $transaction = db_transaction(); + $transaction = $this->database->startTransaction(); try { // Ensure we are dealing with the actual entities. foreach ($entities as $id => $entity) { @@ -513,18 +514,18 @@ public function delete(array $entities) { } $ids = array_keys($entities); - db_delete($this->entityInfo['base_table']) + $this->database->delete($this->entityInfo['base_table']) ->condition($this->idKey, $ids) ->execute(); if ($this->revisionKey) { - db_delete($this->revisionTable) + $this->database->delete($this->revisionTable) ->condition($this->idKey, $ids) ->execute(); } if ($this->dataTable) { - db_delete($this->dataTable) + $this->database->delete($this->dataTable) ->condition($this->idKey, $ids) ->execute(); } diff --git a/core/lib/Drupal/Core/Entity/EntityHandlerInterface.php b/core/lib/Drupal/Core/Entity/EntityHandlerInterface.php new file mode 100644 index 0000000..ec1a3c5 --- /dev/null +++ b/core/lib/Drupal/Core/Entity/EntityHandlerInterface.php @@ -0,0 +1,39 @@ +discovery = new AnnotatedClassDiscovery('Core', 'Entity', $namespaces); $this->discovery = new InfoHookDecorator($this->discovery, 'entity_info'); @@ -178,6 +188,7 @@ public function __construct(array $namespaces) { $this->discovery = new CacheDecorator($this->discovery, 'entity_info:' . language(LANGUAGE_TYPE_INTERFACE)->langcode, 'cache', CacheBackendInterface::CACHE_PERMANENT, array('entity_info' => TRUE)); $this->factory = new DefaultFactory($this->discovery); + $this->container = $container; } /** @@ -265,7 +276,16 @@ public function getControllerClass($entity_type, $controller_type, $nested = NUL public function getStorageController($entity_type) { if (!isset($this->controllers['storage'][$entity_type])) { $class = $this->getControllerClass($entity_type, 'controller_class'); - $this->controllers['storage'][$entity_type] = new $class($entity_type); + // @todo remove this once all controllers implement + // Drupal\Core\Entity\EntityHandlerInterface. + if (in_array('Drupal\Core\Entity\EntityHandlerInterface', class_implements($class))) { + $this->controllers['storage'][$entity_type] = $class::createInstance($this->container, array( + 'entity_type' => $entity_type + )); + } + else { + $this->controllers['storage'][$entity_type] = new $class($entity_type); + } } return $this->controllers['storage'][$entity_type]; } @@ -282,7 +302,17 @@ public function getStorageController($entity_type) { public function getListController($entity_type) { if (!isset($this->controllers['listing'][$entity_type])) { $class = $this->getControllerClass($entity_type, 'list_controller_class'); - $this->controllers['listing'][$entity_type] = new $class($entity_type, $this->getStorageController($entity_type)); + // @todo remove this once all controllers implement + // Drupal\Core\Entity\EntityHandlerInterface. + if (in_array('Drupal\Core\Entity\EntityHandlerInterface', class_implements($class))) { + $this->controllers['listing'][$entity_type] = $class::createInstance($this->container, array( + 'entity_type' => $entity_type, + 'storage' => $this->getStorageController($entity_type) + )); + } + else { + $this->controllers['listing'][$entity_type] = new $class($entity_type, $this->getStorageController($entity_type)); + } } return $this->controllers['listing'][$entity_type]; } @@ -301,7 +331,16 @@ public function getListController($entity_type) { public function getFormController($entity_type, $operation) { if (!isset($this->controllers['form'][$operation][$entity_type])) { $class = $this->getControllerClass($entity_type, 'form_controller_class', $operation); - $this->controllers['form'][$operation][$entity_type] = new $class($operation); + // @todo remove this once all controllers implement + // Drupal\Core\Entity\EntityHandlerInterface. + if (in_array('Drupal\Core\Entity\EntityHandlerInterface', class_implements($class))) { + $this->controllers['form'][$operation][$entity_type] = $class::createInstance($this->container, array( + 'operation' => $operation + )); + } + else { + $this->controllers['form'][$operation][$entity_type] = new $class($operation); + } } return $this->controllers['form'][$operation][$entity_type]; } @@ -318,7 +357,16 @@ public function getFormController($entity_type, $operation) { public function getRenderController($entity_type) { if (!isset($this->controllers['render'][$entity_type])) { $class = $this->getControllerClass($entity_type, 'render_controller_class'); - $this->controllers['render'][$entity_type] = new $class($entity_type); + // @todo remove this once all controllers implement + // Drupal\Core\Entity\EntityHandlerInterface. + if (in_array('Drupal\Core\Entity\EntityHandlerInterface', class_implements($class))) { + $this->controllers['render'][$entity_type] = $class::createInstance($this->container, array( + 'entity_type' => $entity_type + )); + } + else { + $this->controllers['render'][$entity_type] = new $class($entity_type); + } } return $this->controllers['render'][$entity_type]; } @@ -335,7 +383,16 @@ public function getRenderController($entity_type) { public function getAccessController($entity_type) { if (!isset($this->controllers['access'][$entity_type])) { $class = $this->getControllerClass($entity_type, 'access_controller_class'); - $this->controllers['access'][$entity_type] = new $class($entity_type); + // @todo remove this once all controllers implement + // Drupal\Core\Entity\EntityHandlerInterface. + if (in_array('Drupal\Core\Entity\EntityHandlerInterface', class_implements($class))) { + $this->controllers['access'][$entity_type] = $class::createInstance($this->container, array( + 'entity_type' => $entity_type + )); + } + else { + $this->controllers['access'][$entity_type] = new $class($entity_type); + } } return $this->controllers['access'][$entity_type]; } diff --git a/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkStorageController.php b/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkStorageController.php index 5180b3e..2a1dbb3 100644 --- a/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkStorageController.php +++ b/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkStorageController.php @@ -10,6 +10,7 @@ use Drupal\Core\Entity\DatabaseStorageController; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityStorageException; +use Drupal\Core\Database\Connection; /** * Controller class for menu links. @@ -36,8 +37,8 @@ class MenuLinkStorageController extends DatabaseStorageController { /** * Overrides DatabaseStorageController::__construct(). */ - public function __construct($entityType) { - parent::__construct($entityType); + public function __construct($entityType, Connection $database) { + parent::__construct($entityType, $database); if (empty(static::$routerItemFields)) { static::$routerItemFields = array_diff(drupal_schema_fields_sql('menu_router'), array('weight')); @@ -97,7 +98,7 @@ public function save(EntityInterface $entity) { // would be confusing in that situation. $return = SAVED_UPDATED; - $transaction = db_transaction(); + $transaction = $this->database->startTransaction(); try { // Load the stored entity, if any. if (!$entity->isNew() && !isset($entity->original)) { @@ -105,7 +106,7 @@ public function save(EntityInterface $entity) { } if ($entity->isNew()) { - $entity->mlid = db_insert($this->entityInfo['base_table'])->fields(array('menu_name' => 'tools'))->execute(); + $entity->mlid = $this->database->insert($this->entityInfo['base_table'])->fields(array('menu_name' => 'tools'))->execute(); $entity->enforceIsNew(); } @@ -361,7 +362,7 @@ protected function updateParentalStatus(EntityInterface $entity, $exclude = FALS } $parent_has_children = ((bool) $query->execute()) ? 1 : 0; - db_update('menu_links') + $this->database->update('menu_links') ->fields(array('has_children' => $parent_has_children)) ->condition('mlid', $entity->plid) ->execute(); @@ -492,7 +493,7 @@ protected function setParents(EntityInterface $entity, EntityInterface $parent) public function findChildrenRelativeDepth(EntityInterface $entity) { // @todo Since all we need is a specific field from the base table, does it // make sense to convert to EFQ? - $query = db_select('menu_links'); + $query = $this->database->select('menu_links'); $query->addField('menu_links', 'depth'); $query->condition('menu_name', $entity->menu_name); $query->orderBy('depth', 'DESC'); @@ -520,7 +521,7 @@ public function findChildrenRelativeDepth(EntityInterface $entity) { * A menu link entity. */ protected function moveChildren(EntityInterface $entity) { - $query = db_update($this->entityInfo['base_table']); + $query = $this->database->update($this->entityInfo['base_table']); $query->fields(array('menu_name' => $entity->menu_name));