Created
March 6, 2012 14:18
-
-
Save fullybaked/1986510 to your computer and use it in GitHub Desktop.
Upload Component for CakePHP 2.0
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Component handles various types of file upload | |
* | |
* @author Dave Baker | |
* @copyright Dave Baker / Fully Baked 2012 | |
* @link www.fullybaked.co.uk | |
*/ | |
class UploadComponent extends Component { | |
/** | |
* constant for error types | |
* @var integer | |
*/ | |
const SUCCESS = 0; | |
const FILESIZE_EXCEED_SERVER_MAX = 1; | |
const FILESIZE_EXCEED_FORM_MAX = 2; | |
const PARTIAL_UPLOAD = 3; | |
const NO_FILE_UPLOAD = 4; | |
const NO_DIRECTORY_FOR_UPLOAD = 6; | |
const SERVER_WRITE_FAIL = 7; | |
const FILESIZE_EXCEEDS_CODE_MAX = 98; | |
const FILE_FORMAT_NOT_ALLOWED = 99; | |
const DESTINATION_NOT_AVAILABLE = 100; | |
/** | |
* array of mime types that will be accepted by the UploadComponent | |
* left empty it will accept any | |
*/ | |
private $file_types = array(); | |
private $filename = null; | |
private $destination = null; | |
private $max_size = null; | |
private $content_only = false; | |
private $create_destination = true; | |
/** | |
* component constructor - set up local vars based on settings array in controller | |
*/ | |
public function __construct(ComponentCollection $collection, $settings = array()) { | |
if (!empty($settings['file_types'])) $this->file_types = $settings['file_types']; | |
if (!empty($settings['max_size'])) $this->max_size = $settings['max_size']; | |
} | |
/** | |
* set the allowed file types for this upload | |
* values are passed as string arguments to the | |
* method | |
* @example allowed_files('image/jpg', 'image/gif', 'image/png'); | |
* @return UploadComponent | |
*/ | |
public function allowed_types() { | |
$types = func_get_args(); | |
$this->file_types = $this->file_types + $types; | |
return $this; | |
} | |
/** | |
* set a custom name to use for the final uploaded file | |
* if not set then the original name of the uploaded file is used | |
* @param string $name | |
* @return UploadComponent | |
*/ | |
public function custom_name($name) { | |
$this->filename = $name; | |
return $this; | |
} | |
/** | |
* set the destination path for the uploaded file | |
* @param string $path | |
* @return UploadComponent | |
*/ | |
public function destination($path) { | |
// add trailing slash if there isn't one | |
$last_char = substr($path, -1); | |
if ($last_char !== '/') $path .= '/'; | |
$this->destination = $path; | |
return $this; | |
} | |
/** | |
* set the max file size for uploads for added validation | |
* if $this->max_size = 0 (default) then upload size is governed | |
* by PHP.ini settings and/or form settings. | |
* @param integer $size - max size of upload in bytes | |
* @return UploadComponent | |
*/ | |
public function set_max_size($size) { | |
$this->max_size = $size; | |
return $this; | |
} | |
/** | |
* setter for the content_only flag | |
* if true then the upload is read into buffer | |
* and returned rather than being written to server | |
* @param boolean $flag | |
* @return UploadComponent | |
*/ | |
public function content_only($flag = true) { | |
$this->content_only = $flag; | |
return $this; | |
} | |
/** | |
* setter for the create destination flag. | |
* can be turned off if an error on missing destination is required | |
* @param boolean $flag | |
* @return UploadComponent | |
*/ | |
public function create_destination($flag = true) { | |
$this->create_destination = $flag; | |
return $this; | |
} | |
/** | |
* run the upload. | |
* the path param is optional and can be set separately | |
* @param array $form_data - The posted form data for the file element | |
* @param string $path - Optionally set the destination path here | |
* @return mixed - | |
*/ | |
public function upload($form_data, $path = null) { | |
// silent fail on no image | |
if ($form_data['error'] == self::NO_FILE_UPLOAD) { | |
throw new Exception ($this->errors(self::NO_FILE_UPLOAD), self::NO_FILE_UPLOAD); | |
} | |
// handle optional path passed in | |
if (!empty($path)) $this->destination($path); | |
$this->form_data = $form_data; | |
// check we have a path - only if not returning the content | |
if ($this->content_only === false) { | |
if (empty($path) && empty($this->destination)) { | |
$this->form_data['error'] = self::NO_DIRECTORY_FOR_UPLOAD; | |
} | |
} | |
// check file types | |
if (!empty($this->file_types)) { | |
if (!in_array($this->form_data['type'], $this->file_types)) { | |
$this->form_data['error'] = self::FILE_FORMAT_NOT_ALLOWED; | |
} | |
} | |
// check max size set in code | |
if ($this->max_size > 0 && $this->form_data['size'] > $this->max_size) { | |
$this->form_data['error'] = self::FILE_SIZE_EXCEEDS_CODE_MAX; | |
} | |
// check error code | |
if ($this->form_data['error'] !== self::SUCCESS) { | |
throw new Exception($this->errors($this->form_data['error']), $this->form_data['error']); | |
} | |
// if only content required read file and return | |
if ($this->content_only) { | |
return file_get_contents($this->form_data['tmp_name']); | |
} | |
// parse out class params to make the final destination string | |
if (empty($this->filename)) { | |
$destination = $this->destination . $this->form_data['name']; | |
} else { | |
$destination = $this->destination . $this->filename; | |
} | |
// create the destination unless otherwise set | |
if ($this->create_destination) { | |
$dir = dirname($destination); | |
if (!is_dir($dir)) { | |
mkdir($dir, 0777, true); | |
} | |
} else { | |
$dir = dirname($destination); | |
if (!is_dir($dir)) { | |
throw new Exception($this->errors(self::DESTINATION_NOT_AVAILABLE), self::DESTINATION_NOT_AVAILABLE); | |
} | |
} | |
if (move_uploaded_file($this->form_data['tmp_name'], $destination)) { | |
return $destination; | |
} else { | |
throw new Exception($this->errors(self::SERVER_WRITE_FAIL), self::SERVER_WRITE_FAIL); | |
} | |
// if we get here without returning something has definitely gone wrong | |
throw new Exception($this->errors()); | |
} | |
/** | |
* parse the response type and return an error string | |
* @param integer $type | |
* @return string - error text | |
*/ | |
private function errors($type = null) { | |
switch ($type) { | |
case self::FILESIZE_EXCEED_SERVER_MAX: | |
return 'File size exceeds allowed size for server'; | |
break; | |
case self::FILESIZE_EXCEED_FORM_MAX: | |
return 'File size exceeds allowed size in form'; | |
break; | |
case self::PARTIAL_UPLOAD: | |
return 'File was partially uploaded. Please check your Internet connection and try again'; | |
break; | |
case self::NO_FILE_UPLOAD: | |
return 'No file was uploaded.'; | |
break; | |
case self::NO_DIRECTORY_FOR_UPLOAD: | |
return 'No upload directory found'; | |
break; | |
case self::SERVER_WRITE_FAIL: | |
return 'Failed to write to the server'; | |
break; | |
case self::FILE_FORMAT_NOT_ALLOWED: | |
return 'File format of uploaded file is not allowed'; | |
break; | |
case self::FILESIZE_EXCEEDS_CODE_MAX: | |
return 'File size exceeds maximum allowed size'; | |
break; | |
case self::DESTINATION_NOT_AVAILABLE: | |
return 'Destination path does not exist'; | |
break; | |
default: | |
return 'There has been an unexpected error, processing upload failed'; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment