Skip to content

Commit b475838

Browse files
authored
prepare 3.4.0 release (#109)
1 parent 985ffb2 commit b475838

14 files changed

+1045
-205
lines changed

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,13 @@
22

33
All notable changes to the LaunchDarkly PHP SDK will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org).
44

5+
## [3.4.0] - 2018-09-04
6+
### Added:
7+
- The new `LDClient` method `variationDetail` allows you to evaluate a feature flag (using the same parameters as you would for `variation`) and receive more information about how the value was calculated. This information is returned in an object that contains both the result value and a "reason" object which will tell you, for instance, if the user was individually targeted for the flag or was matched by one of the flag's rules, or if the flag returned the default value due to an error.
8+
9+
### Fixed:
10+
- When evaluating a prerequisite feature flag, the analytics event for the evaluation did not include the result value if the prerequisite flag was off.
11+
512
## [3.3.0] - 2018-08-27
613
### Added:
714
- The new `LDClient` method `allFlagsState()` should be used instead of `allFlags()` if you are passing flag data to the front end for use with the JavaScript SDK. It preserves some flag metadata that the front end requires in order to send analytics events correctly. Versions 2.5.0 and above of the JavaScript SDK are able to use this metadata, but the output of `allFlagsState()` will still work with older versions.

VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
3.3.0
1+
3.4.0

src/LaunchDarkly/EvalResult.php

Lines changed: 8 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,37 +4,28 @@
44

55
class EvalResult
66
{
7-
private $_variation = null;
8-
private $_value = null;
7+
/** @var EvaluationDetail */
8+
private $_detail = null;
99
/** @var array */
1010
private $_prerequisiteEvents = [];
1111

1212
/**
1313
* EvalResult constructor.
14-
* @param null $value
14+
* @param EvaluationDetail $detail
1515
* @param array $prerequisiteEvents
1616
*/
17-
public function __construct($variation, $value, array $prerequisiteEvents)
17+
public function __construct($detail, array $prerequisiteEvents)
1818
{
19-
$this->_variation = $variation;
20-
$this->_value = $value;
19+
$this->_detail = $detail;
2120
$this->_prerequisiteEvents = $prerequisiteEvents;
2221
}
2322

2423
/**
25-
* @return int | null
24+
* @return EvaluationDetail
2625
*/
27-
public function getVariation()
26+
public function getDetail()
2827
{
29-
return $this->_variation;
30-
}
31-
32-
/**
33-
* @return null
34-
*/
35-
public function getValue()
36-
{
37-
return $this->_value;
28+
return $this->_detail;
3829
}
3930

4031
/**

src/LaunchDarkly/EvaluationDetail.php

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
<?php
2+
3+
namespace LaunchDarkly;
4+
5+
/**
6+
* An object returned by LDClient.variationDetail(), combining the result of a flag evaluation with
7+
* an explanation of how it was calculated.
8+
*/
9+
class EvaluationDetail
10+
{
11+
private $_variationIndex = null;
12+
private $_value = null;
13+
private $_reason = null;
14+
15+
/**
16+
* EvaluationDetail constructor.
17+
* @param mixed $value the value of the flag variation
18+
* @param int|null $variationIndex the index of the flag variation, or null if it was the default value
19+
* @param EvaluationReason $reason evaluation reason properties
20+
*/
21+
public function __construct($value, $variationIndex, $reason = null)
22+
{
23+
$this->_value = $value;
24+
$this->_variationIndex = $variationIndex;
25+
$this->_reason = $reason;
26+
}
27+
28+
/**
29+
* Returns the value of the flag variation for the user.
30+
*
31+
* @return mixed
32+
*/
33+
public function getValue()
34+
{
35+
return $this->_value;
36+
}
37+
38+
/**
39+
* Returns the index of the flag variation for the user, e.g. 0 for the first variation -
40+
* or null if it was the default value.
41+
*
42+
* @return int | null
43+
*/
44+
public function getVariationIndex()
45+
{
46+
return $this->_variationIndex;
47+
}
48+
49+
/**
50+
* Returns information about how the flag value was calculated.
51+
*
52+
* @return EvaluationReason
53+
*/
54+
public function getReason()
55+
{
56+
return $this->_reason;
57+
}
58+
59+
/**
60+
* Returns true if the flag evaluated to the default value, rather than one of its variations.
61+
*
62+
* @return bool
63+
*/
64+
public function isDefaultValue()
65+
{
66+
return ($this->_variationIndex === null);
67+
}
68+
}

src/LaunchDarkly/EvaluationReason.php

Lines changed: 222 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,222 @@
1+
<?php
2+
3+
namespace LaunchDarkly;
4+
5+
/**
6+
* Describes the reason that a flag evaluation produced a particular value. This is part of
7+
* the EvaluationDetail object returned by LDClient.variationDetail().
8+
*/
9+
class EvaluationReason implements \JsonSerializable
10+
{
11+
/**
12+
* A possible value for getKind(): indicates that the flag was off and therefore returned
13+
* its configured off value.
14+
*/
15+
const OFF = 'OFF';
16+
/**
17+
* A possible value for getKind(): indicates that the flag was on but the user did not
18+
* match any targets or rules.
19+
*/
20+
const FALLTHROUGH = 'FALLTHROUGH';
21+
/**
22+
* A possible value for getKind(): indicates that the user key was specifically targeted
23+
* for this flag.
24+
*/
25+
const TARGET_MATCH = 'TARGET_MATCH';
26+
/**
27+
* A possible value for getKind(): indicates that the user matched one of the flag's rules.
28+
*/
29+
const RULE_MATCH = 'RULE_MATCH';
30+
/**
31+
* A possible value for getKind(): indicates that the flag was considered off because it
32+
* had at least one prerequisite flag that either was off or did not return the desired variation.
33+
*/
34+
const PREREQUISITE_FAILED = 'PREREQUISITE_FAILED';
35+
/**
36+
* A possible value for getKind(): indicates that the flag could not be evaluated, e.g.
37+
* because it does not exist or due to an unexpected error.
38+
*/
39+
const ERROR = 'ERROR';
40+
41+
/**
42+
* A possible value for getErrorKind(): indicates that the caller tried to evaluate a flag
43+
* before the client had successfully initialized.
44+
*/
45+
const CLIENT_NOT_READY_ERROR = 'CLIENT_NOT_READY';
46+
47+
/**
48+
* A possible value for getErrorKind(): indicates that the caller provided a flag key that
49+
* did not match any known flag.
50+
*/
51+
const FLAG_NOT_FOUND_ERROR = 'FLAG_NOT_FOUND';
52+
53+
/**
54+
* A possible value for getErrorKind(): indicates that there was an internal inconsistency
55+
* in the flag data, e.g. a rule specified a nonexistent variation. An error message will
56+
* always be logged in this case.
57+
*/
58+
const MALFORMED_FLAG_ERROR = 'MALFORMED_FLAG';
59+
60+
/**
61+
* A possible value for getErrorKind(): indicates that the caller passed null for the user
62+
* parameter, or the user lacked a key.
63+
*/
64+
const USER_NOT_SPECIFIED_ERROR = 'USER_NOT_SPECIFIED';
65+
66+
/**
67+
* A possible value for getErrorKind(): indicates that an unexpected exception stopped flag
68+
* evaluation.
69+
*/
70+
const EXCEPTION_ERROR = 'EXCEPTION';
71+
72+
private $_kind;
73+
private $_errorKind;
74+
private $_ruleIndex;
75+
private $_ruleId;
76+
private $_prerequisiteKey;
77+
78+
/**
79+
* Creates a new instance of the OFF reason.
80+
*/
81+
public static function off()
82+
{
83+
return new EvaluationReason(self::OFF);
84+
}
85+
86+
/**
87+
* Creates a new instance of the FALLTHROUGH reason.
88+
*/
89+
public static function fallthrough()
90+
{
91+
return new EvaluationReason(self::FALLTHROUGH);
92+
}
93+
94+
/**
95+
* Creates a new instance of the TARGET_MATCH reason.
96+
*/
97+
public static function targetMatch()
98+
{
99+
return new EvaluationReason(self::TARGET_MATCH);
100+
}
101+
102+
/**
103+
* Creates a new instance of the RULE_MATCH reason.
104+
*/
105+
public static function ruleMatch($ruleIndex, $ruleId)
106+
{
107+
return new EvaluationReason(self::RULE_MATCH, null, $ruleIndex, $ruleId);
108+
}
109+
110+
/**
111+
* Creates a new instance of the PREREQUISITE_FAILED reason.
112+
*/
113+
public static function prerequisiteFailed($prerequisiteKey)
114+
{
115+
return new EvaluationReason(self::PREREQUISITE_FAILED, null, null, null, $prerequisiteKey);
116+
}
117+
118+
/**
119+
* Creates a new instance of the ERROR reason.
120+
*/
121+
public static function error($errorKind)
122+
{
123+
return new EvaluationReason(self::ERROR, $errorKind);
124+
}
125+
126+
private function __construct($kind, $errorKind = null, $ruleIndex = null, $ruleId = null, $prerequisiteKey = null)
127+
{
128+
$this->_kind = $kind;
129+
$this->_errorKind = $errorKind;
130+
$this->_ruleIndex = $ruleIndex;
131+
$this->_ruleId = $ruleId;
132+
$this->_prerequisiteKey = $prerequisiteKey;
133+
}
134+
135+
/**
136+
* Returns a constant indicating the general category of the reason, such as OFF.
137+
* @return string
138+
*/
139+
public function getKind()
140+
{
141+
return $this->_kind;
142+
}
143+
144+
/**
145+
* Returns a constant indicating the nature of the error, if getKind() is OFF. Otherwise
146+
* returns null.
147+
* @return string|null
148+
*/
149+
public function getErrorKind()
150+
{
151+
return $this->_errorKind;
152+
}
153+
154+
/**
155+
* Returns the positional index of the rule that was matched (0 for the first), if getKind()
156+
* is RULE_MATCH. Otherwise returns null.
157+
* @return int|null
158+
*/
159+
public function getRuleIndex()
160+
{
161+
return $this->_ruleIndex;
162+
}
163+
164+
/**
165+
* Returns the unique identifier of the rule that was matched, if getKind() is RULE_MATCH.
166+
* Otherwise returns null.
167+
* @return string|null
168+
*/
169+
public function getRuleId()
170+
{
171+
return $this->_ruleId;
172+
}
173+
174+
/**
175+
* Returns the key of the prerequisite feature flag that failed, if getKind() is
176+
* PREREQUISITE_FAILED. Otherwise returns null.
177+
* @return string|null
178+
*/
179+
public function getPrerequisiteKey()
180+
{
181+
return $this->_prerequisiteKey;
182+
}
183+
184+
/**
185+
* Returns a simple string representation of this object.
186+
*/
187+
public function __toString()
188+
{
189+
switch ($this->_kind) {
190+
case self::RULE_MATCH:
191+
return $this->_kind . '(' . $this->_ruleIndex . ',' . $this->_ruleId . ')';
192+
case self::PREREQUISITE_FAILED:
193+
return $this->_kind . '(' . $this->_prerequisiteKey . ')';
194+
case self::ERROR:
195+
return $this->_kind . '(' . $this->_errorKind . ')';
196+
default:
197+
return $this->_kind;
198+
}
199+
}
200+
201+
/**
202+
* Returns a JSON representation of this object. This method is used automatically
203+
* if you call json_encode().
204+
*/
205+
public function jsonSerialize()
206+
{
207+
$ret = array('kind' => $this->_kind);
208+
if ($this->_errorKind !== null) {
209+
$ret['errorKind'] = $this->_errorKind;
210+
}
211+
if ($this->_ruleIndex !== null) {
212+
$ret['ruleIndex'] = $this->_ruleIndex;
213+
}
214+
if ($this->_ruleId !== null) {
215+
$ret['ruleId'] = $this->_ruleId;
216+
}
217+
if ($this->_prerequisiteKey !== null) {
218+
$ret['prerequisiteKey'] = $this->_prerequisiteKey;
219+
}
220+
return $ret;
221+
}
222+
}

0 commit comments

Comments
 (0)