-
-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #9 from tattersoftware/breadcrumbs
Breadcrumbs
- Loading branch information
Showing
10 changed files
with
382 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
<?php namespace Tatter\Menus; | ||
|
||
use CodeIgniter\HTTP\URI; | ||
|
||
/** | ||
* Breadcrumb Class | ||
* | ||
* Represents a single item | ||
* in a breadcrumb menu. | ||
*/ | ||
class Breadcrumb | ||
{ | ||
/** | ||
* The URL. | ||
* | ||
* @var string | ||
*/ | ||
public $url; | ||
|
||
/** | ||
* The display value. | ||
* | ||
* @var string | ||
*/ | ||
public $display; | ||
|
||
/** | ||
* @param string $url | ||
* @param string|null $display | ||
*/ | ||
public function __construct(string $url, string $display = null) | ||
{ | ||
// If no display was passed then make a best guess | ||
if (empty($display)) | ||
{ | ||
$uri = new URI($url); | ||
$segments = $uri->getSegments(); | ||
$display = ucfirst(end($segments) ?: lang('Menus.home')); | ||
} | ||
|
||
$this->url = $url; | ||
$this->display = $display; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
<?php | ||
|
||
return [ | ||
'home' => 'Home', | ||
]; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,130 @@ | ||
<?php namespace Tatter\Menus\Menus; | ||
|
||
use Config\Services; | ||
use CodeIgniter\HTTP\URI; | ||
use Tatter\Menus\Breadcrumb; | ||
use Tatter\Menus\Menu; | ||
use Tatter\Menus\Traits\BreadcrumbsStyle; | ||
|
||
/** | ||
* Breadcrumbs Menu | ||
* | ||
* Generates a BootStrap-style series | ||
* of links for nested content. | ||
* | ||
* This class assumes some very basic | ||
* yet specific application structure | ||
* and should often be used only as | ||
* a guide for implementing your own. | ||
*/ | ||
class BreadcrumbsMenu extends Menu | ||
{ | ||
use BreadcrumbsStyle; | ||
|
||
/** | ||
* Array of the Breadcrumbs. | ||
* | ||
* @var Breadcrumb[]|null | ||
*/ | ||
protected static $breadcrumbs; | ||
|
||
/** | ||
* Sets the crumbs based on the | ||
* current/provided URI segments. | ||
* | ||
* @param URI|null $uri | ||
* | ||
* @return Breadcrumb[] The discovered crumbs | ||
*/ | ||
public static function discover(URI $uri = null): array | ||
{ | ||
$uri = $uri ?? Services::request()->uri; | ||
|
||
// Always start with the base URL | ||
$breadcrumbs = [ | ||
new Breadcrumb(base_url(), lang('Menus.home')), | ||
]; | ||
|
||
// Add each segment | ||
foreach ($uri->getSegments() as $segment) | ||
{ | ||
$breadcrumbs[] = new Breadcrumb(site_url($segment)); | ||
} | ||
self::set($breadcrumbs); | ||
|
||
return self::get(); | ||
} | ||
|
||
/** | ||
* Returns the currently-configured crumbs. | ||
* | ||
* @return Breadcrumb[]|null | ||
*/ | ||
public static function get(): ?array | ||
{ | ||
return self::$breadcrumbs; | ||
} | ||
|
||
/** | ||
* Sets the crumbs used to build the Menu. | ||
* | ||
* @param Breadcrumb[]|null $breadcrumbs | ||
*/ | ||
public static function set(?array $breadcrumbs) | ||
{ | ||
self::$breadcrumbs = $breadcrumbs; | ||
} | ||
|
||
/** | ||
* Removes and returns the last crumb. | ||
* | ||
* @return Breadcrumb | ||
*/ | ||
public static function pop(): ?Breadcrumb | ||
{ | ||
return is_null(self::$breadcrumbs) ? null : array_pop(self::$breadcrumbs); | ||
} | ||
|
||
/** | ||
* Adds a new Breadcrumb to the Menu. | ||
* | ||
* @param Breadcrumb $breadcrumb | ||
* | ||
* @return int New number of items in the Menu | ||
*/ | ||
public static function push(Breadcrumb $breadcrumb): int | ||
{ | ||
self::$breadcrumbs = self::$breadcrumbs ?? []; | ||
|
||
return array_push(self::$breadcrumbs, $breadcrumb); | ||
} | ||
|
||
//-------------------------------------------------------------------- | ||
|
||
/** | ||
* Builds the Menu and returns the | ||
* rendered HTML string. | ||
* | ||
* @return string | ||
*/ | ||
public function __toString(): string | ||
{ | ||
// If no breadcrumbs are set then initiate discovery | ||
if (is_null(self::$breadcrumbs)) | ||
{ | ||
self::discover(); | ||
} | ||
|
||
// Use the last item without a link | ||
$last = self::pop(); | ||
|
||
foreach (self::$breadcrumbs as $breadcrumb) | ||
{ | ||
$this->builder->link($breadcrumb->url, $breadcrumb->display); | ||
} | ||
|
||
return $this->builder | ||
->html($last->display, ['class' => 'breadcrumb-item active']) | ||
->render(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
<?php namespace Tatter\Menus\Traits; | ||
|
||
use Spatie\Menu\Link; | ||
|
||
/** | ||
* Breadcrumbs Style Trait | ||
* | ||
* Applies CSS classes & styles | ||
* to make a Bootstrap-style | ||
* breadcrumbs nav Menu. | ||
* | ||
* @mixin \Tatter\Menus\Menu | ||
*/ | ||
trait BreadcrumbsStyle | ||
{ | ||
protected function applyBreadcrumbsStyle(): void | ||
{ | ||
$this->builder | ||
->addClass('breadcrumb') | ||
->setWrapperTag('ol') | ||
->wrap('nav', ['aria-label' => 'breadcrumb']) | ||
->registerFilter(function (Link $link) { | ||
$link->addParentClass('breadcrumb-item'); | ||
}); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
<?php namespace Tests\Support; | ||
|
||
use Tatter\Menus\Breadcrumb; | ||
use Tests\Support\MenusTestCase; | ||
|
||
class BreadcrumbTest extends MenusTestCase | ||
{ | ||
public function testUsesProvidedDisplay() | ||
{ | ||
$breadcrumb = new Breadcrumb(site_url('fruit'), 'banana'); | ||
|
||
$this->assertSame('banana', $breadcrumb->display); | ||
} | ||
|
||
public function testGuessesDisplay() | ||
{ | ||
$breadcrumb = new Breadcrumb(site_url('fruit')); | ||
|
||
$this->assertSame('Fruit', $breadcrumb->display); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
<?php namespace Tests\Support; | ||
|
||
use Tatter\Menus\Breadcrumb; | ||
use Tatter\Menus\Menus\BreadcrumbsMenu; | ||
use Tests\Support\MenusTestCase; | ||
|
||
class BreadcrumbsMenuTest extends MenusTestCase | ||
{ | ||
/** | ||
* @var BreadcrumbsMenu | ||
*/ | ||
private $menu; | ||
|
||
/** | ||
* Initializes the Breadcrumbs menu. | ||
*/ | ||
protected function setUp(): void | ||
{ | ||
parent::setUp(); | ||
|
||
$this->menu = new BreadcrumbsMenu(); | ||
} | ||
|
||
/** | ||
* Removes any Breadcrumbs. | ||
*/ | ||
protected function tearDown(): void | ||
{ | ||
parent::tearDown(); | ||
|
||
BreadcrumbsMenu::set(null); | ||
} | ||
|
||
public function testDiscovery() | ||
{ | ||
$expected = [ | ||
new Breadcrumb('http://example.com', 'Home'), | ||
new Breadcrumb('http://example.com/current', 'Current'), | ||
]; | ||
|
||
$result = BreadcrumbsMenu::discover(); | ||
|
||
$this->assertEquals($expected, $result); | ||
} | ||
|
||
public function testDefaultUsesDiscovery() | ||
{ | ||
$expected = '<nav aria-label="breadcrumb"><ol class="breadcrumb"><li class="breadcrumb-item"><a href="http://example.com">Home</a></li><li class="breadcrumb-item active">Current</li></ol></nav>'; | ||
$result = (string) $this->menu; | ||
|
||
$this->assertSame($expected, $result); | ||
} | ||
|
||
public function testGet() | ||
{ | ||
$breadcrumbs = BreadcrumbsMenu::discover(); | ||
|
||
$result = BreadcrumbsMenu::get(); | ||
|
||
$this->assertSame($breadcrumbs, $result); | ||
} | ||
|
||
public function testSetNull() | ||
{ | ||
BreadcrumbsMenu::discover(); | ||
BreadcrumbsMenu::set(null); | ||
|
||
$result = BreadcrumbsMenu::get(); | ||
|
||
$this->assertNull($result); | ||
} | ||
|
||
public function testPopNull() | ||
{ | ||
$result = BreadcrumbsMenu::pop(); | ||
|
||
$this->assertNull($result); | ||
} | ||
|
||
public function testPop() | ||
{ | ||
$breadcrumbs = BreadcrumbsMenu::discover(); | ||
|
||
$result = BreadcrumbsMenu::pop(); | ||
|
||
$this->assertSame($breadcrumbs[1], $result); | ||
} | ||
|
||
public function testPushNull() | ||
{ | ||
$breadcrumb = new Breadcrumb('food'); | ||
|
||
$result = BreadcrumbsMenu::push($breadcrumb); | ||
$this->assertSame(1, $result); | ||
|
||
$this->assertSame($breadcrumb, BreadcrumbsMenu::pop()); | ||
} | ||
|
||
public function testPush() | ||
{ | ||
$breadcrumbs = BreadcrumbsMenu::discover(); | ||
|
||
$breadcrumb = new Breadcrumb('food'); | ||
|
||
$result = BreadcrumbsMenu::push($breadcrumb); | ||
$this->assertSame(3, $result); | ||
|
||
$this->assertSame($breadcrumb, BreadcrumbsMenu::pop()); | ||
} | ||
} |
Oops, something went wrong.