Removed GridFieldSortableObject this is now handled by the developer (see README.md)

GridFieldSortableRows now requires the developer to set the field to sort on

Cleaned up handling of many_many relationships
This commit is contained in:
UndefinedOffset 2012-05-10 11:27:01 -03:00
parent 7c68ec17da
commit 3b19642c26
3 changed files with 60 additions and 245 deletions

View File

@ -4,25 +4,10 @@ SortableGridField
Adds drag and drop functionality to SilverStripe 3.0's GridField Adds drag and drop functionality to SilverStripe 3.0's GridField
## Usage ## Usage
To enable sorting on a data object add one of the following you your sites _config.php To enable sorting on a has_many relationship set up an interger field on your data object.
*mysite/_config.php*
:::php To enable drag and drop sorting on the grid field add the following to your grid field's config
GridFieldSortableObject::add_sortable_class('{ClassName}'); //For has_many relationships
GridFieldSortableObject::add_sortable_many_many_relation('{Owner ClassName}', '{Component Name}'); //For many_many relationships
To enable sorting on the grid field add the following to your grid field's config
*Grid Field Config* *Grid Field Config*
:::php :::php
$myGridConfig->addComponent(new GridFieldSortableRows()); $myGridConfig->addComponent(new GridFieldSortableRows('{Column to store sort}'));
## Known Isuses
* Many_many relationship is largely untested and may not work as expected
## Credits
GridFieldSortableObject is based off of dataobject_manager's SortableDataObject class by @unclecheese

View File

@ -1,164 +0,0 @@
<?php
/**
* @package extensions
*/
class GridFieldSortableObject extends DataExtension {
public static $db=array(
'SortOrder'=>'Int'
);
protected static $sortable_classes = array();
protected static $many_many_sortable_relations = array();
protected static $sort_dir = "ASC";
/**
* Sets the direction of the sort, by default it is ASC
* @param {string} $dir Sort direction ASC or DESC
*/
public static function set_sort_dir($dir) {
if(strtoupper($dir)!='ASC' && strtoupper($dir)!='DESC') {
user_error('Sort direction must be ASC or DESC', E_USER_ERROR);
}
self::$sort_dir=$dir;
}
/**
* Makes a class sortable
* @param {string} $className Name of the DataObject to extend
*/
public static function add_sortable_class($className) {
if(!self::is_sortable_class($className)) {
Object::add_extension($className, 'GridFieldSortableObject');
self::$sortable_classes[]=$className;
}
}
/**
* Makes a many_many relationship sortable
* @param {string} $ownerClass Name of the owner class of the relationship
* @param {string} $componentName Name of the relationship
*/
public static function add_sortable_many_many_relation($ownerClass, $componentName) {
list($parentClass, $componentClass, $parentField, $componentField, $table)=singleton($ownerClass)->many_many($componentName);
Object::add_static_var($ownerClass, 'many_many_extraFields', array(
$componentName=>array(
'SortOrder'=>'Int'
)));
if(!isset(self::$many_many_sortable_relations[$componentClass])) {
self::$many_many_sortable_relations[$componentClass] = array();
}
self::$many_many_sortable_relations[$componentClass][$parentClass]=$table;
self::add_sortable_class($componentClass);
}
/**
* Checks to see if a given DataObject class is sortable or not
* @param {string} $className Name of the DataObject to check
*/
public static function is_sortable_class($className) {
if(in_array($className, self::$sortable_classes)) {
return true;
}
foreach(self::$sortable_classes as $class) {
if(is_subclass_of($className, $class)) {
return true;
}
}
return Object::has_extension($className, 'GridFieldSortableObject');
}
/**
* Checks to see if a given many_many relationship is sortable or not
* @param {string} $componentClass Name of the component's class
* @param {string} $parentClass Name of the owner class of the relationship
* @return {bool} Returns boolean true if the many_many relationship is sortable
*/
public static function is_sortable_many_many($componentClass, $parentClass=null) {
$map=self::$many_many_sortable_relations;
if($parentClass===null) {
return isset($map[$componentClass]);
}else {
if(isset($map[$componentClass])) {
return isset($map[$componentClass][$parentClass]);
}
return false;
}
}
/**
* Gets the join tables for the given class name
* @param {string} $className Name of the DataObject to fetch for
*/
public static function get_join_tables($className) {
if(isset(self::$many_many_sortable_relations[$className])) {
return self::$many_many_sortable_relations[$className];
}
return false;
}
/**
* Modifies the SQL appending the SortOrder with the direction to the orderby statement
* @param {SQLQuery} $query SQL Query to adjust
*/
public function augmentSQL(SQLQuery &$query) {
if(empty($query->select) || $query->delete || in_array("COUNT(*)", $query->select) || in_array("count(*)", $query->select)) {
return;
}
$sort_field=false;
if($join_tables=self::get_join_tables($this->owner->class)) {
foreach($query->from as $from) {
if($sort_field) {
break;
}
foreach($join_tables as $join_table) {
if(stristr($from,$join_table)) {
$sort_field="\"$join_table\".\"SortOrder\"";
if(isset($query->select['SortOrder'])) {
$query->select['SortOrder']="\"{$this->owner->class}\".SortOrder AS LocalSort";
}
break;
}
}
}
}
if(!$sort_field) {
$sort_field="\"SortOrder\"";
}
if(!$query->orderby || ($query->orderby==$this->owner->stat('default_sort'))) {
$query->orderby="$sort_field ".self::$sort_dir;
}
}
/**
* Sets the sort order on the DataObject when its being written to the database for the first time
*/
public function onBeforeWrite() {
if(!$this->owner->ID) {
if($peers=DataList::create($this->owner->class)) {
$this->owner->SortOrder=$peers->Count()+1;
}
}
}
}
?>

View File

@ -2,7 +2,16 @@
/** /**
* @package forms * @package forms
*/ */
class GridFieldSortableRows implements GridField_HTMLProvider, GridField_ActionProvider { class GridFieldSortableRows implements GridField_HTMLProvider, GridField_ActionProvider, GridField_DataManipulator {
protected $sortColumn;
/**
* @param {string} $sortColumn Column that should be used to update the sort information
*/
public function __construct($sortColumn) {
$this->sortColumn=$sortColumn;
}
/** /**
* Returns a map where the keys are fragment names and the values are pieces of HTML to add to these fragments. * Returns a map where the keys are fragment names and the values are pieces of HTML to add to these fragments.
* @param GridField $gridField Grid Field Reference * @param GridField $gridField Grid Field Reference
@ -16,54 +25,52 @@ class GridFieldSortableRows implements GridField_HTMLProvider, GridField_ActionP
if(Object::has_extension($gridField->getModelClass(), 'GridFieldSortableObject')) { //Sort order toggle
//Sort order toggle $sortOrderToggle=new GridField_FormAction($gridField, 'sortablerows_toggle', 'Allow drag and drop re-ordering', 'saveGridRowSort', null);
$sortOrderToggle=new GridField_FormAction($gridField, 'sortablerows_toggle', 'Allow drag and drop re-ordering', 'saveGridRowSort', null); $sortOrderToggle->addExtraClass('sortablerows_toggle');
$sortOrderToggle->addExtraClass('sortablerows_toggle');
//Disable Pagenator //Disable Pagenator
if($gridField->getConfig()->getComponentByType('GridFieldPaginator')) { $disablePagenator=new GridField_FormAction($gridField, 'sortablerows_disablepagenator', 'Disable Pagenator', 'sortableRowsDisablePaginator', null);
$disablePagenator=new GridField_FormAction($gridField, 'sortablerows_disablepagenator', 'Disable Pagenator', 'sortableRowsDisablePaginator', null); $disablePagenator->addExtraClass('sortablerows_disablepagenator');
$disablePagenator->addExtraClass('sortablerows_disablepagenator');
}else {
$disablePagenator=null; $forTemplate=new ArrayData(array(
} 'SortableToggle'=>$sortOrderToggle,
'PagenatorToggle'=>$disablePagenator,
$forTemplate=new ArrayData(array( 'Checked'=>($state->sortableToggle==true ? ' checked="checked"':'')
'SortableToggle'=>$sortOrderToggle, ));
'PagenatorToggle'=>$disablePagenator,
'Checked'=>($state->sortableToggle==true ? ' checked="checked"':'')
)); //Inject Requirements
Requirements::css('SortableGridField/css/GridFieldSortableRows.css');
Requirements::javascript('SortableGridField/javascript/GridFieldSortableRows.js');
//Inject Requirements
Requirements::css('SortableGridField/css/GridFieldSortableRows.css');
Requirements::javascript('SortableGridField/javascript/GridFieldSortableRows.js'); return array(
'header'=>$forTemplate->renderWith('GridFieldSortableRows', array('Colspan'=>count($gridField->getColumns())))
);
return array(
'header'=>$forTemplate->renderWith('GridFieldSortableRows', array('Colspan'=>count($gridField->getColumns())))
);
}
return array(); return array();
} }
/**
* Manipulate the datalist as needed by this grid modifier.
* @param {GridField} $gridField Grid Field Reference
* @param {SS_List} $dataList Data List to adjust
* @return {DataList} Modified Data List
*/
public function getManipulatedData(GridField $gridField, SS_List $dataList) {
return $dataList->sort($this->sortColumn);
}
/** /**
* Return a list of the actions handled by this action provider. * Return a list of the actions handled by this action provider.
* @param GridField $gridField Grid Field Reference * @param GridField $gridField Grid Field Reference
* @return {array} Array with action identifier strings. * @return {array} Array with action identifier strings.
*/ */
public function getActions($gridField) { public function getActions($gridField) {
if(Object::has_extension($gridField->getModelClass(), 'GridFieldSortableObject')) { return array('saveGridRowSort', 'sortableRowsDisablePaginator');
if($gridField->getConfig()->getComponentByType('GridFieldPaginator')) {
return array('saveGridRowSort', 'sortableRowsDisablePaginator');
}else {
return array('saveGridRowSort');
}
}
return array();
} }
/** /**
@ -88,10 +95,8 @@ class GridFieldSortableRows implements GridField_HTMLProvider, GridField_ActionP
} }
if(Object::has_extension($gridField->getModelClass(), 'GridFieldSortableObject')) { if($actionName=='savegridrowsort') {
if($actionName=='savegridrowsort') { return $this->saveGridRowSort($gridField, $data);
return $this->saveGridRowSort($gridField, $data);
}
} }
} }
@ -106,25 +111,14 @@ class GridFieldSortableRows implements GridField_HTMLProvider, GridField_ActionP
} }
$className=$gridField->getModelClass(); $className=$gridField->getModelClass();
$ownerClass=$gridField->Form->Controller()->class; $owner=$gridField->Form->getRecord();
$controllerID=$gridField->Form->Controller()->ID; $items=$gridField->getList();
$many_many=($items instanceof ManyManyList);
$sortColumn=$this->sortColumn;
$many_many=GridFieldSortableObject::is_sortable_many_many($className);
if($many_many) { if($many_many) {
$candidates=singleton($ownerClass)->many_many(); list($parentClass, $componentClass, $parentField, $componentField, $table)=$owner->many_many($gridField->getName());
if(is_array($candidates)) {
foreach($candidates as $name => $class)
if($class==$className) {
$relationName=$name;
break;
}
}
if(!isset($relationName)) {
return false;
}
list($parentClass, $componentClass, $parentField, $componentField, $table)=singleton($ownerClass)->many_many($relationName);
} }
@ -132,10 +126,10 @@ class GridFieldSortableRows implements GridField_HTMLProvider, GridField_ActionP
for($sort=0;$sort<count($data['Items']);$sort++) { for($sort=0;$sort<count($data['Items']);$sort++) {
$id=intval($data['Items'][$sort]); $id=intval($data['Items'][$sort]);
if($many_many) { if($many_many) {
DB::query('UPDATE "'.$table.'" SET "SortOrder" = '.($sort+1).' WHERE "'.$className.'ID" = $id AND "'.$ownerClass.'ID" = '.$controllerID); DB::query('UPDATE "'.$table.'" SET "'.$sortColumn.'"='.($sort+1).' WHERE "'.$componentField.'"='.$id.' AND "'.$parentField.'"='.$owner->ID);
}else { }else {
$obj=DataObject::get_by_id($className, $id); $obj=$items->byID($data['Items'][$sort]);
$obj->SortOrder=$sort+1; $obj->$sortColumn=$sort+1;
$obj->write(); $obj->write();
} }
} }