diff --git a/core/modules/field/field.module b/core/modules/field/field.module index 0d56a0a..e5aa4d1 100644 --- a/core/modules/field/field.module +++ b/core/modules/field/field.module @@ -317,7 +317,7 @@ function field_modules_uninstalled($modules) { */ function field_sync_field_status() { $module_handler = \Drupal::moduleHandler(); - $state = \Drupal::state(); + $field_controller = \Drupal::entityManager()->getStorageController('field_entity'); // Get both deleted and non-deleted field definitions. $fields = array(); @@ -325,7 +325,7 @@ function field_sync_field_status() { $field = \Drupal::config($name)->get(); $fields[$field['uuid']] = $field; } - $deleted_fields = $state->get('field.field.deleted') ?: array(); + $deleted_fields = $field_controller->getDeletedFieldData(); $fields += $deleted_fields; if (empty($fields)) { @@ -363,7 +363,7 @@ function field_sync_field_status() { ->save(); } } - $state->set('field.field.deleted', $deleted_fields); + $field_controller->setDeletedFieldData($deleted_fields); field_cache_clear(); } diff --git a/core/modules/field/field.purge.inc b/core/modules/field/field.purge.inc index a061b5f..c0af0c2 100644 --- a/core/modules/field/field.purge.inc +++ b/core/modules/field/field.purge.inc @@ -119,10 +119,8 @@ function field_purge_batch($batch_size) { } // Retrieve all deleted fields. Any that have no instances can be purged. - $deleted_fields = \Drupal::state()->get('field.field.deleted') ?: array(); + $deleted_fields = \Drupal::entityManager()->getStorageController('field_entity')->getDeletedFields(); foreach ($deleted_fields as $field) { - $field = new Field($field); - // We cannot purge anything if the entity type is unknown (e.g. the // providing module was uninstalled). // @todo Revisit after https://drupal.org/node/2080823. @@ -169,18 +167,19 @@ function field_purge_instance($instance) { * The field record to purge. */ function field_purge_field($field) { + $entity_manager = \Drupal::entityManager(); $instances = field_read_instances(array('field_id' => $field->uuid()), array('include_deleted' => 1)); if (count($instances) > 0) { throw new FieldException(t('Attempt to purge a field @field_name that still has instances.', array('@field_name' => $field->getFieldName()))); } - $state = \Drupal::state(); - $deleted_fields = $state->get('field.field.deleted'); + $field_storage_controller = $entity_manager->getStorageController('field_entity'); + $deleted_fields = $field_storage_controller->getDeletedFieldData(); unset($deleted_fields[$field->uuid()]); - $state->set('field.field.deleted', $deleted_fields); + $field_storage_controller->setDeletedFieldData($deleted_fields); // Notify the storage layer. - \Drupal::entityManager()->getStorageController($field->entity_type)->onFieldPurge($field); + $entity_manager->getStorageController($field->entity_type)->onFieldPurge($field); // Clear the cache. field_info_cache_clear(); diff --git a/core/modules/field/field.services.yml b/core/modules/field/field.services.yml index 8615517..e92f257 100644 --- a/core/modules/field/field.services.yml +++ b/core/modules/field/field.services.yml @@ -1,5 +1,4 @@ services: field.info: class: Drupal\field\FieldInfo - arguments: ['@cache.field', '@config.factory', '@module_handler', '@plugin.manager.field.field_type'] - + arguments: ['@cache.field', '@config.factory', '@module_handler', '@entity.manager', '@plugin.manager.field.field_type'] diff --git a/core/modules/field/lib/Drupal/field/Entity/Field.php b/core/modules/field/lib/Drupal/field/Entity/Field.php index 47003fb..c049e50 100644 --- a/core/modules/field/lib/Drupal/field/Entity/Field.php +++ b/core/modules/field/lib/Drupal/field/Entity/Field.php @@ -414,8 +414,8 @@ protected function saveUpdated() { */ public function delete() { if (!$this->deleted) { + $field_controller = \Drupal::entityManager()->getStorageController('field_entity'); $instance_controller = \Drupal::entityManager()->getStorageController('field_instance'); - $state = \Drupal::state(); // Delete all non-deleted instances. $instance_ids = array(); @@ -436,11 +436,11 @@ public function delete() { // in the key_value table so we can use it later during // field_purge_batch(). This makes sure a new field can be created // immediately with the same name. - $deleted_fields = $state->get('field.field.deleted') ?: array(); $config = $this->getExportProperties(); $config['deleted'] = TRUE; + $deleted_fields = $field_controller->getDeletedFieldData(); $deleted_fields[$this->uuid] = $config; - $state->set('field.field.deleted', $deleted_fields); + $field_controller->setDeletedFieldData($deleted_fields); parent::delete(); diff --git a/core/modules/field/lib/Drupal/field/FieldInfo.php b/core/modules/field/lib/Drupal/field/FieldInfo.php index 2287e6c..432195d 100644 --- a/core/modules/field/lib/Drupal/field/FieldInfo.php +++ b/core/modules/field/lib/Drupal/field/FieldInfo.php @@ -9,6 +9,7 @@ use Drupal\Core\Cache\CacheBackendInterface; use Drupal\Core\Config\ConfigFactory; +use Drupal\Core\Entity\EntityManager; use Drupal\Core\Field\FieldTypePluginManager; use Drupal\Core\Extension\ModuleHandlerInterface; use Drupal\field\FieldInterface; @@ -41,13 +42,20 @@ class FieldInfo { protected $cacheBackend; /** - * Stores a module manager to invoke hooks. + * The module handler. * * @var \Drupal\Core\Extension\ModuleHandlerInterface */ protected $moduleHandler; /** + * The entity manager. + * + * @var \Drupal\Core\Entity\EntityManager + */ + protected $entityManager; + + /** * The field type manager to define field. * * @var \Drupal\Core\Field\FieldTypePluginManager @@ -133,13 +141,16 @@ class FieldInfo { * The configuration factory object to use. * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler * The module handler class to use for invoking hooks. + * @param \Drupal\Core\Entity\EntityManager $entity_manager + * The entity manager. * @param \Drupal\Core\Field\FieldTypePluginManager $field_type_manager * The 'field type' plugin manager. */ - public function __construct(CacheBackendInterface $cache_backend, ConfigFactory $config, ModuleHandlerInterface $module_handler, FieldTypePluginManager $field_type_manager) { + public function __construct(CacheBackendInterface $cache_backend, ConfigFactory $config, ModuleHandlerInterface $module_handler, EntityManager $entity_manager, FieldTypePluginManager $field_type_manager) { $this->cacheBackend = $cache_backend; - $this->moduleHandler = $module_handler; $this->config = $config; + $this->moduleHandler = $module_handler; + $this->entityManager = $entity_manager; $this->fieldTypeManager = $field_type_manager; } @@ -227,18 +238,12 @@ public function getFields() { return $this->fieldsById; } - // Read from persistent cache. - if ($cached = $this->cacheBackend->get('field_info:fields')) { - $this->fieldsById = $cached->data; - } - else { - // Collect and prepare fields. - foreach (field_read_fields(array(), array('include_deleted' => TRUE)) as $field) { - $this->fieldsById[$field->uuid()] = $this->prepareField($field); - } - - // Store in persistent cache. - $this->cacheBackend->set('field_info:fields', $this->fieldsById, CacheBackendInterface::CACHE_PERMANENT, array('field_info' => TRUE)); + // Collect and prepare fields. + $storage_controller = $this->entityManager->getStorageController('field_entity'); + $fields = $storage_controller->loadMultiple(); + $fields += $storage_controller->getDeletedFields(); + foreach ($fields as $field) { + $this->fieldsById[$field->uuid()] = $this->prepareField($field); } // Fill the name/ID map. @@ -267,25 +272,14 @@ public function getFields() { public function getInstances($entity_type = NULL) { // If the full list is not present in "static" cache yet. if (!$this->loadedAllInstances) { - - // Read from persistent cache. - if ($cached = $this->cacheBackend->get('field_info:instances')) { - $this->bundleInstances = $cached->data; - } - else { - // Collect and prepare instances. - - // We also need to populate the static field cache, since it will not - // be set by subsequent getBundleInstances() calls. - $this->getFields(); - - foreach (field_read_instances() as $instance) { - $instance = $this->prepareInstance($instance); - $this->bundleInstances[$instance->entity_type][$instance->bundle][$instance->getFieldName()] = $instance; - } - - // Store in persistent cache. - $this->cacheBackend->set('field_info:instances', $this->bundleInstances, CacheBackendInterface::CACHE_PERMANENT, array('field_info' => TRUE)); + // We also need to populate the static field cache, since it will not be + // set by subsequent getBundleInstances() calls. + $this->getFields(); + + // Collect and prepare instances. + foreach ($this->entityManager->getStorageController('field_instance')->loadMultiple() as $instance) { + $instance = $this->prepareInstance($instance); + $this->bundleInstances[$instance->entity_type][$instance->bundle][$instance->field_name] = $instance; } $this->loadedAllInstances = TRUE; @@ -322,10 +316,8 @@ public function getField($entity_type, $field_name) { return; } - // Do not check the (large) persistent cache, but read the definition. - // Cache miss: read from definition. - if ($field = entity_load('field_entity', $entity_type . '.' . $field_name)) { + if ($field = $this->entityManager->getStorageController('field_entity')->load($entity_type . '.' . $field_name)) { $field = $this->prepareField($field); // Save in the "static" cache. @@ -359,14 +351,14 @@ public function getFieldById($field_id) { return; } - // No persistent cache, fields are only persistently cached as part of a - // bundle. - // Cache miss: read from definition. - if ($fields = field_read_fields(array('uuid' => $field_id), array('include_deleted' => TRUE))) { + $properties = array( + 'uuid' => $field_id, + 'include_deleted' => TRUE, + ); + if ($fields = $this->entityManager->getStorageController('field_entity')->loadByProperties($properties)) { $field = current($fields); $field = $this->prepareField($field); - // Store in the static cache. $this->fieldsById[$field->uuid()] = $field; if (!$field->deleted) { @@ -403,46 +395,13 @@ public function getBundleInstances($entity_type, $bundle) { return array(); } - // Read from the persistent cache. We read fields first, since - // unserializing the cached instance objects tries to access the field - // definitions. - if ($cached_fields = $this->cacheBackend->get("field_info:bundle:fields:$entity_type:$bundle")) { - $fields = $cached_fields->data; - - // Extract the field definitions and save them in the "static" cache. - foreach ($fields as $field) { - if (!isset($this->fieldsById[$field->uuid()])) { - $this->fieldsById[$field->uuid()] = $field; - if (!$field->deleted) { - $this->fieldIdsByName[$field->entity_type][$field->getFieldName()] = $field->uuid(); - } - } - } - - // We can now unserialize the instances. - $cached_instances = $this->cacheBackend->get("field_info:bundle:instances:$entity_type:$bundle"); - $instances = $cached_instances->data; - - // Store the instance definitions in the "static" cache'. Empty (or - // non-existent) bundles are stored separately, so that they do not - // pollute the global list returned by getInstances(). - if ($instances) { - $this->bundleInstances[$entity_type][$bundle] = $instances; - } - else { - $this->emptyBundles[$entity_type][$bundle] = TRUE; - } - return $instances; - } - // Cache miss: collect from the definitions. $field_map = $this->getFieldMap(); $instances = array(); $fields = array(); // Do not return anything for unknown entity types. - if (entity_get_info($entity_type) && !empty($field_map[$entity_type])) { - + if ($this->entityManager->getDefinition($entity_type) && !empty($field_map[$entity_type])) { // Collect names of fields and instances involved in the bundle, using the // field map. The field map is already filtered to active, non-deleted // fields and instances, so those are kept out of the persistent caches. @@ -456,7 +415,7 @@ public function getBundleInstances($entity_type, $bundle) { // Load and prepare the corresponding fields and instances entities. if ($config_ids) { // Place the fields in our global "static". - $loaded_fields = entity_load_multiple('field_entity', array_keys($config_ids)); + $loaded_fields = $this->entityManager->getStorageController('field_entity')->loadMultiple(array_keys($config_ids)); foreach ($loaded_fields as $field) { if (!isset($this->fieldsById[$field->uuid()])) { $field = $this->prepareField($field); @@ -469,7 +428,7 @@ public function getBundleInstances($entity_type, $bundle) { } // Then collect the instances. - $loaded_instances = entity_load_multiple('field_instance', array_values($config_ids)); + $loaded_instances = $this->entityManager->getStorageController('field_instance')->loadMultiple(array_values($config_ids)); foreach ($loaded_instances as $instance) { $instance = $this->prepareInstance($instance); $instances[$instance->getFieldName()] = $instance; @@ -487,11 +446,6 @@ public function getBundleInstances($entity_type, $bundle) { $this->emptyBundles[$entity_type][$bundle] = TRUE; } - // Store in the persistent cache. Fields and instances are cached in - // separate entries because they need to be unserialized separately. - $this->cacheBackend->set("field_info:bundle:fields:$entity_type:$bundle", $fields, CacheBackendInterface::CACHE_PERMANENT, array('field_info' => TRUE)); - $this->cacheBackend->set("field_info:bundle:instances:$entity_type:$bundle", $instances, CacheBackendInterface::CACHE_PERMANENT, array('field_info' => TRUE)); - return $instances; } diff --git a/core/modules/field/lib/Drupal/field/FieldInstanceStorageController.php b/core/modules/field/lib/Drupal/field/FieldInstanceStorageController.php index 5d8fa9c..bd48452 100644 --- a/core/modules/field/lib/Drupal/field/FieldInstanceStorageController.php +++ b/core/modules/field/lib/Drupal/field/FieldInstanceStorageController.php @@ -190,4 +190,20 @@ public function loadByProperties(array $conditions = array()) { return $matching_instances; } + public function getDeletedFieldInstances() { + $deleted = array(); + foreach ($this->getDeletedFieldInstanceData() as $uuid => $config) { + $deleted[$uuid] = $this->create($config); + } + return $deleted; + } + + public function getDeletedFieldInstanceData() { + return $this->state->get('field.instance.deleted') ?: array(); + } + + public function setDeletedFieldInstanceData(array $data) { + $this->state->set('field.instance.deleted', $data); + } + } diff --git a/core/modules/field/lib/Drupal/field/FieldStorageController.php b/core/modules/field/lib/Drupal/field/FieldStorageController.php index 24db2c2..a9b23f1 100644 --- a/core/modules/field/lib/Drupal/field/FieldStorageController.php +++ b/core/modules/field/lib/Drupal/field/FieldStorageController.php @@ -115,10 +115,7 @@ public function loadByProperties(array $conditions = array()) { // Merge deleted fields (stored in state) if needed. if ($include_deleted) { - $deleted_fields = $this->state->get('field.field.deleted') ?: array(); - foreach ($deleted_fields as $id => $config) { - $fields[$id] = $this->entityManager->getStorageController($this->entityType)->create($config); - } + $fields += $this->getDeletedFields(); } // Translate "do not include inactive instances" into actual conditions. @@ -156,6 +153,22 @@ public function loadByProperties(array $conditions = array()) { } return $matching_fields; + } + + public function getDeletedFields() { + $deleted = array(); + foreach ($this->getDeletedFieldData() as $uuid => $config) { + $deleted[$uuid] = $this->create($config); + } + return $deleted; + } + + public function getDeletedFieldData() { + return $this->state->get('field.field.deleted') ?: array(); + } + public function setDeletedFieldData(array $data) { + return $this->state->set('field.field.deleted', $data); } + }