387 lines
16 KiB
PHP
387 lines
16 KiB
PHP
<?php
|
|
namespace App\Services\Cti;
|
|
|
|
use App\Models\Amministratore;
|
|
use App\Models\User;
|
|
use App\Support\StabileContext;
|
|
use Illuminate\Support\Arr;
|
|
use Illuminate\Support\Facades\Schema;
|
|
|
|
class PbxRoutingService
|
|
{
|
|
public function normalizeExtension(?string $extension): string
|
|
{
|
|
$digits = preg_replace('/\D+/', '', (string) $extension);
|
|
|
|
return is_string($digits) ? $digits : '';
|
|
}
|
|
|
|
public function normalizeLineNumber(?string $line): string
|
|
{
|
|
$digits = preg_replace('/\D+/', '', (string) $line);
|
|
|
|
return is_string($digits) ? $digits : '';
|
|
}
|
|
|
|
/**
|
|
* @return array{extension:string,user_id:int|null,stabile_id:int|null,user:?User,amministratore_id:int|null,studio_role:?string,studio_mode:?string}
|
|
*/
|
|
public function resolveByExtension(?string $extension): array
|
|
{
|
|
$normalized = $this->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 (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' => 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<int,string>
|
|
*/
|
|
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<int,string>
|
|
*/
|
|
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 (method_exists($user, 'stabiliAssegnati')) {
|
|
$amministratoreId = $user->stabiliAssegnati()->value('stabili.amministratore_id');
|
|
}
|
|
|
|
return $amministratoreId ? Amministratore::query()->find((int) $amministratoreId) : null;
|
|
}
|
|
|
|
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;
|
|
}
|
|
}
|