00001 <?php
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064 include_once( "lib/ezutils/classes/ezini.php" );
00065 include_once( "lib/ezutils/classes/ezhttptool.php" );
00066 include_once( "lib/ezutils/classes/ezdebugsetting.php" );
00067 include_once( "kernel/classes/ezcontentobject.php" );
00068 include_once( "kernel/classes/ezurlalias.php" );
00069
00070 class eZContentObjectTreeNode extends eZPersistentObject
00071 {
00072
00073
00074
00075 function eZContentObjectTreeNode( $row = array() )
00076 {
00077 $this->eZPersistentObject( $row );
00078 }
00079
00080 function definition()
00081 {
00082 return array( "fields" => array( "node_id" => array( 'name' => "NodeID",
00083 'datatype' => 'integer',
00084 'default' => 0,
00085 'required' => true ),
00086 "parent_node_id" => array( 'name' => "ParentNodeID",
00087 'datatype' => 'integer',
00088 'default' => 0,
00089 'required' => true,
00090 'foreign_class' => 'eZContentObjectTreeNode',
00091 'foreign_attribute' => 'node_id',
00092 'multiplicity' => '1..*' ),
00093 "main_node_id" => array( 'name' => "MainNodeID",
00094 'datatype' => 'integer',
00095 'default' => 0,
00096 'required' => true,
00097 'foreign_class' => 'eZContentObjectTreeNode',
00098 'foreign_attribute' => 'node_id',
00099 'multiplicity' => '1..*' ),
00100 "contentobject_id" => array( 'name' => "ContentObjectID",
00101 'datatype' => 'integer',
00102 'default' => 0,
00103 'required' => true,
00104 'foreign_class' => 'eZContentObject',
00105 'foreign_attribute' => 'id',
00106 'multiplicity' => '1..*' ),
00107 'contentobject_version' => array( 'name' => 'ContentObjectVersion',
00108 'datatype' => 'integer',
00109 'default' => 0,
00110 'required' => true ),
00111 'contentobject_is_published' => array( 'name' => 'ContentObjectIsPublished',
00112 'datatype' => 'integer',
00113 'default' => 0,
00114 'required' => true ),
00115 "depth" => array( 'name' => "Depth",
00116 'datatype' => 'integer',
00117 'default' => 0,
00118 'required' => true ),
00119 'sort_field' => array( 'name' => 'SortField',
00120 'datatype' => 'integer',
00121 'default' => 1,
00122 'required' => true ),
00123 'sort_order' => array( 'name' => 'SortOrder',
00124 'datatype' => 'integer',
00125 'default' => 1,
00126 'required' => true ),
00127 'priority' => array( 'name' => 'Priority',
00128 'datatype' => 'integer',
00129 'default' => 0,
00130 'required' => true ),
00131 'modified_subnode' => array( 'name' => 'ModifiedSubNode',
00132 'datatype' => 'integer',
00133 'default' => 0,
00134 'required' => true ),
00135 "path_string" => array( 'name' => "PathString",
00136 'datatype' => 'string',
00137 'default' => '',
00138 'required' => true ),
00139 "path_identification_string" => array( 'name' => "PathIdentificationString",
00140 'datatype' => 'text',
00141 'default' => '',
00142 'required' => true ),
00143 'remote_id' => array( 'name' => 'RemoteID',
00144 'datatype' => 'string',
00145 'default' => '',
00146 'required' => true ),
00147 "is_hidden" => array( 'name' => "IsHidden",
00148 'datatype' => 'integer',
00149 'default' => 0,
00150 'required' => true ),
00151 "is_invisible" => array( 'name' => "IsInvisible",
00152 'datatype' => 'integer',
00153 'default' => 0,
00154 'required' => true ) ),
00155 "keys" => array( "node_id" ),
00156 "function_attributes" => array( "name" => "getName",
00157 'data_map' => 'dataMap',
00158 'remote_id' => 'remoteID',
00159 "object" => "object",
00160 "subtree" => "subTree",
00161 "children" => "children",
00162 "children_count" => "childrenCount",
00163 'view_count' => 'viewCount',
00164 'contentobject_version_object' => 'contentObjectVersionObject',
00165 'sort_array' => 'sortArray',
00166 'can_read' => 'canRead',
00167 'can_pdf' => 'canPdf',
00168 'can_create' => 'canCreate',
00169 'can_edit' => 'canEdit',
00170 'can_hide' => 'canHide',
00171 'can_remove' => 'canRemove',
00172 'can_move' => 'canMoveFrom',
00173 'can_move_from' => 'canMoveFrom',
00174 'can_add_location' => 'canAddLocation',
00175 'can_remove_location' => 'canRemoveLocation',
00176 'can_view_embed' => 'canViewEmbed',
00177 'is_main' => 'isMain',
00178 'creator' => 'creator',
00179 "path" => "fetchPath",
00180 'path_array' => 'pathArray',
00181 "parent" => "fetchParent",
00182 'url' => 'url',
00183 'url_alias' => 'urlAlias',
00184 'class_identifier' => 'classIdentifier',
00185 'class_name' => 'className',
00186 'hidden_invisible_string' => 'hiddenInvisibleString',
00187 'hidden_status_string' => 'hiddenStatusString',
00188 'classes_js_array' => 'availableClassesJsArray' ),
00189 "increment_key" => "node_id",
00190 "class_name" => "eZContentObjectTreeNode",
00191 "name" => "ezcontentobject_tree" );
00192 }
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203 function create( $parentNodeID = null, $contentObjectID = null, $contentObjectVersion = 0,
00204 $sortField = 0, $sortOrder = true )
00205 {
00206 $row = array( 'node_id' => null,
00207 'main_node_id' => null,
00208 'parent_node_id' => $parentNodeID,
00209 'contentobject_id' => $contentObjectID,
00210 'contentobject_version' => $contentObjectVersion,
00211 'contentobject_is_published' => false,
00212 'depth' => 1,
00213 'path_string' => null,
00214 'path_identification_string' => null,
00215 'is_hidden' => false,
00216 'is_invisible' => false,
00217 'sort_field' => $sortField,
00218 'sort_order' => $sortOrder,
00219 'modified_subnode' => 0,
00220 'remote_id' => md5( (string)mt_rand() . (string)mktime() ),
00221 'priority' => 0 );
00222 $node = new eZContentObjectTreeNode( $row );
00223 return $node;
00224 }
00225
00226
00227
00228
00229
00230
00231 function &dataMap()
00232 {
00233 $obj =& $this->object();
00234 return $obj->fetchDataMap( $this->attribute( 'contentobject_version' ) );
00235 }
00236
00237
00238
00239
00240
00241 function &remoteID()
00242 {
00243 $remoteID = eZPersistentObject::attribute( 'remote_id', true );
00244 if ( !$remoteID )
00245 {
00246 $this->setAttribute( 'remote_id', md5( (string)mt_rand() . (string)mktime() ) );
00247 $this->sync( array( 'remote_id' ) );
00248 $remoteID = eZPersistentObject::attribute( 'remote_id', true );
00249 }
00250
00251 return $remoteID;
00252 }
00253
00254
00255
00256
00257 function &isMain()
00258 {
00259 $retVal = $this->NodeID == $this->MainNodeID;
00260 return $retVal;
00261 }
00262
00263
00264
00265
00266
00267
00268 function classAttributeIDByIdentifier( $identifier )
00269 {
00270 $db =& eZDB::instance();
00271 $dbName = $db->DB;
00272
00273 include_once( 'lib/ezutils/classes/ezphpcreator.php' );
00274 $cacheDir = eZSys::cacheDirectory();
00275 $phpCache = new eZPHPCreator( "$cacheDir", "classattributeidentifiers_$dbName.php" );
00276
00277 include_once( 'lib/ezutils/classes/ezexpiryhandler.php' );
00278 $handler =& eZExpiryHandler::instance();
00279 $expiryTime = 0;
00280 if ( $handler->hasTimestamp( 'class-identifier-cache' ) )
00281 {
00282 $expiryTime = $handler->timestamp( 'class-identifier-cache' );
00283 }
00284
00285 if ( $phpCache->canRestore( $expiryTime ) )
00286 {
00287 $var = $phpCache->restore( array( 'identifierHash' => 'identifier_hash' ) );
00288 $identifierHash =& $var['identifierHash'];
00289 }
00290 else
00291 {
00292
00293 $query = "SELECT ezcontentclass_attribute.id as attribute_id, ezcontentclass_attribute.identifier as attribute_identifier, ezcontentclass.identifier as class_identifier
00294 FROM ezcontentclass_attribute, ezcontentclass
00295 WHERE ezcontentclass.id=ezcontentclass_attribute.contentclass_id";
00296 $identifierArray = $db->arrayQuery( $query );
00297
00298 $identifierHash = array();
00299 foreach ( $identifierArray as $identifierRow )
00300 {
00301 $classIdentifier = $identifierRow['class_identifier'];
00302 $attributeIdentifier = $identifierRow['attribute_identifier'];
00303 $attributeID = $identifierRow['attribute_id'];
00304 $combinedIdentifier = $classIdentifier . '/' . $attributeIdentifier;
00305 $identifierHash[$combinedIdentifier] = (int)$attributeID;
00306 }
00307
00308
00309 $phpCache->addVariable( 'identifier_hash', $identifierHash );
00310 $phpCache->store();
00311 }
00312 $return = false;
00313 if ( isset( $identifierHash[$identifier] ) )
00314 $return = $identifierHash[$identifier];
00315
00316 return $return;
00317 }
00318
00319
00320
00321
00322
00323
00324 function classIDByIdentifier( $identifier )
00325 {
00326 $db =& eZDB::instance();
00327 $dbName = $db->DB;
00328
00329
00330
00331 include_once( 'lib/ezutils/classes/ezphpcreator.php' );
00332 $cacheDir = eZSys::cacheDirectory();
00333 $phpCache = new eZPHPCreator( "$cacheDir", "classidentifiers_$dbName.php", '', array( 'clustering' => 'classidentifiers' ) );
00334
00335 include_once( 'lib/ezutils/classes/ezexpiryhandler.php' );
00336 $handler =& eZExpiryHandler::instance();
00337 $expiryTime = 0;
00338 if ( $handler->hasTimestamp( 'class-identifier-cache' ) )
00339 {
00340 $expiryTime = $handler->timestamp( 'class-identifier-cache' );
00341 }
00342
00343 if ( $phpCache->canRestore( $expiryTime ) )
00344 {
00345 $var = $phpCache->restore( array( 'identifierHash' => 'identifier_hash' ) );
00346 $identifierHash =& $var['identifierHash'];
00347 }
00348 else
00349 {
00350
00351 $query = "SELECT id, identifier FROM ezcontentclass where version=0";
00352 $identifierArray = $db->arrayQuery( $query );
00353
00354 $identifierHash = array();
00355 foreach ( $identifierArray as $identifierRow )
00356 {
00357 $identifierHash[$identifierRow['identifier']] = $identifierRow['id'];
00358 }
00359
00360
00361 $phpCache->addVariable( 'identifier_hash', $identifierHash );
00362 $phpCache->store();
00363 }
00364 $return = false;
00365 if ( isset( $identifierHash[$identifier] ) )
00366 $return = $identifierHash[$identifier];
00367
00368 return $return;
00369 }
00370
00371
00372
00373
00374
00375
00376
00377 function &canRead( )
00378 {
00379 if ( !isset( $this->Permissions["can_read"] ) )
00380 {
00381 $this->Permissions["can_read"] = $this->checkAccess( 'read' );
00382 }
00383 $p = ( $this->Permissions["can_read"] == 1 );
00384 return $p;
00385 }
00386
00387
00388
00389
00390
00391
00392 function &canPdf( )
00393 {
00394 if ( !isset( $this->Permissions["can_pdf"] ) )
00395 {
00396 $this->Permissions["can_pdf"] = $this->checkAccess( 'pdf' );
00397 }
00398 $p = ( $this->Permissions["can_pdf"] == 1 );
00399 return $p;
00400 }
00401
00402
00403
00404
00405
00406
00407
00408
00409 function &canViewEmbed( )
00410 {
00411 if ( !isset( $this->Permissions["can_view_embed"] ) )
00412 {
00413 $this->Permissions["can_view_embed"] = $this->checkAccess( 'view_embed' );
00414 }
00415 $p = ( $this->Permissions["can_view_embed"] == 1 );
00416 return $p;
00417 }
00418
00419
00420
00421
00422
00423
00424
00425 function &canEdit( )
00426 {
00427 if ( !isset( $this->Permissions["can_edit"] ) )
00428 {
00429 $this->Permissions["can_edit"] = $this->checkAccess( 'edit' );
00430 if ( $this->Permissions["can_edit"] != 1 )
00431 {
00432 $user =& eZUser::currentUser();
00433 if ( $user->id() == $this->ContentObject->attribute( 'id' ) )
00434 {
00435 $access = $user->hasAccessTo( 'user', 'selfedit' );
00436 if ( $access['accessWord'] == 'yes' )
00437 {
00438 $this->Permissions["can_edit"] = 1;
00439 }
00440 }
00441 }
00442 }
00443 $p = ( $this->Permissions["can_edit"] == 1 );
00444 return $p;
00445 }
00446
00447
00448
00449
00450
00451
00452
00453 function &canHide( )
00454 {
00455 if ( !isset( $this->Permissions["can_hide"] ) )
00456 {
00457 $this->Permissions["can_hide"] = $this->checkAccess( 'hide' );
00458 }
00459 $p = ( $this->Permissions["can_hide"] == 1 );
00460 return $p;
00461 }
00462
00463
00464
00465
00466
00467
00468
00469 function &canCreate( )
00470 {
00471 if ( !isset( $this->Permissions["can_create"] ) )
00472 {
00473 $this->Permissions["can_create"] = $this->checkAccess( 'create' );
00474 }
00475 $p = ( $this->Permissions["can_create"] == 1 );
00476 return $p;
00477 }
00478
00479
00480
00481
00482
00483
00484
00485 function &canRemove( )
00486 {
00487 if ( !isset( $this->Permissions["can_remove"] ) )
00488 {
00489 $this->Permissions["can_remove"] = $this->checkAccess( 'remove' );
00490 }
00491 $p = ( $this->Permissions["can_remove"] == 1 );
00492 return $p;
00493 }
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503 function &canMove()
00504 {
00505 return $this->canMoveFrom();
00506 }
00507
00508
00509
00510
00511
00512
00513
00514
00515 function &canMoveFrom( )
00516 {
00517 if ( !isset( $this->Permissions['can_move_from'] ) )
00518 {
00519 $this->Permissions['can_move_from'] = $this->checkAccess( 'edit' ) && $this->checkAccess( 'remove' );
00520 }
00521 $p = ( $this->Permissions['can_move_from'] == 1 );
00522 return $p;
00523 }
00524
00525
00526
00527
00528
00529
00530
00531 function &canMoveTo( $classID = false )
00532 {
00533 if ( !isset( $this->Permissions['can_move_to'] ) )
00534 {
00535 $this->Permissions['can_move_to'] = $this->checkAccess( 'create', $classID );
00536 }
00537 $p = ( $this->Permissions['can_move_to'] == 1 );
00538 return $p;
00539 }
00540
00541
00542
00543
00544
00545
00546
00547 function &canSwap()
00548 {
00549 if ( !isset( $this->Permissions['can_swap'] ) )
00550 {
00551 $this->Permissions['can_swap'] = $this->checkAccess( 'edit' );
00552 }
00553 $p = ( $this->Permissions['can_swap'] == 1 );
00554 return $p;
00555 }
00556
00557
00558
00559
00560
00561 function &canAddLocation()
00562 {
00563 if ( !isset( $this->Permissions['can_add_location'] ) )
00564 {
00565 $this->Permissions['can_add_location'] = $this->checkAccess( 'can_add_location' );
00566 }
00567 $p = ( $this->Permissions['can_add_location'] == 1 );
00568 return $p;
00569 }
00570
00571
00572
00573
00574 function &canRemoveLocation()
00575 {
00576 if ( !isset( $this->Permissions['can_remove_location'] ) )
00577 {
00578 $this->Permissions['can_remove_location'] = $this->checkAccess( 'can_remove_location' );
00579 }
00580 $p = ( $this->Permissions['can_remove_location'] == 1 );
00581 return $p;
00582 }
00583
00584
00585
00586
00587
00588
00589 function sortKeyByClassAttributeID( $classAttributeID )
00590 {
00591 include_once( 'kernel/classes/ezcontentclassattribute.php' );
00592 return eZContentClassAttribute::sortKeyTypeByID( $classAttributeID );
00593 }
00594
00595
00596
00597
00598 function dataTypeByClassAttributeID( $classAttributeID )
00599 {
00600 include_once( 'kernel/classes/ezcontentclassattribute.php' );
00601 return eZContentClassAttribute::dataTypeByID( $classAttributeID );
00602 }
00603
00604
00605
00606
00607
00608 function fetchListCount()
00609 {
00610 $sql = "SELECT count( node_id ) as count FROM ezcontentobject_tree";
00611 $db =& eZDB::instance();
00612 $rows = $db->arrayQuery( $sql );
00613 return $rows[0]['count'];
00614 }
00615
00616
00617
00618
00619 function fetchList( $asObject = true, $offset = false, $limit = false )
00620 {
00621 $sql = "SELECT * FROM ezcontentobject_tree";
00622 $parameters = array();
00623 if ( $offset !== false )
00624 $parameters['offset'] = $offset;
00625 if ( $limit !== false )
00626 $parameters['limit'] = $limit;
00627 $db =& eZDB::instance();
00628 $rows = $db->arrayQuery( $sql, $parameters );
00629 $nodes = array();
00630 if ( $asObject )
00631 {
00632 foreach ( $rows as $row )
00633 {
00634 $nodes[] = new eZContentObjectTreeNode( $row );
00635 }
00636 return $nodes;
00637 }
00638 else
00639 return $rows;
00640 }
00641
00642
00643
00644
00645 function createSortingSQLStrings( $sortList, $treeTableName = 'ezcontentobject_tree' )
00646 {
00647 $sortingInfo = array( 'sortCount' => 0,
00648 'sortingFields' => " path_string ASC",
00649 'attributeJoinCount' => 0,
00650 'attributeFromSQL' => "",
00651 'attributeTargetSQL' => "",
00652 'attributeWhereSQL' => "" );
00653
00654 if ( $sortList and is_array( $sortList ) and count( $sortList ) > 0 )
00655 {
00656 if ( count( $sortList ) > 1 and !is_array( $sortList[0] ) )
00657 {
00658 $sortList = array( $sortList );
00659 }
00660
00661 $sortingFields = '';
00662 $sortCount = 0;
00663 $attributeJoinCount = 0;
00664 $attributeFromSQL = "";
00665 $attributeWhereSQL = "";
00666 $datatypeSortingTargetSQL = "";
00667
00668 foreach ( $sortList as $sortBy )
00669 {
00670 if ( is_array( $sortBy ) and count( $sortBy ) > 0 )
00671 {
00672 if ( $sortCount > 0 )
00673 {
00674 $sortingFields .= ', ';
00675 }
00676
00677 $sortField = $sortBy[0];
00678 switch ( $sortField )
00679 {
00680 case 'path':
00681 {
00682 $sortingFields .= 'path_string';
00683 } break;
00684 case 'path_string':
00685 {
00686 $sortingFields .= 'path_identification_string';
00687 } break;
00688 case 'published':
00689 {
00690 $sortingFields .= 'ezcontentobject.published';
00691 } break;
00692 case 'modified':
00693 {
00694 $sortingFields .= 'ezcontentobject.modified';
00695 } break;
00696 case 'modified_subnode':
00697 {
00698 $sortingFields .= 'modified_subnode';
00699 } break;
00700 case 'section':
00701 {
00702 $sortingFields .= 'ezcontentobject.section_id';
00703 } break;
00704 case 'depth':
00705 {
00706 $sortingFields .= 'depth';
00707 } break;
00708 case 'class_identifier':
00709 {
00710 $sortingFields .= 'ezcontentclass.identifier';
00711 } break;
00712 case 'class_name':
00713 {
00714 $classNameFilter = eZContentClassName::sqlFilter();
00715 $sortingFields .= $classNameFilter['nameField'];
00716 $attributeFromSQL .= ", $classNameFilter[from]";
00717 $attributeWhereSQL .= "$classNameFilter[where] AND ";
00718 } break;
00719 case 'priority':
00720 {
00721 $sortingFields .= $treeTableName . '.priority';
00722 } break;
00723 case 'name':
00724 {
00725 $sortingFields .= 'ezcontentobject_name.name';
00726 } break;
00727 case 'attribute':
00728 {
00729 include_once( 'kernel/classes/ezdatatype.php' );
00730
00731 $classAttributeID = $sortBy[2];
00732 if ( !is_numeric( $classAttributeID ) )
00733 $classAttributeID = eZContentObjectTreeNode::classAttributeIDByIdentifier( $classAttributeID );
00734
00735
00736 $contentAttributeTableAlias = "a$attributeJoinCount";
00737 $datatypeFromSQL = "ezcontentobject_attribute $contentAttributeTableAlias";
00738 $datatypeWhereSQL = "
00739 $contentAttributeTableAlias.contentobject_id = ezcontentobject.id AND
00740 $contentAttributeTableAlias.contentclassattribute_id = $classAttributeID AND
00741 $contentAttributeTableAlias.version = ezcontentobject_name.content_version AND";
00742 $datatypeWhereSQL .= eZContentLanguage::sqlFilter( $contentAttributeTableAlias, 'ezcontentobject' );
00743
00744 $dataType = eZDataType::create( eZContentObjectTreeNode::dataTypeByClassAttributeID( $classAttributeID ) );
00745 if( is_object( $dataType ) && $dataType->customSorting() )
00746 {
00747 $params = array();
00748 $params['contentobject_attr_id'] = "$contentAttributeTableAlias.id";
00749 $params['contentobject_attr_version'] = "$contentAttributeTableAlias.version";
00750 $params['table_alias_suffix'] = "$attributeJoinCount";
00751
00752 $sql = $dataType->customSortingSQL( $params );
00753
00754 $datatypeFromSQL .= ", {$sql['from']}";
00755 $datatypeWhereSQL .= " AND {$sql['where']}";
00756 $datatypeSortingFieldSQL = $sql['sorting_field'];
00757 $datatypeSortingTargetSQL .= ', ' . $sql['sorting_field'];
00758 }
00759 else
00760 {
00761
00762 $sortKeyType = eZContentObjectTreeNode::sortKeyByClassAttributeID( $classAttributeID );
00763 switch ( $sortKeyType )
00764 {
00765 case 'string':
00766 {
00767 $sortKey = 'sort_key_string';
00768 } break;
00769
00770 case 'int':
00771 default:
00772 {
00773 $sortKey = 'sort_key_int';
00774 } break;
00775 }
00776
00777 $datatypeSortingFieldSQL = "a$attributeJoinCount.$sortKey";
00778 $datatypeSortingTargetSQL .= ', ' . $datatypeSortingFieldSQL;
00779 }
00780
00781 $sortingFields .= "$datatypeSortingFieldSQL";
00782 $attributeFromSQL .= ", $datatypeFromSQL";
00783 $attributeWhereSQL .= "$datatypeWhereSQL AND ";
00784
00785 $attributeJoinCount++;
00786 }break;
00787
00788 default:
00789 {
00790 eZDebug::writeWarning( 'Unknown sort field: ' . $sortField, 'eZContentObjectTreeNode::getSortingInfo' );
00791 continue;
00792 };
00793 }
00794 $sortOrder = true;
00795 if ( isset( $sortBy[1] ) )
00796 $sortOrder = $sortBy[1];
00797 $sortingFields .= $sortOrder ? " ASC" : " DESC";
00798 ++$sortCount;
00799 }
00800 }
00801
00802 $sortingInfo['sortCount'] = $sortCount;
00803 $sortingInfo['sortingFields'] = $sortingFields;
00804 $sortingInfo['attributeTargetSQL'] = $datatypeSortingTargetSQL;
00805 $sortingInfo['attributeJoinCount'] = $attributeJoinCount;
00806 $sortingInfo['attributeFromSQL'] = $attributeFromSQL;
00807 $sortingInfo['attributeWhereSQL'] = $attributeWhereSQL;
00808 }
00809
00810 return $sortingInfo;
00811 }
00812
00813
00814
00815
00816 function createClassFilteringSQLString( $classFilterType, &$classFilterArray )
00817 {
00818
00819 $classCondition = '';
00820
00821 if ( isset( $classFilterType ) and
00822 ( $classFilterType == 'include' or $classFilterType == 'exclude' ) and
00823 count( $classFilterArray ) > 0 )
00824 {
00825 $classCondition = ' ';
00826 $i = 0;
00827 $classCount = count( $classFilterArray );
00828 $classIDArray = array();
00829 foreach ( $classFilterArray as $classID )
00830 {
00831 $originalClassID = $classID;
00832
00833 if ( is_string( $classID ) && !is_numeric( $classID ) )
00834 {
00835 $classID = eZContentObjectTreeNode::classIDByIdentifier( $classID );
00836 }
00837 if ( is_numeric( $classID ) )
00838 {
00839 $classIDArray[] = $classID;
00840 }
00841 else
00842 {
00843 eZDebugSetting::writeWarning( 'kernel-content-class', "Invalid class identifier in subTree() classfilterarray, classID : " . $originalClassID );
00844 }
00845 }
00846
00847 if ( count( $classIDArray ) > 0 )
00848 {
00849 $classCondition .= " ezcontentobject.contentclass_id ";
00850 if ( $classFilterType == 'include' )
00851 $classCondition .= " IN ";
00852 else
00853 $classCondition .= " NOT IN ";
00854
00855 $classIDString = implode( ', ', $classIDArray );
00856 $classCondition .= ' ( ' . $classIDString . ' ) AND';
00857 }
00858 else
00859 {
00860 if ( count( $classIDArray ) == 0 and count( $classFilterArray ) > 0 and $classFilterType == 'include' )
00861 {
00862 $classCondition = false;
00863 }
00864 }
00865 }
00866
00867 return $classCondition;
00868 }
00869
00870
00871
00872
00873 function createExtendedAttributeFilterSQLStrings( &$extendedAttributeFilter )
00874 {
00875 $filter = array( 'tables' => '',
00876 'joins' => '' );
00877
00878 if ( $extendedAttributeFilter and count( $extendedAttributeFilter ) > 1 )
00879 {
00880 $extendedAttributeFilterID = $extendedAttributeFilter['id'];
00881 $extendedAttributeFilterParams = $extendedAttributeFilter['params'];
00882 $filterINI =& eZINI::instance( 'extendedattributefilter.ini' );
00883
00884 $filterClassName = $filterINI->variable( $extendedAttributeFilterID, 'ClassName' );
00885 $filterMethodName = $filterINI->variable( $extendedAttributeFilterID, 'MethodName' );
00886 $filterFile = $filterINI->variable( $extendedAttributeFilterID, 'FileName' );
00887
00888 if ( $filterINI->hasVariable( $extendedAttributeFilterID, 'ExtensionName' ) )
00889 {
00890 include_once( 'lib/ezutils/classes/ezextension.php' );
00891 $extensionName = $filterINI->variable( $extendedAttributeFilterID, 'ExtensionName' );
00892 ext_activate( $extensionName, $filterFile );
00893 }
00894 else
00895 {
00896 include_once( $filterFile );
00897 }
00898
00899 $classObject = new $filterClassName();
00900 $parameterArray = array( $extendedAttributeFilterParams );
00901
00902 $sqlResult = call_user_func_array( array( $classObject, $filterMethodName ), $parameterArray );
00903
00904 $filter['tables'] = $sqlResult['tables'];
00905 $filter['joins'] = $sqlResult['joins'];
00906
00907 }
00908
00909 return $filter;
00910 }
00911
00912
00913
00914
00915 function createMainNodeConditionSQLString( $mainNodeOnly )
00916 {
00917
00918 $mainNodeCondition = '';
00919 if ( isset( $mainNodeOnly ) && $mainNodeOnly === true )
00920 {
00921 $mainNodeCondition = 'ezcontentobject_tree.node_id = ezcontentobject_tree.main_node_id AND';
00922 }
00923
00924 return $mainNodeCondition;
00925 }
00926
00927
00928
00929
00930 function createObjectNameFilterConditionSQLString( $filter )
00931 {
00932 if ( !$filter )
00933 return '';
00934
00935 $db =& eZDB::instance();
00936 if ( $filter == 'others' )
00937 {
00938 include_once('kernel/common/ezalphabetoperator.php');
00939 $alphabet = eZAlphabetOperator::fetchAlphabet();
00940 $sql = '';
00941 foreach ( $alphabet as $letter )
00942 {
00943 $sql .= " AND ezcontentobject.name NOT LIKE '". $db->escapeString( $letter ) . "%'\n";
00944 }
00945 return $sql;
00946 }
00947 $objectNameFilterSQL = " AND ezcontentobject.name LIKE '" . $db->escapeString( $filter ) ."%'";
00948 return $objectNameFilterSQL;
00949 }
00950
00951
00952
00953
00954
00955 function createAttributeFilterSQLStrings( &$attributeFilter, &$sortingInfo )
00956 {
00957
00958
00959 $filterSQL = array( 'from' => '',
00960 'where' => '' );
00961
00962 $invalidFilterSQL = false;
00963 $totalAttributesFiltersCount = 0;
00964 $invalidAttributesFiltersCount = 0;
00965
00966 if ( isset( $attributeFilter ) && $attributeFilter !== false )
00967 {
00968 $filterArray = $attributeFilter;
00969
00970
00971
00972 $filterJoinType = 'AND';
00973 if ( is_string( $filterArray[0] ) )
00974 {
00975 if ( strtolower( $filterArray[0] ) == 'or' )
00976 {
00977 $filterJoinType = 'OR';
00978 }
00979 else if ( strtolower( $filterArray[0] ) == 'and' )
00980 {
00981 $filterJoinType = 'AND';
00982 }
00983 unset( $filterArray[0] );
00984 }
00985
00986 $attibuteFilterJoinSQL = "";
00987 $filterCount = $sortingInfo['sortCount'];
00988 $justFilterCount = 0;
00989
00990 $db =& eZDB::instance();
00991 if ( is_array( $filterArray ) )
00992 {
00993
00994 $totalAttributesFiltersCount = count( $filterArray );
00995
00996 foreach ( $filterArray as $filter )
00997 {
00998 $isFilterValid = true;
00999
01000 $filterAttributeID = $filter[0];
01001 $filterType = $filter[1];
01002 $filterValue = is_array( $filter[2] ) ? '' : $db->escapeString( $filter[2] );
01003
01004 $useAttributeFilter = false;
01005 switch ( $filterAttributeID )
01006 {
01007 case 'path':
01008 {
01009 $filterField = 'path_string';
01010 } break;
01011 case 'published':
01012 {
01013 $filterField = 'ezcontentobject.published';
01014 } break;
01015 case 'modified':
01016 {
01017 $filterField = 'ezcontentobject.modified';
01018 } break;
01019 case 'modified_subnode':
01020 {
01021 $filterField = 'modified_subnode';
01022 } break;
01023 case 'section':
01024 {
01025 $filterField = 'ezcontentobject.section_id';
01026 } break;
01027 case 'depth':
01028 {
01029 $filterField = 'depth';
01030 } break;
01031 case 'class_identifier':
01032 {
01033 $filterField = 'ezcontentclass.identifier';
01034 } break;
01035 case 'class_name':
01036 {
01037 $classNameFilter = eZContentClassName::sqlFilter();
01038 $filterField = $classNameFilter['nameField'];
01039 $filterSQL['from'] .= ", $classNameFilter[from]";
01040 $filterSQL['where'] .= "$classNameFilter[where] AND ";
01041 } break;
01042 case 'priority':
01043 {
01044 $filterField = 'ezcontentobject_tree.priority';
01045 } break;
01046 case 'name':
01047 {
01048 $filterField = 'ezcontentobject_name.name';
01049 } break;
01050 case 'owner':
01051 {
01052 $filterField = 'ezcontentobject.owner_id';
01053 } break;
01054 default:
01055 {
01056 $useAttributeFilter = true;
01057 } break;
01058 }
01059
01060 if ( $useAttributeFilter )
01061 {
01062 if ( !is_numeric( $filterAttributeID ) )
01063 $filterAttributeID = eZContentObjectTreeNode::classAttributeIDByIdentifier( $filterAttributeID );
01064
01065 if ( $filterAttributeID === false )
01066 {
01067 $isFilterValid = false;
01068 if( $filterJoinType === 'AND' )
01069 {
01070
01071 $invalidAttributesFiltersCount = $totalAttributesFiltersCount;
01072 break;
01073 }
01074
01075 ++$invalidAttributesFiltersCount;
01076 }
01077 else
01078 {
01079
01080 $filterDataType = eZContentObjectTreeNode::sortKeyByClassAttributeID( $filterAttributeID );
01081 if ( $filterDataType === false )
01082 {
01083 $isFilterValid = false;
01084 if( $filterJoinType === 'AND' )
01085 {
01086
01087 $invalidAttributesFiltersCount = $totalAttributesFiltersCount;
01088 break;
01089 }
01090
01091
01092 ++$invalidAttributesFiltersCount;
01093 }
01094 else
01095 {
01096 $sortKey = false;
01097 if ( $filterDataType == 'string' )
01098 {
01099 $sortKey = 'sort_key_string';
01100 }
01101 else
01102 {
01103 $sortKey = 'sort_key_int';
01104 }
01105
01106 $filterField = "a$filterCount.$sortKey";
01107
01108
01109
01110 if ( $filterCount >= $sortingInfo['attributeJoinCount'] )
01111 {
01112 $filterSQL['from'] .= ", ezcontentobject_attribute a$filterCount ";
01113 $filterSQL['where'] .= "
01114 a$filterCount.contentobject_id = ezcontentobject.id AND
01115 a$filterCount.contentclassattribute_id = $filterAttributeID AND
01116 a$filterCount.version = ezcontentobject_name.content_version AND ";
01117 $filterSQL['where'] .= eZContentLanguage::sqlFilter( "a$filterCount", 'ezcontentobject' ).' AND ';
01118 }
01119 else
01120 {
01121 $filterSQL['where'] .= "
01122 a$filterCount.contentobject_id = ezcontentobject.id AND
01123 a$filterCount.contentclassattribute_id = $filterAttributeID AND
01124 a$filterCount.version = ezcontentobject_name.content_version AND ";
01125 $filterSQL['where'] .= eZContentLanguage::sqlFilter( "a$filterCount", 'ezcontentobject' ). ' AND ';
01126 }
01127 }
01128 }
01129 }
01130
01131 if( $isFilterValid )
01132 {
01133 $hasFilterOperator = true;
01134
01135 $noQuotes = false;
01136
01137 $unEscape = false;
01138
01139 switch ( $filterType )
01140 {
01141 case '=' :
01142 {
01143 $filterOperator = '=';
01144 }break;
01145
01146 case '!=' :
01147 {
01148 $filterOperator = '<>';
01149 }break;
01150
01151 case '>' :
01152 {
01153 $filterOperator = '>';
01154 }break;
01155
01156 case '<' :
01157 {
01158 $filterOperator = '<';
01159 }break;
01160
01161 case '<=' :
01162 {
01163 $filterOperator = '<=';
01164 }break;
01165
01166 case '>=' :
01167 {
01168 $filterOperator = '>=';
01169 }break;
01170
01171 case 'like':
01172 case 'not_like':
01173 {
01174 $filterOperator = ( $filterType == 'like' ? 'LIKE' : 'NOT LIKE' );
01175
01176 $filter[2] = $db->escapeString( $filter[2] );
01177 $unEscape = true;
01178
01179
01180
01181
01182
01183
01184
01185 $filter[2] = preg_replace( array( '#%#m',
01186 '#(?<!\\\\)\\*#m',
01187 '#(?<!\\\\)\\\\\\*#m',
01188 '#\\\\\\\\#m' ),
01189 array( '\\%',
01190 '%',
01191 '*',
01192 '\\\\' ),
01193 $filter[2] );
01194 } break;
01195
01196 case 'in':
01197 case 'not_in' :
01198 {
01199 $filterOperator = ( $filterType == 'in' ? 'IN' : 'NOT IN' );
01200
01201 $noQuotes = true;
01202 if ( is_array( $filter[2] ) )
01203 {
01204 reset( $filter[2] );
01205 while ( list( $key, $value ) = each( $filter[2] ) )
01206 {
01207
01208 $filter[2][$key] = is_numeric( $value ) ? $value : "'" . $db->escapeString( $value ) . "'";
01209 }
01210 $filterValue = '(' . implode( ",", $filter[2] ) . ')';
01211 }
01212 else
01213 {
01214 $hasFilterOperator = false;
01215 }
01216 } break;
01217
01218 case 'between':
01219 case 'not_between' :
01220 {
01221 $filterOperator = ( $filterType == 'between' ? 'BETWEEN' : 'NOT BETWEEN' );
01222
01223 $noQuotes = true;
01224 if ( is_array( $filter[2] ) )
01225 {
01226
01227 if ( !is_numeric( $filter[2][0] ) )
01228 $filter[2][0] = "'" . $db->escapeString( $filter[2][0] ) . "'";
01229 if ( !is_numeric( $filter[2][1] ) )
01230 $filter[2][1] = "'" . $db->escapeString( $filter[2][1] ) . "'";
01231
01232 $filterValue = $filter[2][0] . ' AND ' . $filter[2][1];
01233 }
01234 } break;
01235
01236 default :
01237 {
01238 $hasFilterOperator = false;
01239 eZDebug::writeError( "Unknown attribute filter type: $filterType", "eZContentObjectTreeNode::subTree()" );
01240 }break;
01241
01242 }
01243 if ( $hasFilterOperator )
01244 {
01245 if ( ( $filterCount - $sortingInfo['sortCount'] ) > 0 )
01246 $attibuteFilterJoinSQL .= " $filterJoinType ";
01247
01248
01249
01250 $filterValue = $unEscape ? $filter[2] : $filterValue;
01251
01252 $attibuteFilterJoinSQL .= "$filterField $filterOperator ";
01253 $attibuteFilterJoinSQL .= $noQuotes ? "$filterValue " : "'" . $filterValue . "' ";
01254
01255 $filterCount++;
01256 $justFilterCount++;
01257 }
01258 }
01259 }
01260
01261 if( $totalAttributesFiltersCount == $invalidAttributesFiltersCount )
01262 {
01263 eZDebug::writeNotice( "Attribute filter returned false" );
01264 $filterSQL = $invalidFilterSQL;
01265 }
01266 else
01267 {
01268 if ( $justFilterCount > 0 )
01269 $filterSQL['where'] .= "\n ( " . $attibuteFilterJoinSQL . " ) AND ";
01270 }
01271 }
01272 }
01273
01274 return $filterSQL;
01275 }
01276
01277
01278
01279
01280 function createNotEqParentSQLString( $nodeID, $depth = false, $depthOperator = 'le' )
01281 {
01282 $notEqParentString = '';
01283 if( !$depth || $depthOperator == 'le' || $depthOperator == 'lt' )
01284 {
01285 $notEqParentString = "ezcontentobject_tree.node_id != $nodeID AND";
01286 }
01287
01288 return $notEqParentString;
01289 }
01290
01291
01292
01293
01294 function createPathConditionSQLString( $nodePath, $nodeDepth, $depth = false, $depthOperator = 'le' )
01295 {
01296 $pathCondition = '';
01297 $depthCondition = '';
01298
01299 if ( $depth )
01300 {
01301 $sqlDepthOperator = '<=';
01302 if ( $depthOperator )
01303 {
01304 if ( $depthOperator == 'lt' )
01305 {
01306 $sqlDepthOperator = '<';
01307 }
01308 else if ( $depthOperator == 'gt' )
01309 {
01310 $sqlDepthOperator = '>';
01311 }
01312 else if ( $depthOperator == 'le' )
01313 {
01314 $sqlDepthOperator = '<=';
01315 }
01316 else if ( $depthOperator == 'ge' )
01317 {
01318 $sqlDepthOperator = '>=';
01319 }
01320 else if ( $depthOperator == 'eq' )
01321 {
01322 $sqlDepthOperator = '=';
01323 }
01324 }
01325
01326 $nodeDepth += $depth;
01327 $depthCondition = ' ezcontentobject_tree.depth '. $sqlDepthOperator . ' ' . $nodeDepth . ' and ';
01328 }
01329
01330 $pathCondition = " ezcontentobject_tree.path_string like '$nodePath%' and $depthCondition ";
01331 return $pathCondition;
01332 }
01333
01334
01335
01336
01337 function createPathConditionAndNotEqParentSQLStrings( &$outPathConditionStr, &$outNotEqParentStr, &$treeNode, $nodeID, $depth = false, $depthOperator = 'le' )
01338 {
01339 if ( !$depthOperator )
01340 {
01341 $depthOperator = 'le';
01342 }
01343
01344
01345
01346
01347 $onlyChildren = ( $depth === 1 && ( $depthOperator === 'le' || $depthOperator === 'eq' ) ) ||
01348 ( $depth === 2 && $depthOperator === 'lt' );
01349
01350 if ( is_array( $nodeID ) && count( $nodeID ) == 1 )
01351 {
01352 $nodeID = $nodeID[0];
01353 }
01354
01355 if ( is_array( $nodeID ) )
01356 {
01357 $outNotEqParentStr = '';
01358
01359
01360 if ( $onlyChildren )
01361 {
01362 $db = eZDB::instance();
01363 $impStr = $db->implodeWithTypeCast( ',', $nodeID, 'int' );
01364 $outPathConditionStr = 'ezcontentobject_tree.parent_node_id IN ( ' . $impStr . ' ) and';
01365 }
01366 else
01367 {
01368 $nodeIDList = $nodeID;
01369 $sqlPartForOneNodeList = array();
01370
01371 foreach ( $nodeIDList as $nodeID )
01372 {
01373 $node = eZContentObjectTreeNode::fetch( $nodeID, false, false );
01374 if ( !is_array( $node ) )
01375 return false;
01376
01377 $nodePath = $node['path_string'];
01378 $nodeDepth = $node['depth'];
01379 $depthCond = '';
01380 if ( $depth )
01381 {
01382 $sqlDepthOperator = '<=';
01383 if ( $depthOperator )
01384 {
01385 if ( $depthOperator == 'lt' )
01386 {
01387 $sqlDepthOperator = '<';
01388 }
01389 else if ( $depthOperator == 'gt' )
01390 {
01391 $sqlDepthOperator = '>';
01392 }
01393 else if ( $depthOperator == 'le' )
01394 {
01395 $sqlDepthOperator = '<=';
01396 }
01397 else if ( $depthOperator == 'ge' )
01398 {
01399 $sqlDepthOperator = '>=';
01400 }
01401 else if ( $depthOperator == 'eq' )
01402 {
01403 $sqlDepthOperator = '=';
01404 }
01405 }
01406 $nodeDepth += $depth;
01407 $depthCond = ' and ezcontentobject_tree.depth '. $sqlDepthOperator . ' ' . $nodeDepth . ' ';
01408 }
01409
01410 $requireNotEqParentStr = !$depth || $depthOperator == 'le' || $depthOperator == 'lt';
01411 $notEqParentStr = $requireNotEqParentStr ? " and ezcontentobject_tree.node_id != $nodeID " : '';
01412 $sqlPartForOneNodeList[] = " ( ezcontentobject_tree.path_string like '$nodePath%' $depthCond $notEqParentStr ) ";
01413 }
01414 $outPathConditionStr = implode( ' or ', $sqlPartForOneNodeList );
01415 $outPathConditionStr = ' (' . $outPathConditionStr . ') and';
01416 }
01417 }
01418 else
01419 {
01420 if ( $nodeID == 0 )
01421 {
01422 if ( !is_object( $treeNode ) or get_class( $treeNode ) != 'ezcontentobjecttreenode' )
01423 {
01424 return false;
01425 }
01426
01427 $node =& $treeNode;
01428 $nodeID = $node->attribute( 'node_id' );
01429 $nodePath = $node->attribute('path_string');
01430 $nodeDepth = $node->attribute('depth');
01431 }
01432
01433
01434 if ( $onlyChildren )
01435 {
01436 $outNotEqParentStr = '';
01437 $outPathConditionStr = 'ezcontentobject_tree.parent_node_id = ' . (int) $nodeID . ' and';
01438 }
01439 else
01440 {
01441 if ( !isset( $node ) )
01442 {
01443 $node = eZContentObjectTreeNode::fetch( $nodeID, false, false );
01444 if ( !is_array( $node ) )
01445 return false;
01446
01447 $nodePath = $node['path_string'];
01448 $nodeDepth = $node['depth'];
01449 }
01450
01451 $outNotEqParentStr = eZContentObjectTreeNode::createNotEqParentSQLString( $nodeID, $depth, $depthOperator );
01452 $outPathConditionStr = eZContentObjectTreeNode::createPathConditionSQLString( $nodePath, $nodeDepth, $depth, $depthOperator );
01453 }
01454 }
01455
01456 return true;
01457 }
01458
01459
01460
01461
01462 function createGroupBySQLStrings( &$outGroupBySelectText, &$outGroupByText, $groupBy )
01463 {
01464 if ( $groupBy )
01465 {
01466 if ( isset( $groupBy['field'] ) and isset( $groupBy['type'] ) )
01467 {
01468 $groupByField = $groupBy['field'];
01469 $groupByFieldType = $groupBy['type'];
01470
01471 switch ( $groupByField )
01472 {
01473 case 'published':
01474 {
01475 $groupBySelect = eZContentObjectTreeNode::subTreeGroupByDateField( "ezcontentobject." . $groupByField, $groupByFieldType );
01476 $groupBySelect['field'] = "ezcontentobject." . $groupByField;
01477 } break;
01478 case 'modified':
01479 {
01480 $groupBySelect = eZContentObjectTreeNode::subTreeGroupByDateField( "ezcontentobject." . $groupByField, $groupByFieldType );
01481 $groupBySelect['field'] = "ezcontentobject." . $groupByField;
01482 } break;
01483 }
01484
01485 $outGroupBySelectText = ", " . $groupBySelect['select'];
01486 $outGroupByText = "GROUP BY " . $groupBySelect['group_field'];
01487 }
01488 }
01489 }
01490
01491
01492
01493
01494 function createVersionNameTablesSQLString( $useVersionName )
01495 {
01496 $versionNameTables = '';
01497
01498 if ( $useVersionName )
01499 {
01500 $versionNameTables = ', ezcontentobject_name ';
01501 }
01502
01503 return $versionNameTables;
01504 }
01505
01506
01507
01508
01509 function createVersionNameTargetsSQLString( $useVersionName )
01510 {
01511 $versionNameTargets = '';
01512
01513 if ( $useVersionName )
01514 {
01515 $versionNameTargets = ', ezcontentobject_name.name as name, ezcontentobject_name.real_translation ';
01516 }
01517
01518
01519 return $versionNameTargets;
01520 }
01521
01522
01523
01524
01525 function createVersionNameJoinsSQLString( $useVersionName, $includeAnd = true, $onlyTranslated = false, $lang = false, $treeTableName = 'ezcontentobject_tree' )
01526 {
01527 $versionNameJoins = '';
01528 if ( $useVersionName )
01529 {
01530 if ( $includeAnd )
01531 {
01532 $versionNameJoins .= ' AND ';
01533 }
01534 $versionNameJoins .= " $treeTableName.contentobject_id = ezcontentobject_name.contentobject_id and
01535 $treeTableName.contentobject_version = ezcontentobject_name.content_version and ";
01536 $versionNameJoins .= eZContentLanguage::sqlFilter( 'ezcontentobject_name', 'ezcontentobject' );
01537 }
01538 return $versionNameJoins;
01539 }
01540
01541
01542
01543
01544
01545 function createPermissionCheckingSQLString( &$limitationList )
01546 {
01547 $sqlPermissionChecking = eZContentObjectTreeNode::createPermissionCheckingSQL( $limitationList );
01548 return $sqlPermissionChecking['where'];
01549 }
01550
01551
01552
01553
01554 function createPermissionCheckingSQL( &$limitationList, $treeTableName = 'ezcontentobject_tree', $tableAliasName = 'ezcontentobject_tree' )
01555 {
01556 $db =& eZDB::instance();
01557
01558 $sqlPermissionCheckingFrom = '';
01559 $sqlPermissionCheckingWhere = '';
01560 $sqlPermissionTempTables = array();
01561 $groupPermTempTable = false;
01562
01563 if ( is_array( $limitationList ) && count( $limitationList ) > 0 )
01564 {
01565 $sqlParts = array();
01566 foreach( $limitationList as $limitationArray )
01567 {
01568 $sqlPartPart = array();
01569 $sqlPartPartPart = array();
01570 $sqlPlacementPart = array();
01571
01572 $count = 1;
01573 foreach ( array_keys( $limitationArray ) as $ident )
01574 {
01575 switch( $ident )
01576 {
01577 case 'Class':
01578 {
01579 $sqlPartPart[] = 'ezcontentobject.contentclass_id in (' . implode( ', ', $limitationArray[$ident] ) . ')';
01580 } break;
01581
01582 case 'Section':
01583 case 'User_Section':
01584 {
01585 $sqlPartPart[] = 'ezcontentobject.section_id in (' . implode( ', ', $limitationArray[$ident] ) . ')';
01586 } break;
01587
01588 case 'Owner':
01589 {
01590 $user =& eZUser::currentUser();
01591 $userID = $user->attribute( 'contentobject_id' );
01592 $sqlPartPart[] = "ezcontentobject.owner_id = '" . $db->escapeString( $userID ) . "'";
01593 } break;
01594
01595 case 'Group':
01596 {
01597 if ( !$groupPermTempTable )
01598 {
01599 $user =& eZUser::currentUser();
01600 $userContentObject =& $user->attribute( 'contentobject' );
01601 $parentList =& $userContentObject->attribute( 'parent_nodes' );
01602
01603 $groupPermTempTable = $db->generateUniqueTempTableName( 'ezgroup_perm_tmp_%' );
01604 $sqlPermissionTempTables[] = $groupPermTempTable;
01605
01606 $db->createTempTable( "CREATE TEMPORARY TABLE $groupPermTempTable ( user_id int )" );
01607 $db->query( "INSERT INTO $groupPermTempTable
01608 SELECT DISTINCT contentobject_id AS user_id
01609 FROM ezcontentobject_tree
01610 WHERE parent_node_id IN (" . implode( ', ', $parentList ) . ')',
01611 EZ_DB_SERVER_SLAVE );
01612
01613 $sqlPermissionCheckingFrom = ', ' . $groupPermTempTable;
01614 }
01615 $sqlPartPart[] = "ezcontentobject.owner_id = $groupPermTempTable.user_id";
01616 } break;
01617
01618 case 'Node':
01619 {
01620 $sqlPlacementPart[] = $tableAliasName . '.node_id in (' . implode( ', ', $limitationArray[$ident] ) . ')';
01621 } break;
01622
01623 case 'Subtree':
01624 {
01625 $pathArray =& $limitationArray[$ident];
01626
01627 $sqlSubtreePart = array();
01628 foreach ( $pathArray as $limitationPathString )
01629 {
01630 $sqlSubtreePart[] = "$tableAliasName.path_string like '$limitationPathString%'";
01631 }
01632 $sqlPlacementPart[] = implode( ' OR ', $sqlSubtreePart );
01633 } break;
01634
01635 case 'User_Subtree':
01636 {
01637 $pathArray =& $limitationArray[$ident];
01638 $sqlPartUserSubtree = array();
01639 foreach ( $pathArray as $limitationPathString )
01640 {
01641 $sqlPartUserSubtree[] = "$tableAliasName.path_string like '$limitationPathString%'";
01642 }
01643 $sqlPartPart[] = implode( ' OR ', $sqlPartUserSubtree );
01644 }
01645 }
01646
01647 $count++;
01648 }
01649 if ( $sqlPlacementPart )
01650 {
01651 $sqlPartPart[] = '( ( ' . implode( ' ) OR ( ', $sqlPlacementPart ) . ' ) )';
01652 }
01653 if ( $sqlPartPartPart )
01654 {
01655 $sqlPartPart[] = '( ' . implode( ' ) OR ( ', $sqlPartPartPart ) . ' )';
01656 }
01657 $sqlParts[] = implode( ' AND ', $sqlPartPart );
01658 }
01659 $sqlPermissionCheckingWhere = ' AND ((' . implode( ') OR (', $sqlParts ) . ')) ';
01660 }
01661
01662 $sqlPermissionChecking = array( 'from' => $sqlPermissionCheckingFrom,
01663 'where' => $sqlPermissionCheckingWhere,
01664 'temp_tables' => $sqlPermissionTempTables );
01665
01666 return $sqlPermissionChecking;
01667 }
01668
01669
01670
01671
01672
01673
01674
01675 function createNodesConditionSQLStringFromPath( $nodePath, $includingLastNodeInThePath, $limit = false )
01676 {
01677 $pathString = false;
01678 $pathArray = explode( '/', trim( $nodePath, '/' ) );
01679
01680 $pathArrayCount = count( $pathArray );
01681
01682 if ( $limit && $includingLastNodeInThePath == false )
01683 {
01684 $limit++;
01685 }
01686
01687 $sliceOffset = $limit && $pathArrayCount > $limit ? $pathArrayCount - $limit : 0;
01688 $sliceLength = $includingLastNodeInThePath ? $pathArrayCount - $sliceOffset : $pathArrayCount - ( $sliceOffset + 1 );
01689
01690
01691 if ( ( $sliceOffset + $sliceLength ) < $pathArrayCount )
01692 {
01693 $pathArray = array_slice( $pathArray, $sliceOffset, $sliceLength );
01694 }
01695
01696 if ( $sliceLength == 1 )
01697 {
01698 $pathString = ' node_id = ' . implode( '', $pathArray ) . ' and ';
01699 }
01700 else if ( $sliceLength > 0 )
01701 {
01702 $db = eZDB::instance();
01703 $pathString = ' node_id IN ( ' . implode( ', ', $pathArray ) . ') and ';
01704 }
01705
01706 return $pathString;
01707 }
01708
01709
01710
01711
01712
01713
01714 function createShowInvisibleSQLString( $useSettings, $fetchHidden = true )
01715 {
01716 $showInvisibleNodesCond = '';
01717 $showInvisible = $fetchHidden;
01718
01719 if ( $useSettings )
01720 $showInvisible = eZContentObjectTreeNode::showInvisibleNodes();
01721
01722 if ( !$showInvisible )
01723 $showInvisibleNodesCond = 'AND ezcontentobject_tree.is_invisible = 0';
01724
01725 return $showInvisibleNodesCond;
01726 }
01727
01728
01729
01730
01731
01732 function showInvisibleNodes()
01733 {
01734 static $cachedResult;
01735
01736 if ( !isset( $cachedResult ) )
01737 {
01738 $ini =& eZINI::instance( 'site.ini' );
01739 $cachedResult = $ini->hasVariable( 'SiteAccessSettings', 'ShowHiddenNodes' ) ?
01740 $ini->variable( 'SiteAccessSettings', 'ShowHiddenNodes' ) == 'true' :
01741 true;
01742 }
01743
01744 return $cachedResult;
01745 }
01746
01747
01748
01749
01750 function getLimitationList( &$limitation )
01751 {
01752 include_once( "kernel/classes/datatypes/ezuser/ezuser.php" );
01753 $currentUser =& eZUser::currentUser();
01754 $currentUserID = $currentUser->attribute( 'contentobject_id' );
01755 $limitationList = array();
01756
01757 if ( $limitation !== false )
01758 {
01759 $limitationList = $limitation;
01760 }
01761 else if ( isset( $GLOBALS['ezpolicylimitation_list'][$currentUserID]['content']['read'] ) )
01762 {
01763 $limitationList =& $GLOBALS['ezpolicylimitation_list'][$currentUserID]['content']['read'];
01764 eZDebugSetting::writeDebug( 'kernel-content-treenode', $limitationList, "limitation list" );
01765 }
01766 else
01767 {
01768 $accessResult = $currentUser->hasAccessTo( 'content', 'read' );
01769
01770 if ( $accessResult['accessWord'] == 'no' )
01771 {
01772 $limitationList = false;
01773 $GLOBALS['ezpolicylimitation_list'][$currentUserID]['content']['read'] = false;
01774 }
01775 else if ( $accessResult['accessWord'] == 'limited' )
01776 {
01777 $limitationList =& $accessResult['policies'];
01778 $GLOBALS['ezpolicylimitation_list'][$currentUserID]['content']['read'] =& $accessResult['policies'];
01779 }
01780 }
01781
01782 return $limitationList;
01783 }
01784
01785
01786
01787 function &subTree( $params = false ,$nodeID = 0 )
01788 {
01789 if ( !is_numeric( $nodeID ) and !is_array( $nodeID ) )
01790 {
01791 $retValue = null;
01792 return $retValue;
01793 }
01794
01795 if ( $params === false )
01796 {
01797 $params = array( 'Depth' => false,
01798 'Offset' => false,
01799
01800 'Language' => false,
01801 'Limit' => false,
01802 'SortBy' => false,
01803 'AttributeFilter' => false,
01804 'ExtendedAttributeFilter' => false,
01805 'ClassFilterType' => false,
01806 'ClassFilterArray' => false,
01807 'GroupBy' => false );
01808 }
01809
01810 $offset = ( isset( $params['Offset'] ) && is_numeric( $params['Offset'] ) ) ? $params['Offset'] : false;
01811
01812 $language = ( isset( $params['Language'] ) ) ? $params['Language'] : false;
01813 $limit = ( isset( $params['Limit'] ) && is_numeric( $params['Limit'] ) ) ? $params['Limit'] : false;
01814 $depth = ( isset( $params['Depth'] ) && is_numeric( $params['Depth'] ) ) ? $params['Depth'] : false;
01815 $depthOperator = ( isset( $params['DepthOperator'] ) ) ? $params['DepthOperator'] : false;
01816 $asObject = ( isset( $params['AsObject'] ) ) ? $params['AsObject'] : true;
01817 $loadDataMap = ( isset( $params['LoadDataMap'] ) ) ? $params['LoadDataMap'] : false;
01818 $groupBy = ( isset( $params['GroupBy'] ) ) ? $params['GroupBy'] : false;
01819 $mainNodeOnly = ( isset( $params['MainNodeOnly'] ) ) ? $params['MainNodeOnly'] : false;
01820 $ignoreVisibility = ( isset( $params['IgnoreVisibility'] ) ) ? $params['IgnoreVisibility'] : false;
01821 $objectNameFilter = ( isset( $params['ObjectNameFilter'] ) ) ? $params['ObjectNameFilter'] : false;
01822
01823 if ( $offset < 0 )
01824 {
01825 $offset = ABS( $offset );
01826 }
01827
01828 if ( !isset( $params['SortBy'] ) )
01829 $params['SortBy'] = false;
01830 if ( !isset( $params['ClassFilterType'] ) )
01831 $params['ClassFilterType'] = false;
01832
01833 if ( $language )
01834 {
01835 if ( !is_array( $language ) )
01836 {
01837 $language = array( $language );
01838 }
01839 eZContentLanguage::setPrioritizedLanguages( $language );
01840 }
01841
01842 $sortingInfo = eZContentObjectTreeNode::createSortingSQLStrings( $params['SortBy'] );
01843 $classCondition = eZContentObjectTreeNode::createClassFilteringSQLString( $params['ClassFilterType'], $params['ClassFilterArray'] );
01844 if ( $classCondition === false )
01845 {
01846 eZDebug::writeNotice( "Class filter returned false" );
01847 $retValue = null;
01848 return $retValue;
01849 }
01850
01851 $attributeFilter = eZContentObjectTreeNode::createAttributeFilterSQLStrings( $params['AttributeFilter'], $sortingInfo );
01852 if ( $attributeFilter === false )
01853 {
01854 $retValue = null;
01855 return $retValue;
01856 }
01857 $extendedAttributeFilter = eZContentObjectTreeNode::createExtendedAttributeFilterSQLStrings( $params['ExtendedAttributeFilter'] );
01858 $mainNodeOnlyCond = eZContentObjectTreeNode::createMainNodeConditionSQLString( $mainNodeOnly );
01859
01860 $pathStringCond = '';
01861 $notEqParentString = '';
01862
01863 if ( !eZContentObjectTreeNode::createPathConditionAndNotEqParentSQLStrings( $pathStringCond, $notEqParentString, $this, $nodeID, $depth, $depthOperator ) )
01864 {
01865 $retValue = null;
01866 return $retValue;
01867 }
01868
01869 $groupBySelectText = '';
01870 $groupByText = '';
01871 eZContentObjectTreeNode::createGroupBySQLStrings( $groupBySelectText, $groupByText, $groupBy );
01872
01873 $useVersionName = true;
01874
01875 $versionNameTables = eZContentObjectTreeNode::createVersionNameTablesSQLString ( $useVersionName );
01876 $versionNameTargets = eZContentObjectTreeNode::createVersionNameTargetsSQLString( $useVersionName );
01877 $versionNameJoins = eZContentObjectTreeNode::createVersionNameJoinsSQLString ( $useVersionName, false );
01878
01879 $languageFilter = ' AND ' . eZContentLanguage::languagesSQLFilter( 'ezcontentobject' );
01880
01881 if ( $language )
01882 {
01883 eZContentLanguage::clearPrioritizedLanguages();
01884 }
01885 $objectNameFilterSQL = eZContentObjectTreeNode::createObjectNameFilterConditionSQLString( $objectNameFilter );
01886
01887 $limitation = ( isset( $params['Limitation'] ) && is_array( $params['Limitation'] ) ) ? $params['Limitation']: false;
01888 $limitationList = eZContentObjectTreeNode::getLimitationList( $limitation );
01889 $sqlPermissionChecking = eZContentObjectTreeNode::createPermissionCheckingSQL( $limitationList );
01890
01891
01892 $showInvisibleNodesCond = eZContentObjectTreeNode::createShowInvisibleSQLString( !$ignoreVisibility );
01893
01894 $query = "SELECT DISTINCT
01895 ezcontentobject.*,
01896 ezcontentobject_tree.*,
01897 ezcontentclass.serialized_name_list as class_serialized_name_list,
01898 ezcontentclass.identifier as class_identifier,
01899 ezcontentclass.is_container as is_container
01900 $groupBySelectText
01901 $versionNameTargets
01902 $sortingInfo[attributeTargetSQL]
01903 FROM
01904 ezcontentobject_tree,
01905 ezcontentobject,ezcontentclass
01906 $versionNameTables
01907 $sortingInfo[attributeFromSQL]
01908 $attributeFilter[from]
01909 $extendedAttributeFilter[tables]
01910 $sqlPermissionChecking[from]
01911 WHERE
01912 $pathStringCond
01913 $extendedAttributeFilter[joins]
01914 $sortingInfo[attributeWhereSQL]
01915 $attributeFilter[where]
01916 ezcontentclass.version=0 AND
01917 $notEqParentString
01918 ezcontentobject_tree.contentobject_id = ezcontentobject.id AND
01919 ezcontentclass.id = ezcontentobject.contentclass_id AND
01920 $mainNodeOnlyCond
01921 $classCondition
01922 $versionNameJoins
01923 $showInvisibleNodesCond
01924 $sqlPermissionChecking[where]
01925 $objectNameFilterSQL
01926 $languageFilter
01927 $groupByText";
01928
01929 if ( $sortingInfo['sortingFields'] )
01930 $query .= " ORDER BY $sortingInfo[sortingFields]";
01931
01932 $db =& eZDB::instance();
01933
01934 $server = count( $sqlPermissionChecking['temp_tables'] ) > 0 ? EZ_DB_SERVER_SLAVE : false;
01935
01936 if ( !$offset && !$limit )
01937 {
01938 $nodeListArray = $db->arrayQuery( $query, array(), $server );
01939 }
01940 else
01941 {
01942 $nodeListArray = $db->arrayQuery( $query, array( 'offset' => $offset,
01943 'limit' => $limit ),
01944 $server );
01945 }
01946
01947 if ( $asObject )
01948 {
01949 $retNodeList = eZContentObjectTreeNode::makeObjectsArray( $nodeListArray );
01950 if ( $loadDataMap )
01951 eZContentObject::fillNodeListAttributes( $retNodeList );
01952 }
01953 else
01954 {
01955 $retNodeList =& $nodeListArray;
01956 }
01957
01958
01959 $db->dropTempTableList( $sqlPermissionChecking['temp_tables'] );
01960
01961 return $retNodeList;
01962 }
01963
01964
01965
01966
01967
01968
01969
01970
01971
01972
01973
01974
01975
01976
01977
01978
01979
01980
01981
01982
01983
01984
01985
01986
01987
01988
01989
01990
01991
01992
01993
01994
01995
01996 function subTreeMultiPaths( $nodesParams, $listParams = NULL )
01997 {
01998 if( !is_array( $nodesParams ) || !count( $nodesParams ) )
01999 {
02000 eZDebug::writeWarning( __CLASS__.'::'.__FUNCTION__.': Nodes parameter must be an array with at least one key.' );
02001 $retValue = null;
02002 return $retValue;
02003 }
02004
02005 if( is_null( $listParams ) )
02006 {
02007 $listParams = array(
02008 'SortBy' => false,
02009 'Offset' => false,
02010 'Limit' => false,
02011 'SortBy' => false,
02012 'GroupBy' => false );
02013 }
02014
02015 $offset = ( isset( $listParams['Offset'] ) && is_numeric( $listParams['Offset'] ) ) ? $listParams['Offset'] : false;
02016 $limit = ( isset( $listParams['Limit'] ) && is_numeric( $listParams['Limit'] ) ) ? $listParams['Limit'] : false;
02017 $groupBy = ( isset( $listParams['GroupBy'] ) ) ? $listParams['GroupBy'] : false;
02018 if ( !isset( $listParams['SortBy'] ) )
02019 {
02020 $listParams['SortBy'] = false;
02021 }
02022 $sortBy = $listParams['SortBy'];
02023
02024 $queryNodes = '';
02025
02026 foreach( $nodesParams as $nodeParams )
02027 {
02028 $nodeID = $nodeParams['ParentNodeID'];
02029
02030 if ( !is_numeric( $nodeID ) && !is_array( $nodeID ) )
02031 {
02032 eZDebug::writeWarning( __CLASS__.'::'.__FUNCTION__.': Nodes parameter must be numeric or an array with numeric values.' );
02033 $retValue = null;
02034 return $retValue;
02035 }
02036
02037 if ( is_null( $nodeParams ) )
02038 {
02039 $nodeParams = array(
02040 'Depth' => false,
02041
02042 'Language' => false,
02043 'AttributeFilter' => false,
02044 'ExtendedAttributeFilter' => false,
02045 'ClassFilterType' => false,
02046 'ClassFilterArray' => false );
02047 }
02048
02049
02050 $language = ( isset( $nodeParams['Language'] ) ) ? $nodeParams['Language'] : false;
02051 $depth = ( isset( $nodeParams['Depth'] ) && is_numeric( $nodeParams['Depth'] ) ) ? $nodeParams['Depth'] : false;
02052 $depthOperator = ( isset( $nodeParams['DepthOperator'] ) ) ? $nodeParams['DepthOperator'] : false;
02053 $asObject = ( isset( $nodeParams['AsObject'] ) ) ? $nodeParams['AsObject'] : true;
02054 $mainNodeOnly = ( isset( $nodeParams['MainNodeOnly'] ) ) ? $nodeParams['MainNodeOnly'] : false;
02055 $ignoreVisibility = ( isset( $nodeParams['IgnoreVisibility'] ) ) ? $nodeParams['IgnoreVisibility'] : false;
02056 if ( !isset( $nodeParams['ClassFilterType'] ) )
02057 {
02058 $nodeParams['ClassFilterType'] = false;
02059 }
02060
02061 if ( $language )
02062 {
02063 if ( !is_array( $language ) )
02064 {
02065 $language = array( $language );
02066 }
02067 eZContentLanguage::setPrioritizedLanguages( $language );
02068 }
02069
02070 $sortingInfo = eZContentObjectTreeNode::createSortingSQLStrings( $sortBy );
02071 $classCondition = eZContentObjectTreeNode::createClassFilteringSQLString( $nodeParams['ClassFilterType'], $nodeParams['ClassFilterArray'] );
02072 $attributeFilter = eZContentObjectTreeNode::createAttributeFilterSQLStrings( $nodeParams['AttributeFilter'], $sortingInfo );
02073 $extendedAttributeFilter = eZContentObjectTreeNode::createExtendedAttributeFilterSQLStrings( $nodeParams['ExtendedAttributeFilter'] );
02074 $mainNodeOnlyCond = eZContentObjectTreeNode::createMainNodeConditionSQLString( $mainNodeOnly );
02075
02076 $pathStringCond = '';
02077 $notEqParentString = '';
02078
02079 $noNode = null;
02080 if ( !eZContentObjectTreeNode::createPathConditionAndNotEqParentSQLStrings( $pathStringCond, $notEqParentString, $noNode, $nodeID, $depth, $depthOperator ) )
02081 {
02082 $retValue = null;
02083 return $retValue;
02084 }
02085
02086 $useVersionName = true;
02087 $versionNameTables = eZContentObjectTreeNode::createVersionNameTablesSQLString ( $useVersionName );
02088 $versionNameTargets = eZContentObjectTreeNode::createVersionNameTargetsSQLString( $useVersionName );
02089 $versionNameJoins = eZContentObjectTreeNode::createVersionNameJoinsSQLString ( $useVersionName, false );
02090
02091 $languageFilter = ' AND ' . eZContentLanguage::languagesSQLFilter( 'ezcontentobject' );
02092
02093 if ( $language )
02094 {
02095 eZContentLanguage::clearPrioritizedLanguages();
02096 }
02097
02098 $limitation = ( isset( $nodeParams['Limitation'] ) && is_array( $nodeParams['Limitation'] ) ) ? $nodeParams['Limitation']: false;
02099 $limitationList = eZContentObjectTreeNode::getLimitationList( $limitation );
02100 $sqlPermissionChecking = eZContentObjectTreeNode::createPermissionCheckingSQL( $limitationList );
02101
02102
02103 $showInvisibleNodesCond = eZContentObjectTreeNode::createShowInvisibleSQLString( !$ignoreVisibility );
02104
02105 $queryNodes .= " (
02106 $pathStringCond
02107 $extendedAttributeFilter[joins]
02108 $sortingInfo[attributeWhereSQL]
02109 $attributeFilter[where]
02110 ezcontentclass.version=0 AND
02111 $notEqParentString
02112 ezcontentobject_tree.contentobject_id = ezcontentobject.id AND
02113 ezcontentclass.id = ezcontentobject.contentclass_id AND
02114 $mainNodeOnlyCond
02115 $classCondition
02116 $versionNameJoins
02117 $showInvisibleNodesCond
02118 $sqlPermissionChecking[where]
02119 $languageFilter
02120 )
02121 OR";
02122 }
02123
02124 $groupBySelectText = '';
02125 $groupByText = '';
02126 eZContentObjectTreeNode::createGroupBySQLStrings( $groupBySelectText, $groupByText, $groupBy );
02127
02128 $query = "SELECT DISTINCT
02129 ezcontentobject.*,
02130 ezcontentobject_tree.*,
02131 ezcontentclass.serialized_name_list as class_serialized_name_list,
02132 ezcontentclass.identifier as class_identifier
02133 $groupBySelectText
02134 $versionNameTargets
02135 $sortingInfo[attributeTargetSQL]
02136 , ".$nodeParams['ResultID']." AS resultid
02137 FROM
02138 ezcontentobject_tree,
02139 ezcontentobject,ezcontentclass
02140 $versionNameTables
02141 $sortingInfo[attributeFromSQL]
02142 $attributeFilter[from]
02143 $extendedAttributeFilter[tables]
02144 $sqlPermissionChecking[from]
02145 WHERE
02146 ".substr($queryNodes, 0, -2)."
02147 $groupByText";
02148
02149 if ( $sortingInfo['sortingFields'] )
02150 {
02151 $query .= " ORDER BY $sortingInfo[sortingFields]";
02152 }
02153
02154 $db =& eZDB::instance();
02155
02156 $server = count( $sqlPermissionChecking['temp_tables'] ) > 0 ? EZ_DB_SERVER_SLAVE : false;
02157
02158 if ( !$offset && !$limit )
02159 {
02160 $nodeListArray = $db->arrayQuery( $query, array(), $server );
02161 }
02162 else
02163 {
02164 $nodeListArray = $db->arrayQuery( $query, array( 'offset' => $offset,
02165 'limit' => $limit ),
02166 $server );
02167 }
02168
02169 if ( $asObject )
02170 {
02171 $retNodeList = eZContentObjectTreeNode::makeObjectsArray( $nodeListArray );
02172 }
02173 else
02174 {
02175 $retNodeList =& $nodeListArray;
02176 }
02177
02178
02179 $db->dropTempTableList( $sqlPermissionChecking['temp_tables'] );
02180
02181 return $retNodeList;
02182 }
02183
02184 function subTreeGroupByDateField( $field, $type )
02185 {
02186 $divisor = 0;
02187 switch ( $type )
02188 {
02189 case 'year':
02190 {
02191 $divisor = 60*60*24*365;
02192 } break;
02193 case 'week':
02194 {
02195 $divisor = 60*60*24*7;
02196 } break;
02197 case 'day':
02198 {
02199 $divisor = 60*60*24;
02200 } break;
02201 case 'hour':
02202 {
02203 $divisor = 60*60;
02204 } break;
02205 case 'minute':
02206 {
02207 $divisor = 60;
02208 } break;
02209 case 'second':
02210 {
02211 $divisor = 0;
02212 } break;
02213 default:
02214 {
02215 eZDebug::writeError( "Unknown field type $type",
02216 'eZContentObjectTreeNode::subTreeGroupByDateField' );
02217 }
02218 }
02219 if ( $divisor > 0 )
02220 $text = "( $field / $divisor ) AS groupbyfield";
02221 else
02222 $text = "$field AS groupbyfield";
02223 return array( 'select' => $text,
02224 'group_field' => "( $field / $divisor )" );
02225 }
02226
02227
02228
02229
02230
02231
02232 function &subTreeCount( $params = array(), $nodeID = 0 )
02233 {
02234 if ( !is_numeric( $nodeID ) and !is_array( $nodeID ) )
02235 {
02236 $retVal = null;
02237 return $retVal;
02238 }
02239
02240 $language = ( isset( $params['Language'] ) ) ? $params['Language'] : false;
02241
02242 if ( $language )
02243 {
02244 if ( !is_array( $language ) )
02245 {
02246 $language = array( $language );
02247 }
02248 eZContentLanguage::setPrioritizedLanguages( $language );
02249 }
02250
02251 $depth = isset( $params['Depth'] ) && is_numeric( $params['Depth'] ) ? $params['Depth'] : false;
02252 $depthOperator = isset( $params['DepthOperator'] ) ? $params['DepthOperator'] : false;
02253
02254 $pathStringCond = '';
02255 $notEqParentString = '';
02256
02257 if ( !eZContentObjectTreeNode::createPathConditionAndNotEqParentSQLStrings( $pathStringCond, $notEqParentString, $this, $nodeID, $depth, $depthOperator ) )
02258 {
02259 $retVal = null;
02260 return $retVal;
02261 }
02262
02263 $db =& eZDB::instance();
02264
02265 $limitation = ( isset( $params['Limitation'] ) && is_array( $params['Limitation'] ) ) ? $params['Limitation']: false;
02266 $limitationList = eZContentObjectTreeNode::getLimitationList( $limitation );
02267
02268 $ini =& eZINI::instance();
02269
02270
02271 $classCondition = '';
02272
02273 if ( isset( $params['ClassFilterType'] ) and isset( $params['ClassFilterArray'] ) and
02274 ( $params['ClassFilterType'] == 'include' or $params['ClassFilterType'] == 'exclude' )
02275 and count( $params['ClassFilterArray'] ) > 0 )
02276 {
02277 $classCondition = ' ';
02278 $i = 0;
02279 $classCount = count( $params['ClassFilterArray'] );
02280 $classIDArray = array();
02281 foreach ( $params['ClassFilterArray'] as $classID )
02282 {
02283 $originalClassID = $classID;
02284
02285 if ( is_string( $classID ) && !is_numeric( $classID ) )
02286 {
02287 $classID = eZContentObjectTreeNode::classIDByIdentifier( $classID );
02288 }
02289 if ( is_numeric( $classID ) )
02290 {
02291 $classIDArray[] = $classID;
02292 }
02293 else
02294 {
02295 eZDebugSetting::writeWarning( 'kernel-content-class', "Invalid class identifier in subTree() classfilterarray, classID : " . $originalClassID );
02296 }
02297 }
02298 if ( count( $classIDArray ) > 0 )
02299 {
02300 $classCondition .= " ezcontentobject.contentclass_id ";
02301 if ( $params['ClassFilterType'] == 'include' )
02302 $classCondition .= " IN ";
02303 else
02304 $classCondition .= " NOT IN ";
02305
02306 $classIDString = implode( ', ', $classIDArray );
02307 $classCondition .= ' ( ' . $classIDString . ' ) AND';
02308 }
02309 }
02310
02311
02312
02313 $mainNodeOnlyCond = '';
02314 if ( isset( $params['MainNodeOnly'] ) && $params['MainNodeOnly'] === true )
02315 {
02316 $mainNodeOnlyCond = 'ezcontentobject_tree.node_id = ezcontentobject_tree.main_node_id AND';
02317 }
02318
02319
02320
02321 $attributeFilterFromSQL = "";
02322 $attributeFilterWhereSQL = "";
02323
02324 $totalAttributesFiltersCount = 0;
02325 $invalidAttributesFiltersCount = 0;
02326
02327 if ( isset( $params['AttributeFilter'] ) )
02328 {
02329 $filterArray = $params['AttributeFilter'];
02330
02331
02332
02333 $filterJoinType = 'AND';
02334 if ( is_string( $filterArray[0] ) )
02335 {
02336 if ( strtolower( $filterArray[0] ) == 'or' )
02337 {
02338 $filterJoinType = 'OR';
02339 }
02340 else if ( strtolower( $filterArray[0] ) == 'and' )
02341 {
02342 $filterJoinType = 'AND';
02343 }
02344 unset( $filterArray[0] );
02345 }
02346
02347 $attibuteFilterJoinSQL = "";
02348 $filterCount = 0;
02349
02350 if ( is_array( $filterArray ) )
02351 {
02352
02353 $totalAttributesFiltersCount = count( $filterArray );
02354
02355 foreach ( $filterArray as $filter )
02356 {
02357 $isFilterValid = true;
02358
02359 $filterAttributeID = $filter[0];
02360 $filterType = $filter[1];
02361 $filterValue = is_array( $filter[2] ) ? '' : $db->escapeString( $filter[2] );
02362
02363 $useAttributeFilter = false;
02364 switch ( $filterAttributeID )
02365 {
02366 case 'path':
02367 {
02368 $filterField = 'path_string';
02369 } break;
02370 case 'published':
02371 {
02372 $filterField = 'ezcontentobject.published';
02373 } break;
02374 case 'modified':
02375 {
02376 $filterField = 'ezcontentobject.modified';
02377 } break;
02378 case 'modified_subnode':
02379 {
02380 $filterField = 'modified_subnode';
02381 } break;
02382 case 'section':
02383 {
02384 $filterField = 'ezcontentobject.section_id';
02385 } break;
02386 case 'depth':
02387 {
02388 $filterField = 'depth';
02389 } break;
02390 case 'class_identifier':
02391 {
02392 $filterField = 'ezcontentclass.identifier';
02393 } break;
02394 case 'class_name':
02395 {
02396 $classNameFilter = eZContentClassName::sqlFilter();
02397 $filterField .= $classNameFilter['nameField'];
02398 $attributeFromSQL .= ", $classNameFilter[from]";
02399 $attributeWhereSQL .= "$classNameFilter[where] AND ";
02400 } break;
02401 case 'priority':
02402 {
02403 $filterField = 'ezcontentobject_tree.priority';
02404 } break;
02405 case 'name':
02406 {
02407 $filterField = 'ezcontentobject_name.name';
02408 } break;
02409 case 'owner':
02410 {
02411 $filterField = 'ezcontentobject.owner_id';
02412 } break;
02413 default:
02414 {
02415 $useAttributeFilter = true;
02416 } break;
02417 }
02418
02419 if ( $useAttributeFilter )
02420 {
02421 if ( !is_numeric( $filterAttributeID ) )
02422 $filterAttributeID = eZContentObjectTreeNode::classAttributeIDByIdentifier( $filterAttributeID );
02423
02424 if ( $filterAttributeID === false )
02425 {
02426 $isFilterValid = false;
02427 if( $filterJoinType === 'AND' )
02428 {
02429
02430 $invalidAttributesFiltersCount = $totalAttributesFiltersCount;
02431 break;
02432 }
02433
02434
02435 ++$invalidAttributesFiltersCount;
02436 }
02437 else
02438 {
02439
02440 $filterDataType = eZContentObjectTreeNode::sortKeyByClassAttributeID( $filterAttributeID );
02441 if ( $filterDataType === false )
02442 {
02443 $isFilterValid = false;
02444 if( $filterJoinType === 'AND' )
02445 {
02446
02447 $invalidAttributesFiltersCount = $totalAttributesFiltersCount;
02448 break;
02449 }
02450
02451
02452 ++$invalidAttributesFiltersCount;
02453 }
02454 else
02455 {
02456 $sortKey = false;
02457 if ( $filterDataType == 'string' )
02458 {
02459 $sortKey = 'sort_key_string';
02460 }
02461 else
02462 {
02463 $sortKey = 'sort_key_int';
02464 }
02465
02466 $filterField = "a$filterCount.$sortKey";
02467
02468
02469
02470 $attributeFilterFromSQL .= ", ezcontentobject_attribute a$filterCount ";
02471 $attributeFilterWhereSQL .= "
02472 a$filterCount.contentobject_id = ezcontentobject.id AND
02473 a$filterCount.version = ezcontentobject.current_version AND
02474 a$filterCount.contentclassattribute_id = $filterAttributeID AND ";
02475 $attributeFilterWhereSQL .= eZContentLanguage::sqlFilter( "a$filterCount", 'ezcontentobject' );
02476 $attributeFilterWhereSQL .= ' AND ';
02477 }
02478
02479 }
02480 }
02481
02482 if ( $isFilterValid )
02483 {
02484 $hasFilterOperator = true;
02485
02486 $noQuotes = false;
02487
02488 $unEscape = false;
02489
02490 switch ( $filterType )
02491 {
02492 case '=' :
02493 {
02494 $filterOperator = '=';
02495 }break;
02496
02497 case '!=' :
02498 {
02499 $filterOperator = '<>';
02500 }break;
02501
02502 case '>' :
02503 {
02504 $filterOperator = '>';
02505 }break;
02506
02507 case '<' :
02508 {
02509 $filterOperator = '<';
02510 }break;
02511
02512 case '<=' :
02513 {
02514 $filterOperator = '<=';
02515 }break;
02516
02517 case '>=' :
02518 {
02519 $filterOperator = '>=';
02520 }break;
02521
02522 case 'like':
02523 case 'not_like':
02524 {
02525 $filterOperator = ( $filterType == 'like' ? 'LIKE' : 'NOT LIKE' );
02526
02527 $filter[2] = $db->escapeString( $filter[2] );
02528 $unEscape = true;
02529
02530
02531
02532
02533
02534
02535
02536 $filter[2] = preg_replace( array( '#%#m',
02537 '#(?<!\\\\)\\*#m',
02538 '#(?<!\\\\)\\\\\\*#m',
02539 '#\\\\\\\\#m' ),
02540 array( '\\%',
02541 '%',
02542 '*',
02543 '\\\\' ),
02544 $filter[2] );
02545 } break;
02546
02547 case 'in':
02548 case 'not_in' :
02549 {
02550 $filterOperator = ( $filterType == 'in' ? 'IN' : 'NOT IN' );
02551
02552 $noQuotes = true;
02553 if ( is_array( $filter[2] ) )
02554 {
02555 reset( $filter[2] );
02556 while ( list( $key, $value ) = each( $filter[2] ) )
02557 {
02558
02559 $filter[2][$key] = is_numeric( $value ) ? $value : "'" . $db->escapeString( $value ) . "'";
02560 }
02561 $filterValue = '(' . implode( ",", $filter[2] ) . ')';
02562 }
02563 else
02564 {
02565 $hasFilterOperator = false;
02566 }
02567 } break;
02568
02569 case 'between':
02570 case 'not_between' :
02571 {
02572 $filterOperator = ( $filterType == 'between' ? 'BETWEEN' : 'NOT BETWEEN' );
02573
02574 $noQuotes = true;
02575 if ( is_array( $filter[2] ) )
02576 {
02577
02578 if ( !is_numeric( $filter[2][0] ) )
02579 $filter[2][0] = "'" . $db->escapeString( $filter[2][0] ) . "'";
02580 if ( !is_numeric( $filter[2][1] ) )
02581 $filter[2][1] = "'" . $db->escapeString( $filter[2][1] ) . "'";
02582
02583 $filterValue = $filter[2][0] . ' AND ' . $filter[2][1];
02584 }
02585 } break;
02586
02587 default :
02588 {
02589 $hasFilterOperator = false;
02590 eZDebug::writeError( "Unknown attribute filter type: $filterType", "eZContentObjectTreeNode::subTree()" );
02591 }break;
02592
02593 }
02594 if ( $hasFilterOperator )
02595 {
02596 if ( $filterCount > 0 )
02597 $attibuteFilterJoinSQL .= " $filterJoinType ";
02598
02599
02600
02601 $filterValue = $unEscape ? $filter[2] : $filterValue;
02602
02603 $attibuteFilterJoinSQL .= "$filterField $filterOperator ";
02604 $attibuteFilterJoinSQL .= $noQuotes ? "$filterValue " : "'$filterValue' ";
02605
02606 $filterCount++;
02607 }
02608 }
02609 }
02610
02611 if ( $totalAttributesFiltersCount == $invalidAttributesFiltersCount )
02612 {
02613 $attributeFilterFromSQL = "";
02614 $attributeFilterWhereSQL = "";
02615
02616 eZDebug::writeNotice( "Attribute filter returned false" );
02617 $retVal = 0;
02618 return $retVal;
02619 }
02620 else
02621 {
02622 if ( $filterCount > 0 )
02623 $attributeFilterWhereSQL .= "\n ( " . $attibuteFilterJoinSQL . " ) AND ";
02624 }
02625 }
02626 }
02627
02628
02629
02630 $useVersionName = true;
02631
02632 $versionNameTables = eZContentObjectTreeNode::createVersionNameTablesSQLString ( $useVersionName );
02633 $versionNameTargets = eZContentObjectTreeNode::createVersionNameTargetsSQLString( $useVersionName );
02634 $versionNameJoins = eZContentObjectTreeNode::createVersionNameJoinsSQLString ( $useVersionName, false );
02635
02636 $languageFilter = ' AND '.eZContentLanguage::languagesSQLFilter( 'ezcontentobject' );
02637
02638 if ( $language )
02639 {
02640 eZContentLanguage::clearPrioritizedLanguages();
02641 }
02642 $objectNameFilter = ( isset( $params['ObjectNameFilter'] ) ) ? $params['ObjectNameFilter'] : false;
02643 $objectNameFilterSQL = eZContentObjectTreeNode::createObjectNameFilterConditionSQLString( $objectNameFilter );
02644
02645 $extendedAttributeFilter = eZContentObjectTreeNode::createExtendedAttributeFilterSQLStrings( $params['ExtendedAttributeFilter'] );
02646
02647
02648 $ignoreVisibility = isset( $params['IgnoreVisibility'] ) ? $params['IgnoreVisibility'] : false;
02649 $showInvisibleNodesCond = eZContentObjectTreeNode::createShowInvisibleSQLString( !$ignoreVisibility );
02650
02651 $sqlPermissionCheckingFrom = '';
02652 $sqlPermissionCheckingWhere = '';
02653 $sqlPermissionTempTables = array();
02654 $groupPermTempTable = false;
02655
02656 if ( $limitationList !== false && count( $limitationList ) > 0 )
02657 {
02658 $sqlParts = array();
02659
02660 foreach( $limitationList as $limitationArray )
02661 {
02662 $sqlPartPart = array();
02663 $sqlPartPartPart = array();
02664
02665 foreach ( array_keys( $limitationArray ) as $ident )
02666 {
02667 switch( $ident )
02668 {
02669 case 'Class':
02670 {
02671 $sqlPartPart[] = 'ezcontentobject.contentclass_id in (' . implode( ', ', $limitationArray[$ident] ) . ')';
02672 } break;
02673
02674 case 'Section':
02675 case 'User_Section':
02676 {
02677 $sqlPartPart[] = 'ezcontentobject.section_id in (' . implode( ', ', $limitationArray[$ident] ) . ')';
02678 } break;
02679
02680 case 'Owner':
02681 {
02682 $user =& eZUser::currentUser();
02683 $userID = $user->attribute( 'contentobject_id' );
02684 $sqlPartPart[] = "ezcontentobject.owner_id = '" . $db->escapeString( $userID ) . "'";
02685 } break;
02686
02687 case 'Group':
02688 {
02689 if ( !$groupPermTempTable )
02690 {
02691 $user =& eZUser::currentUser();
02692 $userContentObject =& $user->attribute( 'contentobject' );
02693 $parentList =& $userContentObject->attribute( 'parent_nodes' );
02694
02695 $groupPermTempTable = $db->generateUniqueTempTableName( 'ezgroup_perm_tmp_%' );
02696 $sqlPermissionTempTables[] = $groupPermTempTable;
02697
02698 $db->createTempTable( "CREATE TEMPORARY TABLE $groupPermTempTable ( user_id int )" );
02699 $db->query( "INSERT INTO $groupPermTempTable
02700 SELECT DISTINCT contentobject_id AS user_id
02701 FROM ezcontentobject_tree
02702 WHERE parent_node_id IN (" . implode( ', ', $parentList ) . ')' );
02703
02704 $sqlPermissionCheckingFrom = ', ' . $groupPermTempTable;
02705 }
02706 $sqlPartPart[] = "ezcontentobject.owner_id = $groupPermTempTable.user_id";
02707 } break;
02708
02709 case 'Node':
02710 {
02711 $sqlPartPartPart[] = 'ezcontentobject_tree.node_id in (' . implode( ', ', $limitationArray[$ident] ) . ')';
02712 } break;
02713
02714 case 'Subtree':
02715 {
02716 $pathArray =& $limitationArray[$ident];
02717 foreach ( $pathArray as $limitationPathString )
02718 {
02719 $sqlPartPartPart[] = "ezcontentobject_tree.path_string like '$limitationPathString%'";
02720 }
02721 } break;
02722
02723 case 'User_Subtree':
02724 {
02725 $pathArray =& $limitationArray[$ident];
02726 $sqlPartUserSubtree = array();
02727 foreach ( $pathArray as $limitationPathString )
02728 {
02729 $sqlPartUserSubtree[] = "ezcontentobject_tree.path_string like '$limitationPathString%'";
02730 }
02731 $sqlPartPart[] = implode( ' OR ', $sqlPartUserSubtree );
02732 }
02733 }
02734 }
02735 if ( $sqlPartPartPart )
02736 {
02737 $sqlPartPart[] = '( ' . implode( ' ) OR ( ', $sqlPartPartPart ). ' )';
02738 }
02739 $sqlParts[] = implode( ' AND ', $sqlPartPart );
02740 }
02741
02742 $sqlPermissionCheckingWhere = ' AND ((' . implode( ') or (', $sqlParts ) . ')) ';
02743 $sqlPermissionChecking = array( 'from' => $sqlPermissionCheckingFrom,
02744 'where' => $sqlPermissionCheckingWhere );
02745
02746 $query = "SELECT
02747 count( DISTINCT ezcontentobject_tree.node_id ) as count
02748 FROM
02749 ezcontentobject_tree,
02750 ezcontentobject,ezcontentclass
02751 $versionNameTables
02752 $attributeFilterFromSQL
02753 $extendedAttributeFilter[tables]
02754 $sqlPermissionChecking[from]
02755 WHERE $pathStringCond
02756 $extendedAttributeFilter[joins]
02757 $mainNodeOnlyCond
02758 $classCondition
02759 $attributeFilterWhereSQL
02760 ezcontentclass.version=0 AND
02761 $notEqParentString
02762 ezcontentobject_tree.contentobject_id = ezcontentobject.id AND
02763 ezcontentclass.id = ezcontentobject.contentclass_id AND
02764 $versionNameJoins
02765 $showInvisibleNodesCond
02766 $sqlPermissionChecking[where]
02767 $objectNameFilterSQL
02768 $languageFilter ";
02769
02770 }
02771 else
02772 {
02773 $query="SELECT
02774 count( DISTINCT ezcontentobject_tree.node_id ) as count
02775 FROM
02776 ezcontentobject_tree,
02777 ezcontentobject,
02778 ezcontentclass
02779 $versionNameTables
02780 $attributeFilterFromSQL
02781 $extendedAttributeFilter[tables]
02782 WHERE
02783 $pathStringCond
02784 $extendedAttributeFilter[joins]
02785 $mainNodeOnlyCond
02786 $classCondition
02787 $attributeFilterWhereSQL
02788 ezcontentclass.version=0 AND
02789 $notEqParentString
02790 ezcontentobject_tree.contentobject_id = ezcontentobject.id AND
02791 ezcontentclass.id = ezcontentobject.contentclass_id AND
02792 $versionNameJoins
02793 $showInvisibleNodesCond
02794 $objectNameFilterSQL
02795 $languageFilter ";
02796 }
02797
02798 $server = count( $sqlPermissionTempTables ) > 0 ? EZ_DB_SERVER_SLAVE : false;
02799
02800 $nodeListArray = $db->arrayQuery( $query, array(), $server );
02801
02802
02803 $db->dropTempTableList( $sqlPermissionTempTables );
02804
02805 return $nodeListArray[0]['count'];
02806 }
02807
02808
02809
02810
02811 function calendar( $params = false, $nodeID = 0 )
02812 {
02813 if ( !is_numeric( $nodeID ) and !is_array( $nodeID ) )
02814 {
02815 return array();
02816 }
02817
02818 if ( $params === false )
02819 {
02820 $params = array( 'Depth' => false,
02821 'Offset' => false,
02822 'Limit' => false,
02823 'AttributeFilter' => false,
02824 'ExtendedAttributeFilter' => false,
02825 'ClassFilterType' => false,
02826 'ClassFilterArray' => false,
02827 'GroupBy' => false );
02828 }
02829
02830 $offset = ( isset( $params['Offset'] ) && is_numeric( $params['Offset'] ) ) ? $params['Offset'] : false;
02831 $limit = ( isset( $params['Limit'] ) && is_numeric( $params['Limit'] ) ) ? $params['Limit'] : false;
02832 $depth = ( isset( $params['Depth'] ) && is_numeric( $params['Depth'] ) ) ? $params['Depth'] : false;
02833 $depthOperator = ( isset( $params['DepthOperator'] ) ) ? $params['DepthOperator'] : false;
02834 $groupBy = ( isset( $params['GroupBy'] ) ) ? $params['GroupBy'] : false;
02835 $mainNodeOnly = ( isset( $params['MainNodeOnly'] ) ) ? $params['MainNodeOnly'] : false;
02836 $ignoreVisibility = ( isset( $params['IgnoreVisibility'] ) ) ? $params['IgnoreVisibility'] : false;
02837 if ( !isset( $params['ClassFilterType'] ) )
02838 $params['ClassFilterType'] = false;
02839
02840 $classCondition = eZContentObjectTreeNode::createClassFilteringSQLString( $params['ClassFilterType'], $params['ClassFilterArray'] );
02841 $attributeFilter = eZContentObjectTreeNode::createAttributeFilterSQLStrings( $params['AttributeFilter'], $sortingInfo );
02842 $extendedAttributeFilter = eZContentObjectTreeNode::createExtendedAttributeFilterSQLStrings( $params['ExtendedAttributeFilter'] );
02843 $mainNodeOnlyCond = eZContentObjectTreeNode::createMainNodeConditionSQLString( $mainNodeOnly );
02844
02845 $pathStringCond = '';
02846 $notEqParentString = '';
02847 eZContentObjectTreeNode::createPathConditionAndNotEqParentSQLStrings( $pathStringCond, $notEqParentString, $this, $nodeID, $depth, $depthOperator );
02848
02849 $groupBySelectText = '';
02850 $groupByText = '';
02851 eZContentObjectTreeNode::createGroupBySQLStrings( $groupBySelectText, $groupByText, $groupBy );
02852
02853 $useVersionName = true;
02854 $versionNameTables = eZContentObjectTreeNode::createVersionNameTablesSQLString( $useVersionName );
02855 $versionNameJoins = eZContentObjectTreeNode::createVersionNameJoinsSQLString( $useVersionName, false );
02856
02857 $limitation = ( isset( $params['Limitation'] ) && is_array( $params['Limitation'] ) ) ? $params['Limitation']: false;
02858 $limitationList = eZContentObjectTreeNode::getLimitationList( $limitation );
02859 $sqlPermissionChecking = eZContentObjectTreeNode::createPermissionCheckingSQL( $limitationList );
02860
02861
02862 $showInvisibleNodesCond = eZContentObjectTreeNode::createShowInvisibleSQLString( !$ignoreVisibility );
02863
02864 $query = "SELECT DISTINCT
02865 ezcontentobject.published as published
02866 $groupBySelectText
02867 FROM
02868 ezcontentobject_tree,
02869 ezcontentobject,ezcontentclass
02870 $versionNameTables
02871 $attributeFilter[from]
02872 $extendedAttributeFilter[tables]
02873 $sqlPermissionChecking[from]
02874 WHERE
02875 $pathStringCond
02876 $extendedAttributeFilter[joins]
02877 $attributeFilter[where]
02878 ezcontentclass.version=0
02879 AND
02880 $notEqParentString
02881 $mainNodeOnlyCond
02882 ezcontentobject_tree.contentobject_id = ezcontentobject.id AND
02883 ezcontentclass.id = ezcontentobject.contentclass_id AND
02884 $classCondition
02885 $versionNameJoins
02886 $showInvisibleNodesCond
02887 $sqlPermissionChecking[where]
02888 $groupByText ";
02889
02890
02891 $db =& eZDB::instance();
02892
02893 $server = count( $sqlPermissionChecking['temp_tables'] ) > 0 ? EZ_DB_SERVER_SLAVE : false;
02894
02895 if ( !$offset && !$limit )
02896 {
02897 $nodeListArray = $db->arrayQuery( $query, array(), $server );
02898 }
02899 else
02900 {
02901 $nodeListArray = $db->arrayQuery( $query, array( 'offset' => $offset,
02902 'limit' => $limit ),
02903 $server );
02904 }
02905
02906 $retNodeList =& $nodeListArray;
02907
02908
02909 $db->dropTempTableList( $sqlPermissionChecking['temp_tables'] );
02910
02911 return $retNodeList;
02912
02913 }
02914
02915
02916
02917 function &childrenByName( $name )
02918 {
02919 $nodeID = $this->attribute( 'node_id' );
02920
02921 $fromNode = $nodeID ;
02922
02923 $nodePath = $this->attribute( 'path_string' );
02924 $nodeDepth = $this->attribute( 'depth' );
02925
02926 $childrensPath = $nodePath ;
02927
02928 $db =& eZDB::instance();
02929 $pathString = " path_string like '$childrensPath%' and ";
02930 $depthCond = '';
02931 $nodeDepth = $this->Depth + 1;
02932 $depthCond = ' depth <= ' . $nodeDepth . ' and ';
02933
02934 $ini =& eZINI::instance();
02935 $db =& eZDB::instance();
02936
02937 $name = $db->escapeString( $name );
02938 $query = "SELECT ezcontentobject.*,
02939 ezcontentobject_tree.*,
02940 ezcontentclass.serialized_name_list as class_serialized_name_list,
02941 ezcontentclass.identifier as class_identifier,
02942 ezcontentclass.is_container as is_container
02943 FROM
02944 ezcontentobject_tree,
02945 ezcontentobject,ezcontentclass
02946 WHERE $pathString
02947 $depthCond
02948 ezcontentobject.name = '$name' AND
02949 ezcontentclass.version=0 AND
02950 node_id != $fromNode AND
02951 ezcontentobject_tree.contentobject_id = ezcontentobject.id AND
02952 ezcontentclass.id = ezcontentobject.contentclass_id";
02953
02954 $nodeListArray = $db->arrayQuery( $query );
02955
02956 $retNodeList = eZContentObjectTreeNode::makeObjectsArray( $nodeListArray );
02957
02958 return $retNodeList;
02959 }
02960
02961
02962
02963
02964 function &children()
02965 {
02966 $children =& $this->subTree( array( 'Depth' => 1,
02967 'DepthOperator' => 'eq',
02968 'SortBy' => $this->sortArray() ) );
02969 return $children;
02970 }
02971
02972
02973
02974
02975
02976
02977 function &childrenCount( $checkPolicies = true )
02978 {
02979 $params = array( 'Depth' => 1,
02980 'DepthOperator' => 'eq' );
02981 if ( !$checkPolicies )
02982 $params['Limitation'] = array();
02983 $subTreeCount = $this->subTreeCount( $params );
02984 return $subTreeCount;
02985 }
02986
02987
02988
02989
02990 function &viewCount()
02991 {
02992 include_once( 'kernel/classes/ezviewcounter.php' );
02993 $count = eZViewCounter::fetch( $this->attribute( 'node_id' ), false );
02994 $count = (int) $count['count'];
02995 return $count;
02996 }
02997
02998
02999
03000
03001
03002 function sortFieldName( $sortOrder )
03003 {
03004 switch ( $sortOrder )
03005 {
03006 default:
03007 eZDebug::writeWarning( 'Unknown sort order: ' . $sortOrder, 'eZContentObjectTreeNode::sortFieldName' );
03008 case 1:
03009 return 'path';
03010 case 2:
03011 return 'published';
03012 case 3:
03013 return 'modified';
03014 case 4:
03015 return 'section';
03016 case 5:
03017 return 'depth';
03018 case 6:
03019 return 'class_identifier';
03020 case 7:
03021 return 'class_name';
03022 case 8:
03023 return 'priority';
03024 case 9:
03025 return 'name';
03026 case 10:
03027 return 'modified_subnode';
03028 }
03029 }
03030
03031
03032
03033
03034
03035 function sortFieldID( $sortFieldName )
03036 {
03037 switch ( $sortFieldName )
03038 {
03039 default:
03040 eZDebug::writeWarning( 'Unknown sort order: ' . $sortFieldName, 'eZContentObjectTreeNode::sortFieldID()' );
03041 case 'path':
03042 return 1;
03043 case 'published':
03044 return 2;
03045 case 'modified':
03046 return 3;
03047 case 'section':
03048 return 4;
03049 case 'depth':
03050 return 5;
03051 case 'class_identifier':
03052 return 6;
03053 case 'class_name':
03054 return 7;
03055 case 'priority':
03056 return 8;
03057 case 'name':
03058 return 9;
03059 case 'modified_subnode':
03060 return 10;
03061 }
03062 }
03063
03064
03065
03066
03067
03068
03069 function &sortArray()
03070 {
03071 $retVal = eZContentObjectTreeNode::sortArrayBySortFieldAndSortOrder( $this->attribute( 'sort_field' ),
03072 $this->attribute( 'sort_order' ) );
03073 return $retVal;
03074 }
03075
03076
03077
03078
03079
03080
03081
03082 function sortArrayBySortFieldAndSortOrder( $sortField, $sortOrder )
03083 {
03084 return array( array( eZContentObjectTreeNode::sortFieldName( $sortField ),
03085 $sortOrder ) );
03086 }
03087
03088
03089
03090
03091
03092
03093
03094 function assignSectionToSubTree( $nodeID, $sectionID, $oldSectionID = false )
03095 {
03096 $db =& eZDB::instance();
03097
03098 $node = eZContentObjectTreeNode::fetch( $nodeID );
03099 $nodePath = $node->attribute( 'path_string' );
03100
03101 $sectionID =(int) $sectionID;
03102
03103 $pathString = " path_string like '$nodePath%' AND ";
03104
03105
03106 $objectIDArray = $db->arrayQuery( "SELECT
03107 ezcontentobject.id
03108 FROM
03109 ezcontentobject_tree, ezcontentobject
03110 WHERE
03111 $pathString
03112 ezcontentobject_tree.contentobject_id=ezcontentobject.id AND
03113 ezcontentobject_tree.main_node_id=ezcontentobject_tree.node_id" );
03114 if ( count( $objectIDArray ) == 0 )
03115 return;
03116
03117
03118 include_once( 'kernel/classes/ezsection.php' );
03119 $section = eZSection::fetch( $sectionID );
03120 $object = $node->object();
03121 include_once( "kernel/classes/ezaudit.php" );
03122 eZAudit::writeAudit( 'section-assign', array( 'Section ID' => $sectionID, 'Section name' => $section->attribute( 'name' ),
03123 'Node ID' => $nodeID,
03124 'Content object ID' => $object->attribute( 'id' ),
03125 'Content object name' => $object->attribute( 'name' ),
03126 'Comment' => 'Assigned a section to the current node and all child objects: eZContentObjectTreeNode::assignSectionToSubTree()' ) );
03127
03128 $objectSimpleIDArray = array();
03129 $inSQL = array();
03130 $inSQLs = array();
03131 $counter = 0;
03132 foreach ( $objectIDArray as $objectID )
03133 {
03134 $objectSimpleIDArray[] = $objectID['id'];
03135 if ( $counter < 99 )
03136 {
03137 $inSQL[] = $objectID['id'];
03138 ++$counter;
03139 }
03140 else
03141 {
03142 $inSQL[] = $objectID['id'];
03143 $counter = 0;
03144 $inSQLs[] = $inSQL;
03145 $inSQL = array();
03146 }
03147 }
03148 $inSQLs[] = $inSQL;
03149
03150 $filterPart = '';
03151 if ( $oldSectionID !== false )
03152 {
03153 $oldSectionID =(int) $oldSectionID;
03154 $filterPart = " section_id = '$oldSectionID' and ";
03155 }
03156
03157 $sets = count( $inSQLs );
03158
03159 $db->begin();
03160 for ( $i = 0; $i < $sets; ++$i )
03161 {
03162 $inPart = implode( ',', $inSQLs[$i] );
03163 $db->query( "UPDATE ezcontentobject SET section_id='$sectionID' WHERE $filterPart id IN ( $inPart )" );
03164 $db->query( "UPDATE ezsearch_object_word_link SET section_id='$sectionID' WHERE $filterPart contentobject_id IN ( $inPart )" );
03165 }
03166 $db->commit();
03167
03168
03169 eZContentObject::clearCache( $objectSimpleIDArray );
03170 }
03171
03172
03173
03174
03175
03176
03177
03178
03179
03180
03181
03182
03183
03184 function updateMainNodeID( $mainNodeID, $objectID, $version = false, $parentMainNodeID )
03185 {
03186 $mainNodeID = (int)$mainNodeID;
03187 $parentMainNodeID = (int)$parentMainNodeID;
03188 $objectID = (int)$objectID;
03189 $version = (int)$version;
03190
03191 $db =& eZDB::instance();
03192 $db->begin();
03193 $db->query( "UPDATE ezcontentobject_tree SET main_node_id=$mainNodeID WHERE contentobject_id=$objectID" );
03194 if ( !$version )
03195 {
03196 $rows = $db->arrayQuery( "SELECT current_version FROM ezcontentobject WHERE id=$objectID" );
03197 $version = $rows[0]['current_version'];
03198 }
03199 $db->query( "UPDATE eznode_assignment SET is_main=1 WHERE contentobject_id=$objectID AND contentobject_version=$version AND parent_node=$parentMainNodeID" );
03200 $db->query( "UPDATE eznode_assignment SET is_main=0 WHERE contentobject_id=$objectID AND contentobject_version=$version AND parent_node!=$parentMainNodeID" );
03201
03202 $contentObject = eZContentObject::fetch( $objectID );
03203 $parentContentObject = eZContentObject::fetchByNodeID( $parentMainNodeID );
03204 if ( $contentObject->attribute( 'section_id' ) != $parentContentObject->attribute( 'section_id' ) )
03205 {
03206 $newSectionID = $parentContentObject->attribute( 'section_id' );
03207 eZContentObjectTreeNode::assignSectionToSubTree( $mainNodeID, $newSectionID );
03208 }
03209
03210 $db->commit();
03211
03212 }
03213
03214 function &fetchByCRC( $pathStr )
03215 {
03216 eZDebug::writeWarning( "Obsolete: use ezurlalias instead", 'eZContentObjectTreeNode::fetchByCRC' );
03217 $retValue = null;
03218 return $retValue;
03219 }
03220
03221 function fetchByContentObjectID( $contentObjectID, $asObject = true, $contentObjectVersion = false )
03222 {
03223 $conds = array( 'contentobject_id' => $contentObjectID );
03224 if ( $contentObjectVersion !== false )
03225 {
03226 $conds['contentobject_version'] = $contentObjectVersion;
03227 }
03228 return eZPersistentObject::fetchObjectList( eZContentObjectTreeNode::definition(),
03229 null,
03230 $conds,
03231 null,
03232 null,
03233 $asObject );
03234 }
03235
03236 function fetchByRemoteID( $remoteID, $asObject = true )
03237 {
03238 return eZContentObjectTreeNode::fetch( false, false, $asObject, array( "remote_id" => $remoteID ) );
03239 }
03240
03241 function fetchByPath( $pathString, $asObject = true )
03242 {
03243 return eZContentObjectTreeNode::fetch( false, false, $asObject, array( "path_string" => $pathString ) );
03244 }
03245
03246 function fetchByURLPath( $pathString, $asObject = true )
03247 {
03248 if ( $pathString == "" )
03249 {
03250 eZDebug::writeWarning( 'Can not fetch, given URLPath is empty', 'eZContentObjectTreeNode::fetchByURLPath' );
03251 return null;
03252 }
03253
03254 return eZContentObjectTreeNode::fetch( false, false, $asObject, array( "path_identification_string" => $pathString ) );
03255 }
03256
03257 function fetchAliasesFromNodeList( $nodeList )
03258 {
03259 if ( !is_array( $nodeList ) || count( $nodeList ) < 1 )
03260 return array();
03261
03262 $db =& eZDB::instance();
03263 $nodeIDs = $db->implodeWithTypeCast( ', ', $nodeList, 'int' );
03264 $query = "SELECT path_identification_string FROM ezcontentobject_tree WHERE node_id IN ( $nodeIDs )";
03265 $pathListArray = $db->arrayQuery( $query );
03266 return $pathListArray;
03267 }
03268
03269 function &findMainNode( $objectID, $asObject = false )
03270 {
03271 $objectID=(int) $objectID;
03272 $query="SELECT ezcontentobject.*,
03273 ezcontentobject_tree.*,
03274 ezcontentclass.serialized_name_list as class_serialized_name_list,
03275 ezcontentclass.identifier as class_identifier,
03276 ezcontentclass.is_container as is_container
03277 FROM ezcontentobject_tree,
03278 ezcontentobject,
03279 ezcontentclass
03280 WHERE ezcontentobject_tree.contentobject_id=$objectID AND
03281 ezcontentobject_tree.main_node_id = ezcontentobject_tree.node_id AND
03282 ezcontentobject_tree.contentobject_id=ezcontentobject.id AND
03283 ezcontentclass.version=0 AND
03284 ezcontentclass.id = ezcontentobject.contentclass_id";
03285 $db =& eZDB::instance();
03286 $nodeListArray = $db->arrayQuery( $query );
03287 if ( count( $nodeListArray ) > 1 )
03288 {
03289 eZDebug::writeError( $nodeListArray , "There are more then one main_node for objectID: $objectID" );
03290 }
03291 else
03292 {
03293 if ( $asObject )
03294 {
03295 $retNodeArray = eZContentObjectTreeNode::makeObjectsArray( $nodeListArray );
03296 $returnValue =& $retNodeArray[0];
03297 return $returnValue;
03298 }else
03299 {
03300 $retNodeArray =& $nodeListArray;
03301 return $retNodeArray[0]['node_id'];
03302 }
03303
03304 }
03305 $retVal = null;
03306 return $retVal;
03307 }
03308
03309
03310
03311
03312 function &findMainNodeArray( $objectIDArray, $asObject = true )
03313 {
03314 if ( count( $objectIDArray ) )
03315 {
03316 $db =& eZDB::instance();
03317 $objectIDString = $db->implodeWithTypeCast( ',', $objectIDArray, 'int' );
03318 $query="SELECT ezcontentobject.*,
03319 ezcontentobject_tree.*,
03320 ezcontentclass.serialized_name_list as class_serialized_name_list,
03321 ezcontentclass.identifier as class_identifier,
03322 ezcontentclass.is_container as is_container
03323 FROM ezcontentobject_tree,
03324 ezcontentobject,
03325 ezcontentclass
03326 WHERE ezcontentobject_tree.contentobject_id in ( $objectIDString ) AND
03327 ezcontentobject_tree.main_node_id = ezcontentobject_tree.node_id AND
03328 ezcontentobject_tree.contentobject_id=ezcontentobject.id AND
03329 ezcontentclass.version=0 AND
03330 ezcontentclass.id = ezcontentobject.contentclass_id";
03331
03332 $nodeListArray = $db->arrayQuery( $query );
03333 if ( $asObject )
03334 {
03335 $retNodeArray = eZContentObjectTreeNode::makeObjectsArray( $nodeListArray );
03336 return $retNodeArray;
03337 }
03338 else
03339 {
03340 return $nodeListArray;
03341 }
03342 }
03343 $retValue = null;
03344 return $retValue;
03345 }
03346
03347
03348
03349
03350
03351
03352 function fetch( $nodeID = false, $lang = false, $asObject = true, $conditions = false )
03353 {
03354 $returnValue = null;
03355 $db = eZDB::instance();
03356 if ( ( is_numeric( $nodeID ) && $nodeID == 1 ) ||
03357 ( is_array( $nodeID ) && count( $nodeID ) === 1 && $nodeID[0] == 1 ) )
03358 {
03359 $query = "SELECT *
03360 FROM ezcontentobject_tree
03361 WHERE node_id = 1";
03362 }
03363 else
03364 {
03365 $versionNameTables = ', ezcontentobject_name ';
03366 $versionNameTargets = ', ezcontentobject_name.name as name, ezcontentobject_name.real_translation ';
03367 $versionNameJoins = " and ezcontentobject_tree.contentobject_id = ezcontentobject_name.contentobject_id and
03368 ezcontentobject_tree.contentobject_version = ezcontentobject_name.content_version and ";
03369 if ( $lang )
03370 {
03371 $lang = $db->escapeString( $lang );
03372 $versionNameJoins .= " ezcontentobject_name.content_translation = '$lang' ";
03373 }
03374 else
03375 {
03376 $versionNameJoins .= eZContentLanguage::sqlFilter( 'ezcontentobject_name', 'ezcontentobject' );
03377 }
03378
03379 $languageFilter = ' AND '.eZContentLanguage::languagesSQLFilter( 'ezcontentobject' );
03380
03381 $sqlCondition = '';
03382
03383 if ( $nodeID !== false )
03384 {
03385 if ( is_array( $nodeID ) )
03386 {
03387 if( count( $nodeID ) === 1 )
03388 {
03389 $sqlCondition = 'node_id = ' . (int) $nodeID[0] . ' AND';
03390 }
03391 else
03392 {
03393
03394 $impStr = $db->implodeWithTypeCast( ',', $nodeID, 'int' );
03395 $sqlCondition = 'node_id IN ( ' . $impStr . ' ) AND';
03396 }
03397 }
03398 else
03399 {
03400 $sqlCondition = 'node_id = ' . (int) $nodeID . ' AND';
03401 }
03402 }
03403
03404 if ( is_array( $conditions ) )
03405 {
03406 foreach( $conditions as $key => $condition )
03407 {
03408 if ( is_string( $condition ) )
03409 {
03410 $condition = $db->escapeString( $condition );
03411 $condition = "'$condition'";
03412 }
03413
03414 $sqlCondition .= "ezcontentobject_tree." . $db->escapeString( $key ) . "=$condition AND ";
03415 }
03416 }
03417
03418 if ( $sqlCondition == '' )
03419 {
03420 eZDebug::writeWarning( 'Cannot fetch node, emtpy ID or no conditions given', 'eZContentObjectTreeNode::fetch' );
03421 return $returnValue;
03422 }
03423
03424 $query="SELECT ezcontentobject.*,
03425 ezcontentobject_tree.*,
03426 ezcontentclass.serialized_name_list as class_serialized_name_list,
03427 ezcontentclass.identifier as class_identifier,
03428 ezcontentclass.is_container as is_container
03429 $versionNameTargets
03430 FROM ezcontentobject_tree,
03431 ezcontentobject,
03432 ezcontentclass
03433 $versionNameTables
03434 WHERE $sqlCondition
03435 ezcontentobject_tree.contentobject_id=ezcontentobject.id AND
03436 ezcontentclass.version=0 AND
03437 ezcontentclass.id = ezcontentobject.contentclass_id
03438 $languageFilter
03439 $versionNameJoins";
03440 }
03441
03442 $nodeListArray = $db->arrayQuery( $query );
03443
03444 if ( count( $nodeListArray ) > 0 )
03445 {
03446 if ( $asObject )
03447 {
03448 $returnValue = eZContentObjectTreeNode::makeObjectsArray( $nodeListArray );
03449 if ( count( $returnValue ) === 1 )
03450 $returnValue = $returnValue[0];
03451 }
03452 else
03453 {
03454 if ( count( $nodeListArray ) === 1 )
03455 $returnValue = $nodeListArray[0];
03456 else
03457 $returnValue = $nodeListArray;
03458 }
03459 }
03460
03461 return $returnValue;
03462 }
03463
03464
03465
03466
03467
03468
03469 function fetchNode( $contentObjectID, $parentNodeID )
03470 {
03471 $returnValue = null;
03472 $ini =& eZINI::instance();
03473 $db =& eZDB::instance();
03474 $contentObjectID =(int) $contentObjectID;
03475 $parentNodeID =(int) $parentNodeID;
03476 $query = "SELECT ezcontentobject_tree.*
03477 FROM ezcontentobject_tree, ezcontentobject
03478 WHERE ezcontentobject_tree.contentobject_id = '$contentObjectID' AND
03479 ezcontentobject.id = '$contentObjectID' AND
03480 ezcontentobject_tree.contentobject_is_published = 1 AND
03481 ezcontentobject_tree.parent_node_id = '$parentNodeID' AND ".
03482 eZContentLanguage::languagesSQLFilter( 'ezcontentobject' );
03483
03484 $nodeListArray = $db->arrayQuery( $query );
03485 if ( count( $nodeListArray ) == 1 )
03486 {
03487 $retNodeArray = eZContentObjectTreeNode::makeObjectsArray( $nodeListArray, false );
03488 $returnValue = $retNodeArray[0];
03489 }
03490 return $returnValue;
03491 }
03492
03493
03494
03495
03496
03497 function &fetchParent()
03498 {
03499 $parent = $this->fetch( $this->attribute( 'parent_node_id' ) );
03500 return $parent;
03501 }
03502
03503
03504
03505
03506
03507 function &pathArray()
03508 {
03509 $pathString = $this->attribute( 'path_string' );
03510 $pathItems = explode( '/', $pathString );
03511 $pathArray = array();
03512 foreach ( $pathItems as $pathItem )
03513 {
03514 if ( $pathItem != '' )
03515 $pathArray[] = (int) $pathItem;
03516 }
03517 return $pathArray;
03518 }
03519
03520
03521 function &fetchPath()
03522 {
03523 $nodePath = $this->attribute( 'path_string' );
03524
03525 $retNodes = eZContentObjectTreeNode::fetchNodesByPathString( $nodePath, false, true );
03526
03527 return $retNodes;
03528 }
03529
03530
03531
03532
03533
03534
03535
03536
03537
03538 function fetchNodesByPathString( $nodePath, $withLastNode = false, $asObjects = true, $limit = false )
03539 {
03540 $nodesListArray = array();
03541 $pathString = eZContentObjectTreeNode::createNodesConditionSQLStringFromPath( $nodePath, $withLastNode, $limit );
03542
03543 if ( $pathString )
03544 {
03545 $useVersionName = true;
03546 $versionNameTables = eZContentObjectTreeNode::createVersionNameTablesSQLString ( $useVersionName );
03547 $versionNameTargets = eZContentObjectTreeNode::createVersionNameTargetsSQLString( $useVersionName );
03548 $versionNameJoins = eZContentObjectTreeNode::createVersionNameJoinsSQLString ( $useVersionName );
03549
03550 $query = "SELECT ezcontentobject.*,
03551 ezcontentobject_tree.*,
03552 ezcontentclass.serialized_name_list as class_serialized_name_list,
03553 ezcontentclass.identifier as class_identifier
03554 $versionNameTargets
03555 FROM ezcontentobject_tree,
03556 ezcontentobject,
03557 ezcontentclass
03558 $versionNameTables
03559 WHERE $pathString
03560 ezcontentobject_tree.contentobject_id=ezcontentobject.id AND
03561 ezcontentclass.version=0 AND
03562 ezcontentclass.id = ezcontentobject.contentclass_id
03563 $versionNameJoins
03564 ORDER BY path_string";
03565
03566 $db =& eZDB::instance();
03567 $nodesListArray = $db->arrayQuery( $query );
03568 }
03569
03570 if ( $asObjects )
03571 $retNodes = eZContentObjectTreeNode::makeObjectsArray( $nodesListArray );
03572 else
03573 $retNodes =& $nodesListArray;
03574
03575 return $retNodes;
03576 }
03577
03578
03579
03580
03581
03582
03583
03584
03585
03586
03587
03588
03589
03590
03591
03592
03593
03594 function &fetchClassIdentifierListByPathString( $nodePath, $withLastNode, $limit = false )
03595 {
03596 $itemList = array();
03597 $nodes = eZContentObjectTreeNode::fetchNodesByPathString( $nodePath, $withLastNode, false, $limit );
03598
03599 foreach ( array_keys( $nodes ) as $nodeKey )
03600 {
03601 $node =& $nodes[$nodeKey];
03602 $itemList[] = array( 'node_id' => $node['node_id'],
03603 'class_identifier' => $node['class_identifier'] );
03604 }
03605
03606 return $itemList;
03607 }
03608
03609
03610
03611
03612 function createObject( $contentClassID, $parentNodeID = 2 )
03613 {
03614 $user =& eZUser::currentUser();
03615 $userID =& $user->attribute( 'contentobject_id' );
03616
03617 $class = eZContentClass::fetch( $contentClassID );
03618 $parentNode = eZContentObjectTreeNode::fetch( $parentNodeID );
03619 $parentContentObject =& $parentNode->attribute( 'object' );
03620 $sectionID = $parentContentObject->attribute( 'section_id' );
03621 $object = $class->instantiate( $userID, $sectionID );
03622
03623
03624
03625 $node =& eZContentObjectTreeNode::addChild( $object->attribute( "id" ), $parentNodeID, true );
03626
03627 $node->setAttribute( 'main_node_id', $node->attribute( 'node_id' ) );
03628 $object->store();
03629 $node->store();
03630
03631 return $object;
03632 }
03633
03634
03635
03636
03637
03638
03639
03640
03641
03642
03643
03644 function &addChild( $contentobjectID, $nodeID = 0, $asObject = false, $contentObjectVersion = false )
03645 {
03646 if ( $nodeID == 0 )
03647 {
03648 $node = $this;
03649 }
03650 else
03651 {
03652 $node = eZContentObjectTreeNode::fetch( $nodeID );
03653 }
03654
03655 $contentObject =& eZContentObject::fetch( $contentobjectID );
03656 if ( !$contentObject )
03657 {
03658 return false;
03659 }
03660
03661 if ( !$contentObjectVersion )
03662 {
03663 $contentObjectVersion = $contentObject->attribute( 'current_version' );
03664 }
03665
03666 $db =& eZDB::instance();
03667 $parentMainNodeID = $node->attribute( 'node_id' );
03668 $parentPath = $node->attribute( 'path_string' );
03669 $parentDepth = $node->attribute( 'depth' );
03670 $isInvinsible = $node->attribute( 'is_invisible' );
03671
03672 $nodeDepth = $parentDepth + 1 ;
03673
03674 $insertedNode = eZContentObjectTreeNode::create( $parentMainNodeID, $contentobjectID );
03675
03676
03677 $contentClass = $contentObject->attribute( 'content_class' );
03678 $insertedNode->setAttribute( 'sort_field', $contentClass->attribute( 'sort_field' ) );
03679 $insertedNode->setAttribute( 'sort_order', $contentClass->attribute( 'sort_order' ) );
03680
03681 $insertedNode->setAttribute( 'depth', $nodeDepth );
03682 $insertedNode->setAttribute( 'path_string', '/TEMPPATH' );
03683
03684 $insertedNode->setAttribute( 'contentobject_version', $contentObjectVersion );
03685
03686
03687 $insertedNode->setAttribute( 'is_invisible', $isInvinsible );
03688
03689 $db->begin();
03690 $insertedNode->store();
03691 $insertedID = $insertedNode->attribute( 'node_id' );
03692 $newNodePath = $parentPath . $insertedID . '/';
03693 $insertedNode->setAttribute( 'path_string', $newNodePath );
03694 $insertedNode->store();
03695 $db->commit();
03696
03697 if ( $asObject )
03698 {
03699 return $insertedNode;
03700 }
03701 else
03702 {
03703 return $insertedID;
03704 }
03705 }
03706
03707
03708
03709
03710 function pathWithNames( $nodeID = 0 )
03711 {
03712 if ( $nodeID == 0 )
03713 {
03714 $node =& $this;
03715 }
03716 else
03717 {
03718 $node = eZContentObjectTreeNode::fetch( $nodeID );
03719 }
03720
03721 $nodeList =& $node->attribute( 'path' );
03722 if ( $node->attribute( 'depth' ) > 1 )
03723 {
03724 $parentNodeID = $node->attribute( 'parent_node_id' );
03725 $parentNode = eZContentObjectTreeNode::fetch( $parentNodeID, false, false );
03726 if ( ! is_null( $parentNode ) )
03727 {
03728 $parentNodePathString = $parentNode['path_identification_string'];
03729 }
03730 else
03731 {
03732 eZDebug::writeError( 'Parent node was null.', 'eZContentObjectTreeNode::pathWithNames()' );
03733 }
03734 }
03735 else
03736 {
03737 $parentNodePathString = '';
03738 }
03739
03740 if ( count( $nodeList ) > 0 )
03741 {
03742 $topLevelNode = $nodeList[0];
03743 $topLevelName = $topLevelNode->getName();
03744 $topLevelName = eZURLAlias::convertToAlias( $topLevelName, 'node_' . $topLevelNode->attribute( 'node_id' ) );
03745
03746 $pathElementArray = explode( '/', $parentNodePathString );
03747 if ( count( $pathElementArray ) > 0 )
03748 {
03749 $parentNodePathString = implode( '/', $pathElementArray );
03750 }
03751 else
03752 {
03753 $parentNodePathString = '';
03754 }
03755 }
03756 else
03757 {
03758 $parentNodePathString = '';
03759 }
03760
03761
03762 $ini =& eZINI::instance( 'content.ini' );
03763 $contentRootID = $ini->variable( 'NodeSettings', 'RootNode' );
03764 if ( $node->attribute( 'node_id' ) != $contentRootID )
03765 {
03766 $nodeName = $node->attribute( 'name' );
03767 $nodeName = eZURLAlias::convertToAlias( $nodeName, 'node_' . $node->attribute( 'node_id' ) );
03768
03769 if ( $parentNodePathString != '' )
03770 {
03771 $nodePath = $parentNodePathString . '/' . $nodeName ;
03772 }
03773 else
03774 {
03775 $nodePath = $nodeName ;
03776 }
03777 }
03778 else
03779 {
03780 $nodePath = '';
03781 }
03782 $nodePath = $node->checkPath( $nodePath );
03783 return $nodePath;
03784 }
03785
03786
03787
03788
03789 function checkPath( $path )
03790 {
03791 $moduleINI =& eZINI::instance( 'module.ini' );
03792 $reserved = $moduleINI->variable( 'ModuleSettings', 'ModuleList' );
03793 $reservedReg = implode( '|', $reserved );
03794 $uniqueNumber = 0;
03795 if ( preg_match( "#^($reservedReg)$#", $path ) )
03796 {
03797 ++$uniqueNumber;
03798 }
03799
03800 $nodeID = $this->attribute( 'node_id' );
03801 $parentNodeID = $this->attribute( 'parent_node_id' );
03802 $depth = $this->attribute( 'depth' );
03803 $db =& eZDB::instance();
03804
03805
03806 $pathLikeCheck = 'path_identification_string LIKE \'' . $path . '\\_\\_%\' ESCAPE \'' . $db->escapeString( '\\' ) . '\'';
03807
03808
03809
03810
03811 $sql = 'SELECT path_identification_string
03812 FROM ezcontentobject_tree
03813 WHERE ( path_identification_string = \'' . $path . '\' OR ' . $pathLikeCheck . ' ) AND node_id = ' . $nodeID;
03814 $rows = $db->arrayQuery( $sql );
03815 foreach ( $rows as $idx => $row ) // exclude rows that do not match the pattern
03816 {
03817 if ( !preg_match( "#^$path(__\d+)?$#", $row['path_identification_string'] ) )
03818 unset( $rows[$idx] );
03819 }
03820 if ( count( $rows ) > 0 )
03821 return $rows[0]['path_identification_string'];
03822 unset( $rows );
03823
03824 // If the path matches a module ($uniqueNumber > 0 ) we should not check for existing path
03825 if ( $uniqueNumber == 0 )
03826 {
03827 /* Else if there are no other nodes having path equal to $path
03828 * then return $path.
03829 */
03830 $sql = 'SELECT COUNT(*) AS cnt
03831 FROM ezcontentobject_tree
03832 WHERE path_identification_string = \'' . $path . '\' AND node_id <> ' . $nodeID;
03833 $rows = $db->arrayQuery( $sql );
03834 if ( $rows[0]['cnt'] == 0 )
03835 return $path;
03836 unset( $rows );
03837 }
03838
03839 /* Else if there are other nodes having path like "<$path>__<number>"
03840 * then return computed unique path.
03841 */
03842 if ( $depth == 2 ) // in this case we should take into account toplevels that may have path equal to one we're checking
03843 $depthCheck = ' depth IN ( 1, 2 )';
03844 else
03845 $depthCheck = 'depth = ' . $depth . ' AND parent_node_id = ' . $parentNodeID;
03846 $sql = 'SELECT path_identification_string
03847 FROM ezcontentobject_tree
03848 WHERE ' . $depthCheck . ' AND ' . $pathLikeCheck . ' AND node_id <> ' . $nodeID;
03849 $rows = $db->arrayQuery( $sql );
03850 foreach ( $rows as $row )
03851 {
03852 $pathString =& $row['path_identification_string'];
03853 if ( !preg_match( "#^${path}__(\d+)$#", $pathString, $matches ) )
03854 continue;
03855 if ( $matches[1] >= $uniqueNumber )
03856 $uniqueNumber = $matches[1] + 1;
03857 }
03858
03859 if ( $uniqueNumber == 0 )
03860 $uniqueNumber = 1;
03861 return $path . '__' . $uniqueNumber;
03862 }
03863
03864
03865
03866
03867
03868 function updateURLAlias()
03869 {
03870 $hasChanged = 0;
03871 include_once( 'kernel/classes/ezurlalias.php' );
03872 $newPathString = $this->pathWithNames();
03873
03874 $existingUrlAlias = eZURLAlias::fetchBySourceURL( $newPathString );
03875
03876 $db =& eZDB::instance();
03877 $db->begin();
03878 if ( get_class( $existingUrlAlias ) == 'ezurlalias' )
03879 {
03880 $alias =& $existingUrlAlias;
03881 if ( $alias->attribute( 'source_url' ) != $newPathString )
03882 $hasChanged++;
03883 $alias->setAttribute( 'source_url', $newPathString );
03884 $alias->setAttribute( 'destination_url', 'content/view/full/' . $this->NodeID );
03885 $alias->setAttribute( 'forward_to_id', 0 );
03886 $alias->store();
03887 }
03888 else
03889 {
03890 $alias = eZURLAlias::create( $newPathString, 'content/view/full/' . $this->NodeID );
03891 $alias->store();
03892 $hasChanged++;
03893 }
03894
03895 eZURLAlias::cleanupForwardingURLs( $newPathString );
03896 eZURLAlias::cleanupWildcards( $newPathString );
03897
03898 $oldPathString = $this->attribute( 'path_identification_string' );
03899
03900
03901 if ( strcmp( $oldPathString, $newPathString ) != 0 )
03902 {
03903 $oldUrlAlias = false;
03904
03905 if ( $oldPathString != "" )
03906 {
03907 $oldUrlAlias = eZURLAlias::fetchBySourceURL( $oldPathString );
03908 }
03909
03910
03911 if ( get_class( $oldUrlAlias ) == 'ezurlalias' )
03912 {
03913 $oldUrlAlias->setAttribute( 'forward_to_id', $alias->attribute( 'id' ) );
03914 $oldUrlAlias->setAttribute( 'destination_url', 'content/view/full/' . $this->NodeID );
03915 $oldUrlAlias->store();
03916 eZURLAlias::updateForwardID( $alias->attribute( 'id' ), $oldUrlAlias->attribute( 'id' ) );
03917 }
03918 }
03919
03920 if ( $this->attribute( 'path_identification_string' ) != $newPathString )
03921 $hasChanged++;
03922 $this->setAttribute( 'path_identification_string', $newPathString );
03923 $this->store();
03924 $db->commit();
03925
03926 return $hasChanged;
03927 }
03928
03929
03930
03931
03932
03933 function updateSubTreePath()
03934 {
03935 include_once( 'kernel/classes/ezurlalias.php' );
03936 include_once( 'kernel/classes/datatypes/ezurl/ezurl.php' );
03937 $oldPathString = $this->attribute( 'path_identification_string' );
03938
03939 $newPathString = $this->pathWithNames();
03940
03941
03942 if ( $oldPathString == $newPathString )
03943 return;
03944
03945 $oldUrlAlias = false;
03946
03947 if ( $oldPathString != "" )
03948 {
03949 $oldUrlAlias = eZURLAlias::fetchBySourceURL( $oldPathString );
03950 }
03951
03952
03953 $existingUrlAlias = eZURLAlias::fetchBySourceURL( $newPathString );
03954
03955 $db =& eZDB::instance();
03956 $db->begin();
03957
03958
03959 $oldPathStringLength = strlen( $oldPathString );
03960 $newPathStringText = $db->escapeString( $newPathString );
03961 $oldPathStringText = $db->escapeString( $oldPathString );
03962 $subStringQueryPart = $db->subString( 'path_identification_string', $oldPathStringLength + 1 );
03963 $newPathStringQueryPart = $db->concatString( array( "'$newPathStringText'", $subStringQueryPart ) );
03964 $sql = "UPDATE ezcontentobject_tree SET path_identification_string = $newPathStringQueryPart " .
03965 "WHERE path_identification_string LIKE '$oldPathStringText/%'";
03966 $db->query( $sql );
03967
03968 if ( get_class( $existingUrlAlias ) == 'ezurlalias' )
03969 {
03970 $alias =& $existingUrlAlias;
03971 $alias->setAttribute( 'source_url', $newPathString );
03972 $alias->setAttribute( 'destination_url', 'content/view/full/' . $this->NodeID );
03973 $alias->setAttribute( 'forward_to_id', 0 );
03974 $alias->store();
03975 }
03976 else
03977 {
03978 $alias = eZURLAlias::create( $newPathString, 'content/view/full/' . $this->NodeID );
03979 $alias->store();
03980 }
03981
03982 eZURLAlias::cleanupForwardingURLs( $newPathString );
03983 eZURLAlias::cleanupWildcards( $newPathString );
03984
03985 $subNodeCount = $this->subTreeCount( array( 'Limitation' => array() ) );
03986 if ( $subNodeCount > 0 )
03987 {
03988 $wildcardAlias = eZURLAlias::create( $oldPathString . '/*', $newPathString . '/{1}', true, false, EZ_URLALIAS_WILDCARD_TYPE_FORWARD );
03989 $wildcardAlias->store();
03990 }
03991
03992
03993 if ( get_class( $oldUrlAlias ) == 'ezurlalias' )
03994 {
03995 $oldUrlAlias->setAttribute( 'forward_to_id', $alias->attribute( 'id' ) );
03996 $oldUrlAlias->setAttribute( 'destination_url', 'content/view/full/' . $this->NodeID );
03997 $oldUrlAlias->store();
03998 eZURLAlias::updateForwardID( $alias->attribute( 'id' ), $oldUrlAlias->attribute( 'id' ) );
03999 }
04000
04001
04002 if ( include_once( 'kernel/classes/datatypes/ezurl/ezurltype.php' ) )
04003 $url = eZURL::urlByURL( "/" . $oldPathString );
04004
04005 if ( $url && $oldPathString != "")
04006 {
04007 $url->setAttribute( 'url', '/' . $newPathString );
04008 $url->store();
04009 }
04010
04011 eZDebugSetting::writeDebug( 'kernel-content-treenode', $oldPathString .' ' . strlen( $oldPathString ) . ' ' . $newPathString );
04012 $this->setAttribute( 'path_identification_string', $newPathString );
04013 $this->store();
04014
04015
04016
04017
04018
04019 if ( $oldPathString != "" )
04020 eZURLAlias::updateChildAliases( $newPathString, $oldPathString );
04021
04022 eZURLAlias::expireWildcards();
04023 $db->commit();
04024 }
04025
04026
04027
04028
04029
04030
04031
04032 function remove( $nodeID = 0 )
04033 {
04034 include_once( "kernel/classes/ezrole.php" );
04035 include_once( "kernel/classes/ezpolicy.php" );
04036 include_once( "kernel/classes/ezpolicylimitation.php" );
04037
04038 $ini =& eZINI::instance();
04039
04040 if ( $nodeID == 0 )
04041 {
04042 $node =& $this;
04043 }
04044 else
04045 {
04046 $node = eZContentObjectTreeNode::fetch( $nodeID );
04047 }
04048
04049 if ( !is_object( $node ) )
04050 {
04051 return;
04052 }
04053
04054 include_once( "kernel/classes/ezaudit.php" );
04055 if ( eZAudit::isAuditEnabled() )
04056 {
04057
04058 $nodeIDAudit = $node->attribute( 'node_id' );
04059 $object = $node->object();
04060 $objectID = $object->attribute( 'id' );
04061 $objectName = $object->attribute( 'name' );
04062
04063 eZAudit::writeAudit( 'content-delete', array( 'Node ID' => $nodeIDAudit, 'Object ID' => $objectID, 'Content Name' => $objectName,
04064 'Comment' => 'Removed the current node: eZContentObjectTreeNode::remove()' ) );
04065 }
04066
04067 $db =& eZDB::instance();
04068 $db->begin();
04069
04070 $nodePath = $node->attribute( 'path_string' );
04071 $childrensPath = $nodePath ;
04072
04073 $pathString = " path_string like '$childrensPath%' ";
04074
04075 $urlAlias = $node->attribute( 'url_alias' );
04076
04077
04078 if ( $ini->variable( 'ContentSettings', 'StaticCache' ) == 'enabled' )
04079 {
04080 include_once( 'kernel/classes/ezstaticcache.php' );
04081 $staticCache = new eZStaticCache();
04082 $staticCache->removeURL( "/" . $urlAlias );
04083 $staticCache->generateAlwaysUpdatedCache();
04084
04085 $parent = $node->fetchParent();
04086 }
04087
04088 $db->query( "DELETE FROM ezcontentobject_tree
04089 WHERE $pathString OR
04090 path_string = '$nodePath'" );
04091
04092
04093 if ( $ini->variable( 'ContentSettings', 'StaticCache' ) == 'enabled' )
04094 {
04095 if ( $parent )
04096 {
04097 $staticCache->cacheURL( "/" . $parent->urlAlias() );
04098 }
04099 }
04100
04101
04102 $urlObject = eZURLAlias::fetchBySourceURL( $urlAlias );
04103 if ( $urlObject )
04104 {
04105 $urlObject->cleanup();
04106 }
04107
04108
04109 include_once( 'kernel/classes/ezcontentcachemanager.php' );
04110 eZContentCacheManager::clearContentCacheIfNeeded( $node->attribute( 'contentobject_id' ) );
04111
04112 $parentNode =& $node->attribute( 'parent' );
04113 if ( is_object( $parentNode ) )
04114 {
04115 eZContentCacheManager::clearContentCacheIfNeeded( $parentNode->attribute( 'contentobject_id' ) );
04116 $parentNode->updateAndStoreModified();
04117 }
04118
04119
04120 eZRole::cleanupByNode( $node );
04121
04122
04123 $nodeID = $node->attribute( 'node_id' );
04124 include_once( 'kernel/classes/ezcontentbrowserecent.php' );
04125 eZContentBrowseRecent::removeRecentByNodeID( $nodeID );
04126
04127
04128 include_once( 'kernel/classes/ezcontentbrowsebookmark.php' );
04129 eZContentBrowseBookmark::removeByNodeID( $nodeID );
04130
04131
04132 include_once( 'kernel/classes/eztipafriendcounter.php' );
04133 eZTipafriendCounter::removeForNode( $nodeID );
04134
04135
04136 include_once( 'kernel/classes/ezviewcounter.php' );
04137 eZViewCounter::remove( $nodeID );
04138
04139 $db->commit();
04140 }
04141
04142
04143
04144
04145
04146
04147
04148
04149
04150
04151
04152
04153
04154
04155
04156
04157
04158
04159
04160
04161
04162
04163
04164
04165
04166 function subtreeRemovalInformation( $deleteIDArray )
04167 {
04168 return eZContentObjectTreeNode::removeSubtrees( $deleteIDArray, true, true );
04169 }
04170
04171
04172
04173
04174
04175
04176
04177
04178
04179
04180
04181
04182
04183
04184
04185
04186
04187 function removeSubtrees( $deleteIDArray, $moveToTrash = true, $infoOnly = false )
04188 {
04189 if ( !$infoOnly )
04190 {
04191 include_once( "kernel/classes/ezcontentcachemanager.php" );
04192 }
04193
04194 $moveToTrashAllowed = true;
04195 $deleteResult = array();
04196 $totalChildCount = 0;
04197 $totalLoneNodeCount = 0;
04198 $canRemoveAll = true;
04199
04200 $db =& eZDB::instance();
04201 $db->begin();
04202 foreach ( $deleteIDArray as $deleteID )
04203 {
04204 $node = eZContentObjectTreeNode::fetch( $deleteID );
04205 if ( $node === null )
04206 continue;
04207
04208 $object = $node->attribute( 'object' );
04209 if ( $object === null )
04210 continue;
04211
04212 $class = $object->attribute( 'content_class' );
04213 $canRemove = $object->attribute( 'can_remove' );
04214 $canRemoveSubtree = true;
04215
04216 $nodeID = $node->attribute( 'node_id' );
04217 $nodeName = $object->attribute( 'name' );
04218
04219 $childCount = 0;
04220 $newMainNodeID = false;
04221 $objectNodeCount = 0;
04222 $readableChildCount = 0;
04223
04224 if ( $canRemove )
04225 {
04226 $isUserClass = false;
04227
04228 $attributes = eZContentClass::fetchAttributes( $class->attribute( 'id' ) );
04229 foreach ( $attributes as $attribute )
04230 {
04231 if ( $attribute->attribute( 'data_type_string' ) == 'ezuser' )
04232 {
04233 $isUserClass = true;
04234 break;
04235 }
04236 }
04237
04238 if ( $moveToTrashAllowed and $isUserClass )
04239 {
04240 $moveToTrashAllowed = false;
04241 }
04242 $readableChildCount = $node->subTreeCount( array( 'Limitation' => array() ) );
04243 $childCount = $node->subTreeCount();
04244 $totalChildCount += $childCount;
04245
04246 $allAssignedNodes =& $object->attribute( 'assigned_nodes' );
04247 $objectNodeCount = count( $allAssignedNodes );
04248
04249
04250 if ( $node->attribute( 'main_node_id' ) == $nodeID )
04251 {
04252 if ( count( $allAssignedNodes ) > 1 )
04253 {
04254 foreach( $allAssignedNodes as $assignedNode )
04255 {
04256 $assignedNodeID = $assignedNode->attribute( 'node_id' );
04257 if ( $assignedNodeID == $nodeID )
04258 continue;
04259 $newMainNodeID = $assignedNodeID;
04260 break;
04261 }
04262 }
04263 }
04264
04265 if ( $infoOnly )
04266 {
04267
04268
04269
04270
04271 include_once( "kernel/classes/datatypes/ezuser/ezuser.php" );
04272 $currentUser =& eZUser::currentUser();
04273 $accessResult = $currentUser->hasAccessTo( 'content', 'remove' );
04274 if ( $accessResult['accessWord'] == 'limited' )
04275 {
04276 $limitationList =& $accessResult['policies'];
04277 $removeableChildCount = $node->subTreeCount( array( 'Limitation' => $limitationList ) );
04278 $canRemoveSubtree = ( $removeableChildCount == $childCount );
04279 $canRemove = $canRemoveSubtree;
04280 }
04281 }
04282
04283
04284
04285 if ( $canRemove and !$infoOnly )
04286 {
04287 $moveToTrashTemp = $moveToTrash;
04288 if ( !$moveToTrashAllowed )
04289 $moveToTrashTemp = false;
04290
04291 eZContentCacheManager::clearContentCacheIfNeeded( $node->attribute( 'contentobject_id' ) );
04292
04293
04294 while ( 1 )
04295 {
04296
04297
04298 $children =& $node->subTree( array( 'Limitation' => array(),
04299 'SortBy' => array( 'path' , false ),
04300 'Limit' => 100 ) );
04301 if ( !$children )
04302 break;
04303
04304 foreach ( array_keys( $children ) as $childKey )
04305 {
04306 $child =& $children[$childKey];
04307 $child->removeNodeFromTree( $moveToTrashTemp );
04308 eZContentObject::clearCache();
04309 }
04310 }
04311
04312 $node->removeNodeFromTree( $moveToTrashTemp );
04313 }
04314 }
04315 if ( !$canRemove )
04316 $canRemoveAll = false;
04317
04318
04319 if ( !$infoOnly )
04320 continue;
04321
04322 $soleNodeCount = $node->subtreeSoleNodeCount();
04323 $totalLoneNodeCount += $soleNodeCount;
04324 if ( $objectNodeCount <= 1 )
04325 ++$totalLoneNodeCount;
04326
04327 $item = array( "nodeName" => $nodeName,
04328 "childCount" => $childCount,
04329 "additionalWarning" => '',
04330 'node' => $node,
04331 'object' => $object,
04332 'class' => $class,
04333 'node_name' => $nodeName,
04334 'child_count' => $childCount,
04335 'object_node_count' => $objectNodeCount,
04336 'sole_node_count' => $soleNodeCount,
04337 'can_remove' => $canRemove,
04338 'can_remove_subtree' => $canRemoveSubtree,
04339 'real_child_count' => $readableChildCount,
04340 'new_main_node_id' => $newMainNodeID );
04341 $deleteResult[] = $item;
04342 }
04343 $db->commit();
04344
04345
04346 if ( !$infoOnly )
04347 return true;
04348
04349 if ( $moveToTrashAllowed and $totalLoneNodeCount == 0 )
04350 $moveToTrashAllowed = false;
04351
04352 return array( 'move_to_trash' => $moveToTrashAllowed,
04353 'total_child_count' => $totalChildCount,
04354 'can_remove_all' => $canRemoveAll,
04355 'delete_list' => $deleteResult,
04356 'reverse_related_count' => eZContentObjectTreeNode::reverseRelatedCount( $deleteIDArray ) );
04357 }
04358
04359
04360
04361
04362
04363
04364
04365
04366
04367
04368 function reverseRelatedCount( $nodeIDArray )
04369 {
04370
04371 if ( $nodeIDArray === array() )
04372 {
04373 return 0;
04374 }
04375
04376 foreach( $nodeIDArray as $nodeID )
04377 {
04378 $contentObjectTreeNode = eZContentObjectTreeNode::fetch( $nodeID, false, false );
04379 $tempPathString = $contentObjectTreeNode['path_string'];
04380
04381
04382 $pathStringArray[] = "tree.path_string like '$tempPathString%'";
04383 $path2StringArray[] = "tree2.path_string like '$tempPathString%'";
04384 }
04385 $path_strings = '( ' . implode( ' OR ', $pathStringArray ) . ' ) ';
04386 $path_strings_where = '( ' . implode( ' OR ', $path2StringArray ) . ' ) ';
04387
04388
04389 $db = eZDB::instance();
04390 $countOfItems = $db->arrayQuery( "SELECT COUNT( DISTINCT( tree.node_id ) ) as count
04391 FROM ezcontentobject_tree tree, ezcontentobject obj,
04392 ezcontentobject_link link LEFT JOIN ezcontentobject_tree tree2
04393 ON link.from_contentobject_id = tree2.contentobject_id
04394 WHERE $path_strings
04395 and link.to_contentobject_id = tree.contentobject_id
04396 and obj.id = link.from_contentobject_id
04397 and obj.current_version = link.from_contentobject_version
04398 and not $path_strings_where" );
04399
04400 if ( $countOfItems )
04401 {
04402 return $countOfItems[0]['count'];
04403 }
04404 }
04405
04406
04407
04408
04409
04410
04411
04412
04413
04414
04415
04416
04417 function removeNodeFromTree( $moveToTrash = true )
04418 {
04419 include_once( 'kernel/classes/ezcontentcachemanager.php' );
04420 $nodeID = $this->attribute( 'node_id' );
04421 if ( $nodeID == $this->attribute( 'main_node_id' ) )
04422 {
04423 $object = $this->object();
04424 $assignedNodes =& $object->attribute( 'assigned_nodes' );
04425 if ( count( $assignedNodes ) > 1 )
04426 {
04427 $newMainNode = false;
04428 foreach ( $assignedNodes as $assignedNode )
04429 {
04430 $assignedNodeID = $assignedNode->attribute( 'node_id' );
04431 if ( $assignedNodeID == $nodeID )
04432 continue;
04433 $newMainNode = $assignedNode;
04434 break;
04435 }
04436
04437
04438 $db =& eZDB::instance();
04439 $db->begin();
04440 eZContentObjectTreeNode::updateMainNodeID( $newMainNode->attribute( 'node_id' ),
04441 $object->attribute( 'id' ),
04442 $object->attribute( 'current_version' ),
04443 $newMainNode->attribute( 'parent_node_id' ) );
04444
04445 eZContentCacheManager::clearContentCacheIfNeeded( $this->attribute( 'contentobject_id' ) );
04446 $this->remove();
04447 $db->commit();
04448 }
04449 else
04450 {
04451
04452 eZContentCacheManager::clearContentCacheIfNeeded( $this->attribute( 'contentobject_id' ) );
04453
04454 $db =& eZDB::instance();
04455 $db->begin();
04456 $this->remove();
04457
04458 if ( $moveToTrash )
04459 {
04460
04461 include_once( 'kernel/classes/ezcontentobjecttrashnode.php' );
04462 $trashNode = eZContentObjectTrashNode::createFromNode( $this );
04463 $db =& eZDB::instance();
04464 $db->begin();
04465 $trashNode->storeToTrash();
04466 $db->commit();
04467 $object->remove();
04468 }
04469 else
04470 {
04471 $object->purge();
04472 }
04473 $db->commit();
04474 }
04475 }
04476 else
04477 {
04478 eZContentCacheManager::clearContentCacheIfNeeded( $this->attribute( 'contentobject_id' ) );
04479 $this->remove();
04480 }
04481 }
04482
04483
04484
04485
04486 function subtreeSoleNodeCount( $params = array() )
04487 {
04488 $nodeID = $this->attribute( 'node_id' );
04489 $node = $this;
04490
04491 $depth = false;
04492 if ( isset( $params['Depth'] ) && is_numeric( $params['Depth'] ) )
04493 {
04494 $depth = $params['Depth'];
04495
04496 }
04497
04498 $fromNode = $nodeID;
04499
04500 $nodePath = null;
04501 $nodeDepth = 0;
04502 if ( count( $node ) != 0 )
04503 {
04504 $nodePath = $node->attribute( 'path_string' );
04505 $nodeDepth = $node->attribute( 'depth' );
04506 }
04507
04508 $childPath = $nodePath;
04509
04510 $db =& eZDB::instance();
04511 $pathString = " ezcot.path_string like '$childPath%' and ";
04512
04513 $notEqParentString = "ezcot.node_id != $fromNode";
04514 $depthCond = '';
04515 if ( $depth )
04516 {
04517
04518 $nodeDepth += $depth;
04519 if ( isset( $params[ 'DepthOperator' ] ) && $params[ 'DepthOperator' ] == 'eq' )
04520 {
04521 $depthCond = ' ezcot.depth = ' . $nodeDepth . '';
04522 $notEqParentString = '';
04523 }
04524 else
04525 $depthCond = ' ezcot.depth <= ' . $nodeDepth . ' and ';
04526 }
04527
04528 $tmpTableName = $db->generateUniqueTempTableName( 'eznode_count_%' );
04529 $db->createTempTable( "CREATE TEMPORARY TABLE $tmpTableName ( count int )" );
04530 $query = "INSERT INTO $tmpTableName
04531 SELECT
04532 count( ezcot.main_node_id ) AS count
04533 FROM
04534 ezcontentobject_tree ezcot,
04535 ezcontentobject_tree ezcot_all
04536 WHERE
04537 $pathString
04538 $depthCond
04539 $notEqParentString
04540 and ezcot.contentobject_id = ezcot_all.contentobject_id
04541 GROUP BY ezcot_all.main_node_id
04542 HAVING count( ezcot.main_node_id ) <= 1";
04543
04544 $db->query( $query, EZ_DB_SERVER_SLAVE );
04545 $query = "SELECT count( * ) AS count
04546 FROM $tmpTableName";
04547
04548 $rows = $db->arrayQuery( $query, array(), EZ_DB_SERVER_SLAVE );
04549 $db->dropTempTable( "DROP TABLE $tmpTableName" );
04550 return $rows[0]['count'];
04551 }
04552
04553
04554
04555
04556
04557
04558 function move( $newParentNodeID, $nodeID = 0 )
04559 {
04560 include_once( "kernel/classes/ezpolicylimitation.php" );
04561 if ( $nodeID == 0 )
04562 {
04563 $node = $this;
04564 $nodeID = $node->attribute( 'node_id' );
04565 }
04566 else
04567 {
04568 $node = eZContentObjectTreeNode::fetch( $nodeID );
04569 }
04570
04571 $oldPath = $node->attribute( 'path_string' );
04572 $oldParentNodeID = $node->attribute( 'parent_node_id' );
04573 $newParentNodeID =(int) $newParentNodeID;
04574 if ( $oldParentNodeID != $newParentNodeID )
04575 {
04576 $node->updateAndStoreModified();
04577
04578 include_once( "kernel/classes/ezaudit.php" );
04579 $object = $node->object();
04580 eZAudit::writeAudit( 'content-move', array( 'Node ID' => $node->attribute( 'node_id' ),
04581 'Old parent node ID' => $oldParentNodeID, 'New parent node ID' => $newParentNodeID,
04582 'Object ID' => $object->attribute( 'id' ), 'Content Name' => $object->attribute( 'name' ),
04583 'Comment' => 'Moved the node to the given node: eZContentObjectTreeNode::move()' ) );
04584
04585 $newParentNode = eZContentObjectTreeNode::fetch( $newParentNodeID );
04586 $newParentPath = $newParentNode->attribute( 'path_string' );
04587 $newParentDepth = $newParentNode->attribute( 'depth' );
04588 $newPath = $newParentPath . $nodeID;
04589 $oldDepth = $node->attribute( 'depth' );
04590
04591 $oldPathLength = strlen( $oldPath );
04592 $moveQuery = "UPDATE
04593 ezcontentobject_tree
04594 SET
04595 parent_node_id = $newParentNodeID
04596 WHERE
04597 node_id = $nodeID";
04598 $db =& eZDB::instance();
04599 $subStringString = $db->subString( 'path_string', $oldPathLength );
04600 $newPathString = $db->concatString( array( "'$newPath'", $subStringString ) );
04601 $moveQuery1 = "UPDATE
04602 ezcontentobject_tree
04603 SET
04604 path_string = $newPathString,
04605 depth = depth + $newParentDepth - $oldDepth + 1
04606 WHERE
04607 path_string LIKE '$oldPath%'";
04608 $db->begin();
04609 $db->query( $moveQuery );
04610 $db->query( $moveQuery1 );
04611
04612
04613
04614
04615 $expireRoleCache = false;
04616
04617 $limitationsToFix = eZPolicyLimitation::findByType( 'SubTree', $node->attribute( 'path_string' ), false );
04618 if ( count( $limitationsToFix ) > 0 )
04619 {
04620 include_once( "kernel/classes/ezrole.php" );
04621 $limitationIDString = implode( ',', $limitationsToFix );
04622 $limitationIDString = "limitation_id in ( $limitationIDString ) ";
04623 $subStringString = $db->subString( 'value', $oldPathLength );
04624 $newValue = $db->concatString( array( "'$newPath'", $subStringString ) );
04625
04626 $query = "UPDATE
04627 ezpolicy_limitation_value
04628 SET
04629 value = $newValue
04630 WHERE
04631 value LIKE '$oldPath%' AND $limitationIDString";
04632
04633 $db->query( $query );
04634
04635 $expireRoleCache = true;
04636 }
04637
04638
04639 $countRows = $db->arrayQuery( "SELECT COUNT(*) AS row_count FROM ezuser_role WHERE limit_identifier='Subtree' AND limit_value LIKE '$oldPath%'" );
04640 $assignmentsToFixCount = $countRows[0]['row_count'];
04641
04642 if ( $assignmentsToFixCount > 0 )
04643 {
04644 $subStringString = $db->subString( 'limit_value', $oldPathLength );
04645 $newValue = $db->concatString( array( "'$newPath'", $subStringString ) );
04646
04647 $db->query( "UPDATE
04648 ezuser_role
04649 SET
04650 limit_value = $newValue
04651 WHERE
04652 limit_identifier='Subtree' AND limit_value LIKE '$oldPath%'"
04653 );
04654
04655 $expireRoleCache = true;
04656 }
04657
04658 if ( $expireRoleCache )
04659 {
04660 eZRole::expireCache();
04661 }
04662
04663
04664 $newNode = eZContentObjectTreeNode::fetch( $nodeID );
04665 eZContentObjectTreeNode::updateNodeVisibility( $newNode, $newParentNode );
04666 $db->commit();
04667 }
04668 }
04669
04670 function checkAccess( $functionName, $originalClassID = false, $parentClassID = false, $returnAccessList = false, $language = false )
04671 {
04672 $classID = $originalClassID;
04673 $user =& eZUser::currentUser();
04674 $userID = $user->attribute( 'contentobject_id' );
04675
04676 include_once( 'kernel/classes/ezcontentlanguage.php' );
04677
04678
04679 $originalLanguage = $language;
04680 if ( is_string( $language ) && strlen( $language ) > 0 )
04681 {
04682 $language = eZContentLanguage::idByLocale( $language );
04683 }
04684 else
04685 {
04686 $language = false;
04687 }
04688
04689
04690
04691 $languageList = false;
04692
04693
04694 $parentObject = false;
04695
04696 $origFunctionName = $functionName;
04697
04698
04699
04700 if ( $functionName == 'move' )
04701 $functionName = 'edit';
04702
04703
04704 if ( $functionName == 'can_add_location' ||
04705 $functionName == 'can_remove_location' )
04706 {
04707 $functionName = 'manage_locations';
04708 }
04709
04710 $accessResult = $user->hasAccessTo( 'content' , $functionName );
04711 $accessWord = $accessResult['accessWord'];
04712 if ( $origFunctionName == 'can_remove_location' )
04713 {
04714 if ( $this->ParentNodeID <= 1 )
04715 {
04716 return 0;
04717 }
04718 $currentNode = eZContentObjectTreeNode::fetch( $this->ParentNodeID );
04719 $contentObject = $currentNode->attribute( 'object' );
04720 }
04721 else
04722 {
04723 $currentNode = $this;
04724 $contentObject =& $this->attribute( 'object' );
04725 }
04726
04727
04728
04729
04730
04731
04732
04733
04734
04735
04736
04737
04738
04739
04740
04741
04742
04743
04744
04745
04746
04747
04748
04749
04750
04751
04752 if ( $origFunctionName == 'remove' or
04753 $origFunctionName == 'move' or
04754 $origFunctionName == 'can_remove_location' )
04755 {
04756
04757
04758
04759 if ( $this->ParentNodeID <= 1 )
04760 {
04761 return 0;
04762 }
04763 }
04764
04765 if ( $classID === false )
04766 {
04767 $classID = $contentObject->attribute( 'contentclass_id' );
04768 }
04769 if ( $accessWord == 'yes' )
04770 {
04771 return 1;
04772 }
04773 else if ( $accessWord == 'no' )
04774 {
04775 if ( $functionName == 'edit' )
04776 {
04777
04778 $object =& $currentNode->object();
04779 if ( $object && $object->attribute( 'current_version' ) == 1 && !$object->attribute( 'status' ) )
04780 {
04781 $mainNode = eZNodeAssignment::fetchForObject( $object->attribute( 'id' ), $object->attribute( 'current_version' ) );
04782 $parentObj = $mainNode[0]->attribute( 'parent_contentobject' );
04783 $result = $parentObj->checkAccess( 'create', $object->attribute( 'contentclass_id' ),
04784 $parentObj->attribute( 'contentclass_id' ), false, $originalLanguage );
04785 return $result;
04786 }
04787 else
04788 {
04789 return 0;
04790 }
04791 }
04792
04793 return 0;
04794 }
04795 else
04796 {
04797 $policies =& $accessResult['policies'];
04798 $access = 'denied';
04799
04800 foreach ( array_keys( $policies ) as $pkey )
04801 {
04802 if ( $access == 'allowed' )
04803 {
04804 break;
04805 }
04806
04807 $limitationArray =& $policies[$pkey];
04808 $limitationList = array();
04809 if ( isset( $limitationArray['Subtree' ] ) )
04810 {
04811 $checkedSubtree = false;
04812 }
04813 else
04814 {
04815 $checkedSubtree = true;
04816 $accessSubtree = false;
04817 }
04818 if ( isset( $limitationArray['Node'] ) )
04819 {
04820 $checkedNode = false;
04821 }
04822 else
04823 {
04824 $checkedNode = true;
04825 $accessNode = false;
04826 }
04827 foreach ( array_keys( $limitationArray ) as $key )
04828 {
04829 $access = 'denied';
04830 switch( $key )
04831 {
04832 case 'Class':
04833 {
04834 if ( $functionName == 'create' and
04835 !$originalClassID )
04836 {
04837 $access = 'allowed';
04838 }
04839 else if ( $functionName == 'create' and
04840 in_array( $classID, $limitationArray[$key] ) )
04841 {
04842 $access = 'allowed';
04843 }
04844 else if ( $functionName != 'create' and
04845 in_array( $contentObject->attribute( 'contentclass_id' ), $limitationArray[$key] ) )
04846 {
04847 $access = 'allowed';
04848 }
04849 else
04850 {
04851 $access = 'denied';
04852 $limitationList = array( 'Limitation' => $key,
04853 'Required' => $limitationArray[$key] );
04854 }
04855 } break;
04856
04857 case 'ParentClass':
04858 {
04859 if ( in_array( $contentObject->attribute( 'contentclass_id' ), $limitationArray[$key] ) )
04860 {
04861 $access = 'allowed';
04862 }
04863 else
04864 {
04865 $access = 'denied';
04866 $limitationList = array( 'Limitation' => $key,
04867 'Required' => $limitationArray[$key] );
04868 }
04869 } break;
04870
04871 case 'Section':
04872 case 'User_Section':
04873 {
04874 if ( in_array( $contentObject->attribute( 'section_id' ), $limitationArray[$key] ) )
04875 {
04876 $access = 'allowed';
04877 }
04878 else
04879 {
04880 $access = 'denied';
04881 $limitationList = array( 'Limitation' => $key,
04882 'Required' => $limitationArray[$key] );
04883 }
04884 } break;
04885
04886 case 'Language':
04887 {
04888 $languageMask = 0;
04889
04890
04891 if ( $functionName == 'create' )
04892 {
04893
04894 if ( $language !== false )
04895 {
04896 $languageMask = $language;
04897 }
04898 else
04899 {
04900
04901
04902
04903 $languageMask = -1;
04904 }
04905 }
04906 else
04907 {
04908 if ( $language !== false )
04909 {
04910 if ( $languageList === false )
04911 {
04912 $languageMask = $contentObject->attribute( 'language_mask' );
04913
04914 $languageMask &= $language;
04915
04916
04917
04918 if ( $languageMask == 0 )
04919 {
04920 $languageMask = $language;
04921 }
04922 }
04923 }
04924 else
04925 {
04926 $languageMask = -1;
04927 }
04928 }
04929
04930 $limitMask = eZContentLanguage::maskByLocale( $limitationArray[$key] );
04931 if ( ( $languageMask & $limitMask ) != 0 )
04932 {
04933 $access = 'allowed';
04934 }
04935 else
04936 {
04937 $access = 'denied';
04938 $limitationList = array( 'Limitation' => $key,
04939 'Required' => $limitationArray[$key] );
04940 }
04941 } break;
04942
04943 case 'Owner':
04944 {
04945
04946 if ( in_array( 2, $limitationArray[$key] ) &&
04947 $user->isAnonymous() )
04948 {
04949 include_once( 'kernel/classes/ezpreferences.php' );
04950 $createdObjectIDList = eZPreferences::value( 'ObjectCreationIDList' );
04951 if ( $createdObjectIDList &&
04952 in_array( $contentObject->attribute( 'id' ), unserialize( $createdObjectIDList ) ) )
04953 {
04954 $access = 'allowed';
04955 }
04956 }
04957 else if ( $contentObject->attribute( 'owner_id' ) == $userID || $contentObject->attribute( 'id' ) == $userID )
04958 {
04959 $access = 'allowed';
04960 }
04961 if ( $access != 'allowed' )
04962 {
04963 $access = 'denied';
04964 $limitationList = array ( 'Limitation' => $key );
04965 }
04966 } break;
04967
04968 case 'Group':
04969 {
04970 $access = $contentObject->checkGroupLimitationAccess( $limitationArray[$key], $userID );
04971
04972 if ( $access != 'allowed' )
04973 {
04974 $access = 'denied';
04975 $limitationList = array ( 'Limitation' => $key,
04976 'Required' => $limitationArray[$key] );
04977 }
04978 } break;
04979
04980 case 'ParentDepth':
04981 {
04982 if ( in_array( $currentNode->attribute( 'depth' ), $limitationArray[$key] ) )
04983 {
04984 $access = 'allowed';
04985 }
04986 else
04987 {
04988 $access = 'denied';
04989 $limitationList = array( 'Limitation' => $key,
04990 'Required' => $limitationArray[$key] );
04991 }
04992 } break;
04993
04994 case 'Node':
04995 {
04996 $accessNode = false;
04997 $mainNodeID = $currentNode->attribute( 'main_node_id' );
04998 foreach ( $limitationArray[$key] as $nodeID )
04999 {
05000 $node = eZContentObjectTreeNode::fetch( $nodeID, false, false );
05001 $limitationNodeID = $node['main_node_id'];
05002 if ( $mainNodeID == $limitationNodeID )
05003 {
05004 $access = 'allowed';
05005 $accessNode = true;
05006 break;
05007 }
05008 }
05009 if ( $access != 'allowed' && $checkedSubtree && !$accessSubtree )
05010 {
05011 $access = 'denied';
05012
05013 $limitationList = array( 'Limitation' => $key,
05014 'Required' => $limitationArray[$key] );
05015 }
05016 else
05017 {
05018 $access = 'allowed';
05019 }
05020 $checkedNode = true;
05021 } break;
05022
05023 case 'Subtree':
05024 {
05025 $accessSubtree = false;
05026 $path = $currentNode->attribute( 'path_string' );
05027 $subtreeArray = $limitationArray[$key];
05028 foreach ( $subtreeArray as $subtreeString )
05029 {
05030 if ( strstr( $path, $subtreeString ) )
05031 {
05032 $access = 'allowed';
05033 $accessSubtree = true;
05034 break;
05035 }
05036 }
05037 if ( $access != 'allowed' && $checkedNode && !$accessNode )
05038 {
05039 $access = 'denied';
05040
05041 $limitationList = array( 'Limitation' => $key,
05042 'Required' => $limitationArray[$key] );
05043 }
05044 else
05045 {
05046 $access = 'allowed';
05047 }
05048 $checkedSubtree = true;
05049 } break;
05050
05051 case 'User_Subtree':
05052 {
05053 $path = $currentNode->attribute( 'path_string' );
05054 $subtreeArray = $limitationArray[$key];
05055 foreach ( $subtreeArray as $subtreeString )
05056 {
05057 if ( strstr( $path, $subtreeString ) )
05058 {
05059 $access = 'allowed';
05060 }
05061 }
05062 if ( $access != 'allowed' )
05063 {
05064 $access = 'denied';
05065 $limitationList = array( 'Limitation' => $key,
05066 'Required' => $limitationArray[$key] );
05067 }
05068 } break;
05069 }
05070
05071 if ( $access == 'denied' )
05072 {
05073 break;
05074 }
05075 }
05076
05077 $policyList[] = array( 'PolicyID' => $pkey,
05078 'LimitationList' => $limitationList );
05079 }
05080 if ( $access == 'denied' )
05081 {
05082 $accessList = array( 'FunctionRequired' => array ( 'Module' => 'content',
05083 'Function' => $origFunctionName,
05084 'ClassID' => $classID,
05085 'MainNodeID' => $currentNode->attribute( 'main_node_id' ) ),
05086 'PolicyList' => $policyList );
05087 return 0;
05088 }
05089 else
05090 {
05091 return 1;
05092 }
05093 }
05094 }
05095
05096
05097
05098
05099
05100
05101 function classListFromPolicy( $policy, $allowedLanguageCodes = false )
05102 {
05103 $canCreateClassIDListPart = array();
05104 $hasClassIDLimitation = false;
05105 $object = false;
05106 if ( isset( $policy['Class'] ) )
05107 {
05108 $canCreateClassIDListPart = $policy['Class'];
05109 $hasClassIDLimitation = true;
05110 }
05111
05112 if ( isset( $policy['User_Section'] ) )
05113 {
05114 if ( $object === false )
05115 $object = $this->attribute( 'object' );
05116 if ( !in_array( $object->attribute( 'section_id' ), $policy['User_Section'] ) )
05117 {
05118 return array();
05119 }
05120 }
05121
05122 if ( isset( $policy['User_Subtree'] ) )
05123 {
05124 $allowed = false;
05125 if ( $object === false )
05126 $object = $this->attribute( 'object' );
05127 $assignedNodes = $object->attribute( 'assigned_nodes' );
05128 foreach ( $assignedNodes as $assignedNode )
05129 {
05130 $path = $assignedNode->attribute( 'path_string' );
05131 foreach ( $policy['User_Subtree'] as $subtreeString )
05132 {
05133 if ( strstr( $path, $subtreeString ) )
05134 {
05135 $allowed = true;
05136 break;
05137 }
05138 }
05139 }
05140 if( !$allowed )
05141 {
05142 return array();
05143 }
05144 }
05145
05146 if ( isset( $policy['Section'] ) )
05147 {
05148 if ( $object === false )
05149 $object = $this->attribute( 'object' );
05150 if ( !in_array( $object->attribute( 'section_id' ), $policy['Section'] ) )
05151 {
05152 return array();
05153 }
05154 }
05155
05156 if ( isset( $policy['ParentClass'] ) )
05157 {
05158 if ( $object === false )
05159 $object = $this->attribute( 'object' );
05160 if ( !in_array( $object->attribute( 'contentclass_id' ), $policy['ParentClass'] ) )
05161 {
05162 return array();
05163 }
05164 }
05165
05166 if ( isset( $policy['ParentDepth'] ) && is_array( $policy['ParentDepth'] ) )
05167 {
05168 $NodeDepth = $this->attribute( 'depth' );
05169 if ( !in_array( '*', $policy['ParentDepth'] ) && !in_array( $NodeDepth, $policy['ParentDepth'] ) )
05170 {
05171 return array();
05172 }
05173 }
05174
05175 if ( isset( $policy['Assigned'] ) )
05176 {
05177 if ( $object === false )
05178 $object = $this->attribute( 'object' );
05179 if ( $object->attribute( 'owner_id' ) != $user->attribute( 'contentobject_id' ) )
05180 {
05181 return array();
05182 }
05183 }
05184
05185 $allowedNode = false;
05186 if ( isset( $policy['Node'] ) )
05187 {
05188 $allowed = false;
05189 foreach( $policy['Node'] as $nodeID )
05190 {
05191 $mainNodeID = $this->attribute( 'main_node_id' );
05192 $node = eZContentObjectTreeNode::fetch( $nodeID, false, false );
05193 if ( $mainNodeID == $node['main_node_id'] )
05194 {
05195 $allowed = true;
05196 $allowedNode = true;
05197 break;
05198 }
05199 }
05200 if ( !$allowed && !isset( $policy['Subtree'] ) )
05201 {
05202 return array();
05203 }
05204 }
05205
05206 if ( isset( $policy['Subtree'] ) )
05207 {
05208 $allowed = false;
05209 if ( $object === false )
05210 $object = $this->attribute( 'object' );
05211 $assignedNodes = $object->attribute( 'assigned_nodes' );
05212 foreach ( $assignedNodes as $assignedNode )
05213 {
05214 $path = $assignedNode->attribute( 'path_string' );
05215 foreach ( $policy['Subtree'] as $subtreeString )
05216 {
05217 if ( strstr( $path, $subtreeString ) )
05218 {
05219 $allowed = true;
05220 break;
05221 }
05222 }
05223 }
05224 if ( !$allowed && !$allowedNode )
05225 {
05226 return array();
05227 }
05228 }
05229
05230 if ( isset( $policy['Language'] ) )
05231 {
05232 if ( $allowedLanguageCodes )
05233 {
05234 $allowedLanguageCodes = array_intersect( $allowedLanguageCodes, $policy['Language'] );
05235 }
05236 else
05237 {
05238 $allowedLanguageCodes = $policy['Language'];
05239 }
05240 }
05241
05242 if ( $hasClassIDLimitation )
05243 {
05244 return array( 'classes' => $canCreateClassIDListPart, 'language_codes' => $allowedLanguageCodes );
05245 }
05246 return array( 'classes' => '*', 'language_codes' => $allowedLanguageCodes );
05247 }
05248
05249
05250
05251
05252
05253
05254
05255
05256
05257
05258
05259
05260
05261
05262
05263
05264
05265
05266
05267
05268
05269
05270 function &canCreateClassList( $asObject = false, $includeFilter = true, $groupList = false, $fetchID = false )
05271 {
05272 $ini =& eZINI::instance();
05273 $groupArray = array();
05274 $languageCodeList = eZContentLanguage::fetchLocaleList();
05275 $allowedLanguages = array( '*' => array() );
05276
05277 $user =& eZUser::currentUser();
05278 $accessResult = $user->hasAccessTo( 'content' , 'create' );
05279 $accessWord = $accessResult['accessWord'];
05280
05281 $classIDArray = array();
05282 $classList = array();
05283 $fetchAll = false;
05284 if ( $accessWord == 'yes' )
05285 {
05286 $fetchAll = true;
05287 $allowedLanguages['*'] = $languageCodeList;
05288 }
05289 else if ( $accessWord == 'no' )
05290 {
05291
05292 return $classList;
05293 }
05294 else
05295 {
05296 $policies = $accessResult['policies'];
05297 foreach ( $policies as $policyKey => $policy )
05298 {
05299 $policyArray = $this->classListFromPolicy( $policy, $languageCodeList );
05300 if ( count( $policyArray ) == 0 )
05301 {
05302 continue;
05303 }
05304 $classIDArrayPart = $policyArray['classes'];
05305 $languageCodeArrayPart = $policyArray['language_codes'];
05306 if ( $classIDArrayPart == '*' )
05307 {
05308 $fetchAll = true;
05309 $allowedLanguages['*'] = array_unique( array_merge( $allowedLanguages['*'], $languageCodeArrayPart ) );
05310 }
05311 else
05312 {
05313 foreach( $classIDArrayPart as $class )
05314 {
05315 if ( isset( $allowedLanguages[$class] ) )
05316 {
05317 $allowedLanguages[$class] = array_unique( array_merge( $allowedLanguages[$class], $languageCodeArrayPart ) );
05318 }
05319 else
05320 {
05321 $allowedLanguages[$class] = $languageCodeArrayPart;
05322 }
05323 }
05324 $classIDArray = array_merge( $classIDArray, array_diff( $classIDArrayPart, $classIDArray ) );
05325 }
05326 }
05327 }
05328
05329 $filterTableSQL = '';
05330 $filterSQL = '';
05331
05332 if ( is_array( $groupList ) )
05333 {
05334 $filterTableSQL = ', ezcontentclass_classgroup ccg';
05335 $filterSQL = ( " AND\n" .
05336 " cc.id = ccg.contentclass_id AND\n" .
05337 " ccg.group_id " );
05338 $groupText = implode( ', ', $groupList );
05339 if ( $includeFilter )
05340 $filterSQL .= "IN ( $groupText )";
05341 else
05342 $filterSQL .= "NOT IN ( $groupText )";
05343 }
05344
05345 $classNameFilter = eZContentClassName::sqlFilter( 'cc' );
05346
05347 if ( $fetchAll )
05348 {
05349 $classList = array();
05350 $db =& eZDb::instance();
05351
05352 $fields = $asObject ? "cc.*, $classNameFilter[nameField]" : "cc.id, $classNameFilter[nameField]";
05353 $rows = $db->arrayQuery( "SELECT DISTINCT $fields\n" .
05354 "FROM ezcontentclass cc$filterTableSQL, $classNameFilter[from]\n" .
05355 "WHERE cc.version = " . EZ_CLASS_VERSION_STATUS_DEFINED . " $filterSQL AND $classNameFilter[where]\n" .
05356 "ORDER BY $classNameFilter[nameField] ASC" );
05357 $classList = eZPersistentObject::handleRows( $rows, 'ezcontentclass', $asObject );
05358 }
05359 else
05360 {
05361
05362 if ( count( $classIDArray ) == 0 )
05363 {
05364 $classList = array();
05365 return $classList;
05366 }
05367
05368 $classList = array();
05369 $db =& eZDb::instance();
05370 $classString = implode( ',', $classIDArray );
05371
05372 $fields = $asObject ? "cc.*, $classNameFilter[nameField]" : "cc.id, $classNameFilter[nameField]";
05373 $rows = $db->arrayQuery( "SELECT DISTINCT $fields\n" .
05374 "FROM ezcontentclass cc$filterTableSQL, $classNameFilter[from]\n" .
05375 "WHERE cc.id IN ( $classString ) AND\n" .
05376 " cc.version = " . EZ_CLASS_VERSION_STATUS_DEFINED . " $filterSQL AND $classNameFilter[where]\n" .
05377 "ORDER BY $classNameFilter[nameField] ASC" );
05378 $classList = eZPersistentObject::handleRows( $rows, 'ezcontentclass', $asObject );
05379 }
05380
05381 if ( $asObject )
05382 {
05383 foreach ( $classList as $key => $class )
05384 {
05385 $id = $class->attribute( 'id' );
05386 if ( isset( $allowedLanguages[$id] ) )
05387 {
05388 $languageCodes = array_unique( array_merge( $allowedLanguages['*'], $allowedLanguages[$id] ) );
05389 }
05390 else
05391 {
05392 $languageCodes = $allowedLanguages['*'];
05393 }
05394 $classList[$key]->setCanInstantiateLanguages( $languageCodes );
05395 }
05396 }
05397
05398 eZDebugSetting::writeDebug( 'kernel-content-class', $classList, "class list fetched from db" );
05399 return $classList;
05400 }
05401
05402
05403
05404
05405 function makeObjectsArray( &$array , $with_contentobject = true )
05406 {
05407 $retNodes = array();
05408 if ( !is_array( $array ) )
05409 return $retNodes;
05410
05411 $ini =& eZINI::instance();
05412
05413 foreach ( $array as $node )
05414 {
05415 unset( $object );
05416
05417 if( $node['node_id'] == 1 )
05418 {
05419 if( !array_key_exists( 'name', $node ) || !$node['name'] )
05420 $node['name'] = ezi18n( 'kernel/content', 'Top Level Nodes' );
05421 }
05422
05423 $object = new eZContentObjectTreeNode( $node );
05424
05425
05426 if ( isset( $node['name'] ) )
05427 {
05428 $object->setName( $node['name'] );
05429 }
05430
05431 if ( isset( $node['class_serialized_name_list'] ) )
05432 {
05433 $node['class_name'] = eZContentClass::nameFromSerializedString( $node['class_serialized_name_list'] );
05434 $object->ClassName = $node['class_name'];
05435 }
05436 if ( isset( $node['class_identifier'] ) )
05437 $object->ClassIdentifier = $node['class_identifier'];
05438 if ( $with_contentobject )
05439 {
05440 if ( array_key_exists( 'class_name', $node ) )
05441 {
05442 unset( $node['remote_id'] );
05443 $contentObject = new eZContentObject( $node );
05444
05445 $permissions = array();
05446 $contentObject->setPermissions( $permissions );
05447 $contentObject->setClassName( $node['class_name'] );
05448 if ( isset( $node['class_identifier'] ) )
05449 $contentObject->ClassIdentifier = $node['class_identifier'];
05450
05451 }
05452 else
05453 {
05454 $contentObject = new eZContentObject( array());
05455 if ( isset( $node['name'] ) )
05456 $contentObject->setCachedName( $node['name'] );
05457 }
05458 if ( isset( $node['real_translation'] ) && $node['real_translation'] != '' )
05459 {
05460 $object->CurrentLanguage = $node['real_translation'];
05461 $contentObject->CurrentLanguage = $node['real_translation'];
05462 }
05463 if ( $node['node_id'] == 1 )
05464 {
05465 $contentObject->ClassName = 'Folder';
05466 $contentObject->ClassIdentifier = 'folder';
05467 $contentObject->ClassID = 1;
05468 $contentObject->SectionID = 1;
05469 }
05470
05471 $object->setContentObject( $contentObject );
05472 }
05473 $retNodes[] =& $object;
05474 }
05475 return $retNodes;
05476 }
05477
05478 function getParentNodeId( $nodeID )
05479 {
05480 if ( !isset( $nodeID ) )
05481 return null;
05482 $db =& eZDB::instance();
05483 $nodeID =(int) $nodeID;
05484 $parentArr = $db->arrayQuery( "SELECT
05485 parent_node_id
05486 FROM
05487 ezcontentobject_tree
05488 WHERE
05489 node_id = $nodeID");
05490 return $parentArr[0]['parent_node_id'];
05491 }
05492
05493
05494
05495
05496
05497 function deleteNodeWhereParent( $node, $id )
05498 {
05499 eZContentObjectTreeNode::remove( eZContentObjectTreeNode::findNode( $node, $id ) );
05500
05501 }
05502
05503 function findNode( $parentNode, $id, $asObject = false, $remoteID = false )
05504 {
05505 if ( !isset( $parentNode) || $parentNode == NULL )
05506 {
05507 $parentNode = 2;
05508 }
05509 $parentNode =(int) $parentNode;
05510 $db =& eZDB::instance();
05511 if( $asObject )
05512 {
05513 if ( $remoteID )
05514 {
05515 $objectIDFilter = 'ezcontentobject.remote_id = ' . (string) $id;
05516 }
05517 else
05518 {
05519 $objectIDFilter = 'contentobject_id = ' . (int) $id;
05520 }
05521
05522 $query="SELECT ezcontentobject.*,
05523 ezcontentobject_tree.*,
05524 ezcontentclass.serialized_name_list as class_serialized_name_list,
05525 ezcontentclass.identifier as class_identifier,
05526 ezcontentclass.is_container as is_container
05527 FROM ezcontentobject_tree,
05528 ezcontentobject,
05529 ezcontentclass
05530 WHERE parent_node_id = $parentNode AND
05531 $objectIDFilter AND
05532 ezcontentobject_tree.contentobject_id=ezcontentobject.id AND
05533 ezcontentclass.version=0 AND
05534 ezcontentclass.id = ezcontentobject.contentclass_id ";
05535
05536 $nodeListArray = $db->arrayQuery( $query );
05537 $retNodeArray = eZContentObjectTreeNode::makeObjectsArray( $nodeListArray );
05538
05539 if ( count( $retNodeArray ) > 0 )
05540 {
05541 return $retNodeArray[0];
05542 }
05543 else
05544 {
05545 return null;
05546 }
05547 }
05548 else
05549 {
05550 $id = (int) $id;
05551 $getNodeQuery = "SELECT node_id
05552 FROM ezcontentobject_tree
05553 WHERE
05554 parent_node_id=$parentNode AND
05555 contentobject_id = $id ";
05556 $nodeArr = $db->arrayQuery( $getNodeQuery );
05557 if ( isset( $nodeArr[0] ) )
05558 {
05559 return $nodeArr[0]['node_id'];
05560 }
05561 else
05562 {
05563 return false;
05564 }
05565 }
05566 }
05567
05568 function &getName( $language = false )
05569 {
05570
05571 if ( $this->Name === null || $language !== false )
05572 {
05573 if ( $this->CurrentLanguage || $language !== false )
05574 {
05575 $sql = "SELECT name FROM ezcontentobject_name WHERE contentobject_id=" . (int) $this->ContentObjectID . " AND content_version=" . (int)$this->attribute( 'contentobject_version' ) . " AND real_translation='" . ( $language !== false ? $language : $this->CurrentLanguage ) . "'";
05576 }
05577 else
05578 {
05579 $sql = "SELECT name FROM ezcontentobject WHERE id=" . (int) $this->ContentObjectID;
05580 }
05581 $db =& eZDB::instance();
05582 $rows = $db->arrayQuery( $sql );
05583 if ( count( $rows ) > 0 )
05584 {
05585 if ( $language !== false )
05586 {
05587 return $rows[0]['name'];
05588 }
05589 $this->Name = $rows[0]['name'];
05590 }
05591 else
05592 {
05593 if ( $language !== false )
05594 {
05595 return false;
05596 }
05597 $this->Name = false;
05598 }
05599 }
05600 return $this->Name;
05601 }
05602
05603 function setName( $name )
05604 {
05605 $this->Name = $name;
05606 }
05607
05608
05609
05610
05611
05612
05613
05614
05615
05616
05617
05618
05619
05620
05621 function unserialize( $contentNodeDOMNode, $contentObject, $version, $isMain, &$nodeList, &$options, $handlerType = 'ezcontentobject' )
05622 {
05623 $parentNodeID = -1;
05624
05625 $remoteID = $contentNodeDOMNode->attributeValue( 'remote-id' );
05626 $parentNodeRemoteID = $contentNodeDOMNode->attributeValue( 'parent-node-remote-id' );
05627 $node = eZContentObjectTreeNode::fetchByRemoteID( $remoteID );
05628 if ( is_object( $node ) )
05629 {
05630 $description = "Node with remote ID $remoteID already exists.";
05631
05632 include_once( 'kernel/classes/ezpackagehandler.php' );
05633 $choosenAction = eZPackageHandler::errorChoosenAction( EZ_PACKAGE_CONTENTOBJECT_ERROR_EXISTS,
05634 $options, $description, $handlerType, false );
05635
05636 switch( $choosenAction )
05637 {
05638
05639 case EZ_PACKAGE_CONTENTOBJECT_NEW:
05640 {
05641 $newRemoteID = md5( (string)mt_rand() . (string)mktime() );
05642 $node->setAttribute( 'remote_id', $newRemoteID );
05643 $node->store();
05644 $nodeInfo = array( 'contentobject_id' => $node->attribute( 'contentobject_id' ),
05645 'contentobject_version' => $node->attribute( 'contentobject_version' ),
05646 'parent_remote_id' => $remoteID );
05647 $nodeAssignment = eZPersistentObject::fetchObject( eZNodeAssignment::definition(),
05648 null,
05649 $nodeInfo );
05650 if ( is_object( $nodeAssignment ) )
05651 {
05652 $nodeAssignment->setAttribute( 'parent_remote_id', $newRemoteID );
05653 $nodeAssignment->store();
05654 }
05655 } break;
05656
05657
05658 case EZ_PACKAGE_NON_INTERACTIVE:
05659 {
05660
05661 if ( !$parentNodeRemoteID )
05662 {
05663
05664 $node->setAttribute( 'sort_field', eZContentObjectTreeNode::sortFieldID( $contentNodeDOMNode->getAttribute( 'sort-field' ) ) );
05665 $node->setAttribute( 'sort_order', $contentNodeDOMNode->getAttribute( 'sort-order' ) );
05666 $node->store();
05667 return true;
05668 }
05669 } break;
05670
05671 default:
05672 {
05673
05674 $options['error'] = array( 'error_code' => EZ_PACKAGE_CONTENTOBJECT_ERROR_NODE_EXISTS,
05675 'element_id' => $remoteID,
05676 'description' => $description );
05677 return false;
05678 } break;
05679 }
05680 }
05681
05682 if ( $parentNodeRemoteID )
05683 {
05684 $parentNode = eZContentObjectTreeNode::fetchByRemoteID( $parentNodeRemoteID );
05685 if ( $parentNode !== null )
05686 {
05687 $parentNodeID = $parentNode->attribute( 'node_id' );
05688 }
05689 }
05690 else
05691 {
05692 if ( isset( $options['top_nodes_map'][$contentNodeDOMNode->attributeValue( 'node-id' )]['new_node_id'] ) )
05693 {
05694 $parentNodeID = $options['top_nodes_map'][$contentNodeDOMNode->attributeValue( 'node-id' )]['new_node_id'];
05695 }
05696 else if ( isset( $options['top_nodes_map']['*'] ) )
05697 {
05698 $parentNodeID = $options['top_nodes_map']['*'];
05699 }
05700 else
05701 {
05702 eZDebug::writeError( 'New parent node not set ' . $contentNodeDOMNode->attributeValue( 'name' ),
05703 'eZContentObjectTreeNode::unserialize()' );
05704 }
05705 }
05706
05707 $isMain = ( $isMain && $contentNodeDOMNode->attributeValue( 'is-main-node' ) );
05708
05709 $nodeInfo = array( 'contentobject_id' => $contentObject->attribute( 'id' ),
05710 'contentobject_version' => $version,
05711 'is_main' => $isMain,
05712 'parent_node' => $parentNodeID,
05713 'parent_remote_id' => $remoteID,
05714 'sort_field' => eZContentObjectTreeNode::sortFieldID( $contentNodeDOMNode->attributeValue( 'sort-field' ) ),
05715 'sort_order' => $contentNodeDOMNode->attributeValue( 'sort-order' ) );
05716
05717 if ( $parentNodeID == -1 && $parentNodeRemoteID )
05718 {
05719 if ( !isset( $options['suspended-nodes'] ) )
05720 {
05721 $options['suspended-nodes'] = array();
05722 }
05723
05724 $options['suspended-nodes'][$parentNodeRemoteID] = array( 'nodeinfo' => $nodeInfo,
05725 'priority' => $contentNodeDOMNode->attributeValue( 'priority' ) );
05726 return true;
05727 }
05728
05729 $existNodeAssignment = eZPersistentObject::fetchObject( eZNodeAssignment::definition(),
05730 null,
05731 $nodeInfo );
05732 $nodeInfo['priority'] = $contentNodeDOMNode->attributeValue( 'priority' );
05733 if( !is_object( $existNodeAssignment ) )
05734 {
05735 $nodeAssignment = eZNodeAssignment::create( $nodeInfo );
05736 $nodeList[] = $nodeInfo;
05737 $nodeAssignment->store();
05738 }
05739
05740 return true;
05741 }
05742
05743
05744
05745
05746
05747
05748
05749
05750 function serialize( $options, $contentNodeIDArray, $topNodeIDArray )
05751 {
05752 if ( $options['node_assignment'] == 'main' &&
05753 $this->attribute( 'main_node_id' ) != $this->attribute( 'node_id' ) )
05754 {
05755 return false;
05756 }
05757 if ( ! in_array( $this->attribute( 'node_id' ), array_keys( $contentNodeIDArray ) ) )
05758 {
05759 return false;
05760 }
05761
05762 $nodeAssignmentNode = new eZDOMNode();
05763 $nodeAssignmentNode->setName( 'node-assignment' );
05764 if ( $this->attribute( 'main_node_id' ) == $this->attribute( 'node_id' ) )
05765 {
05766 $nodeAssignmentNode->appendAttribute( eZDOMDocument::createAttributeNode( 'is-main-node', 1 ) );
05767 }
05768 if( !in_array( $this->attribute( 'node_id'), $topNodeIDArray ) )
05769 {
05770 $parentNode = $this->attribute( 'parent' );
05771 $nodeAssignmentNode->appendAttribute( eZDOMDocument::createAttributeNode( 'parent-node-remote-id', $parentNode->attribute( 'remote_id' ) ) );
05772 }
05773 $nodeAssignmentNode->appendAttribute( eZDOMDocument::createAttributeNode( 'name', $this->attribute( 'name' ) ) );
05774 $nodeAssignmentNode->appendAttribute( eZDOMDocument::createAttributeNode( 'node-id', $this->attribute( 'node_id' ) ) );
05775 $nodeAssignmentNode->appendAttribute( eZDOMDocument::createAttributeNode( 'remote-id', $this->attribute( 'remote_id' ) ) );
05776 $nodeAssignmentNode->appendAttribute( eZDOMDocument::createAttributeNode( 'sort-field', eZContentObjectTreeNode::sortFieldName( $this->attribute( 'sort_field' ) ) ) );
05777 $nodeAssignmentNode->appendAttribute( eZDOMDocument::createAttributeNode( 'sort-order', $this->attribute( 'sort_order' ) ) );
05778 $nodeAssignmentNode->appendAttribute( eZDOMDocument::createAttributeNode( 'priority', $this->attribute( 'priority' ) ) );
05779 return $nodeAssignmentNode;
05780 }
05781
05782
05783
05784
05785
05786
05787 function updateAndStoreModified()
05788 {
05789 $pathArray = explode( '/', $this->attribute( 'path_string' ) );
05790 $sql = '';
05791
05792 for( $pathCount = 1; $pathCount < count( $pathArray ) - 1; ++$pathCount )
05793 {
05794 $sql .= ( $pathCount != 1 ? 'OR ' : '' ) . 'node_id=\'' . $pathArray[$pathCount] . '\' ';
05795 }
05796
05797 if ( $sql != '' )
05798 {
05799 $sql = 'UPDATE ezcontentobject_tree SET modified_subnode=' . time() .
05800 ' WHERE ' . $sql;
05801 $db =& eZDB::instance();
05802 $db->query( $sql );
05803 }
05804 }
05805
05806
05807
05808
05809
05810 function store()
05811 {
05812 $db =& eZDB::instance();
05813
05814 $db->begin();
05815 eZPersistentObject::storeObject( $this );
05816 $this->updateAndStoreModified();
05817 $db->commit();
05818 }
05819
05820 function &object()
05821 {
05822 if ( $this->hasContentObject() )
05823 {
05824 return $this->ContentObject;
05825 }
05826 $contentobject_id = $this->attribute( 'contentobject_id' );
05827 $obj =& eZContentObject::fetch( $contentobject_id );
05828 $obj->setCurrentLanguage( $this->CurrentLanguage );
05829 $this->ContentObject =& $obj;
05830 return $obj;
05831 }
05832
05833 function hasContentObject()
05834 {
05835 if ( isset( $this->ContentObject ) && get_class( $this->ContentObject ) == "ezcontentobject" )
05836 return true;
05837 else
05838 return false;
05839 }
05840
05841
05842
05843
05844 function setContentObject( $object )
05845 {
05846 $this->ContentObject =& $object;
05847 }
05848
05849
05850
05851
05852
05853
05854 function &creator()
05855 {
05856 $db =& eZDB::instance();
05857 $query = "SELECT creator_id
05858 FROM ezcontentobject_version
05859 WHERE
05860 contentobject_id = '$this->ContentObjectID' AND
05861 version = '$this->ContentObjectVersion' ";
05862
05863 $creatorArray = $db->arrayQuery( $query );
05864 return eZContentObject::fetch( $creatorArray[0]['creator_id'] );
05865 }
05866
05867 function &contentObjectVersionObject( $asObject = true )
05868 {
05869 $version = eZContentObjectVersion::fetchVersion( $this->ContentObjectVersion, $this->ContentObjectID, $asObject );
05870 if ( $this->CurrentLanguage != false )
05871 {
05872 $version->CurrentLanguage = $this->CurrentLanguage;
05873 }
05874 return $version;
05875 }
05876
05877 function &urlAlias()
05878 {
05879 $useURLAlias =& $GLOBALS['eZContentObjectTreeNodeUseURLAlias'];
05880 $ini =& eZINI::instance();
05881 $cleanURL = '';
05882 if ( !isset( $useURLAlias ) )
05883 {
05884 $useURLAlias = $ini->variable( 'URLTranslator', 'Translation' ) == 'enabled';
05885 }
05886 if ( $useURLAlias )
05887 {
05888 if ( $ini->hasVariable( 'SiteAccessSettings', 'PathPrefix' ) &&
05889 $ini->variable( 'SiteAccessSettings', 'PathPrefix' ) != '' )
05890 {
05891 $prepend = $ini->variable( 'SiteAccessSettings', 'PathPrefix' );
05892 $pathIdenStr = substr( $prepend, strlen( $prepend ) -1 ) == '/'
05893 ? $this->PathIdentificationString . '/'
05894 : $this->PathIdentificationString;
05895 if ( strncmp( $pathIdenStr, $prepend, strlen( $prepend ) ) == 0 )
05896 $cleanURL = eZUrlAlias::cleanURL( substr( $this->PathIdentificationString, strlen( $prepend ) ) );
05897 else
05898 $cleanURL = eZUrlAlias::cleanURL( $this->PathIdentificationString );
05899 }
05900 else
05901 {
05902 $cleanURL = eZUrlAlias::cleanURL( $this->PathIdentificationString );
05903 }
05904 }
05905 else
05906 {
05907 $cleanURL = eZUrlAlias::cleanURL( 'content/view/full/' . $this->NodeID );
05908 }
05909
05910 return $cleanURL;
05911 }
05912
05913 function &url()
05914 {
05915 $ini =& eZINI::instance();
05916 if ( $ini->variable( 'URLTranslator', 'Translation' ) == 'enabled' )
05917 {
05918 $url =& $this->urlAlias();
05919 }
05920 else
05921 {
05922 $url = 'content/view/full/' . $this->NodeID;
05923 }
05924
05925 return $url;
05926 }
05927
05928
05929
05930
05931
05932 function &classIdentifier()
05933 {
05934 $identifier = '';
05935 if ( $this->ClassIdentifier !== null )
05936 {
05937 $identifier = $this->ClassIdentifier;
05938 }
05939 else
05940 {
05941 $object = $this->object();
05942 $class = $object->contentClass();
05943 $identifier = $class->attribute( 'identifier' );
05944 }
05945
05946 return $identifier;
05947 }
05948
05949
05950
05951
05952 function &className()
05953 {
05954 $name = "";
05955 if ( $this->ClassName !== null )
05956 {
05957 $name = $this->ClassName;
05958 }
05959 else
05960 {
05961 $object = $this->object();
05962 $class = $object->contentClass();
05963 $name = $class->attribute( 'name' );
05964 }
05965
05966 return $name;
05967 }
05968
05969
05970
05971
05972
05973
05974 function &hiddenInvisibleString()
05975 {
05976 $retValue = ( $this->IsHidden ? 'H' : '-' ) . '/' . ( $this->IsInvisible ? 'X' : '-' );
05977 return $retValue;
05978 }
05979
05980
05981
05982
05983
05984 function &hiddenStatusString()
05985 {
05986 if( $this->IsHidden )
05987 $retVal = ezi18n( 'kernel/content', 'Hidden' );
05988 else if( $this->IsInvisible )
05989 $retVal = ezi18n( 'kernel/content', 'Hidden by superior' );
05990 else
05991 $retVal = ezi18n( 'kernel/content', 'Visible' );
05992
05993 return $retVal;
05994 }
05995
05996
05997
05998
05999
06000
06001
06002
06003
06004
06005
06006
06007
06008
06009
06010
06011
06012
06013
06014
06015
06016
06017
06018
06019
06020 function hideSubTree( &$node, $modifyRootNode = true )
06021 {
06022 $nodeID = $node->attribute( 'node_id' );
06023 $db =& eZDB::instance();
06024
06025 if ( !$node->attribute( 'is_invisible' ) ) // if root node is visible
06026 {
06027 $db->begin();
06028
06029 // 1) Mark root node as hidden and invisible.
06030 if ( $modifyRootNode )
06031 $db->query( "UPDATE ezcontentobject_tree SET is_hidden=1, is_invisible=1 WHERE node_id=$nodeID" );
06032
06033 // 2) Recursively mark child nodes as invisible, except for ones which have been previously marked as invisible.
06034 $nodePath = $node->attribute( 'path_string' );
06035 $db->query( "UPDATE ezcontentobject_tree SET is_invisible=1 WHERE is_invisible=0 AND path_string LIKE '$nodePath%'" );
06036
06037 $db->commit();
06038 }
06039 else
06040 {
06041 // Mark root node as hidden
06042 if ( $modifyRootNode )
06043 $db->query( "UPDATE ezcontentobject_tree SET is_hidden=1 WHERE node_id=$nodeID" );
06044 }
06045
06046 eZContentObjectTreeNode::clearViewCacheForSubtree( $node, $modifyRootNode );
06047 }
06048
06049
06050
06051
06052
06053
06054
06055
06056
06057
06058
06059
06060
06061
06062
06063
06064
06065
06066
06067
06068
06069 function unhideSubTree( &$node, $modifyRootNode = true )
06070 {
06071 $nodeID = $node->attribute( 'node_id' );
06072 $nodePath = $node->attribute( 'path_string' );
06073 $nodeInvisible = $node->attribute( 'is_invisible' );
06074 $parentNode =& $node->attribute( 'parent' );
06075 $db =& eZDB::instance();
06076
06077
06078 if ( ! $parentNode->attribute( 'is_invisible' ) ) // if parent node is visible
06079 {
06080 $db->begin();
06081 // 1) Mark root node as not hidden and visible.
06082 if ( $modifyRootNode )
06083 $db->query( "UPDATE ezcontentobject_tree SET is_invisible=0, is_hidden=0 WHERE node_id=$nodeID" );
06084
06085 // 2) Recursively mark child nodes as visible (except for nodes previosly marked as hidden, and all their children).
06086
06087 // 2.1) $hiddenChildren = Fetch all hidden children for the root node
06088 $hiddenChildren = $db->arrayQuery( "SELECT path_string FROM ezcontentobject_tree " .
06089 "WHERE node_id <> $nodeID AND is_hidden=1 AND path_string LIKE '$nodePath%'" );
06090 $skipSubtreesString = '';
06091 foreach ( $hiddenChildren as $i )
06092 $skipSubtreesString .= " AND path_string NOT LIKE '" . $i['path_string'] . "%'";
06093
06094 // 2.2) Mark those children as visible which are not under nodes in $hiddenChildren
06095 $db->query( "UPDATE ezcontentobject_tree SET is_invisible=0 WHERE path_string LIKE '$nodePath%' $skipSubtreesString" );
06096 $db->commit();
06097 }
06098 else
06099 {
06100 // Mark root node as not hidden.
06101 if ( $modifyRootNode )
06102 $db->query( "UPDATE ezcontentobject_tree SET is_hidden=0 WHERE node_id=$nodeID" );
06103 }
06104
06105 eZContentObjectTreeNode::clearViewCacheForSubtree( $node, $modifyRootNode );
06106 }
06107
06108
06109
06110
06111
06112
06113 function updateNodeVisibility( &$node, &$parentNode, $recursive = true )
06114 {
06115 if ( !$node )
06116 {
06117 eZDebug::writeWarning( 'No such node to update visibility for.' );
06118 return;
06119 }
06120
06121 if ( !$parentNode )
06122 {
06123 eZDebug::writeWarning( 'No parent node found when updating node visibility' );
06124 return;
06125 }
06126
06127 if ( $node->attribute( 'is_hidden' ) == 0 &&
06128 $parentNode->attribute( 'is_invisible' ) != $node->attribute( 'is_invisible' ) )
06129 {
06130 $parentNodeIsVisible = $parentNode->attribute( 'is_invisible' );
06131 $nodeID = $node->attribute( 'node_id' );
06132 $db =& eZDB::instance();
06133 $db->begin();
06134 $db->query( "UPDATE ezcontentobject_tree SET is_invisible=$parentNodeIsVisible WHERE node_id=$nodeID" );
06135
06136 if ( $recursive )
06137 {
06138 // update visibility for children of the node
06139 if( $parentNodeIsVisible )
06140 eZContentObjectTreeNode::hideSubTree( $node, $modifyRootNode = false );
06141 else
06142 eZContentObjectTreeNode::unhideSubTree( $node, $modifyRootNode = false );
06143 }
06144 $db->commit();
06145 }
06146 }
06147
06148
06149
06150
06151
06152 function clearViewCacheForSubtree( &$node, $clearForRootNode = true )
06153 {
06154 include_once( 'kernel/classes/ezcontentcachemanager.php' );
06155
06156 // Max nodes to fetch at a time
06157 static $limit = 50;
06158
06159 if ( !$node )
06160 {
06161 eZDebug::writeWarning( "No such subtree to clear view cache for" );
06162 return false;
06163 }
06164
06165 if ( $clearForRootNode )
06166 {
06167 $objectID = $node->attribute( 'contentobject_id' );
06168 eZContentCacheManager::clearContentCacheIfNeeded( $objectID );
06169 }
06170
06171 $offset = 0;
06172 $params = array( 'AsObject' => false,
06173 'Depth' => false,
06174 'Limitation' => array() ); // Empty array means no permission checking
06175 $subtreeCount = $node->subTreeCount( $params );
06176 while ( $offset < $subtreeCount )
06177 {
06178 $params['Offset'] = $offset;
06179 $params['Limit'] = $limit;
06180
06181 $subtreeChunk =& $node->subTree( $params );
06182 $nNodesInChunk = count( $subtreeChunk );
06183 $offset += $nNodesInChunk;
06184 if ( $nNodesInChunk == 0 )
06185 break;
06186
06187 $objectIDList = array();
06188 foreach ( $subtreeChunk as $curNode )
06189 $objectIDList[] = $curNode['contentobject_id'];
06190 $objectIDList = array_unique( $objectIDList );
06191 unset( $subtreeChunk );
06192
06193 foreach ( $objectIDList as $objectID )
06194 eZContentCacheManager::clearContentCacheIfNeeded( $objectID );
06195 }
06196
06197 return true;
06198 }
06199
06200 function setVersionByObjectID( $objectID, $newVersion )
06201 {
06202 $db =& eZDB::instance();
06203 $db->query( "UPDATE ezcontentobject_tree SET contentobject_version='$newVersion' WHERE contentobject_id='$objectID'" );
06204 }
06205
06206 function currentLanguage()
06207 {
06208 return $this->CurrentLanguage;
06209 }
06210
06211 function setCurrentLanguage( $languageCode )
06212 {
06213 $this->CurrentLanguage = $languageCode;
06214 if ( $this->hasContentObject() )
06215 {
06216 $this->ContentObject->setCurrentLanguage( $languageCode );
06217 }
06218 $this->Name = null;
06219 }
06220
06221
06222
06223
06224 function parentDepthLimitationList()
06225 {
06226 $maxLevel = 0;
06227 $ini =& eZINI::instance();
06228 if ( $ini->hasVariable( 'RoleSettings', 'MaxParentDepthLimitation' ) )
06229 $maxLevel = $ini->variable( 'RoleSettings', 'MaxParentDepthLimitation' );
06230
06231 $depthArray = array();
06232 for ( $i = 1; $i <= $maxLevel; $i++ )
06233 {
06234 $depthArray[] = array( 'name' => $i, 'id' => $i );
06235 }
06236
06237 return $depthArray;
06238 }
06239
06240 /*
06241 Returns available classes as Js array.
06242 Checks if the node is container, if yes emptyStr will be returned.
06243 */
06244 function &availableClassesJsArray()
06245 {
06246 $classList = eZContentObjectTreeNode::availableClassListJsArray( array( 'node' => &$this ) );
06247 return $classList;
06248 }
06249
06250 /*
06251 Returns available classes as Js array.
06252 Checks for ini settings.
06253 */
06254 function availableClassListJsArray( $parameters = false )
06255 {
06256 $iniMenu =& eZINI::instance( 'contentstructuremenu.ini' );
06257 $falseValue = "''";
06258
06259 if ( $iniMenu->hasVariable( 'TreeMenu', 'CreateHereMenu' ) )
06260 {
06261 $createHereMenu = $iniMenu->variable( 'TreeMenu', 'CreateHereMenu' );
06262 }
06263 else
06264 {
06265 $createHereMenu = 'simplified';
06266 }
06267 if ( $createHereMenu != 'simplified' and $createHereMenu != 'full' )
06268 return $falseValue;
06269
06270 $ini =& eZINI::instance( 'content.ini' );
06271 list( $usersClassGroupID, $setupClassGroupID ) = $ini->variableMulti( 'ClassGroupIDs', array( 'Users', 'Setup' ) );
06272 $userRootNode = $ini->variable( 'NodeSettings', 'UserRootNode' );
06273 $groupIDs = false;
06274 $filterType = 'include';
06275
06276 if ( !is_array( $parameters ) )
06277 return $falseValue;
06278
06279 $node = isset( $parameters['node'] ) ? $parameters['node'] : false;
06280 if ( is_object( $node ) )
06281 {
06282 if ( $createHereMenu == 'full' and !$node->canCreate() )
06283 return $falseValue;
06284
06285 $obj =& $node->object();
06286 $contentClass =& $obj->attribute( 'content_class' );
06287 if ( !$contentClass->attribute( 'is_container' ) )
06288 return $falseValue;
06289
06290 $pathArray = $node->pathArray();
06291 }
06292 else
06293 {
06294 // If current object is not container we should not return class list, should not display "create here" menu.
06295 if ( isset( $parameters['is_container'] ) and !$parameters['is_container'] )
06296 return $falseValue;
06297
06298 // Check if current user can create under this node
06299 if ( $createHereMenu == 'full' and isset( $parameters['node_id'] ) )
06300 {
06301 $node =& eZContentObjectTreeNode::fetch( $parameters['node_id'] );
06302 if ( is_object( $node ) and !$node->canCreate() )
06303 return $falseValue;
06304 }
06305 $pathString = isset( $parameters['path_string'] ) ? $parameters['path_string'] : false;
06306 if ( !$pathString )
06307 return $falseValue;
06308
06309 $pathItems = explode( '/', $pathString );
06310 $pathArray = array();
06311 foreach ( $pathItems as $pathItem )
06312 {
06313 if ( $pathItem != '' )
06314 $pathArray[] = (int) $pathItem;
06315 }
06316 }
06317
06318 if ( in_array( $userRootNode, $pathArray ) )
06319 {
06320 $groupIDs = array( $usersClassGroupID );
06321 }
06322 else
06323 {
06324 $groupIDs = array( $usersClassGroupID, $setupClassGroupID );
06325 $filterType = 'exclude';
06326 }
06327
06328 if ( $createHereMenu == 'simplified' )
06329 {
06330 include_once( "kernel/classes/ezcontentclass.php" );
06331 $classes =& eZContentClass::fetchAllClasses( false, $filterType == 'include', $groupIDs );
06332 $classList = eZContentObjectTreeNode::getClassesJsArray( false, $filterType == 'include', $groupIDs, false, $classes );
06333 return $classList;
06334 }
06335
06336 $classList = eZContentObjectTreeNode::getClassesJsArray( $node, $filterType == 'include', $groupIDs );
06337 return $classList;
06338 }
06339
06340 /*
06341 Returns available classes as Js array.
06342 \note building js array.
06343 */
06344 function getClassesJsArray( $node = false, $includeFilter = true, $groupList = false, $fetchID = false, $classes = false )
06345 {
06346 include_once( 'kernel/classes/ezcontentclass.php' );
06347 $falseValue = "''";
06348 // If $classes is false we should check $node and fetch class list
06349 if ( $classes === false )
06350 {
06351 // If $node is object we should fetch available classes from node, from ezcontentclass otherwise
06352 $classes = ( is_object( $node ) and get_class( $node ) == 'ezcontentobjecttreenode' )
06353 ? $node->canCreateClassList( false, $includeFilter, $groupList, $fetchID )
06354 : eZContentClass::canInstantiateClassList( false, $includeFilter, $groupList, $fetchID );
06355 }
06356 if ( !is_array( $classes ) )
06357 return $falseValue;
06358
06359 // Create javascript array
06360 $jsArray = array();
06361 $db =& eZDB::instance();
06362 foreach ( $classes as $class )
06363 {
06364 if ( is_object( $class ) )
06365 {
06366 $classID = $class->attribute( 'id' );
06367 $className = $class->attribute( 'name' );
06368 }
06369 elseif ( is_array( $class ) )
06370 {
06371 $classID = $class['id'];
06372 $className = $class['name'];
06373 }
06374 $jsArray[] = "{ classID: '" . $db->escapeString( $classID ) .
06375 "', name: '" . $db->escapeString( $className ) . "' }";
06376 }
06377
06378 if ( $jsArray )
06379 return '[ '.implode( ', ', $jsArray ).' ]';
06380
06381 return $falseValue;
06382 }
06383
06384
06385
06386 var $CurrentLanguage = false;
06387
06388
06389 var $Name;
06390
06391
06392 var $ClassIdentifier = null;
06393 var $ClassName = null;
06394 }
06395
06396 ?>