Créer un plugin enfant sous WordPress : Parce que les enfants, c’est bien.

Créer un plugin enfant sous WordPress : Parce que les enfants, c’est bien.

Créer un plugin enfant dans WordPress, possible ou pas ?

J’entends par la création d’un plugin enfant, la même chose que la création d’un thème enfant, le but est de ne pas modifier le core du plugin afin que les prochaines mises à jour n’écrasent pas mes modifications.

Oui mais WordPress ne permets pas de créer un plugin pour en faire un « enfant » d’un autre … En fait, si … c’est tout à fait possible. La preuve, Greg m’a devancé et a créé un hack pour un plugin existant : http://www.screenfeed.fr/blog/plugin-drag-drop-for-post-thumbnails-hack-01007/

Vas y dis comment !!

Oui une seconde :p D’abord, comment ça peut fonctionner. Et bien je vois 2 choses :

  1. La première et la meilleure serait l’utilisation des hooks et filtres disponibles dans le plugin parent. SI ce plugin en contient assez et bien placés alors il est simple de les utiliser pour ajuster le plugin à nos besoins. C’est exactement ce que nous faisons déjà avec le core de WordPress en fait !
  2. La deuxième c’est la possibilité de « déhooker » et « rehooker » un hook… oula … ok je la refait. Le plugin parent, s’il n’a pas assez (ou du tout !) de hook, il va falloir retirer les hooks qu’il a posé, créer notre fonction basé sur la sienne, puis reposer le hook sur cette même action.

Ok j’ai (un peu) compris, montre un exemple

Un exemple avec (soyons chauvins) mon plugin More Secure Login. Je souhaite supprimer le lien « Powered by BAW More Secure Login » qui se trouve dans les champs de connexion (vilain !) et je souhaite aussi modifier le type du champ du plugin en « password » car là , il est en « text » par défaut et ça ne me plait pas.

Je regarde si le plugin fourni des hooks pour ça : Premier réflexe, je lis la FAQ qui m’invite à lire le fichier « help.html » dans les dossiers du plugin. Je l’ouvre et je lis :

Ha super ça, exactement ce dont j’avais besoin (comme par hasard …), et pour la suppression du lien je lis :

Aà¯e, là , pas de filtre, au contraire, l’auteur demande de ne pas le supprimer … Mais je suis vilain alors je vais le faire quand même, sans modifier le code, oui Môsieur.

Allez du code !!

Ok, alors créons un plugin avec une entete normale habituelle :

/*
Plugin Name: BAW More Secure Login "Child"
Description: Modifie le champ en "password" et supprime le lien dans les champs
Version: 1.0
Author: Moi
*/

Puis ajoutons notre filtre perso sur le hook du plugin :

function modify_msl_field( $input_props )
{
$input_props['type'] = 'password';
return $input_props;
}
add_filter( 'bawmsl_inputprops', 'modify_msl_field' );

J’active le plugin et j’obtiens:

Ha super !

Supprimons le lien maintenant.

Oui oui ok. Ici il va falloir regarder dans quelle fonction est ce lien et quel hook et lié à cette fonction.
Je lis donc : Fonction « bawmsl_login_form_add_field » pour le hook « login_form« . je l’ai lu ici : « add_action( ‘login_form’, ‘bawmsl_login_form_add_field’ ); »
Je vais ajouter une ligne dans mon plugin enfant :

Maintenant, le plugin parent ne pourra plus ajouter le lien. Euh mince, ni le champ ni rien d’autre. Je vais devoir copier/coller sa fonction, un peu comme si je clonais son plugin. L’avantage de faire ça plutôt que de créer mon pluginn basé sur le sien c’est que je vais profiter des mises à jour du plugin parent et de ses nouvelles fonctionnalités !
Voici donc mon copié/collé modifié :

function my_login_form_add_field()
{
global $wpdb;
$hash = md5( time() . rand() );
$table_name = $wpdb->prefix . 'moresecurelogin';
$col = chr( rand( 1, 8 ) + 64 );
$row = rand( 1, 8 );
// Insert a random hash associated with a code couple, like A1
$wpdb->insert( $table_name, array( 'timestamp' => current_time('mysql'), 'code' => $col.$row, 'hash' => $hash ) );
// Delete all hash if generated 5mn or more earlier
$wpdb->query( 'DELETE FROM ' . $table_name . ' WHERE timestamp < "' . date( 'Y-m-d H:i:s', mktime( date( 'H' ), date( 'i' ) - 5, date( 's' ), date( 'n' ), date( 'j' ), date( 'Y' ) ) ) . '"' ); // 5 mn
$input_props = array( 'type' => 'text',
'id' => 'mslcode',
'class' => 'input',
'value' => '',
'autocomplete' => 'off',
'placeholder' => __( 'Required code: ', 'bawmsl' ) . $col.$row,
'tabindex' => '89',
'style' => ''
);
$input_props = apply_filters( 'bawmsl_inputprops', $input_props );
?>
<p id="bawmsl"><label>
More Secure Login <?php _e( 'Code', 'bawmsl' ) ?><strong><?php echo $col.$row; ?></strong> <a href="<?php echo BAWMSL_PLUGIN_URL; ?>/helps/help-<?php _e( 'en', 'bawmsl' ); ?>.html" target="_blank"><img title="<?php _e( 'Need help?', 'bawmsl' ); ?>" alt="<?php _e( 'Need help?', 'bawmsl' ); ?>" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAsxJREFUeNpUUktME2EQnu1ut29o00JoQUCKBqQhIqISxQcEhShehBNevHnwyMlEI+JRYzQeuElijNGIejPqARPDQSNCCNaatsqrtKRb7YOW0n38zr9boP7Jl52dme/7Z+YfhhACXOtb0I4CwOgQLIJpRMe9YmAECAkCkQEI5oBOdUrz/UWr9NAEojgQY4MDLR2DF1o60L6NcGnk/09RgDxDjKJRi2jGxPs9Xd4jNVVl7uoqm/vs6cZO9D1QY2oOuaVxADiNL7uuXD7W93zyWzfDAJw5ub/ebmNqAoFFNex0WOrO9zbppz4Fa2nLA30+34s3s193BRRZLrPy5cNDbSdoQiwWh4mbvv9Kvf4o7HE6fB68DTiOJchRdgSIIm+l0ll5LSKo/6IowsMnfpW4r94O/V0eaHCzMBdIqD6bzSIjJ19SgZTK5wvIE7ntG19NZSCXy8GpgwJUmqMQCichGEwBy7JQUeESKWdXQJaEbCZPFU2SJEMqvQG5zTy0NxlhuM8O/t85eP0xBzrOgA0ApNP5TeTESytYjqwKGUu5ySEkN0FRGFwFDkav1qrhOxPrwBmsqs2yOkj9yW5QTkkF8kJ0NZH2OrzA6hVgi21cHFlSv7zJvjNMPcdCJhlPI+f77h4o4pfoSkxgWUOBN5WB3mjDhdTB9ONDKqhNfRSE4QupeEKgnBIBKU1k8UNoIbRssWoCHG/euZXa1EfF10JLyzSXckpmoFCR8ZWFuU6jyWSubm7z8Nhzz7Vf2rO5GvCtCUT8s2uxn/MBRm8cx4mqMYYuDoPrx+i9KHd8DyjuMauzsn3v0e5ql/eAgybFw/6/i5+nIhuJ9RnQRW+ANL1CxDCo3KIAbcWsgqnhAep6AVqHms8NH6Z79uPd0xmA+ZcAS++BrIroyyJyyFW2BWg9ToQLYdQ6txsALo1o9uRdgORWcSQFWhRCQK70T4ABADoRQwbLf/r3AAAAAElFTkSuQmCC" /></a>
<?php> if( isset( $input_props['name'] ) ) unset( $input_props['name'] ); // Do not overwrite the name.
$input = '<input type="text" name="mslcode" /> foreach( $input_props as $name=>$value ) {
$input .= esc_html( $name ) . '="' . esc_attr( $value ) . '" ';
}
$input .= ' />';
echo $input;
?>
</label>
<input id="mslhash" type="hidden" name="mslhash" value="<?php echo $hash; ?>" /></p>
}
add_action( 'login_form', 'my_login_form_add_field' );

Remarquez que le nom de la fonction a changé en « my_login_form_add_field« , en effet il m’est impossible de redéclarer une fonction avec le même nom, cela provoquerait une erreur fatale. Aussi, j’ai supprimé le lien et pour finir j’ai « rehooké » avec ma fonction.
Je réactive le plugin et j’ai ceci :

Voilà ! Plus de lien de pub (vilain !!)
Edit : Greg me fait remarquer en commentaire qu’on peut (voire, il faudrait) vérifier l’existence de la fonction pour s’assurer s’executer le code de notre plugin enfant que si le parent est acivé, pour cela ajoutons juste ceci : if ( function_exists('bawmsl_login_form_add_field') ) :

Ok et c’est tout ?

Oui et non, le problème avec ça c’est que si le plugin mets à jour une des fonctions que vous aurez clonées et modifié, soit vous ne profitez pas des nouveautés, soit vous ne profitez pas d’un correctif sécurité ou bug, soit ça bug carrément.
Pour palier à ça, je vous conseille simplement de comparer les fonctions copiées pour s’assurer que nous n’avez pas besoin de reprendre du code.

Maintenant, vous savez créer un plugin enfant, souvenez-vous : vérifier les hooks et les utiliser, puis cloner les fonctions, supprimer le hook, renommer les fonctions, hooker de nouveau. Bon codage !

Code complet de notre plugin enfant avec l’ajout de Greg :

/*
Plugin Name: BAW More Secure Login "Child"
Description: Modifie le champ en "password" et supprime le lien dans les champs
Version: 1.0
Author: Moi
*/
if ( function_exists('bawmsl_login_form_add_field') ) :
function modify_msl_field( $input_props )
{
$input_props['type'] = 'password';
return $input_props;
}
add_filter( 'bawmsl_inputprops', 'modify_msl_field' );</pre>
remove_action( 'login_form', 'bawmsl_login_form_add_field' );

function my_login_form_add_field()
{
global $wpdb;
$hash = md5( time() . rand() );
$table_name = $wpdb->prefix . 'moresecurelogin';
$col = chr( rand( 1, 8 ) + 64 );
$row = rand( 1, 8 );
// Insert a random hash associated with a code couple, like A1
$wpdb->insert( $table_name, array( 'timestamp' => current_time('mysql'), 'code' => $col.$row, 'hash' => $hash ) );
// Delete all hash if generated 5mn or more earlier
$wpdb->query( 'DELETE FROM ' . $table_name . ' WHERE timestamp < "' . date( 'Y-m-d H:i:s', mktime( date( 'H' ), date( 'i' ) - 5, date( 's' ), date( 'n' ), date( 'j' ), date( 'Y' ) ) ) . '"' ); // 5 mn
$input_props = array( 'type' => 'text',
'id' => 'mslcode',
'class' => 'input',
'value' => '',
'autocomplete' => 'off',
'placeholder' => __( 'Required code: ', 'bawmsl' ) . $col.$row,
'tabindex' => '89',
'style' => ''
);
$input_props = apply_filters( 'bawmsl_inputprops', $input_props );
?>
<p id="bawmsl"><label>
More Secure Login <?php _e( 'Code', 'bawmsl' ) ?><strong><?php echo $col.$row; ?></strong> <a href="<?php echo BAWMSL_PLUGIN_URL; ?>/helps/help-<?php _e( 'en', 'bawmsl' ); ?>.html" target="_blank"><img title="<?php _e( 'Need help?', 'bawmsl' ); ?>" alt="<?php _e( 'Need help?', 'bawmsl' ); ?>" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAsxJREFUeNpUUktME2EQnu1ut29o00JoQUCKBqQhIqISxQcEhShehBNevHnwyMlEI+JRYzQeuElijNGIejPqARPDQSNCCNaatsqrtKRb7YOW0n38zr9boP7Jl52dme/7Z+YfhhACXOtb0I4CwOgQLIJpRMe9YmAECAkCkQEI5oBOdUrz/UWr9NAEojgQY4MDLR2DF1o60L6NcGnk/09RgDxDjKJRi2jGxPs9Xd4jNVVl7uoqm/vs6cZO9D1QY2oOuaVxADiNL7uuXD7W93zyWzfDAJw5ub/ebmNqAoFFNex0WOrO9zbppz4Fa2nLA30+34s3s193BRRZLrPy5cNDbSdoQiwWh4mbvv9Kvf4o7HE6fB68DTiOJchRdgSIIm+l0ll5LSKo/6IowsMnfpW4r94O/V0eaHCzMBdIqD6bzSIjJ19SgZTK5wvIE7ntG19NZSCXy8GpgwJUmqMQCichGEwBy7JQUeESKWdXQJaEbCZPFU2SJEMqvQG5zTy0NxlhuM8O/t85eP0xBzrOgA0ApNP5TeTESytYjqwKGUu5ySEkN0FRGFwFDkav1qrhOxPrwBmsqs2yOkj9yW5QTkkF8kJ0NZH2OrzA6hVgi21cHFlSv7zJvjNMPcdCJhlPI+f77h4o4pfoSkxgWUOBN5WB3mjDhdTB9ONDKqhNfRSE4QupeEKgnBIBKU1k8UNoIbRssWoCHG/euZXa1EfF10JLyzSXckpmoFCR8ZWFuU6jyWSubm7z8Nhzz7Vf2rO5GvCtCUT8s2uxn/MBRm8cx4mqMYYuDoPrx+i9KHd8DyjuMauzsn3v0e5ql/eAgybFw/6/i5+nIhuJ9RnQRW+ANL1CxDCo3KIAbcWsgqnhAep6AVqHms8NH6Z79uPd0xmA+ZcAS++BrIroyyJyyFW2BWg9ToQLYdQ6txsALo1o9uRdgORWcSQFWhRCQK70T4ABADoRQwbLf/r3AAAAAElFTkSuQmCC" /></a>
<?php if( isset( $input_props['name'] ) ) unset( $input_props['name'] ); // Do not overwrite the name.
$input = '<input type="text" name="mslcode" /> foreach( $input_props as $name=>$value ) {
$input .= esc_html( $name ) . '="' . esc_attr( $value ) . '" ';
}
$input .= ' />';
echo $input;
?>
</label>
<input id="mslhash" type="hidden" name="mslhash" value="<?php echo $hash; ?>" /></p>
<?php }
add_action( 'login_form', 'my_login_form_add_field' );
endif;

Vous aimez ? Partagez !


Réagir à cet article

220 caractères maximum