Skip to content

Commit 36f326b

Browse files
committed
Merge branch 'release/2.0.6'
2 parents ca9be26 + 5ddde92 commit 36f326b

File tree

15 files changed

+253
-107
lines changed

15 files changed

+253
-107
lines changed

Example/Leanplum-SDK.xcodeproj/project.pbxproj

Lines changed: 12 additions & 60 deletions
Large diffs are not rendered by default.
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3+
<plist version="1.0">
4+
<dict>
5+
<key>IDEDidComputeMac32BitWarning</key>
6+
<true/>
7+
</dict>
8+
</plist>

Example/Tests/Classes/ActionManagerTest.m

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,4 +278,50 @@ - (void)test_push_token
278278
[self waitForExpectationsWithTimeout:2 handler:nil];
279279
}
280280

281+
- (void)test_active_period_false
282+
{
283+
LPActionManager *manager = [LPActionManager sharedManager];
284+
LPContextualValues *contextualValues = [[LPContextualValues alloc] init];
285+
286+
NSDictionary *config = [self messageConfigInActivePeriod:NO];
287+
288+
LeanplumMessageMatchResult result = [manager shouldShowMessage:@""
289+
withConfig:config
290+
when:@"event"
291+
withEventName:@"ActivePeriodTest"
292+
contextualValues:contextualValues];
293+
XCTAssertFalse(result.matchedActivePeriod);
294+
}
295+
296+
- (void)test_active_period_true
297+
{
298+
LPActionManager *manager = [LPActionManager sharedManager];
299+
LPContextualValues *contextualValues = [[LPContextualValues alloc] init];
300+
301+
NSDictionary *config = [self messageConfigInActivePeriod:YES];
302+
303+
LeanplumMessageMatchResult result = [manager shouldShowMessage:@""
304+
withConfig:config
305+
when:@"event"
306+
withEventName:@"ActivePeriodTest"
307+
contextualValues:contextualValues];
308+
XCTAssertTrue(result.matchedActivePeriod);
309+
310+
}
311+
312+
#pragma mark Helpers
313+
314+
-(NSDictionary *)messageConfigInActivePeriod:(BOOL)inActivePeriod
315+
{
316+
NSDictionary *config = @{@"whenLimits":@{@"children":@[]},
317+
@"whenTriggers":@{@"children":@[@{@"noun":@"ActivePeriodTest",
318+
@"subject":@"event",
319+
}],
320+
@"verb":@"OR"
321+
},
322+
@"startTime": inActivePeriod ? @1524507600000 : @956557100000,
323+
@"endTime": inActivePeriod ? @7836202020000 : @956557200000
324+
};
325+
return config;
326+
}
281327
@end

Example/Tests/Classes/MessagesTest.m

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,10 +69,20 @@ - (void)tearDown
6969

7070
- (void)setMockResult
7171
{
72-
self.mockResult = LeanplumMessageMatchResultMake(YES, NO, YES);
72+
self.mockResult = LeanplumMessageMatchResultMake(YES, NO, YES, YES);
7373
XCTAssertFalse(self.mockResult.matchedUnlessTrigger);
7474
XCTAssertTrue(self.mockResult.matchedTrigger);
7575
XCTAssertTrue(self.mockResult.matchedLimit);
76+
XCTAssertTrue(self.mockResult.matchedActivePeriod);
77+
}
78+
79+
- (void)setMockResultActivePeriodFalse
80+
{
81+
self.mockResult = LeanplumMessageMatchResultMake(YES, NO, YES, NO);
82+
XCTAssertFalse(self.mockResult.matchedUnlessTrigger);
83+
XCTAssertTrue(self.mockResult.matchedTrigger);
84+
XCTAssertTrue(self.mockResult.matchedLimit);
85+
XCTAssertFalse(self.mockResult.matchedActivePeriod);
7686
}
7787

7888
- (void)setMockActionManager
@@ -243,4 +253,33 @@ - (void)test_chained_messages
243253
XCTAssertTrue([chainedMessageId isEqual:@"1"]);
244254
}
245255

256+
- (void) test_active_period_true
257+
{
258+
NSString *jsonString = [LeanplumHelper retrieve_string_from_file:@"SingleMessage"
259+
ofType:@"json"];
260+
261+
NSDictionary *messageConfigs = [LPJSON JSONFromString:jsonString];
262+
[self runInAppMessagePrioritizationTest:messageConfigs
263+
withExpectedMessageIds:[NSSet setWithObjects: @"1", nil]];
264+
265+
// Test creating action context for message id.
266+
LPActionContext *context = [Leanplum createActionContextForMessageId:@"1"];
267+
XCTAssertEqualObjects(@"Alert", context.actionName);
268+
}
269+
270+
- (void) test_active_period_false
271+
{
272+
[self setMockResultActivePeriodFalse];
273+
[self setMockActionManager];
274+
[self setMockLPInternalState];
275+
276+
NSString *jsonString = [LeanplumHelper retrieve_string_from_file:@"SingleMessage"
277+
ofType:@"json"];
278+
279+
NSDictionary *messageConfigs = [LPJSON JSONFromString:jsonString];
280+
[self runInAppMessagePrioritizationTest:messageConfigs
281+
withExpectedMessageIds:[NSSet set]];
282+
283+
}
284+
246285
@end

Example/Tests/Classes/UtilitiesTest.m

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,4 +79,11 @@ - (void)test_base64EncodedStringFromData {
7979
XCTAssertEqualObjects(base64String, expectedSring);
8080
}
8181

82+
- (void)test_urlEncodedStringFromString {
83+
XCTAssertEqualObjects([Utils urlEncodedStringFromString:@"http://www.leanplum.com"], @"http://www.leanplum.com");
84+
XCTAssertEqualObjects([Utils urlEncodedStringFromString:@"http://www.leanplum.com?q=simple_english1&test=2"], @"http://www.leanplum.com?q=simple_english1&test=2");
85+
XCTAssertEqualObjects([Utils urlEncodedStringFromString:@"https://ramsey.tfaforms.net/356302?id={}"], @"https://ramsey.tfaforms.net/356302?id=%7B%7D");
86+
XCTAssertEqualObjects([Utils urlEncodedStringFromString:@"lomotif://music/月亮"], @"lomotif://music/%E6%9C%88%E4%BA%AE");
87+
}
88+
8289
@end

Leanplum-SDK/Classes/Constants.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,11 @@
2828
#define IOS_6_SUPPORTED defined(_ARM_ARCH_7) || defined(__i386__) || defined(__LP64__)
2929

3030
#ifndef LP_NOT_TV
31-
#define LP_NOT_TV (!defined(TARGET_OS_TV) || !TARGET_OS_TV)
31+
#if (!defined(TARGET_OS_TV) || !TARGET_OS_TV)
32+
#define LP_NOT_TV 1
33+
#else
34+
#define LP_NOT_TV 0
35+
#endif
3236
#endif
3337

3438
#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)
@@ -45,7 +49,7 @@
4549
#define IS_NOOP ((!IS_SUPPORTED_IOS_VERSION) || IS_JAILBROKEN || [LPConstantsState sharedState].isTestMode || [LPConstantsState sharedState].isInPermanentFailureState)
4650
#define RETURN_IF_NOOP if (IS_NOOP) return
4751

48-
#define LEANPLUM_SDK_VERSION @"2.0.5"
52+
#define LEANPLUM_SDK_VERSION @"2.0.6"
4953
#define LEANPLUM_CLIENT @"ios"
5054

5155
// Can upload up to 100 files or 50 MB per request.

Leanplum-SDK/Classes/LPActionManager.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,11 @@ struct LeanplumMessageMatchResult {
3333
BOOL matchedTrigger;
3434
BOOL matchedUnlessTrigger;
3535
BOOL matchedLimit;
36+
BOOL matchedActivePeriod;
3637
};
3738
typedef struct LeanplumMessageMatchResult LeanplumMessageMatchResult;
3839

39-
LeanplumMessageMatchResult LeanplumMessageMatchResultMake(BOOL matchedTrigger, BOOL matchedUnlessTrigger, BOOL matchedLimit);
40+
LeanplumMessageMatchResult LeanplumMessageMatchResultMake(BOOL matchedTrigger, BOOL matchedUnlessTrigger, BOOL matchedLimit, BOOL matchedActivePeriod);
4041

4142
typedef enum {
4243
kLeanplumActionFilterForeground = 0b1,

Leanplum-SDK/Classes/LPActionManager.m

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,13 @@
3737
#import <objc/runtime.h>
3838
#import <objc/message.h>
3939

40-
LeanplumMessageMatchResult LeanplumMessageMatchResultMake(BOOL matchedTrigger, BOOL matchedUnlessTrigger, BOOL matchedLimit)
40+
LeanplumMessageMatchResult LeanplumMessageMatchResultMake(BOOL matchedTrigger, BOOL matchedUnlessTrigger, BOOL matchedLimit, BOOL matchedActivePeriod)
4141
{
4242
LeanplumMessageMatchResult result;
4343
result.matchedTrigger = matchedTrigger;
4444
result.matchedUnlessTrigger = matchedUnlessTrigger;
4545
result.matchedLimit = matchedLimit;
46+
result.matchedActivePeriod = matchedActivePeriod;
4647
return result;
4748
}
4849

@@ -1064,7 +1065,7 @@ - (LeanplumMessageMatchResult)shouldShowMessage:(NSString *)messageId
10641065
withEventName:(NSString *)eventName
10651066
contextualValues:(LPContextualValues *)contextualValues
10661067
{
1067-
LeanplumMessageMatchResult result = LeanplumMessageMatchResultMake(NO, NO, NO);
1068+
LeanplumMessageMatchResult result = LeanplumMessageMatchResultMake(NO, NO, NO, NO);
10681069

10691070
// 1. Must not be muted.
10701071
if ([[NSUserDefaults standardUserDefaults] boolForKey:
@@ -1088,6 +1089,17 @@ - (LeanplumMessageMatchResult)shouldShowMessage:(NSString *)messageId
10881089
// 3. Must match all limit conditions.
10891090
NSDictionary *limitConfig = messageConfig[@"whenLimits"];
10901091
result.matchedLimit = [self matchesLimits:limitConfig messageId:messageId];
1092+
1093+
// 4. Must be within active period.
1094+
NSTimeInterval now = [[NSDate date] timeIntervalSince1970];
1095+
NSTimeInterval startTime = [messageConfig[@"startTime"] doubleValue] / 1000.0;
1096+
NSTimeInterval endTime = [messageConfig[@"endTime"] doubleValue] / 1000.0;
1097+
if (startTime && endTime) {
1098+
result.matchedActivePeriod = now > startTime && now < endTime;
1099+
} else {
1100+
result.matchedActivePeriod = YES;
1101+
}
1102+
10911103
return result;
10921104
}
10931105

Leanplum-SDK/Classes/LPDatabase.m

Lines changed: 40 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ - (id)init
5050
- (sqlite3 *)initSQLite
5151
{
5252
const char *sqliteFilePath = [[LPDatabase sqliteFilePath] UTF8String];
53-
int result = sqlite3_open(sqliteFilePath, &sqlite);
53+
int result = sqlite3_open_v2(sqliteFilePath, &sqlite, SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE | SQLITE_OPEN_FULLMUTEX, NULL);
5454
if (result != SQLITE_OK) {
5555
[self handleSQLiteError:@"SQLite fail to open" errorResult:result query:nil];
5656
return nil;
@@ -84,7 +84,11 @@ + (LPDatabase *)sharedDatabase
8484
*/
8585
+ (NSString *)sqliteFilePath
8686
{
87+
#if LP_NOT_TV
8788
return [[LPFileManager documentsDirectory] stringByAppendingPathComponent:LEANPLUM_SQLITE_NAME];
89+
#else
90+
return [[LPFileManager cachesDirectory] stringByAppendingPathComponent:LEANPLUM_SQLITE_NAME];
91+
#endif
8892
}
8993

9094
/**
@@ -190,40 +194,45 @@ - (NSArray *)rowsFromQuery:(NSString *)query bindObjects:(NSArray *)objectsToBin
190194
}
191195

192196
@synchronized (self) {
193-
NSMutableArray *rows = [NSMutableArray new];
194-
sqlite3_stmt *statement = [self sqliteStatementFromQuery:query
195-
bindObjects:objectsToBind];
196-
if (!statement) {
197-
return @[];
198-
}
199-
200-
// Iterate through rows.
201-
while (sqlite3_step(statement) == SQLITE_ROW) {
202-
// Get column data as dictionary where column name is the key
203-
// and value will be a blob or a string. This is a safe conversion.
204-
// Details: http://www.sqlite.org/c3ref/column_blob.html
205-
NSMutableDictionary *columnData = [NSMutableDictionary new];
206-
int columnsCount = sqlite3_column_count(statement);
207-
for (int i=0; i<columnsCount; i++){
208-
char *columnKeyUTF8 = (char *)sqlite3_column_name(statement, i);
209-
NSString *columnKey = [NSString stringWithUTF8String:columnKeyUTF8];
210-
211-
if (sqlite3_column_type(statement, i) == SQLITE_BLOB) {
212-
NSData *columnBytes = [[NSData alloc] initWithBytes:sqlite3_column_blob(statement, i)
213-
length:sqlite3_column_bytes(statement, i)];
214-
columnData[columnKey] = [NSKeyedUnarchiver unarchiveObjectWithData:columnBytes];
215-
} else {
216-
char *columnValueUTF8 = (char *)sqlite3_column_text(statement, i);
217-
if (columnValueUTF8) {
218-
NSString *columnValue = [NSString stringWithUTF8String:columnValueUTF8];
219-
columnData[columnKey] = columnValue;
197+
@try {
198+
NSMutableArray *rows = [NSMutableArray new];
199+
sqlite3_stmt *statement = [self sqliteStatementFromQuery:query
200+
bindObjects:objectsToBind];
201+
if (!statement) {
202+
return @[];
203+
}
204+
205+
// Iterate through rows.
206+
while (sqlite3_step(statement) == SQLITE_ROW) {
207+
// Get column data as dictionary where column name is the key
208+
// and value will be a blob or a string. This is a safe conversion.
209+
// Details: http://www.sqlite.org/c3ref/column_blob.html
210+
NSMutableDictionary *columnData = [NSMutableDictionary new];
211+
int columnsCount = sqlite3_column_count(statement);
212+
for (int i=0; i<columnsCount; i++){
213+
char *columnKeyUTF8 = (char *)sqlite3_column_name(statement, i);
214+
NSString *columnKey = [NSString stringWithUTF8String:columnKeyUTF8];
215+
216+
if (sqlite3_column_type(statement, i) == SQLITE_BLOB) {
217+
NSData *columnBytes = [[NSData alloc] initWithBytes:sqlite3_column_blob(statement, i)
218+
length:sqlite3_column_bytes(statement, i)];
219+
columnData[columnKey] = [NSKeyedUnarchiver unarchiveObjectWithData:columnBytes];
220+
} else {
221+
char *columnValueUTF8 = (char *)sqlite3_column_text(statement, i);
222+
if (columnValueUTF8) {
223+
NSString *columnValue = [NSString stringWithUTF8String:columnValueUTF8];
224+
columnData[columnKey] = columnValue;
225+
}
220226
}
221227
}
228+
[rows addObject:columnData];
222229
}
223-
[rows addObject:columnData];
230+
sqlite3_finalize(statement);
231+
return rows;
232+
} @catch (NSException *e) {
233+
LPLog(LPError, @"SQLite operation failed.");
234+
// TODO: Make sure to catch this when new logging is in place,
224235
}
225-
sqlite3_finalize(statement);
226-
return rows;
227236
}
228237
return @[];
229238
}

0 commit comments

Comments
 (0)