Make WordPress Core

Opened 9 years ago

Closed 9 years ago

#33452 closed defect (bug) (fixed)

wp_dropdown_categories doesn't respect show_option_all

Reported by: dfellini's profile dfellini Owned by: boonebgorges's profile boonebgorges
Milestone: 4.3.1 Priority: normal
Severity: normal Version: 4.3
Component: Taxonomy Keywords: fixed-major
Focuses: Cc:

Description

Using the following code:
wp_dropdown_categories('show_option_all=All Locations&name=location&show_count=1&orderby=name&echo=1&taxonomy=joblocation&value_field=slug');

... yields me a list of states in correct order with 'All Locations' properly selected by default, up until the 4.3 upgrade. Now it has the very last item in the list selected by default.

Tested by running plugin on 4.2.4 where it displayed as expected, then upgrading to 4.3, where the problem was introduced.

Attachments (2)

Screen Shot 2015-08-19 at 3.23.04 PM.png (35.0 KB) - added by dfellini 9 years ago.
Screenshot of category list with wrong default selected
33452.diff (2.3 KB) - added by boonebgorges 9 years ago.

Download all attachments as: .zip

Change History (9)

@dfellini
9 years ago

Screenshot of category list with wrong default selected

#1 @dfellini
9 years ago

  • Component changed from General to Taxonomy

#2 @boonebgorges
9 years ago

  • Keywords has-patch needs-testing added
  • Milestone changed from Awaiting Review to 4.3.1

Hi dfellini - Welcome to Trac, and thanks for the report!

I've confirmed the issue. It dates from [32484]. This odd bug arises due to an unfortunate combination of (a) the way that the 'selected' argument works, and (b) the way PHP interprets == between an integer and a string.

More specifically: The default 'selected' value in wp_dropdown_categories() is 0. In Walker_CategoryDropdown::start_el(), we do a comparison if ( $category->{$value_field} == $args['selected'] ). Because you're using slug as your 'value_field', the check looks something like this: if ( 'connecticut' == 0 ). The problem is that PHP resolves 'connecticut' == 0 to true; see http://stackoverflow.com/questions/6843030/why-does-php-consider-0-to-be-equal-to-a-string for some explanation. So each <option> in your dropdown is getting selected="selected".

The most straightforward fix is to cast everything to a string, and to do a strict comparison. See 33452.diff. Can you have a look to see whether this solves your problem?

This is going to be a relatively large annoyance for people who are relying on the default value of 'selected' in wp_dropdown_categories(), so I'm moving the ticket to 4.3.1 to address in the next minor release.

@boonebgorges
9 years ago

#3 @dfellini
9 years ago

This seems to have solved my issue. Thanks so much. I appreciate it.

#4 @boonebgorges
9 years ago

  • Owner set to boonebgorges
  • Resolution set to fixed
  • Status changed from new to closed

In 33681:

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.

#5 @boonebgorges
9 years ago

  • Keywords fixed-major added; has-patch needs-testing removed
  • Resolution fixed deleted
  • Status changed from closed to reopened

Reopening for 4.3.1.

This ticket was mentioned in Slack in #core by sam. View the logs.


9 years ago

#7 @boonebgorges
9 years ago

  • Resolution set to fixed
  • Status changed from reopened to closed

In 33949:

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 ===.

Merges [33681] to the 4.3 branch.

Fixes #33452 for 4.3.1.

Note: See TracTickets for help on using tickets.