Real-World Examples

This guide provides complete, working examples of MilliRules implementations for common use cases. Each example includes full code with explanations.

Table of Contents#Copied!


Page Caching System#Copied!

A complete page caching implementation using early execution.

 1/**
 2 * Plugin Name: MilliRules Page Cache
 3 * Description: Intelligent page caching with MilliRules
 4 */
 5
 6require_once __DIR__ . '/vendor/autoload.php';
 7
 8use MilliRulesMilliRules;
 9use MilliRulesRules;
10use MilliRulesContext;
11
12// Initialize early (in mu-plugins or early hook)
13add_action('plugins_loaded', function() {
14    MilliRules::init();
15
16    // Register cache check action
17    Rules::register_action('check_page_cache', function($args, Context $context) {
18        $context->load('request');
19        $uri = $context->get('request.uri', '') ?? '';
20        $cache_key = 'page_cache_' . md5($uri);
21
22        $cached = get_transient($cache_key);
23
24        if ($cached !== false) {
25            header('Content-Type: text/html; charset=UTF-8');
26            header('X-Cache: HIT');
27            header('X-Cache-Key: ' . $cache_key);
28            echo $cached;
29            exit;
30        }
31    });
32
33    // Register cache save action
34    Rules::register_action('save_page_cache', function($args, Context $context) {
35        $uri = $context->get('request.uri', '') ?? '';
36        $cache_key = 'page_cache_' . md5($uri);
37        $duration = $args['duration'] ?? 3600;
38
39        ob_start(function($buffer) use ($cache_key, $duration) {
40            // Save to cache
41            set_transient($cache_key, $buffer, $duration);
42
43            // Add cache header
44            header('X-Cache: MISS');
45            header('X-Cache-Key: ' . $cache_key);
46
47            return $buffer;
48        });
49    });
50
51    // Rule 1: Check cache for cacheable requests
52    Rules::create('check_cache', 'php')
53        ->order(5)
54        ->when()
55            ->request_method(['GET', 'HEAD'], 'IN')
56            ->request_url('/wp-admin/*', 'NOT LIKE')
57            ->request_url('/wp-login.php', '!=')
58            ->cookie('wordpress_logged_in_*', null, 'NOT EXISTS')
59        ->then()
60            ->custom('check_page_cache')
61        ->register();
62
63    // Rule 2: Save to cache after response
64    Rules::create('save_cache', 'php')
65        ->order(10)
66        ->when()
67            ->request_method(['GET', 'HEAD'], 'IN')
68            ->request_url('/wp-admin/*', 'NOT LIKE')
69            ->request_url('/wp-login.php', '!=')
70        ->then()
71            ->custom('save_page_cache', ['duration' => 3600])
72        ->register();
73
74    // Execute early rules
75    MilliRules::execute_rules(['PHP']);
76}, 1);
77
78// Clear cache on post update
79add_action('save_post', function($post_id) {
80    // Clear all page cache
81    global $wpdb;
82    $wpdb->query("DELETE FROM {$wpdb->options} WHERE option_name LIKE '_transient_page_cache_%'");
83});

Access Control and Redirects#Copied!

Protect pages and redirect unauthorized users.

 1/**
 2 * Plugin Name: MilliRules Access Control
 3 * Description: Rule-based access control
 4 */
 5
 6require_once __DIR__ . '/vendor/autoload.php';
 7
 8use MilliRulesMilliRules;
 9use MilliRulesRules;
10
11add_action('init', function() {
12    MilliRules::init();
13
14    // Register custom conditions
15    Rules::register_condition('user_has_role', function($args, Context $context) {
16        $required_role = $args['role'] ?? '';
17        $user_roles = $context['wp']['user']['roles'] ?? [];
18        return in_array($required_role, $user_roles);
19    });
20
21    Rules::register_condition('user_can', function($args, Context $context) {
22        $capability = $args['capability'] ?? '';
23        $user_id = $context->get('user.id', 0) ?? 0;
24        return $user_id && user_can($user_id, $capability);
25    });
26
27    // Register redirect action
28    Rules::register_action('redirect_to', function($args, Context $context) {
29        $url = $args['url'] ?? home_url();
30        $status = $args['status'] ?? 302;
31        $message = $args['message'] ?? '';
32
33        if ($message) {
34            set_transient('redirect_message_' . get_current_user_id(), $message, 30);
35        }
36
37        wp_redirect($url, $status);
38        exit;
39    });
40
41    // Register message display action
42    Rules::register_action('show_redirect_message', function($args, Context $context) {
43        $user_id = get_current_user_id();
44        $message = get_transient('redirect_message_' . $user_id);
45
46        if ($message) {
47            delete_transient('redirect_message_' . $user_id);
48            add_action('admin_notices', function() use ($message) {
49                echo '<div class="notice notice-warning"><p>' . esc_html($message) . '</p></div>';
50            });
51        }
52    });
53
54    // Rule 1: Protect admin area
55    Rules::create('protect_admin', 'wp')
56        ->on('admin_init', 5)
57        ->when()
58            ->is_user_logged_in()
59            ->custom('user_can', ['capability' => 'edit_posts'])
60            ->match_none()
61        ->then()
62            ->custom('redirect_to', [
63                'url' => home_url(),
64                'message' => 'You do not have permission to access the admin area.'
65            ])
66        ->register();
67
68    // Rule 2: Protect specific pages
69    Rules::create('protect_membership_pages', 'wp')
70        ->on('template_redirect', 10)
71        ->when()
72            ->request_url('/members/*', 'LIKE')
73            ->is_user_logged_in(false)
74        ->then()
75            ->custom('redirect_to', [
76                'url' => wp_login_url($_SERVER['REQUEST_URI'] ?? ''),
77                'message' => 'Please log in to access member content.',
78                'status' => 302
79            ])
80        ->register();
81
82    // Rule 3: Role-based page protection
83    Rules::create('protect_premium_content', 'wp')
84        ->on('template_redirect', 10)
85        ->when()
86            ->request_url('/premium/*', 'LIKE')
87            ->is_user_logged_in()
88            ->custom('user_has_role', ['role' => 'subscriber'])
89            ->match_none()
90        ->then()
91            ->custom('redirect_to', [
92                'url' => home_url('/upgrade'),
93                'message' => 'Upgrade to premium to access this content.'
94            ])
95        ->register();
96
97    // Rule 4: Display redirect messages
98    Rules::create('display_messages', 'wp')
99        ->on('admin_notices', 10)
100        ->when()->is_user_logged_in()
101        ->then()->custom('show_redirect_message')
102        ->register();
103
104}, 1);

Content Modification#Copied!

Dynamically modify WordPress content based on conditions.

 1/**
 2 * Plugin Name: MilliRules Content Modifier
 3 * Description: Conditional content modification
 4 */
 5
 6require_once __DIR__ . '/vendor/autoload.php';
 7
 8use MilliRulesMilliRules;
 9use MilliRulesRules;
10
11add_action('init', function() {
12    MilliRules::init();
13
14    // Register content modification actions
15    Rules::register_action('prepend_content', function($args, Context $context) {
16        $text = $args['text'] ?? '';
17        $priority = $args['priority'] ?? 10;
18
19        add_filter('the_content', function($content) use ($text) {
20            return $text . $content;
21        }, $priority);
22    });
23
24    Rules::register_action('append_content', function($args, Context $context) {
25        $text = $args['text'] ?? '';
26        $priority = $args['priority'] ?? 10;
27
28        add_filter('the_content', function($content) use ($text) {
29            return $content . $text;
30        }, $priority);
31    });
32
33    Rules::register_action('add_reading_time', function($args, Context $context) {
34        add_filter('the_content', function($content) {
35            $word_count = str_word_count(strip_tags($content));
36            $reading_time = ceil($word_count / 200); // 200 words per minute
37
38            $badge = '<div class="reading-time" style="background: #f0f0f0; padding: 10px; margin-bottom: 20px; border-radius: 5px;">';
39            $badge .= '<strong>⏱ Reading time:</strong> ' . $reading_time . ' min';
40            $badge .= '</div>';
41
42            return $badge . $content;
43        }, 10);
44    });
45
46    // Rule 1: Add disclaimer to product posts
47    Rules::create('product_disclaimer', 'wp')
48        ->on('the_content', 10)
49        ->when()
50            ->is_singular('post')
51            ->post_type('product')
52        ->then()
53            ->custom('prepend_content', [
54                'text' => '<div class="disclaimer" style="background: #fff3cd; padding: 15px; margin-bottom: 20px; border-left: 4px solid #ffc107;">' .
55                         '<strong>⚠ Disclaimer:</strong> Product specifications and prices are subject to change without notice.' .
56                         '</div>',
57                'priority' => 10
58            ])
59        ->register();
60
61    // Rule 2: Add reading time to blog posts
62    Rules::create('add_blog_reading_time', 'wp')
63        ->on('the_content', 10)
64        ->when()
65            ->is_singular('post')
66            ->post_type('post')
67        ->then()
68            ->custom('add_reading_time')
69        ->register();
70
71    // Rule 3: Add CTA to pages for non-members
72    Rules::create('membership_cta', 'wp')
73        ->on('the_content', 10)
74        ->when()
75            ->is_singular('page')
76            ->is_user_logged_in(false)
77        ->then()
78            ->custom('append_content', [
79                'text' => '<div class="membership-cta" style="background: #007cba; color: white; padding: 30px; margin-top: 30px; text-align: center; border-radius: 5px;">' .
80                         '<h3 style="color: white; margin-top: 0;">Enjoying this content?</h3>' .
81                         '<p>Join our community to access exclusive content and features!</p>' .
82                         '<a href="/register" style="background: white; color: #007cba; padding: 12px 30px; text-decoration: none; border-radius: 3px; display: inline-block; font-weight: bold;">Join Now</a>' .
83                         '</div>',
84                'priority' => 20
85            ])
86        ->register();
87
88    // Rule 4: Add author bio to posts
89    Rules::create('author_bio', 'wp')
90        ->on('the_content', 10)
91        ->when()
92            ->is_singular('post')
93            ->post_type('post')
94        ->then()
95            ->custom('append_content', [
96                'text' => '<?php
97                    $author_id = get_the_author_meta("ID");
98                    $author_name = get_the_author();
99                    $author_bio = get_the_author_meta("description");
100                    $author_url = get_author_posts_url($author_id);
101
102                    echo "<div class="author-bio" style="background: #f9f9f9; padding: 20px; margin-top: 30px; border-radius: 5px;">";
103                    echo "<h4>About " . esc_html($author_name) . "</h4>";
104                    echo "<p>" . esc_html($author_bio) . "</p>";
105                    echo "<a href="" . esc_url($author_url) . "">View all posts by " . esc_html($author_name) . "</a>";
106                    echo "</div>";
107                ?>',
108                'priority' => 30
109            ])
110        ->register();
111
112}, 1);

User Tracking and Analytics#Copied!

Track user behavior and log analytics events.

 1/**
 2 * Plugin Name: MilliRules Analytics
 3 * Description: User tracking and analytics
 4 */
 5
 6require_once __DIR__ . '/vendor/autoload.php';
 7
 8use MilliRulesMilliRules;
 9use MilliRulesRules;
10
11add_action('init', function() {
12    MilliRules::init();
13
14    // Register tracking actions
15    Rules::register_action('track_page_view', function($args, Context $context) {
16        global $wpdb;
17
18        $table = $wpdb->prefix . 'page_views';
19        $user_id = $context->get('user.id', 0) ?? 0;
20        $url = $context->get('request.uri', '') ?? '';
21        $ip = $context['request']['ip'] ?? '';
22        $user_agent = $context['request']['user_agent'] ?? '';
23
24        $wpdb->insert($table, [
25            'user_id' => $user_id,
26            'url' => $url,
27            'ip' => $ip,
28            'user_agent' => $user_agent,
29            'viewed_at' => current_time('mysql'),
30        ]);
31    });
32
33    Rules::register_action('track_event', function($args, Context $context) {
34        global $wpdb;
35
36        $table = $wpdb->prefix . 'analytics_events';
37        $event_type = $args['event_type'] ?? 'pageview';
38        $event_data = $args['event_data'] ?? [];
39        $user_id = $context->get('user.id', 0) ?? 0;
40
41        $wpdb->insert($table, [
42            'user_id' => $user_id,
43            'event_type' => $event_type,
44            'event_data' => json_encode($event_data),
45            'created_at' => current_time('mysql'),
46        ]);
47    });
48
49    Rules::register_action('update_user_activity', function($args, Context $context) {
50        $user_id = $context->get('user.id', 0) ?? 0;
51
52        if ($user_id) {
53            update_user_meta($user_id, 'last_activity', time());
54            update_user_meta($user_id, 'total_visits',
55                (int) get_user_meta($user_id, 'total_visits', true) + 1
56            );
57        }
58    });
59
60    // Rule 1: Track all page views
61    Rules::create('track_all_pages', 'wp')
62        ->on('wp', 10)
63        ->when()->request_url('*')
64        ->then()->custom('track_page_view')
65        ->register();
66
67    // Rule 2: Track user activity
68    Rules::create('track_user_activity', 'wp')
69        ->on('wp', 10)
70        ->when()->is_user_logged_in()
71        ->then()->custom('update_user_activity')
72        ->register();
73
74    // Rule 3: Track important pages
75    Rules::create('track_important_pages', 'wp')
76        ->on('wp', 10)
77        ->when()
78            ->request_url(['/pricing', '/contact', '/checkout'], 'IN')
79        ->then()
80            ->custom('track_event', [
81                'event_type' => 'important_page_view',
82                'event_data' => [
83                    'page' => '{request.uri}',
84                    'referrer' => '{request.referer}'
85                ]
86            ])
87        ->register();
88
89    // Rule 4: Track downloads
90    Rules::create('track_downloads', 'wp')
91        ->on('wp', 10)
92        ->when()
93            ->request_url('/downloads/*', 'LIKE')
94            ->request_param('file')
95        ->then()
96            ->custom('track_event', [
97                'event_type' => 'file_download',
98                'event_data' => [
99                    'file' => '{param.file}',
100                    'user_id' => '{user.id}'
101                ]
102            ])
103        ->register();
104
105}, 1);
106
107// Create tables on plugin activation
108register_activation_hook(__FILE__, function() {
109    global $wpdb;
110
111    $charset_collate = $wpdb->get_charset_collate();
112
113    $sql1 = "CREATE TABLE IF NOT EXISTS {$wpdb->prefix}page_views (
114        id bigint(20) NOT NULL AUTO_INCREMENT,
115        user_id bigint(20) NOT NULL DEFAULT 0,
116        url varchar(255) NOT NULL,
117        ip varchar(45) NOT NULL,
118        user_agent text,
119        viewed_at datetime NOT NULL,
120        PRIMARY KEY  (id),
121        KEY user_id (user_id),
122        KEY viewed_at (viewed_at)
123    ) $charset_collate;";
124
125    $sql2 = "CREATE TABLE IF NOT EXISTS {$wpdb->prefix}analytics_events (
126        id bigint(20) NOT NULL AUTO_INCREMENT,
127        user_id bigint(20) NOT NULL DEFAULT 0,
128        event_type varchar(100) NOT NULL,
129        event_data text,
130        created_at datetime NOT NULL,
131        PRIMARY KEY  (id),
132        KEY user_id (user_id),
133        KEY event_type (event_type),
134        KEY created_at (created_at)
135    ) $charset_collate;";
136
137    require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
138    dbDelta($sql1);
139    dbDelta($sql2);
140});

API Rate Limiting#Copied!

Implement rate limiting for API endpoints.

 1/**
 2 * Plugin Name: MilliRules API Rate Limiter
 3 * Description: Rate limiting for API endpoints
 4 */
 5
 6require_once __DIR__ . '/vendor/autoload.php';
 7
 8use MilliRulesMilliRules;
 9use MilliRulesRules;
10
11add_action('init', function() {
12    MilliRules::init();
13
14    // Register rate limit condition
15    Rules::register_condition('within_rate_limit', function($args, Context $context) {
16        $ip = $context['request']['ip'] ?? '';
17        $limit = $args['limit'] ?? 60; // Requests per minute
18        $period = $args['period'] ?? 60; // Seconds
19
20        $cache_key = 'rate_limit_' . md5($ip);
21        $current = get_transient($cache_key) ?: 0;
22
23        if ($current >= $limit) {
24            return false; // Rate limit exceeded
25        }
26
27        // Increment counter
28        set_transient($cache_key, $current + 1, $period);
29
30        return true;
31    });
32
33    // Register rate limit response action
34    Rules::register_action('send_rate_limit_response', function($args, Context $context) {
35        $retry_after = $args['retry_after'] ?? 60;
36
37        status_header(429);
38        header('Content-Type: application/json');
39        header('Retry-After: ' . $retry_after);
40
41        echo json_encode([
42            'error' => 'Rate limit exceeded',
43            'message' => 'Too many requests. Please try again later.',
44            'retry_after' => $retry_after
45        ]);
46
47        exit;
48    });
49
50    // Rule 1: Rate limit API endpoints
51    Rules::create('api_rate_limit', 'php')
52        ->order(5)
53        ->when()
54            ->request_url('/wp-json/*', 'LIKE')
55            ->custom('within_rate_limit', ['limit' => 60, 'period' => 60])
56            ->match_none() // If NOT within limit
57        ->then()
58            ->custom('send_rate_limit_response', ['retry_after' => 60])
59        ->register();
60
61    // Rule 2: Stricter limits for authentication endpoints
62    Rules::create('auth_rate_limit', 'php')
63        ->order(3)
64        ->when()
65            ->request_url('/wp-json/*/auth/*', 'LIKE')
66            ->custom('within_rate_limit', ['limit' => 10, 'period' => 60])
67            ->match_none()
68        ->then()
69            ->custom('send_rate_limit_response', ['retry_after' => 300])
70        ->register();
71
72    // Execute early
73    MilliRules::execute_rules(['PHP']);
74
75}, 1);

Feature Flags#Copied!

Implement dynamic feature flags.

 1/**
 2 * Plugin Name: MilliRules Feature Flags
 3 * Description: Dynamic feature flag system
 4 */
 5
 6require_once __DIR__ . '/vendor/autoload.php';
 7
 8use MilliRulesMilliRules;
 9use MilliRulesRules;
10
11add_action('init', function() {
12    MilliRules::init();
13
14    // Register feature flag condition
15    Rules::register_condition('feature_enabled', function($args, Context $context) {
16        $feature = $args['feature'] ?? '';
17        return get_option("feature_flag_{$feature}", false);
18    });
19
20    // Register feature actions
21    Rules::register_action('enable_feature', function($args, Context $context) {
22        $feature = $args['feature'] ?? '';
23
24        if ($feature) {
25            // Mark feature as enabled
26            update_option("feature_enabled_{$feature}", true);
27
28            // Load feature code
29            $feature_file = plugin_dir_path(__FILE__) . "features/{$feature}.php";
30            if (file_exists($feature_file)) {
31                require_once $feature_file;
32            }
33        }
34    });
35
36    // Rule 1: Enable beta features for admins in dev
37    Rules::create('enable_beta_for_admins', 'wp')
38        ->when()
39            ->is_user_logged_in()
40            ->custom('user_has_role', ['role' => 'administrator'])
41            ->constant('WP_ENVIRONMENT_TYPE', ['local', 'development'], 'IN')
42        ->then()
43            ->custom('enable_feature', ['feature' => 'beta_dashboard'])
44            ->custom('enable_feature', ['feature' => 'advanced_editor'])
45        ->register();
46
47    // Rule 2: Enable features based on flags
48    Rules::create('load_new_checkout', 'wp')
49        ->when()->custom('feature_enabled', ['feature' => 'new_checkout'])
50        ->then()->custom('enable_feature', ['feature' => 'new_checkout'])
51        ->register();
52
53    // Rule 3: Gradual rollout (10% of users)
54    Rules::register_condition('in_rollout_group', function($args, Context $context) {
55        $percentage = $args['percentage'] ?? 10;
56        $user_id = $context->get('user.id', 0) ?? 0;
57
58        // Consistent assignment based on user ID
59        return ($user_id % 100) < $percentage;
60    });
61
62    Rules::create('gradual_rollout', 'wp')
63        ->when()
64            ->is_user_logged_in()
65            ->custom('in_rollout_group', ['percentage' => 10])
66        ->then()
67            ->custom('enable_feature', ['feature' => 'experimental_ui'])
68        ->register();
69
70}, 1);
71
72// Helper function to check if feature is enabled
73function is_feature_enabled($feature) {
74    return get_option("feature_enabled_{$feature}", false);
75}

WooCommerce Integration#Copied!

Complete WooCommerce conditional logic example.

 1/**
 2 * Plugin Name: MilliRules WooCommerce Integration
 3 * Description: Advanced WooCommerce rules
 4 */
 5
 6require_once __DIR__ . '/vendor/autoload.php';
 7
 8use MilliRulesMilliRules;
 9use MilliRulesRules;
10
11add_action('init', function() {
12    if (!class_exists('WooCommerce')) {
13        return;
14    }
15
16    MilliRules::init();
17
18    // Register WooCommerce conditions
19    Rules::register_condition('cart_total', function($args, Context $context) {
20        $minimum = $args['minimum'] ?? 0;
21        $operator = $args['operator'] ?? '>=';
22        $cart_total = WC()->cart->get_total('edit');
23
24        return BaseCondition::compare_values($cart_total, $minimum, $operator);
25    });
26
27    Rules::register_condition('cart_item_count', function($args, Context $context) {
28        $count = $args['count'] ?? 1;
29        $operator = $args['operator'] ?? '>=';
30        $cart_count = WC()->cart->get_cart_contents_count();
31
32        return BaseCondition::compare_values($cart_count, $count, $operator);
33    });
34
35    Rules::register_condition('has_product_category_in_cart', function($args, Context $context) {
36        $category_slug = $args['category'] ?? '';
37
38        foreach (WC()->cart->get_cart() as $cart_item) {
39            $product_id = $cart_item['product_id'];
40            if (has_term($category_slug, 'product_cat', $product_id)) {
41                return true;
42            }
43        }
44
45        return false;
46    });
47
48    // Register WooCommerce actions
49    Rules::register_action('apply_discount', function($args, Context $context) {
50        $coupon = $args['coupon'] ?? '';
51
52        if ($coupon && !WC()->cart->has_discount($coupon)) {
53            WC()->cart->apply_coupon($coupon);
54            wc_add_notice('Discount applied automatically!', 'success');
55        }
56    });
57
58    Rules::register_action('add_cart_notice', function($args, Context $context) {
59        $message = $args['message'] ?? '';
60        $type = $args['type'] ?? 'notice';
61
62        if ($message) {
63            wc_add_notice($message, $type);
64        }
65    });
66
67    // Rule 1: Free shipping for orders over $50
68    Rules::create('free_shipping_notice', 'wp')
69        ->on('woocommerce_before_cart', 10)
70        ->when()
71            ->custom('cart_total', ['minimum' => 50])
72        ->then()
73            ->custom('add_cart_notice', [
74                'message' => '🎉 You qualify for free shipping!',
75                'type' => 'success'
76            ])
77        ->register();
78
79    // Rule 2: Auto-apply discount for bulk orders
80    Rules::create('bulk_order_discount', 'wp')
81        ->on('woocommerce_before_calculate_totals', 10)
82        ->when()
83            ->custom('cart_item_count', ['count' => 10, 'operator' => '>='])
84        ->then()
85            ->custom('apply_discount', ['coupon' => 'BULK10'])
86        ->register();
87
88    // Rule 3: Category-specific promotion
89    Rules::create('electronics_promo', 'wp')
90        ->on('woocommerce_before_cart', 10)
91        ->when()
92            ->custom('has_product_category_in_cart', ['category' => 'electronics'])
93            ->custom('cart_total', ['minimum' => 100, 'operator' => '>='])
94        ->then()
95            ->custom('apply_discount', ['coupon' => 'ELECTRONICS15'])
96            ->custom('add_cart_notice', [
97                'message' => '15% discount applied to your electronics purchase!',
98                'type' => 'success'
99            ])
100        ->register();
101
102    // Rule 4: Minimum order notice
103    Rules::create('minimum_order_notice', 'wp')
104        ->on('woocommerce_before_cart', 10)
105        ->when()
106            ->custom('cart_total', ['minimum' => 25, 'operator' => '<'])
107        ->then()
108            ->custom('add_cart_notice', [
109                'message' => 'Add $' . (25 - WC()->cart->get_total('edit')) . ' more to meet our minimum order amount.',
110                'type' => 'notice'
111            ])
112        ->register();
113
114}, 1);

Membership System#Copied!

Complete membership system with tiers and access control.

 1/**
 2 * Plugin Name: MilliRules Membership System
 3 * Description: Complete membership tier system
 4 */
 5
 6require_once __DIR__ . '/vendor/autoload.php';
 7
 8use MilliRulesMilliRules;
 9use MilliRulesRules;
10
11add_action('init', function() {
12    MilliRules::init();
13
14    // Register membership conditions
15    Rules::register_condition('has_membership_level', function($args, Context $context) {
16        $required_level = $args['level'] ?? 'free';
17        $user_id = $context->get('user.id', 0) ?? 0;
18
19        if (!$user_id) {
20            return $required_level === 'free';
21        }
22
23        $user_level = get_user_meta($user_id, 'membership_level', true) ?: 'free';
24
25        $levels = ['free' => 0, 'basic' => 1, 'premium' => 2, 'enterprise' => 3];
26
27        return ($levels[$user_level] ?? 0) >= ($levels[$required_level] ?? 0);
28    });
29
30    Rules::register_condition('membership_expired', function($args, Context $context) {
31        $user_id = $context->get('user.id', 0) ?? 0;
32
33        if (!$user_id) {
34            return false;
35        }
36
37        $expiry = get_user_meta($user_id, 'membership_expiry', true);
38
39        if (!$expiry) {
40            return false; // No expiry = lifetime
41        }
42
43        return time() > $expiry;
44    });
45
46    // Register membership actions
47    Rules::register_action('restrict_content', function($args, Context $context) {
48        $message = $args['message'] ?? 'This content requires a membership.';
49        $cta_url = $args['cta_url'] ?? home_url('/membership');
50
51        add_filter('the_content', function($content) use ($message, $cta_url) {
52            $restricted = '<div class="membership-required" style="background: #f9f9f9; padding: 30px; text-align: center; border: 2px solid #ddd; border-radius: 5px;">';
53            $restricted .= '<h3>🔒 Members Only Content</h3>';
54            $restricted .= '<p>' . esc_html($message) . '</p>';
55            $restricted .= '<a href="' . esc_url($cta_url) . '" class="button" style="background: #007cba; color: white; padding: 12px 30px; text-decoration: none; border-radius: 3px; display: inline-block;">Upgrade Membership</a>';
56            $restricted .= '</div>';
57
58            return $restricted;
59        });
60    });
61
62    Rules::register_action('show_membership_badge', function($args, Context $context) {
63        $user_id = $context->get('user.id', 0) ?? 0;
64        $level = get_user_meta($user_id, 'membership_level', true) ?: 'free';
65
66        $badges = [
67            'free' => '',
68            'basic' => '🔵',
69            'premium' => '',
70            'enterprise' => '👑'
71        ];
72
73        add_filter('the_author', function($author) use ($level, $badges) {
74            return $author . ' ' . ($badges[$level] ?? '');
75        });
76    });
77
78    // Rule 1: Restrict premium content
79    Rules::create('restrict_premium_posts', 'wp')
80        ->on('the_content', 10)
81        ->when()
82            ->post_type('post')
83            ->custom('post_meta', ['key' => 'membership_required', 'value' => 'premium'])
84            ->custom('has_membership_level', ['level' => 'premium'])
85            ->match_none()
86        ->then()
87            ->custom('restrict_content', [
88                'message' => 'This premium content is available to Premium and Enterprise members.',
89                'cta_url' => home_url('/upgrade-to-premium')
90            ])
91        ->register();
92
93    // Rule 2: Expired membership redirect
94    Rules::create('expired_membership_redirect', 'wp')
95        ->on('template_redirect', 5)
96        ->when()
97            ->is_user_logged_in()
98            ->custom('membership_expired')
99            ->request_url('/members/*', 'LIKE')
100        ->then()
101            ->custom('redirect_to', [
102                'url' => home_url('/renew-membership'),
103                'message' => 'Your membership has expired. Please renew to access member content.'
104            ])
105        ->register();
106
107    // Rule 3: Show membership badge on comments
108    Rules::create('show_member_badge', 'wp')
109        ->on('comment_text', 10)
110        ->when()->is_user_logged_in()
111        ->then()->custom('show_membership_badge')
112        ->register();
113
114    // Rule 4: Member-only downloads
115    Rules::create('protect_downloads', 'wp')
116        ->on('template_redirect', 10)
117        ->when()
118            ->request_url('/downloads/*', 'LIKE')
119            ->custom('has_membership_level', ['level' => 'basic'])
120            ->match_none()
121        ->then()
122            ->custom('redirect_to', [
123                'url' => home_url('/membership'),
124                'message' => 'Membership required to access downloads.'
125            ])
126        ->register();
127
128}, 1);

Summary#Copied!

These examples demonstrate:

Complete implementations - Ready-to-use code ✅ Real-world scenarios - Common use cases ✅ Best practices - Proper error handling and validation ✅ WordPress integration - Hook usage and compatibility ✅ Advanced patterns - Complex condition logic and actions

Next Steps#Copied!


Have questions or suggestions? Visit the MilliRules GitHub repository for support and contributions.