Commits

Christoffer Niska committed 9624544

Added support for saving images in different subdirectories.

Comments (0)

Files changed (6)

  * @author Christoffer Niska <ChristofferNiska@gmail.com>
  * @copyright Copyright &copy; Christoffer Niska 2011-
  * @license http://www.opensource.org/licenses/bsd-license.php New BSD License
- * @version 1.2.0
+ * @version 1.2.1
  */
 class ImageModule extends CWebModule
 {
 	 */
 	public function getVersion()
 	{
-		return '1.2.0';
+		return '1.2.1';
 	}
 }

components/ImgInstaller.php

 		// Replace the placeholders in the template file.
 		$htaccess=strtr($htaccess,array(
 			'{baseUrl}'=>Yii::app()->getRequest()->getBaseUrl().'/',
-			'{sourceUrl}'=>'^versions/([^\<\>:"/\\\|\?\*]+)/[^\<\>:"/\\\|\?\*]+\-([0-9]+)\.(gif|jpg|png)$',
+			'{sourceUrl}'=>'^versions/([^/]+)/.*[^/]+\-([0-9]+)\.(gif|jpg|png)$',
 			'{targetUrl}'=>$targetUrl,
 		));
 

components/ImgManager.php

 	{
 		if(isset($this->versions[$version]))
 		{
-			$image = $this->loadModel($id);
-			$filename=$this->resolveFileName($image);
-			$path=$this->getVersionPath($version);
-			return Yii::app()->request->getBaseUrl($absolute).'/'.$path.$filename;
+			$image=$this->loadModel($id);
+			$path=$this->getVersionPath($version).$image->getPath().$this->resolveFileName($image);
+			return Yii::app()->request->getBaseUrl($absolute).'/'.$path;
 		}
 		else
 			throw new ImgException(Img::t('error','Failed to get image URL! Version is unknown.'));
 
 	/**
 	 * Saves a new image.
+	 * @param CUploadedFile $file the uploaded image.
 	 * @param string $name the image name. Available since 1.2.0
-	 * @param CUploadedFile $file the uploaded image.
+	 * @param string $path the path to save the file to. Available since 1.2.1.
 	 * @return Image the image record.
 	 * @throws ImageException if saving the image record or file fails.
 	 */
-	public function save($name,$file)
+	public function save($file,$name=null,$path=null)
 	{
 		$trx=Yii::app()->db->beginTransaction();
 
 		try
 		{
 			$image=new Image();
-			$image->name=$this->normalizeString($name);
 			$image->extension=strtolower($file->getExtensionName());
 			$image->filename=$file->getName();
 			$image->byteSize=$file->getSize();
 			$image->mimeType=$file->getType();
 			$image->created=new CDbExpression('NOW()');
 
+			if($name!==null)
+				$image->name=$this->normalizeString($name);
+
+			if($path!==null)
+				$image->path=trim($path,'/');
+
 			if($image->save()===false)
 				throw new ImgException(Img::t('error','Failed to save image! Record could not be saved.'));
 
-			$filename=$this->resolveFileName($image);
-			$path=$this->getImagePath(true);
+			$path=$this->resolveImagePath($image);
 
-			if($file->saveAs($path.$filename)===false)
+			if(!file_exists($path))
+				if(!$this->createDirectory($path))
+					throw new ImgException(Img::t('error','Failed to save image! Directory could not be created.'));
+
+			$path.=$this->resolveFileName($image);
+
+			if($file->saveAs($path)===false)
 				throw new ImgException(Img::t('error','Failed to save image! File could not be saved.'));
 
 			$trx->commit();
 	}
 
 	/**
+	 * Creates a new version of a specific image.
+	 * @param integer $id the image id.
+	 * @param string $version the image version.
+	 * @return ThumbBase
+	 */
+	public function createVersion($id,$version)
+	{
+		if(isset($this->versions[$version]))
+		{
+			$image=$this->loadModel($id);
+
+			if($image!=null)
+			{
+				$fileName=$this->resolveFileName($image);
+				$thumb=self::thumbFactory($this->resolveImagePath($image).$fileName);
+				$options=ImgOptions::create($this->versions[$version]);
+				$thumb->applyOptions($options);
+				$path=$this->resolveImageVersionPath($image,$version);
+
+				if(!file_exists($path))
+					if(!$this->createDirectory($path))
+						throw new ImgException(Img::t('error','Failed to create version! Directory could not be created.'));
+
+				$path.=$fileName;
+
+				return $thumb->save($path);
+			}
+			else
+				throw new ImgException(Img::t('error','Failed to create version! Image could not be found.'));
+		}
+		else
+			throw new ImgException(Img::t('error','Failed to create version! Version is unknown.'));
+	}
+
+	/**
 	 * Deletes a specific image.
 	 * @param $id the image id.
 	 * @return boolean whether the image was deleted.
 
 		if($image instanceof Image)
 		{
-			$fileName=$this->resolveFileName($image);
-			$filePath=$this->getImagePath(true).$fileName;
+			$path=$this->resolveImagePath($image).$this->resolveFileName($image);
 
 			if($image->delete()===false)
 				throw new ImgException(Img::t('error', 'Failed to delete image! Record could not be deleted.'));
 
-			if(file_exists($filePath)!==false && unlink($filePath)===false)
+			if(file_exists($path)!==false && unlink($path)===false)
 				throw new ImgException(Img::t('error', 'Failed to delete image! File could not be deleted.'));
 
 			foreach($this->versions as $version=>$config)
-				$this->deleteVersion($image, $version);
+				$this->deleteVersion($image,$version);
 		}
 		else
 			throw new ImgException(Img::t('error', 'Failed to delete image! Record could not be found.'));
 	{
 		if(isset($this->versions[$version]))
 		{
-			$filePath=$this->resolveImageVersionPath($image,$version);
-			if(file_exists($filePath)!==false && unlink($filePath)===false)
+			$path=$this->resolveImageVersionPath($image,$version).$this->resolveFileName($image);
+			
+			if(file_exists($path)!==false && unlink($path)===false)
 				throw new ImgException(Img::t('error', 'Failed to delete the image version! File could not be deleted.'));
 		}
 		else
 		if($image!==null)
 		{
 			$fileName=$this->resolveFileName($image);
-			$thumb=self::thumbFactory($fileName);
+			$thumb=self::thumbFactory($this->resolveImagePath($image).$fileName);
 			return $thumb;
 		}
 		else
 	}
 
 	/**
-	 * Creates a new version of a specific image.
-	 * @param integer $id the image id.
+	 * Returns the original image file name.
+	 * @param Image $image the image model.
+	 * @return string the file name.
+	 */
+	protected function resolveFileName($image)
+	{
+		if(!empty($image->name))
+			return $image->name.'-'.$image->id.'.'.$image->extension; // 1.2.0 ->
+		else
+			return $image->id.'.'.$image->extension; // backwards compatibility
+	}
+
+	/**
+	 * Returns the path to a specific image.
+	 * @param Image $image the image model.
+	 * @return string the path.
+	 */
+	protected function resolveImagePath($image)
+	{
+		return $this->getImagePath(true).$image->getPath();
+	}
+
+	/**
+	 * Returns the path to a specific image version.
+	 * @param Image $image the image model.
 	 * @param string $version the image version.
-	 * @return ThumbBase
+	 * @return string the path.
 	 */
-	public function createVersion($id,$version)
+	protected function resolveImageVersionPath($image,$version)
 	{
-		if(isset($this->versions[$version]))
-		{
-			$image=$this->loadModel($id);
-
-			if($image!=null)
-			{
-				$fileName=$this->resolveFileName($image);
-				$thumb=self::thumbFactory($fileName);
-				$options=ImgOptions::create($this->versions[$version]);
-				$thumb->applyOptions($options);
-				$path=$this->getVersionPath($version,true);
-				return $thumb->save($path.$fileName);
-			}
-			else
-				throw new ImgException(Img::t('error','Failed to create version! Image could not be found.'));
-		}
-		else
-			throw new ImgException(Img::t('error','Failed to create version! Version is unknown.'));
+		return $this->getVersionPath($version,true).$image->getPath();
 	}
 
 	/**
 	 * @param boolean $absolute whether or not the path should be absolute.
 	 * @return string the path.
 	 */
-	public function getImagePath($absolute=false)
+	protected function getImagePath($absolute=false)
 	{
 		$path='';
 
 	}
 
 	/**
-	 * Returns the original image file name.
-	 * @param Image $image the image model.
-	 * @return string the file name.
-	 */
-	protected function resolveFileName($image)
-	{
-		if($image instanceof Image)
-		{
-			if(!empty($image->name))
-				return $image->name.'-'.$image->id.'.'.$image->extension; // since 1.2.0
-			else
-				return $image->id.'.'.$image->extension; // backwards compatibility
-		}
-		else
-			return null;
-	}
-
-	/**
-	 * Returns the path to a specific image version.
-	 * @param Image $image the image model.
-	 * @param string $version the image version.
-	 * @return string the path.
-	 */
-	protected function resolveImageVersionPath($image,$version)
-	{
-		if($image instanceof Image)
-			return $this->getVersionPath($version,true).$this->resolveFileName($image);
-		else
-			return null;
-	}
-
-	/**
-	 * Returns the base path.
-	 * @return string the path.
-	 */
-	protected function getBasePath()
-	{
-		if($this->_basePath!==null)
-			return $this->_basePath;
-		else
-			return $this->_basePath=realpath(Yii::app()->basePath.'/../').'/';
-	}
-
-	/**
 	 * Returns the image version path.
 	 * @param boolean $absolute whether or not the path should be absolute.
 	 * @return string the path.
 	}
 
 	/**
+	 * Returns the base path.
+	 * @return string the path.
+	 */
+	protected function getBasePath()
+	{
+		if($this->_basePath!==null)
+			return $this->_basePath;
+		else
+			return $this->_basePath=realpath(Yii::app()->basePath.'/../').'/';
+	}
+
+	/**
+	 * Creates the specified directory.
+	 * @param string $path the directory path.
+	 * @param integer $mode the file mode.
+	 * @param boolean $recursive allows the creation of nested directories.
+	 * @return boolean whether or not the directory was created.
+	 * @since 1.2.1
+	 */
+	protected function createDirectory($path,$mode=0777,$recursive=true)
+	{
+		return mkdir($path,$mode,$recursive);
+	}
+
+	/**
 	 * Normalizes the given string by replacing special characters. �=>a, �=>e, �=>o, etc.
-	 * @param string the string to normalize.
+	 * @param string $text the text to normalize.
 	 * @return string the normalized string.
 	 * @since 1.2.0
 	 */
-	protected function normalizeString($string)
+	protected function normalizeString($text)
 	{
-        return preg_replace('~&([a-z]{1,2})(acute|cedil|circ|grave|lig|orn|ring|slash|th|tilde|uml);~i','$1',htmlentities($string,ENT_QUOTES,'UTF-8'));
+        return preg_replace('~&([a-z]{1,2})(acute|cedil|circ|grave|lig|orn|ring|slash|th|tilde|uml);~i','$1',htmlentities($text,ENT_QUOTES,'UTF-8'));
 	}
 
 	/**
 	 * Creates a new image.
-	 * @param string $fileName the file name.
+	 * @param string $filePath the image file path.
 	 * @return ImgThumb
 	 */
-	protected static function thumbFactory($fileName)
+	protected static function thumbFactory($filePath)
 	{
-		$phpThumb=PhpThumbFactory::create(self::$_imagePath.$fileName,self::$_thumbOptions);
+		$phpThumb=PhpThumbFactory::create($filePath,self::$_thumbOptions);
 		return new ImgThumb($phpThumb);
 	}
 }

components/ImgRecordBehavior.php

 	/**
 	 * Saves the image for the owner of this behavior.
 	 * @param string $name the image name.
+	 * @param string $path the path for saving the image.
 	 * @param CUploadedFile $file the uploaded file.
 	 */
-	public function saveImage($name,$file)
+	public function saveImage($file,$name=null,$path=null)
 	{
-		$image=Yii::app()->image->save($name,$file);
+		$image=Yii::app()->image->save($file,$name,$path);
 
 		if($image!==null && $this->owner->hasAttribute($this->attribute))
 			$this->owner->{$this->attribute}=$image->id;

messages/templates/error.php

   'Failed to create the access file! File could not be created.' => '',
   'Failed to create the access file! Template could not be read.' => '',
   'Failed to create version! Image could not be found.' => '',
+  'Failed to create version! Directory could not be created.' => '',
   'Failed to create version! Version is unknown.' => '',
   'Failed to crop image! Crop method is unknown.' => '',
   'Failed to delete image version! Version is unknown.' => '',
   'Failed to resize image! Resize method is unknown.' => '',
   'Failed to rotate image! Rotate method is unknown.' => '',
   'Failed to save image! File could not be saved.' => '',
+  'Failed to save image! Directory could not be created.' => '',
   'Failed to save image! Record could not be saved.' => '',
 );
  * The followings are the available columns in table 'Image':
  * @property integer $id
  * @property string $name
+ * @property string $path
  * @property string $extension
  * @property string $filename
  * @property integer $byteSize
 	public function rules()
 	{
 		return array(
-			array('name, extension, filename, byteSize, mimeType','required'),
+			array('name, path, extension, filename, byteSize, mimeType','required'),
 			array('byteSize','numerical','integerOnly'=>true),
-			array('name, extension, filename, mimeType, created','length','max'=>255),
-			array('id, name, extension, filename, byteSize, mimeType, created','safe','on'=>'search'),
+			array('name, path, extension, filename, mimeType, created','length','max'=>255),
+			array('id, name, path, extension, filename, byteSize, mimeType, created','safe','on'=>'search'),
 		);
 	}
 
 		return array(
 			'id' => Img::t('core','Id'),
 			'name' => Img::t('core','Name'),
+			'path' => Img::t('core','Path'),
 			'extension' => Img::t('core','Extension'),
 			'filename' => Img::t('core','Filename'),
 			'byteSize' => Img::t('core','Byte Size'),
 
 		$criteria->compare('id',$this->id);
 		$criteria->compare('name',$this->name,true);
+		$criteria->compare('path',$this->path,true);
 		$criteria->compare('extension',$this->extension,true);
 		$criteria->compare('filename',$this->filename,true);
 		$criteria->compare('byteSize',$this->byteSize);
 		$src = Yii::app()->image->getURL($this->id,$version);
 		echo CHtml::image($src,$alt,$htmlOptions);
 	}
+
+	/**
+	 * @return string the path for this image.
+	 */
+	public function getPath()
+	{
+		return !empty($this->path) ? $this->path.'/' : '';
+	}
 }