class.t3lib_treeview.php

Go to the documentation of this file.
00001 <?php
00002 /***************************************************************
00003 *  Copyright notice
00004 *
00005 *  (c) 1999-2008 Kasper Skaarhoj (kasperYYYY@typo3.com)
00006 *  All rights reserved
00007 *
00008 *  This script is part of the TYPO3 project. The TYPO3 project is
00009 *  free software; you can redistribute it and/or modify
00010 *  it under the terms of the GNU General Public License as published by
00011 *  the Free Software Foundation; either version 2 of the License, or
00012 *  (at your option) any later version.
00013 *
00014 *  The GNU General Public License can be found at
00015 *  http://www.gnu.org/copyleft/gpl.html.
00016 *  A copy is found in the textfile GPL.txt and important notices to the license
00017 *  from the author is found in LICENSE.txt distributed with these scripts.
00018 *
00019 *
00020 *  This script is distributed in the hope that it will be useful,
00021 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00022 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00023 *  GNU General Public License for more details.
00024 *
00025 *  This copyright notice MUST APPEAR in all copies of the script!
00026 ***************************************************************/
00027 /**
00028  * Contains base class for creating a browsable array/page/folder tree in HTML
00029  *
00030  * $Id: class.t3lib_treeview.php 4432 2008-11-07 03:52:22Z flyguide $
00031  * Revised for TYPO3 3.6 November/2003 by Kasper Skaarhoj
00032  *
00033  * @author  Kasper Skaarhoj <kasperYYYY@typo3.com>
00034  * @coauthor    René Fritz <r.fritz@colorcube.de>
00035  */
00036 /**
00037  * [CLASS/FUNCTION INDEX of SCRIPT]
00038  *
00039  *
00040  *
00041  *  115: class t3lib_treeView
00042  *  270:     function init($clause='', $orderByFields='')
00043  *  301:     function setTreeName($treeName='')
00044  *  315:     function addField($field,$noCheck=0)
00045  *  329:     function reset()
00046  *
00047  *              SECTION: output
00048  *  349:     function getBrowsableTree()
00049  *  412:     function printTree($treeArr='')
00050  *
00051  *              SECTION: rendering parts
00052  *  467:     function PMicon($row,$a,$c,$nextCount,$exp)
00053  *  489:     function PM_ATagWrap($icon,$cmd,$bMark='')
00054  *  511:     function wrapTitle($title,$row,$bank=0)
00055  *  524:     function wrapIcon($icon,$row)
00056  *  535:     function addTagAttributes($icon,$attr)
00057  *  547:     function wrapStop($str,$row)
00058  *
00059  *              SECTION: tree handling
00060  *  575:     function expandNext($id)
00061  *  585:     function initializePositionSaving()
00062  *  612:     function savePosition()
00063  *
00064  *              SECTION: Functions that might be overwritten by extended classes
00065  *  641:     function getRootIcon($rec)
00066  *  654:     function getIcon($row)
00067  *  673:     function getTitleStr($row,$titleLen=30)
00068  *  685:     function getTitleAttrib($row)
00069  *  695:     function getId($row)
00070  *  705:     function getJumpToParam($row)
00071  *
00072  *              SECTION: tree data buidling
00073  *  739:     function getTree($uid, $depth=999, $depthData='',$blankLineCode='',$subCSSclass='')
00074  *
00075  *              SECTION: Data handling
00076  *  839:     function getCount($uid)
00077  *  865:     function getRootRecord($uid)
00078  *  878:     function getRecord($uid)
00079  *  898:     function getDataInit($parentId,$subCSSclass='')
00080  *  929:     function getDataCount(&$res)
00081  *  947:     function getDataNext(&$res,$subCSSclass='')
00082  *  986:     function getDataFree(&$res)
00083  * 1006:     function setDataFromArray(&$dataArr,$traverse=FALSE,$pid=0)
00084  * 1035:     function setDataFromTreeArray(&$treeArr, &$treeLookupArr)
00085  *
00086  * TOTAL FUNCTIONS: 31
00087  * (This index is automatically created/updated by the extension "extdeveval")
00088  *
00089  */
00090 
00091 
00092 
00093 
00094 
00095 
00096 
00097 
00098 
00099 
00100 
00101 require_once (PATH_t3lib.'class.t3lib_iconworks.php');
00102 require_once (PATH_t3lib.'class.t3lib_befunc.php');
00103 require_once (PATH_t3lib.'class.t3lib_div.php');
00104 
00105 
00106 /**
00107  * Base class for creating a browsable array/page/folder tree in HTML
00108  *
00109  * @author  Kasper Skaarhoj <kasperYYYY@typo3.com>
00110  * @coauthor    René Fritz <r.fritz@colorcube.de>
00111  * @package TYPO3
00112  * @subpackage t3lib
00113  * @see t3lib_browsetree, t3lib_pagetree, t3lib_foldertree
00114  */
00115 class t3lib_treeView {
00116 
00117         // EXTERNAL, static:
00118     var $expandFirst=0;     // If set, the first element in the tree is always expanded.
00119     var $expandAll=0;       // If set, then ALL items will be expanded, regardless of stored settings.
00120     var $thisScript='';     // Holds the current script to reload to.
00121     var $titleAttrib = 'title';     // Which HTML attribute to use: alt/title. See init().
00122     var $ext_IconMode = false;      // If true, no context menu is rendered on icons. If set to "titlelink" the icon is linked as the title is.
00123     var $addSelfId = 0;             // If set, the id of the mounts will be added to the internal ids array
00124     var $title='no title';          // Used if the tree is made of records (not folders for ex.)
00125     var $showDefaultTitleAttribute = FALSE;     // If true, a default title attribute showing the UID of the record is shown. This cannot be enabled by default because it will destroy many applications where another title attribute is in fact applied later.
00126     var $highlightPagesWithVersions = TRUE;     // If true, pages containing child records which has versions will be highlighted in yellow. This might be too expensive in terms of processing power.
00127 
00128     /**
00129      * Needs to be initialized with $GLOBALS['BE_USER']
00130      * Done by default in init()
00131      *
00132      * @var t3lib_beUserAuth
00133      */
00134     var $BE_USER='';
00135 
00136     /**
00137      * Needs to be initialized with e.g. $GLOBALS['WEBMOUNTS']
00138      * Default setting in init() is 0 => 0
00139      * The keys are mount-ids (can be anything basically) and the values are the ID of the root element (COULD be zero or anything else. For pages that would be the uid of the page, zero for the pagetree root.)
00140      */
00141     var $MOUNTS='';
00142 
00143 
00144 
00145     /**
00146      * Database table to get the tree data from.
00147      * Leave blank if data comes from an array.
00148      */
00149     var $table='';
00150 
00151     /**
00152      * Defines the field of $table which is the parent id field (like pid for table pages).
00153      */
00154     var $parentField='pid';
00155 
00156     /**
00157      * WHERE clause used for selecting records for the tree. Is set by function init.
00158      * Only makes sense when $this->table is set.
00159      * @see init()
00160      */
00161     var $clause='';
00162 
00163     /**
00164      * Field for ORDER BY. Is set by function init.
00165      * Only makes sense when $this->table is set.
00166      * @see init()
00167      */
00168     var $orderByFields='';
00169 
00170     /**
00171      * Default set of fields selected from the tree table.
00172      * Make SURE that these fields names listed herein are actually possible to select from $this->table (if that variable is set to a TCA table name)
00173      * @see addField()
00174      */
00175     var $fieldArray = Array('uid','title');
00176 
00177     /**
00178      * List of other fields which are ALLOWED to set (here, based on the "pages" table!)
00179      * @see addField()
00180      */
00181     var $defaultList = 'uid,pid,tstamp,sorting,deleted,perms_userid,perms_groupid,perms_user,perms_group,perms_everybody,crdate,cruser_id';
00182 
00183 
00184     /**
00185      * Unique name for the tree.
00186      * Used as key for storing the tree into the BE users settings.
00187      * Used as key to pass parameters in links.
00188      * MUST NOT contain underscore chars.
00189      * etc.
00190      */
00191     var $treeName = '';
00192 
00193     /**
00194      * A prefix for table cell id's which will be wrapped around an item.
00195      * Can be used for highlighting by JavaScript.
00196      * Needs to be unique if multiple trees are on one HTML page.
00197      * @see printTree()
00198      */
00199     var $domIdPrefix = 'row';
00200 
00201     /**
00202      * Back path for icons
00203      */
00204     var $backPath;
00205 
00206     /**
00207      * Icon file path.
00208      */
00209     var $iconPath = '';
00210 
00211 
00212     /**
00213      * Icon file name for item icons.
00214      */
00215     var $iconName = 'default.gif';
00216 
00217     /**
00218      * If true, HTML code is also accumulated in ->tree array during rendering of the tree.
00219      * If 2, then also the icon prefix code (depthData) is stored
00220      */
00221     var $makeHTML=1;
00222 
00223     /**
00224      * If true, records as selected will be stored internally in the ->recs array
00225      */
00226     var $setRecs = 0;
00227 
00228     /**
00229      * Sets the associative array key which identifies a new sublevel if arrays are used for trees.
00230      * This value has formerly been "subLevel" and "--sublevel--"
00231      */
00232     var $subLevelID = '_SUB_LEVEL';
00233 
00234 
00235 
00236 
00237         // *********
00238         // Internal
00239         // *********
00240         // For record trees:
00241     var $ids = Array();             // one-dim array of the uid's selected.
00242     var $ids_hierarchy = array();   // The hierarchy of element uids
00243     var $orig_ids_hierarchy = array();  // The hierarchy of versioned element uids
00244     var $buffer_idH = array();      // Temporary, internal array
00245 
00246         // For FOLDER trees:
00247     var $specUIDmap=array();        // Special UIDs for folders (integer-hashes of paths)
00248 
00249         // For arrays:
00250     var $data = false;              // Holds the input data array
00251     var $dataLookup = false;        // Holds an index with references to the data array.
00252 
00253         // For both types
00254     var $tree = Array();            // Tree is accumulated in this variable
00255     var $stored = array();          // Holds (session stored) information about which items in the tree are unfolded and which are not.
00256     var $bank=0;                    // Points to the current mountpoint key
00257     var $recs = array();            // Accumulates the displayed records.
00258 
00259 
00260 
00261 
00262 
00263 
00264 
00265     /**
00266      * Initialize the tree class. Needs to be overwritten
00267      * Will set ->fieldsArray, ->backPath and ->clause
00268      *
00269      * @param   string      record WHERE clause
00270      * @param   string      record ORDER BY field
00271      * @return  void
00272      */
00273     function init($clause='', $orderByFields='')    {
00274         $this->BE_USER = $GLOBALS['BE_USER'];   // Setting BE_USER by default
00275         $this->titleAttrib = 'title';   // Setting title attribute to use.
00276         $this->backPath = $GLOBALS['BACK_PATH'];    // Setting backpath.
00277 
00278         if ($clause)    $this->clause = $clause;    // Setting clause
00279         if ($orderByFields) $this->orderByFields = $orderByFields;
00280 
00281         if (!is_array($this->MOUNTS))   {
00282             $this->MOUNTS = array(0 => 0); // dummy
00283         }
00284 
00285         $this->setTreeName();
00286 
00287         if($this->table) {
00288             t3lib_div::loadTCA($this->table);
00289         }
00290 
00291             // setting this to false disables the use of array-trees by default
00292         $this->data = false;
00293         $this->dataLookup = false;
00294     }
00295 
00296 
00297     /**
00298      * Sets the tree name which is used to identify the tree
00299      * Used for JavaScript and other things
00300      *
00301      * @param   string      Default is the table name. Underscores are stripped.
00302      * @return  void
00303      */
00304     function setTreeName($treeName='') {
00305         $this->treeName = $treeName ? $treeName : $this->treeName;
00306         $this->treeName = $this->treeName ? $this->treeName : $this->table;
00307         $this->treeName = str_replace('_','',$this->treeName);
00308     }
00309 
00310 
00311     /**
00312      * Adds a fieldname to the internal array ->fieldArray
00313      *
00314      * @param   string      Field name to
00315      * @param   boolean     If set, the fieldname will be set no matter what. Otherwise the field name must either be found as key in $TCA[$table]['columns'] or in the list ->defaultList
00316      * @return  void
00317      */
00318     function addField($field,$noCheck=0)    {
00319         global $TCA;
00320         if ($noCheck || is_array($TCA[$this->table]['columns'][$field]) || t3lib_div::inList($this->defaultList,$field))    {
00321             $this->fieldArray[]=$field;
00322         }
00323     }
00324 
00325 
00326 
00327     /**
00328      * Resets the tree, recs, ids, ids_hierarchy and orig_ids_hierarchy internal variables. Use it if you need it.
00329      *
00330      * @return  void
00331      */
00332     function reset()    {
00333         $this->tree = array();
00334         $this->recs = array();
00335         $this->ids = array();
00336         $this->ids_hierarchy = array();
00337         $this->orig_ids_hierarchy = array();
00338     }
00339 
00340 
00341     /*******************************************
00342      *
00343      * output
00344      *
00345      *******************************************/
00346 
00347     /**
00348      * Will create and return the HTML code for a browsable tree
00349      * Is based on the mounts found in the internal array ->MOUNTS (set in the constructor)
00350      *
00351      * @return  string      HTML code for the browsable tree
00352      */
00353     function getBrowsableTree() {
00354 
00355             // Get stored tree structure AND updating it if needed according to incoming PM GET var.
00356         $this->initializePositionSaving();
00357 
00358             // Init done:
00359         $titleLen=intval($this->BE_USER->uc['titleLen']);
00360         $treeArr=array();
00361 
00362             // Traverse mounts:
00363         foreach($this->MOUNTS as $idx => $uid)  {
00364 
00365                 // Set first:
00366             $this->bank=$idx;
00367             $isOpen = $this->stored[$idx][$uid] || $this->expandFirst;
00368 
00369                 // Save ids while resetting everything else.
00370             $curIds = $this->ids;
00371             $this->reset();
00372             $this->ids = $curIds;
00373 
00374                 // Set PM icon for root of mount:
00375             $cmd=$this->bank.'_'.($isOpen?"0_":"1_").$uid.'_'.$this->treeName;
00376             $icon='<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/ol/'.($isOpen?'minus':'plus').'only.gif','width="18" height="16"').' alt="" />';
00377             $firstHtml= $this->PM_ATagWrap($icon,$cmd);
00378 
00379                 // Preparing rootRec for the mount
00380             if ($uid)   {
00381                 $rootRec = $this->getRecord($uid);
00382                 $firstHtml.=$this->getIcon($rootRec);
00383             } else {
00384                     // Artificial record for the tree root, id=0
00385                 $rootRec = $this->getRootRecord($uid);
00386                 $firstHtml.=$this->getRootIcon($rootRec);
00387             }
00388 
00389             if (is_array($rootRec)) {
00390                 $uid = $rootRec['uid'];     // In case it was swapped inside getRecord due to workspaces.
00391 
00392                     // Add the root of the mount to ->tree
00393                 $this->tree[]=array('HTML'=>$firstHtml, 'row'=>$rootRec, 'bank'=>$this->bank);
00394 
00395                     // If the mount is expanded, go down:
00396                 if ($isOpen)    {
00397                         // Set depth:
00398                     $depthD='<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/ol/blank.gif','width="18" height="16"').' alt="" />';
00399                     if ($this->addSelfId)   $this->ids[] = $uid;
00400                     $this->getTree($uid,999,$depthD,'',$rootRec['_SUBCSSCLASS']);
00401                 }
00402 
00403                     // Add tree:
00404                 $treeArr=array_merge($treeArr,$this->tree);
00405             }
00406         }
00407         return $this->printTree($treeArr);
00408     }
00409 
00410     /**
00411      * Compiles the HTML code for displaying the structure found inside the ->tree array
00412      *
00413      * @param   array       "tree-array" - if blank string, the internal ->tree array is used.
00414      * @return  string      The HTML code for the tree
00415      */
00416     function printTree($treeArr='') {
00417         $titleLen=intval($this->BE_USER->uc['titleLen']);
00418         if (!is_array($treeArr))    $treeArr=$this->tree;
00419         $out='';
00420 
00421             // put a table around it with IDs to access the rows from JS
00422             // not a problem if you don't need it
00423             // In XHTML there is no "name" attribute of <td> elements - but Mozilla will not be able to highlight rows if the name attribute is NOT there.
00424         $out .= '
00425 
00426             <!--
00427               TYPO3 tree structure.
00428             -->
00429             <table cellpadding="0" cellspacing="0" border="0" id="typo3-tree">';
00430 
00431         foreach($treeArr as $k => $v)   {
00432             $idAttr = htmlspecialchars($this->domIdPrefix.$this->getId($v['row']).'_'.$v['bank']);
00433 
00434             $out.='
00435                 <tr>
00436                     <td id="'.$idAttr.'"'.
00437                         ($v['row']['_CSSCLASS'] ? ' class="'.$v['row']['_CSSCLASS'].'"' : '').'>'.
00438                         $v['HTML'].
00439                         $this->wrapTitle($this->getTitleStr($v['row'],$titleLen),$v['row'],$v['bank']).
00440                     '</td>
00441                 </tr>
00442             ';
00443         }
00444         $out .= '
00445             </table>';
00446         return $out;
00447     }
00448 
00449 
00450 
00451     /*******************************************
00452      *
00453      * rendering parts
00454      *
00455      *******************************************/
00456 
00457 
00458 
00459     /**
00460      * Generate the plus/minus icon for the browsable tree.
00461      *
00462      * @param   array       record for the entry
00463      * @param   integer     The current entry number
00464      * @param   integer     The total number of entries. If equal to $a, a "bottom" element is returned.
00465      * @param   integer     The number of sub-elements to the current element.
00466      * @param   boolean     The element was expanded to render subelements if this flag is set.
00467      * @return  string      Image tag with the plus/minus icon.
00468      * @access private
00469      * @see t3lib_pageTree::PMicon()
00470      */
00471     function PMicon($row,$a,$c,$nextCount,$exp) {
00472         $PM = $nextCount ? ($exp?'minus':'plus') : 'join';
00473         $BTM = ($a==$c)?'bottom':'';
00474         $icon = '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/ol/'.$PM.$BTM.'.gif','width="18" height="16"').' alt="" />';
00475 
00476         if ($nextCount) {
00477             $cmd=$this->bank.'_'.($exp?'0_':'1_').$row['uid'].'_'.$this->treeName;
00478             $bMark=($this->bank.'_'.$row['uid']);
00479             $icon = $this->PM_ATagWrap($icon,$cmd,$bMark);
00480         }
00481         return $icon;
00482     }
00483 
00484     /**
00485      * Wrap the plus/minus icon in a link
00486      *
00487      * @param   string      HTML string to wrap, probably an image tag.
00488      * @param   string      Command for 'PM' get var
00489      * @param   boolean     If set, the link will have a anchor point (=$bMark) and a name attribute (=$bMark)
00490      * @return  string      Link-wrapped input string
00491      * @access private
00492      */
00493     function PM_ATagWrap($icon,$cmd,$bMark='')  {
00494         if ($this->thisScript) {
00495             if ($bMark) {
00496                 $anchor = '#'.$bMark;
00497                 $name=' name="'.$bMark.'"';
00498             }
00499             $aUrl = $this->thisScript.'?PM='.$cmd.$anchor;
00500             return '<a href="'.htmlspecialchars($aUrl).'"'.$name.'>'.$icon.'</a>';
00501         } else {
00502             return $icon;
00503         }
00504     }
00505 
00506     /**
00507      * Wrapping $title in a-tags.
00508      *
00509      * @param   string      Title string
00510      * @param   string      Item record
00511      * @param   integer     Bank pointer (which mount point number)
00512      * @return  string
00513      * @access private
00514      */
00515     function wrapTitle($title,$row,$bank=0) {
00516         $aOnClick = 'return jumpTo(\''.$this->getJumpToParam($row).'\',this,\''.$this->domIdPrefix.$this->getId($row).'\','.$bank.');';
00517         return '<a href="#" onclick="'.htmlspecialchars($aOnClick).'">'.$title.'</a>';
00518     }
00519 
00520     /**
00521      * Wrapping the image tag, $icon, for the row, $row (except for mount points)
00522      *
00523      * @param   string      The image tag for the icon
00524      * @param   array       The row for the current element
00525      * @return  string      The processed icon input value.
00526      * @access private
00527      */
00528     function wrapIcon($icon,$row)   {
00529         return $icon;
00530     }
00531 
00532     /**
00533      * Adds attributes to image tag.
00534      *
00535      * @param   string      Icon image tag
00536      * @param   string      Attributes to add, eg. ' border="0"'
00537      * @return  string      Image tag, modified with $attr attributes added.
00538      */
00539     function addTagAttributes($icon,$attr)  {
00540         return ereg_replace(' ?\/?>$','',$icon).' '.$attr.' />';
00541     }
00542 
00543     /**
00544      * Adds a red "+" to the input string, $str, if the field "php_tree_stop" in the $row (pages) is set
00545      *
00546      * @param   string      Input string, like a page title for the tree
00547      * @param   array       record row with "php_tree_stop" field
00548      * @return  string      Modified string
00549      * @access private
00550      */
00551     function wrapStop($str,$row)    {
00552         if ($row['php_tree_stop'])  {
00553             $str.='<span class="typo3-red">+ </span>';
00554         }
00555         return $str;
00556     }
00557 
00558 
00559 
00560 
00561 
00562 
00563     /*******************************************
00564      *
00565      * tree handling
00566      *
00567      *******************************************/
00568 
00569 
00570     /**
00571      * Returns true/false if the next level for $id should be expanded - based on data in $this->stored[][] and ->expandAll flag.
00572      * Extending parent function
00573      *
00574      * @param   integer     record id/key
00575      * @return  boolean
00576      * @access private
00577      * @see t3lib_pageTree::expandNext()
00578      */
00579     function expandNext($id)    {
00580         return ($this->stored[$this->bank][$id] || $this->expandAll)? 1 : 0;
00581     }
00582 
00583     /**
00584      * Get stored tree structure AND updating it if needed according to incoming PM GET var.
00585      *
00586      * @return  void
00587      * @access private
00588      */
00589     function initializePositionSaving() {
00590             // Get stored tree structure:
00591         $this->stored=unserialize($this->BE_USER->uc['browseTrees'][$this->treeName]);
00592 
00593             // PM action
00594             // (If an plus/minus icon has been clicked, the PM GET var is sent and we must update the stored positions in the tree):
00595         $PM = explode('_',t3lib_div::_GP('PM'));    // 0: mount key, 1: set/clear boolean, 2: item ID (cannot contain "_"), 3: treeName
00596         if (count($PM)==4 && $PM[3]==$this->treeName)   {
00597             if (isset($this->MOUNTS[$PM[0]]))   {
00598                 if ($PM[1]) {   // set
00599                     $this->stored[$PM[0]][$PM[2]]=1;
00600                     $this->savePosition();
00601                 } else {    // clear
00602                     unset($this->stored[$PM[0]][$PM[2]]);
00603                     $this->savePosition();
00604                 }
00605             }
00606         }
00607     }
00608 
00609     /**
00610      * Saves the content of ->stored (keeps track of expanded positions in the tree)
00611      * $this->treeName will be used as key for BE_USER->uc[] to store it in
00612      *
00613      * @return  void
00614      * @access private
00615      */
00616     function savePosition() {
00617         $this->BE_USER->uc['browseTrees'][$this->treeName] = serialize($this->stored);
00618         $this->BE_USER->writeUC();
00619     }
00620 
00621 
00622 
00623 
00624 
00625 
00626 
00627 
00628 
00629 
00630 
00631 
00632 
00633     /******************************
00634      *
00635      * Functions that might be overwritten by extended classes
00636      *
00637      ********************************/
00638 
00639     /**
00640      * Returns the root icon for a tree/mountpoint (defaults to the globe)
00641      *
00642      * @param   array       Record for root.
00643      * @return  string      Icon image tag.
00644      */
00645     function getRootIcon($rec) {
00646         return $this->wrapIcon('<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/i/_icon_website.gif','width="18" height="16"').' alt="" />',$rec);
00647     }
00648 
00649 
00650 
00651     /**
00652      * Get icon for the row.
00653      * If $this->iconPath and $this->iconName is set, try to get icon based on those values.
00654      *
00655      * @param   array       Item row.
00656      * @return  string      Image tag.
00657      */
00658     function getIcon($row) {
00659         if ($this->iconPath && $this->iconName) {
00660             $icon = '<img'.t3lib_iconWorks::skinImg('',$this->iconPath.$this->iconName,'width="18" height="16"').' alt=""'.($this->showDefaultTitleAttribute ? ' title="UID: '.$row['uid'].'"':'').' />';
00661         } else {
00662             $icon = t3lib_iconWorks::getIconImage($this->table,$row,$this->backPath,'align="top" class="c-recIcon"'.($this->showDefaultTitleAttribute ? ' title="UID: '.$row['uid'].'"':''));
00663         }
00664 
00665         return $this->wrapIcon($icon,$row);
00666     }
00667 
00668 
00669     /**
00670      * Returns the title for the input record. If blank, a "no title" label (localized) will be returned.
00671      * Do NOT htmlspecialchar the string from this function - has already been done.
00672      *
00673      * @param   array       The input row array (where the key "title" is used for the title)
00674      * @param   integer     Title length (30)
00675      * @return  string      The title.
00676      */
00677     function getTitleStr($row,$titleLen=30) {
00678         if ($this->ext_showNavTitle && strlen(trim($row['nav_title'])) > 0) {
00679             $title = '<span title="'.$GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_tca.xml:title',1).' '.htmlspecialchars(trim($row['title'])).'">'.htmlspecialchars(t3lib_div::fixed_lgd_cs($row['nav_title'],$titleLen)).'</span>';
00680         } else {
00681             $title = htmlspecialchars(t3lib_div::fixed_lgd_cs($row['title'],$titleLen));
00682             if (strlen(trim($row['nav_title'])) > 0)    {
00683                 $title = '<span title="'.$GLOBALS['LANG']->sL('LLL:EXT:cms/locallang_tca.xml:pages.nav_title',1).' '.htmlspecialchars(trim($row['nav_title'])).'">'.$title.'</span>';
00684             }
00685             $title = (strlen(trim($row['title'])) == 0) ? '<em>['.$GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.no_title',1).']</em>' : $title;
00686         }
00687 
00688         return $title;
00689     }
00690 
00691     /**
00692      * Returns the value for the image "title" attribute
00693      *
00694      * @param   array       The input row array (where the key "title" is used for the title)
00695      * @return  string      The attribute value (is htmlspecialchared() already)
00696      * @see wrapIcon()
00697      */
00698     function getTitleAttrib($row) {
00699         return htmlspecialchars($row['title']);
00700     }
00701 
00702     /**
00703      * Returns the id from the record (typ. uid)
00704      *
00705      * @param   array       Record array
00706      * @return  integer     The "uid" field value.
00707      */
00708     function getId($row) {
00709         return $row['uid'];
00710     }
00711 
00712     /**
00713      * Returns jump-url parameter value.
00714      *
00715      * @param   array       The record array.
00716      * @return  string      The jump-url parameter.
00717      */
00718     function getJumpToParam($row) {
00719         return $this->getId($row);
00720     }
00721 
00722 
00723 
00724 
00725 
00726 
00727 
00728 
00729 
00730 
00731 
00732 
00733 
00734 
00735 
00736     /********************************
00737      *
00738      * tree data buidling
00739      *
00740      ********************************/
00741 
00742     /**
00743      * Fetches the data for the tree
00744      *
00745      * @param   integer     item id for which to select subitems (parent id)
00746      * @param   integer     Max depth (recursivity limit)
00747      * @param   string      HTML-code prefix for recursive calls.
00748      * @param   string      ? (internal)
00749      * @param   string      CSS class to use for <td> sub-elements
00750      * @return  integer     The count of items on the level
00751      */
00752     function getTree($uid, $depth=999, $depthData='',$blankLineCode='',$subCSSclass='') {
00753 
00754             // Buffer for id hierarchy is reset:
00755         $this->buffer_idH=array();
00756 
00757             // Init vars
00758         $depth=intval($depth);
00759         $HTML='';
00760         $a=0;
00761 
00762         $res = $this->getDataInit($uid,$subCSSclass);
00763         $c = $this->getDataCount($res);
00764         $crazyRecursionLimiter = 999;
00765 
00766             // Traverse the records:
00767         while ($crazyRecursionLimiter>0 && $row = $this->getDataNext($res,$subCSSclass))    {
00768             $a++;
00769             $crazyRecursionLimiter--;
00770 
00771             $newID = $row['uid'];
00772 
00773             if ($newID==0)  {
00774                 t3lib_BEfunc::typo3PrintError ('Endless recursion detected', 'TYPO3 has detected an error in the database. Please fix it manually (e.g. using phpMyAdmin) and change the UID of '.$this->table.':0 to a new value.<br /><br />See <a href="http://bugs.typo3.org/view.php?id=3495" target="_blank">bugs.typo3.org/view.php?id=3495</a> to get more information about a possible cause.',0);
00775                 exit;
00776             }
00777 
00778             $this->tree[]=array();      // Reserve space.
00779             end($this->tree);
00780             $treeKey = key($this->tree);    // Get the key for this space
00781             $LN = ($a==$c)?'blank':'line';
00782 
00783                 // If records should be accumulated, do so
00784             if ($this->setRecs) {
00785                 $this->recs[$row['uid']] = $row;
00786             }
00787 
00788                 // Accumulate the id of the element in the internal arrays
00789             $this->ids[] = $idH[$row['uid']]['uid'] = $row['uid'];
00790             $this->ids_hierarchy[$depth][] = $row['uid'];
00791             $this->orig_ids_hierarchy[$depth][] = $row['_ORIG_uid'] ? $row['_ORIG_uid'] : $row['uid'];
00792 
00793                 // Make a recursive call to the next level
00794             $HTML_depthData = $depthData.'<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/ol/'.$LN.'.gif','width="18" height="16"').' alt="" />';
00795             if ($depth>1 && $this->expandNext($newID) && !$row['php_tree_stop'])    {
00796                 $nextCount=$this->getTree(
00797                         $newID,
00798                         $depth-1,
00799                         $this->makeHTML ? $HTML_depthData : '',
00800                         $blankLineCode.','.$LN,
00801                         $row['_SUBCSSCLASS']
00802                     );
00803                 if (count($this->buffer_idH))   $idH[$row['uid']]['subrow']=$this->buffer_idH;
00804                 $exp=1; // Set "did expand" flag
00805             } else {
00806                 $nextCount=$this->getCount($newID);
00807                 $exp=0; // Clear "did expand" flag
00808             }
00809 
00810                 // Set HTML-icons, if any:
00811             if ($this->makeHTML)    {
00812                 $HTML = $depthData.$this->PMicon($row,$a,$c,$nextCount,$exp);
00813                 $HTML.=$this->wrapStop($this->getIcon($row),$row);
00814                 #   $HTML.=$this->wrapStop($this->wrapIcon($this->getIcon($row),$row),$row);
00815             }
00816 
00817                 // Finally, add the row/HTML content to the ->tree array in the reserved key.
00818             $this->tree[$treeKey] = Array(
00819                 'row'=>$row,
00820                 'HTML'=>$HTML,
00821                 'HTML_depthData' => $this->makeHTML==2 ? $HTML_depthData : '',
00822                 'invertedDepth'=>$depth,
00823                 'blankLineCode'=>$blankLineCode,
00824                 'bank' => $this->bank
00825             );
00826         }
00827 
00828         $this->getDataFree($res);
00829         $this->buffer_idH=$idH;
00830         return $c;
00831     }
00832 
00833 
00834 
00835 
00836 
00837 
00838 
00839 
00840 
00841 
00842 
00843 
00844     /********************************
00845      *
00846      * Data handling
00847      * Works with records and arrays
00848      *
00849      ********************************/
00850 
00851     /**
00852      * Returns the number of records having the parent id, $uid
00853      *
00854      * @param   integer     id to count subitems for
00855      * @return  integer
00856      * @access private
00857      */
00858     function getCount($uid) {
00859         if (is_array($this->data)) {
00860             $res = $this->getDataInit($uid);
00861             return $this->getDataCount($res);
00862         } else {
00863             $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
00864                         'count(*)',
00865                         $this->table,
00866                         $this->parentField.'='.$GLOBALS['TYPO3_DB']->fullQuoteStr($uid, $this->table).
00867                             t3lib_BEfunc::deleteClause($this->table).
00868                             t3lib_BEfunc::versioningPlaceholderClause($this->table).
00869                             $this->clause   // whereClauseMightContainGroupOrderBy
00870                     );
00871             $row = $GLOBALS['TYPO3_DB']->sql_fetch_row($res);
00872             return $row[0];
00873         }
00874     }
00875 
00876 
00877 
00878     /**
00879      * Returns root record for uid (<=0)
00880      *
00881      * @param   integer     uid, <= 0 (normally, this does not matter)
00882      * @return  array       Array with title/uid keys with values of $this->title/0 (zero)
00883      */
00884     function getRootRecord($uid) {
00885         return array('title' => $this->title, 'uid' => 0);
00886     }
00887 
00888 
00889     /**
00890      * Returns the record for a uid.
00891      * For tables: Looks up the record in the database.
00892      * For arrays: Returns the fake record for uid id.
00893      *
00894      * @param   integer     UID to look up
00895      * @return  array       The record
00896      */
00897     function getRecord($uid) {
00898         if (is_array($this->data)) {
00899             return $this->dataLookup[$uid];
00900         } else {
00901             return t3lib_BEfunc::getRecordWSOL($this->table, $uid);
00902         }
00903     }
00904 
00905     /**
00906      * Getting the tree data: Selecting/Initializing data pointer to items for a certain parent id.
00907      * For tables: This will make a database query to select all children to "parent"
00908      * For arrays: This will return key to the ->dataLookup array
00909      *
00910      * @param   integer     parent item id
00911      * @param   string      Class for sub-elements.
00912      * @return  mixed       data handle (Tables: An sql-resource, arrays: A parentId integer. -1 is returned if there were NO subLevel.)
00913      * @access private
00914      */
00915     function getDataInit($parentId,$subCSSclass='') {
00916         if (is_array($this->data)) {
00917             if (!is_array($this->dataLookup[$parentId][$this->subLevelID])) {
00918                 $parentId = -1;
00919             } else {
00920                 reset($this->dataLookup[$parentId][$this->subLevelID]);
00921             }
00922             return $parentId;
00923         } else {
00924             $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
00925                         implode(',',$this->fieldArray),
00926                         $this->table,
00927                         $this->parentField.'='.$GLOBALS['TYPO3_DB']->fullQuoteStr($parentId, $this->table).
00928                             t3lib_BEfunc::deleteClause($this->table).
00929                             t3lib_BEfunc::versioningPlaceholderClause($this->table).
00930                             $this->clause,  // whereClauseMightContainGroupOrderBy
00931                         '',
00932                         $this->orderByFields
00933                     );
00934             return $res;
00935         }
00936     }
00937 
00938     /**
00939      * Getting the tree data: Counting elements in resource
00940      *
00941      * @param   mixed       data handle
00942      * @return  integer     number of items
00943      * @access private
00944      * @see getDataInit()
00945      */
00946     function getDataCount(&$res) {
00947         if (is_array($this->data)) {
00948             return count($this->dataLookup[$res][$this->subLevelID]);
00949         } else {
00950             $c = $GLOBALS['TYPO3_DB']->sql_num_rows($res);
00951             return $c;
00952         }
00953     }
00954 
00955     /**
00956      * Getting the tree data: next entry
00957      *
00958      * @param   mixed       data handle
00959      * @param   string      CSS class for sub elements (workspace related)
00960      * @return  array       item data array OR FALSE if end of elements.
00961      * @access private
00962      * @see getDataInit()
00963      */
00964     function getDataNext(&$res,$subCSSclass='') {
00965         if (is_array($this->data)) {
00966             if ($res<0) {
00967                 $row=FALSE;
00968             } else {
00969                 list(,$row) = each($this->dataLookup[$res][$this->subLevelID]);
00970 
00971                     // Passing on default <td> class for subelements:
00972                 if (is_array($row) && $subCSSclass!=='')    {
00973                     $row['_CSSCLASS'] = $row['_SUBCSSCLASS'] = $subCSSclass;
00974                 }
00975             }
00976             return $row;
00977         } else {
00978             while($row = @$GLOBALS['TYPO3_DB']->sql_fetch_assoc($res))  {
00979                 t3lib_BEfunc::workspaceOL($this->table, $row, $this->BE_USER->workspace, TRUE);
00980                 if (is_array($row)) break;
00981             }
00982 
00983                 // Passing on default <td> class for subelements:
00984             if (is_array($row) && $subCSSclass!=='')    {
00985 
00986                 if ($this->table==='pages' && $this->highlightPagesWithVersions && !isset($row['_CSSCLASS']) && count(t3lib_BEfunc::countVersionsOfRecordsOnPage($this->BE_USER->workspace, $row['uid'], TRUE)))    {
00987                     $row['_CSSCLASS'] = 'ver-versions';
00988                 }
00989 
00990                 if (!isset($row['_CSSCLASS']))  $row['_CSSCLASS'] = $subCSSclass;
00991                 if (!isset($row['_SUBCSSCLASS']))   $row['_SUBCSSCLASS'] = $subCSSclass;
00992             }
00993 
00994             return $row;
00995         }
00996     }
00997 
00998     /**
00999      * Getting the tree data: frees data handle
01000      *
01001      * @param   mixed       data handle
01002      * @return  void
01003      * @access private
01004      */
01005     function getDataFree(&$res) {
01006         if (!is_array($this->data)) {
01007             $GLOBALS['TYPO3_DB']->sql_free_result($res);
01008         }
01009     }
01010 
01011     /**
01012      * Used to initialize class with an array to browse.
01013      * The array inputted will be traversed and an internal index for lookup is created.
01014      * The keys of the input array are perceived as "uid"s of records which means that keys GLOBALLY must be unique like uids are.
01015      * "uid" and "pid" "fakefields" are also set in each record.
01016      * All other fields are optional.
01017      *
01018      * @param   array       The input array, see examples below in this script.
01019      * @param   boolean     Internal, for recursion.
01020      * @param   integer     Internal, for recursion.
01021      * @return  void
01022      */
01023     function setDataFromArray(&$dataArr,$traverse=FALSE,$pid=0) {
01024         if (!$traverse) {
01025             $this->data = &$dataArr;
01026             $this->dataLookup=array();
01027                 // add root
01028             $this->dataLookup[0][$this->subLevelID]=&$dataArr;
01029         }
01030 
01031         foreach($dataArr as $uid => $val)   {
01032 
01033             $dataArr[$uid]['uid']=$uid;
01034             $dataArr[$uid]['pid']=$pid;
01035 
01036                 // gives quick access to id's
01037             $this->dataLookup[$uid] = &$dataArr[$uid];
01038 
01039             if (is_array($val[$this->subLevelID])) {
01040                 $this->setDataFromArray($dataArr[$uid][$this->subLevelID],TRUE,$uid);
01041             }
01042         }
01043     }
01044 
01045     /**
01046      * Sets the internal data arrays
01047      *
01048      * @param   array       Content for $this->data
01049      * @param   array       Content for $this->dataLookup
01050      * @return  void
01051      */
01052     function setDataFromTreeArray(&$treeArr, &$treeLookupArr)   {
01053         $this->data = &$treeArr;
01054         $this->dataLookup=&$treeLookupArr;
01055     }
01056 
01057 
01058     /*
01059         array(
01060             [id1] => array(
01061                 'title'=>'title...',
01062                 'id' => 'id1',
01063                 'icon' => 'icon ref, relative to typo3/ folder...'
01064             ),
01065             [id2] => array(
01066                 'title'=>'title...',
01067                 'id' => 'id2',
01068                 'icon' => 'icon ref, relative to typo3/ folder...'
01069             ),
01070             [id3] => array(
01071                 'title'=>'title...',
01072                 'id' => 'id3',
01073                 'icon' => 'icon ref, relative to typo3/ folder...'
01074                 $this->subLevelID => array(
01075                     [id3_asdf#1] => array(
01076                         'title'=>'title...',
01077                         'id' => 'asdf#1',
01078                         'icon' => 'icon ref, relative to typo3/ folder...'
01079                     ),
01080                     [5] => array(
01081                         'title'=>'title...',
01082                         'id' => 'id...',
01083                         'icon' => 'icon ref, relative to typo3/ folder...'
01084                     ),
01085                     [6] => array(
01086                         'title'=>'title...',
01087                         'id' => 'id...',
01088                         'icon' => 'icon ref, relative to typo3/ folder...'
01089                     ),
01090                 )
01091             ),
01092         )
01093 */
01094 }
01095 
01096 
01097 if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_treeview.php'])  {
01098     include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_treeview.php']);
01099 }
01100 
01101 ?>

Generated on Sat Jan 3 04:23:28 2009 for TYPO3 API by  doxygen 1.4.7