Completed
Push — master ( df31dd...7668ba )
by Andreas
08:37
created

process_results()   C

Complexity

Conditions 7
Paths 16

Size

Total Lines 51
Code Lines 28

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
eloc 28
nc 16
nop 1
dl 0
loc 51
rs 6.9743
c 0
b 0
f 0

How to fix   Long Method   

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
 * @package midcom.helper.search
4
 * @author CONTENT CONTROL http://www.contentcontrol-berlin.de/
5
 * @copyright CONTENT CONTROL http://www.contentcontrol-berlin.de/
6
 * @license http://www.gnu.org/licenses/gpl.html GNU General Public License
7
 */
8
9
/**
10
 * Search handler
11
 *
12
 * @package midcom.helper.search
13
 */
14
class midcom_helper_search_handler_search extends midcom_baseclasses_components_handler
1 ignored issue
show
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
15
{
16
    /**
17
     * Search form handler, nothing to do here.
18
     *
19
     * It uses the handler ID to distinguish between basic and advanced search forms.
20
     *
21
     * @param mixed $handler_id The ID of the handler.
22
     * @param array $args The argument list.
23
     * @param array &$data The local request data.
24
     */
25
    public function _handler_searchform($handler_id, array $args, array &$data)
26
    {
27
        $this->prepare_formdata($handler_id);
28
        $this->populate_toolbar();
29
    }
30
31
    private function prepare_formdata($handler_id)
0 ignored issues
show
Coding Style introduced by
prepare_formdata uses the super-global variable $_REQUEST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
32
    {
33
        $this->_request_data['query'] = (array_key_exists('query', $_REQUEST) ? $_REQUEST['query'] : '');
34
        if ($handler_id === 'advanced')
35
        {
36
            $this->_request_data['request_topic'] = (array_key_exists('topic', $_REQUEST) ? $_REQUEST['topic'] : '');
37
            $this->_request_data['component'] = (array_key_exists('component', $_REQUEST) ? $_REQUEST['component'] : '');
38
            $this->_request_data['lastmodified'] = (array_key_exists('lastmodified', $_REQUEST) ? ((integer) $_REQUEST['lastmodified']) : 0);
39
40
            $this->_request_data['topics'] = array('' => $this->_l10n->get('search anywhere'));
41
            $this->_request_data['components'] = array('' => $this->_l10n->get('search all content types'));
42
43
            $nap = new midcom_helper_nav();
44
            $this->search_nodes($nap->get_root_node(), $nap, '');
45
        }
46
        $this->_request_data['type'] = $handler_id;
47
    }
48
49
    /**
50
     * Prepare the topic and component listings, this is a bit work intensive though,
51
     * we need to traverse everything.
52
     */
53
    private function search_nodes($node_id, $nap, $prefix)
54
    {
55
        $node = $nap->get_node($node_id);
56
57
        if (   ! array_key_exists($node[MIDCOM_NAV_COMPONENT], $this->_request_data['components'])
58
            && $node[MIDCOM_NAV_COMPONENT] != 'midcom.helper.search')
59
        {
60
            $l10n = $this->_i18n->get_l10n($node[MIDCOM_NAV_COMPONENT]);
61
            $this->_request_data['components'][$node[MIDCOM_NAV_COMPONENT]] = $l10n->get($node[MIDCOM_NAV_COMPONENT]);
62
        }
63
        $this->_request_data['topics'][$node[MIDCOM_NAV_FULLURL]] = "{$prefix}{$node[MIDCOM_NAV_NAME]}";
64
65
        // Recurse
66
        $prefix .= "{$node[MIDCOM_NAV_NAME]} &rsaquo; ";
67
        $subnodes = $nap->list_nodes($node_id);
68
        foreach ($subnodes as $sub_id)
69
        {
70
            $this->search_nodes($sub_id, $nap, $prefix);
71
        }
72
    }
73
74
    /**
75
     * Search form show handler, displays the search form, including
76
     * some hints about how to write queries.
77
     *
78
     * @param mixed $handler_id The ID of the handler.
79
     * @param array &$data The local request data.
80
     */
81
    public function _show_searchform($handler_id, array &$data)
82
    {
83
        midcom_show_style('search_form');
84
    }
85
86
    /**
87
     * Expand arrays of custom rules to end of query
88
     *
89
     * @param string &$final_query reference to the query string to be passed on to the indexer.
90
     * @param mixed $terms array or string to append
91
     */
92
    private function append_terms_recursive(&$final_query, $terms)
93
    {
94
        if (is_array($terms))
95
        {
96
            foreach ($terms as $term)
97
            {
98
                $this->append_terms_recursive($final_query, $term);
99
            }
100
        }
101
        else if (is_string($terms))
102
        {
103
            $final_query .= "{$terms}";
104
        }
105
        else
106
        {
107
            debug_add('Don\'t know how to handle terms of type: ' . gettype($terms), MIDCOM_LOG_ERROR);
108
            debug_print_r('$terms', $terms);
109
        }
110
    }
111
112
    /**
113
     * Queries the information from the index and prepares to display the result page.
114
     *
115
     * @param mixed $handler_id The ID of the handler.
116
     * @param array $args The argument list.
117
     * @param array &$data The local request data.
118
     */
119
    public function _handler_result($handler_id, array $args, array &$data)
0 ignored issues
show
Coding Style introduced by
_handler_result uses the super-global variable $_REQUEST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
120
    {
121
        $this->prepare_query_data();
122
        $this->prepare_formdata($_REQUEST['type']);
123
124
        if (   count(explode(' ', $data['query'])) == 1
125
            && strpos($data['query'], '*') === false
126
            && $this->_config->get('single_term_auto_wilcard'))
127
        {
128
            //If there is only one search term append * to the query if auto_wildcard is enabled
129
            $data['query'] .= '*';
130
        }
131
132
        switch ($data['type'])
133
        {
134
            case 'basic':
135
                $indexer = midcom::get()->indexer;
136
                $final_query = $data['query'];
137
                debug_add("Final query: {$final_query}");
138
                $result = $indexer->query($final_query);
139
                break;
140
141
            case 'advanced':
142
                $result = $this->do_advanced_query($data);
143
                break;
144
        }
145
146
        $this->process_results($result);
0 ignored issues
show
Bug introduced by
The variable $result does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
147
        $this->populate_toolbar();
148
    }
149
150
    private function populate_toolbar()
0 ignored issues
show
Coding Style introduced by
populate_toolbar uses the super-global variable $_GET which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
151
    {
152
        $other_type = ($this->_request_data['type'] == 'advanced') ? 'basic' : 'advanced';
153
        $this->_request_data['params'] = '';
154
        if (!empty($_GET))
155
        {
156
            $this->_request_data['params'] = '?';
157
            $params = $_GET;
158
            $params['type'] = $other_type;
159
            $this->_request_data['params'] .= http_build_query($params);
160
        }
161
162
        $url = '';
163
        if ($this->_request_data['type'] == 'basic')
164
        {
165
            $url = 'advanced/';
166
        }
167
168
        $this->_view_toolbar->add_item
169
        (
170
            array
171
            (
172
                MIDCOM_TOOLBAR_URL => $url . $this->_request_data['params'],
173
                MIDCOM_TOOLBAR_LABEL => $this->_l10n->get($other_type . ' search'),
174
                MIDCOM_TOOLBAR_ICON => 'stock-icons/16x16/search.png',
175
            )
176
        );
177
    }
178
179
    private function process_results($result)
0 ignored issues
show
Coding Style introduced by
process_results uses the super-global variable $_REQUEST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
180
    {
181
        if ($result === false)
182
        {
183
            // Error while searching, we ignore this silently, as this is usually
184
            // a broken query. We don't have yet a way to pass error messages from
185
            // the indexer backend though (what would I give for a decent exception
186
            // handling here...)
187
            debug_add('Got boolean false as resultset (likely broken query), casting to empty array', MIDCOM_LOG_WARN);
188
            $result = Array();
189
        }
190
191
        $count = count($result);
192
        $this->_request_data['document_count'] = $count;
193
194
        if ($count == 0)
195
        {
196
            midcom::get()->cache->content->uncached();
197
        }
198
199
        if ($count > 0)
200
        {
201
            $results_per_page = $this->_config->get('results_per_page');
202
            $max_pages = ceil($count / $results_per_page);
203
            $page = min($_REQUEST['page'], $max_pages);
204
            $first_document_id = ($page - 1) * $results_per_page;
205
            $last_document_id = min(($count - 1), (($page * $results_per_page) - 1));
206
207
            $this->_request_data['page'] = $page;
208
            $this->_request_data['max_pages'] = $max_pages;
209
            $this->_request_data['first_document_number'] = $first_document_id + 1;
210
            $this->_request_data['last_document_number'] = $last_document_id + 1;
211
            $this->_request_data['shown_documents'] = $last_document_id - $first_document_id + 1;
212
            $this->_request_data['results_per_page'] = $results_per_page;
213
            $this->_request_data['all_results'] =& $result;
214
            $this->_request_data['result'] = array_slice($result, $first_document_id, $results_per_page);
215
216
            // Register GUIDs for cache engine
217
            foreach ($this->_request_data['result'] as $doc)
218
            {
219
                if (   !isset($doc->source)
220
                    || !mgd_is_guid($doc->source))
221
                {
222
                    // Non-Midgard results don't need to go through cache registration
223
                    continue;
224
                }
225
                midcom::get()->cache->content->register($doc->source);
226
            }
227
            reset($this->_request_data['result']);
228
        }
229
    }
230
231
    /**
232
     * Sane defaults for REQUEST vars
233
     */
234
    private function prepare_query_data()
0 ignored issues
show
Coding Style introduced by
prepare_query_data uses the super-global variable $_REQUEST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
235
    {
236
        // If we don't have a query string, relocate to empty search form
237
        if (!isset($_REQUEST['query']))
238
        {
239
            debug_add('$_REQUEST["query"] is not set, relocating back to form', MIDCOM_LOG_INFO);
240
            if ($this->_request_data['type'] == 'basic')
241
            {
242
                midcom::get()->relocate('');
243
            }
244
            midcom::get()->relocate('advanced/');
245
        }
246
        $defaults = array
247
        (
248
            'type' => 'basic',
249
            'page' => 1,
250
            'component' => '',
251
            'topic' => '',
252
            'lastmodified' => 0
253
        );
254
255
        $_REQUEST = array_merge($defaults, $_REQUEST);
256
    }
257
258
    private function do_advanced_query(array &$data)
0 ignored issues
show
Coding Style introduced by
do_advanced_query uses the super-global variable $_REQUEST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
259
    {
260
        $data['request_topic'] = trim($_REQUEST['topic']);
261
        $data['component'] = trim($_REQUEST['component']);
262
        $data['lastmodified'] = (integer) trim($_REQUEST['lastmodified']);
263
        $filter = new midcom_services_indexer_filter_chained;
264
        if ($data['lastmodified'] > 0)
265
        {
266
            $filter->add_filter(new midcom_services_indexer_filter_date('__EDITED', $data['lastmodified'], 0));
267
        }
268
269
        $final_query = '';
270
        if ($data['query'] != '')
271
        {
272
            $final_query = (midcom::get()->config->get('indexer_backend') == 'solr') ? $data['query'] : "({$data['query']})";
273
        }
274
275
        if ($data['request_topic'] != '')
276
        {
277
            $filter->add_filter(new midcom_services_indexer_filter_string('__TOPIC_URL', '"' . $data['request_topic'] . '*"'));
278
        }
279
280
        if ($data['component'] != '')
281
        {
282
            $filter->add_filter(new midcom_services_indexer_filter_string('__COMPONENT', $data['component']));
283
        }
284
285
        // Way to add very custom terms
286
        if (isset($_REQUEST['append_terms']))
287
        {
288
            $this->append_terms_recursive($final_query, $_REQUEST['append_terms']);
289
        }
290
291
        debug_add("Final query: {$final_query}");
292
        $indexer = midcom::get()->indexer;
293
294
        if ($filter->count() == 0)
295
        {
296
            $filter = null;
297
        }
298
        return $indexer->query($final_query, $filter);
299
    }
300
301
    /**
302
     * Displays the resultset.
303
     *
304
     * @param mixed $handler_id The ID of the handler.
305
     * @param array &$data The local request data.
306
     */
307
    public function _show_result($handler_id, array &$data)
308
    {
309
        if ($data['document_count'] > 0)
310
        {
311
            midcom_show_style('results');
312
        }
313
        else
314
        {
315
            midcom_show_style('no_match');
316
        }
317
    }
318
319
    /**
320
     * Prepare OpenSearch data file for browser search bar integration.
321
     *
322
     * @param mixed $handler_id The ID of the handler.
323
     * @param array $args The argument list.
324
     * @param array &$data The local request data.
325
     */
326
    public function _handler_opensearchdescription($handler_id, array $args, array &$data)
327
    {
328
        midcom::get()->cache->content->content_type("application/opensearchdescription+xml");
329
        midcom::get()->header("Content-type: application/opensearchdescription+xml; charset=UTF-8");
330
        midcom::get()->skip_page_style = true;
331
    }
332
333
    /**
334
     * Display OpenSearch data file for browser search bar integration.
335
     *
336
     * @param mixed $handler_id The ID of the handler.
337
     * @param array &$data The local request data.
338
     */
339
    public function _show_opensearchdescription($handler_id, array &$data)
340
    {
341
        $data['node'] = $this->_topic;
342
        midcom_show_style('opensearch_description');
343
    }
344
}
345