Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

API Remove code which is being migrated to a new TinyMCE module #11617

Draft
wants to merge 1 commit into
base: 6.0
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 0 additions & 22 deletions _config/html.yml

This file was deleted.

34 changes: 34 additions & 0 deletions src/Forms/HTMLEditor/AttributeRule.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

namespace SilverStripe\Forms\HTMLEditor;

use DOMAttr;

class AttributeRule
{
public string $name;

public array $validValues = [];

public ?string $defaultValue = null;

public ?string $forcedValue = null;

public bool $required = false;

public function __construct(string $name)
{
$this->name = $name;
}

public function attributeIsAllowed(DOMAttr $attribute): bool
{
// If the rule has a set of valid values, check them to see if this attribute has one
if (isset($this->validValues) && !in_array($attribute->value, $this->validValues ?? [])) {
return false;
}

// No further tests required, attribute passes
return true;
}
}
98 changes: 98 additions & 0 deletions src/Forms/HTMLEditor/ElementRule.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
<?php

namespace SilverStripe\Forms\HTMLEditor;

use DOMAttr;
use DOMElement;

class ElementRule // @TODO maybe we should have an ElementRules instead? And elementIsAllowed() checks against all rules for that element in the list?
{
public string $name;
// @TODO
// Special "@" element (global rules)
// e.g. "-b" - what's the prefix?
// is ~ prefix handled? Used to be : prefix
// What about any other special characters?

/**
* @todo
* example
* [
* 'id' => ?????? (they're stdClass rn for some reason?? Looks like it's related to "required/default/forced"
* ]
* @var AttributeRule[]
*/
public array $attributes = [];

/**
* Undocumented variable
*
* @var AttributeRule[]
*/
public array $attributePatterns; //@TODO what's that?

public $attributesRequired = []; //@TODO what's that?

public $attributesDefault = []; //@TODO what's that?

public $attributesForced = []; //@TODO what's that?

public bool $paddEmpty = false; //@TODO what's that?

public bool $removeEmpty = false; //@TODO what's that?

public string $outputName = ''; //@TODO what's that?

// @TODO incl bool or enum or something for "is negation" i.e. some elements may be explicitly NOT allowed

public function __construct(string $name)
{
$this->name = $name;
}

public function elementIsAllowed(DOMElement $element): bool
{
// @TODO consider whether to check the element type matches??
// If the rule has attributes required, check them to see if this element has at least one
if ($this->attributesRequired) {
$hasMatch = false;

foreach ($this->attributesRequired as $attr) {
if ($element->getAttribute($attr)) {
$hasMatch = true;
break;
}
}

if (!$hasMatch) {
return false;
}
}

// If the rule says to remove empty elements, and this element is empty, remove it
if ($this->removeEmpty && !$element->firstChild) {
return false;
}

// No further tests required, element passes
return true;
}

public function attributeIsAllowed(DOMAttr $attribute): bool
{
return $this->getRuleForAttribute($attribute->name)?->attributeIsAllowed($attribute);
}

private function getRuleForAttribute(string $name): AttributeRule
{
if (isset($this->attributes[$name])) {
return $this->attributes[$name];
}
foreach ($this->attributePatterns as $attributeRule) {
if (preg_match($attributeRule->name, $name)) { // @TODO maybe name isn't right for pattern?
return $attributeRule;
}
}
return null;
}
}
51 changes: 50 additions & 1 deletion src/Forms/HTMLEditor/HTMLEditorConfig.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@

namespace SilverStripe\Forms\HTMLEditor;

use LogicException;
use SilverStripe\Core\Config\Config;
use SilverStripe\Core\Config\Configurable;
use SilverStripe\Core\Injector\Injectable;

/**
* A PHP version of TinyMCE's configuration, to allow various parameters to be configured on a site or section basis
* A generic API for WYSIWYG editor configuration, to allow various parameters to be configured on a site or section basis
*
* There can be multiple HTMLEditorConfig's, which should always be created / accessed using HTMLEditorConfig::get.
* You can then set the currently active config using set_active.
Expand Down Expand Up @@ -60,13 +61,27 @@ abstract class HTMLEditorConfig
*/
private static $user_themes = [];

/**
* The height for the editable portion of editor in number of rows.
* Null means use the default for whichever WYSIWYG library is active.
*/
private static ?int $fixed_row_height = 20;

/**
* List of the current themes set for this config
*
* @var array
*/
protected static $current_themes = null;

/**
* The name of the client-side component to inject for fields using this config.
* Must be overridden in subclasses to a valid component name.
*/
protected string $schemaComponent = '';// @TODO find out what to set this to to get a regular textarea

private ?int $rows = null;

/**
* Get the HTMLEditorConfig object for the given identifier. This is a correct way to get an HTMLEditorConfig
* instance - do not call 'new'
Expand Down Expand Up @@ -227,6 +242,22 @@ abstract public function getAttributes();
*/
abstract public function init();

/**
* Get the element rules for server-side sanitisation.
*/
abstract public function getElementRuleSet(): HtmlEditorRuleSet;

/**
* Get the name of the client-side component to inject for fields using this config
*/
public function getSchemaComponent(): string
{
if (!$this->schemaComponent) {
throw new LogicException('schemaComponent must be set on ' . static::class);
}
return $this->schemaComponent;
}

/**
* Provide additional schema data for the field this object configures
*
Expand All @@ -239,4 +270,22 @@ public function getConfigSchemaData()
'editorjs' => null,
];
}

/**
* Get the number of rows this config will use in its editable area.
*/
public function getRows(): ?int
{
return $this->rows;
}

/**
* Set the number of rows this config will use in its editable area.
* This is set by HTMLEditorField - set the number of rows in your field.
*/
public function setRows(int $numRows): static
{
$this->rows = $numRows;
return $this;
}
}
40 changes: 16 additions & 24 deletions src/Forms/HTMLEditor/HTMLEditorField.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
use SilverStripe\View\Parsers\HTMLValue;

/**
* A TinyMCE-powered WYSIWYG HTML editor field with image and link insertion and tracking capabilities. Editor fields
* A WYSIWYG HTML editor field with image and link insertion and tracking capabilities. Editor fields
* are created from `<textarea>` tags, which are then converted with JavaScript.
*
* Caution: The form field does not include any JavaScript or CSS when used outside of the CMS context,
Expand All @@ -29,7 +29,7 @@ class HTMLEditorField extends TextareaField

protected $schemaDataType = FormField::SCHEMA_DATA_TYPE_HTML;

protected $schemaComponent = 'HtmlEditorField';
protected $schemaComponent = 'HtmlEditorField';// @TODO probably just remove from here since we don't use this anymore

/**
* @config
Expand All @@ -53,13 +53,6 @@ class HTMLEditorField extends TextareaField
*/
private static $default_rows = 20;

/**
* Extra height per row
*
* @var int
*/
private static $fixed_row_height = 20;

/**
* ID or instance of editorconfig
*
Expand Down Expand Up @@ -95,6 +88,11 @@ public function setEditorConfig($config)
return $this;
}

public function getSchemaComponent()
{
return $this->getEditorConfig()->getSchemaComponent();
}

/**
* Creates a new HTMLEditorField.
* @see TextareaField::__construct()
Expand Down Expand Up @@ -136,13 +134,13 @@ public function saveInto(DataObjectInterface $record)

// Sanitise if requested
$htmlValue = HTMLValue::create($this->getValue());
if (HTMLEditorField::config()->sanitise_server_side) {
if (static::config()->get('sanitise_server_side')) {
$config = $this->getEditorConfig();
$santiser = HTMLEditorSanitiser::create($config);
$santiser->sanitise($htmlValue);
}

// optionally manipulate the HTML after a TinyMCE edit and prior to a save
// optionally manipulate the HTML prior to storing it on the record
$this->extend('processHTML', $htmlValue);

// Store into record
Expand Down Expand Up @@ -205,22 +203,16 @@ public function getFormattedValueEntities(): string
}

/**
* Set height of editor based on number of rows
* Set height of editor based on number of rows.
*
* This uses a clone because different HMTLEditorField instances may use different number of rows
* and the config is a singleton.
*/
private function setEditorHeight(HTMLEditorConfig $config): HTMLEditorConfig
{
$rowHeight = $this->config()->get('fixed_row_height');
if ($rowHeight && ($config instanceof TinyMCEConfig)) {
$rows = (int) $this->getRows();
$height = $rows * $rowHeight;
$config = clone $config;
if ($height) {
$config->setOption('height', 'auto');
$config->setOption('row_height', sprintf('%dpx', $height));
}
}

return $config;
$clone = clone $config;
$clone->setRows($this->rows);
return $clone;
}

private function usesXmlFriendlyField(DataObjectInterface $record): bool
Expand Down
Loading
Loading