contextResolver->resolve($user); if (!$context->isClinic()) { return null; } $doctor = $this->doctorRepo->findByUser($user); return $doctor !== null && $context->clinic->hasDoctor($doctor) ? $context->id : null; } /** * فقط پزشکِ عضوِ کلینیک را با ClinicDoctorPermission محدود کن؛ سایر کاربران true. */ public function canOrNonMember(User $user, string $resource, string $action): bool { $context = $this->contextResolver->resolve($user); if (!$context->isClinic()) { // محیطِ مطب شخصی یا نامشخص → این checker مالِ او نیست. return true; } $clinic = $context->clinic; // مالکِ کلینیک هرگز با مجوزهای عضویت قفل نمی‌شود. if ($clinic->getUser()->getId() === $user->getId()) { return true; } $doctor = $this->doctorRepo->findByUser($user); if ($doctor === null || !$clinic->hasDoctor($doctor)) { // غیرعضو (مثلاً منشی) — این checker مالِ او نیست. return true; } return $this->permissions->can($user, $clinic, $resource, $action); } /** 403 اگر پزشکِ عضو مجاز نباشد؛ سایر کاربران بدون تغییر عبور می‌کنند. */ public function denyUnlessGranted(User $user, string $resource, string $action): void { if (!$this->canOrNonMember($user, $resource, $action)) { throw new AppException(ErrorCodes::ERR_FORBIDDEN_001, null, 403); } } }