Issues (104)

driver/mysqli.php (10 issues)

Labels
Severity
1
<?php
2
/**
3
 *
4
 * Precise Similar Topics
5
 *
6
 * @copyright (c) 2018 Matt Friedman
7
 * @license GNU General Public License, version 2 (GPL-2.0)
8
 *
9
 */
10
11
namespace vse\similartopics\driver;
12
13
/**
14
 * This class handles similar topics queries for MySQLi dbms
15
 */
16
class mysqli implements driver_interface
17
{
18
	/** @var \phpbb\db\driver\driver_interface */
0 ignored issues
show
The type phpbb\db\driver\driver_interface was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
19
	protected $db;
20
21
	/** @var string */
22
	protected $engine;
23
24
	/**
25
	 * Constructor
26
	 *
27
	 * @param \phpbb\db\driver\driver_interface $db
28
	 */
29
	public function __construct(\phpbb\db\driver\driver_interface $db)
30
	{
31
		$this->db = $db;
32
	}
33
34
	/**
35
	 * {@inheritdoc}
36
	 */
37
	public function get_name()
38
	{
39
		return 'mysqli';
40
	}
41
42
	/**
43
	 * {@inheritdoc}
44
	 */
45
	public function get_type()
46
	{
47
		return 'mysql';
48
	}
49
50
	/**
51
	 * {@inheritdoc}
52
	 */
53
	public function get_query($topic_id, $topic_title, $length, $sensitivity)
54
	{
55
		return array(
56
			'SELECT'	=> "f.forum_id, f.forum_name, t.*,
57
				MATCH (t.topic_title) AGAINST ('" . $this->db->sql_escape($topic_title) . "') AS score",
58
59
			'FROM'		=> array(
60
				TOPICS_TABLE	=> 't',
0 ignored issues
show
The constant vse\similartopics\driver\TOPICS_TABLE was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
61
			),
62
			'LEFT_JOIN'	=> array(
63
				array(
64
					'FROM'	=>	array(FORUMS_TABLE	=> 'f'),
0 ignored issues
show
The constant vse\similartopics\driver\FORUMS_TABLE was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
65
					'ON'	=> 'f.forum_id = t.forum_id',
66
				),
67
			),
68
			'WHERE'		=> "MATCH (t.topic_title) AGAINST ('" . $this->db->sql_escape($topic_title) . "') >= " . (float) $sensitivity . '
69
				AND t.topic_status <> ' . ITEM_MOVED . '
0 ignored issues
show
The constant vse\similartopics\driver\ITEM_MOVED was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
70
				AND t.topic_visibility = ' . ITEM_APPROVED . '
0 ignored issues
show
The constant vse\similartopics\driver\ITEM_APPROVED was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
71
				AND t.topic_time > (UNIX_TIMESTAMP() - ' . (int) $length . ')
72
				AND t.topic_id <> ' . (int) $topic_id,
73
		);
74
	}
75
76
	/**
77
	 * {@inheritdoc}
78
	 */
79
	public function is_supported()
80
	{
81
		return $this->is_mysql() && $this->supported_engine();
82
	}
83
84
	/**
85
	 * {@inheritdoc}
86
	 */
87
	public function is_fulltext($column = 'topic_title', $table = TOPICS_TABLE)
0 ignored issues
show
The constant vse\similartopics\driver\TOPICS_TABLE was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
88
	{
89
		return in_array($column, $this->get_fulltext_indexes($column, $table), true);
90
	}
91
92
	/**
93
	 * {@inheritdoc}
94
	 */
95
	public function get_fulltext_indexes($column = 'topic_title', $table = TOPICS_TABLE)
0 ignored issues
show
The constant vse\similartopics\driver\TOPICS_TABLE was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
96
	{
97
		$indexes = array();
98
99
		if (!$this->is_supported())
100
		{
101
			return $indexes;
102
		}
103
104
		$sql = 'SHOW INDEX
105
			FROM ' . $this->db->sql_escape($table);
106
		$result = $this->db->sql_query($sql);
107
108
		while ($row = $this->db->sql_fetchrow($result))
109
		{
110
			// Older MySQL versions didn't use Index_type, so fallback to Comment
111
			$index_type = isset($row['Index_type']) ? $row['Index_type'] : $row['Comment'];
112
113
			if ($index_type === 'FULLTEXT' && $row['Key_name'] === $column)
114
			{
115
				$indexes[] = $row['Key_name'];
116
			}
117
		}
118
119
		$this->db->sql_freeresult($result);
120
121
		return $indexes;
122
	}
123
124
	/**
125
	 * {@inheritdoc}
126
	 */
127
	public function create_fulltext_index($column = 'topic_title', $table = TOPICS_TABLE)
0 ignored issues
show
The constant vse\similartopics\driver\TOPICS_TABLE was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
128
	{
129
		if (!$this->is_fulltext($column, $table))
130
		{
131
			// First see if we need to update the table engine to support fulltext indexes
132
			if (!$this->is_supported())
133
			{
134
				$sql = 'ALTER TABLE ' . $this->db->sql_escape($table) . ' ENGINE = MYISAM';
135
				$this->db->sql_query($sql);
136
				$this->set_engine();
137
			}
138
139
			$sql = 'ALTER TABLE ' . $this->db->sql_escape($table) . '
140
				ADD FULLTEXT (' . $this->db->sql_escape($column) . ')';
141
			$this->db->sql_query($sql);
142
		}
143
	}
144
145
	/**
146
	 * {@inheritdoc}
147
	 */
148
	public function get_engine()
149
	{
150
		return $this->engine !== null ? $this->engine : $this->set_engine();
151
	}
152
153
	/**
154
	 * Set the database storage engine name
155
	 *
156
	 * @access protected
157
	 * @return string The storage engine name
158
	 */
159
	protected function set_engine()
160
	{
161
		$this->engine = '';
162
163
		if ($this->is_mysql())
164
		{
165
			$info = $this->get_table_info();
166
167
			// Modern MySQL uses 'Engine', but older may still use 'Type'
168
			foreach (array('Engine', 'Type') as $name)
169
			{
170
				if (isset($info[$name]))
171
				{
172
					$this->engine = strtolower($info[$name]);
173
					break;
174
				}
175
			}
176
		}
177
178
		return $this->engine;
179
	}
180
181
	/**
182
	 * Get topics table information
183
	 *
184
	 * @access protected
185
	 * @param string $table Name of the table
186
	 * @return mixed Array with the table info, false if the table does not exist
187
	 */
188
	protected function get_table_info($table = TOPICS_TABLE)
0 ignored issues
show
The constant vse\similartopics\driver\TOPICS_TABLE was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
189
	{
190
		$result = $this->db->sql_query("SHOW TABLE STATUS LIKE '" . $this->db->sql_escape($table) . "'");
191
		$info = $this->db->sql_fetchrow($result);
192
		$this->db->sql_freeresult($result);
193
194
		return $info;
195
	}
196
197
	/**
198
	 * Check if the database is using MySQL
199
	 *
200
	 * @access public
201
	 * @return bool True if is mysql, false otherwise
202
	 */
203
	protected function is_mysql()
204
	{
205
		return ($this->db->get_sql_layer() === 'mysql4' || $this->db->get_sql_layer() === 'mysqli');
206
	}
207
208
	/**
209
	 * Check if the database engine is supported.
210
	 * FULLTEXT is supported on MyISAM, and also on InnoDB as of MySQL 5.6.4 according
211
	 * to http://dev.mysql.com/doc/refman/5.6/en/innodb-storage-engine.html
212
	 *
213
	 * @return bool True if supported, false otherwise
214
	 */
215
	protected function supported_engine()
216
	{
217
		if ($this->get_engine() === 'myisam')
218
		{
219
			return true;
220
		}
221
222
		if ($this->get_engine() === 'innodb')
223
		{
224
			return phpbb_version_compare($this->db->sql_server_info(true), '5.6.4', '>=');
0 ignored issues
show
The function phpbb_version_compare was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

224
			return /** @scrutinizer ignore-call */ phpbb_version_compare($this->db->sql_server_info(true), '5.6.4', '>=');
Loading history...
225
		}
226
227
		return false;
228
	}
229
}
230