arraypress/wp-compare-utils

Comprehensive comparison utilities for WordPress development with meta value support

dev-main 2025-07-21 18:26 UTC

This package is auto-updated.

Last update: 2025-09-02 11:28:27 UTC


README

Comprehensive comparison utilities for WordPress development with special support for meta value comparisons and conditional logic. Handles operator decoding, multiple data types, and complex comparison scenarios.

Features

  • 🎯 Multiple Data Types: Boolean, numeric, string, date, time, array, IP address comparisons
  • 🔧 WordPress-Optimized: Handles meta value operator encoding issues
  • Flexible Operators: Support for equality, contains, starts/ends with, ranges, and more
  • 🛡️ Robust Validation: Built-in validation for all comparison types
  • 📊 Multi-Value Support: Compare against arrays of values with AND/OR logic
  • 🌐 IP Address Support: CIDR range matching and IP validation
  • 🕒 Time Comparisons: Perfect for store hours, scheduling, and time-based logic

Requirements

  • PHP 7.4 or later
  • WordPress 5.0 or later

Installation

composer require arraypress/wp-compare-utils

Basic Usage

Boolean Comparisons

use ArrayPress\CompareUtils\Compare;

// Meta value boolean checks
$is_featured = Compare::boolean( '==', true, $post_meta_featured );
$not_draft   = Compare::boolean( '!=', false, $post_published );

// Supported operators: ==, ===, is, equal_to, !=, !==, is_not, not_equal_to

Numeric Comparisons

// Price comparisons with float precision
$in_budget   = Compare::numeric( '<=', 100.00, $product_price );
$adult       = Compare::numeric( '>=', 18, $user_age );
$exact_match = Compare::numeric( '==', 99.99, $price, 0.01 ); // Custom epsilon

// Supported operators: ==, ===, !=, !==, >, >=, <, <=

String Comparisons

// Case-sensitive comparisons
$has_keyword = Compare::string( 'contains', 'wordpress', $post_content );
$is_admin    = Compare::string( 'starts_with', 'admin', $page_slug );
$is_php      = Compare::string( 'ends_with', '.php', $filename );

// Case-insensitive comparisons
$matches = Compare::string_i( '==', 'WORDPRESS', $platform ); // true for 'wordpress'

// Supported operators: ==, !=, contains, not_contains, starts_with, ends_with

Date and Time Comparisons

// Date comparisons
$is_future = Compare::dates( '>', 'now', $event_date );
$this_year = Compare::dates( '>=', '2024-01-01', $post_date );

// Time comparisons (perfect for store hours)
$is_open      = Compare::times( '>=', '09:00', $current_time );
$before_close = Compare::times( '<', '17:00', $current_time );

// Store hours example
$current_time = date( 'H:i' );
$store_open   = Compare::times( '>=', '09:00', $current_time );
$store_close  = Compare::times( '<=', '17:00', $current_time );
$is_open      = $store_open && $store_close;

Array Comparisons

// Check if value exists in array
$has_role    = Compare::array( 'contains', 'administrator', $user_roles );
$not_in_list = Compare::array( 'not_contains', $user_id, $blocked_users );

// Multi-value comparisons (unified method)
$tags    = [ 'wordpress', 'php', 'development' ];
$content = 'This is about WordPress and PHP development';

// String subject - check if content contains any tags
$relevant = Compare::multi( 'contains', $tags, $content ); // true

// String subject - check if content contains ALL tags  
$comprehensive = Compare::multi( 'contains_all', $tags, $content ); // true

// Array subject - check if arrays have any overlap
$user_skills = [ 'php', 'javascript', 'css' ];
$has_skills  = Compare::multi( 'contains', $tags, $user_skills ); // true (php match)

IP Address Comparisons

// Exact IP matching
$is_admin_ip = Compare::ip_address( '==', '192.168.1.100', $user_ip );

// CIDR range matching
$internal    = Compare::ip_address( '==', '192.168.1.0/24', $user_ip );
$not_blocked = Compare::ip_address( '!=', '10.0.0.0/8', $user_ip );

Advanced Examples

// WordPress meta field filtering
$posts = get_posts( [
	'meta_query' => [
		[
			'key'     => 'price',
			'value'   => 100,
			'compare' => 'NUMERIC'
		]
	]
] );

// Use Compare utils for additional filtering
$affordable_posts = array_filter( $posts, function ( $post ) {
	$price = get_post_meta( $post->ID, 'price', true );

	return Compare::numeric( '<=', 50, $price );
} );

// Multi-condition filtering
$premium_posts = array_filter( $posts, function ( $post ) {
	$featured = get_post_meta( $post->ID, 'featured', true );
	$category = get_post_meta( $post->ID, 'category', true );
	$tags     = get_post_meta( $post->ID, 'tags', true );

	return Compare::boolean( '==', true, $featured ) &&
	       Compare::array( 'contains', 'premium', explode( ',', $category ) ) &&
	       Compare::multi( 'contains', [ 'exclusive', 'vip' ], $tags );
} );

API Reference

Core Comparison Methods

Method Description Returns
boolean($operator, $value, $bool) Compare boolean values bool
numeric($operator, $value1, $value2, $epsilon) Compare numbers with precision bool
string($operator, $value, $string) Compare strings (case-sensitive) bool
string_i($operator, $value, $string) Compare strings (case-insensitive) bool
dates($operator, $value, $date) Compare date values bool
times($operator, $value, $time) Compare time values (H:i format) bool
array($operator, $value, $array) Check if value exists in array bool

Multi-Value Methods

Method Description Returns
multi($operator, $values, $subject) Compare multiple values against string or array bool

Specialized Methods

Method Description Returns
ip_address($operator, $value, $ip) Compare IP addresses (supports CIDR) bool
fuzzy_string($value, $string, $max_distance) Fuzzy string matching with Levenshtein bool

Supported Operators

Equality Operators

  • ==, ===, equal_to
  • !=, !==, not_equal_to

Comparison Operators

  • >, >=, <, <=

String Operators

  • contains, not_contains
  • starts_with, ends_with

Multi-Value Operators

  • contains - Any value matches
  • contains_all - All values must match
  • not_contains - No values match

Boolean Operators

  • is, is_not

Common Use Cases

WordPress Post Filtering

// Filter posts by custom fields
function filter_posts_by_criteria( $posts, $criteria ) {
	return array_filter( $posts, function ( $post ) use ( $criteria ) {
		$price    = get_post_meta( $post->ID, 'price', true );
		$featured = get_post_meta( $post->ID, 'featured', true );
		$category = get_post_meta( $post->ID, 'category', true );

		return Compare::numeric( '<=', $criteria['max_price'], $price ) &&
		       Compare::boolean( '==', $criteria['featured'], $featured ) &&
		       Compare::string( '==', $criteria['category'], $category );
	} );
}

User Access Control

// Check user permissions and conditions
function can_user_access( $user_id, $resource ) {
	$user        = get_user_by( 'id', $user_id );
	$user_roles  = $user->roles;
	$user_ip     = $_SERVER['REMOTE_ADDR'];
	$blocked_ips = get_option( 'blocked_ip_ranges', [] );

	$has_permission = Compare::multi( 'contains', [ 'administrator', 'editor' ], $user_roles );
	$ip_allowed     = ! Compare::multi( 'contains', $blocked_ips, $user_ip );

	return $has_permission && $ip_allowed;
}

Store Hours / Business Logic

// Check if store is currently open
function is_store_open() {
	$current_time = date( 'H:i' );
	$current_day  = date( 'N' ); // 1 (Monday) to 7 (Sunday)

	$hours = get_option( 'store_hours', [
		'1' => [ 'open' => '09:00', 'close' => '17:00' ], // Monday
		'2' => [ 'open' => '09:00', 'close' => '17:00' ], // Tuesday
		// ... etc
	] );

	if ( ! isset( $hours[ $current_day ] ) ) {
		return false; // Closed on this day
	}

	$today_hours  = $hours[ $current_day ];
	$after_open   = Compare::times( '>=', $today_hours['open'], $current_time );
	$before_close = Compare::times( '<=', $today_hours['close'], $current_time );

	return $after_open && $before_close;
}

Content Personalization

// Show content based on user criteria
function should_show_promotion( $user_id ) {
	$user_meta        = get_user_meta( $user_id );
	$purchase_history = get_user_meta( $user_id, 'purchase_history', true );
	$user_tags        = get_user_meta( $user_id, 'tags', true );

	// Multiple conditions
	$is_premium      = Compare::boolean( '==', true, $user_meta['premium'][0] ?? false );
	$recent_purchase = Compare::dates( '>', '-30 days', $user_meta['last_purchase'][0] ?? '' );
	$target_audience = Compare::multi( 'contains', [ 'vip', 'loyal' ], explode( ',', $user_tags ) );

	return $is_premium || $recent_purchase || $target_audience;
}

API Response Filtering

// Filter API responses based on criteria
function filter_api_results( $results, $filters ) {
	return array_filter( $results, function ( $item ) use ( $filters ) {
		$matches = true;

		foreach ( $filters as $field => $criteria ) {
			$operator = $criteria['operator'];
			$value    = $criteria['value'];

			if ( ! isset( $item[ $field ] ) ) {
				$matches = false;
				break;
			}

			switch ( $criteria['type'] ) {
				case 'string':
					$matches = Compare::string( $operator, $value, $item[ $field ] );
					break;
				case 'numeric':
					$matches = Compare::numeric( $operator, $value, $item[ $field ] );
					break;
				case 'array':
					$matches = Compare::array( $operator, $value, $item[ $field ] );
					break;
			}

			if ( ! $matches ) {
				break;
			}
		}

		return $matches;
	} );
}

Meta Value Support

This library was specifically designed to handle WordPress meta value comparisons, including the operator decoding issue where operators saved as meta values can contain hidden characters:

// Automatically handles encoded operators from meta values
$operator      = get_post_meta( $post_id, 'comparison_operator', true ); // Might be encoded
$threshold     = get_post_meta( $post_id, 'threshold', true );
$current_value = get_post_meta( $post_id, 'current_value', true );

// The comparison will work even if operator has encoding issues
$passes = Compare::numeric( $operator, $threshold, $current_value );

Key Benefits

  • WordPress-Native: Built specifically for WordPress development patterns
  • Meta Value Safe: Handles operator encoding issues automatically
  • Type Flexible: Works with various data types and WordPress meta formats
  • Performance Focused: Efficient comparisons suitable for filtering large datasets
  • Developer Friendly: Intuitive method names and consistent API
  • Self-Contained: No external dependencies beyond PHP core functions

Requirements

  • PHP 7.4+
  • WordPress 5.0+

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

This project is licensed under the GPL-2.0-or-later License.

Support