toCKEditor5ElementsArray example

'p' => FALSE, '*' => ['foo' => ['b' => TRUE, 'a' => TRUE]], '$text-container' => ['foo' => ['c' => TRUE]]],
    ];
  }

  /** * @covers ::toCKEditor5ElementsArray * @covers ::toFilterHtmlAllowedTagsString * @covers ::toGeneralHtmlSupportConfig * @dataProvider providerRepresentations */
  public function testRepresentations(HTMLRestrictions $restrictions, array $expected_elements_array, string $expected_allowed_html_string, array $expected_ghs_config): void {
    $this->assertSame($expected_elements_array$restrictions->toCKEditor5ElementsArray());
    $this->assertSame($expected_allowed_html_string$restrictions->toFilterHtmlAllowedTagsString());
    $this->assertSame($expected_ghs_config$restrictions->toGeneralHtmlSupportConfig());
  }

  public function providerRepresentations(): \Generator {
    yield 'empty set' => [
      HTMLRestrictions::emptySet(),
      [],
      '',
      [],
    ];

    
$source_editing_before = $source_editing_is_already_enabled
        ? static::getSourceEditingRestrictions($editor_before)
        : HTMLRestrictions::emptySet();
      $source_editing_after = static::getSourceEditingRestrictions($editor_after);
      if ($source_editing_is_already_enabled) {
        // Nothing has been removed from the allowed source editing tags.         $this->assertFalse($source_editing_before->allowsNothing());
        $this->assertTrue($source_editing_before->diff($source_editing_after)
          ->allowsNothing());
      }
      $this->assertSame($expected_source_editing_additions$source_editing_after->diff($source_editing_before)
        ->toCKEditor5ElementsArray());
    }
    // Otherwise verify that sourceEditing configuration remains unchanged.     else {
      if (!$source_editing_is_already_enabled) {
        $this->assertNotContains('sourceEditing', $editor_before->getSettings()['toolbar']['items']);
      }
      else {
        $this->assertContains('sourceEditing', $editor_before->getSettings()['toolbar']['items']);
        $this->assertSame(
          static::getSourceEditingRestrictions($editor_before)->toCKEditor5ElementsArray(),
          static::getSourceEditingRestrictions($editor_after)->toCKEditor5ElementsArray()
        );
$unparseable_lines[$index + 1] = $line;
        continue;
      }

      // Parse selector into tag + classes and normalize.       $tag = $selector_matches[1];
      $classes = array_filter(explode('.', $selector_matches[2]));
      $normalized = HTMLRestrictions::fromString(sprintf('<%s class="%s">', $tagimplode(' ', $classes)));

      $styles[] = [
        'label' => $label,
        'element' => $normalized->toCKEditor5ElementsArray()[0],
      ];
    }
    return [$styles$unparseable_lines];
  }

  /** * {@inheritdoc} */
  public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
    $this->configuration['styles'] = $form_state->getValue('styles');
  }

  
            ->merge($enabled_plugin_restrictions)
            ->diff($enabled_plugin_restrictions);
        }

        // Skip plugins that provide a subset, only mention the plugin that         // actually provides the overlap.         // For example: avoid listing the image alignment/captioning plugins         // when matching `<img src>`; only lists the main image plugin.         if (!$overlap->diff($plugin_capabilities)->allowsNothing()) {
          continue;
        }
        foreach ($plugin_capabilities->intersect($overlap)->toCKEditor5ElementsArray() as $element) {
          $message_array[(string) $definition->label()][] = $element;
        }
      }
    }
    foreach ($message_array as $plugin_label => $tag_list) {
      $tags_string = implode(', ', $tag_list);
      $message_string .= "$plugin_label ($tags_string), ";
    }

    return trim($message_string, ' ,');
  }

}

  private static function validateAllowedRestrictionsPhase5(array $elements): void {
    $conflict = self::findElementsOverridingGloballyDisallowedAttributes($elements);
    if ($conflict) {
      [$globally_disallowed_attribute_restrictions$elements_overriding_globally_disallowed_attributes] = $conflict;
      throw new \InvalidArgumentException(sprintf(
        'The attribute restrictions in "%s" are allowing attributes "%s" that are disallowed by the special "*" global attribute restrictions.',
        implode(' ', (new self($elements_overriding_globally_disallowed_attributes))->toCKEditor5ElementsArray()),
        implode('", "', array_keys($globally_disallowed_attribute_restrictions))
      ));
    }
  }

  /** * Finds elements overriding globally disallowed attributes. * * @param array $elements * The allowed elements. * * @return null|array * NULL if no conflict is found, an array containing otherwise, containing: * - the globally disallowed attribute restrictions * - the elements overriding globally disallowed attributes */
return $form;
  }

  /** * {@inheritdoc} */
  public function validateConfigurationForm(array &$form, FormStateInterface $form_state) {
    // Match the config schema structure at     // ckeditor5.plugin.ckeditor5_sourceEditing.     $form_value = $form_state->getValue('allowed_tags');
    assert(is_string($form_value));
    $config_value = HTMLRestrictions::fromString($form_value)->toCKEditor5ElementsArray();
    $form_state->setValue('allowed_tags', $config_value);
  }

  /** * {@inheritdoc} */
  public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
    $this->configuration['allowed_tags'] = $form_state->getValue('allowed_tags');
  }

  /** * {@inheritdoc} */

      }

      // Generate warning for:       // - The addition of <p>/<br> due to them being fundamental tags.       // - The addition of other tags/attributes previously unsupported by the       // format.       if (!$missing_fundamental_tags->allowsNothing() || !empty($attributes_to_tag) || !empty($added_tags)) {
        $beginning = $this->t('Updating to CKEditor 5 added support for some previously unsupported tags/attributes.');
        $fundamental_tags = '';
        if ($help_enabled && !$missing_fundamental_tags->allowsNothing()) {
          $fundamental_tags = $this->formatPlural(count($missing_fundamental_tags->toCKEditor5ElementsArray()),
            'The @tag tag was added because it is <a target="_blank" href=":fundamental_tag_link">required by CKEditor 5</a>.',
            'The @tag tags were added because they are <a target="_blank" href=":fundamental_tag_link">required by CKEditor 5</a>.',
            [
              '@tag' => implode(', ', $missing_fundamental_tags->toCKEditor5ElementsArray()),
              ':fundamental_tag_link' => URL::fromRoute('help.page', ['name' => 'ckeditor5']['fragment' => 'required-tags'])->toString(),
            ]);
        }
        elseif (!$missing_fundamental_tags->allowsNothing()) {
          $fundamental_tags = $this->formatPlural(count($missing_fundamental_tags->toCKEditor5ElementsArray()),
            'The @tag tag was added because it is required by CKEditor 5.',
            'The @tag tags were added because they are required by CKEditor 5.',
            [

  public function validate($element$constraint) {
    if (!$constraint instanceof CKEditor5ElementConstraint) {
      throw new UnexpectedTypeException($constraint, __NAMESPACE__ . '\CKEditor5Element');
    }

    $parsed = HTMLRestrictions::fromString($element);
    if ($parsed->allowsNothing() || count($parsed->getAllowedElements()) > 1 || $element !== $parsed->toCKEditor5ElementsArray()[0]) {
      $this->context->buildViolation($constraint->message)
        ->setParameter('%provided_element', $element)
        ->addViolation();
    }

    // The optional "requiredAttributes" constraint property allows more     // detailed validation.     if (isset($constraint->requiredAttributes)) {
      $allowed_elements = $parsed->getAllowedElements();
      $tag = array_keys($allowed_elements)[0];
      $attribute_restrictions = $allowed_elements[$tag];
      
      if (!$editor->getImageUploadSettings()['status']) {
        // Add `sourceEditing` toolbar item if it does not already exist.         if (!in_array('sourceEditing', $settings['toolbar']['items'], TRUE)) {
          $settings['toolbar']['items'][] = '|';
          $settings['toolbar']['items'][] = 'sourceEditing';
          // @see \Drupal\ckeditor5\Plugin\CKEditor5Plugin\SourceEditing::defaultConfiguration()           $settings['plugins']['ckeditor5_sourceEditing'] = ['allowed_tags' => []];
        }
        // Update configuration.         $settings['plugins']['ckeditor5_sourceEditing']['allowed_tags'] = HTMLRestrictions::fromString(implode(' ', $settings['plugins']['ckeditor5_sourceEditing']['allowed_tags']))
          ->merge(HTMLRestrictions::fromString('<img data-entity-uuid data-entity-type>'))
          ->toCKEditor5ElementsArray();
      }
      $needs_update = TRUE;
    }
    if ($needs_update) {
      $editor->setSettings($settings);
    }
    return $needs_update;
  };

  $config_entity_updater->update($sandbox, 'editor', $callback);
}

$enabled_plugins = array_keys($this->pluginManager->getEnabledDefinitions($text_editor));
    $provided_elements = $this->pluginManager->getProvidedElements($enabled_plugins$text_editor);
    $provided = new HTMLRestrictions($provided_elements);

    foreach ($html_restrictor_filters as $filter_plugin_id => $filter) {
      $allowed = HTMLRestrictions::fromFilterPluginInstance($filter);
      $diff_allowed = $allowed->diff($provided);
      $diff_elements = $provided->diff($allowed);

      if (!$diff_allowed->allowsNothing()) {
        $this->context->buildViolation($constraint->notSupportedElementsMessage)
          ->setParameter('@list', implode(' ', $provided->toCKEditor5ElementsArray()))
          ->setParameter('@diff', implode(' ', $diff_allowed->toCKEditor5ElementsArray()))
          ->atPath("filters.$filter_plugin_id")
          ->addViolation();
      }

      if (!$diff_elements->allowsNothing()) {
        $this->context->buildViolation($constraint->missingElementsMessage)
          ->setParameter('@list', implode(' ', $provided->toCKEditor5ElementsArray()))
          ->setParameter('@diff', implode(' ', $diff_elements->toCKEditor5ElementsArray()))
          ->atPath("filters.$filter_plugin_id")
          ->addViolation();
      }
$max_supported = $max_supported->merge($concrete_tags_to_use_to_resolve_wildcards)
              ->diff($concrete_tags_to_use_to_resolve_wildcards);
          }
          $not_in_max_supported = $subset_restrictions->diff($max_supported);
          if (!$not_in_max_supported->allowsNothing()) {
            // If the editor is still being configured, the configuration may             // not yet be valid.             if ($editor->isNew()) {
              $subset = [];
            }
            else {
              throw new \LogicException(sprintf('The "%s" CKEditor 5 plugin implements ::getElementsSubset() and did not return a subset, the following tags are absent from the plugin definition: "%s".', $idimplode(' ', $not_in_max_supported->toCKEditor5ElementsArray())));
            }
          }

          // Also detect what is technically a valid subset, but has lost the           // ability to create tags that are still in the subset. This points to           // a bug in the plugin's ::getElementsSubset() logic.           $defined_creatable = HTMLRestrictions::fromString(implode($definition->getCreatableElements()));
          $subset_creatable_actual = HTMLRestrictions::fromString(implode(array_filter($subset[CKEditor5PluginDefinition::class, 'isCreatableElement'])));
          $subset_creatable_needed = $subset_restrictions->extractPlainTagsSubset()
            ->intersect($defined_creatable);
          $missing_creatable_for_subset = $subset_creatable_needed->diff($subset_creatable_actual);
          
public function getElementsSubset(): array {
    $enabled_alignments = $this->configuration['enabled_alignments'];
    $plugin_definition = $this->getPluginDefinition();
    $all_elements = $plugin_definition->getElements();
    $subset = HTMLRestrictions::fromString(implode($all_elements));
    foreach ($plugin_definition->getCKEditor5Config()['alignment']['options'] as $configured_alignment) {
      if (!in_array($configured_alignment['name']$enabled_alignments, TRUE)) {
        $element_string = '<$text-container class=' . '"' . $configured_alignment["className"] . '"' . '>';
        $subset = $subset->diff(HTMLRestrictions::fromString($element_string));
      }
    }
    return $subset->toCKEditor5ElementsArray();
  }

}
// 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);
    }
    else {
      // No update.       $updated_text_format = $text_format;
    }
Home | Imprint | This part of the site doesn't use cookies.