public function test_wp_idea_stream_parse_query() { // Generate a publish idea $idea_id = $this->factory->idea->create(array('author' => 1)); // Create a user $u1 = $this->factory->user->create(); $u2 = $this->factory->user->create(); wp_idea_stream_add_rate($idea_id, $u1, 1); wp_idea_stream_add_rate($idea_id, $u2, 1); $rates = get_post_meta($idea_id, '_ideastream_rates', true); // Get user 1 rates $u1_rated_ideas = wp_idea_stream_ideas_get_ideas(array('per_page' => -1, 'meta_query' => array(array('key' => '_ideastream_rates', 'value' => ';i:' . $u1 . ';', 'compare' => 'LIKE')))); $u1_rated_id = wp_list_pluck($u1_rated_ideas['ideas'], 'ID'); $this->assertTrue($idea_id === (int) reset($u1_rated_id)); // Get user 2 rates $u2_rated_ideas = wp_idea_stream_ideas_get_ideas(array('per_page' => -1, 'meta_query' => array(array('key' => '_ideastream_rates', 'value' => ';i:' . $u2 . ';', 'compare' => 'LIKE')))); $u2_rated_id = wp_list_pluck($u2_rated_ideas['ideas'], 'ID'); $this->assertTrue($idea_id === (int) reset($u2_rated_id)); // Get user 2 rates $author_rated_ideas = wp_idea_stream_ideas_get_ideas(array('per_page' => -1, 'meta_query' => array(array('key' => '_ideastream_rates', 'value' => ';i:1;', 'compare' => 'LIKE')))); // Author did not vote on his idea $author_rated_id = wp_list_pluck($author_rated_ideas['ideas'], 'ID'); $this->assertFalse($idea_id === (int) reset($author_rated_id), 'Only ideas the user rated should be in the query'); }
/** * Process the repair tool * * In case something went wrong with group activities (visibility, component...), * this tool should repair the problematic activities. * * @package WP Idea Stream * @subpackage buddypress/activity * * @since 2.0.0 * * @global $wpdb * @uses bp_is_active() to check if a component is active * @uses wp_list_pluck() to pluck a certain field out of each object in a list. * @uses bp_activity_get() to get all ideastream activities * @uses wp_filter_object_list() to filter a list of objects, based on a set of key => value arguments. * @uses wp_parse_id_list() to sanitize a list of ids * @uses get_post_meta() to get the group id the idea is attached to * @uses groups_get_groups() to get the needed groups * @uses WP_Idea_Stream_Activity::bulk_edit_activity() to update the activities (component/item_id/visibility) * @return array the result of the repair operation. */ public function repair_activities() { global $wpdb; $buddypress = buddypress(); $blog_id = get_current_blog_id(); // Description of this tool, displayed to the user $statement = __('Making sure IdeaStream activities are consistent: %s', 'wp-idea-stream'); // Default to failure text $result = __('No activity needs to be repaired.', 'wp-idea-stream'); // Default to unrepaired $repair = 0; if (!bp_is_active('groups')) { return; } $ideastream_types = wp_list_pluck($this->activity_actions, 'type'); // Get all activities $ideastream_activities = bp_activity_get(array('filter' => array('action' => $ideastream_types), 'show_hidden' => true, 'spam' => 'all', 'per_page' => false)); if (is_array($ideastream_activities['activities'])) { $idea_comments = array(); $idea_posts = array(); $to_repair = array(); $attached_component = array('comment' => array($buddypress->groups->id => array(), $buddypress->blogs->id => array()), 'post' => array($buddypress->groups->id => array(), $buddypress->blogs->id => array())); foreach ($ideastream_activities['activities'] as $activity) { if (false !== strpos($activity->type, 'comment')) { $idea_comments[$activity->id] = $activity->secondary_item_id; $attached_component['comment'][$activity->component][] = $activity->id; } else { $idea_posts[$activity->id] = $activity->secondary_item_id; $attached_component['post'][$activity->component][] = $activity->id; } } // Gets the comment activities to repair if (!empty($idea_comments)) { // I don't think get_comments() allow us to get comments // using a list of comment ids.. $in = implode(',', wp_parse_id_list($idea_comments)); $sql = array('select' => "SELECT c.comment_ID, m.meta_value as group_id", 'from' => "FROM {$wpdb->comments} c LEFT JOIN {$wpdb->postmeta} m", 'on' => "ON (c.comment_post_ID = m.post_id )", 'where' => $wpdb->prepare("WHERE comment_ID IN ({$in}) AND m.meta_key = %s", '_ideastream_group_id')); $idea_comments_check = $wpdb->get_results(join(' ', $sql), OBJECT_K); foreach ($idea_comments as $activity_comment_id => $comment_secondary_id) { if (!empty($idea_comments_check[$comment_secondary_id]) && !in_array($activity_comment_id, $attached_component['comment'][$buddypress->groups->id])) { $to_repair['groups'][$idea_comments_check[$comment_secondary_id]->group_id][] = $activity_comment_id; } else { if (empty($idea_comments_check[$comment_secondary_id]) && in_array($activity_comment_id, $attached_component['comment'][$buddypress->groups->id])) { $to_repair['blogs'][] = $activity_comment_id; } } } } // Gets the idea activities to repair if (!empty($idea_posts)) { add_filter('wp_idea_stream_ideas_get_status', 'wp_idea_stream_ideas_get_all_status', 10, 1); // Get user's ideas posted in the group $idea_posts_check = wp_idea_stream_ideas_get_ideas(array('per_page' => -1, 'include' => $idea_posts, 'meta_query' => array(array('key' => '_ideastream_group_id', 'compare' => 'EXIST')))); $idea_posts_check = wp_list_pluck($idea_posts_check['ideas'], 'ID'); remove_filter('wp_idea_stream_ideas_get_status', 'wp_idea_stream_ideas_get_all_status', 10, 1); foreach ($idea_posts as $activity_post_id => $post_secondary_id) { if (in_array($post_secondary_id, $idea_posts_check) && !in_array($activity_post_id, $attached_component['post'][$buddypress->groups->id])) { $group_id = get_post_meta($post_secondary_id, '_ideastream_group_id', true); if (!empty($group_id)) { $to_repair['groups'][$group_id][] = $activity_post_id; } } else { if (!in_array($post_secondary_id, $idea_posts_check) && in_array($activity_post_id, $attached_component['post'][$buddypress->groups->id])) { $to_repair['blogs'][] = $activity_post_id; } } } } } if (!empty($to_repair['groups'])) { // Get the groups to have their status $groups = groups_get_groups(array('show_hidden' => true, 'populate_extras' => false, 'include' => join(',', array_keys($to_repair['groups'])), 'per_page' => false)); if (!empty($groups['groups'])) { $public_groups = wp_filter_object_list($groups['groups'], array('status' => 'public'), 'and', 'id'); foreach ($to_repair['groups'] as $item_id => $repair_activities) { $hide_sitewide = 0; if (!in_array($item_id, $public_groups)) { $hide_sitewide = 1; } self::bulk_edit_activity($repair_activities, $hide_sitewide, $buddypress->groups->id, $item_id); $repair += count($repair_activities); } } } if (!empty($to_repair['blogs'])) { self::bulk_edit_activity($to_repair['blogs'], 0, $buddypress->blogs->id, $blog_id); $repair += count($to_repair['blogs']); } // Setup success/fail messaging if (!empty($repair)) { $result = sprintf(__('%d repared', 'wp-idea-stream'), $repair); } // All done! return array(0, sprintf($statement, $result)); }
/** * Constructor * * @package WP Idea Stream * @subpackage idea/tags * * @since 2.0.0 * * @param array $args the loop args * @uses get_query_var() * @uses wp_idea_stream_get_idea_var() to get the globalized query loop * @uses wp_idea_stream_ideas_get_idea_by_name() to get the idea object thanks to its post_name * @uses wp_idea_stream_reset_post() to reset the $wp_query->post data * @uses wp_idea_stream_set_idea_var() to globalized the need for a reset postdata * @uses wp_idea_stream_ideas_get_ideas() get all matching ideas * @uses wp_idea_stream_is_pretty_links() do we have a custom permalink structure ? * @uses add_query_arg() to build the url in case default permalink is set * @uses wp_idea_stream_is_idea_archive() to check an idea archive page is being displayed * @uses wp_idea_stream_get_root_url() to get ideas archive url * @uses wp_idea_stream_is_category() to check a category page is being displayed * @uses wp_idea_stream_get_category_url() to get the category url * @uses wp_idea_stream_is_tag() to check a tag page is being displayed * @uses wp_idea_stream_get_tag_url() to get the category url * @uses wp_idea_stream_is_user_profile_rates() to check the rates user's profile page is displayed * @uses wp_idea_stream_users_get_displayed_profile_url() to get user's profile url * @uses wp_idea_stream_is_user_profile_ideas() to check the main user's profile page is displayed * @uses wp_idea_stream_paged_slug() to get the pagination slug * @uses wp_idea_stream_search_rewrite_id() to get the search rewrite id * @uses WP_Idea_Stream_Loop::start() to launch the loop * @uses apply_filters() call 'wp_idea_stream_ideas_pagination_args' to override paginate args */ public function __construct($args = array()) { if (!empty($args) && empty($args['is_widget'])) { $paged = get_query_var('paged'); // Set which pagination page if (!empty($paged)) { $args['page'] = $paged; // Checking query string just in case } else { if (!empty($_GET['paged'])) { $args['page'] = absint($_GET['paged']); // Checking in page args } else { if (!empty($args['page'])) { $args['page'] = absint($args['page']); // Default to first page } else { $args['page'] = 1; } } } } // Only get the idea requested if (!empty($args['idea_name'])) { $query_loop = wp_idea_stream_get_idea_var('query_loop'); if (empty($query_loop->idea)) { $idea = wp_idea_stream_ideas_get_idea_by_name($args['idea_name']); } else { $idea = $query_loop->idea; } // can't do this too ealy $reset_data = array_merge((array) $idea, array('is_page' => true)); wp_idea_stream_reset_post($reset_data); // this needs a "reset postdata"! wp_idea_stream_set_idea_var('needs_reset', true); $ideas = array('ideas' => array($idea), 'total' => 1, 'get_args' => array('page' => 1, 'per_page' => 1)); // Get the ideas } else { $ideas = wp_idea_stream_ideas_get_ideas($args); } if (!empty($ideas['get_args'])) { foreach ($ideas['get_args'] as $key => $value) { $this->{$key} = $value; } } else { return false; } $params = array('plugin_prefix' => 'wp_idea_stream', 'item_name' => 'idea', 'item_name_plural' => 'ideas', 'items' => $ideas['ideas'], 'total_item_count' => $ideas['total'], 'page' => $this->page, 'per_page' => $this->per_page); $paginate_args = array(); // No pretty links if (!wp_idea_stream_is_pretty_links()) { $paginate_args['base'] = add_query_arg('paged', '%#%'); } else { // Is it the main archive page ? if (wp_idea_stream_is_idea_archive()) { $base = trailingslashit(wp_idea_stream_get_root_url()) . '%_%'; // Or the category archive page ? } else { if (wp_idea_stream_is_category()) { $base = trailingslashit(wp_idea_stream_get_category_url()) . '%_%'; // Or the tag archive page ? } else { if (wp_idea_stream_is_tag()) { $base = trailingslashit(wp_idea_stream_get_tag_url()) . '%_%'; // Or the displayed user rated ideas ? } else { if (wp_idea_stream_is_user_profile_rates()) { $base = trailingslashit(wp_idea_stream_users_get_displayed_profile_url('rates')) . '%_%'; // Or the displayed user published ideas ? } else { if (wp_idea_stream_is_user_profile_ideas()) { $base = trailingslashit(wp_idea_stream_users_get_displayed_profile_url()) . '%_%'; // Or nothing i've planed ? } else { /** * Create your own pagination base if not handled by the plugin * * @param string empty string */ $base = apply_filters('wp_idea_stream_ideas_pagination_base', ''); } } } } } $paginate_args['base'] = $base; $paginate_args['format'] = wp_idea_stream_paged_slug() . '/%#%/'; } // Is this a search ? if (wp_idea_stream_get_idea_var('is_search')) { $paginate_args['add_args'] = array(wp_idea_stream_search_rewrite_id() => $_GET[wp_idea_stream_search_rewrite_id()]); } // Do we have a specific order to use ? $orderby = wp_idea_stream_get_idea_var('orderby'); if (!empty($orderby) && 'date' != $orderby) { $merge = array(); if (!empty($paginate_args['add_args'])) { $merge = $paginate_args['add_args']; } $paginate_args['add_args'] = array_merge($merge, array('orderby' => $orderby)); } /** * Use this filter to override the pagination * * @param array $paginate_args the pagination arguments */ parent::start($params, apply_filters('wp_idea_stream_ideas_pagination_args', $paginate_args)); }
/** * Remove ideas of a banned / removed user from group * * @package WP Idea Stream * @subpackage buddypress/groups * * @since 2.0.0 * * @param int $group_id the ID of the group * @param int $user_id the ID of the user * @uses apply_filters() call 'wp_idea_stream_buddypress_group_removed_user_ideas' to force ideas to be kept in group * @uses add_filter() to temporarly include all post stati * @uses wp_idea_stream_ideas_get_ideas() to get user's ideas posted in the group * @uses remove_filter() to remove the filter * @uses bp_loggedin_user_id() to get current user ID * @uses WP_Idea_Stream_Idea()->save to update the idea * @uses wp_idea_stream_user_can() to check for user's capacity * @uses delete_post_meta() to remove the attached group * @uses WP_Idea_Stream_Group::bulk_edit_ideas_status to bulk edit the ideas stati * @uses do_action() call 'wp_idea_stream_buddypress_user_removed_from_group' to perform custom actions */ public function user_removed_from_group($group_id = 0, $user_id = 0) { if (empty($group_id) || empty($user_id)) { return false; } /** * Use this filter if you want to keep the ideas the user posted in the group * even if he was banned / removed from the group or if he left the group. * * @param bool true to remove user's ideas, false otherwise * @param int $group_id the group id the user left/was removed, banned from * @param int $user_id the user id */ $remove_user_ideas = apply_filters('wp_idea_stream_buddypress_group_removed_user_ideas', true, $group_id, $user_id); if (empty($remove_user_ideas)) { return; } add_filter('wp_idea_stream_ideas_get_status', 'wp_idea_stream_ideas_get_all_status', 10, 1); // Get user's ideas posted in the group $user_ideas = wp_idea_stream_ideas_get_ideas(array('per_page' => -1, 'author' => $user_id, 'meta_query' => array(array('key' => '_ideastream_group_id', 'value' => $group_id, 'compare' => '=')))); remove_filter('wp_idea_stream_ideas_get_status', 'wp_idea_stream_ideas_get_all_status', 10, 1); if (empty($user_ideas['ideas'])) { return; } $ideas = array(); $leaving_group = doing_action('groups_leave_group'); // Remove user's ideas from group foreach ($user_ideas['ideas'] as $idea) { if (!empty($leaving_group) && $idea->post_author == bp_loggedin_user_id()) { // Edit each idea's status and reset their group id $edit_idea = new WP_Idea_Stream_Idea($idea->ID); $edit_idea->status = 'publish'; $edit_idea->metas['group_id'] = 0; // Update the idea $edit_idea->save(); // Else prepare remove from group } else { if (wp_idea_stream_user_can('remove_group_ideas')) { delete_post_meta($idea->ID, '_ideastream_group_id'); $ideas[] = $idea->ID; } } } if (!empty($ideas)) { // Bulk edit ideas to reset status to publish self::bulk_edit_ideas_status(array('status' => 'publish', 'ideas' => $ideas)); /** * Use this action to perform custom ones, after the user ideas are removed as the user was banned * or removed from the group * * @param int $user_id the user id * @param array $user_ideas list of WP_Post idea objects * @param int $group_id the group ID */ do_action('wp_idea_stream_buddypress_user_removed_from_group', $user_id, $ideas, $group_id); } }
/** * @group remove_from_group */ public function test_wp_idea_stream_groups_member_remove_public_group() { $bp = buddypress(); // Set current group $bp->groups->current_group = groups_get_group(array('group_id' => $this->group_id, 'populate_extras' => true)); $u = $this->factory->user->create(); groups_join_group($this->group_id, $u); $idea1 = $this->factory->idea->create(array('author' => $u, 'metas' => array('group_id' => $this->group_id))); $idea2 = $this->factory->idea->create(array('author' => $u, 'metas' => array('group_id' => $this->group_id))); $bp->is_item_admin = true; groups_remove_member($u, $this->group_id); // Check metas $this->assertEmpty(wp_idea_stream_ideas_get_meta($idea1, 'group_id')); $this->assertEmpty(wp_idea_stream_ideas_get_meta($idea2, 'group_id')); $ideas = wp_idea_stream_ideas_get_ideas(array('include' => array($idea1, $idea2))); $public_ideas = wp_filter_object_list($ideas['ideas'], array('post_status' => 'publish'), 'and', 'ID'); $this->assertEqualSets(array($idea1, $idea2), $public_ideas, 'When a member is banned from the group, ideas should always be public'); // Reset item admin $bp->is_item_admin = false; }
/** * Hooks to deleted_user to perform additional actions * * When a user is deleted, we need to be sure the ideas he shared are also * deleted to avoid troubles in edit screens as the post author field will found * no user. I also remove rates. * * The main problem here (excepting error notices) is ownership of the idea. To avoid any * troubles, deleting when user leaves seems to be the safest. If you have a different point * of view, you can remove_action( 'deleted_user', 'wp_idea_stream_users_delete_user_data', 10, 1 ) * and use a different way of managing this. I advise you to make sure ideas are reattributed to * an existing user ID. About rates, there's no problem if a non existing user ID is in the rating * list of an idea. * * @package WP Idea Stream * @subpackage users/functions * * @since 2.0.0 * * @uses add_filter() to temporarly include all post status * @uses wp_idea_stream_ideas_get_ideas() to get all user's ideas and rates * @uses remove_filter() to remove the filter * @uses apply_filters() Calls 'wp_idea_stream_users_delete_user_force_delete' to override * @uses do_action() Calls 'wp_idea_stream_users_before_trash_user_data' to perform actions before idea is trashed * Calls 'wp_idea_stream_users_before_delete_user_data' to perform actions before idea is deleted * @uses wp_delete_post() to peramanently delete (forces flag on) these ideas * @uses wp_idea_stream_is_rating_disabled() to check if rating functionality is available * @uses wp_idea_stream_delete_rate() to delete user's rates * @uses do_action() Calls 'wp_idea_stream_delete_user_rates' to perform actions once user is deleted */ function wp_idea_stream_users_delete_user_data($user_id = 0) { if (empty($user_id)) { return; } // Make sure we don't miss any ideas add_filter('wp_idea_stream_ideas_get_status', 'wp_idea_stream_ideas_get_all_status', 10, 1); // Get user's ideas, in case of multisite $user_ideas = wp_idea_stream_ideas_get_ideas(array('per_page' => -1, 'author' => $user_id)); // remove asap remove_filter('wp_idea_stream_ideas_get_status', 'wp_idea_stream_ideas_get_all_status', 10, 1); /** * We're forcing ideas to be deleted definitively * Using this filter you can set it to only be trashed * * Internally use in case user has been spammed (BuddyPress functionnality) * @see buddypress/functions * * @param bool $force_delete true to permanently delete, false to trash */ $force_delete = apply_filters('wp_idea_stream_users_delete_user_force_delete', true); // If any delete them if (!empty($user_ideas['ideas'])) { foreach ($user_ideas['ideas'] as $user_idea) { /** * WordPress is using a check on native post types * so we can't just pass $force_delete to wp_delete_post(). */ if (empty($force_delete)) { /** * @param int ID of the idea being trashed * @param int $user_id the user id */ do_action('wp_idea_stream_users_before_trash_user_data', $user_idea->ID, $user_id); wp_trash_post($user_idea->ID); } else { /** * @param int ID of the idea being trashed * @param int $user_id the user id */ do_action('wp_idea_stream_users_before_delete_user_data', $user_idea->ID, $user_id); wp_delete_post($user_idea->ID, true); } } } // Ratings are on, try to delete them. if (!wp_idea_stream_is_rating_disabled()) { // Make sure we don't miss any ideas add_filter('wp_idea_stream_ideas_get_status', 'wp_idea_stream_ideas_get_all_status', 10, 1); // Get user's rates $rated_ideas = wp_idea_stream_ideas_get_ideas(array('per_page' => -1, 'meta_query' => array(array('key' => '_ideastream_rates', 'value' => ';i:' . $user_id . ';', 'compare' => 'LIKE')))); // remove asap remove_filter('wp_idea_stream_ideas_get_status', 'wp_idea_stream_ideas_get_all_status', 10, 1); // If any delete them. if (!empty($rated_ideas['ideas'])) { foreach ($rated_ideas['ideas'] as $idea) { wp_idea_stream_delete_rate($idea->ID, $user_id); } /** * Internally used in BuddyPress part of the plugin to delete notifications * generated by the deleted user. * @see buddypress/notifications part * * @param int $user_id the user ID */ do_action('wp_idea_stream_delete_user_rates', $user_id); } } /** * @param int $user_id the user ID */ do_action('wp_idea_stream_users_deleted_user_data', $user_id); }