array( * 'file' => , * 'mime' => , * '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 refernce through manager afterwards. When overwriting * the constructor. * * @param string $name * Displayable name for handler. */ public function __construct( $name ) { parent::__construct( $name ); $this->filters = null; } /** * Creates the filter object for the handler and returns it. * This must be reimplemented in the subclasses to return the correct * object. * * @var ezcImageFilters * @return void */ abstract protected function createFilter(); /** * 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 * * @throws ezcImageHandlerException * If the filters object for the current filter does not exist. * {@link ezcImageHandlerException::IMPLEMENTATION_ERROR}. */ public function hasFilter( $name ) { if ( $this->filters === null ) { $this->filters = $this->createFilter();; } return method_exists( $this->filters, $name ); } /** * Returns a list of filters this handler provides. * The list returned is in format: * * * array( * 0 => , * 1 => , * ... * ) * * * @return array(string) * * @throws ezcImageHandlerException * If the filters object for the current filter does not exist. * {@link ezcImageHandlerException::IMPLEMENTATION_ERROR}. */ public function getFilterNames() { if ( $this->filters === null ) { $this->filters = $this->createFilter();; } return $this->filters->getFilters(); } /** * 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 ezcImageHandlerException * If the filters object for the current filter does not exist. * {@link ezcImageHandlerException::IMPLEMENTATION_ERROR}. * @throws ezcImageHandlerException * If no valid resource for the active reference could be found * {@link ezcImageHandlerException::INVALID_REFERENCE}. * @throws ezcImageHandlerException * No loaded file could be found or an error destroyed a loaded reference * {@link ezcImageHandlerException::NO_ACTIVE_REFERENCE}. * @throws ezcImageFiltersException * If the desired filter does not exist. * {@link ezcImageFiltersException::NOT_AVAILABLE}. * @throws ezcImageFiltersException * If a parameter for the filter is missing. * {@link ezcImageFiltersException::MISSING_PARAMETER}. * @throws ezcImageFiltersException * If the operation performed by the the filter failed * {@link ezcImageFiltersException::FAILED}. * @throws ezcImageFiltersException * If a parameter was not within the expected range between 0 and 1 * {@link ezcImageFiltersException::INVALID_PARAMETER}. */ public function applyFilter( $image, ezcImageFilter $filter ) { if ( !$this->hasFilter( $filter->name ) ) { throw new ezcImageFiltersException( "Filter <{$filter->name}> not available for this handler.", ezcImageFiltersException::NOT_AVAILABLE ); } if ( $this->filters === null ) { $this->filters = $this->createFilter();; } $reflectClass = new ReflectionClass( get_class( $this->filters ) ); $reflectParameters = $reflectClass->getMethod( $filter->name )->getParameters(); $parameters = array(); foreach ( $reflectParameters as $id => $parameter ) { $paramName = $parameter->getName(); if ( !isset( $filter->options[$paramName] ) ) { throw new ezcImageFiltersException( "Missing parameter <{$paramName}> for filter <{$filter->name}>", ezcImageFiltersException::MISSING_PARAMETER ); } $parameters[] = $filter->options[$paramName]; } $this->setActiveReference( $image ); call_user_func_array( array( $this->filters, $filter->name ), $parameters ); } /** * 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 ezcImageHandlerException * If the given MIME type is not supported by the filter * {@link ezcImageHandlerException::UNKNOWN_TYPE}. * @throws ezcImageHandlerException * If no valid resource for the active reference could be found * {@link ezcImageHandlerException::INVALID_REFERENCE}. */ public function convert( $image, $mime ) { $oldMime = $this->getReferenceData( $image, 'mime' ); if ( !$this->allowsOutput( $mime ) ) { throw new ezcImageHandlerException( "MIME type <{$mime}> not supported.", ezcImageHandlerException::UNKNOWN_TYPE ); } $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 ezcImageHandlerException * If no valid resource for the active reference could be found * {@link ezcImageHandlerException::INVALID_REFERENCE}. */ public function getActiveResource() { $ref = $this->getActiveReference(); if ( ( $resource = $this->getReferenceData( $ref, 'resource' ) ) === false ) { throw new ezcImageHandlerException( "No resource <{$ref}> found in active reference.", ezcImageHandlerException::INVALID_REFERENCE ); } 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 */ public 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 ezcImageHandlerException * No loaded file could be found or an error destroyed a loaded reference * {@link ezcImageHandlerException::NO_ACTIVE_REFERENCE}. * * @return string The active reference. */ public function getActiveReference() { if ( !isset( $this->activeReference ) ) { throw new ezcImageHandlerException( 'No reference is defined as active. Either no file is loeaded, yet or an internal error destroyed the reference.', ezcImageHandlerException::NO_ACTIVE_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 ezcImageHandlerException * If the given reference is invalid * {@link ezcImageHandlerException::INVALID_REFERENCE}. */ protected function setActiveReference( $image ) { if ( !isset( $this->references[$image] ) ) { throw new ezcImageHandlerException( 'Could not mark invalid reference as active.', ezcImageHandlerException::INVALID_REFERENCE ); } $this->activeReference = $image; } /** * Returns data about a reference. * This gives you access to the data stored about a loaded image. You can * either retreive a certain detail (defined in the references array), with * specifying it through the second parameter (the method then simply * returns that detail) or retreive all available details with leaving that * parameter out. * * By default the following details are available: * * 'file' => The file name of the image loaded. * 'mime' => The mime type of the image loaded. * 'resource' => A resource referencing it. * * * 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 ezcImageHandlerException * If the given reference is invalid * {@link ezcImageHandlerException::INVALID_REFERENCE}. * * @see ezcImageMethodcallHandler::setReferenceData() */ protected function getReferenceData( $reference, $detail = null ) { if ( !isset( $this->references[$reference] ) ) { throw new ezcImageHandlerException( "Inavlid image reference given: <{$reference}>.", ezcImageHandlerException::INVALID_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 retreived throughh * 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 ezcImageHandlerException * If the given reference is invalid * {@link ezcImageHandlerException::INVALID_REFERENCE}. * @throws ezcImageHandlerException * If the given detail is invalid. * {@link ezcImageHandlerException::INVALID_DETAILS}. */ protected function setReferenceData( $reference, $value, $detail = null ) { if ( !isset( $this->references[$reference] ) ) { throw new ezcImageHandlerException( "Invalid image reference given: <{$reference}>.", ezcImageHandlerException::INVALID_REFERENCE ); } if ( isset( $detail ) ) { $this->references[$reference][$detail] = $value; } else { if ( !is_array( $value ) ) { throw new ezcImageHandlerException( "Invalid details given for image reference: <{$reference}>. Details must be stored in an array.", ezcImageHandlerException::INVALID_DETAILS ); } if ( !isset( $value['file'] ) || !isset( $value['mime'] ) || !isset( $value['resource'] ) ) { throw new ezcImageHandlerException( "Invalid details given for image reference: <{$reference}>. Details must contain , and .", ezcImageHandlerException::INVALID_DETAILS ); } $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 ezcImageHandlerException * If the desired file does not exist * {@link ezcImageHandlerException::FILE_NOT_EXISTS}. * @throws ezcImageHandlerException * If the desired file has a not recognized type * {@link ezcImageHandlerException::UNKNOWN_TYPE}. * @throws ezcImageHandlerException * If the given detail is invalid. * {@link ezcImageHandlerException::INVALID_DETAILS}. */ protected function loadCommon( $file, $mime = null ) { $file = realpath( $file ); $ref = md5( $file ); if ( !is_file( $file ) || !is_readable( $file ) ) { throw new ezcImageHandlerException( "Could not read file <{$file}>.", ezcImageHandlerException::FILE_NOT_EXISTS ); } if ( !isset( $mime ) ) { $mime = ''; try { $analyzer = new ezcImageAnalyzer( $file ); $mime = $analyzer->mime; } catch ( ezcImageAnalyzerException $e ) { throw new ezcImageHandlerException( "Unable to get MIME type for file <{$file}>.", ezcImageHandlerException::UNKNOWN_TYPE ); } } $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 ezcImageHandlerException * If the desired file exists and is not writeable * {@link ezcImageHandlerException::FILE_NOT_PROCESSABLE}. * @throws ezcImageHandlerException * If the desired MIME type is not recognized * {@link ezcImageHandlerException::UNKNOWN_TYPE}. */ 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 ezcImageHandlerException( "File is not writeable <{$file}>", ezcImageHandlerException::FILE_NOT_PROCESSABLE ); } if ( isset( $mime ) ) { $this->setReferenceData( $reference, $mime, 'mime' ); } $mime = $this->getReferenceData( $reference, 'mime' ); if ( $this->allowsOutput( $mime ) === false ) { throw new ezcImageHandlerException( "MIME type <{$mime}> can not be processed by this handler.", ezcImageHandlerException::UNKNOWN_TYPE ); } } /** * 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] ); } /** * Returns the current filters object. * * @return ezcImageFilters */ protected function getFilters() { if ( $this->filters === null ) { $this->filters = $this->createFilter();; } return $this->filters; } } ?>