Merge branch '2'

This commit is contained in:
Daniel Hensby 2017-09-18 14:59:43 +01:00
commit 9e26e38d75
No known key found for this signature in database
GPG Key ID: 5DE415D786BBB2FD
11 changed files with 828 additions and 38 deletions

View File

@ -4,6 +4,8 @@ sudo: false
language: php
dist: precise
php:
- 5.6
- 7.0

View File

@ -1,29 +1,30 @@
# SilverStripe Grid Field Extensions Module
[![Build Status](https://travis-ci.org/symbiote/silverstripe-gridfieldextensions.svg?branch=master)](https://travis-ci.org/symbiote/silverstripe-gridfieldextensions)
[![Latest Stable Version](https://poser.pugx.org/symbiote/silverstripe-gridfieldextensions/version.svg)](https://github.com/symbiote/silverstripe-gridfieldextensions/releases)
[![Latest Unstable Version](https://poser.pugx.org/symbiote/silverstripe-gridfieldextensions/v/unstable.svg)](https://packagist.org/packages/symbiote/silverstripe-gridfieldextensions)
[![Total Downloads](https://poser.pugx.org/symbiote/silverstripe-gridfieldextensions/downloads.svg)](https://packagist.org/packages/symbiote/silverstripe-gridfieldextensions)
[![License](https://poser.pugx.org/symbiote/silverstripe-gridfieldextensions/license.svg)](https://github.com/symbiote/silverstripe-gridfieldextensions/blob/master/LICENSE.md)
This module provides a number of useful grid field components:
* `GridFieldAddExistingSearchButton` - a more advanced search form for adding
items.
* `GridFieldAddNewInlineButton` - builds on `GridFieldEditableColumns` to allow
inline creation of records.
* `GridFieldAddNewMultiClass` - lets the user select from a list of classes to
create a new record from.
* `GridFieldEditableColumns` - allows inline editing of records.
* `GridFieldOrderableRows` - drag and drop re-ordering of rows.
* `GridFieldRequestHandler` - a basic utility class which can be used to build
custom grid field detail views including tabs, breadcrumbs and other CMS
features.
* `GridFieldTitleHeader` - a simple header which displays column titles.
This branch will aim for compatibility with SilverStripe 4.x.
For SilverStripe 3.x, please see the [compatible branch](https://github.com/symbiote/silverstripe-gridfieldextensions/tree/1).
See [docs/en/index.md](docs/en/index.md) for documentation and examples.
# SilverStripe Grid Field Extensions Module
[![Build Status](https://travis-ci.org/symbiote/silverstripe-gridfieldextensions.svg?branch=master)](https://travis-ci.org/symbiote/silverstripe-gridfieldextensions)
[![Latest Stable Version](https://poser.pugx.org/symbiote/silverstripe-gridfieldextensions/version.svg)](https://github.com/symbiote/silverstripe-gridfieldextensions/releases)
[![Latest Unstable Version](https://poser.pugx.org/symbiote/silverstripe-gridfieldextensions/v/unstable.svg)](https://packagist.org/packages/symbiote/silverstripe-gridfieldextensions)
[![Total Downloads](https://poser.pugx.org/symbiote/silverstripe-gridfieldextensions/downloads.svg)](https://packagist.org/packages/symbiote/silverstripe-gridfieldextensions)
[![License](https://poser.pugx.org/symbiote/silverstripe-gridfieldextensions/license.svg)](https://github.com/symbiote/silverstripe-gridfieldextensions/blob/master/LICENSE.md)
This module provides a number of useful grid field components:
* `GridFieldAddExistingSearchButton` - a more advanced search form for adding
items.
* `GridFieldAddNewInlineButton` - builds on `GridFieldEditableColumns` to allow
inline creation of records.
* `GridFieldAddNewMultiClass` - lets the user select from a list of classes to
create a new record from.
* `GridFieldEditableColumns` - allows inline editing of records.
* `GridFieldOrderableRows` - drag and drop re-ordering of rows.
* `GridFieldRequestHandler` - a basic utility class which can be used to build
custom grid field detail views including tabs, breadcrumbs and other CMS
features.
* `GridFieldTitleHeader` - a simple header which displays column titles.
* `GridFieldConfigurablePaginator` - a paginator for GridField that allows customisable page sizes.
This branch will aim for compatibility with SilverStripe 4.x.
For SilverStripe 3.x, please see the [compatible branch](https://github.com/symbiote/silverstripe-gridfieldextensions/tree/1).
See [docs/en/index.md](docs/en/index.md) for documentation and examples.

View File

@ -21,6 +21,9 @@
"require": {
"silverstripe/framework": "~4.0"
},
"require-dev": {
"phpunit/phpunit": "^5.7"
},
"extra": {
"installer-name": "gridfieldextensions",
"branch-alias": {

View File

@ -73,8 +73,7 @@
*/
.ss-gridfield-add-new-multi-class {
margin-bottom: 8px !important;
white-space: nowrap;
margin-bottom: 8px !important;white-space: nowrap;
}
.ss-gridfield-add-new-multi-class .field {
@ -131,7 +130,7 @@
.ss-gridfield-editable select.dropdown {
border: 1px solid #b3b3b3;
background-color: #fff;
padding: 7px 7px 7px 4px;
padding: 7px 7px7px 4px;
line-height: 16px;
-moz-border-radius: 4px;
-webkit-border-radius: 4px;
@ -166,12 +165,13 @@
}
.ss-gridfield-orderable .col-reorder .handle {
cursor: move;
padding: 16px 0 11px;
cursor: move;padding: 16px 0 11px;
}
.ss-gridfield-orderable .col-reorder .handle .icon {
line-height: 100%;
line-
height: 100%;
font-size: 1.5em;
}
@ -199,3 +199,25 @@
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

@ -106,3 +106,36 @@ class Item extends DataObject {
**Please NOTE:** There is a limitation when using `GridFieldOrderableRows` on unsaved data objects; namely, that it doesn't work as without data being saved, the list of related objects has no context. Please check `$this->ID` before adding the `GridFieldOrderableRows` component to the grid field config (or even, before adding the gridfield at all).
Configurable Paginator
----------------------
The `GridFieldConfigurablePaginator` component allows you to have a page size dropdown added to your GridField
pagination controls. The page sizes are configurable via the configuration system, or at call time using the public API.
To use this component you should remove the original paginator component first:
```php
$gridField->getConfig()
->removeComponentsByType('GridFieldPaginator')
->addComponent(new GridFieldConfigurablePaginator());
```
You can configure the page sizes with the configuration system. Note that merging is the default strategy, so to replace
the default sizes with your own you will need to unset the original first, for example:
```php
# File: mysite/_config.php
Config::inst()->remove('GridFieldConfigurablePaginator', 'default_page_sizes');
Config::inst()->update('GridFieldConfigurablePaginator', 'default_page_sizes', array(100, 200, 500));
```
You can also override these at call time:
```php
$paginator = new GridFieldConfigurablePaginator(100, array(100, 200, 500));
$paginator->setPageSizes(array(200, 500, 1000));
$paginator->setItemsPerPage(500);
```
The first shown record will be maintained across page size changes, and the number of pages and current page will be
recalculated on each request, based on the current first shown record and page size.

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

@ -181,7 +181,6 @@ class GridFieldAddNewInlineButton implements GridField_HTMLProvider, GridField_S
$editable = $grid->getConfig()->getComponentByType(GridFieldEditableColumns::class);
/** @var GridFieldOrderableRows $sortable */
$sortable = $grid->getConfig()->getComponentByType(GridFieldOrderableRows::class);
$form = $editable->getForm($grid, $record);
if (!singleton($class)->canCreate()) {
return;
@ -192,6 +191,7 @@ class GridFieldAddNewInlineButton implements GridField_HTMLProvider, GridField_S
$item = $class::create();
$extra = array();
$form = $editable->getForm($grid, $record);
$form->loadDataFrom($fields, Form::MERGE_CLEAR_MISSING);
$form->saveInto($item);

View File

@ -0,0 +1,453 @@
<?php
namespace Symbiote\GridFieldExtensions;
use Exception;
use SilverStripe\Core\Config\Configurable;
use SilverStripe\Forms\GridField\GridField;
use SilverStripe\Forms\GridField\GridFieldPaginator;
use SilverStripe\Forms\GridField\GridField_FormAction;
use SilverStripe\Forms\GridField\GridState_Data;
use SilverStripe\ORM\ArrayList;
use SilverStripe\ORM\Limitable;
use SilverStripe\ORM\SS_List;
use SilverStripe\ORM\UnsavedRelationList;
use SilverStripe\View\ArrayData;
/**
* 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
{
use Configurable;
/**
* Specifies default page sizes
*
* @config
* @var int
*/
private static $default_page_sizes = array(15, 30, 60);
/**
* @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 ?: $this->config()->get('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;
// Reset items per page
$this->setItemsPerPage(current($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);
// Retain page sizes during actions provided by other components
$state = $this->getGridPagerState();
if (is_numeric($state->pageSize)) {
$this->setItemsPerPage($state->pageSize);
}
if (!($dataList instanceof 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();
if (is_numeric($state->pageSize)) {
$this->setItemsPerPage($state->pageSize);
}
$arguments = $this->getPagerArguments();
// Figure out which page and record range we're on
if (!$arguments['total-rows']) {
return;
}
// 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' => 'btn btn-secondary btn--hide-text btn-sm font-icon-angle-double-left ss-gridfield-firstpage',
'disable-previous' => ($this->getCurrentPage() == 1)
),
'prev' => array(
'title' => 'Previous',
'args' => array('first-shown' => $arguments['first-shown'] - $this->getItemsPerPage()),
'extra-class' => 'btn btn-secondary btn--hide-text btn-sm font-icon-angle-left ss-gridfield-previouspage',
'disable-previous' => ($this->getCurrentPage() == 1)
),
'next' => array(
'title' => 'Next',
'args' => array('first-shown' => $arguments['first-shown'] + $this->getItemsPerPage()),
'extra-class' => 'btn btn-secondary btn--hide-text btn-sm font-icon-angle-right 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' => 'btn btn-secondary btn--hide-text btn-sm font-icon-angle-double-right 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' => ($arguments['total-pages'] == 1),
'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(
__CLASS__,
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

@ -124,8 +124,6 @@ class GridFieldEditableColumns extends GridFieldDataColumns implements
/** @var GridFieldOrderableRows $sortable */
$sortable = $grid->getConfig()->getComponentByType(GridFieldOrderableRows::class);
$form = $this->getForm($grid, $record);
foreach ($value[self::POST_KEY] as $id => $fields) {
if (!is_numeric($id) || !is_array($fields)) {
continue;
@ -139,6 +137,7 @@ class GridFieldEditableColumns extends GridFieldDataColumns implements
$extra = array();
$form = $this->getForm($grid, $record);
$form->loadDataFrom($fields, Form::MERGE_CLEAR_MISSING);
$form->saveInto($item);

View File

@ -0,0 +1,30 @@
<tr>
<td class="bottom-all" colspan="$Colspan">
<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>
<% if not $OnlyOnePage %>
<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,238 @@
<?php
use SilverStripe\Core\Config\Config;
use SilverStripe\Dev\SapphireTest;
use SilverStripe\Forms\GridField\GridField;
use SilverStripe\Forms\GridField\GridField_FormAction;
use SilverStripe\ORM\ArrayList;
use Symbiote\GridFieldExtensions\GridFieldConfigurablePaginator;
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 testItemsPerPageIsSetToFirstInPageSizesListWhenChanged()
{
$paginator = new GridFieldConfigurablePaginator(20, array(20, 40, 60));
$paginator->setGridField($this->gridField);
// Initial state, should be what was provided to the constructor
$this->assertSame(20, $paginator->getItemsPerPage());
$paginator->setPageSizes(array(50, 100, 200));
// Set via public API, should now be set to 50
$this->assertSame(50, $paginator->getItemsPerPage());
}
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::class, '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::class)->disableOriginalConstructor()->getMock();
$paginator = new GridFieldConfigurablePaginator;
$result = $paginator->getPagerActions($controls, $gridField);
$this->assertCount(2, $result);
$this->assertArrayHasKey('next', $result);
$this->assertContainsOnlyInstancesOf(GridField_FormAction::class, $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;
}
}