Mots-clé : code

WordPress : notes pour les débutants

Petites notes que j’ai apprises lors du développement d’un plugin qui créait des champs entièrement personnalisés :

Les filtres et les actions se ressemblent beaucoup à la fois dans la documentation et dans la déclaration, pourtant :

  • un filtre est une fonction qui reçoit quelque chose en paramètre et qui doit renvoyer quelque chose en paramètre, et s’il n’y a aucune modification du paramètre qui arrive, elle doit obligatoirement renvoyer le paramètre entrant ;
  • par opposition, une action est une fonction qui ne reçoit pas forcément quelque chose en paramètre et surtout, qui n’a pas besoin de renvoyer quelque chose (même si elle renvoie quelque chose, c’est ignoré).

Dans beaucoup de fonctions, il y a deux versions : avec et sans get_ :

  • the_ID(); et get_the_ID();
  • the_category(); et get_the_category();

La version sans le get_ affiche le contenu correspondant (= echo) alors que la version avec get_ renvoie le contenu correspondant, il faut donc utiliser cette dernière en l’assignant à une variable (par exemple : $categorie = get_the_category();).

Enfin dernière astuce : très souvent (voire tout le temps), les fonctions qui commencent par wp_ affichent le contenu, elles font un echo. Exemple de code que j’ai trouvé un peu déroutant quand on ne sait pas ce qu’il en est :

echo '<div class="form-wrap">';
wp_nonce_field(
    'ma_cle_unique',
    'ma_cle_unique_nonce'
);
echo '</div>';

Ici, wp_nonce_field() affiche quelque chose. Les fonctions qui commencent par wp_ affichent quelque chose.

Voilà. En espérant que cela évite à des personnes de perdre autant de temps que cela m’en a fait perdre…

google code prettify – prettyprint : les codes possibles

Pour rappel rapide, l’utilisation est extrêmement simple : un simple include JavaScript de google code prettifier (je vous laisse le chercher et le faire), puis l’utilisation : au lieu d’écrire de simples balises <code></code> ou <pre></pre>, ajoutez-y la classe prettyprint comme ceci :
<code class="prettyprint">Mon code</code>

Et vous passerez d’un code tel que :
alert("Bonjour");
…à :
alert("Bonjour");

Mais le seul hic c’est que le JavaScript de google « essaie » de deviner ce qu’il y a entre dans le code pour le mettre en couleur. Parfois il ne trouve pas et donc ne colore pas la syntaxe, ou pire, il se trompe (sur de très courts morceaux de code c’est normal). Il vous suffit de préciser de quel type de code il s’agit.

  • Exemple avec du JavaScript :
    <pre class="prettyprint lang-js">var t=12;</pre>
    Ce qui donnne 

    var t=12;
  • Exemple avec du Shell :
    <pre class="prettyprint lang-sh">echo "$MAVAR ok"</pre>
    Ce qui donnne 

    echo "$MAVAR ok"

Voici tous les codes qu’il est possible d’utiliser si jamais vous utilisez le google code prettifier

  • lang-c
  • lang-cc
  • lang-coffee
  • lang-cs
  • lang-css
  • lang-el
  • lang-erlang
  • lang-go
  • lang-hs
  • lang-html
  • lang-java
  • lang-js
  • lang-lua
  • lang-ml
  • lang-proto
  • lang-py
  • lang-scala
  • lang-sh
  • lang-sql
  • lang-vb
  • lang-vhdl
  • lang-wiki
  • lang-yaml

WordPress et shortcodes : comment les lister

Si jamais vous commencez à découvrir la chose super pratique qu’est un shortcode alors voici une petite astuce, si vous êtes sur Linux : comment lister les shortcodes présents.

Il suffit dans le shell, d’aller dans votre répertoire WordPress et de taper cette ligne de commande :

find . -type f -print0 | grep -z php$ | xargs -0 grep 'add_shortcode' | more

Et vous aurez le listing de tous les endroits où on appelle cette fonction. Il ne vous reste plus qu’à regarder ce qu’ont fait les personnes ! Il existe même des shortcodes cachés dans certains thèmes, que les auteurs ont dû faire pour eux, mais qu’ils n’ont pas documenté ! Très pratique !

Exemple :

...ygen/library/functions/shortcodes.php: add_shortcode( 'entry-title', 'hybrid_entry_title_shortcode' );
...ygen/library/functions/shortcodes.php: add_shortcode( 'entry-author', 'hybrid_entry_author_shortcode' );
...ygen/library/functions/shortcodes.php: add_shortcode( 'entry-terms', 'hybrid_entry_terms_shortcode' );
...ygen/library/functions/shortcodes.php: add_shortcode( 'entry-comments-link', 'hybrid_entry_comments_link_shortcode' );
...ygen/library/functions/shortcodes.php: add_shortcode( 'entry-published', 'hybrid_entry_published_shortcode' );
...ygen/library/functions/shortcodes.php: add_shortcode( 'entry-edit-link', 'hybrid_entry_edit_link_shortcode' );
...ygen/library/functions/shortcodes.php: add_shortcode( 'entry-shortlink', 'hybrid_entry_shortlink_shortcode' );
...ygen/library/functions/shortcodes.php: add_shortcode( 'entry-permalink', 'hybrid_entry_permalink_shortcode' );
...ygen/library/functions/shortcodes.php: add_shortcode( 'post-format-link', 'hybrid_post_format_link_shortcode' );
...ygen/library/functions/shortcodes.php: add_shortcode( 'comment-published', 'hybrid_comment_published_shortcode' );
...ygen/library/functions/shortcodes.php: add_shortcode( 'comment-author', 'hybrid_comment_author_shortcode' );
...ygen/library/functions/shortcodes.php: add_shortcode( 'comment-edit-link', 'hybrid_comment_edit_link_shortcode' );
...ygen/library/functions/shortcodes.php: add_shortcode( 'comment-reply-link', 'hybrid_comment_reply_link_shortcode' );
...ygen/library/functions/shortcodes.php: add_shortcode( 'comment-permalink', 'hybrid_comment_permalink_shortcode' );
...gelines/includes/class.shortcodes.php: add_shortcode( $shortcode, array( &$this, $data['function']) );
...b/library/shortcodes.php:add_shortcode('gallery', 'gallery_shortcode_tbs');
...b/library/shortcodes.php:add_shortcode('button', 'buttons');
...b/library/shortcodes.php:add_shortcode('alert', 'alerts');
...b/library/shortcodes.php:add_shortcode('block-message', 'block_messages');
...b/library/shortcodes.php:add_shortcode('blockquote', 'blockquotes');
...ean-retina/library/shortcodes/cleanretina-shortcodes.php: * Creates new shortcodes for use in any shortcode-ready area. This function uses the add_shortcode()
...ean-retina/library/shortcodes/cleanretina-shortcodes.php: * @uses add_shortcode() to create new shortcodes.
...ean-retina/library/shortcodes/cleanretina-shortcodes.php: add_shortcode( 'the-year', 'cleanretina_the_year_shortcode' );
...ean-retina/library/shortcodes/cleanretina-shortcodes.php: add_shortcode( 'site-link', 'cleanretina_site_link_shortcode' );
...ean-retina/library/shortcodes/cleanretina-shortcodes.php: add_shortcode( 'wp-link', 'cleanretina_wp_link_shortcode' );
...ean-retina/library/shortcodes/cleanretina-shortcodes.php: add_shortcode( 'th-link', 'cleanretina_themehorse_link_shortcode' );
...ntra/includes/theme-shortcodes.php:add_shortcode('mantra-site', 'mantra_site_link_fn');
...ntra/includes/theme-shortcodes.php:add_shortcode('mantra-author', 'mantra_the_author_fn');
...ntra/includes/theme-shortcodes.php:add_shortcode('mantra-tag-cloud', 'mantra_tag_cloud_fn');
...ntra/includes/theme-shortcodes.php:add_shortcode('mantra-multi', 'mantra_multi_column_fn');
...ntra/includes/theme-shortcodes.php:add_shortcode('mantra-column', 'mantra_column_fn');
...ntra/includes/theme-shortcodes.php:add_shortcode( 'mantra-pullquote', 'mantra_pullquote_fn' );
...ntra/includes/theme-shortcodes.php:add_shortcode( 'mantra-button-light', 'mantra_button_light_fn' );
...ntra/includes/theme-shortcodes.php:add_shortcode( 'mantra-button-dark', 'mantra_button_dark_fn' );
...ntra/includes/theme-shortcodes.php:add_shortcode( 'mantra-button-color', 'mantra_button_color_fn' );
...ntra/includes/theme-shortcodes.php:add_shortcode('cryout-site', 'mantra_site_link_fn');
...ntra/includes/theme-shortcodes.php:add_shortcode('cryout-author', 'mantra_the_author_fn');
...ntra/includes/theme-shortcodes.php:add_shortcode('cryout-tag-cloud', 'mantra_tag_cloud_fn');
...ntra/includes/theme-shortcodes.php:add_shortcode('cryout-multi', 'mantra_multi_column_fn');
...ntra/includes/theme-shortcodes.php:add_shortcode('cryout-column', 'mantra_column_fn');
...ntra/includes/theme-shortcodes.php:add_shortcode( 'cryout-pullquote', 'mantra_pullquote_fn' );
...ntra/includes/theme-shortcodes.php:add_shortcode( 'cryout-button-light', 'mantra_button_light_fn' );
...ntra/includes/theme-shortcodes.php:add_shortcode( 'cryout-button-dark', 'mantra_button_dark_fn' );
...ntra/includes/theme-shortcodes.php:add_shortcode( 'cryout-button-color', 'mantra_button_color_fn' );
...artupwp/functions.php:add_shortcode('wp_caption', 'fixed_img_caption_shortcode');
...artupwp/functions.php:add_shortcode('caption', 'fixed_img_caption_shortcode');
...p:add_shortcode('wp_caption', 'img_caption_shortcode');
...p:add_shortcode('caption', 'img_caption_shortcode');
...p:add_shortcode('gallery', 'gallery_shortcode');
...p:add_shortcode( 'audio', 'wp_audio_shortcode' );
...p:add_shortcode( 'video', 'wp_video_shortcode' );
...-embed.php: add_shortcode( 'embed', '__return_false' );
...-embed.php: * @uses add_shortcode()
...-embed.php: add_shortcode( 'embed', array( $this, 'shortcode' ) );
...es.php: * add_shortcode('footag', 'footag_func');
...es.php: * add_shortcode('bartag', 'bartag_func');
...es.php: * add_shortcode('baztag', 'baztag_func');
...es.php:function add_shortcode($tag, $func) {

Symfony 2 Embedded Forms: Catchable Fatal Error: Argument 1 passed to Entity::addProperty must be an instance of XX\MyClass, array given

Encore une abstraction qui fuit.

Si jamais vous avec un problème avec un ManyToMany et que vous rencontrez une erreur du type : Symfony 2 Embedded Forms: Catchable Fatal Error: Argument 1 passed to Entity::addProperty must be an instance of XX\MyClass, array given, c’est que vous avez peut-être le même problème que moi, à savoir : une mauvaise déclaration de votre type de formulaire.

Enfin… mauvaise… disons qu’il manque des choses, et que logiquement, tant qu’on n’a pas une connaissance parfaite des rouages de Symfony, on ne comprend pas pourquoi ça ne fonctionne pas.

Je vais donc vous dire ce qu’il me manquait : j’avais une table personne et une table adresse.
Ces deux tables étaient reliées par une relation ManyToMany : une personne peut avoir une ou plusieurs adresses, et à une même adresse, plusieurs personnes peuvent habiter (heureusement ! 😉 ).

Dans la déclaration du type d’adresse, tout semblait cohérent, il n’y avait aucune erreur, mais il manquait une seule chose : la fonction setDefaultOption(). Je vous la fais courte : le code qui suit fonctionne.

Même si cette astuce ne fonctionne pas pour vous, essayez de suivre mon raisonnement : j’ai refait complètement un projet en partant de zéro, en suivant les instructions ici (Symfony 2 : Comment imbriquer une Collection de Formulaires) : et ensuite j’ai comparé pas à pas avec mon code. Pour en arriver aux six petites lignes qui manquaient : la fonction setDefaultOption().

<?php

namespace MaSociete\Bundle\MyBundle\Form\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\OptionsResolver;
use Symfony\Component\Form\FormBuilderInterface;

class AdresseType extends AbstractType
{
   /**
    * Builds the form.
    *
    * This method is called for each type in the hierarchy
    * starting form the top most type. Type extensions can
    * further modify the form.
    *
    * @see FormTypeExtensionInterface::buildForm()
    *
    * @param FormBuilderInterface $builder The form builder
    * @param array                $options The options
    */
    public function buildForm(
        FormBuilderInterface $builder,
        array $options
    ) {
        $builder->add('adresse1', 'text')
            ->add('adresse2', 'text')
            ->add('cp', 'text')
            ->add('ville', 'text');
        }
    public function setDefaultOptions(
        \Symfony\Component\OptionsResolver\OptionsResolverInterface $resolver
    ) {
        $resolver->setDefaults(array(
            'data_class' => 'MaSociete\Bundle\MyBundle\Entity\Adresse',
        ));
    }
    public function getDefaultOptions(array $options)
    {
        return array(
            'data_class' => 'MaSociete\Bundle\MyBundle\Entity\Adresse',
        );
    }
    public function getName()
    {
        return 'adresse';
    }
}

Développement : Coding contest !

Nouveau challenge de codeurs !

C’est pour le fun, essayez vous aussi 

Le principe est simple

Vous aurez deux puzzles de programmation à résoudre.

Pour ce faire, vous pourrez choisir votre langage favori parmi ceux-ci : Java, C, C++, C#, Javascript, PHP, Python, Ruby, Objective-C, Haskell and Go.
La durée moyenne d’un challenge est de 2 heures et 30 minutes.

J’y serai, le 23 novembre !

Inscrivez vous !
Si jamais plus de trois personnes se sont inscrites via le lien précédent, et ont dépassé un score de 0% (= y sont allées), j’aurais un t-shirt codingame 😉

Php : une boucle qui incarne une des pires horreurs possibles

Voici une horreur qu’on peut trouver, en plein milieu du code sur lequel on m’a demandé de travailler.
Si vous faites mieux dans la série « la pire horreur en Php », n’hésitez pas à en donner un exemple en commentaire…

for ($i=0; $i<count($tab); $i++)
{
    if ($tab[key($tab)]==true) {
        $montableau2[][key($tab)]='code';
    }
    next($tab);
}

Drupal : code pour les liens avec des URLs dynamiques

Drupal : comment s’adapter à une migration si le site n’est plus à la racine ?

Dans les modules, activation du module « Php filter », afin que le code Php soit exécuté.
Et dans le texte qu’il y a dans un bloc « menu », par exemple, vous pourriez vous inspirer d’un code comme celui-ci (sachant qu’il vous faut absolument revoir l’indentation, qui n’est pas acceptable pour un code digne de ce nom) 🙂  :

<?php /* Ce code sert à générer les URLs
 * de manière dynamique, afin que si l'installation
 * Drupal est dans un sous-répertoire, les liens
 * soient "automatiquement" adaptés, via
 * le code "'absolute' => TRUE", 
 */ ?>
<ol>
    <li>
        <?php echo l(t('Menu1'),
            'lien1',
            array( 'absolute' => TRUE, 'query' => array()
        )); ?>
    </li>
    <li>
        <?php echo l(t('Menu2'),
            'lien2',
            array( 'absolute' => TRUE, 'query' => array()
        )); ?>
    </li>
    <li>
        <?php echo l(t('Menu3'),
            'lien3',
            array( 'absolute' => TRUE, 'query' => array()
        )); ?>
    </li>
    <li>
        <?php echo l(t('Menu4'),
            'lien4',
            array( 'absolute' => TRUE, 'query' => array()
        )); ?>
    </li>
</ol>

Php Code Sniffer : changer l’indentation

PHPCodeSniffer est un super outil de vérification de qualité de code.
Le seul souci c’est qu’il vérifie en ayant une indentation de 4.

Tous mes sources sont basés sur une indentation de 2.

La solution :

  • chercher où se trouve le fichier :
    CodeSniffer/Standards/Generic/Sniffs/WhiteSpace/ScopeIndentSniff.php
  • éditer à la main le fichier et changer la valeur :
    public $indent = 4;
    en :
    public $indent = 2;

Pour information, mon fichier se trouvait ici (Ubutunu 10.04) :
/usr/share/php/PHP/CodeSniffer/Standards/Generic/Sniffs/WhiteSpace/ScopeIndentSniff.php

La seconde modification c’est pour les variables passées à l’intérieur des fonctions : de la même façon le code est censé avoir une indentation de 4.

C’est dans le fichier :
CodeSniffer/Standards/PEAR/Sniffs/Functions/FunctionCallSignatureSniff.php

Qu’il vous faudra modifier :
$expectedIndent = ($functionIndent + 4);
par :
$expectedIndent = ($functionIndent + 2);

Pour information, mon fichier se trouvait ici (Ubutunu 10.04) :
/usr/share/php/PHP/CodeSniffer/Standards/PEAR/Sniffs/Functions/FunctionCallSignatureSniff.php

Php : comment dériver la classe Exception et lui passer un tableau de chaines

Dans la plupart de mes pages, j’ai besoin, lorsqu’il y a une erreur, de mettre un message explicite qui est souvent long. Qui dit long dit plusieurs lignes. Ou bien j’ai envie de stopper l’exécution en cours et d’afficher plusieurs messages. L’idée de base est de lever une exception, mais une exception qui reçoit plusieurs chaînes de caractères comme message d’erreur. Alors j’ai fait ma propre classe en m’inspirant de l’aide sur les exceptions de php.net.

On peut lever une exception de cette façon :

throw new ExceptionErr(
  array(
    "Nous vous avons envoyé la liste récemment.",
    "Afin de garantir une qualité de service ".
    "pour tout le monde, ",
    "nous ne pouvons ré-envoyer la liste que dans ".
    $delai
  ) 
);

Vous pouvez la récupérer ou simplement lire le code. En espérant que cela serve à d’autres personnes :

<?
/**
 * fichier exception_err.php
 *
 * Historique :
 * 21/09/2011 : Olivier Pons
 *              Création
 * @author Olivier Pons
 * @version 1.0
 * @since 1.0
 * @copyright Olivier Pons
 * @package Classes_Base
 */

/**
 * Includes
 */

/**
 * Classe Exception qu'on peut
 * lever en lui passant un tableau
 * en paramètre.
 *
 * @author Olivier Pons
 * @version 1.0
 * @since 1.0
 * @copyright Olivier Pons
 * @package Classes_Base
 *
 */
class ExceptionErr extends Exception
{
  /** 
   * @var array le tableau contenant les lignes d'erreur
   */
  private $TabErr;
  
  /** 
   * Lit le tableau contenant les lignes d'erreur
   * @return array le tableau contenant les lignes d'erreur
   */
  public function getTabErr()
  {
    if (!isset($this->TabErr)) {
      throw new Exception('TabErr : pas initialise');
    }   
    return $this->TabErr;
  }

  /** 
   * Surcharge de la représentation de l'objet sous forme de
   * chaine
   *
   * @return string Représentation de l'objet sous forme de
   *   chaine.
   */
  public function __toString() {
      return __CLASS__ .
        ": [{".$this->code."}]: {".$this->message."} ".
        "- {".var_export($this->TabErr,true)."}\n";
  }

  /** 
   * Constructeur surchargé de la classe "Exception" de base.
   *
   * @param array $tab_err
   *   Tableau contenant les chaines à mettre à la suite dans
   *   un tableau d'erreur (voir les classes qui utilisent
   *   cette classe pour comprendre)
   * @param integer $code
   *   Numéro de code d'erreur
   * @param Exception $previous
   *   Exception précédente
   *
   * @return void
   */
  public function __construct(
    $messages, $code = 0,
    Exception $previous = null) 
  {
      if (!is_array($messages)) {
        throw new Exception("Messages : array attendu");
      }   
      if (count($messages)==0) {
        throw new Exception("Messages : tableau vide");
      }   
      list($message)=each($messages);
      parent::__construct($message, $code, $previous);
      $this->TabErr = $messages;
  }
}

?>

HTML : tags <pre> / <code> : comment forcer retour à la ligne

Voici une astuce : vous avec une page qui s’affiche parfaitement, avec plein de choses, à part un petit détail plutôt gênant : vous avez des lignes de code qui « débordent » et lorsque vous voulez imprimer, comme, justement, ça déborde, vous n’avez pas le code en entier.

Il vous suffit de mettre ce code en dernier dans le css (afin qu’il « écrase » toutes les configurations précedentes des retour-chariot) :


pre, code {
 white-space: pre-wrap;       /* css-3 */
 white-space: -moz-pre-wrap;  /* Mozilla, since 1999 */
 white-space: -pre-wrap;      /* Opera 4-6 */
 white-space: -o-pre-wrap;    /* Opera 7 */
 word-wrap: break-word;       /* Internet Explorer 5.5+ */
}

Et voilà, vous pourrez imprimer votre document tranquillement, tout le code sera affiché.
Cet article fait suite à une question que j’ai posée sur stackoverflow.com. Cette dernière avait déjà été posée, et la réponse était valide : le lien est ici. Et la solution, carrément à la source, est ici.