Mercurial > hg > isophonics-drupal-site
comparison core/modules/field/src/ConfigImporterFieldPurger.php @ 0:4c8ae668cc8c
Initial import (non-working)
author | Chris Cannam |
---|---|
date | Wed, 29 Nov 2017 16:09:58 +0000 |
parents | |
children | 1fec387a4317 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:4c8ae668cc8c |
---|---|
1 <?php | |
2 | |
3 namespace Drupal\field; | |
4 | |
5 use Drupal\Core\Config\ConfigImporter; | |
6 use Drupal\Core\Config\Entity\ConfigEntityStorage; | |
7 use Drupal\field\Entity\FieldStorageConfig; | |
8 | |
9 /** | |
10 * Processes field purges before a configuration synchronization. | |
11 */ | |
12 class ConfigImporterFieldPurger { | |
13 | |
14 /** | |
15 * Processes fields targeted for purge as part of a configuration sync. | |
16 * | |
17 * This takes care of deleting the field if necessary, and purging the data on | |
18 * the fly. | |
19 * | |
20 * @param array $context | |
21 * The batch context. | |
22 * @param \Drupal\Core\Config\ConfigImporter $config_importer | |
23 * The config importer. | |
24 */ | |
25 public static function process(array &$context, ConfigImporter $config_importer) { | |
26 if (!isset($context['sandbox']['field'])) { | |
27 static::initializeSandbox($context, $config_importer); | |
28 } | |
29 | |
30 // Get the list of field storages to purge. | |
31 $field_storages = static::getFieldStoragesToPurge($context['sandbox']['field']['extensions'], $config_importer->getUnprocessedConfiguration('delete')); | |
32 // Get the first field storage to process. | |
33 $field_storage = reset($field_storages); | |
34 if (!isset($context['sandbox']['field']['current_storage_id']) || $context['sandbox']['field']['current_storage_id'] != $field_storage->id()) { | |
35 $context['sandbox']['field']['current_storage_id'] = $field_storage->id(); | |
36 // If the storage has not been deleted yet we need to do that. This is the | |
37 // case when the storage deletion is staged. | |
38 if (!$field_storage->isDeleted()) { | |
39 $field_storage->delete(); | |
40 } | |
41 } | |
42 field_purge_batch($context['sandbox']['field']['purge_batch_size'], $field_storage->uuid()); | |
43 $context['sandbox']['field']['current_progress']++; | |
44 $fields_to_delete_count = count(static::getFieldStoragesToPurge($context['sandbox']['field']['extensions'], $config_importer->getUnprocessedConfiguration('delete'))); | |
45 if ($fields_to_delete_count == 0) { | |
46 $context['finished'] = 1; | |
47 } | |
48 else { | |
49 $context['finished'] = $context['sandbox']['field']['current_progress'] / $context['sandbox']['field']['steps_to_delete']; | |
50 $context['message'] = \Drupal::translation()->translate('Purging field @field_label', ['@field_label' => $field_storage->label()]); | |
51 } | |
52 } | |
53 | |
54 /** | |
55 * Initializes the batch context sandbox for processing field deletions. | |
56 * | |
57 * This calculates the number of steps necessary to purge all the field data | |
58 * and saves data for later use. | |
59 * | |
60 * @param array $context | |
61 * The batch context. | |
62 * @param \Drupal\Core\Config\ConfigImporter $config_importer | |
63 * The config importer. | |
64 */ | |
65 protected static function initializeSandbox(array &$context, ConfigImporter $config_importer) { | |
66 $context['sandbox']['field']['purge_batch_size'] = \Drupal::config('field.settings')->get('purge_batch_size'); | |
67 // Save the future list of installed extensions to limit the amount of times | |
68 // the configuration is read from disk. | |
69 $context['sandbox']['field']['extensions'] = $config_importer->getStorageComparer()->getSourceStorage()->read('core.extension'); | |
70 | |
71 $context['sandbox']['field']['steps_to_delete'] = 0; | |
72 $fields = static::getFieldStoragesToPurge($context['sandbox']['field']['extensions'], $config_importer->getUnprocessedConfiguration('delete')); | |
73 foreach ($fields as $field) { | |
74 $row_count = \Drupal::entityManager()->getStorage($field->getTargetEntityTypeId()) | |
75 ->countFieldData($field); | |
76 if ($row_count > 0) { | |
77 // The number of steps to delete each field is determined by the | |
78 // purge_batch_size setting. For example if the field has 9 rows and the | |
79 // batch size is 10 then this will add 1 step to $number_of_steps. | |
80 $how_many_steps = ceil($row_count / $context['sandbox']['field']['purge_batch_size']); | |
81 $context['sandbox']['field']['steps_to_delete'] += $how_many_steps; | |
82 } | |
83 } | |
84 // Each field possibly needs one last field_purge_batch() call to remove the | |
85 // last field and the field storage itself. | |
86 $context['sandbox']['field']['steps_to_delete'] += count($fields); | |
87 | |
88 $context['sandbox']['field']['current_progress'] = 0; | |
89 } | |
90 | |
91 /** | |
92 * Gets the list of fields to purge before configuration synchronization. | |
93 * | |
94 * If, during a configuration synchronization, a field is being deleted and | |
95 * the module that provides the field type is being uninstalled then the field | |
96 * data must be purged before the module is uninstalled. Also, if deleted | |
97 * fields exist whose field types are provided by modules that are being | |
98 * uninstalled their data need to be purged too. | |
99 * | |
100 * @param array $extensions | |
101 * The list of extensions that will be enabled after the configuration | |
102 * synchronization has finished. | |
103 * @param array $deletes | |
104 * The configuration that will be deleted by the configuration | |
105 * synchronization. | |
106 * | |
107 * @return \Drupal\field\Entity\FieldStorageConfig[] | |
108 * An array of field storages that need purging before configuration can be | |
109 * synchronized. | |
110 */ | |
111 public static function getFieldStoragesToPurge(array $extensions, array $deletes) { | |
112 $providers = array_keys($extensions['module']); | |
113 $providers[] = 'core'; | |
114 $storages_to_delete = []; | |
115 | |
116 // Gather fields that will be deleted during configuration synchronization | |
117 // where the module that provides the field type is also being uninstalled. | |
118 $field_storage_ids = []; | |
119 foreach ($deletes as $config_name) { | |
120 $field_storage_config_prefix = \Drupal::entityManager()->getDefinition('field_storage_config')->getConfigPrefix(); | |
121 if (strpos($config_name, $field_storage_config_prefix . '.') === 0) { | |
122 $field_storage_ids[] = ConfigEntityStorage::getIDFromConfigName($config_name, $field_storage_config_prefix); | |
123 } | |
124 } | |
125 if (!empty($field_storage_ids)) { | |
126 $field_storages = \Drupal::entityQuery('field_storage_config') | |
127 ->condition('id', $field_storage_ids, 'IN') | |
128 ->condition('module', $providers, 'NOT IN') | |
129 ->execute(); | |
130 if (!empty($field_storages)) { | |
131 $storages_to_delete = FieldStorageConfig::loadMultiple($field_storages); | |
132 } | |
133 } | |
134 | |
135 // Gather deleted fields from modules that are being uninstalled. | |
136 /** @var \Drupal\field\FieldStorageConfigInterface[] $field_storages */ | |
137 $field_storages = entity_load_multiple_by_properties('field_storage_config', ['deleted' => TRUE, 'include_deleted' => TRUE]); | |
138 foreach ($field_storages as $field_storage) { | |
139 if (!in_array($field_storage->getTypeProvider(), $providers)) { | |
140 $storages_to_delete[$field_storage->id()] = $field_storage; | |
141 } | |
142 } | |
143 return $storages_to_delete; | |
144 } | |
145 | |
146 } |