*/ class ElementBrowser { /** * Optional instance of a record list that TBE_expandPage() should * use to render the records in a page * * @var ElementBrowserRecordList */ protected $recordList = NULL; /** * Current site URL (Frontend) * * @var string * @internal */ public $siteURL; /** * the script to link to * * @var string */ public $thisScript; /** * RTE specific TSconfig * * @var array[] */ public $thisConfig; /** * Target (RTE specific) * * @var string */ public $setTarget; /** * CSS Class (RTE specific) * * @var string */ public $setClass; /** * title (RTE specific) * * @var string */ public $setTitle; /** * @var string */ public $setParams; /** * Backend template object * * @var DocumentTemplate */ public $doc; /** * Holds information about files * * @var mixed[][] */ public $elements = array(); /** * The mode determines the main kind of output from the element browser. * There are these options for values: rte, db, file, filedrag, wizard. * "rte" will show the link selector for the Rich Text Editor (see main_rte()) * "db" will allow you to browse for pages or records in the page tree (for TCEforms, see main_db()) * "file"/"filedrag" will allow you to browse for files or folders in the folder mounts (for TCEforms, main_file()) * "wizard" will allow you to browse for links (like "rte") which are passed back to TCEforms (see main_rte(1)) * * @see main() * @var string */ public $mode; /** * Link selector action. * page,file,url,mail,spec are allowed values. * These are only important with the link selector function and in that case they switch * between the various menu options. * * @var string */ public $act; /** * When you click a page title/expand icon to see the content of a certain page, this * value will contain that value (the ID of the expanded page). If the value is NOT set, * then it will be restored from the module session data (see main(), mode="db") * * @var NULL|int */ public $expandPage; /** * When you click a folder name/expand icon to see the content of a certain file folder, * this value will contain that value (the path of the expanded file folder). If the * value is NOT set, then it will be restored from the module session data (see main(), * mode="file"/"filedrag"). Example value: "/www/htdocs/typo3/32/3dsplm/fileadmin/css/" * * @var string */ public $expandFolder; /** * the folder object of a parent folder that was selected * * @var Folder */ protected $selectedFolder; /** * TYPO3 Element Browser, wizard mode parameters. There is a heap of parameters there, * better debug() them out if you need something... :-) * * @var array[] */ public $P; /** * 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:contentTypo3Charset * 2: RTE config parameters: RTEtsConfigParams * 3: allowed types. Eg. "tt_content" or "gif,jpg,jpeg,tif,bmp,pcx,tga,png,pdf,ai" * 4: IRRE uniqueness: target level object-id to perform actions/checks on, eg. "data[79][tt_address][1][][]" * 5: IRRE uniqueness: name of function in opener window that checks if element is already used, eg. "inline.checkUniqueElement" * 6: IRRE uniqueness: name of function in opener window that performs some additional(!) action, eg. "inline.setUniqueElement" * 7: IRRE uniqueness: name of function in opener window that performs action instead of using addElement/insertElement, eg. "inline.importElement" * * $pArr = explode('|', $this->bparams); * $formFieldName = $pArr[0]; * $allowedTablesOrFileTypes = $pArr[3]; * * @var string */ public $bparams; /** * Used with the Rich Text Editor. * Example value: "tt_content:NEW3fba58c969f5c:bodytext:23:text:23:" * * @var string */ public $RTEtsConfigParams; /** * Plus/Minus icon value. Used by the tree class to open/close notes on the trees. * * @var string */ public $PM; /** * Pointer, used when browsing a long list of records etc. * * @var int */ public $pointer; /** * Used with the link selector: Contains the GET input information about the CURRENT link * in the RTE/TCEform field. This consists of "href", "target" and "title" keys. * This information is passed around in links. * * @var array[] */ public $curUrlArray; /** * Used with the link selector: Contains a processed version of the input values from curUrlInfo. * This is splitted into pageid, content element id, label value etc. * This is used for the internal processing of that information. * * @var array[] */ public $curUrlInfo; /** * array which holds hook objects (initialised in init()) * * @var ElementBrowserHookInterface[] */ protected $hookObjects = array(); /** * @var BasicFileUtility */ public $fileProcessor; /** * Sets the script url depending on being a module or script request */ protected function determineScriptUrl() { if ($moduleName = GeneralUtility::_GP('M')) { $this->thisScript = BackendUtility::getModuleUrl($moduleName); } else { $this->thisScript = GeneralUtility::getIndpEnv('SCRIPT_NAME'); } } /** * Calculate path to this script. * This method is public, to be used in hooks of this class only. * * @return string */ public function getThisScript() { return strpos($this->thisScript, '?') === FALSE ? $this->thisScript . '?' : $this->thisScript . '&'; } /** * Constructor: * Initializes a lot of variables, setting JavaScript functions in header etc. * * @return void * @throws \UnexpectedValueException */ public function init() { $this->initVariables(); $this->RTEtsConfigParams = GeneralUtility::_GP('RTEtsConfigParams'); $this->initConfiguration(); $this->initDocumentTemplate(); // init hook objects: $this->initHookObjects('typo3/class.browse_links.php'); $this->initCurrentUrl(); // Determine nature of current url: $this->act = GeneralUtility::_GP('act'); if (!$this->act) { $this->act = $this->curUrlInfo['act']; } // Initializing the target value (RTE) $this->setTarget = $this->curUrlArray['target'] != '-' ? $this->curUrlArray['target'] : ''; if ($this->thisConfig['defaultLinkTarget'] && !isset($this->curUrlArray['target'])) { $this->setTarget = $this->thisConfig['defaultLinkTarget']; } // Initializing the class value (RTE) $this->setClass = $this->curUrlArray['class'] != '-' ? $this->curUrlArray['class'] : ''; // Initializing the title value (RTE) $this->setTitle = $this->curUrlArray['title'] != '-' ? $this->curUrlArray['title'] : ''; // Initializing the params value $this->setParams = $this->curUrlArray['params'] != '-' ? $this->curUrlArray['params'] : ''; // Finally, add the accumulated JavaScript to the template object: // also unset the default jumpToUrl() function before unset($this->doc->JScodeArray['jumpToUrl']); $this->doc->JScode .= $this->doc->wrapScriptTags($this->getJSCode()); } /** * Initialize class variables * * @return void */ public function initVariables() { // Main GPvars: $this->pointer = GeneralUtility::_GP('pointer'); $this->bparams = GeneralUtility::_GP('bparams'); $this->P = GeneralUtility::_GP('P'); $this->expandPage = GeneralUtility::_GP('expandPage'); $this->expandFolder = GeneralUtility::_GP('expandFolder'); $this->PM = GeneralUtility::_GP('PM'); // Site URL // Current site url $this->siteURL = GeneralUtility::getIndpEnv('TYPO3_SITE_URL'); $this->determineScriptUrl(); // Find "mode" $this->mode = GeneralUtility::_GP('mode'); if (!$this->mode) { $this->mode = 'rte'; } // Init fileProcessor $this->fileProcessor = GeneralUtility::makeInstance(BasicFileUtility::class); $this->fileProcessor->init(array(), $GLOBALS['TYPO3_CONF_VARS']['BE']['fileExtensions']); } /** * Initializes the configuration variables * * @return void */ public function initConfiguration() { // Rich Text Editor specific configuration: if ((string)$this->mode === 'rte') { $this->thisConfig = $this->getRTEConfig(); } } /** * Initialize document template object * * @return void */ protected function initDocumentTemplate() { // Creating backend template object: $this->doc = GeneralUtility::makeInstance(DocumentTemplate::class); $this->doc->bodyTagId = 'typo3-browse-links-php'; $this->doc->backPath = $GLOBALS['BACK_PATH']; $this->doc->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Backend/BrowseLinks'); $this->doc->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Backend/LegacyTree'); } /** * Initialize hook objects implementing the interface * * @param string $hookKey the hook key * @throws \UnexpectedValueException * @return void */ protected function initHookObjects($hookKey) { if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS'][$hookKey]['browseLinksHook'])) { foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS'][$hookKey]['browseLinksHook'] as $classData) { $processObject = GeneralUtility::getUserObj($classData); if (!$processObject instanceof ElementBrowserHookInterface) { throw new \UnexpectedValueException('$processObject must implement interface ' . ElementBrowserHookInterface::class, 1195039394); } $parameters = array(); $processObject->init($this, $parameters); $this->hookObjects[] = $processObject; } } } /** * 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 if ($this->mode == 'wizard') { $currentValues = GeneralUtility::trimExplode(LF, trim($this->P['currentValue'])); if (count($currentValues) > 0) { $currentValue = array_pop($currentValues); } else { $currentValue = ''; } $currentLinkParts = GeneralUtility::unQuoteFilenames($currentValue, TRUE); $initialCurUrlArray = array( 'href' => $currentLinkParts[0], 'target' => $currentLinkParts[1], 'class' => $currentLinkParts[2], 'title' => $currentLinkParts[3], 'params' => $currentLinkParts[4] ); $this->curUrlArray = is_array(GeneralUtility::_GP('curUrl')) ? array_merge($initialCurUrlArray, GeneralUtility::_GP('curUrl')) : $initialCurUrlArray; // Additional fields for page links if (isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/class.browse_links.php']['extendUrlArray']) && is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/class.browse_links.php']['extendUrlArray']) ) { $conf = array(); $_params = array( 'conf' => &$conf, 'linkParts' => $currentLinkParts ); foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/class.browse_links.php']['extendUrlArray'] as $objRef) { $processor =& GeneralUtility::getUserObj($objRef); $processor->extendUrlArray($_params, $this); } } $this->curUrlInfo = $this->parseCurUrl($this->siteURL . '?id=' . $this->curUrlArray['href'], $this->siteURL); // pageid == 0 means that this is not an internal (page) link if ($this->curUrlInfo['pageid'] == 0 && $this->curUrlArray['href']) { // Check if there is the FAL API if (GeneralUtility::isFirstPartOfStr($this->curUrlArray['href'], 'file:')) { $this->curUrlInfo = $this->parseCurUrl($this->curUrlArray['href'], $this->siteURL); // Remove the "file:" prefix $currentLinkParts[0] = rawurldecode(substr($this->curUrlArray['href'], 5)); } elseif (file_exists(PATH_site . rawurldecode($this->curUrlArray['href']))) { if (GeneralUtility::isFirstPartOfStr($this->curUrlArray['href'], PATH_site)) { $currentLinkParts[0] = PathUtility::stripPathSitePrefix($this->curUrlArray['href']); } $this->curUrlInfo = $this->parseCurUrl($this->siteURL . $this->curUrlArray['href'], $this->siteURL); } elseif (strstr($this->curUrlArray['href'], '@')) { // check for email link if (GeneralUtility::isFirstPartOfStr($this->curUrlArray['href'], 'mailto:')) { $currentLinkParts[0] = substr($this->curUrlArray['href'], 7); } $this->curUrlInfo = $this->parseCurUrl('mailto:' . $this->curUrlArray['href'], $this->siteURL); } else { // nothing of the above. this is an external link if (strpos($this->curUrlArray['href'], '://') === FALSE) { $currentLinkParts[0] = 'http://' . $this->curUrlArray['href']; } $this->curUrlInfo = $this->parseCurUrl($currentLinkParts[0], $this->siteURL); } } elseif (!$this->curUrlArray['href']) { $this->curUrlInfo = array(); $this->act = 'page'; } else { $this->curUrlInfo = $this->parseCurUrl($this->siteURL . '?id=' . $this->curUrlArray['href'], $this->siteURL); } } else { $this->curUrlArray = GeneralUtility::_GP('curUrl'); if ($this->curUrlArray['all']) { $this->curUrlArray = GeneralUtility::get_tag_attributes($this->curUrlArray['all']); } $this->curUrlInfo = $this->parseCurUrl($this->curUrlArray['href'], $this->siteURL); } } /** * Get the RTE configuration from Page TSConfig * * @return array[] RTE configuration array */ protected function getRTEConfig() { $RTEtsConfigParts = explode(':', $this->RTEtsConfigParams); $RTEsetup = $this->getBackendUserAuthentication()->getTSConfig('RTE', BackendUtility::getPagesTSconfig($RTEtsConfigParts[5])); return BackendUtility::RTEsetup($RTEsetup['properties'], $RTEtsConfigParts[0], $RTEtsConfigParts[2], $RTEtsConfigParts[4]); } /** * Generate JS code to be used on the link insert/modify dialogue * * @return string the generated JS code */ public function getJsCode() { // Rich Text Editor specific configuration: $addPassOnParams = ''; if ((string)$this->mode == 'rte') { $addPassOnParams .= '&RTEtsConfigParams=' . rawurlencode($this->RTEtsConfigParams); } // BEGIN accumulation of header JavaScript: $JScode = ' // This JavaScript is primarily for RTE/Link. jumpToUrl is used in the other cases as well... 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 cur_href=' . GeneralUtility::quoteJSvalue($this->curUrlArray['href'] ?: '') . '; var cur_target=' . GeneralUtility::quoteJSvalue($this->setTarget ?: '') . '; var cur_class=' . GeneralUtility::quoteJSvalue($this->setClass ?: '') . '; var cur_title=' . GeneralUtility::quoteJSvalue($this->setTitle ?: '') . '; var cur_params=' . GeneralUtility::quoteJSvalue($this->setParams ?: '') . '; function browse_links_setTarget(target) { // cur_target=target; add_target="&curUrl[target]="+escape(target); } function browse_links_setClass(cssClass) { // cur_class = cssClass; add_class = "&curUrl[class]=" + escape(cssClass); } function browse_links_setTitle(title) { // cur_title=title; add_title="&curUrl[title]="+escape(title); } function browse_links_setValue(value) { // cur_href=value; add_href="&curUrl[href]="+value; } function browse_links_setParams(params) { // cur_params=params; add_params="&curUrl[params]="+escape(params); } ' . $this->doc->redirectUrls(); // Functions used, if the link selector is in wizard mode (= TCEforms fields) if ($this->mode == 'wizard') { if (!$this->areFieldChangeFunctionsValid() && !$this->areFieldChangeFunctionsValid(TRUE)) { $this->P['fieldChangeFunc'] = array(); } unset($this->P['fieldChangeFunc']['alert']); $update = ''; foreach ($this->P['fieldChangeFunc'] as $v) { $update .= ' window.opener.' . $v; } $P2 = array(); $P2['uid'] = $this->P['uid']; $P2['pid'] = $this->P['pid']; $P2['itemName'] = $this->P['itemName']; $P2['formName'] = $this->P['formName']; $P2['fieldChangeFunc'] = $this->P['fieldChangeFunc']; $P2['fieldChangeFuncHash'] = GeneralUtility::hmac(serialize($this->P['fieldChangeFunc'])); $P2['params']['allowedExtensions'] = isset($this->P['params']['allowedExtensions']) ? $this->P['params']['allowedExtensions'] : ''; $P2['params']['blindLinkOptions'] = isset($this->P['params']['blindLinkOptions']) ? $this->P['params']['blindLinkOptions'] : ''; $P2['params']['blindLinkFields'] = isset($this->P['params']['blindLinkFields']) ? $this->P['params']['blindLinkFields']: ''; $addPassOnParams .= GeneralUtility::implodeArrayForUrl('P', $P2); $JScode .= ' function link_typo3Page(id,anchor) { // updateValueInMainForm(id + (anchor ? anchor : "")); close(); return false; } function link_folder(folder) { // updateValueInMainForm(folder); close(); return false; } function link_current() { // if (cur_href!="http://" && cur_href!="mailto:") { returnBeforeCleaned = cur_href; if (returnBeforeCleaned.substr(0, 7) == "http://") { returnToMainFormValue = returnBeforeCleaned.substr(7); } else if (returnBeforeCleaned.substr(0, 7) == "mailto:") { if (returnBeforeCleaned.substr(0, 14) == "mailto:mailto:") { returnToMainFormValue = returnBeforeCleaned.substr(14); } else { returnToMainFormValue = returnBeforeCleaned.substr(7); } } else { returnToMainFormValue = returnBeforeCleaned; } updateValueInMainForm(returnToMainFormValue); close(); } return false; } function checkReference() { // if (window.opener && window.opener.document && window.opener.document.' . $this->P['formName'] . ' && window.opener.document.' . $this->P['formName'] . '["' . $this->P['itemName'] . '"] ) { return window.opener.document.' . $this->P['formName'] . '["' . $this->P['itemName'] . '"]; } else { close(); } } function updateValueInMainForm(input) { // var field = checkReference(); if (field) { if (cur_target == "" && (cur_class != "" || cur_title != "" || cur_params != "")) { cur_target = "-"; } if (cur_class == "" && (cur_title != "" || cur_params != "")) { cur_class = "-"; } cur_class = cur_class.replace(/[\'\\"]/g, ""); if (cur_class.indexOf(" ") != -1) { cur_class = "\\"" + cur_class + "\\""; } if (cur_title == "" && cur_params != "") { cur_title = "-"; } cur_title = cur_title.replace(/(^\\")|(\\"$)/g, ""); if (cur_title.indexOf(" ") != -1) { cur_title = "\\"" + cur_title + "\\""; } if (cur_params) { cur_params = cur_params.replace(/\\bid\\=.*?(\\&|$)/, ""); } input = input + " " + cur_target + " " + cur_class + " " + cur_title + " " + cur_params; input = input.replace(/^\s+|\s+$/g, ""); if(field.value && field.className.search(/textarea/) != -1) { field.value += "\\n" + input; } else { field.value = input; } field.onchange(); ' . $update . ' } } '; } else { // Functions used, if the link selector is in RTE mode: $JScode .= ' function link_typo3Page(id,anchor) { // var theLink = \'' . $this->siteURL . '?id=\'+id+(anchor?anchor:""); self.parent.parent.renderPopup_addLink(theLink, cur_target, cur_class, cur_title); return false; } function link_folder(folder) { // var theLink = \'' . $this->siteURL . '\'+folder; self.parent.parent.renderPopup_addLink(theLink, cur_target, cur_class, cur_title); return false; } function link_spec(theLink) { // self.parent.parent.renderPopup_addLink(theLink, cur_target, cur_class, cur_title); return false; } function link_current() { // if (cur_href!="http://" && cur_href!="mailto:") { self.parent.parent.renderPopup_addLink(cur_href, cur_target, cur_class, cur_title); } return false; } '; } // General "jumpToUrl" function: $JScode .= ' function jumpToUrl(URL,anchor) { // if (URL.charAt(0) === \'?\') { URL = ' . GeneralUtility::quoteJSvalue($this->getThisScript()) . ' + URL.substring(1); } var add_act = URL.indexOf("act=")==-1 ? "&act=' . $this->act . '" : ""; var add_mode = URL.indexOf("mode=")==-1 ? "&mode=' . $this->mode . '" : ""; var theLocation = URL + add_act + add_mode + add_href + add_target + add_class + add_title + add_params' . ($addPassOnParams ? '+' . GeneralUtility::quoteJSvalue($addPassOnParams) : '') . '+(typeof(anchor)=="string"?anchor:""); window.location.href = theLocation; return false; } '; /** * Splits parts of $this->bparams * * @see $bparams */ $pArr = explode('|', $this->bparams); // This is JavaScript especially for the TBE Element Browser! $formFieldName = 'data[' . $pArr[0] . '][' . $pArr[1] . '][' . $pArr[2] . ']'; // insertElement - Call check function (e.g. for uniqueness handling): $JScodeCheck = ''; if ($pArr[4] && $pArr[5]) { $JScodeCheck = ' // Call a check function in the opener window (e.g. for uniqueness handling): if (parent.window.opener) { var res = parent.window.opener.' . $pArr[5] . '("' . addslashes($pArr[4]) . '",table,uid,type); if (!res.passed) { if (res.message) alert(res.message); performAction = false; } } else { alert("Error - reference to main window is not set properly!"); parent.close(); } '; } // insertElement - Call helper function: $JScodeHelper = ''; if ($pArr[4] && $pArr[6]) { $JScodeHelper = ' // Call helper function to manage data in the opener window: if (parent.window.opener) { parent.window.opener.' . $pArr[6] . '("' . addslashes($pArr[4]) . '",table,uid,type,"' . addslashes($pArr[0]) . '"); } else { alert("Error - reference to main window is not set properly!"); parent.close(); } '; } // insertElement - perform action commands: $JScodeActionMultiple = ''; if ($pArr[4] && $pArr[7]) { // Call user defined action function: $JScodeAction = ' if (parent.window.opener) { parent.window.opener.' . $pArr[7] . '("' . addslashes($pArr[4]) . '",table,uid,type); if (close) { focusOpenerAndClose(close); } } else { alert("Error - reference to main window is not set properly!"); if (close) { parent.close(); } } '; $JScodeActionMultiple = ' // Call helper function to manage data in the opener window: if (parent.window.opener) { parent.window.opener.' . $pArr[7] . 'Multiple("' . addslashes($pArr[4]) . '",table,uid,type,"' . addslashes($pArr[0]) . '"); } else { alert("Error - reference to main window is not set properly!"); parent.close(); } '; } elseif ($pArr[0] && !$pArr[1] && !$pArr[2]) { $JScodeAction = ' addElement(filename,table+"_"+uid,fp,close); '; } else { $JScodeAction = ' if (setReferences()) { parent.window.opener.group_change("add","' . $pArr[0] . '","' . $pArr[1] . '","' . $pArr[2] . '",elRef,targetDoc); } else { alert("Error - reference to main window is not set properly!"); } focusOpenerAndClose(close); '; } $JScode .= ' var elRef=""; var targetDoc=""; 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(); } } function setReferences() { // if (parent.window.opener && parent.window.opener.content && parent.window.opener.content.document.editform' . '&& parent.window.opener.content.document.editform["' . $formFieldName . '"]) { targetDoc = parent.window.opener.content.document; elRef = targetDoc.editform["' . $formFieldName . '"]; return true; } else { return false; } } function insertElement(table, uid, type, filename, fp, filetype, imagefile, action, close) { // var performAction = true; ' . $JScodeCheck . ' // Call performing function and finish this action: if (performAction) { ' . $JScodeHelper . $JScodeAction . ' } return false; } function insertMultiple(table, uid) { var type = ""; ' . $JScodeActionMultiple . ' return false; } function addElement(elName, elValue, altElValue, close) { // if (parent.window.opener && parent.window.opener.setFormValueFromBrowseWin) { parent.window.opener.setFormValueFromBrowseWin("' . $pArr[0] . '",altElValue?altElValue:elValue,elName); focusOpenerAndClose(close); } else { alert("Error - reference to main window is not set properly!"); parent.close(); } } function focusOpenerAndClose(close) { // BrowseLinks.focusOpenerAndClose(close); } '; // extends JavaScript code if (isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/class.browse_links.php']['extendJScode']) && is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/class.browse_links.php']['extendJScode']) ) { $conf = array(); $update = ''; $_params = array( 'conf' => &$conf, 'wizardUpdate' => $update, 'addPassOnParams' => $addPassOnParams ); foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/class.browse_links.php']['extendJScode'] as $objRef) { $processor =& GeneralUtility::getUserObj($objRef); $JScode .= $processor->extendJScode($_params, $this); } } return $JScode; } /** * Session data for this class can be set from outside with this method. * Call after init() * * @param mixed[] $data Session data array * @return array[] Session data and boolean which indicates that data needs to be stored in session because it's changed */ public function processSessionData($data) { $store = FALSE; switch ((string)$this->mode) { case 'db': if (isset($this->expandPage)) { $data['expandPage'] = $this->expandPage; $store = TRUE; } else { $this->expandPage = $data['expandPage']; } break; case 'file': case 'filedrag': case 'folder': if (isset($this->expandFolder)) { $data['expandFolder'] = $this->expandFolder; $store = TRUE; } else { $this->expandFolder = $data['expandFolder']; } break; } return array($data, $store); } /****************************************************************** * * 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 bool $wiz 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. */ public function main_rte($wiz = FALSE) { // Starting content: $content = $this->doc->startPage('RTE link'); $allowedItems = $this->getAllowedItems('page,file,folder,url,mail,spec'); // Removing link fields if configured $blindLinkFields = isset($this->thisConfig['blindLinkFields']) ? GeneralUtility::trimExplode(',', $this->thisConfig['blindLinkFields'], TRUE) : array(); $pBlindLinkFields = isset($this->P['params']['blindLinkFields']) ? GeneralUtility::trimExplode(',', $this->P['params']['blindLinkFields'], TRUE) : array(); $allowedFields = array_diff(array('target', 'title', 'class', 'params'), $blindLinkFields, $pBlindLinkFields); $content .= $this->doc->getTabMenuRaw($this->buildMenuArray($wiz, $allowedItems)); // Adding the menu and header to the top of page: $content .= $this->printCurrentUrl($this->curUrlInfo['info']) . '
'; // Depending on the current action we will create the actual module content for selecting a link: switch ($this->act) { case 'mail': $content .= $this->getEmailSelectorHtml(); break; case 'url': $content .= $this->getExternalUrlSelectorHtml(); break; case 'file': case 'folder': $content .= $this->getFileSelectorHtml(); break; case 'spec': $content .= $this->getUserLinkSelectorHtml(); break; case 'page': $content .= $this->getPageSelectorHtml(); break; default: // Call hook foreach ($this->hookObjects as $hookObject) { $content .= $hookObject->getTab($this->act); } } $lang = $this->getLanguageService(); if (in_array('params', $allowedFields, TRUE)) { $content .= '
' . $lang->getLL('params', TRUE) . '
'; } if (in_array('class', $allowedFields, TRUE)) { $content .= '
' . $lang->getLL('class', TRUE) . '
'; } if (in_array('title', $allowedFields, TRUE)) { $content .= '
' . $lang->getLL('title', TRUE) . '
'; } // additional fields for page links if (isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/class.browse_links.php']['addFields_PageLink']) && is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/class.browse_links.php']['addFields_PageLink']) ) { $conf = array(); $_params = array( 'conf' => &$conf ); foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/class.browse_links.php']['addFields_PageLink'] as $objRef) { $processor =& GeneralUtility::getUserObj($objRef); $content .= $processor->addFields($_params, $this); } } // Target: if ($this->act != 'mail' && in_array('target', $allowedFields, TRUE)) { $ltarget = '
' . $lang->getLL('target', TRUE) . ': doc->formWidth(10) . ' /> '; if (($this->curUrlInfo['act'] == 'page' || $this->curUrlInfo['act'] == 'file' || $this->curUrlInfo['act'] == 'folder') && $this->curUrlArray['href'] && $this->curUrlInfo['act'] == $this->act ) { $ltarget .= ' '; } $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.ltargetformbrowse_links_setTarget.popup_height.options[' . 'document.ltargetform.popup_height.selectedIndex].value; browse_links_setTarget(document.ltargetform.ltarget.value); browse_links_setClass(document.lclassform.lclass.value); browse_links_setTitle(document.ltitleform.ltitle.value); browse_links_setParams(document.lparamsform.lparams.value); document.ltargetform.popup_width.selectedIndex=0; document.ltargetform.popup_height.selectedIndex=0; } '; $ltarget .= '
' . $lang->getLL('target_popUpWindow', TRUE) . ': x
'; // Add "target selector" box to content: $content .= $ltarget; // Add some space $content .= '

'; } // End page, return content: $content .= $this->doc->endPage(); $content = $this->doc->insertStylesAndJS($content); return $content; } /** * Get the allowed items or tabs * * @param string $items initial list of possible items * @return array the allowed items */ public function getAllowedItems($items) { // Initializing the action value, possibly removing blinded values etc: $blindLinkOptions = isset($this->thisConfig['blindLinkOptions']) ? GeneralUtility::trimExplode(',', $this->thisConfig['blindLinkOptions'], TRUE) : array(); $pBlindLinkOptions = isset($this->P['params']['blindLinkOptions']) ? GeneralUtility::trimExplode(',', $this->P['params']['blindLinkOptions']) : array(); $allowedItems = array_diff(explode(',', $items), $blindLinkOptions, $pBlindLinkOptions); // Call hook for extra options foreach ($this->hookObjects as $hookObject) { $allowedItems = $hookObject->addAllowedItems($allowedItems); } return $allowedItems; } /** * Returns an array definition of the top menu * * @param $wiz * @param $allowedItems * @return mixed[][] */ protected function buildMenuArray($wiz, $allowedItems) { // Making menu in top: $menuDef = array(); $lang = $this->getLanguageService(); if (!$wiz) { $menuDef['removeLink']['isActive'] = $this->act === 'removeLink'; $menuDef['removeLink']['label'] = $lang->getLL('removeLink', TRUE); $menuDef['removeLink']['url'] = '#'; $menuDef['removeLink']['addParams'] = 'onclick="self.parent.parent.renderPopup_unLink();return false;"'; } if (in_array('page', $allowedItems)) { $menuDef['page']['isActive'] = $this->act === 'page'; $menuDef['page']['label'] = $lang->getLL('page', TRUE); $menuDef['page']['url'] = '#'; $menuDef['page']['addParams'] = 'onclick="jumpToUrl(' . GeneralUtility::quoteJSvalue('?act=page') . ');return false;"'; } if (in_array('file', $allowedItems)) { $menuDef['file']['isActive'] = $this->act === 'file'; $menuDef['file']['label'] = $lang->getLL('file', TRUE); $menuDef['file']['url'] = '#'; $menuDef['file']['addParams'] = 'onclick="jumpToUrl(' . GeneralUtility::quoteJSvalue('?act=file') . ');return false;"'; } if (in_array('folder', $allowedItems)) { $menuDef['folder']['isActive'] = $this->act === 'folder'; $menuDef['folder']['label'] = $lang->getLL('folder', TRUE); $menuDef['folder']['url'] = '#'; $menuDef['folder']['addParams'] = 'onclick="jumpToUrl(' . GeneralUtility::quoteJSvalue('?act=folder') . ');return false;"'; } if (in_array('url', $allowedItems)) { $menuDef['url']['isActive'] = $this->act === 'url'; $menuDef['url']['label'] = $lang->getLL('extUrl', TRUE); $menuDef['url']['url'] = '#'; $menuDef['url']['addParams'] = 'onclick="jumpToUrl(' . GeneralUtility::quoteJSvalue('?act=url') . ');return false;"'; } if (in_array('mail', $allowedItems)) { $menuDef['mail']['isActive'] = $this->act === 'mail'; $menuDef['mail']['label'] = $lang->getLL('email', TRUE); $menuDef['mail']['url'] = '#'; $menuDef['mail']['addParams'] = 'onclick="jumpToUrl(' . GeneralUtility::quoteJSvalue('?act=mail') . ');return false;"'; } if (is_array($this->thisConfig['userLinks.']) && in_array('spec', $allowedItems)) { $menuDef['spec']['isActive'] = $this->act === 'spec'; $menuDef['spec']['label'] = $lang->getLL('special', TRUE); $menuDef['spec']['url'] = '#'; $menuDef['spec']['addParams'] = 'onclick="jumpToUrl(' . GeneralUtility::quoteJSvalue('?act=spec') . ');return false;"'; } // Call hook for extra options foreach ($this->hookObjects as $hookObject) { $menuDef = $hookObject->modifyMenuDefinition($menuDef); } return $menuDef; } /** * Returns HTML of the email link from * * @return string */ protected function getEmailSelectorHtml() { $lang = $this->getLanguageService(); $extUrl = '
' . $lang->getLL('emailAddress', TRUE) . ': doc->formWidth(20) . ' value="' . htmlspecialchars(($this->curUrlInfo['act'] === 'mail' ? $this->curUrlInfo['info'] : '')) . '" />
'; return $extUrl; } /** * Returns HTML of the external url link from * * @return string */ protected function getExternalUrlSelectorHtml() { $extUrl = '
URL: doc->formWidth(30) . ' value="' . htmlspecialchars(($this->curUrlInfo['act'] === 'url' ? $this->curUrlInfo['info'] : 'http://')) . '" /> ' . '
'; return $extUrl; } /** * Returns HTML of the file/folder link selector * * @param string $treeClassName * @return string */ protected function getFileSelectorHtml($treeClassName = \TYPO3\CMS\Backend\Tree\View\ElementBrowserFolderTreeView::class) { $folderTree = GeneralUtility::makeInstance($treeClassName); $folderTree->thisScript = $this->thisScript; $tree = $folderTree->getBrowsableTree(); $backendUser = $this->getBackendUserAuthentication(); if (!$this->curUrlInfo['value'] || $this->curUrlInfo['act'] != $this->act) { $cmpPath = ''; } else { $cmpPath = $this->curUrlInfo['value']; if (!isset($this->expandFolder)) { $this->expandFolder = $cmpPath; } } // Create upload/create folder forms, if a path is given $selectedFolder = FALSE; if ($this->expandFolder) { $fileOrFolderObject = NULL; try { $fileOrFolderObject = ResourceFactory::getInstance()->retrieveFileOrFolderObject($this->expandFolder); } catch (\Exception $e) { // No path is selected } if ($fileOrFolderObject instanceof Folder) { // It's a folder $selectedFolder = $fileOrFolderObject; } elseif ($fileOrFolderObject instanceof FileInterface) { // It's a file try { $selectedFolder = $fileOrFolderObject->getParentFolder(); } catch (\Exception $e) { // Accessing the parent folder failed for some reason. e.g. permissions } } } // If no folder is selected, get the user's default upload folder if (!$selectedFolder) { try { $selectedFolder = $backendUser->getDefaultUploadFolder(); } catch (\Exception $e) { // The configured default user folder does not exist } } // Build the file upload and folder creation form $uploadForm = ''; $createFolder = ''; $content = ''; if ($selectedFolder) { $uploadForm = ($this->act === 'file') ? $this->uploadForm($selectedFolder) : ''; $createFolder = $this->createFolder($selectedFolder); } // Insert the upload form on top, if so configured if ($backendUser->getTSConfigVal('options.uploadFieldsInTopOfEB')) { $content .= $uploadForm; } // Render the filelist if there is a folder selected $files = ''; if ($selectedFolder) { $allowedExtensions = isset($this->P['params']['allowedExtensions']) ? $this->P['params']['allowedExtensions'] : ''; $files = $this->expandFolder($selectedFolder, $allowedExtensions); } // Create folder tree: $this->doc->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Backend/LegacyTree', 'function(Tree) { Tree.ajaxID = "SC_alt_file_navframe::expandCollapse"; }'); $content .= '
' . $this->barheader(($this->getLanguageService()->getLL('folderTree') . ':')) . $tree . ' ' . $files . '
'; // Adding create folder + upload form if applicable if (!$backendUser->getTSConfigVal('options.uploadFieldsInTopOfEB')) { $content .= $uploadForm; } $content .= '
' . $createFolder . '
'; return $content; } /** * Returns HTML of the user defined link selector * * @return string */ protected function getUserLinkSelectorHtml() { if (!is_array($this->thisConfig['userLinks.'])) { return ''; } $lang = $this->getLanguageService(); $subcats = array(); $v = $this->thisConfig['userLinks.']; foreach ($v as $k2 => $value) { $k2i = (int)$k2; if (substr($k2, -1) === '.' && is_array($v[$k2i . '.'])) { // Title: $title = trim($v[$k2i]); if (!$title) { $title = $v[$k2i . '.']['url']; } else { $title = $lang->sL($title); } // Description: $description = $v[$k2i . '.']['description'] ? $lang->sL($v[($k2i . '.')]['description'], TRUE) . '
' : ''; // URL + onclick event: $onClickEvent = ''; if (isset($v[$k2i . '.']['target'])) { $onClickEvent .= 'browse_links_setTarget(' . GeneralUtility::quoteJSvalue($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('', ''); // Adding link to menu of user defined links: $subcats[$k2i] = ' ' . $A[0] . '' . htmlspecialchars($title) . ($this->curUrlInfo['info'] == $v[$k2i . '.']['url'] ? '' : '') . '
' . $description . $A[1] . ' '; } } // Sort by keys: ksort($subcats); // Add menu to content: $content = ' ' . implode('', $subcats) . '
' . $lang->getLL('special', TRUE) . '
'; return $content; } /** * Returns HTML of the page link selector * * @param string $treeClassName name of the class used for page tree rendering * @return string */ protected function getPageSelectorHtml($treeClassName = \TYPO3\CMS\Backend\Tree\View\ElementBrowserPageTreeView::class) { $backendUser = $this->getBackendUserAuthentication(); $pageTree = GeneralUtility::makeInstance($treeClassName); $pageTree->thisScript = $this->thisScript; $pageTree->ext_showPageId = $backendUser->getTSConfigVal('options.pageTree.showPageIdWithTitle'); $pageTree->ext_showNavTitle = $backendUser->getTSConfigVal('options.pageTree.showNavTitle'); $pageTree->addField('nav_title'); $tree = $pageTree->getBrowsableTree(); $cElements = $this->expandPage(); $dbmount = $this->getTemporaryTreeMountCancelNotice(); $content = '
' . $this->barheader(($this->getLanguageService()->getLL('pageTree') . ':')) . $dbmount . $tree . ' ' . $cElements . '
'; return $content; } /** * TYPO3 Element Browser: Showing a page tree and allows you to browse for records * * @return string HTML content for the module */ public function main_db() { // Starting content: $content = $this->doc->startPage('TBE record selector'); // Init variable: $pArr = explode('|', $this->bparams); $tables = $pArr[3]; $backendUser = $this->getBackendUserAuthentication(); // Making the browsable pagetree: /** @var \TYPO3\CMS\Recordlist\Tree\View\ElementBrowserPageTreeView $pageTree */ $pageTree = GeneralUtility::makeInstance(\TYPO3\CMS\Recordlist\Tree\View\ElementBrowserPageTreeView::class); $pageTree->thisScript = $this->thisScript; $pageTree->ext_pArrPages = $tables === 'pages' ? 1 : 0; $pageTree->ext_showNavTitle = $backendUser->getTSConfigVal('options.pageTree.showNavTitle'); $pageTree->ext_showPageId = $backendUser->getTSConfigVal('options.pageTree.showPageIdWithTitle'); $pageTree->addField('nav_title'); $withTree = TRUE; if (($tables !== '') && ($tables !== '*')) { $tablesArr = GeneralUtility::trimExplode(',', $tables, TRUE); $onlyRootLevel = TRUE; foreach ($tablesArr as $currentTable) { $tableTca = $GLOBALS['TCA'][$currentTable]; if (isset($tableTca)) { if (!isset($tableTca['ctrl']['rootLevel']) || ((int)$tableTca['ctrl']['rootLevel']) != 1) { $onlyRootLevel = FALSE; } } } if ($onlyRootLevel) { $withTree = FALSE; // page to work on will be root $this->expandPage = 0; } } $tree = $pageTree->getBrowsableTree(); // Making the list of elements, if applicable: $cElements = $this->TBE_expandPage($tables); // Putting the things together, side by side: $content .= ' '; if ($withTree) { $content .= ''; } $content .= '
' . $this->barheader(($this->getLanguageService()->getLL('pageTree') . ':')) . $this->getTemporaryTreeMountCancelNotice() . $tree . '' . $cElements . '
'; // Add some space $content .= '

'; // End page, return content: $content .= $this->doc->endPage(); $content = $this->doc->insertStylesAndJS($content); return $content; } /** * TYPO3 Element Browser: Showing a folder tree, allowing you to browse for files. * * @return string HTML content for the module */ public function main_file() { // include JS files and set prefs for foldertree $this->doc->getDragDropCode('folders', 'Tree.ajaxID = "SC_alt_file_navframe::expandCollapse"'); // Starting content: $content = $this->doc->startPage('TBE file selector'); // Init variable: $pArr = explode('|', $this->bparams); // The key number 3 of the pArr contains the "allowed" string. Disallowed is not passed to // the element browser at all but only filtered out in TCEMain afterwards $allowed = $pArr[3]; if ($allowed !== 'sys_file' && $allowed !== '*' && !empty($allowed)) { $allowedFileExtensions = $allowed; } $backendUser = $this->getBackendUserAuthentication(); if (isset($allowedFileExtensions)) { // Create new filter object $filterObject = GeneralUtility::makeInstance(FileExtensionFilter::class); $filterObject->setAllowedFileExtensions($allowedFileExtensions); // Set file extension filters on all storages $storages = $backendUser->getFileStorages(); /** @var $storage \TYPO3\CMS\Core\Resource\ResourceStorage */ foreach ($storages as $storage) { $storage->addFileAndFolderNameFilter(array($filterObject, 'filterFileList')); } } // Create upload/create folder forms, if a path is given $this->selectedFolder = FALSE; if ($this->expandFolder) { $fileOrFolderObject = NULL; // Try to fetch the folder the user had open the last time he browsed files // Fallback to the default folder in case the last used folder is not existing try { $fileOrFolderObject = ResourceFactory::getInstance()->retrieveFileOrFolderObject($this->expandFolder); } catch (Exception $accessException) { // We're just catching the exception here, nothing to be done if folder does not exist or is not accessible. } if ($fileOrFolderObject instanceof Folder) { // It's a folder $this->selectedFolder = $fileOrFolderObject; } elseif ($fileOrFolderObject instanceof FileInterface) { // It's a file $this->selectedFolder = $fileOrFolderObject->getParentFolder(); } } // Or get the user's default upload folder if (!$this->selectedFolder) { try { $this->selectedFolder = $backendUser->getDefaultUploadFolder(); } catch (\Exception $e) { // The configured default user folder does not exist } } // Build the file upload and folder creation form $uploadForm = ''; $createFolder = ''; if ($this->selectedFolder) { $uploadForm = $this->uploadForm($this->selectedFolder); $createFolder = $this->createFolder($this->selectedFolder); } // Insert the upload form on top, if so configured if ($backendUser->getTSConfigVal('options.uploadFieldsInTopOfEB')) { $content .= $uploadForm; } // Getting flag for showing/not showing thumbnails: $noThumbs = $backendUser->getTSConfigVal('options.noThumbsInEB'); $_MOD_SETTINGS = array(); if (!$noThumbs) { // MENU-ITEMS, fetching the setting for thumbnails from File>List module: $_MOD_MENU = array('displayThumbs' => ''); $_MCONF['name'] = 'file_list'; $_MOD_SETTINGS = BackendUtility::getModuleData($_MOD_MENU, GeneralUtility::_GP('SET'), $_MCONF['name']); } $noThumbs = $noThumbs ?: !$_MOD_SETTINGS['displayThumbs']; // Create folder tree: /** @var \TYPO3\CMS\Recordlist\Tree\View\ElementBrowserFolderTreeView $folderTree */ $folderTree = GeneralUtility::makeInstance(\TYPO3\CMS\Recordlist\Tree\View\ElementBrowserFolderTreeView::class); $folderTree->thisScript = $this->thisScript; $folderTree->ext_noTempRecyclerDirs = $this->mode == 'filedrag'; $tree = $folderTree->getBrowsableTree(); if ($this->selectedFolder) { if ($this->mode == 'filedrag') { $files = $this->TBE_dragNDrop($this->selectedFolder, $pArr[3]); } else { $files = $this->TBE_expandFolder($this->selectedFolder, $pArr[3], $noThumbs); } } else { $files = ''; } // Add the FlashMessages if any $content .= $this->doc->getFlashMessages(); // Putting the parts together, side by side: $content .= '
' . $this->barheader(($this->getLanguageService()->getLL('folderTree') . ':')) . $tree . ' ' . $files . '
'; // Adding create folder + upload forms if applicable: if (!$backendUser->getTSConfigVal('options.uploadFieldsInTopOfEB')) { $content .= $uploadForm; } $content .= $createFolder; // Add some space $content .= '

'; // Setup indexed elements: $this->doc->JScode .= $this->doc->wrapScriptTags(' require(["TYPO3/CMS/Backend/BrowseLinks"], function(BrowseLinks) { BrowseLinks.addElements(' . json_encode($this->elements) . '); });'); // Ending page, returning content: $content .= $this->doc->endPage(); $content = $this->doc->insertStylesAndJS($content); return $content; } /** * TYPO3 Element Browser: Showing a folder tree, allowing you to browse for folders. * * @return string HTML content for the module */ public function main_folder() { // include JS files // Setting prefs for foldertree $this->doc->getDragDropCode('folders', 'Tree.ajaxID = "SC_alt_file_navframe::expandCollapse";'); // Starting content: $content = $this->doc->startPage('TBE folder selector'); // Init variable: $parameters = explode('|', $this->bparams); if ($this->expandFolder) { $this->selectedFolder = ResourceFactory::getInstance()->getFolderObjectFromCombinedIdentifier($this->expandFolder); } if ($this->selectedFolder) { $createFolder = $this->createFolder($this->selectedFolder); } else { $createFolder = ''; } // Create folder tree: /** @var \TYPO3\CMS\Recordlist\Tree\View\ElementBrowserFolderTreeView $folderTree */ $folderTree = GeneralUtility::makeInstance(\TYPO3\CMS\Recordlist\Tree\View\ElementBrowserFolderTreeView::class); $folderTree->thisScript = $this->thisScript; $folderTree->ext_noTempRecyclerDirs = $this->mode == 'filedrag'; $tree = $folderTree->getBrowsableTree(FALSE); $folders = ''; if ($this->selectedFolder) { if ($this->mode == 'filedrag') { $folders = $this->TBE_dragNDrop($this->selectedFolder, $parameters[3]); } else { $folders = $this->TBE_expandSubFolders($this->selectedFolder); } } // Putting the parts together, side by side: $content .= '
' . $this->barheader(($this->getLanguageService()->getLL('folderTree') . ':')) . $tree . ' ' . $folders . '
'; // Adding create folder if applicable: $content .= $createFolder; // Add some space $content .= '

'; // Ending page, returning content: $content .= $this->doc->endPage(); $content = $this->doc->insertStylesAndJS($content); return $content; } /****************************************************************** * * Record listing * ******************************************************************/ /** * For RTE: This displays all content elements on a page and lets you create a link to the element. * * @return string HTML output. Returns content only if the ->expandPage value is set (pointing to a page uid to show tt_content records from ...) */ public function expandPage() { $out = ''; // Set page id (if any) to expand $expPageId = $this->expandPage; // If there is an anchor value (content element reference) in the element reference, then force an ID to expand: if (!$this->expandPage && $this->curUrlInfo['cElement']) { // Set to the current link page id. $expPageId = $this->curUrlInfo['pageid']; } // Draw the record list IF there is a page id to expand: if ($expPageId && MathUtility::canBeInterpretedAsInteger($expPageId) && $this->getBackendUserAuthentication()->isInWebMount($expPageId) ) { // Set header: $out .= $this->barheader($this->getLanguageService()->getLL('contentElements') . ':'); // Create header for listing, showing the page title/icon: $mainPageRec = BackendUtility::getRecordWSOL('pages', $expPageId); $db = $this->getDatabaseConnection(); $picon = IconUtility::getSpriteIconForRecord('pages', $mainPageRec); $picon .= BackendUtility::getRecordTitle('pages', $mainPageRec, TRUE); $out .= $picon . '
'; // Look up tt_content elements from the expanded page: $res = $db->exec_SELECTquery( 'uid,header,hidden,starttime,endtime,fe_group,CType,colPos,bodytext', 'tt_content', 'pid=' . (int)$expPageId . BackendUtility::deleteClause('tt_content') . BackendUtility::versioningPlaceholderClause('tt_content'), '', 'colPos,sorting' ); $cc = $db->sql_num_rows($res); // Traverse list of records: $c = 0; while ($row = $db->sql_fetch_assoc($res)) { $c++; $icon = IconUtility::getSpriteIconForRecord('tt_content', $row); if ($this->curUrlInfo['act'] == 'page' && $this->curUrlInfo['cElement'] == $row['uid']) { $arrCol = ''; } else { $arrCol = ''; } // Putting list element HTML together: $out .= '' . $arrCol . '' . $icon . BackendUtility::getRecordTitle('tt_content', $row, TRUE) . '
'; // Finding internal anchor points: if (GeneralUtility::inList('text,textpic', $row['CType'])) { $split = preg_split('/(]+name=[\'"]?([^"\'>[:space:]]+)[\'"]?[^>]*>)/i', $row['bodytext'], -1, PREG_SPLIT_DELIM_CAPTURE); foreach ($split as $skey => $sval) { if ($skey % 3 == 2) { // Putting list element HTML together: $sval = substr($sval, 0, 100); $out .= '' . ' count($split) ? 'bottom' : '') . '.gif'), 'width="18" height="16"') . ' alt="" />' . '' . htmlspecialchars((' ' . $sval)) . '
'; } } } } } return $out; } /** * For TYPO3 Element Browser: This lists all content elements from the given list of tables * * @param string $tables Comma separated list of tables. Set to "*" if you want all tables. * @return string HTML output. */ public function TBE_expandPage($tables) { $backendUser = $this->getBackendUserAuthentication(); if (!MathUtility::canBeInterpretedAsInteger($this->expandPage) || $this->expandPage < 0 || !$backendUser->isInWebMount($this->expandPage) ) { return ''; } // Set array with table names to list: if (trim($tables) === '*') { $tablesArr = array_keys($GLOBALS['TCA']); } else { $tablesArr = GeneralUtility::trimExplode(',', $tables, TRUE); } reset($tablesArr); // Headline for selecting records: $out = $this->barheader($this->getLanguageService()->getLL('selectRecords') . ':'); // Create the header, showing the current page for which the listing is. // Includes link to the page itself, if pages are amount allowed tables. $titleLen = (int)$backendUser->uc['titleLen']; $mainPageRec = BackendUtility::getRecordWSOL('pages', $this->expandPage); $ATag = ''; $ATag_e = ''; $ATag2 = ''; $picon = ''; if (is_array($mainPageRec)) { $picon = IconUtility::getSpriteIconForRecord('pages', $mainPageRec); if (in_array('pages', $tablesArr)) { $ATag = ''; $ATag2 = ''; $ATag_e = ''; } } $pBicon = $ATag2 ? '' : ''; $pText = htmlspecialchars(GeneralUtility::fixed_lgd_cs($mainPageRec['title'], $titleLen)); $out .= $picon . $ATag2 . $pBicon . $ATag_e . $ATag . $pText . $ATag_e . '
'; // Initialize the record listing: $id = $this->expandPage; $pointer = MathUtility::forceIntegerInRange($this->pointer, 0, 100000); $perms_clause = $backendUser->getPagePermsClause(1); $pageInfo = BackendUtility::readPageAccess($id, $perms_clause); // Generate the record list: /** @var $dbList ElementBrowserRecordList */ if (is_object($this->recordList)) { $dbList = $this->recordList; } else { $dbList = GeneralUtility::makeInstance(ElementBrowserRecordList::class); } $dbList->thisScript = $this->thisScript; $dbList->backPath = $GLOBALS['BACK_PATH']; $dbList->thumbs = 0; $dbList->calcPerms = $backendUser->calcPerms($pageInfo); $dbList->noControlPanels = 1; $dbList->clickMenuEnabled = 0; $dbList->tableList = implode(',', $tablesArr); $pArr = explode('|', $this->bparams); // a string like "data[pages][79][storage_pid]" $fieldPointerString = $pArr[0]; // parts like: data, pages], 79], storage_pid] $fieldPointerParts = explode('[', $fieldPointerString); $relatingTableName = substr($fieldPointerParts[1], 0, -1); $relatingFieldName = substr($fieldPointerParts[3], 0, -1); if ($relatingTableName && $relatingFieldName) { $dbList->setRelatingTableAndField($relatingTableName, $relatingFieldName); } $dbList->start($id, GeneralUtility::_GP('table'), $pointer, GeneralUtility::_GP('search_field'), GeneralUtility::_GP('search_levels'), GeneralUtility::_GP('showLimit') ); $dbList->setDispFields(); $dbList->generateList(); $out .= $dbList->getSearchBox(); $out .= ""; // Add the HTML for the record list to output variable: $out .= $dbList->HTMLcode; // Add support for fieldselectbox in singleTableMode if ($dbList->table) { $out .= $dbList->fieldSelectBox($dbList->table); } // Return accumulated content: return $out; } /** * Render list of folders inside a folder. * * @param Folder $folder Folder * @return string HTML output */ public function TBE_expandSubFolders(Folder $folder) { $content = ''; if ($folder->checkActionPermission('read')) { $content .= $this->folderList($folder); } // Return accumulated content for folderlisting: return $content; } /****************************************************************** * * File listing * ******************************************************************/ /** * For RTE: This displays all files from folder. No thumbnails shown * * @param Folder $folder The folder path to expand * @param string $extensionList List of file extensions to show * @return string HTML output */ public function expandFolder(Folder $folder, $extensionList = '') { if (!$folder->checkActionPermission('read')) { return ''; } $lang = $this->getLanguageService(); $renderFolders = $this->act === 'folder'; // Create header for file/folder listing: if ($renderFolders) { $out = $this->barheader($lang->getLL('folders') . ':'); } else { $out = $this->barheader($lang->getLL('files') . ':'); } // Prepare current path value for comparison (showing red arrow) $currentIdentifier = ''; if ($this->curUrlInfo['value']) { $currentIdentifier = $this->curUrlInfo['info']; } // Create header element; The folder from which files are listed. $titleLen = (int)$this->getBackendUserAuthentication()->uc['titleLen']; $folderIcon = IconUtility::getSpriteIconForResource($folder); $folderIcon .= htmlspecialchars(GeneralUtility::fixed_lgd_cs($folder->getIdentifier(), $titleLen)); $picon = '' . $folderIcon . ''; if ($this->curUrlInfo['act'] == 'folder' && $currentIdentifier == $folder->getCombinedIdentifier()) { $out .= ''; } $out .= $picon . '
'; // Get files from the folder: if ($renderFolders) { $items = $folder->getSubfolders(); } else { $items = $this->getFilesInFolder($folder, $extensionList); } $c = 0; $totalItems = count($items); foreach ($items as $fileOrFolderObject) { $c++; if ($renderFolders) { $fileIdentifier = $fileOrFolderObject->getCombinedIdentifier(); $overlays = array(); if ($fileOrFolderObject instanceof InaccessibleFolder) { $overlays = array('status-overlay-locked' => array()); } $icon = IconUtility::getSpriteIcon( IconUtility::mapFileExtensionToSpriteIconName('folder'), array('title' => $fileOrFolderObject->getName()), $overlays); $itemUid = 'file:' . $fileIdentifier; } else { $fileIdentifier = $fileOrFolderObject->getUid(); // Get size and icon: $size = ' (' . GeneralUtility::formatSize($fileOrFolderObject->getSize()) . 'bytes)'; $icon = IconUtility::getSpriteIconForResource($fileOrFolderObject, array('title' => $fileOrFolderObject->getName() . $size)); $itemUid = 'file:' . $fileIdentifier; } // If the listed file turns out to be the CURRENT file, then show blinking arrow: if (($this->curUrlInfo['act'] == 'file' || $this->curUrlInfo['act'] == 'folder') && $currentIdentifier == $fileIdentifier ) { $arrCol = ''; } else { $arrCol = ''; } // Put it all together for the file element: $out .= '' . $arrCol . '' . $icon . htmlspecialchars(GeneralUtility::fixed_lgd_cs($fileOrFolderObject->getName(), $titleLen)) . '
'; } return $out; } /** * For TYPO3 Element Browser: Expand folder of files. * * @param Folder $folder The folder path to expand * @param string $extensionList List of fileextensions to show * @param bool $noThumbs Whether to show thumbnails or not. If set, no thumbnails are shown. * @return string HTML output */ public function TBE_expandFolder(Folder $folder, $extensionList = '', $noThumbs = FALSE) { if (!$folder->checkActionPermission('read')) { return ''; } $extensionList = $extensionList == '*' ? '' : $extensionList; $files = $this->getFilesInFolder($folder, $extensionList); return $this->fileList($files, $folder, $noThumbs); } /** * Render list of files. * * @param File[] $files List of files * @param Folder $folder If set a header with a folder icon and folder name are shown * @param bool $noThumbs Whether to show thumbnails or not. If set, no thumbnails are shown. * @return string HTML output */ protected function fileList(array $files, Folder $folder = NULL, $noThumbs = FALSE) { $out = ''; $lang = $this->getLanguageService(); $lines = array(); // Create headline (showing number of files): $filesCount = count($files); $out .= $this->barheader(sprintf($lang->getLL('files') . ' (%s):', $filesCount)); $out .= '
'; $out .= $this->getBulkSelector($filesCount); $titleLen = (int)$this->getBackendUserAuthentication()->uc['titleLen']; // Create the header of current folder: if ($folder) { $folderIcon = IconUtility::getSpriteIconForResource($folder); $lines[] = ' ' . $folderIcon . htmlspecialchars(GeneralUtility::fixed_lgd_cs($folder->getIdentifier(), $titleLen)) . ' '; } if ($filesCount == 0) { $lines[] = ' No files found. '; } // Traverse the file list: /** @var $fileObject \TYPO3\CMS\Core\Resource\File */ foreach ($files as $fileObject) { $fileExtension = $fileObject->getExtension(); // Thumbnail/size generation: $imgInfo = array(); if (GeneralUtility::inList(strtolower($GLOBALS['TYPO3_CONF_VARS']['GFX']['imagefile_ext']), strtolower($fileExtension)) && !$noThumbs) { $imageUrl = $fileObject->process( ProcessedFile::CONTEXT_IMAGEPREVIEW, array('width' => 64, 'height' => 64) )->getPublicUrl(TRUE); $imgInfo = array( $fileObject->getProperty('width'), $fileObject->getProperty('height') ); $pDim = $imgInfo[0] . 'x' . $imgInfo[1] . ' pixels'; $clickIcon = ''; } else { $clickIcon = ''; $pDim = ''; } // Create file icon: $size = ' (' . GeneralUtility::formatSize($fileObject->getSize()) . 'bytes' . ($pDim ? ', ' . $pDim : '') . ')'; $icon = IconUtility::getSpriteIconForResource($fileObject, array('title' => $fileObject->getName() . $size)); // Create links for adding the file: $filesIndex = count($this->elements); $this->elements['file_' . $filesIndex] = array( 'type' => 'file', 'table' => 'sys_file', 'uid' => $fileObject->getUid(), 'fileName' => $fileObject->getName(), 'filePath' => $fileObject->getUid(), 'fileExt' => $fileExtension, 'fileIcon' => $icon ); if ($this->fileIsSelectableInFileList($fileObject, $imgInfo)) { $ATag = ''; $ATag_alt = substr($ATag, 0, -4) . ',1);">'; $bulkCheckBox = ' '; $ATag_e = ''; } else { $ATag = ''; $ATag_alt = ''; $ATag_e = ''; $bulkCheckBox = ''; } // Create link to showing details about the file in a window: $Ahref = $GLOBALS['BACK_PATH'] . 'show_item.php?type=file&table=_FILE&uid=' . rawurlencode($fileObject->getCombinedIdentifier()) . '&returnUrl=' . rawurlencode(GeneralUtility::getIndpEnv('REQUEST_URI')); $ATag2 = ''; $ATag2_e = ''; // Combine the stuff: $filenameAndIcon = $bulkCheckBox . $ATag_alt . $icon . htmlspecialchars(GeneralUtility::fixed_lgd_cs($fileObject->getName(), $titleLen)) . $ATag_e; // Show element: if ($pDim) { // Image... $lines[] = ' ' . $filenameAndIcon . '  ' . ($ATag . '' . $ATag_e) . ' ' . ($ATag2 . ' ' . $lang->getLL('info', TRUE) . $ATag2_e) . '  ' . $pDim . ' '; $lines[] = ' ' . $ATag_alt . $clickIcon . $ATag_e . ' '; } else { $lines[] = ' ' . $filenameAndIcon . '  ' . ($ATag . '' . $ATag_e) . ' ' . ($ATag2 . ' ' . $lang->getLL('info', TRUE) . $ATag2_e) . '   '; } } // Wrap all the rows in table tags: $out .= ' ' . implode('', $lines) . '
'; // Return accumulated content for file listing: $out .= '
'; return $out; } /** * Checks if the given file is selectable in the file list. * * By default all files are selectable. This method may be overwritten in child classes. * * @param FileInterface $file * @param mixed[] $imgInfo Image dimensions from \TYPO3\CMS\Core\Imaging\GraphicalFunctions::getImageDimensions() * @return bool TRUE if file is selectable. */ protected function fileIsSelectableInFileList(FileInterface $file, array $imgInfo) { return TRUE; } /** * Render list of folders. * * @param Folder $baseFolder * @return string HTML output */ public function folderList(Folder $baseFolder) { $content = ''; $lang = $this->getLanguageService(); $folders = $baseFolder->getSubfolders(); $folderIdentifier = $baseFolder->getCombinedIdentifier(); // Create headline (showing number of folders): $content .= $this->barheader(sprintf($lang->getLL('folders') . ' (%s):', count($folders))); $titleLength = (int)$this->getBackendUserAuthentication()->uc['titleLen']; // Create the header of current folder: $aTag = ''; // Add the foder icon $folderIcon = $aTag; $folderIcon .= ''; $folderIcon .= htmlspecialchars(GeneralUtility::fixed_lgd_cs($baseFolder->getName(), $titleLength)); $folderIcon .= ''; $content .= $folderIcon . '
'; $lines = array(); // Traverse the folder list: foreach ($folders as $subFolder) { $subFolderIdentifier = $subFolder->getCombinedIdentifier(); // Create folder icon: $icon = ''; // Create links for adding the folder: if ($this->P['itemName'] != '' && $this->P['formName'] != '') { $aTag = ''; } else { $aTag = ''; } if (strstr($subFolderIdentifier, ',') || strstr($subFolderIdentifier, '|')) { // In case an invalid character is in the filepath, display error message: $errorMessage = GeneralUtility::quoteJSvalue(sprintf($lang->getLL('invalidChar'), ', |')); $aTag = ($aTag_alt = ''); } else { // If foldername is OK, just add it: $aTag_alt = substr($aTag, 0, -4) . ',\'\',1);">'; } $aTag_e = ''; // Combine icon and folderpath: $foldernameAndIcon = $aTag_alt . $icon . htmlspecialchars(GeneralUtility::fixed_lgd_cs($subFolder->getName(), $titleLength)) . $aTag_e; if ($this->P['itemName'] != '') { $lines[] = ' ' . $foldernameAndIcon . '    '; } else { $lines[] = ' ' . $foldernameAndIcon . '  ' . $aTag . '' . $aTag_e . '   '; } $lines[] = ' '; } // Wrap all the rows in table tags: $content .= ' ' . implode('', $lines) . '
'; // Return accumulated content for folderlisting: return $content; } /** * For RTE: This displays all IMAGES (gif,png,jpg) (from extensionList) from folder. Thumbnails are shown for images. * This listing is of images located in the web-accessible paths ONLY - the listing is for drag-n-drop use in the RTE * * @param Folder $folder The folder path to expand * @param string $extensionList List of file extensions to show * @return string HTML output */ public function TBE_dragNDrop(Folder $folder, $extensionList = '') { if (!$folder) { return ''; } $lang = $this->getLanguageService(); if (!$folder->getStorage()->isPublic()) { // Print this warning if the folder is NOT a web folder return $this->barheader($lang->getLL('files')) . $this->getMsgBox($lang->getLL('noWebFolder'), 'icon_warning2'); } $out = ''; // Read files from directory: $extensionList = $extensionList == '*' ? '' : $extensionList; $files = $this->getFilesInFolder($folder, $extensionList); $out .= $this->barheader(sprintf($lang->getLL('files') . ' (%s):', count($files))); $titleLen = (int)$this->getBackendUserAuthentication()->uc['titleLen']; $picon = ''; $picon .= htmlspecialchars(GeneralUtility::fixed_lgd_cs(basename($folder->getName()), $titleLen)); $out .= $picon . '
'; // Init row-array: $lines = array(); // Add "drag-n-drop" message: $lines[] = ' ' . $this->getMsgBox($lang->getLL('findDragDrop')) . ' '; // Traverse files: foreach ($files as $fileObject) { // URL of image: $iUrl = GeneralUtility::rawurlencodeFP($fileObject->getPublicUrl(TRUE)); // Show only web-images $fileExtension = strtolower($fileObject->getExtension()); if (GeneralUtility::inList('gif,jpeg,jpg,png', $fileExtension)) { $imgInfo = array( $fileObject->getProperty('width'), $fileObject->getProperty('height') ); $pDim = $imgInfo[0] . 'x' . $imgInfo[1] . ' pixels'; $size = ' (' . GeneralUtility::formatSize($fileObject->getSize()) . 'bytes' . ($pDim ? ', ' . $pDim : '') . ')'; $filenameAndIcon = IconUtility::getSpriteIconForResource($fileObject, array('title' => $fileObject->getName() . $size)); if (GeneralUtility::_GP('noLimit')) { $maxW = 10000; $maxH = 10000; } else { $maxW = 380; $maxH = 500; } $IW = $imgInfo[0]; $IH = $imgInfo[1]; if ($IW > $maxW) { $IH = ceil($IH / $IW * $maxW); $IW = $maxW; } if ($IH > $maxH) { $IW = ceil($IW / $IH * $maxH); $IH = $maxH; } // Make row: $lines[] = ' ' . $filenameAndIcon . '  ' . ($imgInfo[0] != $IW ? '' . '' . '' : '') . $pDim . '  '; $lines[] = ' '; $lines[] = ' '; } } // Finally, wrap all rows in a table tag: $out .= ' ' . implode('', $lines) . '
'; return $out; } /****************************************************************** * * Miscellaneous functions * ******************************************************************/ /** * Prints a 'header' where string is in a tablecell * * @param string $str The string to print in the header. The value is htmlspecialchars()'ed before output. * @return string The header HTML (wrapped in a table) */ public function barheader($str) { return '

' . htmlspecialchars($str) . '

'; } /** * Displays a message box with the input message * * @param string $in_msg Input message to show (will be htmlspecialchars()'ed inside of this function) * @param string $icon Icon filename body from gfx/ (default is "icon_note") - meant to allow change to warning type icons... * @return string HTML for the message (wrapped in a table). */ public function getMsgBox($in_msg, $icon = 'icon_note') { $msg = '' . htmlspecialchars($in_msg); $msg = '
' . $msg . '
'; return $msg; } /** * For RTE/link: This prints the 'currentUrl' * * @param string $str URL value. The value is htmlspecialchars()'ed before output. * @return string HTML content, wrapped in a table. */ public function printCurrentUrl($str) { // Output the folder or file identifier, when working with files if (isset($str) && MathUtility::canBeInterpretedAsInteger($str)) { try { $fileObject = ResourceFactory::getInstance()->retrieveFileOrFolderObject($str); } catch (Exception\FileDoesNotExistException $e) { $fileObject = NULL; } $str = is_object($fileObject) ? $fileObject->getIdentifier() : ''; } if ($str !== '') { return '
' . $this->getLanguageService()->getLL('currentLink', TRUE) . ': ' . htmlspecialchars(rawurldecode($str)) . '
'; } else { return ''; } } /** * For RTE/link: Parses the incoming URL and determines if it's a page, file, external or mail address. * * @param string $href HREF value tp analyse * @param string $siteUrl The URL of the current website (frontend) * @return array[] Array with URL information stored in assoc. keys: value, act (page, file, spec, mail), pageid, cElement, info */ public function parseCurUrl($href, $siteUrl) { $href = trim($href); $lang = $this->getLanguageService(); if ($href) { $info = array(); // Default is "url": $info['value'] = $href; $info['act'] = 'url'; $specialParts = explode('#_SPECIAL', $href); // Special kind (Something RTE specific: User configurable links through: "userLinks." from ->thisConfig) if (count($specialParts) == 2) { $info['value'] = '#_SPECIAL' . $specialParts[1]; $info['act'] = 'spec'; } elseif (strpos($href, 'file:') !== FALSE) { $rel = substr($href, strpos($href, 'file:') + 5); $rel = rawurldecode($rel); // resolve FAL-api "file:UID-of-sys_file-record" and "file:combined-identifier" $fileOrFolderObject = ResourceFactory::getInstance()->retrieveFileOrFolderObject($rel); if ($fileOrFolderObject instanceof Folder) { $info['act'] = 'folder'; $info['value'] = $fileOrFolderObject->getCombinedIdentifier(); } elseif ($fileOrFolderObject instanceof File) { $info['act'] = 'file'; $info['value'] = $fileOrFolderObject->getUid(); } else { $info['value'] = $rel; } } elseif (GeneralUtility::isFirstPartOfStr($href, $siteUrl)) { // If URL is on the current frontend website: // URL is a file, which exists: if (file_exists(PATH_site . rawurldecode($href))) { $info['value'] = rawurldecode($href); if (@is_dir((PATH_site . $info['value']))) { $info['act'] = 'folder'; } else { $info['act'] = 'file'; } } else { // URL is a page (id parameter) $uP = parse_url($href); $pp = preg_split('/^id=/', $uP['query']); $pp[1] = preg_replace('/&id=[^&]*/', '', $pp[1]); $parameters = explode('&', $pp[1]); $id = array_shift($parameters); if ($id) { // Checking if the id-parameter is an alias. if (!MathUtility::canBeInterpretedAsInteger($id)) { list($idPartR) = BackendUtility::getRecordsByField('pages', 'alias', $id); $id = (int)$idPartR['uid']; } $pageRow = BackendUtility::getRecordWSOL('pages', $id); $titleLen = (int)$this->getBackendUserAuthentication()->uc['titleLen']; $info['value'] = ((((($lang->getLL('page', TRUE) . ' \'') . htmlspecialchars(GeneralUtility::fixed_lgd_cs($pageRow['title'], $titleLen))) . '\' (ID:') . $id) . ($uP['fragment'] ? ', #' . $uP['fragment'] : '')) . ')'; $info['pageid'] = $id; $info['cElement'] = $uP['fragment']; $info['act'] = 'page'; $info['query'] = $parameters[0] ? '&' . implode('&', $parameters) : ''; } } } else { // Email link: if (strtolower(substr($href, 0, 7)) === 'mailto:') { $info['value'] = trim(substr($href, 7)); $info['act'] = 'mail'; } } $info['info'] = $info['value']; } else { // NO value input: $info = array(); $info['info'] = $lang->getLL('none'); $info['value'] = ''; $info['act'] = 'page'; } // let the hook have a look foreach ($this->hookObjects as $hookObject) { $info = $hookObject->parseCurrentUrl($href, $siteUrl, $info); } return $info; } /** * Setter for the class that should be used by TBE_expandPage() to generate the record list. * This method is intended to be used by Extensions that implement their own browsing functionality. * * @param ElementBrowserRecordList $recordList * @throws \InvalidArgumentException * @return void * @api */ public function setRecordList($recordList) { if (!$recordList instanceof ElementBrowserRecordList) { throw new \InvalidArgumentException('$recordList needs to be an instance of ' . ElementBrowserRecordList::class, 1370878522); } $this->recordList = $recordList; } /** * For TBE: Makes an upload form for uploading files to the filemount the user is browsing. * The files are uploaded to the tce_file.php script in the core which will handle the upload. * * @param Folder $folderObject Absolute filepath on server to which to upload. * @return string HTML for an upload form. */ public function uploadForm(Folder $folderObject) { if (!$folderObject->checkActionPermission('write')) { return ''; } // Read configuration of upload field count $userSetting = $this->getBackendUserAuthentication()->getTSConfigVal('options.folderTree.uploadFieldsInLinkBrowser'); $count = isset($userSetting) ? $userSetting : 1; if ($count === '0') { return ''; } $count = (int)$count === 0 ? 1 : (int)$count; // Create header, showing upload path: $header = $folderObject->getIdentifier(); $lang = $this->getLanguageService(); $code = '
' . $this->barheader($lang->sL( 'LLL:EXT:lang/locallang_core.xlf:file_upload.php.pagetitle', TRUE) . ':') . '
' . $lang->getLL('path', TRUE) . ': ' . htmlspecialchars($header) . '
'; // Traverse the number of upload fields (default is 3): for ($a = 1; $a <= $count; $a++) { $code .= 'doc->formWidth(35) . ' size="50" />
'; } // Make footer of upload form, including the submit button: $redirectValue = $this->getThisScript() . 'act=' . $this->act . '&mode=' . $this->mode . '&expandFolder=' . rawurlencode($folderObject->getCombinedIdentifier()) . '&bparams=' . rawurlencode($this->bparams) . (is_array($this->P) ? GeneralUtility::implodeArrayForUrl('P', $this->P) : ''); $code .= ''; $code .= FormEngine::getHiddenTokenField('tceAction'); $code .= '
'; $code .= '

'; return $code; } /** * For TBE: Makes a form for creating new folders in the filemount the user is browsing. * The folder creation request is sent to the tce_file.php script in the core which will handle the creation. * * @param Folder $folderObject Absolute filepath on server in which to create the new folder. * @return string HTML for the create folder form. */ public function createFolder(Folder $folderObject) { if (!$folderObject->checkActionPermission('write')) { return ''; } $backendUser = $this->getBackendUserAuthentication(); if (!($backendUser->isAdmin() || $backendUser->getTSConfigVal('options.createFoldersInEB'))) { return ''; } // Don't show Folder-create form if it's denied if ($backendUser->getTSConfigVal('options.folderTree.hideCreateFolder')) { return ''; } $lang = $this->getLanguageService(); // Create header, showing upload path: $header = $folderObject->getIdentifier(); $code = '
' . $this->barheader($lang->sL( 'LLL:EXT:lang/locallang_core.xlf:file_newfolder.php.pagetitle') . ':') . '
' . $lang->getLL('path', TRUE) . ': ' . htmlspecialchars($header) . '
'; // Create the new-folder name field: $a = 1; $code .= 'doc->formWidth(20) . ' type="text" name="file[newfolder][' . $a . '][data]" />' . ''; // Make footer of upload form, including the submit button: $redirectValue = $this->getThisScript() . 'act=' . $this->act . '&mode=' . $this->mode . '&expandFolder=' . rawurlencode($folderObject->getCombinedIdentifier()) . '&bparams=' . rawurlencode($this->bparams); $code .= '' . FormEngine::getHiddenTokenField('tceAction') . ''; $code .= '
'; return $code; } /** * Get the HTML data required for a bulk selection of files of the TYPO3 Element Browser. * * @param int $filesCount Number of files currently displayed * @return string HTML data required for a bulk selection of files - if $filesCount is 0, nothing is returned */ public function getBulkSelector($filesCount) { if (!$filesCount) { return ''; } $lang = $this->getLanguageService(); $labelToggleSelection = $lang->sL('LLL:EXT:lang/locallang_browse_links.xlf:toggleSelection', TRUE); $labelImportSelection = $lang->sL('LLL:EXT:lang/locallang_browse_links.xlf:importSelection', TRUE); // Getting flag for showing/not showing thumbnails: $noThumbsInEB = $this->getBackendUserAuthentication()->getTSConfigVal('options.noThumbsInEB'); $out = $this->doc->spacer(10) . ''; if (!$noThumbsInEB && $this->selectedFolder) { // MENU-ITEMS, fetching the setting for thumbnails from File>List module: $_MOD_MENU = array('displayThumbs' => ''); $_MCONF['name'] = 'file_list'; $_MOD_SETTINGS = BackendUtility::getModuleData($_MOD_MENU, GeneralUtility::_GP('SET'), $_MCONF['name']); $addParams = '&act=' . $this->act . '&mode=' . $this->mode . '&expandFolder=' . rawurlencode($this->selectedFolder->getCombinedIdentifier()) . '&bparams=' . rawurlencode($this->bparams); $thumbNailCheck = BackendUtility::getFuncCheck('', 'SET[displayThumbs]', $_MOD_SETTINGS['displayThumbs'], GeneralUtility::_GP('M') ? '' : $this->thisScript, $addParams, 'id="checkDisplayThumbs"') . ' '; $out .= $this->doc->spacer(5) . $thumbNailCheck . $this->doc->spacer(15); } else { $out .= $this->doc->spacer(15); } return $out; } /** * Determines whether submitted field change functions are valid * and are coming from the system and not from an external abuse. * * @param bool $handleFlexformSections Whether to handle flexform sections differently * @return bool Whether the submitted field change functions are valid */ protected function areFieldChangeFunctionsValid($handleFlexformSections = FALSE) { $result = FALSE; if (isset($this->P['fieldChangeFunc']) && is_array($this->P['fieldChangeFunc']) && isset($this->P['fieldChangeFuncHash'])) { $matches = array(); $pattern = '#\\[el\\]\\[(([^]-]+-[^]-]+-)(idx\\d+-)([^]]+))\\]#i'; $fieldChangeFunctions = $this->P['fieldChangeFunc']; // Special handling of flexform sections: // Field change functions are modified in JavaScript, thus the hash is always invalid if ($handleFlexformSections && preg_match($pattern, $this->P['itemName'], $matches)) { $originalName = $matches[1]; $cleanedName = $matches[2] . $matches[4]; foreach ($fieldChangeFunctions as &$value) { $value = str_replace($originalName, $cleanedName, $value); } unset($value); } $result = $this->P['fieldChangeFuncHash'] === GeneralUtility::hmac(serialize($fieldChangeFunctions)); } return $result; } /** * Check if a temporary tree mount is set and return a cancel button * * @return string */ protected function getTemporaryTreeMountCancelNotice() { if ((int)$this->getBackendUserAuthentication()->getSessionData('pageTree_temporaryMountPoint') === 0) { return ''; } $link = '' . $this->getLanguageService()->sl('LLL:EXT:lang/locallang_core.xlf:labels.temporaryDBmount', TRUE) . ''; /** @var FlashMessage $flashMessage */ $flashMessage = GeneralUtility::makeInstance( FlashMessage::class, $link, '', FlashMessage::INFO ); return $flashMessage->render(); } /** * Get a list of Files in a folder filtered by extension * * @param Folder $folder * @param string $extensionList * @return \TYPO3\CMS\Core\Resource\File[] */ protected function getFilesInFolder(Folder $folder, $extensionList) { if ($extensionList !== '') { /** @var FileExtensionFilter $filter */ $filter = GeneralUtility::makeInstance(FileExtensionFilter::class); $filter->setAllowedFileExtensions($extensionList); $folder->setFileAndFolderNameFilters(array(array($filter, 'filterFileList'))); } return $folder->getFiles(); } /** * @return LanguageService */ protected function getLanguageService() { return $GLOBALS['LANG']; } /** * @return BackendUserAuthentication */ protected function getBackendUserAuthentication() { return $GLOBALS['BE_USER']; } /** * @return DatabaseConnection */ protected function getDatabaseConnection() { return $GLOBALS['TYPO3_DB']; } }