Events Manager conditional placeholders for custom attributes

The Events Manager plugin for WordPress is pretty flexible, allowing you to easily add custom attributes to your event posts. It also has conditional placeholders that allow you to display or hide information conditionally. There is a nice tutorial on the plugin website showing you how to add your own conditional placeholders. Lets bring this all together with a conditional placeholder for a custom attribute.

Let’s say we want to add an attribute called Website, with a link to a website promoting the event. We could add it to the list of attributes and then add the following snippet to our Single Event Page format in the Events Manager settings:

<p>
  <strong>Website</strong><br/>
  <a href="http://#_ATT{Website}" target="_blank">#_ATT{Website}</a>
</p>

The problem is that it will always show this on the event page, even when our Website attribute is empty. To hide that content when the attribute is empty, we need to add a conditional placeholder for it — let’s call it has_att_website (for “has attribute Website”). A simple regular expression will take care of removing our conditional placeholder without removing the content it surrounds, as you’ll see in the code below.

Conditional placeholders can actually do more than just hide or show content, they can change it. A very simple use of this is to take a chunk of text with line breaks in it, and convert those line breaks to BR tags using the handy nl2br() PHP function. So let’s add that to our placeholder code too!

Here’s the code, which can be added to a plugin or to a theme’s functions.php file.

[edit: {nl2br} is processed before placeholders, so I have changed it to call $EM_Event->output() on its contents to pick up placeholders too.]

/**
* add some conditional output conditions for Events Manager
* @param string $replacement
* @param string $condition
* @param string $match
* @param object $EM_Event
* @return string
*/
function filterEventOutputCondition($replacement, $condition, $match, $EM_Event){
    if (is_object($EM_Event)) {

        switch ($condition) {

            // replace LF with HTML line breaks
            case 'nl2br':
                // remove conditional
                $replacement = preg_replace('/\{\/?nl2br\}/', '', $match);
                // process any placeholders and replace LF
                $replacement = nl2br($EM_Event->output($replacement));
                break;

            // #_ATT{Website}
            case 'has_att_website':
                if (is_array($EM_Event->event_attributes) && !empty($EM_Event->event_attributes['Website']))
                    $replacement = preg_replace('/\{\/?has_att_website\}/', '', $match);
                else
                    $replacement = '';
                break;

        }

    }

    return $replacement;
}

add_filter('em_event_output_condition', 'filterEventOutputCondition', 10, 4);

Now, we can change our Single Event Page format to make use of the conditional placeholder.

{has_att_website}
<p>
  <strong>Website</strong><br/>
  <a href="http://#_ATT{Website}" target="_blank">#_ATT{Website}</a>
</p>
{/has_att_website}

<p><strong>Something with line breaks</strong>
{nl2br}
#_ATT{Something with line breaks}
{/nl2br}
</p>

There, job is done if and when we want it.

facebooktwittergoogle_plusredditpinterestlinkedinmailfacebooktwittergoogle_plusredditpinterestlinkedinmail
  • http://www.kingjason.co.uk Jason King

    That worked nicely. The Event Manager plugin doesn’t come with a way to say that an event’s date has not yet been announced. But my client still wanted to advertise the course on their website and start signing people up.

    First I set up an attribute called TBA (to be announced).

    Then set up two new functions:
    1) has_att_tba (so I can display a message)
    2) has_no_att_tba (so I can hide the date)

    Here’s the code I used to display a message in lists and single events:

    {has_att_tba}
    #_ATT{TBA}
    {/has_att_tba}
    {has_no_att_tba}
    #j #M #Y #@_{ — j M Y}
    {/has_no_att_tba}

    • http://snippets.webaware.com.au/ rmckay

      Excellent, well done. Events Manager doesn’t cater for all occasions right out of the box, but it certainly is flexible enough. I’ve been fighting with a few other plugins that don’t let you hook into them the way Events Manager does, and it makes a real difference.

  • http://www.cucocreative.co.uk Tony

    Thanks for the post, your instruction is far clearer then the official documentation. But I just can’t get it to work.

    I have this in the functions.php:

    function filterEventOutputCondition($replacement, $condition, $match, $EM_Event){
    if (is_object($EM_Event)) {
    switch ($condition) {
    // #_ATT{Premium}
    case 'has_att_premium':
    if (is_array($EM_Event->event_attributes) && !empty($EM_Event->event_attributes['Premium']))
    $replacement = preg_replace('/{/?has_att_premium}/', '', $match);
    else
    $replacement = '';
    break;
    }
    }
    return $replacement;
    }
    add_filter('em_event_output_condition', 'filterEventOutputCondition', 10, 4);

    And I have this within the ‘Default event list format’:

    #_ATT{Premium}
    {has_att_premium}
    #_ATT{Premium}
    More
    {/has_att_premium}

    NB: the ‘hideMe’ class will be set to display:none; as I don’t want the new attibute display, it’s only purpose is to show/side the #_EVENTURL.

    The attribute does display when set, but the conditional statement doesn’t show when the attribute is set.

    Any thoughts?

    • http://snippets.webaware.com.au/ rmckay

      G’day Tony,

      I can’t spot a problem, looking at your code. When you say “the conditional statement doesn’t show”, what do you actually get in your output? Can you be sure that your function is actually being called?

      e.g. for a quick test, change the last line to “return ‘filterEventOutputCondition’;” and it should write that function name all over the event if the function is being called.

      Also, if you turn on debugging (edit your wp-config.php file and change WP_DEBUG to true), does it give you any errors? NB: you might find that experience somewhat frightening, some plugins throw lots of warnings and errors!

  • http://www.cucocreative.co.uk Tony

    The second block of code should read as:

    http://pastebin.com/hzZi5d77

  • http://www.cucocreative.co.uk Tony

    Thanks for getting back to me.

    I mean that where it should output the code within the conditional statement if it were true and being called there is nothing being shown within the front end source code. So it may not actually be being called. It displays the attribute that I have included outside of the conditional statement (to test that the attribute is being set).

    Do you mean replace:
    return $replacement;
    with:
    return “filterEventOutputCondition”;
    If so nothing happens.

    I an new to EM so I might have missed an obvious setting somewhere?

    Regards debug.

    In backend I get:

    Notice: load_plugin_textdomain was called with an argument that is deprecated since version 2.7 with no alternative available. in ………../wp-includes/functions.php on line 3553

    Notice: has_cap was called with an argument that is deprecated since version 2.0! Usage of user levels by plugins and themes is deprecated. Use roles and capabilities instead. in ………../wp-includes/functions.php on line 3551

    In frontend I only get:

    Notice: load_plugin_textdomain was called with an argument that is deprecated since version 2.7 with no alternative available. in ……./wp-includes/functions.php on line 3553

    • http://snippets.webaware.com.au/ rmckay

      G’day Tony, the debug messages just mean that a plugin or theme you’re using is using old parameters when calling some WP functions; nothing to worry about there.

      Now, I suspect you might be putting this code in the wrong file. I copied your code exactly, and pasted it into the bottom of the functions.php file in my active theme — i.e.

      /wp-content/themes/my-theme/functions.php

      and it worked as advertised. What file are you putting this code into?

      Also, have you ticked yes on Enable event attributes? in the General Options?

  • http://www.cucocreative.co.uk Tony

    Thanks for getting back to me.

    It’s going at the bottom of my my themes function.php file:
    http://pastebin.com/2FncBeiM

    Might it conflict with something else?

    And yes ‘Enable event attributes’ is checked. The new attribute is being set as I have included the attribute outside of the conditional statement to check that it is being set.

    It would be so much easier if you could include php code within the Setting>Layout>Formatting for the plug in.

    • http://snippets.webaware.com.au/ rmckay

      Did you mean functions.php or did you actually put it into function.php?

  • http://www.cucocreative.co.uk Tony

    I meant functions.php.

    I have just added it to the Twenty Eleven functions.php file and it it working so it is something on my theme. I will see if I can figure that one out….

    • http://www.cucocreative.co.uk Tony

      Doh!

      I think it was down to a missing ‘;’ in a previous function. All working now, thanks for the input, helped me look at the problem from a different angle.

      • http://snippets.webaware.com.au/ rmckay

        Well done, nice to hear it was a happy ending :)

        cheers,
        Ross

  • Dan

    Hi there,

    I was just wondering if there is a way to use multiple attributes as in: has_att_this or has_att_that. I have a few different prices which work great using conditional placeholders individually but I also want to be able to get rid of all prices when the venue is closed some weeks.

    Any ideas?

    • http://snippets.webaware.com.au/ Ross McKay

      G’day Dan, you can create a conditional placeholder that tests for any condition, be it a simple one-attribute test or more complex multi-attribute logic. So if you want to test whether either one or another attribute has a value, you can make one placeholder that does both tests. But for the example you mention, you probably just need a placeholder that tests that the venue is not closed, and wrap that around the prices.

      cheers,
      Ross

  • Sam Blowes

    Im using the NL2BR function like so:
    {nl2br}#_EVENTEXCERPT{/nl2br}

    And im echoing the result to check it:

    case 'nl2br':
    $replacement = nl2br(preg_replace('/{/?nl2br}/', '', $match));
    echo $replacement;
    break;

    And it reurns: #_EVENTEXCERPT

    What am I doing wrong?

    • http://snippets.webaware.com.au/ Ross McKay

      G’day Sam,

      The problem was that conditional placeholders are processed before “regular” placeholders, so #_EVENTEXCERPT wasn’t being replaced until after the {nl2br} replacement. I’ve changed the code above to process the contents of {nl2br} before calling nl2br(), so please update your code.

      cheers,
      Ross

  • Kelly Andrews

    This code saved my life – dropped it in, edited a bit, good to go. Thanks!

    • http://snippets.webaware.com.au/ Ross McKay

      No worries, glad it helped :)

  • http://azchipka.thechipkahouse.com Avery Z Chipka

    When I use the listed code it results in a error of

    “Parse error: syntax error, unexpected ‘{‘ in /home/crew505/public_html/dev/wp-content/themes/Venturing Crew 505/functions.php on line 11″

    line 11 includes the following code:
    if (is_object($EM_Event)) {

    Code is currently being placed in a child theme functions.php file.

    Please help

    • http://azchipka.thechipkahouse.com Avery Z Chipka

      Issue resolved

      • http://snippets.webaware.com.au/ Ross McKay

        I’m glad you resolved your issue; sorry I wasn’t around to help (it was sleepy bye time here in Australia!)

        cheers,
        Ross

  • http://www.kidonthetown.com Brittney

    Hello,
    Thank you for this helpful code and explanation. I added an attribute ‘higlights’ and this code to the function:
    ———–
    case 'has_att_highlights':
    if (is_array($EM_Event->event_attributes) && !empty($EM_Event->event_attributes['highlights']))
    $replacement = preg_replace('/{/?has_att_highlights}/', '', $match);

    else
    $replacement = '';
    break;

    ——-
    In the page this works beautifully:

    #_ATT{highlights}
    {has_att_highlights}We'll be at: #_ATT{highlights}{/has_att_highlights}

    but this does not:

    {has_att_highlights}We'll be at: #_ATT{highlights}{/has_att_highlights}

    does the #_ATT{highlights} need to be initialized in some way before calling the function? It is inside a [events_list recurring="1" orderby="event_name"] loop.

    Thank you so much!

    • http://snippets.webaware.com.au/ Ross McKay

      G’day Brittney,

      You need to separate the conditional statements from the attribute, due to some issue with the way Events Manager handles those two things. This works with your code above:

      {has_att_highlights}
      We'll be at: #_ATT{highlights}
      {/has_att_highlights}

      cheers,
      Ross

  • http://www.kidonthetown.com Brittney

    Thank you! That worked. Thought I was going crazy because it was working at some point. Your code is a great help, I appreciate it.

  • http://www.kidonthetown.com Brittney

    One more question, how can I create a conditional for a custom attribute for that event’s location? For example, my locations have a custom attribute ‘tips’, would I use something like this to check if this event’s location has ‘tips’:

    if (is_array($EM_Event->location->attributes) && !empty($EM_Event->location->attributes['tips']))
    or
    if (is_array($EM_Event->location_attributes) && !empty($EM_Event->location_attributes['tips']))

    Thanks!
    Brittney

    • http://snippets.webaware.com.au/ Ross McKay

      G’day Brittney,

      Assuming that you’re still talking about the single event (and its location), you can create a location attribute (#_LATT{}) and this code will pick up the non-empty ones one a single event:


      case 'has_latt_loctest':
      if (isset($EM_Event->location) && !empty($EM_Event->location->location_attributes['loctest']))
      $replacement = preg_replace('/{/?has_latt_loctest}/', '', $match);
      else
      $replacement = '';
      break;

      NB: if you mean a single location view, you’ll need to use a different filter hook: em_location_output_condition is the equivalent.

      cheers,
      Ross

      • http://3x5.co 3×5

        Hello, I assume this also means all instances of

        $EM_Event->event_attributes

        Need to change to

        $EM_Event->location->location_attributes

        Is this correct? I want to modify the code in this article to apply to locations, not events. Thanks.

        • http://snippets.webaware.com.au/ Ross McKay

          Yes, if you’re accessing location attributes from the em_event_output_condition hook. If you’re using the em_location_output_condition hook, you’ll get an EM_Location object instead of an EM_Event object.

          cheers,
          Ross

  • http://www.kidonthetown.com Brittney

    works perfectly! thanks again.
    Brittney

  • http://www.wordpresschef.it Dimitri

    Hi!
    I’ve an attribute like this:

    #_ATT{Link vendita ticket online}

    and your function seems not working..

    Do you have any hints for me?

    Thank you

    Dimitri Grassi

    • http://snippets.webaware.com.au/ Ross McKay

      G’day Dimitri,

      In the code above, you should be replacing ‘has_att_website’ with something like ‘has_link_vendita_ticket_online’ or similar — with no spaces — which you’d then use like this:

      {has_link_vendita_ticket_online}
      <p>
      <strong>Website</strong><br/>
      <a href="http://#_ATT{Link vendita ticket online}" target="_blank" rel="nofollow">#_ATT{Link vendita ticket online}</a>
      </p>
      {/has_link_vendita_ticket_online}

      cheers,
      Ross

  • AJD

    Hello! Thanks for this great tutorial on conditional placeholders for Events Manager.
    I tried to use your version to check when a custom ATT is empty instead of when it is filled in, but for some reason it didn’t work. It kept displaying the ‘{no_message}’ markup.

    Here is what is working:


    function my_em_has_attribute_event_output_condition($replacement, $condition, $match, $EM_Event){
    if( is_object($EM_Event) && preg_match('/^no_message$/', $condition,$matches) ){
    if( !in_array($args['feat_message'],$EM_Event->event_attributes)
    && empty($EM_Event->event_attributes['feat_message']) ){
    $replacement = preg_replace("/\{\/?$condition\}/", '', $match);
    }else{
    $replacement = '';
    }
    }
    return $replacement;
    }
    add_action('em_event_output_condition', 'my_em_has_attribute_event_output_condition', 1, 4);

    ////////////// Usage:

    [events_list]
    #_EVENTLINK
    #_ATT{feat_message}
    {no_message}
    This displays when the feat_message ATT is not set.
    {/no_message}
    [/events_list]
    /////////////

  • Mimmo Melissa

    How can I change code for locations page?
    For events page I use:

    // SHOW PRICE
    function my_em_has_attribute_event_output_condition($replacement, $condition, $match, $EM_Event){
    if( is_object($EM_Event) && preg_match(‘/^show_price$/’, $condition,$matches) ){
    if( !in_array($args['price'],$EM_Event->event_attributes) && ($EM_Event->event_attributes['price']) ){
    $replacement = preg_replace(“/{/?$condition}/”, ”, $match);
    }else{
    $replacement = ”;
    }
    }
    return $replacement;
    }
    add_action(‘em_event_output_condition’, ‘my_em_has_attribute_event_output_condition’, 1, 4);

    • http://snippets.webaware.com.au/ Ross McKay

      G’day Mimmo,

      Checkout out this previous comment thread which sounds like what you’re asking for. Basically, there’s another filter hook for locations.

      cheers,
      Ross

  • Tako van Midwoud

    Great tutorial! But unfortunately it doesn’t seems to work. This is the code I use:

    function filterEventOutputCondition($replacement, $condition, $match, $EM_Event){
    if (is_object($EM_Event)) {
    switch ($condition) {
    // #_ATT{Mobiel}
    case 'has_att_mobiel':
    if (is_array($EM_Event->event_attributes) && !empty($EM_Event->event_attributes['Mobiel']))
    $replacement = preg_replace('/{/?has_att_mobiel}/', '', $match);
    else
    $replacement = '';
    break;
    }
    }
    return $replacement;
    }
    add_filter('em_event_output_condition', 'filterEventOutputCondition', 10, 4);

    And this in the ‘Default event list format’:

    <p>
    <strong>Contact</strong><br/>
    #_ATT{Contactpersoon}<br/>
    #_ATT{Telefoon}<br/>
    {has_att_mobiel}
    #_ATT{Mobiel}<br/>
    {/has_att_mobiel}
    #_ATT{E-mail}<br/>
    <a href="http://#_ATT{Website}" target="_blank">#_ATT{Website}</a>
    </p>

    When I use this code, this error wil show up on the top of my page:

    Warning: preg_replace() [function.preg-replace]: Unknown modifier '?' in /public/sites/www.weekvandebegraafplaats.nl/wp-content/themes/weekvandebegraafplaats/functions.php on line 43

    What am I doing wrong? Hope you can help me.

    • http://snippets.webaware.com.au/ Ross McKay

      G’day Tako,

      My apologies, somehow (perhaps when I moved this blog into a multisite) some backslashes went missing. Look again :)

      • Tako van Midwoud

        Awesome! Thanks for your help, you saved me. :D

  • GaetanAsselberghs

    Is it possible to render the H (hour) in the next statement:

    {is_long}#D #d #M from #H:#i until #@H:#@i{/is_long}
    {not_long}#D #d #M from #H:#i until #@H:#@i{/not_long}

    As H+2 ?? What would be the syntax of such a statement?

    (An event from 19:00 untill 22:00 would render in single event page as: from 21:00 until 24:00)

    Thanx for any help!

    • http://snippets.webaware.com.au/ Ross McKay

      You probably should be asking that on the support forum.

      • GaetanAsselberghs

        I did, but to no response yet, but this site/thread seems to be populated with people with knowledge about the subject #dare to ask.