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