Docs Evenzo – Events Manager for WooCommerce

Developer Guide

Developer Guide#

Extend and customize the plugin using hooks, filters, templates, and the API. This guide covers common customization scenarios.

Architecture overview#

File structure#

evenzo-events-manager/
├── assets/
│   ├── css/           # Stylesheets
│   └── js/            # JavaScript files
├── includes/
│   ├── admin/         # Admin screens and settings
│   ├── api/           # REST API controllers and webhooks
│   ├── blocks/        # Gutenberg blocks
│   ├── core/          # Event, attendee, post types, QR code, recurrence
│   ├── emails/        # WooCommerce email classes
│   ├── export/        # CSV and iCal export
│   ├── frontend/      # Templates, shortcodes, calendar, widgets
│   ├── import/        # CSV and iCal import
│   ├── pdf/           # Printable tickets
│   ├── seating/       # Seating charts
│   ├── speakers/      # Speaker post type
│   ├── waitlist/      # Waitlist and pricing rules
│   └── woocommerce/   # Product and order integration
├── languages/         # Translation files
└── templates/         # Template files

Class naming#

All classes use the EMWC_ prefix. The main plugin class is EMWC (use class_exists( 'EMWC' ) for dependency checks).

  • EMWC_Event - Event model (get_start_date(), get_venue_id(), is_upcoming(), save())
  • EMWC_Attendee - Attendee model (check_in(), check_out(), get_by_ticket_code(), get_for_event())
  • EMWC_Logger - Logging through the WooCommerce logger

Database tables#

Custom tables created on activation:

TablePurpose
wp_emwc_attendeesAttendee and ticket records
wp_emwc_checkinsCheck-in and check-out history
wp_emwc_waitlistWaitlist entries
wp_emwc_pricing_rulesCreated but not used by the current pricing code (rules are stored in product meta)

Hooks reference#

Action hooks#

Tickets and attendees

// Attendee record created while generating tickets for an order
do_action( 'emwc_attendee_created', $attendee_id, $attendee_data, $event_id, $order_id );

// All tickets for an order generated
do_action( 'emwc_tickets_generated', $order_id, $order );

// All tickets for an order cancelled (order cancelled or refunded)
do_action( 'emwc_tickets_cancelled', $order_id );

// Single ticket cancelled or reactivated from the Attendees screen
do_action( 'emwc_ticket_cancelled', $attendee_id, $attendee );
do_action( 'emwc_ticket_reactivated', $attendee_id, $attendee );

// Ticket email resent from the Attendees screen
do_action( 'emwc_ticket_email_resent', $attendee_id, $order_id );

// Attendee deleted
do_action( 'emwc_attendee_deleted', $attendee_id );

$attendee is an EMWC_Attendee object. $attendee_data is an array with first_name, last_name, email, and ticket_code.

Check-in

// Fired from the admin check-in screen (second argument is an EMWC_Attendee)
// and from the REST check-in endpoint (second argument is the attendee row as an array)
do_action( 'emwc_attendee_checked_in', $attendee_id, $attendee );
do_action( 'emwc_attendee_checked_out', $attendee_id, $attendee );

Waitlist

// Someone joined the waitlist
do_action( 'emwc_waitlist_joined', $entry_id, $product_id, $email );

// Notification email sent to a waitlist entry
do_action( 'emwc_waitlist_notification_sent', $entry, $product );

REST API

do_action( 'emwc_rest_event_created', $post_id, $request );
do_action( 'emwc_rest_event_updated', $post_id, $request );
do_action( 'emwc_rest_event_deleted', $post_id, $force );
do_action( 'emwc_rest_venue_created', $post_id, $request );
do_action( 'emwc_rest_venue_updated', $post_id, $request );
do_action( 'emwc_rest_venue_deleted', $post_id, $force );
do_action( 'emwc_rest_organizer_created', $post_id, $request );
do_action( 'emwc_rest_organizer_updated', $post_id, $request );
do_action( 'emwc_rest_organizer_deleted', $post_id, $force );
do_action( 'emwc_rest_attendee_updated', $attendee_id, $request );

Templates

// Inside the single event template, after the event details block
do_action( 'emwc_single_event_after_details', $event_id );

Filter hooks#

REST responses

add_filter( 'emwc_rest_prepare_event', function( $data, $post, $request ) {
    $data['custom_field'] = get_post_meta( $post->ID, 'custom_field', true );
    return $data;
}, 10, 3 );

Also available: emwc_rest_prepare_venue and emwc_rest_prepare_organizer ($data, $post, $request), and emwc_rest_prepare_attendee ($data, $attendee array, $request).

Structured data

// Schema.org Event data printed on single event pages
add_filter( 'emwc_event_schema', function( $schema, $event_id ) {
    $schema['eventAttendanceMode'] = 'https://schema.org/MixedEventAttendanceMode';
    return $schema;
}, 10, 2 );

Tickets

// Accent color on the printable ticket (default #2563eb)
add_filter( 'emwc_ticket_primary_color', function( $color ) {
    return '#111111';
} );

Template overrides#

Page templates#

Copy a template from:

plugins/evenzo-events-manager/templates/

To either of these locations in your theme:

your-theme/single-emwc_event.php
your-theme/evenzo-events-manager/single-emwc_event.php
TemplatePurpose
single-emwc_event.phpSingle event page
archive-emwc_event.phpEvent archive and category pages
single-emwc_speaker.phpSingle speaker page
archive-emwc_speaker.phpSpeaker archive

Email templates#

Emails are WooCommerce emails and follow the WooCommerce override path:

your-theme/woocommerce/emails/registration-confirmation.php
your-theme/woocommerce/emails/plain/registration-confirmation.php

Available files: admin-new-registration.php, event-cancellation.php, event-reminder.php, event-update.php, registration-confirmation.php, ticket-delivery.php, each with a plain/ version.

Custom post type integration#

Post types: emwc_event, emwc_venue, emwc_organizer, emwc_speaker. Taxonomy: emwc_event_category.

Event meta keys#

KeyDescription
_emwc_start_dateStart date (Y-m-d)
_emwc_end_dateEnd date
_emwc_start_timeStart time (H:i)
_emwc_end_timeEnd time
_emwc_all_dayAll day event (yes/no)
_emwc_timezoneEvent timezone
_emwc_event_statusscheduled, postponed, cancelled, sold-out
_emwc_event_typein-person, virtual, hybrid
_emwc_venue_idVenue post ID
_emwc_organizer_idOrganizer post ID
_emwc_capacityMaximum attendees
_emwc_registration_deadlineRegistration deadline
_emwc_featuredFeatured event (yes/no)
_emwc_virtual_urlVirtual event URL
_emwc_external_urlExternal URL (meta only, no admin field)

The REST API and calendar endpoints read and write venue and organizer under _emwc_venue and _emwc_organizer instead. Events created in the admin report venue_id: 0 through the API until the two key names match.

Querying events#

$events = new WP_Query( array(
    'post_type'  => 'emwc_event',
    'meta_key'   => '_emwc_start_date',
    'orderby'    => 'meta_value',
    'order'      => 'ASC',
    'meta_query' => array(
        array(
            'key'     => '_emwc_start_date',
            'value'   => current_time( 'Y-m-d' ),
            'compare' => '>=',
            'type'    => 'DATE',
        ),
    ),
) );

Database operations#

Attendee table#

Prefer the model over raw SQL:

$attendees = EMWC_Attendee::get_for_event( $event_id, array( 'status' => 'active' ) );
$attendee  = EMWC_Attendee::get_by_ticket_code( 'EMWC-ABC123DEF' );
$attendee->check_in( get_current_user_id(), 'front desk', 'VIP' );

Attendee statuses: active, checked_in, checked_out, cancelled.

Check-in table#

Columns: checkin_id, attendee_id, event_id, check_type (in or out), checked_by, checked_at, device_info, notes. Rows are written by EMWC_Attendee::check_in() and check_out().

Creating extensions#

Plugin header#

<?php
/**
 * Plugin Name: EMWC Custom Extension
 * Description: Custom features for Evenzo Events Manager
 * Version: 1.0.0
 * Requires Plugins: woocommerce
 */

Dependency check#

add_action( 'plugins_loaded', function() {
    if ( ! class_exists( 'EMWC' ) ) {
        add_action( 'admin_notices', function() {
            echo '<div class="error"><p>This extension requires Evenzo Events Manager.</p></div>';
        } );
        return;
    }

    // Initialize extension
}, 20 );

Adding admin pages#

The top-level menu slug is emwc-dashboard and uses the manage_woocommerce capability.

add_action( 'admin_menu', function() {
    add_submenu_page(
        'emwc-dashboard',
        'Custom Page',
        'Custom Page',
        'manage_woocommerce',
        'emwc-custom',
        'render_custom_page'
    );
}, 20 );

Debugging#

Enable Debug Mode under Events > Settings > Advanced (option emwc_enable_debug_mode). Debug, info, notice, and warning messages are then written to the WooCommerce log with source emwc. Error level messages and above are always written.

EMWC_Logger::debug( 'Custom message', 'my-context', array( 'key' => 'value' ) );
EMWC_Logger::error( 'Something failed', 'my-context' );

View logs under WooCommerce > Status > Logs.

Performance#

  • Cache expensive queries
  • Use transients for repeated data
  • Load assets only where needed

Security#

  • Sanitize all input
  • Escape all output
  • Verify nonces
  • Check capabilities

Compatibility#

  • Test with the latest WordPress and WooCommerce
  • Use hooks instead of modifying plugin files