06.05 php saved
adrien.gibrat
Tags add more
 
Note
An upload behavior that give standard methods to validate uploaded files and set mimetype & filesize automagic model fields.

Do just upload, but do it well.

Sorry but it's not well documented!
  1. <?php
  2. /**
  3. Exemple how to use this behavior in your model:
  4.     var $actsAs                 = array(
  5.         'Upload'    => 'audio_file',// use one field with default options
  6. //      'Upload'    => array('audio_file','image_file')// use two fields with default options
  7. //      'Upload'    => array('audio_file'=>array('dir'=>'/data','filename'=>'my_method'))// use one fields with custom options
  8.         );
  9.     var $validate               = array(
  10.         'audio_file'       => array(
  11.             'upload_type' => array(
  12.                 'rule'          => array('upload_type', array('audio/x-wav','audio/mpeg')),
  13.                 'no_upload'     => true,// no_upload is what should return the test is no uploaded file
  14.                 'message'       => 'Please provide a wav or mp3 file.'
  15.             ),
  16.             'upload_size' => array(
  17.                 'rule'          => array('upload_size', '30k', null),
  18.                 'no_upload'     => true,
  19.                 'message'       => 'Please provide file up to 30 ko.'
  20.             ),
  21.             'uploaded' => array(
  22.                 'rule'          => array('uploaded', null),
  23.                 'no_upload'     => true,
  24.                 'message'       => 'Error while uploading file.'
  25.             ),
  26.             'create' => array(
  27.                 'rule'          => array('uploaded', null),
  28.                 'on'            => 'create',
  29.                 'message'       => 'Please provide a file.'
  30.             )
  31.         ),
  32.     );
  33.  
  34.     function my_method($filename) {
  35.         return md5(uniqid(time())) . '-' . $filename;
  36.     }
  37. */
  38.  
  39. if (!defined('FILES')) {
  40.     define('FILES', WWW_ROOT . 'files' . DS);
  41. }
  42.  
  43. class UploadBehavior extends ModelBehavior {
  44.  
  45.     var $options    = array(       
  46.         'dir'       => null,
  47.         'filename'  => null,
  48.         'overwrite' => null,
  49.         'cascade'   => null,
  50.         'messages'  => array(
  51.             'no_dir'        => 'The servers upload directory is missing.',
  52.             'no_write'      => 'Failed to write to the upload directory.',
  53.             'file_exists'   => 'The file %s already exists.',
  54.             'no_move'       => 'Failed to move file the upload directory.'
  55.         )
  56.     );
  57.  
  58.     var $fields     = array();
  59.  
  60.     function setup(&$model, $config = array()) {
  61.         if(!is_array($config)) {
  62.             $config = array($config);
  63.         }
  64.         foreach($config as $field => $options) {
  65.             if(is_numeric($field) && is_string($options) && $model->hasField($options)) {
  66.                 unset($config[$field]);
  67.                 $field = $options;
  68.                 $options = array();
  69.             } elseif(!$model->hasField($field)) {
  70.                 unset($config[$field]);
  71.                 continue;
  72.             }
  73.             $options = array_merge_recursive($this->options, $options);
  74.             if(empty($options['dir'])) {
  75.                 $options['dir'] = FILES . low(Inflector::pluralize($model->name) . DS . $field) . DS;
  76.             } elseif(substr($options['dir'], -1) != DS) {
  77.                 $options['dir'] .= DS;
  78.             }
  79.             $config[$field] = $options;
  80.         }
  81.         $this->fields = $config;
  82.     }
  83.  
  84.     function beforeSave(&$model) {
  85.         if(count($this->fields)) {
  86.             foreach($this->fields as $field => $options) {
  87.                 if (!empty($model->data[$model->name][$field]['tmp_name']) && file_exists($model->data[$model->name][$field]['tmp_name'])) {
  88.                     if(!is_dir($options['dir']) && !Folder::mkdirr($options['dir'])) {
  89.                         return $model->invalidate($field, $options['messages']['no_dir']) && false;
  90.                     }
  91.                     if(!is_writable($options['dir'])) {
  92.                         return $model->invalidate($field, $options['messages']['no_write']) && false;
  93.                     }
  94.                     if($options['filename'] === true) {
  95.                         $filename  = $model->data[$model->name][$field]['name'];
  96.                     } elseif(method_exists($model, $options['filename'])) {
  97.                         $filename  = call_user_func(array($model, $options['filename']), $model->data[$model->name][$field]['name']);
  98.                     } else {
  99.                         $filename  = md5(uniqid(time())) . '.' . pathinfo($model->data[$model->name][$field]['name'], PATHINFO_EXTENSION);
  100.                     }
  101.                     $file = $options['dir'] . $filename;
  102.                     if(empty($options['overwrite']) && file_exists($file)) {
  103.                         return $model->invalidate($field, sprintf($options['messages']['no_write'], $filename)) && false;
  104.                     }
  105.                     if(!move_uploaded_file(@$model->data[$model->name][$field]['tmp_name'], $file)) {
  106.                         return $model->invalidate($field, $options['messages']['no_move']) && false;
  107.                     }
  108.                     $model->data[$model->name][$field] = $filename;
  109.                     $model->data[$model->name]['mimetype'] = mime_content_type($file);
  110.                     $model->data[$model->name]['filesize'] = filesize($file);
  111.                 } else {
  112.                     //Not an uploaded file
  113.                 }
  114.             }
  115.         }
  116.     }
  117.  
  118.     function beforeDelete(&$model, $cascade) {
  119.         if(count($this->fields)) {
  120.             $model->read(null, $model->id);
  121.             if(isset($model->data)) {
  122.                 foreach($this->fields as $field => $options) {
  123.                     $file   = $options['dir'] . $model->data[$model->name][$field];
  124.                     if(is_file($file) && !unlink($file)) {
  125.                         return false;
  126.                     }
  127.                 }
  128.             }
  129.         }
  130.         return true;
  131.     }
  132.  
  133.     function afterDelete(&$model) {
  134.         if(count($this->fields)) {
  135.             foreach($this->fields as $field => $options) {
  136.                 $used  = $model->findAll("{$model->name}.$field = '{$model->data[$model->name][$field]}'");
  137.                 if(!empty($options['cascade']) && !empty($used)){
  138.                     foreach($used as $line) {
  139.                         $model->del($line[$model->name]['id']);
  140.                     }
  141.                 }
  142.             }
  143.         }
  144.     }
  145.  
  146.     /* check uploaded file error */
  147.     function uploaded($model, $check, $messages = array(), $param) {
  148.         if(!$this->upload_check($model, $check, $param)) {
  149.             return false;
  150.         }
  151.         $messages(array)$messages + array(
  152.             'Error while uploading file.',
  153.             UPLOAD_ERR_INI_SIZE     => 'The file is too large, max filesize on server: %s.',
  154.             UPLOAD_ERR_FORM_SIZE    => 'The file is too large, max filesize on form: %s.',
  155.             UPLOAD_ERR_PARTIAL      => 'The file was only partially uploaded.',
  156.             UPLOAD_ERR_NO_TMP_DIR   => 'The servers temporary folder is missing.',
  157.             UPLOAD_ERR_CANT_WRITE   => 'Failed to write file to disk.',
  158.             UPLOAD_ERR_EXTENSION    => 'File upload stopped by extension.'
  159.         );
  160.         $data = array_shift(array_values($check));
  161.         $message = !empty($messages[$data['error']]) ?
  162.             $messages[$data['error']] :
  163.             (!empty($param['message']) ? $param['message'] : $messages[0]);
  164.         switch($data['error']) {
  165.             case UPLOAD_ERR_OK:
  166.                 return true;
  167.             case UPLOAD_ERR_NO_FILE:
  168.                 return isset($param['no_upload']) && $param['no_upload'];
  169.             case UPLOAD_ERR_INI_SIZE:
  170.                 $message = sprintf($message, $this->_size_format($this->_size_int(ini_get('upload_max_filesize'))));
  171.             break;
  172.             case UPLOAD_ERR_FORM_SIZE:
  173.                 $message = sprintf($message, $this->_size_format($_POST['MAX_FILE_SIZE']));
  174.             break;
  175.         }
  176.         return $model->invalidate(array_shift(array_keys($check)), $message) && true;
  177.         // return true to show the custom message
  178.     }
  179.  
  180.     /* check if file is uploaded via HTTP POST */
  181.     function upload_check($model, $check, $param) {
  182.         $data = array_shift(array_values($check));
  183.         return !empty($data['tmp_name']) ?
  184.             is_uploaded_file($data['tmp_name']) :
  185.             (isset($param['no_upload']) && $param['no_upload']);
  186.     }
  187.  
  188.     /* check uploaded file name */
  189.     function upload_name($model, $check, $regex = VALID_NOT_EMPTY, $param) {
  190.         $data = array_shift(array_values($check));
  191.         return !empty($data['tmp_name']) ?
  192.             preg_match($regex, $data['name']) :
  193.             (isset($param['no_upload']) && $param['no_upload']);
  194.     }
  195.  
  196.     /* check uploaded file type */
  197.     function upload_type($model, $check, $allowed = array('image/jpeg', 'image/png', 'image/gif'), $param) {
  198.         $data = array_shift(array_values($check));
  199.         return !empty($data['tmp_name']) ?
  200.             in_array(mime_content_type($data['tmp_name']), $allowed) :
  201.             (isset($param['no_upload']) && $param['no_upload']);
  202.     }
  203.  
  204.     /* check uploaded file size */
  205.     function upload_size($model, $check, $min = 0, $max = null, $param) {
  206.         $max = !$max ? ini_get('upload_max_filesize') : $max;
  207.         $data = array_shift(array_values($check));
  208.         return !empty($data['tmp_name']) ?
  209.             Validation::range(filesize($data['tmp_name']), $this->_size_int($min), $this->_size_int($max)) :
  210.             (isset($param['no_upload']) && $param['no_upload']);
  211.     }
  212.  
  213.     function _size_format($size) {
  214.         return array_reduce (
  215.             array ('octets', 'Ko', 'Mo'),
  216.             create_function('$a,$b', 'return is_numeric($a)?($a>=1024?$a/1024:intval($a)." ".$b):$a;'),
  217.             $size
  218.         );
  219.     }
  220.  
  221.     function _size_int($size) {
  222.         switch(substr(low(preg_replace('/[^tgmk]/i' , '', $size)), 0, 1)) {
  223.             case 'm':
  224.                 $size *= 1024;
  225.             case 'k':
  226.                 $size *= 1024;
  227.         }
  228.         return intval($size);
  229.     }
  230.  
  231. }
  232. ?>
  233.  
Parsed in 0.494 seconds, using GeSHi 1.0.7.14

Modify this Paste