Make WordPress Core

Changeset 33681


Ignore:
Timestamp:
08/21/2015 01:10:34 AM (9 years ago)
Author:
boonebgorges
Message:

In Walker_CategoryDropdown::start_el(), cast values to strings before deciding whether to append 'selected' attribute.

As of [32484], wp_dropdown_categories() uses the $value_field value to
decide whether a given <option> should be 'selected'. However, $value_field
can refer to a value that is a string, such as a category's slug. This causes
problems when doing a loose comparison (==) with the value of the 'selected'
parameter, which defaults to 0, because when doing a loose comparison
between an integer and a string, PHP will cast the string to an integer. This
creates false matches, resulting in <option> elements getting a 'selected'
attribute incorrectly.

We address the issue by casting the comparison values to strings, and then
using the strict comparison operator ===.

Fixes #33452 for trunk.

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/category-template.php

    r33318 r33681  
    12081208        $output .= "\t<option class=\"level-$depth\" value=\"" . esc_attr( $category->{$value_field} ) . "\"";
    12091209
    1210         if ( $category->{$value_field} == $args['selected'] )
     1210        // Type-juggling causes false matches, so we force everything to a string.
     1211        if ( (string) $category->{$value_field} === (string) $args['selected'] )
    12111212            $output .= ' selected="selected"';
    12121213        $output .= '>';
  • trunk/tests/phpunit/tests/category.php

    r32484 r33681  
    352352        $this->assertContains( "value=\"test_category_2\" selected=\"selected\"", $found );
    353353    }
     354
     355    /**
     356     * @ticket 33452
     357     */
     358    public function test_wp_dropdown_categories_show_option_all_should_be_selected_if_no_selected_value_is_explicitly_passed_and_value_field_does_not_have_string_values() {
     359        $cats = $this->factory->category->create_many( 3 );
     360
     361        $found = wp_dropdown_categories( array(
     362            'echo' => 0,
     363            'hide_empty' => 0,
     364            'show_option_all' => 'Foo',
     365            'value_field' => 'slug',
     366        ) );
     367
     368        $this->assertContains( "value='0' selected='selected'", $found );
     369
     370        foreach ( $cats as $cat ) {
     371            $_cat = get_term( $cat, 'category' );
     372            $this->assertNotContains( 'value="' . $_cat->slug . '" selected="selected"', $found );
     373        }
     374    }
     375
     376    /**
     377     * @ticket 33452
     378     */
     379    public function test_wp_dropdown_categories_show_option_all_should_be_selected_if_selected_value_of_0_string_is_explicitly_passed_and_value_field_does_not_have_string_values() {
     380        $cats = $this->factory->category->create_many( 3 );
     381
     382        $found = wp_dropdown_categories( array(
     383            'echo' => 0,
     384            'hide_empty' => 0,
     385            'show_option_all' => 'Foo',
     386            'value_field' => 'slug',
     387            'selected' => '0',
     388        ) );
     389
     390        $this->assertContains( "value='0' selected='selected'", $found );
     391
     392        foreach ( $cats as $cat ) {
     393            $_cat = get_term( $cat, 'category' );
     394            $this->assertNotContains( 'value="' . $_cat->slug . '" selected="selected"', $found );
     395        }
     396    }
    354397}
Note: See TracChangeset for help on using the changeset viewer.