10

I am writing a plugin to send an invitation to a friend which opens up a form when a link is clicked. I encapsulated all the functions in class by following the code given in the Report Broken Video plugin by @toscho. The relevant code is below:

/*
Plugin Name: Send Invitation
Plugin URI: http://w3boutique.net
Description: Emails a the link of the current page to a friend
Author: Nandakumar Chandrasekhar
Version: 0.1
Author URI: http://w3boutique.net/about-nanda.html
License: GPL2
*/

// include() or require() any necessary files here

// Settings and/or Configuration Details go here
define('SEND_INVITATION_MIN_WORDPRESS_VERSION', '3.1.1');

define('SEND_INVITATION_PLUGIN_URL', plugins_url('', __FILE__));

add_action( 'init', array( 'SendInvitation', 'nc_sendinvitation_init' ) );

class SendInvitation {

    protected $nonce_name = 'nc_sendinvitation';
    protected $post_url = '';

    public static function nc_sendinvitation_init() {
        new self;
    }

    public function __construct() {
        add_action( 'init', array(&$this, 'nc_sendinvitation_head' ));
        add_action( 'init', array(&$this,  'nc_sendinvitation_check_wordpress_version' ));
       add_action( 'init', array(&$this, 'nc_sendinvitation_form_action' ));
       //$this->post_url = $this->nc_sendinvitation_get_post_url();
   }

   public function nc_sendinvitation_head() {
       wp_enqueue_script( 'jquery' );
       wp_enqueue_script( 'send_invitation_js',
        plugins_url( 'js/send-invitation.js', __FILE__ ),
        array( 'jquery' ) );

       wp_enqueue_style( 'send_invitation_css',
        plugins_url( 'css/send-invitation.css', __FILE__ ) );
   }

   public function nc_sendinvitation_check_wordpress_version() {
       global $wp_version;

       $exit_msg = 'Send Invitation requires version '
    . SEND_INVITATION_MIN_WORDPRESS_VERSION
    . 'or newer <a href="http://codex.wordpress.org/Upgrading_WordPress">Please
update!</a>';

       if ( version_compare( $wp_version, SEND_INVITATION_MIN_WORDPRESS_VERSION, '<') )
       {
            exit( $exit_msg );
       }
   }

   public function nc_sendinvitation_form_action() {

        $action = '';
        if ( $_SERVER['REQUEST_METHOD'] != 'POST' )
        {
             $action = $this->nc_sendinvitation_get_form();
        }
        else if ( $_SERVER['REQUEST_METHOD'] == 'POST' ) {
            $action = $this->nc_sendinvitation_handle_submit();
        }
        return $action;
   }

   public function nc_sendinvitation_get_form() {
       // Start the output buffer, prevents content being output directly into
       // script, instead it is stored in a buffer which can then be flushed
       // to allow the include file to be stored in a variable
       // See http://www.codingforums.com/showthread.php?t=124537
       ob_start();
       include('send-invitation-form.php');
       $send_invitation_link = ob_get_clean();

       return $send_invitation_link;
   }

   public function nc_sendinvitation_handle_submit() {
         if ( isset( $_POST['form_type'] ) && ( $_POST['form_type'] == 'nc_sendinvitation' ) ) {
            $to = '[email protected]';
            $subject = 'Invitation to SwanLotus';
            $message = 'Navanitachora invites you to take a look at this link';
            wp_mail($to, $subject, $message);
            $result = 'Email was sent successfully';
    }
    else {
        $result = $this->nc_sendinvitation_get_form();
    }
    return $result;
}

public function nc_sendinvitation_get_post_url() {
    global $post;
    $blog_id = get_option('page_for_posts');
    $post_id = '';
    if (is_home($blog_id)) {
        $post_id = $blog_id;
    } else {
        $post_id = $post->ID;
    }

    return get_permalink($post_id);
}
}
/* End of File */
?>

I am at a loss as to how to use this class in my template so that I can display the form. I know that I need to instantiate the class but I am not sure where to put the code and how to access the object so that I can use it in my template. I have knowledge of OOP but have not used it in this context before and require a little bit of step by step instruction.

Many Thanks.

1 Answer 1

9

The best way to use your class without knowing the object is an action. You register the action before the theme files for presentation are loaded, WordPress will handle the rest.

Sample code:

<?php # -*- coding: utf-8 -*-
/**
 * Plugin Name: Plugin Action Demo
 */
add_action( 'init', array ( 'Plugin_Action_Demo', 'init' ) );

class Plugin_Action_Demo
{
    /**
     * Creates a new instance.
     *
     * @wp-hook init
     * @see    __construct()
     * @return void
     */
    public static function init()
    {
        new self;
    }

    /**
     * Register the action. May do more magic things.
     */
    public function __construct()
    {
        add_action( 'plugin_action_demo', array ( $this, 'print_foo' ), 10, 1 );
    }

    /**
     * Prints 'foo' multiple $times.
     *
     * Usage:
     *    <code>do_action( 'plugin_action_demo', 50 );</code>
     *
     * @wp-hook plugin_action_demo
     * @param int $times
     * @return void
     */
    public function print_foo( $times = 1 )
    {
        print str_repeat( ' foo ', (int) $times );
    }
}

Now you can call do_action( 'plugin_action_demo', 50 ); somewhere in your theme or in another plugin, and you don't have to care about the inner workings of the class anymore.

If you deactivate the plugin you are still safe: WordPress just ignores unknown actions and the do_action() will do no harm. Plus, other plugins are able to remove or replace the action, so you have build a nice mini API with one add_action().

You could also build a singleton:

<?php # -*- coding: utf-8 -*-
/**
 * Plugin Name: Plugin Singleton Demo
 */
class Plugin_Singleton_Demo
{
    protected static $instance = NULL;

    /**
     * Creates a new instance if there isn't one.
     *
     * @wp-hook init
     * @return object
     */
    public static function get_instance()
    {

        NULL === self::$instance and self::$instance = new self;
        return self::$instance;
    }

    /**
     * Not accessible from the outside.
     */
    protected function __construct() {}

    /**
     * Prints 'foo' multiple $times.
     *
     * @param int $times
     * @return void
     */
    public function print_foo( $times = 1 )
    {
        echo str_repeat( ' foo ', (int) $times );
    }
}

Now print_foo() is accessible per:

Plugin_Singleton_Demo::get_instance()->print_foo();

I don’t recommend the Singleton pattern. It has some serious drawbacks.

14
  • 1
    Out of curiosity, what is the purpose of plugin_action_demo in add_action()? How does do_action( 'print_foo', 50 ); know that the action is plugin_action_demo or is that name irrelevant?
    – Jared
    Commented Mar 7, 2012 at 8:05
  • Ok, was a bit confused. :) Thanks for clearing that up.
    – Jared
    Commented Mar 7, 2012 at 8:26
  • For the record: declare() requires php 5.3+ :)
    – kaiser
    Commented Mar 7, 2012 at 9:23
  • Thanks that works just have to add some validation and I should be done. Thanks @toscho you have taught me a lot. :-)
    – nandac
    Commented Mar 8, 2012 at 7:12
  • @tosco Found your answer looking for articles about singletons for WordPress plugins. You do realize you are using a Singleton in your recommended answer, you are just not enforcing it? Imagine a themer calls new Plugin_Action_Demo?? Anyone using do_action('plugin_action_demo') would trigger two (2) calls to Plugin_Action_Demo->print_foo(), not what you want. The furor over singletons ignores there are appropriate use-cases. As an FYI both @ericmann and I are blogging now to advocate singletons for WordPress plugin namespacing, he at eamann.com and me at hardcorewp.com. Commented Jan 9, 2013 at 14:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.