JezK
Edit File: class-cartflows-pro-ability-config.php
<?php /** * CartFlows Pro — Ability Config * * Defines all ability configurations (registration arrays) for CartFlows Pro. * Execute callbacks delegate to Cartflows_Pro_Ability_Runtime methods. * * @package cartflows-pro * @since 2.2.2 */ if ( ! defined( 'ABSPATH' ) ) { exit; } /** * Class Cartflows_Pro_Ability_Config * * Provides static ability definitions consumed by Cartflows_Pro_Ability_Runtime::register(). * * @since 2.2.2 */ class Cartflows_Pro_Ability_Config { /** * Cached abilities array. * * @var array|false */ public static $abilities = false; /** * Get all ability configurations. * * @since 2.2.2 * @return array Ability definitions keyed by ability name. */ public static function get_abilities() { if ( false !== self::$abilities ) { return self::$abilities; } $runtime = new Cartflows_Pro_Ability_Runtime(); $abilities = array( // ============================================================ // Offer / Upsell / Downsell Module // ============================================================ // List all upsell/downsell steps across all funnels. CARTFLOWS_PRO_ABILITY_API_NAMESPACE . 'list-offer-steps' => array( 'label' => __( 'List offer steps', 'cartflows-pro' ), 'description' => __( 'Returns a paginated list of upsell and downsell steps across all funnels, with the associated product, discount type, and disable/skip flags. Filter by funnel (flow_id) or step type (upsell/downsell/all).', 'cartflows-pro' ), 'category' => 'cartflows-pro', 'permission_callback' => function () use ( $runtime ) { return $runtime->permission_callback( 'cartflows_manage_flows_steps' ); }, 'input_schema' => array( 'type' => 'object', 'properties' => array( 'flow_id' => array( 'type' => 'integer', 'description' => __( 'Limit results to a specific funnel (flow). Omit or set to 0 for all funnels.', 'cartflows-pro' ), 'default' => 0, ), 'step_type' => array( 'type' => 'string', 'enum' => array( 'upsell', 'downsell', 'all' ), 'default' => 'all', 'description' => __( 'Filter by offer type. Use "all" to include both upsell and downsell steps.', 'cartflows-pro' ), ), 'page' => array( 'type' => 'integer', 'description' => __( 'Page number (1-based).', 'cartflows-pro' ), 'default' => 1, ), 'per_page' => array( 'type' => 'integer', 'description' => __( 'Results per page (max 100).', 'cartflows-pro' ), 'default' => 20, ), ), ), 'output_schema' => array( 'type' => 'object', 'properties' => array( 'steps' => array( 'type' => 'array', 'items' => array( 'type' => 'object', 'properties' => array( 'step_id' => array( 'type' => 'integer', 'description' => __( 'Step post ID.', 'cartflows-pro' ), ), 'flow_id' => array( 'type' => 'integer', 'description' => __( 'Parent funnel ID.', 'cartflows-pro' ), ), 'title' => array( 'type' => 'string', 'description' => __( 'Step title.', 'cartflows-pro' ), ), 'step_type' => array( 'type' => 'string', 'description' => __( 'upsell or downsell.', 'cartflows-pro' ), ), 'product_id' => array( 'type' => 'integer', 'description' => __( 'Assigned WooCommerce product ID (0 if none).', 'cartflows-pro' ), ), 'product_name' => array( 'type' => 'string', 'description' => __( 'Product name (empty if no product assigned).', 'cartflows-pro' ), ), 'discount_type' => array( 'type' => 'string', 'description' => __( 'Discount type: percent, price, free, or empty.', 'cartflows-pro' ), ), 'discount_value' => array( 'type' => 'number', 'description' => __( 'Discount amount.', 'cartflows-pro' ), ), 'is_disabled' => array( 'type' => 'boolean', 'description' => __( 'True if the step is disabled.', 'cartflows-pro' ), ), 'skip_if_owned' => array( 'type' => 'boolean', 'description' => __( 'True if the step is skipped when the customer already owns the product.', 'cartflows-pro' ), ), 'url_edit' => array( 'type' => 'string', 'format' => 'uri', 'description' => __( 'Admin edit URL for the step.', 'cartflows-pro' ), ), ), ), ), 'total' => array( 'type' => 'integer', 'description' => __( 'Total number of matching steps.', 'cartflows-pro' ), ), 'total_pages' => array( 'type' => 'integer', 'description' => __( 'Total number of pages.', 'cartflows-pro' ), ), ), ), 'execute_callback' => function ( $input ) use ( $runtime ) { return $runtime->list_offer_steps( $input ); }, 'meta' => array( 'annotations' => array( 'priority' => 1.0, 'readOnlyHint' => true, 'destructiveHint' => false, 'idempotentHint' => true, 'openWorldHint' => false, ), 'show_in_rest' => true, 'mcp' => array( 'public' => true, 'type' => 'tool', ), ), ), // Get full configuration of a single offer step. CARTFLOWS_PRO_ABILITY_API_NAMESPACE . 'get-offer-step' => array( 'label' => __( 'Get offer step', 'cartflows-pro' ), 'description' => __( 'Returns full configuration of a single upsell or downsell step: product, discount, routing (yes/no next steps), skip-offer flag, disable-step flag, replace-main-order flag, and admin URLs.', 'cartflows-pro' ), 'category' => 'cartflows-pro', 'permission_callback' => function () use ( $runtime ) { return $runtime->permission_callback( 'cartflows_manage_flows_steps' ); }, 'input_schema' => array( 'type' => 'object', 'required' => array( 'step_id' ), 'properties' => array( 'step_id' => array( 'type' => 'integer', 'description' => __( 'The upsell or downsell step ID.', 'cartflows-pro' ), ), ), ), 'output_schema' => array( 'type' => 'object', 'properties' => array( 'step_id' => array( 'type' => 'integer', 'description' => __( 'Step post ID.', 'cartflows-pro' ), ), 'flow_id' => array( 'type' => 'integer', 'description' => __( 'Parent funnel ID.', 'cartflows-pro' ), ), 'title' => array( 'type' => 'string', 'description' => __( 'Step title.', 'cartflows-pro' ), ), 'step_type' => array( 'type' => 'string', 'description' => __( 'upsell or downsell.', 'cartflows-pro' ), ), 'product_id' => array( 'type' => 'integer', 'description' => __( 'Assigned WooCommerce product ID (0 if none).', 'cartflows-pro' ), ), 'product_name' => array( 'type' => 'string', 'description' => __( 'Product name.', 'cartflows-pro' ), ), 'product_price' => array( 'type' => 'number', 'description' => __( 'Product regular price (raw float).', 'cartflows-pro' ), ), 'discount_type' => array( 'type' => 'string', 'description' => __( 'Discount type: percent, price, free, or empty.', 'cartflows-pro' ), ), 'discount_value' => array( 'type' => 'number', 'description' => __( 'Discount amount.', 'cartflows-pro' ), ), 'yes_next_step_id' => array( 'type' => 'integer', 'description' => __( 'Step ID to go to when the offer is accepted (0 = not set).', 'cartflows-pro' ), ), 'no_next_step_id' => array( 'type' => 'integer', 'description' => __( 'Step ID to go to when the offer is declined (0 = not set).', 'cartflows-pro' ), ), 'is_disabled' => array( 'type' => 'boolean', 'description' => __( 'True if the step is disabled.', 'cartflows-pro' ), ), 'skip_if_owned' => array( 'type' => 'boolean', 'description' => __( 'True if the step is skipped when the customer already owns the product.', 'cartflows-pro' ), ), 'replace_main_order' => array( 'type' => 'boolean', 'description' => __( 'True if the main order is replaced/cancelled when the offer is accepted.', 'cartflows-pro' ), ), 'url_edit' => array( 'type' => 'string', 'format' => 'uri', 'description' => __( 'Admin edit URL for the step.', 'cartflows-pro' ), ), 'url_preview' => array( 'type' => 'string', 'format' => 'uri', 'description' => __( 'Frontend preview URL for the step.', 'cartflows-pro' ), ), ), ), 'execute_callback' => function ( $input ) use ( $runtime ) { return $runtime->get_offer_step( $input ); }, 'meta' => array( 'annotations' => array( 'priority' => 1.0, 'readOnlyHint' => true, 'destructiveHint' => false, 'idempotentHint' => true, 'openWorldHint' => false, ), 'show_in_rest' => true, 'mcp' => array( 'public' => true, 'type' => 'tool', ), ), ), // Update the product assigned to an offer step. CARTFLOWS_PRO_ABILITY_API_NAMESPACE . 'update-offer-step-product' => array( 'label' => __( 'Update offer step product', 'cartflows-pro' ), 'description' => __( 'Sets or changes the product assigned to an upsell or downsell step, including discount type and discount value. Requires the cartflows_pro_abilities_api_write option to be enabled.', 'cartflows-pro' ), 'category' => 'cartflows-pro', 'permission_callback' => function () use ( $runtime ) { return ( get_option( 'cartflows_pro_abilities_api_write', true ) && $runtime->permission_callback( 'cartflows_manage_flows_steps' ) ); }, 'input_schema' => array( 'type' => 'object', 'required' => array( 'step_id', 'product_id' ), 'properties' => array( 'step_id' => array( 'type' => 'integer', 'description' => __( 'The offer step ID.', 'cartflows-pro' ), ), 'product_id' => array( 'type' => 'integer', 'description' => __( 'The WooCommerce product ID to assign to the step.', 'cartflows-pro' ), ), 'discount_type' => array( 'type' => 'string', 'enum' => array( 'percent', 'price', 'free', '' ), 'default' => '', 'description' => __( 'Discount type to apply. Use "percent" for percentage off, "price" for flat price reduction, "free" for free product, or empty for no discount.', 'cartflows-pro' ), ), 'discount_value' => array( 'type' => 'number', 'default' => 0, 'description' => __( 'Discount amount. Required when discount_type is percent or price.', 'cartflows-pro' ), ), ), ), 'output_schema' => array( 'type' => 'object', 'properties' => array( 'step_id' => array( 'type' => 'integer', 'description' => __( 'The updated step ID.', 'cartflows-pro' ), ), 'product_id' => array( 'type' => 'integer', 'description' => __( 'The newly assigned product ID.', 'cartflows-pro' ), ), 'product_name' => array( 'type' => 'string', 'description' => __( 'Product name.', 'cartflows-pro' ), ), 'discount_type' => array( 'type' => 'string', 'description' => __( 'Stored discount type.', 'cartflows-pro' ), ), 'discount_value' => array( 'type' => 'number', 'description' => __( 'Stored discount value.', 'cartflows-pro' ), ), 'url_edit' => array( 'type' => 'string', 'format' => 'uri', 'description' => __( 'Admin edit URL for the step.', 'cartflows-pro' ), ), ), ), 'execute_callback' => function ( $input ) use ( $runtime ) { return $runtime->update_offer_step_product( $input ); }, 'meta' => array( 'annotations' => array( 'priority' => 2.0, 'readOnlyHint' => false, 'destructiveHint' => false, 'idempotentHint' => true, 'openWorldHint' => false, ), 'show_in_rest' => true, 'mcp' => array( 'public' => true, 'type' => 'tool', ), ), ), // Toggle an offer step enabled/disabled. CARTFLOWS_PRO_ABILITY_API_NAMESPACE . 'toggle-offer-step' => array( 'label' => __( 'Toggle offer step enabled/disabled', 'cartflows-pro' ), 'description' => __( 'Enables or disables a upsell or downsell step. Disabled steps are bypassed entirely in the funnel flow. Requires the cartflows_pro_abilities_api_write option to be enabled.', 'cartflows-pro' ), 'category' => 'cartflows-pro', 'permission_callback' => function () use ( $runtime ) { return ( get_option( 'cartflows_pro_abilities_api_write', true ) && $runtime->permission_callback( 'cartflows_manage_flows_steps' ) ); }, 'input_schema' => array( 'type' => 'object', 'required' => array( 'step_id', 'disabled' ), 'properties' => array( 'step_id' => array( 'type' => 'integer', 'description' => __( 'The offer step ID.', 'cartflows-pro' ), ), 'disabled' => array( 'type' => 'boolean', 'description' => __( 'True to disable the step; false to enable it.', 'cartflows-pro' ), ), ), ), 'output_schema' => array( 'type' => 'object', 'properties' => array( 'step_id' => array( 'type' => 'integer', 'description' => __( 'The updated step ID.', 'cartflows-pro' ), ), 'is_disabled' => array( 'type' => 'boolean', 'description' => __( 'Current disabled state of the step.', 'cartflows-pro' ), ), 'message' => array( 'type' => 'string', 'description' => __( 'Human-readable result message.', 'cartflows-pro' ), ), ), ), 'execute_callback' => function ( $input ) use ( $runtime ) { return $runtime->toggle_offer_step( $input ); }, 'meta' => array( 'annotations' => array( 'priority' => 2.0, 'readOnlyHint' => false, 'destructiveHint' => false, 'idempotentHint' => true, 'openWorldHint' => false, ), 'show_in_rest' => true, 'mcp' => array( 'public' => true, 'type' => 'tool', ), ), ), // Update yes/no routing for an offer step. CARTFLOWS_PRO_ABILITY_API_NAMESPACE . 'update-offer-step-routing' => array( 'label' => __( 'Update offer step routing', 'cartflows-pro' ), 'description' => __( 'Sets the yes-next-step and no-next-step routing for a upsell or downsell step, controlling where customers are redirected after accepting or declining the offer. Requires the cartflows_pro_abilities_api_write option to be enabled.', 'cartflows-pro' ), 'category' => 'cartflows-pro', 'permission_callback' => function () use ( $runtime ) { return ( get_option( 'cartflows_pro_abilities_api_write', true ) && $runtime->permission_callback( 'cartflows_manage_flows_steps' ) ); }, 'input_schema' => array( 'type' => 'object', 'required' => array( 'step_id' ), 'properties' => array( 'step_id' => array( 'type' => 'integer', 'description' => __( 'The offer step ID.', 'cartflows-pro' ), ), 'yes_next_step_id' => array( 'type' => 'integer', 'default' => 0, 'description' => __( 'Step ID to redirect to when the offer is accepted. Set to 0 to clear.', 'cartflows-pro' ), ), 'no_next_step_id' => array( 'type' => 'integer', 'default' => 0, 'description' => __( 'Step ID to redirect to when the offer is declined. Set to 0 to clear.', 'cartflows-pro' ), ), ), ), 'output_schema' => array( 'type' => 'object', 'properties' => array( 'step_id' => array( 'type' => 'integer', 'description' => __( 'The updated step ID.', 'cartflows-pro' ), ), 'yes_next_step_id' => array( 'type' => 'integer', 'description' => __( 'Stored yes-next-step ID (0 if not set).', 'cartflows-pro' ), ), 'no_next_step_id' => array( 'type' => 'integer', 'description' => __( 'Stored no-next-step ID (0 if not set).', 'cartflows-pro' ), ), 'url_edit' => array( 'type' => 'string', 'format' => 'uri', 'description' => __( 'Admin edit URL for the step.', 'cartflows-pro' ), ), ), ), 'execute_callback' => function ( $input ) use ( $runtime ) { return $runtime->update_offer_step_routing( $input ); }, 'meta' => array( 'annotations' => array( 'priority' => 2.0, 'readOnlyHint' => false, 'destructiveHint' => false, 'idempotentHint' => true, 'openWorldHint' => false, ), 'show_in_rest' => true, 'mcp' => array( 'public' => true, 'type' => 'tool', ), ), ), // Get offer metadata for a WooCommerce order. CARTFLOWS_PRO_ABILITY_API_NAMESPACE . 'get-offer-order-details' => array( 'label' => __( 'Get offer order details', 'cartflows-pro' ), 'description' => __( 'Returns CartFlows offer metadata for a WooCommerce order: whether it is an offer order, its type (upsell/downsell), the parent order ID, amount charged (for difference-billing), and any linked child offer orders.', 'cartflows-pro' ), 'category' => 'cartflows-pro', 'permission_callback' => function () use ( $runtime ) { return $runtime->permission_callback( 'cartflows_manage_flows_steps' ); }, 'input_schema' => array( 'type' => 'object', 'required' => array( 'order_id' ), 'properties' => array( 'order_id' => array( 'type' => 'integer', 'description' => __( 'The WooCommerce order ID to inspect.', 'cartflows-pro' ), ), ), ), 'output_schema' => array( 'type' => 'object', 'properties' => array( 'order_id' => array( 'type' => 'integer', 'description' => __( 'The queried order ID.', 'cartflows-pro' ), ), 'is_offer_order' => array( 'type' => 'boolean', 'description' => __( 'True if this order was created as a CartFlows offer order.', 'cartflows-pro' ), ), 'offer_type' => array( 'type' => 'string', 'description' => __( 'upsell, downsell, or empty string for main orders.', 'cartflows-pro' ), ), 'parent_order_id' => array( 'type' => 'integer', 'description' => __( 'Parent order ID (0 if not an offer order or not set).', 'cartflows-pro' ), ), 'amount_charged' => array( 'type' => 'number', 'description' => __( 'Amount charged for difference-billing offers (0 if not applicable).', 'cartflows-pro' ), ), 'child_offer_orders' => array( 'type' => 'array', 'description' => __( 'Child offer orders linked to this order (empty for offer orders themselves).', 'cartflows-pro' ), 'items' => array( 'type' => 'object', 'properties' => array( 'order_id' => array( 'type' => 'integer', 'description' => __( 'Child offer order ID.', 'cartflows-pro' ), ), 'offer_type' => array( 'type' => 'string', 'description' => __( 'upsell or downsell.', 'cartflows-pro' ), ), ), ), ), 'url_edit' => array( 'type' => 'string', 'format' => 'uri', 'description' => __( 'Admin edit URL for the order.', 'cartflows-pro' ), ), ), ), 'execute_callback' => function ( $input ) use ( $runtime ) { return $runtime->get_offer_order_details( $input ); }, 'meta' => array( 'annotations' => array( 'priority' => 1.0, 'readOnlyHint' => true, 'destructiveHint' => false, 'idempotentHint' => true, 'openWorldHint' => false, ), 'show_in_rest' => true, 'mcp' => array( 'public' => true, 'type' => 'tool', ), ), ), // List all CartFlows offer orders (paginated). CARTFLOWS_PRO_ABILITY_API_NAMESPACE . 'list-offer-orders' => array( 'label' => __( 'List offer orders', 'cartflows-pro' ), 'description' => __( 'Returns a paginated list of WooCommerce orders that are CartFlows offer orders (upsell or downsell), with their parent order, offer type, total, currency, status, and date. Filter by offer_type or scope to a specific funnel via flow_id.', 'cartflows-pro' ), 'category' => 'cartflows-pro', 'permission_callback' => function () use ( $runtime ) { return $runtime->permission_callback( 'cartflows_manage_flows_steps' ); }, 'input_schema' => array( 'type' => 'object', 'properties' => array( 'offer_type' => array( 'type' => 'string', 'enum' => array( 'upsell', 'downsell', 'all' ), 'default' => 'all', 'description' => __( 'Filter by offer type. Use "all" to include both upsell and downsell orders.', 'cartflows-pro' ), ), 'flow_id' => array( 'type' => 'integer', 'default' => 0, 'description' => __( 'Scope to a specific funnel. Omit or set to 0 for all funnels.', 'cartflows-pro' ), ), 'page' => array( 'type' => 'integer', 'default' => 1, 'description' => __( 'Page number (1-based).', 'cartflows-pro' ), ), 'per_page' => array( 'type' => 'integer', 'default' => 20, 'description' => __( 'Results per page (max 100).', 'cartflows-pro' ), ), ), ), 'output_schema' => array( 'type' => 'object', 'properties' => array( 'orders' => array( 'type' => 'array', 'items' => array( 'type' => 'object', 'properties' => array( 'order_id' => array( 'type' => 'integer', 'description' => __( 'Offer order ID.', 'cartflows-pro' ), ), 'parent_order_id' => array( 'type' => 'integer', 'description' => __( 'Parent order ID.', 'cartflows-pro' ), ), 'offer_type' => array( 'type' => 'string', 'description' => __( 'upsell or downsell.', 'cartflows-pro' ), ), 'total' => array( 'type' => 'number', 'description' => __( 'Order total (raw float).', 'cartflows-pro' ), ), 'currency' => array( 'type' => 'string', 'description' => __( 'Order currency code (e.g. USD).', 'cartflows-pro' ), ), 'status' => array( 'type' => 'string', 'description' => __( 'WooCommerce order status (e.g. wc-completed).', 'cartflows-pro' ), ), 'date_created' => array( 'type' => 'string', 'format' => 'date-time', 'description' => __( 'Order creation date (ISO 8601).', 'cartflows-pro' ), ), 'url_edit' => array( 'type' => 'string', 'format' => 'uri', 'description' => __( 'Admin edit URL for the order.', 'cartflows-pro' ), ), ), ), ), 'total' => array( 'type' => 'integer', 'description' => __( 'Total number of matching offer orders.', 'cartflows-pro' ), ), 'total_pages' => array( 'type' => 'integer', 'description' => __( 'Total number of pages.', 'cartflows-pro' ), ), ), ), 'execute_callback' => function ( $input ) use ( $runtime ) { return $runtime->list_offer_orders( $input ); }, 'meta' => array( 'annotations' => array( 'priority' => 1.0, 'readOnlyHint' => true, 'destructiveHint' => false, 'idempotentHint' => true, 'openWorldHint' => false, ), 'show_in_rest' => true, 'mcp' => array( 'public' => true, 'type' => 'tool', ), ), ), // ============================================================ // Tracking / Analytics Module // ============================================================ // Get funnel-level revenue analytics for a date range. CARTFLOWS_PRO_ABILITY_API_NAMESPACE . 'get-funnel-analytics' => array( 'label' => __( 'Get funnel analytics', 'cartflows-pro' ), 'description' => __( 'Returns funnel-level revenue and visit analytics for a date range. Includes total revenue, orders, bump revenue, offer revenue, visits, avg order value, revenue per visit, revenue per unique visitor, and daily time-series data. Optionally scoped to a single funnel; omit flow_id for all funnels.', 'cartflows-pro' ), 'category' => 'cartflows-pro', 'permission_callback' => function () use ( $runtime ) { return $runtime->permission_callback( 'cartflows_manage_flows_steps' ); }, 'input_schema' => array( 'type' => 'object', 'required' => array( 'start_date', 'end_date' ), 'properties' => array( 'start_date' => array( 'type' => 'string', 'format' => 'date', 'description' => __( 'Start of the reporting window (YYYY-MM-DD).', 'cartflows-pro' ), ), 'end_date' => array( 'type' => 'string', 'format' => 'date', 'description' => __( 'End of the reporting window (YYYY-MM-DD).', 'cartflows-pro' ), ), 'flow_id' => array( 'type' => 'integer', 'description' => __( 'Funnel (flow) ID to scope results to. Omit for all funnels.', 'cartflows-pro' ), 'default' => 0, ), 'comparison_range_type' => array( 'type' => 'string', 'enum' => array( '', 'previous-period', 'previous-year' ), 'default' => '', 'description' => __( 'Include comparison period data. Empty string disables comparison.', 'cartflows-pro' ), ), ), ), 'output_schema' => array( 'type' => 'object', 'properties' => array( 'total_revenue' => array( 'type' => 'string', 'description' => __( 'Formatted total revenue.', 'cartflows-pro' ), ), 'total_orders' => array( 'type' => 'integer', 'description' => __( 'Total order count.', 'cartflows-pro' ), ), 'total_bump_revenue' => array( 'type' => 'string', 'description' => __( 'Formatted order bump revenue.', 'cartflows-pro' ), ), 'total_offers_revenue' => array( 'type' => 'string', 'description' => __( 'Formatted upsell/downsell revenue.', 'cartflows-pro' ), ), 'total_visits' => array( 'type' => 'integer', 'description' => __( 'Total funnel visits.', 'cartflows-pro' ), ), 'total_unique_visitors' => array( 'type' => 'integer', 'description' => __( 'Total unique visitors.', 'cartflows-pro' ), ), 'avg_order_value' => array( 'type' => 'string', 'description' => __( 'Formatted average order value.', 'cartflows-pro' ), ), 'revenue_per_visit' => array( 'type' => 'string', 'description' => __( 'Formatted revenue per visit.', 'cartflows-pro' ), ), 'revenue_per_unique_visitor' => array( 'type' => 'string', 'description' => __( 'Formatted revenue per unique visitor.', 'cartflows-pro' ), ), 'flows_conversions' => array( 'type' => 'array', 'description' => __( 'Per-flow analytics summary array.', 'cartflows-pro' ), 'items' => array( 'type' => 'object' ), ), 'top_performing_funnels' => array( 'type' => 'array', 'description' => __( 'Top 5 funnels by revenue.', 'cartflows-pro' ), 'items' => array( 'type' => 'object' ), ), 'revenue_by_date' => array( 'type' => 'array', 'description' => __( 'Daily revenue time-series.', 'cartflows-pro' ), 'items' => array( 'type' => 'object' ), ), 'orders_by_date' => array( 'type' => 'array', 'description' => __( 'Daily orders time-series.', 'cartflows-pro' ), 'items' => array( 'type' => 'object' ), ), 'visits_by_date' => array( 'type' => 'array', 'description' => __( 'Daily visits time-series.', 'cartflows-pro' ), 'items' => array( 'type' => 'object' ), ), 'comparison' => array( 'type' => 'object', 'description' => __( 'Prior-period comparison metrics (empty when comparison_range_type is empty).', 'cartflows-pro' ), ), ), ), 'execute_callback' => function ( $input ) use ( $runtime ) { return $runtime->get_funnel_analytics( $input ); }, 'meta' => array( 'annotations' => array( 'priority' => 1.0, 'readOnlyHint' => true, 'destructiveHint' => false, 'idempotentHint' => true, 'openWorldHint' => false, ), 'show_in_rest' => true, 'mcp' => array( 'public' => true, 'type' => 'tool', ), ), ), // Get conversion-focused analytics for a date range. CARTFLOWS_PRO_ABILITY_API_NAMESPACE . 'get-conversion-analytics' => array( 'label' => __( 'Get conversion analytics', 'cartflows-pro' ), 'description' => __( 'Returns conversion-focused analytics for a date range: total conversions, bump conversions, offer conversions, device breakdown (mobile/desktop), step-level conversion rates, and product performance. Optionally scoped to a single funnel.', 'cartflows-pro' ), 'category' => 'cartflows-pro', 'permission_callback' => function () use ( $runtime ) { return $runtime->permission_callback( 'cartflows_manage_flows_steps' ); }, 'input_schema' => array( 'type' => 'object', 'required' => array( 'start_date', 'end_date' ), 'properties' => array( 'start_date' => array( 'type' => 'string', 'format' => 'date', 'description' => __( 'Start of the reporting window (YYYY-MM-DD).', 'cartflows-pro' ), ), 'end_date' => array( 'type' => 'string', 'format' => 'date', 'description' => __( 'End of the reporting window (YYYY-MM-DD).', 'cartflows-pro' ), ), 'flow_id' => array( 'type' => 'integer', 'description' => __( 'Funnel (flow) ID to scope results to. Omit for all funnels.', 'cartflows-pro' ), 'default' => 0, ), 'comparison_range_type' => array( 'type' => 'string', 'enum' => array( '', 'previous-period', 'previous-year' ), 'default' => '', 'description' => __( 'Include comparison period data.', 'cartflows-pro' ), ), ), ), 'output_schema' => array( 'type' => 'object', 'properties' => array( 'total_visits' => array( 'type' => 'integer', 'description' => __( 'Total visits.', 'cartflows-pro' ), ), 'total_conversions' => array( 'type' => 'integer', 'description' => __( 'Total conversions (checkout completions).', 'cartflows-pro' ), ), 'total_bump_conversions' => array( 'type' => 'integer', 'description' => __( 'Total order bump conversions.', 'cartflows-pro' ), ), 'total_offer_conversions' => array( 'type' => 'integer', 'description' => __( 'Total upsell/downsell conversions.', 'cartflows-pro' ), ), 'total_mobile_conversions' => array( 'type' => 'integer', 'description' => __( 'Conversions from mobile devices.', 'cartflows-pro' ), ), 'total_desktop_conversions' => array( 'type' => 'integer', 'description' => __( 'Conversions from desktop devices.', 'cartflows-pro' ), ), 'steps_conversion' => array( 'type' => 'object', 'description' => __( 'Per-step conversion data (only when flow_id is provided).', 'cartflows-pro' ), ), 'products' => array( 'type' => 'array', 'description' => __( 'Product-level analytics (only when flow_id is provided).', 'cartflows-pro' ), 'items' => array( 'type' => 'object' ), ), 'conversions_by_date' => array( 'type' => 'array', 'description' => __( 'Daily conversions time-series.', 'cartflows-pro' ), 'items' => array( 'type' => 'object' ), ), 'comparison' => array( 'type' => 'object', 'description' => __( 'Prior-period comparison metrics.', 'cartflows-pro' ), ), ), ), 'execute_callback' => function ( $input ) use ( $runtime ) { return $runtime->get_conversion_analytics( $input ); }, 'meta' => array( 'annotations' => array( 'priority' => 1.0, 'readOnlyHint' => true, 'destructiveHint' => false, 'idempotentHint' => true, 'openWorldHint' => false, ), 'show_in_rest' => true, 'mcp' => array( 'public' => true, 'type' => 'tool', ), ), ), // Get detailed earnings breakdown for a specific funnel. CARTFLOWS_PRO_ABILITY_API_NAMESPACE . 'get-flow-earnings' => array( 'label' => __( 'Get flow earnings', 'cartflows-pro' ), 'description' => __( 'Returns detailed earnings data for a specific funnel in a date range: gross sales, checkout sales, average order value, order bump earnings, upsell/downsell revenue, and per-step offer earnings breakdown.', 'cartflows-pro' ), 'category' => 'cartflows-pro', 'permission_callback' => function () use ( $runtime ) { return $runtime->permission_callback( 'cartflows_manage_flows_steps' ); }, 'input_schema' => array( 'type' => 'object', 'required' => array( 'flow_id', 'start_date', 'end_date' ), 'properties' => array( 'flow_id' => array( 'type' => 'integer', 'description' => __( 'Funnel (flow) ID.', 'cartflows-pro' ), ), 'start_date' => array( 'type' => 'string', 'format' => 'date', 'description' => __( 'Start of the reporting window (YYYY-MM-DD).', 'cartflows-pro' ), ), 'end_date' => array( 'type' => 'string', 'format' => 'date', 'description' => __( 'End of the reporting window (YYYY-MM-DD).', 'cartflows-pro' ), ), ), ), 'output_schema' => array( 'type' => 'object', 'properties' => array( 'order_count' => array( 'type' => 'integer', 'description' => __( 'Number of orders in the period.', 'cartflows-pro' ), ), 'gross_sale' => array( 'type' => 'string', 'description' => __( 'Formatted total revenue from all orders.', 'cartflows-pro' ), ), 'checkout_sale' => array( 'type' => 'string', 'description' => __( 'Formatted revenue from checkout (excluding bumps/upsells).', 'cartflows-pro' ), ), 'avg_order_value' => array( 'type' => 'string', 'description' => __( 'Formatted average order value.', 'cartflows-pro' ), ), 'bump_offer' => array( 'type' => 'string', 'description' => __( 'Formatted total order bump revenue.', 'cartflows-pro' ), ), 'upsell_revenue' => array( 'type' => 'string', 'description' => __( 'Formatted upsell/downsell revenue.', 'cartflows-pro' ), ), 'revenue_per_visit' => array( 'type' => 'string', 'description' => __( 'Formatted revenue per visit.', 'cartflows-pro' ), ), 'offer' => array( 'type' => 'object', 'description' => __( 'Per-step offer earnings (keys are step IDs).', 'cartflows-pro' ), ), 'checkout' => array( 'type' => 'object', 'description' => __( 'Per-checkout-step earnings (keys are step IDs).', 'cartflows-pro' ), ), ), ), 'execute_callback' => function ( $input ) use ( $runtime ) { return $runtime->get_flow_earnings( $input ); }, 'meta' => array( 'annotations' => array( 'priority' => 1.0, 'readOnlyHint' => true, 'destructiveHint' => false, 'idempotentHint' => true, 'openWorldHint' => false, ), 'show_in_rest' => true, 'mcp' => array( 'public' => true, 'type' => 'tool', ), ), ), // Get all-time gross sale total for a specific funnel (fast, cached). CARTFLOWS_PRO_ABILITY_API_NAMESPACE . 'get-gross-sale-by-flow' => array( 'label' => __( 'Get gross sale by flow', 'cartflows-pro' ), 'description' => __( 'Returns the all-time gross sale total (sum of completed and processing order totals) for a specific funnel. Result is cached for 60 seconds.', 'cartflows-pro' ), 'category' => 'cartflows-pro', 'permission_callback' => function () use ( $runtime ) { return $runtime->permission_callback( 'cartflows_manage_flows_steps' ); }, 'input_schema' => array( 'type' => 'object', 'required' => array( 'flow_id' ), 'properties' => array( 'flow_id' => array( 'type' => 'integer', 'description' => __( 'Funnel (flow) ID.', 'cartflows-pro' ), ), ), ), 'output_schema' => array( 'type' => 'object', 'properties' => array( 'flow_id' => array( 'type' => 'integer', 'description' => __( 'The queried flow ID.', 'cartflows-pro' ), ), 'gross_sale' => array( 'type' => 'number', 'description' => __( 'Raw gross sale amount (float).', 'cartflows-pro' ), ), 'gross_sale_formatted' => array( 'type' => 'string', 'description' => __( 'Formatted gross sale with currency symbol (HTML stripped).', 'cartflows-pro' ), ), ), ), 'execute_callback' => function ( $input ) use ( $runtime ) { return $runtime->get_gross_sale_by_flow( $input ); }, 'meta' => array( 'annotations' => array( 'priority' => 1.0, 'readOnlyHint' => true, 'destructiveHint' => false, 'idempotentHint' => true, 'openWorldHint' => false, ), 'show_in_rest' => true, 'mcp' => array( 'public' => true, 'type' => 'tool', ), ), ), // Get optin-specific analytics. CARTFLOWS_PRO_ABILITY_API_NAMESPACE . 'get-optin-analytics' => array( 'label' => __( 'Get optin analytics', 'cartflows-pro' ), 'description' => __( 'Returns optin-specific analytics for a date range: optin visit counts, conversion rate, and list growth rate. Optionally scoped to a single funnel.', 'cartflows-pro' ), 'category' => 'cartflows-pro', 'permission_callback' => function () use ( $runtime ) { return $runtime->permission_callback( 'cartflows_manage_flows_steps' ); }, 'input_schema' => array( 'type' => 'object', 'required' => array( 'start_date', 'end_date' ), 'properties' => array( 'start_date' => array( 'type' => 'string', 'format' => 'date', 'description' => __( 'Start of the reporting window (YYYY-MM-DD).', 'cartflows-pro' ), ), 'end_date' => array( 'type' => 'string', 'format' => 'date', 'description' => __( 'End of the reporting window (YYYY-MM-DD).', 'cartflows-pro' ), ), 'flow_id' => array( 'type' => 'integer', 'description' => __( 'Funnel (flow) ID to scope results to. Omit for all funnels.', 'cartflows-pro' ), 'default' => 0, ), 'comparison_range_type' => array( 'type' => 'string', 'enum' => array( '', 'previous-period', 'previous-year' ), 'default' => '', 'description' => __( 'Include comparison period data.', 'cartflows-pro' ), ), ), ), 'output_schema' => array( 'type' => 'object', 'properties' => array( 'optin_visits' => array( 'type' => 'integer', 'description' => __( 'Total optin step visits.', 'cartflows-pro' ), ), 'optin_conversion_rate' => array( 'type' => 'string', 'description' => __( 'Optin conversion rate (percentage).', 'cartflows-pro' ), ), 'optin_list_growth' => array( 'type' => 'number', 'description' => __( 'Optin list growth rate.', 'cartflows-pro' ), ), 'comparison' => array( 'type' => 'object', 'description' => __( 'Prior-period comparison metrics.', 'cartflows-pro' ), ), ), ), 'execute_callback' => function ( $input ) use ( $runtime ) { return $runtime->get_optin_analytics( $input ); }, 'meta' => array( 'annotations' => array( 'priority' => 1.0, 'readOnlyHint' => true, 'destructiveHint' => false, 'idempotentHint' => true, 'openWorldHint' => false, ), 'show_in_rest' => true, 'mcp' => array( 'public' => true, 'type' => 'tool', ), ), ), // Reset analytics for a funnel (sets reset date cutoff). CARTFLOWS_PRO_ABILITY_API_NAMESPACE . 'reset-flow-analytics' => array( 'label' => __( 'Reset flow analytics', 'cartflows-pro' ), 'description' => __( 'Resets analytics for a specific funnel by setting the analytics reset date to today. All analytics queries will exclude data recorded before this date. Non-destructive — no data is deleted. Requires the cartflows_pro_abilities_api_write option to be enabled.', 'cartflows-pro' ), 'category' => 'cartflows-pro', 'permission_callback' => function () use ( $runtime ) { return ( get_option( 'cartflows_pro_abilities_api_write', true ) && $runtime->permission_callback( 'cartflows_manage_flows_steps' ) ); }, 'input_schema' => array( 'type' => 'object', 'required' => array( 'flow_id' ), 'properties' => array( 'flow_id' => array( 'type' => 'integer', 'description' => __( 'Funnel (flow) ID to reset analytics for.', 'cartflows-pro' ), ), ), ), 'output_schema' => array( 'type' => 'object', 'properties' => array( 'success' => array( 'type' => 'boolean', 'description' => __( 'Whether the reset was successful.', 'cartflows-pro' ), ), 'flow_id' => array( 'type' => 'integer', 'description' => __( 'The flow ID that was reset.', 'cartflows-pro' ), ), 'reset_date' => array( 'type' => 'string', 'format' => 'date', 'description' => __( 'The date analytics were reset to (YYYY-MM-DD).', 'cartflows-pro' ), ), ), ), 'execute_callback' => function ( $input ) use ( $runtime ) { return $runtime->reset_flow_analytics( $input ); }, 'meta' => array( 'annotations' => array( 'priority' => 2.0, 'readOnlyHint' => false, 'destructiveHint' => false, 'idempotentHint' => true, 'openWorldHint' => false, ), 'instructions' => 'Confirm with the user before resetting analytics. This hides all historical analytics data recorded before today for the specified funnel.', 'show_in_rest' => true, 'mcp' => array( 'public' => true, 'type' => 'tool', ), ), ), // Get step-level analytics (single step or all steps in a flow). CARTFLOWS_PRO_ABILITY_API_NAMESPACE . 'get-step-analytics' => array( 'label' => __( 'Get step analytics', 'cartflows-pro' ), 'description' => __( 'Returns analytics for a specific step or all steps in a funnel: visits, unique visits, conversions, conversion rate, and revenue. Pass step_id for a single step result; pass flow_id to get all steps in that funnel. If both are provided, step_id takes precedence. Date range is optional (defaults to last 30 days).', 'cartflows-pro' ), 'category' => 'cartflows-pro', 'permission_callback' => function () use ( $runtime ) { return $runtime->permission_callback( 'cartflows_manage_flows_steps' ); }, 'input_schema' => array( 'type' => 'object', 'properties' => array( 'step_id' => array( 'type' => 'integer', 'description' => __( 'A single step ID. Takes precedence over flow_id if both provided.', 'cartflows-pro' ), 'default' => 0, ), 'flow_id' => array( 'type' => 'integer', 'description' => __( 'Funnel (flow) ID — returns analytics for all steps in the funnel.', 'cartflows-pro' ), 'default' => 0, ), 'start_date' => array( 'type' => 'string', 'format' => 'date', 'description' => __( 'Start of the reporting window (YYYY-MM-DD). Defaults to 30 days ago.', 'cartflows-pro' ), 'default' => '', ), 'end_date' => array( 'type' => 'string', 'format' => 'date', 'description' => __( 'End of the reporting window (YYYY-MM-DD). Defaults to today.', 'cartflows-pro' ), 'default' => '', ), ), ), 'output_schema' => array( 'type' => 'object', 'properties' => array( 'mode' => array( 'type' => 'string', 'enum' => array( 'single', 'flow' ), 'description' => __( 'Whether results are for a single step or all steps in a flow.', 'cartflows-pro' ), ), 'step' => array( 'type' => 'object', 'description' => __( 'Single step analytics object (present when mode=single).', 'cartflows-pro' ), 'properties' => array( 'step_id' => array( 'type' => 'integer', 'description' => __( 'Step ID.', 'cartflows-pro' ), ), 'step_title' => array( 'type' => 'string', 'description' => __( 'Step post title.', 'cartflows-pro' ), ), 'step_type' => array( 'type' => 'string', 'description' => __( 'Step type (checkout, upsell, downsell, optin, thankyou, landing).', 'cartflows-pro' ), ), 'total_visits' => array( 'type' => 'integer', 'description' => __( 'Total visits to the step.', 'cartflows-pro' ), ), 'unique_visits' => array( 'type' => 'integer', 'description' => __( 'Unique visits to the step.', 'cartflows-pro' ), ), 'conversions' => array( 'type' => 'integer', 'description' => __( 'Conversion count.', 'cartflows-pro' ), ), 'conversion_rate' => array( 'type' => 'string', 'description' => __( 'Conversion rate as a percentage string (e.g. "12.50").', 'cartflows-pro' ), ), 'revenue' => array( 'type' => 'string', 'description' => __( 'Revenue attributed to this step (formatted number string).', 'cartflows-pro' ), ), ), ), 'steps' => array( 'type' => 'array', 'description' => __( 'All steps analytics array (present when mode=flow).', 'cartflows-pro' ), 'items' => array( 'type' => 'object', 'properties' => array( 'step_id' => array( 'type' => 'integer', 'description' => __( 'Step ID.', 'cartflows-pro' ), ), 'step_title' => array( 'type' => 'string', 'description' => __( 'Step post title.', 'cartflows-pro' ), ), 'step_type' => array( 'type' => 'string', 'description' => __( 'Step type.', 'cartflows-pro' ), ), 'total_visits' => array( 'type' => 'integer', 'description' => __( 'Total visits.', 'cartflows-pro' ), ), 'unique_visits' => array( 'type' => 'integer', 'description' => __( 'Unique visits.', 'cartflows-pro' ), ), 'conversions' => array( 'type' => 'integer', 'description' => __( 'Conversion count.', 'cartflows-pro' ), ), 'conversion_rate' => array( 'type' => 'string', 'description' => __( 'Conversion rate percentage string.', 'cartflows-pro' ), ), 'revenue' => array( 'type' => 'string', 'description' => __( 'Revenue attributed to this step.', 'cartflows-pro' ), ), ), ), ), ), ), 'execute_callback' => function ( $input ) use ( $runtime ) { return $runtime->get_step_analytics( $input ); }, 'meta' => array( 'annotations' => array( 'priority' => 1.0, 'readOnlyHint' => true, 'destructiveHint' => false, 'idempotentHint' => true, 'openWorldHint' => false, ), 'show_in_rest' => true, 'mcp' => array( 'public' => true, 'type' => 'tool', ), ), ), // ============================================================ // Checkout Module — Order Bumps, Pre-Checkout Offer, Product Options // ============================================================ // List all order bumps configured on a checkout step. CARTFLOWS_PRO_ABILITY_API_NAMESPACE . 'list-order-bumps' => array( 'label' => __( 'List order bumps', 'cartflows-pro' ), 'description' => __( 'Returns all order bumps configured on a checkout step, including product, discount, position, style, status, default state, and visibility rule flag.', 'cartflows-pro' ), 'category' => 'cartflows-pro', 'permission_callback' => function () use ( $runtime ) { return $runtime->permission_callback( 'cartflows_manage_flows_steps' ); }, 'input_schema' => array( 'type' => 'object', 'required' => array( 'step_id' ), 'properties' => array( 'step_id' => array( 'type' => 'integer', 'description' => __( 'The checkout step post ID.', 'cartflows-pro' ), ), ), ), 'output_schema' => array( 'type' => 'object', 'properties' => array( 'step_id' => array( 'type' => 'integer', 'description' => __( 'The checkout step ID.', 'cartflows-pro' ), ), 'order_bumps' => array( 'type' => 'array', 'items' => array( 'type' => 'object', 'properties' => array( 'ob_id' => array( 'type' => 'string', 'description' => __( 'Order bump unique ID.', 'cartflows-pro' ), ), 'title' => array( 'type' => 'string', 'description' => __( 'Order bump admin title.', 'cartflows-pro' ), ), 'status' => array( 'type' => 'boolean', 'description' => __( 'True if the order bump is enabled.', 'cartflows-pro' ), ), 'product_id' => array( 'type' => 'integer', 'description' => __( 'Assigned WooCommerce product ID (0 if none).', 'cartflows-pro' ), ), 'product_name' => array( 'type' => 'string', 'description' => __( 'Product name.', 'cartflows-pro' ), ), 'quantity' => array( 'type' => 'integer', 'description' => __( 'Product quantity.', 'cartflows-pro' ), ), 'discount_type' => array( 'type' => 'string', 'description' => __( 'Discount type: percent, price, coupon, or empty.', 'cartflows-pro' ), ), 'discount_value' => array( 'type' => 'number', 'description' => __( 'Discount amount.', 'cartflows-pro' ), ), 'position' => array( 'type' => 'string', 'description' => __( 'Display position: before-checkout, after-customer, after-order, after-payment.', 'cartflows-pro' ), ), 'style' => array( 'type' => 'string', 'description' => __( 'Visual style template (e.g. style-1 through style-5).', 'cartflows-pro' ), ), 'default_state' => array( 'type' => 'string', 'description' => __( 'Pre-checked state: yes or no.', 'cartflows-pro' ), ), 'action_element' => array( 'type' => 'string', 'description' => __( 'Action element type: checkbox or button.', 'cartflows-pro' ), ), 'display_quantity_field' => array( 'type' => 'string', 'description' => __( 'Show quantity field: yes or no.', 'cartflows-pro' ), ), 'has_rules' => array( 'type' => 'boolean', 'description' => __( 'True if conditional visibility rules are enabled.', 'cartflows-pro' ), ), 'replace_product' => array( 'type' => 'string', 'description' => __( 'Replace main product: yes or no.', 'cartflows-pro' ), ), ), ), ), 'total' => array( 'type' => 'integer', 'description' => __( 'Total number of order bumps.', 'cartflows-pro' ), ), ), ), 'execute_callback' => function ( $input ) use ( $runtime ) { return $runtime->list_order_bumps( $input ); }, 'meta' => array( 'annotations' => array( 'priority' => 1.0, 'readOnlyHint' => true, 'destructiveHint' => false, 'idempotentHint' => true, 'openWorldHint' => false, ), 'show_in_rest' => true, 'mcp' => array( 'public' => true, 'type' => 'tool', ), ), ), // Get full configuration of a single order bump. CARTFLOWS_PRO_ABILITY_API_NAMESPACE . 'get-order-bump' => array( 'label' => __( 'Get order bump details', 'cartflows-pro' ), 'description' => __( 'Returns the full configuration of a single order bump by its ID within a checkout step: product, discount, position, style, content (label, title, highlight text, description), image settings, default state, action element, visibility rules flag, and styling options.', 'cartflows-pro' ), 'category' => 'cartflows-pro', 'permission_callback' => function () use ( $runtime ) { return $runtime->permission_callback( 'cartflows_manage_flows_steps' ); }, 'input_schema' => array( 'type' => 'object', 'required' => array( 'step_id', 'ob_id' ), 'properties' => array( 'step_id' => array( 'type' => 'integer', 'description' => __( 'The checkout step post ID.', 'cartflows-pro' ), ), 'ob_id' => array( 'type' => 'string', 'description' => __( 'The order bump unique ID.', 'cartflows-pro' ), ), ), ), 'output_schema' => array( 'type' => 'object', 'properties' => array( 'step_id' => array( 'type' => 'integer', 'description' => __( 'Checkout step ID.', 'cartflows-pro' ), ), 'ob_id' => array( 'type' => 'string', 'description' => __( 'Order bump unique ID.', 'cartflows-pro' ), ), 'title' => array( 'type' => 'string', 'description' => __( 'Admin title.', 'cartflows-pro' ), ), 'status' => array( 'type' => 'boolean', 'description' => __( 'True if enabled.', 'cartflows-pro' ), ), 'product_id' => array( 'type' => 'integer', 'description' => __( 'Product ID.', 'cartflows-pro' ), ), 'product_name' => array( 'type' => 'string', 'description' => __( 'Product name.', 'cartflows-pro' ), ), 'quantity' => array( 'type' => 'integer', 'description' => __( 'Quantity.', 'cartflows-pro' ), ), 'discount_type' => array( 'type' => 'string', 'description' => __( 'Discount type.', 'cartflows-pro' ), ), 'discount_value' => array( 'type' => 'number', 'description' => __( 'Discount amount.', 'cartflows-pro' ), ), 'position' => array( 'type' => 'string', 'description' => __( 'Display position.', 'cartflows-pro' ), ), 'style' => array( 'type' => 'string', 'description' => __( 'Visual style.', 'cartflows-pro' ), ), 'width' => array( 'type' => 'string', 'description' => __( 'Width percentage.', 'cartflows-pro' ), ), 'default_state' => array( 'type' => 'string', 'description' => __( 'Pre-checked: yes or no.', 'cartflows-pro' ), ), 'action_element' => array( 'type' => 'string', 'description' => __( 'Action element type.', 'cartflows-pro' ), ), 'display_quantity_field' => array( 'type' => 'string', 'description' => __( 'Show quantity field: yes or no.', 'cartflows-pro' ), ), 'checkbox_label' => array( 'type' => 'string', 'description' => __( 'Checkbox/button label text.', 'cartflows-pro' ), ), 'title_text' => array( 'type' => 'string', 'description' => __( 'Offer title text.', 'cartflows-pro' ), ), 'hl_text' => array( 'type' => 'string', 'description' => __( 'Highlight text.', 'cartflows-pro' ), ), 'desc_text' => array( 'type' => 'string', 'description' => __( 'Description text.', 'cartflows-pro' ), ), 'replace_product' => array( 'type' => 'string', 'description' => __( 'Replace main product: yes or no.', 'cartflows-pro' ), ), 'next_step' => array( 'type' => 'string', 'description' => __( 'Next step ID when bump is accepted (empty if not set).', 'cartflows-pro' ), ), 'enable_show_image' => array( 'type' => 'string', 'description' => __( 'Show product image: yes or no.', 'cartflows-pro' ), ), 'ob_image_position' => array( 'type' => 'string', 'description' => __( 'Image position: left or right.', 'cartflows-pro' ), ), 'has_rules' => array( 'type' => 'boolean', 'description' => __( 'True if conditional rules are enabled.', 'cartflows-pro' ), ), ), ), 'execute_callback' => function ( $input ) use ( $runtime ) { return $runtime->get_order_bump( $input ); }, 'meta' => array( 'annotations' => array( 'priority' => 1.0, 'readOnlyHint' => true, 'destructiveHint' => false, 'idempotentHint' => true, 'openWorldHint' => false, ), 'show_in_rest' => true, 'mcp' => array( 'public' => true, 'type' => 'tool', ), ), ), // Update order bump settings. CARTFLOWS_PRO_ABILITY_API_NAMESPACE . 'update-order-bump' => array( 'label' => __( 'Update order bump settings', 'cartflows-pro' ), 'description' => __( 'Updates the configuration of an existing order bump on a checkout step. Supports partial updates: product, discount, position, style, content fields, default state, action element, quantity settings. Requires the cartflows_pro_abilities_api_write option to be enabled.', 'cartflows-pro' ), 'category' => 'cartflows-pro', 'permission_callback' => function () use ( $runtime ) { return ( get_option( 'cartflows_pro_abilities_api_write', true ) && $runtime->permission_callback( 'cartflows_manage_flows_steps' ) ); }, 'input_schema' => array( 'type' => 'object', 'required' => array( 'step_id', 'ob_id' ), 'properties' => array( 'step_id' => array( 'type' => 'integer', 'description' => __( 'The checkout step post ID.', 'cartflows-pro' ), ), 'ob_id' => array( 'type' => 'string', 'description' => __( 'The order bump unique ID.', 'cartflows-pro' ), ), 'product' => array( 'type' => 'integer', 'default' => 0, 'description' => __( 'WooCommerce product ID. Set to 0 to leave unchanged.', 'cartflows-pro' ), ), 'discount_type' => array( 'type' => 'string', 'default' => '__unchanged__', 'description' => __( 'Discount type: percent, price, coupon, or empty.', 'cartflows-pro' ), ), 'discount_value' => array( 'type' => 'number', 'default' => -1, 'description' => __( 'Discount amount. Set to -1 to leave unchanged.', 'cartflows-pro' ), ), 'position' => array( 'type' => 'string', 'default' => '__unchanged__', 'description' => __( 'Display position: before-checkout, after-customer, after-order, after-payment.', 'cartflows-pro' ), ), 'style' => array( 'type' => 'string', 'default' => '__unchanged__', 'description' => __( 'Visual style: style-1 through style-5, or style-default.', 'cartflows-pro' ), ), 'status' => array( 'type' => 'string', 'default' => '__unchanged__', 'description' => __( 'Enable bump: "true" or "false" as string. Leave unchanged to skip.', 'cartflows-pro' ), ), 'default_state' => array( 'type' => 'string', 'default' => '__unchanged__', 'description' => __( 'Pre-checked state: yes or no.', 'cartflows-pro' ), ), 'checkbox_label' => array( 'type' => 'string', 'default' => '__unchanged__', 'description' => __( 'Checkbox/button label text.', 'cartflows-pro' ), ), 'title_text' => array( 'type' => 'string', 'default' => '__unchanged__', 'description' => __( 'Offer title text.', 'cartflows-pro' ), ), 'hl_text' => array( 'type' => 'string', 'default' => '__unchanged__', 'description' => __( 'Highlight text.', 'cartflows-pro' ), ), 'desc_text' => array( 'type' => 'string', 'default' => '__unchanged__', 'description' => __( 'Description text.', 'cartflows-pro' ), ), 'action_element' => array( 'type' => 'string', 'default' => '__unchanged__', 'description' => __( 'Action element: checkbox or button.', 'cartflows-pro' ), ), 'display_quantity_field' => array( 'type' => 'string', 'default' => '__unchanged__', 'description' => __( 'Show quantity field: yes or no.', 'cartflows-pro' ), ), 'quantity' => array( 'type' => 'integer', 'default' => 0, 'description' => __( 'Default quantity. Set to 0 to leave unchanged.', 'cartflows-pro' ), ), ), ), 'output_schema' => array( 'type' => 'object', 'properties' => array( 'step_id' => array( 'type' => 'integer', 'description' => __( 'Checkout step ID.', 'cartflows-pro' ), ), 'ob_id' => array( 'type' => 'string', 'description' => __( 'Updated order bump ID.', 'cartflows-pro' ), ), 'updated' => array( 'type' => 'boolean', 'description' => __( 'True if the update was applied.', 'cartflows-pro' ), ), 'fields_set' => array( 'type' => 'array', 'items' => array( 'type' => 'string' ), 'description' => __( 'List of field names that were changed.', 'cartflows-pro' ), ), 'url_edit' => array( 'type' => 'string', 'format' => 'uri', 'description' => __( 'Admin edit URL for the checkout step.', 'cartflows-pro' ), ), ), ), 'execute_callback' => function ( $input ) use ( $runtime ) { return $runtime->update_order_bump( $input ); }, 'meta' => array( 'annotations' => array( 'priority' => 2.0, 'readOnlyHint' => false, 'destructiveHint' => false, 'idempotentHint' => true, 'openWorldHint' => false, ), 'show_in_rest' => true, 'mcp' => array( 'public' => true, 'type' => 'tool', ), ), ), // Toggle an order bump enabled/disabled. CARTFLOWS_PRO_ABILITY_API_NAMESPACE . 'toggle-order-bump' => array( 'label' => __( 'Toggle order bump enabled/disabled', 'cartflows-pro' ), 'description' => __( 'Enables or disables an order bump on a checkout step by setting its status field. Requires the cartflows_pro_abilities_api_write option to be enabled.', 'cartflows-pro' ), 'category' => 'cartflows-pro', 'permission_callback' => function () use ( $runtime ) { return ( get_option( 'cartflows_pro_abilities_api_write', true ) && $runtime->permission_callback( 'cartflows_manage_flows_steps' ) ); }, 'input_schema' => array( 'type' => 'object', 'required' => array( 'step_id', 'ob_id', 'enabled' ), 'properties' => array( 'step_id' => array( 'type' => 'integer', 'description' => __( 'The checkout step post ID.', 'cartflows-pro' ), ), 'ob_id' => array( 'type' => 'string', 'description' => __( 'The order bump unique ID.', 'cartflows-pro' ), ), 'enabled' => array( 'type' => 'boolean', 'description' => __( 'True to enable the order bump; false to disable it.', 'cartflows-pro' ), ), ), ), 'output_schema' => array( 'type' => 'object', 'properties' => array( 'step_id' => array( 'type' => 'integer', 'description' => __( 'Checkout step ID.', 'cartflows-pro' ), ), 'ob_id' => array( 'type' => 'string', 'description' => __( 'Order bump ID.', 'cartflows-pro' ), ), 'is_enabled' => array( 'type' => 'boolean', 'description' => __( 'Current enabled state.', 'cartflows-pro' ), ), 'message' => array( 'type' => 'string', 'description' => __( 'Human-readable result message.', 'cartflows-pro' ), ), ), ), 'execute_callback' => function ( $input ) use ( $runtime ) { return $runtime->toggle_order_bump( $input ); }, 'meta' => array( 'annotations' => array( 'priority' => 2.0, 'readOnlyHint' => false, 'destructiveHint' => false, 'idempotentHint' => true, 'openWorldHint' => false, ), 'show_in_rest' => true, 'mcp' => array( 'public' => true, 'type' => 'tool', ), ), ), // Get pre-checkout offer configuration for a checkout step. CARTFLOWS_PRO_ABILITY_API_NAMESPACE . 'get-pre-checkout-offer' => array( 'label' => __( 'Get pre-checkout offer settings', 'cartflows-pro' ), 'description' => __( 'Returns the pre-checkout offer configuration for a checkout step: enabled state, product, discount, popup content (title, subtitle, product title, description, button text, skip text), and styling options.', 'cartflows-pro' ), 'category' => 'cartflows-pro', 'permission_callback' => function () use ( $runtime ) { return $runtime->permission_callback( 'cartflows_manage_flows_steps' ); }, 'input_schema' => array( 'type' => 'object', 'required' => array( 'step_id' ), 'properties' => array( 'step_id' => array( 'type' => 'integer', 'description' => __( 'The checkout step post ID.', 'cartflows-pro' ), ), ), ), 'output_schema' => array( 'type' => 'object', 'properties' => array( 'step_id' => array( 'type' => 'integer', 'description' => __( 'Checkout step ID.', 'cartflows-pro' ), ), 'enabled' => array( 'type' => 'boolean', 'description' => __( 'True if pre-checkout offer is enabled.', 'cartflows-pro' ), ), 'product_id' => array( 'type' => 'integer', 'description' => __( 'Offer product ID (0 if none).', 'cartflows-pro' ), ), 'product_name' => array( 'type' => 'string', 'description' => __( 'Product name.', 'cartflows-pro' ), ), 'discount_type' => array( 'type' => 'string', 'description' => __( 'Discount type.', 'cartflows-pro' ), ), 'discount_value' => array( 'type' => 'number', 'description' => __( 'Discount amount.', 'cartflows-pro' ), ), 'popup_title' => array( 'type' => 'string', 'description' => __( 'Popup title text.', 'cartflows-pro' ), ), 'popup_sub_title' => array( 'type' => 'string', 'description' => __( 'Popup subtitle text.', 'cartflows-pro' ), ), 'product_title' => array( 'type' => 'string', 'description' => __( 'Product title override.', 'cartflows-pro' ), ), 'description' => array( 'type' => 'string', 'description' => __( 'Offer description text.', 'cartflows-pro' ), ), 'button_text' => array( 'type' => 'string', 'description' => __( 'Accept button text.', 'cartflows-pro' ), ), 'skip_button_text' => array( 'type' => 'string', 'description' => __( 'Skip/decline button text.', 'cartflows-pro' ), ), 'bg_color' => array( 'type' => 'string', 'description' => __( 'Background color.', 'cartflows-pro' ), ), 'title_color' => array( 'type' => 'string', 'description' => __( 'Title color.', 'cartflows-pro' ), ), ), ), 'execute_callback' => function ( $input ) use ( $runtime ) { return $runtime->get_pre_checkout_offer( $input ); }, 'meta' => array( 'annotations' => array( 'priority' => 1.0, 'readOnlyHint' => true, 'destructiveHint' => false, 'idempotentHint' => true, 'openWorldHint' => false, ), 'show_in_rest' => true, 'mcp' => array( 'public' => true, 'type' => 'tool', ), ), ), // Update pre-checkout offer settings. CARTFLOWS_PRO_ABILITY_API_NAMESPACE . 'update-pre-checkout-offer' => array( 'label' => __( 'Update pre-checkout offer settings', 'cartflows-pro' ), 'description' => __( 'Updates the pre-checkout offer configuration for a checkout step: enable/disable, product, discount, popup content. Requires the cartflows_pro_abilities_api_write option to be enabled.', 'cartflows-pro' ), 'category' => 'cartflows-pro', 'permission_callback' => function () use ( $runtime ) { return ( get_option( 'cartflows_pro_abilities_api_write', true ) && $runtime->permission_callback( 'cartflows_manage_flows_steps' ) ); }, 'input_schema' => array( 'type' => 'object', 'required' => array( 'step_id' ), 'properties' => array( 'step_id' => array( 'type' => 'integer', 'description' => __( 'The checkout step post ID.', 'cartflows-pro' ), ), 'enabled' => array( 'type' => 'string', 'default' => '__unchanged__', 'description' => __( 'Enable pre-checkout offer: yes or no.', 'cartflows-pro' ), ), 'product_id' => array( 'type' => 'integer', 'default' => 0, 'description' => __( 'Product ID. Set to 0 to leave unchanged.', 'cartflows-pro' ), ), 'discount_type' => array( 'type' => 'string', 'default' => '__unchanged__', 'description' => __( 'Discount type: percent, price, or empty.', 'cartflows-pro' ), ), 'discount_value' => array( 'type' => 'number', 'default' => -1, 'description' => __( 'Discount amount. Set to -1 to leave unchanged.', 'cartflows-pro' ), ), 'popup_title' => array( 'type' => 'string', 'default' => '__unchanged__', 'description' => __( 'Popup title text.', 'cartflows-pro' ), ), 'popup_sub_title' => array( 'type' => 'string', 'default' => '__unchanged__', 'description' => __( 'Popup subtitle text.', 'cartflows-pro' ), ), 'product_title' => array( 'type' => 'string', 'default' => '__unchanged__', 'description' => __( 'Product title override.', 'cartflows-pro' ), ), 'description' => array( 'type' => 'string', 'default' => '__unchanged__', 'description' => __( 'Offer description text.', 'cartflows-pro' ), ), 'button_text' => array( 'type' => 'string', 'default' => '__unchanged__', 'description' => __( 'Accept button text.', 'cartflows-pro' ), ), 'skip_button_text' => array( 'type' => 'string', 'default' => '__unchanged__', 'description' => __( 'Skip/decline button text.', 'cartflows-pro' ), ), ), ), 'output_schema' => array( 'type' => 'object', 'properties' => array( 'step_id' => array( 'type' => 'integer', 'description' => __( 'Checkout step ID.', 'cartflows-pro' ), ), 'updated' => array( 'type' => 'boolean', 'description' => __( 'True if the update was applied.', 'cartflows-pro' ), ), 'fields_set' => array( 'type' => 'array', 'items' => array( 'type' => 'string' ), 'description' => __( 'Fields that were changed.', 'cartflows-pro' ), ), 'url_edit' => array( 'type' => 'string', 'format' => 'uri', 'description' => __( 'Admin edit URL for the checkout step.', 'cartflows-pro' ), ), ), ), 'execute_callback' => function ( $input ) use ( $runtime ) { return $runtime->update_pre_checkout_offer( $input ); }, 'meta' => array( 'annotations' => array( 'priority' => 2.0, 'readOnlyHint' => false, 'destructiveHint' => false, 'idempotentHint' => true, 'openWorldHint' => false, ), 'show_in_rest' => true, 'mcp' => array( 'public' => true, 'type' => 'tool', ), ), ), // Get checkout product options configuration. CARTFLOWS_PRO_ABILITY_API_NAMESPACE . 'get-checkout-product-options' => array( 'label' => __( 'Get checkout product options', 'cartflows-pro' ), 'description' => __( 'Returns the product options configuration for a checkout step: enabled state, selection mode (force-all/single/multiple), product list with per-product discount and quantity, variation display mode, quantity toggle, product images, section title, position, and skin.', 'cartflows-pro' ), 'category' => 'cartflows-pro', 'permission_callback' => function () use ( $runtime ) { return $runtime->permission_callback( 'cartflows_manage_flows_steps' ); }, 'input_schema' => array( 'type' => 'object', 'required' => array( 'step_id' ), 'properties' => array( 'step_id' => array( 'type' => 'integer', 'description' => __( 'The checkout step post ID.', 'cartflows-pro' ), ), ), ), 'output_schema' => array( 'type' => 'object', 'properties' => array( 'step_id' => array( 'type' => 'integer', 'description' => __( 'Checkout step ID.', 'cartflows-pro' ), ), 'enabled' => array( 'type' => 'boolean', 'description' => __( 'True if product options are enabled.', 'cartflows-pro' ), ), 'selection_mode' => array( 'type' => 'string', 'description' => __( 'Product selection mode: force-all, single, or multiple.', 'cartflows-pro' ), ), 'title' => array( 'type' => 'string', 'description' => __( 'Section title (e.g. "Your Products").', 'cartflows-pro' ), ), 'position' => array( 'type' => 'string', 'description' => __( 'Section position: after-customer, before-customer, before-order, instant-checkout.', 'cartflows-pro' ), ), 'skin' => array( 'type' => 'string', 'description' => __( 'Visual skin: classic or cards.', 'cartflows-pro' ), ), 'variation_enabled' => array( 'type' => 'boolean', 'description' => __( 'True if variation selection is enabled.', 'cartflows-pro' ), ), 'variation_mode' => array( 'type' => 'string', 'description' => __( 'Variation display mode: inline or popup.', 'cartflows-pro' ), ), 'quantity_enabled' => array( 'type' => 'boolean', 'description' => __( 'True if quantity field is enabled.', 'cartflows-pro' ), ), 'images_enabled' => array( 'type' => 'boolean', 'description' => __( 'True if product images are shown.', 'cartflows-pro' ), ), 'products' => array( 'type' => 'array', 'items' => array( 'type' => 'object', 'properties' => array( 'product_id' => array( 'type' => 'integer', 'description' => __( 'Product ID.', 'cartflows-pro' ), ), 'product_name' => array( 'type' => 'string', 'description' => __( 'Product name.', 'cartflows-pro' ), ), 'quantity' => array( 'type' => 'integer', 'description' => __( 'Quantity.', 'cartflows-pro' ), ), 'discount_type' => array( 'type' => 'string', 'description' => __( 'Discount type.', 'cartflows-pro' ), ), 'discount_value' => array( 'type' => 'number', 'description' => __( 'Discount amount.', 'cartflows-pro' ), ), 'unique_id' => array( 'type' => 'string', 'description' => __( 'Unique product option ID.', 'cartflows-pro' ), ), ), ), ), ), ), 'execute_callback' => function ( $input ) use ( $runtime ) { return $runtime->get_checkout_product_options( $input ); }, 'meta' => array( 'annotations' => array( 'priority' => 1.0, 'readOnlyHint' => true, 'destructiveHint' => false, 'idempotentHint' => true, 'openWorldHint' => false, ), 'show_in_rest' => true, 'mcp' => array( 'public' => true, 'type' => 'tool', ), ), ), // Get checkout conditional routing rules. CARTFLOWS_PRO_ABILITY_API_NAMESPACE . 'get-checkout-rules' => array( 'label' => __( 'Get checkout conditional rules', 'cartflows-pro' ), 'description' => __( 'Returns the conditional routing rules for a checkout step: enabled state, default next step, and rule groups with conditions (cart item, cart total, coupon, etc.) and target step IDs. These rules determine which step a customer is routed to after checkout based on cart conditions.', 'cartflows-pro' ), 'category' => 'cartflows-pro', 'permission_callback' => function () use ( $runtime ) { return $runtime->permission_callback( 'cartflows_manage_flows_steps' ); }, 'input_schema' => array( 'type' => 'object', 'required' => array( 'step_id' ), 'properties' => array( 'step_id' => array( 'type' => 'integer', 'description' => __( 'The checkout step post ID.', 'cartflows-pro' ), ), ), ), 'output_schema' => array( 'type' => 'object', 'properties' => array( 'step_id' => array( 'type' => 'integer', 'description' => __( 'Checkout step ID.', 'cartflows-pro' ), ), 'enabled' => array( 'type' => 'boolean', 'description' => __( 'True if conditional rules are enabled.', 'cartflows-pro' ), ), 'default_step' => array( 'type' => 'string', 'description' => __( 'Default next step ID when no rules match (empty if not set).', 'cartflows-pro' ), ), 'rule_groups' => array( 'type' => 'array', 'items' => array( 'type' => 'object', 'properties' => array( 'group_id' => array( 'type' => 'string', 'description' => __( 'Rule group identifier.', 'cartflows-pro' ), ), 'step_id' => array( 'type' => 'string', 'description' => __( 'Target step ID for this group.', 'cartflows-pro' ), ), 'rules' => array( 'type' => 'array', 'items' => array( 'type' => 'object', 'properties' => array( 'rule_id' => array( 'type' => 'string', 'description' => __( 'Rule identifier.', 'cartflows-pro' ), ), 'condition' => array( 'type' => 'string', 'description' => __( 'Condition type: cart_item, cart_total, cart_item_count, cart_shipping_method, cart_coupons, cart_item_category, cart_item_tag.', 'cartflows-pro' ), ), 'operator' => array( 'type' => 'string', 'description' => __( 'Comparison operator.', 'cartflows-pro' ), ), 'value' => array( 'type' => 'string', 'description' => __( 'Condition value.', 'cartflows-pro' ), ), ), ), ), ), ), ), ), ), 'execute_callback' => function ( $input ) use ( $runtime ) { return $runtime->get_checkout_rules( $input ); }, 'meta' => array( 'annotations' => array( 'priority' => 1.0, 'readOnlyHint' => true, 'destructiveHint' => false, 'idempotentHint' => true, 'openWorldHint' => false, ), 'show_in_rest' => true, 'mcp' => array( 'public' => true, 'type' => 'tool', ), ), ), // Get two-step checkout layout configuration. CARTFLOWS_PRO_ABILITY_API_NAMESPACE . 'get-two-step-config' => array( 'label' => __( 'Get two-step checkout configuration', 'cartflows-pro' ), 'description' => __( 'Returns the two-step (multi-step) checkout layout configuration for a checkout step: step one title/subtitle, step two title/subtitle, note box text and visibility, section width, border style, and offer button text.', 'cartflows-pro' ), 'category' => 'cartflows-pro', 'permission_callback' => function () use ( $runtime ) { return $runtime->permission_callback( 'cartflows_manage_flows_steps' ); }, 'input_schema' => array( 'type' => 'object', 'required' => array( 'step_id' ), 'properties' => array( 'step_id' => array( 'type' => 'integer', 'description' => __( 'The checkout step post ID.', 'cartflows-pro' ), ), ), ), 'output_schema' => array( 'type' => 'object', 'properties' => array( 'step_id' => array( 'type' => 'integer', 'description' => __( 'Checkout step ID.', 'cartflows-pro' ), ), 'note_enabled' => array( 'type' => 'boolean', 'description' => __( 'True if the note box is enabled.', 'cartflows-pro' ), ), 'note_text' => array( 'type' => 'string', 'description' => __( 'Note box text.', 'cartflows-pro' ), ), 'note_text_color' => array( 'type' => 'string', 'description' => __( 'Note text color.', 'cartflows-pro' ), ), 'note_bg_color' => array( 'type' => 'string', 'description' => __( 'Note background color.', 'cartflows-pro' ), ), 'step_one_title' => array( 'type' => 'string', 'description' => __( 'Step one tab title.', 'cartflows-pro' ), ), 'step_one_sub_title' => array( 'type' => 'string', 'description' => __( 'Step one tab subtitle.', 'cartflows-pro' ), ), 'step_two_title' => array( 'type' => 'string', 'description' => __( 'Step two tab title.', 'cartflows-pro' ), ), 'step_two_sub_title' => array( 'type' => 'string', 'description' => __( 'Step two tab subtitle.', 'cartflows-pro' ), ), 'offer_button_title' => array( 'type' => 'string', 'description' => __( 'Offer button title.', 'cartflows-pro' ), ), 'offer_button_sub_title' => array( 'type' => 'string', 'description' => __( 'Offer button subtitle.', 'cartflows-pro' ), ), 'section_width' => array( 'type' => 'string', 'description' => __( 'Two-step section width in pixels.', 'cartflows-pro' ), ), 'section_border' => array( 'type' => 'string', 'description' => __( 'Section border style.', 'cartflows-pro' ), ), ), ), 'execute_callback' => function ( $input ) use ( $runtime ) { return $runtime->get_two_step_config( $input ); }, 'meta' => array( 'annotations' => array( 'priority' => 1.0, 'readOnlyHint' => true, 'destructiveHint' => false, 'idempotentHint' => true, 'openWorldHint' => false, ), 'show_in_rest' => true, 'mcp' => array( 'public' => true, 'type' => 'tool', ), ), ), // Get checkout Pro settings summary. CARTFLOWS_PRO_ABILITY_API_NAMESPACE . 'get-checkout-pro-settings' => array( 'label' => __( 'Get checkout Pro settings summary', 'cartflows-pro' ), 'description' => __( 'Returns a unified summary of all Pro-specific settings on a checkout step: order bumps count and active count, pre-checkout offer status, product options mode, two-step checkout layout, conditional rules status, browser tab animation, and advance fields setting. Useful for quickly auditing what Pro features are active on a checkout.', 'cartflows-pro' ), 'category' => 'cartflows-pro', 'permission_callback' => function () use ( $runtime ) { return $runtime->permission_callback( 'cartflows_manage_flows_steps' ); }, 'input_schema' => array( 'type' => 'object', 'required' => array( 'step_id' ), 'properties' => array( 'step_id' => array( 'type' => 'integer', 'description' => __( 'The checkout step post ID.', 'cartflows-pro' ), ), ), ), 'output_schema' => array( 'type' => 'object', 'properties' => array( 'step_id' => array( 'type' => 'integer', 'description' => __( 'Checkout step ID.', 'cartflows-pro' ), ), 'order_bumps_total' => array( 'type' => 'integer', 'description' => __( 'Total order bumps configured.', 'cartflows-pro' ), ), 'order_bumps_active' => array( 'type' => 'integer', 'description' => __( 'Number of enabled order bumps.', 'cartflows-pro' ), ), 'pre_checkout_offer_enabled' => array( 'type' => 'boolean', 'description' => __( 'True if pre-checkout offer is enabled.', 'cartflows-pro' ), ), 'product_options_enabled' => array( 'type' => 'boolean', 'description' => __( 'True if product options are enabled.', 'cartflows-pro' ), ), 'product_options_mode' => array( 'type' => 'string', 'description' => __( 'Product selection mode: force-all, single, or multiple.', 'cartflows-pro' ), ), 'checkout_layout' => array( 'type' => 'string', 'description' => __( 'Checkout layout from the free plugin (one-column, two-column, two-step).', 'cartflows-pro' ), ), 'conditional_rules_enabled' => array( 'type' => 'boolean', 'description' => __( 'True if conditional routing rules are active.', 'cartflows-pro' ), ), 'browser_tab_animation' => array( 'type' => 'boolean', 'description' => __( 'True if browser tab animation is enabled.', 'cartflows-pro' ), ), 'advance_fields_enabled' => array( 'type' => 'boolean', 'description' => __( 'True if advance field options are enabled.', 'cartflows-pro' ), ), 'url_edit' => array( 'type' => 'string', 'format' => 'uri', 'description' => __( 'Admin edit URL for the checkout step.', 'cartflows-pro' ), ), ), ), 'execute_callback' => function ( $input ) use ( $runtime ) { return $runtime->get_checkout_pro_settings( $input ); }, 'meta' => array( 'annotations' => array( 'priority' => 1.0, 'readOnlyHint' => true, 'destructiveHint' => false, 'idempotentHint' => true, 'openWorldHint' => false, ), 'show_in_rest' => true, 'mcp' => array( 'public' => true, 'type' => 'tool', ), ), ), // ============================================================ // Orders Module // ============================================================ // List all WooCommerce orders for a specific funnel. CARTFLOWS_PRO_ABILITY_API_NAMESPACE . 'list-funnel-orders' => array( 'label' => __( 'List funnel orders', 'cartflows-pro' ), 'description' => __( 'Returns a paginated list of all WooCommerce orders associated with a specific funnel (flow), including both main checkout orders and child offer orders (upsell/downsell). Filter by order status. Each entry shows order type (main or offer), total, currency, status, and date.', 'cartflows-pro' ), 'category' => 'cartflows-pro', 'permission_callback' => function () use ( $runtime ) { return $runtime->permission_callback( 'cartflows_manage_flows_steps' ); }, 'input_schema' => array( 'type' => 'object', 'required' => array( 'flow_id' ), 'properties' => array( 'flow_id' => array( 'type' => 'integer', 'description' => __( 'Funnel (flow) ID to list orders for.', 'cartflows-pro' ), ), 'status' => array( 'type' => 'string', 'default' => 'any', 'description' => __( 'WooCommerce order status to filter by (e.g. "completed", "processing"). Use "any" for all statuses.', 'cartflows-pro' ), ), 'page' => array( 'type' => 'integer', 'description' => __( 'Page number (1-based).', 'cartflows-pro' ), 'default' => 1, ), 'per_page' => array( 'type' => 'integer', 'description' => __( 'Results per page (max 100).', 'cartflows-pro' ), 'default' => 20, ), ), ), 'output_schema' => array( 'type' => 'object', 'properties' => array( 'orders' => array( 'type' => 'array', 'items' => array( 'type' => 'object', 'properties' => array( 'order_id' => array( 'type' => 'integer', 'description' => __( 'WooCommerce order ID.', 'cartflows-pro' ), ), 'order_type' => array( 'type' => 'string', 'description' => __( 'main or offer.', 'cartflows-pro' ), ), 'offer_type' => array( 'type' => 'string', 'description' => __( 'upsell, downsell, or empty for main orders.', 'cartflows-pro' ), ), 'parent_order_id' => array( 'type' => 'integer', 'description' => __( 'Parent order ID (0 for main orders).', 'cartflows-pro' ), ), 'total' => array( 'type' => 'number', 'description' => __( 'Order total (raw float).', 'cartflows-pro' ), ), 'currency' => array( 'type' => 'string', 'description' => __( 'Order currency code.', 'cartflows-pro' ), ), 'status' => array( 'type' => 'string', 'description' => __( 'WooCommerce order status.', 'cartflows-pro' ), ), 'date_created' => array( 'type' => 'string', 'format' => 'date-time', 'description' => __( 'Order creation date (ISO 8601).', 'cartflows-pro' ), ), 'url_edit' => array( 'type' => 'string', 'format' => 'uri', 'description' => __( 'Admin edit URL for the order.', 'cartflows-pro' ), ), ), ), ), 'total' => array( 'type' => 'integer', 'description' => __( 'Total number of matching orders.', 'cartflows-pro' ), ), 'total_pages' => array( 'type' => 'integer', 'description' => __( 'Total number of pages.', 'cartflows-pro' ), ), ), ), 'execute_callback' => function ( $input ) use ( $runtime ) { return $runtime->list_funnel_orders( $input ); }, 'meta' => array( 'annotations' => array( 'priority' => 1.0, 'readOnlyHint' => true, 'destructiveHint' => false, 'idempotentHint' => true, 'openWorldHint' => false, ), 'show_in_rest' => true, 'mcp' => array( 'public' => true, 'type' => 'tool', ), ), ), // Get offer line items from a WooCommerce order. CARTFLOWS_PRO_ABILITY_API_NAMESPACE . 'get-order-offer-items' => array( 'label' => __( 'Get order offer items', 'cartflows-pro' ), 'description' => __( 'Returns the line items in a WooCommerce order that are CartFlows offer items (upsell or downsell). Each item includes the product ID, name, quantity, total, offer type, step ID, transaction ID, and shipping fee. Returns an empty array if the order has no offer items.', 'cartflows-pro' ), 'category' => 'cartflows-pro', 'permission_callback' => function () use ( $runtime ) { return $runtime->permission_callback( 'cartflows_manage_flows_steps' ); }, 'input_schema' => array( 'type' => 'object', 'required' => array( 'order_id' ), 'properties' => array( 'order_id' => array( 'type' => 'integer', 'description' => __( 'The WooCommerce order ID to inspect.', 'cartflows-pro' ), ), ), ), 'output_schema' => array( 'type' => 'object', 'properties' => array( 'order_id' => array( 'type' => 'integer', 'description' => __( 'The queried order ID.', 'cartflows-pro' ), ), 'offer_items' => array( 'type' => 'array', 'items' => array( 'type' => 'object', 'properties' => array( 'item_id' => array( 'type' => 'integer', 'description' => __( 'WooCommerce order item ID.', 'cartflows-pro' ), ), 'product_id' => array( 'type' => 'integer', 'description' => __( 'Product ID.', 'cartflows-pro' ), ), 'product_name' => array( 'type' => 'string', 'description' => __( 'Product name.', 'cartflows-pro' ), ), 'quantity' => array( 'type' => 'integer', 'description' => __( 'Quantity ordered.', 'cartflows-pro' ), ), 'total' => array( 'type' => 'number', 'description' => __( 'Line item total (raw float).', 'cartflows-pro' ), ), 'offer_type' => array( 'type' => 'string', 'description' => __( 'upsell or downsell.', 'cartflows-pro' ), ), 'step_id' => array( 'type' => 'integer', 'description' => __( 'CartFlows step ID that generated this item.', 'cartflows-pro' ), ), 'txn_id' => array( 'type' => 'string', 'description' => __( 'Offer transaction ID (empty if not set).', 'cartflows-pro' ), ), 'shipping_fee' => array( 'type' => 'number', 'description' => __( 'Offer shipping fee (0 if not applicable).', 'cartflows-pro' ), ), ), ), ), 'total_offer_items' => array( 'type' => 'integer', 'description' => __( 'Number of offer items found.', 'cartflows-pro' ), ), ), ), 'execute_callback' => function ( $input ) use ( $runtime ) { return $runtime->get_order_offer_items( $input ); }, 'meta' => array( 'annotations' => array( 'priority' => 1.0, 'readOnlyHint' => true, 'destructiveHint' => false, 'idempotentHint' => true, 'openWorldHint' => false, ), 'show_in_rest' => true, 'mcp' => array( 'public' => true, 'type' => 'tool', ), ), ), // Get global offer order settings. CARTFLOWS_PRO_ABILITY_API_NAMESPACE . 'get-offer-order-settings' => array( 'label' => __( 'Get offer order settings', 'cartflows-pro' ), 'description' => __( 'Returns the global offer order configuration for CartFlows Pro: whether offer orders are created as separate WooCommerce orders or merged into the main checkout order. This setting affects how upsell/downsell purchases appear in WooCommerce order management.', 'cartflows-pro' ), 'category' => 'cartflows-pro', 'permission_callback' => function () use ( $runtime ) { return $runtime->permission_callback( 'cartflows_manage_flows_steps' ); }, 'input_schema' => array( 'type' => 'object', 'properties' => array(), ), 'output_schema' => array( 'type' => 'object', 'properties' => array( 'separate_offer_orders' => array( 'type' => 'string', 'description' => __( 'Order mode: "separate" creates individual WC orders for each offer; "merged" adds offer products to the main checkout order.', 'cartflows-pro' ), ), ), ), 'execute_callback' => function ( $input ) use ( $runtime ) { return $runtime->get_offer_order_settings( $input ); }, 'meta' => array( 'annotations' => array( 'priority' => 1.0, 'readOnlyHint' => true, 'destructiveHint' => false, 'idempotentHint' => true, 'openWorldHint' => false, ), 'show_in_rest' => true, 'mcp' => array( 'public' => true, 'type' => 'tool', ), ), ), // ============================================================ // A/B Test Module // ============================================================ // List all A/B tests across funnels. CARTFLOWS_PRO_ABILITY_API_NAMESPACE . 'list-ab-tests' => array( 'label' => __( 'List A/B tests', 'cartflows-pro' ), 'description' => __( 'Returns a list of all A/B tests across all funnels, or scoped to a single funnel. Each entry shows the control step, test status (not_started, running, or completed), active variants with traffic distribution, and archived variant count.', 'cartflows-pro' ), 'category' => 'cartflows-pro', 'permission_callback' => function () use ( $runtime ) { return $runtime->permission_callback( 'cartflows_manage_flows_steps' ); }, 'input_schema' => array( 'type' => 'object', 'properties' => array( 'flow_id' => array( 'type' => 'integer', 'description' => __( 'Funnel (flow) ID to scope results to. Omit or set to 0 for all funnels.', 'cartflows-pro' ), 'default' => 0, ), ), ), 'output_schema' => array( 'type' => 'object', 'properties' => array( 'tests' => array( 'type' => 'array', 'items' => array( 'type' => 'object', 'properties' => array( 'flow_id' => array( 'type' => 'integer', 'description' => __( 'Funnel ID.', 'cartflows-pro' ), ), 'flow_title' => array( 'type' => 'string', 'description' => __( 'Funnel title.', 'cartflows-pro' ), ), 'control_step_id' => array( 'type' => 'integer', 'description' => __( 'Control step ID (primary step in the test).', 'cartflows-pro' ), ), 'control_step_title' => array( 'type' => 'string', 'description' => __( 'Control step title.', 'cartflows-pro' ), ), 'step_type' => array( 'type' => 'string', 'description' => __( 'Step type (landing, checkout, upsell, downsell, optin, thankyou).', 'cartflows-pro' ), ), 'status' => array( 'type' => 'string', 'description' => __( 'Test status: not_started, running, or completed.', 'cartflows-pro' ), ), 'variations' => array( 'type' => 'array', 'items' => array( 'type' => 'object', 'properties' => array( 'step_id' => array( 'type' => 'integer', 'description' => __( 'Variation step ID.', 'cartflows-pro' ), ), 'traffic' => array( 'type' => 'integer', 'description' => __( 'Traffic percentage (0-100).', 'cartflows-pro' ), ), ), ), 'description' => __( 'Active variations with traffic splits.', 'cartflows-pro' ), ), 'archived_count' => array( 'type' => 'integer', 'description' => __( 'Number of archived variations.', 'cartflows-pro' ), ), ), ), ), 'total' => array( 'type' => 'integer', 'description' => __( 'Total number of A/B tests found.', 'cartflows-pro' ), ), ), ), 'execute_callback' => function ( $input ) use ( $runtime ) { return $runtime->list_ab_tests( $input ); }, 'meta' => array( 'annotations' => array( 'priority' => 1.0, 'readOnlyHint' => true, 'destructiveHint' => false, 'idempotentHint' => true, 'openWorldHint' => false, ), 'show_in_rest' => true, 'mcp' => array( 'public' => true, 'type' => 'tool', ), ), ), // Get full details of a single A/B test. CARTFLOWS_PRO_ABILITY_API_NAMESPACE . 'get-ab-test' => array( 'label' => __( 'Get A/B test details', 'cartflows-pro' ), 'description' => __( 'Returns full details of a single A/B test identified by its control step ID: all active variants with traffic percentages, archived variations with dates and notes, test status (not_started, running, completed), and the flow it belongs to.', 'cartflows-pro' ), 'category' => 'cartflows-pro', 'permission_callback' => function () use ( $runtime ) { return $runtime->permission_callback( 'cartflows_manage_flows_steps' ); }, 'input_schema' => array( 'type' => 'object', 'required' => array( 'step_id' ), 'properties' => array( 'step_id' => array( 'type' => 'integer', 'description' => __( 'The control step ID (or any variation step ID — the control will be resolved automatically).', 'cartflows-pro' ), ), ), ), 'output_schema' => array( 'type' => 'object', 'properties' => array( 'flow_id' => array( 'type' => 'integer', 'description' => __( 'Funnel ID.', 'cartflows-pro' ), ), 'flow_title' => array( 'type' => 'string', 'description' => __( 'Funnel title.', 'cartflows-pro' ), ), 'control_step_id' => array( 'type' => 'integer', 'description' => __( 'Control step ID.', 'cartflows-pro' ), ), 'control_step_title' => array( 'type' => 'string', 'description' => __( 'Control step title.', 'cartflows-pro' ), ), 'step_type' => array( 'type' => 'string', 'description' => __( 'Step type.', 'cartflows-pro' ), ), 'status' => array( 'type' => 'string', 'description' => __( 'Test status: not_started, running, or completed.', 'cartflows-pro' ), ), 'has_ui' => array( 'type' => 'boolean', 'description' => __( 'True if the A/B test UI panel is visible in admin.', 'cartflows-pro' ), ), 'variations' => array( 'type' => 'array', 'items' => array( 'type' => 'object', 'properties' => array( 'step_id' => array( 'type' => 'integer', 'description' => __( 'Variation step ID.', 'cartflows-pro' ), ), 'title' => array( 'type' => 'string', 'description' => __( 'Variation step title.', 'cartflows-pro' ), ), 'traffic' => array( 'type' => 'integer', 'description' => __( 'Traffic percentage (0-100).', 'cartflows-pro' ), ), ), ), 'description' => __( 'Active variations.', 'cartflows-pro' ), ), 'archived_variations' => array( 'type' => 'array', 'items' => array( 'type' => 'object', 'properties' => array( 'step_id' => array( 'type' => 'integer', 'description' => __( 'Archived variation step ID.', 'cartflows-pro' ), ), 'title' => array( 'type' => 'string', 'description' => __( 'Archived variation title.', 'cartflows-pro' ), ), 'note' => array( 'type' => 'string', 'description' => __( 'Step note at archive time.', 'cartflows-pro' ), ), 'deleted' => array( 'type' => 'boolean', 'description' => __( 'True if the step post was deleted.', 'cartflows-pro' ), ), 'date' => array( 'type' => 'string', 'description' => __( 'Formatted archive date.', 'cartflows-pro' ), ), ), ), 'description' => __( 'Archived (concluded) variations.', 'cartflows-pro' ), ), ), ), 'execute_callback' => function ( $input ) use ( $runtime ) { return $runtime->get_ab_test( $input ); }, 'meta' => array( 'annotations' => array( 'priority' => 1.0, 'readOnlyHint' => true, 'destructiveHint' => false, 'idempotentHint' => true, 'openWorldHint' => false, ), 'show_in_rest' => true, 'mcp' => array( 'public' => true, 'type' => 'tool', ), ), ), // Get global A/B test settings. CARTFLOWS_PRO_ABILITY_API_NAMESPACE . 'get-ab-test-settings' => array( 'label' => __( 'Get A/B test settings', 'cartflows-pro' ), 'description' => __( 'Returns the global A/B test configuration for CartFlows Pro: whether the override_permalink setting is enabled (causes the control step URL to show variation content instead of redirecting).', 'cartflows-pro' ), 'category' => 'cartflows-pro', 'permission_callback' => function () use ( $runtime ) { return $runtime->permission_callback( 'cartflows_manage_flows_steps' ); }, 'input_schema' => array( 'type' => 'object', 'properties' => array(), ), 'output_schema' => array( 'type' => 'object', 'properties' => array( 'override_permalink' => array( 'type' => 'string', 'description' => __( 'Whether A/B test variations override the control step URL content instead of redirecting. Values: "enable" or "disable".', 'cartflows-pro' ), ), ), ), 'execute_callback' => function ( $input ) use ( $runtime ) { return $runtime->get_ab_test_settings( $input ); }, 'meta' => array( 'annotations' => array( 'priority' => 1.0, 'readOnlyHint' => true, 'destructiveHint' => false, 'idempotentHint' => true, 'openWorldHint' => false, ), 'show_in_rest' => true, 'mcp' => array( 'public' => true, 'type' => 'tool', ), ), ), // Update A/B test traffic distribution. CARTFLOWS_PRO_ABILITY_API_NAMESPACE . 'update-ab-test-traffic' => array( 'label' => __( 'Update A/B test traffic', 'cartflows-pro' ), 'description' => __( 'Changes the traffic distribution percentages for all active variants in an A/B test. The traffic array must contain one entry per active variation and the values must sum to 100. Requires the cartflows_pro_abilities_api_write option to be enabled.', 'cartflows-pro' ), 'category' => 'cartflows-pro', 'permission_callback' => function () use ( $runtime ) { return ( get_option( 'cartflows_pro_abilities_api_write', true ) && $runtime->permission_callback( 'cartflows_manage_flows_steps' ) ); }, 'input_schema' => array( 'type' => 'object', 'required' => array( 'flow_id', 'step_id', 'traffic' ), 'properties' => array( 'flow_id' => array( 'type' => 'integer', 'description' => __( 'Funnel (flow) ID.', 'cartflows-pro' ), ), 'step_id' => array( 'type' => 'integer', 'description' => __( 'Control step ID of the A/B test.', 'cartflows-pro' ), ), 'traffic' => array( 'type' => 'array', 'items' => array( 'type' => 'object', 'properties' => array( 'step_id' => array( 'type' => 'integer', 'description' => __( 'Variation step ID.', 'cartflows-pro' ), ), 'traffic' => array( 'type' => 'integer', 'description' => __( 'Traffic percentage (0-100).', 'cartflows-pro' ), ), ), ), 'description' => __( 'Array of {step_id, traffic} pairs. Must include all active variations and sum to 100.', 'cartflows-pro' ), ), ), ), 'output_schema' => array( 'type' => 'object', 'properties' => array( 'success' => array( 'type' => 'boolean', 'description' => __( 'Whether the update was successful.', 'cartflows-pro' ), ), 'variations' => array( 'type' => 'array', 'items' => array( 'type' => 'object', 'properties' => array( 'step_id' => array( 'type' => 'integer', 'description' => __( 'Variation step ID.', 'cartflows-pro' ), ), 'traffic' => array( 'type' => 'integer', 'description' => __( 'Updated traffic percentage.', 'cartflows-pro' ), ), ), ), 'description' => __( 'Updated traffic distribution.', 'cartflows-pro' ), ), ), ), 'execute_callback' => function ( $input ) use ( $runtime ) { return $runtime->update_ab_test_traffic( $input ); }, 'meta' => array( 'annotations' => array( 'priority' => 2.0, 'readOnlyHint' => false, 'destructiveHint' => false, 'idempotentHint' => true, 'openWorldHint' => false, ), 'show_in_rest' => true, 'mcp' => array( 'public' => true, 'type' => 'tool', ), ), ), // Start or stop an A/B test. CARTFLOWS_PRO_ABILITY_API_NAMESPACE . 'start-ab-test' => array( 'label' => __( 'Start or stop A/B test', 'cartflows-pro' ), 'description' => __( 'Toggles a A/B test between running and stopped states. When running, visitors are distributed across variations according to traffic percentages. When stopped, all visitors see the control step. Requires the cartflows_pro_abilities_api_write option to be enabled.', 'cartflows-pro' ), 'category' => 'cartflows-pro', 'permission_callback' => function () use ( $runtime ) { return ( get_option( 'cartflows_pro_abilities_api_write', true ) && $runtime->permission_callback( 'cartflows_manage_flows_steps' ) ); }, 'input_schema' => array( 'type' => 'object', 'required' => array( 'flow_id', 'step_id' ), 'properties' => array( 'flow_id' => array( 'type' => 'integer', 'description' => __( 'Funnel (flow) ID.', 'cartflows-pro' ), ), 'step_id' => array( 'type' => 'integer', 'description' => __( 'Control step ID of the A/B test.', 'cartflows-pro' ), ), ), ), 'output_schema' => array( 'type' => 'object', 'properties' => array( 'success' => array( 'type' => 'boolean', 'description' => __( 'Whether the toggle was successful.', 'cartflows-pro' ), ), 'running' => array( 'type' => 'boolean', 'description' => __( 'True if the test is now running; false if stopped.', 'cartflows-pro' ), ), 'message' => array( 'type' => 'string', 'description' => __( 'Human-readable status message.', 'cartflows-pro' ), ), ), ), 'execute_callback' => function ( $input ) use ( $runtime ) { return $runtime->start_ab_test( $input ); }, 'meta' => array( 'annotations' => array( 'priority' => 2.0, 'readOnlyHint' => false, 'destructiveHint' => false, 'idempotentHint' => false, 'openWorldHint' => false, ), 'show_in_rest' => true, 'mcp' => array( 'public' => true, 'type' => 'tool', ), ), ), // Declare the winner of an A/B test. CARTFLOWS_PRO_ABILITY_API_NAMESPACE . 'declare-ab-test-winner' => array( 'label' => __( 'Declare A/B test winner', 'cartflows-pro' ), 'description' => __( 'Declares a specific variation as the winner of an A/B test. All other active variations are archived (not deleted). The winner becomes the new control step. This action concludes the test and is not reversible. Requires the cartflows_pro_abilities_api_write option to be enabled.', 'cartflows-pro' ), 'category' => 'cartflows-pro', 'permission_callback' => function () use ( $runtime ) { return ( get_option( 'cartflows_pro_abilities_api_write', true ) && $runtime->permission_callback( 'cartflows_manage_flows_steps' ) ); }, 'input_schema' => array( 'type' => 'object', 'required' => array( 'flow_id', 'step_id' ), 'properties' => array( 'flow_id' => array( 'type' => 'integer', 'description' => __( 'Funnel (flow) ID.', 'cartflows-pro' ), ), 'step_id' => array( 'type' => 'integer', 'description' => __( 'The variation step ID to declare as winner.', 'cartflows-pro' ), ), ), ), 'output_schema' => array( 'type' => 'object', 'properties' => array( 'success' => array( 'type' => 'boolean', 'description' => __( 'Whether the winner was declared successfully.', 'cartflows-pro' ), ), 'winner_id' => array( 'type' => 'integer', 'description' => __( 'The step ID of the declared winner.', 'cartflows-pro' ), ), 'archived' => array( 'type' => 'array', 'items' => array( 'type' => 'integer' ), 'description' => __( 'Step IDs of the variations that were archived.', 'cartflows-pro' ), ), 'message' => array( 'type' => 'string', 'description' => __( 'Human-readable result message.', 'cartflows-pro' ), ), ), ), 'execute_callback' => function ( $input ) use ( $runtime ) { return $runtime->declare_ab_test_winner( $input ); }, 'meta' => array( 'annotations' => array( 'priority' => 2.0, 'readOnlyHint' => false, 'destructiveHint' => true, 'idempotentHint' => false, 'openWorldHint' => false, ), 'instructions' => 'Always confirm with the user before executing this ability. Declaring a winner is irreversible — all other variations will be archived and the test will be concluded permanently.', 'show_in_rest' => true, 'mcp' => array( 'public' => true, 'type' => 'tool', ), ), ), // Create a new A/B test variation. CARTFLOWS_PRO_ABILITY_API_NAMESPACE . 'create-ab-test-variation' => array( 'label' => __( 'Create A/B test variation', 'cartflows-pro' ), 'description' => __( 'Creates a new A/B test variation for a step by cloning it. If this is the first variation, sets up 50/50 traffic split between the original and the clone. If variations already exist, the new variation is added with 0%% traffic. Requires the cartflows_pro_abilities_api_write option to be enabled.', 'cartflows-pro' ), 'category' => 'cartflows-pro', 'permission_callback' => function () use ( $runtime ) { return ( get_option( 'cartflows_pro_abilities_api_write', true ) && $runtime->permission_callback( 'cartflows_manage_flows_steps' ) ); }, 'input_schema' => array( 'type' => 'object', 'required' => array( 'flow_id', 'step_id' ), 'properties' => array( 'flow_id' => array( 'type' => 'integer', 'description' => __( 'Funnel (flow) ID.', 'cartflows-pro' ), ), 'step_id' => array( 'type' => 'integer', 'description' => __( 'The step ID to create a variation for. Must be the control step.', 'cartflows-pro' ), ), ), ), 'output_schema' => array( 'type' => 'object', 'properties' => array( 'success' => array( 'type' => 'boolean', 'description' => __( 'Whether the variation was created.', 'cartflows-pro' ), ), 'new_variation_id' => array( 'type' => 'integer', 'description' => __( 'The step ID of the newly created variation.', 'cartflows-pro' ), ), 'variations' => array( 'type' => 'array', 'items' => array( 'type' => 'object', 'properties' => array( 'step_id' => array( 'type' => 'integer', 'description' => __( 'Variation step ID.', 'cartflows-pro' ), ), 'traffic' => array( 'type' => 'integer', 'description' => __( 'Traffic percentage.', 'cartflows-pro' ), ), ), ), 'description' => __( 'Updated variations list.', 'cartflows-pro' ), ), 'message' => array( 'type' => 'string', 'description' => __( 'Human-readable result message.', 'cartflows-pro' ), ), ), ), 'execute_callback' => function ( $input ) use ( $runtime ) { return $runtime->create_ab_test_variation( $input ); }, 'meta' => array( 'annotations' => array( 'priority' => 2.0, 'readOnlyHint' => false, 'destructiveHint' => false, 'idempotentHint' => false, 'openWorldHint' => false, ), 'show_in_rest' => true, 'mcp' => array( 'public' => true, 'type' => 'tool', ), ), ), // Archive an A/B test variation. CARTFLOWS_PRO_ABILITY_API_NAMESPACE . 'archive-ab-test-variation' => array( 'label' => __( 'Archive A/B test variation', 'cartflows-pro' ), 'description' => __( 'Archives (soft-removes) a variation from an active A/B test. The step is preserved but removed from traffic distribution. Can be restored later. The test is stopped after archiving. Requires the cartflows_pro_abilities_api_write option to be enabled.', 'cartflows-pro' ), 'category' => 'cartflows-pro', 'permission_callback' => function () use ( $runtime ) { return ( get_option( 'cartflows_pro_abilities_api_write', true ) && $runtime->permission_callback( 'cartflows_manage_flows_steps' ) ); }, 'input_schema' => array( 'type' => 'object', 'required' => array( 'flow_id', 'step_id' ), 'properties' => array( 'flow_id' => array( 'type' => 'integer', 'description' => __( 'Funnel (flow) ID.', 'cartflows-pro' ), ), 'step_id' => array( 'type' => 'integer', 'description' => __( 'The variation step ID to archive.', 'cartflows-pro' ), ), ), ), 'output_schema' => array( 'type' => 'object', 'properties' => array( 'success' => array( 'type' => 'boolean', 'description' => __( 'Whether the variation was archived.', 'cartflows-pro' ), ), 'message' => array( 'type' => 'string', 'description' => __( 'Human-readable result message.', 'cartflows-pro' ), ), ), ), 'execute_callback' => function ( $input ) use ( $runtime ) { return $runtime->archive_ab_test_variation( $input ); }, 'meta' => array( 'annotations' => array( 'priority' => 2.0, 'readOnlyHint' => false, 'destructiveHint' => false, 'idempotentHint' => false, 'openWorldHint' => false, ), 'show_in_rest' => true, 'mcp' => array( 'public' => true, 'type' => 'tool', ), ), ), // Restore an archived A/B test variation. CARTFLOWS_PRO_ABILITY_API_NAMESPACE . 'restore-ab-test-variation' => array( 'label' => __( 'Restore A/B test variation', 'cartflows-pro' ), 'description' => __( 'Restores a previously archived variation back into the active A/B test. The variation is added with 0%% traffic — use update-ab-test-traffic to set the desired split after restoring. Requires the cartflows_pro_abilities_api_write option to be enabled.', 'cartflows-pro' ), 'category' => 'cartflows-pro', 'permission_callback' => function () use ( $runtime ) { return ( get_option( 'cartflows_pro_abilities_api_write', true ) && $runtime->permission_callback( 'cartflows_manage_flows_steps' ) ); }, 'input_schema' => array( 'type' => 'object', 'required' => array( 'flow_id', 'step_id', 'control_id' ), 'properties' => array( 'flow_id' => array( 'type' => 'integer', 'description' => __( 'Funnel (flow) ID.', 'cartflows-pro' ), ), 'step_id' => array( 'type' => 'integer', 'description' => __( 'The archived variation step ID to restore.', 'cartflows-pro' ), ), 'control_id' => array( 'type' => 'integer', 'description' => __( 'The control step ID of the A/B test.', 'cartflows-pro' ), ), ), ), 'output_schema' => array( 'type' => 'object', 'properties' => array( 'success' => array( 'type' => 'boolean', 'description' => __( 'Whether the variation was restored.', 'cartflows-pro' ), ), 'message' => array( 'type' => 'string', 'description' => __( 'Human-readable result message.', 'cartflows-pro' ), ), ), ), 'execute_callback' => function ( $input ) use ( $runtime ) { return $runtime->restore_ab_test_variation( $input ); }, 'meta' => array( 'annotations' => array( 'priority' => 2.0, 'readOnlyHint' => false, 'destructiveHint' => false, 'idempotentHint' => false, 'openWorldHint' => false, ), 'show_in_rest' => true, 'mcp' => array( 'public' => true, 'type' => 'tool', ), ), ), // ============================================================ // Gateways Module (read-only) // ============================================================ // List all CartFlows Pro supported payment gateways with availability status. CARTFLOWS_PRO_ABILITY_API_NAMESPACE . 'list-supported-gateways' => array( 'label' => __( 'List supported gateways', 'cartflows-pro' ), 'description' => __( 'Returns the full list of payment gateways that CartFlows Pro supports for upsell/downsell offers, cross-referenced with the gateways currently active in WooCommerce. Each entry includes the gateway key, label, and whether it is available.', 'cartflows-pro' ), 'category' => 'cartflows-pro', 'permission_callback' => function () use ( $runtime ) { return $runtime->permission_callback( 'cartflows_manage_flows_steps' ); }, 'input_schema' => array( 'type' => 'object', 'properties' => array(), ), 'output_schema' => array( 'type' => 'object', 'properties' => array( 'gateways' => array( 'type' => 'array', 'items' => array( 'type' => 'object', 'properties' => array( 'key' => array( 'type' => 'string', 'description' => __( 'Gateway identifier (e.g. stripe, ppcp-gateway, bacs).', 'cartflows-pro' ), ), 'label' => array( 'type' => 'string', 'description' => __( 'Human-readable gateway name from WooCommerce (empty if gateway plugin not installed).', 'cartflows-pro' ), ), 'is_available' => array( 'type' => 'boolean', 'description' => __( 'True if the gateway is currently enabled and available in WooCommerce.', 'cartflows-pro' ), ), ), ), ), 'total_supported' => array( 'type' => 'integer', 'description' => __( 'Total number of gateways CartFlows Pro supports.', 'cartflows-pro' ), ), 'total_available' => array( 'type' => 'integer', 'description' => __( 'Number of supported gateways currently active in WooCommerce.', 'cartflows-pro' ), ), ), ), 'execute_callback' => function ( $input ) use ( $runtime ) { return $runtime->list_supported_gateways( $input ); }, 'meta' => array( 'annotations' => array( 'priority' => 1.0, 'readOnlyHint' => true, 'destructiveHint' => false, 'idempotentHint' => true, 'openWorldHint' => false, ), 'show_in_rest' => true, 'mcp' => array( 'public' => true, 'type' => 'tool', ), ), ), // ============================================================ // Creation Abilities (write-gated) // ============================================================ // Create a new Pro step (upsell or downsell) in a funnel. CARTFLOWS_PRO_ABILITY_API_NAMESPACE . 'create-step' => array( 'label' => __( 'Create step', 'cartflows-pro' ), 'description' => __( 'Creates a new upsell or downsell step in a funnel. Only Pro step types (upsell, downsell) are accepted — use cartflows/create-step for free step types. Requires the cartflows_pro_abilities_api_write option to be enabled.', 'cartflows-pro' ), 'category' => 'cartflows-pro', 'permission_callback' => function () use ( $runtime ) { return ( get_option( 'cartflows_pro_abilities_api_write', true ) && $runtime->permission_callback( 'cartflows_manage_flows_steps' ) ); }, 'input_schema' => array( 'type' => 'object', 'required' => array( 'flow_id', 'title', 'type' ), 'properties' => array( 'flow_id' => array( 'type' => 'integer', 'description' => __( 'The funnel (flow) ID to add the step to.', 'cartflows-pro' ), ), 'title' => array( 'type' => 'string', 'description' => __( 'Title for the new step.', 'cartflows-pro' ), ), 'type' => array( 'type' => 'string', 'enum' => array( 'upsell', 'downsell' ), 'description' => __( 'Step type. Must be upsell or downsell.', 'cartflows-pro' ), ), ), ), 'output_schema' => array( 'type' => 'object', 'properties' => array( 'step_id' => array( 'type' => 'integer', 'description' => __( 'The newly created step ID.', 'cartflows-pro' ), ), 'flow_id' => array( 'type' => 'integer', 'description' => __( 'The parent funnel ID.', 'cartflows-pro' ), ), 'title' => array( 'type' => 'string', 'description' => __( 'Step title.', 'cartflows-pro' ), ), 'type' => array( 'type' => 'string', 'description' => __( 'Step type (upsell or downsell).', 'cartflows-pro' ), ), 'edit_url' => array( 'type' => 'string', 'format' => 'uri', 'description' => __( 'Admin edit URL for the new step.', 'cartflows-pro' ), ), ), ), 'execute_callback' => function ( $input ) use ( $runtime ) { return $runtime->create_step( $input ); }, 'meta' => array( 'annotations' => array( 'priority' => 2.0, 'readOnlyHint' => false, 'destructiveHint' => false, 'idempotentHint' => false, 'openWorldHint' => false, ), 'show_in_rest' => true, 'mcp' => array( 'public' => true, 'type' => 'tool', ), ), ), // Create a new order bump on a checkout step. CARTFLOWS_PRO_ABILITY_API_NAMESPACE . 'create-order-bump' => array( 'label' => __( 'Create order bump', 'cartflows-pro' ), 'description' => __( 'Creates a new order bump on a checkout step with default settings. Optionally assigns a WooCommerce product. Requires the cartflows_pro_abilities_api_write option to be enabled.', 'cartflows-pro' ), 'category' => 'cartflows-pro', 'permission_callback' => function () use ( $runtime ) { return ( get_option( 'cartflows_pro_abilities_api_write', true ) && $runtime->permission_callback( 'cartflows_manage_flows_steps' ) ); }, 'input_schema' => array( 'type' => 'object', 'required' => array( 'step_id' ), 'properties' => array( 'step_id' => array( 'type' => 'integer', 'description' => __( 'The checkout step ID to add the order bump to.', 'cartflows-pro' ), ), 'title' => array( 'type' => 'string', 'default' => 'Order Bump', 'description' => __( 'Title for the order bump.', 'cartflows-pro' ), ), 'product_id' => array( 'type' => 'integer', 'default' => 0, 'description' => __( 'WooCommerce product ID to assign to the order bump. Omit or set to 0 for none.', 'cartflows-pro' ), ), ), ), 'output_schema' => array( 'type' => 'object', 'properties' => array( 'ob_id' => array( 'type' => 'string', 'description' => __( 'The generated order bump ID.', 'cartflows-pro' ), ), 'step_id' => array( 'type' => 'integer', 'description' => __( 'The checkout step ID.', 'cartflows-pro' ), ), 'title' => array( 'type' => 'string', 'description' => __( 'Order bump title.', 'cartflows-pro' ), ), 'product_id' => array( 'type' => 'integer', 'description' => __( 'Assigned product ID (0 if none).', 'cartflows-pro' ), ), 'status' => array( 'type' => 'boolean', 'description' => __( 'Whether the order bump is enabled.', 'cartflows-pro' ), ), 'position' => array( 'type' => 'string', 'description' => __( 'Display position on the checkout page.', 'cartflows-pro' ), ), 'style' => array( 'type' => 'string', 'description' => __( 'Order bump visual style.', 'cartflows-pro' ), ), ), ), 'execute_callback' => function ( $input ) use ( $runtime ) { return $runtime->create_order_bump( $input ); }, 'meta' => array( 'annotations' => array( 'priority' => 2.0, 'readOnlyHint' => false, 'destructiveHint' => false, 'idempotentHint' => false, 'openWorldHint' => false, ), 'show_in_rest' => true, 'mcp' => array( 'public' => true, 'type' => 'tool', ), ), ), // Create a new A/B test for a step in a funnel. CARTFLOWS_PRO_ABILITY_API_NAMESPACE . 'create-ab-test' => array( 'label' => __( 'Create A/B test', 'cartflows-pro' ), 'description' => __( 'Sets up a new A/B split test for a step in a funnel. The step becomes the control, a clone is created as the variation, and traffic is split 50/50. Requires the cartflows_pro_abilities_api_write option to be enabled.', 'cartflows-pro' ), 'category' => 'cartflows-pro', 'permission_callback' => function () use ( $runtime ) { return ( get_option( 'cartflows_pro_abilities_api_write', true ) && $runtime->permission_callback( 'cartflows_manage_flows_steps' ) ); }, 'input_schema' => array( 'type' => 'object', 'required' => array( 'flow_id', 'step_id' ), 'properties' => array( 'flow_id' => array( 'type' => 'integer', 'description' => __( 'The funnel (flow) ID.', 'cartflows-pro' ), ), 'step_id' => array( 'type' => 'integer', 'description' => __( 'The step ID to split test. This step becomes the control.', 'cartflows-pro' ), ), ), ), 'output_schema' => array( 'type' => 'object', 'properties' => array( 'control_id' => array( 'type' => 'integer', 'description' => __( 'The control step ID (original step).', 'cartflows-pro' ), ), 'variation_id' => array( 'type' => 'integer', 'description' => __( 'The newly created variation step ID.', 'cartflows-pro' ), ), 'variation_title' => array( 'type' => 'string', 'description' => __( 'Title of the variation step.', 'cartflows-pro' ), ), 'traffic_split' => array( 'type' => 'array', 'items' => array( 'type' => 'integer', ), 'description' => __( 'Traffic distribution percentages [control, variation].', 'cartflows-pro' ), ), 'started' => array( 'type' => 'boolean', 'description' => __( 'Whether the A/B test is running.', 'cartflows-pro' ), ), ), ), 'execute_callback' => function ( $input ) use ( $runtime ) { return $runtime->create_ab_test( $input ); }, 'meta' => array( 'annotations' => array( 'priority' => 2.0, 'readOnlyHint' => false, 'destructiveHint' => false, 'idempotentHint' => false, 'openWorldHint' => false, ), 'show_in_rest' => true, 'mcp' => array( 'public' => true, 'type' => 'tool', ), ), ), ); // Allow third-party extensions to add/modify abilities. $abilities = apply_filters( 'cartflows_pro_config_abilities', $abilities ); if ( ! is_array( $abilities ) ) { $abilities = array(); } self::$abilities = $abilities; return $abilities; } /** * Get a single ability config by name. * * @since 2.2.2 * @param string $ability_name Ability identifier (e.g., 'cartflows-pro/get-funnel-analytics'). * @return array|false Ability config array, or false if not found. */ public static function get_ability( $ability_name ) { if ( false === self::$abilities ) { self::$abilities = self::get_abilities(); } return isset( self::$abilities[ $ability_name ] ) ? self::$abilities[ $ability_name ] : false; } /** * Get ability input schema. * * @since 2.2.2 * @param string $ability_name Ability identifier. * @return array|false Input schema array, or false if not found. */ public static function get_ability_input_schema( $ability_name ) { $ability = self::get_ability( $ability_name ); if ( false === $ability ) { return false; } return isset( $ability['input_schema'] ) ? $ability['input_schema'] : false; } /** * Get ability output schema. * * @since 2.2.2 * @param string $ability_name Ability identifier. * @return array|false Output schema array, or false if not found. */ public static function get_ability_output_schema( $ability_name ) { $ability = self::get_ability( $ability_name ); if ( false === $ability ) { return false; } return isset( $ability['output_schema'] ) ? $ability['output_schema'] : false; } }