Manage BP cover picture and user profile picture uploads to rtAmazon S3

Below is the sample code to manage BuddyPress cover picture and profile picture uploads of group and member’s profile to rtAmazon S3.
Paste this code inside your theme’s functions.php file.

/**
 * Function to setup hooks for rtamazon custom code.
 */
function rtamazon_setup_custom_code_hooks() {
	require_once ABSPATH . 'wp-admin/includes/plugin.php';
	if ( ! class_exists( 'RTAWSS3_Class' ) || ! is_plugin_active( 'buddypress/bp-loader.php' ) || ! is_plugin_active( 'rtamazon-s3/index.php' ) ) {
		return;
	}

	add_filter( 'bp_attachments_pre_get_attachment', 'rtamazon_modify_cover_image', 10, 2 );
	add_filter( 'rtawss3_match_urls', 'rtamazon_content_url' );
	add_filter( 'rtawss3_match_urls', 'rtamazon_content_wp_url' );
	add_filter( 'bp_attachments_pre_cover_image_ajax_upload', 'rtamazon_send_coverimage_to_s3', 10, 4 );
	add_action( 'bp_members_avatar_uploaded', 'rtamazon_send_avatar_to_s3', 10, 3 );
	add_action( 'groups_avatar_uploaded', 'rtamazon_send_avatar_to_s3', 10, 3 );
	add_filter( 'bp_core_fetch_avatar_url', 'rtamazon_set_profile', 99, 2 );
	add_filter( 'bp_core_fetch_avatar', 'rtamazon_set_profile_html', 10, 2 );
	add_action( 'bp_core_delete_existing_avatar', 'rtamazon_delete_avatar' );
	add_filter( 'bp_attachments_pre_delete_file', 'rtamazon_delete_coverphoto', 10, 2 );
	add_filter( 'the_content', 'rtawss3_custom_filter_content', 99 );
	add_filter( 'inspirebook_cover_image_url', 'rtamazon_inspirebook_cover_image_url' );
}

add_action( 'after_setup_theme', 'rtamazon_setup_custom_code_hooks' );

/**
 * Replace cover image url with s3 url.
 *
 * @param bool  $flag   Flag to modify cover-image url.
 * @param array $param Attachment data.
 *
 * @return bool|string
 */
function rtamazon_modify_cover_image( $flag, $param ) {
	if ( ! class_exists( 'RTAWSS3_Class' ) ) {
		return $flag;
	}

	if ( 'cover-image' !== $param['type'] ) {
		return $flag;
	}
	remove_filter( 'bp_attachments_pre_get_attachment', 'rtamazon_modify_cover_image', 10 );

	$url = bp_attachments_get_attachment(
		'url',
		array(
			'item_id' => $param['item_id'],
			'object_dir' => $param['object_dir'],
			'type' => $param['type'],
		)
	);
	if ( empty( $url ) && empty( $param['file'] ) ) {
		return $flag;
	}

	if ( empty( $url ) && ! empty( $param['file'] ) ) {
		return $param['file'];
	}

	$cover_image_aws = rtamazon_get_aws_url( $url );
	$cover_image_aws = ( ! empty( $cover_image_aws ) ) ? $cover_image_aws : $url;
	add_filter( 'bp_attachments_pre_get_attachment', 'rtamazon_modify_cover_image', 10, 2 );

	return $cover_image_aws;
}

/**
 * Set selected url structure, selected in rtAmazon settings.
 *
 * @since 1.4.0
 *
 * @param  string $urls urls in content.
 *
 * @return array  $newurls/$urls return array of all urls in content.
 */
function rtamazon_content_url( $urls ) {
	// get bucket name.
	$bucket = rtamazon_s3_get_bucket_name();
	if ( ! empty( $bucket ) ) {
		// get bucket url structure.
		$url_structure = rtamazon_s3_get_url_structure( $bucket );
		$newurls = array();
		// If url structure is default than return the content, no need to search and replace.
		if ( ! empty( $url_structure ) ) {
			// get custom domain for bucket url.
			$custom_domain = rtamazon_s3_get_custom_url_domain_name( $bucket );
			// get default bucket url.
			$amazon_url = rtamazon_s3_get_default_bucket_url( $bucket );
			// get bucket url as per bucket url structure and custom domain.
			$domain = rtamazon_s3_get_bucket_url( $bucket, $url_structure, $custom_domain );
			// Wp url pattern.
			$wp_url_pattern = preg_replace( '(^https?://)', '', site_url() );
			$search = array();
			$replace = array();
			foreach ( $urls as $url ) {
				$aws_url = rtamazon_get_aws_url( $url );
				/* Set url according to selected url structure */
				if ( strpos( $url, $bucket . '.s3.amazonaws.com' ) !== false ) { // for Bucket name as subdomain.
					/**
					 * Filters elements for search array.
					 *
					 * @since 1.4.0
					 *
					 * @param array Array of search elements.
					 */
					$search = apply_filters( 'rtamazon_search_pattern', array( $bucket . '.s3.amazonaws.com' ) );
				} elseif ( strpos( $url, 's3.amazonaws.com/' . $bucket ) !== false ) { // for Bucket name in path
					$search = apply_filters( 'rtamazon_search_pattern', array( 's3.amazonaws.com/' . $bucket ) );
				} elseif ( ! empty( $custom_domain ) && strpos( $url, $custom_domain ) !== false ) { // for Custom Domain
					$search = apply_filters( 'rtamazon_search_pattern', array( $custom_domain ) );
				} elseif ( strstr( $url, $wp_url_pattern ) !== false ) {
					$search = apply_filters( 'rtamazon_search_pattern', array( $wp_url_pattern ) );
				}
				/**
				 * Filters elements for replacing array.
				 *
				 * @since 1.4.0
				 *
				 * @param array Array of replacing elements.
				 */
				$replace = apply_filters( 'rtamazon_replace_pattern', array( $domain ) );
				/**
				 * Set original value as a key into array
				 * so we can use that for replace with new
				 * urls in content
				 */
				$newurls[ $url ] = str_replace( $search, $replace, $aws_url );
			} // End foreach().
			return $newurls;
		} // End if().
	} // End if().
	return $urls;
}
/**
 * Set default WP url when "WordPress Media URL" is enabled
 *
 * @param string $urls contains wp content url.
 */
function rtamazon_content_wp_url( $urls ) {
	if ( class_exists( 'RTAWSS3_Class' ) ) {
		$bucket = rtamazon_s3_get_bucket_name();
		if ( ! empty( $bucket ) ) {
			// get bucket url structure.
			$url_structure = rtamazon_s3_get_url_structure( $bucket );
			$newurls = array();
			// If url structure is default than return the content, no need to search and replace.
			if ( 'rtawss3_wp_url' === $url_structure ) {
				// get custom domain for bucket url.
				$custom_domain = rtamazon_s3_get_custom_url_domain_name( $bucket );
				// get default bucket url.
				$amazon_url = rtamazon_s3_get_default_bucket_url( $bucket );
				// get bucket url as per bucket url structure and custom domain.
				$domain = rtamazon_s3_get_bucket_url( $bucket, $url_structure, $custom_domain );
				$search = array(); // search the pattern into urls.
				$replace = array(); // replace with this into urls.
				foreach ( $urls as $url ) {
					/* Set url according to selected url structure */
					if ( strpos( $url, $bucket . '.s3.amazonaws.com' ) !== false ) {
						$search = apply_filters( 'rtamazon_search_pattern', array( $bucket . '.s3.amazonaws.com' ) );
					} elseif ( strpos( $url, 's3.amazonaws.com/' . $bucket ) !== false ) {
						$search = apply_filters( 'rtamazon_search_pattern', array( 's3.amazonaws.com/' . $bucket ) );
					} elseif ( strpos( $url, $custom_domain ) !== false ) {
						$search = apply_filters( 'rtamazon_search_pattern', array( $custom_domain ) );
					}
					$replace = apply_filters( 'rtamazon_replace_pattern', array( $domain ) );
					/**
					 * Set original value as a key into array
					 * so we can use that for replace with new
					 * urls in content
					 */
					$newurls[ $url ] = str_replace( $search, $replace, $url );
				}
				return $newurls;
			} // End if().
		} // End if().
	} // End if().
	return $urls;
} // End if().
/***************** Cover picture for member and group ********************/
/**
 * Send cover image to s3
 */
function rtamazon_send_coverimage_to_s3( $emptyarr = array(), $bp_params, $needs_reset, $object_data ) {
	if ( class_exists( 'RTAWSS3_Class' ) ) {
		global $wpdb;
		/* get bucket name */
		$bucket = rtamazon_s3_get_bucket_name();
		// Get BuddyPress Attachments Uploads Dir datas.
		$bp_attachments_uploads_dir = bp_attachments_uploads_dir_get();
		$cover_subdir = $object_data['dir'] . '/' . $bp_params['item_id'] . '/cover-image';
		$cover_dir    = trailingslashit( $bp_attachments_uploads_dir['basedir'] ) . $cover_subdir;
		$match = $cover_subdir;
		// First, escape the match for use in a LIKE statement.
		$search = $wpdb->esc_like( $match );
		// Add wildcards, since we are searching within match text.
		$search = '%' . $search . '%';
		$sql = "SELECT id, obj_key FROM {$wpdb->prefix}rtamazon_s3_media WHERE ( obj_key LIKE %s )";
		// Prepare the SQL statement so the string input gets escaped for security.
		$sql = $wpdb->prepare( $sql, $search );
		$get_results = $wpdb->get_results( $sql );
		$object_arr = array();
		// Default error message.
		$error_message = __( 'There was a problem uploading the cover image.', 'buddypress' );
		$cover_image_attachment = new BP_Attachment_Cover_Image();
		$uploaded = $cover_image_attachment->upload( $_FILES );
		// The BP Attachments Uploads Dir is not set, stop.
		if ( ! $bp_attachments_uploads_dir ) {
			bp_attachments_json_response(
				false,
				$is_html4,
				array(
					'type'    => 'upload_error',
					'message' => $error_message,
				)
			);
		}
		if ( ! is_dir( $cover_dir ) ) {
			// Upload error response.
			bp_attachments_json_response(
				false,
				$is_html4,
				array(
					'type'    => 'upload_error',
					'message' => $error_message,
				)
			);
		}
		$cover = bp_attachments_cover_image_generate_file(
			array(
				'file'            => $uploaded['file'],
				'component'       => $object_data['component'],
				'cover_image_dir' => $cover_dir,
			),
			$cover_image_attachment
		);
		// Build the url to the file.
		$cover_url = trailingslashit( $bp_attachments_uploads_dir['baseurl'] ) . $cover_subdir . '/' . $cover['cover_basename'];
		// Init Feedback code, 1 is success.
		$feedback_code = 1;
		// Set the name of the file.
		$name = $_FILES['file']['name'];
		$name_parts = pathinfo( $name );
		$name = trim( substr( $name, 0, - ( 1 + strlen( $name_parts['extension'] ) ) ) );
		$data = array(
			'url'   => $cover_url,
			'file'  => $cover['cover_file'],
		);
		$data = apply_filters( 'rtamazon_cover_image_params', $data );
		$hash = md5( $cover_url );
		rtamazon_sent_to_s3( $data, $hash, true );
		// delete profile pictures
		rtamazon_delete_images_from_bucket( $bucket, $get_results );
		$cover_url = rtamazon_get_aws_url( $cover_url );
		// Finally return the cover image url to the UI.
		bp_attachments_json_response(
			true,
			$is_html4,
			array(
				'name'          => $name,
				'url'           => $cover_url,
				'feedback_code' => $feedback_code,
			)
		);
	}
}
/***************** Cover picture for member and group end ********************/
/************************* User profile picture **************************/
/**
 * Send profile image to amazon s3
 */
function rtamazon_send_avatar_to_s3( $item_id, $item_type, $r ) {
	if ( class_exists( 'RTAWSS3_Class' ) ) {
		if ( empty( $r['object'] ) && defined( 'RTMEDIA_BUDDYPRESS_PROFILE_PICTURE_BASE_NAME' ) ) {
			$r['object'] = 'user';
		}
		$avatar_types = array( 'full', 'thumb' );
		$avatarfolder = apply_filters( 'rtmedia_avatars_foldername', ( ( 'group' === $r['object'] ) ? 'group-avatars' : 'avatars' ) );
		global $wpdb;
		/* get bucket name */
		$bucket = rtamazon_s3_get_bucket_name();
		$get_results = rtamazon_get_bucket_images( $avatarfolder, $item_id );
		$object_arr = array();
		// Upload thumb and full image to amazon s3
		foreach ( $avatar_types as $type ) {
			$avatar = bp_core_fetch_avatar(
				array(
					'object'    => $r['object'],
					'item_id'   => $item_id,
					'html'      => false,
					'type'      => $type,
				)
			);
			$avatar_path = BP_AVATAR_UPLOAD_PATH . '/' . $avatarfolder . '/' . $item_id . '/' . basename( $avatar );
			$data = array(
				'url'   => $avatar,
				'file'  => $avatar_path,
			);
			$data = apply_filters( 'rtamazon_avatar_params', $data );
			$hash = md5( $avatar );
			rtamazon_sent_to_s3( $data, $hash, true );
		}
		// delete profile pictures
		if ( bp_avatar_history_is_disabled() ) {
			rtamazon_delete_images_from_bucket( $bucket, $get_results );
		} else {
			$item_id = $item_id . '/history';
			rtamazon_recycle_avatar( $bucket, $get_results );
		}
	}
}
/**
 * Get profile picture from s3 bucket
 */
function rtamazon_set_profile( $avatar_url, $params ) {
	if ( class_exists( 'RTAWSS3_Class' ) ) {
		$rtawss3 = RTAWSS3_Class::instance();
		$obj = $rtawss3->rtawss3_db( 'get_row', array(), 'wp_url', trim( $avatar_url ) );
		if ( $obj && isset( $obj->s3_url ) ) {
			$avatar_url = rtamazon_s3_replace_content_urls( $obj->s3_url );
		}
		// remove_filter( 'bp_core_fetch_avatar_url', 'rtamazon_set_profile', 999 );
		return $avatar_url;
	}
}
/**
 * Get members / groups profile picture from s3 bucket
 */
function rtamazon_set_profile_html( $avatar_html, $params ) {
	if ( class_exists( 'RTAWSS3_Class' ) && ( isset( $params['object'] ) && ( 'user' === $params['object'] || 'group' === $params['object'] ) ) ) {
		$rtawss3 = RTAWSS3_Class::instance();
		$matches = rtawss3_custom_match_urls( $avatar_html );
		if ( ! empty( $matches ) ) {
			$where = array(
				'wp_url' => array(
					'compare' => 'IN',
					'value' => array_keys( $matches ),
				),
			);
			$rows = $rtawss3->rtawss3_db( 'get_results', array(), 'status', 'moved', false, array(), $where );
			$urls = array();
			$urls_data = array();
			// check if image is moved to s3 bucket then.
			// show image from bucket.
			if ( count( $rows ) > 0 ) {
				foreach ( $rows as $row ) {
					if ( $rtawss3->rtawss3_check_bucket_url( $row->bucket ) ) {
						$urls[] = $row->wp_url;
						$urls_data[] = $row;
					}
				}
				// Change url for images.
				$avatar_html = str_replace( array_keys( $matches ), $matches, $avatar_html );
			}
			foreach ( $matches as $match ) {
				$search = array_search( $match, $urls );
				if ( $search !== false ) {
					$row = $urls_data[ $search ];
					$avatar_url = str_replace( $match, $row->s3_url, $avatar_url );
				}
			}
		}
	}
	return $avatar_html;
}
/************************* User profile picture end **************************/
/**************************** Delete avatar pic **********************************/
/**
 * rtamazon_delete_avatar Delete avatar image for member from s3 bucket.
 */
function rtamazon_delete_avatar( $args ) {
	if ( class_exists( 'RTAWSS3_Class' ) ) {
		if ( empty( $args ) ) {
			return;
		}
	}
	$item_id = ( isset( $args['item_id'] ) && ! empty( $args['item_id'] ) ) ? $args['item_id'] : 0;
	if ( 'user' === $args['object'] ) {
		$avatarfolder = apply_filters( 'rtmedia_grpavatars_foldername', 'avatars' );
	} elseif ( 'group' === $args['object'] ) {
		$avatarfolder = apply_filters( 'rtmedia_grpavatars_foldername', 'group-avatars' );
	}
	global $wpdb;
	/* get bucket name */
	$bucket = rtamazon_s3_get_bucket_name();
	$get_results = rtamazon_get_bucket_images( $avatarfolder, $item_id );
	// delete profile pictures
	rtamazon_delete_images_from_bucket( $bucket, $get_results );
}
/**************************** Delete avatar pic end **********************************/
/**************************** Delete cover pic **********************************/
/**
 * rtamazon_delete_coverphoto Delete cover image for members and groups from s3 bucket
 */
function rtamazon_delete_coverphoto( $status, $args ) {
	if ( class_exists( 'RTAWSS3_Class' ) ) {
		if ( empty( $args ) ) {
			return;
		}
	}
	$item_id = ( isset( $args['item_id'] ) && ! empty( $args['item_id'] ) ) ? $args['item_id'] : 0;
	if ( 'members' === $args['object_dir'] ) {
		$coverfolder = apply_filters( 'rtmedia_coveravatars_foldername', 'members' );
	} elseif ( 'groups' === $args['object_dir'] ) {
		$coverfolder = apply_filters( 'rtmedia_coveravatars_foldername', 'groups' );
	}
	global $wpdb;
	/* get bucket name */
	$bucket = rtamazon_s3_get_bucket_name();
	$get_results = rtamazon_get_bucket_images( $coverfolder, $item_id );
	$object_arr = array();
	// delete profile pictures.
	rtamazon_delete_images_from_bucket( $bucket, $get_results );
	return true;
}
/**
 * rtamazon_get_bucket_images Get list of perticular images uploaded to s3 amazon
 */
function rtamazon_get_bucket_images( $coverfolder, $item_id ) {
	global $wpdb;
	$match = '/' . $coverfolder . '/' . $item_id . '/';
	// First, escape the match for use in a LIKE statement.
	$search = $wpdb->esc_like( $match );
	// Add wildcards, since we are searching within match text.
	$search = '%' . $match . '%';
	$sql = "SELECT id, obj_key FROM {$wpdb->prefix}rtamazon_s3_media WHERE ( obj_key LIKE %s )";
	// Prepare the SQL statement so the string input gets escaped for security.
	$sql = $wpdb->prepare( $sql, $search );
	return $wpdb->get_results( $sql );
}
/**
 * rtamazon_delete_images_from_bucket Delete requested images from s3 bucket
 */
function rtamazon_delete_images_from_bucket( $bucket, $get_results = array() ) {
	global $wpdb;
	$object_arr = array();
	// delete profile pictures
	if ( count( $get_results ) > 0 ) {
		foreach ( $get_results as $key_arr ) {
			$object_arr[]['Key'] = $key_arr->obj_key;
			$rtawss3 = RTAWSS3_Class::instance();
			$delete_obj = $rtawss3->rtawss3_db( 'get_row', array(), 'obj_key', trim( $key_arr->obj_key ) );
			if ( $delete_obj ) {
				$where['obj_key'] = trim( $key_arr->obj_key );
				$rtawss3->rtawss3_db( 'delete', '', '', '', '', '', $where );
			}
		}
		$rtawss3_client = new RTAWSS3_Client();
		$status = $rtawss3_client->rtawss3_delete_bucket_object( $bucket, $object_arr );
	}
}
/**************************** Delete cover pic end **********************************/
/*
 * Matching urls
 */
function rtawss3_custom_match_urls( $content ) {
	$regex = '/\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|$!:,.;]*[A-Z0-9+&@#\/%=~_|$]/i';
	preg_match_all( $regex, $content, $matches );
	$mediaList = array();
	if ( isset( $matches[0] ) && ! empty( $matches[0] ) ) {
		/**
		 * Filters attachment urls in content.
		 *
		 * @param array Array of all urls into content.
		 */
		$mediaList = apply_filters( 'rtawss3_match_urls', $matches[0] );
	}
	return $mediaList;
}
/*
 * Filtering content
 */
function rtawss3_custom_filter_content( $content ) {
	$matches = rtawss3_custom_match_urls( $content );
	if ( ! empty( $matches ) ) {
		$content = rtamazon_s3_replace_content_urls( $content );
	}
	return $content;
}
/**
 * rtamazon_inspirebook_cover_image_url     Fetch cover image from s3bucket.
 *                      This function is "Inspirebook" theme specific
 *
 * @param  url $url    Original url
 * @return url          S3 bucket url
 */
function rtamazon_inspirebook_cover_image_url( $url ) {
	if ( class_exists( 'RTAWSS3_Class' ) ) {
		// New image url from AWS server
		$cover_image_aws = rtamazon_get_aws_url( $url );
		$cover_image_aws = ( ! empty( $cover_image_aws ) ) ? $cover_image_aws : $url;
		$url = $cover_image_aws;
	}
	return $url;
}

/**
 * rtamazon_recycle_profile
 */
function rtamazon_recycle_avatar( $bucket, $get_results ) {
	global $wpdb;
	$object_arr = array();
	// delete profile pictures
	if ( count( $get_results ) > 0 ) {
		foreach ( $get_results as $key_arr ) {
			$object_arr[]['Key'] = $key_arr->obj_key;
			$rtawss3 = RTAWSS3_Class::instance();
			$delete_obj = $rtawss3->rtawss3_db( 'get_row', array(), 'obj_key', trim( $key_arr->obj_key ) );
			if ( $delete_obj ) {
				$where['obj_key'] = trim( $key_arr->obj_key );
				$rtawss3->rtawss3_db( 'delete', '', '', '', '', '', $where );
			}
		}
		$new_path       = '/history/';
		$rtawss3_client = new RTAWSS3_Client();
		$status         = $rtawss3_client->rtawss3_rename_bucket_object( $bucket, $object_arr, $new_path );
	}
}