WordPress.org

Make WordPress Core

Opened 3 years ago

Closed 3 years ago

Last modified 7 months ago

#30737 closed enhancement (fixed)

JS templates for Customizer Panels and Sections

Reported by: celloexpressions Owned by: westonruter
Milestone: 4.3 Priority: normal
Severity: normal Version: 4.1
Component: Customize Keywords: has-patch commit
Focuses: Cc:

Description

Follow up to #28907 and #29572. This is necessary for truly dynamic containers, which don't require any ajax and can be added using the new JS API.

This is required for Menu Customizer, which is currently working around the issue by supplying its own template for a generic section. I'd like to get this done early in 4.2.

Working on a patch that's very similar to #29572, but for sections and panels. It will be possible to override in subclasses, of course, like the existing render/render content methods.

If anyone's wondering why we would ever need dynamically-rendered panels, think things like in-page theme switching, where available options change inline based on the previewed theme.

Attachments (19)

30737.diff (14.1 KB) - added by celloexpressions 3 years ago.
Implement support for JS templates for sections and panel contents. Note that panels are like controls, with separate templates/logic for containers vs. content, but sections just have containers. The section part of this patch represents how we'd implement container templates for controls and panels in #30741.
30737.2.diff (15.3 KB) - added by celloexpressions 3 years ago.
Also implement panel container templates, address feedback from @westonruter.
30737.3.diff (15.3 KB) - added by celloexpressions 3 years ago.
30737.4.diff (18.1 KB) - added by westonruter 3 years ago.
Additional changes: https://github.com/xwp/wordpress-develop/compare/e07a0f0...3758798
30737.5.diff (26.2 KB) - added by westonruter 3 years ago.
Additional changes: https://github.com/xwp/wordpress-develop/compare/de06ebd...55c18ea
30737.6.diff (25.2 KB) - added by ocean90 3 years ago.
Refresh + $.trim( template( container.params ) ); in getContainer
30737.7.diff (25.5 KB) - added by westonruter 3 years ago.
Refresh. https://github.com/xwp/wordpress-develop/pull/87
30737.8.diff (34.0 KB) - added by westonruter 3 years ago.
Add unit tests for WP_Customize_Section; update references from 4.2.0 to 4.3.0
30737.9.diff (43.9 KB) - added by westonruter 3 years ago.
Add QUnit tests.
30737.10.diff (44.1 KB) - added by westonruter 3 years ago.
Add compatibility with #31336: https://github.com/xwp/wordpress-develop/commit/3b6920938ea71fbaadf38eebd005cd79895f843d
30737.11.diff (45.1 KB) - added by westonruter 3 years ago.
30737.12.diff (45.0 KB) - added by westonruter 3 years ago.
Remove PHP code copied from class into QUnit HTML
30737.13.diff (45.0 KB) - added by westonruter 3 years ago.
Fix phpunit tests: https://github.com/xwp/wordpress-develop/compare/f3fcf05...c3f5434
30737.14.diff (50.4 KB) - added by westonruter 3 years ago.
Fix QUnit tests: https://github.com/xwp/wordpress-develop/commit/a4ec734a5d7e1a63aaa87e16b3e2ed0e7c039c78
30737.15.diff (49.6 KB) - added by westonruter 3 years ago.
https://github.com/xwp/wordpress-develop/commit/36e0899897d30903c85764f8c1eaab2b96cd42df
30737.fix-custom-sections.diff (1.3 KB) - added by celloexpressions 3 years ago.
Always fall back to using the default template if no custom template exists.
30737.fix-custom-sections.2.diff (1.3 KB) - added by celloexpressions 3 years ago.
fix typo
30737.addendum.diff (9.0 KB) - added by westonruter 3 years ago.
Additional changes: https://github.com/xwp/wordpress-develop/compare/8dfa3d5...d37d805 PR: https://github.com/xwp/wordpress-develop/pull/90
30737.addendum.2.diff (10.1 KB) - added by ocean90 3 years ago.

Download all attachments as: .zip

Change History (75)

@celloexpressions
3 years ago

Implement support for JS templates for sections and panel contents. Note that panels are like controls, with separate templates/logic for containers vs. content, but sections just have containers. The section part of this patch represents how we'd implement container templates for controls and panels in #30741.

#2 follow-up: @celloexpressions
3 years ago

  • Keywords has-patch added; needs-patch removed
  • Milestone changed from Future Release to 4.2

Would like to get this reviewed, polished, and hopefully commited sooner rather than later so that we can do #30741 and the other related tickets, as well as leveraging all of this in the Menu Customizer project.

This ticket was mentioned in Slack in #core-customize by nacin. View the logs.


3 years ago

#4 in reply to: ↑ 2 @westonruter
3 years ago

Replying to celloexpressions:

Would like to get this reviewed, polished, and hopefully commited sooner rather than later so that we can do #30741 and the other related tickets, as well as leveraging all of this in the Menu Customizer project.

I've added feedback for your patch here: https://github.com/xwp/wordpress-develop/pull/59

We also need to update the unit tests to make use of these new methods.

This ticket was mentioned in Slack in #core-customize by celloexpressions. View the logs.


3 years ago

#6 @celloexpressions
3 years ago

  • Keywords needs-refresh added

Will update to address westonruter's feedback hopefully tonight.

@celloexpressions
3 years ago

Also implement panel container templates, address feedback from @westonruter.

#7 @celloexpressions
3 years ago

  • Keywords needs-refresh removed

Updated patch per westonruter's feedback. I ended up just implementing templates for panel containers and content (which is similar to how we'll do it for controls in #30741 after we do #30738).

#8 follow-up: @ocean90
3 years ago

30737.2.diff:

  • The indentation in class-wp-customize-panel.php and class-wp-customize-section.php is still mixed up.
  • render_template() in class-wp-customize-panel.php uses var classes for the CSS classes while class-wp-customize-section.php doesn't. The extra variable isn't needed IMO.

#9 in reply to: ↑ 8 @celloexpressions
3 years ago

Replying to ocean90:

30737.2.diff:

  • The indentation in class-wp-customize-panel.php and class-wp-customize-section.php is still mixed up.
  • render_template() in class-wp-customize-panel.php uses var classes for the CSS classes while class-wp-customize-section.php doesn't. The extra variable isn't needed IMO.

30737.3.diff.

#10 @westonruter
3 years ago

What about adding to the QUnit tests to check that the new methods work as expected?

Nevermind that we currently don't have any PHPUnit tests at all for WP_Customize_Manager or WP_Customize_Control ;-P

Also, in the case where a panel/section/control's check_capabilities() returns false resulting in the json() method returning null, how will this affect _wpCustomizeSettings in customize.php which is passed into the JS boot logic? There will be panels/sections/controls in that are null.

From looking at customize-controls.js, it seems it would try to pass null into the constructor, and it would even throw a Null is not an object error when attempting api.panelConstructor[ data.type ]. See https://github.com/xwp/wordpress-develop/blob/2b4099c6bd5faa4b99436ab404279699ffc442f9/src/wp-admin/js/customize-controls.js#L2023-L2055

Should the logic instead be moved to customize.php, for instance:

	// Prepare Customize Control objects to pass to JavaScript.
	foreach ( $wp_customize->controls() as $id => $control ) {
		if ( $control->check_capabilities() ) { // this conditional added
			$settings['controls'][ $id ] = $control->json();
		}
	}

Really, however, that whole blob of logic in customize.php should be moved to a new method on WP_Customize_Manager, like WP_Customize_Manager::get_configuration()

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


3 years ago

#12 @celloexpressions
3 years ago

I don't think we should hold this up for unit tests since most of the Customizer code still needs unit tests. But if you're able to write some for this, it wouldn't hurt (that's not within my scope of abilities).

I think it's important to keep objects from potentially being sent to JS if the caps aren't available within the control/panel/section objects, but it would probably work if that was handled by the manager. We should probably move all of that logic out of customize.php in another ticket, so should we just move the checks there for now?

#13 @DrewAPicture
3 years ago

Not already having unit tests does not a compelling argument make for skipping them for new functionality.

#14 @kuus
3 years ago

I think it would be great to expose the Container class to the js API. Because otherwise extending the Section or Panel classes with a custom one is a bit problematic. It would be an easy change here: https://github.com/xwp/wordpress-develop/blob/customize-2.0/src/wp-admin/js/customize-controls.js#L227

Anyway thanks for your great work on the Customizer API.

#15 @celloexpressions
3 years ago

If we're going to wait for someone to write unit tests, then this is in a holding pattern indefinitely. I think it's okay without them, but I don't do them so I don't really know. If we need unit tests, we're probably going to have to punt, which has significant implications on the timeline of things like menus in the Customizer happening in core.

#16 @westonruter
3 years ago

In 30737.4.diff:

  • Remove check_capabilities() calls from json() methods since redundant with prepare_controls()
  • Wrap setting exporting with cap checks.
  • Add cap checks to panels, sections, and controls before adding to JS exports.

PR: https://github.com/xwp/wordpress-develop/pull/59/files

@celloexpressions: I'll try to add the unit tests over the next 48 hours.

Last edited 3 years ago by westonruter (previous) (diff)

This ticket was mentioned in Slack in #core-customize by ocean90. View the logs.


3 years ago

@ocean90
3 years ago

Refresh + $.trim( template( container.params ) ); in getContainer

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


3 years ago

#20 @ocean90
3 years ago

  • Keywords needs-unit-tests added
  • Milestone changed from 4.2 to Future Release
  • Priority changed from high to normal

Punted from 4.2 per bug scrub. This needs some QUnit tests.

This ticket was mentioned in Slack in #core-customize by westonruter. View the logs.


3 years ago

This ticket was mentioned in Slack in #core-customize by celloexpressions. View the logs.


3 years ago

#23 @celloexpressions
3 years ago

  • Keywords needs-refresh added
  • Milestone changed from Future Release to 4.3

New menus in Menu Customizer will require users to close the Customizer to go back to the menus panel until we can get this ticket fixed as of #31336. #31336 will also require the actual JS templates for panels and sections to be rewritten, which I can take care of as soon as the first-pass is committed there, along with a general refresh. In the meantime, we need unit tests still, so if anyone can work on those that would be great.

We also need to do this as a first step for #30741, which should also be in 4.3 if at all possible, but that won't happen if we don't get moving here soon.

This ticket was mentioned in Slack in #core-customize by celloexpressions. View the logs.


3 years ago

This ticket was mentioned in Slack in #core-customize by celloexpressions. View the logs.


3 years ago

#26 @westonruter
3 years ago

  • Keywords needs-refresh removed

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


3 years ago

#28 @westonruter
3 years ago

  • Owner set to westonruter
  • Status changed from new to accepted

@westonruter
3 years ago

Add unit tests for WP_Customize_Section; update references from 4.2.0 to 4.3.0

This ticket was mentioned in Slack in #core-customize by westonruter. View the logs.


3 years ago

@westonruter
3 years ago

Add QUnit tests.

#30 @westonruter
3 years ago

  • Keywords needs-unit-tests removed

OK, I've added all of the outstanding unit tests, both PHP and JS: 30737.9.diff

#31 @westonruter
3 years ago

Refreshed patch in 30737.11.diff after merge of #31336. Includes some resolved conflicts. Needs verification. See pull request as well: https://github.com/xwp/wordpress-develop/pull/87

This ticket was mentioned in Slack in #core-customize by westonruter. View the logs.


3 years ago

@westonruter
3 years ago

@westonruter
3 years ago

Remove PHP code copied from class into QUnit HTML

#33 @westonruter
3 years ago

Note that QUnit tests are currently broken in trunk due to changes in #31336.

#34 @valendesigns
3 years ago

Those will need to be fixed ASAP, but I have no experience with QUnit so I'm not the one to fix it. I'll test this patch now that #31336 has landed.

#35 @ocean90
3 years ago

With 30737.12.diff I get two PHPUnit failures:

There was 1 error:

1) Tests_WP_Customize_Section::test_json
Trying to get property of non-object

/srv/www/wp-develop/svn/src/wp-includes/class-wp-customize-section.php:233
/srv/www/wp-develop/svn/tests/phpunit/tests/customize/section.php:121

--

There was 1 failure:

1) Tests_WP_Customize_Panel::test_print_templates_standard
Failed asserting that '		<script type="text/html" id="tmpl-customize-panel-default-content">
					<li class="panel-meta customize-info accordion-section <# if ( ! data.description ) { #> cannot-expand<# } #>">
			<button class="customize-panel-back" tabindex="-1"><span class="screen-reader-text">Back</span></button>
			<div class="accordion-section-title">
				<span class="preview-notice">You are customizing <strong class="panel-title">{{ data.title }}</strong></span>
				<button class="customize-help-toggle dashicons dashicons-editor-help" tabindex="0" aria-expanded="false"><span class="screen-reader-text">Help</span></button>
			</div>
			<# if ( data.description ) { #>
				<div class="description customize-panel-description">
					{{{ data.description }}}
				</div>
			<# } #>
		</li>
				</script>
		<script type="text/html" id="tmpl-customize-panel-default">
					<li id="accordion-panel-{{ data.id }}" class="accordion-section control-section control-panel control-panel-{{ data.type }}">
			<h3 class="accordion-section-title" tabindex="0">
				{{ data.title }}
				<span class="screen-reader-text">Press return or enter to open this panel</span>
			</h3>
			<ul class="accordion-sub-container control-panel-content"></ul>
		</li>
				</script>
        ' contains "accordion-section-content".

/srv/www/wp-develop/svn/tests/phpunit/tests/customize/panel.php:192

FAILURES!

#36 @westonruter
3 years ago

@celloexpressions I noticed something that may be unexpected when testing with Menu Customizer. Namely, I had to make sure I added:

$this->manager->register_section_type( 'WP_Customize_Menu_Section' );

Or else the custom sections would never render. Nevertheless, Menu Customizer just needed the default section to render right? So it seems that if a custom section didn't have register_section_type called, it should fallback to render the default section.

So I'm suggesting an additional patch something like this:

  • src/wp-admin/js/customize-controls.js

     
    170170   container.params = {};
    171171   $.extend( container, options || {} );
    172172   container.templateSelector = 'customize-' + container.containerType + '-' + container.params.type;
     173   if ( ! document.getElementById( 'tmpl-' + container.templateSelector ) ) {
     174    container.templateSelector = 'customize-' + container.containerType + '-default';
     175   }
    173176   container.container = $( container.params.content );
    174177   if ( 0 === container.container.length ) {
    175178    container.container = $( container.getContainer() );
     
    12111214   */
    12121215  renderContent: function () {
    12131216   var template,
     1217    templateSelector,
    12141218    panel = this;
    12151219
     1220   if ( document.getElementById( 'tmpl-' + panel.templateSelector + '-content' ) ) {
     1221    templateSelector = panel.templateSelector + '-content';
     1222   } else {
     1223    templateSelector = 'customize-' + panel.containerType + '-default-content';
     1224   }
     1225
    12161226   // Add the content to the container.
    1217    if ( 0 !== $( '#tmpl-' + panel.templateSelector + '-content' ).length ) {
    1218     template = wp.template( panel.templateSelector + '-content' );
     1227   if ( 0 !== $( '#tmpl-' + templateSelector ).length ) {
     1228    template = wp.template( templateSelector );
    12191229    if ( template && panel.container ) {
    12201230     panel.container.find( '.accordion-sub-container' ).html( template( panel.params ) );
    12211231    }

Thoughts?

#37 @westonruter
3 years ago

PHPUnit and QUnit tests are all fixed.

#38 @valendesigns
3 years ago

  • Keywords commit added

I'm not finding any UI or behavior changes. There was some expected breakage in Menu Customizer, but beyond that 30737.14.diff looks good. Both QUnit & PHPUnit are passing. Though there is some discussion around jshint complaints in Slack, once those are fixed I move for commit. Cheers!

#39 @westonruter
3 years ago

Fixed JSHint complaints.

#40 @westonruter
3 years ago

In 32658:

Add JS templates for Customizer Panels and Sections.

This extends the approach taken for Customizer Controls in #29572.

Props celloexpressions, westonruter, ocean90.
See #30737.

This ticket was mentioned in Slack in #core-customize by celloexpressions. View the logs.


3 years ago

#42 @westonruter
3 years ago

Only two things remain before closing this out:

1) Address the question I've raised regarding falling back to the templates for default types.

2) Provide a set of default params when constructing new Section and Panel objects (and even Controls). As discussed in Slack, if you fail to supply a param.type, then it will not even fall back to the default template, but will try to use a undefined template, which is even worse. So something like this would be good, to go along with my suggestion above.

  • src/wp-admin/js/customize-controls.js

     
    167167                initialize: function ( id, options ) {
    168168                        var container = this;
    169169                        container.id = id;
    170                         container.params = {};
    171                         $.extend( container, options || {} );
     170                        options = options || {};
     171                        options.params = $.extend(
     172                                {
     173                                        'type': 'default',
     174                                        customizeAction: api.l10n.defaultSectionCustomizeAction
     175                                        // ...
     176                                },
     177                                options.params || {}
     178                        );
     179                        $.extend( container, options );
    172180                        container.templateSelector = 'customize-' + container.containerType + '-' + container.params.type;
    173181                        container.container = $( container.params.content );
    174182                        if ( 0 === container.container.length ) {

@celloexpressions
3 years ago

Always fall back to using the default template if no custom template exists.

#43 @celloexpressions
3 years ago

30737.fix-custom-sections.diff fixes issue 1) above. This removes the need for any modifications in Menu Customizer in order for its custom sections to work as they should.

#44 @celloexpressions
3 years ago

Default customize action would be good for Menu Customizer too.

This ticket was mentioned in Slack in #core-customize by celloexpressions. View the logs.


3 years ago

#46 @westonruter
3 years ago

In 30737.addendum.diff I add QUnit tests for the template fallbacks, and then I also add default params for panels and sections when they are constructed, along with documenting the parameters that are accepted by their constructors.

#47 @ocean90
3 years ago

30737.addendum.2.diff moves defaultParams out of api.Container.initialize to a defaults property and adds a defaults property to api.Section. I think this looks a bit cleaner since api.Container shouldn't care about child objects (api.Section).

#48 follow-up: @celloexpressions
3 years ago

Looks good to me. Only thing - can we set the action to something better by default? Since that is required for the UI to look right now. Would it be feasible to pass "Customizing > " to JS and then get the parent panel title if it exists?

This ticket was mentioned in Slack in #core-customize by celloexpressions. View the logs.


3 years ago

#50 in reply to: ↑ 48 @ocean90
3 years ago

Replying to celloexpressions:

Only thing - can we set the action to something better by default? Since that is required for the UI to look right now. Would it be feasible to pass "Customizing > " to JS and then get the parent panel title if it exists?

I'm not a fan of adding a default string here. The UI needs to handle views without an action, for example the Themes "panel" shows an action, which is wrong.

#51 @ocean90
3 years ago

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

In 32681:

Customizer: Improve JS templates for Panels and Sections added in [32658].

  • Always fall back to using the default template if no custom template exists.
  • Provide a set of default params when constructing new Section and Panel objects.

Includes QUnit tests.

Props celloexpressions, westonruter, ocean90.
Fixes #30737.

This ticket was mentioned in Slack in #core-customize by ocean90. View the logs.


3 years ago

#53 @westonruter
3 years ago

In 32744:

Customizer: Allow sections and panels to be exported to JS.

Also fix param docs for customize_dynamic_setting_class filter, and use require_once for class-wp-customize-manager.php in bootstrap function _wp_customize_include().

See #30737, #32576.

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


3 years ago

#55 @ocean90
3 years ago

In 32822:

Customizer: Decode HTML entities of panel/section titles.

Titles are now passed into Underscore templates but HTML-escaped, see #30737.

fixes #32670.

#56 @westonruter
7 months ago

In 42038:

Customize: Fix interface alignment between Setting and Control, adding defaults to wp.customize.Setting and using wp.customize.previewer as default previewer param.

Also move jsdoc from class to initialize method and correct the param types.

Amends [41726], [42037], [32681].
See #42083, #30737.

Note: See TracTickets for help on using tickets.