Index: kernel/constants.php =================================================================== --- kernel/constants.php (revision 14860) +++ kernel/constants.php (working copy) @@ -183,4 +183,15 @@ class PromoBlockType { const INTERNAL = 1; const EXTERNAL = 2; - } \ No newline at end of file + } + + // storage engines + define('STORAGE_ENGINE_NONE', ''); + define('STORAGE_ENGINE_HASH', 'HASH'); + define('STORAGE_ENGINE_TIMESTAMP', 'TIMESTAMP'); + + // prefixes/suffixes + define('PREFIX_SUFFIX_NONE', ''); + define('PREFIX_SUFFIX_DATE_TIME', 'DATE-TIME'); + define('PREFIX_SUFFIX_PREFIX', 'PREFIX'); + define('PREFIX_SUFFIX_USER', 'USER'); \ No newline at end of file Index: kernel/globals.php =================================================================== --- kernel/globals.php (revision 14860) +++ kernel/globals.php (working copy) @@ -660,6 +660,26 @@ return $default; } + + /** + * Generate subpath from hashed value + * + * @param string $name + * @param int $levels + * @return string + */ + public static function getHashPathForLevel( $name, $levels = 2 ) { + if ( $levels == 0 ) { + return ''; + } else { + $hash = md5( $name ); + $path = ''; + for ( $i = 0; $i < $levels; $i++ ) { + $path .= substr( $hash, $i, 1 ) . '/'; + } + return $path; + } + } } /** Index: kernel/utility/formatters/upload_formatter.php =================================================================== --- kernel/utility/formatters/upload_formatter.php (revision 14860) +++ kernel/utility/formatters/upload_formatter.php (working copy) @@ -101,15 +101,19 @@ } for ($i=0; $ifileHelper->ensureUniqueFilename($this->FullPath, $real_name, $files2delete); - $file_name = $this->FullPath.$real_name; + $real_name = $this->getFormattedFileName($swf_uploaded_names[$i], $options, $object->Prefix); + + $storage_engine_subpath = $this->getStoragEngineSubpath($real_name, $options); + + $real_name = $this->fileHelper->ensureUniqueFilename($this->FullPath.$storage_engine_subpath, $real_name, $files2delete); + $file_name = $this->FullPath.$storage_engine_subpath.$real_name; + $tmp_file = WRITEABLE . '/tmp/' . $swf_uploaded_ids[$i].'_'.$swf_uploaded_names[$i]; rename($tmp_file, $file_name); @chmod($file_name, 0666); - $fret[] = getArrayValue($options, 'upload_dir') ? $real_name : $this->DestinationPath.$real_name; + $fret[] = getArrayValue($options, 'upload_dir') ? $storage_engine_subpath.$real_name : $this->DestinationPath.$storage_engine_subpath.$real_name; } $fret = array_merge($existing, $fret); return implode('|', $fret); @@ -154,9 +158,12 @@ $object->SetError($field_name, 'cant_save_file', 'la_error_cant_save_file'); } else { - $real_name = $this->fileHelper->ensureUniqueFilename($this->FullPath, $value['name']); + $real_name = $this->getFormattedFileName($value['name'], $options, $object->Prefix); + $real_name = $this->fileHelper->ensureUniqueFilename($this->FullPath, $real_name); - $file_name = $this->FullPath . $real_name; + $storage_engine_subpath = $this->getStoragEngineSubpath($real_name, $options); + + $file_name = $this->FullPath . $storage_engine_subpath . $real_name; if ( !move_uploaded_file($value['tmp_name'], $file_name) ) { $object->SetError($field_name, 'cant_save_file', 'la_error_cant_save_file'); } @@ -175,7 +182,7 @@ $object->SetDBField($options['content_type_field'], $value['type']); } - $ret = getArrayValue($options, 'upload_dir') ? $real_name : $this->DestinationPath . $real_name; + $ret = getArrayValue($options, 'upload_dir') ? $storage_engine_subpath. $real_name : $this->DestinationPath . $storage_engine_subpath . $real_name; // delete previous file, when new file is uploaded under same field /*$previous_file = isset($value['upload']) ? $value['upload'] : false; @@ -348,6 +355,80 @@ return sprintf($format, $value); } + + /** + * Subpath for uploaded file + * + * @param string $file_name + * @param array $options + * @return string + */ + private function getStoragEngineSubpath($file_name, $options) + { + switch ( getArrayValue($options, 'storage_engine') ) { + case STORAGE_ENGINE_HASH: + $storage_engine_subpath = kUtil::getHashPathForLevel($file_name); + break; + case STORAGE_ENGINE_TIMESTAMP: + $storage_engine_subpath = adodb_date('Ym/d/'); + break; + default: + $storage_engine_subpath = ''; + } + + if ($storage_engine_subpath) { + $this->fileHelper->CheckFolder($this->FullPath.$storage_engine_subpath); + } + + return $storage_engine_subpath; + } + + /** + * Subpath for uploaded file + * + * @param string $name + * @param array $options + * @param string $unit_prefix + * @return string + */ + private function getFormattedFileName($name, $options, $unit_prefix) + { + $prefix = $this->getFileNamePart( getArrayValue($options, 'filename_prefix'), $unit_prefix); + $suffix = $this->getFileNamePart( getArrayValue($options, 'filename_suffix'), $unit_prefix); + + $parts = pathinfo($name); + $ext = '.' . $parts['extension']; + $filename = mb_substr($parts['basename'], 0, -mb_strlen($ext)); + + return ($prefix ? $prefix . '_ ' : '') . $filename . ($suffix ? '_' . $suffix : '') . $ext; + } + + /** + * Subpath for uploaded file + * + * @param string $option + * @param string $unit_prefix + * @return string + */ + private function getFileNamePart($option, $prefix) + { + switch ( $option ) { + case PREFIX_SUFFIX_DATE_TIME: + $ret = adodb_date('Ymd-His'); + break; + case PREFIX_SUFFIX_PREFIX: + $ret = $prefix; + break; + case PREFIX_SUFFIX_USER: + $ret = $this->Application->RecallVar('user_id'); + break; + default: + $ret = $option; + } + + return $ret; + } + } class kPictureFormatter extends kUploadFormatter