Cómo añadir campos personalizados a los archivos adjuntos
Spanish (Español) translation by Eva Collados Pascual (you can also view the original English article)
Deberías estar familiarizado con los campos personalizados en WordPress. Los usamos en una entrada o una página para añadir datos adicionales. En WordPress los archivos adjuntos también se guardan como posts, por lo que los campos personalizados están disponibles para ellos también.
Hoy veremos cómo podemos añadir algunos campos personalizados para que los archivos adjuntos puedan incluir más información que tan solo los datos predeterminados.
Lo que haremos
En primer lugar, vamos a crear un plugin para manejar los campos personalizados de los archivos adjuntos. Obtendrás un conjunto de opciones, las transformarás para que formen parte del formulario cuando editemos un archivo adjunto y las guardaremos en la base de datos.
Para esto, usaremos dos ganchos de WordPress:
-
attachment_fields_to_edit
para gestionar el formulario de edición -
attachment_fields_to_save
para guardar los campos personalizados
1. Crea el plugin
Voy a explicar rápidamente en esta parte, ya que no es el propósito principal de este tutorial.
Crea una nueva carpeta "media-fields" en el directorio plugins (wp-content/plugins/media-fields/, por ejemplo) y coloca dentro un archivo (llamado plugin.php). También vamos a poner un archivo llamado custom_media_fields.php que mantendrá nuestras opciones.
Este es el aspecto que debería tener tu archivo plugin.php al principio:
/* Plugin Name: Wptuts+ Custom Media Fields Plugin URI: Description: Create attachments custom fields Version: 0.1 Author: Guillaume Voisin Author URI: http://wp.tutsplus.com/author/guillaumevoisin License: GPL2 */ require_once( plugin_dir_path( __FILE__ ) . '/custom_media_fields.php' ); Class Wptuts_Custom_Media_Fields { private $media_fields = array(); function __construct( $fields ) { } public function applyFilter( $form_fields, $post = null ) { } function saveFields( $post, $attachment ) { } } $cmf = new Wptuts_Custom_Media_Fields( $attchments_options );
Esta es la base, la cual rellenaremos en las siguientes secciones. Por ahora, vamos a definir nuestro conjunto de opciones.
2. Definir nuestras opciones
En el otro archivo, añadiremos algunas opciones para mejorar el formulario de edición de los datos adjuntos. Consideraremos, para este tutorial, opciones para mejorar las imágenes. Por ejemplo, añadiremos campos para los derechos de autor, descripción del autor, marca de agua, valoración y disposición de imágenes.
$themename = "twentytwelve"; $attchments_options = array( 'image_copyright' => array( 'label' => __( 'Image copyright', $themename ), 'input' => 'text', 'helps' => __( 'If your image is protected by copyrights', $themename ), 'application' => 'image', 'exclusions' => array( 'audio', 'video' ), 'required' => true, 'error_text' => __( 'Copyright field required', $themename ) ), 'image_author_desc' => array( 'label' => __( 'Image author description', $themename ), 'input' => 'textarea', 'application' => 'image', 'exclusions' => array( 'audio', 'video' ), ), 'image_watermark' => array( 'label' => __( 'Image watermark', $themename ), 'input' => 'checkbox', 'application' => 'image', 'exclusions' => array( 'audio', 'video' ) ), 'image_stars' => array( 'label' => __( 'Image rating', $themename ), 'input' => 'radio', 'options' => array( '0' => 0, '1' => 1, '2' => 2, '3' => 3, '4' => 4 ), 'application' => 'image', 'exclusions' => array( 'audio', 'video' ) ), 'image_disposition' => array( 'label' => __( 'Image disposition', $themename ), 'input' => 'select', 'options' => array( 'portrait' => __( 'portrtait', $themename ), 'landscape' => __( 'landscape', $themename ) ), 'application' => 'image', 'exclusions' => array( 'audio', 'video' ) ) );
Es básicamente una matriz asociativa que contiene los siguientes parámetros:
-
label
- el nombre del campo que se mostrará -
input
- el tipo de campo de entrada (por ejemplo, texto, selección, radio, ...) -
helps
- información para ayudar al usuario a rellenar el campo -
application
- a que tipo de mime de archivo adjunto se aplicará -
exclusions
- que tipo de mime de adjunto excluir -
required
- ¿será un campo requerido? (valor predeterminadofalse
) -
error_text
- campo opcional para describir el error (si es necesario se establece entrue
) -
options
- campo opcional para los tipos de campo de radio y de selección -
show_in_modal
- si se muestra el campo en modal o no (valor predeterminadotrue
) -
show_in_edit
- si se muestra el campo en la forma de visualización de edición clásica o no (valor predeterminadotrue
) -
extra_rows
- filas adicionales para mostrar contenido (dentro de la misma etiqueta "tr
") -
tr
- filas adicionales (etiqueta "tr
")
Las opciones destacadas representan opciones con las que trabajaremos manualmente, mientras que otras son opciones predeterminadas que WordPress procesará automáticamente.
Como estamos tratando con imágenes, establecemos el parámetro application
en "image
". En realidad se aplicará a todo tipo de imágenes cuyo tipo mimo comience con "image
" como image/jpeg
, image/png
y así sucesivamente. Podrías excluir el tipo de mime gif
estableciéndolo en el campo exclusiones, por ejemplo.
Ahora nuestras opciones están establecidas, vamos a profundizar en los ganchos.
3. Los ganchos
Como se mencionó anteriormente, trabajaremos con dos ganchos.
Enlazamos nuestras dos funciones a esos ganchos con el método constructor.
function __construct( $fields ) { $this->media_fields = $fields; add_filter( 'attachment_fields_to_edit', array( $this, 'applyFilter' ), 11, 2 ); add_filter( 'attachment_fields_to_save', array( $this, 'saveFields' ), 11, 2 ); }
Veamos ahora esos ganchos en detalle.
attachment_fields_to_edit
Tiene dos parámetros:
-
$form_fields
- Una matriz de campos contenidos en el formulario de edición de los adjuntos -
$post
- Objeto que representa el propio archivo adjunto
Usaremos el parámetro $form_fields
para combinar nuestros propios campos y comprobar cada uno de ellos con los requisitos de los adjuntos (con el tipo mime, por ejemplo).
public function applyFilter( $form_fields, $post = null ) { // If our fields array is not empty if ( ! empty( $this->media_fields ) ) { // We browse our set of options foreach ( $this->media_fields as $field => $values ) { // If the field matches the current attachment mime type // and is not one of the exclusions if ( preg_match( "/" . $values['application'] . "/", $post->post_mime_type) && ! in_array( $post->post_mime_type, $values['exclusions'] ) ) { // We get the already saved field meta value $meta = get_post_meta( $post->ID, '_' . $field, true ); // Define the input type to 'text' by default $values['input'] = 'text'; // And set it to the field before building it $values['value'] = $meta; // We add our field into the $form_fields array $form_fields[$field] = $values; } } } // We return the completed $form_fields array return $form_fields; }
En este paso, deberías tener el formulario de edición de adjuntos mejorado con los nuevos campos que hemos añadido. Pero se verán como campos de entrada de texto. Ahora tenemos que considerar diferentes tipos de campos de entrada (radio, casilla de verificación, etc...).
Así que vamos a editar nuestra función para manejar esto. Reemplaza $values['input'] = 'text';
con el siguiente código:
switch ( $values['input'] ) { default: case 'text': $values['input'] = 'text'; break; case 'textarea': $values['input'] = 'textarea'; break; case 'select': // Select type doesn't exist, so we will create the html manually // For this, we have to set the input type to 'html' $values['input'] = 'html'; // Create the select element with the right name (matches the one that wordpress creates for custom fields) $html = '<select name="attachments[' . $post->ID . '][' . $field . ']">'; // If options array is passed if ( isset( $values['options'] ) ) { // Browse and add the options foreach ( $values['options'] as $k => $v ) { // Set the option selected or not if ( $meta == $k ) $selected = ' selected="selected"'; else $selected = ''; $html .= '<option' . $selected . ' value="' . $k . '">' . $v . '</option>'; } } $html .= '</select>'; // Set the html content $values['html'] = $html; break; case 'checkbox': // Checkbox type doesn't exist either $values['input'] = 'html'; // Set the checkbox checked or not if ( $meta == 'on' ) $checked = ' checked="checked"'; else $checked = ''; $html = '<input' . $checked . ' type="checkbox" name="attachments[' . $post->ID . '][' . $field . ']" id="attachments-' . $post->ID . '-' . $field . '" />'; $values['html'] = $html; break; case 'radio': // radio type doesn't exist either $values['input'] = 'html'; $html = ''; if ( ! empty( $values['options'] ) ) { $i = 0; foreach ( $values['options'] as $k => $v ) { if ( $meta == $k ) $checked = ' checked="checked"'; else $checked = ''; $html .= '<input' . $checked . ' value="' . $k . '" type="radio" name="attachments[' . $post->ID . '][' . $field . ']" id="' . sanitize_key( $field . '_' . $post->ID . '_' . $i ) . '" /> <label for="' . sanitize_key( $field . '_' . $post->ID . '_' . $i ) . '">' . $v . '</label><br />'; $i++; } } $values['html'] = $html; break; }
Ahora, podemos crear elementos HTML comunes. Echemos un vistazo a nuestro formulario de edición de archivos adjuntos. Debería tener este aspecto:



Los campos personalizados, dependiendo de si estableces tus opciones modales en true o no, también aparecerán en el formulario modal de medios al editar un post.



Ahora nuestros campos se muestran en nuestro formulario de edición de archivos adjuntos, tenemos que guardarlos en la base de datos. Para esto, vamos a usar el segundo gancho.
attachment_fields_to_save
Este gancho también tiene dos parámetros:
-
$post
-array
que representa la entidad del dato adjunto -
$attachment
- contiene todos los campos adjuntados al post de adjuntos
Ahora, vamos a rellenar la función saveFields
que dejamos en la sección anterior.
function saveFields( $post, $attachment ) { // If our fields array is not empty if ( ! empty( $this->media_fields ) ) { // Browser those fields foreach ( $this->media_fields as $field => $values ) { // If this field has been submitted (is present in the $attachment variable) if ( isset( $attachment[$field] ) ) { // If submitted field is empty // We add errors to the post object with the "error_text" parameter we set in the options if ( strlen( trim( $attachment[$field] ) ) == 0 ) $post['errors'][$field]['errors'][] = __( $values['error_text'] ); // Otherwise we update the custom field else update_post_meta( $post['ID'], '_' . $field, $attachment[$field] ); } // Otherwise, we delete it if it already existed else { delete_post_meta( $post['ID'], $field ); } } } return $post; }
Ok, ahora nuestros campos personalizados se guardan en la base de datos y estarán disponibles para el front-end.
- Ten cuidado al manipular el parámetro post en ambos ganchos. Es un objeto (
object
) en el primero y una matriz (array
) en el segundo. - Consejo: el
update_post_meta
creará la meta si no existe. - Consejo: Prefijamos la clave del campo personalizado con un guión bajo "
_
" de manera que no aparezcan en los metaboxes de los campos personalizados en las páginas de edición de las entradas.
Consideraciones de error
A partir de la versión 3.5, parece que los errores todavía no aparecen en los formularios de edición de datos adjuntos. Traté de investigar el código principal, y a pesar del hecho de que debería haber sido arreglado (http://core.trac.wordpress.org/ticket/13810), parece que no.
Para el proceso de guardado de ajax, es cierto que aún no se ha hecho como se menciona en el archivo ajax-actions.php
:
$errors = $post['errors']; // @todo return me and display me!
Así que en este momento, los errores no van a funcionar correctamente, pero el código se ha creado de manera que cuando esos errores sean corregidos, funcione.
Front End
Para usar esos campos personalizados en tus plantillas, solo tienes que recuperar los metas del post de la misma manera que lo harías para las entradas estándar. No olvides añadir el prefijo "_
" a las claves de los campos personalizados.
Por ejemplo, podrías hacerlo así:
echo "<ul>"; echo " <li><strong>Copyright</strong>: " . get_post_meta( get_the_ID(), '_image_copyright', true ) . "</li>"; echo " <li><strong>Rating</strong>: " . get_post_meta( get_the_ID(), '_image_stars', true ) . "</li>"; echo " <li><strong>Author description</strong>: " . get_post_meta( get_the_ID(), '_image_author_desc', true ) . "</li>"; echo " <li><strong>Image disposition</strong>: " . get_post_meta( get_the_ID(), '_image_disposition', true ) . "</li>"; echo " <li><strong>Watermark?</strong> " . ( get_post_meta( get_the_ID(), '_image_watermark', true ) == "on" ? "yes" : "no" ) . "</li>"; echo "</ul>";



Llevarlo más lejos
Hay varios puntos de mejora dependiendo de tus necesidades:
- Podrías tener tus ajustes en la base de datos para que sea más flexible añadirlos, editarlos y eliminarlos
- Podrías tener un valor predeterminado establecido para todos los nuevos archivos adjuntos cuando no se establece un valor
- Deberías establecer algún estilo para el formulario modal de manera que muestre los campos personalizados correctamente
Conclusión
No dudes en compartir con nosotros tus ideas sobre cómo mejorar este plugin y lo que se esperaría de dicha funcionalidad.