Plugin Directory

Changeset 2980355


Ignore:
Timestamp:
10/17/2023 09:39:00 PM (2 years ago)
Author:
getpantheon
Message:

Update to version 1.4.0 from GitHub

Location:
wp-native-php-sessions
Files:
14 edited
1 copied

Legend:

Unmodified
Added
Removed
  • wp-native-php-sessions/tags/1.4.0/inc/class-admin.php

    r2920329 r2980355  
    136136        <?php
    137137    }
    138 
    139138}
  • wp-native-php-sessions/tags/1.4.0/inc/class-cli-command.php

    r2920329 r2980355  
    8080    }
    8181
     82    /**
     83     * Set id as primary key in the Native PHP Sessions plugin table.
     84     *
     85     * @subcommand add-index
     86     */
     87    public function add_index( $args, $assoc_arc ) {
     88        $pantheon_session = new \Pantheon_Sessions();
     89        $pantheon_session->add_index();
     90    }
     91
     92    /**
     93     * Finalizes the creation of a primary key by deleting the old data.
     94     *
     95     * @subcommand primary-key-finalize
     96     */
     97    public function primary_key_finalize() {
     98        $pan_session = new \Pantheon_Sessions();
     99        $pan_session->primary_key_finalize();
     100    }
     101
     102    /**
     103     * Reverts addition of primary key.
     104     *
     105     * @subcommand primary-key-revert
     106     */
     107    public function primary_key_revert() {
     108        $pan_session = new \Pantheon_Sessions();
     109        $pan_session->primary_key_revert();
     110    }
    82111}
    83112
  • wp-native-php-sessions/tags/1.4.0/inc/class-list-table.php

    r2920329 r2980355  
    4343     */
    4444    public function no_items() {
    45         _e( 'No sessions found.', 'wp-native-php-sessions' );
     45        esc_html_e( 'No sessions found.', 'wp-native-php-sessions' );
    4646    }
    4747
     
    8585        }
    8686    }
    87 
    8887}
  • wp-native-php-sessions/tags/1.4.0/inc/class-session-handler.php

    r2861737 r2980355  
    124124        return true;
    125125    }
    126 
    127126}
  • wp-native-php-sessions/tags/1.4.0/inc/class-session.php

    r2920329 r2980355  
    320320        }
    321321    }
    322 
    323322}
  • wp-native-php-sessions/tags/1.4.0/pantheon-sessions.php

    r2920329 r2980355  
    22/**
    33 * Plugin Name: Native PHP Sessions for WordPress
    4  * Version: 1.3.6
     4 * Version: 1.4.0
    55 * Description: Offload PHP's native sessions to your database for multi-server compatibility.
    66 * Author: Pantheon
     
    1414use Pantheon_Sessions\Session;
    1515
    16 define( 'PANTHEON_SESSIONS_VERSION', '1.3.6' );
     16define( 'PANTHEON_SESSIONS_VERSION', '1.4.0' );
    1717
    1818/**
     
    5050
    5151    /**
    52      * Load the plugin
     52     * Load the plugin.
    5353     */
    5454    private function load() {
     
    179179                        /* translators: %1s: File path, %2d: Line number */
    180180                        __( "Oops! The wp-native-php-sessions plugin couldn't start the session because output has already been sent. This might be caused by PHP throwing errors. Please check the code in %1s on line %2d.", 'wp-native-php-sessions' ),
    181                         $file,
    182                         $line
     181                        esc_html( $file ),
     182                        esc_html( $line )
    183183                    ),
    184184                    E_USER_WARNING
     
    262262        }
    263263    }
     264
     265    /**
     266     * Checks whether primary keys were set and notifies users if not.
     267     */
     268    public static function check_native_primary_keys() {
     269        global $wpdb;
     270        $table_name = $wpdb->base_prefix . 'pantheon_sessions';
     271        $old_table  = $wpdb->base_prefix . 'bak_pantheon_sessions';
     272        $query      = "SHOW KEYS FROM {$table_name} WHERE key_name = 'PRIMARY';";
     273
     274        $key_existence = $wpdb->get_results( $query );
     275
     276        if ( empty( $key_existence ) ) {
     277            // If the key doesn't exist, recommend remediation.
     278            ?>
     279            <div class="notice notice-error is-dismissible">
     280                <p>
     281                <?php
     282                print wp_kses_post( __( 'Your PHP Native Sessions table is missing a primary key. Please run <code>wp pantheon session add-index</code> and verify that the process completes successfully and that this message goes away to resolve this issue on your live environment.', 'wp-native-php-sessions' ) );
     283                ?>
     284                        </p>
     285            </div>
     286            <?php
     287        }
     288
     289        $query = $wpdb->prepare( 'SHOW TABLES LIKE %s',
     290        $wpdb->esc_like( $old_table ) );
     291
     292        // Check for table existence and delete if present.
     293        if ( $wpdb->get_var( $query ) == $old_table ) {
     294            // If an old table exists but has not been removed, suggest doing so.
     295            ?>
     296            <div class="notice notice-error">
     297                <p>
     298                <?php
     299                print wp_kses_post( __( 'An old version of the PHP Native Sessions table is detected. When testing is complete, run <code>wp pantheon session primary-key-finalize</code> to clean up old data, or run <code>wp pantheon session primary-key-revert</code> if there were issues.', 'wp-native-php-sessions' ) );
     300                ?>
     301                        </p>
     302            </div>
     303            <?php
     304        }
     305    }
     306
     307    /**
     308     * Set id as primary key in the Native PHP Sessions plugin table.
     309     */
     310    public function add_index() {
     311        global $wpdb;
     312        $unprefixed_table = 'pantheon_sessions';
     313        $table            = $wpdb->base_prefix . $unprefixed_table;
     314        $temp_clone_table = $wpdb->base_prefix . 'sessions_temp_clone';
     315
     316        // If the command has been run multiple times and there is already a
     317        // temp_clone table, drop it.
     318        $query = $wpdb->prepare( 'SHOW TABLES LIKE %s', $wpdb->esc_like( $temp_clone_table ) );
     319
     320        if ( $wpdb->get_var( $query ) == $temp_clone_table ) {
     321            $query = "DROP TABLE {$temp_clone_table};";
     322            $wpdb->query( $query );
     323        }
     324
     325        if ( ! PANTHEON_SESSIONS_ENABLED ) {
     326            $this->safe_output( __( 'Pantheon Sessions is currently disabled.', 'wp-native-php-sessions' ), 'error' );
     327        }
     328
     329        // Verify that the ID column/primary key does not already exist.
     330        $query         = "SHOW KEYS FROM {$table} WHERE key_name = 'PRIMARY';";
     331        $key_existence = $wpdb->get_results( $query );
     332
     333        // Avoid errors by not attempting to add a column that already exists.
     334        if ( ! empty( $key_existence ) ) {
     335            $this->safe_output( __( 'ID column already exists and does not need to be added to the table.', 'wp-native-php-sessions' ), 'error' );
     336        }
     337
     338        // Alert the user that the action is going to go through.
     339        $this->safe_output( __( 'Primary Key does not exist, resolution starting.', 'wp-native-php-sessions' ), 'log' );
     340
     341        $count_query = "SELECT COUNT(*) FROM {$table};";
     342        $count_total = $wpdb->get_results( $count_query );
     343        $count_total = $count_total[0]->{'COUNT(*)'};
     344
     345        if ( $count_total >= 20000 ) {
     346            // translators: %s is the total number of rows that exist in the pantheon_sessions table.
     347            $this->safe_output( __( 'A total of %s rows exist. To avoid service interruptions, this operation will be run in batches. Any sessions created between now and when operation completes may need to be recreated.', 'wp-native-php-sessions' ), 'log', [ $count_total ] );
     348        }
     349        // Create temporary table to copy data into in batches.
     350        $query = "CREATE TABLE {$temp_clone_table} LIKE {$table};";
     351        $wpdb->query( $query );
     352        $query = "ALTER TABLE {$temp_clone_table} ADD COLUMN id BIGINT AUTO_INCREMENT PRIMARY KEY FIRST";
     353        $wpdb->query( $query );
     354
     355        $batch_size = 20000;
     356        $loops      = ceil( $count_total / $batch_size );
     357
     358        for ( $i = 0; $i < $loops; $i++ ) {
     359            $offset = $i * $batch_size;
     360
     361            $query           = sprintf( "INSERT INTO {$temp_clone_table}
     362(user_id, session_id, secure_session_id, ip_address, datetime, data)
     363SELECT user_id,session_id,secure_session_id,ip_address,datetime,data
     364FROM %s ORDER BY user_id LIMIT %d OFFSET %d", $table, $batch_size, $offset );
     365            $results         = $wpdb->query( $query );
     366            $current_results = $results + ( $batch_size * $i );
     367
     368            // translators: %1 and %2 are how many rows have been processed out of how many total.
     369            $this->safe_output( __( 'Updated %1$s / %2$s rows. ', 'wp-native-php-sessions' ), 'log', [ $current_results, $count_total ] );
     370        }
     371
     372        // Hot swap the old table and the new table, deleting a previous old
     373        // table if necessary.
     374        $old_table = $wpdb->base_prefix . 'bak_' . $unprefixed_table;
     375        $query     = $wpdb->prepare( 'SHOW TABLES LIKE %s', $wpdb->esc_like( $old_table ) );
     376
     377        if ( $wpdb->get_var( $query ) == $old_table ) {
     378            $query = "DROP TABLE {$old_table};";
     379            $wpdb->query( $query );
     380        }
     381
     382        $query = "ALTER TABLE {$table} RENAME {$old_table};";
     383        $wpdb->query( $query );
     384        $query = "ALTER TABLE {$temp_clone_table} RENAME {$table};";
     385        $wpdb->query( $query );
     386
     387        $this->safe_output( __( 'Operation complete, please verify that your site is working as expected. When ready, run wp pantheon session primary-key-finalize to clean up old data, or run wp pantheon session primary-key-revert if there were issues.', 'wp-native-php-sessions' ), 'log' );
     388    }
     389
     390    /**
     391     * Finalizes the creation of a primary key by deleting the old data.
     392     */
     393    public function primary_key_finalize() {
     394        global $wpdb;
     395        $table = $wpdb->base_prefix . 'bak_pantheon_sessions';
     396
     397        $query = $wpdb->prepare( 'SHOW TABLES LIKE %s', $wpdb->esc_like( $table ) );
     398
     399        // Check for table existence and delete if present.
     400        if ( ! $wpdb->get_var( $query ) == $table ) {
     401            $this->safe_output( __( 'Old table does not exist to be removed.', 'wp-native-php-sessions' ), 'error' );
     402        } else {
     403            $query = "DROP TABLE {$table};";
     404            $wpdb->query( $query );
     405
     406            $this->safe_output( __( 'Old table has been successfully removed, process complete.', 'wp-native-php-sessions' ), 'log' );
     407
     408        }
     409    }
     410
     411    /**
     412     * Reverts addition of primary key.
     413     */
     414    public function primary_key_revert() {
     415        global $wpdb;
     416        $old_clone_table  = $wpdb->base_prefix . 'bak_pantheon_sessions';
     417        $temp_clone_table = $wpdb->base_prefix . 'temp_pantheon_sessions';
     418        $table            = $wpdb->base_prefix . 'pantheon_sessions';
     419
     420        // If there is no old table to roll back to, error.
     421        $query = $wpdb->prepare( 'SHOW TABLES LIKE %s', $wpdb->esc_like( $old_clone_table ) );
     422
     423        if ( ! $wpdb->get_var( $query ) == $old_clone_table ) {
     424            $this->safe_output( __( 'There is no old table to roll back to.', 'wp-native-php-sessions' ), 'error' );
     425        }
     426
     427        // Swap old table and new one.
     428        $query = "ALTER TABLE {$table} RENAME {$temp_clone_table};";
     429        $wpdb->query( $query );
     430        $query = "ALTER TABLE {$old_clone_table} RENAME {$table};";
     431        $wpdb->query( $query );
     432        $this->safe_output( __( 'Rolled back to previous state successfully, dropping corrupt table.', 'wp-native-php-sessions' ), 'log' );
     433
     434        // Remove table which did not function.
     435        $query = "DROP TABLE {$temp_clone_table}";
     436        $wpdb->query( $query );
     437        $this->safe_output( __( 'Process complete.', 'wp-native-php-sessions' ), 'log' );
     438    }
     439
     440    /**
     441     * Provide output to users, whether it's being run in WP_CLI or not.
     442     *
     443     * @param string $message Message to be printed.
     444     * @param string $type If message is being printed through WP_CLI, what type of message.
     445     * @param array $variables If sprintf is needed, an array of values.
     446     *
     447     * @return void
     448     */
     449    protected function safe_output( $message, $type, array $variables = [] ) {
     450        if ( defined( 'WP_CLI' ) && WP_CLI ) {
     451            WP_CLI::$type( vsprintf( $message, $variables ) );
     452            return;
     453        }
     454
     455        print "\n" . wp_kses_post( vsprintf( $message, $variables ) );
     456
     457        // Calling WP_CLI::error triggers an exit, but we still need to exist even if we don't have WP_CLI available.
     458        if ( $type === 'error' ) {
     459            exit( 1 );
     460        }
     461    }
    264462}
    265463
     
    274472
    275473add_action( 'activated_plugin', 'Pantheon_Sessions::force_first_load' );
     474add_action( 'admin_notices', 'Pantheon_Sessions::check_native_primary_keys' );
    276475
    277476Pantheon_Sessions();
  • wp-native-php-sessions/tags/1.4.0/readme.txt

    r2920329 r2980355  
    33Tags: comments, sessions
    44Requires at least: 4.7
    5 Tested up to: 6.2.2
    6 Stable tag: 1.3.6
     5Tested up to: 6.3
     6Stable tag: 1.4.0
    77Requires PHP: 5.4
    88License: GPLv2 or later
     
    4242    add_filter( 'pantheon_session_expiration', 'my_session_expiration_override' );
    4343
     44== CLI Commands ==
     45
     46= `wp pantheon session add-index` =
     47
     48Added in 1.4.0. This command should be run if your installation of the plugin occurred before the addition of the primary ID key to the session table in version 1.2.2. You will be automatically notified when you visit any admin page if this is the case. If there's no message, your version is good to go. Note that this command is non-destructive, a new table will be created and the existing one preserved in a backup state until you have verified that the upgrade is functioning as expected.
     49
     50= `wp pantheon session primary-key-finalize` =
     51
     52Added in 1.4.0. If you have run the `add-index` command and have verified that the new table is functioning correctly, running the `primary-key-finalize` command will perform a database cleanup and remove the backup table.
     53
     54= `wp pantheon session primary-key-revert` =
     55
     56Added in 1.4.0. If you have run the `add-index` command and something unexpected has occurred, just run the `primary-key-revert` command and the backup table will immediately be returned to being the active table.
     57
    4458== Contributing ==
    4559
     
    5771
    5872However, if you intend to scale your application, local tempfiles are a dangerous choice. They are not shared between different instances of the application, producing erratic behavior that can be impossible to debug. By storing them in the database the state of the sessions is shared across all application instances.
     73
     74= Where do I report security bugs found in this plugin? =
     75
     76Please report security bugs found in the source code of the WP Native PHP Sessions plugin through the [Patchstack Vulnerability Disclosure Program](https://patchstack.com/database/vdp/wp-native-php-sessions). The Patchstack team will assist you with verification, CVE assignment, and notify the developers of this plugin.
    5977
    6078== Troubleshooting ==
     
    6987This mu-plugin will load WP Native PHP Sessions before all other plugins, while letting you still use the WordPress plugin updater to keep the plugin up-to-date.
    7088
     89== Upgrade Notice ==
     90
     91= 1.4.0 (October 17, 2023) =
     92Adds a WP-CLI command to add an index to the sessions table if one does not exist already. If you installed this plugin before version 1.2.2, you likely need to run this command. However, regardless of version at installation a notice will appear in your admin dashboard if your database table is missing the index. If no notice appears, no action is necessary.
     93
    7194== Changelog ==
     95
     96= 1.4.0 =
     97* Adds new CLI command to add a Primary Column (id) to the `pantheon_sessions` table for users who do not have one. [[#265](https://github.com/pantheon-systems/wp-native-php-sessions/pull/265)]
     98* Adds alert to dashboard for users who need to run the command.
     99* 8.3 compatibility and code quality updates
     100
     101= 1.3.7-dev =
     102* Updates Pantheon WP Coding Standards to 2.0 [[#264](https://github.com/pantheon-systems/wp-native-php-sessions/pull/264)]
    72103
    73104= 1.3.6 (June 1, 2023) =
  • wp-native-php-sessions/trunk/inc/class-admin.php

    r2920329 r2980355  
    136136        <?php
    137137    }
    138 
    139138}
  • wp-native-php-sessions/trunk/inc/class-cli-command.php

    r2920329 r2980355  
    8080    }
    8181
     82    /**
     83     * Set id as primary key in the Native PHP Sessions plugin table.
     84     *
     85     * @subcommand add-index
     86     */
     87    public function add_index( $args, $assoc_arc ) {
     88        $pantheon_session = new \Pantheon_Sessions();
     89        $pantheon_session->add_index();
     90    }
     91
     92    /**
     93     * Finalizes the creation of a primary key by deleting the old data.
     94     *
     95     * @subcommand primary-key-finalize
     96     */
     97    public function primary_key_finalize() {
     98        $pan_session = new \Pantheon_Sessions();
     99        $pan_session->primary_key_finalize();
     100    }
     101
     102    /**
     103     * Reverts addition of primary key.
     104     *
     105     * @subcommand primary-key-revert
     106     */
     107    public function primary_key_revert() {
     108        $pan_session = new \Pantheon_Sessions();
     109        $pan_session->primary_key_revert();
     110    }
    82111}
    83112
  • wp-native-php-sessions/trunk/inc/class-list-table.php

    r2920329 r2980355  
    4343     */
    4444    public function no_items() {
    45         _e( 'No sessions found.', 'wp-native-php-sessions' );
     45        esc_html_e( 'No sessions found.', 'wp-native-php-sessions' );
    4646    }
    4747
     
    8585        }
    8686    }
    87 
    8887}
  • wp-native-php-sessions/trunk/inc/class-session-handler.php

    r2861737 r2980355  
    124124        return true;
    125125    }
    126 
    127126}
  • wp-native-php-sessions/trunk/inc/class-session.php

    r2920329 r2980355  
    320320        }
    321321    }
    322 
    323322}
  • wp-native-php-sessions/trunk/pantheon-sessions.php

    r2920329 r2980355  
    22/**
    33 * Plugin Name: Native PHP Sessions for WordPress
    4  * Version: 1.3.6
     4 * Version: 1.4.0
    55 * Description: Offload PHP's native sessions to your database for multi-server compatibility.
    66 * Author: Pantheon
     
    1414use Pantheon_Sessions\Session;
    1515
    16 define( 'PANTHEON_SESSIONS_VERSION', '1.3.6' );
     16define( 'PANTHEON_SESSIONS_VERSION', '1.4.0' );
    1717
    1818/**
     
    5050
    5151    /**
    52      * Load the plugin
     52     * Load the plugin.
    5353     */
    5454    private function load() {
     
    179179                        /* translators: %1s: File path, %2d: Line number */
    180180                        __( "Oops! The wp-native-php-sessions plugin couldn't start the session because output has already been sent. This might be caused by PHP throwing errors. Please check the code in %1s on line %2d.", 'wp-native-php-sessions' ),
    181                         $file,
    182                         $line
     181                        esc_html( $file ),
     182                        esc_html( $line )
    183183                    ),
    184184                    E_USER_WARNING
     
    262262        }
    263263    }
     264
     265    /**
     266     * Checks whether primary keys were set and notifies users if not.
     267     */
     268    public static function check_native_primary_keys() {
     269        global $wpdb;
     270        $table_name = $wpdb->base_prefix . 'pantheon_sessions';
     271        $old_table  = $wpdb->base_prefix . 'bak_pantheon_sessions';
     272        $query      = "SHOW KEYS FROM {$table_name} WHERE key_name = 'PRIMARY';";
     273
     274        $key_existence = $wpdb->get_results( $query );
     275
     276        if ( empty( $key_existence ) ) {
     277            // If the key doesn't exist, recommend remediation.
     278            ?>
     279            <div class="notice notice-error is-dismissible">
     280                <p>
     281                <?php
     282                print wp_kses_post( __( 'Your PHP Native Sessions table is missing a primary key. Please run <code>wp pantheon session add-index</code> and verify that the process completes successfully and that this message goes away to resolve this issue on your live environment.', 'wp-native-php-sessions' ) );
     283                ?>
     284                        </p>
     285            </div>
     286            <?php
     287        }
     288
     289        $query = $wpdb->prepare( 'SHOW TABLES LIKE %s',
     290        $wpdb->esc_like( $old_table ) );
     291
     292        // Check for table existence and delete if present.
     293        if ( $wpdb->get_var( $query ) == $old_table ) {
     294            // If an old table exists but has not been removed, suggest doing so.
     295            ?>
     296            <div class="notice notice-error">
     297                <p>
     298                <?php
     299                print wp_kses_post( __( 'An old version of the PHP Native Sessions table is detected. When testing is complete, run <code>wp pantheon session primary-key-finalize</code> to clean up old data, or run <code>wp pantheon session primary-key-revert</code> if there were issues.', 'wp-native-php-sessions' ) );
     300                ?>
     301                        </p>
     302            </div>
     303            <?php
     304        }
     305    }
     306
     307    /**
     308     * Set id as primary key in the Native PHP Sessions plugin table.
     309     */
     310    public function add_index() {
     311        global $wpdb;
     312        $unprefixed_table = 'pantheon_sessions';
     313        $table            = $wpdb->base_prefix . $unprefixed_table;
     314        $temp_clone_table = $wpdb->base_prefix . 'sessions_temp_clone';
     315
     316        // If the command has been run multiple times and there is already a
     317        // temp_clone table, drop it.
     318        $query = $wpdb->prepare( 'SHOW TABLES LIKE %s', $wpdb->esc_like( $temp_clone_table ) );
     319
     320        if ( $wpdb->get_var( $query ) == $temp_clone_table ) {
     321            $query = "DROP TABLE {$temp_clone_table};";
     322            $wpdb->query( $query );
     323        }
     324
     325        if ( ! PANTHEON_SESSIONS_ENABLED ) {
     326            $this->safe_output( __( 'Pantheon Sessions is currently disabled.', 'wp-native-php-sessions' ), 'error' );
     327        }
     328
     329        // Verify that the ID column/primary key does not already exist.
     330        $query         = "SHOW KEYS FROM {$table} WHERE key_name = 'PRIMARY';";
     331        $key_existence = $wpdb->get_results( $query );
     332
     333        // Avoid errors by not attempting to add a column that already exists.
     334        if ( ! empty( $key_existence ) ) {
     335            $this->safe_output( __( 'ID column already exists and does not need to be added to the table.', 'wp-native-php-sessions' ), 'error' );
     336        }
     337
     338        // Alert the user that the action is going to go through.
     339        $this->safe_output( __( 'Primary Key does not exist, resolution starting.', 'wp-native-php-sessions' ), 'log' );
     340
     341        $count_query = "SELECT COUNT(*) FROM {$table};";
     342        $count_total = $wpdb->get_results( $count_query );
     343        $count_total = $count_total[0]->{'COUNT(*)'};
     344
     345        if ( $count_total >= 20000 ) {
     346            // translators: %s is the total number of rows that exist in the pantheon_sessions table.
     347            $this->safe_output( __( 'A total of %s rows exist. To avoid service interruptions, this operation will be run in batches. Any sessions created between now and when operation completes may need to be recreated.', 'wp-native-php-sessions' ), 'log', [ $count_total ] );
     348        }
     349        // Create temporary table to copy data into in batches.
     350        $query = "CREATE TABLE {$temp_clone_table} LIKE {$table};";
     351        $wpdb->query( $query );
     352        $query = "ALTER TABLE {$temp_clone_table} ADD COLUMN id BIGINT AUTO_INCREMENT PRIMARY KEY FIRST";
     353        $wpdb->query( $query );
     354
     355        $batch_size = 20000;
     356        $loops      = ceil( $count_total / $batch_size );
     357
     358        for ( $i = 0; $i < $loops; $i++ ) {
     359            $offset = $i * $batch_size;
     360
     361            $query           = sprintf( "INSERT INTO {$temp_clone_table}
     362(user_id, session_id, secure_session_id, ip_address, datetime, data)
     363SELECT user_id,session_id,secure_session_id,ip_address,datetime,data
     364FROM %s ORDER BY user_id LIMIT %d OFFSET %d", $table, $batch_size, $offset );
     365            $results         = $wpdb->query( $query );
     366            $current_results = $results + ( $batch_size * $i );
     367
     368            // translators: %1 and %2 are how many rows have been processed out of how many total.
     369            $this->safe_output( __( 'Updated %1$s / %2$s rows. ', 'wp-native-php-sessions' ), 'log', [ $current_results, $count_total ] );
     370        }
     371
     372        // Hot swap the old table and the new table, deleting a previous old
     373        // table if necessary.
     374        $old_table = $wpdb->base_prefix . 'bak_' . $unprefixed_table;
     375        $query     = $wpdb->prepare( 'SHOW TABLES LIKE %s', $wpdb->esc_like( $old_table ) );
     376
     377        if ( $wpdb->get_var( $query ) == $old_table ) {
     378            $query = "DROP TABLE {$old_table};";
     379            $wpdb->query( $query );
     380        }
     381
     382        $query = "ALTER TABLE {$table} RENAME {$old_table};";
     383        $wpdb->query( $query );
     384        $query = "ALTER TABLE {$temp_clone_table} RENAME {$table};";
     385        $wpdb->query( $query );
     386
     387        $this->safe_output( __( 'Operation complete, please verify that your site is working as expected. When ready, run wp pantheon session primary-key-finalize to clean up old data, or run wp pantheon session primary-key-revert if there were issues.', 'wp-native-php-sessions' ), 'log' );
     388    }
     389
     390    /**
     391     * Finalizes the creation of a primary key by deleting the old data.
     392     */
     393    public function primary_key_finalize() {
     394        global $wpdb;
     395        $table = $wpdb->base_prefix . 'bak_pantheon_sessions';
     396
     397        $query = $wpdb->prepare( 'SHOW TABLES LIKE %s', $wpdb->esc_like( $table ) );
     398
     399        // Check for table existence and delete if present.
     400        if ( ! $wpdb->get_var( $query ) == $table ) {
     401            $this->safe_output( __( 'Old table does not exist to be removed.', 'wp-native-php-sessions' ), 'error' );
     402        } else {
     403            $query = "DROP TABLE {$table};";
     404            $wpdb->query( $query );
     405
     406            $this->safe_output( __( 'Old table has been successfully removed, process complete.', 'wp-native-php-sessions' ), 'log' );
     407
     408        }
     409    }
     410
     411    /**
     412     * Reverts addition of primary key.
     413     */
     414    public function primary_key_revert() {
     415        global $wpdb;
     416        $old_clone_table  = $wpdb->base_prefix . 'bak_pantheon_sessions';
     417        $temp_clone_table = $wpdb->base_prefix . 'temp_pantheon_sessions';
     418        $table            = $wpdb->base_prefix . 'pantheon_sessions';
     419
     420        // If there is no old table to roll back to, error.
     421        $query = $wpdb->prepare( 'SHOW TABLES LIKE %s', $wpdb->esc_like( $old_clone_table ) );
     422
     423        if ( ! $wpdb->get_var( $query ) == $old_clone_table ) {
     424            $this->safe_output( __( 'There is no old table to roll back to.', 'wp-native-php-sessions' ), 'error' );
     425        }
     426
     427        // Swap old table and new one.
     428        $query = "ALTER TABLE {$table} RENAME {$temp_clone_table};";
     429        $wpdb->query( $query );
     430        $query = "ALTER TABLE {$old_clone_table} RENAME {$table};";
     431        $wpdb->query( $query );
     432        $this->safe_output( __( 'Rolled back to previous state successfully, dropping corrupt table.', 'wp-native-php-sessions' ), 'log' );
     433
     434        // Remove table which did not function.
     435        $query = "DROP TABLE {$temp_clone_table}";
     436        $wpdb->query( $query );
     437        $this->safe_output( __( 'Process complete.', 'wp-native-php-sessions' ), 'log' );
     438    }
     439
     440    /**
     441     * Provide output to users, whether it's being run in WP_CLI or not.
     442     *
     443     * @param string $message Message to be printed.
     444     * @param string $type If message is being printed through WP_CLI, what type of message.
     445     * @param array $variables If sprintf is needed, an array of values.
     446     *
     447     * @return void
     448     */
     449    protected function safe_output( $message, $type, array $variables = [] ) {
     450        if ( defined( 'WP_CLI' ) && WP_CLI ) {
     451            WP_CLI::$type( vsprintf( $message, $variables ) );
     452            return;
     453        }
     454
     455        print "\n" . wp_kses_post( vsprintf( $message, $variables ) );
     456
     457        // Calling WP_CLI::error triggers an exit, but we still need to exist even if we don't have WP_CLI available.
     458        if ( $type === 'error' ) {
     459            exit( 1 );
     460        }
     461    }
    264462}
    265463
     
    274472
    275473add_action( 'activated_plugin', 'Pantheon_Sessions::force_first_load' );
     474add_action( 'admin_notices', 'Pantheon_Sessions::check_native_primary_keys' );
    276475
    277476Pantheon_Sessions();
  • wp-native-php-sessions/trunk/readme.txt

    r2920329 r2980355  
    33Tags: comments, sessions
    44Requires at least: 4.7
    5 Tested up to: 6.2.2
    6 Stable tag: 1.3.6
     5Tested up to: 6.3
     6Stable tag: 1.4.0
    77Requires PHP: 5.4
    88License: GPLv2 or later
     
    4242    add_filter( 'pantheon_session_expiration', 'my_session_expiration_override' );
    4343
     44== CLI Commands ==
     45
     46= `wp pantheon session add-index` =
     47
     48Added in 1.4.0. This command should be run if your installation of the plugin occurred before the addition of the primary ID key to the session table in version 1.2.2. You will be automatically notified when you visit any admin page if this is the case. If there's no message, your version is good to go. Note that this command is non-destructive, a new table will be created and the existing one preserved in a backup state until you have verified that the upgrade is functioning as expected.
     49
     50= `wp pantheon session primary-key-finalize` =
     51
     52Added in 1.4.0. If you have run the `add-index` command and have verified that the new table is functioning correctly, running the `primary-key-finalize` command will perform a database cleanup and remove the backup table.
     53
     54= `wp pantheon session primary-key-revert` =
     55
     56Added in 1.4.0. If you have run the `add-index` command and something unexpected has occurred, just run the `primary-key-revert` command and the backup table will immediately be returned to being the active table.
     57
    4458== Contributing ==
    4559
     
    5771
    5872However, if you intend to scale your application, local tempfiles are a dangerous choice. They are not shared between different instances of the application, producing erratic behavior that can be impossible to debug. By storing them in the database the state of the sessions is shared across all application instances.
     73
     74= Where do I report security bugs found in this plugin? =
     75
     76Please report security bugs found in the source code of the WP Native PHP Sessions plugin through the [Patchstack Vulnerability Disclosure Program](https://patchstack.com/database/vdp/wp-native-php-sessions). The Patchstack team will assist you with verification, CVE assignment, and notify the developers of this plugin.
    5977
    6078== Troubleshooting ==
     
    6987This mu-plugin will load WP Native PHP Sessions before all other plugins, while letting you still use the WordPress plugin updater to keep the plugin up-to-date.
    7088
     89== Upgrade Notice ==
     90
     91= 1.4.0 (October 17, 2023) =
     92Adds a WP-CLI command to add an index to the sessions table if one does not exist already. If you installed this plugin before version 1.2.2, you likely need to run this command. However, regardless of version at installation a notice will appear in your admin dashboard if your database table is missing the index. If no notice appears, no action is necessary.
     93
    7194== Changelog ==
     95
     96= 1.4.0 =
     97* Adds new CLI command to add a Primary Column (id) to the `pantheon_sessions` table for users who do not have one. [[#265](https://github.com/pantheon-systems/wp-native-php-sessions/pull/265)]
     98* Adds alert to dashboard for users who need to run the command.
     99* 8.3 compatibility and code quality updates
     100
     101= 1.3.7-dev =
     102* Updates Pantheon WP Coding Standards to 2.0 [[#264](https://github.com/pantheon-systems/wp-native-php-sessions/pull/264)]
    72103
    73104= 1.3.6 (June 1, 2023) =
Note: See TracChangeset for help on using the changeset viewer.