-
Notifications
You must be signed in to change notification settings - Fork 14
/
Copy pathDefaultVariantHandler.php
executable file
·113 lines (102 loc) · 3.27 KB
/
DefaultVariantHandler.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
<?php
namespace Unleash\Client\Variant;
use JetBrains\PhpStorm\Pure;
use Override;
use Unleash\Client\Configuration\Context;
use Unleash\Client\DTO\DefaultVariant;
use Unleash\Client\DTO\Variant;
use Unleash\Client\Enum\Stickiness;
use Unleash\Client\Stickiness\StickinessCalculator;
final class DefaultVariantHandler implements VariantHandler
{
/**
* @readonly
* @var \Unleash\Client\Stickiness\StickinessCalculator
*/
private $stickinessCalculator;
/**
* @var int
*/
private const VARIANT_HASH_SEED = 86028157;
public function __construct(StickinessCalculator $stickinessCalculator)
{
$this->stickinessCalculator = $stickinessCalculator;
}
public function getDefaultVariant(): Variant
{
return new DefaultVariant(
'disabled',
false
);
}
/**
* @param array<Variant> $variants
*/
public function selectVariant(array $variants, string $groupId, Context $context): ?Variant
{
$totalWeight = 0;
foreach ($variants as $variant) {
$totalWeight += $variant->getWeight();
}
if ($totalWeight <= 0) {
return null;
}
if ($overridden = $this->findOverriddenVariant($variants, $context)) {
return $overridden;
}
$stickiness = $this->calculateStickiness($variants, $groupId, $context, $totalWeight);
$counter = 0;
foreach ($variants as $variant) {
if ($variant->getWeight() <= 0) {
continue;
}
$counter += $variant->getWeight();
if ($counter >= $stickiness) {
return $variant;
}
}
// while this is in theory possible to happen, it really cannot happen unless the Unleash server is misconfigured
// and in that case there are bigger problems than missing code coverage
// @codeCoverageIgnoreStart
return null;
// @codeCoverageIgnoreEnd
}
/**
* @param array<Variant> $variants
*/
private function findOverriddenVariant(array $variants, Context $context): ?Variant
{
foreach ($variants as $variant) {
foreach ($variant->getOverrides() as $override) {
if ($context->hasMatchingFieldValue($override->getField(), $override->getValues())) {
return $variant;
}
}
}
return null;
}
/**
* @param array<Variant> $variants
*/
private function calculateStickiness(
array $variants,
string $groupId,
Context $context,
int $totalWeight
): int {
$stickiness = $variants[0]->getStickiness();
if ($stickiness !== Stickiness::DEFAULT) {
$seed = $context->findContextValue($stickiness) ?? $this->randomString();
} else {
$seed = $context->getCurrentUserId()
?? $context->getSessionId()
?? $context->getIpAddress()
?? $this->randomString();
}
return $this->stickinessCalculator->calculate($seed, $groupId, $totalWeight, $seed = DefaultVariantHandler::VARIANT_HASH_SEED);
}
private function randomString(): string
{
return (string) random_int(1, 100000);
}
}