mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 12:05:37 +00:00
Merge pull request #363 from mateusz/uploadfield-choosefolder2
UploadField doesn't allow you to choose the folder to attach files from
This commit is contained in:
commit
dc71df74e0
@ -471,20 +471,10 @@ class UploadField extends FileField {
|
|||||||
$fileObject = null;
|
$fileObject = null;
|
||||||
|
|
||||||
if ($this->relationAutoSetting) {
|
if ($this->relationAutoSetting) {
|
||||||
// Search for classes that can hold the uploaded files by traversing the relationship.
|
// Search for relations that can hold the uploaded files.
|
||||||
if ($record->hasMethod($name)) {
|
if ($relationClass = $this->getRelationAutosetClass()) {
|
||||||
$remote = $record->$name();
|
// Create new object explicitly. Otherwise rely on Upload::load to choose the class.
|
||||||
if ($remote instanceof DataList) {
|
$fileObject = Object::create($relationClass);
|
||||||
// has_many or many_many
|
|
||||||
$desiredClass = $remote->dataClass();
|
|
||||||
}
|
|
||||||
else if (is_object($remote)) {
|
|
||||||
// has_one
|
|
||||||
$desiredClass = $remote->ClassName;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we have a specific class, create new object explicitly. Otherwise rely on Upload::load to choose the class.
|
|
||||||
if (is_string($desiredClass)) $fileObject = Object::create($desiredClass);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -593,6 +583,17 @@ class UploadField extends FileField {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the foreign class that needs to be created.
|
||||||
|
*
|
||||||
|
* @return string Foreign class name.
|
||||||
|
*/
|
||||||
|
public function getRelationAutosetClass() {
|
||||||
|
$name = $this->getName();
|
||||||
|
$record = $this->getRecord();
|
||||||
|
|
||||||
|
if (isset($name) && isset($record)) return $record->getRelationClass($name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -828,7 +829,9 @@ class UploadField_ItemHandler extends RequestHandler {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* File selection popup for attaching existing files.
|
||||||
|
*/
|
||||||
class UploadField_SelectHandler extends RequestHandler {
|
class UploadField_SelectHandler extends RequestHandler {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -854,6 +857,8 @@ class UploadField_SelectHandler extends RequestHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function index() {
|
function index() {
|
||||||
|
// Requires a separate JS file, because we can't reach into the iframe with entwine.
|
||||||
|
Requirements::javascript(FRAMEWORK_DIR . '/javascript/UploadField_select.js');
|
||||||
return $this->renderWith('CMSDialog');
|
return $this->renderWith('CMSDialog');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -866,42 +871,70 @@ class UploadField_SelectHandler extends RequestHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Build the file selection form.
|
||||||
|
*
|
||||||
* @return Form
|
* @return Form
|
||||||
*/
|
*/
|
||||||
function Form() {
|
function Form() {
|
||||||
|
// Find out the requested folder ID.
|
||||||
|
$folderID = $this->parent->getRequest()->requestVar('ParentID');
|
||||||
|
if (!isset($folderID)) {
|
||||||
|
$folder = Folder::find_or_make($this->folderName);
|
||||||
|
$folderID = $folder->ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Construct the form
|
||||||
$action = new FormAction('doAttach', _t('UploadField.AttachFile', 'Attach file(s)'));
|
$action = new FormAction('doAttach', _t('UploadField.AttachFile', 'Attach file(s)'));
|
||||||
$action->addExtraClass('ss-ui-action-constructive icon-accept');
|
$action->addExtraClass('ss-ui-action-constructive icon-accept');
|
||||||
return new Form(
|
$form = new Form(
|
||||||
$this,
|
$this,
|
||||||
'Form',
|
'Form',
|
||||||
new FieldList($this->getListField()),
|
new FieldList($this->getListField($folderID)),
|
||||||
new FieldList($action)
|
new FieldList($action)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Add a class so we can reach the form from the frontend.
|
||||||
|
$form->addExtraClass('uploadfield-form');
|
||||||
|
|
||||||
|
return $form;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @param $folderID The ID of the folder to display.
|
||||||
* @return FormField
|
* @return FormField
|
||||||
*/
|
*/
|
||||||
protected function getListField() {
|
protected function getListField($folderID) {
|
||||||
$folder = $this->getFolder();
|
// 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 = GridFieldConfig::create();
|
||||||
$config->addComponent(new GridFieldSortableHeader());
|
$config->addComponent(new GridFieldSortableHeader());
|
||||||
$config->addComponent(new GridFieldFilterHeader());
|
$config->addComponent(new GridFieldFilterHeader());
|
||||||
$config->addComponent(new GridFieldDataColumns());
|
$config->addComponent(new GridFieldDataColumns());
|
||||||
$config->addComponent(new GridFieldPaginator(10));
|
$config->addComponent(new GridFieldPaginator(10));
|
||||||
|
|
||||||
$field = new GridField('Files', false, $folder->stageChildren(), $config);
|
// Create the data source for the list of files within the current directory.
|
||||||
$field->setAttribute('data-selectable', true);
|
$files = DataList::create('File')->filter('ParentID', $folderID);
|
||||||
if($this->parent->getConfig('allowedMaxFileNumber') > 1) $field->setAttribute('data-multiselect', true);
|
|
||||||
|
|
||||||
return $field;
|
// If relation is to be autoset, make sure only objects from related class are listed.
|
||||||
}
|
if ($this->parent->relationAutoSetting) {
|
||||||
|
if ($relationClass = $this->parent->getRelationAutosetClass()) {
|
||||||
|
$files->filter('ClassName', $relationClass);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
$fileField = new GridField('Files', false, $files, $config);
|
||||||
* @return Folder
|
$fileField->setAttribute('data-selectable', true);
|
||||||
*/
|
if($this->parent->getConfig('allowedMaxFileNumber') > 1) $fileField->setAttribute('data-multiselect', true);
|
||||||
function getFolder() {
|
|
||||||
return Folder::find_or_make($this->folderName);
|
$selectComposite = new CompositeField(
|
||||||
|
$folderField,
|
||||||
|
$fileField
|
||||||
|
);
|
||||||
|
|
||||||
|
return $selectComposite;
|
||||||
}
|
}
|
||||||
|
|
||||||
function doAttach($data, $form) {
|
function doAttach($data, $form) {
|
||||||
|
@ -132,7 +132,7 @@
|
|||||||
if(!dialog.length) dialog = jQuery('<div class="ss-uploadfield-dialog" id="' + dialogId + '" />');
|
if(!dialog.length) dialog = jQuery('<div class="ss-uploadfield-dialog" id="' + dialogId + '" />');
|
||||||
|
|
||||||
// Show dialog
|
// Show dialog
|
||||||
dialog.ssdialog({iframeUrl: config['urlSelectDialog']});
|
dialog.ssdialog({iframeUrl: config['urlSelectDialog'], height: 550});
|
||||||
|
|
||||||
// TODO Allow single-select
|
// TODO Allow single-select
|
||||||
dialog.find('iframe').bind('load', function(e) {
|
dialog.find('iframe').bind('load', function(e) {
|
||||||
@ -265,4 +265,4 @@
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}(jQuery));
|
}(jQuery));
|
||||||
|
18
javascript/UploadField_select.js
Normal file
18
javascript/UploadField_select.js
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
(function($) {
|
||||||
|
$.entwine('ss', function($) {
|
||||||
|
// Install the directory selection handler
|
||||||
|
$('form.uploadfield-form #ParentID .TreeDropdownField').entwine({
|
||||||
|
onmatch: function() {
|
||||||
|
this._super();
|
||||||
|
|
||||||
|
var self = this;
|
||||||
|
this.bind('change', function() {
|
||||||
|
// Display the contents of the folder in the listing field.
|
||||||
|
var fileList = self.closest('form').find('.ss-gridfield');
|
||||||
|
fileList.setState('ParentID', self.getValue());
|
||||||
|
fileList.reload();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
})(jQuery);
|
@ -1342,7 +1342,38 @@ class DataObject extends ViewableData implements DataObjectInterface, i18nEntity
|
|||||||
|
|
||||||
return singleton($componentClass)->extendedSQL($combinedFilter, $sort, $limit, $join);
|
return singleton($componentClass)->extendedSQL($combinedFilter, $sort, $limit, $join);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find the foreign class of a relation on this DataObject, regardless of the relation type.
|
||||||
|
*
|
||||||
|
* @param $relationName Relation name.
|
||||||
|
* @return string Class name, or null if not found.
|
||||||
|
*/
|
||||||
|
public function getRelationClass($relationName) {
|
||||||
|
// Go through all relationship configuration fields.
|
||||||
|
$candidates = array_merge(
|
||||||
|
($relations = Config::inst()->get($this->class, 'has_one')) ? $relations : array(),
|
||||||
|
($relations = Config::inst()->get($this->class, 'has_many')) ? $relations : array(),
|
||||||
|
($relations = Config::inst()->get($this->class, 'many_many')) ? $relations : array(),
|
||||||
|
($relations = Config::inst()->get($this->class, 'belongs_many_many')) ? $relations : array(),
|
||||||
|
($relations = Config::inst()->get($this->class, 'belongs_to')) ? $relations : array()
|
||||||
|
);
|
||||||
|
|
||||||
|
if (isset($candidates[$relationName])) {
|
||||||
|
$remoteClass = $candidates[$relationName];
|
||||||
|
|
||||||
|
// If dot notation is present, extract just the first part that contains the class.
|
||||||
|
if(($fieldPos = strpos($remoteClass, '.'))!==false) {
|
||||||
|
return substr($remoteClass, 0, $fieldPos);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise just return the class
|
||||||
|
return $remoteClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tries to find the database key on another object that is used to store a relationship to this class. If no join
|
* Tries to find the database key on another object that is used to store a relationship to this class. If no join
|
||||||
* field can be found it defaults to 'ParentID'.
|
* field can be found it defaults to 'ParentID'.
|
||||||
|
@ -183,6 +183,15 @@ class DataObjectTest extends SapphireTest {
|
|||||||
$this->assertEquals($this->idFromFixture('DataObjectTest_Team', 'team1'), $captain1->FavouriteTeamID);
|
$this->assertEquals($this->idFromFixture('DataObjectTest_Team', 'team1'), $captain1->FavouriteTeamID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function testGetRelationClass() {
|
||||||
|
$obj = new DataObjectTest_Player();
|
||||||
|
$this->assertEquals(singleton('DataObjectTest_Player')->getRelationClass('FavouriteTeam'), 'DataObjectTest_Team', 'has_one is properly inspected');
|
||||||
|
$this->assertEquals(singleton('DataObjectTest_Company')->getRelationClass('CurrentStaff'), 'DataObjectTest_Staff', 'has_many is properly inspected');
|
||||||
|
$this->assertEquals(singleton('DataObjectTest_Team')->getRelationClass('Players'), 'DataObjectTest_Player', 'many_many is properly inspected');
|
||||||
|
$this->assertEquals(singleton('DataObjectTest_Player')->getRelationClass('Teams'), 'DataObjectTest_Team', 'belongs_many_many is properly inspected');
|
||||||
|
$this->assertEquals(singleton('DataObjectTest_CEO')->getRelationClass('Company'), 'DataObjectTest_Company', 'belongs_to is properly inspected');
|
||||||
|
}
|
||||||
|
|
||||||
function testGetHasOneRelations() {
|
function testGetHasOneRelations() {
|
||||||
$captain1 = $this->objFromFixture("DataObjectTest_Player", "captain1");
|
$captain1 = $this->objFromFixture("DataObjectTest_Player", "captain1");
|
||||||
/* There will be a field called (relname)ID that contains the ID of the object linked to via the has_one relation */
|
/* There will be a field called (relname)ID that contains the ID of the object linked to via the has_one relation */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user