<commit_before><?php
/**
 * This file is a part of UploadPack - a plugin that makes file uploads in CakePHP as easy as possible. 
 * 
 * UploadBehavior
 * 
 * UploadBehavior does all the job of saving files to disk while saving records to database. For more info read UploadPack documentation.
 *
 * joe bartlett's lovingly handcrafted tweaks add several resize modes. see "more on styles" in the documentation.
 *
 * @author <NAME> (<EMAIL>) and <NAME> (<EMAIL>)
 * @link http://github.com/szajbus/uploadpack
 */
class UploadBehavior extends ModelBehavior {
  
  static $__settings = array();
  
  var $toWrite = array();
  
  var $toDelete = array();
  
  function setup(&$model, $settings = array()) {
    $defaults = array(
      'path' => ':webroot/upload/:model/:id/:basename_:style.:extension',
      'styles' => array()
    );
    
    foreach ($settings as $field => $array) {
      self::$__settings[$model->name][$field] = array_merge($defaults, $array);
    }
  }
  
  function beforeSave(&$model) {
    $this->_reset();
    foreach (self::$__settings[$model->name] as $field => $settings) {
      if (!empty($model->data[$model->name][$field]) && is_array($model->data[$model->name][$field]) && file_exists($model->data[$model->name][$field]['tmp_name'])) {
        if (!empty($model->id)) {
          $this->_prepareToDeleteFiles($model, $field, true);
        }
        $this->_prepareToWriteFiles($model, $field);
        unset($model->data[$model->name][$field]);
        $model->data[$model->name][$field.'_file_name'] = $this->toWrite[$field]['name'];
        $model->data[$model->name][$field.'_file_size'] = $this->toWrite[$field]['size'];
        $model->data[$model->name][$field.'_content_type'] = $this->toWrite[$field]['type'];
      }
    }
    return true;
  }
  
  function afterSave(&$model, $create) {
    if (!$create) {
      $this->_deleteFiles($model);
    }
    $this->_writeFiles($model);
  }
  
  function beforeDelete(&$model) {
    $this->_reset();
    $this->_prepareToDeleteFiles($model);
    return true;
  }
  
  function afterDelete(&$model) {
    $this->_deleteFiles($model);
  }
  
  function _reset() {
    $this->_toWrite = null;
    $this->_toDelete = null;
  }
  
  function _prepareToWriteFiles(&$model, $field) {
    $this->toWrite[$field] = $model->data[$model->name][$field];
  }
  
  function _writeFiles(&$model) {
    if (!empty($this->toWrite)) {
      foreach ($this->toWrite as $field => $toWrite) {
        $settings = $this->_interpolate($model, $field, $toWrite['name'], 'original');
        $destDir = dirname($settings['path']);
        if (!file_exists($destDir)) {
          @mkdir($destDir, 0777, true);
          @chmod($destDir, 0777);
        }
        if (is_dir($destDir) && is_writable($destDir)) {
          if (@move_uploaded_file($toWrite['tmp_name'], $settings['path'])) {
            foreach ($settings['styles'] as $style => $geometry) {
              $newSettings = $this->_interpolate($model, $field, $toWrite['name'], $style);
              $this->_resize($settings['path'], $newSettings['path'], $geometry);
            }
          }
        }
      }
    }
  }
  
  function _prepareToDeleteFiles(&$model, $field = null, $forceRead = false) {
    $needToRead = true;
    if ($field === null) {
      $fields = array_keys(self::$__settings[$model->name]);
      foreach ($fields as &$field) {
        $field .= '_file_name';
      }
    } else {
      $field .= '_file_name';
      $fields = array($field);
    }
    
    if (!$forceRead && !empty($model->data[$model->alias])) {
      $needToRead = false;
      foreach ($fields as $field) {
        if (!array_key_exists($field, $model->data[$model->alias])) {
          $needToRead = true;
          break;
        }
      }
    }
    if ($needToRead) {
      $data = $model->find('first', array('conditions' => array($model->alias.'.'.$model->primaryKey => $model->id), 'fields' => $fields, 'callbacks' => false));
    } else {
      $data = $model->data;
    }
    if (is_array($this->toDelete)) {
      $this->toDelete = array_merge($this->toDelete, $data[$model->alias]);
    } else {
      $this->toDelete = $data[$model->alias];
    }
    $this->toDelete['id'] = $model->id;
  }
  
  function _deleteFiles(&$model) {
    foreach (self::$__settings[$model->name] as $field => $settings) {
      if (!empty($this->toDelete[$field.'_file_name'])) {
        $styles = array_keys($settings['styles']);
        $styles[] = 'original';
        foreach ($styles as $style) {
          $settings = $this->_interpolate($model, $field, $this->toDelete[$field.'_file_name'], $style);
          if (file_exists($settings['path'])) {
            @unlink($settings['path']);
          }
        }
      }
    }
  }
  
  function _interpolate(&$model, $field, $filename, $style) {
    return self::interpolate($model->name, $model->id, $field, $filename, $style);
  }
  
  static function interpolate($modelName, $modelId, $field, $filename, $style = 'original', $defaults = array()) {
    $pathinfo = pathinfo($filename);
    $interpolations = array_merge(array(
      'app' => preg_replace('/\/$/', '', APP),
      'webroot' => preg_replace('/\/$/', '', WWW_ROOT),
      'model' => Inflector::tableize($modelName),
      'basename' => !empty($filename) ? $pathinfo['filename'] : null,
      'extension' => !empty($filename) ? $pathinfo['extension'] : null,
      'id' => $modelId,
      'style' => $style,
      'attachment' => Inflector::pluralize($field)
    ), $defaults);
    $settings = self::$__settings[$modelName][$field];
    $keys = array('path', 'url', 'default_url');
    foreach ($interpolations as $k => $v) {
      foreach ($keys as $key) {
        if (isset($settings[$key])) {
          $settings[$key] = preg_replace('/\/{2,}/', '/', str_replace(":$k", $v, $settings[$key]));
        }
      }
    }
    return $settings;
  }
  
  function _resize($srcFile, $destFile, $geometry) {
    copy($srcFile, $destFile);
    $pathinfo = pathinfo($srcFile);
    $src = null;
    $createHandler = null;
    $outputHandler = null;
    switch (low($pathinfo['extension'])) {
      case 'gif':
        $createHandler = 'imagecreatefromgif';
        $outputHandler = 'imagegif';
        break;
      case 'jpg':
      case 'jpeg':<commit_msg>Added support for pathinfo() in PHP < 5.2.0.<commit_after><?php
/**
 * This file is a part of UploadPack - a plugin that makes file uploads in CakePHP as easy as possible. 
 * 
 * UploadBehavior
 * 
 * UploadBehavior does all the job of saving files to disk while saving records to database. For more info read UploadPack documentation.
 *
 * joe bartlett's lovingly handcrafted tweaks add several resize modes. see "more on styles" in the documentation.
 *
 * @author <NAME> (<EMAIL>) and joe bartlett (<EMAIL>)
 * @link http://github.com/szajbus/uploadpack
 */
class UploadBehavior extends ModelBehavior {
  
  static $__settings = array();
  
  var $toWrite = array();
  
  var $toDelete = array();
  
  function setup(&$model, $settings = array()) {
    $defaults = array(
      'path' => ':webroot/upload/:model/:id/:basename_:style.:extension',
      'styles' => array()
    );
    
    foreach ($settings as $field => $array) {
      self::$__settings[$model->name][$field] = array_merge($defaults, $array);
    }
  }
  
  function beforeSave(&$model) {
    $this->_reset();
    foreach (self::$__settings[$model->name] as $field => $settings) {
      if (!empty($model->data[$model->name][$field]) && is_array($model->data[$model->name][$field]) && file_exists($model->data[$model->name][$field]['tmp_name'])) {
        if (!empty($model->id)) {
          $this->_prepareToDeleteFiles($model, $field, true);
        }
        $this->_prepareToWriteFiles($model, $field);
        unset($model->data[$model->name][$field]);
        $model->data[$model->name][$field.'_file_name'] = $this->toWrite[$field]['name'];
        $model->data[$model->name][$field.'_file_size'] = $this->toWrite[$field]['size'];
        $model->data[$model->name][$field.'_content_type'] = $this->toWrite[$field]['type'];
      }
    }
    return true;
  }
  
  function afterSave(&$model, $create) {
    if (!$create) {
      $this->_deleteFiles($model);
    }
    $this->_writeFiles($model);
  }
  
  function beforeDelete(&$model) {
    $this->_reset();
    $this->_prepareToDeleteFiles($model);
    return true;
  }
  
  function afterDelete(&$model) {
    $this->_deleteFiles($model);
  }
  
  function _reset() {
    $this->_toWrite = null;
    $this->_toDelete = null;
  }
  
  function _prepareToWriteFiles(&$model, $field) {
    $this->toWrite[$field] = $model->data[$model->name][$field];
  }
  
  function _writeFiles(&$model) {
    if (!empty($this->toWrite)) {
      foreach ($this->toWrite as $field => $toWrite) {
        $settings = $this->_interpolate($model, $field, $toWrite['name'], 'original');
        $destDir = dirname($settings['path']);
        if (!file_exists($destDir)) {
          @mkdir($destDir, 0777, true);
          @chmod($destDir, 0777);
        }
        if (is_dir($destDir) && is_writable($destDir)) {
          if (@move_uploaded_file($toWrite['tmp_name'], $settings['path'])) {
            foreach ($settings['styles'] as $style => $geometry) {
              $newSettings = $this->_interpolate($model, $field, $toWrite['name'], $style);
              $this->_resize($settings['path'], $newSettings['path'], $geometry);
            }
          }
        }
      }
    }
  }
  
  function _prepareToDeleteFiles(&$model, $field = null, $forceRead = false) {
    $needToRead = true;
    if ($field === null) {
      $fields = array_keys(self::$__settings[$model->name]);
      foreach ($fields as &$field) {
        $field .= '_file_name';
      }
    } else {
      $field .= '_file_name';
      $fields = array($field);
    }
    
    if (!$forceRead && !empty($model->data[$model->alias])) {
      $needToRead = false;
      foreach ($fields as $field) {
        if (!array_key_exists($field, $model->data[$model->alias])) {
          $needToRead = true;
          break;
        }
      }
    }
    if ($needToRead) {
      $data = $model->find('first', array('conditions' => array($model->alias.'.'.$model->primaryKey => $model->id), 'fields' => $fields, 'callbacks' => false));
    } else {
      $data = $model->data;
    }
    if (is_array($this->toDelete)) {
      $this->toDelete = array_merge($this->toDelete, $data[$model->alias]);
    } else {
      $this->toDelete = $data[$model->alias];
    }
    $this->toDelete['id'] = $model->id;
  }
  
  function _deleteFiles(&$model) {
    foreach (self::$__settings[$model->name] as $field => $settings) {
      if (!empty($this->toDelete[$field.'_file_name'])) {
        $styles = array_keys($settings['styles']);
        $styles[] = 'original';
        foreach ($styles as $style) {
          $settings = $this->_interpolate($model, $field, $this->toDelete[$field.'_file_name'], $style);
          if (file_exists($settings['path'])) {
            @unlink($settings['path']);
          }
        }
      }
    }
  }
  
  function _interpolate(&$model, $field, $filename, $style) {
    return self::interpolate($model->name, $model->id, $field, $filename, $style);
  }
  
  static function interpolate($modelName, $modelId, $field, $filename, $style = 'original', $defaults = array()) {
    $pathinfo = UploadBehavior::_pathinfo($filename);
    $interpolations = array_merge(array(
      'app' => preg_replace('/\/$/', '', APP),
      'webroot' => preg_replace('/\/$/', '', WWW_ROOT),
      'model' => Inflector::tableize($modelName),
      'basename' => !empty($filename) ? $pathinfo['filename'] : null,
      'extension' => !empty($filename) ? $pathinfo['extension'] : null,
      'id' => $modelId,
      'style' => $style,
      'attachment' => Inflector::pluralize($field)
    ), $defaults);
    $settings = self::$__settings[$modelName][$field];
    $keys = array('path', 'url', 'default_url');
    foreach ($interpolations as $k => $v) {
      foreach ($keys as $key) {
        if (isset($settings[$key])) {
          $settings[$key] = preg_replace('/\/{2,}/', '/', str_replace(":$k", $v, $settings[$key]));
        }
      }
    }
    return $settings;
  }

  static function _pathinfo($filename) {
    $pathinfo = pathinfo($filename);
    // PHP < 5.2.0 doesn't include 'filename' key in pathinfo. Let's try to fix this.
    if (empty($pathinfo['filename'])) {
      $suffix = !empty($pathinfo['extension']) ? '.'.$pathinfo['extension'] : '';
      $pathinfo['filename'] = basename($pathinfo['basename'], $suffix);
    }
    return $pathinfo;
  }

  function _resize($srcFile, $destFile, $geometry) {
    copy($srcFile, $destFile);
    $pathinfo = UploadBehavior::_pathinfo($srcFile);
    $src = null;
    $createHandler = null;
    $outputHandler = null;
    switch (low($pathinfo['extension'])) {
      case 'gif':
        $createHandler = 'imagecreatefromgif';
        $outputHandler = 'imagegif';
        break;
      case 'jpg':
      case 'jpeg':
{'fraction_non_alphanumeric': 0.19574239163848756, 'fraction_numerical': 0.0018444512757454657, 'mean_word_length': 3.022565687789799, 'pattern_counts': {'":': 2, '<': 14, '<?xml version=': 0, '>': 174, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4998118', 'n_tokens_mistral': 4160, 'n_tokens_neox': 4138, 'n_words': 796}