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; /** * Load an image file. * Loads an image file and returns a reference to it. * * For developers: The use of ezcImageHandler::loadCommon() is highly * recommended for the implementation of this method! * * @param string $file File to load. * @param string $mime The MIME type of the file. * @return string Reference to the file in this handler. */ public abstract function load( $file, $mime = null ); /** * Save an image file. * Saves a given open file. Can optionally save to a new file name. * The image reference is not freed automatically, so you need to call * the close() method explicitly to free the referenced data. * * @see ezcImageHandler::load() * @see ezcImageHandler::close() * * @param string $image File reference created through. * @param string $newFile Filename to save the image to. * @param string $mime New MIME type, if differs from initial one. */ public abstract function save( $image, $newFile = null, $mime = null ); /** * Close the file referenced by $image. * Frees the image reference. You should call close() before. * * @see ezcImageHandler::load() * @see ezcImageHandler::save() * @param string $image The image reference. */ abstract public function close( $reference ); /** * 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. * * @internal Make sure you call parent::__construct() within * your constructor and TO SET THE $name PROPERTY BEFORE THAT PROPERLY. * * @param array(string) $settings Settings * @param array(string) $options Options */ public function __construct() { if ( !isset( $this->name ) ) { throw new ezcImageHandlerException( 'Missing attribute name. Cannot proceed without name attribute. Must be set in deriving constructor.', ezcImageHandlerException::IMPLEMENTATION_ERROR ); } $filtersClass = 'ezcImageFilters' . ucfirst( strtolower( $this->name ) ); if ( !class_exists( $filtersClass ) ) { throw new ezcImageHandlerException( "Filter class not found for filter <{$this->name}>. Must be named <{$filtersClass}>", ezcImageHandlerException::IMPLEMENTATION_ERROR ); } $this->filters = new $filtersClass( $this ); } /** * 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->filters, $name ); } /** * Returns a list of filters this handler provides. * The list returned is in format: * * * array( * 0 => , * 1 => , * ... * ) * * * @return array(string) */ public function listFilters() { $methods = get_class_methods( $this->filters ); $filters = array(); foreach ( $methods as $method ) { if ( substr( $method, 0, 1 ) !== '_' ) { $filters[] = $method; } } return $filters; } /** * 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 ezcImageHandler::load() * @see ezcImageHandler::save() * * @param string $image Image reference to apply the filter on. * @param string $filter Filter name * @param array(string) $options Options for the filter. */ public function applyFilter( $image, $filter, $options ) { if ( !$this->hasFilter( $filter ) ) { throw new ezcImageFiltersException( "Filter <{$filter}> not available for this handler.", ezcImageFiltersException::NOT_AVAILABLE ); } $reflectClass = new ReflectionClass( get_class( $this->filters ) ); $reflectParameters = $reflectClass->getMethod( $filter )->getParameters(); $parameters = array(); foreach ( $reflectParameters as $id => $parameter ) { $paramName = $parameter->getName(); if ( !isset( $options[$paramName] ) ) { throw new ezcImageFiltersException( "Missing parameter <{$paramName}> for filter <{$filter}>", ezcImageFiltersException::MISSING_PARAMETER ); } $parameters[] = $options[$paramName]; } $this->setActiveReference( $image ); call_user_func_array( array( $this->filters, $filter ), $parameters ); } /** * Converts an image to another MIME type. * * Use {@link ezcImageHandler::allowsOutput()} to determine, * if the output MIME type is supported by this handler! * * @see ezcImageHandler::load() * @see ezcImageHandler::save() * * @param string $image Image reference to convert. * @param string $mime MIME type to convert to. */ 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' ); } /** * Returns the name of this handler. * * @return string */ public function getName() { return $this->name; } /** * 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. */ 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 */ 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 ezcImageHandler::setActiveReference() * @see ezcImageHandler::load() * @see ezcImageHandler::$references * * @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 loeade, 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. */ 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 Shell 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. * * @see ezcImageHandler::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 * ezcImageHandler::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. */ 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 * ezcImageHandler::$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. */ 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->getMime(); } 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 * ezcImageHandler. 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 */ 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 ezcImageHandler to finally remove the reference. * * @param string $reference The reference to free. */ protected function closeCommon( $reference ) { $data = $this->getReferenceData( $reference ); unset( $this->references[$reference] ); } } ?>