Commit 3f31dbed authored by alexpott's avatar alexpott

Issue #2546828 by Wim Leers: Remove ckeditor_rebuild()

parent f2194d17
......@@ -100,78 +100,3 @@ function _ckeditor_theme_css($theme = NULL) {
}
return $css;
}
/**
* Implements hook_ENTITY_TYPE_insert() for 'filter_format'.
*
* Recalculates the 'format_tags' CKEditor setting when a text format is added.
*
* @see \Drupal\ckeditor\Plugin\CKEditorPlugin\Internal::generateFormatTagsSetting()
* @see ckeditor_rebuild()
*/
function ckeditor_filter_format_insert() {
ckeditor_rebuild();
}
/**
* Implements hook_ENTITY_TYPE_update() for 'filter_format'.
*
* Recalculates the 'format_tags' CKEditor setting when a text format changes.
*
* @see \Drupal\ckeditor\Plugin\CKEditorPlugin\Internal::generateFormatTagsSetting()
* @see ckeditor_rebuild()
*/
function ckeditor_filter_format_update() {
ckeditor_rebuild();
}
/**
* Implements hook_rebuild().
*
* Calculates the 'format_tags' CKEditor setting for each text format.
*
* If this wouldn't happen in hook_rebuild(), then the first drupal_render()
* call that occurs for a page that contains a #type 'text_format' element will
* cause the CKEditor::getJSSettings() to be called, which will cause
* Internal::generateFormatTagsSetting() to be called, which calls
* check_markup(), which finally calls drupal_render() non-recursively, because
* a filter might add placeholders to replace.
* This would be a root call inside a root call, which breaks the stack-based
* logic for bubbling rendering metadata.
* Therefore this pre-calculates the needed values, and hence performs the
* check_markup() calls outside of a drupal_render() call tree.
*
* @see \Drupal\ckeditor\Plugin\CKEditorPlugin\Internal::generateFormatTagsSetting()
* @see ckeditor_filter_format_insert()
* @see ckeditor_filter_format_update()
*/
function ckeditor_rebuild() {
/** @var \Drupal\filter\FilterFormatInterface[] $formats */
$formats = filter_formats();
foreach ($formats as $format) {
$key = 'ckeditor_internal_format_tags:' . $format->id();
// The <p> tag is always allowed — HTML without <p> tags is nonsensical.
$format_tags = array('p');
// Given the list of possible format tags, automatically determine whether
// the current text format allows this tag, and thus whether it should show
// up in the "Format" dropdown.
$possible_format_tags = array('h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'pre');
foreach ($possible_format_tags as $tag) {
$input = '<' . $tag . '>TEST</' . $tag . '>';
$output = trim(check_markup($input, $format->id()));
if ($input == $output) {
$format_tags[] = $tag;
}
}
$format_tags = implode(';', $format_tags);
// Cache the "format_tags" configuration. This cache item is infinitely
// valid; it only changes whenever the text format is changed, which is
// guaranteed by the hook_ENTITY_TYPE_update() and hook_ENTITY_TYPE_insert()
// hook implementations.
\Drupal::state()->set($key, $format_tags);
}
}
......@@ -325,10 +325,6 @@ public function getButtons() {
*
* @return array
* An array containing the "format_tags" configuration.
*
* @see ckeditor_rebuild()
* @see ckeditor_filter_format_insert()
* @see ckeditor_filter_format_update()
*/
protected function generateFormatTagsSetting(Editor $editor) {
// When no text format is associated yet, assume no tag is allowed.
......@@ -338,9 +334,35 @@ protected function generateFormatTagsSetting(Editor $editor) {
}
$format = $editor->getFilterFormat();
// The <p> tag is always allowed — HTML without <p> tags is nonsensical.
$default = 'p';
return \Drupal::state()->get('ckeditor_internal_format_tags:' . $format->id(), $default);
$cid = 'ckeditor_internal_format_tags:' . $format->id();
if ($cached = $this->cache->get($cid)) {
$format_tags = $cached->data;
}
else {
// The <p> tag is always allowed — HTML without <p> tags is nonsensical.
$format_tags = ['p'];
// Given the list of possible format tags, automatically determine whether
// the current text format allows this tag, and thus whether it should show
// up in the "Format" dropdown.
$possible_format_tags = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'pre'];
foreach ($possible_format_tags as $tag) {
$input = '<' . $tag . '>TEST</' . $tag . '>';
$output = trim(check_markup($input, $editor->id()));
if ($input == $output) {
$format_tags[] = $tag;
}
}
$format_tags = implode(';', $format_tags);
// Cache the "format_tags" configuration. This cache item is infinitely
// valid; it only changes whenever the text format is changed, hence it's
// tagged with the text format's cache tag.
$this->cache->set($cid, $format_tags, Cache::PERMANENT, $format->getCacheTags());
}
return $format_tags;
}
/**
......
......@@ -103,9 +103,6 @@ function testGetJSSettings() {
$this->container->get('plugin.manager.editor')->clearCachedDefinitions();
$this->ckeditor = $this->container->get('plugin.manager.editor')->createInstance('ckeditor');
$this->container->get('plugin.manager.ckeditor.plugin')->clearCachedDefinitions();
// KernelTestBase::enableModules() unfortunately doesn't invoke
// hook_rebuild() just like a "real" Drupal site would. Do it manually.
\Drupal::moduleHandler()->invoke('ckeditor', 'rebuild');
$settings = $editor->getSettings();
$settings['toolbar']['rows'][0][0]['items'][] = 'Strike';
$settings['toolbar']['rows'][0][0]['items'][] = 'Format';
......@@ -209,11 +206,6 @@ function testGetJSSettings() {
$expected_config['format_tags'] = 'p';
ksort($expected_config);
$this->assertIdentical($expected_config, $this->ckeditor->getJSSettings($editor), 'Generated JS settings are correct for customized configuration.');
// Assert that we're robust enough to withstand people messing with State
// manually.
\Drupal::state()->delete('ckeditor_internal_format_tags:' . $format->id());
$this->assertIdentical($expected_config, $this->ckeditor->getJSSettings($editor), 'Even when somebody manually deleted the key-value pair in State with the pre-calculated format_tags setting, it returns "p" — because the <p> tag is always allowed.');
}
/**
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment