GridFieldDropdownFilter::removeFilterOption()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 1
dl 0
loc 4
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace BringYourOwnIdeas\Maintenance\Forms;
4
5
use LogicException;
6
use SilverStripe\Forms\DropdownField;
7
use SilverStripe\Forms\GridField\GridField;
8
use SilverStripe\Forms\GridField\GridField_ActionProvider;
9
use SilverStripe\Forms\GridField\GridField_DataManipulator;
10
use SilverStripe\Forms\GridField\GridField_FormAction;
11
use SilverStripe\Forms\GridField\GridField_HTMLProvider;
12
use SilverStripe\ORM\ArrayList;
13
use SilverStripe\ORM\Filterable;
14
use SilverStripe\ORM\SS_List;
15
use SilverStripe\View\ArrayData;
16
use SilverStripe\View\Requirements;
17
18
/**
19
 * GridFieldDropdownFilter provides a dropdown that can be used to filter a GridField arbitrarily
20
 *
21
 * @package forms
22
 * @subpackage fields-gridfield
23
 */
24
class GridFieldDropdownFilter implements GridField_HTMLProvider, GridField_ActionProvider, GridField_DataManipulator
25
{
26
    /**
27
     * Default string used in the value http attribute on the option for all results
28
     */
29
    const DEFAULT_OPTION_VALUE = '_all';
30
31
    /**
32
     * @var string
33
     */
34
    protected $name;
35
36
    /**
37
     * @var string
38
     */
39
    protected $targetFragment;
40
41
    /**
42
     * @var SS_List
43
     */
44
    protected $filterOptions;
45
46
    /**
47
     * @var string
48
     */
49
    protected $defaultOption;
50
51
    /**
52
     * @param string $name A name unique to this GridFieldDropdownFilter on this GridField
53
     * @param string $targetFragment Fragment to write the html fragment to.
54
     * @param string $defaultOption A string used as the label for the default "All results" option
55
     */
56
    public function __construct($name, $targetFragment, $defaultOption = null)
57
    {
58
        $this->name = $name;
59
        $this->targetFragment = $targetFragment;
60
        $this->defaultOption = $defaultOption ?: _t(__CLASS__ . '.AllResults', 'All results');
61
        $this->filterOptions = ArrayList::create();
62
    }
63
64
    /**
65
     * Add an option to the dropdown that provides a filter
66
     *
67
     * @param string $name
68
     * @param string $title
69
     * @param callable|array $filter Either a closure to filter a given SS_Filterable or a simple associative array will
70
     *                              be used for filtering
71
     * @return $this
72
     */
73
    public function addFilterOption($name, $title, $filter)
74
    {
75
        $this->filterOptions->push(compact('name', 'title', 'filter'));
0 ignored issues
show
Bug introduced by
The method push() does not exist on SilverStripe\ORM\SS_List. It seems like you code against a sub-type of said class. However, the method does not exist in SilverStripe\ORM\Sortable or SilverStripe\ORM\Filterable or SilverStripe\ORM\Relation or SilverStripe\ORM\Limitable or SilverStripe\ORM\Relation or SilverStripe\ORM\Relation or SilverStripe\ORM\Relation. Are you sure you never get one of those? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

75
        $this->filterOptions->/** @scrutinizer ignore-call */ 
76
                              push(compact('name', 'title', 'filter'));
Loading history...
76
        return $this;
77
    }
78
79
    /**
80
     * Remove a filter option with the given name
81
     *
82
     * @param string $name
83
     * @return $this
84
     */
85
    public function removeFilterOption($name)
86
    {
87
        $this->filterOptions->remove($this->filterOptions->find('name', $name));
88
        return $this;
89
    }
90
91
    /**
92
     * {@inheritdoc}
93
     */
94
    public function getActions($gridField)
95
    {
96
        return ['filter'];
97
    }
98
99
    /**
100
     * {@inheritdoc}
101
     */
102
    public function handleAction(GridField $gridField, $actionName, $arguments, $data)
103
    {
104
        if ($actionName !== 'filter') {
105
            return;
106
        }
107
108
        if (!isset($data['filter-selection']) || $data['filter-selection'] === static::DEFAULT_OPTION_VALUE) {
109
            $gridField->State->{__CLASS__ . '_' . $this->name} = null;
110
        } else {
111
            $gridField->State->{__CLASS__ . '_' . $this->name} = $data['filter-selection'];
112
        }
113
    }
114
115
    /**
116
     * {@inheritdoc}
117
     */
118
    public function getManipulatedData(GridField $gridField, SS_List $dataList)
119
    {
120
        if (!$dataList instanceof Filterable) {
121
            throw new LogicException(__CLASS__ . ' is only compatible with SS_Filterable lists');
122
        }
123
124
        $filter = $gridField->State->{__CLASS__ . '_' . $this->name};
125
126
        if (!$filter || !($option = $this->filterOptions->find('name', $filter))) {
127
            return $dataList;
128
        }
129
130
        $filterSpec = $option['filter'];
131
132
        if (is_callable($filterSpec)) {
133
            return $filterSpec($dataList);
134
        }
135
        if (is_array($filterSpec)) {
136
            foreach ($filterSpec as $key => $value) {
137
                if ($dataList->canFilterBy($key)) {
138
                    $dataList = $dataList->filter($key, $value);
0 ignored issues
show
Unused Code introduced by
The call to SilverStripe\ORM\Filterable::filter() has too many arguments starting with $key. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

138
                    /** @scrutinizer ignore-call */ 
139
                    $dataList = $dataList->filter($key, $value);

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
139
                }
140
            }
141
            return $dataList;
142
        }
143
144
        throw new LogicException('Invalid filter specification given');
145
    }
146
147
    /**
148
     * {@inheritdoc}
149
     */
150
    public function getHTMLFragments($gridField)
151
    {
152
        Requirements::javascript('bringyourownideas/silverstripe-maintenance: client/dist/js/bundle.js');
153
154
        $dropdownOptions = [static::DEFAULT_OPTION_VALUE => $this->defaultOption] +
155
            $this->filterOptions->map('name', 'title')->toArray();
156
157
        $dropdown = DropdownField::create(
158
            'filter-selection',
159
            null,
160
            $dropdownOptions,
161
            $gridField->State->{__CLASS__ . '_' . $this->name} ?: static::DEFAULT_OPTION_VALUE
162
        );
163
        $dropdown->addExtraClass('no-change-track');
164
165
        return [
166
            $this->targetFragment => ArrayData::create([
167
                'Filter' => $dropdown,
168
                'Action' => GridField_FormAction::create($gridField, 'filter', 'Go', 'filter', null),
169
            ])->renderWith(GridFieldDropdownFilter::class),
170
        ];
171
    }
172
}
173