I have a plugin which adds the option to add a permission filter for church or PMO ID:
This plugin gives the possiblility to hide sites or UX builder objects based on the church or PMO ID given in the id token:
UX Builder field:
Site field:
I guess that such functionaliy would be interesting for many people using the BCC Wordpress plugin so I would like to get this merged into the main plugin - but I am not an expert in neither Wordpress nor PHP. Can someone help me to create a PR for this?
This is the plugin for this functionality:
<?php
/*
Plugin Name: Only Selected Church Or PMO-ID
Description: Allows authors to restrict access to parts or full pages and posts or to widgets to users of your local church or specific users by PMO-ID. Requires the plugin "BCC Signon"
Version: 1.1.0
Author: Simon Schick
Co-Authored: Bastian Wissler, Leonhard Schick
Author URI: http://simonsimcity.net/
CHANGELOG
---------
Version 1.1.0
- use church and user id from id token instead of user metadata
- use case insensitive matching for church name
Version 1.0.0
- initial version
*/
/* =========================================================================
* Non-admin filters
* these perform the actual changes seen by visiters
* =========================================================================*/
/**
* add filters used on non-admin screens
* filter out pages from menus, replace content with message
*/
add_filter('wp_get_nav_menu_items', 'sco_filter_nav_items');
add_filter('wp_list_pages_excludes', 'sco_pages_excludes');
add_filter('get_pages', 'sco_filter_pages');
add_filter('the_posts', 'sco_filter_pages');
add_action('template_redirect', 'sco_redirect');
/**
* exclude locked pages from the list used in the default main menu
* @global type $wpdb wordpress database access
* @param type $excludes the list of excludes
* @return type the modified list of excludes
*/
function sco_pages_excludes($excludes){
global $current_user, $wpdb;
$sql = "SELECT post_id, meta_value from $wpdb->postmeta WHERE meta_key = 'sco_selection'";
$rows = $wpdb->get_results($sql, ARRAY_A );
$ids = array();
foreach($rows as $row) {
if(!sco_allowed($row['post_id'], true, $row['meta_value'])){
$ids[] = $row['post_id'];
}
}
$excludes = array_merge($excludes, $ids);
return $excludes;
}
/**
* filter the navigation menu items. returns all if the user is logged in (ID > 0)
* or those that do not have the sco_selection meta set if the user is not logged in
*
* @global type $current_user the object representing th ecurren user
* @param type $items the menu items
* @return type the filtered menu items
*/
function sco_filter_nav_items($items) {
global $current_user;
foreach($items as $item) {
$allowed = sco_allowed($item->object_id, true);
if($allowed)$filtered[] = $item;
}
return $filtered;
}
/**
* replace the content of posts and pages with the message that the page is locked
* will not reduce the list to empty, always returns at least one post
* @global type $current_user
* @param type $posts a list of posts or pages
* @return type the filtered list
*/
function sco_filter_pages($pages) {
$filtered = array();
foreach($pages as $page) {
$allowed = sco_allowed($page->ID);
$id = $page->ID;
if($allowed) {
$filtered[] = $page;
} else {
if($page->post_type == 'page') {
$filtered[] = sco_set_locked_text($page);
}
}
}
if(!$filtered && $pages){
$filtered[] = sco_set_locked_text($pages[0]);
}
return $filtered;
}
/*
* check for direct access to page or post
* and produce 404 if requested
*/
function sco_redirect() {
global $post;
$pid = $post->ID;
$allowed = sco_allowed($post->ID);
error_log("allowed=$allowed");
if($allowed)return;
error_log("forcing 404");
status_header( 404 );
nocache_headers();
include( get_query_template( '404' ) );
die();
}
/**
* set the text for pages that should not be displayed, also turns off comments
* @global type $current_user
* @param type $page
* @return type
*/
function sco_set_locked_text($page) {
global $current_user;
if(0 < $current_user->ID) {
} else {
$page->post_content = get_option('sco_selection_text', sco_default_login_text());
}
$page->comment_status = 'close';
return $page;
}
/**
* determine if content is to be displayed
* always display if in admin pages
* otherwise display based on lco locked value
* @global type $current_user
* @param type $post_id of the content
* @param type $menu true if this is for a menu
* @return type true if not restricted
*/
function sco_allowed($post_id, $menu=false, $value=null) {
if(is_admin())return true;
$logged_in = is_user_logged_in();
if(!$value)$value = get_post_meta($post_id, 'sco_selection', true);
if(!$value)return true;
return sco_is_user_allowed($value);
}
function sco_get_oidc_token() {
#setcookie('wordpress_nocache', 'true');
$token = '';
$token_id = $_COOKIE['oidc_token_id'];
if ( ! empty( $token_id ) ) {
$token = get_transient( 'oidc_id_token_' . $token_id );
}
return $token;
}
function sco_get_church_for_user() {
$jwt_token_payload = BCC_Login_Token_Utility::get_token_claims( sco_get_oidc_token() );
if ($jwt_token_payload) {
return $jwt_token_payload["https://login.bcc.no/claims/churchName"];
} else {
return '';
}
}
function sco_get_pmoid_for_user() {
$jwt_token_payload = BCC_Login_Token_Utility::get_token_claims( sco_get_oidc_token() );
if ($jwt_token_payload) {
return $jwt_token_payload["https://login.bcc.no/claims/personId"] . "";
} else {
return '';
}
}
function sco_is_user_allowed($selection) {
$cleaned_selection = array_map('strtolower', explode(',',preg_replace('/\s+/', '', $selection)));
return $selection === '' || in_array(strtolower(sco_get_church_for_user()), $cleaned_selection) || in_array(sco_get_pmoid_for_user(), $cleaned_selection);
}
/* =========================================================================
* Page and post admin, used by authors, editors and administrators
* filter the list of pages and posts
* allow the user to set the locked status of a page or post
* =========================================================================*/
/**
* set up filers for the posts and pages lists
* add action to add the locked column
*/
add_filter('manage_posts_columns', 'sco_posts_columns');
add_filter('manage_pages_columns', 'sco_posts_columns');
add_action('manage_posts_custom_column', 'sco_show_columns');
add_action('manage_pages_custom_column', 'sco_show_columns');
/**
* add the locked column and set its headre
* @param array $columns list of columns
* @return string list of columns with locked column added
*/
function sco_posts_columns($columns) {
$columns['sco_selection'] = 'Selected Churches or PMO-IDs Only';
return $columns;
}
/**
* display the content of the locked column
* @global type $post the post for this row and column
* @param type $name the name of the column
*/
function sco_show_columns($name) {
sco_show_column_value($name, 'sco_selection');
}
/**
* display the value for a column
* @param type $name the column being processed
* @param type $key the post meta key that should match the column
*/
function sco_show_column_value($name, $key) {
global $post;
if($name == $key) {
$value = get_post_meta($post->ID, $key, true);
echo $value;
}
}
/**
* set up meta box support on the page and post edit pages
*/
add_action('add_meta_boxes', 'sco_add_metas');
add_action('save_post', 'sco_save_meta');
/**
* add actions to create meta boxes, this must be delayed until the add_meta-box
* these allow the user to set the locked status
*/
function sco_add_metas() {
add_meta_box('sco_show_meta', 'Selected Churches or PMO-IDs Only', 'sco_show_meta', 'post', 'side');
add_meta_box('sco_show_meta', 'Selected Churches or PMO-IDs Only', 'sco_show_meta', 'page', 'side');
}
/**
* display the locked meta box
* @param type $post
*/
function sco_show_meta($post) {
$id = $post->ID;
$fieldId = esc_attr( 'sco_selection' );
$fieldTitle = __( 'Limit to members of church or PMO-ID:', 'text_domain' );
$fieldDescription = __( 'List the churches or PMO-IDs you want to limit this item to. List is comma-separated.', 'text_domain' );
$fieldName = esc_attr( 'sco_selection' );
$fieldValue = esc_attr( get_post_meta($id, 'sco_selection', true) );
$html = <<<QEND
<p>
<label for="$fieldId">$fieldTitle
<input class="widefat" value="$fieldValue" id="$fieldId" name="$fieldName" type="text" />
<small>$fieldDescription</small>
</label>
</p>
QEND;
echo $html;
}
/**
* process the meta box result data
* @param type $post_id
*/
function sco_save_meta($post_id) {
$field = 'sco_selection';
if ($_POST['sco_selection']) {
update_post_meta($post_id, $field, $_POST['sco_selection']);
} else {
delete_post_meta($post_id, $field);
}
}
/* =========================================================================
* Build settings used by administrators either as a separate page or as a
* section in the general settings page.
*
* This code uses the new settings api
* thanks to http://ottopress.com/2009/wordpress-settings-api-tutorial/ for the helpful tutorial
* =========================================================================*/
/**
* set up actions to link into the admin settings
*/
$sco_options_location = 'sco_options'; // on a separate page
add_action('admin_init', 'sco_admin_init');
if($sco_options_location == 'sco_options') {
add_action('admin_menu', 'sco_add_option_page');
}
/**
* run when admin initializes
* register our settings as part of the sco_options_group
* add the section sco_options:sco_options_main
* add the fields to that section
*/
function sco_admin_init() {
global $sco_options_location;
add_settings_section ('sco_options_main', '', 'sco_main_section_text', $sco_options_location);
register_setting('sco_options_group', 'sco_selection_text');
add_settings_field('sco_selection_text', 'Text to display in place of locked content', 'sco_selection_text', $sco_options_location, 'sco_options_main');
}
/**
* action to add the custom options page, for users with manage_options capabilities
*/
function sco_add_option_page() {
add_options_page('Local Church or PMO-ID Only Settings', 'Local Church or PMO-ID Only',
'manage_options', 'sco_options', 'sco_options_page');
}
/**
* display the custom options page
*/
function sco_options_page() {
?>
<div class="wrap">
<h2>Local Church or PMO-ID Only Settings</h2>
<p>Church: <?php echo sco_get_church_for_user() ?></p>
<p>ID: <?php echo sco_get_pmoid_for_user() ?></p>
<form action="options.php" method="post">
<?php settings_fields('sco_options_group');?>
<?php do_settings_sections('sco_options')?>
<p class="submit"> <input name="submit" class="button-primary" type="submit" value="Save changes"/></p>
</form>
</div>
<?php
}
/**
* display the section title, empty if separate page
*/
function sco_main_section_text() {
global $sco_options_location;
if($sco_options_location != 'sco_options'){
echo "<strong>Local Church or PMO-ID Only</strong>";
}
}
/**
* display the form field for the locked page content text
*/
function sco_selection_text() {
$value=trim(get_option('sco_selection_text', ''));
if(!$value) $value = sco_default_login_text ();
echo '<textarea id="sco_selection_text" name="sco_selection_text" rows="5" cols="40" >'.$value.'</textarea>';
}
function sco_default_login_text() {
return '<h3>This content is for local church or selected members only.</h3>';
}
/**
* Access control for all widgets
*/
if ( ! function_exists( 'olc_display_selection_field_in_widget_form' ) ) {
add_action( 'in_widget_form', 'olc_display_selection_field_in_widget_form', 10, 3 );
/**
* Append custom selection field end of the widgets control form
*/
function olc_display_selection_field_in_widget_form( $widget, $return, $instance ) {
$sco_selection = isset( $instance['sco_selection'] ) ? $instance['sco_selection'] : '';
ob_start();
?>
<p>
<label for="<?php echo esc_attr( $widget->get_field_id( 'sco_selection' ) ) ?>"><?php _e( 'Limit to members of church or PMO-IDs:', 'text_domain' ) ?>
<input class="widefat" value="<?php echo esc_attr( $sco_selection ) ?>" id="<?php echo esc_attr( $widget->get_field_id( 'sco_selection' ) ) ?>" name="<?php echo esc_attr( $widget->get_field_name( 'sco_selection' ) ) ?>" type="text" />
<small><?php _e( 'List the churches or PMO-IDs you want to limit this widget to. List is comma-separated.', 'text_domain' ) ?></small>
</label>
</p>
<?php
echo ob_get_clean();
}
}
if ( ! function_exists( 'olc_update_selection_field_in_widget_form' ) ) {
add_action( 'widget_update_callback', 'olc_update_selection_field_in_widget_form', 10, 2 );
function olc_update_selection_field_in_widget_form( $instance, $new_instance ) {
$instance['sco_selection'] = !empty( $new_instance['sco_selection'] ) ? $new_instance['sco_selection'] : '';
return $instance;
}
}
if ( ! function_exists( 'olc_apply_access_control_field_on_widget' ) ) {
add_filter( 'widget_display_callback', 'olc_apply_access_control_field_on_widget', 10, 1 );
function olc_apply_access_control_field_on_widget( $array ) {
$selection = isset( $array['sco_selection'] ) ? $array['sco_selection'] : '';
if (sco_is_user_allowed($selection)) {
return $array;
} else {
return false;
}
};
}
/**
* Access control for all shortcodes
*/
if ( ! function_exists( 'olc_add_selection_to_ux_builder_shortcode_data' ) ) {
add_filter( 'ux_builder_shortcode_data', 'olc_add_selection_to_ux_builder_shortcode_data', 10, 1 );
function olc_add_selection_to_ux_builder_shortcode_data( $data ) {
$data['options']['sco_selection'] = array(
'type' => 'textfield',
'heading' => 'Limit to members of church or PMO-IDs:',
'placeholder' => 'Enter church names or PMO-IDs (comma separated)...',
'default' => '',
);
return $data;
};
}
if ( ! function_exists( 'olc_pre_do_shortcode_tag' ) ) {
add_filter( 'pre_do_shortcode_tag', 'olc_pre_do_shortcode_tag', 10, 3 );
function olc_pre_do_shortcode_tag( $data, $tag, $attr ) {
if ($data !== false) {
return $data;
}
// Hide the element (return empty string) if ...
return (
is_array($attr) &&
!empty($attr['sco_selection']) &&
!sco_is_user_allowed($attr['sco_selection'])
) ? '' : false;
};
}
/* =========================================================================
* end of program, php close tag intentionally omitted
* ========================================================================= */
I have a plugin which adds the option to add a permission filter for church or PMO ID:
This plugin gives the possiblility to hide sites or UX builder objects based on the church or PMO ID given in the id token:
UX Builder field:
Site field:
I guess that such functionaliy would be interesting for many people using the BCC Wordpress plugin so I would like to get this merged into the main plugin - but I am not an expert in neither Wordpress nor PHP. Can someone help me to create a PR for this?
This is the plugin for this functionality:
It is possible to add it as a dedicated plugin.