Overview

Packages

  • CONTENIDO
  • Core
    • Authentication
    • Backend
    • Cache
    • CEC
    • Chain
    • ContentType
    • Database
    • Debug
    • Exception
    • Frontend
      • Search
      • URI
      • Util
    • GenericDB
      • Model
    • GUI
      • HTML
    • I18N
    • LayoutHandler
    • Log
    • Security
    • Session
    • Util
    • Validation
    • Versioning
    • XML
  • Module
    • ContentSitemapHtml
    • ContentSitemapXml
    • ContentUserForum
    • NavigationTop
    • ScriptCookieDirective
  • mpAutoloaderClassMap
  • None
  • PHP
  • Plugin
    • ContentAllocation
    • CronjobOverview
    • FormAssistant
    • FrontendLogic
    • FrontendUsers
    • Linkchecker
    • ModRewrite
    • Newsletter
    • Repository
      • FrontendNavigation
      • KeywordDensity
    • SmartyWrapper
    • UrlShortener
    • UserForum
    • Workflow
  • PluginManager
  • Setup
    • Form
    • GUI
    • Helper
      • Environment
      • Filesystem
      • MySQL
      • PHP
    • UpgradeJob

Classes

  • cAjaxRequest
  • cAutoload
  • cBackend
  • cEffectiveSetting
  • cGuiScrollListAlltranslations
  • cHTMLValidator
  • cMailer
  • cModuleFileTranslation
  • cModuleHandler
  • cModuleSearch
  • cModuleSynchronizer
  • cModuleTemplateHandler
  • CodeMirror
  • cPasswordRequest
  • cPermission
  • cRegistry
  • cSystemPurge
  • cSystemtest
  • cTinymce4Configuration
  • cTinyMCE4Editor
  • cTinyMCEEditor
  • cWYSIWYGEditor
  • FrontendList
  • HtmlParser
  • TODOBackendList
  • TreeItem
  • UploadList
  • UploadSearchResultList

Functions

  • addArtspec
  • addSortImages
  • backToMainArea
  • buildArticleSelect
  • buildCategorySelect
  • buildCategorySelectRights
  • buildHeapTable
  • buildStackString
  • buildTree
  • buildUserOrGroupPermsFromRequest
  • callPluginStore
  • cApiCatGetLevelNode
  • cApiImageCheckCachedImageValidity
  • cApiImageCheckImageEditingPosibility
  • cApiImageCheckImageEditingPossibility
  • cApiImageGetCacheFileName
  • cApiImageGetTargetDimensions
  • cApiImageIsAnimGif
  • cApiImgScale
  • cApiImgScaleGetMD5CacheFile
  • cApiImgScaleHQ
  • cApiImgScaleImageMagick
  • cApiImgScaleLQ
  • cApiIsImageMagickAvailable
  • cApiStrCleanURLCharacters
  • cApiStrNormalizeLineEndings
  • cApiStrRecodeString
  • cApiStrReplaceDiacritics
  • cApiStrTrimAfterWord
  • cApiStrTrimHard
  • cApiStrTrimSentence
  • cDeprecated
  • cDie
  • cError
  • checkLangInClients
  • checkPathInformation
  • cInclude
  • compareUrlStrings
  • conChangeTemplateForCat
  • conCopyArticle
  • conCopyArtLang
  • conCopyContainerConf
  • conCopyContent
  • conCopyMetaTags
  • conCopyTemplateConfiguration
  • conCreateLocationString
  • conDeeperCategoriesArray
  • conDeleteart
  • conEditArt
  • conEditFirstTime
  • conFetchCategoryTree
  • conFlagOnOffline
  • conGenerateCode
  • conGenerateCodeForAllArts
  • conGenerateCodeForAllArtsInCategory
  • conGenerateCodeForAllartsUsingLayout
  • conGenerateCodeForAllartsUsingMod
  • conGenerateCodeForAllArtsUsingTemplate
  • conGenerateCodeForArtInAllCategories
  • conGenerateCodeForClient
  • conGenerateKeywords
  • conGetAvailableMetaTagTypes
  • conGetCategoryArticleId
  • conGetCategoryAssignments
  • conGetContainerConfiguration
  • conGetContentFromArticle
  • conGetHtmlTranslationTable
  • conGetMetaValue
  • conGetTemplateConfigurationIdForArticle
  • conGetTemplateConfigurationIdForCategory
  • conGetTopmostCat
  • conGetUniqueArticleUrlname
  • conGetUsedModules
  • conHtmlentities
  • conHtmlEntityDecode
  • conHtmlSpecialChars
  • conIsArticleUrlnameUnique
  • conIsLocked
  • conLock
  • conLockBulkEditing
  • conMakeArticleIndex
  • conMakeCatOnline
  • conMakeInlineScript
  • conMakeOnline
  • conMakeOnlineBulkEditing
  • conMakePublic
  • conMakeStart
  • conMoveArticles
  • conPhp54Check
  • conRemoveOldCategoryArticle
  • conSaveContentEntry
  • conSetCodeFlag
  • conSetCodeFlagBulkEditing
  • conSetMetaValue
  • conSetStartArticle
  • consoleLog
  • conSyncArticle
  • copyRightsForElement
  • createBulkEditingFunction
  • createRandomName
  • createRightsForElement
  • cWarning
  • dbGetColumns
  • dbGetIndexes
  • dbGetPrimaryKeyName
  • dbTableExists
  • dbUpgradeTable
  • defineIfNotDefined
  • deleteArtspec
  • deleteRightsForElement
  • deleteSystemProperty
  • displayDatetime
  • emptyLogFile
  • endAndLogTiming
  • extractNumber
  • generateDisplayFilePath
  • generateJs
  • getAllClientsAndLanguages
  • getArtLang
  • getArtspec
  • getAvailableContentTypes
  • getCanonicalDay
  • getCanonicalMonth
  • getDirectorySize
  • getEffectiveSetting
  • getEffectiveSettingsByType
  • getEncodingByLanguage
  • getFileInformation
  • getFileType
  • getGroupOrUserName
  • getIDForArea
  • getJsHelpContext
  • getLanguageNamesByClient
  • getLanguagesByClient
  • getmicrotime
  • getNamedFrame
  • getParentAreaId
  • getRightsList
  • getSearchResults
  • getStrExpandCollapseButton
  • getSystemProperties
  • getSystemPropertiesByType
  • getSystemProperty
  • getTemplateSelect
  • getUplExpandCollapseButton
  • htmldecode
  • htmlentities_iso88592
  • humanReadableSize
  • includePlugins
  • insertEmptyStrRow
  • ipMatch
  • isAlphanumeric
  • isArchive
  • isArtInMultipleUse
  • isFunctionDisabled
  • isGroup
  • isIPv4
  • isRunningFromWeb
  • isStartArticle
  • isUtf8
  • isValidMail
  • langActivateDeactivateLanguage
  • langDeleteLanguage
  • langEditLanguage
  • langGetTextDirection
  • langNewLanguage
  • langRenameLanguage
  • layDeleteLayout
  • layEditLayout
  • machineReadableSize
  • mailLogBulkEditingFunctions
  • mailLogDecodeAddresses
  • markSubMenuItem
  • mask
  • modDeleteModule
  • modEditModule
  • phpInfoToHtml
  • plugin_include
  • prCreateURLNameLocationString
  • prDeleteCacheFileContent
  • prGetCacheFileContent
  • prResolvePathViaCategoryNames
  • prResolvePathViaURLNames
  • prWriteCacheFileContent
  • recursiveCopy
  • removeFileInformation
  • renderBackendBreadcrumb
  • renderLabel
  • renderSelectProperty
  • renderTextProperty
  • saveGroupRights
  • saveRights
  • scanDirectory
  • scanPlugins
  • sendEncodingHeader
  • set_magic_quotes_gpc
  • setArtspecDefault
  • setArtspecOnline
  • setSystemProperty
  • showTree
  • startTiming
  • statCreateLocationString
  • statDisplayTopChooser
  • statDisplayYearlyTopChooser
  • statGetAvailableMonths
  • statGetAvailableYears
  • statResetStatistic
  • statsArchive
  • statsDisplayInfo
  • statsOverviewAll
  • statsOverviewTop
  • statsOverviewTopYear
  • statsOverviewYear
  • strAssignTemplate
  • strBuildSqlValues
  • strCheckAlias
  • strCheckTreeForErrors
  • strCopyCategory
  • strCopyTree
  • strDeeperCategoriesArray
  • strDeleteCategory
  • strHasArticles
  • strHasStartArticle
  • strMakePublic
  • strMakeVisible
  • strMoveCatTargetallowed
  • strMoveDownCategory
  • strMoveSubtree
  • strMoveUpCategory
  • strNewCategory
  • strNewTree
  • strNextBackwards
  • strNextDeeper
  • strNextDeeperAll
  • strNextPost
  • strOrderedPostTreeList
  • strRemakeTreeTable
  • strRenameCategory
  • strRenameCategoryAlias
  • strSortPrePost
  • strSyncCategory
  • systemHavePerm
  • tplAutoFillModules
  • tplBrowseLayoutForContainers
  • tplcfgDuplicate
  • tplDeleteTemplate
  • tplDuplicateTemplate
  • tplEditTemplate
  • tplGetContainerDefault
  • tplGetContainerMode
  • tplGetContainerName
  • tplGetContainerNumbersInLayout
  • tplGetContainerTypes
  • tplGetInUsedData
  • tplIsTemplateInUse
  • tplPreparseLayout
  • tplProcessSendContainerConfiguration
  • updateClientCache
  • updateFileInformation
  • uplCreateFriendlyName
  • uplDirectoryListRecursive
  • uplGetDirectoriesToExclude
  • uplGetFileExtension
  • uplGetFileIcon
  • uplGetFileTypeDescription
  • uplGetThumbnail
  • uplHasFiles
  • uplHasSubdirs
  • uplmkdir
  • uplRecursiveDBDirectoryList
  • uplRecursiveDirectoryList
  • uplRenameDirectory
  • uplSearch
  • uplSyncDirectory
  • uplSyncDirectoryDBFS
  • Overview
  • Package
  • Class
  • Tree
  • Deprecated
  • Todo
  1: <?php
  2: /**
  3:  * This file contains the system integrity backend page.
  4:  *
  5:  * @package          Core
  6:  * @subpackage       Backend
  7:  * @author           Thomas Stauer
  8:  * @copyright        four for business AG <www.4fb.de>
  9:  * @license          http://www.contenido.org/license/LIZENZ.txt
 10:  * @link             http://www.4fb.de
 11:  * @link             http://www.contenido.org
 12:  */
 13: 
 14: defined('CON_FRAMEWORK') || die('Illegal call: Missing framework initialization - request aborted.');
 15: 
 16: /**
 17:  *
 18:  * @package    Core
 19:  * @subpackage Backend
 20:  */
 21: class cTinymce4Configuration {
 22: 
 23:     /**
 24:      *
 25:      * @var bool
 26:      */
 27:     public $successfully = false;
 28: 
 29:     /**
 30:      *
 31:      * @var bool
 32:      */
 33:     private $_perm = false;
 34: 
 35:     /**
 36:      *
 37:      * @var array
 38:      */
 39:     private $_configErrors = array();
 40: 
 41:     /**
 42:      * Constructor function.
 43:      * Inits permission.
 44:      */
 45:     public function __construct() {
 46:         global $currentuser;
 47: 
 48:         // decide whether user is allowed to change values
 49:         if (cRegistry::getPerm()->isSysadmin($currentuser) === true) {
 50:             $this->_perm = true;
 51:         }
 52:     }
 53: 
 54:     /**
 55:      * Generate a div containing a label and a textbox.
 56:      *
 57:      * @param string $description
 58:      *        Label text before the textbox
 59:      * @param string $name
 60:      *        Name of textbox form element
 61:      * @param string $value
 62:      *        Default value of textbox
 63:      * @param number $width
 64:      *        Width of label in px
 65:      * @return cHTMLDiv
 66:      *        The div element containing label and textbox
 67:      */
 68:     private function _addLabelWithTextarea($description, $name, $value = '', $width = 75) {
 69:         $label = new cHTMLLabel($description, $name);
 70:         $label->setClass("sys_config_txt_lbl");
 71:         $label->setStyle('width:' . $width . 'px; vertical-align: top;');
 72: 
 73:         $textarea = new cHTMLTextarea($name);
 74:         $textarea->setValue($value);
 75:         $textarea->setAttribute('style', 'box-sizing: border-box; width: 600px;');
 76:         if ($this->_perm === false) {
 77:             $textarea->updateAttribute('disabled', 'disabled');
 78:         }
 79:         $div = new cHTMLDiv($label .  $textarea, 'systemSetting');
 80: 
 81:         return $div;
 82:     }
 83: 
 84:     /**
 85:      * Generates a cHTMLCheckbox based on function arguments and sets
 86:      * its disabled state based on permission check.
 87:      *
 88:      * @param string $description
 89:      *        Description that will be displayed in checkbox label
 90:      * @param string $name
 91:      *        Name of checkbox, this is important for fetching values
 92:      *        from sent form
 93:      * @param string $value
 94:      *        The value that will be sent as content in the name key
 95:      * @param bool $checked
 96:      *        Whether this checkbox is setup as checked
 97:      * @return cHTMLCheckbox
 98:      *        Checkbox with label
 99:      */
100:     private function _addLabelWithCheckbox($description, $name, $value, $checked) {
101:         $checkBox = new cHTMLCheckbox($name, $value, str_replace('[]', '_', $name . $value), (true === $checked));
102:         $checkBox->setLabelText($description);
103: 
104:         if (false === $this->_perm) {
105:             $checkBox->updateAttribute('disabled', 'disabled');
106:         }
107: 
108:         return $checkBox;
109:     }
110: 
111:     /**
112:      * Check if a type pattern matches value.
113:      *
114:      * @param string $type
115:      *        Pattern that is applied to value
116:      * @param string $value
117:      *        Value that is checked for pattern
118:      * @return boolean
119:      *        Whether type matches value
120:      */
121:     private function _checkType($type, $value) {
122:         if (true === empty($value)) {
123:             return true;
124:         }
125:         if (true === isset($value)) {
126:             // parameter is known, check it using type expression
127:             // preg match returns 1 if match occurs
128:             return (1 === preg_match($type, $value));
129:         }
130: 
131:         return false;
132:     }
133: 
134:     /**
135:      *
136:      * @param array haystack
137:      * @param array $needles
138:      * @return bool
139:      */
140:     private function _checkIsset(array $haystack, array $needles) {
141:         if (count($haystack) !== count($needles)) {
142:             return false;
143:         }
144:         foreach ($needles as $needle) {
145:             if (false === isset($haystack[$needle])) {
146:                 return false;
147:             }
148:         }
149: 
150:         return true;
151:     }
152: 
153:     /**
154:      * This function lists all external plugins that should be shown in
155:      * a table.
156:      *
157:      * @return string
158:      */
159:     private function _listExternalPlugins() {
160:         /// TODO: use a preference loading function for plugins to list
161:         $externalPlugins = static::get(array(), 'raw', 'externalplugins');
162: 
163:         // build a table
164:         $table = new cHTMLTable();
165:         $table->setClass('generic');
166: 
167:         // table row
168:         $headrow = new cHTMLTableRow();
169: 
170:         // table column 1 (plugin name)
171:         $col = new cHTMLTableHead();
172:         $col->appendContent(i18n('Name'));
173:         $headrow->appendContent($col);
174: 
175:         // table column 2 (plugin url)
176:         $col = new cHTMLTableHead();
177:         $col->appendContent(i18n('URL'));
178:         $headrow->appendContent($col);
179: 
180:         // table column 3 (user actions)
181:         $col = new cHTMLTableHead();
182:         $col->appendContent(i18n('Action'));
183:         $headrow->appendContent($col);
184: 
185:         // add columns to table
186:         $table->appendContent($headrow);
187: 
188:         // build table body
189:         $tbody = new cHTMLTableBody();
190:         $i = 0;
191:         $n = count($externalPlugins) -1;
192:         for ($i; $i < $n; $i++) {
193:             // new tr
194:             $row = new cHTMLTableRow();
195: 
196:             // create new td
197:             $td = new cHTMLTableData();
198:             $td->appendContent($externalPlugins[$i]['name']);
199: 
200:             // insert hidden input field
201:             $input = new cHTMLFormElement();
202:             $input->setAttribute('type', 'hidden');
203:             $input->setAttribute('name', 'externalplugins[' . $i . '][name]');
204:             $input->setAttribute('value', $externalPlugins[$i]['name']);
205:             $td->appendContent($input);
206: 
207:             // add td to tr
208:             $row->appendContent($td);
209: 
210:             // create new td
211:             $td = new cHTMLTableData();
212:             $td->appendContent($externalPlugins[$i]['url']);
213: 
214:             // insert hidden input field
215:             $input = new cHTMLFormElement();
216:             $input->setAttribute('type', 'hidden');
217:             $input->setAttribute('name', 'externalplugins[' . $i . '][url]');
218:             $input->setAttribute('value', $externalPlugins[$i]['url']);
219:             $td->appendContent($input);
220: 
221:             // add td to tr
222:             $row->appendContent($td);
223: 
224:             // create new td
225:             $td = new cHTMLTableData();
226:             if (true === $this->_perm) {
227:                 // Edit/delete links only for sysadmin
228:                 $oLinkDelete = new cHTMLLink();
229:                 $oLinkDelete->setCLink(cRegistry::getArea(), cRegistry::getFrame(), "system_wysiwyg_tinymce4_delete_item");
230:                 $oLinkDelete->setCustom("external_plugin_idx", urlencode($i));
231:                 $img = new cHTMLImage(cRegistry::getBackendUrl() . cRegistry::getConfigValue('path', 'images') . 'delete.gif');
232:                 $img->setAttribute('alt', i18n("Delete"));
233:                 $img->setAttribute('title', i18n("Delete"));
234:                 $oLinkDelete->appendContent($img);
235:                 $td->appendContent($oLinkDelete);
236:             }
237: 
238:             // add td to tr
239:             $row->appendContent($td);
240: 
241:             // insert row into table body
242:             $tbody->appendContent($row);
243:         }
244:         // append empty row to let user enter new plugins
245:         $row = new cHTMLTableRow();
246: 
247:         // create new td for plugin name
248:         $td = new cHTMLTableData();
249:         $input = new cHTMLFormElement('externalplugins[' . $i . '][name]');
250:         $td->appendContent($input);
251:         $row->appendContent($td);
252: 
253:         // create new td for plugin url
254:         $td = new cHTMLTableData();
255:         $input = new cHTMLFormElement('externalplugins[' . $i . '][url]');
256:         $td->appendContent($input);
257:         $row->appendContent($td);
258: 
259:         // empty action column
260:         $td = new cHTMLTableData();
261:         $row->appendContent($td);
262: 
263:         // append row to table body
264:         $tbody->appendContent($row);
265: 
266: 
267:         // insert table body into table
268:         $table->appendContent($tbody);
269: 
270:         // return table as string
271:         return $table->render();
272:     }
273: 
274:     /**
275:      * Function to check if toolbar data contains valid input.
276:      *
277:      * @param string $toolbarData
278:      *        The toolbar data to check for validity
279:      * @return boolean
280:      *        True if toolbar data is valid, false otherwise
281:      */
282:     private function _validateToolbarN($toolbarData) {
283:         // do not use cRequestValidator instance
284:         // because it does not support multi-dimensional arrays
285:         if (false === $this->_checkType('/^[a-zA-Z0-9 \-\|_]*$/', $toolbarData)
286:         || false !== cString::findFirstPos($toolbarData, '||')) {
287:             return false;
288:         }
289: 
290:         return true;
291:     }
292: 
293:     /**
294:      * Variadic function to obtain config values using nested key values.
295:      *
296:      * @param mixed $default
297:      *        Default value to use in case no value is set
298:      * param string keys
299:      *        The keys to access values in configuration
300:      * @return string|array
301:      */
302:     public static function get($default) {
303:         $cfg = cRegistry::getConfig();
304: 
305:         if (false === isset($cfg['wysiwyg'])
306:         || false === isset($cfg['wysiwyg']['tinymce4'])) {
307:             $configPath = cRegistry::getConfigValue('path', 'contenido_config') . 'config.wysiwyg_tinymce4.php';
308:             // check if configuration file exists
309:             if (true !== cFileHandler::exists($configPath)) {
310:                 return $default;
311:             }
312:             // check if file is reable
313:             if (true !== cFileHandler::readable($configPath)) {
314:                 return $default;
315:             }
316:             // Include configuration file
317:             require $configPath;
318:         }
319: 
320:         // check number of keys passed to function
321:         $numargs = func_num_args();
322:         if (0 === $numargs) {
323:             return $default;
324:         }
325: 
326:         // walk through config
327:         $result = cRegistry::getConfig();
328: 
329:         // select ['wysiwyg']['tinymce4'] by default
330:         if (false === isset($result['wysiwyg'])) {
331:             return $default;
332:         }
333:         if (false === $result['wysiwyg']['tinymce4']) {
334:             return $default;
335:         }
336:         $result = $result['wysiwyg']['tinymce4'];
337:         // get values in key path that user requested
338:         for ($i = 0; $i < $numargs -1; $i++) {
339:             if (false === isset($result[func_get_arg(1 + $i)])) {
340:                 return $default;
341:             }
342:             // jump one array level deeper into the result
343:             $result = $result[func_get_arg(1 + $i)];
344:         }
345: 
346:         return $result;
347:     }
348: 
349:     /**
350:      * Function to validate form from showConfigurationForm().
351:      *
352:      * @param array $config
353:      *        The post parameters of submitted form
354:      * @return boolean|array
355:      *        False if data should not be saved, otherwise data to save
356:      */
357:     public function validateForm($config) {
358:         // Checks for cross site requests and cross site scripting
359:         // are omitted due to time constraints
360: 
361:         if ($this->_perm === false) {
362:             return false;
363:         }
364: 
365:         // remove not used area field
366:         unset($config['area']);
367:         // remove not used frame field
368:         unset($config['frame']);
369:         // remove not used contenido field
370:         unset($config['contenido']);
371: 
372:         // remove x and y values from image submit button in in form
373:         unset($config['submit_x']);
374:         unset($config['submit_y']);
375: 
376:         // form action (added in showConfigurationForm() inside this
377:         // class) is not used for saving config
378:         if ('system_wysiwyg_tinymce4_delete_item' === $_GET['action']) {
379:             return $this->removeExternalPluginLoad($_GET);
380:         }
381:         unset($config['action']);
382: 
383:         // check if config should be deleted
384:         if (isset($_POST['reset'])) {
385:             $noti = new cGuiNotification();
386: 
387:             // try to delete configuration
388:             $configPath = cRegistry::getConfigValue('path', 'contenido_config');
389:             $configPath .= 'config.wysiwyg_tinymce4.php';
390:             if (cFileHandler::exists($configPath)
391:             && cFileHandler::writeable($configPath)) {
392:                 cFileHandler::remove($configPath);
393:                 $noti->displayNotification(cGuiNotification::LEVEL_INFO, i18n('TinyMCE 4 configuration got reset back to default'));
394:             } else {
395:                 // can not delete config, display message
396:                 $noti->displayNotification(cGuiNotification::LEVEL_ERROR, i18n('Can not delete config file'));
397:             }
398: 
399:             // do not save config
400:             return false;
401:         }
402: 
403:         // check if all array entries actually exist
404:         // abort if too many values are encountered
405:         $shouldArrayStructure =  array (
406:             'tinymce4_full' =>
407:             array (
408:                     'toolbar1',
409:                     'toolbar2',
410:                     'toolbar3',
411:                     'plugins'
412:             ),
413:             'tinymce4_fullscreen' =>
414:             array (
415:                     'toolbar1',
416:                     'toolbar2',
417:                     'toolbar3',
418:                     'plugins'
419:             ),
420:             'contenido_lists',
421:             'contenido_gzip',
422:             'custom',
423:         );
424: 
425:         // get name of first key
426:         reset($config);
427:         $key = key($config);
428: 
429:         if (false === isset($_POST['externalplugins']) && false === $this->_checkIsset($config[$key]['tinymce4_full'], $shouldArrayStructure['tinymce4_full'])) {
430:             $this->_configErrors[] = i18n('Fullscreen config of inline editor is erroneous.');
431:             return false;
432:         }
433:         if (false === isset($_POST['externalplugins']) && false === $this->_checkIsset($config[$key]['tinymce4_fullscreen'], $shouldArrayStructure['tinymce4_fullscreen'])) {
434:             $this->_configErrors[] = i18n('Config of editor on separate editor page is erroneous.');
435:             return false;
436:         }
437:         if (false === isset($_POST['externalplugins']) && false === isset($config[$key]['custom'])) {
438:             $this->_configErrors[] = i18n('Custom configuration of tinyMCE 4 is not set.');
439:             return false;
440:         }
441: 
442:         // do not use cRequestValidator instance because it does not support multi-dimensional arrays
443:         if (false === $this->_validateToolbarN($config[$key]['tinymce4_full']['toolbar1'])
444:         || false === $this->_validateToolbarN($config[$key]['tinymce4_full']['toolbar2'])
445:         || false === $this->_validateToolbarN($config[$key]['tinymce4_full']['toolbar3'])
446:         || false === $this->_validateToolbarN($config[$key]['tinymce4_fullscreen']['toolbar1'])
447:         || false === $this->_validateToolbarN($config[$key]['tinymce4_fullscreen']['toolbar2'])
448:         || false === $this->_validateToolbarN($config[$key]['tinymce4_fullscreen']['toolbar3'])) {
449:             $this->_configErrors[] = i18n('Toolbar(s) of editor contain erroneous data.');
450:             return false;
451:         }
452: 
453:         // remove last entry of external plugins if it is empty
454:         $lastExternalPlugin = $config[$key]['externalplugins'][count($config[$key]['externalplugins']) -1];
455:         if ('' === $lastExternalPlugin['name']
456:         && '' === $lastExternalPlugin['url']) {
457:             unset($config[$key]['externalplugins'][count($config[$key]['externalplugins']) -1]);
458:         }
459: 
460:         // custom tinymce 4 settings overwrite other fields
461:         if (cRegistry::getConfigValue('simulate_magic_quotes') === true) {
462:             $config[$key]['custom'] = stripslashes($config[$key]['custom']);
463:         }
464: 
465:         // unescape strings then build config
466:         $customConfig = (array) json_decode($config[$key]['custom'], true);
467:         switch(json_last_error()) {
468:             case JSON_ERROR_DEPTH:
469:                 $this->_configErrors[] = i18n('Maximum stack depth exceeded while decoding json');
470:             return false;
471:             case JSON_ERROR_CTRL_CHAR:
472:                 $this->_configErrors[] = i18n('Unexpected control character found');
473:             return false;
474:             case JSON_ERROR_SYNTAX:
475:                 $this->_configErrors[] = i18n('Syntax error, malformed JSON');
476:             return false;
477:         }
478: 
479:         // append new config to old config
480:         $origConfig = static::get(array(), 'raw');
481:         $config['raw'] = array_merge($origConfig, $config);
482:         //$config['raw'] = $config;
483: 
484:         // use custom parameters if they are correct JSON
485:         if (JSON_ERROR_NONE === json_last_error()) {
486:             $config[$key] = array_merge($config[$key], $customConfig);
487:         }
488:         unset($config[$key]['custom']);
489: 
490:         // put all config values into ['tinymce4']['tinymce4']
491:         // put the raw settings of config page into ['tinymce4']['raw']
492:         $origConfig = static::get(array(), 'tinymce4');
493:         $config = array_merge($origConfig, $config);
494:         $res = array('tinymce4' => array('tinymce4' =>$config));
495:         //unset($res['tinymce4']['tinymce4']['custom']);
496:         $res['tinymce4']['raw'] = $res['tinymce4']['tinymce4']['raw'];
497:         unset($res['tinymce4']['tinymce4']['raw']);
498: 
499:         // $config contains only valid content, returned processed config
500:         return $res;
501:     }
502: 
503:     /**
504:      * Do not load external plugin if user has permission to request that.
505:      *
506:      * @param array $form
507:      *        get parameters from deletion link
508:      * @return boolean|array
509:      *        False if data should not be saved, otherwise data to save
510:      */
511:     public function removeExternalPluginLoad($form) {
512:         // abort if user has not sufficient permissions
513:         if (false === $this->_perm) {
514:             return;
515:         }
516: 
517:         $pluginToRemoveIdx = (int) $form['external_plugin_idx'];
518: 
519:         // load config through usage of get function
520:         $settings = static::get(false);
521: 
522:         // no config or no external plugins or no plugin with that index
523:         // means nothing to remove
524:         if (false === $settings
525:         || false === isset($settings['raw'])
526:         || false === isset($settings['raw']['externalplugins'])
527:         || false === isset($settings['raw']['externalplugins'][$pluginToRemoveIdx])) {
528:             return false;
529:         }
530: 
531:         // remove value from raw settings
532:         unset($settings['raw']['externalplugins'][$pluginToRemoveIdx]);
533:         // remove stray custom setting
534:         unset($settings['raw']['externalplugins']['custom']);
535: 
536:         // re-index array
537:         $settings['raw']['externalplugins'] = array_values($settings['raw']['externalplugins']);
538: 
539:         // apply raw settings to computed settings
540:         $settings['tinymce4']['externalplugins'] = $settings['raw']['externalplugins'];
541: 
542:         return array('tinymce4' => $settings);
543:     }
544: 
545:     /**
546:      * Generates an HTML form to configure tinymce 4.
547:      */
548:     public function showConfigurationForm() {
549:         $page = new cGuiPage('system_wysiwyg_tinymce4', '', '5');
550:         $auth = cRegistry::getAuth();
551:         $frame = cRegistry::getFrame();
552:         $area = cRegistry::getArea();
553: 
554:         // validate if user has permission to edit this area
555:         if (false === cRegistry::getPerm()->have_perm_area_action($area, 'edit_system_wysiwyg_tinymce4')) {
556:             $page->displayCriticalError(i18n('Access denied'));
557:             $page->render();
558:             return;
559:         }
560: 
561:         if (count($this->_configErrors) > 0) {
562:             $errorMessage = i18n('The following errors occurred when trying to verify configuration:') . '<ul>';
563:             foreach ($this->_configErrors as $error) {
564:                 $errorMessage .= '<li>' . $error . '</li>';
565:             }
566:             $errorMessage .= '</ul>';
567:             $page->displayError($errorMessage);
568:         }
569: 
570:         if ($this->successfully === true) $page->displayOk(i18n("Changes saved successfully!"));
571: 
572:         $page->displayInfo(sprintf(i18n('Currently active WYSIWYG editor: %s'), cWYSIWYGEditor::getCurrentWysiwygEditorName()));
573: 
574:         $oTypeColl = new cApiTypeCollection();
575:         $oTypeColl->select();
576:         $result = '';
577:         while (false !== ($typeEntry = $oTypeColl->next())) {
578:             // specify a shortcut for type field
579:             $curType = $typeEntry->get('type');
580: 
581:             $contentTypeClassName = cTypeGenerator::getContentTypeClassName($curType);
582:             if (false === class_exists($contentTypeClassName)) {
583:                 continue;
584:             }
585:             $cContentType = new $contentTypeClassName(null, 0, array());
586:             if (false === $cContentType->isWysiwygCompatible()) {
587:                 continue;
588:             }
589: 
590: 
591:             $form = new cGuiTableForm('system_wysiwyg_tinymce4_' . strtolower($curType));
592:             $form->setAcceptCharset('UTF-8');
593: 
594:             $form->addHeader(i18n('TinyMCE 4 configuration for ') . $curType);
595: 
596:             $form->setVar('area', $area);
597:             $form->setVar('frame', $frame);
598:             $form->setVar('action', 'edit_tinymce4');
599: 
600: 
601:             $containerDiv = new cHTMLDiv();
602:             if ('CMS_HTMLHEAD' === $curType) {
603:                 $defaultToolbar1 = static::get('undo redo | consave conclose', 'raw', $curType, 'tinymce4_full', 'toolbar1');
604:                 $defaultToolbar2 = static::get('', 'raw', $curType, 'tinymce4_full', 'toolbar2');
605:                 $defaultToolbar3 = static::get('', 'raw', $curType, 'tinymce4_full', 'toolbar3');
606:                 $defaultPlugins = static::get('conclose', 'raw', $curType, 'tinymce4_full', 'plugins');
607:             } else {
608:                 $defaultToolbar1 = static::get('cut copy paste pastetext | searchreplace | undo redo | bold italic underline strikethrough subscript superscript | insertdatetime preview | visualchars nonbreaking template pagebreak | help | fullscreen', 'raw', $curType, 'tinymce4_full', 'toolbar1');
609:                 $defaultToolbar2 = static::get('link unlink anchor image media hr | bullist numlist | outdent indent blockquote | alignleft aligncenter alignright alignfull removeformat | forecolor backcolor | ltr rtl | charmap | code', 'raw', $curType, 'tinymce4_full', 'toolbar2');
610:                 $defaultToolbar3 = static::get('table | formatselect fontselect fontsizeselect | consave conclose', 'raw', $curType, 'tinymce4_full', 'toolbar3');
611:                 $defaultPlugins = static::get('charmap code table conclose hr image link pagebreak layer insertdatetime preview anchor media searchreplace print contextmenu paste directionality fullscreen visualchars nonbreaking template textcolor', 'raw', $curType, 'tinymce4_full', 'plugins');
612:             }
613:             $containerDiv->appendContent($this->_addLabelWithTextarea('Toolbar 1:', $curType . '[tinymce4_full][toolbar1]', $defaultToolbar1));
614:             $containerDiv->appendContent($this->_addLabelWithTextarea('Toolbar 2:', $curType . '[tinymce4_full][toolbar2]', $defaultToolbar2));
615:             $containerDiv->appendContent($this->_addLabelWithTextarea('Toolbar 3:', $curType . '[tinymce4_full][toolbar3]', $defaultToolbar3));
616:             $containerDiv->appendContent($this->_addLabelWithTextarea('Plugins:', $curType . '[tinymce4_full][plugins]', $defaultPlugins));
617:             $form->add(i18n('Settings of editor in separate editor page'), $containerDiv->render());
618: 
619:             $containerDiv = new cHTMLDiv();
620:             if ('CMS_HTMLHEAD' === $curType) {
621:                 $defaultToolbar1 = static::get('undo redo | consave conclose', 'raw', $curType, 'tinymce4_inline', 'toolbar1');
622:                 $defaultToolbar2 = static::get('', 'raw', $curType, 'tinymce4_inline', 'toolbar2');
623:                 $defaultToolbar3 = static::get('', 'raw', $curType, 'tinymce4_inline', 'toolbar3');
624:                 $defaultPlugins = static::get('conclose', 'raw', $curType, 'tinymce4_inline', 'plugins');
625:             } else {
626:                 $defaultToolbar1 = static::get('bold italic underline strikethrough | undo redo | bullist numlist separator forecolor backcolor | alignleft aligncenter alignright | confullscreen | consave conclose', 'raw', $curType, 'tinymce4_inline', 'toolbar1');
627:                 $defaultToolbar2 = static::get('', 'raw', $curType, 'tinymce4_inline', 'toolbar2');
628:                 $defaultToolbar3 = static::get('', 'raw', $curType, 'tinymce4_inline', 'toolbar3');
629:                 $defaultPlugins = static::get('conclose confullscreen media table textcolor', 'raw', $curType, 'tinymce4_inline', 'plugins');
630:             }
631:             $containerDiv->appendContent($this->_addLabelWithTextarea('Toolbar 1:', $curType . '[tinymce4_inline][toolbar1]', $defaultToolbar1));
632:             $containerDiv->appendContent($this->_addLabelWithTextarea('Toolbar 2:', $curType . '[tinymce4_inline][toolbar2]', $defaultToolbar2));
633:             $containerDiv->appendContent($this->_addLabelWithTextarea('Toolbar 3:', $curType . '[tinymce4_inline][toolbar3]', $defaultToolbar3));
634:             $containerDiv->appendContent($this->_addLabelWithTextarea('Plugins:', $curType . '[tinymce4_inline][plugins]', $defaultPlugins));
635:             $form->add(i18n('Settings of inline editor in inline mode'), $containerDiv->render());
636: 
637:             $containerDiv = new cHTMLDiv();
638:             if ('CMS_HTMLHEAD' === $curType) {
639:                 $defaultToolbar1 = static::get('undo redo | consave conclose', 'raw', $curType, 'tinymce4_fullscreen', 'toolbar1');
640:                 $defaultToolbar2 = static::get('', 'raw', $curType, 'tinymce4_fullscreen', 'toolbar2');
641:                 $defaultToolbar3 = static::get('', 'raw', $curType, 'tinymce4_fullscreen', 'toolbar3');
642:                 $defaultPlugins = static::get('conclose', 'raw', $curType, 'tinymce4_fullscreen', 'plugins');
643:             } else {
644:                 $defaultToolbar1 = static::get('cut copy paste pastetext | searchreplace | undo redo | bold italic underline strikethrough subscript superscript | insertdatetime preview | visualchars nonbreaking template pagebreak | help | fullscreen', 'raw', $curType, 'tinymce4_fullscreen', 'toolbar1');
645:                 $defaultToolbar2 = static::get('link unlink anchor image media | bullist numlist | outdent indent blockquote | alignleft aligncenter alignright alignfull removeformat | forecolor backcolor | ltr rtl | charmap | code', 'raw', $curType, 'tinymce4_fullscreen', 'toolbar2');
646:                 $defaultToolbar3 = static::get('table | formatselect fontselect fontsizeselect | consave conclose', 'raw', $curType, 'tinymce4_fullscreen', 'toolbar3');
647:                 $defaultPlugins = static::get('charmap code conclose table hr image link pagebreak layer insertdatetime preview anchor media searchreplace print contextmenu paste directionality fullscreen visualchars nonbreaking template textcolor', 'raw', $curType, 'tinymce4_fullscreen', 'plugins');
648:             }
649:             $containerDiv->appendContent($this->_addLabelWithTextarea('Toolbar 1:', $curType . '[tinymce4_fullscreen][toolbar1]', $defaultToolbar1));
650:             $containerDiv->appendContent($this->_addLabelWithTextarea('Toolbar 2:', $curType . '[tinymce4_fullscreen][toolbar2]', $defaultToolbar2));
651:             $containerDiv->appendContent($this->_addLabelWithTextarea('Toolbar 3:', $curType . '[tinymce4_fullscreen][toolbar3]', $defaultToolbar3));
652:             $containerDiv->appendContent($this->_addLabelWithTextarea('Plugins:', $curType . '[tinymce4_fullscreen][plugins]', $defaultPlugins));
653:             $form->add(i18n('Settings of inline editor in fullscreen mode'), $containerDiv->render());
654: 
655:             // GZIP editor over HTTP using tinymce's library
656:             $containerDiv = new cHTMLDiv();
657:             $checked = 'contenido_gzip' === static::get(false, 'raw', $curType, 'contenido_gzip');
658:             $containerDiv->appendContent($this->_addLabelWithCheckbox(i18n('GZIP TinyMCE (only activate if server does not compress content already)'), $curType . '[contenido_gzip]', 'contenido_gzip', $checked));
659:             $form->add(i18n('contenido_gzip'), $containerDiv->render());
660: 
661:             // Add jump lists to tinymce's dialogs
662:             $containerDiv = new cHTMLDiv();
663:             $checked = true === ('image' === static::get(false, 'raw', $curType, 'contenido_lists', 'image'));
664:             $containerDiv->appendContent($this->_addLabelWithCheckbox(i18n('Provide jump lists in image insertion dialog'), $curType . '[contenido_lists][image]', 'image', $checked));
665:             $checked = true === ('link' === static::get(false, 'raw', $curType, 'contenido_lists', 'link'));
666:             $containerDiv->appendContent($this->_addLabelWithCheckbox(i18n('Provide jump lists in link insertion dialog'), $curType . '[contenido_lists][link]', 'link', $checked));
667:             $form->add(i18n('contenido_lists'), $containerDiv->render());
668: 
669:             //add textarea for custom tinymce 4 settings
670:             $textarea = new cHTMLTextarea($curType . '[custom]');
671:             $textarea->setAttribute('style', 'width: 99%;');
672:             $defaultParams = '';
673:             if ('CMS_HTMLHEAD' === $curType) {
674:                 $defaultParams = '{' . PHP_EOL . '"inline": true,' . PHP_EOL . '"menubar": false' . PHP_EOL . '}';
675:             }
676:             $textarea->setValue(static::get($defaultParams, 'raw', $curType, 'custom'));
677:             $form->add(i18n('Additional parameters (JSON passed to tinymce constructor)'), $textarea->render());
678: 
679:             // check permission to save system wysiwyg editor settings
680:             if (false === $this->_perm) {
681:                 $form->setActionButton('submit', cRegistry::getBackendUrl() . 'images/but_ok_off.gif', i18n("You are not sysadmin. You can't change these settings."), 's');
682:             }
683:             $result .= '<p>' . $form->render() . '</p>';
684:         }
685: 
686:         // external plugins (can not be configured per CMS-type)
687:         $form = new cGuiTableForm('system_wysiwyg_tinymce4_external_plugins');
688:         $form->setAcceptCharset('UTF-8');
689:         $form->addHeader(i18n('TinyMCE 4 configuration for external plugins'));
690: 
691:         $form->setVar('area', $area);
692:         $form->setVar('frame', $frame);
693:         $form->setVar('action', 'edit_tinymce4');
694:         $containerDiv = new cHTMLDiv();
695:         $containerDiv->appendContent($this->_listExternalPlugins());
696:         $form->add(i18n('External plugins to load'), $containerDiv);
697:         $result .= '<p>' . $form->render() . '</p>';
698: 
699:         $configPath = cRegistry::getConfigValue('path', 'contenido_config');
700:         $configPath .= 'config.wysiwyg_tinymce4.php';
701:         if (cFileHandler::exists($configPath)
702:         && cFileHandler::writeable($configPath)) {
703:             $resetForm = new cHTMLForm('system_wysiwyg_tinymce4_general_options', 'main.php', 'post');
704:             $resetForm->setVar('area', $area);
705:             $resetForm->setVar('frame', $frame);
706:             $resetForm->setVar('action', 'edit_tinymce4');
707:             $oResetButton = new cHTMLButton('reset', i18n('Reset configuration back to default'));
708:             $oResetButton->setAttribute('value', i18n('Reset Configuration'));
709: 
710:             $resetForm = $resetForm->appendContent($oResetButton);
711:             $result .= $resetForm->render();
712:         }
713: 
714: 
715:         $page->set('s', 'FORM', $result);
716:         $page->set('s', 'RELOAD_HEADER', (false) ? 'true' : 'false');
717:         $page->render();
718:     }
719: }
720: 
CMS CONTENIDO 4.10.0 API documentation generated by ApiGen 2.8.0