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