Subir la imagen destacada desde el frontend
Nos gustaría que los usuarios pudieran subir la imagen destacada cuando editan publicaciones. ¿Cómo se podría hacer esto? Me imagino que se haría uso de las funciones AJAX de WordPress.
¿Alguna idea?
Marvelloso

Subir archivos mediante AJAX puede ser un poco complicado porque no es posible hacerlo directamente con el objeto XMLHttpRequest del navegador, por lo que necesitas usar algún plugin de carga AJAX. El más sencillo sería el JQuery Form Plugin, que simplifica mucho el proceso y está incluido en WordPress. Para usarlo, primero debes encolarlo:
add_action('wp_print_scripts','include_jquery_form_plugin');
function include_jquery_form_plugin(){
if (is_page('12')){ // solo agregar esto en la página que permite la carga
wp_enqueue_script( 'jquery' );
wp_enqueue_script( 'jquery-form',array('jquery'),false,true );
}
}
En esa página, agrega tu formulario de carga y el código jQuery para llamar al plugin JQuery Form, por ejemplo:
<form id="thumbnail_upload" method="post" action="#" enctype="multipart/form-data" >
<input type="file" name="thumbnail" id="thumbnail">
<input type='hidden' value='<?php wp_create_nonce( 'upload_thumb' ); ?>' name='_nonce' />
<input type="hidden" name="post_id" id="post_id" value="POSTID">
<input type="hidden" name="action" id="action" value="my_upload_action">
<input id="submit-ajax" name="submit-ajax" type="submit" value="Subir">
<form>
<div id="output1"></div>
<script>
$(document).ready(function() {
var options = {
target: '#output1', // elemento(s) objetivo a actualizar con la respuesta del servidor
beforeSubmit: showRequest, // callback antes de enviar
success: showResponse, // callback después de enviar
url: ajaxurl // desde la versión 2.8, ajaxurl siempre está definido en el encabezado del admin y apunta a admin-ajax.php
};
// vincular el formulario usando 'ajaxForm'
$('#thumbnail_upload').ajaxForm(options);
});
function showRequest(formData, jqForm, options) {
// hacer cosas adicionales antes de enviar, como deshabilitar el botón de envío
$('#output1').html('Enviando...');
$('#submit-ajax').attr("disabled", "disabled");
}
function showResponse(responseText, statusText, xhr, $form) {
// hacer cosas adicionales después de enviar
}
</script>
Debes reemplazar POSTID con el ID real de la publicación. Luego, crea la función Ajax para aceptar la carga del archivo y actualizar la imagen destacada de la publicación:
// enganchar la llamada Ajax
// para usuarios logueados
add_action('wp_ajax_my_upload_action', 'my_ajax_upload');
// para usuarios no logueados
add_action('wp_ajax_nopriv_my_upload_action', 'my_ajax_upload');
function my_ajax_upload(){
// verificación básica de seguridad
check_ajax_referer('upload_thumb');
// obtener datos POST
$post_id = $_POST['post_id'];
// incluir los archivos necesarios
require_once(ABSPATH . "wp-admin" . '/includes/image.php');
require_once(ABSPATH . "wp-admin" . '/includes/file.php');
require_once(ABSPATH . "wp-admin" . '/includes/media.php');
// luego iterar sobre los archivos enviados y guardarlos usando media_handle_upload();
if ($_FILES) {
foreach ($_FILES as $file => $array) {
if ($_FILES[$file]['error'] !== UPLOAD_ERR_OK) {
echo "error de carga: " . $_FILES[$file]['error'];
die();
}
$attach_id = media_handle_upload( $file, $post_id );
}
}
// y si deseas establecer esa imagen como imagen destacada del Post, usa:
update_post_meta($post_id,'_thumbnail_id',$attach_id);
echo "Nueva imagen destacada cargada";
die();
}
Espero que esto te ayude.

Esto es brillante. Solo un par de dudas. Es decir, ¿dónde debe ir cada parte? Obviamente el formulario va en la página correspondiente y ese será el ID de la publicación que se usará. La primera acción add_action, ¿es para el área HEAD o para el functions.php? Y el bloque final de ajax que comienza con //hook the ajax call. ¿Dónde va esa parte? Muchas gracias.

el primer y último fragmento de código se pueden colocar en cualquier parte de tu functions.php y el segundo fragmento debe colocarse en la página donde deseas mostrar tu formulario de carga, también puedes convertir el segundo fragmento en un shortcode para facilitar las cosas.

Lo que no entiendo es, ¿cómo sabe el formulario que debe usar my_ajax_upload()? ¿No debería estar incluido en la llamada ajax? Pregunto esto porque tengo un bucle de publicaciones que estoy permitiendo editar y necesitan diferentes funciones para procesar ciertas publicaciones.

El formulario sabe usar my_ajax_upload porque su valor de acción está enlazado (add_action(...
) a la función my_ajax_upload
.

¿Ha cambiado algo recientemente en WP que afectaría esta funcionalidad? Por alguna razón no tengo datos en $_POST
cuando llego a my_ajax_upload
, aunque en la devolución de llamada JS showRequest
el parámetro formData
contiene todo lo que espero.

Curiosamente, si cambio el método del formulario a "GET", todavía hace un post pero con los detalles del formulario en la URL, y solo entonces los datos del formulario están disponibles en el servidor (aunque como parámetros de URL). Actualización: Excepto los archivos :)

@Bainternet, Solución increíble. La función de devolución de llamada de publicación (showResponse) no está funcionando. ¿Tienes alguna sugerencia para eso?
