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
|
|
|
public function index() |
37
|
|
|
{ |
38
|
|
|
return $this->renderWith(array('Addons', 'Page')); |
39
|
|
|
} |
40
|
|
|
|
41
|
|
|
public function setElasticaService(ElasticaService $elastica) |
42
|
|
|
{ |
43
|
|
|
$this->elastica = $elastica; |
44
|
|
|
} |
45
|
|
|
|
46
|
|
|
public function addon($request) |
47
|
|
|
{ |
48
|
|
|
$vendor = $request->param('Vendor'); |
49
|
|
|
$name = $request->param('Name'); |
50
|
|
|
$addon = Addon::get()->filter('Name', "$vendor/$name")->first(); |
51
|
|
|
|
52
|
|
|
if (!$addon) { |
53
|
|
|
$this->httpError(404); |
54
|
|
|
} |
55
|
|
|
|
56
|
|
|
return new AddonController($this, $addon); |
57
|
|
|
} |
58
|
|
|
|
59
|
|
|
public function vendor($request) |
60
|
|
|
{ |
61
|
|
|
$name = $request->param('Vendor'); |
62
|
|
|
$vendor = AddonVendor::get()->filter('Name', $name)->first(); |
63
|
|
|
|
64
|
|
|
if (!$vendor) { |
65
|
|
|
$this->httpError(404); |
66
|
|
|
} |
67
|
|
|
|
68
|
|
|
return new VendorController($this, $vendor); |
69
|
|
|
} |
70
|
|
|
|
71
|
|
|
public function Title() |
72
|
|
|
{ |
73
|
|
|
return 'Add-ons'; |
74
|
|
|
} |
75
|
|
|
|
76
|
|
|
public function Link($slug = null) |
77
|
|
|
{ |
78
|
|
|
if ($slug) { |
79
|
|
|
return Controller::join_links(Director::baseURL(), 'add-ons', $slug); |
80
|
|
|
} else { |
81
|
|
|
return Controller::join_links(Director::baseURL(), 'add-ons'); |
82
|
|
|
} |
83
|
|
|
} |
84
|
|
|
|
85
|
|
|
public function ListView() |
86
|
|
|
{ |
87
|
|
|
$view = $this->request->getVar('view'); |
88
|
|
|
if ($view) { |
89
|
|
|
return $view; |
90
|
|
|
} else { |
91
|
|
|
return 'list'; |
92
|
|
|
} |
93
|
|
|
} |
94
|
|
|
|
95
|
|
|
public function Addons() |
96
|
|
|
{ |
97
|
|
|
$list = Addon::get(); |
98
|
|
|
|
99
|
|
|
$search = $this->request->getVar('search'); |
100
|
|
|
$type = $this->request->getVar('type'); |
101
|
|
|
$compat = $this->request->getVar('compatibility'); |
102
|
|
|
$tags = $this->request->getVar('tags'); |
103
|
|
|
$sort = $this->request->getVar('sort'); |
104
|
|
|
|
105
|
|
|
if (!in_array($sort, array('name', 'downloads', 'newest', 'relative'))) { |
106
|
|
|
$sort = null; |
107
|
|
|
} |
108
|
|
|
|
109
|
|
|
// Proxy out a search to elastic if any parameters are set. |
110
|
|
|
if ($search || $type || $compat || $tags) { |
111
|
|
|
$bool = new Query\BoolQuery(); |
112
|
|
|
|
113
|
|
|
$query = new Query(); |
114
|
|
|
$query->setQuery($bool); |
115
|
|
|
$query->setSize(count($list)); |
116
|
|
|
|
117
|
|
|
if ($search) { |
118
|
|
|
$match = new Match(); |
119
|
|
|
$match->setField('_all', $search); |
120
|
|
|
|
121
|
|
|
$bool->addMust($match); |
122
|
|
|
} |
123
|
|
|
|
124
|
|
|
if ($type) { |
125
|
|
|
$bool->addMust(new Query\Term(array('type' => $type))); |
126
|
|
|
} |
127
|
|
|
|
128
|
|
|
if ($compat) { |
129
|
|
|
$bool->addMust(new Query\Terms('compatibility', (array)$compat)); |
130
|
|
|
} |
131
|
|
|
|
132
|
|
|
if ($tags) { |
133
|
|
|
$bool->addMust(new Query\Terms('tags', (array)$tags)); |
134
|
|
|
} |
135
|
|
|
|
136
|
|
|
$list = new ResultList($this->elastica->getIndex(), $query); |
137
|
|
|
|
138
|
|
|
if ($sort) { |
139
|
|
|
$ids = $list->column('ID'); |
140
|
|
|
|
141
|
|
|
if ($ids) { |
|
|
|
|
142
|
|
|
$list = Addon::get()->byIDs($ids); |
143
|
|
|
} else { |
144
|
|
|
$list = new ArrayList(); |
145
|
|
|
} |
146
|
|
|
} else { |
147
|
|
|
$list = $list->toArrayList(); |
148
|
|
|
} |
149
|
|
|
} else { |
150
|
|
|
if (!$sort) { |
151
|
|
|
$sort = 'relative'; |
152
|
|
|
} |
153
|
|
|
} |
154
|
|
|
|
155
|
|
|
switch ($sort) { |
156
|
|
|
case 'name': |
157
|
|
|
$list = $list->sort('Name'); |
158
|
|
|
break; |
159
|
|
|
case 'newest': |
160
|
|
|
$list = $list->sort('Released', 'DESC'); |
161
|
|
|
break; |
162
|
|
|
case 'downloads': |
163
|
|
|
$list = $list->sort('Downloads', 'DESC'); |
164
|
|
|
break; |
165
|
|
|
case 'relative': |
166
|
|
|
if (!$list instanceof ArrayList) { |
167
|
|
|
/** @var ArrayList|Addon[] $unsorted */ |
168
|
|
|
$unsorted = ArrayList::create($list->toArray()); |
169
|
|
|
} else { |
170
|
|
|
$unsorted = $list; |
171
|
|
|
} |
172
|
|
|
foreach ($unsorted as $item) { |
173
|
|
|
$item->Score = $item->relativePopularityFormatted() . ' per day'; |
174
|
|
|
} |
175
|
|
|
$list = $unsorted->sort('relativePopularity DESC'); |
176
|
|
|
break; |
177
|
|
|
default: |
178
|
|
|
$list = $list->sort('Downloads', 'DESC'); |
179
|
|
|
} |
180
|
|
|
|
181
|
|
|
$list = new PaginatedList($list, $this->request); |
|
|
|
|
182
|
|
|
$list->setPageLength(16); |
183
|
|
|
|
184
|
|
|
return $list; |
185
|
|
|
} |
186
|
|
|
|
187
|
|
|
public function AddonsSearchForm() |
188
|
|
|
{ |
189
|
|
|
$form = new Form( |
190
|
|
|
$this, |
191
|
|
|
'AddonsSearchForm', |
192
|
|
|
new FieldList(array( |
193
|
|
|
TextField::create('search', 'Search for') |
194
|
|
|
->setValue($this->request->getVar('search')) |
195
|
|
|
->addExtraClass('input-block-level'), |
196
|
|
|
DropdownField::create('sort', 'Sort by') |
197
|
|
|
->setSource(array( |
198
|
|
|
'name' => 'Name', |
199
|
|
|
'downloads' => 'Most downloaded', |
200
|
|
|
'relative' => 'Average downloads per day', |
201
|
|
|
'newest' => 'Newest' |
202
|
|
|
)) |
203
|
|
|
->setEmptyString('Best match') |
204
|
|
|
->setValue($this->request->getVar('sort')) |
205
|
|
|
->addExtraClass('input-block-level'), |
206
|
|
|
DropdownField::create('type', 'Add-on type') |
207
|
|
|
->setSource(array( |
208
|
|
|
'module' => 'Modules', |
209
|
|
|
'theme' => 'Themes' |
210
|
|
|
)) |
211
|
|
|
->setEmptyString('Modules and themes') |
212
|
|
|
->setValue($this->request->getVar('type')) |
213
|
|
|
->addExtraClass('input-block-level'), |
214
|
|
|
CheckboxSetField::create('compatibility', 'Compatible SilverStripe versions') |
215
|
|
|
->setSource(SilverStripeVersion::get()->map('Name', 'Name')) |
216
|
|
|
->setValue($this->request->getVar('compatibility')) |
217
|
|
|
->setTemplate('AddonsSearchCheckboxSetField') |
218
|
|
|
)), |
219
|
|
|
new FieldList() |
220
|
|
|
); |
221
|
|
|
|
222
|
|
|
return $form |
223
|
|
|
->setFormMethod('GET') |
224
|
|
|
->setFormAction($this->Link()); |
225
|
|
|
} |
226
|
|
|
|
227
|
|
|
public function rss($request, $limit = 10) |
|
|
|
|
228
|
|
|
{ |
229
|
|
|
$addons = Addon::get() |
230
|
|
|
->sort('Released', 'DESC') |
231
|
|
|
->limit($limit); |
232
|
|
|
|
233
|
|
|
$rss = new RSSFeed( |
234
|
|
|
$addons, |
235
|
|
|
$this->Link(), |
236
|
|
|
"Newest addons on addons.silverstripe.org", |
237
|
|
|
null, |
238
|
|
|
'RSSTitle' |
239
|
|
|
); |
240
|
|
|
|
241
|
|
|
return $rss->outputToBrowser(); |
242
|
|
|
} |
243
|
|
|
} |
244
|
|
|
|
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.