Make WordPress Core


Ignore:
Timestamp:
11/14/2014 09:27:17 PM (10 years ago)
Author:
pento
Message:

When creating a post containing emoji, the post can be saved incorrectly if MySQL isn't using a character set that supports emoji.

This change prevents the save from occurring, so it can be handled correctly in the UI.

See #21212.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/tests/phpunit/tests/db.php

    r30320 r30345  
    1515
    1616    /**
     17     * Our special WPDB
     18     * @var resource
     19     */
     20    protected static $_wpdb;
     21
     22    public static function setUpBeforeClass() {
     23        self::$_wpdb = new wpdb_exposed_methods_for_testing();
     24    }
     25
     26    /**
    1727     * Set up the test fixture
    1828     */
     
    2737     */
    2838    public function tearDown() {
     39        remove_filter( 'query', array( $this, 'query_filter' ) );
    2940        parent::tearDown();
    30         remove_filter( 'query', array( $this, 'query_filter' ) );
    3141    }
    3242
     
    225235
    226236    /**
     237     * @ticket 21212
     238     */
     239    function test_wpdb_actually_protected_properties() {
     240        global $wpdb;
     241
     242        $new_meta = "HAHA I HOPE THIS DOESN'T WORK";
     243
     244        $col_meta = $wpdb->col_meta;
     245        $wpdb->col_meta = $new_meta;
     246
     247        $this->assertNotEquals( $col_meta, $new_meta );
     248        $this->assertEquals( $col_meta, $wpdb->col_meta );
     249    }
     250
     251    /**
    227252     * @ticket 18510
    228253     */
     
    494519        $wpdb->suppress_errors( $suppress );
    495520    }
     521
     522    /**
     523     * @ticket 21212
     524     */
     525    function data_get_table_from_query() {
     526        $table = 'a_test_table_name';
     527
     528        $queries = array(
     529            // Basic
     530            "SELECT * FROM $table",
     531            "SELECT * FROM `$table`",
     532
     533            "INSERT $table",
     534            "INSERT IGNORE $table",
     535            "INSERT IGNORE INTO $table",
     536            "INSERT INTO $table",
     537            "INSERT LOW_PRIORITY $table",
     538            "INSERT DELAYED $table",
     539            "INSERT HIGH_PRIORITY $table",
     540            "INSERT LOW_PRIORITY IGNORE $table",
     541            "INSERT LOW_PRIORITY INTO $table",
     542            "INSERT LOW_PRIORITY IGNORE INTO $table",
     543
     544            "REPLACE $table",
     545            "REPLACE INTO $table",
     546            "REPLACE LOW_PRIORITY $table",
     547            "REPLACE DELAYED $table",
     548            "REPLACE LOW_PRIORITY INTO $table",
     549
     550            "UPDATE LOW_PRIORITY $table",
     551            "UPDATE LOW_PRIORITY IGNORE $table",
     552
     553            "DELETE $table",
     554            "DELETE IGNORE $table",
     555            "DELETE IGNORE FROM $table",
     556            "DELETE FROM $table",
     557            "DELETE LOW_PRIORITY $table",
     558            "DELETE QUICK $table",
     559            "DELETE IGNORE $table",
     560            "DELETE LOW_PRIORITY FROM $table",
     561
     562            // STATUS
     563            "SHOW TABLE STATUS LIKE '$table'",
     564            "SHOW TABLE STATUS WHERE NAME='$table'",
     565
     566            "SHOW TABLES LIKE '$table'",
     567            "SHOW FULL TABLES LIKE '$table'",
     568            "SHOW TABLES WHERE NAME='$table'",
     569
     570            // Extended
     571            "EXPLAIN SELECT * FROM $table",
     572            "EXPLAIN EXTENDED SELECT * FROM $table",
     573            "EXPLAIN EXTENDED SELECT * FROM `$table`",
     574
     575            "DESCRIBE $table",
     576            "DESC $table",
     577            "EXPLAIN $table",
     578            "HANDLER $table",
     579
     580            "LOCK TABLE $table",
     581            "LOCK TABLES $table",
     582            "UNLOCK TABLE $table",
     583
     584            "RENAME TABLE $table",
     585            "OPTIMIZE TABLE $table",
     586            "BACKUP TABLE $table",
     587            "RESTORE TABLE $table",
     588            "CHECK TABLE $table",
     589            "CHECKSUM TABLE $table",
     590            "ANALYZE TABLE $table",
     591            "REPAIR TABLE $table",
     592
     593            "TRUNCATE $table",
     594            "TRUNCATE TABLE $table",
     595
     596            "CREATE TABLE $table",
     597            "CREATE TEMPORARY TABLE $table",
     598            "CREATE TABLE IF NOT EXISTS $table",
     599
     600            "ALTER TABLE $table",
     601            "ALTER IGNORE TABLE $table",
     602
     603            "DROP TABLE $table",
     604            "DROP TABLE IF EXISTS $table",
     605
     606            "CREATE INDEX foo(bar(20)) ON $table",
     607            "CREATE UNIQUE INDEX foo(bar(20)) ON $table",
     608            "CREATE FULLTEXT INDEX foo(bar(20)) ON $table",
     609            "CREATE SPATIAL INDEX foo(bar(20)) ON $table",
     610
     611            "DROP INDEX foo ON $table",
     612
     613            "LOAD DATA INFILE 'wp.txt' INTO TABLE $table",
     614            "LOAD DATA LOW_PRIORITY INFILE 'wp.txt' INTO TABLE $table",
     615            "LOAD DATA CONCURRENT INFILE 'wp.txt' INTO TABLE $table",
     616            "LOAD DATA LOW_PRIORITY LOCAL INFILE 'wp.txt' INTO TABLE $table",
     617            "LOAD DATA INFILE 'wp.txt' REPLACE INTO TABLE $table",
     618            "LOAD DATA INFILE 'wp.txt' IGNORE INTO TABLE $table",
     619
     620            "GRANT ALL ON TABLE $table",
     621            "REVOKE ALL ON TABLE $table",
     622
     623            "SHOW COLUMNS FROM $table",
     624            "SHOW FULL COLUMNS FROM $table",
     625            "SHOW CREATE TABLE $table",
     626            "SHOW INDEX FROM $table",
     627        );
     628
     629        foreach ( $queries as &$query ) {
     630            $query = array( $query, $table );
     631        }
     632        return $queries;
     633    }
     634
     635    /**
     636     * @dataProvider data_get_table_from_query
     637     * @ticket 21212
     638     */
     639    function test_get_table_from_query( $query, $table ) {
     640        $this->assertEquals( $table, self::$_wpdb->get_table_from_query( $query ) );
     641    }
     642
     643    function data_get_table_from_query_false() {
     644        $table = 'a_test_table_name';
     645        return array(
     646            array( "LOL THIS ISN'T EVEN A QUERY $table" ),
     647        );
     648    }
     649
     650    /**
     651     * @dataProvider data_get_table_from_query_false
     652     * @ticket 21212
     653     */
     654    function test_get_table_from_query_false( $query ) {
     655        $this->assertFalse( self::$_wpdb->get_table_from_query( $query ) );
     656    }
     657
     658    /**
     659     * @ticket 21212
     660     */
     661    function data_process_field_formats() {
     662        $core_db_fields_no_format_specified = array(
     663            array( 'post_content' => 'foo', 'post_parent' => 0 ),
     664            null,
     665            array(
     666                'post_content' => array( 'value' => 'foo', 'format' => '%s' ),
     667                'post_parent' => array( 'value' => 0, 'format' => '%d' ),
     668            )
     669        );
     670
     671        $core_db_fields_formats_specified = array(
     672            array( 'post_content' => 'foo', 'post_parent' => 0 ),
     673            array( '%d', '%s' ), // These override core field_types
     674            array(
     675                'post_content' => array( 'value' => 'foo', 'format' => '%d' ),
     676                'post_parent' => array( 'value' => 0, 'format' => '%s' ),
     677            )
     678        );
     679
     680        $misc_fields_no_format_specified = array(
     681            array( 'this_is_not_a_core_field' => 'foo', 'this_is_not_either' => 0 ),
     682            null,
     683            array(
     684                'this_is_not_a_core_field' => array( 'value' => 'foo', 'format' => '%s' ),
     685                'this_is_not_either' => array( 'value' => 0, 'format' => '%s' ),
     686            )
     687        );
     688
     689        $misc_fields_formats_specified = array(
     690            array( 'this_is_not_a_core_field' => 0, 'this_is_not_either' => 1.2 ),
     691            array( '%d', '%f' ),
     692            array(
     693                'this_is_not_a_core_field' => array( 'value' => 0, 'format' => '%d' ),
     694                'this_is_not_either' => array( 'value' => 1.2, 'format' => '%f' ),
     695            )
     696        );
     697
     698        $misc_fields_insufficient_formats_specified = array(
     699            array( 'this_is_not_a_core_field' => 0, 'this_is_not_either' => 's', 'nor_this' => 1 ),
     700            array( '%d', '%s' ), // The first format is used for the third
     701            array(
     702                'this_is_not_a_core_field' => array( 'value' => 0, 'format' => '%d' ),
     703                'this_is_not_either' => array( 'value' => 's', 'format' => '%s' ),
     704                'nor_this' => array( 'value' => 1, 'format' => '%d' ),
     705            )
     706        );
     707
     708        $vars = get_defined_vars();
     709        // Push the variable name onto the end for assertSame $message
     710        foreach ( $vars as $var_name => $var ) {
     711            $vars[ $var_name ][] = $var_name;
     712        }
     713        return array_values( $vars );
     714    }
     715
     716    /**
     717     * @dataProvider data_process_field_formats
     718     * @ticket 21212
     719     */
     720    function test_process_field_formats( $data, $format, $expected, $message ) {
     721        $actual = self::$_wpdb->process_field_formats( $data, $format );
     722        $this->assertSame( $expected, $actual, $message );
     723    }
     724
     725    /**
     726     * @ticket 21212
     727     */
     728    function test_process_fields() {
     729        global $wpdb;
     730        $data = array( 'post_content' => '¡foo foo foo!' );
     731        $expected = array(
     732            'post_content' => array(
     733                'value' => '¡foo foo foo!',
     734                'format' => '%s',
     735                'charset' => $wpdb->charset,
     736                'ascii' => false,
     737            )
     738        );
     739
     740        $this->assertSame( $expected, self::$_wpdb->process_fields( $wpdb->posts, $data, null ) );
     741    }
     742
     743    /**
     744     * @ticket 21212
     745     * @depends test_process_fields
     746     */
     747    function test_process_fields_on_nonexistent_table( $data ) {
     748        self::$_wpdb->suppress_errors( true );
     749        $data = array( 'post_content' => '¡foo foo foo!' );
     750        $this->assertFalse( self::$_wpdb->process_fields( 'nonexistent_table', $data, null ) );
     751        self::$_wpdb->suppress_errors( false );
     752    }
     753
     754    /**
     755     * @ticket 21212
     756     */
     757    function test_pre_get_table_charset_filter() {
     758        add_filter( 'pre_get_table_charset', array( $this, 'filter_pre_get_table_charset' ), 10, 2 );
     759        $charset = self::$_wpdb->get_table_charset( 'some_table' );
     760        remove_filter( 'pre_get_table_charset', array( $this, 'filter_pre_get_table_charset' ), 10 );
     761
     762        $this->assertEquals( $charset, 'fake_charset' );
     763    }
     764    function filter_pre_get_table_charset( $charset, $table ) {
     765        return 'fake_charset';
     766    }
     767
     768    /**
     769     * @ ticket 21212
     770     */
     771    function test_pre_get_col_charset_filter() {
     772        add_filter( 'pre_get_col_charset', array( $this, 'filter_pre_get_col_charset' ), 10, 3 );
     773        $charset = self::$_wpdb->get_col_charset( 'some_table', 'some_col' );
     774        remove_filter( 'pre_get_col_charset', array( $this, 'filter_pre_get_col_charset' ), 10 );
     775
     776        $this->assertEquals( $charset, 'fake_col_charset' );
     777    }
     778    function filter_pre_get_col_charset( $charset, $table, $column ) {
     779        return 'fake_col_charset';
     780    }
    496781}
     782
     783/**
     784 * Special class for exposing protected wpdb methods we need to access
     785 */
     786class wpdb_exposed_methods_for_testing extends wpdb {
     787    public function __construct() {
     788        global $wpdb;
     789        $this->dbh = $wpdb->dbh;
     790        $this->use_mysqli = $wpdb->use_mysqli;
     791        $this->ready = true;
     792        $this->field_types = $wpdb->field_types;
     793        $this->charset = $wpdb->charset;
     794    }
     795
     796    public function __call( $name, $arguments ) {
     797        return call_user_func_array( array( $this, $name ), $arguments );
     798    }
     799}
Note: See TracChangeset for help on using the changeset viewer.