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

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