### Package Documentation Example Source: https://millipress.com/docs/millirules/03-customization/03-custom-packages Example of documenting a package using a PHPDoc block, detailing its components, conditions, actions, context, and placeholders. ```php 1/** 2 * Membership Package 3 * 4 * Provides membership-related conditions and actions. 5 * 6 * Conditions: 7 * - membership_level: Check user's membership level 8 * - membership_status: Check membership status 9 * - has_feature: Check if user has access to feature 10 * 11 * Actions: 12 * - upgrade_membership: Upgrade user to new level 13 * - grant_feature: Grant feature access 14 * - send_membership_email: Send membership-related email 15 * 16 * Context: 17 * - membership.user.level: User's membership level 18 * - membership.user.status: Membership status 19 * - membership.user.features: Available features 20 * 21 * Placeholders: 22 * - {membership:user:level}: User's membership level 23 * - {membership:user:status}: Membership status 24 */ 25class MembershipPackage extends BasePackage { 26 // ... 27} ``` -------------------------------- ### Placeholder Examples Source: https://millipress.com/docs/millirules/02-core-concepts/05-placeholders Provides examples of common placeholder usages, mapping them to their equivalent PHP array access for clarity. These examples cover various context categories. ```plaintext 1'{request.uri}' // $context['request']['uri'] 2'{request.method}' // $context['request']['method'] 3'{request:headers:host}' // $context['request']['headers']['host'] 4'{user.id}' // $context['user']['id'] 5'{post.title}' // $context['post']['title'] 6'{cookie.session_id}' // $context['cookie']['session_id'] ``` -------------------------------- ### Cache Control Headers Example Source: https://millipress.com/docs/acorn-millirules/04-reference/02-actions Demonstrates setting cache control and vary headers for document routes. ```php 1Rules::create('cache-docs') 2 ->when() 3 ->routeName('docs.show') 4 ->then() 5 ->setHeader('Cache-Control', 'public, max-age=3600') 6 ->setHeader('Vary', 'Accept-Encoding') 7 ->register(); ``` -------------------------------- ### Set Header Action Array Syntax Source: https://millipress.com/docs/acorn-millirules/04-reference/02-actions Provides examples of configuring headers using array syntax. ```php 1['type' => 'set_header', 'name' => 'X-Custom', 'value' => 'hello'] 2['type' => 'set_header', 'name' => 'X-Product', 'value' => '{route.parameters.product}'] ``` -------------------------------- ### Focused Action Example (Good Practice) Source: https://millipress.com/docs/millirules/03-customization/02-custom-actions Demonstrates a well-focused action with a single responsibility, adhering to best practices for maintainability. ```php 1// ✅ Good - single responsibility 2Rules::register_action('log_event', function($args, Context $context) { 3 error_log($args[0] ?? ''); 4}); ``` -------------------------------- ### Complete MilliCache Configuration Example Source: https://millipress.com/docs/millicache/02-configuration/02-reference A comprehensive example demonstrating how to configure MilliCache in your wp-config.php file, including storage, cache settings, and exclusions. ```php 1when() 3 ->routeName('docs.*', 'LIKE') 4 ->then() 5 ->setHeader('X-Content-Type-Options', 'nosniff') 6 ->register(); ``` -------------------------------- ### Complete WordPress Plugin Example Source: https://millipress.com/docs/millirules/01-getting-started/03-first-rule Combines initialization, custom action registration, and rule creation for a WordPress plugin that logs admin dashboard access. ```php /** * Plugin Name: My First MilliRules Plugin * Description: Logs admin dashboard access using MilliRules * Version: 1.0.0 */ require_once __DIR__ . '/vendor/autoload.php'; use MilliRulesMilliRules; use MilliRulesRules; use MilliRulesContext; // Initialize MilliRules MilliRules::init(); // Register custom log action Rules::register_action('log_message', function($args, Context $context) { $message = $args['message'] ?? $args[0] ?? 'No message'; error_log('MilliRules: ' . $message); }); // Create the rule Rules::create('log_admin_access', 'wp') ->title('Log Admin Dashboard Access') ->order(10) ->when() ->request_url('/wp-admin/*') ->is_user_logged_in() ->then() ->custom('log_message', ['value' => 'Admin dashboard accessed']) ->register(); ``` -------------------------------- ### Customized Rule Stub Example Source: https://millipress.com/docs/acorn-millirules/03-customization/02-configuration An example of a customized rule stub template, demonstrating placeholder usage for namespace, class name, and rule ID. ```php 1order(10) 13 ->when() 14 // Add conditions here 15 ->then() 16 // Add actions here 17 ->register(); 18 } 19} ``` -------------------------------- ### Multiple Headers Example Source: https://millipress.com/docs/acorn-millirules/04-reference/02-actions Shows how to set multiple HTTP headers within a single rule. ```php 1Rules::create('security-headers') 2 ->when() 3 ->routeName('docs.*', 'LIKE') 4 ->then() 5 ->setHeader('X-Content-Type-Options', 'nosniff') 6 ->setHeader('X-Frame-Options', 'DENY') 7 ->setHeader('X-XSS-Protection', '1; mode=block') 8 ->register(); ``` -------------------------------- ### Install MilliCache Drop-in Source: https://millipress.com/docs/millicache/09-troubleshooting/02-faq Run this WP-CLI command to install the MilliCache drop-in, which is essential for the plugin to intercept and cache requests. ```bash wp millicache drop ``` -------------------------------- ### Full Context Structure Example Source: https://millipress.com/docs/millirules/05-reference/02-actions Illustrates the comprehensive structure of the context object, showing available request parameters, WordPress data, and query flags. ```json 1[ 2 'request' => [ 3 'method' => 'GET', 4 'uri' => '/path', 5 'scheme' => 'https', 6 'host' => 'example.com', 7 'path' => '/path', 8 'query' => 'key=value', 9 'referer' => 'https://example.com', 10 'user_agent' => 'Mozilla/5.0...', 11 'headers' => [...], 12 'ip' => '192.168.1.1', 13 'cookies' => [...], 14 'params' => [...], 15 ], 16 'wp' => [ // WordPress only 17 'post' => [...], 18 'user' => [...], 19 'query' => [...], 20 'constants' => [...], 21] 22] ``` -------------------------------- ### Dynamic Redirect Example Source: https://millipress.com/docs/acorn-millirules/04-reference/02-actions Illustrates a dynamic redirect using route parameters as placeholders in the URL. ```php 1Rules::create('product-redirect') 2 ->when() 3 ->routeName('docs.old-product') 4 ->then() 5 ->redirect('/docs/{route.parameters.product}/latest', 301) 6 ->register(); ``` -------------------------------- ### Simple Redirect Example Source: https://millipress.com/docs/acorn-millirules/04-reference/02-actions Demonstrates a simple redirect with a permanent status code (301). ```php 1Rules::create('legacy-docs-redirect') 2 ->when() 3 ->routeName('docs.legacy') 4 ->then() 5 ->redirect('/docs', 301) 6 ->register(); ``` -------------------------------- ### Redirect Action Array Syntax Source: https://millipress.com/docs/acorn-millirules/04-reference/02-actions Provides examples of configuring redirects using array syntax. ```php 1['type' => 'redirect', 'url' => '/docs', 'status' => 301] 2['type' => 'redirect', 'url' => '/docs/{route.parameters.product}'] ``` -------------------------------- ### Verify Installation Commands Source: https://millipress.com/docs/acorn-millirules/01-getting-started/02-installation Run these commands to confirm that Acorn MilliRules and its components are correctly registered. ```bash wp acorn rules:packages ``` ```bash wp acorn rules:actions ``` ```bash wp acorn rules:conditions ``` -------------------------------- ### Verify MilliRules Installation and Loaded Packages Source: https://millipress.com/docs/millirules/01-getting-started/02-quick-start Check loaded packages after initialization to confirm MilliRules is set up correctly. Logs the packages to the error log. ```php use MilliRulesMilliRules; // Initialize MilliRules MilliRules::init(); // Check loaded packages $packages = MilliRules::get_loaded_packages(); error_log('Loaded packages: ' . print_r($packages, true)); ``` -------------------------------- ### Dynamic Header Value Example Source: https://millipress.com/docs/acorn-millirules/04-reference/02-actions Illustrates setting a header with a dynamic value using route parameters. ```php 1Rules::create('product-header') 2 ->when() 3 ->routeParameter('product') 4 ->then() 5 ->setHeader('X-Product', '{route.parameters.product}') 6 ->register(); ``` -------------------------------- ### Action with Configuration Validation Source: https://millipress.com/docs/millirules/03-customization/02-custom-actions Example of an action that includes validation for its arguments to ensure correct configuration before execution. ```php 1Rules::register_action('send_email', function($args, Context $context) { 2 if (!isset($args['to']) || !is_email($args['to'])) { 3 error_log('send_email: invalid recipient'); 4 return; 5 } 6 7 wp_mail($args['to'], $args['subject'] ?? '', $args['message'] ?? ''); 8}); ``` -------------------------------- ### Implement SecurityHeaders Rule Source: https://millipress.com/docs/acorn-millirules/01-getting-started/02-installation Fill in the `SecurityHeaders` rule with specific conditions and actions. This example adds security headers to routes matching `docs.*`. ```php when() ->routeName('docs.*', 'LIKE') ->then() ->setHeader('X-Content-Type-Options', 'nosniff') ->setHeader('X-Frame-Options', 'DENY') ->register(); } } ``` -------------------------------- ### Context Class Methods Source: https://millipress.com/docs/millirules/02-core-concepts/01-concepts Demonstrates common operations on the Context class, such as getting, setting, checking existence, loading, and exporting context data. The `get()` method automatically loads sections if they are not already present. ```php $value = $context->get('post.type', 'post'); // ↑ Internally calls $context->load('post') if not already loaded // Set a value using dot notation $context->set('custom.data', 'value'); // Check if a path exists if ($context->has('user.id')) { // User data is loaded } // Explicitly load a context section (optional - get() does this automatically) $context->load('request'); // Export context as array (for debugging) $array = $context->to_array(); ``` -------------------------------- ### Circular Dependency Example Source: https://millipress.com/docs/millirules/03-customization/03-custom-packages Illustrates a circular dependency between two packages, which is an incorrect structure. ```php 1// ❌ Wrong - circular dependency 2class PackageA extends BasePackage { 3 public function get_required_packages(): array { 4 return ['PackageB']; // A requires B 5 } 6} 7 8class PackageB extends BasePackage { 9 public function get_required_packages(): array { 10 return ['PackageA']; // B requires A - CIRCULAR! 11 } 12} ``` -------------------------------- ### Register Custom Package Source: https://millipress.com/docs/millirules/03-customization/03-custom-packages Example of registering a custom package with specific message content. Ensure all necessary configurations are in place before calling register(). ```php 'message' => 'Congratulations! Upgraded to premium membership.' ]) ->register(); ``` -------------------------------- ### Create Rule with LIKE Operator for Header Patterns Source: https://millipress.com/docs/millirules/02-core-concepts/04-operators Example of creating a rule to match 'Authorization' headers starting with 'Bearer ' followed by any characters. ```php 1Rules::create('bearer_tokens') ->when() ->request_header('Authorization', 'Bearer *', 'LIKE') ->then()->custom('validate_token') ->register(); ``` -------------------------------- ### Create Rule with LIKE Operator for Prefix Matching Source: https://millipress.com/docs/millirules/02-core-concepts/04-operators Example of creating a rule that matches URLs starting with '/wp-admin/'. The '*' wildcard matches any characters. ```php 1Rules::create('admin_urls') ->when() ->request_url('/wp-admin/*') // Matches /wp-admin/anything ->then()->custom('admin_action') ->register(); ``` -------------------------------- ### Create Rule with REGEXP Operator Source: https://millipress.com/docs/millirules/02-core-concepts/04-operators Example of creating a rule that uses a regular expression to match URLs starting with '/api/'. Note the escaped forward slash. ```php 1Rules::create('api_route') ->when() ->request_url('/^\/api\//') ->then()->custom('handle_api_request') ->register(); ``` -------------------------------- ### Create a Rule with Basic Conditions and Actions Source: https://millipress.com/docs/millirules/05-reference/03-api Demonstrates the basic structure of creating a rule, defining conditions using `when()`, specifying actions with `then()`, and registering the rule. ```php 1Rules::create('my_rule') 2 ->when() 3 ->request_url('/api/*') 4 ->request_method('GET') 5 ->then() 6 ->custom('action') 7 ->register(); ``` -------------------------------- ### Multisite Cache Operations Source: https://millipress.com/docs/millicache/06-wp-cli/01-commands Demonstrates how to perform cache operations on specific sites, multiple sites, or the entire network in a multisite WordPress installation. Also shows how to get stats for a specific site. ```bash # Run on specific site wp millicache clear --url=site1.example.com # Clear specific sites wp millicache clear --site=1,2,3 # Clear entire network wp millicache clear --network=1 # Stats for specific site wp millicache stats --flag="2:*" ``` -------------------------------- ### Install Acorn MilliCache Package Source: https://millipress.com/docs/acorn-millicache/01-getting-started/02-installation Use Composer to install the Acorn MilliCache package. This command also installs MilliCache as a dependency. Remember to activate and configure MilliCache within WordPress after installation. ```bash composer require millipress/acorn-millicache ``` -------------------------------- ### Verify Context Providers Source: https://millipress.com/docs/millirules/02-core-concepts/02-packages Initialize MilliRules to register all providers and then check for the availability of specific context data, such as user ID. This example also shows how to export the context to see all loaded sections. ```php use MilliRulesContext; $context = new Context(); MilliRules::init(); // Registers all providers // Check if a specific provider is available $context->load('user'); if (!$context->has('user.id')) { error_log('WordPress user context not available'); } // Export context to see all loaded sections $array = $context->to_array(); error_log('Available context keys: ' . implode(', ', array_keys($array))); ``` -------------------------------- ### Full Configuration Reference Source: https://millipress.com/docs/acorn-millirules/03-customization/02-configuration The default configuration file for MilliRules middleware registration. ```php 1 [ 17 18 // Set to false to disable automatic middleware registration. 19 'enabled' => true, 20 21 // Middleware groups to attach to (e.g. ['web', 'api']). 22 'groups' => ['web'], 23 ], 24 25]; ``` -------------------------------- ### Install MilliRules via Composer Source: https://millipress.com/docs/millirules/01-getting-started/02-quick-start Use Composer to install MilliRules and its dependencies into your project's vendor directory. ```bash composer require MilliPress/MilliRules ``` -------------------------------- ### Install MilliCache via Composer Source: https://millipress.com/docs/millicache/01-getting-started/20-installation Use this command to install MilliCache if you manage WordPress with Composer. Dependencies are automatically handled. ```bash composer require millipress/millicache ``` -------------------------------- ### Registering a Simple Context Provider Source: https://millipress.com/docs/millirules/03-customization/03-custom-packages Packages can register context providers to load data lazily. This example shows a simple provider that retrieves options and a timestamp. ```php use MilliRulesContext; public function register_providers(Context $context): void { // Register a simple provider that loads on-demand $context->register_provider('my_custom', function() { return [ 'my_custom' => [ 'value1' => get_option('my_option_1'), 'value2' => get_option('my_option_2'), 'timestamp' => time(), ], ]; }); } ``` -------------------------------- ### Acorn MilliRules Usage Example Source: https://millipress.com/docs/millirules/03-customization/03-custom-packages Example of creating a rule to redirect legacy documentation routes using Acorn MilliRules. ```php 1// app/Rules/RedirectLegacyDocs.php 2namespace AppRules; 3 4use MilliRulesRules; 5 6class RedirectLegacyDocs 7{ 8 public function register(): void 9 { 10 Rules::create('redirect_legacy_docs', 'Acorn') 11 ->when() 12 ->routeName('docs.*') 13 ->routeParameter('product', ['value' => 'old-product']) 14 ->then() 15 ->redirect('/docs/new-product/', ['status' => 301]) 16 ->register(); 17 } 18} ``` -------------------------------- ### Setup Analytics Plugin with Rules Source: https://millipress.com/docs/millirules/04-advanced/01-examples Initializes MilliRules and registers custom actions for tracking page views, events, and user activity. Includes rules for automatically triggering these actions based on specific conditions. ```php 1/** 2 * Plugin Name: MilliRules Analytics 3 * Description: User tracking and analytics 4 */ require_once __DIR__ . '/vendor/autoload.php'; use MilliRulesMilliRules; use MilliRulesRules; add_action('init', function() { MilliRules::init(); // Register tracking actions Rules::register_action('track_page_view', function($args, Context $context) { global $wpdb; $table = $wpdb->prefix . 'page_views'; $user_id = $context->get('user.id', 0) ?? 0; $url = $context->get('request.uri', '') ?? ''; $ip = $context['request']['ip'] ?? ''; $user_agent = $context['request']['user_agent'] ?? ''; $wpdb->insert($table, [ 'user_id' => $user_id, 'url' => $url, 'ip' => $ip, 'user_agent' => $user_agent, 'viewed_at' => current_time('mysql'), ]); }); Rules::register_action('track_event', function($args, Context $context) { global $wpdb; $table = $wpdb->prefix . 'analytics_events'; $event_type = $args['event_type'] ?? 'pageview'; $event_data = $args['event_data'] ?? []; $user_id = $context->get('user.id', 0) ?? 0; $wpdb->insert($table, [ 'user_id' => $user_id, 'event_type' => $event_type, 'event_data' => json_encode($event_data), 'created_at' => current_time('mysql'), ]); }); Rules::register_action('update_user_activity', function($args, Context $context) { $user_id = $context->get('user.id', 0) ?? 0; if ($user_id) { update_user_meta($user_id, 'last_activity', time()); update_user_meta($user_id, 'total_visits', (int) get_user_meta($user_id, 'total_visits', true) + 1 ); } }); // Rule 1: Track all page views Rules::create('track_all_pages', 'wp') ->on('wp', 10) ->when()->request_url('*') ->then()->custom('track_page_view') ->register(); // Rule 2: Track user activity Rules::create('track_user_activity', 'wp') ->on('wp', 10) ->when()->is_user_logged_in() ->then()->custom('update_user_activity') ->register(); // Rule 3: Track important pages Rules::create('track_important_pages', 'wp') ->on('wp', 10) ->when() ->request_url(['/pricing', '/contact', '/checkout'], 'IN') ->then() ->custom('track_event', [ 'event_type' => 'important_page_view', 'event_data' => [ 'page' => '{request.uri}', 'referrer' => '{request.referer}' ] ]) ->register(); // Rule 4: Track downloads Rules::create('track_downloads', 'wp') ->on('wp', 10) ->when() ->request_url('/downloads/*', 'LIKE') ->request_param('file') ->then() ->custom('track_event', [ 'event_type' => 'file_download', 'event_data' => [ 'file' => '{param.file}', 'user_id' => '{user.id}' ] ]) ->register(); }, 1); // Create tables on plugin activation register_activation_hook(__FILE__, function() { global $wpdb; $charset_collate = $wpdb->get_charset_collate(); $sql1 = "CREATE TABLE IF NOT EXISTS {$wpdb->prefix}page_views ( id bigint(20) NOT NULL AUTO_INCREMENT, user_id bigint(20) NOT NULL DEFAULT 0, url varchar(255) NOT NULL, ip varchar(45) NOT NULL, user_agent text, viewed_at datetime NOT NULL, PRIMARY KEY (id), KEY user_id (user_id), KEY viewed_at (viewed_at) ) $charset_collate;"; $sql2 = "CREATE TABLE IF NOT EXISTS {$wpdb->prefix}analytics_events ( id bigint(20) NOT NULL AUTO_INCREMENT, user_id bigint(20) NOT NULL DEFAULT 0, event_type varchar(100) NOT NULL, event_data text, created_at datetime NOT NULL, PRIMARY KEY (id), KEY user_id (user_id), KEY event_type (event_type), KEY created_at (created_at) ) $charset_collate;"; require_once(ABSPATH . 'wp-admin/includes/upgrade.php'); dbDelta($sql1); dbDelta($sql2); }); ``` -------------------------------- ### Install Acorn MilliRules with Composer Source: https://millipress.com/docs/acorn-millicache/01-getting-started/01-introduction Use Composer to install the Acorn MilliRules package, which is recommended for defining route-aware cache conditions. ```bash 1composer require millipress/acorn-millirules ``` -------------------------------- ### Progressive Enhancement with Packages Source: https://millipress.com/docs/millirules/02-core-concepts/02-packages Initialize with a base set of rules and conditionally enhance functionality by loading additional packages like WordPress if they are available. ```php // Base rules with PHP package MilliRules::init(['PHP']); Rules::create('base_security') ->when()->request_url('*') ->then()->custom('basic_security') ->register(); // Enhance with WordPress if available if (PackageManager::is_package_loaded('WP')) { Rules::create('wp_security') ->when()->is_user_logged_in() ->then()->custom('enhanced_security') ->register(); } ``` -------------------------------- ### Cache Entry Flags Example Source: https://millipress.com/docs/millicache/05-usage/10-how-caching-works Provides examples of flags (tags) used for cache invalidation, demonstrating how different page types are tagged. ```text Homepage: [home, archive:post] Single post: [post:123] Archives: [archive:category:5, archive:post] Author: [archive:author:1] ``` -------------------------------- ### Load Packages During Initialization Source: https://millipress.com/docs/millirules/02-core-concepts/02-packages Load all available packages automatically using MilliRules::init(), or specify a list of package names to load explicitly. ```php 1use MilliRulesMilliRules; 2 3// Auto-loads available packages 4MilliRules::init(); 5 6// Or specify packages explicitly 7MilliRules::init(['PHP', 'WP']); ``` -------------------------------- ### Install Acorn MilliRules Source: https://millipress.com/docs/acorn-millicache Use Composer to install the Acorn MilliRules package, which is recommended to pair with Acorn MilliCache for defining route-aware caching conditions. ```bash 1composer require millipress/acorn-millirules ``` -------------------------------- ### Logging API Requests with Placeholders Source: https://millipress.com/docs/millirules/02-core-concepts/05-placeholders This example demonstrates how to log detailed information about incoming API requests using placeholders for method, URI, and IP address. It registers a custom action to handle the logging. ```php 1Rules::register_action('log_request', function($args, Context $context) { 2 $message = $args['value'] ?? ''; 3 error_log($message); 4}); 5 6Rules::create('log_requests') 7 ->when()->request_url('/api/*') 8 ->then() 9 ->custom('log_request', [ 10 'value' => 'API request: {request.method} {request.uri} from {request.ip}' 11 ]) 12 ->register(); 13 14// Logs: "API request: GET /api/users from 192.168.1.1" ``` -------------------------------- ### Registering and Using Logging Actions Source: https://millipress.com/docs/millirules/05-reference/02-actions Demonstrates how to register simple and structured logging actions and then use them within a rule. The `log` action logs a simple message, while `log_structured` logs a JSON object with context-specific data. ```php 1// Simple logging 2Rules::register_action('log', function($args, Context $context) { 3 error_log($args['value'] ?? ''); 4}); 5 6// Structured logging 7Rules::register_action('log_structured', function($args, Context $context) { 8 $data = [ 9 'timestamp' => time(), 10 'user' => $context->get('user.login', 'guest') ?? 'guest', 11 'ip' => $context['request']['ip'] ?? 'unknown', 12 'message' => $args['value'] ?? '', 13 ]; 14 error_log(json_encode($data)); 15}); 16 17// Usage 18Rules::create('log_actions') 19 ->when()->request_url('/important/*') 20 ->then() 21 ->custom('log', ['value' => 'Important URL accessed']) 22 ->custom('log_structured', ['value' => 'Security alert']) 23 ->register(); ``` -------------------------------- ### Context Class Methods Source: https://millipress.com/docs/millirules/02-core-concepts Use the Context class to get, set, check, load, and export data using dot notation. The get() method automatically loads sections if they are not already present. ```php $value = $context->get('post.type', 'post'); $context->set('custom.data', 'value'); if ($context->has('user.id')) { // User data is loaded } $context->load('request'); $array = $context->to_array(); ``` -------------------------------- ### Early Execution with Packages Source: https://millipress.com/docs/millirules/02-core-concepts/02-packages Initialize MilliRules and execute rules early in the loading process, specifying the required packages. ```PHP 1// In mu-plugins or early hook 2MilliRules::init(['PHP']); 4// Execute only PHP rules 5$result = MilliRules::execute_rules(['PHP']); ``` -------------------------------- ### Configuration Management with Settings Source: https://millipress.com/docs/millicache/07-developers/01-architecture The Settings class manages configuration, accessible via the Engine singleton. Use instance() to get the MilliBaseSettings object. Settings can be retrieved by key or modified. ```php 1use MilliCacheCoreSettings; 2 3$settings = Settings::instance(); 4 5// Get settings 6$ttl = $settings->get( 'cache.ttl' ); 7$cache = $settings->get( 'cache' ); 8 9// Set settings 10$settings->set( 'cache.ttl', 3600 ); 11 12// Import/Export 13$settings->export( 'cache' ); 14$settings->import( $data ); ``` -------------------------------- ### Install Acorn MilliCache Companion Package Source: https://millipress.com/docs/millicache/01-getting-started/10-introduction Use Composer to install the Acorn MilliCache companion package for Roots stacks with Acorn. This package integrates MilliCache with Laravel middleware for automatic response caching. ```bash 1composer require millipress/acorn-millicache ``` -------------------------------- ### Action Configuration with Arrays Source: https://millipress.com/docs/millirules/02-core-concepts/03-building-rules Illustrates how to pass configuration data to custom actions using associative arrays. ```php Rules::create('send_notification') ->when() ->request_url('/api/notify') ->then() ->custom('send_email', [ 'value' => 'admin@example.com', 'subject' => 'New Notification', 'message' => 'You have a new notification' ]) ->custom('log_notification', [ 'value' => 'Email sent to admin' ]) ->register(); ``` -------------------------------- ### Install Acorn MilliRules Package Source: https://millipress.com/docs/acorn-millicache/01-getting-started/02-installation Install the Acorn MilliRules package using Composer to enable route-aware caching conditions, redirects, and custom cache flags. This package is optional and extends MilliCache's functionality. ```bash composer require millipress/acorn-millirules ``` -------------------------------- ### Operator Auto-Detection Examples Source: https://millipress.com/docs/millirules/02-core-concepts/04-operators Demonstrates how MilliRules auto-detects operators based on the type of value provided. For example, an array value triggers the 'IN' operator, a boolean triggers 'IS', and a string with wildcards triggers 'LIKE'. ```millirules ->request_method('GET') // = (string, no wildcard) ->request_method(['GET', 'HEAD']) // IN (array) ->constant('WP_DEBUG', true) // IS (boolean) ->cookie('session_id') // EXISTS (no value parameter) ->request_url('/admin/*') // LIKE (has wildcard) ->request_url('/^\/api\//i') // REGEXP (starts with /) ``` -------------------------------- ### WordPress Hook Timing Best Practice Source: https://millipress.com/docs/millirules/04-advanced/03-wordpress-integration Demonstrates the correct timing for initializing MilliRules and registering rules using the 'init' hook with an early priority. ```php 1// ✅ Good - initialize early 2add_action('init', function() { MilliRules::init(); register_rules(); }, 1); // Early priority 7// ❌ Bad - too late, hooks may have fired 8add_action('wp_footer', function() { MilliRules::init(); // Too late! register_rules(); }); ``` -------------------------------- ### Get Loaded Packages Source: https://millipress.com/docs/millirules/05-reference/03-api Retrieves the names of all packages that have been loaded into MilliRules. ```php $packages = MilliRules::get_loaded_packages(); // ['PHP', 'WP'] ``` -------------------------------- ### Package Interface - Get Name Source: https://millipress.com/docs/millirules/05-reference/03-api Implement `get_name` to return the unique name of a package. ```php public function get_name(): string { return 'my_package'; } ``` -------------------------------- ### MilliRules::init Source: https://millipress.com/docs/millirules/05-reference/03-api Initializes MilliRules and loads specified or all available packages. ```APIDOC ## MilliRules::init ### Description Initialize MilliRules and load packages. ### Method `init(?array $package_names = null, ?array $packages = null): array` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Parameters * `$package_names` (array|null): Array of package names to load (null = auto-load all available) * `$packages` (array|null): Array of PackageInterface instances to register (null = register defaults) ### Returns `array` - Array of loaded package names ### Request Example ```php // Auto-load available packages MilliRules::init(); // Load specific packages by name MilliRules::init(['PHP', 'WP']); // Load with custom package instances $custom = new CustomPackage(); MilliRules::init(null, [$custom]); ``` ``` -------------------------------- ### Get All Loaded Packages Source: https://millipress.com/docs/millirules/02-core-concepts/02-packages Retrieve an array of names for all currently loaded MilliRules packages. ```PHP 1use MilliRulesMilliRules; 2 3// Get package names 4$package_names = MilliRules::get_loaded_packages(); 5// ['PHP', 'WP'] 6 7error_log('Loaded packages: ' . implode(', ', $package_names)); ``` -------------------------------- ### Complete Cache Integration Example Source: https://millipress.com/docs/millicache/07-developers/03-api-reference Demonstrates a comprehensive cache integration for a membership site, including custom flags, clearing cache on level change, short TTL for dynamic pages, and REST API endpoint for clearing membership cache. ```php 1 'POST', 33 'callback' => function() { 34 millicache_clear_cache_by_flags( [ 'membership:*' ] ); 35 return [ 'success' => true ]; 36 }, 37 'permission_callback' => function() { 38 return current_user_can( 'manage_options' ); 39 }, 40 ] ); 41} ); ``` -------------------------------- ### Sequential Condition Evaluation Source: https://millipress.com/docs/millirules/05-reference/01-conditions Conditions are evaluated in the order they are defined. This example shows a sequence of checks. ```php 1Rules::create('sequential_checks') 2 ->when() 3 ->request_url('/api/*') // Checked first 4 ->request_method('POST') // Checked second 5 ->cookie('auth_token') // Checked third 6 ->then()->custom('action') 7 ->register(); ``` -------------------------------- ### Publish Configuration File Source: https://millipress.com/docs/acorn-millirules/03-customization/02-configuration Publish the MilliRules configuration file to your application. ```bash 1wp acorn vendor:publish --tag=millirules ``` -------------------------------- ### Package Interface - Build Context Source: https://millipress.com/docs/millirules/05-reference/03-api Implement `build_context` to construct and return context data for the package. ```php public function build_context(): array { return ['user_id' => 123]; } ``` -------------------------------- ### Verify Rule with Commands Source: https://millipress.com/docs/acorn-millirules/01-getting-started/02-installation Use `rules:list` to see all registered rules and `rules:show` to inspect a specific rule's details, including its conditions and actions. ```bash wp acorn rules:list ``` ```bash wp acorn rules:show security-headers ``` -------------------------------- ### Temporary Redirect Example Source: https://millipress.com/docs/acorn-millirules/04-reference/02-actions Shows a temporary redirect using the default status code (302). ```php 1Rules::create('maintenance-redirect') 2 ->when() 3 ->routeName('docs.maintenance') 4 ->then() 5 ->redirect('/maintenance') 6 ->register(); ``` -------------------------------- ### Rule Action Ordering in MilliRules Source: https://millipress.com/docs/millirules/05-reference/02-actions Demonstrates the correct way to define multiple actions within a single rule to ensure they execute sequentially. Actions within the same rule are guaranteed to run in the order they are defined. ```php 1// ❌ Wrong - different rules, no guaranteed order 2Rules::create('rule1')->order(10)->when()->then()->custom('action1')->register(); 3Rules::create('rule2')->order(20)->when()->then()->custom('action2')->register(); 4// action1 and action2 only execute if their respective rule conditions match 5 6// ✅ Correct - actions in same rule execute in order 7Rules::create('rule')->order(10) 8 ->when()->request_url('*') 9 ->then() 10 ->custom('action1') // Executes first 11 ->custom('action2') // Executes second 12 ->register(); ``` -------------------------------- ### Action Interface - Get Type Source: https://millipress.com/docs/millirules/05-reference/03-api Implement `get_type` to return the unique identifier string for the action. ```php public function get_type(): string { return 'my_action'; } ``` -------------------------------- ### Initialize MilliRules (PHP Package) Source: https://millipress.com/docs/millirules/02-core-concepts The PHP package is always available and can be initialized using MilliRules::init(). ```php MilliRules::init(); ``` -------------------------------- ### Condition Interface - Get Type Source: https://millipress.com/docs/millirules/05-reference/03-api Implement `get_type` to return the unique identifier string for the condition. ```php public function get_type(): string { return 'my_condition'; } ``` -------------------------------- ### Get Route Middleware Source: https://millipress.com/docs/acorn-millirules/04-reference/03-route-context Retrieve an array of middleware names or classes applied to the current route. ```php 1$context->get('route.middleware'); // ['web', 'auth'] ``` -------------------------------- ### Publish Config and Stubs Source: https://millipress.com/docs/acorn-millirules/01-getting-started/02-installation Publish the configuration file and stub templates for customization. This is optional as the package works with defaults. ```bash wp acorn vendor:publish --tag=millirules ``` -------------------------------- ### Processing Request Parameters with Placeholders Source: https://millipress.com/docs/millirules/02-core-concepts/05-placeholders This example shows how to process specific request parameters like 'action' and 'id' using placeholders. It registers a custom action to log the processed parameters. ```php 1Rules::register_action('process_action', function($args, Context $context) { 2 $action = $args['action'] ?? ''; 3 $id = $args['id'] ?? 0; 4 error_log("Processing action: {$action} for ID: {$id}"); 5}); 6 7Rules::create('process_request') 8 ->when() 9 ->request_param('action') 10 ->request_param('id') 11 ->then() 12 ->custom('process_action', [ 13 'action' => '{param.action}', 14 'id' => '{param.id}' 15 ]) 16 ->register(); ``` -------------------------------- ### Package Interface - Get Required Packages Source: https://millipress.com/docs/millirules/05-reference/03-api Implement `get_required_packages` to return an array of required package names. ```php public function get_required_packages(): array { return ['core', 'utils']; } ``` -------------------------------- ### Get Route URI Pattern Source: https://millipress.com/docs/acorn-millirules/04-reference/03-route-context Access the raw route URI pattern, including any parameter placeholders. ```php 1$context->get('route.uri'); // '/docs/{product}/{path?} ' ``` -------------------------------- ### Context Structure Example Source: https://millipress.com/docs/millirules/02-core-concepts Illustrates the structure of the Millirules context object, showing available data sections like 'request', 'user', and 'hook'. Data is loaded on-demand. ```php 1use MilliRulesContext; 2 3// Context sections (loaded on-demand): 4[ 5 'request' => [ 6 'method' => 'GET', 7 'uri' => '/wp-admin/edit.php', 8 'scheme' => 'https', 9 'host' => 'example.com', 10 'path' => '/wp-admin/edit.php', 11 'query' => 'post_type=page', 12 'referer' => 'https://example.com', 13 'user_agent' => 'Mozilla/5.0...', 14 'headers' => [...], 15 'ip' => '192.168.1.1', 16 ], 17 'cookie' => [...], // Cookies (separate from request) 18 'param' => [...], // Request parameters (GET/POST) 19 'post' => [...], // WordPress post data 20 'user' => [...], // WordPress user data 21 'query' => [...], // WordPress query variables (post_type, paged, s, etc.) 22 'term' => [...], // WordPress taxonomy terms 23 'rule' => [ 24 'id' => 'my-rule', 25 'order' => 10, 26 ], 27 'hook' => [ 28 'name' => 'template_redirect', 29 'args' => [...], 30 ], 31 // Custom package data... 32] ``` -------------------------------- ### Create Rule with Less Than Operator Source: https://millipress.com/docs/millirules/02-core-concepts/04-operators Example of creating a rule for early pagination, triggering for pages less than '5'. ```php 1Rules::create('early_pagination') ->when() ->request_param('page', '5', '<') // First 4 pages ->then()->custom('show_getting_started') ->register(); ``` -------------------------------- ### Rule Execution Order Example Source: https://millipress.com/docs/millirules/02-core-concepts Illustrates how rules with different 'order' values execute sequentially. The rule with the lower order executes first, and subsequent rules can override previous actions. ```php // Rule 1 (order: 10) sets cache to 3600 seconds Rules::create('cache_short')->order(10) ->when()->request_url('/api/*') ->then()->custom('set_cache', ['value' => '3600']) ->register(); // Rule 2 (order: 20) overrides cache to 7200 seconds Rules::create('cache_long')->order(20) ->when()->request_url('/api/stable/*') ->then()->custom('set_cache', ['value' => '7200']) ->register(); ``` -------------------------------- ### Registering Custom Actions Before Use Source: https://millipress.com/docs/millirules/01-getting-started/03-first-rule Demonstrates the correct way to use custom actions by first registering them with `Rules::register_action()` before they are referenced in a rule. Using an undefined action will cause an error. ```php 1// ❌ Wrong - 'send_email' not registered 2Rules::create('notify') 3 ->when()->request_url('/contact') 4 ->then()->custom('send_email') // Not defined! 5 ->register(); 6 7// ✅ Correct - register action first 8Rules::register_action('send_email', function($args, Context $context) { 9 // Email sending logic here 10}); 11 12Rules::create('notify') 13 ->when()->request_url('/contact') 14 ->then()->custom('send_email') 15 ->register(); ``` -------------------------------- ### Dynamic Rule Generation with Loop Source: https://millipress.com/docs/millirules/02-core-concepts/03-building-rules Generate multiple rules programmatically using a loop, for example, to protect a list of URLs. ```php $protected_urls = ['/admin', '/dashboard', '/settings']; foreach ($protected_urls as $url) { Rules::create('protect_' . sanitize_title($url)) ->when() ->request_url($url . '/*') ->is_user_logged_in(false) // Not logged in ->then() ->custom('redirect_to_login', ['url' => $url]) ->register(); } ``` -------------------------------- ### Registering a Custom Package Source: https://millipress.com/docs/millirules/03-customization/03-custom-packages Register your custom package instance with `MilliRules::init()`. Alternatively, MilliRules can auto-discover packages if they are registered globally. ```php use MilliRulesMilliRules; use MyPluginPackagesMyCustomPackage; // Register custom package $custom_package = new MyCustomPackage(); MilliRules::init(null, [$custom_package]); // Or let MilliRules auto-discover (if registered globally) MilliRules::init(); ``` -------------------------------- ### Using Descriptive Action Names (Good Practice) Source: https://millipress.com/docs/millirules/05-reference/02-actions Employ clear and descriptive names for actions to indicate their purpose, enhancing code readability. ```php // ✅ Good Rules::register_action('send_admin_notification_email', ...); Rules::register_action('log_security_event', ...); Rules::register_action('update_user_last_login_timestamp', ...); ``` -------------------------------- ### MilliCache Status Header Example Source: https://millipress.com/docs/millicache/05-usage/10-how-caching-works Demonstrates how to view the cache status of a served response using the X-MilliCache-Status debug header. ```http X-MilliCache-Status: hit ``` -------------------------------- ### Package Interface - Get Namespaces Source: https://millipress.com/docs/millirules/05-reference/03-api Implement `get_namespaces` to return an array of namespace strings for conditions and actions provided by the package. ```php public function get_namespaces(): array { return ['App\Conditions', 'App\Actions']; } ``` -------------------------------- ### Initialize Millirules with Custom Package Source: https://millipress.com/docs/millirules/03-customization/03-custom-packages Initializes Millirules with a custom package and demonstrates creating a rule that uses both built-in and custom conditions and actions. ```php 1use MilliRulesMilliRules; 2use MyPluginPackagesMembershipPackage; 3 4// Initialize with custom package 5$membership_package = new MembershipPackage(); 6MilliRules::init(null, [$membership_package]); 7 8// Create rule using package conditions and actions 9Rules::create('auto_upgrade_frequent_buyers') 10 ->when() 11 ->is_user_logged_in() // WP condition 12 ->custom('membership_level', ['value' => 'free']) // Membership condition 13 ->custom('purchase_count', ['value' => 10, 'operator' => '>=']) 14 ->then() 15 ->custom('upgrade_membership', [ 16 'level' => 'premium', ``` -------------------------------- ### Get Package Instance Source: https://millipress.com/docs/millirules/02-core-concepts/02-packages Retrieve a specific package instance by its name. Check if the package was successfully loaded before accessing its methods. ```php use MilliRulesPackageManager; $php_package = PackageManager::get_package('PHP'); if ($php_package) { $namespaces = $php_package->get_namespaces(); error_log('PHP package namespaces: ' . print_r($namespaces, true)); } ```