Issue #3404431 by claudiu.cristea, Wim Leers, borisson_, quietone: Filter settings schema types are incorrect

merge-requests/6260/merge
Dave Long 2024-02-05 09:49:36 +00:00
parent e1312a3d8b
commit d8c4e4cfac
No known key found for this signature in database
GPG Key ID: ED52AE211E142771
8 changed files with 121 additions and 9 deletions

View File

@ -46,14 +46,11 @@ filter.format.*:
label: 'Dependencies'
filter_settings.*:
type: sequence
type: mapping
label: 'Filter settings'
sequence:
type: string
label: 'Value'
filter_settings.filter_html:
type: filter
type: mapping
label: 'Filter HTML'
mapping:
allowed_html:
@ -66,9 +63,8 @@ filter_settings.filter_html:
type: boolean
label: 'HTML nofollow'
filter_settings.filter_url:
type: filter
type: mapping
label: 'Filter URL'
mapping:
filter_url_length:

View File

@ -7,6 +7,7 @@
use Drupal\Core\Config\Entity\ConfigEntityUpdater;
use Drupal\filter\Entity\FilterFormat;
use Drupal\filter\FilterFormatInterface;
/**
* Sorts filter format filter configuration.
@ -19,3 +20,17 @@ function filter_post_update_sort_filters(?array &$sandbox = NULL): void {
return $sorted_filters !== $filters;
});
}
/**
* Change filter_settings to type mapping.
*/
function filter_post_update_consolidate_filter_config(?array &$sandbox = NULL): void {
\Drupal::classResolver(ConfigEntityUpdater::class)->update($sandbox, 'filter_format', function (FilterFormatInterface $format): bool {
foreach ($format->get('filters') as $config) {
if (empty($config['id']) || empty($config['provider'])) {
return TRUE;
}
}
return FALSE;
});
}

View File

@ -208,6 +208,11 @@ class FilterFormat extends ConfigEntityBase implements FilterFormatInterface, En
// read and there is a minimal changeset. If the save is not trusted then
// the configuration will be sorted by StorableConfigBase.
ksort($this->filters);
// Ensure the filter configuration is well-formed.
array_walk($this->filters, function (array &$config, string $filter): void {
$config['id'] ??= $filter;
$config['provider'] ??= $this->filters($filter)->getPluginDefinition()['provider'];
});
}
assert(is_string($this->label()), 'Filter format label is expected to be a string.');

View File

@ -131,6 +131,20 @@ abstract class FilterFormatFormBase extends EntityForm {
'#attributes' => ['class' => ['filter-order-weight']],
];
// Ensure the resulting FilterFormat complies with `type: filter`.
// @see core.data_types.schema.yml
// @see \Drupal\filter\FilterFormatFormBase::submitForm()
$form['filters']['order'][$name]['id'] = [
'#type' => 'value',
'#value' => $filter->getPluginId(),
'#parents' => ['filters', $name, 'id'],
];
$form['filters']['order'][$name]['provider'] = [
'#type' => 'value',
'#value' => $filter->provider,
'#parents' => ['filters', $name, 'provider'],
];
// Retrieve the settings form of the filter plugin. The plugin should not be
// aware of the text format. Therefore, it only receives a set of minimal
// base properties to allow advanced implementations to work.

View File

@ -1,7 +1,7 @@
# Schema for the configuration files of the Filter test module.
filter_settings.filter_test_restrict_tags_and_attributes:
type: filter
type: mapping
label: 'Filter to restrict HTML tags and attributes'
mapping:
restrictions:

View File

@ -0,0 +1,32 @@
<?php
/**
* @file
* Fixture file to test filter_post_update_consolidate_filter_config().
*
* @see https://www.drupal.org/project/drupal/issues/3404431
* @see \Drupal\Tests\filter\Functional\FilterFormatConsolidateFilterConfigUpdateTest
* @see filter_post_update_consolidate_filter_config()
*/
use Drupal\Core\Database\Database;
$db = Database::getConnection();
$format = unserialize($db->select('config')
->fields('config', ['data'])
->condition('collection', '')
->condition('name', 'filter.format.plain_text')
->execute()
->fetchField());
unset($format['filters']['filter_autop']['id']);
unset($format['filters']['filter_html_escape']['provider']);
unset($format['filters']['filter_url']['id']);
unset($format['filters']['filter_url']['provider']);
$db->update('config')
->fields(['data' => serialize($format)])
->condition('collection', '')
->condition('name', 'filter.format.plain_text')
->execute();

View File

@ -0,0 +1,50 @@
<?php
namespace Drupal\Tests\filter\Functional;
use Drupal\FunctionalTests\Update\UpdatePathTestBase;
/**
* Tests the upgrade path for filter formats.
*
* @see filter_post_update_consolidate_filter_config()
*
* @group Update
* @group legacy
*/
class FilterFormatConsolidateFilterConfigUpdateTest extends UpdatePathTestBase {
/**
* {@inheritdoc}
*/
protected function setDatabaseDumpFiles(): void {
$this->databaseDumpFiles = [
__DIR__ . '/../../../../system/tests/fixtures/update/drupal-9.4.0.bare.standard.php.gz',
__DIR__ . '/../../fixtures/update/filter_post_update_consolidate_filter_config-3404431.php',
];
}
/**
* @covers \filter_post_update_consolidate_filter_config
*/
public function testConsolidateFilterConfig() {
$format = $this->config('filter.format.plain_text');
$this->assertArrayNotHasKey('id', $format->get('filters.filter_autop'));
$this->assertSame('filter', $format->get('filters.filter_autop.provider'));
$this->assertSame('filter_html_escape', $format->get('filters.filter_html_escape.id'));
$this->assertArrayNotHasKey('provider', $format->get('filters.filter_html_escape'));
$this->assertArrayNotHasKey('id', $format->get('filters.filter_url'));
$this->assertArrayNotHasKey('provider', $format->get('filters.filter_url'));
$this->runUpdates();
$format = $this->config('filter.format.plain_text');
$this->assertSame('filter_autop', $format->get('filters.filter_autop.id'));
$this->assertSame('filter', $format->get('filters.filter_autop.provider'));
$this->assertSame('filter_html_escape', $format->get('filters.filter_html_escape.id'));
$this->assertSame('filter', $format->get('filters.filter_html_escape.provider'));
$this->assertSame('filter_url', $format->get('filters.filter_url.id'));
$this->assertSame('filter', $format->get('filters.filter_url.provider'));
}
}

View File

@ -119,7 +119,7 @@ media.source.field_aware:
label: 'Source field'
filter_settings.media_embed:
type: filter
type: mapping
label: 'Media Embed'
mapping:
default_view_mode: