Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,16 +35,20 @@ The Dropzone module provides `FileAttachmentField`, a robust HTML5 uploading int
<img src="https://raw.githubusercontent.com/unclecheese/silverstripe-dropzone/master/images/screenshots/screen5.png" width="75%">

## Usage
The field instantiates similarly to `UploadField`, taking the name of the file relationship and a label, as the first two arguments. Once instantiated, there are many ways to configure the UI.
The field instantiates similarly to `UploadField`, taking the name of the file relationship and a label, as the first
two arguments. Once instantiated, there are many ways to configure the UI.

```php
FileAttachmentField::create('MyFile', 'Upload a file')
->setView('grid')
```

If the form holding the upload field is bound to a record, (i.e. with `loadDataFrom()`), the upload field will automatically allow multiple files if the relation is a `has_many` or `many_many`. If the form is not bound to a record, you can use `setMultiple(true)`.
If the form holding the upload field is bound to a record, (i.e. with `loadDataFrom()`), the upload field will
automatically allow multiple files if the relation is a `has_many` or `many_many`. If the form is not bound to a record,
you can use `setMultiple(true)`.

Image-only uploads can be forced using the `imagesOnly()` method. If the form is bound to a record, and the relation points to an `Image` class, this will be automatically set.
Image-only uploads can be forced using the `imagesOnly()` method. If the form is bound to a record, and the relation
points to an `Image` class, this will be automatically set.

### More advanced options

Expand Down
3 changes: 0 additions & 3 deletions _config.php

This file was deleted.

22 changes: 14 additions & 8 deletions _config/config.yml
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
---
Name: dropzone
After: 'framework/*','cms/*'
---
FileAttachmentField:
default_config_path: 'javascript/default_config.json'
icon_sizes: [16, 32, 48, 64, 128, 512]
UncleCheese\DropZone\FileAttachmentField:
default_config_path: javascript/default_config.json
icon_sizes:
- 16
- 32
- 48
- 64
- 128
- 512
upgrade_images: true
list_thumbnail_width: 64
list_thumbnail_height: 64
Expand All @@ -17,9 +22,10 @@ FileAttachmentField:
param_name: file
create_image_thumbnails: true
max_thumbnail_filesize: 10
clickable: '.dropzone-select'
clickable: .dropzone-select
auto_process_queue: true
auto_queue: true
add_remove_links: false
File:
extensions: [DropzoneFile]
add_remove_links: false
SilverStripe\Assets\File:
extensions:
- UncleCheese\DropZone\DropzoneFile
10 changes: 9 additions & 1 deletion code/DropzoneFile.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
<?php

namespace UncleCheese\DropZone;

use SilverStripe\Assets\Image;
use SilverStripe\Control\Director;
use SilverStripe\Core\Config\Config;
use SilverStripe\Assets\Folder;
use SilverStripe\ORM\DataExtension;

/**
* Adds helper methods to the core {@link File} object
*
Expand Down Expand Up @@ -71,4 +79,4 @@ protected function getFilenameForType($ext, $size) {
strtolower($ext)
);
}
}
}
156 changes: 62 additions & 94 deletions code/FileAttachmentField.php
Original file line number Diff line number Diff line change
@@ -1,4 +1,38 @@
<?php
namespace UncleCheese\DropZone;

use SilverStripe\Assets\File;
use SilverStripe\Core\Injector\Injector;
use SilverStripe\View\Requirements;
use SilverStripe\Assets\Image;
use SilverStripe\ORM\DataObjectInterface;
use SilverStripe\Control\Controller;
use SilverStripe\Control\Session;
use SilverStripe\ORM\DataObject;
use SilverStripe\Admin\LeftAndMain;
use SilverStripe\Control\HTTPRequest;
use SilverStripe\Forms\Form;
use SilverStripe\Control\HTTPResponse;
use SilverStripe\ORM\SS_List;
use SilverStripe\ORM\ArrayList;
use SilverStripe\ORM\ManyManyList;
use SilverStripe\ORM\RelationList;
use SilverStripe\ORM\UnsavedRelationList;
use SilverStripe\Core\Config\Config;
use SilverStripe\Core\Convert;
use SilverStripe\Assets\Folder;
use SilverStripe\Forms\FileField;
use SilverStripe\Forms\TreeDropdownField;
use SilverStripe\Forms\GridField\GridFieldConfig;
use SilverStripe\Forms\GridField\GridFieldSortableHeader;
use SilverStripe\Forms\GridField\GridFieldFilterHeader;
use SilverStripe\Forms\GridField\GridFieldDataColumns;
use SilverStripe\Forms\GridField\GridFieldPaginator;
use SilverStripe\ORM\DataList;
use SilverStripe\Forms\GridField\GridField;
use SilverStripe\Forms\CompositeField;
use SilverStripe\View\SSViewer;
use SilverStripe\View\ArrayData;

/**
* Defines the FileAttachementField form field type
Expand Down Expand Up @@ -71,7 +105,7 @@ class FileAttachmentField extends FileField {
* that have been attached to the uploader client side
* @var string
*/
protected $previewTemplate = 'FileAttachmentField_preview';
protected $previewTemplate = 'UncleCheese\DropZone\Includes\FileAttachmentField_preview';

/**
* UploadField compatability. Used for the select handler, when KickAssets
Expand Down Expand Up @@ -138,7 +172,7 @@ public function __construct($name, $title = null, $value = null, $form = null) {
$this->permissions['upload'] = true;
$this->permissions['detach'] = true;
$this->permissions['delete'] = function () use ($instance) {
return Injector::inst()->get('File')->canDelete() && $instance->isCMS();
return Injector::inst()->get(File::class)->canDelete() && $instance->isCMS();
};
$this->permissions['attach'] = function () use ($instance) {
return $instance->isCMS();
Expand Down Expand Up @@ -175,12 +209,12 @@ public function SmallFieldHolder($attributes = array ()) {
* Define some requirements and settings just before rendering the Field Holder.
*/
protected function defineFieldHolderRequirements() {
Requirements::javascript(DROPZONE_DIR.'/javascript/dropzone.js');
Requirements::javascript(DROPZONE_DIR.'/javascript/file_attachment_field.js');
Requirements::javascript('unclecheese/dropzone:/javascript/dropzone.js');
Requirements::javascript('unclecheese/dropzone:/javascript/file_attachment_field.js');
if($this->isCMS()) {
Requirements::javascript(DROPZONE_DIR.'/javascript/file_attachment_field_backend.js');
Requirements::javascript('unclecheese/dropzone:/javascript/file_attachment_field_backend.js');
}
Requirements::css(DROPZONE_DIR.'/css/file_attachment_field.css');
Requirements::css('unclecheese/dropzone:/css/file_attachment_field.css');

if(!$this->getSetting('url')) {
$this->settings['url'] = $this->Link('upload');
Expand Down Expand Up @@ -365,14 +399,17 @@ public function setMaxThumbnailFilesize($num) {
* @return void
*/
public function addValidFileIDs(array $ids) {
$validIDs = Session::get('FileAttachmentField.validFileIDs');
$request = Injector::inst()->get(HTTPRequest::class);
$session = $request->getSession();

$validIDs = $session->get('FileAttachmentField.validFileIDs');
if (!$validIDs) {
$validIDs = array();
}
foreach ($ids as $id) {
$validIDs[$id] = $id;
}
Session::set('FileAttachmentField.validFileIDs', $validIDs);
$session->set('FileAttachmentField.validFileIDs', $validIDs);
}

/**
Expand All @@ -382,7 +419,9 @@ public function addValidFileIDs(array $ids) {
* @return array
*/
public function getValidFileIDs() {
$validIDs = Session::get('FileAttachmentField.validFileIDs');
$request = Injector::inst()->get(HTTPRequest::class);
$session = $request->getSession();
$validIDs = $session->get('FileAttachmentField.validFileIDs');
if ($validIDs && is_array($validIDs)) {
return $validIDs;
}
Expand Down Expand Up @@ -788,7 +827,7 @@ private function getUploadUserError($code) {
* @return SS_HTTPResponse
* @return SS_HTTPResponse
*/
public function upload(SS_HTTPRequest $request) {
public function upload(HTTPRequest $request) {

$name = $this->getSetting('paramName');
$files = (!empty($_FILES[$name]) ? $_FILES[$name] : array());
Expand Down Expand Up @@ -840,7 +879,7 @@ public function upload(SS_HTTPRequest $request) {
return $this->httpError(400, $user_message);
}
if($relationClass = $this->getFileClass($tmpFile['name'])) {
$fileObject = Object::create($relationClass);
$fileObject = new $relationClass();
}

try {
Expand All @@ -867,7 +906,7 @@ public function upload(SS_HTTPRequest $request) {
if (!$formController instanceof LeftAndMain) {
$trackFile->setRecord($formController->getRecord());
}
} else if ($formClass !== 'Form') {
} else if ($formClass !== Form::class) {
$trackFile->ControllerClass = $formClass;
} else {
// If using generic 'Form' instance, get controller
Expand All @@ -879,15 +918,16 @@ public function upload(SS_HTTPRequest $request) {
}

$this->addValidFileIDs($ids);
return new SS_HTTPResponse(implode(',', $ids), 200);
$this->extend('onAfterUploadFiles', $ids);
return new HTTPResponse(implode(',', $ids), 200);
}


/**
* @param SS_HTTPRequest $request
* @return UploadField_ItemHandler
*/
public function handleSelect(SS_HTTPRequest $request) {
public function handleSelect(HTTPRequest $request) {
if($this->isDisabled() || $this->isReadonly() || !$this->CanAttach()) {
return $this->httpError(403);
}
Expand Down Expand Up @@ -933,7 +973,7 @@ public function IsMultiple() {
}

if($record = $this->getRecord()) {
return ($record->many_many($this->getName()) || $record->has_many($this->getName()));
return ($record->manyMany($this->getName()) || $record->hasMany($this->getName()));
}

return false;
Expand Down Expand Up @@ -994,7 +1034,7 @@ public function AttachedFiles() {
* @return string
*/
public function RootThumbnailsDir() {
return $this->getSetting('thumbnailsDir') ?: DROPZONE_DIR.'/images/file-icons';
return $this->getSetting('thumbnailsDir') ?: 'unclecheese/dropzone:/images/file-icons';
}

/**
Expand Down Expand Up @@ -1142,15 +1182,15 @@ public function getFileClass($filename = null) {

if($record) {
$class = $record->getRelationClass($name);
if(!$class) $class = "File";
if(!$class) $class = File::class;
}

if($filename) {
if($defaultClass == "Image" &&
if($defaultClass == Image::class &&
$this->config()->upgrade_images &&
!Injector::inst()->get($class) instanceof Image
) {
$class = "Image";
$class = Image::class;
}
}

Expand All @@ -1166,7 +1206,7 @@ public function getRecord() {
if (($record = $this->form->getRecord()) && ($record instanceof DataObject)) {
$this->record = $record;
}
elseif (($controller = $this->form->Controller())
elseif (($controller = $this->form->getController())
&& $controller->hasMethod('data')
&& ($record = $controller->data())
&& ($record instanceof DataObject)
Expand Down Expand Up @@ -1221,9 +1261,9 @@ protected function getSetting($setting) {
* @return array
*/
protected function getDefaults() {
$file_path = BASE_PATH.'/'.DROPZONE_DIR.'/'.$this->config()->default_config_path;
$file_path = BASE_PATH.'/'.'dropzone/'.$this->config()->default_config_path;
if(!file_exists($file_path)) {
throw new Exception("FileAttachmentField::getDefaults() - There is no config json file at $file_path");
throw new \Exception("FileAttachmentField::getDefaults() - There is no config json file at $file_path");
}

return Convert::json2array(file_get_contents($file_path));
Expand Down Expand Up @@ -1300,76 +1340,4 @@ public function getConfigJSON() {
}
}

class FileAttachmentField_SelectHandler extends UploadField_SelectHandler {

private static $allowed_actions = array (
'filesbyid',
);

/**
* @param $folderID The ID of the folder to display.
* @return FormField
*/
protected function getListField($folderID) {
// Generate the folder selection field.
$folderField = new TreeDropdownField('ParentID', _t('HtmlEditorField.FOLDER', 'Folder'), 'Folder');
$folderField->setValue($folderID);

// Generate the file list field.
$config = GridFieldConfig::create();
$config->addComponent(new GridFieldSortableHeader());
$config->addComponent(new GridFieldFilterHeader());
$config->addComponent($columns = new GridFieldDataColumns());
$columns->setDisplayFields(array(
'StripThumbnail' => '',
'Name' => 'Name',
'Title' => 'Title'
));
$config->addComponent(new GridFieldPaginator(8));

// If relation is to be autoset, we need to make sure we only list compatible objects.
$baseClass = $this->parent->getFileClass();

// Create the data source for the list of files within the current directory.
$files = DataList::create($baseClass)->filter('ParentID', $folderID);

$fileField = new GridField('Files', false, $files, $config);
$fileField->setAttribute('data-selectable', true);
if($this->parent->IsMultiple()) {
$fileField->setAttribute('data-multiselect', true);
}

$selectComposite = new CompositeField(
$folderField,
$fileField
);

return $selectComposite;
}


public function filesbyid(SS_HTTPRequest $r) {
$ids = $r->getVar('ids');
$files = File::get()->byIDs(explode(',',$ids));

$validIDs = array();
$json = array ();
foreach($files as $file) {
$template = new SSViewer('FileAttachmentField_attachments');
$html = $template->process(ArrayData::create(array(
'File' => $file,
'Scope' => $this->parent
)));

$validIDs[$file->ID] = $file->ID;
$json[] = array (
'id' => $file->ID,
'html' => $html->forTemplate()
);
}

$this->parent->addValidFileIDs($validIDs);
return Convert::array2json($json);
}

}
4 changes: 4 additions & 0 deletions code/FileAttachmentFieldCleanTask.php
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
<?php
namespace UncleCheese\DropZone;

use SilverStripe\ORM\DB;
use SilverStripe\Dev\BuildTask;

/**
* Delete all files being tracked that weren't saved against anything.
Expand Down
Loading