eZ Publish  [trunk]
ezserializedobjectnamelist.php
Go to the documentation of this file.
00001 <?php
00002 /**
00003  * File containing the eZSerializedObjectNameList 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 eZSerializedObjectNameList
00012 {
00013     const ALWAYS_AVAILABLE_STR = 'always-available';
00014 
00015     function eZSerializedObjectNameList( $serializedNamesString = false )
00016     {
00017         $this->DefaultLanguage = null;
00018 
00019         if ( $serializedNamesString )
00020             $this->initFromSerializedList( $serializedNamesString );
00021     }
00022 
00023     function initFromSerializedList( $serializedNamesString )
00024     {
00025         $this->HasDirtyData = false;
00026         $this->unserializeNames( $serializedNamesString );
00027     }
00028 
00029     function initFromString( $nameString, $languageLocale = false )
00030     {
00031         if ( !$languageLocale )
00032             $languageLocale = $this->defaultLanguageLocale();
00033 
00034         $serializedNameList = serialize( array( $languageLocale => $nameString,
00035                                                 eZSerializedObjectNameList::ALWAYS_AVAILABLE_STR => $languageLocale ) );
00036         $this->initFromSerializedList( $serializedNameList );
00037     }
00038 
00039     function initDefault()
00040     {
00041         $this->initFromString( '' );
00042     }
00043 
00044     function create( $serializedNamesString = false )
00045     {
00046         $object = new eZSerializedObjectNameList( $serializedNamesString );
00047         return $object;
00048     }
00049 
00050     function __clone()
00051     {
00052     }
00053 
00054     function copy( $serializedObjectNameListObject )
00055     {
00056         $serializedObjectNameListObject->setNameList( $this->nameList() );
00057         $serializedObjectNameListObject->setHasDirtyData( $this->hasDirtyData() );
00058         $serializedObjectNameListObject->setDefaultLanguage( $this->defaultLanguage() );
00059     }
00060 
00061     function mergeNameList( $inNameList )
00062     {
00063         foreach ( $inNameList as $languageLocale => $name )
00064             $this->setNameByLanguageLocale( $name, $languageLocale );
00065 
00066         $this->setHasDirtyData();
00067     }
00068 
00069     function serializeNames()
00070     {
00071         return serialize( $this->NameList );
00072     }
00073 
00074     function isEmpty()
00075     {
00076         return ( count( $this->NameList ) == 0 );
00077     }
00078 
00079     function unserializeNames( $serializedNamesString )
00080     {
00081         $this->NameList = array();
00082         if ( $serializedNamesString )
00083         {
00084             $this->NameList = @unserialize( $serializedNamesString );
00085             if ( $this->NameList === false || !is_array( $this->NameList ) )
00086                 $this->NameList = array();
00087         }
00088 
00089         $this->setHasDirtyData( false );
00090     }
00091 
00092     function alwaysAvailableLanguageID()
00093     {
00094         $languageLocale = $this->alwaysAvailableLanguageLocale();
00095         $languageID = $languageLocale ? eZContentLanguage::idByLocale( $languageLocale ) : false;
00096 
00097         return $languageID;
00098     }
00099 
00100     function alwaysAvailableLanguageLocale()
00101     {
00102         $languageLocale = isset( $this->NameList[eZSerializedObjectNameList::ALWAYS_AVAILABLE_STR] ) ? $this->NameList[eZSerializedObjectNameList::ALWAYS_AVAILABLE_STR] : false;
00103         return $languageLocale;
00104     }
00105 
00106     function alwaysAvailableLanguage()
00107     {
00108         $language = false;
00109         if ( isset( $this->NameList[eZSerializedObjectNameList::ALWAYS_AVAILABLE_STR] ) )
00110             $language = eZContentLanguage::fetchByLocale( $this->NameList[eZSerializedObjectNameList::ALWAYS_AVAILABLE_STR] );
00111 
00112         return $language;
00113     }
00114 
00115     function languageMask()
00116     {
00117         $mask = 0;
00118         foreach ( $this->NameList as $languageLocale => $name )
00119         {
00120             if ( $languageLocale == eZSerializedObjectNameList::ALWAYS_AVAILABLE_STR )
00121             {
00122                 $mask += 1;
00123             }
00124             else
00125             {
00126                 $languageID = eZContentLanguage::idByLocale( $languageLocale );
00127                 $mask += $languageID;
00128             }
00129         }
00130 
00131         return $mask;
00132     }
00133 
00134     function name( $languageLocale = false )
00135     {
00136         return ( ( $languageLocale === false ) ? $this->nameByPrioritizedLanguages() : $this->nameByLanguageLocale( $languageLocale ) );
00137     }
00138 
00139     function nameByPrioritizedLanguages()
00140     {
00141         $name = $this->alwaysAvailableName();
00142         $languageList = eZContentLanguage::prioritizedLanguages();
00143         foreach ( $languageList as $language )
00144         {
00145             if ( $this->hasNameInLocale( $language->attribute( 'locale' ) ) )
00146             {
00147                 $name = $this->nameByLanguageLocale( $language->attribute( 'locale' ) );
00148                 break;
00149             }
00150         }
00151 
00152         return $name;
00153     }
00154 
00155     function nameByLanguageLocale( $languageLocale )
00156     {
00157         $name = '';
00158         if ( $this->hasNameInLocale( $languageLocale ) )
00159             $name = $this->NameList[$languageLocale];
00160 
00161         return $name;
00162     }
00163 
00164     function alwaysAvailableName()
00165     {
00166         $name = '';
00167         if ( isset( $this->NameList[eZSerializedObjectNameList::ALWAYS_AVAILABLE_STR] ) )
00168         {
00169             $name = $this->nameByLanguageLocale( $this->NameList[eZSerializedObjectNameList::ALWAYS_AVAILABLE_STR] );
00170         }
00171 
00172         return $name;
00173     }
00174 
00175     function setAlwaysAvailableLanguage( $languageLocale )
00176     {
00177         if ( $languageLocale )
00178         {
00179             $this->NameList[eZSerializedObjectNameList::ALWAYS_AVAILABLE_STR] = $languageLocale;
00180         }
00181         else
00182         {
00183             unset( $this->NameList[eZSerializedObjectNameList::ALWAYS_AVAILABLE_STR] );
00184         }
00185 
00186         $this->setHasDirtyData();
00187     }
00188 
00189     function updateAlwaysAvailable( $alwaysAvailableLocale = false )
00190     {
00191         if ( !$alwaysAvailableLocale )
00192             $alwaysAvailableLocale = $this->alwaysAvailableLanguageLocale();
00193 
00194         if ( !$this->hasNameInLocale( $alwaysAvailableLocale ) )
00195         {
00196             $languageLocaleList = array_keys( $this->nameList() );
00197             $alwaysAvailableLocale = $languageLocaleList[0];
00198         }
00199 
00200         $this->setAlwaysAvailableLanguage( $alwaysAvailableLocale );
00201     }
00202 
00203     function hasNameInLocale( $languageLocale )
00204     {
00205         $hasName = false;
00206         if ( is_array ( $this->NameList ) )
00207         {
00208             if ( $languageLocale && isset( $this->NameList[$languageLocale] ) )
00209             {
00210                 $hasName = true;
00211             }
00212         }
00213         else
00214         {
00215             eZDebug::writeWarning( "Trying to get name for language '$languageLocale' without initialized name list.", __METHOD__ );
00216         }
00217 
00218         return $hasName;
00219     }
00220 
00221     function setName( $name, $languageLocale = false )
00222     {
00223         $oldName = $this->name( $languageLocale );
00224         if ( !$languageLocale )
00225             $languageLocale = $this->topPriorityLanguageLocale();
00226 
00227         $this->setNameByLanguageLocale( $name, $languageLocale );
00228         return $oldName;
00229     }
00230 
00231     function setNameByLanguageLocale( $name, $languageLocale )
00232     {
00233         if ( is_array( $this->NameList ) )
00234         {
00235             if ( $languageLocale )
00236             {
00237                 $this->NameList[$languageLocale] = $name;
00238                 $this->setHasDirtyData();
00239             }
00240             else
00241             {
00242                 eZDebug::writeWarning( "Language locale is not specified while setting name '$name'", __METHOD__ );
00243             }
00244         }
00245         else
00246         {
00247             eZDebug::writeWarning( "Trying to set name '$name' for language '$languageLocale' without initialized name list.", __METHOD__ );
00248         }
00249     }
00250 
00251     /*!
00252      Appends \a $appendString string to each name in NameList.
00253     */
00254     function appendGroupName( $appendString )
00255     {
00256         foreach ( array_keys( $this->NameList ) as $languageLocale )
00257         {
00258             if ( $languageLocale != eZSerializedObjectNameList::ALWAYS_AVAILABLE_STR )
00259                 $this->NameList[$languageLocale] .= $appendString;
00260         }
00261     }
00262 
00263     /*!
00264      \static
00265     */
00266     static function nameFromSerializedString( $serializedNames, $languageLocale = false )
00267     {
00268         $nameList = new eZSerializedObjectNameList( $serializedNames );
00269         return $nameList->name( $languageLocale );
00270     }
00271 
00272 
00273     /*!
00274      \return true if the data is considered dirty(e.g. names were changed)
00275     */
00276     function hasDirtyData()
00277     {
00278         return $this->HasDirtyData;
00279     }
00280 
00281     /*!
00282      Sets whether the object has dirty data or not.
00283      \sa hasDirtyData, sync
00284     */
00285     function setHasDirtyData( $hasDirtyData = true )
00286     {
00287         $this->HasDirtyData = $hasDirtyData;
00288     }
00289 
00290     function nameList()
00291     {
00292         return $this->NameList;
00293     }
00294 
00295     /*!
00296      Same as 'nameList()' but without 'always-available' entry.
00297      */
00298     function cleanNameList()
00299     {
00300         $nameList = $this->nameList();
00301         unset( $nameList[eZSerializedObjectNameList::ALWAYS_AVAILABLE_STR] );
00302         return $nameList;
00303     }
00304 
00305     function nameListCount()
00306     {
00307         return count( $this->nameList );
00308     }
00309 
00310     function setNameList( $nameListArray )
00311     {
00312         $this->NameList = $nameListArray;
00313     }
00314 
00315     function resetNameList()
00316     {
00317         $this->setNameList( array() );
00318     }
00319 
00320     function removeName( $languageLocale )
00321     {
00322         if ( isset( $this->NameList[$languageLocale] ) )
00323         {
00324             unset( $this->NameList[$languageLocale] );
00325             $this->setHasDirtyData();
00326         }
00327     }
00328 
00329     function defaultLanguageLocale()
00330     {
00331         $languageLocale = false;
00332         $language = $this->defaultLanguage();
00333 
00334         if ( is_object( $language ) )
00335             $languageLocale = $language->attribute( 'locale' );
00336 
00337         return $languageLocale;
00338     }
00339 
00340     function defaultLanguage()
00341     {
00342         if ( !is_object( $this->DefaultLanguage ) )
00343         {
00344             $this->DefaultLanguage = eZContentLanguage::topPriorityLanguage();
00345         }
00346 
00347         return $this->DefaultLanguage;
00348     }
00349 
00350     function setDefaultLanguage( $language )
00351     {
00352         $this->DefaultLanguage = $language;
00353     }
00354 
00355     function setDefaultLanguageByLocale( $languageLocale, $createIfNotExist = true )
00356     {
00357         $language = eZContentLanguage::fetchByLocale( $languageLocale, $createIfNotExist );
00358 
00359         if ( is_object( $language ) )
00360         {
00361             $this->setDefaultLanguage( $language );
00362         }
00363         else
00364         {
00365             eZDebug::writeWarning( "Can't set '$languageLocale' as default language. '$languageLocale' language doesn't exist in system", __METHOD__ );
00366         }
00367 
00368         return $language;
00369     }
00370 
00371     /*!
00372      The same as 'topPriorityLanguage' but returns language locale.
00373 
00374      \return language locale.
00375     */
00376     function topPriorityLanguageLocale()
00377     {
00378         $languageLocale = false;
00379 
00380         $language = $this->topPriorityLanguage();
00381         if ( $language )
00382             $languageLocale = $language->attribute( 'locale' );
00383 
00384         return $languageLocale;
00385     }
00386 
00387     /*!
00388      Returns top prioriry language for which there is translation according to
00389      siteaccess's available language list.
00390      If there is no translations for languages listed in siteaccess's available language list
00391      it returns 'always available' language.
00392 
00393      \return language object.
00394     */
00395     function topPriorityLanguage()
00396     {
00397         $language = false;
00398 
00399         $languageLocaleList = $this->languageLocaleList();
00400 
00401         $language = eZContentLanguage::topPriorityLanguageByLocaleList( $languageLocaleList );
00402 
00403         if ( !$language )
00404             $language = $this->alwaysAvailableLanguage();
00405 
00406         return $language;
00407     }
00408 
00409     /*!
00410      Returns an array of languages in which contentclass has translations.
00411      However, if there is a name in language which is not
00412      listed as 'available' for siteaccess, that langugese will not be returned
00413      (except of 'always available' language).
00414 
00415      \return an array of language's locales.
00416     */
00417     function prioritizedLanguages()
00418     {
00419         $languageLocaleList = $this->languageLocaleList();
00420         $languages = eZContentLanguage::prioritizedLanguagesByLocaleList( $languageLocaleList );
00421 
00422         $alwaysAvailableLanguage = $this->alwaysAvailableLanguage();
00423         if ( $alwaysAvailableLanguage )
00424         {
00425             $alwaysAvailableLanguageLocale = $alwaysAvailableLanguage->attribute( 'locale' );
00426             if ( !isset( $languages[$alwaysAvailableLanguageLocale] ) )
00427             {
00428                 $languages[$alwaysAvailableLanguageLocale] = $alwaysAvailableLanguage;
00429             }
00430         }
00431 
00432         return $languages;
00433     }
00434 
00435     function prioritizedLanguagesJsArray()
00436     {
00437         $langList = array();
00438         $languages = $this->prioritizedLanguages();
00439         foreach ( $languages as $key => $language )
00440         {
00441             $langList[] = array( 'locale' => $language->attribute( 'locale' ),
00442                                  'name'   => $language->attribute( 'name' ) );
00443         }
00444 
00445         if ( $langList )
00446             return json_encode( $langList );
00447 
00448         return '[]';
00449     }
00450 
00451     function languageLocaleList()
00452     {
00453         $languageLocaleList = array();
00454 
00455         if ( is_array( $this->NameList ) && count( $this->NameList ) > 0 )
00456         {
00457             foreach ( array_keys( $this->NameList ) as $languageLocale )
00458             {
00459                 if ( $languageLocale != eZSerializedObjectNameList::ALWAYS_AVAILABLE_STR )
00460                     $languageLocaleList[] = $languageLocale;
00461             }
00462         }
00463 
00464         return $languageLocaleList;
00465     }
00466 
00467     /*!
00468      The same as 'languageLocaleList' but returns a list of 'eZContentLanguage' objects.
00469 
00470      \return array of language objects.
00471     */
00472     function languages()
00473     {
00474         $languages = array();
00475 
00476         $languageLocaleList = $this->languageLocaleList();
00477         foreach( $languageLocaleList as $languageLocale )
00478             $languages[$languageLocale] = eZContentLanguage::fetchByLocale( $languageLocale );
00479 
00480         return $languages;
00481     }
00482 
00483     /*!
00484      Returns an array of languages for which translations don't exist.
00485 
00486      \return an array of languages. Each key in this array is 'language locale'.
00487     */
00488     function untranslatedLanguages()
00489     {
00490         $availableLanguages = $this->prioritizedLanguages();
00491         $availableLanguagesCodes = array_keys( $availableLanguages );
00492 
00493         $languages = array();
00494         foreach ( eZContentLanguage::prioritizedLanguages() as $language )
00495         {
00496             $languageCode = $language->attribute( 'locale' );
00497             if ( !in_array( $languageCode, $availableLanguagesCodes ) )
00498             {
00499                 $languages[$languageCode] = $language;
00500             }
00501         }
00502 
00503         return $languages;
00504     }
00505 
00506     /*!
00507      \param $languageInfo. languageInfo = array( 'map_table' => array( [<lang> => <to_lang>],
00508                                                                        [<lang> => 'skip_language'],
00509                                                                        .... ) );
00510 
00511      Note: it's probably needed to call 'validate' after 'normalize'.
00512            'normialize' doesnt' check whether language exist or not, cause you can have names in languages which are not
00513            in 'map_table', so you need to call 'validate' anyway.
00514     */
00515     function normalize( $languageInfo )
00516     {
00517         if ( is_array( $languageInfo ) && isset( $languageInfo['map_table'] ) )
00518         {
00519             // do normalization on new 'nameList' to avoid dependence on the order
00520             // of <lang>s in 'map_table'. Normailzation on $this->nameList directly
00521             // can lead to unwanted behaviour, like
00522             //      'map_table' => array( 'ger-DE' => 'skip_language',
00523             //                            'eng-GB' => 'ger-DE' )
00524             // and
00525             //      'map_table' => array( 'eng-GB' => 'get-DE',
00526             //                            'ger-DE' => 'skip_language' )
00527             // will produce different results.
00528             $nameList = clone $this;
00529             $this->resetNameList();
00530 
00531             foreach ( $languageInfo['map_table'] as $fromLanguageLocale => $toLanguageLocale )
00532             {
00533                 $name = $nameList->nameByLanguageLocale( $fromLanguageLocale );
00534 
00535                 if ( $toLanguageLocale == 'skip_language' )
00536                 {
00537                     // do nothing;
00538                 }
00539                 else
00540                 {
00541                     $this->setNameByLanguageLocale( $name, $toLanguageLocale );
00542                 }
00543 
00544                 // exclude 'processed' name.
00545                 $nameList->removeName( $fromLanguageLocale );
00546             }
00547 
00548             // copy names which were not transformed
00549             $this->mergeNameList( $nameList );
00550 
00551             // update always-available(probably original 'always-available' was skiped)
00552             $this->updateAlwaysAvailable();
00553         }
00554     }
00555 
00556     /*!
00557      Make sure that languages namelist corresponds to languages in the system.
00558      \param $param. TRUE - create languages if they don't exist in the system.
00559                     FALSE - remove names form namelist if corresponding language doesn't exist in the system.
00560                     array - language map. The name will be removed if its language is not in the map.
00561                             Ex: array( 'language_locale_1' => 'map_to_language_locale',
00562                                        'language_locale_2' => 'skip' );
00563                                 will map name in 'language_locale_1' language to 'map_to_language_locale' and
00564                                 remove name in 'language_locale_2'. 'map_to_language_locale' language will be
00565                                 created If it doesn't exist in the system.
00566     */
00567     function validate( $param = true )
00568     {
00569         $languageMap = ( is_array( $param ) && (count( $param ) > 0) ) ? $param : false;
00570         $createLanguageIfNotExist = ( $param === true ) ? true : false;
00571         $nameList = $this->nameList();
00572         foreach ( $nameList as $nameLanguageLocale => $name )
00573         {
00574             if ( $nameLanguageLocale != eZSerializedObjectNameList::ALWAYS_AVAILABLE_STR )
00575             {
00576                 $language = false;
00577 
00578                 if( $createLanguageIfNotExist )
00579                 {
00580                     $language = eZContentLanguage::fetchByLocale( $nameLanguageLocale, true );
00581                 }
00582                 else
00583                 {
00584                     if ( is_array( $languageMap ) )
00585                     {
00586                         $languageLocale = isset( $languageMap[$nameLanguageLocale] ) ? $languageMap[$nameLanguageLocale] : false;
00587 
00588                         if( $languageLocale && $languageLocale != 'skip' )
00589                         {
00590                             $language = eZContentLanguage::fetchByLocale( $languageLocale, true );
00591                         }
00592                     }
00593                     else
00594                     {
00595                         // just check '$nameLanguageLocale' language if '$languageMap' is not specified.
00596                         $language = eZContentLanguage::fetchByLocale( $nameLanguageLocale, false );
00597                     }
00598                 }
00599 
00600                 $languageLocale = is_object( $language ) ? $language->attribute( 'locale' ) : false;
00601 
00602                 if( $languageLocale != $nameLanguageLocale )
00603                 {
00604                     if( $languageLocale )
00605                     {
00606                         // map name's language.
00607                         $this->removeName( $nameLanguageLocale );
00608                         $this->setName( $name, $languageLocale );
00609                     }
00610                     else
00611                     {
00612                         $this->removeName( $nameLanguageLocale );
00613                     }
00614                 }
00615             }
00616         }
00617         // update always-available(probably original 'always-available' was skiped)
00618         $this->updateAlwaysAvailable();
00619     }
00620 
00621     public $NameList;
00622     public $HasDirtyData;
00623     public $DefaultLanguage;
00624 }
00625 
00626 ?>