react-native-firebase/ios/RNFirebase/database/RNFirebaseDatabaseReference.m

218 lines
9.0 KiB
Objective-C

#import "RNFirebaseDatabaseReference.h"
@implementation RNFirebaseDatabaseReference
#if __has_include(<FirebaseDatabase/FIRDatabase.h>)
- (id)initWithPathAndModifiers:(RCTEventEmitter *)emitter
appDisplayName:(NSString *)appDisplayName
key:(NSString *)key
refPath:(NSString *)refPath
modifiers:(NSArray *)modifiers {
self = [super init];
if (self) {
_emitter = emitter;
_appDisplayName = appDisplayName;
_key = key;
_path = refPath;
_listeners = [[NSMutableDictionary alloc] init];
_query = [self buildQueryAtPathWithModifiers:refPath modifiers:modifiers];
}
return self;
}
- (void)removeEventListener:(NSString *)eventRegistrationKey {
FIRDatabaseHandle handle = (FIRDatabaseHandle)[_listeners[eventRegistrationKey] integerValue];
if (handle) {
[_query removeObserverWithHandle:handle];
[_listeners removeObjectForKey:eventRegistrationKey];
}
}
- (void)on:(NSString *)eventType registration:(NSDictionary *)registration {
NSString *eventRegistrationKey = registration[@"eventRegistrationKey"];
if (![self hasEventListener:eventRegistrationKey]) {
id andPreviousSiblingKeyWithBlock = ^(FIRDataSnapshot *_Nonnull snapshot, NSString *_Nullable previousChildName) {
[self handleDatabaseEvent:eventType registration:registration dataSnapshot:snapshot previousChildName:previousChildName];
};
id errorBlock = ^(NSError *_Nonnull error) {
NSLog(@"Error onDBEvent: %@", [error debugDescription]);
[self removeEventListener:eventRegistrationKey];
[self handleDatabaseError:registration error:error];
};
FIRDataEventType firDataEventType = (FIRDataEventType)[self eventTypeFromName:eventType];
FIRDatabaseHandle handle = [_query observeEventType:firDataEventType andPreviousSiblingKeyWithBlock:andPreviousSiblingKeyWithBlock withCancelBlock:errorBlock];
_listeners[eventRegistrationKey] = @(handle);
}
}
- (void)once:(NSString *)eventType
resolver:(RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject {
FIRDataEventType firDataEventType = (FIRDataEventType)[self eventTypeFromName:eventType];
[_query observeSingleEventOfType:firDataEventType andPreviousSiblingKeyWithBlock:^(FIRDataSnapshot *_Nonnull snapshot, NSString *_Nullable previousChildName) {
NSDictionary *data = [RNFirebaseDatabaseReference snapshotToDictionary:snapshot previousChildName:previousChildName];
resolve(data);
} withCancelBlock:^(NSError *_Nonnull error) {
NSLog(@"Error onDBEventOnce: %@", [error debugDescription]);
[RNFirebaseDatabase handlePromise:resolve rejecter:reject databaseError:error];
}];
}
- (void)handleDatabaseEvent:(NSString *)eventType
registration:(NSDictionary *)registration
dataSnapshot:(FIRDataSnapshot *)dataSnapshot
previousChildName:(NSString *)previousChildName {
NSMutableDictionary *event = [[NSMutableDictionary alloc] init];
NSDictionary *data = [RNFirebaseDatabaseReference snapshotToDictionary:dataSnapshot previousChildName:previousChildName];
[event setValue:data forKey:@"data"];
[event setValue:_key forKey:@"key"];
[event setValue:eventType forKey:@"eventType"];
[event setValue:registration forKey:@"registration"];
[RNFirebaseUtil sendJSEvent:self.emitter name:DATABASE_SYNC_EVENT body:event];
}
- (void)handleDatabaseError:(NSDictionary *)registration
error:(NSError *)error {
NSMutableDictionary *event = [[NSMutableDictionary alloc] init];
[event setValue:_key forKey:@"key"];
[event setValue:[RNFirebaseDatabase getJSError:error] forKey:@"error"];
[event setValue:registration forKey:@"registration"];
[RNFirebaseUtil sendJSEvent:self.emitter name:DATABASE_SYNC_EVENT body:event];
}
+ (NSDictionary *)snapshotToDictionary:(FIRDataSnapshot *)dataSnapshot
previousChildName:(NSString *)previousChildName {
NSMutableDictionary *result = [[NSMutableDictionary alloc] init];
NSDictionary *snapshot = [RNFirebaseDatabaseReference snapshotToDict:dataSnapshot];
[result setValue:snapshot forKey:@"snapshot"];
[result setValue:previousChildName forKey:@"previousChildName"];
return result;
}
+ (NSDictionary *)snapshotToDict:(FIRDataSnapshot *)dataSnapshot {
NSMutableDictionary *snapshot = [[NSMutableDictionary alloc] init];
[snapshot setValue:dataSnapshot.key forKey:@"key"];
[snapshot setValue:@(dataSnapshot.exists) forKey:@"exists"];
[snapshot setValue:@(dataSnapshot.hasChildren) forKey:@"hasChildren"];
[snapshot setValue:@(dataSnapshot.childrenCount) forKey:@"childrenCount"];
[snapshot setValue:[RNFirebaseDatabaseReference getChildKeys:dataSnapshot] forKey:@"childKeys"];
[snapshot setValue:dataSnapshot.priority forKey:@"priority"];
[snapshot setValue:dataSnapshot.value forKey:@"value"];
return snapshot;
}
+ (NSMutableArray *)getChildKeys:(FIRDataSnapshot *)snapshot {
NSMutableArray *childKeys = [NSMutableArray array];
if (snapshot.childrenCount > 0) {
NSEnumerator *children = [snapshot children];
FIRDataSnapshot *child;
while (child = [children nextObject]) {
[childKeys addObject:child.key];
}
}
return childKeys;
}
- (FIRDatabaseQuery *)buildQueryAtPathWithModifiers:(NSString *)path
modifiers:(NSArray *)modifiers {
FIRDatabase *firebaseDatabase = [RNFirebaseDatabase getDatabaseForApp:_appDisplayName];
FIRDatabaseQuery *query = [[firebaseDatabase reference] child:path];
for (NSDictionary *modifier in modifiers) {
NSString *type = [modifier valueForKey:@"type"];
NSString *name = [modifier valueForKey:@"name"];
if ([type isEqualToString:@"orderBy"]) {
if ([name isEqualToString:@"orderByKey"]) {
query = [query queryOrderedByKey];
} else if ([name isEqualToString:@"orderByPriority"]) {
query = [query queryOrderedByPriority];
} else if ([name isEqualToString:@"orderByValue"]) {
query = [query queryOrderedByValue];
} else if ([name isEqualToString:@"orderByChild"]) {
NSString *key = [modifier valueForKey:@"key"];
query = [query queryOrderedByChild:key];
}
} else if ([type isEqualToString:@"limit"]) {
int limit = [[modifier valueForKey:@"limit"] integerValue];
if ([name isEqualToString:@"limitToLast"]) {
query = [query queryLimitedToLast:limit];
} else if ([name isEqualToString:@"limitToFirst"]) {
query = [query queryLimitedToFirst:limit];
}
} else if ([type isEqualToString:@"filter"]) {
NSString *valueType = [modifier valueForKey:@"valueType"];
NSString *key = [modifier valueForKey:@"key"];
id value = [self getIdValue:[modifier valueForKey:@"value"] type:valueType];
if ([name isEqualToString:@"equalTo"]) {
if (key != nil) {
query = [query queryEqualToValue:value childKey:key];
} else {
query = [query queryEqualToValue:value];
}
} else if ([name isEqualToString:@"endAt"]) {
if (key != nil) {
query = [query queryEndingAtValue:value childKey:key];
} else {
query = [query queryEndingAtValue:value];
}
} else if ([name isEqualToString:@"startAt"]) {
if (key != nil) {
query = [query queryStartingAtValue:value childKey:key];
} else {
query = [query queryStartingAtValue:value];
}
}
}
}
return query;
}
- (id)getIdValue:(NSString *)value type:(NSString *)type {
if ([type isEqualToString:@"number"]) {
return @(value.doubleValue);
} else if ([type isEqualToString:@"boolean"]) {
return @(value.boolValue);
} else {
return value;
}
}
- (BOOL)hasEventListener:(NSString *)eventRegistrationKey {
return _listeners[eventRegistrationKey] != nil;
}
- (BOOL)hasListeners {
return [[_listeners allKeys] count] > 0;
}
- (int)eventTypeFromName:(NSString *)name {
int eventType = FIRDataEventTypeValue;
if ([name isEqualToString:DATABASE_VALUE_EVENT]) {
eventType = FIRDataEventTypeValue;
} else if ([name isEqualToString:DATABASE_CHILD_ADDED_EVENT]) {
eventType = FIRDataEventTypeChildAdded;
} else if ([name isEqualToString:DATABASE_CHILD_MODIFIED_EVENT]) {
eventType = FIRDataEventTypeChildChanged;
} else if ([name isEqualToString:DATABASE_CHILD_REMOVED_EVENT]) {
eventType = FIRDataEventTypeChildRemoved;
} else if ([name isEqualToString:DATABASE_CHILD_MOVED_EVENT]) {
eventType = FIRDataEventTypeChildMoved;
}
return eventType;
}
#endif
@end