|
eZ Publish
[4.1]
|
00001 <?php 00002 // 00003 // Definition of eZContentClass class 00004 // 00005 // Created on: <16-Apr-2002 11:08:14 amos> 00006 // 00007 // ## BEGIN COPYRIGHT, LICENSE AND WARRANTY NOTICE ## 00008 // SOFTWARE NAME: eZ Publish 00009 // SOFTWARE RELEASE: 4.1.x 00010 // COPYRIGHT NOTICE: Copyright (C) 1999-2009 eZ Systems AS 00011 // SOFTWARE LICENSE: GNU General Public License v2.0 00012 // NOTICE: > 00013 // This program is free software; you can redistribute it and/or 00014 // modify it under the terms of version 2.0 of the GNU General 00015 // Public License as published by the Free Software Foundation. 00016 // 00017 // This program is distributed in the hope that it will be useful, 00018 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00019 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00020 // GNU General Public License for more details. 00021 // 00022 // You should have received a copy of version 2.0 of the GNU General 00023 // Public License along with this program; if not, write to the Free 00024 // Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 00025 // MA 02110-1301, USA. 00026 // 00027 // 00028 // ## END COPYRIGHT, LICENSE AND WARRANTY NOTICE ## 00029 // 00030 00031 /*! 00032 \class eZContentClass ezcontentclass.php 00033 \ingroup eZKernel 00034 \brief Handles eZ Publish content classes 00035 00036 \sa eZContentObject 00037 */ 00038 00039 require_once( "kernel/common/i18n.php" ); 00040 00041 class eZContentClass extends eZPersistentObject 00042 { 00043 const VERSION_STATUS_DEFINED = 0; 00044 const VERSION_STATUS_TEMPORARY = 1; 00045 const VERSION_STATUS_MODIFIED = 2; 00046 00047 function eZContentClass( $row ) 00048 { 00049 if ( is_array( $row ) ) 00050 { 00051 $this->eZPersistentObject( $row ); 00052 $this->VersionCount = false; 00053 $this->InGroups = null; 00054 $this->AllGroups = null; 00055 if ( isset( $row["version_count"] ) ) 00056 $this->VersionCount = $row["version_count"]; 00057 00058 $this->NameList = new eZContentClassNameList(); 00059 if ( isset( $row['serialized_name_list'] ) ) 00060 $this->NameList->initFromSerializedList( $row['serialized_name_list'] ); 00061 else 00062 $this->NameList->initDefault(); 00063 } 00064 $this->DataMap = false; 00065 } 00066 00067 static function definition() 00068 { 00069 return array( "fields" => array( "id" => array( 'name' => 'ID', 00070 'datatype' => 'integer', 00071 'default' => 0, 00072 'required' => true ), 00073 "version" => array( 'name' => 'Version', 00074 'datatype' => 'integer', 00075 'default' => 0, 00076 'required' => true ), 00077 "serialized_name_list" => array( 'name' => 'SerializedNameList', 00078 'datatype' => 'string', 00079 'default' => '', 00080 'required' => true ), 00081 "identifier" => array( 'name' => "Identifier", 00082 'datatype' => 'string', 00083 'default' => '', 00084 'required' => true ), 00085 "contentobject_name" => array( 'name' => "ContentObjectName", 00086 'datatype' => 'string', 00087 'default' => '', 00088 'required' => true ), 00089 "url_alias_name" => array( 'name' => "URLAliasName", 00090 'datatype' => 'string', 00091 'default' => '', 00092 'required' => false ), 00093 "creator_id" => array( 'name' => "CreatorID", 00094 'datatype' => 'integer', 00095 'default' => 0, 00096 'required' => true, 00097 'foreign_class' => 'eZUser', 00098 'foreign_attribute' => 'contentobject_id', 00099 'multiplicity' => '1..*' ), 00100 "modifier_id" => array( 'name' => "ModifierID", 00101 'datatype' => 'integer', 00102 'default' => 0, 00103 'required' => true, 00104 'foreign_class' => 'eZUser', 00105 'foreign_attribute' => 'contentobject_id', 00106 'multiplicity' => '1..*' ), 00107 "created" => array( 'name' => "Created", 00108 'datatype' => 'integer', 00109 'default' => 0, 00110 'required' => true ), 00111 "remote_id" => array( 'name' => "RemoteID", 00112 'datatype' => 'string', 00113 'default' => '', 00114 'required' => true ), 00115 "modified" => array( 'name' => "Modified", 00116 'datatype' => 'integer', 00117 'default' => 0, 00118 'required' => true ), 00119 "is_container" => array( 'name' => "IsContainer", 00120 'datatype' => 'integer', 00121 'default' => 0, 00122 'required' => true ), 00123 'always_available' => array( 'name' => "AlwaysAvailable", 00124 'datatype' => 'integer', 00125 'default' => 0, 00126 'required' => true ), 00127 'language_mask' => array( 'name' => "LanguageMask", 00128 'datatype' => 'integer', 00129 'default' => 0, 00130 'required' => true ), 00131 'initial_language_id' => array( 'name' => "InitialLanguageID", 00132 'datatype' => 'integer', 00133 'default' => 0, 00134 'required' => true, 00135 'foreign_class' => 'eZContentLanguage', 00136 'foreign_attribute' => 'id', 00137 'multiplicity' => '1..*' ), 00138 'sort_field' => array( 'name' => 'SortField', 00139 'datatype' => 'integer', 00140 'default' => 1, 00141 'required' => true ), 00142 'sort_order' => array( 'name' => 'SortOrder', 00143 'datatype' => 'integer', 00144 'default' => 1, 00145 'required' => true ) ), 00146 "keys" => array( "id", "version" ), 00147 "function_attributes" => array( "data_map" => "dataMap", 00148 'object_count' => 'objectCount', 00149 'object_list' => 'objectList', 00150 'version_count' => 'versionCount', 00151 'version_status' => 'versionStatus', 00152 'remote_id' => 'remoteID', // Note: This overrides remote_id field 00153 'ingroup_list' => 'fetchGroupList', 00154 'ingroup_id_list' => 'fetchGroupIDList', 00155 'match_ingroup_id_list' => 'fetchMatchGroupIDList', 00156 'group_list' => 'fetchAllGroups', 00157 'creator' => 'creator', 00158 'modifier' => 'modifier', 00159 'can_instantiate_languages' => 'canInstantiateLanguages', 00160 'name' => 'name', 00161 'nameList' => 'nameList', 00162 'languages' => 'languages', 00163 'prioritized_languages' => 'prioritizedLanguages', 00164 'prioritized_languages_js_array' => 'prioritizedLanguagesJsArray', 00165 'can_create_languages' => 'canCreateLanguages', 00166 'top_priority_language_locale' => 'topPriorityLanguageLocale', 00167 'always_available_language' => 'alwaysAvailableLanguage' ), 00168 'set_functions' => array( 'name' => 'setName' ), 00169 "increment_key" => "id", 00170 "class_name" => "eZContentClass", 00171 "sort" => array( "id" => "asc" ), 00172 "name" => "ezcontentclass" ); 00173 return $definition; 00174 } 00175 00176 function __clone() 00177 { 00178 unset( $this->Version ); 00179 unset( $this->InGroups ); 00180 unset( $this->AllGroups ); 00181 unset( $this->CanInstantiateLanguages ); 00182 unset( $this->VersionCount ); 00183 $this->ID = null; 00184 $this->RemoteID = md5( (string)mt_rand() . (string)time() ); 00185 } 00186 00187 /*! 00188 Creates an 'eZContentClass' object. 00189 00190 To specify contentclass name use either $optionalValues['serialized_name_list'] or 00191 combination of $optionalValues['name'] and/or $languageLocale. 00192 00193 In case of conflict(when both 'serialized_name_list' and 'name' with/without $languageLocale 00194 are specified) 'serialized_name_list' has top priority. This means that 'name' and 00195 $languageLocale will be ingnored because 'serialized_name_list' already has all needed info 00196 about names and languages. 00197 00198 If 'name' is specified then the contentclass will have a name in $languageLocale(if specified) or 00199 in default language. 00200 00201 If neither of 'serialized_name_list' or 'name' isn't specified then the contentclass will have an empty 00202 name in 'languageLocale'(if specified) or in default language. 00203 00204 'language_mask' and 'initial_language_id' attributes will be set according to specified(either 00205 in 'serialized_name_list' or by $languageLocale) languages. 00206 00207 \return 'eZContentClass' object. 00208 */ 00209 static function create( $userID = false, $optionalValues = array(), $languageLocale = false ) 00210 { 00211 $dateTime = time(); 00212 if ( !$userID ) 00213 $userID = eZUser::currentUserID(); 00214 00215 $nameList = new eZContentClassNameList(); 00216 if ( isset( $optionalValues['serialized_name_list'] ) ) 00217 $nameList->initFromSerializedList( $optionalValues['serialized_name_list'] ); 00218 else if ( isset( $optionalValues['name'] ) ) 00219 $nameList->initFromString( $optionalValues['name'], $languageLocale ); 00220 else 00221 $nameList->initFromString( '', $languageLocale ); 00222 00223 $languageMask = $nameList->languageMask(); 00224 $initialLanguageID = $nameList->alwaysAvailableLanguageID(); 00225 00226 $contentClassDefinition = eZContentClass::definition(); 00227 $row = array( 00228 "id" => null, 00229 "version" => 1, 00230 "serialized_name_list" => $nameList->serializeNames(), 00231 "identifier" => "", 00232 "contentobject_name" => "", 00233 "creator_id" => $userID, 00234 "modifier_id" => $userID, 00235 "created" => $dateTime, 00236 'remote_id' => md5( (string)mt_rand() . (string)time() ), 00237 "modified" => $dateTime, 00238 "is_container" => $contentClassDefinition[ 'fields' ][ 'is_container' ][ 'default' ], 00239 "always_available" => $contentClassDefinition[ 'fields' ][ 'always_available' ][ 'default' ], 00240 'language_mask' => $languageMask, 00241 'initial_language_id' => $initialLanguageID, 00242 "sort_field" => $contentClassDefinition[ 'fields' ][ 'sort_field' ][ 'default' ], 00243 "sort_order" => $contentClassDefinition[ 'fields' ][ 'sort_order' ][ 'default' ] ); 00244 00245 $row = array_merge( $row, $optionalValues ); 00246 00247 $contentClass = new eZContentClass( $row ); 00248 00249 // setting 'dirtyData' to make sure the 'NameList' will be stored into db. 00250 $contentClass->NameList->setHasDirtyData( true ); 00251 00252 return $contentClass; 00253 } 00254 00255 function instantiateIn( $lang, $userID = false, $sectionID = 0, $versionNumber = false, $versionStatus = eZContentObjectVersion::STATUS_INTERNAL_DRAFT ) 00256 { 00257 return eZContentClass::instantiate( $userID, $sectionID, $versionNumber, $lang, $versionStatus ); 00258 } 00259 00260 /*! 00261 Creates a new content object instance and stores it. 00262 00263 \param userID user ID (optional), current user if not set 00264 \param sectionID section ID (optional), 0 if not set 00265 \param versionNumber version number, create initial version if not set 00266 \note Transaction unsafe. If you call several transaction unsafe methods you must enclose 00267 the calls within a db transaction; thus within db->begin and db->commit. 00268 */ 00269 function instantiate( $userID = false, $sectionID = 0, $versionNumber = false, $languageCode = false, $versionStatus = eZContentObjectVersion::STATUS_INTERNAL_DRAFT ) 00270 { 00271 $attributes = $this->fetchAttributes(); 00272 00273 $user = eZUser::currentUser(); 00274 if ( $userID === false ) 00275 { 00276 $userID = $user->attribute( 'contentobject_id' ); 00277 } 00278 00279 if ( $languageCode == false ) 00280 { 00281 $languageCode = eZContentObject::defaultLanguage(); 00282 } 00283 00284 $object = eZContentObject::create( ezi18n( "kernel/contentclass", "New %1", null, array( $this->name( $languageCode ) ) ), 00285 $this->attribute( "id" ), 00286 $userID, 00287 $sectionID, 00288 1, 00289 $languageCode ); 00290 00291 if ( $this->attribute( 'always_available' ) ) 00292 { 00293 $object->setAttribute( 'language_mask', (int)$object->attribute( 'language_mask') | 1 ); 00294 } 00295 00296 $db = eZDB::instance(); 00297 $db->begin(); 00298 00299 $object->store(); 00300 $object->assignDefaultStates(); 00301 $object->setName( ezi18n( "kernel/contentclass", "New %1", null, array( $this->name( $languageCode ) ) ), false, $languageCode ); 00302 00303 if ( !$versionNumber ) 00304 { 00305 $version = $object->createInitialVersion( $userID, $languageCode ); 00306 } 00307 else 00308 { 00309 $version = eZContentObjectVersion::create( $object->attribute( "id" ), $userID, $versionNumber, $languageCode ); 00310 } 00311 if ( $versionStatus !== false ) 00312 { 00313 $version->setAttribute( 'status', $versionStatus ); 00314 } 00315 00316 $version->store(); 00317 00318 foreach ( $attributes as $attribute ) 00319 { 00320 $attribute->instantiate( $object->attribute( 'id' ), $languageCode ); 00321 } 00322 00323 if ( $user->isAnonymous() ) 00324 { 00325 $createdObjectIDList = eZPreferences::value( 'ObjectCreationIDList' ); 00326 if ( !$createdObjectIDList ) 00327 { 00328 $createdObjectIDList = array( $object->attribute( 'id' ) ); 00329 } 00330 else 00331 { 00332 $createdObjectIDList = unserialize( $createdObjectIDList ); 00333 $createdObjectIDList[] = $object->attribute( 'id' ); 00334 } 00335 eZPreferences::setValue( 'ObjectCreationIDList', serialize( $createdObjectIDList ) ); 00336 } 00337 00338 $db->commit(); 00339 return $object; 00340 } 00341 00342 function canInstantiateClasses() 00343 { 00344 $ini = eZINI::instance(); 00345 $enableCaching = $ini->variable( 'RoleSettings', 'EnableCaching' ); 00346 00347 if ( $enableCaching == 'true' ) 00348 { 00349 $http = eZHTTPTool::instance(); 00350 00351 eZExpiryHandler::registerShutdownFunction(); 00352 $handler = eZExpiryHandler::instance(); 00353 $expiredTimeStamp = 0; 00354 if ( $handler->hasTimestamp( 'user-class-cache' ) ) 00355 $expiredTimeStamp = $handler->timestamp( 'user-class-cache' ); 00356 00357 $classesCachedForUser = $http->sessionVariable( 'CanInstantiateClassesCachedForUser' ); 00358 $classesCachedTimestamp = $http->sessionVariable( 'ClassesCachedTimestamp' ); 00359 $user = eZUser::currentUser(); 00360 $userID = $user->id(); 00361 00362 if ( ( $classesCachedTimestamp >= $expiredTimeStamp ) && $classesCachedForUser == $userID ) 00363 { 00364 if ( $http->hasSessionVariable( 'CanInstantiateClasses' ) ) 00365 { 00366 return $http->sessionVariable( 'CanInstantiateClasses' ); 00367 } 00368 } 00369 else 00370 { 00371 // store cache 00372 $http->setSessionVariable( 'CanInstantiateClassesCachedForUser', $userID ); 00373 } 00374 } 00375 $user = eZUser::currentUser(); 00376 $accessResult = $user->hasAccessTo( 'content' , 'create' ); 00377 $accessWord = $accessResult['accessWord']; 00378 $canInstantiateClasses = 1; 00379 if ( $accessWord == 'no' ) 00380 { 00381 $canInstantiateClasses = 0; 00382 } 00383 00384 if ( $enableCaching == 'true' ) 00385 { 00386 $http->setSessionVariable( 'CanInstantiateClasses', $canInstantiateClasses ); 00387 } 00388 return $canInstantiateClasses; 00389 } 00390 00391 // code-template::create-block: can-instantiate-class-list, group-filter, role-caching, class-policy-list, name-instantiate, object-creation, class-sql-creation, static-method 00392 // code-template::auto-generated:START can-instantiate-class-list 00393 // This code is automatically generated from templates/classcreatelist.ctpl 00394 // DO NOT EDIT THIS CODE DIRECTLY, CHANGE THE TEMPLATE FILE INSTEAD 00395 00396 /*! 00397 \static 00398 Finds all classes that the current user can create objects from and returns. 00399 It is also possible to filter the list event more with \a $includeFilter and \a $groupList. 00400 00401 \param $asObject If \c true then it return eZContentClass objects, if not it will 00402 be an associative array with \c name and \c id keys. 00403 \param $includeFilter If \c true then it will include only from class groups defined in 00404 \a $groupList, if not it will exclude those groups. 00405 \param $groupList An array with class group IDs that should be used in filtering, use 00406 \c false if you do not wish to filter at all. 00407 \param $fetchID A unique name for the current fetch, this must be supplied when filtering is 00408 used if you want caching to work. 00409 */ 00410 static function canInstantiateClassList( $asObject = false, $includeFilter = true, $groupList = false, $fetchID = false ) 00411 { 00412 $ini = eZINI::instance(); 00413 $groupArray = array(); 00414 00415 $enableCaching = ( $ini->variable( 'RoleSettings', 'EnableCaching' ) == 'true' ); 00416 if ( is_array( $groupList ) ) 00417 { 00418 if ( $fetchID == false ) 00419 $enableCaching = false; 00420 } 00421 00422 if ( $enableCaching ) 00423 { 00424 $http = eZHTTPTool::instance(); 00425 eZExpiryHandler::registerShutdownFunction(); 00426 $handler = eZExpiryHandler::instance(); 00427 $expiredTimeStamp = 0; 00428 if ( $handler->hasTimestamp( 'user-class-cache' ) ) 00429 $expiredTimeStamp = $handler->timestamp( 'user-class-cache' ); 00430 00431 $classesCachedForUser = $http->sessionVariable( 'ClassesCachedForUser' ); 00432 $classesCachedTimestamp = $http->sessionVariable( 'ClassesCachedTimestamp' ); 00433 00434 $cacheVar = 'CanInstantiateClassList'; 00435 if ( is_array( $groupList ) and $fetchID !== false ) 00436 { 00437 $cacheVar = 'CanInstantiateClassListGroup'; 00438 } 00439 00440 $user = eZUser::currentUser(); 00441 $userID = $user->id(); 00442 if ( ( $classesCachedTimestamp >= $expiredTimeStamp ) && $classesCachedForUser == $userID ) 00443 { 00444 if ( $http->hasSessionVariable( $cacheVar ) ) 00445 { 00446 if ( $fetchID !== false ) 00447 { 00448 // Check if the group contains our ID, if not we need to fetch from DB 00449 $groupArray = $http->sessionVariable( $cacheVar ); 00450 if ( isset( $groupArray[$fetchID] ) ) 00451 { 00452 return $groupArray[$fetchID]; 00453 } 00454 } 00455 else 00456 { 00457 return $http->sessionVariable( $cacheVar ); 00458 } 00459 } 00460 } 00461 else 00462 { 00463 $http->setSessionVariable( 'ClassesCachedForUser' , $userID ); 00464 $http->setSessionVariable( 'ClassesCachedTimestamp', time() ); 00465 } 00466 } 00467 00468 $languageCodeList = eZContentLanguage::fetchLocaleList(); 00469 $allowedLanguages = array( '*' => array() ); 00470 00471 $user = eZUser::currentUser(); 00472 $accessResult = $user->hasAccessTo( 'content' , 'create' ); 00473 $accessWord = $accessResult['accessWord']; 00474 00475 $classIDArray = array(); 00476 $classList = array(); 00477 $fetchAll = false; 00478 if ( $accessWord == 'yes' ) 00479 { 00480 $fetchAll = true; 00481 $allowedLanguages['*'] = $languageCodeList; 00482 } 00483 else if ( $accessWord == 'no' ) 00484 { 00485 // Cannnot create any objects, return empty list. 00486 return $classList; 00487 } 00488 else 00489 { 00490 $policies = $accessResult['policies']; 00491 foreach ( $policies as $policyKey => $policy ) 00492 { 00493 $classIDArrayPart = '*'; 00494 if ( isset( $policy['Class'] ) ) 00495 { 00496 $classIDArrayPart = $policy['Class']; 00497 } 00498 $languageCodeArrayPart = $languageCodeList; 00499 if ( isset( $policy['Language'] ) ) 00500 { 00501 $languageCodeArrayPart = array_intersect( $policy['Language'], $languageCodeList ); 00502 } 00503 00504 if ( $classIDArrayPart == '*' ) 00505 { 00506 $fetchAll = true; 00507 $allowedLanguages['*'] = array_unique( array_merge( $allowedLanguages['*'], $languageCodeArrayPart ) ); 00508 } 00509 else 00510 { 00511 foreach( $classIDArrayPart as $class ) 00512 { 00513 if ( isset( $allowedLanguages[$class] ) ) 00514 { 00515 $allowedLanguages[$class] = array_unique( array_merge( $allowedLanguages[$class], $languageCodeArrayPart ) ); 00516 } 00517 else 00518 { 00519 $allowedLanguages[$class] = $languageCodeArrayPart; 00520 } 00521 } 00522 $classIDArray = array_merge( $classIDArray, array_diff( $classIDArrayPart, $classIDArray ) ); 00523 } 00524 } 00525 } 00526 00527 $db = eZDB::instance(); 00528 00529 $filterTableSQL = ''; 00530 $filterSQL = ''; 00531 // Create extra SQL statements for the class group filters. 00532 if ( is_array( $groupList ) ) 00533 { 00534 if ( count( $groupList ) == 0 ) 00535 { 00536 return $classList; 00537 } 00538 00539 $filterTableSQL = ', ezcontentclass_classgroup ccg'; 00540 $filterSQL = ( " AND" . 00541 " cc.id = ccg.contentclass_id AND" . 00542 " " ); 00543 $filterSQL .= $db->generateSQLINStatement( $groupList, 'ccg.group_id', !$includeFilter, true, 'int' ); 00544 } 00545 00546 $classNameFilter = eZContentClassName::sqlFilter( 'cc' ); 00547 $filterSQL .= " AND cc.id=" . $classNameFilter['from'] . ".contentclass_id"; 00548 00549 if ( $fetchAll ) 00550 { 00551 // If $asObject is true we fetch all fields in class 00552 $fields = $asObject ? "cc.*, $classNameFilter[nameField]" : "cc.id, $classNameFilter[nameField]"; 00553 $rows = $db->arrayQuery( "SELECT DISTINCT $fields " . 00554 "FROM ezcontentclass cc$filterTableSQL, $classNameFilter[from] " . 00555 "WHERE cc.version = " . eZContentClass::VERSION_STATUS_DEFINED . " $filterSQL " . 00556 "ORDER BY $classNameFilter[nameField] ASC" ); 00557 $classList = eZPersistentObject::handleRows( $rows, 'eZContentClass', $asObject ); 00558 } 00559 else 00560 { 00561 // If the constrained class list is empty we are not allowed to create any class 00562 if ( count( $classIDArray ) == 0 ) 00563 { 00564 return $classList; 00565 } 00566 00567 $classIDCondition = $db->generateSQLInStatement( $classIDArray, 'cc.id' ); 00568 // If $asObject is true we fetch all fields in class 00569 $fields = $asObject ? "cc.*, $classNameFilter[nameField]" : "cc.id, $classNameFilter[nameField]"; 00570 $rows = $db->arrayQuery( "SELECT DISTINCT $fields " . 00571 "FROM ezcontentclass cc$filterTableSQL, $classNameFilter[from] " . 00572 "WHERE $classIDCondition AND" . 00573 " cc.version = " . eZContentClass::VERSION_STATUS_DEFINED . " $filterSQL " . 00574 "ORDER BY $classNameFilter[nameField] ASC" ); 00575 $classList = eZPersistentObject::handleRows( $rows, 'eZContentClass', $asObject ); 00576 } 00577 00578 if ( $asObject ) 00579 { 00580 foreach ( $classList as $key => $class ) 00581 { 00582 $id = $class->attribute( 'id' ); 00583 if ( isset( $allowedLanguages[$id] ) ) 00584 { 00585 $languageCodes = array_unique( array_merge( $allowedLanguages['*'], $allowedLanguages[$id] ) ); 00586 } 00587 else 00588 { 00589 $languageCodes = $allowedLanguages['*']; 00590 } 00591 $classList[$key]->setCanInstantiateLanguages( $languageCodes ); 00592 } 00593 } 00594 00595 eZDebugSetting::writeDebug( 'kernel-content-class', $classList, "class list fetched from db" ); 00596 if ( $enableCaching ) 00597 { 00598 if ( $fetchID !== false ) 00599 { 00600 $groupArray[$fetchID] = $classList; 00601 $http->setSessionVariable( $cacheVar, $groupArray ); 00602 } 00603 else 00604 { 00605 $http->setSessionVariable( $cacheVar, $classList ); 00606 } 00607 } 00608 00609 return $classList; 00610 } 00611 00612 // This code is automatically generated from templates/classcreatelist.ctpl 00613 // code-template::auto-generated:END can-instantiate-class-list 00614 00615 /*! 00616 \return The creator of the class as an eZUser object by using the $CreatorID as user ID. 00617 */ 00618 function creator() 00619 { 00620 if ( isset( $this->CreatorID ) and $this->CreatorID ) 00621 { 00622 return eZUser::fetch( $this->CreatorID ); 00623 } 00624 return null; 00625 } 00626 00627 /*! 00628 \return The modifier of the class as an eZUser object by using the $ModifierID as user ID. 00629 */ 00630 function modifier() 00631 { 00632 if ( isset( $this->ModifierID ) and $this->ModifierID ) 00633 { 00634 return eZUser::fetch( $this->ModifierID ); 00635 } 00636 return null; 00637 } 00638 00639 /*! 00640 Find all groups the current class is placed in and returns a list of group objects. 00641 \return An array with eZContentClassGroup objects. 00642 \sa fetchGroupIDList() 00643 */ 00644 function fetchGroupList() 00645 { 00646 $this->InGroups = eZContentClassClassGroup::fetchGroupList( $this->attribute( "id" ), 00647 $this->attribute( "version" ), 00648 true ); 00649 return $this->InGroups; 00650 } 00651 00652 /*! 00653 Find all groups the current class is placed in and returns a list of group IDs. 00654 \return An array with integers (ids). 00655 \sa fetchGroupList() 00656 */ 00657 function fetchGroupIDList() 00658 { 00659 $list = eZContentClassClassGroup::fetchGroupList( $this->attribute( "id" ), 00660 $this->attribute( "version" ), 00661 false ); 00662 $this->InGroupIDs = array(); 00663 foreach ( $list as $item ) 00664 { 00665 $this->InGroupIDs[] = $item['group_id']; 00666 } 00667 return $this->InGroupIDs; 00668 } 00669 00670 /*! 00671 Returns the result from fetchGroupIDList() if class group overrides is 00672 enabled in content.ini. 00673 \return An array with eZContentClassGroup objects or \c false if disabled. 00674 \note \c EnableClassGroupOverride in group \c ContentOverrideSettings from INI file content.ini 00675 controls this behaviour. 00676 */ 00677 function fetchMatchGroupIDList() 00678 { 00679 $contentINI = eZINI::instance( 'content.ini' ); 00680 if( $contentINI->variable( 'ContentOverrideSettings', 'EnableClassGroupOverride' ) == 'true' ) 00681 { 00682 return $this->attribute( 'ingroup_id_list' ); 00683 } 00684 00685 return false; 00686 } 00687 00688 /*! 00689 Finds all Classes in the system and returns them. 00690 \return An array with eZContentClass objects. 00691 */ 00692 static function fetchAllClasses( $asObject = true, $includeFilter = true, $groupList = false ) 00693 { 00694 $filterTableSQL = ''; 00695 $filterSQL = ''; 00696 if ( is_array( $groupList ) ) 00697 { 00698 $filterTableSQL = ', ezcontentclass_classgroup ccg'; 00699 $filterSQL = ( " AND" . 00700 " cc.id = ccg.contentclass_id AND" . 00701 " ccg.group_id " ); 00702 $groupText = implode( ', ', $groupList ); 00703 if ( $includeFilter ) 00704 $filterSQL .= "IN ( $groupText )"; 00705 else 00706 $filterSQL .= "NOT IN ( $groupText )"; 00707 } 00708 00709 $classNameFilter = eZContentClassName::sqlFilter( 'cc' ); 00710 00711 $classList = array(); 00712 $db = eZDb::instance(); 00713 // If $asObject is true we fetch all fields in class 00714 $fields = $asObject ? "cc.*" : "cc.id, $classNameFilter[nameField]"; 00715 $rows = $db->arrayQuery( "SELECT DISTINCT $fields " . 00716 "FROM ezcontentclass cc$filterTableSQL, $classNameFilter[from] " . 00717 "WHERE cc.version = " . eZContentClass::VERSION_STATUS_DEFINED . "$filterSQL AND $classNameFilter[where]" . 00718 "ORDER BY $classNameFilter[nameField] ASC" ); 00719 00720 $classList = eZPersistentObject::handleRows( $rows, 'eZContentClass', $asObject ); 00721 return $classList; 00722 } 00723 00724 /*! 00725 Finds all Class groups in the system and returns them. 00726 \return An array with eZContentClassGroup objects. 00727 \sa fetchGroupList(), fetchGroupIDList() 00728 */ 00729 function fetchAllGroups() 00730 { 00731 $this->AllGroups = eZContentClassGroup::fetchList(); 00732 return $this->AllGroups; 00733 } 00734 00735 /*! 00736 \return true if the class is part of the group \a $groupID 00737 */ 00738 function inGroup( $groupID ) 00739 { 00740 return eZContentClassClassGroup::classInGroup( $this->attribute( 'id' ), 00741 $this->attribute( 'version' ), 00742 $groupID ); 00743 } 00744 00745 /*! 00746 \static 00747 Will remove all temporary classes from the database. 00748 */ 00749 static function removeTemporary() 00750 { 00751 $version = eZContentClass::VERSION_STATUS_TEMPORARY; 00752 $temporaryClasses = eZContentClass::fetchList( $version, true ); 00753 $db = eZDB::instance(); 00754 $db->begin(); 00755 foreach ( $temporaryClasses as $class ) 00756 { 00757 $class->remove( true, $version ); 00758 } 00759 eZPersistentObject::removeObject( eZContentClassAttribute::definition(), 00760 array( 'version' => $version ) ); 00761 00762 $db->commit(); 00763 } 00764 00765 /*! 00766 Get remote id of content node 00767 */ 00768 function remoteID() 00769 { 00770 $remoteID = eZPersistentObject::attribute( 'remote_id', true ); 00771 if ( !$remoteID && 00772 $this->Version == eZContentClass::VERSION_STATUS_DEFINED ) 00773 { 00774 $this->setAttribute( 'remote_id', md5( (string)mt_rand() . (string)time() ) ); 00775 $this->sync( array( 'remote_id' ) ); 00776 $remoteID = eZPersistentObject::attribute( 'remote_id', true ); 00777 } 00778 00779 return $remoteID; 00780 } 00781 00782 /*! 00783 \note If you want to remove a class with all data associated with it (objects/classMembers) 00784 you should use eZContentClassOperations::remove() 00785 */ 00786 function remove( $removeAttributes = false, $version = eZContentClass::VERSION_STATUS_DEFINED ) 00787 { 00788 // If we are not allowed to remove just return false 00789 if ( $this->Version != eZContentClass::VERSION_STATUS_TEMPORARY && !$this->isRemovable() ) 00790 return false; 00791 00792 if ( is_array( $removeAttributes ) or $removeAttributes ) 00793 $this->removeAttributes( $removeAttributes ); 00794 00795 $this->NameList->remove( $this ); 00796 eZPersistentObject::remove(); 00797 } 00798 00799 /*! 00800 Checks if the class can be removed and returns \c true if it can, \c false otherwise. 00801 \sa removableInformation() 00802 */ 00803 function isRemovable() 00804 { 00805 $info = $this->removableInformation( false ); 00806 return count( $info['list'] ) == 0; 00807 } 00808 00809 /*! 00810 Returns information on why the class cannot be removed, 00811 it does the same checks as in isRemovable() but generates 00812 some text in the return array. 00813 \return An array which contains: 00814 - text - Plain text description why this cannot be removed 00815 - list - An array with reasons why this failed, each entry contains: 00816 - text - Plain text description of the reason. 00817 - list - A sublist of reason (e.g from an attribute), is optional. 00818 \param $includeAll Controls whether the returned information will contain all 00819 sources for not being to remove or just the first that it finds. 00820 */ 00821 function removableInformation( $includeAll = true ) 00822 { 00823 $result = array( 'text' => ezi18n( 'kernel/contentclass', "Cannot remove class '%class_name':", 00824 null, array( '%class_name' => $this->attribute( 'name' ) ) ), 00825 'list' => array() ); 00826 $db = eZDB::instance(); 00827 00828 // Check top-level nodes 00829 $rows = $db->arrayQuery( "SELECT ezcot.node_id 00830 FROM ezcontentobject_tree ezcot, ezcontentobject ezco 00831 WHERE ezcot.depth = 1 AND 00832 ezco.contentclass_id = $this->ID AND 00833 ezco.id=ezcot.contentobject_id" ); 00834 if ( count( $rows ) > 0 ) 00835 { 00836 $result['list'][] = array( 'text' => ezi18n( 'kernel/contentclass', 'The class is used by a top-level node and cannot be removed. 00837 You will need to change the class of the node by using the swap functionality.' ) ); 00838 if ( !$includeAll ) 00839 return $result; 00840 } 00841 00842 // Check class attributes 00843 foreach ( $this->fetchAttributes() as $attribute ) 00844 { 00845 $dataType = $attribute->dataType(); 00846 if ( !$dataType->isClassAttributeRemovable( $attribute ) ) 00847 { 00848 $info = $dataType->classAttributeRemovableInformation( $attribute, $includeAll ); 00849 $result['list'][] = $info; 00850 if ( !$includeAll ) 00851 return $result; 00852 } 00853 } 00854 00855 return $result; 00856 } 00857 00858 /*! 00859 \note Removes class attributes 00860 00861 \param removeAtttributes Array of attributes to remove 00862 \param version Version to remove( optional ) 00863 */ 00864 function removeAttributes( $removeAttributes = false, $version = false ) 00865 { 00866 if ( is_array( $removeAttributes ) ) 00867 { 00868 $db = eZDB::instance(); 00869 $db->begin(); 00870 foreach( $removeAttributes as $attribute ) 00871 { 00872 $attribute->removeThis(); 00873 } 00874 $db->commit(); 00875 } 00876 else 00877 { 00878 $contentClassID = $this->ID; 00879 00880 if ( $version === false ) 00881 { 00882 $version = $this->Version; 00883 } 00884 $classAttributes = $this->fetchAttributes( ); 00885 00886 $db = eZDB::instance(); 00887 $db->begin(); 00888 foreach ( $classAttributes as $classAttribute ) 00889 { 00890 $dataType = $classAttribute->dataType(); 00891 $dataType->deleteStoredClassAttribute( $classAttribute, $version ); 00892 } 00893 eZPersistentObject::removeObject( eZContentClassAttribute::definition(), 00894 array( 'contentclass_id' => $contentClassID, 00895 'version' => $version ) ); 00896 $db->commit(); 00897 } 00898 } 00899 00900 function compareAttributes( $attr1, $attr2 ) 00901 { 00902 return ( $attr1->attribute( "placement" ) > $attr2->attribute( "placement" ) ) ? 1 : -1; 00903 } 00904 00905 function adjustAttributePlacements( $attributes ) 00906 { 00907 if ( !is_array( $attributes ) ) 00908 return; 00909 usort( $attributes, array( $this, "compareAttributes" ) ); 00910 $i = 0; 00911 foreach( $attributes as $attribute ) 00912 { 00913 $attribute->setAttribute( "placement", ++$i ); 00914 } 00915 } 00916 00917 function store( $store_childs = false, $fieldFilters = null ) 00918 { 00919 00920 self::expireCache(); 00921 00922 $db = eZDB::instance(); 00923 $db->begin(); 00924 00925 if ( is_array( $store_childs ) || 00926 $store_childs ) 00927 { 00928 if ( is_array( $store_childs ) ) 00929 { 00930 $attributes = $store_childs; 00931 } 00932 else 00933 { 00934 $attributes = $this->fetchAttributes(); 00935 } 00936 00937 foreach( $attributes as $attribute ) 00938 { 00939 if ( is_object ( $attribute ) ) 00940 $attribute->store(); 00941 } 00942 } 00943 00944 eZExpiryHandler::registerShutdownFunction(); 00945 $handler = eZExpiryHandler::instance(); 00946 $handler->setTimestamp( 'user-class-cache', time() ); 00947 $handler->store(); 00948 00949 $this->setAttribute( 'serialized_name_list', $this->NameList->serializeNames() ); 00950 00951 eZPersistentObject::store( $fieldFilters ); 00952 00953 $this->NameList->store( $this ); 00954 00955 $db->commit(); 00956 } 00957 00958 function sync( $fieldFilters = null ) 00959 { 00960 if ( $this->hasDirtyData() ) 00961 $this->store( false, $fieldFilters ); 00962 } 00963 00964 /*! 00965 Initializes this class as a copy of \a $originalClass by 00966 creating new a new name and identifier. 00967 It will check if there are other classes already with this name 00968 in which case it will append a unique number to the name and identifier. 00969 */ 00970 function initializeCopy( &$originalClass ) 00971 { 00972 $name = ezi18n( 'kernel/class', 'Copy of %class_name', null, 00973 array( '%class_name' => $originalClass->attribute( 'name' ) ) ); 00974 $identifier = 'copy_of_' . $originalClass->attribute( 'identifier' ); 00975 $db = eZDB::instance(); 00976 $sql = "SELECT count( ezcontentclass_name.name ) AS count FROM ezcontentclass, ezcontentclass_name WHERE ezcontentclass.id = ezcontentclass_name.contentclass_id AND ezcontentclass_name.name like '" . $db->escapeString( $name ) . "%'"; 00977 $rows = $db->arrayQuery( $sql ); 00978 $count = $rows[0]['count']; 00979 if ( $count > 0 ) 00980 { 00981 ++$count; 00982 $name .= $count; 00983 $identifier .= $count; 00984 } 00985 $this->setName( $name ); 00986 $this->setAttribute( 'identifier', $identifier ); 00987 $this->setAttribute( 'created', time() ); 00988 $user = eZUser::currentUser(); 00989 $userID = $user->attribute( "contentobject_id" ); 00990 $this->setAttribute( 'creator_id', $userID ); 00991 } 00992 00993 /*! 00994 Stores the current class as a defined version, updates the contentobject_name 00995 attribute and recreates the class group entries. 00996 \note It will remove any existing temporary or defined classes before storing. 00997 */ 00998 function storeDefined( $attributes ) 00999 { 01000 $db = eZDB::instance(); 01001 $db->begin(); 01002 01003 $this->removeAttributes( false, eZContentClass::VERSION_STATUS_DEFINED ); 01004 $this->removeAttributes( false, eZContentClass::VERSION_STATUS_TEMPORARY ); 01005 $this->remove( false ); 01006 $this->setVersion( eZContentClass::VERSION_STATUS_DEFINED, $attributes ); 01007 // include_once( "kernel/classes/datatypes/ezuser/ezuser.php" ); 01008 $user = eZUser::currentUser(); 01009 $user_id = $user->attribute( "contentobject_id" ); 01010 $this->setAttribute( "modifier_id", $user_id ); 01011 $this->setAttribute( "modified", time() ); 01012 $this->adjustAttributePlacements( $attributes ); 01013 foreach( $attributes as $attribute ) 01014 { 01015 $attribute->storeDefined(); 01016 } 01017 01018 // Set contentobject_name to something sensible if it is missing 01019 if ( count( $attributes ) > 0 ) 01020 { 01021 $identifier = $attributes[0]->attribute( 'identifier' ); 01022 $identifier = '<' . $identifier . '>'; 01023 if ( trim( $this->attribute( 'contentobject_name' ) ) == '' ) 01024 { 01025 $this->setAttribute( 'contentobject_name', $identifier ); 01026 } 01027 } 01028 01029 // Recreate class member entries 01030 eZContentClassClassGroup::removeClassMembers( $this->ID, eZContentClass::VERSION_STATUS_DEFINED ); 01031 $classgroups = eZContentClassClassGroup::fetchGroupList( $this->ID, eZContentClass::VERSION_STATUS_TEMPORARY ); 01032 foreach( $classgroups as $classgroup ) 01033 { 01034 $classgroup->setAttribute( 'contentclass_version', eZContentClass::VERSION_STATUS_DEFINED ); 01035 $classgroup->store(); 01036 } 01037 eZContentClassClassGroup::removeClassMembers( $this->ID, eZContentClass::VERSION_STATUS_TEMPORARY ); 01038 01039 eZExpiryHandler::registerShutdownFunction(); 01040 $handler = eZExpiryHandler::instance(); 01041 $time = time(); 01042 $handler->setTimestamp( 'user-class-cache', $time ); 01043 $handler->setTimestamp( 'class-identifier-cache', $time ); 01044 $handler->setTimestamp( 'sort-key-cache', $time ); 01045 $handler->store(); 01046 01047 eZContentCacheManager::clearAllContentCache(); 01048 01049 $this->setAttribute( 'serialized_name_list', $this->NameList->serializeNames() ); 01050 eZPersistentObject::store(); 01051 $this->NameList->store( $this ); 01052 01053 $db->commit(); 01054 } 01055 01056 function setVersion( $version, $set_childs = false ) 01057 { 01058 if ( is_array( $set_childs ) or $set_childs ) 01059 { 01060 if ( is_array( $set_childs ) ) 01061 { 01062 $attributes = $set_childs; 01063 } 01064 else 01065 { 01066 $attributes = $this->fetchAttributes(); 01067 } 01068 foreach( $attributes as $attribute ) 01069 { 01070 $attribute->setAttribute( "version", $version ); 01071 } 01072 } 01073 01074 if ( $this->Version != $version ) 01075 $this->NameList->setHasDirtyData(); 01076 01077 $this->setAttribute( "version", $version ); 01078 } 01079 01080 static function exists( $id, $version = eZContentClass::VERSION_STATUS_DEFINED, $userID = false, $useIdentifier = false ) 01081 { 01082 $conds = array( "version" => $version ); 01083 if ( $useIdentifier ) 01084 $conds["identifier"] = $id; 01085 else 01086 $conds["id"] = $id; 01087 if ( $userID !== false and is_numeric( $userID ) ) 01088 $conds["creator_id"] = $userID; 01089 $version_sort = "desc"; 01090 if ( $version == eZContentClass::VERSION_STATUS_DEFINED ) 01091 $conds['version'] = $version; 01092 $rows = eZPersistentObject::fetchObjectList( eZContentClass::definition(), 01093 null, 01094 $conds, 01095 null, 01096 array( "offset" => 0, 01097 "length" => 1 ), 01098 false ); 01099 if ( count( $rows ) > 0 ) 01100 return $rows[0]['id']; 01101 return false; 01102 } 01103 01104 static function fetch( $id, $asObject = true, $version = eZContentClass::VERSION_STATUS_DEFINED, $user_id = false ,$parent_id = null ) 01105 { 01106 global $eZContentClassObjectCache; 01107 01108 // If the object given by its id is not cached or should be returned as array 01109 // then we fetch it from the DB (objects are always cached as arrays). 01110 if ( !isset( $eZContentClassObjectCache[$id] ) or $asObject === false or $version != eZContentClass::VERSION_STATUS_DEFINED ) 01111 { 01112 $conds = array( "id" => $id, 01113 "version" => $version ); 01114 01115 if ( $user_id !== false and is_numeric( $user_id ) ) 01116 $conds["creator_id"] = $user_id; 01117 01118 $version_sort = "desc"; 01119 if ( $version == eZContentClass::VERSION_STATUS_DEFINED ) 01120 $version_sort = "asc"; 01121 $rows = eZPersistentObject::fetchObjectList( eZContentClass::definition(), 01122 null, 01123 $conds, 01124 array( "version" => $version_sort ), 01125 array( "offset" => 0, 01126 "length" => 2 ), 01127 false ); 01128 01129 if ( count( $rows ) == 0 ) 01130 { 01131 $contentClass = null; 01132 return $contentClass; 01133 } 01134 01135 $row = $rows[0]; 01136 $row["version_count"] = count( $rows ); 01137 01138 if ( $asObject ) 01139 { 01140 $contentClass = new eZContentClass( $row ); 01141 if ( $version == eZContentClass::VERSION_STATUS_DEFINED ) 01142 { 01143 $eZContentClassObjectCache[$id] = $contentClass; 01144 } 01145 return $contentClass; 01146 } 01147 else 01148 $contentClass = $row; 01149 } 01150 else 01151 { 01152 $contentClass = $eZContentClassObjectCache[$id]; 01153 } 01154 01155 return $contentClass; 01156 } 01157 01158 static function fetchByRemoteID( $remoteID, $asObject = true, $version = eZContentClass::VERSION_STATUS_DEFINED, $user_id = false ,$parent_id = null ) 01159 { 01160 $conds = array( "remote_id" => $remoteID, 01161 "version" => $version ); 01162 if ( $user_id !== false and is_numeric( $user_id ) ) 01163 $conds["creator_id"] = $user_id; 01164 $version_sort = "desc"; 01165 if ( $version == eZContentClass::VERSION_STATUS_DEFINED ) 01166 $version_sort = "asc"; 01167 $rows = eZPersistentObject::fetchObjectList( eZContentClass::definition(), 01168 null, 01169 $conds, 01170 array( "version" => $version_sort ), 01171 array( "offset" => 0, 01172 "length" => 2 ), 01173 false ); 01174 if ( count( $rows ) == 0 ) 01175 { 01176 $contentClass = null; 01177 return $contentClass; 01178 } 01179 01180 $row = $rows[0]; 01181 $row["version_count"] = count( $rows ); 01182 01183 if ( $asObject ) 01184 { 01185 return new eZContentClass( $row ); 01186 } 01187 01188 return $row; 01189 } 01190 01191 static function fetchByIdentifier( $identifier, $asObject = true, $version = eZContentClass::VERSION_STATUS_DEFINED, $user_id = false ,$parent_id = null ) 01192 { 01193 $conds = array( "identifier" => $identifier, 01194 "version" => $version ); 01195 if ( $user_id !== false and is_numeric( $user_id ) ) 01196 $conds["creator_id"] = $user_id; 01197 $version_sort = "desc"; 01198 if ( $version == eZContentClass::VERSION_STATUS_DEFINED ) 01199 $version_sort = "asc"; 01200 $rows = eZPersistentObject::fetchObjectList( eZContentClass::definition(), 01201 null, 01202 $conds, 01203 array( "version" => $version_sort ), 01204 array( "offset" => 0, 01205 "length" => 2 ), 01206 false ); 01207 if ( count( $rows ) == 0 ) 01208 { 01209 $contentClass = null; 01210 return $contentClass; 01211 } 01212 01213 $row = $rows[0]; 01214 $row["version_count"] = count( $rows ); 01215 01216 if ( $asObject ) 01217 { 01218 return new eZContentClass( $row ); 01219 } 01220 return $row; 01221 } 01222 01223 /*! 01224 \static 01225 */ 01226 static function fetchList( $version = eZContentClass::VERSION_STATUS_DEFINED, $asObject = true, $user_id = false, 01227 $sorts = null, $fields = null, $classFilter = false, $limit = null ) 01228 { 01229 $conds = array(); 01230 $custom_fields = null; 01231 $custom_tables = null; 01232 $custom_conds = null; 01233 01234 if ( is_numeric( $version ) ) 01235 $conds["version"] = $version; 01236 if ( $user_id !== false and is_numeric( $user_id ) ) 01237 $conds["creator_id"] = $user_id; 01238 if ( $classFilter ) 01239 { 01240 $classIDCount = 0; 01241 $classIdentifierCount = 0; 01242 01243 $classIDFilter = array(); 01244 $classIdentifierFilter = array(); 01245 foreach ( $classFilter as $classType ) 01246 { 01247 if ( is_numeric( $classType ) ) 01248 { 01249 $classIDFilter[] = $classType; 01250 $classIDCount++; 01251 } 01252 else 01253 { 01254 $classIdentifierFilter[] = $classType; 01255 $classIdentifierCount++; 01256 } 01257 } 01258 01259 if ( $classIDCount > 1 ) 01260 $conds['id'] = array( $classIDFilter ); 01261 else if ( $classIDCount == 1 ) 01262 $conds['id'] = $classIDFilter[0]; 01263 if ( $classIdentifierCount > 1 ) 01264 $conds['identifier'] = array( $classIdentifierFilter ); 01265 else if ( $classIdentifierCount == 1 ) 01266 $conds['identifier'] = $classIdentifierFilter[0]; 01267 } 01268 01269 if ( $sorts && isset( $sorts['name'] ) ) 01270 { 01271 $nameFiler = eZContentClassName::sqlFilter( 'ezcontentclass' ); 01272 $custom_tables = array( $nameFiler['from'] ); 01273 $custom_conds = "AND " . $nameFiler['where']; 01274 $custom_fields = array( $nameFiler['nameField'] ); 01275 01276 $sorts[$nameFiler['orderBy']] = $sorts['name']; 01277 unset( $sorts['name'] ); 01278 } 01279 01280 return eZPersistentObject::fetchObjectList( eZContentClass::definition(), 01281 $fields, 01282 $conds, 01283 $sorts, 01284 $limit, 01285 $asObject, 01286 false, 01287 $custom_fields, 01288 $custom_tables, 01289 $custom_conds ); 01290 } 01291 01292 /*! 01293 Returns all attributes as an associative array with the key taken from the attribute identifier. 01294 */ 01295 function dataMap() 01296 { 01297 if ( !isset( $this->DataMap[$this->Version] ) ) 01298 { 01299 $attributes = $this->fetchAttributes( false, true, $this->Version ); 01300 foreach ( $attributes as $attribute ) 01301 { 01302 $this->DataMap[$this->Version][$attribute->attribute( 'identifier' )] = $attribute; 01303 } 01304 } 01305 return $this->DataMap[$this->Version]; 01306 } 01307 01308 function fetchAttributes( $id = false, $asObject = true, $version = eZContentClass::VERSION_STATUS_DEFINED ) 01309 { 01310 if ( $id === false ) 01311 { 01312 $id = $this->ID; 01313 $version = $this->Version; 01314 } 01315 01316 return eZContentClassAttribute::fetchFilteredList( array( "contentclass_id" => $id, 01317 "version" => $version ), 01318 $asObject ); 01319 } 01320 01321 /*! 01322 Fetch class attribute by identifier, return null if none exist. 01323 01324 \param attribute identifier. 01325 01326 \return Class Attribute, null if none matched 01327 */ 01328 function fetchAttributeByIdentifier( $identifier, $asObject = true ) 01329 { 01330 $attributeArray = eZContentClassAttribute::fetchFilteredList( array( 'contentclass_id' => $this->ID, 01331 'version' => $this->Version, 01332 'identifier' => $identifier ), $asObject ); 01333 if ( count( $attributeArray ) > 0 ) 01334 { 01335 return $attributeArray[0]; 01336 } 01337 return null; 01338 } 01339 01340 function fetchSearchableAttributes( $id = false, $asObject = true, $version = eZContentClass::VERSION_STATUS_DEFINED ) 01341 { 01342 if ( $id === false ) 01343 { 01344 $id = $this->ID; 01345 $version = $this->Version; 01346 } 01347 01348 return eZContentClassAttribute::fetchFilteredList( array( "contentclass_id" => $id, 01349 "is_searchable" => 1, 01350 "version" => $version ), $asObject ); 01351 } 01352 01353 function versionStatus() 01354 { 01355 01356 if ( $this->VersionCount == 1 ) 01357 { 01358 if ( $this->Version == eZContentClass::VERSION_STATUS_TEMPORARY ) 01359 { 01360 return eZContentClass::VERSION_STATUS_TEMPORARY; 01361 } 01362 return eZContentClass::VERSION_STATUS_DEFINED; 01363 } 01364 return eZContentClass::VERSION_STATUS_MODIFIED; 01365 } 01366 01367 /*! 01368 \deprecated 01369 \return The version count for the class if has been determined. 01370 */ 01371 function versionCount() 01372 { 01373 return $this->VersionCount; 01374 } 01375 01376 /*! 01377 Will generate a name for the content object based on the class 01378 settings for content object. 01379 */ 01380 function contentObjectName( $contentObject, $version = false, $translation = false ) 01381 { 01382 $contentObjectNamePattern = $this->ContentObjectName; 01383 01384 $nameResolver = new eZNamePatternResolver( $contentObjectNamePattern, $contentObject, $version, $translation ); 01385 $contentObjectName = $nameResolver->resolveNamePattern(); 01386 01387 return $contentObjectName; 01388 } 01389 01390 /* 01391 Will generate a name for the url alias based on the class 01392 settings for content object. 01393 */ 01394 function urlAliasName( $contentObject, $version = false, $translation = false ) 01395 { 01396 if ( $this->URLAliasName ) 01397 { 01398 $urlAliasNamePattern = $this->URLAliasName; 01399 } 01400 else 01401 { 01402 $urlAliasNamePattern = $this->ContentObjectName; 01403 } 01404 01405 $nameResolver = new eZNamePatternResolver( $urlAliasNamePattern, $contentObject, $version, $translation ); 01406 $urlAliasName = $nameResolver->resolveNamePattern(); 01407 01408 return $urlAliasName; 01409 } 01410 01411 /*! 01412 Generates a name for the content object based on the content object name pattern 01413 and data map of an object. 01414 */ 01415 function buildContentObjectName( $contentObjectName, $dataMap, $tmpTags = false ) 01416 { 01417 preg_match_all( "|<[^>]+>|U", 01418 $contentObjectName, 01419 $tagMatchArray ); 01420 01421 foreach ( $tagMatchArray[0] as $tag ) 01422 { 01423 $tagName = str_replace( "<", "", $tag ); 01424 $tagName = str_replace( ">", "", $tagName ); 01425 01426 $tagParts = explode( '|', $tagName ); 01427 01428 $namePart = ""; 01429 foreach ( $tagParts as $name ) 01430 { 01431 // get the value of the attribute to use in name 01432 if ( isset( $dataMap[$name] ) ) 01433 { 01434 $namePart = $dataMap[$name]->title(); 01435 if ( $namePart != "" ) 01436 break; 01437 } 01438 elseif ( $tmpTags && isset( $tmpTags[$name] ) && $tmpTags[$name] != '' ) 01439 { 01440 $namePart = $tmpTags[$name]; 01441 break; 01442 } 01443 01444 } 01445 01446 // replace tag with object name part 01447 $contentObjectName = str_replace( $tag, $namePart, $contentObjectName ); 01448 } 01449 return $contentObjectName; 01450 } 01451 01452 /*! 01453 \return will return the number of objects published by this class. 01454 */ 01455 function objectCount() 01456 { 01457 $db = eZDB::instance(); 01458 01459 $countRow = $db->arrayQuery( 'SELECT count(*) AS count FROM ezcontentobject '. 01460 'WHERE contentclass_id='.$this->ID ." and status = " . eZContentObject::STATUS_PUBLISHED ); 01461 01462 return $countRow[0]['count']; 01463 } 01464 01465 /*! 01466 \return will return the list of objects published by this class. 01467 */ 01468 function objectList() 01469 { 01470 return eZContentObject::fetchSameClassList( $this->ID ); 01471 } 01472 01473 /*! 01474 \return Sets the languages which are allowed to be instantiated for the class. 01475 Used only for the content/ fetch function. 01476 */ 01477 function setCanInstantiateLanguages( $languageCodes ) 01478 { 01479 $this->CanInstantiateLanguages = $languageCodes; 01480 } 01481 01482 function canInstantiateLanguages() 01483 { 01484 if ( is_array( $this->CanInstantiateLanguages ) ) 01485 { 01486 return array_intersect( eZContentLanguage::prioritizedLanguageCodes(), $this->CanInstantiateLanguages ); 01487 } 01488 return array(); 01489 } 01490 01491 /*! 01492 \static 01493 Returns a contentclass name from serialized array \a $serializedNameList using 01494 top language from siteaccess language list or 'always available' name 01495 from \a $serializedNameList. 01496 01497 \return string with contentclass name. 01498 */ 01499 static function nameFromSerializedString( $serializedNameList ) 01500 { 01501 return eZContentClassNameList::nameFromSerializedString( $serializedNameList ); 01502 } 01503 01504 function hasNameInLanguage( $languageLocale ) 01505 { 01506 $hasName = $this->NameList->hasNameInLocale( $languageLocale ); 01507 return $hasName; 01508 } 01509 01510 /*! 01511 Returns a contentclass name in \a $languageLocale language. 01512 Uses siteaccess language list or 'always available' language if \a $languageLocale is 'false'. 01513 01514 \return string with contentclass name. 01515 */ 01516 function name( $languageLocale = false ) 01517 { 01518 return $this->NameList->name( $languageLocale ); 01519 } 01520 01521 function setName( $name, $languageLocale = false ) 01522 { 01523 if ( !$languageLocale ) 01524 $languageLocale = $this->topPriorityLanguageLocale(); 01525 $this->NameList->setNameByLanguageLocale( $name, $languageLocale ); 01526 01527 $languageID = eZContentLanguage::idByLocale( $languageLocale ); 01528 $languageMask = $this->attribute( 'language_mask' ); 01529 $this->setAttribute( 'language_mask', $languageMask | $languageID ); 01530 } 01531 01532 function setAlwaysAvailableLanguageID( $languageID, $updateChilds = true ) 01533 { 01534 $db = eZDB::instance(); 01535 $db->begin(); 01536 01537 $languageLocale = false; 01538 if ( $languageID ) 01539 { 01540 $language = eZContentLanguage::fetch( $languageID ); 01541 $languageLocale = $language->attribute( 'locale' ); 01542 } 01543 01544 if ( $languageID ) 01545 { 01546 $this->setAttribute( 'language_mask', (int)$this->attribute( 'language_mask' ) | 1 ); 01547 $this->NameList->setAlwaysAvailableLanguage( $languageLocale ); 01548 } 01549 else 01550 { 01551 $this->setAttribute( 'language_mask', (int)$this->attribute( 'language_mask' ) & ~1 ); 01552 $this->NameList->setAlwaysAvailableLanguage( false ); 01553 } 01554 $this->store(); 01555 01556 $classID = $this->attribute( 'id' ); 01557 $version = $this->attribute( 'version' ); 01558 01559 $attributes = $this->fetchAttributes(); 01560 foreach( $attributes as $attribute ) 01561 { 01562 $attribute->setAlwaysAvailableLanguage( $languageLocale ); 01563 $attribute->store(); 01564 } 01565 01566 // reset 'always available' flag 01567 $sql = "UPDATE ezcontentclass_name SET language_id="; 01568 if ( $db->databaseName() == 'oracle' ) 01569 { 01570 $sql .= "bitand( language_id, -2 )"; 01571 } 01572 else 01573 { 01574 $sql .= "language_id & ~1"; 01575 } 01576 $sql .= " WHERE contentclass_id = '$classID' AND contentclass_version = '$version'"; 01577 $db->query( $sql ); 01578 01579 if ( $languageID != false ) 01580 { 01581 $newLanguageID = $languageID | 1; 01582 01583 $sql = "UPDATE ezcontentclass_name 01584 SET language_id='$newLanguageID' 01585 WHERE language_id='$languageID' AND contentclass_id = '$classID' AND contentclass_version = '$version'"; 01586 $db->query( $sql ); 01587 } 01588 01589 $db->commit(); 01590 } 01591 01592 function clearAlwaysAvailableLanguageID() 01593 { 01594 $this->setAlwaysAvailableLanguageID( false ); 01595 } 01596 01597 /*! 01598 Wrapper for eZContentClassNameList::languages. 01599 */ 01600 function languages() 01601 { 01602 return $this->NameList->languages(); 01603 } 01604 01605 /*! 01606 Wrapper for eZContentClassNameList::prioritizedLanguages. 01607 */ 01608 function prioritizedLanguages() 01609 { 01610 return $this->NameList->prioritizedLanguages(); 01611 } 01612 01613 function prioritizedLanguagesJsArray() 01614 { 01615 return $this->NameList->prioritizedLanguagesJsArray(); 01616 } 01617 01618 /*! 01619 Wrapper for eZContentClassNameList::untranslatedLanguages. 01620 */ 01621 function canCreateLanguages() 01622 { 01623 return $this->NameList->untranslatedLanguages(); 01624 } 01625 01626 /*! 01627 Wrapper for eZContentClassNameList::topPriorityLanguageLocale. 01628 */ 01629 function topPriorityLanguageLocale() 01630 { 01631 return $this->NameList->topPriorityLanguageLocale(); 01632 } 01633 01634 /*! 01635 Wrapper for eZContentClassNameList::alwaysAvailableLanguage. 01636 01637 \return 'language' object. 01638 */ 01639 function alwaysAvailableLanguage() 01640 { 01641 return $this->NameList->alwaysAvailableLanguage(); 01642 } 01643 01644 /*! 01645 Wrapper for eZContentClassNameList::alwaysAvailableLanguageLocale. 01646 01647 \return 'language' object. 01648 */ 01649 function alwaysAvailableLanguageLocale() 01650 { 01651 $language = $this->NameList->alwaysAvailableLanguageLocale(); 01652 return $language; 01653 } 01654 01655 function nameList() 01656 { 01657 return $this->NameList->nameList(); 01658 } 01659 01660 /*! 01661 Removes translated name for specified by \a $languageID language. 01662 */ 01663 function removeTranslation( $languageID ) 01664 { 01665 $language = eZContentLanguage::fetch( $languageID ); 01666 01667 if ( !$language ) 01668 { 01669 return false; 01670 } 01671 01672 // check if it is not the initial language 01673 $classInitialLanguageID = $this->attribute( 'initial_language_id' ); 01674 if ( $classInitialLanguageID == $languageID ) 01675 { 01676 return false; 01677 } 01678 01679 $db = eZDB::instance(); 01680 $db->begin(); 01681 01682 $classID = $this->attribute( 'id' ); 01683 $languageID = $language->attribute( 'id' ); 01684 01685 // change language_mask of the object 01686 $languageMask = (int) $this->attribute( 'language_mask' ); 01687 $languageMask = (int) $languageMask & ~ (int) $languageID; 01688 $this->setAttribute( 'language_mask', $languageMask ); 01689 01690 // Remove all names in the language 01691 $db->query( "DELETE FROM ezcontentclass_name 01692 WHERE contentclass_id='$classID' 01693 AND language_id='$languageID'" ); 01694 01695 $languageLocale = $language->attribute( 'locale' ); 01696 $this->NameList->removeName( $languageLocale ); 01697 01698 $this->store(); 01699 01700 // Remove names for attributes in the language 01701 $attributes = $this->fetchAttributes(); 01702 foreach ( $attributes as $attribute ) 01703 { 01704 $attribute->removeTranslation( $languageLocale ); 01705 $attribute->store(); 01706 } 01707 01708 $db->commit(); 01709 01710 return true; 01711 } 01712 01713 /** 01714 * Resolves the string class identifier $identifier to its numeric value 01715 * Use {@link eZContentObjectTreeNode::classIDByIdentifier()} for < 4.1. 01716 * If multiple classes have the same identifier, the first found is returned. 01717 * 01718 * @static 01719 * @since Version 4.1 01720 * @param string|array $identifier identifier string or array of identifiers (array support added in 4.1.1) 01721 * @return int|false Returns classid or false 01722 */ 01723 public static function classIDByIdentifier( $identifier ) 01724 { 01725 $identifierHash = self::classIdentifiersHash(); 01726 01727 if ( is_array( $identifier ) ) 01728 { 01729 $idList = array(); 01730 foreach( $identifier as $identifierItem ) 01731 { 01732 if ( isset( $identifierHash[$identifierItem] ) ) 01733 $idList[] = $identifierHash[$identifierItem]; 01734 else if ( is_numeric( $identifierItem ) ) // to be able to pass mixed arrays 01735 $idList[] = $identifierItem; 01736 } 01737 return $idList; 01738 } 01739 else if ( isset( $identifierHash[$identifier] ) ) 01740 return $identifierHash[$identifier]; 01741 else 01742 return false; 01743 } 01744 01745 /** 01746 * Resolves the numeric class identifier $id to its string value 01747 * 01748 * @static 01749 * @since Version 4.1 01750 * @return string|false Returns classidentifier or false 01751 */ 01752 public static function classIdentifierByID( $id ) 01753 { 01754 $identifierHash = array_flip( self::classIdentifiersHash() ); 01755 01756 if ( isset( $identifierHash[$id] ) ) 01757 return $identifierHash[$id]; 01758 else 01759 return false; 01760 } 01761 01762 /** 01763 * Returns the class identifier hash for the current database. 01764 * If it is outdated or non-existent, the method updates/generates the file 01765 * 01766 * @static 01767 * @since Version 4.1 01768 * @access protected 01769 * @return array Returns hash of classidentifier => classid 01770 */ 01771 protected static function classIdentifiersHash() 01772 { 01773 if ( self::$identifierHash === null ) 01774 { 01775 $db = eZDB::instance(); 01776 $dbName = md5( $db->DB ); 01777 01778 $cacheDir = eZSys::cacheDirectory(); 01779 $phpCache = new eZPHPCreator( $cacheDir, 01780 'classidentifiers_' . $dbName . '.php', 01781 '', 01782 array( 'clustering' => 'classidentifiers' ) ); 01783 01784 eZExpiryHandler::registerShutdownFunction(); 01785 $handler = eZExpiryHandler::instance(); 01786 $expiryTime = 0; 01787 if ( $handler->hasTimestamp( 'class-identifier-cache' ) ) 01788 { 01789 $expiryTime = $handler->timestamp( 'class-identifier-cache' ); 01790 } 01791 01792 if ( $phpCache->canRestore( $expiryTime ) ) 01793 { 01794 $var = $phpCache->restore( array( 'identifierHash' => 'identifier_hash' ) ); 01795 self::$identifierHash = $var['identifierHash']; 01796 } 01797 else 01798 { 01799 // Fetch identifier/id pair from db 01800 $query = "SELECT id, identifier FROM ezcontentclass where version=0"; 01801 $identifierArray = $db->arrayQuery( $query ); 01802 01803 self::$identifierHash = array(); 01804 foreach ( $identifierArray as $identifierRow ) 01805 { 01806 self::$identifierHash[$identifierRow['identifier']] = $identifierRow['id']; 01807 } 01808 01809 // Store identifier list to cache file 01810 $phpCache->addVariable( 'identifier_hash', self::$identifierHash ); 01811 $phpCache->store(); 01812 } 01813 } 01814 return self::$identifierHash; 01815 } 01816 01817 /*! 01818 Returns an array of IDs of classes containing a specified datatype 01819 01820 \param $dataTypeString a datatype identification string 01821 */ 01822 static function fetchIDListContainingDatatype( $dataTypeString ) 01823 { 01824 $db = eZDB::instance(); 01825 01826 $version = self::VERSION_STATUS_DEFINED; 01827 $escapedDataTypeString = $db->escapeString( $dataTypeString ); 01828 01829 $sql = "SELECT DISTINCT contentclass_id 01830 FROM ezcontentclass_attribute 01831 WHERE version=$version 01832 AND data_type_string='$escapedDataTypeString'"; 01833 01834 $classIDArray = $db->arrayQuery( $sql, array( 'column' => 'contentclass_id' ) ); 01835 return $classIDArray; 01836 } 01837 01838 /** 01839 * Expires in-memory cache for eZContentClass. 01840 * 01841 * Clears cache for fetched eZContentClass objects, 01842 * class identifiers and class attributes. 01843 * 01844 * @since 4.1.4 01845 */ 01846 public static function expireCache() 01847 { 01848 unset( $GLOBALS['eZContentClassObjectCache'] ); 01849 self::$identifierHash = null; 01850 eZContentClassAttribute::expireCache(); 01851 } 01852 01853 /** 01854 * Computes the version history limit for a content class 01855 * 01856 * @param mixed $class 01857 * Content class ID, content class identifier or content class object 01858 * @return int 01859 * @since 4.2 01860 */ 01861 public static function versionHistoryLimit( $class ) 01862 { 01863 // default version limit 01864 $contentINI = eZINI::instance( 'content.ini' ); 01865 $versionLimit = $contentINI->variable( 'VersionManagement', 'DefaultVersionHistoryLimit' ); 01866 01867 // version limit can't be < 2 01868 if ( $versionLimit < 2 ) 01869 { 01870 eZDebug::writeWarning( "Global version history limit must be equal to or higher than 2", __METHOD__ ); 01871 $versionLimit = 2; 01872 } 01873 01874 // we need to take $class down to a class ID 01875 if ( is_numeric( $class ) ) 01876 { 01877 if (!eZContentClass::classIdentifierByID( $class ) ) 01878 { 01879 eZDebug::writeWarning( "class integer parameter doesn't match any content class ID", __METHOD__ ); 01880 return $versionLimit; 01881 } 01882 $classID = (int)$class; 01883 } 01884 // literal identifier 01885 elseif ( is_string( $class ) ) 01886 { 01887 $classID = eZContentClass::classIDByIdentifier( $class ); 01888 if ( !$classID ) 01889 { 01890 eZDebug::writeWarning( "class string parameter doesn't match any content class identifier", __METHOD__ ); 01891 return $versionLimit; 01892 } 01893 } 01894 // eZContentClass object 01895 elseif ( is_object( $class ) ) 01896 { 01897 if ( !$class instanceof eZContentClass ) 01898 { 01899 eZDebug::writeWarning( "class object parameter is not an eZContentClass", __METHOD__ ); 01900 return $versionLimit; 01901 } 01902 else 01903 { 01904 $classID = $class->attribute( 'id' ); 01905 } 01906 } 01907 01908 $classLimitSetting = $contentINI->variable( 'VersionManagement', 'VersionHistoryClass' ); 01909 $classArray = array_keys( $classLimitSetting ); 01910 $limitsArray = array_values( $classLimitSetting ); 01911 01912 $classArray = eZContentClass::classIDByIdentifier( $classArray ); 01913 01914 foreach ( $classArray as $index => $id ) 01915 { 01916 if ( $id == $classID ) 01917 { 01918 $limit = $limitsArray[$index]; 01919 // version limit can't be < 2 01920 if ( $limit < 2 ) 01921 { 01922 $classIdentifier = eZContentClass::classIdentifierByID( $classID ); 01923 eZDebug::writeWarning( "Version history limit for class {$classIdentifier} must be equal to or higher than 2", __METHOD__ ); 01924 $limit = 2; 01925 } 01926 $versionLimit = $limit; 01927 } 01928 } 01929 01930 return $versionLimit; 01931 } 01932 01933 /// \privatesection 01934 public $ID; 01935 // serialized array of translated class names 01936 public $SerializedNameList; 01937 // unserialized class names 01938 public $NameList; 01939 public $Identifier; 01940 public $ContentObjectName; 01941 public $Version; 01942 public $VersionCount; 01943 public $CreatorID; 01944 public $ModifierID; 01945 public $Created; 01946 public $Modified; 01947 public $InGroups; 01948 public $AllGroups; 01949 public $IsContainer; 01950 public $CanInstantiateLanguages; 01951 public $LanguageMask; 01952 01953 /** 01954 * In-memory cache for class identifiers / id matching 01955 **/ 01956 private static $identifierHash = null; 01957 } 01958 01959 ?>