| Total Complexity | 43 |
| Total Lines | 288 |
| Duplicated Lines | 0 % |
| Changes | 7 | ||
| Bugs | 3 | Features | 0 |
Complex classes like AbstractManager often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use AbstractManager, and based on these observations, apply Extract Interface, too.
| 1 | <?php declare(strict_types=1); |
||
| 23 | abstract class AbstractManager |
||
| 24 | { |
||
| 25 | use RenderingFields, |
||
| 26 | SavingFields, |
||
| 27 | HasDetails, |
||
| 28 | HasSections, |
||
| 29 | ManagesMedia, |
||
| 30 | ManagesPagebuilder, |
||
| 31 | TranslatableCommand, |
||
| 32 | ManagesAssistants; |
||
| 33 | |||
| 34 | protected $translation_columns = []; |
||
| 35 | |||
| 36 | protected $model; |
||
| 37 | |||
| 38 | /** @var Register */ |
||
| 39 | protected $registration; |
||
| 40 | |||
| 41 | protected $pageCount = 20; |
||
| 42 | protected $paginated = true; |
||
| 43 | protected static $bootedTraitMethods = []; |
||
| 44 | |||
| 45 | final public function __construct(Registration $registration) |
||
| 46 | { |
||
| 47 | $this->registration = $registration; |
||
| 48 | |||
| 49 | // Upon instantiation, a general model is set that doesn't point to a persisted record. |
||
| 50 | $this->manage(app($this->registration->model())); |
||
| 51 | |||
| 52 | // Check if key and model are present since the model should be set by the manager itself |
||
| 53 | $this->validateConstraints(); |
||
| 54 | |||
| 55 | static::bootTraitMethods(); |
||
| 56 | } |
||
| 57 | |||
| 58 | public function managerKey(): string |
||
| 59 | { |
||
| 60 | return $this->registration->key(); |
||
| 61 | } |
||
| 62 | |||
| 63 | public function manage($model): Manager |
||
| 64 | { |
||
| 65 | $this->model = $model; |
||
| 66 | |||
| 67 | return $this; |
||
| 68 | } |
||
| 69 | |||
| 70 | public function findManaged($id): Manager |
||
| 71 | { |
||
| 72 | $modelInstance = $this->modelInstance()::where('id', $id)->withoutGlobalScopes()->first(); |
||
| 73 | |||
| 74 | return (new static($this->registration))->manage($modelInstance); |
||
| 75 | } |
||
| 76 | |||
| 77 | public function indexCollection() |
||
| 78 | { |
||
| 79 | $builder = ($this->modelInstance())->query(); |
||
| 80 | |||
| 81 | $this->filters()->apply($builder); |
||
| 82 | |||
| 83 | $builder = $this->indexBuilder($builder); |
||
| 84 | |||
| 85 | $builder = $this->indexSorting($builder); |
||
| 86 | |||
| 87 | if ($this->paginated) { |
||
| 88 | return $this->indexPagination($builder); |
||
| 89 | } |
||
| 90 | |||
| 91 | return $builder->get()->map(function ($model) { |
||
| 92 | return (new static($this->registration))->manage($model); |
||
| 93 | }); |
||
| 94 | } |
||
| 95 | |||
| 96 | protected function indexBuilder(Builder $builder): Builder |
||
| 97 | { |
||
| 98 | return $builder; |
||
| 99 | } |
||
| 100 | |||
| 101 | protected function indexSorting(Builder $builder): Builder |
||
| 102 | { |
||
| 103 | if ($this->isAssistedBy('publish') && Schema::hasColumn($this->modelInstance()->getTable(), 'published_at')) { |
||
| 104 | $builder->orderBy('published_at', 'DESC'); |
||
| 105 | } |
||
| 106 | |||
| 107 | // if model has no timestamps, updated_at doesn't exist |
||
| 108 | if ($this->modelInstance()->timestamps) { |
||
| 109 | $builder->orderBy('updated_at', 'DESC'); |
||
| 110 | } |
||
| 111 | |||
| 112 | return $builder; |
||
| 113 | } |
||
| 114 | |||
| 115 | protected function indexPagination($builder): Paginator |
||
| 116 | { |
||
| 117 | $paginator = $builder->paginate($this->pageCount); |
||
| 118 | |||
| 119 | $modifiedCollection = $builder->paginate($this->pageCount)->getCollection()->transform(function ($model) { |
||
| 120 | return (new static($this->registration))->manage($model); |
||
| 121 | }); |
||
| 122 | |||
| 123 | return $paginator->setCollection($modifiedCollection); |
||
| 124 | } |
||
| 125 | |||
| 126 | public function modelInstance(): ManagedModel |
||
| 127 | { |
||
| 128 | $class = $this->registration->model(); |
||
| 129 | |||
| 130 | return new $class; |
||
| 131 | } |
||
| 132 | |||
| 133 | public function existingModel(): ManagedModel |
||
| 134 | { |
||
| 135 | if (!$this->hasExistingModel()) { |
||
| 136 | throw new NonExistingRecord('Model does not exist yet but is expected.'); |
||
| 137 | } |
||
| 138 | |||
| 139 | return $this->model; |
||
| 140 | } |
||
| 141 | |||
| 142 | public function hasExistingModel(): bool |
||
| 143 | { |
||
| 144 | return ($this->model && $this->model->exists); |
||
| 145 | } |
||
| 146 | |||
| 147 | /** |
||
| 148 | * Determine which actions should be available for this |
||
| 149 | * manager and their respective routed urls. |
||
| 150 | * |
||
| 151 | * @param $verb |
||
| 152 | * @return null|string |
||
| 153 | * @throws NonExistingRecord |
||
| 154 | */ |
||
| 155 | public function route($verb): ?string |
||
| 176 | } |
||
| 177 | |||
| 178 | public function can($verb): bool |
||
| 179 | { |
||
| 180 | foreach (static::$bootedTraitMethods['can'] as $method) { |
||
| 181 | if (!method_exists($this, $method)) { |
||
| 182 | continue; |
||
| 183 | } |
||
| 184 | $this->$method($verb); |
||
| 185 | } |
||
| 186 | |||
| 187 | return !is_null($this->route($verb)); |
||
| 188 | } |
||
| 189 | |||
| 190 | public function guard($verb): Manager |
||
| 197 | } |
||
| 198 | |||
| 199 | public function fields(): Fields |
||
| 200 | { |
||
| 201 | return new Fields(); |
||
| 202 | } |
||
| 203 | |||
| 204 | /** |
||
| 205 | * Enrich the manager fields with any of the assistant specified fields |
||
| 206 | * |
||
| 207 | * @return Fields |
||
| 208 | * @throws \Exception |
||
| 209 | */ |
||
| 210 | public function fieldsWithAssistantFields(): Fields |
||
| 223 | } |
||
| 224 | |||
| 225 | /** |
||
| 226 | * This determines the arrangement of the manageable fields |
||
| 227 | * on the create and edit forms. By default, all fields |
||
| 228 | * are presented in their order of appearance |
||
| 229 | * |
||
| 230 | * @param null $key pinpoint to a specific field arrangement e.g. for create page. |
||
| 231 | * @return FieldArrangement |
||
| 232 | * @throws \Exception |
||
| 233 | */ |
||
| 234 | public function fieldArrangement($key = null): FieldArrangement |
||
| 237 | } |
||
| 238 | |||
| 239 | public function delete() |
||
| 240 | { |
||
| 241 | $this->guard('delete'); |
||
| 242 | |||
| 243 | if ($this->model instanceof ActsAsChild) { |
||
| 244 | $this->model->detachAllParentRelations(); |
||
| 245 | } |
||
| 246 | |||
| 247 | if ($this->model instanceof ActsAsParent) { |
||
| 248 | $this->model->detachAllChildRelations(); |
||
| 249 | } |
||
| 250 | |||
| 251 | $this->model->delete(); |
||
| 252 | } |
||
| 253 | |||
| 254 | public static function filters(): Filters |
||
| 255 | { |
||
| 256 | return new Filters(); |
||
| 257 | } |
||
| 258 | |||
| 259 | /** |
||
| 260 | * This method can be used to manipulate the store request payload |
||
| 261 | * before being passed to the storing / updating the models. |
||
| 262 | * |
||
| 263 | * @param Request $request |
||
| 264 | * @return Request |
||
| 265 | */ |
||
| 266 | public function storeRequest(Request $request): Request |
||
| 269 | } |
||
| 270 | |||
| 271 | /** |
||
| 272 | * This method can be used to manipulate the update request payload |
||
| 273 | * before being passed to the storing / updating the models. |
||
| 274 | * |
||
| 275 | * @param Request $request |
||
| 276 | * @return Request |
||
| 277 | */ |
||
| 278 | public function updateRequest(Request $request): Request |
||
| 279 | { |
||
| 280 | return $request; |
||
| 281 | } |
||
| 282 | |||
| 283 | protected function requestContainsTranslations(Request $request): bool |
||
| 284 | { |
||
| 285 | return $request->has('trans'); |
||
| 286 | } |
||
| 287 | |||
| 288 | protected function validateConstraints() |
||
| 292 | } |
||
| 293 | } |
||
| 294 | |||
| 295 | public static function bootTraitMethods() |
||
| 311 | } |
||
| 312 | } |
||
| 313 | } |
||
| 314 | } |
||
| 315 | } |
||
| 316 |