diff --git a/Sources/WordPressData/Objective-C/AbstractPost.m b/Sources/WordPressData/Objective-C/AbstractPost.m index fee78a210cb7..a54b0058ec06 100644 --- a/Sources/WordPressData/Objective-C/AbstractPost.m +++ b/Sources/WordPressData/Objective-C/AbstractPost.m @@ -28,13 +28,6 @@ @implementation AbstractPost @dynamic permalinkTemplateURL; @synthesize voiceContent; -#pragma mark - Life Cycle Methods - -- (void)save -{ - [[ContextManager sharedInstance] saveContext:self.managedObjectContext]; -} - #pragma mark - #pragma mark Revision management @@ -58,45 +51,6 @@ - (AbstractPost *)original #pragma mark - Helpers -- (BOOL)dateCreatedIsNilOrEqualToDateModified -{ - return self.date_created_gmt == nil || [self.date_created_gmt isEqualToDate:self.dateModified]; -} - -- (BOOL)hasPhoto -{ - if ([self.media count] == 0) { - return NO; - } - - if (self.featuredImage != nil) { - return YES; - } - - for (Media *media in self.media) { - if (media.mediaType == MediaTypeImage) { - return YES; - } - } - - return NO; -} - -- (BOOL)hasVideo -{ - if ([self.media count] == 0) { - return NO; - } - - for (Media *media in self.media) { - if (media.mediaType == MediaTypeVideo) { - return YES; - } - } - - return NO; -} - - (BOOL)hasCategories { return NO; @@ -107,93 +61,4 @@ - (BOOL)hasTags return NO; } -- (BOOL)hasRemote -{ - return ((self.postID != nil) && ([self.postID longLongValue] > 0)); -} - -#pragma mark - Convenience methods - -// If the post has a scheduled status. -- (BOOL)isScheduled -{ - return ([self.status isEqualToString:PostStatusScheduled]); -} - -- (BOOL)isDraft -{ - return [self.status isEqualToString:PostStatusDraft]; -} - -- (BOOL)isPublished -{ - return [self.status isEqualToString:PostStatusPublish]; -} - -- (BOOL)originalIsDraft -{ - if ([self.status isEqualToString:PostStatusDraft]) { - return YES; - } else if (self.isRevision && [self.original.status isEqualToString:PostStatusDraft]) { - return YES; - } - return NO; -} - -- (BOOL)shouldPublishImmediately -{ - /// - warning: Yes, this is WordPress logic and it matches the behavior on - /// the web. If `dateCreated` is the same as `dateModified`, the system - /// uses it to represent a "no publish date selected" scenario. - return [self originalIsDraft] && [self dateCreatedIsNilOrEqualToDateModified]; -} - -- (NSURL *)blogURL -{ - return [NSURL URLWithString:self.blog.url]; -} - -- (BOOL)isPrivateAtWPCom -{ - return self.blog.isPrivateAtWPCom; -} - -#pragma mark - Post - -- (void)updatePathForDisplayImageBasedOnContent -{ - // First lets check the post content for a suitable image - NSString *result = [DisplayableImageHelper searchPostContentForImageToDisplay:self.content]; - if (result.length > 0) { - self.pathForDisplayImage = result; - } - // If none found let's see if some galleries are available - NSSet *mediaIDs = [DisplayableImageHelper searchPostContentForAttachmentIdsInGalleries:self.content]; - for (Media *media in self.blog.media) { - NSNumber *mediaID = media.mediaID; - if (mediaID && [mediaIDs containsObject:mediaID]) { - result = media.remoteURL; - } - } - self.pathForDisplayImage = result; -} - -- (void)setParsedOtherTerms:(NSDictionary *> *)data -{ - if (data == nil) { - self.rawOtherTerms = nil; - } else { - self.rawOtherTerms = [NSJSONSerialization dataWithJSONObject:data options:0 error:nil]; - } -} - -- (NSDictionary *> *)parseOtherTerms -{ - if (self.rawOtherTerms == nil) { - return [NSDictionary dictionary]; - } - - return [NSJSONSerialization JSONObjectWithData:self.rawOtherTerms options:0 error:nil] ?: [NSDictionary dictionary]; -} - @end diff --git a/Sources/WordPressData/Objective-C/include/AbstractPost.h b/Sources/WordPressData/Objective-C/include/AbstractPost.h index 6d091cb2cc6b..24833ca1ef5b 100644 --- a/Sources/WordPressData/Objective-C/include/AbstractPost.h +++ b/Sources/WordPressData/Objective-C/include/AbstractPost.h @@ -62,54 +62,9 @@ typedef NS_ENUM(NSUInteger, AbstractPostRemoteStatus) { @property (nonatomic, strong, nullable) NSString *voiceContent; -- (BOOL)hasPhoto; -- (BOOL)hasVideo; - (BOOL)hasCategories; - (BOOL)hasTags; - -#pragma mark - Conveniece Methods -- (BOOL)shouldPublishImmediately; -- (BOOL)isPrivateAtWPCom; - - -#pragma mark - Unsaved Changes - -/** - Returns YES if the post is has a `future` post status - */ -- (BOOL)isScheduled; - -/** - Returns YES if the post is a draft - */ -- (BOOL)isDraft; - -/** - Returns YES if the post is a published. - */ -- (BOOL)isPublished; - -/** - Returns YES if the original post is a draft - */ -- (BOOL)originalIsDraft; - -// Does the post exist on the blog? -- (BOOL)hasRemote; - -// Save changes to disk -- (void)save; - -/** - * Updates the path for the display image by looking at the post content and trying to find an good image to use. - * If no appropiated image is found the path is set to nil. - */ -- (void)updatePathForDisplayImageBasedOnContent; - -- (void)setParsedOtherTerms:(NSDictionary *> *)data; -- (NSDictionary *> *)parseOtherTerms; - @end @interface AbstractPost (CoreDataGeneratedAccessors) diff --git a/Sources/WordPressData/Swift/AbstractPost.swift b/Sources/WordPressData/Swift/AbstractPost.swift index 6945b54a3df9..a46d445ce523 100644 --- a/Sources/WordPressData/Swift/AbstractPost.swift +++ b/Sources/WordPressData/Swift/AbstractPost.swift @@ -328,4 +328,114 @@ public extension AbstractPost { func hasRevision() -> Bool { revision != nil } + + /// Returns YES if the post is has a `future` post status + @objc + func isScheduled() -> Bool { + status == .scheduled + } + + /// Returns YES if the post is a draft + @objc + func isDraft() -> Bool { + status == .draft + } + + /// Returns YES if the post is a published. + @objc + func isPublished() -> Bool { + status == .publish + } + + /// Returns YES if the original post is a draft + @objc + func originalIsDraft() -> Bool { + if status == .draft { + return true + } else if isRevision(), original?.status == .draft { + return true + } + return false + } + + @objc + func shouldPublishImmediately() -> Bool { + // - warning: Yes, this is WordPress logic and it matches the behavior on + // the web. If `dateCreated` is the same as `dateModified`, the system + // uses it to represent a "no publish date selected" scenario. + originalIsDraft() && (date_created_gmt == nil || date_created_gmt == dateModified) + } + + @objc + func hasPhoto() -> Bool { + if media.isEmpty { + return false + } + + if featuredImage != nil { + return true + } + + return media.contains { $0.mediaType == .image } + } + + @objc + func hasVideo() -> Bool { + if media.isEmpty { + return false + } + + return media.contains { $0.mediaType == .video } + } + + /// Does the post exist on the blog? + @objc + func hasRemote() -> Bool { + (postID?.int64Value ?? 0) > 0 + } + + @objc + var parsedOtherTerms: [String: [String]] { + get { + guard let rawOtherTerms else { + return [:] + } + + return (try? JSONSerialization.jsonObject(with: rawOtherTerms) as? [String: [String]]) ?? [:] + } + set { + rawOtherTerms = try? JSONSerialization.data(withJSONObject: newValue) + } + } + + /// Updates the path for the display image by looking at the post content and trying to find an good image to use. + /// If no appropiated image is found the path is set to nil. + @objc + func updatePathForDisplayImageBasedOnContent() { + guard let content else { + return + } + + if let result = DisplayableImageHelper.searchPostContentForImage(toDisplay: content), !result.isEmpty { + pathForDisplayImage = result + return + } + + guard let allMedia = blog.media, !allMedia.isEmpty else { return } + + let mediaIDs = DisplayableImageHelper.searchPostContentForAttachmentIds(inGalleries: content) as? Set ?? [] + for media in allMedia { + guard let media = media as? Media else { continue } + + guard let mediaID = media.mediaID, + mediaIDs.contains(mediaID) else { + continue + } + + if let remoteURL = media.remoteURL { + pathForDisplayImage = remoteURL + break + } + } + } } diff --git a/Sources/WordPressData/Swift/RemotePostCreateParameters+Helpers.swift b/Sources/WordPressData/Swift/RemotePostCreateParameters+Helpers.swift index b4465f326300..cbd0434a230d 100644 --- a/Sources/WordPressData/Swift/RemotePostCreateParameters+Helpers.swift +++ b/Sources/WordPressData/Swift/RemotePostCreateParameters+Helpers.swift @@ -20,7 +20,7 @@ extension RemotePostCreateParameters { excerpt = post.mt_excerpt slug = post.wp_slug featuredImageID = post.featuredImage?.mediaID?.intValue - otherTerms = post.parseOtherTerms() + otherTerms = post.parsedOtherTerms switch post { case let page as Page: parentPageID = page.parentID?.intValue diff --git a/WordPress/Classes/ViewRelated/Gutenberg/EditorMediaUtility.swift b/WordPress/Classes/ViewRelated/Gutenberg/EditorMediaUtility.swift index d269f5219993..f185fc957d65 100644 --- a/WordPress/Classes/ViewRelated/Gutenberg/EditorMediaUtility.swift +++ b/WordPress/Classes/ViewRelated/Gutenberg/EditorMediaUtility.swift @@ -139,7 +139,7 @@ class EditorMediaUtility { let requestURL: URL if url.isFileURL { requestURL = url - } else if post.isPrivateAtWPCom() && url.isHostedAtWPCom { + } else if post.blog.isPrivateAtWPCom() && url.isHostedAtWPCom { // private wpcom image needs special handling. // the size that WPImageHelper expects is pixel size size.width = size.width * scale diff --git a/WordPress/Classes/ViewRelated/Post/PostSettings/PostSettings.swift b/WordPress/Classes/ViewRelated/Post/PostSettings/PostSettings.swift index 6758d5f530b4..797c9a1519ad 100644 --- a/WordPress/Classes/ViewRelated/Post/PostSettings/PostSettings.swift +++ b/WordPress/Classes/ViewRelated/Post/PostSettings/PostSettings.swift @@ -54,7 +54,7 @@ struct PostSettings: Hashable { } featuredImageID = post.featuredImage?.mediaID?.intValue - otherTerms = post.parseOtherTerms() + otherTerms = post.parsedOtherTerms metadata = PostMetadata(post) @@ -112,8 +112,8 @@ struct PostSettings: Hashable { post.featuredImage = nil } - if !RemotePost.compare(otherTerms: post.parseOtherTerms(), withAnother: otherTerms) { - post.setParsedOtherTerms(otherTerms) + if !RemotePost.compare(otherTerms: post.parsedOtherTerms, withAnother: otherTerms) { + post.parsedOtherTerms = otherTerms } var postMetadataContainer = PostMetadataContainer(post)