Autonomía digital y tecnológica

Código e ideas para una internet distribuida

Cómo evitar el error «Cannot modify header information – headers already sent» cuando se usa wp_redirect en WordPress

Imago voragine.net
[actualizado el ] • Por

Si se quiere redirigir a otra página en WordPress usando wp_redirect() suele ocurrir que no hay efecto alguno, que no se produce la redirección al incluir esta función en una función del archivo functions.php o en una plantilla de un tema.

WordPress devuelve un error del tipo "Cannot modify header information - headers already sent".

Incluir tipos de contenido personalizado (custom post types) en el feed principal de un sitio web WordPress

Por omisión en el feed principal de un sitio que funciona con WordPress se muestran las entradas del tipo de contenido post. Para incluir otros tipos de contenidos se puede usar el siguiente código, añadiéndolo al archivo functions.php:

add_filter( 'pre_get_posts', 'prefix_custom_feed' );
function prefix_modify_feed( $query ) {
        if ( $query->is_feed() )
            $query->set( 'post_type', array( 'post', 'link' ) ); 
        return $query;
}

También se puede obtener un feed combinado modificando los parámetros de la URL del feed, de la siguiente manera:

https://voragine.net/feed?post_type[]=post&post_type[]=link

Paginar un listado de entradas en una page template usada como portada en WordPress

Para paginar un loop en una page template usada como portada en WordPress se puede usar el mismo procedimiento que para un loop en cualquier otra plantilla. Lo único que hay que cambiar el el nombre de la variable, que en este caso no se llama paged sino page. Una de estas cosas que te pueden hacer perder medio día hasta que des con ello.

Entonces, para mostrar las entradas de la página actual de un loop paginado dentro de una plantilla de página (page template) en la portada (front page):

$paged = ( get_query_var('page') ) ? get_query_var('page') : 1;
$query = new WP_Query( array( 'paged' => $paged ) );

Todo está documentado en el codex de WordPress.

Cómo solucionar el error ‘File not found’ en WordPress Multisite funcionando con Apache 2.4 y PHP-FPM 5.6

Imago voragine.net
[actualizado el ] • Por Enlace permanente

Las instalaciones de WordPress Multisite que estén configuradas para mostrar los sitios como subdirectorios pueden dar error en un servidor funcionando con Apache 2.4 y PHP-FPM 5.6. Cuando se visita el panel de administración de cualquier sitio que no sea el principal: File not found.

Si se consulta el log de FPM se verán multitud de respuestas 404. Y si se consulta el log de Apache se encontrarán errores de este tipo: Got error 'Primary script unknown'

Para solucionarlo hay que modificar ligeramente la configuración de Apache. La siguiente línea configura la conexión con FPM:

ProxyPassMatch ^/(.*\.php(/.*)?)$ unix:/ruta/hasta/el/php5-fpm.socket.sock|fcgi://localhost/ruta/hasta/el/hroot/

Hay que añadir otra regla (antes que la anterior) para cubrir el caso de los sitios secundarios del Multisite:

ProxyPassMatch ^/([_0-9a-zA-Z-]+/)?(wp-(content|admin|includes)/.*\.php(/.*)?)$ unix:/ruta/hasta/el/socket.sock|fcgi://localhost/ruta/hasta/el/hroot/$2

Aunque esta solución funciona sigue arrojando los mismos errores, así que yo prefiero eliminar la configuración de FPM mediante ProxyPassMatch e incluir un handler dentro del entorno Directory. Así:

<Directory "/ruta/hasta/el/hroot">
  # otras configuraciones
   <FilesMatch \.php$>
      SetHandler "proxy:unix:/ruta/hasta/el/socket.sock|fcgi://localhost"
   </FileMarch>
</Directory>

Evitar ataques de fuerza bruta en WordPress protegiendo el archivo wp-login.php con contraseña

Imago voragine.net
• Por
Una de las medidas para prevenir ataques de fuerza bruta en WordPress es protegiendo el inicio de sesión con contraseña usando HTTP Basic Authentication. Esta capa de seguridad se configura directamente en el servidor web, Apache2 por ejemplo. Este método permite proteger con contraseña el acceso a determinadas áreas de un servidor, archivos o carpetas, previamente a la ejecución de PHP. Al no ejecutar PHP, el consumo de recursos del servidor es mucho menor y el colapso es más difícil. Por esta razón es una manera más eficaz que usar un plugin.

WordPress es software libre, sin embargo ¿es libre el ecosistema de themes y plugins que se ha generado a su alrededor?

Imago voragine.net
[actualizado el ] • Por

Empecé a usar WordPress entre otras razones porque es software libre. Además está liberado bajo licencia GPL versión 2 o posterior, la misma licencia con la que libero el software que yo mismo programo. La licencia GPL incluye la condición de que cualquier obra derivada debe liberarse a su vez bajo la misma licencia GPL. De esta manera se asegura que el procomún digital que es el software libre siga nutriéndose.

Sin embargo muchos de los themes y plugins de WordPress no son software libre. Si los themes y plugins se consideran obras derivadas de WordPress deberían liberarse bajo la misma licencia GPL que WordPress, y por tanto ser software libre.

En este post explico cómo es esto posible y qué consecuencias tiene para usuarios y desarrolladores.

Cómo habilitar el uso de oEmbed en los widgets de WordPress

Para usar el sistema oEmbed en los widgets de WordPress, y de esa manera evitar el uso de algunos plugins, basta añadir las siguientes líneas al archivo functions.php del theme que se esté usando.

global $wp_embed;
add_filter( 'widget_text', array( $wp_embed, 'run_shortcode' ), 8 );
add_filter( 'widget_text', array( $wp_embed, 'autoembed'), 8 );

Una vez añadidas estas líneas podemos incrustar vídeos y otros contenidos externos en un área de widgets añadiendo la URL a un widget de texto.

Encontré el snippet en wpbeginner, donde tienen otros dos relacionados para controlar el ancho del elemento incrustado:

Contexto

Feed para custom post types o custom taxonomies en WordPress

Por omisión WordPress genera el feed de contenidos en la URL /feed. Por ejemplo, para este blog en https://voragine.net/feed. Sin embargo, en este feed solo se incluyen los posts, ningún otro tipo de contenido, ni siquiera las páginas.

WordPress genera feeds para el resto de post types de manera separada. Por ejemplo, para obtener un feed de la linkoteca, que funciona con el post type «link», la URL del feed es https://voragine.net/feed/?post_type=link.

Lo mismo ocurre con las taxonomías. Por ejemplo, para obtener el feed de un tag: https://voragine.net/feed?tag=apache.

Por último se pueden combinar parámetros: https://voragine.net/feed?post_type=link&tag=apache.

Contexto

Cómo sobreescribir un script js en un child theme de WordPress

Imago voragine.net
[actualizado el ] • Por Enlace permanente

Para modificar un archivo javascript en un tema hijo (child theme) de WordPress no basta con incluirlo en la carpeta del child theme y esperar que WordPress lo use en vez del equivalente en el parent theme (tema padre), como ocurre con los archivos PHP.

Con los archivos javascript tenemos que realizar dos operaciones: eliminar de la cola de scripts el archivos del parent theme, y añadir el archivo modificado alojado en la carpeta del child theme:

function child_theme_prefix_load_scripts() {
 wp_dequeue_script('parent-theme-script-handler');
 wp_enqueue_script(
   'child-theme-script-hadler',
   get_stylesheet_directory_uri().'/js/script.js',
   array( 'jquery' ), // dependencias
   '1.0', // versión
   false // incluir script en la sección header del HTML
 );
}
add_action( 'wp_print_scripts', 'child_theme_prefix_load_scripts', 100 );

Usar el hook wp_print_scripts, en vez de wp_enqueue_scripts, nos asegura que la acción se ejecutará después de que el parent theme haya registrado y añadido a la cola los scripts.

Además de la función wp_dequeue_script existe wp_deregister_script. Ambas conseguirán que el script del parent theme no se cargue, pero usando la segunda sin la primera obtendremos un notice de PHP. Parece ser que lo correcto es usar ambas.

Cómo cargar archivos .mo con las cadenas de traducción en un tema hijo en WordPress

Cuando se trabaja con un tema hijo (child theme) en WordPress para una página en varios idiomas nos encontraremos con cadenas a traducir en el parent theme y en el child theme. Cada uno tendrá sus archivos .po y .mo y los archivos de traducciones se activarán desde el archivo functions.php.

Para el archivo con las cadenas del chid theme utilizamos load_child_theme_textdomain:

add_action( 'after_setup_theme', 'child_theme_setup' );
function child_theme_setup() {
  load_child_theme_textdomain( 'child-theme-text-domain', get_stylesheet_directory() . '/ruta-al-archivo-mo' );
}

Si el archivo con las cadenas del parent theme no está cargado, lo podemos cargar en el child theme de la misma manera que el del child theme pero usando el hook load_theme_textdomain.