Skip to content

Commit bba9f06

Browse files
committed
Merge pull request #31 from linasmo/feature_custom-filters
Custom filters can be added via service tags
2 parents 6ef62cf + 5b27310 commit bba9f06

File tree

22 files changed

+693
-114
lines changed

22 files changed

+693
-114
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the ONGR package.
5+
*
6+
* (c) NFQ Technologies UAB <info@nfq.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace ONGR\FilterManagerBundle\DependencyInjection\Compiler;
13+
14+
use ONGR\FilterManagerBundle\Filters\FilterInterface;
15+
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
16+
use Symfony\Component\DependencyInjection\ContainerBuilder;
17+
use Symfony\Component\DependencyInjection\Definition;
18+
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
19+
use Symfony\Component\DependencyInjection\Reference;
20+
21+
/**
22+
* Compiles custom filters.
23+
*/
24+
class FilterPass implements CompilerPassInterface
25+
{
26+
/**
27+
* {@inheritdoc}
28+
*/
29+
public function process(ContainerBuilder $container)
30+
{
31+
$filters = [];
32+
foreach ($container->findTaggedServiceIds('es.filter_manager') as $managerId => $managerTags) {
33+
$managerDefinition = $container->getDefinition($managerId);
34+
foreach ($container->findTaggedServiceIds('ongr_filter_manager.filter') as $filterId => $filterTags) {
35+
if (array_key_exists('manager', $filterTags[0])
36+
&& strrpos(
37+
$managerId,
38+
$filterTags[0]['manager'],
39+
strlen($filterTags[0]['manager'])
40+
)
41+
) {
42+
if (!array_key_exists('filter_name', $filterTags[0])) {
43+
throw new InvalidArgumentException(
44+
"Filters tagged with 'ongr_filter_manager.filter' must have 'filter_name' parameter."
45+
);
46+
}
47+
48+
if (($container->get($filterId) instanceof FilterInterface) === false) {
49+
throw new InvalidArgumentException("Service {$filterId} must implement FilterInterface.");
50+
}
51+
52+
$filters[] = $filterId;
53+
$filterName = $filterTags[0]['filter_name'];
54+
55+
$filtersContainer = $managerDefinition->getArgument(0);
56+
$filtersContainer->addMethodCall(
57+
'set',
58+
[$filterName, new Reference($filterId)]
59+
);
60+
$managerDefinition->replaceArgument(0, $filtersContainer);
61+
$container->setDefinition($managerId, $managerDefinition);
62+
}
63+
}
64+
/** @var Definition $filtersContainer */
65+
$filtersContainer = $managerDefinition->getArgument(0);
66+
if (!$filtersContainer->hasMethodCall('set')) {
67+
throw new InvalidArgumentException("Manager '{$managerId}' does not have any filters.");
68+
}
69+
}
70+
$filtersMap = $container->getParameter('ongr_filter_manager.filter_map');
71+
$container->setParameter('ongr_filter_manager.filter_map', array_merge_recursive($filtersMap, $filters));
72+
}
73+
}

DependencyInjection/Configuration.php

-2
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,6 @@ private function addManagersSection(ArrayNodeDefinition $rootNode)
5858
->children()
5959
->scalarNode('name')->end()
6060
->arrayNode('filters')
61-
->requiresAtLeastOneElement()
62-
->isRequired()
6361
->prototype('scalar')->end()
6462
->end()
6563
->scalarNode('repository')->isRequired()->end()

DependencyInjection/ONGRFilterManagerExtension.php

+1
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ public function load(array $configs, ContainerBuilder $container)
8282
new Reference(sprintf('es.manager.%s.%s', $config['es_manager'], $manager['repository'])),
8383
]
8484
);
85+
$managerDefinition->addTag('es.filter_manager');
8586

8687
$container->setDefinition(sprintf('ongr_filter_manager.%s', $name), $managerDefinition);
8788
}

ONGRFilterManagerBundle.php

+11
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,22 @@
1111

1212
namespace ONGR\FilterManagerBundle;
1313

14+
use ONGR\FilterManagerBundle\DependencyInjection\Compiler\FilterPass;
15+
use Symfony\Component\DependencyInjection\ContainerBuilder;
1416
use Symfony\Component\HttpKernel\Bundle\Bundle;
1517

1618
/**
1719
* Class ONGRFilterManagerBundle.
1820
*/
1921
class ONGRFilterManagerBundle extends Bundle
2022
{
23+
/**
24+
* {@inheritdoc}
25+
*/
26+
public function build(ContainerBuilder $container)
27+
{
28+
parent::build($container);
29+
30+
$container->addCompilerPass(new FilterPass());
31+
}
2132
}

Resources/doc/filter/choice.rst

+5-5
Original file line numberDiff line numberDiff line change
@@ -131,8 +131,8 @@ Each choice has its own data:
131131
| getUrlParameters() | Returns a list of available choices |
132132
+--------------------+--------------------------------------------+
133133

134-
* `Multi choice filter <multi_choice.rst>`_
135-
* `Document field filter <document_field.rst>`_
136-
* `Match filter <match.rst>`_
137-
* `Pager filter <pager.rst>`_
138-
* `Sort filter <sort.rst>`_
134+
* `Multi choice filter <multi_choice.html>`_
135+
* `Document field filter <document_field.html>`_
136+
* `Match filter <match.html>`_
137+
* `Pager filter <pager.html>`_
138+
* `Sort filter <sort.html>`_
+105
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
=============
2+
Custom filter
3+
=============
4+
5+
There is possibility to add custom filters to filter managers via tagged filter service.
6+
You must create filter class, define it as a service with ``ongr_filter_manager.filter`` tag.
7+
8+
1. Create filter class
9+
~~~~~~~~~~~~~~~~~~~~~~
10+
11+
Class must implement ``FilterInterface``.
12+
13+
.. code-block:: php
14+
15+
// File location: ONGR\FilterManagerBundle\Filters\FilterInterface.pnp
16+
17+
/**
18+
* Resolves filter state by given request.
19+
*
20+
* @param Request $request
21+
*
22+
* @return FilterState
23+
*/
24+
public function getState(Request $request);
25+
26+
/**
27+
* Modifies search request by given state. Usually should be used to add query or post_filter parameters.
28+
*
29+
* @param Search $search Search request.
30+
* @param FilterState $state Current filter state.
31+
* @param SearchRequest $request State of all filters.
32+
*/
33+
public function modifySearch(Search $search, FilterState $state = null, SearchRequest $request = null);
34+
35+
/**
36+
* Modifies search request by given state and related search. Usually is used to add aggregations into query.
37+
*
38+
* Related search does not include conditions from not related filters. Conditions made by filter
39+
* itself are also excluded on $relatedSearch. This method normally is called after modifySearch just before search
40+
* query execution
41+
*
42+
* @param Search $search
43+
* @param Search $relatedSearch
44+
* @param FilterState $state
45+
*
46+
* @return mixed
47+
*/
48+
public function preProcessSearch(Search $search, Search $relatedSearch, FilterState $state = null);
49+
50+
/**
51+
* Prepares all needed filter data to pass into view.
52+
*
53+
* @param DocumentIterator $result Search results.
54+
* @param ViewData $data Initial view data.
55+
*
56+
* @return ViewData
57+
*/
58+
public function getViewData(DocumentIterator $result, ViewData $data);
59+
60+
61+
2. Defining service
62+
~~~~~~~~~~~~~~~~~~~
63+
64+
Filter service must be tagged with ``ongr_filter_manager.filter`` tag, ``manager`` and ``filter_name`` nodes are required.
65+
Filter will be added to specified ``manager`` ``FilterContainer``.
66+
67+
.. code-block:: yaml
68+
69+
parameters:
70+
ongr_filter_manager.filter.foo_range.class: ONGR\FilterManagerBundle\Tests\app\fixture\Acme\TestBundle\Filters\FooRange\FooRange
71+
72+
services:
73+
ongr_filter_manager.filter.foo_range:
74+
class: %ongr_filter_manager.filter.foo_range.class%
75+
arguments:
76+
- 'price'
77+
- 'price'
78+
tags:
79+
- { name: ongr_filter_manager.filter, manager: foo_filters, filter_name: foo_range }
80+
81+
Arguments from service definition can be passed to filters constructor.
82+
83+
.. code-block:: php
84+
85+
// File location: ONGR\FilterManagerBundle\Tests\app\fixture\Acme\TestBundle\Filters\FooRange\FooRange.php;
86+
87+
/**
88+
* @param string $requestField
89+
* @param string $field
90+
*/
91+
public function __construct($requestField, $field)
92+
{
93+
$this->setRequestField($requestField);
94+
$this->setField($field);
95+
}
96+
97+
Filter example can be found `here <https://github.com/ongr-io/FilterManagerBundle/blob/master/Tests/app/fixture/Acme/TestBundle/Filters/FooRange/FooRange.php>`_.
98+
99+
Services `configuration <https://github.com/ongr-io/FilterManagerBundle/blob/master/Tests/app/fixture/Acme/TestBundle/Resources/config/services.yml>`_.
100+
101+
102+
3. Using filter
103+
~~~~~~~~~~~~~~~
104+
105+
Filter can be used as other filters trough ``FilterManager``, see FilterManager bundle usage `documentation <usage.html>`_.

Resources/doc/filter/document_field.rst

+5-5
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,8 @@ View data returned by this filter to be used in template:
7878
| getUrlParameters() | Url parameters representing current filter state |
7979
+-------------------------+--------------------------------------------------+
8080

81-
* `Choice filter <choice.rst>`_
82-
* `Multi choice filter <multi_choice.rst>`_
83-
* `Match filter <match.rst>`_
84-
* `Pager filter <pager.rst>`_
85-
* `Sort filter <sort.rst>`_
81+
* `Choice filter <choice.html>`_
82+
* `Multi choice filter <multi_choice.html>`_
83+
* `Match filter <match.html>`_
84+
* `Pager filter <pager.html>`_
85+
* `Sort filter <sort.html>`_

Resources/doc/filter/match.rst

+5-5
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,8 @@ View data returned by this filter to be used in template:
7979
| getUrlParameters() | Url parameters representing current filter state |
8080
+-------------------------+--------------------------------------------------+
8181

82-
* `Choice filter <choice.rst>`_
83-
* `Multi choice filter <multi_choice.rst>`_
84-
* `Document field filter <document_field.rst>`_
85-
* `Pager filter <pager.rst>`_
86-
* `Sort filter <sort.rst>`_
82+
* `Choice filter <choice.html>`_
83+
* `Multi choice filter <multi_choice.html>`_
84+
* `Document field filter <document_field.html>`_
85+
* `Pager filter <pager.html>`_
86+
* `Sort filter <sort.html>`_

Resources/doc/filter/multi_choice.rst

+5-5
Original file line numberDiff line numberDiff line change
@@ -117,8 +117,8 @@ Each choice has its own data:
117117
| getUrlParameters() | Returns a list of available choices |
118118
+--------------------+--------------------------------------------+
119119

120-
* `Choice filter <choice.rst>`_
121-
* `Document field filter <document_field.rst>`_
122-
* `Match filter <match.rst>`_
123-
* `Pager filter <pager.rst>`_
124-
* `Sort filter <sort.rst>`_
120+
* `Choice filter <choice.html>`_
121+
* `Document field filter <document_field.html>`_
122+
* `Match filter <match.html>`_
123+
* `Pager filter <pager.html>`_
124+
* `Sort filter <sort.html>`_

Resources/doc/filter/pager.rst

+5-5
Original file line numberDiff line numberDiff line change
@@ -92,8 +92,8 @@ View data returned by this filter to be used in template:
9292
| getPagerService() | Returns pager service to be used in template |
9393
+-------------------------+--------------------------------------------------+
9494

95-
* `Choice filter <choice.rst>`_
96-
* `Multi choice filter <multi_choice.rst>`_
97-
* `Document field filter <document_field.rst>`_
98-
* `Match filter <match.rst>`_
99-
* `Sort filter <sort.rst>`_
95+
* `Choice filter <choice.html>`_
96+
* `Multi choice filter <multi_choice.html>`_
97+
* `Document field filter <document_field.html>`_
98+
* `Match filter <match.html>`_
99+
* `Sort filter <sort.html>`_

Resources/doc/filter/sort.rst

+5-5
Original file line numberDiff line numberDiff line change
@@ -117,8 +117,8 @@ Each choice has its own data:
117117
| getUrlParameters() | Returns a list of available choices |
118118
+--------------------+--------------------------------------------+
119119

120-
* `Choice filter <choice.rst>`_
121-
* `Multi choice filter <multi_choice.rst>`_
122-
* `Document field filter <document_field.rst>`_
123-
* `Match filter <match.rst>`_
124-
* `Pager filter <pager.rst>`_
120+
* `Choice filter <choice.html>`_
121+
* `Multi choice filter <multi_choice.html>`_
122+
* `Document field filter <document_field.html>`_
123+
* `Match filter <match.html>`_
124+
* `Pager filter <pager.html>`_

Resources/doc/index.rst

+15-9
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,24 @@ Filter manager
55
Filter manager for product lists. It provides ties between commonly used filtering options and UI elements with Elasticsearch repositories.
66
You can use it from a single controller.
77

8-
Documentation for ONGR Filter Manager Bundle can be found `here <setup.rst>`_.
8+
Documentation for ONGR Filter Manager Bundle can be found `here <setup.html>`_.
99

10-
`Read the documentation for 0.1.x (master) <https://github.com/ongr-io/FilterManagerBundle/blob/master/Resources/doc/index.rst>`_
10+
`Read the documentation for master <https://github.com/ongr-io/FilterManagerBundle/blob/master/Resources/doc/index.rst>`_
1111

12-
-------
13-
License
14-
-------
15-
16-
This bundle is covered by the MIT license. Please see the complete license in the bundle `LICENSE </LICENSE>`_ file.
12+
Contents:
13+
~~~~~~~~~
1714

1815
.. toctree::
1916
:maxdepth: 1
20-
:glob:
17+
:glob:
18+
19+
setup
20+
usage
21+
manager
22+
filter/*
2123

22-
*
24+
25+
License
26+
~~~~~~~
27+
28+
This bundle is covered by the MIT license. Please see the complete license in the bundle `LICENSE </LICENSE>`_ file.

Resources/doc/manager.rst

+8-8
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22
Manager configuration
33
=====================
44

5-
Note: Documentation about bundle setup is `here <manager.rst>`_.
5+
Note: Documentation about bundle setup is `here <setup.html>`_.
66

7-
Note: Documentation on bundle usage is `here <usage.rst>`_.
7+
Note: Documentation on bundle `usage <usage.html>`_.
88

99

1010
FilterManager is used for retrieving filtered entities from database. It provides ties between commonly used filtering options and UI elements with Elasticsearch repositories.
@@ -89,9 +89,9 @@ Configuration for different filters
8989

9090
A detailed explanation and configuration for each type of filter can be found on its documentation page:
9191

92-
* `Choice filter <filter/choice.rst>`_
93-
* `Multi choice filter <filter/multi_choice.rst>`_
94-
* `Document field filter <filter/document_field.rst>`_
95-
* `Match filter <filter/match.rst>`_
96-
* `Pager filter <filter/pager.rst>`_
97-
* `Sort filter <filter/sort.rst>`_
92+
* `Choice filter <filter/choice.html>`_
93+
* `Multi choice filter <filter/multi_choice.html>`_
94+
* `Document field filter <filter/document_field.html>`_
95+
* `Match filter <filter/match.html>`_
96+
* `Pager filter <filter/pager.html>`_
97+
* `Sort filter <filter/sort.html>`_

0 commit comments

Comments
 (0)