silverstripe-framework/forms/HtmlEditorConfig.php
Damian Mooyman 0b1f297873 Merge remote-tracking branch 'origin/3.1'
Conflicts:
	.travis.yml
	README.md
	admin/code/LeftAndMain.php
	admin/css/screen.css
	admin/scss/screen.scss
	api/RestfulService.php
	conf/ConfigureFromEnv.php
	control/injector/ServiceConfigurationLocator.php
	control/injector/SilverStripeServiceConfigurationLocator.php
	core/ClassInfo.php
	core/Object.php
	css/AssetUploadField.css
	css/ComplexTableField_popup.css
	dev/CSSContentParser.php
	dev/DevelopmentAdmin.php
	docs/en/changelogs/index.md
	docs/en/misc/contributing/code.md
	docs/en/reference/execution-pipeline.md
	filesystem/GD.php
	filesystem/ImagickBackend.php
	filesystem/Upload.php
	forms/Form.php
	forms/FormField.php
	forms/HtmlEditorConfig.php
	forms/gridfield/GridFieldDetailForm.php
	forms/gridfield/GridFieldSortableHeader.php
	lang/en.yml
	model/Aggregate.php
	model/DataList.php
	model/DataObject.php
	model/DataQuery.php
	model/Image.php
	model/MySQLDatabase.php
	model/SQLQuery.php
	model/fieldtypes/HTMLText.php
	model/fieldtypes/Text.php
	scss/AssetUploadField.scss
	search/filters/SearchFilter.php
	security/Authenticator.php
	security/LoginForm.php
	security/Member.php
	security/MemberAuthenticator.php
	security/MemberLoginForm.php
	security/Security.php
	tests/behat/features/bootstrap/SilverStripe/Framework/Test/Behaviour/CmsFormsContext.php
	tests/control/HTTPTest.php
	tests/control/RequestHandlingTest.php
	tests/filesystem/UploadTest.php
	tests/forms/FormTest.php
	tests/forms/NumericFieldTest.php
	tests/model/DataListTest.php
	tests/model/DataObjectTest.php
	tests/model/TextTest.php
	tests/security/MemberAuthenticatorTest.php
	tests/security/SecurityDefaultAdminTest.php
	tests/view/SSViewerCacheBlockTest.php
	tests/view/SSViewerTest.php
2014-11-18 12:45:54 +13:00

329 lines
10 KiB
PHP

<?php
/**
* A PHP version of TinyMCE's 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. Whichever config is active when
* HtmlEditorField#Field is called wins.
*
* @author "Hamish Friedlander" <hamish@silverstripe.com>
* @package forms
* @subpackage fields-formattedinput
*/
class HtmlEditorConfig {
private static $configs = array();
private static $current = null;
/**
* Get the HtmlEditorConfig object for the given identifier. This is a correct way to get an HtmlEditorConfig
* instance - do not call 'new'
*
* @param $identifier string - the identifier for the config set
* @return HtmlEditorConfig - the configuration object. This will be created if it does not yet exist for that
* identifier
*/
public static function get($identifier = 'default') {
if (!array_key_exists($identifier, self::$configs)) self::$configs[$identifier] = new HtmlEditorConfig();
return self::$configs[$identifier];
}
/**
* Set the currently active configuration object
* @param $identifier string - the identifier for the config set
* @return null
*/
public static function set_active($identifier = null) {
self::$current = $identifier;
}
/**
* Get the currently active configuration object
* @return HtmlEditorConfig - the active configuration object
*/
public static function get_active() {
$identifier = self::$current ? self::$current : 'default';
return self::get($identifier);
}
/**
* Get the available configurations as a map of friendly_name to
* configuration name.
* @return array
*/
public static function get_available_configs_map() {
$configs = array();
foreach(self::$configs as $identifier => $config) {
$configs[$identifier] = $config->getOption('friendly_name');
}
return $configs;
}
/**
* Holder for all TinyMCE settings _except_ plugins and buttons
*/
protected $settings = array(
'friendly_name' => '(Please set a friendly name for this config)',
'priority' => 0,
'mode' => "none", // initialized through HtmlEditorField.js redraw() logic
'editor_selector' => "htmleditor",
'width' => "100%",
'auto_resize' => false,
'update_interval' => 5000, // Ensure update of this data every 5 seconds to the underlying textarea
'theme' => "advanced",
'theme_advanced_layout_manager' => "SimpleLayout",
'theme_advanced_toolbar_location' => "top",
'theme_advanced_toolbar_align' => "left",
'theme_advanced_toolbar_parent' => "right",
'blockquote_clear_tag' => "p",
'table_inline_editing' => true,
'safari_warning' => false,
'relative_urls' => true,
'verify_html' => true,
'browser_spellcheck' => true,
);
/**
* Holder list of enabled plugins
*/
protected $plugins = array(
'contextmenu' => null,
'table' => null,
'emotions' => null,
'paste' => null,
);
/**
* Holder list of buttons, organised by line
*/
protected $buttons = array(
1 => array('bold','italic','underline','strikethrough','separator',
'justifyleft','justifycenter','justifyright','justifyfull','formatselect','separator',
'bullist','numlist','outdent','indent','blockquote','hr','charmap'),
2 => array('undo','redo','separator','cut','copy','paste','pastetext','pasteword','separator',
'advcode','search','replace','selectall','visualaid','separator','tablecontrols'),
3 => array()
);
/**
* Get the current value of an option
* @param $k string - The key of the option to get
* @return mixed - The value of the specified option
*/
public function getOption($k) {
if(isset($this->settings[$k])) return $this->settings[$k];
}
/**
* Set the value of one option
* @param $k string - The key of the option to set
* @param $v mixed - The value of the option to set
* @return HtmlEditorConfig
*/
public function setOption($k,$v) {
$this->settings[$k] = $v;
return $this;
}
/**
* Set multiple options
* @param $a array - The options to set, as keys and values of the array
* @return HtmlEditorConfig
*/
public function setOptions($a) {
foreach ($a as $k=>$v) {
$this->settings[$k] = $v;
}
return $this;
}
/**
* Enable one or several plugins. Will maintain unique list if already
* enabled plugin is re-passed. If passed in as a map of plugin-name to path,
* the plugin will be loaded by tinymce.PluginManager.load() instead of through tinyMCE.init().
* Keep in mind that these externals plugins require a dash-prefix in their name.
*
* @see http://wiki.moxiecode.com/index.php/TinyMCE:API/tinymce.PluginManager/load
*
* @param String [0..] a string, or several strings, or a single array of strings - The plugins to enable
* @return HtmlEditorConfig
*/
public function enablePlugins() {
$plugins = func_get_args();
if (is_array(current($plugins))) $plugins = current($plugins);
foreach ($plugins as $plugin => $path) {
// if plugins are passed without a path
if(is_numeric($plugin)) {
$plugin = $path;
$path = null;
}
if (!array_key_exists($plugin, $this->plugins)) $this->plugins[$plugin] = $path;
}
return $this;
}
/**
* Enable one or several plugins. Will properly handle being passed a plugin that is already disabled
* @param String [0..] a string, or several strings, or a single array of strings - The plugins to disable
* @return HtmlEditorConfig
*/
public function disablePlugins() {
$plugins = func_get_args();
if (is_array(current($plugins))) $plugins = current($plugins);
foreach ($plugins as $plugin) {
if(array_key_exists($plugin, $this->plugins)) {
unset($this->plugins[$plugin]);
}
}
return $this;
}
/**
* @return Array
*/
public function getPlugins() {
return $this->plugins;
}
/**
* Totally re-set the buttons on a given line
*
* @param integer from 1..3 - The line number to redefine
* @param string a string or several strings, or a single array of strings - The button names to make this line
* contain
* @return HtmlEditorConfig
*/
public function setButtonsForLine() {
if (func_num_args() == 2) {
list($line, $buttons) = func_get_args();
}
else {
$buttons = func_get_args();
$line = array_shift($buttons);
}
$this->buttons[$line] = is_array($buttons) ? $buttons : array($buttons);
return $this;
}
/**
* Add buttons to the end of a line
* @param integer from 1..3
* @param string a string, or several strings, or a single array of strings - The button names to add to the end
* of this line
* @return HtmlEditorConfig
*/
public function addButtonsToLine() {
$inserts = func_get_args();
$line = array_shift($inserts);
if (is_array($inserts[0])) $inserts = $inserts[0];
foreach ($inserts as $button) {
$this->buttons[$line][] = $button;
}
return $this;
}
/**
* Internal function for adding and removing buttons related to another button
* @param $name string - the name of the button to modify
* @param $offset integer - the offset relative to that button to perform an array_splice at - 0 for before $name,
* 1 for after
* @param $del integer - the number of buttons to remove at the position given by index(string) + offset
* @param $add mixed - an array or single item to insert at the position given by index(string) + offset,
* or null for no insertion
* @return boolean - true if $name matched a button, false otherwise
*/
protected function modifyButtons($name, $offset, $del=0, $add=null) {
foreach ($this->buttons as &$buttons) {
if (($idx = array_search($name, $buttons)) !== false) {
if ($add) array_splice($buttons, $idx+$offset, $del, $add);
else array_splice($buttons, $idx+$offset, $del, $add);
return true;
}
}
return false;
}
/**
* Insert buttons before the first occurance of another button
* @param string - the name of the button to insert other buttons before
* @param string a string, or several strings, or a single array of strings - the button names to insert before
* that button
* @return boolean - true if insertion occured, false if it did not (because the given button name was not found)
*/
public function insertButtonsBefore() {
$inserts = func_get_args();
$before = array_shift($inserts);
return $this->modifyButtons($before, 0, 0, $inserts);
}
/**
* Insert buttons after the first occurance of another button
* @param string - the name of the button to insert other buttons after
* @param string a string, or several strings, or a single array of strings - the button names to insert after
* that button
* @return boolean - true if insertion occured, false if it did not (because the given button name was not found)
*/
public function insertButtonsAfter() {
$inserts = func_get_args();
$after = array_shift($inserts);
return $this->modifyButtons($after, 1, 0, $inserts);
}
/**
* Remove the first occurance of buttons
* @param string one or more strings - the name of the buttons to remove
* @return null
*/
public function removeButtons() {
$removes = func_get_args();
foreach ($removes as $button) {
$this->modifyButtons($button, 0, 1);
}
}
/**
* Generate the javascript that will set tinyMCE's configuration to that of the current settings of this object
* @return string - the javascript
*/
public function generateJS() {
$config = $this->settings;
// plugins
$internalPlugins = array();
$externalPluginsJS = '';
foreach($this->plugins as $plugin => $path) {
if(!$path) {
$internalPlugins[] = $plugin;
} else {
$internalPlugins[] = '-' . $plugin;
$externalPluginsJS .= sprintf(
'tinymce.PluginManager.load("%s", "%s");' . "\n",
$plugin,
$path
);
}
}
$config['plugins'] = implode(',', $internalPlugins);
foreach ($this->buttons as $i=>$buttons) {
$config['theme_advanced_buttons'.$i] = implode(',', $buttons);
}
return "
if((typeof tinyMCE != 'undefined')) {
$externalPluginsJS
var ssTinyMceConfig = " . Convert::raw2json($config) . ";
}
";
}
}