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