Skip to content

Commit 3df278b

Browse files
authored
Merge pull request #228 from splitio/sdks-8291-unsupported-matcher
Unsupported matcher implementation
2 parents ffacf6f + f606df6 commit 3df278b

23 files changed

+1367
-15
lines changed

.github/workflows/ci.yml

+1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ jobs:
3030
- '8.0'
3131
- '8.1'
3232
- '8.2'
33+
- '8.3'
3334
steps:
3435
- name: Checkout code
3536
uses: actions/checkout@v3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<?php
2+
namespace SplitIO\Exception;
3+
4+
class SemverParseException extends \LogicException
5+
{
6+
7+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<?php
2+
namespace SplitIO\Exception;
3+
4+
class UnsupportedMatcherException extends \LogicException
5+
{
6+
7+
}

src/SplitIO/Grammar/Condition.php

+30-3
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,17 @@
22
namespace SplitIO\Grammar;
33

44
use SplitIO\Exception\InvalidMatcherException;
5-
use SplitIO\Split as SplitApp;
65
use SplitIO\Grammar\Condition\Combiner\AndCombiner;
76
use SplitIO\Grammar\Condition\Combiner\CombinerEnum;
87
use SplitIO\Grammar\Condition\Combiner\Factor\NotFactor;
8+
use SplitIO\Grammar\Condition\ConditionTypeEnum;
99
use SplitIO\Grammar\Condition\Matcher;
10-
use SplitIO\Grammar\Condition\Partition;
1110
use SplitIO\Grammar\Condition\Matcher\AbstractMatcher;
12-
use SplitIO\Grammar\Condition\ConditionTypeEnum;
1311
use SplitIO\Grammar\Condition\Matcher\Dependency;
12+
use SplitIO\Grammar\Condition\Partition;
13+
use SplitIO\Grammar\Condition\Partition\TreatmentEnum;
14+
use SplitIO\Sdk\Impressions\ImpressionLabel;
15+
use SplitIO\Split as SplitApp;
1416

1517
class Condition
1618
{
@@ -115,6 +117,31 @@ public function match($key, array $attributes = null, $bucketingKey = null)
115117
return false;
116118
}
117119

120+
public static function getDefaultCondition()
121+
{
122+
return new Condition(array(
123+
'conditionType' => ConditionTypeEnum::WHITELIST,
124+
'matcherGroup' => array(
125+
'combiner' => CombinerEnum::_AND,
126+
'matchers' => array(
127+
array(
128+
'matcherType' => Matcher::ALL_KEYS,
129+
'negate' => false,
130+
'userDefinedSegmentMatcherData' => null,
131+
'whitelistMatcherData' => null
132+
)
133+
)
134+
),
135+
'partitions' => array(
136+
array(
137+
'treatment' => TreatmentEnum::CONTROL,
138+
'size' => 100
139+
)
140+
),
141+
'label' => ImpressionLabel::UNSUPPORTED_MATCHER
142+
));
143+
}
144+
118145
/**
119146
* @return array|null
120147
*/

src/SplitIO/Grammar/Condition/Matcher.php

+37-1
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,17 @@
11
<?php
22
namespace SplitIO\Grammar\Condition;
33

4+
use SplitIO\Exception\UnsupportedMatcherException;
45
use SplitIO\Grammar\Condition\Matcher\All;
56
use SplitIO\Grammar\Condition\Matcher\Between;
7+
use SplitIO\Grammar\Condition\Matcher\BetweenSemver;
68
use SplitIO\Grammar\Condition\Matcher\EqualTo;
9+
use SplitIO\Grammar\Condition\Matcher\EqualToSemver;
710
use SplitIO\Grammar\Condition\Matcher\GreaterThanOrEqualTo;
11+
use SplitIO\Grammar\Condition\Matcher\GreaterThanOrEqualToSemver;
12+
use SplitIO\Grammar\Condition\Matcher\InListSemver;
813
use SplitIO\Grammar\Condition\Matcher\LessThanOrEqualTo;
14+
use SplitIO\Grammar\Condition\Matcher\LessThanOrEqualToSemver;
915
use SplitIO\Grammar\Condition\Matcher\Segment;
1016
use SplitIO\Grammar\Condition\Matcher\Whitelist;
1117
use SplitIO\Grammar\Condition\Matcher\StartsWith;
@@ -39,6 +45,11 @@ class Matcher
3945
const IN_SPLIT_TREATMENT = 'IN_SPLIT_TREATMENT';
4046
const EQUAL_TO_BOOLEAN = 'EQUAL_TO_BOOLEAN';
4147
const MATCHES_STRING = 'MATCHES_STRING';
48+
const EQUAL_TO_SEMVER = 'EQUAL_TO_SEMVER';
49+
const GREATER_THAN_OR_EQUAL_TO_SEMVER = 'GREATER_THAN_OR_EQUAL_TO_SEMVER';
50+
const LESS_THAN_OR_EQUAL_TO_SEMVER = 'LESS_THAN_OR_EQUAL_TO_SEMVER';
51+
const BETWEEN_SEMVER = 'BETWEEN_SEMVER';
52+
const IN_LIST_SEMVER = 'IN_LIST_SEMVER';
4253

4354
public static function factory($matcher)
4455
{
@@ -129,9 +140,34 @@ public static function factory($matcher)
129140
is_string($matcher['stringMatcherData']) ?
130141
$matcher['stringMatcherData'] : null;
131142
return new Regex($data, $negate, $attribute);
143+
case self::EQUAL_TO_SEMVER:
144+
$data = isset($matcher['stringMatcherData']) &&
145+
is_string($matcher['stringMatcherData']) ?
146+
$matcher['stringMatcherData'] : null;
147+
return new EqualToSemver($data, $negate, $attribute);
148+
case self::GREATER_THAN_OR_EQUAL_TO_SEMVER:
149+
$data = isset($matcher['stringMatcherData']) &&
150+
is_string($matcher['stringMatcherData']) ?
151+
$matcher['stringMatcherData'] : null;
152+
return new GreaterThanOrEqualToSemver($data, $negate, $attribute);
153+
case self::LESS_THAN_OR_EQUAL_TO_SEMVER:
154+
$data = isset($matcher['stringMatcherData']) &&
155+
is_string($matcher['stringMatcherData']) ?
156+
$matcher['stringMatcherData'] : null;
157+
return new LessThanOrEqualToSemver($data, $negate, $attribute);
158+
case self::BETWEEN_SEMVER:
159+
$data = (isset($matcher['betweenStringMatcherData']) &&
160+
is_array($matcher['betweenStringMatcherData']))
161+
? $matcher['betweenStringMatcherData'] : null;
162+
return new BetweenSemver($data, $negate, $attribute);
163+
case self::IN_LIST_SEMVER:
164+
$data = (isset($matcher['whitelistMatcherData']['whitelist']) &&
165+
is_array($matcher['whitelistMatcherData']['whitelist']))
166+
? $matcher['whitelistMatcherData']['whitelist'] : null;
167+
return new InListSemver($data, $negate, $attribute);
132168
// @codeCoverageIgnoreStart
133169
default:
134-
return null;
170+
throw new UnsupportedMatcherException("Unable to create matcher for matcher type: " . $matcherType);
135171
}
136172
// @codeCoverageIgnoreEnd
137173
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
<?php
2+
namespace SplitIO\Grammar\Condition\Matcher;
3+
4+
use SplitIO\Grammar\Condition\Matcher;
5+
use SplitIO\Grammar\Semver\Semver;
6+
use SplitIO\Grammar\Semver\SemverComparer;
7+
use SplitIO\Split as SplitApp;
8+
9+
class BetweenSemver extends AbstractMatcher
10+
{
11+
protected $startTarget = null;
12+
protected $endTarget = null;
13+
14+
public function __construct($data, $negate = false, $attribute = null)
15+
{
16+
parent::__construct(Matcher::BETWEEN_SEMVER, $negate, $attribute);
17+
18+
$this->startTarget = Semver::build($data['start']);
19+
$this->endTarget = Semver::build($data['end']);
20+
}
21+
22+
/**
23+
*
24+
* @param mixed $key
25+
*/
26+
protected function evalKey($key)
27+
{
28+
if ($key == null || !is_string($key) || $this->startTarget == null || $this->endTarget == null) {
29+
return false;
30+
}
31+
32+
$keySemver = Semver::build($key);
33+
if ($keySemver == null) {
34+
return false;
35+
}
36+
37+
$result = SemverComparer::do($keySemver, $this->startTarget) >= 0
38+
&& SemverComparer::do($keySemver, $this->endTarget) <= 0;
39+
40+
SplitApp::logger()->debug($this->startTarget->getVersion() . " <= "
41+
. $keySemver->getVersion() . " <= " . $this->endTarget->getVersion()
42+
. " | Result: " . $result);
43+
44+
return $result;
45+
}
46+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<?php
2+
namespace SplitIO\Grammar\Condition\Matcher;
3+
4+
use SplitIO\Grammar\Condition\Matcher;
5+
use SplitIO\Grammar\Semver\Semver;
6+
use SplitIO\Grammar\Semver\SemverComparer;
7+
use SplitIO\Split as SplitApp;
8+
9+
class EqualToSemver extends AbstractMatcher
10+
{
11+
private $toCompare;
12+
13+
public function __construct($toCompare, $negate = false, $attribute = null)
14+
{
15+
parent::__construct(Matcher::EQUAL_TO_SEMVER, $negate, $attribute);
16+
17+
$this->toCompare = Semver::build($toCompare);
18+
}
19+
20+
/**
21+
*
22+
* @param mixed $key
23+
*/
24+
protected function evalKey($key)
25+
{
26+
if ($key == null || $this->toCompare == null || !is_string($key)) {
27+
return false;
28+
}
29+
30+
$keySemver = Semver::build($key);
31+
if ($keySemver == null) {
32+
return false;
33+
}
34+
35+
$result = SemverComparer::equals($this->toCompare, $keySemver);
36+
37+
SplitApp::logger()->debug($this->toCompare->getVersion() . " == "
38+
. $keySemver->getVersion() . " | Result: " . $result);
39+
40+
return $result;
41+
}
42+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<?php
2+
namespace SplitIO\Grammar\Condition\Matcher;
3+
4+
use SplitIO\Grammar\Condition\Matcher;
5+
use SplitIO\Grammar\Semver\Semver;
6+
use SplitIO\Grammar\Semver\SemverComparer;
7+
use SplitIO\Split as SplitApp;
8+
9+
class GreaterThanOrEqualToSemver extends AbstractMatcher
10+
{
11+
private $target;
12+
13+
public function __construct($toCompare, $negate = false, $attribute = null)
14+
{
15+
parent::__construct(Matcher::GREATER_THAN_OR_EQUAL_TO_SEMVER, $negate, $attribute);
16+
17+
$this->target = Semver::build($toCompare);
18+
}
19+
20+
/**
21+
*
22+
* @param mixed $key
23+
*/
24+
protected function evalKey($key)
25+
{
26+
if ($key == null || $this->target == null || !is_string($key)) {
27+
return false;
28+
}
29+
30+
$keySemver = Semver::build($key);
31+
if ($keySemver == null) {
32+
return false;
33+
}
34+
35+
$result = SemverComparer::do($keySemver, $this->target) >= 0;
36+
37+
SplitApp::logger()->debug($this->target->getVersion() . " >= "
38+
. $keySemver->getVersion() . " | Result: " . $result);
39+
40+
return $result;
41+
}
42+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
<?php
2+
namespace SplitIO\Grammar\Condition\Matcher;
3+
4+
use SplitIO\Grammar\Condition\Matcher;
5+
use SplitIO\Grammar\Semver\Semver;
6+
use SplitIO\Grammar\Semver\SemverComparer;
7+
8+
class InListSemver extends AbstractMatcher
9+
{
10+
private $targetList;
11+
12+
public function __construct($targetList, $negate = false, $attribute = null)
13+
{
14+
$this->targetList = array();
15+
parent::__construct(Matcher::IN_LIST_SEMVER, $negate, $attribute);
16+
17+
if (is_array($targetList)) {
18+
foreach ($targetList as $item) {
19+
$toAdd = Semver::build($item);
20+
21+
if ($toAdd != null) {
22+
array_push($this->targetList, $toAdd);
23+
}
24+
}
25+
}
26+
}
27+
28+
/**
29+
*
30+
* @param mixed $key
31+
*/
32+
protected function evalKey($key)
33+
{
34+
if ($key == null || !is_string($key) || count($this->targetList) == 0) {
35+
return false;
36+
}
37+
38+
$keySemver = Semver::build($key);
39+
if ($keySemver == null) {
40+
return false;
41+
}
42+
43+
foreach ($this->targetList as $item) {
44+
if (SemverComparer::equals($keySemver, $item)) {
45+
return true;
46+
}
47+
}
48+
49+
return false;
50+
}
51+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<?php
2+
namespace SplitIO\Grammar\Condition\Matcher;
3+
4+
use SplitIO\Grammar\Condition\Matcher;
5+
use SplitIO\Grammar\Semver\Semver;
6+
use SplitIO\Grammar\Semver\SemverComparer;
7+
use SplitIO\Split as SplitApp;
8+
9+
class LessThanOrEqualToSemver extends AbstractMatcher
10+
{
11+
private $target;
12+
13+
public function __construct($toCompare, $negate = false, $attribute = null)
14+
{
15+
parent::__construct(Matcher::LESS_THAN_OR_EQUAL_TO_SEMVER, $negate, $attribute);
16+
17+
$this->target = Semver::build($toCompare);
18+
}
19+
20+
/**
21+
*
22+
* @param mixed $key
23+
*/
24+
protected function evalKey($key)
25+
{
26+
if ($key == null || $this->target == null || !is_string($key)) {
27+
return false;
28+
}
29+
30+
$keySemver = Semver::build($key);
31+
if ($keySemver == null) {
32+
return false;
33+
}
34+
35+
$result = SemverComparer::do($keySemver, $this->target) <= 0;
36+
37+
SplitApp::logger()->debug($this->target->getVersion() . " <= "
38+
. $keySemver->getVersion() . " | Result: " . $result);
39+
40+
return $result;
41+
}
42+
}

0 commit comments

Comments
 (0)