1 | <?php |
||
2 | |||
3 | /** |
||
4 | * Find and retrieve information about recently posted topics, messages, and the like. |
||
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 | namespace ElkArte; |
||
18 | |||
19 | use ElkArte\Database\QueryInterface; |
||
20 | |||
21 | /** |
||
22 | * Unread posts and replies Controller |
||
23 | */ |
||
24 | class Unread |
||
25 | { |
||
26 | /** @var int */ |
||
27 | public const UNREAD = 0; |
||
28 | |||
29 | /** @var int */ |
||
30 | public const UNREADREPLIES = 1; |
||
31 | |||
32 | /** @var bool */ |
||
33 | private $_ascending = false; |
||
34 | |||
35 | /** @var string */ |
||
36 | private $_sort_query = ''; |
||
37 | |||
38 | /** @var int */ |
||
39 | private $_num_topics = 0; |
||
40 | |||
41 | /** @var int */ |
||
42 | private $_min_message = 0; |
||
43 | |||
44 | /** @var int */ |
||
45 | private $_action = self::UNREAD; |
||
46 | |||
47 | /** @var int */ |
||
48 | private $_earliest_msg = 0; |
||
49 | |||
50 | /** @var bool */ |
||
51 | private $_showing_all_topics; |
||
52 | |||
53 | /** @var int */ |
||
54 | private $_user_id = 0; |
||
55 | |||
56 | /** @var bool */ |
||
57 | private $_post_mod; |
||
58 | |||
59 | /** @var bool */ |
||
60 | private $_unwatch; |
||
61 | |||
62 | /** @var QueryInterface */ |
||
63 | private $_db; |
||
64 | |||
65 | /** @var int|string */ |
||
66 | private $_preview_bodies = 0; |
||
67 | |||
68 | /** |
||
69 | * Parameters for the main query. |
||
70 | */ |
||
71 | private $_query_parameters = []; |
||
72 | |||
73 | /** |
||
74 | * Constructor |
||
75 | * |
||
76 | * @param int $user - ID of the user |
||
77 | * @param bool|int $post_mod - if post moderation is active or not |
||
78 | * @param bool|int $unwatch - if unwatch topics is active or not |
||
79 | * @param bool|int $showing_all_topics - Is the user looking at all the unread replies, or the recent topics? |
||
80 | */ |
||
81 | public function __construct($user, $post_mod, $unwatch, $showing_all_topics = false) |
||
82 | { |
||
83 | $this->_user_id = (int) $user; |
||
84 | $this->_post_mod = (bool) $post_mod; |
||
85 | $this->_unwatch = (bool) $unwatch; |
||
86 | $this->_showing_all_topics = (bool) $showing_all_topics; |
||
87 | |||
88 | $this->_db = database(); |
||
89 | } |
||
90 | |||
91 | /** |
||
92 | * Sets the boards the member is looking at |
||
93 | * |
||
94 | * @param int|int[] $boards - the id of the boards |
||
95 | */ |
||
96 | public function setBoards($boards) |
||
97 | { |
||
98 | $this->_query_parameters['boards'] = is_array($boards) ? $boards : [$boards]; |
||
99 | } |
||
100 | |||
101 | /** |
||
102 | * The action the user is performing |
||
103 | * |
||
104 | * @param int $action - Unread::UNREAD, Unread::UNREADREPLIES |
||
105 | */ |
||
106 | public function setAction($action) |
||
107 | { |
||
108 | if (in_array($action, [self::UNREAD, self::UNREADREPLIES])) |
||
109 | { |
||
110 | $this->_action = $action; |
||
111 | } |
||
112 | } |
||
113 | |||
114 | /** |
||
115 | * Sets the lower message id to be taken in consideration |
||
116 | * |
||
117 | * @param int $msg_id - id of the earliest message to consider |
||
118 | */ |
||
119 | public function setEarliestMsg($msg_id) |
||
120 | { |
||
121 | $this->_earliest_msg = (int) $msg_id; |
||
122 | } |
||
123 | |||
124 | /** |
||
125 | * Sets the sorting query and the direction |
||
126 | * |
||
127 | * @param string $query - The query to be used in the ORDER clause |
||
128 | * @param bool|int $asc - If the sorting is ascending or not |
||
129 | */ |
||
130 | public function setSorting($query, $asc) |
||
131 | { |
||
132 | $this->_sort_query = $query; |
||
133 | $this->_ascending = $asc; |
||
0 ignored issues
–
show
|
|||
134 | } |
||
135 | |||
136 | /** |
||
137 | * Return the sorting direction |
||
138 | * |
||
139 | * @return bool |
||
140 | */ |
||
141 | public function isSortAsc() |
||
142 | { |
||
143 | return $this->_ascending; |
||
144 | } |
||
145 | |||
146 | /** |
||
147 | * Sets if the data returned by the class will include a shorted version |
||
148 | * of the body of the last message. |
||
149 | * |
||
150 | * @param bool|int $chars - The number of chars to retrieve. |
||
151 | * If true it will return the entire body, |
||
152 | * if 0 no preview will be generated. |
||
153 | */ |
||
154 | public function bodyPreview($chars) |
||
155 | { |
||
156 | $this->_preview_bodies = $chars === true ? 'all' : (int) $chars; |
||
157 | } |
||
158 | |||
159 | /** |
||
160 | * Counts the number of unread topics or messages |
||
161 | * |
||
162 | * @param bool $first_login - If this is the first login of the user |
||
163 | * @param int $id_msg_last_visit - highest id_msg found during the last visit |
||
164 | * |
||
165 | * @return int |
||
166 | */ |
||
167 | public function numUnreads($first_login = false, $id_msg_last_visit = 0) |
||
168 | { |
||
169 | if ($this->_action === self::UNREAD) |
||
170 | { |
||
171 | $this->_countRecentTopics($first_login, $id_msg_last_visit); |
||
172 | } |
||
173 | else |
||
174 | { |
||
175 | $this->_countUnreadReplies(); |
||
176 | } |
||
177 | |||
178 | return $this->_num_topics; |
||
179 | } |
||
180 | |||
181 | /** |
||
182 | * Counts unread topics, used in *all* unread replies and |
||
183 | * new posts since last visit |
||
184 | * |
||
185 | * @param bool $is_first_login - if the member has already logged in at least |
||
186 | * once, then there is an $id_msg_last_visit |
||
187 | * @param int $id_msg_last_visit - highest id_msg found during the last visit |
||
188 | */ |
||
189 | private function _countRecentTopics($is_first_login, $id_msg_last_visit = 0) |
||
190 | { |
||
191 | $request = $this->_db->fetchQuery(' |
||
192 | SELECT |
||
193 | COUNT(*), MIN(t.id_last_msg) |
||
194 | FROM {db_prefix}topics AS t |
||
195 | LEFT JOIN {db_prefix}log_topics AS lt ON (lt.id_topic = t.id_topic AND lt.id_member = {int:current_member}) |
||
196 | LEFT JOIN {db_prefix}log_mark_read AS lmr ON (lmr.id_board = t.id_board AND lmr.id_member = {int:current_member}) |
||
197 | WHERE t.id_board IN ({array_int:boards})' . ($this->_showing_all_topics && !empty($this->_earliest_msg) ? ' |
||
198 | AND t.id_last_msg > {int:earliest_msg}' : (!$this->_showing_all_topics && $is_first_login ? ' |
||
199 | AND t.id_last_msg > {int:id_msg_last_visit}' : '')) . ' |
||
200 | AND COALESCE(lt.id_msg, lmr.id_msg, 0) < t.id_last_msg' . |
||
201 | ($this->_post_mod ? ' AND t.approved = {int:is_approved}' : '') . |
||
202 | ($this->_unwatch ? ' AND COALESCE(lt.unwatched, 0) != 1' : ''), |
||
203 | array_merge($this->_query_parameters, [ |
||
204 | 'current_member' => $this->_user_id, |
||
205 | 'earliest_msg' => $this->_earliest_msg, |
||
206 | 'id_msg_last_visit' => $id_msg_last_visit, |
||
207 | 'is_approved' => 1, |
||
208 | ]) |
||
209 | ); |
||
210 | [$this->_num_topics, $this->_min_message] = $request->fetch_row(); |
||
211 | $request->free_result(); |
||
212 | } |
||
213 | |||
214 | /** |
||
215 | * Counts unread replies |
||
216 | */ |
||
217 | private function _countUnreadReplies() |
||
218 | { |
||
219 | $request = $this->_db->fetchQuery(' |
||
220 | SELECT |
||
221 | COUNT(DISTINCT t.id_topic), MIN(t.id_last_msg) |
||
222 | FROM {db_prefix}topics AS t |
||
223 | INNER JOIN {db_prefix}messages AS m ON (m.id_topic = t.id_topic) |
||
224 | LEFT JOIN {db_prefix}log_topics AS lt ON (lt.id_topic = t.id_topic AND lt.id_member = {int:current_member}) |
||
225 | LEFT JOIN {db_prefix}log_mark_read AS lmr ON (lmr.id_board = t.id_board AND lmr.id_member = {int:current_member}) |
||
226 | WHERE t.id_board IN ({array_int:boards}) |
||
227 | AND m.id_member = {int:current_member} |
||
228 | AND COALESCE(lt.id_msg, lmr.id_msg, 0) < t.id_last_msg' . ($this->_post_mod ? ' |
||
229 | AND t.approved = {int:is_approved}' : '') . ($this->_unwatch ? ' |
||
230 | AND COALESCE(lt.unwatched, 0) != 1' : ''), |
||
231 | array_merge($this->_query_parameters, [ |
||
232 | 'current_member' => $this->_user_id, |
||
233 | 'is_approved' => 1, |
||
234 | ]) |
||
235 | ); |
||
236 | [$this->_num_topics, $this->_min_message] = $request->fetch_row(); |
||
237 | $request->free_result(); |
||
238 | } |
||
239 | |||
240 | /** |
||
241 | * Retrieves unread topics or messages |
||
242 | * |
||
243 | * @param string $join - kind of "JOIN" to execute. If 'topic' JOINs boards on |
||
244 | * the topics table, otherwise ('message') the JOIN is on the messages table |
||
245 | * @param int $start - position to start the query |
||
246 | * @param int $limit - number of entries to grab |
||
247 | * @param bool $include_avatars - if avatars should be retrieved as well |
||
248 | * @return array - see \ElkArte\TopicUtil::prepareContext |
||
249 | */ |
||
250 | public function getUnreads($join, $start, $limit, $include_avatars) |
||
251 | { |
||
252 | if ($this->_action === self::UNREAD) |
||
253 | { |
||
254 | return $this->_getUnreadTopics($join, $start, $limit, $include_avatars); |
||
255 | } |
||
256 | |||
257 | return $this->_getUnreadReplies($start, $limit, $include_avatars); |
||
258 | } |
||
259 | |||
260 | /** |
||
261 | * Retrieves unread topics, used in *all* unread replies and |
||
262 | * new posts since last visit |
||
263 | * |
||
264 | * @param string $join - kind of "JOIN" to execute. If 'topic' JOINs boards on |
||
265 | * the topics table, otherwise ('message') the JOIN is on |
||
266 | * the messages table |
||
267 | * @param int $start - position to start the query |
||
268 | * @param int $limit - number of entries to grab |
||
269 | * @param bool|int $include_avatars - if avatars should be retrieved as well |
||
270 | * @return array - see \ElkArte\TopicUtil::prepareContext |
||
271 | */ |
||
272 | private function _getUnreadTopics($join, $start, $limit, $include_avatars = false) |
||
273 | { |
||
274 | $body_query = $this->_setBodyQuery(); |
||
275 | |||
276 | if (!empty($include_avatars)) |
||
277 | { |
||
278 | if ($include_avatars === 1 || $include_avatars === 3) |
||
279 | { |
||
280 | $custom_selects = ['meml.avatar', 'COALESCE(a.id_attach, 0) AS id_attach', 'a.filename', 'a.attachment_type', 'meml.email_address']; |
||
281 | $custom_joins = ['LEFT JOIN {db_prefix}attachments AS a ON (a.id_member = ml.id_member AND a.id_member != 0)']; |
||
282 | } |
||
283 | else |
||
284 | { |
||
285 | $custom_selects = []; |
||
286 | $custom_joins = []; |
||
287 | } |
||
288 | |||
289 | if ($include_avatars === 2 || $include_avatars === 3) |
||
290 | { |
||
291 | $custom_selects = array_merge($custom_selects, ['memf.avatar AS avatar_first', 'COALESCE(af.id_attach, 0) AS id_attach_first', 'af.filename AS filename_first', 'af.attachment_type AS attachment_type_first', 'memf.email_address AS email_address_first']); |
||
292 | $custom_joins = array_merge($custom_joins, ['LEFT JOIN {db_prefix}attachments AS af ON (af.id_member = mf.id_member AND af.id_member != 0)']); |
||
293 | } |
||
294 | } |
||
295 | |||
296 | $request = $this->_db->fetchQuery(' |
||
297 | SELECT |
||
298 | ms.subject AS first_subject, ms.poster_time AS first_poster_time, ms.poster_name AS first_member_name, |
||
299 | ms.id_topic, t.id_board, b.name AS bname, t.num_replies, t.num_views, t.num_likes, t.approved, |
||
300 | ms.id_member AS first_id_member, ml.id_member AS last_id_member, ml.poster_name AS last_member_name, |
||
301 | ml.poster_time AS last_poster_time, COALESCE(mems.real_name, ms.poster_name) AS first_display_name, |
||
302 | COALESCE(meml.real_name, ml.poster_name) AS last_display_name, ml.subject AS last_subject, |
||
303 | ml.icon AS last_icon, ms.icon AS first_icon, t.id_poll, t.is_sticky, t.locked, ml.modified_time AS last_modified_time, |
||
304 | COALESCE(lt.id_msg, lmr.id_msg, -1) + 1 AS new_from, |
||
305 | ' . $body_query . ' |
||
306 | ' . (empty($custom_selects) ? '' : implode(',', $custom_selects) . ', ') . ' |
||
307 | ml.smileys_enabled AS last_smileys, ms.smileys_enabled AS first_smileys, t.id_first_msg, t.id_last_msg |
||
308 | FROM {db_prefix}messages AS ms |
||
309 | INNER JOIN {db_prefix}topics AS t ON (t.id_topic = ms.id_topic AND t.id_first_msg = ms.id_msg) |
||
310 | INNER JOIN {db_prefix}messages AS ml ON (ml.id_msg = t.id_last_msg)' . ($join === 'topics' ? ' |
||
311 | LEFT JOIN {db_prefix}boards AS b ON (b.id_board = t.id_board)' : ' |
||
312 | LEFT JOIN {db_prefix}boards AS b ON (b.id_board = ms.id_board)') . ' |
||
313 | LEFT JOIN {db_prefix}members AS mems ON (mems.id_member = ms.id_member) |
||
314 | LEFT JOIN {db_prefix}members AS meml ON (meml.id_member = ml.id_member) |
||
315 | LEFT JOIN {db_prefix}log_topics AS lt ON (lt.id_topic = t.id_topic AND lt.id_member = {int:current_member})' . (empty($custom_joins) ? '' : implode("\n\t\t\t\t", $custom_joins)) . ' |
||
316 | LEFT JOIN {db_prefix}log_mark_read AS lmr ON (lmr.id_board = t.id_board AND lmr.id_member = {int:current_member}) |
||
317 | WHERE t.id_board IN ({array_int:boards}) |
||
318 | AND t.id_last_msg >= {int:min_message} |
||
319 | AND COALESCE(lt.id_msg, lmr.id_msg, 0) < ml.id_msg' . |
||
320 | ($this->_post_mod ? ' AND ms.approved = {int:is_approved}' : '') . |
||
321 | ($this->_unwatch ? ' AND COALESCE(lt.unwatched, 0) != 1' : '') . ' |
||
322 | ORDER BY {raw:order} |
||
323 | LIMIT {int:limit} OFFSET {int:offset}', |
||
324 | array_merge($this->_query_parameters, [ |
||
325 | 'current_member' => $this->_user_id, |
||
326 | 'min_message' => $this->_min_message, |
||
327 | 'is_approved' => 1, |
||
328 | 'order' => $this->_sort_query . ($this->_ascending ? '' : ' DESC'), |
||
329 | 'offset' => $start, |
||
330 | 'limit' => $limit, |
||
331 | ]) |
||
332 | ); |
||
333 | $topics = $request->fetch_all(); |
||
334 | $request->free_result(); |
||
335 | |||
336 | return TopicUtil::prepareContext($topics, true, ((int) $this->_preview_bodies) + 128); |
||
337 | } |
||
338 | |||
339 | /** |
||
340 | * Retrieves unread replies since last visit |
||
341 | * |
||
342 | * @param int $start - position to start the query |
||
343 | * @param int $limit - number of entries to grab |
||
344 | * @param bool|int $include_avatars - if avatars should be retrieved as well |
||
345 | * @return array|bool - see \ElkArte\TopicUtil::prepareContext |
||
346 | */ |
||
347 | private function _getUnreadReplies($start, $limit, $include_avatars = false) |
||
348 | { |
||
349 | $request = $this->_db->fetchQuery(' |
||
350 | SELECT |
||
351 | t.id_topic, ' . $this->_sort_query . ' |
||
352 | FROM {db_prefix}topics AS t |
||
353 | INNER JOIN {db_prefix}messages AS m ON (m.id_topic = t.id_topic AND m.id_member = {int:current_member})' . (strpos($this->_sort_query, 'ms.') === false ? '' : ' |
||
354 | INNER JOIN {db_prefix}messages AS ms ON (ms.id_msg = t.id_first_msg)') . (strpos($this->_sort_query, 'mems.') === false ? '' : ' |
||
355 | LEFT JOIN {db_prefix}members AS mems ON (mems.id_member = ms.id_member)') . ' |
||
356 | LEFT JOIN {db_prefix}log_topics AS lt ON (lt.id_topic = t.id_topic AND lt.id_member = {int:current_member}) |
||
357 | LEFT JOIN {db_prefix}log_mark_read AS lmr ON (lmr.id_board = t.id_board AND lmr.id_member = {int:current_member}) |
||
358 | WHERE t.id_board IN ({array_int:boards}) |
||
359 | AND t.id_last_msg >= {int:min_message} |
||
360 | AND COALESCE(lt.id_msg, lmr.id_msg, 0) < t.id_last_msg' . |
||
361 | ($this->_post_mod ? ' AND t.approved = {int:is_approved}' : '') . |
||
362 | ($this->_unwatch ? ' AND COALESCE(lt.unwatched, 0) != 1' : '') . ' |
||
363 | ORDER BY {raw:order} |
||
364 | LIMIT {int:limit} OFFSET {int:offset}', |
||
365 | array_merge($this->_query_parameters, [ |
||
366 | 'current_member' => $this->_user_id, |
||
367 | 'min_message' => $this->_min_message, |
||
368 | 'is_approved' => 1, |
||
369 | 'order' => $this->_sort_query . ($this->_ascending ? '' : ' DESC'), |
||
370 | 'offset' => $start, |
||
371 | 'limit' => $limit, |
||
372 | ]) |
||
373 | ); |
||
374 | $topics = []; |
||
375 | while (($row = $request->fetch_assoc())) |
||
376 | { |
||
377 | $topics[] = $row['id_topic']; |
||
378 | } |
||
379 | |||
380 | $request->free_result(); |
||
381 | |||
382 | // Sanity... where have you gone? |
||
383 | if (empty($topics)) |
||
384 | { |
||
385 | return false; |
||
386 | } |
||
387 | |||
388 | $body_query = $this->_setBodyQuery(); |
||
389 | |||
390 | if (!empty($include_avatars)) |
||
391 | { |
||
392 | if ($include_avatars === 1 || $include_avatars === 3) |
||
393 | { |
||
394 | $custom_selects = ['meml.avatar', 'COALESCE(a.id_attach, 0) AS id_attach', 'a.filename', 'a.attachment_type', 'meml.email_address']; |
||
395 | $custom_joins = ['LEFT JOIN {db_prefix}attachments AS a ON (a.id_member = ml.id_member AND a.id_member != 0)']; |
||
396 | } |
||
397 | else |
||
398 | { |
||
399 | $custom_selects = []; |
||
400 | $custom_joins = []; |
||
401 | } |
||
402 | |||
403 | if ($include_avatars === 2 || $include_avatars === 3) |
||
404 | { |
||
405 | $custom_selects = array_merge($custom_selects, ['memf.avatar AS avatar_first', 'COALESCE(af.id_attach, 0) AS id_attach_first', 'af.filename AS filename_first', 'af.attachment_type AS attachment_type_first', 'memf.email_address AS email_address_first']); |
||
406 | $custom_joins = array_merge($custom_joins, ['LEFT JOIN {db_prefix}attachments AS af ON (af.id_member = ms.id_member AND af.id_member != 0)']); |
||
407 | } |
||
408 | } |
||
409 | |||
410 | $request = $this->_db->fetchQuery(' |
||
411 | SELECT |
||
412 | ms.subject AS first_subject, ms.poster_time AS first_poster_time, ms.id_topic, t.id_board, b.name AS bname, |
||
413 | ms.poster_name AS first_member_name, ml.poster_name AS last_member_name, t.approved, |
||
414 | t.num_replies, t.num_views, t.num_likes, ms.id_member AS first_id_member, ml.id_member AS last_id_member, |
||
415 | ml.poster_time AS last_poster_time, COALESCE(mems.real_name, ms.poster_name) AS first_display_name, |
||
416 | COALESCE(meml.real_name, ml.poster_name) AS last_display_name, ml.subject AS last_subject, |
||
417 | ml.icon AS last_icon, ms.icon AS first_icon, t.id_poll, t.is_sticky, t.locked, ml.modified_time AS last_modified_time, |
||
418 | COALESCE(lt.id_msg, lmr.id_msg, -1) + 1 AS new_from, |
||
419 | ' . $body_query . ' |
||
420 | ' . (empty($custom_selects) ? '' : implode(',', $custom_selects) . ', ') . ' |
||
421 | ml.smileys_enabled AS last_smileys, ms.smileys_enabled AS first_smileys, t.id_first_msg, t.id_last_msg |
||
422 | FROM {db_prefix}topics AS t |
||
423 | INNER JOIN {db_prefix}messages AS ms ON (ms.id_topic = t.id_topic AND ms.id_msg = t.id_first_msg) |
||
424 | INNER JOIN {db_prefix}messages AS ml ON (ml.id_msg = t.id_last_msg) |
||
425 | INNER JOIN {db_prefix}boards AS b ON (b.id_board = t.id_board) |
||
426 | LEFT JOIN {db_prefix}members AS mems ON (mems.id_member = ms.id_member) |
||
427 | LEFT JOIN {db_prefix}members AS meml ON (meml.id_member = ml.id_member) |
||
428 | LEFT JOIN {db_prefix}log_topics AS lt ON (lt.id_topic = t.id_topic AND lt.id_member = {int:current_member}) |
||
429 | LEFT JOIN {db_prefix}log_mark_read AS lmr ON (lmr.id_board = t.id_board AND lmr.id_member = {int:current_member})' . (empty($custom_joins) ? '' : implode("\n\t\t\t\t", $custom_joins)) . ' |
||
430 | WHERE t.id_topic IN ({array_int:topic_list}) |
||
431 | ORDER BY {raw:order} |
||
432 | LIMIT {int:limit}', |
||
433 | [ |
||
434 | 'current_member' => $this->_user_id, |
||
435 | 'order' => $this->_sort_query . ($this->_ascending ? '' : ' DESC'), |
||
436 | 'topic_list' => $topics, |
||
437 | 'limit' => count($topics), |
||
438 | ] |
||
439 | ); |
||
440 | $return = $request->fetch_all(); |
||
441 | $request->free_result(); |
||
442 | |||
443 | return TopicUtil::prepareContext($return, true, ((int) $this->_preview_bodies) + 128); |
||
444 | } |
||
445 | |||
446 | /** |
||
447 | * Set the body query |
||
448 | * |
||
449 | * @return string |
||
450 | */ |
||
451 | private function _setBodyQuery() |
||
452 | { |
||
453 | if ($this->_preview_bodies === 'all') |
||
454 | { |
||
455 | return 'ml.body AS last_body, ms.body AS first_body,'; |
||
456 | } |
||
457 | |||
458 | // If empty, no preview at all |
||
459 | if (empty($this->_preview_bodies)) |
||
460 | { |
||
461 | return ''; |
||
462 | } |
||
463 | |||
464 | // Default: a SUBSTRING |
||
465 | return 'SUBSTRING(ml.body, 1, ' . ($this->_preview_bodies + 256) . ') AS last_body, SUBSTRING(ms.body, 1, ' . ($this->_preview_bodies + 256) . ') AS first_body,'; |
||
466 | } |
||
467 | } |
||
468 |
Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.
For example, imagine you have a variable
$accountId
that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to theid
property of an instance of theAccount
class. This class holds a proper account, so the id value must no longer be false.Either this assignment is in error or a type check should be added for that assignment.