Commit 726b6580 by Dima Bart

Merge pull request #220 from Shopify/task/status-aggregate

Add internal API for aggregate checkout status operation
parents e7632aba fff851b0
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#import "BUYClient+Routing.h" #import "BUYClient+Routing.h"
#import "BUYRequestOperation.h" #import "BUYRequestOperation.h"
#import "BUYCheckoutOperation.h" #import "BUYCheckoutOperation.h"
#import "BUYStatusOperation.h"
#import "BUYAddress.h" #import "BUYAddress.h"
#import "BUYCheckout.h" #import "BUYCheckout.h"
#import "BUYGiftCard.h" #import "BUYGiftCard.h"
...@@ -104,7 +105,7 @@ ...@@ -104,7 +105,7 @@
- (BUYOperation *)completeCheckoutWithToken:(NSString *)checkoutToken paymentToken:(id<BUYPaymentToken>)paymentToken completion:(BUYDataCheckoutBlock)block - (BUYOperation *)completeCheckoutWithToken:(NSString *)checkoutToken paymentToken:(id<BUYPaymentToken>)paymentToken completion:(BUYDataCheckoutBlock)block
{ {
BUYCheckoutOperation *operation = [[BUYCheckoutOperation alloc] initWithClient:self checkoutToken:checkoutToken token:paymentToken completion:block]; BUYCheckoutOperation *operation = [BUYCheckoutOperation operationWithClient:self checkoutToken:checkoutToken token:paymentToken completion:block];
[self startOperation:operation]; [self startOperation:operation];
return operation; return operation;
} }
...@@ -152,6 +153,15 @@ ...@@ -152,6 +153,15 @@
}]; }];
} }
- (NSOperation *)pollCompletionStatusAndGetCheckoutWithToken:(NSString *)token start:(BOOL)start completion:(BUYDataCheckoutBlock)block
{
BUYStatusOperation *operation = [BUYStatusOperation operationWithClient:self checkoutToken:token completion:block];
if (start) {
[self startOperation:operation];
}
return operation;
}
- (NSOperation *)postCheckout:(NSDictionary *)checkoutJSON completion:(BUYDataCheckoutBlock)block - (NSOperation *)postCheckout:(NSDictionary *)checkoutJSON completion:(BUYDataCheckoutBlock)block
{ {
return [self postRequestForURL:[self urlForCheckouts] object:checkoutJSON completionHandler:^(NSDictionary *json, NSHTTPURLResponse *response, NSError *error) { return [self postRequestForURL:[self urlForCheckouts] object:checkoutJSON completionHandler:^(NSDictionary *json, NSHTTPURLResponse *response, NSError *error) {
......
...@@ -35,6 +35,10 @@ typedef void (^BUYClientRequestJSONCompletion)(NSDictionary *json, NSHTTPURLResp ...@@ -35,6 +35,10 @@ typedef void (^BUYClientRequestJSONCompletion)(NSDictionary *json, NSHTTPURLResp
@interface BUYClient (Internal) @interface BUYClient (Internal)
@property (nonatomic, strong) NSOperationQueue *requestQueue;
- (NSOperation *)pollCompletionStatusAndGetCheckoutWithToken:(NSString *)token start:(BOOL)start completion:(BUYDataCheckoutBlock)block;
- (NSOperation *)getRequestForURL:(NSURL *)url completionHandler:(BUYClientRequestJSONCompletion)completionHandler; - (NSOperation *)getRequestForURL:(NSURL *)url completionHandler:(BUYClientRequestJSONCompletion)completionHandler;
- (NSOperation *)deleteRequestForURL:(NSURL *)url completionHandler:(BUYClientRequestJSONCompletion)completionHandler; - (NSOperation *)deleteRequestForURL:(NSURL *)url completionHandler:(BUYClientRequestJSONCompletion)completionHandler;
......
...@@ -24,7 +24,8 @@ ...@@ -24,7 +24,8 @@
// THE SOFTWARE. // THE SOFTWARE.
// //
#import <Buy/BUYOperation.h> #import <Buy/BUYGroupOperation.h>
#import <Buy/BUYStatusOperation.h>
NS_ASSUME_NONNULL_BEGIN NS_ASSUME_NONNULL_BEGIN
@class BUYClient; @class BUYClient;
...@@ -32,11 +33,7 @@ NS_ASSUME_NONNULL_BEGIN ...@@ -32,11 +33,7 @@ NS_ASSUME_NONNULL_BEGIN
@protocol BUYPaymentToken; @protocol BUYPaymentToken;
typedef void (^BUYCheckoutOperationCompletion)(BUYCheckout * _Nullable checkout, NSError * _Nullable error); @interface BUYCheckoutOperation : BUYGroupOperation
@interface BUYCheckoutOperation : BUYOperation
@property (strong, nonatomic, readonly, nonnull) BUYClient *client;
+ (instancetype)operationWithClient:(BUYClient *)client checkoutToken:(NSString *)checkoutToken token:(id<BUYPaymentToken>)token completion:(BUYCheckoutOperationCompletion)completion; + (instancetype)operationWithClient:(BUYClient *)client checkoutToken:(NSString *)checkoutToken token:(id<BUYPaymentToken>)token completion:(BUYCheckoutOperationCompletion)completion;
- (instancetype)initWithClient:(BUYClient *)client checkoutToken:(NSString *)checkoutToken token:(id<BUYPaymentToken>)token completion:(BUYCheckoutOperationCompletion)completion; - (instancetype)initWithClient:(BUYClient *)client checkoutToken:(NSString *)checkoutToken token:(id<BUYPaymentToken>)token completion:(BUYCheckoutOperationCompletion)completion;
......
...@@ -29,15 +29,15 @@ ...@@ -29,15 +29,15 @@
#import "BUYClient+Internal.h" #import "BUYClient+Internal.h"
#import "BUYPaymentToken.h" #import "BUYPaymentToken.h"
#import "BUYRequestOperation.h" #import "BUYRequestOperation.h"
#import "BUYStatusOperation.h"
@interface BUYCheckoutOperation () @interface BUYCheckoutOperation ()
@property (strong, nonatomic, readonly) BUYClient *client;
@property (strong, nonatomic, readonly) NSString *checkoutToken; @property (strong, nonatomic, readonly) NSString *checkoutToken;
@property (strong, nonatomic, readonly) id<BUYPaymentToken> token; @property (strong, nonatomic, readonly) id<BUYPaymentToken> token;
@property (strong, nonatomic, readonly) BUYCheckoutOperationCompletion completion; @property (strong, nonatomic, readonly) BUYCheckoutOperationCompletion completion;
@property (strong, atomic) NSArray *operations;
@end @end
@implementation BUYCheckoutOperation @implementation BUYCheckoutOperation
...@@ -51,7 +51,7 @@ ...@@ -51,7 +51,7 @@
- (instancetype)initWithClient:(BUYClient *)client checkoutToken:(NSString *)checkoutToken token:(id<BUYPaymentToken>)token completion:(BUYCheckoutOperationCompletion)completion - (instancetype)initWithClient:(BUYClient *)client checkoutToken:(NSString *)checkoutToken token:(id<BUYPaymentToken>)token completion:(BUYCheckoutOperationCompletion)completion
{ {
self = [super init]; self = [super initWithRequestQueue:client.requestQueue operations:nil];
if (self) { if (self) {
_client = client; _client = client;
_token = token; _token = token;
...@@ -63,25 +63,23 @@ ...@@ -63,25 +63,23 @@
#pragma mark - Finishing - #pragma mark - Finishing -
- (void)finishWithCheckout:(BUYCheckout *)checkout - (void)finishWithObject:(id)object
{ {
[super finishWithObject:object];
if (self.cancelled) { if (self.cancelled) {
return; return;
} }
self.completion(object, nil);
[self finishExecution];
self.completion(checkout, nil);
} }
- (void)finishWithError:(NSError *)error - (void)finishWithError:(NSError *)error
{ {
[super finishWithError:error];
if (self.cancelled) { if (self.cancelled) {
return; return;
} }
[self cancelAllOperations];
[self finishExecution];
self.completion(nil, error); self.completion(nil, error);
} }
...@@ -93,44 +91,12 @@ ...@@ -93,44 +91,12 @@
return; return;
} }
[super startExecution];
NSOperation *beginOperation = [self createBeginOperation];
NSOperation *pollOperation = [self createPollOperation];
NSOperation *getOperation = [self createGetOperation];
[pollOperation addDependency:beginOperation];
[getOperation addDependency:pollOperation];
self.operations = @[ self.operations = @[
beginOperation, [self createBeginOperation],
pollOperation, [self createStatusOperation],
getOperation,
]; ];
[self startAllOperations]; [super startExecution];
}
- (void)cancelExecution
{
[super cancelExecution];
[self cancelAllOperations];
}
#pragma mark - Start / Stop -
- (void)startAllOperations
{
for (BUYRequestOperation *operation in self.operations) {
[self.client startOperation:operation];
}
}
- (void)cancelAllOperations
{
for (BUYRequestOperation *operation in self.operations) {
[operation cancel];
}
} }
#pragma mark - Operations - #pragma mark - Operations -
...@@ -144,25 +110,11 @@ ...@@ -144,25 +110,11 @@
}]; }];
} }
- (NSOperation *)createPollOperation - (NSOperation *)createStatusOperation
{
BUYRequestOperation *operation = (BUYRequestOperation *)[self.client getCompletionStatusOfCheckoutWithToken:self.checkoutToken start:NO completion:^(BUYStatus status, NSError *error) {
if (status != BUYStatusComplete) {
[self finishWithError:error];
}
}];
operation.pollingHandler = ^BOOL (NSDictionary *json, NSHTTPURLResponse *response, NSError *error) {
return response.statusCode == BUYStatusProcessing;
};
return operation;
}
- (NSOperation *)createGetOperation
{ {
return [self.client getCheckoutWithToken:self.checkoutToken start:NO completion:^(BUYCheckout *checkout, NSError *error) { return [self.client pollCompletionStatusAndGetCheckoutWithToken:self.checkoutToken start:NO completion:^(BUYCheckout *checkout, NSError *error) {
if (checkout) { if (checkout) {
[self finishWithCheckout:checkout]; [self finishWithObject:checkout];
} else { } else {
[self finishWithError:error]; [self finishWithError:error];
} }
......
//
// BUYGroupOperation.h
// Mobile Buy SDK
//
// Created by Shopify.
// Copyright (c) 2015 Shopify Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#import "BUYOperation.h"
@interface BUYGroupOperation : BUYOperation
@property (strong, atomic) NSArray<NSOperation *> *operations;
+ (instancetype)groupOperationWithRequestQueue:(NSOperationQueue *)queue operations:(NSArray<NSOperation *> *)operations;
- (instancetype)initWithRequestQueue:(NSOperationQueue *)queue operations:(NSArray<NSOperation *> *)operations;
- (void)finishWithObject:(id)object;
- (void)finishWithError:(NSError *)error;
@end
//
// BUYGroupOperation.m
// Mobile Buy SDK
//
// Created by Shopify.
// Copyright (c) 2015 Shopify Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#import "BUYGroupOperation.h"
#import "NSArray+BUYAdditions.h"
@interface BUYGroupOperation ()
@property (weak, nonatomic) NSOperationQueue *queue;
@end
@implementation BUYGroupOperation
#pragma mark - Init -
+ (instancetype)groupOperationWithRequestQueue:(NSOperationQueue *)queue operations:(NSArray<NSOperation *> *)operations
{
return [[[self class] alloc] initWithRequestQueue:queue operations:operations];
}
- (instancetype)initWithRequestQueue:(NSOperationQueue *)queue operations:(NSArray<NSOperation *> *)operations
{
self = [super init];
if (self) {
_queue = queue;
self.operations = operations;
}
return self;
}
#pragma mark - Finishing -
- (void)finishWithObject:(id)object
{
if (self.cancelled) {
return;
}
[self finishExecution];
}
- (void)finishWithError:(NSError *)error
{
if (self.cancelled) {
return;
}
[self cancelAllOperations];
[self finishExecution];
}
#pragma mark - Execution -
- (void)startExecution
{
if (self.cancelled) {
return;
}
[super startExecution];
[self linkDependencies];
[self startAllOperations];
}
- (void)cancelExecution
{
[super cancelExecution];
[self cancelAllOperations];
}
#pragma mark - Dependencies -
- (void)linkDependencies
{
NSArray *tail = [self.operations buy_tail];
if (tail.count > 0) {
NSOperation *former = self.operations.firstObject;
for (NSOperation *latter in tail) {
[latter addDependency:former];
former = latter;
}
}
}
#pragma mark - Start / Stop -
- (void)startAllOperations
{
for (NSOperation *operation in self.operations) {
[self.queue addOperation:operation];
}
}
- (void)cancelAllOperations
{
for (NSOperation *operation in self.operations) {
[operation cancel];
}
}
@end
//
// BUYStatusOperation.h
// Mobile Buy SDK
//
// Created by Shopify.
// Copyright (c) 2015 Shopify Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#import "BUYGroupOperation.h"
NS_ASSUME_NONNULL_BEGIN
@class BUYCheckout;
@class BUYClient;
typedef void (^BUYCheckoutOperationCompletion)(BUYCheckout * _Nullable checkout, NSError * _Nullable error);
@interface BUYStatusOperation : BUYGroupOperation
+ (instancetype)operationWithClient:(BUYClient *)client checkoutToken:(NSString *)checkoutToken completion:(BUYCheckoutOperationCompletion)completion;
- (instancetype)initWithClient:(BUYClient *)client checkoutToken:(NSString *)checkoutToken completion:(BUYCheckoutOperationCompletion)completion;
@end
NS_ASSUME_NONNULL_END
//
// BUYStatusOperation.m
// Mobile Buy SDK
//
// Created by Shopify.
// Copyright (c) 2015 Shopify Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#import "BUYStatusOperation.h"
#import "BUYClient+Checkout.h"
#import "BUYClient+Internal.h"
#import "BUYRequestOperation.h"
@interface BUYStatusOperation ()
@property (strong, nonatomic, readonly) BUYClient *client;
@property (strong, nonatomic, readonly) NSString *checkoutToken;
@property (strong, nonatomic, readonly) BUYCheckoutOperationCompletion completion;
@end
@implementation BUYStatusOperation
#pragma mark - Init -
+ (instancetype)operationWithClient:(BUYClient *)client checkoutToken:(NSString *)checkoutToken completion:(BUYCheckoutOperationCompletion)completion
{
return [[[self class] alloc] initWithClient:client checkoutToken:checkoutToken completion:completion];
}
- (instancetype)initWithClient:(BUYClient *)client checkoutToken:(NSString *)checkoutToken completion:(BUYCheckoutOperationCompletion)completion
{
self = [super initWithRequestQueue:client.requestQueue operations:nil];
if (self) {
_client = client;
_completion = completion;
_checkoutToken = checkoutToken;
}
return self;
}
#pragma mark - Execution -
- (void)startExecution
{
if (self.cancelled) {
return;
}
self.operations = @[
[self createPollOperation],
[self createGetOperation],
];
[super startExecution];
}
#pragma mark - Finishing -
- (void)finishWithObject:(id)object
{
[super finishWithObject:object];
if (self.cancelled) {
return;
}
self.completion(object, nil);
}
- (void)finishWithError:(NSError *)error
{
[super finishWithError:error];
if (self.cancelled) {
return;
}
self.completion(nil, error);
}
#pragma mark - Operations -
- (NSOperation *)createPollOperation
{
BUYRequestOperation *operation = (BUYRequestOperation *)[self.client getCompletionStatusOfCheckoutWithToken:self.checkoutToken start:NO completion:^(BUYStatus status, NSError *error) {
if (status != BUYStatusComplete) {
[self finishWithError:error];
}
}];
operation.pollingHandler = ^BOOL (NSDictionary *json, NSHTTPURLResponse *response, NSError *error) {
return response.statusCode == BUYStatusProcessing;
};
return operation;
}
- (NSOperation *)createGetOperation
{
return [self.client getCheckoutWithToken:self.checkoutToken start:NO completion:^(BUYCheckout *checkout, NSError *error) {
if (checkout) {
[self finishWithObject:checkout];
} else {
[self finishWithError:error];
}
}];
}
@end
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment