From 8b805471449897edd0c5943a35167929863ae74b Mon Sep 17 00:00:00 2001 From: Reece Date: Sat, 27 May 2017 14:46:40 +1000 Subject: [PATCH] SS4 Compliance & Updated Tests --- src/Forms/GridFieldSortableRows.php | 1425 +++++++++-------- .../GridFieldSortableRowsAutoSortTest.php | 588 ++++--- .../GridFieldSortableRowsAutoSortTest.yml | 72 +- tests/forms/GridFieldSortableRowsPageTest.php | 380 +++-- tests/forms/GridFieldSortableRowsPageTest.yml | 148 +- tests/forms/GridFieldSortableRowsTest.php | 246 +-- tests/forms/GridFieldSortableRowsTest.yml | 52 +- 7 files changed, 1604 insertions(+), 1307 deletions(-) diff --git a/src/Forms/GridFieldSortableRows.php b/src/Forms/GridFieldSortableRows.php index e8c6020..fff21db 100644 --- a/src/Forms/GridFieldSortableRows.php +++ b/src/Forms/GridFieldSortableRows.php @@ -1,681 +1,766 @@ sortColumn = $sortColumn; - $this->disable_selection = $disableSelection; - $this->update_versioned_stage = $updateVersionStage; - $this->custom_relation_name = $customRelationName; - } - - /** - * 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 - * @return Array Map where the keys are fragment names and the values are pieces of HTML to add to these fragments. - */ - public function getHTMLFragments($gridField) { - $dataList = $gridField->getList(); + /** @var bool */ + protected $disable_selection = true; - if(class_exists('UnsavedRelationList') && $dataList instanceof UnsavedRelationList) { - return array(); - } - - $state = $gridField->State->GridFieldSortableRows; - if(!is_bool($state->sortableToggle)) { - $state->sortableToggle = false; - } - - //Ensure user can edit - if(!singleton($gridField->getModelClass())->canEdit()){ - return array(); - } - - - //Sort order toggle - $sortOrderToggle = GridField_FormAction::create( - $gridField, - 'sortablerows-toggle', - 'sorttoggle', - 'sortableRowsToggle', - null - )->addExtraClass('sortablerows-toggle'); - - - $sortOrderSave = GridField_FormAction::create( - $gridField, - 'sortablerows-savesort', - 'savesort', - 'saveGridRowSort', - null - )->addExtraClass('sortablerows-savesort'); - - - //Sort to Page Action - $sortToPage = GridField_FormAction::create( - $gridField, - 'sortablerows-sorttopage', - 'sorttopage', - 'sortToPage', - null - )->addExtraClass('sortablerows-sorttopage'); - - - $data = array('SortableToggle' => $sortOrderToggle, - 'SortOrderSave' => $sortOrderSave, - 'SortToPage' => $sortToPage, - 'Checked' => ($state->sortableToggle == true ? ' checked = "checked"':''), - 'List' => $dataList); - - $forTemplate = new ArrayData($data); - - - //Inject Requirements - $custom = Config::inst()->get('GridFieldSortableRows', 'Base'); - $base = $custom ?: SORTABLE_GRIDFIELD_BASE; + /** @var bool */ + protected $append_to_top = false; - Requirements::css($base . '/css/GridFieldSortableRows.css'); - Requirements::javascript($base . '/javascript/GridFieldSortableRows.js'); - - - $args = array('Colspan' => count($gridField->getColumns()), 'ID' => $gridField->ID(), 'DisableSelection' => $this->disable_selection); - - - $fragments=array('header' => $forTemplate->renderWith('GridFieldSortableRows', $args)); - - if($gridField->getConfig()->getComponentByType('GridFieldPaginator')) { - $fragments['after']=$forTemplate->renderWith('GridFieldSortableRows_paginator'); - } - - return $fragments; - } - - /** - * 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) { - //Detect and correct items with a sort column value of 0 (push to bottom) - $this->fixSortColumn($gridField, $dataList); - - - $headerState = $gridField->State->GridFieldSortableHeader; - $state = $gridField->State->GridFieldSortableRows; - if ((!is_bool($state->sortableToggle) || $state->sortableToggle===false) && $headerState && is_string($headerState->SortColumn) && is_string($headerState->SortDirection)) { - return $dataList->sort($headerState->SortColumn, $headerState->SortDirection); - } - - if ($state->sortableToggle === true) { - $gridField->getConfig()->removeComponentsByType('GridFieldFilterHeader'); - $gridField->getConfig()->removeComponentsByType('GridFieldSortableHeader'); - } - - return $dataList->sort($this->sortColumn); - } - - /** - * Sets if new records should be appended to the top or the bottom of the list - * @param bool $value Boolean true to append to the top false to append to the bottom - * @return GridFieldSortableRows Returns the current instance - */ - public function setAppendToTop($value) { - $this->append_to_top=$value; - return $this; - } - - /** - * @param bool $value Boolean true to disable selection of table contents false to enable selection - * @return GridFieldSortableRows Returns the current instance - */ - public function setDisableSelection($value){ - $this->disable_selection = $value; - return $this; - } - - /** - * Sets the suffix of the versioned stage that should be updated along side the default stage - * @param string $value Versioned Stage to update this is disabled by default unless this is set - * @return GridFieldSortableRows Returns the current instance - */ - public function setUpdateVersionedStage($value) { - $this->update_versioned_stage=$value; - return $this; - } - - /** - * Sets the name of the relationship to use, by default the name is determined from the GridField's name - * @param string $value Name of the relationship to use, by default the name is determined from the GridField's name - * @return GridFieldSortableRows Returns the current instance - */ - public function setCustomRelationName($value) { - $this->custom_relation_name=$value; - return $this; - } - - /** - * Detects and corrects items with a sort column value of 0, by appending them to the bottom of the list - * @param GridField $gridField Grid Field Reference - * @param SS_List $dataList Data List of items to be checked - */ - protected function fixSortColumn($gridField, SS_List $dataList) { - if(class_exists('UnsavedRelationList') && $dataList instanceof UnsavedRelationList) { - return; - } - - $list=clone $dataList; - $list=$list->alterDataQuery(function($query, SS_List $tmplist) { - $query->limit(array()); - return $query; - }); - - $many_many = ($list instanceof ManyManyList); - if (!$many_many) { - $sng=singleton($gridField->getModelClass()); - $fieldType=$sng->db($this->sortColumn); - if(!$fieldType || !(strtolower($fieldType) == 'int' || is_subclass_of($fieldType, 'Int'))) { - if(is_array($fieldType)) { - user_error('Sort column '.$this->sortColumn.' could not be found in '.$gridField->getModelClass().'\'s ancestry', E_USER_ERROR); - }else { - user_error('Sort column '.$this->sortColumn.' must be an Int, column is of type '.$fieldType, E_USER_ERROR); - } - - exit; - } - } - - - $max = $list->Max($this->sortColumn); - $list=$list->filter($this->sortColumn, 0)->sort("Created,ID"); - if($list->Count()>0) { - $owner = $gridField->Form->getRecord(); - $sortColumn = $this->sortColumn; - $i = 1; - - if ($many_many) { - list($parentClass, $componentClass, $parentField, $componentField, $table) = $owner->many_many((!empty($this->custom_relation_name) ? $this->custom_relation_name:$gridField->getName())); - $extraFields=$owner->many_many_extraFields((!empty($this->custom_relation_name) ? $this->custom_relation_name:$gridField->getName())); - - if(!$extraFields || !array_key_exists($this->sortColumn, $extraFields) || !($extraFields[$this->sortColumn]=='Int' || is_subclass_of('Int', $extraFields[$this->sortColumn]))) { - user_error('Sort column '.$this->sortColumn.' must be an Int, column is of type '.$extraFields[$this->sortColumn], E_USER_ERROR); - exit; - } - }else { - //Find table containing the sort column - $table=false; - $class=$gridField->getModelClass(); - - $db = Config::inst()->get($class, "db", CONFIG::UNINHERITED); - if(!empty($db) && array_key_exists($sortColumn, $db)) { - $table=$class; - }else { - $classes=ClassInfo::ancestry($class, true); - foreach($classes as $class) { - $db = Config::inst()->get($class, "db", CONFIG::UNINHERITED); - if(!empty($db) && array_key_exists($sortColumn, $db)) { - $table=$class; - break; - } - } - } - - if($table===false) { - user_error('Sort column '.$this->sortColumn.' could not be found in '.$gridField->getModelClass().'\'s ancestry', E_USER_ERROR); - exit; - } - - $baseDataClass=ClassInfo::baseDataClass($gridField->getModelClass()); - } - - - //Start transaction if supported - if(DB::getConn()->supportsTransactions()) { - DB::getConn()->transactionStart(); - } - - $idCondition=null; - if($this->append_to_top && !($list instanceof RelationList)) { - $idCondition='"ID" IN(\''.implode("','", $dataList->getIDList()).'\')'; - } - - if($this->append_to_top) { - $topIncremented=array(); - } - - foreach($list as $obj) { - if($many_many) { - if($this->append_to_top) { - //Upgrade all the records (including the last inserted from 0 to 1) - DB::query('UPDATE "' . $table - . '" SET "' . $sortColumn . '" = "' . $sortColumn .'"+1' - . ' WHERE "' . $parentField . '" = ' . $owner->ID . (!empty($topIncremented) ? ' AND "' . $componentField . '" NOT IN(\''.implode('\',\'', $topIncremented).'\')':'')); - - $topIncremented[]=$obj->ID; - }else { - //Append the last record to the bottom - DB::query('UPDATE "' . $table - . '" SET "' . $sortColumn .'" = ' . ($max + $i) - . ' WHERE "' . $componentField . '" = ' . $obj->ID . ' AND "' . $parentField . '" = ' . $owner->ID); - } - }else if($this->append_to_top) { - //Upgrade all the records (including the last inserted from 0 to 1) - DB::query('UPDATE "' . $table - . '" SET "' . $sortColumn . '" = "' . $sortColumn .'"+1' - . ' WHERE '.($list instanceof RelationList ? '"' . $list->foreignKey . '" = '. $owner->ID:$idCondition) . (!empty($topIncremented) ? ' AND "ID" NOT IN(\''.implode('\',\'', $topIncremented).'\')':'')); - - if($this->update_versioned_stage && class_exists($table) && Object::has_extension($table, 'Versioned')) { - DB::query('UPDATE "' . $table . '_' . $this->update_versioned_stage - . '" SET "' . $sortColumn . '" = "' . $sortColumn .'"+1' - . ' WHERE '. ($list instanceof RelationList ? '"' . $list->foreignKey . '" = '. $owner->ID:$idCondition) . (!empty($topIncremented) ? ' AND "ID" NOT IN(\''.implode('\',\'', $topIncremented).'\')':'')); - } - - $topIncremented[]=$obj->ID; - }else { - //Append the last record to the bottom - DB::query('UPDATE "' . $table - . '" SET "' . $sortColumn . '" = ' . ($max + $i) - . ' WHERE "ID" = '. $obj->ID); - //LastEdited - DB::query('UPDATE "' . $baseDataClass - . '" SET "LastEdited" = \'' . date('Y-m-d H:i:s') . '\'' - . ' WHERE "ID" = '. $obj->ID); - - if($this->update_versioned_stage && class_exists($table) && Object::has_extension($table, 'Versioned')) { - DB::query('UPDATE "' . $table . '_' . $this->update_versioned_stage - . '" SET "' . $sortColumn . '" = ' . ($max + $i) - . ' WHERE "ID" = '. $obj->ID); - - if(Object::has_extension($baseDataClass, 'Versioned')) { - DB::query('UPDATE "' . $baseDataClass . '_' . $this->update_versioned_stage - . '" SET "LastEdited" = \'' . date('Y-m-d H:i:s') . '\'' - . ' WHERE "ID" = '. $obj->ID); - } - } - } - - $i++; - } - - //Update LastEdited for affected records when using append to top on a many_many relationship - if(!$many_many && $this->append_to_top && count($topIncremented)>0) { - DB::query('UPDATE "' . $baseDataClass - . '" SET "LastEdited" = \'' . date('Y-m-d H:i:s') . '\'' - . ' WHERE "ID" IN(\''.implode('\',\'', $topIncremented).'\')'); - - if($this->update_versioned_stage && class_exists($table) && Object::has_extension($table, 'Versioned') && Object::has_extension($baseDataClass, 'Versioned')) { - DB::query('UPDATE "' . $baseDataClass . '_' . $this->update_versioned_stage - . '" SET "LastEdited" = \'' . date('Y-m-d H:i:s') . '\'' - . ' WHERE "ID" IN(\''.implode('\',\'', $topIncremented).'\')'); - } - } - - - //End transaction if supported - if(DB::getConn()->supportsTransactions()) { - DB::getConn()->transactionEnd(); - } - } - } - - /** - * 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) { - return array('saveGridRowSort', 'sortableRowsToggle', 'sortToPage'); - } - - /** - * Handle an action on the given grid field. - * @param GridField $gridField Grid Field Reference - * @param String $actionName Action identifier, see {@link getActions()}. - * @param Array $arguments Arguments relevant for this - * @param Array $data All form data - */ - public function handleAction(GridField $gridField, $actionName, $arguments, $data) { - $state = $gridField->State->GridFieldSortableRows; - if (!is_bool($state->sortableToggle)) { - $state->sortableToggle = false; - } else if ($state->sortableToggle == true) { - $gridField->getConfig()->removeComponentsByType('GridFieldFilterHeader'); - $gridField->getConfig()->removeComponentsByType('GridFieldSortableHeader'); - } - - - if ($actionName == 'savegridrowsort') { - return $this->saveGridRowSort($gridField, $data); - } else if ($actionName == 'sorttopage') { - return $this->sortToPage($gridField, $data); - } - } - - /** - * Handles saving of the row sort order - * @param GridField $gridField Grid Field Reference - * @param Array $data Data submitted in the request - */ - protected function saveGridRowSort(GridField $gridField, $data) { - $dataList = $gridField->getList(); + /** @var null|string */ + protected $update_versioned_stage = null; - if(class_exists('UnsavedRelationList') && $dataList instanceof UnsavedRelationList) { - user_error('Cannot sort an UnsavedRelationList', E_USER_ERROR); - return; - } - - if(!singleton($gridField->getModelClass())->canEdit()){ - throw new ValidationException(_t('GridFieldSortableRows.EditPermissionsFailure', "No edit permissions"),0); - } - - if (empty($data['ItemIDs'])) { - user_error('No items to sort', E_USER_ERROR); - } - - $className = $gridField->getModelClass(); - $owner = $gridField->Form->getRecord(); - $items = clone $gridField->getList(); - $many_many = ($items instanceof ManyManyList); - $sortColumn = $this->sortColumn; - $pageOffset = 0; - - if ($paginator = $gridField->getConfig()->getComponentsByType('GridFieldPaginator')->First()) { - $pageState = $gridField->State->GridFieldPaginator; - - if($pageState->currentPage && is_int($pageState->currentPage) && $pageState->currentPage>1) { - $pageOffset = $paginator->getItemsPerPage() * ($pageState->currentPage - 1); - } - } - - - if ($many_many) { - list($parentClass, $componentClass, $parentField, $componentField, $table) = $owner->many_many((!empty($this->custom_relation_name) ? $this->custom_relation_name:$gridField->getName())); - }else { - //Find table containing the sort column - $table=false; - $class=$gridField->getModelClass(); - $db = Config::inst()->get($class, "db", CONFIG::UNINHERITED); - if(!empty($db) && array_key_exists($sortColumn, $db)) { - $table=$class; - }else { - $classes=ClassInfo::ancestry($class, true); - foreach($classes as $class) { - $db = Config::inst()->get($class, "db", CONFIG::UNINHERITED); - if(!empty($db) && array_key_exists($sortColumn, $db)) { - $table=$class; - break; - } - } - } - - if($table===false) { - user_error('Sort column '.$this->sortColumn.' could not be found in '.$gridField->getModelClass().'\'s ancestry', E_USER_ERROR); - exit; - } - - $baseDataClass=ClassInfo::baseDataClass($gridField->getModelClass()); - } - - - //Event to notify the Controller or owner DataObject before list sort - if($owner && $owner instanceof DataObject && method_exists($owner, 'onBeforeGridFieldRowSort')) { - $owner->onBeforeGridFieldRowSort(clone $items); - }else if(Controller::has_curr() && Controller::curr() instanceof ModelAdmin && method_exists(Controller::curr(), 'onBeforeGridFieldRowSort')) { - Controller::curr()->onBeforeGridFieldRowSort(clone $items); - } - - - //Start transaction if supported - if(DB::getConn()->supportsTransactions()) { - DB::getConn()->transactionStart(); - } - - - //Perform sorting - $ids = explode(',', $data['ItemIDs']); - for($sort = 0;$sortupdate_versioned_stage - . '" SET "' . $sortColumn . '" = ' . (($sort + 1) + $pageOffset) - . ' WHERE "ID" = '. $id); - - if(Object::has_extension($baseDataClass, 'Versioned')) { - DB::query('UPDATE "' . $baseDataClass . '_' . $this->update_versioned_stage - . '" SET "LastEdited" = \'' . date('Y-m-d H:i:s') . '\'' - . ' WHERE "ID" = '. $id); - } - } - } - } - - - //End transaction if supported - if(DB::getConn()->supportsTransactions()) { - DB::getConn()->transactionEnd(); - } - - - //Event to notify the Controller or owner DataObject after list sort - if($owner && $owner instanceof DataObject && method_exists($owner, 'onAfterGridFieldRowSort')) { - $owner->onAfterGridFieldRowSort(clone $items); - }else if(Controller::has_curr() && Controller::curr() instanceof ModelAdmin && method_exists(Controller::curr(), 'onAfterGridFieldRowSort')) { - Controller::curr()->onAfterGridFieldRowSort(clone $items); - } - } - - /** - * Handles sorting across pages - * @param GridField $gridField Grid Field Reference - * @param Array $data Data submitted in the request - */ - protected function sortToPage(GridField $gridField, $data) { - if (!$paginator = $gridField->getConfig()->getComponentsByType('GridFieldPaginator')->First()) { - user_error('Paginator not detected', E_USER_ERROR); - } - - if (empty($data['ItemID'])) { - user_error('No item to sort', E_USER_ERROR); - } - - if (empty($data['Target'])) { - user_error('No target page', E_USER_ERROR); - } - - - $className = $gridField->getModelClass(); - $owner = $gridField->Form->getRecord(); - $items = clone $gridField->getList(); - $many_many = ($items instanceof ManyManyList); - $sortColumn = $this->sortColumn; - $targetItem = $items->byID(intval($data['ItemID'])); - - if (!$targetItem) { - user_error('Target item not found', E_USER_ERROR); - } - - $currentPage = 1; - - - $pageState = $gridField->State->GridFieldPaginator; - if($pageState->currentPage && $pageState->currentPage>1) { - $currentPage = $pageState->currentPage; - } - - - if ($many_many) { - list($parentClass, $componentClass, $parentField, $componentField, $table) = $owner->many_many((!empty($this->custom_relation_name) ? $this->custom_relation_name:$gridField->getName())); - } - - - if ($data['Target'] == 'previouspage') { - $items = $items->limit($paginator->getItemsPerPage() + 1, ($paginator->getItemsPerPage() * ($currentPage - 1)) - 1); - } else if ($data['Target'] == 'nextpage') { - $items = $items->limit($paginator->getItemsPerPage() + 1, $paginator->getItemsPerPage() * ($currentPage - 1)); - } else { - user_error('Not implemented: '.$data['Target'], E_USER_ERROR); - } - - $sortPositions = $items->column($sortColumn); - - - //Event to notify the Controller or owner DataObject before list sort - if($owner && $owner instanceof DataObject && method_exists($owner, 'onBeforeGridFieldPageSort')) { - $owner->onBeforeGridFieldPageSort(clone $items); - }else if(Controller::has_curr() && Controller::curr() instanceof ModelAdmin && method_exists(Controller::curr(), 'onBeforeGridFieldPageSort')) { - Controller::curr()->onBeforeGridFieldPageSort(clone $items); - } - - - //Find the sort column - if($this->update_versioned_stage && Object::has_extension($className, 'Versioned')) { - $table=false; - $classes=ClassInfo::ancestry($className, true); - foreach($classes as $class) { - $db = Config::inst()->get($class, "db", CONFIG::UNINHERITED); - if(!empty($db) && array_key_exists($sortColumn, $db)) { - $table=$class; - break; - } - } - - if($table===false) { - user_error('Sort column '.$this->sortColumn.' could not be found in '.$gridField->getModelClass().'\'s ancestry', E_USER_ERROR); - exit; - } - } - - - //Start transaction if supported - if(DB::getConn()->supportsTransactions()) { - DB::getConn()->transactionStart(); - } - - if($data['Target']=='previouspage') { - if ($many_many) { - DB::query('UPDATE "' . $table - . '" SET "' . $sortColumn.'" = ' . $sortPositions[0] - . ' WHERE "' . $componentField . '" = ' . $targetItem->ID . ' AND "' . $parentField . '" = ' . $owner->ID); - } else { - $targetItem->$sortColumn = $sortPositions[0]; - $targetItem->write(); - - if($this->update_versioned_stage && Object::has_extension($className, 'Versioned')) { - DB::query('UPDATE "' . $table . '_' . $this->update_versioned_stage - . '" SET "' . $sortColumn.'" = ' . $sortPositions[0] - . ' WHERE "ID" = ' . $targetItem->ID); - } - } - - - $i = 1; - foreach ($items as $obj) { - if ($obj->ID == $targetItem->ID) { - continue; - } - - - if ($many_many) { - DB::query('UPDATE "' . $table - . '" SET "' . $sortColumn.'" = ' . $sortPositions[$i] - . ' WHERE "' . $componentField . '" = ' . $obj->ID . ' AND "' . $parentField . '" = ' . $owner->ID); - } else { - $obj->$sortColumn = $sortPositions[$i]; - $obj->write(); - - if($this->update_versioned_stage && Object::has_extension($className, 'Versioned')) { - DB::query('UPDATE "' . $table . '_' . $this->update_versioned_stage - . '" SET "' . $sortColumn.'" = ' . $sortPositions[$i] - . ' WHERE "ID" = ' . $obj->ID); - } - } - - $i++; - } - } else { - if ($many_many) { - DB::query('UPDATE "' . $table - . '" SET "' . $sortColumn.'" = ' . $sortPositions[count($sortPositions) - 1] - . ' WHERE "' . $componentField . '" = ' . $targetItem->ID . ' AND "' . $parentField . '" = ' . $owner->ID); - } else { - $targetItem->$sortColumn = $sortPositions[count($sortPositions) - 1]; - $targetItem->write(); - - if($this->update_versioned_stage && Object::has_extension($className, 'Versioned')) { - DB::query('UPDATE "' . $table . '_' . $this->update_versioned_stage - . '" SET "' . $sortColumn.'" = ' . $sortPositions[count($sortPositions) - 1] - . ' WHERE "ID" = ' . $targetItem->ID); - } - } - - - $i = 0; - foreach ($items as $obj) { - if ($obj->ID == $targetItem->ID) { - continue; - } - - - if ($many_many) { - DB::query('UPDATE "' . $table - . '" SET "' . $sortColumn.'" = ' . $sortPositions[$i] - . ' WHERE "' . $componentField . '" = ' . $obj->ID . ' AND "' . $parentField . '" = ' . $owner->ID); - } else { - $obj->$sortColumn = $sortPositions[$i]; - $obj->write(); - - if($this->update_versioned_stage && Object::has_extension($className, 'Versioned')) { - DB::query('UPDATE "' . $table . '_' . $this->update_versioned_stage - . '" SET "' . $sortColumn.'" = ' . $sortPositions[$i] - . ' WHERE "ID" = ' . $obj->ID); - } - } - - $i++; - } - } - - - //End transaction if supported - if(DB::getConn()->supportsTransactions()) { - DB::getConn()->transactionEnd(); - } - - - //Event to notify the Controller or owner DataObject after list sort - if($owner && $owner instanceof DataObject && method_exists($owner, 'onAfterGridFieldPageSort')) { - $owner->onAfterGridFieldPageSort(clone $items); - }else if(Controller::has_curr() && Controller::curr() instanceof ModelAdmin && method_exists(Controller::curr(), 'onAfterGridFieldPageSort')) { - Controller::curr()->onAfterGridFieldPageSort(clone $items); - } - } + /** @var null|string */ + protected $custom_relation_name = null; + + /** @var array */ + protected $tableMap = []; + + /** + * @param string $sortColumn Column that should be used to update the sort information + * @param bool $disableSelection Disable selection on the GridField when dragging + * @param string $updateVersionStage Name of the versioned stage to update this disabled by default unless this is set + * @param string $customRelationName Name of the relationship to use, if left null the name is determined from the GridField's name + */ + public function __construct($sortColumn, $disableSelection = true, $updateVersionStage = null, $customRelationName = null) + { + $this->sortColumn = $sortColumn; + $this->disable_selection = $disableSelection; + $this->update_versioned_stage = $updateVersionStage; + $this->custom_relation_name = $customRelationName; + } + + /** + * 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 + * @return array Map where the keys are fragment names and the values are pieces of HTML to add to these fragments. + */ + public function getHTMLFragments($gridField) + { + $dataList = $gridField->getList(); + + if (class_exists('UnsavedRelationList') && $dataList instanceof UnsavedRelationList) { + return array(); + } + + $state = $gridField->State->GridFieldSortableRows; + if (!is_bool($state->sortableToggle)) { + $state->sortableToggle = false; + } + + //Ensure user can edit + if (!singleton($gridField->getModelClass())->canEdit()) { + return array(); + } + + + //Sort order toggle + $sortOrderToggle = GridField_FormAction::create( + $gridField, + 'sortablerows-toggle', + 'sorttoggle', + 'sortableRowsToggle', + null + )->addExtraClass('sortablerows-toggle'); + + + $sortOrderSave = GridField_FormAction::create( + $gridField, + 'sortablerows-savesort', + 'savesort', + 'saveGridRowSort', + null + )->addExtraClass('sortablerows-savesort'); + + + //Sort to Page Action + $sortToPage = GridField_FormAction::create( + $gridField, + 'sortablerows-sorttopage', + 'sorttopage', + 'sortToPage', + null + )->addExtraClass('sortablerows-sorttopage'); + + + $data = array('SortableToggle' => $sortOrderToggle, + 'SortOrderSave' => $sortOrderSave, + 'SortToPage' => $sortToPage, + 'Checked' => ($state->sortableToggle == true ? ' checked = "checked"' : ''), + 'List' => $dataList); + + $forTemplate = new arrayData($data); + + //Inject Requirements + $custom = Config::inst()->get(GridFieldSortableRows::class, 'Base'); + $base = $custom ?: SORTABLE_GRIDFIELD_BASE; + + Requirements::css($base . '/css/GridFieldSortableRows.css'); + Requirements::javascript($base . '/javascript/GridFieldSortableRows.js'); + + $args = array('Colspan' => count($gridField->getColumns()), 'ID' => $gridField->ID(), 'DisableSelection' => $this->disable_selection); + + $fragments = array('header' => $forTemplate->renderWith('SortableGridField\Forms\Includes\GridFieldSortableRows', $args)); + + if ($gridField->getConfig()->getComponentByType(GridFieldPaginator::class)) { + $fragments['after'] = $forTemplate->renderWith('SortableGridField\Forms\Includes\GridFieldSortableRows_paginator'); + } + + return $fragments; + } + + /** + * Manipulate the datalist as needed by this grid modifier. + * @param GridField $gridField Grid Field Reference + * @param SS_List|DataList $dataList Data List to adjust + * @return DataList Modified Data List + */ + public function getManipulatedData(GridField $gridField, SS_List $dataList) + { + //Detect and correct items with a sort column value of 0 (push to bottom) + $this->fixSortColumn($gridField, $dataList); + + + $headerState = $gridField->State->GridFieldSortableHeader; + $state = $gridField->State->GridFieldSortableRows; + if ((!is_bool($state->sortableToggle) || $state->sortableToggle === false) && $headerState && is_string($headerState->SortColumn) && is_string($headerState->SortDirection)) { + return $dataList->sort($headerState->SortColumn, $headerState->SortDirection); + } + + if ($state->sortableToggle === true) { + $gridField->getConfig()->removeComponentsByType(GridFieldFilterHeader::class); + $gridField->getConfig()->removeComponentsByType(GridFieldSortableHeader::class); + } + + return $dataList->sort($this->sortColumn); + } + + /** + * Sets if new records should be appended to the top or the bottom of the list + * @param bool $value Boolean true to append to the top false to append to the bottom + * @return GridFieldSortableRows Returns the current instance + */ + public function setAppendToTop($value) + { + $this->append_to_top = $value; + return $this; + } + + /** + * @param bool $value Boolean true to disable selection of table contents false to enable selection + * @return GridFieldSortableRows Returns the current instance + */ + public function setDisableSelection($value) + { + $this->disable_selection = $value; + return $this; + } + + /** + * Sets the suffix of the versioned stage that should be updated along side the default stage + * @param string $value Versioned Stage to update this is disabled by default unless this is set + * @return GridFieldSortableRows Returns the current instance + */ + public function setUpdateVersionedStage($value) + { + $this->update_versioned_stage = $value; + return $this; + } + + /** + * Sets the name of the relationship to use, by default the name is determined from the GridField's name + * @param string $value Name of the relationship to use, by default the name is determined from the GridField's name + * @return GridFieldSortableRows Returns the current instance + */ + public function setCustomRelationName($value) + { + $this->custom_relation_name = $value; + return $this; + } + + /** + * Detects and corrects items with a sort column value of 0, by appending them to the bottom of the list + * @param GridField $gridField Grid Field Reference + * @param SS_List|DataList $dataList Data List of items to be checked + */ + protected function fixSortColumn($gridField, SS_List $dataList) + { + if ($dataList instanceof UnsavedRelationList) { + return; + } + + /** @var SS_List|DataList $list */ + $list = clone $dataList; + $list = $list->alterDataQuery(function ($query, SS_List $tmplist) { + /** @var DataQuery $query */ + $query->limit(array()); + return $query; + }); + + $many_many = ($list instanceof ManyManyList); + if (!$many_many) { + $sng = singleton($gridField->getModelClass()); + $fieldType = $sng->config()->db[$this->sortColumn]; + + if (!$fieldType || !(strtolower($fieldType) == 'int' || is_subclass_of($fieldType, 'Int'))) { + if (is_array($fieldType)) { + user_error('Sort column ' . $this->sortColumn . ' could not be found in ' . $gridField->getModelClass() . '\'s ancestry', E_USER_ERROR); + } else { + user_error('Sort column ' . $this->sortColumn . ' must be an Int, column is of type ' . $fieldType, E_USER_ERROR); + } + + exit; + } + } + + $max = $list->Max($this->sortColumn); + $list = $list->filter($this->sortColumn, 0)->sort("Created,ID"); + if ($list->Count() > 0) { + $owner = $gridField->getForm()->getRecord(); + $sortColumn = $this->sortColumn; + $i = 1; + + if ($many_many) { + list($parentClass, $componentClass, $parentField, $componentField, $table) = $owner->many_many((!empty($this->custom_relation_name) ? $this->custom_relation_name : $gridField->getName())); + + /** @var DataObject $table */ + $table = $this->mapTableNameAndReturn($table); + + $extraFields = $owner->many_many_extraFields((!empty($this->custom_relation_name) ? $this->custom_relation_name : $gridField->getName())); + + if (!$extraFields || !array_key_exists($this->sortColumn, $extraFields) || !($extraFields[$this->sortColumn] == 'Int' || is_subclass_of('Int', $extraFields[$this->sortColumn]))) { + user_error('Sort column ' . $this->sortColumn . ' must be an Int, column is of type ' . $extraFields[$this->sortColumn], E_USER_ERROR); + exit; + } + } else { + //Find table containing the sort column + $table = false; + $class = $gridField->getModelClass(); + + $db = Config::inst()->get($class, "db", CONFIG::UNINHERITED); + if (!empty($db) && array_key_exists($sortColumn, $db)) { + $table = $this->mapTableNameAndReturn($class); + } else { + $classes = ClassInfo::ancestry($class, true); + foreach ($classes as $class) { + $db = Config::inst()->get($class, "db", CONFIG::UNINHERITED); + if (!empty($db) && array_key_exists($sortColumn, $db)) { + $table = $this->mapTableNameAndReturn($class); + break; + } + } + } + + if ($table === false) { + user_error('Sort column ' . $this->sortColumn . ' could not be found in ' . $gridField->getModelClass() . '\'s ancestry', E_USER_ERROR); + exit; + } + + $baseDataClass = DataObject::getSchema()->baseDataClass($gridField->getModelClass()); + $baseDataClass = $this->mapTableNameAndReturn($baseDataClass); + + } + + + //Start transaction if supported + if (DB::get_conn()->supportsTransactions()) { + DB::get_conn()->transactionStart(); + } + + $idCondition = null; + if ($this->append_to_top && !($list instanceof RelationList)) { + $idCondition = '"ID" IN(\'' . implode("','", $dataList->getIDList()) . '\')'; + } + + if ($this->append_to_top) { + $topIncremented = array(); + } + + foreach ($list as $obj) { + if ($many_many) { + if ($this->append_to_top) { + //Upgrade all the records (including the last inserted from 0 to 1) + DB::query('UPDATE "' . $table + . '" SET "' . $sortColumn . '" = "' . $sortColumn . '"+1' + . ' WHERE "' . $parentField . '" = ' . $owner->ID . (!empty($topIncremented) ? ' AND "' . $componentField . '" NOT IN(\'' . implode('\',\'', $topIncremented) . '\')' : '')); + + $topIncremented[] = $obj->ID; + } else { + //Append the last record to the bottom + DB::query('UPDATE "' . $table + . '" SET "' . $sortColumn . '" = ' . ($max + $i) + . ' WHERE "' . $componentField . '" = ' . $obj->ID . ' AND "' . $parentField . '" = ' . $owner->ID); + } + } else if ($this->append_to_top) { + //Upgrade all the records (including the last inserted from 0 to 1) + DB::query('UPDATE "' . $table + . '" SET "' . $sortColumn . '" = "' . $sortColumn . '"+1' + . ' WHERE ' . ($list instanceof RelationList ? '"' . $list->foreignKey . '" = ' . $owner->ID : $idCondition) . (!empty($topIncremented) ? ' AND "ID" NOT IN(\'' . implode('\',\'', $topIncremented) . '\')' : '')); + + if ($this->update_versioned_stage && class_exists($this->tableMap[$table]) && $this->hasVersionedExtension($this->tableMap[$table])) { + DB::query('UPDATE "' . $table . '_' . $this->update_versioned_stage + . '" SET "' . $sortColumn . '" = "' . $sortColumn . '"+1' + . ' WHERE ' . ($list instanceof RelationList ? '"' . $list->foreignKey . '" = ' . $owner->ID : $idCondition) . (!empty($topIncremented) ? ' AND "ID" NOT IN(\'' . implode('\',\'', $topIncremented) . '\')' : '')); + } + + $topIncremented[] = $obj->ID; + } else { + //Append the last record to the bottom + DB::query('UPDATE "' . $table + . '" SET "' . $sortColumn . '" = ' . ($max + $i) + . ' WHERE "ID" = ' . $obj->ID); + //LastEdited + DB::query('UPDATE "' . $baseDataClass + . '" SET "LastEdited" = \'' . date('Y-m-d H:i:s') . '\'' + . ' WHERE "ID" = ' . $obj->ID); + + if ($this->update_versioned_stage && class_exists($this->tableMap[$table]) && $this->hasVersionedExtension($this->tableMap[$table])) { + DB::query('UPDATE "' . $table . '_' . $this->update_versioned_stage + . '" SET "' . $sortColumn . '" = ' . ($max + $i) + . ' WHERE "ID" = ' . $obj->ID); + + if ($this->hasVersionedExtension($this->tableMap[$baseDataClass])) { + DB::query('UPDATE "' . $baseDataClass . '_' . $this->update_versioned_stage + . '" SET "LastEdited" = \'' . date('Y-m-d H:i:s') . '\'' + . ' WHERE "ID" = ' . $obj->ID); + } + } + } + + $i++; + } + + //Update LastEdited for affected records when using append to top on a many_many relationship + if (!$many_many && $this->append_to_top && count($topIncremented) > 0) { + DB::query('UPDATE "' . $baseDataClass + . '" SET "LastEdited" = \'' . date('Y-m-d H:i:s') . '\'' + . ' WHERE "ID" IN(\'' . implode('\',\'', $topIncremented) . '\')'); + + if ($this->update_versioned_stage && class_exists($this->tableMap[$table]) && $this->hasVersionedExtension($this->tableMap[$table]) && $this->hasVersionedExtension($this->tableMap[$baseDataClass])) { + DB::query('UPDATE "' . $baseDataClass . '_' . $this->update_versioned_stage + . '" SET "LastEdited" = \'' . date('Y-m-d H:i:s') . '\'' + . ' WHERE "ID" IN(\'' . implode('\',\'', $topIncremented) . '\')'); + } + } + + + //End transaction if supported + if (DB::get_conn()->supportsTransactions()) { + DB::get_conn()->transactionEnd(); + } + } + } + + /** + * 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) + { + return array('saveGridRowSort', 'sortableRowsToggle', 'sortToPage'); + } + + /** + * Handle an action on the given grid field. + * @param GridField $gridField Grid Field Reference + * @param String $actionName Action identifier, see {@link getActions()}. + * @param array $arguments Arguments relevant for this + * @param array $data All form data + */ + public function handleAction(GridField $gridField, $actionName, $arguments, $data) + { + $state = $gridField->State->GridFieldSortableRows; + if (!is_bool($state->sortableToggle)) { + $state->sortableToggle = false; + } else if ($state->sortableToggle == true) { + $gridField->getConfig()->removeComponentsByType(GridFieldFilterHeader::class); + $gridField->getConfig()->removeComponentsByType(GridFieldSortableHeader::class); + } + + + if ($actionName == 'savegridrowsort') { + return $this->saveGridRowSort($gridField, $data); + } else if ($actionName == 'sorttopage') { + return $this->sortToPage($gridField, $data); + } + } + + /** + * Handles saving of the row sort order + * @param GridField $gridField Grid Field Reference + * @param array $data Data submitted in the request + * @throws ValidationException If user has no edit permissions + */ + protected function saveGridRowSort(GridField $gridField, $data) + { + $dataList = $gridField->getList(); + + if ($dataList instanceof UnsavedRelationList) { + user_error('Cannot sort an UnsavedRelationList', E_USER_ERROR); + return; + } + + if (!singleton($gridField->getModelClass())->canEdit()) { + throw new ValidationException(_t('GridFieldSortableRows.EditPermissionsFailure', "No edit permissions"), 0); + } + + if (empty($data['ItemIDs'])) { + user_error('No items to sort', E_USER_ERROR); + } + + $className = $gridField->getModelClass(); + $owner = $gridField->Form->getRecord(); + $items = clone $gridField->getList(); + $many_many = ($items instanceof ManyManyList); + $sortColumn = $this->sortColumn; + $pageOffset = 0; + + if ($paginator = $gridField->getConfig()->getComponentsByType(GridFieldPaginator::class)->First()) { + $pageState = $gridField->State->GridFieldPaginator; + + if ($pageState->currentPage && is_int($pageState->currentPage) && $pageState->currentPage > 1) { + $pageOffset = $paginator->getItemsPerPage() * ($pageState->currentPage - 1); + } + } + + + if ($many_many) { + list($parentClass, $componentClass, $parentField, $componentField, $table) = $owner->many_many((!empty($this->custom_relation_name) ? $this->custom_relation_name : $gridField->getName())); + + /** @var DataObject $table */ + $table = $this->mapTableNameAndReturn($table); + } else { + //Find table containing the sort column + $table = false; + $class = $gridField->getModelClass(); + $db = Config::inst()->get($class, "db", CONFIG::UNINHERITED); + if (!empty($db) && array_key_exists($sortColumn, $db)) { + $table = $this->mapTableNameAndReturn($class); + } else { + $classes = ClassInfo::ancestry($class, true); + foreach ($classes as $class) { + $db = Config::inst()->get($class, "db", CONFIG::UNINHERITED); + if (!empty($db) && array_key_exists($sortColumn, $db)) { + $table = $this->mapTableNameAndReturn($class); + break; + } + } + } + + if ($table === false) { + user_error('Sort column ' . $this->sortColumn . ' could not be found in ' . $gridField->getModelClass() . '\'s ancestry', E_USER_ERROR); + exit; + } + + $baseDataClass = DataObject::getSchema()->baseDataClass($gridField->getModelClass()); + $baseDataClass = $this->mapTableNameAndReturn($baseDataClass); + } + + + //Event to notify the Controller or owner DataObject before list sort + if ($owner && $owner instanceof DataObject && method_exists($owner, 'onBeforeGridFieldRowSort')) { + $owner->onBeforeGridFieldRowSort(clone $items); + } else if (Controller::has_curr() && Controller::curr() instanceof ModelAdmin && method_exists(Controller::curr(), 'onBeforeGridFieldRowSort')) { + Controller::curr()->onBeforeGridFieldRowSort(clone $items); + } + + //Start transaction if supported + if (DB::get_conn()->supportsTransactions()) { + DB::get_conn()->transactionStart(); + } + + //Perform sorting + $ids = explode(',', $data['ItemIDs']); + for ($sort = 0; $sort < count($ids); $sort++) { + $id = intval($ids[$sort]); + if ($many_many) { + DB::query('UPDATE "' . $table + . '" SET "' . $sortColumn . '" = ' . (($sort + 1) + $pageOffset) + . ' WHERE "' . $componentField . '" = ' . $id . ' AND "' . $parentField . '" = ' . $owner->ID); + } else { + DB::query('UPDATE "' . $table + . '" SET "' . $sortColumn . '" = ' . (($sort + 1) + $pageOffset) + . ' WHERE "ID" = ' . $id); + + DB::query('UPDATE "' . $baseDataClass + . '" SET "LastEdited" = \'' . date('Y-m-d H:i:s') . '\'' + . ' WHERE "ID" = ' . $id); + + if ($this->update_versioned_stage && class_exists($this->tableMap[$table]) && $this->hasVersionedExtension($this->tableMap[$table])) { + DB::query('UPDATE "' . $table . '_' . $this->update_versioned_stage + . '" SET "' . $sortColumn . '" = ' . (($sort + 1) + $pageOffset) + . ' WHERE "ID" = ' . $id); + + if ($this->hasVersionedExtension($this->tableMap[$baseDataClass])) { + DB::query('UPDATE "' . $baseDataClass . '_' . $this->update_versioned_stage + . '" SET "LastEdited" = \'' . date('Y-m-d H:i:s') . '\'' + . ' WHERE "ID" = ' . $id); + } + } + } + } + + + //End transaction if supported + if (DB::get_conn()->supportsTransactions()) { + DB::get_conn()->transactionEnd(); + } + + + //Event to notify the Controller or owner DataObject after list sort + if ($owner && $owner instanceof DataObject && method_exists($owner, 'onAfterGridFieldRowSort')) { + $owner->onAfterGridFieldRowSort(clone $items); + } else if (Controller::has_curr() && Controller::curr() instanceof ModelAdmin && method_exists(Controller::curr(), 'onAfterGridFieldRowSort')) { + Controller::curr()->onAfterGridFieldRowSort(clone $items); + } + } + + /** + * Handles sorting across pages + * @param GridField $gridField Grid Field Reference + * @param array $data Data submitted in the request + */ + protected function sortToPage(GridField $gridField, $data) + { + if (!$paginator = $gridField->getConfig()->getComponentsByType(GridFieldPaginator::class)->First()) { + user_error('Paginator not detected', E_USER_ERROR); + } + + if (empty($data['ItemID'])) { + user_error('No item to sort', E_USER_ERROR); + } + + if (empty($data['Target'])) { + user_error('No target page', E_USER_ERROR); + } + + /** @var Extensible $className */ + $className = $gridField->getModelClass(); + $owner = $gridField->Form->getRecord(); + + /** @var DataList $items */ + $items = clone $gridField->getList(); + + $many_many = ($items instanceof ManyManyList); + $sortColumn = $this->sortColumn; + $targetItem = $items->byID(intval($data['ItemID'])); + + if (!$targetItem) { + user_error('Target item not found', E_USER_ERROR); + } + + $currentPage = 1; + + $pageState = $gridField->State->GridFieldPaginator; + if ($pageState->currentPage && $pageState->currentPage > 1) { + $currentPage = $pageState->currentPage; + } + + if ($many_many) { + list($parentClass, $componentClass, $parentField, $componentField, $table) = $owner->many_many((!empty($this->custom_relation_name) ? $this->custom_relation_name : $gridField->getName())); + $table = $this->mapTableNameAndReturn($table); + } + + if ($data['Target'] == 'previouspage') { + $items = $items->limit($paginator->getItemsPerPage() + 1, ($paginator->getItemsPerPage() * ($currentPage - 1)) - 1); + } else if ($data['Target'] == 'nextpage') { + $items = $items->limit($paginator->getItemsPerPage() + 1, $paginator->getItemsPerPage() * ($currentPage - 1)); + } else { + user_error('Not implemented: ' . $data['Target'], E_USER_ERROR); + } + + $sortPositions = $items->column($sortColumn); + + //Event to notify the Controller or owner DataObject before list sort + if ($owner && $owner instanceof DataObject && method_exists($owner, 'onBeforeGridFieldPageSort')) { + $owner->onBeforeGridFieldPageSort(clone $items); + } else if (Controller::has_curr() && Controller::curr() instanceof ModelAdmin && method_exists(Controller::curr(), 'onBeforeGridFieldPageSort')) { + Controller::curr()->onBeforeGridFieldPageSort(clone $items); + } + + //Find the sort column + if ($this->update_versioned_stage && $this->hasVersionedExtension($className)) { + $table = false; + $classes = ClassInfo::ancestry($className, true); + foreach ($classes as $class) { + $db = Config::inst()->get($class, "db", CONFIG::UNINHERITED); + if (!empty($db) && array_key_exists($sortColumn, $db)) { + $table = $this->mapTableNameAndReturn($class); + break; + } + } + + if ($table === false) { + user_error('Sort column ' . $this->sortColumn . ' could not be found in ' . $gridField->getModelClass() . '\'s ancestry', E_USER_ERROR); + exit; + } + } + + //Start transaction if supported + if (DB::get_conn()->supportsTransactions()) { + DB::get_conn()->transactionStart(); + } + + if ($data['Target'] == 'previouspage') { + if ($many_many) { + DB::query('UPDATE "' . $table + . '" SET "' . $sortColumn . '" = ' . $sortPositions[0] + . ' WHERE "' . $componentField . '" = ' . $targetItem->ID . ' AND "' . $parentField . '" = ' . $owner->ID); + } else { + $targetItem->$sortColumn = $sortPositions[0]; + $targetItem->write(); + + if ($this->update_versioned_stage && $this->hasVersionedExtension($className)) { + DB::query('UPDATE "' . $table . '_' . $this->update_versioned_stage + . '" SET "' . $sortColumn . '" = ' . $sortPositions[0] + . ' WHERE "ID" = ' . $targetItem->ID); + } + } + + $i = 1; + foreach ($items as $obj) { + if ($obj->ID == $targetItem->ID) { + continue; + } + + + if ($many_many) { + DB::query('UPDATE "' . $table + . '" SET "' . $sortColumn . '" = ' . $sortPositions[$i] + . ' WHERE "' . $componentField . '" = ' . $obj->ID . ' AND "' . $parentField . '" = ' . $owner->ID); + } else { + $obj->$sortColumn = $sortPositions[$i]; + $obj->write(); + + if ($this->update_versioned_stage && $this->hasVersionedExtension($className)) { + DB::query('UPDATE "' . $table . '_' . $this->update_versioned_stage + . '" SET "' . $sortColumn . '" = ' . $sortPositions[$i] + . ' WHERE "ID" = ' . $obj->ID); + } + } + + $i++; + } + } else { + if ($many_many) { + DB::query('UPDATE "' . $table + . '" SET "' . $sortColumn . '" = ' . $sortPositions[count($sortPositions) - 1] + . ' WHERE "' . $componentField . '" = ' . $targetItem->ID . ' AND "' . $parentField . '" = ' . $owner->ID); + } else { + $targetItem->$sortColumn = $sortPositions[count($sortPositions) - 1]; + $targetItem->write(); + + if ($this->update_versioned_stage && $this->hasVersionedExtension($className)) { + DB::query('UPDATE "' . $table . '_' . $this->update_versioned_stage + . '" SET "' . $sortColumn . '" = ' . $sortPositions[count($sortPositions) - 1] + . ' WHERE "ID" = ' . $targetItem->ID); + } + } + + $i = 0; + foreach ($items as $obj) { + if ($obj->ID == $targetItem->ID) { + continue; + } + + + if ($many_many) { + DB::query('UPDATE "' . $table + . '" SET "' . $sortColumn . '" = ' . $sortPositions[$i] + . ' WHERE "' . $componentField . '" = ' . $obj->ID . ' AND "' . $parentField . '" = ' . $owner->ID); + } else { + $obj->$sortColumn = $sortPositions[$i]; + $obj->write(); + + if ($this->update_versioned_stage && $this->hasVersionedExtension($className)) { + DB::query('UPDATE "' . $table . '_' . $this->update_versioned_stage + . '" SET "' . $sortColumn . '" = ' . $sortPositions[$i] + . ' WHERE "ID" = ' . $obj->ID); + } + } + + $i++; + } + } + + //End transaction if supported + if (DB::get_conn()->supportsTransactions()) { + DB::get_conn()->transactionEnd(); + } + + //Event to notify the Controller or owner DataObject after list sort + if ($owner && $owner instanceof DataObject && method_exists($owner, 'onAfterGridFieldPageSort')) { + $owner->onAfterGridFieldPageSort(clone $items); + } else if (Controller::has_curr() && Controller::curr() instanceof ModelAdmin && method_exists(Controller::curr(), 'onAfterGridFieldPageSort')) { + Controller::curr()->onAfterGridFieldPageSort(clone $items); + } + } + + /** + * Check to see if the given class name has the Versioned extension + * + * @param Extensible|string $className + * @return bool + */ + public function hasVersionedExtension($className) + { + return $className::has_extension(Versioned::class); + } + + /** + * Checks to see if $table_name is declared on the DataObject, if not returns string as given + * + * @param $tableName + * @return mixed + */ + public function mapTableNameAndReturn($tableName) + { + if (array_key_exists($tableName, $this->tableMap)) { + return $this->tableMap[$tableName]; + } + + $realName = (Config::inst()->get($tableName, 'table_name', CONFIG::UNINHERITED)) ? Config::inst()->get($tableName, 'table_name', CONFIG::UNINHERITED) : $table; + + $this->tableMap[$realName] = $tableName; + + return $realName; + } } -?> diff --git a/tests/forms/GridFieldSortableRowsAutoSortTest.php b/tests/forms/GridFieldSortableRowsAutoSortTest.php index 15b6c43..0356b9e 100644 --- a/tests/forms/GridFieldSortableRowsAutoSortTest.php +++ b/tests/forms/GridFieldSortableRowsAutoSortTest.php @@ -1,253 +1,361 @@ logOut(); } - - $list = GridFieldAction_SortOrder_Player::get(); - $config = GridFieldConfig::create()->addComponent(new GridFieldSortableRows('SortOrder')); - $gridField = new GridField('testfield', 'testfield', $list, $config); - $form = new Form(new Controller(), 'mockform', new FieldList(array($gridField)), new FieldList()); - - $stateID = 'testGridStateActionField'; - Session::set($stateID, array('grid'=>'', 'actionName'=>'sortableRowsToggle', 'args'=>array('GridFieldSortableRows'=>array('sortableToggle'=>true)))); - $request = new SS_HTTPRequest('POST', 'url', array(), array('action_gridFieldAlterAction?StateID='.$stateID=>true, $form->getSecurityToken()->getName()=>$form->getSecurityToken()->getValue())); - $gridField->gridFieldAlterAction(array('StateID'=>$stateID), $form, $request); - - //Insure sort ran - $this->assertEquals(3, $list->last()->SortOrder, 'Auto sort should have run'); - - - //Check for duplicates (there shouldn't be any) - $count=$list->Count(); - $indexes=count(array_unique($list->column('SortOrder'))); - $this->assertEquals(0, $count-$indexes, 'Duplicate indexes detected'); - } - - public function testAppendToTopAutoSort() { - if(Member::currentUser()) { Member::currentUser()->logOut(); } - - $list = GridFieldAction_SortOrder_Player::get(); - $config = GridFieldConfig::create()->addComponent(new GridFieldSortableRows('SortOrder')); - $gridField = new GridField('testfield', 'testfield', $list, $config); - $form = new Form(new Controller(), 'mockform', new FieldList(array($gridField)), new FieldList()); - - $gridField->getConfig()->getComponentByType('GridFieldSortableRows')->setAppendToTop(true); - - $this->assertEquals(0, $list->last()->SortOrder, 'Auto sort should not have run'); - - $stateID = 'testGridStateActionField'; - Session::set($stateID, array('grid'=>'', 'actionName'=>'sortableRowsToggle', 'args'=>array('GridFieldSortableRows'=>array('sortableToggle'=>true)))); - $request = new SS_HTTPRequest('POST', 'url', array(), array('action_gridFieldAlterAction?StateID='.$stateID=>true, $form->getSecurityToken()->getName()=>$form->getSecurityToken()->getValue())); - $gridField->gridFieldAlterAction(array('StateID'=>$stateID), $form, $request); - - //Insure sort ran - $this->assertEquals(3, $list->last()->SortOrder, 'Auto sort should have run'); - - - //Check for duplicates (there shouldn't be any) - $count=$list->Count(); - $indexes=count(array_unique($list->column('SortOrder'))); - $this->assertEquals(0, $count-$indexes, 'Duplicate indexes detected'); - } - - public function testAutoSortVersioned() { - if(Member::currentUser()) { Member::currentUser()->logOut(); } - - //Force versioned to reset - Versioned::reset(); - - $list = GridFieldAction_SortOrder_VPlayer::get(); - - //Publish all records - foreach($list as $item) { - $item->publish('Stage', 'Live'); - } - - - $config = GridFieldConfig::create()->addComponent(new GridFieldSortableRows('SortOrder', true, 'Live')); - $gridField = new GridField('testfield', 'testfield', $list, $config); - $form = new Form(new Controller(), 'mockform', new FieldList(array($gridField)), new FieldList()); - - $stateID = 'testGridStateActionField'; - Session::set($stateID, array('grid'=>'', 'actionName'=>'sortableRowsToggle', 'args'=>array('GridFieldSortableRows'=>array('sortableToggle'=>true)))); - $request = new SS_HTTPRequest('POST', 'url', array(), array('action_gridFieldAlterAction?StateID='.$stateID=>true, $form->getSecurityToken()->getName()=>$form->getSecurityToken()->getValue())); - $gridField->gridFieldAlterAction(array('StateID'=>$stateID), $form, $request); - - - //Insure sort ran - $this->assertEquals(3, $list->last()->SortOrder, 'Auto sort should have run on Versioned stage "Stage"'); - - - //Check for duplicates (there shouldn't be any) - $count=$list->Count(); - $indexes=count(array_unique($list->column('SortOrder'))); - $this->assertEquals(0, $count-$indexes, 'Duplicate indexes detected on Versioned stage "Stage"'); - - - //Force versioned over to Live stage - Versioned::reading_stage('Live'); - - //Get live instance - $obj=Versioned::get_one_by_stage('GridFieldAction_SortOrder_VPlayer', 'Live', '"ID"='.$list->last()->ID); - - //Insure sort ran - $this->assertEquals(3, $obj->SortOrder, 'Auto sort should have run on Versioned stage "Live"'); - - - //Check for duplicates (there shouldn't be any) - $list=Versioned::get_by_stage('GridFieldAction_SortOrder_VPlayer', 'Live'); - $count=$list->Count(); - $indexes=count(array_unique($list->column('SortOrder'))); - $this->assertEquals(0, $count-$indexes, 'Duplicate indexes detected on Versioned stage "Live"'); - } - - public function testAppendToTopAutoSortVersioned() { - if(Member::currentUser()) { Member::currentUser()->logOut(); } - - //Force versioned to reset - Versioned::reset(); - - $list = GridFieldAction_SortOrder_VPlayer::get(); - - //Publish all records - foreach($list as $item) { - $item->publish('Stage', 'Live'); - } - - - $config = GridFieldConfig::create()->addComponent(new GridFieldSortableRows('SortOrder', true, 'Live')); - $gridField = new GridField('testfield', 'testfield', $list, $config); - $form = new Form(new Controller(), 'mockform', new FieldList(array($gridField)), new FieldList()); - - $gridField->getConfig()->getComponentByType('GridFieldSortableRows')->setAppendToTop(true); - - $this->assertEquals(0, $list->last()->SortOrder, 'Auto sort should not have run on Versioned stage "Stage"'); - - $stateID = 'testGridStateActionField'; - Session::set($stateID, array('grid'=>'', 'actionName'=>'sortableRowsToggle', 'args'=>array('GridFieldSortableRows'=>array('sortableToggle'=>true)))); - $request = new SS_HTTPRequest('POST', 'url', array(), array('action_gridFieldAlterAction?StateID='.$stateID=>true, $form->getSecurityToken()->getName()=>$form->getSecurityToken()->getValue())); - $gridField->gridFieldAlterAction(array('StateID'=>$stateID), $form, $request); - - - //Insure sort ran - $this->assertEquals(3, $list->last()->SortOrder, 'Auto sort should have run on Versioned stage "Stage"'); - - - //Check for duplicates (there shouldn't be any) - $count=$list->Count(); - $indexes=count(array_unique($list->column('SortOrder'))); - $this->assertEquals(0, $count-$indexes, 'Duplicate indexes detected on Versioned stage "Stage"'); - - - //Force versioned over to Live stage - Versioned::reading_stage('Live'); - - //Insure sort ran - $this->assertEquals(3, $list->last()->SortOrder, 'Auto sort should have run on Versioned stage "Live"'); - - - //Check for duplicates (there shouldn't be any) - $count=$list->Count(); - $indexes=count(array_unique($list->column('SortOrder'))); - $this->assertEquals(0, $count-$indexes, 'Duplicate indexes detected on Versioned stage "Live"'); - } - - public function testAppendToTopAutoSortChild() { - if(Member::currentUser()) { Member::currentUser()->logOut(); } - - //Push the edit date into the past, we're checking this later - DB::query('UPDATE "GridFieldAction_SortOrder_BaseObject" SET "LastEdited"=\''.date('Y-m-d 00:00:00', strtotime('yesterday')).'\''); - - $parent = GridFieldAction_SortOrder_TestParent::get()->first(); - $list = $parent->TestRelation(); - $config = GridFieldConfig::create()->addComponent(new GridFieldSortableRows('SortOrder')); - $gridField = new GridField('testfield', 'testfield', $list, $config); - $form = new Form(new Controller(), 'mockform', new FieldList(array($gridField)), new FieldList()); - $form->loadDataFrom($parent); - - $gridField->getConfig()->getComponentByType('GridFieldSortableRows')->setAppendToTop(true); - - $this->assertEquals(0, $list->last()->SortOrder, 'Auto sort should not have run'); - - $stateID = 'testGridStateActionField'; - Session::set($stateID, array('grid'=>'', 'actionName'=>'sortableRowsToggle', 'args'=>array('GridFieldSortableRows'=>array('sortableToggle'=>true)))); - $request = new SS_HTTPRequest('POST', 'url', array(), array('action_gridFieldAlterAction?StateID='.$stateID=>true, $form->getSecurityToken()->getName()=>$form->getSecurityToken()->getValue())); - $gridField->gridFieldAlterAction(array('StateID'=>$stateID), $form, $request); - - //Insure sort ran - $this->assertEquals(3, $list->last()->SortOrder, 'Auto sort should have run'); - - - //Check for duplicates (there shouldn't be any) - $count=$list->Count(); - $indexes=count(array_unique($list->column('SortOrder'))); - $this->assertEquals(0, $count-$indexes, 'Duplicate indexes detected'); - - - //Make sure the last edited is today for all records - $this->assertEquals(3, $list->filter('LastEdited:GreaterThan', date('Y-m-d 00:00:00'))->count()); - } +namespace UndefinedOffset\SortableGridField\Tests; + +use SilverStripe\Control\Controller; +use SilverStripe\Control\HTTPRequest; +use SilverStripe\Control\Session; +use SilverStripe\Dev\SapphireTest; +use SilverStripe\Dev\TestOnly; +use SilverStripe\Forms\FieldList; +use SilverStripe\Forms\Form; +use SilverStripe\Forms\GridField\GridField; +use SilverStripe\Forms\GridField\GridFieldConfig; +use SilverStripe\ORM\DataList; +use SilverStripe\ORM\DataObject; +use SilverStripe\ORM\DB; +use SilverStripe\Security\Member; +use SilverStripe\Versioned\Versioned; +use UndefinedOffset\SortableGridField\Forms\GridFieldSortableRows; + +/** + * Class GridFieldSortableRowsAutoSortTest + * + * @package SortableGridField\Tests + */ +class GridFieldSortableRowsAutoSortTest extends SapphireTest +{ + /** @var string */ + public static $fixture_file = 'sortablegridfield/tests/forms/GridFieldSortableRowsAutoSortTest.yml'; + + /** @var array */ + protected static $extra_dataobjects = array( + GridFieldAction_SortOrder_Player::class, + GridFieldAction_SortOrder_VPlayer::class, + GridFieldAction_SortOrder_TestParent::class, + GridFieldAction_SortOrder_BaseObject::class, + GridFieldAction_SortOrder_ChildObject::class + ); + + public function testAutoSort() + { + if (Member::currentUser()) { + Member::currentUser()->logOut(); + } + + $list = GridFieldAction_SortOrder_Player::get(); + $config = GridFieldConfig::create()->addComponent(new GridFieldSortableRows('SortOrder')); + $gridField = new GridField('testfield', 'testfield', $list, $config); + $form = new Form(new SortableGridField_DummyController(), 'mockform', new FieldList(array($gridField)), new FieldList()); + + $stateID = 'testGridStateActionField'; + Session::set($stateID, array('grid' => '', 'actionName' => 'sortableRowsToggle', 'args' => array('GridFieldSortableRows' => array('sortableToggle' => true)))); + $request = new HTTPRequest('POST', 'url', array(), array('action_gridFieldAlterAction?StateID=' . $stateID => true, $form->getSecurityToken()->getName() => $form->getSecurityToken()->getValue())); + $gridField->gridFieldAlterAction(array('StateID' => $stateID), $form, $request); + + //Insure sort ran + $this->assertEquals(3, $list->last()->SortOrder, 'Auto sort should have run'); + + + //Check for duplicates (there shouldn't be any) + $count = $list->Count(); + $indexes = count(array_unique($list->column('SortOrder'))); + $this->assertEquals(0, $count - $indexes, 'Duplicate indexes detected'); + } + + public function testAppendToTopAutoSort() + { + if (Member::currentUser()) { + Member::currentUser()->logOut(); + } + + $list = GridFieldAction_SortOrder_Player::get(); + $config = GridFieldConfig::create()->addComponent(new GridFieldSortableRows('SortOrder')); + $gridField = new GridField('testfield', 'testfield', $list, $config); + $form = new Form(new SortableGridField_DummyController(), 'mockform', new FieldList(array($gridField)), new FieldList()); + + /** @var GridFieldSortableRows $sortableRows */ + $sortableRows = $gridField->getConfig()->getComponentByType(GridFieldSortableRows::class); + $sortableRows->setAppendToTop(true); + + $this->assertEquals(0, $list->last()->SortOrder, 'Auto sort should not have run'); + + $stateID = 'testGridStateActionField'; + Session::set($stateID, array('grid' => '', 'actionName' => 'sortableRowsToggle', 'args' => array('GridFieldSortableRows' => array('sortableToggle' => true)))); + $request = new HTTPRequest('POST', 'url', array(), array('action_gridFieldAlterAction?StateID=' . $stateID => true, $form->getSecurityToken()->getName() => $form->getSecurityToken()->getValue())); + $gridField->gridFieldAlterAction(array('StateID' => $stateID), $form, $request); + + //Insure sort ran + $this->assertEquals(3, $list->last()->SortOrder, 'Auto sort should have run'); + + + //Check for duplicates (there shouldn't be any) + $count = $list->Count(); + $indexes = count(array_unique($list->column('SortOrder'))); + $this->assertEquals(0, $count - $indexes, 'Duplicate indexes detected'); + } + + public function testAutoSortVersioned() + { + if (Member::currentUser()) { + Member::currentUser()->logOut(); + } + + //Force versioned to reset + Versioned::reset(); + + $list = GridFieldAction_SortOrder_VPlayer::get(); + + //Publish all records + foreach ($list as $item) { + $item->publish('Stage', 'Live'); + } + + + $config = GridFieldConfig::create()->addComponent(new GridFieldSortableRows('SortOrder', true, 'Live')); + $gridField = new GridField('testfield', 'testfield', $list, $config); + $form = new Form(new SortableGridField_DummyController(), 'mockform', new FieldList(array($gridField)), new FieldList()); + + $stateID = 'testGridStateActionField'; + Session::set($stateID, array('grid' => '', 'actionName' => 'sortableRowsToggle', 'args' => array('GridFieldSortableRows' => array('sortableToggle' => true)))); + $request = new HTTPRequest('POST', 'url', array(), array('action_gridFieldAlterAction?StateID=' . $stateID => true, $form->getSecurityToken()->getName() => $form->getSecurityToken()->getValue())); + $gridField->gridFieldAlterAction(array('StateID' => $stateID), $form, $request); + + + //Insure sort ran + $this->assertEquals(3, $list->last()->SortOrder, 'Auto sort should have run on Versioned stage "Stage"'); + + + //Check for duplicates (there shouldn't be any) + $count = $list->Count(); + $indexes = count(array_unique($list->column('SortOrder'))); + $this->assertEquals(0, $count - $indexes, 'Duplicate indexes detected on Versioned stage "Stage"'); + + + //Force versioned over to Live stage + Versioned::set_reading_mode('Live'); + + //Get live instance + $obj = Versioned::get_one_by_stage(GridFieldAction_SortOrder_VPlayer::class, 'Live', '"ID"=' . $list->last()->ID); + + //Insure sort ran + $this->assertEquals(3, $obj->SortOrder, 'Auto sort should have run on Versioned stage "Live"'); + + + //Check for duplicates (there shouldn't be any) + $list = Versioned::get_by_stage(GridFieldAction_SortOrder_VPlayer::class, 'Live'); + $count = $list->Count(); + $indexes = count(array_unique($list->column('SortOrder'))); + $this->assertEquals(0, $count - $indexes, 'Duplicate indexes detected on Versioned stage "Live"'); + } + + public function testAppendToTopAutoSortVersioned() + { + if (Member::currentUser()) { + Member::currentUser()->logOut(); + } + + //Force versioned to reset + Versioned::reset(); + + $list = GridFieldAction_SortOrder_VPlayer::get(); + + //Publish all records + foreach ($list as $item) { + $item->publish('Stage', 'Live'); + } + + + $config = GridFieldConfig::create()->addComponent(new GridFieldSortableRows('SortOrder', true, 'Live')); + $gridField = new GridField('testfield', 'testfield', $list, $config); + $form = new Form(new SortableGridField_DummyController(), 'mockform', new FieldList(array($gridField)), new FieldList()); + + /** @var GridFieldSortableRows $sortableRows */ + $sortableRows = $gridField->getConfig()->getComponentByType(GridFieldSortableRows::class); + $sortableRows->setAppendToTop(true); + + $this->assertEquals(0, $list->last()->SortOrder, 'Auto sort should not have run on Versioned stage "Stage"'); + + $stateID = 'testGridStateActionField'; + Session::set($stateID, array('grid' => '', 'actionName' => 'sortableRowsToggle', 'args' => array('GridFieldSortableRows' => array('sortableToggle' => true)))); + $request = new HTTPRequest('POST', 'url', array(), array('action_gridFieldAlterAction?StateID=' . $stateID => true, $form->getSecurityToken()->getName() => $form->getSecurityToken()->getValue())); + $gridField->gridFieldAlterAction(array('StateID' => $stateID), $form, $request); + + + //Insure sort ran + $this->assertEquals(3, $list->last()->SortOrder, 'Auto sort should have run on Versioned stage "Stage"'); + + + //Check for duplicates (there shouldn't be any) + $count = $list->Count(); + $indexes = count(array_unique($list->column('SortOrder'))); + $this->assertEquals(0, $count - $indexes, 'Duplicate indexes detected on Versioned stage "Stage"'); + + + //Force versioned over to Live stage + Versioned::set_reading_mode('Live'); + + //Insure sort ran + $this->assertEquals(3, $list->last()->SortOrder, 'Auto sort should have run on Versioned stage "Live"'); + + + //Check for duplicates (there shouldn't be any) + $count = $list->Count(); + $indexes = count(array_unique($list->column('SortOrder'))); + $this->assertEquals(0, $count - $indexes, 'Duplicate indexes detected on Versioned stage "Live"'); + } + + public function testAppendToTopAutoSortChild() + { + if (Member::currentUser()) { + Member::currentUser()->logOut(); + } + + //Push the edit date into the past, we're checking this later + DB::query('UPDATE "GridFieldAction_SortOrder_BaseObject" SET "LastEdited"=\'' . date('Y-m-d 00:00:00', strtotime('yesterday')) . '\''); + + /** @var GridFieldAction_SortOrder_TestParent $parent */ + $parent = GridFieldAction_SortOrder_TestParent::get()->first(); + + /** @var DataList $list */ + $list = $parent->TestRelation(); + + $config = GridFieldConfig::create()->addComponent(new GridFieldSortableRows('SortOrder')); + $gridField = new GridField('testfield', 'testfield', $list, $config); + $form = new Form(new SortableGridField_DummyController(), 'mockform', new FieldList(array($gridField)), new FieldList()); + $form->loadDataFrom($parent); + + /** @var GridFieldSortableRows $sortableRows */ + $sortableRows = $gridField->getConfig()->getComponentByType(GridFieldSortableRows::class); + $sortableRows->setAppendToTop(true); + + $this->assertEquals(0, $list->last()->SortOrder, 'Auto sort should not have run'); + + $stateID = 'testGridStateActionField'; + Session::set($stateID, array('grid' => '', 'actionName' => 'sortableRowsToggle', 'args' => array('GridFieldSortableRows' => array('sortableToggle' => true)))); + $request = new HTTPRequest('POST', 'url', array(), array('action_gridFieldAlterAction?StateID=' . $stateID => true, $form->getSecurityToken()->getName() => $form->getSecurityToken()->getValue())); + $gridField->gridFieldAlterAction(array('StateID' => $stateID), $form, $request); + + //Insure sort ran + $this->assertEquals(3, $list->last()->SortOrder, 'Auto sort should have run'); + + + //Check for duplicates (there shouldn't be any) + $count = $list->Count(); + $indexes = count(array_unique($list->column('SortOrder'))); + $this->assertEquals(0, $count - $indexes, 'Duplicate indexes detected'); + + + //Make sure the last edited is today for all records + $this->assertEquals(3, $list->filter('LastEdited:GreaterThan', date('Y-m-d 00:00:00'))->count()); + } } -class GridFieldAction_SortOrder_Player extends DataObject implements TestOnly { - static $db = array( - 'Name' => 'Varchar', - 'SortOrder' => 'Int' - ); - - static $default_sort='SortOrder'; +/** + * Class GridFieldAction_SortOrder_Player + * + * @package SortableGridField\Tests + * @property string Name + * @property int SortOrder + */ +class GridFieldAction_SortOrder_Player extends DataObject implements TestOnly +{ + private static $table_name = 'GridFieldAction_SortOrder_Player'; + + private static $db = array( + 'Name' => 'Varchar', + 'SortOrder' => 'Int' + ); + + private static $default_sort = 'SortOrder'; } -class GridFieldAction_SortOrder_VPlayer extends DataObject implements TestOnly { - static $db = array( - 'Name' => 'Varchar', - 'SortOrder' => 'Int' - ); - - static $default_sort = 'SortOrder'; - - static $extensions=array( - "Versioned('Stage', 'Live')" - ); +/** + * Class GridFieldAction_SortOrder_VPlayer + * + * @package SortableGridField\Tests + * @property string Name + * @property int SortOrder + */ +class GridFieldAction_SortOrder_VPlayer extends DataObject implements TestOnly +{ + private static $table_name = 'GridFieldAction_SortOrder_VPlayer'; + + private static $db = array( + 'Name' => 'Varchar', + 'SortOrder' => 'Int' + ); + + private static $default_sort = 'SortOrder'; + + private static $extensions = array( + "SilverStripe\\Versioned\\Versioned('Stage', 'Live')" + ); } -class GridFieldAction_SortOrder_TestParent extends DataObject implements TestOnly { - static $db = array( - 'Name' => 'Varchar' - ); - - static $has_many = array( - 'TestRelation' => 'GridFieldAction_SortOrder_ChildObject' - ); +/** + * Class GridFieldAction_SortOrder_TestParent + * + * @package SortableGridField\Tests + * @property string Name + * @method GridFieldAction_SortOrder_ChildObject TestRelation + */ +class GridFieldAction_SortOrder_TestParent extends DataObject implements TestOnly +{ + private static $table_name = 'GridFieldAction_SortOrder_TestParent'; + + private static $db = array( + 'Name' => 'Varchar' + ); + + private static $has_many = array( + 'TestRelation' => GridFieldAction_SortOrder_ChildObject::class + ); } -class GridFieldAction_SortOrder_BaseObject extends DataObject implements TestOnly { - static $db = array( - 'Name' => 'Varchar' - ); +/** + * Class GridFieldAction_SortOrder_BaseObject + * + * @package SortableGridField\Tests + * @property string Name + */ +class GridFieldAction_SortOrder_BaseObject extends DataObject implements TestOnly +{ + private static $table_name = 'GridFieldAction_SortOrder_BaseObject'; + + private static $db = array( + 'Name' => 'Varchar' + ); } -class GridFieldAction_SortOrder_ChildObject extends GridFieldAction_SortOrder_BaseObject implements TestOnly { - static $db = array( - 'SortOrder' => 'Int' - ); - - static $has_one = array( - 'Parent'=>'GridFieldAction_SortOrder_TestParent' - ); - - static $default_sort='SortOrder'; +/** + * Class GridFieldAction_SortOrder_ChildObject + * + * @package SortableGridField\Tests + * @property int SortOrder + * @method GridFieldAction_SortOrder_TestParent Parent + */ +class GridFieldAction_SortOrder_ChildObject extends GridFieldAction_SortOrder_BaseObject implements TestOnly +{ + private static $table_name = 'GridFieldAction_SortOrder_ChildObject'; + + private static $db = array( + 'SortOrder' => 'Int' + ); + + private static $has_one = array( + 'Parent' => GridFieldAction_SortOrder_TestParent::class + ); + + private static $default_sort = 'SortOrder'; } -?> \ No newline at end of file + +/** + * Class SortableGridField_DummyController + * + * @package SortableGridField\Tests + */ +class SortableGridField_DummyController extends Controller +{ + private static $url_segment = 'sortable-grid-field'; +} \ No newline at end of file diff --git a/tests/forms/GridFieldSortableRowsAutoSortTest.yml b/tests/forms/GridFieldSortableRowsAutoSortTest.yml index af91f76..826514c 100644 --- a/tests/forms/GridFieldSortableRowsAutoSortTest.yml +++ b/tests/forms/GridFieldSortableRowsAutoSortTest.yml @@ -1,39 +1,39 @@ -GridFieldAction_SortOrder_Player: - player1: - Name: Player 1 - SortOrder: 0 - player2: - Name: Player 2 - SortOrder: 0 - player3: - Name: Player 3 - SortOrder: 0 +UndefinedOffset\SortableGridField\Tests\GridFieldAction_SortOrder_Player: + player1: + Name: Player 1 + SortOrder: 0 + player2: + Name: Player 2 + SortOrder: 0 + player3: + Name: Player 3 + SortOrder: 0 -GridFieldAction_SortOrder_VPlayer: - player1: - Name: Player 1 - SortOrder: 0 - player2: - Name: Player 2 - SortOrder: 0 - player3: - Name: Player 3 - SortOrder: 0 +UndefinedOffset\SortableGridField\Tests\GridFieldAction_SortOrder_VPlayer: + player1: + Name: Player 1 + SortOrder: 0 + player2: + Name: Player 2 + SortOrder: 0 + player3: + Name: Player 3 + SortOrder: 0 -GridFieldAction_SortOrder_TestParent: - testparent: - Name: Test +UndefinedOffset\SortableGridField\Tests\GridFieldAction_SortOrder_TestParent: + testparent: + Name: Test -GridFieldAction_SortOrder_ChildObject: - testitem1: - Name: Test 1 - SortOrder: 0 - Parent: =>GridFieldAction_SortOrder_TestParent.testparent - testitem2: - Name: Test 2 - SortOrder: 0 - Parent: =>GridFieldAction_SortOrder_TestParent.testparent - testitem3: - Name: Test 3 - SortOrder: 0 - Parent: =>GridFieldAction_SortOrder_TestParent.testparent \ No newline at end of file +UndefinedOffset\SortableGridField\Tests\GridFieldAction_SortOrder_ChildObject: + testitem1: + Name: Test 1 + SortOrder: 0 + Parent: =>UndefinedOffset\SortableGridField\Tests\GridFieldAction_SortOrder_TestParent.testparent + testitem2: + Name: Test 2 + SortOrder: 0 + Parent: =>UndefinedOffset\SortableGridField\Tests\GridFieldAction_SortOrder_TestParent.testparent + testitem3: + Name: Test 3 + SortOrder: 0 + Parent: =>UndefinedOffset\SortableGridField\Tests\GridFieldAction_SortOrder_TestParent.testparent \ No newline at end of file diff --git a/tests/forms/GridFieldSortableRowsPageTest.php b/tests/forms/GridFieldSortableRowsPageTest.php index c5c92e7..70491b6 100644 --- a/tests/forms/GridFieldSortableRowsPageTest.php +++ b/tests/forms/GridFieldSortableRowsPageTest.php @@ -1,171 +1,225 @@ list = GridFieldAction_PageSortOrder_Team::get(); - $config = GridFieldConfig_Base::create(5)->addComponent(new GridFieldSortableRows('SortOrder')); - $this->gridField = new GridField('testfield', 'testfield', $this->list, $config); - $this->form = new Form(new Controller(), 'mockform', new FieldList(array($this->gridField)), new FieldList()); - } - - public function testSortToNextPage() { - $this->gridField->State->GridFieldPaginator->currentPage=1; - - - $team3 = $this->objFromFixture('GridFieldAction_PageSortOrder_Team', 'team3'); - - $this->logInWithPermission('ADMIN'); - $stateID = 'testGridStateActionField'; - Session::set($stateID, array('grid'=>'', 'actionName'=>'sortToPage', 'args'=>array('GridFieldSortableRows'=>array('sortableToggle'=>true), 'GridFieldPaginator'=>array('currentPage'=>1)))); - $request = new SS_HTTPRequest('POST', 'url', array('ItemID'=>$team3->ID, 'Target'=>'nextpage'), array('action_gridFieldAlterAction?StateID='.$stateID=>true, $this->form->getSecurityToken()->getName()=>$this->form->getSecurityToken()->getValue())); - $this->gridField->gridFieldAlterAction(array('StateID'=>$stateID), $this->form, $request); - - - $team6 = $this->objFromFixture('GridFieldAction_PageSortOrder_Team', 'team6'); - $this->assertEquals(5, $team6->SortOrder, 'Team 6 Should have moved to the bottom of the first page'); - - $team3 = $this->objFromFixture('GridFieldAction_PageSortOrder_Team', 'team3'); - $this->assertEquals(6, $team3->SortOrder, 'Team 3 Should have moved to the top of the second page'); - } - - public function testSortToPrevPage() { - $this->gridField->State->GridFieldPaginator->currentPage=2; - - - $team7 = $this->objFromFixture('GridFieldAction_PageSortOrder_Team', 'team7'); - - $this->logInWithPermission('ADMIN'); - $stateID = 'testGridStateActionField'; - Session::set($stateID, array('grid'=>'', 'actionName'=>'sortToPage', 'args'=>array('GridFieldSortableRows'=>array('sortableToggle'=>true), 'GridFieldPaginator'=>array('currentPage'=>1)))); - $request = new SS_HTTPRequest('POST', 'url', array('ItemID'=>$team7->ID, 'Target'=>'previouspage'), array('action_gridFieldAlterAction?StateID='.$stateID=>true, $this->form->getSecurityToken()->getName()=>$this->form->getSecurityToken()->getValue())); - $this->gridField->gridFieldAlterAction(array('StateID'=>$stateID), $this->form, $request); - - - $team7 = $this->objFromFixture('GridFieldAction_PageSortOrder_Team', 'team7'); - $this->assertEquals(5, $team7->SortOrder, 'Team 7 Should have moved to the bottom of the first page'); - - $team5 = $this->objFromFixture('GridFieldAction_PageSortOrder_Team', 'team5'); - $this->assertEquals(6, $team5->SortOrder, 'Team 5 Should have moved to the top of the second page'); - } - - public function testSortToNextPageVersioned() { - //Force versioned to reset - Versioned::reset(); - - $list=GridFieldAction_PageSortOrder_VTeam::get(); - $this->gridField->setList($list); - $this->gridField->getConfig()->getComponentByType('GridFieldSortableRows')->setUpdateVersionedStage('Live'); - $this->gridField->State->GridFieldPaginator->currentPage=1; - - //Publish all records - foreach($list as $item) { - $item->publish('Stage', 'Live'); - } - - - $team3 = $this->objFromFixture('GridFieldAction_PageSortOrder_VTeam', 'team3'); - - $this->logInWithPermission('ADMIN'); - $stateID = 'testGridStateActionField'; - Session::set($stateID, array('grid'=>'', 'actionName'=>'sortToPage', 'args'=>array('GridFieldSortableRows'=>array('sortableToggle'=>true), 'GridFieldPaginator'=>array('currentPage'=>1)))); - $request = new SS_HTTPRequest('POST', 'url', array('ItemID'=>$team3->ID, 'Target'=>'nextpage'), array('action_gridFieldAlterAction?StateID='.$stateID=>true, $this->form->getSecurityToken()->getName()=>$this->form->getSecurityToken()->getValue())); - $this->gridField->gridFieldAlterAction(array('StateID'=>$stateID), $this->form, $request); - - - $team6 = $this->objFromFixture('GridFieldAction_PageSortOrder_VTeam', 'team6'); - $this->assertEquals(5, $team6->SortOrder, 'Team 6 Should have moved to the bottom of the first page on Versioned stage "Stage"'); - - $team3 = $this->objFromFixture('GridFieldAction_PageSortOrder_VTeam', 'team3'); - $this->assertEquals(6, $team3->SortOrder, 'Team 3 Should have moved to the top of the second page on Versioned stage "Stage"'); - - - $list=Versioned::get_by_stage('GridFieldAction_PageSortOrder_VTeam', 'Live'); - - $team6 = $list->byID($team6->ID); - $this->assertEquals(5, $team6->SortOrder, 'Team 6 Should have moved to the bottom of the first page on Versioned stage "Live"'); - - $team3 = $list->byID($team3->ID); - $this->assertEquals(6, $team3->SortOrder, 'Team 3 Should have moved to the top of the second page on Versioned stage "Live"'); - } - - public function testSortToPrevPageVersioned() { - //Force versioned to reset - Versioned::reset(); - - $list=GridFieldAction_PageSortOrder_VTeam::get(); - $this->gridField->setList($list); - $this->gridField->getConfig()->getComponentByType('GridFieldSortableRows')->setUpdateVersionedStage('Live'); - $this->gridField->State->GridFieldPaginator->currentPage=2; - - //Publish all records - foreach($list as $item) { - $item->publish('Stage', 'Live'); - } - - - $team7 = $this->objFromFixture('GridFieldAction_PageSortOrder_VTeam', 'team7'); - - $this->logInWithPermission('ADMIN'); - $stateID = 'testGridStateActionField'; - Session::set($stateID, array('grid'=>'', 'actionName'=>'sortToPage', 'args'=>array('GridFieldSortableRows'=>array('sortableToggle'=>true), 'GridFieldPaginator'=>array('currentPage'=>1)))); - $request = new SS_HTTPRequest('POST', 'url', array('ItemID'=>$team7->ID, 'Target'=>'previouspage'), array('action_gridFieldAlterAction?StateID='.$stateID=>true, $this->form->getSecurityToken()->getName()=>$this->form->getSecurityToken()->getValue())); - $this->gridField->gridFieldAlterAction(array('StateID'=>$stateID), $this->form, $request); - - - $team7 = $this->objFromFixture('GridFieldAction_PageSortOrder_VTeam', 'team7'); - $this->assertEquals(5, $team7->SortOrder, 'Team 7 Should have moved to the bottom of the first page on Versioned stage "Stage"'); - - $team5 = $this->objFromFixture('GridFieldAction_PageSortOrder_VTeam', 'team5'); - $this->assertEquals(6, $team5->SortOrder, 'Team 5 Should have moved to the top of the second page on Versioned stage "Stage"'); - - - $list=Versioned::get_by_stage('GridFieldAction_PageSortOrder_VTeam', 'Live'); - - $team7 = $list->byID($team7->ID); - $this->assertEquals(5, $team7->SortOrder, 'Team 7 Should have moved to the bottom of the first page on Versioned stage "Live"'); - - $team5 = $list->byID($team5->ID); - $this->assertEquals(6, $team5->SortOrder, 'Team 5 Should have moved to the top of the second page on Versioned stage "Live"'); - } +use SilverStripe\Control\Controller; +use SilverStripe\Control\HTTPRequest; +use SilverStripe\Control\Session; +use SilverStripe\Dev\SapphireTest; +use SilverStripe\Dev\TestOnly; +use SilverStripe\Forms\FieldList; +use SilverStripe\Forms\Form; +use SilverStripe\Forms\GridField\GridField; +use SilverStripe\Forms\GridField\GridFieldConfig_Base; +use SilverStripe\ORM\ArrayList; +use SilverStripe\ORM\DataObject; +use SilverStripe\Versioned\Versioned; +use UndefinedOffset\SortableGridField\Forms\GridFieldSortableRows; + +/** + * Class GridFieldSortableRowsPageTest + * + * @package SortableGridField\Tests + */ +class GridFieldSortableRowsPageTest extends SapphireTest +{ + /** @var ArrayList */ + protected $list; + + /** @var GridField */ + protected $gridField; + + /** @var Form */ + protected $form; + + /** @var string */ + public static $fixture_file = 'sortablegridfield/tests/forms/GridFieldSortableRowsPageTest.yml'; + + /** @var array */ + protected static $extra_dataobjects = array( + GridFieldAction_PageSortOrder_Team::class, + GridFieldAction_PageSortOrder_VTeam::class + ); + + public function setUp() + { + parent::setUp(); + $this->list = GridFieldAction_PageSortOrder_Team::get(); + $config = GridFieldConfig_Base::create(5)->addComponent(new GridFieldSortableRows('SortOrder')); + $this->gridField = new GridField('testfield', 'testfield', $this->list, $config); + $this->form = new Form(new SortableGridField_DummyController(), 'mockform', FieldList::create(array($this->gridField)), FieldList::create()); + } + + public function testSortToNextPage() + { + $this->gridField->State->GridFieldPaginator->currentPage = 1; + + $team3 = $this->objFromFixture('UndefinedOffset\SortableGridField\Tests\GridFieldAction_PageSortOrder_Team', 'team3'); + + $this->logInWithPermission('ADMIN'); + $stateID = 'testGridStateActionField'; + Session::set($stateID, array('grid' => '', 'actionName' => 'sortToPage', 'args' => array('GridFieldSortableRows' => array('sortableToggle' => true), 'GridFieldPaginator' => array('currentPage' => 1)))); + $request = new HTTPRequest('POST', 'url', array('ItemID' => $team3->ID, 'Target' => 'nextpage'), array('action_gridFieldAlterAction?StateID=' . $stateID => true, $this->form->getSecurityToken()->getName() => $this->form->getSecurityToken()->getValue())); + $this->gridField->gridFieldAlterAction(array('StateID' => $stateID), $this->form, $request); + + $team6 = $this->objFromFixture('UndefinedOffset\SortableGridField\Tests\GridFieldAction_PageSortOrder_Team', 'team6'); + $this->assertEquals(5, $team6->SortOrder, 'Team 6 Should have moved to the bottom of the first page'); + + $team3 = $this->objFromFixture('UndefinedOffset\SortableGridField\Tests\GridFieldAction_PageSortOrder_Team', 'team3'); + $this->assertEquals(6, $team3->SortOrder, 'Team 3 Should have moved to the top of the second page'); + } + + public function testSortToPrevPage() + { + $this->gridField->State->GridFieldPaginator->currentPage = 2; + + $team7 = $this->objFromFixture('UndefinedOffset\SortableGridField\Tests\GridFieldAction_PageSortOrder_Team', 'team7'); + + $this->logInWithPermission('ADMIN'); + $stateID = 'testGridStateActionField'; + Session::set($stateID, array('grid' => '', 'actionName' => 'sortToPage', 'args' => array('GridFieldSortableRows' => array('sortableToggle' => true), 'GridFieldPaginator' => array('currentPage' => 1)))); + $request = new HTTPRequest('POST', 'url', array('ItemID' => $team7->ID, 'Target' => 'previouspage'), array('action_gridFieldAlterAction?StateID=' . $stateID => true, $this->form->getSecurityToken()->getName() => $this->form->getSecurityToken()->getValue())); + $this->gridField->gridFieldAlterAction(array('StateID' => $stateID), $this->form, $request); + + + $team7 = $this->objFromFixture('UndefinedOffset\SortableGridField\Tests\GridFieldAction_PageSortOrder_Team', 'team7'); + $this->assertEquals(5, $team7->SortOrder, 'Team 7 Should have moved to the bottom of the first page'); + + $team5 = $this->objFromFixture('UndefinedOffset\SortableGridField\Tests\GridFieldAction_PageSortOrder_Team', 'team5'); + $this->assertEquals(6, $team5->SortOrder, 'Team 5 Should have moved to the top of the second page'); + } + + public function testSortToNextPageVersioned() + { + //Force versioned to reset + Versioned::reset(); + + $list = GridFieldAction_PageSortOrder_VTeam::get(); + $this->gridField->setList($list); + + /** @var GridFieldSortableRows $sortableGrid */ + $sortableGrid = $this->gridField->getConfig()->getComponentByType(GridFieldSortableRows::class); + $sortableGrid->setUpdateVersionedStage('Live'); + $this->gridField->State->GridFieldPaginator->currentPage = 1; + + //Publish all records + foreach ($list as $item) { + $item->publish('Stage', 'Live'); + } + + + $team3 = $this->objFromFixture('UndefinedOffset\SortableGridField\Tests\GridFieldAction_PageSortOrder_VTeam', 'team3'); + + $this->logInWithPermission('ADMIN'); + $stateID = 'testGridStateActionField'; + Session::set($stateID, array('grid' => '', 'actionName' => 'sortToPage', 'args' => array('GridFieldSortableRows' => array('sortableToggle' => true), 'GridFieldPaginator' => array('currentPage' => 1)))); + $request = new HTTPRequest('POST', 'url', array('ItemID' => $team3->ID, 'Target' => 'nextpage'), array('action_gridFieldAlterAction?StateID=' . $stateID => true, $this->form->getSecurityToken()->getName() => $this->form->getSecurityToken()->getValue())); + $this->gridField->gridFieldAlterAction(array('StateID' => $stateID), $this->form, $request); + + + $team6 = $this->objFromFixture('UndefinedOffset\SortableGridField\Tests\GridFieldAction_PageSortOrder_VTeam', 'team6'); + $this->assertEquals(5, $team6->SortOrder, 'Team 6 Should have moved to the bottom of the first page on Versioned stage "Stage"'); + + $team3 = $this->objFromFixture('UndefinedOffset\SortableGridField\Tests\GridFieldAction_PageSortOrder_VTeam', 'team3'); + $this->assertEquals(6, $team3->SortOrder, 'Team 3 Should have moved to the top of the second page on Versioned stage "Stage"'); + + + $list = Versioned::get_by_stage(GridFieldAction_PageSortOrder_VTeam::class, 'Live'); + + $team6 = $list->byID($team6->ID); + $this->assertEquals(5, $team6->SortOrder, 'Team 6 Should have moved to the bottom of the first page on Versioned stage "Live"'); + + $team3 = $list->byID($team3->ID); + $this->assertEquals(6, $team3->SortOrder, 'Team 3 Should have moved to the top of the second page on Versioned stage "Live"'); + } + + public function testSortToPrevPageVersioned() + { + //Force versioned to reset + Versioned::reset(); + + $list = GridFieldAction_PageSortOrder_VTeam::get(); + $this->gridField->setList($list); + + /** @var GridFieldSortableRows $sortableGrid */ + $sortableGrid = $this->gridField->getConfig()->getComponentByType(GridFieldSortableRows::class); + $sortableGrid->setUpdateVersionedStage('Live'); + $this->gridField->State->GridFieldPaginator->currentPage = 2; + + //Publish all records + foreach ($list as $item) { + $item->publish('Stage', 'Live'); + } + + + $team7 = $this->objFromFixture('UndefinedOffset\SortableGridField\Tests\GridFieldAction_PageSortOrder_VTeam', 'team7'); + + $this->logInWithPermission('ADMIN'); + $stateID = 'testGridStateActionField'; + Session::set($stateID, array('grid' => '', 'actionName' => 'sortToPage', 'args' => array('GridFieldSortableRows' => array('sortableToggle' => true), 'GridFieldPaginator' => array('currentPage' => 1)))); + $request = new HTTPRequest('POST', 'url', array('ItemID' => $team7->ID, 'Target' => 'previouspage'), array('action_gridFieldAlterAction?StateID=' . $stateID => true, $this->form->getSecurityToken()->getName() => $this->form->getSecurityToken()->getValue())); + $this->gridField->gridFieldAlterAction(array('StateID' => $stateID), $this->form, $request); + + + $team7 = $this->objFromFixture('UndefinedOffset\SortableGridField\Tests\GridFieldAction_PageSortOrder_VTeam', 'team7'); + $this->assertEquals(5, $team7->SortOrder, 'Team 7 Should have moved to the bottom of the first page on Versioned stage "Stage"'); + + $team5 = $this->objFromFixture('UndefinedOffset\SortableGridField\Tests\GridFieldAction_PageSortOrder_VTeam', 'team5'); + $this->assertEquals(6, $team5->SortOrder, 'Team 5 Should have moved to the top of the second page on Versioned stage "Stage"'); + + + $list = Versioned::get_by_stage(GridFieldAction_PageSortOrder_VTeam::class, 'Live'); + + $team7 = $list->byID($team7->ID); + $this->assertEquals(5, $team7->SortOrder, 'Team 7 Should have moved to the bottom of the first page on Versioned stage "Live"'); + + $team5 = $list->byID($team5->ID); + $this->assertEquals(6, $team5->SortOrder, 'Team 5 Should have moved to the top of the second page on Versioned stage "Live"'); + } } -class GridFieldAction_PageSortOrder_Team extends DataObject implements TestOnly { - static $db = array( - 'Name' => 'Varchar', - 'City' => 'Varchar', - 'SortOrder' => 'Int' - ); - - static $default_sort='SortOrder'; +/** + * Class GridFieldAction_PageSortOrder_Team + * + * @package SortableGridField\Tests + * @property string Name + * @property string City + * @property int SortOrder + */ +class GridFieldAction_PageSortOrder_Team extends DataObject implements TestOnly +{ + private static $table_name = 'GridFieldAction_PageSortOrder_Team'; + + private static $db = array( + 'Name' => 'Varchar', + 'City' => 'Varchar', + 'SortOrder' => 'Int' + ); + + private static $default_sort = 'SortOrder'; } -class GridFieldAction_PageSortOrder_VTeam extends DataObject implements TestOnly { - static $db = array( - 'Name' => 'Varchar', - 'City' => 'Varchar', - 'SortOrder' => 'Int' - ); - - static $default_sort='SortOrder'; - - static $extensions=array( - "Versioned('Stage', 'Live')" - ); +/** + * Class GridFieldAction_PageSortOrder_VTeam + * + * @package SortableGridField\Tests + * @property string Name + * @property string City + * @property int SortOrder + */ +class GridFieldAction_PageSortOrder_VTeam extends DataObject implements TestOnly +{ + private static $table_name = 'GridFieldAction_PageSortOrder_VTeam'; + + private static $db = array( + 'Name' => 'Varchar', + 'City' => 'Varchar', + 'SortOrder' => 'Int' + ); + + private static $default_sort = 'SortOrder'; + + private static $extensions = array( + "SilverStripe\\Versioned\\Versioned('Stage', 'Live')" + ); } -?> \ No newline at end of file diff --git a/tests/forms/GridFieldSortableRowsPageTest.yml b/tests/forms/GridFieldSortableRowsPageTest.yml index 42d2609..0f6ffac 100644 --- a/tests/forms/GridFieldSortableRowsPageTest.yml +++ b/tests/forms/GridFieldSortableRowsPageTest.yml @@ -1,75 +1,75 @@ -GridFieldAction_PageSortOrder_Team: - team1: - Name: Team 1 - City: Cologne - SortOrder: 1 - team2: - Name: Team 2 - City: Wellington - SortOrder: 2 - team3: - Name: Team 3 - City: Auckland - SortOrder: 3 - team4: - Name: Team 4 - City: Cologne - SortOrder: 4 - team5: - Name: Team 5 - City: Wellington - SortOrder: 5 - team6: - Name: Team 6 - City: Auckland - SortOrder: 6 - team7: - Name: Team 7 - City: Cologne - SortOrder: 7 - team8: - Name: Team 8 - City: Wellington - SortOrder: 8 - team9: - Name: Team 9 - City: Auckland - SortOrder: 9 +UndefinedOffset\SortableGridField\Tests\GridFieldAction_PageSortOrder_Team: + team1: + Name: Team 1 + City: Cologne + SortOrder: 1 + team2: + Name: Team 2 + City: Wellington + SortOrder: 2 + team3: + Name: Team 3 + City: Auckland + SortOrder: 3 + team4: + Name: Team 4 + City: Cologne + SortOrder: 4 + team5: + Name: Team 5 + City: Wellington + SortOrder: 5 + team6: + Name: Team 6 + City: Auckland + SortOrder: 6 + team7: + Name: Team 7 + City: Cologne + SortOrder: 7 + team8: + Name: Team 8 + City: Wellington + SortOrder: 8 + team9: + Name: Team 9 + City: Auckland + SortOrder: 9 -GridFieldAction_PageSortOrder_VTeam: - team1: - Name: Team 1 - City: Cologne - SortOrder: 1 - team2: - Name: Team 2 - City: Wellington - SortOrder: 2 - team3: - Name: Team 3 - City: Auckland - SortOrder: 3 - team4: - Name: Team 4 - City: Cologne - SortOrder: 4 - team5: - Name: Team 5 - City: Wellington - SortOrder: 5 - team6: - Name: Team 6 - City: Auckland - SortOrder: 6 - team7: - Name: Team 7 - City: Cologne - SortOrder: 7 - team8: - Name: Team 8 - City: Wellington - SortOrder: 8 - team9: - Name: Team 9 - City: Auckland - SortOrder: 9 +UndefinedOffset\SortableGridField\Tests\GridFieldAction_PageSortOrder_VTeam: + team1: + Name: Team 1 + City: Cologne + SortOrder: 1 + team2: + Name: Team 2 + City: Wellington + SortOrder: 2 + team3: + Name: Team 3 + City: Auckland + SortOrder: 3 + team4: + Name: Team 4 + City: Cologne + SortOrder: 4 + team5: + Name: Team 5 + City: Wellington + SortOrder: 5 + team6: + Name: Team 6 + City: Auckland + SortOrder: 6 + team7: + Name: Team 7 + City: Cologne + SortOrder: 7 + team8: + Name: Team 8 + City: Wellington + SortOrder: 8 + team9: + Name: Team 9 + City: Auckland + SortOrder: 9 diff --git a/tests/forms/GridFieldSortableRowsTest.php b/tests/forms/GridFieldSortableRowsTest.php index 76a6c55..c4c49e8 100644 --- a/tests/forms/GridFieldSortableRowsTest.php +++ b/tests/forms/GridFieldSortableRowsTest.php @@ -1,106 +1,156 @@ list = GridFieldAction_SortOrder_Team::get(); - $config = GridFieldConfig::create()->addComponent(new GridFieldSortableRows('SortOrder')); - $this->gridField = new GridField('testfield', 'testfield', $this->list, $config); - $this->form = new Form(new Controller(), 'mockform', new FieldList(array($this->gridField)), new FieldList()); - } - - public function testSortActionWithoutCorrectPermission() { - if(Member::currentUser()) { Member::currentUser()->logOut(); } - $this->setExpectedException('ValidationException'); - $team1 = $this->objFromFixture('GridFieldAction_SortOrder_Team', 'team1'); - $team2 = $this->objFromFixture('GridFieldAction_SortOrder_Team', 'team2'); - $team3 = $this->objFromFixture('GridFieldAction_SortOrder_Team', 'team3'); - - $stateID = 'testGridStateActionField'; - Session::set($stateID, array('grid'=>'', 'actionName'=>'saveGridRowSort', 'args'=>array('GridFieldSortableRows'=>array('sortableToggle'=>true)))); - $request = new SS_HTTPRequest('POST', 'url', array('ItemIDs'=>"$team1->ID, $team3->ID, $team2->ID"), array('action_gridFieldAlterAction?StateID='.$stateID=>true, $this->form->getSecurityToken()->getName()=>$this->form->getSecurityToken()->getValue())); - $this->gridField->gridFieldAlterAction(array('StateID'=>$stateID), $this->form, $request); - $this->assertEquals($team3->ID, $this->list->last()->ID, 'User should\'t be able to sort records without correct permissions.'); - } - - public function testSortActionWithAdminPermission() { - $team1 = $this->objFromFixture('GridFieldAction_SortOrder_Team', 'team1'); - $team2 = $this->objFromFixture('GridFieldAction_SortOrder_Team', 'team2'); - $team3 = $this->objFromFixture('GridFieldAction_SortOrder_Team', 'team3'); - $this->logInWithPermission('ADMIN'); - $stateID = 'testGridStateActionField'; - Session::set($stateID, array('grid'=>'', 'actionName'=>'saveGridRowSort', 'args'=>array('GridFieldSortableRows'=>array('sortableToggle'=>true)))); - $request = new SS_HTTPRequest('POST', 'url', array('ItemIDs'=>"$team1->ID, $team3->ID, $team2->ID"), array('action_gridFieldAlterAction?StateID='.$stateID=>true, $this->form->getSecurityToken()->getName()=>$this->form->getSecurityToken()->getValue())); - $this->gridField->gridFieldAlterAction(array('StateID'=>$stateID), $this->form, $request); - $this->assertEquals($team2->ID, $this->list->last()->ID, 'User should be able to sort records with ADMIN permission.'); - } - - public function testSortActionVersioned() { - //Force versioned to reset - Versioned::reset(); - - $list = GridFieldAction_SortOrder_VTeam::get(); - $this->gridField->setList($list); - $this->gridField->getConfig()->getComponentByType('GridFieldSortableRows')->setUpdateVersionedStage('Live'); - - //Publish all records - foreach($list as $item) { - $item->publish('Stage', 'Live'); - } - - $team1 = $this->objFromFixture('GridFieldAction_SortOrder_VTeam', 'team1'); - $team2 = $this->objFromFixture('GridFieldAction_SortOrder_VTeam', 'team2'); - $team3 = $this->objFromFixture('GridFieldAction_SortOrder_VTeam', 'team3'); - - $this->logInWithPermission('ADMIN'); - $stateID = 'testGridStateActionField'; - Session::set($stateID, array('grid'=>'', 'actionName'=>'saveGridRowSort', 'args'=>array('GridFieldSortableRows'=>array('sortableToggle'=>true)))); - $request = new SS_HTTPRequest('POST', 'url', array('ItemIDs'=>"$team1->ID, $team3->ID, $team2->ID"), array('action_gridFieldAlterAction?StateID='.$stateID=>true, $this->form->getSecurityToken()->getName()=>$this->form->getSecurityToken()->getValue())); - $this->gridField->gridFieldAlterAction(array('StateID'=>$stateID), $this->form, $request); - - $this->assertEquals($team2->ID, $list->last()->ID, 'Sort should have happened on Versioned stage "Stage"'); - - $list=Versioned::get_by_stage('GridFieldAction_SortOrder_VTeam', 'Live'); - $this->assertEquals($team2->ID, $list->last()->ID, 'Sort should have happened on Versioned stage "Live"'); - } +use SilverStripe\Control\HTTPRequest; +use SilverStripe\Control\Session; +use SilverStripe\Dev\SapphireTest; +use SilverStripe\Dev\TestOnly; +use SilverStripe\Forms\FieldList; +use SilverStripe\Forms\Form; +use SilverStripe\Forms\GridField\GridField; +use SilverStripe\Forms\GridField\GridFieldConfig; +use SilverStripe\ORM\ArrayList; +use SilverStripe\ORM\DataObject; +use SilverStripe\ORM\ValidationException; +use SilverStripe\Security\Member; +use SilverStripe\Versioned\Versioned; +use UndefinedOffset\SortableGridField\Forms\GridFieldSortableRows; + +class GridFieldSortableRowsTest extends SapphireTest +{ + /** @var ArrayList */ + protected $list; + + /** @var GridField */ + protected $gridField; + + /** @var Form */ + protected $form; + + /** @var string */ + public static $fixture_file = 'sortablegridfield/tests/forms/GridFieldSortableRowsTest.yml'; + + /** @var array */ + protected static $extra_dataobjects = array( + GridFieldAction_SortOrder_Team::class, + GridFieldAction_SortOrder_VTeam::class + ); + + public function setUp() + { + parent::setUp(); + $this->list = GridFieldAction_SortOrder_Team::get(); + $config = GridFieldConfig::create()->addComponent(new GridFieldSortableRows('SortOrder')); + $this->gridField = new GridField('testfield', 'testfield', $this->list, $config); + $this->form = new Form(new SortableGridField_DummyController(), 'mockform', new FieldList(array($this->gridField)), new FieldList()); + } + + public function testSortActionWithoutCorrectPermission() + { + if (Member::currentUser()) { + Member::currentUser()->logOut(); + } + $this->setExpectedException(ValidationException::class); + $team1 = $this->objFromFixture('UndefinedOffset\SortableGridField\Tests\GridFieldAction_SortOrder_Team', 'team1'); + $team2 = $this->objFromFixture('UndefinedOffset\SortableGridField\Tests\GridFieldAction_SortOrder_Team', 'team2'); + $team3 = $this->objFromFixture('UndefinedOffset\SortableGridField\Tests\GridFieldAction_SortOrder_Team', 'team3'); + + $stateID = 'testGridStateActionField'; + Session::set($stateID, array('grid' => '', 'actionName' => 'saveGridRowSort', 'args' => array('GridFieldSortableRows' => array('sortableToggle' => true)))); + $request = new HTTPRequest('POST', 'url', array('ItemIDs' => "$team1->ID, $team3->ID, $team2->ID"), array('action_gridFieldAlterAction?StateID=' . $stateID => true, $this->form->getSecurityToken()->getName() => $this->form->getSecurityToken()->getValue())); + $this->gridField->gridFieldAlterAction(array('StateID' => $stateID), $this->form, $request); + $this->assertEquals($team3->ID, $this->list->last()->ID, 'User should\'t be able to sort records without correct permissions.'); + } + + public function testSortActionWithAdminPermission() + { + $team1 = $this->objFromFixture('UndefinedOffset\SortableGridField\Tests\GridFieldAction_SortOrder_Team', 'team1'); + $team2 = $this->objFromFixture('UndefinedOffset\SortableGridField\Tests\GridFieldAction_SortOrder_Team', 'team2'); + $team3 = $this->objFromFixture('UndefinedOffset\SortableGridField\Tests\GridFieldAction_SortOrder_Team', 'team3'); + $this->logInWithPermission('ADMIN'); + $stateID = 'testGridStateActionField'; + Session::set($stateID, array('grid' => '', 'actionName' => 'saveGridRowSort', 'args' => array('GridFieldSortableRows' => array('sortableToggle' => true)))); + $request = new HTTPRequest('POST', 'url', array('ItemIDs' => "$team1->ID, $team3->ID, $team2->ID"), array('action_gridFieldAlterAction?StateID=' . $stateID => true, $this->form->getSecurityToken()->getName() => $this->form->getSecurityToken()->getValue())); + $this->gridField->gridFieldAlterAction(array('StateID' => $stateID), $this->form, $request); + $this->assertEquals($team2->ID, $this->list->last()->ID, 'User should be able to sort records with ADMIN permission.'); + } + + public function testSortActionVersioned() + { + //Force versioned to reset + Versioned::reset(); + + $list = GridFieldAction_SortOrder_VTeam::get(); + $this->gridField->setList($list); + + /** @var GridFieldSortableRows $sortableGrid */ + $sortableGrid = $this->gridField->getConfig()->getComponentByType(GridFieldSortableRows::class); + $sortableGrid->setUpdateVersionedStage('Live'); + + //Publish all records + foreach ($list as $item) { + $item->publish('Stage', 'Live'); + } + + $team1 = $this->objFromFixture('UndefinedOffset\SortableGridField\Tests\GridFieldAction_SortOrder_VTeam', 'team1'); + $team2 = $this->objFromFixture('UndefinedOffset\SortableGridField\Tests\GridFieldAction_SortOrder_VTeam', 'team2'); + $team3 = $this->objFromFixture('UndefinedOffset\SortableGridField\Tests\GridFieldAction_SortOrder_VTeam', 'team3'); + + $this->logInWithPermission('ADMIN'); + $stateID = 'testGridStateActionField'; + Session::set($stateID, array('grid' => '', 'actionName' => 'saveGridRowSort', 'args' => array('GridFieldSortableRows' => array('sortableToggle' => true)))); + $request = new HTTPRequest('POST', 'url', array('ItemIDs' => "$team1->ID, $team3->ID, $team2->ID"), array('action_gridFieldAlterAction?StateID=' . $stateID => true, $this->form->getSecurityToken()->getName() => $this->form->getSecurityToken()->getValue())); + $this->gridField->gridFieldAlterAction(array('StateID' => $stateID), $this->form, $request); + + $this->assertEquals($team2->ID, $list->last()->ID, 'Sort should have happened on Versioned stage "Stage"'); + + $list = Versioned::get_by_stage(GridFieldAction_SortOrder_VTeam::class, 'Live'); + $this->assertEquals($team2->ID, $list->last()->ID, 'Sort should have happened on Versioned stage "Live"'); + } } -class GridFieldAction_SortOrder_Team extends DataObject implements TestOnly { - static $db = array( - 'Name' => 'Varchar', - 'City' => 'Varchar', - 'SortOrder' => 'Int' - ); - - static $default_sort='SortOrder'; +/** + * Class GridFieldAction_SortOrder_Team + * + * @package SortableGridField\Tests + * @property string Name + * @property string City + * @property int SortOrder + */ +class GridFieldAction_SortOrder_Team extends DataObject implements TestOnly +{ + private static $table_name = 'GridFieldAction_SortOrder_Team'; + + private static $db = array( + 'Name' => 'Varchar', + 'City' => 'Varchar', + 'SortOrder' => 'Int' + ); + + private static $default_sort = 'SortOrder'; } -class GridFieldAction_SortOrder_VTeam extends DataObject implements TestOnly { - static $db = array( - 'Name' => 'Varchar', - 'City' => 'Varchar', - 'SortOrder' => 'Int' - ); - - static $default_sort='SortOrder'; - - static $extensions=array( - "Versioned('Stage', 'Live')" - ); +/** + * Class GridFieldAction_SortOrder_VTeam + * + * @package SortableGridField\Tests + * @property string Name + * @property string City + * @property int SortOrder + */ +class GridFieldAction_SortOrder_VTeam extends DataObject implements TestOnly +{ + private static $table_name = 'GridFieldAction_SortOrder_VTeam'; + + private static $db = array( + 'Name' => 'Varchar', + 'City' => 'Varchar', + 'SortOrder' => 'Int' + ); + private static $default_sort = 'SortOrder'; + + private static $extensions = array( + "SilverStripe\\Versioned\\Versioned('Stage', 'Live')" + ); } -?> \ No newline at end of file diff --git a/tests/forms/GridFieldSortableRowsTest.yml b/tests/forms/GridFieldSortableRowsTest.yml index 1446eac..f719e47 100644 --- a/tests/forms/GridFieldSortableRowsTest.yml +++ b/tests/forms/GridFieldSortableRowsTest.yml @@ -1,27 +1,27 @@ -GridFieldAction_SortOrder_Team: - team1: - Name: Team 1 - City: Cologne - SortOrder: 1 - team2: - Name: Team 2 - City: Wellington - SortOrder: 2 - team3: - Name: Team 3 - City: Auckland - SortOrder: 3 +UndefinedOffset\SortableGridField\Tests\GridFieldAction_SortOrder_Team: + team1: + Name: Team 1 + City: Cologne + SortOrder: 1 + team2: + Name: Team 2 + City: Wellington + SortOrder: 2 + team3: + Name: Team 3 + City: Auckland + SortOrder: 3 -GridFieldAction_SortOrder_VTeam: - team1: - Name: Team 1 - City: Cologne - SortOrder: 1 - team2: - Name: Team 2 - City: Wellington - SortOrder: 2 - team3: - Name: Team 3 - City: Auckland - SortOrder: 3 +UndefinedOffset\SortableGridField\Tests\GridFieldAction_SortOrder_VTeam: + team1: + Name: Team 1 + City: Cologne + SortOrder: 1 + team2: + Name: Team 2 + City: Wellington + SortOrder: 2 + team3: + Name: Team 3 + City: Auckland + SortOrder: 3