eZ Publish  [4.0]
ezcontentstructuretreeoperator.php
Go to the documentation of this file.
00001 <?php
00002 //
00003 // Definition of eZContentStructureTreeOperator class
00004 //
00005 // Created on: <14-Jul-2004 14:18:58 dl>
00006 //
00007 // ## BEGIN COPYRIGHT, LICENSE AND WARRANTY NOTICE ##
00008 // SOFTWARE NAME: eZ Publish
00009 // SOFTWARE RELEASE: 4.0.x
00010 // COPYRIGHT NOTICE: Copyright (C) 1999-2008 eZ Systems AS
00011 // SOFTWARE LICENSE: GNU General Public License v2.0
00012 // NOTICE: >
00013 //   This program is free software; you can redistribute it and/or
00014 //   modify it under the terms of version 2.0  of the GNU General
00015 //   Public License as published by the Free Software Foundation.
00016 //
00017 //   This program is distributed in the hope that it will be useful,
00018 //   but WITHOUT ANY WARRANTY; without even the implied warranty of
00019 //   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00020 //   GNU General Public License for more details.
00021 //
00022 //   You should have received a copy of version 2.0 of the GNU General
00023 //   Public License along with this program; if not, write to the Free
00024 //   Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
00025 //   MA 02110-1301, USA.
00026 //
00027 //
00028 // ## END COPYRIGHT, LICENSE AND WARRANTY NOTICE ##
00029 //
00030 
00031 /*! \file ezcontentstructuretreeoperator.php
00032 */
00033 
00034 /*!
00035   \class eZContentStructureTreeOperator ezcontentstructuretreeoperator.php
00036   \brief
00037 */
00038 
00039 require_once( 'kernel/classes/ezcontentlanguage.php' );
00040 //include_once( 'kernel/classes/ezcontentclassnamelist.php' );
00041 
00042 class eZContentStructureTreeOperator
00043 {
00044     function eZContentStructureTreeOperator( $name = 'content_structure_tree' )
00045     {
00046         $this->Operators = array( $name );
00047     }
00048 
00049     /*!
00050      Returns the operators in this class.
00051     */
00052     function operatorList()
00053     {
00054         return $this->Operators;
00055     }
00056 
00057     /*!
00058      See eZTemplateOperator::namedParameterList()
00059     */
00060     function namedParameterList()
00061     {
00062         return array( 'root_node_id' => array( 'type' => 'int',
00063                                                'required' => true,
00064                                                'default' => 0 ),
00065                       'class_filter' => array( 'type' => 'array',
00066                                                'required' => false,
00067                                                'default' => false ),
00068                       'max_depth' => array( 'type' => 'int',
00069                                             'required' => false,
00070                                             'default' => 0 ),
00071                       'max_nodes' => array( 'type' => 'int',
00072                                             'required' => false,
00073                                             'default' => 0 ),
00074                       'sort_by' => array( 'type' => 'array',
00075                                           'required' => false,
00076                                           'default' => 'false' ),
00077                       'fetch_hidden' => array( 'type' => 'bool',
00078                                                'required' => false,
00079                                                'default' => 'false' ),
00080                       'unfold_node_id' => array( 'type' => 'int',
00081                                                'required' => false,
00082                                                'default' => 0 ) );
00083     }
00084 
00085     /*!
00086      \reimp
00087     */
00088     function modify( $tpl, $operatorName, $operatorParameters, $rootNamespace, $currentNamespace, &$operatorValue, $namedParameters )
00089     {
00090         $sortArray = false;
00091         $fetchHidden = false;
00092         if ( $namedParameters[ 'sort_by' ] != 'false' )
00093         {
00094             if( is_array($namedParameters[ 'sort_by' ]))
00095             {
00096                 $sortArray = array();
00097                 foreach( $namedParameters[ 'sort_by' ] as $parameter )
00098                 {
00099                     $sortingMethod = explode("/", $parameter );
00100                     $sortingMethod[1] = ($sortingMethod[1] == 'ascending') ? '1' : '0';
00101                     $sortArray[] = $sortingMethod;
00102                 }
00103             }
00104             else
00105             {
00106                 $sortingMethod = explode("/", $namedParameters[ 'sort_by' ]);
00107                 $sortingMethod[1] = ($sortingMethod[1] == 'ascending') ? '1' : '0';
00108                 $sortArray = array();
00109                 $sortArray[] = $sortingMethod;
00110             }
00111         }
00112 
00113         if ( $namedParameters[ 'fetch_hidden' ] != 'false' )
00114         {
00115             $fetchHidden = true;
00116         }
00117         $operatorValue = eZContentStructureTreeOperator::contentStructureTree( $namedParameters['root_node_id'],
00118                                                                                $namedParameters['class_filter'],
00119                                                                                $namedParameters['max_depth'],
00120                                                                                $namedParameters['max_nodes'],
00121                                                                                $sortArray,
00122                                                                                $fetchHidden,
00123                                                                                $namedParameters['unfold_node_id'] );
00124     }
00125 
00126     /*!
00127         \static
00128         Returns one-level children of node \a $nodeID if \a $countChildren = false,
00129         othewise returns count of one-level children of node \a nodeID.
00130     */
00131     function subTree( $params, $nodeID, $countChildren = false )
00132     {
00133         $nodeListArray = array();
00134 
00135         // sorting params
00136         $sortingInfo = eZContentObjectTreeNode::createSortingSQLStrings( $params['SortBy'] );
00137 
00138         // node params
00139         $notEqParentString = '';
00140         $pathStringCond    = '';
00141         eZContentObjectTreeNode::createPathConditionAndNotEqParentSQLStrings( $pathStringCond, $notEqParentString, $nodeID, 1, false );
00142 
00143         // class filter
00144         $classCondition = eZContentObjectTreeNode::createClassFilteringSQLString( $params['ClassFilterType'], $params['ClassFilterArray'] );
00145         if ( $classCondition === false )
00146         {
00147             return $nodeListArray;
00148         }
00149 
00150         // permissions
00151         $limitationParams = false;
00152         $limitationList = eZContentObjectTreeNode::getLimitationList( $limitationParams );
00153 
00154         if ( $limitationList === false )
00155         {
00156             return $nodeListArray;
00157         }
00158 
00159         $permissionChecking = eZContentObjectTreeNode::createPermissionCheckingSQL( $limitationList );
00160 
00161         // version
00162         $useVersionName = true;
00163         $versionNameTables = eZContentObjectTreeNode::createVersionNameTablesSQLString( $useVersionName );
00164         $versionNameTargets = eZContentObjectTreeNode::createVersionNameTargetsSQLString( $useVersionName );
00165         $versionNameJoins = eZContentObjectTreeNode::createVersionNameJoinsSQLString( $useVersionName );
00166 
00167         // invisible nodes.
00168         $showInvisibleNodesCond = eZContentObjectTreeNode::createShowInvisibleSQLString( false, $params['FetchHidden'] );
00169 
00170         $query = '';
00171         if ( $countChildren )
00172         {
00173             $query = "SELECT count(*) as count
00174                           FROM
00175                                ezcontentobject_tree,
00176                                ezcontentobject,ezcontentclass
00177                                $versionNameTables
00178                                $permissionChecking[from]
00179                           WHERE $pathStringCond
00180                                 $classCondition
00181                                 ezcontentclass.version=0 AND
00182                                 $notEqParentString
00183                                 ezcontentobject_tree.contentobject_id = ezcontentobject.id  AND
00184                                 ezcontentclass.id = ezcontentobject.contentclass_id
00185                                 $versionNameJoins
00186                                 $permissionChecking[where] ";
00187         }
00188         else
00189         {
00190             $query = "SELECT ezcontentobject.*,
00191                              ezcontentobject_tree.*,
00192                              ezcontentclass.serialized_name_list as class_serialized_name_list,
00193                              ezcontentclass.identifier as class_identifier,
00194                              ezcontentclass.is_container as is_container
00195                              $versionNameTargets
00196                       FROM
00197                              ezcontentobject_tree,
00198                              ezcontentobject,ezcontentclass
00199                              $versionNameTables
00200                              $sortingInfo[attributeFromSQL]
00201                              $permissionChecking[from]
00202                       WHERE
00203                              $pathStringCond
00204                              $sortingInfo[attributeWhereSQL]
00205                              ezcontentclass.version=0 AND
00206                              $notEqParentString
00207                              ezcontentobject_tree.contentobject_id = ezcontentobject.id  AND
00208                              ezcontentclass.id = ezcontentobject.contentclass_id AND
00209                              $classCondition
00210                              ezcontentobject_tree.contentobject_is_published = 1
00211                              $versionNameJoins
00212                              $showInvisibleNodesCond
00213                              $permissionChecking[where]
00214                       ORDER BY $sortingInfo[sortingFields]";
00215 
00216         }
00217 
00218         $db = eZDB::instance();
00219         $nodeListArray = $db->arrayQuery( $query );
00220 
00221         // cleanup temp tables
00222         $db->dropTempTableList( $permissionChecking['temp_tables'] );
00223 
00224         if ( $countChildren )
00225         {
00226             return $nodeListArray[0]['count'];
00227         }
00228         else
00229         {
00230             foreach ( $nodeListArray as $key => $row )
00231             {
00232                 $nodeListArray[$key]['path_identification_string'] = eZContentObjectTreeNode::fetch( $row['node_id'] )->pathWithNames();
00233             }
00234             return $nodeListArray;
00235         }
00236     }
00237 
00238     /*!
00239      \static
00240      \Returns a tree of content structure:
00241             tree = array( tree_node, children ), where
00242                 'tree_node' is array( 'node'             => info about node,
00243                                       'object'           => info about object );
00244 
00245                 'children' is array( tree_node, children );
00246     */
00247     function contentStructureTree( $rootNodeID, $classFilter, $maxDepth, $maxNodes, $sortArray, $fetchHidden, $unfoldNodeID )
00248     {
00249         $contentTree = eZContentStructureTreeOperator::initContentStructureTree( $rootNodeID, $fetchHidden, $classFilter );
00250 
00251         // if root node is invisible then no point to fetch children
00252         //if ( count( $contentTree ) == 0 )
00253         //    return $contentTree;
00254 
00255         if ( $contentTree === false)
00256             return $contentTree;
00257 
00258         $nodesLeft = $maxNodes - 1;
00259         $depthLeft = $maxDepth - 1;
00260 
00261         eZContentStructureTreeOperator::children( $contentTree, $classFilter, $depthLeft, $nodesLeft, $sortArray, $fetchHidden, $unfoldNodeID );
00262 
00263         return $contentTree;
00264     }
00265 
00266     /*!
00267      \static
00268      \private
00269         Parameters the same as in \a children.
00270      \Returns one-level children.
00271     */
00272     function oneLevelChildren( &$contentTree, &$classFilter, &$sortBy, &$nodesLeft, $fetchHidden )
00273     {
00274         $parentNode = $contentTree['parent_node'];
00275 
00276         if ( !is_array( $parentNode ) || count( $parentNode['node'] ) == 0 )
00277         {
00278             return false;
00279         }
00280 
00281         if ( !$parentNode['object']['is_container'] || $parentNode['node']['children_count'] == 0 )
00282         {
00283             return true;
00284         }
00285 
00286         // fill parent node attributes
00287         if ( $nodesLeft != 0)
00288         {
00289             // get children
00290             $sortArray = ( $sortBy == false ) ? $parentNode['node']['sort_array'] : $sortBy;
00291 
00292             $children = eZContentStructureTreeOperator::subTree( array(  'SortBy' => $sortArray,
00293                                                                          'ClassFilterType' => 'include',
00294                                                                          'ClassFilterArray'=> $classFilter,
00295                                                                          'NodePath' => $parentNode['node']['path_string'],
00296                                                                          'NodeDepth' => $parentNode['node']['depth'],
00297                                                                          'FetchHidden' => $fetchHidden ),
00298                                                                  $parentNode['node']['node_id'] );
00299             if ( $children && count( $children ) > 0 )
00300             {
00301                 $childrenNodes =& $contentTree['children'];
00302                 // fill children attributes
00303                 foreach ( $children as $child )
00304                 {
00305                     $childrenCount = 0;
00306 
00307                     if ( $child['is_container'] == '1' )
00308                     {
00309                         $childrenCount = eZContentStructureTreeOperator::subTree( array(  'SortBy' => false,
00310                                                                               'ClassFilterType' => 'include',
00311                                                                               'ClassFilterArray'=> $classFilter,
00312                                                                               'NodePath' => $child['path_string'],
00313                                                                               'NodeDepth' => $child['depth'],
00314                                                                               'FetchHidden' => $fetchHidden ),
00315                                                                       $child['node_id'],
00316                                                                       true );
00317                     }
00318 
00319                     $childNode = eZContentStructureTreeOperator::createContentStructureNode( $child, $childrenCount );
00320 
00321                     $childrenNodes[] = array( 'parent_node' => $childNode,
00322                                               'children' => array() );
00323 
00324                     --$nodesLeft;
00325                     if ( $nodesLeft == 0 )
00326                     {
00327                         return false;
00328                     }
00329                 }
00330             }
00331             return true;
00332         }
00333 
00334         return false;
00335     }
00336 
00337     /*!
00338      \static
00339      \private
00340         Creates a tree of content by recursive calls to \a children and \a oneLevelChildren.
00341         \a $contentTree is a tree at previous call to \a children.
00342         \a $classFilter is an array of class ids. Only nodes of these classes will be fetched from db.
00343         \a $depthLeft determines a depth of recursion.
00344         \a $nodesLeft determines a number of nodes which are left to fetch.
00345         \a $sortBy is a method of sorting one-level children.
00346         \a $fetchHidden - should or not fetch unpublished/hidden nodes
00347     */
00348     function children( &$contentTree, &$classFilter, &$depthLeft, &$nodesLeft, &$sortBy, $fetchHidden, $unfoldNodeID )
00349     {
00350         if ( $depthLeft == 0 )
00351             return false;
00352 
00353         if ( eZContentStructureTreeOperator::oneLevelChildren( $contentTree, $classFilter, $sortBy, $nodesLeft, $fetchHidden ) )
00354         {
00355             --$depthLeft;
00356             if ( $depthLeft != 0 )
00357             {
00358                 $children =& $contentTree['children'];
00359 
00360                 foreach( $children as &$child )
00361                 {
00362                     $currentDepth = $depthLeft;
00363 
00364                     if ( $unfoldNodeID != 0 and $unfoldNodeID != $child['parent_node']['node']['node_id'] )
00365                         continue;
00366 
00367                     if ( !eZContentStructureTreeOperator::children( $child, $classFilter, $currentDepth, $nodesLeft, $sortBy, $fetchHidden, 0 ) )
00368                     {
00369                         return false;
00370                     }
00371                 }
00372             }
00373             return true;
00374         }
00375         return false;
00376     }
00377 
00378     /*!
00379      \static
00380      \private
00381         Creates a node of content structure tree and sets up attributes of node
00382         using \a $treeNode to retrieve necessary data.
00383      \return new content structure tree node.
00384     */
00385     function createContentStructureNode( &$treeNode, $childrenCount )
00386     {
00387         $node = array( 'node' => array( 'node_id' => $treeNode['node_id'],
00388                                         'path_identification_string' => $treeNode['path_identification_string'],
00389                                         'children_count' => $childrenCount,
00390                                         'sort_array' => eZContentObjectTreeNode::sortArrayBySortFieldAndSortOrder( $treeNode['sort_field'], $treeNode['sort_order'] ),
00391                                         'path_string' => $treeNode['path_string'],
00392                                         'depth' => $treeNode['depth'],
00393                                         'is_hidden' => $treeNode['is_hidden'],
00394                                         'is_invisible' => $treeNode['is_invisible'] ),
00395                                         'classes_js_array' => eZContentObjectTreeNode::availableClassListJsArray( array( 'path_string' => $treeNode['path_string'], 'is_container' => $treeNode['is_container'], 'node_id' => $treeNode['node_id'] ) ),
00396                        'object' => array( 'id' => $treeNode['id'],
00397                                           'name' => $treeNode['name'],
00398                                           'class_identifier' => $treeNode['class_identifier'],
00399                                           'class_name' => eZContentClass::nameFromSerializedString( $treeNode['class_serialized_name_list'] ),
00400                                           'published' => $treeNode['published'],
00401                                           'is_container' => ( $treeNode['is_container'] == '1' ),
00402                                           'language_js_array' => eZContentLanguage::jsArrayByMask( $treeNode['language_mask'] ) ) );
00403         return $node;
00404     }
00405 
00406     /*!
00407      \static
00408      \private
00409         Initializes a tree: creates root node.
00410      \return a tree with one node and empty children subtree.
00411     */
00412     function initContentStructureTree( $rootNodeID, $fetchHidden, $classFilter = false )
00413     {
00414         // create initial subtree with root node and empty children.
00415         $nodes = false;
00416         $rootTreeNode = eZContentObjectTreeNode::fetch( $rootNodeID );
00417         if ( $rootTreeNode && $rootTreeNode->canRead() )
00418         {
00419             if ( !$fetchHidden && ( $rootTreeNode->attribute( 'is_hidden' ) || $rootTreeNode->attribute( 'is_invisible' ) ) )
00420             {
00421                 return false;
00422             }
00423             else
00424             {
00425                 $contentObject = $rootTreeNode->attribute( 'object' );
00426 
00427                 $viewNodeAllowed = true;
00428                 if ( is_array( $classFilter ) && count( $classFilter ) > 0 )
00429                 {
00430                     $contentClassIdentifier = $contentObject->attribute( 'class_identifier' );
00431 
00432                     if ( !in_array( $contentClassIdentifier, $classFilter ) )
00433                         $viewNodeAllowed = false;
00434                 }
00435 
00436                 if ( $viewNodeAllowed )
00437                 {
00438                     $rootNode = array( 'node' => array( 'node_id' => $rootTreeNode->attribute( 'node_id' ),
00439                                                         'path_identification_string' => $rootTreeNode->pathWithNames(),
00440                                                         'children_count' => $rootTreeNode->attribute( 'children_count' ),
00441                                                         'sort_array' => $rootTreeNode->attribute( 'sort_array' ),
00442                                                         'path_string' => $rootTreeNode->attribute( 'path_string' ),
00443                                                         'depth' => $rootTreeNode->attribute( 'depth' ),
00444                                                         'is_hidden' => $rootTreeNode->attribute( 'is_hidden' ),
00445                                                         'is_invisible' => $rootTreeNode->attribute( 'is_invisible' ) ),
00446                                                         'classes_js_array' => eZContentObjectTreeNode::availableClassListJsArray( array( 'node' => &$rootTreeNode ) ),
00447                                        'object' => array( 'id' => $contentObject->attribute( 'id' ),
00448                                                           'name' => $contentObject->attribute( 'name' ),
00449                                                           'class_identifier' => $contentObject->attribute( 'class_identifier' ),
00450                                                           'class_name' => $contentObject->attribute('class_name'),
00451                                                           'published' => $contentObject->attribute( 'published' ),
00452                                                           'is_container' => true,
00453                                                           'language_js_array' => eZContentLanguage::jsArrayByMask( $contentObject->attribute( 'language_mask' ) ) ) );
00454 
00455                     $nodes = array( 'parent_node' => &$rootNode,
00456                                     'children' => array() );
00457                 }
00458             }
00459         }
00460 
00461         return $nodes;
00462     }
00463 
00464     /// \privatesection
00465     public $Operators;
00466 }
00467 ?>