Passed
Push — master ( 19e85c...7a6648 )
by Nicolaas
10:46
created

SearchAdmin::providePermissions()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 5
nc 1
nop 0
dl 0
loc 7
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\Injector\Injector;
8
9
use SilverStripe\Core\Environment;
10
use SilverStripe\Forms\CheckboxField;
11
use SilverStripe\Forms\Form;
12
use SilverStripe\Forms\FormAction;
13
use SilverStripe\Forms\HTMLReadonlyField;
14
use SilverStripe\Forms\LiteralField;
15
use SilverStripe\Forms\TextField;
16
use SilverStripe\ORM\ArrayList;
17
use SilverStripe\ORM\DataObject;
18
use SilverStripe\ORM\FieldType\DBField;
19
use SilverStripe\Security\PermissionProvider;
20
use Sunnysideup\SiteWideSearch\Api\SearchApi;
21
22
class SearchAdmin extends LeftAndMain implements PermissionProvider
23
{
24
    protected $listHTML = '';
25
26
    protected $keywords = '';
27
28
    protected $replace = '';
29
30
    protected $applyReplace = false;
31
32
    protected $isQuickSearch = false;
33
34
    protected $searchWholePhrase = false;
35
36
    protected $rawData;
37
38
    private static $url_segment = 'find';
39
40
    private static $menu_title = 'Search';
41
42
    private static $menu_icon_class = 'font-icon-p-search';
43
44
    private static $menu_priority = 99999;
45
46
    private static $required_permission_codes = [
47
        'CMS_ACCESS_SITE_WIDE_SEARCH',
48
    ];
49
50
    public function getEditForm($id = null, $fields = null)
51
    {
52
        $form = parent::getEditForm($id, $fields);
53
54
        // if ($form instanceof HTTPResponse) {
55
        //     return $form;
56
        // }
57
        // $form->Fields()->removeByName('LastVisited');
58
        $form->Fields()->push(
59
            (new TextField('Keywords', 'Keyword(s)', $this->keywords ?? ''))
60
                ->setAttribute('placeholder', 'e.g. agreement')
61
        );
62
        $form->Fields()->push(
63
            (new CheckboxField('QuickSearch', 'Search Main Fields Only', $this->isQuickSearch))
64
                ->setDescription('This is faster but only searches a limited number of fields')
65
        );
66
        $form->Fields()->push(
67
            (new CheckboxField('SearchWholePhrase', 'Search exact phrase', $this->searchWholePhrase))
68
                ->setDescription('If ticked, any item will be included that includes the whole phrase (e.g. New Zealand, rather than New OR Zealand)')
69
        );
70
71
        $form->Fields()->push(
72
            (new TextField('ReplaceWith', 'Replace (optional - careful!)', $this->replace ?? ''))
73
                ->setAttribute('placeholder', 'e.g. contract - make sure to also tick checkbox below')
74
        );
75
        $form->Fields()->push(
76
            (new CheckboxField('ApplyReplace', 'Run replace (please make sure to make a backup first!)', $this->applyReplace))
77
                ->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.')
78
        );
79
80
        if (!$this->getRequest()->requestVar('Keywords')) {
81
            $resultsTitle = 'Recently Edited';
82
            $this->listHTML = $this->renderWith(self::class . '_Results');
83
        } else {
84
            $resultsTitle = 'Search Results';
85
        }
86
87
        $form->setFormMethod('get', false);
88
89
        $form->Fields()->push(
90
            (new HTMLReadonlyField('List', $resultsTitle, DBField::create_field('HTMLText', $this->listHTML)))
91
        );
92
        $form->Fields()->push(
93
            (new LiteralField('Styling', $this->renderWith(self::class . '_Styling')))
94
        );
95
        $form->Actions()->push(
96
            FormAction::create('search', 'Find')
97
                ->addExtraClass('btn-primary')
98
                ->setUseButtonTag(true)
99
        );
100
        $form->addExtraClass('root-form cms-edit-form center fill-height');
101
        // $form->disableSecurityToken();
102
        // $form->setFormMethod('get');
103
104
        return $form;
105
    }
106
107
    public function search(array $data, Form $form): HTTPResponse
108
    {
109
        if (empty($data['Keywords'])) {
110
            $form->sessionMessage('Please enter one or more keywords', 'bad');
111
112
            return $this->redirectBack();
113
        }
114
115
        $request = $this->getRequest();
116
117
        $this->rawData = $data;
118
        $this->listHTML = $this->renderWith(self::class . '_Results');
119
        // Existing or new record?
120
121
        return $this->getResponseNegotiator()->respond($request);
122
    }
123
124
    /**
125
     * Only show first element, as the profile form is limited to editing
126
     * the current member it doesn't make much sense to show the member name
127
     * in the breadcrumbs.
128
     *
129
     * @param bool $unlinked
130
     *
131
     * @return ArrayList
132
     */
133
    public function Breadcrumbs($unlinked = false)
134
    {
135
        $items = parent::Breadcrumbs($unlinked);
136
137
        return new ArrayList([$items[0]]);
138
    }
139
140
    public function IsQuickSearch(): bool
141
    {
142
        return $this->isQuickSearch;
143
    }
144
145
    public function SearchResults(): ?ArrayList
146
    {
147
        Environment::increaseTimeLimitTo(300);
148
        Environment::setMemoryLimitMax(-1);
149
        Environment::increaseMemoryLimitTo(-1);
150
        $this->isQuickSearch = $this->workOutBoolean('QuickSearch', $this->rawData, true);
151
        $this->searchWholePhrase = $this->workOutBoolean('SearchWholePhrase', $this->rawData, true);
152
        $this->applyReplace = isset($this->rawData['ReplaceWith']) && $this->workOutBoolean('ApplyReplace', $this->rawData, false);
153
        $this->keywords = trim($this->rawData['Keywords'] ?? '');
154
        $this->replace = trim($this->rawData['ReplaceWith'] ?? '');
155
        if ($this->applyReplace) {
156
            Injector::inst()->get(SearchApi::class)
157
                ->setBaseClass(DataObject::class)
158
                ->setIsQuickSearch($this->isQuickSearch)
159
                ->setSearchWholePhrase(true)
160
                ->setWordsAsString($this->keywords)
161
                ->buildCache()
162
                ->doReplacement($this->keywords, $this->replace)
163
            ;
164
            $this->applyReplace = false;
165
        }
166
167
        return Injector::inst()->get(SearchApi::class)
168
            ->setBaseClass(DataObject::class)
169
            ->setIsQuickSearch($this->isQuickSearch)
170
            ->setSearchWholePhrase($this->searchWholePhrase)
171
            ->setWordsAsString($this->keywords)
172
            ->getLinks()
173
        ;
174
    }
175
176
    protected function workOutBoolean(string $fieldName, ?array $data = null, ?bool $default = false)
177
    {
178
        $val = $data[$fieldName] ?? $default;
179
        if(!$val) {
180
            return false;
181
        }
182
        return $val === '1' || $val === 'true' || $val === 'on' || $val === 'yes' || $val === true;
183
    }
184
185
    public function providePermissions()
186
    {
187
        return [
188
            'CMS_ACCESS_SITE_WIDE_SEARCH' => [
189
                'name' => 'Access to Search Website in the CMS',
190
                'category' => _t('SilverStripe\\Security\\Permission.CMS_ACCESS_CATEGORY', 'CMS Access'),
191
                'help' => 'Allow users to search for documents (all documents will also be checked to see if they are allowed to be viewed)',
192
            ],
193
        ];
194
    }
195
}
196