HTMLRestrictions example

public function testSurplusScore(HTMLRestrictions $surplus, HTMLRestrictions $needed, int $expected): void {
    $method = self::getMethod(SmartDefaultSettings::class, 'computeSurplusScore');
    $this->assertSame($expected$method->invoke(NULL, $surplus$needed));
  }

  /** * Data provider for testing computeSurplusScore(). * * @return \Generator */
  public function providerSurplusScore(): \Generator {
    $needed = new HTMLRestrictions(['code' => FALSE]);

    yield 'surplus: 1 tag, 1 attribute, 1 attribute with wildcard restriction' => [
      HTMLRestrictions::fromString('<pre> <code class="language-*">'),
      $needed,
      1001010,
    ];

    yield 'surplus: 1 tag, 1 attribute, 2 allowed attribute values' => [
      HTMLRestrictions::fromString('<code class="language-php language-js">'),
      $needed,
      1002,
    ];

  private function checkHtmlRestrictionsAreCompatible(FilterFormatInterface $text_format, FundamentalCompatibilityConstraint $constraint): void {
    $html_restrictions = HTMLRestrictions::fromTextFormat($text_format);
    if ($html_restrictions->isUnrestricted()) {
      return;
    }

    $fundamental = new HTMLRestrictions($this->pluginManager->getProvidedElements(self::FUNDAMENTAL_CKEDITOR5_PLUGINS));
    if (!$fundamental->diff($html_restrictions)->allowsNothing()) {
      $offending_filter = static::findHtmlRestrictorFilterNotAllowingTags($text_format$fundamental);
      $this->context->buildViolation($constraint->nonAllowedElementsMessage)
        ->setParameter('%filter_label', (string) $offending_filter->getLabel())
        ->setParameter('%filter_plugin_id', $offending_filter->getPluginId())
        ->addViolation();
    }
  }

  /** * Checks the HTML restrictions match the enabled CKEditor 5 plugins' output. * * @param \Drupal\editor\EditorInterface $text_editor * The text editor to validate. * @param \Drupal\ckeditor5\Plugin\Validation\Constraint\FundamentalCompatibilityConstraint $constraint * The constraint to validate. */
if (!$style_element->diff($supported_range)->allowsNothing()) {
      $this->context->buildViolation($constraint->nonHtml5TagMessage)
        ->setParameter('@tag', sprintf("<%s>", $tag))
        ->addViolation();
      return;
    }

    // Get the list of tags enabled by every plugin other than Style.     $other_enabled_plugins = $this->getOtherEnabledPlugins($text_editor, 'ckeditor5_style');
    $enableable_disabled_plugins = $this->getEnableableDisabledPlugins($text_editor);

    $other_enabled_plugin_elements = new HTMLRestrictions($this->pluginManager->getProvidedElements(array_keys($other_enabled_plugins)$text_editor, FALSE));
    $disabled_plugin_elements = new HTMLRestrictions($this->pluginManager->getProvidedElements(array_keys($enableable_disabled_plugins)$text_editor, FALSE));

    // Next, validate that the classes specified for this style are not     // supported by an enabled plugin.     if (self::intersectionWithClasses($style_element$other_enabled_plugin_elements)) {
      $this->context->buildViolation($constraint->conflictingEnabledPluginMessage)
        ->setParameter('@tag', sprintf("<%s>", $tag))
        ->setParameter('@classes', implode(", ", $classes))
        ->setParameter('%plugin', $this->findStyleConflictingPluginLabel($style_element))
        ->addViolation();
    }
    
unset($definitions['ckeditor5_arbitraryHtmlSupport']);
    }

    // Evaluate `plugins` condition.     foreach ($definitions_with_plugins_condition as $plugin_id => $definition) {
      if (!empty(array_diff($definition->getConditions()['plugins']array_keys($definitions)))) {
        unset($definitions[$plugin_id]);
      }
    }

    if (!isset($definitions['ckeditor5_arbitraryHtmlSupport'])) {
      $restrictions = new HTMLRestrictions($this->getProvidedElements(array_keys($definitions)$editor, FALSE));
      if ($restrictions->getWildcardSubset()->allowsNothing()) {
        // This is only reached if arbitrary HTML is not enabled. If wildcard         // tags (such as $text-container) are present, they need to         // be resolved via the wildcardHtmlSupport plugin.         // @see \Drupal\ckeditor5\Plugin\CKEditor5PluginManager::getCKEditor5PluginConfig()         unset($definitions['ckeditor5_wildcardHtmlSupport']);
      }
    }
    // When arbitrary HTML is already supported, there is no need to support     // wildcard tags.     else {
      
      $this->addDefaultSettingsForEnabledConfigurablePlugins($editor);
      $this->computeSubsetSettingForEnabledPluginsWithSubsets($editor$text_format);
    }

    // Add toolbar items based on HTML tags and attributes.     // NOTE: Helper updates $editor->settings by reference and returns info for the message.     $result = $this->addToolbarItemsToMatchHtmlElementsInFormat($text_format$editor);
    if ($result !== NULL) {
      [$enabling_message_content$enabled_for_attributes_message_content$missing$plugins_enabled] = $result;

      // Distinguish between unsupported elements covering only tags or not.       $missing_attributes = new HTMLRestrictions(array_filter($missing->getAllowedElements()));
      $unsupported = $missing->diff($missing_attributes);

      if ($enabling_message_content) {
        $this->logger->info('The CKEditor 5 migration enabled the following plugins to support tags that are allowed by the %text_format text format: %enabling_message_content. The text format must be saved to make these changes active.',
          [
            '%text_format' => $editor->getFilterFormat()->get('name'),
            '%enabling_message_content' => $enabling_message_content,
          ]
        );
      }

      
class HTMLRestrictionsTest extends UnitTestCase {

  /** * @covers ::__construct * @dataProvider providerConstruct */
  public function testConstructor(array $elements, ?string $expected_exception_message): void {
    if ($expected_exception_message !== NULL) {
      $this->expectException(\InvalidArgumentException::class);
      $this->expectExceptionMessage($expected_exception_message);
    }
    new HTMLRestrictions($elements);
  }

  public function providerConstruct(): \Generator {
    // Fundamental structure.     yield 'INVALID: list instead of key-value pairs' => [
      ['<foo>', '<bar>'],
      'An array of key-value pairs must be provided, with HTML tag names as keys.',
    ];

    // Invalid HTML tag names.     yield 'INVALID: key-value pairs now, but invalid keys due to angular brackets' => [
      [
if ($definition->hasConditions() && isset($definition->getConditions()['requiresConfiguration'])) {
        $config_enabled_plugins[$id] = TRUE;
      }
    }
    $updated_settings = [
      'plugins' => array_intersect_key($original_settings['plugins']$enabled_plugins + $config_enabled_plugins),
    ] + $original_settings;
    $pair->setSettings($updated_settings);

    if ($pair->getFilterFormat()->filters('filter_html')->status) {
      // Compute elements provided by the current CKEditor 5 settings.       $restrictions = new HTMLRestrictions($this->ckeditor5PluginManager->getProvidedElements(array_keys($enabled_plugins)$pair));

      // Compute eventual filter_html setting. Eventual as in: this is the list       // of eventually allowed HTML tags.       // @see \Drupal\filter\FilterFormatFormBase::submitForm()       // @see ckeditor5_form_filter_format_form_alter()       $filter_html_config = $pair->getFilterFormat()->filters('filter_html')->getConfiguration();
      $filter_html_config['settings']['allowed_html'] = $restrictions->toFilterHtmlAllowedTagsString();
      $pair->getFilterFormat()->setFilterConfig('filter_html', $filter_html_config);
    }

    return $pair;
  }

  public function toFilterHtmlAllowedTagsString(): string {
    // Resolve wildcard tags, because Drupal's filter_html filter plugin does     // not support those.     $concrete = self::resolveWildcards($this);
    // The filter_html plugin does not allow configuring additional globally     // allowed or disallowed attributes. It uses a hardcoded list.     $concrete = new HTMLRestrictions(array_diff_key($concrete->getAllowedElements(FALSE)['*' => NULL]));
    return implode(' ', $concrete->toCKEditor5ElementsArray());
  }

  /** * Transforms into the CKEditor 5 GHS configuration representation. * * @return string[] * An array of allowed elements, structured in the manner expected by the * CKEditor 5 htmlSupport plugin constructor. * * @see https://ckeditor5.github.io/docs/nightly/ckeditor5/latest/features/general-html-support.html#configuration * @see https://ckeditor5.github.io/docs/nightly/ckeditor5/latest/api/module_engine_view_matcher-MatcherPattern.html */
'format' => 'dummy',
      'name' => 'dummy',
    ])->save();
    $this->assertConfigSchema(
      $this->typedConfig,
      $text_editor->getConfigDependencyName(),
      $text_editor->toArray()
    );

    $provided_elements = $this->manager->getProvidedElements($plugins$text_editor);
    $this->assertSame($expected_elements$provided_elements);
    $this->assertSame($expected_readable_string(new HTMLRestrictions($provided_elements))->toFilterHtmlAllowedTagsString());
  }

  /** * Provides uses cases enabling different elements and the expected results. */
  public function providerTestProvidedElements(): array {
    $text_align_classes = [
      'text-align-left' => TRUE,
      'text-align-center' => TRUE,
      'text-align-right' => TRUE,
      'text-align-justify' => TRUE,
    ];
    if (isset($violations[''])) {
      unset($violations['']);
    }
    $this->assertSame([]$violations);

    // If the text format has HTML restrictions, ensure that a strict superset     // is allowed after switching to CKEditor 5.     $html_restrictions = $text_format->getHtmlRestrictions();
    if (is_array($html_restrictions) && array_key_exists('allowed', $html_restrictions)) {
      $allowed_tags = HTMLRestrictions::fromTextFormat($text_format);
      $enabled_plugins = array_keys($this->manager->getEnabledDefinitions($updated_text_editor));
      $updated_allowed_tags = new HTMLRestrictions($this->manager->getProvidedElements($enabled_plugins$updated_text_editor));
      $unsupported_tags_attributes = $allowed_tags->diff($updated_allowed_tags);
      $superset_tags_attributes = $updated_allowed_tags->diff($allowed_tags);
      $this->assertSame($expected_superset$superset_tags_attributes->toFilterHtmlAllowedTagsString());
      $this->assertTrue($unsupported_tags_attributes->allowsNothing(), "The following tags/attributes are not allowed in the updated text format:" . implode(' ', $unsupported_tags_attributes->toCKEditor5ElementsArray()));

      // Update the text format like ckeditor5_form_filter_format_form_alter()       // would.       $updated_text_format = clone $text_format;
      $filter_html_config = $text_format->filters('filter_html')->getConfiguration();
      $filter_html_config['settings']['allowed_html'] = $updated_allowed_tags->toFilterHtmlAllowedTagsString();
      $updated_text_format->setFilterConfig('filter_html', $filter_html_config);
    }

    if (empty($value)) {
      return;
    }

    $text_editor = $this->createTextEditorObjectFromContext();

    $other_enabled_plugins = $this->getOtherEnabledPlugins($text_editor, 'ckeditor5_sourceEditing');
    $enableable_disabled_plugins = $this->getEnableableDisabledPlugins($text_editor);

    // An array of tags enabled by every plugin other than Source Editing.     $enabled_plugin_elements = new HTMLRestrictions($this->pluginManager->getProvidedElements(array_keys($other_enabled_plugins)$text_editor, FALSE));
    $disabled_plugin_elements = new HTMLRestrictions($this->pluginManager->getProvidedElements(array_keys($enableable_disabled_plugins)$text_editor, FALSE));
    $enabled_plugin_plain_tags = new HTMLRestrictions($this->pluginManager->getProvidedElements(array_keys($other_enabled_plugins)$text_editor, FALSE, TRUE));
    $disabled_plugin_plain_tags = new HTMLRestrictions($this->pluginManager->getProvidedElements(array_keys($enableable_disabled_plugins)$text_editor, FALSE, TRUE));

    // The single element for which source editing is enabled, which we are     // checking now.     $source_enabled_element = HTMLRestrictions::fromString($value);
    // Test for empty allowed elements with resolved wildcards since, for the     // purposes of this validator, HTML restrictions containing only wildcards     // should be considered empty.     // @todo Remove this early return in
Home | Imprint | This part of the site doesn't use cookies.