/forms/FileField.php

https://github.com/silverstripe-scienceninjas/sapphire · PHP · 208 lines · 73 code · 26 blank · 109 comment · 10 complexity · c0413a987461183c46fa71c2dea49745 MD5 · raw file

  1. <?php
  2. /**
  3. * Represents a file type which can be added to a form.
  4. * Automatically tries to save has_one-relations on the saved
  5. * record.
  6. *
  7. * Please set a validator on the form-object to get feedback
  8. * about imposed filesize/extension restrictions.
  9. *
  10. * See {@link UploadField} For a more full-featured field
  11. * (incl. ajax-friendly uploads, previews and relationship management).
  12. *
  13. * <b>Usage</p>
  14. *
  15. * If you want to implement a FileField into a form element, you need to pass it an array of source data.
  16. *
  17. * <code>
  18. * class ExampleForm_Controller extends Page_Controller {
  19. *
  20. * public function Form() {
  21. * $fields = new FieldList(
  22. * new TextField('MyName'),
  23. * new FileField('MyFile')
  24. * );
  25. * $actions = new FieldList(
  26. * new FormAction('doUpload', 'Upload file')
  27. * );
  28. * $validator = new RequiredFields(array('MyName', 'MyFile'));
  29. *
  30. * return new Form($this, 'Form', $fields, $actions, $validator);
  31. * }
  32. *
  33. * function doUpload($data, $form) {
  34. * $file = $data['MyFile'];
  35. * $content = file_get_contents($file['tmp_name']);
  36. * // ... process content
  37. * }
  38. * }
  39. * </code>
  40. *
  41. * @package forms
  42. * @subpackage fields-files
  43. */
  44. class FileField extends FormField {
  45. /**
  46. * Restrict filesize for either all filetypes
  47. * or a specific extension, with extension-name
  48. * as array-key and the size-restriction in bytes as array-value.
  49. *
  50. * @deprecated 2.5
  51. * @var array
  52. */
  53. public $allowedMaxFileSize = array();
  54. /**
  55. * @var array Collection of extensions.
  56. * Extension-names are treated case-insensitive.
  57. *
  58. * Example:
  59. * <code>
  60. * array("jpg","GIF")
  61. * </code>
  62. *
  63. * @deprecated 2.5
  64. * @var array
  65. */
  66. public $allowedExtensions = array();
  67. /**
  68. * Flag to automatically determine and save a has_one-relationship
  69. * on the saved record (e.g. a "Player" has_one "PlayerImage" would
  70. * trigger saving the ID of newly created file into "PlayerImageID"
  71. * on the record).
  72. *
  73. * @var boolean
  74. */
  75. public $relationAutoSetting = true;
  76. /**
  77. * Upload object (needed for validation
  78. * and actually moving the temporary file
  79. * created by PHP).
  80. *
  81. * @var Upload
  82. */
  83. protected $upload;
  84. /**
  85. * Partial filesystem path relative to /assets directory.
  86. * Defaults to 'Uploads'.
  87. *
  88. * @var string
  89. */
  90. protected $folderName = 'Uploads';
  91. /**
  92. * Create a new file field.
  93. *
  94. * @param string $name The internal field name, passed to forms.
  95. * @param string $title The field label.
  96. * @param int $value The value of the field.
  97. */
  98. function __construct($name, $title = null, $value = null) {
  99. if(count(func_get_args()) > 3) Deprecation::notice('3.0', 'Use setRightTitle() and setFolderName() instead of constructor arguments');
  100. $this->upload = new Upload();
  101. parent::__construct($name, $title, $value);
  102. }
  103. public function Field($properties = array()) {
  104. $properties = array_merge($properties, array(
  105. 'MaxFileSize' => $this->getValidator()->getAllowedMaxFileSize()
  106. ));
  107. return parent::Field($properties);
  108. }
  109. function getAttributes() {
  110. return array_merge(
  111. parent::getAttributes(),
  112. array('type' => 'file')
  113. );
  114. }
  115. public function saveInto(DataObjectInterface $record) {
  116. if(!isset($_FILES[$this->name])) return false;
  117. $fileClass = File::get_class_for_file_extension(pathinfo($_FILES[$this->name]['name'], PATHINFO_EXTENSION));
  118. if($this->relationAutoSetting) {
  119. // assume that the file is connected via a has-one
  120. $hasOnes = $record->has_one($this->name);
  121. // try to create a file matching the relation
  122. $file = (is_string($hasOnes)) ? Object::create($hasOnes) : new $fileClass();
  123. } else {
  124. $file = new $fileClass();
  125. }
  126. $this->upload->loadIntoFile($_FILES[$this->name], $file, $this->folderName);
  127. if($this->upload->isError()) return false;
  128. $file = $this->upload->getFile();
  129. if($this->relationAutoSetting) {
  130. if(!$hasOnes) return false;
  131. // save to record
  132. $record->{$this->name . 'ID'} = $file->ID;
  133. }
  134. return $this;
  135. }
  136. public function Value() {
  137. return isset($_FILES[$this->getName()]) ? $_FILES[$this->getName()] : null;
  138. }
  139. /**
  140. * Get custom validator for this field
  141. *
  142. * @param object $validator
  143. */
  144. public function getValidator() {
  145. return $this->upload->getValidator();
  146. }
  147. /**
  148. * Set custom validator for this field
  149. *
  150. * @param object $validator
  151. */
  152. public function setValidator($validator) {
  153. $this->upload->setValidator($validator);
  154. return $this;
  155. }
  156. /**
  157. * @param string $folderName
  158. */
  159. public function setFolderName($folderName) {
  160. $this->folderName = $folderName;
  161. return $this;
  162. }
  163. /**
  164. * @return string
  165. */
  166. public function getFolderName() {
  167. return $this->folderName;
  168. }
  169. public function validate($validator) {
  170. if(!isset($_FILES[$this->name])) return true;
  171. $tmpFile = $_FILES[$this->name];
  172. $valid = $this->upload->validate($tmpFile);
  173. if(!$valid) {
  174. $errors = $this->upload->getErrors();
  175. if($errors) foreach($errors as $error) {
  176. $validator->validationError($this->name, $error, "validation", false);
  177. }
  178. return false;
  179. }
  180. return true;
  181. }
  182. }