, Ruben Garcia * @since 1.3.9 */ // Exit if accessed directly if( !defined( 'ABSPATH' ) ) exit; /** * Register [gamipress_earnings] shortcode * * @since 1.3.9 */ function gamipress_register_earnings_shortcode() { gamipress_register_shortcode( 'gamipress_earnings', array( 'name' => __( 'User Earnings', 'gamipress' ), 'description' => __( 'Display a list of user earnings.', 'gamipress' ), 'group' => 'gamipress', 'output_callback' => 'gamipress_earnings_shortcode', 'tabs' => array( 'general' => array( 'icon' => 'dashicons-admin-generic', 'title' => __( 'General', 'gamipress' ), 'fields' => array( 'current_user', 'user_id', 'force_responsive', 'limit', 'pagination', 'order', 'include', 'exclude', ), ), 'points' => array( 'icon' => 'dashicons-star-filled', 'title' => __( 'Points', 'gamipress' ), 'fields' => array( 'points', 'points_types', 'awards', 'deducts' ), ), 'achievements' => array( 'icon' => 'dashicons-awards', 'title' => __( 'Achievements', 'gamipress' ), 'fields' => array( 'achievements', 'achievement_types', 'steps', 'achievements_without_points', ), ), 'ranks' => array( 'icon' => 'dashicons-rank', 'title' => __( 'Ranks', 'gamipress' ), 'fields' => array( 'ranks', 'rank_types', 'rank_requirements', ), ), ), 'fields' => array( 'current_user' => array( 'name' => __( 'Current User', 'gamipress' ), 'tooltip' => __( 'Show only earned items of the current logged in user.', 'gamipress' ), 'label_cb' => 'cmb_tooltip_label_cb', 'type' => 'checkbox', 'classes' => 'gamipress-switch', 'default' => 'yes', ), 'user_id' => array( 'name' => __( 'User', 'gamipress' ), 'tooltip' => __( 'Show only earned items by a specific user. Leave blank to show earned items of all users.', 'gamipress' ), 'label_cb' => 'cmb_tooltip_label_cb', 'type' => 'select', 'default' => '', 'options_cb' => 'gamipress_options_cb_users' ), 'force_responsive' => array( 'name' => __( 'Force Responsive', 'gamipress' ), 'tooltip' => __( 'Force to display the earnings table with the responsive style.', 'gamipress' ), 'label_cb' => 'cmb_tooltip_label_cb', 'type' => 'checkbox', 'classes' => 'gamipress-switch', ), 'limit' => array( 'name' => __( 'Limit', 'gamipress' ), 'tooltip' => __( 'Number of items to display.', 'gamipress' ), 'label_cb' => 'cmb_tooltip_label_cb', 'type' => 'text', 'default' => 10, ), 'pagination' => array( 'name' => __( 'Enable Pagination', 'gamipress' ), 'tooltip' => __( 'Show pagination links to navigate through all earned items.', 'gamipress' ), 'label_cb' => 'cmb_tooltip_label_cb', 'type' => 'checkbox', 'classes' => 'gamipress-switch', 'default' => 'yes', ), 'order' => array( 'name' => __( 'Order', 'gamipress' ), 'tooltip' => __( 'Sort order.', 'gamipress' ), 'label_cb' => 'cmb_tooltip_label_cb', 'type' => 'select', 'options' => array( 'DESC' => __( 'Newest', 'gamipress' ), 'ASC' => __( 'Older', 'gamipress' ) ), 'default' => 'DESC', ), 'include' => array( 'name' => __( 'Include', 'gamipress' ), 'tooltip' => __( 'Comma-separated list of specific earnings IDs to include.', 'gamipress' ), 'label_cb' => 'cmb_tooltip_label_cb', 'type' => 'text', ), 'exclude' => array( 'name' => __( 'Exclude', 'gamipress' ), 'tooltip' => __( 'Comma-separated list of specific earnings IDs to exclude.', 'gamipress' ), 'label_cb' => 'cmb_tooltip_label_cb', 'type' => 'text', ), // Points types 'points' => array( 'name' => __( 'Show Points', 'gamipress' ), 'tooltip' => __( 'Show points earned and deducted.', 'gamipress' ), 'label_cb' => 'cmb_tooltip_label_cb', 'type' => 'checkbox', 'classes' => 'gamipress-switch', 'default' => 'yes', ), 'points_types' => array( 'name' => __( 'Points Type(s)', 'gamipress' ), 'tooltip' => __( 'Points type(s) to display.', 'gamipress' ), 'label_cb' => 'cmb_tooltip_label_cb', 'shortcode_desc' => __( 'Single or comma-separated list of points type(s) to display.', 'gamipress' ), 'type' => 'advanced_select', 'multiple' => true, 'classes' => 'gamipress-selector', 'attributes' => array( 'data-placeholder' => __( 'Default: All', 'gamipress' ), ), 'options_cb' => 'gamipress_options_cb_points_types', 'default' => 'all', ), 'awards' => array( 'name' => __( 'Show Points Awards', 'gamipress' ), 'tooltip' => __( 'Show points awarded.', 'gamipress' ), 'label_cb' => 'cmb_tooltip_label_cb', 'type' => 'checkbox', 'classes' => 'gamipress-switch', 'default' => 'yes', ), 'deducts' => array( 'name' => __( 'Show Points Deductions', 'gamipress' ), 'tooltip' => __( 'Show points deducted.', 'gamipress' ), 'label_cb' => 'cmb_tooltip_label_cb', 'type' => 'checkbox', 'classes' => 'gamipress-switch', 'default' => 'yes', ), // Achievement types 'achievements' => array( 'name' => __( 'Show Achievements', 'gamipress' ), 'tooltip' => __( 'Show achievements earned.', 'gamipress' ), 'label_cb' => 'cmb_tooltip_label_cb', 'type' => 'checkbox', 'classes' => 'gamipress-switch', 'default' => 'yes', ), 'achievement_types' => array( 'name' => __( 'Achievement Type(s)', 'gamipress' ), 'tooltip' => __( 'Achievements type(s) to display.', 'gamipress' ), 'label_cb' => 'cmb_tooltip_label_cb', 'shortcode_desc' => __( 'Single or comma-separated list of achievements type(s) to display.', 'gamipress' ), 'type' => 'advanced_select', 'multiple' => true, 'classes' => 'gamipress-selector', 'attributes' => array( 'data-placeholder' => __( 'Default: All', 'gamipress' ), ), 'options_cb' => 'gamipress_options_cb_achievement_types', 'default' => 'all', ), 'steps' => array( 'name' => __( 'Show Steps', 'gamipress' ), 'tooltip' => __( 'Show steps completed.', 'gamipress' ), 'label_cb' => 'cmb_tooltip_label_cb', 'type' => 'checkbox', 'classes' => 'gamipress-switch', 'default' => 'yes', ), 'achievements_without_points' => array( 'name' => __( 'Show Achievements Without Points', 'gamipress' ), 'tooltip' => __( 'Show achievements that do not award points.', 'gamipress' ), 'label_cb' => 'cmb_tooltip_label_cb', 'type' => 'checkbox', 'classes' => 'gamipress-switch', 'default' => 'yes', ), // Rank types 'ranks' => array( 'name' => __( 'Show Ranks', 'gamipress' ), 'tooltip' => __( 'Show ranks reached.', 'gamipress' ), 'label_cb' => 'cmb_tooltip_label_cb', 'type' => 'checkbox', 'classes' => 'gamipress-switch', 'default' => 'yes', ), 'rank_types' => array( 'name' => __( 'Rank Type(s)', 'gamipress' ), 'tooltip' => __( 'Ranks type(s) to display.', 'gamipress' ), 'label_cb' => 'cmb_tooltip_label_cb', 'shortcode_desc' => __( 'Single or comma-separated list of ranks type(s) to display.', 'gamipress' ), 'type' => 'advanced_select', 'multiple' => true, 'classes' => 'gamipress-selector', 'attributes' => array( 'data-placeholder' => __( 'Default: All', 'gamipress' ), ), 'options_cb' => 'gamipress_options_cb_rank_types', 'default' => 'all', ), 'rank_requirements' => array( 'name' => __( 'Show Rank Requirements', 'gamipress' ), 'tooltip' => __( 'Show rank requirements completed.', 'gamipress' ), 'label_cb' => 'cmb_tooltip_label_cb', 'type' => 'checkbox', 'classes' => 'gamipress-switch', 'default' => 'yes', ), ), ) ); } add_action( 'init', 'gamipress_register_earnings_shortcode' ); /** * User Earnings Shortcode * * @since 1.3.9 * * @param array $atts Shortcode attributes * @param string $content Shortcode content * * @return string HTML markup */ function gamipress_earnings_shortcode( $atts = array(), $content = '' ) { global $gamipress_template_args; // Initialize GamiPress template args global $gamipress_template_args = array(); $shortcode = 'gamipress_earnings'; $atts = shortcode_atts( gamipress_earnings_shortcode_defaults(), $atts, $shortcode ); gamipress_enqueue_scripts(); // On network wide active installs, we need to switch to main blog mostly for posts permalinks and thumbnails $blog_id = gamipress_switch_to_main_site_if_network_wide_active(); // Force to set current user as user ID if( $atts['current_user'] === 'yes' ) { /** * Filter to override shortcode workflow with not logged in users when current user is set to yes * * @since 1.7.4.2 * * @param bool $empty_if_not_logged_in Final workflow to follow * @param array $atts Shortcode attributes * @param string $content Shortcode content */ $empty_if_not_logged_in = apply_filters( 'gamipress_earnings_shortcode_empty_if_not_logged_in', true, $atts, $content ); // Return if current_user is set to yes and current user is a guest if( get_current_user_id() === 0 && $empty_if_not_logged_in ) return ''; $atts['user_id'] = get_current_user_id(); } // GamiPress template args global $gamipress_template_args = $atts; // Earnings query $gamipress_template_args['query'] = gamipress_earnings_shortcode_query( $atts ); if( ! $gamipress_template_args['query'] ) { return ''; } // Earnings columns $gamipress_template_args['columns'] = array(); if( absint( $atts['user_id'] ) === 0 ) { $gamipress_template_args['columns']['user'] = __( 'User', 'gamipress' ); } $gamipress_template_args['columns']['thumbnail'] = __( 'Thumbnail', 'gamipress' ); $gamipress_template_args['columns']['description'] = __( 'Description', 'gamipress' ); $gamipress_template_args['columns']['date'] = __( 'Date', 'gamipress' ); $gamipress_template_args['columns']['points'] = __( 'Points', 'gamipress' ); // Render the earnings template ob_start(); gamipress_get_template_part( 'earnings' ); $output = ob_get_clean(); // If switched to blog, return back to que current blog if( $blog_id !== get_current_blog_id() && is_multisite() ) { restore_current_blog(); } /** * Filter to override shortcode output * * @since 1.6.5 * * @param string $output Final output * @param array $atts Shortcode attributes * @param string $content Shortcode content */ return apply_filters( 'gamipress_earnings_shortcode_output', $output, $atts, $content ); } /** * User Earnings Shortcode Query * * @since 1.4.9 * * @param array $args Query arguments * * @return CT_Query */ function gamipress_earnings_shortcode_query( $args = array () ) { // Query args $query_args = array( 'orderby' => 'date', 'order' => $args['order'], 'items_per_page' => $args['limit'], 'paged' => max( 1, get_query_var( 'paged' ) ) ); $query_args['post_type'] = array(); $query_args['points_type'] = array(); $query_args['post_type__not_in'] = array(); $query_args['parent_post_type'] = array(); // User if( isset( $args['user_id'] ) && absint( $args['user_id'] ) !== 0 ) { $query_args['user_id'] = $args['user_id']; } // Build $include array if ( ! is_array( $args['include'] ) && ! empty( $args['include'] ) ) { $include = explode( ',', $args['include'] ); } // Build $exclude array if ( ! is_array( $args['exclude'] ) && ! empty( $args['exclude'] ) ) { $exclude = explode( ',', $args['exclude'] ); } // Include certain user earnings if ( isset( $include ) && ! empty( $include ) ) { $query_args[ 'user_earning__in' ] = $include; } // Exclude certain user earnings if ( isset( $exclude ) && ! empty( $exclude ) ) { $query_args[ 'user_earning__not_in' ] = $exclude; } // Points types if( $args['points'] === 'yes' ) { if( $args['points_types'] === 'all') { $query_args['points_type'] = gamipress_get_points_types_slugs(); } else { $point_types = explode( ',', $args['points_types'] ); $query_args['points_type'] = gamipress_sanitize_point_types_slugs_array( $point_types ); } // For custom earnings points to the points type $query_args['post_type'][] = 'points-type'; // Points awards if( $args['awards'] === 'yes' ) { $query_args['post_type'][] = 'points-award'; } else { $query_args['post_type__not_in'][] = 'points-award'; } // Points deducts if( $args['deducts'] === 'yes' ) { $query_args['post_type'][] = 'points-deduct'; } else { $query_args['post_type__not_in'][] = 'points-deduct'; } } else { $query_args['post_type__not_in'][] = 'points-type'; $query_args['post_type__not_in'][] = 'points-award'; $query_args['post_type__not_in'][] = 'points-deduct'; } // Achievement types if( $args['achievements'] === 'yes' ) { if( $args['achievement_types'] === 'all') { $achievement_types = gamipress_get_achievement_types_slugs(); } else { $achievement_types = explode( ',', $args['achievement_types'] ); $achievement_types = gamipress_sanitize_achievement_types_slugs_array( $achievement_types ); } $query_args['post_type'] = array_merge( $query_args['post_type'], $achievement_types ); // Step if( $args['steps'] === 'yes' ) { if( $args['achievement_types'] === 'all') { $query_args['post_type'][] = 'step'; } else { $query_args['parent_post_type'] = array_merge( $query_args['parent_post_type'], $achievement_types ); } } else { $query_args['post_type__not_in'][] = 'step'; } } else { $query_args['post_type__not_in'] = array_merge( $query_args['post_type__not_in'], gamipress_get_achievement_types_slugs() ); $query_args['post_type__not_in'][] = 'step'; } // Rank types if( $args['ranks'] === 'yes' ) { if( $args['rank_types'] === 'all') { $rank_types = gamipress_get_rank_types_slugs(); } else { $rank_types = explode( ',', $args['rank_types'] ); $rank_types = gamipress_sanitize_rank_types_slugs_array( $rank_types ); } $query_args['post_type'] = array_merge( $query_args['post_type'], $rank_types ); // Rank requirements if( $args['rank_requirements'] === 'yes' ) { if( $args['rank_types'] === 'all') { $query_args['post_type'][] = 'rank-requirement'; } else { $query_args['parent_post_type'] = array_merge( $query_args['parent_post_type'], $rank_types ); } } else { $query_args['post_type__not_in'][] = 'rank-requirement'; } } else { $query_args['post_type__not_in'] = array_merge( $query_args['post_type__not_in'], gamipress_get_rank_types_slugs() ); $query_args['post_type__not_in'][] = 'rank-requirement'; } // Remove types that has 'all' value foreach( $query_args['post_type'] as $index => $type ) { if( $type === 'all' ) { unset( $query_args['post_type'][$index] ); } } // Return if not types selected if( empty( $query_args['post_type'] ) ) { return false; } if( ! empty( $query_args['points_type'] ) ) { $query_args['force_types'] = true; } // If looking to show achievements that do not award any points, then need to add the empty points type value and force the post and points types queries if( $args['achievements_without_points'] === 'yes' ) { $query_args['points_type'][] = ''; $query_args['force_types'] = true; } /** * Filters earnings shortcode query args * * @since 2.0.7 * * @param array $query_args Query args to be passed to CT_Query * @param array $args Function received args * * @return array */ $query_args = apply_filters( 'gamipress_earnings_shortcode_query_args', $query_args, $args ); // Setup table $ct_table = ct_setup_table( 'gamipress_user_earnings' ); // Sanitize query args $query_args = gamipress_sanitize_query_args( $query_args, gamipress_user_earnings_query_vars_rules() ); return new CT_Query( $query_args ); } /** * Earnings shortcode defaults attributes values * * @since 7.1.6 * * @return array */ function gamipress_earnings_shortcode_defaults() { return apply_filters( 'gamipress_earnings_shortcode_defaults', array( 'current_user' => 'yes', 'user_id' => '0', 'force_responsive' => '', 'limit' => '10', 'pagination' => 'yes', 'order' => 'DESC', 'include' => '', 'exclude' => '', 'points' => 'yes', 'points_types' => 'all', 'awards' => 'yes', 'deducts' => 'yes', 'achievements' => 'yes', 'achievement_types' => 'all', 'steps' => 'yes', 'achievements_without_points' => 'yes', 'ranks' => 'yes', 'rank_types' => 'all', 'rank_requirements' => 'yes', ) ); } /** * User Earnings query vars rules * * @since 7.8.8 * * @return array */ function gamipress_user_earnings_query_vars_rules() { // Setup table $ct_table = ct_setup_table( 'gamipress_user_earnings' ); $rules = apply_filters( 'gamipress_user_earnings_query_vars_rules', array( // Query fields 'orderby' => array( 'type' => 'string', 'sanitize' => 'text', 'allowed_values' => array_keys( $ct_table->db->schema->fields ), ), 'order' => array( 'type' => 'string', 'sanitize' => 'uppercase', 'allowed_values' => array( 'ASC', 'DESC' ), ), 'items_per_page' => array( 'type' => 'integer', ), 'paged' => array( 'type' => 'integer', ), // Earning fields 'user_id' => array( 'type' => 'integer', ), 'user_earning__in' => array( 'type' => 'array', 'sanitize' => 'integer', ), 'user_earning__not_in' => array( 'type' => 'array', 'sanitize' => 'integer', ), 'post_type' => array( 'type' => 'array', 'sanitize' => 'text', ), 'post_type__not_in' => array( 'type' => 'array', 'sanitize' => 'text', ), 'parent_post_type' => array( 'type' => 'array', 'sanitize' => 'text', ), 'points_type' => array( 'type' => 'array', 'sanitize' => 'text', ), 'force_types' => array( 'type' => 'boolean', ), ) ); ct_reset_setup_table(); return $rules; }