diff --git a/Sources/mParticle-Appboy/MPKitAppboy.m b/Sources/mParticle-Appboy/MPKitAppboy.m index 68639e4..05525b4 100644 --- a/Sources/mParticle-Appboy/MPKitAppboy.m +++ b/Sources/mParticle-Appboy/MPKitAppboy.m @@ -17,6 +17,7 @@ static NSString *const enableTypeDetectionKey = @"enableTypeDetection"; static NSString *const bundleCommerceEventData = @"bundleCommerceEventData"; static NSString *const replaceSkuWithProductName = @"replaceSkuWithProductName"; +static NSString *const subscriptionGroupMapping = @"subscriptionGroupMapping"; // The possible values for userIdentificationType static NSString *const userIdValueOther = @"Other"; @@ -72,6 +73,7 @@ @interface MPKitAppboy() { Braze *appboyInstance; BOOL collectIDFA; BOOL forwardScreenViews; + NSMutableDictionary *subscriptionGroupDictionary; } @property (nonatomic) NSString *host; @@ -180,6 +182,27 @@ - (NSString *)stripCharacter:(NSString *)character fromString:(NSString *)origin } } +- (NSMutableDictionary *)getSubscriptionGroupIds:(NSString *)subscriptionGroupMap { + NSMutableDictionary *subscriptionGroupDictionary = [NSMutableDictionary dictionary]; + + if (!subscriptionGroupMap.length) { + return subscriptionGroupDictionary; + } + + NSData *subsctiprionGroupData = [subscriptionGroupMap dataUsingEncoding:NSUTF8StringEncoding]; + + NSError *error = nil; + NSArray *subsctiprionGroupDataArray = [NSJSONSerialization JSONObjectWithData:subsctiprionGroupData options:0 error:&error]; + + for (NSDictionary *item in subsctiprionGroupDataArray) { + NSString *key = item[@"map"]; + NSString *value = item[@"value"]; + subscriptionGroupDictionary[key] = value; + } + + return subscriptionGroupDictionary; +} + - (MPKitExecStatus *)logAppboyCustomEvent:(MPEvent *)event eventType:(NSUInteger)eventType { void (^logCustomEvent)(void) = ^{ NSDictionary *transformedEventInfo = [event.customAttributes transformValuesToString]; @@ -387,6 +410,8 @@ - (void)start { self->appboyInstance.delegate = [MPKitAppboy urlDelegate]; } + self->subscriptionGroupDictionary = [self getSubscriptionGroupIds:self.configuration[subscriptionGroupMapping]]; + #if TARGET_OS_IOS BrazeInAppMessageUI *inAppMessageUI = [[BrazeInAppMessageUI alloc] init]; inAppMessageUI.delegate = [MPKitAppboy inAppMessageControllerDelegate]; @@ -708,6 +733,7 @@ - (MPKitExecStatus *)setUserAttribute:(NSString *)key value:(NSString *)value { } value = [self stringRepresentation:value]; + if (!value) { execStatus = [[MPKitExecStatus alloc] initWithSDKCode:@(MPKitInstanceAppboy) returnCode:MPKitReturnCodeFail]; return execStatus; @@ -822,6 +848,17 @@ - (MPKitExecStatus *)setUserAttribute:(NSString *)key value:(NSString *)value { execStatus = [[MPKitExecStatus alloc] initWithSDKCode:@(MPKitInstanceAppboy) returnCode:MPKitReturnCodeFail]; return execStatus; } + } else if (subscriptionGroupDictionary[key]){ + NSString *subscriptionGroupId = subscriptionGroupDictionary[key]; + if ([value isEqualToString:@"1"]) { + [appboyInstance.user addToSubscriptionGroupWithGroupId:subscriptionGroupId]; + } else if ([value isEqualToString:@"0"]) { + [appboyInstance.user removeFromSubscriptionGroupWithGroupId:subscriptionGroupId]; + } else { + NSLog(@"mParticle -> Invalid value type for subscriptionGroupId mapped user attribute key: %@, expected value should be of type BOOL", key); + execStatus = [[MPKitExecStatus alloc] initWithSDKCode:@(MPKitInstanceAppboy) returnCode:MPKitReturnCodeFail]; + return execStatus; + } } else { key = [self stripCharacter:@"$" fromString:key]; diff --git a/mParticle_AppboyTests/mParticle_AppboyTests.m b/mParticle_AppboyTests/mParticle_AppboyTests.m index 2dae0d1..dde3bcb 100644 --- a/mParticle_AppboyTests/mParticle_AppboyTests.m +++ b/mParticle_AppboyTests/mParticle_AppboyTests.m @@ -234,6 +234,42 @@ - (void)testPushSubscribtionUserAttribute { [mockClient stopMocking]; } +- (void)testSubscriptionGroupIdsMappedUserAttributes { + NSDictionary *kitConfiguration = @{@"apiKey":@"BrazeID", + @"id":@42, + @"ABKCollectIDFA":@"true", + @"ABKRequestProcessingPolicyOptionKey": @"1", + @"ABKFlushIntervalOptionKey":@"2", + @"ABKSessionTimeoutKey":@"3", + @"ABKMinimumTriggerTimeIntervalKey":@"4", + @"userIdentificationType":@"MPID", + @"subscriptionGroupMapping" : @"[{\"jsmap\":null,\"map\":\"testAttribute1\",\"maptype\":\"UserAttributeClass.Name\",\"value\":\"00000000-0000-0000-0000-00000000000\"},{\"jsmap\":null,\"map\":\"testAttribute2\",\"maptype\":\"UserAttributeClass.Name\",\"value\":\"00000000-0000-0000-0000-00000000001\"}]" + }; + + MPKitAppboy *kitInstance = [[MPKitAppboy alloc] init]; + [kitInstance didFinishLaunchingWithConfiguration:kitConfiguration]; + + BRZConfiguration *configuration = [[BRZConfiguration alloc] init]; + Braze *testClient = [[Braze alloc] initWithConfiguration:configuration]; + id mockClient = OCMPartialMock(testClient); + [kitInstance setAppboyInstance:mockClient]; + XCTAssertEqualObjects(mockClient, [kitInstance appboyInstance]); + + // Should succeed since Bool false is a valid value + MPKitExecStatus *execStatus1 = [kitInstance setUserAttribute:@"testAttribute1" value:@NO]; + XCTAssertEqual(execStatus1.returnCode, MPKitReturnCodeSuccess); + // Should succeed since Bool true is a valid value + MPKitExecStatus *execStatus2 = [kitInstance setUserAttribute:@"testAttribute2" value:@YES]; + XCTAssertEqual(execStatus2.returnCode, MPKitReturnCodeSuccess); + // Should fail since testValue is not type BOOL + MPKitExecStatus *execStatus3 = [kitInstance setUserAttribute:@"testAttribute2" value:@"testValue"]; + XCTAssertEqual(execStatus3.returnCode, MPKitReturnCodeFail); + + [mockClient verify]; + + [mockClient stopMocking]; +} + //- (void)testEndpointOverride { // MPKitAppboy *appBoy = [[MPKitAppboy alloc] init];