These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | /** |
||
3 | * This file contains only a single class. |
||
4 | * |
||
5 | * @file |
||
6 | * @package Tabulate |
||
7 | */ |
||
8 | |||
9 | namespace WordPress\Tabulate\DB; |
||
10 | |||
11 | /** |
||
12 | * The database class represents the entire MySQL database that WordPress uses. |
||
13 | */ |
||
14 | class Database { |
||
15 | |||
16 | /** |
||
17 | * The global wpdb object. |
||
18 | * |
||
19 | * @var \wpdb |
||
20 | */ |
||
21 | protected $wpdb; |
||
22 | |||
23 | /** |
||
24 | * A list of all table names. |
||
25 | * |
||
26 | * @var string[] |
||
27 | */ |
||
28 | protected $table_names; |
||
29 | |||
30 | /** |
||
31 | * The filesystem. |
||
32 | * |
||
33 | * @var \WP_Filesystem_Base |
||
34 | */ |
||
35 | protected $filesystem; |
||
36 | |||
37 | /** |
||
38 | * The list of all tables that the user can read. |
||
39 | * |
||
40 | * @var Table[] |
||
41 | */ |
||
42 | protected $tables; |
||
43 | |||
44 | /** |
||
45 | * Create a new Database object based on the given wpdb object. |
||
46 | * |
||
47 | * @param \wpdb $wpdb The global wpdb object. |
||
48 | */ |
||
49 | public function __construct( $wpdb ) { |
||
50 | $this->wpdb = $wpdb; |
||
51 | } |
||
52 | |||
53 | /** |
||
54 | * Set the filesystem. |
||
55 | * |
||
56 | * @param \WP_Filesystem_Base $filesystem The filesystem object. |
||
57 | */ |
||
58 | public function set_filesystem( \WP_Filesystem_Base $filesystem ) { |
||
59 | $this->filesystem = $filesystem; |
||
60 | } |
||
61 | |||
62 | /** |
||
63 | * Get the filesystem. |
||
64 | * |
||
65 | * @return \WP_Filesystem_Base |
||
66 | */ |
||
67 | public function get_filesystem() { |
||
68 | return $this->filesystem; |
||
69 | } |
||
70 | |||
71 | /** |
||
72 | * Get the global wpdb object. |
||
73 | * |
||
74 | * @return \wpdb |
||
75 | */ |
||
76 | public function get_wpdb() { |
||
77 | return $this->wpdb; |
||
78 | } |
||
79 | |||
80 | /** |
||
81 | * Get a list of tables and views that the current user can read. |
||
82 | * |
||
83 | * @return string[] The table names. |
||
84 | */ |
||
85 | public function get_table_names() { |
||
86 | if ( ! $this->table_names ) { |
||
0 ignored issues
–
show
|
|||
87 | $this->table_names = array(); |
||
88 | foreach ( $this->wpdb->get_col( 'SHOW TABLES' ) as $table_name ) { |
||
89 | if ( Grants::current_user_can( Grants::READ, $table_name ) ) { |
||
90 | $this->table_names[ $table_name ] = $table_name; |
||
91 | } |
||
92 | } |
||
93 | } |
||
94 | return $this->table_names; |
||
95 | } |
||
96 | |||
97 | /** |
||
98 | * Get a table from the database. |
||
99 | * |
||
100 | * @param string $name The name of the desired table. |
||
101 | * @return \WordPress\Tabulate\DB\Table|false The table, or false if it's not available. |
||
102 | */ |
||
103 | public function get_table( $name ) { |
||
104 | if ( ! in_array( $name, $this->get_table_names(), true ) ) { |
||
105 | return false; |
||
106 | } |
||
107 | if ( ! isset( $this->tables[ $name ] ) ) { |
||
108 | $this->tables[ $name ] = new Table( $this, $name ); |
||
109 | } |
||
110 | return $this->tables[ $name ]; |
||
111 | } |
||
112 | |||
113 | /** |
||
114 | * Forget all table information, forcing it to be re-read from the database |
||
115 | * when next required. Used after schema changes. |
||
116 | */ |
||
117 | public function reset() { |
||
118 | $this->table_names = false; |
||
119 | $this->tables = false; |
||
120 | } |
||
121 | |||
122 | /** |
||
123 | * Get all tables in this database. |
||
124 | * |
||
125 | * @param boolean $exclude_views Whether to exclude database views from the returned list. |
||
126 | * @return Table[] An array of all Tables. |
||
127 | */ |
||
128 | public function get_tables( $exclude_views = true ) { |
||
129 | $out = array(); |
||
130 | foreach ( $this->get_table_names() as $name ) { |
||
131 | $table = $this->get_table( $name ); |
||
132 | // If this table is not available, skip it. |
||
133 | if ( ! $table ) { |
||
134 | continue; |
||
135 | } |
||
136 | if ( $exclude_views && $table->is_view() ) { |
||
137 | continue; |
||
138 | } |
||
139 | $out[ $table->get_name() ] = $table; |
||
140 | } |
||
141 | return $out; |
||
142 | } |
||
143 | |||
144 | /** |
||
145 | * Get all views in this database. |
||
146 | * |
||
147 | * @return Table|array An array of all Tables that are views. |
||
148 | */ |
||
149 | public function get_views() { |
||
150 | $out = array(); |
||
151 | foreach ( $this->get_tables( false ) as $table ) { |
||
152 | if ( $table->is_view() ) { |
||
153 | $out[ $table->get_name() ] = $table; |
||
154 | } |
||
155 | } |
||
156 | return $out; |
||
157 | } |
||
158 | |||
159 | /** |
||
160 | * Create a new table. |
||
161 | * |
||
162 | * @param string $name The name of the new table. |
||
163 | * @param string $comment The table comment. |
||
164 | * @throws Exception If the current user cannot 'promote_users'. |
||
165 | */ |
||
166 | public function create_table( $name, $comment = '' ) { |
||
167 | if ( ! current_user_can( 'promote_users' ) ) { |
||
168 | throw new Exception( 'Only administrators are allowed to create tables' ); |
||
169 | } |
||
170 | $sql = "CREATE TABLE IF NOT EXISTS `$name` ( " |
||
171 | . " `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY " |
||
172 | . ") ENGINE=InnoDB, COMMENT='$comment';"; |
||
173 | $this->query( $sql ); |
||
174 | $this->reset(); |
||
175 | return $this->get_table( $name ); |
||
176 | } |
||
177 | |||
178 | /** |
||
179 | * A wrapper around wpdb::prepare() and wpdb::query() |
||
180 | * that also checks wpdb::$last_error and throws up on occasion of badness. |
||
181 | * |
||
182 | * @param string $sql The SQL statement to execute. |
||
183 | * @param string[] $params Parameters to pass to wpdb::prepare(). |
||
184 | * @param string $error_message What to tell the user if this query fails. |
||
185 | * @throws Exception The exception message is taken from wpdb::$last_error and if WP_DEBUG is set will also include the erroneous SQL. |
||
186 | */ |
||
187 | public function query( $sql, $params = null, $error_message = null ) { |
||
188 | if ( $params ) { |
||
189 | $sql = $this->get_wpdb()->prepare( $sql, $params ); |
||
190 | } |
||
191 | $this->get_wpdb()->query( $sql ); |
||
192 | if ( ! empty( $this->get_wpdb()->last_error ) ) { |
||
193 | $msg = $error_message . ': ' . $this->get_wpdb()->last_error; |
||
194 | if ( WP_DEBUG ) { |
||
195 | $msg .= " <code>$sql</code>"; |
||
196 | } |
||
197 | throw new Exception( $msg ); |
||
198 | } |
||
199 | } |
||
200 | |||
201 | /** |
||
202 | * Get the name of the directory to which MySQL will write temporary export files. |
||
203 | * This is either the value of the 'secure_file_priv' server variable, |
||
204 | * or WordPress's normal temporary directory as returned by get_temp_dir(). |
||
205 | * Always has a trailing slash. |
||
206 | * |
||
207 | * @return string Full path of the directory. |
||
208 | * @throws Exception If the directory is not writable. |
||
209 | */ |
||
210 | public function get_tmp_dir() { |
||
211 | $query = "SHOW VARIABLES LIKE 'secure_file_priv';"; |
||
212 | $db_dir = $this->get_wpdb()->get_var( $query, 1 ); |
||
213 | $dir = empty( $db_dir ) ? get_temp_dir() : $db_dir; |
||
214 | $out = rtrim( $dir, '/' ) . '/'; |
||
215 | if ( ! $this->get_filesystem()->is_writable( $out ) ) { |
||
216 | throw new Exception( "Unable to write to temporary directory $out" ); |
||
217 | } |
||
218 | return $out; |
||
219 | } |
||
220 | } |
||
221 |
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.
Consider making the comparison explicit by using
empty(..)
or! empty(...)
instead.