Browse Source

Add the render method to the BreadcrumbsHelper

Yves P 9 years ago
parent
commit
04dc55e3b1

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

@@ -15,13 +15,40 @@
 namespace Cake\View\Helper;
 namespace Cake\View\Helper;
 
 
 use Cake\View\Helper;
 use Cake\View\Helper;
+use Cake\View\StringTemplateTrait;
 use LogicException;
 use LogicException;
 
 
 /**
 /**
  * BreadcrumbsHelper to register and display a breadcrumb trail for your views
  * BreadcrumbsHelper to register and display a breadcrumb trail for your views
+ *
+ * @property \Cake\View\Helper\UrlHelper $Url
  */
  */
 class BreadcrumbsHelper extends Helper
 class BreadcrumbsHelper extends Helper
 {
 {
+
+    use StringTemplateTrait;
+
+    /**
+     * Other helpers used by BreadcrumbsHelper
+     *
+     * @var array
+     */
+    public $helpers = ['Url'];
+
+    /**
+     * Default config for the helper.
+     *
+     * @var array
+     */
+    protected $_defaultConfig = [
+        'templates' => [
+            'wrapper' => '<ul{{attrs}}>{{content}}</ul>',
+            'item' => '<li{{attrs}}><a href="{{link}}"{{innerAttrs}}>{{title}}</a></li>',
+            'itemWithoutLink' => '<li{{attrs}}><span{{innerAttrs}}>{{title}}</span></li>',
+            'separator' => '<li{{attrs}}><span{{innerAttrs}}>{{separator}}</span></li>'
+        ]
+    ];
+
     /**
     /**
      * The crumbs list.
      * The crumbs list.
      *
      *
@@ -148,4 +175,93 @@ class BreadcrumbsHelper extends Helper
     {
     {
        return $this->crumbs;
        return $this->crumbs;
     }
     }
+
+    /**
+     * Renders the breadcrumbs trail
+     *
+     * @param array $attributes Array of attributes applied to the wrapper element
+     * @param array $separator Array of attributes for the `separator` template
+     * @return string The breadcrumbs trail
+     */
+    public function render(array $attributes = [], array $separator = [])
+    {
+        $crumbs = $this->crumbs;
+        $crumbsCount = count($crumbs);
+        $templater = $this->templater();
+
+        if (!empty($separator)) {
+            $separatorParams = [];
+            if (isset($separator['innerAttrs'])) {
+                $separatorParams['innerAttrs'] = $templater->formatAttributes($separator['innerAttrs']);
+                unset($separator['innerAttrs']);
+            }
+
+            if (isset($separator['separator'])) {
+                $separatorParams['separator'] = $separator['separator'];
+                unset($separator['separator']);
+            }
+
+            $separatorParams['attrs'] = $templater->formatAttributes($separator);
+        }
+
+        $crumbTrail = '';
+        foreach ($crumbs as $key => $crumb) {
+            $link = $this->prepareLink($crumb['link']);
+            $title = $crumb['title'];
+            $options = $crumb['options'];
+
+            $optionsLink = [];
+            if (isset($options['innerAttrs'])) {
+                $optionsLink = $options['innerAttrs'];
+                unset($options['innerAttrs']);
+            }
+
+            $template = 'item';
+            $templateParams = [
+                'attrs' => $templater->formatAttributes($options),
+                'innerAttrs' => $templater->formatAttributes($optionsLink),
+                'title' => $title,
+                'link' => $link,
+            ];
+
+            if (empty($link)) {
+                $template = 'itemWithoutLink';
+            }
+
+            $crumbTrail .= $this->formatTemplate($template, $templateParams);
+
+            if (isset($separatorParams) && $key !== ($crumbsCount-1)) {
+                $crumbTrail .= $this->formatTemplate('separator', $separatorParams);
+            }
+        }
+
+        $crumbTrail = $this->formatTemplate('wrapper', [
+            'content' => $crumbTrail,
+            'attrs' => $templater->formatAttributes($attributes)
+        ]);
+
+        return $crumbTrail;
+    }
+
+    /**
+     * Prepare the URL for a specific `link` param of a crumb
+     *
+     * @param array|string|null $link If array, an array of Router url params
+     * If string, will be used as is
+     * If empty, will consider that there is no link
+     *
+     * @return null|string The URL of a crumb
+     */
+    protected function prepareLink($link)
+    {
+        if (is_string($link)) {
+            return $link;
+        }
+
+        if (is_array($link)) {
+            return $this->Url->build($link);
+        }
+
+        return null;
+    }
 }
 }

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

@@ -242,4 +242,92 @@ class BreadcrumbsHelperTest extends TestCase
         ];
         ];
         $this->assertEquals($expected, $result);
         $this->assertEquals($expected, $result);
     }
     }
+
+    /**
+     * Tests the render method
+     * @return void
+     */
+    public function testRender()
+    {
+        $this->breadcrumbs
+            ->add('Home', '/', ['class' => 'first', 'innerAttrs' => ['data-foo' => 'bar']])
+            ->add('Some text', ['controller' => 'tests_apps', 'action' => 'some_method'])
+            ->add('Final crumb', null, ['class' => 'final', 'innerAttrs' => ['class' => 'final-link']]);
+
+        $result = $this->breadcrumbs->render(
+            ['data-stuff' => 'foo and bar'],
+            ['separator' => ' > ', 'class' => 'separator']
+        );
+        $expected = [
+            ['ul' => ['data-stuff' => 'foo and bar']],
+            ['li' => ['class' => 'first']],
+            ['a' => ['href' => '/', 'data-foo' => 'bar']],
+            'Home',
+            '/a',
+            '/li',
+            ['li' => ['class' => 'separator']],
+            ['span' => []],
+            ' > ',
+            '/span',
+            '/li',
+            ['li' => []],
+            ['a' => ['href' => '/some_alias']],
+            'Some text',
+            '/a',
+            '/li',
+            ['li' => ['class' => 'separator']],
+            ['span' => []],
+            ' > ',
+            '/span',
+            '/li',
+            ['li' => ['class' => 'final']],
+            ['span' => ['class' => 'final-link']],
+            'Final crumb',
+            '/span',
+            '/li',
+            '/ul'
+        ];
+        $this->assertHtml($expected, $result);
+    }
+
+    /**
+     * Tests the render method with custom templates
+     * @return void
+     */
+    public function testRenderCustomTemplate()
+    {
+        $this->breadcrumbs = new BreadcrumbsHelper(new View(), [
+            'templates' => [
+                'wrapper' => '<ol itemtype="http://schema.org/BreadcrumbList"{{attrs}}>{{content}}</ol>',
+                'item' => '<li itemprop="itemListElement" itemtype="http://schema.org/ListItem"{{attrs}}><a itemtype="http://schema.org/Thing" itemprop="item" href="{{link}}"{{innerAttrs}}><span itemprop="name">{{title}}</span></a></li>',
+                'itemWithoutLink' => '<li itemprop="itemListElement" itemtype="http://schema.org/ListItem"{{attrs}}><span itemprop="name"{{innerAttrs}}>{{title}}</span></li>',
+                'separator' => ''
+            ]
+        ]);
+        $this->breadcrumbs
+            ->add('Home', '/', ['class' => 'first', 'innerAttrs' => ['data-foo' => 'bar']])
+            ->add('Final crumb', null, ['class' => 'final', 'innerAttrs' => ['class' => 'final-link']]);
+
+        $result = $this->breadcrumbs->render(
+            ['data-stuff' => 'foo and bar'],
+            ['separator' => ' > ', 'class' => 'separator']
+        );
+        $expected = [
+            ['ol' => ['itemtype' => 'http://schema.org/BreadcrumbList', 'data-stuff' => 'foo and bar']],
+            ['li' => ['itemprop' => 'itemListElement', 'itemtype' => 'http://schema.org/ListItem', 'class' => 'first']],
+            ['a' => ['itemtype' => 'http://schema.org/Thing', 'itemprop' => 'item', 'href' => '/', 'data-foo' => 'bar']],
+            ['span' => ['itemprop' => 'name']],
+            'Home',
+            '/span',
+            '/a',
+            '/li',
+            ['li' => ['itemprop' => 'itemListElement', 'itemtype' => 'http://schema.org/ListItem', 'class' => 'final']],
+            ['span' => ['itemprop' => 'name', 'class' => 'final-link']],
+            'Final crumb',
+            '/span',
+            '/li',
+            '/ol'
+        ];
+        $this->assertHtml($expected, $result, true);
+    }
 }
 }