WordPress.org

Make WordPress Core

Ticket #26847: 26847.6.diff

File 26847.6.diff, 4.9 KB (added by pento, 8 years ago)
  • src/wp-includes/wp-db.php

     
    510510        public $is_mysql = null;
    511511
    512512        /**
     513         *  A list of MySQL's SQL modes to disallow when changing the SQL mode.
     514         *
     515         * @since 3.9.0
     516         * @see wpdb::set_sql_mode()
     517         * @access protected
     518         * @var array
     519         */
     520        protected $incompatible_modes = array( 'NO_ZERO_DATE', 'ONLY_FULL_GROUP_BY',
     521                'STRICT_TRANS_TABLES', 'STRICT_ALL_TABLES', 'TRADITIONAL' );
     522
     523        /**
    513524         * Connects to the database server and selects a database
    514525         *
    515526         * PHP5 style constructor for compatibility with PHP5. Does
     
    649660        }
    650661
    651662        /**
     663         * Changes the current SQL mode, and ensures the SQL mode is
     664         * WordPress compatible. If no modes are passed, it will ensure
     665         * the current MySQL server modes are compatible.
     666         *
     667         * @since 3.9.0
     668         *
     669         * @param array $modes Optional. A list of SQL modes to set.
     670         */
     671        function set_sql_mode( $modes = array() ) {
     672                if ( empty( $modes ) ) {
     673                        $res = mysql_query( 'SELECT @@SESSION.sql_mode;', $this->dbh );
     674                        if ( empty( $res ) ) {
     675                                return;
     676                        }
     677       
     678                        $modes_str = mysql_result( $res, 0 );
     679
     680                        if ( empty( $modes_str ) ) {
     681                                return;
     682                        }
     683       
     684                        $modes = explode( ',', $modes_str );
     685                }
     686               
     687                $modes = array_change_key_case( $modes, CASE_UPPER );
     688
     689                $incompatible_modes = $this->incompatible_modes;
     690                /**
     691                 * Filter the SQL modes that cannot be set
     692                 *
     693                 * WordPress doesn't operate with some of MySQL's SQL modes. This filter can be used to add
     694                 * any other filters to the list that aren't allowed to be set.
     695                 *
     696                 * @since 3.9.0
     697                 * @param array $incompatible_modes An array of incompatible modes
     698                 */
     699                $incompatible_modes = (array)apply_filters( 'incompatible_sql_modes', $incompatible_modes );
     700
     701                foreach( $modes as $i => $mode ) {
     702                        if ( in_array( $mode, $incompatible_modes ) ) {
     703                                unset( $modes[ $i ] );
     704                        }
     705                }
     706
     707                $modes_str = implode( ',', $modes );
     708
     709                mysql_query( "SET SESSION sql_mode='$modes_str';", $this->dbh );
     710        }
     711
     712        /**
    652713         * Sets the table prefix for the WordPress tables.
    653714         *
    654715         * @since 2.5.0
     
    11771238
    11781239                $this->set_charset( $this->dbh );
    11791240
     1241                $this->set_sql_mode();
     1242
    11801243                $this->ready = true;
    11811244
    11821245                $this->select( $this->dbname, $this->dbh );
  • tests/phpunit/tests/db.php

     
    126126                $sql = $wpdb->prepare( "UPDATE test_table SET string_column = '%%f is a float, %%d is an int %d, %%s is a string', field = %s", 3, '4' );
    127127                $this->assertEquals( "UPDATE test_table SET string_column = '%f is a float, %d is an int 3, %s is a string', field = '4'", $sql );
    128128        }
     129
     130        /**
     131         * Test that SQL modes are set correctly
     132         * @ticket 26847
     133         */
     134        public function test_set_sql_mode() {
     135                global $wpdb;
     136
     137                $current_modes = $wpdb->get_var( 'SELECT @@SESSION.sql_mode;' );
     138
     139                $new_modes = array( 'IGNORE_SPACE', 'NO_AUTO_CREATE_USER' );
     140                $wpdb->set_sql_mode( $new_modes );
     141                $check_new_modes = $wpdb->get_var( 'SELECT @@SESSION.sql_mode;' );
     142                $this->assertEquals( implode( ',', $new_modes ), $check_new_modes );
     143
     144                $wpdb->set_sql_mode( explode( ',', $current_modes ) );
     145        }
     146
     147        /**
     148         * Test that incompatible SQL modes are blocked
     149         * @ticket 26847
     150         */
     151        public function test_set_incompatible_sql_mode() {
     152                global $wpdb;
     153
     154                $current_modes = $wpdb->get_var( 'SELECT @@SESSION.sql_mode;' );
     155
     156                $new_modes = array( 'IGNORE_SPACE', 'NO_ZERO_DATE', 'NO_AUTO_CREATE_USER' );
     157                $wpdb->set_sql_mode( $new_modes );
     158                $check_new_modes = $wpdb->get_var( 'SELECT @@SESSION.sql_mode;' );
     159                $this->assertFalse( in_array( 'NO_ZERO_DATE', explode( ',', $check_new_modes ) ) );
     160
     161                $wpdb->set_sql_mode( explode( ',', $current_modes ) );
     162        }
     163
     164        /**
     165         * Test that incompatible SQL modes can be changed
     166         * @ticket 26847
     167         */
     168        public function test_set_allowed_incompatible_sql_mode() {
     169                global $wpdb;
     170
     171                $current_modes = $wpdb->get_var( 'SELECT @@SESSION.sql_mode;' );
     172
     173                $new_modes = array( 'IGNORE_SPACE', 'NO_ZERO_DATE', 'NO_AUTO_CREATE_USER' );
     174
     175                add_filter( 'incompatible_sql_modes', array( $this, 'filter_allowed_incompatible_sql_mode' ), 1, 1 );
     176                $wpdb->set_sql_mode( $new_modes );
     177                remove_filter( 'incompatible_sql_modes', array( $this, 'filter_allowed_incompatible_sql_mode' ), 1 );
     178
     179                $check_new_modes = $wpdb->get_var( 'SELECT @@SESSION.sql_mode;' );
     180                $this->assertTrue( in_array( 'NO_ZERO_DATE', explode( ',', $check_new_modes ) ) );
     181
     182                $wpdb->set_sql_mode( explode( ',', $current_modes ) );
     183        }
     184
     185        public function filter_allowed_incompatible_sql_mode( $modes ) {
     186                $pos = array_search( 'NO_ZERO_DATE', $modes );
     187                $this->assertGreaterThanOrEqual( 0, $pos );
     188
     189                if ( FALSE === $pos ) {
     190                        return $modes;
     191                }
     192
     193                unset( $modes[ $pos ] );
     194                return $modes;
     195        }
    129196}