# Events Block - Developer Guide

This guide is for site developers implementing the Itinerator plugin who need to create custom event templates or work with the Events block beyond the standard user interface.

## Overview

The Events block (`itinerator/events`) displays events from your Tourismo admin platform. While the block works out-of-the-box, this guide covers how to create custom templates and work with the underlying data structure for advanced implementations.

## How the Events Block Works

The Events block has four main components, but as a site developer, you'll primarily work with:

### 1. **View Templates** (`templates/events.php`)
- **What you'll modify**: Create custom templates for different display layouts
- **Purpose**: Controls how events are displayed on the frontend
- **Access**: Available in your theme or child theme

### 2. **PHP Template Class** (`src/Templates/Events.php`)
- **What you'll use**: Helper methods for processing event data
- **Purpose**: Provides methods to work with event data in your custom templates
- **Access**: Static methods you can call from your templates

### 3. **Block Attributes** (set in WordPress editor)
- **What you'll configure**: Display options and filtering settings
- **Purpose**: Controls what data is available and how the block behaves
- **Access**: Available in the block editor sidebar

### 4. **JavaScript Block** (plugin core)
- **What you won't modify**: Handles the WordPress editor interface
- **Purpose**: Provides the block editor experience
- **Access**: Not typically modified by site developers

## Creating Custom Event Templates

The most common customization is creating custom templates for different display layouts.

### Template Location
Custom templates should be placed in your theme's `itinerator` directory:
```
your-theme/
├── itinerator/
│   ├── events-custom.php
│   ├── events-calendar.php
│   └── events-list.php
```

### Using Custom Templates
1. Create your custom template file
2. In the Events block editor, set **Custom Template Name** to your template name (without `.php`)
3. The block will load your custom template instead of the default

### Template Structure
Your custom template receives the processed event data and can access all block attributes:

```php
<?php
// Your custom template receives:
// $this->events - Array of event objects
// $this->attributes - All block settings
// $this->showImage, $this->showName, etc. - Individual attribute values
?>

<div class="your-custom-events">
    <?php foreach ($this->events as $event): ?>
        <!-- Your custom event display -->
    <?php endforeach; ?>
</div>
```

## Event Data Structure

Each event in your template is a `SimpleEvent` object with the following properties:

### Basic Event Information
```php
$event->id              // Event ID
$event->slug            // URL slug
$event->name            // Event title
$event->description     // Event description
$event->featured        // Boolean - is featured
$event->cost            // Cost as string
$event->status          // Publication status
```

### Contact Information
```php
$event->email           // Contact email
$event->website         // Event website URL
$event->phone_number    // Contact phone
$event->ticket_url      // Ticket purchase URL
```

### Location & Categorization
```php
$event->region_id       // Region ID
$event->region_name     // Region name
$event->region_slug     // Region URL slug
$event->tags            // Array of tag objects
$event->recurring       // Boolean - is recurring event
```

### Media
```php
$event->hero            // Hero image object
$event->carousel_images // Array of additional images
$event->meta_image      // Meta/social image
```

### Event Times
```php
$event->event_times     // Array of event time objects
```

### Navigation
```php
$event->path            // Full URL path to event detail page
$event->filter_classes  // CSS classes for filtering
```

## Helper Methods for Custom Templates

The Events block provides several static methods you can use in your custom templates to work with event data.

### Event Time Processing

#### `Events::createDateTime($dateTime)`
Creates a DateTime object from a datetime string.

```php
$startDate = \Itinerator\Templates\Events::createDateTime($event->event_times[0]->next_start);
```

#### `Events::convertDateTimeRange($startDateTime, $endDateTime, $dateFormat = null, $timeFormat = null)`
Formats datetime ranges for display.

```php
$datetimes = \Itinerator\Templates\Events::convertDateTimeRange(
    $event->event_times[0]->next_start,
    $event->event_times[0]->next_end
);

echo $datetimes['date_range']; // "Mon, Nov 15"
echo $datetimes['time_range']; // "6:00 pm - 10:00 pm"
```

### Recurring Event Detection

#### `Events::isRecurring($event)`
Check if an event is recurring.

```php
if (\Itinerator\Templates\Events::isRecurring($event)) {
    echo "This event repeats";
}
```

#### `Events::isSeries($event)`
Check if an event is a series (recurring OR multiple event_times).

```php
if (\Itinerator\Templates\Events::isSeries($event)) {
    echo "This is a series or recurring event";
}
```

#### `Events::getRecurringEventOccurrences($eventTimes, $limit = 3, $format = 'D, M j')`
Get upcoming occurrences from recurring events.

```php
$occurrences = \Itinerator\Templates\Events::getRecurringEventOccurrences(
    $event->event_times,
    5, // Get next 5 occurrences
    'M j' // Format: "Nov 15"
);

foreach ($occurrences as $occurrence) {
    echo $occurrence['start']; // "Nov 15"
    echo $occurrence['time'];  // "6:00 pm - 10:00 pm"
}
```

#### `Events::getNextEventTime($event_times)`
Get the next upcoming event time.

```php
$nextTime = \Itinerator\Templates\Events::getNextEventTime($event->event_times);
if ($nextTime) {
    echo "Next occurrence: " . $nextTime->next_start;
}
```

## Working with Event Times

Event times are stored in the `$event->event_times` array. Each event can have multiple time slots.

### Event Time Object Structure
```php
$eventTime = {
    id: "789",
    all_day: false,
    sold_out: false,
    next_start: "2025-07-15T18:00:00-05:00",
    next_end: "2025-07-15T22:00:00-05:00",
    upcoming_times: [
        { start: "2025-07-15T18:00:00-05:00", end: "2025-07-15T22:00:00-05:00" },
        { start: "2025-07-22T18:00:00-05:00", end: "2025-07-22T22:00:00-05:00" }
    ],
    locations: [
        {
            name: "Central Park",
            full_address: "123 Main St, City, State 12345"
        }
    ]
}
```

### Common Event Time Operations

#### Get the Next Event Time
```php
$nextTime = \Itinerator\Templates\Events::getNextEventTime($event->event_times);
if ($nextTime) {
    echo "Next: " . $nextTime->next_start;
}
```

#### Check if Event is All Day
```php
$eventTime = $event->event_times[0];
if ($eventTime->all_day) {
    echo "All Day Event";
} else {
    echo "Time: " . $eventTime->next_start . " - " . $eventTime->next_end;
}
```

#### Get Event Locations
```php
$eventTime = $event->event_times[0];
if (!empty($eventTime->locations)) {
    foreach ($eventTime->locations as $location) {
        echo $location->name . " - " . $location->full_address;
    }
}
```

#### Format Date and Time
```php
$eventTime = $event->event_times[0];
$datetimes = \Itinerator\Templates\Events::convertDateTimeRange(
    $eventTime->next_start,
    $eventTime->next_end,
    'F j, Y', // Date format
    'g:i a'   // Time format
);

echo $datetimes['date_range']; // "July 15, 2025"
echo $datetimes['time_range']; // "6:00 pm - 10:00 pm"
```

## Block Attributes in Templates

In your custom templates, you can access all block settings through the `$this` object:

### Display Settings
```php
// Check if features are enabled
if ($this->showImage) {
    // Display event images
}

if ($this->showName) {
    echo $event->name;
}

if ($this->showEventDateTimes) {
    // Display dates and times
}

if ($this->showCost) {
    echo "Cost: " . $event->cost;
}
```

### Filtering Settings
```php
// Check filtering settings
if ($this->filterRecordsByRegion) {
    // Region filtering is enabled
}

if (!empty($this->tagFilters)) {
    // Tag filtering is active
}
```

### Template Settings
```php
// Get custom template name
$templateName = $this->customTemplateName;

// Get linked page ID
$linkedPageId = $this->linkedPageId;

// Get custom CSS classes
$customClass = $this->className;
```

### Available Attributes
All block settings are available as `$this->attributeName` in your templates:
- `$this->showImage`, `$this->showName`, `$this->showEventDateTimes`, `$this->showCost`
- `$this->showPhone`, `$this->showEmail`, `$this->showWebsite`, `$this->showTicketLink`
- `$this->showTags`, `$this->showLocation`, `$this->showDescription`, `$this->showDateFilter`
- `$this->customTemplateName`, `$this->linkedPageId`, `$this->className`, `$this->buttonText`

## Template Examples

### Basic Custom Template
```php
<?php
// your-theme/itinerator/events-simple.php
?>
<div class="custom-events-list">
    <?php foreach ($this->events as $event): ?>
        <div class="event-item">
            <h3><?= esc_html($event->name) ?></h3>

            <?php if ($this->showEventDateTimes && !empty($event->event_times)): ?>
                <?php
                $eventTime = $event->event_times[0];
                $datetimes = \Itinerator\Templates\Events::convertDateTimeRange(
                    $eventTime->next_start,
                    $eventTime->next_end
                );
                ?>
                <div class="event-date"><?= $datetimes['date_range'] ?></div>
                <div class="event-time"><?= $datetimes['time_range'] ?></div>
            <?php endif; ?>

            <?php if ($this->showCost && $event->cost): ?>
                <div class="event-cost">$<?= esc_html($event->cost) ?></div>
            <?php endif; ?>

            <a href="<?= esc_url($event->path) ?>" class="btn btn-primary">
                <?= esc_html($this->buttonText) ?>
            </a>
        </div>
    <?php endforeach; ?>
</div>
```

### Calendar-Style Template
For a more advanced calendar view with traditional month grids, see the [Advanced Calendar Methods](#advanced-calendar-methods) section below, which includes a complete calendar template implementation.

### Featured Events Template
```php
<?php
// your-theme/itinerator/events-featured.php
$featuredEvents = array_filter($this->events, function($event) { return $event->featured; });
$regularEvents = array_filter($this->events, function($event) { return !$event->featured; });
?>

<div class="featured-events">
    <h2>Featured Events</h2>
    <?php foreach ($featuredEvents as $event): ?>
        <div class="featured-event">
            <?php if ($this->showImage && $event->hero): ?>
                <img src="<?= esc_url($event->hero->url) ?>" alt="<?= esc_attr($event->name) ?>">
            <?php endif; ?>
            <h3><?= esc_html($event->name) ?></h3>
        </div>
    <?php endforeach; ?>
</div>
```

## Working with Images and Tags

### Images
```php
// Hero images
if ($this->showImage && $event->hero) {
    echo '<img src="' . esc_url($event->hero->url) . '" alt="' . esc_attr($event->name) . '">';
    // Or use: $event->hero->getMedia('medium', 'event-image');
}

// Carousel images
if (!empty($event->carousel_images)) {
    foreach ($event->carousel_images as $image) {
        echo '<img src="' . esc_url($image->url) . '" alt="' . esc_attr($event->name) . '">';
    }
}
```

### Tags
```php
// Display tags
if ($this->showTags && !empty($event->tags)) {
    echo '<div class="event-tags">';
    foreach ($event->tags as $tag) {
        echo '<span class="tag">' . esc_html($tag->name) . '</span>';
    }
    echo '</div>';
}
```

### CSS Classes
Events get filter classes: `$event->filter_classes` (e.g., "searchable-item downtown tag-id-45")

## Advanced Calendar Methods

*Note: We have prepared these methods for calendar templates, but we do not offer support for calendar implementations at this time.*

### Calendar Helper Methods

#### `Events::getAllEventOccurrences($event, $start_date, $end_date)`
Gets all occurrences of an event within a date range, including recurring events and multi-day events.

```php
$occurrences = \Itinerator\Templates\Events::getAllEventOccurrences($event, '2025-11-01', '2025-12-31');
foreach ($occurrences as $occurrence) {
    echo $occurrence['date']; // "2025-11-15"
    echo $occurrence['time_display']; // "6:00 pm - 10:00 pm"
}
```

#### `Events::mapEventsToDateArray($events, $start_date, $end_date)`
Processes events into a date-indexed array for calendar display.

```php
$events_by_date = \Itinerator\Templates\Events::mapEventsToDateArray($this->events, '2025-11-01', '2025-12-31');
// Result: ['2025-11-15' => [event1, event2], '2025-11-16' => [event3]]
```

#### `Events::buildCalendarGrid($start_date, $end_date, $events_by_date, $week_start_day = 0)`
Generates calendar structure with separate grids for each month in the date range.

```php
$calendar_months = \Itinerator\Templates\Events::buildCalendarGrid('2025-11-01', '2025-12-31', $events_by_date, 0);
```

### Calendar Template Implementation

```php
<?php
// your-theme/itinerator/events-calendar.php
$calendar_start_date = '2025-11-01';
$calendar_end_date = '2025-12-31';
$week_start_day = 0;

$events_by_date = \Itinerator\Templates\Events::mapEventsToDateArray($this->events, $calendar_start_date, $calendar_end_date);
$calendar_months = \Itinerator\Templates\Events::buildCalendarGrid($calendar_start_date, $calendar_end_date, $events_by_date, $week_start_day);
?>

<div class="itin itinerator-events itinerator-calendar <?= $this->attributes['className'] ?? '' ?>">
  <?php foreach ($calendar_months as $month): ?>
    <div class="calendar-month">
      <h2 class="calendar-month-label"><?= $month['month_label'] ?></h2>
      <div class="calendar-grid">
        <div class="calendar-header">
          <div class="calendar-day-name">Sun</div>
          <div class="calendar-day-name">Mon</div>
          <div class="calendar-day-name">Tue</div>
          <div class="calendar-day-name">Wed</div>
          <div class="calendar-day-name">Thu</div>
          <div class="calendar-day-name">Fri</div>
          <div class="calendar-day-name">Sat</div>
        </div>
        <?php foreach ($month['weeks'] as $week): ?>
          <div class="calendar-week">
            <?php foreach ($week as $day): ?>
              <div class="calendar-day <?= $day['is_today'] ? 'today' : '' ?> <?= !$day['is_current_month'] ? 'other-month' : '' ?>">
                <div class="calendar-day-number"><?= $day['day_number'] ?></div>
                <div class="calendar-day-events">
                  <?php foreach ($day['events'] as $occurrence): ?>
                    <a href="<?= $occurrence['event']->path ?>" class="calendar-event">
                      <?php if ($occurrence['event']->hero): ?>
                        <div class="calendar-event-thumbnail">
                          <?= $occurrence['event']->hero->getMedia('thumbnail', 'calendar-event-img') ?>
                        </div>
                      <?php endif; ?>
                      <div class="calendar-event-details">
                        <div class="calendar-event-time"><?= $occurrence['time_display'] ?></div>
                        <div class="calendar-event-name"><?= esc_html($occurrence['event']->name) ?></div>
                      </div>
                    </a>
                  <?php endforeach; ?>
                </div>
              </div>
            <?php endforeach; ?>
          </div>
        <?php endforeach; ?>
      </div>
    </div>
  <?php endforeach; ?>
</div>
```

### Key CSS Classes
- `.itin.itinerator-events.itinerator-calendar` - Main wrapper
- `.calendar-month` - Individual month container
- `.calendar-day` - Individual day cell
- `.calendar-day.today` - Today
- `.calendar-day.other-month` - Padding days
- `.calendar-event` - Individual event link


## Troubleshooting

### Common Issues

1. **Events not displaying**: Check that `linked_page_id` is set in the block settings
2. **Custom template not loading**: Verify the template file exists in your theme's `itinerator/` directory
3. **Date formatting issues**: Check WordPress timezone settings in Settings > General
4. **Images not showing**: Ensure `showImage` is enabled in block settings
5. **Template errors**: Check for PHP syntax errors in your custom template

### Debug Tips

- Enable `WP_DEBUG` in `wp-config.php` to see error messages
- Check that your custom template file has the correct name and location
- Verify that all required attributes are being checked before use
- Test with the default template first to ensure the block is working

## Getting Help

For additional support with custom template development:
- Check the [User Guide](../user-guide/blocks/collection-blocks/events.md) for basic usage
- Review the default template (`templates/events.php`) for reference
- Test your templates with different event data to ensure compatibility
