Random images using Nivo Slider for WordPress

I like to keep things simple. When it comes to designing a website and managing it, I usely know quite precisely what I want and what I don’t, and for this new version of CaerCam, I wanted a slideshow I can use really easily, meaning that I want to be able to manage my featured pictures however I want without using my FTP access. There’s a lot of great WordPress plugins that will do that, but I found Nivo Slider for WordPress to be the simplest and lightest to meet my needs; it lacks only one tiny little thing: you can’t randomize the pictures you show. Well, you couldn’t, until just now.

Add a « random order » option to Nivo Slider for WordPress

This is actually a very basic hack, just a few lines of code will be needed and we’ll have to modify only two files: nivoslider4wp-show.php and nivoslider4wp-option.php. Let’s look at it. First thing, we need to add the option; I put it right after the control nav option in the Nivo Slider Setting section, but you can place it wherever you wish. Edit your nivoslider4wp-option.php:

After

if (isset($_POST['options'])) {

Add this line:

update_option('nivoslider4wp_randomImg', $_POST['nivoslider4wp_randomImg']); // Random image order

Now we have to add some field in the option form, a basic enable/disable radio button. After

			<p>
			<?php _e('Show the navigation bullets ','nivoslider4wp'); ?>:
				<input type="radio" name="nivoslider4wp_controlNav" class="radiocheck" id="nivoslider4wp_controlNav" value="true" <?php if(get_option('nivoslider4wp_controlNav') == 'true'){echo 'checked';}?> /><?php _e('Enable','nivoslider4wp'); ?>
				<input type="radio" name="nivoslider4wp_controlNav" class="radiocheck" id="nivoslider4wp_controlNav" value="false" <?php if(get_option('nivoslider4wp_controlNav') == 'false'){echo 'checked';}?> /><?php _e('Disable','nivoslider4wp'); ?>
			</p>

Add these lines:

			<!-- Random order start -->
			<p>
			Display images in random order :
				<input type="radio" name="nivoslider4wp_randomImg" class="radiocheck" id="nivoslider4wp_randomImg" value="true" <?php if(get_option('nivoslider4wp_randomImg') == 'true'){echo 'checked';}?> /><?php _e('Enable','nivoslider4wp'); ?>
				<input type="radio" name="nivoslider4wp_randomImg" class="radiocheck" id="nivoslider4wp_randomImg" value="false" <?php if(get_option('nivoslider4wp_randomImg') == 'false'){echo 'checked';}?> /><?php _e('Disable','nivoslider4wp'); ?>
			</p>
			<!-- Random order end -->

Yeah, I didn’t bother with internationalization, my bad.

That’s it! Now we edit nivoslider4wp-show.php. We just need to test if our newly defined option is active and, if so, randomize the images. That we do using Php shuffle function to… Shuffle the array containing the images:

After

<?php $items = $wpdb->get_results("SELECT nivoslider4wp_id,nivoslider4wp_type,nivoslider4wp_text_headline,nivoslider4wp_image_link,nivoslider4wp_image_status FROM {$wpdb->prefix}nivoslider4wp WHERE nivoslider4wp_image_status = 1 OR nivoslider4wp_image_status IS NULL ORDER BY nivoslider4wp_order,nivoslider4wp_id"); ?>

Add this line:

<?php if ( get_option('nivoslider4wp_randomImg') == 'true' ) shuffle( $items ); ?>

And we’re done. Just go to the Nivo Slider for WordPress options page and toggle the option to ‘enable’.

London Eye by Fernando García

Question aux pros du SQL résolue : clause HAVING

Comme le titre l’indique, une question aux gens qui déchirent en base de données 🙂

J’ai une table SQL pour WordPress, qui contient 4 colonnes : meta_id, post_id, meta_key, meta_value. C’est la table postmeta, même si ça n’est pas important en soi. Admettons que j’ai les valeurs suivantes :

meta_id  |  post_id  |  meta_key  |      meta_value
---------+-----------+------------+---------------------
    1    |    1541   |  'acteur'  |    'Johnny Depp'
    2    |    1541   |  'acteur'  |  'Helena B. Carter'
    3    |    1684   |  'acteur'  |    'Alan Rickman'
    4    |    1684   |  'acteur'  |    'Kevin Costner'
    5    |    6843   |  'acteur'  |    'Johnny Depp'
    6    |    6843   |  'acteur'  |  'Helena B. Carter'
    7    |    3184   |  'acteur'  |       'Sam Neil'
    8    |    3184   |  'acteur'  |  'Helena B. Carter'

Je veux récupérer les articles pour lesquels on a ‘Johnny Depp’ et ‘Helena B. Carter’, c’est-à-dire les post_id 1541 et 6843. Comment je récupère ça en une seule requête SQL ?

L’idée est de faire un formulaire de recherche qui me permettrait de trouver par exemple des films en fonction d’une liste d’acteurs ayant joué dedans. Il me semble qu’il y a un moyen simple de faire ça, mais je n’ai pas encore remis la main dessus.

Bon, il faut voir aussi niveau performance. À terme, il n’est pas impossible qu’il faille effectuer les requêtes avec deux, trois, cinq ou six acteurs ; dans ce cas il vaudra probablement mieux effectuer toutes les requêtes séparément et les croiser en PHP pour n’obtenir que les fiches de films ou les acteurs apparaissent tous ; ou alors diviser, et croiser les requêtes deux par deux…

Bref, c’est ouvert aux suggestions 🙂

Édition 1er décembre 18h12 :

Solution apportée par François : la clause HAVING.

SELECT post_id,
    COUNT(*) AS nb
FROM postmeta
WHERE meta_key = 'acteur'
AND meta_value IN( 'Johnny Depp', 'Helena B. Carter' )
GROUP BY post_id
HAVING nb = 2

Avec possibilité d’augmenter le nombre d’acteurs en changeant HAVING nb = i, voire même HAVING nb >= i pour obtenir les films où apparaissent au moins i acteurs…

Basic WordPress Feed importer, Widget version

Few days ago I was talking about one basic Feed importer I wrote to be used in WordPress templates, and the possibility of making a Widget out of it. Now here it is 🙂

<?php
class FriendsRSS extends WP_Widget {
    /** constructor */
    function FriendsRSS() {
        parent::WP_Widget( false, $name = 'FriendsRSS',
                           array( 'description' => 'Show latest posts from other websites using their feeds.' ) );  
    }

    /** @see WP_Widget::widget */
    function widget($args, $instance) {     
        extract( $args );
        $title = apply_filters('widget_title', $instance['title']);
        $friends = apply_filters('widget_title', $instance['friends']);
        $quantity = apply_filters('widget_title', $instance['quantity']);
        ?>
              <?php echo $before_widget; ?>
                  <?php if ( $title ) echo $before_title . $title . $after_title; ?>
<?php $display = ( ( isset($quantity) && $quantity != NULL ) ? ( $quantity > 15 ? 15 : (int) $quantity ) : 2 ); ?>
<?php if ( isset( $friends ) && $friends != NULL ) : $feeds = get_friends_feeds( explode( "n", $friends ), $display ); krsort( $feeds ); ?>
<?php if ( count( $feeds ) > 0 ) : ?>
			<ul>
<?php foreach($feeds as $feed) : $feed = (object) $feed; ?>
				<li>
					<?php echo $feed->_date; ?> : 
					<a class="permalink" href="<?php echo $feed->_href; ?>" title="<?php echo $feed->_atitle . '. ' . long_excerpt($feed->_desc, 25); ?>">
						<?php echo $feed->_title; ?>
					</a>
				</li>
<?php endforeach; ?>
			</ul>
<?php endif; ?>
<?php endif; ?>
              <?php echo $after_widget; ?>
        <?php
    }

    /** @see WP_Widget::update */
    function update($new_instance, $old_instance) {             
    $instance = $old_instance;
    $instance['title'] = strip_tags($new_instance['title']);
    $instance['friends'] = strip_tags($new_instance['friends']);
    $instance['quantity'] = strip_tags($new_instance['quantity']);
        return $instance;
    }

    /** @see WP_Widget::form */
    function form($instance) {              
        $title = esc_attr($instance['title']);
        $friends = esc_attr($instance['friends']);
        $quantity = esc_attr($instance['quantity']);
        ?>
        <p>
          <label for="<?= $this->get_field_id('title'); ?>"><?= _e('Title:'); ?></label> 
          <input class="widefat" id="<?= $this->get_field_id('title'); ?>" name="<?= $this->get_field_name('title'); ?>" type="text" value="<?= $title; ?>" />
        </p>
        <p>
          <label for="<?= $this->get_field_id('friends'); ?>"><?= _e('Feeds to include<br /><small>(one url per line)</small>'); ?></label> 
          <textarea class="widefat" id="<?= $this->get_field_id('friends'); ?>" name="<?= $this->get_field_name('friends'); ?>" style="width:220px;height:175px"><?= $friends; ?></textarea>
        </p>
        <p>
          <label for="<?= $this->get_field_id('quantity'); ?>"><?= _e('Number of posts to fetch<br /><small>(default is 2, maximum is 15)</small>'); ?></label> 
          <input class="widefat" id="<?= $this->get_field_id('quantity'); ?>" name="<?= $this->get_field_name('quantity'); ?>" type="text" value="<?= $quantity; ?>" />
        </p>
        <?php 
    }
}

add_action('widgets_init', create_function('', 'return register_widget("FriendsRSS");'));
?>

To be include in your theme’s functions.php file. I’ll let you go through WordPress’ Codex if you need more details on Widget developing. What we do here is simple enough: three options, title, friends and quantity. First is the Widget’s title to be displayed, second is the list of feeds to fetch, third is the number of feeds to fetch.

Really basic stuff, as usual feel free to modify whatever you want 🙂

Basic WordPress Feed importer

Just a basic how-to here: making your own Feed importer tool to add some feeds in your WordPress themes. WordPress offers a bunch of useful tools to manage feeds, and among other cool stuffs, a method to import feeds : fetch_feed(). Given the feed’s url, you get back the feed content. Piece of cake 🙂 This goes in your theme’s functions.php:

function get_friends_feeds($friends = array(), $display = 2) {
    include_once(ABSPATH.WPINC.'/feed.php');
    $feeds = array();
    
    if (count($friends) != 0) {
        foreach($friends as $friend) {
            $rss = fetch_feed($friend);
            if (!is_wp_error( $rss ) ) :
                $maxitems = $rss->get_item_quantity($display); 
                $rss_items = $rss->get_items(0, $maxitems); 
            endif;
            
            if ($maxitems > 0) {
                foreach($rss_items as $item ) {
                    $feeds[$item->get_date('U')] = array('_href'  => esc_url($item->get_permalink()),
                                                         '_title' => esc_html($item->get_title()),
                                                         '_desc'  => strip_tags($item->get_description()),
                                                         '_date'  => $item->get_date('j<br />M'));
                }
            }
        }
    }
    
    return $feeds;
}

Note that this part only returns an array containing the feeds you want as objects; what to do with them depends on what you want. I use it to show me a simple bulleted list. This goes in my theme’s home.php, put it wherever you want:

<?php $feeds = get_friends_feeds(array('http://feeds.boston.com/boston/bigpicture/index', 'http://fluxbb.org/forums/extern.php?action=feed&type=atom')); krsort($feeds); ?>
<?php if (count($feeds) != 0) : ?>
        <div>
          <ul>
<?php foreach($feeds as $feed) : $feed = (object) $feed; ?>
            <li>
              <?php echo $feed->_date; ?>: <a href="<?php echo $feed->_href; ?>" title="<?php echo $feed->_title; ?>"><?php echo $feed->_title; ?><br />
              <?php echo long_excerpt($feed->_desc, 25); ?></a>
            </li>
<?php endforeach; ?>
          </ul>
        </div>
<?php endif; ?>

get_friends_feeds() takes two parameters: first is an array containing all your feeds url, second is an integer to limit the returned items. Default is 2. Pretty simple way to get a few feeds to dynamize a bit your blog 🙂 I might make some Widget integration of that thing so that it can be include directly from Dashboard without editing the templates’ code. Feel free to use and abuse!

Note: the ksort() call on $feeds could be done directly into the get_friends_feeds() method; I chose not to do so to keep the liberty to order feeds’ items by date on a global scale or to let them ordered by feed if I want to. Anyway, you may modify this code however you want, so… Go ahead!

Webdesign : un texte bicolore en jQuery

Actuellement en plein travaux sur la version 2.0 de CaerCam.org, je cherchais un moyen simple, rapide et efficace de passer un texte donné en bicolore, bicolore dans le sens un mot dans une couleur, le suivant dans une autre, et ainsi de suite en boucle jusqu’à la fin du texte. Bon, sur un long texte ça n’a évidemment aucun intérêt pratique puisque cela alourdit atrocement ledit texte et rend la lecture désagréable au possible, mais pour des titres par exemple, cela peut-être sympathique de briser un peut l’uniformité du texte, et cela sans avoir à passer par des images. Utilisant jQuery au travail depuis, c’est vers cette technologie que je me suis tourné pour cette simple petite tâche. Démo rapide :

Déjà, il faut inclure la lib jquery ainsi que le plugin pour qu’ils soient chargés. Dans le header de votre page, ajoutez les lignes suivantes :

<script type="text/javascript" src="http://code.jquery.com/jquery-latest.js"></script>
<script type="text/javascript" src="js/jquery.checker.js"></script>

À la toute fin de votre page, juste avant le [sp]</body>[/sp], ajoutez le code suivant qui va appliquer le plugin. En l’ajoutant en fin de page vous éviter qu’un problème quelconque avec ce plugin ne perturbe le chargement de votre page.

<script type="text/javascript">
$(function() {
	$('.bicolor').bicolorize({
		light:'#ffb400',
		dark:'#0087dc'
	});
});
</script>
<h1 class="bicolor">This is a title</h1>
<h2 class="bicolor">This is a title</h2>
<h3 class="bicolor">This is a title</h3>
<h4 class="bicolor">This is a title</h4>
<h5 class="bicolor">This is a title</h5>
<h6 class="bicolor">This is a title</h6>

On obtient le résultat suivant :

title

Quelques détails pratiques, sous forme de commentaire du code :

// Plugin jQuery classique
(function($) {
	$.fn.bicolorize = function(o) {
		// Options par défaut
		o = $.extend( {
			light: '#eeeeee',
			dark: '#606060'
		}, o || {});
		
		return this.each(function() {
			// On récupère le texte à formater
			var text = $(this).text().split(' ');
			// On prépare la valeur de retour : le texte formaté
			var ret = '';
			// Et on insère à l'endroit voulu, préalablement vidé, le texte formaté
			$(this).empty().append(colorize());
			
			// Méthode qui formate le texte. Simple : on découpe la phrase par mots,
			// et on traite un mot sur deux d'une couleur précise.
			function colorize() {
				// Pour chaque mot de la phrase
				for(i=0;i<text.length;i++) {
					// Si rang pair (premier mot, troisième mot, cinquième, etc
					// on le colorise en clair et on l'ajoute au nouveau texte
					if(i%2==0) ret += '<span style="color:'+o.light+'">'+text[i]+'</span> ';
					// Sinon, on le colorie en sombre, et on ajoute
					else ret += '<span style="color:'+o.dark+'">'+text[i]+'</span> ';
				}
				// Et on le renvoie, il sera donc pris comme paramètre par append() ligne 16
				return ret;
			}
		});
	}
})(jQuery);

Simplissime 🙂

FluxBB, topics et tags

Un papier programmation cette fois, de la vraie, du Php objet qui défrise de la queue de poney !

Introduction

Ce bout de code vient d’une proposition d’amélioration de mon forum de randonnée légère favoris ; afin de faciliter les recherches sur ce forum, un système de tags a été mis en place, par exemple un sujet traitant des matelas Therm-a-Rest Z-lite aura pour titre [Matelas] Therm-a-Rest Z-litre. Mais il faut ajouter ces tags à la main, suivant une norme établie, ce qui peut se révéler fastidieux, tant pour les utilisateurs pas encore habitués que pour les modérateurs qui doivent passer derrière pour faire le ménage et les corrections.

L’idée proposée est simple : ajouter, dans le formulaire de création/édition de sujet, des listes déroulantes contenant les tags utilisables pour normaliser le titre du sujet. Techniquement, puisque les deux listes sont ajoutées dans le formulaire, leurs valeurs seront postées en même temps que le reste du formulaire, et donc manipulables via $_POST. Marche à suivre détaillée.

Installation
Ce hack a été testé avec les versions suivantes :

  • FluxBB 1.2.22
  • Apache 2.2.14
  • Php 5.3.2
  • MySQL 5.1.41

L’installation d’un seul fichier est nécessaire, que vous pouvez télécharger ici. Extrayez le fichier tags.php dans votre répertoire /include/ ; si vous voulez le mettre ailleurs, c’est possible, il faudra juste le préciser un peu plus loin.

Maintenant, il y a deux fichiers qui doivent être un peu modifiés : /post.php et /edit.php qui gèrent respectivement la publication et l’édition des topics et posts.

edit.php

D’abord, on inclue les deux tags au début du sujet du topic. À la ligne 77, remplacez :

$subject = pun_trim($_POST['req_subject']);
$subject = pun_trim($_POST['tag1']." ".$_POST['tag2']." ".$_POST['req_subject']);

Puis on fournit la nouvelle version du titre. Ligne 209, remplacez :

echo pun_htmlspecialchars(isset($_POST['req_subject']) ? $_POST['req_subject'] : $cur_post['subject'])
echo pun_htmlspecialchars($subject)

Enfin, à la ligne 210, ajoutez juste avant

<label><br />
getSubject(false);
?&gt;

Ligne 2. : inclusion de la classe.
Si vous n’avez pas mis tags.php dans /include/, c’est ici qu’il faut le préciser.
Ligne 3. : on créé une instance de la classe
Ligne 4. : on récupère le titre du sujet.
Le paramètre false indique de ne pas afficher les tags dans le titre, modifiez-le en true si vous voulez les afficher.

post.php

Les modifications a effectuer pour [sp]post.php[/sp] sont très similaires à celles de [sp]edit.php[/sp] :

Ligne 86, modifier :

$subject = pun_trim($_POST['req_subject']);
$subject = pun_trim($_POST['tag1']." ".$_POST['tag2']." ".$_POST['req_subject']);

Ligne 492, ajouter :

getSubject(false);
?&gt;

Mêmes remarques que pour edit.php

Et voilà, c’est tout ! Cela devrait fonctionner 😉

Annexe : code source

Voici le code source tel qu’il est prévu pour le forum Randonner Léger.

Cette version ne propose que deux types de tags, mais il est tout-à-fait envisageable d’en ajouter d’autres. Elle fait aussi la distinction du forum ; dans le cas présent, les tags que j’appelle «types» ou «spécifiques» ne seront disponibles que dans le forum d’id 11. Les possibilités d’adaptation sont très nombreuses, n’hésitez pas à réutiliser ce code à votre guise, ça marche au GPLCe code est publié sous GNU General Public Licence : http://www.gnu.org/licenses/gpl-3.0.htmlhttp://www.april.org/files/groupes/trad-gpl/doc/GPLv3/www.rodage.org/gpl-3.0.fr.html 😉

J’ai essayé de commenter au mieux le code, cela me semble assez clair, si vous avez des questions sur le fonctionnement n’hésitez pas à les poser en mail ou commentaire.

forum_id = $forum_id;
		// id of specific forum
		$this-&gt;forum = 11;
	
		$this-&gt;subject = $subject;
	
		$this-&gt;tag['types'] = $tag1;
		$this-&gt;tag['tags'] = $tag2;
		
		// debug
		//echo "<!-- tags.php : ".$this-&gt;subject." - ".$this-&gt;tag['types']." - ".$this-&gt;tag['tags']." -->n";

		$this-&gt;types = array(	"[Achat]" ,
					"[Acheté]" ,
					"[Vente]" ,
					"[Vendu]" ,
					"[Don]",
					"[Donné]",
					"[Troc]",
					"[Troqué]",
					"[Bon Plan hors RL]");
	
		$this-&gt;tags = array(	"[Abri]",
					"[Alimentation]",
					"[Autre]",
					"[Bâtons]",
					"[Chaussures]",
					"[GPS]",
					"[Hamac]",
					"[Hygiène]",
					"[Lampe]",
					"[Liste prévisionnelle]",
					"[Matelas]",
					"[Matériaux]",
					"[Montre]",
					"[Photo]",
					"[Popote]",
					"[Questions multiples]",
					"[Réchaud]",
					"[Sac_à_dos]",
					"[Sac_de_couchage]",
					"[Sursac]",
					"[Tarp]",
					"[Tente]",
					"[Vêtements]");
		
		
		// showing lists
		$this-&gt;showTagsList();
	}

	/**
	 * Cleans given tag to display textonly version
	 * Delete [, ] and _
	 * 
	 * @param string $tag to clean
	 * @return cleaned tag
	 */

	function clean($tag)
	{
		// backup
		$tag_propre = $tag;
		// cleaning
		$tag_propre = str_replace("[","", $tag_propre);
		$tag_propre = str_replace("]","", $tag_propre);
		$tag_propre = str_replace("_"," ", $tag_propre);
		// returning
		return $tag_propre;
	}

	/**
	 * Show tags list.
	 * Dirty way due to the way of listing tags, have to double the foreach...
	 * Delete [, ] and _
	 * To avoid repetitions we clean the subject first, and add the tags again
	 * 
	 * @param string $subject the post's subject
	 * @param string $tag1 the first tag in the subject
	 * @param string $tag2 the second tag in the subject
	 */
	public function showTagsList()
	{
		// debug
		//echo "<!-- tags.php : ".$this-&gt;subject." - ".$this-&gt;tag['types']." - ".$this-&gt;tag['tags']." -->n";

		preg_match_all("([(.*?)])",$this-&gt;subject,$matches);
		
		// if there's no tags posted, try to get them from the subject
		if($this-&gt;tag['types'] == null)
			$this-&gt;tag['types'] = $matches[0][0];
		if($this-&gt;tag['tags'] == null)
			$this-&gt;tag['tags'] = $matches[0][1];
		
		// debug
		//echo "<!-- tags.php : ".$this-&gt;subject." - ".$this-&gt;tag['types']." - ".$this-&gt;tag['tags']." -->n";

		if($this-&gt;forum_id == $this-&gt;forum)
		{
			// select list for specific tags
			printf("n");
			$this-&gt;generatOptionTags($this-&gt;types,$this-&gt;tag['types']);
			printf("n");
		}
		
		printf("n");
		$this-&gt;generatOptionTags($this-&gt;tags,$this-&gt;tag['tags']);
		printf("n");
	}
	
	/**
	 * Generates the  list
	 * We check each tag in the list for the one used in the subject
	 * this one will be the default choice to be displayed.
	 * 
	 * @param string $list the list of tags to show
	 * @param string $test the tag already in use
	 */
	private function generatOptionTags($list,$test)
	{
		printf("----n");
		
		foreach($list as $element)
		{
			// not always needed, depending on character encoding used to edit this file
			// I use UTF8 and need this to avoid getting ugly accent...
			// won't be of any use if you're not using accents, anyway.
			$element = utf8_decode($element);
			// getting a clean name for display
			$clean_element = $this-&gt;clean($element);
			// debug
			//echo "<!-- $test ?= $element -->";
			// printing tag
			printf("".$clean_element."n");
		}
	}
	
	/**
	 * Simple accessaccessor
	 * 
	 * @param boolean $show_tags do we show the tags in the subject?
	 * @return the post's subject, with or without tags, default with.
	 */
	public function getSubject($show_tags)
	{
		if($show_tags)
			return $this-&gt;subject;
		else if(!$show_tags)
			return $this-&gt;subject = trim(preg_replace("([(.*?)])", "$2", $this-&gt;subject));
		else
			return $this-&gt;subject;
	}
}
?&gt;

Validation et exclusion

Bon, j’ai partiellement résolu mes problèmes dus au passage à Php 5.3.2, et assez facilement.

Déjà, je me suis aperçu que mes pages n’étaient pas valides W3C pour le XHTML 1.1, et ceux à cause des captions, ces boites qui permettent d’insérer une image et de l’afficher, avec son commentaire, dans un joli cadre autour. La raison est simple, ces boites sont en fait des balises <div> insérées dans un paragraphe ; hors les spécifications d’XHTML 1.1 n’autorisent pas à mettre des <div> dans des <p>, d’où une erreur. Deux solutions à ça :

  • Mode bourrin dégueulasse : modifier à la main la fonction qui gère les captions. elle est trouve dans /wp-includes/media.php, il suffit de changer le <div …> en <span …>, et c’est valide ! Sauf qu’il faudra à nouveau modifier le fichier à chaque mise-à-jour de WordPress… bref, ça marche, mais c’est pas génial.
  • Mode intelligent : on surcharge le shortcode. Une API de WordPress qui permet de créer facilement et rapidement des… shortcodes, hé oui : http://codex.wordpress.org/Shortcode_API qui gère les captions. Ajoutez le code suivant dans le fichier de fonctions de votre thème (/wp-content/votrethème/functions.php) :
function W3CValidCaption($attr, $content = null) {

   extract(shortcode_atts(array(
       'id'    =&gt; '',
       'align' =&gt; 'alignnone',
       'width' =&gt; '',
       'caption' =&gt; ''
   ), $attr));

    if ( 1 &gt; (int) $width || empty($caption) )
       return $content;

   if ( $id ) $id = 'id="' . esc_attr($id) . '" ';

   return '<span>'
   . do_shortcode( $content ) . '<span class="wp-caption-text">' . $caption . '</span></span>';
}

add_shortcode('caption', 'W3CValidCaption');
add_shortcode('wp-caption', 'W3CValidCaption');

C’est une simple copie de la fonction img_caption_shortcode() du fichier /wp-includes/media.php, avec les retouches permettant la validation : le <div> devient un <span>, et du coup le <p> contenant le texte devient également un <span>. Si ce texte apparait à gauche ou à droite et pas au centre sous l’image comme auparavant, pensez à éditer la feuille de style de votre thème en changeant text-align: left; ou text-align: right; en text-align: center;. Voilà pour la validation 🙂

Reste l’exclusion, ou comment ne pas afficher les articles de certaines catégorie sur la page d’accueil. C’est ce que faisait jusqu’à maintenant le plugin Ace dont j’ai parlé la dernière fois, mais comme il ne fonctionne plus depuis la mise-à-jour de Php, j’ai du trouver autre chose. Et finalement, j’aurais du commencer directement par là puisque le Codex WordPress apporte une réponse efficacePar ici : http://codex.wordpress.org/The_Loop#Exclude_Posts_From_Some_Category, il suffit d’ajouter :


(-xx et -yy correspondent aux ID des catégories à ne pas afficher)

Juste avant


Dans votre fichier index de thème /wp-content/votrethème/index.php, et le tour est joué !

WordPress et Php 5.3.2

Hop, un second papier dans la catégorie Info.

J’ai effectué dimanche soir la mise-à-jour d’Ubuntu de la 9.10 vers la 10.04, principalement à cause de MediaWiki, mais j’en reparlerais plus tard. Lucid Lynx propose PHP en version 5.3.2(-1ubuntu4.1), ce qui m’a causé quelques problèmes d’adaptation, que cela soit avec MediaWiki, Piwigo où WordPress.

Pour WordPress, version 2.9.2, le bilan n’est pas brillant puisqu’il y a plusieurs trucs qui foirent un brin… principalement le plugin Ace version 1.4.3 Un plugin bien pratique qui permet entre autres de ne pas afficher les billets d’une certaine catégorie sur la page d’accueil… comme c’était le cas ici jusqu’à il y a peu pour les billets de la catégorie Info. http://ace.dev.rain.hu/http://wordpress.org/extend/plugins/advanced-category-excluder/ d’après ce que j’ai regardé. Déjà, l’erreur suivante apparait :

Warning: Parameter 1 to ace_where() expected to be a reference, value given in /***/wp-includes/plugin.php on line 166

Solution, remplacer la ligne 166 :

$value = call_user_func_array($the_['function'], array_slice($args, 1, (int) $the_['accepted_args']));

Part :

$value = @call_user_func_array($the_['function'], array_slice($args, 1, (int) $the_['accepted_args']));

Tout bête, ça ne corrige rien, mais ça désactive l’affiche de l’erreur ; c’est bourrin, mais en attendant ça évite de ruiner le css.

Toutefois il reste un soucis : les restrictions d’affichage des billets ne fonctionnent plus, et le moindre papier en cours de rédaction et publié en temps réel et systématiquement affiché sur la page d’accueil, pas génial…

Une nouvelle version d’Ace devrait arriver d’ici peu, mais en attendant il va falloir faire avec.

Ajout de références à WordPress

Hop, premier papier dans la catégorie geekage informatique. D’une manière générale les articles postés ici seront surtout des mémos des différents bricolages que j’effectue, ça me permettra d’en garder une trace et donc de ne pas tout perdre dès que je fais une mise-à-jour 🙄

Premier truc donc, ajouter un système de gestion de référence à WordPress. En d’autre terme, faire en sorte que si vous placez dans votre article : Ceci est un texte <ref>et ceci une référence.</ref>

Vous obteniez : Ceci est un texte [1]

Et à la fin de l’article une boite listant toutes les références données.

J’avais initialement bricolé un petit truc perso en 3 ou 4 lignes de Php, mais c’était pas génial car implanté comme un porc dans le code même de WordPress, donc à chaque mise-à-jour il fallait l’insérer de nouveau. De plus il y a (au moins) un plugin qui fait en gros cela, mais il se base directement sur des liens, donc pas exactement ce que je veux. C’est le plugin List of references, et c’est par ici pour le télécharger : http://wordpress.org/extend/plugins/auto-list-of-references/. Comme il ne fait pas exactement ce que je veux, à savoir gérer des tags spécifiques et compter dynamiquement mes références, je l’ai adapté à mes besoins. Le code est assez compréhensible je crois, et j’ai pas mal commenté :

/**
   * Plugin Name: List of references reload
   * Plugin URI: http://wordpress.org/extend/plugins/auto-list-of-references/
   * Description: Personnal adaptation of &quot;List of references&quot; plugin by Christian Weichel (http://32leaves.net)
   * Version: 1.1
   * Author: Charlie Merland
   * Author URI: http://32leaves.net/
   */

// basic format for our ref links
$FORMAT = &quot;&lt;small&gt;[&lt;a id={id}&gt;{uid}&lt;/a&gt;]&lt;/small&gt; {content}&quot;;

class ListOfReferencesGenerator {
	private $_id;
	private $_text;
	
	public function __construct($text) {
		$this-&gt;_id = rand();
		$this-&gt;_text = $text;
		$this-&gt;_text = $this-&gt;setOldRef($text);
	}

	/**
	 * Deal with older manual references
	 * @param string $text the post content
	 * @return string the text where all :int: and [int] have been replaced by anchors and links
	 */
	private function setOldRef($text) {
		// remplacement
		$text = preg_replace(&quot;((:)(d+)(:))&quot;, &quot;&lt;small&gt;[&lt;a id=&quot;&quot;.$this-&gt;_id.&quot;$2&quot;&gt;$2&lt;/a&gt;]&lt;/small&gt;&quot;, $text);
		$text = preg_replace(&quot;(([)(d+)(]))&quot;, &quot;&lt;small&gt;[&lt;a href=&quot;#&quot;.$this-&gt;_id.&quot;$2&quot;&gt;$2&lt;/a&gt;]&lt;/small&gt;&quot;, $text);
		// return
		return $text;
	}

	/**
	 * Search for every reference in the text
	 * @return array all references found
	 */
	private function parseReferences() {
		// &lt;ref&gt;this is a reference&lt;/ref&gt;
		preg_match_all(&quot;#&lt;ref&gt;s*(.*?)&lt;/ref&gt;#i&quot;, $this-&gt;_text, $matches);
		return $matches;
	}

	/**
	 * Create the list that will be displayed
	 * @return string the references list
	 */
	private function prepareReferencesList() {
		// how to present our references
		global $FORMAT;
		// list to store those references
		$list = array();
		// parsing those refs
		$parsed_refs = $this-&gt;parseReferences();
		// init id
		$id = 0;
		// for each ref
		for($i = 0; $i &lt; count($parsed_refs[0]); $i += 1) {
			$id += 1;
			// strip &quot; &quot;
			$text = str_replace('&quot;', '', $parsed_refs[1][$i]);
			// every reference has a text and an ID
			$list[$text] = array($text, $id);
		}
		$this-&gt;list = $list;
		
		$result = &quot;&lt;fieldset class=&quot;ref&quot;&gt;&lt;legend&gt;R&amp;amp;eacute;f&amp;amp;eacute;rences :&lt;/legend&gt;&quot;;
		// for each ref of the list
		foreach($list as $ref =&gt; $content) {
			// get text
			$text = $content[0];
			// get ID
			$id = &quot;&quot;.$this-&gt;_id.&quot;&quot;.$content[1];
			// get ID to show
			$uid = $content[1];
			// replace each tag
			$result .= str_replace(&quot;{id}&quot;, $id, str_replace(&quot;{uid}&quot;, $uid, str_replace(&quot;{content}&quot;, $text, $FORMAT)));
		}
		$result .= &quot;&lt;/fieldset&gt;&quot;;
		
		return $result;
	}

	/**
	 * Replace every reference declaration with a simple link
	 * @return string the link
	 */
	public function replace_link_callback($matches) {
		// strip &quot; &quot;
		$id = $this-&gt;list[str_replace('&quot;', '', $matches[1])];
		// return a simple link to the anchor
		return $result = &quot;&lt;small&gt;[&lt;a href=&quot;#$tid$id[1]&quot;&gt;$id[1]&lt;/a&gt;]&lt;/small&gt;&quot;;
	}

	/**
	 * Replace every reference declaration with a simple link
	 * @return string the link
	 */
	public function process() {
		// checking ref presence
		if(!$this-&gt;isEnabled()) return $this-&gt;_text;

		// prepare the list
		$list = $this-&gt;prepareReferencesList();
		// this must be useful
		$result = preg_replace_callback(&quot;#&lt;ref&gt;s*(.*?)&lt;/ref&gt;#i&quot;, array(&amp;amp;$this, 'replace_link_callback'), $this-&gt;_text);
		// add the references list
		$result = str_replace(&quot;&lt;references /&gt;&quot;, $list, $result);
		// return
		return $result;
	}
	
	/**
	 * Check for a &lt;references /&gt; tag indicating we actually have references
	 * @return boolean any ref or not?
	 */
	private function isEnabled() {
		return strpos($this-&gt;_text, '&lt;references /&gt;') !== false;
	}
	
}

function filter_list_of_references($text) {
	$processor = new ListOfReferencesGenerator($text);
	return $processor-&gt;process();
}

add_filter('the_content', 'filter_list_of_references');

Ainsi il vous suffit de mettre toutes vos références de la forme <ref>ma référence</ref>, ajouter un <references /> à la fin de votre article, et toutes les références y seront listées, numérotées et liées. Ça n’a l’air de rien, mais c’est quand même bien pratique…