Scrutinizer GitHub App not installed

We could not synchronize checks via GitHub's checks API since Scrutinizer's GitHub App is not installed for this repository.

Install GitHub App

Passed
Push — Form-component-alone ( 212cf4 )
by Pedro
12:33
created

CrudPanelManager   A

Complexity

Total Complexity 28

Size/Duplication

Total Lines 226
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 61
c 1
b 0
f 0
dl 0
loc 226
rs 10
wmc 28

14 Methods

Rating   Name   Duplication   Size   Complexity  
A getCrudPanel() 0 13 3
A isOperationInitialized() 0 3 1
A getInitializedOperations() 0 3 1
A storeInitializedOperation() 0 6 2
A getActiveController() 0 3 1
A setupCrudPanel() 0 25 4
A getParentController() 0 7 2
A setActiveController() 0 4 1
A hasCrudPanel() 0 3 1
B identifyCrudPanel() 0 35 7
A unsetActiveController() 0 3 1
A getActiveCrudPanel() 0 7 2
A getCrudPanels() 0 3 1
A storeCrudPanel() 0 3 1
1
<?php
2
3
namespace Backpack\CRUD;
4
5
use Backpack\CRUD\app\Http\Controllers\Contracts\CrudControllerContract;
6
use Backpack\CRUD\app\Http\Controllers\CrudController;
7
use Backpack\CRUD\app\Library\CrudPanel\CrudPanel;
8
use Illuminate\Support\Facades\Facade;
9
10
/**
11
 * CrudPanelManager - Central registry and factory for CRUD panels.
12
 *
13
 * This class manages multiple CrudPanel instances across different controllers.
14
 * It acts as a singleton registry that:
15
 * - Creates and stores CrudPanel instances for each controller
16
 * - Tracks which operations have been initialized for each controller
17
 * - Manages the currently active controller context
18
 * - Provides methods to retrieve the appropriate CrudPanel based on context
19
 *
20
 * This allows multiple CRUD controllers to coexist and share state properly
21
 * within a single request lifecycle.
22
 */
23
final class CrudPanelManager
24
{
25
    /** @var array<string, CrudPanel> Registry of CrudPanel instances indexed by controller class name */
26
    private array $cruds = [];
27
28
    /** @var array<string, array<string>> Tracks which operations have been initialized for each controller */
29
    private array $initializedOperations = [];
30
31
    /** @var string|null The currently active controller class name */
32
    private ?string $currentlyActiveCrudController = null;
33
34
    /**
35
     * Get or create a CrudPanel instance for the given controller.
36
     */
37
    public function getCrudPanel(CrudControllerContract|string $controller): CrudPanel
38
    {
39
        $controllerClass = is_string($controller) ? $controller : get_class($controller);
40
41
        if (isset($this->cruds[$controllerClass])) {
42
            return $this->cruds[$controllerClass];
43
        }
44
45
        $instance = new CrudPanel();
46
47
        $this->cruds[$controllerClass] = $instance;
48
49
        return $this->cruds[$controllerClass];
50
    }
51
52
    /**
53
     * Setup and initialize a CrudPanel for the given controller and operation.
54
     *
55
     * @param  string  $controller  The controller class name
56
     * @param  string|null  $operation  The operation to set (defaults to 'list')
57
     * @return CrudPanel The initialized CrudPanel instance
58
     */
59
    public function setupCrudPanel(string $controller, ?string $operation = null): CrudPanel
60
    {
61
        $controller = $this->getActiveController() ?? $controller;
62
63
        $controller = is_string($controller) ? app($controller) : $controller;
0 ignored issues
show
introduced by
The condition is_string($controller) is always true.
Loading history...
64
65
        $crud = $this->getCrudPanel($controller);
0 ignored issues
show
Bug introduced by
It seems like $controller can also be of type Illuminate\Contracts\Foundation\Application and Illuminate\Foundation\Application; however, parameter $controller of Backpack\CRUD\CrudPanelManager::getCrudPanel() does only seem to accept Backpack\CRUD\app\Http\C...ntrollerContract|string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

65
        $crud = $this->getCrudPanel(/** @scrutinizer ignore-type */ $controller);
Loading history...
66
67
        // Use provided operation or default to 'list'
68
        $operation = $operation ?? 'list';
69
        $crud->setOperation($operation);
70
71
        $primaryControllerRequest = $this->cruds[array_key_first($this->cruds)]->getRequest();
72
        if (! $crud->isInitialized() || ! $this->isOperationInitialized($controller::class, $operation)) {
73
            self::setActiveController($controller::class);
0 ignored issues
show
Bug Best Practice introduced by
The method Backpack\CRUD\CrudPanelM...::setActiveController() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

73
            self::/** @scrutinizer ignore-call */ 
74
                  setActiveController($controller::class);
Loading history...
74
            $crud->initialized = false;
75
            self::setActiveController($controller::class);
76
            $controller->initializeCrudPanel($primaryControllerRequest, $crud);
77
            self::unsetActiveController();
0 ignored issues
show
Bug Best Practice introduced by
The method Backpack\CRUD\CrudPanelM...unsetActiveController() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

77
            self::/** @scrutinizer ignore-call */ 
78
                  unsetActiveController();
Loading history...
78
            $crud = $this->cruds[$controller::class];
0 ignored issues
show
Unused Code introduced by
The assignment to $crud is dead and can be removed.
Loading history...
79
80
            return $this->cruds[$controller::class];
81
        }
82
83
        return $this->cruds[$controller::class];
84
    }
85
86
    /**
87
     * Check if a specific operation has been initialized for a controller.
88
     */
89
    public function isOperationInitialized(string $controller, string $operation): bool
90
    {
91
        return in_array($operation, $this->getInitializedOperations($controller), true);
92
    }
93
94
    /**
95
     * Record that an operation has been initialized for a controller.
96
     *
97
     * @param  string  $controller  The controller class name
98
     * @param  string  $operation  The operation name (e.g., 'list', 'create', 'update')
99
     */
100
    public function storeInitializedOperation(string $controller, ?string $operation): void
101
    {
102
        if (! $operation) {
103
            return;
104
        }
105
        $this->initializedOperations[$controller][] = $operation;
106
    }
107
108
    /**
109
     * Get the list of operations that have been initialized for a controller.
110
     *
111
     * @param  string  $controller  The controller class name
112
     * @return array<string> Array of initialized operation names
113
     */
114
    public function getInitializedOperations(string $controller): array
115
    {
116
        return $this->initializedOperations[$controller] ?? [];
117
    }
118
119
    /**
120
     * Store a CrudPanel instance for a specific controller.
121
     */
122
    public function storeCrudPanel(string $controller, CrudPanel $crud): void
123
    {
124
        $this->cruds[$controller] = $crud;
125
    }
126
127
    /**
128
     * Check if a CrudPanel exists for the given controller.
129
     */
130
    public function hasCrudPanel(string $controller): bool
131
    {
132
        return isset($this->cruds[$controller]);
133
    }
134
135
    /**
136
     * Get the active CrudPanel for a controller, with fallback logic.
137
     *
138
     * @param  string  $controller  The controller class name
139
     * @return CrudPanel The CrudPanel instance, creating one if necessary
140
     */
141
    public function getActiveCrudPanel(string $controller): CrudPanel
142
    {
143
        if (! isset($this->cruds[$controller])) {
144
            return $this->getCrudPanel($this->getActiveController() ?? $this->getParentController() ?? $controller);
145
        }
146
147
        return $this->cruds[$controller];
148
    }
149
150
    /**
151
     * Get the parent (first registered) controller class name.
152
     *
153
     * @return string|null The parent controller class name or null if none exists
154
     */
155
    public function getParentController(): ?string
156
    {
157
        if (! empty($this->cruds)) {
158
            return array_key_first($this->cruds);
159
        }
160
161
        return $this->getActiveController();
162
    }
163
164
    /**
165
     * Set the currently active controller and clear the CRUD facade cache.
166
     *
167
     * @param  string  $controller  The controller class name to set as active
168
     */
169
    public function setActiveController(string $controller): void
170
    {
171
        Facade::clearResolvedInstance('crud');
172
        $this->currentlyActiveCrudController = $controller;
173
    }
174
175
    /**
176
     * Get the currently active controller class name.
177
     *
178
     * @return string|null The active controller class name or null if none is set
179
     */
180
    public function getActiveController(): ?string
181
    {
182
        return $this->currentlyActiveCrudController;
183
    }
184
185
    /**
186
     * Clear the currently active controller.
187
     */
188
    public function unsetActiveController(): void
189
    {
190
        $this->currentlyActiveCrudController = null;
191
    }
192
193
    /**
194
     * Intelligently identify and return the appropriate CrudPanel based on context.
195
     *
196
     * This method uses multiple strategies to find the correct CrudPanel:
197
     * 1. Use the currently active controller if set
198
     * 2. Analyze the call stack to find a CRUD controller in the backtrace
199
     * 3. Return the first available CrudPanel if any exist
200
     * 4. Create a default CrudPanel as a last resort
201
     *
202
     * @return CrudPanel The identified or created CrudPanel instance
203
     */
204
    public function identifyCrudPanel(): CrudPanel
205
    {
206
        if ($this->getActiveController()) {
207
            return $this->getCrudPanel($this->getActiveController());
208
        }
209
210
        // Prioritize explicit controller context
211
        $trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
212
        $controller = null;
213
214
        foreach ($trace as $step) {
215
            if (isset($step['class']) &&
216
                is_a($step['class'], CrudControllerContract::class, true)) {
217
                $controller = (string) $step['class'];
218
                break;
219
            }
220
        }
221
222
        if ($controller) {
223
            $crudPanel = $this->getActiveCrudPanel($controller);
224
225
            return $crudPanel;
226
        }
227
228
        $cruds = $this->getCrudPanels();
229
230
        if (! empty($cruds)) {
231
            $crudPanel = reset($cruds);
232
233
            return $crudPanel;
234
        }
235
236
        $this->cruds[CrudController::class] = new CrudPanel();
237
238
        return $this->cruds[CrudController::class];
239
    }
240
241
    /**
242
     * Get all registered CrudPanel instances.
243
     *
244
     * @return array<string, CrudPanel> Array of CrudPanel instances indexed by controller class name
245
     */
246
    public function getCrudPanels(): array
247
    {
248
        return $this->cruds;
249
    }
250
}
251