eZ Publish  [4.0]
ezimagehandler.php
Go to the documentation of this file.
00001 <?php
00002 //
00003 // Definition of eZImageHandler class
00004 //
00005 // Created on: <16-Oct-2003 13:58:34 amos>
00006 //
00007 // ## BEGIN COPYRIGHT, LICENSE AND WARRANTY NOTICE ##
00008 // SOFTWARE NAME: eZ Publish
00009 // SOFTWARE RELEASE: 4.0.x
00010 // COPYRIGHT NOTICE: Copyright (C) 1999-2008 eZ Systems AS
00011 // SOFTWARE LICENSE: GNU General Public License v2.0
00012 // NOTICE: >
00013 //   This program is free software; you can redistribute it and/or
00014 //   modify it under the terms of version 2.0  of the GNU General
00015 //   Public License as published by the Free Software Foundation.
00016 //
00017 //   This program is distributed in the hope that it will be useful,
00018 //   but WITHOUT ANY WARRANTY; without even the implied warranty of
00019 //   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00020 //   GNU General Public License for more details.
00021 //
00022 //   You should have received a copy of version 2.0 of the GNU General
00023 //   Public License along with this program; if not, write to the Free
00024 //   Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
00025 //   MA 02110-1301, USA.
00026 //
00027 //
00028 // ## END COPYRIGHT, LICENSE AND WARRANTY NOTICE ##
00029 //
00030 
00031 /*! \file ezimagehandler.php
00032 */
00033 
00034 /*!
00035   \class eZImageHandler ezimagehandler.php
00036   \ingroup eZImage
00037   \brief The class eZImageHandler does
00038 
00039 */
00040 
00041 class eZImageHandler
00042 {
00043     const KEEP_SUFFIX = 1;
00044     const REPLACE_SUFFIX = 2;
00045     const PREPEND_TAG_REPLACE_SUFFIX = 3;
00046 
00047     /*!
00048      Initializes the image handler with data sent from the inheriting class.
00049      \param $handlerName The name of the current handler
00050      \param $isEnabled A boolean which tells whether the handler can be used or not
00051      \param $outputRewriteType Defines how output filenames are rewritten
00052      \param $supportedInputMIMETypes A list of MIME-Types the handler supports as input or \c false if no type as defined
00053      \param $supportedOutputMIMETypes A list of MIME-Types the handler supports as output or \c false if no type as defined
00054      \param $conversionRules A list of conversion rules specific for this handler, is combined with the global rules
00055      \param $filters A list of filters this handler supports
00056      \param $mimeTagMap A mapping table which maps from a MIME-Type to a specific tag, this tag can be used when rewriting the filename.
00057     */
00058     function eZImageHandler( $handlerName, $isEnabled = true, $outputRewriteType = self::REPLACE_SUFFIX,
00059                              $supportedInputMIMETypes = false, $supportedOutputMIMETypes,
00060                              $conversionRules = false, $filters = false, $mimeTagMap = false )
00061     {
00062         $this->HandlerName = $handlerName;
00063         $this->SupportedInputMIMETypes = $supportedInputMIMETypes;
00064         $this->SupportedOutputMIMETypes = $supportedOutputMIMETypes;
00065         $this->ConversionRules = $conversionRules;
00066         $this->OutputRewriteType = $outputRewriteType;
00067         $this->Filters = $filters;
00068         $this->FilterMap = array();
00069         $this->SupportImageFilters = array();
00070         $this->MIMETagMap = array();
00071         if ( $mimeTagMap )
00072             $this->MIMETagMap = $mimeTagMap;
00073         if ( $this->Filters)
00074         {
00075             foreach ( array_keys( $this->Filters ) as $filterKey )
00076             {
00077                 $filter =& $this->Filters[$filterKey];
00078                 $this->FilterMap[$filter['name']] =& $filter;
00079                 $this->SupportImageFilters[] = $filter['name'];
00080             }
00081         }
00082         $this->SupportImageFilters = array_unique( $this->SupportImageFilters );
00083         $this->IsEnabled = $isEnabled;
00084     }
00085 
00086     /*!
00087      \virtual
00088      \return whether this handler can be used or not.
00089 
00090      Implementors of image handlers should implement this to return true if
00091      the image conversion system to be used is available, for instance to check
00092      for a PHP extension.
00093      \note default is to return \c true.
00094     */
00095     function isAvailable()
00096     {
00097         return $this->IsEnabled;
00098     }
00099 
00100     /*!
00101      \virtual
00102      \return the tag for the MIME type named \a $mimeName.
00103      This is a helper function for some shell based handlers, it will create a
00104      proper name from the MIME type \a $mimeData.
00105      \note The default returns the type part of the MIME type.
00106     */
00107     function tagForMIMEType( $mimeData )
00108     {
00109         $name = $mimeData['name'];
00110         if ( isset( $this->MIMETagMap[$name] ) )
00111             return $this->MIMETagMap[$name];
00112         $position = strpos( $name, '/' );
00113         if ( $position !== false )
00114             return substr( $name, $position + 1 );
00115         else
00116             return false;
00117     }
00118 
00119     /*!
00120      \return an array with the names of the filters this handler can work with.
00121     */
00122     function supportedImageFilters()
00123     {
00124         return $this->SupportImageFilters;
00125     }
00126 
00127     /*!
00128      \return The conversion rules for this handler.
00129     */
00130     function conversionRules()
00131     {
00132         return $this->ConversionRules;
00133      }
00134 
00135     /*!
00136      Parses the filter text \a $filterText which is taken from an INI file
00137      and returns a filter definition structure for it.
00138     */
00139     static function createFilterDefinitionFromINI( $filterText )
00140     {
00141         $equalPosition = strpos( $filterText, '=' );
00142         $filterData = false;
00143         if ( $equalPosition !== false )
00144         {
00145             $filterName = substr( $filterText, 0, $equalPosition );
00146             $filterData = substr( $filterText, $equalPosition + 1 );
00147         }
00148         else
00149             $filterName = $filterText;
00150         return array( 'name' => $filterName,
00151                       'text' => $filterData );
00152     }
00153 
00154     /*!
00155      Converts a filter definition and filter data into a text string.
00156      This string is usually the commandline parameter.
00157     */
00158     static function convertFilterToText( $filterDefinition, $filterData )
00159     {
00160         $replaceList = array();
00161         if ( $filterData['data'] )
00162         {
00163             $counter = 1;
00164             foreach ( $filterData['data'] as $data )
00165             {
00166                 $replaceList['%' . $counter] = $data;
00167                 ++$counter;
00168             }
00169         }
00170         $argumentText = $filterDefinition['text'];
00171         $text = eZSys::createShellArgument( $argumentText, $replaceList );
00172         return $text;
00173     }
00174 
00175     /*!
00176      Calls convertFilterToText with the correct filter definition and returns the text.
00177     */
00178     function textForFilter( $filterData )
00179     {
00180         $text = false;
00181         if ( isset( $this->FilterMap[$filterData['name']] ) )
00182         {
00183             $filterDefinition =& $this->FilterMap[$filterData['name']];
00184             $text = $this->convertFilterToText( $filterDefinition, $filterData );
00185         }
00186         return $text;
00187     }
00188 
00189     /*!
00190      \virtual
00191      Rewrites the URL in \a $originalMimeData to become a url for \a $destinationMimeData.
00192      The type of rewrite is determined by \a $rewriteType which can be one of:
00193      - self::KEEP_SUFFIX - Does nothing to the url
00194      - self::REPLACE_SUFFIX - Replaces the suffix or the url
00195      - self::PREPEND_TAG_REPLACE_SUFFIX - Prepends the tag name and replaces the suffix of the url
00196      The new url is placed in the \a $destinationMimeData.
00197     */
00198     static function rewriteURL( $originalMimeData, &$destinationMimeData, $rewriteType, $aliasName = false )
00199     {
00200         $extraText = false;
00201         if ( $aliasName and
00202              $aliasName != 'original' )
00203             $extraText = '_' . $aliasName;
00204         switch ( $rewriteType )
00205         {
00206             case self::KEEP_SUFFIX:
00207             {
00208                 $destinationMimeData['basename'] = $originalMimeData['basename'];
00209                 $destinationMimeData['filename'] = $originalMimeData['basename'] . $extraText . '.' . $originalMimeData['suffix'];
00210                 $destinationMimeData['dirpath'] = $originalMimeData['dirpath'];
00211                 if ( $originalMimeData['dirpath'] )
00212                     $destinationMimeData['url'] = $originalMimeData['dirpath'] . '/' . $destinationMimeData['filename'];
00213                 else
00214                     $destinationMimeData['url'] = $destinationMimeData['filename'];
00215             } break;
00216             case self::REPLACE_SUFFIX:
00217             {
00218                 $destinationMimeData['basename'] = $originalMimeData['basename'];
00219                 $destinationMimeData['filename'] = $originalMimeData['basename'] . $extraText . '.' . $destinationMimeData['suffixes'][0];
00220                 $destinationMimeData['dirpath'] = $originalMimeData['dirpath'];
00221                 if ( $originalMimeData['dirpath'] )
00222                     $destinationMimeData['url'] = $originalMimeData['dirpath'] . '/' . $destinationMimeData['filename'];
00223                 else
00224                     $destinationMimeData['url'] = $destinationMimeData['filename'];
00225             } break;
00226             case self::PREPEND_TAG_REPLACE_SUFFIX:
00227             {
00228                 $tagName = $this->tagForMIMEType( $destinationMimeData );
00229                 $destinationMimeData['basename'] = $originalMimeData['basename'];
00230                 $destinationMimeData['filename'] = $originalMimeData['basename'] . $extraText . '.' . $destinationMimeData['suffixes'][0];
00231                 $destinationMimeData['dirpath'] = $originalMimeData['dirpath'];
00232                 if ( $originalMimeData['dirpath'] )
00233                     $destinationMimeData['url'] = $originalMimeData['dirpath'] . '/' . $destinationMimeData['filename'];
00234                 else
00235                     $destinationMimeData['url'] = $destinationMimeData['filename'];
00236                 $destinationMimeData['url'] = $tagName . ':' . $destinationMimeData['url'];
00237             } break;
00238         }
00239     }
00240 
00241     /*!
00242      \virtual
00243      \return an array with MIME type names that the handler supports as input.
00244              MIME type names can also be specified with wildcards, for instance
00245              image/* to say that all image types are supported.
00246      \note The default implementation returns the MIME types specified in the constructor
00247     */
00248     function supportedInputMIMETypes()
00249     {
00250         return $this->SupportedInputMIMETypes;
00251     }
00252 
00253     /*!
00254      \virtual
00255      \return an array with MIME type names that the handler supports as output.
00256              MIME type names can also be specified with wildcards, for instance
00257              image/* to say that all image types are supported.
00258      \note The default implementation returns the MIME types specified in the constructor
00259     */
00260     function supportedOutputMIMETypes()
00261     {
00262         return $this->SupportedOutputMIMETypes;
00263     }
00264 
00265     /*!
00266      \static
00267      Changes the file permissions for image file \a $filepath to the ones
00268      defines in image.ini. It uses the group FileSettings and variable ImagePermissions.
00269      \return \c true on success, \c false otherwise
00270     */
00271     static function changeFilePermissions( $filepath )
00272     {
00273         if ( !file_exists( $filepath ) )
00274             return false;
00275         $ini = eZINI::instance( 'image.ini' );
00276         $perm = $ini->variable( "FileSettings", "ImagePermissions" );
00277         $success = false;
00278         $oldmask = umask( 0 );
00279         if ( !chmod( $filepath, octdec( $perm ) ) )
00280             eZDebug::writeError( "Chmod $perm $filepath failed",
00281                                  'eZImageHandler::changeFilePermissions' );
00282         else
00283             $success = true;
00284         umask( $oldmask );
00285         return $success;
00286     }
00287 
00288     /*!
00289      \static
00290      Creats a regexp string out of the wildcard \a $wilcard and returns it.
00291     */
00292     static function wildcardToRegexp( $wildcard, $separatorCharacter = false )
00293     {
00294         if ( !$separatorCharacter )
00295             $separatorCharacter = '#';
00296         $wildcardArray = preg_split( "#[*]#", $wildcard, -1, PREG_SPLIT_DELIM_CAPTURE );
00297         $wildcardList = array();
00298         $i = 0;
00299         foreach ( $wildcardArray as $wildcardElement )
00300         {
00301             if ( ( $i % 2 ) == 1 )
00302                 $wildcardList[] = '(.+)';
00303             else
00304                 $wildcardList[] = preg_quote( $wildcardElement, $separatorCharacter );
00305             ++$i;
00306         }
00307         $wildcardString = implode( '', $wildcardList );
00308         return $wildcardString;
00309     }
00310 
00311     /*!
00312      \return \c true if the MIME-Type defined in \a $mimeData is supported as output by this handler.
00313     */
00314     function isOutputMIMETypeSupported( $mimeData )
00315     {
00316         $mimeTypes = $this->supportedOutputMIMETypes();
00317         $mimeName = $mimeData;
00318         if ( is_array( $mimeData ) )
00319             $mimeName = $mimeData['name'];
00320         foreach ( $mimeTypes as $mimeType )
00321         {
00322             if ( strpos( $mimeType, '*' ) !== false )
00323             {
00324                 $matchString = eZImageHandler::wildcardToRegexp( $mimeType );
00325                 if ( preg_match( "#^" . $matchString . "$#", $mimeName ) )
00326                 {
00327                     return true;
00328                 }
00329             }
00330             else if ( $mimeType == $mimeName )
00331             {
00332                 return true;
00333             }
00334         }
00335         return false;
00336     }
00337 
00338     /*!
00339      \return \c true if the MIME-Type defined in \a $mimeData is supported as input by this handler.
00340     */
00341     function isInputMIMETypeSupported( $mimeData )
00342     {
00343         $mimeTypes = $this->supportedInputMIMETypes();
00344         $mimeName = $mimeData;
00345         if ( is_array( $mimeData ) )
00346             $mimeName = $mimeData['name'];
00347         foreach ( $mimeTypes as $mimeType )
00348         {
00349             if ( strpos( $mimeType, '*' ) !== false )
00350             {
00351                 $matchString = eZImageHandler::wildcardToRegexp( $mimeType );
00352                 if ( preg_match( "#^" . $matchString . "$#", $mimeName ) )
00353                 {
00354                     return true;
00355                 }
00356             }
00357             else if ( $mimeType == $mimeName )
00358             {
00359                 return true;
00360             }
00361         }
00362         return false;
00363     }
00364 
00365     /*!
00366      \virtual
00367      Figures out the output MIME type for the \a $currentMimeData. It goes trough
00368      all conversion rules for this handler and returns a MIME structure for the
00369      possible output. The returned structure also contains the correct url for the output.
00370      \param $wantedMimeData an optional MIME structure for the wanted output type,
00371                             if a direct conversion rule exists from \a $currentMimeData to \a $wantedMimeData
00372                             then this is used.
00373      \param $aliasName An optional name for the current alias being used, if supplied
00374                        the output MIME structure will have the alias name in the filename.
00375     */
00376     function outputMIMEType( &$manager, $currentMimeData, $wantedMimeData, $supportedFormatsOriginal, $aliasName = false )
00377     {
00378         if ( is_array( $this->conversionRules() ) )
00379         {
00380             $conversionRules = array_merge( $manager->conversionRules(), $this->conversionRules() );
00381         }
00382         else
00383         {
00384             $conversionRules = $manager->conversionRules();
00385         }
00386         $mimeData = false;
00387         $mimeType = false;
00388         if ( !$this->isInputMIMETypeSupported( $currentMimeData ) )
00389             return false;
00390 
00391         if ( $wantedMimeData )
00392         {
00393             $conversionRules = array_merge( array( array( 'from' => $currentMimeData['name'],
00394                                                           'to' => $wantedMimeData['name'] ) ),
00395                                             $conversionRules );
00396         }
00397 
00398         $supportedFormats = array();
00399         foreach ( $supportedFormatsOriginal as $supportedFormat )
00400         {
00401             if ( $this->isOutputMIMETypeSupported( $supportedFormat ) )
00402             {
00403                 $supportedFormats[] = $supportedFormat;
00404                 $conversionRules[] = array( 'from' => $supportedFormat,
00405                                             'to' => $supportedFormat );
00406             }
00407         }
00408 
00409         if ( $wantedMimeData and
00410              in_array( $wantedMimeData['name'], $supportedFormats ) )
00411         {
00412             $mimeType = $wantedMimeData['name'];
00413         }
00414         else if ( is_array( $conversionRules ) )
00415         {
00416             foreach ( $conversionRules as $rule )
00417             {
00418                 if ( !$this->isOutputMIMETypeSupported( $rule['to'] ) or
00419                      !in_array( $rule['to'], $supportedFormats ) )
00420                     continue;
00421 
00422                 $matchRule = false;
00423                 if ( strpos( $rule['from'], '*' ) !== false )
00424                 {
00425                     $matchString = eZImageHandler::wildcardToRegexp( $rule['from'] );
00426                     if ( preg_match( "#^" . $matchString . "$#", $currentMimeData['name'] ) )
00427                     {
00428                         $matchRule = $rule;
00429                     }
00430                 }
00431                 else if ( $rule['from'] == $currentMimeData['name'] )
00432                 {
00433                     $matchRule = $rule;
00434                 }
00435                 if ( $matchRule )
00436                 {
00437                     if ( $mimeType )
00438                     {
00439                         if ( $wantedMimeData and
00440                              $matchRule['to'] == $wantedMimeData['name'] )
00441                             $mimeType = $matchRule['to'];
00442                     }
00443                     else
00444                         $mimeType = $matchRule['to'];
00445                 }
00446             }
00447         }
00448         if ( $mimeType )
00449         {
00450             $mimeData = eZMimeType::findByName( $mimeType );
00451             eZImageHandler::rewriteURL( $currentMimeData, $mimeData, $this->outputRewriteType(), $aliasName );
00452         }
00453         return $mimeData;
00454     }
00455 
00456     /*!
00457      \return the type of filename rewrite this handler uses for output.
00458     */
00459     function outputRewriteType()
00460     {
00461         return $this->OutputRewriteType;
00462     }
00463 
00464     /*!
00465      \return \c true if the filter \a $filter is supported by this handler.
00466     */
00467     function isFilterSupported( $filter )
00468     {
00469         return isset( $this->FilterMap[$filter['name']] );
00470     }
00471 
00472     /*!
00473      \pure
00474      Converts the source file \a $sourceMimeData to the destination file \a $destinationMimeData.
00475      If \a $filters is supplied then the filters will be applied to the conversion.
00476     */
00477     function convert( $manager, $sourceMimeData, &$destinationMimeData, $filters = false )
00478     {
00479     }
00480 
00481 }
00482 
00483 ?>