Skip to content
This repository has been archived by the owner on Oct 18, 2020. It is now read-only.

Added string class support #129

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions config/breadcrumbs.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@
return [

'view' => 'breadcrumbs::bootstrap3',
'namespace' => '',

];
22 changes: 22 additions & 0 deletions src/Breadcrumbs.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php

namespace DaveJamesMiller\Breadcrumbs;

abstract class Breadcrumbs
{
/**
* @var Generator
*/
protected $generator;


/**
* Breadcrumbs constructor.
*
* @param Generator $generator
*/
public function __construct(Generator $generator)
{
$this->generator = $generator;
}
}
93 changes: 90 additions & 3 deletions src/Generator.php
Original file line number Diff line number Diff line change
@@ -1,11 +1,42 @@
<?php namespace DaveJamesMiller\Breadcrumbs;

use Illuminate\Container\Container;
use Illuminate\Contracts\Container\Container as ContainerContract;
use Illuminate\Support\Str;
use UnexpectedValueException;

class Generator {

protected $breadcrumbs = [];
protected $callbacks = [];

public function generate(array $callbacks, $name, $params)
/**
* The IoC container instance.
*
* @var \Illuminate\Contracts\Container\Container
*/
protected $container;

/**
* Namespace
*
* @var String
*/
protected $namespace;

/**
* Generator constructor.
*
* @param \Illuminate\Contracts\Container\Container|null $container
* @param String $namespace
*/
public function __construct(ContainerContract $container = null, $namespace)
{
$this->container = $container ?: new Container;
$this->namespace = $namespace;
}

public function generate(array $callbacks, $name, $params)
{
$this->breadcrumbs = [];
$this->callbacks = $callbacks;
Expand All @@ -19,9 +50,9 @@ protected function call($name, $params)
if (!isset($this->callbacks[$name]))
throw new Exception("Breadcrumb not found with name \"{$name}\"");

array_unshift($params, $this);
list($function, $param_arr) = $this->createClassCallable($this->callbacks[$name], $this->container, $params);

call_user_func_array($this->callbacks[$name], $params);
call_user_func_array($function, $param_arr);
}

public function parent($name)
Expand Down Expand Up @@ -60,4 +91,60 @@ public function toArray()
return $breadcrumbs;
}

/**
* @param mixed $callback
* @param ContainerContract $container
* @param array $param_arr
*
* @return array
*/
protected function createClassCallable($callback, $container, $param_arr)
{
array_unshift($param_arr, $this);

if(is_callable($callback)) {
return [$callback, $param_arr];
}

if( ! is_string($callback)) {
throw new UnexpectedValueException(sprintf(
'Invalid breadcrumbs callback: [%s]', $callback
));
}

if( ! Str::contains($callback, '@')) {
$callback .= '@__invoke';
}

list($class, $method) = $this->parseClassCallable($callback);

if( ! method_exists($class, $method)) {
throw new UnexpectedValueException(sprintf(
'Invalid breadcrumbs callback: [%s]', $callback
));
}

$parameters = [];

if(is_subclass_of($class, 'DaveJamesMiller\Breadcrumbs\Breadcrumbs')) {
array_shift($param_arr);

$parameters = [$this];
}

return [[$container->make($class, $parameters), $method], $param_arr];
}

protected function parseClassCallable($callback)
{
$segments = explode('@', $callback);
$class = $segments[0];

if (!empty($this->namespace) && !starts_with($class, '\\')) {
$class = str_finish($this->namespace, '\\') . $class;
}

return [$class, count($segments) == 2 ? $segments[1] : null];
}

}
13 changes: 12 additions & 1 deletion src/Manager.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,18 @@ public function __construct(CurrentRoute $currentRoute, Generator $generator, Vi
$this->generator = $generator;
$this->currentRoute = $currentRoute;
$this->view = $view;
}
}

public function registerFromRoutes(RouteCollection $routes) {
foreach ($routes as $route) {
$name = array_get($route, 'name');
$breadcrumbs = array_get($route, 'breadcrumb');

if($name && $breadcrumbs) {
$this->register($name, $breadcrumbs);
}
}
}

public function register($name, $callback)
{
Expand Down
47 changes: 47 additions & 0 deletions src/RouteCollection.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<?php

namespace DaveJamesMiller\Breadcrumbs;

use Illuminate\Routing\Route;
use Illuminate\Support\Collection;

class RouteCollection extends Collection
{

/**
* RouteCollection constructor.
*
* @param \Illuminate\Routing\RouteCollection $collection
*/
public function __construct(\Illuminate\Routing\RouteCollection $collection)
{
$items = $this->parseRoutes($collection);

parent::__construct($items);
}

private function parseRoutes($collection)
{
$result = [];

foreach ($collection as $route) {
if($info = $this->getRouteInformation($route)) {
$result[] = $info;
}
}

return $result;
}

protected function getRouteInformation(Route $route)
{
$name = $route->getName();
$breadcrumb = array_get($route->getAction(), 'breadcrumb', null);

if ($breadcrumb === null) {
return null;
}

return compact('name', 'breadcrumb');
}
}
13 changes: 13 additions & 0 deletions src/ServiceProvider.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<?php namespace DaveJamesMiller\Breadcrumbs;

use Illuminate\Container\Container;
use Illuminate\Support\ServiceProvider as BaseServiceProvider;

class ServiceProvider extends BaseServiceProvider {
Expand Down Expand Up @@ -31,6 +32,10 @@ public function provides()
*/
public function register()
{
$this->app->bind('DaveJamesMiller\Breadcrumbs\Generator', function ($app) {
return new Generator(new Container(), $app['config']['breadcrumbs.namespace']);
});

$this->app['breadcrumbs'] = $this->app->share(function($app)
{
$breadcrumbs = $this->app->make('DaveJamesMiller\Breadcrumbs\Manager');
Expand Down Expand Up @@ -62,6 +67,7 @@ public function boot()
]);

$this->registerBreadcrumbs();
$this->registerRoutesBreadcrumbs();
}

// This method can be overridden in a child class
Expand All @@ -74,4 +80,11 @@ public function registerBreadcrumbs()
}
}

private function registerRoutesBreadcrumbs()
{
$routes = new RouteCollection($this->app['router']->getRoutes());

$this->app['breadcrumbs']->registerFromRoutes($routes);
}

}
64 changes: 63 additions & 1 deletion tests/unit/GeneratorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ public function setUp()
{
parent::setUp();

$this->generator = new Generator;
$this->generator = new Generator(null, null);
}

public function testCallbacks()
Expand All @@ -22,6 +22,54 @@ public function testCallbacks()
], 'sample', []);
}

public function testClassCallbacks()
{
$breadcrumbs = $this->generator->generate([
'sample' => 'ExampleAction@sample',
], 'sample', []);

$this->assertCount(1, $breadcrumbs);
}

public function testClassInvokeCallbacks()
{
$breadcrumbs = $this->generator->generate([
'sample' => 'ExampleAction',
], 'sample', []);

$this->assertCount(2, $breadcrumbs);
}

public function testClassCallbacks_error()
{
$isError = false;

try {
$this->generator->generate([
'sample' => 'ExampleAction@fail',
], 'sample', []);
} catch (Exception $e) {
$isError = true;
}

$this->assertTrue($isError);
}

public function testClassCallbacks_wrongParamenter()
{
$isError = false;

try {
$this->generator->generate([
'sample' => 1234,
], 'sample', []);
} catch (Exception $e) {
$isError = true;
}

$this->assertTrue($isError);
}

public function testCallbackParameters()
{
$this->generator->generate([
Expand Down Expand Up @@ -187,3 +235,17 @@ public function testFirstLast()
}

}

class ExampleAction {

public function sample(Generator $generator)
{
$generator->push('Level 1');
}

public function __invoke(Generator $generator)
{
$generator->push('Level 1');
$generator->push('Level 2');
}
}