Muestra un widget con tags de bbPress en WordPress

This post was published 7 years ago. It may be exremely outdated.

Lista de temas de un foro bbPress como Widget de WordPressUna de las características que sorprendentemente no incluye bbPress 2.0 es un Widget para WordPress que muestre las etiquetas de los temas del foro. Es curioso que incluya un Widget que sólo muestre un enlace a la lista de mensajes sin responder y por contra no incluya un índice de etiquetas.

Esta tarde me he tomado la molestia de crear yo uno y quiero compartirlo con todo aquel al que le parezca interesante. Básicamente se copia el siguiente código en el archivo functions.php de nuestro theme de WordPress o en un archivo .php en la carpeta de plugins de WordPress.

class bbPress_Widget_Tag_Cloud extends WP_Widget {
		function bbPress_Widget_Tag_Cloud() {
			$widget_ops = array( 'description' => __( "Your most used tags in cloud format") );
			$this->WP_Widget('bbpress_tag_cloud', __('bbPress Tag Cloud'), $widget_ops);
		}
		function widget( $args, $instance ) {
			extract($args);
			$current_taxonomy = $this->_get_current_taxonomy($instance);
			if ( !empty($instance['title']) ) {
				$title = $instance['title'];
			} else {
				if ( 'post_tag' == $current_taxonomy ) {
					$title = __('Tags');
				} else {
					$tax = get_taxonomy($current_taxonomy);
					$title = $tax->labels->name;
				}
			}
			$title = apply_filters('widget_title', $title, $instance, $this->id_base);
			echo $before_widget;
			if ( $title )
				echo $before_title . $title . $after_title;
			echo '
<div class="tagcloud">';
			wp_tag_cloud( apply_filters('widget_tag_cloud_args', array('taxonomy' => $current_taxonomy) ) );
			echo "</div>
n";
			echo $after_widget;
		}
		function update( $new_instance, $old_instance ) {
			$instance['title'] = strip_tags(stripslashes($new_instance['title']));
			$instance['taxonomy'] = stripslashes($new_instance['taxonomy']);
			return $instance;
		}
		function form( $instance ) {
			global $bbp;
			$current_taxonomy = $this->_get_current_taxonomy($instance);
	?>
<label for="<?php echo $this->get_field_id('title'); ?>"><!--?php _e('Title:') ?--></label>
		<input id="<?php echo $this->get_field_id('title'); ?>" class="widefat" name="<?php echo $this->get_field_name('title'); ?>" type="text" value="<?php if (isset ( $instance['title'])) {echo esc_attr( $instance['title'] );} ?>" />
<label for="<?php echo $this->get_field_id('taxonomy'); ?>"><!--?php _e('Taxonomy:') ?--></label>
<select id="<?php echo $this->get_field_id('taxonomy'); ?>" class="widefat" name="<?php echo $this->get_field_name('taxonomy'); ?>">		<!--?php foreach ( get_object_taxonomies($bbp--->forum_post_type) as $taxonomy ) :					$tax = get_taxonomy($taxonomy);					if ( !$tax->show_tagcloud || empty($tax->labels->name) )						continue;		?>			<option value="<?php echo esc_attr($taxonomy) ?>">><!--?php echo $tax--->labels->name; ?></option>		<!--?php endforeach; ?-->		<!--?php foreach ( get_object_taxonomies($bbp--->topic_post_type) as $taxonomy ) :					$tax = get_taxonomy($taxonomy);					if ( !$tax->show_tagcloud || empty($tax->labels->name) )						continue;		?>			<option value="<?php echo esc_attr($taxonomy) ?>">><!--?php echo $tax--->labels->name; ?></option>		<!--?php endforeach; ?-->		<!--?php foreach ( get_object_taxonomies($bbp--->reply_post_type) as $taxonomy ) :					$tax = get_taxonomy($taxonomy);					if ( !$tax->show_tagcloud || empty($tax->labels->name) )						continue;		?>			<option value="<?php echo esc_attr($taxonomy) ?>">><!--?php echo $tax--->labels->name; ?></option>		<!--?php endforeach; ?--></select>
<!--?php<br /-->		}
		function _get_current_taxonomy($instance) {
			if ( !empty($instance['taxonomy']) && taxonomy_exists($instance['taxonomy']) )
				return $instance['taxonomy'];
			return 'post_tag';
		}
	}
register_widget('bbPress_Widget_Tag_Cloud');

¿Cómo funciona? Pues lo que he hecho ha sido copiar el código del Widget de nube de etiquetas que viene por defecto en WordPress (sobre la línea 986 del archivo wp-includes/default-widgets.php) y modificarlo para que en la lista de posibles taxonomías a mostrar muestre todas las taxonomías que pertenezcan a alguno de los post_type que añade bbPress 2.0.

Lamentablemente hay un pequeño problema en esto y es que aparecerán también las etiquetas que se aplican a temas publicados en foros privados, comprometiendo la privacidad de dichos foros. La solución me ha costado bastante más de encontrar, pero la tenéis a continuación. Se trata básicamente de aplicar un filtro al Widget, que añade a la lista de etiquetas a excluir cualquier etiqueta que haya sido asignada a un tema de un foro privado. De nuevo, se puede añadir en el archivo functions.php de nuestro theme o en un archivo aparte en wp-content/plugins.

function parchear_bug_tag_cloud($content)
	{
		global $bbp;
		$private_forums = bbp_get_private_forum_ids();
		if (bbp_user_can_view_forum(array('forum_id' => $private_forums[1])))
		{
			return $content;
		}
		$tags_to_remove = array();
		foreach ($private_forums as $pf_id => $pf_forum)
		{
			if ($pf_forum == '') { continue; }
			$temp_query = new WP_Query(array('suppress_filters' => true, 'post_type' => $bbp->topic_post_type, 'meta_query' => array(array('key' => '_bbp_forum_id', 'value' => $pf_forum, 'compare' => '='))));
			while ( $temp_query->have_posts() ) : $temp_query->the_post();
				$tags = wp_get_object_terms(get_the_ID(), $bbp->topic_tag_id);
				foreach ($tags as $t_key => $t_value)
				{
					$tags_to_remove[] = $t_value->term_id;
				}
			endwhile;
			wp_reset_postdata();
		}
		$content['exclude'] = $tags_to_remove;
		return $content;
	}
	add_filter('widget_tag_cloud_args', 'parchear_bug_tag_cloud');

¿Cómo funciona? Primero se obtienen los foros privados y se comprueba que el usuario no puede verlos. A continuación se recorren todos los temas de todos los foros privados (sí, se que no está demasiado optimizado, pero no he encontrado una forma mejor de hacerlo) y se añaden todas sus etiquetas a la lista de etiquetas a excluir. Por último se devuelven los nuevos parámetros del Widget.

La lástima es que hay un segundo bug, y es que si un usuario accede a la URL de una etiqueta que está asignada a un tema publicado en un foro privado, el usuario puede ver la lista de temas que tienen asignada dicha etiqueta, y entre esos temas, aparecerá también el tema que debería estar oculto al ser publicado en un foro privado.

De nuevo para solucionar esto podemos recurrir a los filtros de bbPress y WordPress, en concreto arreglar el error se logra con el siguiente código:

function parchear_bug_foros_privados($content)
	{
		global $bbp;
		$private_forums = bbp_get_private_forum_ids();
		if (bbp_user_can_view_forum(array('forum_id' => $private_forums[1])))
		{
			return $bbp->topic_query->post_count;
		}
		$topics_to_remove = array();
		foreach ($bbp->topic_query->posts as $key => $post)
		{
			if (in_array(get_post_meta($post->ID, '_bbp_forum_id', true), $private_forums))
			{
				$topics_to_remove[] = $key;
			}
		}
		foreach ($topics_to_remove as $key => $topic_to_remove)
		{
			unset($bbp->topic_query->posts[$topic_to_remove]);
		}
		$bbp->topic_query->post_count = count($bbp->topic_query->posts);
		$bbp->topic_query->post = reset($bbp->topic_query->posts);
		return $bbp->topic_query->post_count;
	}
	add_filter('bbp_has_topics', 'parchear_bug_foros_privados');

Esto tiene un efecto secundario: a partir del momento de aplicar estos dos parches, cualquier tema que tenga asignada una etiqueta que esté a su vez asignada a un tema publicado en un foro privado, será invisible para los usuarios que no tengan permiso para ver dicho foro, es decir, se volverá tan privado como los temas publicados en un foro privado. Este efecto desaparece al eliminar el código de ambos parches, sin embargo si no usamos estas funciones, queda a la vista de cualquier usuario (incluso los no registrados) la lista de temas privados.

Sencillo y limpio, pues si queremos eliminar este parche o el Widget basta con borrar el código anterior. Además, en caso de que este error no se arreglara en futuras versiones, el parche y el Widget seguirán disponibles tras actualizar bbPress, manteniendo la sencillez característica de WordPress.

De todos modos, espero que en la versión final de bbPress 2.0 se incluya un Widget que reemplace al mío, y que los fallos sean arreglados.

Leave a Reply