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 — next ( d901ea...c80d63 )
by Cristian
17:46
created

CrudPanelManager   A

Complexity

Total Complexity 26

Size/Duplication

Total Lines 216
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 58
c 1
b 0
f 0
dl 0
loc 216
rs 10
wmc 26

13 Methods

Rating   Name   Duplication   Size   Complexity  
A getInitializedOperations() 0 3 1
A storeInitializedOperation() 0 6 2
A getActiveController() 0 3 1
A setupCrudPanel() 0 23 3
A getParentController() 0 7 2
A getCrudPanel() 0 13 3
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()) {
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
            $controller->initializeCrudPanel($primaryControllerRequest, $crud);
75
            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

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