Skip to content

Commit

Permalink
Merge pull request #5677 from Laravel-Backpack/allow-customization-of…
Browse files Browse the repository at this point in the history
…-reorder-column-names

Allow customization of reorder column names
  • Loading branch information
pxpm authored Sep 24, 2024
2 parents 3714d7d + b2da3a5 commit b58f971
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 22 deletions.
6 changes: 6 additions & 0 deletions src/app/Http/Controllers/Operations/ReorderOperation.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,12 @@ protected function setupReorderDefaults()

$this->crud->operation('reorder', function () {
$this->crud->loadDefaultOperationSettingsFromConfig();
$this->crud->setOperationSetting('reorderColumnNames', [
'parent_id' => 'parent_id',
'lft' => 'lft',
'rgt' => 'rgt',
'depth' => 'depth',
]);
});

$this->crud->operation('list', function () {
Expand Down
33 changes: 25 additions & 8 deletions src/app/Library/CrudPanel/Traits/Reorder.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ public function updateTreeOrder($request)
{
$primaryKey = $this->model->getKeyName();

$columns = $this->getOperationSetting('reorderColumnNames');

// we use the upsert method that should update the values of the matching ids.
// it has the drawback of creating new entries when the id is not found
// for that reason we get a list of all the ids and filter the ones
Expand All @@ -28,14 +30,29 @@ public function updateTreeOrder($request)
// filter the items that are not in the database and map the request
$reorderItems = collect($request)->filter(function ($item) use ($itemKeys) {
return $item['item_id'] !== '' && $item['item_id'] !== null && $itemKeys->contains($item['item_id']);
})->map(function ($item) use ($primaryKey) {
})->map(function ($item) use ($primaryKey, $columns) {
$item[$primaryKey] = $item['item_id'];
$item['parent_id'] = empty($item['parent_id']) ? null : $item['parent_id'];
$item['depth'] = empty($item['depth']) ? null : (int) $item['depth'];
$item['lft'] = empty($item['left']) ? null : (int) $item['left'];
$item['rgt'] = empty($item['right']) ? null : (int) $item['right'];
$item[$columns['parent_id']] = empty($item['parent_id']) ? null : $item['parent_id'];
$item[$columns['depth']] = empty($item['depth']) ? null : (int) $item['depth'];
$item[$columns['lft']] = empty($item['left']) ? null : (int) $item['left'];
$item[$columns['rgt']] = empty($item['right']) ? null : (int) $item['right'];

// unset mapped items properties.
unset($item['item_id'], $item['left'], $item['right']);
if ($columns['parent_id'] !== 'parent_id') {
unset($item['parent_id']);
}
if ($columns['depth'] !== 'depth') {
unset($item['depth']);
}
if ($columns['lft'] !== 'left') {
unset($item['left']);
}
if ($columns['rgt'] !== 'right') {
unset($item['right']);
}

// unset the item_id property
unset($item['item_id']);

return $item;
})->toArray();
Expand All @@ -47,13 +64,13 @@ public function updateTreeOrder($request)
});

// wrap the queries in a transaction to avoid partial updates
DB::connection($this->model->getConnectionName())->transaction(function () use ($reorderItems, $primaryKey, $itemKeys) {
DB::connection($this->model->getConnectionName())->transaction(function () use ($reorderItems, $primaryKey, $itemKeys, $columns) {
// create a string of ?,?,?,? to use as bind placeholders for item keys
$reorderItemsBindString = implode(',', array_fill(0, count($reorderItems), '?'));

// each of this properties will be updated using a single query with a CASE statement
// this ensures that only 4 queries are run, no matter how many items are reordered
foreach (['parent_id', 'depth', 'lft', 'rgt'] as $column) {
foreach (array_values($columns) as $column) {
$query = '';
$bindings = [];
$query .= "UPDATE {$this->model->getTable()} SET {$column} = CASE ";
Expand Down
33 changes: 19 additions & 14 deletions src/resources/views/crud/reorder.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
trans('backpack::crud.reorder') => false,
];
$columns = $crud->getOperationSetting('reorderColumnNames');
// if breadcrumbs aren't defined in the CrudController, use the default breadcrumbs
$breadcrumbs = $breadcrumbs ?? $defaultBreadcrumbs;
@endphp
Expand All @@ -24,9 +26,11 @@
@endsection

@section('content')
<?php
function tree_element($entry, $key, $all_entries, $crud)
{
<?php
if(!function_exists('tree_element')) {
function tree_element($entry, $key, $all_entries, $crud) {
$columns = $crud->getOperationSetting('reorderColumnNames');
if (! isset($entry->tree_element_shown)) {
// mark the element as shown
$all_entries[$key]->tree_element_shown = true;
Expand All @@ -39,12 +43,12 @@ function tree_element($entry, $key, $all_entries, $crud)
// see if this element has any children
$children = [];
foreach ($all_entries as $key => $subentry) {
if ($subentry->parent_id == $entry->getKey()) {
if ($subentry->{$columns['parent_id']} == $entry->getKey()) {
$children[] = $subentry;
}
}
$children = collect($children)->sortBy('lft');
$children = collect($children)->sortBy($columns['lft']);
// if it does have children, show them
if (count($children)) {
Expand All @@ -59,6 +63,7 @@ function tree_element($entry, $key, $all_entries, $crud)
return $entry;
}
}
?>

Expand All @@ -68,15 +73,15 @@ function tree_element($entry, $key, $all_entries, $crud)
<p>{{ trans('backpack::crud.reorder_text') }}</p>

<ol class="sortable mt-0 mb-0">
<?php
$all_entries = collect($entries->all())->sortBy('lft')->keyBy($crud->getModel()->getKeyName());
$root_entries = $all_entries->filter(function ($item) {
return $item->parent_id == 0;
});
foreach ($root_entries as $key => $entry) {
$root_entries[$key] = tree_element($entry, $key, $all_entries, $crud);
}
?>
<?php
$all_entries = collect($entries->all())->sortBy($columns['lft'])->keyBy($crud->getModel()->getKeyName());
$root_entries = $all_entries->filter(function ($item) use ($columns) {
return $item->{$columns['parent_id']} == 0;
});
foreach ($root_entries as $key => $entry) {
$root_entries[$key] = tree_element($entry, $key, $all_entries, $crud);
}
?>
</ol>

</div>{{-- /.card --}}
Expand Down
7 changes: 7 additions & 0 deletions tests/Unit/CrudPanel/CrudPanelReorderOperationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,13 @@ public function testSaveReorderTree()
$this->createReorderItems();
$this->crudPanel->setModel(Reorder::class);

$this->crudPanel->setOperationSetting('reorderColumnNames', [
'parent_id' => 'parent_id',
'depth' => 'depth',
'lft' => 'lft',
'rgt' => 'rgt',
]);

$this->crudPanel->updateTreeOrder(
[
[
Expand Down

0 comments on commit b58f971

Please sign in to comment.