wp_post = get_post($team_id); $this->members = array_map('get_userdata', array_unique(get_post_meta($this->wp_post->ID, '_team_members'))); $this->invitees = array_unique(get_post_meta($this->wp_post->ID, '_invitees')); $this->author = get_userdata($this->wp_post->post_author); } /** * Gets team member IDs by state. * * For the "invited" state, an ID is an email address. * * @param array $states Defaults to `array('confirmed', 'unconfirmed', 'invited')`. * * @return array[]|WP_Error 2D array of state => IDs */ public function get_members_in_states ($states = array()) { $defaults = array('confirmed', 'unconfirmed', 'invited'); $states = wp_parse_args($states, $defaults); $ret = array(); foreach ($states as $state) { switch ($state) { case 'confirmed': case 'unconfirmed': case 'invited': $func = "get_{$state}_members"; $ret[$state] = $this->$func(); break; default: return new WP_Error( 'no-such-state', __('Invalid state for membership.', 'buoy'), $state ); break; } } return $ret; } /** * Checks whether or not this team is one of user's default teams. * * @return bool */ public function is_default () { return (bool) get_post_meta($this->wp_post->ID, self::$prefix.'_default_team', true); } /** * Makes this team part a default team of the author. * * @return WP_Buoy_Team */ public function set_default () { update_post_meta($this->wp_post->ID, self::$prefix.'_default_team', true); return $this; } /** * Removes this team from the list of default teams. * * Refuses to remove the team from the list of default teams if * the team's author does not have any other default teams. This * ensures that a user always has at least one default team. * * @return WP_Buoy_Team */ public function unset_default () { $user = new WP_Buoy_User($this->author->ID); if (1 < count($user->get_default_teams())) { delete_post_meta($this->wp_post->ID, self::$prefix.'_default_team'); } return $this; } /** * Gets the Team's owner. * * @return WP_Buoy_User */ public function get_team_owner () { return new WP_Buoy_User($this->author->ID); } /** * Gets a list of all the user IDs associated with this team. * * This does not do any checking about whether the given user ID * is "confirmed" or not. * * @return string[] IDs are actually returned as string values. */ public function get_member_ids () { return array_unique(get_post_meta($this->wp_post->ID, '_team_members')); } /** * Gets a list of all email addresses invited to join this team. * * @return string[] */ public function get_invited_members () { return array_unique(get_post_meta($this->wp_post->ID, '_invitees')); } /** * Checks whether or not the given user ID is on the team. * * This does not check whether the user is confirmed or not, only * whether the user has been at least invited to be a member of a * team. * * @uses WP_Buoy_Team::get_member_ids() * * @param int $user_id * * @return bool */ public function is_member ($user_id) { return in_array($user_id, $this->get_member_ids()); } /** * Adds an invitation for this email address to this team. * * @param string $email */ public function invite_user ($email) { add_post_meta($this->wp_post->ID, '_invitees', $email, false); /** * Fires when a user is added or invited to a team. * * @param int|string $added A user ID or the email address of the new user. * @param WP_Buoy_Team $this */ do_action(self::$prefix . '_team_member_added', $email, $this); } /** * Adds a user to this team (a new member). * * @uses add_post_meta() * @uses do_action() * * @param int $user_id * @param bool $notify Whether or not to trigger a notification when adding. * * @return WP_Buoy_Team */ public function add_member ($user_id, $notify = true) { add_post_meta($this->wp_post->ID, '_team_members', $user_id, false); $this->members[] = get_userdata($user_id); do_action(self::$prefix . '_team_member_added', $user_id, $this, $notify); return $this; } /** * Removes a member from this team. * * @uses delete_post_meta() * @uses do_action() * * @param int $user_id * * @return WP_Buoy_Team */ public function remove_member ($user_id) { delete_post_meta($this->wp_post->ID, '_team_members', $user_id); delete_post_meta($this->wp_post->ID, '_invitees', $user_id); /** * Fires when a user is removed from a team. * * @param int $user_id * @param WP_Buoy_Team $this */ do_action(self::$prefix . '_team_member_removed', $user_id, $this); return $this; } /** * Sets the confirmation flag for a user on this team. * * @uses add_post_meta() * * @param int $user_id * * @return WP_Buoy_Team */ public function confirm_member ($user_id) { add_post_meta($this->wp_post->ID, "_member_{$user_id}_is_confirmed", true, true); return $this; } /** * Unsets the confirmation flag for a user on this team. * * @uses delete_post_meta() * * @param int $user_id * * @return WP_Buoy_Team */ public function unconfirm_member ($user_id) { delete_post_meta($this->wp_post->ID, "_member_{$user_id}_is_confirmed"); return $this; } /** * Checks whether or not a user is "confirmed" to be on the team. * * "Confirmation" consists of a flag in the team post's metadata. * * @uses get_post_meta() * * @param int $user_id * * @return bool */ public function is_confirmed ($user_id) { return get_post_meta($this->wp_post->ID, "_member_{$user_id}_is_confirmed", true); } /** * Checks to ensure there is at least one confirmed member on the * team. * * A "responder" in this context is a confirmed team member. * * @uses WP_Buoy_Team::is_confirmed() * * @return bool */ public function has_responder () { foreach ($this->members as $member) { if ($this->is_confirmed($member->ID)) { return true; } } return false; } /** * Gets the confirmed members of this team. * * @uses WP_Buoy_Team::get_member_ids() * @uses WP_Buoy_Team::is_confirmed() * * @return int[] */ public function get_confirmed_members () { $responders = array(); foreach ($this->get_member_ids() as $id) { if ($this->is_confirmed($id)) { $responders[] = $id; } } return $responders; } /** * Gets the unconfirmed members of this team. * * @uses WP_Buoy_Team::get_member_ids() * @uses WP_Buoy_Team::is_confirmed() * * @return int[] */ public function get_unconfirmed_members () { $responders = array(); foreach ($this->get_member_ids() as $id) { if (!$this->is_confirmed($id)) { $responders[] = $id; } } return $responders; } /** * @return void */ public static function register () { if (!class_exists('Buoy_Team_Membership_List_Table')) { require plugin_dir_path(__FILE__) . 'class-buoy-team-membership-list-table.php'; } if (!class_exists('WP_Posts_List_Table')) { require_once ABSPATH . 'wp-admin/includes/class-wp-posts-list-table.php'; } $post_type = self::$prefix . '_team'; register_post_type($post_type, array( 'labels' => array( 'name' => __('Crisis Response Teams', 'buoy'), 'singular_name' => __('Crisis Response Team', 'buoy'), 'add_new_item' => __('Add New Team', 'buoy'), 'edit_item' => __('Edit Team', 'buoy'), 'new_item' => __('New Team', 'buoy'), 'view_item' => __('View Team', 'buoy'), 'search_items' => __('Search Teams', 'Buoy'), 'not_found' => __('No teams found', 'Buoy'), 'not_found_in_trash' => __('No teams found in Trash', 'buoy'), 'all_items' => __('All Teams', 'buoy'), 'menu_name' => __('My Teams', 'buoy') ), 'description' => __('Groups of crisis responders', 'buoy'), 'public' => false, 'show_ui' => true, 'capability_type' => $post_type, 'map_meta_cap' => true, 'hierarchical' => false, 'supports' => array( 'title', 'author' ), 'register_meta_box_cb' => array(__CLASS__, 'registerMetaBoxes'), 'has_archive' => false, 'rewrite' => false, 'can_export' => false, 'menu_icon' => 'dashicons-sos', )); add_action('load-post.php', array('WP_Buoy_Plugin', 'addHelpTab')); add_action('load-post-new.php', array('WP_Buoy_Plugin', 'addHelpTab')); add_action('load-edit.php', array('WP_Buoy_Plugin', 'addHelpTab')); add_filter('enter_title_here', array(__CLASS__, 'filterTitlePlaceholder'), 10, 2); // TODO: This should probably be moved so it loads only where needed. if (is_admin()) { wp_enqueue_style( __CLASS__ . '-style', plugins_url('../css/admin-teams.css', __FILE__) ); } add_action('current_screen', array(__CLASS__, 'processTeamTableActions')); add_action('admin_notices', array(__CLASS__, 'renderAdminNotices')); add_action('admin_menu', array(__CLASS__, 'registerAdminMenu')); add_action('pre_get_posts', array(__CLASS__, 'filterTeamPostsList')); add_action('post_updated', array(__CLASS__, 'postUpdated'), 10, 3); add_action("save_post_{$post_type}", array(__CLASS__, 'saveTeam'), 10, 2); add_action('deleted_post_meta', array(__CLASS__, 'deletedPostMeta'), 10, 4); add_action("{$post_type}_member_removed", array(__CLASS__, 'checkMemberCount'), 10, 2); add_filter('user_has_cap', array(__CLASS__, 'filterCaps')); add_filter("manage_{$post_type}_posts_columns", array(__CLASS__, 'filterTeamPostsColumns')); add_filter("manage_edit-{$post_type}_sortable_columns", array(__CLASS__, 'filterSortableColumns')); add_action('wp', array(__CLASS__, 'orderTeamPosts')); add_action("manage_{$post_type}_posts_custom_column", array(__CLASS__, 'renderTeamPostsColumn'), 10, 2); add_action('user_register', array(__CLASS__, 'checkInvitations')); add_action('user_register', array(__CLASS__, 'createTeamTemplates')); } /** * @param WP_Post $post * * @return void */ public static function registerMetaBoxes ($post) { $team = new self($post->ID); add_meta_box( 'add-team-member', esc_html__('Add new member', 'buoy'), array(__CLASS__, 'renderAddTeamMemberMetaBox'), null, 'normal', 'high' ); add_meta_box( 'current-team', sprintf( esc_html__('Current team members %s', 'buoy'), '(' . count($team->get_confirmed_members()) . ')' ), array(__CLASS__, 'renderCurrentTeamMetaBox'), null, 'normal', 'high' ); add_meta_box( 'default-team', sprintf( esc_html__('Default Team? (%s)', 'buoy'), ($team->is_default()) ? esc_html__('Yes', 'buoy') : esc_html__('No', 'buoy') ), array(__CLASS__, 'renderDefaultTeamMetaBox'), null, 'side', 'low' ); add_meta_box( 'sms-bridge', esc_html__('SMS/txt Messages', 'buoy'), array(__CLASS__, 'renderTxtMessagesMetaBox') ); } /** * @param WP_Post $post * * @return void */ public static function renderAddTeamMemberMetaBox ($post) { wp_nonce_field(self::$prefix . '_add_team_member', self::$prefix . '_add_team_member_nonce'); require plugin_dir_path(dirname(__FILE__)).'pages/add-team-member-meta-box.php'; } /** * @param WP_Post $post * * @return void */ public static function renderCurrentTeamMetaBox ($post) { wp_nonce_field(self::$prefix . '_choose_team', self::$prefix . '_choose_team_nonce'); require plugin_dir_path(dirname(__FILE__)).'pages/current-team-meta-box.php'; } /** * Displays the "default team" meta box. * * @param WP_Post $post * * @return void */ public static function renderDefaultTeamMetaBox ($post) { $team = new WP_Buoy_Team($post->ID); $html = 'is_default(), true, false); $html .= ' />'; $html .= esc_html__('Include as default team?', 'buoy'); $html .= '

'; if ($team->is_default()) { $html .= esc_html__('This team is one of your default teams.', 'buoy') .' ' .esc_html__('Uncheck the box to remove this team from your list of default teams.', 'buoy'); } else { $html .= esc_html__('This team is not one of your default teams.', 'buoy') .' ' .esc_html__('Check the box to add this team to your list of default teams.', 'buoy'); } $html .= '

'; print ""; } /** * Displays the "SMS/txt Messages" meta box. * * @param WP_Post $post * * @return void */ public static function renderTxtMessagesMetaBox ($post) { $user = new WP_Buoy_User($post->post_author); if ($user->get_phone_number()) { require_once dirname(__FILE__).'/../pages/meta-box-sms-messages.php'; } else { esc_html_e('You must set a phone number in your profile to use txt messages.', 'buoy'); } } /** * @return void */ public static function renderTeamMembershipPage () { $post_type = self::$prefix . '_team'; $team_table = new Buoy_Team_Membership_List_Table($post_type); $team_table->prepare_items(); print '
'; print ''; print '

' . esc_html__('Team membership', 'buoy') . '

'; $team_table->display(); print ''; print '
'; } /** * Sets team parameters based on actions taken in Team admin UI. * * @link https://developer.wordpress.org/reference/hooks/current_screen/ * * @global $_POST * @global $_GET * * @uses WP_Screen::$post_type * @uses WP_Posts_List_Table::current_action() * @uses WP_Buoy_User_Settings::set() * @uses WP_Buoy_User_Settings::save() * @uses Buoy_Team_Membership_List_Table::current_action() * @uses wp_verify_nonce() * @uses WP_Buoy_Team::remove_member() * @uses WP_Buoy_Team::confirm_member() * * @param WP_Screen $current_screen * * @return void */ public static function processTeamTableActions ($current_screen) { $post_type = self::$prefix . '_team'; if ($post_type !== $current_screen->post_type) { return; } if ('post' === $current_screen->base) { // The "My Teams" page. $table = new WP_Posts_List_Table(); $action = $table->current_action(); if ('set_default' === $action || 'unset_default' === $action) { $team = new WP_Buoy_Team(absint($_GET['post'])); $team->$action(); $msg = self::$prefix . '-default-team-updated'; wp_safe_redirect(admin_url( "edit.php?post_type={$current_screen->post_type}&msg=$msg" )); exit(); } } else if ("{$post_type}_page_{$post_type}_membership") { // The "Team Membership" page. $table = new Buoy_Team_Membership_List_Table($post_type); $teams = array(); if (isset($_GET['_wpnonce']) && wp_verify_nonce($_GET['_wpnonce'], 'single-' . $table->_args['plural'])) { $teams[] = $_GET['team_id']; } else if (isset($_POST['_wpnonce']) && wp_verify_nonce($_POST['_wpnonce'], 'bulk-' . $table->_args['plural'])) { $teams = array_merge($teams, $_POST['teams']); } if (!empty($teams)) { foreach ($teams as $team_id) { $team = new self($team_id); if ('leave' === $table->current_action()) { $team->remove_member(get_current_user_id()); } if ('join' === $table->current_action()) { $team->confirm_member(get_current_user_id()); } } wp_safe_redirect(admin_url( 'edit.php?page=' . urlencode($_GET['page']) . '&post_type=' . urlencode($_GET['post_type']) )); exit(); } } } /** * Prints an admin notice for the given message code. * * @global $_GET['msg'] * * @return void */ public static function renderAdminNotices () { if (isset($_GET['msg'])) { $notices = array( // message-code => array('class' => 'css-class', 'message' => "Message text.") self::$prefix . '-default-team-updated' => array( 'class' => 'notice updated is-dismissible', 'message' => esc_html__('Default team updated.', 'buoy') ) ); if (array_key_exists($_GET['msg'], $notices)) { ?>

post_type) { return; } $buoy_user = new WP_Buoy_User($post_before->post_author); // Prevent the user from trashing their last responder team. if ('publish' === $post_before->post_status && 'publish' !== $post_after->post_status) { if (!$buoy_user->has_responder()) { wp_update_post(array( 'ID' => $post_id, 'post_status' => 'publish' )); } } // Re-set the default team if the default team is trashed. $team = new WP_Buoy_Team($post_id); if ('trash' === $post_after->post_status && $team->is_default()) { $teams = $buoy_user->get_teams(); $next_team = new WP_Buoy_Team(array_pop($teams)); $next_team->set_default(); } } /** * Updates the team metadata (mostly membership list). * * This is called by WordPress's `save_post_{$post->post_type}` hook. * * @link https://developer.wordpress.org/reference/hooks/save_post_post-post_type/ * * @global $_POST * * @uses wp_verify_nonce() * @uses WP_Buoy_Team::remove_member() * @uses WP_Buoy_Team::get_member_ids() * @uses WP_Buoy_Team::add_member() * @uses WP_Buoy_Team::set_default() * @uses WP_Buoy_Team::unset_default() * * @param int $post_id * @param WP_Post $post * * @return void */ public static function saveTeam ($post_id, $post) { $team = new self($post_id); // Remove any team members indicated. if (isset($_POST[self::$prefix . '_choose_team_nonce']) && wp_verify_nonce($_POST[self::$prefix . '_choose_team_nonce'], self::$prefix . '_choose_team')) { if (isset($_POST['remove_team_members'])) { foreach ($_POST['remove_team_members'] as $id) { $team->remove_member($id); } } } // Add a new team member if (isset($_POST[self::$prefix . '_add_team_member_nonce']) && wp_verify_nonce($_POST[self::$prefix . '_add_team_member_nonce'], self::$prefix . '_add_team_member')) { $add_team_member_input = $_POST[self::$prefix . '_add_team_member']; $user_id = username_exists($add_team_member_input); if (false !== $user_id) { if (!in_array($user_id, $team->get_member_ids())) { $team->add_member($user_id); } } else { if (is_email($add_team_member_input)) { $email = $add_team_member_input; $user = get_user_by('email', $email); if ($user) { $team->add_member($user->ID); } else { $team->invite_user($email); } } } } // Set default status if (!empty($_POST[self::$prefix.'_default_team'])) { $team->set_default(); } else { $team->unset_default(); } // If this is the user's only team, make this the default one. $cnt = count(get_posts(array( 'post_type' => $post->post_type, 'author' => $post->post_author, 'fields' => 'ids' ))); if (0 === $cnt) { $team->set_default(); } // If we're enabling the SMS/email bridge, save that data. if (!empty($_POST['sms_email_bridge_enabled'])) { update_post_meta($post_id, 'sms_email_bridge_enabled', true); // and schedule a check WP_Buoy_SMS_Email_Bridge::scheduleNext($post_id, 0); } else { update_post_meta($post_id, 'sms_email_bridge_enabled', false); // and unschedule the next check WP_Buoy_SMS_Email_Bridge::unscheduleNext($post_id); } if (!empty($_POST['sms_email_bridge_address'])) { update_post_meta($post_id, 'sms_email_bridge_address', sanitize_email($_POST['sms_email_bridge_address'])); } if (!empty($_POST['sms_email_bridge_username'])) { update_post_meta($post_id, 'sms_email_bridge_username', sanitize_text_field($_POST['sms_email_bridge_username'])); } if (!empty($_POST['sms_email_bridge_password'])) { update_post_meta($post_id, 'sms_email_bridge_password', $_POST['sms_email_bridge_password']); } if (!empty($_POST['sms_email_bridge_server'])) { update_post_meta($post_id, 'sms_email_bridge_server', sanitize_text_field($_POST['sms_email_bridge_server'])); } if (empty($_POST['sms_email_bridge_port']) || 0 === absint($_POST['sms_email_bridge_port'])) { delete_post_meta($post_id, 'sms_email_bridge_port'); } else { update_post_meta($post_id, 'sms_email_bridge_port', absint($_POST['sms_email_bridge_port'])); } if (empty($_POST['sms_email_bridge_connection_security'])) { delete_post_meta($post_id, 'sms_email_bridge_connection_security'); } else { switch ($_POST['sms_email_bridge_connection_security']) { case 'tlsv1': case 'tls': case 'ssl': case 'sslv3': case 'sslv2': case 'none': update_post_meta( $post_id, 'sms_email_bridge_connection_security', $_POST['sms_email_bridge_connection_security'] ); break; default: update_post_meta($post_id, 'sms_email_bridge_connection_security', 'tlsv1'); break; } } } /** * Hooks the `deleted_post_meta` action. * * This is used primarily to detect when a user is removed from a * team and, when this occurrs, remove the confirmation flag, too. * * @link https://developer.wordpress.org/reference/hooks/deleted_meta_type_meta/ * * @param array $meta_ids * @param int $post_id * @param string $meta_key * @param mixed $meta_value * * @return void */ public static function deletedPostMeta ($meta_ids, $post_id, $meta_key, $meta_value) { $team = new self($post_id); if ('_team_members' === $meta_key) { // delete confirmation when removing a team member $team->unconfirm_member($meta_value); } } /** * Checks if a team no longer has any members. * * If a team is emptied for any reason, whether because the user * has removed all their members or the members themselves decide * to leave, this will fire a "{$post->post_type}_emptied" hook. * * @param int $user_id The user who was just removed. * @param WP_Buoy_Team The team they left. */ public static function checkMemberCount ($user_id, $team) { $ids = $team->get_member_ids(); if (empty($ids)) { /** * Fires after the last member of a team is removed (or leaves). * * @param WP_Buoy_Team $team */ do_action($team->wp_post->post_type . '_emptied', $team); } } /** * @return void */ public static function registerAdminMenu () { $hooks = array(); $hooks[] = add_submenu_page( 'edit.php?post_type=' . self::$prefix . '_team', __('Team membership', 'buoy'), __('Team membership', 'buoy'), 'read', self::$prefix . '_team_membership', array(__CLASS__, 'renderTeamMembershipPage') ); foreach ($hooks as $hook) { add_action('load-' . $hook, array('WP_Buoy_Plugin', 'addHelpTab')); } } /** * Dynamically configures user capabilities. * This dynamism prevents the need to write capabilities into the * database's `options` table's `wp_user_roles` record itself. * * Currently simply unconditionally gives every user the required * capabilities to manage their own crisis response teams. * * Called by the `user_has_cap` filter. * * @link https://developer.wordpress.org/reference/hooks/user_has_cap/ * * @param array $caps The user's actual capabilities. * * @return array $caps */ public static function filterCaps ($caps) { $caps['edit_' . self::$prefix . '_teams'] = true; $caps['delete_' . self::$prefix . '_teams'] = true; $caps['publish_' . self::$prefix . '_teams'] = true; $caps['edit_published_' . self::$prefix . '_teams'] = true; $caps['delete_published_' . self::$prefix . '_teams'] = true; return $caps; } /** * Sets the placeholder text for the "New Team" page. * * @link https://developer.wordpress.org/reference/hooks/enter_title_here/ * * @param string $text * @param WP_Post $post * * @return string */ public static function filterTitlePlaceholder ($text, $post) { if (self::$prefix . '_team' === $post->post_type) { $text = __('Enter team name here', 'buoy'); } return $text; } /** * Add custom columns shown in the "My Teams" admin UI. * * @link https://developer.wordpress.org/reference/hooks/manage_post_type_posts_columns/ * * @param array $post_columns * * @return array */ public static function filterTeamPostsColumns ($post_columns) { unset($post_columns['author']); $post_columns['num_members'] = __('Members', 'buoy'); $post_columns['confirmed_members'] = __('Confirmed Members', 'buoy'); $post_columns['default_team'] = __('Default Team?', 'buoy'); return $post_columns; } /** * Makes the custom columns sortable in the "My Teams" admin UI. * * @link https://developer.wordpress.org/reference/hooks/manage_this-screen-id_sortable_columns/ * * @param array $sortable_columns * * @return array */ public static function filterSortableColumns ($sortable_columns) { $sortable_columns['num_members'] = self::$prefix . '_team_member_count'; $sortable_columns['confirmed_members'] = self::$prefix . '_team_confirmed_members'; return $sortable_columns; } /** * Re-orders the query results based on the team member count. * * This changes the global `$wp_query->posts` array directly. * * @todo Possibly the count should be its own meta field managed by us so this hook is more performant? * * @global $wp_query * * @uses WP_Buoy_Team::get_member_ids() * @uses WP_Buoy_Team::get_confirmed_members() * * @param WP $wp * * @return void */ public static function orderTeamPosts ($wp) { if (is_admin() && isset($wp->query_vars['orderby'])) { if (self::$prefix . '_team_member_count' === $wp->query_vars['orderby']) { $method = 'get_member_ids'; } else if (self::$prefix . '_team_confirmed_members' === $wp->query_vars['orderby']) { $method = 'get_confirmed_members'; } if (isset($method)) { global $wp_query; $member_counts = array(); foreach ($wp_query->posts as $post) { $team = new WP_Buoy_Team($post->ID); $member_counts[count($team->$method())][] = $post; // variable function } ksort($member_counts); if ('desc' === $wp->query_vars['order']) { $member_counts = array_reverse($member_counts); } $sorted = array(); foreach ($member_counts as $counts) { foreach ($counts as $post) { $sorted[] = $post; } } $wp_query->posts = $sorted; } } } /** * Add the column content for custom columns in the "My Teams" UI. * * @link https://developer.wordpress.org/reference/hooks/manage_post-post_type_posts_custom_column/ * * @param string $column_name * @param int $post_id * * @return void */ public static function renderTeamPostsColumn ($column_name, $post_id) { $team = new WP_Buoy_Team($post_id); switch ($column_name) { case 'num_members': print esc_html(count($team->get_member_ids())); break; case 'confirmed_members': print esc_html(count($team->get_confirmed_members())); break; case 'default_team': if ($team->is_default()) { print '' . esc_html__('Yes', 'buoy') . ''; } break; } } /** * Ensures that users can only see their own crisis teams in the * WP admin view when viewing their "My Teams" dashboard page. * * @param WP_Query $query * * @return void */ public static function filterTeamPostsList ($query) { // @ticket 119 if (!function_exists('get_current_screen')) { require_once ABSPATH . 'wp-admin/includes/screen.php'; } if (is_admin() && $screen = get_current_screen()) { if ('edit-' . self::$prefix .'_team' === $screen->id && current_user_can('edit_' . self::$prefix . '_teams')) { $query->set('author', get_current_user_id()); add_filter('views_' . $screen->id, array(__CLASS__, 'filterTeamPostViews')); add_filter('post_row_actions', array(__CLASS__, 'postRowActions'), 10, 2); } } } /** * Removes the views links in the Team posts table. * * @link https://developer.wordpress.org/reference/hooks/views_this-screen-id/ * * @param array $items * * @return array */ public static function filterTeamPostViews ($items) { return array(); // remove all view links } /** * Customizes the post row actions in the "My Teams" admin UI. * * @link https://developer.wordpress.org/reference/hooks/post_row_actions/ * * @uses WP_Buoy_Team::is_default() * @uses WP_Buoy_Team::has_responder() * * @param array $items * @param WP_Post $post * * @return array $items */ public static function postRowActions ($items, $post) { $team = new WP_Buoy_Team($post->ID); if (!$team->is_default() && $team->has_responder() && 'publish' === $post->post_status) { $url = admin_url('post.php?post=' . $post->ID . '&action=set_default'); $items['default'] = '' . __('Add to defaults', 'buoy') . ''; } else if ($team->is_default() && $team->has_responder() && 'publish' === $post->post_status) { $url = admin_url('post.php?post=' . $post->ID . '&action=unset_default'); $items['default'] = '' . __('Remove from defaults', 'buoy') . ''; } unset($items['inline hide-if-no-js']); // the "Quick Edit" link return $items; } /** * Adds a user to teams they were invited to join before they had * created an account. * * @param int $user_id * * @return void */ public static function checkInvitations ($user_id) { $user = get_userdata($user_id); $team_posts = self::getAllTeamPosts(); foreach ($team_posts as $post) { $team = new WP_Buoy_Team($post->ID); if (in_array($user->user_email, $team->get_invited_members())) { $team->remove_member($user->user_email); // removes the invitation $team->add_member($user_id, false); // then adds the user } } } /** * Creates teams for newly-registered users. * * @link https://developer.wordpress.org/reference/hooks/user_register/ * * @param int $user_id * * @return void */ public static function createTeamTemplates ($user_id) { // Create three new "teams" for the new user so that they can // begin editing the members lists and can invite folks ASAP. $new_teams = array( array( 'post_title' => __('Friends', 'buoy') ), array( 'post_title' => __('Family', 'buoy') ), array( 'post_title' => __('Neighbours', 'buoy') ) ); foreach ($new_teams as $new_team) { $new_team['post_author'] = $user_id; $new_team['post_type'] = self::$prefix.'_team'; $new_team['post_status'] = 'private'; wp_insert_post($new_team); } } /** * Gets a list of all team posts. * * @return WP_Post[] */ public static function getAllTeamPosts () { return get_posts(array( 'post_type' => self::$prefix . '_team', 'post_status' => array('publish', 'draft', 'trash'), 'posts_per_page' => -1 )); } }