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

Modify this Paste