singleton.
*
* @since 2.0
*/
private function __construct() {
if ( is_admin() ) {
// in_widget_form: Add our button inside each widget.
add_action(
'in_widget_form',
array( $this, 'admin_widget_button' ),
10, 3
);
// When the widget is saved (via Ajax) we save our options.
add_filter(
'widget_update_callback',
array( $this, 'admin_widget_update' ),
10, 3
);
$url = 'widgets.php';
if ( isset( $_SERVER['SCRIPT_NAME'] ) ) {
$url = explode( '/', $_SERVER['SCRIPT_NAME'] );
$url = array_pop( $url );
}
lib3()->ui->add( CSB_JS_URL . 'cs-visibility.min.js', $url );
lib3()->ui->add( CSB_CSS_URL . 'cs-visibility.css', $url );
// Custom Sidebars Ajax request.
add_action(
'cs_ajax_request_get',
array( $this, 'handle_ajax' )
);
} else {
// Filters the list of widget-areas and their widgets
add_filter(
'sidebars_widgets',
array( $this, 'sidebars_widgets' )
);
}
}
/**
* Extracts and sanitizes the CSB visibility data from the widget instance.
*
* @since 2.0
* @param array $instance The widget instance data.
* @return array Sanitized CSB visibility data.
*/
protected function get_widget_data( $instance ) {
static $Condition_keys = null;
$data = array();
if ( null === $Condition_keys ) {
$tax_list = get_taxonomies( array( 'public' => true ), 'objects' );
$type_list = CustomSidebars::get_post_types( 'objects' );
$Condition_keys = array(
'guest' => array(),
'date' => array(),
'roles' => array(),
'pagetypes' => array(),
'posttypes' => array(),
'membership' => array(),
'membership2' => array(),
'prosite' => array(),
);
foreach ( $type_list as $type_item ) {
$Condition_keys[ 'pt-' . $type_item->name ] = array();
}
foreach ( $tax_list as $tax_item ) {
$Condition_keys[ 'tax-' . $tax_item->name ] = array();
}
}
if ( isset( $instance['csb_visibility'] ) ) {
$data = $instance['csb_visibility'];
}
$valid_action = array( 'show', 'hide' );
if ( ! isset( $data['action'] ) || ! in_array( $data['action'], $valid_action ) ) {
$data['action'] = reset( $valid_action );
}
$conditions = isset( $data['conditions'] )? $data['conditions'] : array();
if ( ! is_array( $conditions ) ) {
$conditions = array();
}
$data['conditions'] = array();
$data['always'] = true;
foreach ( $Condition_keys as $key => $def_value ) {
$val = $def_value;
if ( isset( $conditions[ $key ] ) && ! empty( $conditions[ $key ] ) ) {
$data['always'] = false;
$val = $conditions[ $key ];
}
$data['conditions'][ $key ] = $val;
}
return $data;
}
/**
* Action handler for 'in_widget_form'
*
* @since 2.0
*/
public function admin_widget_button( $widget, $return, $instance ) {
static $Loaded = false;
static $tax_list = array();
static $type_list = array();
static $role_list = array();
static $membership_levels = array();
static $pagetype_list = array();
if ( false === $Loaded ) {
$tax_list = get_taxonomies( array( 'public' => true ), 'objects' );
$type_list = CustomSidebars::get_post_types( 'objects' );
$role_list = array_reverse( get_editable_roles() );
$membership_levels = $this->get_membership_levels();
$membership2_items = $this->get_membership2_items();
$pagetype_list = array(
'frontpage' => 'Front Page',
'home' => 'Post Index',
'single' => 'Single page',
//'posts' => 'Posts page', "Posts page" is same as "Post Index"...
'archive' => 'Archives',
'search' => 'Search results',
'e404' => 'Not found (404)',
'preview' => 'Preview',
'day' => 'Archive: Day',
'month' => 'Archive: Month',
'year' => 'Archive: Year',
);
// Remove taxonomies without values.
if ( ! self::$filtered_tax_list ) {
foreach ( $tax_list as $index => $tax_item ) {
$tags = get_terms( $tax_item->name, array( 'hide_empty' => false ) );
if ( empty( $tags ) ) {
unset( $tax_list[ $index ] );
}
}
self::$filtered_tax_list = $tax_list;
} else {
$tax_list = self::$filtered_tax_list;
}
}
$is_visible = ( isset( $_POST['csb_visible'] ) && '1' == $_POST['csb_visible'] ? 1 : 0);
$data = $this->get_widget_data( $instance );
$action_show = ('show' == $data['action']);
$cond = $data['conditions'];
?>
get_results(
sprintf(
'SELECT
id, level_title, level_active
FROM %s
ORDER BY id',
MEMBERSHIP_TABLE_LEVELS
), ARRAY_A
);
} else {
$Result = false;
}
}
return $Result;
}
/**
* Integration with the WPMU Dev Membership2 plugin:
* If the plugin is installed and active this function returns a list of
* all membership levels.
*
* If the plugin is not active the return value is boolean false.
*
* @since 2.0
* @return bool|array
*/
public function get_membership2_items() {
$Result = null;
if ( null === $Result ) {
$is_active_membership = apply_filters( 'ms_active', false );
if ( $is_active_membership ) {
$Result = MS_Plugin::$api->list_memberships( true );
}
}
return $Result;
}
/**
* When user saves the widget we check for the
*
* @since 2.0
* @param array $new_instance New settings for this instance as input by the user.
* @param array $old_instance Old settings for this instance.
* @return array Modified settings.
*/
public function admin_widget_update( $instance, $new_instance, $old_instance ) {
$data = $this->get_widget_data( $_POST );
foreach ( $data['conditions'] as $key => $list ) {
if ( ! is_array( $list ) ) {
$list = explode( ',', $list );
$data['conditions'][ $key ] = $list;
}
}
$instance['csb_visibility'] = $data;
return $instance;
}
// == Front-end functions
/**
* Filter the list of widgets for a sidebar so that active sidebars work as expected.
*
* @since 2.0
* @param array $widget_areas An array of widget areas and their widgets.
* @return array The modified $widget_area array.
*/
public function sidebars_widgets( $widget_areas ) {
static $Settings = array();
static $Result = array();
$expl = CustomSidebarsExplain::do_explain();
if ( ! did_action( 'cs_before_replace_sidebars' ) ) {
return $widget_areas;
}
$key = serialize( $widget_areas );
if ( ! isset( $Result[ $key ] ) ) {
$expl && do_action( 'cs_explain', 'Filter widgets
', true );
foreach ( $widget_areas as $widget_area => $widgets ) {
if ( empty( $widgets ) ) {
continue;
}
if ( 'wp_inactive_widgets' == $widget_area ) {
continue;
}
$expl && do_action( 'cs_explain', 'Sidebar "' . $widget_area . '"
', true );
foreach ( $widgets as $position => $widget_id ) {
// Find the conditions for this widget.
if ( preg_match( '/^(.+?)-(\d+)$/', $widget_id, $matches ) ) {
$id_base = $matches[1];
$widget_number = intval( $matches[2] );
} else {
$id_base = $widget_id;
$widget_number = null;
}
if ( ! isset( $Settings[ $id_base ] ) ) {
$Settings[ $id_base ] = get_option( 'widget_' . $id_base );
}
$expl && do_action( 'cs_explain', 'Widget "' . $widget_id . '"', true );
// New multi widget (WP_Widget)
if ( ! is_null( $widget_number ) ) {
if ( isset( $Settings[ $id_base ][ $widget_number ] ) && false === $this->maybe_display_widget( $Settings[ $id_base ][ $widget_number ] ) ) {
unset( $widget_areas[ $widget_area ][ $position ] );
}
} elseif ( ! empty( $Settings[ $id_base ] ) && false === $this->maybe_display_widget( $Settings[ $id_base ] ) ) {
// Old single widget.
unset( $widget_areas[ $widget_area ][ $position ] );
}
}
}
$Result[ $key ] = $widget_areas;
}
return $Result[ $key ];
}
public function maybe_display_widget( $instance ) {
global $post, $wp_query;
static $Type_list = null;
static $Tax_list = null;
$show_widget = true;
$condition_true = true;
$action = 'show';
$explain = ''; // This is used to explain why a widget is not displayed.
$expl = CustomSidebarsExplain::do_explain();
if ( empty( $instance['csb_visibility'] ) || empty( $instance['csb_visibility']['conditions'] ) ) {
return $show_widget;
}
$cond = $instance['csb_visibility']['conditions'];
$action = 'hide' != $instance['csb_visibility']['action'] ? 'show' : 'hide';
if ( $instance['csb_visibility']['always'] ) {
$expl && do_action( 'cs_explain', 'Always ' . $action . '' );
return ( 'hide' == $action ? false : true );
}
if ( null === $Type_list ) {
$Tax_list = get_taxonomies( array( 'public' => true ), 'objects' );
$Type_list = get_post_types( array( 'public' => true ), 'objects' );
}
// Filter for DATE-RANGE.
if ( $condition_true && ! empty( $cond['date'] ) ) {
// not implemented yet...
}
// Filter for GUEST STATUS.
if ( $condition_true && ! empty( $cond['guest'] ) && is_array( $cond['guest'] ) ) {
$expl && $explain .= '
GUEST [';
if ( is_user_logged_in() ) {
if ( 'member' != $cond['guest'][0] ) {
$expl && $explain .= 'user is logged in';
$condition_true = false;
}
} else {
if ( 'guest' != $cond['guest'][0] ) {
$expl && $explain .= 'user not logged in';
$condition_true = false;
}
}
$expl && $explain .= '] ';
}
// Filter for USER ROLES.
if ( $condition_true && ! empty( $cond['roles'] ) && is_array( $cond['roles'] ) ) {
$expl && $explain .= '
ROLE [';
if ( ! is_user_logged_in() ) {
$expl && $explain .= 'user not logged in';
$condition_true = false;
} else {
global $current_user;
$has_role = false;
foreach ( $current_user->roles as $user_role ) {
if ( in_array( $user_role, $cond['roles'] ) ) {
$expl && $explain .= 'ok:' . $user_role;
$has_role = true;
break;
}
}
if ( ! $has_role ) {
$expl && $explain .= 'invalid role';
$condition_true = false;
}
}
$expl && $explain .= '] ';
}
// Filter for MEMBERSHIP Level.
if ( $condition_true && ! empty( $cond['membership'] ) ) {
$expl && $explain .= '
MEMBERSHIP [';
if ( class_exists( 'Membership_Factory' ) ) {
$has_level = false;
$wpuser = get_userdata( get_current_user_id() );
$is_admin = $wpuser && (
$wpuser->has_cap( 'membershipadmin' ) ||
$wpuser->has_cap( 'manage_options' ) ||
is_super_admin()
);
if ( $is_admin ) {
$expl && $explain .= 'is admin';
$has_level = true;
} else {
$factory = new Membership_Factory();
$user = $factory->get_member( get_current_user_id() );
$levels = $user->get_level_ids();
if ( ! is_array( $levels ) ) { $levels = array( $levels ); }
foreach ( $cond['membership'] as $need_level_id ) {
if ( empty( $need_level_id ) ) { continue; }
foreach ( $levels as $the_level ) {
if ( $the_level->level_id == $need_level_id ) {
$expl && $explain .= 'ok';
$has_level = true;
break;
}
}
if ( $has_level ) { break; }
}
}
if ( ! $has_level ) {
$expl && $explain .= 'invalid user level';
$condition_true = false;
}
}
$expl && $explain .= '] ';
}
// Filter for MEMBERSHIP2 Level.
if ( $condition_true && ! empty( $cond['membership2'] ) ) {
$expl && $explain .= '
MEMBERSHIP2 [';
if ( apply_filters( 'ms_active', false ) ) {
$is_member = false;
$member = MS_Plugin::$api->get_current_member();
if ( $member->is_admin_user() ) {
$expl && $explain .= 'is admin';
$is_member = true;
} else {
foreach ( $cond['membership2'] as $membership_id ) {
if ( $member->has_membership( $membership_id ) ) {
$is_member = true;
break;
}
}
}
if ( ! $is_member ) {
$expl && $explain .= 'is no member';
$condition_true = false;
}
}
$expl && $explain .= '] ';
}
// Filter for PRO-SITE Level.
if ( $condition_true && ! empty( $cond['prosite'] ) ) {
$expl && $explain .= '
PROSITE [';
// not implemented yet...
$expl && $explain .= '] ';
}
// Filter for SPECIAL PAGES.
if ( $condition_true && ! empty( $cond['pagetypes'] ) && is_array( $cond['pagetypes'] ) ) {
$expl && $explain .= '
PAGETYPE [';
$is_type = false;
foreach ( $cond['pagetypes'] as $type ) {
if ( $is_type ) {
break;
}
switch ( $type ) {
case 'e404':
$is_type = $is_type || is_404();
break;
case 'single':
$is_type = $is_type || is_singular();
break;
case 'search':
$is_type = $is_type || is_search();
break;
case 'archive':
$is_type = $is_type || is_archive();
break;
case 'preview':
$is_type = $is_type || is_preview();
break;
case 'day':
$is_type = $is_type || is_day();
break;
case 'month':
$is_type = $is_type || is_month();
break;
case 'year':
$is_type = $is_type || is_year();
break;
case 'frontpage':
if ( current_theme_supports( 'infinite-scroll' ) ) {
$is_type = $is_type || is_front_page();
} else {
$is_type = $is_type || ( is_front_page() && ! is_paged() );
}
break;
case 'posts':
case 'home':
$is_type = $is_type || is_home();
break;
}
$expl && $explain .= $type . ':' . ($is_type ? 'ok' : 'invalid');
}
if ( ! $is_type ) {
$condition_true = false;
}
$expl && $explain .= '] ';
}
// Filter for POST-TYPE.
if ( $condition_true && ! empty( $cond['posttypes'] ) ) {
$posttype = get_post_type();
$expl && $explain .= '
POSTTYPE-' . strtoupper( $posttype ) . ' [';
if ( ! in_array( $posttype, $cond['posttypes'] ) ) {
$expl && $explain .= 'invalid posttype';
$condition_true = false;
} else {
// Filter for SPECIFIC POSTS.
if ( ! empty( $cond[ 'pt-' . $posttype ] ) ) {
if ( ! in_array( get_the_ID(), $cond[ 'pt-' . $posttype ] ) ) {
$expl && $explain .= 'invalid post_id';
$condition_true = false;
}
}
}
if ( $condition_true ) {
$expl && $explain .= 'ok';
}
$expl && $explain .= '] ';
}
if ( $condition_true ) {
// TAXONOMY condition.
$tax_query = null;
if ( isset( $wp_query->tax_query ) ) {
$tax_query = $wp_query->tax_query->queries;
}
$tax_type = $tax_terms = false;
if ( ! empty( $tax_query ) && is_array( $tax_query ) ) {
$tax_type = $tax_query[0]['taxonomy'];
$tax_terms = $tax_query[0]['terms'];
}
foreach ( $Tax_list as $tax_item ) {
if ( ! $condition_true ) {
break;
}
$tax_key = 'tax-' . $tax_item->name;
if ( isset( $cond[ $tax_key ] ) && ! empty( $cond[ $tax_key ] ) ) {
$expl && $explain .= '
TAX-' . strtoupper( $tax_item->name ) . ' [';
$has_term = false;
if ( $tax_type && $tax_type == $tax_item->name ) {
// Check if we did filter for the specific taxonomy.
foreach ( $tax_terms as $slug ) {
$term_data = get_term_by( 'slug', $slug, $tax_type );
if ( in_array( $term_data->term_id, $cond[ $tax_key ] ) ) {
$expl && $explain .= 'ok:' . $term_data->term_id;
$has_term = true;
}
}
} else {
// Check if current post has the specific taxonomy.
foreach ( $cond[ $tax_key ] as $term ) {
if ( has_term( $term, $tax_item->name ) ) {
$expl && $explain .= 'ok:' . $term;
$has_term = true;
break;
}
}
}
if ( ! $has_term ) {
$expl && $explain .= 'no match';
$condition_true = false;
}
$expl && $explain .= '] ';
}
}
}
if ( ( 'show' == $action && ! $condition_true ) || ( 'hide' == $action && $condition_true ) ) {
$show_widget = false;
}
$expl && do_action(
'cs_explain',
($condition_true ? 'Do' : 'Dont') .
' ' . $action . ' - ' .
$explain
);
return $show_widget;
}
//
// ========== AJAX Handler
//
/**
* Ajax handler. If the action is processed the request is closed via die()
*
* @since 2.0.9.7
* @param string $action
*/
public function handle_ajax( $action ) {
// The ajax request was not meant for us...
if ( 'visibility' != $action ) {
return false;
}
$data = array();
if ( isset( $_GET['tag'] ) ) {
$data = $this->ajax_data_terms( @$_GET['tag'], @$_REQUEST['q'] );
} elseif ( isset( $_GET['posttype'] ) ) {
$data = $this->ajax_data_posts( @$_GET['posttype'], @$_REQUEST['q'] );
}
self::json_response( array( 'items' => $data ) );
}
/**
* Returns an array with tags that contain the specified search term.
*
* @since 2.0.9.7
* @param string $term_name Taxonomy type.
* @param string $search Search term.
* @return array
*/
protected function ajax_data_terms( $term_name, $search ) {
$data = array();
$tags = get_terms(
$term_name,
array(
'hide_empty' => false,
'search' => $search,
)
);
foreach ( $tags as $tag ) {
$key = $tag->term_id;
$name = $tag->name;
$data[] = array(
'id' => $key,
'text' => esc_html( $name ),
);
}
return $data;
}
/**
* Returns an array with post-titles that contain the specified search term.
*
* @since 2.0.9.7
* @param string $posttype Post-type to search.
* @param string $search Search term.
* @return array
*/
protected function ajax_data_posts( $posttype, $search ) {
$data = array();
$posts = get_posts(
array(
'post_type' => $posttype,
'order_by' => 'title',
'order' => 'ASC',
'numberposts' => '0',
's' => $search,
)
);
foreach ( $posts as $post ) {
$id = $post->ID;
$text = $post->post_title;
$data[] = array(
'id' => $post->ID,
'text' => esc_html( $text ),
);
}
return $data;
}
};