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