Passed
Push — master ( 0ae06f...63b5e6 )
by Nicolaas
03:29
created

SearchAdmin::Breadcrumbs()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 2
nc 1
nop 1
dl 0
loc 5
rs 10
c 1
b 0
f 0
1
<?php
2
3
namespace Sunnysideup\SiteWideSearch\Admin;
4
5
use SilverStripe\Admin\LeftAndMain;
6
use SilverStripe\Control\HTTPResponse;
7
use SilverStripe\Core\ClassInfo;
8
use SilverStripe\Core\Injector\Injector;
9
10
use SilverStripe\Core\Environment;
11
use SilverStripe\Forms\CheckboxField;
12
use SilverStripe\Forms\Form;
13
use SilverStripe\Forms\FormAction;
14
use SilverStripe\Forms\HiddenField;
15
use SilverStripe\Forms\HTMLReadonlyField;
16
use SilverStripe\Forms\LiteralField;
17
use SilverStripe\Forms\OptionsetField;
18
use SilverStripe\Forms\TextField;
19
use SilverStripe\Forms\ToggleCompositeField;
20
use SilverStripe\ORM\ArrayList;
21
use SilverStripe\ORM\DataObject;
22
use SilverStripe\ORM\FieldType\DBField;
23
use SilverStripe\Security\PermissionProvider;
24
use Sunnysideup\SiteWideSearch\Api\SearchApi;
25
use Sunnysideup\SiteWideSearch\QuickSearches\QuickSearchBaseClass;
26
27
class SearchAdmin extends LeftAndMain implements PermissionProvider
28
{
29
    protected $listHTML = '';
30
31
    protected $keywords = '';
32
33
    protected $replace = '';
34
35
    protected $applyReplace = false;
36
37
    protected $quickSearchType = 'all';
38
39
    protected $searchWholePhrase = false;
40
41
    protected $rawData;
42
43
    private static $default_quick_search_type = 'limited';
44
45
    private static $url_segment = 'find';
46
47
    private static $menu_title = 'Search';
48
49
    private static $menu_icon_class = 'font-icon-p-search';
50
51
    private static $menu_priority = 99999;
52
53
    private static $required_permission_codes = [
54
        'CMS_ACCESS_SITE_WIDE_SEARCH',
55
    ];
56
57
    public function getEditForm($id = null, $fields = null)
58
    {
59
        $form = parent::getEditForm($id, $fields);
60
        $fields = $form->Fields();
61
62
        // if ($form instanceof HTTPResponse) {
63
        //     return $form;
64
        // }
65
        // $fields->removeByName('LastVisited');
66
        $fields->push(
67
            (new TextField('Keywords', 'Keyword(s)', $this->keywords ?? ''))
68
                ->setAttribute('placeholder', 'e.g. agreement')
69
        );
70
        $fields->push(
71
            (new HiddenField('IsSubmitHiddenField', 'IsSubmitHiddenField', 1))
72
        );
73
74
        $options = QuickSearchBaseClass::get_list_of_quick_searches();
75
        $fields->push(
76
            OptionsetField::create(
77
                'QuickSearchType',
78
                'Quick Search',
79
                $options
80
            )->setValue($this->quickSearchType ?: $this->Config()->get('default_quick_search_type'))
81
        );
82
83
        $fields->push(
84
            (new CheckboxField('SearchWholePhrase', 'Search exact phrase', $this->searchWholePhrase))
85
                ->setDescription('If ticked, any item will be included that includes the whole phrase (e.g. New Zealand, rather than New OR Zealand)')
86
        );
87
        $fields->push(
88
            ToggleCompositeField::create(
89
                'ReplaceToggle',
90
                _t(__CLASS__ . '.ReplaceToggle', 'Replace with ... (optional - make a backup first!)'),
91
                [
92
                    (new CheckboxField('ApplyReplace', 'Run replace (please make sure to make a backup first!)', $this->applyReplace))
93
                      ->setDescription('Check this to replace the searched value set above with its replacement value. Note that searches ignore uppercase / lowercase, but replace actions will only search and replace values with the same upper / lowercase.'),
94
                    (new TextField('ReplaceWith', 'Replace (optional - careful!)', $this->replace ?? ''))
95
                        ->setAttribute('placeholder', 'e.g. contract - make sure to also tick checkbox below'),
96
                ]
97
            )->setHeadingLevel(4)
98
        );
99
100
101
        if (!$this->getRequest()->requestVar('Keywords')) {
102
            $resultsTitle = 'Recently Edited';
103
            $this->listHTML = $this->renderWith(self::class . '_Results');
104
        } else {
105
            $resultsTitle = 'Search Results';
106
        }
107
108
        $form->setFormMethod('get', false);
109
110
        $fields->push(
111
            (new HTMLReadonlyField('List', $resultsTitle, DBField::create_field('HTMLText', $this->listHTML)))
112
        );
113
        $fields->push(
114
            (new LiteralField('Styling', $this->renderWith(self::class . '_Styling')))
115
        );
116
        $form->Actions()->push(
117
            FormAction::create('search', 'Find')
118
                ->addExtraClass('btn-primary')
119
                ->setUseButtonTag(true)
120
        );
121
        $form->addExtraClass('root-form cms-edit-form center fill-height');
122
        // $form->disableSecurityToken();
123
        // $form->setFormMethod('get');
124
125
        return $form;
126
    }
127
128
    public function search(array $data, Form $form): HTTPResponse
129
    {
130
        if (empty($data['Keywords'])) {
131
            $form->sessionMessage('Please enter one or more keywords', 'bad');
132
133
            return $this->redirectBack();
134
        }
135
136
        $request = $this->getRequest();
137
138
        $this->rawData = $data;
139
        $this->listHTML = $this->renderWith(self::class . '_Results');
140
        // Existing or new record?
141
142
        return $this->getResponseNegotiator()->respond($request);
143
    }
144
145
    /**
146
     * Only show first element, as the profile form is limited to editing
147
     * the current member it doesn't make much sense to show the member name
148
     * in the breadcrumbs.
149
     *
150
     * @param bool $unlinked
151
     *
152
     * @return ArrayList
153
     */
154
    public function Breadcrumbs($unlinked = false)
155
    {
156
        $items = parent::Breadcrumbs($unlinked);
157
158
        return new ArrayList([$items[0]]);
159
    }
160
161
    public function IsQuickSearch(): bool
162
    {
163
        return $this->quickSearchType !== 'all';
164
    }
165
166
    public function SearchResults(): ?ArrayList
167
    {
168
        Environment::increaseTimeLimitTo(300);
169
        Environment::setMemoryLimitMax(-1);
170
        Environment::increaseMemoryLimitTo(-1);
171
        $this->keywords = $this->workOutString('Keywords', $this->rawData);
172
        $this->quickSearchType = $this->workOutString('QuickSearchType', $this->rawData, 'limited');
173
        $this->searchWholePhrase = $this->workOutBoolean('SearchWholePhrase', $this->rawData, true);
174
        $this->applyReplace = isset($this->rawData['ReplaceWith']) && $this->workOutBoolean('ApplyReplace', $this->rawData, false);
175
        $this->replace = $this->workOutString('ReplaceWith', $this->rawData);
176
        if ($this->applyReplace) {
177
            Injector::inst()->get(SearchApi::class)
178
                ->setQuickSearchType($this->quickSearchType)
179
                ->setSearchWholePhrase(true)
180
                ->setWordsAsString($this->keywords)
181
                ->buildCache() // make sure we have the lastest cache!
182
                ->doReplacement($this->keywords, $this->replace)
183
            ;
184
            $this->applyReplace = false;
185
        }
186
187
        return Injector::inst()->get(SearchApi::class)
188
            ->setQuickSearchType($this->quickSearchType)
189
            ->setSearchWholePhrase($this->searchWholePhrase)
190
            ->setWordsAsString($this->keywords)
191
            ->getLinks()
192
        ;
193
    }
194
195
    protected function workOutBoolean(string $fieldName, ?array $data = null, ?bool $default = false): bool
196
    {
197
        return (bool) (isset($data['IsSubmitHiddenField']) ? !empty($data[$fieldName]) : $default);
198
    }
199
200
    protected function workOutString(string $fieldName, ?array $data = null, ?string $default = ''): string
201
    {
202
        return trim($data[$fieldName] ?? $default);
0 ignored issues
show
Bug introduced by
It seems like $data[$fieldName] ?? $default can also be of type null; however, parameter $string of trim() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

202
        return trim(/** @scrutinizer ignore-type */ $data[$fieldName] ?? $default);
Loading history...
203
    }
204
205
    public function providePermissions()
206
    {
207
        return [
208
            'CMS_ACCESS_SITE_WIDE_SEARCH' => [
209
                'name' => 'Access to Search Website in the CMS',
210
                'category' => _t('SilverStripe\\Security\\Permission.CMS_ACCESS_CATEGORY', 'CMS Access'),
211
                'help' => 'Allow users to search for documents (all documents will also be checked to see if they are allowed to be viewed)',
212
            ],
213
        ];
214
    }
215
}
216