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
## Usage
To enable sorting on a data object add one of the following you your sites _config.php
*mysite/_config.php*
To enable sorting on a has_many relationship set up an interger field on your data object.
:::php
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
To enable drag and drop sorting on the grid field add the following to your grid field's config
*Grid Field Config*
:::php
$myGridConfig->addComponent(new GridFieldSortableRows());
## 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
$myGridConfig->addComponent(new GridFieldSortableRows('{Column to store sort}'));

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
*/
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.
* @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
$sortOrderToggle=new GridField_FormAction($gridField, 'sortablerows_toggle', 'Allow drag and drop re-ordering', 'saveGridRowSort', null);
$sortOrderToggle->addExtraClass('sortablerows_toggle');
//Disable Pagenator
if($gridField->getConfig()->getComponentByType('GridFieldPaginator')) {
$disablePagenator=new GridField_FormAction($gridField, 'sortablerows_disablepagenator', 'Disable Pagenator', 'sortableRowsDisablePaginator', null);
$disablePagenator->addExtraClass('sortablerows_disablepagenator');
}else {
$disablePagenator=null;
}
$forTemplate=new ArrayData(array(
'SortableToggle'=>$sortOrderToggle,
'PagenatorToggle'=>$disablePagenator,
'Checked'=>($state->sortableToggle==true ? ' checked="checked"':'')
));
//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())))
);
}
//Sort order toggle
$sortOrderToggle=new GridField_FormAction($gridField, 'sortablerows_toggle', 'Allow drag and drop re-ordering', 'saveGridRowSort', null);
$sortOrderToggle->addExtraClass('sortablerows_toggle');
//Disable Pagenator
$disablePagenator=new GridField_FormAction($gridField, 'sortablerows_disablepagenator', 'Disable Pagenator', 'sortableRowsDisablePaginator', null);
$disablePagenator->addExtraClass('sortablerows_disablepagenator');
$forTemplate=new ArrayData(array(
'SortableToggle'=>$sortOrderToggle,
'PagenatorToggle'=>$disablePagenator,
'Checked'=>($state->sortableToggle==true ? ' checked="checked"':'')
));
//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();
}
/**
* 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.
* @param GridField $gridField Grid Field Reference
* @return {array} Array with action identifier strings.
*/
public function getActions($gridField) {
if(Object::has_extension($gridField->getModelClass(), 'GridFieldSortableObject')) {
if($gridField->getConfig()->getComponentByType('GridFieldPaginator')) {
return array('saveGridRowSort', 'sortableRowsDisablePaginator');
}else {
return array('saveGridRowSort');
}
}
return array();
return array('saveGridRowSort', 'sortableRowsDisablePaginator');
}
/**
@ -88,10 +95,8 @@ class GridFieldSortableRows implements GridField_HTMLProvider, GridField_ActionP
}
if(Object::has_extension($gridField->getModelClass(), 'GridFieldSortableObject')) {
if($actionName=='savegridrowsort') {
return $this->saveGridRowSort($gridField, $data);
}
if($actionName=='savegridrowsort') {
return $this->saveGridRowSort($gridField, $data);
}
}
@ -106,25 +111,14 @@ class GridFieldSortableRows implements GridField_HTMLProvider, GridField_ActionP
}
$className=$gridField->getModelClass();
$ownerClass=$gridField->Form->Controller()->class;
$controllerID=$gridField->Form->Controller()->ID;
$owner=$gridField->Form->getRecord();
$items=$gridField->getList();
$many_many=($items instanceof ManyManyList);
$sortColumn=$this->sortColumn;
$many_many=GridFieldSortableObject::is_sortable_many_many($className);
if($many_many) {
$candidates=singleton($ownerClass)->many_many();
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);
list($parentClass, $componentClass, $parentField, $componentField, $table)=$owner->many_many($gridField->getName());
}
@ -132,10 +126,10 @@ class GridFieldSortableRows implements GridField_HTMLProvider, GridField_ActionP
for($sort=0;$sort<count($data['Items']);$sort++) {
$id=intval($data['Items'][$sort]);
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 {
$obj=DataObject::get_by_id($className, $id);
$obj->SortOrder=$sort+1;
$obj=$items->byID($data['Items'][$sort]);
$obj->$sortColumn=$sort+1;
$obj->write();
}
}