Roots Discourse

The Events Calendar and Sage 9 (blade)

Like WooCommerce before it The Events Calendar by Tribe doesn’t want to play nice with Blade templates.

This looks like a slightly different challenge than WooCommerce, because TEC wants to choose a Page template (default or a custom template), and sees the templates just fine, but only shows a stripped down “Archive” view of the events no matter which template is chosen.

How can I troubleshoot and/or work around this issue in a way that’s helpful to the Sage project? Is there specific information I can provide?

2 Likes

Just a quick confirmation that $template variable at the /events/ slug is index.blade.php, and on an individual event it’s single.blade.php.

For troubleshooting these issues, I’ve found it helpful to just var_dump($templates); in wp-includes/template.php#L42

You’ll get something that looks like this (normally it’s not doubled up like this, but this seems to be happening on events archives pages with that plugin):

This is more or less a list of what files it’s sending to locate_template() in wp-includes/template-loader.php.

Each new block of file names from the var_dump() could be an indicator that the return value from locate_template() (in each of the get_{type}_template() from template-loader.php) was falsy.

I hope that makes sense.

2 Likes

For the particular plugin you’re discussing, the best solution is to probably create an events.blade.php file in your templates directory with the following contents:

{{--
  Template Name: Events
--}}

@extends('layouts.base')

@section('content')
  <div id="tribe-events-pg-template">
	<?php tribe_events_before_html(); ?>
	<?php tribe_get_view(); ?>
	<?php tribe_events_after_html(); ?>
  </div> <!-- #tribe-events-pg-template -->
@endsection

Be sure to select it in the admin panel.

If you need further refinement, then create a templates/tribe-events/ folder and have at it. If you want to use blade for these, then you’ll need to basically copy how we implemented blade for WordPress core (see sage/src/filters.php), and even then I’m not sure if it would work; it might cause the plugin to shit its pants.

9 Likes

This did the trick. Thank you!

Going forward perhaps the docs could include basic snippets and info for common plugins like The Events Calendar, WooCommerce, etc? Just a thought.

I really appreciate your time on this!

Both WooCommerce and The Events Calendar document how to do this. It’s just standard implementation of these respective plugins. The Events Calendar is doing something slightly wrong, though, in my opinion.

Here’s a neat thing I found: I can automatically set the The Events Calendar default template using their settings class, so that I never see the error that started this thread:

/** 
* Set the The Events Calendar default template to our Sage-friendly template.
**/
Tribe__Settings_Manager::set_option( 'tribeEventsTemplate', 'views/template-events.blade.php' );

2 Likes

Nice, I’m about to use TEC on a Sage 9 project, so this will definitely come in handy.
Thanks!

1 Like

Have you ever had to move the whole tribe-events views folder to edit multiple tribe files?

@timothy_m_alber I have.

In Sage 9, putting events calendar template overrides in the resources dir seems to do the trick:

./resources/tribe-events/{tribe-template-to-override}.php
4 Likes

This is what i’m using now for the event calendar:

Essentially removing everything thats included by the event calendar and rendering it again with blade. A huge waste of resources. If anyone has another solution, let me know!

The first filter alone allows for overwrites to be placed in /resources/views/tribe-events/, but doesn’t enable blade.

Thanks! This did the trick and it was the shortest path from A to B.

Only problem was Tribe’s js template, ‘/src/views/month/tooltip.php’. In case anyone else runs into this issue (tooltip markup not generated in month view), the tooltip markup can be easily recreated client-side:

<script>
$('.tribe_events.status-publish').each(function() {
      var tribeJson = $(this).data('tribejson');
      console.log(tribeJson);
      var eventUrl = tribeJson.permalink,
          eventTitle = tribeJson.title,
          eventThumb = tribeJson.imageTooltipSrc,
          eventTime = tribeJson.dateDisplay,
          eventDesc = tribeJson.excerpt;
      $(this).append('<div class="tribe-events-tooltip" style="bottom: 50px; display: none; opacity: 1;"><a class="url" href="'+eventUrl+'" title="'+eventTitle+'" rel="bookmark"><h4 class="entry-title summary">'+eventTitle+'</h4></a>	<div class="tribe-events-event-body"><div class="tribe-event-duration"><a class="url" href="'+eventUrl+'" title="'+eventTitle+'" rel="bookmark"><abbr class="tribe-events-abbr tribe-event-date-start">'+eventTime+' </abbr></a></div> <div class="tribe-events-event-thumb"><a class="url" href="'+eventUrl+'" title="'+eventTitle+'" rel="bookmark"><img src="'+eventThumb+'" alt="'+eventTitle+'"></a></div><div class="tribe-event-description">'+eventDesc+'</div><span class="tribe-events-arrow"></span></div></div>');
    });
</script>

I had a bit of trouble with this, as the events calendar was doing something funky with the standard wp_query data. I found that the following worked as expected:

{{--
  Template Name: Events Template
--}}

@extends('layouts.app')

@section('content')
    <main id="tribe-events-pg-template"
          class="tribe-events-pg-template">
        {!!Tribe__Events__Templates::load_ecp_into_page_template() !!}
    </main>
@endsection
2 Likes

Actually, still had problems with my previous template. I’ve found that the following snippet works as it will fire all of the hooks defined in the Tribe__Events__Templates::setup_ecp_template() function and handle all the “ninja magic” mentioned there.

Not sure if anyone else has had this problem, but it looks like it’s working as expected for me now.

{{--
  Template Name: Events Template
--}}

@extends('layouts.app')

@section('content')
    <main id="tribe-events-pg-template"
          class="tribe-events-pg-template">
        @while(have_posts()) @php the_post() @endphp
        @php the_content() @endphp
        @endwhile
    </main> <!-- #tribe-events-pg-template -->
@endsection

Right now, we solve this by ignoring their complete HTML for specific pages and loading our own like so:

add_filter('tribe_template_html', function($html, $file, $name, $that) {
    if ($name[0] === 'single-event-blocks') {
        return template('tribe.events.single-event-blocks', ['that' => $that]);
    }
    return $html;
}, 999, 4);

Needs refactoring, especially to make the default blade filters and Controllers work again, but it was a quick solve to use our custom template for a single event.

I’ve been having a tinker to see how close I could get to solving this (similarly to sage-woocommerce).
Using this, I’ve managed to output some templates with Controller support:

<?php

declare(strict_types=1);

namespace App\Plugins;

use function App\template;

class EventsCalendar
{
    public function run(): void
    {
        $this->addFilters();
    }

    public function addFilters(): void
    {
        add_filter('tribe_get_current_template', [self::class, 'setupTemplates'], PHP_INT_MAX);
        add_filter('tribe_get_template_part_path', [self::class, 'setupTemplates'], PHP_INT_MAX);
    }

    public static function setupTemplates(string $original_template): string
    {
        $template = basename($original_template);
        $view = basename(dirname($original_template));
        $view_template = "{$view}/{$template}";
        $data = collect(get_body_class())->reduce(function ($data, $class) use ($template) {
            return apply_filters("sage/template/{$class}/data", $data, $template);
        }, []);
        $location_paths = [
            "tribe-events/{$view_template}",
            "tribe-events/{$template}",
            $template,
        ];
        $template = \App\locate_template($location_paths);

        if ($template) {
            // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
            echo template($template, $data);
            return get_stylesheet_directory() . '/index.php';
        }

        return $original_template;
    }
}

The only problem is that there are a fair few template parts in Events Calendar that when trying to load will give the error “Fatal error: Allowed memory size of xxxxx”.

Unfortunately, I haven’t really figured that bit out…

But I hope this may help someone get closer to complete support with Blade+Controllers!

Edit:
One of the issues I had was using a custom events template.
Using a custom event template (chosen in Events Calendar settings) would provide strange results (e.g. get_the_ID() returns 0).
Using the default template and overriding in the theme provides more consistent results.