Contents

Hooks reference - Plugixa Car Parking

The plugin fires 24 actions and 59 filters. All of them are prefixed plugixa_carparking_. One action is fired only by a Pro module and is marked PRO.

The Pro features are built on these same hooks. Extras, tax, pricing rules, deposits, the card gateways and the SMS and Telegram channels are ordinary listeners on the hooks below, so anything they do, your code can do too.

The ones you are most likely to want

Hook Type What it is for
plugixa_carparking_booking_created action React to a new booking
plugixa_carparking_booking_cancelled action React to a customer cancelling
plugixa_carparking_payment_recorded action React to a payment or a refund
plugixa_carparking_entity_field_changed action React to a status change on any record
plugixa_carparking_base_charge filter Change the rate or the booking fee of a quote
plugixa_carparking_quote filter Change a finished quote
plugixa_carparking_public_request_captcha filter Put a CAPTCHA in front of the public routes
plugixa_carparking_client_ip filter Tell the rate limiter the real visitor address behind a proxy
plugixa_carparking_user_can filter Narrow or widen what a user may do

Entity slugs

Many hooks pass an entity slug. These are the slugs in use.

Slug Record
booking A booking
payment A payment or a refund
location A location
location_space A space at a location
space_type A space type
coupon A coupon
booking_form A booking form
booking_extra PRO An extra
tax_rate PRO A tax rate
pricing_rule PRO A pricing rule
customer_group PRO A customer group

Actions

Lifecycle

Action Arguments When it fires
plugixa_carparking_fs_loaded none While the main plugin file is read, after the Freemius SDK has been initialised. Attach from a must-use plugin, because it fires before plugins_loaded.
plugixa_carparking_loaded Container $container Once the plugin has booted on plugins_loaded, after every module has registered its hooks.
plugixa_carparking_activated none On activation, after the tables exist and the default settings are stored. The demo content is seeded on this action. It does not fire on an update.
plugixa_carparking_deactivated none On deactivation. Modules clear their scheduled events here.
plugixa_carparking_uninstall none During an uninstall that erases data, before the tables are dropped. See Privacy and uninstall.
plugixa_carparking_settings_saved array $settings After the settings option is saved.
add_action( 'plugixa_carparking_loaded', function ( $container ) {
	// The plugin is present and booted.
} );

REST and assets

Action Arguments When it fires
plugixa_carparking_register_rest_routes string $namespace, Container $container On rest_api_init, after the plugin has registered its own routes. $namespace is plugixa-car-parking/v1.
plugixa_carparking_register_gateways GatewayRegistry $registry The first time the list of payment gateways is needed. Call $registry->register( $gateway ).
plugixa_carparking_enqueue_assets string $hook_suffix After the admin app’s assets are enqueued on its own page.
plugixa_carparking_public_assets string $surface, string $handle, array $context After the script of a public page is enqueued. $surface is wizard, account or summary. $handle is the script handle to depend on.
plugixa_carparking_enqueue_public_styles PRO none Do this action to load the public stylesheet on a page the plugin does not recognise as its own. The map shortcode fires it.

Records

Every record table goes through one repository, so these fire for every entity in Entity slugs.

Action Arguments When it fires
plugixa_carparking_entity_created string $entity, int $id, array $data After a row is inserted.
plugixa_carparking_entity_field_changed string $entity, int $id, string $field, mixed $new_value, mixed $old_value Once for each scalar column that changed in an update, before entity_updated.
plugixa_carparking_entity_updated string $entity, int $id, array $data, array $old After a row is updated. $data holds the applied changes.
plugixa_carparking_before_delete string $entity, int $id, array $old Before a row is moved to the trash.
plugixa_carparking_entity_deleted string $entity, int $id, array $old After a row is moved to the trash. It can still be restored.
plugixa_carparking_entity_restored string $entity, int $id, array $row After a row is brought back from the trash.
plugixa_carparking_before_purge string $entity, int $id, array $row Before a row is deleted permanently.
plugixa_carparking_entity_purged string $entity, int $id, array $row After a row is deleted permanently.

There is no separate “status changed” action. Listen for the status column:

add_action(
	'plugixa_carparking_entity_field_changed',
	function ( $entity, $id, $field, $new_value, $old_value ) {
		if ( 'booking' === $entity && 'status' === $field ) {
			// Booking $id moved from $old_value to $new_value.
		}
	},
	10,
	5
);

Bookings, payments and messages

Action Arguments When it fires
plugixa_carparking_booking_created array $booking After a booking is stored and the location’s lock is released. The booking emails are sent from this action.
plugixa_carparking_booking_cancelled array $booking When a customer cancels their own booking from the account page.
plugixa_carparking_booking_repriced int $booking_id, float $previous After a booking has been moved to new dates and priced again. $previous is the total before.
plugixa_carparking_payment_recorded array $booking, float $paid After a payment or refund is recorded and the booking’s paid state has been worked out again. $paid is the total paid so far.
plugixa_carparking_booking_notify array $booking, array $context, string $event, LogTable $log After the emails for a booking event are sent. Use it to deliver the same event another way. $context maps each placeholder to its value. $event is booking_created, payment_received, or an event a module announces.
add_action( 'plugixa_carparking_booking_created', function ( $booking ) {
	error_log( 'New booking ' . $booking['booking_ref'] );
} );

Filters

Pricing and quotes

These run every time a price is worked out: in the wizard, in the admin booking form and when a booking is saved. See Pricing for the order.

Filter Value and arguments Purpose
plugixa_carparking_quote_request_fields array $carried, array $input Claim a field of a booking request so it reaches the quote. Return field => cleaned value.
plugixa_carparking_requote_fields array $fields, array $booking, array $items Rebuild those request fields from a stored booking when it is priced again.
plugixa_carparking_base_charge array $base, array $context Adjust the per-unit rate or the booking fee before anything else is added. $base has use_type, units, unit_price, initial_fee, subtotal and optionally adjustments.
plugixa_carparking_quote_lines_before_discount array $items, array $request, array $stay Add priced lines to the subtotal, ahead of the coupon. $stay has quantity, days and hours.
plugixa_carparking_quote_lines_after_discount array $items, float $amount, int $location_id Add priced lines on top of the discounted amount. Tax is added here.
plugixa_carparking_quote_due_now float $due_now, float $total, array $settings, array $request The part of the total to take now. 0 means the whole amount is due. $settings is the location’s own settings.
plugixa_carparking_quote_line_totals array $groups Name a total of some line types: total key => line types. The sum is worked out from the lines.
plugixa_carparking_quote array $quote, array $request Adjust the finished quote.
plugixa_carparking_payment_charge array $charge, array $booking, string $requested What a customer is charged when they start an online payment. $charge has amount and type.
plugixa_carparking_inventory_strategies array $strategies Register another way of counting a location’s spaces: inventory mode => InventoryStrategy.
plugixa_carparking_availability_response array $data, int $location_id, string $entry, string $exit Add to what the booking form is told about a location and a window. The form’s own four keys are restored if removed.

An adjustment made on plugixa_carparking_base_charge should name itself, so the line shows the price before the change and the reason for it:

add_filter(
	'plugixa_carparking_base_charge',
	function ( $base, $context ) {
		$base['unit_price']   -= 1.00;
		$base['adjustments'][] = array(
			'target' => 'unit_price',
			'label'  => 'Member rate',
			'amount' => -1.00,
		);

		return $base;
	},
	10,
	2
);

Public pages and abuse protection

Filter Value and arguments Purpose
plugixa_carparking_rate_limits array $limits The rate limits of the public routes: action => array( requests, seconds ). An unusable entry falls back to the built-in limit.
plugixa_carparking_public_request_captcha `true false
plugixa_carparking_client_ip string $ip The address a public request is counted against. The default is REMOTE_ADDR only.
plugixa_carparking_public_style_tags array $tags The shortcode tags whose presence on a page loads the public stylesheet.
plugixa_carparking_public_datepicker bool $needed, string $surface Whether a public page loads the date picker. True for the wizard by default.
plugixa_carparking_status_labels array $labels, string $kind The labels a public page shows for stored statuses. $kind is booking or payment.
plugixa_carparking_summary_actions array $actions, string $ref Extra links beside the print button on the booking summary. Each entry is array( 'url' => ..., 'label' => ... ).
plugixa_carparking_allowed_html array $allowed, string $context The wp_kses() allowlist for what a public page prints.
plugixa_carparking_content_allowed_html array $allowed The allowlist for text an administrator wrote, such as payment instructions. Starts from what a post may contain.
plugixa_carparking_invoice_total_rows array $rows, array $booking, array $invoice Rows shown in the invoice totals between the discount and the total. Each row is array( 'label' => ..., 'amount' => ... ).

The rate limiter reads REMOTE_ADDR. Behind Cloudflare or a load balancer every visitor shares the proxy’s address, so tell it which header to trust:

add_filter( 'plugixa_carparking_client_ip', function ( $ip ) {
	if ( ! empty( $_SERVER['HTTP_CF_CONNECTING_IP'] ) ) {
		$candidate = sanitize_text_field( wp_unslash( $_SERVER['HTTP_CF_CONNECTING_IP'] ) );

		return filter_var( $candidate, FILTER_VALIDATE_IP ) ? $candidate : $ip;
	}

	return $ip;
} );

Only do this when the proxy is the one way into the site. A header is something any visitor can send.

Emails and messages

Filter Value and arguments Purpose
plugixa_carparking_email_template array $template, string $event, array $booking The subject and body of the customer’s email for an event, as array( $subject, $body ). An empty subject sends nothing.
plugixa_carparking_email_attachments array $attachments, array $booking, string $event Absolute paths of files to attach to the customer’s email. A file under the system’s temporary directory is deleted after sending.
plugixa_carparking_notification_channel_labels array $labels The names of the channels shown in the message log: channel id => name.

Permissions

Filter Value and arguments Purpose
plugixa_carparking_user_can bool $allowed, string $action, string $entity_type, `array null $record, int $user_id`
plugixa_carparking_capabilities array $map The capability map handed to the admin app. It hides controls only: every route asks again on the server.
plugixa_carparking_unreadable_fields array $denied, string $entity_type, int $user_id Fields of an entity the current user may not filter by.
plugixa_carparking_filter_output mixed $data, string $entity_type A successful REST payload of the admin routes before it is sent. The one place field-level access can be enforced.
plugixa_carparking_query_clauses array $clauses, string $entity_type, string $context, int $user_id, string $table Extra join, where and params for a list query. Use it to narrow a list to the records a user may see.
plugixa_carparking_load_record `array null $record, string $entity_type, int $id`
// Let a custom check decide who may delete bookings.
add_filter(
	'plugixa_carparking_user_can',
	function ( $allowed, $action, $entity_type, $record, $user_id ) {
		if ( 'booking' === $entity_type && 'delete' === $action ) {
			return user_can( $user_id, 'manage_options' );
		}

		return $allowed;
	},
	10,
	5
);

Records

Filter Value and arguments Purpose
plugixa_carparking_before_insert array $data, string $entity A row’s data immediately before insert.
plugixa_carparking_before_update array $data, string $entity, int $id, array $old A row’s data immediately before update.
plugixa_carparking_can_delete bool $allowed, string $entity, int $id, array $old Veto moving a row to the trash. Return anything but true to refuse.
plugixa_carparking_can_purge bool $allowed, string $entity, int $id, array $row Veto a permanent delete. Return anything but true to refuse.
plugixa_carparking_location_delete_blockers array $blockers, int $id, array $location Reasons a location must not be trashed, as sentences. A non-empty list refuses with status 409.
plugixa_carparking_location_space_delete_blockers array $blockers, int $id, array $space The same for a space.
plugixa_carparking_space_type_delete_blockers array $blockers, int $id, array $type The same for a space type.
plugixa_carparking_coupon_delete_blockers array $blockers, int $id, array $coupon The same for a coupon.
plugixa_carparking_booking_form_delete_blockers array $blockers, int $id, array $form The same for a booking form.
plugixa_carparking_booking_export_columns array $columns The columns of the bookings CSV export, in order: booking field => heading.
plugixa_carparking_form_step_keys array $keys The steps a booking form can be built from. The form’s own steps cannot be removed.

Lists, search and the entity registry

Filter Value and arguments Purpose
plugixa_carparking_entity_types array $entities Register an entity: slug => descriptor.
plugixa_carparking_entity_fields array $fields, string $slug The field definitions of one entity.
plugixa_carparking_record_writers array $writers Register generic write access to an entity: slug => array( 'create' => callable, 'update' => callable, 'delete' => callable ). Mass actions use it.
plugixa_carparking_record_names array $names, string $entity, array $ids The display name behind each id of an entity, as id => name.
plugixa_carparking_filterable_fields array $fields, string $entity_type What a list of this entity may be filtered by.
plugixa_carparking_filter_api_bases array $map URL segment to filter slug mappings, for lists that are not registered entities.
plugixa_carparking_search_fragments array $fragments, string $entity_type, string $term, string $context Extra OR conditions for a search. Each entry is array( 'sql' => ..., 'params' => array( ... ) ), with placeholders in the same order as the parameters.

Settings and the admin app

Filter Value and arguments Purpose
plugixa_carparking_settings_schema array $schema The settings that exist and the type that cleans each one. A key the schema does not list is dropped from a save.
plugixa_carparking_settings_defaults array $defaults The value each setting starts with.
plugixa_carparking_sanitize_settings array $clean, array $input Adjust settings after each has been cleaned. For a rule that spans several settings.
plugixa_carparking_settings_choices array $choices The lists a settings control offers, keyed by control.
plugixa_carparking_config_settings_keys array $keys Which settings reach every user of the app. Secrets are always removed.
plugixa_carparking_admin_config array $config What the admin app is told at start-up. It is printed into the page, so never add a credential.
plugixa_carparking_bootstrap_payload array $payload The admin app’s first REST payload.
plugixa_carparking_admin_i18n_strings array $strings The admin app’s strings: key => translated text.
plugixa_carparking_admin_menu_links array $links The shortcuts under the Car Parking menu item: app route => label.
plugixa_carparking_modules array $classes The module classes to load. Each must implement PlugixaCarParking\Core\Modules\ModuleInterface.
plugixa_carparking_legacy_route_aliases array $paths The route paths kept answering on the old plugixacarparking/v1 namespace. See REST API.

Adding a setting takes two filters, one for the type and one for the default:

add_filter( 'plugixa_carparking_settings_schema', function ( $schema ) {
	$schema['gate_code'] = array( 'type' => 'text' );

	return $schema;
} );

add_filter( 'plugixa_carparking_settings_defaults', function ( $defaults ) {
	$defaults['gate_code'] = '';

	return $defaults;
} );

The setting types are text, textarea, css, email, int (with optional min and max), bool, choice (with options and default), keys, map and secret. A secret is stored encrypted and is never sent back to a browser.

Deprecated hook names

An earlier line of the plugin mixed two prefixes. These old names still fire, straight after the current one, and WordPress reports each use as deprecated when debugging is on. Rename any listener to the current name.

Old name Current name Type
plugixacarparking_booking_created plugixa_carparking_booking_created action
plugixacarparking_booking_cancelled plugixa_carparking_booking_cancelled action
plugixacarparking_payment_recorded plugixa_carparking_payment_recorded action
plugixacarparking_base_charge plugixa_carparking_base_charge filter
plugixacarparking_quote plugixa_carparking_quote filter
plugixa_carparking_quote_extras PRO plugixa_carparking_quote_lines_before_discount filter
plugixa_carparking_location_extras PRO plugixa_carparking_availability_response filter
plugixa_carparking_quote_taxes PRO plugixa_carparking_quote_lines_after_discount filter
plugixa_carparking_quote_deposit PRO plugixa_carparking_quote_due_now filter

The four Pro names run at priority 1000 on the current filter, so a listener on an old name has the last word.

Scheduled events

Cron hook Schedule What it does
plugixa_carparking_expire_holds Hourly Expires pending bookings whose hold has run out. See Availability.

The Pro reminders and reports schedule their own events. See Reminders and reports.

Quick Links