ForumSphinxSearch::getResults()   B
last analyzed

Complexity

Conditions 6
Paths 6

Size

Total Lines 57
Code Lines 30

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 57
rs 8.7433
c 0
b 0
f 0
cc 6
eloc 30
nc 6
nop 5

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
/**
4
 * An extension to the default Forum search to use the {@link Sphinx} class instead
5
 * of the standard database search.
6
 *
7
 * To use Sphinx instead of the built in Search is use:
8
 *
9
 * ``ForumHolder::set_search_engine('Sphinx');``
10
 *
11
 * @todo Currently this does not index or search forum Titles...
12
 *
13
 * @package forum
14
 */
15
16
class ForumSphinxSearch implements ForumSearchProvider
17
{
18
    
19
    private $search_cache = array();
20
    
21
    // These are classes that *may* be indexed by Sphinx. If they are,
22
    // we can search for them, and we may need to add extra sphinx
23
    // properties to them.
24
    protected static $extra_search_classes = array('Forum', 'Member');
25
26
    /**
27
     * Get the results
28
     *
29
     * @return DataObjectSet
30
     */
31
    public function getResults($forumHolderID, $query, $order, $offset = 0, $limit = 10)
32
    {
33
        $query = $this->cleanQuery($query);
34
35
        // Default weights put title ahead of content, which effectively
36
        // puts threads ahead of posts.
37
        $fieldWeights = array("Title" => 5, "Content" => 1);
38
39
        // Work out what sorting method
40
        switch ($order) {
41
            case 'date':
42
                $mode = 'fields';
43
                
44
                $sortarg = array('Created' => 'DESC');
45
                break;
46
            case 'title':
47
                $mode = 'fields';
48
                
49
                $sortarg = array('Title' => 'ASC');
50
                break;
51
            default:
52
                // Sort by relevancy, but add the calculated age band,
53
                // which will push up more recent content.
54
                $mode = 'eval';
55
                $sortarg = "@relevance + _ageband";
56
57
                // Downgrade the title weighting, which will give more
58
                // emphasis to age.
59
                $fieldWeights = array("Title" => 1, "Content" => 1);
60
61
                break;
62
        }
63
        
64
        $cachekey = $query.':'.$offset;
65
        if (!isset($this->search_cache[$cachekey])) {
66
            // Determine the classes to search. This always include
67
            // ForumThread and Post, since we decorated them. It also
68
            // includes Forum and Member if they are decorated, as
69
            // appropriate.
70
            $classes = array('ForumThread', 'Post');
71
            foreach (self::$extra_search_classes as $c) {
72
                if (Object::has_extension($c, 'SphinxSearchable')) {
73
                    $classes[] = $c;
74
                }
75
            }
76
77
            $this->search_cache[$cachekey] = SphinxSearch::search($classes, $query, array(
78
                'start'             => $offset,
79
                'pagesize'      => $limit,
80
                'sortmode'      => $mode,
81
                'sortarg'       => $sortarg,
82
                'field_weights'     => $fieldWeights
83
            ));
84
        }
85
        
86
        return $this->search_cache[$cachekey]->Matches;
87
    }
88
89
    // Clean up the query text with some combinatiosn that are known to
90
    // cause problems for sphinx, including:
91
    // - term starts with $
92
    // - presence of /, ^, @, !, (, )
93
    // we just remove the chars when we see these
94
    public function cleanQuery($query)
95
    {
96
        $query = trim($query);
97
        if (!$query) {
98
            return $query;
99
        }
100
        if ($query[0] == "$") {
101
            $query = substr($query, 1);
102
        }
103
        $query = str_replace(
104
            array("/", "^", "@", "!", "(", ")", "~"),
105
            array("",  "",  "",  "",  "",  "",  ""),
106
            $query
107
        );
108
        return $query;
109
    }
110
111
    public function load()
112
    {
113
        // Add the SphinxSearchable extension to ForumThread and Post,
114
        // with an extra computed column that gives an age band. The
115
        // age bands are based on Created, as follows:
116
        // _ageband = 10		where object is <30 days old
117
        // _ageband = 9			where object is 30-90 days old
118
        // _ageband = 8			where object is 90-180 days old
119
        // _ageband = 7			where object is 180 days to 1 year old
120
        // _ageband = 6			older than one year.
121
        // The age band is calculated so that when added to @relevancy,
122
        // it can be sorted. This calculation is valid for data that
123
        // ages like Post and ForumThread, but not for other classes
124
        // we can search, like Member and Forum. In those cases,
125
        // we still have to add the extra field _ageband, but we set it
126
        // to 10 so it's sorted like it's recent.
127
        DataObject::add_extension('ForumThread', 'SphinxSearchable');
128
        Object::set_static("ForumThread", "sphinx", array(
0 ignored issues
show
Deprecated Code introduced by
The method Object::set_static() has been deprecated.

This method has been deprecated.

Loading history...
129
            "extra_fields" => array("_ageband" => "if(datediff(now(),LastEdited)<30,10,if(datediff(now(),LastEdited)<90,9,if(datediff(now(),LastEdited)<180,8,if(datediff(now(),LastEdited)<365,7,6))))")
130
        ));
131
        DataObject::add_extension('Post', 'SphinxSearchable');
132
        Object::set_static("Post", "sphinx", array(
0 ignored issues
show
Deprecated Code introduced by
The method Object::set_static() has been deprecated.

This method has been deprecated.

Loading history...
133
            "extra_fields" => array("_ageband" => "if(datediff(now(),Created)<30,10,if(datediff(now(),Created)<90,9,if(datediff(now(),Created)<180,8,if(datediff(now(),Created)<365,7,6))))")
134
        ));
135
136
        // For classes that might be indexed, add the extra field if they
137
        // are decorated with SphinxSearchable.
138
        foreach (self::$extra_search_classes as $c) {
139
            if (Object::has_extension($c, 'SphinxSearchable')) {
140
                $conf = Object::uninherited_static($c, "sphinx");
0 ignored issues
show
Deprecated Code introduced by
The method Object::uninherited_static() has been deprecated.

This method has been deprecated.

Loading history...
141
                if (!$conf) {
142
                    $conf = array();
143
                }
144
                if (!isset($conf['extra_fields'])) {
145
                    $conf['extra_fields'] = array();
146
                }
147
                $conf['extra_fields']['_ageband'] = "10";
148
                Object::set_static($c, "sphinx", $conf);
0 ignored issues
show
Deprecated Code introduced by
The method Object::set_static() has been deprecated.

This method has been deprecated.

Loading history...
149
            }
150
        }
151
    }
152
}
153