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
- Access Control and Redirects
- Content Modification
- User Tracking and Analytics
- API Rate Limiting
- Feature Flags
- WooCommerce Integration
- Membership System
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!
- Getting Started - Begin your MilliRules journey
- Core Concepts - Understand the fundamentals
- API Reference - Complete method documentation
Have questions or suggestions? Visit the MilliRules GitHub repository for support and contributions.