Make WordPress Core

Opened 12 years ago

Closed 10 years ago

#20733 closed defect (bug) (duplicate)

Theme customizer doesn't order sections based on order added

Reported by: andyadams's profile andyadams Owned by:
Milestone: Priority: normal
Severity: normal Version: 3.4
Component: Customize Keywords: 3.6-early needs-patch
Focuses: Cc:

Description

When adding sections to the theme customizer, sections with the same priority are given seemingly random order. From the original customizer ticket:

Settings and sections both contain priority parameters (you can specify these in the constructor or alter them afterwards) which serve as the primary means of sorting sections before they're rendered. The order settings/sections are added serves as a secondary sorting mechanism (tiebreaker) when multiple items share the same priority.

I was under the impression that if the priority was the same, the sections would appear in the order they were added. However, if you add sections A, B, and C (in that order) it seems to display them in order B, C, A.

To replicate, add this code to your theme:

add_action( 'customize_register', 'theme_customize_register' );

function theme_customize_register( $wp_customize ) {
	// Register Section A
	$wp_customize->add_section( 'theme_section_a', array(
		'title'    => 'Section A',
		'priority' => 35,
	) );
	$wp_customize->add_setting( 'theme_option_a', array(
		'type'              => 'option',
	) );
	$wp_customize->add_control( 'theme_option_a', array(
		'section'    => 'theme_section_a',
		'type'       => 'text',
	) );

	// Register Section B
	$wp_customize->add_section( 'theme_section_b', array(
		'title'    => 'Section B',
		'priority' => 35,
	) );
	$wp_customize->add_setting( 'theme_option_b', array(
		'type'              => 'option',
	) );
	$wp_customize->add_control( 'theme_option_b', array(
		'section'    => 'theme_section_b',
		'type'       => 'text',
	) );

	// Register Section C
	$wp_customize->add_section( 'theme_section_c', array(
		'title'    => 'Section C',
		'priority' => 35,
	) );
	$wp_customize->add_setting( 'theme_option_c', array(
		'type'              => 'option',
	) );
	$wp_customize->add_control( 'theme_option_c', array(
		'section'    => 'theme_section_c',
		'type'       => 'text',
	) );
}

Expected result: Sections show up in order A, B, C

Actual result: Sections show up in order B, C, A

Sorry if I'm doing something stupid, or if this isn't the intended functionality. I'm running trunk without any plugins.

Attachments (3)

20733.patch (406 bytes) - added by SergeyBiryukov 12 years ago.
20733.patch.2 (557 bytes) - added by andyadams 12 years ago.
Comparing array key index instead
20733.3.diff (557 bytes) - added by Japh 12 years ago.
Refreshed patch

Download all attachments as: .zip

Change History (19)

#1 @nacin
12 years ago

  • Milestone changed from Awaiting Review to 3.4

#2 follow-up: @jane
12 years ago

This seems fairly trivial and not worth holding up 3.4. I suggest fixing for 3.5 but not worrying about it for 3.4. As long as they all actually show up that's what counts, right?

#3 @ocean90
12 years ago

  • Cc ocean90 added

Example output:

id -> prio

// before:
header - 20
background - 30
nav - 40
static_front_page - 50
strings - 5
theme_section_a - 35
theme_section_d - 32
theme_section_b - 35
theme_section_c - 35


// array_reverse
theme_section_c - 35
theme_section_b - 35
theme_section_d - 32
theme_section_a - 35
strings - 5
static_front_page - 50
nav - 40
background - 30
header - 20


// uasort
strings - 5
header - 20
background - 30
theme_section_d - 32
theme_section_c - 35
theme_section_a - 35
theme_section_b - 35
nav - 40
static_front_page - 50
Last edited 12 years ago by ocean90 (previous) (diff)

#4 in reply to: ↑ 2 @andyadams
12 years ago

Replying to jane:

This seems fairly trivial and not worth holding up 3.4. I suggest fixing for 3.5 but not worrying about it for 3.4. As long as they all actually show up that's what counts, right?

Ultimately, I suppose that's true. In my case, I'm trying to add support for the customizer into a theme options library. Having this work as intended would prevent those of us who want to control order from having to set incrementing priorities to each section.

The use case where this would become an issue is when two separate sources (say a theme and a plugin) try to add sections to the same priority level. Instead of the theme sections and plugin sections being grouped together, they'd be intermingled at random. Not a disaster, but not ideal, either. A use case like that isn't something I see being common, but I thought it was worth mentioning.

It's not a huge deal, so if it ends up being a major issue to fix I think we can work around it.

#5 @SergeyBiryukov
12 years ago

  • Keywords has-patch added

Perhaps we could use strcmp( $a->id, $b->id ) as a fallback for equal priorities.

Seems to work properly with the example from the description.

@andyadams
12 years ago

Comparing array key index instead

#6 @andyadams
12 years ago

Replying to SergeyBiryukov:

Perhaps we could use strcmp( $a->id, $b->id ) as a fallback for equal priorities.

Seems to work properly with the example from the description.

I think that will only work if the IDs are in alphabetical order. If we compare the position of the array keys instead, it works in my tests.

Sorry for the patch format - my first time trying SVN patching.

#7 @jeffsebring
12 years ago

You can use the priority arg to set the control order.

Here is an example:

      $wp_customize->add_control( 'customize[header_width]', array(
         'label'           => __( 'Logo Width ( px )', 'render' ),
         'section'         => 'header',
         'type'            => 'text',
         'priority'        => 11,
      ) );
Last edited 12 years ago by jeffsebring (previous) (diff)

#8 @nacin
12 years ago

Just so everyone is aware of why this is happening, PHP's user-sorting algorithm does not guarantee the original order of the array: http://php.net/usort. "If two members compare as equal, their relative order in the sorted array is undefined." and "The cmp_function doesn't keep the original order for elements comparing as equal."

We avoid these issues in the plugin API (and elsewhere) by keying things by priority. Or we could do the sorting ourself by simply looping through the elements and adding them to an array keyed by priority. Not necessarily the best idea here. Some kind of array_search is probably isn't going to be the fastest, but seems reasonable enough.

#9 @westi
12 years ago

I think for 3.4 we should leave it as is because there is a simple workaround - use distinct priorities to order your things.

Later we can revisit how we index the original arrays so that we can not need to do any sorting at all.

My feeling is we just push this to 3.5

#10 @ocean90
12 years ago

  • Keywords 3.5-early needs-patch added; has-patch removed
  • Milestone changed from 3.4 to Future Release

My feeling is we just push this to 3.5

I agree, since you can still use the priority arg to change the order.


keying things by priority

+1

#11 @SergeyBiryukov
12 years ago

Closed #21180 as a duplicate (controls are also affected).

@Japh
12 years ago

Refreshed patch

#12 @Japh
12 years ago

  • Cc japh@… added
  • Keywords has-patch added; needs-patch removed

I've refreshed @andyadams' patch. If there's a different approach that should be taken, I'd be happy to re-patch with that.

#13 @Japh
12 years ago

  • Keywords needs-patch added; has-patch removed

Actually, the patch I refreshed is too specific. We need this patch to resolve for both sections and controls...

#14 @Otto42
12 years ago

  • Cc Otto42 added

#15 @unknowndomain
12 years ago

  • Cc me@… added
  • Keywords 3.6-early settings-api added; 3.5-early removed

What is the best way forward with this as it also has implications on #22487 where the same block of code is currently being proposed for adding priority to settings fields. It seems like rather a massive job to change the array layout for priority, is there a working solution for this?

#16 @ocean90
10 years ago

  • Keywords settings-api removed
  • Milestone Future Release deleted
  • Resolution set to duplicate
  • Status changed from new to closed

Duplicate of #30225.

Note: See TracTickets for help on using tickets.