SearchController::renderPageLinks()   F
last analyzed

Complexity

Conditions 14
Paths 480

Size

Total Lines 68

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 68
rs 2.9559
cc 14
nc 480
nop 0

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
namespace Alpha\Controller;
4
5
use Alpha\Util\Logging\Logger;
6
use Alpha\Util\Logging\KPI;
7
use Alpha\Util\Logging\LogProviderFile;
8
use Alpha\Util\Config\ConfigProvider;
9
use Alpha\Util\Http\Request;
10
use Alpha\Util\Http\Response;
11
use Alpha\Util\Service\ServiceFactory;
12
use Alpha\View\View;
13
use Alpha\View\Widget\Button;
14
use Alpha\Controller\Front\FrontController;
15
16
/**
17
 * Search engine controller.
18
 *
19
 * @since 1.0
20
 *
21
 * @author John Collins <[email protected]>
22
 * @license http://www.opensource.org/licenses/bsd-license.php The BSD License
23
 * @copyright Copyright (c) 2018, John Collins (founder of Alpha Framework).
24
 * All rights reserved.
25
 *
26
 * <pre>
27
 * Redistribution and use in source and binary forms, with or
28
 * without modification, are permitted provided that the
29
 * following conditions are met:
30
 *
31
 * * Redistributions of source code must retain the above
32
 *   copyright notice, this list of conditions and the
33
 *   following disclaimer.
34
 * * Redistributions in binary form must reproduce the above
35
 *   copyright notice, this list of conditions and the
36
 *   following disclaimer in the documentation and/or other
37
 *   materials provided with the distribution.
38
 * * Neither the name of the Alpha Framework nor the names
39
 *   of its contributors may be used to endorse or promote
40
 *   products derived from this software without specific
41
 *   prior written permission.
42
 *
43
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
44
 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
45
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
46
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
47
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
48
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
49
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
50
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
51
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
52
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
53
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
54
 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
55
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
56
 * </pre>
57
 */
58
class SearchController extends Controller implements ControllerInterface
59
{
60
    /**
61
     * Trace logger.
62
     *
63
     * @var \Alpha\Util\Logging\Logger
64
     *
65
     * @since 1.0
66
     */
67
    private static $logger = null;
0 ignored issues
show
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
68
69
    /**
70
     * The start number for list pageination.
71
     *
72
     * @var int
73
     *
74
     * @since 1.0
75
     */
76
    protected $startPoint;
77
78
    /**
79
     * The result count from the search.
80
     *
81
     * @var int
82
     *
83
     * @since 1.0
84
     */
85
    protected $resultCount = 0;
86
87
    /**
88
     * The search query supplied.
89
     *
90
     * @var string
91
     *
92
     * @since 1.0
93
     */
94
    protected $query;
95
96
    /**
97
     * constructor to set up the object.
98
     *
99
     * @param string $visibility The name of the rights group that can access this controller.
100
     *
101
     * @since 1.0
102
     */
103
    public function __construct($visibility = 'Public')
104
    {
105
        self::$logger = new Logger('SearchController');
106
        self::$logger->debug('>>__construct(visibility=['.$visibility.'])');
107
108
        // ensure that the super class constructor is called, indicating the rights group
109
        parent::__construct($visibility);
110
111
        self::$logger->debug('<<__construct');
112
    }
113
114
    /**
115
     * Handle GET requests.
116
     *
117
     * @param \Alpha\Util\Http\Request $request
118
     *
119
     * @return \Alpha\Util\Http\Response
120
     *
121
     * @since 1.0
122
     *
123
     * @throws \Alpha\Exception\IllegalArguementException
124
     */
125
    public function doGET($request)
126
    {
127
        self::$logger->debug('>>doGET($request=['.var_export($request, true).'])');
128
129
        $params = $request->getParams();
130
131
        if (isset($params['start']) ? $this->startPoint = $params['start'] : $this->startPoint = 0);
132
133
        $config = ConfigProvider::getInstance();
134
135
        $KPI = new KPI('search');
136
137
        $body = '';
138
139
        if (isset($params['query'])) {
140
            $this->query = $params['query'];
141
142
            // replace any %20 on the URL with spaces
143
            $params['query'] = str_replace('%20', ' ', $params['query']);
144
145
            $this->setTitle('Search results - '.$params['query']);
146
            $body .= View::displayPageHead($this);
147
148
            // log the user's search query in a log file
149
            $log = new LogProviderFile();
150
            $log->setPath($config->get('app.file.store.dir').'logs/search.log');
151
            $log->writeLine(array($params['query'], date('Y-m-d H:i:s'), $request->getUserAgent(), $request->getIP()));
152
153
            $KPI->logStep('log search query');
154
155
            $provider = ServiceFactory::getInstance('Alpha\Util\Search\SearchProviderTags', 'Alpha\Util\Search\SearchProviderInterface');
156
157
            // if a Record name is provided, only search tags on that class, otherwise search all records
158
            if (isset($params['ActiveRecordType'])) {
159
                $results = $provider->search($params['query'], $params['bo'], $this->startPoint);
160
            } else {
161
                $results = $provider->search($params['query'], 'all', $this->startPoint);
162
            }
163
164
            $this->resultCount = $provider->getNumberFound();
165
166
            $KPI->logStep('search completed using SearchProviderTags provider');
167
168
            $body .= $this->renderResultList($results, $params['query']);
169
        } else {
170
            $this->setTitle('Search results');
171
            $body .= View::displayPageHead($this);
172
            self::$logger->debug('No search query provided!');
173
        }
174
175
        $body .= View::displayPageFoot($this);
176
177
        $KPI->log();
178
179
        self::$logger->debug('<<doGET');
180
181
        return new Response(200, $body, array('Content-Type' => 'text/html'));
182
    }
183
184
    /**
185
     * Renders the search result list.
186
     *
187
     * @param array  $results
188
     * @param string $query
189
     * @param bool   $showTags
190
     *
191
     * @since 1.0
192
     *
193
     * @return string
194
     */
195
    protected function renderResultList($results, $query = '', $showTags = true)
196
    {
197
        $body = '';
198
199
        if (!empty($query)) {
200
            $body .= '<h2>Displaying results for &quot;'.$query.'&quot;</h2>';
201
        }
202
203
        foreach ($results as $bo) {
204
            if ($bo instanceof \Alpha\Model\Article && $bo->get('published') == false) {
205
                --$this->resultCount;
206
            } else {
207
                $view = View::getInstance($bo);
208
                $URI = $this->request->getURI();
209
                $body .= $view->listView(array('formAction' => $URI));
210
211
                if ($showTags) {
212
                    $tags = $bo->getPropObject('tags')->getRelated();
213
214
                    if (count($tags) > 0) {
215
                        $body .= '<p>Tags: ';
216
217
                        $queryTerms = explode(' ', mb_strtolower($query));
218
219
                        foreach ($tags as $tag) {
220
                            $body .= (in_array($tag->get('content'), $queryTerms) ? '<strong>'.$tag->get('content').' </strong>' : $tag->get('content').' ');
221
                        }
222
223
                        $body .= '</p>';
224
                    }
225
                }
226
            }
227
        }
228
229
        return $body;
230
    }
231
232
    /**
233
     * Displays a search form on the top of the page.
234
     *
235
     * @return string
236
     *
237
     * @since 1.0
238
     */
239
    public function after_displayPageHead_callback()
240
    {
241
        $config = ConfigProvider::getInstance();
242
243
        $body = parent::after_displayPageHead_callback();
244
245
        $body .= '<div align="center" class="form-group"><form class="form-inline" method="GET" id="search_form" onsubmit="document.location = \''.$config->get('app.url').'search/\'+document.getElementById(\'q\').value; return false;">';
246
        $body .= '<label for="q">Search for</label><input type="text" name="q" id="q" class="form-control" style="width:50%; margin:10px;"/>';
247
        $button = new Button('document.location = \''.$config->get('app.url').'/search/\'+document.getElementById(\'q\').value', 'Search', 'searchButton');
248
        $body .= $button->render();
249
        $body .= '</p></form></div>';
250
251
        return $body;
252
    }
253
254
    /**
255
     * Method to display the page footer with pageination links.
256
     *
257
     * @return string
258
     *
259
     * @since 1.0
260
     */
261
    public function before_displayPageFoot_callback()
262
    {
263
        $body = $this->renderPageLinks();
264
265
        $body .= '<br>';
266
267
        return $body;
268
    }
269
270
    /**
271
     * Method for rendering the pagination links.
272
     *
273
     * @return string
274
     *
275
     * @since 1.0
276
     */
277
    protected function renderPageLinks()
278
    {
279
        $config = ConfigProvider::getInstance();
280
281
        $params = $this->request->getParams();
282
283
        $body = '';
284
285
        $end = ($this->startPoint+$config->get('app.list.page.amount'));
286
287
        if ($end > $this->resultCount) {
288
            $end = $this->resultCount;
289
        }
290
291
        if ($this->resultCount > 0) {
292
            $body .= '<p align="center">Displaying '.($this->startPoint+1).' to '.$end.' of <strong>'.$this->resultCount.'</strong>.&nbsp;&nbsp;';
293
        } else {
294
            if (!empty($this->query)) {
295
                $body .= View::displayUpdateMessage('There were no search results for your query.');
296
            }
297
        }
298
299
        $body .= '<ul class="pagination">';
300
301
        if ($this->startPoint > 0) {
302
            // handle secure URLs
303
            if (isset($params['tk'])) {
304
                $body .= '<li><a href="'.FrontController::generateSecureURL('act=Search&q='.$this->query.'&start='.($this->startPoint-$config->get('app.list.page.amount'))).'">&laquo;</a></li>';
305
            } else {
306
                $body .= '<li><a href="'.$config->get('app.url').'/search/'.$this->query.'/'.($this->startPoint-$config->get('app.list.page.amount')).'">&laquo;</a></li>';
307
            }
308
        } elseif ($this->resultCount > $config->get('app.list.page.amount')) {
309
            $body .= '<li class="disabled"><a href="#">&laquo;</a></li>';
310
        }
311
312
        $page = 1;
313
314
        for ($i = 0; $i < $this->resultCount; $i += $config->get('app.list.page.amount')) {
315
            if ($i != $this->startPoint) {
316
                // handle secure URLs
317
                if (isset($params['tk'])) {
318
                    $body .= '<li><a href="'.FrontController::generateSecureURL('act=Search&q='.$this->query.'&start='.$i).'">'.$page.'</a></li>';
319
                } else {
320
                    $body .= '<li><a href="'.$config->get('app.url').'/search/'.$this->query.'/'.$i.'">'.$page.'</a></li>';
321
                }
322
            } elseif ($this->resultCount > $config->get('app.list.page.amount')) {
323
                $body .= '<li class="active"><a href="#">'.$page.'</a></li>';
324
            }
325
326
            ++$page;
327
        }
328
329
        if ($this->resultCount > $end) {
330
            // handle secure URLs
331
            if (isset($params['tk'])) {
332
                $body .= '<li><a href="'.FrontController::generateSecureURL('act=Search&q='.$this->query.'&start='.($this->startPoint+$config->get('app.list.page.amount'))).'">Next-&gt;&gt;</a></li>';
333
            } else {
334
                $body .= '<li><a href="'.$config->get('app.url').'/search/'.$this->query.'/'.($this->startPoint+$config->get('app.list.page.amount')).'">&raquo;</a></li>';
335
            }
336
        } elseif ($this->resultCount > $config->get('app.list.page.amount')) {
337
            $body .= '<li class="disabled"><a href="#">&raquo;</a></li>';
338
        }
339
340
        $body .= '</ul>';
341
        $body .= '</p>';
342
343
        return $body;
344
    }
345
346
    /**
347
     * Get the search result count.
348
     *
349
     * @return int
350
     *
351
     * @since 1.2.4
352
     */
353
    public function getResultCount()
354
    {
355
        return $this->resultCount;
356
    }
357
358
    /**
359
     * Set the search result count.
360
     *
361
     * @param int $resultCount
362
     *
363
     * @since 1.2.4
364
     */
365
    protected function setResultCount($resultCount)
366
    {
367
        $this->resultCount = $resultCount;
368
    }
369
370
    /**
371
     * Get the search query.
372
     *
373
     * @return string
374
     *
375
     * @since 1.2.4
376
     */
377
    public function getSearchQuery()
378
    {
379
        return $this->query;
380
    }
381
382
    /**
383
     * Set the search query.
384
     *
385
     * @param string $query
386
     *
387
     * @since 1.2.4
388
     */
389
    protected function setSearchQuery($query)
390
    {
391
        $this->query = $query;
392
    }
393
}
394