Completed
Push — 3.5 ( 1a9180...1bec8a )
by Daniel
24s
created

GridFieldPaginatorTest::testUnlimitedRowCount()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 19
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 13
nc 1
nop 0
dl 0
loc 19
rs 9.4285
c 0
b 0
f 0
1
<?php
2
class GridFieldPaginatorTest extends FunctionalTest {
3
	/** @var ArrayList */
4
	protected $list;
5
6
	/** @var GridField */
7
	protected $gridField;
8
9
	/** @var string */
10
	protected static $fixture_file = 'GridFieldTest.yml';
11
12
	/** @var Form */
13
	protected $form;
14
15
	/** @var array */
16
	protected $extraDataObjects = array('GridFieldTest_Team', 'GridFieldTest_Player');
17
18
	public function setUp() {
19
		parent::setUp();
20
		$this->list = new DataList('GridFieldTest_Team');
0 ignored issues
show
Documentation Bug introduced by
It seems like new \DataList('GridFieldTest_Team') of type object<DataList> is incompatible with the declared type object<ArrayList> of property $list.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
21
		$config = GridFieldConfig::create()->addComponents(
22
			new GridFieldToolbarHeader(), // Required to support pagecount
23
			new GridFieldPaginator(2),
24
			new GridFieldPageCount('toolbar-header-right')
25
		);
26
		$this->gridField = new GridField('testfield', 'testfield', $this->list, $config);
27
		$this->form = new Form(new Controller(), 'mockform', new FieldList(array($this->gridField)), new FieldList());
28
	}
29
30
	public function testThereIsPaginatorWhenMoreThanOnePage() {
31
		$fieldHolder = $this->gridField->FieldHolder();
32
		$content = new CSSContentParser($fieldHolder);
33
		// Check that there is paginator render into the footer
34
		$this->assertEquals(1, count($content->getBySelector('.datagrid-pagination')));
35
36
		// Check that the header and footer both contains a page count
37
		$this->assertEquals(2, count($content->getBySelector('.pagination-records-number')));
38
	}
39
40
	public function testThereIsNoPaginatorWhenOnlyOnePage() {
41
		// We set the itemsPerPage to an reasonably big number so as to avoid test broke from small changes
42
		// on the fixture YML file
43
		$total = $this->list->count();
44
		$this->gridField->getConfig()->getComponentByType("GridFieldPaginator")->setItemsPerPage($total);
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface GridFieldComponent as the method setItemsPerPage() does only exist in the following implementations of said interface: GridFieldPaginator.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
45
		$fieldHolder = $this->gridField->FieldHolder();
46
		$content = new CSSContentParser($fieldHolder);
47
48
		// Check that there is no paginator render into the footer
49
		$this->assertEquals(0, count($content->getBySelector('.datagrid-pagination')));
50
51
		// Check that there is still 'View 1 - 4 of 4' part on the left of the paginator
52
		$this->assertEquals(2, count($content->getBySelector('.pagination-records-number')));
53
	}
54
55
	public function testPaginationAvoidsIllegalOffsets() {
56
		$grid = $this->gridField;
57
		$total = $this->list->count();
58
		$perPage = $grid->getConfig()->getComponentByType('GridFieldPaginator')->getItemsPerPage();
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface GridFieldComponent as the method getItemsPerPage() does only exist in the following implementations of said interface: GridFieldPaginator.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
59
		// Get the last page that will contain results
60
		$lastPage = ceil($total / $perPage);
61
		// Set the paginator state to point to an 'invalid' page
62
		$grid->State->GridFieldPaginator->currentPage = $lastPage + 1;
63
64
		// Get the paginated list
65
		$list = $grid->getManipulatedList();
66
67
		// Assert that the paginator state has been corrected and the list contains items
68
		$this->assertEquals(1, $grid->State->GridFieldPaginator->currentPage);
69
		$this->assertEquals($perPage, $list->count());
70
	}
71
72
}
73