3 min 26/09/2021

En este post vamos a ver como poner el tiempo de lectura y como calcularlo, con su correspondiente iconito por supuesto 😜. Es una funcionalidad muy interesante, ya que le da al lector una estimación del tiempo que le puede llevar leer un post. A ver, en mi web igual es una flipada, ya que mis post suelen ser cortos, pero imagínate una web que tenga 4000 palabras. Sería interesante saber el tiempo que te lleva leerlo, ¿no?

Este post fue actualizado el 21-11-21 gracias al aporte que me hizo Carlos Longarela, un crack del desarrollo en WordPress. Muchas gracias 🙌🙌

Como calcular el tiempo de lectura

Primero vamos con algo básico, ¿cómo calculamos el tiempo de lectura de una web?. Eso mismo me pregunté yo cuando Isaac me dijo que quería esa implementación para su web de viajes. Y él mismo me dio la contestación. Si estimamos que una persona lee una media de 300 palabras por minutos la formula mágica se reduce a calcular el número de palabra entre 300 🤯.

Tiempo de lectura = número de palabras / 300

Ahí tienes tu fórmula mágica 😁

Como calculamos el tiempo de lectura para un post de WordPress

Bueno, primero os voy a explicar un poco el proceso y luego os meto el código que yo estoy usando en la web. Tendríamos que coger el contenido del post, convertimos el HTML en caracteres, luego renderizamos los shortcodes que haya en el contenido, eliminamos las etiquetas HTML y contamos las palabras que nos devuelta el último resultado. Con este último valor ya tenemos en número de palabras de nuestro post. Solo nos queda dividirlo entre 300 y ya tenemos nuestro objetivo. Ahora guardamos este valor en un campo adicional, o meta, con la función update. Vale, después del coñazo, aquí tienes lo que venías a buscar, el código que hace esa magia 😜

/**
 * Contar el número de palabras en cada artículo.
 *
 * @param  string $content Contenido del post.
 * @return string
 */
function soivigol_count_words( $id, $content ) {
	$decode_content   = html_entity_decode( $content );
	$filter_shortcode = do_shortcode( $decode_content );
	$strip_tags       = wp_strip_all_tags( $filter_shortcode, true );
	$count            = str_word_count( $strip_tags );
	$time             = strval( round( intval( $count ) / 300 ) );
	update_post_meta( $id, 'time_reading', $time );
	return $time;
}

Con esto ya tenemos calculado el tiempo y guardado en un meta campo. Pero, ¿cuándo llamamos esta función?
Si empiezas el blog desde cero, se puede llamar en el evento save_post, pero si ya tienes varios posts publicados, lo ideal es llamarlo en el save_post y en una función que es la que vamos a llamar cuando se imprima el post. Esta función yo la hice así:

/**
 * Tiempo de lectura si está en el meta reading_time, de lo contrario calcularlo según el número de palabras.
 *
 * @param  int $id Id del post actual
 * @return string
 */
function soivigol_get_reading_time( $id ) {
	$reading_time = get_post_meta( $id, 'reading_time', true );
	if ( empty( $reading_time ) ) {
		$reading_time = soivigol_count_words( $id, get_the_content( $id ) );
	}
	return $reading_time;
}

Y aquí tienes el save_post tal y como lo tengo yo:

/**
 * Guardar la meta reading_time cuando creamos un post o lo actualizamos
 * 
 * @param int $id Id del post actual.
 */
function soivigol_save_reading_time( $id ) {
	soivigol_count_words( $id, get_the_content( $id ) );
}
add_action( 'save_post', 'soivigol_save_reading_time' );

En la anterior función cogemos el valor que haya en la meta reading_time. Si no existe la meta o tiene un valor vacío, entonces llamamos a la función soivigol_count_words. En caso contrario retornamos el valor que había en la meta. En la segunda función llamamos a la función soivigol_count_words cuando creamos un post nuevo o lo actualizamos (Sí, el rollo de guardarlo en la meta fue la sugerencia de Carlos Longarela 😉).

Como ponemos el tiempo de lectura en un post

Vamos a ver donde tendrías que llamar la función del apartado anterior. Si fuese tan fácil como ponerla donde quieras… 😅

Primero tendremos que llamarla en el hook exacto donde quieras que se imprima. En mi caso uso la plantilla de Kadence (una maravilla dijera lo que dijese en otros posts anteriores 😁). Esta plantilla tiene un hook maravilloso para poner código justo antes del contenido que es kadence_single_before_entry_content. Si utilizas otra plantilla puedes buscar tu hook particular. O también puedes utilizar la solución que yo te voy a dar que es aplicando un filter en el contenido de la web. El código final quedaría así:

/**
 * Añadir código al inicio del post en el caso de un post.
 * 
 * @param int    $id Id del post.
 * @param string $content Contenido de la web.
 */
function soivigol_my_single_content( $content ) {
	if ( is_single() ) {
		ob_start();
		?>
		<p class="soivigol-count">
			<img src="<?php echo esc_url( get_stylesheet_directory_uri() . '/imgs/clock.svg' ) ?>" alt=""><?php echo soivigol_get_reading_time( get_the_ID() ); ?> min
		</p>
		<?php
		$content = ob_get_clean() . $content;
	}
	return $content;
}
add_filter( 'the_content', 'soivigol_my_single_content' );

Os explico un poco. Primero comprobamos que sea un single. En caso afirmativo, añadimos el icono ( yo lo añadí como una imagen desde un svg que me pasó el diseñador en la carpeta del child-theme, pero tu puedes añadir el svg o la imagen desde otro sitio). Hacemos un echo del resultado de la función que creamos antes. A esta función le pasamos como parámetro el id del post que lo recuperamos con get_the_ID(). Luego recogemos ese código con ob_get_clean() (acordaros de poner el ob_start() desde donde recogerá el código) y lo añadimos justo antes del $content. Y listo. Ya tenemos nuestro maravilloso contador.

Estilos CSS para que quede más bonito

Os voy a pasar los estilos CSS que le puse yo a mi web para esto.

.soivigol-count img {
	display: inline-block;
	margin-right: 1rem;
	vertical-align: middle;
}

.soivigol-count {
	color: #B6B3BA;
	margin-top: 2rem;
	margin-bottom: 3rem;
	position: relative;
}

Muy sencillito como ves 😁.

Conclusión

Pueden ser cosas que no les demos mucha importancia, pero el lector lo agradece, especialmente en post muy grandes. Seguro que hay algún plugin que hace esto mismo, pero como son unas pocas líneas de código no me molesté en buscar aparte que esto lo hice para un diseño a medida como el de Chavetas por lo que no era muy recomendable tirar de plugins 😅. Y mira, si te sirve, pues mejor que mejor 😉

Publicaciones Similares

Deja una respuesta

Tu dirección de correo electrónico no será publicada.