Developer Reference
VetCarePress is built with modern PHP practices and provides multiple extension points for developers who need to customize or integrate with the plugin.
Architecture Overview
- PHP Version: 8.1+ required, with strict types enabled throughout.
- Autoloading: PSR-4 autoloading via Composer. The
VetCarePressnamespace maps to theincludes/directory. - Plugin Instance: Singleton pattern via
VetCarePressPlugin::instance(). - Dependency Injection: Lightweight DI container accessible via
Plugin::instance()->container()->make(ClassName::class).
Admin UI
Gutenberg is disabled for all VetCarePress custom post types. The admin interface uses a metabox-based UI with custom meta fields. This ensures a consistent editing experience regardless of the active theme or editor preferences.
Template System
Frontend templates can be overridden by copying them from the plugin directory into your active theme:
- Plugin path:
vetcarepress/templates/frontend/ - Theme override path:
your-theme/vetcarepress/
The plugin checks for a theme override first. If none is found, the bundled template is used.
See the Template Reference for the full list of overridable templates.
Extensibility Points
Settings System
vcp_settings_tabsfilter — Add or modify settings tabs in the plugin settings page.vcp_settings_fields_{tab}action — Inject custom fields into a specific settings tab.vcp_settings_savedaction — React to settings being saved.
Hooks and Filters
VetCarePress provides action hooks and filters for customizing permission checks, post-save logic, metabox rendering, and more.
See Hooks & Filters for the complete reference.
Data Storage
VetCarePress uses a combination of custom database tables (for customers, sessions, messages, and tokens) and WordPress custom post types (for patients, medical records, vaccinations, and lab data).
- Database Tables — schema reference for all 7 custom tables.
- Custom Post Types — reference for all 9 registered CPTs.
Key Developer Resources
| Resource | Description |
|---|---|
| Hooks & Filters | Action hooks and filters for extending the plugin |
| Template Reference | Overridable frontend templates |
| Database Tables | Custom table schemas |
| Custom Post Types | CPT definitions and meta fields |
| Roles & Capabilities | Permission system reference |
Hooks & Filters
Hooks & Filters
VetCarePress provides action hooks and filters that allow developers to extend and customize plugin behavior without modifying core files. This reference covers all public extension points.
Filters
vcp_settings_tabs
Modify the array of settings tabs displayed on the VetCarePress settings page.
- Receives:
array<string, string>— associative array ofslug => label. - Returns: Modified array.
Usage: Add a custom settings tab.
add_filter('vcp_settings_tabs', function (array $tabs): array {
$tabs['my_custom_tab'] = 'My Custom Tab';
return $tabs;
});
vcp_patient_query_args
Modify the WP_Query arguments used when listing patients via the REST API.
- Receives:
array $args— the query arguments array. - Returns: Modified array.
Usage: Add custom ordering, meta queries, or tax queries to the patient list endpoint.
add_filter('vcp_patient_query_args', function (array $args): array {
$args['meta_key'] = '_vcp_birthdate';
$args['orderby'] = 'meta_value';
return $args;
});
vcp_patient_rest_response
Modify the formatted patient data returned by the REST API.
- Receives:
array $data— the formatted patient response array. - Returns: Modified array.
vcp_medical_record_rest_response
Modify the formatted medical record data returned by the REST API.
- Receives:
array $data— the formatted record response array. - Returns: Modified array.
vcp_medical_record_types
Add or modify the available medical record types.
- Receives:
array $types— associative array ofslug => label. - Returns: Modified array.
Usage: Register a custom record type.
add_filter('vcp_medical_record_types', function (array $types): array {
$types['cytology'] = 'Cytology';
return $types;
});
vcp_lab_cpt_pairs
Register additional lab CPT pairs (panel + marker CPT combinations) for custom lab types.
- Receives:
array $pairs— array of registered CPT pairs. - Returns: Modified array.
Usage: Add a custom lab panel type (e.g., cytology panels with their own CPT).
vcp_rest_permission_staff
Override the staff permission check for REST API endpoints.
- Receives:
bool— current permission result. - Returns:
bool—trueto allow,falseto deny.
Usage: Grant access to a custom role or external authentication system.
add_filter('vcp_rest_permission_staff', function (bool $allowed): bool {
if (current_user_can('my_custom_capability')) {
return true;
}
return $allowed;
});
vcp_rest_permission_public
Override the public permission check for REST API endpoints.
- Receives:
bool— current permission result. - Returns:
bool—trueto allow,falseto deny.
Usage: Restrict otherwise-public endpoints (e.g., require a nonce or IP whitelist).
Actions
vcp_patient_created
Fired after a patient is successfully created via the REST API.
- Parameter:
int $post_id— the new patient post ID.
vcp_patient_updated
Fired after a patient is successfully updated via the REST API.
- Parameter:
int $post_id— the updated patient post ID.
vcp_medical_record_created
Fired after a medical record is successfully created via the REST API.
- Parameter:
int $post_id— the new record post ID.
vcp_medical_record_updated
Fired after a medical record is successfully updated via the REST API.
- Parameter:
int $post_id— the updated record post ID.
vcp_medical_record_deleted
Fired after a medical record is successfully deleted via the REST API.
- Parameter:
int $post_id— the deleted record post ID.
vcp_settings_saved
Fired when a settings group is saved.
- Parameter 1:
string $group— the option group name being saved. - Parameter 2:
array $post_data— the raw form data submitted.
Usage: React to settings changes, such as clearing a cache or syncing with an external service.
add_action('vcp_settings_saved', function (string $group, array $post_data): void {
if ($group === 'vcp_sms_settings') {
// Re-validate SMS credentials
}
}, 10, 2);
vcp_settings_fields_{tab}
Fired within each settings tab template during rendering. Replace {tab} with the tab slug.
- Parameter:
string $group_key— the option group key for the current tab.
Usage: Add custom fields to an existing or custom settings tab.
add_action('vcp_settings_fields_my_custom_tab', function (string $group_key): void {
echo '<tr>';
echo '<th><label for="my_field">My Field</label></th>';
echo '<td><input type="text" id="my_field" name="my_field" /></td>';
echo '</tr>';
});
vcp_metabox_saved
Fired after a metabox saves its fields on a custom post type edit screen.
- Usage: Add custom post-save logic, such as updating related records or triggering notifications.
vcp_metabox_fields_after
Fired at the end of metabox field rendering.
- Usage: Append custom fields to an existing metabox without overriding its template.
vcp_cleanup_expired
Daily cron action that handles cleanup of expired data.
- Default behavior: Removes expired OTP tokens, expired customer sessions, and other stale data.
- Usage: Hook into this action to add your own daily cleanup tasks.
add_action('vcp_cleanup_expired', function (): void {
// Custom daily cleanup logic
});
WordPress Hooks Used by VetCarePress
VetCarePress hooks into the following standard WordPress actions during its lifecycle:
| Hook | Purpose |
|---|---|
plugins_loaded |
Plugin boot, version check, upgrade routines |
init |
Register custom post types, taxonomies, rewrite rules |
rest_api_init |
Register all REST API routes |
admin_menu |
Register admin pages and menu items |
admin_init |
Register settings, handle admin form submissions |
Best Practices
- Always check that VetCarePress is active before referencing its hooks. Use
class_exists('VetCarePressPlugin')or checkdefined('VCP_VERSION'). - Place custom hook code in a separate plugin or in your theme’s
functions.phpto ensure it persists across VetCarePress updates. - Use appropriate priority values (default is 10) to control execution order when multiple callbacks are attached to the same hook.
See also: Developer Reference, REST API, Roles & Capabilities
Template Reference
Template Reference
VetCarePress uses a template system that allows theme developers to override any frontend template without modifying plugin files.
Template Override System
- Plugin templates: Located in
vetcarepress/templates/frontend/. - Theme overrides: Copy any template to
your-theme/vetcarepress/and modify it. - Priority: The plugin checks for a theme override first. If no override exists, the bundled plugin template is used.
Template List
Page Templates
| Template File | Purpose |
|---|---|
customer-login.php |
OTP/PIN login form for customers |
staff-login.php |
Staff login form |
customer-dashboard.php |
Customer dashboard layout |
customer-view.php |
Customer view of a single patient |
staff-dashboard.php |
Staff dashboard layout |
Patient View Templates
| Template File | Purpose |
|---|---|
patient-view.php |
Patient profile (router — selects layout variant) |
patient-view--tabs.php |
Tabs layout variant |
patient-view--sidebar.php |
Sidebar layout variant |
patient-view--card.php |
Card layout variant |
Record Templates
| Template File | Purpose |
|---|---|
medical-record-view.php |
Single medical record detail view |
Partial Templates
Partials are included by the main templates and handle specific sections of the UI.
| Template File | Purpose |
|---|---|
partials/patient-header.php |
Patient info header/sidebar |
partials/patient-tab-overview.php |
Overview tab content |
partials/patient-tab-clinical-notes.php |
Clinical notes tab |
partials/patient-tab-diagnoses.php |
Diagnoses tab |
partials/patient-tab-laboratory.php |
Lab results tab |
partials/patient-tab-imaging.php |
Imaging tab |
partials/patient-tab-treatments.php |
Treatments tab |
partials/patient-tab-vaccinations.php |
Vaccinations tab |
partials/patient-tab-messages.php |
Messages tab |
partials/patient-weight-graph.php |
Weight chart and measurement table |
partials/patient-temperature-history.php |
Temperature history display |
partials/patient-pagination.php |
Pagination controls |
partials/customer-messages.php |
Customer-facing message view |
partials/staff-customer-messages.php |
Staff-facing message thread |
partials/bloodwork-marker-table.php |
Lab marker results table |
partials/medical-record-clinical-note.php |
Clinical note record rendering |
partials/medical-record-diagnose.php |
Diagnose record rendering |
partials/medical-record-imaging.php |
Imaging record rendering |
partials/medical-record-lab-result.php |
Lab result record rendering |
partials/medical-record-treatment.php |
Treatment record rendering |
partials/medical-record-vaccination.php |
Vaccination record rendering |
Override Example
To override the customer login template:
- Create a
vetcarepressdirectory inside your active theme folder. - Copy
wp-content/plugins/vetcarepress/templates/frontend/customer-login.phptowp-content/themes/your-theme/vetcarepress/customer-login.php. - Edit the copied file as needed.
For partial templates, maintain the subdirectory structure:
wp-content/themes/your-theme/vetcarepress/partials/patient-header.php
Guidelines for Template Overrides
- Maintain variable names: Templates receive specific variables from the plugin. Do not rename or remove expected variables, as this will cause errors.
- Preserve structure: Keep the same general HTML structure to ensure JavaScript interactions continue to work. VetCarePress frontend JS binds to specific CSS classes and data attributes.
- Check for updates: After updating VetCarePress, review the changelog for template changes. Compare your overridden templates against the new plugin versions to incorporate any structural updates or new variables.
- Partial independence: You can override individual partials without overriding the parent template. For example, override only
partials/patient-tab-overview.phpto customize the overview tab while keeping all other tabs at their defaults.
See also: Developer Reference, Custom Post Types, REST API
Database Tables
Database Tables
VetCarePress creates 7 custom database tables to store customer data, authentication tokens, sessions, notifications, share links, and messages. All tables use the standard WordPress table prefix (e.g., wp_).
Tables are created on plugin activation using dbDelta() for safe creation and upgrades. Schema upgrades are applied automatically on plugins_loaded when the plugin version changes.
wp_vcp_customers
Stores customer (pet owner) records. Customers do not require WordPress user accounts.
| Column | Type | Description |
|---|---|---|
| id | BIGINT UNSIGNED AUTO_INCREMENT | Primary key |
| first_name | VARCHAR(100) | First name |
| last_name | VARCHAR(100) | Last name |
| phone | VARCHAR(30) | Phone number |
| phone_country_prefix | VARCHAR(10) | Country code (e.g., +1, +44) |
| VARCHAR(200) | Email address | |
| address_line1 | VARCHAR(255) | Address line 1 |
| address_line2 | VARCHAR(255) | Address line 2 |
| city | VARCHAR(100) | City |
| state | VARCHAR(100) | State/Province |
| postal_code | VARCHAR(20) | Postal code |
| country | VARCHAR(100) | Country |
| pin | VARCHAR(255) | Hashed PIN for quick login |
| notes | TEXT | Admin notes |
| created_at | DATETIME | Creation timestamp |
| updated_at | DATETIME | Last update (auto-updated) |
Indexes: phone, email, (last_name, first_name)
wp_vcp_otp_tokens
Stores one-time password tokens for customer authentication.
| Column | Type | Description |
|---|---|---|
| id | BIGINT UNSIGNED | Primary key |
| customer_id | BIGINT UNSIGNED | FK to customers |
| code | VARCHAR(64) | OTP code |
| channel | ENUM(‘sms’,’email’) | Delivery channel |
| destination | VARCHAR(200) | Email address or phone number |
| expires_at | DATETIME | Code expiry time |
| used_at | DATETIME | When used (NULL if unused) |
| created_at | DATETIME | Creation timestamp |
Indexes: customer_id, (destination, code, expires_at)
wp_vcp_customer_sessions
Tracks active customer sessions created after successful OTP or PIN verification.
| Column | Type | Description |
|---|---|---|
| id | BIGINT UNSIGNED | Primary key |
| customer_id | BIGINT UNSIGNED | FK to customers |
| token | VARCHAR(128) | Session token (UNIQUE) |
| ip_address | VARCHAR(45) | Client IP address |
| user_agent | VARCHAR(500) | Browser user agent string |
| expires_at | DATETIME | Session expiry time |
| created_at | DATETIME | Creation timestamp |
Indexes: token (UNIQUE), customer_id, expires_at
wp_vcp_notification_log
Records all outbound notifications (email and SMS) with delivery status and provider details.
| Column | Type | Description |
|---|---|---|
| id | BIGINT UNSIGNED | Primary key |
| customer_id | BIGINT UNSIGNED | FK to customers (nullable) |
| channel | ENUM(‘sms’,’email’) | Delivery channel |
| destination | VARCHAR(200) | Recipient address or number |
| message | TEXT | Message content |
| status | ENUM(‘sent’,’failed’) | Delivery status |
| error_message | TEXT | Error details (nullable) |
| provider_response | TEXT | Raw provider response (nullable) |
| created_at | DATETIME | Send timestamp |
Indexes: customer_id, (channel, status), created_at
wp_vcp_share_tokens
Stores share links for patient profiles, allowing external access without authentication.
| Column | Type | Description |
|---|---|---|
| id | BIGINT UNSIGNED | Primary key |
| patient_id | BIGINT UNSIGNED | FK to patient post |
| token | VARCHAR(64) | Share token (UNIQUE) |
| expires_at | DATETIME | Expiry time (nullable = never expires) |
| revoked_at | DATETIME | Revocation time (nullable) |
| created_by | BIGINT UNSIGNED | WordPress user ID of creator |
| created_at | DATETIME | Creation timestamp |
Indexes: token (UNIQUE), patient_id
wp_vcp_record_share_tokens
Stores share links for individual medical records. Same structure as wp_vcp_share_tokens but references a record instead of a patient.
| Column | Type | Description |
|---|---|---|
| id | BIGINT UNSIGNED | Primary key |
| record_id | BIGINT UNSIGNED | FK to medical record post |
| token | VARCHAR(64) | Share token (UNIQUE) |
| expires_at | DATETIME | Expiry time (nullable = never expires) |
| revoked_at | DATETIME | Revocation time (nullable) |
| created_by | BIGINT UNSIGNED | WordPress user ID of creator |
| created_at | DATETIME | Creation timestamp |
Indexes: token (UNIQUE), record_id
wp_vcp_messages
Stores messages exchanged between staff and customers, optionally associated with a patient.
| Column | Type | Description |
|---|---|---|
| id | BIGINT UNSIGNED | Primary key |
| customer_id | BIGINT UNSIGNED | FK to customers |
| patient_id | BIGINT UNSIGNED | FK to patient post (nullable) |
| sender_type | ENUM(‘staff’,’customer’) | Who sent the message |
| sender_id | BIGINT UNSIGNED | WordPress user ID or customer ID |
| message | TEXT | Message content |
| is_read | TINYINT(1) | Read flag (0 = unread, 1 = read) |
| read_at | DATETIME | When read (nullable) |
| channel | ENUM(‘web’,’email’,’sms’) | Origin channel |
| external_ref | VARCHAR(255) | External reference ID (nullable) |
| created_at | DATETIME | Send timestamp |
Indexes: customer_id, patient_id, (customer_id, sender_type, is_read), created_at
See also: Developer Reference, Custom Post Types, REST API
Custom Post Types
Custom Post Types
VetCarePress registers 9 custom post types for managing patients, medical records, vaccinations, and laboratory data. All CPTs are registered during the init action.
| CPT Slug | Label | Public | Gutenberg | Purpose |
|---|---|---|---|---|
vcp_patient |
Patients | Yes (virtual URLs) | No | Pet profiles |
vcp_medical_record |
Medical Records | No | No | Clinical records (5 types) |
vcp_vaccination |
Vaccinations | No | No | Vaccination records |
vcp_lab_panel |
Blood Panels | No | No | Bloodwork panel definitions |
vcp_lab_marker |
Blood Markers | No | No | Bloodwork marker definitions |
vcp_urine_panel |
Urine Panels | No | No | Urine panel definitions |
vcp_urine_marker |
Urine Markers | No | No | Urine marker definitions |
vcp_stool_panel |
Stool Panels | No | No | Stool panel definitions |
vcp_stool_marker |
Stool Markers | No | No | Stool marker definitions |
All CPTs use 'show_in_rest' => false for the default WordPress REST API. VetCarePress provides its own REST controllers for data access. Gutenberg is disabled for all VCP post types via the use_block_editor_for_post_type filter.
Detailed Reference
vcp_patient
Pet profiles linked to customer records.
- Supports:
title,thumbnail - Public: Yes — accessible via virtual URLs (configurable slug in Settings > Advanced)
- Taxonomies:
vcp_species - Custom capabilities: Uses VCP capability mapping (
vcp_manage_patients) - Auto-generated title: Composed from pet name and species
- Key meta fields:
_vcp_owner_id— FK to customer record_vcp_birthdate— Date of birth_vcp_sex— Sex (male, female, neutered male, spayed female)_vcp_color— Coat/color description_vcp_microchip— Microchip number_vcp_photo_id— Attachment ID for patient photo_vcp_notes— Internal notes_vcp_deceased— Boolean flag indicating the patient is deceased_vcp_deceased_date— Date of death
vcp_medical_record
Clinical records attached to a patient. Supports 5 record types: clinical notes, diagnoses, medical imaging, treatments, and lab results.
- Supports:
title,editor - Public: No
- Taxonomies: None
- Custom capabilities: Uses VCP capability mapping (varies by record type)
- Auto-generated title: Composed from record type, patient name, and date
- Key meta fields:
_vcp_patient_id— FK to patient post_vcp_record_type— Type:clinical-note,diagnose,lab-result,medical-imaging,treatment_vcp_record_date— Date of the record_vcp_description— Record description/content_vcp_staff_id— WordPress user ID of the creating staff member_vcp_clinical_note_attachment— Attachment IDs for clinical note records_vcp_diagnosis_attachment— Attachment IDs for diagnose records_vcp_lab_attachment— Attachment IDs for lab result records_vcp_imaging_attachment— Attachment IDs for imaging records_vcp_imaging_dicom— DICOM file attachment IDs (imaging records only)_vcp_treatment_attachment— Attachment IDs for treatment records
vcp_vaccination
Vaccination records linked to a patient with reminder scheduling.
- Supports:
title - Public: No
- Taxonomies:
vcp_vaccination_type,vcp_vaccine_product,vcp_vaccine_manufacturer - Custom capabilities: Uses VCP capability mapping (
vcp_manage_patients) - Auto-generated title: Composed from vaccine name and patient name
- Key meta fields:
_vcp_patient_id— FK to patient post_vcp_vaccine_name— Name of the vaccine_vcp_vaccination_date— Date administered_vcp_next_due_date— Next vaccination due date_vcp_batch_number— Vaccine batch/lot number_vcp_administered_by— Staff member who administered_vcp_notes— Additional notes
vcp_lab_panel
Defines groupings of blood markers (e.g., "Complete Blood Count", "Liver Panel").
- Supports:
title - Public: No
- Taxonomies:
vcp_species(panels are species-specific) - Custom capabilities: Uses VCP capability mapping (
vcp_manage_laboratory) - Key meta fields:
_vcp_panel_order— Display order
vcp_lab_marker
Individual blood marker definitions within a panel (e.g., "WBC", "RBC", "ALT").
- Supports:
title - Public: No
- Taxonomies: None
- Custom capabilities: Uses VCP capability mapping (
vcp_manage_laboratory) - Key meta fields:
_vcp_panel_id— FK to lab panel post_vcp_unit— Unit of measurement_vcp_min_value— Reference range minimum_vcp_max_value— Reference range maximum_vcp_marker_order— Display order within panel
vcp_urine_panel
Defines groupings of urine test markers. Structure mirrors vcp_lab_panel.
- Supports:
title - Public: No
- Taxonomies:
vcp_species - Custom capabilities: Uses VCP capability mapping (
vcp_manage_laboratory) - Key meta fields:
_vcp_panel_order— Display order
vcp_urine_marker
Individual urine marker definitions. Structure mirrors vcp_lab_marker.
- Supports:
title - Public: No
- Taxonomies: None
- Custom capabilities: Uses VCP capability mapping (
vcp_manage_laboratory) - Key meta fields:
_vcp_panel_id— FK to urine panel post_vcp_unit— Unit of measurement_vcp_min_value— Reference range minimum_vcp_max_value— Reference range maximum_vcp_marker_order— Display order within panel
vcp_stool_panel
Defines groupings of stool test markers. Structure mirrors vcp_lab_panel.
- Supports:
title - Public: No
- Taxonomies:
vcp_species - Custom capabilities: Uses VCP capability mapping (
vcp_manage_laboratory) - Key meta fields:
_vcp_panel_order— Display order
vcp_stool_marker
Individual stool marker definitions. Structure mirrors vcp_lab_marker.
- Supports:
title - Public: No
- Taxonomies: None
- Custom capabilities: Uses VCP capability mapping (
vcp_manage_laboratory) - Key meta fields:
_vcp_panel_id— FK to stool panel post_vcp_unit— Unit of measurement_vcp_min_value— Reference range minimum_vcp_max_value— Reference range maximum_vcp_marker_order— Display order within panel
Metabox Classes
Each CPT has an associated metabox class that handles the admin editing UI. Metabox classes:
- Render form fields on the post edit screen
- Save meta data on
save_post - Fire
vcp_metabox_savedafter saving - Fire
vcp_metabox_fields_afterat the end of field rendering
See also: Developer Reference, Database Tables, Hooks & Filters, REST API