From 9921a789e5c67b2a1c724411ec741694052a3934 Mon Sep 17 00:00:00 2001 From: Tim Schumacher Date: Wed, 15 Oct 2014 17:23:12 +0200 Subject: [PATCH] Implemented search by tags with these operators: AND (&), OR (|) Fixes #30 --- .../Controller/TagController.php | 100 +++++++++++++++--- .../Resources/views/Event/index.html.twig | 35 ++++-- 2 files changed, 116 insertions(+), 19 deletions(-) diff --git a/src/Hackspace/Bundle/CalciferBundle/Controller/TagController.php b/src/Hackspace/Bundle/CalciferBundle/Controller/TagController.php index 1d0c43b..56974f5 100755 --- a/src/Hackspace/Bundle/CalciferBundle/Controller/TagController.php +++ b/src/Hackspace/Bundle/CalciferBundle/Controller/TagController.php @@ -25,6 +25,7 @@ use Jsvrcek\ICS\Utility\Formatter; use Jsvrcek\ICS\CalendarStream; use Jsvrcek\ICS\CalendarExport; use Symfony\Component\Validator\Constraints\DateTime; +use Doctrine\ORM\Query\ResultSetMappingBuilder; /** * Tag controller. @@ -47,26 +48,98 @@ class TagController extends Controller /** @var EntityRepository $repo */ $repo = $em->getRepository('CalciferBundle:Tag'); + $tags = []; + $operator = 'or'; + if (strpos($slug,'|') !== false) { + $slugs = explode('|',$slug); + foreach($slugs as $item) { + /** @var Tag $tag */ + $tag = $repo->findOneBy(['slug' => $item]); - /** @var Tag $location */ - $tag = $repo->findOneBy(['slug' => $slug]); + if ($tag instanceof Tag) { + $tags[] = $tag; + } + } + } else if (strpos($slug,'&') !== false) { + $slugs = explode('&',$slug); + $operator = 'and'; + foreach($slugs as $item) { + /** @var Tag $tag */ + $tag = $repo->findOneBy(['slug' => $item]); - if (!$tag) { + if ($tag instanceof Tag) { + $tags[] = $tag; + } + } + } else { + /** @var Tag $tag */ + $tag = $repo->findOneBy(['slug' => $slug]); + + if ($tag instanceof Tag) { + $tags[] = $tag; + } + } + + if (count($tags) == 0) { throw $this->createNotFoundException('Unable to find tag entity.'); } $now = new \DateTime(); $now->setTime(0, 0, 0); - /** @var QueryBuilder $qb */ - $qb = $em->createQueryBuilder(); - $qb->select(array('e')) - ->from('CalciferBundle:Event', 'e') - ->join('e.tags', 't', 'WITH', $qb->expr()->in('t.id', $tag->id)) - ->where('e.startdate >= :startdate') - ->orderBy('e.startdate') - ->setParameter('startdate', $now); - $entities = $qb->getQuery()->execute(); + $entities = null; + if ($operator == 'and') { + $sql = << array[@tags@] +) +AND e.startdate >= :startdate +ORDER BY e.startdate +EOF; + $tag_ids = array_reduce($tags,function($carry,$item){ + if (strlen($carry) == 0) { + return $item->id; + } else { + return $carry . ',' . $item->id; + } + }); + + $sql = str_replace('@tags@',$tag_ids,$sql); + + $rsm = new ResultSetMappingBuilder($em); + $rsm->addRootEntityFromClassMetadata('CalciferBundle:Event','e'); + + $query = $em->createNativeQuery($sql,$rsm); + + $query->setParameter('startdate',$now); + + $entities = $query->getResult(); + + } else { + /** @var QueryBuilder $qb */ + $qb = $em->createQueryBuilder(); + $qb->select(array('e')) + ->from('CalciferBundle:Event', 'e') + ->where('e.startdate >= :startdate') + ->orderBy('e.startdate') + ->setParameter('startdate', $now); + + $qb->join('e.tags', 't', 'WITH', $qb->expr()->in('t.id', array_reduce($tags,function($carry,$item){ + if (strlen($carry) == 0) { + return $item->id; + } else { + return $carry . ',' . $item->id; + } + }))); + $entities = $qb->getQuery()->execute(); + } if ($format == 'ics') { $calendar = new Calendar(); @@ -110,7 +183,8 @@ class TagController extends Controller } else { return array( 'entities' => $entities, - 'tag' => $tag, + 'tags' => $tags, + 'operator' => $operator, ); } } diff --git a/src/Hackspace/Bundle/CalciferBundle/Resources/views/Event/index.html.twig b/src/Hackspace/Bundle/CalciferBundle/Resources/views/Event/index.html.twig index bc86b24..457520b 100755 --- a/src/Hackspace/Bundle/CalciferBundle/Resources/views/Event/index.html.twig +++ b/src/Hackspace/Bundle/CalciferBundle/Resources/views/Event/index.html.twig @@ -23,7 +23,22 @@

Termine - {% if tag|default(false) %} für Tag „{{ tag.name }}“{% endif %} + {% if tags|default(false) %} + {% if tags|length == 1 %} + für Tag {{ tags[0].name }} + {% elseif(tags|length == 2) %} + für die Tags {{ tags[0].name }} {% if operator == 'or' %}oder{% else %}und{% endif %} {{ tags[1].name }} + {% else %} + für die Tags + {% for tag in tags %} + {% if not loop.last %} + {{ tag.name }}{% if loop.index < (tags|length - 1) %},{% endif %} + {% else %} + {% if operator == 'or' %}oder{% else %}und{% endif %} {{ tag.name }} + {% endif %} + {% endfor %} + {% endif %} + {% endif %} {% if location|default(false) %} für Ort „{{ location.name }}“ {% endif %}

{% if tag|default(false) %} @@ -68,10 +83,18 @@
-
- {% for entity in entities %} - {{ include('CalciferBundle:Event:event_box.html.twig',{'truncate_summary':true}) }} - {% endfor %} -
+ {% if entities|length > 0 %} +
+ {% for entity in entities %} + {{ include('CalciferBundle:Event:event_box.html.twig',{'truncate_summary':true}) }} + {% endfor %} +
+ {% else %} +
+
+

Es konnten keine Termine gefunden werden.

+
+
+ {% endif %} {% endblock %}