diff --git a/README.md b/README.md index d4f28e78..86c2f833 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ Ultimate Member is the #1 user profile & membership plugin for WordPress. The pl | Latest Version |Requires at least|Stable Tag| | :------------: |:------------:|:------------:| -| 2.0.12 | WordPress 4.9 or higher| 2.0.12 | +| 2.0.15 | WordPress 4.9 or higher| 2.0.15 | Features of the plugin include: @@ -48,7 +48,7 @@ GNU Version 2 or Any Later Version Releases ==================== -[Official Release Version: 2.0.12](https://github.com/ultimatemember/ultimatemember/releases/tag/2.0.12). +[Official Release Version: 2.0.15](https://github.com/ultimatemember/ultimatemember/releases/tag/2.0.15). [Official Release Version: 1.3.88](https://github.com/ultimatemember/ultimatemember/releases). diff --git a/assets/js/um-gdpr.js b/assets/js/um-gdpr.js new file mode 100644 index 00000000..31c0fde9 --- /dev/null +++ b/assets/js/um-gdpr.js @@ -0,0 +1,22 @@ +(function( $ ) { + 'use strict'; + + $(document).on('click', "a.um-toggle-gdpr" ,function() { + + var me = jQuery(this); + + $( ".um-gdpr-content" ).toggle( "fast", function() { + if( $( ".um-gdpr-content" ).is(':visible') ){ + me.text( me.data('toggle-hide') ); + } + + if( $( ".um-gdpr-content" ).is(':hidden') ){ + me.text( me.data('toggle-show') ); + } + + }); + + }); + + +})( jQuery ); diff --git a/assets/js/um-gdpr.min.js b/assets/js/um-gdpr.min.js new file mode 100644 index 00000000..b861cc4a --- /dev/null +++ b/assets/js/um-gdpr.min.js @@ -0,0 +1 @@ +!function(t){"use strict";t(document).on("click","a.um-toggle-gdpr",function(){var e=jQuery(this);t(".um-gdpr-content").toggle("fast",function(){t(".um-gdpr-content").is(":visible")&&e.text(e.data("toggle-hide")),t(".um-gdpr-content").is(":hidden")&&e.text(e.data("toggle-show"))})})}(jQuery); \ No newline at end of file diff --git a/includes/admin/core/class-admin-gdpr.php b/includes/admin/core/class-admin-gdpr.php new file mode 100644 index 00000000..5a69dd2b --- /dev/null +++ b/includes/admin/core/class-admin-gdpr.php @@ -0,0 +1,316 @@ +metabox(), 'load_metabox_form' ), + 'um_form', + 'side', + 'default' + ); + } + + + /** + * + */ + function init_fields() { + $this->meta_associations = array( + + 'account_status' => __( 'Account Status', 'ultimate-member' ), + 'submitted' => __( 'Submitted data on Registration', 'ultimate-member' ), + 'form_id' => __( 'Registration Form ID', 'ultimate-member' ), + 'timestamp' => __( 'Registration Timestamp', 'ultimate-member' ), + 'request' => __( 'Registration Request', 'ultimate-member' ), + '_wpnonce' => __( 'Registration Nonce', 'ultimate-member' ), + '_wp_http_referer' => __( 'Registration HTTP referer', 'ultimate-member' ), + 'role' => __( 'Community Role', 'ultimate-member' ), + 'um_user_profile_url_slug_user_login' => __( 'Profile Slug "Username"', 'ultimate-member' ), + 'um_user_profile_url_slug_name' => __( 'Profile Slug "First and Last Name with \'.\'"', 'ultimate-member' ), + 'um_user_profile_url_slug_name_dash' => __( 'Profile Slug "First and Last Name with \'-\'"', 'ultimate-member' ), + 'um_user_profile_url_slug_name_plus' => __( 'Profile Slug "First and Last Name with \'+\'"', 'ultimate-member' ), + 'um_user_profile_url_slug_user_id' => __( 'Profile Slug "User ID"', 'ultimate-member' ), + '_um_last_login' => __( 'Last Login Timestamp', 'ultimate-member' ), + + //Private content extension + '_um_private_content_post_id' => __( 'Private Content Post ID', 'ultimate-member' ), + + //Verified Users extension + '_um_verified' => __( 'Verified Account', 'ultimate-member' ), + + //Terms & Conditions extension + 'use_terms_conditions_agreement' => __( 'Terms&Conditions Agreement', 'ultimate-member' ), + + //GDPR extension + 'use_gdpr_agreement' => __( 'Privacy Policy Agreement', 'ultimate-member' ), + + + ); + + $all_fields = UM()->builtin()->all_user_fields( null, true ); + unset( $all_fields[0] ); + + $all_fields = array_map( function( $value ) { + return $value['title']; + }, $all_fields ); + + $this->meta_associations = array_merge( $this->meta_associations, $all_fields ); + + /** + * UM hook + * + * @type filter + * @title um_gdpr_meta_associations + * @description Exclude taxonomies for UM + * @input_vars + * [{"var":"$meta_associations","type":"array","desc":"Meta Keys Titles"}] + * @change_log + * ["Since: 2.0.14"] + * @usage + * + * @example + * + */ + $this->meta_associations = apply_filters( 'um_gdpr_meta_associations', $this->meta_associations ); + } + + + /** + * Return the default suggested privacy policy content. + * + * @return string The default policy content. + */ + function plugin_get_default_privacy_content() { + ob_start(); + + include UM()->admin()->templates_path . 'gdpr.php'; + + return ob_get_clean(); + } + + + /** + * Add the suggested privacy policy text to the policy postbox. + */ + function plugin_add_suggested_privacy_content() { + $content = $this->plugin_get_default_privacy_content(); + wp_add_privacy_policy_content( ultimatemember_plugin_name, $content ); + } + + + /** + * Register exporter for Plugin user data. + * + * @see https://github.com/allendav/wp-privacy-requests/blob/master/EXPORT.md + * + * @param $exporters + * + * @return array + */ + function plugin_register_exporters( $exporters ) { + $exporters[] = array( + 'exporter_friendly_name' => ultimatemember_plugin_name, + 'callback' => array( &$this, 'data_exporter' ) + ); + return $exporters; + } + + + /** + * Get user metadata in key => value array + * + * + * @param $user_id + * + * @return array + */ + function get_metadata( $user_id ) { + global $wpdb; + + $metadata = $wpdb->get_results( $wpdb->prepare( + "SELECT meta_key, meta_value + FROM {$wpdb->usermeta} + WHERE user_id = %d", + $user_id + ), ARRAY_A ); + + $filtered = array(); + foreach ( $metadata as $data ) { + if ( in_array( $data['meta_key'], array_keys( $this->meta_associations ) ) ) { + $filtered[] = array( + 'key' => $data['meta_key'], + 'name' => $this->meta_associations[ $data['meta_key'] ], + //'value' => maybe_unserialize( $data['meta_value'] ), + 'value' => $data['meta_value'], + ); + } + } + + return $filtered; + } + + + /** + * Exporter for Plugin user data. + * + * @see https://github.com/allendav/wp-privacy-requests/blob/master/EXPORT.md + * + * @param $email_address + * @param int $page + * + * @return array + */ + function data_exporter( $email_address, $page = 1 ) { + $export_items = array(); + $user = get_user_by( 'email', $email_address ); + + if ( $user && $user->ID ) { + // Most item IDs should look like postType-postID + // If you don't have a post, comment or other ID to work with, + // use a unique value to avoid having this item's export + // combined in the final report with other items of the same id + $item_id = "ultimate-member-{$user->ID}"; + + // Core group IDs include 'comments', 'posts', etc. + // But you can add your own group IDs as needed + $group_id = 'ultimate-member'; + + // Optional group label. Core provides these for core groups. + // If you define your own group, the first exporter to + // include a label will be used as the group label in the + // final exported report + $group_label = ultimatemember_plugin_name; + + // Plugins can add as many items in the item data array as they want + //$data = array(); + + $data = $this->get_metadata( $user->ID ); + + if ( ! empty( $data ) ) { + // Add this group of items to the exporters data array. + $export_items[] = array( + 'group_id' => $group_id, + 'group_label' => $group_label, + 'item_id' => $item_id, + 'data' => $data, + ); + } + } + // Returns an array of exported items for this pass, but also a boolean whether this exporter is finished. + //If not it will be called again with $page increased by 1. + return array( + 'data' => $export_items, + 'done' => true, + ); + } + + + /** + * Register eraser for Plugin user data. + * + * @param array $erasers + * + * @return array + */ + function plugin_register_erasers( $erasers = array() ) { + $erasers[] = array( + 'eraser_friendly_name' => ultimatemember_plugin_name, + 'callback' => array( &$this, 'data_eraser' ) + ); + return $erasers; + } + + + /** + * Eraser for Plugin user data. + * + * @param $email_address + * @param int $page + * + * @return array + */ + function data_eraser( $email_address, $page = 1 ) { + if ( empty( $email_address ) ) { + return array( + 'items_removed' => false, + 'items_retained' => false, + 'messages' => array(), + 'done' => true, + ); + } + + $user = get_user_by( 'email', $email_address ); + $messages = array(); + $items_removed = false; + $items_retained = false; + + if ( $user && $user->ID ) { + $data = $this->get_metadata( $user->ID ); + + foreach ( $data as $metadata ) { + $deleted = delete_user_meta( $user->ID, $metadata['key'] ); + if ( $deleted ) { + $items_removed = true; + } else { + $messages[] = sprintf( __( 'Your %s was unable to be removed at this time.', 'ultimate-member' ), $metadata['name'] ); + $items_retained = true; + } + } + } + + // Returns an array of exported items for this pass, but also a boolean whether this exporter is finished. + //If not it will be called again with $page increased by 1. + return array( + 'items_removed' => $items_removed, + 'items_retained' => $items_retained, + 'messages' => $messages, + 'done' => true, + ); + } + + } + +} \ No newline at end of file diff --git a/includes/admin/core/class-admin-settings.php b/includes/admin/core/class-admin-settings.php index bea6bdc2..29ff98fc 100644 --- a/includes/admin/core/class-admin-settings.php +++ b/includes/admin/core/class-admin-settings.php @@ -1197,12 +1197,14 @@ if ( ! class_exists( 'um\admin\core\Admin_Settings' ) ) { do_action( "um_settings_page_" . $current_tab . "_" . $current_subtab . "_before_section" ); $section_fields = $this->get_section_fields( $current_tab, $current_subtab ); + $settings_section = $this->render_settings_section( $section_fields, $current_tab, $current_subtab ); /** * UM hook * * @type filter * @title um_settings_section_{$current_tab}_{$current_subtab}_content + * * @description Render settings section * @input_vars * [{"var":"$content","type":"string","desc":"Section content"}, @@ -1220,7 +1222,7 @@ if ( ! class_exists( 'um\admin\core\Admin_Settings' ) ) { * ?> */ echo apply_filters( 'um_settings_section_' . $current_tab . '_' . $current_subtab . '_content', - $this->render_settings_section( $section_fields, $current_tab, $current_subtab ), + $settings_section, $section_fields ); @@ -1258,6 +1260,7 @@ if ( ! class_exists( 'um\admin\core\Admin_Settings' ) ) { do_action( "um_settings_page_" . $current_tab . "_" . $current_subtab . "_before_section" ); $section_fields = $this->get_section_fields( $current_tab, $current_subtab ); + $settings_section = $this->render_settings_section( $section_fields, $current_tab, $current_subtab ); /** * UM hook @@ -1281,7 +1284,7 @@ if ( ! class_exists( 'um\admin\core\Admin_Settings' ) ) { * ?> */ echo apply_filters( 'um_settings_section_' . $current_tab . '_' . $current_subtab . '_content', - $this->render_settings_section( $section_fields, $current_tab, $current_subtab ), + $settings_section, $section_fields ); ?> diff --git a/includes/admin/templates/form/register_gdpr.php b/includes/admin/templates/form/register_gdpr.php new file mode 100644 index 00000000..0a226b11 --- /dev/null +++ b/includes/admin/templates/form/register_gdpr.php @@ -0,0 +1,71 @@ +
\ No newline at end of file diff --git a/includes/admin/templates/gdpr.php b/includes/admin/templates/gdpr.php new file mode 100644 index 00000000..da6334ed --- /dev/null +++ b/includes/admin/templates/gdpr.php @@ -0,0 +1,40 @@ + + ++ +
++ +
++ +
+ ++ +
++ +
++ +
+ ++ +
++ +
\ No newline at end of file diff --git a/includes/class-init.php b/includes/class-init.php index 10112ed0..0e9f1fc3 100644 --- a/includes/class-init.php +++ b/includes/class-init.php @@ -485,6 +485,7 @@ if ( ! class_exists( 'UM' ) ) { $this->ajax_init(); $this->metabox(); $this->admin_upgrade()->init_packages_ajax_handlers(); + $this->admin_gdpr(); } elseif ( $this->is_request( 'admin' ) ) { $this->admin(); $this->admin_menu(); @@ -497,6 +498,7 @@ if ( ! class_exists( 'UM' ) ) { $this->users(); $this->dragdrop(); $this->plugin_updater(); + $this->admin_gdpr(); } elseif ( $this->is_request( 'frontend' ) ) { $this->enqueue(); $this->account(); @@ -525,6 +527,7 @@ if ( ! class_exists( 'UM' ) ) { //$this->tracking(); $this->mobile(); $this->external_integrations(); + $this->gdpr(); } @@ -640,6 +643,48 @@ if ( ! class_exists( 'UM' ) ) { } + /** + * GDPR privacy policy + * + * @since 2.0.14 + * + * @return bool|um\admin\core\Admin_GDPR() + */ + function admin_gdpr() { + global $wp_version; + + if ( version_compare( $wp_version, '4.9.6', '<' ) ) { + return false; + } + + if ( empty( $this->classes['admin_gdpr'] ) ) { + $this->classes['admin_gdpr'] = new um\admin\core\Admin_GDPR(); + } + return $this->classes['admin_gdpr']; + } + + + /** + * GDPR privacy policy + * + * @since 2.0.14 + * + * @return bool|um\core\GDPR() + */ + function gdpr() { + global $wp_version; + + if ( version_compare( $wp_version, '4.9.6', '<' ) ) { + return false; + } + + if ( empty( $this->classes['gdpr'] ) ) { + $this->classes['gdpr'] = new um\core\GDPR(); + } + return $this->classes['gdpr']; + } + + /** * @since 2.0 * diff --git a/includes/core/class-access.php b/includes/core/class-access.php index 7f1c1fc5..50938c9e 100644 --- a/includes/core/class-access.php +++ b/includes/core/class-access.php @@ -65,6 +65,10 @@ if ( ! class_exists( 'um\core\Access' ) ) { add_action( 'template_redirect', array( &$this, 'template_redirect' ), 1000 ); add_action( 'um_access_check_individual_term_settings', array( &$this, 'um_access_check_individual_term_settings' ) ); add_action( 'um_access_check_global_settings', array( &$this, 'um_access_check_global_settings' ) ); + + /* Disable comments if user has not permission to access current post */ + add_filter( 'comments_open', array( $this, 'disable_comments_open' ), 99, 2 ); + add_filter( 'get_comments_number', array( $this, 'disable_comments_open' ), 99, 2 ); } @@ -934,6 +938,63 @@ if ( ! class_exists( 'um\core\Access' ) ) { } + /** + * Disable comments if user has not permission to access this post + * @param mixed $open + * @param int $post_id + * @return boolean + */ + public function disable_comments_open( $open, $post_id ) { + + static $cache = array(); + + if ( isset( $cache[ $post_id ] ) ) { + return $cache[ $post_id ] ? $open : false; + } + + $post = get_post( $post_id ); + $restriction = $this->get_post_privacy_settings( $post ); + + if ( ! $restriction ) { + $cache[ $post_id ] = $open; + return $open; + } + + if ( '1' == $restriction['_um_accessible'] ) { + + if ( is_user_logged_in() ) { + if ( ! current_user_can( 'administrator' ) ) { + $open = false; + } + } + + } elseif ( '2' == $restriction['_um_accessible'] ) { + if ( ! is_user_logged_in() ) { + $open = false; + } else { + if ( ! current_user_can( 'administrator' ) ) { + $custom_restrict = $this->um_custom_restriction( $restriction ); + + if ( empty( $restriction['_um_access_roles'] ) || false === array_search( '1', $restriction['_um_access_roles'] ) ) { + if ( ! $custom_restrict ) { + $open = false; + } + } else { + $user_can = $this->user_can( get_current_user_id(), $restriction['_um_access_roles'] ); + + if ( ! isset( $user_can ) || ! $user_can || ! $custom_restrict ) { + $open = false; + } + } + } + } + } + + $cache[ $post_id ] = $open; + return $open; + } + + /** * Protect Post Types in menu query * Restrict content new logic diff --git a/includes/core/class-account.php b/includes/core/class-account.php index 1b7007af..4b617404 100644 --- a/includes/core/class-account.php +++ b/includes/core/class-account.php @@ -55,6 +55,7 @@ if ( ! class_exists( 'um\core\Account' ) ) { * @param $args */ function init_tabs( $args ) { + $this->tabs = $this->get_tabs(); ksort( $this->tabs ); @@ -75,7 +76,6 @@ if ( ! class_exists( 'um\core\Account' ) ) { } } - $this->tabs = $tabs_structed; } @@ -527,7 +527,7 @@ if ( ! class_exists( 'um\core\Account' ) ) { * ?> */ $args = apply_filters( 'um_account_tab_privacy_fields', $args, $shortcode_args ); - + $fields = UM()->builtin()->get_specific_fields( $args ); $fields = $this->account_secure_fields( $fields, $id ); $fields = $this->filter_fields_by_attrs( $fields, $shortcode_args ); @@ -535,7 +535,6 @@ if ( ! class_exists( 'um\core\Account' ) ) { foreach ( $fields as $key => $data ){ $output .= UM()->fields()->edit_field( $key, $data ); } - break; case 'delete': @@ -752,6 +751,7 @@ if ( ! class_exists( 'um\core\Account' ) ) { * ?> */ do_action( "um_after_account_{$tab_id}", $args ); +// var_dump($args); if ( ! isset( $tab_data['show_button'] ) || false !== $tab_data['show_button'] ) { ?> diff --git a/includes/core/class-builtin.php b/includes/core/class-builtin.php index 2242e55b..c076c7a3 100644 --- a/includes/core/class-builtin.php +++ b/includes/core/class-builtin.php @@ -1252,7 +1252,7 @@ if ( ! class_exists( 'um\core\Builtin' ) ) { */ $fields_without_metakey = apply_filters( 'um_fields_without_metakey', $fields_without_metakey ); - if ( !$show_all ) { + if ( ! $show_all ) { $this->fields_dropdown = array('image','file','password','rating'); $this->fields_dropdown = array_merge( $this->fields_dropdown, $fields_without_metakey ); } else { diff --git a/includes/core/class-enqueue.php b/includes/core/class-enqueue.php index 4365b686..b723b213 100644 --- a/includes/core/class-enqueue.php +++ b/includes/core/class-enqueue.php @@ -319,6 +319,8 @@ if ( ! class_exists( 'um\core\Enqueue' ) ) { wp_register_script('um_functions', um_url . 'assets/js/um-functions' . $this->suffix . '.js', array('jquery', 'jquery-masonry') ); wp_enqueue_script('um_functions'); + wp_enqueue_script( 'um-gdpr', um_url . 'assets/js/um-gdpr' . $this->suffix . '.js', array( 'jquery' ), ultimatemember_version, false ); + } diff --git a/includes/core/class-fields.php b/includes/core/class-fields.php index 9a82bd01..a146a9b7 100644 --- a/includes/core/class-fields.php +++ b/includes/core/class-fields.php @@ -814,16 +814,21 @@ if ( ! class_exists( 'um\core\Fields' ) ) { $field_value = um_user( $key ); - if ($key == 'role') { + if ( $key == 'role' ) { $role_keys = get_option( 'um_roles' ); - if (!empty( $role_keys )) { - if (in_array( $field_value, $role_keys )) { + if ( ! empty( $role_keys ) ) { + if ( in_array( $field_value, $role_keys ) ) { $field_value = 'um_' . $field_value; } } - + /*elseif( $this->set_mode == 'register' ){ + $data['default'] = UM()->options()->get( 'register_role' ); + } + else{ + $data['default'] = get_option( 'default_role' ); + }*/ } /** @@ -936,19 +941,25 @@ if ( ! class_exists( 'um\core\Fields' ) ) { $um_user_value = um_user( $key ); - if ($key == 'role') { + if ( $key == 'role' ) { $um_user_value = strtolower( $um_user_value ); $role_keys = get_option( 'um_roles' ); - if (!empty( $role_keys )) { - if (in_array( $um_user_value, $role_keys )) { + if ( ! empty( $role_keys ) ) { + if ( in_array( $um_user_value, $role_keys ) ) { $um_user_value = 'um_' . $um_user_value; } } + /*elseif( $this->set_mode == 'register' ){ + $data['default'] = UM()->options()->get( 'register_role' ); + } + else{ + $data['default'] = get_option( 'default_role' ); + }*/ } - if ($um_user_value == $value) { + if ( $um_user_value == $value ) { return true; } @@ -1625,6 +1636,7 @@ if ( ! class_exists( 'um\core\Fields' ) ) { // forbidden in edit mode? if (isset( $data['edit_forbidden'] )) return; + // required option if (isset( $data['required_opt'] )) { $opt = $data['required_opt']; diff --git a/includes/core/class-gdpr.php b/includes/core/class-gdpr.php new file mode 100644 index 00000000..82ec76e7 --- /dev/null +++ b/includes/core/class-gdpr.php @@ -0,0 +1,86 @@ +form()->add_error( 'use_gdpr_agreement', isset( $args['use_gdpr_error_text'] ) ? $args['use_gdpr_error_text'] : '' ); + } + } + + + /** + * @param $submitted + * + * @return mixed + */ + function add_agreement_date( $submitted ) { + if ( isset( $submitted['use_gdpr_agreement'] ) ) { + $submitted['use_gdpr_agreement'] = time(); + } + + return $submitted; + } + + + /** + * @param $submitted + * + * @return mixed + */ + function email_registration_data( $submitted ) { + + $timestamp = ! empty( $submitted['timestamp'] ) ? $submitted['timestamp'] : $submitted['use_gdpr_agreement']; + + if ( ! empty( $submitted['use_gdpr_agreement'] ) ) { + $submitted['GDPR Applied'] = date( "d M Y H:i", $timestamp ); + unset( $submitted['use_gdpr_agreement'] ); + } + + return $submitted; + } + + } + +} \ No newline at end of file diff --git a/includes/core/class-user.php b/includes/core/class-user.php index 6a0a9aca..a449366c 100644 --- a/includes/core/class-user.php +++ b/includes/core/class-user.php @@ -39,6 +39,7 @@ if ( ! class_exists( 'um\core\User' ) ) { add_action( 'init', array( &$this, 'set' ), 1 ); $this->preview = false; + $this->send_mail_on_delete = true; // a list of keys that should never be in wp_usermeta $this->update_user_keys = array( @@ -54,6 +55,8 @@ if ( ! class_exists( 'um\core\User' ) ) { // When the cache should be cleared add_action('um_delete_user_hook', array(&$this, 'remove_cached_queue') ); + add_action('um_delete_user', array( &$this, 'remove_cache' ), 10, 1 ); + add_action('um_after_user_status_is_changed_hook', array(&$this, 'remove_cached_queue') ); // When user cache should be cleared @@ -83,6 +86,73 @@ if ( ! class_exists( 'um\core\User' ) ) { add_action( 'wpmu_activate_user', array( &$this, 'add_um_role_wpmu_new_user' ), 10, 1 ); add_action( 'init', array( &$this, 'check_membership' ), 10 ); + + add_action( 'delete_user', array( &$this, 'delete_user_handler' ), 10, 1 ); + add_action( 'wpmu_delete_user', array( &$this, 'delete_user_handler' ), 10, 1 ); + } + + + /** + * @param $user_id + */ + function delete_user_handler( $user_id ) { + + um_fetch_user( $user_id ); + + /** + * UM hook + * + * @type action + * @title um_delete_user_hook + * @description On delete user + * @change_log + * ["Since: 2.0"] + * @usage add_action( 'um_delete_user_hook', 'function_name', 10 ); + * @example + * + */ + do_action( 'um_delete_user_hook' ); + + /** + * UM hook + * + * @type action + * @title um_delete_user + * @description On delete user + * @input_vars + * [{"var":"$user_id","type":"int","desc":"User ID"}] + * @change_log + * ["Since: 2.0"] + * @usage add_action( 'um_delete_user', 'function_name', 10, 1 ); + * @example + * + */ + do_action( 'um_delete_user', um_user( 'ID' ) ); + + // send email notifications + if ( $this->send_mail_on_delete ) { + UM()->mail()->send( um_user( 'user_email' ), 'deletion_email' ); + + $emails = um_multi_admin_email(); + if ( ! empty( $emails ) ) { + foreach ( $emails as $email ) { + UM()->mail()->send( $email, 'notification_deletion', array( 'admin' => true ) ); + } + } + } + + // remove uploads + UM()->files()->remove_dir( um_user_uploads_dir() ); } @@ -1288,59 +1358,10 @@ if ( ! class_exists( 'um\core\User' ) ) { * @param bool $send_mail */ function delete( $send_mail = true ) { - /** - * UM hook - * - * @type action - * @title um_delete_user_hook - * @description On delete user - * @change_log - * ["Since: 2.0"] - * @usage add_action( 'um_delete_user_hook', 'function_name', 10 ); - * @example - * - */ - do_action( 'um_delete_user_hook' ); - /** - * UM hook - * - * @type action - * @title um_delete_user - * @description On delete user - * @input_vars - * [{"var":"$user_id","type":"int","desc":"User ID"}] - * @change_log - * ["Since: 2.0"] - * @usage add_action( 'um_delete_user', 'function_name', 10, 1 ); - * @example - * - */ - do_action( 'um_delete_user', um_user( 'ID' ) ); - // send email notifications - if ( $send_mail ) { - UM()->mail()->send( um_user( 'user_email' ), 'deletion_email' ); + $this->send_mail_on_delete = $send_mail; - $emails = um_multi_admin_email(); - if ( ! empty( $emails ) ) { - foreach ( $emails as $email ) { - UM()->mail()->send( $email, 'notification_deletion', array( 'admin' => true ) ); - } - } - } - - // remove uploads - UM()->files()->remove_dir( um_user_uploads_dir() ); + $this->delete_user_handler( um_user( 'ID' ) ); // remove user if ( is_multisite() ) { diff --git a/includes/core/um-actions-core.php b/includes/core/um-actions-core.php index 2c85e9cb..fdfabc43 100644 --- a/includes/core/um-actions-core.php +++ b/includes/core/um-actions-core.php @@ -108,7 +108,9 @@ function um_action_request_process() { break; case 'um_delete': - if ( ! UM()->roles()->um_current_user_can( 'delete', $uid ) ) wp_die( __('You do not have permission to delete this user.','ultimate-member') ); + if ( ! UM()->roles()->um_current_user_can( 'delete', $uid ) ) { + wp_die( __('You do not have permission to delete this user.','ultimate-member') ); + } um_fetch_user( $uid ); UM()->user()->delete(); exit( wp_redirect( UM()->permalinks()->get_current_url( true ) ) ); diff --git a/readme.txt b/readme.txt index 847b4fee..fa7ddfb2 100644 --- a/readme.txt +++ b/readme.txt @@ -6,7 +6,7 @@ Donate link: Tags: community, member, membership, user-profile, user-registration Requires at least: 4.1 Tested up to: 4.9 -Stable tag: 2.0.13 +Stable tag: 2.0.15 License: GNU Version 2 or Any Later Version License URI: http://www.gnu.org/licenses/gpl-3.0.txt @@ -131,6 +131,30 @@ The plugin works with popular caching plugins by automatically excluding Ultimat = Important: UM2.0+ is a significant update to the code base from 1.3.88. Please make sure you take a full-site backup with restore point before updating the plugin = += 2.0.15: May 22, 2018 = + +* Bugfixes: + - Fixed GDPR min.js script + += 2.0.14: May 22, 2018 = + +* Enhancements: + - Added support for GDPR Personal Data Exporter + - Added support for GDPR Personal Data Eraser + - Added new privacy field to form builder for GDPR consent collection + - Added GDPR privacy policy guide text + - Added GDPR compatibility on delete user process + - Added security to Restricted posts comments + - Added security to custom field type `Password` + - Deprecated time checking spam bot + +* Bugfixes: + - Fixed settings tabs for PHP7.1 + - Fixed issues with Profile Tabs + - Fixed User Avatars + - Fixed set user status on Registration process + - Fixed Account Privacy tab content + = 2.0.13: May 2, 2018 = * Bugfixes: diff --git a/templates/gdpr-register.php b/templates/gdpr-register.php new file mode 100644 index 00000000..714c6e84 --- /dev/null +++ b/templates/gdpr-register.php @@ -0,0 +1,44 @@ + + + +' . $error_message . '