PluginProbe
Stream – Activity Log & Audit Trail / 3.3.0
Stream – Activity Log & Audit Trail v3.3.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.3.0, at classes/class-install.php

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