src/Cms/Modules/NewsBundle/Service/NewsModuleConfig.php line 220

Open in your IDE?
  1. <?php
  2. namespace Cms\Modules\NewsBundle\Service;
  3. use App\Doctrine\Repository\Content\ObjectSearch;
  4. use App\Doctrine\Repository\Content\Posts\Post\PostObjectRepository;
  5. use App\Entity\Content\Posts\Post\PostObject;
  6. use App\Enum\ChannelEnum;
  7. use App\Util\Ulids;
  8. use Cms\AssetsBundle\Model\Structure\TitleStructure;
  9. use Cms\CoreBundle\Model\Search\AbstractSearcher;
  10. use Cms\CoreBundle\Util\DateTimeUtils;
  11. use Cms\FrontendBundle\Model\FrontendGlobals;
  12. use Cms\ModuleBundle\Entity\ModuleEntity;
  13. use Cms\ModuleBundle\Entity\Proxy;
  14. use Cms\ModuleBundle\Exception\ModuleConfigException;
  15. use Cms\ModuleBundle\Model\ModuleConfig;
  16. use Cms\ModuleBundle\Model\Traits\FrontendActions\CascadingSharesTrait;
  17. use Cms\ModuleBundle\Model\Traits\FrontendActions\FeedSecurityTrait;
  18. use Cms\ModuleBundle\Model\Traits\FrontendActions\FeedTrait;
  19. use Cms\ModuleBundle\Model\Traits\FrontendActions\RssFeedTrait;
  20. use Cms\ModuleBundle\Model\Traits\FrontendActions\SocialMetaTrait;
  21. use Cms\Modules\NewsBundle\Doctrine\Article\ArticleProxyRepository;
  22. use Cms\Modules\NewsBundle\Entity\Article\ArticleProxy;
  23. use Cms\Modules\NewsBundle\Entity\ModuleSettings;
  24. use Cms\Modules\NewsBundle\Service\Search\ArticleSearcher;
  25. use Cms\Widgets\Html\Html;
  26. use Common\Util\Strings;
  27. use Doctrine\Common\Util\ClassUtils;
  28. use Symfony\Component\HttpFoundation\RedirectResponse;
  29. use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
  30. /**
  31.  * Class NewsModuleConfig
  32.  * @package Cms\Modules\NewsBundle\Service
  33.  */
  34. final class NewsModuleConfig extends ModuleConfig
  35. {
  36.     const NAME 'News';
  37.     use RssFeedTrait;
  38.     use FeedTrait;
  39.     use FeedSecurityTrait;
  40.     use SocialMetaTrait;
  41.     use CascadingSharesTrait;
  42.     /**
  43.      * @return ArticleProxyRepository
  44.      */
  45.     private function getProxyRepository(): ArticleProxyRepository
  46.     {
  47.         return $this->getEntityManager()->getRepository(ArticleProxy::class);
  48.     }
  49.     /**
  50.      * @return PostObjectRepository
  51.      */
  52.     private function getObjectRepository(): PostObjectRepository
  53.     {
  54.         return $this->getEntityManager()->getRepository(PostObject::class);
  55.     }
  56.     /**
  57.      * {@inheritdoc}
  58.      * @param ArticleProxy $proxy
  59.      */
  60.     public function urlify(Proxy $proxy null)
  61.     {
  62.         if ($proxy === null) {
  63.             return '/' $this->key();
  64.         }
  65.         return sprintf(
  66.             '/%s/%s/%s',
  67.             $this->key(),
  68.             $proxy->getId(),
  69.             $proxy->getData()->getSlug()
  70.         );
  71.     }
  72.     /**
  73.      * {@inheritdoc}
  74.      */
  75.     public function frontend(FrontendGlobals $globals)
  76.     {
  77.         $extra $globals->getExtra();
  78.         //override inner layout from module settings
  79.         /** @var ModuleSettings $settings */
  80.         $settings $globals->getModuleSettings();
  81.         if ( ! empty($settings->getInnerLayout())) {
  82.             $globals->setInnerLayout(
  83.                 $settings->getInnerLayout(),
  84.                 true
  85.             );
  86.         }
  87.         switch (true) {
  88.             case preg_match('/^\\/$/'$extra$matches):
  89.                 return $this->frontendList($globals, array(
  90.                     'page' => 1,
  91.                 ));
  92.             case preg_match('/^\\/page\\/([1-9]\\d*)$/'$extra$matches):
  93.                 return $this->frontendList($globals, array(
  94.                     'page' => $matches[1],
  95.                 ));
  96.             // SCHOOLNOW: modify regex to allow for ulid values
  97.             case preg_match('/^\\/([0-9]+|[0-7][0-9a-hA-HjJkKmMnNp-tP-Tv-zV-Z]{25})\\/([-a-zA-Z0-9]+)$/'$extra$matches):
  98.                 return $this->frontendView($globals, array(
  99.                     'id' => $matches[1],
  100.                     'slug' => $matches[2],
  101.                 ));
  102.             case $this->isPrivateFeed($globals->getContainer(), $this->name()):
  103.                 return $this->loginRedirect($globals->getRequest());
  104.             case preg_match('/\\/subscribe$/'$extra):
  105.                 return $this->frontendSubscribe($globals);
  106.             case preg_match('/\\/feed\\/(rss)$/'$extra$matches):
  107.                 return $this->rssFeed(
  108.                     $this->getFeedBuilder(),
  109.                     $globals,
  110.                     $matches[1]
  111.                 );
  112.             default:
  113.                 throw new NotFoundHttpException();
  114.         }
  115.     }
  116.     /**
  117.      * @param FrontendGlobals $globals
  118.      * @param array $params
  119.      * @return array
  120.      * @throws ModuleConfigException
  121.      */
  122.     private function frontendList(FrontendGlobals $globals, array $params)
  123.     {
  124.         // SCHOOLNOW: handle schoolnow
  125.         if ($this->isSchoolNow($globals->getContainer())) {
  126.             return $this->frontendListSchoolNow($globals$params);
  127.         }
  128.         // query for objects, apply paging
  129.         $items $this->paginationResults(
  130.             $this->getProxyRepository()->createQueryBuilder('items')
  131.                 ->andWhere('items.container IN (:container)')
  132.                 ->setParameter('container'$this->flattenContainers($globals->getContainer(), ModuleSettings::class))
  133.                 ->andWhere('items.data_timestamp <= :now')
  134.                 ->setParameter('now'DateTimeUtils::current())
  135.                 ->addOrderBy('items.data_timestamp''DESC')
  136.             ,
  137.             $params['page']
  138.         );
  139.         // handle paging math
  140.         $pagination $this->pagination($items$params['page']);
  141.         // set title, do this after query, so we can attach page number for ada compliance
  142.         if ( ! empty($globals->getModuleSettings()->getTitle())) {
  143.             $globals->getAssetsOrganizer()->getTitles()
  144.                 ->add(new TitleStructure($globals->getModuleSettings()->getTitle()));
  145.             if ( ! empty($pagination)) {
  146.                 $globals->getAssetsOrganizer()->getTitles()
  147.                     ->add(new TitleStructure('Page ' $pagination['current']));
  148.             }
  149.         } else {
  150.             $globals->getAssetsOrganizer()->getTitles()
  151.                 ->add(new TitleStructure($globals->getModule()->name()));
  152.             if ( ! empty($pagination)) {
  153.                 $globals->getAssetsOrganizer()->getTitles()
  154.                     ->add(new TitleStructure('Page ' $pagination['current']));
  155.             }
  156.             $globals->getAssetsOrganizer()->getTitles()
  157.                 ->add(new TitleStructure($globals->getContainer()->getName()));
  158.         }
  159.         // render the content
  160.         $content $this->getTwig()->render(
  161.             $this->getDatabaseLoader()->determine(
  162.                 $globals->getTheme(),
  163.                 sprintf(
  164.                     '/modules/%s/List/build/tpl.html.twig',
  165.                     $globals->getModule()->name()
  166.                 )
  167.             ),
  168.             array(
  169.                 'globals' => $globals,
  170.                 'items' => $items,
  171.                 'pagination' => $pagination,
  172.             )
  173.         );
  174.         // pass back as we need it
  175.         return array(
  176.             array(
  177.                 'content' => array(
  178.                     (new Html())
  179.                         ->setContent($content),
  180.                 ),
  181.             ),
  182.         );
  183.     }
  184.     /**
  185.      * @param FrontendGlobals $globals
  186.      * @param array $params
  187.      * @return array
  188.      * @throws ModuleConfigException
  189.      */
  190.     private function frontendListSchoolNow(FrontendGlobals $globals, array $params)
  191.     {
  192.         // set things we are looking for
  193.         $globals->setThingClasses([
  194.             PostObject::class,
  195.         ]);
  196.         // query for objects, apply paging
  197.         /** @var PostObjectRepository $postObjectRepository */
  198.         $postObjectRepository $this->getEntityManager()->getRepository(PostObject::class);
  199.         $items $postObjectRepository
  200.             ->findBySearch(
  201.                 (new ObjectSearch())
  202.                     ->setContainer($globals->getContainer())
  203.                     ->setChannels(ChannelEnum::WEBSITE)
  204.                 ,
  205.                 self::PAGINATION_SIZE 1,
  206.                 ($params['page'] - 1) * self::PAGINATION_SIZE
  207.             )
  208.             ->getIterator()
  209.             ->getArrayCopy()
  210.         ;
  211.         // handle paging math
  212.         $pagination $this->pagination($items$params['page']);
  213.         // set title, do this after query, so we can attach page number for ada compliance
  214.         if ( ! empty($globals->getModuleSettings()->getTitle())) {
  215.             $globals->getAssetsOrganizer()->getTitles()
  216.                 ->add(new TitleStructure($globals->getModuleSettings()->getTitle()));
  217.             if ( ! empty($pagination)) {
  218.                 $globals->getAssetsOrganizer()->getTitles()
  219.                     ->add(new TitleStructure('Page ' $pagination['current']));
  220.             }
  221.         } else {
  222.             $globals->getAssetsOrganizer()->getTitles()
  223.                 ->add(new TitleStructure($globals->getModule()->name()));
  224.             if ( ! empty($pagination)) {
  225.                 $globals->getAssetsOrganizer()->getTitles()
  226.                     ->add(new TitleStructure('Page ' $pagination['current']));
  227.             }
  228.             $globals->getAssetsOrganizer()->getTitles()
  229.                 ->add(new TitleStructure($globals->getContainer()->getName()));
  230.         }
  231.         // render the content
  232.         $content $this->getTwig()->render(
  233.             $this->getDatabaseLoader()->determine(
  234.                 $globals->getTheme(),
  235.                 sprintf(
  236.                     '/modules/%s/List/build/sn.html.twig',
  237.                     $globals->getModule()->name()
  238.                 )
  239.             ),
  240.             array(
  241.                 'globals' => $globals,
  242.                 'items' => $items,
  243.                 'pagination' => $pagination,
  244.             )
  245.         );
  246.         // pass back as we need it
  247.         return array(
  248.             array(
  249.                 'content' => array(
  250.                     (new Html())
  251.                         ->setContent($content),
  252.                 ),
  253.             ),
  254.         );
  255.     }
  256.     /**
  257.      * @param FrontendGlobals $globals
  258.      * @param array $params
  259.      * @return array|RedirectResponse
  260.      * @throws ModuleConfigException
  261.      */
  262.     private function frontendView(FrontendGlobals $globals, array $params)
  263.     {
  264.         // SCHOOLNOW: handle schoolnow
  265.         if ($this->isSchoolNow($globals->getContainer())) {
  266.             return $this->frontendViewSchoolNow($globals$params);
  267.         }
  268.         /** @var ArticleProxy $item */
  269.         $item $this->getEntityManager()->getRepository(ArticleProxy::class)->find($params['id']);
  270.         // check for item, if none, throw 404
  271.         if ( ! $item) {
  272.             throw new NotFoundHttpException();
  273.         }
  274.         // set the thing on the globals
  275.         $globals->setThing($item);
  276.         // handle non-proxy preview
  277.         if ($globals->getThingOverride() instanceof ModuleEntity) {
  278.             $globals->setThing($item->setData(
  279.                 $globals->getThingOverride()->getData()
  280.             ));
  281.         }
  282.         // set social meta tags
  283.         $this->setSocialMeta(
  284.             $globals,
  285.             $item->getData()->getSocialMetadata()
  286.         );
  287.         // set title
  288.         $globals->getAssetsOrganizer()->getTitles()
  289.             ->add(new TitleStructure($item->getData()->getTitle()))
  290.             ->add(new TitleStructure($globals->getContainer()->getName()));
  291.         // check to see if we have an external link set; if so return a redirect, and only do if not logged in
  292.         if ( ! empty($item->getData()->getExternalLink()) && empty($globals->getMimic())) {
  293.             return new RedirectResponse($item->getData()->getExternalLink());
  294.         }
  295.         // check slugs, and if incorrect, redirect to proper url with slug
  296.         if ($item->getData()->getSlug() !== $params['slug']) {
  297.             return new RedirectResponse(sprintf(
  298.                 '%s/%s/%s/%s',
  299.                 $globals->pathPrefix(),
  300.                 $globals->getModule()->key(),
  301.                 $item->getId(),
  302.                 $item->getData()->getSlug()
  303.             ));
  304.         }
  305.         // render the content
  306.         $content $this->getTwig()->render(
  307.             $this->getDatabaseLoader()->determine(
  308.                 $globals->getTheme(),
  309.                 sprintf(
  310.                     '/modules/%s/View/build/tpl.html.twig',
  311.                     $globals->getModule()->name()
  312.                 )
  313.             ),
  314.             array(
  315.                 'globals' => $globals,
  316.                 'item' => $item,
  317.             )
  318.         );
  319.         // pass back as we need it
  320.         return array(
  321.             array(
  322.                 'content' => array(
  323.                     (new Html())
  324.                         ->setContent($content),
  325.                 ),
  326.             ),
  327.         );
  328.     }
  329.     /**
  330.      * @param FrontendGlobals $globals
  331.      * @param array $params
  332.      * @return array|RedirectResponse
  333.      * @throws ModuleConfigException
  334.      */
  335.     private function frontendViewSchoolNow(FrontendGlobals $globals, array $params)
  336.     {
  337.         if ( ! Ulids::test($params['id'])) {
  338.             throw new NotFoundHttpException();
  339.         }
  340.         /** @var PostObject $item */
  341.         $item $this->getEntityManager()->getRepository(PostObject::class)->find($params['id']);
  342.         // check for item, if none, throw 404
  343.         if ( ! $item) {
  344.             throw new NotFoundHttpException();
  345.         }
  346.         // check if it has website channel
  347.         if ( ! $item->hasChannel(ChannelEnum::WEBSITE)) {
  348.             throw new NotFoundHttpException();
  349.         }
  350.         // set the thing on the globals
  351.         $globals
  352.             ->setThing($item)
  353.             ->setThingClasses([ClassUtils::getClass($item)])
  354.         ;
  355.         // handle non-proxy preview
  356. //        if ($globals->getThingOverride() instanceof ModuleEntity) {
  357. //            $globals->setThing($item->setData(
  358. //                $globals->getThingOverride()->getData()
  359. //            ));
  360. //        }
  361.         // set social meta tags
  362.         $this->setSocialMeta(
  363.             $globals,
  364.             [
  365.                 'og:type' => 'article',
  366.                 'title' => $item->getHeadline(),
  367.                 'image' => $item->getMedia()->getFeature(),
  368. //                'cs:image-presized' => ( ! empty($this->getSocialImage())),
  369.                 'description' => Strings::htmltidytrim($item->getHtml()),
  370.             ]
  371.         );
  372.         // set title
  373.         $globals->getAssetsOrganizer()->getTitles()
  374.             ->add(new TitleStructure($item->getHeadline()))
  375.             ->add(new TitleStructure($globals->getContainer()->getName()));
  376.         // check to see if we have an external link set; if so return a redirect, and only do if not logged in
  377. //        if ( ! empty($item->getData()->getExternalLink()) && empty($globals->getMimic())) {
  378. //            return new RedirectResponse($item->getData()->getExternalLink());
  379. //        }
  380.         // check slugs, and if incorrect, redirect to proper url with slug
  381.         if ($item->getSlug() !== $params['slug']) {
  382.             return new RedirectResponse(sprintf(
  383.                 '%s/%s/%s/%s',
  384.                 $globals->pathPrefix(),
  385.                 $globals->getModule()->key(),
  386.                 $item->getId(),
  387.                 $item->getSlug()
  388.             ));
  389.         }
  390.         // render the content
  391.         $content $this->getTwig()->render(
  392.             $this->getDatabaseLoader()->determine(
  393.                 $globals->getTheme(),
  394.                 sprintf(
  395.                     '/modules/%s/View/build/sn.html.twig',
  396.                     $globals->getModule()->name()
  397.                 )
  398.             ),
  399.             array(
  400.                 'globals' => $globals,
  401.                 'item' => $item,
  402.             )
  403.         );
  404.         // pass back as we need it
  405.         return array(
  406.             array(
  407.                 'content' => array(
  408.                     (new Html())
  409.                         ->setContent($content),
  410.                 ),
  411.             ),
  412.         );
  413.     }
  414.     /**
  415.      * {@inheritdoc}
  416.      */
  417.     public function types()
  418.     {
  419.         return array(ArticleProxy::TYPE);
  420.     }
  421.     /**
  422.      * {@inheritdoc}
  423.      */
  424.     public function typesRoots()
  425.     {
  426.         return array(ArticleProxy::TYPE);
  427.     }
  428.     /**
  429.      * {@inheritdoc}
  430.      */
  431.     public function typesChildren($type)
  432.     {
  433.         return [];
  434.     }
  435.     /**
  436.      * {@inheritdoc}
  437.      */
  438.     public function collectionClass($classname)
  439.     {
  440.     }
  441.     /**
  442.      * @return ArticleSearcher|object
  443.      */
  444.     public function getArticleSearcher(): ArticleSearcher
  445.     {
  446.         return $this->container->get(__METHOD__);
  447.     }
  448.     /**
  449.      * {@inheritDoc}
  450.      * @return ArticleSearcher
  451.      */
  452.     public function getSearcher(): AbstractSearcher
  453.     {
  454.         return $this->getArticleSearcher();
  455.     }
  456. }