Files
crm-ms1/lib/common/File.php
2026-05-27 11:44:10 -04:00

443 lines
14 KiB
PHP

<?php
namespace Common;
class File {
public $_exif = null;
private $_mime_types = array(
'.txt' => 'text/plain',
'.htm' => 'text/html',
'.html' => 'text/html',
'.php' => 'text/html',
'.css' => 'text/css',
'.js' => 'application/javascript',
'.json' => 'application/json',
'.xml' => 'application/xml',
'.swf' => 'application/x-shockwave-flash',
'.flv' => 'video/x-flv',
// images
'.png' => 'image/png',
'.jpe' => 'image/jpeg',
'.jpeg' => 'image/jpeg',
'.jpg' => 'image/jpeg',
'.gif' => 'image/gif',
'.bmp' => 'image/bmp',
'.ico' => 'image/vnd.microsoft.icon',
'.tiff' => 'image/tiff',
'.tif' => 'image/tiff',
'.svg' => 'image/svg+xml',
'.svgz' => 'image/svg+xml',
// archives
'.zip' => 'application/zip',
'.rar' => 'application/x-rar-compressed',
'.exe' => 'application/x-msdownload',
'.msi' => 'application/x-msdownload',
'.cab' => 'application/vnd.ms-cab-compressed',
// audio/video
'.mp3' => 'audio/mpeg',
'.qt' => 'video/quicktime',
'.mov' => 'video/quicktime',
'.wmv' => 'video/x-ms-wmv',
'.mp4' => 'video/mp4',
'.mp4a' => 'audio/mp4',
'.mpeg' => 'video/mpeg',
// adobe
'.pdf' => 'application/pdf',
'.psd' => 'image/vnd.adobe.photoshop',
'.ai' => 'application/postscript',
'.eps' => 'application/postscript',
'.ps' => 'application/postscript',
'.tiff' => 'image/tiff',
// ms office
'.doc' => 'application/msword',
'.rtf' => 'application/rtf',
'.xls' => 'application/vnd.ms-excel',
'.xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
'.docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
'.ppt' => 'application/vnd.ms-powerpoint',
// open office
'.odt' => 'application/vnd.oasis.opendocument.text',
'.ods' => 'application/vnd.oasis.opendocument.spreadsheet',
);
/**
* default structure of the validations array
* @var array
*/
private $_validations = array(
'extension' => array(),
'category' => array(),
'size' => 200,
'custom' => null
);
private $_default_properties = array(
'name' => '',
'tmp_name' => '',
'size' => 0,
'error' => UPLOAD_ERR_OK,
'extension' => ''
);
// custom filtered errors
const UPLOAD_ERR_EXTENSION_FILTER = 100;
const UPLOAD_ERR_CATEGORY_FILTER = 101;
const UPLOAD_ERR_SIZE_FILTER = 102;
/**
* errors container array
* @var array
*/
private $_errors = array();
/**
* error messages container array
* @var array
*/
private $_error_messages = array(
UPLOAD_ERR_OK => "There is no error, the file uploaded with success.",
UPLOAD_ERR_INI_SIZE => "The uploaded file exceeds the upload_max_filesize directive in php.ini.",
UPLOAD_ERR_FORM_SIZE => "The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form.",
UPLOAD_ERR_PARTIAL => "The uploaded file was only partially uploaded.",
UPLOAD_ERR_NO_FILE => "No file was uploaded.",
UPLOAD_ERR_NO_TMP_DIR => "Missing a temporary folder. Introduced in PHP 4.3.10 and PHP 5.0.3.",
UPLOAD_ERR_CANT_WRITE => "Failed to write file to disk. Introduced in PHP 5.1.0.",
UPLOAD_ERR_EXTENSION => "A PHP extension stopped the file upload. PHP does not provide a way to ascertain which extension caused the file upload to stop;examining the list of loaded extensions with phpinfo() may help. Introduced in PHP 5.2.0.",
self::UPLOAD_ERR_EXTENSION_FILTER => "File type not allowed",
self::UPLOAD_ERR_CATEGORY_FILTER => "File not allowed",
self::UPLOAD_ERR_SIZE_FILTER => "File size not allowed"
);
/**
* initialize the File class
* @param array $properties file data
* @param array $validations validation array
*/
public function __construct($properties, $validations = array()) {
$this->_validations = self::_set_array_defaults($this->_validations, $validations);
$this->_default_properties = self::_set_array_defaults($this->_default_properties, $properties);
// set this instance's properties from the provided data
foreach ($this->_default_properties as $key => $value) {
$this->{$key} = $value;
}
// get the file info and add them as this instance's properties
$info = $this->get_info();
foreach ($info as $key => $info) {
$this->{$key} = $info;
}
// see if Exif class exists and if it's an image file
if (class_exists('Exif') && $this->tmp_name) {
switch ($this->extension) {
case '.jpg':
case '.jpeg':
case '.tiff':
$this->_exif = new Exif($this->tmp_name);
break;
}
}
}
/**
* set the default values to an input array
* @param array $default_structure the default structure of the array
* @param array $array_value the input value
* @param string $set_to_key_if_fail set to a default key if failed to set appropriate value
*/
private static function _set_array_defaults($default_structure, $array_value, $set_to_key_if_fail = "") {
if ($set_to_key_if_fail != "") {
if (!is_array($array_value) || !isset($array_value[$set_to_key_if_fail])) {
if (isset($default_structure[$set_to_key_if_fail]))
$default_structure[$set_to_key_if_fail] = $array_value;
return $default_structure;
}
}
foreach ($array_value as $key => $value) {
$default_structure[$key] = $value;
}
return $default_structure;
}
/**
* put the tmp_name somewhere
* @param string $dest_path the destination path
* @param string $filename the filename, leave blank to use the upload's name
* @return boolean true if success, otherwise false
*/
public function put($dest_path, $filename = '') {
if (is_dir($dest_path)) {
if (!$filename) $filename = $this->name;
return move_uploaded_file($this->tmp_name, $dest_path.'/'.$filename);
} return false;
}
/**
* get error messages
* @param boolean $return_str should it return an string or array
* @return string/array returns the error string or errors array
*/
public function get_error($return_str = true) {
$messages = $this->_error_messages;
$errors = array_map(function($error) use ($messages) {
if (isset($messages[$error])) return $messages[$error];
else return is_int($error) ? 'Unknown File Error' : $error;
}, $this->_errors);
return $return_str ? implode('; ', $errors) : $errors;
}
/**
* set the error message of the error type
* @param int $error_num error type
* @param string $message error message
*/
public function set_error_message($error_num, $message = '') {
$this->_error_messages[$error_num] = $message;
}
/**
* validate the file
* @return boolean true if valid, otherwise false
*/
public function validate() {
if ($this->error !== UPLOAD_ERR_OK) {
$this->_errors[] = $this->error;
}
// filter size
$def_size_filter = array(
'max' => 200, // 200 MB
'min' => 0,
'unit' => 'MB',
'message' => '[size (kb): '.$this->size.'] '.$this->_error_messages[self::UPLOAD_ERR_SIZE_FILTER]
);
$size_filter = self::_set_array_defaults($def_size_filter, $this->_validations['size'], 'max');
$this->set_error_message(self::UPLOAD_ERR_SIZE_FILTER, $size_filter['message']);
$get_actual_size = function($size, $unit) {
switch (strtolower($unit)) {
case 'mb':
$size = $size * 1048576;
break;
case 'kb':
$size = $size * 1024;
case 'gb':
$size = $size * 1073741824;
}
return $size;
};
$max_actual_size = $get_actual_size($size_filter['max'], $size_filter['unit']);
$min_actual_size = $get_actual_size($size_filter['min'], $size_filter['unit']);
if ($this->size > $max_actual_size || $this->size < $min_actual_size)
$this->_errors[] = self::UPLOAD_ERR_SIZE_FILTER;
// filter extension
if ($this->_validations['extension']) {
$def_ext_filter = array(
'is' => array(),
'not' => array(),
'message' => '[extension: '.$this->extension.'] '.$this->_error_messages[self::UPLOAD_ERR_EXTENSION_FILTER]
);
$ext_filter = self::_set_array_defaults($def_ext_filter, $this->_validations['extension'], 'is');
$this->set_error_message(self::UPLOAD_ERR_EXTENSION_FILTER, $ext_filter['message']);
if (!is_array($ext_filter['is'])) $ext_filter['is'] = array($ext_filter['is']);
if (!is_array($ext_filter['not'])) $ext_filter['not'] = array($ext_filter['not']);
if (!in_array($this->extension, $ext_filter['is']) || in_array($this->extension, $ext_filter['not']))
$this->_errors[] = self::UPLOAD_ERR_EXTENSION_FILTER;
}
// filter category
if ($this->_validations['category']) {
$def_cat_filter = array(
'is' => array(),
'not' => array(),
'message' => '[category: '.$this->category.'] '.$this->_error_messages[self::UPLOAD_ERR_CATEGORY_FILTER]
);
$cat_filter = self::_set_array_defaults($def_cat_filter, $this->_validations['category'], 'is');
$this->set_error_message(self::UPLOAD_ERR_CATEGORY_FILTER, $cat_filter['message']);
if (!is_array($cat_filter['is'])) $cat_filter['is'] = array($cat_filter['is']);
if (!is_array($cat_filter['not'])) $cat_filter['not'] = array($cat_filter['not']);
if (!in_array($this->category, $cat_filter['is']) || in_array($this->category, $cat_filter['not']))
$this->_errors[] = self::UPLOAD_ERR_CATEGORY_FILTER;
}
if ($this->_validations['custom']) {
$custom_validations = is_array($this->_validations['custom']) ? $this->_validations['custom'] : array($this->_validations['custom']);
foreach ($custom_validations as $validation) {
$result = $this->_validations['custom']($this);
if ($result != '' && $result !== true && $result !== null) {
$this->_errors[] = $result;
}
}
}
return !$this->_errors;
}
/**
* get the exif GPS data (if the file is an image)
* @return array array of lat/lng if success, otherwise false
*/
public function get_exif_gps() {
return $this->_exif ? $this->_exif->get_gps() : false;
}
/**
* get the exif data (if the file is an image)
* @return array array of exif info if success, otherwise false
*/
public function get_exif() {
return $this->_exif ? $this->_exif->get_data() : false;
}
/**
* is category
* @param string $category test if the file is this category
* @return boolean true if it is, otherwise false
*/
public function is($category) {
return $category == $this->category;
}
/**
* get the file info evaluated from the $name property
* @return stdClass file info
*/
public function get_info($icon_prefix = 'octicon') {
preg_match('/\.[^\.]+$/i', $this->name, $ext);
preg_match('/\.\w+/i', isset($ext[0]) ? $ext[0] : '', $ext);
$return = new \stdClass;
$extension = isset($ext[0]) ? $ext[0] : '';
$category = "";
switch (strtolower($extension)) {
case '.pdf':
case '.doc':
case '.rtf':
case '.txt':
case '.docx':
case '.xls':
case '.xlsx':
$category = 'document';
break;
case '.png':
case '.jpg':
case '.jpeg':
case '.gif':
case '.bmp':
case '.psd':
case '.tif':
case '.tiff':
$category = 'image';
break;
case '.mp3':
case '.wav':
case '.wma':
case '.m4a':
case '.m3u':
$category = 'audio';
break;
case '.3g2':
case '.3gp':
case '.asf':
case '.asx':
case '.avi':
case '.flv':
case '.m4v':
case '.mov':
case '.mp4':
case '.mpg':
case '.srt':
case '.swf':
case '.vob':
case '.wmv':
$category = 'video';
break;
case '.css':
case '.php':
case '.php3':
case '.sql':
case '.cs':
case '.html':
case '.less':
case '.xml':
$category = 'code';
break;
case '.zip':
case '.gzip':
case '.7z':
case '.tar':
case '.rar':
$category = 'compressed';
break;
default:
$category = 'other';
break;
}
$return->extension = $extension;
$return->category = $category;
$return->type = isset($this->_mime_types[$extension]) ? $this->_mime_types[$extension] : 'application/octet-stream';
return $return;
}
public function get_mime_type() {
return mime_content_type($this->tmp_name);
}
/**
* get base64_encode of the file
* @return string base64 encoded string
*/
public function get_base64() {
return base64_encode(file_get_contents($this->tmp_name));
}
/**
* format the size of the file to a readable string
* @return string formatted file size
*/
public function format_size() {
$bytes = $this->size;
if ($bytes >= 1073741824) {
$format = number_format($bytes / 1073741824, 2) . ' GB';
} elseif ($bytes >= 1048576) {
$format = number_format($bytes / 1048576, 2) . ' MB';
} elseif ($bytes >= 1024) {
$format = number_format($bytes / 1024, 2) . ' KB';
} elseif ($bytes > 1) {
$format = $bytes . ' bytes';
} elseif ($bytes == 1) {
$format = $bytes . ' byte';
} else {
$format = '0 bytes';
}
return $format;
}
}
?>