diff --git a/core/modules/editor/editor.install b/core/modules/editor/editor.install new file mode 100644 index 0000000000000000000000000000000000000000..a07bd805602e13edc4d3bdb06939220f22aea2cd --- /dev/null +++ b/core/modules/editor/editor.install @@ -0,0 +1,22 @@ +<?php + +/** + * @file + * Install, update and uninstall functions for the Editor module. + */ + +/** + * Synchronizes the editor status with the paired text format status. + */ +function editor_update_8001() { + $config_factory = \Drupal::configFactory(); + // Iterate on all text formats config entities. + foreach ($config_factory->listAll('filter.format.') as $name) { + list(,, $id) = explode('.', $name, 3); + $status = $config_factory->get($name)->get('status'); + $editor = $config_factory->getEditable("editor.editor.$id"); + if (!$editor->isNew() && $editor->get('status') !== $status) { + $editor->set('status', $status)->save(); + } + } +} diff --git a/core/modules/editor/editor.module b/core/modules/editor/editor.module index 16e0520f7f91efea4cb0e5b8424b442f5ae69a1e..e83d49a972a17110a3742909aa8182d43b51d965 100644 --- a/core/modules/editor/editor.module +++ b/core/modules/editor/editor.module @@ -6,6 +6,7 @@ */ use Drupal\Component\Utility\Html; +use Drupal\editor\Entity\Editor; use Drupal\Core\Entity\FieldableEntityInterface; use Drupal\Core\Field\FieldDefinitionInterface; use Drupal\Core\Form\FormStateInterface; @@ -509,3 +510,30 @@ function _editor_parse_file_uuids($text) { } return $uuids; } + +/** + * Implements hook_ENTITY_TYPE_presave(). + * + * Synchronizes the editor status to its paired text format status. + */ +function editor_filter_format_presave(FilterFormatInterface $format) { + // The text format being created cannot have a text editor yet. + if ($format->isNew()) { + return; + } + + /** @var \Drupal\filter\FilterFormatInterface $original */ + $original = \Drupal::entityManager() + ->getStorage('filter_format') + ->loadUnchanged($format->getOriginalId()); + + // If the text format status is the same, return early. + if (($status = $format->status()) === $original->status()) { + return; + } + + /** @var \Drupal\editor\EditorInterface $editor */ + if ($editor = Editor::load($format->id())) { + $editor->setStatus($status)->save(); + } +} diff --git a/core/modules/editor/src/Tests/Update/EditorUpdateTest.php b/core/modules/editor/src/Tests/Update/EditorUpdateTest.php new file mode 100644 index 0000000000000000000000000000000000000000..beefcfdfba5fb343d463c62b464b0fbab89bb018 --- /dev/null +++ b/core/modules/editor/src/Tests/Update/EditorUpdateTest.php @@ -0,0 +1,75 @@ +<?php + +/** + * @file + * Contains \Drupal\editor\Tests\Update\EditorUpdateTest. + */ + +namespace Drupal\editor\Tests\Update; + +use Drupal\system\Tests\Update\UpdatePathTestBase; + +/** + * Tests Editor module database updates. + * + * @group editor + */ +class EditorUpdateTest extends UpdatePathTestBase { + + /** + * {@inheritdoc} + */ + public function setDatabaseDumpFiles() { + $this->databaseDumpFiles = [ + __DIR__ . '/../../../../system/tests/fixtures/update/drupal-8.bare.standard.php.gz', + // Simulate an un-synchronized environment. + __DIR__ . '/../../../../system/tests/fixtures/update/drupal-8.editor-editor_update_8001.php', + ]; + } + + /** + * Tests editor_update_8001(). + * + * @see editor_update_8001() + */ + public function testEditorUpdate8001() { + /** @var \Drupal\Core\Config\ConfigFactoryInterface $config_factory */ + $config_factory = $this->container->get('config.factory'); + + $format_basic_html = $config_factory->get('filter.format.basic_html'); + $editor_basic_html = $config_factory->get('editor.editor.basic_html'); + $format_full_html = $config_factory->get('filter.format.full_html'); + $editor_full_html = $config_factory->get('editor.editor.full_html'); + + // Checks if the 'basic_html' format and editor statuses differ. + $this->assertTrue($format_basic_html->get('status')); + $this->assertFalse($editor_basic_html->get('status')); + $this->assertNotIdentical($format_basic_html->get('status'), $editor_basic_html->get('status')); + + // Checks if the 'full_html' format and editor statuses differ. + $this->assertFalse($format_full_html->get('status')); + $this->assertTrue($editor_full_html->get('status')); + $this->assertNotIdentical($format_full_html->get('status'), $editor_full_html->get('status')); + + + // Run updates. + $this->runUpdates(); + + // Reload text formats and editors. + $format_basic_html = $config_factory->get('filter.format.basic_html'); + $editor_basic_html = $config_factory->get('editor.editor.basic_html'); + $format_full_html = $config_factory->get('filter.format.full_html'); + $editor_full_html = $config_factory->get('editor.editor.full_html'); + + // Checks if the 'basic_html' format and editor statuses are in sync. + $this->assertTrue($format_basic_html->get('status')); + $this->assertTrue($editor_basic_html->get('status')); + $this->assertIdentical($format_basic_html->get('status'), $editor_basic_html->get('status')); + + // Checks if the 'full_html' format and editor statuses are in sync. + $this->assertFalse($format_full_html->get('status')); + $this->assertFalse($editor_full_html->get('status')); + $this->assertIdentical($format_full_html->get('status'), $editor_full_html->get('status')); + } + +} diff --git a/core/modules/editor/tests/src/Kernel/EditorFilterIntegrationTest.php b/core/modules/editor/tests/src/Kernel/EditorFilterIntegrationTest.php new file mode 100644 index 0000000000000000000000000000000000000000..625fb90011bac4c090366ea993be262d7ef6a57a --- /dev/null +++ b/core/modules/editor/tests/src/Kernel/EditorFilterIntegrationTest.php @@ -0,0 +1,61 @@ +<?php + +/** + * @file + * Contains \Drupal\Tests\editor\Kernel\EditorFilterIntegration. + */ + +namespace Drupal\Tests\editor\Kernel; + +use Drupal\Component\Utility\Unicode; +use Drupal\editor\Entity\Editor; +use Drupal\filter\Entity\FilterFormat; +use Drupal\KernelTests\KernelTestBase; + +/** + * Tests integration with filter module. + * + * @group editor + */ +class EditorFilterIntegrationTest extends KernelTestBase { + + /** + * {@inheritdoc} + */ + public static $modules = ['filter', 'editor', 'editor_test']; + + /** + * Tests text format removal or disabling. + */ + public function testTextFormatIntegration() { + // Create an arbitrary text format. + $format = FilterFormat::create([ + 'format' => Unicode::strtolower($this->randomMachineName()), + 'name' => $this->randomString(), + ]); + $format->save(); + + // Create a paired editor. + Editor::create(['format' => $format->id(), 'editor' => 'unicorn'])->save(); + + // Disable the text format. + $format->disable()->save(); + + // The paired editor should be disabled too. + $this->assertFalse(Editor::load($format->id())->status()); + + // Re-enable the text format. + $format->enable()->save(); + + // The paired editor should be enabled too. + $this->assertTrue(Editor::load($format->id())->status()); + + // Completely remove the text format. Usually this cannot occur via UI, but + // can be triggered from API. + $format->delete(); + + // The paired editor should be removed. + $this->assertNull(Editor::load($format->id())); + } + +} diff --git a/core/modules/system/tests/fixtures/update/drupal-8.editor-editor_update_8001.php b/core/modules/system/tests/fixtures/update/drupal-8.editor-editor_update_8001.php new file mode 100644 index 0000000000000000000000000000000000000000..c2e4cab1e93d6a751628e23ed1f3d8102097ce43 --- /dev/null +++ b/core/modules/system/tests/fixtures/update/drupal-8.editor-editor_update_8001.php @@ -0,0 +1,39 @@ +<?php + +/** + * @file + * Contains database additions to drupal-8.bare.standard.php.gz for testing the + * upgrade path of editor_update_8001(). + */ + +use Drupal\Core\Database\Database; + +$connection = Database::getConnection(); + +// Simulate an un-synchronized environment. + +// Disable the 'basic_html' editor. +$data = $connection->select('config') + ->fields('config', ['data']) + ->condition('name', 'editor.editor.basic_html') + ->execute() + ->fetchField(); +$data = unserialize($data); +$data['status'] = FALSE; +$connection->update('config') + ->fields(['data' => serialize($data)]) + ->condition('name', 'editor.editor.basic_html') + ->execute(); + +// Disable the 'full_html' text format. +$data = $connection->select('config') + ->fields('config', ['data']) + ->condition('name', 'filter.format.full_html') + ->execute() + ->fetchField(); +$data = unserialize($data); +$data['status'] = FALSE; +$connection->update('config') + ->fields(['data' => serialize($data)]) + ->condition('name', 'filter.format.full_html') + ->execute();