auto_reduce_sync   A
last analyzed

Complexity

Total Complexity 20

Size/Duplication

Total Lines 263
Duplicated Lines 0 %

Importance

Changes 5
Bugs 0 Features 0
Metric Value
eloc 99
c 5
b 0
f 0
dl 0
loc 263
rs 10
wmc 20

9 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 10 1
A is_runnable() 0 3 1
A should_run() 0 3 1
A get_topic_ary() 0 43 3
A lock_topics() 0 11 3
A array_unique_sort() 0 5 1
A run() 0 29 3
A get_post_ary() 0 33 2
A reduce_search_index() 0 16 5
1
<?php
2
/**
3
 *
4
 * Reduce Search Index [RSI]. An extension for the phpBB Forum Software package.
5
 *
6
 * @copyright (c) 2020-forever, Dark❶, https://dark1.tech
7
 * @license GNU General Public License, version 2 (GPL-2.0)
8
 *
9
 */
10
11
namespace dark1\reducesearchindex\cron;
12
13
/**
14
 * @ignore
15
 */
16
use phpbb\cron\task\base;
17
use dark1\reducesearchindex\core\consts;
18
use phpbb\config\config;
19
use phpbb\db\driver\driver_interface as db_driver;
20
use phpbb\log\log;
21
use phpbb\auth\auth;
22
use phpbb\user;
23
use phpbb\event\dispatcher_interface as dispatcher;
24
use phpbb\search\fulltext_native;
25
26
/**
27
 * Reduce Search Index Cron Task.
28
 */
29
class auto_reduce_sync extends base
30
{
31
32
	/** @var config */
33
	protected $config;
34
35
	/** @var db_driver */
36
	protected $db;
37
38
	/** @var log */
39
	protected $phpbb_log;
40
41
	/** @var auth */
42
	protected $auth;
43
44
	/** @var user */
45
	protected $user;
46
47
	/** @var dispatcher */
48
	protected $phpbb_dispatcher;
49
50
	/** @var string phpBB root path */
51
	protected $phpbb_root_path;
52
53
	/** @var string phpBB php ext */
54
	protected $php_ext;
55
56
	/**
57
	* Constructor for cron task
58
	*
59
	* @param config			$config				phpBB config
60
	* @param db_driver		$db					phpBB DBAL object
61
	* @param log			$phpbb_log			phpBB log
62
	* @param auth			$auth				phpBB auth
63
	* @param user			$user				phpBB user
64
	* @param dispatcher		$dispatcher			phpBB dispatcher
65
	* @param string			$phpbb_root_path	phpBB root path
66
	* @param string			$php_ext			phpBB php ext
67
	* @access public
68
	*/
69
	public function __construct(config $config, db_driver $db, log $phpbb_log, auth $auth, user $user, dispatcher $phpbb_dispatcher, $phpbb_root_path, $php_ext)
70
	{
71
		$this->config			= $config;
72
		$this->db				= $db;
73
		$this->phpbb_log		= $phpbb_log;
74
		$this->auth				= $auth;
75
		$this->user				= $user;
76
		$this->phpbb_dispatcher	= $phpbb_dispatcher;
77
		$this->phpbb_root_path	= $phpbb_root_path;
78
		$this->php_ext			= $php_ext;
79
	}
80
81
	/**
82
	* Returns whether this cron task can run, given current board configuration.
83
	*
84
	* @return bool
85
	*/
86
	public function is_runnable()
87
	{
88
		return (bool) $this->config['dark1_rsi_auto_reduce_sync_enable'];
89
	}
90
91
	/**
92
	* Returns whether this cron task should run now, because enough time has passed since it was last run.
93
	*
94
	* @return bool
95
	*/
96
	public function should_run()
97
	{
98
		return (bool) ($this->config['dark1_rsi_auto_reduce_sync_last_gc'] < (time() - $this->config['dark1_rsi_auto_reduce_sync_gc']));
99
	}
100
101
	/**
102
	* Runs this cron task.
103
	*
104
	* @return null
105
	*/
106
	public function run()
107
	{
108
		if ($this->config['dark1_rsi_enable'] && ($this->config['dark1_rsi_time'] < (time() - $this->config['dark1_rsi_interval'])))
109
		{
110
			$this->config->set('dark1_rsi_time', (time() - $this->config['dark1_rsi_interval']), false);
111
112
			// Get Data
113
			$topic_ary = $this->get_topic_ary();
114
			$post_ary = $this->get_post_ary();
115
116
			// Set Data
117
			$post_ids = $this->array_unique_sort(array_merge($topic_ary['post_ids'], $post_ary['post_ids']));
118
			$poster_ids = $this->array_unique_sort(array_merge($topic_ary['poster_ids'], $post_ary['poster_ids']));
119
			$forum_ids = $this->array_unique_sort(array_merge($topic_ary['forum_ids'], $post_ary['forum_ids']));
120
			$topic_ids = $this->array_unique_sort($topic_ary['topic_ids']);
121
122
			// Lock Topics
123
			$this->lock_topics($topic_ids);
124
125
			// Remove the message from the search index
126
			$this->reduce_search_index($post_ids, $poster_ids, $forum_ids);
127
128
			$dark1_rsi_interval = $this->config['dark1_rsi_interval'] / 86400;
129
			$dark1_rsi_time = date(consts::TIME_FORMAT, (int) $this->config['dark1_rsi_time']);
130
			$this->phpbb_log->add('admin', ANONYMOUS, '127.0.0.1', 'RSI_AUTO_LOG', time(), [$dark1_rsi_interval, $dark1_rsi_time]);
131
		}
132
133
		// Update the last run time
134
		$this->config->set('dark1_rsi_auto_reduce_sync_last_gc', time(), false);
135
	}
136
137
	/**
138
	* Array to Uniquely Sort the IDs.
139
	*
140
	* @param array		$ary_ids		Array with IDs
141
	* @return array
142
	* @access private
143
	*/
144
	private function array_unique_sort($ary_ids)
145
	{
146
		$ary_ids = array_unique($ary_ids);
147
		sort($ary_ids, SORT_NUMERIC);
148
		return $ary_ids;
149
	}
150
151
	/**
152
	* Get Topic Array.
153
	*
154
	* @return array
155
	* @access private
156
	*/
157
	private function get_topic_ary()
158
	{
159
		$post_ids = $poster_ids = $forum_ids = $topic_ids = [];
160
161
		$sql_ary = [
162
			'SELECT'	=> 't.topic_id, p.post_id, p.poster_id, p.forum_id, f.dark1_rsi_f_enable',
163
			'FROM'		=> [
164
				POSTS_TABLE		=> 'p',
165
			],
166
			'LEFT_JOIN' => [
167
				[
168
					'FROM'	=> [TOPICS_TABLE => 't'],
169
					'ON'	=> 't.topic_id = p.topic_id',
170
				],
171
				[
172
					'FROM'	=> [FORUMS_TABLE => 'f'],
173
					'ON'	=> 'f.forum_id = p.forum_id',
174
				],
175
			],
176
			'WHERE'	=> 'f.dark1_rsi_f_enable >= ' . (int) consts::F_ENABLE_TOPIC . ' AND t.topic_time <= ' . (int) $this->config['dark1_rsi_time'],
177
		];
178
		$sql = $this->db->sql_build_query('SELECT', $sql_ary);
179
		$result = $this->db->sql_query($sql);
180
		$rows = $this->db->sql_fetchrowset($result);
181
		$this->db->sql_freeresult($result);
182
183
		foreach ($rows as $row)
184
		{
185
			$post_ids[] = (int) $row['post_id'];
186
			$poster_ids[] = (int) $row['poster_id'];
187
			$forum_ids[] = (int) $row['forum_id'];
188
189
			if ($row['dark1_rsi_f_enable'] == consts::F_ENABLE_LOCK)
190
			{
191
				$topic_ids[] = (int) $row['topic_id'];
192
			}
193
		}
194
195
		return [
196
			'post_ids' => $post_ids,
197
			'poster_ids' => $poster_ids,
198
			'forum_ids' => $forum_ids,
199
			'topic_ids' => $topic_ids,
200
		];
201
	}
202
203
	/**
204
	* Get Post Array.
205
	*
206
	* @return array
207
	* @access private
208
	*/
209
	private function get_post_ary()
210
	{
211
		$post_ids = $poster_ids = $forum_ids = [];
212
213
		$sql_ary = [
214
			'SELECT'	=> 'p.post_id, p.poster_id, p.forum_id',
215
			'FROM'		=> [
216
				POSTS_TABLE		=> 'p',
217
			],
218
			'LEFT_JOIN' => [
219
				[
220
					'FROM'	=> [FORUMS_TABLE => 'f'],
221
					'ON'	=> 'f.forum_id = p.forum_id',
222
				],
223
			],
224
			'WHERE'	=> 'f.dark1_rsi_f_enable = ' . (int) consts::F_ENABLE_POST . ' AND p.post_time <= ' . (int) $this->config['dark1_rsi_time'],
225
		];
226
		$sql = $this->db->sql_build_query('SELECT', $sql_ary);
227
		$result = $this->db->sql_query($sql);
228
		$rows = $this->db->sql_fetchrowset($result);
229
		$this->db->sql_freeresult($result);
230
231
		foreach ($rows as $row)
232
		{
233
			$post_ids[] = (int) $row['post_id'];
234
			$poster_ids[] = (int) $row['poster_id'];
235
			$forum_ids[] = (int) $row['forum_id'];
236
		}
237
238
		return [
239
			'post_ids' => $post_ids,
240
			'poster_ids' => $poster_ids,
241
			'forum_ids' => $forum_ids,
242
		];
243
	}
244
245
	/**
246
	* Lock Topics using Topic IDs.
247
	*
248
	* @param array		$topic_ids		Array with Topic IDs
249
	* @return void
250
	* @access private
251
	*/
252
	private function lock_topics($topic_ids)
253
	{
254
		if (count($topic_ids) > 0)
255
		{
256
			$topic_ids = array_chunk($topic_ids, 50, true);
257
			foreach ($topic_ids as $topic_ids_chunk)
258
			{
259
				$sql = 'UPDATE ' . TOPICS_TABLE .
260
						' SET topic_status = ' . ITEM_LOCKED  .
261
						' WHERE ' . $this->db->sql_in_set('topic_id', $topic_ids_chunk);
262
				$this->db->sql_query($sql);
263
			}
264
		}
265
	}
266
267
	/**
268
	* Reduce Search Index using Post & Poster & Forum IDs.
269
	*
270
	* @param array		$post_ids		Array with Post IDs
271
	* @param array		$poster_ids		Array with Poster IDs
272
	* @param array		$forum_ids		Array with Forum IDs
273
	* @return void
274
	* @access private
275
	*/
276
	private function reduce_search_index($post_ids, $poster_ids, $forum_ids)
277
	{
278
		$search = $this->config['search_type'];
279
		$name = substr($search, strrpos($search, '\\') + 1);
280
281
		if ($name == 'fulltext_native' && class_exists($search) && count($post_ids) > 0)
282
		{
283
			/** @var fulltext_native */
284
			$search = new $search($error = false, $this->phpbb_root_path, $this->php_ext, $this->auth, $this->config, $this->db, $this->user, $this->phpbb_dispatcher);
285
286
			$post_ids = array_chunk($post_ids, 50, true);
287
			foreach ($post_ids as $post_ids_chunk)
288
			{
289
				$this->db->sql_transaction('begin');
290
				$search->index_remove($post_ids_chunk, $poster_ids, $forum_ids);
291
				$this->db->sql_transaction('commit');
292
			}
293
		}
294
	}
295
}
296