src/Domain/BlogPost/Repository/PostRepository.php line 43

  1. <?php
  2. declare(strict_types=1);
  3. namespace App\Domain\BlogPost\Repository;
  4. use App\Domain\BlogPost\Entity\Post;
  5. use App\Domain\BlogPost\Entity\PostTag;
  6. use App\Domain\BlogPost\Pagination\Paginator;
  7. use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
  8. use Doctrine\Persistence\ManagerRegistry;
  9. use function Symfony\Component\String\u;
  10. /**
  11.  * This custom Doctrine repository contains some methods which are useful when
  12.  * querying for blog post information.
  13.  *
  14.  * See https://symfony.com/doc/current/doctrine.html#querying-for-objects-the-repository
  15.  *
  16.  * @author Ryan Weaver <weaverryan@gmail.com>
  17.  * @author Javier Eguiluz <javier.eguiluz@gmail.com>
  18.  * @author Yonel Ceruto <yonelceruto@gmail.com>
  19.  */
  20. class PostRepository extends ServiceEntityRepository
  21. {
  22.     public function __construct(ManagerRegistry $registry)
  23.     {
  24.         parent::__construct($registryPost::class);
  25.     }
  26.     public function getBySlug(string $slug): ?Post
  27.     {
  28.         // Create a query builder that is pre-configured to only select posts from slug and locale behind post translation
  29.         return $this->createQueryBuilder('p')
  30.             ->addSelect('a''t')
  31.             ->innerJoin('p.author''a')
  32.             ->leftJoin('p.translations''t')
  33.             ->where('t.slug = :slug')
  34.             ->andWhere('p.publishedAt IS NOT NULL')
  35.             ->setParameter('slug'$slug)
  36.             ->getQuery()
  37.             ->getOneOrNullResult();
  38.     }
  39.     public function findLatest(int $page 1PostTag $tag null): Paginator
  40.     {
  41.         $qb $this->createQueryBuilder('p')
  42.             ->addSelect('a''t')
  43.             ->innerJoin('p.author''a')
  44.             ->leftJoin('p.tags''t')
  45.             ->where('p.publishedAt <= :now')
  46.             ->orderBy('p.publishedAt''DESC')
  47.             ->setParameter('now', new \DateTime())
  48.         ;
  49.         if (null !== $tag) {
  50.             $qb->andWhere(':tag MEMBER OF p.tags')
  51.                 ->setParameter('tag'$tag);
  52.         }
  53.         return (new Paginator($qb))->paginate($page);
  54.     }
  55.     /**
  56.      * @return Post[]
  57.      */
  58.     public function findBySearchQuery(string $queryint $limit Paginator::PAGE_SIZE): array
  59.     {
  60.         $searchTerms $this->extractSearchTerms($query);
  61.         if (=== \count($searchTerms)) {
  62.             return [];
  63.         }
  64.         $queryBuilder $this->createQueryBuilder('p');
  65.         foreach ($searchTerms as $key => $term) {
  66.             $queryBuilder
  67.                 ->orWhere('p.title LIKE :t_'.$key)
  68.                 ->setParameter('t_'.$key'%'.$term.'%')
  69.             ;
  70.         }
  71.         return $queryBuilder
  72.             ->orderBy('p.publishedAt''DESC')
  73.             ->setMaxResults($limit)
  74.             ->getQuery()
  75.             ->getResult();
  76.     }
  77.     /**
  78.      * Transforms the search string into an array of search terms.
  79.      */
  80.     private function extractSearchTerms(string $searchQuery): array
  81.     {
  82.         $searchQuery u($searchQuery)->replaceMatches('/[[:space:]]+/'' ')->trim();
  83.         $terms array_unique($searchQuery->split(' '));
  84.         // ignore the search terms that are too short
  85.         return array_filter($terms, static function ($term) {
  86.             return <= $term->length();
  87.         });
  88.     }
  89. }