diff --git a/Frameworks/Database/ArticlesTable.swift b/Frameworks/Database/ArticlesTable.swift index 99eda3874..21bc02135 100644 --- a/Frameworks/Database/ArticlesTable.swift +++ b/Frameworks/Database/ArticlesTable.swift @@ -298,8 +298,9 @@ private extension ArticlesTable { saveRelatedObjectsForNewArticles(articles, database) - let databaseDictionaries = articles.map { $0.databaseDictionary() } - insertRows(databaseDictionaries, insertType: .orReplace, in: database) + if let databaseDictionaries = articles.databaseDictionaries() { + insertRows(databaseDictionaries, insertType: .orReplace, in: database) + } } func saveRelatedObjectsForNewArticles(_ articles: Set
, _ database: FMDatabase) { diff --git a/Frameworks/Database/Extensions/Article+Database.swift b/Frameworks/Database/Extensions/Article+Database.swift index b10b34aeb..f001671ee 100644 --- a/Frameworks/Database/Extensions/Article+Database.swift +++ b/Frameworks/Database/Extensions/Article+Database.swift @@ -40,37 +40,12 @@ extension Article { init(parsedItem: ParsedItem, accountID: String, feedID: String) { - let authors = Author.authorsWithParsedAuthors(parsedItem.authors) + let authors = parsedItem.authors?.authors() let attachments = Attachment.attachmentsWithParsedAttachments(parsedItem.attachments) self.init(accountID: accountID, articleID: parsedItem.syncServiceID, feedID: feedID, uniqueID: parsedItem.uniqueID, title: parsedItem.title, contentHTML: parsedItem.contentHTML, contentText: parsedItem.contentText, url: parsedItem.url, externalURL: parsedItem.externalURL, summary: parsedItem.summary, imageURL: parsedItem.imageURL, bannerImageURL: parsedItem.bannerImageURL, datePublished: parsedItem.datePublished, dateModified: parsedItem.dateModified, authors: authors, tags: parsedItem.tags, attachments: attachments, accountInfo: nil) } - func databaseDictionary() -> NSDictionary { - - let d = NSMutableDictionary() - - d[DatabaseKey.articleID] = articleID - d[DatabaseKey.feedID] = feedID - d[DatabaseKey.uniqueID] = uniqueID - - d.addOptionalString(title, DatabaseKey.title) - d.addOptionalString(contentHTML, DatabaseKey.contentHTML) - d.addOptionalString(contentText, DatabaseKey.contentText) - d.addOptionalString(url, DatabaseKey.url) - d.addOptionalString(externalURL, DatabaseKey.externalURL) - d.addOptionalString(summary, DatabaseKey.summary) - d.addOptionalString(imageURL, DatabaseKey.imageURL) - d.addOptionalString(bannerImageURL, DatabaseKey.bannerImageURL) - - d.addOptionalDate(datePublished, DatabaseKey.datePublished) - d.addOptionalDate(dateModified, DatabaseKey.dateModified) - - // TODO: accountInfo - - return d.copy() as! NSDictionary - } - private func addPossibleStringChangeWithKeyPath(_ comparisonKeyPath: KeyPath, _ otherArticle: Article, _ key: String, _ dictionary: NSMutableDictionary) { if self[keyPath: comparisonKeyPath] != otherArticle[keyPath: comparisonKeyPath] { @@ -132,6 +107,31 @@ extension Article { } extension Article: DatabaseObject { + + public func databaseDictionary() -> NSDictionary? { + + let d = NSMutableDictionary() + + d[DatabaseKey.articleID] = articleID + d[DatabaseKey.feedID] = feedID + d[DatabaseKey.uniqueID] = uniqueID + + d.addOptionalString(title, DatabaseKey.title) + d.addOptionalString(contentHTML, DatabaseKey.contentHTML) + d.addOptionalString(contentText, DatabaseKey.contentText) + d.addOptionalString(url, DatabaseKey.url) + d.addOptionalString(externalURL, DatabaseKey.externalURL) + d.addOptionalString(summary, DatabaseKey.summary) + d.addOptionalString(imageURL, DatabaseKey.imageURL) + d.addOptionalString(bannerImageURL, DatabaseKey.bannerImageURL) + + d.addOptionalDate(datePublished, DatabaseKey.datePublished) + d.addOptionalDate(dateModified, DatabaseKey.dateModified) + + // TODO: accountInfo + + return (d.copy() as! NSDictionary) + } public var databaseID: String { get { @@ -160,6 +160,11 @@ extension Set where Element == Article { return self.map{ $0 as DatabaseObject } } + + func databaseDictionaries() -> [NSDictionary]? { + + return self.flatMap { $0.databaseDictionary() } + } } private extension NSMutableDictionary { diff --git a/Frameworks/Database/Extensions/ArticleStatus+Database.swift b/Frameworks/Database/Extensions/ArticleStatus+Database.swift index 3752fca62..f529c9894 100644 --- a/Frameworks/Database/Extensions/ArticleStatus+Database.swift +++ b/Frameworks/Database/Extensions/ArticleStatus+Database.swift @@ -23,22 +23,6 @@ extension ArticleStatus { self.init(articleID: articleID, read: read, starred: starred, userDeleted: userDeleted, dateArrived: dateArrived, accountInfo: nil) } - func databaseDictionary() -> NSDictionary { - - let d = NSMutableDictionary() - - d[DatabaseKey.articleID] = articleID - d[DatabaseKey.read] = read - d[DatabaseKey.starred] = starred - d[DatabaseKey.userDeleted] = userDeleted - d[DatabaseKey.dateArrived] = dateArrived - -// if let accountInfo = accountInfo, let data = PropertyListTransformer.data(withPropertyList: accountInfo) { -// d[DatabaseKey.accountInfo] = data -// } - - return d.copy() as! NSDictionary - } } extension ArticleStatus: DatabaseObject { @@ -48,4 +32,22 @@ extension ArticleStatus: DatabaseObject { return articleID } } + + public func databaseDictionary() -> NSDictionary? { + + let d = NSMutableDictionary() + + d[DatabaseKey.articleID] = articleID + d[DatabaseKey.read] = read + d[DatabaseKey.starred] = starred + d[DatabaseKey.userDeleted] = userDeleted + d[DatabaseKey.dateArrived] = dateArrived + + // if let accountInfo = accountInfo, let data = PropertyListTransformer.data(withPropertyList: accountInfo) { + // d[DatabaseKey.accountInfo] = data + // } + + return (d.copy() as! NSDictionary) + } + } diff --git a/Frameworks/Database/Extensions/Attachment+Database.swift b/Frameworks/Database/Extensions/Attachment+Database.swift index 350c66586..977813ace 100644 --- a/Frameworks/Database/Extensions/Attachment+Database.swift +++ b/Frameworks/Database/Extensions/Attachment+Database.swift @@ -42,28 +42,6 @@ extension Attachment { return attachments.isEmpty ? nil : Set(attachments) } - func databaseDictionary() -> NSDictionary { - - var d = NSMutableDictionary() - - d[DatabaseKey.attachmentID] = attachmentID - d[DatabaseKey.url] = url - - if let mimeType = mimeType { - d[DatabaseKey.mimeType] = mimeType - } - if let title = title { - d[DatabaseKey.title] = title - } - if let sizeInBytes = sizeInBytes { - d[DatabaseKey.sizeInBytes] = NSNumber(sizeInBytes) - } - if let durationInSeconds = durationInSeconds { - d[DatabaseKey.durationInSeconds] = NSNumber(durationInSeconds) - } - - return d.copy() as! NSDictionary - } } private func optionalIntForColumn(_ row: FMResultSet, _ columnName: String) -> Int? { @@ -82,17 +60,41 @@ extension Attachment: DatabaseObject { return attachmentID } } + + func databaseDictionary() -> NSDictionary? { + + let d = NSMutableDictionary() + + d[DatabaseKey.attachmentID] = attachmentID + d[DatabaseKey.url] = url + + if let mimeType = mimeType { + d[DatabaseKey.mimeType] = mimeType + } + if let title = title { + d[DatabaseKey.title] = title + } + if let sizeInBytes = sizeInBytes { + d[DatabaseKey.sizeInBytes] = NSNumber(value: sizeInBytes) + } + if let durationInSeconds = durationInSeconds { + d[DatabaseKey.durationInSeconds] = NSNumber(value: durationInSeconds) + } + + return (d.copy() as! NSDictionary) + } + } extension Set where Element == Attachment { func databaseDictionaries() -> [NSDictionary] { - return self.map { $0.databaseDictionary() } + return self.flatMap { $0.databaseDictionary() } } func databaseObjects() -> [DatabaseObject] { - return self.map { $0 as DatabaseObject } + return self.flatMap { $0 as DatabaseObject } } } diff --git a/Frameworks/Database/Extensions/Author+Database.swift b/Frameworks/Database/Extensions/Author+Database.swift index 5ecfcec42..cd42cddb0 100644 --- a/Frameworks/Database/Extensions/Author+Database.swift +++ b/Frameworks/Database/Extensions/Author+Database.swift @@ -11,24 +11,22 @@ import Data import RSDatabase import RSParser -extension Author { - - static func authorsWithParsedAuthors(_ parsedAuthors: Set?) -> Set? { - - assert(!Thread.isMainThread) - - guard let parsedAuthors = parsedAuthors else { - return nil - } - - let authors = Set(parsedAuthors.flatMap { authorWithParsedAuthor($0) }) - return authors.isEmpty ? nil : authors - } -} - // MARK: - DatabaseObject extension Author: DatabaseObject { + + public func databaseDictionary() -> NSDictionary? { + + var d = NSMutableDictionary() + + // TODO + + if d.count < 1 { + return nil + } + return (d.copy() as! NSDictionary) + } + public var databaseID: String { get { @@ -58,3 +56,14 @@ private extension Author { } } +// MARK: Author creation from Set + +extension Set where Element == ParsedAuthor { + + func authors() -> Set? { + + let createdAuthors = Set(self.flatMap { Author(parsedAuthor: $0) }) + return createdAuthors.isEmpty ? nil: createdAuthors + } +} + diff --git a/Frameworks/RSDatabase/RSDatabase/DatabaseObject.swift b/Frameworks/RSDatabase/RSDatabase/DatabaseObject.swift index bc4eaf0ca..0686c128a 100644 --- a/Frameworks/RSDatabase/RSDatabase/DatabaseObject.swift +++ b/Frameworks/RSDatabase/RSDatabase/DatabaseObject.swift @@ -12,6 +12,8 @@ public protocol DatabaseObject { var databaseID: String { get } + func databaseDictionary() -> NSDictionary? + func relatedObjectsWithName(_ name: String) -> [DatabaseObject]? } @@ -48,4 +50,10 @@ extension Array where Element == DatabaseObject { } return false } + + func databaseDictionaries() -> [NSDictionary]? { + + let dictionaries = self.flatMap{ $0.databaseDictionary() } + return dictionaries.isEmpty ? nil : dictionaries + } } diff --git a/Frameworks/RSDatabase/Related Objects/DatabaseRelatedObjectsTable.swift b/Frameworks/RSDatabase/Related Objects/DatabaseRelatedObjectsTable.swift index 31ec1b159..45bf7dc77 100644 --- a/Frameworks/RSDatabase/Related Objects/DatabaseRelatedObjectsTable.swift +++ b/Frameworks/RSDatabase/Related Objects/DatabaseRelatedObjectsTable.swift @@ -62,4 +62,21 @@ public extension DatabaseRelatedObjectsTable { return resultSet.flatMap(objectWithRow) } + + func save(_ objects: [DatabaseObject], in database: FMDatabase) { + + // Objects in cache must already exist in database. Filter them out. + let objectsToSave = objects.filter { (object) -> Bool in + if let _ = cache[object.databaseID] { + return false + } + return true + } + + cache.add(objectsToSave) + if let databaseDictionaries = objectsToSave.databaseDictionaries() { + insertRows(databaseDictionaries, insertType: .orIgnore, in: database) + } + } + }