SearchesController::advanced()   B
last analyzed

Complexity

Conditions 10
Paths 21

Size

Total Lines 66
Code Lines 39

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 1
Metric Value
cc 10
eloc 39
c 2
b 0
f 1
nc 21
nop 0
dl 0
loc 66
rs 7.6666

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
declare(strict_types=1);
4
5
/**
6
 * Saito - The Threaded Web Forum
7
 *
8
 * @copyright Copyright (c) the Saito Project Developers
9
 * @link https://github.com/Schlaefer/Saito
10
 * @license http://opensource.org/licenses/MIT
11
 */
12
13
namespace SaitoSearch\Controller;
14
15
use App\Controller\AppController;
16
use App\Model\Table\EntriesTable;
17
use Cake\Chronos\Chronos;
18
use Cake\Database\Driver\Mysql;
19
use Cake\Event\Event;
20
use Cake\Http\Response;
21
use Cake\I18n\FrozenDate;
22
use SaitoSearch\Lib\SimpleSearchString;
23
use Saito\Exception\SaitoForbiddenException;
24
use Search\Controller\Component\PrgComponent;
25
26
/**
27
 * @property EntriesTable $Entries
28
 * @property PrgComponent $Prg
29
 */
30
class SearchesController extends AppController
31
{
32
    /** @var array CakePHP helpers */
33
    public $helpers = ['Form', 'Html', 'Posting'];
34
35
    /**
36
     * {@inheritDoc}
37
     */
38
    public function initialize()
39
    {
40
        parent::initialize();
41
        $this->loadModel('Entries');
42
43
        $this->loadComponent('Paginator');
44
        // use setConfig on Component to not merge but overwrite/set the config
45
        $this->Paginator->setConfig('whitelist', ['page'], false);
46
47
        if ($this->getRequest()->getParam('action') === 'simple') {
48
            $this->Entries->addBehavior('SaitoSearch.SaitoSearch');
49
        } else {
50
            $this->Entries->addBehavior('Search.Search');
51
            $this->loadComponent('Search.Prg');
52
            $this->Prg->setConfig('actions', ['advanced'], false);
53
            $this->Prg->setConfig('queryStringWhitelist', [], false);
54
        }
55
    }
56
57
    /**
58
     * {@inheritDoc}
59
     */
60
    public function beforeFilter(Event $event)
61
    {
62
        parent::beforeFilter($event);
63
        $this->Authentication->allowUnauthenticated(['simple']);
64
    }
65
66
    /**
67
     * Simple search
68
     *
69
     * @return void|Response
70
     */
71
    public function simple()
72
    {
73
        $this->set('titleForPage', __d('saito_search', 'simple.t'));
74
75
        $defaults = [
76
            'searchTerm' => '',
77
            'order' => 'time',
78
        ];
79
80
        // @td pgsql
81
        $connection = $this->Entries->getConnection();
82
        if (!($connection->getDriver() instanceof Mysql)) {
83
            return $this->redirect(['action' => 'advanced']);
84
        }
85
86
        $query = $this->request->getQueryParams();
87
        $query = array_intersect_key($query, array_flip(['searchTerm', 'order']));
88
        $query += $defaults;
89
        $this->set('searchDefaults', $query);
90
91
        $showEmptyForm = empty($query['searchTerm']);
92
        if ($showEmptyForm) {
93
            return;
94
        }
95
96
        $searchString = new SimpleSearchString($query['searchTerm']);
97
        $finder = $query['order'] === 'rank' ? 'simpleSearchByRank' : 'simpleSearchByTime';
98
        $config = [
99
            'finder' => [
100
                $finder => [
101
                    'categories' => $this->CurrentUser->getCategories()->getAll('read'),
102
                    'searchTerm' => $searchString,
103
                ],
104
            ],
105
            // only sort paginate for "page"-query-param
106
            'whitelist' => ['page'],
107
        ];
108
109
        $results = $this->Paginator->paginate($this->Entries, $config);
110
        $this->set('omittedWords', $searchString->getOmittedWords());
111
        $this->set('minWordLength', $searchString->getMinWordLength());
112
        $this->set('results', $results);
113
        $this->set('showBottomNavigation', true);
114
    }
115
116
    /**
117
     * Advanced Search
118
     *
119
     * @return void
120
     */
121
    public function advanced()
122
    {
123
        $this->set('titleForPage', __d('saito_search', 'advanced.t'));
124
125
        $queryData = $this->request->getQueryParams();
126
127
        $now = Chronos::now();
128
129
        /// Setup time filter data
130
        $first = $this->Entries->find()
131
            ->order(['id' => 'ASC'])
132
            ->first();
133
        if ($first) {
134
            $startDate = $first->get('time');
135
            /// Limit default search range to one year in the past
136
            $aYearAgo = new FrozenDate('-1 year');
137
            $defaultDate = $startDate < $aYearAgo ? $aYearAgo : $startDate;
138
        } else {
139
            /// No entries yet
140
            $startDate = $defaultDate = $now;
141
        }
142
        $startYear = $startDate->format('Y');
143
144
        // calculate current month and year
145
        $month = $queryData['month']['month'] ?? $defaultDate->month;
146
        $year = $queryData['year']['year'] ?? $defaultDate->year;
147
        $this->set(compact('month', 'year', 'startYear'));
148
149
        /// Category drop-down data
150
        $categories = $this->CurrentUser->getCategories()->getAll('read', 'select');
151
        $this->set('categories', $categories);
152
153
        if (empty($queryData['subject']) && empty($queryData['text']) && empty($queryData['name'])) {
154
            // just show form;
155
            return;
156
        }
157
158
        /// setup find
159
        $query = $this->Entries
160
            ->find('search', ['search' => $queryData])
161
            ->contain(['Categories', 'Users'])
162
            ->order(['Entries.id' => 'DESC']);
163
164
        /// Time filter
165
        $time = Chronos::createFromDate($year, $month, 1);
166
        if ($now->year !== $defaultDate->year || $now->month !== $defaultDate->month) {
167
            $query->where(['time >=' => $time]);
168
        }
169
170
        /// Category filter
171
        $categories = array_flip($categories);
172
        if (!empty($queryData['category_id'])) {
173
            $category = $queryData['category_id'];
174
            if (!in_array($category, $categories)) {
175
                throw new SaitoForbiddenException(
176
                    "Tried to search category $category.",
177
                    ['CurrentUser' => $this->CurrentUser]
178
                );
179
            }
180
            $categories = [$category];
181
        }
182
        $query->where(['category_id IN' => $categories]);
183
184
        $results = $this->paginate($query);
185
        $this->set(compact('results'));
186
        $this->set('showBottomNavigation', true);
187
    }
188
}
189