Skip to content

Instantly share code, notes, and snippets.

@boonebgorges
Created February 9, 2017 03:34
Show Gist options
  • Save boonebgorges/5ac2a5479233c8bb39ccc56153782f7b to your computer and use it in GitHub Desktop.
Save boonebgorges/5ac2a5479233c8bb39ccc56153782f7b to your computer and use it in GitHub Desktop.
Networkwide BP notification formatting for bbPress non-network-activated
<?php
/*
Plugin name: bbPress BP Notification Formatter
Description: A REST API endpoint for WP multisite installations that need to format bbPress-related BP notifications on secondary sites.
Version: 1.0
*/
/**
* Load the plugin.
*
* This consists of registering the API endpoint.
*/
function bbpbpnf_init() {
if ( ! function_exists( 'bbp_format_buddypress_notifications' ) ) {
return;
}
register_rest_route( 'bbpbpnf/v1', '/notification/', array(
'methods' => 'GET',
'permission_callback' => 'bbpbpnf_permissions_callback',
'callback' => 'bbpbpnf_callback',
) );
add_filter( 'rest_pre_serve_request', 'bbpbpnf_send_cors_headers', 10, 4 );
}
add_action( 'rest_api_init', 'bbpbpnf_init' );
/**
* Modify CORS headers to whitelist Commons domains.
*/
function bbpbpnf_send_cors_headers( $sent, $response, $request, $server ) {
global $wpdb;
$origin = get_http_origin();
$origin = untrailingslashit( $origin );
$is_commons_domain = false;
if ( $origin === untrailingslashit( site_url() ) ) {
$is_commons_domain = true;
} elseif ( preg_match( '|\://[^\.]+\.commons\.gc\.cuny\.edu|', $origin ) ) {
$is_commons_domain = true;
} elseif ( isset( $wpdb->dmtable ) ) {
$domain = preg_replace( '|https?\://|', '', $origin );
$mapped_site_id = $wpdb->get_var( $wpdb->prepare( "SELECT blog_id FROM {$wpdb->dmtable} WHERE domain = %s", $domain ) );
if ( $mapped_site_id ) {
$is_commons_domain = true;
}
}
if ( $is_commons_domain ) {
header( 'Access-Control-Allow-Headers: X-WP-Nonce' );
}
return $sent;
}
/**
* Endpoint permissions callback.
*
* @param WP_REST_Request $request
* @return bool
*/
function bbpbpnf_permissions_callback( WP_REST_Request $request ) {
if ( ! is_user_logged_in() ) {
return false;
}
$params = $request->get_params();
if ( empty( $params['ids'] ) ) {
return false;
}
// Users must own all notifications to fetch formatted notification.
$can = true;
$ids = wp_parse_id_list( $params['ids'] );
foreach ( $ids as $id ) {
$notification = new BP_Notifications_Notification( $id );
if ( bp_loggedin_user_id() != $notification->user_id ) {
$can = false;
break;
}
}
return $can;
}
/**
* API endpoint.
*/
function bbpbpnf_callback( WP_REST_Request $request ) {
$params = $request->get_params();
if ( ! isset( $params['ids'] ) ) {
return;
}
$ids = wp_parse_id_list( $params['ids'] );
$notifications = array();
foreach ( $ids as $id ) {
$n = new BP_Notifications_Notification( $id );
if ( 'bbp_new_reply' !== $n->component_action ) {
continue;
}
$notifications[] = $n;
}
if ( empty( $notifications ) ) {
return;
}
$count = count( $notifications );
$n = $notifications[0];
$formatted = bbp_format_buddypress_notifications( $n->component_action, $n->item_id, $n->secondary_item_id, $count );
// Must add the class="ab-item" selector, which WP does dynamically.
$formatted = str_replace( '<a ', '<a class="ab-item" ', $formatted );
$retval = rest_ensure_response( $formatted );
return $retval;
}
<?php
/*
Plugin name: bbPress BP Notification Grabber
Description: Fetches formatted bbPress notifications on a WordPress Multisite installation.
Version: 1.0
Network: true
*/
define( 'BBPBPNG_ENDPOINT_BASE', 'http://commons.gc.cuny.edu/wp-json/bbpbpnf/v1/notification/' );
/**
* Load the plugin.
*/
function bbpbpng_init() {
// If bbPress is present, let it do its own formatting.
if ( function_exists( 'bbp_format_buddypress_notifications' ) ) {
return;
}
// Logged-out users don't need to see anything.
if ( ! is_user_logged_in() ) {
return;
}
add_filter( 'wp_footer', 'bbpbpng_maybe_make_request', 10 );
add_action( 'rest_api_init', 'bbpbpng_register_endpoint' );
}
add_action( 'plugins_loaded', 'bbpbpng_init' );
/**
* Check whether a remote request is necessary, and if so, set up scripts.
*
* Can't wait until the admin bar renders because it's too late to enqueue scripts.
*/
function bbpbpng_maybe_make_request() {
$notifications = bp_notifications_get_notifications_for_user( bp_loggedin_user_id(), 'object' );
$bbp_ids = array();
foreach ( $notifications as $notification ) {
if ( 'bbp_new_reply' === $notification->component_action ) {
$bbp_ids[] = $notification->id;
}
}
// Only bother if there are bbp_new_reply items.
if ( $bbp_ids ) {
$bbp_ids = array_map( 'intval', $bbp_ids );
$request_uri = add_query_arg( 'ids', implode( ',', $bbp_ids ), BBPBPNG_ENDPOINT_BASE );
// If a cached value is found, the async request will be skipped.
$cached = wp_cache_get( md5( $request_uri ), 'bbpbpng' );
wp_enqueue_script( 'bbpbpng', plugin_dir_url( __FILE__ ) . '/assets/js/bbpbpng.js', array( 'jquery' ) );
wp_localize_script( 'bbpbpng', 'BBPBPNG', array(
'request_uri' => $request_uri,
'cached' => $cached,
'cache_uri' => home_url( 'wp-json/bbpbpng/v1/notification/' ),
'nonce' => wp_create_nonce( 'wp_rest' ),
'ids' => $bbp_ids,
) );
}
return $notifications;
}
/**
* Register the caching endpoint.
*/
function bbpbpng_register_endpoint() {
register_rest_route( 'bbpbpng/v1', '/notification/', array(
'methods' => 'POST',
'callback' => 'bbpbpng_cache_callback',
'permission_callback' => 'bbpbpng_cache_permission_callback',
) );
}
/**
* Permissions callback for the caching endpoint.
*
* @param WP_REST_Request $request
* @return bool
*/
function bbpbpng_cache_permission_callback( WP_REST_Request $request ) {
if ( ! is_user_logged_in() ) {
return false;
}
$params = $request->get_params();
if ( empty( $params['ids'] ) ) {
return false;
}
// Users must own all notifications to set cached value.
$can = true;
foreach ( $params['ids'] as $id ) {
$notification = new BP_Notifications_Notification( $id );
if ( bp_loggedin_user_id() != $notification->user_id ) {
$can = false;
break;
}
}
return $can;
}
/**
* Cache endpoint callback.
*
* @param WP_REST_Request $request
*/
function bbpbpng_cache_callback( WP_REST_Request $request ) {
$params = $request->get_params();
if ( empty( $params['ids'] ) || empty( $request['formatted'] ) ) {
return false;
}
$request_uri = add_query_arg( 'ids', implode( ',', $params['ids'] ), BBPBPNG_ENDPOINT_BASE );
wp_cache_set( md5( $request_uri ), $request['formatted'], 'bbpbpng' );
}
(function($){
$(document).ready(function(){
if ( BBPBPNG.cached.length > 0 ) {
replaceFormattedNotification( BBPBPNG.cached );
} else {
$.ajax( {
method: 'GET',
url: BBPBPNG.request_uri,
beforeSend: function ( xhr ) {
xhr.setRequestHeader( 'X-WP-Nonce', BBPBPNG.nonce );
},
xhrFields: {
// Ensures that auth cookie is sent - required for subdomains.
withCredentials: true
},
success: function( response ) {
replaceFormattedNotification( response );
cacheFormattedNotification( BBPBPNG.request_uri, response );
}
} );
}
});
var replaceFormattedNotification = function( text ) {
$('#wp-admin-bar-bp-notifications-default li a').each( function( k, v ) {
var $item = $( v );
if ( 'bbp_new_reply' == $item.html() ) {
$item.parent().html( text );
}
} );
};
var cacheFormattedNotification = function( request_uri, formatted ) {
$.ajax( {
url: BBPBPNG.cache_uri,
method: 'POST',
beforeSend: function ( xhr ) {
xhr.setRequestHeader( 'X-WP-Nonce', BBPBPNG.nonce );
},
data: {
'ids': BBPBPNG.ids,
'formatted': formatted
}
} );
};
}(jQuery));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment