Skip to content

Commit

Permalink
Added the controller hooks feature
Browse files Browse the repository at this point in the history
  • Loading branch information
fulopattila122 committed Mar 15, 2024
1 parent f2b7e1a commit b39c4de
Show file tree
Hide file tree
Showing 4 changed files with 144 additions and 3 deletions.
5 changes: 5 additions & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

## 1.X Series

### Unreleased
##### 2024-XX-YY

- Added the controller hooks feature

### 1.14.0
##### 2024-01-08

Expand Down
67 changes: 64 additions & 3 deletions docs/controllers.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,69 @@
# Controllers

A box can ship with predefined controllers, and they can be used directly or via routes.
A module can ship with controllers which can be used directly or via predefined routes.

## Hooking Into Data Injection

> This feature is available since version 1.15
If you are developing a package you can allow the host application to modify the data injected into the views,
by making the controller hookable.

This can be very useful if the application has knowledge and access to data that the package is not aware of.

To do this:

1. Add the `HasControllerHooks` trait to your controller;
2. Pass the view data through the `processViewData()` method.

```php
// Controller code in your package:
use \Konekt\Concord\Hooks\HasControllerHooks;

class ChannelController
{
use HasControllerHooks;

public function create()
{
return view('vanilo::channel.create', $this->processViewData(__METHOD__, [
'countries' => Countries::pluck('name', 'id'),
'currencies' => Currencies::choices(),
'domains' => [],
]));
}

public function edit(Channel $channel)
{
return view('vanilo::channel.edit', $this->processViewData(__METHOD__, [
'channel' => $channel,
'countries' => Countries::pluck('name', 'id'),
'currencies' => Currencies::choices(),
'domains' => [],
]));
}
}
```

Having the controller prepared this way, the application can modify the data passed to the view.

The example below will populate the `domains` variable that gets injected into the view with data:

```php
// Application code, most commonly the AppServiceProvider::boot() method:
ChannelController::hookInto('create', 'edit')
->viewDataInjection(function (array $viewData): array {
$viewData['domains'] = tenant()->domains->pluck('domain', 'domain')->toArray();

return $viewData;
});
```

The hook will be called both in the create and the edit actions.

## Using Custom Action

> **NOTE:** This is nothing Concord specific, Laravel provides these
> possibilities out of the box.
> **NOTE:** This solution is not Concord-specific, Laravel provides these possibilities out of the box.
In case an app wants to extend a boxes controller AND wants to use the boxes built in routes, it should do the following thing:

Expand All @@ -16,6 +74,7 @@ You can put this code either in your app's `RouteServiceProvider` or the
`AppServiceProvider` (or any service provider you prefer).

**Example:**

```php
//app/Providers/RouteServiceProvider.php
namespace App\Providers;
Expand Down Expand Up @@ -45,7 +104,9 @@ class RouteServiceProvider extends ServiceProvider
// [...]
}
```

*The Custom Controller:*

```php
//app/Http/Controllers/Admin/OrderController.php
namespace App\Http\Controllers\Admin;
Expand Down
31 changes: 31 additions & 0 deletions src/Hooks/ControllerHook.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

declare(strict_types=1);

/**
* Contains the ControllerHook class.
*
* @copyright Copyright (c) 2024 Attila Fulop
* @author Attila Fulop
* @license MIT
* @since 2024-03-15
*
*/

namespace Konekt\Concord\Hooks;

class ControllerHook
{
/** @var callable $injectionCallback */
protected $injectionCallback;

public function viewDataInjection(callable $callback): void
{
$this->injectionCallback = $callback;
}

public function onInject(array $viewData): array
{
return call_user_func($this->injectionCallback, $viewData);
}
}
44 changes: 44 additions & 0 deletions src/Hooks/HasControllerHooks.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?php

declare(strict_types=1);

/**
* Contains the HasControllerHooks trait.
*
* @copyright Copyright (c) 2024 Attila Fulop
* @author Attila Fulop
* @license MIT
* @since 2024-03-15
*
*/

namespace Konekt\Concord\Hooks;

trait HasControllerHooks
{
/** @var ControllerHook[] */
private static array $controllerHooks = [];

public static function hookInto(string ...$actions): ControllerHook
{
$hook = new ControllerHook();

foreach ($actions as $action) {
$method = static::class . '::' . $action;
self::$controllerHooks[$method] ??= [];
self::$controllerHooks[$method][] = $hook;
}

return $hook;
}

protected function processViewData(string $method, array $data): array
{
$result = $data;
foreach (self::$controllerHooks[$method] ?? [] as $hook) {
$result = $hook->onInject($result);
}

return $result;
}
}

0 comments on commit b39c4de

Please sign in to comment.