Browse Source

Implements the API to manage the crumbs trail

Yves P 9 years ago
parent
commit
f8b993fe41

+ 151 - 0
src/View/Helper/BreadcrumbsHelper.php

@@ -0,0 +1,151 @@
+<?php
+/**
+ * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
+ * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
+ *
+ * Licensed under The MIT License
+ * For full copyright and license information, please see the LICENSE.txt
+ * Redistributions of files must retain the above copyright notice.
+ *
+ * @copyright     Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
+ * @link          http://cakephp.org CakePHP(tm) Project
+ * @since         3.3.6
+ * @license       http://www.opensource.org/licenses/mit-license.php MIT License
+ */
+namespace Cake\View\Helper;
+
+use Cake\View\Helper;
+use LogicException;
+
+/**
+ * BreadcrumbsHelper to register and display a breadcrumb trail for your views
+ */
+class BreadcrumbsHelper extends Helper
+{
+    /**
+     * The crumbs list.
+     *
+     * @var array
+     */
+    protected $crumbs = [];
+
+    /**
+     * Add a crumb to the trail.
+     *
+     * @param string $title Title of the crumb
+     * @param string|array|null $link Link of the crumb. Either a string, an array of route params to pass to
+     * Url::build() or null / empty if the crumb does not have a link
+     * @param array $options Array of options
+     * @return $this
+     */
+    public function add($title, $link = null, array $options = [])
+    {
+        $this->crumbs[] = ['title' => $title, 'link' => $link, 'options' => $options];
+
+        return $this;
+    }
+
+    /**
+     * Prepend a crumb to the start of the queue.
+     *
+     * @param string $title Title of the crumb
+     * @param string|array|null $link Link of the crumb. Either a string, an array of route params to pass to
+     * Url::build() or null / empty if the crumb does not have a link
+     * @param array $options Array of options
+     * @return $this
+     */
+    public function prepend($title, $link = null, array $options = [])
+    {
+        array_unshift($this->crumbs, ['title' => $title, 'link' => $link, 'options' => $options]);
+
+        return $this;
+    }
+
+    /**
+     * Insert a crumb at a specific index.
+     *
+     * If the index already exists, the new crumb will be inserted,
+     * and the existing element will be shifted one index greater.
+     *
+     * @param int $index The index to insert at.
+     * @param string $title Title of the crumb
+     * @param string|array|null $link Link of the crumb. Either a string, an array of route params to pass to
+     * Url::build() or null / empty if the crumb does not have a link
+     * @param array $options Array of options
+     * @return $this
+     */
+    public function insertAt($index, $title, $link = null, array $options = [])
+    {
+        array_splice($this->crumbs, $index, 0, [['title' => $title, 'link' => $link, 'options' => $options]]);
+
+        return $this;
+    }
+
+    /**
+     * Insert a crumb before the first matching crumb with the specified title.
+     *
+     * Finds the index of the first middleware that matches the provided class,
+     * and inserts the supplied callable before it.
+     *
+     * @param string $matchingTitle The title of the crumb you want to insert this one before
+     * @param string $title Title of the crumb
+     * @param string|array|null $link Link of the crumb. Either a string, an array of route params to pass to
+     * Url::build() or null / empty if the crumb does not have a link
+     * @param array $options Array of options
+     * @return $this
+     */
+    public function insertBefore($matchingTitle, $title, $link = null, array $options = [])
+    {
+        $found = false;
+        foreach ($this->crumbs as $key => $crumb) {
+            if ($crumb['title'] === $matchingTitle) {
+                $found = true;
+                break;
+            }
+        }
+
+        if ($found) {
+            return $this->insertAt($key, $title, $link, $options);
+        }
+        throw new LogicException(sprintf("No crumb matching '%s' could be found.", $matchingTitle));
+    }
+
+    /**
+     * Insert a crumb after the first matching crumb with the specified title.
+     *
+     * Finds the index of the first middleware that matches the provided class,
+     * and inserts the supplied callable before it.
+     *
+     * @param string $matchingTitle The title of the crumb you want to insert this one after
+     * @param string $title Title of the crumb
+     * @param string|array|null $link Link of the crumb. Either a string, an array of route params to pass to
+     * Url::build() or null / empty if the crumb does not have a link
+     * @param array $options Array of options
+     * @return $this
+     */
+    public function insertAfter($matchingTitle, $title, $link = null, array $options = [])
+    {
+        $found = false;
+        foreach ($this->crumbs as $key => $crumb) {
+            if ($crumb['title'] === $matchingTitle) {
+                $found = true;
+                break;
+            }
+        }
+
+        if ($found) {
+            return $this->insertAt($key + 1, $title, $link, $options);
+        }
+        throw new LogicException(sprintf("No crumb matching '%s' could be found.", $matchingTitle));
+    }
+
+    /**
+     * Returns the crumbs list
+     *
+     * @return array
+     */
+    public function getCrumbs()
+    {
+       return $this->crumbs;
+    }
+}

+ 245 - 0
tests/TestCase/View/Helper/BreadcrumbsHelperTest.php

@@ -0,0 +1,245 @@
+<?php
+/**
+ * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
+ * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
+ *
+ * Licensed under The MIT License
+ * For full copyright and license information, please see the LICENSE.txt
+ * Redistributions of files must retain the above copyright notice
+ *
+ * @copyright     Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
+ * @link          http://cakephp.org CakePHP(tm) Project
+ * @since         3.3.6
+ * @license       http://www.opensource.org/licenses/mit-license.php MIT License
+ */
+namespace Cake\Test\TestCase\View\Helper;
+
+use Cake\TestSuite\TestCase;
+use Cake\View\Helper\BreadcrumbsHelper;
+use Cake\View\View;
+
+class BreadcrumbsHelperTest extends TestCase
+{
+
+    /**
+     * Instance of the BreadcrumbsHelper
+     *
+     * @var BreadcrumbsHelper
+     */
+    public $breadcrumbs;
+
+    /**
+     * setUp method
+     *
+     * @return void
+     */
+    public function setUp()
+    {
+        parent::setUp();
+        $view = new View();
+        $this->breadcrumbs = new BreadcrumbsHelper($view);
+    }
+
+    /**
+     * Test adding crumbs to the trail using add()
+     * @return void
+     */
+    public function testAdd()
+    {
+        $this->breadcrumbs
+            ->add('Home', '/', ['class' => 'first'])
+            ->add('Some text', ['controller' => 'Some', 'action' => 'text']);
+
+        $result = $this->breadcrumbs->getCrumbs();
+        $expected = [
+            [
+                'title' => 'Home',
+                'link' => '/',
+                'options' => [
+                    'class' => 'first'
+                ]
+            ],
+            [
+                'title' => 'Some text',
+                'link' => [
+                    'controller' => 'Some',
+                    'action' => 'text'
+                ],
+                'options' => []
+            ]
+        ];
+        $this->assertEquals($expected, $result);
+    }
+
+    /**
+     * Test adding crumbs to the trail using prepend()
+     * @return void
+     */
+    public function testPrepend()
+    {
+        $this->breadcrumbs
+            ->add('Home', '/', ['class' => 'first'])
+            ->prepend('Some text', ['controller' => 'Some', 'action' => 'text'])
+            ->prepend('The root', '/root', ['data-name' => 'some-name']);
+
+        $result = $this->breadcrumbs->getCrumbs();
+        $expected = [
+            [
+                'title' => 'The root',
+                'link' => '/root',
+                'options' => ['data-name' => 'some-name']
+            ],
+            [
+                'title' => 'Some text',
+                'link' => [
+                    'controller' => 'Some',
+                    'action' => 'text'
+                ],
+                'options' => []
+            ],
+            [
+                'title' => 'Home',
+                'link' => '/',
+                'options' => [
+                    'class' => 'first'
+                ]
+            ]
+        ];
+        $this->assertEquals($expected, $result);
+    }
+
+    /**
+     * Test adding crumbs to a specific index
+     * @return void
+     */
+    public function testInsertAt()
+    {
+        $this->breadcrumbs
+            ->add('Home', '/', ['class' => 'first'])
+            ->prepend('Some text', ['controller' => 'Some', 'action' => 'text'])
+            ->insertAt(1, 'Insert At', ['controller' => 'Insert', 'action' => 'at'])
+            ->insertAt(1, 'Insert At Again', ['controller' => 'Insert', 'action' => 'at_again']);
+
+        $result = $this->breadcrumbs->getCrumbs();
+        $expected = [
+            [
+                'title' => 'Some text',
+                'link' => [
+                    'controller' => 'Some',
+                    'action' => 'text'
+                ],
+                'options' => []
+            ],
+            [
+                'title' => 'Insert At Again',
+                'link' => [
+                    'controller' => 'Insert',
+                    'action' => 'at_again'
+                ],
+                'options' => []
+            ],
+            [
+                'title' => 'Insert At',
+                'link' => [
+                    'controller' => 'Insert',
+                    'action' => 'at'
+                ],
+                'options' => []
+            ],
+            [
+                'title' => 'Home',
+                'link' => '/',
+                'options' => [
+                    'class' => 'first'
+                ]
+            ]
+        ];
+        $this->assertEquals($expected, $result);
+    }
+
+    /**
+     * Test adding crumbs before a specific one
+     * @return void
+     */
+    public function testInsertBefore()
+    {
+        $this->breadcrumbs
+            ->add('Home', '/', ['class' => 'first'])
+            ->prepend('Some text', ['controller' => 'Some', 'action' => 'text'])
+            ->prepend('The root', '/root', ['data-name' => 'some-name'])
+            ->insertBefore('The root', 'The super root');
+
+        $result = $this->breadcrumbs->getCrumbs();
+        $expected = [
+            [
+                'title' => 'The super root',
+                'link' => null,
+                'options' => []
+            ],
+            [
+                'title' => 'The root',
+                'link' => '/root',
+                'options' => ['data-name' => 'some-name']
+            ],
+            [
+                'title' => 'Some text',
+                'link' => [
+                    'controller' => 'Some',
+                    'action' => 'text'
+                ],
+                'options' => []
+            ],
+            [
+                'title' => 'Home',
+                'link' => '/',
+                'options' => [
+                    'class' => 'first'
+                ]
+            ]
+        ];
+        $this->assertEquals($expected, $result);
+    }
+
+    /**
+     * Test adding crumbs after a specific one
+     * @return void
+     */
+    public function testInsertAfter()
+    {
+        $this->breadcrumbs
+            ->add('Home', '/', ['class' => 'first'])
+            ->prepend('Some text', ['controller' => 'Some', 'action' => 'text'])
+            ->prepend('The root', '/root', ['data-name' => 'some-name'])
+            ->insertAfter('The root', 'The less super root');
+
+        $result = $this->breadcrumbs->getCrumbs();
+        $expected = [
+            [
+                'title' => 'The root',
+                'link' => '/root',
+                'options' => ['data-name' => 'some-name']
+            ],
+            [
+                'title' => 'The less super root',
+                'link' => null,
+                'options' => []
+            ],
+            [
+                'title' => 'Some text',
+                'link' => [
+                    'controller' => 'Some',
+                    'action' => 'text'
+                ],
+                'options' => []
+            ],
+            [
+                'title' => 'Home',
+                'link' => '/',
+                'options' => [
+                    'class' => 'first'
+                ]
+            ]
+        ];
+        $this->assertEquals($expected, $result);
+    }
+}