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

472 lines 12.7 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 global $wpdb;
80
81 if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
82 return;
83 }
84
85 if ( empty( $this->db_version ) ) {
86 $this->install( $this->plugin->get_version() );
87
88 return;
89 }
90
91 if ( $this->plugin->get_version() === $this->db_version ) {
92 return;
93 }
94
95 $update = isset( $_REQUEST['wp_stream_update'] ) ? $_REQUEST['wp_stream_update'] : null;
96
97 if ( ! $update ) {
98 $this->update_required = true;
99 $this->success_db = $this->update( $this->db_version, $this->plugin->get_version(), array( 'type' => 'auto' ) );
100 } elseif ( '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 ( version_compare( end( $versions ), $this->db_version, '>' ) ) {
107 add_action( 'all_admin_notices', array( $this, 'update_notice_hook' ) );
108
109 return;
110 }
111
112 $this->update_db_option();
113 }
114
115 /**
116 * Verify that the required DB tables exists
117 *
118 * @return void
119 */
120 public function verify_db() {
121 /**
122 * Filter will halt install() if set to true
123 *
124 * @param bool
125 *
126 * @return bool
127 */
128 if ( apply_filters( 'wp_stream_no_tables', false ) ) {
129 return;
130 }
131
132 if ( ! function_exists( 'is_plugin_active_for_network' ) ) {
133 require_once( ABSPATH . '/wp-admin/includes/plugin.php' );
134 }
135
136 /**
137 * Fires before admin notices are triggered for missing database tables.
138 */
139 do_action( 'wp_stream_before_db_notices' );
140
141 global $wpdb;
142
143 $database_message = '';
144 $uninstall_message = '';
145
146 // Check if all needed DB is present
147 $missing_tables = array();
148
149 foreach ( $this->plugin->db->get_table_names() as $table_name ) {
150 $table_search = $wpdb->get_var(
151 $wpdb->prepare( 'SHOW TABLES LIKE %s', $table_name )
152 );
153 if ( $table_search !== $table_name ) {
154 $missing_tables[] = $table_name;
155 }
156 }
157
158 if ( $missing_tables ) {
159 $database_message .= sprintf(
160 '%s <strong>%s</strong>',
161 _n(
162 'The following table is not present in the WordPress database:',
163 'The following tables are not present in the WordPress database:',
164 count( $missing_tables ),
165 'stream'
166 ),
167 esc_html( implode( ', ', $missing_tables ) )
168 );
169 }
170
171 if ( is_plugin_active_for_network( $this->plugin->locations['plugin'] ) && current_user_can( 'manage_network_plugins' ) ) {
172 $uninstall_message = sprintf( __( 'Please <a href="%s">uninstall</a> the Stream plugin and activate it again.', 'stream' ), network_admin_url( 'plugins.php#stream' ) );
173 } elseif ( current_user_can( 'activate_plugins' ) ) {
174 $uninstall_message = sprintf( __( 'Please <a href="%s">uninstall</a> the Stream plugin and activate it again.', 'stream' ), admin_url( 'plugins.php#stream' ) );
175 }
176
177 if ( ! empty( $database_message ) ) {
178 $this->plugin->admin->notice( $database_message );
179
180 if ( ! empty( $uninstall_message ) ) {
181 $this->plugin->admin->notice( $uninstall_message );
182 }
183 }
184 }
185
186 /**
187 * Register a routine to be called when stream or a stream connector has been updated
188 * It works by comparing the current version with the version previously stored in the database.
189 *
190 * @param string $file A reference to the main plugin file
191 * @param string $callback The function to run when the hook is called.
192 * @param string $version The version to which the plugin is updating.
193 *
194 * @return void
195 */
196 public function register_update_hook( $file, $callback, $version ) {
197 if ( ! is_admin() ) {
198 return;
199 }
200
201 $plugin = plugin_basename( $file );
202
203 if ( is_plugin_active_for_network( $plugin ) ) {
204 $current_versions = get_site_option( $this->option_key . '_connectors', array() );
205 $network = true;
206 } elseif ( is_plugin_active( $plugin ) ) {
207 $current_versions = get_option( $this->option_key . '_connectors', array() );
208 $network = false;
209 } else {
210 return;
211 }
212
213 if ( version_compare( $version, $current_versions[ $plugin ], '>' ) ) {
214 call_user_func( $callback, $current_versions[ $plugin ], $network );
215
216 $current_versions[ $plugin ] = $version;
217 }
218
219 if ( $network ) {
220 update_site_option( $this->option_key . '_registered_connectors', $current_versions );
221 } else {
222 update_option( $this->option_key . '_registered_connectors', $current_versions );
223 }
224
225 return;
226 }
227
228 /**
229 * @return string
230 */
231 public function get_db_version() {
232 return get_site_option( $this->option_key );
233 }
234
235 /**
236 * @return void
237 */
238 public function update_db_option() {
239 if ( $this->success_db ) {
240 $success_op = update_site_option( $this->option_key, $this->plugin->get_version() );
241 }
242
243 if ( ! empty( $this->success_db ) && ! empty( $success_op ) ) {
244 return;
245 }
246
247 wp_die(
248 esc_html__( 'There was an error updating the Stream database. Please try again.', 'stream' ),
249 esc_html__( 'Database Update Error', 'stream' ),
250 array(
251 'response' => 200,
252 'back_link' => 1,
253 )
254 );
255 }
256
257 /**
258 * Added to the admin_notices hook when file plugin version is higher than database plugin version
259 *
260 * @action admin_notices
261 *
262 * @return void
263 */
264 public function update_notice_hook() {
265 if ( ! current_user_can( $this->plugin->admin->view_cap ) ) {
266 return;
267 }
268
269 $update = isset( $_REQUEST['wp_stream_update'] ) ? $_REQUEST['wp_stream_update'] : null;
270
271 if ( ! $update ) {
272 $this->prompt_update();
273
274 return;
275 }
276
277 if ( 'update_and_continue' === $update ) {
278 $this->prompt_update_status();
279 }
280 }
281
282 /**
283 * Action hook callback function
284 *
285 * Adds the user controlled database upgrade routine to the plugins updated page.
286 * When database update is complete page will refresh with dismissible message to user.
287 *
288 * @return void
289 */
290 public function prompt_update() {
291 ?>
292 <div class="error">
293 <form method="post" action="<?php echo esc_url( remove_query_arg( 'wp_stream_update' ) ) ?>">
294 <?php wp_nonce_field( 'wp_stream_update_db' ) ?>
295 <input type="hidden" name="wp_stream_update" value="update_and_continue"/>
296 <p><strong><?php esc_html_e( 'Stream Database Update Required', 'stream' ) ?></strong></p>
297 <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>
298 <p><?php esc_html_e( 'This process could take a little while, so please be patient.', 'stream' ) ?></p>
299 <?php submit_button( esc_html__( 'Update Database', 'stream' ), 'primary', 'stream-update-db-submit' ) ?>
300 </form>
301 </div>
302 <?php
303 }
304
305 /**
306 * When user initiates a database update this function calls the update methods, checks for success
307 * updates the stream_db version number in the database and outputs a success and continue message
308 *
309 * @return void
310 */
311 public function prompt_update_status() {
312 check_admin_referer( 'wp_stream_update_db' );
313
314 $this->update_db_option();
315 ?>
316 <div class="updated">
317 <form method="post" action="<?php echo esc_url( remove_query_arg( 'wp_stream_update' ) ) ?>" style="display:inline;">
318 <p><strong><?php esc_html_e( 'Update Complete', 'stream' ) ?></strong></p>
319 <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( $this->plugin->get_version() ) ), 'stream' ) ?></p>
320 <?php submit_button( esc_html__( 'Continue', 'stream' ), 'secondary', false ) ?>
321 </form>
322 </div>
323 <?php
324 }
325
326 /**
327 * Array of database versions that require and updates
328 *
329 * To add your own stream extension database update routine
330 * use the filter and return the version that requires an update
331 * You must also make the callback function available in the global namespace on plugins loaded
332 * use the wp_stream_update_{version_number} version number must be a string of characters that represent the version with no periods
333 *
334 * @return array
335 */
336 public function db_update_versions() {
337 $db_update_versions = array(
338 '3.0.0' /* @version 3.0.0 Drop the stream_context table, changes to stream table */,
339 '3.0.2' /* @version 3.0.2 Fix uppercase values in stream table, connector 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(20) 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