NEW Add paginator with configurable page sizes

This commit is contained in:
Robbie Averill 2017-07-20 11:51:24 +12:00
parent ff12337e6e
commit e95c92a168
5 changed files with 904 additions and 184 deletions

View File

@ -0,0 +1,442 @@
<?php
/**
* GridFieldConfigurablePaginator paginates the {@link GridField} list and adds controls to the bottom of
* the {@link GridField}. The page sizes are configurable.
*/
class GridFieldConfigurablePaginator extends GridFieldPaginator
{
/**
* Specifies default page sizes
*
* @config
* @var int
*/
private static $default_page_sizes = array(15, 30, 60);
/**
* Which template to use for rendering
*
* @var string
*/
protected $itemClass = 'GridFieldConfigurablePaginator';
/**
* @var GridField
*/
protected $gridField;
/**
* @var GridState_Data
*/
protected $gridFieldState;
/**
* @var int[]
*/
protected $pageSizes = array();
/**
* @param int $itemsPerPage How many items should be displayed per page
* @param int $pageSizes The page sizes to show in the dropdown
*/
public function __construct($itemsPerPage = null, $pageSizes = null)
{
$this->setPageSizes($pageSizes ?: Config::inst()->get('GridFieldConfigurablePaginator', 'default_page_sizes'));
if (!$itemsPerPage) {
$itemsPerPage = $this->pageSizes[0];
}
parent::__construct($itemsPerPage);
}
/**
* Get the total number of records in the list
*
* @return int
*/
public function getTotalRecords()
{
return (int) $this->getGridField()->getList()->count();
}
/**
* Get the first shown record number
*
* @return int
*/
public function getFirstShown()
{
$firstShown = $this->getGridPagerState()->firstShown ?: 1;
// Prevent visiting a page with an offset higher than the total number of items
if ($firstShown > $this->getTotalRecords()) {
$this->getGridPagerState()->firstShown = $firstShown = 1;
}
return $firstShown;
}
/**
* Set the first shown record number. Will be stored in the state.
*
* @param int $firstShown
* @return $this
*/
public function setFirstShown($firstShown = 1)
{
$this->getGridPagerState()->firstShown = (int) $firstShown;
return $this;
}
/**
* Get the last shown record number
*
* @return int
*/
public function getLastShown()
{
return min($this->getTotalRecords(), $this->getFirstShown() + $this->getItemsPerPage() - 1);
}
/**
* Get the total number of pages, given the current number of items per page. The total
* pages might be higher than <totalitems> / <itemsperpage> if the first shown record
* is half way through a standard page break point.
*
* @return int
*/
public function getTotalPages()
{
// Pages before
$pages = ceil(($this->getFirstShown() - 1) / $this->getItemsPerPage());
// Current page
$pages++;
// Pages after
$pages += ceil(($this->getTotalRecords() - $this->getLastShown()) / $this->getItemsPerPage());
return (int) $pages;
}
/**
* Get the page currently active. This is calculated by adding one to the previous number
* of pages calculated via the "first shown record" position.
*
* @return int
*/
public function getCurrentPage()
{
return (int) ceil(($this->getFirstShown() - 1) / $this->getItemsPerPage()) + 1;
}
/**
* Get the next page number
*
* @return int
*/
public function getNextPage()
{
return min($this->getTotalPages(), $this->getCurrentPage() + 1);
}
/**
* Get the previous page number
*
* @return int
*/
public function getPreviousPage()
{
return max(1, $this->getCurrentPage() - 1);
}
/**
* Set the page sizes to use in the "Show x" dropdown
*
* @param array $pageSizes
* @return $this
*/
public function setPageSizes(array $pageSizes)
{
$this->pageSizes = $pageSizes;
return $this;
}
/**
* Get the sizes for the "Show x" dropdown
*
* @return array
*/
public function getPageSizes()
{
return $this->pageSizes;
}
/**
* Gets a list of page sizes for use in templates as a dropdown
*
* @return ArrayList
*/
public function getPageSizesAsList()
{
$pageSizes = ArrayList::create();
$perPage = $this->getItemsPerPage();
foreach ($this->getPageSizes() as $pageSize) {
$pageSizes->push(array(
'Size' => $pageSize,
'Selected' => $pageSize == $perPage
));
}
return $pageSizes;
}
/**
* Get the GridField used in this request
*
* @return GridField
* @throws Exception If the GridField has not been previously set
*/
public function getGridField()
{
if ($this->gridField) {
return $this->gridField;
}
throw new Exception('No GridField available yet for this request!');
}
/**
* Set the GridField so it can be used in other parts of the component during this request
*
* @param GridField $gridField
* @return $this
*/
public function setGridField(GridField $gridField)
{
$this->gridField = $gridField;
return $this;
}
public function handleAction(GridField $gridField, $actionName, $arguments, $data)
{
$this->setGridField($gridField);
if ($actionName !== 'paginate') {
return;
}
$state = $this->getGridPagerState();
$state->firstShown = (int) $arguments['first-shown'];
$state->pageSize = $data[$gridField->getName()]['page-sizes'];
$this->setItemsPerPage($state->pageSize);
}
public function getManipulatedData(GridField $gridField, SS_List $dataList)
{
// Assign the GridField to the class so it can be used later in the request
$this->setGridField($gridField);
if (!($dataList instanceof SS_Limitable) || ($dataList instanceof UnsavedRelationList)) {
return $dataList;
}
return $dataList->limit($this->getItemsPerPage(), $this->getFirstShown() - 1);
}
/**
* Add the configurable page size options to the template data
*
* {@inheritDoc}
*
* @param GridField $gridField
* @return ArrayList|null
*/
public function getTemplateParameters(GridField $gridField)
{
$state = $this->getGridPagerState();
$arguments = $this->getPagerArguments();
// Figure out which page and record range we're on
if (!$arguments['total-rows']) {
return;
}
// If there is only 1 page for all the records in list, we don't need to go further to sort out those
// first page, last page, pre and next pages, etc we are not render those in to the paginator.
if ($arguments['total-pages'] == 1) {
return ArrayData::create(array(
'OnlyOnePage' => true,
'FirstShownRecord' => $arguments['first-shown'],
'LastShownRecord' => $arguments['last-shown'],
'NumRecords' => $arguments['total-rows'],
'NumPages' => $arguments['total-pages']
));
}
// Define a list of the FormActions that should be generated for pager controls (see getPagerActions())
$controls = array(
'first' => array(
'title' => 'First',
'args' => array('first-shown' => 1),
'extra-class' => 'ss-gridfield-firstpage',
'disable-previous' => ($this->getCurrentPage() == 1)
),
'prev' => array(
'title' => 'Previous',
'args' => array('first-shown' => $arguments['first-shown'] - $this->getItemsPerPage()),
'extra-class' => 'ss-gridfield-previouspage',
'disable-previous' => ($this->getCurrentPage() == 1)
),
'next' => array(
'title' => 'Next',
'args' => array('first-shown' => $arguments['first-shown'] + $this->getItemsPerPage()),
'extra-class' => 'ss-gridfield-nextpage',
'disable-next' => ($this->getCurrentPage() == $arguments['total-pages'])
),
'last' => array(
'title' => 'Last',
'args' => array('first-shown' => ($this->getTotalPages() - 1) * $this->getItemsPerPage() + 1),
'extra-class' => 'ss-gridfield-lastpage',
'disable-next' => ($this->getCurrentPage() == $arguments['total-pages'])
),
'pagesize' => array(
'title' => 'Page Size',
'args' => array('first-shown' => $arguments['first-shown']),
'extra-class' => 'ss-gridfield-pagesize-submit'
),
);
if ($controls['prev']['args']['first-shown'] < 1) {
$controls['prev']['args']['first-shown'] = 1;
}
$actions = $this->getPagerActions($controls, $gridField);
// Render in template
return ArrayData::create(array(
'OnlyOnePage' => false,
'FirstPage' => $actions['first'],
'PreviousPage' => $actions['prev'],
'NextPage' => $actions['next'],
'LastPage' => $actions['last'],
'PageSizesSubmit' => $actions['pagesize'],
'CurrentPageNum' => $this->getCurrentPage(),
'NumPages' => $arguments['total-pages'],
'FirstShownRecord' => $arguments['first-shown'],
'LastShownRecord' => $arguments['last-shown'],
'NumRecords' => $arguments['total-rows'],
'PageSizes' => $this->getPageSizesAsList(),
'PageSizesName' => $gridField->getName() . '[page-sizes]',
));
}
public function getHTMLFragments($gridField)
{
GridFieldExtensions::include_requirements();
$gridField->addExtraClass('ss-gridfield-configurable-paginator');
$forTemplate = $this->getTemplateParameters($gridField);
if ($forTemplate) {
return array(
'footer' => $forTemplate->renderWith(
$this->itemClass,
array('Colspan' => count($gridField->getColumns()))
)
);
}
}
/**
* Returns an array containing the arguments for the pagination: total rows, pages, first record etc
*
* @return array
*/
protected function getPagerArguments()
{
return array(
'total-rows' => $this->getTotalRecords(),
'total-pages' => $this->getTotalPages(),
'items-per-page' => $this->getItemsPerPage(),
'first-shown' => $this->getFirstShown(),
'last-shown' => $this->getLastShown(),
);
}
/**
* Returns FormActions for each of the pagination actions, in an array
*
* @param array $controls
* @param GridField $gridField
* @return GridField_FormAction[]
*/
public function getPagerActions(array $controls, GridField $gridField)
{
$actions = array();
foreach ($controls as $key => $arguments) {
$action = GridField_FormAction::create(
$gridField,
'pagination_' . $key,
$arguments['title'],
'paginate',
$arguments['args']
);
if (isset($arguments['extra-class'])) {
$action->addExtraClass($arguments['extra-class']);
}
if (isset($arguments['disable-previous']) && $arguments['disable-previous']) {
$action = $action->performDisabledTransformation();
} elseif (isset($arguments['disable-next']) && $arguments['disable-next']) {
$action = $action->performDisabledTransformation();
}
$actions[$key] = $action;
}
return $actions;
}
public function getActions($gridField)
{
return array('paginate');
}
/**
* Gets the state from the current request's GridField and sets some default values on it
*
* @param GridField $gridField Not used, but present for parent method compatibility
* @return GridState_Data
*/
protected function getGridPagerState(GridField $gridField = null)
{
if (!$this->gridFieldState) {
$state = $this->getGridField()->State->GridFieldConfigurablePaginator;
// SS 3.1 compatibility (missing __call)
if (is_object($state->firstShown)) {
$state->firstShown = 1;
}
if (is_object($state->pageSize)) {
$state->pageSize = $this->getItemsPerPage();
}
// Handle free input in the page number field
$parentState = $this->getGridField()->State->GridFieldPaginator;
if (is_object($parentState->currentPage)) {
$parentState->currentPage = 0;
}
if ($parentState->currentPage >= 1) {
$state->firstShown = ($parentState->currentPage - 1) * $this->getItemsPerPage() + 1;
$parentState->currentPage = null;
}
$this->gridFieldState = $state;
}
return $this->gridFieldState;
}
}

View File

@ -1,184 +1,206 @@
/**
* GridFieldAddExistingSearchButton
*/
.add-existing-search-dialog {
min-width: inherit !important;
}
.add-existing-search-dialog .add-existing-search-form .field {
border: none;
box-shadow: none;
margin-bottom: 0;
padding-bottom: 0;
}
.add-existing-search-dialog .add-existing-search-form .field label {
padding-bottom: 4px;
}
.add-existing-search-dialog .add-existing-search-form .Actions {
margin-top: 10px;
padding: 0;
}
.add-existing-search-dialog .add-existing-search-items li a {
background: #FFF;
border-bottom-width: 1px;
border-color: #CCC;
border-left-width: 1px;
border-right-width: 1px;
border-style: solid;
display: block;
padding: 6px;
}
.add-existing-search-dialog .add-existing-search-items li:first-child a {
border-top-left-radius: 4px;
border-top-right-radius: 4px;
border-top-width: 1px;
}
.add-existing-search-dialog .add-existing-search-items li:last-child a {
border-bottom-left-radius: 4px;
border-bottom-right-radius: 4px;
}
.add-existing-search-dialog .add-existing-search-items li a:hover {
background: #F4F4F4;
}
.add-existing-search-dialog .add-existing-search-pagination li {
background: #FFF;
display: block;
float: left;
margin-right: 2px;
margin-top: 12px;
padding: 6px;
}
/**
* GridFieldAddNewInlineButton
*/
.ss-gridfield-inline-new {
background: #EFE;
}
.ss-gridfield-inline-new:nth-child(2n) {
background: #DFD;
}
/**
* GridFieldAddNewMultiClass
*/
.ss-gridfield-add-new-multi-class {
margin-bottom: 8px !important;
}
.ss-gridfield-add-new-multi-class .field {
border: none;
box-shadow: none;
float: left;
margin: 0 4px 0 0;
}
/**
* GridFieldEditableColumns
*/
.ss-gridfield-editable .readonly {
padding-top: 0 !important;
}
.ss-gridfield-editable input.text,
.ss-gridfield-editable textarea,
.ss-gridfield-editable select,
.ss-gridfield-editable .TreeDropdownField {
margin: 0 !important;
max-width: none !important;
}
.ss-gridfield-editable select.dropdown {
border: 1px solid #b3b3b3;
background-color: #fff;
padding: 7px 7px;
padding-left: 4px;
line-height: 16px;
-moz-border-radius: 4px;
-webkit-border-radius: 4px;
border-radius: 4px;
}
.ss-gridfield-add-new-inline {
margin-bottom: 12px;
}
.ss-gridfield-add-new-inline span.readonly {
color: #FFF !important;
}
.ss-gridfield-add-new-inline .col-buttons {
text-align: right;
}
/**
* GridFieldOrderableRows
*/
.ss-gridfield-orderable thead tr th.col-Reorder span {
padding: 0 !important;
margin-left: 8px;
}
.ss-gridfield-orderable .col-reorder {
position: relative;
padding: 0 !important;
width: 16px !important;
}
.ss-gridfield-orderable .col-reorder .handle {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
cursor: move;
}
.ss-gridfield-orderable .col-reorder .handle .icon {
position: absolute;
top: 50%;
left: 50%;
width: 5px;
height: 11px;
margin: -5px 0 0 -2px;
background-image: url('../../framework/thirdparty/jquery-ui-themes/smoothness/images/ui-icons_222222_256x240.png');
background-position: -5px -227px;
}
.ss-gridfield-orderhelper {
border-bottom: 1px solid rgba(0, 0, 0, .1);
border-top: 1px solid rgba(0, 0, 0, .1);
box-shadow: 0 0 8px rgba(0, 0, 0, .4);
}
.ss-gridfield-orderable tfoot .ui-droppable {
padding-left: 12px;
padding-right: 12px;
}
.ss-gridfield-orderable tfoot .ui-droppable-active {
background-color: #D4CF90 !important;
}
.ss-gridfield-orderable tfoot .ss-gridfield-previouspage {
background-position: -16px 9px !important;
margin-left: 0;
}
.ss-gridfield-orderable tfoot .ss-gridfield-nextpage {
background-position: -40px 9px !important;
margin-right: 0;
}
/**
* GridFieldAddExistingSearchButton
*/
.add-existing-search-dialog {
min-width: inherit !important;
}
.add-existing-search-dialog .add-existing-search-form .field {
border: none;
box-shadow: none;
margin-bottom: 0;
padding-bottom: 0;
}
.add-existing-search-dialog .add-existing-search-form .field label {
padding-bottom: 4px;
}
.add-existing-search-dialog .add-existing-search-form .Actions {
margin-top: 10px;
padding: 0;
}
.add-existing-search-dialog .add-existing-search-items li a {
background: #FFF;
border-bottom-width: 1px;
border-color: #CCC;
border-left-width: 1px;
border-right-width: 1px;
border-style: solid;
display: block;
padding: 6px;
}
.add-existing-search-dialog .add-existing-search-items li:first-child a {
border-top-left-radius: 4px;
border-top-right-radius: 4px;
border-top-width: 1px;
}
.add-existing-search-dialog .add-existing-search-items li:last-child a {
border-bottom-left-radius: 4px;
border-bottom-right-radius: 4px;
}
.add-existing-search-dialog .add-existing-search-items li a:hover {
background: #F4F4F4;
}
.add-existing-search-dialog .add-existing-search-pagination li {
background: #FFF;
display: block;
float: left;
margin-right: 2px;
margin-top: 12px;
padding: 6px;
}
/**
* GridFieldAddNewInlineButton
*/
.ss-gridfield-inline-new {
background: #EFE;
}
.ss-gridfield-inline-new:nth-child(2n) {
background: #DFD;
}
/**
* GridFieldAddNewMultiClass
*/
.ss-gridfield-add-new-multi-class {
margin-bottom: 8px !important;
}
.ss-gridfield-add-new-multi-class .field {
border: none;
box-shadow: none;
float: left;
margin: 0 4px 0 0;
}
/**
* GridFieldEditableColumns
*/
.ss-gridfield-editable .readonly {
padding-top: 0 !important;
}
.ss-gridfield-editable input.text,
.ss-gridfield-editable textarea,
.ss-gridfield-editable select,
.ss-gridfield-editable .TreeDropdownField {
margin: 0 !important;
max-width: none !important;
}
.ss-gridfield-editable select.dropdown {
border: 1px solid #b3b3b3;
background-color: #fff;
padding: 7px 7px;
padding-left: 4px;
line-height: 16px;
-moz-border-radius: 4px;
-webkit-border-radius: 4px;
border-radius: 4px;
}
.ss-gridfield-add-new-inline {
margin-bottom: 12px;
}
.ss-gridfield-add-new-inline span.readonly {
color: #FFF !important;
}
.ss-gridfield-add-new-inline .col-buttons {
text-align: right;
}
/**
* GridFieldOrderableRows
*/
.ss-gridfield-orderable thead tr th.col-Reorder span {
padding: 0 !important;
margin-left: 8px;
}
.ss-gridfield-orderable .col-reorder {
position: relative;
padding: 0 !important;
width: 16px !important;
}
.ss-gridfield-orderable .col-reorder .handle {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
cursor: move;
}
.ss-gridfield-orderable .col-reorder .handle .icon {
position: absolute;
top: 50%;
left: 50%;
width: 5px;
height: 11px;
margin: -5px 0 0 -2px;
background-image: url('../../framework/thirdparty/jquery-ui-themes/smoothness/images/ui-icons_222222_256x240.png');
background-position: -5px -227px;
}
.ss-gridfield-orderhelper {
border-bottom: 1px solid rgba(0, 0, 0, .1);
border-top: 1px solid rgba(0, 0, 0, .1);
box-shadow: 0 0 8px rgba(0, 0, 0, .4);
}
.ss-gridfield-orderable tfoot .ui-droppable {
padding-left: 12px;
padding-right: 12px;
}
.ss-gridfield-orderable tfoot .ui-droppable-active {
background-color: #D4CF90 !important;
}
.ss-gridfield-orderable tfoot .ss-gridfield-previouspage {
background-position: -16px 9px !important;
margin-left: 0;
}
.ss-gridfield-orderable tfoot .ss-gridfield-nextpage {
background-position: -40px 9px !important;
margin-right: 0;
}
/**
* GridFieldConfigurablePaginator
*/
.ss-gridfield-configurable-paginator .pagination-page-size {
color: #fff;
float: left;
padding: 6px 0;
}
.ss-gridfield-configurable-paginator .pagination-page-size-select {
margin-left: 0;
width: auto;
}
.ss-gridfield-configurable-paginator .ss-gridfield-pagesize-submit {
display: none;
}
.ss-gridfield-configurable-paginator .pagination-page-number input {
text-align: center;
}

View File

@ -387,5 +387,14 @@
if(this.hasClass("ui-droppable")) this.droppable("destroy");
}
});
/**
* GridFieldConfigurablePaginator
*/
$('.ss-gridfield-configurable-paginator .pagination-page-size-select').entwine({
onchange: function () {
this.parent().find('.ss-gridfield-pagesize-submit').trigger('click');
}
});
});
})(jQuery);

View File

@ -0,0 +1,30 @@
<tr>
<td class="bottom-all" colspan="$Colspan">
<% if not $OnlyOnePage %>
<span class="pagination-page-size">
<%t GridFieldConfigurablePaginator.SHOW 'Show' %>
<select name="$PageSizesName" class="pagination-page-size-select" data-skip-autofocus="true">
<% loop $PageSizes %>
<option <% if $Selected %>selected="selected"<% end_if %>>$Size</option>
<% end_loop %>
</select>
$PageSizesSubmit
</span>
<div class="datagrid-pagination">
$FirstPage $PreviousPage
<span class="pagination-page-number">
<%t Pagination.Page 'Page' %>
<input class="text" value="$CurrentPageNum" data-skip-autofocus="true" />
<%t TableListField_PageControls_ss.OF 'of' is 'Example: View 1 of 2' %>
$NumPages
</span>
$NextPage $LastPage
</div>
<% end_if %>
<span class="pagination-records-number">
{$FirstShownRecord}&ndash;{$LastShownRecord}
<%t TableListField_PageControls_ss.OF 'of' is 'Example: View 1 of 2' %>
$NumRecords
</span>
</td>
</tr>

View File

@ -0,0 +1,217 @@
<?php
class GridFieldConfigurablePaginatorTest extends SapphireTest
{
/**
* @var GridField
*/
protected $gridField;
public function setUp()
{
parent::setUp();
// Some dummy GridField list data
$data = ArrayList::create();
for ($i = 1; $i <= 130; $i++) {
$data->push(array('ID' => $i));
}
$this->gridField = GridField::create('Mock', null, $data);
}
public function testGetTotalRecords()
{
$paginator = new GridFieldConfigurablePaginator;
$paginator->setGridField($this->gridField);
$this->assertSame(130, $paginator->getTotalRecords());
}
public function testGetFirstShown()
{
$paginator = new GridFieldConfigurablePaginator;
$paginator->setGridField($this->gridField);
// No state
$this->assertSame(1, $paginator->getFirstShown());
// With a state
$paginator->setFirstShown(123);
$this->assertSame(123, $paginator->getFirstShown());
// Too high!
$paginator->setFirstShown(234);
$this->assertSame(1, $paginator->getFirstShown());
}
public function testGetLastShown()
{
$paginator = new GridFieldConfigurablePaginator(20, array(10, 20, 30));
$paginator->setGridField($this->gridField);
$this->assertSame(20, $paginator->getLastShown());
$paginator->setFirstShown(5);
$this->assertSame(24, $paginator->getLastShown());
}
public function testGetTotalPages()
{
$paginator = new GridFieldConfigurablePaginator(20, array(20, 40, 60));
$paginator->setGridField($this->gridField);
// Default calculation
$this->assertSame(7, $paginator->getTotalPages());
// With a standard "first shown" record number, e.g. page 2
$paginator->setFirstShown(21);
$this->assertSame(7, $paginator->getTotalPages());
// Non-standard "first shown", e.g. when a page size is changed at page 3. In this case the first page is
// 20 records, the second page is 7 records, third page 20 records, etc
$paginator->setFirstShown(27);
$this->assertSame(8, $paginator->getTotalPages());
// ... and when the page size has also been changed. In this case the first page is 57 records, second page
// 60 records and last page is 13 records
$paginator->setFirstShown(57);
$paginator->setItemsPerPage(60);
$this->assertSame(3, $paginator->getTotalPages());
}
public function testGetCurrentPreviousAndNextPages()
{
$paginator = new GridFieldConfigurablePaginator(20, array(20, 40, 60));
$paginator->setGridField($this->gridField);
// No page selected (first page)
$this->assertSame(1, $paginator->getCurrentPage());
$this->assertSame(1, $paginator->getPreviousPage());
$this->assertSame(2, $paginator->getNextPage());
// Second page
$paginator->setFirstShown(21);
$this->assertSame(2, $paginator->getCurrentPage());
$this->assertSame(1, $paginator->getPreviousPage());
$this->assertSame(3, $paginator->getNextPage());
// Third page
$paginator->setFirstShown(41);
$this->assertSame(3, $paginator->getCurrentPage());
$this->assertSame(2, $paginator->getPreviousPage());
$this->assertSame(4, $paginator->getNextPage());
// Fourth page, partial record count
$paginator->setFirstShown(42);
$this->assertSame(4, $paginator->getCurrentPage());
$this->assertSame(3, $paginator->getPreviousPage());
$this->assertSame(5, $paginator->getNextPage());
// Last page (default paging)
$paginator->setFirstShown(121);
$this->assertSame(7, $paginator->getCurrentPage());
$this->assertSame(6, $paginator->getPreviousPage());
$this->assertSame(7, $paginator->getNextPage());
// Non-standard page size should recalculate the page numbers to be relative to the page size
$paginator->setFirstShown(121);
$paginator->setItemsPerPage(60);
$this->assertSame(3, $paginator->getCurrentPage());
$this->assertSame(2, $paginator->getPreviousPage());
$this->assertSame(3, $paginator->getNextPage());
}
public function testPageSizesAreConfigurable()
{
// Via constructor
$paginator = new GridFieldConfigurablePaginator(3, array(2, 4, 6));
$this->assertSame(3, $paginator->getItemsPerPage());
$this->assertSame(array(2, 4, 6), $paginator->getPageSizes());
// Via public API
$paginator->setPageSizes(array(10, 20, 30));
$this->assertSame(array(10, 20, 30), $paginator->getPageSizes());
// Via default configuration
$paginator = new GridFieldConfigurablePaginator;
$default = Config::inst()->get('GridFieldConfigurablePaginator', 'default_page_sizes');
$this->assertSame($default, $paginator->getPageSizes());
}
public function testGetPageSizesAsList()
{
$paginator = new GridFieldConfigurablePaginator(10, array(10, 20, 30));
$this->assertDOSEquals(array(
array('Size' => '10', 'Selected' => true),
array('Size' => '20', 'Selected' => false),
array('Size' => '30', 'Selected' => false),
), $paginator->getPageSizesAsList());
}
/**
* @expectedException Exception
* @expectedExceptionMessage No GridField available yet for this request!
*/
public function testGetGridFieldThrowsExceptionWhenNotSet()
{
$paginator = new GridFieldConfigurablePaginator;
$paginator->getGridField();
}
public function testGetPagerActions()
{
$controls = array(
'prev' => array(
'title' => 'Previous',
'args' => array(
'next-page' => 123,
'first-shown' => 234
),
'extra-class' => 'ss-gridfield-previouspage',
'disable-previous' => false
),
'next' => array(
'title' => 'Next',
'args' => array(
'next-page' => 234,
'first-shown' => 123
),
'extra-class' => 'ss-gridfield-nextpage',
'disable-next' => true
)
);
$gridField = $this->getMockBuilder('GridField')->disableOriginalConstructor()->getMock();
$paginator = new GridFieldConfigurablePaginator;
$result = $paginator->getPagerActions($controls, $gridField);
$this->assertCount(2, $result);
$this->assertArrayHasKey('next', $result);
$this->assertContainsOnlyInstancesOf('GridField_FormAction', $result);
$this->assertFalse($result['prev']->isDisabled());
$this->assertTrue((bool) $result['next']->hasClass('ss-gridfield-nextpage'));
$this->assertTrue($result['next']->isDisabled());
}
public function testSinglePageWithLotsOfItems()
{
$paginator = new GridFieldConfigurablePaginator(null, array(100, 200, 300));
$this->assertSame(100, $paginator->getItemsPerPage());
}
/**
* Set something to the GridField's paginator state data
*
* @param string $key
* @param mixed $value
* @return $this
*/
protected function setState($key, $value)
{
$this->gridField->State->GridFieldConfigurablePaginator->$key = $value;
return $this;
}
}