getEntity($request); $activity = $this->activityRepository->find($id); if (!$activity) { throw $this->createNotFoundException('Unable to find Activity entity.'); } if ($activity->getAccompanyingPeriod() instanceof AccompanyingPeriod) { $view = 'ChillActivityBundle:Activity:confirm_deleteAccompanyingCourse.html.twig'; $accompanyingPeriod = $activity->getAccompanyingPeriod(); } else { $view = 'ChillActivityBundle:Activity:confirm_deletePerson.html.twig'; } // TODO // $this->denyAccessUnlessGranted('CHILL_ACTIVITY_DELETE', $activity); $form = $this->createDeleteForm($activity->getId(), $person, $accompanyingPeriod); if ($request->getMethod() === Request::METHOD_DELETE) { $form->handleRequest($request); if ($form->isValid()) { $this->logger->notice('An activity has been removed', [ 'by_user' => $this->getUser()->getUsername(), 'activity_id' => $activity->getId(), 'person_id' => $activity->getPerson() ? $activity->getPerson()->getId() : null, 'comment' => $activity->getComment()->getComment(), 'scope_id' => $activity->getScope() ? $activity->getScope()->getId() : null, 'reasons_ids' => $activity->getReasons() ->map( static fn (ActivityReason $ar): int => $ar->getId() ) ->toArray(), 'type_id' => $activity->getActivityType()->getId(), 'duration' => $activity->getDurationTime() ? $activity->getDurationTime()->format('U') : null, 'date' => $activity->getDate()->format('Y-m-d'), 'attendee' => $activity->getAttendee(), ]); $this->entityManager->remove($activity); $this->entityManager->flush(); $this->addFlash('success', $this->translator ->trans('The activity has been successfully removed.')); $params = $this->buildParamsToUrl($person, $accompanyingPeriod); return $this->redirectToRoute('chill_activity_activity_list', $params); } } if (null === $view) { throw $this->createNotFoundException('Template not found'); } return $this->render($view, [ 'activity' => $activity, 'delete_form' => $form->createView(), 'person' => $person, 'accompanyingCourse' => $accompanyingPeriod, ]); } /** * Displays a form to edit an existing Activity entity. */ public function editAction(int $id, Request $request): Response { $view = null; $entity = $this->activityRepository->find($id); if (null === $entity) { throw $this->createNotFoundException('Unable to find Activity entity.'); } $accompanyingPeriod = $entity->getAccompanyingPeriod(); $person = $entity->getPerson(); if ($entity->getAccompanyingPeriod() instanceof AccompanyingPeriod) { $view = 'ChillActivityBundle:Activity:editAccompanyingCourse.html.twig'; $accompanyingPeriod = $entity->getAccompanyingPeriod(); } else { $view = 'ChillActivityBundle:Activity:editPerson.html.twig'; } // TODO // $this->denyAccessUnlessGranted('CHILL_ACTIVITY_UPDATE', $entity); $form = $this->createForm(ActivityType::class, $entity, [ 'center' => $this->centerResolver->resolveCenters($entity)[0] ?? null, 'role' => 'CHILL_ACTIVITY_UPDATE', 'activityType' => $entity->getActivityType(), 'accompanyingPeriod' => $accompanyingPeriod, ]); if ($form->has('documents')) { $form->add('gendocTemplateId', HiddenType::class, [ 'mapped' => false, 'data' => null, 'attr' => [ // required for js 'data-template-id' => 'data-template-id', ], ]); } $form->handleRequest($request); if ($form->isSubmitted() && $form->isValid()) { $this->entityManager->persist($entity); $this->entityManager->flush(); $params = $this->buildParamsToUrl($person, $accompanyingPeriod); $params['id'] = $entity->getId(); if ($form->has('gendocTemplateId') && null !== $form['gendocTemplateId']->getData()) { return $this->redirectToRoute( 'chill_docgenerator_generate_from_template', [ 'template' => $form->get('gendocTemplateId')->getData(), 'entityClassName' => Activity::class, 'entityId' => $entity->getId(), 'returnPath' => $this->generateUrl('chill_activity_activity_edit', $params), ] ); } $this->addFlash('success', $this->translator->trans('Success : activity updated!')); return $this->redirectToRoute('chill_activity_activity_show', $params); } $deleteForm = $this->createDeleteForm($entity->getId(), $person, $accompanyingPeriod); /* * TODO $event = new PrivacyEvent($person, array( 'element_class' => Activity::class, 'element_id' => $entity->getId(), 'action' => 'edit' )); $this->eventDispatcher->dispatch(PrivacyEvent::PERSON_PRIVACY_EVENT, $event); */ if (null === $view) { throw $this->createNotFoundException('Template not found'); } $activity_array = $this->serializer->normalize($entity, 'json', ['groups' => 'read']); return $this->render($view, [ 'entity' => $entity, 'edit_form' => $form->createView(), 'delete_form' => $deleteForm->createView(), 'person' => $person, 'accompanyingCourse' => $accompanyingPeriod, 'activity_json' => $activity_array, ]); } /** * Lists all Activity entities. */ public function listAction(Request $request): Response { $view = null; $activities = []; [$person, $accompanyingPeriod] = $this->getEntity($request); $filter = $this->buildFilterOrder($person ?? $accompanyingPeriod); $filterArgs = [ 'my_activities' => $filter->getSingleCheckboxData('my_activities'), 'types' => $filter->hasEntityChoice('activity_types') ? $filter->getEntityChoiceData('activity_types') : [], 'jobs' => $filter->hasEntityChoice('jobs') ? $filter->getEntityChoiceData('jobs') : [], 'before' => $filter->getDateRangeData('activity_date')['to'], 'after' => $filter->getDateRangeData('activity_date')['from'], ]; if ($person instanceof Person) { $this->denyAccessUnlessGranted(ActivityVoter::SEE, $person); $count = $this->activityACLAwareRepository->countByPerson($person, ActivityVoter::SEE, $filterArgs); $paginator = $this->paginatorFactory->create($count); $activities = $this->activityACLAwareRepository ->findByPerson( $person, ActivityVoter::SEE, $paginator->getCurrentPageFirstItemNumber(), $paginator->getItemsPerPage(), ['date' => 'DESC', 'id' => 'DESC'], $filterArgs ); $event = new PrivacyEvent($person, [ 'element_class' => Activity::class, 'action' => 'list', ]); $this->eventDispatcher->dispatch(PrivacyEvent::PERSON_PRIVACY_EVENT, $event); $view = 'ChillActivityBundle:Activity:listPerson.html.twig'; } elseif ($accompanyingPeriod instanceof AccompanyingPeriod) { $this->denyAccessUnlessGranted(ActivityVoter::SEE, $accompanyingPeriod); $count = $this->activityACLAwareRepository->countByAccompanyingPeriod($accompanyingPeriod, ActivityVoter::SEE, $filterArgs); $paginator = $this->paginatorFactory->create($count); $activities = $this->activityACLAwareRepository ->findByAccompanyingPeriod( $accompanyingPeriod, ActivityVoter::SEE, $paginator->getCurrentPageFirstItemNumber(), $paginator->getItemsPerPage(), ['date' => 'DESC', 'id' => 'DESC'], $filterArgs ); $view = 'ChillActivityBundle:Activity:listAccompanyingCourse.html.twig'; } else { throw new \LogicException("Unsupported"); } return $this->render( $view, [ 'activities' => $activities, 'person' => $person, 'accompanyingCourse' => $accompanyingPeriod, 'filter' => $filter, 'paginator' => $paginator, ] ); } private function buildFilterOrder(AccompanyingPeriod|Person $associated): FilterOrderHelper { $filterBuilder = $this->filterOrderHelperFactory->create(self::class); $types = $this->activityACLAwareRepository->findActivityTypeByAssociated($associated); $jobs = $this->activityACLAwareRepository->findUserJobByAssociated($associated); $filterBuilder ->addDateRange('activity_date', 'activity.date') ->addSingleCheckbox('my_activities', 'activity_filter.My activities'); if (1 < count($types)) { $filterBuilder ->addEntityChoice('activity_types', 'activity_filter.Types', \Chill\ActivityBundle\Entity\ActivityType::class, $types, [ 'choice_label' => function (\Chill\ActivityBundle\Entity\ActivityType $activityType) { $text = match ($activityType->hasCategory()) { true => $this->translatableStringHelper->localize($activityType->getCategory()->getName()) . ' > ', false => '', }; return $text . $this->translatableStringHelper->localize($activityType->getName()); } ]); } if (1 < count($jobs)) { $filterBuilder ->addEntityChoice('jobs', 'activity_filter.Jobs', UserJob::class, $jobs, [ 'choice_label' => fn (UserJob $u) => $this->translatableStringHelper->localize($u->getLabel()) ]); } return $filterBuilder->build(); } public function newAction(Request $request): Response { $view = null; [$person, $accompanyingPeriod] = $this->getEntity($request); if ($accompanyingPeriod instanceof AccompanyingPeriod) { $view = 'ChillActivityBundle:Activity:newAccompanyingCourse.html.twig'; } elseif ($person instanceof Person) { $view = 'ChillActivityBundle:Activity:newPerson.html.twig'; } $activityType_id = $request->get('activityType_id', 0); $activityType = $this->activityTypeRepository->find($activityType_id); if (isset($activityType) && !$activityType->isActive()) { throw new InvalidArgumentException('Activity type must be active'); } $activityData = null; if ($request->query->has('activityData')) { $activityData = $request->query->get('activityData'); } if ( !$activityType instanceof \Chill\ActivityBundle\Entity\ActivityType || !$activityType->isActive() ) { $params = $this->buildParamsToUrl($person, $accompanyingPeriod); if (null !== $activityData) { $params['activityData'] = $activityData; } return $this->redirectToRoute('chill_activity_activity_select_type', $params); } $entity = new Activity(); $entity->setUser($this->getUser()); if ($person instanceof Person) { $entity->setPerson($person); $entity->getPersons()->add($person); } if ($accompanyingPeriod instanceof AccompanyingPeriod) { $entity->setAccompanyingPeriod($accompanyingPeriod); } $entity->setActivityType($activityType); $entity->setDate(new DateTime('now')); if ($request->query->has('activityData')) { $activityData = $request->query->get('activityData'); if (array_key_exists('durationTime', $activityData) && $activityType->getDurationTimeVisible() > 0) { $durationTimeInMinutes = $activityData['durationTime']; $hours = floor($durationTimeInMinutes / 60); $minutes = $durationTimeInMinutes % 60; $duration = DateTime::createFromFormat('H:i', $hours . ':' . $minutes); if ($duration) { $entity->setDurationTime($duration); } } if (array_key_exists('date', $activityData)) { $date = DateTime::createFromFormat('Y-m-d', $activityData['date']); if ($date) { $entity->setDate($date); } } if (array_key_exists('personsId', $activityData) && $activityType->getPersonsVisible() > 0) { foreach ($activityData['personsId'] as $personId) { $concernedPerson = $this->personRepository->find($personId); $entity->addPerson($concernedPerson); } } if (array_key_exists('professionalsId', $activityData) && $activityType->getThirdPartiesVisible() > 0) { foreach ($activityData['professionalsId'] as $professionalsId) { $professional = $this->thirdPartyRepository->find($professionalsId); $entity->addThirdParty($professional); } } if (array_key_exists('usersId', $activityData) && $activityType->getUsersVisible() > 0) { foreach ($activityData['usersId'] as $userId) { $user = $this->userRepository->find($userId); if (null !== $user) { $entity->addUser($user); } } } if (array_key_exists('location', $activityData) && $activityType->getLocationVisible() > 0) { $location = $this->locationRepository->find($activityData['location']); $entity->setLocation($location); } if (array_key_exists('comment', $activityData) && $activityType->getCommentVisible() > 0) { $comment = new CommentEmbeddable(); $comment->setComment($activityData['comment']); $comment->setUserId($this->getUser()->getid()); $comment->setDate(new DateTime('now')); $entity->setComment($comment); } } $this->denyAccessUnlessGranted(ActivityVoter::CREATE, $entity); $form = $this->createForm(ActivityType::class, $entity, [ 'center' => $this->centerResolver->resolveCenters($entity)[0] ?? null, 'role' => 'CHILL_ACTIVITY_CREATE', 'activityType' => $entity->getActivityType(), 'accompanyingPeriod' => $accompanyingPeriod, ]); if ($form->has('documents')) { $form->add('gendocTemplateId', HiddenType::class, [ 'mapped' => false, 'data' => null, 'attr' => [ // required for js 'data-template-id' => 'data-template-id', ], ]); } $form->handleRequest($request); if ($form->isSubmitted() && $form->isValid()) { $this->entityManager->persist($entity); $this->entityManager->flush(); if ($form->has('gendocTemplateId') && null !== $form['gendocTemplateId']->getData()) { return $this->redirectToRoute( 'chill_docgenerator_generate_from_template', [ 'template' => $form->get('gendocTemplateId')->getData(), 'entityClassName' => Activity::class, 'entityId' => $entity->getId(), 'returnPath' => $this->generateUrl('chill_activity_activity_edit', [ 'id' => $entity->getId(), ]), ] ); } $this->addFlash('success', $this->translator->trans('Success : activity created!')); $params = $this->buildParamsToUrl($person, $accompanyingPeriod); $params['id'] = $entity->getId(); return $this->redirectToRoute('chill_activity_activity_show', $params); } if (null === $view) { throw $this->createNotFoundException('Template not found'); } $activity_array = $this->serializer->normalize($entity, 'json', ['groups' => 'read']); $defaultLocation = $this->getUser()->getCurrentLocation(); return $this->render($view, [ 'person' => $person, 'accompanyingCourse' => $accompanyingPeriod, 'entity' => $entity, 'form' => $form->createView(), 'activity_json' => $activity_array, 'default_location' => $defaultLocation, ]); } public function selectTypeAction(Request $request): Response { $view = null; [$person, $accompanyingPeriod] = $this->getEntity($request); if ($accompanyingPeriod instanceof AccompanyingPeriod) { $view = 'ChillActivityBundle:Activity:selectTypeAccompanyingCourse.html.twig'; } elseif ($person instanceof Person) { $view = 'ChillActivityBundle:Activity:selectTypePerson.html.twig'; } $data = []; $activityTypeCategories = $this ->activityTypeCategoryRepository ->findBy(['active' => true], ['ordering' => 'ASC']); foreach ($activityTypeCategories as $activityTypeCategory) { $activityTypes = $this ->activityTypeRepository ->findBy( ['active' => true, 'category' => $activityTypeCategory], ['ordering' => 'ASC'] ); $data[] = [ 'activityTypeCategory' => $activityTypeCategory, 'activityTypes' => $activityTypes, ]; } if (null === $view) { throw $this->createNotFoundException('Template not found'); } return $this->render($view, [ 'person' => $person, 'accompanyingCourse' => $accompanyingPeriod, 'data' => $data, 'activityData' => $request->query->get('activityData', []), ]); } public function showAction(Request $request, int $id): Response { $entity = $this->activityRepository->find($id); if (null === $entity) { throw $this->createNotFoundException('Unable to find Activity entity.'); } $accompanyingPeriod = $entity->getAccompanyingPeriod(); $person = $entity->getPerson(); if ($accompanyingPeriod instanceof AccompanyingPeriod) { $view = 'ChillActivityBundle:Activity:showAccompanyingCourse.html.twig'; } elseif ($person instanceof Person) { $view = 'ChillActivityBundle:Activity:showPerson.html.twig'; } else { throw new RuntimeException('the activity should be linked with a period or person'); } if (null !== $accompanyingPeriod) { // @TODO: Properties created dynamically. $entity->personsAssociated = $entity->getPersonsAssociated(); $entity->personsNotAssociated = $entity->getPersonsNotAssociated(); } $this->denyAccessUnlessGranted(ActivityVoter::SEE, $entity); $deleteForm = $this->createDeleteForm($entity->getId(), $person, $accompanyingPeriod); // TODO /* $event = new PrivacyEvent($person, array( 'element_class' => Activity::class, 'element_id' => $entity->getId(), 'action' => 'show' )); $this->eventDispatcher->dispatch(PrivacyEvent::PERSON_PRIVACY_EVENT, $event); */ if (null === $view) { throw $this->createNotFoundException('Template not found'); } return $this->render($view, [ 'person' => $person, 'accompanyingCourse' => $accompanyingPeriod, 'entity' => $entity, 'delete_form' => $deleteForm->createView(), ]); } private function buildParamsToUrl(?Person $person, ?AccompanyingPeriod $accompanyingPeriod): array { $params = []; if (null !== $person) { $params['person_id'] = $person->getId(); } if (null !== $accompanyingPeriod) { $params['accompanying_period_id'] = $accompanyingPeriod->getId(); } return $params; } /** * Creates a form to delete a Activity entity by id. */ private function createDeleteForm(int $id, ?Person $person, ?AccompanyingPeriod $accompanyingPeriod): FormInterface { $params = $this->buildParamsToUrl($person, $accompanyingPeriod); $params['id'] = $id; return $this->createFormBuilder() ->setAction($this->generateUrl('chill_activity_activity_delete', $params)) ->setMethod('DELETE') ->add('submit', SubmitType::class, ['label' => 'Delete']) ->getForm(); } private function getEntity(Request $request): array { $person = $accompanyingPeriod = null; if ($request->query->has('person_id')) { $person_id = $request->get('person_id'); $person = $this->personRepository->find($person_id); if (null === $person) { throw $this->createNotFoundException('Person not found'); } $this->denyAccessUnlessGranted('CHILL_PERSON_SEE', $person); } elseif ($request->query->has('accompanying_period_id')) { $accompanying_period_id = $request->get('accompanying_period_id'); $accompanyingPeriod = $this->accompanyingPeriodRepository->find($accompanying_period_id); if (null === $accompanyingPeriod) { throw $this->createNotFoundException('Accompanying Period not found'); } // TODO Add permission // $this->denyAccessUnlessGranted('CHILL_PERSON_SEE', $person); } else { throw $this->createNotFoundException('Person or Accompanying Period not found'); } return [ $person, $accompanyingPeriod, ]; } }