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
|
|
|
* @param \phpbb\auth\auth $auth |
55
|
|
|
* @param \phpbb\cache\service $cache |
56
|
|
|
* @param \phpbb\config\config $config |
57
|
|
|
* @param \phpbb\db\driver\driver_interface $db |
58
|
|
|
* @param \phpbb\event\dispatcher_interface $dispatcher |
59
|
|
|
* @param \phpbb\pagination $pagination |
60
|
|
|
* @param \phpbb\request\request $request |
61
|
|
|
* @param \phpbb\template\template $template |
62
|
|
|
* @param \phpbb\user $user |
63
|
|
|
* @param \phpbb\content_visibility $content_visibility |
64
|
|
|
* @param string $root_path |
65
|
|
|
* @param string $php_ext |
66
|
|
|
* @access public |
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
|
|
|
* @return bool True if available, false otherwise |
88
|
|
|
* @access public |
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
|
|
|
* @return bool True if configured, false otherwise |
99
|
|
|
* @access public |
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
|
|
|
* @return bool True if viewable, false otherwise |
110
|
|
|
* @access public |
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
|
|
|
* Is the forum available for displaying similar topics |
119
|
|
|
* |
120
|
|
|
* @param int $forum_id A forum identifier |
121
|
|
|
* @return bool True if available, false otherwise |
122
|
|
|
* @access public |
123
|
|
|
*/ |
124
|
|
|
public function forum_available($forum_id) |
125
|
|
|
{ |
126
|
|
|
return !in_array($forum_id, explode(',', $this->config['similar_topics_hide'])); |
127
|
|
|
} |
128
|
|
|
|
129
|
|
|
/** |
130
|
|
|
* Get similar topics by matching topic titles |
131
|
|
|
* |
132
|
|
|
* NOTE: Currently requires MySQL due to the use of FULLTEXT indexes |
133
|
|
|
* and MATCH and AGAINST and UNIX_TIMESTAMP. MySQL FULLTEXT has built-in |
134
|
|
|
* English ignore words. We use phpBB's ignore words for non-English |
135
|
|
|
* languages. We also remove any admin-defined special ignore words. |
136
|
|
|
* |
137
|
|
|
* @param array $topic_data Array with topic data |
138
|
|
|
* @return null |
139
|
|
|
* @access public |
140
|
|
|
*/ |
141
|
|
|
public function display_similar_topics($topic_data) |
142
|
|
|
{ |
143
|
|
|
$topic_title = $this->clean_topic_title($topic_data['topic_title']); |
144
|
|
|
|
145
|
|
|
// If the cleaned up topic_title is empty, no need to continue |
146
|
|
|
if (empty($topic_title)) |
147
|
|
|
{ |
148
|
|
|
return; |
149
|
|
|
} |
150
|
|
|
|
151
|
|
|
// Similar Topics query |
152
|
|
|
$sql_array = array( |
153
|
|
|
'SELECT' => "f.forum_id, f.forum_name, t.*, |
154
|
|
|
MATCH (t.topic_title) AGAINST ('" . $this->db->sql_escape($topic_title) . "') AS score", |
155
|
|
|
|
156
|
|
|
'FROM' => array( |
157
|
|
|
TOPICS_TABLE => 't', |
158
|
|
|
), |
159
|
|
|
'LEFT_JOIN' => array( |
160
|
|
|
array( |
161
|
|
|
'FROM' => array(FORUMS_TABLE => 'f'), |
162
|
|
|
'ON' => 'f.forum_id = t.forum_id', |
163
|
|
|
), |
164
|
|
|
), |
165
|
|
|
'WHERE' => "MATCH (t.topic_title) AGAINST ('" . $this->db->sql_escape($topic_title) . "') >= 0.5 |
166
|
|
|
AND t.topic_status <> " . ITEM_MOVED . ' |
167
|
|
|
AND t.topic_visibility = ' . ITEM_APPROVED . ' |
168
|
|
|
AND t.topic_time > (UNIX_TIMESTAMP() - ' . $this->config['similar_topics_time'] . ') |
169
|
|
|
AND t.topic_id <> ' . (int) $topic_data['topic_id'], |
170
|
|
|
//'GROUP_BY' => 't.topic_id', |
|
|
|
|
171
|
|
|
//'ORDER_BY' => 'score DESC', // this is done automatically by MySQL when not using IN BOOLEAN MODE |
|
|
|
|
172
|
|
|
); |
173
|
|
|
|
174
|
|
|
// Add topic tracking data to the query (only if query caching is off) |
175
|
|
|
if ($this->user->data['is_registered'] && $this->config['load_db_lastread'] && !$this->config['similar_topics_cache']) |
176
|
|
|
{ |
177
|
|
|
$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']); |
178
|
|
|
$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']); |
179
|
|
|
$sql_array['SELECT'] .= ', tt.mark_time, ft.mark_time as f_mark_time'; |
180
|
|
|
} |
181
|
|
|
else if ($this->config['load_anon_lastread'] || $this->user->data['is_registered']) |
182
|
|
|
{ |
183
|
|
|
// Cookie based tracking copied from search.php |
184
|
|
|
$tracking_topics = $this->request->variable($this->config['cookie_name'] . '_track', '', true, \phpbb\request\request_interface::COOKIE); |
185
|
|
|
$tracking_topics = ($tracking_topics) ? tracking_unserialize($tracking_topics) : array(); |
186
|
|
|
} |
187
|
|
|
|
188
|
|
|
// We need to exclude passworded forums so we do not leak the topic title |
189
|
|
|
$passworded_forums = $this->user->get_passworded_forums(); |
190
|
|
|
|
191
|
|
|
// See if the admin set this forum to only search a specific group of other forums, and include them |
192
|
|
|
if (!empty($topic_data['similar_topic_forums'])) |
193
|
|
|
{ |
194
|
|
|
// Remove any passworded forums from this group of forums we will be searching |
195
|
|
|
$included_forums = array_diff(explode(',', $topic_data['similar_topic_forums']), $passworded_forums); |
196
|
|
|
// if there's nothing left to display (user has no access to the forums we want to search) |
197
|
|
|
if (empty($included_forums)) |
198
|
|
|
{ |
199
|
|
|
return; |
200
|
|
|
} |
201
|
|
|
|
202
|
|
|
$sql_array['WHERE'] .= ' AND ' . $this->db->sql_in_set('f.forum_id', $included_forums); |
203
|
|
|
} |
204
|
|
|
// Otherwise, see what forums are not allowed to be searched, and exclude them |
205
|
|
|
else if (!empty($this->config['similar_topics_ignore'])) |
206
|
|
|
{ |
207
|
|
|
// Add passworded forums to the exlude array |
208
|
|
|
$excluded_forums = array_unique(array_merge(explode(',', $this->config['similar_topics_ignore']), $passworded_forums)); |
209
|
|
|
$sql_array['WHERE'] .= ' AND ' . $this->db->sql_in_set('f.forum_id', $excluded_forums, true); |
210
|
|
|
} |
211
|
|
|
// In all other cases, exclude any passworded forums the user is not allowed to view |
212
|
|
|
else if (!empty($passworded_forums)) |
213
|
|
|
{ |
214
|
|
|
$sql_array['WHERE'] .= ' AND ' . $this->db->sql_in_set('f.forum_id', $passworded_forums, true); |
215
|
|
|
} |
216
|
|
|
|
217
|
|
|
/** |
218
|
|
|
* Event to modify the sql_array for similar topics |
219
|
|
|
* |
220
|
|
|
* @event vse.similartopics.get_topic_data |
221
|
|
|
* @var array sql_array SQL array to get similar topics data |
222
|
|
|
* @since 1.3.0 |
223
|
|
|
*/ |
224
|
|
|
$vars = array('sql_array'); |
225
|
|
|
extract($this->dispatcher->trigger_event('vse.similartopics.get_topic_data', compact($vars))); |
226
|
|
|
|
227
|
|
|
$sql = $this->db->sql_build_query('SELECT', $sql_array); |
228
|
|
|
$result = $this->db->sql_query_limit($sql, $this->config['similar_topics_limit'], 0, $this->config['similar_topics_cache']); |
229
|
|
|
|
230
|
|
|
// Grab icons |
231
|
|
|
$icons = $this->cache->obtain_icons(); |
232
|
|
|
|
233
|
|
|
$rowset = array(); |
234
|
|
|
|
235
|
|
|
while ($row = $this->db->sql_fetchrow($result)) |
236
|
|
|
{ |
237
|
|
|
$similar_forum_id = (int) $row['forum_id']; |
238
|
|
|
$similar_topic_id = (int) $row['topic_id']; |
239
|
|
|
$rowset[$similar_topic_id] = $row; |
240
|
|
|
|
241
|
|
|
if ($this->auth->acl_get('f_read', $similar_forum_id)) |
242
|
|
|
{ |
243
|
|
|
// Get topic tracking info |
244
|
|
|
if ($this->user->data['is_registered'] && $this->config['load_db_lastread'] && !$this->config['similar_topics_cache']) |
245
|
|
|
{ |
246
|
|
|
$topic_tracking_info = get_topic_tracking($similar_forum_id, $similar_topic_id, $rowset, array($similar_forum_id => $row['f_mark_time'])); |
247
|
|
|
} |
248
|
|
|
else if ($this->config['load_anon_lastread'] || $this->user->data['is_registered']) |
249
|
|
|
{ |
250
|
|
|
$topic_tracking_info = get_complete_topic_tracking($similar_forum_id, $similar_topic_id); |
251
|
|
|
|
252
|
|
|
if (!$this->user->data['is_registered']) |
253
|
|
|
{ |
254
|
|
|
$this->user->data['user_lastmark'] = (isset($tracking_topics['l'])) ? (int) (base_convert($tracking_topics['l'], 36, 10) + $this->config['board_startdate']) : 0; |
255
|
|
|
} |
256
|
|
|
} |
257
|
|
|
|
258
|
|
|
// Replies |
259
|
|
|
$replies = $this->content_visibility->get_count('topic_posts', $row, $similar_forum_id) - 1; |
260
|
|
|
|
261
|
|
|
// Get folder img, topic status/type related information |
262
|
|
|
$folder_img = $folder_alt = $topic_type = ''; |
263
|
|
|
$unread_topic = (isset($topic_tracking_info[$similar_topic_id]) && $row['topic_last_post_time'] > $topic_tracking_info[$similar_topic_id]) ? true : false; |
264
|
|
|
topic_status($row, $replies, $unread_topic, $folder_img, $folder_alt, $topic_type); |
265
|
|
|
|
266
|
|
|
$topic_unapproved = ($row['topic_visibility'] == ITEM_UNAPPROVED && $this->auth->acl_get('m_approve', $similar_forum_id)) ? true : false; |
267
|
|
|
$posts_unapproved = ($row['topic_visibility'] == ITEM_APPROVED && $row['topic_posts_unapproved'] && $this->auth->acl_get('m_approve', $similar_forum_id)) ? true : false; |
268
|
|
|
//$topic_deleted = $row['topic_visibility'] == ITEM_DELETED; |
|
|
|
|
269
|
|
|
$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) : ''; |
270
|
|
|
//$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; |
|
|
|
|
271
|
|
|
|
272
|
|
|
$base_url = append_sid("{$this->root_path}viewtopic.{$this->php_ext}", 'f=' . $similar_forum_id . '&t=' . $similar_topic_id); |
273
|
|
|
|
274
|
|
|
$topic_row = array( |
275
|
|
|
'TOPIC_AUTHOR_FULL' => get_username_string('full', $row['topic_poster'], $row['topic_first_poster_name'], $row['topic_first_poster_colour']), |
276
|
|
|
'FIRST_POST_TIME' => $this->user->format_date($row['topic_time']), |
277
|
|
|
'LAST_POST_TIME' => $this->user->format_date($row['topic_last_post_time']), |
278
|
|
|
'LAST_POST_AUTHOR_FULL' => get_username_string('full', $row['topic_last_poster_id'], $row['topic_last_poster_name'], $row['topic_last_poster_colour']), |
279
|
|
|
|
280
|
|
|
'TOPIC_REPLIES' => $replies, |
281
|
|
|
'TOPIC_VIEWS' => $row['topic_views'], |
282
|
|
|
'TOPIC_TITLE' => censor_text($row['topic_title']), |
283
|
|
|
'FORUM_TITLE' => $row['forum_name'], |
284
|
|
|
|
285
|
|
|
'TOPIC_IMG_STYLE' => $folder_img, |
286
|
|
|
'TOPIC_FOLDER_IMG' => $this->user->img($folder_img, $folder_alt), |
287
|
|
|
'TOPIC_FOLDER_IMG_ALT' => $this->user->lang($folder_alt), |
288
|
|
|
|
289
|
|
|
'TOPIC_ICON_IMG' => (!empty($icons[$row['icon_id']])) ? $icons[$row['icon_id']]['img'] : '', |
290
|
|
|
'TOPIC_ICON_IMG_WIDTH' => (!empty($icons[$row['icon_id']])) ? $icons[$row['icon_id']]['width'] : '', |
291
|
|
|
'TOPIC_ICON_IMG_HEIGHT' => (!empty($icons[$row['icon_id']])) ? $icons[$row['icon_id']]['height'] : '', |
292
|
|
|
'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')) : '', |
293
|
|
|
'UNAPPROVED_IMG' => ($topic_unapproved || $posts_unapproved) ? $this->user->img('icon_topic_unapproved', ($topic_unapproved) ? 'TOPIC_UNAPPROVED' : 'POSTS_UNAPPROVED') : '', |
294
|
|
|
|
295
|
|
|
'S_UNREAD_TOPIC' => $unread_topic, |
296
|
|
|
'S_TOPIC_REPORTED' => (!empty($row['topic_reported']) && $this->auth->acl_get('m_report', $similar_forum_id)) ? true : false, |
297
|
|
|
'S_TOPIC_UNAPPROVED' => $topic_unapproved, |
298
|
|
|
'S_POSTS_UNAPPROVED' => $posts_unapproved, |
299
|
|
|
//'S_TOPIC_DELETED' => $topic_deleted, |
|
|
|
|
300
|
|
|
'S_HAS_POLL' => ($row['poll_start']) ? true : false, |
301
|
|
|
|
302
|
|
|
'U_NEWEST_POST' => append_sid("{$this->root_path}viewtopic.{$this->php_ext}", 'f=' . $similar_forum_id . '&t=' . $similar_topic_id . '&view=unread') . '#unread', |
303
|
|
|
'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'], |
304
|
|
|
'U_VIEW_TOPIC' => append_sid("{$this->root_path}viewtopic.{$this->php_ext}", 'f=' . $similar_forum_id . '&t=' . $similar_topic_id), |
305
|
|
|
'U_VIEW_FORUM' => append_sid("{$this->root_path}viewforum.{$this->php_ext}", 'f=' . $similar_forum_id), |
306
|
|
|
'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), |
307
|
|
|
'U_MCP_QUEUE' => $u_mcp_queue, |
308
|
|
|
); |
309
|
|
|
|
310
|
|
|
/** |
311
|
|
|
* Event to modify the similar topics template block |
312
|
|
|
* |
313
|
|
|
* @event vse.similartopics.modify_topicrow |
314
|
|
|
* @var array row Array with similar topic data |
315
|
|
|
* @var array topic_row Template block array |
316
|
|
|
* @since 1.3.0 |
317
|
|
|
*/ |
318
|
|
|
$vars = array('row', 'topic_row'); |
319
|
|
|
extract($this->dispatcher->trigger_event('vse.similartopics.modify_topicrow', compact($vars))); |
320
|
|
|
|
321
|
|
|
$this->template->assign_block_vars('similar', $topic_row); |
322
|
|
|
|
323
|
|
|
$this->pagination->generate_template_pagination($base_url, 'similar.pagination', 'start', $replies + 1, $this->config['posts_per_page'], 1, true, true); |
324
|
|
|
} |
325
|
|
|
} |
326
|
|
|
|
327
|
|
|
$this->db->sql_freeresult($result); |
328
|
|
|
|
329
|
|
|
$this->user->add_lang_ext('vse/similartopics', 'similar_topics'); |
330
|
|
|
|
331
|
|
|
$this->template->assign_vars(array( |
332
|
|
|
'L_SIMILAR_TOPICS' => $this->user->lang('SIMILAR_TOPICS'), |
333
|
|
|
'NEWEST_POST_IMG' => $this->user->img('icon_topic_newest', 'VIEW_NEWEST_POST'), |
334
|
|
|
'LAST_POST_IMG' => $this->user->img('icon_topic_latest', 'VIEW_LATEST_POST'), |
335
|
|
|
'REPORTED_IMG' => $this->user->img('icon_topic_reported', 'TOPIC_REPORTED'), |
336
|
|
|
//'DELETED_IMG' => $this->user->img('icon_topic_deleted', 'TOPIC_DELETED'), |
|
|
|
|
337
|
|
|
'POLL_IMG' => $this->user->img('icon_topic_poll', 'TOPIC_POLL'), |
338
|
|
|
)); |
339
|
|
|
} |
340
|
|
|
|
341
|
|
|
/** |
342
|
|
|
* Clean topic title (and if needed, ignore-words) |
343
|
|
|
* |
344
|
|
|
* @param string $text The topic title |
345
|
|
|
* @return string The topic title |
346
|
|
|
* @access public |
347
|
|
|
*/ |
348
|
|
|
public function clean_topic_title($text) |
349
|
|
|
{ |
350
|
|
|
// Strip quotes, ampersands |
351
|
|
|
$text = str_replace(array('"', '&'), '', $text); |
352
|
|
|
|
353
|
|
|
if (!$this->english_lang() || $this->has_ignore_words()) |
354
|
|
|
{ |
355
|
|
|
$text = $this->strip_stop_words($text); |
356
|
|
|
} |
357
|
|
|
|
358
|
|
|
return $text; |
359
|
|
|
} |
360
|
|
|
|
361
|
|
|
/** |
362
|
|
|
* Remove any non-english and/or custom defined ignore-words |
363
|
|
|
* |
364
|
|
|
* @param string $text The topic title |
365
|
|
|
* @return string The topic title |
366
|
|
|
* @access protected |
367
|
|
|
*/ |
368
|
|
|
protected function strip_stop_words($text) |
369
|
|
|
{ |
370
|
|
|
$words = array(); |
371
|
|
|
|
372
|
|
|
// Retrieve a language dependent list of words to be ignored (method copied from search.php) |
373
|
|
|
$search_ignore_words = "{$this->user->lang_path}{$this->user->lang_name}/search_ignore_words.{$this->php_ext}"; |
374
|
|
|
if (!$this->english_lang() && file_exists($search_ignore_words)) |
375
|
|
|
{ |
376
|
|
|
include($search_ignore_words); |
377
|
|
|
} |
378
|
|
|
|
379
|
|
|
if ($this->has_ignore_words()) |
380
|
|
|
{ |
381
|
|
|
// Merge any custom defined ignore words from the ACP to the stop-words array |
382
|
|
|
$words = array_merge($this->make_word_array($this->config['similar_topics_words']), $words); |
383
|
|
|
} |
384
|
|
|
|
385
|
|
|
// Remove stop-words from the topic title text |
386
|
|
|
$words = array_diff($this->make_word_array($text), $words); |
387
|
|
|
|
388
|
|
|
// Convert our words array back to a string |
389
|
|
|
$text = (!empty($words)) ? implode(' ', $words) : ''; |
390
|
|
|
|
391
|
|
|
return $text; |
392
|
|
|
} |
393
|
|
|
|
394
|
|
|
/** |
395
|
|
|
* Helper function to split string into an array of words |
396
|
|
|
* |
397
|
|
|
* @param string $text String of plain text words |
398
|
|
|
* @return array Array of plaintext words |
399
|
|
|
* @access protected |
400
|
|
|
*/ |
401
|
|
|
protected function make_word_array($text) |
402
|
|
|
{ |
403
|
|
|
// Strip out any non-alpha-numeric characters using PCRE regex syntax |
404
|
|
|
$text = trim(preg_replace('#[^\p{L}\p{N}]+#u', ' ', $text)); |
405
|
|
|
|
406
|
|
|
$words = explode(' ', utf8_strtolower($text)); |
407
|
|
|
foreach ($words as $key => $word) |
408
|
|
|
{ |
409
|
|
|
// Strip words of 2 characters or less |
410
|
|
|
if (utf8_strlen(trim($word)) < 3) |
411
|
|
|
{ |
412
|
|
|
unset($words[$key]); |
413
|
|
|
} |
414
|
|
|
} |
415
|
|
|
|
416
|
|
|
return $words; |
417
|
|
|
} |
418
|
|
|
|
419
|
|
|
/** |
420
|
|
|
* Check if English is the current user's language |
421
|
|
|
* |
422
|
|
|
* @return bool True if lang is 'en' or 'en_us', false otherwise |
423
|
|
|
* @access protected |
424
|
|
|
*/ |
425
|
|
|
protected function english_lang() |
426
|
|
|
{ |
427
|
|
|
return ($this->user->lang_name == 'en' || $this->user->lang_name == 'en_us'); |
428
|
|
|
} |
429
|
|
|
|
430
|
|
|
/** |
431
|
|
|
* Check if custom ignore words have been defined for similar topics |
432
|
|
|
* |
433
|
|
|
* @return bool True or false |
434
|
|
|
* @access protected |
435
|
|
|
*/ |
436
|
|
|
protected function has_ignore_words() |
437
|
|
|
{ |
438
|
|
|
return !empty($this->config['similar_topics_words']); |
439
|
|
|
} |
440
|
|
|
|
441
|
|
|
/** |
442
|
|
|
* Check if the database layer is MySQL4 or later |
443
|
|
|
* |
444
|
|
|
* @return bool True is MySQL4 or later, false otherwise |
445
|
|
|
* @access protected |
446
|
|
|
*/ |
447
|
|
|
protected function is_mysql() |
448
|
|
|
{ |
449
|
|
|
return ($this->db->get_sql_layer() == 'mysql4' || $this->db->get_sql_layer() == 'mysqli'); |
450
|
|
|
} |
451
|
|
|
} |
452
|
|
|
|
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.