Skip to content

Commit 2e27873

Browse files
Revert "feat (audience match types): Update audience evaluator and project config for new audience match types (#145)"
This reverts commit d617d18.
1 parent d617d18 commit 2e27873

13 files changed

+153
-576
lines changed

src/Optimizely/ProjectConfig.php

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -214,15 +214,13 @@ public function __construct($datafile, $logger, $errorHandler)
214214
$events = $config['events'] ?: [];
215215
$attributes = $config['attributes'] ?: [];
216216
$audiences = $config['audiences'] ?: [];
217-
$typedAudiences = isset($config['typedAudiences']) ? $config['typedAudiences']: [];
218217
$rollouts = isset($config['rollouts']) ? $config['rollouts'] : [];
219218
$featureFlags = isset($config['featureFlags']) ? $config['featureFlags']: [];
220219

221220
$this->_groupIdMap = ConfigParser::generateMap($groups, 'id', Group::class);
222221
$this->_experimentKeyMap = ConfigParser::generateMap($experiments, 'key', Experiment::class);
223222
$this->_eventKeyMap = ConfigParser::generateMap($events, 'key', Event::class);
224223
$this->_attributeKeyMap = ConfigParser::generateMap($attributes, 'key', Attribute::class);
225-
$typedAudienceIdMap = ConfigParser::generateMap($typedAudiences, 'id', Audience::class);
226224
$this->_audienceIdMap = ConfigParser::generateMap($audiences, 'id', Audience::class);
227225
$this->_rollouts = ConfigParser::generateMap($rollouts, null, Rollout::class);
228226
$this->_featureFlags = ConfigParser::generateMap($featureFlags, null, FeatureFlag::class);
@@ -251,19 +249,12 @@ public function __construct($datafile, $logger, $errorHandler)
251249
}
252250
}
253251

252+
$conditionDecoder = new ConditionDecoder();
254253
foreach (array_values($this->_audienceIdMap) as $audience) {
255-
$audience->setConditionsList(json_decode($audience->getConditions(), true));
254+
$conditionDecoder->deserializeAudienceConditions($audience->getConditions());
255+
$audience->setConditionsList($conditionDecoder->getConditionsList());
256256
}
257257

258-
// Conditions in typedAudiences are not expected to be string-encoded so they don't need
259-
// to be decoded unlike audiences.
260-
foreach (array_values($typedAudienceIdMap) as $typedAudience) {
261-
$typedAudience->setConditionsList($typedAudience->getConditions());
262-
}
263-
264-
// Overwrite audiences by typedAudiences.
265-
$this->_audienceIdMap = array_replace($this->_audienceIdMap, $typedAudienceIdMap);
266-
267258
$rolloutVariationIdMap = [];
268259
$rolloutVariationKeyMap = [];
269260
foreach ($this->_rollouts as $rollout) {
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<?php
2+
/**
3+
* Copyright 2016, Optimizely
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
namespace Optimizely\Utils;
19+
20+
class ConditionDecoder
21+
{
22+
/**
23+
* @var array JSON decoded audience conditions.
24+
*/
25+
private $_conditionsList;
26+
27+
/**
28+
* Deserialize audience conditions into a list of structure and conditions.
29+
*
30+
* @param $conditions string Audience conditions.
31+
*/
32+
public function deserializeAudienceConditions($conditions)
33+
{
34+
$this->_conditionsList = json_decode($conditions);
35+
}
36+
37+
/**
38+
* @return array JSON decoded audience conditions.
39+
*/
40+
public function getConditionsList()
41+
{
42+
return $this->_conditionsList;
43+
}
44+
}

src/Optimizely/Utils/ConditionTreeEvaluator.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ protected function notEvaluator(array $condition, callable $leafEvaluator)
140140
*/
141141
public function evaluate($conditions, callable $leafEvaluator)
142142
{
143-
if (!Validator::doesArrayContainOnlyStringKeys($conditions)) {
143+
if (is_array($conditions)) {
144144

145145
if(in_array($conditions[0], $this->getOperators())) {
146146
$operator = array_shift($conditions);

src/Optimizely/Utils/CustomAttributeConditionEvaluator.php

Lines changed: 12 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -44,21 +44,6 @@ public function __construct(array $userAttributes)
4444
$this->userAttributes = $userAttributes;
4545
}
4646

47-
/**
48-
* Sets null for missing keys in a leaf condition.
49-
*
50-
* @param array $leafCondition The leaf condition node of an audience.
51-
*/
52-
protected function setNullForMissingKeys(array $leafCondition)
53-
{
54-
$keys = ['type', 'match', 'value'];
55-
foreach($keys as $key) {
56-
$leafCondition[$key] = isset($leafCondition[$key]) ? $leafCondition[$key]: null;
57-
}
58-
59-
return $leafCondition;
60-
}
61-
6247
/**
6348
* Gets the supported match types for condition evaluation.
6449
*
@@ -118,8 +103,8 @@ protected function isValueValidForExactConditions($value)
118103
*/
119104
protected function exactEvaluator($condition)
120105
{
121-
$conditionName = $condition['name'];
122-
$conditionValue = $condition['value'];
106+
$conditionName = $condition->{'name'};
107+
$conditionValue = $condition->{'value'};
123108
$userValue = isset($this->userAttributes[$conditionName]) ? $this->userAttributes[$conditionName]: null;
124109

125110
if(!$this->isValueValidForExactConditions($userValue) ||
@@ -143,7 +128,7 @@ protected function exactEvaluator($condition)
143128
*/
144129
protected function existsEvaluator($condition)
145130
{
146-
$conditionName = $condition['name'];
131+
$conditionName = $condition->{'name'};
147132
return isset($this->userAttributes[$conditionName]);
148133
}
149134

@@ -159,8 +144,8 @@ protected function existsEvaluator($condition)
159144
*/
160145
protected function greaterThanEvaluator($condition)
161146
{
162-
$conditionName = $condition['name'];
163-
$conditionValue = $condition['value'];
147+
$conditionName = $condition->{'name'};
148+
$conditionValue = $condition->{'value'};
164149
$userValue = isset($this->userAttributes[$conditionName]) ? $this->userAttributes[$conditionName]: null;
165150

166151
if(!Validator::isFiniteNumber($userValue) || !Validator::isFiniteNumber($conditionValue)) {
@@ -182,8 +167,8 @@ protected function greaterThanEvaluator($condition)
182167
*/
183168
protected function lessThanEvaluator($condition)
184169
{
185-
$conditionName = $condition['name'];
186-
$conditionValue = $condition['value'];
170+
$conditionName = $condition->{'name'};
171+
$conditionValue = $condition->{'value'};
187172
$userValue = isset($this->userAttributes[$conditionName]) ? $this->userAttributes[$conditionName]: null;
188173

189174
if(!Validator::isFiniteNumber($userValue) || !Validator::isFiniteNumber($conditionValue)) {
@@ -205,8 +190,8 @@ protected function lessThanEvaluator($condition)
205190
*/
206191
protected function substringEvaluator($condition)
207192
{
208-
$conditionName = $condition['name'];
209-
$conditionValue = $condition['value'];
193+
$conditionName = $condition->{'name'};
194+
$conditionValue = $condition->{'value'};
210195
$userValue = isset($this->userAttributes[$conditionName]) ? $this->userAttributes[$conditionName]: null;
211196

212197
if(!is_string($userValue) || !is_string($conditionValue)) {
@@ -226,16 +211,14 @@ protected function substringEvaluator($condition)
226211
*/
227212
public function evaluate($leafCondition)
228213
{
229-
$leafCondition = $this->setNullForMissingKeys($leafCondition);
230-
231-
if($leafCondition['type'] !== self::CUSTOM_ATTRIBUTE_CONDITION_TYPE) {
214+
if($leafCondition->{'type'} !== self::CUSTOM_ATTRIBUTE_CONDITION_TYPE) {
232215
return null;
233216
}
234217

235-
if(($leafCondition['match']) === null) {
218+
if(!isset($leafCondition->{'match'})) {
236219
$conditionMatch = self::EXACT_MATCH_TYPE;
237220
} else {
238-
$conditionMatch = $leafCondition['match'];
221+
$conditionMatch = $leafCondition->{'match'};
239222
}
240223

241224
if(!in_array($conditionMatch, $this->getMatchTypes())) {

src/Optimizely/Utils/Validator.php

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -111,8 +111,9 @@ public static function isUserInExperiment($config, $experiment, $userAttributes)
111111
return true;
112112
}
113113

114-
if ($userAttributes == null) {
115-
$userAttributes = [];
114+
// Return false if there is audience, but no user attributes.
115+
if (empty($userAttributes)) {
116+
return false;
116117
}
117118

118119
$customAttrCondEval = new CustomAttributeConditionEvaluator($userAttributes);
@@ -222,18 +223,4 @@ public static function areValuesSameType($firstVal, $secondVal)
222223

223224
return $firstValType == $secondValType;
224225
}
225-
226-
/**
227-
* Returns true only if given input is an array with all of it's keys of type string.
228-
* @param mixed $arr
229-
* @return bool True if array contains all string keys. Otherwise, false.
230-
*/
231-
public static function doesArrayContainOnlyStringKeys($arr)
232-
{
233-
if(!is_array($arr) || empty($arr)) {
234-
return false;
235-
}
236-
237-
return count(array_filter(array_keys($arr), 'is_string')) == count(array_keys($arr));
238-
}
239226
}

tests/DecisionServiceTests/DecisionServiceTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1138,7 +1138,7 @@ public function testGetVariationForFeatureRolloutWhenUserDoesNotQualifyForAnyTar
11381138
$experiment2 = $rollout->getExperiments()[2];
11391139

11401140
// Set an AudienceId for everyone else/last rule so that user does not qualify for audience
1141-
$experiment2->setAudienceIds(["11155"]);
1141+
$experiment2->setAudienceIds(["11154"]);
11421142
$expected_variation = $experiment2->getVariations()[0];
11431143

11441144
// Provide null attributes so that user does not qualify for audience

0 commit comments

Comments
 (0)