mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 12:05:37 +00:00
ENHANCEMENT Added File::get_class_for_file_extension() instead of hardcoding it in Folder->constructChild(). Allows for custom classes in files uploaded through core functionality like the Upload and FileField logic.
This commit is contained in:
parent
3bd80dfb87
commit
afeccbc9cb
@ -790,6 +790,53 @@ class File extends DataObject {
|
||||
return $fields;
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
* @var Array Only use lowercase extensions in here.
|
||||
*/
|
||||
static $class_for_file_extension = array(
|
||||
'*' => 'File',
|
||||
'jpg' => 'Image',
|
||||
'jpeg' => 'Image',
|
||||
'png' => 'Image',
|
||||
'gif' => 'Image',
|
||||
);
|
||||
|
||||
?>
|
||||
/**
|
||||
* Maps a {@link File} subclass to a specific extension.
|
||||
* By default, files with common image extensions will be created
|
||||
* as {@link Image} instead of {@link File} when using
|
||||
* {@link Folder::constructChild}, {@link Folder::addUploadToFolder}),
|
||||
* and the {@link Upload} class (either directly or through {@link FileField}).
|
||||
* For manually instanciated files please use this mapping getter.
|
||||
*
|
||||
* Caution: Changes to mapping doesn't apply to existing file records in the database.
|
||||
* Also doesn't hook into {@link Object::getCustomClass()}.
|
||||
*
|
||||
* @param String File extension, without dot prefix. Use an asterisk ('*')
|
||||
* to specify a generic fallback if no mapping is found for an extension.
|
||||
* @return String Classname for a subclass of {@link File}
|
||||
*/
|
||||
static function get_class_for_file_extension($ext) {
|
||||
$map = array_change_key_case(self::$class_for_file_extension, CASE_LOWER);
|
||||
return (array_key_exists(strtolower($ext), $map)) ? $map[strtolower($ext)] : $map['*'];
|
||||
}
|
||||
|
||||
/**
|
||||
* See {@link get_class_for_file_extension()}.
|
||||
*
|
||||
* @param String|array
|
||||
* @param String
|
||||
*/
|
||||
static function set_class_for_file_extension($exts, $class) {
|
||||
if(!is_array($exts)) $exts = array($exts);
|
||||
foreach($exts as $ext) {
|
||||
if(ClassInfo::is_subclass_of($ext, 'File')) {
|
||||
throw new InvalidArgumentException(
|
||||
sprintf('Class "%s" (for extension "%s") is not a valid subclass of File', $class, $ext)
|
||||
);
|
||||
}
|
||||
self::$class_for_file_extension[$ext] = $class;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -183,12 +183,7 @@ class Folder extends File {
|
||||
if(is_dir($baseDir . $name)) {
|
||||
$className = "Folder";
|
||||
} else {
|
||||
// Could use getimagesize to get the type of the image
|
||||
$ext = strtolower(substr($name,strrpos($name,'.')+1));
|
||||
switch($ext) {
|
||||
case "gif": case "jpg": case "jpeg": case "png": $className = "Image"; break;
|
||||
default: $className = "File";
|
||||
}
|
||||
$className = File::get_class_for_file_extension(pathinfo($name, PATHINFO_EXTENSION));
|
||||
}
|
||||
|
||||
if(Member::currentUser()) $ownerID = Member::currentUser()->ID;
|
||||
|
@ -98,7 +98,10 @@ class Upload extends Controller {
|
||||
|
||||
if(!$folderPath) $folderPath = self::$uploads_folder;
|
||||
|
||||
if(!$this->file) $this->file = new File();
|
||||
if(!$this->file) {
|
||||
$fileClass = File::get_class_for_file_extension(pathinfo($tmpFile['name'], PATHINFO_EXTENSION));
|
||||
$this->file = new $fileClass();
|
||||
}
|
||||
|
||||
if(!is_array($tmpFile)) {
|
||||
user_error("Upload::load() Not passed an array. Most likely, the form hasn't got the right enctype", E_USER_ERROR);
|
||||
|
@ -133,14 +133,15 @@ class FileField extends FormField {
|
||||
|
||||
public function saveInto(DataObject $record) {
|
||||
if(!isset($_FILES[$this->name])) return false;
|
||||
$fileClass = File::get_class_for_file_extension(pathinfo($_FILES[$this->name]['name'], PATHINFO_EXTENSION));
|
||||
|
||||
if($this->relationAutoSetting) {
|
||||
// assume that the file is connected via a has-one
|
||||
$hasOnes = $record->has_one($this->name);
|
||||
// try to create a file matching the relation
|
||||
$file = (is_string($hasOnes)) ? Object::create($hasOnes) : new File();
|
||||
$file = (is_string($hasOnes)) ? Object::create($hasOnes) : new $fileClass();
|
||||
} else {
|
||||
$file = new File();
|
||||
$file = new $fileClass();
|
||||
}
|
||||
|
||||
$this->upload->loadIntoFile($_FILES[$this->name], $file, $this->folderName);
|
||||
|
@ -7,6 +7,8 @@ class FileTest extends SapphireTest {
|
||||
|
||||
static $fixture_file = 'FileTest.yml';
|
||||
|
||||
protected $extraDataObjects = array('FileTest_MyCustomFile');
|
||||
|
||||
function testCreateWithFilenameWithSubfolder() {
|
||||
// Note: We can't use fixtures/setUp() for this, as we want to create the db record manually.
|
||||
// Creating the folder is necessary to avoid having "Filename" overwritten by setName()/setRelativePath(),
|
||||
@ -257,6 +259,43 @@ class FileTest extends SapphireTest {
|
||||
$this->assertEquals($folder->Title, $newTitle3, "Folder Title updated after rename of Filename");
|
||||
}
|
||||
|
||||
|
||||
function testGetClassForFileExtension() {
|
||||
$orig = File::$class_for_file_extension;
|
||||
File::$class_for_file_extension['*'] = 'MyGenericFileClass';
|
||||
File::$class_for_file_extension['foo'] = 'MyFooFileClass';
|
||||
|
||||
$this->assertEquals(
|
||||
'MyFooFileClass',
|
||||
File::get_class_for_file_extension('foo'),
|
||||
'Finds directly mapped file classes'
|
||||
);
|
||||
$this->assertEquals(
|
||||
'MyFooFileClass',
|
||||
File::get_class_for_file_extension('FOO'),
|
||||
'Works without case sensitivity'
|
||||
);
|
||||
$this->assertEquals(
|
||||
'MyGenericFileClass',
|
||||
File::get_class_for_file_extension('unknown'),
|
||||
'Falls back to generic class for unknown extensions'
|
||||
);
|
||||
|
||||
File::$class_for_file_extension = $orig;
|
||||
}
|
||||
|
||||
function testFolderConstructChild() {
|
||||
$orig = File::$class_for_file_extension;
|
||||
File::$class_for_file_extension['gif'] = 'FileTest_MyCustomFile';
|
||||
|
||||
$folder1 = $this->objFromFixture('Folder', 'folder1');
|
||||
$fileID = $folder1->constructChild('myfile.gif');
|
||||
$file = DataObject::get_by_id('File', $fileID);
|
||||
$this->assertEquals('FileTest_MyCustomFile', get_class($file));
|
||||
|
||||
File::$class_for_file_extension = $orig;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function setUp() {
|
||||
@ -309,3 +348,7 @@ class FileTest extends SapphireTest {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class FileTest_MyCustomFile extends File implements TestOnly {
|
||||
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user