[TYPO3-core] RFC: Feature #4923: provide new inputfield "directorypicker" in BE
Ralf Hettinger
ng at ralfhettinger.de
Fri Feb 8 10:48:23 CET 2008
ToDo for integration into 4.2:
Solve handling of link in TCEForm to wizard from single input fields properly.
The link should be built by appending ?mode=wizard&act=folder or similar to
that. Currently it uses mode=folder and results in JavaScript-Errors.
For testing the wizard with an input field, you can simply use Andreas dirpicker
demo extension at http://bugs.typo3.org/file_download.php?file_id=2455&type=bug
Ralf
Ralf Hettinger schrieb:
> This is an SVN patch request.
>
> Type: New feature
>
> Bugtracker references:
> http://bugs.typo3.org/view.php?id=4923
>
> Branches:
> trunk only
>
> Problem:
> Extend TCA-types with the possibilty to select a directory instead of only
> picking a file. Could be used for e.g. Galleries, Filelists etc.
>
> Solution:
> This solution is initially provided by Andreas Wolf (thank you!)
> With attached patch, the following is possible by TCA
> [...]
> 'config' => Array (
> 'type'=>'group',
> 'internal_type'=>'folder',
> [...]
> ),
> [...]
>
> There is a .t3x by Andreas attached as "dirpicker"-demo to the bugreport for
> easy demonstration what it does.
>
> Notes:
> I haven't tested the patch heavily (though I _have_ tested it with the current
> trunk). The original reporter redacted user just passed a request to me couple
> of days ago for this feature to be included in 4.2 since this "dirpicker" seemed
> top be quite well accepted.
> Thanks for reminding, Boris.
>
> Ralf Hettinger
>
>
> ------------------------------------------------------------------------
>
> Index: t3lib/class.t3lib_tceforms.php
> ===================================================================
> --- t3lib/class.t3lib_tceforms.php (revision 2950)
> +++ t3lib/class.t3lib_tceforms.php (working copy)
> @@ -2026,6 +2026,23 @@
> if ($this->edit_docModuleUpload) $item.='<input type="file" name="'.$PA['itemFormElName_file'].'"'.$this->formWidth().' size="60" />';
> }
> break;
> + case 'folder': // If the element is of the internal type "folder":
> +
> + // array of file items:
> + $itemArray = t3lib_div::trimExplode(',',$PA['itemFormElValue'],1);
> +
> + // Creating the element:
> + $params = array(
> + 'size' => $size,
> + 'dontShowMoveIcons' => ($maxitems<=1),
> + 'autoSizeMax' => t3lib_div::intInRange($config['autoSizeMax'],0),
> + 'maxitems' => $maxitems,
> + 'style' => isset($config['selectedListStyle']) ? ' style="'.htmlspecialchars($config['selectedListStyle']).'"' : ' style="'.$this->defaultMultipleSelectorStyle.'"',
> + 'info' => $info,
> + 'readOnly' => $disabled
> + );
> + $item.= $this->dbFileIcons($PA['itemFormElName'],'folder','',$itemArray,'',$params,$PA['onFocus']);
> + break;
> case 'db': // If the element is of the internal type "db":
>
> // Creating string showing allowed types:
> @@ -3296,6 +3313,7 @@
> }
> break;
> case 'file':
> + case 'folder':
> while(list(,$pp)=each($itemArray)) {
> $pParts = explode('|',$pp);
> $uidList[]=$pUid=$pTitle = $pParts[0];
> Index: typo3/class.browse_links.php
> ===================================================================
> --- typo3/class.browse_links.php (revision 2950)
> +++ typo3/class.browse_links.php (working copy)
> @@ -882,24 +882,26 @@
> }
> ';
>
> -
> - if ($this->mode=='wizard') { // Functions used, if the link selector is in wizard mode (= TCEforms fields)
> + $P2=array();
> + $P2['itemName']=$this->P['itemName'];
> + $P2['formName']=$this->P['formName'];
> + $P2['fieldChangeFunc']=$this->P['fieldChangeFunc'];
> + $P2['params']['allowedExtensions']=$this->P['params']['allowedExtensions'];
> + $P2['params']['blindLinkOptions']=$this->P['params']['blindLinkOptions'];
> + $addPassOnParams.=t3lib_div::implodeArrayForUrl('P',$P2);
> + $update='';
> + if (is_array($this->P['fieldChangeFunc'])) {
> unset($this->P['fieldChangeFunc']['alert']);
> reset($this->P['fieldChangeFunc']);
> - $update='';
> while(list($k,$v)=each($this->P['fieldChangeFunc'])) {
> - $update.= '
> - window.opener.'.$v;
> + if (trim($v)) {
> + $update.= '
> + window.opener.'.$v;
> + }
> }
> + }
>
> - $P2=array();
> - $P2['itemName']=$this->P['itemName'];
> - $P2['formName']=$this->P['formName'];
> - $P2['fieldChangeFunc']=$this->P['fieldChangeFunc'];
> - $P2['params']['allowedExtensions']=$this->P['params']['allowedExtensions'];
> - $P2['params']['blindLinkOptions']=$this->P['params']['blindLinkOptions'];
> - $addPassOnParams.=t3lib_div::implodeArrayForUrl('P',$P2);
> -
> + if ($this->mode=='wizard' || $this->mode=='folder') { // Functions used, if the link selector is in wizard mode (= TCEforms fields or simple input field used as dirpicker)
> $JScode.='
> function link_typo3Page(id,anchor) { //
> updateValueInMainForm(id+(anchor?anchor:"")+" "+cur_target);
> @@ -921,12 +923,10 @@
> }
> return false;
> }
> - function checkReference() { //
> - if (window.opener && window.opener.document && window.opener.document.'.$this->P['formName'].' && window.opener.document.'.$this->P['formName'].'["'.$this->P['itemName'].'"] ) {
> - return window.opener.document.'.$this->P['formName'].'["'.$this->P['itemName'].'"];
> - } else {
> - close();
> - }
> + function set_folderpath(folder) { //
> + updateValueInMainForm(folder);
> + close();
> + return false;
> }
> function updateValueInMainForm(input) { //
> var field = checkReference();
> @@ -936,7 +936,18 @@
> }
> }
> ';
> - } else { // Functions used, if the link selector is in RTE mode:
> + if ($this->P['formName'] && $this->P['itemName']) {
> + $JScode.='
> + function checkReference() { //
> + if (window.opener && window.opener.document && window.opener.document.'.$this->P['formName'].' && window.opener.document.'.$this->P['formName'].'["'.$this->P['itemName'].'"] ) {
> + return window.opener.document.'.$this->P['formName'].'["'.$this->P['itemName'].'"];
> + } else {
> + close();
> + }
> + }
> + ';
> + }
> + } else { // Functions used, if the link selector is in RTE or any other mode:
> $JScode.='
> function link_typo3Page(id,anchor) { //
> var theLink = \''.$this->siteURL.'?id=\'+id+(anchor?anchor:"");
> @@ -1127,6 +1138,7 @@
> break;
> case 'file':
> case 'filedrag':
> + case 'folder':
> if (isset($this->expandFolder)) {
> $data['expandFolder']=$this->expandFolder;
> $store = true;
> @@ -1163,7 +1175,7 @@
> $content=$this->doc->startPage('RTE link');
>
> // Initializing the action value, possibly removing blinded values etc:
> - $allowedItems = array_diff(explode(',','page,file,url,mail,spec'),t3lib_div::trimExplode(',',$this->thisConfig['blindLinkOptions'],1));
> + $allowedItems = array_diff(explode(',','page,file,folder,url,mail,spec'),t3lib_div::trimExplode(',',$this->thisConfig['blindLinkOptions'],1));
> $allowedItems = array_diff($allowedItems, t3lib_div::trimExplode(',',$this->P['params']['blindLinkOptions']));
>
> //call hook for extra options
> @@ -1194,6 +1206,12 @@
> $menuDef['file']['url'] = '#';
> $menuDef['file']['addParams'] = 'onclick="jumpToUrl(\'?act=file\');return false;"';
> }
> + if (in_array('folder',$allowedItems)){
> + $menuDef['folder']['isActive'] = $this->act=='folder';
> + $menuDef['folder']['label'] = $LANG->getLL('folder',1);
> + $menuDef['folder']['url'] = '#';
> + $menuDef['folder']['addParams'] = 'onclick="jumpToUrl(\'?act=folder\');return false;"';
> + }
> if (in_array('url',$allowedItems)) {
> $menuDef['url']['isActive'] = $this->act=='url';
> $menuDef['url']['label'] = $LANG->getLL('extUrl',1);
> @@ -1261,11 +1279,12 @@
> $content.=$extUrl;
> break;
> case 'file':
> + case 'folder':
> $foldertree = t3lib_div::makeInstance('rteFolderTree');
> $foldertree->thisScript = $this->thisScript;
> $tree=$foldertree->getBrowsableTree();
>
> - if (!$this->curUrlInfo['value'] || $this->curUrlInfo['act']!='file') {
> + if (!$this->curUrlInfo['value'] || $this->curUrlInfo['act']!=$this->act) {
> $cmpPath='';
> } elseif (substr(trim($this->curUrlInfo['info']),-1)!='/') {
> $cmpPath=PATH_site.dirname($this->curUrlInfo['info']).'/';
> @@ -1275,17 +1294,17 @@
> }
>
> list(,,$specUid) = explode('_',$this->PM);
> - $files = $this->expandFolder($foldertree->specUIDmap[$specUid], $this->P['params']['allowedExtensions']);
> + $filesOrFolders = $this->expandFolder($foldertree->specUIDmap[$specUid], $this->P['params']['allowedExtensions']);
>
> $content.= '
>
> <!--
> - Wrapper table for folder tree / file list:
> + Wrapper table for folder tree / file list / folder list:
> -->
> <table border="0" cellpadding="0" cellspacing="0" id="typo3-linkFiles">
> <tr>
> <td class="c-wCell" valign="top">'.$this->barheader($GLOBALS['LANG']->getLL('folderTree').':').$tree.'</td>
> - <td class="c-wCell" valign="top">'.$files.'</td>
> + <td class="c-wCell" valign="top">'.$filesOrFolders.'</td>
> </tr>
> </table>
> ';
> @@ -1608,14 +1627,74 @@
> return $content;
> }
>
> + /**
> + * TYPO3 Element Browser: Showing a folder tree, allowing you to browse for folders.
> + *
> + * @return string HTML content for the module
> + */
> + function main_folder() {
> + global $BE_USER;
>
> + // Starting content:
> + $content.=$this->doc->startPage('TBE folder selector');
> +
> + // Init variable:
> + $pArr = explode('|',$this->bparams);
> +
> + // Create upload/create folder forms, if a path is given:
> + $fileProcessor = t3lib_div::makeInstance('t3lib_basicFileFunctions');
> + $fileProcessor->init($GLOBALS['FILEMOUNTS'], $GLOBALS['TYPO3_CONF_VARS']['BE']['fileExtensions']);
> + $path=$this->expandFolder;
> + if (!$path || !@is_dir($path)) {
> + $path = $fileProcessor->findTempFolder().'/'; // The closest TEMP-path is found
> + }
> + if ($path!='/' && @is_dir($path)) {
> + $createFolder=$this->createFolder($path);
> + } else {
> + $createFolder='';
> + }
>
> + // Create folder tree:
> + $foldertree = t3lib_div::makeInstance('TBE_FolderTree');
> + $foldertree->thisScript=$this->thisScript;
> + $foldertree->ext_noTempRecyclerDirs = ($this->mode == 'filedrag');
> + $tree = $foldertree->getBrowsableTree(false);
>
> + list(,,$specUid) = explode('_',$this->PM);
> +
> + if ($this->mode=='filedrag') {
> + $folders = $this->TBE_dragNDrop($foldertree->specUIDmap[$specUid],$pArr[3]);
> + } else {
> + $folders = $this->TBE_expandSubFolders($foldertree->specUIDmap[$specUid]);
> + }
>
> + // Putting the parts together, side by side:
> + $content.= '
>
> + <!--
> + Wrapper table for folder tree / folder list:
> + -->
> + <table border="0" cellpadding="0" cellspacing="0" id="typo3-EBfiles">
> + <tr>
> + <td class="c-wCell" valign="top">'.$this->barheader($GLOBALS['LANG']->getLL('folderTree').':').$tree.'</td>
> + <td class="c-wCell" valign="top">'.$folders.'</td>
> + </tr>
> + </table>
> + ';
>
> + // Adding create folder if applicable:
> + if ($BE_USER->isAdmin() || $BE_USER->getTSConfigVal('options.createFoldersInEB')) {
> + $content.=$createFolder;
> + }
>
> + // Add some space
> + $content.='<br /><br />';
>
> + // Ending page, returning content:
> + $content.= $this->doc->endPage();
> + $content = $this->doc->insertStylesAndJS($content);
> + return $content;
> + }
>
>
>
> @@ -1902,6 +1981,37 @@
> }
>
> /**
> + * Render list of folders inside a folder.
> + *
> + * @param string string of the current folder
> + * @return string HTML output
> + */
> + function TBE_expandSubFolders($expandFolder=0) {
> + global $LANG;
> +
> + $expandFolder = $expandFolder ? $expandFolder : $this->expandFolder;
> + $out='';
> + if ($expandFolder && $this->checkFolder($expandFolder)) {
> + if (t3lib_div::isFirstPartOfStr($expandFolder,PATH_site)) {
> + $rootFolder = substr($expandFolder, strlen(PATH_site));
> + }
> + $folders = array();
> +
> + // Listing the folders:
> + $folders = t3lib_div::get_dirs($expandFolder);
> + if (count($folders) > 0) {
> + foreach ($folders as $index => $folder) {
> + $folders[$index] = $rootFolder.$folder.'/';
> + }
> + }
> + $out.= $this->folderList($rootFolder, $folders);
> + }
> +
> + // Return accumulated content for folderlisting:
> + return $out;
> + }
> +
> + /**
> * Render list of files.
> *
> * @param array List of files. See t3lib_div::getFilesInDir
> @@ -2031,6 +2141,105 @@
> }
>
> /**
> + * Render list of folders.
> + *
> + * @param array List of folders. See t3lib_div::get_dirs
> + * @param string If set a header with a folder icon and folder name are shown
> + * @return string HTML output
> + */
> + function folderList($base_folder, $folders) {
> + global $LANG, $BACK_PATH;
> +
> + $out='';
> +
> + // Create headline (showing number of folders):
> + $out.=$this->barheader(sprintf($GLOBALS['LANG']->getLL('folders').' (%s):',count($folders)));
> +
> + $titleLen=intval($GLOBALS['BE_USER']->uc['titleLen']);
> +
> + // Create the header of current folder:
> + if($base_folder) {
> + if (strstr($base_folder,',') || strstr($base_folder,'|')) { // In case an invalid character is in the filepath, display error message:
> + $eMsg = $LANG->JScharCode(sprintf($LANG->getLL('invalidChar'),', |'));
> + $ATag = $ATag_alt = "<a href=\"#\" onclick=\"alert(".$eMsg.");return false;\">";
> + } else { // If foldername is OK, just add it:
> + $ATag = "<a href=\"#\" onclick=\"return insertElement('','".rawurlencode($base_folder)."', 'folder', '".rawurlencode($base_folder)."', unescape('".rawurlencode($base_folder)."'), '".$fI['extension']."', '".$ficon."');\">";
> + $ATag_alt = substr($ATag,0,-4).",'',1);\">";
> + }
> + $ATag_e='</a>';
> +
> + $picon = $ATag_alt;
> + $picon.='<img'.t3lib_iconWorks::skinImg($BACK_PATH,'gfx/i/_icon_webfolders.gif','width="18" height="16"').' alt="" />';
> + $picon.=htmlspecialchars(t3lib_div::fixed_lgd_cs(basename($base_folder),$titleLen));
> + $picon.=$ATag_e;
> + $out.=$picon.'<br />';
> + }
> +
> + // Listing the folders:
> + if (is_array($folders)) {
> + if (count($folders) > 0) {
> + // Traverse the folder list:
> + $lines=array();
> + foreach($folders as $folderpath) {
> + $fI=pathinfo($folderpath);
> +
> + // Create folder icon:
> + $icon = '<img src="clear.gif" width="16" height="16" alt="" /><img'.t3lib_iconWorks::skinImg($BACK_PATH,'gfx/i/_icon_webfolders.gif','width="16" height="16"').' title="'.htmlspecialchars($fI['basename'].$size).'" class="absmiddle" alt="" />';
> +
> + // Create links for adding the folder:
> + if ($this->P['itemName'] != '' && $this->P['formName'] != '') {
> + $ATag = "<a href=\"#\" onclick=\"return set_folderpath(unescape('".rawurlencode($folderpath)."'));\">";
> + } else {
> + $ATag = "<a href=\"#\" onclick=\"return insertElement('','".rawurlencode($folderpath)."', 'folder', '".rawurlencode($folderpath)."', unescape('".rawurlencode($folderpath)."'), '".$fI['extension']."', '".$ficon."');\">";
> + }
> + if (strstr($folderpath,',') || strstr($folderpath,'|')) { // In case an invalid character is in the filepath, display error message:
> + $eMsg = $LANG->JScharCode(sprintf($LANG->getLL('invalidChar'),', |'));
> + $ATag = $ATag_alt = "<a href=\"#\" onclick=\"alert(".$eMsg.");return false;\">";
> + } else { // If foldername is OK, just add it:
> + $ATag_alt = substr($ATag,0,-4).",'',1);\">";
> + }
> + $ATag_e='</a>';
> +
> + // Combine icon and folderpath:
> + $foldernameAndIcon=$ATag_alt.$icon.htmlspecialchars(t3lib_div::fixed_lgd_cs(basename($folderpath),$titleLen)).$ATag_e;
> +
> + if ($this->P['itemName'] != '') {
> + $lines[]='
> + <tr class="bgColor4">
> + <td nowrap="nowrap">'.$foldernameAndIcon.' </td>
> + <td> </td>
> + </tr>';
> + } else {
> + $lines[]='
> + <tr class="bgColor4">
> + <td nowrap="nowrap">'.$foldernameAndIcon.' </td>
> + <td>'.$ATag.'<img'.t3lib_iconWorks::skinImg($BACK_PATH,'gfx/plusbullet2.gif','width="18" height="16"').' title="'.$LANG->getLL('addToList',1).'" alt="" />'.$ATag_e.'</td>
> + <td> </td>
> + </tr>';
> + }
> + $lines[]='
> + <tr>
> + <td colspan="3"><img src="clear.gif" width="1" height="3" alt="" /></td>
> + </tr>';
> + }
> + }
> +
> + // Wrap all the rows in table tags:
> + $out.='
> +
> + <!--
> + Folder listing
> + -->
> + <table border="0" cellpadding="0" cellspacing="1" id="typo3-folderList">
> + '.implode('',$lines).'
> + </table>';
> + }
> +
> + // Return accumulated content for folderlisting:
> + return $out;
> + }
> +
> + /**
> * For RTE: This displays all IMAGES (gif,png,jpg) (from extensionList) from folder. Thumbnails are shown for images.
> * This listing is of images located in the web-accessible paths ONLY - the listing is for drag-n-drop use in the RTE
> *
> Index: typo3/browse_links.php
> ===================================================================
> --- typo3/browse_links.php (revision 2950)
> +++ typo3/browse_links.php (working copy)
> @@ -178,6 +178,7 @@
> break;
> case 'file':
> case 'filedrag':
> + case 'folder':
> // Setting alternative browsing mounts (ONLY local to browse_links.php this script so they stay "read-only")
> $altMountPoints = trim($GLOBALS['BE_USER']->getTSConfigVal('options.folderTree.altElementBrowserMountPoints'));
> if ($altMountPoints) {
> @@ -204,6 +205,9 @@
> case 'filedrag':
> $this->content = $this->browser->main_file();
> break;
> + case 'folder':
> + $this->content = $this->browser->main_folder();
> + break;
> case 'wizard':
> $this->content = $this->browser->main_rte(1);
> break;
More information about the TYPO3-team-core
mailing list