M config/packages/twig.yaml +0 -2
@@ 2,5 2,3 @@ twig:
default_path: '%kernel.project_dir%/templates'
debug: '%kernel.debug%'
strict_variables: '%kernel.debug%'
- form_themes:
- - 'forms/themes.html.twig'
M src/Controller/ArticleController.php +18 -5
@@ 3,7 3,7 @@
namespace App\Controller;
use App\Entity\Article;
-use App\Form\TagFilterType;
+use App\Form\TagLabelFilterType;
use App\Repository\ArticleRepository;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
@@ 24,12 24,25 @@ class ArticleController extends Abstract
]);
}
- public function showArchive(?int $page = 0)
+ public function showArchive(Request $request, ?int $page = 0)
{
- $pageCount = $this->articleRepository->getPageCount();
- $articles = $this->articleRepository->findPaginatedOrdered($page);
+ $itemPerPage = 10;
+ $tagLabelsFilter = [];
+ $qb = null;
- $form = $this->createForm(TagFilterType::class);
+ $form = $this->createForm(TagLabelFilterType::class);
+ $form->handleRequest($request);
+ if ($form->isSubmitted() && $form->isValid()) {
+ $tagLabelsFilter = $form->getData()['labels'];
+ $qb = $this->articleRepository->findByTagLabelsQueryBuilder($tagLabelsFilter, 'a');
+ }
+
+ $pageCount = ceil($this->articleRepository->getCount('a', $qb) / $itemPerPage);
+
+ $qb = $this->articleRepository->lastFirstQueryBuilder('a', $qb);
+ $qb = $this->articleRepository->paginateQueryBuilder($page, $itemPerPage, 'a', $qb);
+
+ $articles = $qb->getQuery()->execute();
return $this->render('article/archive.html.twig', [
'articles' => $articles,
R src/Form/TagFilterType.php => +0 -32
@@ 1,32 0,0 @@
-<?php
-
-namespace App\Form;
-
-use Symfony\Component\Form\AbstractType;
-use Symfony\Component\Form\CallbackTransformer;
-use Symfony\Component\Form\Extension\Core\Type;
-use Symfony\Component\Form\FormBuilderInterface;
-
-class TagFilterType extends AbstractType
-{
- public function buildForm(FormBuilderInterface $builder, array $options)
- {
- $builder
- ->add('tags', Type\TextType::class, [
- 'label' => 'tags'
- ])
- //->addModelTransformer(new CallbackTransformer(
- // function ($tagsAsEntities) {
- // dump($tagsAsEntities);
- // // transform the array to a string
- // return implode(', ', $tagsAsEntities);
- // },
- // function ($tagsAsString) {
- // dump($tagsAsString);
- // // transform the string back to an array
- // return explode(', ', $tagsAsString);
- // }
- //))
- ;
- }
-}
A => src/Form/TagLabelFilterType.php +45 -0
@@ 0,0 1,45 @@
+<?php
+
+namespace App\Form;
+
+use Symfony\Component\Form\AbstractType;
+use Symfony\Component\Form\CallbackTransformer;
+use Symfony\Component\Form\FormBuilderInterface;
+use Symfony\Component\Form\Extension\Core\Type;
+use Symfony\Component\OptionsResolver\OptionsResolver;
+
+class TagLabelFilterType extends AbstractType
+{
+ public function buildForm(FormBuilderInterface $builder, array $options)
+ {
+ $builder
+ ->add('labels', Type\TextType::class, [
+ 'label' => false,
+ 'required' => false,
+ 'attr' => [
+ 'placeholder' => 'tags'
+ ]
+ ])
+ ->get('labels')
+ ->addModelTransformer(new CallbackTransformer(
+ function ($tagsAsArray) {
+ return null;
+ },
+ function ($tagsAsString) {
+ if (null === $tagsAsString) {
+ return [];
+ }
+ return explode(' ', $tagsAsString);
+ }
+ ))
+ ;
+ }
+
+ public function configureOptions(OptionsResolver $resolver)
+ {
+ $resolver->setDefaults([
+ 'method' => 'get',
+ 'csrf_protection' => false,
+ ]);
+ }
+}
M src/Repository/ArticleRepository.php +55 -18
@@ 4,6 4,7 @@ namespace App\Repository;
use App\Entity\Article;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
+use Doctrine\ORM\QueryBuilder;
use Symfony\Bridge\Doctrine\RegistryInterface;
class ArticleRepository extends ServiceEntityRepository
@@ 13,27 14,63 @@ class ArticleRepository extends ServiceE
parent::__construct($registry, Article::class);
}
- public function getPageCount(?int $itemPerPage = 5): int
+ public function paginateQueryBuilder(int $page, int $itemPerPage, ?string $alias = 'a', ?QueryBuilder $qb = null): QueryBuilder
+ {
+ if (null === $qb) {
+ $qb = $this->createQueryBuilder($alias);
+ }
+
+ return $qb
+ ->setFirstResult($page * $itemPerPage)
+ ->setMaxResults($itemPerPage)
+ ;
+ }
+
+ public function lastFirstQueryBuilder(?string $alias = 'a', ?QueryBuilder $qb = null): QueryBuilder
+ {
+ if (null === $qb) {
+ $qb = $this->createQueryBuilder($alias);
+ }
+
+ return $qb
+ ->orderBy(sprintf('%s.createdAt', $alias), 'DESC')
+ ;
+ }
+
+ public function findByTagLabelsQueryBuilder(array $tagLabels, ?string $alias = 'a', ?QueryBuilder $qb = null): QueryBuilder
{
- $count = $this
- ->createQueryBuilder('a')
- ->select('count(a.id)')
+ if (null === $qb) {
+ $qb = $this->createQueryBuilder($alias);
+ }
+
+ foreach ($tagLabels as $tagLabel) {
+ $tagJoin = sprintf('t%d', uniqid(rand()));
+ $qb
+ ->join(
+ sprintf('%s.tags', $alias),
+ $tagJoin,
+ 'WITH',
+ sprintf('%s.label = :tagLabel%s', $tagJoin, $tagJoin)
+ )
+ ->setParameter(sprintf('tagLabel%s', $tagJoin), $tagLabel)
+ ;
+ }
+
+ return $qb;
+ }
+
+ public function getCount(?string $alias = 'a', ?QueryBuilder $qb = null): int
+ {
+ if (null === $qb) {
+ $qb = $this->createQueryBuilder($alias);
+ } else {
+ $qb = clone $qb;
+ }
+
+ return $qb
+ ->select(sprintf('count(%s.id)', $alias))
->getQuery()
->getSingleScalarResult()
;
-
- return ceil($count / $itemPerPage);
- }
-
- public function findPaginatedOrdered(?int $page = 0, ?int $itemPerPage = 5): array
- {
- return $this
- ->createQueryBuilder('a')
- ->setFirstResult($page * $itemPerPage)
- ->setMaxResults($itemPerPage)
- ->orderBy('a.createdAt', 'DESC')
- ->getQuery()
- ->execute()
- ;
}
}
M templates/article/archive.html.twig +2 -2
@@ 16,12 16,12 @@
<div class="pagination">
{% if 0 < page %}
- <a href="{{ path('article_archive', {'page': page-1}) }}">Page {{ page-1 }}</a>
+ <a href="{{ path('article_archive', app.request.query.all|merge({'page': page-1})) }}">Page {{ page-1 }}</a>
{% else %}
<span></span>
{% endif %}
{% if page + 1 < pageCount %}
- <a href="{{ path('article_archive', {'page': page+1}) }}">Page {{ page+1 }}</a>
+ <a href="{{ path('article_archive', app.request.query.all|merge({'page': page+1})) }}">Page {{ page+1 }}</a>
{% else %}
<span></span>
{% endif %}
R templates/forms/themes.html.twig => +0 -5
@@ 1,5 0,0 @@
-{% block tag_filter_widget %}
- <div>
- {{ form_widget(form.tags, {'attr': {'placeholder': form.tags.vars.label}}) }}
- </div>
-{% endblock %}