mirror of
https://github.com/symbiote/silverstripe-gridfieldextensions.git
synced 2024-10-22 15:05:39 +00:00
changing from windows line endings to linux line endings
This commit is contained in:
parent
381c6044ee
commit
9e3e51ebe2
@ -1,99 +1,99 @@
|
||||
<?php
|
||||
/**
|
||||
* A modal search dialog which uses search context to search for and add
|
||||
* existing records to a grid field.
|
||||
*/
|
||||
class GridFieldAddExistingSearchButton implements
|
||||
GridField_HTMLProvider,
|
||||
GridField_URLHandler {
|
||||
|
||||
private static $allowed_actions = array(
|
||||
'handleSearch'
|
||||
);
|
||||
|
||||
protected $title;
|
||||
protected $fragment;
|
||||
protected $searchList;
|
||||
|
||||
/**
|
||||
* @param string $fragment
|
||||
*/
|
||||
public function __construct($fragment = 'buttons-before-left') {
|
||||
$this->fragment = $fragment;
|
||||
$this->title = _t('GridFieldExtensions.ADDEXISTING', 'Add Existing');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getTitle() {
|
||||
return $this->title;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $title
|
||||
* @return GridFieldAddExistingSearchButton $this
|
||||
*/
|
||||
public function setTitle($title) {
|
||||
$this->title = $title;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getFragment() {
|
||||
return $this->fragment;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $fragment
|
||||
* @return GridFieldAddExistingSearchButton $this
|
||||
*/
|
||||
public function setFragment($fragment) {
|
||||
$this->fragment = $fragment;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a custom list to use to provide the searchable items.
|
||||
*
|
||||
* @param SS_List $list
|
||||
* @return GridFieldAddExistingSearchButton $this
|
||||
*/
|
||||
public function setSearchList(SS_List $list) {
|
||||
$this->searchList = $list;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return SS_List|null
|
||||
*/
|
||||
public function getSearchList() {
|
||||
return $this->searchList;
|
||||
}
|
||||
|
||||
public function getHTMLFragments($grid) {
|
||||
GridFieldExtensions::include_requirements();
|
||||
|
||||
$data = new ArrayData(array(
|
||||
'Title' => $this->getTitle(),
|
||||
'Link' => $grid->Link('add-existing-search')
|
||||
));
|
||||
|
||||
return array(
|
||||
$this->fragment => $data->renderWith('GridFieldAddExistingSearchButton'),
|
||||
);
|
||||
}
|
||||
|
||||
public function getURLHandlers($grid) {
|
||||
return array(
|
||||
'add-existing-search' => 'handleSearch'
|
||||
);
|
||||
}
|
||||
|
||||
public function handleSearch($grid, $request) {
|
||||
return new GridFieldAddExistingSearchHandler($grid, $this);
|
||||
}
|
||||
|
||||
}
|
||||
<?php
|
||||
/**
|
||||
* A modal search dialog which uses search context to search for and add
|
||||
* existing records to a grid field.
|
||||
*/
|
||||
class GridFieldAddExistingSearchButton implements
|
||||
GridField_HTMLProvider,
|
||||
GridField_URLHandler {
|
||||
|
||||
private static $allowed_actions = array(
|
||||
'handleSearch'
|
||||
);
|
||||
|
||||
protected $title;
|
||||
protected $fragment;
|
||||
protected $searchList;
|
||||
|
||||
/**
|
||||
* @param string $fragment
|
||||
*/
|
||||
public function __construct($fragment = 'buttons-before-left') {
|
||||
$this->fragment = $fragment;
|
||||
$this->title = _t('GridFieldExtensions.ADDEXISTING', 'Add Existing');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getTitle() {
|
||||
return $this->title;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $title
|
||||
* @return GridFieldAddExistingSearchButton $this
|
||||
*/
|
||||
public function setTitle($title) {
|
||||
$this->title = $title;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getFragment() {
|
||||
return $this->fragment;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $fragment
|
||||
* @return GridFieldAddExistingSearchButton $this
|
||||
*/
|
||||
public function setFragment($fragment) {
|
||||
$this->fragment = $fragment;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a custom list to use to provide the searchable items.
|
||||
*
|
||||
* @param SS_List $list
|
||||
* @return GridFieldAddExistingSearchButton $this
|
||||
*/
|
||||
public function setSearchList(SS_List $list) {
|
||||
$this->searchList = $list;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return SS_List|null
|
||||
*/
|
||||
public function getSearchList() {
|
||||
return $this->searchList;
|
||||
}
|
||||
|
||||
public function getHTMLFragments($grid) {
|
||||
GridFieldExtensions::include_requirements();
|
||||
|
||||
$data = new ArrayData(array(
|
||||
'Title' => $this->getTitle(),
|
||||
'Link' => $grid->Link('add-existing-search')
|
||||
));
|
||||
|
||||
return array(
|
||||
$this->fragment => $data->renderWith('GridFieldAddExistingSearchButton'),
|
||||
);
|
||||
}
|
||||
|
||||
public function getURLHandlers($grid) {
|
||||
return array(
|
||||
'add-existing-search' => 'handleSearch'
|
||||
);
|
||||
}
|
||||
|
||||
public function handleSearch($grid, $request) {
|
||||
return new GridFieldAddExistingSearchHandler($grid, $this);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,109 +1,109 @@
|
||||
<?php
|
||||
/**
|
||||
* Used by {@link GridFieldAddExistingSearchButton} to provide the searching
|
||||
* functionality.
|
||||
*/
|
||||
class GridFieldAddExistingSearchHandler extends RequestHandler {
|
||||
|
||||
private static $allowed_actions = array(
|
||||
'index',
|
||||
'add',
|
||||
'SearchForm'
|
||||
);
|
||||
|
||||
/**
|
||||
* @var GridField
|
||||
*/
|
||||
protected $grid;
|
||||
|
||||
/**
|
||||
* @var GridFieldAddExistingSearchButton
|
||||
*/
|
||||
protected $button;
|
||||
|
||||
/**
|
||||
* @var SearchContext
|
||||
*/
|
||||
protected $context;
|
||||
|
||||
public function __construct($grid, $button) {
|
||||
$this->grid = $grid;
|
||||
$this->button = $button;
|
||||
$this->context = singleton($grid->getModelClass())->getDefaultSearchContext();
|
||||
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
public function index() {
|
||||
return $this->renderWith('GridFieldAddExistingSearchHandler');
|
||||
}
|
||||
|
||||
public function add($request) {
|
||||
if(!$id = $request->postVar('id')) {
|
||||
$this->httpError(400);
|
||||
}
|
||||
|
||||
$list = $this->grid->getList();
|
||||
$item = DataList::create($list->dataClass())->byID($id);
|
||||
|
||||
if(!$item) {
|
||||
$this->httpError(400);
|
||||
}
|
||||
|
||||
$list->add($item);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Form
|
||||
*/
|
||||
public function SearchForm() {
|
||||
$form = new Form(
|
||||
$this,
|
||||
'SearchForm',
|
||||
$this->context->getFields(),
|
||||
new FieldList(
|
||||
FormAction::create('doSearch', _t('GridFieldExtensions.SEARCH', 'Search'))
|
||||
->setUseButtonTag(true)
|
||||
->addExtraClass('ss-ui-button')
|
||||
->setAttribute('data-icon', 'magnifier')
|
||||
)
|
||||
);
|
||||
|
||||
$form->addExtraClass('stacked add-existing-search-form');
|
||||
$form->setFormMethod('GET');
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
public function doSearch($data, $form) {
|
||||
$list = $this->context->getQuery($data, false, false, $this->getSearchList());
|
||||
$list = $list->subtract($this->grid->getList());
|
||||
$list = new PaginatedList($list, $this->request);
|
||||
|
||||
$data = $this->customise(array(
|
||||
'SearchForm' => $form,
|
||||
'Items' => $list
|
||||
));
|
||||
return $data->index();
|
||||
}
|
||||
|
||||
public function Items() {
|
||||
$list = $this->getSearchList();
|
||||
$list = $list->subtract($this->grid->getList());
|
||||
$list = new PaginatedList($list, $this->request);
|
||||
|
||||
return $list;
|
||||
}
|
||||
|
||||
public function Link($action = null) {
|
||||
return Controller::join_links($this->grid->Link(), 'add-existing-search', $action);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return DataList
|
||||
*/
|
||||
protected function getSearchList() {
|
||||
return $this->button->getSearchList() ?: DataList::create($this->grid->getList()->dataClass());
|
||||
}
|
||||
|
||||
}
|
||||
<?php
|
||||
/**
|
||||
* Used by {@link GridFieldAddExistingSearchButton} to provide the searching
|
||||
* functionality.
|
||||
*/
|
||||
class GridFieldAddExistingSearchHandler extends RequestHandler {
|
||||
|
||||
private static $allowed_actions = array(
|
||||
'index',
|
||||
'add',
|
||||
'SearchForm'
|
||||
);
|
||||
|
||||
/**
|
||||
* @var GridField
|
||||
*/
|
||||
protected $grid;
|
||||
|
||||
/**
|
||||
* @var GridFieldAddExistingSearchButton
|
||||
*/
|
||||
protected $button;
|
||||
|
||||
/**
|
||||
* @var SearchContext
|
||||
*/
|
||||
protected $context;
|
||||
|
||||
public function __construct($grid, $button) {
|
||||
$this->grid = $grid;
|
||||
$this->button = $button;
|
||||
$this->context = singleton($grid->getModelClass())->getDefaultSearchContext();
|
||||
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
public function index() {
|
||||
return $this->renderWith('GridFieldAddExistingSearchHandler');
|
||||
}
|
||||
|
||||
public function add($request) {
|
||||
if(!$id = $request->postVar('id')) {
|
||||
$this->httpError(400);
|
||||
}
|
||||
|
||||
$list = $this->grid->getList();
|
||||
$item = DataList::create($list->dataClass())->byID($id);
|
||||
|
||||
if(!$item) {
|
||||
$this->httpError(400);
|
||||
}
|
||||
|
||||
$list->add($item);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Form
|
||||
*/
|
||||
public function SearchForm() {
|
||||
$form = new Form(
|
||||
$this,
|
||||
'SearchForm',
|
||||
$this->context->getFields(),
|
||||
new FieldList(
|
||||
FormAction::create('doSearch', _t('GridFieldExtensions.SEARCH', 'Search'))
|
||||
->setUseButtonTag(true)
|
||||
->addExtraClass('ss-ui-button')
|
||||
->setAttribute('data-icon', 'magnifier')
|
||||
)
|
||||
);
|
||||
|
||||
$form->addExtraClass('stacked add-existing-search-form');
|
||||
$form->setFormMethod('GET');
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
public function doSearch($data, $form) {
|
||||
$list = $this->context->getQuery($data, false, false, $this->getSearchList());
|
||||
$list = $list->subtract($this->grid->getList());
|
||||
$list = new PaginatedList($list, $this->request);
|
||||
|
||||
$data = $this->customise(array(
|
||||
'SearchForm' => $form,
|
||||
'Items' => $list
|
||||
));
|
||||
return $data->index();
|
||||
}
|
||||
|
||||
public function Items() {
|
||||
$list = $this->getSearchList();
|
||||
$list = $list->subtract($this->grid->getList());
|
||||
$list = new PaginatedList($list, $this->request);
|
||||
|
||||
return $list;
|
||||
}
|
||||
|
||||
public function Link($action = null) {
|
||||
return Controller::join_links($this->grid->Link(), 'add-existing-search', $action);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return DataList
|
||||
*/
|
||||
protected function getSearchList() {
|
||||
return $this->button->getSearchList() ?: DataList::create($this->grid->getList()->dataClass());
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ class GridFieldAddNewMultiClass implements GridField_HTMLProvider, GridField_URL
|
||||
private static $allowed_actions = array(
|
||||
'handleAdd'
|
||||
);
|
||||
|
||||
|
||||
// Should we add an empty string to the add class dropdown?
|
||||
private static $showEmptyString = true;
|
||||
|
||||
@ -19,7 +19,7 @@ class GridFieldAddNewMultiClass implements GridField_HTMLProvider, GridField_URL
|
||||
private $title;
|
||||
|
||||
private $classes;
|
||||
|
||||
|
||||
private $defaultClass;
|
||||
|
||||
/**
|
||||
@ -128,7 +128,7 @@ class GridFieldAddNewMultiClass implements GridField_HTMLProvider, GridField_URL
|
||||
*/
|
||||
public function setDefaultClass($default) {
|
||||
$this->defaultClass = $default;
|
||||
return $this;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,403 +1,403 @@
|
||||
<?php
|
||||
/**
|
||||
* Allows grid field rows to be re-ordered via drag and drop. Both normal data
|
||||
* lists and many many lists can be ordered.
|
||||
*
|
||||
* If the grid field has not been sorted, this component will sort the data by
|
||||
* the sort field.
|
||||
*/
|
||||
class GridFieldOrderableRows extends RequestHandler implements
|
||||
GridField_ColumnProvider,
|
||||
GridField_DataManipulator,
|
||||
GridField_HTMLProvider,
|
||||
GridField_URLHandler {
|
||||
|
||||
private static $allowed_actions = array(
|
||||
'handleReorder',
|
||||
'handleMoveToPage'
|
||||
);
|
||||
|
||||
/**
|
||||
* The database field which specifies the sort, defaults to "Sort".
|
||||
*
|
||||
* @see setSortField()
|
||||
* @var string
|
||||
*/
|
||||
protected $sortField;
|
||||
|
||||
/**
|
||||
* Extra sort fields to apply before the sort field.
|
||||
*
|
||||
* @see setExtraSortFields()
|
||||
* @var string|array
|
||||
*/
|
||||
protected $extraSortFields = null;
|
||||
|
||||
/**
|
||||
* The number of the column containing the reorder handles
|
||||
*
|
||||
* @see setReorderColumnNumber()
|
||||
* @var integer
|
||||
*/
|
||||
protected $reorderColumnNumber = 0;
|
||||
|
||||
/**
|
||||
* @param string $sortField
|
||||
*/
|
||||
public function __construct($sortField = 'Sort') {
|
||||
$this->sortField = $sortField;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getSortField() {
|
||||
return $this->sortField;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the field used to specify the sort.
|
||||
*
|
||||
* @param string $sortField
|
||||
* @return GridFieldOrderableRows $this
|
||||
*/
|
||||
public function setSortField($field) {
|
||||
$this->sortField = $field;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string|array
|
||||
*/
|
||||
public function getExtraSortFields() {
|
||||
return $this->extraSortFields;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets extra sort fields to apply before the sort field.
|
||||
*
|
||||
* @param string|array $fields
|
||||
* @return GridFieldOrderableRows $this
|
||||
*/
|
||||
public function setExtraSortFields($fields) {
|
||||
$this->extraSortFields = $fields;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return integer
|
||||
*/
|
||||
public function getReorderColumnNumber() {
|
||||
return $this->reorderColumnNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the number of the column containing the reorder handles.
|
||||
*
|
||||
* @param integer $colno
|
||||
* @return GridFieldOrderableRows $this
|
||||
*/
|
||||
public function setReorderColumnNumber($colno) {
|
||||
$this->reorderColumnNumber = $colno;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the table which contains the sort field.
|
||||
*
|
||||
* @param DataList $list
|
||||
* @return string
|
||||
*/
|
||||
public function getSortTable(DataList $list) {
|
||||
$field = $this->getSortField();
|
||||
|
||||
if($list instanceof ManyManyList) {
|
||||
$extra = $list->getExtraFields();
|
||||
$table = $list->getJoinTable();
|
||||
|
||||
if($extra && array_key_exists($field, $extra)) {
|
||||
return $table;
|
||||
}
|
||||
}
|
||||
|
||||
$classes = ClassInfo::dataClassesFor($list->dataClass());
|
||||
|
||||
foreach($classes as $class) {
|
||||
if(singleton($class)->hasOwnTableDatabaseField($field)) {
|
||||
return $class;
|
||||
}
|
||||
}
|
||||
|
||||
throw new Exception("Couldn't find the sort field '$field'");
|
||||
}
|
||||
|
||||
public function getURLHandlers($grid) {
|
||||
return array(
|
||||
'POST reorder' => 'handleReorder',
|
||||
'POST movetopage' => 'handleMoveToPage'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param GridField $field
|
||||
*/
|
||||
public function getHTMLFragments($field) {
|
||||
GridFieldExtensions::include_requirements();
|
||||
|
||||
$field->addExtraClass('ss-gridfield-orderable');
|
||||
$field->setAttribute('data-url-reorder', $field->Link('reorder'));
|
||||
$field->setAttribute('data-url-movetopage', $field->Link('movetopage'));
|
||||
}
|
||||
|
||||
public function augmentColumns($grid, &$cols) {
|
||||
if(!in_array('Reorder', $cols) && $grid->getState()->GridFieldOrderableRows->enabled) {
|
||||
array_splice($cols, $this->reorderColumnNumber, 0, 'Reorder');
|
||||
}
|
||||
}
|
||||
|
||||
public function getColumnsHandled($grid) {
|
||||
return array('Reorder');
|
||||
}
|
||||
|
||||
public function getColumnContent($grid, $record, $col) {
|
||||
return ViewableData::create()->renderWith('GridFieldOrderableRowsDragHandle');
|
||||
}
|
||||
|
||||
public function getColumnAttributes($grid, $record, $col) {
|
||||
return array('class' => 'col-reorder');
|
||||
}
|
||||
|
||||
public function getColumnMetadata($grid, $col) {
|
||||
return array('title' => '');
|
||||
}
|
||||
|
||||
public function getManipulatedData(GridField $grid, SS_List $list) {
|
||||
$state = $grid->getState();
|
||||
$sorted = (bool) ((string) $state->GridFieldSortableHeader->SortColumn);
|
||||
|
||||
// If the data has not been sorted by the user, then sort it by the
|
||||
// sort column, otherwise disable reordering.
|
||||
$state->GridFieldOrderableRows->enabled = !$sorted;
|
||||
|
||||
if(!$sorted) {
|
||||
$sortterm = '';
|
||||
if ($this->extraSortFields) {
|
||||
if (is_array($this->extraSortFields)) {
|
||||
foreach($this->extraSortFields as $col => $dir) {
|
||||
$sortterm .= "$col $dir, ";
|
||||
}
|
||||
} else {
|
||||
$sortterm = $this->extraSortFields.', ';
|
||||
}
|
||||
}
|
||||
$sortterm .= '"'.$this->getSortTable($list).'"."'.$this->getSortField().'"';
|
||||
return $list->sort($sortterm);
|
||||
} else {
|
||||
return $list;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles requests to reorder a set of IDs in a specific order.
|
||||
*
|
||||
* @param GridField $grid
|
||||
* @param SS_HTTPRequest $request
|
||||
* @return SS_HTTPResponse
|
||||
*/
|
||||
public function handleReorder($grid, $request) {
|
||||
$list = $grid->getList();
|
||||
$modelClass = $grid->getModelClass();
|
||||
if ($list instanceof ManyManyList && !singleton($modelClass)->canView()) {
|
||||
$this->httpError(403);
|
||||
} else if(!($list instanceof ManyManyList) && !singleton($modelClass)->canEdit()) {
|
||||
$this->httpError(403);
|
||||
}
|
||||
|
||||
$ids = $request->postVar('order');
|
||||
$field = $this->getSortField();
|
||||
|
||||
if(!is_array($ids)) {
|
||||
$this->httpError(400);
|
||||
}
|
||||
|
||||
$sortterm = '';
|
||||
if ($this->extraSortFields) {
|
||||
if (is_array($this->extraSortFields)) {
|
||||
foreach($this->extraSortFields as $col => $dir) {
|
||||
$sortterm .= "$col $dir, ";
|
||||
}
|
||||
} else {
|
||||
$sortterm = $this->extraSortFields.', ';
|
||||
}
|
||||
}
|
||||
$sortterm .= '"'.$this->getSortTable($list).'"."'.$field.'"';
|
||||
$items = $list->filter('ID', $ids)->sort($sortterm);
|
||||
|
||||
// Ensure that each provided ID corresponded to an actual object.
|
||||
if(count($items) != count($ids)) {
|
||||
$this->httpError(404);
|
||||
}
|
||||
|
||||
// Save any un-comitted changes to the gridfield
|
||||
if(($form = $grid->getForm()) && ($record = $form->getRecord()) ) {
|
||||
$form->loadDataFrom($request->requestVars(), true);
|
||||
$grid->saveInto($record);
|
||||
}
|
||||
|
||||
// Populate each object we are sorting with a sort value.
|
||||
$this->populateSortValues($items);
|
||||
|
||||
// Generate the current sort values.
|
||||
if ($items instanceof ManyManyList)
|
||||
{
|
||||
$current = array();
|
||||
foreach ($items->toArray() as $record)
|
||||
{
|
||||
// NOTE: _SortColumn0 is the first ->sort() field
|
||||
// used by SS when functions are detected in a SELECT
|
||||
// or CASE WHEN.
|
||||
if (isset($record->_SortColumn0)) {
|
||||
$current[$record->ID] = $record->_SortColumn0;
|
||||
} else {
|
||||
$current[$record->ID] = $record->$field;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$current = $items->map('ID', $field)->toArray();
|
||||
}
|
||||
|
||||
// Perform the actual re-ordering.
|
||||
$this->reorderItems($list, $current, $ids);
|
||||
|
||||
return $grid->FieldHolder();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles requests to move an item to the previous or next page.
|
||||
*/
|
||||
public function handleMoveToPage(GridField $grid, $request) {
|
||||
if(!$paginator = $grid->getConfig()->getComponentByType('GridFieldPaginator')) {
|
||||
$this->httpError(404, 'Paginator component not found');
|
||||
}
|
||||
|
||||
$move = $request->postVar('move');
|
||||
$field = $this->getSortField();
|
||||
|
||||
$list = $grid->getList();
|
||||
$manip = $grid->getManipulatedList();
|
||||
|
||||
$existing = $manip->map('ID', $field)->toArray();
|
||||
$values = $existing;
|
||||
$order = array();
|
||||
|
||||
$id = isset($move['id']) ? (int) $move['id'] : null;
|
||||
$to = isset($move['page']) ? $move['page'] : null;
|
||||
|
||||
if(!isset($values[$id])) {
|
||||
$this->httpError(400, 'Invalid item ID');
|
||||
}
|
||||
|
||||
$this->populateSortValues($list);
|
||||
|
||||
$page = ((int) $grid->getState()->GridFieldPaginator->currentPage) ?: 1;
|
||||
$per = $paginator->getItemsPerPage();
|
||||
|
||||
if($to == 'prev') {
|
||||
$swap = $list->limit(1, ($page - 1) * $per - 1)->first();
|
||||
$values[$swap->ID] = $swap->$field;
|
||||
|
||||
$order[] = $id;
|
||||
$order[] = $swap->ID;
|
||||
|
||||
foreach($existing as $_id => $sort) {
|
||||
if($id != $_id) $order[] = $_id;
|
||||
}
|
||||
} elseif($to == 'next') {
|
||||
$swap = $list->limit(1, $page * $per)->first();
|
||||
$values[$swap->ID] = $swap->$field;
|
||||
|
||||
foreach($existing as $_id => $sort) {
|
||||
if($id != $_id) $order[] = $_id;
|
||||
}
|
||||
|
||||
$order[] = $swap->ID;
|
||||
$order[] = $id;
|
||||
} else {
|
||||
$this->httpError(400, 'Invalid page target');
|
||||
}
|
||||
|
||||
$this->reorderItems($list, $values, $order);
|
||||
|
||||
return $grid->FieldHolder();
|
||||
}
|
||||
|
||||
protected function reorderItems($list, array $values, array $order) {
|
||||
// Get a list of sort values that can be used.
|
||||
$pool = array_values($values);
|
||||
sort($pool);
|
||||
|
||||
// Loop through each item, and update the sort values which do not
|
||||
// match to order the objects.
|
||||
foreach(array_values($order) as $pos => $id) {
|
||||
if($values[$id] != $pool[$pos]) {
|
||||
DB::query(sprintf(
|
||||
'UPDATE "%s" SET "%s" = %d WHERE %s',
|
||||
$this->getSortTable($list),
|
||||
$this->getSortField(),
|
||||
$pool[$pos],
|
||||
$this->getSortTableClauseForIds($list, $id)
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function populateSortValues(DataList $list) {
|
||||
$list = clone $list;
|
||||
$field = $this->getSortField();
|
||||
$table = $this->getSortTable($list);
|
||||
$clause = sprintf('"%s"."%s" = 0', $table, $this->getSortField());
|
||||
|
||||
foreach($list->where($clause)->column('ID') as $id) {
|
||||
$max = DB::query(sprintf('SELECT MAX("%s") + 1 FROM "%s"', $field, $table));
|
||||
$max = $max->value();
|
||||
|
||||
DB::query(sprintf(
|
||||
'UPDATE "%s" SET "%s" = %d WHERE %s',
|
||||
$table,
|
||||
$field,
|
||||
$max,
|
||||
$this->getSortTableClauseForIds($list, $id)
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
protected function getSortTableClauseForIds(DataList $list, $ids) {
|
||||
if(is_array($ids)) {
|
||||
$value = 'IN (' . implode(', ', array_map('intval', $ids)) . ')';
|
||||
} else {
|
||||
$value = '= ' . (int) $ids;
|
||||
}
|
||||
|
||||
if($list instanceof ManyManyList) {
|
||||
$extra = $list->getExtraFields();
|
||||
$key = $list->getLocalKey();
|
||||
$foreignKey = $list->getForeignKey();
|
||||
$foreignID = (int) $list->getForeignID();
|
||||
|
||||
if($extra && array_key_exists($this->getSortField(), $extra)) {
|
||||
return sprintf(
|
||||
'"%s" %s AND "%s" = %d',
|
||||
$key,
|
||||
$value,
|
||||
$foreignKey,
|
||||
$foreignID
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return "\"ID\" $value";
|
||||
}
|
||||
|
||||
}
|
||||
<?php
|
||||
/**
|
||||
* Allows grid field rows to be re-ordered via drag and drop. Both normal data
|
||||
* lists and many many lists can be ordered.
|
||||
*
|
||||
* If the grid field has not been sorted, this component will sort the data by
|
||||
* the sort field.
|
||||
*/
|
||||
class GridFieldOrderableRows extends RequestHandler implements
|
||||
GridField_ColumnProvider,
|
||||
GridField_DataManipulator,
|
||||
GridField_HTMLProvider,
|
||||
GridField_URLHandler {
|
||||
|
||||
private static $allowed_actions = array(
|
||||
'handleReorder',
|
||||
'handleMoveToPage'
|
||||
);
|
||||
|
||||
/**
|
||||
* The database field which specifies the sort, defaults to "Sort".
|
||||
*
|
||||
* @see setSortField()
|
||||
* @var string
|
||||
*/
|
||||
protected $sortField;
|
||||
|
||||
/**
|
||||
* Extra sort fields to apply before the sort field.
|
||||
*
|
||||
* @see setExtraSortFields()
|
||||
* @var string|array
|
||||
*/
|
||||
protected $extraSortFields = null;
|
||||
|
||||
/**
|
||||
* The number of the column containing the reorder handles
|
||||
*
|
||||
* @see setReorderColumnNumber()
|
||||
* @var integer
|
||||
*/
|
||||
protected $reorderColumnNumber = 0;
|
||||
|
||||
/**
|
||||
* @param string $sortField
|
||||
*/
|
||||
public function __construct($sortField = 'Sort') {
|
||||
$this->sortField = $sortField;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getSortField() {
|
||||
return $this->sortField;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the field used to specify the sort.
|
||||
*
|
||||
* @param string $sortField
|
||||
* @return GridFieldOrderableRows $this
|
||||
*/
|
||||
public function setSortField($field) {
|
||||
$this->sortField = $field;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string|array
|
||||
*/
|
||||
public function getExtraSortFields() {
|
||||
return $this->extraSortFields;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets extra sort fields to apply before the sort field.
|
||||
*
|
||||
* @param string|array $fields
|
||||
* @return GridFieldOrderableRows $this
|
||||
*/
|
||||
public function setExtraSortFields($fields) {
|
||||
$this->extraSortFields = $fields;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return integer
|
||||
*/
|
||||
public function getReorderColumnNumber() {
|
||||
return $this->reorderColumnNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the number of the column containing the reorder handles.
|
||||
*
|
||||
* @param integer $colno
|
||||
* @return GridFieldOrderableRows $this
|
||||
*/
|
||||
public function setReorderColumnNumber($colno) {
|
||||
$this->reorderColumnNumber = $colno;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the table which contains the sort field.
|
||||
*
|
||||
* @param DataList $list
|
||||
* @return string
|
||||
*/
|
||||
public function getSortTable(DataList $list) {
|
||||
$field = $this->getSortField();
|
||||
|
||||
if($list instanceof ManyManyList) {
|
||||
$extra = $list->getExtraFields();
|
||||
$table = $list->getJoinTable();
|
||||
|
||||
if($extra && array_key_exists($field, $extra)) {
|
||||
return $table;
|
||||
}
|
||||
}
|
||||
|
||||
$classes = ClassInfo::dataClassesFor($list->dataClass());
|
||||
|
||||
foreach($classes as $class) {
|
||||
if(singleton($class)->hasOwnTableDatabaseField($field)) {
|
||||
return $class;
|
||||
}
|
||||
}
|
||||
|
||||
throw new Exception("Couldn't find the sort field '$field'");
|
||||
}
|
||||
|
||||
public function getURLHandlers($grid) {
|
||||
return array(
|
||||
'POST reorder' => 'handleReorder',
|
||||
'POST movetopage' => 'handleMoveToPage'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param GridField $field
|
||||
*/
|
||||
public function getHTMLFragments($field) {
|
||||
GridFieldExtensions::include_requirements();
|
||||
|
||||
$field->addExtraClass('ss-gridfield-orderable');
|
||||
$field->setAttribute('data-url-reorder', $field->Link('reorder'));
|
||||
$field->setAttribute('data-url-movetopage', $field->Link('movetopage'));
|
||||
}
|
||||
|
||||
public function augmentColumns($grid, &$cols) {
|
||||
if(!in_array('Reorder', $cols) && $grid->getState()->GridFieldOrderableRows->enabled) {
|
||||
array_splice($cols, $this->reorderColumnNumber, 0, 'Reorder');
|
||||
}
|
||||
}
|
||||
|
||||
public function getColumnsHandled($grid) {
|
||||
return array('Reorder');
|
||||
}
|
||||
|
||||
public function getColumnContent($grid, $record, $col) {
|
||||
return ViewableData::create()->renderWith('GridFieldOrderableRowsDragHandle');
|
||||
}
|
||||
|
||||
public function getColumnAttributes($grid, $record, $col) {
|
||||
return array('class' => 'col-reorder');
|
||||
}
|
||||
|
||||
public function getColumnMetadata($grid, $col) {
|
||||
return array('title' => '');
|
||||
}
|
||||
|
||||
public function getManipulatedData(GridField $grid, SS_List $list) {
|
||||
$state = $grid->getState();
|
||||
$sorted = (bool) ((string) $state->GridFieldSortableHeader->SortColumn);
|
||||
|
||||
// If the data has not been sorted by the user, then sort it by the
|
||||
// sort column, otherwise disable reordering.
|
||||
$state->GridFieldOrderableRows->enabled = !$sorted;
|
||||
|
||||
if(!$sorted) {
|
||||
$sortterm = '';
|
||||
if ($this->extraSortFields) {
|
||||
if (is_array($this->extraSortFields)) {
|
||||
foreach($this->extraSortFields as $col => $dir) {
|
||||
$sortterm .= "$col $dir, ";
|
||||
}
|
||||
} else {
|
||||
$sortterm = $this->extraSortFields.', ';
|
||||
}
|
||||
}
|
||||
$sortterm .= '"'.$this->getSortTable($list).'"."'.$this->getSortField().'"';
|
||||
return $list->sort($sortterm);
|
||||
} else {
|
||||
return $list;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles requests to reorder a set of IDs in a specific order.
|
||||
*
|
||||
* @param GridField $grid
|
||||
* @param SS_HTTPRequest $request
|
||||
* @return SS_HTTPResponse
|
||||
*/
|
||||
public function handleReorder($grid, $request) {
|
||||
$list = $grid->getList();
|
||||
$modelClass = $grid->getModelClass();
|
||||
if ($list instanceof ManyManyList && !singleton($modelClass)->canView()) {
|
||||
$this->httpError(403);
|
||||
} else if(!($list instanceof ManyManyList) && !singleton($modelClass)->canEdit()) {
|
||||
$this->httpError(403);
|
||||
}
|
||||
|
||||
$ids = $request->postVar('order');
|
||||
$field = $this->getSortField();
|
||||
|
||||
if(!is_array($ids)) {
|
||||
$this->httpError(400);
|
||||
}
|
||||
|
||||
$sortterm = '';
|
||||
if ($this->extraSortFields) {
|
||||
if (is_array($this->extraSortFields)) {
|
||||
foreach($this->extraSortFields as $col => $dir) {
|
||||
$sortterm .= "$col $dir, ";
|
||||
}
|
||||
} else {
|
||||
$sortterm = $this->extraSortFields.', ';
|
||||
}
|
||||
}
|
||||
$sortterm .= '"'.$this->getSortTable($list).'"."'.$field.'"';
|
||||
$items = $list->filter('ID', $ids)->sort($sortterm);
|
||||
|
||||
// Ensure that each provided ID corresponded to an actual object.
|
||||
if(count($items) != count($ids)) {
|
||||
$this->httpError(404);
|
||||
}
|
||||
|
||||
// Save any un-comitted changes to the gridfield
|
||||
if(($form = $grid->getForm()) && ($record = $form->getRecord()) ) {
|
||||
$form->loadDataFrom($request->requestVars(), true);
|
||||
$grid->saveInto($record);
|
||||
}
|
||||
|
||||
// Populate each object we are sorting with a sort value.
|
||||
$this->populateSortValues($items);
|
||||
|
||||
// Generate the current sort values.
|
||||
if ($items instanceof ManyManyList)
|
||||
{
|
||||
$current = array();
|
||||
foreach ($items->toArray() as $record)
|
||||
{
|
||||
// NOTE: _SortColumn0 is the first ->sort() field
|
||||
// used by SS when functions are detected in a SELECT
|
||||
// or CASE WHEN.
|
||||
if (isset($record->_SortColumn0)) {
|
||||
$current[$record->ID] = $record->_SortColumn0;
|
||||
} else {
|
||||
$current[$record->ID] = $record->$field;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$current = $items->map('ID', $field)->toArray();
|
||||
}
|
||||
|
||||
// Perform the actual re-ordering.
|
||||
$this->reorderItems($list, $current, $ids);
|
||||
|
||||
return $grid->FieldHolder();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles requests to move an item to the previous or next page.
|
||||
*/
|
||||
public function handleMoveToPage(GridField $grid, $request) {
|
||||
if(!$paginator = $grid->getConfig()->getComponentByType('GridFieldPaginator')) {
|
||||
$this->httpError(404, 'Paginator component not found');
|
||||
}
|
||||
|
||||
$move = $request->postVar('move');
|
||||
$field = $this->getSortField();
|
||||
|
||||
$list = $grid->getList();
|
||||
$manip = $grid->getManipulatedList();
|
||||
|
||||
$existing = $manip->map('ID', $field)->toArray();
|
||||
$values = $existing;
|
||||
$order = array();
|
||||
|
||||
$id = isset($move['id']) ? (int) $move['id'] : null;
|
||||
$to = isset($move['page']) ? $move['page'] : null;
|
||||
|
||||
if(!isset($values[$id])) {
|
||||
$this->httpError(400, 'Invalid item ID');
|
||||
}
|
||||
|
||||
$this->populateSortValues($list);
|
||||
|
||||
$page = ((int) $grid->getState()->GridFieldPaginator->currentPage) ?: 1;
|
||||
$per = $paginator->getItemsPerPage();
|
||||
|
||||
if($to == 'prev') {
|
||||
$swap = $list->limit(1, ($page - 1) * $per - 1)->first();
|
||||
$values[$swap->ID] = $swap->$field;
|
||||
|
||||
$order[] = $id;
|
||||
$order[] = $swap->ID;
|
||||
|
||||
foreach($existing as $_id => $sort) {
|
||||
if($id != $_id) $order[] = $_id;
|
||||
}
|
||||
} elseif($to == 'next') {
|
||||
$swap = $list->limit(1, $page * $per)->first();
|
||||
$values[$swap->ID] = $swap->$field;
|
||||
|
||||
foreach($existing as $_id => $sort) {
|
||||
if($id != $_id) $order[] = $_id;
|
||||
}
|
||||
|
||||
$order[] = $swap->ID;
|
||||
$order[] = $id;
|
||||
} else {
|
||||
$this->httpError(400, 'Invalid page target');
|
||||
}
|
||||
|
||||
$this->reorderItems($list, $values, $order);
|
||||
|
||||
return $grid->FieldHolder();
|
||||
}
|
||||
|
||||
protected function reorderItems($list, array $values, array $order) {
|
||||
// Get a list of sort values that can be used.
|
||||
$pool = array_values($values);
|
||||
sort($pool);
|
||||
|
||||
// Loop through each item, and update the sort values which do not
|
||||
// match to order the objects.
|
||||
foreach(array_values($order) as $pos => $id) {
|
||||
if($values[$id] != $pool[$pos]) {
|
||||
DB::query(sprintf(
|
||||
'UPDATE "%s" SET "%s" = %d WHERE %s',
|
||||
$this->getSortTable($list),
|
||||
$this->getSortField(),
|
||||
$pool[$pos],
|
||||
$this->getSortTableClauseForIds($list, $id)
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function populateSortValues(DataList $list) {
|
||||
$list = clone $list;
|
||||
$field = $this->getSortField();
|
||||
$table = $this->getSortTable($list);
|
||||
$clause = sprintf('"%s"."%s" = 0', $table, $this->getSortField());
|
||||
|
||||
foreach($list->where($clause)->column('ID') as $id) {
|
||||
$max = DB::query(sprintf('SELECT MAX("%s") + 1 FROM "%s"', $field, $table));
|
||||
$max = $max->value();
|
||||
|
||||
DB::query(sprintf(
|
||||
'UPDATE "%s" SET "%s" = %d WHERE %s',
|
||||
$table,
|
||||
$field,
|
||||
$max,
|
||||
$this->getSortTableClauseForIds($list, $id)
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
protected function getSortTableClauseForIds(DataList $list, $ids) {
|
||||
if(is_array($ids)) {
|
||||
$value = 'IN (' . implode(', ', array_map('intval', $ids)) . ')';
|
||||
} else {
|
||||
$value = '= ' . (int) $ids;
|
||||
}
|
||||
|
||||
if($list instanceof ManyManyList) {
|
||||
$extra = $list->getExtraFields();
|
||||
$key = $list->getLocalKey();
|
||||
$foreignKey = $list->getForeignKey();
|
||||
$foreignID = (int) $list->getForeignID();
|
||||
|
||||
if($extra && array_key_exists($this->getSortField(), $extra)) {
|
||||
return sprintf(
|
||||
'"%s" %s AND "%s" = %d',
|
||||
$key,
|
||||
$value,
|
||||
$foreignKey,
|
||||
$foreignID
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return "\"ID\" $value";
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user