Skip to main content

Escribiendo un manejador de descargas en WordPress

Publicado hace
Actualizado hace
29 minutos de lectura

Siempre he dicho que puedes hacer casi cualquier cosa usando WordPress gracias a todas las funciones y APIs integradas que tenemos a nuestra disposición. Sin embargo, parece que para algunas de ellas la documentación todavía está en etapas iniciales.

He tenido la necesidad de usar estas APIs en el pasado, pero casi nunca las he usado todas juntas. Así que con la esperanza de aprender un poco más sobre ellas, decidí escribir un plugin simple usando todas ellas, y documentar mi progreso aquí.

Escribiré un simple manejador de descargas, llamado Mah Download Manager (¡patente pendiente!). Este plugin debería ayudarme a subir archivos, almacenarlos en la base de datos y mostrar una lista de los datos guardados.

Para hacer esto, usaremos tres de las APIs en WordPress, Filesystem, Database y List Table. Así que comencemos.

Parte I – Definir el plugin y configurar la función de subida

Este artículo es un poco avanzado, así que asumo que al menos tienes algo de conocimiento sobre cómo escribir un plugin de WordPress, por eso no entraré en detalles específicos, simplemente comencemos:

mah-plugin-manager.php

1<?php
2/**
3 * Plugin Name: Mah Download Manager
4 * Plugin URI: https://github.com/emeaguiar/mah-download-manager
5 * Description: Un simple manejador de descargas para WordPress
6 * Version: 1.0
7 * Author: Mario Aguiar
8 * Author URI: https://www.marioaguiar.net
9 * License: GPL2
10 */
11class Mah_Download_Manager {
12
13 function __construct() {
14 add_action( 'admin_menu', array( $this, 'register_menu_pages' ) );
15 }
16
17 function register_menu_pages() {
18 add_menu_page( 'Mah Download manager', 'Downloads', 'manage_options', 'mah-download-manager', array( $this, 'display_menu_page' ), 'dashicons-download', 12 );
19 }
20
21 function display_menu_page() {
22
23?>
24
25“>
26
27Aquí mostraremos una lista de los archivos subidos.
28
29<?php
30 }
31}
32
33$mah_download_manager = new Mah_Download_Manager;
34

Aquí estoy definiendo una estructura muy básica, agrego los metadatos del plugin y una página de administración donde mostraré una lista de todos nuestros archivos más adelante. Por ahora está vacía, así que configuremos otra página para agregar los archivos y luego volveremos a esta.

1add_submenu_page( 'mah-download-manager', __( 'Agregar nuevo archivo', 'mah-download-manager' ), __( 'Agregar nuevo archivo', 'mah-download-manager' ), 'upload_files', 'mah-download-manager/new', array( $this, 'display_add_new_page' ) );
2

Primero, creamos una nueva página de submenú donde pondremos nuestro formulario de carga, esta nueva página solo será visible para las personas que pueden subir archivos, y mostrará lo que pongamos en la función display_add_new_page.

1function display_add_new_page() {
2 if ( $this->form_is_submitted() ) {
3 return;
4 }
5?>
6
7 : ” name=”mdm-upload”>
8
9<?php
10 }
11

Un formulario muy simple, solo agregamos un campo para seleccionar nuestro archivo, un botón de envío y un campo de nonce para asegurarnos de que estamos enviando el formulario desde el lugar correcto, también verificamos si nuestro formulario se está procesando, en caso de que lo esté, no mostramos el formulario. Dado que dejamos nuestro atributo action vacío, el formulario se procesará en la misma función, a menos que realicemos esta verificación.

1function form_is_submitted() {
2 if ( empty( $_POST ) ) {
3 return false;
4 }
5 check_admin_referer( 'mah-download-manager' );
6
7 $mdm_form_fields = array( 'mdm-file', 'mdm-upload' );
8 $mdm_method = '';
9
10 if ( isset( $_POST[ 'mdm-upload' ] ) ) {
11 $url = wp_nonce_url( 'mah-download-manager/new', 'mah-download-manager' );
12 if ( ! $creds = request_filesystem_credentials( $url, $mdm_method, false, false, $mdm_form_fields ) ) {
13 return true;
14 }
15
16 if ( ! WP_Filesystem( $creds ) ) {
17 request_filesystem_credentials( $url, $mdm_method, true, false, $mdm_form_fields );
18 return true;
19 }
20
21 $fileTempData = $_FILES[ 'mdm-file' ];
22
23 $this->upload_file( $fileTempData );
24 }
25 return true;
26 }
27

Ahora, si el formulario se ha enviado, verificamos si está vacío, si lo está, no necesitamos continuar en esta función, así que devolvemos false. check_admin_referer verifica si el campo de nonce que agregamos al formulario es válido y si lo es, estamos listos para realizar nuestra magia con la API del sistema de archivos.

Primero, nos aseguramos de que hemos enviado el formulario verificando el valor del botón de carga, luego preparamos un nuevo nonce para acompañar nuestra pantalla de carga.

request_filesystem_credentials verifica si tenemos las credenciales para subir archivos dependiendo del método que usemos para realizar la carga, en este caso dejé $mdm_method en blanco, WordPress por defecto usará acceso FTP. Si no tenemos las credenciales, WordPress mostrará otra pantalla pidiéndolas.

Una vez que WordPress ha confirmado que podemos escribir en el servidor, podemos guardar los datos temporales del archivo en una variable y luego ir a nuestra función de carga.

1function upload_file( $file ) {
2 $file = ( ! empty( $file ) ) ? $file : new WP_Error( 'empty_file', __( "Parece que no subiste un archivo.", 'mah-download-manager' ) );
3
4 if ( is_wp_error( $file ) ) {
5 wp_die( $file->get_error_message(), __( 'Error al subir el archivo.', 'mah-download-manager' ) );
6 }
7
8 $fileTempDir = $file[ 'tmp_name' ];
9 $filename = trailingslashit( $this->uploadsDirectory[ 'path' ] ) . $file[ 'name' ];
10
11 $response = $this->move_file( $fileTempDir, $filename );
12
13 if ( is_wp_error( $response ) ) {
14 wp_die( $response->get_error_message(), __( 'Error subiendo el archivo.', 'mah-download-manager' ) );
15 }
16
17 wp_redirect( admin_url( 'admin.php?page=mah-download-manager&message=1' ) );
18 exit;
19}
20

Primero me aseguro de que nuestra variable $file no esté vacía, si lo está, algo salió mal en el proceso y uso WP_Error para informar al usuario sobre el problema.

Si no hay error, preparo la ruta donde se guardará el archivo usando $this->uploadsDirectory['path'] y el nombre y extensión de nuestro archivo en $file['name'].

Luego movemos nuestro archivo a su nueva ubicación permanente en el servidor y esperamos la respuesta, si la respuesta de nuestra próxima función es exitosa, redirigiremos al usuario de nuevo a la pantalla principal y le mostraremos un mensaje de éxito, si no, mostraremos otro error.

1function move_file( $from, $to ) {
2 global $wp_filesystem;
3 if ( $wp_filesystem->move( $from, $to ) ) {
4 return true;
5 } else {
6 return WP_Error( 'moving_error', __( "Error tratando de mover el archivo a su nueva ubicación.", 'mah-download-manager' ) );
7 }
8}
9

Esta función es realmente simple, simplemente llamamos a la API del sistema de archivos y tratamos de mover el archivo, si funciona, devolvemos true, si no funciona, devolvemos un error.

¿Recuerdas cómo redirigí al usuario junto con un mensaje de éxito? Cuando registré la página principal, es posible que hayas notado que también agregué esta línea:

1<?php do_action( 'mdm_display_messages' ); ?>
2

Esto es lo que conocemos como un hook, o para ser más precisos, este es el lugar donde se ejecutará nuestro hook. El núcleo de WordPress está lleno de estas bellezas, y sí, podemos crear las nuestras, tal como hice aquí. Creé esto para que sea más sencillo agregar mensajes. Ahora enganchemos algo a él.

1function display_messages() {
2 if ( ! isset( $_GET[ 'message' ] || ! intval( $_GET[ 'message' ] ) ) ) {
3 return;
4 }
5
6 $message = $_GET[ 'message' ];
7
8 switch ( $message ) {
9 case 1:
10 $class = 'updated';
11 $text = __( 'Archivo subido correctamente.', 'mah-download-manager' );
12 break;
13 }
14
15 echo '
16
17‘ . $text . ‘
18
19';
20}
21

Y agregamos el hook a la función __construct.

1add_action( 'mdm_display_messages', array( $this, 'display_messages' ) );
2

Ahora la página verificará si se ha enviado un $message, si es así, buscará en la lista un partido y mostrará el mensaje.

El camino hasta ahora…

Revisa el código completo en mi github.

Hasta ahora tenemos un plugin que nos permite subir y almacenar archivos en el servidor, pero eso es todo, todavía necesitamos hacer un seguimiento de esos archivos, almacenar sus datos y mostrárselos al usuario. Hasta ahora tenemos un plugin que nos permite subir y almacenar archivos en el servidor, pero eso es todo, todavía necesitamos hacer un seguimiento de esos archivos, almacenar sus datos y mostrárselos al usuario. Primero, almacenemos los datos en nuestra base de datos. Ahora, hay algunas formas en las que podríamos hacer esto, pero creo que la forma más adecuada para este plugin es crear nuestras propias tablas en la base de datos.

Parte II – Instalación, desinstalación y almacenamiento de datos en la base de datos

La mejor manera de hacer esto es creando una función de instalación, y engancharla al proceso de activación del plugin, este hook se ve un poco diferente al resto, pero confía en mí, es el correcto.

1register_activation_hook( __FILE__, array( $this, 'install' ) );
2

Esto ejecutará nuestro método install() solo cuando nuestro plugin se active, pero lo ejecutará cada vez que se active nuestro plugin, así que asegurémonos de que solo ejecutamos el proceso de instalación si no lo hemos hecho antes, me gusta hacerlo agregando una variable de versión de la base de datos, de esa manera seguirá siendo útil en caso de que necesitemos actualizarla más adelante.

1function __construct() {
2 $this->mdb_db_version = 1;
3...
4

Ahora nuestro método de instalación.

1function install() {
2 $current_db_version = get_option( 'mdm_db_version' );
3 if ( ! $current_db_version ) {
4 global $wpdb;
5
6 $table_name = $wpdb->prefix . "mah_download_manager";
7
8 $charset_collate = '';
9
10 if ( ! empty( $wpdb->charset ) ) {
11 $charset_collate = "DEFAULT CHARACTER SET {$wpdb->charset}";
12 }
13
14 if ( ! empty( $wpdb->collate ) ) {
15 $charset_collate .= " COLLATE {$wpdb->collate}";
16 }
17
18 $sql = "CREATE TABLE $table_name (
19 id mediumint(9) NOT NULL AUTO_INCREMENT,
20 date datetime DEFAULT '0000-00-00 00:00:00' NOT NULL,
21 name tinytext NOT NULL,
22 url varchar(255) DEFAULT '' NOT NULL,
23 UNIQUE KEY id (id)
24 ) $charset_collate;";
25
26 require_once ABSPATH . 'wp-admin/includes/upgrade.php';
27
28 dbDelta( $sql );
29
30 add_option( 'mdm_db_version', 1 );
31 } elseif ( $current_db_version < $this->mdb_db_version ) {
32 $this->upgrade( $current_db_version );
33 }
34
35}
36

Esta función hace varias cosas, así que desglosemos los pasos:

  1. Intentamos recuperar el número de versión de la base de datos de las opciones de WordPress, en caso de que sea la primera vez que activamos el plugin, esto no existirá, lo que significa que podemos instalar el plugin sin preocupaciones.
  2. Luego llamamos a $wpdb, la API de la base de datos, y configuramos la estructura básica de nuestra tabla. $wpdb->prefix es el prefijo actualmente utilizado por nuestra instalación, y se define en el archivo wp-config.
  3. Después de eso necesitamos definir manualmente nuestra consulta SQL, con los campos que necesitaremos, en este caso elegí almacenar la fecha, el nombre del archivo y la URL en el servidor.
  4. dbDelta() es la función que usaremos para ejecutar esta consulta, como no se carga por defecto, necesitamos incluir las funciones de actualización y ejecutar la consulta.
  5. Configuramos una opción en WordPress, esto almacenará la versión actual del plugin, que se comprobará la próxima vez que se active el plugin.
  6. Si la opción de versión está presente en WordPress, pero es diferente a la versión que establecimos en el plugin, esto significa que necesitamos actualizar nuestra base de datos, así que ejecutamos el script de actualización.

El script de actualización está vacío por ahora, pero será útil en el futuro:

1/**
2 * Reservado para futuras actualizaciones
3 */
4function upgrade( $current ) {
5
6}
7

No olvides, al igual que creamos tablas al instalar el plugin, necesitamos eliminarlas cuando lo desinstalamos, esto es importante porque no queremos tener opciones lingüísticas en el sitio web.

uninstall.php

1<?php
2 if ( !defined( 'WP_UNINSTALL_PLUGIN' ) )
3 exit();
4
5 $option_name = 'mdm_db_version';
6
7 delete_option( $option_name );
8
9 // For site options in multisite
10 delete_site_option( $option_name );
11
12 global $wpdb;
13
14 $table_name = $wpdb->prefix . "mah_download_manager";
15
16 $wpdb->query( "DROP TABLE IF EXISTS {$table_name}" );
17

Quitamos las opciones que agregamos, y eliminamos la tabla que creamos, asegurándonos de que todo quede como estaba antes de instalar nuestro plugin.

Ahora necesitamos cambiar nuestra función de carga, para que almacene los datos después de una carga exitosa, esperamos esa respuesta y luego redirigimos al usuario.

1function upload_file( $file ) {
2...
3 $file_id = $this->store_data( $file );
4
5 if ( $file_id ) {
6 wp_redirect( admin_url( 'admin.php?page=mah-download-manager&message=1' ) );
7 exit();
8 } else {
9 wp_die( 'Hubo un error guardando el archivo en la base de datos' );
10 }
11
12}
13

Nuestra función store_data se ve así:

1function store_data( $file ) {
2 global $wpdb;
3
4 $this->table_name = $wpdb->prefix . "mah_download_manager";
5
6 $data = array(
7 'name' => sanitize_file_name( $file[ 'name' ] ),
8 'type' => sanitize_mime_type( $file[ 'type' ] ),
9 'size' => intval( $file[ 'size' ] ),
10 'url' => trailingslashit( $this->uploadsDirectory[ 'url' ] ) . $file[ 'name' ],
11 'path' => trailingslashit( $this->uploadsDirectory[ 'path' ] ) . sanitize_file_name( $file[ 'name' ] )
12 );
13
14 return $wpdb->insert( $this->table_name, $data );
15
16}
17

Aquí configuramos la tabla que usaremos para almacenar los datos, y creamos un array $data para definir qué datos vamos a guardar en la base de datos. NO olvides sanitizar los datos. WordPress ya nos proporciona funciones útiles para asegurarnos de que nuestros datos sean lo más seguros posible.

Después de todo eso, ejecutamos la consulta que devolverá el valor de nuestro campo AUTO_INCREMENT, en este caso, el id. O falso si hay un error.

Si todo salió bien, seremos redirigidos a la página principal de nuestro plugin con un mensaje de éxito, y los datos estarán disponibles en nuestra base de datos.

El camino hasta ahora…

Revisa el código hasta ahora en github.

Ahora tenemos un plugin que muestra un formulario para subir archivos, los guarda en la carpeta de subidas de nuestro servidor, y almacena los datos del archivo en una tabla personalizada dentro de nuestra base de datos, genial ¿no? Pero todavía necesitamos ver esos datos en la página de nuestro plugin, ahora solo están disponibles si vemos nuestra carpeta de subidas o navegamos directamente a nuestra base de datos, así que sigamos adelante.

Parte III – Mostrar los datos de los archivos en el panel de control

Voy a usar otra API para mostrar todos los registros en la base de datos, WP_List_Table.

Deberías notar que no se recomienda usar esta clase, porque se supone que es solo para uso interno y puede cambiar en cualquier momento sin previo aviso. Sin embargo, en el momento en que se escribió este artículo, la clase no ha tenido cambios importantes prácticamente desde que se escribió. Aún así, si eres paranoico, es seguro incluir una copia de la clase en tu plugin, yo no lo haré ahora.

Primero que nada, no deberíamos acceder a esta clase directamente, necesitamos extenderla usando otra clase. Así que necesitamos un nuevo archivo.

class-mah-download-manager-list.php

1<?php
2 class Mah_Download_Manager_List extends WP_List_Table {
3
4 }
5

Necesitamos sobrescribir un par de métodos aquí, comenzando con prepare_items, porque necesitamos tener datos para mostrar.

1function prepare_items() {
2 global $wpdb;
3
4 $table_name = $wpdb->prefix . "mah_download_manager";
5
6 $per_page = $this->get_items_per_page( 'posts_per_page' );
7
8 if ( isset( $_REQUEST[ 'number' ] ) ) {
9 $number = (int) $_REQUEST[ 'number' ];
10 } else {
11 $number = $per_page + min( 8, $per_page );
12 }
13
14 if ( isset( $_REQUEST[ 'start' ] ) ) {
15 $start = (int) $_REQUEST[ 'start' ];
16 } else {
17 $start = ( $page - 1 ) * $per_page;
18 }
19
20 $items = $wpdb->get_results( "SELECT * FROM $table_name ORDER BY date DESC LIMIT $start, $number" );
21
22 $this->items = array_slice( $items, 0, $number );
23 $this->extra_items = array_slice( $items, $number );
24
25 $total = count( $items );
26
27 $this->set_pagination_args( array(
28 'total_items' => $total,
29 'per_page' => $per_page
30 ) );
31
32 $this->_column_headers = array(
33 $this->get_columns(),
34 array(),
35 $this->get_sortable_columns()
36 );
37
38}
39

Ok hay muchas cosas pasando aquí, vamos a desglosarlo:

  1. Primero llamamos a la API de la base de datos (como hicimos cuando almacenamos los datos) y especificamos la tabla de la que solicitaremos los datos.
  2. Configuramos el número de elementos que mostraremos en cada página, get_items_per_page es un método integrado en la API de listas, en este caso devolverá el mismo número que hemos almacenado en la opción posts_per_page, que se puede cambiar en las opciones de "Lectura" del lado de la administración.
  3. Luego verificamos en qué página estamos ahora, y configuramos el límite y el desplazamiento para nuestra consulta, esto solo devolverá los elementos que necesitamos.
  4. Ahora que hemos definido el inicio y el final de nuestra consulta, es hora de ejecutarla con get_results.
  5. Cortamos el resultado y almacenamos los elementos en las propiedades de la clase, también almacenamos el número de resultados. Y configuramos los argumentos de paginación con él.
  6. Por último, pero no menos importante, necesitamos configurar los encabezados de nuestras columnas, _column_headers acepta una matriz, esta debe contener los encabezados visibles, los encabezados ocultos y los encabezados ordenables (en este caso no agregaré propiedades ordenables, pero es necesario).

Si intentamos ejecutar el código ahora, obtendremos un mensaje de error, eso es porque get_columns es otro método que debemos definir nosotros mismos, afortunadamente, es muy simple.

1function get_columns() {
2 return array(
3 'file' => __( 'Atchivo', 'mah_download_manager' ),
4 'type' => __( 'Tipo', 'mah_download_manager' ),
5 'size' => __( 'Tamaño', 'mah_download_manager' ),
6 'date' => __( 'Fecha de Carga', 'mah_download_manager' )
7 );
8}
9

Como puedes ver, solo necesitamos devolver un array con los nombres e ids de nuestras cabeceras, nada del otro mundo.

Ahora, hay otra método que necesitamos definir, el que mostrará los datos de todas esas columnas en la lista. De hecho, tenemos una elección que hacer aquí. Podemos crear un método predeterminado que maneje todo, o podemos crear múltiples métodos que manejen una columna específica.

Para los propósitos de este artículo, usaré ambos.

1function column_default( $item, $column_name ) {
2 switch ( $column_name ) {
3 case 'file':
4 echo '<a href="' . $item->url . '">' . $item->name . '</a>';
5 break;
6 default:
7 echo $item->$column_name;
8 break;
9 }
10}
11

column_default es el método que se llamará si no hay otro método que maneje una columna específica, ¿cómo lo encuentra WordPress? Usando la sintaxis column_$columnName, así que si quiero un método específico que maneje la columna date, hago esto:

1function column_date( $item ) {
2 $m_time = $item->date;
3 $time = strtotime( $m_time );
4 $time_diff = time() - $time;
5 if ( $time_diff > 0 && $time_diff < 24*60*60 ) {
6 $h_time = sprintf( __( 'Hace %s' ), human_time_diff( $time ) );
7 } else {
8 $h_time = mysql2date( __( 'Y/m/d' ), $m_time );
9 }
10 echo '<abbr title="' . $m_time . '">' . $h_time . '</abbr>';
11}
12

Y asi column_default no se llamará para la columna date. Por cierto, esta es una función simple para hacer que la fecha sea más legible, la copié del núcleo de WordPress y la adapté un poco.

El camino hasta ahora…

Revisa el código hasta ahora en github.

Eso es prácticamente todo lo que necesitamos para mostrar nuestros datos en la página de nuestro plugin. Ahora tenemos un plugin que muestra un formulario para subir archivos, los guarda en la carpeta de subidas de nuestro servidor, almacena los datos del archivo en una tabla personalizada dentro de nuestra base de datos y muestra una lista de los archivos subidos. Lo único que queda por hacer es eliminar esos archivos de nuestro servidor y base de datos, así que sigamos adelante.

Parte IV – Eliminar archivos de nuestro servidor y base de datos

Para eliminar archivos de nuestro servidor, primero necesitamos actualizar nuestra lista con un enlace de eliminación en los archivos que tenemos, para hacer eso, necesitamos editar nuestro método column_default y llamar a otro método: row_actions.

class-mah-download-manager-list.php

1function column_default( $item, $column_name ) {
2...
3 case 'file':
4...
5 $actions = array(
6 'delete' => '<a href="' . add_query_arg( array( 'action' => 'delete', 'file_id' => $item->id ) ) . '">' . __( 'Eliminar', 'mah_download_manager' ) . '</a>'
7 );
8 echo $this->row_actions( $actions );
9...
10

Primero creamos un array con las acciones que necesitamos, necesitamos dar un nombre a nuestra acción y definir el texto o el marcado que se mostrará. La función add_query_arg devuelve la URL actual y agrega una matriz como parámetros para enviar, en este caso agrego la acción delete con un valor file_id, lo usaremos para encontrar el archivo en la base de datos y eliminarlo del servidor.

Ahora, ¿qué pasa después de que el usuario hace clic en ese enlace? Podemos crear una nueva página para administrar las descargas o podemos hacerlo en la misma página en la que estamos. O mejor aún, usar un hook para buscar la acción dentro de esta página.

Cada vez que registramos una nueva página, WordPress también registra un hook que solo funciona en dicha página, la sintaxis es toplevel_page_$menuslug, en este caso el slug es mah-download-manager así que agregamos la acción:

mah-download-manager.php

1function __construct() {
2...
3 add_action( 'toplevel_page_mah-download-manager', array( $this, 'custom_action' ) );
4...
5

Y agregamos la funcionalidad:

1function custom_action() {
2 if ( ! isset( $_GET[ 'action' ] ) ) {
3 return;
4 }
5
6 if ( ! isset( $_GET[ 'file_id' ] ) ) {
7 wp_die( __( '¡Debes seleccionar un archivo para trabajar!' ) );
8 }
9
10 $action = $_GET[ 'action' ];
11 $file_id = (int) $_GET[ 'file_id' ];
12
13 switch ( $action ) {
14 case 'delete':
15 if ( isset( $_GET[ 'confirm' ] ) && $_GET[ 'confirm' ] == 1 ) {
16 $mdm_method = '';
17
18 $url = wp_nonce_url( 'admin.php?page=mah-download-manager&action=delete', 'mah-download-manager' );
19 if ( ! $creds = request_filesystem_credentials( $url, $mdm_method, false, false ) ) {
20 return true;
21 }
22
23 if ( ! WP_Filesystem( $creds ) ) {
24 request_filesystem_credentials( $url, $mdm_method, true, false );
25 return true;
26 }
27
28 $fileTempData = $_FILES[ 'mdm-file' ];
29
30 $this->delete_file( $file_id );
31 } else {
32 echo '<p>' . __( '¿Estás seguro que quieres eliminar este archivo? Esto no se puede deshacer' ) . '</p>';
33 echo '<a href="' . add_query_arg( array( 'confirm' => 1 ) ) . '" class="button-primary">' . __( 'Eliminar de todos modos', 'mah_download_manager' ) . '</a> ';
34 echo '<a href="' . admin_url( 'admin.php?page=mah-download-manager' ) . '" class="button">' . __( 'Cancelar' ) . '</a>';
35 }
36 break;
37 default:
38 wp_die( __( '¡Esa acción no es válida!' ) );
39 break;
40 }
41
42}
43

Parece que hay mucho código aquí, pero no te preocupes, la mayoría de esto ya lo hemos visto antes, así que déjame explicar los pasos que seguimos:

  1. Primero nos aseguramos de que haya una acción definida, si no simplemente detenemos la ejecución del código.
  2. Luego nos aseguramos de que se haya seleccionado un archivo, si no, no tiene sentido intentar hacer algo.
  3. Luego verificamos qué acción estamos tratando de ejecutar, si no está en la lista, detenemos todo. Escribí esto pensando que en el futuro podríamos querer agregar más acciones. - 1 Dentro de la acción delete, necesitamos asegurarnos de que el usuario no haya hecho clic por accidente, así que mostramos un mensaje preguntando si realmente quiere hacerlo. - Una vez que hemos confirmado que el usuario realmente quiere eliminar el archivo, necesitamos activar la API del sistema de archivos nuevamente, y luego llamar al nuevo método delete_file.
1function delete_file( $id ) {
2 global $wpdb, $wp_filesystem;
3 $table_name = $wpdb->prefix . "mah_download_manager";
4
5 $file_path = $wpdb->get_var( $wpdb->prepare( "SELECT path FROM $table_name WHERE id = %d", $id ) );
6
7 $file_deleted = ( $wp_filesystem->delete( $file_path ) ) ? true : new WP_Error( 'delete_file_error', __( 'Hubo un error eliminando el archivo de el servicor, ¿Revisa la ubicación?', 'mah_download_manager' ) );
8
9 $row_deleted = ( $wpdb->delete( $table_name, array( 'id' => $id ) ) ) ? true : new WP_Error( 'delete_row_error', __( 'Hubo un error eliminando el archivo de la base de datos.', 'mah_download_manager' ) );
10
11 if ( ! is_wp_error( $file_deleted ) && ! is_wp_error( $row_deleted ) ) {
12 wp_redirect( admin_url( 'admin.php?page=mah-download-manager&message=2' ) );
13 exit;
14 } else {
15 wp_die( __( 'Hubieron errores al eliminar el archivo.', 'mah_download_manager' ) );
16 }
17
18}
19

Este método eliminará el archivo del servidor y de la base de datos, aquí está el desglose:

  1. Primero llamamos a las API $wpdb para manejar la base de datos y $wp_filesystem para manejar los archivos (este último solo está disponible después de activarlo previamente).
  2. Luego recuperamos la ruta del archivo de la base de datos, ¡recuerda hacer esto antes de eliminar los datos!
  3. Ahora que tenemos la ruta, eliminamos el archivo del servidor, y verificamos si hay errores en el camino.
  4. Después de eliminar el archivo, es seguro eliminar los datos de la base de datos, una vez más, verificamos si hay errores.
  5. Si no hubo errores al eliminar los datos, entonces redirigimos al usuario de vuelta a la página principal, y agregamos un nuevo mensaje.

Ahora volvamos a display_messages y agreguemos el nuevo mensaje:

1function display_messages() {
2...
3 case 2:
4 $class = 'updated';
5 $text = __( 'El archivo seleccionado ha sido eliminado.', 'mah-download-manager' );
6 break;
7...
8

El camino hasta ahora…

Revisa el código hasta ahora en github.

¡Que viaje tan divertido! Ahora estamos prácticamente terminados con nuestro plugin, aquí está la lista de características:

  • Subir y almacenar archivos usando API del sistema de archivos de WordPress.
  • Crear y manejar datos en la base de datos usando API de la base de datos de WordPress.
  • Mostrar una lista del contenido usando API de listas de WordPress.
  • Eliminar archivos existentes de la base de datos y del servidor usando APIs de la base de datos y del sistema de archivos.

Bastante genial ¿no? Acabamos de crear un plugin funcional que depende principalmente de APIs que están en el núcleo de WordPress, esto significa que si WordPress funciona en tu servidor, es una apuesta segura decir que este plugin también funcionará.