<?php 
 
namespace App\Controller; 
 
use App\Entity\Application; 
use App\Entity\ApplicationParagraph; 
use App\Entity\ApplicationProduct; 
use App\Entity\ApplicationTranslation; 
use App\Entity\Category; 
use App\Entity\Contact; 
use App\Entity\JobOffer; 
use App\Entity\JobOfferParagraph; 
use App\Entity\JobOfferTranslation; 
use App\Entity\Member; 
use App\Entity\Newsletter; 
use App\Entity\Page; 
use App\Entity\Paragraph; 
use App\Entity\Partner; 
use App\Entity\Post; 
use App\Entity\PostMedia; 
use App\Entity\PostTranslation; 
use App\Entity\PresentationParagraph; 
use App\Entity\Product; 
use App\Entity\ProductMedia; 
use App\Entity\ProductTranslation; 
use App\Entity\RelatedProduct; 
use App\Entity\SubCategory; 
use App\Entity\Testimonial; 
use App\Form\ContactType; 
use App\Form\NewsletterType; 
use App\Form\ProductsFilterType; 
use App\Service\AppService; 
use Doctrine\Persistence\ManagerRegistry; 
use Knp\Component\Pager\PaginatorInterface; 
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security; 
use Symfony\Bridge\Twig\Mime\BodyRenderer; 
use Symfony\Bridge\Twig\Mime\TemplatedEmail; 
use Symfony\Bundle\FrameworkBundle\Console\Application as FrameworkApplication; 
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; 
use Symfony\Component\Asset\Packages; 
use Symfony\Component\Console\Input\ArrayInput; 
use Symfony\Component\Console\Output\NullOutput; 
use Symfony\Component\HttpFoundation\Request; 
use Symfony\Component\HttpFoundation\Response; 
use Symfony\Component\HttpFoundation\Session\SessionInterface; 
use Symfony\Component\HttpKernel\KernelInterface; 
use Symfony\Component\Mailer\Mailer; 
use Symfony\Component\Mailer\MailerInterface; 
use Symfony\Component\Mailer\Transport; 
use Symfony\Component\Mime\Email; 
use Symfony\Component\Routing\Annotation\Route; 
use Symfony\Contracts\Translation\TranslatorInterface; 
use Twig\Environment; 
use Twig\Loader\FilesystemLoader; 
use Symfony\Component\Filesystem\Exception\IOExceptionInterface; 
use Symfony\Component\Filesystem\Filesystem; 
use Symfony\Component\Filesystem\Path; 
 
/** 
 * @Route("/{_locale}", requirements={"_locale": "%managed_locales_routing%"}) 
 */ 
class FrontController extends AbstractController 
{ 
    public static $LIMIT_PRODUCTS = 9; 
 
    /** 
     * @Route({ 
     *     "fr": "/changer-la-langue/{locale}/{routeName}/{routeParams}", 
     *     "en": "/change-language/{locale}/{routeName}/{routeParams}" 
     * }, name="front_change_language", requirements={"routeParams"=".+"}) 
     */ 
    public function changeLanguage(Request $request, SessionInterface $session, $locale, $routeName, $routeParams = null) 
    { 
        $routeParams = array_merge(["_locale" => $locale], $_GET); 
        return $this->redirectToRoute($routeName, $routeParams); 
    } 
 
 
    /** 
     * @Route({ 
     *     "fr": "/application/{slug}", 
     *     "en": "/application/{slug}" 
     * }, name="front_application") 
     */ 
    public function application(ManagerRegistry $managerRegistry, Request $request, ApplicationTranslation $applicationTranslation) 
    { 
        $application = $applicationTranslation->getTranslatable(); 
        $repoApplicationParagraph = $managerRegistry->getRepository(ApplicationParagraph::class); 
        $applicationParagraphs = $repoApplicationParagraph->findBy([], ["position" => "asc"]); 
        $repoApplicationProduct = $managerRegistry->getRepository(ApplicationProduct::class); 
        $applicationProducts = $repoApplicationProduct->findBy(["application" => $application], ["position" => "asc"]); 
        return $this->render('front/application.html.twig', array( 
            "application" => $application, 
            "applicationProducts" => $applicationProducts, 
            "applicationParagraphs" => $applicationParagraphs 
        )); 
    } 
 
    /** 
     * @Route({ 
     *     "fr": "/presentation", 
     *     "en": "/presentation" 
     * }, name="front_presentation") 
     */ 
    public function presentation(ManagerRegistry $managerRegistry, Request $request) 
    { 
 
        $repoPresentationParagraph = $managerRegistry->getRepository(PresentationParagraph::class); 
        $presentationParagraphs = $repoPresentationParagraph->findBy(["isOther" => false], ["position" => "asc"]); 
        $otherPresentationParagraphs = $repoPresentationParagraph->findBy(["isOther" => true], ["position" => "asc"]); 
        return $this->render('front/presentation.html.twig', array( 
            "presentationParagraphs" => $presentationParagraphs, 
            "otherPresentationParagraphs" => $otherPresentationParagraphs, 
        )); 
    } 
 
    /** 
     * @Route({ 
     *     "fr": "/produits/{catSlug}/{subCatSlug}", 
     *     "en": "/products/{catSlug}/{subCatSlug}" 
     * }, name="front_products") 
     */ 
    public function products(ManagerRegistry $managerRegistry, PaginatorInterface $paginator, Request $request, $catSlug, $subCatSlug = null) 
    { 
        $repoSubCategory = $managerRegistry->getRepository(SubCategory::class); 
        $subCategory = $repoSubCategory->search(["slug" => $subCatSlug, "limit" => 1]); 
        $repoCategory = $managerRegistry->getRepository(Category::class); 
        $category = $subCategory ? $subCategory->getCategory() : $repoCategory->search(["slug" => $catSlug, "limit" => 1]); 
        $data["orderBy"] = ["a.position", "asc"]; 
        $data["limit"] = self::$LIMIT_PRODUCTS; 
        $data["hide"] = false; 
        $data["searchProducts"] = ["categories" => [], "subCategories" => []]; 
        if (!$request->isXmlHttpRequest()) { 
            if ($subCategory) { 
                $data["searchProducts"]["subCategories"][] = $subCategory; 
            } 
            if ($category) { 
                $data["searchProducts"]["categories"][] = $category; 
            } 
        } 
        $productsFilterForm = $this->createForm(ProductsFilterType::class); 
        $productsFilterForm->handleRequest($request); 
        if ($productsFilterForm->isSubmitted() && $productsFilterForm->isValid()) { 
            $data["searchProducts"] = $productsFilterForm->getData(); 
        } 
        $repoProduct = $managerRegistry->getRepository(Product::class); 
        $products = $repoProduct->search($data); 
        $data['count'] = true; 
        unset($data['offset']); 
        unset($data['limit']); 
        unset($data['orderBy']); 
        $nbProducts = $repoProduct->search($data); 
        $nbProducts = count($nbProducts); 
        $products = (is_array($products) ? $products : ($products ? [$products] : [])); 
        $otherCategories = $repoCategory->search(["different" => ["a.id" => $category->getId()], "isChaine" => false]); 
        $otherSubCategories = $subCategory ? $repoSubCategory->search(["different" => ["a.id" => $subCategory->getId()], "category" => $category]) : []; 
        return $this->render('front/products.html.twig', array( 
            'productsFilterForm' => $productsFilterForm->createView(), 
            "products" => $products, 
            'limit' => self::$LIMIT_PRODUCTS, 
            'total' => $nbProducts, 
            "categoryActive" => $category, 
            "subCategoryActive" => $subCategory, 
            "otherCategories" => $otherCategories, 
            "otherSubCategories" => $otherSubCategories 
        )); 
    } 
 
    /** 
     * @Route({ 
     *     "fr": "/produit/{catSlug}/{subCatSlug}/{slug}", 
     *     "en": "/product/{catSlug}/{subCatSlug}/{slug}", 
     * }, name="front_product") 
     */ 
    public function product(ManagerRegistry $managerRegistry, Request $request, $catSlug, $subCatSlug, ProductTranslation $productTranslation) 
    { 
        $product = $productTranslation->getTranslatable(); 
        $repoRelatedProduct = $managerRegistry->getRepository(RelatedProduct::class); 
        $relatedProducts = $repoRelatedProduct->findBy(["product" => $product], ["position" => "asc"]); 
        $repoProductMedia = $managerRegistry->getRepository(ProductMedia::class); 
        $productMedias = $repoProductMedia->findBy(["product" => $product], ["position" => "asc"]); 
        return $this->render('front/product.html.twig', array( 
            "relatedProducts" => $relatedProducts, 
            "productMedias" => $productMedias, 
            "product" => $product 
        )); 
    } 
 
    /** 
     * @Route({ 
     *     "fr": "/mentions-legales", 
     *     "en": "/legal-terms", 
     * }, name="front_privacy_policy") 
     */ 
    public function privacyPolicy(ManagerRegistry $managerRegistry, Request $request) 
    { 
 
        return $this->render('front/privacyPolicy.html.twig', array()); 
    } 
 
    /** 
     * @Route({ 
     *     "fr": "/", 
     *     "en": "/", 
     * }, name="front_landing") 
     */ 
    public function landing(Request $request, ManagerRegistry $managerRegistry): Response 
    { 
        $repoPartner = $managerRegistry->getRepository(Partner::class); 
        $partners = $repoPartner->findBy([], ["position" => "asc"]); 
        $repoPost = $managerRegistry->getRepository(Post::class); 
        $data["between"]["notStrict"]["a.date"]["max"] = new \DateTime(); 
        $data["orderBy"] = ["a.date", "desc"]; 
        $data["isPublished"] = true; 
        $data["limit"] = 3; 
        $posts = $repoPost->search($data); 
        $repoTestimonial = $managerRegistry->getRepository(Testimonial::class); 
        $testimonials = $repoTestimonial->findBy([], ["position" => "asc"]); 
        $repoApplication = $managerRegistry->getRepository(Application::class); 
        $applications = $repoApplication->findBy(["displayOnLanding" => true], ["position" => "asc"]); 
        return $this->render('front/landing.html.twig', [ 
            "applications" => $applications, 
            "posts" => $posts, 
            "partners" => $partners, 
            "testimonials" => $testimonials, 
        ]); 
    } 
 
    /** 
     * @Route({ 
     *     "fr": "/offres-d-emploi", 
     *     "en": "/job-offers", 
     * }, name="front_job_offers") 
     */ 
    public function jobOffers(ManagerRegistry $managerRegistry, Request $request) 
    { 
        $repoJobOffer = $managerRegistry->getRepository(JobOffer::class); 
        $jobOffers = $repoJobOffer->findBy([], ["position" => "asc"]); 
        return $this->render('front/jobOffers.html.twig', array( 
            "jobOffers" => $jobOffers 
        )); 
    } 
 
    /** 
     * @Route({ 
     *     "fr": "/offre-d-emploi/{slug}", 
     *     "en": "/job-offer/{slug}", 
     * }, name="front_job_offer") 
     */ 
    public function jobOffer(ManagerRegistry $managerRegistry, Request $request, JobOfferTranslation $jobOfferTranslation) 
    { 
        $jobOffer = $jobOfferTranslation->getTranslatable(); 
        $repoJobOfferParagraph = $managerRegistry->getRepository(JobOfferParagraph::class); 
        $jobOfferParagraphs = $repoJobOfferParagraph->findBy(["jobOffer" => $jobOffer], ["position" => "asc"]); 
        return $this->render('front/jobOffer.html.twig', array( 
            "jobOffer" => $jobOffer, 
            "jobOfferParagraphs" => $jobOfferParagraphs, 
        )); 
    } 
 
    public function sitemap(Request $request, Packages $packages) 
    { 
        $repoPage = $this->getDoctrine()->getRepository(Page::class); 
        $page = $repoPage->search(["notNull" => ["a.sitemapFileName"], "limit" => 1]); 
        if ($page and $page->getSitemapFileName()) { 
            return $this->redirect($packages->getUrl('upload/sitemap/' . $page->getSitemapFileName())); 
        } else { 
            return $this->redirectToRoute('front_landing'); 
        } 
    } 
 
    /** 
     * @Route({ 
     *     "fr": "/contactez-nous/{slug}", 
     *     "en": "/contact-us/{slug}", 
     * }, name="front_contact", defaults={"slug":null}) 
     */ 
    public function contact(Request $request, ManagerRegistry $managerRegistry, TranslatorInterface $translator, $slug = null) 
    { 
        $repoProduct = $managerRegistry->getRepository(Product::class); 
        $product = $slug ? $repoProduct->search(["slug" => $slug, "limit" => 1]) : null; 
        $contact = new Contact(); 
        $contactForm = $this->createForm(ContactType::class, $contact, [ 
            "product" => $product 
        ]); 
        $contactForm->handleRequest($request); 
        if ($contactForm->isSubmitted() && $contactForm->isValid()) { 
            $recaptchaResponse = $request->request->get('g-recaptcha-response', null); 
            $isRecaptchaValid = false; 
            if ($recaptchaResponse) { 
                $paramsArr = array( 
                    "response" => $recaptchaResponse, 
                    "secret" => $this->getParameter('recaptchaSecret') 
                ); 
                $ch = curl_init(); 
                curl_setopt($ch, CURLOPT_URL, "https://www.google.com/recaptcha/api/siteverify"); 
                curl_setopt($ch, CURLOPT_POST, 1); 
                curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($paramsArr)); 
                curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 
                $isRecaptchaValid = json_decode(curl_exec($ch))->success; 
            } 
            if (!$isRecaptchaValid) { 
                $this->addFlash("danger", "Veuillez recommencer en validant le captcha."); 
            } else { 
                $em = $managerRegistry->getManager(); 
                $em->persist($contact); 
                $em->flush(); 
                $this->addFlash("success", "Message envoyé."); 
                $transport = Transport::fromDsn($this->getParameter('mailer_dsn')); 
                $mailer = new Mailer($transport); 
                $subject = ("Nouveau message : " . $contact->getSubject() . " " . $contact->getCity()); 
                $email = (new TemplatedEmail()) 
                    ->from($this->getParameter('mailer_user')) 
                    ->to("facomia.sarl@facomia.com") 
                    ->subject($subject) 
                    // path of the Twig template to render 
                    ->htmlTemplate('mail/contact.html.twig') 
                    // pass variables (name => value) to the template 
                    ->context(["contact" => $contact]); 
                if ($contact->getEmail()) { 
                    $email 
                        ->replyTo($contact->getEmail()); 
                } 
                foreach ($contact->getCustomFiles() as $key => $customFile) { 
                    $email->attachFromPath(("upload/customFile/" . $customFile->getCustomFileFileName())); 
                } 
                $loader = new FilesystemLoader($this->getParameter('kernel.project_dir') . '/templates/'); 
                $twigEnv = new Environment($loader); 
                $twigBodyRenderer = new BodyRenderer($twigEnv); 
                $twigBodyRenderer->render($email); 
                $mailer->send($email); 
                return $this->redirectToRoute('front_contact'); 
            } 
        } 
        return $this->render('front/contact.html.twig', array( 
            'contactForm' => $contactForm->createView(), 
        )); 
    } 
 
    /** 
     * @Route({ 
     *     "fr": "/plan-du-site", 
     *     "en": "/sitemap", 
     * }, name="front_sitemap_links") 
     */ 
    public function sitemapLinks(ManagerRegistry $managerRegistry, Request $request) 
    { 
 
        return $this->render('front/sitemapLinks.html.twig', array()); 
    } 
 
    /** 
     * @Route({ 
     *     "fr": "/notre-equipe", 
     *     "en": "/our-team", 
     * }, name="front_members") 
     */ 
    public function members(ManagerRegistry $managerRegistry, Request $request) 
    { 
        $repoMember = $managerRegistry->getRepository(Member::class); 
        $members = $repoMember->findBy([], ["position" => "asc"]); 
        return $this->render('front/members.html.twig', array( 
            "members" => $members 
        )); 
    } 
 
    /** 
     * @Route({ 
     *     "fr": "/actualites", 
     *     "en": "/news", 
     * }, name="front_posts") 
     */ 
    public function posts(Request $request, PaginatorInterface $paginator, ManagerRegistry $managerRegistry) 
    { 
        $repoPost = $managerRegistry->getRepository(Post::class); 
        $data["between"]["notStrict"]["a.date"]["max"] = new \DateTime(); 
        $data["orderBy"] = ["a.date", "desc"]; 
        $data["isPublished"] = true; 
        $posts = $paginator->paginate( 
            $repoPost->search($data), $request->query->getInt('page', 1)/* page number */, 12/* limit per page */ 
        ); 
        return $this->render('front/posts.html.twig', array( 
            "posts" => $posts 
        )); 
    } 
 
    /** 
     * @Route({ 
     *     "fr": "/navbar-search", 
     *     "en": "/navbar-search", 
     * }, name="front_navbar_search") 
     */ 
    public function navbarSearch(ManagerRegistry $managerRegistry, Request $request) 
    { 
        $query = $request->query->get('nav-search'); 
        $repoPost = $managerRegistry->getRepository(Post::class); 
        $data["search"] = $query; 
        $data["isPublished"] = true; 
        $data["orderBy"] = ["a.date", "asc"]; 
        $posts = $repoPost->search($data); 
        return $this->render('front/navbarSearch.html.twig', array( 
            "posts" => $posts, 
            "navSearchQuery" => $query 
        )); 
    } 
 
    /** 
     * @Route({ 
     *     "fr": "/actualite/{slug}", 
     *     "en": "/news/{slug}", 
     * }, name="front_post") 
     */ 
    public function post(Request $request, ManagerRegistry $managerRegistry, string $slug) 
    { 
        $repoPostTranslation = $managerRegistry->getRepository(PostTranslation::class); 
        $postTranslation = $repoPostTranslation->findOneBy(["slug" => $slug]); 
        if ($postTranslation and $post = $postTranslation->getTranslatable()) { 
            if ($post->getIsPublished() or $this->isGranted("ROLE_ADMIN")) { 
                $repoParagraph = $managerRegistry->getRepository(Paragraph::class); 
                $paragraphs = $repoParagraph->findBy(["post" => $post], ["position" => "asc"]); 
                $repoPostMedia = $managerRegistry->getRepository(PostMedia::class); 
                $postMedias = $repoPostMedia->findBy(["post" => $post], ["position" => "asc"]); 
                $repoPost = $managerRegistry->getRepository(Post::class); 
                $data["between"]["notStrict"]["a.date"]["max"] = new \DateTime(); 
                $data["orderBy"] = ["a.date", "desc"]; 
                $data["isPublished"] = true; 
                $data["limit"] = 2; 
                $data["different"] = ["a.id" => $post->getId()]; 
                $posts = $repoPost->search($data); 
                return $this->render('front/post.html.twig', array( 
                    "posts" => $posts, 
                    "post" => $post, 
                    "paragraphs" => $paragraphs, 
                    "postMedias" => $postMedias, 
                )); 
            } else { 
                $this->addFlash("danger", "flash.not_allowed_post"); 
                return $this->redirectToRoute('front_posts'); 
            } 
        } else { 
            $this->addFlash("danger", "flash.post_not_found"); 
            return $this->redirectToRoute('front_posts'); 
        } 
    } 
 
    /** 
     * @Route({ 
     *     "fr": "/inscription-newsletter", 
     *     "en": "/newsletter-register", 
     * }, name="front_subscribe_newsletter") 
     */ 
    public function subscribeNewsletter(ManagerRegistry $managerRegistry, Request $request, AppService $appService) 
    { 
        $newsletter = new Newsletter(); 
        $newsletterForm = $this->createForm(NewsletterType::class, $newsletter); 
        $newsletterForm->handleRequest($request); 
        $em = $managerRegistry->getManager(); 
        if ($newsletterForm->isSubmitted() && $newsletterForm->isValid()) { 
            $appService->suscribeToList($newsletter->getEmail()); 
            $em->persist($newsletter); 
            $em->flush(); 
            $this->addFlash("success", "flash.newsletter.success"); 
            return $this->redirectToRoute('front_landing'); 
        } 
        return $this->render('form/newsletterForm.html.twig', array( 
            'newsletterForm' => $newsletterForm->createView(), 
        )); 
    } 
 
    /** 
     * @Route({ 
     *     "fr": "/admin/fsdhj78Hjkdfsb0920dfjdfhq87djhaoppsnv720", 
     *     "en": "/admin/fsdhj78Hjkdfsb0920dfjdfhq87djhaoppsnv720", 
     * }, name="front_clear_cache") 
     */ 
    public function clearCache(Request $request, KernelInterface $kernel) 
    { 
        $application = new FrameworkApplication($kernel); 
        $application->setAutoExit(false); 
 
        $input = new ArrayInput([ 
            'command' => 'cache:clear', 
        ]); 
 
        // You can use NullOutput() if you don't need the output 
        $output = new NullOutput(); 
        $application->run($input, $output); 
        $this->addFlash("success", "Le cache a bien été nettoyé, les traductions sont à jour !"); 
        return $this->redirectToRoute('front_landing'); 
    } 
 
}