p =& $plugin; if ( $this->p->debug->enabled ) { $this->p->debug->mark(); } /* * This hook is fired once WordPress, plugins, and the theme are fully loaded and instantiated. */ add_action( 'wp_loaded', array( $this, 'add_wp_callbacks' ) ); } /* * Add WordPress action and filter callbacks. */ public function add_wp_callbacks() { if ( $this->p->debug->enabled ) { $this->p->debug->mark(); } /* * Since WPSSO Core v17.0.0. * * Register our user meta. */ $this->register_meta( $object_type = 'user', WPSSO_META_NAME ); $is_admin = is_admin(); // Only check once. $cm_fb_name = $this->p->options[ 'plugin_cm_fb_name' ]; if ( ! SucomUtilWP::role_exists( 'person' ) ) { $role_label_transl = _x( 'Person', 'user role', 'wpsso' ); add_role( 'person', $role_label_transl, array() ); } if ( ! empty( $this->p->options[ 'plugin_new_user_is_person' ] ) ) { if ( is_multisite() ) { add_action( 'wpmu_new_user', array( __CLASS__, 'add_role_by_id' ), 20, 1 ); } else add_action( 'user_register', array( __CLASS__, 'add_role_by_id' ), 20, 1 ); } add_filter( 'user_contactmethods', array( $this, 'add_contact_methods' ), 20, 2 ); add_filter( 'user_' . $cm_fb_name . '_label', array( $this, 'modify_fb_contact_label' ), 20, 1 ); add_action( 'wpsso_add_person_role', array( $this, 'add_person_role' ), 10, 1 ); // For single scheduled task. add_action( 'wpsso_remove_person_role', array( $this, 'remove_person_role' ), 10, 1 ); // For single scheduled task. /* * Hook a minimum number of admin actions to maximize performance. The user_id argument is * always present when we're editing a user, but missing when viewing our own profile page. */ if ( $is_admin ) { if ( ! empty( $_GET ) ) { // Skip some action hooks if no query argument(s). /* * load_meta_page() priorities: 100 post, 200 user, 300 term. * * Sets the parent::$head_tags and parent::$head_info class properties. */ add_action( 'current_screen', array( $this, 'load_meta_page' ), 200, 1 ); /* * Fires after the 'About the User' settings table on the 'Edit User' screen. */ add_action( 'edit_user_profile', array( $this, 'add_meta_boxes' ), 10, 1 ); } add_action( 'admin_bar_menu', array( $this, 'add_admin_bar_menu_view_profile' ), WPSSO_TB_VIEW_PROFILE_MENU_ORDER, 1 ); add_filter( 'views_users', array( $this, 'add_person_view' ) ); /* * Add edit table columns. */ if ( $this->p->debug->enabled ) { $this->p->debug->log( 'adding column filters for users' ); } add_filter( 'manage_users_columns', array( $this, 'add_user_column_headings' ), WPSSO_ADD_COLUMN_PRIORITY, 1 ); add_filter( 'manage_users_sortable_columns', array( $this, 'add_sortable_columns' ), 10, 1 ); add_filter( 'manage_users_custom_column', array( $this, 'get_column_content' ), 10, 3 ); /* * The 'parse_query' action is hooked once in the WpssoPost class to set the column orderby for * post, term, and user edit tables. * * This comment is here as a reminder - do not uncomment the following 'parse_query' action hook. * * add_action( 'parse_query', array( $this, 'set_column_orderby' ), 10, 1 ); */ /* * Maybe create or update the user column content. */ add_action( 'get_user_metadata', array( $this, 'check_sortable_meta' ), 1000, 4 ); /* * Hooks when editing a user. */ add_action( 'edit_user_profile', array( $this, 'show_metaboxes' ), 20, 1 ); add_action( 'edit_user_profile_update', array( $this, 'save_about_section' ), -3000, 1 ); add_action( 'edit_user_profile_update', array( $this, 'sanitize_submit_cm' ), -2000, 1 ); add_action( 'edit_user_profile_update', array( $this, 'save_options' ), WPSSO_META_SAVE_PRIORITY, 1 ); add_action( 'edit_user_profile_update', array( $this, 'clear_cache' ), WPSSO_META_CLEAR_PRIORITY, 1 ); add_action( 'edit_user_profile_update', array( $this, 'refresh_cache' ), WPSSO_META_REFRESH_PRIORITY, 1 ); /* * Hooks when editing personal profile. */ add_action( 'personal_options_update', array( $this, 'save_about_section' ), -3000, 1 ); add_action( 'personal_options_update', array( $this, 'sanitize_submit_cm' ), -2000, 1 ); add_action( 'personal_options_update', array( $this, 'save_options' ), WPSSO_META_SAVE_PRIORITY, 1 ); add_action( 'personal_options_update', array( $this, 'clear_cache' ), WPSSO_META_CLEAR_PRIORITY, 1 ); add_action( 'personal_options_update', array( $this, 'refresh_cache' ), WPSSO_META_REFRESH_PRIORITY, 1 ); /* * Use the 'show_password_fields' filter as an action to get more information about the user. */ add_filter( 'show_password_fields', array( $this, 'pre_password_fields' ), -1000, 2 ); } } /* * Get the $mod object for a user id. */ public function get_mod( $user_id ) { if ( $this->p->debug->enabled ) { $this->p->debug->mark_caller(); $this->p->debug->log_args( array( 'user_id' => $user_id, ) ); } static $local_fifo = array(); /* * Maybe return the array from the local cache. */ if ( isset( $local_fifo[ $user_id ] ) ) { if ( ! $this->md_cache_disabled ) { if ( $this->p->debug->enabled ) { $this->p->debug->log( 'exiting early: user id ' . $user_id . ' mod array from local cache' ); } return $local_fifo[ $user_id ]; } else unset( $local_fifo[ $user_id ] ); } /* * Maybe limit the number of array elements. */ $local_fifo = SucomUtil::array_slice_fifo( $local_fifo, WPSSO_CACHE_ARRAY_FIFO_MAX ); $mod = self::get_mod_defaults(); /* * Common elements. */ $mod[ 'id' ] = is_numeric( $user_id ) ? (int) $user_id : 0; // Cast as integer. $mod[ 'name' ] = 'user'; $mod[ 'name_transl' ] = _x( 'user', 'module name', 'wpsso' ); $mod[ 'obj' ] =& $this; /* * WpssoUser elements. */ $mod[ 'is_user' ] = true; $mod[ 'is_archive' ] = true; // Required for WpssoUtil->get_url_paged(). if ( $mod[ 'id' ] ) { // Just in case. $mod[ 'wp_obj' ] = SucomUtilWP::get_user_object( $mod[ 'id' ] ); // Optimize and fetch once. if ( $mod[ 'wp_obj' ] instanceof WP_User ) { // Just in case. $mod[ 'user_name' ] = (string) $mod[ 'wp_obj' ]->display_name; } else $mod[ 'wp_obj' ] = false; } /* * Filter the user mod array. */ $mod = apply_filters( 'wpsso_get_user_mod', $mod, $user_id ); if ( $this->p->debug->enabled ) { $this->p->debug->log_arr( 'mod', $mod ); } /* * Maybe save the array to the local cache. */ if ( ! $this->md_cache_disabled ) { $local_fifo[ $user_id ] = $mod; if ( $this->p->debug->enabled ) { $this->p->debug->log_size( 'local_fifo', $local_fifo ); } } return $mod; } public function get_mod_wp_object( array $mod ) { if ( $mod[ 'wp_obj' ] instanceof WP_User ) { return $mod[ 'wp_obj' ]; } return SucomUtilWP::get_user_object( $mod[ 'id' ] ); } /* * Option handling methods: * * get_defaults() * get_options() * save_options() * delete_options() */ public function get_options( $user_id, $md_key = false, $filter_opts = true, $merge_defs = false ) { if ( $this->p->debug->enabled ) { $this->p->debug->mark_caller(); $this->p->debug->log_args( array( 'user_id' => $user_id, 'md_key' => $md_key, 'filter_opts' => $filter_opts, 'merge_defs' => $merge_defs, // Fallback to value in meta defaults. ) ); } $user_id = false === $user_id ? get_current_user_id() : $user_id; if ( empty( $user_id ) ) { if ( false !== $md_key ) { return null; } return array(); } static $local_fifo = array(); /* * Use $user_id and $filter_opts to create the cache ID string, but do not add $merge_defs. */ $cache_id = SucomUtil::get_assoc_salt( array( 'id' => $user_id, 'filter' => $filter_opts ) ); /* * Maybe initialize a new local cache element. Use isset() instead of empty() to allow for an empty array. */ if ( ! isset( $local_fifo[ $cache_id ] ) ) { /* * Maybe limit the number of array elements. */ $local_fifo = SucomUtil::array_slice_fifo( $local_fifo, WPSSO_CACHE_ARRAY_FIFO_MAX ); $local_fifo[ $cache_id ] = null; // Create an element to reference. } $md_opts =& $local_fifo[ $cache_id ]; // Reference the local cache element. if ( null === $md_opts ) { // Maybe read metadata into a new local cache element. if ( $this->p->debug->enabled ) { $this->p->debug->log( 'getting metadata for user id ' . $user_id ); } $user_exists = SucomUtilWP::user_exists( $user_id ); if ( $user_exists ) { $user_exists_id = $user_id; $md_opts = self::get_meta( $user_exists_id, WPSSO_META_NAME, $single = true ); if ( ! is_array( $md_opts ) ) { $md_opts = array(); // WPSSO_META_NAME not found. } } else { $user_exists_id = 0; $md_opts = apply_filters( 'wpsso_get_other_user_meta', array(), $user_id ); } unset( $md_opts[ 'opt_filtered' ] ); // Just in case. /* * Check if options need to be upgraded and saved. */ if ( $this->p->opt->is_upgrade_required( $md_opts ) ) { $md_opts = $this->upgrade_options( $md_opts, $user_exists_id ); if ( $user_exists ) { self::update_meta( $user_exists_id, WPSSO_META_NAME, $md_opts ); } else apply_filters( 'wpsso_update_other_user_meta', $md_opts, $user_id ); } } if ( $filter_opts ) { if ( ! empty( $md_opts[ 'opt_filtered' ] ) ) { // Set before calling filters to prevent recursion. if ( $this->p->debug->enabled ) { $this->p->debug->log( 'skipping filters: options already filtered' ); } } else { if ( $this->p->debug->enabled ) { $this->p->debug->log( 'setting opt_filtered to 1' ); } $md_opts[ 'opt_filtered' ] = 1; // Set before calling filters to prevent recursion. if ( $this->p->debug->enabled ) { $this->p->debug->log( 'required call to WpssoUser->get_mod() for user ID ' . $user_id ); } $mod = $this->get_mod( $user_id ); $filter_name = 'wpsso_get_md_options'; if ( $this->p->debug->enabled ) { $this->p->debug->log( 'applying filters "' . $filter_name . '"' ); } $md_opts = apply_filters( $filter_name, $md_opts, $mod ); $filter_name = 'wpsso_get_' . $mod[ 'name' ] . '_options'; if ( $this->p->debug->enabled ) { $this->p->debug->log( 'applying filters "' . $filter_name . '"' ); } $md_opts = apply_filters( $filter_name, $md_opts, $user_id, $mod ); $filter_name = 'wpsso_sanitize_md_options'; if ( $this->p->debug->enabled ) { $this->p->debug->log( 'applying filters "' . $filter_name . '"' ); } $md_opts = apply_filters( $filter_name, $md_opts, $mod ); /* * Prevent users from modifying specific options. */ $disable_keys = array( 'og_type', 'schema_type', 'canonical_url', 'redirect_url', ); $filter_name = 'wpsso_get_user_options_keys_disabled'; if ( $this->p->debug->enabled ) { $this->p->debug->log( 'applying filters "' . $filter_name . '"' ); } $disable_keys = apply_filters( $filter_name, $disable_keys, $user_id, $mod ); if ( ! empty( $disable_keys ) ) { foreach ( $disable_keys as $opt_key ) { $md_opts[ $opt_key . ':disabled' ] = true; } } } } /* * Maybe save the array to the local cache. */ if ( $this->md_cache_disabled ) { $deref_md_opts = $local_fifo[ $cache_id ]; // Dereference. unset( $local_fifo, $md_opts ); return $this->return_options( $user_id, $deref_md_opts, $md_key, $merge_defs ); } return $this->return_options( $user_id, $md_opts, $md_key, $merge_defs ); } /* * Use $rel = false to extend WpssoAbstractWpMeta->save_options(). */ public function save_options( $user_id, $rel = false ) { if ( $this->p->debug->enabled ) { $this->p->debug->log_args( array( 'user_id' => $user_id, ) ); } if ( empty( $user_id ) ) { // Just in case. if ( $this->p->debug->enabled ) { $this->p->debug->log( 'exiting early: user id is empty' ); } return; } elseif ( ! $this->verify_submit_nonce() ) { if ( $this->p->debug->enabled ) { $this->p->debug->log( 'exiting early: verify_submit_nonce failed' ); } return; /* * Check user capability for the user id. */ } elseif ( ! $this->user_can_edit( $user_id ) ) { if ( $this->p->debug->enabled ) { $user_id = get_current_user_id(); $this->p->debug->log( 'exiting early: user id ' . $user_id . ' cannot edit use id ' . $user_id ); } return; } $this->md_cache_disable(); // Disable the local cache. $mod = $this->get_mod( $user_id ); $md_opts = $this->get_submit_opts( $mod ); // Merge previous + submitted options and then sanitize. $this->md_cache_enable(); // Re-enable the local cache. if ( false === $md_opts ) { if ( $this->p->debug->enabled ) { $this->p->debug->log( 'exiting early: returned submit options is false' ); } return; } $md_opts = apply_filters( 'wpsso_save_md_options', $md_opts, $mod ); $md_opts = apply_filters( 'wpsso_save_' . $mod[ 'name' ] . '_options', $md_opts, $user_id, $mod ); return self::update_meta( $user_id, WPSSO_META_NAME, $md_opts ); } /* * Use $rel = false to extend WpssoAbstractWpMeta->delete_options(). */ public function delete_options( $user_id, $rel = false ) { return self::delete_meta( $user_id, WPSSO_META_NAME ); } /* * Get all publicly accessible user ids in the 'creator' array. */ public static function get_public_ids( array $users_args = array() ) { $wpsso =& Wpsso::get_instance(); $mtime_start = microtime( $get_float = true ); $role_names = empty( $users_args[ 'role' ] ) ? $wpsso->cf[ 'wp' ][ 'roles' ][ 'creator' ] : array( $users_args[ 'role' ] ); $users_args = array_merge( $users_args, array( 'fields' => 'ids' ) ); $public_ids = array(); foreach ( $role_names as $name ) { /* * See https://developer.wordpress.org/reference/classes/wp_user_query/__construct/. */ $query_args = array_merge( $users_args, array( 'role' => $name ) ); $users_ids = get_users( $query_args ); if ( is_array( $users_ids ) ) { foreach ( $users_ids as $user_id ) { if ( is_numeric( $user_id ) ) { $public_ids[ $user_id ] = $user_id; // Prevents duplicates. } } } } unset( $query_args, $users_ids ); /* * Sort public user IDs with the newest user ID first. * * Note that rsort() assigns new keys to elements in the array. * * See https://www.php.net/manual/en/function.rsort.php. */ rsort( $public_ids ); $mtime_total = microtime( $get_float = true ) - $mtime_start; if ( $wpsso->debug->enabled ) { $wpsso->debug->log( count( $public_ids ) . ' user IDs returned in ' . sprintf( '%0.3f secs', $mtime_total ) ); } return apply_filters( 'wpsso_user_public_ids', $public_ids, $users_args ); } /* * Get the posts for a user. * * Returns an array of post IDs for a given $mod object. * * The 'posts_per_page' value should be set for an archive page before calling this method. * * See WpssoAbstractWpMeta->get_posts_mods(). */ public function get_posts_ids( array $mod ) { if ( $this->p->debug->enabled ) { $this->p->debug->mark(); } if ( empty( $mod[ 'is_user' ] ) ) { if ( $this->p->debug->enabled ) { $this->p->debug->log( 'exiting early: ' . $mod[ 'name' ] . ' ID ' . $mod[ 'id' ] . ' is not a user' ); } return array(); } $posts_args = array_merge( array( 'has_password' => false, 'order' => 'DESC', // Newest first. 'orderby' => 'date', 'post_status' => 'publish', // Only 'publish' (not 'auto-draft', 'draft', 'future', 'inherit', 'pending', 'private', or 'trash'). 'post_type' => 'post', // Return only posts authored by the user. 'author' => $mod[ 'id' ], ), $mod[ 'posts_args' ], array( 'fields' => 'ids' ) ); // Return an array of post IDs. if ( $this->p->debug->enabled ) { $this->p->debug->log( 'getting posts for ' . $mod[ 'name' ] . ' ID ' . $mod[ 'id' ] ); $this->p->debug->log_arr( 'posts_args', $posts_args ); } $mtime_start = microtime( $get_float = true ); $posts_ids = SucomUtilWP::get_posts( $posts_args ); // Alternative to get_posts() that does not exclude sticky posts. $mtime_total = microtime( $get_float = true ) - $mtime_start; if ( $this->p->debug->enabled ) { $this->p->debug->log( count( $posts_ids ) . ' post IDs returned in ' . sprintf( '%0.3f secs', $mtime_total ) ); } return $posts_ids; } public function add_user_column_headings( $columns ) { if ( $this->p->debug->enabled ) { $this->p->debug->mark(); } return $this->add_column_headings( $columns, $opt_suffix = 'user_page' ); } public function get_update_meta_cache( $user_id ) { return SucomUtilWP::get_update_meta_cache( $user_id, $meta_type = 'user' ); } /* * Hooked into the current_screen action. * * Sets the parent::$head_tags and parent::$head_info class properties. */ public function load_meta_page( $screen = false ) { if ( $this->p->debug->enabled ) { $this->p->debug->mark(); } /* * All meta modules set this property, so use it to optimize code execution. */ if ( false !== parent::$head_tags || ! isset( $screen->id ) ) { return; } if ( $this->p->debug->enabled ) { $this->p->debug->log( 'screen id = ' . $screen->id ); } switch ( $screen->id ) { case ( 0 === strpos( $screen->id, 'users_page_wpsso-add-' ) ? true : false ): // Add user page. $user_id = null; $mod = $this->get_mod( null ); break; case 'profile': // User profile page. case 'user-edit': // User editing page. case ( 0 === strpos( $screen->id, 'profile_page_' ) ? true : false ): // Your profile page. case ( 0 === strpos( $screen->id, 'users_page_' . $this->p->id ) ? true : false ): // Profile SSO page. /* * Get the user id. * * Returns the current user id if the 'user_id' query argument is empty. */ $user_id = SucomUtilWP::get_user_object( false, 'id' ); $mod = $this->get_mod( $user_id ); break; default: if ( $this->p->debug->enabled ) { $this->p->debug->log( 'exiting early: not a recognized user page' ); } return; } /* * Define parent::$head_tags and signal to other 'current_screen' actions that this is a user page. */ parent::$head_tags = array(); // Used by WpssoAbstractWpMeta->is_meta_page(). if ( $this->p->debug->enabled ) { $this->p->debug->log( 'user id = ' . $user_id ); $this->p->debug->log( 'home url = ' . get_option( 'home' ) ); $this->p->debug->log( 'locale default = ' . SucomUtilWP::get_locale() ); $this->p->debug->log( 'locale current = ' . SucomUtilWP::get_locale( 'current' ) ); $this->p->debug->log( 'locale mod = ' . SucomUtilWP::get_locale( $mod ) ); $this->p->debug->log( SucomUtil::get_array_pretty( $mod ) ); } if ( $user_id && ! empty( $this->p->options[ 'plugin_add_to_user_page' ] ) ) { do_action( 'wpsso_admin_user_head', $mod, $screen->id ); list( parent::$head_tags, // Used by WpssoAbstractWpMeta->is_meta_page(). parent::$head_info // Used by WpssoAbstractWpMeta->check_head_info(). ) = $this->p->util->cache->refresh_mod_head_meta( $mod ); /* * Check for missing open graph image and description values. */ if ( $mod[ 'id' ] && $mod[ 'is_public' ] ) { // Since WPSSO Core v7.0.0. $this->check_head_info( $mod ); } } $action_query = 'wpsso-action'; if ( ! empty( $_GET[ $action_query ] ) ) { $action_name = SucomUtil::sanitize_hookname( $_GET[ $action_query ] ); if ( $this->p->debug->enabled ) { $this->p->debug->log( 'found action query: ' . $action_name ); } if ( empty( $_GET[ WPSSO_NONCE_NAME ] ) ) { // WPSSO_NONCE_NAME is an md5() string if ( $this->p->debug->enabled ) { $this->p->debug->log( 'nonce token query field missing' ); } } elseif ( ! wp_verify_nonce( $_GET[ WPSSO_NONCE_NAME ], WpssoAdmin::get_nonce_action() ) ) { $this->p->notice->err( sprintf( __( 'Nonce token validation failed for %1$s action "%2$s".', 'wpsso' ), 'user', $action_name ) ); } else { $_SERVER[ 'REQUEST_URI' ] = remove_query_arg( array( $action_query, WPSSO_NONCE_NAME ) ); switch ( $action_name ) { default: do_action( 'wpsso_load_meta_page_user_' . $action_name, $user_id, $screen->id ); break; } } } } /* * Use $rel = false to extend WpssoAbstractWpMeta->add_meta_boxes(). */ public function add_meta_boxes( $user_obj, $rel = false ) { if ( $this->p->debug->enabled ) { $this->p->debug->mark(); } $user_id = empty( $user_obj->ID ) ? 0 : $user_obj->ID; if ( empty( $this->p->options[ 'plugin_add_to_user_page' ] ) ) { if ( $this->p->debug->enabled ) { $this->p->debug->log( 'exiting early: cannot add metabox to user page' ); } return; } $capability = 'edit_user'; if ( ! current_user_can( $capability, $user_id ) ) { if ( $this->p->debug->enabled ) { $this->p->debug->log( 'exiting early: cannot ' . $capability . ' for user id ' . $user_id ); } return; } $metabox_id = $this->p->cf[ 'meta' ][ 'id' ]; $metabox_title = _x( $this->p->cf[ 'meta' ][ 'title' ], 'metabox title', 'wpsso' ); $metabox_screen = 'wpsso-user'; $metabox_context = 'normal'; $metabox_prio = 'default'; $callback_args = array( // Second argument passed to the callback. 'metabox_id' => $metabox_id, 'metabox_title' => $metabox_title, '__block_editor_compatible_meta_box' => true, ); if ( $this->p->debug->enabled ) { $this->p->debug->log( 'adding metabox id wpsso_' . $metabox_id . ' for screen ' . $metabox_screen ); } add_meta_box( 'wpsso_' . $metabox_id, $metabox_title, array( $this, 'show_metabox_' . $metabox_id ), $metabox_screen, $metabox_context, $metabox_prio, $callback_args ); } /* * Show additional fields in the user profile About Yourself / About the user sections. * * Hooked to the 'show_password_fields' filter (not an action). */ public function pre_password_fields( $show_password_fields, $user_obj ) { if ( ! isset( $user_obj->ID ) ) { // Just in case. /* * This is a filter, so return the filter value unchanged. */ return $show_password_fields; } if ( ! current_user_can( 'edit_user', $user_obj->ID ) ) { // Just in case. /* * This is a filter, so return the filter value unchanged. */ return $show_password_fields; } $this->show_about_section( $user_obj->ID ); // Echo the additional input fields. /* * This is a filter, so return the filter value unchanged. */ return $show_password_fields; } /* * Called by the WpssoUser->pre_password_fields() and WpssoUsersAddPerson->show_post_body_settings_form() methods. */ public function show_about_section( $user_id = 0 ) { foreach ( $this->p->cf[ 'opt' ][ 'user_about' ] as $about_key => $about_label ) { if ( empty( $this->p->options[ 'plugin_user_about_' . $about_key ] ) ) { continue; } echo ''; echo ''; foreach ( $this->get_user_about_meta_keys( $about_key ) as $meta_key ) { $val = $user_id ? self::get_meta( $user_id, $meta_key, $single = true ) : ''; echo '

'; } switch ( $about_key ) { case 'honorific_prefix': echo '

' . __( 'Examples: Dr, Mrs, Mr.', 'wpsso' ) . '

'; break; case 'honorific_suffix': echo '

' . __( 'Examples: CPA, Esq., M.D., P.E., PhD., PMP, RN', 'wpsso' ) . '

'; break; } echo ''; } } public function show_metaboxes( $user_obj ) { if ( ! isset( $user_obj->ID ) ) { // Just in case. return; } if ( empty( $this->p->options[ 'plugin_add_to_user_page' ] ) ) { return; } if ( ! current_user_can( 'edit_user', $user_obj->ID ) ) { // Just in case. return; } $metabox_screen = 'wpsso-user'; $metabox_context = 'normal'; echo '
' . "\n"; do_meta_boxes( $metabox_screen, $metabox_context, $user_obj ); echo "\n" . '
' . "\n"; } public function ajax_get_metabox_sso() { die( -1 ); // Nothing to do. } public function get_form_contact_fields( $fields = array() ) { return array( 'none' => '[None]' ) + $this->add_contact_methods( array( 'author' => 'Author Archive', 'url' => 'WebSite' ) ); } public function add_contact_methods( $fields = array(), $user = null ) { /* * Unset built-in contact fields and/or update their labels. */ if ( ! empty( $this->p->cf[ 'wp' ][ 'cm_names' ] ) && is_array( $this->p->cf[ 'wp' ][ 'cm_names' ] ) ) { foreach ( $this->p->cf[ 'wp' ][ 'cm_names' ] as $id => $desc ) { $cm_enabled_key = 'wp_cm_' . $id . '_enabled'; $cm_label_key = 'wp_cm_' . $id . '_label'; if ( isset( $this->p->options[ $cm_enabled_key ] ) ) { if ( ! empty( $this->p->options[ $cm_enabled_key ] ) ) { $cm_label_value = SucomUtilOptions::get_key_value( $cm_label_key, $this->p->options ); if ( ! empty( $cm_label_value ) ) { // Just in case. $fields[ $id ] = $cm_label_value; } } else { unset( $fields[ $id ] ); } } } } /* * Loop through each social website option prefix. */ foreach ( $this->p->cf[ 'opt' ][ 'cm_prefix' ] as $id => $opt_pre ) { $cm_enabled_key = 'plugin_cm_' . $opt_pre . '_enabled'; $cm_name_key = 'plugin_cm_' . $opt_pre . '_name'; $cm_label_key = 'plugin_cm_' . $opt_pre . '_label'; if ( ! empty( $this->p->options[ $cm_enabled_key ] ) && ! empty( $this->p->options[ $cm_name_key ] ) ) { $cm_label_value = SucomUtilOptions::get_key_value( $cm_label_key, $this->p->options ); if ( ! empty( $cm_label_value ) ) { $fields[ $this->p->options[ $cm_name_key ] ] = $cm_label_value; } } } uasort( $fields, 'strnatcmp' ); // Sort associative array by value. return $fields; } public function modify_fb_contact_label( $label ) { return $label . '
' . __( '(not a Facebook Pages URL)', 'wpsso' ) . ''; } /* * Save the additional fields for the user profile About Yourself / About the user sections. * * Hooked to the 'edit_user_profile_update' and 'personal_options_update' actions. * * Also called by the WpssoUsersAddPerson->add_person() method. */ public function save_about_section( $user_id ) { static $do_once = array(); // Just in case - prevent recursion. if ( isset( $do_once[ $user_id ] ) ) return; // Stop here. $do_once[ $user_id ] = true; if ( ! current_user_can( 'edit_user', $user_id ) ) { return; } foreach ( $this->p->cf[ 'opt' ][ 'user_about' ] as $about_key => $about_label ) { if ( empty( $this->p->options[ 'plugin_user_about_' . $about_key ] ) ) { continue; } foreach ( $this->get_user_about_meta_keys( $about_key ) as $meta_key ) { /* * Regular text input fields. * * See https://developer.wordpress.org/themes/theme-security/data-sanitization-escaping/. */ if ( isset( $_POST[ $meta_key ] ) ) { self::update_meta( $user_id, $meta_key, sanitize_text_field( $_POST[ $meta_key ] ) ); } } } } public function sanitize_submit_cm( $user_id ) { static $do_once = array(); // Just in case - prevent recursion. if ( isset( $do_once[ $user_id ] ) ) return; // Stop here. $do_once[ $user_id ] = true; if ( ! current_user_can( 'edit_user', $user_id ) ) { return; } foreach ( $this->p->cf[ 'opt' ][ 'cm_prefix' ] as $id => $opt_pre ) { /* * Check that the social site has a contact field. */ if ( isset( $this->p->options[ 'plugin_cm_' . $opt_pre . '_name' ] ) ) { $cm_enabled_value = $this->p->options[ 'plugin_cm_' . $opt_pre . '_enabled' ]; $cm_name_value = $this->p->options[ 'plugin_cm_' . $opt_pre . '_name' ]; /* * Sanitize values only for those enabled contact methods. */ if ( isset( $_POST[ $cm_name_value ] ) && ! empty( $cm_enabled_value ) && ! empty( $cm_name_value ) ) { $value = wp_filter_nohtml_kses( $_POST[ $cm_name_value ] ); if ( ! empty( $value ) ) { switch ( $cm_name_value ) { case $this->p->options[ 'plugin_cm_skype_name' ]: /* * No change. */ break; case $this->p->options[ 'plugin_cm_twitter_name' ]: $value = SucomUtil::sanitize_twitter_name( $value ); break; default: /* * All other contact methods are assumed to be URLs. */ if ( false === strpos( $value, '://' ) ) { $value = ''; } break; } } $_POST[ $cm_name_value ] = $value; } } } return $user_id; } public function get_user_sameas( $user_id ) { $user_sameas = array(); $contact_methods = WpssoUser::get_user_id_contact_methods( $user_id ); foreach ( $contact_methods as $cm_id => $cm_label ) { $url = $this->get_author_meta( $user_id, $cm_id ); if ( empty( $url ) ) { continue; } elseif ( $cm_id === $this->p->options[ 'plugin_cm_twitter_name' ] ) { // Convert twitter name to url. $url = 'https://twitter.com/' . SucomUtil::sanitize_twitter_name( $url, $add_at = false ); } if ( false === filter_var( $url, FILTER_VALIDATE_URL ) ) { // Just in case. if ( $this->p->debug->enabled ) { $this->p->debug->log( 'skipping ' . $cm_id . ': url "' . $url . '" is invalid' ); } } else $user_sameas[] = $url; } return $user_sameas; } /* * Convert user ID to user object and call wp_get_user_contact_methods(). */ public static function get_user_id_contact_methods( $user_id ) { $user_obj = get_user_by( 'ID', $user_id ); return wp_get_user_contact_methods( $user_obj ); } /* * Returns the user id for a comment author, post author, or user module. */ public static function get_author_id( array $mod ) { $author_id = false; if ( $mod[ 'is_user' ] ) { $author_id = $mod[ 'id' ]; } elseif ( $mod[ 'is_comment' ] ) { if ( $mod[ 'comment_author' ] ) { $author_id = $mod[ 'comment_author' ]; } } elseif ( $mod[ 'is_post' ] ) { if ( $mod[ 'post_author' ] ) { $author_id = $mod[ 'post_author' ]; } } return $author_id; } /* * Returns the display name for a user module, comment author, or post author. */ public function get_author_name( array $mod ) { $author_name = ''; if ( $mod[ 'is_user' ] ) { $author_name = get_the_author_meta( 'display_name', $mod[ 'id' ] ); } elseif ( $mod[ 'is_comment' ] ) { if ( $mod[ 'comment_author_name' ] ) { $author_id = $mod[ 'comment_author_name' ]; } } elseif ( $author_id = self::get_author_id( $mod ) ) { $author_name = get_the_author_meta( 'display_name', $author_id ); } return $author_name; } /* * Returns the description for a user module or post author. */ public function get_author_description( array $mod ) { $author_desc = ''; if ( $mod[ 'is_user' ] ) { $author_desc = get_the_author_meta( 'description', $mod[ 'id' ] ); } elseif ( $author_id = self::get_author_id( $mod ) ) { $author_desc = get_the_author_meta( 'description', $author_id ); } return $author_desc; } public function get_author_meta( $user_id, $meta_key ) { if ( $this->p->debug->enabled ) { $this->p->debug->log_args( array( 'user_id' => $user_id, 'meta_key' => $meta_key, ) ); } static $local_fifo = array(); if ( isset( $local_fifo[ $user_id ] ) ) { if ( isset( $local_fifo[ $user_id ][ $meta_key ] ) ) { return $local_fifo[ $user_id ][ $meta_key ]; } } else { /* * Maybe limit the number of array elements. */ $local_fifo = SucomUtil::array_slice_fifo( $local_fifo, WPSSO_CACHE_ARRAY_FIFO_MAX ); $local_fifo[ $user_id ] = array(); } $user_exists = SucomUtilWP::user_exists( $user_id ); $author_meta = ''; if ( $user_exists ) { switch ( $meta_key ) { case 'none': break; case 'fullname': $author_meta = get_the_author_meta( 'first_name', $user_id ) . ' ' . get_the_author_meta( 'last_name', $user_id ); break; case 'description': $author_meta = preg_replace( '/[\s\n\r]+/s', ' ', get_the_author_meta( $meta_key, $user_id ) ); break; case 'awards': $author_meta = array(); foreach ( $this->get_user_about_meta_keys( 'award' ) as $meta_key ) { $val = self::get_meta( $user_id, $meta_key, $single = true ); if ( SucomUtil::is_valid_option_value( $val ) ) { $author_meta[] = $val; } } break; default: $author_meta = get_the_author_meta( $meta_key, $user_id ); break; } if ( is_string( $author_meta ) ) { $author_meta = trim( $author_meta ); // Just in case. } } elseif ( $this->p->debug->enabled ) { $this->p->debug->log( 'user id ' . $user_id . ' is not a WordPress user' ); } $filter_name = 'wpsso_get_author_meta'; if ( $this->p->debug->enabled ) { $this->p->debug->log( 'applying filters "' . $filter_name . '"' ); } $author_meta = apply_filters( $filter_name, $author_meta, $user_id, $meta_key, $user_exists ); return $local_fifo[ $user_id ][ $meta_key ] = $author_meta; } public function get_author_website( $user_id, $meta_key = 'url' ) { if ( $this->p->debug->enabled ) { $this->p->debug->log_args( array( 'user_id' => $user_id, 'meta_key' => $meta_key, ) ); } static $local_fifo = array(); if ( isset( $local_fifo[ $user_id ] ) ) { if ( isset( $local_fifo[ $user_id ][ $meta_key ] ) ) { return $local_fifo[ $user_id ][ $meta_key ]; } } else { /* * Maybe limit the number of array elements. */ $local_fifo = SucomUtil::array_slice_fifo( $local_fifo, WPSSO_CACHE_ARRAY_FIFO_MAX ); $local_fifo[ $user_id ] = array(); } $user_exists = SucomUtilWP::user_exists( $user_id ); $website_url = ''; if ( $user_exists ) { switch ( $meta_key ) { case 'none': break; case 'archive': $website_url = get_author_posts_url( $user_id ); break; case 'twitter': $website_url = get_the_author_meta( $meta_key, $user_id ); if ( false === filter_var( $website_url, FILTER_VALIDATE_URL ) ) { $website_url = 'https://twitter.com/' . preg_replace( '/^@/', '', $website_url ); } break; case 'url': case 'website': $website_url = get_the_author_meta( 'url', $user_id ); break; default: $website_url = get_the_author_meta( $meta_key, $user_id ); break; } $website_url = trim( $website_url ); // Just in case. } elseif ( $this->p->debug->enabled ) { $this->p->debug->log( 'user id ' . $user_id . ' is not a WordPress user' ); } $website_url = apply_filters( 'wpsso_get_author_website', $website_url, $user_id, $meta_key, $user_exists ); return $local_fifo[ $user_id ][ $meta_key ] = (string) $website_url; } /* * WpssoUser class specific methods. * * Called by WpssoOpenGraph->get_array() for a single post author and (possibly) several coauthors. */ public function get_authors_websites( $users_ids, $meta_key = 'url' ) { $urls = array(); if ( empty( $users_ids ) ) { // Just in case. return $urls; } if ( ! is_array( $users_ids ) ) { $users_ids = array( $users_ids ); } if ( $meta_key && 'none' !== $meta_key ) { // Just in case. foreach ( $users_ids as $user_id ) { if ( empty( $user_id ) ) { continue; } $value = $this->get_author_website( $user_id, $meta_key ); // Returns a single URL string. if ( ! empty( $value ) ) { // Make sure we don't add empty values. $urls[] = $value; } } } return $urls; } /* * Called by the WpssoRegister::uninstall_plugin() method. * * Do not use Wpsso::get_instance() since the Wpsso class may not exist. */ public static function delete_metabox_prefs( $user_id = false, $slug_prefix = 'wpsso' ) { $cf = WpssoConfig::get_config(); $user_id = empty( $user_id ) ? get_current_user_id() : $user_id; $parent_slug = 'options-general.php'; if ( ! empty( $cf[ '*' ][ 'lib' ][ 'settings' ] ) ) { foreach ( array_keys( $cf[ '*' ][ 'lib' ][ 'settings' ] ) as $lib_id ) { $menu_slug = $slug_prefix . '-' . $lib_id; self::delete_metabox_pagehook( $user_id, $menu_slug, $parent_slug ); } } if ( ! empty( $cf[ '*' ][ 'lib' ][ 'submenu' ] ) ) { $parent_slug = $slug_prefix . '-' . key( $cf[ '*' ][ 'lib' ][ 'submenu' ] ); foreach ( array_keys( $cf[ '*' ][ 'lib' ][ 'submenu' ] ) as $lib_id ) { $menu_slug = $slug_prefix . '-' . $lib_id; self::delete_metabox_pagehook( $user_id, $menu_slug, $parent_slug ); } } } private static function delete_metabox_pagehook( $user_id, $menu_slug, $parent_slug ) { $pagehook = get_plugin_page_hookname( $menu_slug, $parent_slug); foreach ( array( 'meta-box-order', 'metaboxhidden', 'closedpostboxes' ) as $mb_state ) { $meta_key = $mb_state . '_' . $pagehook; if ( false === $user_id ) { $users_args = array( 'role' => 'contributor', // Contributors can delete_posts, edit_posts, read. 'order' => 'DESC', // Newest user first. 'orderby' => 'ID', 'meta_key' => $meta_key, // The meta_key in the wp_usermeta table. 'fields' => array( // Save memory and only return only specific fields. 'ID', ), ); foreach ( get_users( $users_args ) as $user_obj ) { if ( ! empty( $user_obj->ID ) ) { // Just in case. /* * Deletes user option with global blog capability. * * User options are just like user metadata except that they have support * for global blog options. If the 'is_global' parameter is false, which it * is by default, it will prepend the WordPress table prefix to the option * name. */ delete_user_option( $user_obj->ID, $meta_key, $global = false ); delete_user_option( $user_obj->ID, $meta_key, $global = true ); } } } elseif ( is_numeric( $user_id ) ) { delete_user_option( $user_id, $meta_key, $global = false ); delete_user_option( $user_id, $meta_key, $global = true ); } } } public static function is_metabox_hidden( $metabox_id, $screen_id = '', $user_id = null ) { $screen_id = empty( $screen_id ) ? SucomUtilWP::get_screen_id() : $screen_id; $user_id = empty( $user_id ) ? get_current_user_id() : $user_id; $md_key = SucomUtil::sanitize_hookname( 'metaboxhidden_' . $screen_id ); $md = get_metadata( 'user', $user_id, $md_key, $single = true ); return is_array( $md ) && in_array( $metabox_id, $md ) ? true : false; } public static function is_show_all( $user_id = false ) { return self::show_opts( 'all', $user_id ); } public static function get_show_val( $user_id = false ) { return self::show_opts( false, $user_id ); } /* * Returns the value for show_opts, or return true/false if a value to compare is provided. */ public static function show_opts( $compare = false, $user_id = false ) { $user_id = empty( $user_id ) ? get_current_user_id() : $user_id; $show_opts = self::get_pref( 'show_opts' ); if ( $compare ) { return $compare === $show_opts ? true : false; } return $show_opts; } public static function get_pref( $pref_key = false, $user_id = false ) { $user_id = empty( $user_id ) ? get_current_user_id() : $user_id; if ( ! isset( self::$cache_user_prefs[ $user_id ][ 'prefs_filtered' ] ) || ! self::$cache_user_prefs[ $user_id ][ 'prefs_filtered' ] ) { $wpsso =& Wpsso::get_instance(); self::$cache_user_prefs[ $user_id ] = self::get_meta( $user_id, WPSSO_PREF_NAME, $single = true ); if ( ! is_array( self::$cache_user_prefs[ $user_id ] ) ) { self::$cache_user_prefs[ $user_id ] = array(); } self::$cache_user_prefs[ $user_id ][ 'prefs_filtered' ] = true; // Set before calling filter to prevent recursion. self::$cache_user_prefs[ $user_id ] = apply_filters( 'wpsso_get_user_pref', self::$cache_user_prefs[ $user_id ], $user_id ); if ( ! isset( self::$cache_user_prefs[ $user_id ][ 'show_opts' ] ) ) { self::$cache_user_prefs[ $user_id ][ 'show_opts' ] = $wpsso->options[ 'plugin_show_opts' ]; } if ( $wpsso->debug->enabled ) { $wpsso->debug->log_arr( 'cache_user_prefs', self::$cache_user_prefs[ $user_id ] ); } } if ( false !== $pref_key ) { if ( isset( self::$cache_user_prefs[ $user_id ][ $pref_key ] ) ) { return self::$cache_user_prefs[ $user_id ][ $pref_key ]; } return false; } return self::$cache_user_prefs[ $user_id ]; } public static function save_pref( $user_prefs, $user_id = false ) { $user_id = empty( $user_id ) ? get_current_user_id() : $user_id; if ( ! current_user_can( 'edit_user', $user_id ) ) { return false; } if ( ! is_array( $user_prefs ) || empty( $user_prefs ) ) { return false; } $old_prefs = self::get_pref( false, $user_id ); // get all prefs for user $new_prefs = array_merge( $old_prefs, $user_prefs ); /* * Don't bother saving unless we have to. */ if ( $old_prefs !== $new_prefs ) { self::$cache_user_prefs[ $user_id ] = $new_prefs; // update the pref cache unset( $new_prefs[ 'prefs_filtered' ] ); self::update_meta( $user_id, WPSSO_PREF_NAME, $new_prefs ); return true; } return false; } /* * Use $rel = false to extend WpssoAbstractWpMeta->clear_cache(). */ public function clear_cache( $user_id, $rel = false ) { if ( $this->p->debug->enabled ) { $this->p->debug->log_args( array( 'user_id' => $user_id, ) ); } static $do_once = array(); // Just in case - prevent recursion. if ( isset( $do_once[ $user_id ] ) ) return; // Stop here. $do_once[ $user_id ] = true; if ( empty( $user_id ) ) return; // Just in case. $mod = $this->get_mod( $user_id ); $this->clear_mod_cache( $mod ); do_action( 'wpsso_clear_user_cache', $user_id, $mod ); } /* * Refresh the cache for a single user ID. * * Use $rel = false to extend WpssoAbstractWpMeta->refresh_cache(). */ public function refresh_cache( $user_id, $rel = false ) { if ( $this->p->debug->enabled ) { $this->p->debug->log_args( array( 'user_id' => $user_id, ) ); } static $do_once = array(); // Just in case - prevent recursion. if ( isset( $do_once[ $user_id ] ) ) return; // Stop here. $do_once[ $user_id ] = true; if ( empty( $user_id ) ) return; // Just in case. $mod = $this->get_mod( $user_id ); $this->p->util->cache->refresh_mod_head_meta( $mod ); do_action( 'wpsso_refresh_user_cache', $user_id, $mod ); } /* * Check user capability for the user id. * * Use $rel = false to extend WpssoAbstractWpMeta->user_can_edit(). */ public function user_can_edit( $user_id, $rel = false ) { $capability = 'edit_user'; if ( ! current_user_can( $capability, $user_id ) ) { if ( $this->p->debug->enabled ) { $this->p->debug->log( 'exiting early: cannot ' . $capability . ' for user id ' . $user_id ); } /* * Add notice only if the admin notices have not already been shown. */ if ( $this->p->notice->is_admin_pre_notices() ) { $this->p->notice->err( sprintf( __( 'Insufficient privileges to edit user ID %1$s.', 'wpsso' ), $user_id ) ); } return false; } return true; } /* * Returns an array of single image associative arrays. * * $md_pre can be a text string or array of prefixes. */ public function get_og_images( $num, $size_names, $user_id, $md_pre = 'og', $mt_pre = 'og' ) { if ( $this->p->debug->enabled ) { $this->p->debug->mark(); } $mod = $this->get_mod( $user_id ); $user_exists = SucomUtilWP::user_exists( $user_id ); // Check if this is a valid WordPress user. $filter_name = 'wpsso_get_other_user_images'; if ( $user_exists ) { if ( $this->p->debug->enabled ) { $this->p->debug->log( 'skipping filters "' . $filter_name . '" (user exists)' ); } return $this->get_md_images( $num, $size_names, $mod, $md_pre, $mt_pre ); } if ( $this->p->debug->enabled ) { $this->p->debug->log( 'applying filters "' . $filter_name . '"' ); } return apply_filters( $filter_name, array(), $num, $size_names, $user_id, $md_pre ); } /* * Schedule the addition of user roles for self::get_public_ids(). */ public function schedule_add_person_role( $user_id = null ) { $user_id = $this->p->util->maybe_change_user_id( $user_id ); // Maybe change textdomain for user id. $task_name = 'add the Person role'; $task_name_transl = _x( 'add the Person role', 'task name', 'wpsso' ); $event_time = time() + WPSSO_SCHEDULE_SINGLE_EVENT_TIME; // Default event time is now + 10 seconds. $human_time = human_time_diff( 0, WPSSO_SCHEDULE_SINGLE_EVENT_TIME ); $event_hook = 'wpsso_add_person_role'; $event_args = array( $user_id ); if ( $user_id ) { // Just in case. $notice_msg = sprintf( __( 'A background task will begin in the next %1$s to %2$s for content creators.', 'wpsso' ), $human_time, $task_name_transl ); $notice_key = $task_name . '-scheduled'; $this->p->notice->upd( $notice_msg, $user_id, $notice_key ); } wp_schedule_single_event( $event_time, $event_hook, $event_args ); } public function add_admin_bar_menu_view_profile( &$wp_admin_bar ) { // Pass by reference OK. if ( ! is_admin() ) { // Just in case. return; } $screen_id = SucomUtilWP::get_screen_id(); switch ( $screen_id ) { case 'profile': // User profile page. case ( 0 === strpos( $screen_id, 'profile_page_' ) ? true : false ): // Your profile page. case ( 0 === strpos( $screen_id, 'users_page_' . $this->p->id ) ? true : false ): // Profile SSO page. $user_id = SucomUtilWP::get_user_object( false, 'id' ); $mod = $this->get_mod( $user_id ); break; default: return false; } if ( $mod[ 'is_user' ] ) { $parent_id = 'wpsso-view-profile'; $menu_title = _x( 'View Profile', 'toolbar menu title', 'wpsso' ); $canonical_url = $this->p->util->get_canonical_url( $mod ); $wp_admin_bar->add_node( array( 'id' => $parent_id, 'title' => $menu_title, 'parent' => false, 'href' => $canonical_url, 'group' => false, ) ); return $parent_id; } return false; } public function add_person_role( $user_id = null ) { if ( $this->p->debug->enabled ) { $this->p->debug->mark(); } $user_id = $this->p->util->maybe_change_user_id( $user_id ); // Maybe change textdomain for user id. $role_label_transl = _x( 'Person', 'user role', 'wpsso' ); $task_name = 'add the Person role'; $task_name_transl = _x( 'add the Person role', 'task name', 'wpsso' ); if ( ! $this->p->util->cache->task_start( $user_id, $task_name, WPSSO_ADD_ROLE_MAX_TIME ) ) { return; // Stop here - background task already running. } if ( $user_id ) { $mtime_start = microtime( $get_float = true ); $time_on_date = SucomUtil::sprintf_date_time( _x( '%2$s on %1$s', 'time on date', 'wpsso' ) ); $notice_msg = sprintf( __( 'A task to %1$s to content creators was started at %2$s.', 'wpsso' ), $role_label_transl, $time_on_date ); $notice_key = $task_name . '-task-info'; $this->p->notice->inf( $notice_msg, $user_id, $notice_key ); } if ( 0 === get_current_user_id() ) { // User is the scheduler. $this->p->util->cache->set_task_limit( $user_id, $task_name, WPSSO_ADD_ROLE_MAX_TIME ); } if ( defined( 'DOING_CRON' ) && DOING_CRON ) { /* * Register image sizes and include WooCommerce front-end libs. */ do_action( 'wpsso_scheduled_task_started', $user_id ); } $count = 0; $users_ids = self::get_public_ids(); // Aka 'administrator', 'editor', 'author', and 'contributor'. foreach ( $users_ids as $id ) { $count += self::add_role_by_id( $id, $role = 'person' ); } unset( $users_ids ); if ( $user_id ) { $mtime_total = microtime( $get_float = true ) - $mtime_start; $human_time = human_time_diff( 0, $mtime_total ); $notice_msg = sprintf( __( 'The %1$s role has been added to %2$d content creators.', 'wpsso' ), $role_label_transl, $count ) . ' '; $notice_msg .= sprintf( __( 'The total execution time for this task was %s.', 'wpsso' ), $human_time ) . ' '; $notice_key = $task_name . '-task-info'; $this->p->notice->inf( $notice_msg, $user_id, $notice_key ); } $this->p->util->cache->task_end( $user_id, $task_name ); } /* * Schedule the removal of user roles for self::get_public_ids(). */ public function schedule_remove_person_role( $user_id = null ) { $user_id = $this->p->util->maybe_change_user_id( $user_id ); // Maybe change textdomain for user id. $task_name = 'remove the Person role'; $task_name_transl = _x( 'remove the Person role', 'task name', 'wpsso' ); $event_time = time() + WPSSO_SCHEDULE_SINGLE_EVENT_TIME; // Default event time is now + 10 seconds. $human_time = human_time_diff( 0, WPSSO_SCHEDULE_SINGLE_EVENT_TIME ); $event_hook = 'wpsso_remove_person_role'; $event_args = array( $user_id ); if ( $user_id ) { // Just in case. $notice_msg = sprintf( __( 'A background task will begin in the next %1$s to %2$s from all users.', 'wpsso' ), $human_time, $task_name_transl ); $notice_key = $task_name . '-scheduled'; $this->p->notice->upd( $notice_msg, $user_id, $notice_key ); } wp_schedule_single_event( $event_time, $event_hook, $event_args ); } public function remove_person_role( $user_id = null ) { if ( $this->p->debug->enabled ) { $this->p->debug->mark(); } $user_id = $this->p->util->maybe_change_user_id( $user_id ); // Maybe change textdomain for user id. $role_label_transl = _x( 'Person', 'user role', 'wpsso' ); $task_name = 'remove the Person role'; $task_name_transl = _x( 'remove the Person role', 'task name', 'wpsso' ); if ( ! $this->p->util->cache->task_start( $user_id, $task_name, WPSSO_REMOVE_ROLE_MAX_TIME ) ) { return; // Stop here - background task already running. } if ( $user_id ) { $mtime_start = microtime( $get_float = true ); $time_on_date = SucomUtil::sprintf_date_time( _x( '%2$s on %1$s', 'time on date', 'wpsso' ) ); $notice_msg = sprintf( __( 'A task to %1$s from all users was started at %2$s.', 'wpsso' ), $role_label_transl, $time_on_date ); $notice_key = $task_name . '-task-info'; $this->p->notice->inf( $notice_msg, $user_id, $notice_key ); } if ( 0 === get_current_user_id() ) { // User is the scheduler. $this->p->util->cache->set_task_limit( $user_id, $task_name, WPSSO_REMOVE_ROLE_MAX_TIME ); } if ( defined( 'DOING_CRON' ) && DOING_CRON ) { /* * Register image sizes and include WooCommerce front-end libs. */ do_action( 'wpsso_scheduled_task_started', $user_id ); } $count = 0; $blog_id = get_current_blog_id(); while ( $users_ids = SucomUtilWP::get_users_ids( $blog_id, $role = '', $limit = 1000 ) ) { // Get a maximum of 1000 user ids at a time. foreach ( $users_ids as $id ) { $count += self::remove_role_by_id( $id, $role = 'person' ); } } unset( $users_ids ); if ( $user_id ) { $mtime_total = microtime( $get_float = true ) - $mtime_start; $human_time = human_time_diff( 0, $mtime_total ); $notice_msg = sprintf( __( 'The %1$s role has been removed from %2$d users.', 'wpsso' ), $role_label_transl, $count ) . ' '; $notice_msg .= sprintf( __( 'The total execution time for this task was %s.', 'wpsso' ), $human_time ); $notice_key = $task_name . '-task-info'; $this->p->notice->inf( $notice_msg, $user_id, $notice_key ); } $this->p->util->cache->task_end( $user_id, $task_name ); } /* * Hooked to the 'wpmu_new_user' and 'user_register' actions, which only provides a single argument. */ public static function add_role_by_id( $user_id, $role = 'person' ) { $user_obj = get_user_by( 'ID', $user_id ); if ( ! in_array( $role, $user_obj->roles ) ) { $user_obj->add_role( $role ); // Method does not return anything - assume it worked. return 1; } return 0; } public static function remove_role_by_id( $user_id, $role = 'person' ) { $user_obj = get_user_by( 'ID', $user_id ); if ( in_array( $role, $user_obj->roles ) ) { $user_obj->remove_role( $role ); // Method does not return anything - assume it worked. return 1; } return 0; } public static function get_persons_names( $add_none = true, $roles_id = 'person' ) { $wpsso =& Wpsso::get_instance(); $users = array(); if ( isset( $wpsso->cf[ 'wp' ][ 'roles' ][ $roles_id ] ) ) { // Just in case. $roles = $wpsso->cf[ 'wp' ][ 'roles' ][ $roles_id ]; $users = SucomUtilWP::get_roles_users_select( $roles, $blog_id = null, $add_none ); $users = array_slice( $users, 0, SucomUtil::get_const( 'WPSSO_SELECT_PERSON_NAMES_MAX', 200 ), $preserve_keys = true ); } return $users; } public function add_person_view( $user_views ) { $user_views = array_reverse( $user_views ); $all_view_link = $user_views[ 'all' ]; unset( $user_views[ 'all' ], $user_views[ 'person' ] ); $role_label_transl = _x( 'Person', 'user role', 'wpsso' ); $role_view = add_query_arg( 'role', 'person', admin_url( 'users.php' ) ); $user_query = new WP_User_Query( array( 'role' => 'person' ) ); $user_count = $user_query->get_total(); $user_views[ 'person' ] = '' . $role_label_transl . ' (' . $user_count . ')'; $user_views[ 'all' ] = $all_view_link; $user_views = array_reverse( $user_views ); return $user_views; } private function get_user_about_meta_keys( $about_key ) { $meta_keys = array(); if ( 'award' === $about_key ) { if ( $awards_max = SucomUtil::get_const( 'WPSSO_SCHEMA_AWARDS_MAX' ) ) { foreach ( range( 0, $awards_max - 1, 1 ) as $key_num ) { $meta_keys[] = $about_key . '_' . $key_num; } } } else $meta_keys[] = $about_key; return $meta_keys; } /* * If $meta_key is en empty string, retrieves all metadata for the specified object ID. * * See https://developer.wordpress.org/reference/functions/get_metadata/. */ public static function get_meta( $user_id, $meta_key = '', $single = false ) { return get_metadata( 'user', $user_id, $meta_key, $single ); } public static function update_meta( $user_id, $meta_key, $value ) { return update_metadata( 'user', $user_id, $meta_key, $value ); } public static function delete_meta( $user_id, $meta_key ) { return delete_metadata( 'user', $user_id, $meta_key ); } } }