Skip to content

Commit

Permalink
API Remove code which is being migrated to a new TinyMCE module
Browse files Browse the repository at this point in the history
  • Loading branch information
GuySartorelli committed Feb 20, 2025
1 parent 40c015c commit d3eb6c1
Show file tree
Hide file tree
Showing 12 changed files with 266 additions and 1,549 deletions.
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

0 comments on commit d3eb6c1

Please sign in to comment.