Browse Source

improvements for paginator helper

thinkingmedia 9 years ago
parent
commit
a55d55577b
2 changed files with 147 additions and 109 deletions
  1. 66 18
      src/View/Helper/PaginatorHelper.php
  2. 81 91
      tests/TestCase/View/Helper/PaginatorHelperTest.php

+ 66 - 18
src/View/Helper/PaginatorHelper.php

@@ -195,6 +195,23 @@ class PaginatorHelper extends Helper
     }
 
     /**
+     * Gets the total number of pages in the recordset for the given model.
+     *
+     * @param string|null $model Optional model name. Uses the default if none is specified.
+     * @return int The total pages for the recordset.
+     */
+    public function total($model = null)
+    {
+        $params = $this->params($model);
+
+        if (isset($params['pageCount'])) {
+            return $params['pageCount'];
+        }
+
+        return 0;
+    }
+
+    /**
      * Gets the current key by which the recordset is sorted
      *
      * @param string|null $model Optional model name. Uses the default if none is specified.
@@ -482,9 +499,6 @@ class PaginatorHelper extends Helper
      */
     public function generateUrl(array $options = [], $model = null, $urlOptions = false)
     {
-        $paging = $this->params($model);
-        $paging += ['page' => null, 'sort' => null, 'direction' => null, 'limit' => null];
-
         if (!is_array($urlOptions)) {
             $urlOptions = ['fullBase' => $urlOptions];
         }
@@ -493,6 +507,21 @@ class PaginatorHelper extends Helper
             'fullBase' => false
         ];
 
+        return $this->Url->build($this->generateUrlParams($options, $model), $urlOptions);
+    }
+
+    /**
+     * Merges passed URL options with current pagination state to generate a pagination URL.
+     *
+     * @param array $options Pagination/URL options array
+     * @param string|null $model Which model to paginate on
+     * @return array An array of URL parameters
+     */
+    public function generateUrlParams(array $options = [], $model = null)
+    {
+        $paging = $this->params($model);
+        $paging += ['page' => null, 'sort' => null, 'direction' => null, 'limit' => null];
+
         $url = [
             'page' => $paging['page'],
             'limit' => $paging['limit'],
@@ -519,6 +548,7 @@ class PaginatorHelper extends Helper
         ) {
             $url['sort'] = $url['direction'] = null;
         }
+
         if (!empty($paging['scope'])) {
             $scope = $paging['scope'];
             $currentParams = $this->_config['options']['url'];
@@ -533,7 +563,7 @@ class PaginatorHelper extends Helper
             }
         }
 
-        return $this->Url->build($url, $urlOptions);
+        return $url;
     }
 
     /**
@@ -1076,40 +1106,58 @@ class PaginatorHelper extends Helper
      *
      * - `model` The model to use defaults to PaginatorHelper::defaultModel()
      * - `block` The block name to append the output to, or false/absenst to return as a string
+     * - `prev` (default True) True to generate meta for previous page
+     * - `next` (default True) True to generate meta for next page
+     * - `first` (default False) True to generate meta for first page
+     * - `last` (default False) True to generate meta for last page
      *
      * @param array $options Array of options
      * @return string|null Meta links
      */
     public function meta(array $options = [])
     {
+        $options = $options + [
+                'model' => null,
+                'block' => false,
+                'prev' => true,
+                'next' => true,
+                'first' => false,
+                'last' => false
+            ];
+
         $model = isset($options['model']) ? $options['model'] : null;
         $params = $this->params($model);
         $links = [];
 
-        if ($this->hasPrev()) {
-            $links[] = $this->Html->templater()->format('css', [
-                'rel' => 'prev',
-                'url' => $this->generateUrl(['page' => $params['page'] - 1], null, true)
-            ]);
+        if ($options['prev'] && $this->hasPrev()) {
+            $links[] = $this->Html->meta('prev', $this->generateUrl(['page' => $params['page'] - 1], null, true));
         }
 
-        if ($this->hasNext()) {
-            $links[] = $this->Html->templater()->format('css', [
-                'rel' => 'next',
-                'url' => $this->generateUrl(['page' => $params['page'] + 1], null, true)
-            ]);
+        if ($options['next'] && $this->hasNext()) {
+            $links[] = $this->Html->meta('next', $this->generateUrl(['page' => $params['page'] + 1], null, true));
         }
 
-        $out = implode($links);
+        if ($options['first']) {
+            $links[] = $this->Html->meta('first', $this->generateUrl(['page' => 1], null, true));
+        }
 
-        if (empty($options['block'])) {
-            return $out;
+        if ($options['last']) {
+            $links[] = $this->Html->meta('last', $this->generateUrl(['page' => $params['pageCount']], null, true));
         }
 
+        $out = implode($links);
+
         if ($options['block'] === true) {
             $options['block'] = __FUNCTION__;
         }
-        $this->_View->append($options['block'], $out);
+
+        if (!empty($options['block'])) {
+            $this->_View->append($options['block'], $out);
+
+            return null;
+        }
+
+        return $out;
     }
 
     /**

+ 81 - 91
tests/TestCase/View/Helper/PaginatorHelperTest.php

@@ -34,6 +34,16 @@ class PaginatorHelperTest extends TestCase
     protected $locale;
 
     /**
+     * @var \Cake\View\View
+     */
+    protected $View;
+
+    /**
+     * @var \Cake\View\Helper\PaginatorHelper
+     */
+    protected $Paginator;
+
+    /**
      * setUp method
      *
      * @return void
@@ -44,9 +54,6 @@ class PaginatorHelperTest extends TestCase
         Configure::write('Config.language', 'eng');
         $this->View = new View();
         $this->Paginator = new PaginatorHelper($this->View);
-        $this->Paginator->Js = $this->getMockBuilder('Cake\View\Helper\PaginatorHelper')
-            ->setConstructorArgs([$this->View])
-            ->getMock();
         $this->Paginator->request = new Request();
         $this->Paginator->request->addParams([
             'paging' => [
@@ -2180,7 +2187,7 @@ class PaginatorHelperTest extends TestCase
             'a' => [
                 'href' => '/index?page=15&sort=Client.name&direction=DESC',
             ],
-                'last >>', '/a',
+            'last >>', '/a',
             '/li',
         ];
         $this->assertHtml($expected, $result);
@@ -2386,6 +2393,20 @@ class PaginatorHelperTest extends TestCase
     }
 
     /**
+     * test the total() method
+     *
+     * @return void
+     */
+    public function testTotal()
+    {
+        $result = $this->Paginator->total();
+        $this->assertSame($this->Paginator->request->params['paging']['Article']['pageCount'], $result);
+
+        $result = $this->Paginator->total('Incorrect');
+        $this->assertSame(0, $result);
+    }
+
+    /**
      * test the defaultModel() method
      *
      * @return void
@@ -2450,110 +2471,79 @@ class PaginatorHelperTest extends TestCase
     }
 
     /**
-     * Verifies that no next and prev links are created for single page results.
+     * Test data for meta()
      *
-     * @return void
+     * @return array
      */
-    public function testMetaPage0()
+    public function dataMetaProvider()
     {
-        $this->Paginator->request->params['paging'] = [
-            'Article' => [
-                'page' => 1,
-                'prevPage' => false,
-                'nextPage' => false,
-                'pageCount' => 1,
-            ]
+        return [
+            // Verifies that no next and prev links are created for single page results.
+            [1, false, false, 1, [], ''],
+            // Verifies that first and last pages are created for single page results.
+            [1, false, false, 1, ['first' => true, 'last' => true], '<link href="http://localhost/index" rel="first"/>' .
+                '<link href="http://localhost/index" rel="last"/>'],
+            // Verifies that first page is created for single page results.
+            [1, false, false, 1, ['first' => true], '<link href="http://localhost/index" rel="first"/>'],
+            // Verifies that last page is created for single page results.
+            [1, false, false, 1, ['last' => true], '<link href="http://localhost/index" rel="last"/>'],
+            // Verifies that page 1 only has a next link.
+            [1, false, true, 2, [], '<link href="http://localhost/index?page=2" rel="next"/>'],
+            // Verifies that page 1 only has next, first and last link.
+            [1, false, true, 2, ['first' => true, 'last' => true], '<link href="http://localhost/index?page=2" rel="next"/>' .
+                '<link href="http://localhost/index" rel="first"/>' .
+                '<link href="http://localhost/index?page=2" rel="last"/>'],
+            // Verifies that page 1 only has next and first link.
+            [1, false, true, 2, ['first' => true], '<link href="http://localhost/index?page=2" rel="next"/>' .
+                '<link href="http://localhost/index" rel="first"/>'],
+            // Verifies that page 1 only has next and last link.
+            [1, false, true, 2, ['last' => true], '<link href="http://localhost/index?page=2" rel="next"/>' .
+                '<link href="http://localhost/index?page=2" rel="last"/>'],
+            // Verifies that the last page only has a prev link.
+            [2, true, false, 2, [], '<link href="http://localhost/index" rel="prev"/>'],
+            // Verifies that the last page only has a prev, first and last link.
+            [2, true, false, 2, ['first' => true, 'last' => true], '<link href="http://localhost/index" rel="prev"/>' .
+                '<link href="http://localhost/index" rel="first"/>' .
+                '<link href="http://localhost/index?page=2" rel="last"/>'],
+            // Verifies that a page in the middle has both links.
+            [5, true, true, 10, [], '<link href="http://localhost/index?page=4" rel="prev"/>' .
+                '<link href="http://localhost/index?page=6" rel="next"/>'],
+            // Verifies that a page in the middle has both links.
+            [5, true, true, 10, ['first' => true, 'last' => true], '<link href="http://localhost/index?page=4" rel="prev"/>' .
+                '<link href="http://localhost/index?page=6" rel="next"/>' .
+                '<link href="http://localhost/index" rel="first"/>' .
+                '<link href="http://localhost/index?page=10" rel="last"/>']
         ];
-
-        $expected = '';
-        $result = $this->Paginator->meta();
-        $this->assertSame($expected, $result);
     }
 
     /**
-     * Verifies that page 1 only has a next link.
-     *
-     * @return void
+     * @param int $page
+     * @param int $prevPage
+     * @param int $nextPage
+     * @param int $pageCount
+     * @param array $options
+     * @param string $expected
+     * @dataProvider dataMetaProvider
      */
-    public function testMetaPage1()
+    public function testMeta($page, $prevPage, $nextPage, $pageCount, $options, $expected)
     {
         $this->Paginator->request->params['paging'] = [
             'Article' => [
-                'page' => 1,
-                'prevPage' => false,
-                'nextPage' => true,
-                'pageCount' => 2,
+                'page' => $page,
+                'prevPage' => $prevPage,
+                'nextPage' => $nextPage,
+                'pageCount' => $pageCount,
             ]
         ];
 
-        $expected = '<link rel="next" href="http://localhost/index?page=2"/>';
-        $result = $this->Paginator->meta();
+        $result = $this->Paginator->meta($options);
         $this->assertSame($expected, $result);
-    }
 
-    /**
-     * Verifies that the method will append to a block.
-     *
-     * @return void
-     */
-    public function testMetaPage1InlineFalse()
-    {
-        $this->Paginator->request->params['paging'] = [
-            'Article' => [
-                'page' => 1,
-                'prevPage' => false,
-                'nextPage' => true,
-                'pageCount' => 2,
-            ]
-        ];
-
-        $expected = '<link rel="next" href="http://localhost/index?page=2"/>';
-        $this->Paginator->meta(['block' => true]);
-        $result = $this->View->fetch('meta');
-        $this->assertSame($expected, $result);
-    }
-
-    /**
-     * Verifies that the last page only has a prev link.
-     *
-     * @return void
-     */
-    public function testMetaPage1Last()
-    {
-        $this->Paginator->request->params['paging'] = [
-            'Article' => [
-                'page' => 2,
-                'prevPage' => true,
-                'nextPage' => false,
-                'pageCount' => 2,
-            ]
-        ];
-
-        $expected = '<link rel="prev" href="http://localhost/index"/>';
-        $result = $this->Paginator->meta();
-
-        $this->assertSame($expected, $result);
-    }
+        $this->assertEquals('', $this->View->fetch('meta'));
 
-    /**
-     * Verifies that a page in the middle has both links.
-     *
-     * @return void
-     */
-    public function testMetaPage10Last()
-    {
-        $this->Paginator->request->params['paging'] = [
-            'Article' => [
-                'page' => 5,
-                'prevPage' => true,
-                'nextPage' => true,
-                'pageCount' => 10,
-            ]
-        ];
+        $result = $this->Paginator->meta($options + ['block' => true]);
+        $this->assertNull($result);
 
-        $expected = '<link rel="prev" href="http://localhost/index?page=4"/>';
-        $expected .= '<link rel="next" href="http://localhost/index?page=6"/>';
-        $result = $this->Paginator->meta();
-        $this->assertSame($expected, $result);
+        $this->assertSame($expected, $this->View->fetch('meta'));
     }
 }