Get Plugin

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

event-tickets-for-woocommerce/
├── assets/
│   ├── css/           # Stylesheets
│   └── js/            # JavaScript files
├── includes/
│   ├── admin/         # Admin functionality
│   ├── api/           # REST API endpoints
│   ├── blocks/        # Gutenberg blocks
│   ├── core/          # Core classes
│   ├── emails/        # Email classes
│   ├── export/        # Export functionality
│   ├── frontend/      # Frontend display
│   ├── import/        # Import functionality
│   ├── pdf/           # PDF generation
│   ├── seating/       # Seating charts
│   ├── speakers/      # Speaker management
│   ├── waitlist/      # Waitlist system
│   └── woocommerce/   # WooCommerce integration
├── languages/         # Translation files
└── templates/         # Template files

Class naming

All classes use the EMWC_ prefix:

  • EMWC_Event - Event model
  • EMWC_Attendee - Attendee model
  • EMWC_Admin - Admin functionality

Database tables

Custom tables with wp_emwc_ prefix:

  • wp_emwc_attendees - Attendee records
  • wp_emwc_checkins - Check-in history
  • wp_emwc_waitlist - Waitlist entries

Hooks reference

Action hooks

Event Lifecycle

// Event created
do_action( 'emwc_event_created', $event_id, $event_data );

// Event updated
do_action( 'emwc_event_updated', $event_id, $event_data );

// Event deleted
do_action( 'emwc_event_deleted', $event_id );

// Event status changed
do_action( 'emwc_event_status_changed', $event_id, $new_status, $old_status );

Registration

// Registration completed
do_action( 'emwc_registration_completed', $attendee_id, $order_id, $event_id );

// Registration cancelled
do_action( 'emwc_registration_cancelled', $attendee_id, $order_id );

Check-in

// Attendee checked in
do_action( 'emwc_attendee_checked_in', $attendee_id, $event_id );

// Attendee checked out
do_action( 'emwc_attendee_checked_out', $attendee_id, $event_id );

Capacity

// Event sold out
do_action( 'emwc_event_sold_out', $event_id );

// Capacity available
do_action( 'emwc_capacity_available', $event_id, $spots_available );

Waitlist

// Joined waitlist
do_action( 'emwc_waitlist_joined', $waitlist_id, $event_id, $email );

// Promoted from waitlist
do_action( 'emwc_waitlist_promoted', $waitlist_id, $event_id );

Filter hooks

Event Data

// Modify event statuses
add_filter( 'emwc_event_statuses', function( $statuses ) {
    $statuses['custom'] = __( 'Custom Status' );
    return $statuses;
} );

// Modify event types
add_filter( 'emwc_event_types', function( $types ) {
    return $types;
} );

Display

// Calendar event data
add_filter( 'emwc_calendar_event_data', function( $data, $event_id ) {
    $data['custom'] = get_post_meta( $event_id, 'custom_field', true );
    return $data;
}, 10, 2 );

// Event card output
add_filter( 'emwc_event_card_html', function( $html, $event_id ) {
    return $html;
}, 10, 2 );

Tickets

// Ticket code format
add_filter( 'emwc_ticket_code_format', function( $format ) {
    return 'TICKET-%s'; // %s is replaced with unique string
} );

// Ticket code length
add_filter( 'emwc_ticket_code_length', function( $length ) {
    return 12;
} );

Attendee Fields

// Add custom attendee field
add_filter( 'emwc_attendee_fields', function( $fields ) {
    $fields['dietary'] = array(
        'label' => 'Dietary Requirements',
        'type' => 'select',
        'options' => array( 'none', 'vegetarian', 'vegan', 'gluten-free' ),
        'required' => false
    );
    return $fields;
} );

Emails

// Email recipient
add_filter( 'emwc_admin_notification_recipient', function( $email ) {
    return 'events@example.com';
} );

// Email subject
add_filter( 'emwc_email_subject', function( $subject, $email_id ) {
    return $subject;
}, 10, 2 );

API

// API event response
add_filter( 'emwc_rest_event_response', function( $data, $event ) {
    $data['custom_field'] = get_post_meta( $event->ID, 'custom', true );
    return $data;
}, 10, 2 );

Template overrides

Override location

Copy templates from:

plugins/event-tickets-for-woocommerce/templates/

To:

your-theme/event-tickets-for-woocommerce/

Available templates

TemplatePurpose
single-emwc_event.phpSingle event page
archive-emwc_event.phpEvent archive
single-emwc_speaker.phpSingle speaker page
archive-emwc_speaker.phpSpeaker archive
emails/*.phpEmail templates
Scroll to see all columns →

Template functions

// Get event
$event = emwc_get_event( $event_id );

// Get attendees for event
$attendees = emwc_get_event_attendees( $event_id );

// Check if event is sold out
$sold_out = emwc_is_event_sold_out( $event_id );

// Get remaining capacity
$remaining = emwc_get_remaining_capacity( $event_id );

Custom post type integration

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_statusEvent status
_emwc_event_typeEvent type
_emwc_venue_idVenue post ID
_emwc_organizer_idOrganizer post ID
_emwc_capacityMaximum attendees
_emwc_virtual_urlVirtual event URL
_emwc_external_urlExternal registration URL
Scroll to see all columns →

Querying events

// Upcoming 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' => date( 'Y-m-d' ),
            'compare' => '>=',
            'type' => 'DATE'
        )
    )
) );

Database operations

Attendee table

global $wpdb;
$table = $wpdb->prefix . 'emwc_attendees';

// Get attendees for event
$attendees = $wpdb->get_results( $wpdb->prepare(
    "SELECT * FROM {$table} WHERE event_id = %d AND status = 'active'",
    $event_id
) );

Check-in table

$table = $wpdb->prefix . 'emwc_checkins';

// Log check-in
$wpdb->insert( $table, array(
    'attendee_id' => $attendee_id,
    'event_id' => $event_id,
    'action' => 'check_in',
    'checked_by' => get_current_user_id(),
    'created_at' => current_time( 'mysql' )
) );

JavaScript integration

Global object

// Available on frontend
window.emwc = {
    ajaxUrl: '/wp-admin/admin-ajax.php',
    nonce: 'abc123...',
    events: [ /* event data */ ]
};

AJAX handlers

// Custom AJAX call
jQuery.post( emwc.ajaxUrl, {
    action: 'emwc_custom_action',
    nonce: emwc.nonce,
    data: { /* your data */ }
}, function( response ) {
    console.log( response );
} );

Events

// Listen for check-in
jQuery( document ).on( 'emwc_checked_in', function( e, data ) {
    console.log( 'Checked in:', data.attendee );
} );

Creating extensions

Plugin header

<?php
/**
 * Plugin Name: EMWC Custom Extension
 * Description: Custom functionality for Events Manager
 * Version: 1.0.0
 * Requires Plugins: event-tickets-for-woocommerce
 */

Dependency check

add_action( 'plugins_loaded', function() {
    if ( ! class_exists( 'EMWC' ) ) {
        add_action( 'admin_notices', function() {
            echo '<div class="error"><p>EMWC Extension requires Event Tickets for WooCommerce.</p></div>';
        } );
        return;
    }
    
    // Initialize extension
} );

Adding admin pages

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

Testing

Unit testing

class Test_EMWC_Event extends WP_UnitTestCase {
    
    public function test_event_creation() {
        $event_id = wp_insert_post( array(
            'post_type' => 'emwc_event',
            'post_title' => 'Test Event',
            'post_status' => 'publish'
        ) );
        
        $this->assertNotEmpty( $event_id );
    }
}

Debug mode

Enable debug logging:

define( 'EMWC_DEBUG', true );

Logs appear in wp-content/debug.log.

Best practices

Performance

  • Cache expensive queries
  • Use transients for repeated data
  • Lazy load assets

Security

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

Compatibility

  • Test with latest WordPress
  • Test with latest WooCommerce
  • Avoid overriding core functions
  • Use hooks instead of modifying files