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

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