Skip to content
This repository was archived by the owner on May 2, 2023. It is now read-only.

Commit 2bcf3b7

Browse files
Add support for spermies (~)
All wildcards are internally replaced by x [FIX] Only one x or number allowed per version part
1 parent 98b6faf commit 2bcf3b7

File tree

3 files changed

+67
-22
lines changed

3 files changed

+67
-22
lines changed

definitions

+10-6
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,18 @@ Higher version: >
1212
Lower or equal version: <=
1313
Higher or equal version: >=
1414
x or * as a wildcard
15-
e.g.: 1.x.x ~ >= 1.0.0 < 2.0.0
16-
1.2.* ~ >= 1.2.0 < 1.3.0
15+
e.g.: 1.x.x >= 1.0.0 < 2.0.0
16+
1.2.* >= 1.2.0 < 1.3.0
1717
A range can be expressed with -
18-
e.g.: 1.0.0 - 1.2.3 ~ >=1.0.0 <1.2.3
19-
1.2.0 - 2.0.0 ~ >=1.2.0 <2.0.0
18+
e.g.: 1.0.0 - 1.2.3 >=1.0.0 <1.2.3
19+
1.2.0 - 2.0.0 >=1.2.0 <2.0.0
2020
A range can be expressed by omitting lower order numbers
21-
e.g.: 1 ~ >=1.0.0 <2.0.0
22-
1.2 ~ >=1.2.0 <1.3.0
21+
e.g.: 1 >=1.0.0 <2.0.0
22+
1.2 >=1.2.0 <1.3.0
23+
A range can be expressed with ~
24+
e.g.: ~1 >=1.0.0 <2.0.0
25+
~1.2 >=1.2.0 <1.3.0
26+
~1.2.3 >=1.2.3 <1.3.0
2327

2428
##Logic
2529
Two or more comparators in one string with only spaces between them: AND

test.php

+13
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,19 @@ function testShortversionRange() {
111111
$this->assertEqual($v->getString(),$result,'['.$original.'] %s');
112112
}
113113
}
114+
function testSpermies() {
115+
$t=array(
116+
'~1'=>'>=1.0.0 <2.0.0',
117+
'~2.3'=>'>=2.3.0 <2.4.0',
118+
'~3.7.2'=>'>=3.7.2 <3.8.0',
119+
'~1.x'=>'>=1.0.0 <2.0.0',
120+
'~1.2.x'=>'>=1.2.0 <1.3.0',
121+
);
122+
foreach($t as $original=>$result) {
123+
$v=new versionExpression($original);
124+
$this->assertEqual($v->getString(),$result,'['.$original.'] %s');
125+
}
126+
}
114127
function testInvalidVersion() {
115128
$t=array(
116129
'3.x2',

version.php

+44-16
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
<?php
22
class versionExpression {
3-
const version='0.1.0';
3+
const version='0.2.0';
44
static protected $global_single_version='(([0-9]+)(\\.([0-9]+)(\\.([0-9]+))?)?)';
5-
static protected $global_single_xrange='(([0-9xX*]+)(\\.([0-9xX*]+)(\\.([0-9xX*]+))?)?)';
5+
static protected $global_single_xrange='(([0-9]+|[xX*])(\\.([0-9]+|[xX*])(\\.([0-9]+|[xX*]))?)?)';
66
static protected $global_single_comparator='([<>]=?)?\\s*';
7+
static protected $global_single_spermy='(~?)>?\\s*';
78
static protected $range_mask='%1$s\\s+-\\s+%1$s';
89
static protected $regexp_mask='/%s/';
10+
static protected $wildcards=array('x','X','*');
911
private $chunks=array();
1012
/**
1113
* standarizes the comparator/range/whatever-string to chunks
@@ -16,6 +18,7 @@ function __construct($versions) {
1618
$versions=preg_replace('/'.self::$global_single_comparator.'(\\s+-\\s+)?'.self::$global_single_xrange.'/','$1$2$3',$versions); //Paste comparator and version together
1719
$versions=preg_replace('/\\s+/', ' ', $versions); //Condense multiple spaces to one
1820
if(strstr($versions, '-')) $versions=self::rangesToComparators($versions); //Replace all ranges with comparators
21+
if(strstr($versions,'~')) $versions=self::spermiesToComparators($versions); //Replace all spermies with comparators
1922
if(strstr($versions, 'x')||strstr($versions,'X')||strstr($versions,'*')) $versions=self::xRangesToComparators($versions); //Replace all x-ranges with comparators
2023
$or=explode('||', $versions);
2124
foreach($or as &$orchunk) {
@@ -38,7 +41,7 @@ function satisfiedBy(version $version) {
3841
preg_match($expression, $ablocks, $matches);
3942
$comparators=$matches[1];
4043
$version2=$matches[2];
41-
if($comparators=='') $comparators='=='; //Use equal if no comparator is set
44+
if($comparators==='') $comparators='=='; //Use equal if no comparator is set
4245
if(!version_compare($version, $version2, $comparators)) { //If one chunk of the and-loop does not match...
4346
$ok=false; //It is not okay
4447
break; //And this loop will surely fail: return to or-loop
@@ -106,7 +109,7 @@ static protected function standarizeSingleComparator($version) {
106109
$comparators=$matches[1];
107110
$version=$matches[2];
108111
$hasComparators=true;
109-
if($comparators=='') $hasComparators=false;
112+
if($comparators==='') $hasComparators=false;
110113
$version=self::standarize($version, $hasComparators);
111114
return $comparators.$version;
112115
}
@@ -157,23 +160,45 @@ static protected function xRangesToComparators($ranges) {
157160
* Callback for xRangesToComparators()
158161
* @internal
159162
* @param array $matches
163+
* @return string
160164
*/
161165
static private function xRangesToComparatorsCallback($matches) {
162-
self::matchesToVersionParts($matches, $major, $minor, $patch);
163-
$wildcards=array('x','X','*');
164-
if(in_array($major, $wildcards,true)) return '>=0.0.0';
165-
if(in_array($minor, $wildcards,true)) return '>='.$major.'.0.0 <'.($major+1).'.0.0';
166-
if(in_array($patch, $wildcards,true)) return '>='.$major.'.'.$minor.'.0 <'.$major.'.'.($minor+1).'.0';
166+
self::matchesToVersionParts($matches, $major, $minor, $patch, 'x');
167+
if($major==='x') return '>=0.0.0';
168+
if($minor==='x') return '>='.$major.'.0.0 <'.($major+1).'.0.0';
169+
if($patch==='x') return '>='.$major.'.'.$minor.'.0 <'.$major.'.'.($minor+1).'.0';
167170
return $major.'.'.$minor.'.'.$patch;
168171
}
169172
/**
170-
* Converts matches to named version parts
171-
* @param array $matches
172-
* @param string $major
173-
* @param string $minor
174-
* @param string $patch
175-
* @param string $default
176-
* @param int $offset
173+
* standarizes a bunch of ~-ranges to comparators
174+
* @param string $spermies
175+
* @return string
176+
*/
177+
static protected function spermiesToComparators($spermies) {
178+
$expression=sprintf(self::$regexp_mask,self::$global_single_spermy.self::$global_single_xrange);
179+
return preg_replace_callback($expression, array('self','spermiesToComparatorsCallback'), $spermies);
180+
}
181+
/**
182+
* Callback for spermiesToComparators()
183+
* @internal
184+
* @param unknown_type $matches
185+
* @return string
186+
*/
187+
static private function spermiesToComparatorsCallback($matches) {
188+
self::matchesToVersionParts($matches, $major, $minor, $patch,'x',3);
189+
if($major==='x') return '>=0.0.0';
190+
if($minor==='x') return '>='.$major.'.0.0 <'.($major+1).'.0.0';
191+
if($patch==='x') return '>='.$major.'.'.$minor.'.0 <'.$major.'.'.($minor+1).'.0';
192+
return '>='.$major.'.'.$minor.'.'.$patch.' <'.$major.'.'.($minor+1).'.0';
193+
}
194+
/**
195+
* Converts matches to named version parts, replaces all wildcards by lowercase x
196+
* @param array $matches Matches array from preg_match
197+
* @param int|string $major Reference to major version
198+
* @param int|string $minor Reference to minor version
199+
* @param int|string $patch Reference to patch version
200+
* @param int|string $default Default value for a version if not found in matches array
201+
* @param int $offset The position of the raw occurence of the major version number
177202
*/
178203
static private function matchesToVersionParts($matches, &$major, &$minor, &$patch, $default=0, $offset=2) {
179204
$major=$minor=$patch=$default;
@@ -185,6 +210,9 @@ static private function matchesToVersionParts($matches, &$major, &$minor, &$patc
185210
if(is_numeric($patch)) $patch=intval($patch);
186211
if(is_numeric($minor)) $minor=intval($minor);
187212
if(is_numeric($major)) $major=intval($major);
213+
if(in_array($major, self::$wildcards,true)) $major='x';
214+
if(in_array($minor, self::$wildcards,true)) $minor='x';
215+
if(in_array($patch, self::$wildcards,true)) $patch='x';
188216
}
189217
}
190218
class version extends versionExpression {

0 commit comments

Comments
 (0)