Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • mhuber84/tinymce4_rte
  • agrein/tinymce4_rte
  • DjRussRuss/tinymce4_rte
  • mbrodala/tinymce4_rte
  • vinciygialam/tinymce4_rte
5 results
Show changes
Commits on Source (116)
Showing
with 4064 additions and 2917 deletions
<?php
namespace SGalinski\Tinymce4Rte;
/***************************************************************
* Copyright notice
*
* (c) sgalinski Internet Services (http://www.sgalinski.de)
*
* All rights reserved
*
* This script is part of the TYPO3 project. The TYPO3 project is
* free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* The GNU General Public License can be found at
* http://www.gnu.org/copyleft/gpl.html.
*
* This script is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* This copyright notice MUST APPEAR in all copies of the script!
***************************************************************/
use TYPO3\CMS\Backend\Utility\BackendUtility;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Lang\LanguageService;
use TYPO3\CMS\Recordlist\Browser\ElementBrowser;
/**
* Script class for the Element Browser window.
*/
class BrowseLinks extends ElementBrowser {
public $editorNo;
/**
* TYPO3 language code of the content language
*/
public $contentTypo3Language;
public $contentTypo3Charset = 'utf-8';
/**
* Language service object for localization to the content language
*/
protected $contentLanguageService;
public $additionalAttributes = array();
public $buttonConfig = array();
public $RTEProperties = array();
public $anchorTypes = array('page', 'url', 'file', 'mail', 'spec');
public $classesAnchorDefault = array();
public $classesAnchorDefaultTitle = array();
public $classesAnchorClassTitle = array();
public $classesAnchorDefaultTarget = array();
public $classesAnchorJSOptions = array();
protected $defaultLinkTarget;
public $allowedItems;
/**
* Constructor:
* Initializes a lot of variables, setting JavaScript functions in header etc.
*
* @return void
* @todo Define visibility
*/
public function init() {
$this->initVariables();
// Create content language service
/** @var LanguageService contentLanguageService */
$this->contentLanguageService = GeneralUtility::makeInstance('TYPO3\\CMS\\Lang\\LanguageService');
$this->contentLanguageService->init($GLOBALS['BE_USER']->uc['lang']);
$this->initConfiguration();
$this->initDocumentTemplate();
// Initializing hooking browsers
$this->initHookObjects('ext/rtehtmlarea/mod3/class.tx_rtehtmlarea_browse_links.php');
$this->initCurrentUrl();
// Determine nature of current url:
$this->act = GeneralUtility::_GP('act');
if (!$this->act) {
$this->act = $this->curUrlInfo['act'];
}
// Setting initial values for link attributes
$this->initLinkAttributes();
// Adding RTE JS code
// also unset the default jumpToUrl() function before
unset($this->doc->JScodeArray['jumpToUrl']);
$this->doc->JScodeArray['rtehtmlarea'] = $this->getJSCode();
}
/**
* Initialize class variables
*
* @return void
*/
public function initVariables() {
parent::initVariables();
// Process bparams
$pArr = explode('|', $this->bparams);
$pRteArr = explode(':', $pArr[1]);
$this->editorNo = $pRteArr[0];
$this->contentTypo3Language = $pRteArr[1];
$this->RTEtsConfigParams = $pArr[2];
if (!$this->editorNo) {
$this->editorNo = GeneralUtility::_GP('editorNo');
$this->contentTypo3Language = GeneralUtility::_GP('contentTypo3Language');
$this->RTEtsConfigParams = GeneralUtility::_GP('RTEtsConfigParams');
}
$pArr[1] = implode(':', array($this->editorNo, $this->contentTypo3Language, $this->contentTypo3Charset));
$pArr[2] = $this->RTEtsConfigParams;
$this->bparams = implode('|', $pArr);
}
/**
* Initializes the configuration variables
*
* @return void
*/
public function initConfiguration() {
$this->thisConfig = $this->getRTEConfig();
$this->buttonConfig = $this->getButtonConfig('link');
}
/**
* Initialize document template object
*
* @return void
*/
protected function initDocumentTemplate() {
parent::initDocumentTemplate();
$this->doc->getContextMenuCode();
// Apply the same styles as those of the base script
$this->doc->bodyTagId = 'typo3-browse-links-php';
$this->doc->getPageRenderer()->addCssFile(
$this->doc->backPath . \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::extRelPath(
't3skin'
) . 'rtehtmlarea/htmlarea.css'
);
// Add attributes to body tag. Note: getBodyTagAdditions will invoke the hooks
$this->doc->bodyTagAdditions = $this->getBodyTagAdditions();
}
/**
* Initialize $this->curUrlArray and $this->curUrlInfo based on script parameters
*
* @return void
*/
protected function initCurrentUrl() {
// CurrentUrl - the current link url must be passed around if it exists
$this->curUrlArray = GeneralUtility::_GP('curUrl');
if ($this->curUrlArray['all']) {
$this->curUrlArray = GeneralUtility::get_tag_attributes($this->curUrlArray['all']);
$this->curUrlArray['href'] = htmlspecialchars_decode($this->curUrlArray['href']);
}
// Note: parseCurUrl will invoke the hooks
$this->curUrlInfo = $this->parseCurUrl($this->curUrlArray['href'], $this->siteURL);
if (isset($this->curUrlArray['data-htmlarea-external']) && $this->curUrlInfo['act'] != 'mail') {
$this->curUrlInfo['act'] = 'url';
$this->curUrlInfo['info'] = $this->curUrlArray['href'];
}
}
/**
* Get the RTE configuration from Page TSConfig
*
* @return array RTE configuration array
*/
protected function getRTEConfig() {
$RTEtsConfigParts = explode(':', $this->RTEtsConfigParams);
$RTEsetup = $GLOBALS['BE_USER']->getTSConfig('RTE', BackendUtility::getPagesTSconfig($RTEtsConfigParts[5]));
$this->RTEProperties = $RTEsetup['properties'];
return BackendUtility::RTEsetup(
$this->RTEProperties, $RTEtsConfigParts[0], $RTEtsConfigParts[2], $RTEtsConfigParts[4]
);
}
/**
* Get the configuration of the button
*
* @param string $buttonName : the name of the button
* @return array the configuration array of the image button
*/
protected function getButtonConfig($buttonName) {
return is_array($this->thisConfig['buttons.']) && is_array($this->thisConfig['buttons.'][$buttonName . '.'])
? $this->thisConfig['buttons.'][$buttonName . '.']
: array();
}
/**
* Initialize the current or default values of the link attributes
*
* @return void
*/
protected function initLinkAttributes() {
// Initializing the title value
$this->setTitle = $this->curUrlArray['title'];
// Processing the classes configuration
$classSelected = array();
if ($this->buttonConfig['properties.']['class.']['allowedClasses']) {
$this->setClass = $this->curUrlArray['class'];
$classesAnchorArray = GeneralUtility::trimExplode(
',', $this->buttonConfig['properties.']['class.']['allowedClasses'], TRUE
);
$classesAnchorConfigArray = array();
// Collecting allowed classes and configured default values
$classesAnchor = array();
$classesAnchor['all'] = array();
$titleReadOnly = $this->buttonConfig['properties.']['title.']['readOnly'] || $this->buttonConfig[$this->act . '.']['properties.']['title.']['readOnly'];
if (is_array($this->RTEProperties['classesAnchor.'])) {
foreach ($this->RTEProperties['classesAnchor.'] as $label => $conf) {
if (in_array($conf['class'], $classesAnchorArray)) {
$classesAnchor['all'][] = $conf['class'];
if (in_array($conf['type'], $this->anchorTypes)) {
$classesAnchor[$conf['type']][] = $conf['class'];
if ($this->buttonConfig[$conf['type'] . '.']['properties.']['class.']['default'] == $conf['class']) {
$this->classesAnchorDefault[$conf['type']] = $conf['class'];
if ($conf['titleText']) {
$this->classesAnchorDefaultTitle[$conf['type']] = $this->getLLContent(
trim($conf['titleText'])
);
}
if ($conf['target']) {
$this->classesAnchorDefaultTarget[$conf['type']] = trim($conf['target']);
}
}
}
if ($titleReadOnly && $conf['titleText']) {
$this->classesAnchorClassTitle[$conf['class']] = ($this->classesAnchorDefaultTitle[$conf['type']] = $this->getLLContent(
trim($conf['titleText'])
));
}
}
}
}
// Constructing the class selector options
foreach ($this->anchorTypes as $anchorType) {
foreach ($classesAnchorArray as $class) {
if (!in_array($class, $classesAnchor['all']) || in_array($class, $classesAnchor['all']) && is_array(
$classesAnchor[$anchorType]
) && in_array($class, $classesAnchor[$anchorType])
) {
$selected = '';
if ($this->setClass == $class || !$this->setClass && $this->classesAnchorDefault[$anchorType] == $class) {
$selected = 'selected="selected"';
$classSelected[$anchorType] = TRUE;
}
$classLabel = is_array($this->RTEProperties['classes.']) && is_array(
$this->RTEProperties['classes.'][$class . '.']
) && $this->RTEProperties['classes.'][$class . '.']['name'] ? $this->getPageConfigLabel(
$this->RTEProperties['classes.'][$class . '.']['name'], 0
) : $class;
$classStyle = is_array($this->RTEProperties['classes.']) && is_array(
$this->RTEProperties['classes.'][$class . '.']
) && $this->RTEProperties['classes.'][$class . '.']['value'] ? $this->RTEProperties['classes.'][$class . '.']['value'] : '';
$this->classesAnchorJSOptions[$anchorType] .= '<option ' . $selected . ' value="' . $class . '"' . ($classStyle ? ' style="' . $classStyle . '"' : '') . '>' . $classLabel . '</option>';
}
}
if ($this->classesAnchorJSOptions[$anchorType] && !($this->buttonConfig['properties.']['class.']['required'] || $this->buttonConfig[$this->act . '.']['properties.']['class.']['required'])) {
$selected = '';
if (!$this->setClass && !$this->classesAnchorDefault[$anchorType]) {
$selected = 'selected="selected"';
}
$this->classesAnchorJSOptions[$anchorType] = '<option ' . $selected . ' value=""></option>' . $this->classesAnchorJSOptions[$anchorType];
}
}
}
// Initializing the target value
// Unset the target if it is set to a value different than default and if no class is selected and the target field is not displayed
// In other words, do not forward the target if we changed tab and the target field is not displayed
$this->defaultLinkTarget = isset($this->buttonConfig['properties.']['target.']['default']) ? $this->buttonConfig['properties.']['target.']['default'] : '';
$this->setTarget = '';
if (isset($this->curUrlArray['target']) && !($this->curUrlArray['target'] != $this->defaultLinkTarget && !$classSelected[$this->act] && is_array(
$this->buttonConfig['targetSelector.']
) && $this->buttonConfig['targetSelector.']['disabled'] && is_array(
$this->buttonConfig['popupSelector.']
) && $this->buttonConfig['popupSelector.']['disabled'])
) {
$this->setTarget = $this->curUrlArray['target'];
}
if ($this->defaultLinkTarget && !isset($this->curUrlArray['target'])) {
$this->setTarget = $this->defaultLinkTarget;
}
// Initializing additional attributes
if ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['rtehtmlarea']['plugins']['TYPO3Link']['additionalAttributes']) {
$addAttributes = GeneralUtility::trimExplode(
',',
$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['rtehtmlarea']['plugins']['TYPO3Link']['additionalAttributes'],
TRUE
);
foreach ($addAttributes as $attribute) {
$this->additionalAttributes[$attribute] = isset($this->curUrlArray[$attribute]) ? $this->curUrlArray[$attribute] : '';
}
}
}
/**
* Provide the additional parameters to be included in the template body tag
*
* @return string the body tag additions
*/
public function getBodyTagAdditions() {
$bodyTagAdditions = array();
// call hook for extra additions
foreach ($this->hookObjects as $hookObject) {
if (method_exists($hookObject, 'addBodyTagAdditions')) {
$bodyTagAdditions = $hookObject->addBodyTagAdditions($bodyTagAdditions);
}
}
return GeneralUtility::implodeAttributes($bodyTagAdditions, TRUE);
}
/**
* Generate JS code to be used on the link insert/modify dialogue
*
* @return string the generated JS code
* @todo Define visibility
*/
public function getJSCode() {
// BEGIN accumulation of header JavaScript:
$JScode = '';
$JScode .= '
// var plugin = window.parent.RTEarea["' . $this->editorNo . '"].editor.getPlugin("TYPO3Link");
// var HTMLArea = window.parent.HTMLArea;
var HTMLArea = window.parent.tinymce.activeEditor;
var plugin = window.parent.tinymce.AddOnManager.PluginManager.get("typo3filemanager");
var add_href=' . GeneralUtility::quoteJSvalue(
$this->curUrlArray['href'] ? '&curUrl[href]=' . rawurlencode($this->curUrlArray['href']) : ''
) . ';
var add_target=' . GeneralUtility::quoteJSvalue(
$this->setTarget ? '&curUrl[target]=' . rawurlencode($this->setTarget) : ''
) . ';
var add_class=' . GeneralUtility::quoteJSvalue(
$this->setClass ? '&curUrl[class]=' . rawurlencode($this->setClass) : ''
) . ';
var add_title=' . GeneralUtility::quoteJSvalue(
$this->setTitle ? '&curUrl[title]=' . rawurlencode($this->setTitle) : ''
) . ';
var add_params=' . GeneralUtility::quoteJSvalue(
$this->bparams ? '&bparams=' . rawurlencode($this->bparams) : ''
) . ';
var additionalValues = ' . (count($this->additionalAttributes) ? json_encode(
$this->additionalAttributes, JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT
) : '{}') . ';';
// Attributes setting functions
$JScode .= '
var cur_href=' . GeneralUtility::quoteJSvalue(
$this->curUrlArray['href'] ? ($this->curUrlInfo['query'] ? substr(
$this->curUrlArray['href'], 0, -strlen($this->curUrlInfo['query'])
) : $this->curUrlArray['href']) : ''
) . ';
var cur_target=' . GeneralUtility::quoteJSvalue($this->setTarget ? : '') . ';
var cur_class=' . GeneralUtility::quoteJSvalue($this->setClass ? : '') . ';
var cur_title=' . GeneralUtility::quoteJSvalue($this->setTitle ? : '') . ';
function browse_links_setTarget(value) {
cur_target=value;
add_target="&curUrl[target]="+encodeURIComponent(value);
}
function browse_links_setClass(value) {
cur_class=value;
add_class="&curUrl[class]="+encodeURIComponent(value);
}
function browse_links_setTitle(value) {
cur_title=value;
add_title="&curUrl[title]="+encodeURIComponent(value);
}
function browse_links_setHref(value) {
cur_href=value;
add_href="&curUrl[href]="+value;
}
function browse_links_setAdditionalValue(name, value) {
additionalValues[name] = value;
}
';
// Link setting functions
$JScode .= '
function link_typo3Page(id,anchor) {
var parameters = (document.ltargetform.query_parameters && document.ltargetform.query_parameters.value) ? (document.ltargetform.query_parameters.value.charAt(0) == "&" ? "" : "&") + document.ltargetform.query_parameters.value : "";
var theLink = \'' . $this->siteURL . '?id=\' + id + parameters + (anchor ? anchor : "");
if (document.ltargetform.anchor_title) browse_links_setTitle(document.ltargetform.anchor_title.value);
if (document.ltargetform.anchor_class) browse_links_setClass(document.ltargetform.anchor_class.value);
if (document.ltargetform.ltarget) browse_links_setTarget(document.ltargetform.ltarget.value);
if (document.ltargetform.lrel) browse_links_setAdditionalValue("rel", document.ltargetform.lrel.value);
browse_links_setAdditionalValue("data-htmlarea-external", "");
plugin.createLink(theLink,cur_target,cur_class,cur_title,additionalValues);
return false;
}
function link_folder(folder) {
if (folder && folder.substr(0, 5) == "file:") {
var theLink = \'' . $this->siteURL . '?file:\' + encodeURIComponent(folder.substr(5));
} else {
var theLink = \'' . $this->siteURL . '?\' + folder;
}
if (document.ltargetform.anchor_title) browse_links_setTitle(document.ltargetform.anchor_title.value);
if (document.ltargetform.anchor_class) browse_links_setClass(document.ltargetform.anchor_class.value);
if (document.ltargetform.ltarget) browse_links_setTarget(document.ltargetform.ltarget.value);
if (document.ltargetform.lrel) browse_links_setAdditionalValue("rel", document.ltargetform.lrel.value);
browse_links_setAdditionalValue("data-htmlarea-external", "");
plugin.createLink(theLink,cur_target,cur_class,cur_title,additionalValues);
return false;
}
function link_spec(theLink) {
if (document.ltargetform.anchor_title) browse_links_setTitle(document.ltargetform.anchor_title.value);
if (document.ltargetform.anchor_class) browse_links_setClass(document.ltargetform.anchor_class.value);
if (document.ltargetform.ltarget) browse_links_setTarget(document.ltargetform.ltarget.value);
browse_links_setAdditionalValue("data-htmlarea-external", "");
plugin.createLink(theLink,cur_target,cur_class,cur_title,additionalValues);
return false;
}
function link_current() {
var parameters = (document.ltargetform.query_parameters && document.ltargetform.query_parameters.value) ? (document.ltargetform.query_parameters.value.charAt(0) == "&" ? "" : "&") + document.ltargetform.query_parameters.value : "";
if (document.ltargetform.anchor_title) browse_links_setTitle(document.ltargetform.anchor_title.value);
if (document.ltargetform.anchor_class) browse_links_setClass(document.ltargetform.anchor_class.value);
if (document.ltargetform.ltarget) browse_links_setTarget(document.ltargetform.ltarget.value);
if (document.ltargetform.lrel) browse_links_setAdditionalValue("rel", document.ltargetform.lrel.value);
if (cur_href!="http://" && cur_href!="mailto:") {
plugin.createLink(cur_href + parameters,cur_target,cur_class,cur_title,additionalValues);
}
return false;
}
';
// General "jumpToUrl" and launchView functions:
$JScode .= '
function jumpToUrl(URL,anchor) {
if (URL.charAt(0) === \'?\') {
URL = ' . GeneralUtility::quoteJSvalue($this->getThisScript()) . ' + URL.substring(1);
}
var add_editorNo = URL.indexOf("editorNo=")==-1 ? "&editorNo=' . $this->editorNo . '" : "";
var add_contentTypo3Language = URL.indexOf("contentTypo3Language=")==-1 ? "&contentTypo3Language=' . $this->contentTypo3Language . '" : "";
var add_act = URL.indexOf("act=")==-1 ? "&act=' . $this->act . '" : "";
var add_mode = URL.indexOf("mode=")==-1 ? "&mode=' . $this->mode . '" : "";
var add_additionalValues = "";
if (plugin.pageTSConfiguration && plugin.pageTSConfiguration.additionalAttributes) {
var additionalAttributes = plugin.pageTSConfiguration.additionalAttributes.split(",");
for (var i = additionalAttributes.length; --i >= 0;) {
if (additionalValues[additionalAttributes[i]] != "") {
add_additionalValues += "&curUrl[" + additionalAttributes[i] + "]=" + encodeURIComponent(additionalValues[additionalAttributes[i]]);
}
}
}
var theLocation = URL+add_act+add_editorNo+add_contentTypo3Language+add_mode+add_href+add_target+add_class+add_title+add_additionalValues+add_params+(anchor?anchor:"");
window.location.href = theLocation;
return false;
}
function launchView(url) {
var thePreviewWindow="";
thePreviewWindow = window.open("' . $GLOBALS['BACK_PATH'] . 'show_item.php?table="+url,"ShowItem","height=300,width=410,status=0,menubar=0,resizable=0,location=0,directories=0,scrollbars=1,toolbar=0");
if (thePreviewWindow && thePreviewWindow.focus) {
thePreviewWindow.focus();
}
}
';
// Hook to overwrite or extend javascript functions
if (isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/rtehtmlarea/mod3/class.tx_rtehtmlarea_browse_links.php']['extendJScode']) && is_array(
$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/rtehtmlarea/mod3/class.tx_rtehtmlarea_browse_links.php']['extendJScode']
)
) {
$conf = array();
$_params = array(
'conf' => &$conf
);
foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/rtehtmlarea/mod3/class.tx_rtehtmlarea_browse_links.php']['extendJScode'] as $objRef) {
$processor =& GeneralUtility::getUserObj($objRef);
$JScode .= $processor->extendJScode($_params, $this);
}
}
return $JScode;
}
/******************************************************************
*
* Main functions
*
******************************************************************/
/**
* Rich Text Editor (RTE) link selector (MAIN function)
* Generates the link selector for the Rich Text Editor.
* Can also be used to select links for the TCEforms (see $wiz)
*
* @param boolean If set, the "remove link" is not shown in the menu: Used for the "Select link" wizard which is used by the TCEforms
* @return string Modified content variable.
* @todo Define visibility
*/
public function main_rte($wiz = 0) {
// Starting content:
$content = $this->doc->startPage($GLOBALS['LANG']->getLL('Insert/Modify Link', TRUE));
// Default allowed values
$this->allowedItems = explode(',', 'page,file,folder,url,mail,spec');
// Calling hook for extra options
foreach ($this->hookObjects as $hookObject) {
$this->allowedItems = $hookObject->addAllowedItems($this->allowedItems);
}
// Removing items as per configuration
if (is_array($this->buttonConfig['options.']) && $this->buttonConfig['options.']['removeItems']) {
$this->allowedItems = array_diff(
$this->allowedItems,
GeneralUtility::trimExplode(',', $this->buttonConfig['options.']['removeItems'], TRUE)
);
}
reset($this->allowedItems);
if (!in_array($this->act, $this->allowedItems)) {
$this->act = current($this->allowedItems);
}
// Making menu in top:
$menuDef = array();
if (!$wiz && $this->curUrlArray['href']) {
$menuDef['removeLink']['isActive'] = $this->act == 'removeLink';
$menuDef['removeLink']['label'] = $GLOBALS['LANG']->getLL('removeLink', TRUE);
$menuDef['removeLink']['url'] = '#';
$menuDef['removeLink']['addParams'] = 'onclick="plugin.unLink();return false;"';
}
if (in_array('page', $this->allowedItems)) {
$menuDef['page']['isActive'] = $this->act == 'page';
$menuDef['page']['label'] = $GLOBALS['LANG']->getLL('page', TRUE);
$menuDef['page']['url'] = '#';
$menuDef['page']['addParams'] = 'onclick="jumpToUrl(' . GeneralUtility::quoteJSvalue(
'?act=page&mode=' . $this->mode . '&bparams=' . $this->bparams
) . ');return false;"';
}
if (in_array('file', $this->allowedItems)) {
$menuDef['file']['isActive'] = $this->act == 'file';
$menuDef['file']['label'] = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_browse_links.xlf:file', TRUE);
$menuDef['file']['url'] = '#';
$menuDef['file']['addParams'] = 'onclick="jumpToUrl(' . GeneralUtility::quoteJSvalue(
'?act=file&mode=' . $this->mode . '&bparams=' . $this->bparams
) . ');return false;"';
}
if (in_array('folder', $this->allowedItems)) {
$menuDef['folder']['isActive'] = $this->act == 'folder';
$menuDef['folder']['label'] = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_browse_links.xlf:folder', TRUE);
$menuDef['folder']['url'] = '#';
$menuDef['folder']['addParams'] = 'onclick="jumpToUrl(' . GeneralUtility::quoteJSvalue(
'?act=folder&mode=' . $this->mode . '&bparams=' . $this->bparams
) . ');return false;"';
}
if (in_array('url', $this->allowedItems)) {
$menuDef['url']['isActive'] = $this->act == 'url';
$menuDef['url']['label'] = $GLOBALS['LANG']->getLL('extUrl', TRUE);
$menuDef['url']['url'] = '#';
$menuDef['url']['addParams'] = 'onclick="jumpToUrl(' . GeneralUtility::quoteJSvalue(
'?act=url&mode=' . $this->mode . '&bparams=' . $this->bparams
) . ');return false;"';
}
if (in_array('mail', $this->allowedItems)) {
$menuDef['mail']['isActive'] = $this->act == 'mail';
$menuDef['mail']['label'] = $GLOBALS['LANG']->getLL('email', TRUE);
$menuDef['mail']['url'] = '#';
$menuDef['mail']['addParams'] = 'onclick="jumpToUrl(' . GeneralUtility::quoteJSvalue(
'?act=mail&mode=' . $this->mode . '&bparams=' . $this->bparams
) . ');return false;"';
}
if (is_array($this->thisConfig['userLinks.']) && in_array('spec', $this->allowedItems)) {
$menuDef['spec']['isActive'] = $this->act == 'spec';
$menuDef['spec']['label'] = $GLOBALS['LANG']->getLL('special', TRUE);
$menuDef['spec']['url'] = '#';
$menuDef['spec']['addParams'] = 'onclick="jumpToUrl(' . GeneralUtility::quoteJSvalue(
'?act=spec&mode=' . $this->mode . '&bparams=' . $this->bparams
) . ');return false;"';
}
// call hook for extra options
foreach ($this->hookObjects as $hookObject) {
$menuDef = $hookObject->modifyMenuDefinition($menuDef);
}
$content .= $this->doc->getTabMenuRaw($menuDef);
// Adding the menu and header to the top of page:
$content .= $this->printCurrentUrl($this->curUrlInfo['info']) . '<br />';
// Depending on the current action we will create the actual module content for selecting a link:
switch ($this->act) {
case 'mail':
$extUrl = '
<!--
Enter mail address:
-->
<tr>
<td><label>' . $GLOBALS['LANG']->getLL('emailAddress', TRUE) . ':</label></td>
<td><input type="text" name="lemail"' . $this->doc->formWidth(
20
) . ' value="' . htmlspecialchars(
($this->curUrlInfo['act'] == 'mail' ? $this->curUrlInfo['info'] : '')
) . '" /> ' . '<input type="submit" value="' . $GLOBALS['LANG']->getLL('setLink', TRUE) . '" onclick="browse_links_setTarget(\'\');browse_links_setHref(\'mailto:\'+document.ltargetform.lemail.value);browse_links_setAdditionalValue(\'data-htmlarea-external\', \'\');return link_current();" /></td>
</tr>';
//$content .= $extUrl;
$content .= $this->addAttributesForm($extUrl);
break;
case 'url':
$extUrl = '
<!--
Enter External URL:
-->
<tr>
<td><label>URL:</label></td>
<td colspan="3"><input type="text" name="lurl"' . $this->doc->formWidth(
20
) . ' value="' . htmlspecialchars(
($this->curUrlInfo['act'] == 'url' ? $this->curUrlInfo['info'] : 'http://')
) . '" /> ' . '<input type="submit" value="' . $GLOBALS['LANG']->getLL('setLink', TRUE) . '" onclick="if (/^[A-Za-z0-9_+]{1,8}:/.test(document.ltargetform.lurl.value)) { browse_links_setHref(document.ltargetform.lurl.value); } else { browse_links_setHref(\'http://\'+document.ltargetform.lurl.value); }; browse_links_setAdditionalValue(\'data-htmlarea-external\', \'1\'); return link_current();" /></td>
</tr>';
$content .= $this->addAttributesForm($extUrl);
break;
case 'file':
case 'folder':
$content .= $this->addAttributesForm();
// Create folder tree:
$this->doc->JScode .= $this->doc->wrapScriptTags(
'
Tree.ajaxID = "SC_alt_file_navframe::expandCollapse";
'
);
$foldertree = GeneralUtility::makeInstance('SGalinski\Tinymce4Rte\FolderTree');
$foldertree->thisScript = $this->thisScript;
$tree = $foldertree->getBrowsableTree();
if (!$this->curUrlInfo['value'] || $this->curUrlInfo['act'] != $this->act) {
$cmpPath = '';
} else {
$cmpPath = $this->curUrlInfo['value'];
if (!isset($this->expandFolder)) {
$this->expandFolder = $cmpPath;
}
}
// Get the selected folder
$selectedFolder = FALSE;
if ($this->expandFolder) {
try {
$fileOrFolderObject = \TYPO3\CMS\Core\Resource\ResourceFactory::getInstance(
)->retrieveFileOrFolderObject($this->expandFolder);
} catch (\Exception $e) {
// No path is selected
}
if ($fileOrFolderObject instanceof \TYPO3\CMS\Core\Resource\Folder) {
// It's a folder
$selectedFolder = $fileOrFolderObject;
} elseif ($fileOrFolderObject instanceof \TYPO3\CMS\Core\Resource\FileInterface) {
// It's a file
$selectedFolder = $fileOrFolderObject->getParentFolder();
}
}
// If no folder is selected, get the user's default upload folder
if (!$selectedFolder) {
try {
$selectedFolder = $GLOBALS['BE_USER']->getDefaultUploadFolder();
} catch (\Exception $e) {
// The configured default user folder does not exist
}
}
// Build the file upload and folder creation forms
$uploadForm = '';
$createFolder = '';
if ($selectedFolder) {
$uploadForm = ($this->act === 'file') ? $this->uploadForm($selectedFolder) : '';
$createFolder = $this->createFolder($selectedFolder);
}
// Insert the upload form on top, if so configured
if ($GLOBALS['BE_USER']->getTSConfigVal('options.uploadFieldsInTopOfEB')) {
$content .= $uploadForm;
}
// Render the filelist if there is a folder selected
if ($selectedFolder) {
$files = $this->expandFolder($selectedFolder, $this->P['params']['allowedExtensions']);
}
$content .= '
<!--
Wrapper table for folder tree / file/folder list:
-->
<table border="0" cellpadding="0" cellspacing="0" id="typo3-linkFiles">
<tr>
<td class="c-wCell" valign="top">' . $this->barheader(
($GLOBALS['LANG']->getLL('folderTree') . ':')
) . $tree . '</td>
<td class="c-wCell" valign="top">' . $files . '</td>
</tr>
</table>
';
// Adding create folder + upload form if applicable
if (!$GLOBALS['BE_USER']->getTSConfigVal('options.uploadFieldsInTopOfEB')) {
$content .= $uploadForm;
}
$content .= '<br />';
$content .= $createFolder;
$content .= '<br />';
break;
case 'spec':
if (is_array($this->thisConfig['userLinks.'])) {
$subcats = array();
$v = $this->thisConfig['userLinks.'];
foreach ($v as $k2 => $dummyValue) {
$k2i = (int) $k2;
if (substr($k2, -1) == '.' && is_array($v[$k2i . '.'])) {
// Title:
$title = trim($v[$k2i]);
if (!$title) {
$title = $v[$k2i . '.']['url'];
} else {
$title = $GLOBALS['LANG']->sL($title);
}
// Description:
$description = $v[$k2i . '.']['description'] ? $GLOBALS['LANG']->sL(
$v[($k2i . '.')]['description'], TRUE
) . '<br />' : '';
// URL + onclick event:
$onClickEvent = '';
if (isset($v[$k2i . '.']['target'])) {
$onClickEvent .= 'browse_links_setTarget(\'' . $v[($k2i . '.')]['target'] . '\');';
}
$v[$k2i . '.']['url'] = str_replace('###_URL###', $this->siteURL, $v[$k2i . '.']['url']);
if (substr($v[$k2i . '.']['url'], 0, 7) == 'http://' || substr(
$v[$k2i . '.']['url'], 0, 7
) == 'mailto:'
) {
$onClickEvent .= 'cur_href=' . GeneralUtility::quoteJSvalue(
$v[($k2i . '.')]['url']
) . ';link_current();';
} else {
$onClickEvent .= 'link_spec(' . GeneralUtility::quoteJSvalue(
$this->siteURL . $v[($k2i . '.')]['url']
) . ');';
}
// Link:
$A = array('<a href="#" onclick="' . htmlspecialchars(
$onClickEvent
) . 'return false;">', '</a>');
// Adding link to menu of user defined links:
$subcats[$k2i] = '
<tr>
<td class="bgColor4">' . $A[0] . '<strong>' . htmlspecialchars(
$title
) . ($this->curUrlInfo['info'] == $v[$k2i . '.']['url'] ? '<img' . \TYPO3\CMS\Backend\Utility\IconUtility::skinImg(
$GLOBALS['BACK_PATH'], 'gfx/blinkarrow_right.gif', 'width="5" height="9"'
) . ' class="c-blinkArrowR" alt="" />' : '') . '</strong><br />' . $description . $A[1] . '</td>
</tr>';
}
}
// Sort by keys:
ksort($subcats);
// Add menu to content:
$content .= '
<!--
Special userdefined menu:
-->
<table border="0" cellpadding="1" cellspacing="1" id="typo3-linkSpecial">
<tr>
<td class="bgColor5" class="c-wCell" valign="top"><strong>' . $GLOBALS['LANG']->getLL(
'special', TRUE
) . '</strong></td>
</tr>
' . implode('', $subcats) . '
</table>
';
}
break;
case 'page':
$content .= $this->addAttributesForm();
$pagetree = GeneralUtility::makeInstance('SGalinski\Tinymce4Rte\PageTree');
$pagetree->ext_showNavTitle = $GLOBALS['BE_USER']->getTSConfigVal('options.pageTree.showNavTitle');
$pagetree->ext_showPageId = $GLOBALS['BE_USER']->getTSConfigVal('options.pageTree.showPageIdWithTitle');
$pagetree->addField('nav_title');
$tree = $pagetree->getBrowsableTree();
$cElements = $this->expandPage();
$dbmount = $this->getTemporaryTreeMountCancelNotice();
$content .= '
<!--
Wrapper table for page tree / record list:
-->
<table border="0" cellpadding="0" cellspacing="0" id="typo3-linkPages">
<tr>
<td class="c-wCell" valign="top">' . $this->barheader(
($GLOBALS['LANG']->getLL('pageTree') . ':')
) . $dbmount . $tree . '</td>
<td class="c-wCell" valign="top">' . $cElements . '</td>
</tr>
</table>
';
break;
default:
// call hook
foreach ($this->hookObjects as $hookObject) {
$content .= $hookObject->getTab($this->act);
}
}
// End page, return content:
$content .= $this->doc->endPage();
$content = $this->doc->insertStylesAndJS($content);
return $content;
}
/**
* Creates a form for link attributes
*
* @param string $rows : html code for some initial rows of the table to be wrapped in form
* @return string The HTML code of the form
*/
public function addAttributesForm($rows = '') {
$ltargetForm = '';
$additionalAttributeFields = '';
// Add page id, target, class selector box, title and parameters fields:
$lpageId = $this->addPageIdSelector();
$queryParameters = $this->addQueryParametersSelector();
$ltarget = $this->addTargetSelector();
$lclass = $this->addClassSelector();
$ltitle = $this->addTitleSelector();
$rel = $this->addRelField();
// additional fields for links
if (isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/rtehtmlarea/mod3/class.tx_rtehtmlarea_browse_links.php']['addAttributeFields']) && is_array(
$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/rtehtmlarea/mod3/class.tx_rtehtmlarea_browse_links.php']['addAttributeFields']
)
) {
$conf = array();
$_params = array(
'conf' => &$conf
);
foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/rtehtmlarea/mod3/class.tx_rtehtmlarea_browse_links.php']['addAttributeFields'] as $objRef) {
$processor =& GeneralUtility::getUserObj($objRef);
$additionalAttributeFields .= $processor->getAttributefields($_params, $this);
}
}
if ($rows || $lpageId || $queryParameters || $lclass || $ltitle || $ltarget || $rel) {
$ltargetForm = $this->wrapInForm(
$rows . $lpageId . $queryParameters . $lclass . $ltitle . $ltarget . $rel . $additionalAttributeFields
);
}
return $ltargetForm;
}
/**
* @todo Define visibility
*/
public function wrapInForm($string) {
$form = '
<!--
Selecting target for link:
-->
<form action="" name="ltargetform" id="ltargetform">
<table id="typo3-linkTarget" class="htmlarea-window-table">' . $string;
if ($this->act == $this->curUrlInfo['act'] && $this->act != 'mail' && $this->curUrlArray['href']) {
$form .= '
<tr>
<td>
</td>
<td colspan="3">
<input type="submit" value="' . $GLOBALS['LANG']->getLL(
'update', TRUE
) . '" onclick="' . ($this->act == 'url' ? 'browse_links_setAdditionalValue(\'data-htmlarea-external\', \'1\'); ' : '') . 'return link_current();" />
</td>
</tr>';
}
$form .= '
</table>
</form>';
return $form;
}
/**
* @todo Define visibility
*/
public function addPageIdSelector() {
return $this->act == 'page' && $this->buttonConfig && is_array(
$this->buttonConfig['pageIdSelector.']
) && $this->buttonConfig['pageIdSelector.']['enabled'] ? '
<tr>
<td><label>' . $GLOBALS['LANG']->getLL('page_id', TRUE) . ':</label></td>
<td colspan="3">
<input type="text" size="6" name="luid" />&nbsp;<input type="submit" value="' . $GLOBALS['LANG']->getLL(
'setLink', TRUE
) . '" onclick="return link_typo3Page(document.ltargetform.luid.value);" />
</td>
</tr>' : '';
}
/**
* @todo Define visibility
*/
public function addRelField() {
return ($this->act == 'page' || $this->act == 'url' || $this->act == 'file') && $this->buttonConfig && is_array(
$this->buttonConfig['relAttribute.']
) && $this->buttonConfig['relAttribute.']['enabled'] ? '
<tr>
<td><label>' . $GLOBALS['LANG']->getLL('linkRelationship', TRUE) . ':</label></td>
<td colspan="3">
<input type="text" name="lrel" value="' . $this->additionalAttributes['rel'] . '" ' . $this->doc->formWidth(
30
) . ' />
</td>
</tr>' : '';
}
/**
* @todo Define visibility
*/
public function addQueryParametersSelector() {
return $this->act == 'page' && $this->buttonConfig && is_array(
$this->buttonConfig['queryParametersSelector.']
) && $this->buttonConfig['queryParametersSelector.']['enabled'] ? '
<tr>
<td><label>' . $GLOBALS['LANG']->getLL('query_parameters', TRUE) . ':</label></td>
<td colspan="3">
<input type="text" name="query_parameters" value="' . ($this->curUrlInfo['query'] ? : '') . '" ' . $this->doc->formWidth(
30
) . ' />
</td>
</tr>' : '';
}
/**
* @todo Define visibility
*/
public function addTargetSelector() {
$targetSelectorConfig = array();
$popupSelectorConfig = array();
if (is_array($this->buttonConfig['targetSelector.'])) {
$targetSelectorConfig = $this->buttonConfig['targetSelector.'];
}
if (is_array($this->buttonConfig['popupSelector.'])) {
$popupSelectorConfig = $this->buttonConfig['popupSelector.'];
}
$ltarget = '';
if ($this->act != 'mail') {
$ltarget .= '
<tr id="ltargetrow"' . ($targetSelectorConfig['disabled'] && $popupSelectorConfig['disabled'] ? ' style="display: none;"' : '') . '>
<td><label>' . $GLOBALS['LANG']->getLL('target', TRUE) . ':</label></td>
<td><input type="text" name="ltarget" onchange="browse_links_setTarget(this.value);" value="' . htmlspecialchars(
($this->setTarget ? $this->setTarget : ($this->setClass || !$this->classesAnchorDefault[$this->act] ? '' : $this->classesAnchorDefaultTarget[$this->act]))
) . '"' . $this->doc->formWidth(10) . ' /></td>';
$ltarget .= '
<td colspan="2">';
if (!$targetSelectorConfig['disabled']) {
$ltarget .= '
<select name="ltarget_type" onchange="browse_links_setTarget(this.options[this.selectedIndex].value);document.ltargetform.ltarget.value=this.options[this.selectedIndex].value;this.selectedIndex=0;">
<option></option>
<option value="_top">' . $GLOBALS['LANG']->getLL('top', TRUE) . '</option>
<option value="_blank">' . $GLOBALS['LANG']->getLL('newWindow', TRUE) . '</option>
</select>';
}
$ltarget .= '
</td>
</tr>';
if (!$popupSelectorConfig['disabled']) {
$selectJS = 'if (document.ltargetform.popup_width.options[document.ltargetform.popup_width.selectedIndex].value>0 && document.ltargetform.popup_height.options[document.ltargetform.popup_height.selectedIndex].value>0) {
document.ltargetform.ltarget.value = document.ltargetform.popup_width.options[document.ltargetform.popup_width.selectedIndex].value+\'x\'+document.ltargetform.popup_height.options[document.ltargetform.popup_height.selectedIndex].value;
browse_links_setTarget(document.ltargetform.ltarget.value);
document.ltargetform.popup_width.selectedIndex=0;
document.ltargetform.popup_height.selectedIndex=0;
}';
$ltarget .= '
<tr>
<td><label>' . $GLOBALS['LANG']->getLL('target_popUpWindow', TRUE) . ':</label></td>
<td colspan="3">
<select name="popup_width" onchange="' . $selectJS . '">
<option value="0">' . $GLOBALS['LANG']->getLL('target_popUpWindow_width', TRUE) . '</option>
<option value="300">300</option>
<option value="400">400</option>
<option value="500">500</option>
<option value="600">600</option>
<option value="700">700</option>
<option value="800">800</option>
</select>
x
<select name="popup_height" onchange="' . $selectJS . '">
<option value="0">' . $GLOBALS['LANG']->getLL('target_popUpWindow_height', TRUE) . '</option>
<option value="200">200</option>
<option value="300">300</option>
<option value="400">400</option>
<option value="500">500</option>
<option value="600">600</option>
</select>
</td>
</tr>';
}
}
return $ltarget;
}
/**
* Return html code for the class selector
*
* @return string the html code to be added to the form
*/
public function addClassSelector() {
$selectClass = '';
if ($this->classesAnchorJSOptions[$this->act]) {
$selectClass = '
<tr>
<td><label>' . $GLOBALS['LANG']->getLL('anchor_class', TRUE) . ':</label></td>
<td colspan="3">
<select name="anchor_class" onchange="' . $this->getClassOnChangeJS() . '">
' . $this->classesAnchorJSOptions[$this->act] . '
</select>
</td>
</tr>';
}
return $selectClass;
}
/**
* Return JS code for the class selector onChange event
*
* @return string class selector onChange JS code
*/
public function getClassOnChangeJS() {
return '
if (document.ltargetform.anchor_class) {
document.ltargetform.anchor_class.value = document.ltargetform.anchor_class.options[document.ltargetform.anchor_class.selectedIndex].value;
if (document.ltargetform.anchor_class.value && HTMLArea.classesAnchorSetup) {
for (var i = HTMLArea.classesAnchorSetup.length; --i >= 0;) {
var anchorClass = HTMLArea.classesAnchorSetup[i];
if (anchorClass[\'name\'] == document.ltargetform.anchor_class.value) {
if (anchorClass[\'titleText\'] && document.ltargetform.anchor_title) {
document.ltargetform.anchor_title.value = anchorClass[\'titleText\'];
document.getElementById(\'rtehtmlarea-browse-links-title-readonly\').innerHTML = anchorClass[\'titleText\'];
browse_links_setTitle(anchorClass[\'titleText\']);
}
if (anchorClass[\'target\']) {
if (document.ltargetform.ltarget) {
document.ltargetform.ltarget.value = anchorClass[\'target\'];
}
browse_links_setTarget(anchorClass[\'target\']);
} else if (document.ltargetform.ltarget && document.getElementById(\'ltargetrow\').style.display == \'none\') {
// Reset target to default if field is not displayed and class has no configured target
document.ltargetform.ltarget.value = \'' . ($this->defaultLinkTarget ? : '') . '\';
browse_links_setTarget(document.ltargetform.ltarget.value);
}
break;
}
}
}
browse_links_setClass(document.ltargetform.anchor_class.value);
}
';
}
/**
* @todo Define visibility
*/
public function addTitleSelector() {
$title = $this->setTitle ? : ($this->setClass || !$this->classesAnchorDefault[$this->act] ? '' : $this->classesAnchorDefaultTitle[$this->act]);
$readOnly = $this->buttonConfig['properties.']['title.']['readOnly'] || $this->buttonConfig[$this->act . '.']['properties.']['title.']['readOnly'];
if ($readOnly) {
$title = $this->setClass ? $this->classesAnchorClassTitle[$this->setClass] : $this->classesAnchorDefaultTitle[$this->act];
}
return '
<tr>
<td><label for="rtehtmlarea-browse-links-anchor_title" id="rtehtmlarea-browse-links-title-label">' . $GLOBALS['LANG']->getLL(
'anchor_title', TRUE
) . ':</label></td>
<td colspan="3">
<span id="rtehtmlarea-browse-links-title-input" style="display: ' . ($readOnly ? 'none' : 'inline') . ';">
<input type="text" id="rtehtmlarea-browse-links-anchor_title" name="anchor_title" value="' . $title . '" ' . $this->doc->formWidth(
30
) . ' />
</span>
<span id="rtehtmlarea-browse-links-title-readonly" style="display: ' . ($readOnly ? 'inline' : 'none') . ';">' . $title . '</span>
</td>
</tr>';
}
/**
* Localize a string using the language of the content element rather than the language of the BE interface
*
* @param string string: the label to be localized
* @return string Localized string.
*/
public function getLLContent($string) {
return $this->contentLanguageService->sL($string);
}
/**
* Localize a label obtained from Page TSConfig
*
* @param string $string The label to be localized
* @param boolean $JScharCode If needs to be converted to a array of char numbers
* @return string Localized string.
*/
public function getPageConfigLabel($string, $JScharCode = 1) {
if (substr($string, 0, 4) !== 'LLL:') {
$label = $string;
} else {
$label = $GLOBALS['LANG']->sL(trim($string));
}
$label = str_replace('"', '\\"', str_replace('\\\'', '\'', $label));
$label = $JScharCode ? GeneralUtility::quoteJSvalue($label) : $label;
return $label;
}
}
<?php
namespace SGalinski\Tinymce4Rte\Controller;
/***************************************************************
* Copyright notice
/*
* This file is part of the TYPO3 CMS project.
*
* It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2
* of the License, or any later version.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*
* The TYPO3 project - inspiring people to share!
*/
use Psr\Http\Message\ServerRequestInterface;
use SGalinski\Tinymce4Rte\Utility\VersionUtility;
use TYPO3\CMS\Backend\Utility\BackendUtility;
use TYPO3\CMS\Core\Page\PageRenderer;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Lang\LanguageService;
use TYPO3\CMS\Recordlist\Controller\AbstractLinkBrowserController;
/**
* Extended controller for link browser
*/
class BrowseLinksController extends AbstractLinkBrowserController {
/**
* Active with TYPO3 Element Browser: Contains the name of the form field for which this window
* opens - thus allows us to make references back to the main window in which the form is.
* Example value: "data[pages][39][bodytext]|||tt_content|"
* or "data[tt_content][NEW3fba56fde763d][image]|||gif,jpg,jpeg,tif,bmp,pcx,tga,png,pdf,ai|"
*
* (c) sgalinski Internet Services (http://www.sgalinski.de)
* Values:
* 0: form field name reference, eg. "data[tt_content][123][image]"
* 1: htmlArea RTE parameters: editorNo:contentTypo3Language
* 2: RTE config parameters: RTEtsConfigParams
* 3: allowed types. Eg. "tt_content" or "gif,jpg,jpeg,tif,bmp,pcx,tga,png,pdf,ai"
*
* All rights reserved
* $pArr = explode('|', $this->bparams);
* $formFieldName = $pArr[0];
* $allowedTablesOrFileTypes = $pArr[3];
*
* This script is part of the TYPO3 project. The TYPO3 project is
* free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
* @var string
*/
protected $bparams;
/**
* @var int
*/
protected $editorNo;
/**
* TYPO3 language code of the content language
*
* The GNU General Public License can be found at
* http://www.gnu.org/copyleft/gpl.html.
* @var int
*/
protected $contentTypo3Language;
/**
* Language service object for localization to the content language
*
* This script is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* @var LanguageService
*/
protected $contentLanguageService;
/**
* @var array
*/
protected $buttonConfig = [];
/**
* @var array
*/
protected $thisConfig = [];
/**
* RTE configuration
*
* This copyright notice MUST APPEAR in all copies of the script!
***************************************************************/
* @var array
*/
protected $RTEProperties = [];
/**
* Script class for the Element Browser window.
*/
class BrowseLinksController {
/**
* Used with the Rich Text Editor.
* Example value: "tt_content:NEW3fba58c969f5c:bodytext:23:text:23:"
*
* @var string
*/
protected $RTEtsConfigParams;
/**
* @var array
*/
protected $classesAnchorDefault = array();
public $mode = 'rte';
/**
* @var array
*/
protected $classesAnchorDefaultTitle = array();
public $button = 'link';
/**
* @var array
*/
protected $classesAnchorClassTitle = array();
protected $content = '';
/**
* @var array
*/
protected $classesAnchorDefaultTarget = array();
/**
* Initialize language files
* @var array
*/
public function __construct() {
$GLOBALS['LANG']->includeLLFile('EXT:tinymce4_rte/mod3/locallang.xlf');
protected $classesAnchorJSOptions = array();
/**
* @var string
*/
protected $defaultLinkTarget = '';
/**
* @var array
*/
protected $additionalAttributes = array();
/**
* @var string
*/
protected $siteUrl = '';
/**
* Initialize controller
*/
protected function init() {
parent::init();
$lang = $this->getLanguageService();
$lang->includeLLFile('EXT:tinymce4_rte/Resources/Private/Language/locallang_browselinkscontroller.xlf');
$lang->includeLLFile('EXT:tinymce4_rte/Resources/Private/Language/locallang_dialogs.xlf');
$this->contentLanguageService = GeneralUtility::makeInstance(LanguageService::class);
}
/**
* Main function, rendering the element browser in RTE mode.
*
* @return void
* @todo Define visibility
* @param ServerRequestInterface $request
*/
public function main() {
// Setting alternative web browsing mounts (ONLY local to browse_links.php this script so they stay "read-only")
$altMountPoints = trim($GLOBALS['BE_USER']->getTSConfigVal('options.pageTree.altElementBrowserMountPoints'));
// Clear temporary DB mounts
$tmpMount = \TYPO3\CMS\Core\Utility\GeneralUtility::_GET('setTempDBmount');
if (isset($tmpMount)) {
$GLOBALS['BE_USER']->setAndSaveSessionData('pageTree_temporaryMountPoint', (int) $tmpMount);
protected function initVariables(ServerRequestInterface $request) {
parent::initVariables($request);
$queryParameters = $request->getQueryParams();
$this->bparams = isset($queryParameters['bparams']) ? $queryParameters['bparams'] : '';
$this->siteUrl = GeneralUtility::getIndpEnv('TYPO3_SITE_URL');
$currentLinkParts = isset($queryParameters['curUrl']) ? $queryParameters['curUrl'] : [];
if (isset($currentLinkParts['all'])) {
$currentLinkParts = GeneralUtility::get_tag_attributes($queryParameters['curUrl']['all']);
$currentLinkParts['url'] = htmlspecialchars_decode($currentLinkParts['href']);
unset($currentLinkParts['href']);
}
// Set temporary DB mounts
$tempDBmount = (int) $GLOBALS['BE_USER']->getSessionData('pageTree_temporaryMountPoint');
if ($tempDBmount) {
$altMountPoints = $tempDBmount;
$this->currentLinkParts = $currentLinkParts;
// Process bparams
$pArr = explode('|', $this->bparams);
$pRteArr = explode(':', $pArr[1]);
$this->editorNo = $pRteArr[0];
$this->contentTypo3Language = $pRteArr[1];
$this->RTEtsConfigParams = $pArr[2];
if (!$this->editorNo) {
$this->editorNo = GeneralUtility::_GP('editorNo');
$this->contentTypo3Language = GeneralUtility::_GP('contentTypo3Language');
$this->RTEtsConfigParams = GeneralUtility::_GP('RTEtsConfigParams');
}
if ($altMountPoints) {
$GLOBALS['BE_USER']->groupData['webmounts'] = implode(
',', array_unique(\TYPO3\CMS\Core\Utility\GeneralUtility::intExplode(',', $altMountPoints))
);
$GLOBALS['WEBMOUNTS'] = $GLOBALS['BE_USER']->returnWebmounts();
$pArr[1] = implode(':', array($this->editorNo, $this->contentTypo3Language));
$pArr[2] = $this->RTEtsConfigParams;
$this->bparams = implode('|', $pArr);
$this->contentLanguageService->init($this->contentTypo3Language);
$RTEtsConfigParts = explode(':', $this->RTEtsConfigParams);
$RTEsetup = $this->getBackendUser()->getTSConfig('RTE', BackendUtility::getPagesTSconfig($RTEtsConfigParts[5]));
$this->RTEProperties = $RTEsetup['properties'];
$this->thisConfig = BackendUtility::RTEsetup($this->RTEProperties, $RTEtsConfigParts[0], $RTEtsConfigParts[2], $RTEtsConfigParts[4]);
$this->buttonConfig = isset($this->thisConfig['buttons.']['link.'])
? $this->thisConfig['buttons.']['link.']
: [];
}
/**
* Initialize document template object
*
* @return void
*/
protected function initDocumentTemplate() {
parent::initDocumentTemplate();
$pageRenderer = GeneralUtility::makeInstance(PageRenderer::class);
$pageRenderer->loadRequireJsModule('TYPO3/CMS/Tinymce4Rte/RteLinkBrowser');
}
/**
* Initialize $this->currentLink and $this->currentLinkHandler
*
* @return void
*/
protected function initCurrentUrl() {
if (empty($this->currentLinkParts)) {
return;
}
// Setting alternative file browsing mounts (ONLY local to browse_links.php this script so they stay "read-only")
$altMountPoints = trim($GLOBALS['BE_USER']->getTSConfigVal('options.folderTree.altElementBrowserMountPoints'));
if ($altMountPoints) {
$altMountPoints = \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(',', $altMountPoints);
foreach ($altMountPoints as $filePathRelativeToFileadmindir) {
// @todo: add this feature for FAL and TYPO3 6.2
if (VersionUtility::isVersion870OrHigher()) {
if (!empty($this->currentLinkParts['url'])) {
/** @noinspection ExceptionsAnnotatingAndHandlingInspection */
/** @noinspection PhpUnnecessaryFullyQualifiedNameInspection */
$linkService = GeneralUtility::makeInstance(\TYPO3\CMS\Core\LinkHandling\LinkService::class);
$data = $linkService->resolve($this->currentLinkParts['url']);
$this->currentLinkParts['type'] = $data['type'];
unset($data['type']);
$this->currentLinkParts['url'] = $data;
}
if (!empty($this->currentLinkParts['class'])) {
// Only keep last class value (others are automatically added again by required option)
// https://review.typo3.org/#/c/29643
$currentClasses = GeneralUtility::trimExplode(' ', $this->currentLinkParts['class'], true);
if (count($currentClasses) > 1) {
$this->currentLinkParts['class'] = end($currentClasses);
}
}
} else {
if (!empty($this->currentLinkParts['class'])) {
// remove required classes
$currentClasses = GeneralUtility::trimExplode(' ', $this->currentLinkParts['class'], TRUE);
if (count($currentClasses) > 1) {
$this->currentLinkParts['class'] = end($currentClasses);
}
}
if (empty($this->currentLinkParts['data-htmlarea-external'])) {
// strip siteUrl prefix except for external and mail links
if (strpos($this->currentLinkParts['url'], 'mailto:') === FALSE) {
$paramsPosition = strpos($this->currentLinkParts['url'], '?');
if ($paramsPosition !== FALSE) {
$this->currentLinkParts['url'] = substr($this->currentLinkParts['url'], $paramsPosition + 1);
}
}
// special treatment for page links, remove the id= part
$idPosition = strpos($this->currentLinkParts['url'], 'id=');
if ($idPosition !== FALSE) {
$this->currentLinkParts['url'] = substr($this->currentLinkParts['url'], $idPosition + 3);
}
// in RTE the additional params are encoded directly at the end of the href part
// we need to split this again into dedicated fields
$additionalParamsPosition = strpos($this->currentLinkParts['url'], '?');
if ($additionalParamsPosition === FALSE) {
$additionalParamsPosition = strpos($this->currentLinkParts['url'], '&');
}
if ($additionalParamsPosition !== FALSE) {
$this->currentLinkParts['params'] = substr($this->currentLinkParts['url'], $additionalParamsPosition);
$this->currentLinkParts['url'] = substr($this->currentLinkParts['url'], 0, $additionalParamsPosition);
// in case the first sign was an ? override it with &
$this->currentLinkParts['params'][0] = '&';
}
}
}
// Render type by user function
$browserRendered = FALSE;
if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/browse_links.php']['browserRendering'])) {
foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/browse_links.php']['browserRendering'] as $classRef) {
$browserRenderObj = \TYPO3\CMS\Core\Utility\GeneralUtility::getUserObj($classRef);
if (is_object($browserRenderObj) && method_exists($browserRenderObj, 'isValid') && method_exists(
$browserRenderObj, 'render'
)
) {
if ($browserRenderObj->isValid($this->mode, $this)) {
$this->content .= $browserRenderObj->render($this->mode, $this);
$browserRendered = TRUE;
break;
parent::initCurrentUrl();
}
/**
* Renders the link attributes for the selected link handler
*
* @return string
*/
public function renderLinkAttributeFields() {
// Processing the classes configuration
if (!empty($this->buttonConfig['properties.']['class.']['allowedClasses'])) {
$classesAnchorArray = GeneralUtility::trimExplode(',', $this->buttonConfig['properties.']['class.']['allowedClasses'], true);
// Collecting allowed classes and configured default values
$classesAnchor = [
'all' => []
];
$titleReadOnly = $this->buttonConfig['properties.']['title.']['readOnly']
|| $this->buttonConfig[$this->displayedLinkHandlerId . '.']['properties.']['title.']['readOnly'];
if (is_array($this->RTEProperties['classesAnchor.'])) {
foreach ($this->RTEProperties['classesAnchor.'] as $label => $conf) {
if (in_array($conf['class'], $classesAnchorArray)) {
$classesAnchor['all'][] = $conf['class'];
if ($conf['type'] === $this->displayedLinkHandlerId) {
$classesAnchor[$conf['type']][] = $conf['class'];
if ($this->buttonConfig[$conf['type'] . '.']['properties.']['class.']['default'] == $conf['class']) {
$this->classesAnchorDefault[$conf['type']] = $conf['class'];
if ($conf['titleText']) {
$this->classesAnchorDefaultTitle[$conf['type']] = $this->contentLanguageService->sL(trim($conf['titleText']));
}
if (isset($conf['target'])) {
$this->classesAnchorDefaultTarget[$conf['type']] = trim($conf['target']);
}
}
}
if ($titleReadOnly && $conf['titleText']) {
$this->classesAnchorClassTitle[$conf['class']] = ($this->classesAnchorDefaultTitle[$conf['type']] = $this->contentLanguageService->sL(trim($conf['titleText'])));
}
}
}
}
// Constructing the class selector options
foreach ($classesAnchorArray as $class) {
if (!in_array($class, $classesAnchor['all']) || in_array($class, $classesAnchor['all']) && is_array($classesAnchor[$this->displayedLinkHandlerId]) && in_array($class, $classesAnchor[$this->displayedLinkHandlerId])) {
$selected = '';
if ($this->linkAttributeValues['class'] === $class || !$this->linkAttributeValues['class'] && $this->classesAnchorDefault[$this->displayedLinkHandlerId] == $class) {
$selected = 'selected="selected"';
}
$classLabel = !empty($this->RTEProperties['classes.'][$class . '.']['name'])
? $this->getPageConfigLabel($this->RTEProperties['classes.'][$class . '.']['name'], 0)
: $class;
$classStyle = !empty($this->RTEProperties['classes.'][$class . '.']['value'])
? $this->RTEProperties['classes.'][$class . '.']['value']
: '';
$this->classesAnchorJSOptions[$this->displayedLinkHandlerId] .= '<option ' . $selected . ' value="' . $class . '"' . ($classStyle ? ' style="' . $classStyle . '"' : '') . '>' . $classLabel . '</option>';
}
}
if ($this->classesAnchorJSOptions[$this->displayedLinkHandlerId] && !($this->buttonConfig['properties.']['class.']['required'] || $this->buttonConfig[$this->displayedLinkHandlerId . '.']['properties.']['class.']['required'])) {
$selected = '';
if (!$this->linkAttributeValues['class'] && !$this->classesAnchorDefault[$this->displayedLinkHandlerId]) {
$selected = 'selected="selected"';
}
$this->classesAnchorJSOptions[$this->displayedLinkHandlerId] = '<option ' . $selected . ' value=""></option>' . $this->classesAnchorJSOptions[$this->displayedLinkHandlerId];
}
}
// Default target
$this->defaultLinkTarget = $this->classesAnchorDefault[$this->displayedLinkHandlerId] && $this->classesAnchorDefaultTarget[$this->displayedLinkHandlerId]
? $this->classesAnchorDefaultTarget[$this->displayedLinkHandlerId]
: (isset($this->buttonConfig[$this->displayedLinkHandlerId . '.']['properties.']['target.']['default'])
? $this->buttonConfig[$this->displayedLinkHandlerId . '.']['properties.']['target.']['default']
: (isset($this->buttonConfig['properties.']['target.']['default'])
? $this->buttonConfig['properties.']['target.']['default']
: ''));
// Initializing additional attributes
if ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['rtehtmlarea']['plugins']['TYPO3Link']['additionalAttributes']) {
$addAttributes = GeneralUtility::trimExplode(',', $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['rtehtmlarea']['plugins']['TYPO3Link']['additionalAttributes'], true);
foreach ($addAttributes as $attribute) {
$this->additionalAttributes[$attribute] = isset($this->linkAttributeValues[$attribute]) ? $this->linkAttributeValues[$attribute] : '';
}
}
return parent::renderLinkAttributeFields();
}
/**
* Localize a label obtained from Page TSConfig
*
* @param string $string The label to be localized
* @param bool $JScharCode If needs to be converted to an array of char numbers
* @return string Localized string
*/
public function getPageConfigLabel($string, $JScharCode = true) {
if (substr($string, 0, 4) !== 'LLL:') {
$label = $string;
} else {
$label = $this->getLanguageService()->sL(trim($string));
}
$label = str_replace('"', '\\"', str_replace('\\\'', '\'', $label));
return $JScharCode ? GeneralUtility::quoteJSvalue($label) : $label;
}
/**
* @return string
*/
protected function renderCurrentUrl() {
$removeLink = '<a href="#" class="btn btn-default t3js-removeCurrentLink">' . $this->getLanguageService()->getLL('removeLink', true) . '</a>';
return '
<table border="0" cellpadding="0" cellspacing="0" id="typo3-curUrl">
<tr>
<td>' . $this->getLanguageService()->getLL('currentLink', true) . ': ' . htmlspecialchars($this->currentLinkHandler->formatCurrentUrl()) . $removeLink . '</td>
</tr>
</table>';
}
/**
* Get the allowed items or tabs
*
* @return string[]
*/
protected function getAllowedItems() {
$allowedItems = parent::getAllowedItems();
$blindLinkOptions = isset($this->thisConfig['blindLinkOptions'])
? GeneralUtility::trimExplode(',', $this->thisConfig['blindLinkOptions'], true)
: [];
$allowedItems = array_diff($allowedItems, $blindLinkOptions);
if (is_array($this->buttonConfig['options.']) && $this->buttonConfig['options.']['removeItems']) {
$allowedItems = array_diff($allowedItems, GeneralUtility::trimExplode(',', $this->buttonConfig['options.']['removeItems'], true));
}
return $allowedItems;
}
/**
* Get the allowed link attributes
*
* @return string[]
*/
protected function getAllowedLinkAttributes() {
$allowedLinkAttributes = parent::getAllowedLinkAttributes();
$blindLinkFields = isset($this->thisConfig['blindLinkFields'])
? GeneralUtility::trimExplode(',', $this->thisConfig['blindLinkFields'], true)
: [];
$allowedLinkAttributes = array_diff($allowedLinkAttributes, $blindLinkFields);
return $allowedLinkAttributes;
}
/**
* Create an array of link attribute field rendering definitions
*
* @return string[]
*/
protected function getLinkAttributeFieldDefinitions() {
$fieldRenderingDefinitions = parent::getLinkAttributeFieldDefinitions();
$fieldRenderingDefinitions['title'] = $this->getTitleField();
$fieldRenderingDefinitions['class'] = $this->getClassField();
$fieldRenderingDefinitions['target'] = $this->getTargetField();
$fieldRenderingDefinitions['rel'] = $this->getRelField();
if (empty($this->buttonConfig['queryParametersSelector.']['enabled'])) {
unset($fieldRenderingDefinitions['params']);
}
return $fieldRenderingDefinitions;
}
/**
* Add rel field
*
* @return string
*/
protected function getRelField() {
if (empty($this->buttonConfig['relAttribute.']['enabled'])) {
return '';
}
// @todo add rel to attributes
$currentRel = $this->displayedLinkHandler === $this->currentLinkHandler && !empty($this->currentLinkParts)
? $this->linkAttributeValues['rel']
: '';
// @todo define label "linkRelationship" below in xlf
return '
<form action="" name="lrelform" id="lrelform" class="t3js-dummyform">
<table border="0" cellpadding="2" cellspacing="1" id="typo3-linkRel">
<tr>
<td><label>' . $this->getLanguageService()->getLL('linkRelationship', true) . ':</label></td>
<td colspan="3"><input type="text" name="lrel" value="' . $currentRel . '" /></td>
</tr>
</table>
</form>
';
}
/**
* Add target selector
*
* @return string
*/
protected function getTargetField() {
$targetSelectorConfig = array();
if (is_array($this->buttonConfig['targetSelector.'])) {
$targetSelectorConfig = $this->buttonConfig['targetSelector.'];
}
$target = $this->linkAttributeValues['target'] ?: $this->defaultLinkTarget;
$lang = $this->getLanguageService();
$targetSelector = '';
if (!$targetSelectorConfig['disabled']) {
$targetSelector = '
<select name="ltarget_type" class="t3js-targetPreselect">
<option value=""></option>
<option value="_top">' . $lang->getLL('top', true) . '</option>
<option value="_blank">' . $lang->getLL('newWindow', true) . '</option>
</select>
';
}
return '
<form action="" name="ltargetform" id="ltargetform" class="t3js-dummyform">
<table border="0" cellpadding="2" cellspacing="1" id="typo3-linkTarget">
<tr' . ($targetSelectorConfig['disabled'] ? ' style="display: none;"' : '') . '>
<td style="width: 96px;">' . $lang->getLL('target', true) . ':</td>
<td>
<input type="text" name="ltarget" class="t3js-linkTarget" value="' . htmlspecialchars($target) . '" />
' . $targetSelector . '
</td>
</tr>
</table>
</form>
';
}
/**
* Add title selector
*
* @return string
*/
protected function getTitleField() {
if ($this->linkAttributeValues['title']) {
$title = $this->linkAttributeValues['title'];
} else {
$title = !$this->classesAnchorDefault[$this->displayedLinkHandlerId] ? '' : $this->classesAnchorDefaultTitle[$this->displayedLinkHandlerId];
}
if (isset($this->buttonConfig[$this->displayedLinkHandlerId . '.']['properties.']['title.']['readOnly'])) {
$readOnly = (bool)$this->buttonConfig[$this->displayedLinkHandlerId . '.']['properties.']['title.']['readOnly'];
} else {
$readOnly = isset($this->buttonConfig['properties.']['title.']['readOnly'])
? (bool) $this->buttonConfig['properties.']['title.']['readOnly']
: false;
}
if ($readOnly) {
$currentClass = $this->linkAttributeFields['class'];
if (!$currentClass) {
$currentClass = empty($this->classesAnchorDefault[$this->displayedLinkHandlerId]) ? '' : $this->classesAnchorDefault[$this->displayedLinkHandlerId];
}
$title = $currentClass
? $this->classesAnchorClassTitle[$currentClass]
: $this->classesAnchorDefaultTitle[$this->displayedLinkHandlerId];
}
// If type was not rendered, use default rendering functions
if (!$browserRendered) {
$GLOBALS['SOBE']->browser = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(
'SGalinski\Tinymce4Rte\BrowseLinks'
);
$GLOBALS['SOBE']->browser->init();
$modData = $GLOBALS['BE_USER']->getModuleData('browse_links.php', 'ses');
list($modData, $store) = $GLOBALS['SOBE']->browser->processSessionData($modData);
$GLOBALS['BE_USER']->pushModuleData('browse_links.php', $modData);
$this->content = $GLOBALS['SOBE']->browser->main_rte();
return '
<form action="" name="ltitleform" id="ltitleform" class="t3js-dummyform">
<table border="0" cellpadding="2" cellspacing="1" id="typo3-linkTitle">
<tr>
<td style="width: 96px;"><label for="rtehtmlarea-browse-links-anchor_title" id="rtehtmlarea-browse-links-title-label">' . $this->getLanguageService()->getLL('anchor_title', true) . '</label></td>
<td>
<span id="rtehtmlarea-browse-links-title-input" style="display: ' . ($readOnly ? 'none' : 'inline') . ';">
<input type="text" id="rtehtmlarea-browse-links-anchor_title" name="ltitle" value="' . htmlspecialchars($title) . '" />
</span>
<span id="rtehtmlarea-browse-links-title-readonly" style="display: ' . ($readOnly ? 'inline' : 'none') . ';">' . htmlspecialchars($title) . '</span>
</td>
</tr>
</table>
</form>
';
}
/**
* Return html code for the class selector
*
* @return string the html code to be added to the form
*/
protected function getClassField() {
$selectClass = '';
if ($this->classesAnchorJSOptions[$this->displayedLinkHandlerId]) {
$selectClass = '
<form action="" name="lclassform" id="lclassform" class="t3js-dummyform">
<table border="0" cellpadding="2" cellspacing="1" id="typo3-linkClass">
<tr>
<td style="width: 96px;">' . $this->getLanguageService()->getLL('anchor_class', true) . '</td>
<td><select name="lclass" class="t3js-class-selector">
' . $this->classesAnchorJSOptions[$this->displayedLinkHandlerId] . '
</select></td>
</tr>
</table>
</form>
';
}
return $selectClass;
}
/**
* Return the ID of current page
*
* @return int
*/
protected function getCurrentPageId() {
return explode(':', $this->RTEtsConfigParams)[5];
}
/**
* Print module content
* Retrieve the configuration
*
* This is only used by RTE currently.
*
* @return void
* @todo Define visibility
* @return array
*/
public function printContent() {
echo $this->content;
public function getConfiguration() {
return $this->buttonConfig;
}
/**
* Get attributes for the body tag
*
* @return string[] Array of body-tag attributes
*/
protected function getBodyTagAttributes() {
$parameters = parent::getBodyTagAttributes();
$parameters['data-site-url'] = $this->siteUrl;
return $parameters;
}
/**
* @param array $overrides
*
* @return array Array of parameters which have to be added to URLs
*/
public function getUrlParameters(array $overrides = null) {
return [
'act' => isset($overrides['act']) ? $overrides['act'] : $this->displayedLinkHandlerId,
'bparams' => $this->bparams,
'editorNo' => $this->editorNo,
'contentTypo3Language' => $this->contentTypo3Language
];
}
}
<?php
namespace SGalinski\Tinymce4Rte\Controller;
/**
* This file is part of the TYPO3 CMS project.
*
* It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2
* of the License, or any later version.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*
* The TYPO3 project - inspiring people to share!
*/
use TYPO3\CMS\Core\Resource;
use TYPO3\CMS\Core\Utility\GeneralUtility;
/**
* Render the image attributes and reconstruct magic images, if necessary (and possible)
*/
class ImageRenderingController extends \TYPO3\CMS\Frontend\Plugin\AbstractPlugin {
/**
* Same as class name
*
* @var string
*/
public $prefixId = 'ImageRenderingController';
/**
* Path to this script relative to the extension dir
*
* @var string
*/
public $scriptRelPath = 'Classes/Controller/ImageRenderingController.php';
/**
* The extension key
*
* @var string
*/
public $extKey = 'tinymce4_rte';
/**
* Configuration
*
* @var array
*/
public $conf = array();
/**
* cObj object
*
* @var \TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer
*/
public $cObj;
/**
* Returns a processed image to be displayed on the Frontend.
*
* @param string $content Content input (not used).
* @param array $conf TypoScript configuration
* @return string HTML output
*/
public function renderImageAttributes($content = '', $conf) {
$imageAttributes = $this->getImageAttributes();
// It is pretty rare to be in presence of an external image as the default behaviour
// of the RTE is to download the external image and create a local image.
// However, it may happen if the RTE has the flag "disable"
if (!$this->isExternalImage()) {
$fileUid = (int) $imageAttributes['data-htmlarea-file-uid'];
if ($fileUid) {
try {
$file = Resource\ResourceFactory::getInstance()->getFileObject($fileUid);
if ($imageAttributes['src'] !== $file->getPublicUrl()) {
// Source file is a processed image
$imageConfiguration = array(
'width' => (int) $imageAttributes['width'],
'height' => (int) $imageAttributes['height']
);
$processedFile = $this->getMagicImageService()->createMagicImage($file, $imageConfiguration);
$additionalAttributes = array(
'src' => $processedFile->getPublicUrl(),
'title' => $imageAttributes['title'] ? : $file->getProperty('title'),
'alt' => $imageAttributes['alt'] ? : $file->getProperty('alternative'),
'width' => $processedFile->getProperty('width'),
'height' => $processedFile->getProperty('height'),
);
$imageAttributes = array_merge($imageAttributes, $additionalAttributes);
}
} catch (Resource\Exception\FileDoesNotExistException $fileDoesNotExistException) {
// Log the fact the file could not be retrieved.
$message = sprintf('I could not find file with uid "%s"', $fileUid);
$this->getLogger()->error($message);
}
}
}
return '<img ' . GeneralUtility::implodeAttributes($imageAttributes, TRUE, TRUE) . ' />';
}
/**
* Returns a sanitizes array of attributes out of $this->cObj
*
* @return array
*/
protected function getImageAttributes() {
return $this->cObj->parameters;
}
/**
* Instantiates and prepares the Magic Image service.
*
* @return \TYPO3\CMS\Core\Resource\Service\MagicImageService
*/
protected function getMagicImageService() {
/** @var $magicImageService Resource\Service\MagicImageService */
$magicImageService = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Resource\\Service\\MagicImageService');
// Get RTE configuration
$pageTSConfig = $this->getFrontendObject()->getPagesTSconfig();
if (is_array($pageTSConfig) && is_array($pageTSConfig['RTE.'])) {
$magicImageService->setMagicImageMaximumDimensions($pageTSConfig['RTE.']);
}
return $magicImageService;
}
/**
* Tells whether the image URL is found to be "external".
*
* @return bool
*/
protected function isExternalImage() {
$srcAbsoluteUrl = $this->cObj->parameters['src'];
return strtolower(substr($srcAbsoluteUrl, 0, 4)) === 'http' || substr($srcAbsoluteUrl, 0, 2) === '//';
}
/**
* @return \TYPO3\CMS\Core\Log\Logger
*/
protected function getLogger() {
/** @var $logManager \TYPO3\CMS\Core\Log\LogManager */
$logManager = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Log\\LogManager');
return $logManager->getLogger(get_class($this));
}
/**
* Returns an instance of the Frontend object.
*
* @return \TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController
*/
protected function getFrontendObject() {
return $GLOBALS['TSFE'];
}
}
<?php
namespace SGalinski\Tinymce4Rte\Controller;
/***************************************************************
* Copyright notice
*
* (c) sgalinski Internet Services (http://www.sgalinski.de)
*
* All rights reserved
*
* This script is part of the TYPO3 project. The TYPO3 project is
* free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* The GNU General Public License can be found at
* http://www.gnu.org/copyleft/gpl.html.
*
* This script is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* This copyright notice MUST APPEAR in all copies of the script!
***************************************************************/
/*
* This file is part of the TYPO3 CMS project.
*
* It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2
* of the License, or any later version.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*
* The TYPO3 project - inspiring people to share!
*/
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use TYPO3\CMS\Backend\Utility\BackendUtility;
use TYPO3\CMS\Core\Resource\ResourceFactory;
use TYPO3\CMS\Core\Resource\Service\MagicImageService;
use TYPO3\CMS\Core\Service\DependencyOrderingService;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Recordlist\Controller\AbstractLinkBrowserController;
use TYPO3\CMS\Recordlist\LinkHandler\LinkHandlerInterface;
/**
* Script class for the Element Browser window.
* Script class to select images in RTE
*/
class SelectImageController {
public $mode = 'rte';
public $button = 'image';
protected $content = '';
/**
* Initialize language files
*/
public function __construct() {
$GLOBALS['LANG']->includeLLFile('EXT:lang/locallang_TYPO3\\CMS\\Recordlist\\Browser\\ElementBrowser.xlf');
$GLOBALS['LANG']->includeLLFile('EXT:tinymce4_rte/mod4/locallang.xlf');
}
/**
* Main function, rendering the element browser in RTE mode.
*
* @return void
* @todo Define visibility
*/
public function main() {
// Setting alternative browsing mounts (ONLY local to browse_links.php this script so they stay "read-only")
$altMountPoints = trim($GLOBALS['BE_USER']->getTSConfigVal('options.folderTree.altElementBrowserMountPoints'));
if ($altMountPoints) {
$altMountPoints = \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(',', $altMountPoints);
foreach ($altMountPoints as $filePathRelativeToFileadmindir) {
// @todo: add this feature for FAL and TYPO3 6.2
}
}
// Rendering type by user function
$browserRendered = FALSE;
if (is_array(
$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/TYPO3\\CMS\\Recordlist\\Browser\\ElementBrowser.php']['browserRendering']
)
) {
foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/TYPO3\\CMS\\Recordlist\\Browser\\ElementBrowser.php']['browserRendering'] as $classRef) {
$browserRenderObj = \TYPO3\CMS\Core\Utility\GeneralUtility::getUserObj($classRef);
if (is_object($browserRenderObj) && method_exists($browserRenderObj, 'isValid') && method_exists(
$browserRenderObj, 'render'
)
) {
if ($browserRenderObj->isValid($this->mode, $this)) {
$this->content .= $browserRenderObj->render($this->mode, $this);
$browserRendered = TRUE;
break;
}
}
}
}
// If type was not rendered, use default rendering functions
if (!$browserRendered) {
$GLOBALS['SOBE']->browser = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(
'SGalinski\Tinymce4Rte\SelectImage'
);
$GLOBALS['SOBE']->browser->init();
$modData = $GLOBALS['BE_USER']->getModuleData('select_image.php', 'ses');
list($modData, $store) = $GLOBALS['SOBE']->browser->processSessionData($modData);
$GLOBALS['BE_USER']->pushModuleData('select_image.php', $modData);
$this->content = $GLOBALS['SOBE']->browser->main_rte();
}
}
/**
* Print module content
*
* @return void
* @todo Define visibility
*/
public function printContent() {
echo $this->content;
}
class SelectImageController extends AbstractLinkBrowserController
{
/**
* These file extensions are allowed in the "plain" image selection mode.
*
* @const
*/
const PLAIN_MODE_IMAGE_FILE_EXTENSIONS = 'jpg,jpeg,gif,png';
/**
* Active with TYPO3 Element Browser: Contains the name of the form field for which this window
* opens - thus allows us to make references back to the main window in which the form is.
* Example value: "data[pages][39][bodytext]|||tt_content|"
* or "data[tt_content][NEW3fba56fde763d][image]|||gif,jpg,jpeg,tif,bmp,pcx,tga,png,pdf,ai|"
*
* Values:
* 0: form field name reference, eg. "data[tt_content][123][image]"
* 1: htmlArea RTE parameters: editorNo:contentTypo3Language
* 2: RTE config parameters: RTEtsConfigParams
* 3: allowed types. Eg. "tt_content" or "gif,jpg,jpeg,tif,bmp,pcx,tga,png,pdf,ai"
*
* $pArr = explode('|', $this->bparams);
* $formFieldName = $pArr[0];
* $allowedTablesOrFileTypes = $pArr[3];
*
* @var string
*/
protected $bparams;
/**
* RTE configuration
*
* @var array
*/
protected $RTEProperties = [];
/**
* Used with the Rich Text Editor.
* Example value: "tt_content:NEW3fba58c969f5c:bodytext:23:text:23:"
*
* @var string
*/
protected $RTEtsConfigParams;
/**
* @var int
*/
protected $editorNo;
/**
* TYPO3 language code of the content language
*
* @var int
*/
protected $contentTypo3Language;
/**
* @var array
*/
protected $buttonConfig = [];
/**
* Initialize controller
*/
protected function init()
{
parent::init();
$this->getLanguageService()->includeLLFile('EXT:tinymce4_rte/Resources/Private/Language/locallang_dialogs.xlf');
}
/**
* @param ServerRequestInterface $request
*/
protected function initVariables(ServerRequestInterface $request)
{
parent::initVariables($request);
$queryParameters = $request->getQueryParams();
$this->bparams = isset($queryParameters['bparams']) ? $queryParameters['bparams'] : '';
$this->currentLinkParts['currentImage'] = !empty($queryParameters['fileUid']) ? $queryParameters['fileUid'] : 0;
// Process bparams
$pArr = explode('|', $this->bparams);
$pRteArr = explode(':', $pArr[1]);
$this->editorNo = $pRteArr[0];
$this->contentTypo3Language = $pRteArr[1];
$this->RTEtsConfigParams = $pArr[2];
if (!$this->editorNo) {
$this->editorNo = GeneralUtility::_GP('editorNo');
$this->contentTypo3Language = GeneralUtility::_GP('contentTypo3Language');
$this->RTEtsConfigParams = GeneralUtility::_GP('RTEtsConfigParams');
}
$pArr[1] = implode(':', array($this->editorNo, $this->contentTypo3Language));
$pArr[2] = $this->RTEtsConfigParams;
$pArr[3] = $this->displayedLinkHandlerId === 'plain'
? self::PLAIN_MODE_IMAGE_FILE_EXTENSIONS
: '';
$this->bparams = implode('|', $pArr);
$RTEtsConfigParts = explode(':', $this->RTEtsConfigParams);
$RTEsetup = $this->getBackendUser()->getTSConfig('RTE', BackendUtility::getPagesTSconfig($RTEtsConfigParts[5]));
$this->RTEProperties = $RTEsetup['properties'];
$thisConfig = BackendUtility::RTEsetup($this->RTEProperties, $RTEtsConfigParts[0], $RTEtsConfigParts[2], $RTEtsConfigParts[4]);
$this->buttonConfig = isset($thisConfig['buttons.']['image.'])
? $thisConfig['buttons.']['image.']
: [];
}
/**
* Initialize hook objects implementing the interface
*
* @throws \UnexpectedValueException
* @return void
*/
protected function initHookObjects()
{
if (
isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['RteImageSelector']['hooks'])
&& is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['RteImageSelector']['hooks'])
) {
$hooks = GeneralUtility::makeInstance(DependencyOrderingService::class)->orderByDependencies(
$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['RteImageSelector']['hooks']
);
foreach ($hooks as $key => $hook) {
$this->hookObjects[] = GeneralUtility::makeInstance($hook['handler']);
}
}
}
/**
* Reads the configured image handlers from page TSconfig
*
* @return array
* @throws \UnexpectedValueException
*/
protected function getLinkHandlers()
{
$imageHandler = $this->buttonConfig['options.']['imageHandler.'];
foreach ($this->hookObjects as $hookObject) {
if (method_exists($hookObject, 'modifyImageHandlers')) {
$imageHandler = $hookObject->modifyImageHandlers($imageHandler, $this->currentLinkParts);
}
}
if (empty($imageHandler)) {
throw new \UnexpectedValueException('No image handlers are configured. Check page TSconfig RTE.default.buttons.image.options.imageHandler.', 1455499673);
}
return $imageHandler;
}
/**
* Initialize $this->currentLinkParts and $this->currentLinkHandler
*
* @return void
*/
protected function initCurrentUrl()
{
if (empty($this->currentLinkParts)) {
return;
}
$orderedHandlers = GeneralUtility::makeInstance(DependencyOrderingService::class)->orderByDependencies($this->linkHandlers, 'scanBefore', 'scanAfter');
// find responsible handler for current image
foreach ($orderedHandlers as $key => $configuration) {
/** @var LinkHandlerInterface $handler */
$handler = $configuration['handlerInstance'];
if ($handler->canHandleLink($this->currentLinkParts)) {
$this->currentLinkHandler = $handler;
$this->currentLinkHandlerId = $key;
break;
}
}
// reset the image reference if we have no handler for it
if (!$this->currentLinkHandler) {
$this->currentLinkParts = [];
}
}
/**
* Render the currently set URL
*
* @return string
*/
protected function renderCurrentUrl()
{
return '<!-- Print current URL -->
<table border="0" cellpadding="0" cellspacing="0" id="typo3-curUrl">
<tr>
<td>' . htmlspecialchars($this->getLanguageService()->getLL('currentImage')) . ': ' . htmlspecialchars($this->currentLinkHandler->formatCurrentUrl()) . '</td>
</tr>
</table>';
}
/**
* Get the allowed items or tabs
*
* @return string[]
*/
protected function getAllowedItems()
{
$allowedItems = array_keys($this->linkHandlers);
foreach ($this->hookObjects as $hookObject) {
if (method_exists($hookObject, 'modifyAllowedItems')) {
$allowedItems = $hookObject->modifyAllowedItems($allowedItems, $this->currentLinkParts);
}
}
return $allowedItems;
}
/**
* @param array $overrides
*
* @return array Array of parameters which have to be added to URLs
*/
public function getUrlParameters(array $overrides = null)
{
return [
'act' => isset($overrides['act']) ? $overrides['act'] : $this->displayedLinkHandlerId,
'bparams' => $this->bparams,
'editorNo' => $this->editorNo
];
}
/**
* @return array
*/
public function getButtonConfiguration() {
return $this->buttonConfig;
}
/**
* @return array
*/
public function getRteProperties() {
return $this->RTEProperties;
}
/**
* Compile the final tags to be inserted into RTE
*
* @param ServerRequestInterface $request
* @param ResponseInterface $response
* @return ResponseInterface
*/
public function buildImageMarkup(ServerRequestInterface $request, ResponseInterface $response)
{
$this->initVariables($request);
$uidList = GeneralUtility::_GP('uidList');
// handle ajax request for
$uids = explode('|', $uidList);
$tags = array();
foreach ($uids as $uid) {
$fileObject = ResourceFactory::getInstance()->getFileObject((int)$uid);
// Get default values for alt and title attributes from file properties
$altText = $fileObject->getProperty('alternative');
$titleText = $fileObject->getProperty('title');
if ($this->displayedLinkHandlerId === 'magic') {
// Create the magic image service
$magicImageService = GeneralUtility::makeInstance(MagicImageService::class);
$magicImageService->setMagicImageMaximumDimensions($this->RTEProperties['default.']);
// Create the magic image
$imageConfiguration = array(
'width' => GeneralUtility::_GP('cWidth'),
'height' => GeneralUtility::_GP('cHeight')
);
$fileObject = $magicImageService->createMagicImage($fileObject, $imageConfiguration);
$width = $fileObject->getProperty('width');
$height = $fileObject->getProperty('height');
} else {
$width = $fileObject->getProperty('width');
$height = $fileObject->getProperty('height');
if (!$width || !$height) {
$filePath = $fileObject->getForLocalProcessing(false);
$imageInfo = @getimagesize($filePath);
$width = $imageInfo[0];
$height = $imageInfo[1];
}
}
$imageUrl = $fileObject->getPublicUrl();
// If file is local, make the url absolute
if (strpos($imageUrl, 'http') !== 0) {
$imageUrl = GeneralUtility::getIndpEnv('TYPO3_SITE_URL') . $imageUrl;
}
$tags[] = '<img src="' . htmlspecialchars($imageUrl) . '" width="' . htmlspecialchars($width) . '" height="' . htmlspecialchars($height) . '"'
. (isset($this->buttonConfig['properties.']['class.']['default'])
? ' class="' . trim($this->buttonConfig['properties.']['class.']['default']) . '"'
: '')
. ' alt = "' . ($altText ? htmlspecialchars($altText) : '') . '"'
. ($titleText ? ' title="' . htmlspecialchars($titleText) . '"' : '')
. ' data-htmlarea-file-uid="' . (int)$uid . '" />';
}
$finalHtmlCode = implode(' ', $tags);
$response->getBody()->write(json_encode(['images' => $finalHtmlCode]));
return $response;
}
/**
* Return the ID of current page
*
* @return int
* @throws \RuntimeException
*/
protected function getCurrentPageId()
{
throw new \RuntimeException('Invalid method call. This function is not supported for image handlers', 14554996791);
}
}
<?php
namespace SGalinski\Tinymce4Rte\Editors;
/***************************************************************
* Copyright notice
*
* (c) sgalinski Internet Services (http://www.sgalinski.de)
*
* All rights reserved
*
* This script is part of the TYPO3 project. The TYPO3 project is
* free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* The GNU General Public License can be found at
* http://www.gnu.org/copyleft/gpl.html.
*
* This script is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* This copyright notice MUST APPEAR in all copies of the script!
***************************************************************/
use TYPO3\CMS\Backend\Form\FormEngine;
use TYPO3\CMS\Backend\Rte\AbstractRte;
use TYPO3\CMS\Backend\Utility\BackendUtility;
use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
use TYPO3\CMS\Core\Utility\GeneralUtility;
/**
* A RTE using TinyMCE
*/
class RteBase extends AbstractRte {
/**
* Indicates that the tinymce is loaded
*
* @var bool
*/
static protected $coreLoaded = FALSE;
/**
* Draws the RTE as a form field or whatever is needed (inserts JavaApplet, creates iframe, renders ....)
* Default is to output the transformed content in a plain textarea field. This mode is great for debugging transformations!
*
* @param FormEngine $parentObject Reference to parent object, which is an instance of the TCEforms.
* @param string $table The table name
* @param string $field The field name
* @param array $row The current row from which field is being rendered
* @param array $PA Array of standard content for rendering form fields from TCEforms. See TCEforms for details on this. Includes for instance the value and the form field name, java script actions and more.
* @param array $specConf "special" configuration - what is found at position 4 in the types configuration of a field from record, parsed into an array.
* @param array $thisConfig Configuration for RTEs; A mix between TSconfig and otherwise. Contains configuration for display, which buttons are enabled, additional transformation information etc.
* @param string $RTEtypeVal Record "type" field value.
* @param string $RTErelPath Relative path for images/links in RTE; this is used when the RTE edits content from static files where the path of such media has to be transformed forth and back!
* @param integer $thePidValue PID value of record (true parent page id)
* @return string HTML code for RTE!
*/
public function drawRTE(
FormEngine $parentObject, $table, $field, $row, $PA, $specConf,
$thisConfig, $RTEtypeVal, $RTErelPath, $thePidValue
) {
// render the tinymce textarea
$value = $this->transformContent(
'rte', $PA['itemFormElValue'], $table, $field, $row, $specConf, $thisConfig, $RTErelPath, $thePidValue
);
// render RTE field
$editorId = uniqid();
$code = $this->triggerField($PA['itemFormElName']);
$code .= '<textarea id="editor' . $editorId . '" class="tinymce4_rte"
name="' . htmlspecialchars($PA['itemFormElName']) . '"
rows="20" cols="100">' . GeneralUtility::formatForTextarea($value) . '</textarea>';
// add dedicated RTE configuration
$elementParts = preg_replace('/^(TSFE_EDIT\\[data\\]\\[|data\\[)/', '', $PA['itemFormElName']);
$elementParts = preg_replace('/\\]$/', '', $elementParts);
$elementParts = explode('][', $elementParts);
list($typoscriptConfigurationPid, $pid) = BackendUtility::getTSCpid(
trim($elementParts[0]), trim($elementParts[1]), $thePidValue
);
$rteConfiguration = rawurlencode(
$this->getRteConfiguration($specConf, $RTEtypeVal, $pid, $typoscriptConfigurationPid, $elementParts)
);
$languageId = max($row['sys_language_uid'], 0);
$language = ($GLOBALS['LANG']->lang === '' ? 'default' : $GLOBALS['LANG']->lang);
$code .= '
<script type = "text/javascript" >
var RTE = RTE || {};
RTE["editor' . $editorId . '"] = {};
RTE["editor' . $editorId . '"].rteConfiguration = "' . $rteConfiguration . '";
RTE["editor' . $editorId . '"].typo3ContentLanguage = "' . $language . '";
RTE["editor' . $editorId . '"].sys_language_content = parseInt(' . $languageId . ');
</script>';
// load the tinymce code and it's configuration
if (!self::$coreLoaded) {
self::$coreLoaded = TRUE;
$userOrPageProperties = BackendUtility::getModTSconfig($thePidValue, 'RTE');
/** @var \tinyMCE $tinyMCE */
require_once(ExtensionManagementUtility::extPath('tinymce') . 'class.tinymce.php');
$tinyMCE = GeneralUtility::makeInstance('tinyMCE');
$tinyMCE->loadConfiguration($userOrPageProperties['properties']['default.']['tinymceConfiguration']);
if ($userOrPageProperties['properties']['default.']['contentCSS'] !== '') {
$tinyMCE->addConfigurationOption(
'content_css',
'/' . $userOrPageProperties['properties']['default.']['contentCSS']
);
}
$code .= $tinyMCE->getJS();
$imageModule = BackendUtility::getModuleUrl('rtehtmlarea_wizard_select_image');
$linkModule = BackendUtility::getModuleUrl('rtehtmlarea_wizard_element_browser');
$code .= '
<script type = "text/javascript" >
var RTE = RTE || {};
RTE.linkToImageModule = ' . GeneralUtility::quoteJSvalue($imageModule) . ';
RTE.linkToLinkModule = ' . GeneralUtility::quoteJSvalue($linkModule) . ';
</script>';
}
return $code;
}
/**
* @param array $configuration
* @param string $typeValue
* @param int $pid
* @param int $typoscriptConfigurationPid
* @param array $elementParts
* @return string
*/
public function getRteConfiguration(
array $configuration, $typeValue, $pid, $typoscriptConfigurationPid, array $elementParts
) {
$parameters = BackendUtility::getSpecConfParametersFromArray($configuration['rte_transform']['parameters']);
return $elementParts[0] . ':' . $elementParts[1] . ':' . $elementParts[2] . ':' . (int) $pid . ':' .
$typeValue . ':' . (int) $typoscriptConfigurationPid . ':' . $parameters['imgpath'];
}
}
?>
\ No newline at end of file
<?php
namespace SGalinski\Tinymce4Rte\Extension;
/*
* This file is part of the TYPO3 CMS project.
*
* It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2
* of the License, or any later version.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*
* The TYPO3 project - inspiring people to share!
*/
use SGalinski\Tinymce4Rte\RteHtmlAreaApi;
use TYPO3\CMS\Backend\Utility\BackendUtility;
use TYPO3\CMS\Core\Utility\GeneralUtility;
/**
* TYPO3 Image plugin for htmlArea RTE
*/
class Typo3Image extends RteHtmlAreaApi
{
/**
* The name of the plugin registered by the extension
*
* @var string
*/
protected $pluginName = 'TYPO3Image';
/**
* The comma-separated list of button names that the registered plugin is adding to the htmlArea RTE toolbar
*
* @var string
*/
protected $pluginButtons = 'image';
/**
* The name-converting array, converting the button names used in the RTE PageTSConfing to the button id's used by the JS scripts
*
* @var array
*/
protected $convertToolbarForHtmlAreaArray = array(
'image' => 'InsertImage'
);
/**
* Returns TRUE if the plugin is available and correctly initialized
*
* @param array $configuration Configuration array given from calling object down to the single plugins
* @return bool TRUE if this plugin object should be made available in the current environment and is correctly initialized
*/
public function main(array $configuration)
{
// Check if this should be enabled based on extension configuration and Page TSConfig
// The 'Minimal' and 'Typical' default configurations include Page TSConfig that removes images on the way to the database
return parent::main($configuration)
&& !(
$this->configuration['thisConfig']['proc.']['entryHTMLparser_db.']['tags.']['img.']['allowedAttribs'] == '0'
&& $this->configuration['thisConfig']['proc.']['entryHTMLparser_db.']['tags.']['img.']['rmTagIfNoAttrib'] == '1'
)
&& !$this->configuration['thisConfig']['buttons.']['image.']['TYPO3Browser.']['disabled'];
}
/**
* Return JS configuration of the htmlArea plugins registered by the extension
*
* @return string JS configuration for registered plugins, in this case, JS configuration of block elements
*/
public function buildJavascriptConfiguration()
{
$jsArray = array();
$button = 'image';
// if (in_array($button, $this->toolbar)) {
if (!is_array($this->configuration['thisConfig']['buttons.']) || !is_array($this->configuration['thisConfig']['buttons.'][$button . '.'])) {
$jsArray[] = 'RTEarea[editornumber]["buttons"]["' . $button . '"] = new Object();';
}
$jsArray[] = 'RTEarea[editornumber].buttons.' . $button . '.pathImageModule = ' . GeneralUtility::quoteJSvalue(BackendUtility::getModuleUrl('rtehtmlarea_wizard_select_image')) . ';';
// }
return implode(LF, $jsArray);
}
}
<?php
namespace SGalinski\Tinymce4Rte\Extension;
/*
* This file is part of the TYPO3 CMS project.
*
* It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2
* of the License, or any later version.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*
* The TYPO3 project - inspiring people to share!
*/
use SGalinski\Tinymce4Rte\RteHtmlAreaApi;
use TYPO3\CMS\Backend\Utility\BackendUtility;
use TYPO3\CMS\Core\Utility\GeneralUtility;
/**
* TYPO3Link plugin for htmlArea RTE
*/
class Typo3Link extends RteHtmlAreaApi {
/**
* The name of the plugin registered by the extension
*
* @var string
*/
protected $pluginName = 'TYPO3Link';
/**
* The comma-separated list of button names that the registered plugin is adding to the htmlArea RTE toolbar
*
* @var string
*/
protected $pluginButtons = 'link, unlink';
/**
* The name-converting array, converting the button names used in the RTE PageTSConfing to the button id's used by the JS scripts
*
* @var array
*/
protected $convertToolbarForHtmlAreaArray = array(
'link' => 'CreateLink',
'unlink' => 'UnLink'
);
/**
* Returns TRUE if the plugin is available and correctly initialized
*
* @param array $configuration Configuration array given from calling object down to the single plugins
* @return bool TRUE if this plugin object should be made available in the current environment and is correctly initialized
*/
public function main(array $configuration) {
// Check if this should be enabled based on Page TSConfig
return parent::main($configuration)
&& !$this->configuration['thisConfig']['buttons.']['link.']['TYPO3Browser.']['disabled'];
}
/**
* Return JS configuration of the htmlArea plugins registered by the extension
*
* @return string JS configuration for registered plugins, in this case, JS configuration of block elements
*/
public function buildJavascriptConfiguration() {
$jsArray = array();
$button = 'link';
// if (in_array($button, $this->toolbar)) {
if (!is_array($this->configuration['thisConfig']['buttons.']) || !is_array($this->configuration['thisConfig']['buttons.'][$button . '.'])) {
$jsArray[] = 'RTEarea[editornumber].buttons.' . $button . ' = new Object();';
}
$jsArray[] = 'RTEarea[editornumber].buttons.' . $button . '.pathLinkModule = ' . GeneralUtility::quoteJSvalue(BackendUtility::getModuleUrl('rtehtmlarea_wizard_browse_links')) . ';';
if (is_array($this->configuration['RTEsetup']['properties']['classesAnchor.'])) {
$jsArray[] = 'RTEarea[editornumber].buttons.' . $button . '.classesAnchorUrl = "' . $this->writeTemporaryFile('classesAnchor_' . $this->configuration['contentLanguageUid'], 'js', $this->buildJSClassesAnchorArray()) . '";';
}
$jsArray[] = 'RTEarea[editornumber].buttons.' . $button . '.additionalAttributes = "data-htmlarea-external' . ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF'][$this->extensionKey]['plugins'][$this->pluginName]['additionalAttributes'] ? ',' . $GLOBALS['TYPO3_CONF_VARS']['EXTCONF'][$this->extensionKey]['plugins'][$this->pluginName]['additionalAttributes'] : '') . '";';
// }
return implode(LF, $jsArray);
}
/**
* Return a JS array for special anchor classes
*
* @return string classesAnchor array definition
*/
public function buildJSClassesAnchorArray() {
$JSClassesAnchorArray = 'HTMLArea.classesAnchorSetup = [ ' . LF;
$classesAnchorIndex = 0;
foreach ($this->configuration['RTEsetup']['properties']['classesAnchor.'] as $label => $conf) {
if (is_array($conf) && $conf['class']) {
$JSClassesAnchorArray .= ($classesAnchorIndex++ ? ',' : '') . ' { ' . LF;
$index = 0;
$JSClassesAnchorArray .= ($index++ ? ',' : '') . 'name : "' . str_replace('"', '', str_replace('\'', '', $conf['class'])) . '"' . LF;
if ($conf['type']) {
$JSClassesAnchorArray .= ($index++ ? ',' : '') . 'type : "' . str_replace('"', '', str_replace('\'', '', $conf['type'])) . '"' . LF;
}
if (trim(str_replace('\'', '', str_replace('"', '', $conf['image'])))) {
$JSClassesAnchorArray .= ($index++ ? ',' : '') . 'image : "' . GeneralUtility::getIndpEnv('TYPO3_SITE_URL') . GeneralUtility::resolveBackPath((TYPO3_mainDir . $this->getFullFileName(trim(str_replace('\'', '', str_replace('"', '', $conf['image'])))))) . '"' . LF;
}
$JSClassesAnchorArray .= ($index++ ? ',' : '') . 'addIconAfterLink : ' . ($conf['addIconAfterLink'] ? 'true' : 'false') . LF;
if (trim($conf['altText'])) {
$string = GeneralUtility::quoteJSvalue($this->getLanguageService()->sL(trim($conf['altText'])));
$JSClassesAnchorArray .= ($index++ ? ',' : '') . 'altText : ' . str_replace('"', '\\"', str_replace('\\\'', '\'', $string)) . LF;
}
if (trim($conf['titleText'])) {
$string = GeneralUtility::quoteJSvalue($this->getLanguageService()->sL(trim($conf['titleText'])));
$JSClassesAnchorArray .= ($index++ ? ',' : '') . 'titleText : ' . str_replace('"', '\\"', str_replace('\\\'', '\'', $string)) . LF;
}
if (trim($conf['target'])) {
$JSClassesAnchorArray .= ($index++ ? ',' : '') . 'target : "' . trim($conf['target']) . '"' . LF;
}
$JSClassesAnchorArray .= '}' . LF;
}
}
$JSClassesAnchorArray .= '];' . LF;
return $JSClassesAnchorArray;
}
/**
* Return an updated array of toolbar enabled buttons
*
* @param array $show : array of toolbar elements that will be enabled, unless modified here
* @return array toolbar button array, possibly updated
*/
public function applyToolbarConstraints($show) {
// We will not allow unlink if link is not enabled
if (!in_array('link', $show)) {
return array_diff($show, GeneralUtility::trimExplode(',', $this->pluginButtons));
} else {
return $show;
}
}
}
<?php
namespace SGalinski\Tinymce4Rte;
/***************************************************************
* Copyright notice
*
* (c) sgalinski Internet Services (http://www.sgalinski.de)
*
* All rights reserved
*
* This script is part of the TYPO3 project. The TYPO3 project is
* free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* The GNU General Public License can be found at
* http://www.gnu.org/copyleft/gpl.html.
*
* This script is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* This copyright notice MUST APPEAR in all copies of the script!
***************************************************************/
use TYPO3\CMS\Core\Utility\GeneralUtility;
/**
* Base extension class which generates the folder tree.
* Used directly by the RTE.
*/
class FolderTree extends \localFolderTree {
/**
* Constructor function of the class
*/
public function __construct() {
// The backpath is set here to fix problems with relatives path when used in ajax scope
$GLOBALS['BACK_PATH'] = isset($GLOBALS['ajaxID']) ? '../../../' : $GLOBALS['BACK_PATH'];
parent::__construct();
}
/**
* Wrapping the title in a link, if applicable.
*
* @param string $title Title, ready for output.
* @param \TYPO3\CMS\Core\Resource\Folder $folderObject The "record"
* @return string Wrapping title string.
* @todo Define visibility
*/
public function wrapTitle($title, \TYPO3\CMS\Core\Resource\Folder $folderObject) {
if ($this->ext_isLinkable($folderObject)) {
$aOnClick = 'return jumpToUrl(\'' . $this->getThisScript(
) . 'act=' . $GLOBALS['SOBE']->browser->act . '&mode=' . $GLOBALS['SOBE']->browser->mode . '&editorNo=' . $GLOBALS['SOBE']->browser->editorNo . '&contentTypo3Language=' . $GLOBALS['SOBE']->browser->contentTypo3Language . '&contentTypo3Charset=' . $GLOBALS['SOBE']->browser->contentTypo3Charset . '&expandFolder=' . rawurlencode(
$folderObject->getCombinedIdentifier()
) . '\');';
return '<a href="#" onclick="' . htmlspecialchars($aOnClick) . '">' . $title . '</a>';
} else {
return '<span class="typo3-dimmed">' . $title . '</span>';
}
}
/**
* Wrap the plus/minus icon in a link
*
* @param string $icon HTML string to wrap, probably an image tag.
* @param string $cmd Command for 'PM' get var
* @param boolean $isExpand If expanded
* @return string Link-wrapped input string
* @access private
*/
public function PMiconATagWrap($icon, $cmd, $isExpand = TRUE) {
if (empty($this->scope)) {
$this->scope = array(
'class' => get_class($this),
'script' => $this->thisScript,
'ext_noTempRecyclerDirs' => $this->ext_noTempRecyclerDirs,
'browser' => array(
'mode' => $GLOBALS['SOBE']->browser->mode,
'act' => $GLOBALS['SOBE']->browser->act,
'editorNo' => $GLOBALS['SOBE']->browser->editorNo
),
);
}
if ($this->thisScript) {
// Activates dynamic AJAX based tree
$scopeData = serialize($this->scope);
$scopeHash = GeneralUtility::hmac($scopeData);
$js = htmlspecialchars(
'Tree.load(' . GeneralUtility::quoteJSvalue(
$cmd
) . ', ' . (int) $isExpand . ', this, ' . GeneralUtility::quoteJSvalue(
$scopeData
) . ', ' . GeneralUtility::quoteJSvalue($scopeHash) . ');'
);
return '<a class="pm" onclick="' . $js . '">' . $icon . '</a>';
} else {
return $icon;
}
}
}
This diff is collapsed.
<?php
namespace SGalinski\Tinymce4Rte\Form\Resolver;
/*
* This file is part of the TYPO3 CMS project.
*
* It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2
* of the License, or any later version.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*
* The TYPO3 project - inspiring people to share!
*/
use SGalinski\Tinymce4Rte\Form\Element\RichTextElement;
use SGalinski\Tinymce4Rte\Utility\VersionUtility;
use TYPO3\CMS\Backend\Form\NodeFactory;
use TYPO3\CMS\Backend\Form\NodeResolverInterface;
use TYPO3\CMS\Backend\Utility\BackendUtility;
use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
/**
* This resolver will return the RichTextElement render class of ext:rtehtmlarea if RTE is enabled for this field.
*/
class RichTextNodeResolver implements NodeResolverInterface {
/**
* Global options from NodeFactory
*
* @var array
*/
protected $data;
/**
* Default constructor receives full data array
*
* @param NodeFactory $nodeFactory
* @param array $data
*/
public function __construct(NodeFactory $nodeFactory, array $data) {
$this->data = $data;
}
/**
* Returns RichTextElement as class name if RTE widget should be rendered.
*
* @return string|NULL New class name or void if this resolver does not change current class name.
*/
public function resolve() {
$table = $this->data['tableName'];
$fieldName = $this->data['fieldName'];
$row = $this->data['databaseRow'];
$parameterArray = $this->data['parameterArray'];
$backendUser = $this->getBackendUserAuthentication();
if (VersionUtility::isVersion870OrHigher()) {
$parameterArray = $this->data['parameterArray'];
$backendUser = $this->getBackendUserAuthentication();
if (// This field is not read only
!$parameterArray['fieldConf']['config']['readOnly']
// If RTE is generally enabled by user settings and RTE object registry can return something valid
&& $backendUser->isRTE()
// If RTE is enabled for field
&& isset($parameterArray['fieldConf']['config']['enableRichtext'])
&& (bool) $parameterArray['fieldConf']['config']['enableRichtext'] === TRUE
// If RTE config is found (prepared by TcaText data provider)
&& isset($parameterArray['fieldConf']['config']['richtextConfiguration'])
&& is_array($parameterArray['fieldConf']['config']['richtextConfiguration'])
// If RTE is not disabled on configuration level
&& !$parameterArray['fieldConf']['config']['richtextConfiguration']['disabled']
) {
return RichTextElement::class;
}
} else {
if (// This field is not read only
!$parameterArray['fieldConf']['config']['readOnly']
// If RTE is generally enabled by user settings and RTE object registry can return something valid
&& $backendUser->isRTE()
) {
// @todo: Most of this stuff is prepared by data providers within $this->data already
$specialConfiguration = BackendUtility::getSpecConfParts($parameterArray['fieldConf']['defaultExtras']);
// If "richtext" is within defaultExtras
if (isset($specialConfiguration['richtext'])) {
// Operates by reference on $row! 'pid' is changed ...
BackendUtility::fixVersioningPid($table, $row);
list($recordPid, $tsConfigPid) = BackendUtility::getTSCpidCached($table, $row['uid'], $row['pid']);
// If the pid-value is not negative (that is, a pid could NOT be fetched)
if ($tsConfigPid >= 0) {
// Fetch page ts config and do some magic with it to find out if RTE is disabled on TS level.
$rteSetup = $backendUser->getTSConfig('RTE', BackendUtility::getPagesTSconfig($recordPid));
$rteTcaTypeValue = $this->data['recordTypeValue'];
$rteSetupConfiguration = BackendUtility::RTEsetup(
$rteSetup['properties'], $table, $fieldName, $rteTcaTypeValue
);
if (!$rteSetupConfiguration['disabled']) {
// Finally, we're sure the editor should really be rendered ...
return RichTextElement::class;
}
}
}
}
}
return NULL;
}
/**
* @return BackendUserAuthentication
*/
protected function getBackendUserAuthentication() {
return $GLOBALS['BE_USER'];
}
}
......@@ -2,7 +2,7 @@
namespace SGalinski\Tinymce4Rte\Hook;
/**
/*
* This file is part of the TYPO3 CMS project.
*
* It is free software; you can redistribute it and/or modify it under
......@@ -19,8 +19,6 @@ use TYPO3\CMS\Core\Database\SoftReferenceIndex;
/**
* Class for processing of the FAL soft references on img tags inserted in RTE content
*
* @author Stanislas Rolland <stanislas.rolland@typo3.org>
*/
class SoftReferenceHook extends SoftReferenceIndex {
// Token prefix
......@@ -31,13 +29,12 @@ class SoftReferenceHook extends SoftReferenceIndex {
*
* @param string Database table name
* @param string Field name for which processing occurs
* @param integer UID of the record
* @param int UID of the record
* @param string The content/value of the field
* @param string The softlink parser key. This is only interesting if more than one parser is grouped in the same class. That is the case with this parser.
* @param array Parameters of the softlink parser. Basically this is the content inside optional []-brackets after the softref keys. Parameters are exploded by ";
* @param string If running from inside a FlexForm structure, this is the path of the tag.
* @return array Result array on positive matches. Otherwise FALSE
* @todo Define visibility
*/
public function findRef($table, $field, $uid, $content, $spKey, $spParams, $structurePath = '') {
$retVal = FALSE;
......@@ -56,15 +53,14 @@ class SoftReferenceHook extends SoftReferenceIndex {
* Finding image tags with data-htmlarea-file-uid attribute in the content.
* All images that have an data-htmlarea-file-uid attribute will be returned with an info text
*
* @param string The input content to analyse
* @param array Parameters set for the softref parser key in TCA/columns
* @return array Result array on positive matches, see description above. Otherwise FALSE
* @todo Define visibility
* @param string The input content to analyse
* @param array Parameters set for the softref parser key in TCA/columns
* @return array Result array on positive matches, see description above. Otherwise FALSE
*/
public function findRef_rtehtmlarea_images($content, $spParams) {
$retVal = FALSE;
// Start HTML parser and split content by image tag
$htmlParser = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Html\\HtmlParser');
$htmlParser = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Core\Html\HtmlParser::class);
$imgTags = $htmlParser->splitTags('img', $content);
$elements = array();
// Traverse splitted parts
......@@ -73,7 +69,6 @@ class SoftReferenceHook extends SoftReferenceIndex {
// Get FAL uid reference
$attribs = $htmlParser->get_tag_attributes($v);
$fileUid = $attribs[0]['data-htmlarea-file-uid'];
$fileTable = $attribs[0]['data-htmlarea-file-table'];
// If there is a file uid, continue. Otherwise ignore this img tag.
if ($fileUid) {
// Initialize the element entry with info text here
......@@ -81,13 +76,10 @@ class SoftReferenceHook extends SoftReferenceIndex {
$elements[$k] = array();
$elements[$k]['matchString'] = $v;
// Token and substitute value
$imgTags[$k] = str_replace(
'data-htmlarea-file-uid="' . $fileUid . '"',
'data-htmlarea-file-uid="{softref:' . $tokenID . '}"', $imgTags[$k]
);
$imgTags[$k] = str_replace('data-htmlarea-file-uid="' . $fileUid . '"', 'data-htmlarea-file-uid="{softref:' . $tokenID . '}"', $imgTags[$k]);
$elements[$k]['subst'] = array(
'type' => 'db',
'recordRef' => ($fileTable ? : 'sys_file') . ':' . $fileUid,
'recordRef' => 'sys_file:' . $fileUid,
'tokenID' => $tokenID,
'tokenValue' => $fileUid
);
......@@ -95,7 +87,7 @@ class SoftReferenceHook extends SoftReferenceIndex {
}
}
// Assemble result array
if (count($elements)) {
if (!empty($elements)) {
$retVal = array(
'content' => implode('', $imgTags),
'elements' => $elements
......@@ -104,5 +96,3 @@ class SoftReferenceHook extends SoftReferenceIndex {
return $retVal;
}
}
?>
\ No newline at end of file
This diff is collapsed.
<?php
namespace SGalinski\Tinymce4Rte\ImageHandler;
/*
* This file is part of the TYPO3 CMS project.
*
* It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2
* of the License, or any later version.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*
* The TYPO3 project - inspiring people to share!
*/
use Psr\Http\Message\ServerRequestInterface;
use TYPO3\CMS\Core\Page\PageRenderer;
use TYPO3\CMS\Core\Resource\Exception\FileDoesNotExistException;
use TYPO3\CMS\Core\Resource\FileInterface;
use TYPO3\CMS\Core\Resource\ResourceFactory;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Lang\LanguageService;
use TYPO3\CMS\Recordlist\Controller\AbstractLinkBrowserController;
use TYPO3\CMS\Recordlist\LinkHandler\LinkHandlerInterface;
use TYPO3\CMS\Recordlist\Tree\View\LinkParameterProviderInterface;
use SGalinski\Tinymce4Rte\Controller\SelectImageController;
class EditImageHandler implements LinkHandlerInterface, LinkParameterProviderInterface
{
/**
* @var SelectImageController
*/
protected $selectImageController;
/**
* @var FileInterface
*/
protected $currentFile;
/**
* Initialize the handler
*
* @param AbstractLinkBrowserController $linkBrowser
* @param string $identifier
* @param array $configuration Page TSconfig
*
* @return void
*/
public function initialize(AbstractLinkBrowserController $linkBrowser, $identifier, array $configuration)
{
if (!$linkBrowser instanceof SelectImageController) {
throw new \InvalidArgumentException('The given $linkBrowser must be of type SelectImageController."', 1455499721);
}
$this->selectImageController = $linkBrowser;
}
/**
* Checks if this is the handler for the given link
*
* The handler may store this information locally for later usage.
*
* @param array $linkParts Link parts as returned from TypoLinkCodecService
*
* @return bool
*/
public function canHandleLink(array $linkParts)
{
if (!empty($linkParts['currentImage'])) {
try {
$this->currentFile = ResourceFactory::getInstance()->getFileObject($linkParts['currentImage']);
return true;
} catch (FileDoesNotExistException $e) {
}
}
return false;
}
/**
* Format the current link for HTML output
*
* @return string
*/
public function formatCurrentUrl()
{
return $this->currentFile->getStorage()->getName() . ': ' . $this->currentFile->getIdentifier();
}
/**
* Disallow this handler if no image is there to edit
*
* @param array $allowedItems
* @return array
*/
public function modifyAllowedItems($allowedItems, $linkParts)
{
$selfPosition = array_search('image', $allowedItems, true);
if (empty($linkParts['currentImage']) && $selfPosition !== false) {
unset($allowedItems[$selfPosition]);
}
return $allowedItems;
}
/**
* Render the link handler
*
* @param ServerRequestInterface $request
*
* @return string
*/
public function render(ServerRequestInterface $request)
{
GeneralUtility::makeInstance(PageRenderer::class)->loadRequireJsModule('TYPO3/CMS/Tinymce4Rte/EditImage');
$buttonConfig = $this->selectImageController->getButtonConfiguration();
$removedProperties = array();
if (is_array($buttonConfig['properties.'])) {
if ($buttonConfig['properties.']['removeItems']) {
$removedProperties = GeneralUtility::trimExplode(',', $buttonConfig['properties.']['removeItems'], true);
}
}
$rteProperties = $this->selectImageController->getRteProperties();
$lockPlainWidth = false;
$lockPlainHeight = false;
if (isset($rteProperties['default.']['proc.']['plainImageMode'])) {
$plainImageMode = $rteProperties['default.']['proc.']['plainImageMode'];
$lockPlainWidth = $plainImageMode === 'lockDimensions';
$lockPlainHeight = $lockPlainWidth || $plainImageMode === 'lockRatio' || $plainImageMode === 'lockRatioWhenSmaller';
}
$lang = $this->getLanguageService();
$content = '<div><form name="imageData" class="t3js-editForm"><table class="htmlarea-window-table">';
if (!in_array('class', $removedProperties, true) && !empty($buttonConfig['properties.']['class.']['allowedClasses'])) {
$classesImageArray = GeneralUtility::trimExplode(',', $buttonConfig['properties.']['class.']['allowedClasses'], true);
$classesImageJSOptions = '<option value=""></option>';
foreach ($classesImageArray as $class) {
$classesImageJSOptions .= '<option value="' . $class . '">' . $class . '</option>';
}
$content .= '<tr><td><label for="iClass">' . $lang->getLL('class') . ': </label></td><td>
<select id="t3js-iClass" name="iClass" style="width:140px;">' . $classesImageJSOptions . '
</select></td></tr>';
}
if (!in_array('width', $removedProperties, true) && !($this->currentFile && $lockPlainWidth /* && check if it is a RTE magic image (no clue how to do that now with FAL)*/)) {
$content .= '<tr><td><label for="iWidth">' . $lang->getLL('width') . ': </label></td><td>
<input type="text" id="t3js-iWidth" name="iWidth" value="" style="width: 39px;" maxlength="4" /></td></tr>';
}
if (!in_array('height', $removedProperties, true) && !($this->currentFile && $lockPlainHeight /* && check if it is a RTE magic image (no clue how to do that now with FAL)*/)) {
$content .= '<tr><td><label for="iHeight">' . $lang->getLL('height') . ': </label></td><td>
<input type="text" id="t3js-iHeight" name="iHeight" value="" style="width: 39px;" maxlength="4" /></td></tr>';
}
if (!in_array('border', $removedProperties, true)) {
$content .= '<tr><td><label for="iBorder">' . $lang->getLL('border') . ': </label></td><td>
<input type="checkbox" id="t3js-iBorder" name="iBorder" value="1" /></td></tr>';
}
if (!in_array('float', $removedProperties, true)) {
$content .= '<tr><td><label for="iFloat">' . $lang->getLL('float') . ': </label></td><td>
<select id="t3js-iFloat" name="iFloat">'
. '<option value="">' . $lang->getLL('notSet') . '</option>'
. '<option value="none">' . $lang->getLL('nonFloating') . '</option>'
. '<option value="left">' . $lang->getLL('left') . '</option>'
. '<option value="right">' . $lang->getLL('right') . '</option>'
. '</select>
</td></tr>';
}
if (!in_array('paddingTop', $removedProperties, true)) {
$content .= '<tr><td><label for="iPaddingTop">' . $lang->getLL('padding_top') . ': </label></td><td><input type="text" id="t3js-iPaddingTop" name="iPaddingTop" value="" style="width: 39px;" maxlength="4" /></td></tr>';
}
if (!in_array('paddingRight', $removedProperties, true)) {
$content .= '<tr><td><label for="iPaddingRight">' . $lang->getLL('padding_right') . ': </label></td><td><input type="text" id="t3js-iPaddingRight" name="iPaddingRight" value="" style="width: 39px;" maxlength="4" /></td></tr>';
}
if (!in_array('paddingBottom', $removedProperties, true)) {
$content .= '<tr><td><label for="iPaddingBottom">' . $lang->getLL('padding_bottom') . ': </label></td><td><input type="text" id="t3js-iPaddingBottom" name="iPaddingBottom" value="" style="width: 39px;" maxlength="4" /></td></tr>';
}
if (!in_array('paddingLeft', $removedProperties, true)) {
$content .= '<tr><td><label for="iPaddingLeft">' . $lang->getLL('padding_left') . ': </label></td><td><input type="text" id="t3js-iPaddingLeft" name="iPaddingLeft" value="" style="width: 39px;" maxlength="4" /></td></tr>';
}
if (!in_array('title', $removedProperties, true)) {
$content .= '<tr><td><label for="iTitle">' . $lang->getLL('title') . ': </label></td><td><input type="text" id="t3js-iTitle" name="iTitle" style="width:192px;" maxlength="256" /></td></tr>';
}
if (!in_array('alt', $removedProperties, true)) {
$content .= '<tr><td><label for="iAlt">' . $lang->getLL('alt') . ': </label></td><td><input type="text" id="t3js-iAlt" name="iAlt" style="width:192px;" maxlength="256" /></td></tr>';
}
if (!in_array('lang', $removedProperties, true)) {
$content .= '<tr id="t3js-languageSetting"><td><label for="iLang"></label></td><td><select id="t3js-iLang" name="iLang">###lang_selector###</select></td></tr>';
}
if (!in_array('data-htmlarea-clickenlarge', $removedProperties, true) && !in_array('clickenlarge', $removedProperties, true)) {
$content .= '<tr><td><label for="iClickEnlarge">' . $lang->sL('LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:image_zoom') . ': </label></td><td><input type="checkbox" name="iClickEnlarge" id="t3js-iClickEnlarge" value="0" /></td></tr>';
}
$content .= '<tr><td></td><td><input class="btn btn-default" type="submit" value="' . $lang->getLL('update') . '"></td></tr></table></form>';
return $content;
}
/**
* Return TRUE if the handler supports to update a link.
*
* This is useful for file or page links, when only attributes are changed.
*
* @return bool
*/
public function isUpdateSupported()
{
return false;
}
/**
* @return string[] Array of body-tag attributes
*/
public function getBodyTagAttributes()
{
return [
'data-classes-image' => $this->selectImageController->getButtonConfiguration()['properties.']['class.']['allowedClasses'] || $this->selectImageController->getRteProperties()['default.']['classesImage']
];
}
/**
* Returns the URL of the current script
*
* @return string
*/
public function getScriptUrl()
{
return $this->selectImageController->getScriptUrl();
}
/**
* Provides an array or GET parameters for URL generation
*
* @param array $values Array of values to include into the parameters or which might influence the parameters
*
* @return string[] Array of parameters which have to be added to URLs
*/
public function getUrlParameters(array $values)
{
return [];
}
/**
* Check if given value is currently the selected item
*
* This method is only used in the page tree.
*
* @param array $values Values to be checked
*
* @return bool Returns TRUE if the given values match the currently selected item
*/
public function isCurrentlySelectedItem(array $values)
{
return false;
}
/**
* @return array
*/
public function getLinkAttributes()
{
return [];
}
/**
* @param string[] $fieldDefinitions Array of link attribute field definitions
* @return string[]
*/
public function modifyLinkAttributes(array $fieldDefinitions)
{
return $fieldDefinitions;
}
/**
* @return LanguageService
*/
protected function getLanguageService()
{
return $GLOBALS['LANG'];
}
}
<?php
namespace SGalinski\Tinymce4Rte;
/***************************************************************
* Copyright notice
*
* (c) sgalinski Internet Services (http://www.sgalinski.de)
*
* All rights reserved
*
* This script is part of the TYPO3 project. The TYPO3 project is
* free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* The GNU General Public License can be found at
* http://www.gnu.org/copyleft/gpl.html.
*
* This script is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* This copyright notice MUST APPEAR in all copies of the script!
***************************************************************/
/**
* Displays the page/file tree for browsing database records or files.
* Used from TCEFORMS an other elements
* In other words: This is the ELEMENT BROWSER!
*/
use TYPO3\CMS\Core\Utility\GeneralUtility;
/**
* Class which generates the page tree
*/
class PageTree extends \localPageTree {
/**
* Create the page navigation tree in HTML
*
* @param array Tree array
* @return string HTML output.
* @todo Define visibility
*/
public function printTree($treeArr = '') {
$titleLen = (int) $GLOBALS['BE_USER']->uc['titleLen'];
if (!is_array($treeArr)) {
$treeArr = $this->tree;
}
$out = '';
$c = 0;
foreach ($treeArr as $k => $v) {
$c++;
$bgColorClass = ($c + 1) % 2 ? 'bgColor' : 'bgColor-10';
if ($GLOBALS['SOBE']->browser->curUrlInfo['act'] == 'page' && $GLOBALS['SOBE']->browser->curUrlInfo['pageid'] == $v['row']['uid'] && $GLOBALS['SOBE']->browser->curUrlInfo['pageid']) {
$arrCol = '<td><img' . \TYPO3\CMS\Backend\Utility\IconUtility::skinImg(
$GLOBALS['BACK_PATH'], 'gfx/blinkarrow_right.gif', 'width="5" height="9"'
) . ' class="c-blinkArrowR" alt="" /></td>';
$bgColorClass = 'bgColor4';
} else {
$arrCol = '<td></td>';
}
$aOnClick = 'return jumpToUrl(' . GeneralUtility::quoteJSvalue(
$this->getThisScript(
) . 'act=' . $GLOBALS['SOBE']->browser->act . '&editorNo=' . $GLOBALS['SOBE']->browser->editorNo . '&contentTypo3Language=' . $GLOBALS['SOBE']->browser->contentTypo3Language . '&mode=' . $GLOBALS['SOBE']->browser->mode . '&expandPage=' . $v['row']['uid']
) . ');';
$cEbullet = $this->ext_isLinkable(
$v['row']['doktype'], $v['row']['uid']
) ? '<a href="#" onclick="' . htmlspecialchars(
$aOnClick
) . '"><img' . \TYPO3\CMS\Backend\Utility\IconUtility::skinImg(
$GLOBALS['BACK_PATH'], 'gfx/ol/arrowbullet.gif', 'width="18" height="16"'
) . ' alt="" /></a>' : '';
$out .= '
<tr class="' . $bgColorClass . '">
<td nowrap="nowrap"' . ($v['row']['_CSSCLASS'] ? ' class="' . $v['row']['_CSSCLASS'] . '"' : '') . '>' . $v['HTML'] . $this->wrapTitle(
$this->getTitleStr($v['row'], $titleLen), $v['row'], $this->ext_pArrPages
) . '</td>' . $arrCol . '<td>' . $cEbullet . '</td>
</tr>';
}
$out = '
<!--
Navigation Page Tree:
-->
<table border="0" cellpadding="0" cellspacing="0" id="typo3-tree">
' . $out . '
</table>';
return $out;
}
}
This diff is collapsed.
This diff is collapsed.
<?php
namespace SGalinski\Tinymce4Rte\Service;
/***************************************************************
* Copyright notice
*
* (c) sgalinski Internet Services (https://www.sgalinski.de)
*
* All rights reserved
*
* This script is part of the TYPO3 project. The TYPO3 project is
* free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* The GNU General Public License can be found at
* http://www.gnu.org/copyleft/gpl.html.
*
* This script is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* This copyright notice MUST APPEAR in all copies of the script!
***************************************************************/
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
use TYPO3\CMS\Core\Utility\GeneralUtility;
/**
* Class SGalinski\SgRoutes\Service\LicensingService
*/
class LicensingService {
/**
* Licensing Service Url
*/
const URL = 'https://www.sgalinski.de/?eID=sgLicensing';
/**
* The key name of the uc array inside of the backend user.
*/
const BACKEND_USER_UC_KEY = 'tinymce4_rte_pinged';
/**
* Licensing Service Url
*/
const EXTENSION_KEY = 'tinymce4_rte';
/** @var bool|NULL */
private static $isLicenseKeyValid;
/**
* @return boolean
*/
public static function checkKey(): bool {
if (static::$isLicenseKeyValid === NULL) {
static::$isLicenseKeyValid = FALSE;
$configuration = unserialize($GLOBALS['TYPO3_CONF_VARS']['EXT']['extConf'][self::EXTENSION_KEY], [FALSE]);
if (isset($configuration['key']) && $key = trim($configuration['key'])) {
static::$isLicenseKeyValid = (bool) preg_match('/^([A-Z\d]{6}-?){4}$/', $key);
}
}
return static::$isLicenseKeyValid;
}
/**
* Licensing Service ping
*
* @param boolean $returnUrl
* @return string
*/
public static function ping($returnUrl = FALSE): string {
try {
$configuration = unserialize($GLOBALS['TYPO3_CONF_VARS']['EXT']['extConf'][self::EXTENSION_KEY], [FALSE]);
$key = '';
if (isset($configuration['key'])) {
$key = trim($configuration['key']);
}
$params = [
'extension' => self::EXTENSION_KEY,
'host' => GeneralUtility::getIndpEnv('HTTP_HOST'),
// @todo Enable this, when inserting a licensing.
//'key' => $key
];
$params = http_build_query($params);
$pingUrl = self::URL;
$pingUrl .= $params !== '' ? (strpos($pingUrl, '?') === FALSE ? '?' : '&') . $params : '';
if ($returnUrl) {
return $pingUrl;
}
GeneralUtility::getUrl($pingUrl);
} catch (\Exception $exception) {
}
return '';
}
/**
* Generates a random password string based on the configured password policies.
*
* @param ServerRequestInterface $request
* @param ResponseInterface $response
* @return ResponseInterface
* @throws \InvalidArgumentException
*/
public function ajaxPing(ServerRequestInterface $request, ResponseInterface $response): ResponseInterface {
/** @var BackendUserAuthentication $backendUser */
$backendUser = $GLOBALS['BE_USER'];
$backendUserUC = $backendUser->uc;
if ($backendUser && !isset($backendUserUC[self::BACKEND_USER_UC_KEY])) {
$backendUserUC[self::BACKEND_USER_UC_KEY] = TRUE;
$backendUser->writeUC($backendUserUC);
self::ping();
}
return $response;
}
}
<?php
namespace SGalinski\Tinymce4Rte\Utility;
/***************************************************************
* Copyright notice
*
* (c) sgalinski Internet Services (https://www.sgalinski.de)
*
* All rights reserved
*
* This script is part of the TYPO3 project. The TYPO3 project is
* free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* The GNU General Public License can be found at
* http://www.gnu.org/copyleft/gpl.html.
*
* This script is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* This copyright notice MUST APPEAR in all copies of the script!
***************************************************************/
use TYPO3\CMS\Core\Utility\VersionNumberUtility;
/**
* Helper class to detect the used TYPO3 version.
*/
class VersionUtility {
/**
* Returns true if the current version ts TYPO3 6.2.
*
* @return bool
*/
public static function isVersion62() {
$versionNumber = self::getVersion();
return ($versionNumber >= 6002000 && $versionNumber < 7000000);
}
/**
* Returns true if the current version ts TYPO3 7.6 and less version 8
*
* @return bool
*/
public static function isVersion76() {
$versionNumber = self::getVersion();
return ($versionNumber >= 7006000 && $versionNumber < 8000000);
}
/**
* Returns true if the current version ts TYPO3 7.6 or later
*
* @return bool
*/
public static function isVersion76OOrHigher() {
return (self::getVersion() >= 7006000);
}
/**
* Returns true if the current version ts TYPO3 8.7 or later
*
* @return bool
*/
public static function isVersion870OrHigher() {
return (self::getVersion() >= 8007000);
}
/**
* Returns the current version as an integer.
*
* @return int
*/
protected static function getVersion() {
return VersionNumberUtility::convertVersionNumberToInteger(
VersionNumberUtility::getNumericTypo3Version()
);
}
}
This diff is collapsed.
This diff is collapsed.