Contents

Hooks - Plugixa Car Rental

Every hook the plugin fires starts with plugixa_car_rental_. This page lists the ones you are likely to use from a theme’s functions.php or a small plugin of your own. Hooks that exist only to connect the plugin’s own modules to each other are left out.

Hooks fired only by a Pro module are marked PRO. Everything else fires in both editions. Several Pro features (pricing rules, tax, driver age, delivery) are ordinary listeners on the pricing filters below, so your code can do what they do.

The ones you are most likely to want

Hook Type What it is for
plugixa_car_rental_booking_created action React to a new booking
plugixa_car_rental_booking_status_changed action React to a booking being confirmed, picked up, returned, cancelled and so on
plugixa_car_rental_booking_cancelled_by_customer action React to a customer cancelling from the booking page
plugixa_car_rental_payment_recorded action React to money coming in or going out
plugixa_car_rental_wizard_config filter Change how one booking form starts, such as the desk it opens on
plugixa_car_rental_quote_lines filter Add a charge to every quote
plugixa_car_rental_quote filter Change a finished quote, or refuse a car for a request
plugixa_car_rental_email filter Rewrite or stop a booking email
plugixa_car_rental_confirm_refusal filter Stop a booking being confirmed
plugixa_car_rental_public_request_captcha filter Add an anti-spam check to the public routes
plugixa_car_rental_public_request_refusal filter Refuse a public search or hold that is missing an answer
plugixa_car_rental_client_ip filter Tell the rate limiter the real visitor address behind a proxy
plugixa_car_rental_user_can filter Narrow or widen what a staff member may do
plugixa_car_rental_privacy_keep_booking filter Keep a finished booking out of the personal data eraser

Booking statuses

Status hooks pass these values.

Status Meaning
pending Made, not yet confirmed. A booking from the site holds its car until the hold time runs out.
confirmed Confirmed. The customer and your desk are emailed.
picked_up The car is out.
returned The car is back.
completed Closed. The invoice is issued at this point.
cancelled Cancelled by the customer or by your desk.
no_show The customer did not come.
expired The hold ran out before the booking was finished.

Bookings and payments

Action Arguments When it fires
plugixa_car_rental_booking_created array $booking A booking was created, as pending, from the site or the desk. The booking includes its price lines.
plugixa_car_rental_booking_status_changed int $id, string $from, string $to, array $booking A booking moved from one status to another. $booking is the booking as it now is.
plugixa_car_rental_booking_cancelled_by_customer array $booking, array $terms A customer cancelled their own booking from the booking page. $terms holds fee, refund and free.
plugixa_car_rental_payment_recorded array $booking, float $paid A payment or a refund was recorded and the booking’s paid state worked out again. $paid is what it now holds in total.
plugixa_car_rental_payment_unplaced array $booking, WP_Error $error Money arrived for a booking that could no longer be confirmed: its hold ran out and the car went to somebody else, or a plugixa_car_rental_confirm_refusal listener refused it. (A used-up coupon does not: a paid booking keeps its discount.) The payment is recorded; your desk refunds or rebooks.
plugixa_car_rental_payment_notice string $notice, array $booking, string $gateway, array $data A payment provider reported something that moves no money, such as checkout_expired, payment_processing, payment_failed, dispute_opened, dispute_closed or refund_failed. Fired by the Stripe and PayPal modules.
plugixa_car_rental_invoice_issued array $invoice, array $booking An invoice was issued. This happens when a booking is completed.
plugixa_car_rental_message_sent PRO true|WP_Error $result, string $channel, string $status, array $booking A text message or Telegram alert was sent, or failed to be.
plugixa_car_rental_inspection_signed PRO array $inspection, array $booking A pickup or return inspection was signed and its agreement stored.

Send every confirmed booking to another system:

add_action( 'plugixa_car_rental_booking_status_changed', function ( $id, $from, $to, $booking ) {
	if ( 'confirmed' !== $to ) {
		return;
	}

	wp_remote_post( 'https://example.com/hooks/rentals', array(
		'body' => array(
			'reference' => $booking['reference'],
			'pickup'    => $booking['pickup_at'],
			'return'    => $booking['return_at'],
		),
	) );
}, 10, 4 );

Warn your desk when a payment could not be placed:

add_action( 'plugixa_car_rental_payment_unplaced', function ( $booking, $error ) {
	wp_mail(
		get_option( 'admin_email' ),
		'Payment needs attention: ' . $booking['reference'],
		$error->get_error_message()
	);
}, 10, 2 );

Refusing a confirmation

Filter Value Other arguments What it is for
plugixa_car_rental_confirm_refusal null|WP_Error $refusal array $booking Asked just before a pending booking is confirmed, whoever confirms it: the booking form, an online payment, or your desk. Return null to let it go ahead, or a WP_Error to refuse it. $booking is the booking about to be confirmed, with its price lines in line_items. A refusal changes nothing: the booking stays pending and the error goes back to whoever asked.

It is for a condition that was true when the car was held and may have stopped being true since. The Coupons app uses it to refuse a booking whose coupon was used up while it was held. Pass on a refusal you were given, so you do not undo another module’s answer. Put the form field the message is about in the error’s data as field, and the booking form shows it there.

Refuse to confirm a rental of more than 28 days without a deposit paid:

add_filter( 'plugixa_car_rental_confirm_refusal', function ( $refusal, $booking ) {
	if ( null !== $refusal ) {
		return $refusal;
	}

	if ( (int) $booking['billable_days'] > 28 && (float) $booking['amount_paid'] <= 0 ) {
		return new WP_Error(
			'my_long_rental_unpaid',
			'Rentals of more than four weeks must be paid in part before they are confirmed.',
			array( 'status' => 409 )
		);
	}

	return null;
}, 10, 2 );

The booking form

Filter Arguments What it is for
plugixa_car_rental_wizard_config array $config What one booking form is handed when its page is drawn, by the block or the shortcode. Runs once for each form on the page.

$config holds:

Key Holds
apiUrl The address of the plugin’s REST routes, with a trailing slash
locale The visitor’s language, such as pt-PT, for dates and money
currency Your main currency code
location The ID of the desk the form opens on: the location attribute, else the ?pcr_location= link, else 0 for the first desk that takes pickups
i18n The form’s words, by key
locationPicker PRO Added by the Map at the default priority, when the form shows the map of desks. Remove it to leave the map out of one form.

The form is drawn in the visitor’s browser from this array, so whatever you return is written into the page. Put nothing private in it. A page cache keeps the result, so base it on the page, not on the visitor.

Open the form on the desk with ID 3, without the map, on the page with the slug cascais:

add_filter( 'plugixa_car_rental_wizard_config', function ( array $config ): array {
	if ( is_page( 'cascais' ) ) {
		$config['location'] = 3;
		unset( $config['locationPicker'] );
	}

	return $config;
}, 20 );

Use a priority above 10, as here, so your filter runs after the map has added its part. Removing locationPicker this way hides the map, but Google’s script has already been asked for on that page. To keep Google off the page entirely, turn off Show a map to choose the pickup desk in the booking form under Settings -> Map.

Prices

A quote is built in four steps, and each has a filter. The three line filters work in the site’s currency. When a customer books in another currency PRO, the quote has already been converted by the time plugixa_car_rental_quote runs, and its currency says which.

Filter Value Other arguments What it is for
plugixa_car_rental_quote_lines array $lines array $context Charges added before any discount: extras, a surcharge, a delivery fee.
plugixa_car_rental_quote_discounts array $lines (empty) float $subtotal, array $context Discounts. Only lines with a negative total are kept, and the discount never goes past the subtotal.
plugixa_car_rental_quote_lines_after_discount array $lines (empty) float $net, array $context Charges on the discounted amount, such as tax. A line with 'included' => true is tax already inside the price: it is shown, and not added a second time.
plugixa_car_rental_quote array $quote array $context The finished quote.

Each line needs type, label and a numeric total. You may also give quantity and unit_price. Anything without the three required keys is dropped.

$context holds window (the rental: pickup and return locations and times, and days, the number of days charged), model (the vehicle model’s row), request and currency.

Add a cleaning fee to every rental of a Premium model:

add_filter( 'plugixa_car_rental_quote_lines', function ( $lines, $context ) {
	if ( 4 === (int) $context['model']['category_id'] ) { // Your Premium category's id.
		$lines[] = array(
			'type'  => 'cleaning',
			'label' => 'Premium valet',
			'total' => 25,
		);
	}

	return $lines;
}, 10, 2 );

Refusing a car

On the finished quote, set refusal to a sentence to stop a car being booked for this request. The car is still listed and priced, with your sentence beside it, and holding it is refused in the same words. Add refusal_field to name the form field the reason is about. With 'refusal_scope' => 'request' the reason applies to the whole search instead, and the form shows that one message at the named field instead of a list of refused cars.

add_filter( 'plugixa_car_rental_quote', function ( $quote, $context ) {
	if ( $context['window']->days > 21 && 'Mercedes V-Class' === $context['model']['name'] ) {
		$quote['refusal'] = 'The V-Class can be rented for three weeks at most.';
	}

	return $quote;
}, 10, 2 );

Change totals only together with the lines that explain them. The customer sees the lines.

Narrowing the cars

Filter Value Other arguments What it is for
plugixa_car_rental_availability_units array $candidates int $model_id, RentalWindow $window The cars that could serve a rental, before bookings and blocks are checked. You may remove cars from the list. A car of another model is dropped whatever you return.

Emails

Hook Type Arguments What it is for
plugixa_car_rental_email filter array $email, string $type, array $booking Rewrite a booking email. $email has to, subject and body (HTML). Return an empty to to stop it. $type is customer_confirmed, customer_cancelled, desk_confirmed, or customer_invoice PRO.
plugixa_car_rental_booking_payment_instructions filter string $text, array $booking The payment paragraph of the confirmation email.
plugixa_car_rental_booking_manage_url filter string $url, array $booking The link to the customer’s booking page, used in emails and messages. Empty when the customer portal is off or no page shows it.
plugixa_car_rental_before_send_mail action string|string[] $to, string $subject, array $options Just before the plugin hands an email to wp_mail(). Useful for logging.

Send the desk email to a second address and stop the cancellation email:

add_filter( 'plugixa_car_rental_email', function ( $email, $type, $booking ) {
	if ( 'desk_confirmed' === $type ) {
		$email['to'] = $email['to'] . ',fleet@example.com';
	}

	if ( 'customer_cancelled' === $type ) {
		$email['to'] = '';
	}

	return $email;
}, 10, 3 );

Public routes and abuse protection

The booking form and the customer booking page talk to routes under /wp-json/plugixa-car-rental/v1/public/. Visitors use them without signing in, so each one is rate limited per visitor address.

Filter Value Other arguments What it is for
plugixa_car_rental_public_request_captcha true string $token, string $action Refuse a public request. Return false, or a WP_Error to choose the status and message. $token is the request’s captcha_token, cleaned, or an empty string. $action names the route, such as public_search, public_hold, public_checkout or public_manage_find.
plugixa_car_rental_public_request_refusal null|WP_Error $refusal array $fields Asked before a public search and before a public hold. Return null to let it go ahead, or a WP_Error to refuse it. Not asked for desk bookings. See below.
plugixa_car_rental_client_ip string $ip none The address a public request is counted against. By default REMOTE_ADDR only.
plugixa_car_rental_public_options array $options none What the booking form loads before the visitor types anything: locations, gateways and more. Add only what any visitor may see.
plugixa_car_rental_portal_view array $view array $booking, string $token What the customer booking page shows for a booking. Add only what the holder of the booking’s link may see.

Behind a proxy or Cloudflare, every visitor arrives from the proxy’s address and they would all share one rate-limit counter. Read the trusted header instead, and only when your site really is behind that proxy, because anyone can send the header otherwise:

add_filter( 'plugixa_car_rental_client_ip', function ( $ip ) {
	$forwarded = $_SERVER['HTTP_CF_CONNECTING_IP'] ?? '';

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

The booking form does not send a captcha_token itself, so the CAPTCHA filter is for checks that need no token from the browser, or for your own front end that sends one.

Refusing a public search or hold

plugixa_car_rental_public_request_refusal is for an answer a visitor must give before cars are searched or held, when the browser’s “required” is not enough. The Driver age app PRO uses it to refuse a request without an age from 16 to 99.

$fields is not the request body. It holds only the fields the plugin’s modules claim for pricing, such as extras, coupon, driver_age PRO, currency PRO, delivery_address PRO and collection_address PRO, each already cleaned by the module that owns it. A field the visitor did not send is absent. Dates and locations are not in it. Pass on a refusal you were given, and put the form field in the error’s data as field so the form shows the message beside it.

With the Driver age app PRO on, turn away drivers under 21 before any car is searched, instead of showing every car with a minimum-age message:

add_filter( 'plugixa_car_rental_public_request_refusal', function ( $refusal, $fields ) {
	if ( null !== $refusal ) {
		return $refusal;
	}

	$age = (int) ( $fields['driver_age'] ?? 0 );

	if ( $age > 0 && $age < 21 ) {
		return new WP_Error(
			'my_driver_too_young',
			'We rent to drivers aged 21 and over.',
			array( 'status' => 422, 'field' => 'driver_age' )
		);
	}

	return null;
}, 10, 2 );

Payments

Hook Type Arguments What it is for
plugixa_car_rental_payment_gateways filter Gateway[] $gateways The payment methods on offer. Pay at pickup and bank transfer are built in; Stripe and PayPal add themselves here in Pro. A new gateway implements the plugin’s Gateway interface.
plugixa_car_rental_stripe_checkout_params PRO filter array $params, array $booking The parameters of the Stripe Checkout session before it is created. The mode, metadata, amounts and return addresses are put back as they were, so change only other options such as the locale.
add_filter( 'plugixa_car_rental_stripe_checkout_params', function ( $params, $booking ) {
	$params['locale'] = 'pt';

	return $params;
}, 10, 2 );

Permissions

Filter Value Other arguments What it is for
plugixa_car_rental_user_can bool $allowed string $action, string $entity_type, array|null $record, int $user_id Whether a user may do something to a kind of record. $action is read, create, edit, delete or export. $allowed is the answer from the user’s capabilities.
plugixa_car_rental_capabilities array $map none The capability map handed to the admin app, which decides what it draws.

Let a staff member read bookings but never export them:

add_filter( 'plugixa_car_rental_user_can', function ( $allowed, $action, $entity_type, $record, $user_id ) {
	if ( 'booking' === $entity_type && 'export' === $action && ! user_can( $user_id, 'manage_options' ) ) {
		return false;
	}

	return $allowed;
}, 10, 5 );

The capabilities themselves are plugixa_car_rental_manage, plugixa_car_rental_view, plugixa_car_rental_create, plugixa_car_rental_edit, plugixa_car_rental_delete, plugixa_car_rental_export and plugixa_car_rental_manage_settings. Grant them with any role editor.

Privacy

The plugin adds a Car rental bookings exporter and eraser to WordPress’s Export Personal Data and Erase Personal Data tools. The eraser anonymises finished bookings (completed, cancelled, expired, no-show) and keeps open ones. See Privacy and uninstall.

Filter Value Other arguments What it is for
plugixa_car_rental_privacy_keep_booking string|null $reason array $booking Asked for each finished booking before it is anonymised. Return null to let it be anonymised, or a sentence saying why it is kept. The sentence is shown to the administrator after the booking’s reference. The Invoices app uses it to keep invoiced bookings.

Keep bookings with an open damage claim, marked in a notes line of your own:

add_filter( 'plugixa_car_rental_privacy_keep_booking', function ( $reason, $booking ) {
	if ( null !== $reason ) {
		return $reason;
	}

	if ( str_contains( (string) $booking['notes'], '[damage claim]' ) ) {
		return 'kept because a damage claim is still open.';
	}

	return null;
}, 10, 2 );

Records

These fire for every kind of record the plugin stores. The first argument is the record’s slug: booking, payment, invoice, vehicle_category, vehicle_model, vehicle_unit, location, location_closure, rate_plan, extra, coupon and form_field, plus pricing_rule, tax_rate, inspection and calendar_import PRO.

Hook Type Arguments When it fires
plugixa_car_rental_before_insert filter array $data, string $entity Just before a record is created.
plugixa_car_rental_entity_created action string $entity, int $id, array $data After a record is created.
plugixa_car_rental_before_update filter array $data, string $entity, int $id, array $old Just before a record is changed.
plugixa_car_rental_entity_field_changed action string $entity, int $id, string $field, mixed $new, mixed $old Once for each field whose value changed.
plugixa_car_rental_entity_updated action string $entity, int $id, array $data, array $old After a record is changed.
plugixa_car_rental_can_delete filter bool $allowed, string $entity, int $id, array $old Before a record goes to the trash. Return anything but true to refuse.
plugixa_car_rental_entity_deleted action string $entity, int $id, array $old After a record is moved to the trash. It can still be restored.
plugixa_car_rental_entity_restored action string $entity, int $id, array $row After a record is restored from the trash.
plugixa_car_rental_can_purge filter bool $allowed, string $entity, int $id, array $row Before a record is deleted for good. Return anything but true to refuse.
plugixa_car_rental_entity_purged action string $entity, int $id, array $row After a record is deleted for good.

A refusal from can_delete or can_purge carries no message. To explain why a car, a model or a location cannot be trashed, use the blocker filters instead. Each takes a list of sentences, and any sentence in the list stops the trash and is shown to the user.

Filter Arguments
plugixa_car_rental_vehicle_model_delete_blockers string[] $blockers, int $id, array $model
plugixa_car_rental_vehicle_unit_delete_blockers string[] $blockers, int $id, array $unit
plugixa_car_rental_location_delete_blockers string[] $blockers, int $id, array $location

Lifecycle

Action Arguments When it fires
plugixa_car_rental_loaded Container $container Once the plugin has started, on plugins_loaded, after every module has registered its hooks.
plugixa_car_rental_register_rest_routes string $namespace, Container $container On rest_api_init, after the plugin’s own routes. $namespace is plugixa-car-rental/v1.
plugixa_car_rental_settings_saved array $settings After the settings are saved.
plugixa_car_rental_activated none On activation, after the tables exist.
plugixa_car_rental_deactivated none On deactivation, before scheduled events are cleared.
plugixa_car_rental_uninstall none During an uninstall that erases data, before the tables are dropped. See Privacy and uninstall.

Scheduled events

Event Runs What it does
plugixa_car_rental_expire_holds Hourly Marks pending bookings whose hold ran out as expired. A lapsed hold stops blocking its car at once; this only tidies the status.
plugixa_car_rental_send_message PRO Once per message Sends one text message or Telegram alert, just after the status change that asked for it.
plugixa_car_rental_calendar_import PRO Hourly Reads the calendar feeds you added under calendar sync.

All three rely on WordPress’s scheduler, which runs when somebody visits the site. On a quiet site, or one with DISABLE_WP_CRON set, run wp-cron.php from a real server cron job.

Quick Links