DevinVinson / WordPress-Plugin-Boilerplate

[WordPress] A foundation for WordPress Plugin Development that aims to provide a clear and consistent guide for building your plugins.
http://wppb.io
7.67k stars 2.25k forks source link

How to properly load widget class with text domain #274

Closed seamofreality closed 8 years ago

seamofreality commented 9 years ago

Hello,

I was wondering what's the best way to include widgets?

I tried to create a new instance in my define_admin_hooks function because I wanted to get the plugin name in there as well, since the name is being used as text domain for translations - but then the plugin isn't really registered. If I use the widgets_init action and register the plugin I don't have the text domain available in my widget class.

Maybe someone can help out with some ideas or actually knows the proper way. Thanks for your help :)

allysonsouza commented 9 years ago

Watching... Suffering with the same problem right now > <

bcrigler commented 8 years ago

I figured this out finally... It was annoying no doubt but definitely possible with this latest version using the loader (kind of). I figured I would share for others. I say "kind of" because really if following the Boilerplate Model the register_widget action should be passed through the loader but here I just define it in the construct of the public class.

In your _construct() of /includes/class-plugin-name.php call a new method named define_widget_hooks();

Like this:

    public function __construct() {

        $this->Plugin_Name = 'plugin-name';
        $this->version = '1.0.0';

        $this->load_dependencies();
        $this->set_locale();
        $this->define_admin_hooks();
        $this->define_public_hooks();
        $this->define_widget_hooks();

    }

Then in load_dependencies() let's load our widget class file (You should already have a widget class if not refer to the https://codex.wordpress.org/Widgets_API and just use the example class file to get started.

/**
  * The widget class
  **/
  require_once plugin_dir_path( dirname( __FILE__ ) ) . 'includes/class-widget-name-widget.php';

Next we will define define_widget_hooks().

    /**
     * Register all of the hooks related to the widget functionality
     * of the plugin.
     *
     * @since    1.0.0
     * @access   private
     */
    private function define_widget_hooks() {

        $plugin_widget = new Widget_Name( $this->get_Plugin_Name(), $this->get_version() );

    }

Now we need to go to our widget class and add two private properties to the class.

    /**
     * The ID of this plugin.
     *
     * @since    1.0.0
     * @access   private
     * @var      string    $Plugin_Name    The ID of this plugin.
     */
    private $Plugin_Name;

    /**
     * The version of this plugin.
     *
     * @since    1.0.0
     * @access   private
     * @var      string    $version    The current version of this plugin.
     */
    private $version;

Now directly under that add these two holder properties as the arguments of the _construct() method. Which really are coming from when we instantiated the widget class back in define_widget_hooks(). This is where we are passing the text_domain and the version to the widget class.

    /**
     * Register widget with WordPress.
     */
    function __construct( $Plugin_Name, $version ) {

        $this->Plugin_Name = $Plugin_Name;

        $this->version = $version;

        parent::__construct(
            $this->Plugin_Name . '_widget', // Base ID
            __( 'My Widget', $this->Plugin_Name ), // Name
            array( 'description' => __( 'Describe My Widget here', $this->Plugin_Name ), ) // Args
        );

    }

Finally, we will head over to our public class as this is generally where you would register the widget. /public/class-plugin-name-public.php and add the widgets_init action to it's construct:

    /**
     * Initialize the class and set its properties.
     *
     * @since    1.0.0
     * @param      string    $Plugin_Name       The name of the plugin.
     * @param      string    $version    The version of this plugin.
     */
    public function __construct( $Plugin_Name, $version ) {

        $this->Plugin_Name = $Plugin_Name;
        $this->version = $version;

        add_action( 'widgets_init', array( $this, 'register_widget_name' ) );

    }

Now just define that method register_widget_name like this:

    /**
     * Register the Widget Name Widget
     *
     * @since   1.0.0
     *
     **/
    public function register_widget_name() {

        register_widget('Widget_Name');

    }

Hope this helps you guys out. :smiley:

DevinVinson commented 8 years ago

The most recent update to the boilerplate actually gets rid of this :(

Text domains should only ever be strings and not variables. So the simple answer for this one is make your text domain whatever your text domain is and call it a day.

bcrigler commented 8 years ago

Actually, that code i just posted isn't quite it yet... I forked this repo going to add functionality to load multiple widgets and will post it in this thread when I'm done.

As far as your comment "Text Domains should only ever be strings and not variables"

Throughout the entire boilerplate you use _textdomain and version as a variable. Granted I would imagine it would be rare that a text_domain would change it bothers me enough that I feel like it needs a way to pass the variables as you have for Public / Admin classes. The more important piece then Text Domain though and what actually makes this worthwhile is the plugin version number. Should be able to change that globally without having to open multiple files to change a version. I would like to see an extension of WP_Widget_Factory personally that handles this in the boilerplate so I'm going to do it on my end through my fork.

In general though I love the boilerplate and have been using it throughout it's many iterations so thank you for this! :+1:

DevinVinson commented 8 years ago

Re text domain as string: https://github.com/DevinVinson/WordPress-Plugin-Boilerplate/issues/303

Otherwise dig in. I'm always happy to see iterations on the base classes for all the various cases of plugin needs.

bcrigler commented 8 years ago

Definitely noted and will correct any plugins I build using a pure string and actually we really don't need version number I think I am just sitting here overcomplicating this. Change all text domains to a string and the Widget class file doesn't even need a version number. Done and Done.