Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[POC] datatable as a component for multiple cruds #5688

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
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
16 changes: 16 additions & 0 deletions src/Backpack.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

namespace Backpack\CRUD;

use Illuminate\Support\Facades\Facade;

/**
* @see BackpackManager
*/
class Backpack extends Facade
{
protected static function getFacadeAccessor()
{
return 'backpack-manager';
}
}
52 changes: 52 additions & 0 deletions src/BackpackManager.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<?php

namespace Backpack\CRUD;

use Backpack\CRUD\app\Http\Controllers\Contracts\CrudControllerContract;
use Backpack\CRUD\app\Library\CrudPanel\CrudPanel;

final class BackpackManager
{
private array $cruds;

public function crud(CrudControllerContract $controller): CrudPanel
{
$controllerClass = get_class($controller);

if (isset($this->cruds[$controllerClass])) {
return $this->cruds[$controllerClass];
}

$instance = new CrudPanel();

$this->cruds[$controllerClass] = $instance;

return $this->cruds[$controllerClass];
}

public function crudFromController(string $controller): CrudPanel
{
$controller = new $controller();

$crud = $this->crud($controller);

// TODO: it's hardcoded, but we should figure out a way to make it dynamic if needed.
$crud->setOperation('list');

$primaryControllerRequest = $this->cruds[array_key_first($this->cruds)]->getRequest();

$controller->initializeCrud($primaryControllerRequest, 'list');

return $this->cruds[get_class($controller)];
}

public function hasCrudController(string $controller): bool
{
return isset($this->cruds[$controller]);
}

public function getControllerCrud(string $controller): CrudPanel
{
return $this->cruds[$controller];
}
}
25 changes: 22 additions & 3 deletions src/BackpackServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use Backpack\CRUD\app\Http\Middleware\ThrottlePasswordRecovery;
use Backpack\CRUD\app\Library\CrudPanel\CrudPanel;
use Backpack\CRUD\app\Library\Database\DatabaseSchema;
use Backpack\CRUD\app\Library\Datatable\Datatable;
use Backpack\CRUD\app\Library\Uploaders\Support\UploadersRepository;
use Illuminate\Contracts\Debug\ExceptionHandler;
use Illuminate\Routing\Router;
Expand Down Expand Up @@ -63,6 +64,7 @@ public function boot(Router $router)
$this->sendUsageStats();

Basset::addViewPath(realpath(__DIR__.'/resources/views'));
Blade::component('datatable', Datatable::class);
}

/**
Expand All @@ -83,8 +85,25 @@ public function register()
$this->registerBackpackErrorViews();

// Bind the CrudPanel object to Laravel's service container
$this->app->scoped('crud', function ($app) {
return new CrudPanel();
$this->app->bind('crud', function ($app) {
// loop the stack trace to find the CrudControllerContract that called this method
$trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
$controller = null;
foreach ($trace as $step) {
if (isset($step['class']) && is_a($step['class'], app\Http\Controllers\Contracts\CrudControllerContract::class, true)) {
$controller = $step['class'];
break;
}
}
if (! $controller) {
throw new \Exception('Could not identify the crud controller method. You sure you are calling this from a CrudController?');
}

return Backpack::getControllerCrud($controller);
});

$this->app->scoped('backpack-manager', function ($app) {
return new BackpackManager();
});

$this->app->scoped('DatabaseSchema', function ($app) {
Expand Down Expand Up @@ -329,7 +348,7 @@ public function loadHelpers()
*/
public function provides()
{
return ['crud', 'widgets', 'BackpackViewNamespaces', 'DatabaseSchema', 'UploadersRepository'];
return ['widgets', 'BackpackViewNamespaces', 'DatabaseSchema', 'UploadersRepository'];
}

private function registerBackpackErrorViews()
Expand Down
7 changes: 7 additions & 0 deletions src/app/Http/Controllers/Contracts/CrudControllerContract.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?php

namespace Backpack\CRUD\app\Http\Controllers\Contracts;

interface CrudControllerContract
{
}
42 changes: 27 additions & 15 deletions src/app/Http/Controllers/CrudController.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

namespace Backpack\CRUD\app\Http\Controllers;

use Backpack\CRUD\app\Http\Controllers\Contracts\CrudControllerContract;
use Backpack\CRUD\app\Library\Attributes\DeprecatedIgnoreOnRuntime;
use Backpack\CRUD\Backpack;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Routing\Controller;
Expand All @@ -14,19 +16,16 @@
* @property-read \Backpack\CRUD\app\Library\CrudPanel\CrudPanel $crud
* @property array $data
*/
class CrudController extends Controller
class CrudController extends Controller implements CrudControllerContract
{
use DispatchesJobs, ValidatesRequests;

public $crud;
//public $crud;

public $data = [];

public function __construct()
{
if ($this->crud) {
return;
}

// ---------------------------
// Create the CrudPanel object
// ---------------------------
Expand All @@ -36,18 +35,22 @@ public function __construct()
// It's done inside a middleware closure in order to have
// the complete request inside the CrudPanel object.
$this->middleware(function ($request, $next) {
$this->crud = app('crud');

$this->crud->setRequest($request);

$this->setupDefaults();
$this->setup();
$this->setupConfigurationForCurrentOperation();
if (! Backpack::hasCrudController(get_class($this))) {
$this->initializeCrud($request);
}

return $next($request);
});
}

public function initializeCrud($request, $operation = null)
{
Backpack::crud($this)->setRequest($request);
$this->setupDefaults();
$this->setup();
$this->setupConfigurationForCurrentOperation($operation);
}

/**
* Allow developers to set their configuration options for a CrudPanel.
*/
Expand Down Expand Up @@ -97,9 +100,9 @@ protected function setupDefaults()
* Allow developers to insert default settings by creating a method
* that looks like setupOperationNameOperation (aka setupXxxOperation).
*/
protected function setupConfigurationForCurrentOperation()
protected function setupConfigurationForCurrentOperation(?string $operation = null)
{
$operationName = $this->crud->getCurrentOperation();
$operationName = $operation ?? $this->crud->getCurrentOperation();
if (! $operationName) {
return;
}
Expand All @@ -125,4 +128,13 @@ protected function setupConfigurationForCurrentOperation()
$this->{$setupClassName}();
}
}

public function __get($name)
{
if ($name == 'crud') {
return Backpack::getControllerCrud(get_class($this));
}

return $this->{$name};
}
}
8 changes: 5 additions & 3 deletions src/app/Library/CrudPanel/CrudButton.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

namespace Backpack\CRUD\app\Library\CrudPanel;

use Backpack\CRUD\app\Http\Controllers\CrudController;
use Backpack\CRUD\Backpack;
use Backpack\CRUD\ViewNamespaces;
use Illuminate\Contracts\Support\Arrayable;
use Illuminate\Support\Traits\Conditionable;
Expand Down Expand Up @@ -297,10 +299,10 @@ public function section($stack)
* @param object|null $entry The eloquent Model for the current entry or null if no current entry.
* @return \Illuminate\Contracts\View\View
*/
public function getHtml($entry = null)
public function getHtml($entry = null, $crud = null)
{
$button = $this;
$crud = $this->crud();
$crud = $crud ?? $this->crud();

if ($this->type == 'model_function') {
if (is_null($entry)) {
Expand Down Expand Up @@ -434,7 +436,7 @@ public function collection()
/**
* Access the global CrudPanel object.
*
* @return \Backpack\CRUD\app\Library\CrudPanel\CrudPanel
* @return CrudPanel
*/
public function crud()
{
Expand Down
9 changes: 3 additions & 6 deletions src/app/Library/CrudPanel/CrudPanel.php
Original file line number Diff line number Diff line change
Expand Up @@ -68,21 +68,18 @@ class CrudPanel

public function __construct()
{
$this->setRequest();

if ($this->getCurrentOperation()) {
$this->setOperation($this->getCurrentOperation());
}
}

/**
* Set the request instance for this CRUD.
*
* @param \Illuminate\Http\Request $request
*/
public function setRequest($request = null)
public function setRequest($request = null): self
{
$this->request = $request ?? \Request::instance();

return $this;
}

/**
Expand Down
20 changes: 20 additions & 0 deletions src/app/Library/Datatable/Datatable.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

namespace Backpack\CRUD\app\Library\Datatable;

use Backpack\CRUD\app\Library\CrudPanel\CrudPanel;
use Illuminate\View\Component;

class Datatable extends Component
{
public function __construct(private CrudPanel $crud)
{
}

public function render()
{
return view('crud::datatable.datatable', [
'crud' => $this->crud,
]);
}
}
5 changes: 5 additions & 0 deletions src/resources/views/crud/columns/crud_column.blade.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
@php
$columnCrud = \Backpack\CRUD\Backpack::crudFromController($column['controller']);
@endphp

<x-datatable :crud="$columnCrud" />
Loading