1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Backpack\CRUD; |
4
|
|
|
|
5
|
|
|
class Crud |
6
|
|
|
{ |
7
|
|
|
// -------------- |
8
|
|
|
// CRUD variables |
9
|
|
|
// -------------- |
10
|
|
|
// These variables are passed to the CRUD views, inside the $crud variable. |
11
|
|
|
// All variables are public, so they can be modified from your EntityCrudController. |
12
|
|
|
// All functions and methods are also public, so they can be used in your EntityCrudController to modify these variables. |
13
|
|
|
|
14
|
|
|
// TODO: translate $entity_name and $entity_name_plural by default, with english fallback |
15
|
|
|
// TODO: code logic for using either Laravel Authorization or Entrust (whatever one chooses) for access |
16
|
|
|
|
17
|
|
|
public $model = "\App\Models\Entity"; // what's the namespace for your entity's model |
18
|
|
|
public $route; // what route have you defined for your entity? used for links. |
19
|
|
|
public $entity_name = "entry"; // what name will show up on the buttons, in singural (ex: Add entity) |
20
|
|
|
public $entity_name_plural = "entries"; // what name will show up on the buttons, in plural (ex: Delete 5 entities) |
21
|
|
|
|
22
|
|
|
public $access = ['list', 'create', 'update', 'delete', /* 'reorder', 'show', 'details_row' */]; |
|
|
|
|
23
|
|
|
|
24
|
|
|
public $reorder = false; |
25
|
|
|
public $reorder_label = false; |
26
|
|
|
public $reorder_max_level = 3; |
27
|
|
|
|
28
|
|
|
public $details_row = false; |
29
|
|
|
|
30
|
|
|
public $columns = []; // Define the columns for the table view as an array; |
31
|
|
|
public $create_fields = []; // Define the fields for the "Add new entry" view as an array; |
32
|
|
|
public $update_fields = []; // Define the fields for the "Edit entry" view as an array; |
33
|
|
|
|
34
|
|
|
public $query; |
35
|
|
|
public $entry; |
36
|
|
|
|
37
|
|
|
// TONE FIELDS - TODO: find out what he did with them, replicate or delete |
38
|
|
|
public $field_types = []; |
39
|
|
|
|
40
|
|
|
public $custom_buttons = []; |
41
|
|
|
public $relations = []; |
42
|
|
|
public $sort = []; |
43
|
|
|
|
44
|
|
|
public $buttons = ['']; |
45
|
|
|
|
46
|
|
|
|
47
|
|
|
|
48
|
|
|
// The following methods are used in CrudController or your EntityCrudController to manipulate the variables above. |
49
|
|
|
|
50
|
|
|
|
51
|
|
|
/* |
52
|
|
|
|-------------------------------------------------------------------------- |
53
|
|
|
| CREATE |
54
|
|
|
|-------------------------------------------------------------------------- |
55
|
|
|
*/ |
56
|
|
|
|
57
|
|
|
/** |
58
|
|
|
* Insert a row in the database. |
59
|
|
|
* |
60
|
|
|
* @param [Request] All input values to be inserted. |
61
|
|
|
* @return [Eloquent Collection] |
|
|
|
|
62
|
|
|
*/ |
63
|
|
|
public function create($data) |
64
|
|
|
{ |
65
|
|
|
$values_to_store = $this->compactFakeFields($data, 'create'); |
66
|
|
|
$item = $this->model->create($values_to_store); |
|
|
|
|
67
|
|
|
|
68
|
|
|
// if there are any relationships available, also sync those |
69
|
|
|
$this->syncPivot($item, $data); |
70
|
|
|
|
71
|
|
|
return $item; |
72
|
|
|
} |
73
|
|
|
|
74
|
|
|
|
75
|
|
|
/** |
76
|
|
|
* Get all fields needed for the ADD NEW ENTRY form. |
77
|
|
|
* |
78
|
|
|
* @return [array] The fields with attributes and fake attributes. |
|
|
|
|
79
|
|
|
*/ |
80
|
|
|
public function getCreateFields() |
81
|
|
|
{ |
82
|
|
|
return $this->create_fields; |
83
|
|
|
} |
84
|
|
|
|
85
|
|
|
/** |
86
|
|
|
* Get all fields with relation set (model key set on field) |
87
|
|
|
* |
88
|
|
|
* @param [string: create/update/both] |
89
|
|
|
* @return [array] The fields with model key set. |
|
|
|
|
90
|
|
|
*/ |
91
|
|
|
public function getRelationFields($form = 'create') |
92
|
|
|
{ |
93
|
|
|
if ($form == 'create') |
94
|
|
|
{ |
95
|
|
|
$fields = $this->create_fields; |
96
|
|
|
} |
97
|
|
|
else |
98
|
|
|
{ |
99
|
|
|
$fields = $this->update_fields; |
100
|
|
|
} |
101
|
|
|
|
102
|
|
|
$relationFields = []; |
103
|
|
|
|
104
|
|
|
foreach($fields as $field){ |
105
|
|
|
if(isset($field['model']) || isset($field['dependencies'])){ |
106
|
|
|
array_push($relationFields, $field); |
107
|
|
|
} |
108
|
|
|
} |
109
|
|
|
|
110
|
|
|
return $relationFields; |
111
|
|
|
} |
112
|
|
|
|
113
|
|
|
|
114
|
|
|
public function syncPivot($model, $data, $form = 'create') |
115
|
|
|
{ |
116
|
|
|
|
117
|
|
|
$relations = $this->getRelationFields($form); |
118
|
|
|
|
119
|
|
|
foreach ($relations as $key => $relation) |
120
|
|
|
{ |
121
|
|
|
if ( (isset($relation['pivot']) && $relation['pivot'] ) || isset($relation['dependencies']) ){ |
122
|
|
|
if(is_array($relation['name'])){ |
123
|
|
|
foreach($relation['name'] as $relation){ |
124
|
|
|
if(isset($data[$relation])){ |
125
|
|
|
$model->{$relation}()->sync($data[$relation]); |
126
|
|
|
}else{ |
127
|
|
|
$model->{$relation}()->sync([]); |
128
|
|
|
} |
129
|
|
|
} |
130
|
|
|
}else{ |
131
|
|
|
$model->{$relation['name']}()->sync($data[$relation['name']]); |
132
|
|
|
} |
133
|
|
|
|
134
|
|
|
if( isset($relation['pivotFields']) ){ |
135
|
|
|
foreach($relation['pivotFields'] as $pivotField){ |
136
|
|
|
foreach($data[$pivotField] as $pivot_id => $field){ |
137
|
|
|
$model->{$relation['name']}()->updateExistingPivot($pivot_id, [$pivotField => $field]); |
138
|
|
|
} |
139
|
|
|
} |
140
|
|
|
} |
141
|
|
|
} |
142
|
|
|
} |
143
|
|
|
} |
144
|
|
|
|
145
|
|
|
|
146
|
|
|
|
147
|
|
|
/** |
148
|
|
|
* Adds a required => true attribute to each field, so that the required asterisc will show up in the create/update forms. |
149
|
|
|
* TODO: make this work, by editing the $this->fields variable and all fields. |
150
|
|
|
* |
151
|
|
|
* @param [string or array of strings] |
152
|
|
|
*/ |
153
|
|
|
public function setRequiredFields($fields, $form = 'both') |
|
|
|
|
154
|
|
|
{ |
155
|
|
|
// TODO |
156
|
|
|
} |
157
|
|
|
|
158
|
|
|
/** |
159
|
|
|
* Adds a required => true attribute to this field, so that the required asteris will show up in the create/update forms. |
160
|
|
|
* |
161
|
|
|
* @param [string] |
162
|
|
|
*/ |
163
|
|
|
public function setRequiredField($field, $form = 'both') |
|
|
|
|
164
|
|
|
{ |
165
|
|
|
// TODO |
166
|
|
|
} |
167
|
|
|
|
168
|
|
|
/** |
169
|
|
|
* Get all fields that have the required attribute. |
170
|
|
|
* TODO: make this work after making setRequiredFields() work. |
171
|
|
|
* |
172
|
|
|
* @return [array] |
|
|
|
|
173
|
|
|
*/ |
174
|
|
|
public function getRequiredFields($form = 'both') |
|
|
|
|
175
|
|
|
{ |
176
|
|
|
// TODO |
177
|
|
|
} |
178
|
|
|
|
179
|
|
|
|
180
|
|
|
/* |
181
|
|
|
|-------------------------------------------------------------------------- |
182
|
|
|
| READ |
183
|
|
|
|-------------------------------------------------------------------------- |
184
|
|
|
*/ |
185
|
|
|
|
186
|
|
|
/** |
187
|
|
|
* Find and retrieve an entry in the database or fail. |
188
|
|
|
* |
189
|
|
|
* @param [int] The id of the row in the db to fetch. |
190
|
|
|
* @return [Eloquent Collection] The row in the db. |
|
|
|
|
191
|
|
|
*/ |
192
|
|
|
public function getEntry($id) |
193
|
|
|
{ |
194
|
|
|
$entry = $this->model->findOrFail($id); |
|
|
|
|
195
|
|
|
return $entry->withFakes(); |
196
|
|
|
} |
197
|
|
|
|
198
|
|
|
|
199
|
|
|
/** |
200
|
|
|
* Get all entries from the database. |
201
|
|
|
* |
202
|
|
|
* @return [Collection of your model] |
|
|
|
|
203
|
|
|
*/ |
204
|
|
|
public function getEntries() |
205
|
|
|
{ |
206
|
|
|
$entries = $this->query->get(); |
207
|
|
|
|
208
|
|
|
// add the fake columns for each entry |
209
|
|
|
foreach ($entries as $key => $entry) { |
210
|
|
|
$entry->addFakes($this->getFakeColumnsAsArray()); |
211
|
|
|
} |
212
|
|
|
|
213
|
|
|
return $entries; |
214
|
|
|
} |
215
|
|
|
|
216
|
|
|
|
217
|
|
|
/** |
218
|
|
|
* Get the fields for the create or update forms. |
219
|
|
|
* |
220
|
|
|
* @param [form] create / update / both - defaults to 'both' |
221
|
|
|
* @param [integer] the ID of the entity to be edited in the Update form |
222
|
|
|
* @return [array] all the fields that need to be shown and their information |
|
|
|
|
223
|
|
|
*/ |
224
|
|
|
public function getFields($form, $id = false) |
225
|
|
|
{ |
226
|
|
|
switch (strtolower($form)) { |
227
|
|
|
case 'create': |
228
|
|
|
return $this->getCreateFields(); |
229
|
|
|
break; |
|
|
|
|
230
|
|
|
|
231
|
|
|
case 'update': |
232
|
|
|
return $this->getUpdateFields($id); |
233
|
|
|
break; |
|
|
|
|
234
|
|
|
|
235
|
|
|
default: |
236
|
|
|
return $this->getCreateFields(); |
237
|
|
|
break; |
|
|
|
|
238
|
|
|
} |
239
|
|
|
} |
240
|
|
|
|
241
|
|
|
/** |
242
|
|
|
* Enable the DETAILS ROW functionality: |
243
|
|
|
* |
244
|
|
|
* In the table view, show a plus sign next to each entry. |
245
|
|
|
* When clicking that plus sign, an AJAX call will bring whatever content you want from the EntityCrudController::showDetailsRow($id) and show it to the user. |
246
|
|
|
*/ |
247
|
|
|
public function enableDetailsRow() |
248
|
|
|
{ |
249
|
|
|
$this->details_row = true; |
250
|
|
|
} |
251
|
|
|
|
252
|
|
|
/** |
253
|
|
|
* Disable the DETAILS ROW functionality: |
254
|
|
|
*/ |
255
|
|
|
public function disableDetailsRow() |
256
|
|
|
{ |
257
|
|
|
$this->details_row = false; |
258
|
|
|
} |
259
|
|
|
|
260
|
|
|
|
261
|
|
|
|
262
|
|
|
/* |
263
|
|
|
|-------------------------------------------------------------------------- |
264
|
|
|
| UPDATE |
265
|
|
|
|-------------------------------------------------------------------------- |
266
|
|
|
*/ |
267
|
|
|
|
268
|
|
|
/** |
269
|
|
|
* Update a row in the database. |
270
|
|
|
* |
271
|
|
|
* @param [Int] The entity's id |
272
|
|
|
* @param [Request] All inputs to be updated. |
273
|
|
|
* @return [Eloquent Collection] |
|
|
|
|
274
|
|
|
*/ |
275
|
|
|
public function update($id, $data) |
276
|
|
|
{ |
277
|
|
|
$item = $this->model->findOrFail($id); |
|
|
|
|
278
|
|
|
$updated = $item->update($this->compactFakeFields($data, 'update')); |
|
|
|
|
279
|
|
|
|
280
|
|
|
/*if ($updated) */$this->syncPivot($item, $data, 'update'); |
281
|
|
|
|
282
|
|
|
return $item; |
283
|
|
|
} |
284
|
|
|
|
285
|
|
|
|
286
|
|
|
/** |
287
|
|
|
* Get all fields needed for the EDIT ENTRY form. |
288
|
|
|
* |
289
|
|
|
* @param [integer] The id of the entry that is being edited. |
290
|
|
|
* @return [array] The fields with attributes, fake attributes and values. |
|
|
|
|
291
|
|
|
*/ |
292
|
|
|
public function getUpdateFields($id) |
293
|
|
|
{ |
294
|
|
|
$fields = $this->update_fields; |
295
|
|
|
$entry = $this->getEntry($id); |
296
|
|
|
|
297
|
|
|
foreach ($fields as $k => $field) { |
298
|
|
|
// set the value |
299
|
|
|
if (!isset($fields[$k]['value'])) |
300
|
|
|
{ |
301
|
|
|
if(is_array($field['name'])){ |
302
|
|
|
|
303
|
|
|
$fields[$k]['value'] = []; |
304
|
|
|
foreach($field['name'] as $key => $relation){ |
305
|
|
|
$fields[$k]['value'][] = $entry->{$relation}; |
306
|
|
|
} |
307
|
|
|
|
308
|
|
|
}else{ |
309
|
|
|
$fields[$k]['value'] = $entry->{$field['name']}; |
310
|
|
|
} |
311
|
|
|
} |
312
|
|
|
} |
313
|
|
|
|
314
|
|
|
// always have a hidden input for the entry id |
315
|
|
|
$fields[] = array( |
316
|
|
|
'name' => 'id', |
317
|
|
|
'value' => $entry->id, |
318
|
|
|
'type' => 'hidden' |
319
|
|
|
); |
320
|
|
|
|
321
|
|
|
return $fields; |
322
|
|
|
} |
323
|
|
|
|
324
|
|
|
|
325
|
|
|
|
326
|
|
|
|
327
|
|
|
/* |
328
|
|
|
|-------------------------------------------------------------------------- |
329
|
|
|
| DELETE |
330
|
|
|
|-------------------------------------------------------------------------- |
331
|
|
|
*/ |
332
|
|
|
|
333
|
|
|
/** |
334
|
|
|
* Delete a row from the database. |
335
|
|
|
* |
336
|
|
|
* @param [int] The id of the item to be deleted. |
337
|
|
|
* @return [bool] Deletion confirmation. |
|
|
|
|
338
|
|
|
* |
339
|
|
|
* TODO: should this delete items with relations to it too? |
340
|
|
|
*/ |
341
|
|
|
public function delete($id) |
342
|
|
|
{ |
343
|
|
|
return $this->model->destroy($id); |
|
|
|
|
344
|
|
|
} |
345
|
|
|
|
346
|
|
|
|
347
|
|
|
|
348
|
|
|
|
349
|
|
|
/* |
350
|
|
|
|-------------------------------------------------------------------------- |
351
|
|
|
| REORDER |
352
|
|
|
|-------------------------------------------------------------------------- |
353
|
|
|
*/ |
354
|
|
|
|
355
|
|
|
|
356
|
|
|
/** |
357
|
|
|
* Change the order and parents of the given elements, according to the NestedSortable AJAX call. |
358
|
|
|
* |
359
|
|
|
* @param [Request] The entire request from the NestedSortable AJAX Call. |
360
|
|
|
* @return [integer] The number of items whose position in the tree has been changed. |
|
|
|
|
361
|
|
|
*/ |
362
|
|
|
public function updateTreeOrder($request) |
363
|
|
|
{ |
364
|
|
|
$count = 0; |
365
|
|
|
|
366
|
|
|
foreach ($request as $key => $entry) { |
367
|
|
|
if ($entry['item_id'] != "" && $entry['item_id'] != null) { |
368
|
|
|
$item = $this->model->find($entry['item_id']); |
|
|
|
|
369
|
|
|
$item->parent_id = $entry['parent_id']; |
370
|
|
|
$item->depth = $entry['depth']; |
371
|
|
|
$item->lft = $entry['left']; |
372
|
|
|
$item->rgt = $entry['right']; |
373
|
|
|
$item->save(); |
374
|
|
|
|
375
|
|
|
$count++; |
376
|
|
|
} |
377
|
|
|
} |
378
|
|
|
|
379
|
|
|
return $count; |
380
|
|
|
} |
381
|
|
|
|
382
|
|
|
|
383
|
|
|
/** |
384
|
|
|
* Enable the Reorder functionality in the CRUD Panel for users that have the been given access to 'reorder' using: |
385
|
|
|
* $this->crud->allowAccess('reorder'); |
386
|
|
|
* |
387
|
|
|
* @param [string] Column name that will be shown on the labels. |
388
|
|
|
* @param [integer] Maximum hierarchy level to which the elements can be nested (1 = no nesting, just reordering). |
389
|
|
|
*/ |
390
|
|
|
public function enableReorder($label = 'name', $max_level = 1) |
391
|
|
|
{ |
392
|
|
|
$this->reorder = true; |
393
|
|
|
$this->reorder_label = $label; |
|
|
|
|
394
|
|
|
$this->reorder_max_level = $max_level; |
395
|
|
|
} |
396
|
|
|
|
397
|
|
|
/** |
398
|
|
|
* Disable the Reorder functionality in the CRUD Panel for all users. |
399
|
|
|
* |
400
|
|
|
*/ |
401
|
|
|
public function disableReorder() |
402
|
|
|
{ |
403
|
|
|
$this->reorder = false; |
404
|
|
|
} |
405
|
|
|
|
406
|
|
|
/** |
407
|
|
|
* Check if the Reorder functionality is enabled or not. |
408
|
|
|
* |
409
|
|
|
* @return boolean |
410
|
|
|
*/ |
411
|
|
|
public function isReorderEnabled() |
412
|
|
|
{ |
413
|
|
|
return $this->reorder; |
414
|
|
|
} |
415
|
|
|
|
416
|
|
|
|
417
|
|
|
|
418
|
|
|
/* |
419
|
|
|
|-------------------------------------------------------------------------- |
420
|
|
|
| CRUD ACCESS |
421
|
|
|
|-------------------------------------------------------------------------- |
422
|
|
|
*/ |
423
|
|
|
|
424
|
|
|
public function allowAccess($access) |
425
|
|
|
{ |
426
|
|
|
// $this->addButtons((array)$access); |
|
|
|
|
427
|
|
|
return $this->access = array_merge(array_diff((array)$access, $this->access), $this->access); |
428
|
|
|
} |
429
|
|
|
|
430
|
|
|
public function denyAccess($access) |
431
|
|
|
{ |
432
|
|
|
// $this->removeButtons((array)$access); |
|
|
|
|
433
|
|
|
return $this->access = array_diff($this->access, (array)$access); |
434
|
|
|
} |
435
|
|
|
|
436
|
|
|
/** |
437
|
|
|
* Check if a permission is enabled for a Crud Panel. Return false if not. |
438
|
|
|
* |
439
|
|
|
* @param [string] Permission. |
440
|
|
|
* @return boolean |
441
|
|
|
*/ |
442
|
|
|
public function hasAccess($permission) |
443
|
|
|
{ |
444
|
|
|
if (!in_array($permission, $this->access)) |
445
|
|
|
{ |
446
|
|
|
return false; |
447
|
|
|
} |
448
|
|
|
return true; |
449
|
|
|
} |
450
|
|
|
|
451
|
|
|
/** |
452
|
|
|
* Check if a permission is enabled for a Crud Panel. Fail if not. |
453
|
|
|
* |
454
|
|
|
* @param [string] Permission. |
455
|
|
|
* @return boolean |
456
|
|
|
*/ |
457
|
|
|
public function hasAccessOrFail($permission) |
458
|
|
|
{ |
459
|
|
|
if (!in_array($permission, $this->access)) |
460
|
|
|
{ |
461
|
|
|
abort(403, trans('backpack::crud.unauthorized_access')); |
462
|
|
|
} |
463
|
|
|
} |
464
|
|
|
|
465
|
|
|
|
466
|
|
|
|
467
|
|
|
/* |
468
|
|
|
|-------------------------------------------------------------------------- |
469
|
|
|
| CRUD MANIPULATION |
470
|
|
|
|-------------------------------------------------------------------------- |
471
|
|
|
*/ |
472
|
|
|
|
473
|
|
|
|
474
|
|
|
|
475
|
|
|
// ------------------------------------------------------ |
476
|
|
|
// BASICS - model, route, entity_name, entity_name_plural |
477
|
|
|
// ------------------------------------------------------ |
478
|
|
|
|
479
|
|
|
/** |
480
|
|
|
* This function binds the CRUD to its corresponding Model (which extends Eloquent). |
481
|
|
|
* All Create-Read-Update-Delete operations are done using that Eloquent Collection. |
482
|
|
|
* |
483
|
|
|
* @param [string] Full model namespace. Ex: App\Models\Article |
484
|
|
|
*/ |
485
|
|
|
public function setModel($model_namespace) |
486
|
|
|
{ |
487
|
|
|
if (!class_exists($model_namespace)) throw new \Exception('This model does not exist.', 404); |
488
|
|
|
|
489
|
|
|
$this->model = new $model_namespace(); |
|
|
|
|
490
|
|
|
$this->query = $this->model->select('*'); |
491
|
|
|
|
492
|
|
|
// $this->setFromDb(); // i think that, by default, the auto-fields functionality should be disabled; otherwise, the workflow changes from "set the fields i need" to "update this crud with whatever i need"; which i personally don't like, because it's more hacky and it assumes you should see what the default offers you, then adapt; I propose we set wether the auto-fields functionality is run for panels with a config variable; the config file should be backpack/crud.php and the variable name should be "autoSetFromDb". |
|
|
|
|
493
|
|
|
} |
494
|
|
|
|
495
|
|
|
/** |
496
|
|
|
* Get the corresponding Eloquent Model for the CrudController, as defined with the setModel() function; |
497
|
|
|
* |
498
|
|
|
* @return [Eloquent Collection] |
|
|
|
|
499
|
|
|
*/ |
500
|
|
|
public function getModel() |
501
|
|
|
{ |
502
|
|
|
return $this->model; |
503
|
|
|
} |
504
|
|
|
|
505
|
|
|
/** |
506
|
|
|
* Set the route for this CRUD. |
507
|
|
|
* Ex: admin/article |
508
|
|
|
* |
509
|
|
|
* @param [string] Route name. |
510
|
|
|
* @param [array] Parameters. |
511
|
|
|
*/ |
512
|
|
|
public function setRoute($route) |
513
|
|
|
{ |
514
|
|
|
$this->route = $route; |
515
|
|
|
$this->initButtons(); |
516
|
|
|
} |
517
|
|
|
|
518
|
|
|
/** |
519
|
|
|
* Set the route for this CRUD using the route name. |
520
|
|
|
* Ex: admin.article |
521
|
|
|
* |
522
|
|
|
* @param [string] Route name. |
523
|
|
|
* @param [array] Parameters. |
524
|
|
|
*/ |
525
|
|
|
public function setRouteName($route, $parameters = []) |
526
|
|
|
{ |
527
|
|
|
$complete_route = $route.'.index'; |
528
|
|
|
|
529
|
|
|
if (!\Route::has($complete_route)) throw new \Exception('There are no routes for this route name.', 404); |
530
|
|
|
|
531
|
|
|
$this->route = route($complete_route, $parameters); |
532
|
|
|
$this->initButtons(); |
533
|
|
|
} |
534
|
|
|
|
535
|
|
|
/** |
536
|
|
|
* Get the current CrudController route. |
537
|
|
|
* |
538
|
|
|
* Can be defined in the CrudController with: |
539
|
|
|
* - $this->crud->setRoute('admin/article') |
540
|
|
|
* - $this->crud->setRouteName('admin.article') |
541
|
|
|
* - $this->crud->route = "admin/article" |
542
|
|
|
* |
543
|
|
|
* @return [string] |
|
|
|
|
544
|
|
|
*/ |
545
|
|
|
public function getRoute() |
546
|
|
|
{ |
547
|
|
|
return $this->route; |
548
|
|
|
} |
549
|
|
|
|
550
|
|
|
/** |
551
|
|
|
* Set the entity name in singular and plural. |
552
|
|
|
* Used all over the CRUD interface (header, add button, reorder button, breadcrumbs). |
553
|
|
|
* |
554
|
|
|
* @param [string] Entity name, in singular. Ex: article |
555
|
|
|
* @param [string] Entity name, in plural. Ex: articles |
556
|
|
|
*/ |
557
|
|
|
public function setEntityNameStrings($singular, $plural) { |
558
|
|
|
$this->entity_name = $singular; |
559
|
|
|
$this->entity_name_plural = $plural; |
560
|
|
|
} |
561
|
|
|
|
562
|
|
|
|
563
|
|
|
|
564
|
|
|
|
565
|
|
|
// ------------ |
566
|
|
|
// COLUMNS |
567
|
|
|
// ------------ |
568
|
|
|
|
569
|
|
|
/** |
570
|
|
|
* Add a bunch of column names and their details to the CRUD object. |
571
|
|
|
* |
572
|
|
|
* @param [array or multi-dimensional array] |
573
|
|
|
*/ |
574
|
|
|
public function setColumns($columns) |
575
|
|
|
{ |
576
|
|
|
// clear any columns already set |
577
|
|
|
$this->columns = []; |
578
|
|
|
|
579
|
|
|
// if array, add a column for each of the items |
580
|
|
|
if (is_array($columns) && count($columns)) { |
581
|
|
|
foreach ($columns as $key => $column) { |
582
|
|
|
// if label and other details have been defined in the array |
583
|
|
|
if (is_array($columns[0])) { |
584
|
|
|
$this->addColumn($column); |
585
|
|
|
} |
586
|
|
|
else |
587
|
|
|
{ |
588
|
|
|
$this->addColumn([ |
589
|
|
|
'name' => $column, |
590
|
|
|
'label' => ucfirst($column), |
591
|
|
|
'type' => 'text' |
592
|
|
|
]); |
593
|
|
|
} |
594
|
|
|
} |
595
|
|
|
} |
596
|
|
|
|
597
|
|
|
if (is_string($columns)) { |
598
|
|
|
$this->addColumn([ |
599
|
|
|
'name' => $columns, |
600
|
|
|
'label' => ucfirst($columns), |
601
|
|
|
'type' => 'text' |
602
|
|
|
]); |
603
|
|
|
} |
604
|
|
|
|
605
|
|
|
// This was the old setColumns() function, and it did not work: |
606
|
|
|
// $this->columns = array_filter(array_map([$this, 'addDefaultTypeToColumn'], $columns)); |
|
|
|
|
607
|
|
|
} |
608
|
|
|
|
609
|
|
|
/** |
610
|
|
|
* Add a column at the end of to the CRUD object's "columns" array. |
611
|
|
|
* |
612
|
|
|
* @param [string or array] |
613
|
|
|
*/ |
614
|
|
|
public function addColumn($column) |
615
|
|
|
{ |
616
|
|
|
// make sure the column has a type |
617
|
|
|
$column_with_details = $this->addDefaultTypeToColumn($column); |
|
|
|
|
618
|
|
|
|
619
|
|
|
// make sure the column has a label |
620
|
|
|
$column_with_details = $this->addDefaultLabel($column); |
621
|
|
|
|
622
|
|
|
return array_filter($this->columns[] = $column_with_details); |
623
|
|
|
} |
624
|
|
|
|
625
|
|
|
/** |
626
|
|
|
* Add multiple columns at the end of the CRUD object's "columns" array. |
627
|
|
|
* |
628
|
|
|
* @param [array of columns] |
629
|
|
|
*/ |
630
|
|
|
public function addColumns($columns) |
631
|
|
|
{ |
632
|
|
|
if (count($columns)) { |
633
|
|
|
foreach ($columns as $key => $column) { |
634
|
|
|
$this->addColumn($column); |
635
|
|
|
} |
636
|
|
|
} |
637
|
|
|
} |
638
|
|
|
|
639
|
|
|
/** |
640
|
|
|
* Add the default column type to the given Column, inferring the type from the database column type. |
641
|
|
|
* |
642
|
|
|
* @param [column array] |
643
|
|
|
*/ |
644
|
|
|
public function addDefaultTypeToColumn($column) |
645
|
|
|
{ |
646
|
|
|
if (array_key_exists('name', (array)$column)) |
647
|
|
|
{ |
648
|
|
|
$default_type = $this->getFieldTypeFromDbColumnType($column['name']); |
649
|
|
|
return array_merge(['type' => $default_type], $column); |
650
|
|
|
} |
651
|
|
|
|
652
|
|
|
return false; |
653
|
|
|
} |
654
|
|
|
|
655
|
|
|
/** |
656
|
|
|
* If a field or column array is missing the "label" attribute, an ugly error would be show. |
657
|
|
|
* So we add the field Name as a label - it's better than nothing. |
658
|
|
|
* |
659
|
|
|
* @param [field or column] |
660
|
|
|
*/ |
661
|
|
|
public function addDefaultLabel($array) { |
662
|
|
|
if (!array_key_exists('label', (array)$array) && array_key_exists('name', (array)$array)) { |
663
|
|
|
$array = array_merge(['label' => ucfirst($this->makeLabel($array['name']))], $array); |
664
|
|
|
return $array; |
665
|
|
|
} |
666
|
|
|
|
667
|
|
|
return $array; |
668
|
|
|
} |
669
|
|
|
|
670
|
|
|
/** |
671
|
|
|
* Remove multiple columns from the CRUD object using their names. |
672
|
|
|
* |
673
|
|
|
* @param [column array] |
674
|
|
|
*/ |
675
|
|
|
public function removeColumns($columns) |
676
|
|
|
{ |
677
|
|
|
$this->columns = $this->remove('columns', $columns); |
|
|
|
|
678
|
|
|
} |
679
|
|
|
|
680
|
|
|
/** |
681
|
|
|
* Remove a column from the CRUD object using its name. |
682
|
|
|
* |
683
|
|
|
* @param [column array] |
684
|
|
|
*/ |
685
|
|
|
public function removeColumn($column) |
686
|
|
|
{ |
687
|
|
|
return $this->removeColumns([$column]); |
688
|
|
|
} |
689
|
|
|
|
690
|
|
|
/** |
691
|
|
|
* Change attributes for multiple columns. |
692
|
|
|
* |
693
|
|
|
* @param [columns arrays] |
694
|
|
|
* @param [attributes and values array] |
695
|
|
|
*/ |
696
|
|
|
public function setColumnsDetails($columns, $attributes) |
697
|
|
|
{ |
698
|
|
|
$this->sync('columns', $columns, $attributes); |
699
|
|
|
} |
700
|
|
|
|
701
|
|
|
/** |
702
|
|
|
* Change attributes for a certain column. |
703
|
|
|
* |
704
|
|
|
* @param [string] Column name. |
705
|
|
|
* @param [attributes and values array] |
706
|
|
|
*/ |
707
|
|
|
public function setColumnDetails($column, $attributes) |
708
|
|
|
{ |
709
|
|
|
$this->setColumnsDetails([$column], $attributes); |
710
|
|
|
} |
711
|
|
|
|
712
|
|
|
|
713
|
|
|
/** |
714
|
|
|
* Order the columns in a certain way. |
715
|
|
|
* |
716
|
|
|
* @param [string] Column name. |
717
|
|
|
* @param [attributes and values array] |
718
|
|
|
*/ |
719
|
|
|
public function setColumnOrder($columns) |
|
|
|
|
720
|
|
|
{ |
721
|
|
|
// TODO |
722
|
|
|
} |
723
|
|
|
|
724
|
|
|
// ALIAS of setColumnOrder($columns) |
725
|
|
|
public function setColumnsOrder($columns) { $this->setColumnOrder($columns); } |
726
|
|
|
|
727
|
|
|
|
728
|
|
|
// ------------ |
729
|
|
|
// FIELDS |
730
|
|
|
// ------------ |
731
|
|
|
|
732
|
|
|
/** |
733
|
|
|
* Add a field to the create/update form or both. |
734
|
|
|
* @param [string] $name Field name (the column name in the db in most cases) |
|
|
|
|
735
|
|
|
* @param [array] $options Field-type-specific information. |
|
|
|
|
736
|
|
|
* @param string $form The form to add the field to (create/update/both) |
737
|
|
|
*/ |
738
|
|
|
public function addField($field, $form='both') |
739
|
|
|
{ |
740
|
|
|
// if the field_defition_array array is a string, it means the programmer was lazy and has only passed the name |
741
|
|
|
// set some default values, so the field will still work |
742
|
|
|
if (is_string($field)) |
743
|
|
|
{ |
744
|
|
|
$complete_field_array['name'] = $field; |
|
|
|
|
745
|
|
|
} |
746
|
|
|
else |
747
|
|
|
{ |
748
|
|
|
$complete_field_array = $field; |
749
|
|
|
} |
750
|
|
|
|
751
|
|
|
// if the label is missing, we should set it |
752
|
|
|
if (!isset($complete_field_array['label'])) |
753
|
|
|
$complete_field_array['label'] = ucfirst($complete_field_array['name']); |
754
|
|
|
|
755
|
|
|
// if the field type is missing, we should set it |
756
|
|
|
if (!isset($complete_field_array['type'])) |
757
|
|
|
$complete_field_array['type'] = $this->getFieldTypeFromDbColumnType($complete_field_array['name']); |
758
|
|
|
|
759
|
|
|
// store the field information into the correct variable on the CRUD object |
760
|
|
|
switch (strtolower($form)) { |
761
|
|
|
case 'create': |
762
|
|
|
$this->create_fields[$complete_field_array['name']] = $complete_field_array; |
763
|
|
|
break; |
764
|
|
|
|
765
|
|
|
case 'update': |
766
|
|
|
$this->update_fields[$complete_field_array['name']] = $complete_field_array; |
767
|
|
|
break; |
768
|
|
|
|
769
|
|
|
default: |
770
|
|
|
$this->create_fields[$complete_field_array['name']] = $complete_field_array; |
771
|
|
|
$this->update_fields[$complete_field_array['name']] = $complete_field_array; |
772
|
|
|
break; |
773
|
|
|
} |
774
|
|
|
} |
775
|
|
|
|
776
|
|
|
/** |
777
|
|
|
* Remove a certain field from the create/update/both forms by its name. |
778
|
|
|
* @param string $name Field name (as defined with the addField() procedure) |
779
|
|
|
* @param string $form update/create/both |
780
|
|
|
*/ |
781
|
|
|
public function removeField($name, $form='both') |
782
|
|
|
{ |
783
|
|
|
switch (strtolower($form)) { |
784
|
|
|
case 'create': |
785
|
|
|
array_forget($this->create_fields, $name); |
786
|
|
|
break; |
787
|
|
|
|
788
|
|
|
case 'update': |
789
|
|
|
array_forget($this->update_fields, $name); |
790
|
|
|
break; |
791
|
|
|
|
792
|
|
|
default: |
793
|
|
|
array_forget($this->create_fields, $name); |
794
|
|
|
array_forget($this->update_fields, $name); |
795
|
|
|
break; |
796
|
|
|
} |
797
|
|
|
} |
798
|
|
|
|
799
|
|
|
/** |
800
|
|
|
* Remove many fields from the create/update/both forms by their name. |
801
|
|
|
* @param array $array_of_names A simple array of the names of the fields to be removed. |
802
|
|
|
* @param string $form update/create/both |
803
|
|
|
*/ |
804
|
|
|
public function removeFields($array_of_names, $form='both') |
805
|
|
|
{ |
806
|
|
|
if (!empty($array_of_names)) { |
807
|
|
|
foreach ($array_of_names as $name) { |
808
|
|
|
$this->removeField($name, $form); |
809
|
|
|
} |
810
|
|
|
} |
811
|
|
|
} |
812
|
|
|
|
813
|
|
|
// TODO: $this->crud->replaceField('name', 'update/create/both'); |
|
|
|
|
814
|
|
|
|
815
|
|
|
// TODO: $this->crud->setRequiredFields(['field_1', 'field_2'], 'update/create/both'); |
|
|
|
|
816
|
|
|
// TODO: $this->crud->setRequiredField('field_1', 'update/create/both'); |
|
|
|
|
817
|
|
|
// TODO: $this->crud->getRequiredFields(); |
|
|
|
|
818
|
|
|
|
819
|
|
|
// TODO: $this->crud->setFieldOrder(['field_1', 'field_2', 'field_3'], 'update/create/both'); |
|
|
|
|
820
|
|
|
|
821
|
|
|
|
822
|
|
|
/** |
823
|
|
|
* Order the fields in a certain way. |
824
|
|
|
* |
825
|
|
|
* @param [string] Column name. |
826
|
|
|
* @param [attributes and values array] |
827
|
|
|
*/ |
828
|
|
|
public function setFieldOrder($fields) |
|
|
|
|
829
|
|
|
{ |
830
|
|
|
// TODO |
831
|
|
|
} |
832
|
|
|
|
833
|
|
|
// ALIAS of setFieldOrder($fields) |
834
|
|
|
public function setFieldsOrder($fields) { $this->setFieldOrder($fields); } |
835
|
|
|
|
836
|
|
|
|
837
|
|
|
// ---------------- |
838
|
|
|
// ADVANCED QUERIES |
839
|
|
|
// ---------------- |
840
|
|
|
|
841
|
|
|
|
842
|
|
|
/** |
843
|
|
|
* Add another clause to the query (for ex, a WHERE clause). |
844
|
|
|
* |
845
|
|
|
* Examples: |
846
|
|
|
* // $this->crud->addClause('active'); |
847
|
|
|
* $this->crud->addClause('type', 'car'); |
848
|
|
|
* $this->crud->addClause('where', 'name', '==', 'car'); |
849
|
|
|
* $this->crud->addClause('whereName', 'car'); |
850
|
|
|
* $this->crud->addClause('whereHas', 'posts', function($query) { |
851
|
|
|
* $query->activePosts(); |
852
|
|
|
* }); |
853
|
|
|
* |
854
|
|
|
* @param [type] |
855
|
|
|
*/ |
856
|
|
|
public function addClause($function) |
857
|
|
|
{ |
858
|
|
|
return call_user_func_array([$this->query, $function], array_slice(func_get_args(), 1, 3)); |
859
|
|
|
} |
860
|
|
|
|
861
|
|
|
/** |
862
|
|
|
* Order the results of the query in a certain way. |
863
|
|
|
* |
864
|
|
|
* @param [type] |
865
|
|
|
* @param string |
866
|
|
|
* @return [type] |
|
|
|
|
867
|
|
|
*/ |
868
|
|
|
public function orderBy($field, $order = 'asc') |
869
|
|
|
{ |
870
|
|
|
return $this->query->orderBy($field, $order); |
871
|
|
|
} |
872
|
|
|
|
873
|
|
|
/** |
874
|
|
|
* Group the results of the query in a certain way. |
875
|
|
|
* |
876
|
|
|
* @param [type] |
877
|
|
|
* @return [type] |
|
|
|
|
878
|
|
|
*/ |
879
|
|
|
public function groupBy($field) |
880
|
|
|
{ |
881
|
|
|
return $this->query->groupBy($field); |
882
|
|
|
} |
883
|
|
|
|
884
|
|
|
/** |
885
|
|
|
* Limit the number of results in the query. |
886
|
|
|
* |
887
|
|
|
* @param [number] |
888
|
|
|
* @return [type] |
|
|
|
|
889
|
|
|
*/ |
890
|
|
|
public function limit($number) |
891
|
|
|
{ |
892
|
|
|
return $this->query->limit($number); |
893
|
|
|
} |
894
|
|
|
|
895
|
|
|
|
896
|
|
|
|
897
|
|
|
// ------------ |
898
|
|
|
// BUTTONS |
899
|
|
|
// ------------ |
900
|
|
|
|
901
|
|
|
// TODO: $this->crud->setButtons(); // default includes edit and delete, with their name, icon, permission, link and class (btn-default) |
|
|
|
|
902
|
|
|
// TODO: $this->crud->addButton(); |
|
|
|
|
903
|
|
|
// TODO: $this->crud->removeButton(); |
|
|
|
|
904
|
|
|
// TODO: $this->crud->replaceButton(); |
|
|
|
|
905
|
|
|
|
906
|
|
|
|
907
|
|
|
|
908
|
|
|
// ------------------------------------------------------ |
909
|
|
|
// AUTO-SET-FIELDS-AND-COLUMNS FUNCTIONALITY |
910
|
|
|
// ------------------------------------------------------ |
911
|
|
|
|
912
|
|
|
|
913
|
|
|
/** |
914
|
|
|
* For a simple CRUD Panel, there should be no need to add/define the fields. |
915
|
|
|
* The public columns in the database will be converted to be fields. |
916
|
|
|
* |
917
|
|
|
*/ |
918
|
|
|
public function setFromDb() |
919
|
|
|
{ |
920
|
|
|
$this->getDbColumnTypes(); |
921
|
|
|
|
922
|
|
|
array_map(function($field) { |
923
|
|
|
// $this->labels[$field] = $this->makeLabel($field); |
|
|
|
|
924
|
|
|
|
925
|
|
|
$new_field = [ |
926
|
|
|
'name' => $field, |
927
|
|
|
'label' => ucfirst($field), |
928
|
|
|
'value' => '', 'default' => $this->field_types[$field]['default'], |
929
|
|
|
'type' => $this->getFieldTypeFromDbColumnType($field), |
930
|
|
|
'values' => [], |
931
|
|
|
'attributes' => [] |
932
|
|
|
]; |
933
|
|
|
$this->create_fields[] = $new_field; |
934
|
|
|
$this->update_fields[] = $new_field; |
935
|
|
|
|
936
|
|
|
if (!in_array($field, $this->model->getHidden())) |
|
|
|
|
937
|
|
|
{ |
938
|
|
|
$this->columns[] = [ |
939
|
|
|
'name' => $field, |
940
|
|
|
'label' => ucfirst($field), |
941
|
|
|
'type' => $this->getFieldTypeFromDbColumnType($field) |
942
|
|
|
]; |
943
|
|
|
} |
944
|
|
|
|
945
|
|
|
}, $this->getDbColumnsNames()); |
946
|
|
|
} |
947
|
|
|
|
948
|
|
|
|
949
|
|
|
/** |
950
|
|
|
* Get all columns from the database for that table. |
951
|
|
|
* |
952
|
|
|
* @return [array] |
|
|
|
|
953
|
|
|
*/ |
954
|
|
|
public function getDbColumnTypes() |
955
|
|
|
{ |
956
|
|
|
foreach (\DB::select(\DB::raw('SHOW COLUMNS FROM '.$this->model->getTable())) as $column) |
|
|
|
|
957
|
|
|
{ |
958
|
|
|
$this->field_types[$column->Field] = ['type' => trim(preg_replace('/\(\d+\)(.*)/i', '', $column->Type)), 'default' => $column->Default]; |
959
|
|
|
} |
960
|
|
|
|
961
|
|
|
return $this->field_types; |
962
|
|
|
} |
963
|
|
|
|
964
|
|
|
|
965
|
|
|
/** |
966
|
|
|
* Intuit a field type, judging from the database column type. |
967
|
|
|
* |
968
|
|
|
* @param [string] Field name. |
969
|
|
|
* @return [string] Fielt type. |
|
|
|
|
970
|
|
|
*/ |
971
|
|
|
public function getFieldTypeFromDbColumnType($field) |
972
|
|
|
{ |
973
|
|
|
if (!array_key_exists($field, $this->field_types)) return 'text'; |
974
|
|
|
|
975
|
|
|
if ($field == 'password') return 'password'; |
976
|
|
|
|
977
|
|
|
if ($field == 'email') return 'email'; |
978
|
|
|
|
979
|
|
|
switch ($this->field_types[$field]['type']) |
980
|
|
|
{ |
981
|
|
|
case 'int': |
982
|
|
|
case 'smallint': |
983
|
|
|
case 'mediumint': |
984
|
|
|
case 'longint': |
985
|
|
|
return 'number'; |
986
|
|
|
break; |
|
|
|
|
987
|
|
|
|
988
|
|
|
case 'string': |
989
|
|
|
case 'varchar': |
990
|
|
|
case 'set': |
991
|
|
|
return 'text'; |
992
|
|
|
break; |
|
|
|
|
993
|
|
|
|
994
|
|
|
// case 'enum': |
995
|
|
|
// return 'enum'; |
996
|
|
|
// break; |
997
|
|
|
|
998
|
|
|
case 'tinyint': |
999
|
|
|
return 'active'; |
1000
|
|
|
break; |
|
|
|
|
1001
|
|
|
|
1002
|
|
|
case 'text': |
1003
|
|
|
case 'mediumtext': |
1004
|
|
|
case 'longtext': |
1005
|
|
|
return 'textarea'; |
1006
|
|
|
break; |
|
|
|
|
1007
|
|
|
|
1008
|
|
|
case 'date': |
1009
|
|
|
return 'date'; |
1010
|
|
|
break; |
|
|
|
|
1011
|
|
|
|
1012
|
|
|
case 'datetime': |
1013
|
|
|
case 'timestamp': |
1014
|
|
|
return 'datetime'; |
1015
|
|
|
break; |
|
|
|
|
1016
|
|
|
case 'time': |
1017
|
|
|
return 'time'; |
1018
|
|
|
break; |
|
|
|
|
1019
|
|
|
|
1020
|
|
|
default: |
1021
|
|
|
return 'text'; |
1022
|
|
|
break; |
|
|
|
|
1023
|
|
|
} |
1024
|
|
|
} |
1025
|
|
|
|
1026
|
|
|
|
1027
|
|
|
/** |
1028
|
|
|
* Turn a database column name or PHP variable into a pretty label to be shown to the user. |
1029
|
|
|
* |
1030
|
|
|
* @param [string] |
1031
|
|
|
* @return [string] |
|
|
|
|
1032
|
|
|
*/ |
1033
|
|
|
public function makeLabel($value) |
1034
|
|
|
{ |
1035
|
|
|
return trim(preg_replace('/(id|at|\[\])$/i', '', ucfirst(str_replace('_', ' ', $value)))); |
1036
|
|
|
} |
1037
|
|
|
|
1038
|
|
|
|
1039
|
|
|
/** |
1040
|
|
|
* Get the database column names, in order to figure out what fields/columns to show in the auto-fields-and-columns functionality. |
1041
|
|
|
* |
1042
|
|
|
* @return [array] Database column names as an array. |
|
|
|
|
1043
|
|
|
*/ |
1044
|
|
|
public function getDbColumnsNames() |
1045
|
|
|
{ |
1046
|
|
|
// Automatically-set columns should be both in the database, and in the $fillable variable on the Eloquent Model |
1047
|
|
|
$columns = \Schema::getColumnListing($this->model->getTable()); |
|
|
|
|
1048
|
|
|
$fillable = $this->model->getFillable(); |
|
|
|
|
1049
|
|
|
|
1050
|
|
|
if (!empty($fillable)) $columns = array_intersect($columns, $fillable); |
1051
|
|
|
|
1052
|
|
|
// but not updated_at, deleted_at |
1053
|
|
|
return array_values(array_diff($columns, [$this->model->getKeyName(), 'updated_at', 'deleted_at'])); |
|
|
|
|
1054
|
|
|
} |
1055
|
|
|
|
1056
|
|
|
|
1057
|
|
|
|
1058
|
|
|
|
1059
|
|
|
|
1060
|
|
|
|
1061
|
|
|
|
1062
|
|
|
// ----------------- |
1063
|
|
|
// Commodity methods |
1064
|
|
|
// ----------------- |
1065
|
|
|
|
1066
|
|
|
/** |
1067
|
|
|
* Refactor the request array to something that can be passed to the model's create or update function. |
1068
|
|
|
* The resulting array will only include the fields that are stored in the database and their values, |
1069
|
|
|
* plus the '_token' and 'redirect_after_save' variables. |
1070
|
|
|
* |
1071
|
|
|
* @param Request $request - everything that was sent from the form, usually \Request::all() |
1072
|
|
|
* @param String $form - create/update - to determine what fields should be compacted |
1073
|
|
|
* @return array |
1074
|
|
|
*/ |
1075
|
|
|
public function compactFakeFields($request, $form = 'create') |
1076
|
|
|
{ |
1077
|
|
|
$fake_field_columns_to_encode = []; |
1078
|
|
|
|
1079
|
|
|
// get the right fields according to the form type (create/update) |
1080
|
|
View Code Duplication |
switch (strtolower($form)) { |
|
|
|
|
1081
|
|
|
case 'update': |
1082
|
|
|
$fields = $this->update_fields; |
1083
|
|
|
break; |
1084
|
|
|
|
1085
|
|
|
default: |
1086
|
|
|
$fields = $this->create_fields; |
1087
|
|
|
break; |
1088
|
|
|
} |
1089
|
|
|
|
1090
|
|
|
// go through each defined field |
1091
|
|
|
foreach ($fields as $k => $field) { |
1092
|
|
|
// if it's a fake field |
1093
|
|
|
if (isset($fields[$k]['fake']) && $fields[$k]['fake'] == true) { |
1094
|
|
|
// add it to the request in its appropriate variable - the one defined, if defined |
1095
|
|
|
if (isset($fields[$k]['store_in'])) { |
1096
|
|
|
$request[$fields[$k]['store_in']][$fields[$k]['name']] = $request[$fields[$k]['name']]; |
1097
|
|
|
|
1098
|
|
|
$remove_fake_field = array_pull($request, $fields[$k]['name']); |
|
|
|
|
1099
|
|
View Code Duplication |
if (!in_array($fields[$k]['store_in'], $fake_field_columns_to_encode, true)) { |
|
|
|
|
1100
|
|
|
array_push($fake_field_columns_to_encode, $fields[$k]['store_in']); |
1101
|
|
|
} |
1102
|
|
|
} else //otherwise in the one defined in the $crud variable |
1103
|
|
|
{ |
1104
|
|
|
$request['extras'][$fields[$k]['name']] = $request[$fields[$k]['name']]; |
1105
|
|
|
|
1106
|
|
|
$remove_fake_field = array_pull($request, $fields[$k]['name']); |
|
|
|
|
1107
|
|
|
if (!in_array('extras', $fake_field_columns_to_encode, true)) { |
1108
|
|
|
array_push($fake_field_columns_to_encode, 'extras'); |
1109
|
|
|
} |
1110
|
|
|
} |
1111
|
|
|
} |
1112
|
|
|
} |
1113
|
|
|
|
1114
|
|
|
// json_encode all fake_value columns in the database, so they can be properly stored and interpreted |
1115
|
|
|
if (count($fake_field_columns_to_encode)) { |
1116
|
|
|
foreach ($fake_field_columns_to_encode as $key => $value) { |
1117
|
|
|
$request[$value] = json_encode($request[$value]); |
1118
|
|
|
} |
1119
|
|
|
} |
1120
|
|
|
|
1121
|
|
|
// if there are no fake fields defined, this will just return the original Request in full |
1122
|
|
|
// since no modifications or additions have been made to $request |
1123
|
|
|
return $request; |
1124
|
|
|
} |
1125
|
|
|
|
1126
|
|
|
|
1127
|
|
|
/** |
1128
|
|
|
* Returns an array of database columns names, that are used to store fake values. |
1129
|
|
|
* Returns ['extras'] if no columns have been found. |
1130
|
|
|
* |
1131
|
|
|
*/ |
1132
|
|
|
public function getFakeColumnsAsArray($form = 'create') |
1133
|
|
|
{ |
1134
|
|
|
$fake_field_columns_to_encode = []; |
1135
|
|
|
|
1136
|
|
|
// get the right fields according to the form type (create/update) |
1137
|
|
View Code Duplication |
switch (strtolower($form)) { |
|
|
|
|
1138
|
|
|
case 'update': |
1139
|
|
|
$fields = $this->update_fields; |
1140
|
|
|
break; |
1141
|
|
|
|
1142
|
|
|
default: |
1143
|
|
|
$fields = $this->create_fields; |
1144
|
|
|
break; |
1145
|
|
|
} |
1146
|
|
|
|
1147
|
|
|
|
1148
|
|
|
foreach ($fields as $k => $field) { |
1149
|
|
|
// if it's a fake field |
1150
|
|
|
if (isset($fields[$k]['fake']) && $fields[$k]['fake'] == true) { |
1151
|
|
|
// add it to the request in its appropriate variable - the one defined, if defined |
1152
|
|
|
if (isset($fields[$k]['store_in'])) { |
1153
|
|
View Code Duplication |
if (!in_array($fields[$k]['store_in'], $fake_field_columns_to_encode, true)) { |
|
|
|
|
1154
|
|
|
array_push($fake_field_columns_to_encode, $fields[$k]['store_in']); |
1155
|
|
|
} |
1156
|
|
|
} else //otherwise in the one defined in the $crud variable |
1157
|
|
|
{ |
1158
|
|
|
if (!in_array('extras', $fake_field_columns_to_encode, true)) { |
1159
|
|
|
array_push($fake_field_columns_to_encode, 'extras'); |
1160
|
|
|
} |
1161
|
|
|
} |
1162
|
|
|
} |
1163
|
|
|
} |
1164
|
|
|
|
1165
|
|
|
if (!count($fake_field_columns_to_encode)) { |
1166
|
|
|
return ['extras']; |
1167
|
|
|
} |
1168
|
|
|
|
1169
|
|
|
return $fake_field_columns_to_encode; |
1170
|
|
|
} |
1171
|
|
|
|
1172
|
|
|
|
1173
|
|
|
|
1174
|
|
|
|
1175
|
|
|
|
1176
|
|
|
|
1177
|
|
|
|
1178
|
|
|
|
1179
|
|
|
// ---------------------------------- |
1180
|
|
|
// Miscellaneous functions or methods |
1181
|
|
|
// ---------------------------------- |
1182
|
|
|
|
1183
|
|
|
|
1184
|
|
|
|
1185
|
|
|
|
1186
|
|
|
|
1187
|
|
|
|
1188
|
|
|
|
1189
|
|
|
|
1190
|
|
|
|
1191
|
|
|
|
1192
|
|
|
|
1193
|
|
|
|
1194
|
|
|
|
1195
|
|
|
// ------------ |
1196
|
|
|
// TONE FUNCTIONS - UNDOCUMENTED, UNTESTED, SOME MAY BE USED IN THIS FILE |
1197
|
|
|
// ------------ |
1198
|
|
|
// |
1199
|
|
|
// TODO: |
1200
|
|
|
// - figure out if they are really needed |
1201
|
|
|
// - comments inside the function to explain how they work |
1202
|
|
|
// - write docblock for them |
1203
|
|
|
// - place in the correct section above (CREATE, READ, UPDATE, DELETE, ACCESS, MANIPULATION) |
1204
|
|
|
|
1205
|
|
|
|
1206
|
|
|
|
1207
|
|
|
public function addButton($button) |
1208
|
|
|
{ |
1209
|
|
|
array_unshift($this->buttons, $button); |
1210
|
|
|
} |
1211
|
|
|
|
1212
|
|
|
public function buttons() |
1213
|
|
|
{ |
1214
|
|
|
return $this->buttons; |
1215
|
|
|
} |
1216
|
|
|
|
1217
|
|
|
public function addCustomButton($button) |
1218
|
|
|
{ |
1219
|
|
|
array_unshift($this->custom_buttons, $button); |
1220
|
|
|
} |
1221
|
|
|
|
1222
|
|
|
public function customButtons() |
1223
|
|
|
{ |
1224
|
|
|
return $this->custom_buttons; |
1225
|
|
|
} |
1226
|
|
|
|
1227
|
|
|
public function showButtons() |
1228
|
|
|
{ |
1229
|
|
|
return !empty($this->buttons) && !(count($this->buttons) == 1 && array_key_exists('add', $this->buttons)); |
1230
|
|
|
} |
1231
|
|
|
|
1232
|
|
|
public function initButtons() |
1233
|
|
|
{ |
1234
|
|
|
$this->buttons = [ |
1235
|
|
|
'add' => ['route' => "{$this->route}/create", 'label' => trans('crud::crud.buttons.add'), 'class' => '', 'hide' => [], 'icon' => 'fa-plus-circle', 'extra' => []], |
1236
|
|
|
'view' => ['route' => "{$this->route}/%d", 'label' => trans('crud::crud.buttons.view'), 'class' => '', 'hide' => [], 'icon' => 'fa-eye', 'extra' => []], |
1237
|
|
|
'edit' => ['route' => "{$this->route}/%d/edit", 'label' => trans('crud::crud.buttons.edit'), 'class' => '', 'hide' => [], 'icon' => 'fa-edit', 'extra' => []], |
1238
|
|
|
'delete' => ['route' => "{$this->route}/%d", 'label' => trans('crud::crud.buttons.delete'), 'class' => '', 'hide' => [], 'icon' => 'fa-trash', 'extra' => ['data-confirm' => trans('crud::crud.confirm.delete'), 'data-type' => 'delete']], |
1239
|
|
|
]; |
1240
|
|
|
} |
1241
|
|
|
|
1242
|
|
|
public function removeButtons($buttons) |
1243
|
|
|
{ |
1244
|
|
|
foreach ($buttons as $button) |
1245
|
|
|
{ |
1246
|
|
|
unset($this->buttons[$button]); |
1247
|
|
|
} |
1248
|
|
|
|
1249
|
|
|
return $this->buttons; |
1250
|
|
|
} |
1251
|
|
|
|
1252
|
|
|
|
1253
|
|
|
|
1254
|
|
|
|
1255
|
|
|
|
1256
|
|
|
|
1257
|
|
|
|
1258
|
|
|
|
1259
|
|
|
public function getColumns() |
1260
|
|
|
{ |
1261
|
|
|
return $this->sort('columns'); |
1262
|
|
|
} |
1263
|
|
|
|
1264
|
|
|
public function orderColumns($order) |
1265
|
|
|
{ |
1266
|
|
|
$this->setSort('columns', (array)$order); |
1267
|
|
|
} |
1268
|
|
|
|
1269
|
|
|
|
1270
|
|
|
|
1271
|
|
|
|
1272
|
|
|
|
1273
|
|
|
|
1274
|
|
|
public function setFields($fields) |
1275
|
|
|
{ |
1276
|
|
|
$this->addMultiple('fields', $fields); |
1277
|
|
|
} |
1278
|
|
|
|
1279
|
|
|
// [name, label, value, default, type, required, hint, values[id => value], attributes[class, id, data-, for editor: data-config="basic|medium|full"], callback => [$this, 'methodName'], callback_create => [$this, 'methodName'], callback_edit => [$this, 'methodName'], callback_view => [$this, 'methodName']] |
|
|
|
|
1280
|
|
|
// public function addField($field) |
|
|
|
|
1281
|
|
|
// { |
1282
|
|
|
// return $this->add('fields', $field); |
|
|
|
|
1283
|
|
|
// } |
1284
|
|
|
|
1285
|
|
|
public function updateFields($fields, $attributes) |
1286
|
|
|
{ |
1287
|
|
|
$this->sync('fields', $fields, $attributes); |
1288
|
|
|
} |
1289
|
|
|
|
1290
|
|
|
// public function removeFields($fields) |
|
|
|
|
1291
|
|
|
// { |
1292
|
|
|
// $this->fields = $this->remove('fields', $fields); |
|
|
|
|
1293
|
|
|
// $this->removeColumns($fields); |
|
|
|
|
1294
|
|
|
// } |
1295
|
|
|
|
1296
|
|
|
public function setCreateFields($fields) |
1297
|
|
|
{ |
1298
|
|
|
$this->addMultiple('create_fields', $fields); |
1299
|
|
|
} |
1300
|
|
|
|
1301
|
|
|
public function addCreateField($field) |
1302
|
|
|
{ |
1303
|
|
|
return $this->add('create_fields', $field); |
|
|
|
|
1304
|
|
|
} |
1305
|
|
|
|
1306
|
|
|
public function setUpdateFields($fields) |
1307
|
|
|
{ |
1308
|
|
|
$this->addMultiple('update_fields', $fields); |
1309
|
|
|
} |
1310
|
|
|
|
1311
|
|
|
public function addUpdateField($field) |
1312
|
|
|
{ |
1313
|
|
|
return $this->add('update_fields', $field); |
|
|
|
|
1314
|
|
|
} |
1315
|
|
|
|
1316
|
|
|
public function fields() |
1317
|
|
|
{ |
1318
|
|
|
if (!$this->entry && !empty($this->create_fields)) |
1319
|
|
|
{ |
1320
|
|
|
$this->syncRelations('create_fields'); |
1321
|
|
|
|
1322
|
|
|
return $this->create_fields; |
1323
|
|
|
} |
1324
|
|
|
|
1325
|
|
|
if ($this->entry && !empty($this->update_fields)) |
1326
|
|
|
{ |
1327
|
|
|
$this->syncRelations('update_fields'); |
1328
|
|
|
$this->addFieldsValue(); |
1329
|
|
|
|
1330
|
|
|
return $this->update_fields; |
1331
|
|
|
} |
1332
|
|
|
|
1333
|
|
|
$this->syncRelations('fields'); |
1334
|
|
|
$this->addFieldsValue(); |
1335
|
|
|
|
1336
|
|
|
return $this->sort('fields'); |
1337
|
|
|
} |
1338
|
|
|
|
1339
|
|
|
public function orderFields($order) |
1340
|
|
|
{ |
1341
|
|
|
$this->setSort('fields', (array)$order); |
1342
|
|
|
} |
1343
|
|
|
|
1344
|
|
|
|
1345
|
|
|
// public function syncField($field) |
|
|
|
|
1346
|
|
|
// { |
1347
|
|
|
// if (array_key_exists('name', (array)$field)) |
|
|
|
|
1348
|
|
|
// return array_merge(['type' => $this->getFieldTypeFromDbColumnType($field['name']), 'value' => '', 'default' => null, 'values' => [], 'attributes' => []], $field); |
|
|
|
|
1349
|
|
|
|
1350
|
|
|
// return false; |
1351
|
|
|
// } |
1352
|
|
|
|
1353
|
|
|
|
1354
|
|
|
|
1355
|
|
|
|
1356
|
|
|
|
1357
|
|
|
// iti pune valorile pe field-uri la EDIT |
1358
|
|
|
public function addFieldsValue() |
1359
|
|
|
{ |
1360
|
|
|
if ($this->entry) |
1361
|
|
|
{ |
1362
|
|
|
$fields = !empty($this->update_fields) ? 'update_fields' : 'fields'; |
1363
|
|
|
|
1364
|
|
|
foreach ($this->{$fields} as $key => $field) |
1365
|
|
|
{ |
1366
|
|
|
if (array_key_exists($field['name'], $this->relations) && $this->relations[$field['name']]['pivot']) $this->{$fields}[$key]['value'] = $this->entry->{$this->relations[$field['name']]['name']}()->lists($this->relations[$field['name']]['model']->getKeyName())->toArray(); |
1367
|
|
|
else $this->{$fields}[$key]['value'] = $this->entry->{$field['name']}; |
1368
|
|
|
} |
1369
|
|
|
} |
1370
|
|
|
} |
1371
|
|
|
|
1372
|
|
|
// public function add($entity, $field) |
|
|
|
|
1373
|
|
|
// { |
1374
|
|
|
// return array_filter($this->{$entity}[] = $this->syncField($field)); |
|
|
|
|
1375
|
|
|
// } |
1376
|
|
|
|
1377
|
|
|
public function addMultiple($entity, $field) |
|
|
|
|
1378
|
|
|
{ |
1379
|
|
|
$this->{$entity} = array_filter(array_map([$this, 'syncField'], $fields)); |
|
|
|
|
1380
|
|
|
} |
1381
|
|
|
|
1382
|
|
|
public function sync($type, $fields, $attributes) |
1383
|
|
|
{ |
1384
|
|
|
if (!empty($this->{$type})) |
1385
|
|
|
{ |
1386
|
|
|
$this->{$type} = array_map(function($field) use ($fields, $attributes) { |
1387
|
|
|
if (in_array($field['name'], (array)$fields)) $field = array_merge($field, $attributes); |
1388
|
|
|
|
1389
|
|
|
return $field; |
1390
|
|
|
}, $this->{$type}); |
1391
|
|
|
} |
1392
|
|
|
} |
1393
|
|
|
|
1394
|
|
|
|
1395
|
|
|
|
1396
|
|
|
// public function remove($entity, $fields) |
|
|
|
|
1397
|
|
|
// { |
1398
|
|
|
// return array_values(array_filter($this->{$entity}, function($field) use ($fields) { return !in_array($field['name'], (array)$fields);})); |
|
|
|
|
1399
|
|
|
// } |
1400
|
|
|
|
1401
|
|
|
public function setSort($items, $order) |
1402
|
|
|
{ |
1403
|
|
|
$this->sort[$items] = $order; |
1404
|
|
|
} |
1405
|
|
|
|
1406
|
|
|
public function sort($items) |
1407
|
|
|
{ |
1408
|
|
|
if (array_key_exists($items, $this->sort)) |
1409
|
|
|
{ |
1410
|
|
|
$elements = []; |
1411
|
|
|
|
1412
|
|
|
foreach ($this->sort[$items] as $item) |
1413
|
|
|
{ |
1414
|
|
|
if (is_numeric($key = array_search($item, array_column($this->{$items}, 'name')))) $elements[] = $this->{$items}[$key]; |
1415
|
|
|
} |
1416
|
|
|
|
1417
|
|
|
return $this->{$items} = array_merge($elements, array_filter($this->{$items}, function($item) use($items) {return !in_array($item['name'], $this->sort[$items]);})); |
1418
|
|
|
} |
1419
|
|
|
|
1420
|
|
|
return $this->{$items}; |
1421
|
|
|
} |
1422
|
|
|
|
1423
|
|
|
|
1424
|
|
|
|
1425
|
|
|
|
1426
|
|
|
|
1427
|
|
|
// cred ca ia valorile din tabela de legatura ca sa ti le afiseze in select |
1428
|
|
|
public function getRelationValues($model, $field, $where = [], $order = []) |
1429
|
|
|
{ |
1430
|
|
|
$order = (array)$order; |
1431
|
|
|
$values = $model->select('*'); |
1432
|
|
|
|
1433
|
|
|
if (!empty($where)) call_user_func_array([$values, $where[0]], array_slice($where, 1)); |
1434
|
|
|
|
1435
|
|
|
if (!empty($order)) call_user_func_array([$values, 'orderBy'], $order); |
1436
|
|
|
|
1437
|
|
|
return $values->get()->lists($field, $model->getKeyName())->toArray(); |
1438
|
|
|
} |
1439
|
|
|
|
1440
|
|
|
// face un fel de merge intre ce ii dai si ce e in CRUD |
1441
|
|
|
public function syncRelations($entity) |
1442
|
|
|
{ |
1443
|
|
|
foreach ($this->relations as $field => $relation) { |
1444
|
|
|
if ($relation['pivot']) $this->add($entity, ['name' => $field, 'type' => 'multiselect', 'value' => [], 'values' => $this->relations[$field]['values']]); |
|
|
|
|
1445
|
|
|
else $this->sync($entity, $field, ['type' => 'select', 'values' => $this->relations[$field]['values']]); |
1446
|
|
|
} |
1447
|
|
|
} |
1448
|
|
|
|
1449
|
|
|
|
1450
|
|
|
|
1451
|
|
|
} |
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.
The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.
This check looks for comments that seem to be mostly valid code and reports them.