[wp-trac] [WordPress Trac] #49490: Missing wrapper function and action hook for new attachments
WordPress Trac
noreply at wordpress.org
Fri Feb 21 22:44:38 UTC 2020
#49490: Missing wrapper function and action hook for new attachments
-------------------------------------+-------------------------------------
Reporter: luisrivera | Owner: (none)
Type: enhancement | Status: new
Priority: normal | Milestone: Awaiting Review
Component: Media | Version:
Severity: normal | Keywords: needs-design dev-
Focuses: rest-api, performance, | feedback 2nd-opinion
coding-standards |
-------------------------------------+-------------------------------------
Everywhere you look for the code related to inserting a new attachment you
find 3 steps are needed:
1. wp_insert_attachment
2. wp_generate_attachment_metadata
3. wp_update_attachment_metadata
I see no reason not to have a wrapper function instead of having these 3
functions being repeated all over core files + 3rd party themes and
plugins. Plus, as people commit changes in core mistakes are occurring
[ticket:49449].
The most important reason to create this new wrapper function is to
improve interoperability by adding a real hook to know when an attachment
has been totally processed by core. This is needed by many plugins that
work with images or caching. Right now the hook most used to know of a new
attachment is `add_attachment` found in `wp_insert_post()`, but this is
run before step 2 and 3, therefore attachment metadata has not been
created yet.
Developers are having to create a custom wrapper function to add this hook
(my company included) in their projects and that means attachments
inserted via WP Dashboard wont be taken into action.
`media_handle_upload()` is a good example of the wrapper function I am
talking about, but sadly it goes out of scope by assuming the file will be
located in `$_FILES` variable instead of receiving the file by a
parameter, therefore is not friendly or future proof. When that function
was created I guess it wasn't taken into consideration that files can be
uploaded to the server in many ways. Plus is lacking the appropriate hooks
too.
Even the `WP_REST_Attachments_Controller` had to create custom methods to
fulfill a scenario where attachment data is being sent in the body of the
request.
A fast search in core for `wp_insert_attachment` will illustrate how this
function is followed by `wp_generate_attachment_metadata()` and
`wp_update_attachment_metadata()` in most cases:
* `media_handle_sideload()`
* `media_handle_upload()`
* `wp_ajax_crop_image()`
* `Custom_Background::handle_upload()`
* `WP_Site_Icon::insert_attachment()`
* `wp_xmlrpc_server::mw_newMediaObject()`
* `WP_REST_Attachments_Controller`
I wont even mention third party implementations I’ve found.
A quick boilerplate...
{{{#!php
<?php
/**
* Creates a single attachment.
*
* @param string|array $args Required. Arguments for
inserting a post of type attachment.
* @param array $data
Required. An array of data for a single file
*
Like the one supplied by wp_handle_upload() or wp_handle_sideload()
* @param string $context Optional. Provide context for
hooks (eg. AJAX, REST)
* @param bool $wp_error Optional. Whether to return a
WP_Error on failure. Default false.
*
* @return int|WP_Error The attachment ID on success. The value 0 or
WP_Error on failure.
*
* @author Luis Rivera
*/
function wp_process_attachment ( string|array $args, string $data = false,
string $context, bool $wp_error = false ) {
/**
* Just let us play
* Maybe I need to remove a filter base on X condition
*/
do_action( 'pre_filter_process_attachment', $args, $data, $context
);
/**
* Allow modifications to the file
* First filter because post args may depend on file data
*/
$data = apply_filters( 'wp_process_attachment_file', $data, $args,
$context );
/**
* Allow modifications to the post args
*/
$args = apply_filters( 'wp_process_attachment_args', $args, $data,
$context );
/**
* Filters whether to short-circuit the process
* At last to evaluate values after filters has been applied
*
* If a non-null value is passed to the filter, all the process
will be cancel
*
* @param mixed $process If null
(default) continue process
*
If is_wp_error() && $wp_error the error will be returned
*/
$process = apply_filters( 'wp_process_attachment', null, $args,
$data, $context );
if ( $process !== null ) {
if ( $wp_error && is_wp_error($process) ) {
return $process;
}
return false;
}
do_action( 'before_process_attachment', $args, $data, $context );
if ( empty( $args['post_title'] ) ) {
$args['post_title'] = preg_replace( '/\.[^.]+$/', '',
wp_basename( $data['file'] ) );
}
if ( empty( $args['post_mime_type'] ) ) {
$args['post_mime_type'] = $data['type'];
}
if ( empty( $args['post_status'] ) ) {
$args['post_status'] = 'inherit';
}
$attachment_id = wp_insert_attachment( $args, $data['file']);
/** Include image functions to get access to
wp_generate_attachment_metadata(). */
require_once ABSPATH . 'wp-admin/includes/image.php';
$metadata = wp_generate_attachment_metadata( $attachment_id,
$data['file'] );
wp_update_attachment_metadata( $attachment_id, $metadata );
do_action( 'after_process_attachment', $attachment_id);
return $attachment_id;
}
}}}
--
Ticket URL: <https://core.trac.wordpress.org/ticket/49490>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform
More information about the wp-trac
mailing list