adding counter on menu

This commit is contained in:
Geriano
2022-08-29 14:27:07 +07:00
parent 8a8bc4361d
commit b35b61dc14
9 changed files with 296 additions and 19 deletions

View File

@@ -3,13 +3,18 @@
namespace App\Http\Controllers\Superuser;
use App\Http\Controllers\Controller;
use App\Menus\Menu as MenusMenu;
use App\Models\Menu;
use App\Models\Permission;
use Illuminate\Http\Request;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Route;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Str;
use Inertia\Inertia;
use RecursiveDirectoryIterator;
use RecursiveIteratorIterator;
use SplFileInfo;
use Throwable;
@@ -29,13 +34,55 @@ class MenuController extends Controller
'routes' => array_values($routes),
'icons' => $this->icons(),
'menus' => $this->get(),
'handlers' => $this->handlers(),
]);
}
/**
* @return array
*/
public function icons()
private function handlers() : array
{
$handlers = [];
$iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator(
app_path('Menus')
));
foreach ($iterator as $splFileInfo) {
/**
* @var \SplFileInfo $splFileInfo
*/
if ($splFileInfo->isDir()) {
continue;
}
if ($splFileInfo->getFilename() === 'Menu.php') {
continue;
}
$class = str_replace(dirname(app_path()), '', $splFileInfo->getRealPath());
$class = mb_substr(trim($class, DIRECTORY_SEPARATOR), 0, -4);
$class = str_replace(DIRECTORY_SEPARATOR, '\\', ucfirst($class));
if (!class_exists($class) && !is_subclass_of($class, MenusMenu::class)) {
continue;
}
$name = str_replace(['App\\Menus\\', '\\'], ['', ' '], $class);
$handlers[] = [
'class' => $class,
'name' => ucwords(Str::snake($name, ' ')),
];
}
return $handlers;
}
/**
* @return array
*/
public function icons() : array
{
return array_map(
callback: fn (string $name) => mb_substr(
@@ -78,14 +125,24 @@ class MenuController extends Controller
*/
public function store(Request $request)
{
$post = $request->validate([
Validator::make($request->all(), [
'name' => 'required|string',
'icon' => 'nullable|string',
'route_or_url' => 'nullable|string',
'counter_handler' => 'nullable|string',
'actives.*' => 'nullable|string',
'permissions.*' => 'nullable|integer|exists:permissions,id',
]);
])->after(function ($validator) use ($request) {
if (($class = $request->counter_handler) && !class_exists($class)) {
$validator->errors()->add('counter_handler', __(
'class :name doesn\'t exists', [
'name' => $class,
],
));
}
})->validate();
$post = $request->all();
$post['position'] = Menu::whereNull('parent_id')->count() + 1;
if ($menu = Menu::create($post)) {
@@ -112,13 +169,22 @@ class MenuController extends Controller
*/
public function update(Request $request, Menu $menu)
{
$request->validate([
Validator::make($request->all(), [
'name' => 'required|string',
'icon' => 'nullable|string',
'route_or_url' => 'nullable|string',
'counter_handler' => 'nullable|string',
'actives.*' => 'nullable|string',
'permissions.*' => 'nullable|integer|exists:permissions,id',
]);
])->after(function ($validator) use ($request) {
if (($class = $request->counter_handler) && !class_exists($class)) {
$validator->errors()->add('counter_handler', __(
'class :name doesn\'t exists', [
'name' => $class,
],
));
}
})->validate();
if ($menu->update($request->all())) {
$menu->permissions()->sync($request->input('permissions', []));
@@ -251,4 +317,27 @@ class MenuController extends Controller
return $new;
}, $menus);
}
/**
* @param \App\Models\Menu $menu
* @return \Illuminate\Http\Response
*/
public function counter(Menu $menu)
{
$menu = Menu::with('childs')->find($menu->id);
return [
'count' => $this->counters(0, $menu),
];
}
/**
* @param int $total
* @param \App\Models\Menu $menu
* @return int
*/
public function counters(int $total, Menu $menu)
{
return $total + $menu->counter?->count() + $menu->childs->reduce([$this, 'counters'], 0);
}
}

13
app/Menus/Menu.php Normal file
View File

@@ -0,0 +1,13 @@
<?php
namespace App\Menus;
use Countable;
abstract class Menu implements Countable
{
/**
* @return int
*/
abstract public function count() : int;
}

16
app/Menus/UserMenu.php Normal file
View File

@@ -0,0 +1,16 @@
<?php
namespace App\Menus;
use App\Models\User;
class UserMenu extends Menu
{
/**
* @inheritdoc
*/
public function count() : int
{
return User::count();
}
}

View File

@@ -21,6 +21,7 @@ class Menu extends Model
'name',
'icon',
'route_or_url',
'counter_handler',
'position',
'enable',
'actives',
@@ -34,6 +35,13 @@ class Menu extends Model
'permissions',
];
/**
* @var string[]
*/
protected $appends = [
'counter',
];
/**
* @return \Illuminate\Database\Eloquent\Relations\HasOne
*/
@@ -88,4 +96,14 @@ class Menu extends Model
set: fn ($value) => is_array($value) || $value instanceof JsonSerializable || $value instanceof stdClass ? json_encode($value) : $value,
);
}
/**
* @return \Illuminate\Database\Eloquent\Casts\Attribute
*/
public function counter() : Attribute
{
return Attribute::make(
get: fn () => $this->counter_handler ? new $this->counter_handler : null,
);
}
}