Seguro que alguna vez has necesitado crear un sistema de descarga de ficheros privado (restringido para usuarios autentificados) en WordPress. De manera nativa no es posible hacerlo y hay que, o bien usar algún plugin (como Easy Digital Downloads), o programar código. En labores de mantenimiento de WordPress de nuestros clientes, es una consulta muy habitual.
En este post os voy a enseñar a hacerlo de una forma muy sencilla, programando código.
¿Cuál es el escenario de origen?
Supongamos que tenemos un grupo de campos personalizados con Advanced Custom Fields llamado «información privada»:

Ese grupo de campos está formado por un repetidor que dentro tiene los siguientes dos campos:
- Descripción (opcional y de tipo texto)
- Documento privado (de tipo fichero)

Por una parte, lo que vamos a implementar es un shortcode llamado [descargador]
que vamos a ubicar en una página creada sin nada más que el propio shortcode, en la url /descargas
del sitio web en el que estamos trabajando:

Y en la plantilla donde tenemos los posts y queremos que se muestren los enlaces a los archivos (controlando que sólo un usuario autentificado pueda bajárselos) vamos a añadir el siguiente shortcode: [informacion_privada]
.
Ahora ha llegado el momento del PHP
Y usaremos el siguiente código (que os aconsejo añadir mediante un plugin como Code Snippets, en lugar del functions.php
del tema):
add_shortcode('informacion_privada', 'informacion_privada');
function informacion_privada()
{
if (!is_user_logged_in())
{
//No devolvemos nada al no estar logueado.
//Si quisiéramos devolver algo, tipo "Debes estar logueado...", este es el
//lugar para implementarlo.
return '';
}
else
{
// Suponiendo que estás en el loop de WordPress y $post->ID es el ID de tu post
$post_id = get_the_ID();
// Verifica si el campo repetidor tiene filas de datos
if( have_rows('informacion_privada', $post_id) ):
echo "<h3>Información adicional</h3>";
echo "<ul>";
// Bucle a través de las filas de datos
while ( have_rows('informacion_privada', $post_id) ) : the_row();
// Asigna el subcampo 'documento_privado' a una variable
$archivo = get_sub_field('documento_privado');
// Asigna el subcampo 'documento_privado_descripcion' a una variable
$descripcion = get_sub_field('documento_privado_descripcion');
// Verifica si el subcampo no está vacío
if( $archivo ):
// Obtén la URL del archivo
$url = $archivo['url'];
$file_id = $archivo['ID'];
$url ="/descargas?idf=" . $file_id;
// Define el texto del enlace. Si hay descripción, úsala; si no, usa un texto predeterminado
$texto_del_enlace = $descripcion ? $descripcion : 'Descargar Documento Privado';
// Muestra el enlace para descargar el archivo
echo '<li><a target="_blank" href="' . esc_url($url) . '">' . esc_html($texto_del_enlace) . '</a></li>';
endif;
endwhile;
echo "</ul>";
else :
// No hay filas encontradas
endif;
}
}
function descargador_shortcode() {
// Verifica si se proporcionó un identificador de fichero
if (isset($_GET['idf'])) {
// Asegúrate de que el usuario esté autenticado
if (!is_user_logged_in()) {
return 'Debes estar autenticado para descargar este archivo.';
}
$file_id = intval($_GET['idf']);
if ($file_id) {
manejar_descarga_archivo($file_id);
exit;
}
}
return 'ID de archivo no proporcionado o inválido.';
}
add_shortcode('descargador', 'descargador_shortcode');
function manejar_descarga_archivo($file_id) {
$archivo = get_post($file_id);
if ($archivo) {
$file_path = get_attached_file($file_id);
$file_name = basename($file_path);
if (file_exists($file_path)) {
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="' . $file_name . '"');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($file_path));
ob_clean();
flush();
readfile($file_path);
exit;
}
}
echo 'No tienes permiso para descargar este archivo o el archivo no existe.';
}