src/WebBundle/Repository/PublicationRepository.php line 295

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