Archivo de la categoría: wordpress

WordPress: Creando flash-message

Para que una aplicación web sea más entendible lo que está haciendo, muchas veces recurrimos a los «flash message». Esto son unos avisos que aparecen una vez aterrizamos en una página y solo la primera vez que llegamos. Útiles para notificar que se hizo algo en la anterior página y el resultado de esa acción.

Como mi premisa siempre es intentar no reinventar la rueda, usar los patrones más cercanos a «core» para que la experiencia de usuario sea sencilla me puse a investigar como genera «core» sus flash-message para hacerlos igual.

En general, en el admin de WordPress estamos hablando de engancharnos al hook de acción ‘admin_notices’ y pintar un div con classs «notice».

Y digo en general, porque cuando llegamos a la pantalla de edición de post nos encontramos con el editor Guttenberg, que se renderiza principalmente en el navegador, no en el servidor. No se ejecuta el hook ‘admin_notices’ y aquí toca lanzar un ‘snackbar’ será ejecutar código javascript. En concreto contra el API de guttenber ‘core/notices’.

Voy a poner como ejemplo la solución a un plugin que tiene que mostrar un flash-message después de crear un post y aterrizar en la pantalla de edición, y que funcione tanto para los wordpress viejunos (o que tengan deshabilitado Guttenberg) como para los modernos:

<?php
// Al crear el post, guarda un transient
$post_id = wp_insert_post( array(
    'post_title'   => 'Mi Nuevo Post',
    'post_content' => 'Contenido',
    'post_status'  => 'draft',
    'post_type'    => 'post',
    'post_author'  => get_current_user_id(),
) );

if ( ! is_wp_error( $post_id ) ) {
    // Guardar un transient indicando que se acaba de crear
    set_transient( 'post_creado_' . $post_id, true, HOUR_IN_SECONDS );
    
    wp_redirect( admin_url( 'post.php?action=edit&post=' . $post_id ) );
    exit;
}

// En el admin_notices hook
add_action( 'admin_notices', 'mostrar_notice_post_creado' );

function mostrar_notice_post_creado() {
    global $post;
    
    if ( ! $post ) return;
    
    // Verificar si se acaba de crear
    if ( get_transient( 'post_creado_' . $post->ID ) ) {
        delete_transient( 'post_creado_' . $post->ID );
        
        // Mostrar para editor clásico
        ?>
        <div class="notice notice-success is-dismissible">
            <p><?php esc_html_e( 'Post creado exitosamente', 'tu-textdomain' ); ?></p>
        </div>
        
        <!-- Para Gutenberg -->
        <script>
            ( function( wp ) {
                if ( wp && wp.data ) {
                    wp.data.dispatch( 'core/notices' ).createNotice(
                        'success',
                        '<?php echo esc_js( 'Post creado exitosamente' ); ?>',
                        { isDismissible: true, type: 'snackbar' }
                    );
                }
            } )( window.wp );
        </script>
        <?php
    }
}
?>

Las 3 reglas que deberían guiar el desarrollo de cualquier plugin de WordPress


Hay una tentación bastante común al desarrollar para WordPress: pensar que un plugin debe resolverlo todo, imponer su propia lógica y dejar el resto del sitio a su suerte. Es un error. Un buen plugin no compite con WordPress, ni con el tema, ni con el criterio del usuario. Hace su trabajo concreto, extendiendo lo existente aportando una funcionalidad.

Hace tiempo encontré un artículo de Daniel Auener que resume muy bien esta idea y que me ha servido de guía con tres reglas que, aunque parezcan obvias, siguen siendo necesarias porque demasiados plugins las ignoran.

Regla 1: No reinventes la interfaz de WordPress

Si el sistema ya ofrece componentes, patrones y formas de trabajo reconocibles, tiene poco sentido forzar al usuario a aprender una experiencia nueva. La familiaridad no es un detalle menor, hace que el uso del plugin resulte más intuitivo y fácil de usar. Aprende los patrones probados y adóptalos.

Regla 2: No quites control al theme

Demasiados plugins intentan decidir por encima de la capa visual, del diseño o de la estructura general del sitio. Eso genera fricción, rompe coherencia y obliga a pelearse con el plugin para conseguir algo tan básico como hacer que el resultado encaje con el proyecto. Un plugin útil aporta sin imponer decisiones de diseño que pertenecen al tema. Además, WordPress cada vez ha dejado más sencillo configurar varaibles de aspecto a nivel de instalación que pueden leer themes y plugins.

Regla 3: mantenlo simple

Para mi probablemente la más importante (y también la más ignorada). Hay una tendencia de los plugin «all-in-one», que dan muchas funcionalidades que, en realidad, el usuario no necesita. Al final acabamos con una colección de opciones, pantallas y ajustes que acaban complicando lo que pretendían simplificar. En WordPress eso se nota especialmente: cuanto más intenta un plugin abarcar, más probable es que termine generando dependencia, mantenimiento innecesario y problemas de usabilidad y rendimiento.

Por estas tres reglas prefiero instalar una serie de plugins, lo imprescindibles y, si es necesario, crear los míos propios. De esta manera estoy en control del sitio. En un ecosistema tan extendido como WordPress, hay mucha gente que ya se ha peleado con muchos problemas y no hay que reinventar la rueda, solo rodar con ella. Una interfaz que desentona, una opción que anula al tema, una función que añade complejidad sin necesidad pueden ser piedras en el camino.

Un plugin debería mejorar el sitio, no convertirlo en un campo de batalla entre capas que deberían cooperar. El control sobre nuestro WordPress no viene de plugins que cambian todo, sino de plugins que resuelven problemas concretos de manera óptima.

WordPress: No uses camelCase para tus shortcodes

En breve: no utilices camelCase para nombres de parámetros en los shortcodes de WordPress

He estado un rato dado vueltas a un código de shortcode que estaba haciendo. Quería inyectarle un contenido para que lo usara como una propo de schema para mejorar la semántica del código. Esa prop usaba camelCase y decidí que el parámetro llevase el mismo nombre para no liarme… pero cuando capturaba el recogía el parámetro me aparacía con el valor por defecto.

function shortcode_process($atts) {
	$atts = shortcode_atts( array(
		0 => null,
		'name' => null,
		'price' => null,
		'priceCurrency' => null,
	), $atts );
}

Y es que no sabía que los atributos del shortcode de WordPress se pasan a través de la función strtolower() de PHP.

Es raro que use camelCase en PHP, suelo usar snake_case (aunque últiamente en javascript uso camelCase), pero aquí quería usar el mismo nombre que la prop, y Schema.org marca las props en camelCase. Ha sido un rato rascándome las neuronas intentando averiguar si porqué un parámetro estaba pasando correctamente y el otro se quedaba con el valor por defecto, hasta que finalmente he pensado ¿y si es por el casing?

function shortcode_process($atts) {
	$atts = shortcode_atts( array(
		0 => null,
		'name' => null,
		'price' => null,
		'pricecurrency' => null,
	), $atts );
}

Y así era, resulta que los parámetros estaban siendo ignorados porque ya no coincidían con los nombres esperados después de ser convertidos a minúsculas por la función strtolower() antes mencionada.

Así que aquí te dejo la pista para que no pierdas el tiempo que he perdido. Utiliza nombres de propiedads en minúsculas/snake_case en el array shortcode_atts().