normalizeExtension($extension); if ($normalized === '' || ! Schema::hasColumn('users', 'pbx_extension')) { return [ 'extension' => $normalized, 'user_id' => null, 'stabile_id' => null, 'user' => null, 'amministratore_id' => null, 'studio_role' => null, 'studio_mode' => null, ]; } $studioContext = $this->findStudioContextByExtension($normalized); $user = User::query()->where('pbx_extension', $normalized)->first(); if (! $user) { return [ 'extension' => $normalized, 'user_id' => null, 'stabile_id' => null, 'user' => null, 'amministratore_id' => $studioContext['amministratore_id'], 'studio_role' => $studioContext['studio_role'], 'studio_mode' => $studioContext['studio_mode'], ]; } $stabileId = null; if ($this->canResolveAssignedStabili() && method_exists($user, 'stabiliAssegnati')) { $stabileId = $user->stabiliAssegnati()->value('stabili.id'); } return [ 'extension' => $normalized, 'user_id' => (int) $user->id, 'stabile_id' => $stabileId ? (int) $stabileId : null, 'user' => $user, 'amministratore_id' => $studioContext['amministratore_id'] ?? $this->resolveAmministratoreIdForUser($user), 'studio_role' => $studioContext['studio_role'], 'studio_mode' => $studioContext['studio_mode'], ]; } /** * @return array{line:string,user_id:int|null,stabile_id:int|null,user:?User,amministratore_id:int|null,studio_role:?string,studio_mode:?string,target_extension:string,route_group:string,line_label:?string} */ public function resolveByIncomingLine(?string $line): array { $normalized = $this->normalizeLineNumber($line); $empty = [ 'line' => $normalized, 'user_id' => null, 'stabile_id' => null, 'user' => null, 'amministratore_id' => null, 'studio_role' => null, 'studio_mode' => null, 'target_extension' => '', 'route_group' => '', 'line_label' => null, ]; if ($normalized === '') { return $empty; } foreach (Amministratore::query()->get(['id', 'impostazioni']) as $amministratore) { $incomingLines = array_values(array_filter((array) (($amministratore->impostazioni ?? [])['pbx']['incoming_lines'] ?? []), fn($row): bool => is_array($row))); foreach ($incomingLines as $lineRow) { if (! $this->matchesLineNumber((string) ($lineRow['number'] ?? ''), $normalized)) { continue; } $targetExtension = $this->normalizeExtension((string) ($lineRow['target_extension'] ?? '')); $routeGroup = $this->normalizeExtension((string) ($lineRow['route_group'] ?? '')); $targetRouting = $targetExtension !== '' ? $this->resolveByExtension($targetExtension) : ($routeGroup !== '' ? $this->resolveByExtension($routeGroup) : [ 'user_id' => null, 'stabile_id' => null, 'user' => null, ]); if (($targetRouting['user'] ?? null) === null) { $mappedUser = $this->findUserByLineMapping($amministratore, $normalized); if ($mappedUser instanceof User) { $targetRouting = [ 'user_id' => (int) $mappedUser->id, 'stabile_id' => $this->canResolveAssignedStabili() && method_exists($mappedUser, 'stabiliAssegnati') ? ((int) ($mappedUser->stabiliAssegnati()->value('stabili.id') ?? 0) ?: null): null, 'user' => $mappedUser, ]; } } return [ 'line' => $normalized, 'user_id' => (int) ($targetRouting['user_id'] ?? 0) ?: null, 'stabile_id' => (int) ($targetRouting['stabile_id'] ?? 0) ?: null, 'user' => $targetRouting['user'] ?? null, 'amministratore_id' => (int) $amministratore->id, 'studio_role' => 'linea', 'studio_mode' => filled($lineRow['label'] ?? null) ? (string) $lineRow['label'] : null, 'target_extension' => $targetExtension, 'route_group' => $routeGroup, 'line_label' => filled($lineRow['label'] ?? null) ? (string) $lineRow['label'] : null, ]; } } return $empty; } /** * @return array{extension:string,line:string,user_id:int|null,stabile_id:int|null,user:?User,amministratore_id:int|null,studio_role:?string,studio_mode:?string,target_extension:string,route_group:string,line_label:?string} */ public function resolveBySmdr(?string $extension, ?string $line, ?string $direction): array { $normalizedDirection = strtolower(trim((string) $direction)); $extensionRouting = $this->resolveByExtension($extension); $lineRouting = $this->resolveByIncomingLine($line); if ($normalizedDirection === 'inbound' && ($lineRouting['amministratore_id'] ?? null) !== null) { return [ 'extension' => $extensionRouting['extension'], 'line' => $lineRouting['line'], 'user_id' => $lineRouting['user_id'] ?? $extensionRouting['user_id'], 'stabile_id' => $lineRouting['stabile_id'] ?? $extensionRouting['stabile_id'], 'user' => $lineRouting['user'] ?? $extensionRouting['user'], 'amministratore_id' => $lineRouting['amministratore_id'], 'studio_role' => $lineRouting['studio_role'], 'studio_mode' => $lineRouting['studio_mode'], 'target_extension' => $lineRouting['target_extension'], 'route_group' => $lineRouting['route_group'], 'line_label' => $lineRouting['line_label'], ]; } return [ 'extension' => $extensionRouting['extension'], 'line' => $lineRouting['line'], 'user_id' => $extensionRouting['user_id'], 'stabile_id' => $extensionRouting['stabile_id'], 'user' => $extensionRouting['user'], 'amministratore_id' => $extensionRouting['amministratore_id'] ?? $lineRouting['amministratore_id'], 'studio_role' => $extensionRouting['studio_role'], 'studio_mode' => $extensionRouting['studio_mode'] ?? $lineRouting['studio_mode'], 'target_extension' => '', 'route_group' => '', 'line_label' => $lineRouting['line_label'], ]; } /** * @return array */ public function getWatchedExtensionsForUser(User $user): array { $extensions = []; $userExtension = $this->normalizeExtension((string) ($user->pbx_extension ?? '')); if ($userExtension !== '') { $extensions[] = $userExtension; } $amministratore = $this->resolveAmministratoreForUser($user); if ($amministratore) { $extensions = array_merge($extensions, $this->getStudioExtensionsForAmministratore($amministratore)); } return array_values(array_unique(array_filter($extensions, fn($extension): bool => is_string($extension) && $extension !== ''))); } /** * @return array */ public function getStudioExtensionsForAmministratore(Amministratore $amministratore): array { $pbx = (array) (($amministratore->impostazioni ?? [])['pbx'] ?? []); $centralino = (array) (($amministratore->impostazioni ?? [])['centralino'] ?? []); $extensions = [ $this->normalizeExtension((string) Arr::get($centralino, 'interno_centralino', '')), $this->normalizeExtension((string) Arr::get($centralino, 'interno_operatore', '')), $this->normalizeExtension((string) Arr::get($centralino, 'interno_amministratore', '')), $this->normalizeExtension((string) Arr::get($centralino, 'interno_gruppo_giorno', '')), $this->normalizeExtension((string) Arr::get($centralino, 'interno_gruppo_notte', '')), ]; $watchExtensions = preg_split('/\s*,\s*/', (string) ($pbx['watch_extensions'] ?? ''), -1, PREG_SPLIT_NO_EMPTY) ?: []; foreach ($watchExtensions as $extension) { $extensions[] = $this->normalizeExtension((string) $extension); } foreach ((array) ($pbx['response_groups'] ?? []) as $group) { if (! is_array($group)) { continue; } $extensions[] = $this->normalizeExtension((string) ($group['extension'] ?? '')); $extensions[] = $this->normalizeExtension((string) ($group['target_extension'] ?? '')); } foreach ((array) ($pbx['incoming_lines'] ?? []) as $line) { if (! is_array($line)) { continue; } $extensions[] = $this->normalizeExtension((string) ($line['route_group'] ?? '')); $extensions[] = $this->normalizeExtension((string) ($line['target_extension'] ?? '')); } return array_values(array_unique(array_filter($extensions, fn($extension): bool => $extension !== ''))); } /** * @return array{amministratore_id:int|null,studio_role:?string,studio_mode:?string} */ public function findStudioContextByExtension(?string $extension): array { $normalized = $this->normalizeExtension($extension); if ($normalized === '') { return [ 'amministratore_id' => null, 'studio_role' => null, 'studio_mode' => null, ]; } foreach (Amministratore::query()->get(['id', 'impostazioni']) as $amministratore) { $pbx = (array) (($amministratore->impostazioni ?? [])['pbx'] ?? []); $centralino = (array) (($amministratore->impostazioni ?? [])['centralino'] ?? []); $map = [ 'interno_centralino' => ['studio_role' => 'centralino', 'studio_mode' => null], 'interno_operatore' => ['studio_role' => 'operatore', 'studio_mode' => null], 'interno_amministratore' => ['studio_role' => 'amministratore', 'studio_mode' => null], 'interno_gruppo_giorno' => ['studio_role' => 'gruppo', 'studio_mode' => 'giorno'], 'interno_gruppo_notte' => ['studio_role' => 'gruppo', 'studio_mode' => 'notte'], ]; foreach ($map as $key => $context) { if ($this->normalizeExtension((string) Arr::get($centralino, $key, '')) !== $normalized) { continue; } return [ 'amministratore_id' => (int) $amministratore->id, 'studio_role' => $context['studio_role'], 'studio_mode' => $context['studio_mode'], ]; } foreach ((array) ($pbx['response_groups'] ?? []) as $group) { if (! is_array($group)) { continue; } if ($this->normalizeExtension((string) ($group['extension'] ?? '')) !== $normalized) { continue; } return [ 'amministratore_id' => (int) $amministratore->id, 'studio_role' => 'gruppo', 'studio_mode' => filled($group['mode'] ?? null) ? (string) $group['mode'] : null, ]; } foreach ((array) ($pbx['incoming_lines'] ?? []) as $line) { if (! is_array($line)) { continue; } $routeExtension = $this->normalizeExtension((string) (($line['route_group'] ?? '') !== '' ? $line['route_group'] : ($line['target_extension'] ?? ''))); if ($routeExtension !== $normalized) { continue; } return [ 'amministratore_id' => (int) $amministratore->id, 'studio_role' => 'linea', 'studio_mode' => filled($line['label'] ?? null) ? (string) $line['label'] : null, ]; } } return [ 'amministratore_id' => null, 'studio_role' => null, 'studio_mode' => null, ]; } private function resolveAmministratoreForUser(User $user): ?Amministratore { if ($user->amministratore instanceof Amministratore) { return $user->amministratore; } $activeStabile = StabileContext::getActiveStabile($user); if ($activeStabile?->amministratore instanceof Amministratore) { return $activeStabile->amministratore; } $amministratoreId = null; if ($this->canResolveAssignedStabili() && method_exists($user, 'stabiliAssegnati')) { $amministratoreId = $user->stabiliAssegnati()->value('stabili.amministratore_id'); } return $amministratoreId ? Amministratore::query()->find((int) $amministratoreId) : null; } private function canResolveAssignedStabili(): bool { return Schema::hasTable('collaboratore_stabile') && Schema::hasTable('stabili'); } private function resolveAmministratoreIdForUser(User $user): ?int { $amministratore = $this->resolveAmministratoreForUser($user); return $amministratore ? (int) $amministratore->id : null; } private function matchesLineNumber(string $configuredLine, string $incomingLine): bool { $configured = $this->normalizeLineNumber($configuredLine); if ($configured === '' || $incomingLine === '') { return false; } return $configured === $incomingLine || ltrim($configured, '0') === ltrim($incomingLine, '0'); } private function findUserByLineMapping(Amministratore $amministratore, string $line): ?User { $mappings = (array) (($amministratore->impostazioni ?? [])['pbx']['user_mappings'] ?? []); foreach ($mappings as $userId => $mapping) { if (! is_array($mapping)) { continue; } $lines = array_values(array_filter((array) ($mapping['lines'] ?? []), fn($value): bool => is_string($value) && trim($value) !== '')); foreach ($lines as $configuredLine) { if (! $this->matchesLineNumber($configuredLine, $line)) { continue; } $user = User::query()->find((int) $userId); if ($user instanceof User) { return $user; } } } return null; } }