1 | <?php |
||||
2 | |||||
3 | /** |
||||
4 | * Functions to help with managing the site news and newsletters |
||||
5 | * |
||||
6 | * @package ElkArte Forum |
||||
7 | * @copyright ElkArte Forum contributors |
||||
8 | * @license BSD http://opensource.org/licenses/BSD-3-Clause (see accompanying LICENSE.txt file) |
||||
9 | * |
||||
10 | * This file contains code covered by: |
||||
11 | * copyright: 2011 Simple Machines (http://www.simplemachines.org) |
||||
12 | * |
||||
13 | * @version 2.0 dev |
||||
14 | * |
||||
15 | */ |
||||
16 | |||||
17 | use BBC\ParserWrapper; |
||||
18 | use ElkArte\Helper\Util; |
||||
19 | |||||
20 | /** |
||||
21 | * Prepares an array of the forum news items |
||||
22 | * |
||||
23 | * @return array |
||||
24 | * @package News |
||||
25 | */ |
||||
26 | function getNews() |
||||
27 | { |
||||
28 | global $modSettings; |
||||
29 | |||||
30 | $admin_current_news = array(); |
||||
31 | |||||
32 | $bbc_parser = ParserWrapper::instance(); |
||||
33 | |||||
34 | // Ready the current news. |
||||
35 | foreach (explode("\n", $modSettings['news']) as $id => $line) |
||||
36 | { |
||||
37 | $admin_current_news[$id] = array( |
||||
38 | 'id' => $id, |
||||
39 | 'unparsed' => un_preparsecode($line), |
||||
40 | 'parsed' => preg_replace('~<([/]?)form[^>]*?[>]*>~i', '<em class="smalltext"><$1form></em>', $bbc_parser->parseNews($line)), |
||||
41 | ); |
||||
42 | } |
||||
43 | |||||
44 | $admin_current_news['last'] = array( |
||||
45 | 'id' => 'last', |
||||
46 | 'unparsed' => '', |
||||
47 | 'parsed' => '<div id="moreNewsItems_preview"></div>', |
||||
48 | ); |
||||
49 | |||||
50 | return $admin_current_news; |
||||
51 | } |
||||
52 | |||||
53 | /** |
||||
54 | * Get a list of all full banned users. |
||||
55 | * |
||||
56 | * - Use their Username and email to find them. |
||||
57 | * - Only get the ones that can't login to turn off notification. |
||||
58 | * |
||||
59 | * @return array |
||||
60 | * @package News |
||||
61 | */ |
||||
62 | function excludeBannedMembers() |
||||
63 | { |
||||
64 | $db = database(); |
||||
65 | |||||
66 | $excludes = array(); |
||||
67 | $db->fetchQuery(' |
||||
68 | SELECT |
||||
69 | DISTINCT mem.id_member |
||||
70 | FROM {db_prefix}ban_groups AS bg |
||||
71 | INNER JOIN {db_prefix}ban_items AS bi ON (bg.id_ban_group = bi.id_ban_group) |
||||
72 | INNER JOIN {db_prefix}members AS mem ON (bi.id_member = mem.id_member) |
||||
73 | WHERE (bg.cannot_access = {int:cannot_access} OR bg.cannot_login = {int:cannot_login}) |
||||
74 | AND (bg.expire_time IS NULL OR bg.expire_time > {int:current_time})', |
||||
75 | array( |
||||
76 | 'cannot_access' => 1, |
||||
77 | 'cannot_login' => 1, |
||||
78 | 'current_time' => time(), |
||||
79 | ) |
||||
80 | )->fetch_callback( |
||||
81 | function ($row) use (&$excludes) { |
||||
82 | $excludes[] = $row['id_member']; |
||||
83 | } |
||||
84 | ); |
||||
85 | |||||
86 | $condition_array = array(); |
||||
87 | $condition_array_params = array(); |
||||
88 | $count = 0; |
||||
89 | $db->fetchQuery(' |
||||
90 | SELECT DISTINCT bi.email_address |
||||
91 | FROM {db_prefix}ban_items AS bi |
||||
92 | INNER JOIN {db_prefix}ban_groups AS bg ON (bg.id_ban_group = bi.id_ban_group) |
||||
93 | WHERE (bg.cannot_access = {int:cannot_access} OR bg.cannot_login = {int:cannot_login}) |
||||
94 | AND (bg.expire_time IS NULL OR bg.expire_time > {int:current_time}) |
||||
95 | AND bi.email_address != {string:blank_string}', |
||||
96 | array( |
||||
97 | 'cannot_access' => 1, |
||||
98 | 'cannot_login' => 1, |
||||
99 | 'current_time' => time(), |
||||
100 | 'blank_string' => '', |
||||
101 | ) |
||||
102 | )->fetch_callback( |
||||
103 | function ($row) use (&$condition_array, &$condition_array_params, &$count) { |
||||
104 | $condition_array[] = '{string:email_' . $count . '}'; |
||||
105 | $condition_array_params['email_' . ($count++)] = $row['email_address']; |
||||
106 | } |
||||
107 | ); |
||||
108 | |||||
109 | if (!empty($condition_array)) |
||||
110 | { |
||||
111 | $db->fetchQuery(' |
||||
112 | SELECT |
||||
113 | id_member |
||||
114 | FROM {db_prefix}members |
||||
115 | WHERE email_address IN(' . implode(', ', $condition_array) . ')', |
||||
116 | $condition_array_params |
||||
117 | )->fetch_callback( |
||||
118 | function ($row) use (&$excludes) { |
||||
119 | $excludes[] = $row['id_member']; |
||||
120 | } |
||||
121 | ); |
||||
122 | } |
||||
123 | |||||
124 | return $excludes; |
||||
125 | } |
||||
126 | |||||
127 | /** |
||||
128 | * Get a list of our local board moderators. |
||||
129 | * |
||||
130 | * @return array |
||||
131 | * @package News |
||||
132 | */ |
||||
133 | function getModerators() |
||||
134 | { |
||||
135 | $db = database(); |
||||
136 | |||||
137 | $mods = array(); |
||||
138 | |||||
139 | $db->fetchQuery(' |
||||
140 | SELECT |
||||
141 | DISTINCT mem.id_member AS identifier |
||||
142 | FROM {db_prefix}members AS mem |
||||
143 | INNER JOIN {db_prefix}moderators AS mods ON (mods.id_member = mem.id_member) |
||||
144 | WHERE mem.is_activated = {int:is_activated}', |
||||
145 | array( |
||||
146 | 'is_activated' => 1, |
||||
147 | ) |
||||
148 | )->fetch_callback( |
||||
149 | function ($row) use (&$mods) { |
||||
150 | $mods[] = $row['identifier']; |
||||
151 | } |
||||
152 | ); |
||||
153 | |||||
154 | return $mods; |
||||
155 | } |
||||
156 | |||||
157 | /** |
||||
158 | * Lists our newsletter recipients, step by step. |
||||
159 | * |
||||
160 | * @param string $sendQuery |
||||
161 | * @param mixed[] $sendParams |
||||
162 | * @param int $start |
||||
163 | * @param int $increment |
||||
164 | * @param int $counter |
||||
165 | * @return array |
||||
166 | * @package News |
||||
167 | */ |
||||
168 | function getNewsletterRecipients($sendQuery, $sendParams, $start, $increment, $counter) |
||||
169 | { |
||||
170 | $db = database(); |
||||
171 | |||||
172 | $recipients = array(); |
||||
173 | |||||
174 | $db->fetchQuery(' |
||||
175 | SELECT |
||||
176 | mem.id_member, mem.email_address, mem.real_name, mem.id_group, mem.additional_groups, mem.id_post_group |
||||
177 | FROM {db_prefix}members AS mem |
||||
178 | WHERE mem.id_member > {int:min_id_member} |
||||
179 | AND mem.id_member < {int:max_id_member} |
||||
180 | AND ' . $sendQuery . ' |
||||
181 | AND mem.is_activated = {int:is_activated} |
||||
182 | ORDER BY mem.id_member ASC |
||||
183 | LIMIT {int:atonce}', |
||||
184 | array_merge($sendParams, array( |
||||
185 | 'min_id_member' => $start, |
||||
186 | 'max_id_member' => $start + $increment - $counter, |
||||
187 | 'atonce' => $increment - $counter, |
||||
188 | 'regular_group' => 0, |
||||
189 | 'notify_announcements' => 1, |
||||
190 | 'is_activated' => 1, |
||||
191 | )) |
||||
192 | )->fetch_callback( |
||||
193 | function ($row) use (&$recipients) { |
||||
194 | $recipients[] = $row; |
||||
195 | } |
||||
196 | ); |
||||
197 | |||||
198 | return $recipients; |
||||
199 | } |
||||
200 | |||||
201 | /** |
||||
202 | * Find the latest posts that: |
||||
203 | * - are the first post in their topic. |
||||
204 | * - are on an any board OR in a specified board. |
||||
205 | * - can be seen by this user. |
||||
206 | * - are actually the latest posts. |
||||
207 | * |
||||
208 | * @param string $query_this_board passed to query, assumed raw and inserted as such |
||||
209 | * @param int $board |
||||
210 | * @param int $limit |
||||
211 | * |
||||
212 | * @return array |
||||
213 | * @package News |
||||
214 | * |
||||
215 | */ |
||||
216 | function getXMLNews($query_this_board, $board, $limit) |
||||
0 ignored issues
–
show
|
|||||
217 | { |
||||
218 | global $modSettings, $board, $context; |
||||
219 | |||||
220 | $db = database(); |
||||
221 | |||||
222 | $done = false; |
||||
223 | $loops = 0; |
||||
224 | while (!$done) |
||||
225 | { |
||||
226 | $optimize_msg = implode(' AND ', $context['optimize_msg']); |
||||
227 | $request = $db->query('', ' |
||||
228 | SELECT |
||||
229 | m.smileys_enabled, m.poster_time, m.id_msg, m.subject, m.body, m.modified_time, |
||||
230 | m.icon, t.id_topic, t.id_board, t.num_replies, |
||||
231 | b.name AS bname, |
||||
232 | COALESCE(mem.id_member, 0) AS id_member, |
||||
233 | COALESCE(mem.email_address, m.poster_email) AS poster_email, |
||||
234 | COALESCE(mem.real_name, m.poster_name) AS poster_name |
||||
235 | FROM {db_prefix}topics AS t |
||||
236 | INNER JOIN {db_prefix}messages AS m ON (m.id_msg = t.id_first_msg) |
||||
237 | INNER JOIN {db_prefix}boards AS b ON (b.id_board = t.id_board) |
||||
238 | LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = m.id_member) |
||||
239 | WHERE ' . $query_this_board . (empty($optimize_msg) ? '' : ' |
||||
240 | AND {raw:optimize_msg}') . (empty($board) ? '' : ' |
||||
241 | AND t.id_board = {int:current_board}') . ($modSettings['postmod_active'] ? ' |
||||
242 | AND t.approved = {int:is_approved}' : '') . ' |
||||
243 | ORDER BY t.id_first_msg DESC |
||||
244 | LIMIT {int:limit}', |
||||
245 | array( |
||||
246 | 'current_board' => $board, |
||||
247 | 'is_approved' => 1, |
||||
248 | 'limit' => $limit, |
||||
249 | 'optimize_msg' => $optimize_msg, |
||||
250 | ) |
||||
251 | ); |
||||
252 | // If we don't have $limit results, we try again with an unoptimized version covering all rows. |
||||
253 | if ($loops < 2 && $request->num_rows() < $limit) |
||||
254 | { |
||||
255 | $request->free_result(); |
||||
256 | |||||
257 | if (empty($_REQUEST['boards']) && empty($board)) |
||||
258 | { |
||||
259 | unset($context['optimize_msg']['lowest']); |
||||
260 | } |
||||
261 | else |
||||
262 | { |
||||
263 | $context['optimize_msg']['lowest'] = 'm.id_msg >= t.id_first_msg'; |
||||
264 | } |
||||
265 | |||||
266 | $context['optimize_msg']['highest'] = 'm.id_msg <= t.id_last_msg'; |
||||
267 | $loops++; |
||||
268 | } |
||||
269 | else |
||||
270 | { |
||||
271 | $done = true; |
||||
272 | } |
||||
273 | } |
||||
274 | $data = array(); |
||||
275 | while (($row = $request->fetch_assoc())) |
||||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||||
276 | { |
||||
277 | $data[] = $row; |
||||
278 | } |
||||
279 | |||||
280 | $request->free_result(); |
||||
281 | |||||
282 | return $data; |
||||
283 | } |
||||
284 | |||||
285 | /** |
||||
286 | * Get the recent topics to display. |
||||
287 | * |
||||
288 | * @param string $query_this_board passed to query, assumed raw and inserted as such |
||||
289 | * @param int $board |
||||
290 | * @param int $limit |
||||
291 | * |
||||
292 | * @return array |
||||
293 | * @package News |
||||
294 | * |
||||
295 | */ |
||||
296 | function getXMLRecent($query_this_board, $board, $limit) |
||||
0 ignored issues
–
show
The parameter
$board is not used and could be removed.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check looks for parameters that have been defined for a function or method, but which are not used in the method body. ![]() |
|||||
297 | { |
||||
298 | global $modSettings, $board, $context; |
||||
299 | |||||
300 | $db = database(); |
||||
301 | |||||
302 | $done = false; |
||||
303 | $loops = 0; |
||||
304 | while (!$done) |
||||
305 | { |
||||
306 | $optimize_msg = implode(' AND ', $context['optimize_msg']); |
||||
307 | $request = $db->query('', ' |
||||
308 | SELECT |
||||
309 | m.id_msg |
||||
310 | FROM {db_prefix}messages AS m |
||||
311 | INNER JOIN {db_prefix}boards AS b ON (b.id_board = m.id_board) |
||||
312 | INNER JOIN {db_prefix}topics AS t ON (t.id_topic = m.id_topic) |
||||
313 | WHERE ' . $query_this_board . (empty($optimize_msg) ? '' : ' |
||||
314 | AND {raw:optimize_msg}') . (empty($board) ? '' : ' |
||||
315 | AND m.id_board = {int:current_board}') . ($modSettings['postmod_active'] ? ' |
||||
316 | AND m.approved = {int:is_approved}' : '') . ' |
||||
317 | ORDER BY m.id_msg DESC |
||||
318 | LIMIT {int:limit}', |
||||
319 | array( |
||||
320 | 'limit' => $limit, |
||||
321 | 'current_board' => $board, |
||||
322 | 'is_approved' => 1, |
||||
323 | 'optimize_msg' => $optimize_msg, |
||||
324 | ) |
||||
325 | ); |
||||
326 | // If we don't have $limit results, try again with an unoptimized version covering all rows. |
||||
327 | if ($loops < 2 && $request->num_rows() < $limit) |
||||
328 | { |
||||
329 | $request->free_result(); |
||||
330 | |||||
331 | if (empty($_REQUEST['boards']) && empty($board)) |
||||
332 | { |
||||
333 | unset($context['optimize_msg']['lowest']); |
||||
334 | } |
||||
335 | else |
||||
336 | { |
||||
337 | $context['optimize_msg']['lowest'] = $loops !== 0 ? 'm.id_msg >= t.id_first_msg' : 'm.id_msg >= (t.id_last_msg - t.id_first_msg) / 2'; |
||||
338 | } |
||||
339 | |||||
340 | $loops++; |
||||
341 | } |
||||
342 | else |
||||
343 | { |
||||
344 | $done = true; |
||||
345 | } |
||||
346 | } |
||||
347 | $messages = array(); |
||||
348 | while (($row = $request->fetch_assoc())) |
||||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||||
349 | { |
||||
350 | $messages[] = $row['id_msg']; |
||||
351 | } |
||||
352 | $request->free_result(); |
||||
353 | |||||
354 | // No messages found, then return nothing |
||||
355 | if (empty($messages)) |
||||
356 | { |
||||
357 | return array(); |
||||
358 | } |
||||
359 | |||||
360 | // Find the most recent posts from our message list that this user can see. |
||||
361 | $data = array(); |
||||
362 | $db->fetchQuery(' |
||||
363 | SELECT |
||||
364 | m.smileys_enabled, m.poster_time, m.id_msg, m.subject, m.body, m.id_topic, t.id_board, |
||||
365 | b.name AS bname, t.num_replies, m.id_member, m.icon, mf.id_member AS id_first_member, |
||||
366 | COALESCE(mem.real_name, m.poster_name) AS poster_name, mf.subject AS first_subject, |
||||
367 | COALESCE(memf.real_name, mf.poster_name) AS first_poster_name, |
||||
368 | COALESCE(mem.email_address, m.poster_email) AS poster_email, m.modified_time |
||||
369 | FROM {db_prefix}messages AS m |
||||
370 | INNER JOIN {db_prefix}topics AS t ON (t.id_topic = m.id_topic) |
||||
371 | INNER JOIN {db_prefix}messages AS mf ON (mf.id_msg = t.id_first_msg) |
||||
372 | INNER JOIN {db_prefix}boards AS b ON (b.id_board = t.id_board) |
||||
373 | LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = m.id_member) |
||||
374 | LEFT JOIN {db_prefix}members AS memf ON (memf.id_member = mf.id_member) |
||||
375 | WHERE m.id_msg IN ({array_int:message_list}) |
||||
376 | ' . (empty($board) ? '' : 'AND t.id_board = {int:current_board}') . ' |
||||
377 | ORDER BY m.id_msg DESC |
||||
378 | LIMIT {int:limit}', |
||||
379 | array( |
||||
380 | 'limit' => $limit, |
||||
381 | 'current_board' => $board, |
||||
382 | 'message_list' => $messages, |
||||
383 | ) |
||||
384 | )->fetch_callback( |
||||
385 | function ($row) use (&$data) { |
||||
386 | $data[] = $row; |
||||
387 | } |
||||
388 | ); |
||||
389 | |||||
390 | return $data; |
||||
391 | } |
||||
392 | |||||
393 | /** |
||||
394 | * Called to convert data to xml |
||||
395 | * Finds urls for local site and sanitizes them |
||||
396 | * |
||||
397 | * @param string $val |
||||
398 | * |
||||
399 | * @return string |
||||
400 | */ |
||||
401 | function fix_possible_url($val) |
||||
402 | { |
||||
403 | global $scripturl; |
||||
404 | |||||
405 | if (substr($val, 0, strlen($scripturl)) !== $scripturl) |
||||
406 | { |
||||
407 | return $val; |
||||
408 | } |
||||
409 | |||||
410 | call_integration_hook('integrate_fix_url', array(&$val)); |
||||
411 | |||||
412 | return $val; |
||||
413 | } |
||||
414 | |||||
415 | /** |
||||
416 | * For highest feed compatibility, some special characters should be provided |
||||
417 | * as character entities and not html entities |
||||
418 | * |
||||
419 | * @param string $data |
||||
420 | * |
||||
421 | * @return string |
||||
422 | */ |
||||
423 | function encode_special($data) |
||||
424 | { |
||||
425 | return strtr($data, array('>' => '>', '&' => '&', '<' => '<')); |
||||
426 | } |
||||
427 | |||||
428 | /** |
||||
429 | * Ensures supplied data is properly encapsulated in cdata xml tags |
||||
430 | * Called from action_xmlprofile in News.controller.php |
||||
431 | * |
||||
432 | * @param string $data |
||||
433 | * @param string $ns |
||||
434 | * @param string $override |
||||
435 | * |
||||
436 | * @return string |
||||
437 | */ |
||||
438 | function cdata_parse($data, $ns = '', $override = null) |
||||
439 | { |
||||
440 | static $cdata_override = false; |
||||
441 | |||||
442 | if ($override !== null) |
||||
443 | { |
||||
444 | $cdata_override = (bool) $override; |
||||
445 | } |
||||
446 | |||||
447 | // Are we not doing it? |
||||
448 | if (!empty($cdata_override)) |
||||
449 | { |
||||
450 | return $data; |
||||
451 | } |
||||
452 | |||||
453 | $cdata = '<![CDATA['; |
||||
454 | |||||
455 | for ($pos = 0, $n = Util::strlen($data); $pos < $n; null) |
||||
456 | { |
||||
457 | $positions = array( |
||||
458 | Util::strpos($data, '&', $pos), |
||||
459 | Util::strpos($data, ']]>', $pos), |
||||
460 | ); |
||||
461 | |||||
462 | if ($ns !== '') |
||||
463 | { |
||||
464 | $positions[] = Util::strpos($data, '<', $pos); |
||||
465 | } |
||||
466 | |||||
467 | foreach ($positions as $k => $dummy) |
||||
468 | { |
||||
469 | if ($dummy === false) |
||||
470 | { |
||||
471 | unset($positions[$k]); |
||||
472 | } |
||||
473 | } |
||||
474 | |||||
475 | $old = $pos; |
||||
476 | $pos = empty($positions) ? $n : min($positions); |
||||
477 | |||||
478 | if ($pos - $old > 0) |
||||
479 | { |
||||
480 | $cdata .= Util::substr($data, $old, $pos - $old); |
||||
481 | } |
||||
482 | |||||
483 | if ($pos >= $n) |
||||
484 | { |
||||
485 | break; |
||||
486 | } |
||||
487 | |||||
488 | if (Util::substr($data, $pos, 1) === '<') |
||||
489 | { |
||||
490 | $pos2 = Util::strpos($data, '>', $pos); |
||||
491 | if ($pos2 === false) |
||||
492 | { |
||||
493 | $pos2 = $n; |
||||
494 | } |
||||
495 | |||||
496 | if (Util::substr($data, $pos + 1, 1) === '/') |
||||
497 | { |
||||
498 | $cdata .= ']]></' . $ns . ':' . Util::substr($data, $pos + 2, $pos2 - $pos - 1) . '<![CDATA['; |
||||
499 | } |
||||
500 | else |
||||
501 | { |
||||
502 | $cdata .= ']]><' . $ns . ':' . Util::substr($data, $pos + 1, $pos2 - $pos) . '<![CDATA['; |
||||
503 | } |
||||
504 | |||||
505 | $pos = $pos2 + 1; |
||||
506 | } |
||||
507 | elseif (Util::substr($data, $pos, 3) == ']]>') |
||||
508 | { |
||||
509 | $cdata .= ']]]]><![CDATA[>'; |
||||
510 | $pos = $pos + 3; |
||||
511 | } |
||||
512 | elseif (Util::substr($data, $pos, 1) === '&') |
||||
513 | { |
||||
514 | $pos2 = Util::strpos($data, ';', $pos); |
||||
515 | |||||
516 | if ($pos2 === false) |
||||
517 | { |
||||
518 | $pos2 = $n; |
||||
519 | } |
||||
520 | |||||
521 | $ent = Util::substr($data, $pos + 1, $pos2 - $pos - 1); |
||||
522 | |||||
523 | if (Util::substr($data, $pos + 1, 1) === '#') |
||||
524 | { |
||||
525 | $cdata .= ']]>' . Util::substr($data, $pos, $pos2 - $pos + 1) . '<![CDATA['; |
||||
526 | } |
||||
527 | elseif (in_array($ent, array('amp', 'lt', 'gt', 'quot'))) |
||||
528 | { |
||||
529 | $cdata .= ']]>' . Util::substr($data, $pos, $pos2 - $pos + 1) . '<![CDATA['; |
||||
530 | } |
||||
531 | |||||
532 | $pos = $pos2 + 1; |
||||
533 | } |
||||
534 | } |
||||
535 | |||||
536 | $cdata .= ']]>'; |
||||
537 | |||||
538 | return strtr($cdata, array('<![CDATA[]]>' => '')); |
||||
539 | } |
||||
540 |
This check looks for parameters that have been defined for a function or method, but which are not used in the method body.