protected function Internal::generateACFSettings in Drupal 9
Same name and namespace in other branches
- 8 core/modules/ckeditor/src/Plugin/CKEditorPlugin/Internal.php \Drupal\ckeditor\Plugin\CKEditorPlugin\Internal::generateACFSettings()
Builds the ACF part of the CKEditor JS settings.
This ensures that CKEditor obeys the HTML restrictions defined by Drupal's filter system, by enabling CKEditor's Advanced Content Filter (ACF) functionality: http://ckeditor.com/blog/CKEditor-4.1-RC-Released.
Parameters
\Drupal\editor\Entity\Editor $editor: A configured text editor object.
Return value
array An array with two values:
- the first value is the "allowedContent" setting: a well-formatted array or TRUE. The latter indicates that anything is allowed.
- the second value is the "disallowedContent" setting: a well-formatted array or FALSE. The latter indicates that nothing is disallowed.
See also
getConfig()
1 call to Internal::generateACFSettings()
- Internal::getConfig in core/
modules/ ckeditor/ src/ Plugin/ CKEditorPlugin/ Internal.php - Returns the additions to CKEDITOR.config for a specific CKEditor instance.
File
- core/
modules/ ckeditor/ src/ Plugin/ CKEditorPlugin/ Internal.php, line 408
Class
- Internal
- Defines the "internal" plugin (i.e. core plugins part of our CKEditor build).
Namespace
Drupal\ckeditor\Plugin\CKEditorPluginCode
protected function generateACFSettings(Editor $editor) {
// When no text format is associated yet, assume nothing is disallowed, so
// set allowedContent to true.
if (!$editor
->hasAssociatedFilterFormat()) {
return TRUE;
}
$format = $editor
->getFilterFormat();
$filter_types = $format
->getFilterTypes();
// When nothing is disallowed, set allowedContent to true.
if (!in_array(FilterInterface::TYPE_HTML_RESTRICTOR, $filter_types)) {
return [
TRUE,
FALSE,
];
}
else {
$get_attribute_values = function ($attribute_values, $allowed_values) {
$values = array_keys(array_filter($attribute_values, function ($value) use ($allowed_values) {
if ($allowed_values) {
return $value !== FALSE;
}
else {
return $value === FALSE;
}
}));
if (count($values)) {
return implode(',', $values);
}
else {
return NULL;
}
};
$html_restrictions = $format
->getHtmlRestrictions();
// When all HTML is allowed, also set allowedContent to true and
// disallowedContent to false.
if ($html_restrictions === FALSE) {
return [
TRUE,
FALSE,
];
}
$allowed = [];
$disallowed = [];
if (isset($html_restrictions['forbidden_tags'])) {
foreach ($html_restrictions['forbidden_tags'] as $tag) {
$disallowed[$tag] = TRUE;
}
}
foreach ($html_restrictions['allowed'] as $tag => $attributes) {
// Tell CKEditor the tag is allowed, but no attributes.
if ($attributes === FALSE) {
$allowed[$tag] = [
'attributes' => FALSE,
'styles' => FALSE,
'classes' => FALSE,
];
}
elseif ($attributes === TRUE) {
$allowed[$tag] = [
'attributes' => TRUE,
'styles' => TRUE,
'classes' => TRUE,
];
// We've just marked that any value for the "style" and "class"
// attributes is allowed. However, that may not be the case: the "*"
// tag may still apply restrictions.
// Since CKEditor's ACF follows the following principle:
// - Once validated, an element or its property cannot be
// invalidated by another rule.
// That means that the most permissive setting wins. Which means that
// it will still be allowed by CKEditor, for instance, to define any
// style, no matter what the "*" tag's restrictions may be. If there
// is a setting for either the "style" or "class" attribute, it cannot
// possibly be more permissive than what was set above. Hence, inherit
// from the "*" tag where possible.
if (isset($html_restrictions['allowed']['*'])) {
$wildcard = $html_restrictions['allowed']['*'];
if (isset($wildcard['style'])) {
if (!is_array($wildcard['style'])) {
$allowed[$tag]['styles'] = $wildcard['style'];
}
else {
$allowed_styles = $get_attribute_values($wildcard['style'], TRUE);
if (isset($allowed_styles)) {
$allowed[$tag]['styles'] = $allowed_styles;
}
else {
unset($allowed[$tag]['styles']);
}
}
}
if (isset($wildcard['class'])) {
if (!is_array($wildcard['class'])) {
$allowed[$tag]['classes'] = $wildcard['class'];
}
else {
$allowed_classes = $get_attribute_values($wildcard['class'], TRUE);
if (isset($allowed_classes)) {
$allowed[$tag]['classes'] = $allowed_classes;
}
else {
unset($allowed[$tag]['classes']);
}
}
}
}
}
elseif (is_array($attributes)) {
// Set defaults (these will be overridden below if more specific
// values are present).
$allowed[$tag] = [
'attributes' => FALSE,
'styles' => FALSE,
'classes' => FALSE,
];
// Configure allowed attributes, allowed "style" attribute values and
// allowed "class" attribute values.
// CKEditor only allows specific values for the "class" and "style"
// attributes; so ignore restrictions on other attributes, which
// Drupal filters may provide.
// NOTE: A Drupal contrib module can subclass this class, override the
// getConfig() method, and override the JavaScript at
// Drupal.editors.ckeditor to somehow make validation of values for
// attributes other than "class" and "style" work.
$allowed_attributes = array_filter($attributes, function ($value) {
return $value !== FALSE;
});
if (count($allowed_attributes)) {
$allowed[$tag]['attributes'] = implode(',', array_keys($allowed_attributes));
}
if (isset($allowed_attributes['style'])) {
if (is_bool($allowed_attributes['style'])) {
$allowed[$tag]['styles'] = $allowed_attributes['style'];
}
elseif (is_array($allowed_attributes['style'])) {
$allowed_classes = $get_attribute_values($allowed_attributes['style'], TRUE);
if (isset($allowed_classes)) {
$allowed[$tag]['styles'] = $allowed_classes;
}
}
}
if (isset($allowed_attributes['class'])) {
if (is_bool($allowed_attributes['class'])) {
$allowed[$tag]['classes'] = $allowed_attributes['class'];
}
elseif (is_array($allowed_attributes['class'])) {
$allowed_classes = $get_attribute_values($allowed_attributes['class'], TRUE);
if (isset($allowed_classes)) {
$allowed[$tag]['classes'] = $allowed_classes;
}
}
}
// Handle disallowed attributes analogously. However, to handle *dis-
// allowed* attribute values, we must look at *allowed* attributes'
// disallowed attribute values! After all, a disallowed attribute
// implies that all of its possible attribute values are disallowed,
// thus we must look at the disallowed attribute values on allowed
// attributes.
$disallowed_attributes = array_filter($attributes, function ($value) {
return $value === FALSE;
});
if (count($disallowed_attributes)) {
// No need to blacklist the 'class' or 'style' attributes; CKEditor
// handles them separately (if no specific class or style attribute
// values are allowed, then those attributes are disallowed).
if (isset($disallowed_attributes['class'])) {
unset($disallowed_attributes['class']);
}
if (isset($disallowed_attributes['style'])) {
unset($disallowed_attributes['style']);
}
$disallowed[$tag]['attributes'] = implode(',', array_keys($disallowed_attributes));
}
if (isset($allowed_attributes['style']) && is_array($allowed_attributes['style'])) {
$disallowed_styles = $get_attribute_values($allowed_attributes['style'], FALSE);
if (isset($disallowed_styles)) {
$disallowed[$tag]['styles'] = $disallowed_styles;
}
}
if (isset($allowed_attributes['class']) && is_array($allowed_attributes['class'])) {
$disallowed_classes = $get_attribute_values($allowed_attributes['class'], FALSE);
if (isset($disallowed_classes)) {
$disallowed[$tag]['classes'] = $disallowed_classes;
}
}
}
}
ksort($allowed);
ksort($disallowed);
return [
$allowed,
$disallowed,
];
}
}