PluginProbe
Stream – Activity Log & Audit Trail / 3.6.0
Stream – Activity Log & Audit Trail v3.6.0
4.4.0 4.3.0 4.2.2 4.2.1 trunk 2.0.1 2.0.2 2.0.3 2.0.4 2.0.5 3.0.0 3.0.1 3.0.2 3.0.3 3.0.4 3.0.5 3.0.6 3.0.7 3.1 3.1.1 3.10.0 3.2.0 3.2.1 3.2.2 3.2.3 All 50 releases
stream / classes / class-install.php

class-install.php in Stream – Activity Log & Audit Trail 3.6.0, at classes/class-install.php

520 lines 13.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Handles database migrations
4 *
5 * @package WP_Stream
6 */
7
8 namespace WP_Stream;
9
10 /**
11 * Class - Install
12 */
13 class Install {
14 /**
15 * Holds Instance of plugin object
16 *
17 * @var Plugin
18 */
19 public $plugin;
20
21 /**
22 * Option key to store database version
23 *
24 * @var string
25 */
26 public $option_key = 'wp_stream_db';
27
28 /**
29 * Holds version of database at last update
30 *
31 * @var string
32 */
33 public $db_version;
34
35 /**
36 * URL to the Stream Admin settings page.
37 *
38 * @var string
39 */
40 public $stream_url;
41
42 /**
43 * Array of version numbers that require database update
44 *
45 * @var array
46 */
47 public $update_versions;
48
49 /**
50 * Holds status of whether it's safe to run Stream or not
51 *
52 * @var bool
53 */
54 public $update_required = false;
55
56 /**
57 * Holds status of whether the database update worked
58 *
59 * @var bool
60 */
61 public $success_db;
62
63 /**
64 * Class constructor
65 *
66 * @param Plugin $plugin Instance of plugin object.
67 */
68 public function __construct( $plugin ) {
69 $this->plugin = $plugin;
70
71 $this->db_version = $this->get_db_version();
72 $this->stream_url = self_admin_url( $this->plugin->admin->admin_parent_page . '&page=' . $this->plugin->admin->settings_page_slug );
73
74 // Check DB and display an admin notice if there are tables missing.
75 add_action( 'init', array( $this, 'verify_db' ) );
76
77 // Install the plugin.
78 add_action( 'wp_stream_before_db_notices', array( $this, 'check' ) );
79
80 register_activation_hook( $this->plugin->locations['plugin'], array( $this, 'check' ) );
81 }
82
83 /**
84 * Check db version, create/update table schema accordingly
85 * If database update required admin notice will be given
86 * on the plugin update screen
87 *
88 * @return void
89 */
90 public function check() {
91 if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
92 return;
93 }
94
95 if ( empty( $this->db_version ) ) {
96 $this->install( $this->plugin->get_version() );
97 return;
98 }
99
100 if ( $this->plugin->get_version() === $this->db_version ) {
101 return;
102 }
103
104 $update = null;
105 if ( isset( $_REQUEST['wp_stream_update'] ) && wp_verify_nonce( 'wp_stream_update_db' ) ) {
106 $update = esc_attr( $_REQUEST['wp_stream_update'] );
107 }
108
109 if ( ! $update ) {
110 $this->update_required = true;
111 $this->success_db = $this->update(
112 $this->db_version,
113 $this->plugin->get_version(),
114 array(
115 'type' => 'auto',
116 )
117 );
118 }
119
120 if ( 'update_and_continue' === $update ) {
121 $this->success_db = $this->update(
122 $this->db_version,
123 $this->plugin->get_version(),
124 array(
125 'type' => 'user',
126 )
127 );
128 }
129
130 $versions = $this->db_update_versions();
131
132 if ( ! $this->success_db && version_compare( end( $versions ), $this->db_version, '>' ) ) {
133 add_action( 'all_admin_notices', array( $this, 'update_notice_hook' ) );
134 return;
135 }
136
137 $this->update_db_option();
138 }
139
140 /**
141 * Verify that the required DB tables exists
142 *
143 * @return void
144 */
145 public function verify_db() {
146 /**
147 * Filter will halt install() if set to true
148 *
149 * @param bool
150 *
151 * @return bool
152 */
153 if ( apply_filters( 'wp_stream_no_tables', false ) ) {
154 return;
155 }
156
157 if ( ! function_exists( 'is_plugin_active_for_network' ) ) {
158 require_once ABSPATH . '/wp-admin/includes/plugin.php';
159 }
160
161 /**
162 * Fires before admin notices are triggered for missing database tables.
163 */
164 do_action( 'wp_stream_before_db_notices' );
165
166 global $wpdb;
167
168 $database_message = '';
169 $uninstall_message = '';
170
171 // Check if all needed DB is present.
172 $missing_tables = array();
173
174 foreach ( $this->plugin->db->get_table_names() as $table_name ) {
175 $table_search = $wpdb->get_var(
176 $wpdb->prepare( 'SHOW TABLES LIKE %s', $table_name )
177 );
178 if ( $table_search !== $table_name ) {
179 $missing_tables[] = $table_name;
180 }
181 }
182
183 if ( $missing_tables ) {
184 $database_message .= sprintf(
185 '%s <strong>%s</strong>',
186 _n(
187 'The following table is not present in the WordPress database:',
188 'The following tables are not present in the WordPress database:',
189 count( $missing_tables ),
190 'stream'
191 ),
192 esc_html( implode( ', ', $missing_tables ) )
193 );
194 }
195
196 if ( $this->plugin->is_network_activated() && current_user_can( 'manage_network_plugins' ) ) {
197 $uninstall_message = sprintf(
198 /* translators: %#$s: HTML Link tags (e.g. "<a href="https://foo.com/wp-admin/">") */
199 __( 'Please %1$suninstall%2$s the Stream plugin and activate it again.', 'stream' ),
200 '<a href="' . network_admin_url( 'plugins.php#stream' ) . '">',
201 '</a>'
202 );
203 } elseif ( current_user_can( 'activate_plugins' ) ) {
204 $uninstall_message = sprintf(
205 /* translators: %#$s: HTML Link tags (e.g. "<a href="https://foo.com/wp-admin/">") */
206 __( 'Please %1$suninstall%2$s the Stream plugin and activate it again.', 'stream' ),
207 '<a href="' . admin_url( 'plugins.php#stream' ) . '">',
208 '</a>'
209 );
210 }
211
212 if ( ! empty( $database_message ) ) {
213 $this->plugin->admin->notice( $database_message );
214
215 if ( ! empty( $uninstall_message ) ) {
216 $this->plugin->admin->notice( $uninstall_message );
217 }
218 }
219 }
220
221 /**
222 * Register a routine to be called when stream or a stream connector has been updated
223 * It works by comparing the current version with the version previously stored in the database.
224 *
225 * @param string $file A reference to the main plugin file.
226 * @param string $callback The function to run when the hook is called.
227 * @param string $version The version to which the plugin is updating.
228 *
229 * @return void
230 */
231 public function register_update_hook( $file, $callback, $version ) {
232 if ( ! is_admin() ) {
233 return;
234 }
235
236 $plugin = plugin_basename( $file );
237
238 if ( $this->plugin->is_network_activated() ) {
239 $current_versions = get_site_option( $this->option_key . '_connectors', array() );
240 $network = true;
241 } elseif ( is_plugin_active( $plugin ) ) {
242 $current_versions = get_option( $this->option_key . '_connectors', array() );
243 $network = false;
244 } else {
245 return;
246 }
247
248 if ( version_compare( $version, $current_versions[ $plugin ], '>' ) ) {
249 call_user_func( $callback, $current_versions[ $plugin ], $network );
250
251 $current_versions[ $plugin ] = $version;
252 }
253
254 if ( $network ) {
255 update_site_option( $this->option_key . '_registered_connectors', $current_versions );
256 } else {
257 update_option( $this->option_key . '_registered_connectors', $current_versions );
258 }
259 }
260
261 /**
262 * Returns the database version.
263 *
264 * @return string
265 */
266 public function get_db_version() {
267 return get_site_option( $this->option_key );
268 }
269
270 /**
271 * Checks if migration was successful.
272 */
273 public function update_db_option() {
274 if ( $this->success_db ) {
275 $success_op = update_site_option( $this->option_key, $this->plugin->get_version() );
276 }
277
278 if ( ! empty( $this->success_db ) ) {
279 return;
280 }
281
282 wp_die(
283 esc_html__( 'There was an error updating the Stream database. Please try again.', 'stream' ),
284 esc_html__( 'Database Update Error', 'stream' ),
285 array(
286 'response' => 200,
287 'back_link' => 1,
288 )
289 );
290 }
291
292 /**
293 * Added to the admin_notices hook when file plugin version is higher than database plugin version
294 *
295 * @action admin_notices
296 *
297 * @return void
298 */
299 public function update_notice_hook() {
300 if ( ! current_user_can( $this->plugin->admin->view_cap ) ) {
301 return;
302 }
303
304 $update = null;
305 if ( isset( $_REQUEST['wp_stream_update'] ) && wp_verify_nonce( 'wp_stream_update_db' ) ) {
306 $update = esc_attr( $_REQUEST['wp_stream_update'] );
307 }
308
309 if ( ! $update ) {
310 $this->prompt_update();
311
312 return;
313 }
314
315 if ( 'update_and_continue' === $update ) {
316 $this->prompt_update_status();
317 }
318 }
319
320 /**
321 * Action hook callback function
322 *
323 * Adds the user controlled database upgrade routine to the plugins updated page.
324 * When database update is complete page will refresh with dismissible message to user.
325 *
326 * @return void
327 */
328 public function prompt_update() {
329 ?>
330 <div class="error">
331 <form method="post" action="<?php echo esc_url( remove_query_arg( 'wp_stream_update' ) ); ?>">
332 <?php wp_nonce_field( 'wp_stream_update_db' ); ?>
333 <input type="hidden" name="wp_stream_update" value="update_and_continue"/>
334 <p><strong><?php esc_html_e( 'Stream Database Update Required', 'stream' ); ?></strong></p>
335 <p><?php esc_html_e( 'Stream has updated! Before we send you on your way, we need to update your database to the newest version.', 'stream' ); ?></p>
336 <p><?php esc_html_e( 'This process could take a little while, so please be patient.', 'stream' ); ?></p>
337 <?php submit_button( esc_html__( 'Update Database', 'stream' ), 'primary', 'stream-update-db-submit' ); ?>
338 </form>
339 </div>
340 <?php
341 }
342
343 /**
344 * When user initiates a database update this function calls the update methods, checks for success
345 * updates the stream_db version number in the database and outputs a success and continue message
346 *
347 * @return void
348 */
349 public function prompt_update_status() {
350 check_admin_referer( 'wp_stream_update_db' );
351
352 $this->update_db_option();
353 ?>
354 <div class="updated">
355 <form method="post" action="<?php echo esc_url( remove_query_arg( 'wp_stream_update' ) ); ?>" style="display:inline;">
356 <p><strong><?php esc_html_e( 'Update Complete', 'stream' ); ?></strong></p>
357 <p>
358 <?php
359 printf(
360 /* translators: %1$s: old version, %2$s: new version (e.g. "4.2") */
361 esc_html__( 'Your Stream database has been successfully updated from %1$s to %2$s!', 'stream' ),
362 esc_html( $this->db_version ),
363 esc_html( $this->plugin->get_version() )
364 );
365 ?>
366 </p>
367 <?php submit_button( esc_html__( 'Continue', 'stream' ), 'secondary', false ); ?>
368 </form>
369 </div>
370 <?php
371 }
372
373 /**
374 * Array of database versions that require and updates
375 *
376 * To add your own stream extension database update routine
377 * use the filter and return the version that requires an update
378 * You must also make the callback function available in the global namespace on plugins loaded
379 * use the wp_stream_update_{version_number} version number must be a string of characters that represent the version with no periods
380 *
381 * @return array
382 */
383 public function db_update_versions() {
384 $db_update_versions = array(
385 '3.0.0', /* @version 3.0.0 Drop the stream_context table, changes to stream table */
386 '3.0.2', /* @version 3.0.2 Fix uppercase values in stream table, connector column */
387 '3.0.8', /* @version 3.0.8 Increase size of user role IDs, user_roll column */
388 );
389
390 /**
391 * Filter to alter the DB update versions array
392 *
393 * @param array $db_update_versions
394 *
395 * @return array
396 */
397 return apply_filters( 'wp_stream_db_update_versions', $db_update_versions );
398 }
399
400 /**
401 * Database user controlled update routine
402 *
403 * @param int $db_version Next database version.
404 * @param int $current_version Current database version.
405 * @param array $update_args Update options.
406 *
407 * @return mixed Version number on success, true on no update needed, mysql error message on error
408 */
409 public function update( $db_version, $current_version, $update_args ) {
410 $versions = $this->db_update_versions();
411 include_once $this->plugin->locations['inc_dir'] . 'db-updates.php';
412
413 foreach ( $versions as $version ) {
414 if ( ! isset( $update_args['type'] ) ) {
415 $update_args['type'] = 'user';
416 }
417
418 $function = 'wp_stream_update_' . ( 'user' === $update_args['type'] ? '' : $update_args['type'] . '_' ) . str_ireplace( '.', '', $version );
419
420 if ( version_compare( $db_version, $version, '<' ) ) {
421 $result = function_exists( $function ) ? call_user_func( $function, $db_version, $current_version ) : $current_version;
422
423 if ( $current_version !== $result ) {
424 return false;
425 }
426 }
427 }
428
429 return $current_version;
430 }
431
432 /**
433 * Initial database install routine
434 *
435 * @param string $current_version Current database version.
436 *
437 * @return string
438 */
439 public function install( $current_version ) {
440 global $wpdb;
441
442 require_once ABSPATH . 'wp-admin/includes/upgrade.php';
443
444 $sql = "CREATE TABLE {$wpdb->base_prefix}stream (
445 ID bigint(20) unsigned NOT NULL AUTO_INCREMENT,
446 site_id bigint(20) unsigned NOT NULL DEFAULT '1',
447 blog_id bigint(20) unsigned NOT NULL DEFAULT '1',
448 object_id bigint(20) unsigned NULL,
449 user_id bigint(20) unsigned NOT NULL DEFAULT '0',
450 user_role varchar(50) NOT NULL DEFAULT '',
451 summary longtext NOT NULL,
452 created datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
453 connector varchar(100) NOT NULL,
454 context varchar(100) NOT NULL,
455 action varchar(100) NOT NULL,
456 ip varchar(39) NULL,
457 PRIMARY KEY (ID),
458 KEY site_id (site_id),
459 KEY blog_id (blog_id),
460 KEY object_id (object_id),
461 KEY user_id (user_id),
462 KEY created (created),
463 KEY connector (connector),
464 KEY context (context),
465 KEY action (action)
466 )";
467
468 if ( ! empty( $wpdb->charset ) ) {
469 $sql .= " CHARACTER SET $wpdb->charset";
470 }
471
472 if ( ! empty( $wpdb->collate ) ) {
473 $sql .= " COLLATE $wpdb->collate";
474 }
475
476 $sql .= ';';
477
478 \dbDelta( $sql );
479
480 if ( ! empty( $wpdb->charset ) ) {
481 $sql .= " CHARACTER SET $wpdb->charset";
482 }
483
484 if ( ! empty( $wpdb->collate ) ) {
485 $sql .= " COLLATE $wpdb->collate";
486 }
487
488 $sql .= ';';
489
490 \dbDelta( $sql );
491
492 $sql = "CREATE TABLE {$wpdb->base_prefix}stream_meta (
493 meta_id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
494 record_id bigint(20) unsigned NOT NULL,
495 meta_key varchar(200) NOT NULL,
496 meta_value varchar(200) NOT NULL,
497 PRIMARY KEY (meta_id),
498 KEY record_id (record_id),
499 KEY meta_key (meta_key(191)),
500 KEY meta_value (meta_value(191))
501 )";
502
503 if ( ! empty( $wpdb->charset ) ) {
504 $sql .= " CHARACTER SET $wpdb->charset";
505 }
506
507 if ( ! empty( $wpdb->collate ) ) {
508 $sql .= " COLLATE $wpdb->collate";
509 }
510
511 $sql .= ';';
512
513 \dbDelta( $sql );
514
515 update_site_option( $this->option_key, $this->plugin->get_version() );
516
517 return $current_version;
518 }
519 }
520