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

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