[wp-trac] [WordPress Trac] #29211: Customizer: extract a cropped-image control from header images
WordPress Trac
noreply at wordpress.org
Tue Jul 14 06:30:23 UTC 2015
#29211: Customizer: extract a cropped-image control from header images
------------------------------+-------------------------------
Reporter: celloexpressions | Owner: celloexpressions
Type: task (blessed) | Status: assigned
Priority: normal | Milestone: 4.3
Component: Customize | Version: 3.9
Severity: normal | Resolution:
Keywords: has-patch | Focuses: javascript
------------------------------+-------------------------------
Changes (by celloexpressions):
* keywords: needs-patch => has-patch
Comment:
There are several major issues here still. [attachment:29211.5.diff]
addresses all of them. This may need some tweaking in terms of the way the
code is placed/structured, but we need to address all of the problems here
in a fix before this ticket can be closed, and these fixes need to be in
4.3.
----
Adding a `WP_Customize_Cropped_Image_Control` currently causes the
Customizer to throw a JS error, rendering the entire Customizer completely
unusable. Fortunately this fix is simple: we need to ensure that the
`customize-views` script is loaded after the media scripts. Fixed in
[attachment:29211.5.diff].
----
The hook introduced in [33154] in `wp_ajax_crop_image` is not usable
because insufficient information is passed to the hook to do ''anything''.
You get only the context (which is presumably known and something you'd
test against to determine handling) and `0` currently.
[attachment:29211.5.diff] passes the cropped image URL and the original
attachment id to this filter, and adds clarification of exactly what the
filter does. Specifically, you start with the original attachment id but
need to return an attachment id for an attachment object that has the
cropped image in it. That means either changing the original attachment or
creating a new one. Alternatively, a callback on this filter could
presumably bail out of the ajax call and simply return the cropped image
URL to the JS client. This is based on the information that is needed for
the core site icon implementation of attachment handling after the cropped
image is created.
But when cropping is done from a Customizer control, the ajax action needs
to give developers a reasonable result by default regardless. Currently
there is a vague error that shows up in the media modal after submitting
the copping step that is hard to debug, requiring a deep traversal through
the intricacies of the media JS and the Customizer's implementation of it,
and severely diminishing the developer experience. They're forced to debug
what is really a core bug. The Customizer does not require developers to
hook into core ajax functions in order for a basic control to work. You
add the control and an associated setting and it "just works". Therefore,
this filter is only used when an image is being cropped in ajax by a non-
core feature or from a Customizer control.
----
Continuing on from the issue with the filter, we need to implement the
attachment-handling part for `WP_Customize_Cropped_Image_Control`. One of
the best features of the Customizer is its API. The developer experience
with the Customizer is just as important if not more important than the
user experience. As the API grows, we need to ensure that we stay
consistent with its established patterns, maximize forwards and backwards
compatibility, optimize both ease of implementation and extensibility, and
regularly do QA/QC on our API just like we're trying to do with our UI and
UX. With UI and UX, it's all about screenshots and user testing. With
developer experience, it's all about code examples, test plugins, and
developer testing. When we find issues, we need to fix them, especially if
we're still in beta and can fix them. A good example of this is the
decision in WordPress 4.0 to make Panels a distinct object instead of
being a custom section type (implemented as a subclass), as they had
initially been developed.
To ensure that the cropped-image control works as intended, we initially
included the site icon feature with it in core, as an extension on the
basic functionality offered via the API. This allowed us to catch many of
the issues in the initial implementation, but we missed some things. To
further test our implementation of this new control, this addition to our
API and marketable improvement to the developer experience -- the power of
the media modal and a core-provided image cropper that allows images to be
fine-tuned to countless uses in themes and plugins with minimal developer
effort -- I implemented `WP_Customize_Cropped_Image_Control` in another
place where it's been proposed to be used in core: background images.
The reasons for first implementing background image cropping (#32403) in a
plugin are explained in [https://wordpress.org/plugins/background-image-
cropper/ the plugin] and on the
[https://make.wordpress.org/core/2015/07/10/feature-plugin-chat-on-
july-14/#comment-26314 plugin proposal], but I've attached the plugin to
this ticket also so that it can be evaluated as an example and used
directly for testing. Note that due to some of the oddities of the way
this core feature is implemented, the previewing part won't work yet, but
the focus here is on the control and the preview will work with other
custom cropped-image controls. The code is remarkably minimal for
implementing such a historically complex (see: header images) feature, but
considering the Customizer, and the developer experience that it offers,
it's a reasonable and expected implementation:
{{{
add_action( 'customize_register', 'background_image_cropper_register', 11
); // after core
function background_image_cropper_register( $wp_customize ) {
$wp_customize->remove_control( 'background_image' );
$wp_customize->add_control( new
WP_Customize_Cropped_Image_Control( $wp_customize, 'background_image',
array(
'section' => 'background_image',
'priority' => 0,
'flex_width' => true, // Allow custom aspect ratios and
dimensions.
'flex_height' => true,
'width' => 1920, // "Suggested" size.
'height' => 1080,
) ) );
}
}}}
After testing this plugin, the critical script dependency issue mentioned
above was discovered. Fixing that seemed to allow this control to work
exactly as expected - the currently selected image was displayed just like
it is with a regular image control, the change button opened the media
modal, and after selecting an image, the cropper came up in the modal just
like it does with header images. I successfully adjusted the crop handles
to select the part of the image that I wanted to use and hit the crop
button, expecting the modal to seamlessly close and the cropped image to
show up in the Customizer controls and the preview. But instead, after a
brief pause, I got a vague error message that the image could not be
cropped, leaving closing the media modal as my only option.
This flow is a failure in both user experience and developer experience.
For the user, everything almost worked, then hit a major, insurmountable
roadblock. Similarly, for the developer, the Customizer API offered its
usual power and flexibility... until it wasn't quite able to do what it
usually does, crashing and burning in an error message that is difficult
to parse and assign as the fault of core or the developer's simple
implementation of the typically-easy Customizer API. Even if the developer
were familiar with the basics of custom controls in the Customizer, the
necessity of their understanding the media js would present a significant
barrier to finding the cause of the error and fixing it.
We can, and really must, do better. When you add an image control to the
Customizer, users can access the media modal select an image, and see it
previewed without any additional work on behalf of the developer. When you
add a cropped-image control to the Customizer, it should work just the
same. Sure there are a few more ''optional'' parameters on the control to
deal with the specifics of the cropping to be done, but these only offer
more flexibility within the core control before needed to build a custom
child control. With [attachment:29211.5.diff], the highly backend process
of cropping an image is coupled with the very necessary step of creating a
new attachment to represent the cropped image and returning that object to
the Customizer UI. The `switch` for context is replaced by direct checks
for core features with custom handling, followed by the default handling
in the Customizer (complete with filters for use in more customized
implementations), and finally followed by the above-mentioned filter for
custom handling when a plugin uses this function outside of the
Customizer.
This fix allows the API to remain optimized for simplicity and ease of
use, while still allowing for more advanced solutions if needed.
----
One final fix here is to make the cropped-image control extend
`WP_Customize_Media_Control` directly in PHP like it does in JS. The only
difference between the media control and the image control is that the
media control saves the attachment id while the image control saves the
url (and is restricted to images, which the media control does with a
parameter). The cropped-image control saves the attachment id to the
setting, so it should extend the media control, for clarity. The distinct
image control likely wouldn't have existed had the Customizer been
introduced after the media manager, and is largely technical debt at this
point. Also fixed in [attachment:29211.5.diff].
--
Ticket URL: <https://core.trac.wordpress.org/ticket/29211#comment:26>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform
More information about the wp-trac
mailing list