first commit

This commit is contained in:
2025-11-06 06:55:15 +00:00
commit 0b603376d2
107 changed files with 17279 additions and 0 deletions

27
app/Console/Kernel.php Normal file
View File

@@ -0,0 +1,27 @@
<?php
namespace App\Console;
use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
class Kernel extends ConsoleKernel
{
/**
* Define the application's command schedule.
*/
protected function schedule(Schedule $schedule): void
{
// $schedule->command('inspire')->hourly();
}
/**
* Register the commands for the application.
*/
protected function commands(): void
{
$this->load(__DIR__.'/Commands');
require base_path('routes/console.php');
}
}

View File

@@ -0,0 +1,30 @@
<?php
namespace App\Exceptions;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use Throwable;
class Handler extends ExceptionHandler
{
/**
* The list of the inputs that are never flashed to the session on validation exceptions.
*
* @var array<int, string>
*/
protected $dontFlash = [
'current_password',
'password',
'password_confirmation',
];
/**
* Register the exception handling callbacks for the application.
*/
public function register(): void
{
$this->reportable(function (Throwable $e) {
//
});
}
}

View File

@@ -0,0 +1,271 @@
<?php
namespace App\Http\Controllers;
use App\Http\Resources\UserResource;
use Auth;
use Illuminate\Http\Request;
use App\Models\User;
use App\Traits\ApiResponseHelper;
use App\Traits\ImageHelper;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Validator;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Password;
class AuthController extends Controller
{
use AuthorizesRequests, ValidatesRequests;
use ApiResponseHelper, ImageHelper;
public function login(Request $request)
{
$validator = Validator::make($request->all(), [
'email' => ['required', 'email'],
'password' => ['required', 'min:6'],
'type' => ['required', 'in:super_admin,admin,waiter,client'],
]);
if ($validator->fails()) {
return $this->apiResponse(false, $validator->errors()->first(), $validator->errors());
}
try {
$user = User::where([['email', $request->email], ['type', $request->type]])->first();
if (!$user || !Hash::check($request->password, $user->password)) {
$message = __('messages.invalid_credentials');
return $this->apiResponse(false, $message);
}
if (!($user->status == "active")) {
return $this->apiResponse(false, $user->status_reason);
}
$token = $user->createToken($user->email)->plainTextToken;
$data = collect([
'user' => new UserResource($user),
'token' => $token
]);
$message = __('messages.authorized');
return $this->apiResponse(true, $message, $data);
} catch (\Throwable $exception) {
return $this->apiResponse(false, $exception->getMessage());
}
}
public function register(Request $request)
{
$validator = Validator::make($request->all(), [
'name' => ['required', 'min: 3'],
'email' => ['required', 'email', 'unique:users'],
'password' => ['required', \Illuminate\Validation\Rules\Password::min(8)],
'country_code' => ['required'],
'phone' => ['required', 'min: 8', 'max:11'],
'image' => ['nullable', 'image'],
]);
if ($validator->fails()) {
return $this->apiResponse(false, $validator->errors()->first(), $validator->errors());
}
try {
DB::beginTransaction();
$user = new User();
$user->name = $request->name;
$user->email = strtolower($request->email);
$user->password = Hash::make($request->password);
$user->country_code = $request->country_code;
$user->phone = $request->phone;
$user->type = "client";
$user->save();
if ($request->image) {
$prefix = 'profile';
$profileImagePath = $this->uploadFile($request->image, $prefix, false);
$user->image = $profileImagePath;
$user->save();
}
DB::commit();
$user->refresh();
$token = $user->createToken($user->email)->plainTextToken;
$data = collect([
'user' => new UserResource($user),
'token' => $token
]);
$message = __('messages.account_created');
return $this->apiResponse(true, $message,$data);
} catch (\Throwable $exception) {
return $this->apiResponse(false, $exception->getMessage());
}
}
public function loggedInUser(Request $request)
{
try {
$user = Auth::user();
if (!($user->status == "active")) {
return $this->apiResponse(false, $user->status_reason);
}
$token = $user->createToken($user->email)->plainTextToken;
$data = collect([
'user' => new UserResource($user),
'token' => $token
]);
$message = __('messages.authorized');
return $this->apiResponse(true, $message, $data);
} catch (\Throwable $exception) {
return $this->apiResponse(false, $exception->getMessage());
}
}
public function updatePassword(Request $request)
{
$validator = Validator::make($request->all(), [
'password' => ['required', 'min: 8'],
'confirm_password' => ['required', 'min: 8'],
]);
if ($validator->fails()) {
return $this->apiResponse(false, $validator->errors()->first(), $validator->errors());
}
try {
$user = Auth::user();
if ($request->password != $request->confirm_password) {
return $this->apiResponse(false, __('messages.passwords_not_same'));
}
DB::beginTransaction();
$user->password = Hash::make($request->password);
$user->tokens()->delete();
$user->save();
DB::commit();
$message = __('messages.password_updated');
return $this->apiResponse(true, $message, new UserResource($user));
} catch (\Throwable $exception) {
return $this->apiResponse(false, $exception->getMessage());
}
}
public function updateFcmToken(Request $request)
{
$validator = Validator::make($request->all(), [
'token' => ['required', 'min: 8'],
]);
if ($validator->fails()) {
return $this->apiResponse(false, $validator->errors()->first(), $validator->errors());
}
try {
$user = Auth::user();
DB::beginTransaction();
$user->notification_token = $request->token;
$user->save();
DB::commit();
$message = __('messages.token_updated');
return $this->apiResponse(true, $message);
} catch (\Throwable $exception) {
return $this->apiResponse(false, $exception->getMessage());
}
}
public function updateUser(Request $request)
{
$validator = Validator::make($request->all(), [
'name' => ['sometimes', 'min: 3'],
'email' => ['sometimes', 'email', 'unique:users'],
'country_code' => ['sometimes'],
'phone' => ['sometimes', 'min: 8', 'max:11'],
'password' => ['sometimes', \Illuminate\Validation\Rules\Password::min(8)],
'image' => ['nullable', 'image'],
]);
if ($validator->fails()) {
return $this->apiResponse(false, $validator->errors()->first(), $validator->errors());
}
try {
DB::beginTransaction();
$user = Auth::user();
if ($request->name) {
$user->name = $request->name;
}
if ($request->country_code) {
$user->country_code = $request->country_code;
$user->phone_verified_at = null;
}
if ($request->phone) {
$user->phone = $request->phone;
$user->phone_verified_at = null;
}
if ($request->email) {
$user->email = $request->email;
$user->email_verified_at = null;
}
$user->save();
if ($request->image) {
$prefix = 'profile';
$profileImagePath = $this->updateFile($request->image, $user->image,$prefix, false);
$user->image = $profileImagePath;
$user->save();
}
DB::commit();
$message = __('messages.user_updated');
return $this->apiResponse(true, $message, );
} catch (\Throwable $exception) {
return $this->apiResponse(false, $exception->getMessage());
}
}
public function destroy($id)
{
$user = Auth::user();
if($id != $user->id) {
return $this->apiResponse(false, __('messages.not_authorized'),);
}
if($id == 1){
return $this->apiResponse(false, __('messages.user_not_deletable'),);
}else{
//under_deletion
try {
DB::beginTransaction();
$user = User::where('id',$id)->firstorfail();
$user->status = 'under_deletion';
$user->status_reason = __('messages.account_deletion_review');
$user->save();
DB::commit();
return $this->apiResponse(true, __('messages.account_deletion_received'));
} catch (\Throwable $exception) {
DB::rollBack();
return $this->apiResponse(false, $exception->getMessage());
}
}
}
}

View File

@@ -0,0 +1,233 @@
<?php
namespace App\Http\Controllers;
use App\Models\Category;
use App\Http\Resources\CategoryResource;
use App\Traits\ApiResponseHelper;
use App\Traits\ImageHelper;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Facades\DB;
class CategoryController extends Controller
{
use ApiResponseHelper, ImageHelper;
public function index(Request $request)
{
$perPage = $request->per_page ?? config('custom.paginationItem');
$route = $request->route();
$prefix = $route ? $route->getPrefix() : null;
$isClient = $prefix && (str_contains($prefix, '/client') || $prefix === 'client');
$query = Category::orderBy('sortingIndex', 'desc');
if ($isClient) {
$query->where('isActive', true);
}
$categories = $query->paginate($perPage);
$data = array();
$data['content'] = CategoryResource::collection($categories);
$data['pagination'] = [
'total' => $categories->total(),
'per_page' => $categories->perPage(),
'current_page' => $categories->currentPage(),
'last_page' => $categories->lastPage(),
'from' => $categories->firstItem(),
'to' => $categories->lastItem()
];
return $this->apiResponse(
true,
__('messages.categories_retrieved'),
$data
);
}
public function show($id)
{
$category = Category::find($id);
if (!$category) {
return $this->apiResponse(
false,
__('messages.category_not_found')
);
}
return $this->apiResponse(
true,
__('messages.category_retrieved'),
new CategoryResource($category)
);
}
public function store(Request $request)
{
$validator = Validator::make($request->all(), [
'title.en' => ['required', 'string'],
'title.it' => ['required', 'string'],
'description.en' => ['nullable', 'string'],
'description.it' => ['nullable', 'string'],
'sortingIndex' => ['nullable', 'integer'],
'isActive' => ['nullable', 'boolean'],
'thumbnail' => ['nullable', 'image'],
]);
if ($validator->fails()) {
return $this->apiResponse(false, $validator->errors()->first(), $validator->errors());
}
try {
DB::beginTransaction();
$category = new Category();
$category->title = $request->title;
$category->description = $request->description;
$category->sortingIndex = $request->sortingIndex ?? 0;
$category->isActive = $request->isActive ?? true;
$category->save();
if ($request->thumbnail) {
$prefix = 'category';
$thumbnailPath = $this->uploadFile($request->thumbnail, $prefix, false);
$category->thumbnail = $thumbnailPath;
$category->save();
}
DB::commit();
$category->refresh();
$data = new CategoryResource($category);
$message = __('messages.category_created');
return $this->apiResponse(true, $message, $data);
} catch (\Throwable $exception) {
DB::rollBack();
return $this->apiResponse(false, $exception->getMessage());
}
}
public function update(Request $request, $id)
{
$validator = Validator::make($request->all(), [
'title.en' => ['sometimes', 'string'],
'title.it' => ['sometimes', 'string'],
'description.en' => ['sometimes', 'string'],
'description.it' => ['sometimes', 'string'],
'sortingIndex' => ['sometimes', 'integer'],
'isActive' => ['sometimes', 'boolean'],
'thumbnail' => ['nullable', 'image'],
]);
if ($validator->fails()) {
return $this->apiResponse(false, $validator->errors()->first(), $validator->errors());
}
try {
DB::beginTransaction();
$category = Category::findOrFail($id);
if ($request->has('title')) {
$category->title = $request->title;
}
if ($request->has('description')) {
$category->description = $request->description;
}
if ($request->has('sortingIndex')) {
$category->sortingIndex = $request->sortingIndex;
}
if ($request->has('isActive')) {
$category->isActive = $request->isActive;
}
if ($request->thumbnail) {
$prefix = 'category';
$category->thumbnail = $this->updateFile($request->thumbnail, $category->thumbnail, $prefix, false);
}
$category->save();
DB::commit();
$category->refresh();
$data = new CategoryResource($category);
$message = __('messages.category_updated');
return $this->apiResponse(true, $message, $data);
} catch (\Throwable $exception) {
DB::rollBack();
return $this->apiResponse(false, $exception->getMessage());
}
}
public function destroy($id)
{
$category = Category::find($id);
if (!$category) {
return $this->apiResponse(
false,
__('messages.category_not_found')
);
}
$category->delete();
return $this->apiResponse(
true,
__('messages.category_deleted')
);
}
public function getAllData(Request $request)
{
$categories = \App\Models\Category::with('menus')->get();
$data = \App\Http\Resources\AdminCategoryWithMenusResource::collection($categories);
return $this->apiResponse(true, __('messages.categories_retrieved'), $data);
}
public function importAllData()
{
try {
$jsonPath = base_path('demo/bella_menu.json');
if (!file_exists($jsonPath)) {
return $this->apiResponse(false, 'bella_menu.json not found');
}
$json = file_get_contents($jsonPath);
$categories = json_decode($json, true);
if (!is_array($categories)) {
return $this->apiResponse(false, 'Invalid JSON structure');
}
\DB::beginTransaction();
foreach ($categories as $cat) {
// Check if category exists by both en and it title
$existingCategory = \App\Models\Category::whereJsonContains('title->en', $cat['title']['en'])
->orWhereJsonContains('title->it', $cat['title']['it'])
->first();
if ($existingCategory) {
$category = $existingCategory;
} else {
$category = new \App\Models\Category();
$category->title = $cat['title'];
$category->description = $cat['description'];
$category->sortingIndex = 0;
$category->isActive = $cat['isActive'] ?? true;
$category->thumbnail = $cat['thumbnail'] ?? null;
$category->save();
}
if (!empty($cat['menus']) && is_array($cat['menus'])) {
foreach ($cat['menus'] as $item) {
// Check if menu exists by both en and it title for this category
$exists = \App\Models\Menu::where('category_id', $category->id)
->where(function($query) use ($item) {
$query->whereJsonContains('title->en', $item['title']['en'])
->orWhereJsonContains('title->it', $item['title']['it']);
})->exists();
if ($exists) {
continue;
}
$menu = new \App\Models\Menu();
$menu->menu_id = $item['menu_id'] ?? null;
$menu->title = $item['title'];
$menu->description = $item['description'];
$menu->price = $item['price'];
$menu->image = $item['image'] ?? null;
$menu->isActive = $item['isActive'] ?? true;
$menu->category_id = $category->id;
$menu->save();
}
}
}
\DB::commit();
return $this->apiResponse(true, 'All data imported successfully');
} catch (\Throwable $e) {
\DB::rollBack();
return $this->apiResponse(false, $e->getMessage());
}
}
}

View File

@@ -0,0 +1,13 @@
<?php
namespace App\Http\Controllers;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Routing\Controller as BaseController;
class Controller extends BaseController
{
use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
}

View File

@@ -0,0 +1,254 @@
<?php
namespace App\Http\Controllers;
use App\Models\Menu;
use App\Models\Category;
use Illuminate\Http\Request;
use App\Http\Resources\MenuResource;
use App\Http\Resources\CategoryResource;
use Illuminate\Support\Facades\DB;
use Validator;
use App\Traits\ApiResponseHelper;
use App\Traits\ImageHelper;
class MenuController extends Controller
{
use ApiResponseHelper, ImageHelper;
public function index(Request $request)
{
$validator = Validator::make($request->all(), [
'category_id' => ['nullable', 'exists:categories,id'],
'per_page' => ['nullable', 'integer', 'min:1'],
]);
if ($validator->fails()) {
return $this->apiResponse(false, $validator->errors()->first(), $validator->errors());
}
$query = Menu::query();
$route = $request->route();
$prefix = $route ? $route->getPrefix() : null;
$isClient = $prefix && (str_contains($prefix, '/client') || $prefix === 'client');
if ($isClient && $request->has('category_id')) {
$category = \App\Models\Category::find($request->category_id);
if (!$category || !$category->isActive) {
return $this->apiResponse(false, __('messages.category_not_active'));
}
}
if ($isClient) {
$query->where('isActive', true);
}
$query->orderBy('menu_id', 'asc');
if ($request->has('category_id')) {
$query->where('category_id', $request->category_id);
}
$perPage = $request->per_page ?? config('custom.paginationItem');
$menus = $query->paginate($perPage);
$data = [
'content' => MenuResource::collection($menus),
'pagination' => [
'total' => $menus->total(),
'per_page' => $menus->perPage(),
'current_page' => $menus->currentPage(),
'last_page' => $menus->lastPage(),
'from' => $menus->firstItem(),
'to' => $menus->lastItem(),
]
];
return $this->apiResponse(true, __('messages.menus_fetched'), $data);
}
public function store(Request $request)
{
$validator = Validator::make($request->all(), [
'title.en' => ['required', 'string'],
'title.it' => ['required', 'string'],
'description.en' => ['nullable', 'string'],
'description.it' => ['nullable', 'string'],
'menu_id' => ['nullable', 'integer'],
'price' => ['required', 'numeric'],
'image' => ['nullable', 'image'],
'isActive' => ['nullable', 'boolean'],
'category_id' => ['required', 'exists:categories,id'],
]);
if ($validator->fails()) {
return $this->apiResponse(false, $validator->errors()->first(), $validator->errors());
}
try {
DB::beginTransaction();
$menu = new Menu();
$menu->title = $request->title;
$menu->description = $request->description;
$menu->menu_id = $request->menu_id;
$menu->price = $request->price;
$menu->isActive = $request->isActive ?? true;
$menu->category_id = $request->category_id;
$menu->save();
if ($request->has('menu_id')) {
$menu->menu_id = $request->menu_id;
}else{
$menu->menu_id = $menu->id;
}
if ($request->image) {
$prefix = 'menu';
$imagePath = $this->uploadFile($request->image, $prefix, false);
$menu->image = $imagePath;
$menu->save();
}
DB::commit();
$menu->refresh();
$data = new MenuResource($menu);
$message = __('messages.menu_created');
return $this->apiResponse(true, $message, $data);
} catch (\Throwable $exception) {
DB::rollBack();
return $this->apiResponse(false, $exception->getMessage());
}
}
public function showMcp($id)
{
$menu = Menu::where('menu_id', $id)->firstOrFail();
if (!$menu) {
return $this->apiResponse(false, __('messages.menu_not_found'));
}
return $this->apiResponse(true, __('messages.menu_fetched'), new MenuResource($menu));
}
public function updateMcp(Request $request, $id)
{
$validator = Validator::make($request->all(), [
'title.en' => ['sometimes', 'string'],
'title.it' => ['sometimes', 'string'],
'description.en' => ['sometimes', 'string'],
'description.it' => ['sometimes', 'string'],
'price' => ['sometimes', 'numeric'],
'image' => ['nullable', 'image'],
]);
if ($validator->fails()) {
return $this->apiResponse(false, $validator->errors()->first(), $validator->errors());
}
try {
DB::beginTransaction();
$menu = Menu::where('menu_id', $id)->firstOrFail();
if ($request->has('title')) {
$menu->title = $request->title;
}
if ($request->has('description')) {
$menu->description = $request->description;
}
if ($request->has('price')) {
$menu->price = $request->price;
}
if ($request->image) {
$prefix = 'menu';
$menu->image = $this->updateFile($request->image, $menu->image, $prefix, false);
}
$menu->save();
DB::commit();
$menu->refresh();
$data = new MenuResource($menu);
$message = __('messages.menu_updated');
return $this->apiResponse(true, $message, $data);
} catch (\Throwable $exception) {
DB::rollBack();
return $this->apiResponse(false, $exception->getMessage());
}
}
public function show($id)
{
$menu = Menu::find($id);
if (!$menu) {
return $this->apiResponse(false, __('messages.menu_not_found'));
}
return $this->apiResponse(true, __('messages.menu_fetched'), new MenuResource($menu));
}
public function update(Request $request, $id)
{
$validator = Validator::make($request->all(), [
'title.en' => ['sometimes', 'string'],
'title.it' => ['sometimes', 'string'],
'description.en' => ['sometimes', 'string'],
'description.it' => ['sometimes', 'string'],
'menu_id' => ['sometimes', 'integer'],
'price' => ['sometimes', 'numeric'],
'image' => ['nullable', 'image'],
'isActive' => ['sometimes', 'boolean'],
'category_id' => ['sometimes', 'exists:categories,id'],
]);
if ($validator->fails()) {
return $this->apiResponse(false, $validator->errors()->first(), $validator->errors());
}
try {
DB::beginTransaction();
$menu = Menu::findOrFail($id);
if ($request->has('title')) {
$menu->title = $request->title;
}
if ($request->has('description')) {
$menu->description = $request->description;
}
if ($request->has('menu_id')) {
$menu->menu_id = $request->menu_id;
}
if ($request->has('price')) {
$menu->price = $request->price;
}
if ($request->has('isActive')) {
$menu->isActive = $request->isActive;
}
if ($request->has('category_id')) {
$menu->category_id = $request->category_id;
}
if ($request->image) {
$prefix = 'menu';
$menu->image = $this->updateFile($request->image, $menu->image, $prefix, false);
}
$menu->save();
DB::commit();
$menu->refresh();
$data = new MenuResource($menu);
$message = __('messages.menu_updated');
return $this->apiResponse(true, $message, $data);
} catch (\Throwable $exception) {
DB::rollBack();
return $this->apiResponse(false, $exception->getMessage());
}
}
public function destroy($id)
{
try {
DB::beginTransaction();
$menu = Menu::find($id);
if (!$menu) {
return $this->apiResponse(false, __('messages.menu_not_found'));
}
if ($menu->image) {
$this->deleteFile($menu->image);
}
$menu->delete();
DB::commit();
return $this->apiResponse(true, __('messages.menu_deleted'));
} catch (\Throwable $exception) {
return $this->apiResponse(false, $exception->getMessage());
}
}
}

View File

@@ -0,0 +1,24 @@
<?php
namespace App\Http\Controllers;
use App\Models\Setting;
use App\Traits\ApiResponseHelper;
use Illuminate\Http\Request;
class SettingController extends Controller
{
use ApiResponseHelper;
//
public function index(Request $request)
{
try {
$settings = Setting::latest()->get();
$message = 'Success';
return $this->apiResponse(true, $message, $settings);
} catch (\Throwable $exception) {
return $this->apiResponse(false, $exception->getMessage());
}
}
}

View File

@@ -0,0 +1,68 @@
<?php
namespace App\Http\Controllers;
use App\Traits\ApiResponseHelper;
use Artisan;
use Illuminate\Http\Request;
class SetupController extends Controller
{
use ApiResponseHelper;
//
public function migrateFreshSeed(Request $request)
{
try{
Artisan::call("migrate:fresh --seed");
return $this->apiResponse(true, "Fresh Database migrated + seeded successfully");
}catch(e){
return $this->apiResponse(false, e->getMessage());
}
}
public function migrateFresh(Request $request)
{
try{
Artisan::call("migrate:fresh");
return $this->apiResponse(true, "Fresh Database migrated successfully");
}catch(e){
return $this->apiResponse(false, e->getMessage());
}
}
public function migrate(Request $request)
{
try{
Artisan::call("migrate");
return $this->apiResponse(true, "Database migrated successfully");
}catch(e){
return $this->apiResponse(false, e->getMessage());
}
}
public function seed(Request $request)
{
try{
Artisan::call("db:seed");
return $this->apiResponse(true, "Data Seeding success");
}catch(e){
return $this->apiResponse(false, e->getMessage());
}
}
public function clearCache(Request $request)
{
try{
Artisan::call("config:clear");
Artisan::call("cache:clear");
return $this->apiResponse(true, "Cache cleared successfully");
}catch(e){
return $this->apiResponse(false, e->getMessage());
}
}
}

72
app/Http/Kernel.php Normal file
View File

@@ -0,0 +1,72 @@
<?php
namespace App\Http;
use Illuminate\Foundation\Http\Kernel as HttpKernel;
class Kernel extends HttpKernel
{
/**
* The application's global HTTP middleware stack.
*
* These middleware are run during every request to your application.
*
* @var array<int, class-string|string>
*/
protected $middleware = [
// \App\Http\Middleware\TrustHosts::class,
\App\Http\Middleware\TrustProxies::class,
\Illuminate\Http\Middleware\HandleCors::class,
\App\Http\Middleware\PreventRequestsDuringMaintenance::class,
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
\App\Http\Middleware\TrimStrings::class,
\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
// \App\Http\Middleware\KeyChecker::class,
];
/**
* The application's route middleware groups.
*
* @var array<string, array<int, class-string|string>>
*/
protected $middlewareGroups = [
'web' => [
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
'api' => [
\Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
\Illuminate\Routing\Middleware\ThrottleRequests::class.':api',
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
];
/**
* The application's middleware aliases.
*
* Aliases may be used instead of class names to conveniently assign middleware to routes and groups.
*
* @var array<string, class-string|string>
*/
protected $middlewareAliases = [
'auth' => \App\Http\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'auth.session' => \Illuminate\Session\Middleware\AuthenticateSession::class,
'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
'can' => \Illuminate\Auth\Middleware\Authorize::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class,
'precognitive' => \Illuminate\Foundation\Http\Middleware\HandlePrecognitiveRequests::class,
'signed' => \App\Http\Middleware\ValidateSignature::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
'keyChecker' => \App\Http\Middleware\KeyChecker::class,
'locale' => \App\Http\Middleware\LocaleMiddleware::class
];
}

View File

@@ -0,0 +1,17 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Auth\Middleware\Authenticate as Middleware;
use Illuminate\Http\Request;
class Authenticate extends Middleware
{
/**
* Get the path the user should be redirected to when they are not authenticated.
*/
protected function redirectTo(Request $request): ?string
{
return $request->expectsJson() ? null : route('login');
}
}

View File

@@ -0,0 +1,17 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Cookie\Middleware\EncryptCookies as Middleware;
class EncryptCookies extends Middleware
{
/**
* The names of the cookies that should not be encrypted.
*
* @var array<int, string>
*/
protected $except = [
//
];
}

View File

@@ -0,0 +1,33 @@
<?php
namespace App\Http\Middleware;
use App\Traits\ApiResponseHelper;
use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
class KeyChecker
{
use ApiResponseHelper;
/**
* Handle an incoming request.
*
* @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next
*/
public function handle(Request $request, Closure $next): Response
{
$header = $request->header('Secret');
if (!empty($header)) {
if($header == "fe1ca9859cefff19959d57aadc17187e"){
return $next($request);
}else{
return $this->apiResponse(false, 'Un-Authenticated Request');
}
} else {
return $this->apiResponse(false, 'Un Authenticated Request');
}
}
}

View File

@@ -0,0 +1,19 @@
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
class LocaleMiddleware
{
public function handle(Request $request, Closure $next)
{
$locale = $request->header('Accept-Language', 'en');
if (!in_array($locale, ['en', 'it'])) {
$locale = 'en';
}
app()->setLocale($locale);
return $next($request);
}
}

View File

@@ -0,0 +1,17 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Foundation\Http\Middleware\PreventRequestsDuringMaintenance as Middleware;
class PreventRequestsDuringMaintenance extends Middleware
{
/**
* The URIs that should be reachable while maintenance mode is enabled.
*
* @var array<int, string>
*/
protected $except = [
//
];
}

View File

@@ -0,0 +1,30 @@
<?php
namespace App\Http\Middleware;
use App\Providers\RouteServiceProvider;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Symfony\Component\HttpFoundation\Response;
class RedirectIfAuthenticated
{
/**
* Handle an incoming request.
*
* @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next
*/
public function handle(Request $request, Closure $next, string ...$guards): Response
{
$guards = empty($guards) ? [null] : $guards;
foreach ($guards as $guard) {
if (Auth::guard($guard)->check()) {
return redirect(RouteServiceProvider::HOME);
}
}
return $next($request);
}
}

View File

@@ -0,0 +1,19 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Foundation\Http\Middleware\TrimStrings as Middleware;
class TrimStrings extends Middleware
{
/**
* The names of the attributes that should not be trimmed.
*
* @var array<int, string>
*/
protected $except = [
'current_password',
'password',
'password_confirmation',
];
}

View File

@@ -0,0 +1,20 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Http\Middleware\TrustHosts as Middleware;
class TrustHosts extends Middleware
{
/**
* Get the host patterns that should be trusted.
*
* @return array<int, string|null>
*/
public function hosts(): array
{
return [
$this->allSubdomainsOfApplicationUrl(),
];
}
}

View File

@@ -0,0 +1,28 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Http\Middleware\TrustProxies as Middleware;
use Illuminate\Http\Request;
class TrustProxies extends Middleware
{
/**
* The trusted proxies for this application.
*
* @var array<int, string>|string|null
*/
protected $proxies;
/**
* The headers that should be used to detect proxies.
*
* @var int
*/
protected $headers =
Request::HEADER_X_FORWARDED_FOR |
Request::HEADER_X_FORWARDED_HOST |
Request::HEADER_X_FORWARDED_PORT |
Request::HEADER_X_FORWARDED_PROTO |
Request::HEADER_X_FORWARDED_AWS_ELB;
}

View File

@@ -0,0 +1,22 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Routing\Middleware\ValidateSignature as Middleware;
class ValidateSignature extends Middleware
{
/**
* The names of the query string parameters that should be ignored.
*
* @var array<int, string>
*/
protected $except = [
// 'fbclid',
// 'utm_campaign',
// 'utm_content',
// 'utm_medium',
// 'utm_source',
// 'utm_term',
];
}

View File

@@ -0,0 +1,17 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as Middleware;
class VerifyCsrfToken extends Middleware
{
/**
* The URIs that should be excluded from CSRF verification.
*
* @var array<int, string>
*/
protected $except = [
//
];
}

View File

@@ -0,0 +1,51 @@
<?php
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource;
class AdminCategoryWithMenusResource extends JsonResource
{
public function toArray($request)
{
$title = json_decode($this->getRawOriginal('title'), true);
$description = json_decode($this->getRawOriginal('description'), true);
return [
'title' => [
'en' => $title['en'] ?? '',
'it' => $title['it'] ?? '',
],
'description' => [
'en' => $description['en'] ?? '',
'it' => $description['it'] ?? '',
],
'sortingIndex' => $this->sortingIndex,
'isActive' => $this->isActive,
'thumbnail' => $this->thumbnail,
'created_at' => $this->created_at,
'updated_at' => $this->updated_at,
'menus' => $this->menus->map(function ($menu) {
$menuTitle = json_decode($menu->getRawOriginal('title'), true);
$menuDescription = json_decode($menu->getRawOriginal('description'), true);
return [
'id' => $menu->id, // Removed as per request
'menu_id' => $menu->menu_id,
'title' => [
'en' => $menuTitle['en'] ?? '',
'it' => $menuTitle['it'] ?? '',
],
'description' => [
'en' => $menuDescription['en'] ?? '',
'it' => $menuDescription['it'] ?? '',
],
'price' => $menu->price,
'image' => $menu->image,
'isActive' => $menu->isActive,
//'category_id' => $menu->category_id, // Removed as per request
'created_at' => $menu->created_at,
'updated_at' => $menu->updated_at,
];
})
];
}
}

View File

@@ -0,0 +1,26 @@
<?php
namespace App\Http\Resources;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
use App\Traits\ImageHelper;
class CategoryResource extends JsonResource
{
use ImageHelper;
public function toArray(Request $request): array
{
return [
'id' => $this->id,
'title' => $this->title,
'description' => $this->description,
'sortingIndex' => $this->sortingIndex,
'isActive' => $this->isActive,
'thumbnail' => $this->getFileFullUrl($this->thumbnail),
'created_at' => $this->created_at,
'updated_at' => $this->updated_at,
];
}
}

View File

@@ -0,0 +1,25 @@
<?php
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource;
use App\Traits\ImageHelper;
class MenuResource extends JsonResource
{
use ImageHelper;
public function toArray($request)
{
return [
'id' => $this->id,
'menu_id' => $this->menu_id,
'title' => $this->title,
'description' => $this->description,
'price' => $this->price,
'image' => $this->getFileFullUrl($this->image),
'isActive' => $this->isActive,
'category_id' => $this->category_id,
];
}
}

View File

@@ -0,0 +1,33 @@
<?php
namespace App\Http\Resources;
use App\Traits\ImageHelper;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
class UserResource extends JsonResource
{
use ImageHelper;
/**
* Transform the resource into an array.
*
* @return array<string, mixed>
*/
public function toArray(Request $request): array
{
return [
"id" => $this->id,
"name" => $this->name,
"email" => $this->email,
"country_code" => $this->country_code,
"phone" => $this->phone,
"image" => $this->getFileFullUrl($this->image),
"type" => $this->type,
"email_verified_at" => $this->email_verified_at,
"phone_verified_at" => $this->phone_verified_at,
"status" => $this->status,
"status_reason" => $this->status_reason,
];
}
}

54
app/Models/Category.php Normal file
View File

@@ -0,0 +1,54 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Category extends Model
{
use HasFactory;
protected $fillable = [
'title',
'description',
'sortingIndex',
'isActive',
'thumbnail',
];
protected $casts = [
'title' => 'array',
'description' => 'array',
'isActive' => 'boolean',
];
public function getTitleAttribute($value)
{
$locale = app()->getLocale();
$titles = is_array($value) ? $value : json_decode($value, true);
return $titles[$locale] ?? $titles['en'] ?? '';
}
public function getDescriptionAttribute($value)
{
$locale = app()->getLocale();
$descriptions = is_array($value) ? $value : json_decode($value, true);
return $descriptions[$locale] ?? $descriptions['en'] ?? '';
}
public function setTitleAttribute($value)
{
$this->attributes['title'] = json_encode($value);
}
public function setDescriptionAttribute($value)
{
$this->attributes['description'] = json_encode($value);
}
public function menus()
{
return $this->hasMany(Menu::class);
}
}

57
app/Models/Menu.php Normal file
View File

@@ -0,0 +1,57 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Menu extends Model
{
use HasFactory;
protected $fillable = [
'menu_id',
'title',
'description',
'price',
'image',
'isActive',
'category_id',
];
protected $casts = [
'menu_id' => 'integer',
'title' => 'array',
'description' => 'array',
'isActive' => 'boolean',
];
public function getTitleAttribute($value)
{
$locale = app()->getLocale();
$titles = is_array($value) ? $value : json_decode($value, true);
return $titles[$locale] ?? $titles['en'] ?? '';
}
public function getDescriptionAttribute($value)
{
$locale = app()->getLocale();
$descriptions = is_array($value) ? $value : json_decode($value, true);
return $descriptions[$locale] ?? $descriptions['en'] ?? '';
}
public function setTitleAttribute($value)
{
$this->attributes['title'] = json_encode($value);
}
public function setDescriptionAttribute($value)
{
$this->attributes['description'] = json_encode($value);
}
public function category()
{
return $this->belongsTo(Category::class);
}
}

11
app/Models/Setting.php Normal file
View File

@@ -0,0 +1,11 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Setting extends Model
{
use HasFactory;
}

51
app/Models/User.php Normal file
View File

@@ -0,0 +1,51 @@
<?php
namespace App\Models;
// use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens;
class User extends Authenticatable
{
use HasApiTokens, HasFactory, Notifiable;
/**
* The attributes that are mass assignable.
*
* @var array<int, string>
*/
protected $fillable = [
'name',
'email',
'country_code',
'phone',
'password',
'image',
'how_hear_about_us'
];
/**
* The attributes that should be hidden for serialization.
*
* @var array<int, string>
*/
protected $hidden = [
'password',
'remember_token',
];
/**
* The attributes that should be cast.
*
* @var array<string, string>
*/
protected $casts = [
'email_verified_at' => 'datetime',
'password' => 'hashed',
];
}

View File

@@ -0,0 +1,24 @@
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*/
public function register(): void
{
//
}
/**
* Bootstrap any application services.
*/
public function boot(): void
{
//
}
}

View File

@@ -0,0 +1,26 @@
<?php
namespace App\Providers;
// use Illuminate\Support\Facades\Gate;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
class AuthServiceProvider extends ServiceProvider
{
/**
* The model to policy mappings for the application.
*
* @var array<class-string, class-string>
*/
protected $policies = [
//
];
/**
* Register any authentication / authorization services.
*/
public function boot(): void
{
//
}
}

View File

@@ -0,0 +1,19 @@
<?php
namespace App\Providers;
use Illuminate\Support\Facades\Broadcast;
use Illuminate\Support\ServiceProvider;
class BroadcastServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*/
public function boot(): void
{
Broadcast::routes();
require base_path('routes/channels.php');
}
}

View File

@@ -0,0 +1,38 @@
<?php
namespace App\Providers;
use Illuminate\Auth\Events\Registered;
use Illuminate\Auth\Listeners\SendEmailVerificationNotification;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\Event;
class EventServiceProvider extends ServiceProvider
{
/**
* The event to listener mappings for the application.
*
* @var array<class-string, array<int, class-string>>
*/
protected $listen = [
Registered::class => [
SendEmailVerificationNotification::class,
],
];
/**
* Register any events for your application.
*/
public function boot(): void
{
//
}
/**
* Determine if events and listeners should be automatically discovered.
*/
public function shouldDiscoverEvents(): bool
{
return false;
}
}

View File

@@ -0,0 +1,40 @@
<?php
namespace App\Providers;
use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\RateLimiter;
use Illuminate\Support\Facades\Route;
class RouteServiceProvider extends ServiceProvider
{
/**
* The path to your application's "home" route.
*
* Typically, users are redirected here after authentication.
*
* @var string
*/
public const HOME = '/home';
/**
* Define your route model bindings, pattern filters, and other route configuration.
*/
public function boot(): void
{
RateLimiter::for('api', function (Request $request) {
return Limit::perMinute(60)->by($request->user()?->id ?: $request->ip());
});
$this->routes(function () {
Route::middleware('api')
->prefix('api')
->group(base_path('routes/api.php'));
Route::middleware('web')
->group(base_path('routes/web.php'));
});
}
}

View File

@@ -0,0 +1,22 @@
<?php
namespace App\Traits;
trait ApiResponseHelper
{
/*
* @param array|string $data
* @param string $message
* @param int $code
* @return \Illuminate\Http\JsonResponse
*/
protected function apiResponse(bool $status, string $message = null, $data = [], $code = 200)
{
return response()->json([
'status' => $status,
'message' => $message ?? '',
'data' => $data ?? ''
], $code);
}
}

131
app/Traits/ImageHelper.php Normal file
View File

@@ -0,0 +1,131 @@
<?php
namespace App\Traits;
use Illuminate\Http\File;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
use Intervention\Image\Facades\Image;
trait ImageHelper
{
use MimeToExtensionHelper;
// Direct paths without symlinks
public $uploads_path = "uploads/";
public $public_uploads_path = "public/uploads/";
public function uploadPDF($file, $prefix): string
{
$fileName = '';
if ($file) {
$extension = $file->getClientOriginalExtension();
$fileName = $prefix . '_' . Str::random(30) . '.' . $extension;
// Create directory in public folder if it doesn't exist
$uploadPath = public_path($this->uploads_path);
if (!file_exists($uploadPath)) {
mkdir($uploadPath, 0755, true);
}
// Move file directly to public directory
$file->move($uploadPath, $fileName);
}
return '/' . $this->uploads_path . $fileName;
}
public function uploadFile($file, $prefix, bool $isEncoded): string
{
if ($isEncoded) {
$file = $this->create_file_from_base64($file);
}
$imagePath = '';
if ($file) {
$extension = $file->getClientOriginalExtension();
$fileName = $prefix . '_' . Str::random(30) . '.' . $extension;
// Create directory in public folder if it doesn't exist
$uploadPath = public_path($this->uploads_path);
if (!file_exists($uploadPath)) {
mkdir($uploadPath, 0755, true);
}
// Full path to save the file
$filePath = $uploadPath . $fileName;
// Process with Intervention Image
$img = Image::make($file);
// You can add image manipulation here if needed
// $img->resize(800, null, function ($constraint) {
// $constraint->aspectRatio();
// $constraint->upsize();
// });
// Save directly to public directory
$imagePath = $img->save($filePath) ? '/' . $this->uploads_path . $fileName : '';
}
return $imagePath;
}
public function create_file_from_base64($base64File): UploadedFile
{
$fileData = base64_decode(Arr::last(explode(',', $base64File)));
// Get MimeType
$fileInfo = finfo_open();
$mimeType = finfo_buffer($fileInfo, $fileData, FILEINFO_MIME_TYPE);
// Get Extension from MimeType
$ext = $this->mime2ext($mimeType);
// Save it to temporary dir first
$tempFilePath = sys_get_temp_dir() . '/' . Str::uuid()->toString() . '.' . $ext;
file_put_contents($tempFilePath, $fileData);
$tempFileObject = new File($tempFilePath);
return new UploadedFile(
$tempFileObject->getPathname(),
$tempFileObject->getFilename(),
$tempFileObject->getMimeType(),
0,
true
);
}
public function getFileFullUrl($file): null|string
{
if ($file) {
return App::make('url')->to('/') . $file;
}
return NULL;
}
public function updateFile($file, $existingFile, $prefix, bool $isEncoded): bool|string
{
if ($existingFile) {
$this->deleteFile($existingFile);
}
return $this->uploadFile($file, $prefix, $isEncoded);
}
public function deleteFile($file): bool
{
// Remove leading slash if present
if (str_starts_with($file, '/')) {
$file = substr($file, 1);
}
$filePath = public_path($file);
if (file_exists($filePath)) {
unlink($filePath);
return true;
}
return false;
}
}

View File

@@ -0,0 +1,191 @@
<?php
namespace App\Traits;
trait MimeToExtensionHelper {
public function mime2ext($mime): bool|string
{
$mime_map = [
'video/3gpp2' => '3g2',
'video/3gp' => '3gp',
'video/3gpp' => '3gp',
'application/x-compressed' => '7zip',
'audio/x-acc' => 'aac',
'audio/ac3' => 'ac3',
'application/postscript' => 'ai',
'audio/x-aiff' => 'aif',
'audio/aiff' => 'aif',
'audio/x-au' => 'au',
'video/x-msvideo' => 'avi',
'video/msvideo' => 'avi',
'video/avi' => 'avi',
'application/x-troff-msvideo' => 'avi',
'application/macbinary' => 'bin',
'application/mac-binary' => 'bin',
'application/x-binary' => 'bin',
'application/x-macbinary' => 'bin',
'image/bmp' => 'bmp',
'image/x-bmp' => 'bmp',
'image/x-bitmap' => 'bmp',
'image/x-xbitmap' => 'bmp',
'image/x-win-bitmap' => 'bmp',
'image/x-windows-bmp' => 'bmp',
'image/ms-bmp' => 'bmp',
'image/x-ms-bmp' => 'bmp',
'application/bmp' => 'bmp',
'application/x-bmp' => 'bmp',
'application/x-win-bitmap' => 'bmp',
'application/cdr' => 'cdr',
'application/coreldraw' => 'cdr',
'application/x-cdr' => 'cdr',
'application/x-coreldraw' => 'cdr',
'image/cdr' => 'cdr',
'image/x-cdr' => 'cdr',
'zz-application/zz-winassoc-cdr' => 'cdr',
'application/mac-compactpro' => 'cpt',
'application/pkix-crl' => 'crl',
'application/pkcs-crl' => 'crl',
'application/x-x509-ca-cert' => 'crt',
'application/pkix-cert' => 'crt',
'text/css' => 'css',
'text/x-comma-separated-values' => 'csv',
'text/comma-separated-values' => 'csv',
'application/vnd.msexcel' => 'csv',
'application/x-director' => 'dcr',
'application/vnd.openxmlformats-officedocument.wordprocessingml.document' => 'docx',
'application/x-dvi' => 'dvi',
'message/rfc822' => 'eml',
'application/x-msdownload' => 'exe',
'video/x-f4v' => 'f4v',
'audio/x-flac' => 'flac',
'video/x-flv' => 'flv',
'image/gif' => 'gif',
'application/gpg-keys' => 'gpg',
'application/x-gtar' => 'gtar',
'application/x-gzip' => 'gzip',
'application/mac-binhex40' => 'hqx',
'application/mac-binhex' => 'hqx',
'application/x-binhex40' => 'hqx',
'application/x-mac-binhex40' => 'hqx',
'text/html' => 'html',
'image/x-icon' => 'ico',
'image/x-ico' => 'ico',
'image/vnd.microsoft.icon' => 'ico',
'text/calendar' => 'ics',
'application/java-archive' => 'jar',
'application/x-java-application' => 'jar',
'application/x-jar' => 'jar',
'image/jp2' => 'jp2',
'video/mj2' => 'jp2',
'image/jpx' => 'jp2',
'image/jpm' => 'jp2',
'image/jpeg' => 'jpeg',
'image/pjpeg' => 'jpeg',
'application/x-javascript' => 'js',
'application/json' => 'json',
'text/json' => 'json',
'application/vnd.google-earth.kml+xml' => 'kml',
'application/vnd.google-earth.kmz' => 'kmz',
'text/x-log' => 'log',
'audio/x-m4a' => 'm4a',
'application/vnd.mpegurl' => 'm4u',
'audio/midi' => 'mid',
'application/vnd.mif' => 'mif',
'video/quicktime' => 'mov',
'video/x-sgi-movie' => 'movie',
'audio/mpeg' => 'mp3',
'audio/mpg' => 'mp3',
'audio/mpeg3' => 'mp3',
'audio/mp3' => 'mp3',
'video/mp4' => 'mp4',
'video/mpeg' => 'mpeg',
'application/oda' => 'oda',
'audio/ogg' => 'ogg',
'video/ogg' => 'ogg',
'application/ogg' => 'ogg',
'application/x-pkcs10' => 'p10',
'application/pkcs10' => 'p10',
'application/x-pkcs12' => 'p12',
'application/x-pkcs7-signature' => 'p7a',
'application/pkcs7-mime' => 'p7c',
'application/x-pkcs7-mime' => 'p7c',
'application/x-pkcs7-certreqresp' => 'p7r',
'application/pkcs7-signature' => 'p7s',
'application/pdf' => 'pdf',
'application/octet-stream' => 'pdf',
'application/x-x509-user-cert' => 'pem',
'application/x-pem-file' => 'pem',
'application/pgp' => 'pgp',
'application/x-httpd-php' => 'php',
'application/php' => 'php',
'application/x-php' => 'php',
'text/php' => 'php',
'text/x-php' => 'php',
'application/x-httpd-php-source' => 'php',
'image/png' => 'png',
'image/x-png' => 'png',
'application/powerpoint' => 'ppt',
'application/vnd.ms-powerpoint' => 'ppt',
'application/vnd.ms-office' => 'ppt',
'application/msword' => 'doc',
'application/vnd.openxmlformats-officedocument.presentationml.presentation' => 'pptx',
'application/x-photoshop' => 'psd',
'image/vnd.adobe.photoshop' => 'psd',
'audio/x-realaudio' => 'ra',
'audio/x-pn-realaudio' => 'ram',
'application/x-rar' => 'rar',
'application/rar' => 'rar',
'application/x-rar-compressed' => 'rar',
'audio/x-pn-realaudio-plugin' => 'rpm',
'application/x-pkcs7' => 'rsa',
'text/rtf' => 'rtf',
'text/richtext' => 'rtx',
'video/vnd.rn-realvideo' => 'rv',
'application/x-stuffit' => 'sit',
'application/smil' => 'smil',
'text/srt' => 'srt',
'image/svg+xml' => 'svg',
'application/x-shockwave-flash' => 'swf',
'application/x-tar' => 'tar',
'application/x-gzip-compressed' => 'tgz',
'image/tiff' => 'tiff',
'text/plain' => 'txt',
'text/x-vcard' => 'vcf',
'application/videolan' => 'vlc',
'text/vtt' => 'vtt',
'audio/x-wav' => 'wav',
'audio/wave' => 'wav',
'audio/wav' => 'wav',
'application/wbxml' => 'wbxml',
'video/webm' => 'webm',
'audio/x-ms-wma' => 'wma',
'application/wmlc' => 'wmlc',
'video/x-ms-wmv' => 'wmv',
'video/x-ms-asf' => 'wmv',
'application/xhtml+xml' => 'xhtml',
'application/excel' => 'xl',
'application/msexcel' => 'xls',
'application/x-msexcel' => 'xls',
'application/x-ms-excel' => 'xls',
'application/x-excel' => 'xls',
'application/x-dos_ms_excel' => 'xls',
'application/xls' => 'xls',
'application/x-xls' => 'xls',
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' => 'xlsx',
'application/vnd.ms-excel' => 'xlsx',
'application/xml' => 'xml',
'text/xml' => 'xml',
'text/xsl' => 'xsl',
'application/xspf+xml' => 'xspf',
'application/x-compress' => 'z',
'application/x-zip' => 'zip',
'application/zip' => 'zip',
'application/x-zip-compressed' => 'zip',
'application/s-compressed' => 'zip',
'multipart/x-zip' => 'zip',
'text/x-scriptzsh' => 'zsh',
];
return isset($mime_map[$mime]) === true ? $mime_map[$mime] : false;
}
}

View File

@@ -0,0 +1,121 @@
<?php
namespace App\Traits;
use App\Models\Setting;
trait OneSignalHelper
{
public function setupEnvironmentForServiceProvider(): array
{
$appKey = "7dc8528d-f184-4902-a478-7785b795d5df";
$secretKey = "os_v2_app_pxeffdprqreqfjdyo6c3pfov34dbi44ywtle6xewpet3244pdtkzvrzrc63gl4hmeavupgz3i6hch5wge6f7u2li4dvylyhjp5d6mna";
return [
'appKey' => $appKey,
'secretKey' => $secretKey
];
}
public function setupEnvironmentForClients(): array
{
$appKey = "1abab490-0768-468e-92ca-1512f8b65f90";
$secretKey = "os_v2_app_dk5ljeahnbdi5ewkcujprns7sc4xhmzg6iaujlvl3bdnayojmdoeubourulpnfjru7pf55mlgydnvdhqqmxgw2ipbvcivmn3ravacfy";
return [
'appKey' => $appKey,
'secretKey' => $secretKey
];
}
public function sendAppNotification(string $notificationTitle, string $notificationContent, string $userType)
{
$configuration = $userType === "client"
? $this->setupEnvironmentForClients()
: $this->setupEnvironmentForServiceProvider();
$fields = [
'app_id' => $configuration['appKey'],
'included_segments' => ['All'],
'headings' => ['en' => $notificationTitle],
'contents' => ['en' => $notificationContent],
];
$jsonFields = json_encode($fields);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://onesignal.com/api/v1/notifications");
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Content-Type: application/json; charset=utf-8',
'Authorization: Basic ' . $configuration['secretKey']
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $jsonFields);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
}
public function sendNotificationToSingleUser(
string $notificationTitle,
string $notificationContent,
string $notificationId,
string $userType
) {
$fcmServerKey = "";
return;
if (!empty($notificationId)) {
return response()->json(['error' => 'User or FCM token not found.'], 404);
}
$fcmToken = $user->fcm_token;
$notification = [
'to' => $fcmToken,
'notification' => [
'title' => $notificationTitle,
'body' => $notificationContent,
'sound' => 'default',
],
'data' => [
'notification_id' => $notificationId,
'click_action' => 'FLUTTER_NOTIFICATION_CLICK'
],
'priority' => 'high'
];
$headers = [
'Authorization: key=' . $fcmServerKey,
'Content-Type: application/json'
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://fcm.googleapis.com/fcm/send');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // You can set this to true in production
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($notification));
$result = curl_exec($ch);
$error = curl_error($ch);
curl_close($ch);
if ($error) {
return response()->json(['error' => $error], 500);
}
return response()->json(['response' => json_decode($result)], 200);
}
}