]> Raphaël G. Git Repositories - blogbundle/blobdiff - Repository/ArticleRepository.php
Use entity id as last resort sorting parameter
[blogbundle] / Repository / ArticleRepository.php
index 9dd1556c13bd36f469631cfee380d2b52db6cd15..a2e1a5eb3576e9168eb0ea60755eb7544d14f38b 100644 (file)
-<?php
+<?php declare(strict_types=1);
+
+/*
+ * This file is part of the Rapsys BlogBundle package.
+ *
+ * (c) Raphaël Gertz <symfony@rapsys.eu>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
 
 namespace Rapsys\BlogBundle\Repository;
 
+use Doctrine\ORM\Query\ResultSetMapping;
+
 /**
  * ArticleRepository
  *
  * This class was generated by the Doctrine ORM. Add your own custom
  * repository methods below.
  */
-class ArticleRepository extends \Doctrine\ORM\EntityRepository {
+class ArticleRepository extends EntityRepository {
        /**
-        * Find article
+        * Find article count as int
         *
-        * @param string $_locale
-        * @param string $_article
+        * @return integer The articles count
         */
-       public function findArticle($_locale, $_article) {
-#              //TODO: voir comment faire ça sans gros hack sql ?
-#              //Declare all field
-#              $rsm = new \Doctrine\ORM\Query\ResultSetMapping();
-#              $rsm->addScalarResult('id', 'id');
-#              $rsm->addScalarResult('created', 'created');
-#              $rsm->addScalarResult('updated', 'updated');
-#              $rsm->addScalarResult('slug', 'slug');
-#              $rsm->addScalarResult('title', 'title');
-#              $rsm->addScalarResult('description', 'description');
-#              $rsm->addScalarResult('body', 'body');
-#              $rsm->addScalarResult('keywords', 'keywords');
-#              $rsm->addScalarResult('slugs', 'slugs');
-#
-#              //Fetch article
-#              $ret = $this->getEntityManager()
-#                      #->createQuery('SELECT b.*, JSON(bl.iso6391, bat.slug) AS slugs FROM (SELECT a.id, a.created, a.updated, at.slug, at.title, at.description, at.body, JSON(kt.slug, kt.title) AS keywords FROM RapsysBlogBundle:Article a JOIN RapsysBlogBundle:ArticleTranslation at WITH (at.article_id = a.id AND at.slug = :_article) JOIN RapsysBlogBundle:Language AS l WITH (l.id = at.language_id AND l.iso6391 = :_locale) LEFT JOIN RapsysBlogBundle:ArticleKeyword ak WITH (ak.article_id = a.id) LEFT JOIN RapsysBlogBundle:KeywordTranslation kt WITH (kt.keyword_id = ak.keyword_id AND kt.language_id = at.language_id) GROUP BY a.id) b LEFT JOIN RapsysBlogBundle:Language AS bl WITH (bl.iso6391 <> :_locale) LEFT JOIN RapsysBlogBundle:ArticleTranslation bat WITH (bat.language_id = bl.id AND bat.article_id = b.id) GROUP BY b.id')
-#                      ->createNativeQuery('SELECT b.*, CONCAT(\'{\', GROUP_CONCAT(CONCAT(\'"\', REPLACE(bl.iso6391, \'"\', \'\\\\"\'), \'": "\', REPLACE(bat.slug, \'"\', \'\\\\"\'), \'"\')), \'}\') AS slugs FROM (SELECT a.id, a.created, a.updated, at.slug, at.title, at.description, at.body, CONCAT(\'{\', GROUP_CONCAT(CONCAT(\'"\', REPLACE(kt.slug, \'"\', \'\\\\"\'), \'": "\', REPLACE(kt.title, \'"\', \'\\\\"\'), \'"\')), \'}\') AS keywords FROM articles a JOIN articles_translations at ON (at.article_id = a.id AND at.slug = ?) JOIN languages AS l ON (l.id = at.language_id AND l.iso6391 = ?) LEFT JOIN articles_keywords ak ON (ak.article_id = a.id) LEFT JOIN keywords_translations kt ON (kt.keyword_id = ak.keyword_id AND kt.language_id = at.language_id) GROUP BY a.id) b LEFT JOIN languages AS bl ON (bl.iso6391 <> ?) LEFT JOIN articles_translations bat ON (bat.language_id = bl.id AND bat.article_id = b.id) GROUP BY b.id', $rsm)
-#                      ->setParameter(0, $_article)
-#                      ->setParameter(1, $_locale)
-#                      ->setParameter(2, $_locale)
-#                      ->getSingleResult();
-#              //Decode json
-#              if (!empty($ret['keywords'])) {
-#                      $ret['keywords'] = json_decode($ret['keywords'], true);
-#              }
-#              if (!empty($ret['slugs'])) {
-#                      $ret['slugs'] = json_decode($ret['slugs'], true);
-#              }
-#              //Send result
-#              return $ret;
-#
-               //Fetch article
-               $ret = $this->getEntityManager()
-                       #->createQuery('SELECT b.*, JSON(bl.iso6391, bat.slug) AS slugs FROM (SELECT a.id, a.created, a.updated, at.slug, at.title, at.description, at.body, JSON(kt.slug, kt.title) AS keywords FROM RapsysBlogBundle:Article a JOIN RapsysBlogBundle:ArticleTranslation at WITH (at.article_id = a.id AND at.slug = :_article) JOIN RapsysBlogBundle:Language AS l WITH (l.id = at.language_id AND l.iso6391 = :_locale) LEFT JOIN RapsysBlogBundle:ArticleKeyword ak WITH (ak.article_id = a.id) LEFT JOIN RapsysBlogBundle:KeywordTranslation kt WITH (kt.keyword_id = ak.keyword_id AND kt.language_id = at.language_id) GROUP BY a.id) b LEFT JOIN RapsysBlogBundle:Language AS bl WITH (bl.iso6391 <> :_locale) LEFT JOIN RapsysBlogBundle:ArticleTranslation bat WITH (bat.language_id = bl.id AND bat.article_id = b.id) GROUP BY b.id')
-                       ->createQuery('SELECT a.id, a.created, a.updated, at.slug, at.title, at.description, at.body, JSON(kt.slug, kt.title) AS keywords FROM RapsysBlogBundle:Article a JOIN RapsysBlogBundle:ArticleTranslation at WITH (at.article_id = a.id AND at.slug = :_article) JOIN RapsysBlogBundle:Language AS l WITH (l.id = at.language_id AND l.iso6391 = :_locale) LEFT JOIN RapsysBlogBundle:ArticleKeyword ak WITH (ak.article_id = a.id) LEFT JOIN RapsysBlogBundle:KeywordTranslation kt WITH (kt.keyword_id = ak.keyword_id AND kt.language_id = at.language_id) GROUP BY a.id')
-                       ->setParameter('_locale', $_locale)
-                       ->setParameter('_article', $_article)
-                       ->getSingleResult();
-
-               //Decode json
-               if (!empty($ret['keywords'])) {
-                       $ret['keywords'] = json_decode($ret['keywords'], true);
-               }
+       public function findCountAsInt(): int {
+               //Set the request
+               $req = <<<SQL
+SELECT COUNT(at.article_id) AS count
+FROM RapsysBlogBundle:ArticleTranslation AS at
+WHERE at.locale = :locale
+SQL;
 
-               //Fetch article's slugs in other locale
-               $slugs = $this->getEntityManager()
-                       ->createQuery('SELECT JSON(bl.iso6391, bat.slug) AS slugs FROM RapsysBlogBundle:Language bl LEFT JOIN RapsysBlogBundle:ArticleTranslation bat WITH (bat.article_id = :_article AND bat.language_id = bl.id) WHERE (bl.iso6391 <> :_locale) GROUP BY bat.article_id')
-                       ->setParameter('_locale', $_locale)
-                       ->setParameter('_article', $ret['id'])
-                       ->getSingleResult();
+               //Get result set mapping instance
+               $req = $this->replace($req);
 
-               //Decode json
-               if (!empty($slugs['slugs'])) {
-                       $ret['slugs'] = json_decode($slugs['slugs'], true);
-               }
+               //Get result set mapping instance
+               //XXX: DEBUG: see ../blog.orig/src/Rapsys/BlogBundle/Repository/ArticleRepository.php
+               $rsm = new ResultSetMapping();
+
+               //Declare all fields
+               //XXX: see vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/Types.php
+               //addScalarResult($sqlColName, $resColName, $type = 'string');
+               $rsm->addScalarResult('count', 'count', 'integer');
 
-               //Send result
-               return $ret;
+               //Get result
+               return $this->_em
+                       ->createNativeQuery($req, $rsm)
+                       ->getSingleScalarResult();
        }
 
        /**
-        * Find articles
+        * Find articles as array
         *
-        * @param string $_locale
+        * @param integer $page The page
+        * @param integer $count The count
+        * @return array The articles array
         */
-       public function findArticles($_locale) {
-               //Fetch articles
-               $ret = $this->getEntityManager()
-                        ->createQuery('SELECT a.id, a.created, a.updated, at.slug, at.title, at.description, JSON(kt.slug, kt.title) AS keywords FROM RapsysBlogBundle:Article a JOIN RapsysBlogBundle:ArticleTranslation at WITH (at.article_id = a.id) JOIN RapsysBlogBundle:Language AS l WITH (l.id = at.language_id AND l.iso6391 = :_locale) LEFT JOIN RapsysBlogBundle:ArticleKeyword ak WITH (ak.article_id = a.id) LEFT JOIN RapsysBlogBundle:KeywordTranslation kt WITH (kt.keyword_id = ak.keyword_id AND kt.language_id = at.language_id) GROUP BY a.id')
-                        ->setParameter('_locale', $_locale)
-                       ->execute();
-               //Decode json
-               if (!empty($ret)) {
-                       foreach ($ret as $id => $article) {
-                               if (!empty($article['keywords'])) {
-                                       $ret[$id]['keywords'] = json_decode($article['keywords'], true);
-                               }
+       public function findAllAsArray(int $page, int $count): array {
+               //Set the request
+               $req = <<<SQL
+SELECT
+       a.id,
+       GREATEST(a.created, at.created, k.created, kt.created) AS created,
+       GREATEST(a.updated, at.updated, k.updated, kt.updated) AS updated,
+       GREATEST(a.created, at.created, k.created, kt.created, a.updated, at.updated, k.updated, kt.updated) as modified,
+       at.body,
+       at.description,
+       at.slug,
+       at.title,
+       GROUP_CONCAT(k.id ORDER BY k.id SEPARATOR "\\n") AS k_ids,
+       GROUP_CONCAT(kt.slug ORDER BY k.id SEPARATOR "\\n") AS k_slugs,
+       GROUP_CONCAT(kt.title ORDER BY k.id SEPARATOR "\\n") AS k_titles
+FROM RapsysBlogBundle:Article AS a
+JOIN RapsysBlogBundle:ArticleTranslation AS at ON (at.article_id = a.id AND at.locale = :locale)
+LEFT JOIN RapsysBlogBundle:ArticleKeyword AS ak ON (ak.article_id = a.id)
+LEFT JOIN RapsysBlogBundle:Keyword AS k ON (k.id = ak.keyword_id)
+LEFT JOIN RapsysBlogBundle:KeywordTranslation AS kt ON (kt.keyword_id = k.id AND kt.locale = :locale)
+GROUP BY a.id
+ORDER BY updated, created DESC, a.id
+LIMIT :offset, :count
+SQL;
+
+               //Replace bundle entity name by table name
+               $req = $this->replace($req);
+
+               //Get result set mapping instance
+               //XXX: DEBUG: see ../blog.orig/src/Rapsys/BlogBundle/Repository/ArticleRepository.php
+               $rsm = new ResultSetMapping();
+
+               //Declare all fields
+               //XXX: see vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/Types.php
+               //addScalarResult($sqlColName, $resColName, $type = 'string');
+               $rsm->addScalarResult('id', 'id', 'integer')
+                       ->addScalarResult('body', 'body', 'string')
+                       ->addScalarResult('description', 'description', 'string')
+                       ->addScalarResult('slug', 'slug', 'string')
+                       ->addScalarResult('title', 'title', 'string')
+                       ->addScalarResult('k_ids', 'k_ids', 'string')
+                       ->addScalarResult('k_slugs', 'k_slugs', 'string')
+                       ->addScalarResult('k_titles', 'k_titles', 'string')
+                       ->addScalarResult('created', 'created', 'datetime')
+                       ->addScalarResult('updated', 'updated', 'datetime')
+                       ->addScalarResult('modified', 'modified', 'datetime')
+                       ->addIndexByScalar('id');
+
+               //Get result
+               $result = $this->_em
+                       ->createNativeQuery($req, $rsm)
+                       ->setParameter('offset', $page * $count)
+                       ->setParameter('count', $count)
+                       ->getArrayResult();
+
+               //Set return
+               $return = [];
+
+               //Iterate on each city
+               foreach($result as $data) {
+                       //Add to return
+                       $return[$data['id']] = [
+                               'id' => $id = $data['id'],
+                               'body' => $data['body'],
+                               'description' => $data['description'],
+                               'slug' => $slug = $data['slug'],
+                               'title' => $data['title'],
+                               'created' => $data['created'],
+                               'updated' => $data['updated'],
+                               'modified' => $data['modified'],
+                               'link' => $this->router->generate('rapsys_blog_article_view', ['id' => $id, 'slug' => $slug]),
+                               'keywords' => []
+                       ];
+
+                       //Explode keyword ids
+                       $data['k_ids'] = explode("\n", $data['k_ids']);
+
+                       //Explode keyword slugs
+                       $data['k_slugs'] = explode("\n", $data['k_slugs']);
+
+                       //Explode keyword titles
+                       $data['k_titles'] = explode("\n", $data['k_titles']);
+
+                       foreach($data['k_ids'] as $k => $id) {
+                               $return[$data['id']]['keywords'][$id] = [
+                                       'id' => $id,
+                                       'slug' => $slug = $data['k_slugs'][$k],
+                                       'title' => $data['k_titles'][$k],
+                                       'link' => $this->router->generate('rapsys_blog_keyword_view', ['id' => $id, 'slug' => $slug]),
+                               ];
                        }
                }
-               //Send result
-               return $ret;
+
+               //Return return
+               return $return;
+       }
+
+       /**
+        * Find article by id as array
+        *
+        * @param integer $id The article id
+        * @return array The article array
+        */
+       public function findByIdAsArray(int $id): array {
+               //Set the request
+               $req = <<<SQL
+SELECT
+       b.id,
+       GREATEST(b.created, kat.created) AS created,
+       GREATEST(b.updated, kat.updated) AS updated,
+       GREATEST(b.created, b.updated, kat.created, kat.updated) AS modified,
+       b.body,
+       b.description,
+       b.slug,
+       b.title,
+       b.k_ids,
+       b.k_slugs,
+       b.k_titles,
+       GROUP_CONCAT(kat.locale ORDER BY kat.locale SEPARATOR "\\n") AS kat_locales,
+       GROUP_CONCAT(kat.slug ORDER BY kat.locale SEPARATOR "\\n") AS kat_slugs,
+       GROUP_CONCAT(kat.title ORDER BY kat.locale SEPARATOR "\\n") AS kat_titles
+FROM (
+       SELECT
+               a.id,
+               GREATEST(a.created, at.created, k.created, kt.created) AS created,
+               GREATEST(a.updated, at.updated, k.updated, kt.updated) AS updated,
+               at.body,
+               at.description,
+               at.slug,
+               at.title,
+               GROUP_CONCAT(k.id ORDER BY k.id SEPARATOR "\\n") AS k_ids,
+               GROUP_CONCAT(kt.slug ORDER BY k.id SEPARATOR "\\n") AS k_slugs,
+               GROUP_CONCAT(kt.title ORDER BY k.id SEPARATOR "\\n") AS k_titles
+       FROM RapsysBlogBundle:Article AS a
+       JOIN RapsysBlogBundle:ArticleTranslation AS at ON (at.article_id = a.id AND at.locale = :locale)
+       LEFT JOIN RapsysBlogBundle:ArticleKeyword AS ak ON (ak.article_id = a.id)
+       LEFT JOIN RapsysBlogBundle:Keyword AS k ON (k.id = ak.keyword_id)
+       LEFT JOIN RapsysBlogBundle:KeywordTranslation AS kt ON (kt.keyword_id = k.id AND kt.locale = :locale)
+       WHERE a.id = :id
+       GROUP BY a.id
+       ORDER BY NULL
+       LIMIT 0, :limit
+) AS b
+LEFT JOIN RapsysBlogBundle:ArticleTranslation AS kat ON (kat.article_id = b.id AND kat.locale <> :locale)
+GROUP BY b.id
+SQL;
+
+               //Replace bundle entity name by table name
+               $req = $this->replace($req);
+
+               //Get result set mapping instance
+               //XXX: DEBUG: see ../blog.orig/src/Rapsys/BlogBundle/Repository/ArticleRepository.php
+               $rsm = new ResultSetMapping();
+
+               //Declare all fields
+               //XXX: see vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/Types.php
+               //addScalarResult($sqlColName, $resColName, $type = 'string');
+               $rsm->addScalarResult('id', 'id', 'integer')
+                       ->addScalarResult('body', 'body', 'string')
+                       ->addScalarResult('description', 'description', 'string')
+                       ->addScalarResult('slug', 'slug', 'string')
+                       ->addScalarResult('title', 'title', 'string')
+                       ->addScalarResult('k_ids', 'k_ids', 'string')
+                       ->addScalarResult('k_slugs', 'k_slugs', 'string')
+                       ->addScalarResult('k_titles', 'k_titles', 'string')
+                       ->addScalarResult('kat_locales', 'kat_locales', 'string')
+                       ->addScalarResult('kat_slugs', 'kat_slugs', 'string')
+                       ->addScalarResult('kat_titles', 'kat_titles', 'string')
+                       ->addScalarResult('created', 'created', 'datetime')
+                       ->addScalarResult('updated', 'updated', 'datetime')
+                       ->addScalarResult('modified', 'modified', 'datetime');
+
+               //Get data
+               $data = $this->_em
+                       ->createNativeQuery($req, $rsm)
+                       ->setParameter('id', $id)
+                       ->getOneOrNullResult();
+
+               //Set return
+               $return = [
+                       'id' => $id = $data['id'],
+                       'body' => $data['body'],
+                       'description' => $data['description'],
+                       'slug' => $slug = $data['slug'],
+                       'title' => $data['title'],
+                       'created' => $data['created'],
+                       'updated' => $data['updated'],
+                       'modified' => $data['modified'],
+                       'link' => $this->router->generate('rapsys_blog_article_view', ['id' => $id, 'slug' => $slug]),
+                       'alternates' => [],
+                       'keywords' => []
+               ];
+
+               //Explode keyword ids
+               $data['k_ids'] = explode("\n", $data['k_ids']);
+
+               //Explode keyword slugs
+               $data['k_slugs'] = explode("\n", $data['k_slugs']);
+
+               //Explode keyword titles
+               $data['k_titles'] = explode("\n", $data['k_titles']);
+
+               foreach($data['k_ids'] as $k => $kid) {
+                       $return['keywords'][$kid] = [
+                               'id' => $kid,
+                               'slug' => $slug = $data['k_slugs'][$k],
+                               'title' => $data['k_titles'][$k],
+                               'link' => $this->router->generate('rapsys_blog_keyword_view', ['id' => $kid, 'slug' => $slug]),
+                       ];
+               }
+
+               //Explode alternate locales
+               $data['kat_locales'] = explode("\n", $data['kat_locales']);
+
+               //Explode alternate slugs
+               $data['kat_slugs'] = explode("\n", $data['kat_slugs']);
+
+               //Explode alternate titles
+               $data['kat_titles'] = explode("\n", $data['kat_titles']);
+
+               foreach($data['kat_locales'] as $k => $locale) {
+                       $return['alternates'][$locale] = [
+                               'locale' => $locale,
+                               'slug' => $slug = $data['kat_slugs'][$k],
+                               'title' => $data['kat_titles'][$k],
+                               'link' => $this->router->generate('rapsys_blog_article_view', ['_locale' => $locale, 'id' => $id, 'slug' => $slug]),
+                       ];
+               }
+
+               //Return return
+               return $return;
        }
 }