first commit
This commit is contained in:
387
plugins/editors/tinymce/forms/setoptions.xml
Normal file
387
plugins/editors/tinymce/forms/setoptions.xml
Normal file
@ -0,0 +1,387 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<form>
|
||||
|
||||
<field
|
||||
name="access"
|
||||
type="usergrouplist"
|
||||
label="PLG_TINY_FIELD_SETACCESS_LABEL"
|
||||
multiple="true"
|
||||
class="access-select"
|
||||
labelclass="h3"
|
||||
layout="joomla.form.field.list-fancy-select"
|
||||
/>
|
||||
|
||||
<fieldset name="basic">
|
||||
<field
|
||||
name="skins"
|
||||
type="note"
|
||||
label="PLG_TINY_FIELD_SKIN_INFO_LABEL"
|
||||
description="PLG_TINY_FIELD_SKIN_INFO_DESC"
|
||||
/>
|
||||
|
||||
<field
|
||||
name="skin"
|
||||
type="folderlist"
|
||||
label="PLG_TINY_FIELD_SKIN_LABEL"
|
||||
directory="media/vendor/tinymce/skins/ui"
|
||||
recursive="false"
|
||||
hide_none="true"
|
||||
validate="options"
|
||||
/>
|
||||
|
||||
<field
|
||||
name="skin_admin"
|
||||
type="folderlist"
|
||||
label="PLG_TINY_FIELD_SKIN_ADMIN_LABEL"
|
||||
directory="media/vendor/tinymce/skins/ui"
|
||||
recursive="false"
|
||||
hide_none="true"
|
||||
validate="options"
|
||||
/>
|
||||
|
||||
<field
|
||||
name="toolbar_mode"
|
||||
type="list"
|
||||
label="PLG_TINY_FIELD_TOOLBAR_MODE_LABEL"
|
||||
default="sliding"
|
||||
validate="options"
|
||||
>
|
||||
<option value="floating">PLG_TINY_FIELD_VALUE_FLOATING</option>
|
||||
<option value="scrolling">PLG_TINY_FIELD_VALUE_SCROLLING</option>
|
||||
<option value="sliding">PLG_TINY_FIELD_VALUE_SLIDING</option>
|
||||
<option value="wrap">PLG_TINY_FIELD_VALUE_WRAP</option>
|
||||
</field>
|
||||
|
||||
<field
|
||||
name="drag_drop"
|
||||
type="radio"
|
||||
label="PLG_TINY_FIELD_DRAG_DROP_LABEL"
|
||||
layout="joomla.form.field.radio.switcher"
|
||||
default="1"
|
||||
>
|
||||
<option value="0">JOFF</option>
|
||||
<option value="1">JON</option>
|
||||
</field>
|
||||
|
||||
<field
|
||||
name="path"
|
||||
type="uploaddirs"
|
||||
label="PLG_TINY_FIELD_CUSTOM_PATH_LABEL"
|
||||
showon="drag_drop:1"
|
||||
/>
|
||||
|
||||
<field
|
||||
name="content_template_path"
|
||||
type="templateslist"
|
||||
label="PLG_TINY_FIELD_CUSTOM_CONTENT_TEMPLATE_PATH_LABEL"
|
||||
description="PLG_TINY_FIELD_CUSTOM_CONTENT_TEMPLATE_PATH_DESC"
|
||||
default=""
|
||||
folderFilter="^tinymce"
|
||||
validate="options"
|
||||
/>
|
||||
|
||||
<field
|
||||
name="entity_encoding"
|
||||
type="list"
|
||||
label="PLG_TINY_FIELD_ENCODING_LABEL"
|
||||
default="raw"
|
||||
validate="options"
|
||||
>
|
||||
<option value="named">PLG_TINY_FIELD_VALUE_NAMED</option>
|
||||
<option value="numeric">PLG_TINY_FIELD_VALUE_NUMERIC</option>
|
||||
<option value="raw">PLG_TINY_FIELD_VALUE_RAW</option>
|
||||
</field>
|
||||
|
||||
<field
|
||||
name="lang_mode"
|
||||
type="radio"
|
||||
label="PLG_TINY_FIELD_LANGSELECT_LABEL"
|
||||
layout="joomla.form.field.radio.switcher"
|
||||
default="1"
|
||||
>
|
||||
<option value="0">JOFF</option>
|
||||
<option value="1">JON</option>
|
||||
</field>
|
||||
|
||||
<field
|
||||
name="lang_code"
|
||||
type="filelist"
|
||||
label="PLG_TINY_FIELD_LANGCODE_LABEL"
|
||||
stripext="1"
|
||||
directory="media/vendor/tinymce/langs/"
|
||||
hide_none="1"
|
||||
hide_default="1"
|
||||
fileFilter="\.js$"
|
||||
exclude="\.min\.js$"
|
||||
showon="lang_mode:0"
|
||||
validate="options"
|
||||
>
|
||||
<option value="">en</option>
|
||||
</field>
|
||||
|
||||
<field
|
||||
name="text_direction"
|
||||
type="list"
|
||||
label="PLG_TINY_FIELD_DIRECTION_LABEL"
|
||||
default="ltr"
|
||||
validate="options"
|
||||
>
|
||||
<option value="ltr">PLG_TINY_FIELD_VALUE_LTR</option>
|
||||
<option value="rtl">PLG_TINY_FIELD_VALUE_RTL</option>
|
||||
</field>
|
||||
|
||||
<field
|
||||
name="content_css"
|
||||
type="radio"
|
||||
label="PLG_TINY_FIELD_CSS_LABEL"
|
||||
description="PLG_TINY_FIELD_CSS_DESC"
|
||||
layout="joomla.form.field.radio.switcher"
|
||||
default="1"
|
||||
>
|
||||
<option value="0">JOFF</option>
|
||||
<option value="1">JON</option>
|
||||
</field>
|
||||
|
||||
<field
|
||||
name="content_css_custom"
|
||||
type="text"
|
||||
label="PLG_TINY_FIELD_CUSTOM_CSS_LABEL"
|
||||
description="PLG_TINY_FIELD_CUSTOM_CSS_DESC"
|
||||
/>
|
||||
|
||||
<field
|
||||
name="relative_urls"
|
||||
type="list"
|
||||
label="PLG_TINY_FIELD_URLS_LABEL"
|
||||
default="1"
|
||||
validate="options"
|
||||
>
|
||||
<option value="0">PLG_TINY_FIELD_VALUE_ABSOLUTE</option>
|
||||
<option value="1">PLG_TINY_FIELD_VALUE_RELATIVE</option>
|
||||
</field>
|
||||
|
||||
<field
|
||||
name="newlines"
|
||||
type="list"
|
||||
label="PLG_TINY_FIELD_NEWLINES_LABEL"
|
||||
default="0"
|
||||
validate="options"
|
||||
>
|
||||
<option value="1">PLG_TINY_FIELD_VALUE_BR</option>
|
||||
<option value="0">PLG_TINY_FIELD_VALUE_P</option>
|
||||
</field>
|
||||
|
||||
<field
|
||||
name="use_config_textfilters"
|
||||
type="radio"
|
||||
label="PLG_TINY_CONFIG_TEXTFILTER_ACL_LABEL"
|
||||
layout="joomla.form.field.radio.switcher"
|
||||
default="0"
|
||||
>
|
||||
<option value="0">JOFF</option>
|
||||
<option value="1">JON</option>
|
||||
</field>
|
||||
|
||||
<field
|
||||
name="invalid_elements"
|
||||
type="text"
|
||||
label="PLG_TINY_FIELD_PROHIBITED_LABEL"
|
||||
showon="use_config_textfilters:0"
|
||||
default="script,applet,iframe"
|
||||
/>
|
||||
|
||||
<field
|
||||
name="valid_elements"
|
||||
type="text"
|
||||
label="PLG_TINY_FIELD_VALIDELEMENTS_LABEL"
|
||||
description="PLG_TINY_FIELD_VALIDELEMENTS_DESC"
|
||||
showon="use_config_textfilters:0"
|
||||
/>
|
||||
|
||||
<field
|
||||
name="extended_elements"
|
||||
type="text"
|
||||
label="PLG_TINY_FIELD_ELEMENTS_LABEL"
|
||||
showon="use_config_textfilters:0"
|
||||
/>
|
||||
|
||||
<!-- Extra plugins -->
|
||||
<field
|
||||
name="resizing"
|
||||
type="radio"
|
||||
label="PLG_TINY_FIELD_RESIZING_LABEL"
|
||||
layout="joomla.form.field.radio.switcher"
|
||||
default="1"
|
||||
>
|
||||
<option value="0">JOFF</option>
|
||||
<option value="1">JON</option>
|
||||
</field>
|
||||
|
||||
<field
|
||||
name="resize_horizontal"
|
||||
type="radio"
|
||||
label="PLG_TINY_FIELD_RESIZE_HORIZONTAL_LABEL"
|
||||
layout="joomla.form.field.radio.switcher"
|
||||
default="1"
|
||||
showon="resizing:1"
|
||||
>
|
||||
<option value="0">JOFF</option>
|
||||
<option value="1">JON</option>
|
||||
</field>
|
||||
|
||||
<field
|
||||
name="element_path"
|
||||
type="radio"
|
||||
label="PLG_TINY_FIELD_PATH_LABEL"
|
||||
layout="joomla.form.field.radio.switcher"
|
||||
default="0"
|
||||
>
|
||||
<option value="0">JOFF</option>
|
||||
<option value="1">JON</option>
|
||||
</field>
|
||||
|
||||
<field
|
||||
name="wordcount"
|
||||
type="radio"
|
||||
label="PLG_TINY_FIELD_WORDCOUNT_LABEL"
|
||||
layout="joomla.form.field.radio.switcher"
|
||||
default="1"
|
||||
>
|
||||
<option value="0">JOFF</option>
|
||||
<option value="1">JON</option>
|
||||
</field>
|
||||
|
||||
<field
|
||||
name="textpattern"
|
||||
type="radio"
|
||||
label="PLG_TINY_FIELD_TEXTPATTERN_LABEL"
|
||||
description="PLG_TINY_FIELD_TEXTPATTERN_DESC"
|
||||
layout="joomla.form.field.radio.switcher"
|
||||
default="0"
|
||||
>
|
||||
<option value="0">JOFF</option>
|
||||
<option value="1">JON</option>
|
||||
</field>
|
||||
|
||||
<field
|
||||
name="image_advtab"
|
||||
type="radio"
|
||||
label="PLG_TINY_FIELD_ADVIMAGE_LABEL"
|
||||
layout="joomla.form.field.radio.switcher"
|
||||
default="1"
|
||||
>
|
||||
<option value="0">JOFF</option>
|
||||
<option value="1">JON</option>
|
||||
</field>
|
||||
|
||||
<field
|
||||
name="advlist"
|
||||
type="radio"
|
||||
label="PLG_TINY_FIELD_ADVLIST_LABEL"
|
||||
layout="joomla.form.field.radio.switcher"
|
||||
default="1"
|
||||
>
|
||||
<option value="0">JOFF</option>
|
||||
<option value="1">JON</option>
|
||||
</field>
|
||||
|
||||
<field
|
||||
name="contextmenu"
|
||||
type="radio"
|
||||
label="PLG_TINY_FIELD_CONTEXTMENU_LABEL"
|
||||
layout="joomla.form.field.radio.switcher"
|
||||
default="1"
|
||||
>
|
||||
<option value="0">JOFF</option>
|
||||
<option value="1">JON</option>
|
||||
</field>
|
||||
|
||||
<field
|
||||
name="paste_as_text"
|
||||
type="radio"
|
||||
label="PLG_TINY_FIELD_PASTE_AS_TEXT_LABEL"
|
||||
layout="joomla.form.field.radio.switcher"
|
||||
default="0"
|
||||
>
|
||||
<option value="0">JOFF</option>
|
||||
<option value="1">JON</option>
|
||||
</field>
|
||||
|
||||
<field
|
||||
name="sourcecode"
|
||||
type="radio"
|
||||
label="PLG_TINY_FIELD_SOURCECODE_LABEL"
|
||||
layout="joomla.form.field.radio.switcher"
|
||||
default="1"
|
||||
>
|
||||
<option value="0">JOFF</option>
|
||||
<option value="1">JON</option>
|
||||
</field>
|
||||
|
||||
<field
|
||||
name="content_languages"
|
||||
type="subform"
|
||||
label="PLG_TINY_FIELD_CONTENTLANGS_LABEL"
|
||||
description="PLG_TINY_FIELD_CONTENTLANGS_DESC"
|
||||
layout="joomla.form.field.subform.repeatable-table"
|
||||
icon="list"
|
||||
multiple="true"
|
||||
default=''
|
||||
>
|
||||
<form hidden="true" name="content_languages" repeat="true">
|
||||
<field
|
||||
name="content_language_name"
|
||||
type="text"
|
||||
label="PLG_TINY_FIELD_CONTENTLANGUAGE_LABEL"
|
||||
size="30"
|
||||
filter="string"
|
||||
/>
|
||||
|
||||
<field
|
||||
name="content_language_code"
|
||||
type="text"
|
||||
label="PLG_TINY_FIELD_CONTENTCODE_LABEL"
|
||||
size="10"
|
||||
filter="string"
|
||||
/>
|
||||
</form>
|
||||
</field>
|
||||
|
||||
<field
|
||||
name="custom_plugin"
|
||||
type="text"
|
||||
label="PLG_TINY_FIELD_CUSTOMPLUGIN_LABEL"
|
||||
/>
|
||||
|
||||
<field
|
||||
name="custom_button"
|
||||
type="text"
|
||||
label="PLG_TINY_FIELD_CUSTOMBUTTON_LABEL"
|
||||
/>
|
||||
|
||||
<field
|
||||
name="external_plugins"
|
||||
type="subform"
|
||||
label="PLG_TINY_FIELD_EXTERNALPLUGINS_LABEL"
|
||||
description="PLG_TINY_FIELD_EXTERNALPLUGINS_DESC"
|
||||
layout="joomla.form.field.subform.repeatable-table"
|
||||
icon="list"
|
||||
multiple="true"
|
||||
>
|
||||
<form hidden="true" name="list_templates_modal" repeat="true">
|
||||
<field
|
||||
name="name"
|
||||
type="text"
|
||||
label="PLG_TINY_FIELD_EXTERNALPLUGINS_NAME_LABEL"
|
||||
/>
|
||||
|
||||
<field
|
||||
name="path"
|
||||
type="text"
|
||||
label="PLG_TINY_FIELD_EXTERNALPLUGINS_PATH_LABEL"
|
||||
/>
|
||||
</form>
|
||||
</field>
|
||||
|
||||
</fieldset>
|
||||
</form>
|
||||
48
plugins/editors/tinymce/services/provider.php
Normal file
48
plugins/editors/tinymce/services/provider.php
Normal file
@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Plugin
|
||||
* @subpackage Editors.tinymce
|
||||
*
|
||||
* @copyright (C) 2023 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
\defined('_JEXEC') or die;
|
||||
|
||||
use Joomla\CMS\Extension\PluginInterface;
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\Plugin\PluginHelper;
|
||||
use Joomla\Database\DatabaseInterface;
|
||||
use Joomla\DI\Container;
|
||||
use Joomla\DI\ServiceProviderInterface;
|
||||
use Joomla\Event\DispatcherInterface;
|
||||
use Joomla\Plugin\Editors\TinyMCE\Extension\TinyMCE;
|
||||
|
||||
return new class () implements ServiceProviderInterface {
|
||||
/**
|
||||
* Registers the service provider with a DI container.
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 4.3.0
|
||||
*/
|
||||
public function register(Container $container)
|
||||
{
|
||||
$container->set(
|
||||
PluginInterface::class,
|
||||
function (Container $container) {
|
||||
$plugin = new TinyMCE(
|
||||
$container->get(DispatcherInterface::class),
|
||||
(array) PluginHelper::getPlugin('editors', 'tinymce')
|
||||
);
|
||||
$plugin->setApplication(Factory::getApplication());
|
||||
$plugin->setDatabase($container->get(DatabaseInterface::class));
|
||||
|
||||
return $plugin;
|
||||
}
|
||||
);
|
||||
}
|
||||
};
|
||||
118
plugins/editors/tinymce/src/Extension/TinyMCE.php
Normal file
118
plugins/editors/tinymce/src/Extension/TinyMCE.php
Normal file
@ -0,0 +1,118 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Plugin
|
||||
* @subpackage Editors.tinymce
|
||||
*
|
||||
* @copyright (C) 2006 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Plugin\Editors\TinyMCE\Extension;
|
||||
|
||||
use Joomla\CMS\Event\Editor\EditorSetupEvent;
|
||||
use Joomla\CMS\Filesystem\Folder;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\Plugin\CMSPlugin;
|
||||
use Joomla\CMS\Session\Session;
|
||||
use Joomla\Database\DatabaseAwareTrait;
|
||||
use Joomla\Event\SubscriberInterface;
|
||||
use Joomla\Plugin\Editors\TinyMCE\PluginTraits\KnownButtons;
|
||||
use Joomla\Plugin\Editors\TinyMCE\PluginTraits\ToolbarPresets;
|
||||
use Joomla\Plugin\Editors\TinyMCE\Provider\TinyMCEProvider;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* TinyMCE Editor Plugin
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
final class TinyMCE extends CMSPlugin implements SubscriberInterface
|
||||
{
|
||||
use DatabaseAwareTrait;
|
||||
|
||||
// @todo: KnownButtons, ToolbarPresets for backward compatibility. Remove in Joomla 6
|
||||
use KnownButtons;
|
||||
use ToolbarPresets;
|
||||
|
||||
/**
|
||||
* Returns an array of events this subscriber will listen to.
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @since 5.0.0
|
||||
*/
|
||||
public static function getSubscribedEvents(): array
|
||||
{
|
||||
return ['onEditorSetup' => 'onEditorSetup'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Register Editor instance
|
||||
*
|
||||
* @param EditorSetupEvent $event
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 5.0.0
|
||||
*/
|
||||
public function onEditorSetup(EditorSetupEvent $event)
|
||||
{
|
||||
$this->loadLanguage();
|
||||
|
||||
$event->getEditorsRegistry()
|
||||
->add(new TinyMCEProvider($this->params, $this->getApplication(), $this->getDispatcher(), $this->getDatabase()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the templates
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 5.0.0
|
||||
*/
|
||||
public function onAjaxTinymce()
|
||||
{
|
||||
if (!Session::checkToken('request')) {
|
||||
echo json_encode([]);
|
||||
exit();
|
||||
}
|
||||
|
||||
$this->loadLanguage();
|
||||
|
||||
$templates = [];
|
||||
$language = $this->getApplication()->getLanguage();
|
||||
$template = $this->getApplication()->getInput()->getPath('template', '');
|
||||
|
||||
if ('' === $template) {
|
||||
echo json_encode([]);
|
||||
exit();
|
||||
}
|
||||
|
||||
$filepaths = Folder::exists(JPATH_ROOT . '/templates/' . $template)
|
||||
? Folder::files(JPATH_ROOT . '/templates/' . $template, '\.(html|txt)$', false, true)
|
||||
: [];
|
||||
|
||||
foreach ($filepaths as $filepath) {
|
||||
$fileinfo = pathinfo($filepath);
|
||||
$filename = $fileinfo['filename'];
|
||||
$title_upper = strtoupper($filename);
|
||||
|
||||
if ($filename === 'index') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$templates[] = (object) [
|
||||
'title' => $language->hasKey('PLG_TINY_TEMPLATE_' . $title_upper . '_TITLE') ? Text::_('PLG_TINY_TEMPLATE_' . $title_upper . '_TITLE') : $filename,
|
||||
'description' => $language->hasKey('PLG_TINY_TEMPLATE_' . $title_upper . '_DESC') ? Text::_('PLG_TINY_TEMPLATE_' . $title_upper . '_DESC') : ' ',
|
||||
'content' => file_get_contents($filepath),
|
||||
];
|
||||
}
|
||||
|
||||
echo json_encode($templates);
|
||||
exit();
|
||||
}
|
||||
}
|
||||
95
plugins/editors/tinymce/src/Field/TemplateslistField.php
Normal file
95
plugins/editors/tinymce/src/Field/TemplateslistField.php
Normal file
@ -0,0 +1,95 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Plugin
|
||||
* @subpackage Editors.tinymce
|
||||
*
|
||||
* @copyright (C) 2021 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Plugin\Editors\TinyMCE\Field;
|
||||
|
||||
use Joomla\CMS\Form\Field\FolderlistField;
|
||||
use Joomla\CMS\HTML\HTMLHelper;
|
||||
use Joomla\CMS\Language\Text;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Generates the list of directories available for template snippets.
|
||||
*
|
||||
* @since 4.1.0
|
||||
*/
|
||||
class TemplatesListField extends FolderlistField
|
||||
{
|
||||
protected $type = 'templatesList';
|
||||
|
||||
/**
|
||||
* Method to attach a JForm object to the field.
|
||||
*
|
||||
* @param \SimpleXMLElement $element The SimpleXMLElement object representing the `<field>` tag for the form field object.
|
||||
* @param mixed $value The form field value to validate.
|
||||
* @param string $group The field name group control value. This acts as an array container for the field.
|
||||
* For example if the field has name="foo" and the group value is set to "bar" then the
|
||||
* full field name would end up being "bar[foo]".
|
||||
*
|
||||
* @return boolean True on success.
|
||||
*
|
||||
* @see \Joomla\CMS\Form\FormField::setup()
|
||||
* @since 4.1.0
|
||||
*/
|
||||
public function setup(\SimpleXMLElement $element, $value, $group = null)
|
||||
{
|
||||
$return = parent::setup($element, $value, $group);
|
||||
|
||||
// Set some defaults.
|
||||
$this->recursive = true;
|
||||
$this->hideDefault = true;
|
||||
$this->exclude = 'system';
|
||||
$this->hideNone = true;
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get the directories options.
|
||||
*
|
||||
* @return array The dirs option objects.
|
||||
*
|
||||
* @since 4.1.0
|
||||
*/
|
||||
public function getOptions()
|
||||
{
|
||||
$def = new \stdClass();
|
||||
$def->value = '';
|
||||
$def->text = Text::_('JOPTION_DO_NOT_USE');
|
||||
$options = [0 => $def];
|
||||
$this->directory = JPATH_ROOT . '/templates';
|
||||
|
||||
return array_merge($options, parent::getOptions());
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get the field input markup for the list of directories.
|
||||
*
|
||||
* @return string The field input markup.
|
||||
*
|
||||
* @since 4.1.0
|
||||
*/
|
||||
protected function getInput()
|
||||
{
|
||||
return HTMLHelper::_(
|
||||
'select.genericlist',
|
||||
(array) $this->getOptions(),
|
||||
$this->name,
|
||||
'class="form-select"',
|
||||
'value',
|
||||
'text',
|
||||
$this->value,
|
||||
$this->id
|
||||
);
|
||||
}
|
||||
}
|
||||
174
plugins/editors/tinymce/src/Field/TinymcebuilderField.php
Normal file
174
plugins/editors/tinymce/src/Field/TinymcebuilderField.php
Normal file
@ -0,0 +1,174 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Plugin
|
||||
* @subpackage Editors.tinymce
|
||||
*
|
||||
* @copyright (C) 2016 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Plugin\Editors\TinyMCE\Field;
|
||||
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\Form\Form;
|
||||
use Joomla\CMS\Form\FormField;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\Plugin\PluginHelper;
|
||||
use Joomla\Plugin\Editors\TinyMCE\Provider\TinyMCEProvider;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Form Field class for the TinyMCE editor.
|
||||
*
|
||||
* @package Joomla.Plugin
|
||||
* @subpackage Editors.tinymce
|
||||
* @since 3.7.0
|
||||
*/
|
||||
class TinymcebuilderField extends FormField
|
||||
{
|
||||
/**
|
||||
* The form field type.
|
||||
*
|
||||
* @var string
|
||||
* @since 3.7.0
|
||||
*/
|
||||
protected $type = 'tinymcebuilder';
|
||||
|
||||
/**
|
||||
* Name of the layout being used to render the field
|
||||
*
|
||||
* @var string
|
||||
* @since 3.7.0
|
||||
*/
|
||||
protected $layout = 'plugins.editors.tinymce.field.tinymcebuilder';
|
||||
|
||||
/**
|
||||
* The prepared layout data
|
||||
*
|
||||
* @var array
|
||||
* @since 3.7.0
|
||||
*/
|
||||
protected $layoutData = [];
|
||||
|
||||
/**
|
||||
* Method to get the data to be passed to the layout for rendering.
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @since 3.7.0
|
||||
*/
|
||||
protected function getLayoutData()
|
||||
{
|
||||
if (!empty($this->layoutData)) {
|
||||
return $this->layoutData;
|
||||
}
|
||||
|
||||
$data = parent::getLayoutData();
|
||||
$paramsAll = (object) $this->form->getValue('params');
|
||||
$setsAmount = empty($paramsAll->sets_amount) ? 3 : $paramsAll->sets_amount;
|
||||
|
||||
if (empty($data['value'])) {
|
||||
$data['value'] = [];
|
||||
}
|
||||
|
||||
$menus = [
|
||||
'edit' => ['label' => 'Edit'],
|
||||
'insert' => ['label' => 'Insert'],
|
||||
'view' => ['label' => 'View'],
|
||||
'format' => ['label' => 'Format'],
|
||||
'table' => ['label' => 'Table'],
|
||||
'tools' => ['label' => 'Tools'],
|
||||
'help' => ['label' => 'Help'],
|
||||
];
|
||||
|
||||
$data['menus'] = $menus;
|
||||
$data['menubarSource'] = array_keys($menus);
|
||||
$data['buttons'] = TinyMCEProvider::getKnownButtons();
|
||||
$data['buttonsSource'] = array_keys($data['buttons']);
|
||||
$data['toolbarPreset'] = TinyMCEProvider::getToolbarPreset();
|
||||
$data['setsAmount'] = $setsAmount;
|
||||
|
||||
// Get array of sets names
|
||||
for ($i = 0; $i < $setsAmount; $i++) {
|
||||
$data['setsNames'][$i] = Text::sprintf('PLG_TINY_SET_TITLE', $i);
|
||||
}
|
||||
|
||||
// Prepare the forms for each set
|
||||
$setsForms = [];
|
||||
$formsource = JPATH_PLUGINS . '/editors/tinymce/forms/setoptions.xml';
|
||||
|
||||
// Preload an old params for B/C
|
||||
$setParams = new \stdClass();
|
||||
|
||||
if (!empty($paramsAll->html_width) && empty($paramsAll->configuration['setoptions'])) {
|
||||
$plugin = PluginHelper::getPlugin('editors', 'tinymce');
|
||||
|
||||
Factory::getApplication()->enqueueMessage(Text::sprintf('PLG_TINY_LEGACY_WARNING', '#'), 'warning');
|
||||
|
||||
if (\is_object($plugin) && !empty($plugin->params)) {
|
||||
$setParams = (object) json_decode($plugin->params);
|
||||
}
|
||||
}
|
||||
|
||||
// Collect already used groups
|
||||
$groupsInUse = [];
|
||||
|
||||
// Prepare the Set forms, for the set options
|
||||
foreach (array_keys($data['setsNames']) as $num) {
|
||||
$formname = 'set.form.' . $num;
|
||||
$control = $this->name . '[setoptions][' . $num . ']';
|
||||
|
||||
$setsForms[$num] = Form::getInstance($formname, $formsource, ['control' => $control]);
|
||||
|
||||
// Check whether we already have saved values or it first time or even old params
|
||||
if (empty($this->value['setoptions'][$num])) {
|
||||
$formValues = $setParams;
|
||||
|
||||
/*
|
||||
* Predefine group:
|
||||
* Set 0: for Administrator, Editor, Super Users (4,7,8)
|
||||
* Set 1: for Registered, Manager (2,6), all else are public
|
||||
*/
|
||||
$formValues->access = !$num ? [4, 7, 8] : ($num === 1 ? [2, 6] : []);
|
||||
|
||||
// Assign Public to the new Set, but only when it not in use already
|
||||
if (empty($formValues->access) && !\in_array(1, $groupsInUse)) {
|
||||
$formValues->access = [1];
|
||||
}
|
||||
} else {
|
||||
$formValues = (object) $this->value['setoptions'][$num];
|
||||
}
|
||||
|
||||
// Collect already used groups
|
||||
if (!empty($formValues->access)) {
|
||||
$groupsInUse = array_merge($groupsInUse, $formValues->access);
|
||||
}
|
||||
|
||||
// Bind the values
|
||||
$setsForms[$num]->bind($formValues);
|
||||
}
|
||||
|
||||
$data['setsForms'] = $setsForms;
|
||||
|
||||
// Check for TinyMCE language file
|
||||
$language = Factory::getLanguage();
|
||||
$languageFile1 = 'media/vendor/tinymce/langs/' . $language->getTag() . (JDEBUG ? '.js' : '.min.js');
|
||||
$languageFile2 = 'media/vendor/tinymce/langs/' . substr($language->getTag(), 0, strpos($language->getTag(), '-')) . (JDEBUG ? '.js' : '.min.js');
|
||||
|
||||
$data['languageFile'] = '';
|
||||
|
||||
if (file_exists(JPATH_ROOT . '/' . $languageFile1)) {
|
||||
$data['languageFile'] = $languageFile1;
|
||||
} elseif (file_exists(JPATH_ROOT . '/' . $languageFile2)) {
|
||||
$data['languageFile'] = $languageFile2;
|
||||
}
|
||||
|
||||
$this->layoutData = $data;
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
94
plugins/editors/tinymce/src/Field/UploaddirsField.php
Normal file
94
plugins/editors/tinymce/src/Field/UploaddirsField.php
Normal file
@ -0,0 +1,94 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Plugin
|
||||
* @subpackage Editors.tinymce
|
||||
*
|
||||
* @copyright (C) 2017 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Plugin\Editors\TinyMCE\Field;
|
||||
|
||||
use Joomla\CMS\Component\ComponentHelper;
|
||||
use Joomla\CMS\Form\Field\FolderlistField;
|
||||
use Joomla\CMS\HTML\HTMLHelper;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Generates the list of directories available for drag and drop upload.
|
||||
*
|
||||
* @package Joomla.Plugin
|
||||
* @subpackage Editors.tinymce
|
||||
* @since 3.7.0
|
||||
*/
|
||||
class UploaddirsField extends FolderlistField
|
||||
{
|
||||
protected $type = 'uploaddirs';
|
||||
|
||||
/**
|
||||
* Method to attach a JForm object to the field.
|
||||
*
|
||||
* @param \SimpleXMLElement $element The SimpleXMLElement object representing the `<field>` tag for the form field object.
|
||||
* @param mixed $value The form field value to validate.
|
||||
* @param string $group The field name group control value. This acts as an array container for the field.
|
||||
* For example if the field has name="foo" and the group value is set to "bar" then the
|
||||
* full field name would end up being "bar[foo]".
|
||||
*
|
||||
* @return boolean True on success.
|
||||
*
|
||||
* @see \Joomla\CMS\Form\FormField::setup()
|
||||
* @since 3.7.0
|
||||
*/
|
||||
public function setup(\SimpleXMLElement $element, $value, $group = null)
|
||||
{
|
||||
$return = parent::setup($element, $value, $group);
|
||||
|
||||
// Get the path in which to search for file options.
|
||||
$this->directory = JPATH_ROOT . '/' . ComponentHelper::getParams('com_media')->get('image_path');
|
||||
$this->recursive = true;
|
||||
$this->hideDefault = true;
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get the directories options.
|
||||
*
|
||||
* @return array The dirs option objects.
|
||||
*
|
||||
* @since 3.7.0
|
||||
*/
|
||||
public function getOptions()
|
||||
{
|
||||
return parent::getOptions();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get the field input markup for the list of directories.
|
||||
*
|
||||
* @return string The field input markup.
|
||||
*
|
||||
* @since 3.7.0
|
||||
*/
|
||||
protected function getInput()
|
||||
{
|
||||
$html = [];
|
||||
|
||||
// Get the field options.
|
||||
$options = (array) $this->getOptions();
|
||||
|
||||
// Reset the non selected value to null
|
||||
if ($options[0]->value === '-1') {
|
||||
$options[0]->value = '';
|
||||
}
|
||||
|
||||
// Create a regular list.
|
||||
$html[] = HTMLHelper::_('select.genericlist', $options, $this->name, 'class="form-select"', 'value', 'text', $this->value, $this->id);
|
||||
|
||||
return implode($html);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Plugin
|
||||
* @subpackage Editors.tinymce
|
||||
*
|
||||
* @copyright (C) 2021 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Plugin\Editors\TinyMCE\PluginTraits;
|
||||
|
||||
use Joomla\CMS\Language\Text;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Gets the active Site template style.
|
||||
*
|
||||
* @since 4.1.0
|
||||
*/
|
||||
trait ActiveSiteTemplate
|
||||
{
|
||||
/**
|
||||
* Helper function to get the active Site template style.
|
||||
*
|
||||
* @return object
|
||||
*
|
||||
* @since 4.1.0
|
||||
*/
|
||||
protected function getActiveSiteTemplate()
|
||||
{
|
||||
$db = $this->getDatabase();
|
||||
$query = $db->getQuery(true)
|
||||
->select('*')
|
||||
->from($db->quoteName('#__template_styles'))
|
||||
->where(
|
||||
[
|
||||
$db->quoteName('client_id') . ' = 0',
|
||||
$db->quoteName('home') . ' = ' . $db->quote('1'),
|
||||
]
|
||||
);
|
||||
|
||||
$db->setQuery($query);
|
||||
|
||||
try {
|
||||
return $db->loadObject();
|
||||
} catch (\RuntimeException $e) {
|
||||
$this->getApplication()->enqueueMessage(Text::_('JERROR_AN_ERROR_HAS_OCCURRED'), 'error');
|
||||
|
||||
return new \stdClass();
|
||||
}
|
||||
}
|
||||
}
|
||||
509
plugins/editors/tinymce/src/PluginTraits/DisplayTrait.php
Normal file
509
plugins/editors/tinymce/src/PluginTraits/DisplayTrait.php
Normal file
@ -0,0 +1,509 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Plugin
|
||||
* @subpackage Editors.tinymce
|
||||
*
|
||||
* @copyright (C) 2021 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Plugin\Editors\TinyMCE\PluginTraits;
|
||||
|
||||
use Joomla\CMS\Filesystem\Folder;
|
||||
use Joomla\CMS\Filter\InputFilter;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\Layout\LayoutHelper;
|
||||
use Joomla\CMS\Session\Session;
|
||||
use Joomla\CMS\Uri\Uri;
|
||||
use Joomla\Registry\Registry;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Handles the onDisplay event for the TinyMCE editor.
|
||||
*
|
||||
* @since 4.1.0
|
||||
*/
|
||||
trait DisplayTrait
|
||||
{
|
||||
use GlobalFilters;
|
||||
use KnownButtons;
|
||||
use ResolveFiles;
|
||||
use ToolbarPresets;
|
||||
use XTDButtons;
|
||||
|
||||
/**
|
||||
* Gets the editor HTML markup
|
||||
*
|
||||
* @param string $name Input name.
|
||||
* @param string $content The content of the field.
|
||||
* @param array $attributes Associative array of editor attributes.
|
||||
* @param array $params Associative array of editor parameters.
|
||||
*
|
||||
* @return string The HTML markup of the editor
|
||||
*
|
||||
* @since 5.0.0
|
||||
*/
|
||||
public function display(string $name, string $content = '', array $attributes = [], array $params = []): string
|
||||
{
|
||||
// General variables
|
||||
$app = $this->application;
|
||||
$user = $app->getIdentity();
|
||||
$language = $app->getLanguage();
|
||||
$doc = $app->getDocument();
|
||||
$wa = $doc->getWebAssetManager();
|
||||
$options = $doc->getScriptOptions('plg_editor_tinymce');
|
||||
$csrf = Session::getFormToken();
|
||||
|
||||
// Editor variables
|
||||
$col = $attributes['col'] ?? '';
|
||||
$row = $attributes['row'] ?? '';
|
||||
$width = $attributes['width'] ?? '';
|
||||
$height = $attributes['height'] ?? '';
|
||||
$id = $attributes['id'] ?? $name;
|
||||
$id = preg_replace('/(\s|[^A-Za-z0-9_])+/', '_', $id);
|
||||
$nameGroup = explode('[', preg_replace('/\[\]|\]/', '', $name));
|
||||
$fieldName = end($nameGroup);
|
||||
$buttons = $params['buttons'] ?? true;
|
||||
$asset = $params['asset'] ?? 0;
|
||||
$author = $params['author'] ?? 0;
|
||||
$scriptOptions = [];
|
||||
$externalPlugins = [];
|
||||
$theme = 'silver';
|
||||
|
||||
// Register assets
|
||||
$wa->getRegistry()->addExtensionRegistryFile('plg_editors_tinymce');
|
||||
|
||||
// Data object for the layout
|
||||
$textarea = new \stdClass();
|
||||
$textarea->name = $name;
|
||||
$textarea->id = $id;
|
||||
$textarea->class = 'mce_editable joomla-editor-tinymce';
|
||||
$textarea->cols = $col;
|
||||
$textarea->rows = $row;
|
||||
$textarea->width = is_numeric($width) ? $width . 'px' : $width;
|
||||
$textarea->height = is_numeric($height) ? $height . 'px' : $height;
|
||||
$textarea->content = $content;
|
||||
$textarea->readonly = !empty($params['readonly']);
|
||||
|
||||
// Render Editor markup
|
||||
$editor = '<div class="js-editor-tinymce">';
|
||||
$editor .= LayoutHelper::render('joomla.tinymce.textarea', $textarea);
|
||||
$editor .= !$app->client->mobile ? LayoutHelper::render('joomla.tinymce.togglebutton') : '';
|
||||
$editor .= '</div>';
|
||||
|
||||
// Prepare the instance specific options
|
||||
if (empty($options['tinyMCE'][$fieldName])) {
|
||||
$options['tinyMCE'][$fieldName] = [];
|
||||
}
|
||||
|
||||
// Width and height
|
||||
if ($width && empty($options['tinyMCE'][$fieldName]['width'])) {
|
||||
$options['tinyMCE'][$fieldName]['width'] = $width;
|
||||
}
|
||||
|
||||
if ($height && empty($options['tinyMCE'][$fieldName]['height'])) {
|
||||
$options['tinyMCE'][$fieldName]['height'] = $height;
|
||||
}
|
||||
|
||||
// Set editor to readonly mode
|
||||
if (!empty($params['readonly'])) {
|
||||
$options['tinyMCE'][$fieldName]['readonly'] = 1;
|
||||
}
|
||||
|
||||
// The ext-buttons
|
||||
if (empty($options['tinyMCE'][$fieldName]['joomlaExtButtons'])) {
|
||||
$tinyButtons = $this->tinyButtons($buttons, ['asset' => $asset, 'author' => $author, 'editorId' => $id]);
|
||||
|
||||
$options['tinyMCE'][$fieldName]['joomlaMergeDefaults'] = true;
|
||||
$options['tinyMCE'][$fieldName]['joomlaExtButtons'] = $tinyButtons;
|
||||
}
|
||||
|
||||
$doc->addScriptOptions('plg_editor_tinymce', $options, false);
|
||||
|
||||
// Setup Default (common) options for all Editor instances
|
||||
// Check whether we already have them
|
||||
if (!empty($options['tinyMCE']['default'])) {
|
||||
return $editor;
|
||||
}
|
||||
|
||||
$ugroups = array_combine($user->getAuthorisedGroups(), $user->getAuthorisedGroups());
|
||||
|
||||
// Prepare the parameters
|
||||
$levelParams = new Registry();
|
||||
$extraOptions = new \stdClass();
|
||||
$toolbarParams = new \stdClass();
|
||||
$extraOptionsAll = (array) $this->params->get('configuration.setoptions', []);
|
||||
$toolbarParamsAll = (array) $this->params->get('configuration.toolbars', []);
|
||||
|
||||
// Sort the array in reverse, so the items with the lowest access level goes first
|
||||
krsort($extraOptionsAll);
|
||||
|
||||
// Get configuration depend from User group
|
||||
foreach ($extraOptionsAll as $set => $val) {
|
||||
$val = (object) $val;
|
||||
$val->access = empty($val->access) ? [] : $val->access;
|
||||
|
||||
// Check whether User in one of allowed group
|
||||
foreach ($val->access as $group) {
|
||||
if (isset($ugroups[$group])) {
|
||||
$extraOptions = $val;
|
||||
$toolbarParams = (object) $toolbarParamsAll[$set];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// load external plugins
|
||||
if (isset($extraOptions->external_plugins) && $extraOptions->external_plugins) {
|
||||
foreach (json_decode(json_encode($extraOptions->external_plugins), true) as $external) {
|
||||
// get the path for readability
|
||||
$path = $external['path'];
|
||||
|
||||
// if we have a name and path, add it to the list
|
||||
if ($external['name'] != '' && $path != '') {
|
||||
$externalPlugins[$external['name']] = substr($path, 0, 1) == '/' ? Uri::root() . substr($path, 1) : $path;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Merge the params
|
||||
$levelParams->loadObject($toolbarParams);
|
||||
$levelParams->loadObject($extraOptions);
|
||||
|
||||
// Set the selected skin
|
||||
$skin = $levelParams->get($app->isClient('administrator') ? 'skin_admin' : 'skin', 'oxide');
|
||||
|
||||
// Check that selected skin exists.
|
||||
$skin = Folder::exists(JPATH_ROOT . '/media/vendor/tinymce/skins/ui/' . $skin) ? $skin : 'oxide';
|
||||
|
||||
if (!$levelParams->get('lang_mode', 1)) {
|
||||
// Admin selected language
|
||||
$langPrefix = $levelParams->get('lang_code', 'en');
|
||||
} else {
|
||||
// Reflect the current language
|
||||
if (file_exists(JPATH_ROOT . '/media/vendor/tinymce/langs/' . $language->getTag() . '.js')) {
|
||||
$langPrefix = $language->getTag();
|
||||
} elseif (file_exists(JPATH_ROOT . '/media/vendor/tinymce/langs/' . substr($language->getTag(), 0, strpos($language->getTag(), '-')) . '.js')) {
|
||||
$langPrefix = substr($language->getTag(), 0, strpos($language->getTag(), '-'));
|
||||
} else {
|
||||
$langPrefix = 'en';
|
||||
}
|
||||
}
|
||||
|
||||
$use_content_css = $levelParams->get('content_css', 1);
|
||||
$content_css_custom = $levelParams->get('content_css_custom', '');
|
||||
$content_css = null;
|
||||
|
||||
// Loading of css file for 'styles' dropdown
|
||||
if ($content_css_custom) {
|
||||
/**
|
||||
* If URL, just pass it to $content_css
|
||||
* else, assume it is a file name in the current template folder
|
||||
*/
|
||||
$content_css = strpos($content_css_custom, 'http') !== false
|
||||
? $content_css_custom
|
||||
: $this->includeRelativeFiles('css', $content_css_custom);
|
||||
} else {
|
||||
// Process when use_content_css is Yes and no custom file given
|
||||
$content_css = $use_content_css ? $this->includeRelativeFiles('css', 'editor' . (JDEBUG ? '' : '.min') . '.css') : $content_css;
|
||||
}
|
||||
|
||||
$ignore_filter = false;
|
||||
|
||||
// Text filtering
|
||||
if ($levelParams->get('use_config_textfilters', 0)) {
|
||||
// Use filters from com_config
|
||||
$filter = static::getGlobalFilters($user);
|
||||
$ignore_filter = $filter === false;
|
||||
$blockedTags = !empty($filter->blockedTags) ? $filter->blockedTags : [];
|
||||
$blockedAttributes = !empty($filter->blockedAttributes) ? $filter->blockedAttributes : [];
|
||||
$tagArray = !empty($filter->tagsArray) ? $filter->tagsArray : [];
|
||||
$attrArray = !empty($filter->attrArray) ? $filter->attrArray : [];
|
||||
$invalid_elements = implode(',', array_merge($blockedTags, $blockedAttributes, $tagArray, $attrArray));
|
||||
|
||||
// Valid elements are all entries listed as allowed in com_config, which are now missing in the filter blocked properties
|
||||
$default_filter = InputFilter::getInstance();
|
||||
$valid_elements = implode(',', array_diff($default_filter->blockedTags, $blockedTags));
|
||||
|
||||
$extended_elements = '';
|
||||
} else {
|
||||
// Use filters from TinyMCE params
|
||||
$invalid_elements = trim($levelParams->get('invalid_elements', 'script,applet,iframe'));
|
||||
$extended_elements = trim($levelParams->get('extended_elements', ''));
|
||||
$valid_elements = trim($levelParams->get('valid_elements', ''));
|
||||
}
|
||||
|
||||
// The param is true for vertical resizing only, false or both
|
||||
$resizing = (bool) $levelParams->get('resizing', true);
|
||||
$resize_horizontal = (bool) $levelParams->get('resize_horizontal', true);
|
||||
|
||||
if ($resizing && $resize_horizontal) {
|
||||
$resizing = 'both';
|
||||
}
|
||||
|
||||
// Set of always available plugins
|
||||
$plugins = [
|
||||
'autolink',
|
||||
'lists',
|
||||
'importcss',
|
||||
'quickbars',
|
||||
'jxtdbuttons',
|
||||
];
|
||||
$wa->useScript('plg_editors_tinymce.jxtdbuttons');
|
||||
|
||||
// Allowed elements
|
||||
$elements = [
|
||||
'hr[id|title|alt|class|width|size|noshade]',
|
||||
];
|
||||
$elements = $extended_elements ? array_merge($elements, explode(',', $extended_elements)) : $elements;
|
||||
|
||||
// Prepare the toolbar/menubar
|
||||
$knownButtons = static::getKnownButtons();
|
||||
|
||||
// Check if there no value at all
|
||||
if (!$levelParams->get('menu') && !$levelParams->get('toolbar1') && !$levelParams->get('toolbar2')) {
|
||||
// Get from preset
|
||||
$presets = static::getToolbarPreset();
|
||||
|
||||
/**
|
||||
* Predefine group as:
|
||||
* Set 0: for Administrator, Editor, Super Users (4,7,8)
|
||||
* Set 1: for Registered, Manager (2,6), all else are public
|
||||
*/
|
||||
switch (true) {
|
||||
case isset($ugroups[4]) || isset($ugroups[7]) || isset($ugroups[8]):
|
||||
$preset = $presets['advanced'];
|
||||
break;
|
||||
|
||||
case isset($ugroups[2]) || isset($ugroups[6]):
|
||||
$preset = $presets['medium'];
|
||||
break;
|
||||
|
||||
default:
|
||||
$preset = $presets['simple'];
|
||||
}
|
||||
|
||||
$levelParams->loadArray($preset);
|
||||
}
|
||||
|
||||
$menubar = (array) $levelParams->get('menu', []);
|
||||
$toolbar1 = (array) $levelParams->get('toolbar1', []);
|
||||
$toolbar2 = (array) $levelParams->get('toolbar2', []);
|
||||
|
||||
// Make an easy way to check which button is enabled
|
||||
$allButtons = array_merge($toolbar1, $toolbar2);
|
||||
$allButtons = array_combine($allButtons, $allButtons);
|
||||
|
||||
// Check for button-specific plugins
|
||||
foreach ($allButtons as $btnName) {
|
||||
if (!empty($knownButtons[$btnName]['plugin'])) {
|
||||
$plugins[] = $knownButtons[$btnName]['plugin'];
|
||||
}
|
||||
}
|
||||
|
||||
// Check for extra plugins, from the setoptions form
|
||||
foreach (['wordcount' => 1, 'advlist' => 1, 'autosave' => 1] as $pName => $def) {
|
||||
if ($levelParams->get($pName, $def)) {
|
||||
$plugins[] = $pName;
|
||||
}
|
||||
}
|
||||
|
||||
// Use CodeMirror in the code view instead of plain text to provide syntax highlighting
|
||||
if ($levelParams->get('sourcecode', 1)) {
|
||||
// Enable joomla-highlighter plugin
|
||||
$wa->getRegistry()->addExtensionRegistryFile('plg_editors_codemirror');
|
||||
$wa->useScript('plg_editors_tinymce.highlighter');
|
||||
$plugins[] = 'joomlaHighlighter';
|
||||
}
|
||||
|
||||
$dragdrop = $levelParams->get('drag_drop', 1);
|
||||
|
||||
if ($dragdrop && $user->authorise('core.create', 'com_media')) {
|
||||
$wa->useScript('plg_editors_tinymce.jdragndrop');
|
||||
$plugins[] = 'jdragndrop';
|
||||
$uploadUrl = Uri::base(true) . '/index.php?option=com_media&format=json&url=1&task=api.files';
|
||||
|
||||
Text::script('PLG_TINY_ERR_UNSUPPORTEDBROWSER');
|
||||
Text::script('ERROR');
|
||||
Text::script('PLG_TINY_DND_ADDITIONALDATA');
|
||||
Text::script('PLG_TINY_DND_ALTTEXT');
|
||||
Text::script('PLG_TINY_DND_LAZYLOADED');
|
||||
Text::script('PLG_TINY_DND_EMPTY_ALT');
|
||||
|
||||
$scriptOptions['parentUploadFolder'] = $levelParams->get('path', '');
|
||||
$scriptOptions['csrfToken'] = $csrf;
|
||||
$scriptOptions['uploadUri'] = $uploadUrl;
|
||||
|
||||
// @TODO have a way to select the adapter, similar to $levelParams->get('path', '');
|
||||
$scriptOptions['comMediaAdapter'] = 'local-images:';
|
||||
}
|
||||
|
||||
// Convert pt to px in dropdown
|
||||
$scriptOptions['font_size_formats'] = '8px 10px 12px 14px 18px 24px 36px';
|
||||
|
||||
// select the languages for the "language of parts" menu
|
||||
if (isset($extraOptions->content_languages) && $extraOptions->content_languages) {
|
||||
foreach (json_decode(json_encode($extraOptions->content_languages), true) as $content_language) {
|
||||
// if we have a language name and a language code then add to the menu
|
||||
if ($content_language['content_language_name'] != '' && $content_language['content_language_code'] != '') {
|
||||
$ctemp[] = ['title' => $content_language['content_language_name'], 'code' => $content_language['content_language_code']];
|
||||
}
|
||||
}
|
||||
if (isset($ctemp)) {
|
||||
$scriptOptions['content_langs'] = array_merge($ctemp);
|
||||
}
|
||||
}
|
||||
|
||||
// Should load the template plugin?
|
||||
if (!empty($allButtons['jtemplate'])) {
|
||||
$wa->useScript('plg_editors_tinymce.jtemplate');
|
||||
$plugins[] = 'jtemplate';
|
||||
|
||||
$scriptOptions['jtemplates'] = Uri::base(true) . '/index.php?option=com_ajax&plugin=tinymce&group=editors&format=json&format=json&template='
|
||||
. $levelParams->get('content_template_path') . '&' . $csrf . '=1';
|
||||
}
|
||||
|
||||
// User custom plugins and buttons
|
||||
$custom_plugin = trim($levelParams->get('custom_plugin', ''));
|
||||
$custom_button = trim($levelParams->get('custom_button', ''));
|
||||
|
||||
if ($custom_plugin) {
|
||||
$plugins = array_merge($plugins, explode(strpos($custom_plugin, ',') !== false ? ',' : ' ', $custom_plugin));
|
||||
}
|
||||
|
||||
if ($custom_button) {
|
||||
$toolbar1 = array_merge($toolbar1, explode(strpos($custom_button, ',') !== false ? ',' : ' ', $custom_button));
|
||||
}
|
||||
|
||||
// Merge the two toolbars for backwards compatibility
|
||||
$toolbar = array_merge($toolbar1, $toolbar2);
|
||||
|
||||
// Build the final options set
|
||||
$scriptOptions = array_merge(
|
||||
$scriptOptions,
|
||||
[
|
||||
'suffix' => JDEBUG ? '' : '.min',
|
||||
'baseURL' => Uri::root(true) . '/media/vendor/tinymce',
|
||||
'directionality' => $language->isRtl() ? 'rtl' : 'ltr',
|
||||
'language' => $langPrefix,
|
||||
'autosave_restore_when_empty' => false,
|
||||
'skin' => $skin,
|
||||
'theme' => $theme,
|
||||
'schema' => 'html5',
|
||||
|
||||
// Prevent cursor from getting stuck in blocks when nested or at end of document.
|
||||
'end_container_on_empty_block' => true,
|
||||
|
||||
// Toolbars
|
||||
'menubar' => empty($menubar) ? false : implode(' ', array_unique($menubar)),
|
||||
'toolbar' => empty($toolbar) ? null : 'jxtdbuttons ' . implode(' ', $toolbar),
|
||||
|
||||
'plugins' => implode(',', array_unique($plugins)),
|
||||
|
||||
// Quickbars
|
||||
'quickbars_image_toolbar' => false,
|
||||
'quickbars_insert_toolbar' => false,
|
||||
'quickbars_selection_toolbar' => 'bold italic underline | H2 H3 | link blockquote',
|
||||
|
||||
// Cleanup/Output
|
||||
'browser_spellcheck' => true,
|
||||
'entity_encoding' => $levelParams->get('entity_encoding', 'raw'),
|
||||
'verify_html' => !$ignore_filter,
|
||||
'paste_as_text' => (bool) $levelParams->get('paste_as_text', false),
|
||||
|
||||
'valid_elements' => $valid_elements,
|
||||
'extended_valid_elements' => implode(',', $elements),
|
||||
'invalid_elements' => $invalid_elements,
|
||||
|
||||
// URL
|
||||
'relative_urls' => (bool) $levelParams->get('relative_urls', true),
|
||||
'remove_script_host' => false,
|
||||
|
||||
// Drag and drop Images always FALSE, reverting this allows for inlining the images
|
||||
'paste_data_images' => false,
|
||||
|
||||
// Layout
|
||||
'content_css' => $content_css,
|
||||
'document_base_url' => Uri::root(true) . '/',
|
||||
'image_caption' => true,
|
||||
'importcss_append' => true,
|
||||
'height' => $this->params->get('html_height', '550px'),
|
||||
'width' => $this->params->get('html_width', ''),
|
||||
'elementpath' => (bool) $levelParams->get('element_path', true),
|
||||
'resize' => $resizing,
|
||||
'external_plugins' => empty($externalPlugins) ? null : $externalPlugins,
|
||||
'contextmenu' => (bool) $levelParams->get('contextmenu', true) ? null : false,
|
||||
'toolbar_sticky' => true,
|
||||
'toolbar_mode' => $levelParams->get('toolbar_mode', 'sliding'),
|
||||
|
||||
// Image plugin options
|
||||
'a11y_advanced_options' => true,
|
||||
'image_advtab' => (bool) $levelParams->get('image_advtab', false),
|
||||
'image_title' => true,
|
||||
'image_class_list' => [
|
||||
['title' => 'None', 'value' => 'float-none'],
|
||||
['title' => 'Left', 'value' => 'float-start'],
|
||||
['title' => 'Right', 'value' => 'float-end'],
|
||||
['title' => 'Center', 'value' => 'mx-auto d-block'],
|
||||
],
|
||||
|
||||
// Drag and drop specific
|
||||
'dndEnabled' => $dragdrop,
|
||||
|
||||
// Disable TinyMCE Branding
|
||||
'branding' => false,
|
||||
'promotion' => false,
|
||||
|
||||
// Specify the attributes to be used when previewing a style. This prevents white text on a white background making the preview invisible.
|
||||
'preview_styles' => 'font-family font-size font-weight font-style text-decoration text-transform background-color border border-radius outline text-shadow',
|
||||
]
|
||||
);
|
||||
|
||||
if ($levelParams->get('newlines')) {
|
||||
// Break
|
||||
$scriptOptions['force_br_newlines'] = true;
|
||||
} else {
|
||||
// Paragraph
|
||||
$scriptOptions['force_br_newlines'] = false;
|
||||
$scriptOptions['forced_root_block'] = 'p';
|
||||
}
|
||||
|
||||
$scriptOptions['link_rel_list'] = [
|
||||
['title' => 'None', 'value' => ''],
|
||||
['title' => 'Alternate', 'value' => 'alternate'],
|
||||
['title' => 'Author', 'value' => 'author'],
|
||||
['title' => 'Bookmark', 'value' => 'bookmark'],
|
||||
['title' => 'Help', 'value' => 'help'],
|
||||
['title' => 'License', 'value' => 'license'],
|
||||
['title' => 'Lightbox', 'value' => 'lightbox'],
|
||||
['title' => 'Next', 'value' => 'next'],
|
||||
['title' => 'No Follow', 'value' => 'nofollow'],
|
||||
['title' => 'No Referrer', 'value' => 'noreferrer'],
|
||||
['title' => 'Prefetch', 'value' => 'prefetch'],
|
||||
['title' => 'Prev', 'value' => 'prev'],
|
||||
['title' => 'Search', 'value' => 'search'],
|
||||
['title' => 'Tag', 'value' => 'tag'],
|
||||
];
|
||||
|
||||
$scriptOptions['style_formats'] = [
|
||||
[
|
||||
'title' => Text::_('PLG_TINY_MENU_CONTAINER'),
|
||||
'items' => [
|
||||
['title' => 'article', 'block' => 'article', 'wrapper' => true, 'merge_siblings' => false],
|
||||
['title' => 'aside', 'block' => 'aside', 'wrapper' => true, 'merge_siblings' => false],
|
||||
['title' => 'section', 'block' => 'section', 'wrapper' => true, 'merge_siblings' => false],
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
$scriptOptions['style_formats_merge'] = true;
|
||||
$options['tinyMCE']['default'] = $scriptOptions;
|
||||
|
||||
$doc->addScriptOptions('plg_editor_tinymce', $options);
|
||||
|
||||
return $editor;
|
||||
}
|
||||
}
|
||||
181
plugins/editors/tinymce/src/PluginTraits/GlobalFilters.php
Normal file
181
plugins/editors/tinymce/src/PluginTraits/GlobalFilters.php
Normal file
@ -0,0 +1,181 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Plugin
|
||||
* @subpackage Editors.tinymce
|
||||
*
|
||||
* @copyright (C) 2021 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Plugin\Editors\TinyMCE\PluginTraits;
|
||||
|
||||
use Joomla\CMS\Access\Access;
|
||||
use Joomla\CMS\Component\ComponentHelper;
|
||||
use Joomla\CMS\Filter\InputFilter;
|
||||
use Joomla\CMS\User\User;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Handles the Joomla filters for the TinyMCE editor.
|
||||
*
|
||||
* @since 4.1.0
|
||||
*/
|
||||
trait GlobalFilters
|
||||
{
|
||||
/**
|
||||
* Get the global text filters to arbitrary text as per settings for current user groups
|
||||
* @param User $user The user object
|
||||
*
|
||||
* @return InputFilter
|
||||
*
|
||||
* @since 4.1.0
|
||||
*/
|
||||
protected static function getGlobalFilters($user)
|
||||
{
|
||||
// Filter settings
|
||||
$config = ComponentHelper::getParams('com_config');
|
||||
$userGroups = Access::getGroupsByUser($user->get('id'));
|
||||
$filters = $config->get('filters');
|
||||
|
||||
$forbiddenListTags = [];
|
||||
$forbiddenListAttributes = [];
|
||||
$customListTags = [];
|
||||
$customListAttributes = [];
|
||||
$allowedListTags = [];
|
||||
$allowedListAttributes = [];
|
||||
|
||||
$allowedList = false;
|
||||
$forbiddenList = false;
|
||||
$customList = false;
|
||||
$unfiltered = false;
|
||||
|
||||
/**
|
||||
* Cycle through each of the user groups the user is in.
|
||||
* Remember they are included in the public group as well.
|
||||
*/
|
||||
foreach ($userGroups as $groupId) {
|
||||
// May have added a group but not saved the filters.
|
||||
if (!isset($filters->$groupId)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Each group the user is in could have different filtering properties.
|
||||
$filterData = $filters->$groupId;
|
||||
$filterType = strtoupper($filterData->filter_type);
|
||||
|
||||
if ($filterType === 'NH') {
|
||||
// Maximum HTML filtering.
|
||||
} elseif ($filterType === 'NONE') {
|
||||
// No HTML filtering.
|
||||
$unfiltered = true;
|
||||
} else {
|
||||
/**
|
||||
* Forbidden or allowed lists.
|
||||
* Preprocess the tags and attributes.
|
||||
*/
|
||||
$tags = explode(',', $filterData->filter_tags);
|
||||
$attributes = explode(',', $filterData->filter_attributes);
|
||||
$tempTags = [];
|
||||
$tempAttributes = [];
|
||||
|
||||
foreach ($tags as $tag) {
|
||||
$tag = trim($tag);
|
||||
|
||||
if ($tag) {
|
||||
$tempTags[] = $tag;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($attributes as $attribute) {
|
||||
$attribute = trim($attribute);
|
||||
|
||||
if ($attribute) {
|
||||
$tempAttributes[] = $attribute;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Collect the list of forbidden or allowed tags and attributes.
|
||||
* Each list is cumulative.
|
||||
* "BL" is deprecated in Joomla! 4, will be removed in Joomla! 5
|
||||
*/
|
||||
if (\in_array($filterType, ['BL', 'FL'])) {
|
||||
$forbiddenList = true;
|
||||
$forbiddenListTags = array_merge($forbiddenListTags, $tempTags);
|
||||
$forbiddenListAttributes = array_merge($forbiddenListAttributes, $tempAttributes);
|
||||
} elseif (\in_array($filterType, ['CBL', 'CFL'])) {
|
||||
// "CBL" is deprecated in Joomla! 4, will be removed in Joomla! 5
|
||||
// Only set to true if Tags or Attributes were added
|
||||
if ($tempTags || $tempAttributes) {
|
||||
$customList = true;
|
||||
$customListTags = array_merge($customListTags, $tempTags);
|
||||
$customListAttributes = array_merge($customListAttributes, $tempAttributes);
|
||||
}
|
||||
} elseif (\in_array($filterType, ['WL', 'AL'])) {
|
||||
// "WL" is deprecated in Joomla! 4, will be removed in Joomla! 5
|
||||
$allowedList = true;
|
||||
$allowedListTags = array_merge($allowedListTags, $tempTags);
|
||||
$allowedListAttributes = array_merge($allowedListAttributes, $tempAttributes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Remove duplicates before processing (because the forbidden list uses both sets of arrays).
|
||||
$forbiddenListTags = array_unique($forbiddenListTags);
|
||||
$forbiddenListAttributes = array_unique($forbiddenListAttributes);
|
||||
$customListTags = array_unique($customListTags);
|
||||
$customListAttributes = array_unique($customListAttributes);
|
||||
$allowedListTags = array_unique($allowedListTags);
|
||||
$allowedListAttributes = array_unique($allowedListAttributes);
|
||||
|
||||
// Unfiltered assumes first priority.
|
||||
if ($unfiltered) {
|
||||
// Don't apply filtering.
|
||||
return false;
|
||||
}
|
||||
|
||||
// Custom forbidden list precedes Default forbidden list.
|
||||
if ($customList) {
|
||||
$filter = InputFilter::getInstance([], [], 1, 1);
|
||||
|
||||
// Override filter's default forbidden tags and attributes
|
||||
if ($customListTags) {
|
||||
$filter->blockedTags = $customListTags;
|
||||
}
|
||||
|
||||
if ($customListAttributes) {
|
||||
$filter->blockedAttributes = $customListAttributes;
|
||||
}
|
||||
} elseif ($forbiddenList) {
|
||||
// Forbidden list takes second precedence.
|
||||
// Remove the allowed tags and attributes from the forbidden list.
|
||||
$forbiddenListTags = array_diff($forbiddenListTags, $allowedListTags);
|
||||
$forbiddenListAttributes = array_diff($forbiddenListAttributes, $allowedListAttributes);
|
||||
|
||||
$filter = InputFilter::getInstance($forbiddenListTags, $forbiddenListAttributes, 1, 1);
|
||||
|
||||
// Remove allowed tags from filter's default forbidden list
|
||||
if ($allowedListTags) {
|
||||
$filter->blockedTags = array_diff($filter->blockedTags, $allowedListTags);
|
||||
}
|
||||
|
||||
// Remove allowed attributes from filter's default forbidden list
|
||||
if ($allowedListAttributes) {
|
||||
$filter->blockedAttributes = array_diff($filter->blockedAttributes, $allowedListAttributes);
|
||||
}
|
||||
} elseif ($allowedList) {
|
||||
// Allowed list take third precedence.
|
||||
// Turn off XSS auto clean
|
||||
$filter = InputFilter::getInstance($allowedListTags, $allowedListAttributes, 0, 0, 0);
|
||||
} else {
|
||||
// No HTML takes last place.
|
||||
$filter = InputFilter::getInstance();
|
||||
}
|
||||
|
||||
return $filter;
|
||||
}
|
||||
}
|
||||
108
plugins/editors/tinymce/src/PluginTraits/KnownButtons.php
Normal file
108
plugins/editors/tinymce/src/PluginTraits/KnownButtons.php
Normal file
@ -0,0 +1,108 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Plugin
|
||||
* @subpackage Editors.tinymce
|
||||
*
|
||||
* @copyright (C) 2021 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Plugin\Editors\TinyMCE\PluginTraits;
|
||||
|
||||
use Joomla\CMS\Language\Text;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Returns a list of known TinyMCE buttons.
|
||||
*
|
||||
* @since 4.1.0
|
||||
*/
|
||||
trait KnownButtons
|
||||
{
|
||||
/**
|
||||
* Return list of known TinyMCE buttons
|
||||
* @link https://www.tiny.cloud/docs/demo/full-featured/
|
||||
* @link https://www.tiny.cloud/apps/#core-plugins
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @since 4.1.0
|
||||
*/
|
||||
public static function getKnownButtons()
|
||||
{
|
||||
return [
|
||||
// General buttons
|
||||
'|' => ['label' => Text::_('PLG_TINY_TOOLBAR_BUTTON_SEPARATOR'), 'text' => '|'],
|
||||
|
||||
'undo' => ['label' => 'Undo'],
|
||||
'redo' => ['label' => 'Redo'],
|
||||
|
||||
'bold' => ['label' => 'Bold'],
|
||||
'italic' => ['label' => 'Italic'],
|
||||
'underline' => ['label' => 'Underline'],
|
||||
'strikethrough' => ['label' => 'Strikethrough'],
|
||||
'styles' => ['label' => Text::_('PLG_TINY_TOOLBAR_BUTTON_STYLESELECT'), 'text' => 'Formats'],
|
||||
'blocks' => ['label' => Text::_('PLG_TINY_TOOLBAR_BUTTON_FORMATSELECT'), 'text' => 'Paragraph'],
|
||||
'fontfamily' => ['label' => Text::_('PLG_TINY_TOOLBAR_BUTTON_FONTSELECT'), 'text' => 'Font Family'],
|
||||
'fontsize' => ['label' => Text::_('PLG_TINY_TOOLBAR_BUTTON_FONTSIZESELECT'), 'text' => 'Font Sizes'],
|
||||
|
||||
'alignleft' => ['label' => 'Align left'],
|
||||
'aligncenter' => ['label' => 'Align center'],
|
||||
'alignright' => ['label' => 'Align right'],
|
||||
'alignjustify' => ['label' => 'Justify'],
|
||||
'lineheight' => ['label' => 'Line height'],
|
||||
|
||||
'outdent' => ['label' => 'Decrease indent'],
|
||||
'indent' => ['label' => 'Increase indent'],
|
||||
|
||||
'forecolor' => ['label' => 'Text colour'],
|
||||
'backcolor' => ['label' => 'Background text colour'],
|
||||
|
||||
'bullist' => ['label' => 'Bullet list'],
|
||||
'numlist' => ['label' => 'Numbered list'],
|
||||
|
||||
'link' => ['label' => 'Insert/edit link', 'plugin' => 'link'],
|
||||
'unlink' => ['label' => 'Remove link', 'plugin' => 'link'],
|
||||
|
||||
'subscript' => ['label' => 'Subscript'],
|
||||
'superscript' => ['label' => 'Superscript'],
|
||||
'blockquote' => ['label' => 'Blockquote'],
|
||||
|
||||
'cut' => ['label' => 'Cut'],
|
||||
'copy' => ['label' => 'Copy'],
|
||||
'paste' => ['label' => 'Paste'],
|
||||
'pastetext' => ['label' => 'Paste as text'],
|
||||
'removeformat' => ['label' => 'Clear formatting'],
|
||||
|
||||
'language' => ['label' => 'Language'],
|
||||
|
||||
// Buttons from the plugins
|
||||
'anchor' => ['label' => 'Anchor', 'plugin' => 'anchor'],
|
||||
'hr' => ['label' => 'Horizontal line'],
|
||||
'ltr' => ['label' => 'Left to right', 'plugin' => 'directionality'],
|
||||
'rtl' => ['label' => 'Right to left', 'plugin' => 'directionality'],
|
||||
'code' => ['label' => 'Source code', 'plugin' => 'code'],
|
||||
'codesample' => ['label' => 'Insert/Edit code sample', 'plugin' => 'codesample'],
|
||||
'table' => ['label' => 'Table', 'plugin' => 'table'],
|
||||
'charmap' => ['label' => 'Special character', 'plugin' => 'charmap'],
|
||||
'visualchars' => ['label' => 'Show invisible characters', 'plugin' => 'visualchars'],
|
||||
'visualblocks' => ['label' => 'Show blocks', 'plugin' => 'visualblocks'],
|
||||
'nonbreaking' => ['label' => 'Nonbreaking space', 'plugin' => 'nonbreaking'],
|
||||
'emoticons' => ['label' => 'Emoticons', 'plugin' => 'emoticons'],
|
||||
'media' => ['label' => 'Insert/edit video', 'plugin' => 'media'],
|
||||
'image' => ['label' => 'Insert/edit image', 'plugin' => 'image'],
|
||||
'pagebreak' => ['label' => 'Page break', 'plugin' => 'pagebreak'],
|
||||
'print' => ['label' => 'Print'],
|
||||
'preview' => ['label' => 'Preview', 'plugin' => 'preview'],
|
||||
'fullscreen' => ['label' => 'Fullscreen', 'plugin' => 'fullscreen'],
|
||||
'jtemplate' => ['label' => 'Insert template', 'plugin' => 'jtemplate'],
|
||||
'searchreplace' => ['label' => 'Find and replace', 'plugin' => 'searchreplace'],
|
||||
'insertdatetime' => ['label' => 'Insert date/time', 'plugin' => 'insertdatetime'],
|
||||
'help' => ['label' => 'Help', 'plugin' => 'help'],
|
||||
];
|
||||
}
|
||||
}
|
||||
117
plugins/editors/tinymce/src/PluginTraits/ResolveFiles.php
Normal file
117
plugins/editors/tinymce/src/PluginTraits/ResolveFiles.php
Normal file
@ -0,0 +1,117 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Plugin
|
||||
* @subpackage Editors.tinymce
|
||||
*
|
||||
* @copyright (C) 2021 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Plugin\Editors\TinyMCE\PluginTraits;
|
||||
|
||||
use Joomla\CMS\Filesystem\File;
|
||||
use Joomla\CMS\Uri\Uri;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Handles the editor.css files.
|
||||
*
|
||||
* @since 4.1.0
|
||||
*/
|
||||
trait ResolveFiles
|
||||
{
|
||||
use ActiveSiteTemplate;
|
||||
|
||||
/**
|
||||
* Compute the file paths to be included
|
||||
*
|
||||
* @param string $folder Folder name to search in (i.e. images, css, js).
|
||||
* @param string $file Path to file.
|
||||
*
|
||||
* @return array files to be included.
|
||||
*
|
||||
* @since 4.1.0
|
||||
*/
|
||||
protected function includeRelativeFiles($folder, $file)
|
||||
{
|
||||
$fallback = Uri::root(true) . '/media/system/css/editor' . (JDEBUG ? '' : '.min') . '.css';
|
||||
$template = $this->getActiveSiteTemplate();
|
||||
|
||||
if (!(array) $template) {
|
||||
return $fallback;
|
||||
}
|
||||
|
||||
// Extract extension and strip the file
|
||||
$file = File::stripExt($file) . '.' . File::getExt($file);
|
||||
$templaPath = $template->inheritable || (isset($template->parent) && $template->parent !== '')
|
||||
? JPATH_ROOT . '/media/templates/site'
|
||||
: JPATH_ROOT . '/templates';
|
||||
|
||||
if (isset($template->parent) && $template->parent !== '') {
|
||||
$found = static::resolveFileUrl("$templaPath/$template->template/$folder/$file");
|
||||
|
||||
if (empty($found)) {
|
||||
$found = static::resolveFileUrl("$templaPath/$template->parent/$folder/$file");
|
||||
}
|
||||
} else {
|
||||
$found = static::resolveFileUrl("$templaPath/$template->template/$folder/$file");
|
||||
}
|
||||
|
||||
if (empty($found)) {
|
||||
return $fallback;
|
||||
}
|
||||
|
||||
return $found;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method that searches if file exists in given path and returns the relative path.
|
||||
* If a minified version exists it will be preferred.
|
||||
*
|
||||
* @param string $path The actual path of the file
|
||||
*
|
||||
* @return string The relative path of the file
|
||||
*
|
||||
* @since 4.1.0
|
||||
*/
|
||||
protected static function resolveFileUrl($path = '')
|
||||
{
|
||||
$position = strrpos($path, '.min.');
|
||||
|
||||
// We are handling a name.min.ext file:
|
||||
if ($position !== false) {
|
||||
$minifiedPath = $path;
|
||||
$nonMinifiedPath = substr_replace($path, '', $position, 4);
|
||||
|
||||
if (JDEBUG && is_file($nonMinifiedPath)) {
|
||||
return Uri::root(true) . str_replace(JPATH_ROOT, '', $nonMinifiedPath);
|
||||
}
|
||||
|
||||
if (is_file($minifiedPath)) {
|
||||
return Uri::root(true) . str_replace(JPATH_ROOT, '', $minifiedPath);
|
||||
}
|
||||
|
||||
if (is_file($nonMinifiedPath)) {
|
||||
return Uri::root(true) . str_replace(JPATH_ROOT, '', $nonMinifiedPath);
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
$minifiedPath = pathinfo($path, PATHINFO_DIRNAME) . '/' . pathinfo($path, PATHINFO_FILENAME) . '.min.' . pathinfo($path, PATHINFO_EXTENSION);
|
||||
|
||||
if (JDEBUG && is_file($path)) {
|
||||
return Uri::root(true) . str_replace(JPATH_ROOT, '', $path);
|
||||
}
|
||||
|
||||
if (is_file($minifiedPath)) {
|
||||
return Uri::root(true) . str_replace(JPATH_ROOT, '', $minifiedPath);
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
}
|
||||
88
plugins/editors/tinymce/src/PluginTraits/ToolbarPresets.php
Normal file
88
plugins/editors/tinymce/src/PluginTraits/ToolbarPresets.php
Normal file
@ -0,0 +1,88 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Plugin
|
||||
* @subpackage Editors.tinymce
|
||||
*
|
||||
* @copyright (C) 2021 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Plugin\Editors\TinyMCE\PluginTraits;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* The ToolbarPresets trait holds the default presets for the toolbar.
|
||||
*
|
||||
* @since 4.1.0
|
||||
*/
|
||||
trait ToolbarPresets
|
||||
{
|
||||
/**
|
||||
* Return toolbar presets
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @since 4.1.0
|
||||
*/
|
||||
public static function getToolbarPreset()
|
||||
{
|
||||
return [
|
||||
'simple' => [
|
||||
'menu' => [],
|
||||
'toolbar1' => [
|
||||
'bold', 'underline', 'strikethrough', '|',
|
||||
'undo', 'redo', '|',
|
||||
'bullist', 'numlist', '|',
|
||||
'pastetext', 'jxtdbuttons',
|
||||
],
|
||||
'toolbar2' => [],
|
||||
],
|
||||
'medium' => [
|
||||
'menu' => ['edit', 'insert', 'view', 'format', 'table', 'tools', 'help'],
|
||||
'toolbar1' => [
|
||||
'bold', 'italic', 'underline', 'strikethrough', '|',
|
||||
'alignleft', 'aligncenter', 'alignright', 'alignjustify', '|',
|
||||
'blocks', '|',
|
||||
'bullist', 'numlist', '|',
|
||||
'outdent', 'indent', '|',
|
||||
'undo', 'redo', '|',
|
||||
'link', 'unlink', 'anchor', 'code', '|',
|
||||
'hr', 'table', '|',
|
||||
'subscript', 'superscript', '|',
|
||||
'charmap', 'pastetext', 'preview', 'jxtdbuttons',
|
||||
],
|
||||
'toolbar2' => [],
|
||||
],
|
||||
'advanced' => [
|
||||
'menu' => ['edit', 'insert', 'view', 'format', 'table', 'tools', 'help'],
|
||||
'toolbar1' => [
|
||||
'bold', 'italic', 'underline', 'strikethrough', '|',
|
||||
'alignleft', 'aligncenter', 'alignright', 'alignjustify', '|',
|
||||
'lineheight', '|',
|
||||
'styles', '|',
|
||||
'blocks', 'fontfamily', 'fontsize', '|',
|
||||
'searchreplace', '|',
|
||||
'bullist', 'numlist', '|',
|
||||
'outdent', 'indent', '|',
|
||||
'undo', 'redo', '|',
|
||||
'link', 'unlink', 'anchor', 'image', '|',
|
||||
'code', '|',
|
||||
'forecolor', 'backcolor', '|',
|
||||
'fullscreen', '|',
|
||||
'table', '|',
|
||||
'subscript', 'superscript', '|',
|
||||
'charmap', 'emoticons', 'media', 'hr', 'ltr', 'rtl', '|',
|
||||
'cut', 'copy', 'paste', 'pastetext', '|',
|
||||
'visualchars', 'visualblocks', 'nonbreaking', 'blockquote', 'jtemplate', '|',
|
||||
'print', 'preview', 'codesample', 'insertdatetime', 'removeformat', 'jxtdbuttons',
|
||||
'language',
|
||||
],
|
||||
'toolbar2' => [],
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
118
plugins/editors/tinymce/src/PluginTraits/XTDButtons.php
Normal file
118
plugins/editors/tinymce/src/PluginTraits/XTDButtons.php
Normal file
@ -0,0 +1,118 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Plugin
|
||||
* @subpackage Editors.tinymce
|
||||
*
|
||||
* @copyright (C) 2021 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Plugin\Editors\TinyMCE\PluginTraits;
|
||||
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\Layout\LayoutHelper;
|
||||
use Joomla\CMS\Uri\Uri;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Resolves the XTD Buttons for the current TinyMCE editor.
|
||||
*
|
||||
* @since 4.1.0
|
||||
*/
|
||||
trait XTDButtons
|
||||
{
|
||||
/**
|
||||
* Get the XTD buttons and render them inside tinyMCE
|
||||
*
|
||||
* @param mixed $buttons the buttons that should be hidden
|
||||
* @param array $options Associative array with additional parameters
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @since 4.1.0
|
||||
*/
|
||||
private function tinyButtons($buttons, array $options = []): array
|
||||
{
|
||||
// Get buttons from plugins
|
||||
$buttonsList = $this->getButtons($buttons, $options);
|
||||
|
||||
if (!$buttonsList) {
|
||||
return [];
|
||||
}
|
||||
|
||||
/** @var \Joomla\CMS\WebAsset\WebAssetManager $wa */
|
||||
$wa = $this->application->getDocument()->getWebAssetManager();
|
||||
$editorId = $options['editorId'] ?? '';
|
||||
|
||||
Text::script('PLG_TINY_CORE_BUTTONS');
|
||||
|
||||
// Build a buttons option for TinyMCE
|
||||
$tinyButtons = [];
|
||||
|
||||
foreach ($buttonsList as $button) {
|
||||
$title = $button->get('title') ?: $button->get('text', '');
|
||||
$icon = $button->get('icon');
|
||||
$link = $button->get('link');
|
||||
$action = $button->get('action', '');
|
||||
$options = (array) $button->get('options');
|
||||
|
||||
$btnAsset = 'editor-button.' . $button->getButtonName();
|
||||
|
||||
// Enable the button assets if any
|
||||
if ($wa->assetExists('style', $btnAsset)) {
|
||||
$wa->useStyle($btnAsset);
|
||||
}
|
||||
if ($wa->assetExists('script', $btnAsset)) {
|
||||
$wa->useScript($btnAsset);
|
||||
}
|
||||
|
||||
// Correct the link
|
||||
if ($link && $link[0] !== '#') {
|
||||
$link = str_contains($link, '&') ? htmlspecialchars_decode($link) : $link;
|
||||
$link = Uri::base(true) . '/' . $link;
|
||||
$options['src'] = $options['src'] ?? $link;
|
||||
}
|
||||
|
||||
// Set action to "modal" for legacy buttons, when possible
|
||||
$legacyModal = $button->get('modal');
|
||||
|
||||
// Prepare default values for modal
|
||||
if ($action === 'modal') {
|
||||
$wa->useScript('joomla.dialog');
|
||||
$legacyModal = false;
|
||||
|
||||
$options['popupType'] = $options['popupType'] ?? 'iframe';
|
||||
$options['textHeader'] = $options['textHeader'] ?? $title;
|
||||
$options['iconHeader'] = $options['iconHeader'] ?? 'icon-' . $icon;
|
||||
}
|
||||
|
||||
$coreButton = [];
|
||||
$coreButton['name'] = $title;
|
||||
$coreButton['icon'] = $icon;
|
||||
$coreButton['click'] = $button->get('onclick');
|
||||
$coreButton['iconSVG'] = $button->get('iconSVG');
|
||||
$coreButton['action'] = $action;
|
||||
$coreButton['options'] = $options;
|
||||
|
||||
if ($legacyModal) {
|
||||
$coreButton['bsModal'] = true;
|
||||
$coreButton['id'] = $editorId . '_' . $button->name;
|
||||
|
||||
$button->id = $editorId . '_' . $button->name . '_modal';
|
||||
|
||||
echo LayoutHelper::render('joomla.editors.buttons.modal', $button);
|
||||
}
|
||||
|
||||
// The array with the toolbar buttons
|
||||
$tinyButtons[] = $coreButton;
|
||||
}
|
||||
|
||||
sort($tinyButtons);
|
||||
|
||||
return ['names' => $tinyButtons];
|
||||
}
|
||||
}
|
||||
80
plugins/editors/tinymce/src/Provider/TinyMCEProvider.php
Normal file
80
plugins/editors/tinymce/src/Provider/TinyMCEProvider.php
Normal file
@ -0,0 +1,80 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Joomla! Content Management System
|
||||
*
|
||||
* @copyright (C) 2023 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Plugin\Editors\TinyMCE\Provider;
|
||||
|
||||
use Joomla\CMS\Application\CMSApplicationInterface;
|
||||
use Joomla\CMS\Editor\AbstractEditorProvider;
|
||||
use Joomla\Database\DatabaseAwareTrait;
|
||||
use Joomla\Database\DatabaseInterface;
|
||||
use Joomla\Event\DispatcherInterface;
|
||||
use Joomla\Plugin\Editors\TinyMCE\PluginTraits\DisplayTrait;
|
||||
use Joomla\Registry\Registry;
|
||||
|
||||
/**
|
||||
* Editor provider class
|
||||
*
|
||||
* @since 5.0.0
|
||||
*/
|
||||
final class TinyMCEProvider extends AbstractEditorProvider
|
||||
{
|
||||
use DisplayTrait;
|
||||
use DatabaseAwareTrait;
|
||||
|
||||
/**
|
||||
* A Registry object holding the parameters for the plugin
|
||||
*
|
||||
* @var Registry
|
||||
* @since 5.0.0
|
||||
*/
|
||||
protected $params;
|
||||
|
||||
/**
|
||||
* The application object
|
||||
*
|
||||
* @var CMSApplicationInterface
|
||||
*
|
||||
* @since 5.0.0
|
||||
*/
|
||||
protected $application;
|
||||
|
||||
/**
|
||||
* Class constructor
|
||||
*
|
||||
* @param Registry $params
|
||||
* @param CMSApplicationInterface $application
|
||||
* @param DispatcherInterface $dispatcher
|
||||
* @param DatabaseInterface $database
|
||||
*
|
||||
* @since 5.0.0
|
||||
*/
|
||||
public function __construct(
|
||||
Registry $params,
|
||||
CMSApplicationInterface $application,
|
||||
DispatcherInterface $dispatcher,
|
||||
DatabaseInterface $database
|
||||
) {
|
||||
$this->params = $params;
|
||||
$this->application = $application;
|
||||
|
||||
$this->setDispatcher($dispatcher);
|
||||
$this->setDatabase($database);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return Editor name, CMD string.
|
||||
*
|
||||
* @return string
|
||||
* @since 5.0.0
|
||||
*/
|
||||
public function getName(): string
|
||||
{
|
||||
return 'tinymce';
|
||||
}
|
||||
}
|
||||
63
plugins/editors/tinymce/tinymce.xml
Normal file
63
plugins/editors/tinymce/tinymce.xml
Normal file
@ -0,0 +1,63 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<extension type="plugin" group="editors" method="upgrade">
|
||||
<name>plg_editors_tinymce</name>
|
||||
<version>6.7.0</version>
|
||||
<creationDate>2005-08</creationDate>
|
||||
<author>Tiny Technologies, Inc</author>
|
||||
<authorEmail>N/A</authorEmail>
|
||||
<authorUrl>https://www.tiny.cloud</authorUrl>
|
||||
<copyright>Tiny Technologies, Inc</copyright>
|
||||
<license>MIT</license>
|
||||
<description>PLG_TINY_XML_DESCRIPTION</description>
|
||||
<namespace path="src">Joomla\Plugin\Editors\TinyMCE</namespace>
|
||||
<files>
|
||||
<folder>forms</folder>
|
||||
<folder plugin="tinymce">services</folder>
|
||||
<folder>src</folder>
|
||||
</files>
|
||||
<media destination="editors" folder="media">
|
||||
<folder>tinymce</folder>
|
||||
</media>
|
||||
<languages>
|
||||
<language tag="en-GB">language/en-GB/plg_editors_tinymce.ini</language>
|
||||
<language tag="en-GB">language/en-GB/plg_editors_tinymce.sys.ini</language>
|
||||
</languages>
|
||||
<config>
|
||||
<fields name="params">
|
||||
<fieldset name="basic" addfieldprefix="Joomla\Plugin\Editors\TinyMCE\Field">
|
||||
<field
|
||||
name="configuration"
|
||||
type="tinymcebuilder"
|
||||
label="PLG_TINY_BUILDER"
|
||||
hiddenLabel="true"
|
||||
/>
|
||||
</fieldset>
|
||||
|
||||
<fieldset name="advanced" label="PLG_TINY_FIELD_LABEL_ADVANCEDPARAMS">
|
||||
<field
|
||||
name="sets_amount"
|
||||
type="number"
|
||||
label="PLG_TINY_FIELD_NUMBER_OF_SETS_LABEL"
|
||||
filter="int"
|
||||
validate="number"
|
||||
min="3"
|
||||
default="3"
|
||||
/>
|
||||
|
||||
<field
|
||||
name="html_height"
|
||||
type="text"
|
||||
label="PLG_TINY_FIELD_HTMLHEIGHT_LABEL"
|
||||
default="550px"
|
||||
/>
|
||||
|
||||
<field
|
||||
name="html_width"
|
||||
type="text"
|
||||
label="PLG_TINY_FIELD_HTMLWIDTH_LABEL"
|
||||
default=""
|
||||
/>
|
||||
</fieldset>
|
||||
</fields>
|
||||
</config>
|
||||
</extension>
|
||||
Reference in New Issue
Block a user