Files
kulakpos_web/public/restaurant/Modules/RestaurantDelivery/app/Traits/HasRestaurant.php

158 lines
4.4 KiB
PHP
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
declare(strict_types=1);
namespace Modules\RestaurantDelivery\Traits;
use Illuminate\Auth\Access\AuthorizationException;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Modules\Authentication\Models\Restaurant;
/**
* HasRestaurant Trait
*
* Automatically scopes queries by restaurant_id for multi-restaurant setup.
* Ensures that all records are linked to a restaurant and prevents cross-restaurant access.
*/
trait HasRestaurant
{
/**
* Boot the trait and add global scope
*/
public static function bootHasRestaurant(): void
{
// Global scope: filter by current restaurant automatically
static::addGlobalScope('restaurant', function (Builder $builder) {
if (! config('restaurant-delivery.multi_restaurant.enabled', true)) {
return;
}
$restaurantId = static::getCurrentRestaurantId();
if ($restaurantId) {
$builder->where($builder->getModel()->getTable().'.restaurant_id', $restaurantId);
}
});
// Auto-set restaurant_id on creating
static::creating(function ($model) {
if (! config('restaurant-delivery.multi_restaurant.enabled', true)) {
return;
}
if (empty($model->restaurant_id)) {
$model->restaurant_id = static::getCurrentRestaurantId();
}
});
}
/**
* Get current restaurant ID from helper, auth, session, or header
*/
public static function getCurrentRestaurantId(): ?int
{
// 1⃣ Helper function
if (function_exists('getUserRestaurantId')) {
$restaurantId = getUserRestaurantId();
if ($restaurantId) {
return (int) $restaurantId;
}
}
// 2⃣ Authenticated user
if (auth()->check()) {
$user = auth()->user();
if (! empty($user->restaurant_id)) {
return (int) $user->restaurant_id;
}
if (method_exists($user, 'getRestaurantId')) {
return (int) $user->getRestaurantId();
}
if (method_exists($user, 'restaurant') && $user->restaurant) {
return (int) $user->restaurant->id;
}
}
// 3⃣ Session
if (session()->has('restaurant_id')) {
return (int) session('restaurant_id');
}
// 4⃣ Request header (API)
if (request()->hasHeader('X-Restaurant-ID')) {
return (int) request()->header('X-Restaurant-ID');
}
return null;
}
/**
* Scope to remove restaurant filter (admin or global queries)
*/
public function scopeWithoutRestaurant(Builder $query): Builder
{
return $query->withoutGlobalScope('restaurant');
}
/**
* Scope to filter for a specific restaurant
*/
public function scopeForRestaurant(Builder $query, int $restaurantId): Builder
{
return $query->withoutGlobalScope('restaurant')
->where($this->getTable().'.restaurant_id', $restaurantId);
}
/**
* Relationship to the Restaurant model
*/
public function restaurant(): BelongsTo
{
$restaurantModel = config(
'restaurant-delivery.multi_restaurant.restaurant_model',
Restaurant::class
);
return $this->belongsTo($restaurantModel, 'restaurant_id');
}
/**
* Check if this record belongs to the current restaurant
*/
public function belongsToCurrentRestaurant(): bool
{
$currentId = static::getCurrentRestaurantId();
return $currentId && $this->restaurant_id === $currentId;
}
/**
* Enforce that this record belongs to the current restaurant
*
* @throws AuthorizationException
*/
public function ensureRestaurantOwnership(): void
{
if (! $this->belongsToCurrentRestaurant()) {
throw new AuthorizationException('Access denied: record belongs to another restaurant.');
}
}
/**
* Helper to optionally auto-scope queries for a specific restaurant or all
*/
public static function queryForRestaurant(?int $restaurantId = null): Builder
{
$builder = static::query();
if ($restaurantId) {
return $builder->forRestaurant($restaurantId);
}
return $builder;
}
}