2007-07-19 12:40:28 +02:00
|
|
|
<?php
|
|
|
|
/**
|
|
|
|
* Represents a file type which can be added to a form.
|
2008-04-06 10:20:13 +02:00
|
|
|
* Automatically tries to save has_one-relations on the saved
|
|
|
|
* record.
|
2014-08-15 08:53:05 +02:00
|
|
|
*
|
2008-04-06 10:20:13 +02:00
|
|
|
* Please set a validator on the form-object to get feedback
|
|
|
|
* about imposed filesize/extension restrictions.
|
2014-08-15 08:53:05 +02:00
|
|
|
*
|
|
|
|
* See {@link UploadField} For a more full-featured field
|
2012-02-03 00:59:40 +01:00
|
|
|
* (incl. ajax-friendly uploads, previews and relationship management).
|
2014-08-15 08:53:05 +02:00
|
|
|
*
|
2010-10-15 05:55:22 +02:00
|
|
|
* <b>Usage</p>
|
2014-08-15 08:53:05 +02:00
|
|
|
*
|
2010-10-15 05:55:22 +02:00
|
|
|
* If you want to implement a FileField into a form element, you need to pass it an array of source data.
|
2014-08-15 08:53:05 +02:00
|
|
|
*
|
2010-10-15 05:55:22 +02:00
|
|
|
* <code>
|
|
|
|
* class ExampleForm_Controller extends Page_Controller {
|
2014-08-15 08:53:05 +02:00
|
|
|
*
|
2012-09-19 12:07:39 +02:00
|
|
|
* function Form() {
|
2011-05-11 09:51:54 +02:00
|
|
|
* $fields = new FieldList(
|
2010-10-15 05:55:22 +02:00
|
|
|
* new TextField('MyName'),
|
|
|
|
* new FileField('MyFile')
|
|
|
|
* );
|
2011-05-11 09:51:54 +02:00
|
|
|
* $actions = new FieldList(
|
2010-10-15 05:55:22 +02:00
|
|
|
* new FormAction('doUpload', 'Upload file')
|
|
|
|
* );
|
|
|
|
* $validator = new RequiredFields(array('MyName', 'MyFile'));
|
2014-08-15 08:53:05 +02:00
|
|
|
*
|
2010-10-15 05:55:22 +02:00
|
|
|
* return new Form($this, 'Form', $fields, $actions, $validator);
|
|
|
|
* }
|
2014-08-15 08:53:05 +02:00
|
|
|
*
|
2010-10-15 05:55:22 +02:00
|
|
|
* function doUpload($data, $form) {
|
|
|
|
* $file = $data['MyFile'];
|
|
|
|
* $content = file_get_contents($file['tmp_name']);
|
|
|
|
* // ... process content
|
|
|
|
* }
|
|
|
|
* }
|
|
|
|
* </code>
|
2014-08-15 08:53:05 +02:00
|
|
|
*
|
2008-01-09 05:18:36 +01:00
|
|
|
* @package forms
|
|
|
|
* @subpackage fields-files
|
2007-07-19 12:40:28 +02:00
|
|
|
*/
|
|
|
|
class FileField extends FormField {
|
2014-08-15 08:53:05 +02:00
|
|
|
|
2008-04-06 10:20:13 +02:00
|
|
|
/**
|
|
|
|
* Flag to automatically determine and save a has_one-relationship
|
|
|
|
* on the saved record (e.g. a "Player" has_one "PlayerImage" would
|
|
|
|
* trigger saving the ID of newly created file into "PlayerImageID"
|
|
|
|
* on the record).
|
|
|
|
*
|
2008-04-09 13:11:03 +02:00
|
|
|
* @var boolean
|
2008-04-06 10:20:13 +02:00
|
|
|
*/
|
|
|
|
public $relationAutoSetting = true;
|
2014-08-15 08:53:05 +02:00
|
|
|
|
2008-04-06 10:20:13 +02:00
|
|
|
/**
|
|
|
|
* Upload object (needed for validation
|
|
|
|
* and actually moving the temporary file
|
|
|
|
* created by PHP).
|
|
|
|
*
|
|
|
|
* @var Upload
|
|
|
|
*/
|
|
|
|
protected $upload;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Partial filesystem path relative to /assets directory.
|
2012-12-20 02:52:44 +01:00
|
|
|
* Defaults to Upload::$uploads_folder.
|
2008-04-06 10:20:13 +02:00
|
|
|
*
|
|
|
|
* @var string
|
|
|
|
*/
|
2012-12-20 02:52:44 +01:00
|
|
|
protected $folderName = false;
|
2014-08-15 08:53:05 +02:00
|
|
|
|
2008-01-29 21:18:06 +01:00
|
|
|
/**
|
|
|
|
* Create a new file field.
|
2014-08-15 08:53:05 +02:00
|
|
|
*
|
2008-01-29 21:18:06 +01:00
|
|
|
* @param string $name The internal field name, passed to forms.
|
|
|
|
* @param string $title The field label.
|
|
|
|
* @param int $value The value of the field.
|
|
|
|
*/
|
2012-09-19 12:07:39 +02:00
|
|
|
public function __construct($name, $title = null, $value = null) {
|
2013-02-05 19:10:15 +01:00
|
|
|
$this->upload = Upload::create();
|
2014-08-15 08:53:05 +02:00
|
|
|
|
2012-01-02 17:43:36 +01:00
|
|
|
parent::__construct($name, $title, $value);
|
2008-01-29 21:18:06 +01:00
|
|
|
}
|
|
|
|
|
2015-06-20 12:11:08 +02:00
|
|
|
/**
|
|
|
|
* @param array $properties
|
|
|
|
* @return HTMLText
|
|
|
|
*/
|
2011-03-23 05:12:25 +01:00
|
|
|
public function Field($properties = array()) {
|
2012-04-14 07:32:29 +02:00
|
|
|
$properties = array_merge($properties, array(
|
|
|
|
'MaxFileSize' => $this->getValidator()->getAllowedMaxFileSize()
|
|
|
|
));
|
2014-08-15 08:53:05 +02:00
|
|
|
|
2012-04-14 07:32:29 +02:00
|
|
|
return parent::Field($properties);
|
2007-07-19 12:40:28 +02:00
|
|
|
}
|
2011-03-23 05:12:25 +01:00
|
|
|
|
2012-09-19 12:07:39 +02:00
|
|
|
public function getAttributes() {
|
2011-12-22 13:10:57 +01:00
|
|
|
return array_merge(
|
|
|
|
parent::getAttributes(),
|
|
|
|
array('type' => 'file')
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2012-04-11 07:00:57 +02:00
|
|
|
public function saveInto(DataObjectInterface $record) {
|
2014-08-31 05:55:51 +02:00
|
|
|
if(!isset($_FILES[$this->name])) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
$fileClass = File::get_class_for_file_extension(
|
|
|
|
pathinfo($_FILES[$this->name]['name'], PATHINFO_EXTENSION)
|
|
|
|
);
|
2014-08-15 08:53:05 +02:00
|
|
|
|
2008-04-09 13:11:03 +02:00
|
|
|
if($this->relationAutoSetting) {
|
|
|
|
// assume that the file is connected via a has-one
|
2015-02-25 16:21:33 +01:00
|
|
|
$hasOnes = $record->hasOne($this->name);
|
2008-04-09 13:11:03 +02:00
|
|
|
// try to create a file matching the relation
|
2014-08-15 08:53:05 +02:00
|
|
|
$file = (is_string($hasOnes)) ? Object::create($hasOnes) : new $fileClass();
|
2014-08-31 05:55:51 +02:00
|
|
|
} else if($record instanceof File) {
|
|
|
|
$file = $record;
|
2008-04-09 13:11:03 +02:00
|
|
|
} else {
|
2011-08-22 13:04:15 +02:00
|
|
|
$file = new $fileClass();
|
2008-04-09 13:11:03 +02:00
|
|
|
}
|
2014-08-15 08:53:05 +02:00
|
|
|
|
2012-12-20 02:52:44 +01:00
|
|
|
$this->upload->loadIntoFile($_FILES[$this->name], $file, $this->getFolderName());
|
2014-08-15 08:53:05 +02:00
|
|
|
|
2014-08-31 05:55:51 +02:00
|
|
|
if($this->upload->isError()) {
|
|
|
|
return false;
|
|
|
|
}
|
2014-08-15 08:53:05 +02:00
|
|
|
|
2008-04-06 10:20:13 +02:00
|
|
|
if($this->relationAutoSetting) {
|
2014-08-31 05:55:51 +02:00
|
|
|
if(!$hasOnes) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
$file = $this->upload->getFile();
|
2014-08-15 08:53:05 +02:00
|
|
|
|
2008-04-09 13:11:03 +02:00
|
|
|
$record->{$this->name . 'ID'} = $file->ID;
|
2008-04-06 10:20:13 +02:00
|
|
|
}
|
2014-08-31 05:55:51 +02:00
|
|
|
|
2012-02-03 00:59:40 +01:00
|
|
|
return $this;
|
2007-07-19 12:40:28 +02:00
|
|
|
}
|
2011-12-26 09:08:08 +01:00
|
|
|
|
2007-07-19 12:40:28 +02:00
|
|
|
public function Value() {
|
2011-12-26 09:08:08 +01:00
|
|
|
return isset($_FILES[$this->getName()]) ? $_FILES[$this->getName()] : null;
|
2007-07-19 12:40:28 +02:00
|
|
|
}
|
2011-12-26 09:08:08 +01:00
|
|
|
|
2010-05-25 06:03:46 +02:00
|
|
|
/**
|
|
|
|
* Get custom validator for this field
|
2014-08-15 08:53:05 +02:00
|
|
|
*
|
2013-05-27 05:22:59 +02:00
|
|
|
* @param Upload_Validator $validator
|
2010-05-25 06:03:46 +02:00
|
|
|
*/
|
|
|
|
public function getValidator() {
|
|
|
|
return $this->upload->getValidator();
|
|
|
|
}
|
2014-08-15 08:53:05 +02:00
|
|
|
|
2010-05-25 06:03:46 +02:00
|
|
|
/**
|
|
|
|
* Set custom validator for this field
|
2014-08-15 08:53:05 +02:00
|
|
|
*
|
2013-05-27 05:22:59 +02:00
|
|
|
* @param Upload_Validator $validator
|
|
|
|
* @return FileField Self reference
|
2010-05-25 06:03:46 +02:00
|
|
|
*/
|
|
|
|
public function setValidator($validator) {
|
|
|
|
$this->upload->setValidator($validator);
|
2012-02-03 00:59:40 +01:00
|
|
|
return $this;
|
2010-05-25 06:03:46 +02:00
|
|
|
}
|
2014-08-15 08:53:05 +02:00
|
|
|
|
2008-04-06 10:20:13 +02:00
|
|
|
/**
|
2013-05-27 05:22:59 +02:00
|
|
|
* Sets the upload folder name
|
2014-08-15 08:53:05 +02:00
|
|
|
*
|
2008-04-06 10:20:13 +02:00
|
|
|
* @param string $folderName
|
2013-05-27 05:22:59 +02:00
|
|
|
* @return FileField Self reference
|
2008-04-06 10:20:13 +02:00
|
|
|
*/
|
|
|
|
public function setFolderName($folderName) {
|
|
|
|
$this->folderName = $folderName;
|
2012-02-03 00:59:40 +01:00
|
|
|
return $this;
|
2008-04-06 10:20:13 +02:00
|
|
|
}
|
2014-08-15 08:53:05 +02:00
|
|
|
|
2008-04-06 10:20:13 +02:00
|
|
|
/**
|
2013-05-27 05:22:59 +02:00
|
|
|
* Gets the upload folder name
|
2014-08-15 08:53:05 +02:00
|
|
|
*
|
2008-04-06 10:20:13 +02:00
|
|
|
* @return string
|
|
|
|
*/
|
|
|
|
public function getFolderName() {
|
2013-03-21 19:48:54 +01:00
|
|
|
return ($this->folderName !== false) ? $this->folderName : Config::inst()->get('Upload', 'uploads_folder');
|
2008-04-06 10:20:13 +02:00
|
|
|
}
|
2014-08-15 08:53:05 +02:00
|
|
|
|
2015-05-11 02:32:00 +02:00
|
|
|
public function validate($validator) {
|
2008-04-17 12:11:40 +02:00
|
|
|
if(!isset($_FILES[$this->name])) return true;
|
2014-08-15 08:53:05 +02:00
|
|
|
|
2008-04-06 10:20:13 +02:00
|
|
|
$tmpFile = $_FILES[$this->name];
|
|
|
|
|
|
|
|
$valid = $this->upload->validate($tmpFile);
|
|
|
|
if(!$valid) {
|
|
|
|
$errors = $this->upload->getErrors();
|
|
|
|
if($errors) foreach($errors as $error) {
|
|
|
|
$validator->validationError($this->name, $error, "validation", false);
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
2014-08-15 08:53:05 +02:00
|
|
|
|
2008-04-06 10:20:13 +02:00
|
|
|
return true;
|
|
|
|
}
|
2012-06-28 11:42:27 +02:00
|
|
|
|
|
|
|
/**
|
2013-05-27 05:22:59 +02:00
|
|
|
* Retrieves the Upload handler
|
2014-08-15 08:53:05 +02:00
|
|
|
*
|
2012-06-28 11:42:27 +02:00
|
|
|
* @return Upload
|
|
|
|
*/
|
|
|
|
public function getUpload() {
|
|
|
|
return $this->upload;
|
|
|
|
}
|
|
|
|
|
2013-05-27 05:22:59 +02:00
|
|
|
/**
|
|
|
|
* Sets the upload handler
|
2014-08-15 08:53:05 +02:00
|
|
|
*
|
2013-05-27 05:22:59 +02:00
|
|
|
* @param Upload $upload
|
|
|
|
* @return FileField Self reference
|
|
|
|
*/
|
2012-06-28 11:42:27 +02:00
|
|
|
public function setUpload(Upload $upload) {
|
|
|
|
$this->upload = $upload;
|
2013-05-27 05:22:59 +02:00
|
|
|
return $this;
|
2012-06-28 11:42:27 +02:00
|
|
|
}
|
|
|
|
|
2014-07-17 22:40:23 +02:00
|
|
|
/**
|
|
|
|
* Limit allowed file extensions. Empty by default, allowing all extensions.
|
|
|
|
* To allow files without an extension, use an empty string.
|
|
|
|
* See {@link File::$allowed_extensions} to get a good standard set of
|
|
|
|
* extensions that are typically not harmful in a webserver context.
|
|
|
|
* See {@link setAllowedMaxFileSize()} to limit file size by extension.
|
2014-08-15 08:53:05 +02:00
|
|
|
*
|
2014-07-17 22:40:23 +02:00
|
|
|
* @param array $rules List of extensions
|
|
|
|
* @return $this
|
|
|
|
*/
|
|
|
|
public function setAllowedExtensions($rules) {
|
|
|
|
$this->getValidator()->setAllowedExtensions($rules);
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Limit allowed file extensions by specifying categories of file types.
|
|
|
|
* These may be 'image', 'audio', 'mov', 'zip', 'flash', or 'doc'
|
|
|
|
* See {@link File::$allowed_extensions} for details of allowed extensions
|
|
|
|
* for each of these categories
|
2014-08-15 08:53:05 +02:00
|
|
|
*
|
2014-07-17 22:40:23 +02:00
|
|
|
* @param string $category Category name
|
|
|
|
* @param string,... $categories Additional category names
|
|
|
|
* @return $this
|
|
|
|
*/
|
|
|
|
public function setAllowedFileCategories($category) {
|
|
|
|
$extensions = array();
|
|
|
|
$knownCategories = File::config()->app_categories;
|
2014-08-15 08:53:05 +02:00
|
|
|
|
2014-07-17 22:40:23 +02:00
|
|
|
// Parse arguments
|
|
|
|
$categories = func_get_args();
|
|
|
|
if(func_num_args() === 1 && is_array(reset($categories))) {
|
|
|
|
$categories = reset($categories);
|
|
|
|
}
|
2014-08-15 08:53:05 +02:00
|
|
|
|
2014-07-17 22:40:23 +02:00
|
|
|
// Merge all categories into list of extensions
|
|
|
|
foreach(array_filter($categories) as $category) {
|
|
|
|
if(isset($knownCategories[$category])) {
|
|
|
|
$extensions = array_merge($extensions, $knownCategories[$category]);
|
|
|
|
} else {
|
|
|
|
user_error("Unknown file category: $category", E_USER_ERROR);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return $this->setAllowedExtensions($extensions);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns list of extensions allowed by this field, or an empty array
|
|
|
|
* if there is no restriction
|
2014-08-15 08:53:05 +02:00
|
|
|
*
|
2014-07-17 22:40:23 +02:00
|
|
|
* @return array
|
|
|
|
*/
|
|
|
|
public function getAllowedExtensions() {
|
|
|
|
return $this->getValidator()->getAllowedExtensions();
|
|
|
|
}
|
|
|
|
|
2012-11-14 23:33:10 +01:00
|
|
|
}
|