Skip to content
Merged
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
28 changes: 28 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -383,3 +383,31 @@ Widget::group('sidebar')->removeAll(); // Widget group is empty now
`Widget::group('sidebar')->any(); // bool`

`Widget::group('sidebar')->count(); // int`

## Namespaces for third party packages (extra)

In some cases, it may be useful to deliver widgets with your own packages. For example, if your package allows
you to manage news, it would be convenient to have immediately configurable widgets, ready for display, directly
delivered with your package.

To avoid having to use the fqcn each time, you can set a widget namespace into your package provider. This way the
widgets from your package can be more easily identified, and especially the syntax will be shorter.

To do that, all you have to do is to register the namespace in your package service provider :

```php
public function boot()
{
app('arrilot.widget-namespaces')->registerNamespace('my-package-name', '\VendorName\PackageName\Path\To\Widgets');
}
```

After that you can use the namespace in your views :

```php
@widget('my-package-name::foo.bar')

// is equivalent to
@widget('\VendorName\PackageName\Path\To\Widgets\Foo\Bar')
```

2 changes: 1 addition & 1 deletion src/Console/WidgetMakeCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ protected function makeViewName()
// convert to snake_case part by part to avoid unexpected underscores.
$nameArray = explode('/', $name);
array_walk($nameArray, function (&$part) {
$part = snake_case($part);
$part = Str::snake($part);
});

return implode('/', $nameArray);
Expand Down
9 changes: 9 additions & 0 deletions src/Contracts/ApplicationWrapperContract.php
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,13 @@ public function getNamespace();
* @return mixed
*/
public function make($abstract, array $parameters = []);

/**
* Wrapper around app()->get().
*
* @param string $id
*
* @return mixed
*/
public function get($id);
}
16 changes: 13 additions & 3 deletions src/Factories/AbstractWidgetFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use Arrilot\Widgets\Misc\InvalidWidgetClassException;
use Arrilot\Widgets\Misc\ViewExpressionTrait;
use Arrilot\Widgets\WidgetId;
use Illuminate\Support\Str;

abstract class AbstractWidgetFactory
{
Expand Down Expand Up @@ -115,12 +116,21 @@ protected function instantiateWidget(array $params = [])
{
WidgetId::increment();

$this->widgetName = $this->parseFullWidgetNameFromString(array_shift($params));
$str = array_shift($params);

if (preg_match('#^(.*?)::(.*?)$#', $str, $m)) {
$rootNamespace = $this->app->get('arrilot.widget-namespaces')->getNamespace($m[1]);
$str = $m[2];
}

$this->widgetName = $this->parseFullWidgetNameFromString($str);
$this->widgetFullParams = $params;
$this->widgetConfig = (array) array_shift($params);
$this->widgetParams = $params;

$rootNamespace = $this->app->config('laravel-widgets.default_namespace', $this->app->getNamespace().'Widgets');
if (!isset($rootNamespace)) {
$rootNamespace = $this->app->config('laravel-widgets.default_namespace', $this->app->getNamespace().'Widgets');
}

$fqcn = $rootNamespace.'\\'.$this->widgetName;
$widgetClass = class_exists($fqcn) ? $fqcn : $this->widgetName;
Expand Down Expand Up @@ -149,7 +159,7 @@ protected function instantiateWidget(array $params = [])
*/
protected function parseFullWidgetNameFromString($widgetName)
{
return studly_case(str_replace('.', '\\_', $widgetName));
return Str::studly(str_replace('.', '\\_', $widgetName));
}

/**
Expand Down
14 changes: 14 additions & 0 deletions src/Misc/LaravelApplicationWrapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -90,4 +90,18 @@ public function make($abstract, array $parameters = [])
{
return $this->app->make($abstract, $parameters);
}

/**
* Wrapper around app()->get().
*
* @param string $id
*
* @throws \Illuminate\Container\EntryNotFoundException
*
* @return mixed
*/
public function get($id)
{
return $this->app->get($id);
}
}
9 changes: 9 additions & 0 deletions src/Misc/NamespaceNotFoundException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php

namespace Arrilot\Widgets\Misc;

use Exception;

class NamespaceNotFoundException extends Exception
{
}
48 changes: 48 additions & 0 deletions src/NamespacesRepository.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<?php

namespace Arrilot\Widgets;

use Arrilot\Widgets\Misc\NamespaceNotFoundException;

class NamespacesRepository
{
/**
* The array of namespaces.
*
* @var array
*/
protected $namespaces;

/**
* Register a namespace.
*
* @param string $alias
* @param string $namespace
*
* @return WidgetNamespaces
*/
public function registerNamespace($alias, $namespace)
{
$this->namespaces[$alias] = rtrim($namespace, '\\');

return $this;
}

/**
* Get namespace by his alias.
*
* @param string $label
*
* @throws \Exception
*
* @return string
*/
public function getNamespace($alias)
{
if (!isset($this->namespaces[$alias])) {
throw new NamespaceNotFoundException('Namespace not found with the alias "'.$alias.'"');
}

return $this->namespaces[$alias];
}
}
4 changes: 4 additions & 0 deletions src/ServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ public function register()
return new WidgetGroupCollection(new LaravelApplicationWrapper());
});

$this->app->singleton('arrilot.widget-namespaces', function () {
return new NamespacesRepository();
});

$this->app->singleton('command.widget.make', function ($app) {
return new WidgetMakeCommand($app['files']);
});
Expand Down
17 changes: 16 additions & 1 deletion tests/Support/TestApplicationWrapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@
use Arrilot\Widgets\Contracts\ApplicationWrapperContract;
use Arrilot\Widgets\Factories\AsyncWidgetFactory;
use Arrilot\Widgets\Factories\WidgetFactory;
use Illuminate\Container\Container;
use Arrilot\Widgets\NamespacesRepository;
use Closure;
use Doctrine\Instantiator\Exception\InvalidArgumentException;
use Illuminate\Container\Container;

class TestApplicationWrapper implements ApplicationWrapperContract
{
Expand Down Expand Up @@ -107,4 +108,18 @@ public function make($abstract, array $parameters = [])

throw new InvalidArgumentException("Binding {$abstract} cannot be resolved while testing");
}

/**
* Wrapper around app()->get().
*
* @param string $id
*
* @return mixed
*/
public function get($id)
{
if ($id == 'arrilot.widget-namespaces') {
return (new NamespacesRepository())->registerNamespace('dummy', '\Arrilot\Widgets\Test\Dummies');
}
}
}
14 changes: 14 additions & 0 deletions tests/WidgetFactoryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,20 @@ public function testItCanRunWidgetsUsingFQCN()
$this->assertEquals('Default test slider was executed with $slides = 6', $output);
}

public function testItThrowsExceptionForNamespaceNotFound()
{
$this->expectException('Arrilot\Widgets\Misc\NamespaceNotFoundException');

$output = $this->factory->run('notfound::TestDefaultSlider');
}

public function testItCanRunWidgetsUsingNamespace()
{
$output = $this->factory->run('dummy::TestDefaultSlider');

$this->assertEquals('Default test slider was executed with $slides = 6', $output);
}

public function testItLoadsWidgetsFromRootNamespaceFirst()
{
$output = $this->factory->run('Exception');
Expand Down