Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions PostHog/Classes/PHGPayloadManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ extern NSString *_Nonnull PHGPostHogIntegrationDidStart;
- (instancetype _Nonnull)initWithPostHog:(PHGPostHog *_Nonnull)posthog;

- (NSArray *_Nonnull)getFeatureFlags;
- (NSDictionary *_Nonnull)getFlagVariants;
- (NSDictionary *_Nonnull)getGroups;
- (void)saveGroup:(NSString *_Nonnull)groupType groupKey:(NSString *_Nonnull)groupKey;

Expand Down
58 changes: 9 additions & 49 deletions PostHog/Classes/PHGPayloadManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,6 @@
static NSString *const PHGAnonymousIdKey = @"PHGAnonymousId";
static NSString *const kPHGAnonymousIdFilename = @"posthog.anonymousId";

static NSString *const PHGActiveFeatureFlags = @"PHGActiveFeatureFlags";
static NSString *const kPHGActiveFeatureFlags = @"posthog.activeFeatureFlags";

static NSString *const PHGEnabledFeatureFlags = @"PHGEnabledFeatureFlags";
static NSString *const kPHGEnabledFeatureFlags = @"posthog.enabledFeatureFlags";

static NSString *const PHGGroups = @"PHGGroups";
static NSString *const kPHGGroups = @"posthog.groups";



@interface PHGPayloadManager ()

Expand Down Expand Up @@ -183,19 +173,7 @@ - (void)group:(NSString *)groupType groupKey:(NSString *)groupKey groupPropertie

- (void)receivedFeatureFlags:(NSDictionary *)flags
{
NSArray* keys = [flags allKeys];

#if TARGET_OS_TV
[self.userDefaultsStorage setArray:keys forKey:PHGActiveFeatureFlags];
#else
[self.fileStorage setArray:keys forKey:kPHGActiveFeatureFlags];
#endif

#if TARGET_OS_TV
[self.userDefaultsStorage setDictionary:flags forKey:PHGEnabledFeatureFlags];
#else
[self.fileStorage setDictionary:flags forKey:kPHGEnabledFeatureFlags];
#endif
[self.integration receivedFeatureFlags:flags];
}

- (void)reloadFeatureFlags
Expand Down Expand Up @@ -223,12 +201,12 @@ - (void)reloadFeatureFlags

- (NSArray *)getFeatureFlags
{
#if TARGET_OS_TV
NSArray *keys = [self.userDefaultsStorage arrayForKey:PHGActiveFeatureFlags];
#else
NSArray *keys = [self.fileStorage arrayForKey:kPHGActiveFeatureFlags];
#endif
return keys;
return [self.integration getFeatureFlags];
}

- (NSDictionary *)getFlagVariants
{
return [self.integration getFeatureFlagsAndValues];
}

- (void)receivedRemoteNotification:(NSDictionary *)userInfo
Expand Down Expand Up @@ -315,30 +293,12 @@ - (void)saveAnonymousId:(NSString *)anonymousId

- (void)saveGroup:(NSString *)groupType groupKey:(NSString *)groupKey
{
NSDictionary *currentGroups = [self getGroups];
NSMutableDictionary *newGroups = [currentGroups mutableCopy];
[newGroups setObject:groupKey forKey:groupType];

#if TARGET_OS_TV
[self.userDefaultsStorage setDictionary:newGroups forKey:PHGGroups];
#else
[self.fileStorage setDictionary:newGroups forKey:kPHGGroups];
#endif
[self.integration saveGroup:groupType groupKey:groupKey];
}

- (NSDictionary *)getGroups
{
#if TARGET_OS_TV
NSDictionary *groups = [self.userDefaultsStorage dictionaryForKey:PHGGroups];
#else
NSDictionary *groups = [self.fileStorage dictionaryForKey:kPHGGroups];
#endif

// if groups doesn't exist, return a new empty dict
if (!groups){
return [[NSDictionary alloc] init];
}
return groups;
return [self.integration getGroups];
}

- (void)flush
Expand Down
1 change: 1 addition & 0 deletions PostHog/Classes/PHGPostHog.h
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ NS_ASSUME_NONNULL_BEGIN
- (void)group:(NSString *)groupType groupKey:(NSString *)groupKey;
- (void)group:(NSString *)groupType groupKey:(NSString *)groupKey properties:(SERIALIZABLE_DICT _Nullable)properties;

- (id)getFeatureFlag:(NSString *)flagKey;
- (bool)isFeatureEnabled:(NSString *)flagKey;
- (void)reloadFeatureFlags;

Expand Down
25 changes: 25 additions & 0 deletions PostHog/Classes/PHGPostHog.m
Original file line number Diff line number Diff line change
Expand Up @@ -280,10 +280,35 @@ - (void)group:(NSString *_Nonnull)groupType groupKey:(NSString *_Nonnull)groupKe
}
}

- (id)getFeatureFlag:(NSString *)flagKey
{
NSDictionary *variants = [self.payloadManager getFlagVariants];
id variantValue = [variants valueForKey:flagKey];

NSMutableDictionary *properties = [NSMutableDictionary dictionary];
[properties setValue:flagKey forKey:@"$feature_flag"];
[properties setValue:variantValue forKey:@"$feature_flag_response"];

[self run:PHGEventTypeCapture payload:
[[PHGCapturePayload alloc] initWithEvent:@"$feature_flag_called"
properties:PHGCoerceDictionary(properties)]];
return variantValue;
}

- (bool)isFeatureEnabled:(NSString *)flagKey
{
NSArray *keys = [self.payloadManager getFeatureFlags];
BOOL isFlagEnabled = [keys containsObject: flagKey];

NSMutableDictionary *properties = [NSMutableDictionary dictionary];

[properties setValue:flagKey forKey:@"$feature_flag"];
[properties setValue:@(isFlagEnabled) forKey:@"$feature_flag_response"];

[self run:PHGEventTypeCapture payload:
[[PHGCapturePayload alloc] initWithEvent:@"$feature_flag_called"
properties:PHGCoerceDictionary(properties)]];

return isFlagEnabled;
}

Expand Down
7 changes: 7 additions & 0 deletions PostHog/Internal/PHGPostHogIntegration.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,13 @@ extern NSString *const PHGPostHogRequestDidFailNotification;
- (NSDictionary *)liveContext;
- (void)saveDistinctId:(NSString *)distinctId;

- (NSDictionary *_Nonnull)getGroups;
- (void)saveGroup:(NSString *_Nonnull)groupType groupKey:(NSString *_Nonnull)groupKey;

- (NSArray *_Nonnull)getFeatureFlags;
- (NSDictionary *)getFeatureFlagsAndValues;
- (void)receivedFeatureFlags:(NSDictionary *)flags;

@end

NS_ASSUME_NONNULL_END
74 changes: 74 additions & 0 deletions PostHog/Internal/PHGPostHogIntegration.m
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,12 @@
NSString *const kPHGDistinctIdFilename = @"posthog.distinctId";
NSString *const kPHGQueueFilename = @"posthog.queue.plist";

static NSString *const PHGEnabledFeatureFlags = @"PHGEnabledFeatureFlags";
static NSString *const kPHGEnabledFeatureFlags = @"posthog.enabledFeatureFlags";

static NSString *const PHGGroups = @"PHGGroups";
static NSString *const kPHGGroups = @"posthog.groups";

static NSString *GetDeviceModel()
{
size_t size;
Expand Down Expand Up @@ -217,6 +223,20 @@ - (NSDictionary *)liveContext
context[@"$network_wifi"] = @NO;
context[@"$network_cellular"] = @NO;
}

context[@"$groups"] = [self getGroups];
context[@"$active_feature_flags"] = [self getFeatureFlags];

NSDictionary *flagsAndValues = [self getFeatureFlagsAndValues];

int n = 0;
for(id flag in flagsAndValues){
NSString *key = [NSString stringWithFormat:@"$feature/%@", flag];
NSString *enumeratedKey = [NSString stringWithFormat:@"$active_feature_flags__%d", n];
context[key] = [flagsAndValues objectForKey:flag];
context[enumeratedKey] = flag;
n++;
}

#if TARGET_OS_IOS
static dispatch_once_t networkInfoOnceToken;
Expand Down Expand Up @@ -569,6 +589,60 @@ - (NSString *)getDistinctId
#endif
}

- (void)saveGroup:(NSString *)groupType groupKey:(NSString *)groupKey
{
NSDictionary *currentGroups = [self getGroups];
NSMutableDictionary *newGroups = [currentGroups mutableCopy];
[newGroups setObject:groupKey forKey:groupType];

#if TARGET_OS_TV
[self.userDefaultsStorage setDictionary:newGroups forKey:PHGGroups];
#else
[self.fileStorage setDictionary:newGroups forKey:kPHGGroups];
#endif
}

- (NSDictionary *)getGroups
{
#if TARGET_OS_TV
NSDictionary *groups = [self.userDefaultsStorage dictionaryForKey:PHGGroups];
#else
NSDictionary *groups = [self.fileStorage dictionaryForKey:kPHGGroups];
#endif

// if groups doesn't exist, return a new empty dict
if (!groups){
return [[NSDictionary alloc] init];
}
return groups;
}

- (void)receivedFeatureFlags:(NSDictionary *)flags
{
#if TARGET_OS_TV
[self.userDefaultsStorage setDictionary:flags forKey:PHGEnabledFeatureFlags];
#else
[self.fileStorage setDictionary:flags forKey:kPHGEnabledFeatureFlags];
#endif
}

- (NSArray *)getFeatureFlags
{
NSDictionary *dict = [self getFeatureFlagsAndValues];
NSArray *keys = [dict allKeys];
return keys;
}

- (NSDictionary *)getFeatureFlagsAndValues
{
#if TARGET_OS_TV
NSDictionary *dict = [self.userDefaultsStorage dictionaryForKey:PHGEnabledFeatureFlags];
#else
NSDictionary *dict = [self.fileStorage dictionaryForKey:kPHGEnabledFeatureFlags];
#endif
return dict;
}

- (void)persistQueue
{
[self.fileStorage setArray:[self.queue copy] forKey:kPHGQueueFilename];
Expand Down
22 changes: 22 additions & 0 deletions PostHogTests/FeatureFlagTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,28 @@ class FeatureFlagTests: QuickSpec {
let isEnabled = posthog.isFeatureEnabled("some-flag")
expect(isEnabled).to(beTrue())
}

it("checks multivariate flag is enabled - integer") {
_ = stubRequest("POST", "https://app.posthog.test/decide/?v=2" as LSMatcheable)
.andReturn(200)?
.withBody("{\"featureFlags\":{\"some-flag\":1}}" as LSHTTPBody);
posthog.reloadFeatureFlags()
// Hacky: Need to buffer for async request to happen without stub being cleaned up
sleep(1)
let flagValue = posthog.getFeatureFlag("some-flag")
expect(flagValue).to(be(1))
}

it("checks multivariate flag is enabled - string") {
_ = stubRequest("POST", "https://app.posthog.test/decide/?v=2" as LSMatcheable)
.andReturn(200)?
.withBody("{\"featureFlags\":{\"some-flag\":\"variant-1\"}}" as LSHTTPBody);
posthog.reloadFeatureFlags()
// Hacky: Need to buffer for async request to happen without stub being cleaned up
sleep(1)
let flagValue = posthog.getFeatureFlag("some-flag")
expect(flagValue).to(be("variant-1"))
}

}

Expand Down