PluginProbe
Double Opt-In for Contact Form 7 – Secure, GDPR-Compliant Email Verification / 5.5.0
Double Opt-In for Contact Form 7 – Secure, GDPR-Compliant Email Verification v5.5.0
5.5.0 5.4.0 5.3.2 5.3.1 5.1.6 5.1.5 trunk 2.1.5 2.11 2.12 2.13 2.15 3.0.0 3.0.1 3.0.2 3.0.3 3.0.5 3.0.51 3.0.60 3.0.61 3.0.62 3.0.70 3.0.71 3.0.72 3.1.0 All 34 releases
double-opt-in / src / Versioning / SemverConstraint.php

SemverConstraint.php in Double Opt-In for Contact Form 7 – Secure, GDPR-Compliant Email Verification 5.5.0, at src/Versioning/SemverConstraint.php

93 lines 2.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Semver Constraint Matcher
4 *
5 * Minimal semver constraint evaluator used to compare an addon's declared
6 * core-version requirement (e.g. "^4.3") against the core's actual API
7 * version (e.g. "4.3.0"). Does not require composer/semver — keeps the
8 * Core plugin's dependency surface minimal.
9 *
10 * @package Forge12\DoubleOptIn\Versioning
11 * @since 4.3.0
12 */
13
14 namespace Forge12\DoubleOptIn\Versioning;
15
16 if ( ! defined( 'ABSPATH' ) ) {
17 exit;
18 }
19
20 /**
21 * Class SemverConstraint
22 *
23 * @api
24 *
25 * Supports a deliberately small constraint grammar — enough to express
26 * the dependency shapes addons actually need, no more:
27 *
28 * - "^X.Y" — caret: >=X.Y.0 and <(X+1).0.0
29 * - "^X.Y.Z" — caret: >=X.Y.Z and <(X+1).0.0
30 * - "~X.Y" — tilde: >=X.Y.0 and <X.(Y+1).0
31 * - "~X.Y.Z" — tilde: >=X.Y.Z and <X.(Y+1).0
32 * - ">=X.Y[.Z]" — inclusive lower bound
33 * - "<=X.Y[.Z]" — inclusive upper bound
34 * - ">X.Y[.Z]" — exclusive lower bound
35 * - "<X.Y[.Z]" — exclusive upper bound
36 * - "=X.Y[.Z]" — exact match (alias: no operator, e.g. "X.Y.Z")
37 *
38 * Unsupported, by design: OR clauses, pre-release suffixes, wildcard
39 * ranges, spaces in constraints. If an addon needs those, it has picked
40 * the wrong dependency language.
41 */
42 final class SemverConstraint {
43
44 /**
45 * Check if a version satisfies a constraint.
46 *
47 * @param string $current Current version (e.g. "4.3.0").
48 * @param string $constraint Constraint (e.g. "^4.3").
49 * @return bool True if $current satisfies $constraint. Returns false
50 * for malformed constraints — callers should treat a
51 * false return as "does not match" without needing to
52 * distinguish "malformed" from "not matching".
53 */
54 public static function matches( string $current, string $constraint ): bool {
55 $current = trim( $current );
56 $constraint = trim( $constraint );
57
58 if ( $current === '' || $constraint === '' ) {
59 return false;
60 }
61
62 // Caret: ^X.Y or ^X.Y.Z
63 if ( preg_match( '/^\^(\d+)\.(\d+)(?:\.(\d+))?$/', $constraint, $m ) ) {
64 $min = $m[1] . '.' . $m[2] . '.' . ( $m[3] ?? '0' );
65 $maxMajor = (int) $m[1] + 1;
66 $max = $maxMajor . '.0.0';
67
68 return version_compare( $current, $min, '>=' )
69 && version_compare( $current, $max, '<' );
70 }
71
72 // Tilde: ~X.Y or ~X.Y.Z
73 if ( preg_match( '/^~(\d+)\.(\d+)(?:\.(\d+))?$/', $constraint, $m ) ) {
74 $min = $m[1] . '.' . $m[2] . '.' . ( $m[3] ?? '0' );
75 $maxMinor = (int) $m[2] + 1;
76 $max = $m[1] . '.' . $maxMinor . '.0';
77
78 return version_compare( $current, $min, '>=' )
79 && version_compare( $current, $max, '<' );
80 }
81
82 // Comparison operator: >=, <=, >, <, =, or no operator (exact)
83 if ( preg_match( '/^(>=|<=|>|<|=)?\s*(\d+\.\d+(?:\.\d+)?)$/', $constraint, $m ) ) {
84 $op = $m[1] !== '' ? $m[1] : '=';
85 $version = $m[2];
86
87 return version_compare( $current, $version, $op );
88 }
89
90 return false;
91 }
92 }
93