Updated Drupal to 8.6. This goes with the following updates because it's possible...
[yaffs-website] / web / core / modules / field / tests / src / Functional / Update / FieldUpdateTest.php
1 <?php
2
3 namespace Drupal\Tests\field\Functional\Update;
4
5 use Drupal\Core\Config\Config;
6 use Drupal\Core\Field\FieldDefinitionInterface;
7 use Drupal\Core\Field\FieldStorageDefinitionInterface;
8 use Drupal\field\Entity\FieldConfig;
9 use Drupal\FunctionalTests\Update\UpdatePathTestBase;
10 use Drupal\node\Entity\Node;
11 use Drupal\Tests\Traits\Core\CronRunTrait;
12
13 /**
14  * Tests that field settings are properly updated during database updates.
15  *
16  * @group field
17  * @group legacy
18  */
19 class FieldUpdateTest extends UpdatePathTestBase {
20
21   use CronRunTrait;
22
23   /**
24    * The config factory service.
25    *
26    * @var \Drupal\Core\Config\ConfigFactoryInterface
27    */
28   protected $configFactory;
29
30   /**
31    * The database connection.
32    *
33    * @var \Drupal\Core\Database\Connection
34    */
35   protected $database;
36
37   /**
38    * The key-value collection for tracking installed storage schema.
39    *
40    * @var \Drupal\Core\KeyValueStore\KeyValueStoreInterface
41    */
42   protected $installedStorageSchema;
43
44   /**
45    * The state service.
46    *
47    * @var \Drupal\Core\State\StateInterface
48    */
49   protected $state;
50
51   /**
52    * The deleted fields repository.
53    *
54    * @var \Drupal\Core\Field\DeletedFieldsRepositoryInterface
55    */
56   protected $deletedFieldsRepository;
57
58   /**
59    * {@inheritdoc}
60    */
61   protected function setUp() {
62     parent::setUp();
63
64     $this->configFactory = $this->container->get('config.factory');
65     $this->database = $this->container->get('database');
66     $this->installedStorageSchema = $this->container->get('keyvalue')->get('entity.storage_schema.sql');
67     $this->state = $this->container->get('state');
68     $this->deletedFieldsRepository = $this->container->get('entity_field.deleted_fields_repository');
69   }
70
71   /**
72    * {@inheritdoc}
73    */
74   protected function setDatabaseDumpFiles() {
75     $this->databaseDumpFiles = [
76       __DIR__ . '/../../../../../system/tests/fixtures/update/drupal-8.bare.standard.php.gz',
77       __DIR__ . '/../../../fixtures/update/drupal-8.views_entity_reference_plugins-2429191.php',
78       __DIR__ . '/../../../fixtures/update/drupal-8.remove_handler_submit_setting-2715589.php',
79       __DIR__ . '/../../../fixtures/update/drupal-8.update_deleted_field_definitions-2931436.php',
80     ];
81   }
82
83   /**
84    * Tests field_update_8001().
85    *
86    * @see field_update_8001()
87    */
88   public function testFieldUpdate8001() {
89     // Load the 'node.field_image' field storage config, and check that is has
90     // a 'target_bundle' setting.
91     $config = $this->configFactory->get('field.storage.node.field_image');
92     $settings = $config->get('settings');
93     $this->assertTrue(array_key_exists('target_bundle', $settings));
94
95     // Run updates.
96     $this->runUpdates();
97
98     // Reload the config, and check that the 'target_bundle' setting has been
99     // removed.
100     $config = $this->configFactory->get('field.storage.node.field_image');
101     $settings = $config->get('settings');
102     $this->assertFalse(array_key_exists('target_bundle', $settings));
103   }
104
105   /**
106    * Tests field_update_8002().
107    *
108    * @see field_update_8002()
109    */
110   public function testFieldUpdate8002() {
111     // Check that 'entity_reference' is the provider and a dependency of the
112     // test field storage .
113     $field_storage = $this->configFactory->get('field.storage.node.field_ref_views_select_2429191');
114     $this->assertIdentical($field_storage->get('module'), 'entity_reference');
115     $this->assertEntityRefDependency($field_storage, TRUE);
116
117     // Check that 'entity_reference' is a dependency of the test field.
118     $field = $this->configFactory->get('field.field.node.article.field_ref_views_select_2429191');
119     $this->assertEntityRefDependency($field, TRUE);
120
121     // Check that 'entity_reference' is a dependency of the test view.
122     $view = $this->configFactory->get('views.view.entity_reference_plugins_2429191');
123     $this->assertEntityRefDependency($view, TRUE);
124
125     // Run updates.
126     $this->runUpdates();
127
128     // Check that 'entity_reference' is no longer a dependency of the test field
129     // and view.
130     $field_storage = $this->configFactory->get('field.storage.node.field_ref_views_select_2429191');
131     $this->assertIdentical($field_storage->get('module'), 'core');
132     $this->assertEntityRefDependency($field_storage, FALSE);
133     $field = $this->configFactory->get('field.field.node.article.field_ref_views_select_2429191');
134     $this->assertEntityRefDependency($field, FALSE);
135     $view = $this->configFactory->get('views.view.entity_reference_plugins_2429191');
136     $this->assertEntityRefDependency($view, FALSE);
137
138     // Check that field selection, based on the view, still works. It only
139     // selects nodes whose title contains 'foo'.
140     $node_1 = Node::create(['type' => 'article', 'title' => 'foobar']);
141     $node_1->save();
142     $node_2 = Node::create(['type' => 'article', 'title' => 'barbaz']);
143     $node_2->save();
144     $field = FieldConfig::load('node.article.field_ref_views_select_2429191');
145     $selection = \Drupal::service('plugin.manager.entity_reference_selection')->getSelectionHandler($field);
146     $referencable = $selection->getReferenceableEntities();
147     $this->assertEqual(array_keys($referencable['article']), [$node_1->id()]);
148   }
149
150   /**
151    * Tests field_update_8003().
152    *
153    * @see field_update_8003()
154    */
155   public function testFieldUpdate8003() {
156     // Run updates.
157     $this->runUpdates();
158
159     // Check that the new 'auto_create_bundle' setting is populated correctly.
160     $field = $this->configFactory->get('field.field.node.article.field_ref_autocreate_2412569');
161     $handler_settings = $field->get('settings.handler_settings');
162
163     $expected_target_bundles = ['tags' => 'tags', 'test' => 'test'];
164     $this->assertEqual($handler_settings['target_bundles'], $expected_target_bundles);
165
166     $this->assertTrue($handler_settings['auto_create']);
167     $this->assertEqual($handler_settings['auto_create_bundle'], 'tags');
168   }
169
170   /**
171    * Tests field_update_8500().
172    *
173    * @see field_update_8500()
174    */
175   public function testFieldUpdate8500() {
176     $field_name = 'field_test';
177     $field_uuid = '5d0d9870-560b-46c4-b838-0dcded0502dd';
178     $field_storage_uuid = 'ce93d7c2-1da7-4a2c-9e6d-b4925e3b129f';
179
180     // Check that we have pre-existing entries for 'field.field.deleted' and
181     // 'field.storage.deleted'.
182     $deleted_fields = $this->state->get('field.field.deleted');
183     $this->assertCount(1, $deleted_fields);
184     $this->assertArrayHasKey($field_uuid, $deleted_fields);
185
186     $deleted_field_storages = $this->state->get('field.storage.deleted');
187     $this->assertCount(1, $deleted_field_storages);
188     $this->assertArrayHasKey($field_storage_uuid, $deleted_field_storages);
189
190     // Ensure that cron does not run automatically after running the updates.
191     $this->state->set('system.cron_last', REQUEST_TIME + 100);
192
193     // Run updates.
194     $this->runUpdates();
195
196     // Now that we can use the API, check that the "delete fields" state entries
197     // have been converted to proper field definition objects.
198     $deleted_fields = $this->deletedFieldsRepository->getFieldDefinitions();
199
200     $this->assertCount(1, $deleted_fields);
201     $this->assertArrayHasKey($field_uuid, $deleted_fields);
202     $this->assertTrue($deleted_fields[$field_uuid] instanceof FieldDefinitionInterface);
203     $this->assertEquals($field_name, $deleted_fields[$field_uuid]->getName());
204
205     $deleted_field_storages = $this->deletedFieldsRepository->getFieldStorageDefinitions();
206     $this->assertCount(1, $deleted_field_storages);
207     $this->assertArrayHasKey($field_storage_uuid, $deleted_field_storages);
208     $this->assertTrue($deleted_field_storages[$field_storage_uuid] instanceof FieldStorageDefinitionInterface);
209     $this->assertEquals($field_name, $deleted_field_storages[$field_storage_uuid]->getName());
210
211     // Check that the installed storage schema still exists.
212     $this->assertNotNull($this->installedStorageSchema->get("node.field_schema_data.$field_name"));
213
214     // Check that the deleted field tables exist.
215     /** @var \Drupal\Core\Entity\Sql\DefaultTableMapping $table_mapping */
216     $table_mapping = \Drupal::entityTypeManager()->getStorage('node')->getTableMapping();
217
218     $deleted_field_data_table_name = $table_mapping->getDedicatedDataTableName($deleted_field_storages[$field_storage_uuid], TRUE);
219     $this->assertTrue($this->database->schema()->tableExists($deleted_field_data_table_name));
220     $deleted_field_revision_table_name = $table_mapping->getDedicatedRevisionTableName($deleted_field_storages[$field_storage_uuid], TRUE);
221     $this->assertTrue($this->database->schema()->tableExists($deleted_field_revision_table_name));
222
223     // Run cron and repeat the checks above.
224     $this->cronRun();
225
226     $deleted_fields = $this->deletedFieldsRepository->getFieldDefinitions();
227     $this->assertCount(0, $deleted_fields);
228
229     $deleted_field_storages = $this->deletedFieldsRepository->getFieldStorageDefinitions();
230     $this->assertCount(0, $deleted_field_storages);
231
232     // Check that the installed storage schema has been deleted.
233     $this->assertNull($this->installedStorageSchema->get("node.field_schema_data.$field_name"));
234
235     // Check that the deleted field tables have been deleted.
236     $this->assertFalse($this->database->schema()->tableExists($deleted_field_data_table_name));
237     $this->assertFalse($this->database->schema()->tableExists($deleted_field_revision_table_name));
238   }
239
240   /**
241    * Asserts that a config depends on 'entity_reference' or not
242    *
243    * @param \Drupal\Core\Config\Config $config
244    *   The config to test.
245    * @param bool $present
246    *   TRUE to test that entity_reference is present, FALSE to test that it is
247    *   absent.
248    */
249   protected function assertEntityRefDependency(Config $config, $present) {
250     $dependencies = $config->get('dependencies');
251     $dependencies += ['module' => []];
252     $this->assertEqual(in_array('entity_reference', $dependencies['module']), $present);
253   }
254
255   /**
256    * Tests field_post_update_remove_handler_submit_setting().
257    *
258    * @see field_post_update_remove_handler_submit_setting()
259    */
260   public function testEntityReferenceFieldConfigCleanUpdate() {
261     $field_config = $this->config('field.field.node.article.field_tags');
262     // Check that 'handler_submit' key exists in field config settings.
263     $this->assertEquals('Change handler', $field_config->get('settings.handler_submit'));
264
265     $this->runUpdates();
266
267     $field_config = $this->config('field.field.node.article.field_tags');
268     // Check that 'handler_submit' has been removed from field config settings.
269     $this->assertArrayNotHasKey('handler_submit', $field_config->get('settings'));
270   }
271
272 }