Modifying the Events Manager for WordPress widget to filter events by category

Events widget with Category ID optionI just recently discovered the Events Manager plugin for WordPress and implemented it into a client’s website along with the Events widget that comes with the plugin.  The client liked the plugin and the widget, but wondered if the Events widget could be filtered by category to be able to display the events for a particular category on a page related to that category.

After reading through the documentation and posting a question on the plugin’s forum at WordPress.org, this is the solution I came up with.

The easy way: just modify the widget php file

I actually did this the slightly more difficult way to begin with, but looking back now I guess there’s no reason to not modify the widget and make the desired change all in one move. What makes this simpler than it may sound is that the developer has built the plugin for future modifications such as this one, which you can start reading about on this page on the Events Manager website.

The PHP file that creates the Events widget is em-events.php, and is found in the directory wp-content/plugins/events-manager/widgets.  Once you’ve located that file using your FTP client (I use Filezilla), download it to your desktop and open it with your favorite text editor (I prefer Notepad++).

(Caveat: I’m not a coder, but I like to think that I’m working in that direction, and this exercise is one small step forward.)

Once you’ve got the file open and ready to edit, add the following commented line somewhere around line 14:

Add ‘category’ to the widget’s function

'scope' => 'future',
'category' => 0, // this adds 'category' to the widget's function
'order' => 'ASC',

Next, add the following commented paragraph at approximately line 80:

Add the category option to the widget’s form

<p>
<label for="<?php echo $this->get_field_id('title'); ?>"><?php _e('Title'); ?>: </label>
<input type="text" id="<?php echo $this->get_field_id('title'); ?>" name="<?php echo $this->get_field_name('title'); ?>" value="<?php echo $instance['title']; ?>" />
</p>
<p><!-- this adds the category option to the widget's form -->
<label for="<?php echo $this->get_field_id('category'); ?>"><?php _e('Category ID','dbem'); ?>: </label>
<input type="text" id="<?php echo $this->get_field_id('category'); ?>" name="<?php echo $this->get_field_name('category'); ?>" size="3" value="<?php echo $instance['category']; ?>" /><br />
<label for="<?php echo $this->get_field_id('category'); ?>"><?php _e('(separate multiple IDs by commas, or use "0" for all categories)','dbem'); ?> </label>
</p>
<p>
<label for="<?php echo $this->get_field_id('limit'); ?>"><?php _e('Number of events','dbem'); ?>: </label>
<input type="text" id="<?php echo $this->get_field_id('limit'); ?>" name="<?php echo $this->get_field_name('limit'); ?>" size="3" value="<?php echo $instance['limit']; ?>" />
</p>

Save the file, FTP it back to its directory on your server, go to your widgets screen in your WordPress admin, and you should now have the option to specify one or more categories to be displayed.  The default setting is “0″ (zero), which displays all categories, and to display multiple categories separate the IDs with commas.

To learn more about how this customization potential is built-in to the plugin, check out Event Search Attributes in the plugin’s documentation.

The slightly more difficult way: clone and modify the widget

That was the easy way.  To add a few more steps and have a separate widget for specifying categories, do the following:

  1. Make a copy of em-events.php and name it something like em-events-by-category.php
  2. In this new file find all instances of EM_Widget and replace them with something like EM_Widget_by_category
  3. Add the code in the two places as explained above in the previous section.
  4. Change the ‘title’, ‘description’, and name (see highlighted code below)
  5. FTP the file wp-content/plugins/events-manager/events-manager.php to your desktop and add the following at approximately line 58:

    Add to events-manager.php

    include_once("widgets/em-events-by-category.php");
  6. FTP the new widget file and the events-manager.php file back to their directories.
  7. Go to your widgets screen in WordPress and verify that you have a working plugin that filters events by category.

Here is the code for the modified em-events-by-category.php file, with all the changes and additions commented.

Code for the modified em-events-manager.php file. Changes in lines 4,7,12,14,16,25-26,81-85,165 – click through to this Gist on GitGub to see line numbers.

<?php
/**
* @author marcus
* modified by John Sundberg
* Standard events list widget
*/
 class EM_Widget_by_category extends WP_Widget {//changed
 
     var $defaults;
 
     /** constructor */
     function EM_Widget_by_category() {//changed
$this->defaults = <a href="http://www.php.net/array">array</a>(
             'title' => __('Events by Category','dbem'),//changed
'scope' => 'future',
             'category' => 0,// this adds 'category' to the widget's function
'order' => 'ASC',
             'limit' => 5,
             'format' => '#_LINKEDNAME<ul><li>#j #M #y</li><li>#_TOWN</li></ul>',
             'nolistwrap' => false,
             'orderby' => 'start_date,start_time,name',
             'all_events' => 0,
             'all_events_text' => __('all events', 'dbem')
         );
         $widget_ops = <a href="http://www.php.net/array">array</a>('description' => __( "Display a list of events on Events Manager by category.", 'dbem') ); //changed
parent::WP_Widget(false, $name = 'Events by Category', $widget_ops); //changed
}
 
     /** @see WP_Widget::widget */
     function widget($args, $instance) {
         $instance = <a href="http://www.php.net/array_merge">array_merge</a>($this->defaults, $instance);
         $instance = $this->fix_scope($instance); // depcreciate
         echo $args['before_widget'];
         echo $args['before_title'];
         echo $instance['title'];
         echo $args['after_title'];
         $instance['owner'] = false;
 
         $events = EM_Events::get($instance);
         echo "<ul>";
         $li_wrap = !<a href="http://www.php.net/preg_match">preg_match</a>('/^<li>/i', <a href="http://www.php.net/trim">trim</a>($instance['format']));
         if ( <a href="http://www.php.net/count">count</a>($events) > 0 ){
             foreach($events as $event){
                 if( $li_wrap ){
                     echo '<li>'. $event->output($instance['format']) .'</li>';
                 }else{
                     echo $event->output($instance['format']);
                 }
             }
         }else{
             echo '<li>'.__('No events', 'dbem').'</li>';
         }
         if ( !<a href="http://www.php.net/empty">empty</a>($instance['all_events']) ){
             $events_link = (!<a href="http://www.php.net/empty">empty</a>($instance['all_events_text'])) ? em_get_link($instance['all_events_text']) : em_get_link(__('all events','dbem'));
             echo '<li>'.$events_link.'</li>';
         }
         echo "</ul>";
 
         echo $args['after_widget'];
     }
 
     /** @see WP_Widget::update */
     function update($new_instance, $old_instance) {
         foreach($this->defaults as $key => $value){
             if( <a href="http://www.php.net/empty">empty</a>($new_instance[$key]) ){
                 $new_instance[$key] = $value;
             }
         }
         return $new_instance;
     }
 
     /** @see WP_Widget::form */
     function form($instance) {
         $instance = <a href="http://www.php.net/array_merge">array_merge</a>($this->defaults, $instance);
         $instance = $this->fix_scope($instance); // depcreciate
         ?>
<p>
<label for="<?php echo $this->get_field_id('title'); ?>"><?php _e('Title'); ?>: </label>
<input type="text" id="<?php echo $this->get_field_id('title'); ?>" name="<?php echo $this->get_field_name('title'); ?>" value="<?php echo $instance['title']; ?>" />
</p>
<p><!-- this adds the category option to the widget's form -->
<label for="<?php echo $this->get_field_id('category'); ?>"><?php _e('Category ID','dbem'); ?>: </label>
<input type="text" id="<?php echo $this->get_field_id('category'); ?>" name="<?php echo $this->get_field_name('category'); ?>" size="3" value="<?php echo $instance['category']; ?>" /><br />
<label for="<?php echo $this->get_field_id('category'); ?>"><?php _e('(separate multiple IDs by commas, or use "0" for all categories)','dbem'); ?> </label>
</p>
<p>
<label for="<?php echo $this->get_field_id('limit'); ?>"><?php _e('Number of events','dbem'); ?>: </label>
<input type="text" id="<?php echo $this->get_field_id('limit'); ?>" name="<?php echo $this->get_field_name('limit'); ?>" size="3" value="<?php echo $instance['limit']; ?>" />
</p>
<p>
<label for="<?php echo $this->get_field_id('scope'); ?>"><?php _e('Scope','dbem'); ?>: </label><br/>
<select id="<?php echo $this->get_field_id('scope'); ?>" name="<?php echo $this->get_field_name('scope'); ?>" >
<?php foreach( em_get_scopes() as $key => $value) : ?>
<option value='<?php echo $key ?>' <?php echo ($key == get_option('dbem_events_page_scope')) ? "selected='selected'" : ''; ?>>
<?php echo $value; ?>
</option>
<?php endforeach; ?>
</select>
</p>
<p>
<label for="<?php echo $this->get_field_id('order'); ?>"><?php _e('Order By','dbem'); ?>: </label>
<select id="<?php echo $this->get_field_id('orderby'); ?>" name="<?php echo $this->get_field_name('orderby'); ?>">
<?php
                     $orderby_options = apply_filters('em_widget_orderby_ddm', <a href="http://www.php.net/array">array</a>(
                         'start_date,start_time,name' => __('start date, start time, event name','dbem'),
                         'name,start_date,start_time' => __('name, start date, start time','dbem'),
                         'name,end_date,end_time' => __('name, end date, end time','dbem'),
                         'end_date,end_time,name' => __('end date, end time, event name','dbem'),
                     ));
                 ?>
<?php foreach($orderby_options as $key => $value) : ?>
<option value='<?php echo $key ?>' <?php echo ( !<a href="http://www.php.net/empty">empty</a>($instance['orderby']) && $key == $instance['orderby']) ? "selected='selected'" : ''; ?>>
<?php echo $value; ?>
</option>
<?php endforeach; ?>
</select>
</p>
<p>
<label for="<?php echo $this->get_field_id('order'); ?>"><?php _e('Order','dbem'); ?>: </label>
<select id="<?php echo $this->get_field_id('order'); ?>" name="<?php echo $this->get_field_name('order'); ?>">
<?php
                 $order_options = apply_filters('em_widget_order_ddm', <a href="http://www.php.net/array">array</a>(
                     'ASC' => __('Ascending','dbem'),
                     'DESC' => __('Descending','dbem')
                 ));
                 ?>
<?php foreach( $order_options as $key => $value) : ?>
<option value='<?php echo $key ?>' <?php echo ($key == $instance['order']) ? "selected='selected'" : ''; ?>>
<?php echo $value; ?>
</option>
<?php endforeach; ?>
</select>
</p>
<p>
<label for="<?php echo $this->get_field_id('format'); ?>"><?php _e('List item format','dbem'); ?>: </label>
<textarea rows="5" cols="24" id="<?php echo $this->get_field_id('format'); ?>" name="<?php echo $this->get_field_name('format'); ?>"><?php echo $instance['format']; ?></textarea>
</p>
<p>
<label for="<?php echo $this->get_field_id('all_events'); ?>"><?php _e('Show all events link at bottom?','dbem'); ?>: </label>
<input type="checkbox" id="<?php echo $this->get_field_id('all_events'); ?>" name="<?php echo $this->get_field_name('all_events'); ?>" <?php echo (!<a href="http://www.php.net/empty">empty</a>($instance['all_events']) && $instance['all_events']) ? 'checked':''; ?> >
</p>
<p>
<label for="<?php echo $this->get_field_id('all_events'); ?>"><?php _e('All events link text?','dbem'); ?>: </label>
<input type="text" id="<?php echo $this->get_field_id('all_events_text'); ?>" name="<?php echo $this->get_field_name('all_events_text'); ?>" value="<?php echo (!<a href="http://www.php.net/empty">empty</a>($instance['all_events_text'])) ? $instance['all_events_text']:__('all events','dbem'); ?>" >
</p>
<?php
     }
 
     /**
* Backwards compatability for an old setting which is now just another scope.
* @param unknown_type $instance
* @return string
*/
     function fix_scope($instance){
         if( !<a href="http://www.php.net/empty">empty</a>($instance['time_limit']) && <a href="http://www.php.net/is_numeric">is_numeric</a>($instance['time_limit']) && $instance['time_limit'] > 1 ){
             $instance['scope'] = $instance['time_limit'].'-months';
         }elseif( !<a href="http://www.php.net/empty">empty</a>($instance['time_limit']) && $instance['time_limit'] == 1){
             $instance['scope'] = 'month';
         }elseif( !<a href="http://www.php.net/empty">empty</a>($instance['time_limit']) && $instance['time_limit'] == 'no-limit'){
             $instance['scope'] = 'all';
         }
         return $instance;
     }
 }
 add_action('widgets_init', <a href="http://www.php.net/create_function">create_function</a>('', 'return register_widget("EM_Widget_by_category");'));//changed
?>

Tags:

About John Sundberg

John is the owner and chief blogger at Black Hills Web Works
  • http://netweblogic.com Marcus

    nice tutorial, one comment/suggestion…for the harder way (recommended over the first one), instead of modifying any part of EM directly, you can just copy that widget file into your own theme file, and include it there e.g. within your functions.php file, or pasting it directy into the functions.php file, because it’s then upgrade-safe.

    either that, or copy it into your mu-plugins folder and it’d get included regardless (but remember to delete if you delete EM)

    • http://www.blackhillswebworks.com John Sundberg

      Marcus, thanks for the tips. After I wrote this tutorial the developer incorporated the change into the plugin, rendering this post sort of obsolete. What you suggested is a better way to manage changes though, and lately I’ve been using similar methods for modifications.

  • http://netweblogic.com Marcus

    i am the developer :)

    • http://www.blackhillswebworks.com John Sundberg

      That comment made my morning! I’m still smiling…

      Thanks for your input – good to see a developer who stays involved!

    • http://www.blackhillswebworks.com John Sundberg

      That comment made my morning! I’m still smiling…

      Thanks for your input – good to see a developer who stays involved!