[BUGFIX] ElementBrowser: After file upload no file can be selected
[Packages/TYPO3.CMS.git] / typo3 / sysext / recordlist / Classes / Browser / ElementBrowser.php
1 <?php
2 namespace TYPO3\CMS\Recordlist\Browser;
3
4 /*
5 * This file is part of the TYPO3 CMS project.
6 *
7 * It is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License, either version 2
9 * of the License, or any later version.
10 *
11 * For the full copyright and license information, please read the
12 * LICENSE.txt file that was distributed with this source code.
13 *
14 * The TYPO3 project - inspiring people to share!
15 */
16
17 use TYPO3\CMS\Backend\Form\FormEngine;
18 use TYPO3\CMS\Backend\RecordList\ElementBrowserRecordList;
19 use TYPO3\CMS\Backend\Template\DocumentTemplate;
20 use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
21 use TYPO3\CMS\Core\Database\DatabaseConnection;
22 use TYPO3\CMS\Core\ElementBrowser\ElementBrowserHookInterface;
23 use TYPO3\CMS\Core\Messaging\FlashMessage;
24 use TYPO3\CMS\Core\Resource\Exception;
25 use TYPO3\CMS\Core\Resource\File;
26 use TYPO3\CMS\Core\Resource\FileInterface;
27 use TYPO3\CMS\Core\Resource\Filter\FileExtensionFilter;
28 use TYPO3\CMS\Core\Resource\Folder;
29 use TYPO3\CMS\Core\Resource\InaccessibleFolder;
30 use TYPO3\CMS\Core\Resource\ProcessedFile;
31 use TYPO3\CMS\Core\Resource\ResourceFactory;
32 use TYPO3\CMS\Core\Utility\File\BasicFileUtility;
33 use TYPO3\CMS\Core\Utility\GeneralUtility;
34 use TYPO3\CMS\Backend\Utility\BackendUtility;
35 use TYPO3\CMS\Backend\Utility\IconUtility;
36 use TYPO3\CMS\Core\Utility\MathUtility;
37 use TYPO3\CMS\Core\Utility\PathUtility;
38 use TYPO3\CMS\Lang\LanguageService;
39
40 /**
41 * class for the Element Browser window.
42 *
43 * @author Kasper Skårhøj <kasperYYYY@typo3.com>
44 */
45 class ElementBrowser {
46
47 /**
48 * Optional instance of a record list that TBE_expandPage() should
49 * use to render the records in a page
50 *
51 * @var ElementBrowserRecordList
52 */
53 protected $recordList = NULL;
54
55 /**
56 * Current site URL (Frontend)
57 *
58 * @var string
59 * @internal
60 */
61 public $siteURL;
62
63 /**
64 * the script to link to
65 *
66 * @var string
67 */
68 public $thisScript;
69
70 /**
71 * RTE specific TSconfig
72 *
73 * @var array[]
74 */
75 public $thisConfig;
76
77 /**
78 * Target (RTE specific)
79 *
80 * @var string
81 */
82 public $setTarget;
83
84 /**
85 * CSS Class (RTE specific)
86 *
87 * @var string
88 */
89 public $setClass;
90
91 /**
92 * title (RTE specific)
93 *
94 * @var string
95 */
96 public $setTitle;
97
98 /**
99 * @var string
100 */
101 public $setParams;
102
103 /**
104 * Backend template object
105 *
106 * @var DocumentTemplate
107 */
108 public $doc;
109
110 /**
111 * Holds information about files
112 *
113 * @var mixed[][]
114 */
115 public $elements = array();
116
117 /**
118 * The mode determines the main kind of output from the element browser.
119 * There are these options for values: rte, db, file, filedrag, wizard.
120 * "rte" will show the link selector for the Rich Text Editor (see main_rte())
121 * "db" will allow you to browse for pages or records in the page tree (for TCEforms, see main_db())
122 * "file"/"filedrag" will allow you to browse for files or folders in the folder mounts (for TCEforms, main_file())
123 * "wizard" will allow you to browse for links (like "rte") which are passed back to TCEforms (see main_rte(1))
124 *
125 * @see main()
126 * @var string
127 */
128 public $mode;
129
130 /**
131 * Link selector action.
132 * page,file,url,mail,spec are allowed values.
133 * These are only important with the link selector function and in that case they switch
134 * between the various menu options.
135 *
136 * @var string
137 */
138 public $act;
139
140 /**
141 * When you click a page title/expand icon to see the content of a certain page, this
142 * value will contain that value (the ID of the expanded page). If the value is NOT set,
143 * then it will be restored from the module session data (see main(), mode="db")
144 *
145 * @var NULL|int
146 */
147 public $expandPage;
148
149 /**
150 * When you click a folder name/expand icon to see the content of a certain file folder,
151 * this value will contain that value (the path of the expanded file folder). If the
152 * value is NOT set, then it will be restored from the module session data (see main(),
153 * mode="file"/"filedrag"). Example value: "/www/htdocs/typo3/32/3dsplm/fileadmin/css/"
154 *
155 * @var string
156 */
157 public $expandFolder;
158
159 /**
160 * the folder object of a parent folder that was selected
161 *
162 * @var Folder
163 */
164 protected $selectedFolder;
165
166 /**
167 * TYPO3 Element Browser, wizard mode parameters. There is a heap of parameters there,
168 * better debug() them out if you need something... :-)
169 *
170 * @var array[]
171 */
172 public $P;
173
174 /**
175 * Active with TYPO3 Element Browser: Contains the name of the form field for which this window
176 * opens - thus allows us to make references back to the main window in which the form is.
177 * Example value: "data[pages][39][bodytext]|||tt_content|"
178 * or "data[tt_content][NEW3fba56fde763d][image]|||gif,jpg,jpeg,tif,bmp,pcx,tga,png,pdf,ai|"
179 *
180 * Values:
181 * 0: form field name reference, eg. "data[tt_content][123][image]"
182 * 1: htmlArea RTE parameters: editorNo:contentTypo3Language:contentTypo3Charset
183 * 2: RTE config parameters: RTEtsConfigParams
184 * 3: allowed types. Eg. "tt_content" or "gif,jpg,jpeg,tif,bmp,pcx,tga,png,pdf,ai"
185 * 4: IRRE uniqueness: target level object-id to perform actions/checks on, eg. "data[79][tt_address][1][<field>][<foreign_table>]"
186 * 5: IRRE uniqueness: name of function in opener window that checks if element is already used, eg. "inline.checkUniqueElement"
187 * 6: IRRE uniqueness: name of function in opener window that performs some additional(!) action, eg. "inline.setUniqueElement"
188 * 7: IRRE uniqueness: name of function in opener window that performs action instead of using addElement/insertElement, eg. "inline.importElement"
189 *
190 * $pArr = explode('|', $this->bparams);
191 * $formFieldName = $pArr[0];
192 * $allowedTablesOrFileTypes = $pArr[3];
193 *
194 * @var string
195 */
196 public $bparams;
197
198 /**
199 * Used with the Rich Text Editor.
200 * Example value: "tt_content:NEW3fba58c969f5c:bodytext:23:text:23:"
201 *
202 * @var string
203 */
204 public $RTEtsConfigParams;
205
206 /**
207 * Plus/Minus icon value. Used by the tree class to open/close notes on the trees.
208 *
209 * @var string
210 */
211 public $PM;
212
213 /**
214 * Pointer, used when browsing a long list of records etc.
215 *
216 * @var int
217 */
218 public $pointer;
219
220 /**
221 * Used with the link selector: Contains the GET input information about the CURRENT link
222 * in the RTE/TCEform field. This consists of "href", "target" and "title" keys.
223 * This information is passed around in links.
224 *
225 * @var array[]
226 */
227 public $curUrlArray;
228
229 /**
230 * Used with the link selector: Contains a processed version of the input values from curUrlInfo.
231 * This is splitted into pageid, content element id, label value etc.
232 * This is used for the internal processing of that information.
233 *
234 * @var array[]
235 */
236 public $curUrlInfo;
237
238 /**
239 * array which holds hook objects (initialised in init())
240 *
241 * @var ElementBrowserHookInterface[]
242 */
243 protected $hookObjects = array();
244
245 /**
246 * @var BasicFileUtility
247 */
248 public $fileProcessor;
249
250 /**
251 * Sets the script url depending on being a module or script request
252 */
253 protected function determineScriptUrl() {
254 if ($moduleName = GeneralUtility::_GP('M')) {
255 $this->thisScript = BackendUtility::getModuleUrl($moduleName);
256 } else {
257 $this->thisScript = GeneralUtility::getIndpEnv('SCRIPT_NAME');
258 }
259 }
260
261 /**
262 * Calculate path to this script.
263 * This method is public, to be used in hooks of this class only.
264 *
265 * @return string
266 */
267 public function getThisScript() {
268 return strpos($this->thisScript, '?') === FALSE ? $this->thisScript . '?' : $this->thisScript . '&';
269 }
270
271 /**
272 * Constructor:
273 * Initializes a lot of variables, setting JavaScript functions in header etc.
274 *
275 * @return void
276 * @throws \UnexpectedValueException
277 */
278 public function init() {
279 $this->initVariables();
280
281 $this->RTEtsConfigParams = GeneralUtility::_GP('RTEtsConfigParams');
282 $this->initConfiguration();
283 $this->initDocumentTemplate();
284 // init hook objects:
285 $this->initHookObjects('typo3/class.browse_links.php');
286
287 $this->initCurrentUrl();
288
289 // Determine nature of current url:
290 $this->act = GeneralUtility::_GP('act');
291 if (!$this->act) {
292 $this->act = $this->curUrlInfo['act'];
293 }
294
295 // Initializing the target value (RTE)
296 $this->setTarget = $this->curUrlArray['target'] != '-' ? $this->curUrlArray['target'] : '';
297 if ($this->thisConfig['defaultLinkTarget'] && !isset($this->curUrlArray['target'])) {
298 $this->setTarget = $this->thisConfig['defaultLinkTarget'];
299 }
300 // Initializing the class value (RTE)
301 $this->setClass = $this->curUrlArray['class'] != '-' ? $this->curUrlArray['class'] : '';
302 // Initializing the title value (RTE)
303 $this->setTitle = $this->curUrlArray['title'] != '-' ? $this->curUrlArray['title'] : '';
304 // Initializing the params value
305 $this->setParams = $this->curUrlArray['params'] != '-' ? $this->curUrlArray['params'] : '';
306
307 // Finally, add the accumulated JavaScript to the template object:
308 // also unset the default jumpToUrl() function before
309 unset($this->doc->JScodeArray['jumpToUrl']);
310 $this->doc->JScode .= $this->doc->wrapScriptTags($this->getJSCode());
311 }
312
313 /**
314 * Initialize class variables
315 *
316 * @return void
317 */
318 public function initVariables() {
319 // Main GPvars:
320 $this->pointer = GeneralUtility::_GP('pointer');
321 $this->bparams = GeneralUtility::_GP('bparams');
322 $this->P = GeneralUtility::_GP('P');
323 $this->expandPage = GeneralUtility::_GP('expandPage');
324 $this->expandFolder = GeneralUtility::_GP('expandFolder');
325 $this->PM = GeneralUtility::_GP('PM');
326
327 // Site URL
328 // Current site url
329 $this->siteURL = GeneralUtility::getIndpEnv('TYPO3_SITE_URL');
330 $this->determineScriptUrl();
331
332 // Find "mode"
333 $this->mode = GeneralUtility::_GP('mode');
334 if (!$this->mode) {
335 $this->mode = 'rte';
336 }
337
338 // Init fileProcessor
339 $this->fileProcessor = GeneralUtility::makeInstance(BasicFileUtility::class);
340 $this->fileProcessor->init(array(), $GLOBALS['TYPO3_CONF_VARS']['BE']['fileExtensions']);
341 }
342
343 /**
344 * Initializes the configuration variables
345 *
346 * @return void
347 */
348 public function initConfiguration() {
349 // Rich Text Editor specific configuration:
350 if ((string)$this->mode === 'rte') {
351 $this->thisConfig = $this->getRTEConfig();
352 }
353 }
354
355 /**
356 * Initialize document template object
357 *
358 * @return void
359 */
360 protected function initDocumentTemplate() {
361 // Creating backend template object:
362 $this->doc = GeneralUtility::makeInstance(DocumentTemplate::class);
363 $this->doc->bodyTagId = 'typo3-browse-links-php';
364 $this->doc->backPath = $GLOBALS['BACK_PATH'];
365 $this->doc->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Backend/BrowseLinks');
366 $this->doc->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Backend/LegacyTree');
367 }
368
369 /**
370 * Initialize hook objects implementing the interface
371 *
372 * @param string $hookKey the hook key
373 * @throws \UnexpectedValueException
374 * @return void
375 */
376 protected function initHookObjects($hookKey) {
377 if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS'][$hookKey]['browseLinksHook'])) {
378 foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS'][$hookKey]['browseLinksHook'] as $classData) {
379 $processObject = GeneralUtility::getUserObj($classData);
380 if (!$processObject instanceof ElementBrowserHookInterface) {
381 throw new \UnexpectedValueException('$processObject must implement interface ' . ElementBrowserHookInterface::class, 1195039394);
382 }
383 $parameters = array();
384 $processObject->init($this, $parameters);
385 $this->hookObjects[] = $processObject;
386 }
387 }
388 }
389
390 /**
391 * Initialize $this->curUrlArray and $this->curUrlInfo based on script parameters
392 *
393 * @return void
394 */
395 protected function initCurrentUrl() {
396 // CurrentUrl - the current link url must be passed around if it exists
397 if ($this->mode == 'wizard') {
398 $currentValues = GeneralUtility::trimExplode(LF, trim($this->P['currentValue']));
399 if (count($currentValues) > 0) {
400 $currentValue = array_pop($currentValues);
401 } else {
402 $currentValue = '';
403 }
404 $currentLinkParts = GeneralUtility::unQuoteFilenames($currentValue, TRUE);
405 $initialCurUrlArray = array(
406 'href' => $currentLinkParts[0],
407 'target' => $currentLinkParts[1],
408 'class' => $currentLinkParts[2],
409 'title' => $currentLinkParts[3],
410 'params' => $currentLinkParts[4]
411 );
412 $this->curUrlArray = is_array(GeneralUtility::_GP('curUrl'))
413 ? array_merge($initialCurUrlArray, GeneralUtility::_GP('curUrl'))
414 : $initialCurUrlArray;
415 // Additional fields for page links
416 if (isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/class.browse_links.php']['extendUrlArray'])
417 && is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/class.browse_links.php']['extendUrlArray'])
418 ) {
419 $conf = array();
420 $_params = array(
421 'conf' => &$conf,
422 'linkParts' => $currentLinkParts
423 );
424 foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/class.browse_links.php']['extendUrlArray'] as $objRef) {
425 $processor =& GeneralUtility::getUserObj($objRef);
426 $processor->extendUrlArray($_params, $this);
427 }
428 }
429 $this->curUrlInfo = $this->parseCurUrl($this->siteURL . '?id=' . $this->curUrlArray['href'], $this->siteURL);
430 // pageid == 0 means that this is not an internal (page) link
431 if ($this->curUrlInfo['pageid'] == 0 && $this->curUrlArray['href']) {
432 // Check if there is the FAL API
433 if (GeneralUtility::isFirstPartOfStr($this->curUrlArray['href'], 'file:')) {
434 $this->curUrlInfo = $this->parseCurUrl($this->curUrlArray['href'], $this->siteURL);
435 // Remove the "file:" prefix
436 $currentLinkParts[0] = rawurldecode(substr($this->curUrlArray['href'], 5));
437 } elseif (file_exists(PATH_site . rawurldecode($this->curUrlArray['href']))) {
438 if (GeneralUtility::isFirstPartOfStr($this->curUrlArray['href'], PATH_site)) {
439 $currentLinkParts[0] = PathUtility::stripPathSitePrefix($this->curUrlArray['href']);
440 }
441 $this->curUrlInfo = $this->parseCurUrl($this->siteURL . $this->curUrlArray['href'], $this->siteURL);
442 } elseif (strstr($this->curUrlArray['href'], '@')) {
443 // check for email link
444 if (GeneralUtility::isFirstPartOfStr($this->curUrlArray['href'], 'mailto:')) {
445 $currentLinkParts[0] = substr($this->curUrlArray['href'], 7);
446 }
447 $this->curUrlInfo = $this->parseCurUrl('mailto:' . $this->curUrlArray['href'], $this->siteURL);
448 } else {
449 // nothing of the above. this is an external link
450 if (strpos($this->curUrlArray['href'], '://') === FALSE) {
451 $currentLinkParts[0] = 'http://' . $this->curUrlArray['href'];
452 }
453 $this->curUrlInfo = $this->parseCurUrl($currentLinkParts[0], $this->siteURL);
454 }
455 } elseif (!$this->curUrlArray['href']) {
456 $this->curUrlInfo = array();
457 $this->act = 'page';
458 } else {
459 $this->curUrlInfo = $this->parseCurUrl($this->siteURL . '?id=' . $this->curUrlArray['href'], $this->siteURL);
460 }
461 } else {
462 $this->curUrlArray = GeneralUtility::_GP('curUrl');
463 if ($this->curUrlArray['all']) {
464 $this->curUrlArray = GeneralUtility::get_tag_attributes($this->curUrlArray['all']);
465 }
466 $this->curUrlInfo = $this->parseCurUrl($this->curUrlArray['href'], $this->siteURL);
467 }
468 }
469
470 /**
471 * Get the RTE configuration from Page TSConfig
472 *
473 * @return array[] RTE configuration array
474 */
475 protected function getRTEConfig() {
476 $RTEtsConfigParts = explode(':', $this->RTEtsConfigParams);
477 $RTEsetup = $this->getBackendUserAuthentication()->getTSConfig('RTE', BackendUtility::getPagesTSconfig($RTEtsConfigParts[5]));
478 return BackendUtility::RTEsetup($RTEsetup['properties'], $RTEtsConfigParts[0], $RTEtsConfigParts[2], $RTEtsConfigParts[4]);
479 }
480
481 /**
482 * Generate JS code to be used on the link insert/modify dialogue
483 *
484 * @return string the generated JS code
485 */
486 public function getJsCode() {
487 // Rich Text Editor specific configuration:
488 $addPassOnParams = '';
489 if ((string)$this->mode == 'rte') {
490 $addPassOnParams .= '&RTEtsConfigParams=' . rawurlencode($this->RTEtsConfigParams);
491 }
492 // BEGIN accumulation of header JavaScript:
493 $JScode = '
494 // This JavaScript is primarily for RTE/Link. jumpToUrl is used in the other cases as well...
495 var add_href=' . GeneralUtility::quoteJSvalue($this->curUrlArray['href'] ? '&curUrl[href]=' . rawurlencode($this->curUrlArray['href']) : '') . ';
496 var add_target=' . GeneralUtility::quoteJSvalue($this->setTarget ? '&curUrl[target]=' . rawurlencode($this->setTarget) : '') . ';
497 var add_class=' . GeneralUtility::quoteJSvalue($this->setClass ? '&curUrl[class]=' . rawurlencode($this->setClass) : '') . ';
498 var add_title=' . GeneralUtility::quoteJSvalue($this->setTitle ? '&curUrl[title]=' . rawurlencode($this->setTitle) : '') . ';
499 var add_params=' . GeneralUtility::quoteJSvalue($this->bparams ? '&bparams=' . rawurlencode($this->bparams) : '') . ';
500
501 var cur_href=' . GeneralUtility::quoteJSvalue($this->curUrlArray['href'] ?: '') . ';
502 var cur_target=' . GeneralUtility::quoteJSvalue($this->setTarget ?: '') . ';
503 var cur_class=' . GeneralUtility::quoteJSvalue($this->setClass ?: '') . ';
504 var cur_title=' . GeneralUtility::quoteJSvalue($this->setTitle ?: '') . ';
505 var cur_params=' . GeneralUtility::quoteJSvalue($this->setParams ?: '') . ';
506
507 function browse_links_setTarget(target) { //
508 cur_target=target;
509 add_target="&curUrl[target]="+escape(target);
510 }
511 function browse_links_setClass(cssClass) { //
512 cur_class = cssClass;
513 add_class = "&curUrl[class]=" + escape(cssClass);
514 }
515 function browse_links_setTitle(title) { //
516 cur_title=title;
517 add_title="&curUrl[title]="+escape(title);
518 }
519 function browse_links_setValue(value) { //
520 cur_href=value;
521 add_href="&curUrl[href]="+value;
522 }
523 function browse_links_setParams(params) { //
524 cur_params=params;
525 add_params="&curUrl[params]="+escape(params);
526 }
527 ' . $this->doc->redirectUrls();
528 // Functions used, if the link selector is in wizard mode (= TCEforms fields)
529 if ($this->mode == 'wizard') {
530 if (!$this->areFieldChangeFunctionsValid() && !$this->areFieldChangeFunctionsValid(TRUE)) {
531 $this->P['fieldChangeFunc'] = array();
532 }
533 unset($this->P['fieldChangeFunc']['alert']);
534 $update = '';
535 foreach ($this->P['fieldChangeFunc'] as $v) {
536 $update .= '
537 window.opener.' . $v;
538 }
539 $P2 = array();
540 $P2['uid'] = $this->P['uid'];
541 $P2['pid'] = $this->P['pid'];
542 $P2['itemName'] = $this->P['itemName'];
543 $P2['formName'] = $this->P['formName'];
544 $P2['fieldChangeFunc'] = $this->P['fieldChangeFunc'];
545 $P2['fieldChangeFuncHash'] = GeneralUtility::hmac(serialize($this->P['fieldChangeFunc']));
546 $P2['params']['allowedExtensions'] = isset($this->P['params']['allowedExtensions']) ? $this->P['params']['allowedExtensions'] : '';
547 $P2['params']['blindLinkOptions'] = isset($this->P['params']['blindLinkOptions']) ? $this->P['params']['blindLinkOptions'] : '';
548 $P2['params']['blindLinkFields'] = isset($this->P['params']['blindLinkFields']) ? $this->P['params']['blindLinkFields']: '';
549 $addPassOnParams .= GeneralUtility::implodeArrayForUrl('P', $P2);
550 $JScode .= '
551 function link_typo3Page(id,anchor) { //
552 updateValueInMainForm(id + (anchor ? anchor : ""));
553 close();
554 return false;
555 }
556 function link_folder(folder) { //
557 updateValueInMainForm(folder);
558 close();
559 return false;
560 }
561 function link_current() { //
562 if (cur_href!="http://" && cur_href!="mailto:") {
563 returnBeforeCleaned = cur_href;
564 if (returnBeforeCleaned.substr(0, 7) == "http://") {
565 returnToMainFormValue = returnBeforeCleaned.substr(7);
566 } else if (returnBeforeCleaned.substr(0, 7) == "mailto:") {
567 if (returnBeforeCleaned.substr(0, 14) == "mailto:mailto:") {
568 returnToMainFormValue = returnBeforeCleaned.substr(14);
569 } else {
570 returnToMainFormValue = returnBeforeCleaned.substr(7);
571 }
572 } else {
573 returnToMainFormValue = returnBeforeCleaned;
574 }
575 updateValueInMainForm(returnToMainFormValue);
576 close();
577 }
578 return false;
579 }
580 function checkReference() { //
581 if (window.opener && window.opener.document && window.opener.document.' . $this->P['formName']
582 . ' && window.opener.document.' . $this->P['formName'] . '["' . $this->P['itemName'] . '"] ) {
583 return window.opener.document.' . $this->P['formName'] . '["' . $this->P['itemName'] . '"];
584 } else {
585 close();
586 }
587 }
588 function updateValueInMainForm(input) { //
589 var field = checkReference();
590 if (field) {
591 if (cur_target == "" && (cur_class != "" || cur_title != "" || cur_params != "")) {
592 cur_target = "-";
593 }
594 if (cur_class == "" && (cur_title != "" || cur_params != "")) {
595 cur_class = "-";
596 }
597 cur_class = cur_class.replace(/[\'\\"]/g, "");
598 if (cur_class.indexOf(" ") != -1) {
599 cur_class = "\\"" + cur_class + "\\"";
600 }
601 if (cur_title == "" && cur_params != "") {
602 cur_title = "-";
603 }
604 cur_title = cur_title.replace(/(^\\")|(\\"$)/g, "");
605 if (cur_title.indexOf(" ") != -1) {
606 cur_title = "\\"" + cur_title + "\\"";
607 }
608 if (cur_params) {
609 cur_params = cur_params.replace(/\\bid\\=.*?(\\&|$)/, "");
610 }
611 input = input + " " + cur_target + " " + cur_class + " " + cur_title + " " + cur_params;
612 input = input.replace(/^\s+|\s+$/g, "");
613 if(field.value && field.className.search(/textarea/) != -1) {
614 field.value += "\\n" + input;
615 } else {
616 field.value = input;
617 }
618 field.onchange();
619 ' . $update . '
620 }
621 }
622 ';
623 } else {
624 // Functions used, if the link selector is in RTE mode:
625 $JScode .= '
626 function link_typo3Page(id,anchor) { //
627 var theLink = \'' . $this->siteURL . '?id=\'+id+(anchor?anchor:"");
628 self.parent.parent.renderPopup_addLink(theLink, cur_target, cur_class, cur_title);
629 return false;
630 }
631 function link_folder(folder) { //
632 var theLink = \'' . $this->siteURL . '\'+folder;
633 self.parent.parent.renderPopup_addLink(theLink, cur_target, cur_class, cur_title);
634 return false;
635 }
636 function link_spec(theLink) { //
637 self.parent.parent.renderPopup_addLink(theLink, cur_target, cur_class, cur_title);
638 return false;
639 }
640 function link_current() { //
641 if (cur_href!="http://" && cur_href!="mailto:") {
642 self.parent.parent.renderPopup_addLink(cur_href, cur_target, cur_class, cur_title);
643 }
644 return false;
645 }
646 ';
647 }
648 // General "jumpToUrl" function:
649 $JScode .= '
650 function jumpToUrl(URL,anchor) { //
651 if (URL.charAt(0) === \'?\') {
652 URL = ' . GeneralUtility::quoteJSvalue($this->getThisScript()) . ' + URL.substring(1);
653 }
654 var add_act = URL.indexOf("act=")==-1 ? "&act=' . $this->act . '" : "";
655 var add_mode = URL.indexOf("mode=")==-1 ? "&mode=' . $this->mode . '" : "";
656 var theLocation = URL + add_act + add_mode + add_href + add_target + add_class + add_title + add_params'
657 . ($addPassOnParams ? '+' . GeneralUtility::quoteJSvalue($addPassOnParams) : '')
658 . '+(typeof(anchor)=="string"?anchor:"");
659 window.location.href = theLocation;
660 return false;
661 }
662 ';
663 /**
664 * Splits parts of $this->bparams
665 *
666 * @see $bparams
667 */
668 $pArr = explode('|', $this->bparams);
669 // This is JavaScript especially for the TBE Element Browser!
670 $formFieldName = 'data[' . $pArr[0] . '][' . $pArr[1] . '][' . $pArr[2] . ']';
671 // insertElement - Call check function (e.g. for uniqueness handling):
672 $JScodeCheck = '';
673 if ($pArr[4] && $pArr[5]) {
674 $JScodeCheck = '
675 // Call a check function in the opener window (e.g. for uniqueness handling):
676 if (parent.window.opener) {
677 var res = parent.window.opener.' . $pArr[5] . '("' . addslashes($pArr[4]) . '",table,uid,type);
678 if (!res.passed) {
679 if (res.message) alert(res.message);
680 performAction = false;
681 }
682 } else {
683 alert("Error - reference to main window is not set properly!");
684 parent.close();
685 }
686 ';
687 }
688 // insertElement - Call helper function:
689 $JScodeHelper = '';
690 if ($pArr[4] && $pArr[6]) {
691 $JScodeHelper = '
692 // Call helper function to manage data in the opener window:
693 if (parent.window.opener) {
694 parent.window.opener.' . $pArr[6] . '("' . addslashes($pArr[4]) . '",table,uid,type,"' . addslashes($pArr[0]) . '");
695 } else {
696 alert("Error - reference to main window is not set properly!");
697 parent.close();
698 }
699 ';
700 }
701 // insertElement - perform action commands:
702 $JScodeActionMultiple = '';
703 if ($pArr[4] && $pArr[7]) {
704 // Call user defined action function:
705 $JScodeAction = '
706 if (parent.window.opener) {
707 parent.window.opener.' . $pArr[7] . '("' . addslashes($pArr[4]) . '",table,uid,type);
708 if (close) { focusOpenerAndClose(close); }
709 } else {
710 alert("Error - reference to main window is not set properly!");
711 if (close) { parent.close(); }
712 }
713 ';
714 $JScodeActionMultiple = '
715 // Call helper function to manage data in the opener window:
716 if (parent.window.opener) {
717 parent.window.opener.' . $pArr[7] . 'Multiple("' . addslashes($pArr[4]) . '",table,uid,type,"'
718 . addslashes($pArr[0]) . '");
719 } else {
720 alert("Error - reference to main window is not set properly!");
721 parent.close();
722 }
723 ';
724 } elseif ($pArr[0] && !$pArr[1] && !$pArr[2]) {
725 $JScodeAction = '
726 addElement(filename,table+"_"+uid,fp,close);
727 ';
728 } else {
729 $JScodeAction = '
730 if (setReferences()) {
731 parent.window.opener.group_change("add","' . $pArr[0] . '","' . $pArr[1] . '","' . $pArr[2]
732 . '",elRef,targetDoc);
733 } else {
734 alert("Error - reference to main window is not set properly!");
735 }
736 focusOpenerAndClose(close);
737 ';
738 }
739 $JScode .= '
740 var elRef="";
741 var targetDoc="";
742
743 function launchView(url) { //
744 var thePreviewWindow="";
745 thePreviewWindow = window.open("' . $GLOBALS['BACK_PATH'] . 'show_item.php?table="+url,"ShowItem",'
746 . '"height=300,width=410,status=0,menubar=0,resizable=0,location=0,directories=0,scrollbars=1,toolbar=0");
747 if (thePreviewWindow && thePreviewWindow.focus) {
748 thePreviewWindow.focus();
749 }
750 }
751 function setReferences() { //
752 if (parent.window.opener && parent.window.opener.content && parent.window.opener.content.document.editform'
753 . '&& parent.window.opener.content.document.editform["' . $formFieldName . '"]) {
754 targetDoc = parent.window.opener.content.document;
755 elRef = targetDoc.editform["' . $formFieldName . '"];
756 return true;
757 } else {
758 return false;
759 }
760 }
761 function insertElement(table, uid, type, filename, fp, filetype, imagefile, action, close) { //
762 var performAction = true;
763 ' . $JScodeCheck . '
764 // Call performing function and finish this action:
765 if (performAction) {
766 ' . $JScodeHelper . $JScodeAction . '
767 }
768 return false;
769 }
770 function insertMultiple(table, uid) {
771 var type = "";
772 ' . $JScodeActionMultiple . '
773 return false;
774 }
775 function addElement(elName, elValue, altElValue, close) { //
776 if (parent.window.opener && parent.window.opener.setFormValueFromBrowseWin) {
777 parent.window.opener.setFormValueFromBrowseWin("' . $pArr[0] . '",altElValue?altElValue:elValue,elName);
778 focusOpenerAndClose(close);
779 } else {
780 alert("Error - reference to main window is not set properly!");
781 parent.close();
782 }
783 }
784 function focusOpenerAndClose(close) { //
785 BrowseLinks.focusOpenerAndClose(close);
786 }
787 ';
788 // extends JavaScript code
789 if (isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/class.browse_links.php']['extendJScode'])
790 && is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/class.browse_links.php']['extendJScode'])
791 ) {
792 $conf = array();
793 $update = '';
794 $_params = array(
795 'conf' => &$conf,
796 'wizardUpdate' => $update,
797 'addPassOnParams' => $addPassOnParams
798 );
799 foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/class.browse_links.php']['extendJScode'] as $objRef) {
800 $processor =& GeneralUtility::getUserObj($objRef);
801 $JScode .= $processor->extendJScode($_params, $this);
802 }
803 }
804 return $JScode;
805 }
806
807 /**
808 * Session data for this class can be set from outside with this method.
809 * Call after init()
810 *
811 * @param mixed[] $data Session data array
812 * @return array[] Session data and boolean which indicates that data needs to be stored in session because it's changed
813 */
814 public function processSessionData($data) {
815 $store = FALSE;
816 switch ((string)$this->mode) {
817 case 'db':
818 if (isset($this->expandPage)) {
819 $data['expandPage'] = $this->expandPage;
820 $store = TRUE;
821 } else {
822 $this->expandPage = $data['expandPage'];
823 }
824 break;
825 case 'file':
826
827 case 'filedrag':
828
829 case 'folder':
830 if (isset($this->expandFolder)) {
831 $data['expandFolder'] = $this->expandFolder;
832 $store = TRUE;
833 } else {
834 $this->expandFolder = $data['expandFolder'];
835 }
836 break;
837 }
838 return array($data, $store);
839 }
840
841 /******************************************************************
842 *
843 * Main functions
844 *
845 ******************************************************************/
846 /**
847 * Rich Text Editor (RTE) link selector (MAIN function)
848 * Generates the link selector for the Rich Text Editor.
849 * Can also be used to select links for the TCEforms (see $wiz)
850 *
851 * @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
852 * @return string Modified content variable.
853 */
854 public function main_rte($wiz = FALSE) {
855 // Starting content:
856 $content = $this->doc->startPage('RTE link');
857
858 $allowedItems = $this->getAllowedItems('page,file,folder,url,mail,spec');
859
860 // Removing link fields if configured
861 $blindLinkFields = isset($this->thisConfig['blindLinkFields'])
862 ? GeneralUtility::trimExplode(',', $this->thisConfig['blindLinkFields'], TRUE)
863 : array();
864 $pBlindLinkFields = isset($this->P['params']['blindLinkFields'])
865 ? GeneralUtility::trimExplode(',', $this->P['params']['blindLinkFields'], TRUE)
866 : array();
867 $allowedFields = array_diff(array('target', 'title', 'class', 'params'), $blindLinkFields, $pBlindLinkFields);
868
869 $content .= $this->doc->getTabMenuRaw($this->buildMenuArray($wiz, $allowedItems));
870 // Adding the menu and header to the top of page:
871 $content .= $this->printCurrentUrl($this->curUrlInfo['info']) . '<br />';
872 // Depending on the current action we will create the actual module content for selecting a link:
873 switch ($this->act) {
874 case 'mail':
875 $content .= $this->getEmailSelectorHtml();
876 break;
877 case 'url':
878 $content .= $this->getExternalUrlSelectorHtml();
879 break;
880 case 'file':
881 case 'folder':
882 $content .= $this->getFileSelectorHtml();
883 break;
884 case 'spec':
885 $content .= $this->getUserLinkSelectorHtml();
886 break;
887 case 'page':
888 $content .= $this->getPageSelectorHtml();
889 break;
890 default:
891 // Call hook
892 foreach ($this->hookObjects as $hookObject) {
893 $content .= $hookObject->getTab($this->act);
894 }
895 }
896 $lang = $this->getLanguageService();
897 if (in_array('params', $allowedFields, TRUE)) {
898 $content .= '
899 <!--
900 Selecting params for link:
901 -->
902 <form action="" name="lparamsform" id="lparamsform">
903 <table border="0" cellpadding="2" cellspacing="1" id="typo3-linkParams">
904 <tr>
905 <td style="width: 96px;">' . $lang->getLL('params', TRUE) . '</td>
906 <td><input type="text" name="lparams" class="typo3-link-input" onchange="'
907 . 'browse_links_setParams(this.value);" value="' . htmlspecialchars($this->setParams)
908 . '" /></td>
909 </tr>
910 </table>
911 </form>
912 ';
913 }
914 if (in_array('class', $allowedFields, TRUE)) {
915 $content .= '
916 <!--
917 Selecting class for link:
918 -->
919 <form action="" name="lclassform" id="lclassform">
920 <table border="0" cellpadding="2" cellspacing="1" id="typo3-linkClass">
921 <tr>
922 <td style="width: 96px;">' . $lang->getLL('class', TRUE) . '</td>
923 <td><input type="text" name="lclass" class="typo3-link-input" onchange="'
924 . 'browse_links_setClass(this.value);" value="' . htmlspecialchars($this->setClass)
925 . '" /></td>
926 </tr>
927 </table>
928 </form>
929 ';
930 }
931 if (in_array('title', $allowedFields, TRUE)) {
932 $content .= '
933 <!--
934 Selecting title for link:
935 -->
936 <form action="" name="ltitleform" id="ltitleform">
937 <table border="0" cellpadding="2" cellspacing="1" id="typo3-linkTitle">
938 <tr>
939 <td style="width: 96px;">' . $lang->getLL('title', TRUE) . '</td>
940 <td><input type="text" name="ltitle" class="typo3-link-input" onchange="'
941 . 'browse_links_setTitle(this.value);" value="' . htmlspecialchars($this->setTitle)
942 . '" /></td>
943 </tr>
944 </table>
945 </form>
946 ';
947 }
948 // additional fields for page links
949 if (isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/class.browse_links.php']['addFields_PageLink'])
950 && is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/class.browse_links.php']['addFields_PageLink'])
951 ) {
952 $conf = array();
953 $_params = array(
954 'conf' => &$conf
955 );
956 foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/class.browse_links.php']['addFields_PageLink'] as $objRef) {
957 $processor =& GeneralUtility::getUserObj($objRef);
958 $content .= $processor->addFields($_params, $this);
959 }
960 }
961 // Target:
962 if ($this->act != 'mail' && in_array('target', $allowedFields, TRUE)) {
963 $ltarget = '
964
965 <!--
966 Selecting target for link:
967 -->
968 <form action="" name="ltargetform" id="ltargetform">
969 <table border="0" cellpadding="2" cellspacing="1" id="typo3-linkTarget">
970 <tr>
971 <td>' . $lang->getLL('target', TRUE) . ':</td>
972 <td><input type="text" name="ltarget" onchange="browse_links_setTarget(this.value);" value="'
973 . htmlspecialchars($this->setTarget) . '"' . $this->doc->formWidth(10) . ' /></td>
974 <td>
975 <select name="ltarget_type" onchange="browse_links_setTarget('
976 . 'this.options[this.selectedIndex].value);document.ltargetform.ltarget.value='
977 . 'this.options[this.selectedIndex].value;this.selectedIndex=0;">
978 <option></option>
979 <option value="_top">' . $lang->getLL('top', TRUE) . '</option>
980 <option value="_blank">' . $lang->getLL('newWindow', TRUE) . '</option>
981 </select>
982 </td>
983 <td>';
984 if (($this->curUrlInfo['act'] == 'page' || $this->curUrlInfo['act'] == 'file' || $this->curUrlInfo['act'] == 'folder')
985 && $this->curUrlArray['href'] && $this->curUrlInfo['act'] == $this->act
986 ) {
987 $ltarget .= '
988 <input class="btn btn-default" type="submit" value="' . $lang->getLL('update', TRUE)
989 . '" onclick="return link_current();" />';
990 }
991 $selectJS = '
992 if (document.ltargetform.popup_width.options[document.ltargetform.popup_width.selectedIndex].value>0'
993 . ' && document.ltargetform.popup_height.options[document.ltargetform.popup_height.selectedIndex].value>0) {
994 document.ltargetform.ltarget.value = document.ltargetform.popup_width.options['
995 . 'document.ltargetform.popup_width.selectedIndex].value+"x"'
996 . '+document.ltargetformbrowse_links_setTarget.popup_height.options['
997 . 'document.ltargetform.popup_height.selectedIndex].value;
998 browse_links_setTarget(document.ltargetform.ltarget.value);
999 browse_links_setClass(document.lclassform.lclass.value);
1000 browse_links_setTitle(document.ltitleform.ltitle.value);
1001 browse_links_setParams(document.lparamsform.lparams.value);
1002 document.ltargetform.popup_width.selectedIndex=0;
1003 document.ltargetform.popup_height.selectedIndex=0;
1004 }
1005 ';
1006 $ltarget .= ' </td>
1007 </tr>
1008 <tr>
1009 <td>' . $lang->getLL('target_popUpWindow', TRUE) . ':</td>
1010 <td colspan="3">
1011 <select name="popup_width" onchange="' . htmlspecialchars($selectJS) . '">
1012 <option value="0">' . $lang->getLL('target_popUpWindow_width', TRUE) . '</option>
1013 <option value="300">300</option>
1014 <option value="400">400</option>
1015 <option value="500">500</option>
1016 <option value="600">600</option>
1017 <option value="700">700</option>
1018 <option value="800">800</option>
1019 </select>
1020 x
1021 <select name="popup_height" onchange="' . htmlspecialchars($selectJS) . '">
1022 <option value="0">' . $lang->getLL('target_popUpWindow_height', TRUE) . '</option>
1023 <option value="200">200</option>
1024 <option value="300">300</option>
1025 <option value="400">400</option>
1026 <option value="500">500</option>
1027 <option value="600">600</option>
1028 </select>
1029 </td>
1030 </tr>
1031 </table>
1032 </form>';
1033 // Add "target selector" box to content:
1034 $content .= $ltarget;
1035 // Add some space
1036 $content .= '<br /><br />';
1037 }
1038 // End page, return content:
1039 $content .= $this->doc->endPage();
1040 $content = $this->doc->insertStylesAndJS($content);
1041 return $content;
1042 }
1043
1044 /**
1045 * Get the allowed items or tabs
1046 *
1047 * @param string $items initial list of possible items
1048 * @return array the allowed items
1049 */
1050 public function getAllowedItems($items) {
1051 // Initializing the action value, possibly removing blinded values etc:
1052 $blindLinkOptions = isset($this->thisConfig['blindLinkOptions'])
1053 ? GeneralUtility::trimExplode(',', $this->thisConfig['blindLinkOptions'], TRUE)
1054 : array();
1055 $pBlindLinkOptions = isset($this->P['params']['blindLinkOptions'])
1056 ? GeneralUtility::trimExplode(',', $this->P['params']['blindLinkOptions'])
1057 : array();
1058 $allowedItems = array_diff(explode(',', $items), $blindLinkOptions, $pBlindLinkOptions);
1059
1060 // Call hook for extra options
1061 foreach ($this->hookObjects as $hookObject) {
1062 $allowedItems = $hookObject->addAllowedItems($allowedItems);
1063 }
1064 return $allowedItems;
1065 }
1066
1067 /**
1068 * Returns an array definition of the top menu
1069 *
1070 * @param $wiz
1071 * @param $allowedItems
1072 * @return mixed[][]
1073 */
1074 protected function buildMenuArray($wiz, $allowedItems) {
1075 // Making menu in top:
1076 $menuDef = array();
1077 $lang = $this->getLanguageService();
1078 if (!$wiz) {
1079 $menuDef['removeLink']['isActive'] = $this->act === 'removeLink';
1080 $menuDef['removeLink']['label'] = $lang->getLL('removeLink', TRUE);
1081 $menuDef['removeLink']['url'] = '#';
1082 $menuDef['removeLink']['addParams'] = 'onclick="self.parent.parent.renderPopup_unLink();return false;"';
1083 }
1084 if (in_array('page', $allowedItems)) {
1085 $menuDef['page']['isActive'] = $this->act === 'page';
1086 $menuDef['page']['label'] = $lang->getLL('page', TRUE);
1087 $menuDef['page']['url'] = '#';
1088 $menuDef['page']['addParams'] = 'onclick="jumpToUrl(' . GeneralUtility::quoteJSvalue('?act=page') . ');return false;"';
1089 }
1090 if (in_array('file', $allowedItems)) {
1091 $menuDef['file']['isActive'] = $this->act === 'file';
1092 $menuDef['file']['label'] = $lang->getLL('file', TRUE);
1093 $menuDef['file']['url'] = '#';
1094 $menuDef['file']['addParams'] = 'onclick="jumpToUrl(' . GeneralUtility::quoteJSvalue('?act=file') . ');return false;"';
1095 }
1096 if (in_array('folder', $allowedItems)) {
1097 $menuDef['folder']['isActive'] = $this->act === 'folder';
1098 $menuDef['folder']['label'] = $lang->getLL('folder', TRUE);
1099 $menuDef['folder']['url'] = '#';
1100 $menuDef['folder']['addParams'] = 'onclick="jumpToUrl(' . GeneralUtility::quoteJSvalue('?act=folder') . ');return false;"';
1101 }
1102 if (in_array('url', $allowedItems)) {
1103 $menuDef['url']['isActive'] = $this->act === 'url';
1104 $menuDef['url']['label'] = $lang->getLL('extUrl', TRUE);
1105 $menuDef['url']['url'] = '#';
1106 $menuDef['url']['addParams'] = 'onclick="jumpToUrl(' . GeneralUtility::quoteJSvalue('?act=url') . ');return false;"';
1107 }
1108 if (in_array('mail', $allowedItems)) {
1109 $menuDef['mail']['isActive'] = $this->act === 'mail';
1110 $menuDef['mail']['label'] = $lang->getLL('email', TRUE);
1111 $menuDef['mail']['url'] = '#';
1112 $menuDef['mail']['addParams'] = 'onclick="jumpToUrl(' . GeneralUtility::quoteJSvalue('?act=mail') . ');return false;"';
1113 }
1114 if (is_array($this->thisConfig['userLinks.']) && in_array('spec', $allowedItems)) {
1115 $menuDef['spec']['isActive'] = $this->act === 'spec';
1116 $menuDef['spec']['label'] = $lang->getLL('special', TRUE);
1117 $menuDef['spec']['url'] = '#';
1118 $menuDef['spec']['addParams'] = 'onclick="jumpToUrl(' . GeneralUtility::quoteJSvalue('?act=spec') . ');return false;"';
1119 }
1120 // Call hook for extra options
1121 foreach ($this->hookObjects as $hookObject) {
1122 $menuDef = $hookObject->modifyMenuDefinition($menuDef);
1123 }
1124 return $menuDef;
1125 }
1126
1127 /**
1128 * Returns HTML of the email link from
1129 *
1130 * @return string
1131 */
1132 protected function getEmailSelectorHtml() {
1133 $lang = $this->getLanguageService();
1134 $extUrl = '
1135 <!--
1136 Enter mail address:
1137 -->
1138 <form action="" name="lurlform" id="lurlform">
1139 <table border="0" cellpadding="2" cellspacing="1" id="typo3-linkMail">
1140 <tr>
1141 <td style="width: 96px;">
1142 ' . $lang->getLL('emailAddress', TRUE) . ':
1143 </td>
1144 <td>
1145 <input type="text" name="lemail"' . $this->doc->formWidth(20) . ' value="'
1146 . htmlspecialchars(($this->curUrlInfo['act'] === 'mail' ? $this->curUrlInfo['info'] : ''))
1147 . '" />
1148 <input class="btn btn-default" type="submit" value="' . $lang->getLL('setLink', TRUE)
1149 . '" onclick="browse_links_setTarget(\'\');browse_links_setValue(\'mailto:\'+'
1150 . 'document.lurlform.lemail.value); return link_current();" />
1151 </td>
1152 </tr>
1153 </table>
1154 </form>';
1155 return $extUrl;
1156 }
1157
1158 /**
1159 * Returns HTML of the external url link from
1160 *
1161 * @return string
1162 */
1163 protected function getExternalUrlSelectorHtml() {
1164 $extUrl = '
1165
1166 <!--
1167 Enter External URL:
1168 -->
1169 <form action="" name="lurlform" id="lurlform">
1170 <table border="0" cellpadding="2" cellspacing="1" id="typo3-linkURL">
1171 <tr>
1172 <td style="width: 96px;">URL:</td>
1173 <td><input type="text" name="lurl"' . $this->doc->formWidth(30) . ' value="'
1174 . htmlspecialchars(($this->curUrlInfo['act'] === 'url' ? $this->curUrlInfo['info'] : 'http://'))
1175 . '" /> ' . '<input class="btn btn-default" type="submit" value="' . $this->getLanguageService()->getLL('setLink', TRUE)
1176 . '" onclick="browse_links_setValue(document.lurlform.lurl.value); return link_current();" /></td>
1177 </tr>
1178 </table>
1179 </form>';
1180 return $extUrl;
1181 }
1182
1183 /**
1184 * Returns HTML of the file/folder link selector
1185 *
1186 * @param string $treeClassName
1187 * @return string
1188 */
1189 protected function getFileSelectorHtml($treeClassName = \TYPO3\CMS\Backend\Tree\View\ElementBrowserFolderTreeView::class) {
1190 $folderTree = GeneralUtility::makeInstance($treeClassName);
1191 $folderTree->thisScript = $this->thisScript;
1192 $tree = $folderTree->getBrowsableTree();
1193 $backendUser = $this->getBackendUserAuthentication();
1194 if (!$this->curUrlInfo['value'] || $this->curUrlInfo['act'] != $this->act) {
1195 $cmpPath = '';
1196 } else {
1197 $cmpPath = $this->curUrlInfo['value'];
1198 if (!isset($this->expandFolder)) {
1199 $this->expandFolder = $cmpPath;
1200 }
1201 }
1202 // Create upload/create folder forms, if a path is given
1203 $selectedFolder = FALSE;
1204 if ($this->expandFolder) {
1205 $fileOrFolderObject = NULL;
1206 try {
1207 $fileOrFolderObject = ResourceFactory::getInstance()->retrieveFileOrFolderObject($this->expandFolder);
1208 } catch (\Exception $e) {
1209 // No path is selected
1210 }
1211
1212 if ($fileOrFolderObject instanceof Folder) {
1213 // It's a folder
1214 $selectedFolder = $fileOrFolderObject;
1215 } elseif ($fileOrFolderObject instanceof FileInterface) {
1216 // It's a file
1217 try {
1218 $selectedFolder = $fileOrFolderObject->getParentFolder();
1219 } catch (\Exception $e) {
1220 // Accessing the parent folder failed for some reason. e.g. permissions
1221 }
1222 }
1223 }
1224 // If no folder is selected, get the user's default upload folder
1225 if (!$selectedFolder) {
1226 try {
1227 $selectedFolder = $backendUser->getDefaultUploadFolder();
1228 } catch (\Exception $e) {
1229 // The configured default user folder does not exist
1230 }
1231 }
1232 // Build the file upload and folder creation form
1233 $uploadForm = '';
1234 $createFolder = '';
1235 $content = '';
1236 if ($selectedFolder) {
1237 $uploadForm = ($this->act === 'file') ? $this->uploadForm($selectedFolder) : '';
1238 $createFolder = $this->createFolder($selectedFolder);
1239 }
1240 // Insert the upload form on top, if so configured
1241 if ($backendUser->getTSConfigVal('options.uploadFieldsInTopOfEB')) {
1242 $content .= $uploadForm;
1243 }
1244
1245 // Render the filelist if there is a folder selected
1246 $files = '';
1247 if ($selectedFolder) {
1248 $allowedExtensions = isset($this->P['params']['allowedExtensions']) ? $this->P['params']['allowedExtensions'] : '';
1249 $files = $this->expandFolder($selectedFolder, $allowedExtensions);
1250 }
1251 // Create folder tree:
1252 $this->doc->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Backend/LegacyTree', 'function(Tree) {
1253 Tree.ajaxID = "SC_alt_file_navframe::expandCollapse";
1254 }');
1255 $content .= '
1256 <!--
1257 Wrapper table for folder tree / file/folder list:
1258 -->
1259 <table border="0" cellpadding="0" cellspacing="0" id="typo3-linkFiles">
1260 <tr>
1261 <td class="c-wCell" valign="top">'
1262 . $this->barheader(($this->getLanguageService()->getLL('folderTree') . ':')) . $tree . '</td>
1263 <td class="c-wCell" valign="top">' . $files . '</td>
1264 </tr>
1265 </table>
1266 ';
1267 // Adding create folder + upload form if applicable
1268 if (!$backendUser->getTSConfigVal('options.uploadFieldsInTopOfEB')) {
1269 $content .= $uploadForm;
1270 }
1271 $content .= '<br />' . $createFolder . '<br />';
1272 return $content;
1273 }
1274
1275 /**
1276 * Returns HTML of the user defined link selector
1277 *
1278 * @return string
1279 */
1280 protected function getUserLinkSelectorHtml() {
1281 if (!is_array($this->thisConfig['userLinks.'])) {
1282 return '';
1283 }
1284 $lang = $this->getLanguageService();
1285 $subcats = array();
1286 $v = $this->thisConfig['userLinks.'];
1287 foreach ($v as $k2 => $value) {
1288 $k2i = (int)$k2;
1289 if (substr($k2, -1) === '.' && is_array($v[$k2i . '.'])) {
1290 // Title:
1291 $title = trim($v[$k2i]);
1292 if (!$title) {
1293 $title = $v[$k2i . '.']['url'];
1294 } else {
1295 $title = $lang->sL($title);
1296 }
1297 // Description:
1298 $description = $v[$k2i . '.']['description']
1299 ? $lang->sL($v[($k2i . '.')]['description'], TRUE) . '<br />'
1300 : '';
1301 // URL + onclick event:
1302 $onClickEvent = '';
1303 if (isset($v[$k2i . '.']['target'])) {
1304 $onClickEvent .= 'browse_links_setTarget(' . GeneralUtility::quoteJSvalue($v[($k2i . '.')]['target']) . ');';
1305 }
1306 $v[$k2i . '.']['url'] = str_replace('###_URL###', $this->siteURL, $v[$k2i . '.']['url']);
1307 if (substr($v[$k2i . '.']['url'], 0, 7) === 'http://' || substr($v[$k2i . '.']['url'], 0, 7) === 'mailto:') {
1308 $onClickEvent .= 'cur_href=' . GeneralUtility::quoteJSvalue($v[($k2i . '.')]['url']) . ';link_current();';
1309 } else {
1310 $onClickEvent .= 'link_spec(' . GeneralUtility::quoteJSvalue($this->siteURL . $v[($k2i . '.')]['url']) . ');';
1311 }
1312 // Link:
1313 $A = array('<a href="#" onclick="' . htmlspecialchars($onClickEvent) . 'return false;">', '</a>');
1314 // Adding link to menu of user defined links:
1315 $subcats[$k2i] = '
1316 <tr>
1317 <td class="bgColor4">' . $A[0] . '<strong>' . htmlspecialchars($title)
1318 . ($this->curUrlInfo['info'] == $v[$k2i . '.']['url']
1319 ? '<img' . IconUtility::skinImg(
1320 $GLOBALS['BACK_PATH'],
1321 'gfx/blinkarrow_right.gif',
1322 'width="5" height="9"'
1323 ) . ' class="c-blinkArrowR" alt="" />'
1324 : '')
1325 . '</strong><br />' . $description . $A[1] . '</td>
1326 </tr>';
1327 }
1328 }
1329 // Sort by keys:
1330 ksort($subcats);
1331 // Add menu to content:
1332 $content = '
1333
1334 <!--
1335 Special userdefined menu:
1336 -->
1337 <table border="0" cellpadding="1" cellspacing="1" id="typo3-linkSpecial">
1338 <tr>
1339 <td class="bgColor5" class="c-wCell" valign="top"><strong>'
1340 . $lang->getLL('special', TRUE) . '</strong></td>
1341 </tr>
1342 ' . implode('', $subcats) . '
1343 </table>
1344 ';
1345 return $content;
1346 }
1347
1348 /**
1349 * Returns HTML of the page link selector
1350 *
1351 * @param string $treeClassName name of the class used for page tree rendering
1352 * @return string
1353 */
1354 protected function getPageSelectorHtml($treeClassName = \TYPO3\CMS\Backend\Tree\View\ElementBrowserPageTreeView::class) {
1355 $backendUser = $this->getBackendUserAuthentication();
1356 $pageTree = GeneralUtility::makeInstance($treeClassName);
1357 $pageTree->thisScript = $this->thisScript;
1358 $pageTree->ext_showPageId = $backendUser->getTSConfigVal('options.pageTree.showPageIdWithTitle');
1359 $pageTree->ext_showNavTitle = $backendUser->getTSConfigVal('options.pageTree.showNavTitle');
1360 $pageTree->addField('nav_title');
1361 $tree = $pageTree->getBrowsableTree();
1362 $cElements = $this->expandPage();
1363 $dbmount = $this->getTemporaryTreeMountCancelNotice();
1364 $content = '
1365
1366 <!--
1367 Wrapper table for page tree / record list:
1368 -->
1369 <table border="0" cellpadding="0" cellspacing="0" id="typo3-linkPages">
1370 <tr>
1371 <td class="c-wCell" valign="top">'
1372 . $this->barheader(($this->getLanguageService()->getLL('pageTree') . ':'))
1373 . $dbmount
1374 . $tree . '</td>
1375 <td class="c-wCell" valign="top">' . $cElements . '</td>
1376 </tr>
1377 </table>
1378 ';
1379 return $content;
1380 }
1381
1382 /**
1383 * TYPO3 Element Browser: Showing a page tree and allows you to browse for records
1384 *
1385 * @return string HTML content for the module
1386 */
1387 public function main_db() {
1388 // Starting content:
1389 $content = $this->doc->startPage('TBE record selector');
1390 // Init variable:
1391 $pArr = explode('|', $this->bparams);
1392 $tables = $pArr[3];
1393 $backendUser = $this->getBackendUserAuthentication();
1394
1395 // Making the browsable pagetree:
1396 /** @var \TYPO3\CMS\Recordlist\Tree\View\ElementBrowserPageTreeView $pageTree */
1397 $pageTree = GeneralUtility::makeInstance(\TYPO3\CMS\Recordlist\Tree\View\ElementBrowserPageTreeView::class);
1398 $pageTree->thisScript = $this->thisScript;
1399 $pageTree->ext_pArrPages = $tables === 'pages' ? 1 : 0;
1400 $pageTree->ext_showNavTitle = $backendUser->getTSConfigVal('options.pageTree.showNavTitle');
1401 $pageTree->ext_showPageId = $backendUser->getTSConfigVal('options.pageTree.showPageIdWithTitle');
1402 $pageTree->addField('nav_title');
1403
1404 $withTree = TRUE;
1405 if (($tables !== '') && ($tables !== '*')) {
1406 $tablesArr = GeneralUtility::trimExplode(',', $tables, TRUE);
1407 $onlyRootLevel = TRUE;
1408 foreach ($tablesArr as $currentTable) {
1409 $tableTca = $GLOBALS['TCA'][$currentTable];
1410 if (isset($tableTca)) {
1411 if (!isset($tableTca['ctrl']['rootLevel']) || ((int)$tableTca['ctrl']['rootLevel']) != 1) {
1412 $onlyRootLevel = FALSE;
1413 }
1414 }
1415 }
1416 if ($onlyRootLevel) {
1417 $withTree = FALSE;
1418 // page to work on will be root
1419 $this->expandPage = 0;
1420 }
1421 }
1422
1423 $tree = $pageTree->getBrowsableTree();
1424 // Making the list of elements, if applicable:
1425 $cElements = $this->TBE_expandPage($tables);
1426 // Putting the things together, side by side:
1427 $content .= '
1428
1429 <!--
1430 Wrapper table for page tree / record list:
1431 -->
1432 <table border="0" cellpadding="0" cellspacing="0" id="typo3-EBrecords">
1433 <tr>';
1434 if ($withTree) {
1435 $content .= '<td class="c-wCell" valign="top">'
1436 . $this->barheader(($this->getLanguageService()->getLL('pageTree') . ':'))
1437 . $this->getTemporaryTreeMountCancelNotice()
1438 . $tree . '</td>';
1439 }
1440 $content .= '<td class="c-wCell" valign="top">' . $cElements . '</td>
1441 </tr>
1442 </table>
1443 ';
1444 // Add some space
1445 $content .= '<br /><br />';
1446 // End page, return content:
1447 $content .= $this->doc->endPage();
1448 $content = $this->doc->insertStylesAndJS($content);
1449 return $content;
1450 }
1451
1452 /**
1453 * TYPO3 Element Browser: Showing a folder tree, allowing you to browse for files.
1454 *
1455 * @return string HTML content for the module
1456 */
1457 public function main_file() {
1458 // include JS files and set prefs for foldertree
1459 $this->doc->getDragDropCode('folders', 'Tree.ajaxID = "SC_alt_file_navframe::expandCollapse"');
1460 // Starting content:
1461 $content = $this->doc->startPage('TBE file selector');
1462 // Init variable:
1463 $pArr = explode('|', $this->bparams);
1464 // The key number 3 of the pArr contains the "allowed" string. Disallowed is not passed to
1465 // the element browser at all but only filtered out in TCEMain afterwards
1466 $allowed = $pArr[3];
1467 if ($allowed !== 'sys_file' && $allowed !== '*' && !empty($allowed)) {
1468 $allowedFileExtensions = $allowed;
1469 }
1470 $backendUser = $this->getBackendUserAuthentication();
1471
1472 if (isset($allowedFileExtensions)) {
1473 // Create new filter object
1474 $filterObject = GeneralUtility::makeInstance(FileExtensionFilter::class);
1475 $filterObject->setAllowedFileExtensions($allowedFileExtensions);
1476 // Set file extension filters on all storages
1477 $storages = $backendUser->getFileStorages();
1478 /** @var $storage \TYPO3\CMS\Core\Resource\ResourceStorage */
1479 foreach ($storages as $storage) {
1480 $storage->addFileAndFolderNameFilter(array($filterObject, 'filterFileList'));
1481 }
1482 }
1483 // Create upload/create folder forms, if a path is given
1484 $this->selectedFolder = FALSE;
1485 if ($this->expandFolder) {
1486 $fileOrFolderObject = NULL;
1487
1488 // Try to fetch the folder the user had open the last time he browsed files
1489 // Fallback to the default folder in case the last used folder is not existing
1490 try {
1491 $fileOrFolderObject = ResourceFactory::getInstance()->retrieveFileOrFolderObject($this->expandFolder);
1492 } catch (Exception $accessException) {
1493 // We're just catching the exception here, nothing to be done if folder does not exist or is not accessible.
1494 }
1495
1496 if ($fileOrFolderObject instanceof Folder) {
1497 // It's a folder
1498 $this->selectedFolder = $fileOrFolderObject;
1499 } elseif ($fileOrFolderObject instanceof FileInterface) {
1500 // It's a file
1501 $this->selectedFolder = $fileOrFolderObject->getParentFolder();
1502 }
1503 }
1504 // Or get the user's default upload folder
1505 if (!$this->selectedFolder) {
1506 try {
1507 $this->selectedFolder = $backendUser->getDefaultUploadFolder();
1508 } catch (\Exception $e) {
1509 // The configured default user folder does not exist
1510 }
1511 }
1512 // Build the file upload and folder creation form
1513 $uploadForm = '';
1514 $createFolder = '';
1515 if ($this->selectedFolder) {
1516 $uploadForm = $this->uploadForm($this->selectedFolder);
1517 $createFolder = $this->createFolder($this->selectedFolder);
1518 }
1519 // Insert the upload form on top, if so configured
1520 if ($backendUser->getTSConfigVal('options.uploadFieldsInTopOfEB')) {
1521 $content .= $uploadForm;
1522 }
1523 // Getting flag for showing/not showing thumbnails:
1524 $noThumbs = $backendUser->getTSConfigVal('options.noThumbsInEB');
1525 $_MOD_SETTINGS = array();
1526 if (!$noThumbs) {
1527 // MENU-ITEMS, fetching the setting for thumbnails from File>List module:
1528 $_MOD_MENU = array('displayThumbs' => '');
1529 $_MCONF['name'] = 'file_list';
1530 $_MOD_SETTINGS = BackendUtility::getModuleData($_MOD_MENU, GeneralUtility::_GP('SET'), $_MCONF['name']);
1531 }
1532 $noThumbs = $noThumbs ?: !$_MOD_SETTINGS['displayThumbs'];
1533 // Create folder tree:
1534 /** @var \TYPO3\CMS\Recordlist\Tree\View\ElementBrowserFolderTreeView $folderTree */
1535 $folderTree = GeneralUtility::makeInstance(\TYPO3\CMS\Recordlist\Tree\View\ElementBrowserFolderTreeView::class);
1536 $folderTree->thisScript = $this->thisScript;
1537 $folderTree->ext_noTempRecyclerDirs = $this->mode == 'filedrag';
1538 $tree = $folderTree->getBrowsableTree();
1539 if ($this->selectedFolder) {
1540 if ($this->mode == 'filedrag') {
1541 $files = $this->TBE_dragNDrop($this->selectedFolder, $pArr[3]);
1542 } else {
1543 $files = $this->TBE_expandFolder($this->selectedFolder, $pArr[3], $noThumbs);
1544 }
1545 } else {
1546 $files = '';
1547 }
1548 // Add the FlashMessages if any
1549 $content .= $this->doc->getFlashMessages();
1550
1551 // Putting the parts together, side by side:
1552 $content .= '
1553
1554 <!--
1555 Wrapper table for folder tree / file list:
1556 -->
1557 <table border="0" cellpadding="0" cellspacing="0" id="typo3-EBfiles">
1558 <tr>
1559 <td class="c-wCell" valign="top">' . $this->barheader(($this->getLanguageService()->getLL('folderTree') . ':'))
1560 . $tree . '</td>
1561 <td class="c-wCell" valign="top">' . $files . '</td>
1562 </tr>
1563 </table>
1564 ';
1565 // Adding create folder + upload forms if applicable:
1566 if (!$backendUser->getTSConfigVal('options.uploadFieldsInTopOfEB')) {
1567 $content .= $uploadForm;
1568 }
1569 $content .= $createFolder;
1570 // Add some space
1571 $content .= '<br /><br />';
1572 // Setup indexed elements:
1573 $this->doc->JScode .= $this->doc->wrapScriptTags('
1574 require(["TYPO3/CMS/Backend/BrowseLinks"], function(BrowseLinks) {
1575 BrowseLinks.addElements(' . json_encode($this->elements) . ');
1576 });');
1577 // Ending page, returning content:
1578 $content .= $this->doc->endPage();
1579 $content = $this->doc->insertStylesAndJS($content);
1580 return $content;
1581 }
1582
1583 /**
1584 * TYPO3 Element Browser: Showing a folder tree, allowing you to browse for folders.
1585 *
1586 * @return string HTML content for the module
1587 */
1588 public function main_folder() {
1589 // include JS files
1590 // Setting prefs for foldertree
1591 $this->doc->getDragDropCode('folders', 'Tree.ajaxID = "SC_alt_file_navframe::expandCollapse";');
1592 // Starting content:
1593 $content = $this->doc->startPage('TBE folder selector');
1594 // Init variable:
1595 $parameters = explode('|', $this->bparams);
1596 if ($this->expandFolder) {
1597 $this->selectedFolder = ResourceFactory::getInstance()->getFolderObjectFromCombinedIdentifier($this->expandFolder);
1598 }
1599 if ($this->selectedFolder) {
1600 $createFolder = $this->createFolder($this->selectedFolder);
1601 } else {
1602 $createFolder = '';
1603 }
1604 // Create folder tree:
1605 /** @var \TYPO3\CMS\Recordlist\Tree\View\ElementBrowserFolderTreeView $folderTree */
1606 $folderTree = GeneralUtility::makeInstance(\TYPO3\CMS\Recordlist\Tree\View\ElementBrowserFolderTreeView::class);
1607 $folderTree->thisScript = $this->thisScript;
1608 $folderTree->ext_noTempRecyclerDirs = $this->mode == 'filedrag';
1609 $tree = $folderTree->getBrowsableTree(FALSE);
1610 $folders = '';
1611 if ($this->selectedFolder) {
1612 if ($this->mode == 'filedrag') {
1613 $folders = $this->TBE_dragNDrop($this->selectedFolder, $parameters[3]);
1614 } else {
1615 $folders = $this->TBE_expandSubFolders($this->selectedFolder);
1616 }
1617 }
1618 // Putting the parts together, side by side:
1619 $content .= '
1620
1621 <!--
1622 Wrapper table for folder tree / folder list:
1623 -->
1624 <table border="0" cellpadding="0" cellspacing="0" id="typo3-EBfiles">
1625 <tr>
1626 <td class="c-wCell" valign="top">' . $this->barheader(($this->getLanguageService()->getLL('folderTree') . ':'))
1627 . $tree . '</td>
1628 <td class="c-wCell" valign="top">' . $folders . '</td>
1629 </tr>
1630 </table>
1631 ';
1632 // Adding create folder if applicable:
1633 $content .= $createFolder;
1634 // Add some space
1635 $content .= '<br /><br />';
1636 // Ending page, returning content:
1637 $content .= $this->doc->endPage();
1638 $content = $this->doc->insertStylesAndJS($content);
1639 return $content;
1640 }
1641
1642 /******************************************************************
1643 *
1644 * Record listing
1645 *
1646 ******************************************************************/
1647 /**
1648 * For RTE: This displays all content elements on a page and lets you create a link to the element.
1649 *
1650 * @return string HTML output. Returns content only if the ->expandPage value is set (pointing to a page uid to show tt_content records from ...)
1651 */
1652 public function expandPage() {
1653 $out = '';
1654 // Set page id (if any) to expand
1655 $expPageId = $this->expandPage;
1656 // If there is an anchor value (content element reference) in the element reference, then force an ID to expand:
1657 if (!$this->expandPage && $this->curUrlInfo['cElement']) {
1658 // Set to the current link page id.
1659 $expPageId = $this->curUrlInfo['pageid'];
1660 }
1661 // Draw the record list IF there is a page id to expand:
1662 if ($expPageId
1663 && MathUtility::canBeInterpretedAsInteger($expPageId)
1664 && $this->getBackendUserAuthentication()->isInWebMount($expPageId)
1665 ) {
1666 // Set header:
1667 $out .= $this->barheader($this->getLanguageService()->getLL('contentElements') . ':');
1668 // Create header for listing, showing the page title/icon:
1669 $mainPageRec = BackendUtility::getRecordWSOL('pages', $expPageId);
1670 $db = $this->getDatabaseConnection();
1671 $picon = IconUtility::getSpriteIconForRecord('pages', $mainPageRec);
1672 $picon .= BackendUtility::getRecordTitle('pages', $mainPageRec, TRUE);
1673 $out .= $picon . '<br />';
1674 // Look up tt_content elements from the expanded page:
1675 $res = $db->exec_SELECTquery(
1676 'uid,header,hidden,starttime,endtime,fe_group,CType,colPos,bodytext',
1677 'tt_content',
1678 'pid=' . (int)$expPageId . BackendUtility::deleteClause('tt_content')
1679 . BackendUtility::versioningPlaceholderClause('tt_content'),
1680 '',
1681 'colPos,sorting'
1682 );
1683 $cc = $db->sql_num_rows($res);
1684 // Traverse list of records:
1685 $c = 0;
1686 while ($row = $db->sql_fetch_assoc($res)) {
1687 $c++;
1688 $icon = IconUtility::getSpriteIconForRecord('tt_content', $row);
1689 if ($this->curUrlInfo['act'] == 'page' && $this->curUrlInfo['cElement'] == $row['uid']) {
1690 $arrCol = '<img' . IconUtility::skinImg($GLOBALS['BACK_PATH'], 'gfx/blinkarrow_left.gif', 'width="5" height="9"')
1691 . ' class="c-blinkArrowL" alt="" />';
1692 } else {
1693 $arrCol = '';
1694 }
1695 // Putting list element HTML together:
1696 $out .= '<img' . IconUtility::skinImg($GLOBALS['BACK_PATH'], ('gfx/ol/join' . ($c == $cc ? 'bottom' : '')
1697 . '.gif'), 'width="18" height="16"') . ' alt="" />' . $arrCol
1698 . '<a href="#" onclick="return link_typo3Page(\'' . $expPageId . '\',\'#' . $row['uid'] . '\');">'
1699 . $icon . BackendUtility::getRecordTitle('tt_content', $row, TRUE) . '</a><br />';
1700 // Finding internal anchor points:
1701 if (GeneralUtility::inList('text,textpic', $row['CType'])) {
1702 $split = preg_split('/(<a[^>]+name=[\'"]?([^"\'>[:space:]]+)[\'"]?[^>]*>)/i', $row['bodytext'], -1, PREG_SPLIT_DELIM_CAPTURE);
1703 foreach ($split as $skey => $sval) {
1704 if ($skey % 3 == 2) {
1705 // Putting list element HTML together:
1706 $sval = substr($sval, 0, 100);
1707 $out .= '<img' . IconUtility::skinImg($GLOBALS['BACK_PATH'], 'gfx/ol/line.gif',
1708 'width="18" height="16"') . ' alt="" />'
1709 . '<img' . IconUtility::skinImg($GLOBALS['BACK_PATH'], ('gfx/ol/join'
1710 . ($skey + 3 > count($split) ? 'bottom' : '') . '.gif'), 'width="18" height="16"')
1711 . ' alt="" />' . '<a href="#" onclick="return link_typo3Page(' . GeneralUtility::quoteJSvalue($expPageId)
1712 . ',' . GeneralUtility::quoteJSvalue('#' . $sval) . ');">' . htmlspecialchars((' <A> ' . $sval))
1713 . '</a><br />';
1714 }
1715 }
1716 }
1717 }
1718 }
1719 return $out;
1720 }
1721
1722 /**
1723 * For TYPO3 Element Browser: This lists all content elements from the given list of tables
1724 *
1725 * @param string $tables Comma separated list of tables. Set to "*" if you want all tables.
1726 * @return string HTML output.
1727 */
1728 public function TBE_expandPage($tables) {
1729 $backendUser = $this->getBackendUserAuthentication();
1730 if (!MathUtility::canBeInterpretedAsInteger($this->expandPage)
1731 || $this->expandPage < 0
1732 || !$backendUser->isInWebMount($this->expandPage)
1733 ) {
1734 return '';
1735 }
1736 // Set array with table names to list:
1737 if (trim($tables) === '*') {
1738 $tablesArr = array_keys($GLOBALS['TCA']);
1739 } else {
1740 $tablesArr = GeneralUtility::trimExplode(',', $tables, TRUE);
1741 }
1742 reset($tablesArr);
1743 // Headline for selecting records:
1744 $out = $this->barheader($this->getLanguageService()->getLL('selectRecords') . ':');
1745 // Create the header, showing the current page for which the listing is.
1746 // Includes link to the page itself, if pages are amount allowed tables.
1747 $titleLen = (int)$backendUser->uc['titleLen'];
1748 $mainPageRec = BackendUtility::getRecordWSOL('pages', $this->expandPage);
1749 $ATag = '';
1750 $ATag_e = '';
1751 $ATag2 = '';
1752 $picon = '';
1753 if (is_array($mainPageRec)) {
1754 $picon = IconUtility::getSpriteIconForRecord('pages', $mainPageRec);
1755 if (in_array('pages', $tablesArr)) {
1756 $ATag = '<a href="#" onclick="return insertElement(\'pages\', \'' . $mainPageRec['uid'] . '\', \'db\', '
1757 . GeneralUtility::quoteJSvalue($mainPageRec['title']) . ', \'\', \'\', \'\',\'\',1);">';
1758 $ATag2 = '<a href="#" onclick="return insertElement(\'pages\', \'' . $mainPageRec['uid'] . '\', \'db\', '
1759 . GeneralUtility::quoteJSvalue($mainPageRec['title']) . ', \'\', \'\', \'\',\'\',0);">';
1760 $ATag_e = '</a>';
1761 }
1762 }
1763 $pBicon = $ATag2 ? '<img'
1764 . IconUtility::skinImg($GLOBALS['BACK_PATH'], 'gfx/plusbullet2.gif', 'width="18" height="16"')
1765 . ' alt="" />' : '';
1766 $pText = htmlspecialchars(GeneralUtility::fixed_lgd_cs($mainPageRec['title'], $titleLen));
1767 $out .= $picon . $ATag2 . $pBicon . $ATag_e . $ATag . $pText . $ATag_e . '<br />';
1768 // Initialize the record listing:
1769 $id = $this->expandPage;
1770 $pointer = MathUtility::forceIntegerInRange($this->pointer, 0, 100000);
1771 $perms_clause = $backendUser->getPagePermsClause(1);
1772 $pageInfo = BackendUtility::readPageAccess($id, $perms_clause);
1773 // Generate the record list:
1774 /** @var $dbList ElementBrowserRecordList */
1775 if (is_object($this->recordList)) {
1776 $dbList = $this->recordList;
1777 } else {
1778 $dbList = GeneralUtility::makeInstance(ElementBrowserRecordList::class);
1779 }
1780 $dbList->thisScript = $this->thisScript;
1781 $dbList->backPath = $GLOBALS['BACK_PATH'];
1782 $dbList->thumbs = 0;
1783 $dbList->calcPerms = $backendUser->calcPerms($pageInfo);
1784 $dbList->noControlPanels = 1;
1785 $dbList->clickMenuEnabled = 0;
1786 $dbList->tableList = implode(',', $tablesArr);
1787 $pArr = explode('|', $this->bparams);
1788 // a string like "data[pages][79][storage_pid]"
1789 $fieldPointerString = $pArr[0];
1790 // parts like: data, pages], 79], storage_pid]
1791 $fieldPointerParts = explode('[', $fieldPointerString);
1792 $relatingTableName = substr($fieldPointerParts[1], 0, -1);
1793 $relatingFieldName = substr($fieldPointerParts[3], 0, -1);
1794 if ($relatingTableName && $relatingFieldName) {
1795 $dbList->setRelatingTableAndField($relatingTableName, $relatingFieldName);
1796 }
1797 $dbList->start($id, GeneralUtility::_GP('table'), $pointer, GeneralUtility::_GP('search_field'),
1798 GeneralUtility::_GP('search_levels'), GeneralUtility::_GP('showLimit')
1799 );
1800 $dbList->setDispFields();
1801 $dbList->generateList();
1802 $out .= $dbList->getSearchBox();
1803 $out .= "<script>document.getElementById('db_list-searchbox-toolbar').style.display = 'block';document.getElementById('db_list-searchbox-toolbar').style.position = 'relative';</script>";
1804
1805 // Add the HTML for the record list to output variable:
1806 $out .= $dbList->HTMLcode;
1807 // Add support for fieldselectbox in singleTableMode
1808 if ($dbList->table) {
1809 $out .= $dbList->fieldSelectBox($dbList->table);
1810 }
1811
1812 // Return accumulated content:
1813 return $out;
1814 }
1815
1816 /**
1817 * Render list of folders inside a folder.
1818 *
1819 * @param Folder $folder Folder
1820 * @return string HTML output
1821 */
1822 public function TBE_expandSubFolders(Folder $folder) {
1823 $content = '';
1824 if ($folder->checkActionPermission('read')) {
1825 $content .= $this->folderList($folder);
1826 }
1827 // Return accumulated content for folderlisting:
1828 return $content;
1829 }
1830
1831 /******************************************************************
1832 *
1833 * File listing
1834 *
1835 ******************************************************************/
1836 /**
1837 * For RTE: This displays all files from folder. No thumbnails shown
1838 *
1839 * @param Folder $folder The folder path to expand
1840 * @param string $extensionList List of file extensions to show
1841 * @return string HTML output
1842 */
1843 public function expandFolder(Folder $folder, $extensionList = '') {
1844 if (!$folder->checkActionPermission('read')) {
1845 return '';
1846 }
1847 $lang = $this->getLanguageService();
1848 $renderFolders = $this->act === 'folder';
1849 // Create header for file/folder listing:
1850 if ($renderFolders) {
1851 $out = $this->barheader($lang->getLL('folders') . ':');
1852 } else {
1853 $out = $this->barheader($lang->getLL('files') . ':');
1854 }
1855 // Prepare current path value for comparison (showing red arrow)
1856 $currentIdentifier = '';
1857 if ($this->curUrlInfo['value']) {
1858 $currentIdentifier = $this->curUrlInfo['info'];
1859 }
1860 // Create header element; The folder from which files are listed.
1861 $titleLen = (int)$this->getBackendUserAuthentication()->uc['titleLen'];
1862 $folderIcon = IconUtility::getSpriteIconForResource($folder);
1863 $folderIcon .= htmlspecialchars(GeneralUtility::fixed_lgd_cs($folder->getIdentifier(), $titleLen));
1864 $picon = '<a href="#" title="' . htmlspecialchars($folder->getIdentifier()) . '" onclick="return link_folder(\'file:' . $folder->getCombinedIdentifier() . '\');">'
1865 . $folderIcon . '</a>';
1866 if ($this->curUrlInfo['act'] == 'folder' && $currentIdentifier == $folder->getCombinedIdentifier()) {
1867 $out .= '<img'
1868 . IconUtility::skinImg($GLOBALS['BACK_PATH'], 'gfx/blinkarrow_left.gif', 'width="5" height="9"')
1869 . ' class="c-blinkArrowL" alt="" />';
1870 }
1871 $out .= $picon . '<br />';
1872 // Get files from the folder:
1873 if ($renderFolders) {
1874 $items = $folder->getSubfolders();
1875 } else {
1876 $items = $this->getFilesInFolder($folder, $extensionList);
1877 }
1878 $c = 0;
1879 $totalItems = count($items);
1880 foreach ($items as $fileOrFolderObject) {
1881 $c++;
1882 if ($renderFolders) {
1883 $fileIdentifier = $fileOrFolderObject->getCombinedIdentifier();
1884 $overlays = array();
1885 if ($fileOrFolderObject instanceof InaccessibleFolder) {
1886 $overlays = array('status-overlay-locked' => array());
1887 }
1888 $icon = IconUtility::getSpriteIcon(
1889 IconUtility::mapFileExtensionToSpriteIconName('folder'),
1890 array('title' => $fileOrFolderObject->getName()),
1891 $overlays);
1892 $itemUid = 'file:' . $fileIdentifier;
1893 } else {
1894 $fileIdentifier = $fileOrFolderObject->getUid();
1895 // Get size and icon:
1896 $size = ' (' . GeneralUtility::formatSize($fileOrFolderObject->getSize()) . 'bytes)';
1897 $icon = IconUtility::getSpriteIconForResource($fileOrFolderObject, array('title' => $fileOrFolderObject->getName() . $size));
1898 $itemUid = 'file:' . $fileIdentifier;
1899 }
1900 // If the listed file turns out to be the CURRENT file, then show blinking arrow:
1901 if (($this->curUrlInfo['act'] == 'file' || $this->curUrlInfo['act'] == 'folder')
1902 && $currentIdentifier == $fileIdentifier
1903 ) {
1904 $arrCol = '<img' . IconUtility::skinImg($GLOBALS['BACK_PATH'], 'gfx/blinkarrow_left.gif',
1905 'width="5" height="9"') . ' class="c-blinkArrowL" alt="" />';
1906 } else {
1907 $arrCol = '';
1908 }
1909 // Put it all together for the file element:
1910 $out .=
1911 '<img' .
1912 IconUtility::skinImg(
1913 $GLOBALS['BACK_PATH'],
1914 ('gfx/ol/join' . ($c == $totalItems ? 'bottom' : '') . '.gif'),
1915 'width="18" height="16"'
1916 ) . ' alt="" />' . $arrCol .
1917 '<a href="#" title="' . htmlspecialchars($fileOrFolderObject->getName()) . '" onclick="return link_folder(\'' . $itemUid . '\');">' .
1918 $icon .
1919 htmlspecialchars(GeneralUtility::fixed_lgd_cs($fileOrFolderObject->getName(), $titleLen)) .
1920 '</a><br />';
1921 }
1922 return $out;
1923 }
1924
1925 /**
1926 * For TYPO3 Element Browser: Expand folder of files.
1927 *
1928 * @param Folder $folder The folder path to expand
1929 * @param string $extensionList List of fileextensions to show
1930 * @param bool $noThumbs Whether to show thumbnails or not. If set, no thumbnails are shown.
1931 * @return string HTML output
1932 */
1933 public function TBE_expandFolder(Folder $folder, $extensionList = '', $noThumbs = FALSE) {
1934 if (!$folder->checkActionPermission('read')) {
1935 return '';
1936 }
1937 $extensionList = $extensionList == '*' ? '' : $extensionList;
1938 $files = $this->getFilesInFolder($folder, $extensionList);
1939 return $this->fileList($files, $folder, $noThumbs);
1940 }
1941
1942 /**
1943 * Render list of files.
1944 *
1945 * @param File[] $files List of files
1946 * @param Folder $folder If set a header with a folder icon and folder name are shown
1947 * @param bool $noThumbs Whether to show thumbnails or not. If set, no thumbnails are shown.
1948 * @return string HTML output
1949 */
1950 protected function fileList(array $files, Folder $folder = NULL, $noThumbs = FALSE) {
1951 $out = '';
1952
1953 $lang = $this->getLanguageService();
1954 $lines = array();
1955 // Create headline (showing number of files):
1956 $filesCount = count($files);
1957 $out .= $this->barheader(sprintf($lang->getLL('files') . ' (%s):', $filesCount));
1958 $out .= '<div id="filelist">';
1959 $out .= $this->getBulkSelector($filesCount);
1960 $titleLen = (int)$this->getBackendUserAuthentication()->uc['titleLen'];
1961 // Create the header of current folder:
1962 if ($folder) {
1963 $folderIcon = IconUtility::getSpriteIconForResource($folder);
1964 $lines[] = '<tr class="t3-row-header">
1965 <td colspan="4">' . $folderIcon
1966 . htmlspecialchars(GeneralUtility::fixed_lgd_cs($folder->getIdentifier(), $titleLen)) . '</td>
1967 </tr>';
1968 }
1969 if ($filesCount == 0) {
1970 $lines[] = '
1971 <tr class="file_list_normal">
1972 <td colspan="4">No files found.</td>
1973 </tr>';
1974 }
1975 // Traverse the file list:
1976 /** @var $fileObject \TYPO3\CMS\Core\Resource\File */
1977 foreach ($files as $fileObject) {
1978 $fileExtension = $fileObject->getExtension();
1979 // Thumbnail/size generation:
1980 $imgInfo = array();
1981 if (GeneralUtility::inList(strtolower($GLOBALS['TYPO3_CONF_VARS']['GFX']['imagefile_ext']), strtolower($fileExtension)) && !$noThumbs) {
1982 $imageUrl = $fileObject->process(
1983 ProcessedFile::CONTEXT_IMAGEPREVIEW,
1984 array('width' => 64, 'height' => 64)
1985 )->getPublicUrl(TRUE);
1986 $imgInfo = array(
1987 $fileObject->getProperty('width'),
1988 $fileObject->getProperty('height')
1989 );
1990 $pDim = $imgInfo[0] . 'x' . $imgInfo[1] . ' pixels';
1991 $clickIcon = '<img src="' . $imageUrl . '" hspace="5" vspace="5" border="1" />';
1992 } else {
1993 $clickIcon = '';
1994 $pDim = '';
1995 }
1996 // Create file icon:
1997 $size = ' (' . GeneralUtility::formatSize($fileObject->getSize()) . 'bytes' . ($pDim ? ', ' . $pDim : '') . ')';
1998 $icon = IconUtility::getSpriteIconForResource($fileObject, array('title' => $fileObject->getName() . $size));
1999 // Create links for adding the file:
2000 $filesIndex = count($this->elements);
2001 $this->elements['file_' . $filesIndex] = array(
2002 'type' => 'file',
2003 'table' => 'sys_file',
2004 'uid' => $fileObject->getUid(),
2005 'fileName' => $fileObject->getName(),
2006 'filePath' => $fileObject->getUid(),
2007 'fileExt' => $fileExtension,
2008 'fileIcon' => $icon
2009 );
2010 if ($this->fileIsSelectableInFileList($fileObject, $imgInfo)) {
2011 $ATag = '<a href="#" title="' . htmlspecialchars($fileObject->getName()) . '" onclick="return BrowseLinks.File.insertElement(\'file_' . $filesIndex . '\');">';
2012 $ATag_alt = substr($ATag, 0, -4) . ',1);">';
2013 $bulkCheckBox = '<input type="checkbox" class="typo3-bulk-item" name="file_' . $filesIndex . '" value="0" /> ';
2014 $ATag_e = '</a>';
2015 } else {
2016 $ATag = '';
2017 $ATag_alt = '';
2018 $ATag_e = '';
2019 $bulkCheckBox = '';
2020 }
2021 // Create link to showing details about the file in a window:
2022 $Ahref = $GLOBALS['BACK_PATH'] . 'show_item.php?type=file&table=_FILE&uid='
2023 . rawurlencode($fileObject->getCombinedIdentifier())
2024 . '&returnUrl=' . rawurlencode(GeneralUtility::getIndpEnv('REQUEST_URI'));
2025 $ATag2 = '<a href="' . htmlspecialchars($Ahref) . '">';
2026 $ATag2_e = '</a>';
2027 // Combine the stuff:
2028 $filenameAndIcon = $bulkCheckBox . $ATag_alt . $icon
2029 . htmlspecialchars(GeneralUtility::fixed_lgd_cs($fileObject->getName(), $titleLen)) . $ATag_e;
2030 // Show element:
2031 if ($pDim) {
2032 // Image...
2033 $lines[] = '
2034 <tr class="file_list_normal">
2035 <td nowrap="nowrap">' . $filenameAndIcon . '&nbsp;</td>
2036 <td>' . ($ATag . '<img' . IconUtility::skinImg($GLOBALS['BACK_PATH'], 'gfx/plusbullet2.gif',
2037 'width="18" height="16"') . ' title="' . $lang->getLL('addToList', TRUE)
2038 . '" alt="" />' . $ATag_e) . '</td>
2039 <td nowrap="nowrap">' . ($ATag2 . '<img' . IconUtility::skinImg($GLOBALS['BACK_PATH'],
2040 'gfx/zoom2.gif', 'width="12" height="12"') . ' title="'
2041 . $lang->getLL('info', TRUE) . '" alt="" /> '
2042 . $lang->getLL('info', TRUE) . $ATag2_e) . '</td>
2043 <td nowrap="nowrap">&nbsp;' . $pDim . '</td>
2044 </tr>';
2045 $lines[] = '
2046 <tr>
2047 <td class="filelistThumbnail" colspan="4">' . $ATag_alt . $clickIcon . $ATag_e . '</td>
2048 </tr>';
2049 } else {
2050 $lines[] = '
2051 <tr class="file_list_normal">
2052 <td nowrap="nowrap">' . $filenameAndIcon . '&nbsp;</td>
2053 <td>' . ($ATag . '<img' . IconUtility::skinImg($GLOBALS['BACK_PATH'], 'gfx/plusbullet2.gif',
2054 'width="18" height="16"') . ' title="' . $lang->getLL('addToList', TRUE)
2055 . '" alt="" />' . $ATag_e) . '</td>
2056 <td nowrap="nowrap">' . ($ATag2 . '<img' . IconUtility::skinImg($GLOBALS['BACK_PATH'],
2057 'gfx/zoom2.gif', 'width="12" height="12"') . ' title="'
2058 . $lang->getLL('info', TRUE) . '" alt="" /> '
2059 . $lang->getLL('info', TRUE) . $ATag2_e) . '</td>
2060 <td>&nbsp;</td>
2061 </tr>';
2062 }
2063 }
2064 // Wrap all the rows in table tags:
2065 $out .= '
2066
2067 <!--
2068 File listing
2069 -->
2070 <table cellpadding="0" cellspacing="0" id="typo3-filelist">
2071 ' . implode('', $lines) . '
2072 </table>';
2073 // Return accumulated content for file listing:
2074 $out .= '</div>';
2075 return $out;
2076 }
2077
2078 /**
2079 * Checks if the given file is selectable in the file list.
2080 *
2081 * By default all files are selectable. This method may be overwritten in child classes.
2082 *
2083 * @param FileInterface $file
2084 * @param mixed[] $imgInfo Image dimensions from \TYPO3\CMS\Core\Imaging\GraphicalFunctions::getImageDimensions()
2085 * @return bool TRUE if file is selectable.
2086 */
2087 protected function fileIsSelectableInFileList(FileInterface $file, array $imgInfo) {
2088 return TRUE;
2089 }
2090
2091 /**
2092 * Render list of folders.
2093 *
2094 * @param Folder $baseFolder
2095 * @return string HTML output
2096 */
2097 public function folderList(Folder $baseFolder) {
2098 $content = '';
2099 $lang = $this->getLanguageService();
2100 $folders = $baseFolder->getSubfolders();
2101 $folderIdentifier = $baseFolder->getCombinedIdentifier();
2102 // Create headline (showing number of folders):
2103 $content .= $this->barheader(sprintf($lang->getLL('folders') . ' (%s):', count($folders)));
2104 $titleLength = (int)$this->getBackendUserAuthentication()->uc['titleLen'];
2105 // Create the header of current folder:
2106 $aTag = '<a href="#" onclick="return insertElement(\'\',' . GeneralUtility::quoteJSvalue($folderIdentifier)
2107 . ', \'folder\', ' . GeneralUtility::quoteJSvalue($folderIdentifier) . ', ' . GeneralUtility::quoteJSvalue($folderIdentifier)
2108 . ', \'\', \'\',\'\',1);">';
2109 // Add the foder icon
2110 $folderIcon = $aTag;
2111 $folderIcon .= '<img' . IconUtility::skinImg($GLOBALS['BACK_PATH'], 'gfx/i/_icon_webfolders.gif',
2112 'width="18" height="16"') . ' alt="" />';
2113 $folderIcon .= htmlspecialchars(GeneralUtility::fixed_lgd_cs($baseFolder->getName(), $titleLength));
2114 $folderIcon .= '</a>';
2115 $content .= $folderIcon . '<br />';
2116
2117 $lines = array();
2118 // Traverse the folder list:
2119 foreach ($folders as $subFolder) {
2120 $subFolderIdentifier = $subFolder->getCombinedIdentifier();
2121 // Create folder icon:
2122 $icon = '<img src="clear.gif" width="16" height="16" alt="" /><img'
2123 . IconUtility::skinImg($GLOBALS['BACK_PATH'], 'gfx/i/_icon_webfolders.gif',
2124 'width="16" height="16"') . ' title="' . htmlspecialchars($subFolder->getName())
2125 . '" class="absmiddle" alt="" />';
2126 // Create links for adding the folder:
2127 if ($this->P['itemName'] != '' && $this->P['formName'] != '') {
2128 $aTag = '<a href="#" onclick="return set_folderpath(' . GeneralUtility::quoteJSvalue($subFolderIdentifier)
2129 . ');">';
2130 } else {
2131 $aTag = '<a href="#" onclick="return insertElement(\'\',' . GeneralUtility::quoteJSvalue($subFolderIdentifier)
2132 . ', \'folder\', ' . GeneralUtility::quoteJSvalue($subFolderIdentifier) . ', '
2133 . GeneralUtility::quoteJSvalue($subFolderIdentifier) . ', \'\', \'\');">';
2134 }
2135 if (strstr($subFolderIdentifier, ',') || strstr($subFolderIdentifier, '|')) {
2136 // In case an invalid character is in the filepath, display error message:
2137 $errorMessage = GeneralUtility::quoteJSvalue(sprintf($lang->getLL('invalidChar'), ', |'));
2138 $aTag = ($aTag_alt = '<a href="#" onclick="alert(' . $errorMessage . ');return false;">');
2139 } else {
2140 // If foldername is OK, just add it:
2141 $aTag_alt = substr($aTag, 0, -4) . ',\'\',1);">';
2142 }
2143 $aTag_e = '</a>';
2144 // Combine icon and folderpath:
2145 $foldernameAndIcon = $aTag_alt . $icon
2146 . htmlspecialchars(GeneralUtility::fixed_lgd_cs($subFolder->getName(), $titleLength)) . $aTag_e;
2147 if ($this->P['itemName'] != '') {
2148 $lines[] = '
2149 <tr class="bgColor4">
2150 <td nowrap="nowrap">' . $foldernameAndIcon . '&nbsp;</td>
2151 <td>&nbsp;</td>
2152 </tr>';
2153 } else {
2154 $lines[] = '
2155 <tr class="bgColor4">
2156 <td nowrap="nowrap">' . $foldernameAndIcon . '&nbsp;</td>
2157 <td>' . $aTag . '<img' . IconUtility::skinImg($GLOBALS['BACK_PATH'], 'gfx/plusbullet2.gif',
2158 'width="18" height="16"') . ' title="' . $lang->getLL('addToList', TRUE)
2159 . '" alt="" />' . $aTag_e . ' </td>
2160 <td>&nbsp;</td>
2161 </tr>';
2162 }
2163 $lines[] = '
2164 <tr>
2165 <td colspan="3"><img src="clear.gif" width="1" height="3" alt="" /></td>
2166 </tr>';
2167 }
2168 // Wrap all the rows in table tags:
2169 $content .= '
2170
2171 <!--
2172 Folder listing
2173 -->
2174 <table border="0" cellpadding="0" cellspacing="1" id="typo3-folderList">
2175 ' . implode('', $lines) . '
2176 </table>';
2177 // Return accumulated content for folderlisting:
2178 return $content;
2179 }
2180
2181 /**
2182 * For RTE: This displays all IMAGES (gif,png,jpg) (from extensionList) from folder. Thumbnails are shown for images.
2183 * This listing is of images located in the web-accessible paths ONLY - the listing is for drag-n-drop use in the RTE
2184 *
2185 * @param Folder $folder The folder path to expand
2186 * @param string $extensionList List of file extensions to show
2187 * @return string HTML output
2188 */
2189 public function TBE_dragNDrop(Folder $folder, $extensionList = '') {
2190 if (!$folder) {
2191 return '';
2192 }
2193 $lang = $this->getLanguageService();
2194 if (!$folder->getStorage()->isPublic()) {
2195 // Print this warning if the folder is NOT a web folder
2196 return $this->barheader($lang->getLL('files'))
2197 . $this->getMsgBox($lang->getLL('noWebFolder'), 'icon_warning2');
2198 }
2199 $out = '';
2200
2201 // Read files from directory:
2202 $extensionList = $extensionList == '*' ? '' : $extensionList;
2203 $files = $this->getFilesInFolder($folder, $extensionList);
2204
2205 $out .= $this->barheader(sprintf($lang->getLL('files') . ' (%s):', count($files)));
2206 $titleLen = (int)$this->getBackendUserAuthentication()->uc['titleLen'];
2207 $picon = '<img' . IconUtility::skinImg($GLOBALS['BACK_PATH'], 'gfx/i/_icon_webfolders.gif', 'width="18" height="16"') . ' alt="" />';
2208 $picon .= htmlspecialchars(GeneralUtility::fixed_lgd_cs(basename($folder->getName()), $titleLen));
2209 $out .= $picon . '<br />';
2210 // Init row-array:
2211 $lines = array();
2212 // Add "drag-n-drop" message:
2213 $lines[] = '
2214 <tr>
2215 <td colspan="2">' . $this->getMsgBox($lang->getLL('findDragDrop')) . '</td>
2216 </tr>';
2217 // Traverse files:
2218 foreach ($files as $fileObject) {
2219 // URL of image:
2220 $iUrl = GeneralUtility::rawurlencodeFP($fileObject->getPublicUrl(TRUE));
2221 // Show only web-images
2222 $fileExtension = strtolower($fileObject->getExtension());
2223 if (GeneralUtility::inList('gif,jpeg,jpg,png', $fileExtension)) {
2224 $imgInfo = array(
2225 $fileObject->getProperty('width'),
2226 $fileObject->getProperty('height')
2227 );
2228 $pDim = $imgInfo[0] . 'x' . $imgInfo[1] . ' pixels';
2229 $size = ' (' . GeneralUtility::formatSize($fileObject->getSize()) . 'bytes' . ($pDim ? ', ' . $pDim : '') . ')';
2230 $filenameAndIcon = IconUtility::getSpriteIconForResource($fileObject, array('title' => $fileObject->getName() . $size));
2231 if (GeneralUtility::_GP('noLimit')) {
2232 $maxW = 10000;
2233 $maxH = 10000;
2234 } else {
2235 $maxW = 380;
2236 $maxH = 500;
2237 }
2238 $IW = $imgInfo[0];
2239 $IH = $imgInfo[1];
2240 if ($IW > $maxW) {
2241 $IH = ceil($IH / $IW * $maxW);
2242 $IW = $maxW;
2243 }
2244 if ($IH > $maxH) {
2245 $IW = ceil($IW / $IH * $maxH);
2246 $IH = $maxH;
2247 }
2248 // Make row:
2249 $lines[] = '
2250 <tr class="bgColor4">
2251 <td nowrap="nowrap">' . $filenameAndIcon . '&nbsp;</td>
2252 <td nowrap="nowrap">' . ($imgInfo[0] != $IW
2253 ? '<a href="' . htmlspecialchars(GeneralUtility::linkThisScript(array('noLimit' => '1')))
2254 . '">' . '<img' . IconUtility::skinImg($GLOBALS['BACK_PATH'], 'gfx/icon_warning2.gif',
2255 'width="18" height="16"') . ' title="'
2256 . $lang->getLL('clickToRedrawFullSize', TRUE) . '" alt="" />' . '</a>'
2257 : '')
2258 . $pDim . '&nbsp;</td>
2259 </tr>';
2260 $lines[] = '
2261 <tr>
2262 <td colspan="2"><img src="' . htmlspecialchars($iUrl) . '" data-htmlarea-file-uid="' . $fileObject->getUid()
2263 . '" width="' . htmlspecialchars($IW) . '" height="' . htmlspecialchars($IH) . '" border="1" alt="" /></td>
2264 </tr>';
2265 $lines[] = '
2266 <tr>
2267 <td colspan="2"><img src="clear.gif" width="1" height="3" alt="" /></td>
2268 </tr>';
2269 }
2270 }
2271 // Finally, wrap all rows in a table tag:
2272 $out .= '
2273
2274
2275 <!--
2276 File listing / Drag-n-drop
2277 -->
2278 <table border="0" cellpadding="0" cellspacing="1" id="typo3-dragBox">
2279 ' . implode('', $lines) . '
2280 </table>';
2281
2282 return $out;
2283 }
2284
2285 /******************************************************************
2286 *
2287 * Miscellaneous functions
2288 *
2289 ******************************************************************/
2290
2291 /**
2292 * Prints a 'header' where string is in a tablecell
2293 *
2294 * @param string $str The string to print in the header. The value is htmlspecialchars()'ed before output.
2295 * @return string The header HTML (wrapped in a table)
2296 */
2297 public function barheader($str) {
2298 return '
2299 <!-- Bar header: -->
2300 <h3>' . htmlspecialchars($str) . '</h3>
2301 ';
2302 }
2303
2304 /**
2305 * Displays a message box with the input message
2306 *
2307 * @param string $in_msg Input message to show (will be htmlspecialchars()'ed inside of this function)
2308 * @param string $icon Icon filename body from gfx/ (default is "icon_note") - meant to allow change to warning type icons...
2309 * @return string HTML for the message (wrapped in a table).
2310 */
2311 public function getMsgBox($in_msg, $icon = 'icon_note') {
2312 $msg = '<img' . IconUtility::skinImg($GLOBALS['BACK_PATH'], ('gfx/' . $icon . '.gif'), 'width="18" height="16"')
2313 . ' alt="" />' . htmlspecialchars($in_msg);
2314 $msg = '
2315
2316 <!--
2317 Message box:
2318 -->
2319 <table cellspacing="0" class="bgColor4" id="typo3-msgBox">
2320 <tr>
2321 <td>' . $msg . '</td>
2322 </tr>
2323 </table>
2324 ';
2325 return $msg;
2326 }
2327
2328 /**
2329 * For RTE/link: This prints the 'currentUrl'
2330 *
2331 * @param string $str URL value. The value is htmlspecialchars()'ed before output.
2332 * @return string HTML content, wrapped in a table.
2333 */
2334 public function printCurrentUrl($str) {
2335 // Output the folder or file identifier, when working with files
2336 if (isset($str) && MathUtility::canBeInterpretedAsInteger($str)) {
2337 try {
2338 $fileObject = ResourceFactory::getInstance()->retrieveFileOrFolderObject($str);
2339 } catch (Exception\FileDoesNotExistException $e) {
2340 $fileObject = NULL;
2341 }
2342 $str = is_object($fileObject) ? $fileObject->getIdentifier() : '';
2343 }
2344 if ($str !== '') {
2345 return '
2346 <!-- Print current URL -->
2347 <table border="0" cellpadding="0" cellspacing="0" id="typo3-curUrl">
2348 <tr>
2349 <td>' . $this->getLanguageService()->getLL('currentLink', TRUE) . ': '
2350 . htmlspecialchars(rawurldecode($str)) . '</td>
2351 </tr>
2352 </table>';
2353 } else {
2354 return '';
2355 }
2356 }
2357
2358 /**
2359 * For RTE/link: Parses the incoming URL and determines if it's a page, file, external or mail address.
2360 *
2361 * @param string $href HREF value tp analyse
2362 * @param string $siteUrl The URL of the current website (frontend)
2363 * @return array[] Array with URL information stored in assoc. keys: value, act (page, file, spec, mail), pageid, cElement, info
2364 */
2365 public function parseCurUrl($href, $siteUrl) {
2366 $href = trim($href);
2367 $lang = $this->getLanguageService();
2368 if ($href) {
2369 $info = array();
2370 // Default is "url":
2371 $info['value'] = $href;
2372 $info['act'] = 'url';
2373 $specialParts = explode('#_SPECIAL', $href);
2374 // Special kind (Something RTE specific: User configurable links through: "userLinks." from ->thisConfig)
2375 if (count($specialParts) == 2) {
2376 $info['value'] = '#_SPECIAL' . $specialParts[1];
2377 $info['act'] = 'spec';
2378 } elseif (strpos($href, 'file:') !== FALSE) {
2379 $rel = substr($href, strpos($href, 'file:') + 5);
2380 $rel = rawurldecode($rel);
2381 // resolve FAL-api "file:UID-of-sys_file-record" and "file:combined-identifier"
2382 $fileOrFolderObject = ResourceFactory::getInstance()->retrieveFileOrFolderObject($rel);
2383 if ($fileOrFolderObject instanceof Folder) {
2384 $info['act'] = 'folder';
2385 $info['value'] = $fileOrFolderObject->getCombinedIdentifier();
2386 } elseif ($fileOrFolderObject instanceof File) {
2387 $info['act'] = 'file';
2388 $info['value'] = $fileOrFolderObject->getUid();
2389 } else {
2390 $info['value'] = $rel;
2391 }
2392 } elseif (GeneralUtility::isFirstPartOfStr($href, $siteUrl)) {
2393 // If URL is on the current frontend website:
2394 // URL is a file, which exists:
2395 if (file_exists(PATH_site . rawurldecode($href))) {
2396 $info['value'] = rawurldecode($href);
2397 if (@is_dir((PATH_site . $info['value']))) {
2398 $info['act'] = 'folder';
2399 } else {
2400 $info['act'] = 'file';
2401 }
2402 } else {
2403 // URL is a page (id parameter)
2404 $uP = parse_url($href);
2405
2406 $pp = preg_split('/^id=/', $uP['query']);
2407 $pp[1] = preg_replace('/&id=[^&]*/', '', $pp[1]);
2408 $parameters = explode('&', $pp[1]);
2409 $id = array_shift($parameters);
2410 if ($id) {
2411 // Checking if the id-parameter is an alias.
2412 if (!MathUtility::canBeInterpretedAsInteger($id)) {
2413 list($idPartR) = BackendUtility::getRecordsByField('pages', 'alias', $id);
2414 $id = (int)$idPartR['uid'];
2415 }
2416 $pageRow = BackendUtility::getRecordWSOL('pages', $id);
2417 $titleLen = (int)$this->getBackendUserAuthentication()->uc['titleLen'];
2418 $info['value'] = ((((($lang->getLL('page', TRUE) . ' \'')
2419 . htmlspecialchars(GeneralUtility::fixed_lgd_cs($pageRow['title'], $titleLen)))
2420 . '\' (ID:') . $id) . ($uP['fragment'] ? ', #' . $uP['fragment'] : '')) . ')';
2421 $info['pageid'] = $id;
2422 $info['cElement'] = $uP['fragment'];
2423 $info['act'] = 'page';
2424 $info['query'] = $parameters[0] ? '&' . implode('&', $parameters) : '';
2425 }
2426 }
2427 } else {
2428 // Email link:
2429 if (strtolower(substr($href, 0, 7)) === 'mailto:') {
2430 $info['value'] = trim(substr($href, 7));
2431 $info['act'] = 'mail';
2432 }
2433 }
2434 $info['info'] = $info['value'];
2435 } else {
2436 // NO value input:
2437 $info = array();
2438 $info['info'] = $lang->getLL('none');
2439 $info['value'] = '';
2440 $info['act'] = 'page';
2441 }
2442 // let the hook have a look
2443 foreach ($this->hookObjects as $hookObject) {
2444 $info = $hookObject->parseCurrentUrl($href, $siteUrl, $info);
2445 }
2446 return $info;
2447 }
2448
2449 /**
2450 * Setter for the class that should be used by TBE_expandPage() to generate the record list.
2451 * This method is intended to be used by Extensions that implement their own browsing functionality.
2452 *
2453 * @param ElementBrowserRecordList $recordList
2454 * @throws \InvalidArgumentException
2455 * @return void
2456 * @api
2457 */
2458 public function setRecordList($recordList) {
2459 if (!$recordList instanceof ElementBrowserRecordList) {
2460 throw new \InvalidArgumentException('$recordList needs to be an instance of ' . ElementBrowserRecordList::class, 1370878522);
2461 }
2462 $this->recordList = $recordList;
2463 }
2464
2465 /**
2466 * For TBE: Makes an upload form for uploading files to the filemount the user is browsing.
2467 * The files are uploaded to the tce_file.php script in the core which will handle the upload.
2468 *
2469 * @param Folder $folderObject Absolute filepath on server to which to upload.
2470 * @return string HTML for an upload form.
2471 */
2472 public function uploadForm(Folder $folderObject) {
2473 if (!$folderObject->checkActionPermission('write')) {
2474 return '';
2475 }
2476 // Read configuration of upload field count
2477 $userSetting = $this->getBackendUserAuthentication()->getTSConfigVal('options.folderTree.uploadFieldsInLinkBrowser');
2478 $count = isset($userSetting) ? $userSetting : 1;
2479 if ($count === '0') {
2480 return '';
2481 }
2482 $count = (int)$count === 0 ? 1 : (int)$count;
2483 // Create header, showing upload path:
2484 $header = $folderObject->getIdentifier();
2485 $lang = $this->getLanguageService();
2486 $code = '
2487 <br />
2488 <!--
2489 Form, for uploading files:
2490 -->
2491 <form action="' . htmlspecialchars(BackendUtility::getModuleUrl('tce_file', array(), $GLOBALS['BACK_PATH'])) . '" method="post" name="editform"'
2492 . ' id="typo3-uplFilesForm" enctype="' . $GLOBALS['TYPO3_CONF_VARS']['SYS']['form_enctype'] . '">
2493 <table border="0" cellpadding="0" cellspacing="0" id="typo3-uplFiles">
2494 <tr>
2495 <td>' . $this->barheader($lang->sL(
2496 'LLL:EXT:lang/locallang_core.xlf:file_upload.php.pagetitle', TRUE) . ':') . '</td>
2497 </tr>
2498 <tr>
2499 <td class="c-wCell c-hCell"><strong>' . $lang->getLL('path', TRUE) . ':</strong> '
2500 . htmlspecialchars($header) . '</td>
2501 </tr>
2502 <tr>
2503 <td class="c-wCell c-hCell">';
2504 // Traverse the number of upload fields (default is 3):
2505 for ($a = 1; $a <= $count; $a++) {
2506 $code .= '<input type="file" multiple="multiple" name="upload_' . $a . '[]"' . $this->doc->formWidth(35)
2507 . ' size="50" />
2508 <input type="hidden" name="file[upload][' . $a . '][target]" value="'
2509 . htmlspecialchars($folderObject->getCombinedIdentifier()) . '" />
2510 <input type="hidden" name="file[upload][' . $a . '][data]" value="' . $a . '" /><br />';
2511 }
2512 // Make footer of upload form, including the submit button:
2513 $redirectValue = $this->getThisScript() . 'act=' . $this->act . '&mode=' . $this->mode
2514 . '&expandFolder=' . rawurlencode($folderObject->getCombinedIdentifier())
2515 . '&bparams=' . rawurlencode($this->bparams)
2516 . (is_array($this->P) ? GeneralUtility::implodeArrayForUrl('P', $this->P) : '');
2517 $code .= '<input type="hidden" name="redirect" value="' . htmlspecialchars($redirectValue) . '" />';
2518 $code .= FormEngine::getHiddenTokenField('tceAction');
2519 $code .= '
2520 <div id="c-override">
2521 <label>
2522 <input type="checkbox" name="overwriteExistingFiles" id="overwriteExistingFiles" value="1" /> '
2523 . $lang->sL('LLL:EXT:lang/locallang_misc.xlf:overwriteExistingFiles', TRUE) . '
2524 </label>
2525 </div>
2526 <input class="btn btn-default" type="submit" name="submit" value="'
2527 . $lang->sL('LLL:EXT:lang/locallang_core.xlf:file_upload.php.submit', TRUE) . '" />
2528 ';
2529 $code .= '</td>
2530 </tr>
2531 </table>
2532 </form><br />';
2533 return $code;
2534 }
2535
2536 /**
2537 * For TBE: Makes a form for creating new folders in the filemount the user is browsing.
2538 * The folder creation request is sent to the tce_file.php script in the core which will handle the creation.
2539 *
2540 * @param Folder $folderObject Absolute filepath on server in which to create the new folder.
2541 * @return string HTML for the create folder form.
2542 */
2543 public function createFolder(Folder $folderObject) {
2544 if (!$folderObject->checkActionPermission('write')) {
2545 return '';
2546 }
2547 $backendUser = $this->getBackendUserAuthentication();
2548 if (!($backendUser->isAdmin() || $backendUser->getTSConfigVal('options.createFoldersInEB'))) {
2549 return '';
2550 }
2551 // Don't show Folder-create form if it's denied
2552 if ($backendUser->getTSConfigVal('options.folderTree.hideCreateFolder')) {
2553 return '';
2554 }
2555 $lang = $this->getLanguageService();
2556 // Create header, showing upload path:
2557 $header = $folderObject->getIdentifier();
2558 $code = '
2559
2560 <!--
2561 Form, for creating new folders:
2562 -->
2563 <form action="' . htmlspecialchars(BackendUtility::getModuleUrl('tce_file', array(), $GLOBALS['BACK_PATH'])) . '" method="post" name="editform2" id="typo3-crFolderForm">
2564 <table border="0" cellpadding="0" cellspacing="0" id="typo3-crFolder">
2565 <tr>
2566 <td>' . $this->barheader($lang->sL(
2567 'LLL:EXT:lang/locallang_core.xlf:file_newfolder.php.pagetitle') . ':') . '</td>
2568 </tr>
2569 <tr>
2570 <td class="c-wCell c-hCell"><strong>'
2571 . $lang->getLL('path', TRUE) . ':</strong> ' . htmlspecialchars($header) . '</td>
2572 </tr>
2573 <tr>
2574 <td class="c-wCell c-hCell">';
2575 // Create the new-folder name field:
2576 $a = 1;
2577 $code .= '<input' . $this->doc->formWidth(20) . ' type="text" name="file[newfolder][' . $a . '][data]" />'
2578 . '<input type="hidden" name="file[newfolder][' . $a . '][target]" value="'
2579 . htmlspecialchars($folderObject->getCombinedIdentifier()) . '" />';
2580 // Make footer of upload form, including the submit button:
2581 $redirectValue = $this->getThisScript() . 'act=' . $this->act . '&mode=' . $this->mode
2582 . '&expandFolder=' . rawurlencode($folderObject->getCombinedIdentifier())
2583 . '&bparams=' . rawurlencode($this->bparams);
2584 $code .= '<input type="hidden" name="redirect" value="' . htmlspecialchars($redirectValue) . '" />'
2585 . FormEngine::getHiddenTokenField('tceAction')
2586 . '<input class="btn btn-default" type="submit" name="submit" value="'
2587 . $lang->sL('LLL:EXT:lang/locallang_core.xlf:file_newfolder.php.submit', TRUE) . '" />';
2588 $code .= '</td>
2589 </tr>
2590 </table>
2591 </form>';
2592 return $code;
2593 }
2594
2595 /**
2596 * Get the HTML data required for a bulk selection of files of the TYPO3 Element Browser.
2597 *
2598 * @param int $filesCount Number of files currently displayed
2599 * @return string HTML data required for a bulk selection of files - if $filesCount is 0, nothing is returned
2600 */
2601 public function getBulkSelector($filesCount) {
2602 if (!$filesCount) {
2603 return '';
2604 }
2605
2606 $lang = $this->getLanguageService();
2607 $labelToggleSelection = $lang->sL('LLL:EXT:lang/locallang_browse_links.xlf:toggleSelection', TRUE);
2608 $labelImportSelection = $lang->sL('LLL:EXT:lang/locallang_browse_links.xlf:importSelection', TRUE);
2609 // Getting flag for showing/not showing thumbnails:
2610 $noThumbsInEB = $this->getBackendUserAuthentication()->getTSConfigVal('options.noThumbsInEB');
2611 $out = $this->doc->spacer(10) . '<div>' . '<a href="#" onclick="BrowseLinks.Selector.handle()">'
2612 . '<img' . IconUtility::skinImg($GLOBALS['BACK_PATH'], 'gfx/import.gif', 'width="12" height="12"')
2613 . ' title="' . $labelImportSelection . '" alt="" /> ' . $labelImportSelection . '</a>&nbsp;&nbsp;&nbsp;'
2614 . '<a href="#" onclick="BrowseLinks.Selector.toggle()">' . '<img'
2615 . IconUtility::skinImg($GLOBALS['BACK_PATH'], 'gfx/clip_select.gif', 'width="12" height="12"')
2616 . ' title="' . $labelToggleSelection . '" alt="" /> ' . $labelToggleSelection . '</a>' . '</div>';
2617 if (!$noThumbsInEB && $this->selectedFolder) {
2618 // MENU-ITEMS, fetching the setting for thumbnails from File>List module:
2619 $_MOD_MENU = array('displayThumbs' => '');
2620 $_MCONF['name'] = 'file_list';
2621 $_MOD_SETTINGS = BackendUtility::getModuleData($_MOD_MENU, GeneralUtility::_GP('SET'), $_MCONF['name']);
2622 $addParams = '&act=' . $this->act . '&mode=' . $this->mode
2623 . '&expandFolder=' . rawurlencode($this->selectedFolder->getCombinedIdentifier())
2624 . '&bparams=' . rawurlencode($this->bparams);
2625 $thumbNailCheck = BackendUtility::getFuncCheck('', 'SET[displayThumbs]', $_MOD_SETTINGS['displayThumbs'],
2626 GeneralUtility::_GP('M') ? '' : $this->thisScript, $addParams, 'id="checkDisplayThumbs"')
2627 . ' <label for="checkDisplayThumbs">'
2628 . $lang->sL('LLL:EXT:lang/locallang_mod_file_list.xlf:displayThumbs', TRUE) . '</label>';
2629 $out .= $this->doc->spacer(5) . $thumbNailCheck . $this->doc->spacer(15);
2630 } else {
2631 $out .= $this->doc->spacer(15);
2632 }
2633 return $out;
2634 }
2635
2636 /**
2637 * Determines whether submitted field change functions are valid
2638 * and are coming from the system and not from an external abuse.
2639 *
2640 * @param bool $handleFlexformSections Whether to handle flexform sections differently
2641 * @return bool Whether the submitted field change functions are valid
2642 */
2643 protected function areFieldChangeFunctionsValid($handleFlexformSections = FALSE) {
2644 $result = FALSE;
2645 if (isset($this->P['fieldChangeFunc']) && is_array($this->P['fieldChangeFunc']) && isset($this->P['fieldChangeFuncHash'])) {
2646 $matches = array();
2647 $pattern = '#\\[el\\]\\[(([^]-]+-[^]-]+-)(idx\\d+-)([^]]+))\\]#i';
2648 $fieldChangeFunctions = $this->P['fieldChangeFunc'];
2649 // Special handling of flexform sections:
2650 // Field change functions are modified in JavaScript, thus the hash is always invalid
2651 if ($handleFlexformSections && preg_match($pattern, $this->P['itemName'], $matches)) {
2652 $originalName = $matches[1];
2653 $cleanedName = $matches[2] . $matches[4];
2654 foreach ($fieldChangeFunctions as &$value) {
2655 $value = str_replace($originalName, $cleanedName, $value);
2656 }
2657 unset($value);
2658 }
2659 $result = $this->P['fieldChangeFuncHash'] === GeneralUtility::hmac(serialize($fieldChangeFunctions));
2660 }
2661 return $result;
2662 }
2663
2664 /**
2665 * Check if a temporary tree mount is set and return a cancel button
2666 *
2667 * @return string
2668 */
2669 protected function getTemporaryTreeMountCancelNotice() {
2670 if ((int)$this->getBackendUserAuthentication()->getSessionData('pageTree_temporaryMountPoint') === 0) {
2671 return '';
2672 }
2673 $link = '<a href="' . htmlspecialchars(GeneralUtility::linkThisScript(array('setTempDBmount' => 0))) . '">'
2674 . $this->getLanguageService()->sl('LLL:EXT:lang/locallang_core.xlf:labels.temporaryDBmount', TRUE) . '</a>';
2675 /** @var FlashMessage $flashMessage */
2676 $flashMessage = GeneralUtility::makeInstance(
2677 FlashMessage::class,
2678 $link,
2679 '',
2680 FlashMessage::INFO
2681 );
2682 return $flashMessage->render();
2683 }
2684
2685 /**
2686 * Get a list of Files in a folder filtered by extension
2687 *
2688 * @param Folder $folder
2689 * @param string $extensionList
2690 * @return \TYPO3\CMS\Core\Resource\File[]
2691 */
2692 protected function getFilesInFolder(Folder $folder, $extensionList) {
2693 if ($extensionList !== '') {
2694 /** @var FileExtensionFilter $filter */
2695 $filter = GeneralUtility::makeInstance(FileExtensionFilter::class);
2696 $filter->setAllowedFileExtensions($extensionList);
2697 $folder->setFileAndFolderNameFilters(array(array($filter, 'filterFileList')));
2698 }
2699 return $folder->getFiles();
2700 }
2701
2702 /**
2703 * @return LanguageService
2704 */
2705 protected function getLanguageService() {
2706 return $GLOBALS['LANG'];
2707 }
2708
2709 /**
2710 * @return BackendUserAuthentication
2711 */
2712 protected function getBackendUserAuthentication() {
2713 return $GLOBALS['BE_USER'];
2714 }
2715
2716 /**
2717 * @return DatabaseConnection
2718 */
2719 protected function getDatabaseConnection() {
2720 return $GLOBALS['TYPO3_DB'];
2721 }
2722
2723 }