diff --git a/includes/admin/class-admin.php b/includes/admin/class-admin.php index c4cdf0e3..0afb0a04 100644 --- a/includes/admin/class-admin.php +++ b/includes/admin/class-admin.php @@ -1809,6 +1809,9 @@ if ( ! class_exists( 'um\admin\Admin' ) ) { 'post_title' => sprintf( __( 'Duplicate of %s', 'ultimate-member' ), get_the_title( $post_id ) ), 'post_status' => 'publish', 'post_author' => get_current_user_id(), + 'meta_input' => array( + '_um_mode' => get_post_meta( $post_id, '_um_mode', true ), + ), ); $n_id = wp_insert_post( $n ); diff --git a/includes/admin/core/class-admin-settings.php b/includes/admin/core/class-admin-settings.php index 74af0edc..2e363783 100644 --- a/includes/admin/core/class-admin-settings.php +++ b/includes/admin/core/class-admin-settings.php @@ -3070,8 +3070,10 @@ if ( ! class_exists( 'um\admin\core\Admin_Settings' ) ) { $error_codes = $license->get_error_codes(); if ( ! empty( $error_codes ) ) { foreach ( $error_codes as $error_code ) { + $error_code_messages = $license->get_error_messages( $error_code ); + $error_code_messages = implode( ', ', $error_code_messages ); // translators: %1$s is an error code; %2$s is an error message. - $errors_data[] = sprintf( __( 'code: %1$s, message: %2$s;', 'ultimate-member' ), $error_code, $license->get_error_messages( $error_code ) ); + $errors_data[] = sprintf( __( 'code: %1$s, message: %2$s;', 'ultimate-member' ), $error_code, $error_code_messages ); } } $errors_data = ! empty( $errors_data ) ? implode( ' ', $errors_data ) : ''; diff --git a/includes/class-config.php b/includes/class-config.php index 3d3039a5..5391f9c1 100644 --- a/includes/class-config.php +++ b/includes/class-config.php @@ -279,21 +279,153 @@ if ( ! class_exists( 'um\Config' ) ) { $this->core_form_meta_all = apply_filters( 'um_core_form_meta_all', $this->core_form_meta_all ); $this->core_form_meta['register'] = array( - '_um_custom_fields' => 'a:6:{s:10:"user_login";a:15:{s:5:"title";s:8:"Username";s:7:"metakey";s:10:"user_login";s:4:"type";s:4:"text";s:5:"label";s:8:"Username";s:8:"required";i:1;s:6:"public";i:1;s:8:"editable";b:0;s:8:"validate";s:15:"unique_username";s:9:"min_chars";i:3;s:9:"max_chars";i:24;s:8:"position";s:1:"1";s:6:"in_row";s:9:"_um_row_1";s:10:"in_sub_row";s:1:"0";s:9:"in_column";s:1:"1";s:8:"in_group";s:0:"";}s:10:"user_email";a:13:{s:5:"title";s:14:"Email Address";s:7:"metakey";s:10:"user_email";s:4:"type";s:4:"text";s:5:"label";s:14:"E-mail Address";s:8:"required";i:0;s:6:"public";i:1;s:8:"editable";b:1;s:8:"validate";s:12:"unique_email";s:8:"position";s:1:"4";s:6:"in_row";s:9:"_um_row_1";s:10:"in_sub_row";s:1:"0";s:9:"in_column";s:1:"1";s:8:"in_group";s:0:"";}s:13:"user_password";a:16:{s:5:"title";s:8:"Password";s:7:"metakey";s:13:"user_password";s:4:"type";s:8:"password";s:5:"label";s:8:"Password";s:8:"required";i:1;s:6:"public";i:1;s:8:"editable";b:1;s:9:"min_chars";i:8;s:9:"max_chars";i:30;s:15:"force_good_pass";i:1;s:18:"force_confirm_pass";i:1;s:8:"position";s:1:"5";s:6:"in_row";s:9:"_um_row_1";s:10:"in_sub_row";s:1:"0";s:9:"in_column";s:1:"1";s:8:"in_group";s:0:"";}s:10:"first_name";a:12:{s:5:"title";s:10:"First Name";s:7:"metakey";s:10:"first_name";s:4:"type";s:4:"text";s:5:"label";s:10:"First Name";s:8:"required";i:0;s:6:"public";i:1;s:8:"editable";b:1;s:8:"position";s:1:"2";s:6:"in_row";s:9:"_um_row_1";s:10:"in_sub_row";s:1:"0";s:9:"in_column";s:1:"1";s:8:"in_group";s:0:"";}s:9:"last_name";a:12:{s:5:"title";s:9:"Last Name";s:7:"metakey";s:9:"last_name";s:4:"type";s:4:"text";s:5:"label";s:9:"Last Name";s:8:"required";i:0;s:6:"public";i:1;s:8:"editable";b:1;s:8:"position";s:1:"3";s:6:"in_row";s:9:"_um_row_1";s:10:"in_sub_row";s:1:"0";s:9:"in_column";s:1:"1";s:8:"in_group";s:0:"";}s:9:"_um_row_1";a:4:{s:4:"type";s:3:"row";s:2:"id";s:9:"_um_row_1";s:8:"sub_rows";s:1:"1";s:4:"cols";s:1:"1";}}', + '_um_custom_fields' => array( + 'user_login' => array( + 'title' => __( 'Username', 'ultimate-member' ), + 'metakey' => 'user_login', + 'type' => 'text', + 'label' => __( 'Username', 'ultimate-member' ), + 'required' => 1, + 'public' => 1, + 'editable' => false, + 'validate' => 'unique_username', + 'min_chars' => 3, + 'max_chars' => 24, + 'position' => '1', + 'in_row' => '_um_row_1', + 'in_sub_row' => '0', + 'in_column' => '1', + 'in_group' => '', + ), + 'user_email' => array( + 'title' => __( 'E-mail Address', 'ultimate-member' ), + 'metakey' => 'user_email', + 'type' => 'text', + 'label' => __( 'E-mail Address', 'ultimate-member' ), + 'required' => 0, + 'public' => 1, + 'editable' => true, + 'validate' => 'unique_email', + 'position' => '4', + 'in_row' => '_um_row_1', + 'in_sub_row' => '0', + 'in_column' => '1', + 'in_group' => '', + ), + 'user_password' => array( + 'title' => __( 'Password', 'ultimate-member' ), + 'metakey' => 'user_password', + 'type' => 'password', + 'label' => __( 'Password', 'ultimate-member' ), + 'required' => 1, + 'public' => 1, + 'editable' => true, + 'min_chars' => 8, + 'max_chars' => 30, + 'force_good_pass' => 1, + 'force_confirm_pass' => 1, + 'position' => '5', + 'in_row' => '_um_row_1', + 'in_sub_row' => '0', + 'in_column' => '1', + 'in_group' => '', + ), + 'first_name' => array( + 'title' => __( 'First Name', 'ultimate-member' ), + 'metakey' => 'first_name', + 'type' => 'text', + 'label' => __( 'First Name', 'ultimate-member' ), + 'required' => 0, + 'public' => 1, + 'editable' => true, + 'position' => '2', + 'in_row' => '_um_row_1', + 'in_sub_row' => '0', + 'in_column' => '1', + 'in_group' => '', + ), + 'last_name' => array( + 'title' => __( 'Last Name', 'ultimate-member' ), + 'metakey' => 'last_name', + 'type' => 'text', + 'label' => __( 'Last Name', 'ultimate-member' ), + 'required' => 0, + 'public' => 1, + 'editable' => true, + 'position' => '3', + 'in_row' => '_um_row_1', + 'in_sub_row' => '0', + 'in_column' => '1', + 'in_group' => '', + ), + '_um_row_1' => array( + 'type' => 'row', + 'id' => '_um_row_1', + 'sub_rows' => '1', + 'cols' => '1', + ), + ), '_um_mode' => 'register', '_um_core' => 'register', '_um_register_use_custom_settings' => 0, ); $this->core_form_meta['login'] = array( - '_um_custom_fields' => 'a:3:{s:8:"username";a:13:{s:5:"title";s:18:"Username or Email";s:7:"metakey";s:8:"username";s:4:"type";s:4:"text";s:5:"label";s:18:"Username or E-mail";s:8:"required";i:1;s:6:"public";i:1;s:8:"editable";b:0;s:8:"validate";s:24:"unique_username_or_email";s:8:"position";s:1:"1";s:6:"in_row";s:9:"_um_row_1";s:10:"in_sub_row";s:1:"0";s:9:"in_column";s:1:"1";s:8:"in_group";s:0:"";}s:13:"user_password";a:16:{s:5:"title";s:8:"Password";s:7:"metakey";s:13:"user_password";s:4:"type";s:8:"password";s:5:"label";s:8:"Password";s:8:"required";i:1;s:6:"public";i:1;s:8:"editable";b:1;s:9:"min_chars";i:8;s:9:"max_chars";i:30;s:15:"force_good_pass";i:1;s:18:"force_confirm_pass";i:1;s:8:"position";s:1:"2";s:6:"in_row";s:9:"_um_row_1";s:10:"in_sub_row";s:1:"0";s:9:"in_column";s:1:"1";s:8:"in_group";s:0:"";}s:9:"_um_row_1";a:4:{s:4:"type";s:3:"row";s:2:"id";s:9:"_um_row_1";s:8:"sub_rows";s:1:"1";s:4:"cols";s:1:"1";}}', + '_um_custom_fields' => array( + 'username' => array( + 'title' => __( 'Username or E-mail', 'ultimate-member' ), + 'metakey' => 'username', + 'type' => 'text', + 'label' => __( 'Username or E-mail', 'ultimate-member' ), + 'required' => 1, + 'public' => 1, + 'editable' => false, + 'validate' => 'unique_username_or_email', + 'position' => '1', + 'in_row' => '_um_row_1', + 'in_sub_row' => '0', + 'in_column' => '1', + 'in_group' => '', + ), + 'user_password' => array( + 'title' => __( 'Password', 'ultimate-member' ), + 'metakey' => 'user_password', + 'type' => 'password', + 'label' => __( 'Password', 'ultimate-member' ), + 'required' => 1, + 'public' => 1, + 'editable' => true, + 'min_chars' => 8, + 'max_chars' => 30, + 'force_good_pass' => 1, + 'force_confirm_pass' => 1, + 'position' => '2', + 'in_row' => '_um_row_1', + 'in_sub_row' => '0', + 'in_column' => '1', + 'in_group' => '', + ), + '_um_row_1' => array( + 'type' => 'row', + 'id' => '_um_row_1', + 'sub_rows' => '1', + 'cols' => '1', + ), + ), '_um_mode' => 'login', '_um_core' => 'login', '_um_login_use_custom_settings' => 0, ); $this->core_form_meta['profile'] = array( - '_um_custom_fields' => 'a:1:{s:9:"_um_row_1";a:4:{s:4:"type";s:3:"row";s:2:"id";s:9:"_um_row_1";s:8:"sub_rows";s:1:"1";s:4:"cols";s:1:"1";}}', + '_um_custom_fields' => array( + '_um_row_1' => array( + 'type' => 'row', + 'id' => '_um_row_1', + 'sub_rows' => '1', + 'cols' => '1', + ), + ), '_um_mode' => 'profile', '_um_core' => 'profile', '_um_profile_use_custom_settings' => 0, diff --git a/includes/core/class-member-directory-meta.php b/includes/core/class-member-directory-meta.php index 8460f520..8df10b14 100644 --- a/includes/core/class-member-directory-meta.php +++ b/includes/core/class-member-directory-meta.php @@ -959,7 +959,8 @@ if ( ! class_exists( 'um\core\Member_Directory_Meta' ) ) { } elseif ( 'last_login' === $sortby ) { $this->joins[] = "LEFT JOIN {$wpdb->prefix}um_metadata umm_sort ON ( umm_sort.user_id = u.ID AND umm_sort.um_key = '_um_last_login' )"; - $this->sql_order = ' ORDER BY CAST( umm_sort.um_value AS DATETIME ) DESC '; + $this->joins[] = "LEFT JOIN {$wpdb->prefix}um_metadata umm_show_login ON ( umm_show_login.user_id = u.ID AND umm_show_login.um_key = 'um_show_last_login' )"; + $this->sql_order = $wpdb->prepare( ' ORDER BY CASE ISNULL(NULLIF(umm_show_login.um_value,%s)) WHEN 0 THEN %s ELSE CAST( umm_sort.um_value AS DATETIME ) END DESC ', 'a:1:{i:0;s:3:"yes";}', '1970-01-01 00:00:00' ); } elseif ( 'last_first_name' === $sortby ) { @@ -1051,6 +1052,16 @@ if ( ! class_exists( 'um\core\Member_Directory_Meta' ) ) { $sql_where = implode( ' AND ', $this->where_clauses ); $sql_where = ! empty( $sql_where ) ? 'AND ' . $sql_where : ''; + $query = array( + 'select' => $this->select, + 'sql_where' => $sql_where, + 'having' => $this->having, + 'sql_limit' => $this->sql_limit, + ); + + /** This filter is documented in includes/core/class-member-directory.php */ + do_action( 'um_user_before_query', $query, $this ); + /* * * SQL_CALC_FOUND_ROWS is deprecated as of MySQL 8.0.17 @@ -1068,13 +1079,6 @@ if ( ! class_exists( 'um\core\Member_Directory_Meta' ) ) { {$this->sql_limit}" ); - $query = array( - 'select' => $this->select, - 'sql_where' => $sql_where, - 'having' => $this->having, - 'sql_limit' => $this->sql_limit, - ); - $total_users = (int) $wpdb->get_var( 'SELECT FOUND_ROWS()' ); /** diff --git a/includes/core/class-member-directory.php b/includes/core/class-member-directory.php index 5ff16b8f..d9cdea0e 100644 --- a/includes/core/class-member-directory.php +++ b/includes/core/class-member-directory.php @@ -1463,7 +1463,8 @@ if ( ! class_exists( 'um\core\Member_Directory' ) ) { unset( $this->query_args['order'] ); } elseif ( 'last_login' === $sortby ) { - $this->query_args['orderby'] = array( 'um_last_login' => 'DESC' ); + $this->query_args['orderby'] = array( 'um_last_login' => 'DESC' ); + // Please use custom meta table for better results and sorting. Here we only hide the users without visible last login date. $this->query_args['meta_query'][] = array( 'relation' => 'OR', array( @@ -1478,6 +1479,8 @@ if ( ! class_exists( 'um\core\Member_Directory' ) ) { ), ); unset( $this->query_args['order'] ); + + add_filter( 'pre_user_query', array( &$this, 'sortby_last_login' ) ); } elseif ( $sortby == 'last_first_name' ) { $this->query_args['meta_query'][] = array( @@ -1678,6 +1681,24 @@ if ( ! class_exists( 'um\core\Member_Directory' ) ) { return $query; } + + /** + * Sorting by last login + * + * @param object $query + * + * @return mixed + */ + public function sortby_last_login( $query ) { + if ( array_key_exists( 'um_last_login', $query->query_vars['orderby'] ) ) { + global $wpdb; + $query->query_from .= " LEFT JOIN {$wpdb->prefix}usermeta AS umm_sort ON ( umm_sort.user_id = {$wpdb->prefix}users.ID AND umm_sort.meta_key = '_um_last_login' ) "; + $query->query_from .= " LEFT JOIN {$wpdb->prefix}usermeta AS umm_show_login ON ( umm_show_login.user_id = {$wpdb->prefix}users.ID AND umm_show_login.meta_key = 'um_show_last_login' ) "; + $query->query_orderby = " ORDER BY CASE ISNULL(NULLIF(umm_show_login.meta_value,'a:1:{i:0;s:3:\"yes\";}')) WHEN 0 THEN '1970-01-01 00:00:00' ELSE CAST( umm_sort.meta_value AS DATETIME ) END DESC "; + } + return $query; + } + /** * Prepare the search line. Avoid the using mySQL statement. * diff --git a/includes/core/class-setup.php b/includes/core/class-setup.php index ffa3ed9d..27a342eb 100644 --- a/includes/core/class-setup.php +++ b/includes/core/class-setup.php @@ -97,13 +97,8 @@ KEY meta_value_indx (um_value(191)) $form_id = wp_insert_post( $form ); - foreach ( UM()->config()->core_form_meta[ $id ] as $key => $value ) { - if ( '_um_custom_fields' === $key ) { - $array = maybe_unserialize( $value ); - update_post_meta( $form_id, $key, $array ); - } else { - update_post_meta( $form_id, $key, $value ); - } + foreach ( UM()->config()->core_form_meta[ $id ] as $meta_key => $meta_value ) { + update_post_meta( $form_id, $meta_key, $meta_value ); } $core_forms[ $id ] = $form_id; @@ -132,13 +127,8 @@ KEY meta_value_indx (um_value(191)) $form_id = wp_insert_post( $form ); - foreach ( UM()->config()->core_directory_meta[ $id ] as $key => $value ) { - if ( '_um_custom_fields' === $key ) { - $array = maybe_unserialize( $value ); - update_post_meta( $form_id, $key, $array ); - } else { - update_post_meta( $form_id, $key, $value ); - } + foreach ( UM()->config()->core_directory_meta[ $id ] as $meta_key => $meta_value ) { + update_post_meta( $form_id, $meta_key, $meta_value ); } $core_directories[ $id ] = $form_id; diff --git a/includes/core/class-uploader.php b/includes/core/class-uploader.php index 19f6e28f..9ef60e96 100644 --- a/includes/core/class-uploader.php +++ b/includes/core/class-uploader.php @@ -1300,18 +1300,16 @@ if ( ! class_exists( 'um\core\Uploader' ) ) { } $submitted = get_user_meta( $user_id, 'submitted', true ); - $submitted = ! empty( $submitted ) ? $submitted : array(); + $submitted = ( ! empty( $submitted ) && is_array( $submitted ) ) ? $submitted : array(); $submitted[ $key ] = $new_filename; update_user_meta( $user_id, 'submitted', $submitted ); if ( $move_only ) { - $file = $user_basedir . DIRECTORY_SEPARATOR . $filename; if ( rename( $temp_file_path, $file ) ) { $new_files[ $key ] = $filename; } - } else { $file = $user_basedir . DIRECTORY_SEPARATOR . $new_filename; diff --git a/readme.txt b/readme.txt index e1bb84a7..4394296f 100644 --- a/readme.txt +++ b/readme.txt @@ -181,6 +181,7 @@ IMPORTANT: PLEASE UPDATE THE PLUGIN TO AT LEAST VERSION 2.6.7 IMMEDIATELY. VERSI * Fixed: YouTube validation when field value is empty * Fixed: Social URLs sanitizing where user can put his social username (e.g. Instagram, Facebook) * Fixed: Using only published forms and member directories IDs on predefined pages installation +* Fixed: Member Directory before query hook when custom meta table is active = 2.8.5 2024-04-09 =