addRemoveSomething('comment', $id, $request, $_format, 'comment', Comment::class); } public function confirmApi($id, Request $request, $_format): Response { /** @var AccompanyingPeriod $accompanyingPeriod */ $accompanyingPeriod = $this->getEntity('participation', $id, $request); $this->checkACL('confirm', $request, $_format, $accompanyingPeriod); $workflow = $this->registry->get($accompanyingPeriod); if (false === $workflow->can($accompanyingPeriod, 'confirm')) { // throw new BadRequestException('It is not possible to confirm this period'); $errors = $this->validator->validate($accompanyingPeriod, null, [$accompanyingPeriod::STEP_CONFIRMED]); if (\count($errors) > 0) { return $this->json($errors, 422); } } $workflow->apply($accompanyingPeriod, 'confirm'); $this->managerRegistry->getManager()->flush(); return $this->json($accompanyingPeriod, Response::HTTP_OK, [], [ 'groups' => ['read'], ]); } #[Route(path: '/api/1.0/person/accompanying-course/list/by-recent-attributions')] public function findMyRecentCourseAttribution(Request $request): JsonResponse { $this->denyAccessUnlessGranted('ROLE_USER'); $user = $this->getUser(); if (!$user instanceof User) { throw new AccessDeniedException(); } $since = (new \DateTimeImmutable('now'))->sub(new \DateInterval('P15D')); $total = $this->accompanyingPeriodRepository->countByRecentUserHistory($user, $since); if ($request->query->getBoolean('countOnly', false)) { return new JsonResponse( $this->getSerializer()->serialize(new Counter($total), 'json'), JsonResponse::HTTP_OK, [], true ); } $paginator = $this->getPaginatorFactory()->create($total); if (0 === $total) { return new JsonResponse( $this->getSerializer()->serialize(new Collection([], $paginator), 'json'), JsonResponse::HTTP_OK, [], true ); } $courses = $this->accompanyingPeriodRepository->findByRecentUserHistory( $user, $since, $paginator->getItemsPerPage(), $paginator->getCurrentPageFirstItemNumber() ); return new JsonResponse( $this->getSerializer()->serialize(new Collection($courses, $paginator), 'json', ['groups' => ['read']]), JsonResponse::HTTP_OK, [], true ); } /** * @ParamConverter("person", options={"id": "person_id"}) */ public function getAccompanyingPeriodsByPerson(Person $person) { $accompanyingPeriods = $person->getCurrentAccompanyingPeriods(); $accompanyingPeriodsChecked = array_filter( $accompanyingPeriods, fn (AccompanyingPeriod $period) => $this->isGranted(AccompanyingPeriodVoter::SEE, $period) ); return $this->json(\array_values($accompanyingPeriodsChecked), Response::HTTP_OK, [], ['groups' => ['read']]); } public function participationApi($id, Request $request, $_format) { /** @var AccompanyingPeriod $accompanyingPeriod */ $accompanyingPeriod = $this->getEntity('participation', $id, $request); $person = $this->getSerializer() ->deserialize($request->getContent(), Person::class, $_format, []); if (null === $person) { throw new BadRequestHttpException('person id not found'); } // TODO add acl // $this->onPostCheckACL('participation', $request, $_format, $accompanyingPeriod); $participation = match ($request->getMethod()) { Request::METHOD_POST => $accompanyingPeriod->createParticipationFor($person), Request::METHOD_DELETE => $accompanyingPeriod->closeParticipationFor($person), default => throw new BadRequestHttpException('This method is not supported'), }; $errors = $this->validator->validate($accompanyingPeriod); if ($errors->count() > 0) { // only format accepted return $this->json($errors, 422); } $this->managerRegistry->getManager()->flush(); return $this->json($participation, 200, [], ['groups' => ['read']]); } public function requestorApi($id, Request $request, string $_format): Response { /** @var AccompanyingPeriod $accompanyingPeriod */ $action = 'requestor'; $accompanyingPeriod = $this->getEntity($action, $id, $request); // a requestor may be a person or a thirdParty $this->checkACL($action, $request, $_format, $accompanyingPeriod); $this->onPostCheckACL($action, $request, $_format, $accompanyingPeriod); if (Request::METHOD_DELETE === $request->getMethod()) { $accompanyingPeriod->setRequestor(null); } elseif (Request::METHOD_POST === $request->getMethod()) { $requestor = null; $exceptions = []; try { $requestor = $this->getSerializer()->deserialize( $request->getContent(), '@multi', $_format, [DiscriminatedObjectDenormalizer::ALLOWED_TYPES => [Person::class, ThirdParty::class]] ); } catch (RuntimeException $e) { $exceptions[] = $e; } if (null === $requestor) { throw new BadRequestHttpException('Could not find any person or thirdparty'); } $accompanyingPeriod->setRequestor($requestor); } else { throw new BadRequestHttpException('method not supported'); } $errors = $this->validator->validate($accompanyingPeriod); if ($errors->count() > 0) { // only format accepted return $this->json($errors, 422); } $this->managerRegistry->getManager()->flush(); return $this->json($accompanyingPeriod->getRequestor(), 200, [], ['groups' => ['read']]); } public function resourceApi($id, Request $request, string $_format): Response { $accompanyingPeriod = $this->getEntity('resource', $id, $request); $errors = $this->validator->validate($accompanyingPeriod); if ($errors->count() > 0) { return $this->json($errors, 422); } return $this->addRemoveSomething('resource', $id, $request, $_format, 'resource', Resource::class); } public function scopeApi($id, Request $request, string $_format): Response { return $this->addRemoveSomething('scope', $id, $request, $_format, 'scope', Scope::class, ['groups' => ['read']]); } public function socialIssueApi($id, Request $request, string $_format): Response { return $this->addRemoveSomething('socialissue', $id, $request, $_format, 'socialIssue', SocialIssue::class, ['groups' => ['read']]); } #[Route(path: '/api/1.0/person/accompanying-course/{id}/referrers-suggested.{_format}', requirements: ['_format' => 'json'], name: 'chill_api_person_accompanying_period_referrers_suggested')] public function suggestReferrals(AccompanyingPeriod $period, string $_format = 'json'): JsonResponse { $this->denyAccessUnlessGranted(AccompanyingPeriodVoter::EDIT, $period); $total = $this->referralAvailable->countReferralSuggested($period); $paginator = $this->getPaginatorFactory()->create($total); if (0 < $total) { $users = $this->referralAvailable->findReferralSuggested( $period, $paginator->getItemsPerPage(), $paginator->getCurrentPageFirstItemNumber() ); } else { $users = []; } return $this->json( new Collection($users, $paginator), Response::HTTP_OK, [], [AbstractNormalizer::GROUPS => ['read']] ); } /** * @ParamConverter("accompanyingCourse", options={"id": "id"}) */ #[Route(path: '/api/1.0/person/accompanying-course/{id}/confidential.json', name: 'chill_api_person_accompanying_period_confidential')] public function toggleConfidentialApi(AccompanyingPeriod $accompanyingCourse, mixed $id, Request $request) { if ('POST' === $request->getMethod()) { $this->denyAccessUnlessGranted(AccompanyingPeriodVoter::TOGGLE_CONFIDENTIAL, $accompanyingCourse); $accompanyingCourse->setConfidential(!$accompanyingCourse->isConfidential()); $this->managerRegistry->getManager()->flush(); } return $this->json($accompanyingCourse->isConfidential(), Response::HTTP_OK, [], ['groups' => ['read']]); } /** * @ParamConverter("accompanyingCourse", options={"id": "id"}) */ #[Route(path: '/api/1.0/person/accompanying-course/{id}/intensity.json', name: 'chill_api_person_accompanying_period_intensity')] public function toggleIntensityApi(AccompanyingPeriod $accompanyingCourse, Request $request) { if ('POST' === $request->getMethod()) { $this->denyAccessUnlessGranted(AccompanyingPeriodVoter::TOGGLE_INTENSITY, $accompanyingCourse); $status = 'regular' === $accompanyingCourse->getIntensity() ? 'occasional' : 'regular'; $accompanyingCourse->setIntensity($status); $this->managerRegistry->getManager()->flush(); } return $this->json($accompanyingCourse->getIntensity(), Response::HTTP_OK, [], ['groups' => ['read']]); } public function workApi($id, Request $request, string $_format): Response { return $this->addRemoveSomething( 'work', $id, $request, $_format, 'work', AccompanyingPeriodWork::class, ['groups' => ['accompanying_period_work:create']], true // force persist ); } protected function onPostCheckACL(string $action, Request $request, string $_format, $entity): ?Response { $this->eventDispatcher->dispatch( new AccompanyingPeriodPrivacyEvent($entity, [ 'action' => $action, 'request' => $request->getMethod(), ]), AccompanyingPeriodPrivacyEvent::ACCOMPANYING_PERIOD_PRIVACY_EVENT ); return null; } protected function validate(string $action, Request $request, string $_format, $entity, array $more = []): ConstraintViolationListInterface { if ('work' !== $action) { return parent::validate($action, $request, $_format, $entity, $more); } if (Request::METHOD_POST === $request->getMethod()) { return $this->getValidator()->validate($more[0], null); } return new ConstraintViolationList([]); } }