Creando un plugin de Wordpress para los próximos eventos: Tipo personalizado y panel de control
() translation by (you can also view the original English article)
En esta parte de la serie comenzaremos a escribir nuestro código. Siendo más específicos, vamos a:
- Registrar una base personalizada para los eventos.
- Añadir tres metaboxes para la fecha de inicio del evento, la fecha de finalización y el lugar del evento.
- Incluir el widget jQuery UI Datepicker en el administrador de WordPress.
- Escribir la funcionalidad para que el contenido de los meta-campos en nuestro tipo de evento se guarden en la base de datos.
- Agregar columnas personalizadas a la pantalla de administración de correos para eventos.
Este será un tutorial de código abundante, ¡así que abre tu editor de código favorito y toma una taza de café!
Definiendo rutas básicas constantes
Antes de pasar a escribir el código real, comenzaremos definiendo algunas constantes para nuestras rutas. Esto nos ayudará más tarde al registrar nuestros scripts y hojas de estilo.
Primero, abre el archivo upcoming-events.php
y agrega el siguiente código:
1 |
define( 'ROOT', plugins_url( '', __FILE__ ) ); |
2 |
define( 'IMAGES', ROOT . '/img/' ); |
3 |
define( 'STYLES', ROOT . '/css/' ); |
4 |
define( 'SCRIPTS', ROOT . '/js/' ); |
En el código anterior, hemos utilizado la función plugins_url()
para obtener nuestra ruta del directorio raíz. Esto acepta dos parámetros, es decir, $path
y $plugin
.
Ya que no necesitamos referirnos a ningún archivo, sino al directorio raíz de nuestro plugin, no proporcionamos el argumento $path
. Y para el argumento $plugin
, proporcionamos el archivo actual. Después, simplemente agrega los nombres de otros directorios a la constante ROOT
para sus respectivas rutas.
Registrando un tipo de base personalizada para eventos
WordPress es capaz de mantener diferentes tipos de contenido. Podemos crear tantos tipos de contenido como necesitemos dependiendo del escenario en el que estamos trabajando. Para agregar más tipos de contenido (generalmente conocidas como "custom post types"), WordPress proporciona una función register_post_type()
que acepta dos argumentos:
- El tipo de base
- Argumentos adicionales
En el segundo argumento, es decir, la matriz de argumentos adicionales, definimos las etiquetas del tipo base y otras especificaciones con respecto a la visibilidad, capacidad y taxonomías, etc.
En el archivo upcoming-events.php
, agrega el siguiente código para registrar el tipo de base personalizada para eventos:
1 |
$labels = array( |
2 |
'name' => __( 'Events', 'uep' ), |
3 |
'singular_name' => __( 'Event', 'uep' ), |
4 |
'add_new_item' => __( 'Add New Event', 'uep' ), |
5 |
'all_items' => __( 'All Events', 'uep' ), |
6 |
'edit_item' => __( 'Edit Event', 'uep' ), |
7 |
'new_item' => __( 'New Event', 'uep' ), |
8 |
'view_item' => __( 'View Event', 'uep' ), |
9 |
'not_found' => __( 'No Events Found', 'uep' ), |
10 |
'not_found_in_trash' => __( 'No Events Found in Trash', 'uep' ) |
11 |
);
|
12 |
|
13 |
$supports = array( |
14 |
'title', |
15 |
'editor', |
16 |
'excerpt'
|
17 |
);
|
18 |
|
19 |
$args = array( |
20 |
'label' => __( 'Events', 'uep' ), |
21 |
'labels' => $labels, |
22 |
'description' => __( 'A list of upcoming events', 'uep' ), |
23 |
'public' => true, |
24 |
'show_in_menu' => true, |
25 |
'menu_icon' => IMAGES . 'event.svg', |
26 |
'has_archive' => true, |
27 |
'rewrite' => true, |
28 |
'supports' => $supports |
29 |
);
|
30 |
|
31 |
register_post_type( 'event', $args ); |
En el código anterior, hemos definido las etiquetas para nuestro tipo de base de eventos y hemos hecho que el tipo de publicación sea visible para el público al establecer la clave pública
como true
. Para la pantalla de la nueva publicación o posterior edición, hemos incluido tres campos para el título, el contenido y el extracto.
Observa también que hemos marcado los campos de texto estáticos para la traducción usando el dominio de texto uep
el cual es exclusivo de nuestro plugin. También se ha incluido un icono SVG de 20x20 para el menú Eventos.
La función register_post_type()
debe ser llamada a través de la acción init
para que funcione correctamente. Así que debemos envolverlo dentro de una función y engancharlo a la acción init
:
1 |
function uep_custom_post_type() { |
2 |
$labels = array( |
3 |
'name' => __( 'Events', 'uep' ), |
4 |
'singular_name' => __( 'Event', 'uep' ), |
5 |
'add_new_item' => __( 'Add New Event', 'uep' ), |
6 |
'all_items' => __( 'All Events', 'uep' ), |
7 |
'edit_item' => __( 'Edit Event', 'uep' ), |
8 |
'new_item' => __( 'New Event', 'uep' ), |
9 |
'view_item' => __( 'View Event', 'uep' ), |
10 |
'not_found' => __( 'No Events Found', 'uep' ), |
11 |
'not_found_in_trash' => __( 'No Events Found in Trash', 'uep' ) |
12 |
);
|
13 |
|
14 |
$supports = array( |
15 |
'title', |
16 |
'editor', |
17 |
'excerpt'
|
18 |
);
|
19 |
|
20 |
$args = array( |
21 |
'label' => __( 'Events', 'uep' ), |
22 |
'labels' => $labels, |
23 |
'description' => __( 'A list of upcoming events', 'uep' ), |
24 |
'public' => true, |
25 |
'show_in_menu' => true, |
26 |
'menu_icon' => IMAGES . 'event.svg', |
27 |
'has_archive' => true, |
28 |
'rewrite' => true, |
29 |
'supports' => $supports |
30 |
);
|
31 |
|
32 |
register_post_type( 'event', $args ); |
33 |
}
|
34 |
add_action( 'init', 'uep_custom_post_type' ); |
Ahora tenemos lista nuestra base para el tipo de evento. Navega en el panel de WordPress y verás un menú para eventos debajo del menú de comentarios:

Agregando meta-campos para las fechas de los eventos y el lugar de encuentro
Después de registrar correctamente nuestro tipo de base personalizada para eventos, ahora necesitamos agregar tres meta-campos para que el usuario agregue la fecha de inicio del evento, la fecha de finalización y el lugar del evento. Estos meta-campos deben estar contenidos en un metabox personalizado. Podemos agregar convenientemente un metabox personalizado al administrador de WordPress usando la función add_meta_box()
.
Esto acepta siete argumentos que se definen a continuación:
-
$id
es ese id del metabox. También es el atributo id del metabox entregado en la pantalla. -
$title
es el título del metabox. -
$callback
es el nombre de la función que se utilizará para mostrar el contenido del metabox. -
$post_type
es el nombre del tipo de publicación al que queremos añadir este metabox. -
$context
es el área de la página a la que queremos añadir el metabox. Hay tres contextos:normal
,advance
yside
. -
$prioridad
del metabox dentro del contexto dado que puede ser cualquiera comohigh
,core
,default
olow
. -
$callback_args
es una matriz de argumentos que se pueden pasar a la función de devolución de llamada.
En el archivo upcoming-events.php
agrega el siguiente código después de la función uep_custom_post_type()
:
1 |
function uep_add_event_info_metabox() { |
2 |
add_meta_box( |
3 |
'uep-event-info-metabox', |
4 |
__( 'Event Info', 'uep' ), |
5 |
'uep_render_event_info_metabox', |
6 |
'event', |
7 |
'side', |
8 |
'core'
|
9 |
);
|
10 |
}
|
11 |
add_action( 'add_meta_boxes', 'uep_add_event_info_metabox' ); |
Ve a la página Agregar Nuevo en el menú Eventos y verás una advertencia diciendo que la función de devolución de llamadas no está definida. Esto es porque todavía no hemos definido nuestra función de devolución de llamada para procesar el contenido del metabox.
Hagámoslo ahora:
1 |
function uep_render_event_info_metabox( $post ) { |
2 |
|
3 |
// generate a nonce field
|
4 |
wp_nonce_field( basename( __FILE__ ), 'uep-event-info-nonce' ); |
5 |
|
6 |
// get previously saved meta values (if any)
|
7 |
$event_start_date = get_post_meta( $post->ID, 'event-start-date', true ); |
8 |
$event_end_date = get_post_meta( $post->ID, 'event-end-date', true ); |
9 |
$event_venue = get_post_meta( $post->ID, 'event-venue', true ); |
10 |
|
11 |
// if there is previously saved value then retrieve it, else set it to the current time
|
12 |
$event_start_date = ! empty( $event_start_date ) ? $event_start_date : time(); |
13 |
|
14 |
//we assume that if the end date is not present, event ends on the same day
|
15 |
$event_end_date = ! empty( $event_end_date ) ? $event_end_date : $event_start_date; |
16 |
|
17 |
?>
|
18 |
|
19 |
<label for="uep-event-start-date"><?php _e( 'Event Start Date:', 'uep' ); ?></label> |
20 |
<input class="widefat uep-event-date-input" id="uep-event-start-date" type="text" name="uep-event-start-date" placeholder="Format: February 18, 2014" value="<?php echo date( 'F d, Y', $event_start_date ); ?>" /> |
21 |
|
22 |
<label for="uep-event-end-date"><?php _e( 'Event End Date:', 'uep' ); ?></label> |
23 |
<input class="widefat uep-event-date-input" id="uep-event-end-date" type="text" name="uep-event-end-date" placeholder="Format: February 18, 2014" value="<?php echo date( 'F d, Y', $event_end_date ); ?>" /> |
24 |
|
25 |
<label for="uep-event-venue"><?php _e( 'Event Venue:', 'uep' ); ?></label> |
26 |
<input class="widefat" id="uep-event-venue" type="text" name="uep-event-venue" placeholder="eg. Times Square" value="<?php echo $event_venue; ?>" /> |
27 |
|
28 |
<?php <br ?>} |
En el código anterior, primero generamos un campo 'nonce' WordPress. Esto es importante, ya que tenemos que asegurarnos de que nadie secuestre nuestra solicitud de formulario comprometiendo así la seguridad del sitio.
A continuación, recuperamos nuestro meta para la fecha de inicio, fecha de finalización y el lugar del evento utilizando la función get_post_meta()
. Si se trata de una nueva publicación, la marca de tiempo actual se utilizará para las fechas de inicio y fin del evento. De lo contrario, si se edita la publicación, los valores guardados previamente se mostrarán en los campos meta.
Para los meta-campos, hemos representado tres etiquetas y campos de entrada con texto de reserva para dar al usuario una pista sobre el formato de entrada.
Ahora es el momento de añadir el widget jQuery UI DatePicker a la fecha de inicio del evento y el campo de fecha de finalización del evento para conceder más facilidad al usuario al introducir fechas.
Añadiendo jQuery UI Datepicker en el Panel de Control
Recordemos el último artículo, comentamos que la interfaz de usuario de jQuery y el widget jQuery UI Datepicker ya están incluidos en la biblioteca JavaScript de WordPress. También hemos descargado una versión personalizada de la página web oficial de jQuery UI y arrastramos la hoja de estilos en nuestra carpeta css. Si no lo has hecho todavía, toma una copia de la página web oficial de jQuery UI y coloca la hoja de estilos en la carpeta css.
Crea un archivo llamado script.js
dentro de la carpeta js. Este es el archivo en el cual vamos a inicializar el widget jQuery UI DatePicker para nuestra inicio del evento y las fechas de finalización.
Ahora vamos a poner en cola el código JavaScript y la hoja de estilos de acompañamiento en nuestro administrador utilizando el admin_enqueue_scripts
:
1 |
function uep_admin_script_style( $hook ) { |
2 |
|
3 |
if ( 'post.php' == $hook || 'post-new.php' == $hook ) { |
4 |
wp_enqueue_script( |
5 |
'upcoming-events', |
6 |
SCRIPTS . 'script.js', |
7 |
array( 'jquery', 'jquery-ui-datepicker' ), |
8 |
'1.0', |
9 |
true
|
10 |
);
|
11 |
|
12 |
wp_enqueue_style( |
13 |
'jquery-ui-calendar', |
14 |
STYLES . 'jquery-ui-1.10.4.custom.min.css', |
15 |
false, |
16 |
'1.10.4', |
17 |
'all'
|
18 |
);
|
19 |
}
|
20 |
}
|
21 |
add_action( 'admin_enqueue_scripts', 'uep_admin_script_style' ); |
Puedes haber notado que no tenemos en cola el jQuery y el DatePicker de jQuery UI por separado sino que agregó una especie una dependencia para el archivo script.js
.
Al hacerlo, WordPress se asegura que esa jQuery y jQuery UI DatePicker (junto con las propias dependencias) estén en cola ANTES del archivo script.js
.
La función de devolución de llamada acepta un argumento para la página gancho es decir, la página actual del panel de control. Dado que no queremos incluir este archivo JavaScript en cada página del Panel de Control, comprobamos a través del primer requisito si la página actual es post.php
o post-new.php
.
De esta manera, hemos restringido el JavaScript sólo para incluirse en editar la publicación o las pantallas de nuevas publicaciones, pero ¿qué ocurre si alguien crea o actualiza una publicación normal o una página? El archivo anterior JavaScript también se incluirá en esas páginas, ya que el gancho es el mismo para los dos.
Para ello, comprobaremos más si la publicación que se está editando es un tipo de publicación de evento:
1 |
function uep_admin_script_style( $hook ) { |
2 |
global $post_type; |
3 |
|
4 |
if ( ( 'post.php' == $hook || 'post-new.php' == $hook ) && ( 'event' == $post_type ) ) { |
5 |
wp_enqueue_script( |
6 |
'upcoming-events', |
7 |
SCRIPTS . 'script.js', |
8 |
array( 'jquery', 'jquery-ui-datepicker' ), |
9 |
'1.0', |
10 |
true
|
11 |
);
|
12 |
|
13 |
wp_enqueue_style( |
14 |
'jquery-ui-calendar', |
15 |
STYLES . 'jquery-ui-1.10.4.custom.min.css', |
16 |
false, |
17 |
'1.10.4', |
18 |
'all'
|
19 |
);
|
20 |
}
|
21 |
}
|
22 |
add_action( 'admin_enqueue_scripts', 'uep_admin_script_style' ); |
Ahora el archivo JavaScript anterior sólo se incluirá si el gancho de página es post.php
o post-new.php
y la publicación que se está creando o editando es de tipo event
.
Vamos a inicializar el JQuery UI DatePicker. Abre el archivo script.js
desde el directorio js
y añade el siguiente código:
1 |
(function( $ ) { |
2 |
|
3 |
$( '#uep-event-start-date' ).datepicker({ |
4 |
dateFormat: 'MM dd, yy', |
5 |
onClose: function( selectedDate ){ |
6 |
$( '#uep-event-end-date' ).datepicker( 'option', 'minDate', selectedDate ); |
7 |
}
|
8 |
});
|
9 |
$( '#uep-event-end-date' ).datepicker({ |
10 |
dateFormat: 'MM dd, yy', |
11 |
onClose: function( selectedDate ){ |
12 |
$( '#uep-event-start-date' ).datepicker( 'option', 'maxDate', selectedDate ); |
13 |
}
|
14 |
});
|
15 |
|
16 |
})( jQuery ); |
Ten en cuenta que hemos restringido la fecha de inicio del evento para que no sea mayor que la fecha de finalización del evento y viceversa.
Comprueba si la inicialización ha tenido éxito al ir a la página Agregar nuevo evento y al hacer clic en cualquiera de las fechas de inicio o fin del evento. Deberías ver la ventana DatePicker y poder ingresar la fecha navegando por el calendario y haciendo clic en la fecha deseada.

Hasta ahora, hemos escrito una cantidad justa de código, pero nuestro plugin todavía carece de la funcionalidad más fundamental: Guardar y actualizar los valores del meta-campo del evento.
Obteniendo los valores meta-campo de los eventos guardados en la base de datos
Ahora que hemos creado nuestra base personalizada y hemos agregado tres meta-campos para la fecha de inicio del evento, la fecha de finalización y el lugar del evento, debemos asegurarnos de que los valores de estos campos meta se guarden en la base de datos.
WordPress proporciona un gancho o 'hook' para este propósito que se dispara cada vez que se está guardando una publicación. El gancho es save_post
y su función de devolución de llamada acepta un argumento para el ID de la publicación que se está guardando. Utilizando este gancho, podemos guardar los valores de nuestros meta-campos en la base de datos junto con los campos de publicación regular, como el título y el contenido.
1 |
function uep_save_event_info( $post_id ) { |
2 |
|
3 |
}
|
4 |
add_action( 'save_post', 'uep_save_event_info' ); |
Pero una vez más, tenemos que comprobar si la entrada que se guarda es de tipo event
. Para ello, comprobaremos la variable global $_POST
:
1 |
function uep_save_event_info( $post_id ) { |
2 |
// checking if the post being saved is an 'event',
|
3 |
// if not, then return
|
4 |
if ( 'event' != $_POST['post_type'] ) { |
5 |
return; |
6 |
}
|
Ahora vamos a comprobar el estado de guardar, es decir, si la publicación se guarda automáticamente o es una revisión. WordPress proporciona dos etiquetas condicionales para ese propósito:
wp_is_post_autosave( $post_id )
wp_is_post_revision( $post_id )
Podemos utilizar estas dos etiquetas condicionales de la siguiente manera:
1 |
$is_autosave = wp_is_post_autosave( $post_id ); |
2 |
$is_revision = wp_is_post_revision( $post_id ); |
Pero también necesitamos asegurarnos de que el 'nonce' sea válido. ¿Recuerdas que definimos un campo nonce usando la función wp_nonce_field()
al mostrar el metabox? Comprobaremos el valor del mismo nonce:
1 |
$is_valid_nonce = ( isset( $_POST['uep-event-info-nonce'] ) && ( wp_verify_nonce( $_POST['uep-event-info-nonce'], basename( __FILE__ ) ) ) ) ? true : false; |
Coloca esas tres condiciones en una sola declaración y estamos bien para ir:
1 |
if ( $is_autosave || $is_revision || ! $is_valid_nonce ) { |
2 |
return; |
3 |
}
|
Después de haber realizado las operaciones necesarias antes de guardar los valores meta, ahora estamos listos para insertarlos en la base de datos:
1 |
function uep_save_event_info( $post_id ) { |
2 |
|
3 |
// checking if the post being saved is an 'event',
|
4 |
// if not, then return
|
5 |
if ( 'event' != $_POST['post_type'] ) { |
6 |
return; |
7 |
}
|
8 |
|
9 |
// checking for the 'save' status
|
10 |
$is_autosave = wp_is_post_autosave( $post_id ); |
11 |
$is_revision = wp_is_post_revision( $post_id ); |
12 |
$is_valid_nonce = ( isset( $_POST['uep-event-info-nonce'] ) && ( wp_verify_nonce( $_POST['uep-event-info-nonce'], basename( __FILE__ ) ) ) ) ? true : false; |
13 |
|
14 |
// exit depending on the save status or if the nonce is not valid
|
15 |
if ( $is_autosave || $is_revision || ! $is_valid_nonce ) { |
16 |
return; |
17 |
}
|
18 |
|
19 |
// checking for the values and performing necessary actions
|
20 |
if ( isset( $_POST['uep-event-start-date'] ) ) { |
21 |
update_post_meta( $post_id, 'event-start-date', strtotime( $_POST['uep-event-start-date'] ) ); |
22 |
}
|
23 |
|
24 |
if ( isset( $_POST['uep-event-end-date'] ) ) { |
25 |
update_post_meta( $post_id, 'event-end-date', strtotime( $_POST['uep-event-end-date'] ) ); |
26 |
}
|
27 |
|
28 |
if ( isset( $_POST['uep-event-venue'] ) ) { |
29 |
update_post_meta( $post_id, 'event-venue', sanitize_text_field( $_POST['uep-event-venue'] ) ); |
30 |
}
|
31 |
}
|
32 |
add_action( 'save_post', 'uep_save_event_info' ); |
Aquí, hemos guardado los valores meta en la base de datos con la función update_post_meta()
que acepta cuatro argumentos de los cuales hemos pasado los tres primeros:
-
$post_id
es el id de la publicación a la que pertenece el valor meta. -
$meta_key
es la clave del campo meta personalizado. -
$meta_value
es el nuevo valor meta. -
$prev_value
es el valor meta anterior a ser reemplazado.
Ten en cuenta que no estamos guardando la fecha en la descripción textual, pero primero la estamos convirtiendo a la marca de tiempo de UNIX usando la función strtotime()
de PHP. De esta manera, será mucho más fácil al comparar las fechas entre sí durante la realización de la meta consulta en el front-end.
En este punto, la parte más fundamental de nuestro tutorial se ha completado. Es hora de agregar algunas columnas personalizadas a la pantalla del panel de control de eventos.
Añadiendo columnas personalizadas a la pantalla del Administrador
Dado que los eventos tienen su propia información específica contenida en sus campos personalizados, es apropiado mostrarlos en las columnas personalizadas en la pantalla posterior a la administración para una mejor accesibilidad por parte del usuario.
De forma predeterminada, WordPress muestra el título y las columnas de fecha para el tipo personalizado, pero agregamos tres columnas más para la fecha de inicio del evento, la fecha de finalización y el lugar.
Podemos controlar qué columnas añadir y cuáles ocultar por el gancho de WordPress manage_edit-$post_columns
donde $post
es el nombre del tipo de la publicación personalizada. La función de devolución de llamada acepta una matriz para las columnas que ya se muestran.
1 |
function uep_custom_columns_head( $defaults ) { |
2 |
unset( $defaults['date'] ); |
3 |
|
4 |
$defaults['event_start_date'] = __( 'Start Date', 'uep' ); |
5 |
$defaults['event_end_date'] = __( 'End Date', 'uep' ); |
6 |
$defaults['event_venue'] = __( 'Venue', 'uep' ); |
7 |
|
8 |
return $defaults; |
9 |
}
|
10 |
add_filter( 'manage_edit-event_columns', 'uep_custom_columns_head', 10 ); |
En el código anterior, hemos desactivado la columna de fecha predeterminada y en su lugar, hemos añadido nuestras tres columnas personalizadas.
Pero el contenido de las respectivas columnas no se mostrará hasta que lo definamos utilizando el gancho manage_$post_posts_custom_column
donde $post es el nombre del tipo de la publicación personalizada.
1 |
function uep_custom_columns_content( $column_name, $post_id ) { |
2 |
|
3 |
if ( 'event_start_date' == $column_name ) { |
4 |
$start_date = get_post_meta( $post_id, 'event-start-date', true ); |
5 |
echo date( 'F d, Y', $start_date ); |
6 |
}
|
7 |
|
8 |
if ( 'event_end_date' == $column_name ) { |
9 |
$end_date = get_post_meta( $post_id, 'event-end-date', true ); |
10 |
echo date( 'F d, Y', $end_date ); |
11 |
}
|
12 |
|
13 |
if ( 'event_venue' == $column_name ) { |
14 |
$venue = get_post_meta( $post_id, 'event-venue', true ); |
15 |
echo $venue; |
16 |
}
|
17 |
}
|
18 |
add_action( 'manage_event_posts_custom_column', 'uep_custom_columns_content', 10, 2 ); |
Primero hemos comprobado la columna que se está mostrando y luego hemos hecho eco del contenido en consecuencia. El último parámetro en la llamada de función add_action()
es el número de argumentos que son aceptados por la función de devolución de llamada (callback) –en nuestro caso– son dos.



¿Qué sigue?
En este tutorial, registramos con éxito un tipo personalizado para eventos. También aprendimos a incluir un metabox personalizado y un widget jQuery UI DatePicker integrado en el panel de WordPress. Además, para otorgar al usuario mayor accesibilidad, hemos añadido columnas personalizadas en nuestra pantalla de administración de las publicaciones.
Si bien hemos casi completado el Panel de Control, todavía hay algo que nos queda por abordar — el front-end.
En la próxima prueba de la serie, crearemos un widget personalizado para mostrar la lista de los próximos eventos en la barra lateral. Examinaremos la clase WP_Query
más de cerca para recuperar las publicaciones en función de sus valores meta.