Passed
Push — 1 ( c5209d...9d8264 )
by Morven
10:22
created

ModelAdminPlus::search()   A

Complexity

Conditions 4
Paths 5

Size

Total Lines 19
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 7
nc 5
nop 2
dl 0
loc 19
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace ilateral\SilverStripe\ModelAdminPlus;
4
5
use SilverStripe\Forms\Form;
6
use SilverStripe\ORM\ArrayList;
7
use SilverStripe\Admin\ModelAdmin;
8
use Colymba\BulkManager\BulkManager;
9
use SilverStripe\Core\Config\Config;
10
use SilverStripe\Control\HTTPRequest;
11
use SilverStripe\Forms\GridField\GridField;
12
use Colymba\BulkManager\BulkAction\UnlinkHandler;
13
use SilverStripe\Forms\GridField\GridFieldConfig;
14
use SilverStripe\Forms\GridField\GridFieldPaginator;
15
use ilateral\SilverStripe\ModelAdminPlus\AutoCompleteField;
16
use SilverStripe\Forms\GridField\GridFieldButtonRow;
17
use Symbiote\GridFieldExtensions\GridFieldConfigurablePaginator;
18
use SilverStripe\Forms\GridField\GridFieldFilterHeader as SSGridFieldFilterHeader;
19
20
/**
21
 * Custom version of model admin that adds extra features
22
 * (such as submitting search results via a POST, saving the query
23
 * as a session and automatic Bulk Editing support)
24
 *
25
 * @author ilateral
26
 * @package ModelAdminPlus
27
 */
28
abstract class ModelAdminPlus extends ModelAdmin
29
{
30
    const EXPORT_FIELDS = "export_fields";
31
32
    const ACTION_SUGGEST = 'suggest';
33
34
    /**
35
     * Automatically convert date fields on gridfields
36
     * to use `Date.Nice`.
37
     *
38
     * @var boolean
39
     */
40
    private static $auto_convert_dates = true;
41
42
    /**
43
     * Automatically convert DB text fields to AutoComplete fields
44
     *
45
     * @var boolean
46
     */
47
    private static $convert_to_autocomplete = true;
0 ignored issues
show
introduced by
The private property $convert_to_autocomplete is not used, and could be removed.
Loading history...
48
49
    private static $allowed_actions = [
0 ignored issues
show
introduced by
The private property $allowed_actions is not used, and could be removed.
Loading history...
50
        "SearchForm",
51
        self::ACTION_SUGGEST
52
    ];
53
54
    /**
55
     * List of currently registered ModelAdminSnippets, that is represented as
56
     * a list of classnames.
57
     *
58
     * These snippets are then setup when ModelAdminPlus is initilised and
59
     * rendered into the ModelAdminPlus content template.
60
     * 
61
     * This list can also be a divided up by managed classnames, so that snippets will
62
     * only be loaded when accessing that class, EG:
63
     * 
64
     * $registered_snippets = [
65
     *      MyObject::class => [
66
     *          MySnippetOne::class,
67
     *          MySnippetTwo::class
68
     *      ]
69
     * ];
70
     *
71
     * @var array
72
     */
73
    private static $registered_snippets = [];
74
75
    /**
76
     * Setup snippets for current screen
77
     */
78
    public function getSnippets()
79
    {
80
        $snippets = ArrayList::create();
81
        $model_class = $this->getModelClass();
82
83
        // Setup any model admin plus snippets
84
        foreach ($this->config()->registered_snippets as $key => $value) {
85
            if (is_int($key)) {
86
                $snippet = $this->createSnippetObject($value);
87
                $snippets->add($snippet);
88
            }
89
90
            if (is_array($value) && $key == $model_class) {
91
                foreach ($value as $snippet_class) {
92
                    $snippet = $this->createSnippetObject($snippet_class);
93
                    $snippets->add($snippet);
94
                }
95
            }
96
        }
97
98
        $snippets = $snippets->sort("Order", "DESC");
99
100
        $this->extend("updateSnippets", $snippets);
101
102
        return $snippets;
103
    }
104
105
    protected function createSnippetObject(string $class): ModelAdminSnippet
106
    {
107
        $snippet = new $class('snippets-before');
108
        $snippet->setParent($this);
109
        return $snippet;
110
    }
111
112
    public function init()
113
    {
114
        parent::init();
115
116
        $clear = $this->getRequest()->getVar("clear");
117
118
        if (isset($clear) && $clear == 1) {
119
            $this->clearSearchSession();
120
            // Remove clear flag
121
            return $this->redirect(
122
                $this->Link(
123
                    $this->sanitiseClassName($this->modelClass)
124
                )
125
            );
126
        }
127
    }
128
129
    /**
130
     * Get the default export fields for the current model.
131
     *
132
     * First this checks if there is an `export_fields` config variable set on
133
     * the model class, if not, it reverts to the default behaviour.
134
     *
135
     * @return array
136
     */
137
    public function getExportFields()
138
    {
139
        $export_fields = Config::inst()->get(
140
            $this->modelClass,
141
            self::EXPORT_FIELDS
142
        );
143
144
        if (isset($export_fields) && is_array($export_fields)) {
145
            $fields = $export_fields;
146
        } else {
147
            $fields = parent::getExportFields();
148
        }
149
150
        $this->extend("updateExportFields", $fields);
151
152
        return $fields;
153
    }
154
155
    /**
156
     * Get the name of the session to be useed by this model admin's search
157
     * form.
158
     *
159
     * @return string
160
     */
161
    public function getSearchSessionName()
162
    {
163
        $curr = $this->sanitiseClassName(self::class);
164
        $model = $this->sanitiseClassName($this->modelClass);
165
        return $curr . "." . $model;
166
    }
167
168
    /**
169
     * Empty the current search session
170
     *
171
     * @return Session
0 ignored issues
show
Bug introduced by
The type ilateral\SilverStripe\ModelAdminPlus\Session was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
172
     */
173
    public function clearSearchSession()
174
    {
175
        $session = $this->getRequest()->getSession();
176
        return $session->clear($this->getSearchSessionName());
177
    }
178
179
    /**
180
     * Get the current search session
181
     *
182
     * @return Session
183
     */
184
    public function getSearchSession()
185
    {
186
        $session = $this->getRequest()->getSession();
187
        return $session->get($this->getSearchSessionName());
188
    }
189
190
    /**
191
     * Set some data to a search session. This needs to be an array of
192
     * data (like the data submitted by a form).
193
     *
194
     * @param array $data An array of data to store in the session
195
     *
196
     * @return self
197
     */
198
    public function setSearchSession($data)
199
    {
200
        $session = $this->getRequest()->getSession();
201
        return $session->set($this->getSearchSessionName(), $data);
202
    }
203
204
    /**
205
     * Get the current search results, combined with any saved
206
     * search results and resturn (as an array).
207
     *
208
     * @return array
209
     */
210
    public function getSearchData()
211
    {
212
        $data = $this->getSearchSession();
213
214
        if (!$data || $data && !is_array($data)) {
0 ignored issues
show
introduced by
$data is of type ilateral\SilverStripe\ModelAdminPlus\Session, thus it always evaluated to true.
Loading history...
introduced by
The condition is_array($data) is always false.
Loading history...
215
            $data = [];
216
        }
217
218
        return $data;
219
    }
220
221
    protected function getGridField(): GridField
222
    {
223
        $field = parent::getGridField();
224
225
        if ($this->config()->auto_convert_dates) {
226
            GridFieldDateFinder::create($field)->convertDateFields();
227
        }
228
229
        return $field;
230
    }
231
232
    protected function getGridFieldConfig(): GridFieldConfig
233
    {
234
        $config = parent::getGridFieldConfig();
235
236
        // Add bulk editing to gridfield
237
        $manager = new BulkManager();
238
        $manager->removeBulkAction(UnlinkHandler::class);
239
240
        $config
241
            ->addComponent(new GridFieldSnippetRow(), GridFieldButtonRow::class)
242
            ->removeComponentsByType(GridFieldPaginator::class)
243
            ->addComponent($manager)
244
            ->addComponent(new GridFieldConfigurablePaginator());
245
246
        // Switch to custom filter header
247
        if ($config->getComponentsByType(SSGridFieldFilterHeader::class)->exists()) {
248
            $config
249
            ->removeComponentsByType(SSGridFieldFilterHeader::class)
250
            ->addComponent(new GridFieldFilterHeader(
251
                false,
252
                function ($context) {
253
                    $this->extend('updateSearchContext', $context);
254
                },
255
                function ($form) {
256
                    $this->extend('updateSearchForm', $form);
257
                }
258
            ));
259
        }
260
261
        // Add custom snippets
262
        foreach ($this->getSnippets() as $snippet) {
263
            $config->addComponent($snippet);
264
        }
265
266
        return $config;
267
    }
268
269
    /**
270
     * Find and return the recommended suggestion for an autocomplete
271
     * field
272
     *
273
     * @param array $data Submitted form
274
     * @param Form  $form The current form
275
     *
276
     * @return HTTPResponse
0 ignored issues
show
Bug introduced by
The type ilateral\SilverStripe\ModelAdminPlus\HTTPResponse was not found. Did you mean HTTPResponse? If so, make sure to prefix the type with \.
Loading history...
277
     */
278
    public function suggest(HTTPRequest $request)
279
    {
280
        $name = $request->param('n');
281
        $grid = $this->getGridField();
282
283
        // Manually re-assign gridfield to edit form
284
        $form = $this->getEditForm();
285
        $grid->setForm($form);
286
287
        $config = $grid->getConfig();
288
        /** @var GridFieldFilterHeader */
289
        $search = $config->getComponentByType(GridFieldFilterHeader::class);
290
        $form = isset($search) ? $search->getSearchForm($grid) : null;
0 ignored issues
show
Bug introduced by
The method getSearchForm() does not exist on SilverStripe\Forms\GridField\GridFieldComponent. It seems like you code against a sub-type of SilverStripe\Forms\GridField\GridFieldComponent such as SilverStripe\Forms\GridField\GridFieldFilterHeader or SilverStripe\Forms\GridField\GridFieldPrintButton or SilverStripe\Forms\GridField\GridFieldFilterHeader or SilverStripe\Forms\GridField\GridFieldPrintButton or Symbiote\GridFieldExtens...\GridFieldOrderableRows or SilverStripe\Forms\GridField\GridFieldFilterHeader or ilateral\SilverStripe\Mo...nPlus\ModelAdminSnippet or Symbiote\GridFieldExtens...\GridFieldOrderableRows or SilverStripe\Forms\GridField\GridFieldFilterHeader or Symbiote\GridFieldExtens...\GridFieldOrderableRows or SilverStripe\Forms\GridField\GridFieldPrintButton or Symbiote\GridFieldExtens...\GridFieldOrderableRows or SilverStripe\Forms\GridField\GridFieldFilterHeader or SilverStripe\Forms\Tests...ndlerTest\TestComponent or SilverStripe\Forms\GridField\GridFieldDetailForm or Symbiote\GridFieldExtens...\GridFieldOrderableRows. ( Ignorable by Annotation )

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

290
        $form = isset($search) ? $search->/** @scrutinizer ignore-call */ getSearchForm($grid) : null;
Loading history...
291
        
292
        /** @var AutoCompleteField */
293
        $field = isset($form) ? $form->Fields()->fieldByName($name) : null;
294
295
        if (isset($field)) {
296
            return $field->Suggest($request);
297
        }
298
299
        // the response body
300
        return json_encode([]);
301
    }
302
}
303