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

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