From 1f2dd9ddcec615db4cba4f94450f3dad801c8232 Mon Sep 17 00:00:00 2001 From: Carsten Rose <carsten.rose@math.uzh.ch> Date: Thu, 6 Oct 2016 16:48:58 +0200 Subject: [PATCH] Support.php: escapes double ticks with " instead of \" - needed for JSON encoded config strings for TinyMCE. AbstractBuildForm.php: customize default setup for TinyMCE. --- extension/qfq/qfq/AbstractBuildForm.php | 45 +++++++++++++++++++--- extension/qfq/qfq/Constants.php | 4 ++ extension/qfq/qfq/helper/Support.php | 24 ++++++++++-- extension/qfq/tests/phpunit/DeleteTest.php | 2 +- extension/qfq/tests/phpunit/StoreTest.php | 3 ++ 5 files changed, 68 insertions(+), 10 deletions(-) diff --git a/extension/qfq/qfq/AbstractBuildForm.php b/extension/qfq/qfq/AbstractBuildForm.php index d8834c186..bf71873a3 100644 --- a/extension/qfq/qfq/AbstractBuildForm.php +++ b/extension/qfq/qfq/AbstractBuildForm.php @@ -1980,6 +1980,9 @@ abstract class AbstractBuildForm { } /** + * Build a HTML 'textarea' element which becomes a TinyMCE Editor. + * List of possible plugins: https://www.tinymce.com/docs/plugins/ + * * @param array $formElement * @param $htmlFormElementId * @param $value @@ -1990,20 +1993,25 @@ abstract class AbstractBuildForm { */ public function buildEditor(array $formElement, $htmlFormElementId, $value, array &$json, $mode = FORM_LOAD) { + //TODO plugin autoresize nutzen um Editorgroesse anzugeben + $this->adjustMaxLength($formElement); $attribute = Support::doAttribute('name', $htmlFormElementId); -// $attribute = Support::doAttribute('name', 'rte'); $attribute .= Support::doAttribute('id', $htmlFormElementId); $attribute .= Support::doAttribute('class', 'qfq-tinymce'); $attribute .= Support::doAttribute('data-control-name', "$htmlFormElementId"); $attribute .= Support::doAttribute('data-placeholder', $formElement['placeholder']); -// $attribute .= Support::doAttribute('data-value', htmlentities($value), false); // $attribute .= Support::doAttribute('data-autofocus', $formElement['autofocus']); $attribute .= Support::doAttribute('data-load', ($formElement['dynamicUpdate'] === 'yes') ? 'data-load' : ''); $attribute .= Support::doAttribute('data-title', $formElement['tooltip']); - $attribute .= Support::doAttribute('data-config', $this->getPrefixedElementsAsJSON(FE_EDITOR_PREFIX, $formElement)); + + $formElement = $this->setEditorConfig($formElement, $htmlFormElementId); + // $formElement['editor-plugins']='autoresize code' + // $formElement['editor-contextmenu']='link image | cell row column' + $json = $this->getPrefixedElementsAsJSON(FE_EDITOR_PREFIX, $formElement); + $attribute .= Support::doAttribute('data-config', $json, true, ESCAPE_WITH_HTML_QUOTE); $attribute .= $this->getAttributeFeMode($formElement[FE_MODE]); @@ -2015,6 +2023,33 @@ abstract class AbstractBuildForm { return $element . $this->getHelpBlock(); } + /** + * @param array $formElement + * @param $htmlFormElementId + * @return array + */ + private function setEditorConfig(array $formElement, $htmlFormElementId) { + + + if (!isset($formElement[FE_EDITOR_PREFIX . 'plugins'])) { + $formElement[FE_EDITOR_PREFIX . 'plugins'] = 'code link searchreplace table textcolor textpattern visualchars'; + } + + if (!isset($formElement[FE_EDITOR_PREFIX . 'toolbar'])) { + $formElement[FE_EDITOR_PREFIX . 'toolbar'] = 'code link searchreplace table forecolor backcolor visualchars'; + } + + if (isset($formElement['autofocus']) && $formElement['autofocus'] == 'yes') { + $formElement[FE_EDITOR_PREFIX . 'auto_focus'] = $htmlFormElementId; + } + + + // Disable the element path within the status bar at the bottom of the editor. + $formElement[FE_EDITOR_PREFIX . 'elementpath'] = 'false'; + + return $formElement; + } + /** * Searches for '$prefix*' elements in $formElement. Collect all found elements, strip $prefix (=$keyName) and * returns keys/values JSON encoded. @@ -2035,8 +2070,8 @@ abstract class AbstractBuildForm { $keyName = substr($key, strlen($prefix)); - if ($keyName == '' || !ctype_alpha($keyName)) { - throw new UserFormException("Empty '" . $prefix . "*' keyname or invalid characters: '" . $keyName . "'", ERROR_INVALID_EDITOR_PROPERTY_NAME); + if ($keyName == '') { + throw new UserFormException("Empty '" . $prefix . "*' keyname: '" . $keyName . "'", ERROR_INVALID_EDITOR_PROPERTY_NAME); } if ($value != '') { diff --git a/extension/qfq/qfq/Constants.php b/extension/qfq/qfq/Constants.php index 97f9f9071..1e3fb96cd 100644 --- a/extension/qfq/qfq/Constants.php +++ b/extension/qfq/qfq/Constants.php @@ -149,6 +149,8 @@ const ERROR_MISSING_TABLE_NAME = 1064; const ERROR_MISSING_TABLE = 1065; const ERROR_RECORD_NOT_FOUND = 1066; const ERROR_INVALID_EDITOR_PROPERTY_NAME = 1067; +const ERROR_UNKNOWN_ESCAPE_MODE = 1068; + // Subrecord const ERROR_SUBRECORD_MISSING_COLUMN_ID = 1100; @@ -481,6 +483,8 @@ const ACTION_KEYWORD_SLAVE_ID = 'slaveId'; // SUPPORT const PARAM_T3_ALL = 't3 all'; const PARAM_T3_NO_ID = "t3 no id"; +const ESCAPE_WITH_BACKSLASH = 'backslash'; +const ESCAPE_WITH_HTML_QUOTE = 'htmlquote'; // AbstractBuildForm const FLAG_ALL = 'flagAll'; diff --git a/extension/qfq/qfq/helper/Support.php b/extension/qfq/qfq/helper/Support.php index 407b3910c..e37cc6bbe 100644 --- a/extension/qfq/qfq/helper/Support.php +++ b/extension/qfq/qfq/helper/Support.php @@ -92,7 +92,7 @@ class Support { * @param bool $flagOmitEmpty * @return string */ - public static function doAttribute($type, $value, $flagOmitEmpty = true) { + public static function doAttribute($type, $value, $flagOmitEmpty = true, $modeEscape = ESCAPE_WITH_BACKSLASH) { if ($flagOmitEmpty && $value === "") { return ''; } @@ -114,23 +114,39 @@ class Support { break; } - $value = self::escapeDoubleTick(trim($value)); + $value = self::escapeDoubleTick(trim($value), $modeEscape); + return $type . '="' . $value . '" '; + } /** * Escapes Double Ticks ("), which are not already escaped. + * modeEscape: ESCAPE_WITH_BACKSLASH | ESCAPE_WITH_HTML_QUOTE + * + * TinyMCE: Encoding JS Attributes (keys & values) for TinyMCE needs to be encapsulated in '"' instead of '\"'. * * @param $str + * @param string $modeEscape * @return string + * @throws CodeException */ - public static function escapeDoubleTick($str) { + public static function escapeDoubleTick($str, $modeEscape = ESCAPE_WITH_BACKSLASH) { $newStr = ''; for ($ii = 0; $ii < strlen($str); $ii++) { if ($str[$ii] === '"') { if ($ii === 0 || $str[$ii - 1] != '\\') { - $newStr .= '\\'; + switch ($modeEscape) { + case ESCAPE_WITH_BACKSLASH: + $newStr .= '\\'; + break; + case ESCAPE_WITH_HTML_QUOTE: + $newStr .= '"'; + continue 2; + default: + throw new CodeException('Unknown modeEscape=' . $modeEscape, ERROR_UNKNOWN_ESCAPE_MODE); + } } } $newStr .= $str[$ii]; diff --git a/extension/qfq/tests/phpunit/DeleteTest.php b/extension/qfq/tests/phpunit/DeleteTest.php index 2e1cff860..89b6b0d5d 100644 --- a/extension/qfq/tests/phpunit/DeleteTest.php +++ b/extension/qfq/tests/phpunit/DeleteTest.php @@ -90,7 +90,7 @@ class DeleteTest extends \AbstractDatabaseTest { $this->assertEquals(false, $rc); - $expect = ['content' => "Record 100 not found in table 'Person'.", 'errorCode' => 1065]; + $expect = ['content' => "Record 100 not found in table 'Person'.", 'errorCode' => 1066]; $this->assertEquals($expect, $msg); } diff --git a/extension/qfq/tests/phpunit/StoreTest.php b/extension/qfq/tests/phpunit/StoreTest.php index fa58bb752..279283535 100644 --- a/extension/qfq/tests/phpunit/StoreTest.php +++ b/extension/qfq/tests/phpunit/StoreTest.php @@ -66,6 +66,9 @@ class StoreTest extends \PHPUnit_Framework_TestCase { public function testSetVarStoreSystem() { + // set new Sessionname + $this->store->setVar(SYSTEM_SQL_LOG_MODE, "all", STORE_SYSTEM); + // Sessionname: default value $this->assertEquals('all', $this->store->getVar(SYSTEM_SQL_LOG_MODE, STORE_SYSTEM), "System: SQL_LOG"); -- GitLab