- Upgrade Pods

- Fix refresh token when call response failure
- Various fix
- Release 0.7
This commit is contained in:
giuseppenuc committed 2016-04-19 16:35:26 +02:00
1 parent 6f2f24a533
commit f5750d801c
238 files changed
+4768 -3106

No files matched your search

@@ -44,6 +44,22 @@
*/
@property (nonatomic, copy) NSURL *previewImageURL __attribute__ ((deprecated("use appInvitePreviewImageURL instead")));
/*!
@abstract Promotional code to be displayed while sending and receiving the invite.
@discussion This is optional. This can be between 0 and 10 characters long and can contain
alphanumeric characters only. To set a promo code, you need to set promo text.
*/
@property (nonatomic, copy) NSString *promotionCode;
/*!
@abstract Promotional text to be displayed while sending and receiving the invite.
@discussion This is optional. This can be between 0 and 80 characters long and can contain
alphanumeric and spaces only.
*/
@property (nonatomic, copy) NSString *promotionText;
/*!
@abstract Compares the receiver to another app invite content.
@param content The other content
@@ -22,6 +22,9 @@
#define FBSDK_APP_INVITE_CONTENT_APP_LINK_URL_KEY @"appLinkURL"
#define FBSDK_APP_INVITE_CONTENT_PREVIEW_IMAGE_KEY @"previewImage"
#define FBSDK_APP_INVITE_CONTENT_PROMO_CODE_KEY @"promoCode"
#define FBSDK_APP_INVITE_CONTENT_PROMO_TEXT_KEY @"promoText"
@implementation FBSDKAppInviteContent
@@ -42,6 +45,8 @@
NSUInteger subhashes[] = {
[_appLinkURL hash],
[_appInvitePreviewImageURL hash],
[_promotionCode hash],
[_promotionText hash],
};
return [FBSDKMath hashWithIntegerArray:subhashes count:sizeof(subhashes) / sizeof(subhashes[0])];
}
@@ -61,7 +66,10 @@
{
return (content &&
[FBSDKInternalUtility object:_appLinkURL isEqualToObject:content.appLinkURL] &&
[FBSDKInternalUtility object:_appInvitePreviewImageURL isEqualToObject:content.appInvitePreviewImageURL]);
[FBSDKInternalUtility object:_appInvitePreviewImageURL isEqualToObject:content.appInvitePreviewImageURL] &&
[FBSDKInternalUtility object:_promotionText isEqualToObject:content.promotionText] &&
[FBSDKInternalUtility object:_promotionCode isEqualToObject:content.promotionText]
);
}
#pragma mark - NSCoding
@@ -76,6 +84,11 @@
if ((self = [self init])) {
_appLinkURL = [decoder decodeObjectOfClass:[NSURL class] forKey:FBSDK_APP_INVITE_CONTENT_APP_LINK_URL_KEY];
_appInvitePreviewImageURL = [decoder decodeObjectOfClass:[NSURL class] forKey:FBSDK_APP_INVITE_CONTENT_PREVIEW_IMAGE_KEY];
_promotionCode = [decoder decodeObjectOfClass:[NSString class] forKey:
FBSDK_APP_INVITE_CONTENT_PROMO_CODE_KEY];
_promotionText = [decoder decodeObjectOfClass:[NSString class] forKey:
FBSDK_APP_INVITE_CONTENT_PROMO_TEXT_KEY];
}
return self;
}
@@ -84,6 +97,9 @@
{
[encoder encodeObject:_appLinkURL forKey:FBSDK_APP_INVITE_CONTENT_APP_LINK_URL_KEY];
[encoder encodeObject:_appInvitePreviewImageURL forKey:FBSDK_APP_INVITE_CONTENT_PREVIEW_IMAGE_KEY];
[encoder encodeObject:_promotionCode forKey:FBSDK_APP_INVITE_CONTENT_PROMO_CODE_KEY];
[encoder encodeObject:_promotionText forKey:FBSDK_APP_INVITE_CONTENT_PROMO_TEXT_KEY];
}
#pragma mark - NSCopying
@@ -93,6 +109,8 @@
FBSDKAppInviteContent *copy = [[FBSDKAppInviteContent alloc] init];
copy->_appLinkURL = [_appLinkURL copy];
copy->_appInvitePreviewImageURL = [_appInvitePreviewImageURL copy];
copy->_promotionText = [_promotionText copy];
copy->_promotionCode = [_promotionCode copy];
return copy;
}
@@ -82,6 +82,23 @@
NSMutableDictionary *parameters = [[NSMutableDictionary alloc] init];
[FBSDKInternalUtility dictionary:parameters setObject:self.content.appLinkURL forKey:@"app_link_url"];
[FBSDKInternalUtility dictionary:parameters setObject:self.content.appInvitePreviewImageURL forKey:@"preview_image_url"];
if (self.content.promotionText) {
NSString *promotionCode = self.content.promotionCode ?: @"";
NSDictionary *deeplinkContext = @{@"promo_code" : promotionCode, @"promo_text" : self.content.promotionText};
NSError *jsonError = nil;
NSString *deeplinkContextString = [FBSDKInternalUtility JSONStringForObject:deeplinkContext error:&jsonError invalidObjectHandler:NULL];
if (!jsonError) {
[FBSDKInternalUtility dictionary:parameters setObject:promotionCode forKey:@"promo_code"];
[FBSDKInternalUtility dictionary:parameters setObject:self.content.promotionText forKey:@"promo_text"];
[FBSDKInternalUtility dictionary:parameters setObject:deeplinkContextString forKey:@"deeplink_context"];
} else {
[FBSDKLogger singleShotLogEntry:FBSDKLoggingBehaviorDeveloperErrors
formatString:@"Cannot convert deeplink_contex to json:"];
}
}
FBSDKBridgeAPIRequest *webBridgeRequest = [FBSDKBridgeAPIRequest bridgeAPIRequestWithProtocolType:FBSDKBridgeAPIProtocolTypeWeb
scheme:FBSDK_SHARE_JS_DIALOG_SCHEME
methodName:FBSDK_APP_INVITE_METHOD_NAME
@@ -0,0 +1,59 @@
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
//
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
// copy, modify, and distribute this software in source code or binary form for use
// in connection with the web services and APIs provided by Facebook.
//
// As with any software that integrates with the Facebook platform, your use of
// this software is subject to the Facebook Developer Principles and Policies
// [http://developers.facebook.com/policy/]. This copyright notice shall be
// included in all copies or substantial portions of the software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#import <Foundation/Foundation.h>
#import <FBSDKCoreKit/FBSDKCopying.h>
/*!
@abstract Represents a single hashtag that can be used with the share dialog.
*/
@interface FBSDKHashtag : NSObject <FBSDKCopying, NSSecureCoding>
/*!
@abstract Convenience method to build a new hashtag with a string identifier. Equivalent to setting the
`stringRepresentation` property.
@param hashtagString The hashtag string.
*/
+ (instancetype)hashtagWithString:(NSString *)hashtagString;
/*!
@abstract The hashtag string.
@discussion You are responsible for making sure that `stringRepresentation` is a valid hashtag (a single '#' followed
by one or more word characters). Invalid hashtags are ignored when sharing content. You can check validity with the
`valid` property.
@return The hashtag string.
*/
@property (nonatomic, readwrite, copy) NSString *stringRepresentation;
/*!
@abstract Tests if a hashtag is valid.
@discussion A valid hashtag matches the regular expression "#\w+": A single '#' followed by one or more
word characters.
@return YES if the hashtag is valid, NO otherwise.
*/
@property (nonatomic, readonly, assign, getter=isValid) BOOL valid;
/*!
@abstract Compares the receiver to another hashtag.
@param hashtag The other hashtag
@return YES if the receiver is equal to the other hashtag; otherwise NO
*/
- (BOOL)isEqualToHashtag:(FBSDKHashtag *)hashtag;
@end
@@ -0,0 +1,123 @@
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
//
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
// copy, modify, and distribute this software in source code or binary form for use
// in connection with the web services and APIs provided by Facebook.
//
// As with any software that integrates with the Facebook platform, your use of
// this software is subject to the Facebook Developer Principles and Policies
// [http://developers.facebook.com/policy/]. This copyright notice shall be
// included in all copies or substantial portions of the software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#import "FBSDKHashtag.h"
#import "FBSDKCoreKit+Internal.h"
#define FBSDK_HASHTAG_STRING_KEY @"hashtag"
static NSRegularExpression *HashtagRegularExpression()
{
static NSRegularExpression *hashtagRegularExpression = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
hashtagRegularExpression = [[NSRegularExpression alloc] initWithPattern:@"^#\\w+$" options:0 error:NULL];
});
return hashtagRegularExpression;
}
@implementation FBSDKHashtag
#pragma mark - Class Methods
+ (instancetype)hashtagWithString:(NSString *)hashtagString
{
FBSDKHashtag *hashtag = [[self alloc] init];
hashtag.stringRepresentation = hashtagString;
return hashtag;
}
#pragma mark - Properties
- (NSString *)description
{
if (self.valid) {
return _stringRepresentation;
} else {
return [NSString stringWithFormat:@"Invalid hashtag '%@'", _stringRepresentation];
}
}
- (BOOL)isValid
{
if (_stringRepresentation == nil) {
return NO;
}
NSRange fullString = NSMakeRange(0, _stringRepresentation.length);
NSRegularExpression *hashtagRegularExpression = HashtagRegularExpression();
NSUInteger numberOfMatches = [hashtagRegularExpression numberOfMatchesInString:_stringRepresentation
options:0
range:fullString];
return numberOfMatches > 0;
}
#pragma mark - Equality
- (NSUInteger)hash
{
return [_stringRepresentation hash];
}
- (BOOL)isEqual:(id)object
{
if (self == object) {
return YES;
}
if (![object isKindOfClass:[FBSDKHashtag class]]) {
return NO;
}
return [self isEqualToHashtag:(FBSDKHashtag *)object];
}
- (BOOL)isEqualToHashtag:(FBSDKHashtag *)hashtag
{
return (hashtag &&
[FBSDKInternalUtility object:_stringRepresentation isEqualToObject:hashtag.stringRepresentation]);
}
#pragma mark - NSCoding
+ (BOOL)supportsSecureCoding
{
return YES;
}
- (id)initWithCoder:(NSCoder *)aDecoder
{
if ((self = [self init])) {
_stringRepresentation = [aDecoder decodeObjectOfClass:[NSString class] forKey:FBSDK_HASHTAG_STRING_KEY];
}
return self;
}
- (void)encodeWithCoder:(NSCoder *)aCoder
{
[aCoder encodeObject:_stringRepresentation forKey:FBSDK_HASHTAG_STRING_KEY];
}
#pragma mark - NSCopying
- (id)copyWithZone:(NSZone *)zone
{
FBSDKHashtag *copy = [[FBSDKHashtag alloc] init];
copy.stringRepresentation = [_stringRepresentation copy];
return copy;
}
@end
@@ -25,6 +25,7 @@
#import "FBSDKShareDefines.h"
#import "FBSDKShareError.h"
#import "FBSDKShareLinkContent.h"
#import "FBSDKShareMediaContent.h"
#import "FBSDKShareOpenGraphAction.h"
#import "FBSDKShareOpenGraphContent.h"
#import "FBSDKShareOpenGraphObject.h"
@@ -34,8 +35,6 @@
#import "FBSDKShareVideo.h"
#import "FBSDKShareVideoContent.h"
#define FBSDK_SHARE_DIALOG_APP_SCHEME @"fbapi"
#define FBSDK_SHARE_EXTENSION_APP_SCHEME @"fbshareextension"
#define FBSDK_SHARE_FEED_METHOD_NAME @"feed"
#define FBSDK_SHARE_METHOD_MIN_VERSION @"20130410"
#define FBSDK_SHARE_METHOD_OG_MIN_VERSION @"20130214"
@@ -43,6 +42,25 @@
#define FBSDK_SHARE_METHOD_PHOTOS_MIN_VERSION @"20140116"
#define FBSDK_SHARE_METHOD_VIDEO_MIN_VERSION @"20150313"
#define FBSDK_SHARE_METHOD_ATTRIBUTED_SHARE_SHEET_MIN_VERSION @"20150629"
#define FBSDK_SHARE_METHOD_QUOTE_MIN_VERSION @"20160328"
#define FBSDK_SHARE_METHOD_MMP_MIN_VERSION @"20160328"
FBSDK_STATIC_INLINE void FBSDKShareDialogValidateAPISchemeRegisteredForCanOpenUrl()
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
[FBSDKInternalUtility checkRegisteredCanOpenURLScheme:FBSDK_CANOPENURL_FBAPI];
});
}
FBSDK_STATIC_INLINE void FBSDKShareDialogValidateShareExtensionSchemeRegisteredForCanOpenUrl()
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
[FBSDKInternalUtility checkRegisteredCanOpenURLScheme:FBSDK_CANOPENURL_SHARE_EXTENSION];
});
}
@interface FBSDKShareDialog () <FBSDKWebDialogDelegate>
@end
@@ -113,7 +131,7 @@
BOOL didShow = NO;
NSError *error = nil;
if ([self validateWithError:&error]) {
if ([self _validateWithError:&error]) {
switch (self.mode) {
case FBSDKShareDialogModeAutomatic:{
didShow = [self _showAutomatic:&error];
@@ -156,47 +174,7 @@
- (BOOL)validateWithError:(NSError *__autoreleasing *)errorRef
{
if (errorRef != NULL) {
*errorRef = nil;
}
id<FBSDKSharingContent> shareContent = self.shareContent;
if (!shareContent) {
if (errorRef != NULL) {
*errorRef = [FBSDKShareError requiredArgumentErrorWithName:@"shareContent" message:nil];
}
return NO;
}
if (![FBSDKShareUtility validateShareContent:shareContent error:errorRef]) {
return NO;
}
if ([shareContent isKindOfClass:[FBSDKShareVideoContent class]]) {
if (![FBSDKShareUtility validateAssetLibraryURLWithShareVideoContent:(FBSDKShareVideoContent *)shareContent name:@"videoURL" error:errorRef]) {
return NO;
}
}
switch (self.mode) {
case FBSDKShareDialogModeAutomatic:{
return (
([self _canShowNative] && [self _validateShareContentForNative:errorRef]) ||
([self _canShowShareSheet] && [self _validateShareContentForShareSheet:errorRef]) ||
[self _validateShareContentForFeed:errorRef] ||
[self _validateShareContentForBrowser:errorRef]);
}
case FBSDKShareDialogModeNative:{
return [self _validateShareContentForNative:errorRef];
}
case FBSDKShareDialogModeShareSheet:{
return [self _validateShareContentForShareSheet:errorRef];
}
case FBSDKShareDialogModeBrowser:
case FBSDKShareDialogModeWeb:{
return [self _validateShareContentForBrowser:errorRef];
}
case FBSDKShareDialogModeFeedBrowser:
case FBSDKShareDialogModeFeedWeb:{
return [self _validateShareContentForFeed:errorRef];
}
}
return [self _validateWithError:errorRef] && [self _validateFullyCompatibleWithError:errorRef];
}
#pragma mark - FBSDKWebDialogDelegate
@@ -245,6 +223,17 @@
return [configuration.defaultShareMode isEqualToString:@"share_sheet"];
}
- (BOOL)_isOpenGraphURLShare:(FBSDKShareOpenGraphContent *)shareContent
{
__block BOOL hasOGURL = NO;
[shareContent.action enumerateKeysAndObjectsUsingBlock:^(NSString *key, id object, BOOL *stop) {
if ([object isKindOfClass:[NSURL class]]) {
hasOGURL = YES;
}
}];
return hasOGURL;
}
-(BOOL)_showAutomatic:(NSError *__autoreleasing *)errorRef
{
BOOL isDefaultToShareSheet = [self _isDefaultToShareSheet];
@@ -280,7 +269,7 @@
if ([shareContent isKindOfClass:[FBSDKShareOpenGraphContent class]]) {
methodName = FBSDK_SHARE_OPEN_GRAPH_METHOD_NAME;
BOOL containsMedia = NO;
[FBSDKShareUtility testShareContent:shareContent containsMedia:&containsMedia containsPhotos:NULL];
[FBSDKShareUtility testShareContent:shareContent containsMedia:&containsMedia containsPhotos:NULL containsVideos:NULL];
if (containsMedia) {
methodVersion = FBSDK_SHARE_METHOD_OG_IMAGE_MIN_VERSION;
} else {
@@ -328,7 +317,8 @@
if (![FBSDKInternalUtility isOSRunTimeVersionAtLeast:iOS8Version]) {
return NO;
}
NSString *scheme = FBSDK_SHARE_DIALOG_APP_SCHEME;
FBSDKShareDialogValidateAPISchemeRegisteredForCanOpenUrl();
NSString *scheme = FBSDK_CANOPENURL_FBAPI;
NSString *minimumVersion = FBSDK_SHARE_METHOD_ATTRIBUTED_SHARE_SHEET_MIN_VERSION;
NSURLComponents *components = [[NSURLComponents alloc] init];
components.scheme = [scheme stringByAppendingString:minimumVersion];
@@ -343,8 +333,33 @@
if (![FBSDKInternalUtility isOSRunTimeVersionAtLeast:iOS8Version]) {
return NO;
}
FBSDKShareDialogValidateShareExtensionSchemeRegisteredForCanOpenUrl();
NSURLComponents *components = [[NSURLComponents alloc] init];
components.scheme = FBSDK_SHARE_EXTENSION_APP_SCHEME;
components.scheme = FBSDK_CANOPENURL_SHARE_EXTENSION;
components.path = @"/";
return [[UIApplication sharedApplication] canOpenURL:components.URL];
}
- (BOOL)_canUseQuoteInShareSheet
{
return [self _canUseFBShareSheet] && [self _supportsShareSheetMinimumVersion:FBSDK_SHARE_METHOD_QUOTE_MIN_VERSION];
}
- (BOOL)_canUseMMPInShareSheet
{
return [self _canUseFBShareSheet] && [self _supportsShareSheetMinimumVersion:FBSDK_SHARE_METHOD_MMP_MIN_VERSION];
}
- (BOOL)_supportsShareSheetMinimumVersion:(NSString *)minimumVersion
{
NSOperatingSystemVersion iOS8Version = { .majorVersion = 8, .minorVersion = 0, .patchVersion = 0 };
if (![FBSDKInternalUtility isOSRunTimeVersionAtLeast:iOS8Version]) {
return NO;
}
FBSDKShareDialogValidateAPISchemeRegisteredForCanOpenUrl();
NSString *scheme = FBSDK_CANOPENURL_FBAPI;
NSURLComponents *components = [[NSURLComponents alloc] init];
components.scheme = [scheme stringByAppendingString:minimumVersion];
components.path = @"/";
return [[UIApplication sharedApplication] canOpenURL:components.URL];
}
@@ -357,10 +372,43 @@
- (NSArray *)_contentImages
{
NSMutableArray *ret = [NSMutableArray new];
id<FBSDKSharingContent> shareContent = self.shareContent;
return ([shareContent isKindOfClass:[FBSDKSharePhotoContent class]] ?
[((FBSDKSharePhotoContent *)shareContent).photos valueForKeyPath:@"@distinctUnionOfObjects.image"] :
nil);
if ([shareContent isKindOfClass:[FBSDKSharePhotoContent class]]) {
[ret addObjectsFromArray:[((FBSDKSharePhotoContent *)shareContent).photos valueForKeyPath:@"@distinctUnionOfObjects.image"]];
} else if ([shareContent isKindOfClass:[FBSDKShareMediaContent class]]) {
for (id media in ((FBSDKShareMediaContent *)shareContent).media) {
if ([media isKindOfClass:[FBSDKSharePhoto class]]) {
UIImage *image = ((FBSDKSharePhoto *)media).image;
if (image != nil) {
[ret addObject:image];
}
}
}
}
return [ret copy];
}
- (NSArray *)_contentVideoURLs
{
NSMutableArray *ret = [NSMutableArray new];
id<FBSDKSharingContent> shareContent = self.shareContent;
if ([shareContent isKindOfClass:[FBSDKShareVideoContent class]]) {
NSURL *videoURL = ((FBSDKShareVideoContent *)shareContent).video.videoURL;
if (videoURL != nil) {
[ret addObject:videoURL];
}
} else if ([shareContent isKindOfClass:[FBSDKShareMediaContent class]]) {
for (id media in ((FBSDKShareMediaContent *)shareContent).media) {
if ([media isKindOfClass:[FBSDKShareVideo class]]) {
NSURL *videoURL = ((FBSDKShareVideo *)media).videoURL;
if (videoURL != nil) {
[ret addObject:videoURL];
}
}
}
}
return [ret copy];
}
- (NSArray *)_contentURLs
@@ -545,9 +593,7 @@
}
NSArray *images = [self _contentImages];
NSArray *URLs = [self _contentURLs];
NSURL *videoURL = ([self.shareContent isKindOfClass:[FBSDKShareVideoContent class]] ?
((FBSDKShareVideoContent *)self.shareContent).video.videoURL :
nil);
NSArray *videoURLs = [self _contentVideoURLs];
Class composeViewControllerClass = [fbsdkdfl_SLComposeViewControllerClass() class];
NSString *facebookServiceType = fbsdkdfl_SLServiceTypeFacebook();
@@ -561,17 +607,19 @@
}
return NO;
}
if ([self _canAttributeThroughShareSheet]) {
NSString *attributionToken = [NSString stringWithFormat:@"fb-app-id:%@", [FBSDKSettings appID]];
[composeViewController setInitialText:attributionToken];
NSString *initialText = [self _calculateInitialText];
if (initialText.length > 0) {
[composeViewController setInitialText:initialText];
}
for (UIImage *image in images) {
[composeViewController addImage:image];
}
for (NSURL *URL in URLs) {
[composeViewController addURL:URL];
}
if (videoURL) {
for (NSURL *videoURL in videoURLs) {
[composeViewController addURL:videoURL];
}
composeViewController.completionHandler = ^(SLComposeViewControllerResult result) {
@@ -625,12 +673,105 @@
return [configuration useSafariViewControllerForDialogName:FBSDKDialogConfigurationNameShare];
}
- (BOOL)_validateWithError:(NSError *__autoreleasing *)errorRef
{
if (errorRef != NULL) {
*errorRef = nil;
}
id<FBSDKSharingContent> shareContent = self.shareContent;
if (!shareContent) {
if (errorRef != NULL) {
*errorRef = [FBSDKShareError requiredArgumentErrorWithName:@"shareContent" message:nil];
}
return NO;
}
if (![FBSDKShareUtility validateShareContent:shareContent error:errorRef]) {
return NO;
}
if ([shareContent isKindOfClass:[FBSDKShareVideoContent class]]) {
if (![FBSDKShareUtility validateAssetLibraryURLWithShareVideoContent:(FBSDKShareVideoContent *)shareContent name:@"videoURL" error:errorRef]) {
return NO;
}
}
if ([shareContent isKindOfClass:[FBSDKShareMediaContent class]]) {
if (![FBSDKShareUtility validateAssetLibraryURLsWithShareMediaContent:(FBSDKShareMediaContent *)shareContent name:@"mediaVideoURL" error:errorRef]) {
return NO;
}
}
switch (self.mode) {
case FBSDKShareDialogModeAutomatic:{
return (
([self _canShowNative] && [self _validateShareContentForNative:errorRef]) ||
([self _canShowShareSheet] && [self _validateShareContentForShareSheet:errorRef]) ||
[self _validateShareContentForFeed:errorRef] ||
[self _validateShareContentForBrowser:errorRef]);
}
case FBSDKShareDialogModeNative:{
return [self _validateShareContentForNative:errorRef];
}
case FBSDKShareDialogModeShareSheet:{
return [self _validateShareContentForShareSheet:errorRef];
}
case FBSDKShareDialogModeBrowser:
case FBSDKShareDialogModeWeb:{
return [self _validateShareContentForBrowser:errorRef];
}
case FBSDKShareDialogModeFeedBrowser:
case FBSDKShareDialogModeFeedWeb:{
return [self _validateShareContentForFeed:errorRef];
}
}
}
/**
`validateWithError:` can be used by clients of this API to discover if certain features are
available for a specific `mode`. However, these features could be optional for said `mode`, in which
case `validateWithError:` should return NO but when calling `show`, the dialog must still show.
ie: Quotes are only available if FB for iOS v52 or higher is installed. If the client adds a quote to
the `ShareLinkContent` object and FB for iOS v52 or higher is not installed, `validateWithError:` will
return NO if the `mode` is set to ShareSheet. However, calling `show` will actually show the shareSheet
without the Quote.
This method exists to enable the behavior described above and should only be called from `validateWithError:`.
*/
- (BOOL)_validateFullyCompatibleWithError:(NSError *__autoreleasing *)errorRef
{
id<FBSDKSharingContent> shareContent = self.shareContent;
if ([shareContent isKindOfClass:[FBSDKShareLinkContent class]]) {
FBSDKShareLinkContent *shareLinkContent = (FBSDKShareLinkContent *)shareContent;
if (shareLinkContent.quote.length > 0 &&
self.mode == FBSDKShareDialogModeShareSheet &&
![self _canUseQuoteInShareSheet]) {
if ((errorRef != NULL) && !*errorRef) {
*errorRef = [FBSDKShareError invalidArgumentErrorWithName:@"shareContent"
value:shareLinkContent
message:@"Quotes are only supported if Facebook for iOS version 52 and above is installed"];
}
return NO;
}
} else if ([shareContent isKindOfClass:[FBSDKShareMediaContent class]]) {
FBSDKShareMediaContent *mediaContent = (FBSDKShareMediaContent *)shareContent;
if ([FBSDKShareUtility shareMediaContentContainsPhotosAndVideos:mediaContent] &&
self.mode == FBSDKShareDialogModeShareSheet &&
![self _canUseMMPInShareSheet]) {
if ((errorRef != NULL) && !*errorRef) {
*errorRef = [FBSDKShareError invalidArgumentErrorWithName:@"shareContent"
value:shareContent
message:@"Multimedia content (photos + videos) is only supported if Facebook for iOS version 52 and above is installed"];
}
return NO;
}
}
return YES;
}
- (BOOL)_validateShareContentForBrowser:(NSError **)errorRef
{
id<FBSDKSharingContent> shareContent = self.shareContent;
BOOL containsMedia;
BOOL containsPhotos;
[FBSDKShareUtility testShareContent:shareContent containsMedia:&containsMedia containsPhotos:&containsPhotos];
[FBSDKShareUtility testShareContent:shareContent containsMedia:&containsMedia containsPhotos:&containsPhotos containsVideos:NULL];
if (containsPhotos) {
if ((errorRef != NULL) && !*errorRef) {
*errorRef = [FBSDKShareError invalidArgumentErrorWithName:@"shareContent"
@@ -667,6 +808,16 @@
- (BOOL)_validateShareContentForNative:(NSError **)errorRef
{
id<FBSDKSharingContent> shareContent = self.shareContent;
if ([shareContent isKindOfClass:[FBSDKShareMediaContent class]]) {
if ([FBSDKShareUtility shareMediaContentContainsPhotosAndVideos:(FBSDKShareMediaContent *)shareContent]) {
if ((errorRef != NULL) && !*errorRef) {
*errorRef = [FBSDKShareError invalidArgumentErrorWithName:@"shareContent"
value:shareContent
message:@"Multimedia Content is only available for mode `ShareSheet`"];
}
return NO;
}
}
if (![shareContent isKindOfClass:[FBSDKShareVideoContent class]]) {
return YES;
}
@@ -689,9 +840,26 @@
} else if ([shareContent isKindOfClass:[FBSDKShareVideoContent class]]) {
return ([self _canUseFBShareSheet] &&
[self _validateVideoURL:((FBSDKShareVideoContent *)shareContent).video.videoURL error:errorRef]);
} else if ([shareContent isKindOfClass:[FBSDKShareMediaContent class]]) {
return ([self _canUseFBShareSheet] &&
[FBSDKShareUtility validateShareMediaContent:(FBSDKShareMediaContent *)shareContent error:errorRef]);
} else if ([shareContent isKindOfClass:[FBSDKShareOpenGraphContent class]]) {
FBSDKShareOpenGraphContent *ogContent = (FBSDKShareOpenGraphContent *)shareContent;
BOOL isOGURLShare = [self _isOpenGraphURLShare:ogContent];
BOOL isValidOGShare = (isOGURLShare &&
[ogContent.action.actionType length] != 0 &&
[ogContent.previewPropertyName length] != 0);
if (!isValidOGShare) {
if ((errorRef != NULL) && !*errorRef) {
NSString *message = @"Share content must include an URL in the action, an action type, and a preview property name in order to share with the share sheet.";
*errorRef = [FBSDKShareError invalidArgumentErrorWithName:@"shareContent" value:shareContent message:message];
}
}
return isValidOGShare;
} else if (![shareContent isKindOfClass:[FBSDKShareLinkContent class]]) {
if ((errorRef != NULL) && !*errorRef) {
NSString *message = @"Share content must be FBSDKShareLinkContent or FBSDKSharePhotoContent in order to share "
NSString *message = @"Share content must be FBSDKShareLinkContent or FBSDKShareMediaContent in order to share "
@"with the share sheet.";
*errorRef = [FBSDKShareError invalidArgumentErrorWithName:@"shareContent" value:shareContent message:message];
}
@@ -785,4 +953,58 @@
accessToken:[FBSDKAccessToken currentAccessToken]];
}
- (NSString *)_calculateInitialText
{
NSString *initialText;
if ([self _canAttributeThroughShareSheet]) {
NSMutableDictionary *initialTextDictionary = [NSMutableDictionary new];
initialTextDictionary[@"app_id"] = [FBSDKSettings appID];
NSString *hashtag = [FBSDKShareUtility hashtagStringFromHashtag:self.shareContent.hashtag];
if (hashtag != nil) {
initialTextDictionary[@"hashtags"] = @[hashtag];
}
if ([self.shareContent isKindOfClass:[FBSDKShareLinkContent class]]) {
NSString *quote = [(FBSDKShareLinkContent *)self.shareContent quote];
if (quote != nil) {
initialTextDictionary[@"quotes"] = @[quote];
}
}
if ([self.shareContent isKindOfClass:[FBSDKShareOpenGraphContent class]]) {
NSDictionary *ogData = [FBSDKShareUtility parametersForShareContent:self.shareContent
shouldFailOnDataError:self.shouldFailOnDataError];
initialTextDictionary[@"og_data"] = ogData;
}
NSError *error = nil;
NSString *jsonString = [FBSDKInternalUtility JSONStringForObject:initialTextDictionary error:&error invalidObjectHandler:NULL];
if (error != nil) {
return nil;
}
NSString *JSONStartDelimiter = @"|";
initialText = [NSString stringWithFormat:@"%@%@%@",
[self _calculatePreJSONInitialTextWithHashtag:hashtag],
JSONStartDelimiter,
jsonString];
} else {
NSString *hashtag = [FBSDKShareUtility hashtagStringFromHashtag:self.shareContent.hashtag];
if (hashtag != nil) {
initialText = hashtag;
}
}
return initialText;
}
// Not all versions of the Share Extension support JSON. Adding this text before allows backward compatibility
- (NSString *)_calculatePreJSONInitialTextWithHashtag:(NSString *)hashtag
{
NSMutableString *text = [NSMutableString new];
[text appendString:[NSString stringWithFormat:@"fb-app-id:%@", [FBSDKSettings appID]]];
if (hashtag != nil) {
[text appendString:@" "];
[text appendString:hashtag];
}
return [text copy];
}
@end
@@ -18,6 +18,7 @@
#import <UIKit/UIKit.h>
#import <FBSDKShareKit/FBSDKHashtag.h>
#import <FBSDKShareKit/FBSDKShareAPI.h>
#import <FBSDKShareKit/FBSDKShareConstants.h>
#import <FBSDKShareKit/FBSDKShareLinkContent.h>
@@ -46,5 +47,9 @@
#import <FBSDKShareKit/FBSDKShareButton.h>
#import <FBSDKShareKit/FBSDKShareDialog.h>
#import <FBSDKShareKit/FBSDKShareDialogMode.h>
#import <FBSDKShareKit/FBSDKShareMediaContent.h>
#import <FBSDKShareKit/FBSDKSendButton.h>
#else
#import <FBSDKShareKit/FBSDKDeviceShareViewController.h>
#import <FBSDKShareKit/FBSDKDeviceShareButton.h>
#endif
@@ -46,6 +46,13 @@
*/
@property (nonatomic, copy) NSURL *imageURL;
/*!
@abstract Some quote text of the link.
@discussion If specified, the quote text will render with custom styling on top of the link.
@return The quote text of a link
*/
@property (nonatomic, copy) NSString *quote;
/*!
@abstract Compares the receiver to another link content.
@param content The other content
@@ -19,15 +19,18 @@
#import "FBSDKShareLinkContent+Internal.h"
#import "FBSDKCoreKit+Internal.h"
#import "FBSDKHashtag.h"
#import "FBSDKShareUtility.h"
#define FBSDK_SHARE_STATUS_CONTENT_CONTENT_DESCRIPTION_KEY @"contentDescription"
#define FBSDK_SHARE_STATUS_CONTENT_CONTENT_TITLE_KEY @"contentTitle"
#define FBSDK_SHARE_STATUS_CONTENT_CONTENT_URL_KEY @"contentURL"
#define FBSDK_SHARE_STATUS_CONTENT_HASHTAG_KEY @"hashtag"
#define FBSDK_SHARE_STATUS_CONTENT_IMAGE_URL_KEY @"imageURL"
#define FBSDK_SHARE_STATUS_CONTENT_PEOPLE_IDS_KEY @"peopleIDs"
#define FBSDK_SHARE_STATUS_CONTENT_PLACE_ID_KEY @"placeID"
#define FBSDK_SHARE_STATUS_CONTENT_REF_KEY @"ref"
#define FBSDK_SHARE_STATUS_CONTENT_QUOTE_TEXT_KEY @"quote"
#define FBSDK_SHARE_STATUS_CONTENT_FEED_PARAMETERS_KEY @"feedParameters"
@implementation FBSDKShareLinkContent
@@ -35,10 +38,12 @@
#pragma mark - Properties
@synthesize contentURL = _contentURL;
@synthesize hashtag = _hashtag;
@synthesize peopleIDs = _peopleIDs;
@synthesize placeID = _placeID;
@synthesize ref = _ref;
@synthesize feedParameters = _feedParameters;
@synthesize quote = _quote;
- (void)setPeopleIDs:(NSArray *)peopleIDs
{
@@ -62,12 +67,14 @@
NSUInteger subhashes[] = {
[_contentDescription hash],
[_contentURL hash],
[_hashtag hash],
[_imageURL hash],
[_peopleIDs hash],
[_placeID hash],
[_ref hash],
[_contentTitle hash],
[_feedParameters hash],
[_quote hash],
};
return [FBSDKMath hashWithIntegerArray:subhashes count:sizeof(subhashes) / sizeof(subhashes[0])];
}
@@ -89,11 +96,13 @@
[FBSDKInternalUtility object:_contentDescription isEqualToObject:content.contentDescription] &&
[FBSDKInternalUtility object:_contentTitle isEqualToObject:content.contentTitle] &&
[FBSDKInternalUtility object:_contentURL isEqualToObject:content.contentURL] &&
[FBSDKInternalUtility object:_hashtag isEqualToObject:content.hashtag] &&
[FBSDKInternalUtility object:_feedParameters isEqualToObject:content.feedParameters] &&
[FBSDKInternalUtility object:_imageURL isEqualToObject:content.imageURL] &&
[FBSDKInternalUtility object:_peopleIDs isEqualToObject:content.peopleIDs] &&
[FBSDKInternalUtility object:_placeID isEqualToObject:content.placeID] &&
[FBSDKInternalUtility object:_ref isEqualToObject:content.ref]);
[FBSDKInternalUtility object:_ref isEqualToObject:content.ref]) &&
[FBSDKInternalUtility object:_quote isEqualToObject:content.quote];
}
#pragma mark - NSCoding
@@ -111,10 +120,12 @@
_contentTitle = [decoder decodeObjectOfClass:[NSString class] forKey:FBSDK_SHARE_STATUS_CONTENT_CONTENT_TITLE_KEY];
_contentURL = [decoder decodeObjectOfClass:[NSURL class] forKey:FBSDK_SHARE_STATUS_CONTENT_CONTENT_URL_KEY];
_feedParameters = [decoder decodeObjectOfClass:[NSDictionary class] forKey:FBSDK_SHARE_STATUS_CONTENT_FEED_PARAMETERS_KEY];
_hashtag = [decoder decodeObjectOfClass:[FBSDKHashtag class] forKey:FBSDK_SHARE_STATUS_CONTENT_HASHTAG_KEY];
_imageURL = [decoder decodeObjectOfClass:[NSURL class] forKey:FBSDK_SHARE_STATUS_CONTENT_IMAGE_URL_KEY];
_peopleIDs = [decoder decodeObjectOfClass:[NSArray class] forKey:FBSDK_SHARE_STATUS_CONTENT_PEOPLE_IDS_KEY];
_placeID = [decoder decodeObjectOfClass:[NSString class] forKey:FBSDK_SHARE_STATUS_CONTENT_PLACE_ID_KEY];
_ref = [decoder decodeObjectOfClass:[NSString class] forKey:FBSDK_SHARE_STATUS_CONTENT_REF_KEY];
_quote = [decoder decodeObjectOfClass:[NSString class] forKey:FBSDK_SHARE_STATUS_CONTENT_QUOTE_TEXT_KEY];
}
return self;
}
@@ -125,10 +136,12 @@
[encoder encodeObject:_contentTitle forKey:FBSDK_SHARE_STATUS_CONTENT_CONTENT_TITLE_KEY];
[encoder encodeObject:_contentURL forKey:FBSDK_SHARE_STATUS_CONTENT_CONTENT_URL_KEY];
[encoder encodeObject:_feedParameters forKey:FBSDK_SHARE_STATUS_CONTENT_FEED_PARAMETERS_KEY];
[encoder encodeObject:_hashtag forKey:FBSDK_SHARE_STATUS_CONTENT_HASHTAG_KEY];
[encoder encodeObject:_imageURL forKey:FBSDK_SHARE_STATUS_CONTENT_IMAGE_URL_KEY];
[encoder encodeObject:_peopleIDs forKey:FBSDK_SHARE_STATUS_CONTENT_PEOPLE_IDS_KEY];
[encoder encodeObject:_placeID forKey:FBSDK_SHARE_STATUS_CONTENT_PLACE_ID_KEY];
[encoder encodeObject:_ref forKey:FBSDK_SHARE_STATUS_CONTENT_REF_KEY];
[encoder encodeObject:_quote forKey:FBSDK_SHARE_STATUS_CONTENT_QUOTE_TEXT_KEY];
}
#pragma mark - NSCopying
@@ -140,10 +153,12 @@
copy->_contentTitle = [_contentTitle copy];
copy->_contentURL = [_contentURL copy];
copy->_feedParameters = [_feedParameters copy];
copy->_hashtag = [_hashtag copy];
copy->_imageURL = [_imageURL copy];
copy->_peopleIDs = [_peopleIDs copy];
copy->_placeID = [_placeID copy];
copy->_ref = [_ref copy];
copy->_quote = [_quote copy];
return copy;
}
@@ -0,0 +1,41 @@
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
//
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
// copy, modify, and distribute this software in source code or binary form for use
// in connection with the web services and APIs provided by Facebook.
//
// As with any software that integrates with the Facebook platform, your use of
// this software is subject to the Facebook Developer Principles and Policies
// [http://developers.facebook.com/policy/]. This copyright notice shall be
// included in all copies or substantial portions of the software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#import <Foundation/Foundation.h>
#import <FBSDKShareKit/FBSDKSharingContent.h>
/*!
@abstract A model for media content (photo or video) to be shared.
*/
@interface FBSDKShareMediaContent : NSObject <FBSDKSharingContent>
/*!
@abstract Media to be shared.
@return Array of the media (FBSDKSharePhoto or FBSDKShareVideo)
*/
@property (nonatomic, copy) NSArray *media;
/*!
@abstract Compares the receiver to another media content.
@param content The other content
@return YES if the receiver's values are equal to the other content's values; otherwise NO
*/
- (BOOL)isEqualToShareMediaContent:(FBSDKShareMediaContent *)content;
@end
@@ -0,0 +1,142 @@
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
//
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
// copy, modify, and distribute this software in source code or binary form for use
// in connection with the web services and APIs provided by Facebook.
//
// As with any software that integrates with the Facebook platform, your use of
// this software is subject to the Facebook Developer Principles and Policies
// [http://developers.facebook.com/policy/]. This copyright notice shall be
// included in all copies or substantial portions of the software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#import "FBSDKShareMediaContent.h"
#import "FBSDKCoreKit+Internal.h"
#import "FBSDKHashtag.h"
#import "FBSDKSharePhoto.h"
#import "FBSDKShareUtility.h"
#import "FBSDKShareVideo.h"
#define FBSDK_SHARE_MEDIA_CONTENT_CONTENT_URL_KEY @"contentURL"
#define FBSDK_SHARE_MEDIA_CONTENT_HASHTAG_KEY @"hashtag"
#define FBSDK_SHARE_MEDIA_CONTENT_PEOPLE_IDS_KEY @"peopleIDs"
#define FBSDK_SHARE_MEDIA_CONTENT_MEDIA_KEY @"media"
#define FBSDK_SHARE_MEDIA_CONTENT_PLACE_ID_KEY @"placeID"
#define FBSDK_SHARE_MEDIA_CONTENT_REF_KEY @"ref"
@implementation FBSDKShareMediaContent
#pragma mark - Properties
@synthesize contentURL = _contentURL;
@synthesize hashtag = _hashtag;
@synthesize peopleIDs = _peopleIDs;
@synthesize placeID = _placeID;
@synthesize ref = _ref;
- (void)setPeopleIDs:(NSArray *)peopleIDs
{
[FBSDKShareUtility assertCollection:peopleIDs ofClass:[NSString class] name:@"peopleIDs"];
if (![FBSDKInternalUtility object:_peopleIDs isEqualToObject:peopleIDs]) {
_peopleIDs = [peopleIDs copy];
}
}
- (void)setMedia:(NSArray *)media
{
[FBSDKShareUtility assertCollection:media ofClassStrings:@[NSStringFromClass([FBSDKSharePhoto class]), NSStringFromClass([FBSDKShareVideo class])] name:@"media"];
if (![FBSDKInternalUtility object:_media isEqualToObject:media]) {
_media = [media copy];
}
}
#pragma mark - Equality
- (NSUInteger)hash
{
NSUInteger subhashes[] = {
[_contentURL hash],
[_hashtag hash],
[_peopleIDs hash],
[_media hash],
[_placeID hash],
[_ref hash],
};
return [FBSDKMath hashWithIntegerArray:subhashes count:sizeof(subhashes) / sizeof(subhashes[0])];
}
- (BOOL)isEqual:(id)object
{
if (self == object) {
return YES;
}
if (![object isKindOfClass:[FBSDKShareMediaContent class]]) {
return NO;
}
return [self isEqualToShareMediaContent:(FBSDKShareMediaContent *)object];
}
- (BOOL)isEqualToShareMediaContent:(FBSDKShareMediaContent *)content
{
return (content &&
[FBSDKInternalUtility object:_contentURL isEqualToObject:content.contentURL] &&
[FBSDKInternalUtility object:_hashtag isEqualToObject:content.hashtag] &&
[FBSDKInternalUtility object:_peopleIDs isEqualToObject:content.peopleIDs] &&
[FBSDKInternalUtility object:_media isEqualToObject:content.media] &&
[FBSDKInternalUtility object:_placeID isEqualToObject:content.placeID] &&
[FBSDKInternalUtility object:_ref isEqualToObject:content.ref]);
}
#pragma mark - NSCoding
+ (BOOL)supportsSecureCoding
{
return YES;
}
- (id)initWithCoder:(NSCoder *)decoder
{
if ((self = [self init])) {
_contentURL = [decoder decodeObjectOfClass:[NSURL class] forKey:FBSDK_SHARE_MEDIA_CONTENT_CONTENT_URL_KEY];
_hashtag = [decoder decodeObjectOfClass:[FBSDKHashtag class] forKey:FBSDK_SHARE_MEDIA_CONTENT_HASHTAG_KEY];
_peopleIDs = [decoder decodeObjectOfClass:[NSArray class] forKey:FBSDK_SHARE_MEDIA_CONTENT_PEOPLE_IDS_KEY];
NSSet *classes = [NSSet setWithObjects:[NSArray class], [FBSDKSharePhoto class], nil];
_media = [decoder decodeObjectOfClasses:classes forKey:FBSDK_SHARE_MEDIA_CONTENT_MEDIA_KEY];
_placeID = [decoder decodeObjectOfClass:[NSString class] forKey:FBSDK_SHARE_MEDIA_CONTENT_PLACE_ID_KEY];
_ref = [decoder decodeObjectOfClass:[NSString class] forKey:FBSDK_SHARE_MEDIA_CONTENT_REF_KEY];
}
return self;
}
- (void)encodeWithCoder:(NSCoder *)encoder
{
[encoder encodeObject:_contentURL forKey:FBSDK_SHARE_MEDIA_CONTENT_CONTENT_URL_KEY];
[encoder encodeObject:_hashtag forKey:FBSDK_SHARE_MEDIA_CONTENT_HASHTAG_KEY];
[encoder encodeObject:_peopleIDs forKey:FBSDK_SHARE_MEDIA_CONTENT_PEOPLE_IDS_KEY];
[encoder encodeObject:_media forKey:FBSDK_SHARE_MEDIA_CONTENT_MEDIA_KEY];
[encoder encodeObject:_placeID forKey:FBSDK_SHARE_MEDIA_CONTENT_PLACE_ID_KEY];
[encoder encodeObject:_ref forKey:FBSDK_SHARE_MEDIA_CONTENT_REF_KEY];
}
#pragma mark - NSCopying
- (id)copyWithZone:(NSZone *)zone
{
FBSDKShareMediaContent *copy = [[FBSDKShareMediaContent alloc] init];
copy->_contentURL = [_contentURL copy];
copy->_hashtag = [_hashtag copy];
copy->_peopleIDs = [_peopleIDs copy];
copy->_media = [_media copy];
copy->_placeID = [_placeID copy];
copy->_ref = [_ref copy];
return copy;
}
@end
@@ -19,11 +19,13 @@
#import "FBSDKShareOpenGraphContent.h"
#import "FBSDKCoreKit+Internal.h"
#import "FBSDKHashtag.h"
#import "FBSDKSharePhoto.h"
#import "FBSDKShareUtility.h"
#define FBSDK_SHARE_OPEN_GRAPH_CONTENT_ACTION_KEY @"action"
#define FBSDK_SHARE_OPEN_GRAPH_CONTENT_CONTENT_URL_KEY @"contentURL"
#define FBSDK_SHARE_OPEN_GRAPH_CONTENT_HASHTAG_KEY @"hashtag"
#define FBSDK_SHARE_OPEN_GRAPH_CONTENT_PEOPLE_IDS_KEY @"peopleIDs"
#define FBSDK_SHARE_OPEN_GRAPH_CONTENT_PLACE_ID_KEY @"placeID"
#define FBSDK_SHARE_OPEN_GRAPH_CONTENT_PREVIEW_PROPERTY_NAME_KEY @"previewPropertyName"
@@ -34,6 +36,7 @@
#pragma mark - Properties
@synthesize contentURL = _contentURL;
@synthesize hashtag = _hashtag;
@synthesize peopleIDs = _peopleIDs;
@synthesize placeID = _placeID;
@synthesize ref = _ref;
@@ -53,6 +56,7 @@
NSUInteger subhashes[] = {
[_action hash],
[_contentURL hash],
[_hashtag hash],
[_peopleIDs hash],
[_placeID hash],
[_previewPropertyName hash],
@@ -77,6 +81,7 @@
return (content &&
[FBSDKInternalUtility object:_action isEqualToObject:content.action] &&
[FBSDKInternalUtility object:_contentURL isEqualToObject:content.contentURL] &&
[FBSDKInternalUtility object:_hashtag isEqualToObject:content.hashtag] &&
[FBSDKInternalUtility object:_peopleIDs isEqualToObject:content.peopleIDs] &&
[FBSDKInternalUtility object:_placeID isEqualToObject:content.placeID] &&
[FBSDKInternalUtility object:_previewPropertyName isEqualToObject:content.previewPropertyName] &&
@@ -96,6 +101,7 @@
_action = [decoder decodeObjectOfClass:[FBSDKShareOpenGraphAction class]
forKey:FBSDK_SHARE_OPEN_GRAPH_CONTENT_ACTION_KEY];
_contentURL = [decoder decodeObjectOfClass:[NSURL class] forKey:FBSDK_SHARE_OPEN_GRAPH_CONTENT_CONTENT_URL_KEY];
_hashtag = [decoder decodeObjectOfClass:[FBSDKHashtag class] forKey:FBSDK_SHARE_OPEN_GRAPH_CONTENT_HASHTAG_KEY];
_peopleIDs = [decoder decodeObjectOfClass:[NSArray class] forKey:FBSDK_SHARE_OPEN_GRAPH_CONTENT_PEOPLE_IDS_KEY];
_placeID = [decoder decodeObjectOfClass:[NSString class] forKey:FBSDK_SHARE_OPEN_GRAPH_CONTENT_PLACE_ID_KEY];
_previewPropertyName = [decoder decodeObjectOfClass:[NSString class]
@@ -109,6 +115,7 @@
{
[encoder encodeObject:_action forKey:FBSDK_SHARE_OPEN_GRAPH_CONTENT_ACTION_KEY];
[encoder encodeObject:_contentURL forKey:FBSDK_SHARE_OPEN_GRAPH_CONTENT_CONTENT_URL_KEY];
[encoder encodeObject:_hashtag forKey:FBSDK_SHARE_OPEN_GRAPH_CONTENT_HASHTAG_KEY];
[encoder encodeObject:_peopleIDs forKey:FBSDK_SHARE_OPEN_GRAPH_CONTENT_PEOPLE_IDS_KEY];
[encoder encodeObject:_placeID forKey:FBSDK_SHARE_OPEN_GRAPH_CONTENT_PLACE_ID_KEY];
[encoder encodeObject:_previewPropertyName forKey:FBSDK_SHARE_OPEN_GRAPH_CONTENT_PREVIEW_PROPERTY_NAME_KEY];
@@ -122,6 +129,7 @@
FBSDKShareOpenGraphContent *copy = [[FBSDKShareOpenGraphContent alloc] init];
copy->_action = [_action copy];
copy->_contentURL = [_contentURL copy];
copy->_hashtag = [_hashtag copy];
copy->_peopleIDs = [_peopleIDs copy];
copy->_placeID = [_placeID copy];
copy->_previewPropertyName = [_previewPropertyName copy];
@@ -19,10 +19,12 @@
#import "FBSDKSharePhotoContent.h"
#import "FBSDKCoreKit+Internal.h"
#import "FBSDKHashtag.h"
#import "FBSDKSharePhoto.h"
#import "FBSDKShareUtility.h"
#define FBSDK_SHARE_PHOTO_CONTENT_CONTENT_URL_KEY @"contentURL"
#define FBSDK_SHARE_PHOTO_CONTENT_HASHTAG_KEY @"hashtag"
#define FBSDK_SHARE_PHOTO_CONTENT_PEOPLE_IDS_KEY @"peopleIDs"
#define FBSDK_SHARE_PHOTO_CONTENT_PHOTOS_KEY @"photos"
#define FBSDK_SHARE_PHOTO_CONTENT_PLACE_ID_KEY @"placeID"
@@ -33,6 +35,7 @@
#pragma mark - Properties
@synthesize contentURL = _contentURL;
@synthesize hashtag = _hashtag;
@synthesize peopleIDs = _peopleIDs;
@synthesize placeID = _placeID;
@synthesize ref = _ref;
@@ -59,6 +62,7 @@
{
NSUInteger subhashes[] = {
[_contentURL hash],
[_hashtag hash],
[_peopleIDs hash],
[_photos hash],
[_placeID hash],
@@ -82,6 +86,7 @@
{
return (content &&
[FBSDKInternalUtility object:_contentURL isEqualToObject:content.contentURL] &&
[FBSDKInternalUtility object:_hashtag isEqualToObject:content.hashtag] &&
[FBSDKInternalUtility object:_peopleIDs isEqualToObject:content.peopleIDs] &&
[FBSDKInternalUtility object:_photos isEqualToObject:content.photos] &&
[FBSDKInternalUtility object:_placeID isEqualToObject:content.placeID] &&
@@ -99,6 +104,7 @@
{
if ((self = [self init])) {
_contentURL = [decoder decodeObjectOfClass:[NSURL class] forKey:FBSDK_SHARE_PHOTO_CONTENT_CONTENT_URL_KEY];
_hashtag = [decoder decodeObjectOfClass:[FBSDKHashtag class] forKey:FBSDK_SHARE_PHOTO_CONTENT_HASHTAG_KEY];
_peopleIDs = [decoder decodeObjectOfClass:[NSArray class] forKey:FBSDK_SHARE_PHOTO_CONTENT_PEOPLE_IDS_KEY];
NSSet *classes = [NSSet setWithObjects:[NSArray class], [FBSDKSharePhoto class], nil];
_photos = [decoder decodeObjectOfClasses:classes forKey:FBSDK_SHARE_PHOTO_CONTENT_PHOTOS_KEY];
@@ -111,6 +117,7 @@
- (void)encodeWithCoder:(NSCoder *)encoder
{
[encoder encodeObject:_contentURL forKey:FBSDK_SHARE_PHOTO_CONTENT_CONTENT_URL_KEY];
[encoder encodeObject:_hashtag forKey:FBSDK_SHARE_PHOTO_CONTENT_HASHTAG_KEY];
[encoder encodeObject:_peopleIDs forKey:FBSDK_SHARE_PHOTO_CONTENT_PEOPLE_IDS_KEY];
[encoder encodeObject:_photos forKey:FBSDK_SHARE_PHOTO_CONTENT_PHOTOS_KEY];
[encoder encodeObject:_placeID forKey:FBSDK_SHARE_PHOTO_CONTENT_PLACE_ID_KEY];
@@ -123,6 +130,7 @@
{
FBSDKSharePhotoContent *copy = [[FBSDKSharePhotoContent alloc] init];
copy->_contentURL = [_contentURL copy];
copy->_hashtag = [_hashtag copy];
copy->_peopleIDs = [_peopleIDs copy];
copy->_photos = [_photos copy];
copy->_placeID = [_placeID copy];
@@ -20,6 +20,8 @@
#import <FBSDKCoreKit/FBSDKCopying.h>
@class FBSDKSharePhoto;
/*!
@abstract A video for sharing.
*/
@@ -28,16 +30,28 @@
/*!
@abstract Convenience method to build a new video object with a videoURL.
@param videoURL The URL to the video
application
*/
+ (instancetype)videoWithVideoURL:(NSURL *)videoURL;
/*!
@abstract Convenience method to build a new video object with a videoURL and a previewPhoto
@param videoURL The URL to the video
@param previewPhoto The photo that represents the video
*/
+ (instancetype)videoWithVideoURL:(NSURL *)videoURL previewPhoto:(FBSDKSharePhoto *)previewPhoto;
/*!
@abstract The file URL to the video.
@return URL that points to the location of the video on disk
*/
@property (nonatomic, copy) NSURL *videoURL;
/*!
@abstract The photo that represents the video.
@return The photo
*/
@property (nonatomic, copy) FBSDKSharePhoto *previewPhoto;
/*!
@abstract Compares the receiver to another video.
@param video The other video
@@ -19,8 +19,10 @@
#import "FBSDKShareVideo.h"
#import "FBSDKCoreKit+Internal.h"
#import "FBSDKSharePhoto.h"
#define FBSDK_SHARE_VIDEO_URL_KEY @"videoURL"
#define FBSDK_SHARE_VIDEO_PREVIEW_PHOTO_KEY @"previewPhoto"
@implementation FBSDKShareVideo
@@ -33,11 +35,23 @@
return video;
}
+ (instancetype)videoWithVideoURL:(NSURL *)videoURL previewPhoto:(FBSDKSharePhoto *)previewPhoto
{
FBSDKShareVideo *video = [[FBSDKShareVideo alloc] init];
video.videoURL = videoURL;
video.previewPhoto = previewPhoto;
return video;
}
#pragma mark - Equality
- (NSUInteger)hash
{
return [_videoURL hash];
NSUInteger subhashes[] = {
[_videoURL hash],
[_previewPhoto hash],
};
return [FBSDKMath hashWithIntegerArray:subhashes count:sizeof(subhashes) / sizeof(subhashes[0])];
}
- (BOOL)isEqual:(id)object
@@ -54,7 +68,8 @@
- (BOOL)isEqualToShareVideo:(FBSDKShareVideo *)video
{
return (video &&
[FBSDKInternalUtility object:_videoURL isEqualToObject:video.videoURL]);
[FBSDKInternalUtility object:_videoURL isEqualToObject:video.videoURL] &&
[FBSDKInternalUtility object:_previewPhoto isEqualToObject:video.previewPhoto]);
}
#pragma mark - NSCoding
@@ -68,6 +83,7 @@
{
if ((self = [self init])) {
_videoURL = [decoder decodeObjectOfClass:[NSURL class] forKey:FBSDK_SHARE_VIDEO_URL_KEY];
_previewPhoto = [decoder decodeObjectOfClass:[FBSDKSharePhoto class] forKey:FBSDK_SHARE_VIDEO_PREVIEW_PHOTO_KEY];
}
return self;
}
@@ -75,6 +91,7 @@
- (void)encodeWithCoder:(NSCoder *)encoder
{
[encoder encodeObject:_videoURL forKey:FBSDK_SHARE_VIDEO_URL_KEY];
[encoder encodeObject:_previewPhoto forKey:FBSDK_SHARE_VIDEO_PREVIEW_PHOTO_KEY];
}
#pragma mark - NSCopying
@@ -83,6 +100,7 @@
{
FBSDKShareVideo *copy = [[FBSDKShareVideo alloc] init];
copy->_videoURL = [_videoURL copy];
copy->_previewPhoto = [_previewPhoto copy];
return copy;
}
@@ -19,9 +19,11 @@
#import "FBSDKShareVideoContent.h"
#import "FBSDKCoreKit+Internal.h"
#import "FBSDKHashtag.h"
#import "FBSDKShareUtility.h"
#define FBSDK_SHARE_VIDEO_CONTENT_CONTENT_URL_KEY @"contentURL"
#define FBSDK_SHARE_VIDEO_CONTENT_HASHTAG_KEY @"hashtag"
#define FBSDK_SHARE_VIDEO_CONTENT_PEOPLE_IDS_KEY @"peopleIDs"
#define FBSDK_SHARE_VIDEO_CONTENT_PLACE_ID_KEY @"placeID"
#define FBSDK_SHARE_VIDEO_CONTENT_PREVIEW_PHOTO_KEY @"previewPhoto"
@@ -33,6 +35,7 @@
#pragma mark - Properties
@synthesize contentURL = _contentURL;
@synthesize hashtag = _hashtag;
@synthesize peopleIDs = _peopleIDs;
@synthesize placeID = _placeID;
@synthesize ref = _ref;
@@ -51,6 +54,7 @@
{
NSUInteger subhashes[] = {
[_contentURL hash],
[_hashtag hash],
[_peopleIDs hash],
[_placeID hash],
[_previewPhoto hash],
@@ -75,6 +79,7 @@
{
return (content &&
[FBSDKInternalUtility object:_contentURL isEqualToObject:content.contentURL] &&
[FBSDKInternalUtility object:_hashtag isEqualToObject:content.hashtag] &&
[FBSDKInternalUtility object:_peopleIDs isEqualToObject:content.peopleIDs] &&
[FBSDKInternalUtility object:_placeID isEqualToObject:content.placeID] &&
[FBSDKInternalUtility object:_previewPhoto isEqualToObject:content.previewPhoto] &&
@@ -93,6 +98,7 @@
{
if ((self = [self init])) {
_contentURL = [decoder decodeObjectOfClass:[NSURL class] forKey:FBSDK_SHARE_VIDEO_CONTENT_CONTENT_URL_KEY];
_hashtag = [decoder decodeObjectOfClass:[FBSDKHashtag class] forKey:FBSDK_SHARE_VIDEO_CONTENT_HASHTAG_KEY];
_peopleIDs = [decoder decodeObjectOfClass:[NSArray class] forKey:FBSDK_SHARE_VIDEO_CONTENT_PEOPLE_IDS_KEY];
_placeID = [decoder decodeObjectOfClass:[NSString class] forKey:FBSDK_SHARE_VIDEO_CONTENT_PLACE_ID_KEY];
_previewPhoto = [decoder decodeObjectOfClass:[FBSDKSharePhoto class]
@@ -106,6 +112,7 @@
- (void)encodeWithCoder:(NSCoder *)encoder
{
[encoder encodeObject:_contentURL forKey:FBSDK_SHARE_VIDEO_CONTENT_CONTENT_URL_KEY];
[encoder encodeObject:_hashtag forKey:FBSDK_SHARE_VIDEO_CONTENT_HASHTAG_KEY];
[encoder encodeObject:_peopleIDs forKey:FBSDK_SHARE_VIDEO_CONTENT_PEOPLE_IDS_KEY];
[encoder encodeObject:_placeID forKey:FBSDK_SHARE_VIDEO_CONTENT_PLACE_ID_KEY];
[encoder encodeObject:_previewPhoto forKey:FBSDK_SHARE_VIDEO_CONTENT_PREVIEW_PHOTO_KEY];
@@ -119,6 +126,7 @@
{
FBSDKShareVideoContent *copy = [[FBSDKShareVideoContent alloc] init];
copy->_contentURL = [_contentURL copy];
copy->_hashtag = [_hashtag copy];
copy->_peopleIDs = [_peopleIDs copy];
copy->_placeID = [_placeID copy];
copy->_previewPhoto = [_previewPhoto copy];
@@ -20,6 +20,8 @@
#import <FBSDKCoreKit/FBSDKCopying.h>
@class FBSDKHashtag;
/*!
@abstract A base interface for content to be shared.
*/
@@ -33,6 +35,12 @@
*/
@property (nonatomic, copy) NSURL *contentURL;
/*!
@abstract Hashtag for the content being shared.
@return The hashtag for the content being shared.
*/
@property (nonatomic, copy) FBSDKHashtag *hashtag;
/*!
@abstract List of IDs for taggable people to tag with this content.
@description See documentation for Taggable Friends
@@ -19,6 +19,7 @@
#import <Foundation/Foundation.h>
#import <FBSDKShareKit/FBSDKShareLinkContent.h>
#import <FBSDKShareKit/FBSDKShareMediaContent.h>
#import <FBSDKShareKit/FBSDKShareOpenGraphContent.h>
#import <FBSDKShareKit/FBSDKSharePhotoContent.h>
#import <FBSDKShareKit/FBSDKShareVideoContent.h>
@@ -32,6 +33,7 @@
@interface FBSDKShareUtility : NSObject
+ (void)assertCollection:(id<NSFastEnumeration>)collection ofClass:itemClass name:(NSString *)name;
+ (void)assertCollection:(id<NSFastEnumeration>)collection ofClassStrings:(NSArray *)classStrings name:(NSString *)name;
+ (void)assertOpenGraphKey:(id)key requireNamespace:(BOOL)requireNamespace;
+ (void)assertOpenGraphValue:(id)value;
+ (void)assertOpenGraphValues:(NSDictionary *)dictionary requireKeyNamespace:(BOOL)requireKeyNamespace;
@@ -42,14 +44,19 @@
error:(NSError *__autoreleasing *)errorRef;
+ (NSDictionary *)convertOpenGraphValues:(NSDictionary *)dictionary;
+ (NSDictionary *)feedShareDictionaryForContent:(id<FBSDKSharingContent>)content;
+ (NSString *)hashtagStringFromHashtag:(FBSDKHashtag *)hashtag;
+ (NSDictionary *)parametersForShareContent:(id<FBSDKSharingContent>)shareContent
shouldFailOnDataError:(BOOL)shouldFailOnDataError;
+ (void)testShareContent:(id<FBSDKSharingContent>)shareContent
containsMedia:(BOOL *)containsMediaRef
containsPhotos:(BOOL *)containsPhotosRef;
containsPhotos:(BOOL *)containsPhotosRef
containsVideos:(BOOL *)containsVideosRef;
+ (BOOL)shareMediaContentContainsPhotosAndVideos:(FBSDKShareMediaContent *)shareMediaContent;
+ (BOOL)validateAssetLibraryURLWithShareVideoContent:(FBSDKShareVideoContent *)videoContent name:(NSString *)name error:(NSError *__autoreleasing *)errorRef;
+ (BOOL)validateAssetLibraryURLsWithShareMediaContent:(FBSDKShareMediaContent *)mediaContent name:(NSString *)name error:(NSError *__autoreleasing *)errorRef;
+ (BOOL)validateShareContent:(id<FBSDKSharingContent>)shareContent error:(NSError *__autoreleasing *)errorRef;
+ (BOOL)validateShareLinkContent:(FBSDKShareLinkContent *)linkContent error:(NSError *__autoreleasing *)errorRef;
+ (BOOL)validateShareMediaContent:(FBSDKShareMediaContent *)mediaContent error:(NSError *__autoreleasing *)errorRef;
+ (BOOL)validateShareOpenGraphContent:(FBSDKShareOpenGraphContent *)openGraphContent
error:(NSError *__autoreleasing *)errorRef;
+ (BOOL)validateSharePhotoContent:(FBSDKSharePhotoContent *)photoContent error:(NSError *__autoreleasing *)errorRef;
@@ -18,10 +18,13 @@
#import "FBSDKShareUtility.h"
#import <FBSDKShareKit/FBSDKHashtag.h>
#import "FBSDKCoreKit+Internal.h"
#import "FBSDKShareConstants.h"
#import "FBSDKShareError.h"
#import "FBSDKShareLinkContent+Internal.h"
#import "FBSDKShareMediaContent.h"
#import "FBSDKShareOpenGraphContent.h"
#import "FBSDKShareOpenGraphObject.h"
#import "FBSDKSharePhoto.h"
@@ -34,6 +37,27 @@
#pragma mark - Class Methods
+ (void)assertCollection:(id<NSFastEnumeration>)collection ofClassStrings:(NSArray *)classStrings name:(NSString *)name
{
for (id item in collection) {
BOOL validClass = NO;
for (NSString *classString in classStrings) {
if ([item isKindOfClass:NSClassFromString(classString)]) {
validClass = YES;
break;
}
}
if (!validClass) {
NSString *reason = [[NSString alloc] initWithFormat:
@"Invalid value found in %@: %@ - %@",
name,
item,
collection];
@throw [NSException exceptionWithName:NSInvalidArgumentException reason:reason userInfo:nil];
}
}
}
+ (void)assertCollection:(id<NSFastEnumeration>)collection ofClass:itemClass name:(NSString *)name
{
for (id item in collection) {
@@ -123,6 +147,12 @@
parameters = @{ @"href": linkContent.contentURL.absoluteString };
}
}
NSString *hashtagString = [self hashtagStringFromHashtag:content.hashtag];
if (hashtagString != nil) {
NSMutableDictionary *mutableParameters = [parameters mutableCopy];
[FBSDKInternalUtility dictionary:mutableParameters setObject:hashtagString forKey:@"hashtag"];
parameters = [mutableParameters copy];
}
if (methodNameRef != NULL) {
*methodNameRef = methodName;
}
@@ -182,6 +212,7 @@
parameters = [[NSMutableDictionary alloc] initWithDictionary:linkContent.feedParameters];
[FBSDKInternalUtility dictionary:parameters setObject:linkContent.contentDescription forKey:@"description"];
[FBSDKInternalUtility dictionary:parameters setObject:linkContent.contentURL forKey:@"link"];
[FBSDKInternalUtility dictionary:parameters setObject:linkContent.quote forKey:@"quote"];
[FBSDKInternalUtility dictionary:parameters setObject:linkContent.contentTitle forKey:@"name"];
[FBSDKInternalUtility dictionary:parameters setObject:linkContent.imageURL forKey:@"picture"];
[FBSDKInternalUtility dictionary:parameters setObject:linkContent.ref forKey:@"ref"];
@@ -189,6 +220,20 @@
return [parameters copy];
}
+ (NSString *)hashtagStringFromHashtag:(FBSDKHashtag *)hashtag
{
if (!hashtag) {
return nil;
}
if (hashtag.isValid) {
return hashtag.stringRepresentation;
} else {
[FBSDKLogger singleShotLogEntry:FBSDKLoggingBehaviorDeveloperErrors
formatString:@"Invalid hashtag: '%@'", hashtag.stringRepresentation];
return nil;
}
}
+ (NSDictionary *)parametersForShareContent:(id<FBSDKSharingContent>)shareContent
shouldFailOnDataError:(BOOL)shouldFailOnDataError
{
@@ -210,23 +255,34 @@
+ (void)testShareContent:(id<FBSDKSharingContent>)shareContent
containsMedia:(BOOL *)containsMediaRef
containsPhotos:(BOOL *)containsPhotosRef
containsVideos:(BOOL *)containsVideosRef
{
BOOL containsMedia = NO;
BOOL containsPhotos = NO;
BOOL containsVideos = NO;
if ([shareContent isKindOfClass:[FBSDKShareLinkContent class]]) {
containsMedia = NO;
containsPhotos = NO;
containsVideos = NO;
} else if ([shareContent isKindOfClass:[FBSDKShareVideoContent class]]) {
containsMedia = YES;
containsVideos = YES;
containsPhotos = NO;
} else if ([shareContent isKindOfClass:[FBSDKSharePhotoContent class]]) {
[self _testObject:((FBSDKSharePhotoContent *)shareContent).photos
containsMedia:&containsMedia
containsPhotos:&containsPhotos];
containsPhotos:&containsPhotos
containsVideos:&containsVideos];
} else if ([shareContent isKindOfClass:[FBSDKShareMediaContent class]]) {
[self _testObject:((FBSDKShareMediaContent *)shareContent).media
containsMedia:&containsMedia
containsPhotos:&containsPhotos
containsVideos:&containsVideos];
} else if ([shareContent isKindOfClass:[FBSDKShareOpenGraphContent class]]) {
[self _testOpenGraphValueContainer:((FBSDKShareOpenGraphContent *)shareContent).action
containsMedia:&containsMedia
containsPhotos:&containsPhotos];
containsPhotos:&containsPhotos
containsVideos:&containsVideos];
}
if (containsMediaRef != NULL) {
*containsMediaRef = containsMedia;
@@ -234,6 +290,9 @@
if (containsPhotosRef != NULL) {
*containsPhotosRef = containsPhotos;
}
if (containsVideosRef != NULL) {
*containsVideosRef = containsVideos;
}
}
#if !TARGET_OS_TV
@@ -242,25 +301,77 @@
return ([self _validateRequiredValue:appInviteContent name:@"content" error:errorRef] &&
[self _validateRequiredValue:appInviteContent.appLinkURL name:@"appLinkURL" error:errorRef] &&
[self _validateNetworkURL:appInviteContent.appLinkURL name:@"appLinkURL" error:errorRef] &&
[self _validateNetworkURL:appInviteContent.appInvitePreviewImageURL name:@"appInvitePreviewImageURL" error:errorRef]);
[self _validateNetworkURL:appInviteContent.appInvitePreviewImageURL name:@"appInvitePreviewImageURL" error:errorRef] &&
[self validatePromoCodeWithError:appInviteContent error:errorRef]);
}
+ (BOOL)validatePromoCodeWithError:(FBSDKAppInviteContent *)appInviteContent error:(NSError *__autoreleasing *)errorRef
{
NSString *promoText = appInviteContent.promotionText;
NSString *promoCode = appInviteContent.promotionCode;
NSMutableCharacterSet *alphanumericWithSpaces = [NSMutableCharacterSet alphanumericCharacterSet];
[alphanumericWithSpaces formUnionWithCharacterSet:[NSCharacterSet whitespaceCharacterSet]];
if ([promoText length] > 0 || [promoCode length] > 0) {
// Check for validity of promo text and promo code.
if (!([promoText length] > 0 && [promoText length] <= 80)) {
if (errorRef != NULL) {
*errorRef = [FBSDKError invalidArgumentErrorWithName:@"promotionText" value:promoText message:@"Invalid value for promotionText, promotionText has to be between 1 and 80 characters long."];
}
return NO;
}
if (!([promoCode length] <= 10)) {
if (errorRef != NULL) {
*errorRef = [FBSDKError invalidArgumentErrorWithName:@"promotionCode" value:promoCode message:@"Invalid value for promotionCode, promotionCode has to be between 0 and 10 characters long and is required when promoCode is set."];
}
return NO;
}
if ([promoText rangeOfCharacterFromSet:[alphanumericWithSpaces invertedSet]].location != NSNotFound) {
if(errorRef != NULL) {
*errorRef = [FBSDKError invalidArgumentErrorWithName:@"promotionText" value:promoText message:@"Invalid value for promotionText, promotionText can contain only alphanumeric characters and spaces."];
}
return NO;
}
if ([promoCode length] > 0 && [promoCode rangeOfCharacterFromSet:[alphanumericWithSpaces invertedSet]].location != NSNotFound) {
if (errorRef != NULL) {
*errorRef = [FBSDKError invalidArgumentErrorWithName:@"promotionCode" value:promoCode message:@"Invalid value for promotionCode, promotionCode can contain only alphanumeric characters and spaces."];
}
return NO;
}
}
if (errorRef != NULL) {
*errorRef = nil;
}
return YES;
}
#endif
+ (BOOL)validateAssetLibraryURLWithShareVideoContent:(FBSDKShareVideoContent *)videoContent name:(NSString *)name error:(NSError *__autoreleasing *)errorRef
{
FBSDKShareVideo *video = videoContent.video;
NSURL *videoURL = video.videoURL;
if (!videoURL || [[videoURL.scheme lowercaseString] isEqualToString:@"assets-library"]) {
if (errorRef != NULL) {
*errorRef = nil;
return [self _validateAssetLibraryVideoURL:videoURL name:name error:errorRef];
}
+ (BOOL)validateAssetLibraryURLsWithShareMediaContent:(FBSDKShareMediaContent *)mediaContent name:(NSString *)name error:(NSError *__autoreleasing *)errorRef
{
for (id media in mediaContent.media) {
if ([media isKindOfClass:[FBSDKShareVideo class]]) {
FBSDKShareVideo *video = (FBSDKShareVideo *)media;
if (![self _validateAssetLibraryVideoURL:video.videoURL name:name error:errorRef]) {
return NO;
}
}
return YES;
} else {
if (errorRef != NULL) {
*errorRef = [FBSDKShareError invalidArgumentErrorWithName:name value:videoURL message:nil];
}
return NO;
}
return YES;
}
#if !TARGET_OS_TV
@@ -344,6 +455,8 @@
return [self validateSharePhotoContent:(FBSDKSharePhotoContent *)shareContent error:errorRef];
} else if ([shareContent isKindOfClass:[FBSDKShareVideoContent class]]) {
return [self validateShareVideoContent:(FBSDKShareVideoContent *)shareContent error:errorRef];
} else if ([shareContent isKindOfClass:[FBSDKShareMediaContent class]]) {
return [self validateShareMediaContent:(FBSDKShareMediaContent *)shareContent error:errorRef];
} else if ([shareContent isKindOfClass:[FBSDKShareOpenGraphContent class]]) {
return [self validateShareOpenGraphContent:(FBSDKShareOpenGraphContent *)shareContent error:errorRef];
} else {
@@ -386,6 +499,43 @@
return YES;
}
+ (BOOL)validateShareMediaContent:(FBSDKShareMediaContent *)mediaContent error:(NSError *__autoreleasing *)errorRef
{
NSArray *medias = mediaContent.media;
if (![self _validateRequiredValue:mediaContent name:@"shareContent" error:errorRef] ||
![self _validateArray:medias minCount:1 maxCount:20 name:@"photos" error:errorRef]) {
return NO;
}
for (id media in medias) {
if ([media isKindOfClass:[FBSDKSharePhoto class]]) {
FBSDKSharePhoto *photo = (FBSDKSharePhoto *)media;
if (!photo.image) {
if (errorRef != NULL) {
*errorRef = [FBSDKShareError invalidArgumentErrorWithName:@"media"
value:media
message:@"photos must have UIImages"];
}
return NO;
}
} else if ([media isKindOfClass:[FBSDKShareVideo class]]) {
FBSDKShareVideo *video = (FBSDKShareVideo *)media;
NSURL *videoURL = video.videoURL;
return ([self _validateRequiredValue:video name:@"video" error:errorRef] &&
[self _validateRequiredValue:videoURL name:@"videoURL" error:errorRef]);
} else {
if (errorRef != NULL) {
*errorRef = [FBSDKShareError invalidArgumentErrorWithName:@"media"
value:media
message:@"Only FBSDKSharePhoto and FBSDKShareVideo are allowed in `media` property"];
}
return NO;
}
}
return YES;
}
+ (BOOL)validateShareLinkContent:(FBSDKShareLinkContent *)linkContent error:(NSError *__autoreleasing *)errorRef
{
return ([self _validateRequiredValue:linkContent name:@"shareContent" error:errorRef] &&
@@ -402,6 +552,14 @@
[self _validateRequiredValue:videoURL name:@"videoURL" error:errorRef]);
}
+ (BOOL)shareMediaContentContainsPhotosAndVideos:(FBSDKShareMediaContent *)shareMediaContent
{
BOOL containsPhotos = NO;
BOOL containsVideos = NO;
[self testShareContent:shareMediaContent containsMedia:NULL containsPhotos:&containsPhotos containsVideos:&containsVideos];
return containsVideos && containsPhotos;
}
#pragma mark - Object Lifecycle
- (instancetype)init
@@ -414,6 +572,10 @@
+ (void)_addToParameters:(NSMutableDictionary *)parameters forShareContent:(id<FBSDKSharingContent>)shareContent
{
NSString *hashtagString = [self hashtagStringFromHashtag:shareContent.hashtag];
if (hashtagString != nil) {
[FBSDKInternalUtility dictionary:parameters setObject:@[hashtagString] forKey:@"hashtags"];
}
if ([shareContent isKindOfClass:[FBSDKShareOpenGraphContent class]]) {
FBSDKShareOpenGraphAction *action = ((FBSDKShareOpenGraphContent *)shareContent).action;
[action setArray:shareContent.peopleIDs forKey:@"tags"];
@@ -565,25 +727,32 @@ forShareOpenGraphContent:(FBSDKShareOpenGraphContent *)openGraphContent
[value isKindOfClass:[FBSDKShareOpenGraphObject class]]);
}
+ (void)_testObject:(id)object containsMedia:(BOOL *)containsMediaRef containsPhotos:(BOOL *)containsPhotosRef
+ (void)_testObject:(id)object containsMedia:(BOOL *)containsMediaRef containsPhotos:(BOOL *)containsPhotosRef containsVideos:(BOOL *)containsVideosRef
{
BOOL containsMedia = NO;
BOOL containsPhotos = NO;
BOOL containsVideos = NO;
if ([object isKindOfClass:[FBSDKSharePhoto class]]) {
containsMedia = (((FBSDKSharePhoto *)object).image != nil);
containsPhotos = YES;
} else if ([object isKindOfClass:[FBSDKShareVideo class]]) {
containsMedia = YES;
containsVideos = YES;
} else if ([object isKindOfClass:[FBSDKShareOpenGraphValueContainer class]]) {
[self _testOpenGraphValueContainer:(FBSDKShareOpenGraphValueContainer *)object
containsMedia:&containsMedia
containsPhotos:&containsPhotos];
containsPhotos:&containsPhotos
containsVideos:&containsVideos];
} else if ([object isKindOfClass:[NSArray class]]) {
for (id item in (NSArray *)object) {
BOOL itemContainsMedia = NO;
BOOL itemContainsPhotos = NO;
[self _testObject:item containsMedia:&itemContainsMedia containsPhotos:&itemContainsPhotos];
BOOL itemContainsVideos = NO;
[self _testObject:item containsMedia:&itemContainsMedia containsPhotos:&itemContainsPhotos containsVideos:&itemContainsVideos];
containsMedia |= itemContainsMedia;
containsPhotos |= itemContainsPhotos;
if (containsMedia && containsPhotos) {
containsVideos |= itemContainsVideos;
if (containsMedia && containsPhotos && containsVideos) {
break;
}
}
@@ -594,21 +763,28 @@ forShareOpenGraphContent:(FBSDKShareOpenGraphContent *)openGraphContent
if (containsPhotosRef != NULL) {
*containsPhotosRef = containsPhotos;
}
if (containsVideosRef != NULL) {
*containsVideosRef = containsVideos;
}
}
+ (void)_testOpenGraphValueContainer:(FBSDKShareOpenGraphValueContainer *)container
containsMedia:(BOOL *)containsMediaRef
containsPhotos:(BOOL *)containsPhotosRef
containsVideos:(BOOL *)containsVideosRef
{
__block BOOL containsMedia = NO;
__block BOOL containsPhotos = NO;
__block BOOL containsVideos = NO;
[container enumerateKeysAndObjectsUsingBlock:^(NSString *key, id object, BOOL *stop) {
BOOL itemContainsMedia = NO;
BOOL itemContainsPhotos = NO;
[self _testObject:object containsMedia:&itemContainsMedia containsPhotos:&itemContainsPhotos];
BOOL itemContainsVideos = NO;
[self _testObject:object containsMedia:&itemContainsMedia containsPhotos:&itemContainsPhotos containsVideos:&itemContainsVideos];
containsMedia |= itemContainsMedia;
containsPhotos |= itemContainsPhotos;
if (containsMedia && containsPhotos) {
containsVideos |= itemContainsVideos;
if (containsMedia && containsPhotos && containsVideosRef) {
*stop = YES;
}
}];
@@ -618,6 +794,9 @@ forShareOpenGraphContent:(FBSDKShareOpenGraphContent *)openGraphContent
if (containsPhotosRef != NULL) {
*containsPhotosRef = containsPhotos;
}
if (containsVideosRef != NULL) {
*containsVideosRef = containsVideos;
}
}
+ (BOOL)_validateArray:(NSArray *)array
@@ -729,4 +908,19 @@ forShareOpenGraphContent:(FBSDKShareOpenGraphContent *)openGraphContent
return NO;
}
+ (BOOL)_validateAssetLibraryVideoURL:(NSURL *)videoURL name:(NSString *)name error:(NSError *__autoreleasing *)errorRef
{
if (!videoURL || [[videoURL.scheme lowercaseString] isEqualToString:@"assets-library"]) {
if (errorRef != NULL) {
*errorRef = nil;
}
return YES;
} else {
if (errorRef != NULL) {
*errorRef = [FBSDKShareError invalidArgumentErrorWithName:name value:videoURL message:nil];
}
return NO;
}
}
@end