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 modelEMWC_Attendee- Attendee modelEMWC_Admin- Admin functionality
Database tables#
Custom tables with wp_emwc_ prefix:
wp_emwc_attendees- Attendee recordswp_emwc_checkins- Check-in historywp_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#
| Template | Purpose |
|---|---|
single-emwc_event.php | Single event page |
archive-emwc_event.php | Event archive |
single-emwc_speaker.php | Single speaker page |
archive-emwc_speaker.php | Speaker archive |
emails/*.php | Email templates |
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#
| Key | Description |
|---|---|
_emwc_start_date | Start date (Y-m-d) |
_emwc_end_date | End date |
_emwc_start_time | Start time (H:i) |
_emwc_end_time | End time |
_emwc_all_day | All day event (yes/no) |
_emwc_timezone | Event timezone |
_emwc_event_status | Event status |
_emwc_event_type | Event type |
_emwc_venue_id | Venue post ID |
_emwc_organizer_id | Organizer post ID |
_emwc_capacity | Maximum attendees |
_emwc_virtual_url | Virtual event URL |
_emwc_external_url | External registration URL |
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 Evenzo – Events Manager 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