// // Stack.m // Contentstack // // Created by Reefaq on 11/07/15. // Copyright (c) 2015 Contentstack. All rights reserved. // #import #import "CSIOInternalHeaders.h" #import "CSIOConstants.h" #import "CSIOCoreHTTPNetworking.h" #import "ContentType.h" #import "Taxonomy.h" #import "CSIOAPIURLs.h" #import "NSObject+Extensions.h" #import "GlobalField.h" @interface Stack () @property (nonatomic, copy) NSString *apiKey; @property (nonatomic, copy) NSString *accessToken; @property (nonatomic, copy) Config *config; @property (nonatomic, copy) NSString *environment; @end @implementation Stack - (NSString *)hostURL { return self.config.host; } - (instancetype)initWithAPIKey:(NSString*)apiKey andaccessToken:(NSString *)accessToken andEnvironment:(NSString*)environment andConfig:(Config *)sConfig { if (self = [super init]) { _config = sConfig; _version = [sConfig.version copy]; _environment = [environment copy]; _apiKey = apiKey; _accessToken = accessToken; _network = [[CSIOCoreHTTPNetworking alloc] initWithDelegate:_config.delegate]; _stackHeaders = [NSMutableDictionary dictionary]; ISO8601DateFormatter *formatter = [[ISO8601DateFormatter alloc]init]; _commonDateFormatter = formatter; _commonDateFormatter.includeTime = YES; _requestOperationSet = [NSMutableSet set]; // Add early access headers only if they exist NSDictionary *earlyAccessHeaders = [_config earlyAccessHeaders]; if (earlyAccessHeaders.count > 0) { [_stackHeaders addEntriesFromDictionary:earlyAccessHeaders]; } [self setHeader:_apiKey forKey:kCSIO_SiteApiKey]; [self setHeader:_accessToken forKey:kCSIO_Accesstoken]; } return self; } //MARK: - Get ContentTypes -(void)getContentTypes:(NSDictionary *)params completion:(void (^)(NSArray * _Nullable, NSError * _Nullable))completionBlock { NSString *path = [CSIOAPIURLs fetchSchemaWithVersion:self.version]; NSURLSessionDataTask *op = [self.network requestForStack:self withURLPath:path requestType:CSIOCoreNetworkingRequestTypeGET params:params additionalHeaders:self.stackHeaders completion:^(ResponseType responseType, id responseJSON, NSError *error) { if (completionBlock) { if (error) { completionBlock(nil, error); }else { NSDictionary *responseData = responseJSON; if ([[responseData allKeys] containsObject:@"content_types"] && [responseData objectForKey:@"content_types"] != nil && [[responseData objectForKey:@"content_types"] isKindOfClass:[NSArray class]]) { completionBlock([responseData objectForKey:@"content_types"], nil); }else { NSError *error = [NSError errorWithDomain:@"Error" code:-4001 userInfo:@{@"error": @"Failed to retreive data."}]; completionBlock(nil, error); } } } }]; if (op && ![op isKindOfClass:[NSNull class]]) { [self.requestOperationSet addObject:op]; } } //MARK: - ContentType -(ContentType*)contentTypeWithName:(NSString*)contentTypeName; { ContentType *contentType = [[ContentType alloc] initWithStack:self withName:contentTypeName]; return contentType; } //MARK: - Taxonomy -(Taxonomy*)taxonomy { Taxonomy *taxonomy = [[Taxonomy alloc] initWithStack:self]; return taxonomy; } -(GlobalField*)globalField { GlobalField *globalField = [[GlobalField alloc] initWithStack:self]; return globalField; } -(GlobalField*)globalFieldWithName:(NSString*)globalFieldName { GlobalField *globalField = [[GlobalField alloc] initWithStack:self withName:globalFieldName]; return globalField; } //MARK: - Asset -(Asset *)asset { Asset *asset = [[Asset alloc] initWithStack:self]; return asset; } -(Asset*)assetWithUID:(NSString*)assetUid { Asset *asset = [[Asset alloc] initWithStack:self withAssetUID:assetUid]; return asset; } -(AssetLibrary *)assetLibrary { AssetLibrary *assetLib = [[AssetLibrary alloc] initWithStack:self]; return assetLib; } //MARK: - Headers - (void)setHeader:(NSString *)headerValue forKey:(NSString *)headerKey { [self.stackHeaders setObject:headerValue forKey:headerKey]; } - (void)addHeadersWithDictionary:(NSDictionary *)headers { [headers enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) { [self.stackHeaders setObject:obj forKey:key]; }]; } - (void)removeHeaderForKey:(NSString *)headerKey { if (self.stackHeaders[headerKey]) { [self.stackHeaders removeObjectForKey:headerKey]; } } - (NSDictionary *)getHeaders { return [self.stackHeaders copy]; } - (NSString *)imageTransformWithUrl:(NSString *)url andParams:(NSDictionary *)params{ if([url rangeOfString:@"?" options:NSCaseInsensitiveSearch].length==0) { url = [url stringByAppendingString:@"?"]; } for (id key in params) { id value = [params objectForKey:key]; url = [url stringByAppendingString:[NSString stringWithFormat: @"&%@=%@", key, value]]; } url = [url stringByReplacingOccurrencesOfString:@" " withString:@""]; url = [url stringByReplacingOccurrencesOfString:@"?&" withString:@"?"]; return url; } - (void)syncCallWithParams:(NSDictionary*)params withCompletion:(void (^)(NSDictionary *responseDictionary, NSError *error))completionBlock { NSString *path = [CSIOAPIURLs syncWithVersion:self.version]; NSMutableDictionary *paramsDictionary = [NSMutableDictionary dictionaryWithDictionary:params]; NSURLSessionDataTask *op = [self.network requestForStack:self withURLPath:path requestType:CSIOCoreNetworkingRequestTypeGET params:paramsDictionary additionalHeaders:self.stackHeaders completion:^(ResponseType responseType, id responseJSON, NSError *error) { if (completionBlock) { if (error) { completionBlock(nil, error); }else { NSDictionary *responseData = responseJSON; completionBlock(responseData, nil); } } }]; if (op && ![op isKindOfClass:[NSNull class]]) { [self.requestOperationSet addObject:op]; } } -(void)sync:(void (^)(SyncStack * BUILT_NULLABLE_P syncResult, NSError * BUILT_NULLABLE_P error))completionBlock { SyncStack *syncStack = [self getCurrentSyncStack:nil]; [self sync:syncStack completion:^(SyncStack * _Nullable syncResult, NSError * _Nullable error) { completionBlock(syncResult, error); }]; } -(void)syncToken:(NSString *)token completion:(void (^)(SyncStack * BUILT_NULLABLE_P syncResult, NSError * BUILT_NULLABLE_P error))completionBlock { SyncStack *syncStack = [self getCurrentSyncStack:@{@"sync_token": token}]; [self sync:syncStack completion:^(SyncStack * _Nullable syncResult, NSError * _Nullable error) { completionBlock(syncResult, error); }]; } -(void)syncPaginationToken:(NSString *)token completion:(void (^)(SyncStack * BUILT_NULLABLE_P syncResult, NSError * BUILT_NULLABLE_P error))completionBlock { SyncStack *syncStack = [self getCurrentSyncStack:@{@"pagination_token": token}]; [self sync:syncStack completion:^(SyncStack * _Nullable syncResult, NSError * _Nullable error) { completionBlock(syncResult, error); }]; } - (void)syncFrom:(NSDate*)date completion:(void (^)(SyncStack * BUILT_NULLABLE_P syncResult, NSError * BUILT_NULLABLE_P error))completionBlock { SyncStack *syncStack = [self getCurrentSyncStack:@{kCSIO_Start_From : [_commonDateFormatter stringFromDate:date]}]; [self sync:syncStack completion:^(SyncStack * _Nullable syncResult, NSError * _Nullable error) { completionBlock(syncResult, error); }]; } - (void)syncOnly:(NSString *)contentType completion:(void (^)(SyncStack * BUILT_NULLABLE_P syncResult, NSError * BUILT_NULLABLE_P error))completionBlock { SyncStack *syncStack = [self getCurrentSyncStack:@{kCSIO_Content_Type: contentType}]; [self sync:syncStack completion:^(SyncStack * _Nullable syncResult, NSError * _Nullable error) { completionBlock(syncResult, error); }]; } - (void)syncOnly:(NSString *)contentType from:(NSDate *)date completion:(void (^)(SyncStack * BUILT_NULLABLE_P syncResult, NSError * BUILT_NULLABLE_P error))completionBlock { SyncStack *syncStack = [self getCurrentSyncStack:@{kCSIO_Start_From : [_commonDateFormatter stringFromDate:date], kCSIO_Content_Type: contentType}]; [self sync:syncStack completion:^(SyncStack * _Nullable syncResult, NSError * _Nullable error) { completionBlock(syncResult, error); }]; } -(void)syncLocale:(NSString*)locale completion:(void (^)(SyncStack * _Nullable, NSError * _Nullable))completionBlock { SyncStack *syncStack = [self getCurrentSyncStack:@{kCSIO_Locale : locale}]; [self sync:syncStack completion:^(SyncStack * _Nullable syncResult, NSError * _Nullable error) { completionBlock(syncResult, error); }]; } -(void)syncLocale:(NSString*)locale from:(NSDate *)date completion:(void (^)(SyncStack * _Nullable, NSError * _Nullable))completionBlock { SyncStack *syncStack = [self getCurrentSyncStack:@{kCSIO_Locale : locale, kCSIO_Start_From : [_commonDateFormatter stringFromDate:date]}]; [self sync:syncStack completion:^(SyncStack * _Nullable syncResult, NSError * _Nullable error) { completionBlock(syncResult, error); }]; } -(void)syncPublishType:(PublishType)publishType completion:(void (^)(SyncStack * _Nullable, NSError * _Nullable))completionBlock { SyncStack *syncStack = [self getCurrentSyncStack:@{kCSIO_Type : [self publishType:publishType]}]; [self sync:syncStack completion:^(SyncStack * _Nullable syncResult, NSError * _Nullable error) { completionBlock(syncResult, error); }]; } -(void)syncOnly:(NSString *)contentType locale:(NSString*)locale from:(NSDate *)date completion:(void (^)(SyncStack * _Nullable, NSError * _Nullable))completionBlock { NSMutableDictionary *paramsDict = [NSMutableDictionary dictionary]; [paramsDict setValue:contentType forKey:kCSIO_Content_Type]; [paramsDict setValue:locale forKey:kCSIO_Locale]; if (date != nil) { [paramsDict setValue:[_commonDateFormatter stringFromDate:date] forKey:kCSIO_Start_From]; } SyncStack *syncStack = [self getCurrentSyncStack:paramsDict]; [self sync:syncStack completion:^(SyncStack * _Nullable syncResult, NSError * _Nullable error) { completionBlock(syncResult, error); }]; } -(void)syncOnly:(NSString *)contentType locale:(NSString*)locale from:(NSDate *)date publishType:(PublishType)publishType completion:(void (^)(SyncStack * _Nullable, NSError * _Nullable))completionBlock { NSMutableDictionary *paramsDict = [NSMutableDictionary dictionary]; [paramsDict setValue:contentType forKey:kCSIO_Content_Type]; [paramsDict setValue:locale forKey:kCSIO_Locale]; [paramsDict setValue:[self publishType:publishType] forKey:kCSIO_Type]; if (date != nil) { [paramsDict setValue:[_commonDateFormatter stringFromDate:date] forKey:kCSIO_Start_From]; } SyncStack *syncStack = [self getCurrentSyncStack:paramsDict]; [self sync:syncStack completion:^(SyncStack * _Nullable syncResult, NSError * _Nullable error) { completionBlock(syncResult, error); }]; } - (void)sync:(SyncStack *)syncResult completion:(void (^)(SyncStack * BUILT_NULLABLE_P syncResult, NSError * BUILT_NULLABLE_P error))completionBlock { NSMutableDictionary *params = [NSMutableDictionary dictionaryWithDictionary:[syncResult getParameters]]; if (syncResult.paginationToken == nil && syncResult.syncToken == nil) { [params setValue:self.environment forKey:@"environment"]; } [self syncCallWithParams:params withCompletion:^(NSDictionary *responseDictionary, NSError *error) { if (error == nil) { [syncResult parseSyncResult:responseDictionary]; if (syncResult.hasMorePages) { [self sync:syncResult completion:completionBlock]; } } completionBlock(syncResult, error); }]; } - (SyncStack*) getCurrentSyncStack:(NSDictionary*) params { SyncStack *syncResult = [[SyncStack alloc] initWithParmas:params]; return syncResult; } @end