eZ Publish  [trunk]
ezcontentlanguage.php
Go to the documentation of this file.
00001 <?php
00002 /**
00003  * File containing the eZContentLanguage class.
00004  *
00005  * @copyright Copyright (C) 1999-2012 eZ Systems AS. All rights reserved.
00006  * @license http://www.gnu.org/licenses/gpl-2.0.txt GNU General Public License v2
00007  * @version //autogentag//
00008  * @package kernel
00009  */
00010 
00011 class eZContentLanguage extends eZPersistentObject
00012 {
00013     const MAX_COUNT = 30;
00014 
00015     /**
00016      * Constructor.
00017      *
00018      * \param row Parameter passed to the constructor of eZPersistentObject.
00019      */
00020     function eZContentLanguage( $row = array() )
00021     {
00022         $this->eZPersistentObject( $row );
00023     }
00024 
00025     /**
00026      * Persistent object's definition.
00027      */
00028     static function definition()
00029     {
00030         static $definition = array( 'fields' => array( 'id' => array( 'name' => 'ID',
00031                                                         'datatype' => 'integer',
00032                                                         'required' => true ),
00033                                          'name' => array( 'name' => 'Name',
00034                                                           'datatype' => 'string',
00035                                                           'required' => true ),
00036                                          'locale' => array( 'name' => 'Locale',
00037                                                             'datatype' => 'string',
00038                                                             'required' => true ),
00039                                          'disabled' => array( 'name' => 'Disabled',     /* disabled is reserved for the future */
00040                                                               'datatype' => 'integer',
00041                                                               'default' => 0,
00042                                                               'required' => false ) ),
00043                       'keys' => array( 'id' ),
00044                       'function_attributes' => array( 'translation' => 'translation',
00045                                                       'locale_object' => 'localeObject',
00046                                                       'class_count' => 'classCount',
00047                                                       'object_count' => 'objectCount' ),
00048                       'sort' => array( 'name' => 'asc' ),
00049                       'class_name' => 'eZContentLanguage',
00050                       'name' => 'ezcontent_language' );
00051         return $definition;
00052     }
00053 
00054     /**
00055      * Adds new language to the site.
00056      *
00057      * \param locale Locale code (e.g. 'slk-SK') of language to add.
00058      * \param name Optional. Name of the language. If not specified, the international language name for the $locale locale
00059      *             will be used.
00060      * \return eZContentLanguage object of the added language (or the existing one if specified language has been already used)
00061      *         or false in case of any error (invalid locale code or already reached eZContentLanguage::MAX_COUNT languages).
00062      * \static
00063      */
00064     static function addLanguage( $locale, $name = null )
00065     {
00066         $localeObject = eZLocale::instance( $locale );
00067         if ( !$localeObject )
00068         {
00069             eZDebug::writeError( "No such locale $locale!", __METHOD__ );
00070             return false;
00071         }
00072 
00073         if ( $name === null )
00074         {
00075             $name = $localeObject->attribute( 'intl_language_name' );
00076         }
00077 
00078         $db = eZDB::instance();
00079 
00080         $languages = eZContentLanguage::fetchList( true );
00081 
00082         if ( ( $existingLanguage = eZContentLanguage::fetchByLocale( $locale ) ) )
00083         {
00084             eZDebug::writeWarning( "Language '$locale' already exists!", __METHOD__ );
00085             return $existingLanguage;
00086         }
00087 
00088         if ( count( $languages ) >= eZContentLanguage::MAX_COUNT )
00089         {
00090             eZDebug::writeError( 'Too many languages, cannot add more!', __METHOD__ );
00091             return false;
00092         }
00093 
00094         $db->lock( 'ezcontent_language' );
00095 
00096         $idSum = 0;
00097         foreach( $languages as $language )
00098         {
00099             $idSum += $language->attribute( 'id' );
00100         }
00101 
00102         // ID 1 is reserved
00103         $candidateId = 2;
00104         while ( $idSum & $candidateId )
00105         {
00106             $candidateId *= 2;
00107         }
00108 
00109         $newLanguage = new eZContentLanguage( array(
00110                                                   'id' => $candidateId,
00111                                                   'locale' => $locale,
00112                                                   'name' => $name,
00113                                                   'disabled' => 0 ) );
00114         $newLanguage->store();
00115 
00116         $db->unlock();
00117 
00118         eZContentLanguage::fetchList( true );
00119 
00120         // clear the cache
00121         eZContentCacheManager::clearAllContentCache();
00122 
00123         return $newLanguage;
00124     }
00125 
00126     /**
00127      * Removes the language specified by ID.
00128      *
00129      * \param id ID of the language to be removed.
00130      * \return True if the language was removed from the site, false otherwise.
00131      * \static
00132      */
00133     static function removeLanguage( $id )
00134     {
00135         $language = eZContentLanguage::fetch( $id );
00136         if ( $language )
00137         {
00138             return $language->removeThis();
00139         }
00140         else
00141         {
00142             return false;
00143         }
00144     }
00145 
00146     /**
00147      * Removes the language if there is no object having translation in it.
00148      *
00149      * \return True if the language was removed from the site, false otherwise.
00150      */
00151     function removeThis()
00152     {
00153         if ( ($this->objectCount() > 0) or ($this->classCount() > 0) )
00154         {
00155             return false;
00156         }
00157 
00158         eZPersistentObject::remove();
00159 
00160         eZContentCacheManager::clearAllContentCache();
00161 
00162         eZContentLanguage::fetchList( true );
00163 
00164         return true;
00165     }
00166 
00167     /**
00168      * Fetches the list of the languages used on the site.
00169      *
00170      * \param forceReloading Optional. If true, the list will be fetched from database even if it is cached in memory.
00171      *                       Default value is false.
00172      * \return Array of the eZContentLanguage objects of languages used on the site.
00173      * \static
00174      */
00175     static function fetchList( $forceReloading = false )
00176     {
00177         if( isset( $GLOBALS['eZContentLanguageList'] ) && $forceReloading === false )
00178             return $GLOBALS['eZContentLanguageList'];
00179 
00180         $cachePath = eZSys::cacheDirectory() . '/ezcontentlanguage_cache.php';
00181         $clusterFileHandler = eZClusterFileHandler::instance( $cachePath );
00182 
00183         if( $forceReloading || !$clusterFileHandler->fileExists( $cachePath ) )
00184         {
00185             $languages = eZPersistentObject::fetchObjectList( eZContentLanguage::definition() );
00186             $clusterFileHandler->fileStoreContents( $cachePath, serialize( $languages ), 'content', 'php' );
00187         }
00188         else
00189         {
00190             $languages = unserialize( $clusterFileHandler->fetchContents() );
00191             // If for some reason unserialize operation fails, we force the cache file to regenerate
00192             // See http://issues.ez.no/18613
00193             if ( $languages === false )
00194             {
00195                 eZDebug::writeError(
00196                     "An error occurred while reading content language cache file $cachePath. File is being re-generated",
00197                     __METHOD__
00198                 );
00199                 return self::fetchList( true );
00200             }
00201         }
00202 
00203         unset( $GLOBALS['eZContentLanguageList'] );
00204         unset( $GLOBALS['eZContentLanguageMask'] );
00205         $GLOBALS['eZContentLanguageList'] = array();
00206         $mask = 1; // we want have 0-th bit set too!
00207         foreach ( $languages as $language )
00208         {
00209             $GLOBALS['eZContentLanguageList'][$language->attribute( 'id' )] = $language;
00210             $mask += $language->attribute( 'id' );
00211         }
00212 
00213         $GLOBALS['eZContentLanguageMask'] = $mask;
00214 
00215         return $GLOBALS['eZContentLanguageList'];
00216     }
00217 
00218     /**
00219      * Fetches the array with names and IDs of the languages used on the site. This method is used by the permission system.
00220      *
00221      * \param forceReloading Optional. If true, the list will be fetched from database even if it is cached in memory.
00222      *                       Default value is false.
00223      * \return Array with names and IDs of the languages used on the site.
00224      * \static
00225      */
00226     static function fetchLimitationList( $forceReloading = false )
00227     {
00228         $languages = array();
00229         foreach ( eZContentLanguage::fetchList( $forceReloading ) as $language )
00230         {
00231             $languages[] = array( 'name' => $language->attribute( 'name' ),
00232                                   'id' => $language->attribute( 'locale' ) );
00233         }
00234         return $languages;
00235     }
00236 
00237    /**
00238      * Fetches the array of locale codes of the languages used on the site.
00239      *
00240      * \return Array of locale codes of the languages used on the site.
00241      * \static
00242      */
00243     static function fetchLocaleList()
00244     {
00245         $languages = eZContentLanguage::fetchList();
00246         $localeList = array();
00247 
00248         foreach ( $languages as $language )
00249         {
00250             $localeList[] = $language->attribute( 'locale' );
00251         }
00252 
00253         return $localeList;
00254     }
00255 
00256     /**
00257      * Fetches the language identified by ID.
00258      *
00259      * \param id Identifier of the language to fetch.
00260      * \return eZContentLanguage object of language identified by ID $id.
00261      * \static
00262      */
00263     static function fetch( $id )
00264     {
00265         $languages = eZContentLanguage::fetchList();
00266 
00267         return isset( $languages[$id] )? $languages[$id]: false;
00268     }
00269 
00270     /**
00271      * Fetches the language identified by locale code.
00272      *
00273      * \param locale Locale of the language to fetch, e. g. 'slk-SK'.
00274      * \return eZContentLanguage object identified by locale code $locale.
00275      */
00276     static function fetchByLocale( $locale, $createIfNotExist = false )
00277     {
00278         $languages = eZContentLanguage::fetchList();
00279 
00280         foreach ( $languages as $language )
00281         {
00282             if ( $language->attribute( 'locale' ) == $locale )
00283             {
00284                 return $language;
00285             }
00286         }
00287 
00288         $language = false;
00289         if ( $createIfNotExist )
00290         {
00291             $language = eZContentLanguage::addLanguage( $locale );
00292         }
00293 
00294         return $language;
00295     }
00296 
00297     /**
00298      * Fetches the list of the prioritized languages (in the correct order).
00299      *
00300      * \param languageList Optional. If specified, this array of locale codes with will override the INI
00301      *                     settings. Usage of this parameter is restricted to methods of this class!
00302      *                     See eZContentLanguage::setPrioritizedLanguages().
00303      * \return Array of the eZContentLanguage objects of the prioritized languages.
00304      * \static
00305      */
00306     static function prioritizedLanguages( $languageList = false )
00307     {
00308         if ( !isset( $GLOBALS['eZContentLanguagePrioritizedLanguages'] ) )
00309         {
00310             $GLOBALS['eZContentLanguagePrioritizedLanguages'] = array();
00311 
00312             $ini = eZINI::instance();
00313 
00314             $languageListAsParameter = false;
00315             if ( $languageList )
00316             {
00317                 $languageListAsParameter = true;
00318             }
00319 
00320             if ( !$languageList && $ini->hasVariable( 'RegionalSettings', 'SiteLanguageList' ) )
00321             {
00322                 $languageList = $ini->variable( 'RegionalSettings', 'SiteLanguageList' );
00323             }
00324 
00325             if ( !$languageList )
00326             {
00327                 $languageList = array( $ini->variable( 'RegionalSettings', 'ContentObjectLocale' ) );
00328             }
00329 
00330             $processedLocaleCodes = array();
00331             foreach ( $languageList as $localeCode )
00332             {
00333                 if ( in_array( $localeCode, $processedLocaleCodes ) )
00334                 {
00335                     continue;
00336                 }
00337                 $processedLocaleCodes[] = $localeCode;
00338                 $language = eZContentLanguage::fetchByLocale( $localeCode );
00339                 if ( $language )
00340                 {
00341                     $GLOBALS['eZContentLanguagePrioritizedLanguages'][] = $language;
00342                 }
00343                 else
00344                 {
00345                     eZDebug::writeWarning( "Language '$localeCode' does not exist or is not used!", __METHOD__ );
00346                 }
00347             }
00348 
00349             if ( ( !$languageListAsParameter && $ini->variable( 'RegionalSettings', 'ShowUntranslatedObjects' ) == 'enabled' ) ||
00350                  ( isset( $GLOBALS['eZContentLanguageCronjobMode'] ) && $GLOBALS['eZContentLanguageCronjobMode'] ) )
00351             {
00352                 $completeList = eZContentLanguage::fetchList();
00353                 foreach ( $completeList as $language )
00354                 {
00355                     if ( !in_array( $language->attribute( 'locale' ), $languageList ) )
00356                     {
00357                         $GLOBALS['eZContentLanguagePrioritizedLanguages'][] = $language;
00358                     }
00359                 }
00360             }
00361         }
00362 
00363         return $GLOBALS['eZContentLanguagePrioritizedLanguages'];
00364     }
00365 
00366     /**
00367      * Returns the array of the locale codes of the prioritized languages (in the correct order).
00368      *
00369      * \return Array of the locale codes of the prioritized languages (in the correct order).
00370      * \see eZContentLanguage::prioritizedLanguages()
00371      * \static
00372      */
00373     static function prioritizedLanguageCodes()
00374     {
00375         $languages = eZContentLanguage::prioritizedLanguages();
00376         $localeList = array();
00377 
00378         foreach ( $languages as $language )
00379         {
00380             $localeList[] = $language->attribute( 'locale' );
00381         }
00382 
00383         return $localeList;
00384     }
00385 
00386     /**
00387      * Overrides the prioritized languages set by INI settings with the specified languages.
00388      *
00389      * \param languages Locale codes of the languages which will override the prioritized languages
00390      *                  (the order is relevant).
00391      * \static
00392      */
00393     static function setPrioritizedLanguages( $languages )
00394     {
00395         unset( $GLOBALS['eZContentLanguagePrioritizedLanguages'] );
00396         eZContentLanguage::prioritizedLanguages( $languages );
00397     }
00398 
00399     /**
00400      * Clears the prioritized language list set by eZContentLanguage::setPrioritizedLanguages and reloading
00401      * the list from INI settings.
00402      *
00403      * \static
00404      */
00405     static function clearPrioritizedLanguages()
00406     {
00407         eZContentLanguage::setPrioritizedLanguages( false );
00408     }
00409 
00410     /**
00411      * Returns the most prioritized language.
00412      *
00413      * \return eZContentLanguage object for the most prioritized language.
00414      * \static
00415      */
00416     static function topPriorityLanguage()
00417     {
00418         $prioritizedLanguages = eZContentLanguage::prioritizedLanguages();
00419         if ( $prioritizedLanguages )
00420         {
00421             return $prioritizedLanguages[0];
00422         }
00423         else
00424         {
00425             return false;
00426         }
00427     }
00428 
00429     /**
00430      * \return Locale object for this language.
00431      */
00432     function localeObject()
00433     {
00434         $locale = eZLocale::instance( $this->Locale );
00435         return $locale;
00436     }
00437 
00438     /**
00439      * Returns array of languages which have set the corresponding bit in the mask.
00440      *
00441      * \param mask Bitmap specifying which languages should be returned.
00442      * \return Array of eZContentLanguage objects of languages which have set the corresponding bit in $mask.
00443      */
00444     static function languagesByMask( $mask )
00445     {
00446         $result = array();
00447 
00448         $languages = eZContentLanguage::fetchList();
00449         foreach ( $languages as $key => $language )
00450         {
00451             if ( (int) $key & (int) $mask )
00452             {
00453                 $result[$language->attribute( 'locale' )] = $language;
00454             }
00455         }
00456 
00457         return $result;
00458     }
00459 
00460     /**
00461      * Returns array of prioritized languages which have set the corresponding bit in the mask.
00462      *
00463      * \param mask Bitmap specifying which languages should be returned.
00464      * \return Array of eZContentLanguage objects of prioritized languages which have set the corresponding bit in $mask.
00465      */
00466     static function prioritizedLanguagesByMask( $mask )
00467     {
00468         $result = array();
00469 
00470         $languages = eZContentLanguage::prioritizedLanguages();
00471         foreach ( $languages as $language )
00472         {
00473             if ( ( (int) $language->attribute( 'id' ) & (int) $mask ) > 0 )
00474             {
00475                 $result[$language->attribute( 'locale' )] = $language;
00476             }
00477         }
00478 
00479         return $result;
00480     }
00481 
00482     /**
00483      * Returns array of prioritized languages which are listed in \a $languageLocaleList.
00484      * The function does the same as 'prioritizedLanguagesByMask' but uses language locale list instead of language mask.
00485      *
00486      * \param languageLocaleList List of language locales to choose from.
00487      * \return Array of eZContentLanguage objects of prioritized languages which have set the corresponding bit in $mask.
00488      */
00489     static function prioritizedLanguagesByLocaleList( $languageLocaleList )
00490     {
00491         $result = array();
00492 
00493         if ( is_array( $languageLocaleList ) && count( $languageLocaleList ) > 0 )
00494         {
00495             $languages = eZContentLanguage::prioritizedLanguages();
00496             foreach ( $languages as $language )
00497             {
00498                 if ( in_array( $language->attribute( 'locale' ), $languageLocaleList ) )
00499                 {
00500                     $result[$language->attribute( 'locale' )] = $language;
00501                 }
00502             }
00503         }
00504 
00505         return $result;
00506     }
00507 
00508     /**
00509      * Returns the most prioritized language which has set the corresponding bit in the mask.
00510      *
00511      * \param mask Bitmap specifying which languages should be checked.
00512      * \return eZContentLanguage object of the most prioritized language which have set the corresponding bit in $mask.
00513      */
00514     static function topPriorityLanguageByMask( $mask )
00515     {
00516         $languages = eZContentLanguage::prioritizedLanguages();
00517         foreach ( $languages as $language )
00518         {
00519             if ( ( (int) $language->attribute( 'id' ) & (int) $mask ) > 0 )
00520             {
00521                 return $language;
00522             }
00523         }
00524         return false;
00525     }
00526 
00527     /**
00528      * Returns the most prioritized language from specified by \a $languageLocaleList list of language locales.
00529      * The function does the same as 'topPriorityLanguageByMask' but uses language locale list instead of language mask.
00530      *
00531      * \param languageLocaleList List of language locales to choose from.
00532      * \return eZContentLanguage object of the most prioritized language.
00533      */
00534     static function topPriorityLanguageByLocaleList( $languageLocaleList )
00535     {
00536         if ( is_array( $languageLocaleList ) && count( $languageLocaleList ) > 0 )
00537         {
00538             $languages = eZContentLanguage::prioritizedLanguages();
00539             foreach ( $languages as $language )
00540             {
00541                 if ( in_array( $language->attribute( 'locale' ), $languageLocaleList ) )
00542                 {
00543                     return $language;
00544                 }
00545             }
00546         }
00547 
00548         return false;
00549     }
00550 
00551     /**
00552      * Returns bitmap mask for the specified languages.
00553      *
00554      * \param locales Array of strings or a string specifying locale codes of the languages, e. g. 'slk-SK' or array( 'eng-GB', 'nor-NO' )
00555      * \param setZerothBit Optional. Specifies if the 0-th bit of mask should be set. False by default.
00556      * \return Bitmap mask having set the corresponding bits for the specified languages.
00557      */
00558     static function maskByLocale( $locales, $setZerothBit = false )
00559     {
00560         if ( !$locales )
00561         {
00562             return 0;
00563         }
00564 
00565         if ( !is_array( $locales ) )
00566         {
00567             $locales = array( $locales );
00568         }
00569 
00570         $mask = 0;
00571         if ( $setZerothBit )
00572         {
00573             $mask = 1;
00574         }
00575 
00576         foreach( $locales as $locale )
00577         {
00578             $language = eZContentLanguage::fetchByLocale( $locale );
00579             if ( $language )
00580             {
00581                 $mask += $language->attribute( 'id' );
00582             }
00583         }
00584 
00585         return (int) $mask;
00586     }
00587 
00588     /**
00589      * Decodes $langMask into all languages it comprises and whether or not
00590      * the language mask signifies always available or not.
00591      *
00592      * The constituent languages are returned as an array of language ids. If
00593      * the second parameter, $returnLanguageLocale is set to TRUE, locale-codes
00594      * are used instead of language ids.
00595      *
00596      * @param int $langMask
00597      * @param boolean $returnLanguageLocale
00598      * @return array
00599      */
00600     public static function decodeLanguageMask( $langMask, $returnLanguageLocale = false )
00601     {
00602         $maxNumberOfLanguges = eZContentLanguage::MAX_COUNT;
00603         $maxInteger = pow( 2, $maxNumberOfLanguges );
00604 
00605         $list = array();
00606 
00607         // Applying this bit-logic on negative numbers, or numbers out of bounds
00608         // will have unexpected results.
00609         if ( $langMask < 0 or $langMask > $maxInteger or $langMask == 1 )
00610         {
00611             // We use the default language if the situation above occurs
00612             $defaultLanguage = eZContentLanguage::topPriorityLanguage();
00613             $langMask = $defaultLanguage->attribute( 'id' );
00614         }
00615 
00616         $alwaysAvailable = $langMask % 2;
00617         $mask = $langMask & ~1;
00618 
00619         // Calculating which translations are present in the current version
00620         for ( $i = 1; $i < $maxNumberOfLanguges; ++$i )
00621         {
00622             $newMask = 1 << $i;
00623             if ( ($newMask & $mask) > 0 )
00624             {
00625                 if ( $returnLanguageLocale )
00626                 {
00627                     $list[] = eZContentLanguage::fetch( $newMask )->attribute( 'locale' );
00628                 }
00629                 else
00630                 {
00631                     $list[] = $newMask;
00632                 }
00633             }
00634         }
00635 
00636         return array(
00637                       'always_available' => $alwaysAvailable,
00638                       'language_list'    => $list
00639                     );
00640     }
00641 
00642     /**
00643      * \static
00644      * Returns id of the language specified.
00645      *
00646      * \param locale String specifying locale code of the language, e. g. 'slk-SK'
00647      * \return ID of the language specified by locale or false if the language is not set on the site.
00648      */
00649     static function idByLocale( $locale )
00650     {
00651         $language = eZContentLanguage::fetchByLocale( $locale );
00652         if ( $language )
00653         {
00654             return (int)$language->attribute( 'id' );
00655         }
00656         else
00657         {
00658             return false;
00659         }
00660     }
00661 
00662     /**
00663      * Returns the SQL where-condition for selecting the rows (objects, object versions) which exist in any
00664      * of prioritized languages or are always available.
00665      *
00666      * \param languageListTable Name of the table
00667      * \param languageListAttributeName Optional. Name of the attribute in the table which contains the bitmap mask. 'language_mask' by default.
00668      * \return SQL where-condition described above.
00669      * \static
00670      */
00671     static function languagesSQLFilter( $languageListTable, $languageListAttributeName = 'language_mask' )
00672     {
00673         $prioritizedLanguages = eZContentLanguage::prioritizedLanguages();
00674         $mask = 1; // 1 - always available objects
00675         foreach( $prioritizedLanguages as $language )
00676         {
00677             $mask += $language->attribute( 'id' );
00678         }
00679 
00680         $db = eZDB::instance();
00681         if ( $db->databaseName() == 'oracle' )
00682         {
00683             return "\n bitand( $languageListTable.$languageListAttributeName, $mask ) > 0 \n";
00684         }
00685         else
00686         {
00687             return "\n $languageListTable.$languageListAttributeName & $mask > 0 \n";
00688         }
00689     }
00690 
00691     /**
00692      * Returns the SQL where-condition for selecting the rows (with object names, attributes etc.) in the correct language,
00693      * i. e. in the most prioritized language from those in which an object exists.
00694      *
00695      * \param languageTable Name of the table containing the attribute with the language id.
00696      * \param languageListTable Name of the table containing the attribute with the available languages bitmap.
00697      * \param languageAttributeName Optional. Name of the attribute in $languageTable which contains
00698      *                               the language id. 'language_id' by default.
00699      * \param languageListAttributeName Optional. Name of the attribute in $languageListTable which contains
00700      *                                  the bitmap mask. 'language_mask' by default.
00701      * \return SQL where-condition described above.
00702      */
00703     static function sqlFilter( $languageTable, $languageListTable = null, $languageAttributeName = 'language_id', $languageListAttributeName = 'language_mask' )
00704     {
00705         $db = eZDB::instance();
00706 
00707         if ( $languageListTable === null )
00708         {
00709             $languageListTable = $languageTable;
00710         }
00711 
00712         $prioritizedLanguages = eZContentLanguage::prioritizedLanguages();
00713         if ( $db->databaseName() == 'oracle' )
00714         {
00715             $leftSide = "bitand( $languageListTable.$languageListAttributeName - bitand( $languageListTable.$languageListAttributeName, $languageTable.$languageAttributeName ), 1 )\n";
00716             $rightSide = "bitand( $languageTable.$languageAttributeName, 1 )\n";
00717         }
00718         else
00719         {
00720             $leftSide = "    ( (   $languageListTable.$languageListAttributeName - ( $languageListTable.$languageListAttributeName & $languageTable.$languageAttributeName ) ) & 1 )\n";
00721             $rightSide = "  ( $languageTable.$languageAttributeName & 1 )\n";
00722         }
00723 
00724         for ( $index = count( $prioritizedLanguages ) - 1, $multiplier = 2; $index >= 0; $index--, $multiplier *= 2 )
00725         {
00726             $id = $prioritizedLanguages[$index]->attribute( 'id' );
00727 
00728             if ( $db->databaseName() == 'oracle' )
00729             {
00730                 $leftSide .= "   + bitand( $languageListTable.$languageListAttributeName - bitand( $languageListTable.$languageListAttributeName, $languageTable.$languageAttributeName ), $id )";
00731                 $rightSide .= "   + bitand( $languageTable.$languageAttributeName, $id )";
00732             }
00733             else
00734             {
00735                 $leftSide .= "   + ( ( ( $languageListTable.$languageListAttributeName - ( $languageListTable.$languageListAttributeName & $languageTable.$languageAttributeName ) ) & $id )";
00736                 $rightSide .= "   + ( ( $languageTable.$languageAttributeName & $id )";
00737             }
00738 
00739             if ( $multiplier > $id )
00740             {
00741                 $factor = $multiplier / $id;
00742                 if ( $db->databaseName() == 'oracle' )
00743                 {
00744                     $factorTerm = ' * ' . $factor;
00745                 }
00746                 else
00747                 {
00748                     for ( $shift = 0; $factor > 1; $factor = $factor / 2, $shift++ ) ;
00749                     $factorTerm = ' << '. $shift;
00750                 }
00751                 $leftSide .= $factorTerm;
00752                 $rightSide .= $factorTerm;
00753             }
00754             else if ( $multiplier < $id )
00755             {
00756                 $factor = $id / $multiplier;
00757                 if ( $db->databaseName() == 'oracle' )
00758                 {
00759                     $factorTerm = ' / ' . $factor;
00760                 }
00761                 else
00762                 {
00763                     for ( $shift = 0; $factor > 1; $factor = $factor / 2, $shift++ ) ;
00764                     $factorTerm = ' >> '. $shift;
00765                 }
00766                 $leftSide .= $factorTerm;
00767                 $rightSide .= $factorTerm;
00768             }
00769             if ( $db->databaseName() != 'oracle' )
00770             {
00771                 $leftSide .= " )\n";
00772                 $rightSide .= " )\n";
00773             }
00774         }
00775 
00776         if ( $db->databaseName() == 'oracle' )
00777         {
00778             $sql = "bitand( $languageTable.$languageAttributeName, $languageListTable.$languageListAttributeName ) > 0";
00779         }
00780         else
00781         {
00782             $sql = "$languageTable.$languageAttributeName & $languageListTable.$languageListAttributeName > 0";
00783         }
00784 
00785         return "\n ( $sql AND\n $leftSide   <\n   $rightSide ) \n";
00786     }
00787 
00788     /**
00789      * \return The count of objects containing the translation in this language.
00790      */
00791     function objectCount()
00792     {
00793         $db = eZDB::instance();
00794 
00795         $languageID = $this->ID;
00796         if ( $db->databaseName() == 'oracle' )
00797         {
00798             $whereSQL = "bitand( language_mask, $languageID ) > 0";
00799         }
00800         else
00801         {
00802             $whereSQL = "language_mask & $languageID > 0";
00803         }
00804 
00805         $count = $db->arrayQuery( "SELECT COUNT(*) AS count FROM ezcontentobject WHERE $whereSQL" );
00806         return $count[0]['count'];
00807     }
00808 
00809     /**
00810      * \return The count of classes containing the translation in this language.
00811      */
00812     function classCount()
00813     {
00814         $db = eZDB::instance();
00815 
00816         $languageID = $this->ID;
00817         if ( $db->databaseName() == 'oracle' )
00818         {
00819             $whereSQL = "bitand( language_mask, $languageID ) > 0";
00820         }
00821         else
00822         {
00823             $whereSQL = "language_mask & $languageID > 0";
00824         }
00825 
00826         $count = $db->arrayQuery( "SELECT COUNT(*) AS count FROM ezcontentclass WHERE $whereSQL" );
00827         $count = $count[0]['count'];
00828 
00829         return $count;
00830     }
00831 
00832 
00833     /**
00834      * \return The count of objects having this language as the initial/main one.
00835      */
00836     function objectInitialCount()
00837     {
00838         $db = eZDB::instance();
00839 
00840         $languageID = $this->ID;
00841         $count = $db->arrayQuery( "SELECT COUNT(*) AS count FROM ezcontentobject WHERE initial_language_id = '$languageID'" );
00842         $count = $count[0]['count'];
00843 
00844         return $count;
00845     }
00846 
00847     /**
00848      * \return Reference to itself. Kept because of the backward compatibility.
00849      */
00850     function translation()
00851     {
00852         return $this;
00853     }
00854 
00855     /**
00856      * \deprecated
00857      */
00858     function updateObjectNames()
00859     {
00860     }
00861 
00862     /**
00863      * Switches on the cronjob mode. In this mode, the languages which are not in the list of the prioritized languages
00864      * will be automatically added to it.
00865      *
00866      * \param enable Optional. If false, it will switch off the cronjob mode. True by default.
00867      */
00868     static function setCronjobMode( $enable = true )
00869     {
00870         $GLOBALS['eZContentLanguageCronjobMode'] = true;
00871         unset( $GLOBALS['eZContentLanguagePrioritizedLanguages'] );
00872     }
00873 
00874     /**
00875      * Switches off the cronjob mode.
00876      *
00877      * \see eZContentLanguage::setCronjobMode()
00878      */
00879     static function clearCronjobMode()
00880     {
00881         eZContentLanguage::setCronjobMode( false );
00882     }
00883 
00884     /**
00885      * Returns the Javascript array with locale codes and names of the languages which have set the corresponding
00886      * bit in specified mask.
00887      *
00888      * \param mask Bitmap mask specifying which languages should be considered.
00889      * \return JavaScript array described above.
00890      */
00891     static function jsArrayByMask( $mask )
00892     {
00893         $localList = array();
00894         $languages = eZContentLanguage::prioritizedLanguagesByMask( $mask );
00895         foreach ( $languages as $key => $language )
00896         {
00897             $localList[] = array( 'locale' => $language->attribute( 'locale' ),
00898                                   'name'   => $language->attribute( 'name' ) );
00899         }
00900 
00901         if ( $localList )
00902         {
00903             return json_encode( $localList );
00904         }
00905         else
00906         {
00907             return false;
00908         }
00909     }
00910 
00911     /**
00912      * \return The bitmap mask containing all languages, i. e. the sum of the IDs of all languages. (The 0-th bit is set.)
00913      */
00914     static function maskForRealLanguages()
00915     {
00916         if ( !isset( $GLOBALS['eZContentLanguageMask'] ) )
00917         {
00918             eZContentLanguage::fetchList( true );
00919         }
00920         return $GLOBALS['eZContentLanguageMask'];
00921     }
00922 
00923     /**
00924      * Removes all memory cache forcing it to read from database again for next method calls.
00925      *
00926      * \static
00927      */
00928     static function expireCache()
00929     {
00930         unset( $GLOBALS['eZContentLanguageList'],
00931                $GLOBALS['eZContentLanguagePrioritizedLanguages'],
00932                $GLOBALS['eZContentLanguageMask'],
00933                $GLOBALS['eZContentLanguageCronjobMode'] );
00934 
00935         // With the solution to #14227 we also need to clear the cached
00936         // list of languages
00937         $cachePath = eZSys::cacheDirectory() . '/ezcontentlanguage_cache.php';
00938         eZClusterFileHandler::instance()->fileDelete( $cachePath );
00939     }
00940 }
00941 
00942 ?>