Skip to content

Instantly share code, notes, and snippets.

@cfinke
Created April 1, 2014 21:52
Show Gist options
  • Save cfinke/9923889 to your computer and use it in GitHub Desktop.
Save cfinke/9923889 to your computer and use it in GitHub Desktop.
diff --git a/modules/widget-visibility/widget-conditions.php b/modules/widget-visibility/widget-conditions.php
index bcb32dc..6aedfec 100644
--- a/modules/widget-visibility/widget-conditions.php
+++ b/modules/widget-visibility/widget-conditions.php
@@ -17,6 +17,26 @@ class Jetpack_Widget_Conditions {
add_action( 'widget_display_callback', array( __CLASS__, 'filter_widget' ) );
add_action( 'sidebars_widgets', array( __CLASS__, 'sidebars_widgets' ) );
}
+
+ /**
+ * The widget_visibility_major_conditions filter accepts an array of existing conditions
+ * and should add new conditions in this format:
+ *
+ * $existing_conditions['my_unique_key'] = array(
+ * 'title' => 'User-facing label for this condition type',
+ * 'callback' => callable that accepts two arguments: a major condition (e.g., 'my_unique_key')
+ * and optional minor value (e.g., 'one_of_several_values')
+ */
+ add_filter( 'widget_visibility_major_conditions', array( __CLASS__, 'major_conditions' ) );
+
+ /**
+ * The widget_visibility_minor_conditions filter accepts two arguments: a major condition (e.g.,
+ * 'my_unique_key') and an array of exisiting minor values. It should add new minor conditions in
+ * this format:
+ *
+ * $existing_minor_conditions['a_unique_key'] = 'User-facing label for this condition type'
+ */
+ add_filter( 'widget_visibility_minor_conditions', array( __CLASS__, 'minor_conditions' ), 10, 2 );
}
public static function widget_admin_setup() {
@@ -25,120 +45,278 @@ class Jetpack_Widget_Conditions {
}
/**
- * Provided a second level of granularity for widget conditions.
+ * Register the major condition types that we'll support by default.
*/
- public static function widget_conditions_options_echo( $major = '', $minor = '' ) {
- switch ( $major ) {
+ public static function major_conditions( $major_conditions ) {
+ return array_merge( $major_conditions, array(
+ 'category' => array(
+ 'title' => __( 'Category', 'jetpack' ),
+ 'callback' => array( __CLASS__, 'condition_callback' ),
+ ),
+ 'author' => array(
+ 'title' => _x( 'Author', 'Noun, as in: "The author of this post is..."', 'jetpack' ),
+ 'callback' => array( __CLASS__, 'condition_callback' ),
+ ),
+ 'tag' => array(
+ 'title' => _x( 'Tag', 'Noun, as in: "This post has one tag."', 'jetpack' ),
+ 'callback' => array( __CLASS__, 'condition_callback' ),
+ ),
+ 'date' => array(
+ 'title' => _x( 'Date', 'Noun, as in: "This page is a date archive."', 'jetpack' ),
+ 'callback' => array( __CLASS__, 'condition_callback' ),
+ ),
+ 'page' => array(
+ 'title' => _x( 'Page', 'Example: The user is looking at a page, not a post.', 'jetpack' ),
+ 'callback' => array( __CLASS__, 'condition_callback' ),
+ ),
+ 'taxonomy' => array(
+ 'title' => _x( 'Taxonomy', 'Noun, as in: "This post has one taxonomy."', 'jetpack' ),
+ 'callback' => array( __CLASS__, 'condition_callback' ),
+ ),
+ ) );
+ }
+
+ /**
+ * Register the possible values for the major conditions that we support.
+ *
+ * @param array $minor_conditions An associative array of possible values.
+ * @param string $major_condition The condition for these values.
+ * @return array
+ */
+ public static function minor_conditions( $minor_conditions, $major_condition ) {
+ switch ( $major_condition ) {
case 'category':
- ?>
- <option value=""><?php _e( 'All category pages', 'jetpack' ); ?></option>
- <?php
+ $minor_conditions[''] = __( 'All category pages', 'jetpack' );
$categories = get_categories( array( 'number' => 1000, 'orderby' => 'count', 'order' => 'DESC' ) );
usort( $categories, array( __CLASS__, 'strcasecmp_name' ) );
-
+
foreach ( $categories as $category ) {
- ?>
- <option value="<?php echo esc_attr( $category->term_id ); ?>" <?php selected( $category->term_id, $minor ); ?>><?php echo esc_html( $category->name ); ?></option>
- <?php
+ $minor_conditions[$category->term_id] = $category->name;
}
break;
case 'author':
- ?>
- <option value=""><?php _e( 'All author pages', 'jetpack' ); ?></option>
- <?php
-
+ $minor_conditions[''] = __( 'All author pages', 'jetpack' );
+
foreach ( get_users( array( 'orderby' => 'name', 'exclude_admin' => true ) ) as $author ) {
- ?>
- <option value="<?php echo esc_attr( $author->ID ); ?>" <?php selected( $author->ID, $minor ); ?>><?php echo esc_html( $author->display_name ); ?></option>
- <?php
+ $minor_conditions[$author->ID] = $author->display_name;
}
break;
case 'tag':
- ?>
- <option value=""><?php _e( 'All tag pages', 'jetpack' ); ?></option>
- <?php
-
+ $minor_conditions[''] = __( 'All tag pages', 'jetpack' );
+
$tags = get_tags( array( 'number' => 1000, 'orderby' => 'count', 'order' => 'DESC' ) );
usort( $tags, array( __CLASS__, 'strcasecmp_name' ) );
foreach ( $tags as $tag ) {
- ?>
- <option value="<?php echo esc_attr($tag->term_id ); ?>" <?php selected( $tag->term_id, $minor ); ?>><?php echo esc_html( $tag->name ); ?></option>
- <?php
+ $minor_conditions[$tag->term_id] = $tag->name;
}
break;
case 'date':
- ?>
- <option value="" <?php selected( '', $minor ); ?>><?php _e( 'All date archives', 'jetpack' ); ?></option>
- <option value="day"<?php selected( 'day', $minor ); ?>><?php _e( 'Daily archives', 'jetpack' ); ?></option>
- <option value="month"<?php selected( 'month', $minor ); ?>><?php _e( 'Monthly archives', 'jetpack' ); ?></option>
- <option value="year"<?php selected( 'year', $minor ); ?>><?php _e( 'Yearly archives', 'jetpack' ); ?></option>
- <?php
+ $minor_conditions[''] = __( 'All date archives', 'jetpack' );
+ $minor_conditions['day'] = __( 'Daily archives', 'jetpack' );
+ $minor_conditions['month'] = __( 'Monthly archives', 'jetpack' );
+ $minor_conditions['year'] = __( 'Yearly archives', 'jetpack' );
break;
case 'page':
- // Previously hardcoded post type options.
- if ( ! $minor )
- $minor = 'post_type-page';
- else if ( 'post' == $minor )
- $minor = 'post_type-post';
+ $minor_conditions['front'] = __( 'Front page', 'jetpack' );
+ $minor_conditions['posts'] = __( 'Posts page', 'jetpack' );
+ $minor_conditions['archive'] = __( 'Archive page', 'jetpack' );
+ $minor_conditions['404'] = __( '404 error page', 'jetpack' );
+ $minor_conditions['search'] = __( 'Search results', 'jetpack' );
- ?>
- <option value="front" <?php selected( 'front', $minor ); ?>><?php _e( 'Front page', 'jetpack' ); ?></option>
- <option value="posts" <?php selected( 'posts', $minor ); ?>><?php _e( 'Posts page', 'jetpack' ); ?></option>
- <option value="archive" <?php selected( 'archive', $minor ); ?>><?php _e( 'Archive page', 'jetpack' ); ?></option>
- <option value="404" <?php selected( '404', $minor ); ?>><?php _e( '404 error page', 'jetpack' ); ?></option>
- <option value="search" <?php selected( 'search', $minor ); ?>><?php _e( 'Search results', 'jetpack' ); ?></option>
- <optgroup label="<?php esc_attr_e( 'Post type:', 'jetpack' ); ?>">
- <?php
+ $post_type_values = array();
+ $post_types = get_post_types( array( 'public' => true ), 'objects' );
- $post_types = get_post_types( array( 'public' => true ), 'objects' );
+ foreach ( $post_types as $post_type ) {
+ $post_type_values[ 'post_type-' . $post_type->name ] = $post_type->labels->singular_name;
+ }
- foreach ( $post_types as $post_type ) {
- ?>
- <option value="<?php echo esc_attr( 'post_type-' . $post_type->name ); ?>" <?php selected( 'post_type-' . $post_type->name, $minor ); ?>><?php echo esc_html( $post_type->labels->singular_name ); ?></option>
- <?php
- }
+ $minor_conditions[ __( 'Post type:', 'jetpack' ) ] = $post_type_values;
- ?>
- </optgroup>
- <optgroup label="<?php esc_attr_e( 'Static page:', 'jetpack' ); ?>">
- <?php
+ $static_pages = array();
- echo str_replace( ' value="' . esc_attr( $minor ) . '"', ' value="' . esc_attr( $minor ) . '" selected="selected"', preg_replace( '/<\/?select[^>]*?>/i', '', wp_dropdown_pages( array( 'echo' => false ) ) ) );
+ $pages = get_pages( array( 'sort_order' => 'menu_order' ) );
+ $parent_depths = array();
+
+ foreach ( $pages as $page ) {
+ if ( isset( $parent_depths[ $page->post_parent ] ) ) {
+ $depth = $parent_depths[ $page->post_parent ] + 1;
+ }
+ else {
+ $depth = 0;
+ }
+
+ $parent_depths[ $page->ID ] = $depth;
- ?>
- </optgroup>
- <?php
+ $static_pages[ $page->ID ] = str_repeat( "&nbsp;", $depth * 2 ) . $page->post_title;
+ }
+
+ $minor_conditions[ __( 'Static page:', 'jetpack' ) ] = $static_pages;
break;
case 'taxonomy':
- ?>
- <option value=""><?php _e( 'All taxonomy pages', 'jetpack' ); ?></option>
- <?php
+ $minor_conditions[''] = __( 'All taxonomy pages', 'jetpack' );
$taxonomies = get_taxonomies( array( '_builtin' => false ), 'objects' );
usort( $taxonomies, array( __CLASS__, 'strcasecmp_name' ) );
foreach ( $taxonomies as $taxonomy ) {
- ?>
- <optgroup label="<?php esc_attr_e( $taxonomy->labels->name . ':', 'jetpack' ); ?>">
- <option value="<?php echo esc_attr( $taxonomy->name ); ?>" <?php selected( $taxonomy->name, $minor ); ?>><?php echo 'All ' . esc_html( $taxonomy->name ) . ' pages'; ?></option>
- <?php
-
- $terms = get_terms( array( $taxonomy->name ), array( 'number' => 1000, 'hide_empty' => false ) );
- foreach ( $terms as $term ) {
- ?>
- <option value="<?php echo esc_attr( $taxonomy->name . '_tax_' . $term->term_id ); ?>" <?php selected( $taxonomy->name . '_tax_' . $term->term_id, $minor ); ?>><?php echo esc_html( $term->name ); ?></option>
- <?php
+ $sub_taxonomies = array(
+ $taxonomy->name => sprintf( __( 'All %s pages', 'jetpack' ), $taxonomy->name ),
+ );
+
+ $terms = get_terms( array( $taxonomy->name ), array( 'number' => 1000, 'hide_empty' => false ) );
+ foreach ( $terms as $term ) {
+ $sub_taxonomies[ $taxonomy->name . '_tax_' . $term->term_id ] = $term->name;
+ }
+
+ $minor_conditions[ $taxonomy->labels->name . ':' ] = $sub_taxonomies;
+ }
+ break;
+ }
+
+ return $minor_conditions;
+ }
+
+ /**
+ * The callback that does the actual filtering.
+ *
+ * @param string $major The "major" filter category.
+ * @param string $minor The "minor" filter value.
+ * @return boolean Whether this condition is met in the current context.
+ */
+ public static function condition_callback( $major, $minor ) {
+ switch ( $major ) {
+ case 'date':
+ switch ( $minor ) {
+ case '':
+ return is_date();
+ break;
+ case 'month':
+ return is_month();
+ break;
+ case 'day':
+ return is_day();
+ break;
+ case 'year':
+ return is_year();
+ break;
+ }
+ break;
+ case 'page':
+ // Previously hardcoded post type options.
+ if ( 'post' == $minor )
+ $minor = 'post_type-post';
+ else if ( ! $minor )
+ $minor = 'post_type-page';
+
+ switch ( $minor ) {
+ case '404':
+ return is_404();
+ break;
+ case 'search':
+ return is_search();
+ break;
+ case 'archive':
+ return is_archive();
+ break;
+ case 'posts':
+ return $wp_query->is_posts_page;
+ break;
+ case 'home':
+ return is_home();
+ break;
+ case 'front':
+ if ( current_theme_supports( 'infinite-scroll' ) )
+ return is_front_page();
+ else {
+ return is_front_page() && !is_paged();
}
+ break;
+ default:
+ if ( substr( $minor, 0, 10 ) == 'post_type-' )
+ return is_singular( substr( $minor, 10 ) );
+ else {
+ // $minor is a page ID -- check if we're either looking at that particular page itself OR looking at the posts page, with the correct conditions
+ return ( is_page( $minor ) || ( get_option( 'show_on_front' ) == 'page' && $wp_query->is_posts_page && get_option( 'page_for_posts' ) == $minor ) );
+ }
+ break;
+ }
+ break;
+ case 'tag':
+ if ( ! $minor && is_tag() )
+ return true;
+ else if ( is_singular() && $minor && has_tag( $minor ) )
+ return true;
+ else {
+ $tag = get_tag( $minor );
- ?>
- </optgroup>
- <?php
-
-
+ if ( $tag && is_tag( $tag->slug ) )
+ return true;
}
break;
+ case 'category':
+ if ( ! $minor && is_category() )
+ return true;
+ else if ( is_category( $minor ) )
+ return true;
+ else if ( is_singular() && $minor && in_array( 'category', get_post_taxonomies() ) && has_category( $minor ) )
+ return true;
+ break;
+ case 'author':
+ if ( ! $minor && is_author() )
+ return true;
+ else if ( $minor && is_author( $minor ) )
+ return true;
+ else if ( is_singular() && $minor && $minor == $post->post_author )
+ return true;
+ break;
+ case 'taxonomy':
+ $term = explode( '_tax_', $minor ); // $term[0] = taxonomy name; $term[1] = term id
+ $terms = get_the_terms( $post->ID, $minor ); // Does post have terms in taxonomy?
+ if ( is_tax( $term[0], $term[1] ) )
+ return true;
+ else if ( is_singular() && $term[1] && has_term( $term[1], $term[0] ) )
+ return true;
+ else if ( is_singular() && $terms & !is_wp_error( $terms ) )
+ return true;
+ break;
+ }
+
+ return false;
+ }
+
+ /**
+ * Provided a second level of granularity for widget conditions.
+ */
+ public static function widget_conditions_options_echo( $major = '', $selected_value = '' ) {
+ if ( $major ) {
+ $minor_conditions = apply_filters( 'widget_visibility_minor_conditions', array(), $major );
+
+ foreach ( $minor_conditions as $key => $val ) {
+ self::do_widget_conditions_options_echo( $selected_value, $key, $val );
+ }
+ }
+ }
+
+ private static function do_widget_conditions_options_echo( $selected_value, $minor_key, $minor_value ) {
+ if ( is_array( $minor_value ) ) {
+ ?>
+ <optgroup label="<?php echo esc_attr( $minor_key ); ?>">
+ <?php
+
+ foreach ( $minor_value as $grouped_minor_key => $grouped_minor_value ) {
+ self::do_widget_conditions_options_echo( $selected_value, $grouped_minor_key, $grouped_minor_value );
+ }
+
+ ?>
+ </optgroup>
+ <?php
+ }
+ else {
+ ?>
+ <option value="<?php echo esc_attr( $minor_key ); ?>" <?php selected( $minor_key, $selected_value ); ?>><?php echo esc_html( $minor_value ); ?></option>
+ <?php
}
}
@@ -169,6 +347,8 @@ class Jetpack_Widget_Conditions {
if ( empty( $conditions['rules'] ) )
$conditions['rules'][] = array( 'major' => '', 'minor' => '' );
+ $major_conditions = apply_filters( 'widget_visibility_major_conditions', array() );
+
?>
<div class="widget-conditional <?php if ( empty( $_POST['widget-conditions-visible'] ) || $_POST['widget-conditions-visible'] == '0' ) { ?>widget-conditional-hide<?php } ?>">
<input type="hidden" name="widget-conditions-visible" value="<?php if ( isset( $_POST['widget-conditions-visible'] ) ) { echo esc_attr( $_POST['widget-conditions-visible'] ); } else { ?>0<?php } ?>" />
@@ -187,12 +367,9 @@ class Jetpack_Widget_Conditions {
<div class="alignleft">
<select class="conditions-rule-major" name="conditions[rules_major][]">
<option value="" <?php selected( "", $rule['major'] ); ?>><?php echo esc_html_x( '-- Select --', 'Used as the default option in a dropdown list', 'jetpack' ); ?></option>
- <option value="category" <?php selected( "category", $rule['major'] ); ?>><?php esc_html_e( 'Category', 'jetpack' ); ?></option>
- <option value="author" <?php selected( "author", $rule['major'] ); ?>><?php echo esc_html_x( 'Author', 'Noun, as in: "The author of this post is..."', 'jetpack' ); ?></option>
- <option value="tag" <?php selected( "tag", $rule['major'] ); ?>><?php echo esc_html_x( 'Tag', 'Noun, as in: "This post has one tag."', 'jetpack' ); ?></option>
- <option value="date" <?php selected( "date", $rule['major'] ); ?>><?php echo esc_html_x( 'Date', 'Noun, as in: "This page is a date archive."', 'jetpack' ); ?></option>
- <option value="page" <?php selected( "page", $rule['major'] ); ?>><?php echo esc_html_x( 'Page', 'Example: The user is looking at a page, not a post.', 'jetpack' ); ?></option>
- <option value="taxonomy" <?php selected( "taxonomy", $rule['major'] ); ?>><?php echo esc_html_x( 'Taxonomy', 'Noun, as in: "This post has one taxonomy."', 'jetpack' ); ?></option>
+ <?php foreach ( $major_conditions as $major_condition_key => $major_condition_meta ) { ?>
+ <option value="<?php echo esc_attr( $major_condition_key ); ?>" <?php selected( $major_condition_key, $rule['major'] ); ?>><?php echo esc_html( $major_condition_meta['title'] ); ?></option>
+ <?php } ?>
</select>
<?php _ex( 'is', 'Widget Visibility: {Rule Major [Page]} is {Rule Minor [Search results]}', 'jetpack' ); ?>
<select class="conditions-rule-minor" name="conditions[rules_minor][]" <?php if ( ! $rule['major'] ) { ?> disabled="disabled"<?php } ?> data-loading-text="<?php esc_attr_e( 'Loading...', 'jetpack' ); ?>">
@@ -322,107 +499,16 @@ class Jetpack_Widget_Conditions {
$condition_result = false;
- foreach ( $instance['conditions']['rules'] as $rule ) {
- switch ( $rule['major'] ) {
- case 'date':
- switch ( $rule['minor'] ) {
- case '':
- $condition_result = is_date();
- break;
- case 'month':
- $condition_result = is_month();
- break;
- case 'day':
- $condition_result = is_day();
- break;
- case 'year':
- $condition_result = is_year();
- break;
- }
- break;
- case 'page':
- // Previously hardcoded post type options.
- if ( 'post' == $rule['minor'] )
- $rule['minor'] = 'post_type-post';
- else if ( ! $rule['minor'] )
- $rule['minor'] = 'post_type-page';
-
- switch ( $rule['minor'] ) {
- case '404':
- $condition_result = is_404();
- break;
- case 'search':
- $condition_result = is_search();
- break;
- case 'archive':
- $condition_result = is_archive();
- break;
- case 'posts':
- $condition_result = $wp_query->is_posts_page;
- break;
- case 'home':
- $condition_result = is_home();
- break;
- case 'front':
- if ( current_theme_supports( 'infinite-scroll' ) )
- $condition_result = is_front_page();
- else {
- $condition_result = is_front_page() && !is_paged();
- }
- break;
- default:
- if ( substr( $rule['minor'], 0, 10 ) == 'post_type-' )
- $condition_result = is_singular( substr( $rule['minor'], 10 ) );
- else {
- // $rule['minor'] is a page ID -- check if we're either looking at that particular page itself OR looking at the posts page, with the correct conditions
-
- $condition_result = ( is_page( $rule['minor'] ) || ( get_option( 'show_on_front' ) == 'page' && $wp_query->is_posts_page && get_option( 'page_for_posts' ) == $rule['minor'] ) );
- }
- break;
- }
- break;
- case 'tag':
- if ( ! $rule['minor'] && is_tag() )
- $condition_result = true;
- else if ( is_singular() && $rule['minor'] && has_tag( $rule['minor'] ) )
- $condition_result = true;
- else {
- $tag = get_tag( $rule['minor'] );
+ $major_conditions = apply_filters( 'widget_visibility_major_conditions', array() );
- if ( $tag && is_tag( $tag->slug ) )
- $condition_result = true;
- }
- break;
- case 'category':
- if ( ! $rule['minor'] && is_category() )
- $condition_result = true;
- else if ( is_category( $rule['minor'] ) )
- $condition_result = true;
- else if ( is_singular() && $rule['minor'] && in_array( 'category', get_post_taxonomies() ) && has_category( $rule['minor'] ) )
- $condition_result = true;
- break;
- case 'author':
- if ( ! $rule['minor'] && is_author() )
- $condition_result = true;
- else if ( $rule['minor'] && is_author( $rule['minor'] ) )
- $condition_result = true;
- else if ( is_singular() && $rule['minor'] && $rule['minor'] == $post->post_author )
- $condition_result = true;
- break;
- case 'taxonomy':
- $term = explode( '_tax_', $rule['minor'] ); // $term[0] = taxonomy name; $term[1] = term id
- $terms = get_the_terms( $post->ID, $rule['minor'] ); // Does post have terms in taxonomy?
- if ( is_tax( $term[0], $term[1] ) )
- $condition_result = true;
- else if ( is_singular() && $term[1] && has_term( $term[1], $term[0] ) )
- $condition_result = true;
- else if ( is_singular() && $terms & !is_wp_error( $terms ) )
- $condition_result = true;
- break;
+ foreach ( $instance['conditions']['rules'] as $rule ) {
+ if ( isset( $major_conditions[ $rule['major'] ] ) ) {
+ $condition_result = call_user_func( $major_conditions[ $rule['major'] ]['callback'], $rule['major'], $rule['minor'] );
}
- if ( $condition_result )
+ if ( $condition_result ) {
break;
+ }
}
if ( ( 'show' == $instance['conditions']['action'] && ! $condition_result ) || ( 'hide' == $instance['conditions']['action'] && $condition_result ) )
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment