Personnaliser l’admin bar

class CustomizeAdminBar {

	public static function hooks() {
		add_action( 'wp_before_admin_bar_render', array( __CLASS__, 'customize_admin_bar' ) );
	}

	public static function customize_admin_bar() {
		global $wp_admin_bar;
		global $current_user;

		//Suppression de l'entrée principale de l'admin bar pour les utilisateurs "Subscriber":
		if ( in_array( 'subscriber', $current_user->roles ) ) {
			$wp_admin_bar->remove_menu( 'site-name' );
		}

		//Ajout d'un élément à l'admin bar (lien vers une page "My account") :
		$wp_admin_bar->add_menu( array(
			'id' => 'user-page-my-account',
			'parent' => false,
			'title' => 'My account',
			'href' => get_option( 'siteurl' ) . '/my-account/',
		) );

	}

}

CustomizeAdminBar::hooks();

 

https://codex.wordpress.org/Plugin_API/Action_Reference/wp_before_admin_bar_render

$wp_admin_bar->remove_menu() : Pour trouver l’id de l’entrée du menu à supprimer (ici ‘site-name’), regarder l’attribut id de l’élément dans la source HTML.

Création d’un widget avec upload d’image utilisant la boite de dialogue média de WordPress

Déclaration d’une sidebar

register_sidebar( array('name'=>'My sidebar name', 'id' => "my_sidebar_id" ) );

Déclaration du widget

add_action('widgets_init', 'my_widget_init');
function my_widget_init() {
    register_widget("My_Widget"); //My_Widget is the class defined hereunder, extending WP_Widget 
}

Insertion dans le template

<?php if( dynamic_sidebar('my_sidebar_id') ): ?>
    <!-- Display something after the sidebar widgets contents -->
<?php else : ?>
    <!-- Display something if the sidebar is not defined -->
<?php endif; ?>

Le Widget

Note : javascript et styles sont inclus directement dans le template html ici, la bonne pratique serait de les déplacer dans des fichiers séparés inclus par wp_enqueue_script() / wp_enqueue_style().

<?php

//Enqueue WordPress media JS to handle image upload dialog box
add_action('admin_enqueue_scripts', 'my_widget_scripts');
function my_widget_scripts() {
    global $pagenow;
    if( $pagenow == 'widgets.php' ){
        wp_enqueue_media();
    }
}

//Create a class extending WP_Widget
class My_Widget extends WP_Widget {

    /**
     * Register widget with WordPress.
     */
    public function __construct() {
        parent::__construct(
            'my_widget', // Base ID
            'My widget', // Name
            array( 'description' => __( 'My widget description' ) ) // Args
        );
    }

    /**
     * Widget Front-end display
     */
    public function widget( $args, $instance ) {
        
        $img = $instance['img'];
        $url = $instance['url'];
        $title = $instance['title'];
       
        if( !empty($img) ){
            ?>
                <a href="<?php echo $url ?>" title="<?php echo $title ?>">
                    <div class="my-widget-img" style="background-image: url('<?php echo $img ?>');"></div>
                </a>
            <?php
        }
    }

    /**
     * Sanitize widget form values as they are saved.
     */
    public function update( $new_instance, $old_instance ) {
        $instance = array();

        $instance['img'] = strip_tags( $new_instance['img'] );
        $instance['url'] = strip_tags( $new_instance['url'] );
        $instance['title'] = strip_tags( $new_instance['title'] );

        return $instance;
    }

    /**
     * Back-end widget form.
     */
    public function form( $instance ) {
        
        $img = isset( $instance[ 'img' ] ) ? $instance[ 'img' ] : '';
        $url = isset( $instance[ 'url' ] ) ? $instance[ 'url' ] : '';
        $title = isset( $instance[ 'title' ] ) ? $instance[ 'title' ] : '';
        
        $img_field_id = $this->get_field_id('img');
        
        ?>
        
        <p>
            <label for="<?php echo $img_field_id ?>">Image :</label><br/>
            <input class="upload_image" id="<?php echo $img_field_id ?>" type="hidden" name="<?php echo $this->get_field_name('img') ?>" value="<?php echo $img ?>" />
            <input class="upload_image_button" id="<?php echo $img_field_id ?>_button" type="button" value="Charger une image" data-field-id="<?php echo $img_field_id ?>" />
            <div id="<?php echo $img_field_id ?>_img" class="upload_image_wrapper">
                <?php if( !empty($img) ):?>
                    <img src="<?php echo $img ?>" />
                    <a href="#" class="upload_image_delete" data-field-id="<?php echo $img_field_id ?>">Supprimer l'image</a>
                <?php endif ?>
            </div>
        </p>
        
        <p>
            <label for="<?php echo $this->get_field_id('url') ?>">URL du lien :</label>
            <input class="widefat" id="<?php echo $this->get_field_id('url') ?>" name="<?php echo $this->get_field_name('url') ?>" type="text" value="<?php echo esc_attr($url) ?>" />
        </p>
        
        <p>
            <label for="<?php echo $this->get_field_id('title') ?>">Message au survol de l'image :</label>
            <input class="widefat" id="<?php echo $this->get_field_id('title') ?>" name="<?php echo $this->get_field_name('title') ?>" type="text" value="<?php echo esc_attr($title) ?>" />
        </p>
        
        <style>
            .upload_image_wrapper img{ width:100% }
        </style>
        
        <script>
                //Le code suivant doit normalement être positionné dans un fichier Javascript séparé,
                //notamment dans le cas où on positionne plusieurs fois le widget dans l'interface, 
                //sinon le "jQuery(document).ready()" ci-dessous est lancé autant de fois que le nombre  
                //de widgets positionnés. Ca fonctionne car on fait des "unbind()" mais 
                //ce n'est pas optimisé.

                var upload_image_custom_uploaders = upload_image_custom_uploaders || {};
            
                jQuery(document).ready(function($){
 
                        $('.upload_image_button').unbind().click(function(e) {
 
                                e.preventDefault();
 
                                var field_id = $(this).data('field-id');
                    
                                //If the uploader object has already been created, reopen the dialog
                                if( upload_image_custom_uploaders.hasOwnProperty( field_id ) ) {
                                        upload_image_custom_uploaders[field_id].open();
                                        return;
                                }
              
                                //Extend the wp.media object
                                var upload_image_custom_uploader = wp.media.frames.file_frame = wp.media({
                                        title: 'Choisir une image',
                                        button: {
                                            text: 'Choisir cette image'
                                        },
                                        multiple: false
                                });
                    
                                upload_image_custom_uploaders[field_id] = upload_image_custom_uploader;
              
                                //When a file is selected, grab the URL and set it as the text field's value
                                upload_image_custom_uploader.on('select', function() {
                                        attachment = upload_image_custom_uploader.state().get('selection').first().toJSON();
                                        $('#'+ field_id).val(attachment.url);
                                        $('#'+ field_id +'_img').html('<img src="'+ attachment.url +'" />');
                                });
              
                                //Open the uploader dialog
                                upload_image_custom_uploader.open();
              
                        });
 
                        $('.upload_image_delete').unbind().click(function(e){
                                e.preventDefault();
                                var field_id = $(this).data('field-id');
                                $('#'+ field_id).val('');
                                $('#'+ field_id +'_img').html('');
                        });
              
                });
        </script>
        
        <?php
    }

}

Externalisation du javascript

Dans le cas où l’on souhaite positionner le script dans un fichier séparé, il faut utiliser l’event delegation de jQuery puisque le HTML est rechargé dynamiquement.
Pour cela, remplacer :

$('.upload_image_button').unbind().click(function(e) {

par :

$('#wpbody,#customize-controls').on( 'click', '.upload_image_button', function(e) {

et :

$('.upload_image_delete').unbind().click(function(e){

par :

$('#wpbody,#customize-controls').on( 'click', '.upload_image_delete', function(e){

Doc

http://codex.wordpress.org/Widgets_API
http://www.webmaster-source.com/2013/02/06/using-the-wordpress-3-5-media-uploader-in-your-plugin-or-theme/

Création d’un shortcode

<?php

class my_shortcode{

	public static function hooks(){
		add_shortcode('shortcode_name', array(__CLASS__,'shortcode_handler'));
	}
	
	public static function shortcode_handler( $atts, $content = '' ) {
		global $post;
		
		$html = '';
		
		extract( shortcode_atts( array(
			'arg1' => 'default value 1',
			'arg2' => '',
		), $atts ) );
		
		$content = trim($content);
		
		$html = "Something". $content ."something else.";
				
		return $html;
	}
	
}

my_shortcode::hooks();

Ajout d’un panel Back Office avec enregistrement d’options

<?php

class my_panel{

	const option_id = 'my_panel_option_id';
	
	public static function hooks(){
		
		if ( is_admin() ){
			add_action('admin_menu', array(__CLASS__,'add_settings_panels'));
		}
		
	}
	
	public static function add_settings_panels(){
		
		add_menu_page(
        		__('Mes options'), 
        		__('Mes options'), 
        		'manage_options', 
        		'my_settings_panel', 
       			array(__CLASS__,'settings_panel')
        	);
	
	}
	
	public static function settings_panel(){
		$result = self::handle_posted_settings();
		$options = self::get_options();
		?>
		<div class="wrap">
		
			<h1>Mes options</h1>
			
			<?php if ( !empty( $result['message'] ) ): ?>
				<div class="<?php echo $result['type'] ?>" ><p><?php echo $result['message'] ?></p></div>
			<?php endif ?>

			<form method="post" action="<?php echo add_query_arg(array()) ?>">
				<table class="form-table">
				    <tr valign="top">
				        <th scope="row">Setting 1</th>
				        <td><input type="text" name="setting_1" value="<?php echo $options['setting_1'] ?>" /></td>
				    </tr>
				    <tr valign="top">
				        <th scope="row">Setting 2</th>
				        <td><input type="text" name="setting_2" value="<?php echo $options['setting_2'] ?>" /></td>
				    </tr>
				</table>
				
				<?php wp_nonce_field('my_panel_save_settings') ?>
				
				<input type="submit" class="button button-primary" value="Enregistrer" />
				
			</form>
			
		</div>
		<?php 
	}
	
	
	protected static function handle_posted_settings(){

		$result = array(
			'message' => '',
			'type' => 'updated'
		);

		if( isset($_POST['setting_1']) && check_admin_referer('my_panel_save_settings') ){
			$options = self::get_options();

			if( !empty($_POST['setting_1']) ){
				$options['setting_1'] = $_POST['setting_1']; //format/sanitize posted data!
			}
			
			if( !empty($_POST['setting_2']) ){
				$options['setting_2'] = $_POST['setting_2']; //format/sanitize posted data!
			}
			
			self::save_options($options);

			$result['message'] = "Options enregistrées";
		}

		return $result;
	}
	
	protected static function save_options($options){
		if ( get_option( self::option_id ) !== false ) {
			update_option( self::option_id, $options );
		} else {
			add_option( self::option_id, $options, '', 'no' );
		}
	}
	
	public static function get_options(){
		$options = get_option( self::option_id );
		$options = wp_parse_args(
			$options,
			array(
				'setting_1'=>'Default for setting 1',
				'setting_2'=>'Default for setting 2'
			)
		);
		return $options;
	}
	
}

my_panel::hooks();

Création d’un panel Back Office

class my_module_with_bo_panel{
	
	public static function hooks(){
		if ( is_admin() ){
			add_action('admin_menu',array(__CLASS__,'add_settings_panels'));
		}
	}

	public static function add_settings_panels(){
		
		add_menu_page(
			__('Params'), 
			__('Params'), 
			'manage_options', 
			'my_settings_panel', 
			array(__CLASS__,'settings_panel')
		);

		add_submenu_page(
			'my_settings_panel',
			__('Params 1'), 
			__('Params 1'),
			'manage_options',
			'my_settings_panel',
			array(__CLASS__,'settings_panel_1')
		); 

		add_submenu_page(
			'my_settings_panel',
			__('Params 2'), 
			__('Params 2'),
			'manage_options',
			'my_settings_panel_2',
			array(__CLASS__,'settings_panel_2')
		); 
	}

	public static function settings_panel(){
	}
	
	public static function settings_panel_1(){
		?>
		<div class="wrap">
			<h2>Params 1</h2>
			<form method="post" action="<?php echo add_query_arg(array()) ?>"> 
				<?php //... ?>
				<?php submit_button() ?>
			</form>
		</div>
		<?php
	}

	public static function settings_panel_2(){
		?>
		<div class="wrap">
			<h2>Params 2</h2>
			<?php //... ?>
		</div>
		<?php 
	}
}

my_module_with_bo_panel::hooks();

Ajout d’une métabox, avec sauvegarde des méta-données

class produits{

	public static function hooks(){
		add_action('add_meta_boxes',  array(__CLASS__, 'add_meta_boxes'));
		add_action('save_post',  array(__CLASS__, 'save_post'));
	}

	public static function add_meta_boxes(){

		add_meta_box('produit_metabox_id',
			'Fournisseur',
			array(__CLASS__, 'meta_box_content'),
			'post', //any post_type
			'normal',
			'high'
		);

	}

	public static function meta_box_content($post,$current_metabox){
		?>
		<!-- Contenu de la métabox (formulaire...) -->	
		<input type="text" name="ma_donnee" value="" />
		<?php
		wp_nonce_field('produit_meta_box_action','produit_meta_box_nonce_field');
	}

	public static function save_post($post_id) {
	
		// verify this came from the our screen and with proper authorization,
		// because save_post can be triggered at other times
		
		if ( !isset($_POST['produit_meta_box_nonce_field']) 
		     || !wp_verify_nonce( $_POST['produit_meta_box_nonce_field'], 'produit_meta_box_action') 
		){
			return $post_id;
		}
		
		// verify if this is an auto save routine. If it is our form has not been submitted, so we dont want
		// to do anything
		if ( defined('DOING_AUTOSAVE') && DOING_AUTOSAVE ){
			return $post_id;
		}
		
		// Check permissions and post type
		if ( !isset($_POST['post_type']) 
		     || $_POST['post_type'] != 'le-post-type' 
		     || !current_user_can('edit_post', $post_id)
		){
			return $post_id;
		}
	
		// Handle the case where we are dealing with a revision
		if( $parent_post_id = wp_is_post_revision($post_id) ){
			$post_id = $parent_post_id;
		}
		
		// OK, we're authenticated: we need to find and save the data
	
		if( isset($_POST['ma_donnee']) ){
			add_post_meta($post_id,'_ma_meta',$_POST['ma_donnee'],true) 
			or update_post_meta($post_id, '_ma_meta', $_POST['ma_donnee']);
		}
			
	}

}

produits::hooks();

http://codex.wordpress.org/Function_Reference/add_meta_box
http://codex.wordpress.org/Plugin_API/Action_Reference/save_post

Ajout d’une métabox

class metabox_test{

	public static function hooks(){
		if( is_admin() ){
			add_action('add_meta_boxes',  array(__CLASS__, 'add_meta_boxes'));
		}
	}

	public static function add_meta_boxes(){

		add_meta_box('produit_metabox_id',
			'Titre',
			array(__CLASS__, 'meta_box_content'),
			'post', //any post_type
			'normal',
			'high'
		);

	}

	public static function meta_box_content($post,$current_metabox){
		?>
		<!-- Contenu de la métabox (formulaire...) -->	
		<?php
	}

}

metabox_test::hooks();

http://codex.wordpress.org/Function_Reference/add_meta_box