AddonsController::setElasticaService()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
1
<?php
2
3
use Elastica\Query;
4
use Elastica\Query\Match;
5
use SilverStripe\Elastica\ElasticaService;
6
use SilverStripe\Elastica\ResultList;
7
8
/**
9
 * Lists and searches add-ons.
10
 */
11
class AddonsController extends SiteController
12
{
13
14
    public static $url_handlers = array(
15
        'rss'             => 'rss',
16
        '$Vendor!/$Name!' => 'addon',
17
        '$Vendor!'        => 'vendor',
18
    );
19
20
    public static $allowed_actions = array(
21
        'index',
22
        'addon',
23
        'vendor',
24
        'rss',
25
    );
26
27
    public static $dependencies = array(
28
        'ElasticaService' => '%$ElasticaService'
29
    );
30
31
    /**
32
     * @var \SilverStripe\Elastica\ElasticaService
33
     */
34
    private $elastica;
35
36
    /**
37
     * @var PaginatedList|Addon[]
38
     */
39
    protected $addons;
40
41
    public function index()
42
    {
43
        return $this->renderWith(array('Addons', 'Page'));
44
    }
45
46
    public function setElasticaService(ElasticaService $elastica)
47
    {
48
        $this->elastica = $elastica;
49
    }
50
51
    public function addon($request)
52
    {
53
        $vendor = $request->param('Vendor');
54
        $name = $request->param('Name');
55
        $addon = Addon::get()->filter('Name', "$vendor/$name")->first();
56
57
        if (!$addon) {
58
            $this->httpError(404);
59
        }
60
61
        return new AddonController($this, $addon);
62
    }
63
64
    public function vendor($request)
65
    {
66
        $name = $request->param('Vendor');
67
        $vendor = AddonVendor::get()->filter('Name', $name)->first();
68
69
        if (!$vendor) {
70
            $this->httpError(404);
71
        }
72
73
        return new VendorController($this, $vendor);
74
    }
75
76
    public function Title()
77
    {
78
        return 'Add-ons';
79
    }
80
81
    public function Link($slug = null)
82
    {
83
        if ($slug) {
84
            return Controller::join_links(Director::baseURL(), 'add-ons', $slug);
85
        } else {
86
            return Controller::join_links(Director::baseURL(), 'add-ons');
87
        }
88
    }
89
90
    public function ListView()
91
    {
92
        $view = $this->request->getVar('view');
93
        if ($view) {
94
            return $view;
95
        } else {
96
            return 'list';
97
        }
98
    }
99
100
    public function Addons()
101
    {
102
        $list = Addon::get();
103
104
        if ($this->addons !== null) {
105
            return $this->addons;
106
        }
107
108
        $search = $this->request->getVar('search');
109
        $type = $this->request->getVar('type');
110
        $compat = $this->request->getVar('compatibility');
111
        $tags = $this->request->getVar('tags');
112
        $sort = $this->request->getVar('sort');
113
114
        $useElasticOrderAsDefault = false;
115
116
        if (!in_array($sort, array('name', 'downloads', 'newest', 'relative'))) {
117
            $sort = null;
118
        }
119
120
        // Proxy out a search to elastic if any parameters are set.
121
        if ($search || $type || $compat || $tags) {
122
            $bool = new Query\BoolQuery();
123
124
            $query = new Query();
125
            $query->setQuery($bool);
126
            $query->setSize(count($list));
127
128
            if ($search) {
129
                $match = new Query\MultiMatch();
130
                $match->setQuery($search);
131
                $match->setFields([
132
                    'name^12',
133
                    'description^3',
134
                    'readme',
135
                ]);
136
                $match->setType('phrase_prefix');
137
                $match->setUseDisMax(false);
138
139
                $query->setSort([
140
                    '_score',
141
                    'downloads',
142
                ]);
143
144
                $scorer = new Query\FunctionScore();
145
                $scorer->setQuery($match);
146
                $scorer->addFieldValueFactorFunction(
147
                    'downloads',
148
                    0.01,
149
                    Query\FunctionScore::FIELD_VALUE_FACTOR_MODIFIER_LN2P
150
                );
151
152
                $bool->addMust($scorer);
153
                $useElasticOrderAsDefault = true;
154
            }
155
156
            if ($type) {
157
                $bool->addMust(new Query\Term(array('type' => $type)));
158
            }
159
160
            if ($compat) {
161
                $bool->addMust(new Query\Terms('compatibility', (array)$compat));
162
            }
163
164
            if ($tags) {
165
                $bool->addMust(new Query\Terms('tags', (array)$tags));
166
            }
167
168
            $list = new ResultList($this->elastica->getIndex(), $query);
169
170
            if ($sort) {
171
                $ids = $list->column('ID');
172
173
                if ($ids) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $ids of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
174
                    $list = Addon::get()->byIDs($ids);
175
                } else {
176
                    $list = new ArrayList();
177
                }
178
            } else {
179
                $list = $list->toArrayList();
180
            }
181
        } else {
182
            if (!$sort) {
183
                $sort = 'relative';
184
            }
185
        }
186
187
        switch ($sort) {
188
            case 'name':
189
                $list = $list->sort('Name');
190
                break;
191
            case 'newest':
192
                $list = $list->sort('Released', 'DESC');
193
                break;
194
            case 'downloads':
195
                $list = $list->sort('Downloads', 'DESC');
196
                break;
197
            case 'relative':
198
                if (!$list instanceof ArrayList) {
199
                    /** @var ArrayList|Addon[] $unsorted */
200
                    $unsorted = ArrayList::create($list->toArray());
201
                } else {
202
                    $unsorted = $list;
203
                }
204
                foreach ($unsorted as $item) {
205
                    $item->Score = $item->relativePopularityFormatted() . ' per day';
206
                }
207
                $list = $unsorted->sort('relativePopularity DESC');
208
                break;
209
            default:
210
                if (!$useElasticOrderAsDefault) {
211
                    $list = $list->sort('Downloads', 'DESC');
212
                }
213
        }
214
215
        $list = $this->addons = new PaginatedList($list, $this->request);
0 ignored issues
show
Documentation introduced by
$this->request is of type object<SS_HTTPRequest>, but the function expects a array.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
216
        $list->setPageLength(16);
217
218
        return $list;
219
    }
220
221
    public function AddonsSearchForm()
222
    {
223
        $form = new Form(
224
            $this,
225
            'AddonsSearchForm',
226
            new FieldList(array(
227
                TextField::create('search', 'Search for')
228
                    ->setValue($this->request->getVar('search'))
229
                    ->addExtraClass('input-block-level'),
230
                DropdownField::create('sort', 'Sort by')
231
                    ->setSource(array(
232
                        'name'      => 'Name',
233
                        'downloads' => 'Most downloaded',
234
                        'relative'  => 'Average downloads per day',
235
                        'newest'    => 'Newest'
236
                    ))
237
                    ->setEmptyString('Best match')
238
                    ->setValue($this->request->getVar('sort'))
239
                    ->addExtraClass('input-block-level'),
240
                DropdownField::create('type', 'Add-on type')
241
                    ->setSource(array(
242
                        'module' => 'Modules',
243
                        'theme'  => 'Themes'
244
                    ))
245
                    ->setEmptyString('Modules and themes')
246
                    ->setValue($this->request->getVar('type'))
247
                    ->addExtraClass('input-block-level'),
248
                CheckboxSetField::create('compatibility', 'Compatible SilverStripe versions')
249
                    ->setSource(SilverStripeVersion::get()->map('Name', 'Name'))
250
                    ->setValue($this->request->getVar('compatibility'))
251
                    ->setTemplate('AddonsSearchCheckboxSetField')
252
            )),
253
            new FieldList()
254
        );
255
256
        return $form
257
            ->setFormMethod('GET')
258
            ->setFormAction($this->Link());
259
    }
260
261
    public function rss($request, $limit = 10)
0 ignored issues
show
Unused Code introduced by
The parameter $request is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
262
    {
263
        $addons = Addon::get()
264
            ->sort('Released', 'DESC')
265
            ->limit($limit);
266
267
        $rss = new RSSFeed(
268
            $addons,
269
            $this->Link(),
270
            "Newest addons on addons.silverstripe.org",
271
            null,
272
            'RSSTitle'
273
        );
274
275
        return $rss->outputToBrowser();
276
    }
277
}
278