DOCS

v1.3.28
 // Pro v1.2.20

 · Latest

Docs/Developer Guide/Developer Quick Start

Developer Quick Start

Build your first custom rule component end-to-end in about 15 minutes.

What you’ll build: a custom Condition that checks whether an order was placed in a specific WooCommerce shipping zone – a real use case not covered by the built-in components.

Prerequisites:

  • Order Daemon Core active on a WP/WooCommerce dev site
  • PHP 8.x, Composer, a plugin or mu-plugin to put your code in

1. Understand the component interfaces

Every rule component implements ComponentInterface:

interface ComponentInterface {
    public function get_id(): string;            // Unique string key, e.g. 'my_condition'
    public function get_label(): string;         // Human-readable label shown in the Rule Builder UI
    public function get_description(): string;   // Short description shown in tooltips
    public function get_settings_schema(): ?array; // JSON Schema for the UI settings form; null or [] if no settings
}

Conditions additionally implement ConditionInterface:

interface ConditionInterface extends ComponentInterface {
    public function evaluate(WC_Order $order, array $settings): bool;
}

Triggers implement TriggerInterface, actions follow ComponentInterface with an execute() method.

2. Create the condition class

namespace MyPluginRulesConditions;

use OrderDaemonCompletionManagerCoreRuleComponentsInterfacesConditionInterface;

class ShippingZoneCondition implements ConditionInterface {

    public function get_id(): string {
        return 'shipping_zone';
    }

    public function get_label(): string {
        return __('Shipping Zone', 'my-plugin');
    }

    public function get_description(): string {
        return __('Matches orders shipped to a specific WooCommerce shipping zone.', 'my-plugin');
    }

    public function get_settings_schema(): ?array {
        // Build the list of zones for the dropdown
        $zones    = WC_Shipping_Zones::get_zones();
        $options  = [['value' => '0', 'label' => __('Rest of the World', 'my-plugin')]];
        foreach ($zones as $zone) {
            $options[] = [
                'value' => (string) $zone['zone_id'],
                'label' => $zone['zone_name'],
            ];
        }

        return [
            'type'       => 'object',
            'properties' => [
                'zone_id' => [
                    'type'      => 'string',
                    'title'     => __('Shipping Zone', 'my-plugin'),
                    'enum'      => array_column($options, 'value'),
                    'enumNames' => array_column($options, 'label'),
                    'default'   => '0',
                ],
            ],
            'required' => ['zone_id'],
        ];
    }

    public function evaluate(WC_Order $order, array $settings): bool {
        $target_zone_id = (int) ($settings['zone_id'] ?? 0);
        $package        = [
            'destination' => [
                'country'  => $order->get_shipping_country(),
                'state'    => $order->get_shipping_state(),
                'postcode' => $order->get_shipping_postcode(),
            ],
        ];
        $zone = WC_Shipping_Zones::get_zone_matching_package($package);
        return (int) $zone->get_id() === $target_zone_id;
    }
}

3. Register the component

Hook into odcm_register_conditions to add your component to the registry:

add_action('odcm_register_conditions', function ($registry) {
    $registry->register_condition(new MyPluginRulesConditionsShippingZoneCondition());
});

Place this in your plugin’s bootstrap (e.g. plugins_loaded or init).

4. Test it

  1. Go to Order Daemon → All Order Rules → Add New.
  2. Add a trigger (e.g. “Order Processing”).
  3. Add a condition – your new “Shipping Zone” condition should appear in the list.
  4. Configure it, save the rule, and place a test order to verify it fires correctly.
  5. Check Order Daemon → Insight Dashboard to see the condition’s pass/fail result in the timeline.

Inside evaluate(), emit a log event for visibility:

public function evaluate(WC_Order $order, array $settings): bool {
    $zone    = WC_Shipping_Zones::get_zone_matching_package($package);
    $matched = (int) $zone->get_id() === $target_zone_id;

    if (function_exists('odcm_log_event')) {
        odcm_log_event(
            $matched
                ? 'Shipping zone condition passed'
                : 'Shipping zone condition failed  -  zone mismatch',
            [
                'order_zone'  => $zone->get_id(),
                'target_zone' => $target_zone_id,
            ],
            $order->get_id(),
            $matched ? 'info' : 'debug',
            'shipping_zone_condition'
        );
    }

    return $matched;
}

What’s next