Skip to content

Commit e3475e2

Browse files
author
sakshamg1304
committed
feat: support for object in setAttribute API to send multiple attributes at once
1 parent 09762b9 commit e3475e2

File tree

7 files changed

+118
-51
lines changed

7 files changed

+118
-51
lines changed

CHANGELOG.md

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## [1.6.0] - 2024-04-09
9+
10+
### Added
11+
12+
- Support for `Map` in `setAttribute` method to send multiple attributes data.
13+
814
## [1.5.0] - 2025-03-24
915

1016
### Fixed
@@ -17,14 +23,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1723

1824
- Added the support for using salt for bucketing if provided in the rule configuration.
1925

20-
[1.3.1] - 2024-10-04
26+
27+
## [1.3.1] - 2024-10-04
2128

2229
### Fixed
2330

2431
- Improved Pre-segmentation result comparison logic to handle numeric values more accurately by trimming trailing zeroes and decimal points across various operand types
2532

2633

27-
[1.3.0] - 2024-10-03
34+
## [1.3.0] - 2024-10-03
2835

2936
### Added
3037

@@ -52,28 +59,28 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
5259

5360
- **Code refactoring** - source code is refactored to have error-handling, model-driven code, and inline documentation.
5461

55-
[1.2.5] - 2024-07-29
62+
## [1.2.5] - 2024-07-29
5663

5764
### Fixed
5865

5966
- Removed unnecessary vendor/autoload from `UuidUtil.php`
6067

61-
[1.2.1] - 2024-07-17
68+
## [1.2.1] - 2024-07-17
6269

6370
### Added
6471

6572
- Support for optional parameter SettingsFile in init
6673
- Support for gt,gte,lt,lte in Custom Variable pre-segmentation
6774

6875

69-
[1.1.1] - 2024-07-04
76+
## [1.1.1] - 2024-07-04
7077

7178
### Changed
7279

7380
- **Testing** - PHPUnit version changed to support in lower php versions
7481

7582

76-
[1.1.0] - 2024-07-02
83+
## [1.1.0] - 2024-07-02
7784

7885
### Changed
7986

@@ -88,7 +95,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
8895
- Ensure critical components are working properly on every build
8996

9097

91-
[1.0.0] - 2024-06-11
98+
## [1.0.0] - 2024-06-11
9299

93100
### Added
94101

README.md

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,10 @@ $variableValue = $getFlag->getVariable('variable_key', 'default-value');
4545
$trackRes = $vwoClient->trackEvent('event_name', $userContext);
4646

4747
// set Attribute
48-
$setAttribute = $vwoClient->setAttribute('attribute_key', 'attribute_value', $userContext);
48+
$attributes = [
49+
'attribute_key' => 'attribute_value'
50+
];
51+
$setAttribute = $vwoClient->setAttribute($attributes, $userContext);
4952
```
5053

5154
## Advanced Configuration Options
@@ -151,6 +154,15 @@ Example usage:
151154
$vwoClient->setAttribute('attribute_name', 'attribute_value', $userContext);
152155
```
153156

157+
Or
158+
159+
```php
160+
$attributes = [
161+
'attribute_name' => 'attribute_value'
162+
];
163+
$vwoClient->setAttribute($attributes, $userContext);
164+
```
165+
154166
See [Pushing Attributes](https://developers.vwo.com/v2/docs/fme-php-attributes#usage) documentation for additional information.
155167

156168
### Polling Interval Adjustment
@@ -352,4 +364,4 @@ Please go through our [contributing guidelines](https://github.com/wingify/vwo-f
352364

353365
[Apache License, Version 2.0](https://github.com/wingify/vwo-fme-php-sdk/blob/master/LICENSE)
354366

355-
Copyright 2024-2025 Wingify Software Pvt. Ltd.
367+
Copyright 2024-2025 Wingify Software Pvt. Ltd.

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "vwo/vwo-fme-php-sdk",
3-
"version": "1.5.0",
3+
"version": "1.6.0",
44
"keywords": ["vwo", "fme", "sdk"],
55
"license": "Apache-2.0",
66
"authors": [{

src/Api/SetAttribute.php

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -26,37 +26,34 @@
2626
interface ISetAttribute
2727
{
2828
/**
29-
* Sets an attribute for a user.
29+
* Sets multiple attributes for a user.
3030
* @param SettingsModel $settings Configuration settings.
31-
* @param string $attributeKey The key of the attribute to set.
32-
* @param mixed $attributeValue The value of the attribute.
31+
* @param array $attributes Key-value map of attributes.
3332
* @param ContextModel $context Context containing user information.
3433
*/
35-
public function setAttribute(SettingsModel $settings, string $attributeKey, $attributeValue, ContextModel $context): void;
34+
public function setAttribute(SettingsModel $settings, array $attributes, ContextModel $context): void;
3635
}
3736

3837
class SetAttribute implements ISetAttribute
3938
{
4039
/**
41-
* Implementation of setAttribute to create an impression for a user attribute.
40+
* Implementation of setAttribute to create an impression for multiple user attributes.
4241
* @param SettingsModel $settings Configuration settings.
43-
* @param string $attributeKey The key of the attribute to set.
44-
* @param mixed $attributeValue The value of the attribute.
42+
* @param array $attributes Key-value map of attributes.
4543
* @param ContextModel $context Context containing user information.
4644
*/
47-
public function setAttribute(SettingsModel $settings, string $attributeKey, $attributeValue, ContextModel $context): void
45+
public function setAttribute(SettingsModel $settings, array $attributes, ContextModel $context): void
4846
{
49-
$this->createImpressionForAttribute($settings, $attributeKey, $attributeValue, $context);
47+
$this->createImpressionForAttributes($settings, $attributes, $context);
5048
}
5149

5250
/**
53-
* Creates an impression for a user attribute and sends it to the server.
51+
* Creates an impression for multiple user attributes and sends it to the server.
5452
* @param SettingsModel $settings Configuration settings.
55-
* @param string $attributeKey The key of the attribute.
56-
* @param mixed $attributeValue The value of the attribute.
53+
* @param array $attributes Key-value map of attributes.
5754
* @param ContextModel $context Context containing user information.
5855
*/
59-
private function createImpressionForAttribute(SettingsModel $settings, string $attributeKey, $attributeValue, ContextModel $context): void
56+
private function createImpressionForAttributes(SettingsModel $settings, array $attributes, ContextModel $context): void
6057
{
6158
$networkUtil = new NetworkUtil();
6259

@@ -68,13 +65,12 @@ private function createImpressionForAttribute(SettingsModel $settings, string $a
6865
$context->getIpAddress()
6966
);
7067

71-
// Construct payload data for the attribute
68+
// Construct payload data for multiple attributes
7269
$payload = $networkUtil->getAttributePayloadData(
7370
$settings,
7471
$context->getId(),
7572
EventEnum::VWO_SYNC_VISITOR_PROP,
76-
$attributeKey,
77-
$attributeValue,
73+
$attributes,
7874
$context->getUserAgent(),
7975
$context->getIpAddress()
8076
);
@@ -83,4 +79,3 @@ private function createImpressionForAttribute(SettingsModel $settings, string $a
8379
$networkUtil->sendPostApiRequest($properties, $payload);
8480
}
8581
}
86-
?>

src/Constants/Constants.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ class Constants {
3939
const DEFAULT_REQUEST_TIME_INTERVAL = 600; // 10 * 60(secs) = 600 secs i.e. 10 minutes
4040
const DEFAULT_EVENTS_PER_REQUEST = 100;
4141
const SDK_NAME = 'vwo-fme-php-sdk';
42-
const SDK_VERSION = '1.5.0';
42+
const SDK_VERSION = '1.6.0';
4343
const AP = 'server';
4444

4545
const SETTINGS = 'settings';

src/Utils/NetworkUtil.php

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -196,14 +196,17 @@ public function getTrackGoalPayloadData($settings, $userId, $eventName, $eventPr
196196
return $properties;
197197
}
198198

199-
public function getAttributePayloadData($settings, $userId, $eventName, $attributeKey, $attributeValue, $visitorUserAgent = '', $ipAddress = '' ) {
199+
public function getAttributePayloadData($settings, $userId, $eventName, $attributes, $visitorUserAgent = '', $ipAddress = '') {
200200
$properties = $this->getEventBasePayload($settings, $userId, $eventName, $visitorUserAgent, $ipAddress);
201201
$properties['d']['event']['props']['isCustomEvent'] = true;
202202
$properties['d']['event']['props'][Constants::VWO_FS_ENVIRONMENT] = $settings->getSdkKey();
203-
$properties['d']['visitor']['props'][$attributeKey] = $attributeValue;
204-
203+
// Iterate over the attributes map and append to the visitor properties
204+
foreach ($attributes as $key => $value) {
205+
$properties['d']['visitor']['props'][$key] = $value;
206+
}
207+
205208
LogManager::instance()->debug(
206-
"IMPRESSION_FOR_EVENT_ARCH_SYNC_VISITOR_PROP: Impression built for {$eventName} event for Account ID:{$settings->getAccountId()}, User ID:{$userId}"
209+
"IMPRESSION_FOR_SYNC_VISITOR_PROP: Impression built for {$eventName} event for Account ID: {$settings->getAccountId()}, User ID: {$userId}"
207210
);
208211

209212
return $properties;

src/VWOClient.php

Lines changed: 69 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
interface IVWOClient {
3737
public function getFlag(string $featureKey, $context);
3838
public function trackEvent(string $eventName, $context, array $eventProperties);
39-
public function setAttribute(string $attributeKey, string $attributeValue, $context);
39+
public function setAttribute($attributesOrAttributeValue, $attributeValueOrContext, $context);
4040
}
4141

4242
class VWOClient implements IVWOClient {
@@ -141,31 +141,81 @@ public function trackEvent($eventName = null, $context = null, $eventProperties
141141
}
142142
}
143143

144-
public function setAttribute($attributeKey = null, $attributeValue = null, $context = null) {
144+
public function setAttribute($attributesOrAttributeValue = null , $attributeValueOrContext = null, $context = null) {
145145
$apiName = 'setAttribute';
146146

147147
try {
148148
LogManager::instance()->debug("API Called: $apiName");
149149

150-
if (!DataTypeUtil::isString($attributeKey)) {
151-
LogManager::instance()->error("Attribute key passed to $apiName API is not valid.");
152-
throw new \TypeError('TypeError: attributeKey should be a valid string');
153-
}
154-
155-
if (!DataTypeUtil::isString($attributeValue) && !DataTypeUtil::isNumber($attributeValue) && !DataTypeUtil::isBoolean($attributeValue)) {
156-
LogManager::instance()->error("Attribute value passed to $apiName API is not valid.");
150+
if (DataTypeUtil::isString($attributesOrAttributeValue)) {
151+
// Validate attributeKey is a string
152+
if (!DataTypeUtil::isString($attributesOrAttributeValue)) {
153+
LogManager::instance()->error("Attribute key passed to $apiName API is not valid.");
154+
throw new \TypeError('TypeError: attributeKey should be a valid string');
155+
}
156+
157+
// Validate attributeValue (the second argument) is valid
158+
if (!DataTypeUtil::isString($attributeValueOrContext) &&
159+
!DataTypeUtil::isNumber($attributeValueOrContext) &&
160+
!DataTypeUtil::isBoolean($attributeValueOrContext)) {
161+
LogManager::instance()->error("Attribute value passed to $apiName API is not valid.");
157162
throw new \TypeError('TypeError: attributeValue should be a valid string, number, or boolean');
163+
}
164+
165+
// Ensure context is valid
166+
if (!isset($context['id']) || empty($context['id'])) {
167+
LogManager::instance()->error('Context must contain a valid user ID.');
168+
throw new \Error('TypeError: Invalid context');
169+
}
170+
171+
$contextModel = new ContextModel();
172+
$contextModel->modelFromDictionary($context);
173+
174+
// Create the attributes map from key-value
175+
$attributes = [$attributesOrAttributeValue => $attributeValueOrContext];
176+
(new SetAttribute())->setAttribute($this->settings, $attributes, $contextModel);
177+
178+
} else {
179+
// Case where attributeKey is an array (multiple attributes)
180+
$attributes = $attributesOrAttributeValue;
181+
182+
// Validate attributes is an array
183+
if (!DataTypeUtil::isArray($attributes)) {
184+
LogManager::instance()->error("Attributes passed to $apiName API is not valid.");
185+
throw new \TypeError('TypeError: attributes should be an array');
186+
}
187+
188+
// Validate attributes is not empty
189+
if (empty($attributes)) {
190+
LogManager::instance()->error("Key 'attributesMap' passed to setAttribute API is not of valid type. Got type: null or empty array, should be: a non-empty array.");
191+
throw new \TypeError('TypeError: attributes should be a non-empty array');
192+
}
193+
194+
// Validate that each attribute value is of a supported type (string, number, or boolean)
195+
foreach ($attributes as $key => $value) {
196+
if (!is_string($key)) {
197+
LogManager::instance()->error("Attribute key in attributesMap is not valid. Got type: '" . gettype($key) . "', should be: string.");
198+
throw new \TypeError("TypeError: attribute key '$key' should only be a string");
199+
}
200+
201+
if (!DataTypeUtil::isString($value) && !DataTypeUtil::isNumber($value) && !DataTypeUtil::isBoolean($value)) {
202+
LogManager::instance()->error("Attribute value for key '$key' is not valid.");
203+
throw new \TypeError("TypeError: attributeValue for key '$key' should be a valid string, number, or boolean");
204+
}
205+
}
206+
$context = $attributeValueOrContext;
207+
// Ensure context is valid
208+
if (!isset($context['id']) || empty($context['id'])) {
209+
LogManager::instance()->error('Context must contain a valid user ID.');
210+
throw new \Error('TypeError: Invalid context');
211+
}
212+
213+
$contextModel = new ContextModel();
214+
$contextModel->modelFromDictionary($context);
215+
216+
// Proceed with setting the attributes if validation is successful
217+
(new SetAttribute())->setAttribute($this->settings, $attributes, $contextModel);
158218
}
159-
160-
if (!isset($context['id']) || empty($context['id'])) {
161-
LogManager::instance()->error('Context must contain a valid user ID.');
162-
throw new \Error('TypeError: Invalid context');
163-
}
164-
165-
$contextModel = new ContextModel();
166-
$contextModel->modelFromDictionary($context);
167-
168-
(new SetAttribute())->setAttribute($this->settings, $attributeKey, $attributeValue, $contextModel);
169219
} catch (\Throwable $error) {
170220
LogManager::instance()->error("API - $apiName failed to execute. Error: " . $error->getMessage());
171221
}

0 commit comments

Comments
 (0)