03.12 php saved
bxtox
Tags add more
 
Note
Multiple Upload Behavior
  1. <?php
  2. /**
  3. *  Improved Multiple Upload Behaviour
  4. *  This behaviour is based on Chris Partridge's upload behaviour (http://bin.cakephp.org/saved/17539)
  5. *  @author Tane Piper (digitalspaghetti@gmail.com)
  6. *  @link http://www.digitalspaghetti.me.uk
  7. *  @filesource http://bakery.cakephp.org/articles/view/improved-upload-behaviour-with-thumbnails-and-name-correction
  8. *  @version 1.2.1
  9. *  @modifiedby      $LastChangedBy: dalpo85@gmail.com
  10. *  @lastmodified    $Date:2008/07/29$
  11. *  @svn             $Id:$
  12. *
  13. *  Version Details
  14. *  1.2.2
  15. *  + Rewritten dalpo
  16. *
  17. *
  18. *  1.2
  19. *  + Rewritten AD7six
  20. *
  21. *  1.1
  22. *  + Improved Image scaling code
  23. *  + Fixed check to see if file exists and rename file to unique name
  24. *  + Improved model actsAs to allow more thumbnail sizes
  25. *
  26. *  1.0
  27. *  + Initial release with thumbnail code.
  28. */
  29.  
  30.  
  31.  
  32.  
  33.  
  34. class MultipleUploadBehavior extends ModelBehavior {
  35.  
  36.     var $__defaultSettings = array(
  37.  
  38.         'defaultSettings' => array(
  39.  
  40.               'field' => 'photo',
  41.  
  42.               'allowedMime' => array('image/jpeg', 'image/pjpeg', 'image/gif', 'image/png', 'image/x-png'),
  43.  
  44.               'allowedExt' => array('jpg','jpeg','gif','png'),
  45.  
  46.               'overwriteExisting' => false,
  47.  
  48.               'deleteMainFile' => false,   
  49.  
  50.               'createDirectory' => true,
  51.  
  52.               'randomFilenames' => true,
  53.  
  54.               'thumbsizes' => array(
  55.  
  56.                   'small' => array('width' => 100, 'height' => 100, 'name' => '{$file}.small.{$ext}', 'autoResize' => true),
  57.  
  58.                   'medium' => array('width' => 220, 'height' => 220, 'name' => '{$file}.medium.{$ext}', 'autoResize' => true),
  59.  
  60.                   'large' => array('width' => 800, 'height' => 600, 'name' => '{$file}.large.{$ext}', 'autoResize' => true)
  61.  
  62.     ),
  63.  
  64.               'dir' => '{APP}uploads{DS}{$class}{DS}{$foreign_id}',
  65.  
  66.               'nameCleanups' => array(
  67.  
  68.     //'/&(.)(tilde);/' => "$1y", // ñs
  69.  
  70.     //'/&(.)(uml);/' => "$1e", // umlauts but umlauts are not pronounced the same is all languages.
  71.  
  72.     //'/�/' => 'ss', // German double s
  73.  
  74.     //'/&(.)elig;/' => '$1e', // ae and oe symbols
  75.  
  76.     //'/�/' => 'eth' // Icelandic eth symbol
  77.  
  78.     //'/�/' => 'thorn' // Icelandic thorn
  79.  
  80.  
  81.  
  82.                   '/&(.)(acute|caron|cedil|circ|elig|grave|horn|ring|slash|th|tilde|uml|zlig);/' => '$1', // strip all
  83.  
  84.                   'decode' => true, // html decode at this point
  85.  
  86.                   '/\&/' => ' and ', // Ampersand
  87.  
  88.                   '/\+/' => ' plus ', // Plus
  89.  
  90.                   '/([^a-z0-9\.]+)/' => '_', // None alphanumeric
  91.  
  92.                   '/\\_+/' => '_' // Duplicate sperators
  93.  
  94.     )
  95.     )
  96.  
  97.     );
  98.  
  99.     function setup(&$model, $config=array()) {
  100.         $settings = am ($this->__defaultSettings, $config);
  101.         uses('folder');
  102.         $this->settings[$model->name] = $settings;
  103.     }
  104.  
  105.  
  106.     /**
  107.      * Before Save Method..
  108.      *
  109.      * @param object $model
  110.      * @return boolean
  111.      */
  112.     function beforeSave(&$model) {
  113.         $uploadedFiles  = array();
  114.         $error = true;
  115.         foreach ($this->settings[$model->name] as $keyName => $fileValues) {
  116.             if($keyName == 'defaultSettings') continue;
  117.             extract(am($this->settings[$model->name]['defaultSettings'],$fileValues));
  118.  
  119.             // Check for upload
  120.             if(!isset($model->data[$model->name][$field])) {
  121.                 continue;
  122.             }
  123.             if($model->data[$model->name][$field]['error'] == 4) {
  124.                 unset($model->data[$model->name][$field]);
  125.                 continue;
  126.             }
  127.  
  128.             // Check it's a file submission
  129.             if (!is_array($model->data[$model->name][$field])) {
  130.                 debug($field.' is not an array\nForm must be multipart/form-data');
  131.                 $error = false;
  132.                 break;
  133.             }
  134.  
  135.             // Check error
  136.             if($model->data[$model->name][$field]['error'] > 0) {
  137.                 debug('Not valid file\nerror in upload data');
  138.                 $error = false;
  139.                 break;
  140.             }
  141.  
  142.             // Check mime
  143.             if(count($allowedMime) > 0 && !in_array($model->data[$model->name][$field]['type'], $allowedMime)) {
  144.                 debug($field.' > '.$model->data[$model->name][$field]['type'].' is not a valid file\nerror in mime type');
  145.                 $error = false;
  146.                 break;
  147.             }
  148.  
  149.             // Check extensions
  150.             $parts = explode('.', low($model->data[$model->name][$field]['name']));
  151.             $extension = array_pop($parts);
  152.             $filename = implode('.', $parts);
  153.  
  154.             if(count($allowedExt) > 0 && !in_array($extension, $allowedExt)) {
  155.                 debug($field.' is not a valid file\nerror with extension '. $extension);
  156.                 $error = false;
  157.                 break;
  158.             }
  159.  
  160.             // Get filename
  161.             $filename = $this->_getFilename($model, $fileValues, $filename);
  162.             $model->data[$model->name][$field]['name'] = $filename.'.'.$extension;
  163.  
  164.             // Get file path
  165.             $dir = $this->_getPath($model, $fileValues, $dir);
  166.  
  167.             if (!$dir) {
  168.                 debug('couldn\'t determine or create directory for the field '.$field);
  169.                 $error = false;
  170.                 break;
  171.             }
  172.  
  173.             // Create final save path
  174.             $saveAs = $dir . DS . $model->data[$model->name][$field]['name'];
  175.  
  176.             // Check if file exists
  177.             if(file_exists($saveAs)) {
  178.                 if(!$settings['overwrite_existing'] || !unlink($saveAs)) {
  179.                     $model->data[$model->name][$field]['name'] = uniqid("") . $extension;
  180.                     $saveAs = $dir . DS . $model->data[$model->name][$field]['name'];
  181.                 }
  182.             }
  183.  
  184.             // Attempt to move uploaded file
  185.             if(!move_uploaded_file($model->data[$model->name][$field]['tmp_name'], $saveAs)) {
  186.                 debug('could not move file');
  187.                 $error = false;
  188.                 break;
  189.             }
  190.  
  191.             $uploadedFiles[$keyName] = array(
  192.                     'dir' => $dir,
  193.                     'filename' => $model->data[$model->name][$field]['name'],
  194.                     'saveas' => $saveAs
  195.             );
  196.         }
  197.  
  198.         // If there are errors delete all uploaded files
  199.         if(!$error) {
  200.             foreach ($uploadedFiles as $file) {
  201.                 unlink($file['saveas']);
  202.             }
  203.             return false;
  204.         }
  205.  
  206.         //if all files are uploaded then
  207.         foreach ($this->settings[$model->name] as $keyName => $fileValues) {
  208.             if($keyName == 'defaultSettings') continue;
  209.             extract(am($this->settings[$model->name]['defaultSettings'],$fileValues));
  210.             // Check for upload
  211.             if(!isset($model->data[$model->name][$field]) || $model->data[$model->name][$field]['error'] == 4) continue;
  212.  
  213.             //on Edit or Update delete old files
  214.             if(isset($model->data[$model->name]['id'])) {
  215.                 $oldFileName = $model->findById($model->id,array($model->name.'.'.$field));
  216.  
  217.                 foreach ($thumbsizes as $key => $thumbsize) {
  218.                     //unlink($this->_getPath($model,$dir).DS.$this->getThumbname($model, $key, $fileName[$model->name][$field]));
  219.                     if(file_exists($this->_getPath($model,$fileValues,$dir).DS.$this->getThumbname($model, $fileValues, $key, $oldFileName[$model->name][$field]))
  220.                     && !is_dir($this->_getPath($model,$fileValues,$dir).DS.$this->getThumbname($model, $fileValues, $key, $oldFileName[$model->name][$field]))) {
  221.                         unlink($this->_getPath($model,$fileValues,$dir).DS.$this->getThumbname($model, $fileValues, $key, $oldFileName[$model->name][$field]));
  222.                     }
  223.                 }
  224.                 if(file_exists($this->_getPath($model,$fileValues,$dir).DS.$oldFileName[$model->name][$field])
  225.                 && !is_dir($this->_getPath($model,$fileValues,$dir).DS.$oldFileName[$model->name][$field])) {
  226.                     unlink($this->_getPath($model,$fileValues,$dir).DS.$oldFileName[$model->name][$field]);
  227.                 }
  228.             }
  229.  
  230.             // Create thumbnail of uploaded image
  231.             // This is hard-coded to only support JPEG + PNG + GIF at this time
  232.             if (count($allowedExt) > 0 && in_array($model->data[$model->name][$field]['type'], $allowedMime)) {
  233.                 foreach ($thumbsizes as $key => $value) {
  234.                     if(!isset($value['autoResize'])) $value['autoResize'] = true;
  235.                     $thumbName = $this->getThumbname ($model, $fileValues, $key, $uploadedFiles[$keyName]['filename']);
  236.                     $this->createthumb($model, $uploadedFiles[$keyName]['saveas'], $uploadedFiles[$keyName]['dir'] . DS . $thumbName, $value['width'], $value['height'], $value['autoResize']);
  237.                 }
  238.             }
  239.  
  240.             // Update model data
  241.             $model->data[$model->name]['dir'] = str_replace(ROOT . DS . APP_DIR . DS, '', $dir);
  242.             $model->data[$model->name]['mimetype']$model->data[$model->name][$field]['type'];
  243.             $model->data[$model->name]['filesize'] = $model->data[$model->name][$field]['size'];
  244.             $model->data[$model->name][$field] = $model->data[$model->name][$field]['name'];
  245.  
  246.             //if deleteMainFile = true then delete it and keep only thumbnails
  247.             if($deleteMainFile && file_exists($uploadedFiles[$keyName]['saveas'])) {
  248.                 unlink($uploadedFiles[$keyName]['saveas']);
  249.             }
  250.         }
  251.         //    pr($model->data);
  252.         //    die('beha');
  253.     }
  254.  
  255.     function beforeDelete(&$model) {
  256.         foreach ($this->settings[$model->name] as $keyName => $fileValues) {
  257.             if($keyName == 'defaultSettings') continue;
  258.             extract(am($this->settings[$model->name]['defaultSettings'],$fileValues));
  259.  
  260.             $fileName = $model->findById($model->id,array($model->name.'.'.$field));
  261.             foreach ($thumbsizes as $key => $thumbsize) {
  262.                 $dFile = $this->_getPath($model,$fileValues,$dir).DS.$this->getThumbname($model, $fileValues, $key, $fileName[$model->name][$field]);
  263.                 if(file_exists($dFile) && !is_dir($dFile)) {
  264.                     unlink($dFile);
  265.                 }
  266.             }
  267.             $dFile = $this->_getPath($model,$fileValues,$dir).DS.$fileName[$model->name][$field];
  268.             if(file_exists($dFile) && !is_dir($dFile)) {
  269.                 unlink($dFile);
  270.             }
  271.         }
  272.     }
  273.  
  274.  
  275.  
  276.     // Function to create thumbnail image
  277.  
  278.     function createthumb(&$model, $name, $filename, $new_w, $new_h, $autoResize = true) {
  279.            
  280.         $system = explode(".", $name);
  281.         if (preg_match("/jpg|jpeg/i", $system[1])) {
  282.             $src_img = imagecreatefromjpeg($name);
  283.         }
  284.  
  285.         if (preg_match("/png/i", $system[1])) {
  286.             $src_img = imagecreatefrompng($name);
  287.         }
  288.  
  289.         if (preg_match("/gif/i", $system[1])) {
  290.             $src_img = imagecreatefromgif($name);
  291.         }
  292.  
  293.         $old_x = imagesx($src_img);
  294.  
  295.         $old_y = imagesy($src_img);
  296.  
  297.         $model->data[$model->name]['width'] = $old_x;
  298.  
  299.         $model->data[$model->name]['height'] = $old_y;
  300.  
  301.            
  302.         //    //return false if the thumbnails is greater than image..
  303.         //    if (($old_x < $new_w) || ($old_y < $new_h)) {
  304.         //
  305.         //      return false;
  306.         //
  307.         //    }
  308.  
  309.         //calculate the new dimensions proportionately
  310.  
  311.  
  312.         if($autoResize) {
  313.             if ($old_x >= $old_y) {
  314.                 $thumb_w = $new_w;
  315.                 $ratio = $old_y / $old_x;
  316.                 $thumb_h = $ratio * $new_w;
  317.             } else if ($old_x < $old_y) {
  318.                 $thumb_h = $new_h;
  319.                 $ratio = $old_x / $old_y;
  320.                 $thumb_w = $ratio * $new_h;
  321.             }
  322.         } else {
  323.             $thumb_w = $new_w;
  324.             $thumb_h = $new_h;
  325.         }
  326.            
  327.  
  328.         $dst_img = imagecreatetruecolor($thumb_w, $thumb_h);
  329.  
  330.         imagecopyresampled($dst_img, $src_img, 0, 0, 0, 0, $thumb_w, $thumb_h, $old_x, $old_y);
  331.  
  332.            
  333.  
  334.         if (preg_match("/png/", $system[1])) {
  335.             imagepng($dst_img, $filename);
  336.         }
  337.         elseif(preg_match("/gif/", $system[1])) {
  338.             imagegif($dst_img, $filename);
  339.         }
  340.         else {
  341.             imagejpeg($dst_img, $filename);
  342.         }
  343.         imagedestroy($dst_img);
  344.         imagedestroy($src_img);
  345.     }
  346.  
  347.  
  348.  
  349.     function getThumbname ($model, $fileValues, $thumbsize, $filename, $extension = null) {
  350.  
  351.         if ($extension == null ) {
  352.             $parts = explode('.', low($filename));
  353.             $extension = array_pop($parts);
  354.             $filename = implode('.', $parts);
  355.         }
  356.  
  357.         $mergedSettings = am($this->settings[$model->name]['defaultSettings']['thumbsizes'],$fileValues['thumbsizes']);
  358.         extract($mergedSettings[$thumbsize]);
  359.  
  360.         if (strpos($name, '{') === false) {
  361.             return $name.$filename.'.'.$extension;
  362.         }
  363.  
  364.         $markers = array('{$file}', '{$ext}');
  365.         $replace = array( $filename, $extension);
  366.         return str_replace($markers, $replace, $name);
  367.     }
  368.  
  369.  
  370.  
  371.     function getThumbSizes(&$model, $size = null) {
  372.  
  373.         extract($this->settings[$model->name]);
  374.  
  375.         if ($size) {
  376.             return $thumbsizes[$size];
  377.         }
  378.  
  379.         return $thumbsizes;
  380.     }
  381.  
  382.     function initDir(&$model, $dirToCheck = null) {
  383.  
  384.         extract($this->settings[$model->name]);
  385.  
  386.         if ($dirToCheck) {
  387.  
  388.             $dir = $dirToCheck;
  389.  
  390.         }
  391.  
  392.         // Check if directory exists and create it if required
  393.  
  394.         if(!is_dir($dir)) {
  395.  
  396.             if($create_directory && !$this->Folder->mkdirr($dir)) {
  397.  
  398.                 unset($config[$field]);
  399.  
  400.                 unset($model->data[$model->name][$field]);
  401.  
  402.             }
  403.  
  404.         }
  405.  
  406.         // Check if directory is writable
  407.  
  408.         if(!is_writable($settings['dir'])) {
  409.  
  410.             unset($config[$field]);
  411.  
  412.             unset($model->data[$model->name][$field]);
  413.  
  414.         }
  415.  
  416.         // Check that the given directory does not have a DS on the end
  417.  
  418.         if($settings['dir'][strlen($settings['dir'])-1] == DS) {
  419.  
  420.             $settings['dir'] = substr($settings['dir'],0,strlen($settings['dir'])-2);
  421.  
  422.         }
  423.  
  424.     }
  425.  
  426.  
  427.     /**
  428.      * return the cleaned filename (without the file extension)
  429.      *
  430.      * @param object $model
  431.      * @param array $fileValues
  432.      * @param string $string
  433.      * @return string
  434.      */
  435.     function _getFilename($model, $fileValues, $string) {
  436.  
  437.         extract(am($this->settings[$model->name]['defaultSettings'],$fileValues));
  438.  
  439.         if ($randomFilenames) {
  440.             return uniqid("");
  441.         }
  442.  
  443.         $string = htmlentities(low($string), null, 'UTF-8');
  444.  
  445.         foreach ($nameCleanups as $regex => $replace) {
  446.             if ($regex == 'decode') {
  447.                 $string = html_entity_decode($string);
  448.             }
  449.             else {
  450.                 $string = preg_replace($regex, $replace, $string);
  451.             }
  452.         }
  453.         return $string;
  454.     }
  455.  
  456.  
  457.     /**
  458.      * return the absolute file path
  459.      *
  460.      * @param object $model
  461.      * @param array $fileValues
  462.      * @param string $path
  463.      * @return string
  464.      */
  465.     function _getPath ($model, $fileValues, $path) {
  466.  
  467.         extract(am($this->settings[$model->name]['defaultSettings'],$fileValues));
  468.  
  469.         if (strpos($path,'{') === false) {
  470.             return $path;
  471.         }
  472.  
  473.         $markers = array('{APP}', '{DS}', '{IMAGES}', '{WWW_ROOT}', '{FILES}');
  474.  
  475.         $replace = array( APP, DS, IMAGES, WWW_ROOT, WWW_ROOT.'files'.DS );
  476.  
  477.         $folderPath = str_replace ($markers, $replace, $path);
  478.  
  479.         new Folder ($folderPath, true);
  480.  
  481.         return $folderPath;
  482.  
  483.     }
  484.    
  485.     //validation function
  486.    
  487.     /**
  488.      * Validate an uploaded file
  489.      *
  490.      * @return boolean
  491.      */
  492.     function validateUploadedFile($model) {
  493.         $eachArray = null;
  494.         $upload_info = ($model->data[$model->name]);       
  495.         $eachArray = each($model->validate);   
  496.         reset($model->validate);           
  497.         $field = $eachArray[0];  
  498.                
  499.         $eachArray = each($model->validate);   
  500.         reset($model->validate);
  501.        
  502.         $upload_info = $upload_info[$field];
  503.         if(!is_array($upload_info)) return true;
  504.         if ($upload_info['error'] == 4) {
  505.             return true;
  506.         }
  507.         if ($upload_info['error'] !== 0) {
  508.             return false;
  509.         }
  510.         return is_uploaded_file($upload_info['tmp_name']);
  511.     }
  512.    
  513.     /**
  514.      * Check the file extension of an uploaded file
  515.      *
  516.      * @param unknown_type $data
  517.      * @param unknown_type $extensions
  518.      * @return unknown
  519.      */
  520.     function validateFileExtension($model, $data, $extensions) {
  521.         $eachArray = null;
  522.         $upload_info = ($model->data[$model->name]);
  523.                
  524.         $eachArray = each($model->validate);   
  525.         reset($model->validate);
  526.        
  527.         $field = $eachArray[0];  
  528.         $upload_info = $upload_info[$field];
  529.        
  530.        
  531.         if(!is_array($upload_info))  { return true; }
  532.         if($upload_info['error']==4) { return true; }   
  533.         $filename = low($upload_info['name']);
  534.         $parts = explode('.', $filename);
  535.         $ext = array_pop($parts);
  536.         return in_array($ext, $extensions);
  537.     }
  538.    
  539.     /**
  540.      * Check the file size of an uploaded file
  541.      *
  542.      * @param unknown_type $data
  543.      * @param unknown_type $extensions
  544.      * @return unknown
  545.      */
  546.     function maxFileSize($model, $data, $fileSize) {
  547.         $upload_info = ($model->data[$model->name]);       
  548.         $eachArray = each($model->validate);   
  549.         reset($model->validate);       
  550.         $field =$eachArray[0];   
  551.         $upload_info = $upload_info[$field];
  552.        
  553.         if ($upload_info['size'] > $fileSize) {
  554.             return false;
  555.         } else {
  556.             return true;
  557.         }      
  558.     }
  559.    
  560. /**
  561.      * Validate an uploaded file
  562.      *
  563.      * @return boolean
  564.      */
  565.     function requiredFile($model, $required = true) {
  566.         $eachArray = null;
  567.         $upload_info = ($model->data[$model->name]);       
  568.         $eachArray = each($model->validate);   
  569.         reset($model->validate);           
  570.         $field = $eachArray[0];  
  571.                
  572.         $eachArray = each($model->validate);   
  573.         reset($model->validate);
  574.        
  575.         $upload_info = $upload_info[$field];
  576.         if(!is_array($upload_info) && $required) return false;
  577.         if ($upload_info['error'] == 4 && $required) {
  578.             return false;
  579.         }
  580.         if ($upload_info['error'] !== 0) {
  581.             return false;
  582.         }
  583.         if ($upload_info['size'] == 0) {
  584.             return false;
  585.         }
  586.         return true;
  587.     }
  588.  
  589. }
  590.  
  591. ?>
  592.  
  593. <?php
  594. //example
  595. class Company extends AppModel {
  596.  
  597.     var $name = 'Company';
  598.     var $actsAs = array('MultipleUpload' =>
  599.                             array(
  600.                                 'photo' => array(
  601.                                     'field' => 'photo',
  602.                                     'dir' => "{IMAGES}company",
  603.                                     'deleteMainFile' => true,
  604.                                     'thumbsizes' => array(                   
  605.                                         'main' => array('width' => 350, 'height' => 350, 'name' => 'main.{$file}.{$ext}', 'autoResize' => true)                    
  606.                                     )
  607.                                 )
  608.                             )
  609.                         );
  610.     var $validate = array(
  611.         'photo' => array (
  612.             'valid_upload' => array (
  613.                 'rule' => array('validateUploadedFile'),
  614.                 'message' => 'File non valido',
  615.                 'required' => true     
  616.             ),
  617.             'validFile' => array (
  618.                 'rule' => array('validateFileExtension', array('gif', 'jpg', 'jpeg', 'png')),
  619.                 'message' => 'File non valido, inserire solo file jpg/jpeg, gif o png'
  620.             ),
  621.             'maxFileSize' => array(
  622.                 'rule' => array('maxFileSize', 2097152),
  623.                 'message' => 'File non valido, inserire file di dimensioni inferiori ai 2 MegaByte'
  624.             )
  625.         )
  626.  
  627. }
  628. ?>
  629.  
  630.  
  631.  
  632.  
  633.  
Parsed in 0.923 seconds, using GeSHi 1.0.7.14

Modify this Paste