| <?php |
| /** |
| * This file contains the ezcImageMethodcallHandler interface. |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| * @package ImageConversion |
| * @version //autogentag// |
| * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0 |
| * @filesource |
| * @access private |
| */ |
| |
| /** |
| * Special image handler which handles filters using method calls and keeps |
| * track of resources. |
| * This is a special abstract class which are extended by the ImageMagick and |
| * GD handlers and contains code which is common to both of them. |
| * It performs filter operations by keeping a filter object available and |
| * accesses the filter methods directly, this means the sub-classes only have |
| * to create the correct filter object. |
| * |
| * Implements all abstract methods of ezcImageHandler except load(), save() |
| * and close(). Instead it provides the {@link loadCommon()}, |
| * {@link saveCommon()} and {@link closeCommon()} methods to simplify the code |
| * for sub-classes. |
| * |
| * @see ezcImageConverter |
| * @see ezcImageGdHandler |
| * @see ezcImageImagemagickHandler |
| * @see ezcImageFilters |
| * |
| * @package ImageConversion |
| * @version //autogentag// |
| * @access private |
| */ |
| abstract class ezcImageMethodcallHandler extends ezcImageHandler |
| { |
| /** |
| * Array of MIME types usable for input |
| * |
| * @var array |
| */ |
| protected $inputTypes; |
| |
| /** |
| * Array of MIME types usable for output |
| * |
| * @var array |
| */ |
| protected $outputTypes; |
| |
| /** |
| * Array of filter names cached from getFilterNames(). |
| * |
| * @var array |
| */ |
| protected $filterNameCache; |
| |
| /** |
| * Image references created through load(). |
| * Format: |
| * array( |
| * 'id' => array( |
| * 'file' => <file name>, |
| * 'mime' => <MIME type>, |
| * 'resource' => <image resource>, |
| * ) |
| * ) |
| * |
| * @var array |
| */ |
| private $references = array(); |
| |
| /** |
| * Currently active image reference. |
| * This is used to determine by the filter, which image should be |
| * processed. |
| * |
| * @var string |
| */ |
| private $activeReference; |
| |
| /** |
| * Create a new image handler. |
| * Creates an image handler. This should never be done directly, |
| * but only through the manager for configuration reasons. One can |
| * get a direct reference through manager afterwards. When overwriting |
| * the constructor. |
| * |
| * The contents of the $settings parameter may change from handler to |
| * handler. For detailed information take a look at the specific handler |
| * classes. |
| * |
| * @param ezcImageHandlerSettings $settings Settings for the handler. |
| */ |
| public function __construct( ezcImageHandlerSettings $settings ) |
| { |
| parent::__construct( $settings ); |
| } |
| |
| /** |
| * Destroyes the handler and closes all open references correctly. |
| * |
| * @return void |
| */ |
| public function __destruct() |
| { |
| foreach ( $this->references as $id => $data ) |
| { |
| $this->close( $id ); |
| } |
| } |
| |
| /** |
| * Check wether a specific MIME type is allowed as input for this handler. |
| * |
| * @param string $mime MIME type to check if it's allowed. |
| * @return bool |
| */ |
| public function allowsInput( $mime ) |
| { |
| return ( in_array( strtolower( $mime ), $this->inputTypes ) ); |
| } |
| |
| /** |
| * Checks wether a specific MIME type is allowed as output for this handler. |
| * |
| * @param string $mime MIME type to check if it's allowed. |
| * @return bool |
| */ |
| public function allowsOutput( $mime ) |
| { |
| return ( in_array( strtolower( $mime ), $this->outputTypes ) ); |
| } |
| |
| /** |
| * Checks if a given filter is available in this handler. |
| * |
| * @param string $name Name of the filter to check for. |
| * @return bool |
| * |
| */ |
| public function hasFilter( $name ) |
| { |
| return method_exists( $this, $name ); |
| } |
| |
| /** |
| * Returns a list of filters this handler provides. |
| * The list returned is in format: |
| * |
| * <code> |
| * array( |
| * 0 => <string filtername>, |
| * 1 => <string filtername>, |
| * ... |
| * ) |
| * </code> |
| * |
| * @return array(string) |
| */ |
| public function getFilterNames() |
| { |
| if ( !isset( $this->filterNameCache ) || !is_array( $this->filterNameCache || sizeof( $this->filterNameCache ) === 0 ) ) |
| { |
| $this->filterNameCache = array(); |
| $excludeMethods = array( |
| '__construct', |
| '__destruct', |
| '__get', |
| '__set', |
| '__call', |
| 'allowsInput', |
| 'allowsOutput', |
| 'hasFilter', |
| 'getFilterNames', |
| 'applyFilter', |
| 'convert', |
| 'load', |
| 'save', |
| 'close', |
| 'defaultSettings', |
| ); |
| |
| $refClass = new ReflectionClass( get_class( $this ) ); |
| foreach ( $refClass->getMethods() as $method ) |
| { |
| if ( $method->isPublic() && !in_array( $method->getName(), $excludeMethods ) ) |
| { |
| $this->filterNameCache[] = $method->getName(); |
| } |
| } |
| } |
| return $this->filterNameCache; |
| } |
| |
| /** |
| * Applies a filter to a given image. |
| * |
| * @internal This method is the main one, which will dispatch the |
| * filter action to the specific function of the backend. |
| * |
| * @see ezcImageMethodcallHandler::load() |
| * @see ezcImageMethodcallHandler::save() |
| * |
| * @param string $image Image reference to apply the filter on. |
| * @param ezcImageFilter $filter Contains which filter operation to apply. |
| * @return void |
| * |
| * @throws ezcImageInvalidReferenceException |
| * If no valid resource for the active reference could be found. |
| * @throws ezcImageInvalidReferenceException |
| * No loaded file could be found or an error destroyed a loaded reference. |
| * @throws ezcImageFilterNotAvailableException |
| * If the desired filter does not exist. |
| * @throws ezcImageFiltersMissingFilterParameterException |
| * If a parameter for the filter is missing. |
| * @throws ezcImageFilterFailedException |
| * If the operation performed by the the filter failed. |
| * @throws ezcBaseValueException |
| * If a parameter was not within the expected range. |
| */ |
| public function applyFilter( $image, ezcImageFilter $filter ) |
| { |
| if ( !$this->hasFilter( $filter->name ) ) |
| { |
| throw new ezcImageFilterNotAvailableException( $filter->name ); |
| } |
| $reflectClass = new ReflectionClass( get_class( $this ) ); |
| $reflectParameters = $reflectClass->getMethod( $filter->name )->getParameters(); |
| $parameters = array(); |
| foreach ( $reflectParameters as $id => $parameter ) |
| { |
| $paramName = $parameter->getName(); |
| if ( isset( $filter->options[$paramName] ) ) |
| { |
| $parameters[] = $filter->options[$paramName]; |
| } |
| else if ( $parameter->isOptional() === false ) |
| { |
| throw new ezcImageMissingFilterParameterException( $filter->name, $paramName ); |
| } |
| } |
| // Backup last active reference |
| $oldRef = $this->getActiveReference(); |
| // Perform actual filtering on given image |
| $this->setActiveReference( $image ); |
| call_user_func_array( array( $this, $filter->name ), $parameters ); |
| // Restore last active reference |
| $this->setActiveReference( $oldRef ); |
| } |
| |
| /** |
| * Converts an image to another MIME type. |
| * |
| * Use {@link ezcImageMethodcallHandler::allowsOutput()} to determine, |
| * if the output MIME type is supported by this handler! |
| * |
| * @see ezcImageMethodcallHandler::load() |
| * @see ezcImageMethodcallHandler::save() |
| * |
| * @param string $image Image reference to convert. |
| * @param string $mime MIME type to convert to. |
| * @return void |
| * |
| * @throws ezcImageMimeTypeUnsupportedException |
| * If the given MIME type is not supported by the filter. |
| * @throws ezcImageInvalidReferenceException |
| * If no valid resource for the active reference could be found. |
| */ |
| public function convert( $image, $mime ) |
| { |
| $oldMime = $this->getReferenceData( $image, 'mime' ); |
| if ( !$this->allowsOutput( $mime ) ) |
| { |
| throw new ezcImageMimeTypeUnsupportedException( $mime, 'output' ); |
| } |
| $this->setReferenceData( $image, $mime, 'mime' ); |
| } |
| |
| /** |
| * Receive the resource of the active image reference. |
| * This method is utilized by the ezcImageFilters* class to receive the |
| * currently active resource for manipulations. |
| * |
| * @return resource The currently active resource. |
| * |
| * @throws ezcImageInvalidReferenceException |
| * If no valid resource for the active reference could be found. |
| */ |
| protected function getActiveResource() |
| { |
| $ref = $this->getActiveReference(); |
| if ( ( $resource = $this->getReferenceData( $ref, 'resource' ) ) === false ) |
| { |
| throw new ezcImageInvalidReferenceException( "No resource found for the active reference '{$ref}'." ); |
| } |
| return $resource; |
| } |
| |
| /** |
| * Replace the resource of an image reference with a new one. |
| * After filtering the current image resource might have to be replaced |
| * with a new version. This can be done using this method. |
| * |
| * @param resource(GD) $resource |
| * @return void |
| */ |
| protected function setActiveResource( $resource ) |
| { |
| $this->setReferenceData( |
| $this->getActiveReference(), |
| $resource, |
| 'resource' |
| ); |
| } |
| |
| /** |
| * Returns the currently active reference. |
| * Returns the reference which is currently marked as active. This happens |
| * either by loading a new file or by using the setActiveReference() |
| * method. |
| * |
| * @see ezcImageMethodcallHandler::setActiveReference() |
| * @see ezcImageMethodcallHandler::load() |
| * @see ezcImageMethodcallHandler::$references |
| * |
| * @throws ezcImageInvalidReferenceException |
| * No loaded file could be found or an error destroyed a loaded reference. |
| * |
| * @return string The active reference. |
| */ |
| protected function getActiveReference() |
| { |
| if ( !isset( $this->activeReference ) ) |
| { |
| throw new ezcImageInvalidReferenceException( 'No reference is defined as active. Either no file is loeaded, yet or an internal error destroyed the reference.' ); |
| } |
| return $this->activeReference; |
| } |
| |
| /** |
| * Mark the submitted image reference as active. |
| * The image reference submitted is marked as active. All following |
| * filter operations are performed on this reference. |
| * |
| * @param string $image The image reference. |
| * @return void |
| * |
| * @throws ezcImageInvalidReferenceException |
| * If the given reference is invalid. |
| */ |
| protected function setActiveReference( $image ) |
| { |
| if ( !isset( $this->references[$image] ) ) |
| { |
| throw new ezcImageInvalidReferenceException( 'Could not mark invalid reference as active.' ); |
| } |
| $this->activeReference = $image; |
| } |
| |
| /** |
| * Returns data about a reference. |
| * This gives you access to the data stored about a loaded image. You can |
| * either retrieve a certain detail (defined in the references array), with |
| * specifying it through the second parameter (the method then simply |
| * returns that detail) or retrieve all available details with leaving that |
| * parameter out. |
| * |
| * By default the following details are available: |
| * <code> |
| * 'file' => The file name of the image loaded. |
| * 'mime' => The mime type of the image loaded. |
| * 'resource' => A resource referencing it. |
| * </code> |
| * |
| * Of what type the resource is, may differ from handler to handler (e.g. a |
| * GD resource for the GD handler or a file path for the ImageMagick handler). |
| * You can simply store your own details be setting them and retreive them |
| * through this method. |
| * |
| * @param string $reference Reference string assigned. |
| * @param mixed $detail To receive a single detail, set to detail name. |
| * @return array Array of details if you specify $detail, else depending on |
| * the detail. If detail is not available, returns false. |
| * |
| * @throws ezcImageInvalidReferenceException |
| * If the given reference is invalid. |
| * |
| * @see ezcImageMethodcallHandler::setReferenceData() |
| */ |
| protected function getReferenceData( $reference, $detail = null ) |
| { |
| if ( !isset( $this->references[$reference] ) ) |
| { |
| throw new ezcImageInvalidReferenceException( "Inavlid image reference given: '{$reference}'." ); |
| } |
| if ( isset( $detail ) ) |
| { |
| return isset( $this->references[$reference][$detail] ) ? $this->references[$reference][$detail] : false; |
| } |
| return $this->references[$reference]; |
| } |
| |
| /** |
| * Set data for an image reference. |
| * This method allows you to set all data that can be retrieved through |
| * ezcImageMethodcallHandler::getReferenceData(). You can either set a single detail |
| * by providing the optional $detail parameter or submit an array containing |
| * all details at once as the value to set all details. |
| * |
| * @param string $reference Reference string of the image data. |
| * @param mixed $value The value to set. |
| * @param string $detail The name of the detail to set. |
| * @return void |
| * |
| * @throws ezcImageInvalidReferenceException |
| * If the given reference is invalid. |
| * @throws ezcBaseValueException |
| * If the given detail is invalid. |
| */ |
| protected function setReferenceData( $reference, $value, $detail = null ) |
| { |
| if ( !isset( $this->references[$reference] ) ) |
| { |
| throw new ezcImage( "Invalid image reference given: '{$reference}'." ); |
| } |
| if ( isset( $detail ) ) |
| { |
| $this->references[$reference][$detail] = $value; |
| } |
| else |
| { |
| if ( !is_array( $value ) ) |
| { |
| throw new ezcBaseValueException( 'value', $value, 'array' ); |
| } |
| if ( !isset( $value['file'] ) ) |
| { |
| throw new ezcBaseValueException( 'file', null, 'string' ); |
| } |
| if ( !isset( $value['mime'] ) ) |
| { |
| throw new ezcBaseValueException( 'mime', null, 'string' ); |
| } |
| if ( !isset( $value['resource'] ) ) |
| { |
| throw new ezcBaseValueException( 'resource', null, 'string' ); |
| } |
| $this->references[$reference] = $value; |
| } |
| } |
| |
| /** |
| * Create a reference entry for this file. |
| * Performs common operations on a specific file, like checking if the file |
| * exists, if it is loadable, if it's already loaded. Beside of that, it |
| * creates the reference internally, so you don't need to handle this |
| * stuff manually with the internal data structure of |
| * ezcImageMethodcallHandler::$references. It also cares for determining the MIME- |
| * type of the image and sets the newly created reference to be active. |
| * |
| * @param string $file The file to load. |
| * @param string $mime The MIME type of the file. |
| * @return string reference The reference string for this file. |
| * |
| * @throws ezcBaseFileNotFoundException |
| * If the desired file does not exist. |
| * @throws ezcBaseFilePermissionException |
| * If the desired file is not readable. |
| * @throws ezcBaseValueException |
| * If the given detail is invalid. |
| * @throws ezcImageMimeTypeUnsupportedException |
| * If the desired file has a not recognized type. |
| */ |
| protected function loadCommon( $file, $mime = null ) |
| { |
| if ( !is_file( $file ) ) |
| { |
| throw new ezcBaseFileNotFoundException( $file ); |
| } |
| if ( !is_readable( $file ) ) |
| { |
| throw new ezcBaseFilePermissionException( $file, ezcBaseFileException::READ ); |
| } |
| |
| $file = realpath( $file ); |
| $ref = md5( $file ); |
| |
| if ( !isset( $mime ) ) |
| { |
| $mime = ''; |
| try |
| { |
| $analyzer = new ezcImageAnalyzer( $file ); |
| $mime = $analyzer->mime; |
| } |
| catch ( ezcImageAnalyzerException $e ) |
| { |
| throw new ezcImageMimeTypeUnsupportedException( 'unknown/unknown', 'input' ); |
| } |
| } |
| |
| $this->references[$ref] = array(); |
| $this->setReferenceData( |
| $ref, |
| array( |
| 'file' => $file, |
| 'mime' => $mime, |
| 'resource' => false, |
| ) |
| ); |
| $this->setActiveReference( $ref ); |
| |
| return $ref; |
| } |
| |
| /** |
| * Performs common operations before saving a file. |
| * This method should/can be used while implementing the save method of an |
| * ezcImageMethodcallHandler. It performs several tasks, like setting the new file name, |
| * if it has been submitted, and the new MIME type. Beside that, it checks |
| * if one can write to the new file and if the handler is able to process |
| * the new MIME type. |
| * |
| * @param string $reference The image reference. |
| * @param string $newFile The new filename. |
| * @param string $mime The new MIME type. |
| * @return void |
| * |
| * @throws ezcBaseFilePermissionException |
| * If the desired file is not writeable. |
| * @throws ezcImageMimeTypeUnsupportedException |
| * If the desired MIME type is not recognized. |
| */ |
| protected function saveCommon( $reference, $newFile = null, $mime = null ) |
| { |
| if ( isset( $newFile ) ) |
| { |
| $this->setReferenceData( $reference, $newFile, 'file' ); |
| } |
| $file = $this->getReferenceData( $reference, 'file' ); |
| if ( file_exists( $file ) && !is_writeable( $file ) ) |
| { |
| throw new ezcBaseFilePermissionException( $file, ezcBaseFileException::WRITE ); |
| } |
| |
| if ( isset( $mime ) ) |
| { |
| $this->setReferenceData( $reference, $mime, 'mime' ); |
| } |
| $mime = $this->getReferenceData( $reference, 'mime' ); |
| if ( $this->allowsOutput( $mime ) === false ) |
| { |
| throw new ezcImageMimeTypeUnsupportedException( $mime, 'output' ); |
| } |
| } |
| |
| /** |
| * Unsets the reference data for the given reference. |
| * This method _must_ be called in the implementation of the close() method |
| * in every ezcImageMethodcallHandler to finally remove the reference. |
| * |
| * @param string $reference The reference to free. |
| * @return void |
| */ |
| protected function closeCommon( $reference ) |
| { |
| $data = $this->getReferenceData( $reference ); |
| unset( $this->references[$reference] ); |
| } |
| } |
| ?> |