From e8e0916c2ae24ec14130b1dc00f9574d78940462 Mon Sep 17 00:00:00 2001 From: Sebastian Schmidt Date: Wed, 6 Sep 2017 14:37:04 -0700 Subject: Firebase Storage: Allowing metadata to be cleared (#197) * Allowing metadata to be cleared --- Firebase/Storage/FIRStorageMetadata.m | 37 +++++++++++++++++++++- Firebase/Storage/FIRStorageUpdateMetadataTask.m | 2 +- .../Storage/Private/FIRStorageMetadata_Private.h | 20 ++++++++++++ 3 files changed, 57 insertions(+), 2 deletions(-) (limited to 'Firebase/Storage') diff --git a/Firebase/Storage/FIRStorageMetadata.m b/Firebase/Storage/FIRStorageMetadata.m index 4269a45..c4ff5a8 100644 --- a/Firebase/Storage/FIRStorageMetadata.m +++ b/Firebase/Storage/FIRStorageMetadata.m @@ -31,6 +31,8 @@ - (instancetype)initWithDictionary:(NSDictionary *)dictionary { self = [super init]; if (self) { + _initialMetadata = [dictionary copy]; + _bucket = dictionary[kFIRStorageMetadataBucket]; _cacheControl = dictionary[kFIRStorageMetadataCacheControl]; _contentDisposition = dictionary[kFIRStorageMetadataContentDisposition]; @@ -73,7 +75,10 @@ #pragma mark - NSObject overrides - (instancetype)copyWithZone:(NSZone *)zone { - return [[[self class] allocWithZone:zone] initWithDictionary:[self dictionaryRepresentation]]; + FIRStorageMetadata *clone = + [[[self class] allocWithZone:zone] initWithDictionary:[self dictionaryRepresentation]]; + clone.initialMetadata = [self.initialMetadata copy]; + return clone; } - (BOOL)isEqual:(id)object { @@ -200,6 +205,36 @@ return [_downloadURLs firstObject]; } +#pragma mark - Private methods + ++ (void)removeMatchingMetadata:(NSMutableDictionary *)metadata + oldMetadata:(NSDictionary *)oldMetadata { + for (NSString* metadataKey in [oldMetadata allKeys]) { + id oldValue = [oldMetadata objectForKey:metadataKey]; + id newValue = [metadata objectForKey:metadataKey]; + + if (oldValue && !newValue) { + [metadata setObject:[NSNull null] forKey:metadataKey]; + } else if ([oldValue isKindOfClass:[NSString class]] && + [newValue isKindOfClass:[NSString class]]) { + if ([oldValue isEqualToString:newValue]) { + [metadata removeObjectForKey:metadataKey]; + } + } else if ([oldValue isKindOfClass:[NSDictionary class]] && + [newValue isKindOfClass:[NSDictionary class]]) { + NSMutableDictionary *nestedMetadata = [newValue mutableCopy]; + [self removeMatchingMetadata:nestedMetadata oldMetadata:oldValue]; + [metadata setObject:[nestedMetadata copy] forKey:metadataKey]; + } + } +} + +- (NSDictionary *)updatedMetadata { + NSMutableDictionary *metadataUpdate = [[self dictionaryRepresentation] mutableCopy]; + [FIRStorageMetadata removeMatchingMetadata:metadataUpdate oldMetadata:_initialMetadata]; + return [metadataUpdate copy]; +} + #pragma mark - RFC 3339 conversions static NSDateFormatter *sRFC3339DateFormatter; diff --git a/Firebase/Storage/FIRStorageUpdateMetadataTask.m b/Firebase/Storage/FIRStorageUpdateMetadataTask.m index 005f78f..642ebcd 100644 --- a/Firebase/Storage/FIRStorageUpdateMetadataTask.m +++ b/Firebase/Storage/FIRStorageUpdateMetadataTask.m @@ -45,7 +45,7 @@ - (void)enqueue { NSMutableURLRequest *request = [self.baseRequest mutableCopy]; - NSDictionary *updateDictionary = [_updateMetadata dictionaryRepresentation]; + NSDictionary *updateDictionary = [_updateMetadata updatedMetadata]; NSData *updateData = [NSData frs_dataFromJSONDictionary:updateDictionary]; request.HTTPMethod = @"PATCH"; request.timeoutInterval = self.reference.storage.maxUploadRetryTime; diff --git a/Firebase/Storage/Private/FIRStorageMetadata_Private.h b/Firebase/Storage/Private/FIRStorageMetadata_Private.h index 629c935..ad8cc94 100644 --- a/Firebase/Storage/Private/FIRStorageMetadata_Private.h +++ b/Firebase/Storage/Private/FIRStorageMetadata_Private.h @@ -15,6 +15,7 @@ */ #import "FIRStorageConstants_Private.h" +#import "FIRStorageMetadata.h" @class FIRStorageReference; @@ -33,6 +34,25 @@ NS_ASSUME_NONNULL_BEGIN */ @property(readwrite) FIRStorageMetadataType type; +/** + * The original metadata representation received from the server or an empty dictionary + * if the metadata object was initialized by the user. + */ +@property(copy, nonatomic) NSDictionary *initialMetadata; + +/** + * Recursively removes entries in 'metadata' that are unmodified from 'oldMetadata'. + * Adds 'NSNull' for entries that only exist in oldMetadata. + */ ++ (void)removeMatchingMetadata:(NSMutableDictionary *)metadata + oldMetadata:(NSDictionary *)oldMetadata; + +/** + * Computes the updates between the state at initialization and the current state. + * Returns a dictionary with only the updated data. Removed keys are set to NSNull. + */ +- (NSDictionary *)updatedMetadata; + /** * Returns an RFC3339 formatted date from a string. * @param dateString An NSString of the form: yyyy-MM-ddTHH:mm:ss.SSSZ. -- cgit v1.2.3