Skip to content

Instantly share code, notes, and snippets.

@robksawyer
Created August 21, 2013 07:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save robksawyer/6291290 to your computer and use it in GitHub Desktop.
Save robksawyer/6291290 to your computer and use it in GitHub Desktop.
<?php
App::uses('AppModel', 'Model');
App::uses('AttachmentBehavior', 'Uploader.Model/Behavior');
App::uses('FileValidationBehavior', 'Uploader.Model/Behavior');
/**
* Attachment Model
*
* @property User $User
* @property CheeseProducer $CheeseProducer
* @property Cheese $Cheese
* @property User $User
*/
use Aws\Common\Enum\Region;
class Attachment extends AppModel {
/**
* Display field
*
* @var string
*/
public $displayField = 'name';
//Resize properties
public $imageSmallWidth = '75';
public $imageSmallAppend = '_small';
public $imageSmallDBCol = 'path_small';
//
public $imageMedWidth = '320';
public $imageMedAppend = '_med';
public $imageMedDBCol = 'path_med';
public $currentModelID = null;
public $currentModel = null;
public $uploadDir = null; //The main path to upload the attachment to
public $finalPath = null; //The path that is appended to records in the database
public $modelClass = null; //The model to save in the database as a reference
public $modelId = null; //The model id to save in the database as a reference
public $bucket = null; //The S3 Bucket that the attachment lives in
//The Associations below have been created with all possible keys, those that are not needed can be removed
public $actsAs = array(
'Containable',
'Uploader.FileValidation' => array(
'fileName' => array(
'type' => array('image'), //The type value can be anything before the / in the mime type declarations.
'required' => false,
'minWidth' => 150,
'minHeight' => 150,
'filesize' => 10485760 //10 MB
)
),
'Uploader.Attachment' => array(
'fileName' => array(
'nameCallback' => 'formatFileName',
'overwrite' => true,
'stopSave' => false,
'required' => false,
'dbColumn' => 'path',
'uploadDir' => '/tmp',
'finalPath' => '/',
'metaColumns' => array(
'name' => 'name',
'ext' => 'extension',
'type' => 'mimeType',
'size' => 'fileSize',
'width' => 'width',
'height' => 'height'
),
'transforms' => array(
'path_small' => array(
'nameCallback' => 'transformName',
'method' => 'resize',
'overwrite' => true,
'width' => 75
),
'path_small_crop' => array(
'nameCallback' => 'transformName',
'method' => 'crop',
'append' => '_crop',
'overwrite' => true,
'width' => 75,
'height' => 75
),
'path_med' => array(
'nameCallback' => 'transformName',
'method' => 'resize',
'overwrite' => true,
'width' => 250
),
'path_med_crop' => array(
'nameCallback' => 'transformName',
'method' => 'crop',
'append' => '_crop',
'overwrite' => true,
'height' => 250,
'width' => 250
),
'path_large' => array(
'nameCallback' => 'transformName',
'method' => 'resize',
'expand' => true,
'overwrite' => true,
'width' => 640
),
'path_large_crop' => array(
'nameCallback' => 'transformName',
'method' => 'crop',
'append' => '_crop',
'expand' => true,
'overwrite' => true,
'height' => 640,
'width' => 640
)
),
'transport' => array(
'class' => AttachmentBehavior::S3,
'accessKey' => CC_S3_ACCESS_KEY,
'secretKey' => CC_S3_SECRET_KEY,
'bucket' => '',
'region' => Aws\Common\Enum\Region::US_WEST_2,
'folder' => '',
'meta' => array(
'ext' => 'extension',
'type' => 'mimeType',
'size' => 'fileSize',
'width' => 'width',
'height' => 'height'
)
)
)
)
);
/**
* belongsTo associations
*
* @var array
*/
public $belongsTo = array(
'User' => array(
'className' => 'User',
'foreignKey' => 'user_id',
'conditions' => '',
'fields' => '',
'order' => ''
)
);
/**
* hasMany associations
*
* @var array
*/
public $hasMany = array(
'Badge' => array(
'className' => 'Badge',
'foreignKey' => 'attachment_id',
'dependent' => false,
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'exclusive' => '',
'finderQuery' => '',
'counterQuery' => ''
),
'CheeseProducer' => array(
'className' => 'CheeseProducer',
'foreignKey' => 'attachment_id',
'dependent' => false,
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'exclusive' => '',
'finderQuery' => '',
'counterQuery' => ''
),
'CheeseProducerLocation' => array(
'className' => 'CheeseProducerLocation',
'foreignKey' => 'attachment_id',
'dependent' => false,
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'exclusive' => '',
'finderQuery' => '',
'counterQuery' => ''
),
'CheeseLocation' => array(
'className' => 'CheeseLocation',
'foreignKey' => 'attachment_id',
'dependent' => false,
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'exclusive' => '',
'finderQuery' => '',
'counterQuery' => ''
),
'CheeseRegion' => array(
'className' => 'CheeseRegion',
'foreignKey' => 'attachment_id',
'dependent' => false,
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'exclusive' => '',
'finderQuery' => '',
'counterQuery' => ''
),
'Cheese' => array(
'className' => 'Cheese',
'foreignKey' => 'attachment_id',
'dependent' => false,
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'exclusive' => '',
'finderQuery' => '',
'counterQuery' => ''
),
'CheeseType' => array(
'className' => 'CheeseType',
'foreignKey' => 'attachment_id',
'dependent' => false,
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'exclusive' => '',
'finderQuery' => '',
'counterQuery' => ''
),
'User' => array(
'className' => 'User',
'foreignKey' => 'attachment_id',
'dependent' => false,
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'exclusive' => '',
'finderQuery' => '',
'counterQuery' => ''
),
'AnimalBreed' => array(
'className' => 'AnimalBreed',
'foreignKey' => 'attachment_id',
'dependent' => false,
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'exclusive' => '',
'finderQuery' => '',
'counterQuery' => ''
),
'Affineur' => array(
'className' => 'Affineur',
'foreignKey' => 'attachment_id',
'dependent' => false,
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'exclusive' => '',
'finderQuery' => '',
'counterQuery' => ''
),
'Cheesemaker' => array(
'className' => 'Cheesemaker',
'foreignKey' => 'attachment_id',
'dependent' => false,
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'exclusive' => '',
'finderQuery' => '',
'counterQuery' => ''
),
'Place' => array(
'className' => 'Place',
'foreignKey' => 'attachment_id',
'dependent' => false,
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'exclusive' => '',
'finderQuery' => '',
'counterQuery' => ''
),
'MilkSource' => array(
'className' => 'MilkSource',
'foreignKey' => 'attachment_id',
'dependent' => false,
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'exclusive' => '',
'finderQuery' => '',
'counterQuery' => ''
)
);
/**
* beforeSave Callback
* @link http://book.cakephp.org/2.0/en/models/callback-methods.html
* @param array $options
*/
public function beforeSave($options = array()){
if(isset($this->data[$this->alias]['fileName']) && $this->data[$this->alias]['fileName']['size'] > 0){
if(empty($this->modelClass)){
throw new InvalidArgumentException('You did not provide a model name.');
}
/*if(empty($this->modelId)){
throw new InvalidArgumentException('You did not provide a model id.');
}*/
//If a new attachment exists, delete the old one.
if(!empty($this->data[$this->modelClass]['attachment_id'])){
$success = $this->removeAttachment($this->data[$this->modelClass]['attachment_id']);
$this->data[$this->modelClass]['attachment_id'] = null;
}
$this->data[$this->alias] = $this->processAttachment();
}else{
unset($this->data[$this->alias]['fileName']); //Unset data to prevent a new record from being created.
}
debug($this->data);
return true;
}
/**
* beforeValidate Callback
* Handles finding out whether or not the user added an image via a URL
* @param array $options
*/
public function beforeValidate($options = array()){
if(!empty($this->data[$this->alias]['fileNameUrl'])){
unset($this->data[$this->alias]['fileName']);
$this->data[$this->alias]['fileName'] = $this->data[$this->alias]['fileNameUrl'];
unset($this->data[$this->alias]['fileNameUrl']);
}
return true;
}
/**
* beforeTransform Callback
* @param array $options
*/
/*public function beforeTransform($options){
if(empty($this->uploadDir)){
throw new InvalidArgumentException('You did not provide an upload directory.');
}
if(empty($this->finalPath)){
$this->finalPath = preg_replace('/'.IMAGES. 'uploads\//','',$this->uploadDir);
}
$options['uploadDir'] = $this->uploadDir;
$options['finalPath'] = $this->finalPath;
return $options;
}*/
/**
* beforeTransport Callback
* @param array $options
*/
public function beforeTransport($options){
if(empty($this->bucket)){
throw new InvalidArgumentException('You did not provide an Amazon S3 bucket.');
}
$options['bucket'] = $this->bucket;
return $options;
}
/**
* Format the filename a specific way before uploading and attaching.
*
* @access public
* @param string $name - The current filename without extension
* @param string $field - The form field name
* @param array $file - The $_FILES data
* @return string
*/
public function formatFileName($name, $file) {
//$name = $this->sanitize_file_name($name);
if(!empty($this->modelId)){
$name = $this->modelClass . "_" . $this->modelId;
}else{
$date = new DateTime(); //Create a Date
$stamp = $date->format('m_d_Y_H-i-s');
$name = $this->alias . "_" . $stamp;
}
//$this->data[$this->alias]['name'] = $name;
return $name;
}
/**
* transformName Callback
* @param $name
* @param $file
* @link http://milesj.me/code/cakephp/uploader
*/
public function transformName($name, $file) {
$fWidth = $file->width();
$fHeight = $file->height();
if(!empty($fWidth) && !empty($fHeight)){
$name = preg_replace('/-resize/', '', $this->getUploadedFile()->name());
$name = $name . '-' . $file->width();
}else{
$name = preg_replace('/-resize/', '', $name);
}
return $name;
}
/**
* processAttachment method
* This method simply handles processing the image data and building an array of useful data to be saved.
* @param void
* @return array Attachment data formatted
*/
public function processAttachment(){
$timestamp = date("Y-m-d H:m:s", time()); //Create a timestamp
if(empty($model->data[$this->alias]['edit_user_id'])){
$this->data[$this->alias]['edit_user_id'] = '';
}
if(empty($this->data[$this->alias]['active'])) $this->data[$this->alias]['active'] = 1; //Default to active
if(!isset($this->data[$this->alias]['name']) || empty($this->data[$this->alias]['name'])){
$this->data[$this->alias]['name'] = uniqid();
}
$formattedData = array(
'name' => $this->data[$this->alias]['name'],
'bucket' => $this->bucket,
'group' => 'image',
'model' => $this->modelClass,
//'model_id' => $this->modelId, //Only exists on the edit form
'active' => $this->data[$this->alias]['active'],
'uploaded' => $timestamp
);
if(!isset($this->data[$this->alias]['width']) || !isset($this->data[$this->alias]['height'])){
CakeLog::error('A width or height was not found. This image will not render properly.');
}else{
$formattedData['width'] = $this->data[$this->alias]['width'];
$formattedData['height'] = $this->data[$this->alias]['height'];
}
if(isset($this->data[$this->alias]['user_id'])) $formattedData['user_id'] = $this->data[$this->alias]['user_id'];
if(isset($this->data[$this->alias]['edit_user_id'])) $formattedData['edit_user_id'] = $this->data[$this->alias]['edit_user_id'];
if(isset($this->data[$this->alias]['path'])) $formattedData['path'] = $this->data[$this->alias]['path'];
if(isset($this->data[$this->alias]['path_small'])) $formattedData['path_small'] = $this->data[$this->alias]['path_small'];
if(isset($this->data[$this->alias]['path_small_crop'])) $formattedData['path_small_crop'] = $this->data[$this->alias]['path_small_crop'];
if(isset($this->data[$this->alias]['path_med'])) $formattedData['path_med'] = $this->data[$this->alias]['path_med'];
if(isset($this->data[$this->alias]['path_med_crop'])) $formattedData['path_med_crop'] = $this->data[$this->alias]['path_med_crop'];
if(isset($this->data[$this->alias]['path_large'])) $formattedData['path_large'] = $this->data[$this->alias]['path_large'];
if(isset($this->data[$this->alias]['path_large_crop'])) $formattedData['path_large_crop'] = $this->data[$this->alias]['path_large_crop'];
if(isset($this->data[$this->alias]['source_url'])) $formattedData['source_url'] = $this->data[$this->alias]['source_url'];
if(isset($this->data[$this->alias]['mimeType'])) $formattedData['type'] = $this->data[$this->alias]['mimeType'];
if(isset($this->data[$this->alias]['extension'])) $formattedData['ext'] = $this->data[$this->alias]['extension'];
if(isset($this->data[$this->alias]['fileSize'])){
$formattedData['size'] = $this->data[$this->alias]['fileSize'];
$formattedData['filesize'] = $this->filesize_format($this->data[$this->alias]['fileSize']);
}
CakeLog::info(json_encode($formattedData));
return $formattedData;
}
/**
* Removes the attachment from the file system and deletes the record from the db
* Note: The method also makes sure that the attachment is not being used by any other record first though.
* @param string id The attachment id
* @return bool Whether or not the deletion was a success or not
*/
public function removeAttachment($id = null){
$attachment = $this->find('first',array(
'conditions' => array('Attachment.id' => $id),
'fields' => array('id'),
'recursive' => -1
));
if(!empty($attachment['Attachment']['id'])){
//Delete the record
if($this->deleteFiles($attachment['Attachment']['id'],array('path_small','path_small_crop','path_med','path_med_crop','path_large','path_large_crop'))){
//$deleteSuccess = $this->deleteFiles($attachment['Attachment']['id']);
//Delete success
return true;
}
}
return false;
}
/**
* Function: sanitize
* Returns a sanitized string, typically for URLs.
*
* Parameters:
* $string - The string to sanitize.
* $force_lowercase - Force the string to lowercase?
* $anal - If set to *true*, will remove all non-alphanumeric characters.
*/
public function sanitize_file_name($string, $force_lowercase = true, $anal = false) {
$strip = array("~", "`", "!", "@", "#", "$", "%", "^", "&", "*", "(", ")", "_", "=", "+", "[", "{", "]",
"}", "\\", "|", ";", ":", "\"", "'", "&#8216;", "&#8217;", "&#8220;", "&#8221;", "&#8211;", "&#8212;",
"—", "–", ",", "<", ".", ">", "/", "?");
$clean = trim(str_replace($strip, "", strip_tags($string)));
$clean = preg_replace('/\s+/', "-", $clean);
$clean = ($anal) ? preg_replace("/[^a-zA-Z0-9]/", "", $clean) : $clean ;
return ($force_lowercase) ?
(function_exists('mb_strtolower')) ?
mb_strtolower($clean, 'UTF-8') :
strtolower($clean) :
$clean;
}
/**
* filesize_format method
* Formats the filesize
* @link http://codebyte.dev7studios.com/post/1590919646/php-format-filesize
*/
public function filesize_format($size, $sizes = array('Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB')) {
if ($size == 0) return('n/a');
return (round($size/pow(1024, ($i = floor(log($size, 1024)))), 2) . ' ' . $sizes[$i]);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment