WordPress.org

Make WordPress Core

Ticket #21212: 21212-strict.diff

File 21212-strict.diff, 8.2 KB (added by pento, 6 years ago)
  • src/wp-includes/wp-db.php

     
    566566         * @access protected
    567567         * @var array
    568568         */
    569         protected $incompatible_modes = array( 'NO_ZERO_DATE', 'ONLY_FULL_GROUP_BY',
    570                 'STRICT_TRANS_TABLES', 'STRICT_ALL_TABLES', 'TRADITIONAL' );
     569        protected $incompatible_modes = array( 'NO_ZERO_DATE', 'ONLY_FULL_GROUP_BY', 'TRADITIONAL' );
    571570
    572571        /**
     572         * A list of required SQL modes.
     573         *
     574         * @since 4.1.0
     575         * @access protected
     576         * @var array
     577         */
     578        protected $required_modes = array( 'STRICT_ALL_TABLES' );
     579
     580        /**
    573581         * Whether to use mysqli over mysql.
    574582         *
    575583         * @since 3.9.0
     
    778786         */
    779787        public function set_sql_mode( $modes = array() ) {
    780788                if ( empty( $modes ) ) {
    781                         if ( $this->use_mysqli ) {
    782                                 $res = mysqli_query( $this->dbh, 'SELECT @@SESSION.sql_mode' );
     789                        $modes = $this->get_var( "SELECT @@SESSION.sql_mode" );
     790                        if ( $modes ) {
     791                                $modes = $original_modes = explode( ',', $modes );
    783792                        } else {
    784                                 $res = mysql_query( 'SELECT @@SESSION.sql_mode', $this->dbh );
     793                                $modes = $original_modes = array();
    785794                        }
    786 
    787                         if ( empty( $res ) ) {
    788                                 return;
    789                         }
    790 
    791                         if ( $this->use_mysqli ) {
    792                                 $modes_array = mysqli_fetch_array( $res );
    793                                 if ( empty( $modes_array[0] ) ) {
    794                                         return;
    795                                 }
    796                                 $modes_str = $modes_array[0];
    797                         } else {
    798                                 $modes_str = mysql_result( $res, 0 );
    799                         }
    800 
    801                         if ( empty( $modes_str ) ) {
    802                                 return;
    803                         }
    804 
    805                         $modes = explode( ',', $modes_str );
    806795                }
    807796
    808797                $modes = array_change_key_case( $modes, CASE_UPPER );
     
    816805                 */
    817806                $incompatible_modes = (array) apply_filters( 'incompatible_sql_modes', $this->incompatible_modes );
    818807
    819                 foreach( $modes as $i => $mode ) {
    820                         if ( in_array( $mode, $incompatible_modes ) ) {
    821                                 unset( $modes[ $i ] );
     808                /**
     809                 * Filter the list of required SQL modes to include.
     810                 *
     811                 * @since 4.1.0
     812                 *
     813                 * @param array $required_modes An array of required modes.
     814                 */
     815                $required_modes = (array) apply_filters( 'required_sql_modes', $this->required_modes );
     816
     817                $modes = array_diff( $modes, $incompatible_modes );
     818                $modes = array_unique( array_merge( $modes, $required_modes ) );
     819
     820                // Don't run SET SESSION if we have nothing to change.
     821                if ( isset( $original_modes ) ) {
     822                        sort( $original_modes );
     823                        sort( $modes );
     824                        if ( $original_modes === $modes ) {
     825                                return;
    822826                        }
    823827                }
    824828
    825829                $modes_str = implode( ',', $modes );
    826830
    827                 if ( $this->use_mysqli ) {
    828                         mysqli_query( $this->dbh, "SET SESSION sql_mode='$modes_str'" );
    829                 } else {
    830                         mysql_query( "SET SESSION sql_mode='$modes_str'", $this->dbh );
     831                $this->query( "SET SESSION sql_mode='$modes_str'" );
     832                if ( $this->last_error ) {
     833                        dead_db();
    831834                }
    832835        }
    833836
  • tests/phpunit/tests/db.php

     
    281281
    282282                $current_modes = $wpdb->get_var( 'SELECT @@SESSION.sql_mode;' );
    283283
    284                 $new_modes = array( 'IGNORE_SPACE', 'NO_AUTO_CREATE_USER' );
     284                $new_modes = $expected_modes = array( 'IGNORE_SPACE', 'NO_AUTO_CREATE_USER' );
     285                $expected_modes[] = 'STRICT_ALL_TABLES';
    285286
    286287                $wpdb->set_sql_mode( $new_modes );
    287288
    288289                $check_new_modes = $wpdb->get_var( 'SELECT @@SESSION.sql_mode;' );
    289                 $this->assertEqualSets( $new_modes, explode( ',', $check_new_modes ) );
     290                $this->assertEqualSets( $expected_modes, explode( ',', $check_new_modes ) );
    290291
    291292                $wpdb->set_sql_mode( explode( ',', $current_modes ) );
    292293        }
     
    342343        }
    343344
    344345        /**
     346         * @ticket 21212
     347         */
     348        function test_set_sql_mode_strict() {
     349                global $wpdb;
     350                $wpdb->set_sql_mode();
     351                $sql_modes = $wpdb->get_var( 'SELECT @@SESSION.sql_mode;' );
     352                $this->assertContains( 'STRICT_ALL_TABLES', explode( ',', $sql_modes ) );
     353        }
     354
     355        /**
     356         * @ticket 21212
     357         */
     358        function test_strict_mode_numeric_strings() {
     359                global $wpdb;
     360                $post_id = $this->factory->post->create();
     361                $wpdb->update( $wpdb->posts, array( 'post_parent' => 4 ), array( 'ID' => $post_id ), array( '%s' ) );
     362                $this->assertContains( "`post_parent` = '4'", $wpdb->last_query );
     363                $this->assertEmpty( $wpdb->last_error );
     364        }
     365
     366        /**
     367         * @ticket 21212
     368         */
     369        function test_strict_mode_numeric_strings_using_query() {
     370                global $wpdb;
     371                $post_id = $this->factory->post->create();
     372                $wpdb->query( $wpdb->prepare( "UPDATE $wpdb->posts SET post_parent = %s WHERE ID = %s", '4', $post_id ) );
     373                $this->assertEmpty( $wpdb->last_error );
     374        }
     375
     376        /**
     377         * @ticket 21212
     378         */
     379        function test_strict_mode_nan() {
     380                global $wpdb;
     381                $post_id = $this->factory->post->create();
     382                $suppress = $wpdb->suppress_errors( true );
     383                $wpdb->update( $wpdb->posts, array( 'post_parent' => 'foo' ), array( 'ID' => $post_id ), array( '%s' ) );
     384                $this->assertContains( "`post_parent` = 'foo'", $wpdb->last_query );
     385                $this->assertContains( 'Incorrect integer value', $wpdb->last_error );
     386                $wpdb->suppress_errors( $suppress );
     387        }
     388
     389        /**
     390         * @ticket 21212
     391         */
     392        function test_strict_mode_nan_using_query() {
     393                global $wpdb;
     394                $post_id = $this->factory->post->create();
     395                $suppress = $wpdb->suppress_errors( true );
     396                $wpdb->query( $wpdb->prepare( "UPDATE $wpdb->posts SET post_parent = %s WHERE ID = %s", 'foo', $post_id ) );
     397                $this->assertContains( 'Incorrect integer value', $wpdb->last_error );
     398                $wpdb->suppress_errors( $suppress );
     399        }
     400
     401        /**
     402         * @ticket 21212
     403         */
     404        function test_strict_mode_number_start_of_string() {
     405                global $wpdb;
     406                $post_id = $this->factory->post->create();
     407                $suppress = $wpdb->suppress_errors( true );
     408                $wpdb->query( $wpdb->prepare( "UPDATE $wpdb->posts SET post_parent = %s WHERE ID = %s", '4foo', $post_id ) );
     409                $this->assertContains( "Data truncated for column 'post_parent'", $wpdb->last_error );
     410                $wpdb->suppress_errors( $suppress );
     411        }
     412
     413        /**
     414         * @ticket 21212
     415         */
     416        function test_strict_mode_booleans_true() {
     417                global $wpdb;
     418                $user_id = $this->factory->user->create();
     419                $wpdb->query( "UPDATE $wpdb->users SET user_status = true WHERE ID = $user_id" );
     420                $this->assertEmpty( $wpdb->last_error );
     421                $user = get_userdata( $user_id );
     422                $this->assertSame( '1', $user->user_status );
     423        }
     424
     425        /**
     426         * @ticket 21212
     427         */
     428        function test_strict_mode_booleans_false() {
     429                global $wpdb;
     430                $user_id = $this->factory->user->create();
     431                $wpdb->query( "UPDATE $wpdb->users SET user_status = false WHERE ID = $user_id" );
     432                $this->assertEmpty( $wpdb->last_error );
     433                $user = get_userdata( $user_id );
     434                $this->assertEquals( '0', $user->user_status );
     435        }
     436
     437        /**
     438         * @ticket 21212
     439         */
     440        function test_strict_mode_zero_date_is_valid() {
     441                global $wpdb;
     442                $user_id = $this->factory->user->create();
     443                $wpdb->query( "UPDATE $wpdb->users SET user_registered = '0000-00-00' WHERE ID = $user_id" );
     444                $this->assertEmpty( $wpdb->last_error );
     445                $user = get_userdata( $user_id );
     446                $this->assertEquals( '0000-00-00 00:00:00', $user->user_registered );
     447        }
     448
     449        /**
     450         * @ticket 21212
     451         */
     452        function test_strict_mode_zero_datetime_is_valid() {
     453                global $wpdb;
     454                $user_id = $this->factory->user->create();
     455                $wpdb->query( "UPDATE $wpdb->users SET user_registered = '0000-00-00 00:00:00' WHERE ID = $user_id" );
     456                $this->assertEmpty( $wpdb->last_error );
     457                $user = get_userdata( $user_id );
     458                $this->assertEquals( '0000-00-00 00:00:00', $user->user_registered );
     459        }
     460
     461        /**
     462         * @ticket 21212
     463         */
     464        function test_strict_mode_invalid_dates_are_invalid() {
     465                global $wpdb;
     466                $user_id = $this->factory->user->create();
     467                $suppress = $wpdb->suppress_errors( true );
     468                $wpdb->query( "UPDATE $wpdb->users SET user_registered = '2014-02-29 00:00:00' WHERE ID = $user_id" );
     469                $this->assertContains( 'Incorrect datetime value', $wpdb->last_error );
     470                $wpdb->suppress_errors( $suppress );
     471        }
     472
     473        /**
     474         * @ticket 21212
     475         */
     476        function test_strict_mode_nulls_are_invalid() {
     477                global $wpdb;
     478                $user_id = $this->factory->user->create();
     479                $suppress = $wpdb->suppress_errors( true );
     480                $wpdb->query( "UPDATE $wpdb->users SET user_nicename = NULL WHERE ID = $user_id" );
     481                $this->assertContains( 'cannot be null', $wpdb->last_error );
     482                $wpdb->suppress_errors( $suppress );
     483        }
     484
     485        /**
    345486         * @ticket 25604
    346487         * @expectedIncorrectUsage wpdb::prepare
    347488         */