1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* |
4
|
|
|
* Precise Similar Topics |
5
|
|
|
* |
6
|
|
|
* @copyright (c) 2013 Matt Friedman |
7
|
|
|
* @license GNU General Public License, version 2 (GPL-2.0) |
8
|
|
|
* |
9
|
|
|
*/ |
10
|
|
|
|
11
|
|
|
namespace vse\similartopics\core; |
12
|
|
|
|
13
|
|
|
class similar_topics |
14
|
|
|
{ |
15
|
|
|
/** @var \phpbb\auth\auth */ |
16
|
|
|
protected $auth; |
17
|
|
|
|
18
|
|
|
/** @var \phpbb\cache\service */ |
19
|
|
|
protected $cache; |
20
|
|
|
|
21
|
|
|
/** @var \phpbb\config\config */ |
22
|
|
|
protected $config; |
23
|
|
|
|
24
|
|
|
/** @var \phpbb\db\driver\driver_interface */ |
25
|
|
|
protected $db; |
26
|
|
|
|
27
|
|
|
/** @var \phpbb\event\dispatcher_interface */ |
28
|
|
|
protected $dispatcher; |
29
|
|
|
|
30
|
|
|
/** @var \phpbb\pagination */ |
31
|
|
|
protected $pagination; |
32
|
|
|
|
33
|
|
|
/** @var \phpbb\request\request */ |
34
|
|
|
protected $request; |
35
|
|
|
|
36
|
|
|
/** @var \phpbb\template\template */ |
37
|
|
|
protected $template; |
38
|
|
|
|
39
|
|
|
/** @var \phpbb\user */ |
40
|
|
|
protected $user; |
41
|
|
|
|
42
|
|
|
/** @var \phpbb\content_visibility */ |
43
|
|
|
protected $content_visibility; |
44
|
|
|
|
45
|
|
|
/** @var string phpBB root path */ |
46
|
|
|
protected $root_path; |
47
|
|
|
|
48
|
|
|
/** @var string PHP file extension */ |
49
|
|
|
protected $php_ext; |
50
|
|
|
|
51
|
|
|
/** |
52
|
|
|
* Constructor |
53
|
|
|
* |
54
|
|
|
* @access public |
55
|
|
|
* @param \phpbb\auth\auth $auth |
56
|
|
|
* @param \phpbb\cache\service $cache |
57
|
|
|
* @param \phpbb\config\config $config |
58
|
|
|
* @param \phpbb\db\driver\driver_interface $db |
59
|
|
|
* @param \phpbb\event\dispatcher_interface $dispatcher |
60
|
|
|
* @param \phpbb\pagination $pagination |
61
|
|
|
* @param \phpbb\request\request $request |
62
|
|
|
* @param \phpbb\template\template $template |
63
|
|
|
* @param \phpbb\user $user |
64
|
|
|
* @param \phpbb\content_visibility $content_visibility |
65
|
|
|
* @param string $root_path |
66
|
|
|
* @param string $php_ext |
67
|
|
|
*/ |
68
|
|
|
public function __construct(\phpbb\auth\auth $auth, \phpbb\cache\service $cache, \phpbb\config\config $config, \phpbb\db\driver\driver_interface $db, \phpbb\event\dispatcher_interface $dispatcher, \phpbb\pagination $pagination, \phpbb\request\request $request, \phpbb\template\template $template, \phpbb\user $user, \phpbb\content_visibility $content_visibility, $root_path, $php_ext) |
69
|
|
|
{ |
70
|
|
|
$this->auth = $auth; |
71
|
|
|
$this->cache = $cache; |
72
|
|
|
$this->config = $config; |
73
|
|
|
$this->db = $db; |
74
|
|
|
$this->dispatcher = $dispatcher; |
75
|
|
|
$this->pagination = $pagination; |
76
|
|
|
$this->request = $request; |
77
|
|
|
$this->template = $template; |
78
|
|
|
$this->user = $user; |
79
|
|
|
$this->content_visibility = $content_visibility; |
80
|
|
|
$this->root_path = $root_path; |
81
|
|
|
$this->php_ext = $php_ext; |
82
|
|
|
} |
83
|
|
|
|
84
|
|
|
/** |
85
|
|
|
* Is similar topics available? |
86
|
|
|
* |
87
|
|
|
* @access public |
88
|
|
|
* @return bool True if available, false otherwise |
89
|
|
|
*/ |
90
|
|
|
public function is_available() |
91
|
|
|
{ |
92
|
|
|
return $this->is_enabled() && $this->is_viewable() && $this->is_mysql(); |
93
|
|
|
} |
94
|
|
|
|
95
|
|
|
/** |
96
|
|
|
* Is similar topics configured? |
97
|
|
|
* |
98
|
|
|
* @access public |
99
|
|
|
* @return bool True if configured, false otherwise |
100
|
|
|
*/ |
101
|
|
|
public function is_enabled() |
102
|
|
|
{ |
103
|
|
|
return !empty($this->config['similar_topics']) && !empty($this->config['similar_topics_limit']); |
104
|
|
|
} |
105
|
|
|
|
106
|
|
|
/** |
107
|
|
|
* Is similar topics viewable bu the user? |
108
|
|
|
* |
109
|
|
|
* @access public |
110
|
|
|
* @return bool True if viewable, false otherwise |
111
|
|
|
*/ |
112
|
|
|
public function is_viewable() |
113
|
|
|
{ |
114
|
|
|
return !empty($this->user->data['user_similar_topics']) && $this->auth->acl_get('u_similar_topics'); |
115
|
|
|
} |
116
|
|
|
|
117
|
|
|
/** |
118
|
|
|
* Get similar topics by matching topic titles |
119
|
|
|
* |
120
|
|
|
* NOTE: Currently requires MySQL due to the use of FULLTEXT indexes |
121
|
|
|
* and MATCH and AGAINST and UNIX_TIMESTAMP. MySQL FULLTEXT has built-in |
122
|
|
|
* English ignore words. We use phpBB's ignore words for non-English |
123
|
|
|
* languages. We also remove any admin-defined special ignore words. |
124
|
|
|
* |
125
|
|
|
* @access public |
126
|
|
|
* @param array $topic_data Array with topic data |
127
|
|
|
*/ |
128
|
|
|
public function display_similar_topics($topic_data) |
129
|
|
|
{ |
130
|
|
|
// If the forum should not display similar topics, no need to continue |
131
|
|
|
if ($topic_data['similar_topics_hide']) |
132
|
|
|
{ |
133
|
|
|
return; |
134
|
|
|
} |
135
|
|
|
|
136
|
|
|
$topic_title = $this->clean_topic_title($topic_data['topic_title']); |
137
|
|
|
|
138
|
|
|
// If the cleaned up topic_title is empty, no need to continue |
139
|
|
|
if (empty($topic_title)) |
140
|
|
|
{ |
141
|
|
|
return; |
142
|
|
|
} |
143
|
|
|
|
144
|
|
|
// Similar Topics query |
145
|
|
|
$sql_array = array( |
146
|
|
|
'SELECT' => "f.forum_id, f.forum_name, t.*, |
147
|
|
|
MATCH (t.topic_title) AGAINST ('" . $this->db->sql_escape($topic_title) . "') AS score", |
148
|
|
|
|
149
|
|
|
'FROM' => array( |
150
|
|
|
TOPICS_TABLE => 't', |
151
|
|
|
), |
152
|
|
|
'LEFT_JOIN' => array( |
153
|
|
|
array( |
154
|
|
|
'FROM' => array(FORUMS_TABLE => 'f'), |
155
|
|
|
'ON' => 'f.forum_id = t.forum_id', |
156
|
|
|
), |
157
|
|
|
), |
158
|
|
|
'WHERE' => "MATCH (t.topic_title) AGAINST ('" . $this->db->sql_escape($topic_title) . "') >= 0.5 |
159
|
|
|
AND t.topic_status <> " . ITEM_MOVED . ' |
160
|
|
|
AND t.topic_visibility = ' . ITEM_APPROVED . ' |
161
|
|
|
AND t.topic_time > (UNIX_TIMESTAMP() - ' . $this->config['similar_topics_time'] . ') |
162
|
|
|
AND t.topic_id <> ' . (int) $topic_data['topic_id'], |
163
|
|
|
//'GROUP_BY' => 't.topic_id', |
|
|
|
|
164
|
|
|
//'ORDER_BY' => 'score DESC', // this is done automatically by MySQL when not using IN BOOLEAN MODE |
|
|
|
|
165
|
|
|
); |
166
|
|
|
|
167
|
|
|
// Add topic tracking data to the query (only if query caching is off) |
168
|
|
|
if ($this->user->data['is_registered'] && $this->config['load_db_lastread'] && !$this->config['similar_topics_cache']) |
169
|
|
|
{ |
170
|
|
|
$sql_array['LEFT_JOIN'][] = array('FROM' => array(TOPICS_TRACK_TABLE => 'tt'), 'ON' => 'tt.topic_id = t.topic_id AND tt.user_id = ' . $this->user->data['user_id']); |
171
|
|
|
$sql_array['LEFT_JOIN'][] = array('FROM' => array(FORUMS_TRACK_TABLE => 'ft'), 'ON' => 'ft.forum_id = f.forum_id AND ft.user_id = ' . $this->user->data['user_id']); |
172
|
|
|
$sql_array['SELECT'] .= ', tt.mark_time, ft.mark_time as f_mark_time'; |
173
|
|
|
} |
174
|
|
|
else if ($this->config['load_anon_lastread'] || $this->user->data['is_registered']) |
175
|
|
|
{ |
176
|
|
|
// Cookie based tracking copied from search.php |
177
|
|
|
$tracking_topics = $this->request->variable($this->config['cookie_name'] . '_track', '', true, \phpbb\request\request_interface::COOKIE); |
178
|
|
|
$tracking_topics = $tracking_topics ? tracking_unserialize($tracking_topics) : array(); |
179
|
|
|
} |
180
|
|
|
|
181
|
|
|
// We need to exclude passworded forums so we do not leak the topic title |
182
|
|
|
$passworded_forums = $this->user->get_passworded_forums(); |
183
|
|
|
|
184
|
|
|
// See if the admin set this forum to only search a specific group of other forums, and include them |
185
|
|
|
if (!empty($topic_data['similar_topic_forums'])) |
186
|
|
|
{ |
187
|
|
|
// Remove any passworded forums from this group of forums we will be searching |
188
|
|
|
$included_forums = array_diff(json_decode($topic_data['similar_topic_forums'], true), $passworded_forums); |
189
|
|
|
// if there's nothing left to display (user has no access to the forums we want to search) |
190
|
|
|
if (empty($included_forums)) |
191
|
|
|
{ |
192
|
|
|
return; |
193
|
|
|
} |
194
|
|
|
|
195
|
|
|
$sql_array['WHERE'] .= ' AND ' . $this->db->sql_in_set('f.forum_id', $included_forums); |
196
|
|
|
} |
197
|
|
|
// Otherwise exclude any ignored forums |
198
|
|
|
else |
199
|
|
|
{ |
200
|
|
|
// Remove any passworded forums |
201
|
|
|
if (sizeof($passworded_forums)) |
202
|
|
|
{ |
203
|
|
|
$sql_array['WHERE'] .= ' AND ' . $this->db->sql_in_set('f.forum_id', $passworded_forums, true); |
204
|
|
|
} |
205
|
|
|
|
206
|
|
|
$sql_array['WHERE'] .= ' AND f.similar_topics_ignore = 0'; |
207
|
|
|
} |
208
|
|
|
|
209
|
|
|
/** |
210
|
|
|
* Event to modify the sql_array for similar topics |
211
|
|
|
* |
212
|
|
|
* @event vse.similartopics.get_topic_data |
213
|
|
|
* @var array sql_array SQL array to get similar topics data |
214
|
|
|
* @since 1.3.0 |
215
|
|
|
*/ |
216
|
|
|
$vars = array('sql_array'); |
217
|
|
|
extract($this->dispatcher->trigger_event('vse.similartopics.get_topic_data', compact($vars))); |
218
|
|
|
|
219
|
|
|
$sql = $this->db->sql_build_query('SELECT', $sql_array); |
220
|
|
|
$result = $this->db->sql_query_limit($sql, $this->config['similar_topics_limit'], 0, $this->config['similar_topics_cache']); |
221
|
|
|
|
222
|
|
|
// Grab icons |
223
|
|
|
$icons = $this->cache->obtain_icons(); |
224
|
|
|
|
225
|
|
|
$rowset = array(); |
226
|
|
|
|
227
|
|
|
while ($row = $this->db->sql_fetchrow($result)) |
228
|
|
|
{ |
229
|
|
|
$similar_forum_id = (int) $row['forum_id']; |
230
|
|
|
$similar_topic_id = (int) $row['topic_id']; |
231
|
|
|
$rowset[$similar_topic_id] = $row; |
232
|
|
|
|
233
|
|
|
if ($this->auth->acl_get('f_read', $similar_forum_id)) |
234
|
|
|
{ |
235
|
|
|
// Get topic tracking info |
236
|
|
|
if ($this->user->data['is_registered'] && $this->config['load_db_lastread'] && !$this->config['similar_topics_cache']) |
237
|
|
|
{ |
238
|
|
|
$topic_tracking_info = get_topic_tracking($similar_forum_id, $similar_topic_id, $rowset, array($similar_forum_id => $row['f_mark_time'])); |
239
|
|
|
} |
240
|
|
|
else if ($this->config['load_anon_lastread'] || $this->user->data['is_registered']) |
241
|
|
|
{ |
242
|
|
|
$topic_tracking_info = get_complete_topic_tracking($similar_forum_id, $similar_topic_id); |
243
|
|
|
|
244
|
|
|
if (!$this->user->data['is_registered']) |
245
|
|
|
{ |
246
|
|
|
$this->user->data['user_lastmark'] = isset($tracking_topics['l']) ? ((int) base_convert($tracking_topics['l'], 36, 10) + (int) $this->config['board_startdate']) : 0; |
247
|
|
|
} |
248
|
|
|
} |
249
|
|
|
|
250
|
|
|
// Replies |
251
|
|
|
$replies = $this->content_visibility->get_count('topic_posts', $row, $similar_forum_id) - 1; |
252
|
|
|
|
253
|
|
|
// Get folder img, topic status/type related information |
254
|
|
|
$folder_img = $folder_alt = $topic_type = ''; |
255
|
|
|
$unread_topic = isset($topic_tracking_info[$similar_topic_id]) && $row['topic_last_post_time'] > $topic_tracking_info[$similar_topic_id]; |
256
|
|
|
topic_status($row, $replies, $unread_topic, $folder_img, $folder_alt, $topic_type); |
257
|
|
|
|
258
|
|
|
$topic_unapproved = $row['topic_visibility'] == ITEM_UNAPPROVED && $this->auth->acl_get('m_approve', $similar_forum_id); |
259
|
|
|
$posts_unapproved = $row['topic_visibility'] == ITEM_APPROVED && $row['topic_posts_unapproved'] && $this->auth->acl_get('m_approve', $similar_forum_id); |
260
|
|
|
//$topic_deleted = $row['topic_visibility'] == ITEM_DELETED; |
|
|
|
|
261
|
|
|
$u_mcp_queue = ($topic_unapproved || $posts_unapproved) ? append_sid("{$this->root_path}mcp.{$this->php_ext}", 'i=queue&mode=' . ($topic_unapproved ? 'approve_details' : 'unapproved_posts') . "&t=$similar_topic_id", true, $this->user->session_id) : ''; |
262
|
|
|
//$u_mcp_queue = (!$u_mcp_queue && $topic_deleted) ? append_sid("{$this->root_path}mcp.{$this->php_ext}", "i=queue&mode=deleted_topics&t=$similar_topic_id", true, $this->user->session_id) : $u_mcp_queue; |
|
|
|
|
263
|
|
|
|
264
|
|
|
$base_url = append_sid("{$this->root_path}viewtopic.{$this->php_ext}", 'f=' . $similar_forum_id . '&t=' . $similar_topic_id); |
265
|
|
|
|
266
|
|
|
$topic_row = array( |
267
|
|
|
'TOPIC_AUTHOR_FULL' => get_username_string('full', $row['topic_poster'], $row['topic_first_poster_name'], $row['topic_first_poster_colour']), |
268
|
|
|
'FIRST_POST_TIME' => $this->user->format_date($row['topic_time']), |
269
|
|
|
'LAST_POST_TIME' => $this->user->format_date($row['topic_last_post_time']), |
270
|
|
|
'LAST_POST_AUTHOR_FULL' => get_username_string('full', $row['topic_last_poster_id'], $row['topic_last_poster_name'], $row['topic_last_poster_colour']), |
271
|
|
|
|
272
|
|
|
'TOPIC_REPLIES' => $replies, |
273
|
|
|
'TOPIC_VIEWS' => $row['topic_views'], |
274
|
|
|
'TOPIC_TITLE' => censor_text($row['topic_title']), |
275
|
|
|
'FORUM_TITLE' => $row['forum_name'], |
276
|
|
|
|
277
|
|
|
'TOPIC_IMG_STYLE' => $folder_img, |
278
|
|
|
'TOPIC_FOLDER_IMG' => $this->user->img($folder_img, $folder_alt), |
279
|
|
|
'TOPIC_FOLDER_IMG_ALT' => $this->user->lang($folder_alt), |
280
|
|
|
|
281
|
|
|
'TOPIC_ICON_IMG' => (!empty($icons[$row['icon_id']])) ? $icons[$row['icon_id']]['img'] : '', |
282
|
|
|
'TOPIC_ICON_IMG_WIDTH' => (!empty($icons[$row['icon_id']])) ? $icons[$row['icon_id']]['width'] : '', |
283
|
|
|
'TOPIC_ICON_IMG_HEIGHT' => (!empty($icons[$row['icon_id']])) ? $icons[$row['icon_id']]['height'] : '', |
284
|
|
|
'ATTACH_ICON_IMG' => ($this->auth->acl_get('u_download') && $this->auth->acl_get('f_download', $similar_forum_id) && $row['topic_attachment']) ? $this->user->img('icon_topic_attach', $this->user->lang('TOTAL_ATTACHMENTS')) : '', |
285
|
|
|
'UNAPPROVED_IMG' => ($topic_unapproved || $posts_unapproved) ? $this->user->img('icon_topic_unapproved', $topic_unapproved ? 'TOPIC_UNAPPROVED' : 'POSTS_UNAPPROVED') : '', |
286
|
|
|
|
287
|
|
|
'S_UNREAD_TOPIC' => $unread_topic, |
288
|
|
|
'S_TOPIC_REPORTED' => !empty($row['topic_reported']) && $this->auth->acl_get('m_report', $similar_forum_id), |
289
|
|
|
'S_TOPIC_UNAPPROVED' => $topic_unapproved, |
290
|
|
|
'S_POSTS_UNAPPROVED' => $posts_unapproved, |
291
|
|
|
//'S_TOPIC_DELETED' => $topic_deleted, |
|
|
|
|
292
|
|
|
'S_HAS_POLL' => (bool) $row['poll_start'], |
293
|
|
|
|
294
|
|
|
'U_NEWEST_POST' => append_sid("{$this->root_path}viewtopic.{$this->php_ext}", 'f=' . $similar_forum_id . '&t=' . $similar_topic_id . '&view=unread') . '#unread', |
295
|
|
|
'U_LAST_POST' => append_sid("{$this->root_path}viewtopic.{$this->php_ext}", 'f=' . $similar_forum_id . '&t=' . $similar_topic_id . '&p=' . $row['topic_last_post_id']) . '#p' . $row['topic_last_post_id'], |
296
|
|
|
'U_VIEW_TOPIC' => append_sid("{$this->root_path}viewtopic.{$this->php_ext}", 'f=' . $similar_forum_id . '&t=' . $similar_topic_id), |
297
|
|
|
'U_VIEW_FORUM' => append_sid("{$this->root_path}viewforum.{$this->php_ext}", 'f=' . $similar_forum_id), |
298
|
|
|
'U_MCP_REPORT' => append_sid("{$this->root_path}mcp.{$this->php_ext}", 'i=reports&mode=reports&f=' . $similar_forum_id . '&t=' . $similar_topic_id, true, $this->user->session_id), |
299
|
|
|
'U_MCP_QUEUE' => $u_mcp_queue, |
300
|
|
|
); |
301
|
|
|
|
302
|
|
|
/** |
303
|
|
|
* Event to modify the similar topics template block |
304
|
|
|
* |
305
|
|
|
* @event vse.similartopics.modify_topicrow |
306
|
|
|
* @var array row Array with similar topic data |
307
|
|
|
* @var array topic_row Template block array |
308
|
|
|
* @since 1.3.0 |
309
|
|
|
*/ |
310
|
|
|
$vars = array('row', 'topic_row'); |
311
|
|
|
extract($this->dispatcher->trigger_event('vse.similartopics.modify_topicrow', compact($vars))); |
312
|
|
|
|
313
|
|
|
$this->template->assign_block_vars('similar', $topic_row); |
314
|
|
|
|
315
|
|
|
$this->pagination->generate_template_pagination($base_url, 'similar.pagination', 'start', $replies + 1, $this->config['posts_per_page'], 1, true, true); |
316
|
|
|
} |
317
|
|
|
} |
318
|
|
|
|
319
|
|
|
$this->db->sql_freeresult($result); |
320
|
|
|
|
321
|
|
|
$this->user->add_lang_ext('vse/similartopics', 'similar_topics'); |
322
|
|
|
|
323
|
|
|
$this->template->assign_vars(array( |
324
|
|
|
'L_SIMILAR_TOPICS' => $this->user->lang('SIMILAR_TOPICS'), |
325
|
|
|
'NEWEST_POST_IMG' => $this->user->img('icon_topic_newest', 'VIEW_NEWEST_POST'), |
326
|
|
|
'LAST_POST_IMG' => $this->user->img('icon_topic_latest', 'VIEW_LATEST_POST'), |
327
|
|
|
'REPORTED_IMG' => $this->user->img('icon_topic_reported', 'TOPIC_REPORTED'), |
328
|
|
|
//'DELETED_IMG' => $this->user->img('icon_topic_deleted', 'TOPIC_DELETED'), |
|
|
|
|
329
|
|
|
'POLL_IMG' => $this->user->img('icon_topic_poll', 'TOPIC_POLL'), |
330
|
|
|
'S_PST_BRANCH' => phpbb_version_compare(max($this->config['phpbb_version'], PHPBB_VERSION), '3.2.0-dev', '<') ? '31x' : '32x', |
331
|
|
|
)); |
332
|
|
|
} |
333
|
|
|
|
334
|
|
|
/** |
335
|
|
|
* Clean topic title (and if needed, ignore-words) |
336
|
|
|
* |
337
|
|
|
* @access public |
338
|
|
|
* @param string $text The topic title |
339
|
|
|
* @return string The topic title |
340
|
|
|
*/ |
341
|
|
|
public function clean_topic_title($text) |
342
|
|
|
{ |
343
|
|
|
// Strip quotes, ampersands |
344
|
|
|
$text = str_replace(array('"', '&'), '', $text); |
345
|
|
|
|
346
|
|
|
if (!$this->english_lang() || $this->has_ignore_words()) |
347
|
|
|
{ |
348
|
|
|
$text = $this->strip_stop_words($text); |
349
|
|
|
} |
350
|
|
|
|
351
|
|
|
return $text; |
352
|
|
|
} |
353
|
|
|
|
354
|
|
|
/** |
355
|
|
|
* Remove any non-english and/or custom defined ignore-words |
356
|
|
|
* |
357
|
|
|
* @access protected |
358
|
|
|
* @param string $text The topic title |
359
|
|
|
* @return string The topic title |
360
|
|
|
*/ |
361
|
|
|
protected function strip_stop_words($text) |
362
|
|
|
{ |
363
|
|
|
$words = array(); |
364
|
|
|
|
365
|
|
|
// Retrieve a language dependent list of words to be ignored (method copied from search.php) |
366
|
|
|
$search_ignore_words = "{$this->user->lang_path}{$this->user->lang_name}/search_ignore_words.{$this->php_ext}"; |
367
|
|
|
if (!$this->english_lang() && file_exists($search_ignore_words)) |
368
|
|
|
{ |
369
|
|
|
include($search_ignore_words); |
370
|
|
|
} |
371
|
|
|
|
372
|
|
|
if ($this->has_ignore_words()) |
373
|
|
|
{ |
374
|
|
|
// Merge any custom defined ignore words from the ACP to the stop-words array |
375
|
|
|
$words = array_merge($this->make_word_array($this->config['similar_topics_words']), $words); |
376
|
|
|
} |
377
|
|
|
|
378
|
|
|
// Remove stop-words from the topic title text |
379
|
|
|
$words = array_diff($this->make_word_array($text), $words); |
380
|
|
|
|
381
|
|
|
// Convert our words array back to a string |
382
|
|
|
return implode(' ', $words); |
383
|
|
|
} |
384
|
|
|
|
385
|
|
|
/** |
386
|
|
|
* Helper function to split string into an array of words |
387
|
|
|
* |
388
|
|
|
* @access protected |
389
|
|
|
* @param string $text String of plain text words |
390
|
|
|
* @return array Array of plaintext words |
391
|
|
|
*/ |
392
|
|
|
protected function make_word_array($text) |
393
|
|
|
{ |
394
|
|
|
// Strip out any non-alpha-numeric characters using PCRE regex syntax |
395
|
|
|
$text = trim(preg_replace('#[^\p{L}\p{N}]+#u', ' ', $text)); |
396
|
|
|
|
397
|
|
|
$words = explode(' ', utf8_strtolower($text)); |
398
|
|
|
foreach ($words as $key => $word) |
399
|
|
|
{ |
400
|
|
|
// Strip words of 2 characters or less |
401
|
|
|
if (utf8_strlen(trim($word)) < 3) |
402
|
|
|
{ |
403
|
|
|
unset($words[$key]); |
404
|
|
|
} |
405
|
|
|
} |
406
|
|
|
|
407
|
|
|
return $words; |
408
|
|
|
} |
409
|
|
|
|
410
|
|
|
/** |
411
|
|
|
* Check if English is the current user's language |
412
|
|
|
* |
413
|
|
|
* @access protected |
414
|
|
|
* @return bool True if lang is 'en' or 'en_us', false otherwise |
415
|
|
|
*/ |
416
|
|
|
protected function english_lang() |
417
|
|
|
{ |
418
|
|
|
return ($this->user->lang_name === 'en' || $this->user->lang_name === 'en_us'); |
419
|
|
|
} |
420
|
|
|
|
421
|
|
|
/** |
422
|
|
|
* Check if custom ignore words have been defined for similar topics |
423
|
|
|
* |
424
|
|
|
* @access protected |
425
|
|
|
* @return bool True or false |
426
|
|
|
*/ |
427
|
|
|
protected function has_ignore_words() |
428
|
|
|
{ |
429
|
|
|
return !empty($this->config['similar_topics_words']); |
430
|
|
|
} |
431
|
|
|
|
432
|
|
|
/** |
433
|
|
|
* Check if the database layer is MySQL4 or later |
434
|
|
|
* |
435
|
|
|
* @access protected |
436
|
|
|
* @return bool True is MySQL4 or later, false otherwise |
437
|
|
|
*/ |
438
|
|
|
protected function is_mysql() |
439
|
|
|
{ |
440
|
|
|
return ($this->db->get_sql_layer() === 'mysql4' || $this->db->get_sql_layer() === 'mysqli'); |
441
|
|
|
} |
442
|
|
|
} |
443
|
|
|
|
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.
The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.
This check looks for comments that seem to be mostly valid code and reports them.