Events Manager Custom Event Attributes and Conditionals

The Events Manager plugin for WordPress can be used to build a fantastic event and calendaring system, with countless features and expandability, but there are times that the built in event attributes just aren’t enough. Thankfully the plugin is very developer friendly and allows users to create custom event attributes directly in the dashboard. However, what if you need to display a custom event attribute if it’s used, and not display it if it’s not used? That’s where event attribute conditional placeholders come in, however if you’re wanting to use a conditional placeholder with custom event attributes you’ll have to create it yourself. That’s what we’ll cover in this article.

Creating Custom Event Attributes

First in order to use a custom conditional placeholder you’ll need to have custom event attributes, so let’s create those first. To do this simply login to your WordPress dashboard and go to Events > Settings > General (tab) > General Options and scroll down until you find the radio input for “Enable event attributes?” and be sure that is set to “Yes”. Next you will need to scroll down to the “Event Attributes” text area and add your own custom event attributes. Note that in order for the custom conditional placeholder to function properly the custom event attribute should have no spaces, such as “#_ATT{this_is_my_custom_event_attribute}”. Also note that the custom event attribute is strictly case sensitive so be sure the exact same name is used throughout. For the sake of this article I will be creating a custom event attribute called test, so it will be added using the code below.

Once you’ve finished adding your custom event attributes be sure to save changes.

Creating Custom Conditional Placeholders

Next, we’ll add the necessary code to process our custom conditional placeholders. To do this we’ll implement the use of a filter hook that is called by the Events Manager plugin. Note that the code for the conditional placeholders will be added to your theme’s functions.php file. Thankfully the code for creating custom conditional placeholder is fairly simple, so I’ll show the code that I’ve used for the “test” custom event attribute and then explain how it works, and what you need to change.

It’s as simple as that! Once the above code has been added to the functions.php file the “#_ATT{test}” custom event attribute and “{has_test}” custom conditional placeholder are ready to be used.

Explaining the above code, we’re making use of the “em_event_output_condition” filter that is called by the Events Manager plugin each time it encounters a conditional placeholder that doesn’t match one of the built-in conditional placeholders.

Here is a description of the passed attributes:

  • $replacement (string) will almost always be empty
  • $condition (string) will be the custom conditional placeholder name (such as, “has_test”)
  • $match (string) will contain the text from the beginning of the custom conditional placeholder to the end (such as, “{has_test} #_ATT{test} {/has_test}”)
  • $EM_Event (event object) will be the event object of the current event being viewed

Essentially what the above code does is check for the existence of our custom conditional placeholder, then checks to see if the custom event attribute exists and if it has a non-empty value. If those conditions are met, then the content within the custom conditional placeholder, inside $match, is returned. If those conditions are not met then an empty string is returned.

Due to the simplicity of this filter, in order to modify the above code to work with your custom conditional placeholders simply change the word “test” on lines 2 and 3 to be the name of your custom event attribute, such as “my_custom_event_attribute”.

There you have it! You’ve now created a custom event attribute and a corresponding custom conditional placeholder. You may be wondering, “what if I need to create multiple custom conditional placeholders?”, or “where do I use the custom conditional placeholder?”, and I’ll cover both of those questions in the final section.

Wrapping Everything Up

In the case that you’re needing to create multiple custom conditional placeholders you simply duplicate a portion of the filter code above.

This is the code that actually does the processing, and duplicating it (and placing it above or below the existing code) and then replacing the custom event attribute with your additional custom event attribute is all you need to do. The reason that this works is because the Events Manager will call this filter *each* time it encounters a conditional placeholder that doesn’t match the built-in conditional placeholders. Note that your duplicated code MUST come before the line noted below.

Lastly, in order for the custom event attribute and custom conditional placeholder to have any effect we need to add it to the front-end. The most common, and simple, way to do this is to login to your WordPress dashboard and then go to Events > Settings > Formatting (tab) > Events and scroll down to the  “Default single event format” text area. This is where you can add your custom event attribute and custom conditional placeholder code where ever you’d like it to display on the single event page.

What About no_attribute Conditionals

Update – September 26, 2014: As a follow up to  Koen’s question in the comments I’ve also added a snippet below that will allow you to use a conditional placeholder in the case that a custom attribute is not used.

This can simply be used in addition to your other conditions (has_attribute or no_attribute) within the “em_event_output_condition_filter” filter function.

Nesting Conditionals

Update – October 23, 2014: If you plan to nest conditionals within other conditionals (whether they’re custom or built-in) you will first need to enable this functionality. By default the Events Manager plugin will only look for the first level of conditionals, and unfortunately there is no option for enabling conditional recurrence within the Events Manager Settings within the dashboard. Instead you will need to add some additional code to your functions.php theme file. Once the below code has been added you will need to go to the Events Manager Settings and click save (no changes necessary) to fire the “em_options_save” action. I used this action since this is technically updating an Events Manager option and it prevents the update_option method from being called each page load.

 

The Events Manager plugin checks for the dbem_conditional_recursions option upon instantiation. If this option is set it will use its value, and if not then it will use the default value of one. So, the above code sets the option value to two thus overriding the default.  This will allow for one conditional to be nested within another, however you will need to adjust the above code if you plan nest conditionals at an even deeper level. Keep in mind high levels of recursion can negatively impact performance.

In Conclusion

Overall, the process of adding a custom event attribute and custom conditional placeholder is relatively simple and provides nearly infinite customizability to the Events Manager plugin. I hope this has been an easy to follow and informative guide on how to create custom event attributes. Be sure to post comments and let me know if you’ve ran into any problems or have any questions.

Join the Conversation

49 Comments

    1. Hi Koen, thanks for the comment. I’m glad you found the post helpful. Also, that’s a great question, so I’ve added an additional code snippet to the end of this post.

  1. Hi, thanks for the snippet.

    I’m trying to implement in events list, but doesn’t work.

    I created an attribute ‘test’ and paste your snippet in my functions.php, but doesn’t work like I expect.

    need I make any changes to work in the list?

    thanks in advance

    1. Hi, again.

      I found a mistake in preg_replace condition.

      this
      $replacement = preg_replace(“/{/?$condition}/”, ”, $match);
      for this one
      $replacement = preg_replace(“/\{\/?$condition\}/”, ”, $match);

      And now it works like a charm.

      Again, thanks for the snippet

      1. Hi Juanjo,

        You’re welcome for the snippet, and I’m glad you were able to get it working.

        In my testing I didn’t have problems with the original regular expression, however escaping the brackets and forward slash shouldn’t ever cause a problem. So, I’ve updated the code in the snippet examples.

        Thanks for following up and letting me know what you did to get it working.

  2. So I tried this method and it seems to be the closest I can get to conditionals without doing serious coding. But I can’t get it to work. You think you could explain what I’m doing wrong?

    I specifically copied the code into the functions.php file. Didn’t change anything and added an #_ATT{test} and added the conditional {has_test} to the event formatting but it doesn’t show. Specifically removing the conditional from the formatting causes the attribute to show so it clearly isn’t the attribute itself but the code above. What could be going wrong?

    To note, I’m using a child theme, will that affect the functions.php?

    Also, thanks for making this post. The dev’s tutorials and documentation are quite hard to wrap my mind around and this post laid it out much more clearly. Big thanks!

    1. Follow up:

      I tried using the code in my child theme’s functions.php and it had no effect. Then I tried using the code in the parent theme (twentytwelve)’s functions.php and it white-screened the wordpress admin, implying it broke something. So is there a bug in the code somewhere that I’m not seeing?

      1. Hi Justin,

        Adding the code to your child theme vs the parent twentytwelve theme should make no difference since both functions.php files are loaded. However, if you didn’t remove the method from your child theme functions.php before adding it to the parent theme then that would explain the white screen as it’s likely hit a PHP “cannot redeclare function” error.

        I suggest only adding it to the child theme.

        The first thing that comes to mind that would cause the {has_test} … {/has_test} conditional to display nothing is that the attribute simply has no value (edit your event and add something to the “test” field, below the main editor).

        1. AHH! Found it. It was a plugin conflict. Probably when I was trying to solve this the code got mashed up somewhere. Its fixed now. Should have tried this from the start by turning off all the plugins but I didn’t think of it.

          Now I’m going to use this to make several custom attributes. Will report back if all goes well. Thanks again!

          1. Great! I’m glad you got it figured out, and I hope all goes well with the additional custom attributes.

      2. Another possible cause may be that you’ve placed the {has_test}… {/has_test} conditional within another conditional such as {has_location}. I’m doing some testing to see why this doesn’t work and if it can be fixed.

        1. So conditionals work beautifully but now I want to nest them like you suspected. What I’m trying to do is have the list of a work title that’s being performed and then a link to it on our store with another attribute. I tried by enclosing the anchor tags in the next level but it didn’t process and just ignores the anchor. I suspect the bit at the end of this article is to blame: http://wp-events-plugin.com/documentation/conditional-placeholders/

          I tried their suggestion but it isn’t working.

          Here’s my code:

          {has_work}
          Title:
          {has_work_link}

          {/has_work_link}
          #_ATT{work}
          {has_work_link}

          {/has_work_link}

          {/has_work}
          {has_composer}
          Composer:
          {has_composer_link}

          {/has_composer_link}
          #_ATT{composer}
          {has_composer_link}

          {/has_composer_link}

          {/has_composer}
          ...etc....

          1. Their method of allowing nested conditionals should work just fine, however as the guide says it must be added to the wp-config.php file (likely in your WordPress root folder) rather than the theme functions.php file. Alternatively you can try the method that I’ve added to this guide (near the bottom). Other than that I’m not sure what’s to blame as your code looks good to me.

        2. After doing some further testing I’ve found that nesting conditionals within each other is certainly possible, however by default this behavior is not enabled in the Events Manager plugin. Also, it cannot be enabled within the Events Manager settings, but rather must be manually set in the wp_options table. I’ve updated the guide to make note of this.

  3. Sorry I don’t think it posted right…

  4. Thank you laubsterboy! This was the only place I could find the right instructions on how to use nested conditions. I’ve followed the official tutorial but were unable to do it. Not even using the official forum.

    Thank you

  5. Thank you very much, laubsterboy, for posting this! The original documents did not do me any good, but your article began to shed the light.

    I got a custom “test” attribute working, but my initial goal is to create {has_eventnotes} and {no_eventnotes} conditionals.

    How can I add a conditional to an existing placeholder? How can I find out what the placeholder is called?

    Suggestions? – Thanks!

    1. You’re quite welcome, Dan! I’ve been away from home and didn’t have the chance to answer your question until now, but I believe the code below is what you’re looking for. The EM_Event object contains ‘post_content’ and ‘notes’ properties, which have the same value. You can check either to see if eventnotes have been added.

      Note that the above code is checking for a {has_notes} … {/has_notes} conditional.

      1. Thank you!!

        Got the {has_notes} working.

        Having problems with the {no_notes} though…

        My functions.php code:
        function em_event_output_condition_filter($replacement, $condition, $match, $EM_Event){
        // Checks for has_notes conditional
        if(is_object($EM_Event) && preg_match(‘/^has_(notes)$/’, $condition, $matches)){
        if(isset($EM_Event->$matches[1]) && !empty($EM_Event->$matches[1])){
        $replacement = preg_replace(“/\{\/?$condition\}/”, ”, $match);
        }else{
        $replacement = ”;
        }
        }
        // Checks for no_notes conditional
        if(is_object($EM_Event) && preg_match(‘/^no_(notes)$/’, $condition, $matches)){
        if( !array_key_exists($matches[1], $EM_Event->event_attributes) ){
        $replacement = preg_replace(“/\{\/?$condition\}/”, ”, $match);
        }else{
        $replacement = ”;
        }
        }
        return $replacement;
        }
        add_filter(’em_event_output_condition’, ’em_event_output_condition_filter’, 1, 4);

        1. Hi, Dan. Glad to hear that the has_notes conditional is working. The notes field is a little tricky because it’s handled differently than all of the examples in this article, since it’s technically not an event attribute, but rather a property of the event object itself.

          I’ve updated the code snippet that you provided, and it should do what you’re wanting.

          In the first conditional we’re just checking if the $EM_Event object has a “notes” property AND that it’s not empty. For the no_notes conditional all we need to do is reverse the empty check, and instead check to see if the “notes” property is empty.

          1. I’m afraid that your solution does not work either.

            I added “function” to the beginning, but there is a deeper problem…

            No notes will display at all when your snippet is in place.

            I really appreciate your help! EM’s support (free that is) leaves much to be desired and they just let my thread get buried without responding… trying to get this snippet working before I release a client project.

        2. Hi, Dan. I apologize for the syntax error. I wasn’t able to test the code before posting it, but I’ve edited the post to make a few corrections. First I added “function” to the beginning. Second, I added an exclamation mark before isset (for the no_notes conditional) since the EM_Event doesn’t have a “notes” property if the event notes is left empty. Lastly, I changed the && logical operator to || so that if “notes” is either empty or not set then the no_notes conditional will be called.

          That said, I’ve had the chance to test the code and it does indeed work. I’ve included an example of how it can be used below.

          I’ve also replied to your EM WordPress support post, just incase others see it and are having the same problem.

  6. For those struggling with nested conditionals, I was unable to get their code snippet to work until I placed it above all other code in wp_config.php (under the <?php of course).

  7. I just can’t get this to work.

    Functions:


    function em_event_output_condition_filter($replacement, $condition, $match, $EM_Event){
    // Checks for has_test conditional
    if(is_object($EM_Event) && preg_match('/^has_(test)$/', $condition, $matches)){
    if(array_key_exists($matches[1], $EM_Event->event_attributes) && !empty($EM_Event->event_attributes[$matches[1]]) ){
    $replacement = preg_replace("/\{\/?$condition\}/", '', $match);
    }else{
    $replacement = '';
    }
    }

    return $replacement;
    }
    add_filter('em_event_output_condition', 'em_event_output_condition_filter', 1, 4);

    Code in template:


    {has_more_information}#_ATT{more_information}{/has_more_information}

    What am I missing?

    1. Hi Nick.

      It looks like you have everything setup properly, except for changing the conditional if statement to match your conditional attribute name (more_information). The line that has /^has_(test)$/ needs to be /^has_(more_information)$/, such as the code below:

  8. ah, rookie mistake. I thought it was a global function, I can just add a bunch of if’s for all the custom attributes then.

    Thanks

    1. You’re correct, for each custom attribute you’ll need to create a matching conditional block.

      As for ACF repeater fields, there’s no reason you can’t. I’ve used ACF to add custom fields to Events so that I could add visual editor input boxes and created conditionals like the one below to be used in the Events Manager > Settings > Pages:

      It works quite well, actually.

  9. Yeah I tried it with various fields, and when I have to add a multiple, for say multi-select or a repeater field, it just chucks out the array value. The tutorials on the Events Manager site just confused the hell out of me. 🙂

    1. Odd that it’s throwing out the array value. I’ll have to play around with a repeater field sometime and see what’s going on.

      I was confused by their tutorials as well, which is why I wrote this post in the first place. Judging by the amount of comments and traffic I get on this post I don’t think we’re the only ones.

  10. Nope, the plugin developer assumes far too much.

    Was talking about writing custom styles for attributes. Which I honestly don’t see the point of, seen as nearly every developer I know styles externally.

  11. Hi again,

    Just wanted to comment that for the number of nested conditionals is updated, after incorporating the code at funtions.php, you must enter the Event Manager Settings, and save, although no changes made.

    regards

  12. Wow… after an hour or two of troubleshooting I finally figured out that my PHP code must match my #_ATT{Custom Attribute} exactly. It IS case sensitive.

    I know next to nothing about PHP, but my #_ATT{Contact} would not work until my {has_Contact} and {no_Contact} conditionals matched with a capital “C”.

    1. I’m glad to hear your troubleshooting efforts weren’t completely in vain, though I’m sure frustrating. This is my one complaint with how the custom attributes are created. There’s no way to specify the “title” (what shows up in the WordPress event editor page) and a “slug” (or “variable name” that is used in the backend PHP) for each attribute. The name specified in the Events > Settings is how the attribute must be referenced in the PHP code, exactly. I’ll update the blog post for clarification. Thanks for the comment, and good to hear from you again, Dan.

  13. How can we do {has_test_x} and {no_test_x} conditionals?

    In other words, if the #ATT{test} has an entry of “coffee” then the conditional {has_test_coffee} is activated.

    1. Hi Dan,

      I apologize for the delayed response. My subscription notifications were going into my email spam folder. I should have whitelisted my domain a long time ago. Anyway I haven’t fully tested this but the below code should do what you’re wanting.

      What this is doing is allowing you to create your own {has_test_x}, {has_test_y}, {has_test_z} on the fly without having to create another PHP conditional block statement. It checks to see if #_ATT{test} has an entry matching the end part of the conditional (what ever comes after “has_test_”). The same goes for {no_test_x}. Keep in mind that the way this is setup right now the entry must be “coffee”, as “Coffee” will not work for the {has_test_coffee} conditional.

      The above solution is more dynamic, but not quite as flexible. Another way to handle this would be to create a custom conditional block statement for each {has_test_x} that you need. This would allow you to do things like checking to see if #_ATT{test} has an entry of “Medium roast coffee” to activate the {has_text_med_coffee} conditional. The obvious benefit here is that your conditional doesn’t have to exactly match the custom attribute value.

      Give it a try and let me know if it does what you need.

      1. It all works great! Thank you again!

        I wanted to use this to add a #_ATT{test}{Option1|Option2|Option3} to my events. That way if I had Option2 selected, the conditional would be triggered. Thank you!

  14. Hi and thanks so much for posting this! I wonder if you would help me understand how to handle a space character in the Attribute string? I have an attribute with a space (#ATT_{Exhibit Title}). but when I add the condition {has_Exhibit Title}#ATT_{Exhibit Title}{/has_Exhibit Title} the opening shortcode gets echoed back to the screen: {has_Exhibit Title}My Title{/has_Exhibit Title}
    I’m using:
    if(is_object($EM_Event) && preg_match(‘/^has_(Exhibit Title)$/’, $condition, $matches)){
    if(isset($EM_Event->$matches[1]) && !empty($EM_Event->$matches[1])){
    $replacement = preg_replace(“/\{\/?$condition\}/”, ”, $match);
    }else{
    $replacement = ”;
    }
    }
    I’ve tried has_(Exhibit)\s(Title) but that didn’t work…

    1. Hi Chris,

      There is no problem with having a space (or uppercase letters) in a custom attribute name. The problem is that the custom conditional ({has_Exhibit Title}) does not allow for spaces, but rather only uppercase/lowercase letters, numbers, underscores, and hyphens. This is hard-coded into the Events Manager plugin regular expression so there is no avoiding it. So to work around this you can just do something like this instead:

      Attribute: #_ATT{Exhibit Title}
      Conditional: {has_exhibit_title} #_ATT{Exhibit Title} {/has_exhibit_title}

      However, without changing your conditional code in your functions.php file this will not work, yet. Since the attribute name and conditional name differ you just need to hard-code the names, like below.

      There you can see on line 3 I changed the regular expression from /^has_(Exhibition Title)$/ to /^has_(exhibit_title)$/. Then on line 4 (where we need to do the hard coding) I changed from using $matches[1] to the hard-coded attribute title of ‘Exhibit Title’. We need to do this because $matches[1] refers to the second capture within our regular expression from above (exhibit_title), which doesn’t match the attribute name “Exhibit Title” (see http://php.net/manual/en/function.preg-match.php).

      Note that the code you posted (if(isset($EM_Event->$matches[1]) && !empty($EM_Event->$matches[1])){) won’t work because it’s not referencing the $EM_Event->event_attributes array.

      I hope that helps!

      -John

  15. Hi,
    First of all, thanks for the effort and sharing you’re knowledge.
    I’m trying to make my conditional placeholders work inside my Events List Grouped Template, but I don’t know what I’m doing wrong.
    I’ve just followed your instructions, but I can’t make it work. Do you know what am I doing wrong?
    Here’s my template code

    <?php
    /*
    * Default Events List Template
    * This page displays a list of events, called during the em_content() if this is an events list page.
    * You can override the default display settings pages by copying this file to yourthemefolder/plugins/events-manager/templates/ and modifying it however you need.
    * You can display events however you wish, there are a few variables made available to you:
    *
    * $args – the args passed onto EM_Events::output()
    *
    */

    $args = apply_filters('em_content_events_args', $args);

    em_locate_template('templates/events-search.php',true);

    $args['scope'] = $_REQUEST['scope'][0];

    if( get_option('dbem_css_evlist') ) echo "”;

    echo EM_Events::output_grouped( array(‘scope’=>’future’,’category’=>’travessies’,’mode’=>’monthly’, ‘limit’=>100,
    ‘format_header’=>’

    ‘,
    ‘format’=>’
    {is_future}

    #_{d}
    #_{M}

    #_EVENTIMAGE{90,90}

    #_EVENTLINK#_LATT{nom_organitzador}
    #_LOCATIONNAME, #_LOCATIONTOWN #_LOCATIONSTATE
    {has_distancia_1}#_ATT{distancia_1}{/has_distancia_1}

    {/is_future}

    {is_past}

    #_{d}
    #_{M}

    #_EVENTIMAGE{200,90}

    #_EVENTLINK
    #_LOCATIONNAME, #_LOCATIONTOWN #_LOCATIONSTATE

    {/is_past}
    ‘,

    ‘format_footer’=>’

    )); //note we’re grabbing the content, not em_get_events_list_grouped function
    //echo ”;
    if( get_option(‘dbem_css_evlist’) ) echo “”;
    ?>

    1. Hi Robert,

      The only thing I’m seeing at first glance is that you some of your conditionals are nested (has_distancia_1 inside is_future), so have you setup your site for nested conditionals (explained near the end of the article)? Otherwise, I’m not seeing anything that stands out as problematic or incorrect. I haven’t had a chance to test your code to see if there are any problems with it. Are you getting any error messages? Are the placeholders outputting anything or just disappearing or are they still displayed on the event page?

      //laubsterboy

  16. Hi

    Now is possible to ad custom attributes in settings/formatting/single event page format, but I need to style front-end input form and add some custom text (fill in instruction) for each custom attributes (only visible in event input form but not visible in published event?
    Do you know where any hove i can do this?

    Thx, BR
    MM

  17. This is a great solution to a problem, but not quite my problem!
    I need to get the value of the custom attribute into a php variable so that within an [events_list]… [/event_list] where I insert a PHP block in the middle I can make decisions based on variable.
    All the methods I have tried so far have failed. For example:
    $raceno = do_shortcode(‘#_ATT{Race}’);
    But this produces a variable which when echoed provides the value but when compared it has the value #_ATT{Race}
    Is it possible to get the custom attribute value into PHP variable?

  18. Hi,

    Thanks for you great work, I’m no PHP genius but can follow what you have created – fantastic.

    I’m looking for something like this but with a slight (or many complicated – as I said, no PHP expert) twist. I’ve been reading the thread but cannot seem to find the same condition.

    I have an attribute lets call it Example and it has two possible values Value1 and Value2 so in my Event Manager code I have #_ATT{Example}{Value1|Value2}.

    Your excellent code can check to see if the attribute is blank or if it contains content then give a response accordingly.

    What I would like to do is to see if the attribute has Value1 or Value2 and provide different output accordingly.

    Is this relatively easy to achieve? Could you sho me how?

    Thanks you so much.

    David Watson

    1. Hi, David. Sorry for the long delay, but I think this would do what you’re needing.

      You’ll need to make a few minor edits to the code to match the name of your custom attribute and also the output values for 1 and 2, but that should do what you’re wanting.

  19. Hello,
    Thank you for this. One thing I couldn’t get the no_ conditional to work. I finally did by editing the code: In order to see the key exists OR it’s empty. Did I misunderstand the intention of the code? What i was trying to do was so if the Custom Field was empty as a conditional.

    // Checks for no_frequency conditional
    if(is_object($EM_Event) && preg_match(‘/^no_(test)$/’, $condition, $matches)){
    if( !array_key_exists($matches[1], $EM_Event->event_attributes) || empty($EM_Event->event_attributes[$matches[1]]) ){
    $replacement = preg_replace(“/\{\/?$condition\}/”, ”, $match);
    }else{
    $replacement = ”;
    }
    }

    1. Hi, Daveed. I would have to look back at the specific projects I needed the no_conditional code for to see if that was the intention or not. I was doing some stuff with dynamic attributes so it could have been that some events didn’t even have an attribute key that others may have had, but adding empty would have the same result and work in your situation too. In fact you should be able to remove the array_key_exists check altogether and replace it with the empty check.

      That said based on what I wrote in the blog post it seems the empty() check is necessary, so good catch! Thanks! I’ve updated the post to include checking if it’s empty as well.

Leave a comment

Your email address will not be published. Required fields are marked *

You can also subscribe without commenting.