Skip to content

Instantly share code, notes, and snippets.

@frankmullenger
Last active October 1, 2015 22:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save frankmullenger/09abbe12009835b85349 to your computer and use it in GitHub Desktop.
Save frankmullenger/09abbe12009835b85349 to your computer and use it in GitHub Desktop.
UserForms file attachments
<?php
/**
* Files that are uploaded only to be attached to emails and are not saved into assets.
*/
class EditableFileAttachmentField extends EditableFormField {
private static $singular_name = 'File Attachment Field';
private static $plural_names = 'File Attachment Fields';
public function getFormField() {
$field = FileField::create($this->Name, $this->EscapedTitle)
->setFieldHolderTemplate('UserFormsField_holder')
->setTemplate('UserFormsFileField');
$validator = new EditableFileAttachmentField_UploadValidator();
$field->setValidator($validator);
$this->doUpdateFormField($field);
return $field;
}
/**
* Ensure that this field is validated even if it is not required to ensure only
* certain file types are uploaded.
*
* TODO: Fix validation for this field being required
*/
public function validateField($data, $form) {
$formField = $this->getFormField();
if(isset($data[$this->Name])) {
$formField->setValue($data[$this->Name]);
}
if(
!isset($data[$this->Name]) ||
!$data[$this->Name] ||
!$formField->validate($form->getValidator())
) {
// Get validator messages to display in the UI
$message = $this->getErrorMessage()->HTML();
$validatorErrors = $formField->getValidator()->getErrors();
if ($validatorErrors) {
$message = implode(' ', $validatorErrors);
}
$form->addErrorMessage($this->Name, $message, 'error', false);
}
return true;
}
/**
* Return the value for the database, link to the file is stored as a
* relation so value for the field can be null.
*
* @return string
*/
public function getValueFromData() {
return null;
}
}
/**
* Validator for file attachment fields.
*/
class EditableFileAttachmentField_UploadValidator extends Upload_Validator {
/**
* Max allowed file size is 4MB
*/
public $allowedMaxFileSize = array(
'*' => 4194304 //4MB limit on file uploads, using mebibytes calculation (4 * (1024 * 1024))
);
/**
* Allowed file extensions
*/
public $allowedExtensions = array(
'jpg',
'jpeg',
'png',
);
/**
* Alowed MIME types
*/
public $allowedMimeTypes = array(
'image/jpg',
'image/jpeg',
'image/png'
);
/**
* Validate the file upload to match:
* - valid file types (MIME type check) JPG, JPEG, PNG
* - valid file size 4MB
*
* @return boolean
*/
public function validate() {
// we don't validate for empty upload fields yet
if(!isset($this->tmpFile['name']) || empty($this->tmpFile['name'])) return true;
$isRunningTests = (class_exists('SapphireTest', false) && SapphireTest::is_running_test());
if(isset($this->tmpFile['tmp_name']) && !is_uploaded_file($this->tmpFile['tmp_name']) && !$isRunningTests) {
$this->errors[] = _t('File.NOVALIDUPLOAD', 'File is not a valid upload');
return false;
}
// TODO: Improve error reporting so that more than one message can be displayed at one time
$pathInfo = pathinfo($this->tmpFile['name']);
// Validate file size
if(!$this->isValidSize()) {
$ext = (isset($pathInfo['extension'])) ? $pathInfo['extension'] : '';
$arg = File::format_size($this->getAllowedMaxFileSize($ext));
$this->errors[] = _t(
'File.TOOLARGE',
'Filesize is too large, maximum {size} allowed',
'Argument 1: Filesize (e.g. 1MB)',
array('size' => $arg)
);
return false;
}
// Validate file extension
if(!$this->isValidExtension()) {
$this->errors[] = _t(
'File.INVALIDEXTENSION',
'Extension is not allowed (valid: {extensions})',
'Argument 1: Comma-separated list of valid extensions',
array('extensions' => wordwrap(implode(', ', $this->getAllowedExtensions())))
);
return false;
}
// Validate MIME type
if (!$this->isValidMimeType()) {
$this->errors[] = _t(
'File.INVALID_MIME_TYPE',
'File type is not allowed.'
);
return false;
}
return true;
}
private function isValidMimeType() {
$allowed = false;
$pathInfo = pathinfo($this->tmpFile['name']);
$ext = (isset($pathInfo['extension'])) ? $pathInfo['extension'] : '';
// Validate file MIME type without relying on $_FILES['upfile']['mime'] value
$finfo = new finfo(FILEINFO_MIME_TYPE);
$mimeType = $finfo->file($this->tmpFile['tmp_name']);
$allowed = array_search($mimeType, $this->allowedMimeTypes, true);
// Array search returns value or false, translate to boolean for return value
$allowed = ($allowed !== false) ? true : false;
return $allowed;
}
}
<?php
/**
* Apply customisations to user defined form controller.
*/
class UserFormsExtension_Controller extends DataExtension {
public function updateEmail($email, $recipient, $emailData) {
// If recipient should receive form data
if (!$recipient->HideFormData) {
foreach($this->owner->Fields() as $field) {
if ($field instanceof EditableFileAttachmentField) {
if (isset($_FILES[$field->Name]) && $_FILES[$field->Name]['tmp_name']) {
$fileData = $_FILES[$field->Name];
$email->attachFile(
$fileData['tmp_name'],
$fileData['name'],
HTTP::get_mime_type($fileData['name'])
);
}
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment