Skip to content
Snippets Groups Projects
Select Git revision
  • 5745e62e423931f8097beeda2f6b5eac550137b7
  • main default
  • 35-cgu
  • 34-peertube-support
  • 27-add-autoplay-to-iframe
  • 33-bug-on-youtube-embed-urls
  • RC-Rekall-v1.1-fix_lpo
  • tuleap-140-go-back-to-my-capsules-page-when-i-m-on-capsule-preview-page
  • RC-Rekall-v1.2-fix10
  • RC-Rekall-v1.2-fix9
  • RC-Rekall-v1.2-fix8
  • RC-Rekall-v1.2-fix7
  • RC-Rekall-v1.2-fix6
  • RC-Rekall-v1.2-fix5
  • RC-Rekall-v1.2-fix4
  • RC-Rekall-v1.2-fix3
  • RC-Rekall-v1.2-fix2
  • RC-Rekall-v1.2-fix1
  • RC-Rekall-v1.1-fix-3
  • RC-Rekall-v1.1-fix-2
  • RC-Rekall-v1.1-fix-1
  • RC-Rekall-v1.1-delivered
  • preprod20220209-1535
23 results

CapsuleController.php

Blame
  • CapsuleController.php 13.76 KiB
    <?php
    
    namespace App\Controller;
    
    use App\Entity\Capsule;
    use App\Entity\Group;
    use App\Entity\User;
    use App\Form\DeleteCapsuleFormType;
    use App\Form\DuplicateCapsuleFormType;
    use App\Form\FilterByGroupFormType;
    use App\Helper\StringHelper;
    use App\Repository\CapsuleRepository;
    use App\Builder\CapsuleBuilder;
    use App\Form\CreateCapsuleFormType;
    use Doctrine\ORM\EntityManagerInterface;
    use Knp\Bundle\PaginatorBundle\Pagination\SlidingPagination;
    use Knp\Component\Pager\PaginatorInterface;
    use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
    use Symfony\Component\Filesystem\Filesystem;
    use Symfony\Component\Form\FormInterface;
    use Symfony\Component\HttpFoundation\Request;
    use Symfony\Component\HttpFoundation\Response;
    use Symfony\Component\Routing\Annotation\Route;
    use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
    use Symfony\Component\Uid\Uuid;
    use Symfony\Contracts\HttpClient\HttpClientInterface;
    use Symfony\Contracts\Translation\TranslatorInterface;
    
    class CapsuleController extends AbstractController
    {
        private const DEFAULT_LOCALE = 'en';
    
        public function __construct(
            private CapsuleRepository $capsule_repository,
            private TranslatorInterface $translator,
            private EntityManagerInterface $entity_manager
        ) {
        }
    
    
        #[Route('/')]
        public function indexNoLocale(Request $request): Response
        {
            $locale = self::DEFAULT_LOCALE;
            $current_user = $this->getUser();
    
            if (! $current_user instanceof User) {
                return $this->redirectToRoute('app_logout');
            }
    
            if ($request->getLocale()) {
                $locale = $request->getLocale();
            }
    
            if ($current_user->getLocale()) {
                $locale = $current_user->getLocale();
            }
    
            return $this->redirectToRoute('home', ['_locale' => $locale]);
        }
    
        #[Route('/{_locale<%app.supported_locales%>}/my_capsules', name:'capsule_list')]
        #[Route('/{_locale<%app.supported_locales%>}', name:'home')]
        public function index(
            PaginatorInterface $paginator,
            Request $request,
            HttpClientInterface $http_client
        ): Response {
            $current_user = $this->getUser();
    
            if (! $current_user instanceof User) {
                return $this->redirectToRoute('app_logout');
            }
    
            // get all capsules without any filter
            $all_capsules = $current_user->getCapsules()->toArray();
            $groups = $this->prependGroupAllToUserGroups($current_user);
    
            $group_id = $request->query->getInt('group', Group::$GROUP_ALL_ID);
            $group = $this->getGroupByIdOrNull($groups, $group_id, $groups[0]);
    
            $filter_by_group_form = $this->createForm(
                FilterByGroupFormType::class,
                ['groups' => $groups, 'method' => 'GET', 'selected_group' => $group]
            );
    
            $filter_by_group_form->handleRequest($request);
            if ($filter_by_group_form->isSubmitted() && $filter_by_group_form->isValid()) {
                $group = $filter_by_group_form->getData()['name'];
    
                if (! $group instanceof Group) {
                    throw new \Exception('Group not found');
                }
            }
    
            if ($group instanceof Group && $group->getId() !== Group::$GROUP_ALL_ID) {
                $all_capsules = $group->getCapsules()->toArray();
            }
    
            $nb_elements_per_page = 5;
    
            // Fix the current page.
            // For example, the user is on the page 5 without filter and apply a filter that reduce the number of pages.
            // We display the last page.
            $current_page = min(
                [
                    intval((count($all_capsules) / $nb_elements_per_page) + 1),
                    $request->query->getInt('page', 1)
                ]
            );
            $request->query->set('page', $current_page);
    
            // Pass group param to the paginator (it will be sent as GET data)
            $capsules = $paginator->paginate(
                $all_capsules,
                $current_page,
                $nb_elements_per_page
            );
    
            if ($capsules instanceof SlidingPagination) {
                $capsules->setParam('group', $group->getId());
            }
    
            return $this->renderForm('capsule/index.html.twig', [
                'filterByGroupForm' => $filter_by_group_form,
                'capsules' => $capsules,
                'current_user' => $current_user,
                'legacy_url' => $this->getParameter('app.legacy_external_prefix'),
                'http_client' => $http_client
            ]);
        }
    
        #[Route('/{_locale<%app.supported_locales%>}/create', name:'create_capsule')]
        public function create(Request $request): Response
        {
            $form = $this->createForm(CreateCapsuleFormType::class);
            $form->handleRequest($request);
            $current_user = $this->getUser();
    
            if (! $current_user instanceof User) {
                return $this->redirectToRoute('app_logout');
            }
    
            if ($form->isSubmitted() && $form->isValid()) {
                $video_url =  htmlspecialchars($form->get('video_url')->getData());
    
                $capsule = $this->createCapsuleInDB($form, $current_user);
    
                return $this->forward('App\Controller\ProjectController::create', [
                    'capsule' => $capsule,
                    'video_url' => $video_url
                ]);
            }
    
            return $this->renderForm('capsule/create.html.twig', [
                'capsuleCreationForm' => $form
                ]);
        }
    
        #[Route('/{_locale<%app.supported_locales%>}/capsule/preview/{path}', name:'preview_capsule')]
        public function preview(string $path, UrlGeneratorInterface $urlGenerator): Response
        {
            $file_path = '../legacy/' . $path;
            if (!file_exists($file_path)) {
                return $this->render('project/project_not_found.html.twig');
            }
    
            $url = $this->getParameter('app.legacy_external_prefix') . '/' . $path . "/?w=1";
    
            return $this->render(
                'project/project_view.html.twig',
                [
                    'url' => $url,
                    'linkHome' => $urlGenerator->generate('home', [], UrlGeneratorInterface::ABSOLUTE_URL)
                ]
            );
        }
    
        #[Route('/{_locale<%app.supported_locales%>}/capsule/edit/{path}', name:'edit_capsule')]
        public function edit(string $path, UrlGeneratorInterface $urlGenerator): Response
        {
            $current_user = $this->getUser();
    
            if (! $current_user instanceof User) {
                return $this->redirectToRoute('app_logout');
            }
    
            $capsule = $this->capsule_repository->findOneBy(['link_path' => $path]);
            if (null === $capsule) {
                $this->addFlash('warning', $this->translator->trans('capsule.edit.not_found'));
                return $this->redirectToRoute('capsule_list');
            }
    
            if (! $capsule->getEditors()->contains($current_user)) {
                $this->addFlash('warning', $this->translator->trans('capsule.edit.not_allowed'));
                return $this->redirectToRoute('capsule_list');
            }
    
            $file_path = '../legacy/' . $path;
            if (!file_exists($file_path)) {
                return $this->render('project/project_not_found.html.twig');
            }
    
            $url = $this->getParameter('app.legacy_external_prefix') . '/' . $capsule->getEditionLink();
    
            return $this->render(
                'project/edit.html.twig',
                [
                    'url' => $url,
                    'linkHome' => $urlGenerator->generate(
                        'home',
                        [],
                        UrlGeneratorInterface::ABSOLUTE_URL
                    )
                    ,
                    'linkPreview' => $urlGenerator->generate(
                        'preview_capsule',
                        [ 'path' => $capsule->getLinkPath() ],
                        UrlGeneratorInterface::ABSOLUTE_URL
                    )
                ]
            );
        }
    
        #[Route('/{_locale<%app.supported_locales%>}/capsule/delete/{capsule_id}', name:'delete_capsule')]
        public function delete(
            int $capsule_id,
            Request $request
        ): Response {
            $form = $this->createForm(DeleteCapsuleFormType::class);
            $form->handleRequest($request);
            $current_user = $this->getUser();
    
            if (! $current_user instanceof User) {
                return $this->redirectToRoute('app_logout');
            }
    
            $capsule = $this->capsule_repository->findOneBy(['id' => $capsule_id]);
    
            if (! $capsule) {
                throw $this->createNotFoundException(
                    'No capsule found for id ' . $capsule_id
                );
            }
            $capsule_name = $capsule->getName();
    
            if ($capsule->getCreationAuthor() !== $current_user) {
                $this->addFlash(
                    'warning',
                    $this->translator->trans(
                        'capsule.delete.error',
                        [
                            'capsule_name' => $capsule_name
                        ]
                    )
                );
    
                return $this->redirectToRoute('capsule_list');
            }
    
            if ($form->isSubmitted() && $form->isValid()) {
                $current_user->removeCapsule($capsule);
                $capsule->removeEditor($current_user);
                $this->entity_manager->remove($capsule);
                $this->entity_manager->flush();
    
                $this->addFlash(
                    'success',
                    $this->translator->trans(
                        'capsule.delete.success',
                        [
                            'capsule_name' => $capsule_name
                        ]
                    )
                );
    
                return $this->redirectToRoute('capsule_list');
            }
    
            return $this->renderForm('capsule/delete.html.twig', [
                'deleteCapsuleForm' => $form,
                'capsule_name' => $capsule_name
            ]);
        }
    
        #[Route('/{_locale<%app.supported_locales%>}/capsule/duplicate/{capsule_id}', name:'duplicate_capsule')]
        public function duplicate(
            int $capsule_id,
            Request $request,
            Filesystem $file_system
        ): Response {
            $form = $this->createForm(DuplicateCapsuleFormType::class);
            $form->handleRequest($request);
            $current_user = $this->getUser();
    
            if (! $current_user instanceof User) {
                return $this->redirectToRoute('app_logout');
            }
    
            $parent_capsule = $this->capsule_repository->findOneBy(['id' => $capsule_id]);
    
            if (! $parent_capsule instanceof Capsule) {
                throw new \Exception('The retrieved capsule is not an instance of Capsule.');
            }
    
            $capsule_editors = $parent_capsule->getEditors();
    
            if (! in_array($current_user, $capsule_editors->toArray())) {
                $this->addFlash(
                    'warning',
                    $this->translator->trans(
                        'capsule.duplicate.error',
                        [
                            'capsule_name' => $parent_capsule->getName()
                        ]
                    )
                );
    
                return $this->redirectToRoute('capsule_list');
            }
    
            $parent_directory_name = $parent_capsule->getLinkPath();
            $parent_directory_exists = $file_system->exists('../legacy/' . $parent_directory_name);
            if (! $parent_directory_exists) {
                $this->addFlash(
                    'warning',
                    $this->translator->trans(
                        'project.not_exist',
                        [
                            'capsule_name' => $parent_capsule->getName()
                        ]
                    )
                );
    
                return $this->redirectToRoute('capsule_list');
            }
    
            if ($form->isSubmitted() && $form->isValid()) {
                $capsule = $this->createCapsuleInDB($form, $current_user);
    
                return $this->forward('App\Controller\ProjectController::duplicate', [
                    'capsule' => $capsule,
                    'parent_directory' => $parent_directory_name
                ]);
            }
    
            return $this->renderForm('capsule/duplicate.html.twig', [
                'duplicateCapsuleForm' => $form,
                'capsule_name' => $parent_capsule->getName()
            ]);
        }
    
        private function createCapsuleInDB(FormInterface $form, User $current_user): Capsule
        {
            $new_date_time = new \DateTime();
            $capsule_name = $form->get('name')->getData();
            $password = StringHelper::generateRandomHashedString();
            $preview_link = Uuid::v4();
    
            $capsule_builder = new CapsuleBuilder();
            $capsule = $capsule_builder
                ->withName($capsule_name)
                ->withCreationAuthor($current_user)
                ->withCreationDate($new_date_time)
                ->withLinkPath($preview_link)
                ->withUpdateDate($new_date_time)
                ->withPassword($password)
                ->createCapsule();
    
            $this->entity_manager->persist($capsule);
            $this->entity_manager->flush();
    
            return $capsule;
        }
    
        private function createGroupAll(User $current_user): Group
        {
            $group_all = new Group();
            $group_all->setName($this->translator->trans('groups.filter.no_filter'));
            $group_all->setId(Group::$GROUP_ALL_ID);
            $group_all->setAuthor($current_user);
    
            return $group_all;
        }
    
        /**
         * @return array<Group>
         */
        private function prependGroupAllToUserGroups(User $current_user): array
        {
            $group_all = $this->createGroupAll($current_user);
    
            $author_groups_without_group_all = $current_user->getGroups()->toArray();
            $groups[] = $group_all;
            $groups = array_merge($groups, $author_groups_without_group_all);
    
            return $groups;
        }
    
        /**
         * @param array<Group> $groups
         * @param int|null $id
         * @param Group $defaultGroup The returned group if current groups isn't found
         * @return Group
         */
        private function getGroupByIdOrNull(array $groups, ?int $id, Group $defaultGroup): Group
        {
            if (null === $id) {
                return $defaultGroup;
            }
    
            foreach ($groups as $g) {
                if ($g->getId() === $id) {
                    return $g;
                }
            }
    
            return $defaultGroup;
        }
    }