self::$catchAll, 'facility_id' => null, 'rule_id' => null, 'radiologists' => null, ]; } public static function matchStudy(array $dicomHeaders): array { self::initialize(); if (blank($dicomHeaders)) { return self::fallbackRoute(); } foreach (self::$rules as $rule) { $conditions = $rule->conditions()->orderByDesc('priority')->get(); $matchCondition = MatchCondition::from($rule->match_condition); $matches = $matchCondition === MatchCondition::ALL ? $conditions->every(fn ($condition) => self::matchCondition($condition, $dicomHeaders)) : $conditions->contains(fn ($condition) => self::matchCondition($condition, $dicomHeaders)); if ($matches) { return [ 'institute_id' => $rule->institute_id, 'facility_id' => $rule->facility_id, 'rule_id' => $rule->id, 'radiologists' => self::getRadiologists($rule), ]; } } return self::fallbackRoute(); } private static function initialize(): void { if (is_null(self::$rules)) { self::$rules = Cache::remember('dicom.rules', now()->addMinutes(self::CACHE_TTL), fn () => DicomRoutingRule::active() ->with('conditions') ->orderByDesc('priority') ->get() ); } if (is_null(self::$activeRads)) { self::$activeRads = Cache::remember('dicom.rads', now()->addMinutes(self::CACHE_TTL), fn () => User::active() ->role(Role::Radiologist) ->pluck('id') ); } if (self::$catchAll < 0) { self::$catchAll = Organization::where('name', 'CATCH-ALL') ->first('id') ->id; } } private static function matchCondition(DicomRuleCondition $condition, array $dicomHeaders): bool { $dicomTag = $condition->dicom_tag; $dicomValue = $dicomHeaders[$dicomTag] ?? ''; $searchPattern = $condition->search_pattern; $matchMode = MatchMode::from($condition->match_mode); if (! $condition->case_sensitive) { $dicomValue = strtolower($dicomValue); if ($matchMode != MatchMode::Regex) { $searchPattern = strtolower($searchPattern); } } switch ($matchMode) { case MatchMode::Exact: return $dicomValue === $searchPattern; case MatchMode::StartsWith: return str_starts_with($dicomValue, $searchPattern); case MatchMode::EndsWith: return str_ends_with($dicomValue, $searchPattern); case MatchMode::Contains: return str_contains($dicomValue, $searchPattern); case MatchMode::Regex: return preg_match($searchPattern, $dicomValue) === 1; } } private static function getRadiologists(DicomRoutingRule $rule): array { if ($rule->assignment_panel_id) { $panel = AssignmentPanel::active() ->with('radiologists:id') ->find($rule->assignment_panel_id); if ($panel) { $rads = $panel->radiologists->pluck('id')->toArray(); if (! empty($rads)) { // return only existing id from self::$activeRads return array_intersect($rads, self::$activeRads->toArray()); } } } elseif ($rule->radiologist_id) { if (self::$activeRads->contains($rule->radiologist_id)) { return [$rule->radiologist_id]; } } return []; } }