eZ Publish  [trunk]
ezimagemanager.php
Go to the documentation of this file.
00001 <?php
00002 /**
00003  * File containing the eZImageManager 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 lib
00009  */
00010 
00011 /*! \defgroup eZImage Image conversion and scaling */
00012 
00013 /*!
00014   \class eZImageManager ezimagemanager.php
00015   \ingroup eZImage
00016   \brief Manages image operations using delegates to do the work
00017 
00018   The manager allows for transparent conversion of one image format
00019   to another. The conversion may be done in one step if the required
00020   conversion type is available or it may build a tree of conversion
00021   rules which is needed to reach the desired end format.
00022 
00023   It's also possible to run operations on images. It's up to each conversion
00024   rule to report whether or not the operation is supported, the manager will
00025   then distribute the operations on the available rules which can handle them.
00026   Examples of operations are scaling and grayscale.
00027 
00028   The scale operation is special and is known to the manager directly while
00029   the other operations must be recognized by the converter.
00030 
00031   In determing what image rules to be used the manager must first know
00032   which output types are allowed, this is set with setOutputTypes().
00033   It takes an array of mimetypes which are allowed.
00034 
00035   The manager must then be fed conversion rules, these tell which conversion
00036   type is used for converting from the source mimetype to the destination
00037   mimetype. The rules are set with setRules() which accepts an array of
00038   rules and a default rule as paremeter. The default rule is used when no
00039   other mimetype match is found.
00040   To create a rule you should use the createRule() function, it takes the source
00041   and destination mimetype as well as the conversion type name. Optionally
00042   it can specified whether the rule can scale or run operations.
00043 
00044   The last thing that needs to be done is to specify the mimetypes. The manager
00045   uses mimetypes internally to know what type of image it's working on.
00046   To go from a filename to a mimetype a set of matches must be setup. The matches
00047   are created with createMIMEType() which takes the mimetype, regex filename match
00048   and suffix as parameter. The mimetypes are then registered with setMIMETypes().
00049 
00050   See <a href="http://www.iana.org/">www.iana.org</a> for information on MIME types.
00051 
00052   Now the manager is ready and you can convert images with convert().
00053 
00054   Example:
00055 \code
00056 $img = eZImageManager::instance();
00057 $img->registerType( "convert", new eZImageShell( '', "convert", array(), array(),
00058                                                  array( eZImageShell::createRule( "-geometry %wx%h>", // Scale rule
00059                                                                                   "modify/scale" ),
00060                                                         eZImageShell::createRule( "-colorspace GRAY", // Grayscale rule
00061                                                                                   "colorspace/gray" ) ) ) ); // Register shell program convert
00062 $img->registerType( "gd", new eZImageGD() ); // Register PHP converter GD
00063 
00064 $img->setOutputTypes( array( "image/jpeg",
00065                              "image/png" ) ); // We only want jpeg and png, gif is not recommended due to licencing issues.
00066 $rules = array( $img->createRule( "image/jpeg", "image/jpeg", "GD", true, false ), // Required for scaling jpeg images
00067                 $img->createRule( "image/gif", "image/png", "convert", true, false ) ); // Convert GIF to png
00068 $img->setRules( $rules, $img->createRule( "*", "image/png", "convert", true, false ) ); // Convert all other images to PNG with convert
00069 
00070 $mime_rules = array( $img->createMIMEType( "image/jpeg", "\.jpe?g$", "jpg" ),
00071                      $img->createMIMEType( "image/png", "\.png$", "png" ),
00072                      $img->createMIMEType( "image/gif", "\.gif$", "gif" ) );
00073 $img->setMIMETypes( $mime_rules ); // Register mimetypes
00074 
00075 $img1 = $img->convert( "image1.gif", "cache/" ); // Convert GIF and places it in cache dir
00076 $img1 = $img->convert( "image1.png", "cache/", // Scale PNG image and place in cache dir
00077                        array( "width" => 200, "height" => 200 ), // Scale parameter
00078                        array( array( "rule-type" => "colorspace/gray" ) ) ); // Gray scale conversion
00079  \endcode
00080 
00081 
00082 */
00083 
00084 class eZImageManager
00085 {
00086     /*!
00087      Initializes the manager by registering a application/octet-stream mimetype
00088      which is applied for all unknown files.
00089     */
00090     function eZImageManager()
00091     {
00092         $this->SupportedFormats = array();
00093         $this->SupportedMIMEMap = array();
00094         $this->ImageHandlers = array();
00095         $this->AliasList = array();
00096         $this->Factories = array();
00097         $this->ImageFilters = array();
00098         $this->MIMETypeSettings = array();
00099         $this->MIMETypeSettingsMap = array();
00100         $this->QualityValues = array();
00101         $this->QualityValueMap = array();
00102 
00103         $ini = eZINI::instance( 'image.ini' );
00104         $this->TemporaryImageDirPath = eZSys::cacheDirectory() . '/' . $ini->variable( 'FileSettings', 'TemporaryDir' );
00105     }
00106 
00107     /*!
00108      Sets which MIME-Types are allowed to use for destination format, this is an array of MIME-Type names.
00109      e.g.
00110      \code
00111      $manager->setOutputTypes( array( 'image/jpeg', 'image/gif' ) );
00112      \endcode
00113     */
00114     function setSupportedFormats( $mimeList )
00115     {
00116         $this->SupportedFormats = $mimeList;
00117         $this->SupportedMIMEMap = array();
00118         foreach ( $mimeList as $mimeName )
00119         {
00120             $this->SupportedMIMEMap[$mimeName] = true;
00121         }
00122     }
00123 
00124     /*!
00125      Sets which MIME-Types are allowed to use for destination format, this is an array of MIME-Type names.
00126      e.g.
00127      \code
00128      $manager->setOutputTypes( array( 'image/jpeg', 'image/gif' ) );
00129      \endcode
00130     */
00131     function appendSupportedFormat( $mimeName )
00132     {
00133         $this->SupportedFormats[] = $mimeName;
00134         $this->SupportedMIMEMap[$mimeName] = true;
00135     }
00136 
00137     /*!
00138      Appends the image handler \a $handler to the list of known handlers in the image system.
00139      Onces it is added the supported image filters for that handler is extracted.
00140 
00141      \note If the handler is not available (isAvailable()) it will not be added.
00142     */
00143     function appendImageHandler( $handler )
00144     {
00145         if ( !$handler )
00146             return false;
00147         if ( !$handler->isAvailable() )
00148             return false;
00149         $this->ImageHandlers[] = $handler;
00150         $this->ImageFilters = array_merge( $this->ImageFilters, $handler->supportedImageFilters() );
00151         $this->ImageFilters = array_unique( $this->ImageFilters );
00152         return true;
00153     }
00154 
00155     /*!
00156      \return \c true if the filtername \a $filtername is supported by any of the image handlers.
00157     */
00158     function isFilterSupported( $filterName )
00159     {
00160         return in_array( $filterName, $this->ImageFilters );
00161     }
00162 
00163     /*!
00164      Returns a list of defined image aliases in the image system.
00165      Each entry in the list is an associative array with the following keys:
00166      - name - The name of the alias
00167      - reference - The name of the alias it refers to or \c false if no reference
00168      - mime_type - Controls which MIME-Type the alias will be in, or \c false if not defined.
00169      - filters - An array with filters which applies to this alias
00170      - alias_key - The CRC key for this alias, it is created from the current values of the alias
00171                    and will change each time the alias values changes
00172     */
00173     function aliasList()
00174     {
00175         $aliasList = $this->AliasList;
00176         if ( !isset( $aliasList['original'] ) )
00177         {
00178             $alias = array( 'name' => 'original',
00179                             'reference' => false,
00180                             'mime_type' => false,
00181                             'filters' => array() );
00182             $alias['alias_key'] = $this->createImageAliasKey( $alias );
00183             $aliasList['original'] = $alias;
00184         }
00185         return $aliasList;
00186     }
00187 
00188     /*!
00189      \return \c true if the image alias \a $aliasName exists.
00190     */
00191     function hasAlias( $aliasName )
00192     {
00193         $aliasList = $this->aliasList();
00194         return array_key_exists( $aliasName, $aliasList );
00195     }
00196 
00197     /*!
00198      \return the definition for the Image Alias named \a $aliasName.
00199     */
00200     function alias( $aliasName )
00201     {
00202         $aliasList = $this->aliasList();
00203         if ( !array_key_exists( $aliasName, $aliasList ) )
00204             return false;
00205         return $aliasList[$aliasName];
00206     }
00207 
00208     /*!
00209      Appends the image alias \a $alias to the list of defined aliases.
00210     */
00211     function appendImageAlias( $alias )
00212     {
00213         $key = $this->createImageAliasKey( $alias );
00214         $alias['alias_key'] = $key;
00215         $this->AliasList[$alias['name']] = $alias;
00216         return $key;
00217     }
00218 
00219     /*!
00220      Creates a unique key for the image alias and returns it.
00221      \note The key is an MD5 of the alias settings and is used to determine if alias settings has changed.
00222     */
00223     function createImageAliasKey( $alias )
00224     {
00225         $keyData = array( $alias['name'],
00226                           $alias['reference'],
00227                           $alias['mime_type'] );
00228         if ( $alias['reference'] )
00229         {
00230             $referenceAlias = $this->alias( $alias['reference'] );
00231             if ( $referenceAlias )
00232                 $keyData[] = $referenceAlias['alias_key'];
00233         }
00234         foreach ( $alias['filters'] as $filter )
00235         {
00236             $filterData = $filter['name'];
00237             if ( is_array( $filter['data'] ) )
00238                 $filterData .= '=' . implode( ',', $filter['data'] );
00239             $keyData[] = $filterData;
00240         }
00241 
00242         $key = eZSys::ezcrc32( implode( "\n", $keyData ) );
00243 
00244         return $key;
00245     }
00246 
00247     /*!
00248      \return \c true if the Image Alias \a $alias is valid for use.
00249              This is tested by checking the key against the key for current Image Alias settings.
00250     */
00251     function isImageAliasValid( $alias )
00252     {
00253         $aliasName = $alias['name'];
00254         if ( isset( $this->AliasList[$aliasName] ) )
00255         {
00256             $aliasKey = $alias['alias_key'];
00257             $aliasInfo = $this->AliasList[$aliasName];
00258             $checkKey = $aliasInfo['alias_key'];
00259             $isValid = ( $aliasKey == $checkKey );
00260             if ( $isValid )
00261             {
00262                 $aliasTimestamp = $alias['timestamp'];
00263                 $isValid = $this->isImageTimestampValid( $aliasTimestamp );
00264             }
00265             return $isValid;
00266         }
00267         return false;
00268     }
00269 
00270     /*!
00271      \return \c true if the timestamp \a $timestamp is newer than the image alias expiry timestamp.
00272      The image alias expiry timestamp will be set whenever the image aliases must be recreated.
00273 
00274      \note Normally the expiry timestamp is not set.
00275     */
00276     function isImageTimestampValid( $timestamp )
00277     {
00278         eZExpiryHandler::registerShutdownFunction();
00279         $expiryHandler = eZExpiryHandler::instance();
00280         if ( $expiryHandler->hasTimestamp( 'image-manager-alias' ) )
00281         {
00282             $aliasTimestamp = $expiryHandler->timestamp( 'image-manager-alias' );
00283             return ( $timestamp > $aliasTimestamp );
00284         }
00285         return true;
00286     }
00287 
00288     /*!
00289      Reads all image aliases from the INI file 'image.ini'
00290      and appends them to the image system.
00291      \param $iniFile The INI file to read from or if \c false use 'image.ini'
00292     */
00293     function readImageAliasesFromINI( $iniFile = false )
00294     {
00295         if ( !$iniFile )
00296             $iniFile = 'image.ini';
00297         $ini = eZINI::instance( $iniFile );
00298         if ( !$ini )
00299             return false;
00300         $aliasNames = $ini->variable( 'AliasSettings', 'AliasList' );
00301         foreach ( $aliasNames as $aliasName )
00302         {
00303             $alias = $this->createAliasFromINI( $aliasName );
00304             if ( $alias )
00305             {
00306                 $this->appendImageAlias( $alias );
00307             }
00308             else
00309                 eZDebug::writeWarning( "Failed reading Image Alias $aliasName from $iniFile", __METHOD__ );
00310         }
00311         $aliasName = 'original';
00312         if ( !in_array( $aliasName, $aliasNames ) )
00313         {
00314             $ini = eZINI::instance( 'image.ini' );
00315             if ( $ini->hasGroup( $aliasName ) )
00316             {
00317                 $alias = $this->createAliasFromINI( $aliasName );
00318                 if ( $alias )
00319                 {
00320                     $alias['reference'] = false;
00321                     $this->appendImageAlias( $alias );
00322                 }
00323                 else
00324                 {
00325                     eZDebug::writeWarning( "Failed reading Image Alias $aliasName from $iniFile", __METHOD__ );
00326                 }
00327             }
00328         }
00329     }
00330 
00331     /*!
00332      Reads all supported image formats from the INI file 'image.ini'
00333      and appends them to the image system.
00334      \param $iniFile The INI file to read from or if \c false use 'image.ini'
00335     */
00336     function readSupportedFormatsFromINI( $iniFile = false )
00337     {
00338         if ( !$iniFile )
00339             $iniFile = 'image.ini';
00340         $ini = eZINI::instance( $iniFile );
00341         if ( !$ini )
00342             return false;
00343         $allowedOutputFormats = $ini->variable( 'OutputSettings', 'AllowedOutputFormat' );
00344         foreach ( $allowedOutputFormats as $allowedOutputFormat )
00345         {
00346             $this->appendSupportedFormat( $allowedOutputFormat );
00347         }
00348     }
00349 
00350     /*!
00351      \return \c true if the MIME-Type defined in \a $mimeData exists in the image system.
00352     */
00353     function hasMIMETypeSetting( $mimeData )
00354     {
00355         return isset( $this->MIMETypeSettingsMap[$mimeData['name']] );
00356     }
00357 
00358     /*!
00359      \return The setting for the MIME-Type defined in \a $mimeData.
00360     */
00361     function mimeTypeSetting( $mimeData )
00362     {
00363         if ( !isset( $this->MIMETypeSettingsMap[$mimeData['name']] ) )
00364             return false;
00365         $list = $this->MIMETypeSettingsMap[$mimeData['name']];
00366         foreach ( $list as $item )
00367         {
00368             if ( is_array( $item['match'] ) )
00369             {
00370                 if ( array_key_exists( 'info', $mimeData ) && is_array( $mimeData['info'] ) )
00371                 {
00372                     $isMatch = true;
00373                     $info = $mimeData['info'];
00374                     foreach ( $item['match'] as $matchKey => $matchValue )
00375                     {
00376                         if ( !isset( $info[$matchKey] ) or
00377                              $info[$matchKey] != $matchValue )
00378                         {
00379                             $isMatch = false;
00380                             break;
00381                         }
00382                     }
00383                     if ( $isMatch )
00384                         return $item;
00385                 }
00386             }
00387             else
00388                 return $item;
00389         }
00390         return false;
00391     }
00392 
00393     /*!
00394      Calls eZImageHandler::wildcardToRegexp() to generate
00395      a regular expression out of the wilcard and return it.
00396     */
00397     static function wildcardToRegexp( $wildcard, $separatorCharacter = false )
00398     {
00399         return eZImageHandler::wildcardToRegexp( $wildcard, $separatorCharacter );
00400     }
00401 
00402     /*!
00403      \return The override MIME-Type for the MIME structure \a $mimeData or \c false if no override.
00404     */
00405     function mimeTypeOverride( $mimeData )
00406     {
00407         if ( $this->hasMIMETypeSetting( $mimeData ) )
00408         {
00409             $settings = $this->mimeTypeSetting( $mimeData );
00410             if ( $settings )
00411             {
00412                 return $settings['override_mime_type'];
00413             }
00414         }
00415         return false;
00416     }
00417 
00418     /*!
00419      \return An array with extra filters for the MIME-Type defined in \a $mimeData
00420              or \c false if no filters.
00421     */
00422     function mimeTypeFilters( $mimeData )
00423     {
00424         if ( $this->hasMIMETypeSetting( $mimeData ) )
00425         {
00426             $settings = $this->mimeTypeSetting( $mimeData );
00427             if ( $settings )
00428             {
00429                 return $settings['extra_filters'];
00430             }
00431         }
00432         return false;
00433     }
00434 
00435     /*!
00436      \return \c true if the filtername \a $filtername is allowed to be used on the type defined in \a $mimeData.
00437     */
00438     function isFilterAllowed( $filterName, $mimeData )
00439     {
00440         if ( $this->hasMIMETypeSetting( $mimeData ) )
00441         {
00442             $settings = $this->mimeTypeSetting( $mimeData );
00443             if ( $settings )
00444             {
00445                 if ( is_array( $settings['disallowed_filters'] ) )
00446                 {
00447                     foreach ( $settings['disallowed_filters'] as $filter )
00448                     {
00449                         $regexp = eZImageManager::wildcardToRegexp( $filter );
00450                         if ( preg_match( '#' . $regexp . '#', $filterName ) )
00451                         {
00452                             return false;
00453                         }
00454                     }
00455                 }
00456                 if ( is_array( $settings['allowed_filters'] ) )
00457                 {
00458                     foreach ( $settings['allowed_filters'] as $filter )
00459                     {
00460                         $regexp = eZImageManager::wildcardToRegexp( $filter );
00461                         if ( preg_match( '#' . $regexp . '#', $filterName ) )
00462                         {
00463                             return true;
00464                         }
00465                     }
00466                     return false;
00467                 }
00468                 return true;
00469             }
00470         }
00471         return true;
00472     }
00473 
00474     /*!
00475      Binds the quality value \a $qualityValue to the MIME-Type \a $mimeType.
00476     */
00477     function appendQualityValue( $mimeType, $qualityValue )
00478     {
00479         $element = array( 'name' => $mimeType,
00480                           'value' => $qualityValue );
00481         $this->QualityValues[] = $element;
00482         $this->QualityValueMap[$mimeType] = $element;
00483     }
00484 
00485     /*!
00486      \return the quality value for MIME-Type \a $mimeType or \c false if none exists.
00487     */
00488     function qualityValue( $mimeType )
00489     {
00490         if ( isset( $this->QualityValueMap[$mimeType] ) )
00491             return $this->QualityValueMap[$mimeType]['value'];
00492         return false;
00493     }
00494 
00495     /*!
00496      Appends the MIME-Type setting \a $settings to the image system.
00497     */
00498     function appendMIMETypeSetting( $settings )
00499     {
00500         $this->MIMETypeSettings[] = $settings;
00501         if ( !isset( $this->MIMETypeSettingsMap[$settings['mime_type']] ) )
00502             $this->MIMETypeSettingsMap[$settings['mime_type']] = array();
00503         $this->MIMETypeSettingsMap[$settings['mime_type']][] = $settings;
00504     }
00505 
00506     /*!
00507      Reads all MIME-Type settings from the INI file 'image.ini'
00508      and appends them to the image system.
00509      \param $iniFile The INI file to read from or if \c false use 'image.ini'
00510     */
00511     function readMIMETypeSettingsFromINI( $iniFile = false )
00512     {
00513         if ( !$iniFile )
00514             $iniFile = 'image.ini';
00515         $ini = eZINI::instance( $iniFile );
00516         if ( !$ini )
00517             return false;
00518         $overrideList = $ini->variable( 'MIMETypeSettings', 'OverrideList' );
00519         foreach ( $overrideList as $mimeType )
00520         {
00521             $settings = eZImageManager::readMIMETypeSettingFromINI( $mimeType );
00522             if ( $settings )
00523                 $this->appendMIMETypeSetting( $settings );
00524         }
00525     }
00526 
00527     /*!
00528      Reads MIME-Type quality settings and appends them.
00529     */
00530     function readMIMETypeQualitySettingFromINI( $iniFile = false )
00531     {
00532         if ( !$iniFile )
00533             $iniFile = 'image.ini';
00534         $ini = eZINI::instance( $iniFile );
00535         if ( !$ini )
00536             return false;
00537         if ( !$ini->hasVariable( 'MIMETypeSettings', 'Quality' ) )
00538             return false;
00539         $values = $ini->variable( 'MIMETypeSettings', 'Quality' );
00540         foreach ( $values as $value )
00541         {
00542             $elements = explode( ';', $value );
00543             $mimeType = $elements[0];
00544             $qualityValue = $elements[1];
00545             $this->appendQualityValue( $mimeType, $qualityValue );
00546         }
00547     }
00548 
00549     /*!
00550      Reads in global conversion rules from INI file.
00551     */
00552     function readConversionRuleSettingsFromINI( $iniFile = false )
00553     {
00554         if ( !$iniFile )
00555             $iniFile = 'image.ini';
00556         $ini = eZINI::instance( $iniFile );
00557         if ( !$ini )
00558             return false;
00559         if ( $ini->hasVariable( 'MIMETypeSettings', 'ConversionRules' ) )
00560         {
00561             $conversionRules = array();
00562             $rules = $ini->variable( 'MIMETypeSettings', 'ConversionRules' );
00563             foreach ( $rules as $ruleString )
00564             {
00565                 $ruleItems = explode( ';', $ruleString );
00566                 if ( count( $ruleItems ) >= 2 )
00567                 {
00568                     $conversionRule = array( 'from' => $ruleItems[0],
00569                                              'to' => $ruleItems[1] );
00570                     $this->appendConversionRule( $conversionRule );
00571                 }
00572             }
00573         }
00574     }
00575 
00576     /*!
00577      Will read in all required INI settings.
00578     */
00579     function readINISettings()
00580     {
00581         $this->readImageHandlersFromINI();
00582         $this->readSupportedFormatsFromINI();
00583         $this->readImageAliasesFromINI();
00584         $this->readMIMETypeSettingsFromINI();
00585         $this->readMIMETypeQualitySettingFromINI();
00586         $this->readConversionRuleSettingsFromINI();
00587     }
00588 
00589     /*!
00590      Appends a new global conversion rule.
00591     */
00592     function appendConversionRule( $conversionRule )
00593     {
00594         $this->ConversionRules[] = $conversionRule;
00595     }
00596 
00597     /*!
00598      \return The global conversion rules.
00599     */
00600     function conversionRules()
00601     {
00602         return $this->ConversionRules;
00603     }
00604 
00605     /*!
00606      Reads a single MIME-Type setting from the INI file 'image.ini'
00607      and appends them to the image system.
00608      \param $mimeGroup Which INI group to read settings from.
00609      \param $iniFile The INI file to read from or if \c false use 'image.ini'
00610      \return The settings that were read.
00611     */
00612     function readMIMETypeSettingFromINI( $mimeGroup, $iniFile = false )
00613     {
00614         if ( !$iniFile )
00615             $iniFile = 'image.ini';
00616         $ini = eZINI::instance( $iniFile );
00617         if ( !$ini )
00618             return false;
00619         if ( !$ini->hasGroup( $mimeGroup ) )
00620             return false;
00621         if ( !$ini->hasVariable( $mimeGroup, 'MIMEType' ) )
00622             return false;
00623         $settings = array( 'name' => $mimeGroup,
00624                            'match' => false,
00625                            'mime_type' => false,
00626                            'override_mime_type' => false,
00627                            'allowed_filters' => false,
00628                            'disallowed_filters' => false,
00629                            'extra_filters' => false );
00630         $settings['mime_type'] = $ini->variable( $mimeGroup, 'MIMEType' );
00631         $ini->assign( $mimeGroup, 'Match', $settings['match'] );
00632         $ini->assign( $mimeGroup, 'OverrideMIMEType', $settings['override_mime_type'] );
00633         $ini->assign( $mimeGroup, 'AllowedFilters', $settings['allowed_filters'] );
00634         $ini->assign( $mimeGroup, 'DisallowedFilters', $settings['disallowed_filters'] );
00635         if ( $ini->hasVariable( $mimeGroup, 'ExtraFilters' ) )
00636         {
00637             $filters = array();
00638             $filterRawList = $ini->variable( $mimeGroup, 'ExtraFilters' );
00639             foreach ( $filterRawList as $filterRawItem )
00640             {
00641                 $filters[] = $this->createFilterDataFromINI( $filterRawItem );
00642             }
00643             if ( count( $filters ) > 0 )
00644                 $settings['extra_filters'] = $filters;
00645         }
00646         return $settings;
00647     }
00648 
00649     /*!
00650      Reads all settings for image handlers from the INI file 'image.ini'
00651      and appends them to the image system.
00652      \param $iniFile The INI file to read from or if \c false use 'image.ini'
00653     */
00654     function readImageHandlersFromINI( $iniFile = false )
00655     {
00656         if ( !$iniFile )
00657             $iniFile = 'image.ini';
00658         $ini = eZINI::instance( $iniFile );
00659         if ( !$ini )
00660             return false;
00661 
00662         $converterList = $ini->variable( 'ImageConverterSettings', 'ImageConverters' );
00663         foreach ( $converterList as $converterName )
00664         {
00665             if ( $ini->hasGroup( $converterName ) )
00666             {
00667                 if ( $ini->hasVariable( $converterName, 'Handler' ) )
00668                 {
00669                     $factoryName = $ini->variable( $converterName, 'Handler' );
00670                     $factory = $this->factoryFor( $factoryName, $iniFile, $converterName );
00671                     if ( $factory )
00672                     {
00673                         $convertHandler = $factory->produceFromINI( $converterName, $iniFile );
00674                         $this->appendImageHandler( $convertHandler );
00675                     }
00676                 }
00677                 else
00678                 {
00679                     eZDebug::writeWarning( "INI group $converterName does not have a Handler setting, cannot instantiate handler without it", __METHOD__ );
00680                 }
00681             }
00682             else
00683             {
00684                 eZDebug::writeWarning( "No INI group $converterName for Image Handler $converterName, cannot instantiate", __METHOD__ );
00685             }
00686         }
00687     }
00688 
00689     /*!
00690      Finds the image handler factory with the name \a $factoryName and returns it.
00691      \param $iniFile The INI file to read from or if \c false use 'image.ini'
00692     */
00693     function factoryFor( $factoryName, $iniFile = false, $converterName = false )
00694     {
00695         if ( !$iniFile )
00696             $iniFile = 'image.ini';
00697         if ( isset( $this->Factories[$factoryName] ) )
00698         {
00699             return $this->Factories[$factoryName];
00700         }
00701         else
00702         {
00703             $optionArray = array( 'iniFile'       => $iniFile,
00704                                   'iniSection'    => $converterName,
00705                                   'iniVariable'   => 'Handler' );
00706 
00707             $options = new ezpExtensionOptions( $optionArray );
00708 
00709             $factory = eZExtension::getHandlerClass( $options );
00710 
00711             return $this->Factories[$factoryName] = $factory;
00712         }
00713 
00714         return false;
00715     }
00716 
00717     /*!
00718      Parses the filter text \a $filterText which is taken from an INI file
00719      and returns a filter data structure for it.
00720     */
00721     function createFilterDataFromINI( $filterText )
00722     {
00723         $equalPosition = strpos( $filterText, '=' );
00724         $filterData = false;
00725         if ( $equalPosition !== false )
00726         {
00727             $filterName = substr( $filterText, 0, $equalPosition );
00728             $filterDataText = substr( $filterText, $equalPosition + 1 );
00729             $filterData = explode( ';', $filterDataText );
00730         }
00731         else
00732             $filterName = $filterText;
00733         return array( 'name' => $filterName,
00734                       'data' => $filterData );
00735     }
00736 
00737     /*!
00738      Parses the INI group \a $iniGroup and creates an Image Alias from it.
00739      \return the Image Alias structure.
00740     */
00741     function createAliasFromINI( $iniGroup )
00742     {
00743         $ini = eZINI::instance( 'image.ini' );
00744         if ( !$ini->hasGroup( $iniGroup ) )
00745         {
00746             eZDebug::writeError( "No such group $iniGroup in ini file image.ini", __METHOD__ );
00747             return false;
00748         }
00749         $alias = array( 'name' => $iniGroup,
00750                         'reference' => false,
00751                         'mime_type' => false,
00752                         'filters' => array() );
00753         if ( $ini->hasVariable( $iniGroup, 'Name' ) )
00754             $alias['name'] = $ini->variable( $iniGroup, 'Name' );
00755         if ( $ini->hasVariable( $iniGroup, 'MIMEType' ) )
00756             $alias['mime_type'] = $ini->variable( $iniGroup, 'MIMEType' );
00757         if ( $ini->hasVariable( $iniGroup, 'Filters' ) )
00758         {
00759             $filters = array();
00760             $filterRawList = $ini->variable( $iniGroup, 'Filters' );
00761             foreach ( $filterRawList as $filterRawItem )
00762             {
00763                 $filters[] = $this->createFilterDataFromINI( $filterRawItem );
00764             }
00765             $alias['filters'] = $filters;
00766         }
00767         if ( $ini->hasVariable( $iniGroup, 'Reference' ) )
00768             $alias['reference'] = $ini->variable( $iniGroup, 'Reference' );
00769         return $alias;
00770     }
00771 
00772     /**
00773      * Creates the image alias $aliasName if it's not already part of the
00774      * existing aliases
00775      *
00776      * @param string $aliasName Name of the alias to create
00777      * @param array $existingAliasList
00778      *        Reference to the current alias list. The created alias will be
00779      *        added to the list.
00780      * @param array $parameters
00781      *        Optional array that can be used to specify the image's basename
00782      * @return bool true if the alias was created, false if it wasn't
00783      */
00784     function createImageAlias( $aliasName, &$existingAliasList, $parameters = array() )
00785     {
00786         $fname = "createImageAlias( $aliasName )";
00787 
00788         // check for $aliasName validity
00789         $aliasList = $this->aliasList();
00790         if ( !isset( $aliasList[$aliasName] ) )
00791         {
00792             eZDebug::writeWarning( "Alias name $aliasName does not exist, cannot create it" );
00793             return false;
00794         }
00795 
00796         // check if the reference alias is defined, and if no, use original as ref
00797         $currentAliasInfo = $aliasList[$aliasName];
00798         $referenceAlias = $currentAliasInfo['reference'];
00799         if ( $referenceAlias and !$this->hasAlias( $referenceAlias ) )
00800         {
00801             eZDebug::writeError( "The referenced alias '$referenceAlias' for image alias '$aliasName' does not exist, cannot use it for reference.\n" .
00802                                  "Will use 'original' alias instead.",
00803                                  __METHOD__ );
00804             $referenceAlias = false;
00805         }
00806         if ( !$referenceAlias )
00807             $referenceAlias = 'original';
00808 
00809         // generate the reference alias if it hasn't been generated yet
00810         $hasReference = false;
00811         if ( array_key_exists( $referenceAlias, $existingAliasList ) )
00812         {
00813             $fileHandler = eZClusterFileHandler::instance();
00814             if ( $fileHandler->fileExists( $existingAliasList[$referenceAlias]['url'] ) )
00815             {
00816                 $hasReference = true;
00817             }
00818             else
00819             {
00820                 eZDebug::writeError( "The reference alias $referenceAlias file {$existingAliasList[$referenceAlias]['url']} does not exist", __METHOD__ );
00821             }
00822         }
00823         if ( !$hasReference )
00824         {
00825             if ( $referenceAlias == 'original' )
00826             {
00827                 eZDebug::writeError( "Original alias does not exist, cannot create other aliases without it" );
00828                 return false;
00829             }
00830             if ( !$this->createImageAlias( $referenceAlias, $existingAliasList, $parameters ) )
00831             {
00832                 eZDebug::writeError( "Failed creating the referenced alias $referenceAlias, cannot create alias $aliasName", __METHOD__ );
00833                 return false;
00834             }
00835         }
00836 
00837         // from now on, our reference image (either reference or original)
00838         // exists
00839         $aliasInfo = $existingAliasList[$referenceAlias];
00840         $aliasFilePath = $aliasInfo['url'];
00841         $aliasKey = $currentAliasInfo['alias_key'];
00842 
00843         $sourceMimeData = eZMimeType::findByFileContents( $aliasFilePath );
00844 
00845         /**
00846          * at first, destinationMimeData (mimedata for the alias we're
00847          * generating) is the same as sourceMimeData. It will evolve as
00848          * alias generation goes on
00849          */
00850         $destinationMimeData = $sourceMimeData;
00851         if ( isset( $parameters['basename'] ) )
00852         {
00853             $sourceMimeData['basename'] = $parameters['basename'];
00854             eZMimeType::changeBasename( $destinationMimeData, $parameters['basename'] );
00855         }
00856 
00857         /**
00858          * Concurrency protection
00859          * startCacheGeneration will return true if the file is not
00860          * already being generated by another process. If it is, it will
00861          * return the maximum time before the generating process enters
00862          * generation timeout
00863          */
00864         while ( true )
00865         {
00866             $convertHandler = eZClusterFileHandler::instance( $sourceMimeData['url'] );
00867             $startGeneration = $convertHandler->startCacheGeneration();
00868             if ( $startGeneration === true )
00869             {
00870                 $destinationMimeData['is_valid'] = false;
00871                 if ( $this->convert( $sourceMimeData, $destinationMimeData, $aliasName, $parameters ) )
00872                 {
00873                     /**
00874                      * At this point, we consider that the image exists and destinationMimeData
00875                      * has been filled with the proper information
00876                      *
00877                      * If we were locked during alias generation, we need to recreate
00878                      * this structure so that the image can actually be used, but ONLY
00879                      * if it was the same alias... sounds like a HUGE mess.
00880                      *
00881                      * Can we reload the alias list somehow ?
00882                      */
00883                     $currentAliasData = array( 'url' => $destinationMimeData['url'],
00884                                                'dirpath' => $destinationMimeData['dirpath'],
00885                                                'filename' => $destinationMimeData['filename'],
00886                                                'suffix' => $destinationMimeData['suffix'],
00887                                                'basename' => $destinationMimeData['basename'],
00888                                                'alternative_text' => $aliasInfo['alternative_text'],
00889                                                'name' => $aliasName,
00890                                                'sub_type' => false,
00891                                                'timestamp' => time(),
00892                                                'alias_key' => $aliasKey,
00893                                                'mime_type' => $destinationMimeData['name'],
00894                                                'override_mime_type' => false,
00895                                                'info' => false,
00896                                                'width' => false,
00897                                                'height' => false,
00898                                                'is_valid' => true,
00899                                                'is_new' => true );
00900 
00901                     if ( isset( $destinationMimeData['override_mime_type'] ) )
00902                         $currentAliasData['override_mime_type'] = $destinationMimeData['override_mime_type'];
00903                     if ( isset( $destinationMimeData['info'] ) )
00904                         $currentAliasData['info'] = $destinationMimeData['info'];
00905                     $currentAliasData['full_path'] = $currentAliasData['url'];
00906 
00907                     if ( function_exists( 'getimagesize' ) )
00908                     {
00909                         /**
00910                          * we may want to fetch a unique name here, since we won't use
00911                          * the data for anything else
00912                          */
00913                         $fileHandler = eZClusterFileHandler::instance( $destinationMimeData['url'] );
00914                         if ( $tempPath = $fileHandler->fetchUnique() )
00915                         {
00916                             $info = getimagesize( $tempPath );
00917                             if ( $info )
00918                             {
00919                                 list( $currentAliasData['width'], $currentAliasData['height'] ) = $info;
00920                             }
00921                             else
00922                             {
00923                                 eZDebug::writeError("The size of the generated image {$destinationMimeData['url']} could not be read by getimagesize()", __METHOD__ );
00924                             }
00925                             $fileHandler->fileDeleteLocal( $tempPath );
00926                         }
00927                         else
00928                         {
00929                             eZDebug::writeError( "The destination image {$destinationMimeData['url']} does not exist, cannot figure out image size", __METHOD__ );
00930                         }
00931                     }
00932                     else
00933                     {
00934                         eZDebug::writeError( "Unknown function 'getimagesize', cannot get image size", __METHOD__ );
00935                     }
00936                     $existingAliasList[$aliasName] = $currentAliasData;
00937 
00938                     $convertHandler->endCacheGeneration( false );
00939 
00940                     // Notify about image alias generation. Parameters are alias
00941                     // url and alias name.
00942                     ezpEvent::getInstance()->notify( 'image/alias', array( $currentAliasData['url'],
00943                                                                            $currentAliasData['name'] ) );
00944                     
00945                     return true;
00946                 }
00947                 // conversion failed, we abort generation
00948                 else
00949                 {
00950                     $sourceFile = $sourceMimeData['url'];
00951                     $destinationDir = $destinationMimeData['dirpath'];
00952                     eZDebug::writeError( "Failed converting $sourceFile to alias '$aliasName' in directory '$destinationDir'", __METHOD__ );
00953                     $convertHandler->abortCacheGeneration();
00954                     return false;
00955                 }
00956             }
00957             // we were not granted file generation (someone else is doing it)
00958             // we wait for max. $remainingGenerationTime and check if the
00959             // file has been generated in between
00960             // Actually, we have no clue if the generated file was the one we were
00961             // looking for, and it doesn't seem possible to RELOAD the alias list.
00962             // We don't even know what attribute we're using... CRAP
00963             else
00964             {
00965                 eZDebug::writeDebug( "An alias is already being generated for this image, let's wait", __METHOD__ );
00966                 while ( true )
00967                 {
00968                     $startGeneration = $convertHandler->startCacheGeneration();
00969                     // generation lock granted: we can start again by breaking to
00970                     // the beggining of the while loop
00971                     if ( $startGeneration === true )
00972                     {
00973                         eZDebug::writeDebug( "Got granted generation permission, restarting !", __METHOD__ );
00974                         $convertHandler->abortCacheGeneration();
00975                         continue 2;
00976                     }
00977                     else
00978                     {
00979                         sleep( 1 );
00980                     }
00981                 }
00982             }
00983         }
00984         return false;
00985     }
00986 
00987     /*!
00988      \static
00989      Analyzes the image in the MIME structure \a $mimeData and fills in extra information if found.
00990      \return \c true if the image was succesfully analyzed, \c false otherwise.
00991      \note It will return \c true if there is no analyzer for the image type.
00992     */
00993     static function analyzeImage( &$mimeData, $parameters = array() )
00994     {
00995         $file = $mimeData['url'];
00996 
00997         if ( !file_exists( $file ) )
00998             return false;
00999         $analyzer = eZImageAnalyzer::createForMIME( $mimeData );
01000         $status = true;
01001         if ( is_object( $analyzer ) )
01002         {
01003             $imageInformation = $analyzer->process( $mimeData, $parameters );
01004             if ( $imageInformation )
01005             {
01006                 $mimeData['info'] = $imageInformation;
01007             }
01008             else
01009                 $status = false;
01010         }
01011         return $status;
01012     }
01013 
01014     /**
01015      * Converts the source image $sourceMimeData into the destination image
01016      * $destinationMimeData.
01017      *
01018      * @param mixed $sourceMimeData Source image, either a mimedata array or the
01019      *        source image path
01020      * @param mixed $destinationMimeData
01021      *        Either a mimedata array or the target image path
01022      * @param mixed $aliasName
01023      *        Target alias (small, medium, large...)
01024      * @param array $parameters
01025      *        Optional parameters. Known ones so far: (basename)
01026      * @return bool
01027      */
01028     function convert( $sourceMimeData, &$destinationMimeData, $aliasName = false, $parameters = array() )
01029     {
01030         // if the local file doesn't exist, we need to fetch it locally
01031         if ( !file_exists( $sourceMimeData['url'] ) )
01032         {
01033             $sourceFileHandler = eZClusterFileHandler::instance( $sourceMimeData['url'] );
01034             $sourceFileHandler->fetch();
01035         }
01036 
01037         if ( is_string( $sourceMimeData ) )
01038             $sourceMimeData = eZMimeType::findByFileContents( $sourceMimeData );
01039 
01040         $this->analyzeImage( $sourceMimeData );
01041         $currentMimeData = $sourceMimeData;
01042         $handlers = $this->ImageHandlers;
01043         $supportedMIMEMap = $this->SupportedMIMEMap;
01044         if ( is_string( $destinationMimeData ) )
01045         {
01046             $destinationPath = $destinationMimeData;
01047             $destinationMimeData = eZMimeType::findByFileContents( $destinationPath );
01048         }
01049 
01050         $filters = array();
01051         $alias = false;
01052         if ( $aliasName )
01053         {
01054             $aliasList = $this->aliasList();
01055             if ( isset( $aliasList[$aliasName] ) )
01056             {
01057                 $alias = $aliasList[$aliasName];
01058                 $filters = $alias['filters'];
01059                 if ( $alias['mime_type'] )
01060                 {
01061                     eZMimeType::changeMIMEType( $destinationMimeData, $alias['mime_type'] );
01062                 }
01063             }
01064         }
01065         $mimeTypeOverride = $this->mimeTypeOverride( $sourceMimeData );
01066         if ( $mimeTypeOverride )
01067             $alias['override_mime_type'] = $mimeTypeOverride;
01068 
01069         if ( isset( $parameters['filters'] ) )
01070         {
01071             $filters = array_merge( $filters, $parameters['filters'] );
01072         }
01073 
01074         $wantedFilters = $filters;
01075         $mimeTypeFilters = $this->mimeTypeFilters( $sourceMimeData );
01076         if ( is_array( $mimeTypeFilters ) )
01077             $wantedFilters = array_merge( $wantedFilters, $mimeTypeFilters );
01078         $filters = array();
01079         foreach ( array_keys( $wantedFilters ) as $wantedFilterKey )
01080         {
01081             $wantedFilter = $wantedFilters[$wantedFilterKey];
01082             if ( !$this->isFilterSupported( $wantedFilter['name'] ) )
01083             {
01084                 eZDebug::writeWarning( "The filter '" . $wantedFilter['name'] . "' is not supported by any of the image handlers, will ignore this filter", __METHOD__ );
01085                 continue;
01086             }
01087             $filters[] = $wantedFilter;
01088         }
01089         if ( !$destinationMimeData['is_valid'] )
01090         {
01091             $destinationDirPath = $destinationMimeData['dirpath'];
01092             $destinationBasename = $destinationMimeData['basename'];
01093             if ( isset( $supportedMIMEMap[$sourceMimeData['name']] ) )
01094             {
01095                 $destinationMimeData = $sourceMimeData;
01096                 if ( $alias['mime_type'] )
01097                 {
01098                     eZMimeType::changeMIMEType( $destinationMimeData, $alias['mime_type'] );
01099                 }
01100                 eZMimeType::changeFileData( $destinationMimeData, $destinationDirPath, $destinationBasename );
01101             }
01102             else
01103             {
01104                 $hasDestination = false;
01105                 foreach ( $handlers as $handler )
01106                 {
01107                     $gotMimeData = true;
01108                     while( $gotMimeData )
01109                     {
01110                         $gotMimeData = false;
01111                         $outputMimeData = $handler->outputMIMEType( $this, $sourceMimeData, false, $this->SupportedFormats, $aliasName );
01112                         if ( $outputMimeData and
01113                              isset( $supportedMIMEMap[$outputMimeData['name']] ) )
01114                         {
01115                             $destinationMimeData = $outputMimeData;
01116                             eZMimeType::changeFileData( $destinationMimeData, $destinationDirPath, $destinationBasename );
01117                             $hasDestination = true;
01118                             $gotMimeData = true;
01119                             break;
01120                         }
01121                     }
01122                 }
01123                 if ( !$hasDestination )
01124                 {
01125                     if ( isset( $sourceFileHandler ) )
01126                         $sourceFileHandler->deleteLocal();
01127                     return false;
01128                 }
01129             }
01130         }
01131 
01132         $wantedFilters = $filters;
01133         $filters = array();
01134         foreach ( array_keys( $wantedFilters ) as $wantedFilterKey )
01135         {
01136             $wantedFilter = $wantedFilters[$wantedFilterKey];
01137             if ( !$this->isFilterAllowed( $wantedFilter['name'], $destinationMimeData ) )
01138             {
01139                 continue;
01140             }
01141             $filters[] = $wantedFilter;
01142         }
01143         $result = true;
01144         $tempFiles = array();
01145         if ( $currentMimeData['name'] != $destinationMimeData['name'] or
01146              count( $filters ) > 0 )
01147         {
01148             while ( $currentMimeData['name'] != $destinationMimeData['name'] or
01149                     count( $filters ) > 0 )
01150             {
01151                 $nextMimeData = false;
01152                 $nextHandler = false;
01153                 foreach ( $handlers as $handler )
01154                 {
01155                     if ( !$handler )
01156                         continue;
01157 
01158                     $handlerFilters = array();
01159                     $leftoverFilters = array();
01160                     foreach ( $filters as $filter )
01161                     {
01162                         if ( $handler->isFilterSupported( $filter ) )
01163                             $handlerFilters[] = $filter;
01164                         else
01165                             $leftoverFilters[] = $filter;
01166                     }
01167 
01168                     $outputMimeData = $handler->outputMIMEType( $this, $currentMimeData, $destinationMimeData, $this->SupportedFormats, $aliasName );
01169                     if ( $outputMimeData['name'] == $destinationMimeData['name'] and count( $handlerFilters ) > 0 )
01170                     {
01171                         $nextMimeData = $outputMimeData;
01172                         $nextHandler = $handler;
01173                         break;
01174                     }
01175                     if ( $outputMimeData and
01176                          !$nextMimeData )
01177                     {
01178                         $nextMimeData = $outputMimeData;
01179                         $nextHandler = $handler;
01180                     }
01181                 }
01182                 if ( !$nextMimeData )
01183                 {
01184                     eZDebug::writeError( "None of the handlers can convert MIME-Type " . $currentMimeData['name'], __METHOD__ );
01185                     if ( isset( $sourceFile ) )
01186                         $sourceFile->deleteLocal();
01187                     return false;
01188                 }
01189 
01190                 $useTempImage = false;
01191                 if ( $nextMimeData['name'] == $destinationMimeData['name'] and
01192                      count( $leftoverFilters ) == 0 )
01193                 {
01194                     $nextMimeData['dirpath'] = $destinationMimeData['dirpath'];
01195                 }
01196                 else
01197                 {
01198                     $useTempImage = true;
01199                     $nextMimeData['dirpath'] = $this->temporaryImageDirPath();
01200                 }
01201                 eZMimeType::changeDirectoryPath( $nextMimeData, $nextMimeData['dirpath'] );
01202 
01203                 if ( $nextMimeData['dirpath'] and
01204                      !file_exists( $nextMimeData['dirpath'] ) )
01205                     eZDir::mkdir( $nextMimeData['dirpath'], false, true );
01206                 if ( $currentMimeData['name'] == $nextMimeData['name'] and
01207                      count( $handlerFilters ) == 0 )
01208                 {
01209                     if ( $currentMimeData['url'] != $nextMimeData['url'] )
01210                     {
01211                         if ( eZFileHandler::copy( $currentMimeData['url'], $nextMimeData['url'] ) )
01212                         {
01213                             if ( $useTempImage )
01214                                 $tempFiles[] = $nextMimeData['url'];
01215                         }
01216                         else
01217                         {
01218                             $result = false;
01219                             break;
01220                         }
01221                     }
01222                     $currentMimeData = $nextMimeData;
01223                 }
01224                 else
01225                 {
01226                     if ( $nextHandler->convert( $this, $currentMimeData, $nextMimeData, $handlerFilters ) )
01227                     {
01228                         if ( $useTempImage )
01229                             $tempFiles[] = $nextMimeData['url'];
01230                     }
01231                     else
01232                     {
01233                         $result = false;
01234                         break;
01235                     }
01236                     // store the converted file to cluster if the conversion is between mime name
01237                     $fileHandler = eZClusterFileHandler::instance();
01238                     $fileHandler->fileStore( $nextMimeData['url'], 'image', false, $nextMimeData['name']  );
01239 
01240                     $currentMimeData = $nextMimeData;
01241                 }
01242                 $filters = $leftoverFilters;
01243             }
01244         }
01245         else
01246         {
01247             $useCopy = false;
01248             if ( $aliasName and
01249                  $aliasName != 'original' )
01250             {
01251                 $destinationMimeData['filename'] = $destinationMimeData['basename'] . '_' . $aliasName . '.' . $destinationMimeData['suffix'];
01252                 if ( $destinationMimeData['dirpath'] )
01253                     $destinationMimeData['url'] = $destinationMimeData['dirpath'] . '/' . $destinationMimeData['filename'];
01254                 else
01255                     $destinationMimeData['url'] = $destinationMimeData['filename'];
01256             }
01257             if ( $sourceMimeData['url'] != $destinationMimeData['url'] )
01258             {
01259                 if ( $useCopy )
01260                 {
01261                     eZFileHandler::copy( $sourceMimeData['url'], $destinationMimeData['url'] );
01262                 }
01263                 else
01264                 {
01265                     eZFileHandler::linkCopy( $sourceMimeData['url'], $destinationMimeData['url'], false );
01266                 }
01267                 $currentMimeData = $destinationMimeData;
01268             }
01269         }
01270         foreach ( $tempFiles as $tempFile )
01271         {
01272             if ( !@unlink( $tempFile ) )
01273             {
01274                 eZDebug::writeError( "Failed to unlink temporary image file $tempFile", __METHOD__ );
01275             }
01276         }
01277         $destinationMimeData = $currentMimeData;
01278 
01279         if ( $aliasName && $aliasName != 'original' )
01280         {
01281             if ( $result )
01282             {
01283                 $destinationFilePath = $destinationMimeData['url'];
01284                 $fileHandler = eZClusterFileHandler::instance();
01285                 $fileHandler->fileStore( $destinationFilePath, 'image', true, $destinationMimeData['name'] );
01286             }
01287 
01288             if ( isset( $sourceFileHandler ) )
01289                 $sourceFileHandler->deleteLocal();
01290         }
01291 
01292         return $result;
01293     }
01294 
01295     /**
01296      * Image information for $aliasName. This is the information which normally
01297      * would be provided during generation of aliasName. This so that requests
01298      * not holding the lock will provide meaningful information.
01299      *
01300      * @param mixed $mimeData
01301      * @param string $aliasName
01302      * @return array
01303      */
01304     function imageAliasInfo( $mimeData, $aliasName, $isAliasNew = false )
01305     {
01306         if ( is_string( $mimeData ) )
01307             $mimeData = eZMimeType::findByFileContents( $mimeData );
01308 
01309         $this->analyzeImage( $mimeData );
01310         if ( $aliasName )
01311         {
01312             $aliasList = $this->aliasList();
01313             if ( isset( $aliasList[$aliasName] ) )
01314             {
01315                 $alias = $aliasList[$aliasName];
01316                 if ( $alias['mime_type'] )
01317                 {
01318                     eZMimeType::changeMIMEType( $mimeData, $alias['mime_type'] );
01319                 }
01320             }
01321         }
01322         if ( $aliasName != 'original' )
01323         {
01324             $mimeData['filename'] = $mimeData['basename'] . '_' . $aliasName . '.' . $mimeData['suffix'];
01325             $mimeData['url'] = $mimeData['dirpath'] . '/' . $mimeData['filename'];
01326         }
01327         // eZDebug::writeDebug( $mimeData, __METHOD__ );
01328         return $mimeData;
01329     }
01330 
01331     /*!
01332      \return the path for temporary images.
01333      \note The default value uses the temporary directory setting from site.ini.
01334     */
01335     function temporaryImageDirPath()
01336     {
01337         return $this->TemporaryImageDirPath;
01338     }
01339 
01340     /**
01341      * Returns a shared instance of the eZImageManager class.
01342      * Note: In most cases you'd want to use {@link self:factory()} instead.
01343      *
01344      * @return eZImageManager
01345      */
01346     static function instance()
01347     {
01348         if ( self::$instance === null )
01349         {
01350             self::$instance = new self();
01351         }
01352         return self::$instance;
01353     }
01354 
01355     /**
01356      * Returns a shared instance of the eZImageManager class and makes it ready for use.
01357      * As in calls {@link self::readINISettings()} and {@link eZImageAnalyzer::readAnalyzerSettingsFromINI()}
01358      *
01359      * @since 4.3
01360      * @return eZImageManager
01361      */
01362     static function factory()
01363     {
01364         if ( self::$factory === false )
01365         {
01366             self::$factory = true;
01367             self::instance()->readINISettings();
01368             eZImageAnalyzer::readAnalyzerSettingsFromINI();
01369         }
01370         return self::instance();
01371     }
01372 
01373     /**
01374      * Reset a shared instance of the eZImageManager class and factory variable.
01375      * As used by {@link eZImageManager::instance()} and {@link eZImageManager::factory()}
01376      *
01377      * @since 4.3
01378      */
01379     static function resetInstance()
01380     {
01381         self::$instance = null;
01382         self::$factory = false;
01383 
01384     }
01385 
01386     /// \privatesection
01387     public $ImageHandlers;
01388     public $OutputMIME;
01389     public $OutputMIMEMap;
01390     public $Rules;
01391     public $DefaultRule;
01392     public $RuleMap;
01393     public $MIMETypes;
01394     public $Types = array();
01395 
01396     /**
01397      * Singleton instance of eZImageManager used by {@link eZImageManager::instance()}
01398      * Reset with {@link eZImageManager::resetInstance()}
01399      *
01400      * @var null|eZImageManager
01401      */
01402     protected static $instance;
01403 
01404     /**
01405      * Factory flag as used by {@link eZImageManager::factory()}
01406      * Reset with {@link eZImageManager::resetInstance()}
01407      *
01408      * @var bool
01409      */
01410     protected static $factory = false;
01411 }
01412 ?>