Source of file DropzoneField.php
Size: 9,125 Bytes - Last Modified: 2021-12-24T06:33:30+00:00
/var/www/docs.ssmods.com/process/src/src/DropzoneField.php
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325 | <?php namespace Bigfork\SilverStripeDropzone; use SilverStripe\AssetAdmin\Forms\UploadField; use SilverStripe\Assets\File; use SilverStripe\Assets\Folder; use SilverStripe\Control\HTTP; use SilverStripe\Control\HTTPRequest; use SilverStripe\Control\HTTPResponse; use SilverStripe\Control\HTTPResponse_Exception; use SilverStripe\Forms\FileHandleField; use SilverStripe\Forms\FormField; use SilverStripe\Forms\Validator; use SilverStripe\ORM\DataObject; use SilverStripe\ORM\SS_List; use SilverStripe\ORM\ValidationException; use SilverStripe\Security\NullSecurityToken; class DropzoneField extends FormField implements FileHandleField { use DropzoneFileUploadReceiver; /** * @config * @var array */ private static $allowed_actions = [ 'upload' ]; protected $inputType = 'file'; protected $schemaDataType = FormField::SCHEMA_DATA_TYPE_CUSTOM; protected $schemaComponent = 'DropzoneField'; /** * @var array */ protected $dropzoneConfig = []; /** * The number of files allowed for this field * * @var null|int */ protected $allowedMaxFileNumber = null; /** * @var bool|null */ protected $multiUpload = null; /** * Create a new file field. * * @param string $name The internal field name, passed to forms. * @param string $title The field label. * @param SS_List $items Items assigned to this field */ public function __construct($name, $title = null, SS_List $items = null) { $this->constructFileUploadReceiver(); // When creating new files, rename on conflict $this->getUpload()->setReplaceFile(false); parent::__construct($name, $title); if ($items) { $this->setItems($items); } } /** * Creates a single file based on a form-urlencoded upload. * * @param HTTPRequest $request * @return HTTPResponse * @throws HTTPResponse_Exception * @throws ValidationException */ public function upload(HTTPRequest $request) { if ($this->isDisabled() || $this->isReadonly()) { $this->httpError(403); } // CSRF check $token = $this->getForm()->getSecurityToken(); if (!$token->checkRequest($request)) { $this->httpError(400); } $files = $this->saveTemporaryFilesFromRequest($request, $errors); if (!empty($errors)) { $result = implode(', ', $errors); $this->getUpload()->clearErrors(); return (new HTTPResponse(json_encode($result), 400)) ->addHeader('Content-Type', 'application/json'); } // Null response indicates an unfinished chunked file upload, so just return nothing if ($files === null) { return new HTTPResponse(''); } $result = []; /** @var File $file */ foreach ($files as $file) { // Ensure file is written twice so files that should be protected are actually protected // https://github.com/silverstripe/silverstripe-assets/issues/224 $file->write(); $file->write(); // Return success response $fileResult = [ 'id' => $file->ID, 'filename' => $file->Filename, 'title' => $file->Title, 'exists' => $file->exists(), 'category' => $file instanceof Folder ? 'folder' : $file->appCategory(), 'extension' => $file->Extension, 'size' => $file->AbsoluteSize, 'parent' => null ]; /** @var Folder $parent */ $parent = $file->Parent(); if ($parent) { $fileResult['parent'] = [ 'id' => $parent->ID, 'title' => $parent->Title, 'filename' => $parent->Filename ]; } $result[] = $fileResult; } $this->getUpload()->clearErrors(); return (new HTTPResponse(json_encode($result))) ->addHeader('Content-Type', 'application/json'); } /** * @param array $config * @return $this */ public function setDropzoneConfig(array $config) { $this->dropzoneConfig = $config; return $this; } /** * @param string $option * @param $value * @return $this */ public function setDropzoneConfigOption($option, $value) { $this->dropzoneConfig[$option] = $value; return $this; } public function getSchemaDataDefaults() { $state = parent::getSchemaDataDefaults(); $state['config'] = $this->dropzoneConfig; $state['config']['url'] = $this->Link('upload'); // Push security token $token = $this->getForm()->getSecurityToken(); if (!$token instanceof NullSecurityToken) { $state['config']['headers']["X-{$token->getName()}"] = $token->getValue(); } // If a max files number has been set if ($this->getAllowedMaxFileNumber() !== null) { $state['config']['maxFiles'] = $this->getAllowedMaxFileNumber(); } // If multi-upload is explicitly disallowed, max file number has to be 1 if ($this->getIsMultiUpload() === false) { $state['config']['maxFiles'] = 1; } // Add mime types for allowed file extensions (if set) $extensionsWhitelist = $this->getAllowedExtensions(); if ($extensionsWhitelist) { $accept = []; $mimeTypes = HTTP::config()->uninherited('MimeTypes'); foreach ($extensionsWhitelist as $extension) { $accept[] = ".{$extension}"; // Check for corresponding mime type if (isset($mimeTypes[$extension])) { $accept[] = $mimeTypes[$extension]; } } $state['config']['acceptedFiles'] = implode(',', $accept); } // Max file size validation $maxFileSize = $this->getValidator()->getAllowedMaxFileSize(); if ($maxFileSize && $maxFileSize > 0 && !isset($state['config']['maxFilesize'])) { $base = isset($state['config']['filesizeBase']) ? $state['config']['filesizeBase'] : 1000; $state['config']['maxFilesize'] = $maxFileSize / ($base * 1000); // Bytes -> MB } return $state; } /** * Checks if the number of files attached adheres to the $allowedMaxFileNumber defined * * @param Validator $validator * @return bool */ public function validate($validator) { $maxFiles = $this->getAllowedMaxFileNumber(); $count = count($this->getItems()); if ($maxFiles < 1 || $count <= $maxFiles) { return true; } $validator->validationError( $this->getName(), _t( UploadField::class . '.ErrorMaxFilesReached', 'You can only upload {count} file.|You can only upload {count} files.', ['count' => $maxFiles] ) ); return false; } public function getAttributes() { $attributes = [ 'class' => $this->extraClass(), 'type' => 'file', 'multiple' => $this->getIsMultiUpload(), 'id' => $this->ID(), 'data-schema' => json_encode($this->getSchemaData()), 'data-state' => json_encode($this->getSchemaState()), ]; $attributes = array_merge($attributes, $this->attributes); $this->extend('updateAttributes', $attributes); return $attributes; } /** * Gets the number of files allowed for this field * * @return null|int */ public function getAllowedMaxFileNumber() { return $this->allowedMaxFileNumber; } /** * Sets the number of files allowed for this field * * @param $count * @return $this */ public function setAllowedMaxFileNumber($count) { $this->allowedMaxFileNumber = $count; return $this; } /** * Check if allowed to upload more than one file * * @return bool */ public function getIsMultiUpload() { if (isset($this->multiUpload)) { return $this->multiUpload; } // Guess from record $record = $this->getRecord(); $name = $this->getName(); // Disabled for has_one components if ($record && DataObject::getSchema()->hasOneComponent(get_class($record), $name)) { return false; } return true; } /** * Set upload type to multiple or single * * @param bool $bool True for multiple, false for single * @return $this */ public function setIsMultiUpload($bool) { $this->multiUpload = $bool; return $this; } public function Type() { return 'dropzonefield'; } } |