Mhurd has submitted this change and it was merged. Change subject: Old->new data importer ......................................................................
Old->new data importer Notes on OldDataSchema: * need -ObjC link option to not filter out 'unused' classes :P this can probably be removed if classes are marked used other ways * separate OldDataSchemaBundle.bundle used to get the Core Data object definition into the app, this can be removed if switch to a framework bundle in iOS 8-only future? Still left to do in future: * progress indicator * fix or remove broken code for conversion from PhoneGap app Change-Id: I7234f714b7c368da09b8a63295c623394dfbc70a --- M MediaWikiKit/MediaWikiKit/MWKUserDataStore.h M MediaWikiKit/MediaWikiKit/MWKUserDataStore.m M OldDataSchema/Categories/Article+Convenience.h M OldDataSchema/Data/ArticleDataContextSingleton.m M OldDataSchema/Data/Model/ArticleCoreDataObjects.h M OldDataSchema/OldDataSchema.xcodeproj/project.pbxproj M OldDataSchema/OldDataSchema/OldDataSchema.h M OldDataSchema/OldDataSchema/OldDataSchema.m A OldDataSchema/OldDataSchemaBundle/Info.plist M Wikipedia.xcodeproj/project.pbxproj M Wikipedia.xcodeproj/xcshareddata/xcschemes/Wikipedia-iOS.xcscheme R wikipedia/Data/DataMigrator.h R wikipedia/Data/DataMigrator.m R wikipedia/Data/SQLiteHelper.h R wikipedia/Data/SQLiteHelper.m A wikipedia/Data/SchemaConverter.h A wikipedia/Data/SchemaConverter.m M wikipedia/View Controllers/WebView/WebViewController.m 18 files changed, 642 insertions(+), 15 deletions(-) Approvals: Mhurd: Verified; Looks good to me, approved diff --git a/MediaWikiKit/MediaWikiKit/MWKUserDataStore.h b/MediaWikiKit/MediaWikiKit/MWKUserDataStore.h index b245b04..eccae62 100644 --- a/MediaWikiKit/MediaWikiKit/MWKUserDataStore.h +++ b/MediaWikiKit/MediaWikiKit/MWKUserDataStore.h @@ -23,6 +23,7 @@ -(instancetype)initWithDataStore:(MWKDataStore *)dataStore; -(void)save; +-(void)reset; -(void)updateHistory:(MWKTitle *)title discoveryMethod:(MWKHistoryDiscoveryMethod)discoveryMethod; -(void)savePage:(MWKTitle *)title; diff --git a/MediaWikiKit/MediaWikiKit/MWKUserDataStore.m b/MediaWikiKit/MediaWikiKit/MWKUserDataStore.m index 7e0e440..85eb80b 100644 --- a/MediaWikiKit/MediaWikiKit/MWKUserDataStore.m +++ b/MediaWikiKit/MediaWikiKit/MWKUserDataStore.m @@ -27,6 +27,14 @@ } } +/// Clear out any currently loaded data and force it to be reloaded on next use +-(void)reset +{ + _historyList = nil; + _savedPageList = nil; + _recentSearchList = nil; +} + -(instancetype)initWithDataStore:(MWKDataStore *)dataStore { self = [self init]; diff --git a/OldDataSchema/Categories/Article+Convenience.h b/OldDataSchema/Categories/Article+Convenience.h index 4c6a86f..2f732af 100644 --- a/OldDataSchema/Categories/Article+Convenience.h +++ b/OldDataSchema/Categories/Article+Convenience.h @@ -1,6 +1,8 @@ // Created by Monte Hurd on 12/23/13. // Copyright (c) 2013 Wikimedia Foundation. Provided under MIT-style license; please copy and modify! +#import "UIKit/UIKit.h" + #import "Article.h" @interface Article (Convenience) diff --git a/OldDataSchema/Data/ArticleDataContextSingleton.m b/OldDataSchema/Data/ArticleDataContextSingleton.m index de5091d..ca49ef0 100644 --- a/OldDataSchema/Data/ArticleDataContextSingleton.m +++ b/OldDataSchema/Data/ArticleDataContextSingleton.m @@ -49,7 +49,9 @@ // Setup the masterContext and attach the persistant store to it. self.masterContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; - NSManagedObjectModel *managedObjectModel = [NSManagedObjectModel mergedModelFromBundles:nil]; + NSString *bundlePath = [[NSBundle mainBundle] pathForResource:@"OldDataSchemaBundle" ofType:@"bundle"]; + NSBundle *bundle = [NSBundle bundleWithPath:bundlePath]; + NSManagedObjectModel *managedObjectModel = [NSManagedObjectModel mergedModelFromBundles:@[bundle]]; NSPersistentStoreCoordinator *persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:managedObjectModel]; NSString *articlesDBPath = [[self documentRootPath] stringByAppendingString:@"/articleData6.sqlite"]; diff --git a/OldDataSchema/Data/Model/ArticleCoreDataObjects.h b/OldDataSchema/Data/Model/ArticleCoreDataObjects.h index 7ae506b..c7cda9b 100644 --- a/OldDataSchema/Data/Model/ArticleCoreDataObjects.h +++ b/OldDataSchema/Data/Model/ArticleCoreDataObjects.h @@ -1,6 +1,6 @@ #import <CoreData/CoreData.h> -//#import "Article+Convenience.h" +#import "Article+Convenience.h" #import "DiscoveryContext.h" #import "Section.h" #import "History.h" diff --git a/OldDataSchema/OldDataSchema.xcodeproj/project.pbxproj b/OldDataSchema/OldDataSchema.xcodeproj/project.pbxproj index a663d97..2562281 100644 --- a/OldDataSchema/OldDataSchema.xcodeproj/project.pbxproj +++ b/OldDataSchema/OldDataSchema.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + D4E6D9111A5C65C0004916C1 /* ArticleData.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = D4F478531A48CE0100D8043C /* ArticleData.xcdatamodeld */; }; D4F4782E1A48CD8500D8043C /* OldDataSchema.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D4F4782D1A48CD8500D8043C /* OldDataSchema.h */; }; D4F478301A48CD8500D8043C /* OldDataSchema.m in Sources */ = {isa = PBXBuildFile; fileRef = D4F4782F1A48CD8500D8043C /* OldDataSchema.m */; }; D4F478661A48CE0200D8043C /* ArticleDataContextSingleton.m in Sources */ = {isa = PBXBuildFile; fileRef = D4F4784E1A48CE0100D8043C /* ArticleDataContextSingleton.m */; }; @@ -36,6 +37,8 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + D4E6D90A1A5C65B5004916C1 /* OldDataSchemaBundle.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = OldDataSchemaBundle.bundle; sourceTree = BUILT_PRODUCTS_DIR; }; + D4E6D90D1A5C65B5004916C1 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; D4F4782A1A48CD8500D8043C /* libOldDataSchema.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libOldDataSchema.a; sourceTree = BUILT_PRODUCTS_DIR; }; D4F4782D1A48CD8500D8043C /* OldDataSchema.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OldDataSchema.h; sourceTree = "<group>"; }; D4F4782F1A48CD8500D8043C /* OldDataSchema.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OldDataSchema.m; sourceTree = "<group>"; }; @@ -69,6 +72,13 @@ /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ + D4E6D9071A5C65B5004916C1 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; D4F478271A48CD8500D8043C /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; @@ -79,10 +89,27 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + D4E6D90B1A5C65B5004916C1 /* OldDataSchemaBundle */ = { + isa = PBXGroup; + children = ( + D4E6D90C1A5C65B5004916C1 /* Supporting Files */, + ); + path = OldDataSchemaBundle; + sourceTree = "<group>"; + }; + D4E6D90C1A5C65B5004916C1 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + D4E6D90D1A5C65B5004916C1 /* Info.plist */, + ); + name = "Supporting Files"; + sourceTree = "<group>"; + }; D4F478211A48CD8500D8043C = { isa = PBXGroup; children = ( D4F4782C1A48CD8500D8043C /* OldDataSchema */, + D4E6D90B1A5C65B5004916C1 /* OldDataSchemaBundle */, D4F4782B1A48CD8500D8043C /* Products */, ); sourceTree = "<group>"; @@ -91,6 +118,7 @@ isa = PBXGroup; children = ( D4F4782A1A48CD8500D8043C /* libOldDataSchema.a */, + D4E6D90A1A5C65B5004916C1 /* OldDataSchemaBundle.bundle */, ); name = Products; sourceTree = "<group>"; @@ -150,6 +178,23 @@ /* End PBXGroup section */ /* Begin PBXNativeTarget section */ + D4E6D9091A5C65B5004916C1 /* OldDataSchemaBundle */ = { + isa = PBXNativeTarget; + buildConfigurationList = D4E6D9101A5C65B5004916C1 /* Build configuration list for PBXNativeTarget "OldDataSchemaBundle" */; + buildPhases = ( + D4E6D9061A5C65B5004916C1 /* Sources */, + D4E6D9071A5C65B5004916C1 /* Frameworks */, + D4E6D9081A5C65B5004916C1 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = OldDataSchemaBundle; + productName = OldDataSchemaBundle; + productReference = D4E6D90A1A5C65B5004916C1 /* OldDataSchemaBundle.bundle */; + productType = "com.apple.product-type.bundle"; + }; D4F478291A48CD8500D8043C /* OldDataSchema */ = { isa = PBXNativeTarget; buildConfigurationList = D4F4783E1A48CD8500D8043C /* Build configuration list for PBXNativeTarget "OldDataSchema" */; @@ -176,6 +221,9 @@ LastUpgradeCheck = 0610; ORGANIZATIONNAME = "Wikimedia Foundation"; TargetAttributes = { + D4E6D9091A5C65B5004916C1 = { + CreatedOnToolsVersion = 6.1.1; + }; D4F478291A48CD8500D8043C = { CreatedOnToolsVersion = 6.1.1; }; @@ -194,11 +242,30 @@ projectRoot = ""; targets = ( D4F478291A48CD8500D8043C /* OldDataSchema */, + D4E6D9091A5C65B5004916C1 /* OldDataSchemaBundle */, ); }; /* End PBXProject section */ +/* Begin PBXResourcesBuildPhase section */ + D4E6D9081A5C65B5004916C1 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + /* Begin PBXSourcesBuildPhase section */ + D4E6D9061A5C65B5004916C1 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + D4E6D9111A5C65C0004916C1 /* ArticleData.xcdatamodeld in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; D4F478261A48CD8500D8043C /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -221,6 +288,39 @@ /* End PBXSourcesBuildPhase section */ /* Begin XCBuildConfiguration section */ + D4E6D90E1A5C65B5004916C1 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + INFOPLIST_FILE = OldDataSchemaBundle/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Bundles"; + MACOSX_DEPLOYMENT_TARGET = 10.10; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + WRAPPER_EXTENSION = bundle; + }; + name = Debug; + }; + D4E6D90F1A5C65B5004916C1 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + INFOPLIST_FILE = OldDataSchemaBundle/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Bundles"; + MACOSX_DEPLOYMENT_TARGET = 10.10; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + WRAPPER_EXTENSION = bundle; + }; + name = Release; + }; D4F4783C1A48CD8500D8043C /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { @@ -254,6 +354,10 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, + ); IPHONEOS_DEPLOYMENT_TARGET = 8.1; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; @@ -288,6 +392,10 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, + ); IPHONEOS_DEPLOYMENT_TARGET = 8.1; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; @@ -316,6 +424,14 @@ /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ + D4E6D9101A5C65B5004916C1 /* Build configuration list for PBXNativeTarget "OldDataSchemaBundle" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D4E6D90E1A5C65B5004916C1 /* Debug */, + D4E6D90F1A5C65B5004916C1 /* Release */, + ); + defaultConfigurationIsVisible = 0; + }; D4F478251A48CD8500D8043C /* Build configuration list for PBXProject "OldDataSchema" */ = { isa = XCConfigurationList; buildConfigurations = ( diff --git a/OldDataSchema/OldDataSchema/OldDataSchema.h b/OldDataSchema/OldDataSchema/OldDataSchema.h index 77b5aa2..c74a4aa 100644 --- a/OldDataSchema/OldDataSchema/OldDataSchema.h +++ b/OldDataSchema/OldDataSchema/OldDataSchema.h @@ -14,6 +14,7 @@ @protocol OldDataSchemaDelegate -(void)oldDataSchema:(OldDataSchema *)schema migrateArticle:(NSDictionary *)articleDict; +-(void)oldDataSchema:(OldDataSchema *)schema migrateImage:(NSDictionary *)imageDict; -(void)oldDataSchema:(OldDataSchema *)schema migrateHistoryEntry:(NSDictionary *)historyDict; -(void)oldDataSchema:(OldDataSchema *)schema migrateSavedEntry:(NSDictionary *)savedDict; @@ -26,5 +27,6 @@ -(BOOL)exists; -(void)migrateData; +-(void)removeOldData; @end diff --git a/OldDataSchema/OldDataSchema/OldDataSchema.m b/OldDataSchema/OldDataSchema/OldDataSchema.m index 8ad8d57..4190e04 100644 --- a/OldDataSchema/OldDataSchema/OldDataSchema.m +++ b/OldDataSchema/OldDataSchema/OldDataSchema.m @@ -14,19 +14,301 @@ @implementation OldDataSchema { ArticleDataContextSingleton *context; + NSMutableSet *savedTitles; } --(BOOL)exists +-(instancetype)init +{ + self = [super init]; + if (self) { + savedTitles = [[NSMutableSet alloc] init]; + if (self.exists) { + context = [ArticleDataContextSingleton sharedInstance]; + } else { + context = nil; + } + } + return self; +} + +-(NSString *)sqlitePath { NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *documentRootPath = [documentPaths objectAtIndex:0]; NSString *filePath = [documentRootPath stringByAppendingPathComponent:@"articleData6.sqlite"]; + return filePath; +} + +-(BOOL)exists +{ + NSString *filePath = [self sqlitePath]; return [[NSFileManager defaultManager] fileExistsAtPath:filePath]; } + +-(void)removeOldData +{ + NSString *filePath = [self sqlitePath]; + NSString *backupPath = [filePath stringByAppendingString:@".bak"]; + NSError *err = nil; + [[NSFileManager defaultManager] moveItemAtPath:filePath + toPath:backupPath + error:&err]; + if (err) { + NSLog(@"Error backing up %@: %@", filePath, err); + } +} + -(void)migrateData { // TODO + // 1) Go through saved article list, saving entries and (articles and images) + // 2) Go through page reading history, saving entries and (articles and images) when not already transferred + + NSFetchRequest *req = [NSFetchRequest fetchRequestWithEntityName:@"Saved"]; + req.sortDescriptors = @[[[NSSortDescriptor alloc] initWithKey:@"dateSaved" ascending:YES]]; + NSError *err; + NSArray *savedEntries = [context.mainContext executeFetchRequest:req error:&err]; + if (err) { + NSLog(@"Error reading old Saved entries: %@", err); + } + for (Saved *saved in savedEntries) { + [self migrateSaved:saved]; + [self migrateArticle:saved.article]; + } + + NSFetchRequest *req2 = [NSFetchRequest fetchRequestWithEntityName:@"History"]; + req2.sortDescriptors = @[[[NSSortDescriptor alloc] initWithKey:@"dateVisited" ascending:YES]]; + NSError *err2; + NSArray *historyEntries = [context.mainContext executeFetchRequest:req2 error:&err2]; + if (err2) { + NSLog(@"Error reading old History entries: %@", err2); + } + for (History *history in historyEntries) { + [self migrateHistory:history]; + [self migrateArticle:history.article]; + } +} + +-(void)migrateSaved:(Saved *)saved +{ + NSDictionary *dict = [self exportSaved:saved]; + [self.delegate oldDataSchema:self migrateSavedEntry:dict]; +} + +-(void)migrateHistory:(History *)history +{ + NSDictionary *dict = [self exportHistory:history]; + [self.delegate oldDataSchema:self migrateHistoryEntry:dict]; +} + +-(void)migrateArticle:(Article *)article +{ + NSString *key = [NSString stringWithFormat:@"%@:%@", article.domain, article.title]; + if ([savedTitles containsObject:key]) { + // already imported this article + } else { + // Record for later to avoid dupe imports + [savedTitles addObject:key]; + + NSDictionary *dict = [self exportArticle:article]; + [self.delegate oldDataSchema:self migrateArticle:dict]; + + Image *thumbnail = article.thumbnailImage; + if (thumbnail) { + [self migrateThumbnailImage:thumbnail article:article]; + } + + // Find its images... + for (Section *section in article.section) { + for (SectionImage *sectionImage in section.sectionImage) { + [self migrateImage:sectionImage]; + } + } + } +} + +-(void)migrateThumbnailImage:(Image *)thumbnailImage article:(Article *)article +{ + NSDictionary *dict = [self exportThumbnailImage:thumbnailImage article:article]; + [self.delegate oldDataSchema:self migrateImage:dict]; +} + +-(void)migrateImage:(SectionImage *)sectionImage +{ + NSDictionary *dict = [self exportImage:sectionImage]; + [self.delegate oldDataSchema:self migrateImage:dict]; +} + +-(NSDictionary *)exportSaved:(Saved *)saved +{ + return @{ + @"domain": @"wikipedia.org", + @"language": saved.article.domain, + @"title": saved.article.title, + @"date": [self stringWithDate:saved.dateSaved] + }; +} + +-(NSDictionary *)exportHistory:(History *)history +{ + return @{ + @"domain": @"wikipedia.org", + @"language": history.article.domain, + @"title": history.article.title, + @"date": [self stringWithDate:history.dateVisited], + @"discoveryMethod": history.discoveryMethod, + @"scrollPosition": history.article.lastScrollY + }; +} + +-(NSDictionary *)exportArticle:(Article *)article +{ + NSMutableDictionary *dict = [@{} mutableCopy]; + + if (article.redirected) { + dict[@"redirected"] = article.redirected; + } + if (article.lastmodified) { + dict[@"lastmodified"] = [self stringWithDate:article.lastmodified]; + } + if (article.lastmodifiedby) { + dict[@"lastmodifiedby"] = @{ + @"name": article.lastmodifiedby, + @"gender": @"unknown" + }; + } + if (article.articleId) { + dict[@"id"] = article.articleId; + } + if (article.languagecount) { + dict[@"languagecount"] = article.languagecount; + } + if (article.displayTitle) { + dict[@"displaytitle"] = article.displayTitle; + } + if (article.protectionStatus) { + dict[@"protection"] = @{ + @"edit": article.protectionStatus + }; + } + if (article.editable) { + dict[@"editable"] = @""; + } + + if (article.thumbnailImage) { + dict[@"thumbnailURL"] = article.thumbnailImage.sourceUrl; + } + + // sections! + NSUInteger numSections = [article.section count]; + if (numSections) { + dict[@"sections"] = [[NSMutableArray alloc] initWithCapacity:numSections]; + for (int i = 0; i < numSections; i++) { + dict[@"sections"][i] = [NSNull null]; // stub out + } + for (Section *section in article.section) { + int sectionId = [section.sectionId intValue]; + dict[@"sections"][sectionId] = [self exportSection:section]; + } + } + + return @{ + @"language": article.domain, + @"title": article.title, + @"dict": dict + }; +} + +-(NSDictionary *)exportSection:(Section *)section +{ + NSMutableDictionary *dict = [@{} mutableCopy]; + + if (section.tocLevel) { + dict[@"toclevel"] = section.tocLevel; + } + if (section.level) { + dict[@"level"] = section.level; + } + if (section.title) { + dict[@"line"] = section.title; + } + if (section.fromTitle) { + dict[@"fromtitle"] = section.fromTitle; + } + if (section.anchor) { + dict[@"anchor"] = section.anchor; + } + dict[@"id"] = section.sectionId; + if (section.html) { + dict[@"text"] = section.html; + } + + return dict; +} + +-(NSDictionary *)exportThumbnailImage:(Image *)image article:(Article *)article +{ + ImageData *imageData = image.imageData; + + NSMutableDictionary *dict = [[NSMutableDictionary alloc] init]; + + dict[@"domain"] = @"wikipedia.org"; + dict[@"language"] = article.domain; + dict[@"title"] = article.title; + + dict[@"sectionId"] = @(-1); + + dict[@"sourceURL"] = image.sourceUrl; + if (imageData.data) { + dict[@"data"] = imageData.data; + } + + return dict; +} + +-(NSDictionary *)exportImage:(SectionImage *)sectionImage +{ + Section *section = sectionImage.section; + Article *article = section.article; + Image *image = sectionImage.image; + ImageData *imageData = image.imageData; + + NSMutableDictionary *dict = [[NSMutableDictionary alloc] init]; + + dict[@"domain"] = @"wikipedia.org"; + dict[@"language"] = article.domain; + dict[@"title"] = article.title; + + dict[@"sectionId"] = section.sectionId; + + dict[@"sourceURL"] = image.sourceUrl; + if (imageData.data) { + dict[@"data"] = imageData.data; + } + + return dict; +} + +#pragma mark - date methods + +- (NSDateFormatter *)iso8601Formatter +{ + // See: https://www.mediawiki.org/wiki/Manual:WfTimestamp + NSDateFormatter * formatter = [[NSDateFormatter alloc] init]; + [formatter setTimeZone:[NSTimeZone timeZoneWithName:@"UTC"]]; + [formatter setDateFormat:@"yyyy'-'MM'-'dd'T'HH':'mm':'ss'Z'"]; + return formatter; +} + +- (NSDate *)dateWithString:(NSString *)string +{ + return [[self iso8601Formatter] dateFromString:string]; +} + +- (NSString *)stringWithDate:(NSDate *)date +{ + return [[self iso8601Formatter] stringFromDate:date]; } @end diff --git a/OldDataSchema/OldDataSchemaBundle/Info.plist b/OldDataSchema/OldDataSchemaBundle/Info.plist new file mode 100644 index 0000000..6011a73 --- /dev/null +++ b/OldDataSchema/OldDataSchemaBundle/Info.plist @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>CFBundleDevelopmentRegion</key> + <string>en</string> + <key>CFBundleExecutable</key> + <string>$(EXECUTABLE_NAME)</string> + <key>CFBundleIdentifier</key> + <string>org.wikimedia.$(PRODUCT_NAME:rfc1034identifier)</string> + <key>CFBundleInfoDictionaryVersion</key> + <string>6.0</string> + <key>CFBundleName</key> + <string>$(PRODUCT_NAME)</string> + <key>CFBundlePackageType</key> + <string>BNDL</string> + <key>CFBundleShortVersionString</key> + <string>1.0</string> + <key>CFBundleSignature</key> + <string>????</string> + <key>CFBundleVersion</key> + <string>1</string> + <key>NSHumanReadableCopyright</key> + <string>Copyright © 2015 Wikimedia Foundation. All rights reserved.</string> + <key>NSPrincipalClass</key> + <string></string> +</dict> +</plist> diff --git a/Wikipedia.xcodeproj/project.pbxproj b/Wikipedia.xcodeproj/project.pbxproj index 426cc7e..11098ab 100644 --- a/Wikipedia.xcodeproj/project.pbxproj +++ b/Wikipedia.xcodeproj/project.pbxproj @@ -180,6 +180,7 @@ 04F27B7818FE0F2E00EDD838 /* PageHistoryViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 04F27B7418FE0F2E00EDD838 /* PageHistoryViewController.m */; }; 04F39590186CF80100B0D6FC /* TOCViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 04F3958F186CF80100B0D6FC /* TOCViewController.m */; }; C9180EC418AED30C006C1DCA /* WikipediaAppUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = C9180EC318AED30C006C1DCA /* WikipediaAppUtils.m */; }; + D407E6411A51DBDA00CCC8B1 /* SchemaConverter.m in Sources */ = {isa = PBXBuildFile; fileRef = D407E6401A51DBDA00CCC8B1 /* SchemaConverter.m */; }; D42E75EB18D11237002EA7E5 /* MWLanguageInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = D42E75EA18D11237002EA7E5 /* MWLanguageInfo.m */; }; D46CD8C418A1AC4F0042959E /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = D46CD8C018A1AC4F0042959E /* InfoPlist.strings */; }; D46CD8C518A1AC4F0042959E /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = D46CD8C218A1AC4F0042959E /* Localizable.strings */; }; @@ -201,8 +202,10 @@ D4B0AE0819366A0A00F0AC90 /* CreateAccountFunnel.m in Sources */ = {isa = PBXBuildFile; fileRef = D4B0AE0719366A0A00F0AC90 /* CreateAccountFunnel.m */; }; D4B0AE0B19366A2C00F0AC90 /* ReadingActionFunnel.m in Sources */ = {isa = PBXBuildFile; fileRef = D4B0AE0A19366A2C00F0AC90 /* ReadingActionFunnel.m */; }; D4B0AE0E19366A5400F0AC90 /* LoginFunnel.m in Sources */ = {isa = PBXBuildFile; fileRef = D4B0AE0D19366A5400F0AC90 /* LoginFunnel.m */; }; + D4B7794D1A5F36F700D06E00 /* OldDataSchemaBundle.bundle in Resources */ = {isa = PBXBuildFile; fileRef = D4E6D9161A5C65FA004916C1 /* OldDataSchemaBundle.bundle */; }; D4BC22B4181E9E6300CAC673 /* empty.png in Resources */ = {isa = PBXBuildFile; fileRef = D4BC22B3181E9E6300CAC673 /* empty.png */; }; D4C16A6819709CDF00CD91AD /* (null) in Resources */ = {isa = PBXBuildFile; }; + D4E6D9121A5C65F9004916C1 /* CoreData.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 040E5C4E184566F4007AFE6F /* CoreData.framework */; }; D4E8A8A4190835C100DA4765 /* DataMigrator.m in Sources */ = {isa = PBXBuildFile; fileRef = D4E8A8A3190835C100DA4765 /* DataMigrator.m */; }; D4E8A8A719084F1300DA4765 /* SQLiteHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = D4E8A8A619084F1300DA4765 /* SQLiteHelper.m */; }; D4E8A8A919085CEA00DA4765 /* libsqlite3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = D4E8A8A819085CEA00DA4765 /* libsqlite3.dylib */; }; @@ -267,6 +270,13 @@ proxyType = 1; remoteGlobalIDString = C73D7690357B1F8585BBD225; remoteInfo = "Pods-hpple"; + }; + D4E6D9151A5C65FA004916C1 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = D4F478441A48CD8500D8043C /* OldDataSchema.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = D4E6D90A1A5C65B5004916C1; + remoteInfo = OldDataSchemaBundle; }; D4F478491A48CD8700D8043C /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; @@ -496,8 +506,8 @@ 04AE1C6F1891B302002D5487 /* NSObject+Extras.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSObject+Extras.m"; sourceTree = "<group>"; }; 04AE520319DB5E0900F89B92 /* NSObject+ConstraintsScale.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSObject+ConstraintsScale.h"; sourceTree = "<group>"; }; 04AE520419DB5E0900F89B92 /* NSObject+ConstraintsScale.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSObject+ConstraintsScale.m"; sourceTree = "<group>"; }; - 04B0EA43190AFDD8007458AF /* ArticleImporter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ArticleImporter.h; sourceTree = "<group>"; }; - 04B0EA44190AFDD8007458AF /* ArticleImporter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ArticleImporter.m; sourceTree = "<group>"; }; + 04B0EA43190AFDD8007458AF /* ArticleImporter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ArticleImporter.h; path = wikipedia/Importer/ArticleImporter.h; sourceTree = SOURCE_ROOT; }; + 04B0EA44190AFDD8007458AF /* ArticleImporter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ArticleImporter.m; path = wikipedia/Importer/ArticleImporter.m; sourceTree = SOURCE_ROOT; }; 04B0EA46190B2319007458AF /* PreviewLicenseView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = PreviewLicenseView.xib; sourceTree = "<group>"; }; 04B0EA48190B2348007458AF /* PreviewLicenseView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PreviewLicenseView.h; sourceTree = "<group>"; }; 04B0EA49190B2348007458AF /* PreviewLicenseView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PreviewLicenseView.m; sourceTree = "<group>"; }; @@ -604,6 +614,8 @@ 04F3958F186CF80100B0D6FC /* TOCViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TOCViewController.m; sourceTree = "<group>"; }; C9180EC218AED30C006C1DCA /* WikipediaAppUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WikipediaAppUtils.h; sourceTree = "<group>"; }; C9180EC318AED30C006C1DCA /* WikipediaAppUtils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WikipediaAppUtils.m; sourceTree = "<group>"; }; + D407E63F1A51DBDA00CCC8B1 /* SchemaConverter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SchemaConverter.h; path = wikipedia/Data/SchemaConverter.h; sourceTree = SOURCE_ROOT; }; + D407E6401A51DBDA00CCC8B1 /* SchemaConverter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SchemaConverter.m; path = wikipedia/Data/SchemaConverter.m; sourceTree = SOURCE_ROOT; }; D42E75E918D11237002EA7E5 /* MWLanguageInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MWLanguageInfo.h; path = "mw-support/MWLanguageInfo.h"; sourceTree = "<group>"; }; D42E75EA18D11237002EA7E5 /* MWLanguageInfo.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MWLanguageInfo.m; path = "mw-support/MWLanguageInfo.m"; sourceTree = "<group>"; }; D442F58619709E540013A2CA /* qqq */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = qqq; path = qqq.lproj/Main_iPhone.strings; sourceTree = "<group>"; }; @@ -820,10 +832,10 @@ D4C16A6119708B0E00CD91AD /* krc */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = krc; path = krc.lproj/Main_iPhone.strings; sourceTree = "<group>"; }; D4C16A6419709CDF00CD91AD /* qqq */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = qqq; path = qqq.lproj/InfoPlist.strings; sourceTree = "<group>"; }; D4C16A6519709CDF00CD91AD /* qqq */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = qqq; path = qqq.lproj/Localizable.strings; sourceTree = "<group>"; }; - D4E8A8A2190835C100DA4765 /* DataMigrator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DataMigrator.h; path = wikipedia/DataMigrator.h; sourceTree = SOURCE_ROOT; }; - D4E8A8A3190835C100DA4765 /* DataMigrator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = DataMigrator.m; path = wikipedia/DataMigrator.m; sourceTree = SOURCE_ROOT; }; - D4E8A8A519084F1300DA4765 /* SQLiteHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SQLiteHelper.h; sourceTree = "<group>"; }; - D4E8A8A619084F1300DA4765 /* SQLiteHelper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SQLiteHelper.m; sourceTree = "<group>"; }; + D4E8A8A2190835C100DA4765 /* DataMigrator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DataMigrator.h; path = wikipedia/Data/DataMigrator.h; sourceTree = SOURCE_ROOT; }; + D4E8A8A3190835C100DA4765 /* DataMigrator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = DataMigrator.m; path = wikipedia/Data/DataMigrator.m; sourceTree = SOURCE_ROOT; }; + D4E8A8A519084F1300DA4765 /* SQLiteHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SQLiteHelper.h; path = wikipedia/Data/SQLiteHelper.h; sourceTree = SOURCE_ROOT; }; + D4E8A8A619084F1300DA4765 /* SQLiteHelper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SQLiteHelper.m; path = wikipedia/Data/SQLiteHelper.m; sourceTree = SOURCE_ROOT; }; D4E8A8A819085CEA00DA4765 /* libsqlite3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libsqlite3.dylib; path = usr/lib/libsqlite3.dylib; sourceTree = SDKROOT; }; D4F277F9194235A00032BA38 /* ProtectedEditAttemptFunnel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ProtectedEditAttemptFunnel.h; path = EventLogging/ProtectedEditAttemptFunnel.h; sourceTree = "<group>"; }; D4F277FA194235A00032BA38 /* ProtectedEditAttemptFunnel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ProtectedEditAttemptFunnel.m; path = EventLogging/ProtectedEditAttemptFunnel.m; sourceTree = "<group>"; }; @@ -838,6 +850,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + D4E6D9121A5C65F9004916C1 /* CoreData.framework in Frameworks */, D4F478741A48D1B100D8043C /* libOldDataSchema.a in Frameworks */, D497FCFB1A080810004A36A5 /* libMediaWikiKit.a in Frameworks */, D4AD975019F99E9000957451 /* libPods-hpple.a in Frameworks */, @@ -860,8 +873,9 @@ D4E8A8A11908357600DA4765 /* Data Migration */, 04B0EA42190AFDBA007458AF /* Importer */, ); - path = Data; - sourceTree = "<group>"; + name = Data; + path = wikipedia/Data; + sourceTree = SOURCE_ROOT; }; 0412CC5F192536580010E616 /* Root */ = { isa = PBXGroup; @@ -1289,7 +1303,7 @@ ); name = Importer; path = ../Importer; - sourceTree = "<group>"; + sourceTree = SOURCE_ROOT; }; 04B60509193522650007185A /* MenuButton */ = { isa = PBXGroup; @@ -1743,10 +1757,12 @@ D4E8A8A3190835C100DA4765 /* DataMigrator.m */, D4E8A8A519084F1300DA4765 /* SQLiteHelper.h */, D4E8A8A619084F1300DA4765 /* SQLiteHelper.m */, + D407E63F1A51DBDA00CCC8B1 /* SchemaConverter.h */, + D407E6401A51DBDA00CCC8B1 /* SchemaConverter.m */, ); name = "Data Migration"; path = ..; - sourceTree = "<group>"; + sourceTree = SOURCE_ROOT; }; D4EE00BB182445670090790F /* mw-support */ = { isa = PBXGroup; @@ -1762,6 +1778,7 @@ isa = PBXGroup; children = ( D4F4784A1A48CD8700D8043C /* libOldDataSchema.a */, + D4E6D9161A5C65FA004916C1 /* OldDataSchemaBundle.bundle */, ); name = Products; sourceTree = "<group>"; @@ -1952,6 +1969,13 @@ remoteRef = D4AD974819F99CD700957451 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; + D4E6D9161A5C65FA004916C1 /* OldDataSchemaBundle.bundle */ = { + isa = PBXReferenceProxy; + fileType = wrapper.cfbundle; + path = OldDataSchemaBundle.bundle; + remoteRef = D4E6D9151A5C65FA004916C1 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; D4F4784A1A48CD8700D8043C /* libOldDataSchema.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; @@ -1966,6 +1990,7 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + D4B7794D1A5F36F700D06E00 /* OldDataSchemaBundle.bundle in Resources */, 04D3082C19991CB60034F106 /* logo-placeholder-nea...@2x.png in Resources */, D46CD8C418A1AC4F0042959E /* InfoPlist.strings in Resources */, 045EFF1B19A25FEB00D0EDBB /* logo-placeholder-sea...@2x.png in Resources */, @@ -2184,6 +2209,7 @@ 047801BE18AE987900DBB747 /* UIButton+ColorMask.m in Sources */, 0429300A18604898002A13FC /* SavedPagesResultCell.m in Sources */, 0487048419F8262600B7D307 /* CaptchaResetter.m in Sources */, + D407E6411A51DBDA00CCC8B1 /* SchemaConverter.m in Sources */, 04821CD119895EDC007558F6 /* ReferenceGradientView.m in Sources */, 0460F8DC19B0F932001BC59B /* CenteredPathView.m in Sources */, 0472BC18193AD88C00C40BDA /* MWKSection+DisplayHtml.m in Sources */, @@ -2551,10 +2577,12 @@ "$(PROJECT_DIR)/cocoapods/Pods/Headers/Public/AFNetworking", "$(PROJECT_DIR)/cocoapods/Pods/Headers/Public/hpple", "$(PROJECT_DIR)/MediaWikiKit/MediaWikiKit", + "$(PROJECT_DIR)/OldDataSchema/**", ); INFOPLIST_FILE = "Wikipedia/Wikipedia-Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 6.0; LIBRARY_SEARCH_PATHS = "$(inherited)"; + OTHER_LDFLAGS = "-ObjC"; PRODUCT_NAME = Wikipedia; PROVISIONING_PROFILE = ""; WRAPPER_EXTENSION = app; @@ -2648,10 +2676,12 @@ "$(PROJECT_DIR)/cocoapods/Pods/Headers/Public/AFNetworking", "$(PROJECT_DIR)/cocoapods/Pods/Headers/Public/hpple", "$(PROJECT_DIR)/MediaWikiKit/MediaWikiKit", + "$(PROJECT_DIR)/OldDataSchema/**", ); INFOPLIST_FILE = "Wikipedia/Wikipedia-Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 6.0; LIBRARY_SEARCH_PATHS = "$(inherited)"; + OTHER_LDFLAGS = "-ObjC"; PRODUCT_NAME = Wikipedia; PROVISIONING_PROFILE = ""; WRAPPER_EXTENSION = app; @@ -2674,10 +2704,12 @@ "$(PROJECT_DIR)/cocoapods/Pods/Headers/Public/AFNetworking", "$(PROJECT_DIR)/cocoapods/Pods/Headers/Public/hpple", "$(PROJECT_DIR)/MediaWikiKit/MediaWikiKit", + "$(PROJECT_DIR)/OldDataSchema/**", ); INFOPLIST_FILE = "Wikipedia/Wikipedia-Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 6.0; LIBRARY_SEARCH_PATHS = "$(inherited)"; + OTHER_LDFLAGS = "-ObjC"; PRODUCT_NAME = Wikipedia; PROVISIONING_PROFILE = ""; WRAPPER_EXTENSION = app; diff --git a/Wikipedia.xcodeproj/xcshareddata/xcschemes/Wikipedia-iOS.xcscheme b/Wikipedia.xcodeproj/xcshareddata/xcschemes/Wikipedia-iOS.xcscheme index 2ddce9c..3bbc795 100644 --- a/Wikipedia.xcodeproj/xcshareddata/xcschemes/Wikipedia-iOS.xcscheme +++ b/Wikipedia.xcodeproj/xcshareddata/xcschemes/Wikipedia-iOS.xcscheme @@ -34,6 +34,20 @@ ReferencedContainer = "container:Wikipedia.xcodeproj"> </BuildableReference> </BuildActionEntry> + <BuildActionEntry + buildForTesting = "YES" + buildForRunning = "YES" + buildForProfiling = "YES" + buildForArchiving = "YES" + buildForAnalyzing = "YES"> + <BuildableReference + BuildableIdentifier = "primary" + BlueprintIdentifier = "D4E6D9091A5C65B5004916C1" + BuildableName = "OldDataSchemaBundle.bundle" + BlueprintName = "OldDataSchemaBundle" + ReferencedContainer = "container:OldDataSchema/OldDataSchema.xcodeproj"> + </BuildableReference> + </BuildActionEntry> </BuildActionEntries> </BuildAction> <TestAction diff --git a/wikipedia/DataMigrator.h b/wikipedia/Data/DataMigrator.h similarity index 100% rename from wikipedia/DataMigrator.h rename to wikipedia/Data/DataMigrator.h diff --git a/wikipedia/DataMigrator.m b/wikipedia/Data/DataMigrator.m similarity index 100% rename from wikipedia/DataMigrator.m rename to wikipedia/Data/DataMigrator.m diff --git a/wikipedia/SQLiteHelper.h b/wikipedia/Data/SQLiteHelper.h similarity index 100% rename from wikipedia/SQLiteHelper.h rename to wikipedia/Data/SQLiteHelper.h diff --git a/wikipedia/SQLiteHelper.m b/wikipedia/Data/SQLiteHelper.m similarity index 100% rename from wikipedia/SQLiteHelper.m rename to wikipedia/Data/SQLiteHelper.m diff --git a/wikipedia/Data/SchemaConverter.h b/wikipedia/Data/SchemaConverter.h new file mode 100644 index 0000000..25e854f --- /dev/null +++ b/wikipedia/Data/SchemaConverter.h @@ -0,0 +1,23 @@ +// +// SchemaConverter.h +// Wikipedia +// +// Created by Brion on 12/29/14. +// Copyright (c) 2014 Wikimedia Foundation. All rights reserved. +// + +#import <Foundation/Foundation.h> + +#import "OldDataSchema.h" + +#import "MediaWikiKit.h" + +@interface SchemaConverter : NSObject <OldDataSchemaDelegate> + +@property OldDataSchema *schema; +@property MWKDataStore *dataStore; +@property MWKUserDataStore *userDataStore; + +-(instancetype)initWithDataStore:(MWKDataStore *)dataStore; + +@end diff --git a/wikipedia/Data/SchemaConverter.m b/wikipedia/Data/SchemaConverter.m new file mode 100644 index 0000000..45bda53 --- /dev/null +++ b/wikipedia/Data/SchemaConverter.m @@ -0,0 +1,92 @@ +// +// SchemaConverter.m +// Wikipedia +// +// Created by Brion on 12/29/14. +// Copyright (c) 2014 Wikimedia Foundation. All rights reserved. +// + +#import "SchemaConverter.h" + +@implementation SchemaConverter + +-(instancetype)initWithDataStore:(MWKDataStore *)dataStore +{ + self = [super init]; + if (self) { + self.dataStore = dataStore; + self.userDataStore = [self.dataStore userDataStore]; + } + return self; +} + +-(void)oldDataSchema:(OldDataSchema *)schema migrateArticle:(NSDictionary *)articleDict +{ + NSString *language = articleDict[@"language"]; + NSString *titleStr = articleDict[@"title"]; + NSDictionary *mobileview = articleDict[@"dict"]; + + MWKSite *site = [[MWKSite alloc] initWithDomain:@"wikipedia.org" language:language]; + MWKTitle *title = [site titleWithString:titleStr]; + MWKArticle *article = [self.dataStore articleWithTitle:title]; + [article importMobileViewJSON:mobileview]; + [article save]; +} + +-(void)oldDataSchema:(OldDataSchema *)schema migrateImage:(NSDictionary *)imageDict +{ + NSString *language = imageDict[@"language"]; + NSString *titleStr = imageDict[@"title"]; + NSString *sourceURL = imageDict[@"sourceURL"]; + int sectionId = [imageDict[@"sectionId"] intValue]; + NSData *imageData = imageDict[@"data"]; + + // @todo cache the article object? + MWKSite *site = [[MWKSite alloc] initWithDomain:@"wikipedia.org" language:language]; + MWKTitle *title = [site titleWithString:titleStr]; + MWKArticle *article = [self.dataStore articleWithTitle:title]; + + MWKImage *image = [article importImageURL:sourceURL sectionId:sectionId]; + [image importImageData:imageData]; +} + +-(void)oldDataSchema:(OldDataSchema *)schema migrateHistoryEntry:(NSDictionary *)historyDict +{ + NSString *language = historyDict[@"language"]; + NSString *titleStr = historyDict[@"title"]; + NSString *date = historyDict[@"date"]; + NSString *discoveryMethod = historyDict[@"discoveryMethod"]; + + NSMutableDictionary *dict = [@{} mutableCopy]; + dict[@"domain"] = @"wikipedia.org"; + dict[@"language"] = language; + dict[@"title"] = titleStr; + dict[@"date"] = date; + dict[@"discoveryMethod"] = discoveryMethod; + dict[@"scrollPosition"] = @(0); // @fixme extract from article? + + MWKHistoryEntry *entry = [[MWKHistoryEntry alloc] initWithDict:dict]; + + MWKHistoryList *historyList = self.userDataStore.historyList; + [historyList addEntry:entry]; + [self.userDataStore save]; +} + +-(void)oldDataSchema:(OldDataSchema *)schema migrateSavedEntry:(NSDictionary *)savedDict +{ + NSString *language = savedDict[@"language"]; + NSString *titleStr = savedDict[@"title"]; + + NSMutableDictionary *dict = [@{} mutableCopy]; + dict[@"domain"] = @"wikipedia.org"; + dict[@"language"] = language; + dict[@"title"] = titleStr; + + MWKSavedPageEntry *entry = [[MWKSavedPageEntry alloc] initWithDict:dict]; + + MWKSavedPageList *savedPageList = self.userDataStore.savedPageList; + [savedPageList addEntry:entry]; + [self.userDataStore save]; +} + +@end diff --git a/wikipedia/View Controllers/WebView/WebViewController.m b/wikipedia/View Controllers/WebView/WebViewController.m index 61fe777..cadcd34 100644 --- a/wikipedia/View Controllers/WebView/WebViewController.m +++ b/wikipedia/View Controllers/WebView/WebViewController.m @@ -54,6 +54,8 @@ #import "AssetsFileFetcher.h" #import "LeadImageContainer.h" +#import "OldDataSchema.h" +#import "SchemaConverter.h" //#import "UIView+Debugging.h" @@ -1849,6 +1851,28 @@ - (void)migrateDataIfNecessary { + // Middle-Ages Converter + // From the native app's initial CoreData-based implementation, + // which now lives in OldDataSchema subproject. + OldDataSchema *oldDataSchema = [[OldDataSchema alloc] init]; + if ([oldDataSchema exists]) { + SchemaConverter *schemaConverter = [[SchemaConverter alloc] initWithDataStore:session.dataStore]; + oldDataSchema.delegate = schemaConverter; + NSLog(@"begin migration"); + [oldDataSchema migrateData]; + NSLog(@"end migration"); + + [oldDataSchema removeOldData]; + + // hack for history fix + [session.userDataStore reset]; + + return; + } + + // Ye Ancient Converter + // From the old PhoneGap app + // @fixme: fix this to work again DataMigrator *dataMigrator = [[DataMigrator alloc] init]; if ([dataMigrator hasData]) { NSLog(@"Old data to migrate found!"); @@ -1862,10 +1886,11 @@ [importer importArticles:titles]; [dataMigrator removeOldData]; - } else { - NSLog(@"No old data to migrate."); + + return; } + NSLog(@"No old data to migrate."); } #pragma mark Bottom menu bar -- To view, visit https://gerrit.wikimedia.org/r/183091 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: merged Gerrit-Change-Id: I7234f714b7c368da09b8a63295c623394dfbc70a Gerrit-PatchSet: 9 Gerrit-Project: apps/ios/wikipedia Gerrit-Branch: master Gerrit-Owner: Brion VIBBER <br...@wikimedia.org> Gerrit-Reviewer: Brion VIBBER <br...@wikimedia.org> Gerrit-Reviewer: Dr0ptp4kt <ab...@wikimedia.org> Gerrit-Reviewer: Mhurd <mh...@wikimedia.org> Gerrit-Reviewer: jenkins-bot <> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits