Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 97 |
|
0.00% |
0 / 12 |
CRAP | |
0.00% |
0 / 1 |
feed | |
0.00% |
0 / 97 |
|
0.00% |
0 / 12 |
2352 | |
0.00% |
0 / 1 |
__construct | |
0.00% |
0 / 12 |
|
0.00% |
0 / 1 |
2 | |||
forums | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
6 | |||
news | |
0.00% |
0 / 9 |
|
0.00% |
0 / 1 |
6 | |||
topics | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
6 | |||
topics_new | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
topics_active | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
6 | |||
forum | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
6 | |||
topic | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
6 | |||
overall | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
6 | |||
send_feed | |
0.00% |
0 / 5 |
|
0.00% |
0 / 1 |
12 | |||
send_feed_do | |
0.00% |
0 / 51 |
|
0.00% |
0 / 1 |
812 | |||
send_unavailable | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 |
1 | <?php |
2 | /** |
3 | * |
4 | * This file is part of the phpBB Forum Software package. |
5 | * |
6 | * @copyright (c) phpBB Limited <https://www.phpbb.com> |
7 | * @license GNU General Public License, version 2 (GPL-2.0) |
8 | * |
9 | * For full copyright and license information, please see |
10 | * the docs/CREDITS.txt file. |
11 | * |
12 | */ |
13 | |
14 | namespace phpbb\feed\controller; |
15 | |
16 | use phpbb\auth\auth; |
17 | use phpbb\config\config; |
18 | use phpbb\db\driver\driver_interface; |
19 | use phpbb\event\dispatcher_interface; |
20 | use phpbb\exception\http_exception; |
21 | use phpbb\feed\feed_interface; |
22 | use phpbb\feed\exception\feed_unavailable_exception; |
23 | use phpbb\feed\exception\unauthorized_exception; |
24 | use phpbb\feed\helper as feed_helper; |
25 | use phpbb\controller\helper as controller_helper; |
26 | use phpbb\symfony_request; |
27 | use phpbb\user; |
28 | use phpbb\language\language; |
29 | use Symfony\Component\DependencyInjection\ContainerInterface; |
30 | use Symfony\Component\HttpFoundation\Response; |
31 | use Symfony\Component\Routing\Generator\UrlGeneratorInterface; |
32 | use Twig\Environment; |
33 | |
34 | class feed |
35 | { |
36 | /** |
37 | * @var Environment |
38 | */ |
39 | protected $template; |
40 | |
41 | /** |
42 | * @var symfony_request |
43 | */ |
44 | protected $request; |
45 | |
46 | /** |
47 | * @var controller_helper |
48 | */ |
49 | protected $controller_helper; |
50 | |
51 | /** |
52 | * @var config |
53 | */ |
54 | protected $config; |
55 | |
56 | /** |
57 | * @var driver_interface |
58 | */ |
59 | protected $db; |
60 | |
61 | /** |
62 | * @var ContainerInterface |
63 | */ |
64 | protected $container; |
65 | |
66 | /** |
67 | * @var feed_helper |
68 | */ |
69 | protected $feed_helper; |
70 | |
71 | /** |
72 | * @var user |
73 | */ |
74 | protected $user; |
75 | |
76 | /** |
77 | * @var auth |
78 | */ |
79 | protected $auth; |
80 | |
81 | /** |
82 | * @var dispatcher_interface |
83 | */ |
84 | protected $phpbb_dispatcher; |
85 | |
86 | /** |
87 | * @var string |
88 | */ |
89 | protected $php_ext; |
90 | |
91 | /** |
92 | * @var language |
93 | */ |
94 | protected $language; |
95 | |
96 | /** |
97 | * Constructor |
98 | * |
99 | * @param Environment $twig |
100 | * @param symfony_request $request |
101 | * @param controller_helper $controller_helper |
102 | * @param config $config |
103 | * @param driver_interface $db |
104 | * @param ContainerInterface $container |
105 | * @param feed_helper $feed_helper |
106 | * @param user $user |
107 | * @param auth $auth |
108 | * @param dispatcher_interface $phpbb_dispatcher |
109 | * @param language $language |
110 | * @param string $php_ext |
111 | */ |
112 | public function __construct(Environment $twig, symfony_request $request, controller_helper $controller_helper, config $config, driver_interface $db, ContainerInterface $container, feed_helper $feed_helper, user $user, auth $auth, dispatcher_interface $phpbb_dispatcher, language $language, $php_ext) |
113 | { |
114 | $this->request = $request; |
115 | $this->controller_helper = $controller_helper; |
116 | $this->config = $config; |
117 | $this->db = $db; |
118 | $this->container = $container; |
119 | $this->feed_helper = $feed_helper; |
120 | $this->user = $user; |
121 | $this->auth = $auth; |
122 | $this->php_ext = $php_ext; |
123 | $this->template = $twig; |
124 | $this->language = $language; |
125 | $this->phpbb_dispatcher = $phpbb_dispatcher; |
126 | } |
127 | |
128 | /** |
129 | * Controller for /feed/forums route |
130 | * |
131 | * @return Response |
132 | * |
133 | * @throws http_exception when the feed is disabled |
134 | */ |
135 | public function forums() |
136 | { |
137 | if (!$this->config['feed_overall_forums']) |
138 | { |
139 | $this->send_unavailable(); |
140 | } |
141 | |
142 | return $this->send_feed($this->container->get('feed.forums')); |
143 | } |
144 | |
145 | /** |
146 | * Controller for /feed/news route |
147 | * |
148 | * @return Response |
149 | * |
150 | * @throws http_exception when the feed is disabled |
151 | */ |
152 | public function news() |
153 | { |
154 | // Get at least one news forum |
155 | $sql = 'SELECT forum_id |
156 | FROM ' . FORUMS_TABLE . ' |
157 | WHERE ' . $this->db->sql_bit_and('forum_options', FORUM_OPTION_FEED_NEWS, '<> 0'); |
158 | $result = $this->db->sql_query_limit($sql, 1, 0, 600); |
159 | $s_feed_news = (int) $this->db->sql_fetchfield('forum_id'); |
160 | $this->db->sql_freeresult($result); |
161 | |
162 | if (!$s_feed_news) |
163 | { |
164 | $this->send_unavailable(); |
165 | } |
166 | |
167 | return $this->send_feed($this->container->get('feed.news')); |
168 | } |
169 | |
170 | /** |
171 | * Controller for /feed/topics route |
172 | * |
173 | * @return Response |
174 | * |
175 | * @throws http_exception when the feed is disabled |
176 | */ |
177 | public function topics() |
178 | { |
179 | if (!$this->config['feed_topics_new']) |
180 | { |
181 | $this->send_unavailable(); |
182 | } |
183 | |
184 | return $this->send_feed($this->container->get('feed.topics')); |
185 | } |
186 | |
187 | /** |
188 | * Controller for /feed/topics_new route |
189 | * |
190 | * @return Response |
191 | * |
192 | * @throws http_exception when the feed is disabled |
193 | */ |
194 | public function topics_new() |
195 | { |
196 | return $this->topics(); |
197 | } |
198 | |
199 | /** |
200 | * Controller for /feed/topics_active route |
201 | * |
202 | * @return Response |
203 | * |
204 | * @throws http_exception when the feed is disabled |
205 | */ |
206 | public function topics_active() |
207 | { |
208 | if (!$this->config['feed_topics_active']) |
209 | { |
210 | $this->send_unavailable(); |
211 | } |
212 | |
213 | return $this->send_feed($this->container->get('feed.topics_active')); |
214 | } |
215 | |
216 | /** |
217 | * Controller for /feed/forum/{forum_id} route |
218 | * |
219 | * @param int $forum_id |
220 | * |
221 | * @return Response |
222 | * |
223 | * @throws http_exception when the feed is disabled |
224 | */ |
225 | public function forum($forum_id) |
226 | { |
227 | if (!$this->config['feed_forum']) |
228 | { |
229 | $this->send_unavailable(); |
230 | } |
231 | |
232 | return $this->send_feed($this->container->get('feed.forum')->set_forum_id($forum_id)); |
233 | } |
234 | |
235 | /** |
236 | * Controller for /feed/topic/{topic_id} route |
237 | * |
238 | * @param int $topic_id |
239 | * |
240 | * @return Response |
241 | * |
242 | * @throws http_exception when the feed is disabled |
243 | */ |
244 | public function topic($topic_id) |
245 | { |
246 | if (!$this->config['feed_topic']) |
247 | { |
248 | $this->send_unavailable(); |
249 | } |
250 | |
251 | return $this->send_feed($this->container->get('feed.topic')->set_topic_id($topic_id)); |
252 | } |
253 | |
254 | /** |
255 | * Controller for /feed/{mode] route |
256 | * |
257 | * @return Response |
258 | * |
259 | * @throws http_exception when the feed is disabled |
260 | */ |
261 | public function overall() |
262 | { |
263 | if (!$this->config['feed_overall']) |
264 | { |
265 | $this->send_unavailable(); |
266 | } |
267 | |
268 | return $this->send_feed($this->container->get('feed.overall')); |
269 | } |
270 | |
271 | /** |
272 | * Display a given feed |
273 | * |
274 | * @param feed_interface $feed |
275 | * |
276 | * @return Response |
277 | */ |
278 | protected function send_feed(feed_interface $feed) |
279 | { |
280 | try |
281 | { |
282 | return $this->send_feed_do($feed); |
283 | } |
284 | catch (feed_unavailable_exception $e) |
285 | { |
286 | throw new http_exception(Response::HTTP_NOT_FOUND, $e->getMessage(), $e->get_parameters(), $e); |
287 | } |
288 | catch (unauthorized_exception $e) |
289 | { |
290 | throw new http_exception(Response::HTTP_FORBIDDEN, $e->getMessage(), $e->get_parameters(), $e); |
291 | } |
292 | } |
293 | |
294 | /** |
295 | * Really send the feed |
296 | * |
297 | * @param feed_interface $feed |
298 | * |
299 | * @return Response |
300 | * |
301 | * @throws \phpbb\feed\exception\feed_exception |
302 | */ |
303 | protected function send_feed_do(feed_interface $feed) |
304 | { |
305 | $feed_updated_time = 0; |
306 | $item_vars = array(); |
307 | $this->language->add_lang('viewtopic'); |
308 | |
309 | $board_url = $this->feed_helper->get_board_url(); |
310 | |
311 | // Open Feed |
312 | $feed->open(); |
313 | |
314 | // Iterate through items |
315 | while ($row = $feed->get_item()) |
316 | { |
317 | /** |
318 | * Event to modify the feed row |
319 | * |
320 | * @event core.feed_modify_feed_row |
321 | * @var feed_interface feed Feed instance |
322 | * @var array row Array with feed data |
323 | * |
324 | * @since 3.1.10-RC1 |
325 | * @changed 3.3.0 Replace forum_id, mode, topic_id with feed instance |
326 | */ |
327 | $vars = array('feed', 'row'); |
328 | extract($this->phpbb_dispatcher->trigger_event('core.feed_modify_feed_row', compact($vars))); |
329 | |
330 | // BBCode options to correctly disable urls, smilies, bbcode... |
331 | if ($feed->get('options') === null) |
332 | { |
333 | // Allow all combinations |
334 | $options = 7; |
335 | |
336 | if ($feed->get('enable_bbcode') !== null && $feed->get('enable_smilies') !== null && $feed->get('enable_magic_url') !== null) |
337 | { |
338 | $options = (($row[$feed->get('enable_bbcode')]) ? OPTION_FLAG_BBCODE : 0) + (($row[$feed->get('enable_smilies')]) ? OPTION_FLAG_SMILIES : 0) + (($row[$feed->get('enable_magic_url')]) ? OPTION_FLAG_LINKS : 0); |
339 | } |
340 | } |
341 | else |
342 | { |
343 | $options = $row[$feed->get('options')]; |
344 | } |
345 | |
346 | $title = (isset($row[$feed->get('title')]) && $row[$feed->get('title')] !== '') ? $row[$feed->get('title')] : ((isset($row[$feed->get('title2')])) ? $row[$feed->get('title2')] : ''); |
347 | |
348 | $published = ($feed->get('published') !== null) ? (int) $row[$feed->get('published')] : 0; |
349 | $updated = ($feed->get('updated') !== null) ? (int) $row[$feed->get('updated')] : 0; |
350 | |
351 | $display_attachments = ($this->auth->acl_get('u_download') && $this->auth->acl_get('f_download', $row['forum_id']) && isset($row['post_attachment']) && $row['post_attachment']) ? true : false; |
352 | |
353 | $item_row = array( |
354 | 'author' => ($feed->get('creator') !== null) ? $row[$feed->get('creator')] : '', |
355 | 'published' => ($published > 0) ? $this->feed_helper->format_date($published) : '', |
356 | 'updated' => ($updated > 0) ? $this->feed_helper->format_date($updated) : '', |
357 | 'link' => '', |
358 | 'title' => censor_text($title), |
359 | 'category' => ($this->config['feed_item_statistics'] && !empty($row['forum_id'])) ? $board_url . '/viewforum.' . $this->php_ext . '?f=' . $row['forum_id'] : '', |
360 | 'category_name' => ($this->config['feed_item_statistics'] && isset($row['forum_name'])) ? $row['forum_name'] : '', |
361 | 'description' => censor_text($this->feed_helper->generate_content($row[$feed->get('text')], $row[$feed->get('bbcode_uid')], $row[$feed->get('bitfield')], $options, $row['forum_id'], ($display_attachments ? $feed->get_attachments($row['post_id']) : array()))), |
362 | 'statistics' => '', |
363 | ); |
364 | |
365 | // Adjust items, fill link, etc. |
366 | $feed->adjust_item($item_row, $row); |
367 | |
368 | $item_vars[] = $item_row; |
369 | |
370 | $feed_updated_time = max($feed_updated_time, $published, $updated); |
371 | } |
372 | |
373 | // If we do not have any items at all, sending the current time is better than sending no time. |
374 | if (!$feed_updated_time) |
375 | { |
376 | $feed_updated_time = time(); |
377 | } |
378 | |
379 | $feed->close(); |
380 | |
381 | $content = $this->template->render('feed.xml.twig', array( |
382 | // Some default assignments |
383 | // FEED_IMAGE is not used (atom) |
384 | 'FEED_IMAGE' => '', |
385 | 'SELF_LINK' => $this->controller_helper->route($this->request->attributes->get('_route'), $this->request->attributes->get('_route_params'), true, '', UrlGeneratorInterface::ABSOLUTE_URL), |
386 | 'FEED_LINK' => $board_url . '/index.' . $this->php_ext, |
387 | 'FEED_TITLE' => $this->config['sitename'], |
388 | 'FEED_SUBTITLE' => $this->config['site_desc'], |
389 | 'FEED_UPDATED' => $this->feed_helper->format_date($feed_updated_time), |
390 | 'FEED_LANG' => $this->language->lang('USER_LANG'), |
391 | 'FEED_AUTHOR' => $this->config['sitename'], |
392 | |
393 | // Feed entries |
394 | 'FEED_ROWS' => $item_vars, |
395 | )); |
396 | |
397 | $response = new Response($content); |
398 | $response->headers->set('Content-Type', 'application/atom+xml; charset=UTF-8'); |
399 | $response->setLastModified(new \DateTime('@' . $feed_updated_time)); |
400 | |
401 | if (!empty($this->user->data['is_bot'])) |
402 | { |
403 | // Let reverse proxies know we detected a bot. |
404 | $response->headers->set('X-PHPBB-IS-BOT', 'yes'); |
405 | } |
406 | |
407 | return $response; |
408 | } |
409 | |
410 | /** |
411 | * Throw and exception saying that the feed isn't available |
412 | * |
413 | * @throws http_exception |
414 | */ |
415 | protected function send_unavailable() |
416 | { |
417 | throw new http_exception(404, 'FEATURE_NOT_AVAILABLE'); |
418 | } |
419 | } |