module_url = $this->get_module_url( __FILE__ ); // Register the User Groups module with Edit Flow $args = array( 'title' => __( 'User Groups', 'edit-flow' ), 'short_description' => __( 'Organize your users into groups to mimic your organizational structure.', 'edit-flow' ), 'extended_description' => __( 'Configure user groups to organize all of the users on your site. Each user can be in many user groups and you can change them at any time.', 'edit-flow' ), 'module_url' => $this->module_url, 'img_url' => $this->module_url . 'lib/usergroups_s128.png', 'slug' => 'user-groups', 'default_options' => array( 'enabled' => 'on', 'post_types' => array( 'post' => 'on', 'page' => 'off', ), ), 'messages' => array( 'usergroup-added' => __( "User group created. Feel free to add users to the usergroup.", 'edit-flow' ), 'usergroup-updated' => __( "User group updated.", 'edit-flow' ), 'usergroup-missing' => __( "User group doesn't exist.", 'edit-flow' ), 'usergroup-deleted' => __( "User group deleted.", 'edit-flow' ), ), 'configure_page_cb' => 'print_configure_view', 'configure_link_text' => __( 'Manage User Groups', 'edit-flow' ), 'autoload' => false, 'settings_help_tab' => array( 'id' => 'ef-user-groups-overview', 'title' => __('Overview', 'edit-flow'), 'content' => __('
For those with many people involved in the publishing process, user groups helps you keep them organized.
Currently, user groups are primarily used for subscribing a set of users to a post for notifications.
', 'edit-flow'), ), 'settings_help_sidebar' => __( 'For more information:
', 'edit-flow' ), ); $this->module = EditFlow()->register_module( 'user_groups', $args ); } /** * Module startup */ /** * Initialize the rest of the stuff in the class if the module is active * * @since 0.7 */ function init() { // Register the objects where we'll be storing data and relationships $this->register_usergroup_objects(); $this->manage_usergroups_cap = apply_filters( 'ef_manage_usergroups_cap', $this->manage_usergroups_cap ); // Register our settings add_action( 'admin_init', array( $this, 'register_settings' ) ); // Handle any adding, editing or saving add_action( 'admin_init', array( $this, 'handle_add_usergroup' ) ); add_action( 'admin_init', array( $this, 'handle_edit_usergroup' ) ); add_action( 'admin_init', array( $this, 'handle_delete_usergroup' ) ); add_action( 'wp_ajax_inline_save_usergroup', array( $this, 'handle_ajax_inline_save_usergroup' ) ); // Usergroups can be managed from the User profile view add_action( 'show_user_profile', array( $this, 'user_profile_page' ) ); add_action( 'edit_user_profile', array( $this, 'user_profile_page' ) ); add_action( 'user_profile_update_errors', array( $this, 'user_profile_update' ), 10, 3 ); // Javascript and CSS if we need it add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_admin_scripts' ) ); add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_admin_styles' ) ); } /** * Load the capabilities onto users the first time the module is run * * @since 0.7 */ function install() { // Add necessary capabilities to allow management of user groups $usergroup_roles = array( 'administrator' => array('edit_usergroups'), ); foreach( $usergroup_roles as $role => $caps ) { $this->add_caps_to_role( $role, $caps ); } // Create our default usergroups $default_usergroups = array( array( 'name' => __( 'Copy Editors', 'edit-flow' ), 'description' => __( 'Making sure the quality is top-notch.', 'edit-flow' ), ), array( 'name' => __( 'Photographers', 'edit-flow' ), 'description' => __( 'Capturing the story visually.', 'edit-flow' ), ), array( 'name' => __( 'Reporters', 'edit-flow' ), 'description' => __( 'Out in the field, writing stories.', 'edit-flow' ), ), array( 'name' => __( 'Section Editors', 'edit-flow' ), 'description' => __( 'Providing feedback and direction.', 'edit-flow' ), ), ); foreach( $default_usergroups as $args ) { $this->add_usergroup( $args ); } } /** * Upgrade our data in case we need to * * @since 0.7 */ function upgrade( $previous_version ) { global $edit_flow; // Upgrade path to v0.7 if ( version_compare( $previous_version, '0.7' , '<' ) ) { global $wpdb; // Set all of the user group terms to our new taxonomy $wpdb->update( $wpdb->term_taxonomy, array( 'taxonomy' => self::taxonomy_key ), array( 'taxonomy' => 'following_usergroups' ) ); // Get all of the users who are a part of user groups and assign them to their new user group values $query = "SELECT * FROM $wpdb->usermeta WHERE meta_key='wp_ef_usergroups';"; $usergroup_users = $wpdb->get_results( $query ); // Sort all of the users based on their usergroup(s) $users_to_add = array(); foreach( (array)$usergroup_users as $usergroup_user ) { if ( is_object( $usergroup_user ) ) $users_to_add[$usergroup_user->meta_value][] = (int)$usergroup_user->user_id; } // Add user IDs to each usergroup foreach( $users_to_add as $usergroup_slug => $users_array ) { $usergroup = $this->get_usergroup_by( 'slug', $usergroup_slug ); $this->add_users_to_usergroup( $users_array, $usergroup->term_id ); } // Update the term slugs for each user group $all_usergroups = $this->get_usergroups(); foreach( $all_usergroups as $usergroup ) { $new_slug = str_replace( 'ef_', self::term_prefix, $usergroup->slug ); $this->update_usergroup( $usergroup->term_id, array( 'slug' => $new_slug ) ); } // Delete all of the previous usermeta values $wpdb->query( "DELETE FROM $wpdb->usermeta WHERE meta_key='wp_ef_usergroups';" ); // Technically we've run this code before so we don't want to auto-install new data $edit_flow->update_module_option( $this->module->name, 'loaded_once', true ); } // Upgrade path to v0.7.4 if ( version_compare( $previous_version, '0.7.4', '<' ) ) { // Usergroup descriptions become base64_encoded, instead of maybe json_encoded. $this->upgrade_074_term_descriptions( self::taxonomy_key ); } } /** * Individual Usergroups are stored using a custom taxonomy * Posts are associated with usergroups based on taxonomy relationship * User associations are stored serialized in the term's description field * * @since 0.7 * * @uses register_taxonomy() */ function register_usergroup_objects() { // Load the currently supported post types so we only register against those $supported_post_types = $this->get_post_types_for_module( $this->module ); // Use a taxonomy to manage relationships between posts and usergroups $args = array( 'public' => false, 'rewrite' => false, ); register_taxonomy( self::taxonomy_key, $supported_post_types, $args ); } /** * Enqueue necessary admin scripts * * @since 0.7 * * @uses wp_enqueue_script() */ function enqueue_admin_scripts() { if ( $this->is_whitelisted_functional_view() || $this->is_whitelisted_settings_view( $this->module->name ) ) { wp_enqueue_script( 'jquery-listfilterizer' ); wp_enqueue_script( 'jquery-quicksearch' ); wp_enqueue_script( 'edit-flow-user-groups-js', $this->module_url . 'lib/user-groups.js', array( 'jquery', 'jquery-listfilterizer', 'jquery-quicksearch' ), EDIT_FLOW_VERSION, true ); } if ( $this->is_whitelisted_settings_view( $this->module->name ) ) wp_enqueue_script( 'edit-flow-user-groups-configure-js', $this->module_url . 'lib/user-groups-configure.js', array( 'jquery' ), EDIT_FLOW_VERSION, true ); } /** * Enqueue necessary admin styles, but only on the proper pages * * @since 0.7 * * @uses wp_enqueue_style() */ function enqueue_admin_styles() { if ( $this->is_whitelisted_functional_view() || $this->is_whitelisted_settings_view() ) { wp_enqueue_style( 'jquery-listfilterizer' ); wp_enqueue_style( 'edit-flow-user-groups-css', $this->module_url . 'lib/user-groups.css', false, EDIT_FLOW_VERSION ); } } /** * Module ??? */ /** * Handles a POST request to add a new Usergroup. Redirects to edit view after * for admin to add users to usergroup * Hooked into 'admin_init' and kicks out right away if no action * * @since 0.7 */ function handle_add_usergroup() { if ( !isset( $_POST['submit'], $_POST['form-action'], $_GET['page'] ) || $_GET['page'] != $this->module->settings_slug || $_POST['form-action'] != 'add-usergroup' ) return; if ( !wp_verify_nonce( $_POST['_wpnonce'], 'add-usergroup' ) ) wp_die( $this->module->messages['nonce-failed'] ); if ( !current_user_can( $this->manage_usergroups_cap ) ) wp_die( $this->module->messages['invalid-permissions'] ); // Sanitize all of the user-entered values $name = strip_tags( trim( $_POST['name'] ) ); $description = stripslashes( strip_tags( trim( $_POST['description'] ) ) ); $_REQUEST['form-errors'] = array(); /** * Form validation for adding new Usergroup * * Details * - 'name' is a required field, but can't match an existing name or slug. Needs to be 40 characters or less * - "description" can accept a limited amount of HTML, and is optional */ // Field is required if ( empty( $name ) ) $_REQUEST['form-errors']['name'] = __( 'Please enter a name for the user group.', 'edit-flow' ); // Check to ensure a term with the same name doesn't exist if ( $this->get_usergroup_by( 'name', $name ) ) $_REQUEST['form-errors']['name'] = __( 'Name already in use. Please choose another.', 'edit-flow' ); // Check to ensure a term with the same slug doesn't exist if ( $this->get_usergroup_by( 'slug', sanitize_title( $name ) ) ) $_REQUEST['form-errors']['name'] = __( 'Name conflicts with slug for another term. Please choose again.', 'edit-flow' ); if ( strlen( $name ) > 40 ) $_REQUEST['form-errors']['name'] = __( 'User group name cannot exceed 40 characters. Please try a shorter name.', 'edit-flow' ); // Kick out if there are any errors if ( count( $_REQUEST['form-errors'] ) ) { $_REQUEST['error'] = 'form-error'; return; } // Try to add the Usergroup $args = array( 'name' => $name, 'description' => $description, ); $usergroup = $this->add_usergroup( $args ); if ( is_wp_error( $usergroup ) ) wp_die( __( 'Error adding usergroup.', 'edit-flow' ) ); $args = array( 'action' => 'edit-usergroup', 'usergroup-id' => $usergroup->term_id, 'message' => 'usergroup-added' ); $redirect_url = $this->get_link( $args ); wp_redirect( $redirect_url ); exit; } /** * Handles a POST request to edit a Usergroup * Hooked into 'admin_init' and kicks out right away if no action * * @since 0.7 */ function handle_edit_usergroup() { if ( !isset( $_POST['submit'], $_POST['form-action'], $_GET['page'] ) || $_GET['page'] != $this->module->settings_slug || $_POST['form-action'] != 'edit-usergroup' ) return; if ( !wp_verify_nonce( $_POST['_wpnonce'], 'edit-usergroup' ) ) wp_die( $this->module->messages['nonce-failed'] ); if ( !current_user_can( $this->manage_usergroups_cap ) ) wp_die( $this->module->messages['invalid-permissions'] ); if ( !$existing_usergroup = $this->get_usergroup_by( 'id', (int)$_POST['usergroup_id'] ) ) wp_die( $this->module->messages['usergroup-missing'] ); // Sanitize all of the user-entered values $name = strip_tags( trim( $_POST['name'] ) ); $description = stripslashes( strip_tags( trim( $_POST['description'] ) ) ); $_REQUEST['form-errors'] = array(); /** * Form validation for editing a Usergroup * * Details * - 'name' is a required field, but can't match an existing name or slug. Needs to be 40 characters or less * - "description" can accept a limited amount of HTML, and is optional */ // Field is required if ( empty( $name ) ) $_REQUEST['form-errors']['name'] = __( 'Please enter a name for the user group.', 'edit-flow' ); // Check to ensure a term with the same name doesn't exist $search_term = $this->get_usergroup_by( 'name', $name ); if ( is_object( $search_term ) && $search_term->term_id != $existing_usergroup->term_id ) $_REQUEST['form-errors']['name'] = __( 'Name already in use. Please choose another.', 'edit-flow' ); // Check to ensure a term with the same slug doesn't exist $search_term = $this->get_usergroup_by( 'slug', sanitize_title( $name ) ); if ( is_object( $search_term ) && $search_term->term_id != $existing_usergroup->term_id ) $_REQUEST['form-errors']['name'] = __( 'Name conflicts with slug for another term. Please choose again.', 'edit-flow' ); if ( strlen( $name ) > 40 ) $_REQUEST['form-errors']['name'] = __( 'User group name cannot exceed 40 characters. Please try a shorter name.', 'edit-flow' ); // Kick out if there are any errors if ( count( $_REQUEST['form-errors'] ) ) { $_REQUEST['error'] = 'form-error'; return; } // Try to edit the Usergroup $args = array( 'name' => $name, 'description' => $description, ); // Gracefully handle the case where all users have been unsubscribed from the user group $users = isset( $_POST['usergroup_users'] ) ? (array)$_POST['usergroup_users'] : array(); $users = array_map( 'intval', $users ); $usergroup = $this->update_usergroup( $existing_usergroup->term_id, $args, $users ); if ( is_wp_error( $usergroup ) ) wp_die( __( 'Error updating user group.', 'edit-flow' ) ); $args = array( 'message' => 'usergroup-updated', ); $redirect_url = $this->get_link( $args ); wp_redirect( $redirect_url ); exit; } /** * Handles a request to delete a Usergroup. * Hooked into 'admin_init' and kicks out right away if no action * * @since 0.7 */ function handle_delete_usergroup() { if ( !isset( $_GET['page'], $_GET['action'], $_GET['usergroup-id'] ) || $_GET['page'] != $this->module->settings_slug || $_GET['action'] != 'delete-usergroup' ) return; if ( !wp_verify_nonce( $_GET['nonce'], 'delete-usergroup' ) ) wp_die( $this->module->messages['nonce-failed'] ); if ( !current_user_can( $this->manage_usergroups_cap ) ) wp_die( $this->module->messages['invalid-permissions'] ); $result = $this->delete_usergroup( (int)$_GET['usergroup-id'] ); if ( !$result || is_wp_error( $result ) ) wp_die( __( 'Error deleting user group.', 'edit-flow' ) ); $redirect_url = $this->get_link( array( 'message' => 'usergroup-deleted' ) ); wp_redirect( $redirect_url ); exit; } /** * Handle the request to update a given Usergroup via inline edit * * @since 0.7 */ function handle_ajax_inline_save_usergroup() { if ( !wp_verify_nonce( $_POST['inline_edit'], 'usergroups-inline-edit-nonce' ) ) die( $this->module->messages['nonce-failed'] ); if ( !current_user_can( $this->manage_usergroups_cap ) ) die( $this->module->messages['invalid-permissions'] ); $usergroup_id = (int) $_POST['usergroup_id']; if ( !$existing_term = $this->get_usergroup_by( 'id', $usergroup_id ) ) die( $this->module->messages['usergroup-missing'] ); $name = strip_tags( trim( $_POST['name'] ) ); $description = stripslashes( strip_tags( trim( $_POST['description'] ) ) ); /** * Form validation for editing Usergroup */ // Check if name field was filled in if ( empty( $name ) ) { $change_error = new WP_Error( 'invalid', __( 'Please enter a name for the user group.', 'edit-flow' ) ); die( $change_error->get_error_message() ); } // Check that the name doesn't exceed 40 chars if ( strlen( $name ) > 40 ) { $change_error = new WP_Error( 'invalid', __( 'User group name cannot exceed 40 characters. Please try a shorter name.' ) ); die( $change_error->get_error_message() ); } // Check to ensure a term with the same name doesn't exist $search_term = $this->get_usergroup_by( 'name', $name ); if ( is_object( $search_term ) && $search_term->term_id != $existing_term->term_id ) { $change_error = new WP_Error( 'invalid', __( 'Name already in use. Please choose another.', 'edit-flow' ) ); die( $change_error->get_error_message() ); } // Check to ensure a term with the same slug doesn't exist $search_term = $this->get_usergroup_by( 'slug', sanitize_title( $name ) ); if ( is_object( $search_term ) && $search_term->term_id != $existing_term->term_id ) { $change_error = new WP_Error( 'invalid', __( 'Name conflicts with slug for another term. Please choose again.', 'edit-flow' ) ); die( $change_error->get_error_message() ); } // Prepare the term name and description for saving $args = array( 'name' => $name, 'description' => $description, ); $return = $this->update_usergroup( $existing_term->term_id, $args ); if( !is_wp_error( $return ) ) { set_current_screen( 'edit-usergroup' ); $wp_list_table = new EF_Usergroups_List_Table(); $wp_list_table->prepare_items(); echo $wp_list_table->single_row( $return ); die(); } else { $change_error = new WP_Error( 'invalid', sprintf( __( 'Could not update the user group: %s', 'edit-flow' ), $usergroup_name ) ); die( $change_error->get_error_message() ); } } /** * Register settings for notifications so we can partially use the Settings API * (We use the Settings API for form generation, but not saving) * * @since 0.7 * @uses add_settings_section(), add_settings_field() */ function register_settings() { add_settings_section( $this->module->options_group_name . '_general', false, '__return_false', $this->module->options_group_name ); add_settings_field( 'post_types', __( 'Add to these post types:', 'edit-flow' ), array( $this, 'settings_post_types_option' ), $this->module->options_group_name, $this->module->options_group_name . '_general' ); } /** * Choose the post types for Usergroups * * @since 0.7 */ function settings_post_types_option() { global $edit_flow; $edit_flow->settings->helper_option_custom_post_type( $this->module ); } /** * Validate data entered by the user * * @since 0.7 * * @param array $new_options New values that have been entered by the user * @return array $new_options Form values after they've been sanitized */ function settings_validate( $new_options ) { // Whitelist validation for the post type options if ( !isset( $new_options['post_types'] ) ) $new_options['post_types'] = array(); $new_options['post_types'] = $this->clean_post_type_options( $new_options['post_types'], $this->module->post_type_support ); return $new_options; } /** * Build a configuration view so we can manage our usergroups * * @since 0.7 */ function print_configure_view() { global $edit_flow; if ( isset( $_GET['action'], $_GET['usergroup-id'] ) && $_GET['action'] == 'edit-usergroup' ) : /** Full page width view for editing a given usergroup **/ // Check whether the usergroup exists $usergroup_id = (int)$_GET['usergroup-id']; $usergroup = $this->get_usergroup_by( 'id', $usergroup_id ); if ( !$usergroup ) { echo '' . $this->module->messages['usergroup-missing'] . '
| ID ) : ?> | usergroups_select_form( $selected_usergroups, $usergroups_form_args ); ?> |
|---|