<?php
declare(strict_types=1);
namespace App\Service;
use App\Entity\Source;
use App\Entity\User;
use App\Entity\Warehouse;
use App\Repository\WarehouseRepository;
use Symfony\Component\HttpFoundation\RequestStack;
class WarehouseContextService
{
private const SESSION_KEY = 'admin_current_warehouse_id';
public function __construct(
private RequestStack $requestStack,
private WarehouseRepository $warehouseRepository
) {
}
/**
* @return Warehouse[]
*/
public function getAccessibleWarehouses(?User $user = null): array
{
if ($user instanceof User) {
try {
if ($user->getWarehouses()->count() > 0) {
$warehouses = array_values(array_filter(
$user->getWarehouses()->toArray(),
static fn ($warehouse): bool => $warehouse instanceof Warehouse && $warehouse->getIsActive()
));
usort($warehouses, static function (Warehouse $a, Warehouse $b): int {
if ($a->getIsDefault() !== $b->getIsDefault()) {
return $a->getIsDefault() ? -1 : 1;
}
return strcasecmp((string) $a->getName(), (string) $b->getName());
});
if ($warehouses !== []) {
return $warehouses;
}
return [];
}
} catch (\Throwable $e) {
// La migration user_warehouse peut ne pas être encore appliquée.
}
}
$warehouses = $this->warehouseRepository->findBy(
['isActive' => true],
['isDefault' => 'DESC', 'name' => 'ASC']
);
if ($warehouses !== []) {
return $warehouses;
}
$fallback = $this->warehouseRepository->findDefault();
return $fallback instanceof Warehouse ? [$fallback] : [];
}
public function getCurrentWarehouse(?User $user = null): ?Warehouse
{
$available = $this->getAccessibleWarehouses($user);
if ($available === []) {
return null;
}
$currentId = $this->getStoredWarehouseId();
if ($currentId === 0) {
return null;
}
if ($currentId !== null) {
foreach ($available as $warehouse) {
if ((int) $warehouse->getId() === $currentId) {
return $warehouse;
}
}
}
if (\count($available) === 1) {
return $this->rememberWarehouse($available[0]);
}
$default = $this->getGlobalDefaultWarehouse();
if ($default instanceof Warehouse) {
foreach ($available as $warehouse) {
if ((int) $warehouse->getId() === (int) $default->getId()) {
return $this->rememberWarehouse($warehouse);
}
}
}
return $this->rememberWarehouse($available[0]);
}
public function getCurrentWarehouseName(?User $user = null, string $fallback = 'Principal'): string
{
if ($this->getStoredWarehouseId() === 0) {
return 'Tous les dépôts';
}
return $this->getCurrentWarehouse($user)?->getName() ?: $fallback;
}
public function setCurrentWarehouseById(?int $warehouseId, ?User $user = null): ?Warehouse
{
if (($warehouseId ?? 0) <= 0) {
return $this->rememberWarehouse(null, true);
}
foreach ($this->getAccessibleWarehouses($user) as $warehouse) {
if ((int) $warehouse->getId() === (int) $warehouseId) {
return $this->rememberWarehouse($warehouse);
}
}
return $this->getCurrentWarehouse($user);
}
public function resolveOperationWarehouse(
?Source $source = null,
?User $user = null,
?Warehouse $preferredWarehouse = null
): ?Warehouse {
if ($preferredWarehouse instanceof Warehouse && $preferredWarehouse->getIsActive()) {
return $preferredWarehouse;
}
$sourceWarehouse = $source?->getDefaultWarehouse();
if ($sourceWarehouse instanceof Warehouse && $sourceWarehouse->getIsActive()) {
return $sourceWarehouse;
}
$current = $this->getCurrentWarehouse($user);
if ($current instanceof Warehouse) {
return $current;
}
$default = $this->getGlobalDefaultWarehouse();
if ($default instanceof Warehouse) {
return $default;
}
$available = $this->getAccessibleWarehouses($user);
return $available[0] ?? null;
}
public function getGlobalDefaultWarehouse(): ?Warehouse
{
$default = $this->warehouseRepository->findDefault();
if ($default instanceof Warehouse) {
return $default;
}
$activeWarehouses = $this->warehouseRepository->findBy(
['isActive' => true],
['isDefault' => 'DESC', 'name' => 'ASC']
);
return $activeWarehouses[0] ?? null;
}
private function getStoredWarehouseId(): ?int
{
$request = $this->requestStack->getCurrentRequest();
if (!$request || !$request->hasSession()) {
return null;
}
if (!$request->getSession()->has(self::SESSION_KEY)) {
return null;
}
$warehouseId = (int) $request->getSession()->get(self::SESSION_KEY, 0);
return $warehouseId > 0 ? $warehouseId : 0;
}
private function rememberWarehouse(?Warehouse $warehouse, bool $allWarehouses = false): ?Warehouse
{
$request = $this->requestStack->getCurrentRequest();
if ($request && $request->hasSession()) {
if ($warehouse instanceof Warehouse && $warehouse->getId() !== null) {
$request->getSession()->set(self::SESSION_KEY, (int) $warehouse->getId());
} elseif ($allWarehouses) {
$request->getSession()->set(self::SESSION_KEY, 0);
} else {
$request->getSession()->remove(self::SESSION_KEY);
}
}
return $warehouse;
}
}