/** * Tests some possible entity table updates for a revision view. */ public function testVariousTableUpdatesForRevisionView() { // base + revision <-> base + translation + revision $this->updateEntityTypeToRevisionable(); // Multiple changes, so we have to invalidate the caches, otherwise // the second update will revert the first. $this->entityManager->clearCachedDefinitions(); list($view, $display) = $this->getUpdatedViewAndDisplay(TRUE); $this->assertEqual('entity_test_update_revision', $view->get('base_table')); $this->assertEqual('entity_test_update_revision', $display['display_options']['fields']['id']['table']); $this->assertEqual('entity_test_update_revision', $display['display_options']['fields']['name']['table']); $this->updateEntityTypeToTranslatable(); $this->entityDefinitionUpdateManager->applyUpdates(); list($view, $display) = $this->getUpdatedViewAndDisplay(TRUE); $this->assertEqual('entity_test_update_revision', $view->get('base_table')); $this->assertEqual('entity_test_update_revision', $display['display_options']['fields']['id']['table']); $this->assertEqual('entity_test_update_revision_data', $display['display_options']['fields']['name']['table']); $this->updateEntityTypeToNotTranslatable(); $this->entityDefinitionUpdateManager->applyUpdates(); list($view, $display) = $this->getUpdatedViewAndDisplay(TRUE); $this->assertEqual('entity_test_update_revision', $view->get('base_table')); $this->assertEqual('entity_test_update_revision', $display['display_options']['fields']['id']['table']); $this->assertEqual('entity_test_update_revision', $display['display_options']['fields']['name']['table']); $this->resetEntityType(); }
/** * {@inheritdoc} */ public function applyNewStorage() { // The first call is for making entity types revisionable, the second call // is for adding required fields. $this->updateManager->applyUpdates(); $this->updateManager->applyUpdates(); return $this; }
/** * Asserts the given module can be installed and uninstalled. * * @param string $module_name * The module to install and uninstall. */ protected function assertModuleInstallUninstall($module_name) { $this->enableModules([$module_name]); $this->entityDefinitionUpdateManager->applyUpdates(); $this->assertTrue($this->getModuleHandler()->moduleExists($module_name), $module_name . ' module is enabled.'); $this->getModuleInstaller()->uninstall([$module_name]); $this->entityDefinitionUpdateManager->applyUpdates(); $this->assertFalse($this->getModuleHandler()->moduleExists($module_name), $module_name . ' module is disabled.'); }
/** * Tests that entity updates are correctly reported in the status report page. */ function testStatusReport() { // Create a test entity. $entity = EntityTest::create(['name' => $this->randomString(), 'user_id' => mt_rand()]); $entity->save(); // Check that the status report initially displays no error. $this->drupalGet('admin/reports/status'); $this->assertNoRaw('Out of date'); $this->assertNoRaw('Mismatched entity and/or field definitions'); // Enable an entity update and check that we have a dedicated status report // item. $this->container->get('state')->set('entity_test.remove_name_field', TRUE); $this->drupalGet('admin/reports/status'); $this->assertNoRaw('Out of date'); $this->assertRaw('Mismatched entity and/or field definitions'); // Enable a db update and check that now the entity update status report // item is no longer displayed. We assume an update function will fix the // mismatch. $this->enableUpdates('entity_test', 'status_report', 8001); $this->drupalGet('admin/reports/status'); $this->assertRaw('Out of date'); $this->assertRaw('Mismatched entity and/or field definitions'); // Apply db updates and check that entity updates were not applied. $this->applyUpdates(); $this->drupalGet('admin/reports/status'); $this->assertNoRaw('Out of date'); $this->assertRaw('Mismatched entity and/or field definitions'); // Check that en exception would be triggered when trying to apply them with // existing data. $message = 'Entity updates cannot run if entity data exists.'; try { $this->updatesManager->applyUpdates(); $this->fail($message); } catch (FieldStorageDefinitionUpdateForbiddenException $e) { $this->pass($message); } // Check the status report is the same after trying to apply updates. $this->drupalGet('admin/reports/status'); $this->assertNoRaw('Out of date'); $this->assertRaw('Mismatched entity and/or field definitions'); // Delete entity data, enable a new update, run updates again and check that // entity updates were not applied even when no data exists. $entity->delete(); $this->enableUpdates('entity_test', 'status_report', 8002); $this->applyUpdates(); $this->drupalGet('admin/reports/status'); $this->assertNoRaw('Out of date'); $this->assertRaw('Mismatched entity and/or field definitions'); }
/** * Tests updating entity schema and creating a revisionable base field. * * This tests updating entity schema and creating a revisionable base field * at the same time when there are no existing entities. */ public function testEntityTypeSchemaUpdateAndRevisionableBaseFieldCreateWithoutData() { $this->updateEntityTypeToRevisionable(); $this->addRevisionableBaseField(); $message = 'Successfully updated entity schema and created revisionable base field at the same time.'; // Entity type updates create base fields as well, thus make sure doing both // at the same time does not lead to errors due to the base field being // created twice. try { $this->entityDefinitionUpdateManager->applyUpdates(); $this->pass($message); } catch (\Exception $e) { $this->fail($message); throw $e; } }
/** * Ensures that a new entity level index is created when data exists. * * @see Drupal\Core\Entity\Sql\SqlContentEntityStorageSchema::onEntityTypeUpdate */ public function testCreateIndexUsingEntityStorageSchemaWithData() { // Save an entity. $name = $this->randomString(); $storage = $this->entityManager->getStorage('entity_test_update'); $entity = $storage->create(array('name' => $name)); $entity->save(); // Create an index. $indexes = array('entity_test_update__type_index' => array('type')); $this->state->set('entity_test_update.additional_entity_indexes', $indexes); $this->entityDefinitionUpdateManager->applyUpdates(); $this->assertTrue($this->database->schema()->indexExists('entity_test_update', 'entity_test_update__type_index'), "New index 'entity_test_update__type_index' has been created on the 'entity_test_update' table."); // Check index size in for MySQL. if (Database::getConnection()->driver() == 'mysql') { $result = Database::getConnection()->query('SHOW INDEX FROM {entity_test_update} WHERE key_name = \'entity_test_update__type_index\' and column_name = \'type\'')->fetchObject(); $this->assertEqual(191, $result->Sub_part, 'The index length has been restricted to 191 characters for UTF8MB4 compatibility.'); } }
/** * Tests creating a multi-field index when there are existing entities. */ public function testEntityIndexCreateWithData() { // Save an entity. $name = $this->randomString(); $entity = $this->entityManager->getStorage('entity_test_update')->create(array('name' => $name)); $entity->save(); // Add an entity index, run the update. For now, it's expected to throw an // exception. // @todo Improve SqlContentEntityStorageSchema::requiresEntityDataMigration() // to return FALSE when only index changes are required, so that it can be // applied on top of existing data: https://www.drupal.org/node/2340993. $this->addEntityIndex(); try { $this->entityDefinitionUpdateManager->applyUpdates(); $this->fail('EntityStorageException thrown when trying to apply an update that requires data migration.'); } catch (EntityStorageException $e) { $this->pass('EntityStorageException thrown when trying to apply an update that requires data migration.'); } }
/** * Tests updating a base field when it has existing data. */ public function testBaseFieldEntityKeyUpdateWithExistingData() { // Add the base field and run the update. $this->addBaseField(); $this->entityDefinitionUpdateManager->applyUpdates(); // Save an entity with the base field populated. $this->entityManager->getStorage('entity_test_update')->create(['new_base_field' => $this->randomString()])->save(); // Save an entity with the base field not populated. /** @var \Drupal\entity_test\Entity\EntityTestUpdate $entity */ $entity = $this->entityManager->getStorage('entity_test_update')->create(); $entity->save(); // Promote the base field to an entity key. This will trigger the addition // of a NOT NULL constraint. $this->makeBaseFieldEntityKey(); // Try to apply the update and verify they fail since we have a NULL value. $message = 'An error occurs when trying to enabling NOT NULL constraints with NULL data.'; try { $this->entityDefinitionUpdateManager->applyUpdates(); $this->fail($message); } catch (EntityStorageException $e) { $this->pass($message); } // Check that the update is correctly applied when no NULL data is left. $entity->set('new_base_field', $this->randomString()); $entity->save(); $this->entityDefinitionUpdateManager->applyUpdates(); $this->pass('The update is correctly performed when no NULL data exists.'); // Check that the update actually applied a NOT NULL constraint. $entity->set('new_base_field', NULL); $message = 'The NOT NULL constraint was correctly applied.'; try { $entity->save(); $this->fail($message); } catch (EntityStorageException $e) { $this->pass($message); } }