app/Customize/Controller/CustomBlogController.php line 111

Open in your IDE?
  1. <?php
  2. /*
  3.  * This file is part of Customize of EC-CUBE by Kenji Nakanishi
  4.  *
  5.  * Copyright(c) 2021 Kenji Nakanishi. All Rights Reserved.
  6.  *
  7.  * https://www.facebook.com/web.kenji.nakanishi
  8.  *
  9.  * For the full copyright and license information, please view the LICENSE
  10.  * file that was distributed with this source code.
  11.  */
  12. namespace Customize\Controller;
  13. use Doctrine\ORM\EntityManagerInterface;
  14. use Doctrine\ORM\Query\Expr;
  15. use Doctrine\ORM\QueryBuilder;
  16. use Eccube\Controller\AbstractController;
  17. use Eccube\Entity\Category;
  18. use Eccube\Entity\Customer;
  19. use Eccube\Entity\Master\OrderItemType;
  20. use Eccube\Entity\Master\OrderStatus;
  21. use Eccube\Entity\Master\ProductStatus;
  22. use Eccube\Entity\Master\SaleType;
  23. use Eccube\Entity\Order;
  24. use Eccube\Entity\OrderItem;
  25. use Eccube\Entity\Product;
  26. use Eccube\Entity\ProductClass;
  27. use Eccube\Entity\ProductCategory;
  28. use Eccube\Repository\OrderItemRepository;
  29. use Eccube\Repository\OrderRepository;
  30. use Plugin\SheebDlc4\Entity\Config;
  31. use Plugin\SheebDlc4\Entity\DownloadContent;
  32. use Plugin\SheebDlc4\PluginManager;
  33. use Plugin\SheebDlc4\Service\SaveFile\AbstractSaveFile;
  34. use Plugin\SheebDlc4\Service\SaveFile\Modules\Local;
  35. use Plugin\SheebDlc4\Service\SaveFile\SaveFileModuleFactory;
  36. use Plugin\SheebDlc4\Service\SheebUtils;
  37. use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
  38. use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
  39. use Symfony\Component\Asset\Packages;
  40. use Symfony\Component\HttpFoundation\Request;
  41. use Symfony\Component\HttpFoundation\Response;
  42. use Eccube\Common\EccubeConfig;
  43. use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
  44. use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
  45. use Symfony\Component\HttpKernel\Exception\UnsupportedMediaTypeHttpException;
  46. use Symfony\Component\Routing\Annotation\Route;
  47. use Knp\Component\Pager\PaginatorInterface;
  48. use Eccube\Form\Type\SearchProductType;
  49. use Eccube\Form\Type\Master\ProductListMaxType;
  50. use Eccube\Form\Type\Master\ProductListOrderByType;
  51. use Plugin\CMBlogPro\Form\Type\Admin\BlogType;
  52. use Plugin\CMBlogPro\Repository\BlogRepository;
  53. use Eccube\Doctrine\Query\Queries;
  54. use Plugin\CMBlogPro\Repository\ConfigRepository;
  55. use Plugin\CMBlogPro\Repository\CategoryRepository;
  56. use Eccube\Util\StringUtil;
  57. use Eccube\Repository\PageRepository;
  58. class CustomBlogController extends AbstractController
  59. {
  60.     const BLOG_CATEGORY = array(
  61.         'MEMBER' => 1,
  62.         'NEWS' => 2,
  63.     );
  64.     /**
  65.      * @var BlogRepository $blogRepository
  66.      */
  67.     private $blogRepository;
  68.     private $queries;
  69.     /**
  70.      * @var ConfigRepository
  71.      */
  72.     protected $configRepository;
  73.     /**
  74.      * @var CategoryRepository
  75.      */
  76.     protected $categoryRepository;
  77.     /**
  78.      * @var PageRepository
  79.      */
  80.     protected $pageRepository;
  81.     public function __construct(BlogRepository $blogRepositoryQueries $queriesConfigRepository $configRepositoryCategoryRepository $categoryRepositoryPageRepository $pageRepository)
  82.     {
  83.         $this->blogRepository $blogRepository;
  84.         $this->queries $queries;
  85.         $this->configRepository $configRepository;
  86.         $this->categoryRepository $categoryRepository;
  87.         $this->pageRepository $pageRepository;
  88.     }
  89.     /**
  90.      * ブログ一覧
  91.      *
  92.      * @Route("/blog_list/", name="blog_list", methods={"GET"})
  93.      * @Template("blog/list.twig")
  94.      *
  95.      * @param Request $request
  96.      * @param PaginatorInterface $paginator
  97.      * @return array
  98.      */
  99.     public function blog_list(Request $requestPaginatorInterface $paginator)
  100.     {
  101.         // ログイン時はニュースのみ、非ログイン時は会員カテゴリも除外する
  102.         if ($this->isGranted('ROLE_USER')) {
  103.             return $this->blog_list_response($request$paginator, [self::BLOG_CATEGORY['NEWS']]);
  104.         } else {
  105.             return $this->blog_list_response($request$paginator, [self::BLOG_CATEGORY['MEMBER'], self::BLOG_CATEGORY['NEWS']]);
  106.         }
  107.     }
  108.     /**
  109.      * ブログ詳細ページのブログ遷移先の振り分け
  110.      * ログイン済み→デフォルト, 未ログイン→カスタム
  111.      *
  112.      * @Route("/blog_detail/{id}", name="blog_detail/{id}", methods={"GET"})
  113.      * @Template("blog/detail.twig")
  114.      *
  115.      * @param Request $request
  116.      * @param string $id
  117.      * @return \Symfony\Component\HttpFoundation\RedirectResponse
  118.      *
  119.      * @throws \Exception
  120.      */
  121.     public function blog_detail(Request $request$id)
  122.     {
  123.         $blogDetail $this->getBlogDetailByIdOrSlug($id);
  124.         if ($blogDetail === null) {
  125.             throw new NotFoundHttpException();
  126.         }
  127.         // お知らせを含む場合は404
  128.         if ($this->hasCategoryId($blogDetailself::BLOG_CATEGORY['NEWS']) === true) {
  129.             throw new NotFoundHttpException();
  130.         }
  131.         if ($this->isGranted('ROLE_USER')) {
  132.             // 会員の場合は無条件
  133.             return $this->forwardToRoute('cm_blog_pro_page_detail', ['id' => $id], $request->query->all());
  134.         } else {
  135.             // 非会員の場合は会員カテゴリが設定されている場合のみ一覧画面に遷移
  136.             if ($this->hasCategoryId($blogDetailself::BLOG_CATEGORY['MEMBER']) === true) {
  137.                 return $this->redirectToRoute('blog_list'$request->query->all());
  138.             }
  139.             
  140.             return $this->forwardToRoute('cm_blog_pro_page_detail', ['id' => $id], $request->query->all());
  141.         }
  142.     }
  143.     /**
  144.      * 会員限定のニュース一覧ページ
  145.      *
  146.      * @Route("/news_list/", name="news_list", methods={"GET"})
  147.      * @Template("blog/news_list.twig")
  148.      *
  149.      * @param Request $request
  150.      * @param PaginatorInterface $paginator
  151.      * @return array|RedirectResponse
  152.      */
  153.     public function news_list(Request $requestPaginatorInterface $paginator)
  154.     {
  155.         if ($this->isGranted('ROLE_USER')) {
  156.             return $this->news_list_response($request$paginatornull, [self::BLOG_CATEGORY['NEWS']]);
  157.             // return $this->redirectToRoute('news_entry', $request->query->all());
  158.         } else {
  159.             return $this->news_list_response($request$paginator, [self::BLOG_CATEGORY['MEMBER']], [self::BLOG_CATEGORY['NEWS']]);
  160.         }
  161.     }
  162.     /**
  163.      * ニュース詳細ページのブログ遷移先の振り分け
  164.      * ログイン済み→デフォルト, 未ログイン→カスタム
  165.      *
  166.      * @Route("/news_detail/{id}", name="news_detail/{id}", methods={"GET"})
  167.      * @Template("blog/news_detail.twig")
  168.      *
  169.      * @param Request $request
  170.      * @param int|string $id
  171.      * @return \Symfony\Component\HttpFoundation\RedirectResponse
  172.      *
  173.      * @throws \Exception
  174.      */
  175.     public function news_detail(Request $request$id)
  176.     {
  177.         $blog $this->getBlogDetailByIdOrSlug($id);
  178.         if ($blog === null) {
  179.             throw new NotFoundHttpException();
  180.         }
  181.         // お知らせカテゴリは必須
  182.         if ($this->hasCategoryId($blogself::BLOG_CATEGORY['NEWS']) === false) {
  183.             throw new NotFoundHttpException();
  184.         }
  185.         // 非会員∧会員カテゴリ
  186.         if (!$this->isGranted('ROLE_USER')) {
  187.             // 非会員の場合は会員カテゴリが設定されている場合のみ一覧画面に遷移
  188.             if ($this->hasCategoryId($blog1) === true) {
  189.                 return $this->redirectToRoute('blog_list'$request->query->all());
  190.             }
  191.         }
  192.         $config $this->configRepository->get();
  193.         $form $this->createForm(BlogType::class, $blog);
  194.         $cmPage $this->pageRepository->findOneBy(['url'  => 'cm_blog_pro_page_detail']);
  195.         if ($blog->getAuthor() != null) {
  196.             $Page["author"] = $blog->getAuthor();
  197.         } else {
  198.             $Page["author"] = $cmPage->getAuthor();
  199.         }
  200.             
  201.         if ($blog->getDescription() != null) {
  202.             $Page["description"] = $blog->getDescription();
  203.         } else {
  204.             $Page["description"] = $cmPage->getDescription();
  205.         };
  206.         
  207.         if ($blog->getKeyword() != null) {
  208.             $Page["keyword"] = $blog->getKeyword();
  209.         } else {
  210.             $Page["keyword"] = $cmPage->getKeyword();
  211.         };
  212.         
  213.         if ($blog->getRobot() != null) {
  214.             $Page["meta_robots"] = $blog->getRobot();
  215.         } else {
  216.             $Page["meta_robots"] = $cmPage->getMetaRobots();
  217.         }
  218.         
  219.         if ($blog->getMetatag() != null) {
  220.             $Page["meta_tags"] = $blog->getMetatag();
  221.         } else {
  222.             $Page["meta_tags"] = $cmPage->getMetaTags();
  223.         }
  224.         $tagArr = [];
  225.         if ($blog->getTag() != null) {
  226.             $tagArr preg_split('/[;, 、]+/u'$blog->getTag());
  227.         }
  228.         $Page["edit_type"] = 0;
  229.         return [
  230.             'form' => $form->createView(),
  231.             'blog' => $blog,
  232.             'Page' => $Page,
  233.             'subtitle' => $blog->getTitle(),
  234.             'tags' => $tagArr,
  235.             'monthArr' => $this->setMonthArchive()
  236.         ];
  237.     }
  238.     /**
  239.      * ブログ一覧(会員, ゲスト)のレスポンスを生成する。
  240.      * 検索条件のみ若干異なるためパラメータに応じて処理を分岐する。
  241.      *
  242.      * @param Request $request
  243.      * @param PaginatorInterface $paginator
  244.      * @param array|null $excludeCategoryIds
  245.      * @param array|null $includeCategoryIds
  246.      * @return array
  247.      */
  248.     public function blog_list_response(Request $requestPaginatorInterface $paginator$excludeCategoryIds = [], $includeCategoryIds = [])
  249.     {
  250.         $form $this->createForm(BlogType::class);
  251.         $search $request->query->all();
  252.         $search["status"] = 1;
  253.         $qb $this->getCustomQuery($search$excludeCategoryIds$includeCategoryIds);
  254.         $config $this->configRepository->get();
  255.         $pagination $paginator->paginate(
  256.             $qb,
  257.             !empty($search['pageno']) ? $search['pageno'] : 1,
  258.             !empty($search['disp_number']) ? $search['disp_number'] : $config->getDisplayPage()
  259.         );
  260.         return [
  261.             'form' => $form->createView(),
  262.             'categories' => $this->categoryRepository->getFrontCategoryList(),
  263.             'pagination' => $pagination,
  264.             'monthArr' => $this->setMonthArchive($search),
  265.             'excludeCategoryIds' => $excludeCategoryIds,
  266.             'includeCategoryIds' => $includeCategoryIds,
  267.             'searchData' => $search,
  268.         ];
  269.     }
  270.     /**
  271.      * ニュース一覧(会員, ゲスト)のレスポンスを生成する。
  272.      * 検索条件のみ若干異なるためパラメータに応じて処理を分岐する。
  273.      *
  274.      * @param Request $request
  275.      * @param PaginatorInterface $paginator
  276.      * @param array|null $excludeCategoryIds
  277.      * @param array|null $includeCategoryIds
  278.      * @return array
  279.      */
  280.     public function news_list_response(Request $requestPaginatorInterface $paginator$excludeCategoryIds = [], $includeCategoryIds = [])
  281.     {
  282.         $form $this->createForm(BlogType::class);
  283.         $search $request->query->all();
  284.         $search["status"] = 1;
  285.         $qb $this->getCustomQuery($search$excludeCategoryIds$includeCategoryIds);
  286.         $config $this->configRepository->get();
  287.         $pagination $paginator->paginate(
  288.             $qb,
  289.             !empty($search['pageno']) ? $search['pageno'] : 1,
  290.             !empty($search['disp_number']) ? $search['disp_number'] : $config->getDisplayPage()
  291.         );
  292.         return [
  293.             'form' => $form->createView(),
  294.             'categories' => $this->categoryRepository->getFrontCategoryList(),
  295.             'pagination' => $pagination,
  296.             'monthArr' => $this->setMonthArchive($search),
  297.             'excludeCategoryIds' => $excludeCategoryIds,
  298.             'includeCategoryIds' => $includeCategoryIds,
  299.             'searchData' => $search,
  300.         ];
  301.     }
  302.     /**
  303.      * 検索クエリを生成する
  304.      *
  305.      * @param array $searchData
  306.      * @param array|null $excludeCategoryIds 除外するカテゴリID
  307.      * @param array|null $includeCategoryIds 含む必要のあるカテゴリ
  308.      * @return \Doctrine\ORM\QueryBuilder
  309.      */
  310.     public function getCustomQuery($searchData$excludeCategoryIds = [], $includeCategoryIds = [])
  311.     {
  312.         $currentDate = new \DateTime();
  313.         $qb $this->get_publish_query_builder($currentDate);
  314.         // 除外カテゴリ設定がある場合は対象のブログIDを取得する
  315.         $excludeMemberBlogs null;
  316.         $excludeMemberBlogIds null;
  317.         if (!empty($excludeCategoryIds)) {
  318.             $excludeQb $this->get_publish_query_builder($currentDate'o.id');
  319.             $excludeQb
  320.                 ->innerJoin('o.BlogCategories''bct')
  321.                 ->innerJoin('bct.Category''c''WITH''c.id = bct.Category');
  322.             $excludeQb->andWhere($excludeQb->expr()->in('bct.Category'$excludeCategoryIds));
  323.             $excludeMemberBlogs $excludeQb->getQuery()->getResult();
  324.         
  325.             if (!empty($excludeMemberBlogs)) {
  326.                 $excludeMemberBlogIds array_column($excludeMemberBlogs'id');
  327.             }
  328.         }
  329.         // 指定カテゴリがある場合は対象のブログIDを取得する
  330.         $includeBlogs null;
  331.         $includeBlogIds null;
  332.         if (!empty($includeCategoryIds)) {
  333.             $includeQb $this->get_publish_query_builder($currentDate'o.id');
  334.             $includeQb
  335.                 ->innerJoin('o.BlogCategories''bct')
  336.                 ->innerJoin('bct.Category''c''WITH''c.id = bct.Category');
  337.             $includeQb->andWhere($includeQb->expr()->in('bct.Category'$includeCategoryIds));
  338.             $includeBlogs $includeQb->getQuery()->getResult();
  339.             if (!empty($includeBlogs)) {
  340.                 $includeBlogIds array_column($includeBlogs'id');
  341.             }
  342.         }
  343.         // カテゴリ
  344.         if (isset($searchData['categories']) && StringUtil::isNotBlank($searchData['categories'])) {
  345.             $qb
  346.                 ->innerJoin('o.BlogCategories''bct')
  347.                 ->innerJoin('bct.Category''c')
  348.                 ->andWhere($qb->expr()->in('bct.Category'':categories'))
  349.                 ->setParameter('categories'$searchData['categories']);
  350.         } else {
  351.             // NULL許容
  352.             $qb
  353.                 ->leftJoin('o.BlogCategories''bct')
  354.                 ->leftJoin('bct.Category''c''WITH''c.id = bct.Category');
  355.         }
  356.         // タグで検索
  357.         if (isset($searchData['tag']) && StringUtil::isNotBlank($searchData['tag'])) {
  358.             $qb
  359.                 ->andWhere('o.tag LIKE :tag')
  360.                 ->setParameter('tag''%'$searchData['tag'] .'%');
  361.         }
  362.         // タグで検索
  363.         if (isset($searchData['date']) && StringUtil::isNotBlank($searchData['date'])) {
  364.             
  365.             $currentDate = new \DateTime();
  366.             $qb
  367.                 ->andWhere('o.release_date >= :max_date AND o.release_date <= :min_date AND o.release_date <= :currentDate')
  368.                 ->setParameter('max_date'date('Y-m-01 00:00:00'strtotime($searchData['date'])))
  369.                 ->setParameter('min_date'date('Y-m-t 23:59:59'strtotime($searchData['date'])))
  370.                 ->setParameter('currentDate'$currentDate);
  371.         }
  372.         // カテゴリを指定する場合
  373.         // if (!empty($includeCategoryIds)) {
  374.         //     $qb->andWhere($qb->expr()->in('bct.Category', ':includeCategories'))
  375.         //         ->setParameter('includeCategories', $includeCategoryIds);
  376.         // }
  377.         if (!empty($includeBlogIds)) {
  378.             $qb->andWhere($qb->expr()->in('o.id'':includeIds'))
  379.                 ->setParameter('includeIds'$includeBlogIds);
  380.         }
  381.         // 特定カテゴリの記事IDを結果から除外する
  382.         if (!empty($excludeMemberBlogIds)) {
  383.             $qb->andWhere($qb->expr()->notIn('o.id'':excludeIds'))
  384.                 ->setParameter('excludeIds'$excludeMemberBlogIds);
  385.         }
  386.         // Order By
  387.         $qb->orderBy('o.create_date''DESC');
  388.         return $this->queries->customize('Blog.getQueryBuilderBySearchData'$qb$searchData);
  389.     }
  390.     /**
  391.      * 公開状態の記事を抽出するクエリビルダを返却する
  392.      *
  393.      * @param \Datetime $currentDate
  394.      * @param string $select selectする対象
  395.      * @return \Doctrine\ORM\QueryBuilder
  396.      */
  397.     public function get_publish_query_builder($currentDate null$select 'o')
  398.     {
  399.         if (empty($currentDate)) {
  400.             $currentDate = new \DateTime();
  401.         }
  402.         /** @var \Doctrine\ORM\QueryBuilder $qb */
  403.         $qb $this->blogRepository->createQueryBuilder('o')->select($select)
  404.             ->andWhere('o.release_date < :date OR o.release_date is NULL AND o.create_date < :date')
  405.             ->setParameter('date'$currentDate)
  406.             ->andWhere('o.Status = 1');
  407.         return $qb;
  408.     }
  409.     /**
  410.      * パラメータからブログ詳細を取得する
  411.      *
  412.      * @param int|string $id
  413.      * @return Blog|null
  414.      */
  415.     public function getBlogDetailByIdOrSlug($id)
  416.     {
  417.         $blogDetail null;
  418.         //postgresql→int の最大値:2147483647だから、最大値を超えるとSlug として判断
  419.         if (is_numeric($id) && $id <= 2147483647) {
  420.             $blogDetail $this->blogRepository->find($id);
  421.             // 数字slugの対応
  422.             if (!$blogDetail) {
  423.                 $blogDetail $this->blogRepository->findOneBy(['slug' => $id]);
  424.             }
  425.         } else {
  426.             $blogDetail $this->blogRepository->findOneBy(['slug' => $id]);
  427.         }
  428.         if ($blogDetail) {
  429.             return $blogDetail;
  430.         } else {
  431.             return null;
  432.         }
  433.     }
  434.     /**
  435.      * 記事に指定したカテゴリが含まれるか判別する
  436.      *
  437.      * @param Blog $entries
  438.      * @param int $targetCategoryId
  439.      * @return boolean
  440.      */
  441.     public function hasCategoryId($entry$targetCategoryId)
  442.     {
  443.         foreach ($entry->getBlogCategories() as $entryCategory) {
  444.             if ($entryCategory->getCategoryId() == $targetCategoryId) {
  445.                 return true;
  446.             }
  447.         }
  448.         return false;
  449.     }
  450.     /**
  451.      * 月別アーカイブ表示のため取得
  452.      *
  453.      * @param array $search
  454.      *
  455.      * @return array 月別配列
  456.      */
  457.     public function setMonthArchive($search = [])
  458.     {
  459.         $releaseDate $this->blogRepository->getReleaseDate($search);
  460.         $monthArr = [];
  461.         foreach ($releaseDate as $val) {
  462.             if (is_null($val['release_date'])) {
  463.                 continue;
  464.             }
  465.             $key $val['release_date']->format('Y-m');
  466.             if (isset($monthArr[$key])) {
  467.                 continue;
  468.             }
  469.             $monthArr[$key] = $val['release_date']->format('Y年m月');
  470.         }
  471.         return $monthArr;
  472.     }
  473. }