src/Controller/BlogController.php line 151

Open in your IDE?
  1. <?php
  2. /*
  3.  * This file is part of the Symfony package.
  4.  *
  5.  * (c) Fabien Potencier <fabien@symfony.com>
  6.  *
  7.  * For the full copyright and license information, please view the LICENSE
  8.  * file that was distributed with this source code.
  9.  */
  10. namespace App\Controller;
  11. use App\Entity\Comment;
  12. use App\Entity\Post;
  13. use App\Events;
  14. use App\Form\CommentType;
  15. use App\Repository\PostRepository;
  16. use Sensio\Bundle\FrameworkExtraBundle\Configuration\Cache;
  17. use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
  18. use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
  19. use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
  20. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  21. use Symfony\Component\EventDispatcher\EventDispatcherInterface;
  22. use Symfony\Component\EventDispatcher\GenericEvent;
  23. use Symfony\Component\HttpFoundation\Request;
  24. use Symfony\Component\HttpFoundation\Response;
  25. use Symfony\Component\Routing\Annotation\Route;
  26. /**
  27.  * Controller used to manage blog contents in the public part of the site.
  28.  *
  29.  * @Route("/blog")
  30.  *
  31.  * @author Ryan Weaver <weaverryan@gmail.com>
  32.  * @author Javier Eguiluz <javier.eguiluz@gmail.com>
  33.  */
  34. class BlogController extends AbstractController
  35. {
  36.     /**
  37.      * @Route("/", defaults={"page": "1", "_format"="html"}, name="blog_index")
  38.      * @Route("/rss.xml", defaults={"page": "1", "_format"="xml"}, name="blog_rss")
  39.      * @Route("/page/{page}", defaults={"_format"="html"}, requirements={"page": "[1-9]\d*"}, name="blog_index_paginated")
  40.      * @Method("GET")
  41.      * @Cache(smaxage="10")
  42.      *
  43.      * NOTE: For standard formats, Symfony will also automatically choose the best
  44.      * Content-Type header for the response.
  45.      * See https://symfony.com/doc/current/quick_tour/the_controller.html#using-formats
  46.      */
  47.     public function index(int $pagestring $_formatPostRepository $posts): Response
  48.     {
  49.         $latestPosts $posts->findLatest($page);
  50.         // Every template name also has two extensions that specify the format and
  51.         // engine for that template.
  52.         // See https://symfony.com/doc/current/templating.html#template-suffix
  53.         return $this->render('blog/index.'.$_format.'.twig', ['posts' => $latestPosts]);
  54.     }
  55.     /**
  56.      * @Route("/posts/{slug}", name="blog_post")
  57.      * @Method("GET")
  58.      *
  59.      * NOTE: The $post controller argument is automatically injected by Symfony
  60.      * after performing a database query looking for a Post with the 'slug'
  61.      * value given in the route.
  62.      * See https://symfony.com/doc/current/bundles/SensioFrameworkExtraBundle/annotations/converters.html
  63.      */
  64.     public function postShow(Post $post): Response
  65.     {
  66.         // Symfony's 'dump()' function is an improved version of PHP's 'var_dump()' but
  67.         // it's not available in the 'prod' environment to prevent leaking sensitive information.
  68.         // It can be used both in PHP files and Twig templates, but it requires to
  69.         // have enabled the DebugBundle. Uncomment the following line to see it in action:
  70.         //
  71.         // dump($post, $this->getUser(), new \DateTime());
  72.         return $this->render('blog/post_show.html.twig', ['post' => $post]);
  73.     }
  74.     /**
  75.      * @Route("/comment/{postSlug}/new", name="comment_new")
  76.      * @Method("POST")
  77.      * @Security("is_granted('IS_AUTHENTICATED_FULLY')")
  78.      * @ParamConverter("post", options={"mapping": {"postSlug": "slug"}})
  79.      *
  80.      * NOTE: The ParamConverter mapping is required because the route parameter
  81.      * (postSlug) doesn't match any of the Doctrine entity properties (slug).
  82.      * See https://symfony.com/doc/current/bundles/SensioFrameworkExtraBundle/annotations/converters.html#doctrine-converter
  83.      */
  84.     public function commentNew(Request $requestPost $postEventDispatcherInterface $eventDispatcher): Response
  85.     {
  86.         $comment = new Comment();
  87.         $comment->setAuthor($this->getUser());
  88.         $post->addComment($comment);
  89.         $form $this->createForm(CommentType::class, $comment);
  90.         $form->handleRequest($request);
  91.         if ($form->isSubmitted() && $form->isValid()) {
  92.             $em $this->getDoctrine()->getManager();
  93.             $em->persist($comment);
  94.             $em->flush();
  95.             // When triggering an event, you can optionally pass some information.
  96.             // For simple applications, use the GenericEvent object provided by Symfony
  97.             // to pass some PHP variables. For more complex applications, define your
  98.             // own event object classes.
  99.             // See https://symfony.com/doc/current/components/event_dispatcher/generic_event.html
  100.             $event = new GenericEvent($comment);
  101.             // When an event is dispatched, Symfony notifies it to all the listeners
  102.             // and subscribers registered to it. Listeners can modify the information
  103.             // passed in the event and they can even modify the execution flow, so
  104.             // there's no guarantee that the rest of this controller will be executed.
  105.             // See https://symfony.com/doc/current/components/event_dispatcher.html
  106.             $eventDispatcher->dispatch(Events::COMMENT_CREATED$event);
  107.             return $this->redirectToRoute('blog_post', ['slug' => $post->getSlug()]);
  108.         }
  109.         return $this->render('blog/comment_form_error.html.twig', [
  110.             'post' => $post,
  111.             'form' => $form->createView(),
  112.         ]);
  113.     }
  114.     /**
  115.      * This controller is called directly via the render() function in the
  116.      * blog/post_show.html.twig template. That's why it's not needed to define
  117.      * a route name for it.
  118.      *
  119.      * The "id" of the Post is passed in and then turned into a Post object
  120.      * automatically by the ParamConverter.
  121.      */
  122.     public function commentForm(Post $post): Response
  123.     {
  124.         $form $this->createForm(CommentType::class);
  125.         return $this->render('blog/_comment_form.html.twig', [
  126.             'post' => $post,
  127.             'form' => $form->createView(),
  128.         ]);
  129.     }
  130.     /**
  131.      * @Route("/search", name="blog_search")
  132.      * @Method("GET")
  133.      */
  134.     public function search(Request $requestPostRepository $posts): Response
  135.     {
  136.         if (!$request->isXmlHttpRequest()) {
  137.             return $this->render('blog/search.html.twig');
  138.         }
  139.         $query $request->query->get('q''');
  140.         $limit $request->query->get('l'10);
  141.         $foundPosts $posts->findBySearchQuery($query$limit);
  142.         $results = [];
  143.         foreach ($foundPosts as $post) {
  144.             $results[] = [
  145.                 'title' => htmlspecialchars($post->getTitle()),
  146.                 'date' => $post->getPublishedAt()->format('M d, Y'),
  147.                 'author' => htmlspecialchars($post->getAuthor()->getFullName()),
  148.                 'summary' => htmlspecialchars($post->getSummary()),
  149.                 'url' => $this->generateUrl('blog_post', ['slug' => $post->getSlug()]),
  150.             ];
  151.         }
  152.         return $this->json($results);
  153.     }
  154. }