From 25b400a27a87e99c3067a7cbf93f6541c82496d0 Mon Sep 17 00:00:00 2001 From: Hasby Maulana Date: Sat, 23 Dec 2023 14:52:01 +0700 Subject: [PATCH] build(core): initial --- .github/workflows/cd.yml | 17 + LICENSE | 21 + README.md | 73 +++ composer.json | 55 +++ .../2023_01_15_000001_create_menus_table.php | 39 ++ src/Console/Commands/InstallCommand.php | 75 ++++ .../Repository/Admin/IMenuAdminRepository.php | 14 + src/Contracts/Repository/IMenuRepository.php | 11 + src/Events/.gitkeep | 0 src/Listeners/.gitkeep | 0 src/Models/Menu.php | 46 ++ src/Providers/MenuServiceProvider.php | 104 +++++ .../Eloquent/Admin/MenuAdminRepository.php | 169 +++++++ src/Repositories/Eloquent/MenuRepository.php | 46 ++ src/Repositories/QueryBuilder/.gitkeep | 0 stubs/app/Exports/Menus/MenuExport.php | 58 +++ .../Admin/Menu/MenuAdminController.php | 416 ++++++++++++++++++ .../Http/Controllers/Menu/MenuController.php | 119 +++++ .../Admin/Menus/MenuDestroyValidation.php | 39 ++ .../Admin/Menus/MenuShowValidation.php | 39 ++ .../Admin/Menus/MenuStoreValidation.php | 45 ++ .../Admin/Menus/MenuUpdateValidation.php | 58 +++ .../Requests/Menus/MenuIndexValidation.php | 40 ++ .../Requests/Menus/MenuShowValidation.php | 47 ++ stubs/app/Http/Responses/.gitkeep | 0 stubs/app/Imports/Menus/MenuImport.php | 81 ++++ stubs/routes/admin/menu.php | 14 + stubs/routes/user/menu.php | 12 + 28 files changed, 1638 insertions(+) create mode 100644 .github/workflows/cd.yml create mode 100644 LICENSE create mode 100644 README.md create mode 100644 composer.json create mode 100644 database/migrations/2023_01_15_000001_create_menus_table.php create mode 100644 src/Console/Commands/InstallCommand.php create mode 100644 src/Contracts/Repository/Admin/IMenuAdminRepository.php create mode 100644 src/Contracts/Repository/IMenuRepository.php create mode 100644 src/Events/.gitkeep create mode 100644 src/Listeners/.gitkeep create mode 100644 src/Models/Menu.php create mode 100644 src/Providers/MenuServiceProvider.php create mode 100644 src/Repositories/Eloquent/Admin/MenuAdminRepository.php create mode 100644 src/Repositories/Eloquent/MenuRepository.php create mode 100644 src/Repositories/QueryBuilder/.gitkeep create mode 100644 stubs/app/Exports/Menus/MenuExport.php create mode 100644 stubs/app/Http/Controllers/Admin/Menu/MenuAdminController.php create mode 100644 stubs/app/Http/Controllers/Menu/MenuController.php create mode 100644 stubs/app/Http/Requests/Admin/Menus/MenuDestroyValidation.php create mode 100644 stubs/app/Http/Requests/Admin/Menus/MenuShowValidation.php create mode 100644 stubs/app/Http/Requests/Admin/Menus/MenuStoreValidation.php create mode 100644 stubs/app/Http/Requests/Admin/Menus/MenuUpdateValidation.php create mode 100644 stubs/app/Http/Requests/Menus/MenuIndexValidation.php create mode 100644 stubs/app/Http/Requests/Menus/MenuShowValidation.php create mode 100644 stubs/app/Http/Responses/.gitkeep create mode 100644 stubs/app/Imports/Menus/MenuImport.php create mode 100644 stubs/routes/admin/menu.php create mode 100644 stubs/routes/user/menu.php diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml new file mode 100644 index 0000000..71c0fac --- /dev/null +++ b/.github/workflows/cd.yml @@ -0,0 +1,17 @@ +name: Laravel.php Menu + +on: push + +jobs: + cd: + runs-on: ubuntu-latest + steps: + - name: cd + uses: tripteki/cd-package@1.0.0 + with: + token: ${{ secrets.GITHUB_TOKEN }} + repotoken: ${{ secrets.REPOSITORY_TOKEN }} + repouser: tripteki + repository: https://packagist.org + language: php + artifact: composer.json \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..061b3a5 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2022 Trip Teknologi + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..7f421a8 --- /dev/null +++ b/README.md @@ -0,0 +1,73 @@ +

Menu

+ +This package provides implementation of Menu in repository pattern for Lumen and Laravel besides REST API starterpack of admin management with no intervention to codebase and keep clean. + +Getting Started +--- + +Installation : + +``` +composer require tripteki/laravelphp-menu +``` + +How to use it : + +- Put `Tripteki\Menu\Providers\MenuServiceProvider` to service provider configuration list. + +- Put `Tripteki\Menu\Providers\MenuServiceProvider::ignoreMigrations()` into `register` provider, then publish migrations file into your project's directory with running (optionally) : + +``` +php artisan vendor:publish --tag=tripteki-laravelphp-menu-migrations +``` + +- Migrate. + +``` +php artisan migrate +``` + +- Sample : + +```php +use Tripteki\Menu\Contracts\Repository\Admin\IMenuAdminRepository; +use Tripteki\Menu\Contracts\Repository\IMenuRepository; + +$menuAdminRepository = app(IMenuAdminRepository::class); + +// $menuAdminRepository->create([ "platform" => "desktop", "route" => "/ads", "nth" => 0, "title" => "ads_gallery", "icon" => "md-gallery", "description" => "Gallery", ]); // +// $menuAdminRepository->delete("identifier"); // +// $menuAdminRepository->update("identifier", [ "platform" => "desktop", "route" => "/ads", "nth" => 1, "title" => "ads_gallery", "icon" => "md-gallery", "description" => "Gallery", ]); // +// $menuAdminRepository->activate("identifier"); // +// $menuAdminRepository->deactivate("identifier"); // +// $menuAdminRepository->get("identifier"); // +// $menuAdminRepository->all(); // + +$repository = app(IMenuRepository::class); + +// $repository->get("desktop", "/ads", 5); // +// $repository->all("web", "/ads"); // +// $repository->all("mobile", "/ads"); // +// $repository->all("desktop", "/ads"); // +``` + +- Generate swagger files into your project's directory with putting this into your annotation configuration (optionally) : + +``` +base_path("app/Http/Controllers/Menu") +``` + +``` +base_path("app/Http/Controllers/Admin/Menu") +``` + +Usage +--- + +`php artisan adminer:install:menu` + +Author +--- + +- Trip Teknologi ([@tripteki](https://linkedin.com/company/tripteki)) +- Hasby Maulana ([@hsbmaulana](https://linkedin.com/in/hsbmaulana)) diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..4433435 --- /dev/null +++ b/composer.json @@ -0,0 +1,55 @@ +{ + "name": "tripteki/laravelphp-menu", + "version": "1.0.0", + "description": "Trip Teknologi's Laravel.php Menus", + + "readme": "README.md", + "license": "MIT", + "authors": [ { "name": "Trip Teknologi", "email": "tripteki.company@gmail.com" } ], + "homepage": "https://github.com/tripteki/laravelphp-menu", + "support": { "issues": "https://github.com/tripteki/laravelphp-menu/issues" }, + + "require": { + + "php": "^8.0.2", + + "tripteki/laravelphp-repository": "^1.0.0", + "tripteki/laravelphp-helpers": "^1.0.0", + "tripteki/laravelphp-adminer": "^1.0.0", + "tripteki/laravelphp-import-export": "^1.0.0", + "tripteki/laravelphp-request-response-query": "^1.0.0" + }, + + "require-dev": {}, + + "suggest": { + + "laravel/lumen-framework": "Required when using lumen framework (^9.0).", + "laravel/framework": "Required when using laravel framework (^9.0)." + }, + + "autoload": { + + "psr-4": { + + "Tripteki\\Menu\\": "src/" + } + }, + + "autoload-dev": {}, + + "extra": { + + "laravel": { + + "dont-discover": [], + + "providers": [ + + "Tripteki\\Menu\\Providers\\MenuServiceProvider" + ], + + "aliases": [] + } + } +} diff --git a/database/migrations/2023_01_15_000001_create_menus_table.php b/database/migrations/2023_01_15_000001_create_menus_table.php new file mode 100644 index 0000000..5a0d537 --- /dev/null +++ b/database/migrations/2023_01_15_000001_create_menus_table.php @@ -0,0 +1,39 @@ +uuid("id"); + + $table->string("platform"); + $table->string("route"); + $table->integer("nth")->default(0); + $table->string("title"); + $table->string("icon")->nullable(true); + $table->text("description")->nullable(true); + $table->timestamps(); + $table->softDeletes(); + + $table->primary("id"); + $table->unique([ "platform", "route", "title", ]); + }); + } + + /** + * @return void + */ + public function down() + { + Schema::dropIfExists("menus"); + } +}; diff --git a/src/Console/Commands/InstallCommand.php b/src/Console/Commands/InstallCommand.php new file mode 100644 index 0000000..4f5b542 --- /dev/null +++ b/src/Console/Commands/InstallCommand.php @@ -0,0 +1,75 @@ +helper = $helper; + } + + /** + * @return int + */ + public function handle() + { + $this->installStack(); + + return 0; + } + + /** + * @return int|null + */ + protected function installStack() + { + (new Filesystem)->ensureDirectoryExists(base_path("routes/user")); + (new Filesystem)->ensureDirectoryExists(base_path("routes/admin")); + (new Filesystem)->copy(__DIR__."/../../../stubs/routes/user/menu.php", base_path("routes/user/menu.php")); + (new Filesystem)->copy(__DIR__."/../../../stubs/routes/admin/menu.php", base_path("routes/admin/menu.php")); + $this->helper->putRoute("api.php", "user/menu.php"); + $this->helper->putRoute("api.php", "admin/menu.php"); + + (new Filesystem)->ensureDirectoryExists(app_path("Http/Controllers/Menu")); + (new Filesystem)->copyDirectory(__DIR__."/../../../stubs/app/Http/Controllers/Menu", app_path("Http/Controllers/Menu")); + (new Filesystem)->ensureDirectoryExists(app_path("Http/Requests/Menus")); + (new Filesystem)->copyDirectory(__DIR__."/../../../stubs/app/Http/Requests/Menus", app_path("Http/Requests/Menus")); + (new Filesystem)->ensureDirectoryExists(app_path("Http/Controllers/Admin/Menu")); + (new Filesystem)->copyDirectory(__DIR__."/../../../stubs/app/Http/Controllers/Admin/Menu", app_path("Http/Controllers/Admin/Menu")); + (new Filesystem)->ensureDirectoryExists(app_path("Imports/Menus")); + (new Filesystem)->copyDirectory(__DIR__."/../../../stubs/app/Imports/Menus", app_path("Imports/Menus")); + (new Filesystem)->ensureDirectoryExists(app_path("Exports/Menus")); + (new Filesystem)->copyDirectory(__DIR__."/../../../stubs/app/Exports/Menus", app_path("Exports/Menus")); + (new Filesystem)->ensureDirectoryExists(app_path("Http/Requests/Admin/Menus")); + (new Filesystem)->copyDirectory(__DIR__."/../../../stubs/app/Http/Requests/Admin/Menus", app_path("Http/Requests/Admin/Menus")); + (new Filesystem)->ensureDirectoryExists(app_path("Http/Responses")); + + $this->info("Adminer Menu scaffolding installed successfully."); + } +}; diff --git a/src/Contracts/Repository/Admin/IMenuAdminRepository.php b/src/Contracts/Repository/Admin/IMenuAdminRepository.php new file mode 100644 index 0000000..6f89a81 --- /dev/null +++ b/src/Contracts/Repository/Admin/IMenuAdminRepository.php @@ -0,0 +1,14 @@ +restore(); + } + + /** + * @return void + */ + public function deactivate() + { + $this->delete(); + } +}; diff --git a/src/Providers/MenuServiceProvider.php b/src/Providers/MenuServiceProvider.php new file mode 100644 index 0000000..eb2605f --- /dev/null +++ b/src/Providers/MenuServiceProvider.php @@ -0,0 +1,104 @@ + \Tripteki\Menu\Repositories\Eloquent\MenuRepository::class, + \Tripteki\Menu\Contracts\Repository\Admin\IMenuAdminRepository::class => \Tripteki\Menu\Repositories\Eloquent\Admin\MenuAdminRepository::class, + ]; + + /** + * @var bool + */ + public static $runsMigrations = true; + + /** + * @return bool + */ + public static function shouldRunMigrations() + { + return static::$runsMigrations; + } + + /** + * @return void + */ + public static function ignoreMigrations() + { + static::$runsMigrations = false; + } + + /** + * @return void + */ + public function boot() + { + parent::boot(); + + $this->dataEventListener(); + + $this->registerPublishers(); + $this->registerCommands(); + $this->registerMigrations(); + } + + /** + * @return void + */ + protected function registerCommands() + { + if (! $this->app->isProduction() && $this->app->runningInConsole()) { + + $this->commands( + [ + InstallCommand::class, + ]); + } + } + + /** + * @return void + */ + protected function registerMigrations() + { + if ($this->app->runningInConsole() && static::shouldRunMigrations()) { + + $this->loadMigrationsFrom(__DIR__."/../../database/migrations"); + } + } + + /** + * @return void + */ + protected function registerPublishers() + { + if (! static::shouldRunMigrations()) { + + $this->publishes( + [ + __DIR__."/../../database/migrations" => database_path("migrations"), + ], + + "tripteki-laravelphp-menu-migrations"); + } + } + + /** + * @return void + */ + public function dataEventListener() + { + Menu::observe(UniqueIdObserver::class); + } +}; diff --git a/src/Repositories/Eloquent/Admin/MenuAdminRepository.php b/src/Repositories/Eloquent/Admin/MenuAdminRepository.php new file mode 100644 index 0000000..f2a95b3 --- /dev/null +++ b/src/Repositories/Eloquent/Admin/MenuAdminRepository.php @@ -0,0 +1,169 @@ + $querystring["limit"] ?? request()->query("limit", 10), + "current_page" => $querystring["current_page"] ?? request()->query("current_page", 1), + ]; + extract($querystringed); + + $content = QueryBuilder::for(Menu::class)-> + withTrashed()-> + defaultSort("nth")-> + allowedSorts([ "platform", "route", "nth", "title", ])-> + allowedFilters([ "platform", "route", "nth", "title", ])-> + paginate($limit, [ "*", ], "current_page", $current_page)->appends(empty($querystring) ? request()->query() : $querystringed); + + return $content; + } + + /** + * @param int|string $identifier + * @param array $querystring|[] + * @return mixed + */ + public function get($identifier, $querystring = []) + { + $content = Menu::findOrFail($identifier); + + return $content; + } + + /** + * @param int|string $identifier + * @param array $data + * @return mixed + */ + public function update($identifier, $data) + { + $content = Menu::findOrFail($identifier); + + DB::beginTransaction(); + + try { + + $content->update($data); + + DB::commit(); + + } catch (Exception $exception) { + + DB::rollback(); + } + + return $content; + } + + /** + * @param array $data + * @return mixed + */ + public function create($data) + { + $content = null; + + DB::beginTransaction(); + + try { + + $content = Menu::create($data); + + DB::commit(); + + } catch (Exception $exception) { + + DB::rollback(); + } + + return $content; + } + + /** + * @param int|string $identifier + * @return mixed + */ + public function delete($identifier) + { + $content = Menu::findOrFail($identifier); + + DB::beginTransaction(); + + try { + + $content->forceDelete(); + + DB::commit(); + + } catch (Exception $exception) { + + DB::rollback(); + } + + return $content; + } + + /** + * @param int|string $identifier + * @return mixed + */ + public function activate($identifier) + { + $content = Menu::withTrashed()->findOrFail($identifier); + + DB::beginTransaction(); + + try { + + $content->activate(); + + DB::commit(); + + } catch (Exception $exception) { + + DB::rollback(); + } + + return $content; + } + + /** + * @param int|string $identifier + * @return mixed + */ + public function deactivate($identifier) + { + $content = Menu::findOrFail($identifier); + + DB::beginTransaction(); + + try { + + $content->deactivate(); + + DB::commit(); + + } catch (Exception $exception) { + + DB::rollback(); + } + + return $content; + } +}; diff --git a/src/Repositories/Eloquent/MenuRepository.php b/src/Repositories/Eloquent/MenuRepository.php new file mode 100644 index 0000000..e39c549 --- /dev/null +++ b/src/Repositories/Eloquent/MenuRepository.php @@ -0,0 +1,46 @@ + + where("platform", $platform)-> + where("route", $route)-> + defaultSort("nth")-> + allowedSorts([ "platform", "route", "nth", "title", ])-> + allowedFilters([ "platform", "route", "nth", "title", ])-> + get(); + + return $content; + } + + /** + * @param string $platform + * @param string $route + * @param string $id + * @param array $querystring|[] + * @return mixed + */ + public function get($platform, $route, $id, $querystring = []) + { + $content = Menu::where("platform", $platform)->where("route", $route)->findOrFail($id); + + return $content; + } +}; diff --git a/src/Repositories/QueryBuilder/.gitkeep b/src/Repositories/QueryBuilder/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/stubs/app/Exports/Menus/MenuExport.php b/stubs/app/Exports/Menus/MenuExport.php new file mode 100644 index 0000000..57309da --- /dev/null +++ b/stubs/app/Exports/Menus/MenuExport.php @@ -0,0 +1,58 @@ + [ "font" => [ "bold" => true, ], ], + ]; + } + + /** + * @return array + */ + public function headings(): array + { + return [ + + "Platform", + "Route", + "Position", + "Title", + "Icon", + "Description", + ]; + } + + /** + * @return \Illuminate\Database\Eloquent\Collection + */ + public function collection() + { + return Menu::all([ + + "platform", + "route", + "nth", + "title", + "icon", + "description", + ]); + } +}; diff --git a/stubs/app/Http/Controllers/Admin/Menu/MenuAdminController.php b/stubs/app/Http/Controllers/Admin/Menu/MenuAdminController.php new file mode 100644 index 0000000..3a218bd --- /dev/null +++ b/stubs/app/Http/Controllers/Admin/Menu/MenuAdminController.php @@ -0,0 +1,416 @@ +menuAdminRepository = $menuAdminRepository; + } + + /** + * @OA\Get( + * path="/admin/menus", + * tags={"Admin Menu"}, + * summary="Index", + * @OA\Parameter( + * required=false, + * in="query", + * name="limit", + * description="Menu's Pagination Limit." + * ), + * @OA\Parameter( + * required=false, + * in="query", + * name="current_page", + * description="Menu's Pagination Current Page." + * ), + * @OA\Parameter( + * required=false, + * in="query", + * name="order", + * description="Menu's Pagination Order." + * ), + * @OA\Parameter( + * required=false, + * in="query", + * name="filter[]", + * description="Menu's Pagination Filter." + * ), + * @OA\Response( + * response=200, + * description="Success." + * ) + * ) + * + * @param \Illuminate\Http\Request $request + * @return \Illuminate\Http\JsonResponse + */ + public function index(Request $request) + { + $data = []; + $statecode = 200; + + $data = $this->menuAdminRepository->all(); + + return iresponse($data, $statecode); + } + + /** + * @OA\Get( + * path="/admin/menus/{identifier}", + * tags={"Admin Menu"}, + * summary="Show", + * @OA\Parameter( + * required=true, + * in="path", + * name="identifier", + * description="Menu's Identifier." + * ), + * @OA\Response( + * response=200, + * description="Success." + * ), + * @OA\Response( + * response=404, + * description="Not Found." + * ) + * ) + * + * @param \App\Http\Requests\Admin\Menus\MenuShowValidation $request + * @param string $identifier + * @return \Illuminate\Http\JsonResponse + */ + public function show(MenuShowValidation $request, $identifier) + { + $form = $request->validated(); + $data = []; + $statecode = 200; + + $data = $this->menuAdminRepository->get($identifier); + + return iresponse($data, $statecode); + } + + /** + * @OA\Post( + * path="/admin/menus", + * tags={"Admin Menu"}, + * summary="Store", + * @OA\RequestBody( + * @OA\MediaType( + * mediaType="application/x-www-form-urlencoded", + * @OA\Schema( + * @OA\Property( + * property="platform", + * type="string", + * description="Menu's Platform." + * ), + * @OA\Property( + * property="route", + * type="string", + * description="Menu's Route." + * ), + * @OA\Property( + * property="nth", + * type="integer", + * description="Menu's Position." + * ), + * @OA\Property( + * property="title", + * type="string", + * description="Menu's Title." + * ), + * @OA\Property( + * property="icon", + * type="string", + * description="Menu's Icon." + * ), + * @OA\Property( + * property="description", + * type="string", + * description="Menu's Description." + * ) + * ) + * ) + * ), + * @OA\Response( + * response=201, + * description="Created." + * ), + * @OA\Response( + * response=422, + * description="Unprocessable Entity." + * ) + * ) + * + * @param \App\Http\Requests\Admin\Menus\MenuStoreValidation $request + * @return \Illuminate\Http\JsonResponse + */ + public function store(MenuStoreValidation $request) + { + $form = $request->validated(); + $data = []; + $statecode = 202; + + $data = $this->menuAdminRepository->create($form); + + if ($data) { + + $statecode = 201; + } + + return iresponse($data, $statecode); + } + + /** + * @OA\Put( + * path="/admin/menus/{identifier}", + * tags={"Admin Menu"}, + * summary="Update", + * @OA\Parameter( + * required=true, + * in="path", + * name="identifier", + * description="Menu's Identifier." + * ), + * @OA\RequestBody( + * @OA\MediaType( + * mediaType="application/x-www-form-urlencoded", + * @OA\Schema( + * @OA\Property( + * property="platform", + * type="string", + * description="Menu's Platform." + * ), + * @OA\Property( + * property="route", + * type="string", + * description="Menu's Route." + * ), + * @OA\Property( + * property="nth", + * type="integer", + * description="Menu's Position." + * ), + * @OA\Property( + * property="title", + * type="string", + * description="Menu's Title." + * ), + * @OA\Property( + * property="icon", + * type="string", + * description="Menu's Icon." + * ), + * @OA\Property( + * property="description", + * type="string", + * description="Menu's Description." + * ) + * ) + * ) + * ), + * @OA\Response( + * response=201, + * description="Created." + * ), + * @OA\Response( + * response=422, + * description="Unprocessable Entity." + * ), + * @OA\Response( + * response=404, + * description="Not Found." + * ) + * ) + * + * @param \App\Http\Requests\Admin\Menus\MenuUpdateValidation $request + * @param string $identifier + * @return \Illuminate\Http\JsonResponse + */ + public function update(MenuUpdateValidation $request, $identifier) + { + $form = $request->validated(); + $data = []; + $statecode = 202; + + $data = $this->menuAdminRepository->update($identifier, $form); + + if ($data) { + + $statecode = 201; + } + + return iresponse($data, $statecode); + } + + /** + * @OA\Delete( + * path="/admin/menus/{identifier}", + * tags={"Admin Menu"}, + * summary="Destroy", + * @OA\Parameter( + * required=true, + * in="path", + * name="identifier", + * description="Menu's Identifier." + * ), + * @OA\Response( + * response=200, + * description="Success." + * ), + * @OA\Response( + * response=422, + * description="Unprocessable Entity." + * ), + * @OA\Response( + * response=404, + * description="Not Found." + * ) + * ) + * + * @param \App\Http\Requests\Admin\Menus\MenuDestroyValidation $request + * @param string $identifier + * @return \Illuminate\Http\JsonResponse + */ + public function destroy(MenuDestroyValidation $request, $identifier) + { + $form = $request->validated(); + $data = []; + $statecode = 202; + + $data = $this->menuAdminRepository->delete($identifier); + + if ($data) { + + $statecode = 200; + } + + return iresponse($data, $statecode); + } + + /** + * @OA\Post( + * path="/admin/menus-import", + * tags={"Admin Menu"}, + * summary="Import", + * @OA\RequestBody( + * @OA\MediaType( + * mediaType="multipart/form-data", + * @OA\Schema( + * @OA\Property( + * property="file", + * type="file", + * description="Menu's File." + * ) + * ) + * ) + * ), + * @OA\Response( + * response=200, + * description="Success." + * ), + * @OA\Response( + * response=422, + * description="Unprocessable Entity." + * ) + * ) + * + * @param \Tripteki\Helpers\Http\Requests\FileImportValidation $request + * @return \Illuminate\Http\JsonResponse + */ + public function import(FileImportValidation $request) + { + $form = $request->validated(); + $data = []; + $statecode = 200; + + if ($form["file"]->getClientOriginalExtension() == "csv" || $form["file"]->getClientOriginalExtension() == "txt") { + + $data = Excel::import(new MenuImport(), $form["file"], null, \Maatwebsite\Excel\Excel::CSV); + + } else if ($form["file"]->getClientOriginalExtension() == "xls") { + + $data = Excel::import(new MenuImport(), $form["file"], null, \Maatwebsite\Excel\Excel::XLS); + + } else if ($form["file"]->getClientOriginalExtension() == "xlsx") { + + $data = Excel::import(new MenuImport(), $form["file"], null, \Maatwebsite\Excel\Excel::XLSX); + } + + return iresponse($data, $statecode); + } + + /** + * @OA\Get( + * path="/admin/menus-export", + * tags={"Admin Menu"}, + * summary="Export", + * @OA\Parameter( + * required=false, + * in="query", + * name="file", + * schema={"type": "string", "enum": {"csv", "xls", "xlsx"}}, + * description="Menu's File." + * ), + * @OA\Response( + * response=200, + * description="Success." + * ), + * @OA\Response( + * response=422, + * description="Unprocessable Entity." + * ) + * ) + * + * @param \Tripteki\Helpers\Http\Requests\FileExportValidation $request + * @return mixed + */ + public function export(FileExportValidation $request) + { + $form = $request->validated(); + $data = []; + $statecode = 200; + + if ($form["file"] == "csv") { + + $data = Excel::download(new MenuExport(), "Menu.csv", \Maatwebsite\Excel\Excel::CSV); + + } else if ($form["file"] == "xls") { + + $data = Excel::download(new MenuExport(), "Menu.xls", \Maatwebsite\Excel\Excel::XLS); + + } else if ($form["file"] == "xlsx") { + + $data = Excel::download(new MenuExport(), "Menu.xlsx", \Maatwebsite\Excel\Excel::XLSX); + } + + return $data; + } +}; diff --git a/stubs/app/Http/Controllers/Menu/MenuController.php b/stubs/app/Http/Controllers/Menu/MenuController.php new file mode 100644 index 0000000..b967391 --- /dev/null +++ b/stubs/app/Http/Controllers/Menu/MenuController.php @@ -0,0 +1,119 @@ +menuRepository = $menuRepository; + } + + /** + * @OA\Get( + * path="/menus/{platform}/routes/{route}", + * tags={"Menus"}, + * summary="Index", + * security={{ "bearerAuth": {} }}, + * @OA\Parameter( + * required=true, + * in="path", + * name="platform", + * description="Menu's Platform." + * ), + * @OA\Parameter( + * required=true, + * in="path", + * name="route", + * description="Menu's Route." + * ), + * @OA\Response( + * response=200, + * description="Success." + * ) + * ) + * + * @param \App\Http\Requests\Menus\MenuIndexValidation $request + * @param string $platform + * @param string $route + * @return \Illuminate\Http\JsonResponse + */ + public function index(MenuIndexValidation $request, $platform, $route) + { + $form = $request->validated(); + $data = []; + $statecode = 200; + + $data = $this->menuRepository->all($platform, $route); + + return iresponse($data, $statecode); + } + + /** + * @OA\Get( + * path="/menus/{platform}/routes/{route}/ids/{id}", + * tags={"Menus"}, + * summary="Show", + * security={{ "bearerAuth": {} }}, + * @OA\Parameter( + * required=true, + * in="path", + * name="platform", + * description="Menu's Platform." + * ), + * @OA\Parameter( + * required=true, + * in="path", + * name="route", + * description="Menu's Route." + * ), + * @OA\Parameter( + * required=true, + * in="path", + * name="id", + * description="Menu's Id." + * ), + * @OA\Response( + * response=200, + * description="Success." + * ), + * @OA\Response( + * response=404, + * description="Not Found." + * ) + * ) + * + * @param \App\Http\Requests\Menus\MenuShowValidation $request + * @param string $platform + * @param string $route + * @param string $id + * @return \Illuminate\Http\JsonResponse + */ + public function show(MenuShowValidation $request, $platform, $route, $id) + { + $form = $request->validated(); + $data = []; + $statecode = 200; + + $data = $this->menuRepository->get($platform, $route, $id); + + return iresponse($data, $statecode); + } +}; diff --git a/stubs/app/Http/Requests/Admin/Menus/MenuDestroyValidation.php b/stubs/app/Http/Requests/Admin/Menus/MenuDestroyValidation.php new file mode 100644 index 0000000..e253f18 --- /dev/null +++ b/stubs/app/Http/Requests/Admin/Menus/MenuDestroyValidation.php @@ -0,0 +1,39 @@ + $this->route("menu"), + ]; + } + + /** + * @return bool + */ + public function authorize() + { + return true; + } + + /** + * @return array + */ + public function rules() + { + return [ + + "id" => "required|string|exists:".Menu::class, + ]; + } +}; diff --git a/stubs/app/Http/Requests/Admin/Menus/MenuShowValidation.php b/stubs/app/Http/Requests/Admin/Menus/MenuShowValidation.php new file mode 100644 index 0000000..a70b01b --- /dev/null +++ b/stubs/app/Http/Requests/Admin/Menus/MenuShowValidation.php @@ -0,0 +1,39 @@ + $this->route("menu"), + ]; + } + + /** + * @return bool + */ + public function authorize() + { + return true; + } + + /** + * @return array + */ + public function rules() + { + return [ + + "id" => "required|string|exists:".Menu::class, + ]; + } +}; diff --git a/stubs/app/Http/Requests/Admin/Menus/MenuStoreValidation.php b/stubs/app/Http/Requests/Admin/Menus/MenuStoreValidation.php new file mode 100644 index 0000000..4c2080e --- /dev/null +++ b/stubs/app/Http/Requests/Admin/Menus/MenuStoreValidation.php @@ -0,0 +1,45 @@ + + */ + public function rules() + { + return [ + + "platform" => "required|string|lowercase|max:8", + "route" => "required|string|max:127|regex:/^\/[0-9a-zA-Z\._\-\/]+$/", + "nth" => "required|integer", + "title" => [ + + "required", + "string", + "lowercase", + "max:32", + "alpha_dash:ascii", + Rule::unique(Menu::class)->where(function ($query) { + + return $query->where("platform", $this->input("platform"))->where("route", $this->input("route")); + }), + ], + "icon" => "present|string|max:255|nullable", + "description" => "present|string|max:255|nullable", + ]; + } +}; diff --git a/stubs/app/Http/Requests/Admin/Menus/MenuUpdateValidation.php b/stubs/app/Http/Requests/Admin/Menus/MenuUpdateValidation.php new file mode 100644 index 0000000..81d3c0a --- /dev/null +++ b/stubs/app/Http/Requests/Admin/Menus/MenuUpdateValidation.php @@ -0,0 +1,58 @@ + $this->route("menu"), + ]; + } + + /** + * @return bool + */ + public function authorize() + { + return true; + } + + /** + * @return array + */ + public function rules() + { + return [ + + "id" => "required|string|exists:".Menu::class, + "platform" => "required|string|lowercase|max:8", + "route" => "required|string|max:127|regex:/^\/[0-9a-zA-Z\._\-\/]+$/", + "nth" => "required|integer", + "title" => [ + + "required", + "string", + "lowercase", + "max:32", + "alpha_dash:ascii", + Rule::unique(Menu::class)->where(function ($query) { + + return $query->where("platform", $this->input("platform"))->where("route", $this->input("route")); + + })->ignore($this->route("menu"), "id"), + ], + "icon" => "present|string|max:255|nullable", + "description" => "present|string|max:255|nullable", + ]; + } +}; diff --git a/stubs/app/Http/Requests/Menus/MenuIndexValidation.php b/stubs/app/Http/Requests/Menus/MenuIndexValidation.php new file mode 100644 index 0000000..eb9d9e4 --- /dev/null +++ b/stubs/app/Http/Requests/Menus/MenuIndexValidation.php @@ -0,0 +1,40 @@ + $this->route("platform"), + "route" => $this->route("route"), + ]; + } + + /** + * @return bool + */ + public function authorize() + { + return true; + } + + /** + * @return array + */ + public function rules() + { + return [ + + "platform" => "required|string", + "route" => "required|string", + ]; + } +}; diff --git a/stubs/app/Http/Requests/Menus/MenuShowValidation.php b/stubs/app/Http/Requests/Menus/MenuShowValidation.php new file mode 100644 index 0000000..5d94fcc --- /dev/null +++ b/stubs/app/Http/Requests/Menus/MenuShowValidation.php @@ -0,0 +1,47 @@ + $this->route("platform"), + "route" => $this->route("route"), + "id" => $this->route("menu"), + ]; + } + + /** + * @return bool + */ + public function authorize() + { + return true; + } + + /** + * @return array + */ + public function rules() + { + return [ + + "platform" => "required|string", + "route" => "required|string", + "id" => Rule::exists(Menu::class)->where(function ($query) { + + return $query->where("platform", $this->input("platform"))->where("route", $this->input("route")); + }), + ]; + } +}; diff --git a/stubs/app/Http/Responses/.gitkeep b/stubs/app/Http/Responses/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/stubs/app/Imports/Menus/MenuImport.php b/stubs/app/Imports/Menus/MenuImport.php new file mode 100644 index 0000000..907d3c8 --- /dev/null +++ b/stubs/app/Imports/Menus/MenuImport.php @@ -0,0 +1,81 @@ +rules(); + + $rows->map(function ($row) use ($validator, $rows) { + + Validator::make($rows->toArray(), [ + + "*.0" => $validator["platform"], + "*.1" => $validator["route"], + "*.2" => $validator["nth"], + "*.3" => [ + + "required", + "string", + "lowercase", + "max:32", + "alpha_dash:ascii", + Rule::unique(Menu::class, "title")->where(function ($query) use ($row) { + + return $query->where("platform", $row[0])->where("route", $row[1]); + }), + ], + "*.4" => $validator["icon"], + "*.5" => $validator["description"], + + ])->validate(); + }); + } + + /** + * @param \Illuminate\Support\Collection $rows + * @return void + */ + public function collection(Collection $rows) + { + $this->validate($rows); + + $menuAdminRepository = app(IMenuAdminRepository::class); + + foreach ($rows as $row) { + + $menuAdminRepository->create([ + + "platform" => $row[0], + "route" => $row[1], + "nth" => $row[2], + "title" => $row[3], + "icon" => $row[4], + "description" => $row[5], + ]); + } + } +}; diff --git a/stubs/routes/admin/menu.php b/stubs/routes/admin/menu.php new file mode 100644 index 0000000..cbf5314 --- /dev/null +++ b/stubs/routes/admin/menu.php @@ -0,0 +1,14 @@ +middleware(config("adminer.middleware.admin"))->group(function () { + + /** + * Menus. + */ + Route::apiResource("menus", MenuAdminController::class)->parameters([ "menus" => "menu", ]); + Route::post("menus-import", [ MenuAdminController::class, "import", ]); + Route::get("menus-export", [ MenuAdminController::class, "export", ]); +}); diff --git a/stubs/routes/user/menu.php b/stubs/routes/user/menu.php new file mode 100644 index 0000000..3b622cd --- /dev/null +++ b/stubs/routes/user/menu.php @@ -0,0 +1,12 @@ +middleware(config("adminer.middleware.user"))->group(function () { + + /** + * Menus. + */ + Route::apiResource("menus.routes.ids", MenuController::class)->only([ "index", "show", ])->parameters([ "menus" => "menu", ]); +});