Skip to content

Semver implementation #236

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 30 commits into from
May 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
4968713
Allow symfony/yaml v7
jbreton Apr 15, 2024
2841fd1
unsupported matcher implementation
sanzmauro Apr 24, 2024
7e9aa55
fixed phpcs
sanzmauro Apr 24, 2024
a5ecd0d
fixed tests
sanzmauro Apr 24, 2024
bcc5b04
improved logs
sanzmauro Apr 24, 2024
7510a45
adding 8.3
sanzmauro Apr 24, 2024
6eccc46
Semver class implementation
sanzmauro Apr 29, 2024
6e96ee1
fixed linter
sanzmauro Apr 29, 2024
fbc0fd6
EqualToSemver Matcher implementation
sanzmauro Apr 29, 2024
45126c3
removing comment
sanzmauro Apr 29, 2024
b882519
fixed linter
sanzmauro Apr 29, 2024
ec55ac1
GreaterThanOrEqualToSemver Matcher implementation
sanzmauro Apr 29, 2024
6f0b33d
LessThanOrEqualToSemver Matcher implementation.
sanzmauro Apr 29, 2024
163f5f0
BetweenSemver Matcher implementation.
sanzmauro Apr 29, 2024
89f5500
InListSemver Matcher implementation.
sanzmauro Apr 29, 2024
12d23a6
polishing
sanzmauro Apr 29, 2024
a4990f7
Merge pull request #235 from splitio/semver-polishing
sanzmauro May 3, 2024
f492348
Merge pull request #234 from splitio/sdks-8328-inlist
sanzmauro May 3, 2024
2a11f15
Merge pull request #233 from splitio/sdks-8329-between
sanzmauro May 3, 2024
46ea641
Merge pull request #232 from splitio/sdks-8326-less
sanzmauro May 3, 2024
cf54135
Merge pull request #231 from splitio/sdks-8325-greater
sanzmauro May 3, 2024
b0a6045
Merge pull request #230 from splitio/sdks-8324-equalto
sanzmauro May 3, 2024
f606df6
Merge pull request #229 from splitio/sdks-8322-semver
sanzmauro May 3, 2024
3df278b
Merge pull request #228 from splitio/sdks-8291-unsupported-matcher
sanzmauro May 3, 2024
f930afa
fixing betweenSemverMatcher
sanzmauro May 6, 2024
6600ab7
Merge pull request #227 from jbreton/symfony-yaml-v7
sanzmauro May 14, 2024
3e2e413
updated version
sanzmauro May 14, 2024
a86d003
Merge branch 'sdks-8242-semver-imp' of github.com:splitio/php-client …
sanzmauro May 14, 2024
25a7b42
Added integration test
sanzmauro May 14, 2024
9760831
update changes.txt
sanzmauro May 14, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ jobs:
- '8.0'
- '8.1'
- '8.2'
- '8.3'
steps:
- name: Checkout code
uses: actions/checkout@v3
Expand Down
5 changes: 5 additions & 0 deletions CHANGES.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
7.3.0 (May 14, 2024)
- Added support for targeting rules based on semantic versions (https://semver.org/).
- Added the logic to handle correctly when the SDK receives an unsupported Matcher type.
- Updated dependencies to allow `symfony/yaml` 7.

7.2.1 (March 6, 2024)
- Fix error on duplicated file flagSetsValidator.

Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
"php": ">=7.3",
"psr/log": "1 - 3",
"predis/predis": "^2.0",
"symfony/yaml": "^5.3|^6.0"
"symfony/yaml": "^5.3|^6.0|^7.0"
},

"require-dev": {
Expand Down
7 changes: 7 additions & 0 deletions src/SplitIO/Exception/SemverParseException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?php
namespace SplitIO\Exception;

class SemverParseException extends \LogicException
{

}
7 changes: 7 additions & 0 deletions src/SplitIO/Exception/UnsupportedMatcherException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?php
namespace SplitIO\Exception;

class UnsupportedMatcherException extends \LogicException
{

}
33 changes: 30 additions & 3 deletions src/SplitIO/Grammar/Condition.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,17 @@
namespace SplitIO\Grammar;

use SplitIO\Exception\InvalidMatcherException;
use SplitIO\Split as SplitApp;
use SplitIO\Grammar\Condition\Combiner\AndCombiner;
use SplitIO\Grammar\Condition\Combiner\CombinerEnum;
use SplitIO\Grammar\Condition\Combiner\Factor\NotFactor;
use SplitIO\Grammar\Condition\ConditionTypeEnum;
use SplitIO\Grammar\Condition\Matcher;
use SplitIO\Grammar\Condition\Partition;
use SplitIO\Grammar\Condition\Matcher\AbstractMatcher;
use SplitIO\Grammar\Condition\ConditionTypeEnum;
use SplitIO\Grammar\Condition\Matcher\Dependency;
use SplitIO\Grammar\Condition\Partition;
use SplitIO\Grammar\Condition\Partition\TreatmentEnum;
use SplitIO\Sdk\Impressions\ImpressionLabel;
use SplitIO\Split as SplitApp;

class Condition
{
Expand Down Expand Up @@ -115,6 +117,31 @@ public function match($key, array $attributes = null, $bucketingKey = null)
return false;
}

public static function getDefaultCondition()
{
return new Condition(array(
'conditionType' => ConditionTypeEnum::WHITELIST,
'matcherGroup' => array(
'combiner' => CombinerEnum::_AND,
'matchers' => array(
array(
'matcherType' => Matcher::ALL_KEYS,
'negate' => false,
'userDefinedSegmentMatcherData' => null,
'whitelistMatcherData' => null
)
)
),
'partitions' => array(
array(
'treatment' => TreatmentEnum::CONTROL,
'size' => 100
)
),
'label' => ImpressionLabel::UNSUPPORTED_MATCHER
));
}

/**
* @return array|null
*/
Expand Down
38 changes: 37 additions & 1 deletion src/SplitIO/Grammar/Condition/Matcher.php
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
<?php
namespace SplitIO\Grammar\Condition;

use SplitIO\Exception\UnsupportedMatcherException;
use SplitIO\Grammar\Condition\Matcher\All;
use SplitIO\Grammar\Condition\Matcher\Between;
use SplitIO\Grammar\Condition\Matcher\BetweenSemver;
use SplitIO\Grammar\Condition\Matcher\EqualTo;
use SplitIO\Grammar\Condition\Matcher\EqualToSemver;
use SplitIO\Grammar\Condition\Matcher\GreaterThanOrEqualTo;
use SplitIO\Grammar\Condition\Matcher\GreaterThanOrEqualToSemver;
use SplitIO\Grammar\Condition\Matcher\InListSemver;
use SplitIO\Grammar\Condition\Matcher\LessThanOrEqualTo;
use SplitIO\Grammar\Condition\Matcher\LessThanOrEqualToSemver;
use SplitIO\Grammar\Condition\Matcher\Segment;
use SplitIO\Grammar\Condition\Matcher\Whitelist;
use SplitIO\Grammar\Condition\Matcher\StartsWith;
Expand Down Expand Up @@ -39,6 +45,11 @@ class Matcher
const IN_SPLIT_TREATMENT = 'IN_SPLIT_TREATMENT';
const EQUAL_TO_BOOLEAN = 'EQUAL_TO_BOOLEAN';
const MATCHES_STRING = 'MATCHES_STRING';
const EQUAL_TO_SEMVER = 'EQUAL_TO_SEMVER';
const GREATER_THAN_OR_EQUAL_TO_SEMVER = 'GREATER_THAN_OR_EQUAL_TO_SEMVER';
const LESS_THAN_OR_EQUAL_TO_SEMVER = 'LESS_THAN_OR_EQUAL_TO_SEMVER';
const BETWEEN_SEMVER = 'BETWEEN_SEMVER';
const IN_LIST_SEMVER = 'IN_LIST_SEMVER';

public static function factory($matcher)
{
Expand Down Expand Up @@ -129,9 +140,34 @@ public static function factory($matcher)
is_string($matcher['stringMatcherData']) ?
$matcher['stringMatcherData'] : null;
return new Regex($data, $negate, $attribute);
case self::EQUAL_TO_SEMVER:
$data = isset($matcher['stringMatcherData']) &&
is_string($matcher['stringMatcherData']) ?
$matcher['stringMatcherData'] : null;
return new EqualToSemver($data, $negate, $attribute);
case self::GREATER_THAN_OR_EQUAL_TO_SEMVER:
$data = isset($matcher['stringMatcherData']) &&
is_string($matcher['stringMatcherData']) ?
$matcher['stringMatcherData'] : null;
return new GreaterThanOrEqualToSemver($data, $negate, $attribute);
case self::LESS_THAN_OR_EQUAL_TO_SEMVER:
$data = isset($matcher['stringMatcherData']) &&
is_string($matcher['stringMatcherData']) ?
$matcher['stringMatcherData'] : null;
return new LessThanOrEqualToSemver($data, $negate, $attribute);
case self::BETWEEN_SEMVER:
$data = (isset($matcher['betweenStringMatcherData']) &&
is_array($matcher['betweenStringMatcherData']))
? $matcher['betweenStringMatcherData'] : null;
return new BetweenSemver($data, $negate, $attribute);
case self::IN_LIST_SEMVER:
$data = (isset($matcher['whitelistMatcherData']['whitelist']) &&
is_array($matcher['whitelistMatcherData']['whitelist']))
? $matcher['whitelistMatcherData']['whitelist'] : null;
return new InListSemver($data, $negate, $attribute);
// @codeCoverageIgnoreStart
default:
return null;
throw new UnsupportedMatcherException("Unable to create matcher for matcher type: " . $matcherType);
}
// @codeCoverageIgnoreEnd
}
Expand Down
48 changes: 48 additions & 0 deletions src/SplitIO/Grammar/Condition/Matcher/BetweenSemver.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<?php
namespace SplitIO\Grammar\Condition\Matcher;

use SplitIO\Grammar\Condition\Matcher;
use SplitIO\Grammar\Semver\Semver;
use SplitIO\Grammar\Semver\SemverComparer;
use SplitIO\Split as SplitApp;

class BetweenSemver extends AbstractMatcher
{
protected $startTarget = null;
protected $endTarget = null;

public function __construct($data, $negate = false, $attribute = null)
{
parent::__construct(Matcher::BETWEEN_SEMVER, $negate, $attribute);

if ($data != null) {
$this->startTarget = Semver::build($data['start']);
$this->endTarget = Semver::build($data['end']);
}
}

/**
*
* @param mixed $key
*/
protected function evalKey($key)
{
if ($key == null || !is_string($key) || $this->startTarget == null || $this->endTarget == null) {
return false;
}

$keySemver = Semver::build($key);
if ($keySemver == null) {
return false;
}

$result = SemverComparer::do($keySemver, $this->startTarget) >= 0
&& SemverComparer::do($keySemver, $this->endTarget) <= 0;

SplitApp::logger()->debug($this->startTarget->getVersion() . " <= "
. $keySemver->getVersion() . " <= " . $this->endTarget->getVersion()
. " | Result: " . $result);

return $result;
}
}
42 changes: 42 additions & 0 deletions src/SplitIO/Grammar/Condition/Matcher/EqualToSemver.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php
namespace SplitIO\Grammar\Condition\Matcher;

use SplitIO\Grammar\Condition\Matcher;
use SplitIO\Grammar\Semver\Semver;
use SplitIO\Grammar\Semver\SemverComparer;
use SplitIO\Split as SplitApp;

class EqualToSemver extends AbstractMatcher
{
private $toCompare;

public function __construct($toCompare, $negate = false, $attribute = null)
{
parent::__construct(Matcher::EQUAL_TO_SEMVER, $negate, $attribute);

$this->toCompare = Semver::build($toCompare);
}

/**
*
* @param mixed $key
*/
protected function evalKey($key)
{
if ($key == null || $this->toCompare == null || !is_string($key)) {
return false;
}

$keySemver = Semver::build($key);
if ($keySemver == null) {
return false;
}

$result = SemverComparer::equals($this->toCompare, $keySemver);

SplitApp::logger()->debug($this->toCompare->getVersion() . " == "
. $keySemver->getVersion() . " | Result: " . $result);

return $result;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php
namespace SplitIO\Grammar\Condition\Matcher;

use SplitIO\Grammar\Condition\Matcher;
use SplitIO\Grammar\Semver\Semver;
use SplitIO\Grammar\Semver\SemverComparer;
use SplitIO\Split as SplitApp;

class GreaterThanOrEqualToSemver extends AbstractMatcher
{
private $target;

public function __construct($toCompare, $negate = false, $attribute = null)
{
parent::__construct(Matcher::GREATER_THAN_OR_EQUAL_TO_SEMVER, $negate, $attribute);

$this->target = Semver::build($toCompare);
}

/**
*
* @param mixed $key
*/
protected function evalKey($key)
{
if ($key == null || $this->target == null || !is_string($key)) {
return false;
}

$keySemver = Semver::build($key);
if ($keySemver == null) {
return false;
}

$result = SemverComparer::do($keySemver, $this->target) >= 0;

SplitApp::logger()->debug($this->target->getVersion() . " >= "
. $keySemver->getVersion() . " | Result: " . $result);

return $result;
}
}
51 changes: 51 additions & 0 deletions src/SplitIO/Grammar/Condition/Matcher/InListSemver.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?php
namespace SplitIO\Grammar\Condition\Matcher;

use SplitIO\Grammar\Condition\Matcher;
use SplitIO\Grammar\Semver\Semver;
use SplitIO\Grammar\Semver\SemverComparer;

class InListSemver extends AbstractMatcher
{
private $targetList;

public function __construct($targetList, $negate = false, $attribute = null)
{
$this->targetList = array();
parent::__construct(Matcher::IN_LIST_SEMVER, $negate, $attribute);

if (is_array($targetList)) {
foreach ($targetList as $item) {
$toAdd = Semver::build($item);

if ($toAdd != null) {
array_push($this->targetList, $toAdd);
}
}
}
}

/**
*
* @param mixed $key
*/
protected function evalKey($key)
{
if ($key == null || !is_string($key) || count($this->targetList) == 0) {
return false;
}

$keySemver = Semver::build($key);
if ($keySemver == null) {
return false;
}

foreach ($this->targetList as $item) {
if (SemverComparer::equals($keySemver, $item)) {
return true;
}
}

return false;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php
namespace SplitIO\Grammar\Condition\Matcher;

use SplitIO\Grammar\Condition\Matcher;
use SplitIO\Grammar\Semver\Semver;
use SplitIO\Grammar\Semver\SemverComparer;
use SplitIO\Split as SplitApp;

class LessThanOrEqualToSemver extends AbstractMatcher
{
private $target;

public function __construct($toCompare, $negate = false, $attribute = null)
{
parent::__construct(Matcher::LESS_THAN_OR_EQUAL_TO_SEMVER, $negate, $attribute);

$this->target = Semver::build($toCompare);
}

/**
*
* @param mixed $key
*/
protected function evalKey($key)
{
if ($key == null || $this->target == null || !is_string($key)) {
return false;
}

$keySemver = Semver::build($key);
if ($keySemver == null) {
return false;
}

$result = SemverComparer::do($keySemver, $this->target) <= 0;

SplitApp::logger()->debug($this->target->getVersion() . " <= "
. $keySemver->getVersion() . " | Result: " . $result);

return $result;
}
}
Loading
Loading