Browse Source

Add a global SearchHandler

Thomas Rabaix 11 years ago
parent
commit
5c5c5dfc7f

+ 5 - 5
Datagrid/Datagrid.php

@@ -47,11 +47,11 @@ class Datagrid implements DatagridInterface
     protected $results;
 
     /**
-     * @param ProxyQueryInterface                                  $query
-     * @param \Sonata\AdminBundle\Admin\FieldDescriptionCollection $columns
-     * @param PagerInterface                                       $pager
-     * @param \Symfony\Component\Form\FormBuilder                  $formBuilder
-     * @param array                                                $values
+     * @param ProxyQueryInterface        $query
+     * @param FieldDescriptionCollection $columns
+     * @param PagerInterface             $pager
+     * @param FormBuilder                $formBuilder
+     * @param array                      $values
      */
     public function __construct(ProxyQueryInterface $query, FieldDescriptionCollection $columns, PagerInterface $pager, FormBuilder $formBuilder, array $values = array())
     {

+ 0 - 4
Filter/Filter.php

@@ -23,10 +23,6 @@ abstract class Filter implements FilterInterface
 
     protected $condition;
 
-    const CONDITION_OR = 'OR';
-
-    const CONDITION_AND = 'AND';
-
     /**
      * {@inheritdoc}
      */

+ 16 - 0
Filter/FilterInterface.php

@@ -14,6 +14,10 @@ use Sonata\AdminBundle\Datagrid\ProxyQueryInterface;
 
 interface FilterInterface
 {
+    const CONDITION_OR = 'OR';
+
+    const CONDITION_AND = 'AND';
+
     /**
      * Apply the filter to the QueryBuilder instance
      *
@@ -128,4 +132,16 @@ interface FilterInterface
      * @return boolean
      */
     public function isActive();
+
+    /**
+     * Set the condition to use with the left side of the query : OR or AND
+     *
+     * @param string $condition
+     */
+    public function setCondition($condition);
+
+    /**
+     * @return string
+     */
+    public function getCondition();
 }

+ 3 - 1
Resources/config/core.xml

@@ -58,8 +58,10 @@
             <argument type="service" id="service_container" />
         </service>
 
-        <service id="sonata.admin.exporter" class="Sonata\AdminBundle\Export\Exporter">
+        <service id="sonata.admin.exporter" class="Sonata\AdminBundle\Export\Exporter" />
 
+        <service id="sonata.admin.search.handler" class="Sonata\AdminBundle\Search\SearchHandler">
+            <argument type="service" id="sonata.admin.pool" />
         </service>
     </services>
 </container>

+ 6 - 1
Resources/config/routing/sonata_admin.xml

@@ -22,12 +22,17 @@
         <default key="_controller">sonata.admin.controller.admin:appendFormFieldElementAction</default>
     </route>
 
-    <route id="sonata_admin_short_object_information" pattern="/core/get-short-object-description">
+    <route id="sonata_admin_short_object_information" pattern="/core/get-short-object-description.{_format}">
         <default key="_controller">sonata.admin.controller.admin:getShortObjectDescriptionAction</default>
+        <default key="_format">html</default>
+        <requirement key="_format">html|json</requirement>
     </route>
 
     <route id="sonata_admin_set_object_field_value" pattern="/core/set-object-field-value">
         <default key="_controller">sonata.admin.controller.admin:setObjectFieldValueAction</default>
     </route>
 
+    <route id="sonata_admin_search" pattern="/search">
+        <default key="_controller">SonataAdminBundle:Core:search</default>
+    </route>
 </routes>

+ 1 - 1
Resources/doc/reference/action_list.rst

@@ -83,6 +83,6 @@ To do:
 - basic filter configuration and options
 - how to set default filter values
 - targeting submodel fields using dot-separated notation
-- advanced filter options
+- advanced filter options (global_search)
 
 .. _`issues on Github`: https://github.com/sonata-project/SonataAdminBundle/issues/1519

+ 68 - 0
Search/SearchHandler.php

@@ -0,0 +1,68 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Sonata\AdminBundle\Search;
+
+
+use Sonata\AdminBundle\Admin\AdminInterface;
+use Sonata\AdminBundle\Admin\Pool;
+use Sonata\AdminBundle\Filter\FilterInterface;
+use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
+
+class SearchHandler
+{
+    protected $pool;
+
+    /**
+     * @param Pool $pool
+     */
+    public function __construct(Pool $pool)
+    {
+        $this->pool = $pool;
+    }
+
+    /**
+     * @param AdminInterface $admin
+     * @param string         $term
+     * @param int            $page
+     * @param int            $offset
+     *
+     * @return \Sonata\AdminBundle\Datagrid\PagerInterface
+     *
+     * @throws \RuntimeException
+     */
+    public function search(AdminInterface $admin, $term, $page = 0, $offset = 20)
+    {
+        $datagrid = $admin->getDatagrid();
+
+        $found = false;
+        foreach($datagrid->getFilters() as $name => $filter) {
+            /** @var $filter FilterInterface */
+            if ($filter->getOption('global_search', false)) {
+                $filter->setCondition(FilterInterface::CONDITION_OR);
+                $datagrid->setValue($name, null, $term);
+                $found = true;
+            }
+        }
+
+        if (!$found) {
+            return false;
+        }
+
+        $datagrid->buildPager();
+
+        $pager = $datagrid->getPager();
+        $pager->setPage($page);
+        $pager->setMaxPerPage($offset);
+
+        return $pager;
+    }
+}

+ 77 - 0
Tests/Search/SearchHandlerTest.php

@@ -0,0 +1,77 @@
+<?php
+/*
+ * This file is part of the Sonata project.
+ *
+ * (c) Thomas Rabaix <thomas.rabaix@sonata-project.org>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Sonata\AdminBundle\Route;
+
+use Sonata\AdminBundle\Admin\AdminInterface;
+use Sonata\AdminBundle\Admin\Pool;
+use Sonata\AdminBundle\Search\SearchHandler;
+use Sonata\AdminBundle\Datagrid\DatagridInterface;
+use Sonata\AdminBundle\Filter\FilterInterface;
+use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
+
+class SearchHandlerTest extends \PHPUnit_Framework_TestCase
+{
+
+    /**
+     * @param AdminInterface $admin
+     *
+     * @return Pool
+     */
+    public function getPool(AdminInterface $admin = null)
+    {
+        $container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface');
+        $container->expects($this->any())->method('get')->will($this->returnCallback(function($id) use ($admin) {
+            if ($id == 'fake') {
+                throw new ServiceNotFoundException('Fake service does not exist');
+            }
+
+            return $admin;
+        }));
+
+        return new Pool($container, 'title', 'logo', array('asd'));
+    }
+
+    public function testBuildPagerWithNoGlobalSearchField()
+    {
+        $filter = $this->getMock('Sonata\AdminBundle\Filter\FilterInterface');
+        $filter->expects($this->once())->method('getOption')->will($this->returnValue(false));
+
+        $datagrid = $this->getMock('Sonata\AdminBundle\Datagrid\DatagridInterface');
+        $datagrid->expects($this->once())->method('getFilters')->will($this->returnValue(array($filter)));
+
+        $admin = $this->getMock('Sonata\AdminBundle\Admin\AdminInterface');
+        $admin->expects($this->once())->method('getDatagrid')->will($this->returnValue($datagrid));
+
+        $handler = new SearchHandler($this->getPool($admin));
+        $this->assertFalse($handler->search($admin, 'myservice'));
+    }
+
+    public function testBuildPagerWithGlobalSearchField()
+    {
+        $filter = $this->getMock('Sonata\AdminBundle\Filter\FilterInterface');
+        $filter->expects($this->once())->method('getOption')->will($this->returnValue(true));
+
+        $pager = $this->getMock('Sonata\AdminBundle\Datagrid\PagerInterface');
+        $pager->expects($this->once())->method('setPage');
+        $pager->expects($this->once())->method('setMaxPerPage');
+
+        $datagrid = $this->getMock('Sonata\AdminBundle\Datagrid\DatagridInterface');
+        $datagrid->expects($this->once())->method('getFilters')->will($this->returnValue(array($filter)));
+        $datagrid->expects($this->once())->method('setValue');
+        $datagrid->expects($this->once())->method('getPager')->will($this->returnValue($pager));
+
+        $admin = $this->getMock('Sonata\AdminBundle\Admin\AdminInterface');
+        $admin->expects($this->once())->method('getDatagrid')->will($this->returnValue($datagrid));
+
+        $handler = new SearchHandler($this->getPool($admin));
+        $this->assertInstanceOf('Sonata\AdminBundle\Datagrid\PagerInterface', $handler->search($admin, 'myservice'));
+    }
+}