src/WebBundle/Repository/PublicationRepository.php line 303

Open in your IDE?
  1. <?php
  2. namespace WebBundle\Repository;
  3. use DateTime;
  4. use Doctrine\ORM\QueryBuilder;
  5. use Exception;
  6. use FlexApp\Classes\CommentableEntityTypes;
  7. use FlexApp\Constant\TimeConstant;
  8. use WebBundle\Controller\PublicationController;
  9. use WebBundle\Helper\App;
  10. use WebBundle\Helper\ArrHelper;
  11. use WebBundle\Helper\LocaleHelper;
  12. use WebBundle\Helper\TranslitHelper;
  13. class PublicationRepository extends ExtendEntityRepository
  14. {
  15.     /**
  16.      * Получаем публикации с учетом локали, где есть хотя бы один коммент
  17.      * @param $locale
  18.      * @return array
  19.      */
  20.     public function getActivePagesArrays($locale): array
  21.     {
  22.         $query $this->getEntityManager()->createQuery("
  23.             SELECT
  24.                 DISTINCT p.unid as portalThemeUnid
  25.             FROM WebBundle\Entity\Publication p
  26.             JOIN FlexApp\Entity\CommentEntity c
  27.                 WITH COLLATE(p.unid,utf8mb4_unicode_ci) = COLLATE(c.commentableUnid,utf8mb4_unicode_ci)
  28.                 AND c.locale = :locale
  29.         ");
  30.         $query->setParameter('locale'$locale);
  31.         $result $query->getResult();
  32.         foreach ($result as &$row) {
  33.             $row['locale'] = $locale;
  34.             $row['type'] = CommentableEntityTypes::PUBLICATION;
  35.         }
  36.         return $result;
  37.     }
  38.     /**
  39.      * Это надо для админки в основном
  40.      * @param string $alias
  41.      * @return QueryBuilder
  42.      */
  43.     public function joinQuery($alias 'b')
  44.     {
  45.         $q $this->createQueryBuilder($alias);
  46.         $q->select("{$alias}, url, body, title, description, keywords, statusShow, statusTranslate, hideSingle, preview, likes, author")
  47.             ->leftJoin("{$alias}.url"'url')
  48.             ->leftJoin("{$alias}.body"'body')
  49.             ->leftJoin("{$alias}.title"'title')
  50.             ->leftJoin("{$alias}.description"'description')
  51.             ->leftJoin("{$alias}.keywords"'keywords')
  52.             ->leftJoin("{$alias}.statusShow"'statusShow')
  53.             ->leftJoin("{$alias}.statusTranslate"'statusTranslate')
  54.             ->leftJoin("{$alias}.preview"'preview')
  55.             ->leftJoin("{$alias}.likes"'likes')
  56.             ->leftJoin("{$alias}.author"'author')
  57.             ->leftJoin("{$alias}.hideSingle"'hideSingle');
  58.         return $q;
  59.     }
  60.     /**
  61.      * @param array $param
  62.      * @return array
  63.      * @throws Exception
  64.      * Фильтрация должна быть одинаковая с
  65.      * @see PublicationRepository::getPublicationsCount
  66.      */
  67.     public function getIdsForShortShow(array $param = []): array
  68.     {
  69.         $locale = !empty($param['locale']) ? $param['locale'] : App::getCurLocale();
  70.         $cc = !empty($param['country']) ? $param['country'] : App::getCurCountry();
  71.         $hideSingle = !isset($param['hideSingle']) || boolval($param['hideSingle']);
  72.         $s $this
  73.             ->createQueryBuilder('b')
  74.             ->select('b.id, b.publishDate, b.hideCountries')
  75.             ->leftJoin('b.body''body')
  76.             ->leftJoin('b.statusShow''statusShow')
  77.             ->leftJoin('b.hideSingle''hideSingle')
  78.             ->andWhere('b.enable = true')
  79.             ->andWhere("statusShow.{$locale} = true")
  80.             ->andWhere("body.{$locale} != ''")
  81.             ->andWhere("hideSingle.{$locale} = :hideSingle")
  82.             ->setParameter('hideSingle'$hideSingle)
  83.             ->orderBy('b.publishDate''ASC');
  84.         //блог по снижению ват показываем только для Германии
  85.         if (App::getCurCountry() != 'de') {
  86.             $s->andWhere('b.id <> :idDe')
  87.                 ->setParameter('idDe'2235);
  88.         }
  89.         $q $s->getQuery()->setQueryCacheLifetime(300);
  90.         $data $q->getArrayResult();
  91.         $data array_filter($data, static fn(array $item) => !in_array($cc$item['hideCountries'] ?? []));
  92.         return array_map(function (array $item) {
  93.             $item['t'] = 'blog';
  94.             /**  @var DateTime $date */
  95.             $date $item['publishDate'];
  96.             $item['date'] = $date->getTimestamp();
  97.             return $item;
  98.         }, $data);
  99.     }
  100.     /**
  101.      * @param $ids
  102.      * @param array $param
  103.      * @return array
  104.      * @throws Exception
  105.      */
  106.     public function getByIdsForShortShow($ids$param = [])
  107.     {
  108.         $ids is_array($ids) ? $ids : [$ids];
  109.         $lc = !empty($param['locale']) ? $param['locale'] : App::getCurLocale();
  110.         $cn App::getCurCountry();
  111.         // блог по снижению ват показываем только для Германии
  112.         if ($cn != 'de') {
  113.             if ($idsx array_search(2235$ids)) {
  114.                 unset($ids[$idsx]);
  115.             }
  116.         }
  117.         $idss implode(','$ids);
  118.         $sql "SELECT
  119.                 p.id,
  120.                 p.enable,
  121.                 p.unid,
  122.                 p.view,
  123.                 p.publish_date AS `publishDate`,
  124.                 p.hide_countries AS `hideCountries`,
  125.                 lcurl.{$lc} AS `url`,
  126.                 lctitle.{$lc} AS `title`,
  127.                 lchtml.{$lc} AS `body`,
  128.                 lcssShow.{$lc} AS `statusShow`,
  129.                 lchs.{$lc} AS `hideSingle`,
  130.                 lcpw.def AS `preview.def`,
  131.                 lcpw.en AS `preview.en`,
  132.                 lcpw.{$lc} AS `preview.lc`,
  133.                 COUNT(DISTINCT cmt.id) AS `commentCnt`
  134.             FROM
  135.                 publication p
  136.             LEFT JOIN `publication_like` `plike` ON plike.publication_id = p.id
  137.             LEFT JOIN `locale_url` `lcurl` ON lcurl.publication_id = p.id
  138.             LEFT JOIN `locale_title` `lctitle` ON lctitle.publication_id = p.id
  139.             LEFT JOIN `locale_html` `lchtml` ON lchtml.publication_body_id = p.id
  140.             LEFT JOIN `locale_bool` `lcssShow` ON lcssShow.blog_show_id = p.id
  141.             LEFT JOIN `locale_bool` `lchs` ON lchs.blog_hide_single_id = p.id
  142.             LEFT JOIN `locale_preview` `lcpw` ON lcpw.publication_id = p.id
  143.             LEFT JOIN `comment_refact` `cmt` ON cmt.commentable_unid = p.unid AND cmt.locale = '{$lc}'
  144.             WHERE p.id IN ({$idss})
  145.             GROUP BY p.id;";
  146.         $conn $this->_em->getConnection();
  147.         $rows $conn->fetchAllAssociative($sql);
  148.         $res = [];
  149.         foreach ($rows as $row) {
  150.             if (!$row['url'] and !$row['title'] and !$row['body']) {
  151.                 continue;
  152.             }
  153.             $preview $row['preview.lc'];
  154.             if (!$preview) {
  155.                 $preview = !empty($row['preview.def']) ? $row['preview.def'] : null;
  156.                 if (!$preview) {
  157.                     $preview = !empty($row['preview.en']) ? $row['preview.en'] : null;
  158.                 }
  159.             }
  160.             $hideCountries $row['hideCountries'];
  161.             if ($hideCountries) {
  162.                 $hideCountries json_decode($hideCountriestrue);
  163.             } else {
  164.                 $hideCountries = [];
  165.             }
  166.             $item = [
  167.                 't'             => 'blog',
  168.                 'id'            => $row['id'],
  169.                 'unid'          => $row['unid'],
  170.                 'url'           => $row['url'],
  171.                 'title'         => html_entity_decode($row['title']),
  172.                 'body'          => html_entity_decode(LocaleHelper::modifeLinkForLocales($row['body'])),
  173.                 'preview'       => $preview,
  174.                 'enable'        => boolval($row['enable']),
  175.                 'statusShow'    => boolval($row['statusShow']),
  176.                 'hideSingle'    => boolval($row['hideSingle']),
  177.                 'hideCountries' => $hideCountries,
  178.                 'commentCnt'    => intval($row['commentCnt']),
  179.                 'view'          => intval($row['view']),
  180.                 'publishDate'   => DateTime::createFROMFormat('Y-m-d H:i:s'$row['publishDate']),
  181.             ];
  182.             $res[$row['id']] = $item;
  183.         }
  184.         return $res;
  185.     }
  186.     /**
  187.      * Получение блогов для карты сайта
  188.      * @param string $lc
  189.      * @param string|null $cc
  190.      * @return array
  191.      * @throws Exception
  192.      */
  193.     public function getPublicationsSEO(string $lc, ?string $cc null)
  194.     {
  195.         $oMemcache App::getMemcache();
  196.         $keyCache $this->buildCacheId(__METHOD__"blog.seo.{$lc}.{$cc}"$lc $cc);
  197.         $rows $oMemcache->get($keyCache);
  198.         if (!$rows) {
  199.             $hideIds '2235';
  200.             if ($lc == 'ru') {
  201.                 $hideIds .= ',' PublicationController::BLOG_ABOUT_SAMPLE_ID;
  202.             }
  203.             $sql "SELECT
  204.                 p.id,
  205.                 lcTitle.{$lc} AS title,
  206.                    lcUrl.{$lc} AS url,
  207.                    p.hide_countries AS hideCountries
  208.             FROM
  209.                 publication p
  210.             LEFT JOIN `locale_title` `lcTitle` ON lcTitle.publication_id = p.id
  211.             LEFT JOIN `locale_url` `lcUrl` ON lcUrl.publication_id = p.id
  212.             LEFT JOIN `locale_bool` `lcShow` ON lcShow.blog_show_id = p.id
  213.             LEFT JOIN `locale_bool` `lcSingle` ON lcSingle.blog_hide_single_id = p.id
  214.             WHERE p.enable = 1
  215.               AND p.author IS NOT NULL
  216.               AND lcUrl.{$lc} IS NOT NULL
  217.               AND lcShow.{$lc} = 1
  218.               AND lcSingle.{$lc} != 1
  219.               AND p.id NOT IN ({$hideIds})
  220.             ;
  221.             ";
  222.             $conn $this->_em->getConnection();
  223.             $rows $conn->fetchAllAssociative($sql);
  224.             foreach ($rows as $i => $row) {
  225.                 if ($row['hideCountries']) {
  226.                     if ($c json_decode($row['hideCountries'], true)) {
  227.                         if ($cc) {
  228.                             if (in_array($cc$c)) {
  229.                                 unset($rows[$i]);
  230.                             }
  231.                         } else {
  232.                             if (in_array($lc$c)) {
  233.                                 unset($rows[$i]);
  234.                             }
  235.                         }
  236.                     }
  237.                 }
  238.             }
  239.             // кеш на неделю
  240.             $oMemcache->set($keyCache$rowsMEMCACHE_COMPRESSED, (int) TimeConstant::WEEK);
  241.         }
  242.         return $rows;
  243.     }
  244.     /**
  245.      * Обновление статистики просмотров
  246.      * @param $id
  247.      * @throws \Doctrine\DBAL\Exception
  248.      */
  249.     public function updView($id)
  250.     {
  251.         $conn $this->getEntityManager()->getConnection();
  252.         $conn->executeStatement("UPDATE `publication` SET `view` = `view` + 1  WHERE `id` = {$id};");
  253.     }
  254.     public function getKey($id$locale)
  255.     {
  256.         $q $this->createQueryBuilder('p')
  257.             ->select('u.' $locale ' url')
  258.             ->leftJoin('p.url''u')
  259.             ->andWhere('p.id = :id')
  260.             ->setParameter('id'$id);
  261.         $r $q->getQuery()
  262.             ->useQueryCache(true)
  263.             ->enableResultCache(3600);
  264.         $item $r->getArrayResult();
  265.         return count($item) > $item[0]['url'] : null;
  266.     }
  267.     /**
  268.      * @param      $url
  269.      * @param null $locale
  270.      * @return array|null
  271.      */
  272.     public function getBlogByUrlForDTO($url$locale null)
  273.     {
  274.         $q $this->createQueryBuilder('p')
  275.             ->select('p, url, body, title, description, keywords, statusShow, hideSingle, preview, likes, author')
  276.             ->leftJoin('p.url''url')
  277.             ->leftJoin('p.body''body')
  278.             ->leftJoin('p.title''title')
  279.             ->leftJoin('p.description''description')
  280.             ->leftJoin('p.keywords''keywords')
  281.             ->leftJoin('p.statusShow''statusShow')
  282.             ->leftJoin('p.preview''preview')
  283.             ->leftJoin('p.likes''likes')
  284.             ->leftJoin('p.author''author')
  285.             ->leftJoin('p.hideSingle''hideSingle');
  286.         if ($locale) {
  287.             $q->andWhere("url.{$locale} = :url")->setParameter('url'$url);
  288.         } else {
  289.             foreach (LocaleHelper::getList() as $lc => $item) {
  290.                 $key "url{$lc}";
  291.                 $q->orWhere("url.{$lc} = :{$key}")->setParameter($key$url);
  292.             }
  293.         }
  294.         $r $q->getQuery();
  295.         $item $r->getArrayResult();
  296.         if (count($item) == 1) {
  297.             $item $item[0];
  298.         } else {
  299.             $item null;
  300.         }
  301.         return $item;
  302.     }
  303.     /**
  304.      * @param      $id
  305.      * @param null $locale
  306.      * @param bool $preview
  307.      * @return mixed|null
  308.      * @throws Exception
  309.      */
  310.     public function getPublication($id$locale null$preview false)
  311.     {
  312.         $locale $locale $locale App::getCurLocale();
  313.         $oMemcache App::getMemcache();
  314.         $keyCache $this->buildCacheId(__METHOD__$id$locale);
  315.         $data $oMemcache->get($keyCache);
  316.         // если $preview, то кеш не используем
  317.         if (!$preview) {
  318.             $data null;
  319.         }
  320.         if (!$data) {
  321.             $s $this
  322.                 ->joinQuery()
  323.                 ->setMaxResults(1);
  324.             if (App::isInt($id)) {
  325.                 $s->andWhere('b.id = :id')->setParameters(['id' => $id]);
  326.             } else {
  327.                 // если не ID, то значит urlKey и ведем поиск по нему
  328.                 $s->andWhere("url.{$locale} = :id")->setParameter('id'$id);
  329.             }
  330.             if (!$preview) {
  331.                 $s->andWhere('b.enable = true');
  332.             }
  333.             $q $s->getQuery()->useQueryCache(true);
  334.             $data ArrHelper::get($q->getArrayResult(), '0');
  335.             if (!$data) {
  336.                 return null;
  337.             }
  338.             $url ArrHelper::get($data"url.{$locale}");
  339.             $title ArrHelper::get($data"title.{$locale}");
  340.             $body ArrHelper::get($data"body.{$locale}");
  341.             $description ArrHelper::get($data"description.{$locale}");
  342.             $keywords ArrHelper::get($data"keywords.{$locale}");
  343.             $statusShow ArrHelper::get($data"statusShow.{$locale}");
  344.             $statusTranslate ArrHelper::get($data"statusTranslate.{$locale}");
  345.             $icon ArrHelper::get($data"preview.{$locale}");
  346.             // если показ закрыт, либо не зватает переводов, то проводим дополнительные проверки
  347.             if (!$statusShow or !$body or !$title) {
  348.                 $localeDef LocaleHelper::getDefault();
  349.                 if ($locale == $localeDef) {
  350.                     // если локаль совпалает с дефолтной, то сразу выдаем NULL
  351.                     return null;
  352.                 } else {
  353.                     // получаем тексты для дефолтной локали
  354.                     $title ArrHelper::get($data"title.{$localeDef}");
  355.                     $body ArrHelper::get($data"body.{$localeDef}");
  356.                     $description ArrHelper::get($data"description.{$localeDef}");
  357.                     $keywords ArrHelper::get($data"keywords.{$localeDef}");
  358.                     $statusShow ArrHelper::get($data"statusShow.{$localeDef}");
  359.                     $statusTranslate ArrHelper::get($data"statusTranslate.{$localeDef}");
  360.                     $icon ArrHelper::get($data"preview.{$localeDef}");
  361.                 }
  362.             }
  363.             if (!$icon) {
  364.                 $icon ArrHelper::get($data"preview.default");
  365.             }
  366.             // дополнительная проверка
  367.             if (!$statusShow or !$body or !$title) {
  368.                 return null;
  369.             }
  370.             $data['url'] = $url;
  371.             $data['title'] = html_entity_decode($title);
  372.             $data['body'] = html_entity_decode(LocaleHelper::modifeLinkForLocales($body));
  373.             $data['description'] = $description;
  374.             $data['keywords'] = $keywords;
  375.             $data['statusShow'] = $statusShow;
  376.             $data['statusTranslate'] = $statusTranslate;
  377.             $data['preview'] = $icon;
  378.         }
  379.         return $data;
  380.     }
  381.     /**
  382.      * Количество активных блогов по локали
  383.      * @param array $param
  384.      * @return int
  385.      * @throws Exception фильтрация должна быть одинаковая с
  386.      * @see PublicationRepository::getIdsForShortShow
  387.      */
  388.     public function getPublicationsCount(array $param): int
  389.     {
  390.         $cc App::getCurCountry();
  391.         $oMemcache App::getMemcache();
  392.         $keyCache $this->buildCacheId(__METHOD__$cc$param['locale']);
  393.         $cnt $oMemcache->get($keyCache);
  394.         if (!$cnt) {
  395.             unset($param['offset'], $param['limit']);
  396.             $cnt count($this->getIdsForShortShow($param));
  397.             // кеш на неделю
  398.             $oMemcache->set($keyCache$cntMEMCACHE_COMPRESSED, (int) TimeConstant::WEEK);
  399.         }
  400.         return intval($cnt);
  401.     }
  402.     /**
  403.      * @param null $ids
  404.      * @param null $limit
  405.      * @return array|null
  406.      */
  407.     public function getPublicationsParticipant($ids null$limit null)
  408.     {
  409.         $q $this
  410.             ->createQueryBuilder('p');
  411.         if ($ids) {
  412.             $ids TranslitHelper::replaceSpace($ids);
  413.             $IDS explode(','$ids);
  414.             $q->andWhere('p.id in (:ids)')
  415.                 ->setParameter('ids'$IDS);
  416.         }
  417.         if ($limit) {
  418.             $q->setMaxResults($limit);
  419.         }
  420.         $r $q->getQuery();
  421.         return $r->getResult();
  422.     }
  423.     /**
  424.      * Получение списка для проверки на наличие кириллических символов
  425.      * @return array
  426.      */
  427.     public function getCollectionsAdmForCheckCyrillic()
  428.     {
  429.         $q $this->createQueryBuilder('p')
  430.             ->select('p, body, title')
  431.             ->leftJoin('p.body''body')
  432.             ->leftJoin('p.title''title')
  433.             ->andWhere("p.enable = true");
  434.         return $q->getQuery()->getArrayResult();
  435.     }
  436.     /**
  437.      * Получение списка для проверки на наличие кириллических символов
  438.      * @return array
  439.      * @throws \Doctrine\DBAL\Exception
  440.      */
  441.     public function admGetListForLiMenuSelect()
  442.     {
  443.         $sql "SELECT
  444.                 p.id,
  445.                    lc.ru AS name
  446.             FROM
  447.                 publication p
  448.             LEFT JOIN `locale_title` `lc` ON `lc`.publication_id = `p`.id
  449.             ORDER BY lc.ru ;
  450.             ";
  451.         $conn $this->_em->getConnection();
  452.         $rows $conn->fetchAllAssociative($sql);
  453.         $items = [];
  454.         foreach ($rows as $row) {
  455.             $items[$row['id']] = $row['name'];
  456.         }
  457.         return $items;
  458.     }
  459.     /**
  460.      * отдаем сразу URL или NULL
  461.      * @param bool|null $forPage
  462.      * @return string|null
  463.      * @throws \Doctrine\DBAL\Driver\Exception
  464.      * @throws \Doctrine\DBAL\Exception
  465.      * @throws Exception
  466.      */
  467.     public function getUrlBlogExpressSamples(?bool $forPage false)
  468.     {
  469.         $lc App::getCurLocale();
  470.         $cc App::getCurCountry();
  471.         // для РФ блог не показываем
  472.         if (!$forPage and $cc == 'ru') {
  473.             return null;
  474.         }
  475.         $sql "SELECT
  476.                    lu.{$lc} AS slug
  477.             FROM
  478.                 publication p
  479.             LEFT JOIN `locale_url` `lu` ON `lu`.publication_id = `p`.id
  480.             LEFT JOIN `locale_bool` `lp` ON `lp`.blog_show_id = `p`.id
  481.             LEFT JOIN `locale_status_translate` `lst` ON `lst`.publication_id = `p`.id
  482.             WHERE p.id = " PublicationController::BLOG_ABOUT_SAMPLE_ID " AND lp.{$lc} = 1 AND lst.{$lc} = 1;
  483.             ";
  484.         $conn $this->_em->getConnection();
  485.         $slug $conn->executeQuery($sql)->fetchOne();
  486.         if ($slug) {
  487.             $url App::generateUrl('app_publication_single', ['id' => $slug]);
  488.         } else {
  489.             $url null;
  490.         }
  491.         return $url;
  492.     }
  493. }