Spanish (Español) translation by Esther (you can also view the original English article)
A lo largo de esta serie, hemos creado un plugin que tiene como objetivo proporcionar a los autores una forma de recopilar, gestionar y guardar ideas y referencias a los contenidos que están creando dentro de WordPress.
Al mismo tiempo, también estamos buscando formas de organizar nuestro plugin para que el código y la organización de los archivos sean claros y mantenibles, de modo que a medida que el plugin continúe desarrollándose, podamos agregar, quitar y mantener sus características fácilmente.
Hasta este punto, hemos reunido la organización básica de archivos del plugin así como el front-end, pero en realidad no hemos implementado la funcionalidad para guardar la información en la base de datos. Y si no puedes guardar información, entonces el plugin es de poco beneficio para nadie.
En este post, vamos a saltar de nuevo al código del lado del servidor y comenzaremos a implementar la funcionalidad que hará lo siguiente:
- Verificar que el usuario tiene la capacidad de guardar meta datos del post
- Limpiar los meta datos del post
- Guardar los meta datos del post
- Validar y recuperar los meta datos del post
Tenemos mucho trabajo por delante. En este artículo, vamos a ver los dos primeros pasos y luego en el próximo post, veremos los dos últimos.
Verificación de permisos
Para verificar que el usuario tiene la capacidad de publicar para guardar los metadatos del post, necesitamos implementar un control de seguridad durante el proceso de serialización. Para ello, tenemos que aprovechar un valor nonce.
Un nonce es un "número usado una vez" para proteger las URL y los formularios de un mal uso.
1. Añadir un nonce
Para introducir uno en nuestra meta caja, podemos implementar la funcionalidad en el marcado que se encarga de renderizar la plantilla del post. Para ello, carga admin/views/authors-commentary-navigation.php
y actualiza la plantilla para que incluya una llamada a wp_nonce_field
:
<div id="authors-commentary-navigation"> <h2 class="nav-tab-wrapper current"> <a class="nav-tab nav-tab-active" href="javascript:;">Draft</a> <a class="nav-tab" href="javascript:;">Resources</a> <a class="nav-tab" href="javascript:;">Published</a> </h2> <?php // Include the partials for rendering the tabbed content include_once( 'partials/drafts.php' ); include_once( 'partials/resources.php' ); include_once( 'partials/published.php' ); // Add a nonce field for security wp_nonce_field( 'authors_commentary_save', 'authors_commentary_nonce' ); ?> </div>
En el código anterior, hemos introducido un nonce que corresponde a la acción de guardar el comentario del autor (al que hemos llamado authors_commentary_nonce
) y lo hemos asociado a un valor que se identifica con authors_commentary
.
Veremos dónde entra en juego esto en un momento. Por ahora, si cargas tu navegador, no verás nada nuevo en la pantalla. Eso se debe a que los valores nonce se muestran en un campo oculto.
Para los curiosos, puedes lanzar las herramientas de desarrollo de tu navegador favorito, inspeccionar la meta caja, y deberías encontrar algo como lo siguiente en el marcado:
<input type="hidden" id="authors_commentary_nonce" name="authors_commentary_nonce" value="f3cd131d28">
Por supuesto, el value
de tu nonce será diferente.
2. Revisa el nonce
Para asegurarnos de que el usuario tiene permiso para guardar el post, queremos comprobar tres cosas:
- que el usuario está guardando información para un tipo de post
- que el post no está siendo guardado automáticamente por WordPress
- que el usuario tiene realmente permiso para guardar
Escribiremos dos funciones de ayuda para lograr la primera y la tercera, y usaremos algunas funciones incorporadas para comprobar la número dos (que en realidad se usarán en la segunda función de ayuda).
Primero, vamos a configurar el gancho y la función que se utilizará para aprovechar las funciones de ayuda y guardar los meta datos. En el constructor de Authors_Commentary_Meta_Box
, añade la siguiente línea de código:
<?php add_action( 'save_post', array( $this, 'save_post' ) ); ?>
A continuación, definamos la función. Ten en cuenta que estoy haciendo llamadas a dos funciones en el siguiente bloque de código. Los definiremos en un momento:
<?php /** * Sanitizes and serializes the information associated with this post. * * @since 0.5.0 * * @param int $post_id The ID of the post that's currently being edited. */ public function save_post( $post_id ) { /* If we're not working with a 'post' post type or the user doesn't have permission to save, * then we exit the function. */ if ( ! $this->is_valid_post_type() || ! $this->user_can_save( $post_id, 'authors_commentary_nonce', 'authors_commentary_save' ) ) { return; } }
Dado el código anterior, le decimos a WordPress que dispare nuestra función save_post
cada vez que se llame a su acción save_post
. Dentro de la función, decimos "Si el post que se está guardando no es un tipo de 'post', o si el usuario no tiene permiso para guardar, entonces sal de la función".
Por supuesto, necesitamos definir las funciones para que la lógica funcione. Primero, escribiremos la función is_valid_post_type
como una función private
de la clase actual. Comprobará el array $_POST
para asegurarse de que el tipo de post que se está guardando es, de hecho, un post.
<?php /** * Verifies that the post type that's being saved is actually a post (versus a page or another * custom post type. * * * @since 0.5.0 * @access private * @return bool Return if the current post type is a post; false, otherwise. */ private function is_valid_post_type() { return ! empty( $_POST['post_type'] ) && 'post' == $_POST['post_type']; }
A continuación, añadiremos la función user_can_save
. Esta es la función que asegurará que el post no sea guardado por WordPress, y que si un usuario está guardando la función, entonces el valor de nonce asociado con la acción del post esté correctamente establecido.
<?php /** * Determines whether or not the current user has the ability to save meta data associated with this post. * * @since 0.5.0 * @access private * @param int $post_id The ID of the post being save * @param string $nonce_action The name of the action associated with the nonce. * @param string $nonce_id The ID of the nonce field. * @return bool Whether or not the user has the ability to save this post. */ private function user_can_save( $post_id, $nonce_action, $nonce_id ) { $is_autosave = wp_is_post_autosave( $post_id ); $is_revision = wp_is_post_revision( $post_id ); $is_valid_nonce = ( isset( $_POST[ $nonce_action ] ) && wp_verify_nonce( $_POST[ $nonce_action ], $nonce_id ) ); // Return true if the user is able to save; otherwise, false. return ! ( $is_autosave || $is_revision ) && $is_valid_nonce; }
Observa aquí que estamos pasando el nonce_action
y el nonce_id
que definimos en la plantilla en el primer paso. También estamos usando wp_verify_nonce
en conjunto con dicha información.
Así es como podemos verificar que el post que se está guardando lo hace un usuario que tiene el acceso y los permisos adecuados.
Limpiar los datos
Suponiendo que el usuario trabaja con un tipo de post estándar y que tiene permiso para guardar información, necesitamos limpiar los datos.
Para hacer esto, necesitamos hacer esto a continuación:
- Comprueba que ninguna de las informaciones de los metadatos del post está vacía.
- Despojarnos cualquier cosa cuya escritura en la base de datos pueda ser peligrosa.
Después de hacer esto, veremos cómo guardar la información de cada una de las meta cajas. Pero primero, trabajemos la limpieza Hay un par de maneras en las que podemos implementar esto. Para los propósitos de este post, lo haremos de la manera más directa posible: Comprobaremos la existencia de la información en base a su clave, y si existe, la limpiamos.
Para los programadores experimentados, es probable que noten algunos códigos olorosos con el código que estamos a punto de escribir. Más adelante en esta serie, haremos algunas refactorizaciones para ver cómo podemos hacer que el plugin sea más mantenible, así que es todo parte de la intención de este post en particular.
Dicho esto, vuelve a la función save_post
.
1. Borradores
Ya que la primera pestaña que existe dentro de la meta caja es la pestaña de Borradores, empezaremos con ella. Fíjate que es un textarea
, así que la lógica que existe para limpiar esa información debería ser la siguiente:
- eliminar cualquier etiqueta HTML
- escapar el contenido del área de texto
Recordemos que el textarea
se llama authors-commentary-drafts
para que podamos acceder a ella dentro del array $_POST
. Para lograrlo, usaremos el siguiente código:
<?php // If the 'Drafts' textarea has been populated, then we sanitize the information. if ( ! empty( $_POST['authors-commentary-drafts'] ) ) { // We'll remove all white space, HTML tags, and encode the information to be saved $drafts = trim( $_POST['authors-commentary-drafts'] ); $drafts = esc_textarea( strip_tags( $drafts ) ); // More to come... }
En pocas palabras, estamos comprobando si la información en el array $_POST
está vacía. Si no, entonces limpiaremos los datos.
2. Recursos
Este campo en particular tiene un poco más de forma porque es dinámico. Es decir, el usuario puede tener cualquier cosa desde cero hasta muchos campos de entrada, todos los cuales tendremos que administrar. Recuerda que esta pestaña en particular está diseñada para ser principalmente para URLs, así que tenemos que asegurarnos de que estamos limpiando la información de forma segura de esa manera.
Primero, necesitamos hacer un pequeño cambio en la función createInputElement
que existe en el archivo admin/assets/js/resources.js
. Específicamente, tenemos que asegurarnos de que el atributo name está usando un array para que podamos acceder a él adecuadamente e iterar a través de él al mirar los datos de $_POST
.
Asegúrate de que las líneas de código responsables de crear el elemento real se vean así:
// Next, create the actual input element and then return it to the caller $inputElement = $( '<input />' ) .attr( 'type', 'text' ) .attr( 'name', 'authors-commentary-resources[' + iInputCount + ']' ) .attr( 'id', 'authors-commentary-resource-' + iInputCount ) .attr( 'value', '' );
Fíjate que la clave de lo que hemos hecho está en la línea que actualiza el name
. Específicamente, estamos colocando el número de entradas y los índices del array.
Después, vuelve a la función save_post
y añade el siguiente código (que discutiremos después del bloque):
<?php // If the 'Resources' inputs exist, iterate through them and sanitize them if ( ! empty( $_POST['authors-commentary-resources'] ) ) { $resources = $_POST['authors-commentary-resources']; foreach ( $resources as $resource ) { $resource = esc_url( strip_tags( $resource ) ); // More to come... } }
Debido a que estamos trabajando con un array de entradas, tenemos que comprobar primero que el array no está vacío. Si no lo está, entonces necesitamos iterar a través de él porque no estamos seguros de cuántas entradas vamos a tener que manejar.
Al igual que en el bloque anterior, estamos haciendo un nivel básico de limpieza y fuga. Esto es algo que puedes hacer tan agresivo o tan relajado como quieras. Volveremos a este condicional en el próximo post cuando sea el momento de guardar los datos.
3. Publicado
Esta pestaña es similar a las anteriores en el sentido de que se trata de un número indeterminado de elementos que debemos limpiar. Esto significa que vamos a tener que hacer una pequeña actualización al parcial responsable de renderizar esta entrada.
Por el lado positivo, solo se trata de una casilla de verificación que tiene un valor booleano de estar marcada o no (o, específicamente, "en" o vacía) por lo que limpiar la información es realmente fácil.
Primero, vamos a actualizar el parcial. Localizar admin/views/partials/published.php
. A continuación, encuentra el input
de la casilla de verificación y cámbiala para que se vea así:
<label for="authors-commentary-comment-<?php echo $comment->comment_ID ?>"> <input type="checkbox" name="authors-commentary-comments[<?php echo $comment->comment_ID ?>]" id="authors-commentary-comment-<?php echo $comment->comment_ID ?>" /> This comment has received a reply. </label>
Fíjate en que hemos cambiado el atributo name
para que utilice un array con un índice como valor. A continuación, volveremos a la función save_post
una vez más para introducir la validación de este elemento en particular:
<?php // If there are any values saved in the 'Resources' input, save them if ( ! empty( $_POST['authors-commentary-comments'] ) ) { $comments = $_POST['authors-commentary-comments']; foreach ( $comments as $comment ) { $comment = strip_tags( stripslashes( $comment ) ); // More to come... } }
Al igual que hemos hecho con los datos anteriores, primero comprobamos si el contenido existe. Si es así, lo limpiamos para prepararlo para el almacenamiento. Si no existe, entonces no hacemos nada.
En el guardado
En este punto, estamos posicionados para enfrentarnos a los dos últimos puntos de la serie:
- Guardar y Recuperar
- Refactorización
A partir del próximo post, revisaremos el código que hemos escrito en este post para ver cómo podemos guardarlo en la base de datos y recuperarlo de la base de datos para mostrarlo en el front-end.
A continuación, pasaremos a la refactorización. Después de todo, parte de escribir un código mantenible es asegurarse de que está bien organizado y es fácilmente cambiable. Dado que el código con el que trabajamos diariamente ya ha sido escrito y podría ser refactorizado, vamos a ver cómo hacerlo al final de la serie.
Mientras tanto, revisa el código de arriba, revisa la fuente de GitHub, y deja cualquier pregunta y comentario en el campo de abajo.
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Update me weeklyEnvato Tuts+ tutorials are translated into other languages by our community members—you can be involved too!
Translate this post