dvadf
File manager - Edit - /home/centroca/public_html/ultimate-member.tar
Back
includes/action-scheduler/class-init.php 0000644 00000032415 15252504435 0014374 0 ustar 00 <?php namespace um\action_scheduler; if ( ! defined( 'ABSPATH' ) ) { exit; } if ( ! class_exists( 'um\action_scheduler\Init' ) ) { /** * Class Init * * @since 2.9.0 * * @package um\action_scheduler */ class Init { /** * Global variable if Action Scheduler is active. * * @var bool */ protected $enabled = false; /** * Action Scheduler group * * @var string */ protected $default_group = 'ultimate-member'; /** * Path to library * * @var string */ protected $lib_path = UM_PATH . 'includes/lib/action-scheduler/action-scheduler.php'; /** * */ public function __construct() { if ( ! $this->can_be_active() ) { add_action( 'init', array( $this, 'add_notice' ) ); add_filter( 'um_site_health_extend', array( $this, 'change_site_health' ) ); } else { add_filter( 'um_settings_structure', array( $this, 'add_setting' ) ); // Since 2.10.3 we load library as soon as there are required library files. // Options above are used for enable/disable some Action Scheduler hooks e.g. um_dispatch_email. $this->enabled = true; $this->load_library( true ); } } public function is_enabled() { return $this->enabled; } public function add_notice() { UM()->admin()->notices()->add_notice( 'um-action-scheduler', array( 'class' => 'notice-warning is-dismissible', // translators: %1$s - Plugin name, %1$s - Plugin Version 'message' => '<p>' . sprintf( __( '<strong>%1$s %2$s</strong> The file needed to enable the Action Scheduler is missing. The plugin will continue to function as it did before, but without the new benefits offered by the Action Scheduler.', 'ultimate-member' ), UM_PLUGIN_NAME, UM_VERSION ) . '</p>', ) ); } /** * Adds the Action Scheduler setting to Ultimate Member feature settings * * @param array $settings * * @return array */ public function change_site_health( $site_health ) { $site_health['ultimate-member']['fields']['enable_as_email_sending']['value'] = __( 'No', 'ultimate-member' ); return $site_health; } /** * Adds the Action Scheduler setting to Ultimate Member feature settings * * @param array $settings * * @return array */ public function add_setting( $settings ) { $settings['advanced']['sections']['features']['form_sections']['features']['fields'][] = array( 'id' => 'enable_as_email_sending', 'type' => 'checkbox', 'label' => __( 'Email sending by Action Scheduler', 'ultimate-member' ), 'checkbox_label' => __( 'Enable Action Scheduler for Ultimate Member emails sending', 'ultimate-member' ), 'description' => __( 'Check this box if you want to use the Action Scheduler for Ultimate Member emails sending. By enabling it, sending system emails will be scheduled to run at optimal times, which can help reduce the load on your server', 'ultimate-member' ), ); return $settings; } /** * Verifies whether WooCommerce is installed and activated, * and checks for the existence of the WooCommerce Action Scheduler file. * * @return bool */ public function verify_wc_action_scheduler() { if ( ! is_plugin_active( 'woocommerce/woocommerce.php' ) ) { return false; } $action_scheduler_file = WP_PLUGIN_DIR . '/woocommerce/packages/action-scheduler/action-scheduler.php'; return file_exists( $action_scheduler_file ); } /** * Tries to load Action Scheduler from Ultimate Member if file exists * * @param bool $force * * @return bool */ public function load_library( $force = false ) { if ( file_exists( $this->lib_path ) ) { if ( $force ) { require_once $this->lib_path; } return true; } return false; } /** * Checks whenever Action Scheduler can be active * * @return bool */ public function can_be_active() { return $this->verify_wc_action_scheduler() || $this->load_library(); } public function is_hook_enabled( $hook ) { return apply_filters( 'um_action_scheduler_is_hook_enabled', $this->is_enabled(), $hook ); } /** * Enqueue an action to run one time, as soon as possible. * If Action Scheduler is disabled then do_action_ref_array is called to run action right away. * * @param string $hook Required. Name of the action hook. * @param array $args Arguments to pass to callbacks when the hook triggers. Default: array(). * @param string $group The group to assign this job to. Default: ''. * @param bool $unique Whether the action should be unique. Default: false. * @param int $priority Lower values take precedence over higher values. Defaults to 10, with acceptable values falling in the range 0-255. * * @return int Еhe action’s ID. Zero if there was an error scheduling the action. The error will be sent to error_log */ public function enqueue_async_action( $hook, $args = array(), $group = '', $unique = false, $priority = 10 ) { if ( $this->is_hook_enabled( $hook ) ) { $group = $this->set_group( $group ); return as_enqueue_async_action( $hook, $args, $group, $unique, $priority ); } // Make then standard action without Action Scheduler. do_action_ref_array( $hook, $args ); return 0; } /** * Schedule an action to run one time at some defined point in the future. * * @param int $timestamp Required. The Unix timestamp representing the date you want the action to run. * @param string $hook Required. Name of the action hook. * @param array $args Arguments to pass to callbacks when the hook triggers. Default: array() * @param string $group The group to assign this job to. Default: ''. * @param bool $unique Whether the action should be unique. Default: false. * @param int $priority Lower values take precedence over higher values. Defaults to 10, with acceptable values falling in the range 0-255. * * @return int The action’s ID. Zero if there was an error scheduling the action. The error will be sent to error_log. */ public function schedule_single_action( $timestamp, $hook, $args = array(), $group = '', $unique = false, $priority = 10 ) { if ( $this->is_hook_enabled( $hook ) ) { $group = $this->set_group( $group ); return as_schedule_single_action( $timestamp, $hook, $args, $group, $unique, $priority ); } // Make then standard action without Action Scheduler. do_action_ref_array( $hook, $args ); return 0; } /** * Schedule an action to run repeatedly with a specified interval in seconds. * * @param int $timestamp Required. The Unix timestamp representing the date you want the action to run. * @param int $interval_in_seconds Required. How long to wait between runs. * @param string $hook Required. Name of the action hook. * @param array $args Arguments to pass to callbacks when the hook triggers. Default: array(). * @param string $group The group to assign this job to. Default: ''. * @param bool $unique Whether the action should be unique. Default: false. * @param int $priority Lower values take precedence over higher values. Defaults to 10, with acceptable values falling in the range 0-255. * * @return int The action’s ID. Zero if there was an error scheduling the action. The error will be sent to error_log. */ public function schedule_recurring_action( $timestamp, $interval_in_seconds, $hook, $args = array(), $group = '', $unique = false, $priority = 10 ) { $group = $this->set_group( $group ); return as_schedule_recurring_action( $timestamp, $interval_in_seconds, $hook, $args, $group, $unique, $priority ); } /** * Schedule an action that recurs on a cron-like schedule. * * If execution of a cron-like action is delayed, the next attempt will still be scheduled according to the provided cron expression. * * @param int $timestamp Required. The Unix timestamp representing the date you want the action to run. * @param string $schedule Required. A cron-like schedule string, see http://en.wikipedia.org/wiki/Cron. * @param string $hook Required Name of the action hook. * @param array $args Arguments to pass to callbacks when the hook triggers. Default: array(). * @param string $group The group to assign this job to. Default: ''. * @param bool $unique Whether the action should be unique. Default: false. * @param int $priority Lower values take precedence over higher values. Defaults to 10, with acceptable values falling in the range 0-255. * * @return int The action’s ID. Zero if there was an error scheduling the action. The error will be sent to error_log. */ public function schedule_cron_action( $timestamp, $schedule, $hook, $args = array(), $group = '', $unique = false, $priority = 10 ) { $group = $this->set_group( $group ); return as_schedule_cron_action( $timestamp, $schedule, $hook, $args, $group, $unique, $priority ); } /** * Cancel the next occurrence of a scheduled action. * * @param string $hook Required. Name of the action hook. * @param array $args Arguments passed to callbacks when the hook triggers. Default: array(). * @param string $group The group the job is assigned to. Default: ''. * * @return int|null The scheduled action ID if a scheduled action was found, or null if no matching action found. */ public function unschedule_action( $hook, $args = array(), $group = '' ) { $group = $this->set_group( $group ); return as_unschedule_action( $hook, $args, $group ); } /** * Cancel all occurrences of a scheduled action. * * @param string $hook The hook that the job will trigger. * @param array $args Args that would have been passed to the job. * @param string $group The group the job is assigned to. */ public function unschedule_all_actions( $hook, $args = array(), $group = '' ) { $group = $this->set_group( $group ); as_unschedule_all_actions( $hook, $args, $group ); } /** * Returns the next timestamp for a scheduled action. * * @param string $hook Required. Name of the action hook. Default: none. * @param array $args Arguments passed to callbacks when the hook triggers. Default: array(). * @param string $group The group the job is assigned to. Default: ''. * * @return int|bool The timestamp for the next occurrence of a pending scheduled action, true for an async or in-progress action or false if there is no matching action. */ public function next_scheduled_action( $hook, $args = array(), $group = '' ) { $group = $this->set_group( $group ); return as_next_scheduled_action( $hook, $args, $group ); } /** * Check if there is a scheduled action in the queue, but more efficiently than as_next_scheduled_action(). * It’s recommended to use this function when you need to know whether a specific action is currently scheduled. * * @param string $hook Required. Name of the action hook. Default: none. * @param array $args Arguments passed to callbacks when the hook triggers. Default: array(). * @param string $group The group the job is assigned to. Default: ''. * * @return bool True if a matching action is pending or in-progress, false otherwise. */ public function has_scheduled_action( $hook, $args = array(), $group = '' ) { $group = $this->set_group( $group ); return as_has_scheduled_action( $hook, $args, $group ); } /** * @param array $args Arguments to search and filter results by. Possible arguments, with their default values: * 'hook' => '' - the name of the action that will be triggered * 'args' => NULL - the args array that will be passed with the action * 'date' => NULL - the scheduled date of the action. Expects a DateTime object, a unix timestamp, or a string that can parsed with strtotime(). * 'date_compare' => '<=' - operator for testing “date”. accepted values are ‘!=’, ‘>’, ‘>=’, ‘<’, ‘<=’, ‘=’ * 'modified' => NULL - the date the action was last updated. Expects a DateTime object, a unix timestamp, or a string that can parsed with strtotime(). * 'modified_compare' => '<=' - operator for testing “modified”. accepted values are ‘!=’, ‘>’, ‘>=’, ‘<’, ‘<=’, ‘=’ * 'group' => '' - the group the action belongs to * 'status' => '' - ActionScheduler_Store::STATUS_COMPLETE or ActionScheduler_Store::STATUS_PENDING * 'claimed' => NULL - TRUE to find claimed actions, FALSE to find unclaimed actions, a string to find a specific claim ID * 'per_page' => 5 - Number of results to return * 'offset' => 0 * 'orderby' => 'date' - accepted values are ‘hook’, ‘group’, ‘modified’, or ‘date’ * 'order' => 'ASC' * * @param string $return_format The format in which to return the scheduled actions: 'OBJECT', 'ARRAY_A', or 'ids'. Default: 'OBJECT'. * * @return array Array of action rows matching the criteria specified with $args. */ public function get_scheduled_actions( $args, $return_format = 'OBJECT' ) { if ( ! empty( $args['group'] ) ) { $args['group'] = $this->set_group( $args['group'] ); } return as_get_scheduled_actions( $args, $return_format ); } public function set_group( $group ) { if ( empty( $group ) ) { return $this->default_group; } return $this->default_group . '_' . $group; } } } includes/class-extensions.php 0000644 00000012050 15252504435 0012370 0 ustar 00 <?php namespace um; // Exit if executed directly if ( ! defined( 'ABSPATH' ) ) exit; if ( ! class_exists( 'um\Extensions' ) ) { /** * Class Extensions * * @package um * * @method void bbpress_activation() */ class Extensions { /** * Extensions list * * @var array */ var $list = array(); /** * Extensions data * * @var array */ var $plugin_data = array(); /** * Extensions constructor. */ function __construct() { } /** * */ function check_dependencies() { $extensions = $this->get_list(); foreach ( $extensions as $slug ) { $extension = $this->get_info( $slug ); list( $run, $slug, $message ) = apply_filters_ref_array( 'um_extension_custom_dependencies', array( true, $slug, '' ) ); if ( $run ) { $compare_version_result = UM()->dependencies()->compare_versions( $extension['min_core_version'], $extension['version'], $slug, $extension['title'] ); if ( true !== $compare_version_result ) { UM()->admin()->notices()->add_notice( "{$slug}_dependencies", array( 'class' => 'error', 'message' => '<p>' . $compare_version_result . '</p>', ), 1 ); } } elseif ( ! $run && ! empty( $message ) ) { UM()->admin()->notices()->add_notice( "{$slug}_dependencies", array( 'class' => 'error', 'message' => $message, ), 1 ); } if ( $run ) { UM()->call_class( "um_ext\um_{$slug}\Init" ); } } } /** * @param $settings * * @return mixed */ function license_options( $settings ) { $extensions = $this->get_list(); if ( empty( $extensions ) ) { return $settings; } foreach ( $extensions as $slug ) { $extension = $this->get_info( $slug ); if ( isset( $extension['plan'] ) && $extension['plan'] == 'free' ) { continue; } $settings['licenses']['fields'][] = array( 'id' => "um_{$slug}_license_key", // translators: %s: extension name. 'label' => sprintf( __( '%s License Key', 'ultimate-member' ), $extension['title'] ), 'item_name' => $extension['item_name'], 'author' => 'Ultimate Member', 'version' => $extension['version'], ); } return $settings; } /** * Loading Extensions localizations */ function localization() { $extensions = $this->get_list(); foreach ( $extensions as $slug ) { $extension = $this->get_info( $slug ); $locale = ( get_locale() != '' ) ? get_locale() : 'en_US'; load_textdomain( $extension['textdomain'], WP_LANG_DIR . '/plugins/' . $extension['textdomain'] . '-' . $locale . '.mo'); load_plugin_textdomain( $extension['textdomain'], false, dirname( $extension['plugin'] ) . '/languages/' ); } } /** * @param $slug * * @return string */ function get_version( $slug ) { $version = ''; return $version; } /** * @param $slug * @param bool $field * * @return array|bool */ function get_info( $slug, $field = false ) { if ( ! $field ) { return ! empty( $this->plugin_data[ $slug ] ) ? $this->plugin_data[ $slug ] : array(); } else { return ! empty( $this->plugin_data[ $slug ][ $field ] ) ? $this->plugin_data[ $slug ][ $field ] : false; } } /** * @param string $slug * @param array $plugin_data */ function add( $slug, $plugin_data ) { $this->list[] = $slug; $this->plugin_data[ $slug ] = $plugin_data; } /** * Activate Extension Process * Common functions in activation * * @param $slug */ function activate( $slug ) { $plugin_data = $this->get_info( $slug ); //if extension wasn't inited, init it firstly via "um_{$slug}_add" function //"um_{$slug}_add" must be in the preset structure of UM extension if ( empty( $plugin_data ) && function_exists( "um_{$slug}_add" ) ) { call_user_func( "um_{$slug}_add" ); $plugin_data = $this->get_info( $slug ); } //first install $version = get_option( "um_{$slug}_version" ); if ( ! $version ) { update_option( "um_{$slug}_last_version_upgrade", $plugin_data['version'] ); } if ( $version != $plugin_data['version'] ) { update_option( "um_{$slug}_version", $plugin_data['version'] ); } //start setup UM()->extension( $slug )->setup()->start(); } /** * @return array */ function get_list() { return $this->list; } function get_packages( $slug ) { $plugin_info = $this->get_info( $slug ); $packages_dir = $plugin_info['path'] . DIRECTORY_SEPARATOR . 'includes' . DIRECTORY_SEPARATOR . 'admin' . DIRECTORY_SEPARATOR . 'core' . DIRECTORY_SEPARATOR . 'packages'; $update_versions = array(); $handle = opendir( $packages_dir ); if ( $handle ) { while ( false !== ( $filename = readdir( $handle ) ) ) { if ( $filename != '.' && $filename != '..' ) { if ( is_dir( $packages_dir . DIRECTORY_SEPARATOR . $filename ) ) { $update_versions[] = $filename; } } } closedir( $handle ); usort( $update_versions, array( UM()->admin_upgrade(), 'version_compare_sort' ) ); } return $update_versions; } } } includes/class-functions.php 0000644 00000055664 15252504435 0012223 0 ustar 00 <?php if ( ! defined( 'ABSPATH' ) ) { exit; } if ( ! class_exists( 'UM_Functions' ) ) { /** * Class UM_Functions */ class UM_Functions { /** * Store URL * * @var string */ public static $store_url = 'https://ultimatemember.com/?edd-request=get-info'; /** * WP remote Post timeout * @var int */ public static $request_timeout = 60; /** * Check if AJAX now * * @return bool */ function is_ajax() { return function_exists( 'wp_doing_ajax' ) ? wp_doing_ajax() : defined( 'DOING_AJAX' ); } /** * Check frontend nonce * * @param bool $action */ function check_ajax_nonce( $action = false ) { $nonce = isset( $_REQUEST['nonce'] ) ? sanitize_text_field( $_REQUEST['nonce'] ) : ''; $action = empty( $action ) ? 'um-frontend-nonce' : $action; if ( ! wp_verify_nonce( $nonce, $action ) ) { wp_send_json_error( esc_js( __( 'Wrong Nonce', 'ultimate-member' ) ) ); } } /** * Check if the user rate limit has been reached based on the provided context * * @param string $context The context for which the rate limit check is being performed * @param int|null $requests_num Number requests per minute. Default 10. * * @return bool True if the rate limit has been reached, false otherwise */ public function is_rate_limited( $context, $requests_num = 10 ) { if ( is_user_logged_in() ) { return false; } if ( ! UM()->options()->get( 'ajax_nopriv_rate_limit' ) ) { return false; } $transient_name = 'um_ajax_nopriv_rate_limit_' . md5( $context . '_' . $_SERVER['REMOTE_ADDR'] ); $rate_limit = get_transient( $transient_name ); $requests_num = apply_filters( 'um_ajax_rate_limit_requests_num', $requests_num, $context ); // 10 requests per minute per IP if ( false === $rate_limit ) { set_transient( $transient_name, 1, MINUTE_IN_SECONDS ); } elseif ( $rate_limit < $requests_num ) { set_transient( $transient_name, $rate_limit + 1, MINUTE_IN_SECONDS ); } else { return true; } return false; } /** * What type of request is this? * * @param string $type String containing name of request type (ajax, frontend, cron or admin) * * @return bool */ public function is_request( $type ) { switch ( $type ) { case 'admin' : return is_admin(); case 'ajax' : return defined( 'DOING_AJAX' ); case 'cron' : return defined( 'DOING_CRON' ); case 'frontend' : return ( ! is_admin() || defined( 'DOING_AJAX' ) ) && ! defined( 'DOING_CRON' ); } return false; } /** * Help Tip displaying * * Function for render/displaying UltimateMember help tip * * @since 2.0.0 * * @param string $tip Help tip text * @param bool $allow_html Allow sanitized HTML if true or escape * @param bool $echo Return HTML or echo * @return string */ function tooltip( $tip, $allow_html = false, $echo = true ) { if ( $allow_html ) { $tip = htmlspecialchars( wp_kses( html_entity_decode( $tip ), array( 'br' => array(), 'em' => array(), 'strong' => array(), 'small' => array(), 'span' => array(), 'ul' => array(), 'li' => array(), 'ol' => array(), 'p' => array(), ) ) ); } else { $tip = esc_attr( $tip ); } ob_start(); ?> <span class="um_tooltip dashicons dashicons-editor-help" title="<?php echo $tip ?>"></span> <?php if ( $echo ) { ob_get_flush(); return ''; } else { return ob_get_clean(); } } /** * @return mixed|void */ function excluded_taxonomies() { $taxes = array( 'nav_menu', 'link_category', 'post_format', ); /** * UM hook * * @type filter * @title um_excluded_taxonomies * @description Exclude taxonomies for UM * @input_vars * [{"var":"$taxes","type":"array","desc":"Taxonomies keys"}] * @change_log * ["Since: 2.0"] * @usage * <?php add_filter( 'um_excluded_taxonomies', 'function_name', 10, 1 ); ?> * @example * <?php * add_filter( 'um_excluded_taxonomies', 'my_excluded_taxonomies', 10, 1 ); * function my_excluded_taxonomies( $taxes ) { * // your code here * return $taxes; * } * ?> */ return apply_filters( 'um_excluded_taxonomies', $taxes ); } /** * Output templates * * @access public * @param string $template_name * @param string $basename (default: '') * @param array $t_args (default: array()) * @param bool $echo * * @return string|void */ public function get_template( $template_name, $basename = '', $t_args = array(), $echo = false ) { if ( ! empty( $t_args ) && is_array( $t_args ) ) { /* * This use of extract() cannot be removed. There are many possible ways that * templates could depend on variables that it creates existing, and no way to * detect and deprecate it. * * Passing the EXTR_SKIP flag is the safest option, ensuring globals and * function variables cannot be overwritten. */ // phpcs:ignore WordPress.PHP.DontExtract.extract_extract extract( $t_args, EXTR_SKIP ); } $path = ''; if ( $basename ) { // use '/' instead of "DIRECTORY_SEPARATOR", because wp_normalize_path makes the correct replacement $array = explode( '/', wp_normalize_path( trim( $basename ) ) ); $path = $array[0]; } $located = $this->locate_template( $template_name, $path ); if ( ! file_exists( $located ) ) { _doing_it_wrong( __FUNCTION__, sprintf( '<code>%s</code> does not exist.', $located ), '2.1' ); return; } /** * UM hook * * @type filter * @title um_get_template * @description Change template location * @input_vars * [{"var":"$located","type":"string","desc":"template Located"}, * {"var":"$template_name","type":"string","desc":"Template Name"}, * {"var":"$path","type":"string","desc":"Template Path at server"}, * {"var":"$t_args","type":"array","desc":"Template Arguments"}] * @change_log * ["Since: 2.0"] * @usage add_filter( 'um_get_template', 'function_name', 10, 4 ); * @example * <?php * add_filter( 'um_get_template', 'my_get_template', 10, 4 ); * function my_get_template( $located, $template_name, $path, $t_args ) { * // your code here * return $located; * } * ?> */ $located = apply_filters( 'um_get_template', $located, $template_name, $path, $t_args ); ob_start(); /** * UM hook * * @type action * @title um_before_template_part * @description Make some action before include template file * @input_vars * [{"var":"$template_name","type":"string","desc":"Template Name"}, * {"var":"$path","type":"string","desc":"Template Path at server"}, * {"var":"$located","type":"string","desc":"template Located"}, * {"var":"$t_args","type":"array","desc":"Template Arguments"}] * @change_log * ["Since: 2.0"] * @usage add_action( 'um_before_template_part', 'function_name', 10, 4 ); * @example * <?php * add_action( 'um_before_template_part', 'my_before_template_part', 10, 4 ); * function my_before_template_part( $template_name, $path, $located, $t_args ) { * // your code here * } * ?> */ do_action( 'um_before_template_part', $template_name, $path, $located, $t_args ); include $located; /** * UM hook * * @type action * @title um_after_template_part * @description Make some action after include template file * @input_vars * [{"var":"$template_name","type":"string","desc":"Template Name"}, * {"var":"$path","type":"string","desc":"Template Path at server"}, * {"var":"$located","type":"string","desc":"template Located"}, * {"var":"$t_args","type":"array","desc":"Template Arguments"}] * @change_log * ["Since: 2.0"] * @usage add_action( 'um_after_template_part', 'function_name', 10, 4 ); * @example * <?php * add_action( 'um_after_template_part', 'my_after_template_part', 10, 4 ); * function my_after_template_part( $template_name, $path, $located, $t_args ) { * // your code here * } * ?> */ do_action( 'um_after_template_part', $template_name, $path, $located, $t_args ); $html = ob_get_clean(); if ( ! $echo ) { return $html; } else { echo $html; return; } } /** * Locate a template and return the path for inclusion. * * @access public * @param string $template_name * @param string $path (default: '') * @return string */ function locate_template( $template_name, $path = '' ) { // check if there is template at theme folder $template = locate_template( array( trailingslashit( 'ultimate-member' . DIRECTORY_SEPARATOR . $path ) . $template_name ) ); if ( ! $template ) { if ( $path ) { $template = trailingslashit( trailingslashit( WP_PLUGIN_DIR ) . $path ); } else { $template = trailingslashit( UM_PATH ); } $template .= 'templates' . DIRECTORY_SEPARATOR . $template_name; } /** * UM hook * * @type filter * @title um_locate_template * @description Change template locate * @input_vars * [{"var":"$template","type":"string","desc":"Template locate"}, * {"var":"$template_name","type":"string","desc":"Template Name"}, * {"var":"$path","type":"string","desc":"Template Path at server"}] * @change_log * ["Since: 2.0"] * @usage add_filter( 'um_locate_template', 'function_name', 10, 3 ); * @example * <?php * add_filter( 'um_locate_template', 'my_locate_template', 10, 3 ); * function my_locate_template( $template, $template_name, $path ) { * // your code here * return $template; * } * ?> */ return apply_filters( 'um_locate_template', $template, $template_name, $path ); } /** * @deprecated 2.8.0 * * @return array */ public function cpt_list() { _deprecated_function( __METHOD__, '2.8.0', 'UM()->common()->cpt()->get_list()' ); return UM()->common()->cpt()->get_list(); } /** * @param array $array * @param string $key * @param array $insert_array * * @return array */ function array_insert_before( $array, $key, $insert_array ) { $index = array_search( $key, array_keys( $array ) ); if ( $index === false ) { return $array; } $array = array_slice( $array, 0, $index, true ) + $insert_array + array_slice( $array, $index, count( $array ) - 1, true ); return $array; } /** * @since 2.1.0 * * @param $var * @return array|string */ function clean_array( $var ) { if ( is_array( $var ) ) { return array_map( array( $this, 'clean_array' ), $var ); } else { return ! is_scalar( $var ) ? sanitize_text_field( $var ) : $var; } } /** * Replace the first match in the string, alternative for the `str_replace()` function * * @param string $search * @param string $replace * @param string $subject * * @return string */ function str_replace_first( $search, $replace, $subject ) { $search = '/' . preg_quote( $search, '/' ) . '/'; return preg_replace( $search, $replace, $subject, 1 ); } /** * @param string $context * * @return array */ public function get_allowed_html( $context = '' ) { switch ( $context ) { case 'wp-admin': $allowed_html = array( 'img' => array( 'alt' => true, 'align' => true, 'border' => true, 'height' => true, 'hspace' => true, 'loading' => true, 'longdesc' => true, 'vspace' => true, 'src' => true, 'srcset' => true, 'usemap' => true, 'width' => true, ), 'ol' => array(), 'ul' => array(), 'li' => array(), 'h1' => array( 'align' => true, ), 'h2' => array( 'align' => true, ), 'h3' => array( 'align' => true, ), 'p' => array( 'align' => true, 'dir' => true, 'lang' => true, ), 'form' => array( 'action' => true, 'accept' => true, 'accept-charset' => true, 'enctype' => true, 'method' => true, 'name' => true, 'target' => true, ), 'label' => array( 'for' => true, ), 'select' => array( 'name' => true, 'multiple' => true, 'disabled' => true, 'readonly' => true, 'required' => true, 'autocomplete' => true, ), 'option' => array( 'value' => true, 'selected' => true, 'disabled' => true, ), 'input' => array( 'type' => true, 'name' => true, 'value' => true, 'placeholder' => true, 'readonly' => true, 'disabled' => true, 'checked' => true, 'selected' => true, 'required' => true, 'autocomplete' => true, ), 'textarea' => array( 'cols' => true, 'rows' => true, 'disabled' => true, 'name' => true, 'readonly' => true, 'required' => true, 'autocomplete' => true, ), 'table' => array( 'align' => true, 'bgcolor' => true, 'border' => true, 'cellpadding' => true, 'cellspacing' => true, 'dir' => true, 'rules' => true, 'summary' => true, 'width' => true, ), 'tbody' => array( 'align' => true, 'char' => true, 'charoff' => true, 'valign' => true, ), 'td' => array( 'abbr' => true, 'align' => true, 'axis' => true, 'bgcolor' => true, 'char' => true, 'charoff' => true, 'colspan' => true, 'dir' => true, 'headers' => true, 'height' => true, 'nowrap' => true, 'rowspan' => true, 'scope' => true, 'valign' => true, 'width' => true, ), 'tfoot' => array( 'align' => true, 'char' => true, 'charoff' => true, 'valign' => true, ), 'th' => array( 'abbr' => true, 'align' => true, 'axis' => true, 'bgcolor' => true, 'char' => true, 'charoff' => true, 'colspan' => true, 'headers' => true, 'height' => true, 'nowrap' => true, 'rowspan' => true, 'scope' => true, 'valign' => true, 'width' => true, ), 'thead' => array( 'align' => true, 'char' => true, 'charoff' => true, 'valign' => true, ), 'tr' => array( 'align' => true, 'bgcolor' => true, 'char' => true, 'charoff' => true, 'valign' => true, ), 'a' => array( 'onclick' => array(), ), ); break; case 'templates': $allowed_html = array( 'style' => array(), 'link' => array( 'rel' => true, 'href' => true, 'media' => true, ), 'svg' => array( 'xmlns' => true, 'height' => true, 'preserveaspectratio' => true, 'viewbox' => true, 'width' => true, 'x' => true, 'y' => true, 'fill' => true, 'stroke' => true, 'stroke-linecap' => true, 'stroke-linejoin' => true, 'stroke-width' => true, ), 'path' => array( 'd' => true, 'stroke' => true, 'stroke-width' => true, 'stroke-linecap' => true, 'stroke-linejoin' => true, 'fill' => true, ), 'form' => array( 'action' => true, 'accept' => true, 'accept-charset' => true, 'enctype' => true, 'method' => true, 'name' => true, 'target' => true, 'novalidate' => true, ), 'label' => array( 'for' => true, ), 'select' => array( 'name' => true, 'multiple' => true, 'disabled' => true, 'readonly' => true, 'required' => true, 'autocomplete' => true, ), 'option' => array( 'value' => true, 'selected' => true, 'disabled' => true, ), 'input' => array( 'type' => true, 'name' => true, 'value' => true, 'placeholder' => true, 'readonly' => true, 'disabled' => true, 'checked' => true, 'selected' => true, 'required' => true, 'autocomplete' => true, 'size' => true, 'step' => true, 'min' => true, 'max' => true, 'minlength' => true, 'maxlength' => true, 'pattern' => true, ), 'textarea' => array( 'cols' => true, 'rows' => true, 'disabled' => true, 'name' => true, 'readonly' => true, 'required' => true, 'autocomplete' => true, 'placeholder' => true, ), 'button' => array( 'type' => true, 'name' => true, 'value' => true, 'placeholder' => true, 'readonly' => true, 'disabled' => true, 'checked' => true, 'selected' => true, 'required' => true, 'autocomplete' => true, ), 'img' => array( 'alt' => true, 'align' => true, 'border' => true, 'height' => true, 'hspace' => true, 'loading' => true, 'longdesc' => true, 'vspace' => true, 'src' => true, 'srcset' => true, 'usemap' => true, 'width' => true, ), 'h1' => array( 'align' => true, ), 'h2' => array( 'align' => true, ), 'h3' => array( 'align' => true, ), 'h4' => array( 'align' => true, ), 'h5' => array( 'align' => true, ), 'h6' => array( 'align' => true, ), 'p' => array( 'align' => true, 'dir' => true, 'lang' => true, ), 'ol' => array(), 'ul' => array(), 'li' => array(), 'time' => array( 'datetime' => true, ), 'section' => array(), 'table' => array( 'align' => true, 'bgcolor' => true, 'border' => true, 'cellpadding' => true, 'cellspacing' => true, 'dir' => true, 'rules' => true, 'summary' => true, 'width' => true, ), 'tbody' => array( 'align' => true, 'char' => true, 'charoff' => true, 'valign' => true, ), 'thead' => array( 'align' => true, 'char' => true, 'charoff' => true, 'valign' => true, ), 'th' => array( 'abbr' => true, 'align' => true, 'axis' => true, 'bgcolor' => true, 'char' => true, 'charoff' => true, 'colspan' => true, 'headers' => true, 'height' => true, 'nowrap' => true, 'rowspan' => true, 'scope' => true, 'valign' => true, 'width' => true, ), 'tr' => array( 'align' => true, 'bgcolor' => true, 'char' => true, 'charoff' => true, 'valign' => true, ), 'td' => array( 'abbr' => true, 'align' => true, 'axis' => true, 'bgcolor' => true, 'char' => true, 'charoff' => true, 'colspan' => true, 'dir' => true, 'headers' => true, 'height' => true, 'nowrap' => true, 'rowspan' => true, 'scope' => true, 'valign' => true, 'width' => true, ), 'tfoot' => array( 'align' => true, 'char' => true, 'charoff' => true, 'valign' => true, ), 'noscript' => array(), 'del' => array(), 'blockquote' => array( 'cite' => true, ), ); break; case 'admin_notice': $allowed_html = array( 'p' => array( 'align' => true, 'dir' => true, 'lang' => true, ), 'label' => array( 'for' => true, ), 'strong' => array( 'style' => true, ), ); break; default: $allowed_html = array(); break; } $global_allowed = array( 'a' => array( 'href' => array(), 'rel' => true, 'rev' => true, 'name' => true, 'target' => true, 'download' => array( 'valueless' => 'y', ), ), 'em' => array(), 'i' => array(), 'b' => array(), 'q' => array( 'cite' => true, ), 's' => array(), 'strike' => array(), 'strong' => array(), 'br' => array(), 'div' => array( 'align' => true, 'dir' => true, 'lang' => true, ), 'span' => array( 'dir' => true, 'align' => true, 'lang' => true, ), 'code' => array(), 'hr' => array( 'style' => true, ), ); $allowed_html = array_merge_recursive( $global_allowed, $allowed_html ); $allowed_html = array_map( '_wp_add_global_attributes', $allowed_html ); /** * Filters the allowed HTML tags and their attributes in the late escaping before echo. * * Note: Please use the `wp_kses()` allowed tags structure. * * @since 2.5.4 * @hook um_late_escaping_allowed_tags * * @param {array} $allowed_html Allowed HTML tags with attributes. * @param {string} $context Function context 'wp-admin' for Admin Dashboard echo, 'templates' for the frontend. * * @return {array} Allowed HTML tags with attributes. * * @example <caption>It adds iframe HTML tag and 'onclick' attribute for strong tag.</caption> * function add_extra_kses_allowed_tags( $allowed_html, $context ) { * if ( 'templates' === $context ) { * $allowed_html['iframe'] = array( * 'src' => true, * ); * $allowed_html['strong']['onclick'] = true; * } * return $allowed_html; * } * add_filter( 'um_late_escaping_allowed_tags', 'add_extra_kses_allowed_tags', 10, 2 ); */ $allowed_html = apply_filters( 'um_late_escaping_allowed_tags', $allowed_html, $context ); return $allowed_html; } } } includes/widgets/class-um-search-widget.php 0000644 00000004620 15252504435 0015010 0 ustar 00 <?php namespace um\widgets; // Exit if accessed directly if ( ! defined( 'ABSPATH' ) ) exit; /** * Class UM_Search_Widget * @package um\widgets */ class UM_Search_Widget extends \WP_Widget { /** * UM_Search_Widget constructor. */ function __construct() { parent::__construct( // Base ID of your widget 'um_search_widget', // Widget name will appear in UI __( 'Ultimate Member - Search', 'ultimate-member' ), // Widget description array( 'description' => __( 'Shows the search member form.', 'ultimate-member' ), ) ); } /** * Creating widget front-end * * @param array $args * @param array $instance */ public function widget( $args, $instance ) { if ( defined( 'REST_REQUEST' ) && REST_REQUEST ) { return; } if ( ! empty( $_GET['legacy-widget-preview'] ) && defined( 'IFRAME_REQUEST' ) && IFRAME_REQUEST ) { return; } $title = array_key_exists( 'title', $instance ) ? $instance['title'] : ''; $title = apply_filters( 'widget_title', $title ); // before and after widget arguments are defined by themes echo $args['before_widget']; if ( ! empty( $title ) ) { echo $args['before_title'] . $title . $args['after_title']; } // display the search form echo apply_shortcodes( '[ultimatemember_searchform /]' ); echo $args['after_widget']; } /** * Widget Backend * * @param array $instance */ public function form( $instance ) { if ( isset( $instance[ 'title' ] ) ) { $title = $instance[ 'title' ]; } else { $title = __( 'Search Users', 'ultimate-member' ); } if ( isset( $instance[ 'max' ] ) ) { $max = $instance[ 'max' ]; } else { $max = 11; } // Widget admin form ?> <p> <label for="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>"><?php _e( 'Title', 'ultimate-member' ); ?>:</label> <input class="widefat" id="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'title' ) ); ?>" type="text" value="<?php echo esc_attr( $title ); ?>" /> </p> <?php } /** * Updating widget replacing old instances with new * * @param array $new_instance * @param array $old_instance * * @return array */ public function update( $new_instance, $old_instance ) { $instance = array(); $instance['title'] = ( ! empty( $new_instance['title'] ) ) ? strip_tags( $new_instance['title'] ) : ''; return $instance; } } includes/admin/class-secure.php 0000644 00000037077 15252504435 0012567 0 ustar 00 <?php /** * Usermeta which we use: * * um_user_blocked__metadata * um_user_blocked * um_user_blocked__timestamp * * um_secure_has_reset_password * um_secure_has_reset_password__timestamp */ namespace um\admin; use WP_Session_Tokens; if ( ! defined( 'ABSPATH' ) ) { exit; } if ( ! class_exists( 'um\admin\Secure' ) ) { /** * Class Secure * * @package um\admin * * @since 2.6.8 */ class Secure { /** * Used for flushing user metas. * * @var bool */ private $need_flush_meta = false; /** * Secure constructor. * * @since 2.6.8 */ public function __construct() { add_action( 'admin_init', array( $this, 'admin_init' ) ); add_filter( 'um_settings_structure', array( $this, 'add_settings' ) ); add_filter( 'manage_users_custom_column', array( $this, 'add_restore_account' ), 9999, 3 ); add_filter( 'pre_get_users', array( $this, 'filter_users_by_date_registered' ) ); add_action( 'um_settings_before_save', array( $this, 'check_secure_changes' ) ); add_action( 'um_settings_save', array( $this, 'on_settings_save' ) ); add_action( 'wp_ajax_um_secure_scan_affected_users', array( $this, 'ajax_scanner' ) ); } /** * Filter users by Register Date * * @since 2.6.8 * @param object $query WP query `pre_get_users` */ public function filter_users_by_date_registered( $query ) { global $pagenow; if ( 'users.php' === $pagenow && is_admin() ) { // phpcs:disable WordPress.Security.NonceVerification $date_from = isset( $_GET['um_secure_date_from'] ) ? $_GET['um_secure_date_from'] : null; $date_to = isset( $_GET['um_secure_date_to'] ) ? $_GET['um_secure_date_to'] : null; // phpcs:enable WordPress.Security.NonceVerification if ( $date_from ) { $date_query_attr = array( 'after' => gmdate( get_option( 'date_format', 'F j, Y' ), strtotime( '-1 day', $date_from ) ), 'before' => gmdate( get_option( 'date_format', 'F j, Y' ), strtotime( '+1 day', $date_from ) ), ); if ( $date_to ) { $date_query_attr['before'] = gmdate( get_option( 'date_format', 'F j, Y' ), strtotime( '+1 day', $date_to ) ); } $query->set( 'date_query', $date_query_attr ); } } return $query; } /** * Handle secure actions. * * @since 2.6.8 */ public function admin_init() { global $wpdb; if ( isset( $_REQUEST['um_secure_expire_all_sessions'] ) && ! wp_doing_ajax() ) { if ( ! wp_verify_nonce( $_REQUEST['_wpnonce'], 'um-secure-expire-session-nonce' ) || ! current_user_can( 'manage_options' ) ) { // This nonce is not valid or current logged-in user has no administrative rights. wp_die( esc_html__( 'Security check', 'ultimate-member' ) ); } /** * Destroy all user sessions except the current logged-in user. */ $wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->usermeta} WHERE meta_key='session_tokens' AND user_id != %d", get_current_user_id() ) ); if ( UM()->options()->get( 'display_login_form_notice' ) ) { global $wpdb; $wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->usermeta} WHERE user_id != %d AND ( meta_key = 'um_secure_has_reset_password' OR meta_key = 'um_secure_has_reset_password__timestamp' )", get_current_user_id() ) ); } wp_safe_redirect( add_query_arg( 'update', 'um_secure_expire_sessions', wp_get_referer() ) ); exit; } if ( isset( $_REQUEST['um_secure_restore_account'], $_REQUEST['user_id'] ) && ! wp_doing_ajax() ) { $user_id = absint( $_REQUEST['user_id'] ); if ( ! wp_verify_nonce( $_REQUEST['_wpnonce'], 'um-security-restore-account-nonce-' . $user_id ) || ! current_user_can( 'manage_options' ) ) { // This nonce is not valid or current logged-in user has no administrative rights. wp_die( esc_html__( 'Security check', 'ultimate-member' ) ); } $user = get_userdata( $user_id ); if ( ! $user ) { wp_die( esc_html__( 'Invalid user.', 'ultimate-member' ) ); } um_fetch_user( $user_id ); $metadata = get_user_meta( $user_id, 'um_user_blocked__metadata', true ); $user->update_user_level_from_caps(); // Restore Roles. if ( isset( $metadata['roles'] ) ) { foreach ( $metadata['roles'] as $role ) { $user->add_role( $role ); } } // Restore Account Status. if ( isset( $metadata['account_status'] ) ) { // Force update of the user status without email notifications. UM()->common()->users()->set_status( $user_id, $metadata['account_status'] ); } // Delete blocked meta. delete_user_meta( $user_id, 'um_user_blocked__metadata' ); delete_user_meta( $user_id, 'um_user_blocked' ); delete_user_meta( $user_id, 'um_user_blocked__timestamp' ); // Don't need to reset a password. if ( UM()->options()->get( 'display_login_form_notice' ) ) { update_user_meta( $user_id, 'um_secure_has_reset_password', true ); update_user_meta( $user_id, 'um_secure_has_reset_password__timestamp', current_time( 'mysql', true ) ); } // Clear Cache. UM()->user()->remove_cache( $user_id ); um_reset_user(); wp_safe_redirect( add_query_arg( 'update', 'um_secure_restore', wp_get_referer() ) ); exit; } } /** * Register Secure Settings * * @since 2.6.8 * * @param array $settings * @return array */ public function add_settings( $settings ) { $nonce = wp_create_nonce( 'um-secure-expire-session-nonce' ); $banned_capabilities = array(); $banned_admin_capabilities = UM()->common()->secure()->get_banned_capabilities_list(); foreach ( $banned_admin_capabilities as $cap ) { $banned_capabilities[ $cap ] = $cap; } $disabled_capabilities = UM()->options()->get_default( 'banned_capabilities' ); $disabled_capabilities_text = '<strong>' . implode( '</strong>, <strong>', $disabled_capabilities ) . '</strong>'; $scanner_content = '<button class="button um-secure-scan-content">' . esc_html__( 'Scan Now', 'ultimate-member' ) . '</button>'; $scanner_content .= '<span class="um-secure-scan-results">'; $scanner_content .= esc_html__( 'Last scan:', 'ultimate-member' ) . ' '; $scan_status = get_option( 'um_secure_scan_status' ); $last_scanned_time = get_option( 'um_secure_last_time_scanned' ); if ( ! empty( $last_scanned_time ) ) { $scanner_content .= human_time_diff( strtotime( $last_scanned_time ) ) . ' ' . esc_html__( 'ago', 'ultimate-member' ); if ( 'started' === $scan_status ) { $scanner_content .= ' - ' . esc_html__( 'Not Completed.', 'ultimate-member' ); } } else { $scanner_content .= esc_html__( 'Not Scanned yet.', 'ultimate-member' ); } $scanner_content .= '</span>'; $secure_fields = array( array( 'id' => 'ajax_nopriv_rate_limit', 'type' => 'checkbox', 'label' => __( 'Rate Limit', 'ultimate-member' ), 'checkbox_label' => __( 'Enable Rate Limiting', 'ultimate-member' ), 'description' => __( 'This prevents brute-force enumeration attempts in guest AJAX requests.', 'ultimate-member' ), ), array( 'id' => 'banned_capabilities', 'type' => 'multi_checkbox', 'multi' => true, 'assoc' => true, 'checkbox_key' => true, 'columns' => 2, 'options_disabled' => $disabled_capabilities, 'options' => $banned_capabilities, 'label' => __( 'Banned Administrative Capabilities', 'ultimate-member' ), // translators: %s are disabled default capabilities that are enabled by default. 'description' => sprintf( __( 'All the above are default Administrator & Super Admin capabilities. When someone tries to inject capabilities to the Account, Profile & Register forms submission, it will be flagged with this option. The %s capabilities are locked to ensure no users will be created with these capabilities.', 'ultimate-member' ), $disabled_capabilities_text ), ), array( 'id' => 'secure_scan_affected_users', 'type' => 'info_text', 'label' => __( 'Scanner', 'ultimate-member' ), 'value' => $scanner_content, 'description' => __( 'Scan your site to check for vulnerabilities prior to Ultimate Member version 2.6.7 and get recommendations to secure your site.', 'ultimate-member' ), ), array( 'id' => 'lock_register_forms', 'type' => 'checkbox', 'label' => __( 'Lock All Register Forms', 'ultimate-member' ), 'checkbox_label' => __( 'Lock Forms', 'ultimate-member' ), 'description' => __( 'This prevents all users from registering with Ultimate Member on your site.', 'ultimate-member' ), ), array( 'id' => 'display_login_form_notice', 'type' => 'checkbox', 'label' => __( 'Display Login form notice to reset passwords', 'ultimate-member' ), 'checkbox_label' => __( 'Enable Login form notice', 'ultimate-member' ), 'description' => __( 'Enforces users to reset their passwords (one-time) and prevent from entering old password.', 'ultimate-member' ), ), ); global $wpdb; $count_users = $wpdb->get_var( "SELECT COUNT(*) FROM {$wpdb->users}" ); $count_users_exclude_me = $count_users - 1; if ( $count_users_exclude_me > 0 ) { $secure_fields[] = array( 'id' => 'force_reset_passwords', 'type' => 'info_text', 'label' => __( 'Expire All Users Sessions', 'ultimate-member' ), // translators: %d is the users count. 'value' => '<a class="button um_secure_force_reset_passwords" href="' . admin_url( '?um_secure_expire_all_sessions=1&_wpnonce=' . esc_attr( $nonce ) ) . '" onclick=\'return confirm("' . esc_js( __( 'Are you sure that you want to make all users sessions expired?', 'ultimate-member' ) ) . '");\'>' . esc_html( sprintf( __( 'Logout Users (%d)', 'ultimate-member' ), $count_users_exclude_me ) ) . '</a>', 'description' => __( 'This will log out all users on your site and forces them to reset passwords <br/>when <strong>"Display Login form notice to reset passwords" is enabled/checked.</strong>', 'ultimate-member' ), ); } $secure_fields = array_merge( $secure_fields, array( array( 'id' => 'secure_ban_admins_accounts', 'type' => 'checkbox', 'label' => __( 'Administrative capabilities ban', 'ultimate-member' ), 'checkbox_label' => __( 'Enable ban for administrative capabilities', 'ultimate-member' ), 'description' => __( ' When someone tries to inject capabilities to the Account, Profile & Register forms submission, it will be banned.', 'ultimate-member' ), ), array( 'id' => 'secure_notify_admins_banned_accounts', 'type' => 'checkbox', 'label' => __( 'Notify Administrators', 'ultimate-member' ), 'checkbox_label' => __( 'Enable notification', 'ultimate-member' ), 'description' => __( 'When enabled, All administrators will be notified when someone has suspicious activities in the Account, Profile & Register forms.', 'ultimate-member' ), 'conditional' => array( 'secure_ban_admins_accounts', '=', 1 ), ), array( 'id' => 'secure_notify_admins_banned_accounts__interval', 'type' => 'select', 'options' => array( 'instant' => __( 'Send Immediately', 'ultimate-member' ), 'hourly' => __( 'Hourly', 'ultimate-member' ), 'daily' => __( 'Daily', 'ultimate-member' ), ), 'label' => __( 'Notification Schedule', 'ultimate-member' ), 'conditional' => array( 'secure_notify_admins_banned_accounts', '=', 1 ), ), array( 'id' => 'secure_allowed_redirect_hosts', 'type' => 'textarea', 'label' => __( 'Allowed hosts for safe redirect (one host per line)', 'ultimate-member' ), 'description' => __( 'Extend allowed hosts for frontend pages redirects.', 'ultimate-member' ), ), ) ); $settings['advanced']['sections'] = UM()->array_insert_before( $settings['advanced']['sections'], 'developers', array( 'security' => array( 'title' => __( 'Security', 'ultimate-member' ), 'description' => __( 'This feature scans for suspicious registered accounts, bans the usage of administrative capabilities to site subscribers/members, allows the website administrators to force all users to reset their passwords, preventing users from logging-in using their old passwords that may have been exposed.', 'ultimate-member' ), 'fields' => $secure_fields, ), ) ); return $settings; } /** * Append blocked status to the `account_status` column rows. * * @param string $val Default column row value. * @param string $column_name Current column name. * @param int $user_id User ID in loop. * * @since 2.6.8 * * @return string */ public function add_restore_account( $val, $column_name, $user_id ) { if ( 'account_status' === $column_name ) { um_fetch_user( $user_id ); $is_blocked = um_user( 'um_user_blocked' ); $account_status = UM()->common()->users()->get_status( $user_id ); if ( ! empty( $is_blocked ) && in_array( $account_status, array( 'rejected', 'inactive' ), true ) ) { $datetime = um_user( 'um_user_blocked__timestamp' ); $val .= '<div><small>' . esc_html__( 'Blocked Due to Suspicious Activity', 'ultimate-member' ) . '</small></div>'; $nonce = wp_create_nonce( 'um-security-restore-account-nonce-' . $user_id ); $restore_account_url = admin_url( 'users.php?user_id=' . $user_id . '&um_secure_restore_account=1&_wpnonce=' . $nonce ); $action = ' · <a href=" ' . esc_url( $restore_account_url ) . ' " onclick=\'return confirm("' . esc_js( __( 'Are you sure that you want to restore this account after getting flagged for suspicious activity?', 'ultimate-member' ) ) . '");\'><small>' . esc_html__( 'Restore Account', 'ultimate-member' ) . '</small></a>'; if ( ! empty( $datetime ) ) { $val .= '<div><small>' . human_time_diff( strtotime( $datetime ) ) . ' ' . __( 'ago', 'ultimate-member' ) . '</small>' . $action . '</div>'; } } um_reset_user(); } return $val; } /** * */ public function check_secure_changes() { if ( isset( $_POST['um_options']['display_login_form_notice'] ) ) { //phpcs:ignore WordPress.Security.NonceVerification $current_option_value = UM()->options()->get( 'display_login_form_notice' ); if ( empty( $current_option_value ) ) { return; } if ( empty( $_POST['um_options']['display_login_form_notice'] ) ) { //phpcs:ignore WordPress.Security.NonceVerification $this->need_flush_meta = true; } } } /** * */ public function on_settings_save() { if ( isset( $_POST['um_options']['display_login_form_notice'] ) && ! empty( $this->need_flush_meta ) ) { //phpcs:ignore WordPress.Security.NonceVerification global $wpdb; $wpdb->query( "DELETE FROM {$wpdb->usermeta} WHERE meta_key = 'um_secure_has_reset_password' OR meta_key = 'um_secure_has_reset_password__timestamp'" ); } if ( isset( $_POST['um_options']['secure_notify_admins_banned_accounts'] ) ) { //phpcs:ignore WordPress.Security.NonceVerification if ( ! empty( $_POST['um_options']['secure_notify_admins_banned_accounts'] ) ) { //phpcs:ignore WordPress.Security.NonceVerification UM()->options()->update( 'suspicious-activity_on', 1 ); } else { UM()->options()->update( 'suspicious-activity_on', 0 ); } } } } } includes/admin/class-extensions-updater.php 0000644 00000013772 15252504435 0015136 0 ustar 00 <?php namespace um\admin; if ( ! defined( 'ABSPATH' ) ) { exit; } /** * This class handles all functions that changes data structures and moving files */ class Extensions_Updater { const EXTRA_TIME = 30; const PAGINATION = 50; /** * @var array */ private $updater_data; /** * @param false|array $args */ public function __construct( $args = false ) { if ( empty( $args ) ) { return; } $this->updater_data = wp_parse_args( $args, array( 'slug' => '', 'version' => '0.0.0', 'path' => '', ) ); add_action( 'admin_init', array( $this, 'maybe_run_updater' ) ); add_action( 'um_' . $this->updater_data['slug'] . '_package_start', array( $this, 'package_start' ), 10, 4 ); add_action( 'um_' . $this->updater_data['slug'] . '_package_complete', array( $this, 'package_complete' ) ); } public function package_start( $version, $file_path, $delay, $per_page ) { $hooks = array( 'start' => 'um_' . $this->updater_data['slug'] . '_package_start', 'complete' => 'um_' . $this->updater_data['slug'] . '_package_complete', ); $debug = defined( 'UM_UPDATER_DEBUG' ) && UM_UPDATER_DEBUG; include_once $file_path; /** * IMPORTANT!!!: Last action that we need to do after package is complete. * `UM()->maybe_action_scheduler()->schedule_single_action( * time() + 1, * $hook, * array( * 'version' => $version, * ) * );` */ } public function package_complete( $version ) { $this->set_last_version_upgrade( $version ); $this->reset_in_process_package_version(); } /** * Maybe run upgrade if needed. */ public function maybe_run_updater() { // Cold start to avoid scheduled actions duplicates. Don't remove it. $init = get_transient( 'um_' . $this->updater_data['slug'] . '_updater_init' ); if ( ! empty( $init ) ) { return; } set_transient( 'um_' . $this->updater_data['slug'] . '_updater_init', true, 10 ); $next_package = $this->get_next_package(); if ( empty( $next_package ) ) { $this->set_last_version_upgrade( $this->updater_data['version'] ); $this->reset_in_process_package_version(); return; } list( $package_version, $file_path ) = $next_package; $in_process_package = $this->get_in_process_package_version(); if ( ! empty( $in_process_package ) && version_compare( $in_process_package, $package_version, '=' ) ) { return; } // Initialize start package action. $action_id = UM()->maybe_action_scheduler()->schedule_single_action( time() + self::EXTRA_TIME, 'um_' . $this->updater_data['slug'] . '_package_start', array( 'version' => $package_version, 'path' => $file_path, 'delay' => self::EXTRA_TIME, 'per_page' => self::PAGINATION, ) ); // As soon as scheduler single action is created - then set in progress package version to avoid duplicates of the package start action. if ( ! empty( $action_id ) ) { $this->set_in_process_package_version( $package_version ); } } private function get_next_package() { $last_version_upgrade = $this->get_last_version_upgrade(); if ( ! empty( $last_version_upgrade ) && version_compare( $last_version_upgrade, $this->updater_data['version'], '>=' ) ) { return null; } $packages = $this->get_packages(); if ( empty( $packages ) ) { return null; } $packages_dir = $this->get_packages_dir(); foreach ( $packages as $package_version ) { if ( version_compare( $package_version, $last_version_upgrade, '<=' ) ) { continue; } if ( version_compare( $package_version, $this->updater_data['version'], '>' ) ) { continue; } $file_path = $packages_dir . $package_version . '.php'; if ( ! file_exists( $file_path ) ) { continue; } return array( $package_version, $file_path ); } return null; } /** * Get packages list, based on the files in packages dir. */ private function get_packages() { $packages = array(); $handle = opendir( $this->get_packages_dir() ); // phpcs:ignore Generic.CodeAnalysis.AssignmentInCondition.FoundInWhileCondition, WordPress.CodeAnalysis.AssignmentInCondition.FoundInWhileCondition -- reading folder's content here while ( false !== ( $filename = readdir( $handle ) ) ) { if ( '.' !== $filename && '..' !== $filename ) { $packages[] = preg_replace( '/(.*?)\.php/i', '$1', $filename ); } } closedir( $handle ); usort( $packages, static function ( $a, $b ) { return version_compare( $a, $b ); } ); return $packages; } /** * Retrieve the directory path where packages are stored for updates. * * @return string The normalized path to the packages' directory. */ private function get_packages_dir() { return wp_normalize_path( $this->updater_data['path'] . 'includes/updates/' ); } /** * Gets the last version upgrade from options. * * @return string The last version upgrade. */ private function get_last_version_upgrade() { return get_option( 'um_' . $this->updater_data['slug'] . '_last_version_upgrade', '0.0.0' ); } /** * Set the last version upgrade for the updater. * * @param string $version The version to set as the last upgrade version. */ private function set_last_version_upgrade( $version ) { update_option( 'um_' . $this->updater_data['slug'] . '_last_version_upgrade', $version ); } /** * Gets the last version upgrade from options. * * @return string The last version upgrade. */ private function get_in_process_package_version() { return get_option( 'um_' . $this->updater_data['slug'] . '_in_process_package_upgrade', '' ); } /** * Set the last version upgrade for the updater. * * @param string $version The version to set as the last upgrade version. */ private function set_in_process_package_version( $version ) { update_option( 'um_' . $this->updater_data['slug'] . '_in_process_package_upgrade', $version ); } /** * Set the last version upgrade for the updater. */ private function reset_in_process_package_version() { update_option( 'um_' . $this->updater_data['slug'] . '_in_process_package_upgrade', '' ); } } includes/admin/core/class-admin-theme-updater.php 0000644 00000010736 15252504435 0016054 0 ustar 00 <?php namespace um\admin\core; if ( ! defined( 'ABSPATH' ) ) { exit; } if ( ! class_exists( 'um\admin\core\Admin_Theme_Updater' ) ) { /** * Class Admin_Theme_Updater * @package um\admin\core */ class Admin_Theme_Updater { /** * Restored themes * @var array */ private $restored = array(); /** * Saved themes * @var array */ private $saved = array(); /** * Constructor. */ public function __construct() { add_filter( 'upgrader_package_options', array( $this, 'upgrader_package_options' ), 40, 1 ); add_action( 'upgrader_process_complete', array( $this, 'upgrader_process_complete' ), 40, 2 ); } /** * Copy directory * @param string $src * @param string $dest */ public static function recurse_copy( $src, $dest ) { if ( ! is_dir( $dest ) ) { @mkdir( $dest, 0777, true ); } $dir = opendir( $src ); while ( false !== ( $file = readdir( $dir ) ) ) { if ( ( $file != '.' ) && ( $file != '..' ) ) { if ( is_dir( $src . DIRECTORY_SEPARATOR . $file ) ) { self::recurse_copy( $src . DIRECTORY_SEPARATOR . $file, $dest . DIRECTORY_SEPARATOR . $file ); } else { copy( $src . DIRECTORY_SEPARATOR . $file, $dest . DIRECTORY_SEPARATOR . $file ); } } } closedir( $dir ); } /** * Restore UM templates to theme directory * * @param string $name * @return void */ public function restore_templates( $name = '' ) { $theme = wp_get_theme( $name ); if ( empty( $theme ) || ! $theme->exists() ) { return; } if ( isset( $this->restored[ $theme->get( 'Name' ) ] ) ) { return; } if ( empty( $this->saved[ $theme->get( 'Name' ) ] ) ) { return; } $old_version = get_option( 'theme_version ' . $theme->get( 'Name' ) ); $version = $theme->get( 'Version' ); if ( $old_version === $version ) { return; } $temp_dir = UM()->uploader()->get_core_temp_dir() . DIRECTORY_SEPARATOR . 'themes' . DIRECTORY_SEPARATOR . $theme->get( 'template' ); if ( ! is_dir( $temp_dir ) ) { return; } $um_dir = $theme->get_stylesheet_directory() . DIRECTORY_SEPARATOR . 'ultimate-member'; @mkdir( $um_dir, 0777, true ); $src = realpath( $temp_dir ); $dest = realpath( $um_dir ); if ( $src && $dest ) { self::recurse_copy( $src, $dest ); error_log( "UM Log. Theme '" . $theme->get( 'Name' ) . "' templates restored." ); UM()->files()->remove_dir( $src ); } else { error_log( 'UM Error. Can not restore theme templates.' ); } delete_option( 'theme_version ' . $theme->get( 'Name' ) ); $this->restored[ $theme->get( 'Name' ) ] = $theme->get( 'Version' ); } /** * Save UM templates to temp directory * @param string $name * * @return void */ public function save_templates( $name = '' ) { $theme = wp_get_theme( $name ); if ( empty( $theme ) || ! $theme->exists() ) { return; } if ( isset( $this->restored[ $theme->get( 'Name' ) ] ) ) { return; } if ( isset( $this->saved[ $theme->get( 'Name' ) ] ) ) { return; } $um_dir = $theme->get_stylesheet_directory() . DIRECTORY_SEPARATOR . 'ultimate-member'; if ( ! is_dir( $um_dir ) ) { return; } $temp_dir = UM()->uploader()->get_core_temp_dir() . DIRECTORY_SEPARATOR . 'themes' . DIRECTORY_SEPARATOR . $theme->get( 'template' ); @mkdir( $temp_dir, 0777, true ); $src = realpath( $um_dir ); $dest = realpath( $temp_dir ); if ( $src && $dest ) { self::recurse_copy( $src, $dest ); error_log( "UM Log. Theme '" . $theme->get( 'Name' ) . "' templates saved." ); } else { error_log( 'UM Error. Can not save theme templates.' ); } update_option( 'theme_version ' . $theme->get( 'Name' ), $theme->get( 'Version' ) ); $this->saved[ $theme->get( 'Name' ) ] = $theme->get( 'Version' ); } /** * Filter: upgrader_package_options * * @param array $options * @return array */ function upgrader_package_options( $options ) { if ( isset( $options['hook_extra'] ) && isset( $options['hook_extra']['theme'] ) ) { $this->save_templates( $options['hook_extra']['theme'] ); } return $options; } /** * Action: upgrader_process_complete * * @param \WP_Upgrader $WP_Upgrader * @param array $options */ public function upgrader_process_complete( $WP_Upgrader, $options ) { if ( isset( $options['themes'] ) && is_array( $options['themes'] ) ) { foreach ( $options['themes'] as $theme ) { $this->restore_templates( $theme ); } } } } } includes/admin/core/class-admin-gdpr.php 0000644 00000022041 15252504435 0014234 0 ustar 00 <?php namespace um\admin\core; // Exit if accessed directly. if ( ! defined( 'ABSPATH' ) ) exit; if ( ! class_exists( 'um\admin\core\Admin_GDPR' ) ) { /** * Class Admin_GDPR * @package um\admin\core */ class Admin_GDPR { /** * @var array */ var $meta_associations = array(); /** * Admin_GDPR constructor. */ function __construct() { add_action( 'init', array( &$this, 'init_fields' ) ); add_action( 'admin_init', array( &$this, 'plugin_add_suggested_privacy_content' ), 20 ); add_filter( 'wp_privacy_personal_data_exporters', array( &$this, 'plugin_register_exporters' ) ); add_filter( 'wp_privacy_personal_data_erasers', array( &$this, 'plugin_register_erasers' ) ); add_action( 'um_admin_custom_register_metaboxes', array( &$this, 'add_metabox_register' ) ); } /** * */ function add_metabox_register() { add_meta_box( "um-admin-form-register_gdpr", __( 'Privacy Policy', 'ultimate-member' ), array( UM()->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 date', '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 * <?php add_filter( 'um_gdpr_meta_associations', 'function_name', 10, 1 ); ?> * @example * <?php * add_filter( 'um_gdpr_meta_associations', 'my_gdpr_meta_associations', 10, 1 ); * function my_gdpr_meta_associations( $meta_associations ) { * // your code here * return $meta_associations; * } * ?> */ $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( UM_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' => UM_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 = UM_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' => UM_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 { // translators: %s: metadata name. $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, ); } } } includes/admin/core/class-admin-forms-settings.php 0000644 00000002712 15252504435 0016267 0 ustar 00 <?php namespace um\admin\core; if ( ! defined( 'ABSPATH' ) ) { exit; } if ( ! class_exists( 'um\admin\core\Admin_Forms_Settings' ) ) { /** * Class Admin_Forms_Settings * @package um\admin\core */ class Admin_Forms_Settings extends Admin_Forms { /** * Admin_Forms constructor. * @param bool $form_data */ public function __construct( $form_data = false ) { parent::__construct( $form_data ); } /** * Get field value. * * @param array $field_data * @param string $i * * @return string|array */ public function get_field_value( $field_data, $i = '' ) { $default_key = 'default' . $i; $value_key = 'value' . $i; $id_key = 'id' . $i; $default = isset( $field_data[ $default_key ] ) ? $field_data[ $default_key ] : UM()->options()->get_default( $field_data[ $id_key ] ); if ( in_array( $field_data['type'], array( 'checkbox', 'multi_checkbox' ), true ) ) { if ( isset( $field_data[ $value_key ] ) ) { return $field_data[ $value_key ]; } $value = UM()->options()->get( $field_data[ $id_key ] ); $value = is_string( $value ) ? stripslashes( $value ) : $value; return '' !== $value ? $value : $default; } if ( isset( $field_data[ $value_key ] ) ) { return $field_data[ $value_key ]; } $value = UM()->options()->get( $field_data[ $id_key ] ); $value = is_string( $value ) ? stripslashes( $value ) : $value; return isset( $value ) ? $value : $default; } } } includes/admin/core/class-admin-upgrade.php 0000644 00000026626 15252504435 0014744 0 ustar 00 <?php namespace um\admin\core; if ( ! defined( 'ABSPATH' ) ) exit; if ( ! class_exists( 'um\admin\core\Admin_Upgrade' ) ) { /** * Class Admin_Upgrade * * This class handles all functions that changes data structures and moving files * * @package um\admin\core */ class Admin_Upgrade { /** * @var null */ protected static $instance = null; /** * @var */ var $update_versions; var $update_packages; var $necessary_packages; /** * @var string */ var $packages_dir; /** * Main Admin_Upgrade Instance * * Ensures only one instance of UM is loaded or can be loaded. * * @since 1.0 * @static * @see UM() * @return Admin_Upgrade - Main instance */ static public function instance() { if ( is_null( self::$instance ) ) { self::$instance = new self(); } return self::$instance; } /** * Admin_Upgrade constructor. */ function __construct() { $this->packages_dir = plugin_dir_path( __FILE__ ) . 'packages' . DIRECTORY_SEPARATOR; $this->necessary_packages = $this->need_run_upgrades(); if ( ! empty( $this->necessary_packages ) ) { add_action( 'admin_menu', array( $this, 'admin_menu' ), 0 ); add_action( 'wp_loaded', array( $this, 'initialize_upgrade_packages' ), 0 ); } add_action( 'in_plugin_update_message-' . UM_PLUGIN, array( $this, 'in_plugin_update_message' ) ); } /** * Initialize packages for upgrade process. * Note: Making that only for the 'manage_options' user and when AJAX running. */ public function initialize_upgrade_packages() { if ( defined( 'DOING_AJAX' ) && DOING_AJAX && current_user_can( 'manage_options' ) ) { $this->init_packages_ajax(); add_action( 'wp_ajax_um_run_package', array( $this, 'ajax_run_package' ) ); add_action( 'wp_ajax_um_get_packages', array( $this, 'ajax_get_packages' ) ); } } /** * Function for major updates * */ function in_plugin_update_message( $args ) { $show_additional_notice = false; if ( isset( $args['new_version'] ) ) { $old_version_array = explode( '.', UM_VERSION ); $new_version_array = explode( '.', $args['new_version'] ); if ( $old_version_array[0] < $new_version_array[0] ) { $show_additional_notice = true; } else { if ( $old_version_array[1] < $new_version_array[1] ) { $show_additional_notice = true; } } } if ( $show_additional_notice ) { ob_start(); ?> <style type="text/css"> .um_plugin_upgrade_notice { font-weight: 400; color: #fff; background: #d53221; padding: 1em; margin: 9px 0; display: block; box-sizing: border-box; -webkit-box-sizing: border-box; -moz-box-sizing: border-box; } .um_plugin_upgrade_notice:before { content: "\f348"; display: inline-block; font: 400 18px/1 dashicons; speak: none; margin: 0 8px 0 -2px; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; vertical-align: top; } </style> <span class="um_plugin_upgrade_notice"> <?php // translators: %s: new version. echo wp_kses( sprintf( __( '%s is a major update, and we highly recommend creating a full backup of your site before updating.', 'ultimate-member' ), $args['new_version'] ), UM()->get_allowed_html( 'admin_notice' ) ); ?> </span> <?php ob_get_flush(); } } /** * @return array */ function get_extension_upgrades() { $extensions = UM()->extensions()->get_list(); if ( empty( $extensions ) ) { return array(); } $upgrades = array(); foreach ( $extensions as $extension ) { $upgrades[ $extension ] = UM()->extensions()->get_packages( $extension ); } return $upgrades; } /** * Get array of necessary upgrade packages * * @return array */ function need_run_upgrades() { $um_last_version_upgrade = get_option( 'um_last_version_upgrade', '1.3.88' ); $diff_packages = array(); $all_packages = $this->get_packages(); foreach ( $all_packages as $package ) { if ( version_compare( $um_last_version_upgrade, $package, '<' ) && version_compare( $package, UM_VERSION, '<=' ) ) { $diff_packages[] = $package; } } return $diff_packages; } /** * Get all upgrade packages * * @return array */ function get_packages() { $update_versions = array(); $handle = opendir( $this->packages_dir ); if ( $handle ) { while ( false !== ( $filename = readdir( $handle ) ) ) { if ( $filename != '.' && $filename != '..' ) { if ( is_dir( $this->packages_dir . $filename ) ) { $update_versions[] = $filename; } } } closedir( $handle ); usort( $update_versions, array( &$this, 'version_compare_sort' ) ); } return $update_versions; } /** * */ function init_packages_ajax() { foreach ( $this->necessary_packages as $package ) { $hooks_file = $this->packages_dir . $package . DIRECTORY_SEPARATOR . 'hooks.php'; if ( file_exists( $hooks_file ) ) { $pack_ajax_hooks = include_once $hooks_file; foreach ( $pack_ajax_hooks as $action => $function ) { add_action( 'wp_ajax_um_' . $action, "um_upgrade_$function" ); } } } } /** * */ function init_packages_ajax_handlers() { foreach ( $this->necessary_packages as $package ) { $handlers_file = $this->packages_dir . $package . DIRECTORY_SEPARATOR . 'functions.php'; if ( file_exists( $handlers_file ) ) { include_once $handlers_file; } } } /** * Add Upgrades admin menu */ function admin_menu() { add_submenu_page( 'ultimatemember', __( 'Upgrade', 'ultimate-member' ), '<span style="color:#ca4a1f;">' . __( 'Upgrade', 'ultimate-member' ) . '</span>', 'manage_options', 'um_upgrade', array( &$this, 'upgrade_page' ) ); } /** * Upgrade Menu Callback Page */ function upgrade_page() { $um_last_version_upgrade = get_option( 'um_last_version_upgrade', __( 'empty', 'ultimate-member' ) ); ?> <div class="wrap"> <h2> <?php // translators: %s: plugin name. echo wp_kses( sprintf( __( '%s - Upgrade Process', 'ultimate-member' ), UM_PLUGIN_NAME ), UM()->get_allowed_html( 'admin_notice' ) ); ?> </h2> <p> <?php // translators: %1$s is a plugin version; %2$s is a last version upgrade. echo wp_kses( sprintf( __( 'You have installed <strong>%1$s</strong> version. Your latest DB version is <strong>%2$s</strong>. We recommend creating a backup of your site before running the update process. Do not exit the page before the update process has complete.', 'ultimate-member' ), UM_VERSION, $um_last_version_upgrade ), UM()->get_allowed_html( 'admin_notice' ) ); ?> </p> <p><?php _e( 'After clicking the <strong>"Run"</strong> button, the update process will start. All information will be displayed in the <strong>"Upgrade Log"</strong> field.', 'ultimate-member' ); ?></p> <p><?php _e( 'If the update was successful, you will see a corresponding message. Otherwise, contact technical support if the update failed.', 'ultimate-member' ); ?></p> <h4><?php _e( 'Upgrade Log', 'ultimate-member' ) ?></h4> <div id="upgrade_log" style="width: 100%;height:300px; overflow: auto;border: 1px solid #a1a1a1;margin: 0 0 10px 0;"></div> <div> <input type="button" id="run_upgrade" class="button button-primary" value="<?php esc_attr_e( 'Run', 'ultimate-member' ) ?>"/> </div> </div> <script type="text/javascript"> var um_request_throttle = 15000; var um_packages; jQuery( document ).ready( function() { jQuery( '#run_upgrade' ).click( function() { jQuery(this).prop( 'disabled', true ); um_add_upgrade_log( 'Upgrade Process Started...' ); um_add_upgrade_log( 'Get Upgrades Packages...' ); jQuery.ajax({ url: '<?php echo esc_js( admin_url( 'admin-ajax.php' ) ) ?>', type: 'POST', dataType: 'json', data: { action: 'um_get_packages', nonce: um_admin_scripts.nonce }, success: function( response ) { um_packages = response.data.packages; um_add_upgrade_log( 'Upgrades Packages are ready, start unpacking...' ); //run first package....the running of the next packages will be at each init.php file um_run_upgrade(); } }); }); }); /** * * @returns {boolean} */ function um_run_upgrade() { if ( um_packages.length ) { // 30s between upgrades setTimeout( function () { var pack = um_packages.shift(); um_add_upgrade_log( '<br />=================================================================' ); um_add_upgrade_log( '<h4 style="font-weight: bold;">Prepare package "' + pack + '" version...</h4>' ); jQuery.ajax({ url: '<?php echo esc_js( admin_url( 'admin-ajax.php' ) ) ?>', type: 'POST', dataType: 'html', data: { action: 'um_run_package', pack: pack, nonce: um_admin_scripts.nonce }, success: function( html ) { um_add_upgrade_log( 'Package "' + pack + '" is ready. Start the execution...' ); jQuery( '#run_upgrade' ).after( html ); } }); }, um_request_throttle ); } else { window.location = '<?php echo add_query_arg( array( 'page' => 'ultimatemember', 'msg' => 'updated' ), admin_url( 'admin.php' ) ) ?>' } return false; } /** * * @param line */ function um_add_upgrade_log( line ) { var log_field = jQuery( '#upgrade_log' ); var previous_html = log_field.html(); log_field.html( previous_html + line + "<br />" ); } function um_wrong_ajax() { um_add_upgrade_log( 'Wrong AJAX response...' ); um_add_upgrade_log( 'Your upgrade was crashed, please contact with support' ); } function um_something_wrong() { um_add_upgrade_log( 'Something went wrong with AJAX request...' ); um_add_upgrade_log( 'Your upgrade was crashed, please contact with support' ); } </script> <?php } function ajax_run_package() { UM()->admin()->check_ajax_nonce(); if ( empty( $_POST['pack'] ) ) { exit(''); } else { $pack = sanitize_text_field( $_POST['pack'] ); if ( in_array( $pack, $this->necessary_packages, true ) ) { $file = $this->packages_dir . $pack . DIRECTORY_SEPARATOR . 'init.php'; if ( file_exists( $file ) ) { ob_start(); include_once $file; ob_get_flush(); exit; } else { exit(''); } } else { exit(''); } } } function ajax_get_packages() { UM()->admin()->check_ajax_nonce(); $update_versions = $this->need_run_upgrades(); wp_send_json_success( array( 'packages' => $update_versions ) ); } /** * Parse packages dir for packages files */ function set_update_versions() { $update_versions = array(); $handle = opendir( $this->packages_dir ); if ( $handle ) { while ( false !== ( $filename = readdir( $handle ) ) ) { if ( $filename != '.' && $filename != '..' ) $update_versions[] = preg_replace( '/(.*?)\.php/i', '$1', $filename ); } closedir( $handle ); usort( $update_versions, array( &$this, 'version_compare_sort' ) ); $this->update_versions = $update_versions; } } /** * Sort versions by version compare function * @param $a * @param $b * @return mixed */ function version_compare_sort( $a, $b ) { return version_compare( $a, $b ); } } } includes/admin/core/class-admin-metabox.php 0000644 00000305156 15252504435 0014752 0 ustar 00 <?php namespace um\admin\core; use WP_Post; if ( ! defined( 'ABSPATH' ) ) { exit; } if ( ! class_exists( 'um\admin\core\Admin_Metabox' ) ) { /** * Class Admin_Metabox * * @package um\admin\core */ class Admin_Metabox { /** * @var bool */ private $form_nonce_added = false; /** * @var bool */ private $directory_nonce_added = false; /** * @var bool */ private $custom_nonce_added = false; public $init_icon = false; /** * @var bool */ public $in_edit = false; /** * @var null */ public $edit_mode_value = null; /** * @var array */ public $edit_array = array(); /** * @var array */ public $postmeta = array(); /** * @var bool */ public $is_loaded = false; public $set_field_type; /** * Admin_Metabox constructor. */ public function __construct() { add_action( 'admin_head', array( &$this, 'admin_head' ), 9 ); add_action( 'admin_footer', array( &$this, 'load_modal_content' ), 9 ); add_action( 'admin_init', array( &$this, 'remove_meta_box' ), 0 ); add_filter( 'enter_title_here', array( &$this, 'enter_title_here' ), 10, 2 ); add_action( 'load-post.php', array( &$this, 'add_metabox' ), 9 ); add_action( 'load-post-new.php', array( &$this, 'add_metabox' ), 9 ); add_action( 'admin_init', array( &$this, 'add_taxonomy_metabox' ), 9 ); //roles metaboxes add_action( 'um_roles_add_meta_boxes', array( &$this, 'add_metabox_role' ) ); add_filter( 'um_builtin_validation_types_continue_loop', array( &$this, 'validation_types_continue_loop' ), 1, 4 ); add_filter( 'um_restrict_content_hide_metabox', array( &$this, 'hide_metabox_restrict_content_shop' ), 10, 1 ); add_filter( 'um_member_directory_meta_value_before_save', array( UM()->member_directory(), 'before_save_data' ), 10, 3 ); } public function remove_meta_box() { remove_meta_box( 'submitdiv', 'um_form', 'core' ); remove_meta_box( 'slugdiv', 'um_form', 'core' ); remove_meta_box( 'submitdiv', 'um_directory', 'core' ); remove_meta_box( 'slugdiv', 'um_directory', 'core' ); } /** * Enter title placeholder * * @param string $title * @param WP_Post $post * * @return string */ public function enter_title_here( $title, $post ) { if ( ! isset( $post->post_type ) ) { return $title; } if ( 'um_directory' === $post->post_type ) { $title = __( 'e.g. Member Directory', 'ultimate-member' ); } elseif ( 'um_form' === $post->post_type ) { $title = __( 'e.g. New Registration Form', 'ultimate-member' ); } return $title; } /** * Hide Woocommerce Shop page restrict content metabox * @param $hide * * @return bool */ function hide_metabox_restrict_content_shop( $hide ) { if ( function_exists( 'wc_get_page_id' ) && ! empty( $_GET['post'] ) && absint( $_GET['post'] ) == wc_get_page_id( 'shop' ) ) { return true; } return $hide; } /** * Filter validation types on loop * * @param $break * @param $key * @param $form_id * @param $field_array * * @return bool */ function validation_types_continue_loop( $break, $key, $form_id, $field_array ) { // show unique username validation only for user_login field if ( isset( $field_array['metakey'] ) && $field_array['metakey'] == 'user_login' && $key !== 'unique_username' ) { return false; } return $break; } /** * Gets the role meta * * @param $id * * @return mixed */ function get_custom_post_meta( $id ) { $all_meta = get_post_custom( $id ); foreach ( $all_meta as $k => $v ) { if ( strstr( $k, '_um_' ) ) { $um_meta[ $k ] = $v; } } if ( isset( $um_meta ) ) { return $um_meta; } return false; } /** * Runs on admin head */ public function admin_head() { global $post; if ( isset( $post->ID ) && UM()->admin()->screen()->is_own_post_type() ) { $this->postmeta = $this->get_custom_post_meta( $post->ID ); } } /** * Init the metaboxes */ public function add_metabox() { global $current_screen; if ( 'um_form' === $current_screen->id ) { add_action( 'add_meta_boxes', array( &$this, 'add_metabox_form' ), 1 ); add_action( 'save_post', array( &$this, 'save_metabox_form' ), 10, 2 ); } elseif ( 'um_directory' === $current_screen->id ) { add_action( 'add_meta_boxes', array( &$this, 'add_metabox_directory' ), 1 ); add_action( 'save_post', array( &$this, 'save_metabox_directory' ), 10, 2 ); } //restrict content metabox $post_types = UM()->options()->get( 'restricted_access_post_metabox' ); if ( ! empty( $post_types[ $current_screen->id ] ) ) { /** * UM hook * * @type filter * @title um_restrict_content_hide_metabox * @description Show/Hide Restrict content metabox * @input_vars * [{"var":"$show","type":"bool","desc":"Show Metabox"}] * @change_log * ["Since: 2.0"] * @usage add_filter( 'um_restrict_content_hide_metabox', 'function_name', 10, 1 ); * @example * <?php * add_filter( 'um_restrict_content_hide_metabox', 'my_restrict_content_hide_metabox', 10, 1 ); * function my_restrict_content_hide_metabox( $show ) { * // your code here * return $show; * } * ?> */ $hide_metabox = apply_filters( 'um_restrict_content_hide_metabox', false ); if ( ! $hide_metabox ) { add_action( 'add_meta_boxes', array(&$this, 'add_metabox_restrict_content'), 1 ); add_action( 'save_post', array( &$this, 'save_metabox_restrict_content' ), 10, 2 ); } if ( $current_screen->id == 'attachment' ) { add_action( 'add_attachment', array( &$this, 'save_attachment_metabox_restrict_content' ), 10, 2 ); add_action( 'edit_attachment', array( &$this, 'save_attachment_metabox_restrict_content' ), 10, 2 ); } } add_action( 'save_post', array( &$this, 'save_metabox_custom' ), 10, 2 ); } /** * @param $post_id * @param $post */ public function save_metabox_custom( $post_id, $post ) { // validate nonce if ( ! isset( $_POST['um_admin_save_metabox_custom_nonce'] ) || ! wp_verify_nonce( $_POST['um_admin_save_metabox_custom_nonce'], basename( __FILE__ ) ) ) { return; } /** * UM hook * * @type action * @title um_admin_custom_restrict_content_metaboxes * @description Save metabox custom with restrict content * @input_vars * [{"var":"$post_id","type":"int","desc":"Post ID"}, * {"var":"$post","type":"array","desc":"Post data"}] * @change_log * ["Since: 2.0"] * @usage add_action( 'um_admin_custom_restrict_content_metaboxes', 'function_name', 10, 2 ); * @example * <?php * add_action( 'um_admin_custom_restrict_content_metaboxes', 'my_admin_custom_restrict_content', 10, 2 ); * function my_admin_custom_restrict_content( $post_id, $post ) { * // your code here * } * ?> */ do_action( 'um_admin_custom_restrict_content_metaboxes', $post_id, $post ); } /** * */ function add_metabox_restrict_content() { global $current_screen; add_meta_box( 'um-admin-restrict-content', __( 'Ultimate Member: Content Restriction', 'ultimate-member' ), array( &$this, 'restrict_content_cb' ), $current_screen->id, 'normal', 'default' ); /** * UM hook * * @type action * @title um_admin_custom_restrict_content_metaboxes * @description Add restrict content custom metabox * @change_log * ["Since: 2.0"] * @usage add_action( 'um_admin_custom_restrict_content_metaboxes', 'function_name', 10 ); * @example * <?php * add_action( 'um_admin_custom_restrict_content_metaboxes', 'my_admin_custom_restrict_content', 10 ); * function my_admin_custom_restrict_content() { * // your code here * } * ?> */ do_action( 'um_admin_custom_restrict_content_metaboxes' ); } /** * Content restriction metabox * * @param $object * @param $box */ function restrict_content_cb( $object, $box ) { include_once UM()->admin()->templates_path . 'access/restrict_content.php'; wp_nonce_field( basename( __FILE__ ), 'um_admin_save_metabox_restrict_content_nonce' ); } /** * Init the metaboxes */ function add_taxonomy_metabox() { //restrict content metabox $all_taxonomies = get_taxonomies( array( 'public' => true ) ); $tax_types = UM()->options()->get( 'restricted_access_taxonomy_metabox' ); $exclude_taxonomies = UM()->excluded_taxonomies(); foreach ( $all_taxonomies as $key => $taxonomy ) { if ( in_array( $key, $exclude_taxonomies ) || empty( $tax_types[$key] ) ) continue; add_action( $taxonomy . '_add_form_fields', array( &$this, 'um_category_access_fields_create' ) ); add_action( $taxonomy . '_edit_form_fields', array( &$this, 'um_category_access_fields_edit' ) ); add_action( 'create_' . $taxonomy, array( &$this, 'um_category_access_fields_save' ) ); add_action( 'edited_' . $taxonomy, array( &$this, 'um_category_access_fields_save' ) ); } } /** * @param $post_id * @param $post */ function save_metabox_restrict_content( $post_id, $post ) { // validate nonce if ( ! isset( $_POST['um_admin_save_metabox_restrict_content_nonce'] ) || ! wp_verify_nonce( $_POST['um_admin_save_metabox_restrict_content_nonce'], basename( __FILE__ ) ) ) { return; } // validate user $post_type = get_post_type_object( $post->post_type ); if ( ! current_user_can( $post_type->cap->edit_post, $post_id ) ) { return; } if ( ! empty( $_POST['um_content_restriction'] ) && is_array( $_POST['um_content_restriction'] ) ) { $restriction_meta = UM()->admin()->sanitize_post_restriction_meta( $_POST['um_content_restriction'] ); update_post_meta( $post_id, 'um_content_restriction', $restriction_meta ); } else { delete_post_meta( $post_id, 'um_content_restriction' ); } } /** * @param $post_id * */ function save_attachment_metabox_restrict_content( $post_id ) { // validate nonce if ( ! isset( $_POST['um_admin_save_metabox_restrict_content_nonce'] ) || ! wp_verify_nonce( $_POST['um_admin_save_metabox_restrict_content_nonce'], basename( __FILE__ ) ) ) { return; } $post = get_post( $post_id ); // validate user $post_type = get_post_type_object( $post->post_type ); if ( ! current_user_can( $post_type->cap->edit_post, $post_id ) ) { return; } if ( ! empty( $_POST['um_content_restriction'] ) && is_array( $_POST['um_content_restriction'] ) ) { $restriction_meta = UM()->admin()->sanitize_post_restriction_meta( $_POST['um_content_restriction'] ); update_post_meta( $post_id, 'um_content_restriction', $restriction_meta ); } else { delete_post_meta( $post_id, 'um_content_restriction' ); } } /** * */ function um_category_access_fields_create() { /** * UM hook * * @type filter * @title um_admin_category_access_settings_fields * @description Settings fields for terms * @input_vars * [{"var":"$access_settings_fields","type":"array","desc":"Settings Fields"}, * {"var":"$data","type":"array","desc":"Settings Data"}, * {"var":"$screen","type":"string","desc":"Category Screen"}] * @change_log * ["Since: 2.0"] * @usage add_filter( 'um_admin_category_access_settings_fields', 'function_name', 10, 3 ); * @example * <?php * add_filter( 'um_admin_category_access_settings_fields', 'my_admin_category_access_settings_fields', 10, 3 ); * function my_admin_category_access_settings_fields( $access_settings_fields, $data, $screen ) { * // your code here * $access_settings_fields[] = array( * 'id' => 'my-field-key', * 'type' => 'my-field-type', * 'label' => __( 'My field Label', 'ultimate-member' ), * 'description' => __( 'My Field Description', 'ultimate-member' ), * 'value' => ! empty( $data['_um_custom_access_settings'] ) ? $data['_um_custom_access_settings'] : 0, * ); * return $access_settings_fields; * } * ?> */ $fields = apply_filters( 'um_admin_category_access_settings_fields', array( array( 'id' => '_um_custom_access_settings', 'type' => 'checkbox', 'label' => __( 'Restrict access to this term and its posts?', 'ultimate-member' ), 'description' => __( 'Activate content restriction for this term and its posts. Affects only posts that do not have individual Restriction Content settings', 'ultimate-member' ), 'value' => 0, ), array( 'id' => '_um_accessible', 'type' => 'select', 'label' => __( 'Who can access this term and its posts?', 'ultimate-member' ), 'value' => '0', 'options' => array( '0' => __( 'Everyone', 'ultimate-member' ), '1' => __( 'Logged out users', 'ultimate-member' ), '2' => __( 'Logged in users', 'ultimate-member' ), ), 'conditional' => array( '_um_custom_access_settings', '=', '1' ), ), array( 'id' => '_um_access_roles', 'type' => 'multi_checkbox', 'label' => __( 'Select which roles can access this term and its posts', 'ultimate-member' ), 'description' => __( 'Leave empty if you want to display a term for all logged in users', 'ultimate-member' ), 'options' => UM()->roles()->get_roles( false ), 'columns' => 3, 'conditional' => array( '_um_accessible', '=', '2' ), ), array( 'id' => '_um_access_hide_from_queries', 'type' => 'checkbox', 'label' => UM()->options()->get( 'disable_restriction_pre_queries' ) ? __( 'Hide from queries', 'ultimate-member' ) : __( 'Would you like to display a 404 page for users who do not have access to this term on the term\'s archive page and terms\' posts single pages?', 'ultimate-member' ), 'description' => UM()->options()->get( 'disable_restriction_pre_queries' ) ? __( 'Exclude only from WP queries results', 'ultimate-member' ) : __( 'Recommended to be enabled. Restricted term\'s archive page and all terms\' posts will be hidden by exclusion from WP Query. The safest and most effective method that hides post and its comments from all requests, RSS feeds, etc. on your site', 'ultimate-member' ), 'value' => 1, 'conditional' => array( '_um_accessible', '!=', '0' ), ), array( 'id' => '_um_noaccess_action', 'type' => 'select', 'label' => __( 'What happens when users without access try to view the term\'s post?', 'ultimate-member' ), 'description' => __( 'Action when users without access tries to view the term\'s post', 'ultimate-member' ), 'value' => '0', 'options' => array( '0' => __( 'Show access restricted message', 'ultimate-member' ), '1' => __( 'Redirect user', 'ultimate-member' ), ), 'conditional' => UM()->options()->get( 'disable_restriction_pre_queries' ) ? array( '_um_accessible', '!=', '0' ) : array( '_um_access_hide_from_queries', '=', '0' ), ), array( 'id' => '_um_restrict_by_custom_message', 'type' => 'select', 'label' => __( 'Restricted access message type', 'ultimate-member' ), 'description' => __( 'Would you like to use the global default message or apply a custom message to this term\'s post?', 'ultimate-member' ), 'value' => '0', 'options' => array( '0' => __( 'Global default message', 'ultimate-member' ), '1' => __( 'Custom message', 'ultimate-member' ), ), 'conditional' => array( '_um_noaccess_action', '=', '0' ), ), array( 'id' => '_um_restrict_custom_message', 'type' => 'wp_editor', 'label' => __( 'Custom restricted access message', 'ultimate-member' ), 'description' => __( 'You may replace global restricted access message here', 'ultimate-member' ), 'value' => '', 'conditional' => array( '_um_restrict_by_custom_message', '=', '1' ), ), array( 'id' => '_um_access_redirect', 'type' => 'select', 'label' => __( 'Where should users be redirected to?', 'ultimate-member' ), 'description' => __( 'Select redirect to page when user hasn\'t access to the term\'s post', 'ultimate-member' ), 'value' => '0', 'conditional' => array( '_um_noaccess_action', '=', '1' ), 'options' => array( '0' => __( 'Login page', 'ultimate-member' ), '1' => __( 'Custom URL', 'ultimate-member' ), ), ), array( 'id' => '_um_access_redirect_url', 'type' => 'text', 'label' => __( 'Redirect URL', 'ultimate-member' ), 'description' => __( 'Set full URL where do you want to redirect the user', 'ultimate-member' ), 'value' => '', 'conditional' => array( '_um_access_redirect', '=', '1' ), ), ), array(), 'create' ); UM()->admin_forms( array( 'class' => 'um-restrict-content um-third-column', 'prefix_id' => 'um_content_restriction', 'without_wrapper' => true, 'div_line' => true, 'fields' => $fields, ) )->render_form(); wp_nonce_field( basename( __FILE__ ), 'um_admin_save_taxonomy_restrict_content_nonce' ); } /** * @param $term */ function um_category_access_fields_edit( $term ) { $termID = $term->term_id; $data = get_term_meta( $termID, 'um_content_restriction', true ); $_um_access_roles_value = array(); if ( ! empty( $data['_um_access_roles'] ) ) { foreach ( $data['_um_access_roles'] as $key => $value ) { if ( $value ) { $_um_access_roles_value[] = $key; } } } /** * UM hook * * @type filter * @title um_admin_category_access_settings_fields * @description Settings fields for terms * @input_vars * [{"var":"$access_settings_fields","type":"array","desc":"Settings Fields"}, * {"var":"$data","type":"array","desc":"Settings Data"}, * {"var":"$screen","type":"string","desc":"Category Screen"}] * @change_log * ["Since: 2.0"] * @usage add_filter( 'um_admin_category_access_settings_fields', 'function_name', 10, 3 ); * @example * <?php * add_filter( 'um_admin_category_access_settings_fields', 'my_admin_category_access_settings_fields', 10, 3 ); * function my_admin_category_access_settings_fields( $access_settings_fields, $data, $screen ) { * // your code here * $access_settings_fields[] = array( * 'id' => 'my-field-key', * 'type' => 'my-field-type', * 'label' => __( 'My field Label', 'ultimate-member' ), * 'description' => __( 'My Field Description', 'ultimate-member' ), * 'value' => ! empty( $data['_um_custom_access_settings'] ) ? $data['_um_custom_access_settings'] : 0, * ); * return $access_settings_fields; * } * ?> */ $fields = apply_filters( 'um_admin_category_access_settings_fields', array( array( 'id' => '_um_custom_access_settings', 'type' => 'checkbox', 'label' => __( 'Restrict access to this term and its posts?', 'ultimate-member' ), 'description' => __( 'Activate content restriction for this term and its posts. Affects only posts that do not have individual Restriction Content settings', 'ultimate-member' ), 'value' => ! empty( $data['_um_custom_access_settings'] ) ? $data['_um_custom_access_settings'] : 0, ), array( 'id' => '_um_accessible', 'type' => 'select', 'label' => __( 'Who can access this term and its posts?', 'ultimate-member' ), 'value' => ! empty( $data['_um_accessible'] ) ? $data['_um_accessible'] : '0', 'options' => array( '0' => __( 'Everyone', 'ultimate-member' ), '1' => __( 'Logged out users', 'ultimate-member' ), '2' => __( 'Logged in users', 'ultimate-member' ), ), 'conditional' => array( '_um_custom_access_settings', '=', '1' ), ), array( 'id' => '_um_access_roles', 'type' => 'multi_checkbox', 'label' => __( 'Select which roles can access this term and its posts', 'ultimate-member' ), 'description' => __( 'Leave empty if you want to display a term for all logged in users', 'ultimate-member' ), 'value' => $_um_access_roles_value, 'options' => UM()->roles()->get_roles( false ), 'columns' => 3, 'conditional' => array( '_um_accessible', '=', '2' ), ), array( 'id' => '_um_access_hide_from_queries', 'type' => 'checkbox', 'label' => UM()->options()->get( 'disable_restriction_pre_queries' ) ? __( 'Hide from queries', 'ultimate-member' ) : __( 'Would you like to display a 404 page for users who do not have access to this term on the term\'s archive page and terms\' posts single pages?', 'ultimate-member' ), 'description' => UM()->options()->get( 'disable_restriction_pre_queries' ) ? __( 'Exclude only from WP queries results', 'ultimate-member' ) : __( 'Recommended to be enabled. Restricted term\'s archive page and all terms\' posts will be hidden by exclusion from WP Query. The safest and most effective method that hides post and its comments from all requests, RSS feeds, etc. on your site', 'ultimate-member' ), 'value' => ! empty( $data['_um_access_hide_from_queries'] ) ? $data['_um_access_hide_from_queries'] : '', 'conditional' => array( '_um_accessible', '!=', '0' ), ), array( 'id' => '_um_noaccess_action', 'type' => 'select', 'label' => __( 'What happens when users without access try to view the term\'s post?', 'ultimate-member' ), 'description' => __( 'Action when users without access tries to view the term\'s post', 'ultimate-member' ), 'value' => ! empty( $data['_um_noaccess_action'] ) ? $data['_um_noaccess_action'] : '0', 'options' => array( '0' => __( 'Show access restricted message', 'ultimate-member' ), '1' => __( 'Redirect user', 'ultimate-member' ), ), 'conditional' => UM()->options()->get( 'disable_restriction_pre_queries' ) ? array( '_um_accessible', '!=', '0' ) : array( '_um_access_hide_from_queries', '=', '0' ), ), array( 'id' => '_um_restrict_by_custom_message', 'type' => 'select', 'label' => __( 'Restricted access message type', 'ultimate-member' ), 'description' => __( 'Would you like to use the global default message or apply a custom message to this term\'s post?', 'ultimate-member' ), 'value' => ! empty( $data['_um_restrict_by_custom_message'] ) ? $data['_um_restrict_by_custom_message'] : '0', 'options' => array( '0' => __( 'Global default message', 'ultimate-member' ), '1' => __( 'Custom message', 'ultimate-member' ), ), 'conditional' => array( '_um_noaccess_action', '=', '0' ), ), array( 'id' => '_um_restrict_custom_message', 'type' => 'wp_editor', 'label' => __( 'Custom restricted access message', 'ultimate-member' ), 'description' => __( 'You may replace global restricted access message here', 'ultimate-member' ), 'value' => ! empty( $data['_um_restrict_custom_message'] ) ? $data['_um_restrict_custom_message'] : '', 'conditional' => array( '_um_restrict_by_custom_message', '=', '1' ), ), array( 'id' => '_um_access_redirect', 'type' => 'select', 'label' => __( 'Where should users be redirected to?', 'ultimate-member' ), 'description' => __( 'Select redirect to page when user hasn\'t access to the term\'s post', 'ultimate-member' ), 'value' => ! empty( $data['_um_access_redirect'] ) ? $data['_um_access_redirect'] : '0', 'options' => array( '0' => __( 'Login page', 'ultimate-member' ), '1' => __( 'Custom URL', 'ultimate-member' ), ), 'conditional' => array( '_um_noaccess_action', '=', '1' ), ), array( 'id' => '_um_access_redirect_url', 'type' => 'text', 'label' => __( 'Redirect URL', 'ultimate-member' ), 'description' => __( 'Set full URL where do you want to redirect the user', 'ultimate-member' ), 'value' => ! empty( $data['_um_access_redirect_url'] ) ? $data['_um_access_redirect_url'] : '', 'conditional' => array( '_um_access_redirect', '=', '1' ), ), ), $data, 'edit' ); UM()->admin_forms( array( 'class' => 'um-restrict-content um-third-column', 'prefix_id' => 'um_content_restriction', 'without_wrapper' => true, 'fields' => $fields, ) )->render_form(); wp_nonce_field( basename( __FILE__ ), 'um_admin_save_taxonomy_restrict_content_nonce' ); } /** * @param $termID * * @return mixed */ function um_category_access_fields_save( $termID ) { // validate nonce if ( ! isset( $_REQUEST['um_admin_save_taxonomy_restrict_content_nonce'] ) || ! wp_verify_nonce( $_REQUEST['um_admin_save_taxonomy_restrict_content_nonce'], basename( __FILE__ ) ) ) { return $termID; } // validate user $term = get_term( $termID ); $taxonomy = get_taxonomy( $term->taxonomy ); if ( ! current_user_can( $taxonomy->cap->edit_terms, $termID ) ) { return $termID; } if ( ! empty( $_REQUEST['um_content_restriction'] ) && is_array( $_REQUEST['um_content_restriction'] ) ) { $restriction_meta = UM()->admin()->sanitize_term_restriction_meta( $_REQUEST['um_content_restriction'] ); update_term_meta( $termID, 'um_content_restriction', $restriction_meta ); } else { delete_term_meta( $termID, 'um_content_restriction' ); } return $termID; } /** * Load a directory metabox * * @param $object * @param $box */ public function load_metabox_directory( $object, $box ) { $box['id'] = str_replace( 'um-admin-form-', '', $box['id'] ); preg_match('#\{.*?\}#s', $box['id'], $matches ); if ( isset( $matches[0] ) ) { $path = $matches[0]; $box['id'] = preg_replace('~(\\{[^}]+\\})~','', $box['id'] ); } else { $path = UM_PATH; } $path = str_replace('{','', $path ); $path = str_replace('}','', $path ); include_once $path . 'includes/admin/templates/directory/'. $box['id'] . '.php'; if ( ! $this->directory_nonce_added ) { $this->directory_nonce_added = true; wp_nonce_field( basename( __FILE__ ), 'um_admin_save_metabox_directory_nonce' ); } } /** * Load a role metabox * * @param $object * @param $box */ function load_metabox_role( $object, $box ) { global $post; $box['id'] = str_replace( 'um-admin-form-', '', $box['id'] ); if ( $box['id'] == 'builder' ) { UM()->builder()->form_id = get_the_ID(); } preg_match('#\{.*?\}#s', $box['id'], $matches); if ( isset($matches[0]) ){ $path = $matches[0]; $box['id'] = preg_replace('~(\\{[^}]+\\})~','', $box['id'] ); } else { $path = UM_PATH; } $path = str_replace('{','', $path ); $path = str_replace('}','', $path ); include_once $path . 'includes/admin/templates/role/'. $box['id'] . '.php'; //wp_nonce_field( basename( __FILE__ ), 'um_admin_save_metabox_role_nonce' ); } /** * Load a form metabox * * @param $object * @param $box */ function load_metabox_form( $object, $box ) { global $post; $box['id'] = str_replace( 'um-admin-form-','', $box['id'] ); if ( $box['id'] == 'builder' ) { UM()->builder()->form_id = get_the_ID(); } preg_match('#\{.*?\}#s', $box['id'], $matches); if ( isset( $matches[0] ) ) { $path = $matches[0]; $box['id'] = preg_replace('~(\\{[^}]+\\})~','', $box['id'] ); } else { $path = UM_PATH; } $path = str_replace('{','', $path ); $path = str_replace('}','', $path ); include_once $path . 'includes/admin/templates/form/'. $box['id'] . '.php'; if ( ! $this->form_nonce_added ) { $this->form_nonce_added = true; wp_nonce_field( basename( __FILE__ ), 'um_admin_save_metabox_form_nonce' ); } } /** * Load admin custom metabox * * @param $object * @param $box */ function load_metabox_custom( $object, $box ) { global $post; $box['id'] = str_replace('um-admin-custom-','', $box['id']); preg_match('#\{.*?\}#s', $box['id'], $matches); if ( isset($matches[0]) ){ $path = $matches[0]; $box['id'] = preg_replace('~(\\{[^}]+\\})~','', $box['id'] ); } else { $path = UM_PATH; } $path = str_replace('{','', $path ); $path = str_replace('}','', $path ); include_once $path . 'includes/admin/templates/'. $box['id'] . '.php'; if ( ! $this->custom_nonce_added ) { $this->custom_nonce_added = true; wp_nonce_field( basename( __FILE__ ), 'um_admin_save_metabox_custom_nonce' ); } } /** * Add directory metabox */ public function add_metabox_directory() { add_meta_box( 'submitdiv', __( 'Publish', 'ultimate-member' ), array( &$this, 'custom_submitdiv' ), 'um_directory', 'side', 'high' ); add_meta_box( 'um-admin-form-general', __( 'General Options', 'ultimate-member' ), array( &$this, 'load_metabox_directory' ), 'um_directory', 'normal', 'default' ); add_meta_box( 'um-admin-form-privacy', __( 'Privacy Options', 'ultimate-member' ), array( &$this, 'load_metabox_directory' ), 'um_directory', 'normal', 'default' ); add_meta_box( 'um-admin-form-sorting', __( 'Sorting', 'ultimate-member' ), array( &$this, 'load_metabox_directory' ), 'um_directory', 'normal', 'default' ); add_meta_box( 'um-admin-form-profile', __( 'Profile Card', 'ultimate-member' ), array( &$this, 'load_metabox_directory' ), 'um_directory', 'normal', 'default' ); add_meta_box( 'um-admin-form-search', __( 'Search Options', 'ultimate-member' ), array( &$this, 'load_metabox_directory' ), 'um_directory', 'normal', 'default' ); add_meta_box( 'um-admin-form-pagination', __( 'Results & Pagination', 'ultimate-member' ), array( &$this, 'load_metabox_directory' ), 'um_directory', 'normal', 'default' ); add_meta_box( 'um-admin-form-shortcode', __( 'Shortcode', 'ultimate-member' ), array( &$this, 'load_metabox_directory' ), 'um_directory', 'side', 'default' ); add_meta_box( 'um-admin-form-appearance', __( 'Styling: General', 'ultimate-member' ), array( &$this, 'load_metabox_directory' ), 'um_directory', 'side', 'default' ); } /** * Add role metabox */ function add_metabox_role() { $callback = array( &$this, 'load_metabox_role' ); $roles_metaboxes = array( array( 'id' => 'um-admin-form-admin-permissions', 'title' => __( 'Administrative Permissions', 'ultimate-member' ), 'callback' => $callback, 'screen' => 'um_role_meta', 'context' => 'normal', 'priority' => 'default' ), array( 'id' => 'um-admin-form-general', 'title' => __( 'General Permissions', 'ultimate-member' ), 'callback' => $callback, 'screen' => 'um_role_meta', 'context' => 'normal', 'priority' => 'default' ), array( 'id' => 'um-admin-form-profile', 'title' => __( 'Profile Access', 'ultimate-member' ), 'callback' => $callback, 'screen' => 'um_role_meta', 'context' => 'normal', 'priority' => 'default' ) ); if ( ! isset( $_GET['id'] ) || 'administrator' !== sanitize_key( $_GET['id'] ) ) { $roles_metaboxes[] = array( 'id' => 'um-admin-form-home', 'title' => __( 'Homepage Options', 'ultimate-member' ), 'callback' => $callback, 'screen' => 'um_role_meta', 'context' => 'normal', 'priority' => 'default' ); } $roles_metaboxes = array_merge( $roles_metaboxes, array( array( 'id' => 'um-admin-form-register', 'title' => __( 'Registration Options', 'ultimate-member' ), 'callback' => $callback, 'screen' => 'um_role_meta', 'context' => 'normal', 'priority' => 'default' ), array( 'id' => 'um-admin-form-login', 'title' => __( 'Login Options', 'ultimate-member' ), 'callback' => $callback, 'screen' => 'um_role_meta', 'context' => 'normal', 'priority' => 'default' ), array( 'id' => 'um-admin-form-logout', 'title' => __( 'Logout Options', 'ultimate-member' ), 'callback' => $callback, 'screen' => 'um_role_meta', 'context' => 'normal', 'priority' => 'default' ), array( 'id' => 'um-admin-form-delete', 'title' => __( 'Delete Options', 'ultimate-member' ), 'callback' => $callback, 'screen' => 'um_role_meta', 'context' => 'normal', 'priority' => 'default' ), array( 'id' => 'um-admin-form-publish', 'title' => __( 'Publish', 'ultimate-member' ), 'callback' => $callback, 'screen' => 'um_role_meta', 'context' => 'side', 'priority' => 'default' ) ) ); /** * UM hook * * @type filter * @title um_admin_role_metaboxes * @description Extend metaboxes at Add/Edit User Role * @input_vars * [{"var":"$roles_metaboxes","type":"array","desc":"Metaboxes at Add/Edit UM Role"}] * @change_log * ["Since: 2.0"] * @usage add_filter( 'um_admin_role_metaboxes', 'function_name', 10, 1 ); * @example * <?php * add_filter( 'um_admin_role_metaboxes', 'my_admin_role_metaboxes', 10, 1 ); * function my_admin_role_metaboxes( $roles_metaboxes ) { * // your code here * $roles_metaboxes[] = array( * 'id' => 'um-admin-form-your-custom', * 'title' => __( 'My Roles Metabox', 'ultimate-member' ), * 'callback' => 'my-metabox-callback', * 'screen' => 'um_role_meta', * 'context' => 'side', * 'priority' => 'default' * ); * * return $roles_metaboxes; * } * ?> */ $roles_metaboxes = apply_filters( 'um_admin_role_metaboxes', $roles_metaboxes ); $wp_caps_metabox = false; if ( ! empty( $_GET['id'] ) ) { $data = get_option( 'um_role_' . sanitize_key( $_GET['id'] ) . '_meta' ); if ( ! empty( $data['_um_is_custom'] ) ) { $wp_caps_metabox = true; } } if ( 'add' == sanitize_key( $_GET['tab'] ) || $wp_caps_metabox ) { $roles_metaboxes[] = array( 'id' => 'um-admin-form-wp-capabilities', 'title' => __( 'WP Capabilities', 'ultimate-member' ), 'callback' => $callback, 'screen' => 'um_role_meta', 'context' => 'normal', 'priority' => 'default' ); } foreach ( $roles_metaboxes as $metabox ) { add_meta_box( $metabox['id'], $metabox['title'], $metabox['callback'], $metabox['screen'], $metabox['context'], $metabox['priority'] ); } } /** * Add form metabox */ public function add_metabox_form() { add_meta_box( 'submitdiv', __( 'Publish', 'ultimate-member' ), array( $this, 'custom_submitdiv' ), 'um_form', 'side', 'high' ); if ( defined( 'UM_DEV_MODE' ) && UM_DEV_MODE && UM()->options()->get( 'enable_new_form_builder' ) ) { // Do new metabox. } else { add_meta_box( 'um-admin-form-mode', __( 'Select Form Type', 'ultimate-member' ), array( &$this, 'load_metabox_form' ), 'um_form', 'normal', 'default' ); add_meta_box( 'um-admin-form-builder', __( 'Form Builder', 'ultimate-member' ), array( &$this, 'load_metabox_form' ), 'um_form', 'normal', 'default' ); } add_meta_box( 'um-admin-form-shortcode', __( 'Shortcode', 'ultimate-member' ), array( &$this, 'load_metabox_form' ), 'um_form', 'side', 'default' ); add_meta_box( 'um-admin-form-register_customize', __( 'Customize this form', 'ultimate-member' ), array( &$this, 'load_metabox_form' ), 'um_form', 'side', 'default' ); /** * UM hook * * @type action * @title um_admin_custom_register_metaboxes * @description Add custom metaboxes for register form * @change_log * ["Since: 2.0"] * @usage add_action( 'um_admin_custom_register_metaboxes', 'function_name', 10 ); * @example * <?php * add_action( 'um_admin_custom_register_metaboxes', 'my_admin_custom_register_metaboxes', 10 ); * function my_admin_custom_register_metaboxes() { * // your code here * } * ?> */ do_action( 'um_admin_custom_register_metaboxes' ); add_meta_box( 'um-admin-form-profile_customize', __( 'Customize this form', 'ultimate-member' ), array( &$this, 'load_metabox_form' ), 'um_form', 'side', 'default' ); add_meta_box( 'um-admin-form-profile_settings', __( 'User Meta', 'ultimate-member' ), array( &$this, 'load_metabox_form' ), 'um_form', 'side', 'default' ); /** * UM hook * * @type action * @title um_admin_custom_profile_metaboxes * @description Add custom metaboxes for profile form * @change_log * ["Since: 2.0"] * @usage add_action( 'um_admin_custom_profile_metaboxes', 'function_name', 10 ); * @example * <?php * add_action( 'um_admin_custom_profile_metaboxes', 'my_admin_custom_profile_metaboxes', 10 ); * function my_admin_custom_profile_metaboxes() { * // your code here * } * ?> */ do_action( 'um_admin_custom_profile_metaboxes' ); add_meta_box( 'um-admin-form-login_customize', __( 'Customize this form', 'ultimate-member' ), array( &$this, 'load_metabox_form' ), 'um_form', 'side', 'default' ); add_meta_box( 'um-admin-form-login_settings', __( 'Options', 'ultimate-member' ), array( &$this, 'load_metabox_form' ), 'um_form', 'side', 'default' ); /** * UM hook * * @type action * @title um_admin_custom_login_metaboxes * @description Add custom metaboxes for login form * @change_log * ["Since: 2.0"] * @usage add_action( 'um_admin_custom_login_metaboxes', 'function_name', 10 ); * @example * <?php * add_action( 'um_admin_custom_login_metaboxes', 'my_admin_custom_login_metaboxes', 10 ); * function my_admin_custom_login_metaboxes() { * // your code here * } * ?> */ do_action( 'um_admin_custom_login_metaboxes' ); } /** * */ public function custom_submitdiv() { global $post, $current_screen; ?> <div class="submitbox" id="submitpost"> <div id="major-publishing-actions"> <?php do_action( 'post_submitbox_start' ); ?> <div id="delete-action"> <?php if ( current_user_can( 'delete_post', $post->ID ) ) { if ( ! EMPTY_TRASH_DAYS ) { $delete_text = __( 'Delete Permanently', 'ultimate-member' ); } else { $delete_text = __( 'Move to Trash', 'ultimate-member' ); } ?> <a class="submitdelete deletion" href="<?php echo esc_url( get_delete_post_link( $post->ID ) ); ?>"> <?php echo esc_html( $delete_text ); ?> </a> <?php } ?> </div> <div id="publishing-action"> <span class="spinner"></span> <?php if ( ! in_array( $post->post_status, array( 'publish', 'future', 'private' ) ) || 0 == $post->ID ) { $post_type = $post->post_type; // get current post_type $post_type_object = get_post_type_object( $post_type ); $can_publish = current_user_can( $post_type_object->cap->publish_posts ); if ( $can_publish ) { ?> <input name="original_publish" type="hidden" id="original_publish" value="<?php esc_attr_e( 'Create', 'ultimate-member' ) ?>" /> <?php submit_button( __( 'Create', 'ultimate-member' ), 'primary button-large', 'publish', false, array( 'accesskey' => 'p' ) ); ?> <?php } } else { ?> <input name="original_publish" type="hidden" id="original_publish" value="<?php esc_attr_e('Update', 'ultimate-member' ); ?>" /> <?php submit_button( __( 'Update', 'ultimate-member' ), 'primary button-large', 'save', false, array( 'accesskey' => 'p' ) ); ?> <?php } ?> </div> <?php if ( isset( $current_screen->base ) && 'post' === $current_screen->base && isset( $current_screen->action ) && 'add' === $current_screen->action ) { if ( isset( $_GET['um_mode'] ) ) { $mode = sanitize_key( $_GET['um_mode'] ); ?> <input type="hidden" name="form[_um_mode]" id="form__um_mode" value="<?php echo esc_attr( $mode ); ?>" /> <?php } }?> <div class="clear"></div> </div> </div> <?php } /** * Save directory metabox * * @param $post_id * @param $post */ public function save_metabox_directory( $post_id, $post ) { global $wpdb; // validate nonce if ( ! isset( $_POST['um_admin_save_metabox_directory_nonce'] ) || ! wp_verify_nonce( $_POST['um_admin_save_metabox_directory_nonce'], basename( __FILE__ ) ) ) { return; } // validate post type if ( 'um_directory' !== $post->post_type ) { return; } // validate user $post_type = get_post_type_object( $post->post_type ); if ( ! current_user_can( $post_type->cap->edit_post, $post_id ) ) { return; } if ( empty( $_POST['post_title'] ) ) { $where = array( 'ID' => $post_id ); // translators: %s: Directory id. $_POST['post_title'] = sprintf( __( 'Directory #%s', 'ultimate-member' ), $post_id ); $wpdb->update( $wpdb->posts, array( 'post_title' => sanitize_text_field( wp_unslash( $_POST['post_title'] ) ), ), $where, array( '%s', ), array( '%d', ) ); } do_action( 'um_before_member_directory_save', $post_id ); // save delete_post_meta( $post_id, '_um_roles' ); delete_post_meta( $post_id, '_um_tagline_fields' ); delete_post_meta( $post_id, '_um_reveal_fields' ); delete_post_meta( $post_id, '_um_search_fields' ); delete_post_meta( $post_id, '_um_search_exclude_fields' ); delete_post_meta( $post_id, '_um_search_include_fields' ); delete_post_meta( $post_id, '_um_roles_can_search' ); delete_post_meta( $post_id, '_um_roles_can_filter' ); delete_post_meta( $post_id, '_um_show_these_users' ); delete_post_meta( $post_id, '_um_exclude_these_users' ); delete_post_meta( $post_id, '_um_search_filters' ); delete_post_meta( $post_id, '_um_search_filters_gmt' ); delete_post_meta( $post_id, '_um_sorting_fields' ); //save metadata $metadata = UM()->admin()->sanitize_member_directory_meta( $_POST['um_metadata'] ); foreach ( $metadata as $k => $v ) { if ( '_um_show_these_users' === $k && trim( $v ) ) { $v = preg_split( '/[\r\n]+/', $v, -1, PREG_SPLIT_NO_EMPTY ); } if ( '_um_exclude_these_users' === $k && trim( $v ) ) { $v = preg_split( '/[\r\n]+/', $v, -1, PREG_SPLIT_NO_EMPTY ); } if ( strstr( $k, '_um_' ) ) { if ( '_um_is_default' === $k ) { $mode = UM()->query()->get_attr( 'mode', $post_id ); if ( ! empty( $mode ) ) { $posts = $wpdb->get_col( "SELECT post_id FROM {$wpdb->postmeta} WHERE meta_key = '_um_mode' AND meta_value = 'directory'" ); foreach ( $posts as $p_id ) { delete_post_meta( $p_id, '_um_is_default' ); } } } $v = apply_filters( 'um_member_directory_meta_value_before_save', $v, $k, $post_id ); update_post_meta( $post_id, $k, $v ); } } update_post_meta( $post_id, '_um_search_filters_gmt', (int) $_POST['um-gmt-offset'] ); } /** * Save form metabox. * * @param int $post_id * @param WP_Post $post */ public function save_metabox_form( $post_id, $post ) { global $wpdb; // validate nonce if ( ! isset( $_POST['um_admin_save_metabox_form_nonce'] ) || ! wp_verify_nonce( $_POST['um_admin_save_metabox_form_nonce'], basename( __FILE__ ) ) ) { return; } // validate post type if ( 'um_form' !== $post->post_type ) { return; } // validate user $post_type = get_post_type_object( $post->post_type ); if ( ! current_user_can( $post_type->cap->edit_post, $post_id ) ) { return; } // Set post meta for legacy support in the future. add_post_meta( $post_id, 'um_form_version', UM_VERSION, true ); if ( empty( $_POST['post_title'] ) ) { $where = array( 'ID' => $post_id ); // translators: %s: Form id. $_POST['post_title'] = sprintf( __( 'Form #%s', 'ultimate-member' ), $post_id ); $wpdb->update( $wpdb->posts, array( 'post_title' => sanitize_text_field( wp_unslash( $_POST['post_title'] ) ), ), $where, array( '%s', ), array( '%d', ) ); } // save delete_post_meta( $post_id, '_um_profile_metafields' ); $form_meta = UM()->admin()->sanitize_form_meta( $_POST['form'] ); foreach ( $form_meta as $k => $v ) { if ( 0 === strpos( $k, '_um_' ) ) { if ( '_um_is_default' === $k ) { $mode = UM()->query()->get_attr( 'mode', $post_id ); if ( ! empty( $mode ) ) { $posts = $wpdb->get_col( $wpdb->prepare( "SELECT post_id FROM {$wpdb->postmeta} WHERE meta_key = '_um_mode' AND meta_value = %s", $mode ) ); foreach ( $posts as $p_id ) { delete_post_meta( $p_id, '_um_is_default' ); } } } update_post_meta( $post_id, $k, $v ); } } } /** * Load modal content */ public function load_modal_content() { $screen = get_current_screen(); if ( isset( $screen->id ) && strstr( $screen->id, 'um_form' ) ) { foreach ( glob( UM_PATH . 'includes/admin/templates/modal/forms/*.php' ) as $modal_content ) { include_once $modal_content; } } // Old interface for icon selector in UM admin forms field-type 'icon'. if ( $this->init_icon ) { include_once UM_PATH . 'includes/admin/templates/modal/forms/fonticons.php'; } if ( 'users' === $screen->id ) { include_once UM_PATH . 'includes/admin/templates/modal/dynamic_registration_preview.php'; } // needed on forms only if ( false === $this->is_loaded && isset( $screen->id ) && strstr( $screen->id, 'um_form' ) ) { $settings['textarea_rows'] = 8; echo '<div class="um-hidden-editor-edit" style="display:none;">'; wp_editor( '', 'um_editor_edit', $settings ); echo '</div>'; echo '<div class="um-hidden-editor-new" style="display:none;">'; wp_editor( '', 'um_editor_new', $settings ); echo '</div>'; $this->is_loaded = true; } } /** * Show field input for edit at modal field * * @param $attribute * @param null $form_id * @param array $field_args */ public function field_input( $attribute, $form_id = null, $field_args = array() ) { if ( $this->in_edit ) { // We're editing a field. $real_attr = substr( $attribute, 1 ); $this->edit_mode_value = isset( $this->edit_array[ $real_attr ] ) ? $this->edit_array[ $real_attr ] : null; } $form_data = UM()->query()->post_data( $form_id ); if ( empty( $form_data['mode'] ) && ! empty( $_POST['form_mode'] ) ) { // Case when we add new form with no form mode in postmeta. Then get form mode from AJAX request. $form_data['mode'] = sanitize_key( $_POST['form_mode'] ); } switch ( $attribute ) { default: /** * UM hook * * @type action * @title um_admin_field_edit_hook{$attribute} * @description Integration for 3-d party fields at wp-admin * @input_vars * [{"var":"$edit_mode_value","type":"string","desc":"Post ID"}] * @change_log * ["Since: 2.0"] * @usage add_action( 'um_admin_field_edit_hook{$attribute}', 'function_name', 10, 1 ); * @example * <?php * add_action( 'um_admin_field_edit_hook{$attribute}', 'my_admin_field_edit', 10, 1 ); * function my_admin_field_edit( $edit_mode_value ) { * // your code here * } * ?> */ do_action( "um_admin_field_edit_hook{$attribute}", $this->edit_mode_value, $form_id, $this->edit_array ); break; case '_visibility': ?> <p> <label for="_visibility"><?php esc_html_e( 'Visibility', 'ultimate-member' ); ?> <?php UM()->tooltip( __( 'Select where this field should appear. This option should only be changed on the profile form and allows you to show a field in one mode only (edit or view) or in both modes.','ultimate-member' ) ); ?></label> <select name="_visibility" id="_visibility" style="width: 100%"> <option value="all" <?php selected( 'all', $this->edit_mode_value ); ?>><?php _e( 'View everywhere', 'ultimate-member' ) ?></option> <option value="edit" <?php selected( 'edit', $this->edit_mode_value ); ?>><?php _e( 'Edit mode only', 'ultimate-member' ) ?></option> <option value="view" <?php selected( 'view', $this->edit_mode_value ); ?>><?php _e( 'View mode only', 'ultimate-member' ) ?></option> </select> </p> <?php break; case '_conditional_action': case '_conditional_action1': case '_conditional_action2': case '_conditional_action3': case '_conditional_action4': ?> <p> <select name="<?php echo esc_attr( $attribute ); ?>" id="<?php echo esc_attr( $attribute ); ?>" style="width: 90px"> <option></option> <?php $actions = array( 'show', 'hide' ); foreach ( $actions as $action ) { ?> <option value="<?php echo esc_attr( $action ); ?>" <?php selected( $action, $this->edit_mode_value ); ?>><?php echo esc_html( $action ); ?></option> <?php } ?> </select> <?php esc_html_e( 'If', 'ultimate-member' ); ?> </p> <?php break; case '_conditional_field': case '_conditional_field1': case '_conditional_field2': case '_conditional_field3': case '_conditional_field4': ?> <p> <select name="<?php echo esc_attr( $attribute ); ?>" id="<?php echo esc_attr( $attribute ); ?>" style="width: 150px"> <option></option> <?php $fields = UM()->query()->get_attr( 'custom_fields', $form_id ); foreach ( $fields as $key => $array ) { if ( isset( $array['title'] ) && ( ! isset( $this->edit_array['metakey'] ) || $key != $this->edit_array['metakey'] ) ) { ?> <option value="<?php echo esc_attr( $key ); ?>" <?php selected( $key, $this->edit_mode_value ); ?>><?php echo esc_html( $array['title'] ); ?></option> <?php } } ?> </select> </p> <?php break; case '_conditional_operator': case '_conditional_operator1': case '_conditional_operator2': case '_conditional_operator3': case '_conditional_operator4': $operators = array( 'empty', 'not empty', 'equals to', 'not equals', 'greater than', 'less than', 'contains', ); ?> <p> <select name="<?php echo esc_attr( $attribute ); ?>" id="<?php echo esc_attr( $attribute ); ?>" style="width: 150px"> <option></option> <?php foreach ( $operators as $operator ) { ?> <option value="<?php echo esc_attr( $operator ); ?>" <?php selected( $operator, $this->edit_mode_value ); ?>><?php echo esc_html( $operator ); ?></option> <?php } ?> </select> </p> <?php break; case '_conditional_value': case '_conditional_value1': case '_conditional_value2': case '_conditional_value3': case '_conditional_value4': ?> <p> <input type="text" name="<?php echo esc_attr( $attribute ); ?>" id="<?php echo esc_attr( $attribute ); ?>" value="<?php echo isset( $this->edit_mode_value ) ? esc_attr( $this->edit_mode_value ) : ''; ?>" placeholder="<?php esc_attr_e( 'Value', 'ultimate-member' ); ?>" style="width: 150px!important;position: relative;top: -1px;" /> </p> <?php break; case '_validate': if ( array_key_exists( 'mode', $form_data ) && 'login' === $form_data['mode'] && array_key_exists( 'metakey', $field_args ) && in_array( $field_args['metakey'], array( 'username', 'user_login', 'user_email' ), true ) ) { return; } ?> <p><label for="_validate"><?php _e( 'Validate', 'ultimate-member' ) ?> <?php UM()->tooltip( __( 'Does this field require a special validation', 'ultimate-member' ) ); ?></label> <select name="_validate" id="_validate" data-placeholder="<?php esc_attr_e( 'Select a validation type...', 'ultimate-member' ) ?>" class="um-adm-conditional" data-cond1="custom" data-cond1-show="_custom_validate" style="width: 100%"> <option value="" <?php selected( '', $this->edit_mode_value ); ?>></option> <?php foreach( UM()->builtin()->validation_types() as $key => $name ) { ?> <?php /** * UM hook * * @type filter * @title um_builtin_validation_types_continue_loop * @description Builtin Validation Types * @input_vars * [{"var":"$continue","type":"bool","desc":"Validate?"}, * {"var":"$key","type":"string","desc":"Field Key"}, * {"var":"$form_id","type":"int","desc":"Form ID"}, * {"var":"$field_args","type":"array","desc":"Field Settings"}] * @change_log * ["Since: 2.0"] * @usage add_filter( 'um_builtin_validation_types_continue_loop', 'function_name', 10, 4 ); * @example * <?php * add_filter( 'um_builtin_validation_types_continue_loop', 'my_builtin_validation_types', 10, 4 ); * function my_builtin_validation_types( $continue, $key, $form_id, $field_args ) { * // your code here * return $continue; * } * ?> */ $continue = apply_filters( "um_builtin_validation_types_continue_loop", true, $key, $form_id, $field_args ); if ( $continue ) { ?> <option value="<?php echo esc_attr( $key ); ?>" <?php selected( $key, $this->edit_mode_value ); ?>><?php echo $name; ?></option> <?php } ?> <?php } ?> </select> </p> <?php break; case '_custom_validate': ?> <p class="_custom_validate"><label for="_custom_validate"><?php _e( 'Custom Action', 'ultimate-member' ) ?> <?php UM()->tooltip( __( 'If you want to apply your custom validation, you can use action hooks to add custom validation. Please refer to documentation for further details.', 'ultimate-member' ) ); ?></label> <input type="text" name="_custom_validate" id="_custom_validate" value="<?php echo ( $this->edit_mode_value ) ? $this->edit_mode_value : ''; ?>" /> </p> <?php break; case '_icon': UM()->setup()->set_icons_options(); $um_icons_list = get_option( 'um_icons_list' ); $first_activation_date = get_option( 'um_first_activation_date', false ); $wrapper_classes = array( 'um-icon-select-field-wrapper', ); if ( 'row' === $this->set_field_type ) { $wrapper_classes[] = '_heading_text'; } $wrapper_classes = implode( ' ', $wrapper_classes ); // @todo new version if ( empty( $first_activation_date ) || $first_activation_date >= 1716336000 || empty( $this->edit_mode_value ) || array_key_exists( $this->edit_mode_value, $um_icons_list ) ) { ?> <p class="<?php echo esc_attr( $wrapper_classes ); ?>"> <label for="_icon"><?php esc_html_e( 'Icon', 'ultimate-member' ); ?> <?php UM()->tooltip( __( 'Select an icon to appear in the field. Leave blank if you do not want an icon to show in the field.', 'ultimate-member' ) ); ?></label> <select name="_icon" id="_icon" class="um-icon-select-field" data-placeholder="<?php esc_attr_e( 'Select Icon', 'ultimate-member' ); ?>" > <option value=""><?php esc_html_e( 'Select Icon', 'ultimate-member' ); ?></option> <?php if ( ! empty( $this->edit_mode_value ) && array_key_exists( $this->edit_mode_value, $um_icons_list ) ) { ?> <option value="<?php echo esc_attr( $this->edit_mode_value ); ?>" selected><?php echo esc_html( $um_icons_list[ $this->edit_mode_value ]['label'] ); ?></option> <?php } ?> </select> </p> <?php } else { ?> <p class="<?php echo esc_attr( $wrapper_classes ); ?>"> <label for="um_ui_icon_new"><?php esc_html_e( 'Icon', 'ultimate-member' ); ?> <?php UM()->tooltip( __( 'Select an icon to appear in the field. Leave blank if you do not want an icon to show in the field.', 'ultimate-member' ) ); ?></label> <select name="um_ui_icon_new" id="um_ui_icon_new" class="um-icon-select-field" data-placeholder="<?php esc_attr_e( 'Select Icon', 'ultimate-member' ); ?>" > <option value=""><?php esc_html_e( 'Select Icon', 'ultimate-member' ); ?></option> </select> <span class="um_admin_fonticon_wrapper"> <span><?php esc_html_e( 'The selected icon is using an outdated version. Please select the icon above to use latest version.', 'ultimate-member' ); ?></span> <input type="hidden" name="_icon" id="_icon" class="um_old_icon_field_value" value="<?php echo esc_attr( $this->edit_mode_value ); ?>" /> <span class="um-admin-icon-value"><i class="<?php echo esc_attr( $this->edit_mode_value ); ?>"></i></span> <span class="um-admin-icon-clear show"><i class="um-icon-android-cancel"></i></span> </span> </p> <?php } break; case '_css_class': ?> <p><label for="_css_class"><?php _e( 'CSS Class', 'ultimate-member' ) ?> <?php UM()->tooltip( __( 'Specify a custom CSS class to be applied to this element', 'ultimate-member' ) ); ?></label> <input type="text" name="_css_class" id="_css_class" value="<?php echo ( $this->edit_mode_value ) ? $this->edit_mode_value : ''; ?>" /> </p> <?php break; case '_width': ?> <p><label for="_width"><?php _e( 'Thickness (in pixels)', 'ultimate-member' ) ?> <?php UM()->tooltip( __( 'This is the width in pixels, e.g. 4 or 2, etc', 'ultimate-member' ) ); ?></label> <input type="text" name="_width" id="_width" value="<?php echo ( $this->edit_mode_value ) ? $this->edit_mode_value : 4; ?>" /> </p> <?php break; case '_divider_text': ?> <p><label for="_divider_text"><?php _e( 'Optional Text', 'ultimate-member' ) ?> <?php UM()->tooltip( __( 'Optional text to include with the divider', 'ultimate-member' ) ); ?></label> <input type="text" name="_divider_text" id="_divider_text" value="<?php echo ( $this->edit_mode_value ) ? $this->edit_mode_value : ''; ?>" /> </p> <?php break; case '_padding': ?> <p><label for="_padding"><?php _e( 'Padding', 'ultimate-member' ) ?> <?php UM()->tooltip( __( 'Set padding for this section', 'ultimate-member' ) ); ?></label> <input type="text" name="_padding" id="_padding" value="<?php echo ( $this->edit_mode_value ) ? $this->edit_mode_value : '0px 0px 0px 0px'; ?>" /> </p> <?php break; case '_margin': ?> <p><label for="_margin"><?php _e( 'Margin', 'ultimate-member' ) ?> <?php UM()->tooltip( __( 'Set margin for this section', 'ultimate-member' ) ); ?></label> <input type="text" name="_margin" id="_margin" value="<?php echo ( $this->edit_mode_value ) ? $this->edit_mode_value : '0px 0px 30px 0px'; ?>" /> </p> <?php break; case '_border': ?> <p><label for="_border"><?php _e( 'Border', 'ultimate-member' ) ?> <?php UM()->tooltip( __( 'Set border for this section', 'ultimate-member' ) ); ?></label> <input type="text" name="_border" id="_border" value="<?php echo ( $this->edit_mode_value ) ? $this->edit_mode_value : '0px 0px 0px 0px'; ?>" /> </p> <?php break; case '_borderstyle': ?> <p><label for="_borderstyle"><?php _e( 'Style', 'ultimate-member' ) ?> <?php UM()->tooltip( __( 'Choose the border style', 'ultimate-member' ) ); ?></label> <select name="_borderstyle" id="_borderstyle" style="width: 100%"> <option value="solid" <?php selected( 'solid', $this->edit_mode_value ); ?>><?php _e( 'Solid', 'ultimate-member' ) ?></option> <option value="dotted" <?php selected( 'dotted', $this->edit_mode_value ); ?>><?php _e( 'Dotted', 'ultimate-member' ) ?></option> <option value="dashed" <?php selected( 'dashed', $this->edit_mode_value ); ?>><?php _e( 'Dashed', 'ultimate-member' ) ?></option> <option value="double" <?php selected( 'double', $this->edit_mode_value ); ?>><?php _e( 'Double', 'ultimate-member' ) ?></option> </select> </p> <?php break; case '_borderradius': ?> <p><label for="_borderradius"><?php _e( 'Border Radius', 'ultimate-member' ) ?> <?php UM()->tooltip( __( 'Rounded corners can be applied by setting a pixels value here. e.g. 5px', 'ultimate-member' ) ); ?></label> <input type="text" name="_borderradius" id="_borderradius" value="<?php echo ( $this->edit_mode_value ) ? $this->edit_mode_value : '0px'; ?>" /> </p> <?php break; case '_bordercolor': ?> <p><label for="_bordercolor"><?php _e( 'Border Color', 'ultimate-member' ) ?> <?php UM()->tooltip( __( 'Give a color to this border', 'ultimate-member' ) ); ?></label> <input type="text" name="_bordercolor" id="_bordercolor" class="um-admin-colorpicker" data-default-color="" value="<?php echo ( $this->edit_mode_value ) ? $this->edit_mode_value : ''; ?>" /> </p> <?php break; case '_heading': ?> <p><label for="_heading"><?php _e( 'Enable Row Heading', 'ultimate-member' ) ?> <?php UM()->tooltip( __( 'Whether to enable a heading for this row', 'ultimate-member' ) ); ?></label> <input type="checkbox" name="_heading" id="_heading" value="1" <?php checked( isset( $this->edit_mode_value ) ? $this->edit_mode_value : 0 ) ?> class="um-adm-conditional" data-cond1="1" data-cond1-show="_heading_text" data-cond1-hide="xxx" /> </p> <?php break; case '_heading_text': ?> <p class="_heading_text"><label for="_heading_text"><?php _e( 'Heading Text', 'ultimate-member' ) ?> <?php UM()->tooltip( __( 'Enter the row heading text here', 'ultimate-member' ) ); ?></label> <input type="text" name="_heading_text" id="_heading_text" value="<?php echo ( $this->edit_mode_value ) ? $this->edit_mode_value : ''; ?>" /> </p> <?php break; case '_background': ?> <p><label for="_background"><?php _e( 'Background Color', 'ultimate-member' ) ?> <?php UM()->tooltip( __( 'This will be the background of entire section', 'ultimate-member' ) ); ?></label> <input type="text" name="_background" id="_background" class="um-admin-colorpicker" data-default-color="" value="<?php echo ( $this->edit_mode_value ) ? $this->edit_mode_value : ''; ?>" /> </p> <?php break; case '_heading_background_color': ?> <p class="_heading_text"><label for="_heading_background_color"><?php _e( 'Heading Background Color', 'ultimate-member' ) ?> <?php UM()->tooltip( __( 'This will be the background of the heading section', 'ultimate-member' ) ); ?></label> <input type="text" name="_heading_background_color" id="_heading_background_color" class="um-admin-colorpicker" data-default-color="" value="<?php echo ( $this->edit_mode_value ) ? $this->edit_mode_value : ''; ?>" /> </p> <?php break; case '_heading_text_color': ?> <p class="_heading_text"><label for="_heading_text_color"><?php _e( 'Heading Text Color', 'ultimate-member' ) ?> <?php UM()->tooltip( __( 'This will be the text color of heading part only', 'ultimate-member' ) ); ?></label> <input type="text" name="_heading_text_color" id="_heading_text_color" class="um-admin-colorpicker" data-default-color="" value="<?php echo ( $this->edit_mode_value ) ? $this->edit_mode_value : ''; ?>" /> </p> <?php break; case '_text_color': ?> <p><label for="_text_color"><?php _e( 'Text Color', 'ultimate-member' ) ?> <?php UM()->tooltip( __( 'This will be the text color of entire section', 'ultimate-member' ) ); ?></label> <input type="text" name="_text_color" id="_text_color" class="um-admin-colorpicker" data-default-color="" value="<?php echo ( $this->edit_mode_value ) ? $this->edit_mode_value : ''; ?>" /> </p> <?php break; case '_icon_color': ?> <p class="_heading_text"><label for="_icon_color"><?php _e( 'Icon Color', 'ultimate-member' ) ?> <?php UM()->tooltip( __( 'This will be the color of selected icon. By default It will be the same color as heading text color', 'ultimate-member' ) ); ?></label> <input type="text" name="_icon_color" id="_icon_color" class="um-admin-colorpicker" data-default-color="" value="<?php echo ( $this->edit_mode_value ) ? $this->edit_mode_value : ''; ?>" /> </p> <?php break; case '_color': ?> <p><label for="_color"><?php _e( 'Color', 'ultimate-member' ) ?> <?php UM()->tooltip( __( 'Select a color for this divider', 'ultimate-member' ) ); ?></label> <input type="text" name="_color" id="_color" class="um-admin-colorpicker" data-default-color="#eeeeee" value="<?php echo ( $this->edit_mode_value ) ? $this->edit_mode_value : '#eeeeee'; ?>" /> </p> <?php break; case '_url_text': ?> <p><label for="_url_text"><?php _e( 'URL Alt Text', 'ultimate-member' ) ?> <?php UM()->tooltip( __( 'Entering custom text here will replace the url with a text link', 'ultimate-member' ) ); ?></label> <input type="text" name="_url_text" id="_url_text" value="<?php echo ( $this->edit_mode_value ) ? $this->edit_mode_value : ''; ?>" /> </p> <?php break; case '_url_target': ?> <p><label for="_url_target"><?php _e( 'Link Target', 'ultimate-member' ) ?> <?php UM()->tooltip( __( 'Choose whether to open this link in same window or in a new window', 'ultimate-member' ) ); ?></label> <select name="_url_target" id="_url_target" style="width: 100%"> <option value="_blank" <?php selected( '_blank', $this->edit_mode_value ); ?>><?php _e( 'Open in new window', 'ultimate-member' ) ?></option> <option value="_self" <?php selected( '_self', $this->edit_mode_value ); ?>><?php _e( 'Same window', 'ultimate-member' ) ?></option> </select> </p> <?php break; case '_url_rel': ?> <p><label for="_url_rel"><?php _e( 'SEO Follow', 'ultimate-member' ) ?> <?php UM()->tooltip( __( 'Whether to follow or nofollow this link by search engines', 'ultimate-member' ) ); ?></label> <select name="_url_rel" id="_url_rel" style="width: 100%"> <option value="follow" <?php selected( 'follow', $this->edit_mode_value ); ?>><?php _e( 'Follow', 'ultimate-member' ) ?></option> <option value="nofollow" <?php selected( 'nofollow', $this->edit_mode_value ); ?>><?php _e( 'No-Follow', 'ultimate-member' ) ?></option> </select> </p> <?php break; case '_force_good_pass': ?> <p><label for="_force_good_pass"><?php _e( 'Force strong password?', 'ultimate-member' ) ?> <?php UM()->tooltip( __( 'Turn on to force users to create a strong password (A combination of one lowercase letter, one uppercase letter, and one number). If turned on this option is only applied to register forms and not to login forms.', 'ultimate-member' ) ); ?></label> <input type="checkbox" name="_force_good_pass" id="_force_good_pass" value="1" <?php checked( isset( $this->edit_mode_value ) ? $this->edit_mode_value : UM()->options()->get( 'require_strongpass' ) ) ?> /> </p> <?php break; case '_force_confirm_pass': ?> <p><label for="_force_confirm_pass"><?php _e( 'Automatically add a confirm password field?', 'ultimate-member' ) ?> <?php UM()->tooltip( __( 'Turn on to add a confirm password field. If turned on the confirm password field will only show on register forms and not on login forms.', 'ultimate-member' ) ); ?></label> <input type="checkbox" name="_force_confirm_pass" id="_force_confirm_pass" value="1" <?php checked( isset( $this->edit_mode_value ) ? $this->edit_mode_value : 0 ) ?> class="um-adm-conditional" data-cond1="1" data-cond1-show="_label_confirm_pass" data-cond1-hide="xxx" /> </p> <?php break; case '_style': ?> <p><label for="_style"><?php _e( 'Style', 'ultimate-member' ) ?> <?php UM()->tooltip( __( 'This is the line-style of divider', 'ultimate-member' ) ); ?></label> <select name="_style" id="_style" style="width: 100%"> <option value="solid" <?php selected( 'solid', $this->edit_mode_value ); ?>><?php _e( 'Solid', 'ultimate-member' ) ?></option> <option value="dotted" <?php selected( 'dotted', $this->edit_mode_value ); ?>><?php _e( 'Dotted', 'ultimate-member' ) ?></option> <option value="dashed" <?php selected( 'dashed', $this->edit_mode_value ); ?>><?php _e( 'Dashed', 'ultimate-member' ) ?></option> <option value="double" <?php selected( 'double', $this->edit_mode_value ); ?>><?php _e( 'Double', 'ultimate-member' ) ?></option> </select> </p> <?php break; case '_intervals': ?> <p><label for="_intervals"><?php _e( 'Time Intervals (in minutes)', 'ultimate-member' ) ?> <?php UM()->tooltip( __( 'Choose the minutes interval between each time in the time picker.', 'ultimate-member' ) ); ?></label> <input type="text" name="_intervals" id="_intervals" value="<?php echo ( $this->edit_mode_value ) ? $this->edit_mode_value : 60; ?>" placeholder="<?php esc_attr_e( 'e.g. 30, 60, 120', 'ultimate-member' ) ?>" /> </p> <?php break; case '_format': if ( $this->set_field_type == 'date' ) { ?> <p><label for="_format"><?php _e( 'Date User-Friendly Format', 'ultimate-member' ) ?> <?php UM()->tooltip( __( 'The display format of the date which is visible to user.', 'ultimate-member' ) ); ?></label> <select name="_format" id="_format" style="width: 100%"> <option value="j M Y" <?php selected( 'j M Y', $this->edit_mode_value ); ?>><?php echo UM()->datetime()->get_time('j M Y'); ?></option> <option value="M j Y" <?php selected( 'M j Y', $this->edit_mode_value ); ?>><?php echo UM()->datetime()->get_time('M j Y'); ?></option> <option value="j F Y" <?php selected( 'j F Y', $this->edit_mode_value ); ?>><?php echo UM()->datetime()->get_time('j F Y'); ?></option> <option value="F j Y" <?php selected( 'F j Y', $this->edit_mode_value ); ?>><?php echo UM()->datetime()->get_time('F j Y'); ?></option> </select> </p> <?php } else { ?> <p><label for="_format"><?php _e( 'Time Format', 'ultimate-member' ) ?> <?php UM()->tooltip( __( 'Choose the displayed time-format for this field', 'ultimate-member' ) ); ?></label> <select name="_format" id="_format" style="width: 100%"> <option value="g:i a" <?php selected( 'g:i a', $this->edit_mode_value ); ?>><?php echo UM()->datetime()->get_time('g:i a'); ?><?php _e( '( 12-hr format )', 'ultimate-member' ) ?></option> <option value="g:i A" <?php selected( 'g:i A', $this->edit_mode_value ); ?>><?php echo UM()->datetime()->get_time('g:i A'); ?><?php _e( '( 12-hr format )', 'ultimate-member' ) ?></option> <option value="H:i" <?php selected( 'H:i', $this->edit_mode_value ); ?>><?php echo UM()->datetime()->get_time('H:i'); ?><?php _e( '( 24-hr format )', 'ultimate-member' ) ?></option> </select> </p> <?php } break; case '_format_custom': ?> <p><label for="_format_custom"><?php _e( 'Use custom Date format', 'ultimate-member' ); ?> <?php UM()->tooltip( __( 'This option overrides "Date User-Friendly Format" option. See https://www.php.net/manual/en/function.date.php', 'ultimate-member' ) ); ?></label> <input type="text" name="_format_custom" id="_format_custom" value="<?php echo esc_attr( $this->edit_mode_value ); ?>" placeholder="j M Y" /> </p> <?php break; case '_pretty_format': ?> <p><label for="_pretty_format"><?php esc_html_e( 'Displayed Date Format', 'ultimate-member' ); ?> <?php UM()->tooltip( __( 'Whether you wish to show the date in full or only show the years e.g. 25 Years', 'ultimate-member' ) ); ?></label> <select name="_pretty_format" id="_pretty_format" style="width: 100%"> <option value="0" <?php selected( 0, $this->edit_mode_value ); ?>><?php esc_html_e( 'Show full date', 'ultimate-member' ); ?></option> <option value="1" <?php selected( 1, $this->edit_mode_value ); ?>><?php esc_html_e( 'Show years only', 'ultimate-member' ); ?></option> </select> </p> <?php break; case '_disabled_weekdays': if ( isset( $this->edit_mode_value ) && is_array( $this->edit_mode_value ) ) { $values = $this->edit_mode_value; } else { $values = array(''); } ?> <p><label for="_disabled_weekdays"><?php _e( 'Disable specific weekdays', 'ultimate-member' ) ?> <?php UM()->tooltip( __( 'Disable specific week days from being available for selection in this date picker', 'ultimate-member' ) ); ?></label> <select name="_disabled_weekdays[]" id="_disabled_weekdays" multiple="multiple" style="width: 100%"> <option value="1" <?php if ( in_array( 1, $values ) ) { echo 'selected'; } ?>><?php _e( 'Sunday', 'ultimate-member' ) ?></option> <option value="2" <?php if ( in_array( 2, $values ) ) { echo 'selected'; } ?>><?php _e( 'Monday', 'ultimate-member' ) ?></option> <option value="3" <?php if ( in_array( 3, $values ) ) { echo 'selected'; } ?>><?php _e( 'Tuesday', 'ultimate-member' ) ?></option> <option value="4" <?php if ( in_array( 4, $values ) ) { echo 'selected'; } ?>><?php _e( 'Wednesday', 'ultimate-member' ) ?></option> <option value="5" <?php if ( in_array( 5, $values ) ) { echo 'selected'; } ?>><?php _e( 'Thursday', 'ultimate-member' ) ?></option> <option value="6" <?php if ( in_array( 6, $values ) ) { echo 'selected'; } ?>><?php _e( 'Friday', 'ultimate-member' ) ?></option> <option value="7" <?php if ( in_array( 7, $values ) ) { echo 'selected'; } ?>><?php _e( 'Saturday', 'ultimate-member' ) ?></option> </select> </p> <?php break; case '_years': ?> <p class="_years"><label for="_years"><?php _e( 'Number of Years to pick from', 'ultimate-member' ) ?> <?php UM()->tooltip( __( 'Number of years available for the date selection. Default to last 50 years', 'ultimate-member' ) ); ?></label> <input type="text" name="_years" id="_years" value="<?php echo ( $this->edit_mode_value ) ? $this->edit_mode_value : 50; ?>" /> </p> <?php break; case '_years_x': ?> <p class="_years"><label for="_years_x"><?php _e( 'Years Selection', 'ultimate-member' ) ?> <?php UM()->tooltip( __( 'This decides which years should be shown relative to today date', 'ultimate-member' ) ); ?></label> <select name="_years_x" id="_years_x" style="width: 100%"> <option value="equal" <?php selected( 'equal', $this->edit_mode_value ); ?>><?php _e( 'Equal years before / after today', 'ultimate-member' ) ?></option> <option value="past" <?php selected( 'past', $this->edit_mode_value ); ?>><?php _e( 'Past years only', 'ultimate-member' ) ?></option> <option value="future" <?php selected( 'future', $this->edit_mode_value ); ?>><?php _e( 'Future years only', 'ultimate-member' ) ?></option> </select> </p> <?php break; case '_range_start': ?> <p class="_date_range"><label for="_range_start"><?php _e( 'Date Range Start', 'ultimate-member' ) ?> <?php UM()->tooltip( __( 'Set the minimum date/day in range in the format YYYY/MM/DD', 'ultimate-member' ) ); ?></label> <input type="text" name="_range_start" id="_range_start" value="<?php echo $this->edit_mode_value; ?>" placeholder="<?php esc_attr_e( 'YYYY/MM/DD', 'ultimate-member' ) ?>" /> </p> <?php break; case '_range_end': ?> <p class="_date_range"><label for="_range_end"><?php _e( 'Date Range End', 'ultimate-member' ) ?> <?php UM()->tooltip( __( 'Set the maximum date/day in range in the format YYYY/MM/DD', 'ultimate-member' ) ); ?></label> <input type="text" name="_range_end" id="_range_end" value="<?php echo $this->edit_mode_value; ?>" placeholder="<?php esc_attr_e( 'YYYY/MM/DD', 'ultimate-member' ) ?>" /> </p> <?php break; case '_range': ?> <p><label for="_range"><?php _e( 'Set Date Range', 'ultimate-member' ) ?> <?php UM()->tooltip( __( 'Whether to show a specific number of years or specify a date range to be available for the date picker.', 'ultimate-member' ) ); ?></label> <select name="_range" id="_range" class="um-adm-conditional" data-cond1='years' data-cond1-show='_years' data-cond2="date_range" data-cond2-show="_date_range" style="width: 100%"> <option value="years" <?php selected( 'years', $this->edit_mode_value ); ?>><?php _e( 'Fixed Number of Years', 'ultimate-member' ) ?></option> <option value="date_range" <?php selected( 'date_range', $this->edit_mode_value ); ?>><?php _e( 'Specific Date Range', 'ultimate-member' ) ?></option> </select> </p> <?php break; case '_content': if ( $this->set_field_type == 'shortcode' ) { ?> <p><label for="_content"><?php _e( 'Enter Shortcode', 'ultimate-member' ) ?> <?php UM()->tooltip( __( 'Enter the shortcode in the following textarea and it will be displayed on the fields', 'ultimate-member' ) ); ?></label> <textarea name="_content" id="_content" placeholder="<?php esc_attr_e( 'e.g. [my_custom_shortcode]', 'ultimate-member' ) ?>"><?php echo $this->edit_mode_value; ?></textarea> </p> <?php } else { ?> <div class="um-admin-editor-h"><label><?php _e( 'Content Editor', 'ultimate-member' ) ?> <?php UM()->tooltip( __( 'Edit the content of this field here', 'ultimate-member' ) ); ?></label></div> <div class="um-admin-editor"><!-- editor dynamically loaded here --></div> <?php } break; case '_crop': ?> <p><label for="_crop"><?php _e( 'Crop Feature', 'ultimate-member' ) ?> <?php UM()->tooltip( __( 'Enable/disable crop feature for this image upload and define ratio', 'ultimate-member' ) ); ?></label> <select name="_crop" id="_crop" style="width: 100%"> <option value="0" <?php selected( '0', $this->edit_mode_value ); ?>><?php _e( 'Turn Off (Default)', 'ultimate-member' ) ?></option> <option value="1" <?php selected( '1', $this->edit_mode_value ); ?>><?php _e( 'Crop and force 1:1 ratio', 'ultimate-member' ) ?></option> <option value="3" <?php selected( '3', $this->edit_mode_value ); ?>><?php _e( 'Crop and force user-defined ratio', 'ultimate-member' ) ?></option> </select> </p> <?php break; case '_allowed_types': if ( $this->set_field_type == 'image' ) { if ( isset( $this->edit_mode_value ) && is_array( $this->edit_mode_value ) ) { $values = $this->edit_mode_value; } else { $values = array( 'png','jpeg','jpg','gif' ); } ?> <p><label for="_allowed_types"><?php _e( 'Allowed Image Types', 'ultimate-member' ) ?> <?php UM()->tooltip( __( 'Select the image types that you want to allow to be uploaded via this field.', 'ultimate-member' ) ); ?></label> <select name="_allowed_types[]" id="_allowed_types" multiple="multiple" style="width: 100%"> <?php foreach( UM()->files()->allowed_image_types() as $e => $n ) { ?> <option value="<?php echo $e; ?>" <?php if ( in_array( $e, $values ) ) { echo 'selected'; } ?>><?php echo $n; ?></option> <?php } ?> </select> </p> <?php } else { if ( isset( $this->edit_mode_value ) && is_array( $this->edit_mode_value ) ) { $values = $this->edit_mode_value; } else { $values = array( 'pdf', 'txt' ); } ?> <p><label for="_allowed_types"><?php _e( 'Allowed File Types', 'ultimate-member' ) ?> <?php UM()->tooltip( __( 'Select the image types that you want to allow to be uploaded via this field.', 'ultimate-member' ) ); ?></label> <select name="_allowed_types[]" id="_allowed_types" multiple="multiple" style="width: 100%"> <?php foreach( UM()->files()->allowed_file_types() as $e => $n ) { ?> <option value="<?php echo $e; ?>" <?php if ( in_array( $e, $values ) ) { echo 'selected'; } ?>><?php echo $n; ?></option> <?php } ?> </select> </p> <?php } break; case '_upload_text': if ( $this->set_field_type == 'image' ) { $value = __( 'Drag & Drop Photo', 'ultimate-member' ); } if ( $this->set_field_type == 'file' ) { $value = __( 'Drag & Drop File', 'ultimate-member' ); } ?> <p><label for="_upload_text"><?php _e( 'Upload Box Text', 'ultimate-member' ) ?> <?php UM()->tooltip( __( 'This is the headline that appears in the upload box for this field', 'ultimate-member' ) ); ?></label> <input type="text" name="_upload_text" id="_upload_text" value="<?php echo ( $this->edit_mode_value ) ? $this->edit_mode_value : $value; ?>" /> </p> <?php break; case '_upload_help_text': ?> <p><label for="_upload_help_text"><?php _e( 'Additional Instructions Text', 'ultimate-member' ) ?> <?php UM()->tooltip( __( 'If you need to add information or secondary line below the headline of upload box, enter it here', 'ultimate-member' ) ); ?></label> <input type="text" name="_upload_help_text" id="_upload_help_text" value="<?php echo $this->edit_mode_value; ?>" /> </p> <?php break; case '_button_text': ?> <p><label for="_button_text"><?php _e( 'Upload Box Text', 'ultimate-member' ) ?> <?php UM()->tooltip( __( 'The text that appears on the button. e.g. Upload', 'ultimate-member' ) ); ?></label> <input type="text" name="_button_text" id="_button_text" value="<?php echo ( $this->edit_mode_value ) ? $this->edit_mode_value : __( 'Upload', 'ultimate-member' ); ?>" /> </p> <?php break; case '_max_size': ?> <p><label for="_max_size"><?php _e( 'Maximum Size in bytes', 'ultimate-member' ) ?> <?php UM()->tooltip( __( 'The maximum size for image that can be uploaded through this field. Leave empty for unlimited size.', 'ultimate-member' ) ); ?></label> <input type="text" name="_max_size" id="_max_size" value="<?php echo $this->edit_mode_value; ?>" /> </p> <?php break; case '_height': ?> <p><label for="_height"><?php _e( 'Textarea Height', 'ultimate-member' ) ?> <?php UM()->tooltip( __( 'The height of textarea in pixels. Default is 100 pixels', 'ultimate-member' ) ); ?></label> <input type="text" name="_height" id="_height" value="<?php echo ( $this->edit_mode_value ) ? $this->edit_mode_value : '100px'; ?>" /> </p> <?php break; case '_spacing': ?> <p><label for="_spacing"><?php _e( 'Spacing', 'ultimate-member' ) ?> <?php UM()->tooltip( __( 'This is the required spacing in pixels. e.g. 20px', 'ultimate-member' ) ); ?></label> <input type="text" name="_spacing" id="_spacing" value="<?php echo ( $this->edit_mode_value ) ? $this->edit_mode_value : '20px'; ?>" /> </p> <?php break; case '_is_multi': ?> <p><label for="_is_multi"><?php _e( 'Allow multiple selections', 'ultimate-member' ) ?> <?php UM()->tooltip( __( 'Enable/disable multiple selections for this field', 'ultimate-member' ) ); ?></label> <input type="checkbox" name="_is_multi" id="_is_multi" value="1" <?php checked( isset( $this->edit_mode_value ) ? $this->edit_mode_value : 0 ) ?> class="um-adm-conditional" data-cond1="1" data-cond1-show="_max_selections" data-cond1-hide="xxx" /> </p> <?php break; case '_max_selections': ?> <p class="_max_selections"><label for="_max_selections"><?php _e( 'Maximum number of selections', 'ultimate-member' ) ?> <?php UM()->tooltip( __( 'Enter a number here to force a maximum number of selections by user for this field', 'ultimate-member' ) ); ?></label> <input type="text" name="_max_selections" id="_max_selections" value="<?php echo $this->edit_mode_value; ?>" /> </p> <?php break; case '_min_selections': ?> <p class="_min_selections"><label for="_min_selections"><?php _e( 'Minimum number of selections', 'ultimate-member' ) ?> <?php UM()->tooltip( __( 'Enter a number here to force a minimum number of selections by user for this field', 'ultimate-member' ) ); ?></label> <input type="text" name="_min_selections" id="_min_selections" value="<?php echo $this->edit_mode_value; ?>" /> </p> <?php break; case '_max_entries': ?> <p class="_max_entries"><label for="_max_selections"><?php _e( 'Maximum number of entries', 'ultimate-member' ) ?> <?php UM()->tooltip( __( 'This is the max number of entries the user can add via field group.', 'ultimate-member' ) ); ?></label> <input type="text" name="_max_entries" id="_max_entries" value="<?php echo ( $this->edit_mode_value ) ? $this->edit_mode_value : 10; ?>" /> </p> <?php break; case '_max_words': ?> <p><label for="_max_words"><?php _e( 'Maximum allowed words', 'ultimate-member' ) ?> <?php UM()->tooltip( __( 'If you want to enable a maximum number of words to be input in this textarea. Leave empty to disable this setting', 'ultimate-member' ) ); ?></label> <input type="text" name="_max_words" id="_max_words" value="<?php echo $this->edit_mode_value; ?>" /> </p> <?php break; case '_min': ?> <p><label for="_min"><?php _e( 'Minimum Number', 'ultimate-member' ) ?> <?php UM()->tooltip( __( 'Minimum number that can be entered in this field', 'ultimate-member' ) ); ?></label> <input type="text" name="_min" id="_min" value="<?php echo $this->edit_mode_value; ?>" /> </p> <?php break; case '_max': ?> <p><label for="_max"><?php _e( 'Maximum Number', 'ultimate-member' ) ?> <?php UM()->tooltip( __( 'Maximum number that can be entered in this field', 'ultimate-member' ) ); ?></label> <input type="text" name="_max" id="_max" value="<?php echo $this->edit_mode_value; ?>" /> </p> <?php break; case '_min_chars': ?> <p><label for="_min_chars"><?php _e( 'Minimum length', 'ultimate-member' ) ?> <?php UM()->tooltip( __( 'If you want to enable a minimum number of characters to be input in this field. Leave empty to disable this setting', 'ultimate-member' ) ); ?></label> <input type="text" name="_min_chars" id="_min_chars" value="<?php echo $this->edit_mode_value; ?>" /> </p> <?php break; case '_max_chars': ?> <p><label for="_max_chars"><?php _e( 'Maximum length', 'ultimate-member' ) ?> <?php UM()->tooltip( __( 'If you want to enable a maximum number of characters to be input in this field. Leave empty to disable this setting', 'ultimate-member' ) ); ?></label> <input type="text" name="_max_chars" id="_max_chars" value="<?php echo $this->edit_mode_value; ?>" /> </p> <?php break; case '_html': ?> <p><label for="_html"><?php _e( 'Does this textarea accept HTML?', 'ultimate-member' ) ?> <?php UM()->tooltip( __( 'Turn on/off HTML tags for this textarea', 'ultimate-member' ) ); ?></label> <input type="checkbox" name="_html" id="_html" value="1" <?php checked( isset( $this->edit_mode_value ) ? $this->edit_mode_value : 0 ) ?> /> </p> <?php break; case '_options': if ( isset( $this->edit_mode_value ) && is_array( $this->edit_mode_value ) ) { $values = implode("\n", $this->edit_mode_value); } else if ( $this->edit_mode_value ) { $values = $this->edit_mode_value; } else { $values = ''; } ?> <p><label for="_options"><?php _e( 'Edit Choices', 'ultimate-member' ) ?> <?php UM()->tooltip( __( 'Enter one choice per line. This will represent the available choices or selections available for user.', 'ultimate-member' ) ); ?></label> <textarea name="_options" id="_options"><?php echo $values; ?></textarea> </p> <?php break; case '_title': ?> <p><label for="_title"><?php _e( 'Title', 'ultimate-member' ) ?> <?php UM()->tooltip( __( 'This is the title of the field for your reference in the backend. The title will not appear on the front-end of your website.', 'ultimate-member' ) ); ?></label> <input type="text" name="_title" id="_title" value="<?php echo esc_attr( $this->edit_mode_value ); ?>" /> </p> <?php break; case '_id': ?> <p style="display:none"><label for="_id"><?php _e( 'Unique ID', 'ultimate-member' ) ?></label> <input type="text" name="_id" id="_id" value="<?php echo esc_attr( $this->edit_mode_value ); ?>" /> </p> <?php break; case '_metakey': if ( $this->in_edit ) { ?> <p><label for="_metakey"><?php _e( 'Meta Key', 'ultimate-member' ) ?> <?php UM()->tooltip( __( 'The meta key cannot be changed for duplicated fields or when editing an existing field. If you require a different meta key please create a new field.', 'ultimate-member' ) ); ?></label> <input type="text" name="_metakey_locked" id="_metakey_locked" value="<?php echo $this->edit_mode_value; ?>" disabled /> </p> <?php } else { ?> <p><label for="_metakey"><?php _e( 'Meta Key', 'ultimate-member' ) ?> <?php UM()->tooltip( __( 'A meta key is required to store the entered info in this field in the database. The meta key should be unique to this field and be written in lowercase with an underscore ( _ ) separating words e.g country_list or job_title', 'ultimate-member' ) ); ?></label> <input type="text" name="_metakey" id="_metakey" value="" /> </p> <?php } break; case '_help': ?> <p><label for="_help"><?php _e( 'Help Text', 'ultimate-member' ) ?> <?php UM()->tooltip( __('This is the text that appears in a tooltip when a user hovers over the info icon. Help text is useful for providing users with more information about what they should enter in the field. Leave blank if no help text is needed for field.', 'ultimate-member' ) ); ?></label> <input type="text" name="_help" id="_help" value="<?php echo $this->edit_mode_value; ?>" /> </p> <?php break; case '_default': ?> <?php if ( $this->set_field_type == 'textarea' ) { ?> <p><label for="_default"><?php _e( 'Default Text', 'ultimate-member' ); ?> <?php UM()->tooltip( __( 'Text to display by default in this field', 'ultimate-member' ) ); ?></label> <textarea name="_default" id="_default"><?php echo $this->edit_mode_value; ?></textarea> </p> <?php } elseif ( $this->set_field_type == 'date' ) { ?> <p class="um"><label for="_default"><?php _e( 'Default Date', 'ultimate-member' ); ?> <?php UM()->tooltip( __( 'You may use all PHP compatible date formats such as: 2020-02-02, 02/02/2020, yesterday, today, tomorrow, next monday, first day of next month, +3 day', 'ultimate-member' ) ); ?></label> <input type="text" name="_default" id="_default" value="<?php echo $this->edit_mode_value; ?>" class="um-datepicker" data-format="yyyy/mm/dd" /> </p> <?php } elseif ( $this->set_field_type == 'time' ) { ?> <p class="um"><label for="_default"><?php _e( 'Default Time', 'ultimate-member' ); ?> <?php UM()->tooltip( __( 'You may use all PHP compatible date formats such as: 2020-02-02, 02/02/2020, yesterday, today, tomorrow, next monday, first day of next month, +3 day', 'ultimate-member' ) ); ?></label> <input type="text" name="_default" id="_default" value="<?php echo $this->edit_mode_value; ?>" class="um-timepicker" data-format="HH:i" /> </p> <?php } elseif ( $this->set_field_type == 'rating' ) { ?> <p><label for="_default"><?php _e( 'Default Rating', 'ultimate-member' ); ?> <?php UM()->tooltip( __( 'If you wish the rating field to be prefilled with a number of stars, enter it here.', 'ultimate-member' ) ); ?></label> <input type="text" name="_default" id="_default" value="<?php echo $this->edit_mode_value; ?>" /> </p> <?php } else { ?> <p><label for="_default"><?php _e( 'Default Value', 'ultimate-member' ); ?> <?php UM()->tooltip( __( 'This option allows you to pre-fill the field with a default value prior to the user entering a value in the field. Leave blank to have no default value', 'ultimate-member' ) ); ?></label> <input type="text" name="_default" id="_default" value="<?php echo esc_attr( $this->edit_mode_value ); ?>" /> </p> <?php } ?> <?php break; case '_label': ?> <p><label for="_label"><?php _e( 'Label', 'ultimate-member' ) ?> <?php UM()->tooltip( __( 'The field label is the text that appears above the field on your front-end form. Leave blank to not show a label above field.', 'ultimate-member' ) ); ?></label> <input type="text" name="_label" id="_label" value="<?php echo esc_attr( $this->edit_mode_value ); ?>" /> </p> <?php break; case '_label_confirm_pass': ?> <p><label for="_label_confirm_pass"><?php _e( 'Confirm password field label', 'ultimate-member' ) ?> <?php UM()->tooltip( __( 'This label is the text that appears above the confirm password field. Leave blank to show default label.', 'ultimate-member' ) ); ?></label> <input type="text" name="_label_confirm_pass" id="_label_confirm_pass" value="<?php echo esc_attr( $this->edit_mode_value ); ?>" /> </p> <?php break; case '_placeholder': ?> <p><label for="_placeholder"><?php _e( 'Placeholder', 'ultimate-member' ) ?> <?php UM()->tooltip( __( 'This is the text that appears within the field e.g please enter your email address. Leave blank to not show any placeholder text.', 'ultimate-member' ) ); ?></label> <input type="text" name="_placeholder" id="_placeholder" value="<?php echo esc_attr( $this->edit_mode_value ); ?>" /> </p> <?php break; case '_public': $privacy_options = array( '1' => __( 'Everyone', 'ultimate-member' ), '2' => __( 'Members', 'ultimate-member' ), '-1' => __( 'Only visible to profile owner and users who can edit other member accounts', 'ultimate-member' ), '-3' => __( 'Only visible to profile owner and specific roles', 'ultimate-member' ), '-2' => __( 'Only specific member roles', 'ultimate-member' ), ); $privacy_options = apply_filters( 'um_field_privacy_options', $privacy_options ); ?> <p> <label for="_public"><?php _e( 'Privacy', 'ultimate-member' ) ?> <?php UM()->tooltip( __( 'Field privacy allows you to select who can view this field on the front-end. The site admin can view all fields regardless of the option set here.', 'ultimate-member' ) ); ?></label> <select name="_public" id="_public" class="um-adm-conditional" data-cond1="-2" data-cond1-show="_roles" data-cond2="-3" data-cond2-show="_roles" style="width: 100%"> <?php foreach ( $privacy_options as $value => $title ) { ?> <option value="<?php echo esc_attr( $value ) ?>" <?php selected( $value, $this->edit_mode_value ); ?>> <?php echo $title ?> </option> <?php } ?> </select> </p> <?php break; case '_roles': if ( isset( $this->edit_mode_value ) && is_array( $this->edit_mode_value ) ) { $values = $this->edit_mode_value; } else { $values = array(''); } ?> <p class="_roles"><label for="_roles"><?php _e( 'Select member roles', 'ultimate-member' ) ?> <?php UM()->tooltip( __( 'Select the member roles that can view this field on the front-end.', 'ultimate-member' ) ); ?></label> <select name="_roles[]" id="_roles" style="width: 100%" multiple="multiple"> <?php foreach ( UM()->roles()->get_roles() as $key => $value) { ?> <option value="<?php echo $key; ?>" <?php if ( in_array( $key, $values ) ) { echo 'selected'; } ?>><?php echo $value; ?></option> <?php } ?> </select> </p> <?php break; case '_required': if ( $this->set_field_type == 'password' ) $def_required = 1; else $def_required = 0; ?> <div class="um-admin-tri"> <p><label for="_required"><?php _e( 'Is this field required?', 'ultimate-member' ) ?> <?php UM()->tooltip( __( 'This option allows you to set whether the field must be filled in before the form can be processed.', 'ultimate-member' ) ); ?></label> <input type="checkbox" name="_required" id="_required" value="1" <?php checked( isset( $this->edit_mode_value ) ? $this->edit_mode_value : $def_required ) ?> /> </p> </div> <?php break; case '_editable': // Make a new field editable by default. if ( false === $this->in_edit ) { $this->edit_mode_value = true; } // Set to true if `editable` doesn't exist (legacy case). It will be saved to DB as `true` after the first field update. if ( null === $this->edit_mode_value ) { $this->edit_mode_value = true; } if ( empty( $this->edit_mode_value ) ) { $this->edit_mode_value = false; } ?> <div class="um-admin-tri"> <p><label for="_editable"><?php esc_html_e( 'Can user edit this field?', 'ultimate-member' ); ?> <?php UM()->tooltip( __( 'This option allows you to set whether or not the user can edit the information in this field. The site admin can edit all fields regardless of the option set here.', 'ultimate-member' ) ); ?></label> <input type="hidden" name="_editable" id="_editable_hidden" value="0" /> <input type="checkbox" name="_editable" id="_editable" value="1" <?php checked( $this->edit_mode_value ); ?> /> </p> </div> <?php break; case '_number': ?> <p><label for="_number"><?php _e( 'Rating System', 'ultimate-member' ) ?> <?php UM()->tooltip( __( 'Choose whether you want a 5-stars or 10-stars ratings based here.', 'ultimate-member' ) ); ?></label> <select name="_number" id="_number" style="width: 100%"> <option value="5" <?php selected( 5, $this->edit_mode_value ); ?>><?php _e( '5 stars rating system', 'ultimate-member' ) ?></option> <option value="10" <?php selected( 10, $this->edit_mode_value ); ?>><?php _e( '10 stars rating system', 'ultimate-member' ) ?></option> </select> </p> <?php break; case '_custom_dropdown_options_source': ?> <p><label for="_custom_dropdown_options_source"><?php esc_html_e( 'Choices Callback', 'ultimate-member' ) ?> <?php UM()->tooltip( __( 'Add a callback source to retrieve choices.', 'ultimate-member' ) ); ?></label> <input type="text" name="_custom_dropdown_options_source" id="_custom_dropdown_options_source" value="<?php echo esc_attr( $this->edit_mode_value ); ?>" /> </p> <?php break; case '_parent_dropdown_relationship': ?> <p><label for="_parent_dropdown_relationship"><?php esc_html_e( 'Parent Option', 'ultimate-member' ); ?><?php UM()->tooltip( __( 'Dynamically populates the option based from selected parent option.', 'ultimate-member' ) ); ?></label> <select name="_parent_dropdown_relationship" id="_parent_dropdown_relationship" style="width: 100%"> <option value=""><?php esc_html_e( 'No Selected', 'ultimate-member' ); ?></option> <?php if ( UM()->builtin()->custom_fields ) { foreach ( UM()->builtin()->custom_fields as $array ) { if ( array_key_exists( 'type', $array ) && 'select' === $array['type'] && ( ! isset( $field_args['metakey'] ) || $field_args['metakey'] != $array['metakey'] ) && isset( $array['title'] ) ) { ?> <option value="<?php echo esc_attr( $array['metakey'] ); ?>" <?php selected( $array['metakey'], $this->edit_mode_value ); ?>><?php echo esc_html( $array['title'] ); ?></option> <?php } } } ?> </select> </p> <?php break; } // Flush class variable. $this->edit_mode_value = null; } } } includes/admin/core/list-tables/roles-list-table.php 0000644 00000034627 15252504435 0016531 0 ustar 00 <?php if ( ! defined( 'ABSPATH' ) ) { exit; } global $wpdb; if ( isset( $_REQUEST['_wp_http_referer'] ) ) { $redirect = remove_query_arg( array( '_wp_http_referer' ), wp_unslash( $_REQUEST['_wp_http_referer'] ) ); } else { $redirect = get_admin_url() . 'admin.php?page=um_roles'; } global $wp_roles; if ( isset( $_GET['action'] ) ) { switch ( sanitize_key( $_GET['action'] ) ) { /* delete action */ case 'delete': { // uses sanitize_title instead of sanitize_key for backward compatibility based on #906 pull-request (https://github.com/ultimatemember/ultimatemember/pull/906) // roles e.g. "潜水艦subs" with both latin + not-UTB-8 symbols had invalid role ID $role_keys = array(); if ( isset( $_REQUEST['id'] ) ) { check_admin_referer( 'um_role_delete' . sanitize_title( $_REQUEST['id'] ) . get_current_user_id() ); $role_keys = (array) sanitize_title( $_REQUEST['id'] ); } elseif ( isset( $_REQUEST['item'] ) ) { check_admin_referer( 'bulk-' . sanitize_key( __( 'Roles', 'ultimate-member' ) ) ); $role_keys = array_map( 'sanitize_title', $_REQUEST['item'] ); } if ( ! count( $role_keys ) ) { um_js_redirect( $redirect ); } $um_roles = get_option( 'um_roles', array() ); $um_custom_roles = array(); foreach ( $role_keys as $k => $role_key ) { $role_meta = get_option( "um_role_{$role_key}_meta" ); if ( empty( $role_meta['_um_is_custom'] ) ) { continue; } delete_option( "um_role_{$role_key}_meta" ); /** * Fires after delete UM role. * * @since 2.6.3 * @hook um_after_delete_role * * @param {string} $role_key Role key. * @param {array} $role_meta Role meta. * * @example <caption>Make any custom action after deleting UM role.</caption> * function my_custom_um_after_delete_role( $role_key, $role_meta ) { * // your code here * } * add_action( 'um_after_delete_role', 'my_custom_um_after_delete_role', 10, 2 ); */ do_action( 'um_after_delete_role', $role_key, $role_meta ); $um_roles = array_diff( $um_roles, array( $role_key ) ); $roleID = 'um_' . $role_key; $um_custom_roles[] = $roleID; //check if role exist before removing it if ( get_role( $roleID ) ) { remove_role( $roleID ); } } //set for users with deleted roles role "Subscriber" $args = array( 'blog_id' => get_current_blog_id(), 'role__in' => $um_custom_roles, 'number' => -1, 'count_total' => false, 'fields' => 'ids', ); $users_to_subscriber = get_users( $args ); if ( ! empty( $users_to_subscriber ) ) { foreach ( $users_to_subscriber as $user_id ) { $object_user = get_userdata( $user_id ); if ( ! empty( $object_user ) ) { foreach ( $um_custom_roles as $roleID ) { $object_user->remove_role( $roleID ); } } //update user role if it's empty if ( empty( $object_user->roles ) ) { wp_update_user( array( 'ID' => $user_id, 'role' => 'subscriber', ) ); } } } update_option( 'um_roles', $um_roles ); um_js_redirect( add_query_arg( 'msg', 'd', $redirect ) ); break; } case 'reset': { // uses sanitize_title instead of sanitize_key for backward compatibility based on #906 pull-request (https://github.com/ultimatemember/ultimatemember/pull/906) // roles e.g. "潜水艦subs" with both latin + not-UTB-8 symbols had invalid role ID $role_keys = array(); if ( isset( $_REQUEST['id'] ) ) { check_admin_referer( 'um_role_reset' . sanitize_title( $_REQUEST['id'] ) . get_current_user_id() ); $role_keys = (array) sanitize_title( $_REQUEST['id'] ); } elseif ( isset( $_REQUEST['item'] ) ) { check_admin_referer( 'bulk-' . sanitize_key( __( 'Roles', 'ultimate-member' ) ) ); $role_keys = array_map( 'sanitize_title', $_REQUEST['item'] ); } if ( ! count( $role_keys ) ) { um_js_redirect( $redirect ); } foreach ( $role_keys as $k => $role_key ) { $role_meta = get_option( "um_role_{$role_key}_meta" ); if ( ! empty( $role_meta['_um_is_custom'] ) ) { unset( $role_keys[ array_search( $role_key, $role_keys, true ) ] ); continue; } delete_option( "um_role_{$role_key}_meta" ); /** * Fires after delete UM role meta. * * @since 2.6.3 * @hook um_after_delete_role_meta * * @param {string} $role_key Role key. * @param {array} $role_meta Role meta. * * @example <caption>Make any custom action after deleting UM role meta.</caption> * function my_custom_um_after_delete_role_meta( $role_key, $role_meta ) { * // your code here * } * add_action( 'um_after_delete_role_meta', 'my_custom_um_after_delete_role_meta', 10, 2 ); */ do_action( 'um_after_delete_role_meta', $role_key, $role_meta ); } um_js_redirect( add_query_arg( 'msg', 'reset', $redirect ) ); break; } } } //remove extra query arg if ( ! empty( $_GET['_wp_http_referer'] ) ) { um_js_redirect( remove_query_arg( array( '_wp_http_referer', '_wpnonce' ), wp_unslash( $_SERVER['REQUEST_URI'] ) ) ); } $order_by = 'name'; $order = ( isset( $_GET['order'] ) && 'asc' === strtolower( sanitize_key( $_GET['order'] ) ) ) ? 'ASC' : 'DESC'; if ( ! class_exists( 'WP_List_Table' ) ) { require_once ABSPATH . 'wp-admin/includes/class-wp-list-table.php'; } /** * Class UM_Roles_List_Table */ class UM_Roles_List_Table extends WP_List_Table { /** * @var string */ var $no_items_message = ''; /** * @var array */ var $sortable_columns = array(); /** * @var string */ var $default_sorting_field = ''; /** * @var array */ var $actions = array(); /** * @var array */ var $bulk_actions = array(); /** * @var array */ var $columns = array(); /** * UM_Roles_List_Table constructor. * * @param array $args */ function __construct( $args = array() ) { $args = wp_parse_args( $args, array( 'singular' => __( 'item', 'ultimate-member' ), 'plural' => __( 'items', 'ultimate-member' ), 'ajax' => false, ) ); $this->no_items_message = $args['plural'] . ' ' . __( 'not found.', 'ultimate-member' ); parent::__construct( $args ); } /** * @param callable $name * @param array $arguments * * @return mixed */ function __call( $name, $arguments ) { return call_user_func_array( array( $this, $name ), $arguments ); } /** * */ function prepare_items() { $columns = $this->get_columns(); $hidden = array(); $sortable = $this->get_sortable_columns(); $this->_column_headers = array( $columns, $hidden, $sortable ); } /** * @param object $item * @param string $column_name * * @return string */ function column_default( $item, $column_name ) { if( isset( $item[ $column_name ] ) ) { return $item[ $column_name ]; } else { return ''; } } /** * */ function no_items() { echo $this->no_items_message; } /** * @param array $args * * @return $this */ function set_sortable_columns( $args = array() ) { $return_args = array(); foreach ( $args as $k => $val ) { if ( is_numeric( $k ) ) { $return_args[ $val ] = array( $val, $val === $this->default_sorting_field ); } elseif ( is_string( $k ) ) { $return_args[ $k ] = array( $val, $k === $this->default_sorting_field ); } else { continue; } } $this->sortable_columns = $return_args; return $this; } /** * @return array */ function get_sortable_columns() { return $this->sortable_columns; } /** * @param array $args * * @return $this */ function set_columns( $args = array() ) { if( count( $this->bulk_actions ) ) { $args = array_merge( array( 'cb' => '<input type="checkbox" />' ), $args ); } $this->columns = $args; return $this; } /** * @return array */ function get_columns() { return $this->columns; } /** * @param array $args * * @return $this */ function set_actions( $args = array() ) { $this->actions = $args; return $this; } /** * @return array */ function get_actions() { return $this->actions; } /** * @param array $args * * @return $this */ function set_bulk_actions( $args = array() ) { $this->bulk_actions = $args; return $this; } /** * @return array */ function get_bulk_actions() { return $this->bulk_actions; } /** * @param object $item * * @return string */ function column_cb( $item ) { return sprintf( '<input type="checkbox" name="item[]" value="%s" />', $item['key'] ); } /** * @param $item * * @return string */ function column_title( $item ) { $actions = array(); // for backward compatibility based on #906 pull-request (https://github.com/ultimatemember/ultimatemember/pull/906) // roles e.g. "潜水艦subs" with both latin + not-UTB-8 symbols had invalid role ID $id = urlencode( $item['key'] ); $actions['edit'] = '<a href="admin.php?page=um_roles&tab=edit&id=' . esc_attr( $id ) . '">' . __( 'Edit', 'ultimate-member' ) . '</a>'; if ( ! empty( $item['_um_is_custom'] ) ) { $actions['delete'] = '<a href="admin.php?page=um_roles&action=delete&id=' . esc_attr( $id ) . '&_wpnonce=' . wp_create_nonce( 'um_role_delete' . $item['key'] . get_current_user_id() ) . '" onclick="return confirm( \'' . __( 'Are you sure you want to delete this role?', 'ultimate-member' ) . '\' );">' . __( 'Delete', 'ultimate-member' ) . '</a>'; } else { $role_meta = get_option( "um_role_{$item['key']}_meta" ); if ( ! empty( $role_meta ) ) { $actions['reset'] = '<a href="admin.php?page=um_roles&action=reset&id=' . esc_attr( $id ) . '&_wpnonce=' . wp_create_nonce( 'um_role_reset' . $item['key'] . get_current_user_id() ) . '" onclick="return confirm( \'' . __( 'Are you sure you want to reset UM role meta?', 'ultimate-member' ) . '\' );">' . __( 'Reset UM Role meta', 'ultimate-member' ) . '</a>'; } } /** * Filters the role actions in WP ListTable Ultimate Member > Roles screen. * * @since 2.6.3 * @hook um_role_row_actions * * @param {array} $actions Action links. * @param {string} $id Role key. * * @example <caption>Add custom action to role's row.</caption> * function my_custom_um_role_row_actions( $actions, $id ) { * $actions['{action_key}'] = "<a href="{action_link}">Action Title</a>"; * return $actions; * } * add_action( 'um_role_row_actions', 'my_custom_um_role_row_actions', 10, 2 ); */ $actions = apply_filters( 'um_role_row_actions', $actions, $id ); return sprintf( '%1$s %2$s', '<strong><a class="row-title" href="admin.php?page=um_roles&tab=edit&id=' . esc_attr( $id ) . '">' . stripslashes( $item['name'] ) . '</a></strong>', $this->row_actions( $actions ) ); } /** * @param $item * * @return string */ function column_roleid( $item ) { return ! empty( $item['_um_is_custom'] ) ? 'um_' . $item['key'] : $item['key']; } /** * @param $item */ function column_core( $item ) { echo ! empty( $item['_um_is_custom'] ) ? __( 'Yes', 'ultimate-member' ) : __( 'No', 'ultimate-member' ); } /** * @param $item */ function column_admin_access( $item ) { echo ! empty( $item['_um_can_access_wpadmin'] ) ? __( 'Yes', 'ultimate-member' ) : __( 'No', 'ultimate-member' ); } /** * @param $item */ function column_priority( $item ) { echo ! empty( $item['_um_priority'] ) ? $item['_um_priority'] : '-'; } /** * @param array $attr */ function um_set_pagination_args( $attr = array() ) { $this->set_pagination_args( $attr ); } } $ListTable = new UM_Roles_List_Table( array( 'singular' => __( 'Role', 'ultimate-member' ), 'plural' => __( 'Roles', 'ultimate-member' ), 'ajax' => false )); $per_page = 20; $paged = $ListTable->get_pagenum(); $ListTable->set_bulk_actions( array( 'delete' => __( 'Delete', 'ultimate-member' ) ) ); $ListTable->set_columns( array( 'title' => __( 'Role Title', 'ultimate-member' ), 'roleid' => __( 'Role ID', 'ultimate-member' ), 'users' => __( 'No.of Members', 'ultimate-member' ), 'core' => __( 'UM Custom Role', 'ultimate-member' ), 'admin_access' => __( 'WP-Admin Access', 'ultimate-member' ), 'priority' => __( 'Priority', 'ultimate-member' ), ) ); $ListTable->set_sortable_columns( array( 'title' => 'title' ) ); $users_count = count_users(); $roles = array(); $role_keys = get_option( 'um_roles', array() ); if ( $role_keys ) { foreach ( $role_keys as $role_key ) { $role_meta = get_option( "um_role_{$role_key}_meta" ); if ( $role_meta ) { $roles[ 'um_' . $role_key ] = array( 'key' => $role_key, 'users' => ! empty( $users_count['avail_roles'][ 'um_' . $role_key ] ) ? $users_count['avail_roles'][ 'um_' . $role_key ] : 0 ); $roles[ 'um_' . $role_key ] = array_merge( $roles[ 'um_' . $role_key ], $role_meta ); } } } global $wp_roles; foreach ( $wp_roles->roles as $roleID => $role_data ) { if ( in_array( $roleID, array_keys( $roles ) ) ) { continue; } $roles[ $roleID ] = array( 'key' => $roleID, 'users' => ! empty( $users_count['avail_roles'][ $roleID ] ) ? $users_count['avail_roles'][ $roleID ] : 0, 'name' => $role_data['name'] ); $role_meta = get_option( "um_role_{$roleID}_meta" ); if ( $role_meta ) { $roles[ $roleID ] = array_merge( $roles[ $roleID ], $role_meta ); } } switch( strtolower( $order ) ) { case 'asc': uasort( $roles, function( $a, $b ) { return strnatcmp( $a['name'], $b['name'] ); } ); break; case 'desc': uasort( $roles, function( $a, $b ) { return strnatcmp( $a['name'], $b['name'] ) * -1; } ); break; } $ListTable->prepare_items(); $ListTable->items = array_slice( $roles, ( $paged - 1 ) * $per_page, $per_page ); $ListTable->um_set_pagination_args( array( 'total_items' => count( $roles ), 'per_page' => $per_page ) ); ?> <div class="wrap"> <h2> <?php _e( 'User Roles', 'ultimate-member' ) ?> <a class="add-new-h2" href="<?php echo esc_url( add_query_arg( array( 'page' => 'um_roles', 'tab' => 'add' ), admin_url( 'admin.php' ) ) ) ?>"> <?php _e( 'Add New', 'ultimate-member' ) ?> </a> </h2> <?php if ( ! empty( $_GET['msg'] ) ) { switch ( sanitize_key( $_GET['msg'] ) ) { case 'd': echo '<div id="message" class="updated fade"><p>' . __( 'User Role <strong>Deleted</strong> Successfully.', 'ultimate-member' ) . '</p></div>'; break; } } ?> <form action="" method="get" name="um-roles" id="um-roles" style="float: left;margin-right: 10px;"> <input type="hidden" name="page" value="um_roles" /> <?php $ListTable->display(); ?> </form> </div> includes/admin/core/list-tables/version-template-list-table.php 0000644 00000011633 15252504435 0020673 0 ustar 00 <?php if ( ! defined( 'ABSPATH' ) ) { exit; } /** * Class UM_Versions_List_Table */ class UM_Versions_List_Table extends WP_List_Table { /** * @var string */ public $no_items_message = ''; /** * @var array */ public $columns = array(); /** * UM_Versions_List_Table constructor. * * @param array $args */ public function __construct( $args = array() ) { $args = wp_parse_args( $args, array( 'singular' => __( 'item', 'ultimate-member' ), 'plural' => __( 'items', 'ultimate-member' ), 'ajax' => false, ) ); $this->no_items_message = $args['plural'] . ' ' . __( 'not found.', 'ultimate-member' ); parent::__construct( $args ); } /** * @param callable $name * @param array $arguments * * @return mixed */ public function __call( $name, $arguments ) { return call_user_func_array( array( $this, $name ), $arguments ); } /** * */ public function prepare_items() { $screen = $this->screen; $columns = $this->get_columns(); $sortable = $this->get_sortable_columns(); $this->_column_headers = array( $columns, array(), $sortable ); $templates = UM()->common()->theme()->build_templates_data(); @uasort( $templates, function ( $a, $b ) { if ( strtolower( $a['status_code'] ) === strtolower( $b['status_code'] ) ) { return 0; } return ( strtolower( $a['status_code'] ) < strtolower( $b['status_code'] ) ) ? -1 : 1; } ); $per_page = $this->get_items_per_page( str_replace( '-', '_', $screen->id . '_per_page' ), 999 ); $paged = $this->get_pagenum(); $this->items = array_slice( $templates, ( $paged - 1 ) * $per_page, $per_page ); $this->set_pagination_args( array( 'total_items' => count( $templates ), 'per_page' => $per_page, ) ); } /** * @param object $item * @param string $column_name * * @return string */ public function column_default( $item, $column_name ) { if ( isset( $item[ $column_name ] ) ) { return $item[ $column_name ]; } else { return ''; } } /** * */ public function no_items() { echo $this->no_items_message; } /** * @param array $args * * @return $this */ public function set_columns( $args = array() ) { $this->columns = $args; return $this; } /** * @return array */ public function get_columns() { return $this->columns; } /** * @param $item * * @return string */ public function column_template( $item ) { $output = esc_html__( 'Core path - ', 'ultimate-member' ); $output .= $item['core_file'] . '<br>'; $output .= esc_html__( 'Theme path - ', 'ultimate-member' ); $output .= $item['theme_file']; return $output; } /** * @param $item * * @return string */ public function column_core_version( $item ) { return $item['core_version']; } /** * @param $item * * @return string */ public function column_theme_version( $item ) { return $item['theme_version'] ? $item['theme_version'] : '-'; } /** * @param $item * * @return string */ public function column_status( $item ) { $icon = 1 === $item['status_code'] ? 'um-notification-is-active dashicons-yes' : 'dashicons-no-alt'; return $item['status'] . ' <span class="dashicons um-notification-status ' . esc_attr( $icon ) . '"></span>'; } /** * Generates the table navigation above or below the table * * @since 3.1.0 * @param string $which */ protected function display_tablenav( $which ) { // Stop displaying tablenav. } } $list_table = new UM_Versions_List_Table( array( 'singular' => __( 'Template', 'ultimate-member' ), 'plural' => __( 'Templates', 'ultimate-member' ), 'ajax' => false, ) ); /** * UM hook * * @type filter * @title um_versions_templates_columns * @description Version Templates List Table columns * @input_vars * [{"var":"$columns","type":"array","desc":"Columns"}] * @change_log * ["Since: 2.0"] * @usage add_filter( 'um_versions_templates_columns', 'function_name', 10, 1 ); * @example * <?php * add_filter( 'um_versions_templates_columns', 'um_versions_templates_columns', 10, 1 ); * function um_versions_templates_columns( $columns ) { * // your code here * $columns['my-custom-column'] = 'My Custom Column'; * return $columns; * } * ?> */ $columns = apply_filters( 'um_versions_templates_columns', array( 'template' => __( 'Template', 'ultimate-member' ), 'core_version' => __( 'Core version', 'ultimate-member' ), 'theme_version' => __( 'Theme version', 'ultimate-member' ), 'status' => __( 'Status', 'ultimate-member' ), ) ); $list_table->set_columns( $columns ); $list_table->prepare_items(); ?> <form action="" method="get" name="um-settings-template-versions" id="um-settings-template-versions"> <input type="hidden" name="page" value="um_options" /> <input type="hidden" name="tab" value="advanced" /> <input type="hidden" name="section" value="override_templates" /> <?php $list_table->display(); ?> </form> includes/admin/core/list-tables/emails-list-table.php 0000644 00000017366 15252504435 0016660 0 ustar 00 <?php if ( ! defined( 'ABSPATH' ) ) exit; global $wpdb; if ( isset( $_REQUEST['_wp_http_referer'] ) ) { $redirect = remove_query_arg( array( '_wp_http_referer' ), wp_unslash( $_REQUEST['_wp_http_referer'] ) ); } else { $redirect = get_admin_url(). 'admin.php?page=ultimatemember'; } //remove extra query arg if ( ! empty( $_GET['_wp_http_referer'] ) ) { um_js_redirect( remove_query_arg( array( '_wp_http_referer', '_wpnonce' ), wp_unslash( $_SERVER['REQUEST_URI'] ) ) ); } if ( ! class_exists( 'WP_List_Table' ) ) { require_once ABSPATH . 'wp-admin/includes/class-wp-list-table.php'; } /** * Class UM_Emails_List_Table */ class UM_Emails_List_Table extends WP_List_Table { /** * @var string */ var $no_items_message = ''; /** * @var array */ var $sortable_columns = array(); /** * @var string */ var $default_sorting_field = ''; /** * @var array */ var $actions = array(); /** * @var array */ var $bulk_actions = array(); /** * @var array */ var $columns = array(); /** * UM_Emails_List_Table constructor. * * @param array $args */ function __construct( $args = array() ){ $args = wp_parse_args( $args, array( 'singular' => __( 'item', 'ultimate-member' ), 'plural' => __( 'items', 'ultimate-member' ), 'ajax' => false ) ); $this->no_items_message = $args['plural'] . ' ' . __( 'not found.', 'ultimate-member' ); parent::__construct( $args ); } /** * @param callable $name * @param array $arguments * * @return mixed */ function __call( $name, $arguments ) { return call_user_func_array( array( $this, $name ), $arguments ); } /** * */ function prepare_items() { $columns = $this->get_columns(); $hidden = array(); $sortable = $this->get_sortable_columns(); $this->_column_headers = array( $columns, $hidden, $sortable ); } /** * Generates the table navigation above or below the table * * @since 3.1.0 * @param string $which */ protected function display_tablenav( $which ) { // Stop displaying tablenav. } /** * @param object $item * @param string $column_name * * @return string */ function column_default( $item, $column_name ) { if( isset( $item[ $column_name ] ) ) { return $item[ $column_name ]; } else { return ''; } } /** * */ function no_items() { echo $this->no_items_message; } /** * @param array $args * * @return $this */ function set_sortable_columns( $args = array() ) { $return_args = array(); foreach( $args as $k=>$val ) { if( is_numeric( $k ) ) { $return_args[ $val ] = array( $val, $val == $this->default_sorting_field ); } else if( is_string( $k ) ) { $return_args[ $k ] = array( $val, $k == $this->default_sorting_field ); } else { continue; } } $this->sortable_columns = $return_args; return $this; } /** * @return array */ function get_sortable_columns() { return $this->sortable_columns; } /** * @param array $args * * @return $this */ function set_columns( $args = array() ) { if ( count( $this->bulk_actions ) ) { $args = array_merge( array( 'cb' => '<input type="checkbox" />' ), $args ); } $this->columns = $args; return $this; } /** * @return array */ function get_columns() { return $this->columns; } /** * @param array $args * * @return $this */ function set_actions( $args = array() ) { $this->actions = $args; return $this; } /** * @return array */ function get_actions() { return $this->actions; } /** * @param array $args * * @return $this */ function set_bulk_actions( $args = array() ) { $this->bulk_actions = $args; return $this; } /** * @return array */ function get_bulk_actions() { return $this->bulk_actions; } /** * @param $item * * @return string */ function column_email( $item ) { $active = UM()->options()->get( $item['key'] . '_on' ); $icon = ! empty( $active ) ? 'um-notification-is-active dashicons-yes' : 'dashicons-no-alt'; $icon_title = ! empty( $active ) ? __( 'Enabled', 'ultimate-member' ) : __( 'Disabled', 'ultimate-member' ); $link = add_query_arg( array( 'email' => $item['key'] ), remove_query_arg( 'paged' ) ); $text = '<span class="dashicons um-notification-status ' . esc_attr( $icon ) . '" title="' . esc_attr( $icon_title ) . '"></span><a href="' . esc_url( $link ) . '"><strong>' . esc_html( $item['title'] ) . '</strong></a>'; if ( ! empty( $item['description'] ) ) { $text .= ' <span class="um_tooltip dashicons dashicons-editor-help" title="' . esc_attr( $item['description'] ) . '"></span>'; } return $text; } /** * @param $item * * @return string */ function column_recipients( $item ) { if ( 'admin' === $item['recipient'] ) { return UM()->options()->get( 'admin_email' ); } return __( 'Member', 'ultimate-member' ); } /** * @param $item * * @return string */ function column_configure( $item ) { $edit_link = add_query_arg( array( 'email' => $item['key'] ), remove_query_arg( 'paged' ) ); return '<a class="button um-email-configure" href="' . esc_url( $edit_link ) . '" title="' . esc_attr__( 'Manage', 'ultimate-member' ) . '">' . esc_html__( 'Manage', 'ultimate-member' ) . '</a>'; } /** * @param $item * * @return string */ function column_icl_translations( $item ) { return UM()->external_integrations()->wpml_column_content( $item ); } /** * @param array $attr */ function wpc_set_pagination_args( $attr = array() ) { $this->set_pagination_args( $attr ); } } $ListTable = new UM_Emails_List_Table( array( 'singular' => __( 'Email Notification', 'ultimate-member' ), 'plural' => __( 'Email Notifications', 'ultimate-member' ), 'ajax' => false, )); $per_page = 999; $paged = $ListTable->get_pagenum(); /** * UM hook * * @type filter * @title um_email_templates_columns * @description Email Notifications List Table columns * @input_vars * [{"var":"$columns","type":"array","desc":"Columns"}] * @change_log * ["Since: 2.0"] * @usage add_filter( 'um_email_templates_columns', 'function_name', 10, 1 ); * @example * <?php * add_filter( 'um_email_templates_columns', 'my_email_templates_columns', 10, 1 ); * function my_email_templates_columns( $columns ) { * // your code here * $columns['my-custom-column'] = 'My Custom Column'; * return $columns; * } * ?> */ $columns = apply_filters( 'um_email_templates_columns', array( 'email' => __( 'Email', 'ultimate-member' ), 'recipients' => __( 'Recipient(s)', 'ultimate-member' ), 'configure' => '', ) ); $ListTable->set_columns( $columns ); $emails = UM()->config()->email_notifications; $ListTable->prepare_items(); $ListTable->items = array_slice( $emails, ( $paged - 1 ) * $per_page, $per_page ); $ListTable->wpc_set_pagination_args( array( 'total_items' => count( $emails ), 'per_page' => $per_page ) ); ?> <h2 class="title"><?php esc_html_e( 'Email notifications', 'ultimate-member' ); ?></h2> <p> <?php esc_html_e( 'Email notifications sent from Ultimate Member are listed below. Click on an email to configure it.', 'ultimate-member' ); ?> <br /> <?php esc_html_e( 'Emails should be sent from an email using your website\'s domain name. We highly recommend using a SMTP service email delivery.', 'ultimate-member' ); ?> <?php echo wp_kses( sprintf( __( 'Please see this <a href="%s" target="_blank">doc</a> for more information.', 'ultimate-member' ), 'https://docs.ultimatemember.com/article/116-not-receiving-user-emails-or-admin-notifications' ), UM()->get_allowed_html( 'admin_notice' ) ); ?> </p> <div class="clear"></div> <form action="" method="get" name="um-settings-emails" id="um-settings-emails"> <input type="hidden" name="page" value="um_options" /> <input type="hidden" name="tab" value="email" /> <?php $ListTable->display(); ?> </form> <div class="clear"></div> includes/admin/core/class-admin-navmenu.php 0000644 00000022307 15252504435 0014756 0 ustar 00 <?php namespace um\admin\core; if ( ! defined( 'ABSPATH' ) ) { exit; } if ( ! class_exists( 'um\admin\core\Admin_Navmenu' ) ) { /** * Class Admin_Navmenu * @package um\admin\core */ class Admin_Navmenu { /** * @var array */ protected static $fields = array(); /** * Admin_Navmenu constructor. */ public function __construct() { add_action( 'init', array( &$this, 'set_variables' ) ); add_action( 'customize_controls_print_footer_scripts', array( &$this, '_wp_template' ) ); add_action( 'wp_update_nav_menu_item', array( &$this, '_save' ), 10, 3 ); add_action( 'wp_nav_menu_item_custom_fields', array( $this, 'wp_nav_menu_item_custom_fields' ), 20, 5 ); // @todo Appearance > Customize > Menus section without UM settings // add_action( 'wp_nav_menu_item_custom_fields_customize_template', array( $this, 'wp_nav_menu_item_custom_fields_customize_template' ), 20, 5 ); } public function set_variables() { self::$fields = array( 'um_nav_public' => __( 'Display Mode', 'ultimate-member' ), 'um_nav_roles' => __( 'By Role', 'ultimate-member' ), ); } /** * Fires just before the move buttons of a nav menu item in the menu editor. * Adds block "Ultimate Member Menu Settings" * * @param int $item_id Menu item ID. * @param \WP_Post $item Menu item data object. * @param int $depth Depth of menu item. Used for padding. * @param \stdClass $args An object of menu item arguments. * @param int $id Nav menu ID. */ public function wp_nav_menu_item_custom_fields( $item_id, $item, $depth, $args, $id = null ) { $um_nav_public = get_post_meta( $item->ID, 'menu-item-um_nav_public', true ); $_nav_roles_meta = get_post_meta( $item->ID, 'menu-item-um_nav_roles', true ); $um_nav_roles = array(); if ( $_nav_roles_meta ) { foreach ( $_nav_roles_meta as $key => $value ) { if ( is_int( $key ) ) { $um_nav_roles[] = $value; } } } $options = UM()->roles()->get_roles( false ); ?> <div class="um-nav-edit"> <div class="clear"></div> <h4 style="margin-bottom: 0.6em;"><?php esc_html_e( 'Ultimate Member Menu Settings', 'ultimate-member' ); ?></h4> <p class="description description-wide um-nav-mode"> <label for="edit-menu-item-um_nav_public-<?php echo esc_attr( $item_id ); ?>"> <?php esc_html_e( 'Who can see this menu link?', 'ultimate-member' ); ?><br/> <select id="edit-menu-item-um_nav_public-<?php echo esc_attr( $item_id ); ?>" name="menu-item-um_nav_public[<?php echo esc_attr( $item_id ); ?>]" style="width:100%;"> <option value="0" <?php selected( $um_nav_public, 0 ); ?>><?php esc_html_e( 'Everyone', 'ultimate-member' ); ?></option> <option value="1" <?php selected( $um_nav_public, 1 ); ?>><?php esc_html_e( 'Logged Out Users', 'ultimate-member' ); ?></option> <option value="2" <?php selected( $um_nav_public, 2 ); ?>><?php esc_html_e( 'Logged In Users', 'ultimate-member' ); ?></option> </select> </label> </p> <p class="description description-wide um-nav-roles" <?php echo 2 === absint( $um_nav_public ) ? 'style="display: block;"' : ''; ?>><?php esc_html_e( 'Select the member roles that can see this link', 'ultimate-member' ); ?><br> <?php $i = 0; $html = ''; $columns = apply_filters( 'wp_nav_menu_item:um_nav_columns', 2, $item_id, $item ); $per_page = ceil( count( $options ) / $columns ); while ( $i < $columns ) { $section_fields_per_page = array_slice( $options, $i * $per_page, $per_page ); $html .= '<span class="um-form-fields-section" style="width:' . floor( 100 / $columns ) . '% !important;">'; foreach ( $section_fields_per_page as $k => $title ) { $id_attr = ' id="edit-menu-item-um_nav_roles-' . $item_id . '_' . $k . '" '; $for_attr = ' for="edit-menu-item-um_nav_roles-' . $item_id . '_' . $k . '" '; $checked_attr = checked( in_array( $k, $um_nav_roles, true ), true, false ); $html .= "<label {$for_attr}> <input type='checkbox' {$id_attr} name='menu-item-um_nav_roles[{$item_id}][{$k}]' value='1' {$checked_attr} /> <span>{$title}</span> </label>"; } $html .= '</span>'; $i++; } echo $html; ?> </p> <?php do_action( 'um_wp_nav_menu_custom_fields', $item_id, $um_nav_public ); ?> <div class="clear"></div> </div> <?php } /** * @todo Appearance > Customize > Menus section without UM settings * @return void */ public function wp_nav_menu_item_custom_fields_customize_template() { ?> <div class="clear"></div> <h4 style="margin-bottom: 0.6em;"><?php esc_html_e( 'Ultimate Member Menu Settings', 'ultimate-member' ); ?></h4> <p class="description description-wide um-nav-mode"> <label for="edit-menu-item-um_nav_public-{{ data.menu_item_id }}"> <?php esc_html_e( 'Who can see this menu link?', 'ultimate-member' ); ?><br/> <select id="edit-menu-item-um_nav_public-{{ data.menu_item_id }}" name="menu-item-um_nav_public[{{ data.menu_item_id }}]" style="width:100%;"> <option value="0"><?php esc_html_e( 'Everyone', 'ultimate-member' ); ?></option> <option value="1"><?php esc_html_e( 'Logged Out Users', 'ultimate-member' ); ?></option> <option value="2"><?php esc_html_e( 'Logged In Users', 'ultimate-member' ); ?></option> </select> </label> </p> <?php } /** * * Backward compatibility with WP < 5.4 * */ /** * @param int $menu_id * @param int $menu_item_db_id * @param array $menu_item_args */ public function _save( $menu_id, $menu_item_db_id, $menu_item_args ) { // phpcs:disable WordPress.Security.NonceVerification if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) { return; } if ( empty( $_POST['menu-item-db-id'] ) || ! in_array( $menu_item_db_id, $_POST['menu-item-db-id'] ) ) { return; } self::$fields = apply_filters( 'um_wp_nav_menu_fields', self::$fields ); foreach ( self::$fields as $_key => $label ) { $key = sprintf( 'menu-item-%s', $_key ); // Sanitize if ( ! empty( $_POST[ $key ][ $menu_item_db_id ] ) ) { // Do some checks here... if ( is_array( $_POST[ $key ][ $menu_item_db_id ] ) ) { $value = array_map( 'sanitize_key', array_keys( $_POST[ $key ][ $menu_item_db_id ] ) ); } else { $value = (int) $_POST[ $key ][ $menu_item_db_id ]; } } else { $value = null; } // phpcs:enable WordPress.Security.NonceVerification // Update if ( ! is_null( $value ) ) { update_post_meta( $menu_item_db_id, $key, $value ); } else { delete_post_meta( $menu_item_db_id, $key ); } } } /** * @todo Deprecate */ function _wp_template() { ?> <script type="text/html" id="tmpl-um-nav-menus-fields"> <div class="um-nav-edit"> <div class="clear"></div> <h4 style="margin-bottom: 0.6em;"><?php _e( "Ultimate Member Menu Settings", 'ultimate-member' ) ?></h4> <p class="description description-wide um-nav-mode"> <label for="edit-menu-item-um_nav_public-{{data.menuItemID}}"> <?php _e( "Who can see this menu link?", 'ultimate-member' ); ?><br/> <select id="edit-menu-item-um_nav_public-{{data.menuItemID}}" name="menu-item-um_nav_public[{{data.menuItemID}}]" style="width:100%;"> <option value="0" <# if( data.restriction_data.um_nav_public == '0' ){ #>selected="selected"<# } #>> <?php _e( 'Everyone', 'ultimate-member' ) ?> </option> <option value="1" <# if( data.restriction_data.um_nav_public == '1' ){ #>selected="selected"<# } #>> <?php _e( 'Logged Out Users', 'ultimate-member' ) ?> </option> <option value="2" <# if( data.restriction_data.um_nav_public == '2' ){ #>selected="selected"<# } #>> <?php _e( 'Logged In Users', 'ultimate-member' ) ?> </option> </select> </label> </p> <p class="description description-wide um-nav-roles" <# if( data.restriction_data.um_nav_public == '2' ){ #>style="display: block;"<# } #>> <?php _e( "Select the member roles that can see this link", 'ultimate-member' ) ?><br/> <?php $options = UM()->roles()->get_roles( false ); $i = 0; $html = ''; $columns = 2; while ( $i < $columns ) { $per_page = ceil( count( $options ) / $columns ); $section_fields_per_page = array_slice( $options, $i * $per_page, $per_page ); $html .= '<span class="um-form-fields-section" style="width:' . floor( 100 / $columns ) . '% !important;">'; foreach ( $section_fields_per_page as $k => $title ) { $id_attr = ' id="edit-menu-item-um_nav_roles-{{data.menuItemID}}_' . $k . '" '; $for_attr = ' for="edit-menu-item-um_nav_roles-{{data.menuItemID}}_' . $k . '" '; $html .= "<label $for_attr> <input type='checkbox' {$id_attr} name='menu-item-um_nav_roles[{{data.menuItemID}}][{$k}]' value='1' <# if( _.contains( data.restriction_data.um_nav_roles,'{$k}' ) ){ #>checked='checked'<# } #> /> <span>{$title}</span> </label>"; } $html .= '</span>'; $i++; } echo $html; ?> </p> <div class="clear"></div> </div> </script> <?php } } } includes/admin/core/class-admin-menu.php 0000644 00000026707 15252504435 0014261 0 ustar 00 <?php namespace um\admin\core; use \RecursiveDirectoryIterator; if ( ! defined( 'ABSPATH' ) ) { exit; } if ( ! class_exists( 'um\admin\core\Admin_Menu' ) ) { /** * Class Admin_Menu * @package um\admin\core */ class Admin_Menu { /** * @var string */ var $pagehook; var $slug = 'ultimatemember'; /** * Admin_Menu constructor. */ public function __construct() { add_action( 'admin_menu', array( &$this, 'primary_admin_menu' ), 0 ); add_action( 'admin_menu', array( &$this, 'secondary_menu_items' ), 1000 ); add_action( 'admin_menu', array( &$this, 'extension_menu' ), 9999 ); add_action( 'admin_head', array( $this, 'menu_order_count' ) ); add_filter( 'admin_footer_text', array( $this, 'admin_footer_text' ), 1000 ); add_action( 'load-ultimate-member_page_um_options', array( &$this, 'maybe_settings_redirect' ) ); } /** * Trigger redirect on the Settings screen if there is a wrong tab or section. * * @since 2.8.2 */ public function maybe_settings_redirect() { $current_tab = empty( $_GET['tab'] ) ? '' : sanitize_key( $_GET['tab'] ); $current_subtab = empty( $_GET['section'] ) ? '' : sanitize_key( $_GET['section'] ); $settings_struct = UM()->admin_settings()->settings_structure[ $current_tab ]; // Remove not option hidden fields. if ( ! empty( $settings_struct['fields'] ) ) { foreach ( $settings_struct['fields'] as $field_key => $field_options ) { if ( isset( $field_options['is_option'] ) && false === $field_options['is_option'] ) { unset( $settings_struct['fields'][ $field_key ] ); } } } if ( empty( $settings_struct['fields'] ) && empty( $settings_struct['sections'] ) && empty( $settings_struct['form_sections'] ) ) { wp_safe_redirect( add_query_arg( array( 'page' => 'um_options' ), admin_url( 'admin.php' ) ) ); exit; } if ( ! empty( $settings_struct['sections'] ) ) { if ( empty( $settings_struct['sections'][ $current_subtab ] ) ) { $args = array( 'page' => 'um_options' ); if ( ! empty( $current_tab ) ) { $args['tab'] = $current_tab; } wp_safe_redirect( add_query_arg( $args, admin_url( 'admin.php' ) ) ); exit; } } } /** * Change the admin footer text on UM admin pages * * @param $footer_text * * @return string */ public function admin_footer_text( $footer_text ) { $current_screen = get_current_screen(); // Add the dashboard pages $um_pages[] = 'toplevel_page_ultimatemember'; $um_pages[] = 'ultimate-member_page_um_options'; $um_pages[] = 'edit-um_form'; $um_pages[] = 'edit-um_role'; $um_pages[] = 'edit-um_directory'; $um_pages[] = 'ultimate-member_page_ultimatemember-extensions'; if ( isset( $current_screen->id ) && in_array( $current_screen->id, $um_pages ) ) { // Change the footer text if ( ! get_option( 'um_admin_footer_text_rated' ) ) { ob_start(); ?> <a href="https://wordpress.org/support/plugin/ultimate-member/reviews/?filter=5" target="_blank" class="um-admin-rating-link" data-rated="<?php esc_attr_e( 'Thanks :)', 'ultimate-member' ) ?>"> ★★★★★ </a> <?php $link = ob_get_clean(); ob_start(); // translators: %s: Review link. echo wp_kses( sprintf( __( 'If you like Ultimate Member please consider leaving a %s review. It will help us to grow the plugin and make it more popular. Thank you.', 'ultimate-member' ), $link ), UM()->get_allowed_html( 'admin_notice' ) ); ?> <script type="text/javascript"> jQuery( document.body ).on('click', 'a.um-admin-rating-link', function() { jQuery.ajax({ url: wp.ajax.settings.url, type: 'post', data: { action: 'um_rated', nonce: um_admin_scripts.nonce }, success: function() { } }); jQuery(this).parent().text( jQuery( this ).data( 'rated' ) ); }); </script> <?php $footer_text = ob_get_clean(); } } return $footer_text; } /** * When user clicks the review link in backend */ function ultimatemember_rated() { UM()->admin()->check_ajax_nonce(); if ( ! is_user_logged_in() || ! current_user_can( 'manage_options' ) ) { wp_send_json_error( __( 'Please login as administrator', 'ultimate-member' ) ); } update_option( 'um_admin_footer_text_rated', 1 ); wp_send_json_success(); } /** * Manage order of admin menu items */ public function menu_order_count() { global $menu, $submenu; if ( ! current_user_can( 'list_users' ) ) { return; } $count = UM()->query()->get_pending_users_count(); if ( is_array( $menu ) ) { foreach ( $menu as $key => $menu_item ) { if ( 0 === strpos( $menu_item[0], _x( 'Users', 'Admin menu name' ) ) ) { $menu[ $key ][0] .= ' <span class="update-plugins count-' . $count . '"><span class="processing-count">' . $count . '</span></span>'; } } } if ( is_array( $submenu ) && isset( $submenu['users.php'] ) ) { foreach ( $submenu['users.php'] as $key => $menu_item ) { if ( 0 === strpos( $menu_item[0], _x( 'All Users', 'Admin menu name' ) ) ) { $submenu['users.php'][ $key ][0] .= ' <span class="update-plugins count-' .$count . '"><span class="processing-count">' . $count . '</span></span>'; } } } } /** * Setup admin menu */ public function primary_admin_menu() { $this->pagehook = add_menu_page( __( 'Ultimate Member', 'ultimate-member' ), __( 'Ultimate Member', 'ultimate-member' ), 'manage_options', $this->slug, array( &$this, 'admin_page' ), 'dashicons-admin-users', '42.78578' ); add_action( 'load-' . $this->pagehook, array( &$this, 'on_load_page' ) ); add_submenu_page( $this->slug, __( 'Dashboard', 'ultimate-member' ), __( 'Dashboard', 'ultimate-member' ), 'manage_options', $this->slug, array( &$this, 'admin_page' ) ); } /** * Secondary admin menu (after settings) */ public function secondary_menu_items() { add_submenu_page( $this->slug, __( 'Settings', 'ultimate-member' ), __( 'Settings', 'ultimate-member' ), 'manage_options', 'um_options', array( UM()->admin_settings(), 'settings_page' ) ); add_submenu_page( $this->slug, __( 'Forms', 'ultimate-member' ), __( 'Forms', 'ultimate-member' ), 'manage_options', 'edit.php?post_type=um_form', '' ); add_submenu_page( $this->slug, __( 'User Roles', 'ultimate-member' ), __( 'User Roles', 'ultimate-member' ), 'manage_options', 'um_roles', array( &$this, 'um_roles_pages' ) ); if ( UM()->options()->get( 'members_page' ) ) { add_submenu_page( $this->slug, __( 'Member Directories', 'ultimate-member' ), __( 'Member Directories', 'ultimate-member' ), 'manage_options', 'edit.php?post_type=um_directory', '' ); } /** * UM hook * * @type action * @title um_extend_admin_menu * @description Extend UM menu * @change_log * ["Since: 2.0"] * @usage add_action( 'um_extend_admin_menu', 'function_name', 10 ); * @example * <?php * add_action( 'um_extend_admin_menu', 'my_extend_admin_menu', 10 ); * function my_extend_admin_menu() { * // your code here * } * ?> */ do_action( 'um_extend_admin_menu' ); } /** * Role page menu callback */ function um_roles_pages() { if ( empty( $_GET['tab'] ) ) { include_once UM_PATH . 'includes/admin/core/list-tables/roles-list-table.php'; } elseif ( 'add' === sanitize_key( $_GET['tab'] ) || 'edit' === sanitize_key( $_GET['tab'] ) ) { include_once UM_PATH . 'includes/admin/templates/role/role-edit.php'; } else { um_js_redirect( add_query_arg( array( 'page' => 'um_roles' ), get_admin_url( 'admin.php' ) ) ); } } /** * Extension menu */ function extension_menu() { add_submenu_page( $this->slug, __( 'Extensions', 'ultimate-member' ), '<span style="color: #00B9EB">' .__( 'Extensions', 'ultimate-member' ) . '</span>', 'manage_options', $this->slug . '-extensions', array( &$this, 'admin_page' ) ); } /** * Load metabox stuff */ function on_load_page() { wp_enqueue_script( 'common' ); wp_enqueue_script( 'wp-lists' ); wp_enqueue_script( 'postbox' ); /** custom metaboxes for dashboard defined here **/ add_meta_box( 'um-metaboxes-contentbox-1', __( 'Users Overview', 'ultimate-member' ), array( &$this, 'users_overview' ), $this->pagehook, 'core', 'core' ); add_meta_box( 'um-metaboxes-sidebox-1', __( 'Purge Temp Files', 'ultimate-member' ), array( &$this, 'purge_temp' ), $this->pagehook, 'side', 'core' ); add_meta_box( 'um-metaboxes-sidebox-2', __( 'User Cache', 'ultimate-member' ), array( &$this, 'user_cache' ), $this->pagehook, 'side', 'core' ); //If there are active and licensed extensions - show metabox for upgrade it $exts = UM()->plugin_updater()->get_active_plugins(); if ( 0 < count( $exts ) ) { add_meta_box( 'um-metaboxes-sidebox-3', __( 'Upgrade\'s Manual Request', 'ultimate-member' ), array( &$this, 'upgrade_request' ), $this->pagehook, 'side', 'core' ); } } /** * */ function users_overview() { include_once UM()->admin()->templates_path . 'dashboard/users.php'; } /** * */ function purge_temp() { include_once UM()->admin()->templates_path . 'dashboard/purge.php'; } /** * */ function upgrade_request() { include_once UM()->admin()->templates_path . 'dashboard/upgrade-request.php'; } /** * */ function user_cache() { include_once UM()->admin()->templates_path . 'dashboard/cache.php'; } /** * Get a directory size * * @param $directory * * @return float|int */ function dir_size( $directory ) { if ( $directory == 'temp' ) { $directory = UM()->files()->upload_temp; $size = 0; foreach( new \RecursiveIteratorIterator( new \RecursiveDirectoryIterator( $directory ) ) as $file ) { $filename = $file->getFilename(); if ( $filename == '.' || $filename == '..' ) { continue; } $size += $file->getSize(); } return round ( $size / 1048576, 2); } return 0; } /** * Which admin page to show? */ function admin_page() { $page = ! empty( $_REQUEST['page'] ) ? sanitize_key( $_REQUEST['page'] ) : ''; if ( $page == 'ultimatemember' ) { ?> <div id="um-metaboxes-general" class="wrap"> <h1>Ultimate Member <sup><?php echo UM_VERSION; ?></sup></h1> <?php wp_nonce_field( 'um-metaboxes-general' ); ?> <?php wp_nonce_field( 'closedpostboxes', 'closedpostboxesnonce', false ); ?> <?php wp_nonce_field( 'meta-box-order', 'meta-box-order-nonce', false ); ?> <input type="hidden" name="action" value="save_um_metaboxes_general" /> <div id="dashboard-widgets-wrap"> <div id="dashboard-widgets" class="metabox-holder um-metabox-holder"> <div id="postbox-container-1" class="postbox-container"><?php do_meta_boxes( $this->pagehook, 'core', null ); ?></div> <div id="postbox-container-2" class="postbox-container"><?php do_meta_boxes( $this->pagehook, 'normal', null ); ?></div> <div id="postbox-container-3" class="postbox-container"><?php do_meta_boxes( $this->pagehook, 'side', null ); ?></div> </div> </div> </div> <div class="clear"></div> <script type="text/javascript"> //<![CDATA[ jQuery(document).ready( function($) { // postboxes setup postboxes.add_postbox_toggles('<?php echo esc_js( $this->pagehook ); ?>'); }); //]]> </script> <?php } elseif ( $page == 'ultimatemember-extensions' ) { include_once UM()->admin()->templates_path . 'extensions.php'; } } } } includes/admin/core/class-admin-notices.php 0000644 00000103644 15252504435 0014755 0 ustar 00 <?php namespace um\admin\core; use um\common\actions\Users; if ( ! defined( 'ABSPATH' ) ) { exit; } if ( ! class_exists( 'um\admin\core\Admin_Notices' ) ) { /** * Class Admin_Notices * @package um\admin\core */ class Admin_Notices { /** * Notices list * * @var array */ private $list = array(); /** * Admin_Notices constructor. */ public function __construct() { add_action( 'admin_init', array( &$this, 'create_languages_folder' ) ); add_action( 'admin_init', array( &$this, 'create_list' ) ); add_action( 'admin_notices', array( &$this, 'render_notices' ), 1 ); add_action( 'wp_ajax_um_dismiss_notice', array( &$this, 'dismiss_notice' ) ); add_action( 'admin_init', array( &$this, 'force_dismiss_notice' ) ); } /** * */ public function create_list() { $this->old_extensions_notice(); $this->install_core_page_notice(); $this->exif_extension_notice(); $this->show_update_messages(); $this->check_wrong_install_folder(); $this->need_upgrade(); $this->check_wrong_licenses(); $this->lock_registration(); $this->empty_status_users(); $this->extensions_page(); $this->child_theme_required(); // Removed for now to avoid the bad reviews. //$this->reviews_notice(); //$this->future_changed(); $this->common_secure(); /** * UM hook * * @type action * @title um_admin_create_notices * @description Add notices to wp-admin * @change_log * ["Since: 2.0"] * @usage add_action( 'um_admin_create_notices', 'function_name', 10 ); * @example * <?php * add_action( 'um_admin_create_notices', 'my_admin_create_notices', 10 ); * function my_admin_create_notices() { * // your code here * } * ?> */ do_action( 'um_admin_create_notices' ); } /** * @return array */ public function get_admin_notices() { return $this->list; } /** * @param $admin_notices */ function set_admin_notices( $admin_notices ) { $this->list = $admin_notices; } /** * @param $a * @param $b * * @return mixed */ function notice_priority_sort( $a, $b ) { if ( $a['priority'] == $b['priority'] ) { return 0; } return ( $a['priority'] < $b['priority'] ) ? -1 : 1; } /** * Add notice to UM notices array * * @param string $key * @param array $data * @param int $priority */ function add_notice( $key, $data, $priority = 10 ) { $admin_notices = $this->get_admin_notices(); if ( empty( $admin_notices[ $key ] ) ) { $admin_notices[ $key ] = array_merge( $data, array( 'priority' => $priority ) ); $this->set_admin_notices( $admin_notices ); } } /** * Remove notice from UM notices array * * @param string $key */ function remove_notice( $key ) { $admin_notices = $this->get_admin_notices(); if ( ! empty( $admin_notices[ $key ] ) ) { unset( $admin_notices[ $key ] ); $this->set_admin_notices( $admin_notices ); } } /** * Render all admin notices */ function render_notices() { if ( ! current_user_can( 'manage_options' ) ) { return; } $admin_notices = $this->get_admin_notices(); $hidden = get_option( 'um_hidden_admin_notices', array() ); uasort( $admin_notices, array( &$this, 'notice_priority_sort' ) ); foreach ( $admin_notices as $key => $admin_notice ) { if ( empty( $hidden ) || ! in_array( $key, $hidden ) ) { $this->display_notice( $key ); } } /** * UM hook * * @type action * @title um_admin_after_main_notices * @description Insert some content after main admin notices * @change_log * ["Since: 2.0"] * @usage add_action( 'um_admin_after_main_notices', 'function_name', 10 ); * @example * <?php * add_action( 'um_admin_after_main_notices', 'my_admin_after_main_notices', 10 ); * function my_admin_after_main_notices() { * // your code here * } * ?> */ do_action( 'um_admin_after_main_notices' ); } /** * Display single admin notice * * @param string $key * @param bool $echo * * @return void|string */ function display_notice( $key, $echo = true ) { $admin_notices = $this->get_admin_notices(); if ( empty( $admin_notices[ $key ] ) ) { return; } $notice_data = $admin_notices[ $key ]; $class = ! empty( $notice_data['class'] ) ? $notice_data['class'] : 'updated'; $dismissible = ! empty( $admin_notices[ $key ]['dismissible'] ); ob_start(); ?> <div class="<?php echo esc_attr( $class ); ?> um-admin-notice notice <?php echo $dismissible ? 'is-dismissible' : ''; ?>" data-key="<?php echo esc_attr( $key ); ?>"> <?php echo ! empty( $notice_data['message'] ) ? $notice_data['message'] : ''; ?> </div> <?php $notice = ob_get_clean(); if ( $echo ) { echo $notice; return; } return $notice; } /** * Checking if the "Membership - Anyone can register" WordPress general setting is active */ public function lock_registration() { $users_can_register = get_option( 'users_can_register' ); if ( ! $users_can_register ) { return; } $allowed_html = array( 'a' => array( 'href' => array(), ), 'strong' => array(), ); $this->add_notice( 'lock_registration', array( 'class' => 'info', // translators: %s: Setting link. 'message' => '<p>' . wp_kses( sprintf( __( 'The <strong>"Membership - Anyone can register"</strong> option on the general settings <a href="%s">page</a> is enabled. This means users can register via the standard WordPress wp-login.php page. If you do not want users to be able to register via this page and only register via the Ultimate Member registration form, you should deactivate this option. You can dismiss this notice if you wish to keep the wp-login.php registration page open.', 'ultimate-member' ), admin_url( 'options-general.php' ) . '#users_can_register' ), $allowed_html ) . '</p>', 'dismissible' => true, ), 10 ); } /** * Checking if the "Membership - Anyone can register" WordPress general setting is active */ public function empty_status_users() { $empty_status_users = get_option( '_um_log_empty_status_users', array( 0, 0 ) ); if ( ! is_array( $empty_status_users ) ) { $empty_status_users = array( 0, 0 ); } if ( array( 0, 0 ) === $empty_status_users ) { return; } // Alternative method of checking and maybe schedule a batch action if it has not been scheduled previously. // Avoid case when the option with the empty user statuses isn't empty. // We need to recalculate option value and re-schedule the Batch action. if ( ! UM()->maybe_action_scheduler()->has_scheduled_action( Users::BATCH_ACTION ) ) { do_action( Users::SCHEDULE_ACTION ); } $allowed_html = array( 'a' => array( 'href' => array(), ), 'strong' => array(), ); $this->add_notice( 'empty_status_users', array( 'class' => 'info', // translators: %1$d: Background update for users is complete; %2$d: Total users for background update. 'message' => '<p>' . wp_kses( sprintf( __( 'Background process is running: Setting user statuses %1$d/%2$d.', 'ultimate-member' ), $empty_status_users[0], $empty_status_users[1] ), $allowed_html ) . '</p>', 'dismissible' => false, ) ); } /** * Checking if the "Membership - Anyone can register" WordPress general setting is active */ public function extensions_page() { global $pagenow; if ( isset( $pagenow ) && 'admin.php' === $pagenow && isset( $_GET['page'] ) && 'ultimatemember-extensions' === $_GET['page'] ) { ob_start(); ?> <p> <?php _e( '<strong>All Access Pass</strong> – Get access to all Ultimate Member extensions at a significant discount with our All Access Pass.', 'ultimate-member' ); ?> </p> <p> <a href="https://ultimatemember.com/pricing/" class="button button-primary" target="_blank"> <?php esc_html_e( 'View Pricing', 'ultimate-member' ); ?> </a> </p> <?php $message = ob_get_clean(); $this->add_notice( 'extensions_all_access', array( 'class' => 'info', 'message' => $message, 'dismissible' => false, ), 10 ); } } /** * To store plugin languages */ function create_languages_folder() { $path = UM()->files()->upload_basedir; $path = str_replace( '/uploads/ultimatemember', '', $path ); $path = $path . '/languages/plugins/'; $path = str_replace( '//', '/', $path ); if ( ! file_exists( $path ) ) { $old = umask( 0 ); @mkdir( $path, 0777, true ); umask( $old ); } } /** * Show notice for customers with old extension's versions */ function old_extensions_notice() { $show = false; $old_extensions = array( 'bbpress', 'followers', 'friends', 'instagram', 'mailchimp', 'messaging', 'mycred', 'notices', 'notifications', 'online', 'private-content', 'profile-completeness', 'recaptcha', 'reviews', 'social-activity', 'social-login', 'terms-conditions', 'user-tags', 'verified-users', 'woocommerce', ); $slugs = array_map( function ( $item ) { return 'um-' . $item . '/um-' . $item . '.php'; }, $old_extensions ); $active_plugins = UM()->dependencies()->get_active_plugins(); foreach ( $slugs as $slug ) { if ( in_array( $slug, $active_plugins ) ) { $path = wp_normalize_path( WP_PLUGIN_DIR . DIRECTORY_SEPARATOR . $slug ); if ( ! file_exists( $path ) ) { continue; } $plugin_data = get_plugin_data( $path ); if ( version_compare( '2.0', $plugin_data['Version'], '>' ) ) { $show = true; break; } } } if ( ! $show ) { return; } $this->add_notice( 'old_extensions', array( 'class' => 'error', // translators: %1$s is a plugin name; %2$s is a plugin version; %3$s is a plugin name; %4$s is a doc link. 'message' => '<p>' . sprintf( __( '<strong>%1$s %2$s</strong> requires 2.0 extensions. You have pre 2.0 extensions installed on your site. <br /> Please update %3$s extensions to latest versions. For more info see this <a href="%4$s" target="_blank">doc</a>.', 'ultimate-member' ), UM_PLUGIN_NAME, UM_VERSION, UM_PLUGIN_NAME, 'https://docs.ultimatemember.com/article/201-how-to-update-your-site' ) . '</p>', ), 0 ); } /** * Regarding page setup */ function install_core_page_notice() { $pages = UM()->config()->permalinks; if ( $pages && is_array( $pages ) ) { foreach ( $pages as $slug => $page_id ) { $page = get_post( $page_id ); if ( ! isset( $page->ID ) && array_key_exists( $slug, UM()->config()->core_pages ) ) { $url = add_query_arg( array( 'um_adm_action' => 'install_core_pages', '_wpnonce' => wp_create_nonce( 'install_core_pages' ), ) ); ob_start(); ?> <p> <?php // translators: %s: Plugin name. echo wp_kses( sprintf( __( '%s needs to create several pages (User Profiles, Account, Registration, Login, Password Reset, Logout, Member Directory) to function correctly.', 'ultimate-member' ), UM_PLUGIN_NAME ), UM()->get_allowed_html( 'admin_notice' ) ); ?> </p> <p> <a href="<?php echo esc_url( $url ); ?>" class="button button-primary"><?php esc_html_e( 'Create Pages', 'ultimate-member' ); ?></a> <a href="javascript:void(0);" class="button-secondary um_secondary_dismiss"><?php esc_html_e( 'No thanks', 'ultimate-member' ); ?></a> </p> <?php $message = ob_get_clean(); $this->add_notice( 'wrong_pages', array( 'class' => 'updated', 'message' => $message, 'dismissible' => true, ), 20 ); break; } } if ( isset( $pages['user'] ) ) { $test = get_post( $pages['user'] ); if ( isset( $test->post_parent ) && $test->post_parent > 0 ) { $this->add_notice( 'wrong_user_page', array( 'class' => 'updated', 'message' => '<p>' . esc_html__( 'Ultimate Member Setup Error: User page can not be a child page.', 'ultimate-member' ) . '</p>', ), 25 ); } } if ( isset( $pages['account'] ) ) { $test = get_post( $pages['account'] ); if ( isset( $test->post_parent ) && $test->post_parent > 0 ) { $this->add_notice( 'wrong_account_page', array( 'class' => 'updated', 'message' => '<p>' . esc_html__( 'Ultimate Member Setup Error: Account page can not be a child page.', 'ultimate-member' ) . '</p>', ), 30 ); } } } } /** * EXIF library notice */ public function exif_extension_notice() { if ( ! extension_loaded( 'exif' ) ) { $this->add_notice( 'exif_disabled', array( 'class' => 'updated', // translators: %s: query args. 'message' => '<p>' . esc_html__( 'Exif is not enabled on your server. Mobile photo uploads will not be rotated correctly until you enable the exif extension.', 'ultimate-member' ) . '</p>', 'dismissible' => true, ) ); } } /** * Updating users */ public function show_update_messages() { if ( ! isset( $_REQUEST['update'] ) ) { return; } $update = sanitize_key( $_REQUEST['update'] ); switch ( $update ) { case 'um_purged_temp': $messages[0]['content'] = __( 'Your temp uploads directory is now clean.', 'ultimate-member' ); break; case 'um_cleared_cache': $messages[0]['content'] = __( 'Your user cache is now removed.', 'ultimate-member' ); break; case 'um_cleared_status_cache': $messages[0]['content'] = __( 'Your user statuses cache is now removed.', 'ultimate-member' ); break; case 'um_got_updates': $messages[0]['content'] = __( 'You have the latest updates.', 'ultimate-member' ); break; case 'um_often_updates': $messages[0]['err_content'] = __( 'Try again later. You can run this action once daily.', 'ultimate-member' ); break; case 'um_form_duplicated': $messages[0]['content'] = __( 'The form has been duplicated successfully.', 'ultimate-member' ); break; case 'um_settings_updated': $messages[0]['content'] = __( 'Settings have been saved successfully.', 'ultimate-member' ); break; case 'um_users_updated': $messages[0]['content'] = __( 'Users have been updated.', 'ultimate-member' ); break; case 'um_secure_expire_sessions': $messages[0]['content'] = __( 'All users sessions have been successfully destroyed.', 'ultimate-member' ); break; case 'um_secure_restore': $messages[0]['content'] = __( 'Account has been successfully restored.', 'ultimate-member' ); break; case 'um_approved': $approved_count = isset( $_REQUEST['approved_count'] ) ? absint( $_REQUEST['approved_count'] ) : 0; $messages[0]['content'] = sprintf( _n( '<strong>%s</strong> user has been approved.', '<strong>%s</strong> users have been approved.', $approved_count, 'ultimate-member' ), $approved_count ); break; case 'um_reactivated': $reactivated_count = isset( $_REQUEST['reactivated_count'] ) ? absint( $_REQUEST['reactivated_count'] ) : 0; $messages[0]['content'] = sprintf( _n( '<strong>%s</strong> user has been reactivated.', '<strong>%s</strong> users have been reactivated.', $reactivated_count, 'ultimate-member' ), $reactivated_count ); break; case 'um_rejected': $rejected_count = isset( $_REQUEST['rejected_count'] ) ? absint( $_REQUEST['rejected_count'] ) : 0; $messages[0]['content'] = sprintf( _n( '<strong>%s</strong> user has been rejected.', '<strong>%s</strong> users have been rejected.', $rejected_count, 'ultimate-member' ), $rejected_count ); break; case 'um_deactivate': $deactivated_count = isset( $_REQUEST['deactivated_count'] ) ? absint( $_REQUEST['deactivated_count'] ) : 0; $messages[0]['content'] = sprintf( _n( '<strong>%s</strong> user has been deactivated.', '<strong>%s</strong> users have been deactivated.', $deactivated_count, 'ultimate-member' ), $deactivated_count ); break; case 'um_pending': $pending_count = isset( $_REQUEST['pending_count'] ) ? absint( $_REQUEST['pending_count'] ) : 0; $messages[0]['content'] = sprintf( _n( '<strong>%s</strong> user has been set as pending admin review.', '<strong>%s</strong> users have been set as pending admin review.', $pending_count, 'ultimate-member' ), $pending_count ); break; case 'um_resend_activation': $resend_activation_count = isset( $_REQUEST['resend_activation_count'] ) ? absint( $_REQUEST['resend_activation_count'] ) : 0; $messages[0]['content'] = sprintf( _n( 'Activation email for <strong>%s</strong> user has been sent.', 'Activation emails for <strong>%s</strong> users have been sent.', $resend_activation_count, 'ultimate-member' ), $resend_activation_count ); break; default: /** * Filters the custom admin notice after um_adm_action. * * @param {array} $messages Admin notice messages. * @param {string} $update Update action key. * * @return {array} Admin notice messages. * * @since 2.6.8 * @hook um_adm_action_custom_update_notice * * @example <caption>Add custom admin notice after {custom_update_key} action.</caption> * function my_um_adm_action_custom_update_notice( $messages, $update ) { * if ( 'custom_update_key' === $update ) { * $messages[0]['content'] = 'custom notice text'; * } * return $messages; * } * add_filter( 'um_adm_action_custom_update_notice', 'my_um_adm_action_custom_update_notice', 10, 2 ); */ $messages = apply_filters( 'um_adm_action_custom_update_notice', array(), $update ); break; } if ( ! empty( $messages ) ) { foreach ( $messages as $message ) { if ( isset( $message['err_content'] ) ) { $this->add_notice( 'actions', array( 'class' => 'error', 'message' => '<p>' . $message['err_content'] . '</p>', ), 50 ); } else { $this->add_notice( 'actions', array( 'class' => 'updated', 'message' => '<p>' . $message['content'] . '</p>', ), 50 ); } } } } /** * Check if plugin is installed with correct folder */ function check_wrong_install_folder() { $invalid_folder = false; $slug_array = explode( '/', UM_PLUGIN ); if ( $slug_array[0] != 'ultimate-member' ) { $invalid_folder = true; } if ( $invalid_folder ) { $this->add_notice( 'invalid_dir', array( 'class' => 'error', // translators: %s: Plugin name. 'message' => '<p>' . sprintf( __( 'You have installed <strong>%s</strong> with wrong folder name. Correct folder name is <strong>"ultimate-member"</strong>.', 'ultimate-member' ), UM_PLUGIN_NAME ) . '</p>', ), 1 ); } } public function check_wrong_licenses() { $invalid_license = 0; $arr_inactive_license_keys = array(); if ( empty( UM()->admin_settings()->settings_structure['licenses']['fields'] ) ) { return; } foreach ( UM()->admin_settings()->settings_structure['licenses']['fields'] as $field_data ) { $license = get_option( "{$field_data['id']}_edd_answer" ); if ( ( is_object( $license ) && isset( $license->license ) && 'valid' === $license->license ) || 'valid' === $license ) { continue; } if ( ( is_object( $license ) && isset( $license->license ) && 'inactive' === $license->license ) || 'inactive' === $license ) { $arr_inactive_license_keys[] = $license->item_name; } ++$invalid_license; } if ( ! empty( $arr_inactive_license_keys ) ) { $this->add_notice( 'license_key', array( 'class' => 'error', // translators: %1$s is an inactive license number; %2$s is a plugin name. 'message' => '<p>' . sprintf( __( 'There are %1$s inactive %2$s license keys for this site. This site is not authorized to get plugin updates. You can activate this site on <a href="https://ultimatemember.com/">www.ultimatemember.com</a>.', 'ultimate-member' ), count( $arr_inactive_license_keys ), UM_PLUGIN_NAME ) . '</p>', ), 3 ); } if ( $invalid_license ) { $licenses_page_url = add_query_arg( array( 'page' => 'um_options', 'tab' => 'licenses', ), admin_url( 'admin.php' ) ); $this->add_notice( 'license_key', array( 'class' => 'error', // translators: %1$s is an invalid license; %2$s is a plugin name; %3$s is a license link. 'message' => '<p>' . sprintf( __( 'You have %1$s invalid or expired license keys for %2$s. Please go to the <a href="%3$s">Licenses page</a> to correct this issue.', 'ultimate-member' ), $invalid_license, UM_PLUGIN_NAME, $licenses_page_url ) . '</p>', ), 3 ); } } function need_upgrade() { if ( ! empty( UM()->admin_upgrade()->necessary_packages ) ) { $url = add_query_arg( array( 'page' => 'um_upgrade' ), admin_url( 'admin.php' ) ); ob_start(); ?> <p> <strong><?php echo esc_html( UM_PLUGIN_NAME . ' ' . UM_VERSION . ' ' . __( 'version needs to be updated to work correctly.', 'ultimate-member' ) ); ?></strong> <br /> <?php esc_html_e( 'It is necessary to update the structure of the database and options that are associated with current version', 'ultimate-member' ); ?> <br /> <?php esc_html_e( 'Please run the upgrade process on this ', 'ultimate-member' ); ?><a href="<?php echo esc_url( $url ); ?>"><?php esc_html_e( 'page', 'ultimate-member' ); ?></a> </p> <p> <a href="<?php echo esc_url( $url ); ?>" class="button button-primary"><?php esc_html_e( 'Visit Upgrade Page', 'ultimate-member' ); ?></a> </p> <?php $message = ob_get_clean(); $this->add_notice( 'upgrade', array( 'class' => 'error', 'message' => $message, ), 4 ); } elseif ( isset( $_GET['msg'] ) && 'updated' === sanitize_key( $_GET['msg'] ) ) { if ( isset( $_GET['page'] ) && 'um_options' === sanitize_key( $_GET['page'] ) ) { $this->add_notice( 'settings_upgrade', array( 'class' => 'updated', 'message' => '<p>' . __( 'Settings successfully upgraded', 'ultimate-member' ) . '</p>', ), 4 ); } else { $this->add_notice( 'upgrade', array( 'class' => 'updated', // translators: %1$s is a plugin name title; %2$s is a plugin version. 'message' => '<p>' . sprintf( __( '<strong>%1$s %2$s</strong> Successfully Upgraded', 'ultimate-member' ), UM_PLUGIN_NAME, UM_VERSION ) . '</p>', ), 4 ); } } } /** * @note Removed for now to avoid the bad reviews. * @deprecated 2.8.0 */ private function reviews_notice() { $first_activation_date = get_option( 'um_first_activation_date', false ); if ( empty( $first_activation_date ) ) { return; } if ( $first_activation_date + 2 * WEEK_IN_SECONDS > time() ) { return; } ob_start(); ?> <div id="um_start_review_notice"> <p> <?php // translators: %s: plugin name. echo wp_kses( sprintf( __( 'Hey there! It\'s been one month since you installed %s. How have you found the plugin so far?', 'ultimate-member' ), UM_PLUGIN_NAME ), UM()->get_allowed_html( 'admin_notice' ) ); ?> </p> <p> <a href="javascript:void(0);" id="um_add_review_love"><?php _e( 'I love it!', 'ultimate-member' ); ?></a> | <a href="javascript:void(0);" id="um_add_review_good"><?php _e( 'It\'s good but could be better', 'ultimate-member' ); ?></a> | <a href="javascript:void(0);" id="um_add_review_bad"><?php _e( 'I don\'t like the plugin', 'ultimate-member' ); ?></a> </p> </div> <div class="um-hidden-notice" data-key="love"> <p> <?php printf( __( 'Great! We\'re happy to hear that you love the plugin. It would be amazing if you could let others know why you like %1$s by leaving a review of the plugin. This will help %2$s to grow and become more popular and would be massively appreciated by us!' ), UM_PLUGIN_NAME, UM_PLUGIN_NAME ); ?> </p> <p> <a href="https://wordpress.org/support/plugin/ultimate-member/reviews/?rate=5#new-post" target="_blank" class="button button-primary um_review_link"><?php _e( 'Leave Review', 'ultimate-member' ); ?></a> </p> </div> <div class="um-hidden-notice" data-key="good"> <p> <?php _e( 'We\'re glad to hear that you like the plugin but we would love to get your feedback so we can make the plugin better.' ); ?> </p> <p> <a href="https://ultimatemember.com/feedback/" target="_blank" class="button button-primary um_review_link"><?php _e( 'Provide Feedback', 'ultimate-member' ); ?></a> </p> </div> <div class="um-hidden-notice" data-key="bad"> <p> <?php printf( __( 'We\'re sorry to hear that. If you\'re having the issue with the plugin you can create a topic on our <a href="%s" target="_blank">support forum</a> and we will try and help you out with the issue. Alternatively if you have an idea on how we can make the plugin better or want to tell us what you don\'t like about the plugin you can tell us know by giving us feedback.' ), 'https://wordpress.org/support/plugin/ultimate-member' ); ?> </p> <p> <a href="https://ultimatemember.com/feedback/" target="_blank" class="button button-primary um_review_link"><?php _e( 'Provide Feedback', 'ultimate-member' ); ?></a> </p> </div> <?php $message = ob_get_clean(); $this->add_notice( 'reviews_notice', array( 'class' => 'updated', 'message' => $message, 'dismissible' => true, ), 1 ); } /** * Check Future Changes notice */ function future_changed() { ob_start(); ?> <p> <?php // translators: %1$s is a plugin name; %2$s is a #. echo wp_kses( sprintf( __( '<strong>%1$s</strong> future plans! Detailed future list is <a href="%2$s" target="_blank">here</a>', 'ultimate-member' ), UM_PLUGIN_NAME, '#' ), UM()->get_allowed_html( 'admin_notice' ) ); ?> </p> <?php $message = ob_get_clean(); $this->add_notice( 'future_changes', array( 'class' => 'updated', 'message' => $message, ), 2 ); } /** * Check if there isn't installed child-theme. Child theme is required for safely saved customizations. */ public function child_theme_required() { if ( ! is_child_theme() ) { if ( ! is_dir( get_stylesheet_directory() . DIRECTORY_SEPARATOR . 'ultimate-member' ) ) { return; } ob_start(); ?> <p> <?php // translators: %s child-theme article link. echo wp_kses( sprintf( __( 'We recommend using a <a href="%s">child-theme</a> for Ultimate Member customization. Unlike official theme repositories, child themes don\'t have dependencies that could lead to your custom files being overwritten during a theme upgrade.<br />Without a child theme, your customization files may be deleted after every theme update.', 'ultimate-member' ), 'https://developer.wordpress.org/themes/advanced-topics/child-themes/' ), UM()->get_allowed_html( 'admin_notice' ) ); ?> </p> <?php $message = ob_get_clean(); UM()->admin()->notices()->add_notice( 'um_is_not_child_theme', array( 'class' => 'notice-warning', 'message' => $message, 'dismissible' => true, ), 10 ); } } public function common_secure() { if ( UM()->options()->get( 'lock_register_forms' ) ) { ob_start(); ?> <p> <?php esc_html_e( 'Your Register forms are now locked. You can unlock them in Ultimate Member > Settings > Advanced > Security > Lock All Register Forms.', 'ultimate-member' ); ?> </p> <?php $message = ob_get_clean(); $this->add_notice( 'common_secure_register', array( 'class' => 'warning', 'message' => $message, 'dismissible' => true, ), 1 ); } if ( UM()->options()->get( 'display_login_form_notice' ) ) { ob_start(); ?> <p> <?php esc_html_e( 'Mandatory password changes has been enabled. You can disable them in Ultimate Member > Settings > Advanced > Security > Display Login form notice to reset passwords.', 'ultimate-member' ); ?> </p> <?php $message = ob_get_clean(); $this->add_notice( 'common_secure_password_reset', array( 'class' => 'warning', 'message' => $message, 'dismissible' => true, ), 1 ); } if ( UM()->options()->get( 'secure_ban_admins_accounts' ) ) { ob_start(); ?> <p> <?php esc_html_e( 'Ban for administrative capabilities is enabled. You can disable them in Ultimate Member > Settings > Advanced > Security > Enable ban for administrative capabilities.', 'ultimate-member' ); ?> </p> <?php $message = ob_get_clean(); $this->add_notice( 'common_secure_suspicious_activity', array( 'class' => 'warning', 'message' => $message, 'dismissible' => true, ), 1 ); } $this->check_new_user_role(); $this->check_registration_forms(); } private function check_new_user_role() { $arr_banned_caps = UM()->options()->get( 'banned_capabilities' ); if ( empty( $arr_banned_caps ) ) { return; } $global_role = get_option( 'default_role' ); // WP Global settings $global_role = get_role( $global_role ); $caps = ( null !== $global_role && ! empty( $global_role->capabilities ) ) ? $global_role->capabilities : array(); foreach ( array_keys( $caps ) as $cap ) { if ( in_array( $cap, $arr_banned_caps, true ) ) { ob_start(); ?> <p> <?php esc_html_e( 'The role selected in WordPress native "Settings > New User Default Role" setting has Administrative capabilities.', 'ultimate-member' ); ?> </p> <?php $message = ob_get_clean(); $this->add_notice( 'default_role_suspicious_activity', array( 'class' => 'notice-warning', 'message' => $message, 'dismissible' => true, ), 1 ); break; } } $um_global_role = UM()->options()->get( 'register_role' ); // UM Settings Global settings if ( ! empty( $um_global_role ) ) { $um_global_role = get_role( $um_global_role ); $caps = ( null !== $um_global_role && ! empty( $um_global_role->capabilities ) ) ? $um_global_role->capabilities : array(); foreach ( array_keys( $caps ) as $cap ) { if ( in_array( $cap, $arr_banned_caps, true ) ) { ob_start(); ?> <p> <?php esc_html_e( 'The role selected in "Ultimate Member > Settings > Appearance > Registration Form > Registration Default Role" setting has Administrative capabilities.', 'ultimate-member' ); ?> </p> <?php $message = ob_get_clean(); $this->add_notice( 'register_role_suspicious_activity', array( 'class' => 'notice-warning', 'message' => $message, 'dismissible' => true, ), 1 ); break; } } } } private function check_registration_forms() { $arr_banned_caps = UM()->options()->get( 'banned_capabilities' ); if ( empty( $arr_banned_caps ) ) { return; } $um_forms = get_posts( array( 'post_type' => 'um_form', 'meta_query' => array( array( 'key' => '_um_mode', 'value' => 'register', ), array( 'key' => '_um_register_use_custom_settings', 'value' => true, ), ), 'numberposts' => -1, 'fields' => 'ids', ) ); $content = ''; foreach ( $um_forms as $form_id ) { $role = get_post_meta( $form_id, '_um_register_role', true ); if ( empty( $role ) ) { continue; } $role = get_role( $role ); $caps = ( null !== $role && ! empty( $role->capabilities ) ) ? $role->capabilities : array(); foreach ( array_keys( $caps ) as $cap ) { if ( in_array( $cap, $arr_banned_caps, true ) ) { $content .= '<br /><a target="_blank" href="' . get_edit_post_link( $form_id ) . '">' . get_the_title( $form_id ) . '</a> contains <strong>administrative role</strong>.'; break; } } } if ( empty( $content ) ) { return; } ob_start(); ?> <p> <?php // translators: %s are link(s) to the forms. ?> <?php echo wp_kses( sprintf( __( 'Register forms have Administrative roles, we recommend that you assign a non-admin roles to secure the forms. %s', 'ultimate-member' ), $content ), UM()->get_allowed_html( 'admin_notice' ) ); ?> </p> <?php $message = ob_get_clean(); $this->add_notice( 'forms_secure_suspicious_activity', array( 'class' => 'notice-warning', 'message' => $message, 'dismissible' => true, ), 1 ); } public function dismiss_notice() { UM()->admin()->check_ajax_nonce(); if ( empty( $_POST['key'] ) ) { wp_send_json_error( __( 'Wrong Data', 'ultimate-member' ) ); } $this->dismiss( sanitize_key( $_POST['key'] ) ); wp_send_json_success(); } /** * Dismiss notice by key. * * @param string $key * * @return void */ public function dismiss( $key ) { $hidden_notices = get_option( 'um_hidden_admin_notices', array() ); if ( ! is_array( $hidden_notices ) ) { $hidden_notices = array(); } $hidden_notices[] = $key; update_option( 'um_hidden_admin_notices', $hidden_notices ); } function force_dismiss_notice() { if ( ! empty( $_REQUEST['um_dismiss_notice'] ) && ! empty( $_REQUEST['um_admin_nonce'] ) ) { if ( wp_verify_nonce( $_REQUEST['um_admin_nonce'], 'um-admin-nonce' ) ) { $hidden_notices = get_option( 'um_hidden_admin_notices', array() ); if ( ! is_array( $hidden_notices ) ) { $hidden_notices = array(); } $hidden_notices[] = sanitize_key( $_REQUEST['um_dismiss_notice'] ); update_option( 'um_hidden_admin_notices', $hidden_notices ); } else { wp_die( __( 'Security Check', 'ultimate-member' ) ); } } } } } includes/admin/core/class-admin-columns.php 0000644 00000013464 15252504435 0014771 0 ustar 00 <?php namespace um\admin\core; use WP_Post; if ( ! defined( 'ABSPATH' ) ) { exit; } if ( ! class_exists( 'um\admin\core\Admin_Columns' ) ) { /** * Class Admin_Columns * @package um\admin\core */ class Admin_Columns { /** * Admin_Columns constructor. */ public function __construct() { add_filter( 'manage_edit-um_form_columns', array( &$this, 'manage_edit_um_form_columns' ) ); add_action( 'manage_um_form_posts_custom_column', array( &$this, 'manage_um_form_posts_custom_column' ), 10, 3 ); add_filter( 'manage_edit-um_directory_columns', array( &$this, 'manage_edit_um_directory_columns' ) ); add_action( 'manage_um_directory_posts_custom_column', array( &$this, 'manage_um_directory_posts_custom_column' ), 10, 3 ); add_filter( 'post_row_actions', array( &$this, 'post_row_actions' ), 99, 2 ); // Add a post display state for special UM pages. add_filter( 'display_post_states', array( &$this, 'add_display_post_states' ), 10, 2 ); add_filter( 'post_row_actions', array( &$this, 'remove_bulk_actions_um_form_inline' ), 10, 2 ); } /** * This will remove the "Edit" bulk action, which is actually quick edit. * * @param array $actions * @param WP_Post $post * * @return array */ public function remove_bulk_actions_um_form_inline( $actions, $post ) { $remove_quick_edit = array( 'um_form', 'um_directory', ); $remove_quick_edit = apply_filters( 'um_cpt_remove_quick_edit', $remove_quick_edit ); if ( in_array( $post->post_type, $remove_quick_edit, true ) ) { unset( $actions['inline hide-if-no-js'] ); } return $actions; } /** * Custom row actions * * @param array $actions * @param WP_Post $post * * @return mixed */ public function post_row_actions( $actions, $post ) { //check for your post type if ( 'um_form' === $post->post_type ) { $actions['um_duplicate'] = '<a href="' . esc_url( $this->duplicate_uri( $post->ID ) ) . '">' . __( 'Duplicate', 'ultimate-member' ) . '</a>'; } return $actions; } /** * Duplicate a form * * @param int $id * * @return string */ private function duplicate_uri( $id ) { $url = add_query_arg( array( 'post_type' => 'um_form', 'um_adm_action' => 'duplicate_form', 'post_id' => $id, '_wpnonce' => wp_create_nonce( "um-duplicate_form{$id}" ), ), admin_url( 'edit.php' ) ); return $url; } /** * Custom columns for Form * * @param array $columns * * @return array */ function manage_edit_um_form_columns( $columns ) { $new_columns['cb'] = '<input type="checkbox" />'; $new_columns['title'] = __( 'Title', 'ultimate-member' ); $new_columns['id'] = __('ID', 'ultimate-member' ); $new_columns['mode'] = __( 'Type', 'ultimate-member' ); $new_columns['is_default'] = __( 'Default', 'ultimate-member' ); $new_columns['shortcode'] = __( 'Shortcode', 'ultimate-member' ); $new_columns['date'] = __( 'Date', 'ultimate-member' ); return $new_columns; } /** * Custom columns for Directory * * @param array $columns * * @return array */ function manage_edit_um_directory_columns( $columns ) { $new_columns['cb'] = '<input type="checkbox" />'; $new_columns['title'] = __( 'Title', 'ultimate-member' ); $new_columns['id'] = __( 'ID', 'ultimate-member' ); $new_columns['is_default'] = __( 'Default', 'ultimate-member' ); $new_columns['shortcode'] = __( 'Shortcode', 'ultimate-member' ); $new_columns['date'] = __( 'Date', 'ultimate-member' ); return $new_columns; } /** * Display custom columns for Form * * @param string $column_name * @param int $id */ function manage_um_form_posts_custom_column( $column_name, $id ) { switch ( $column_name ) { case 'id': echo '<span class="um-admin-number">'.$id.'</span>'; break; case 'shortcode': $is_default = UM()->query()->get_attr( 'is_default', $id ); if ( $is_default ) { echo UM()->shortcodes()->get_default_shortcode( $id ); } else { echo UM()->shortcodes()->get_shortcode( $id ); } break; case 'is_default': $is_default = UM()->query()->get_attr( 'is_default', $id ); echo empty( $is_default ) ? __( 'No', 'ultimate-member' ) : __( 'Yes', 'ultimate-member' ); break; case 'mode': $mode = UM()->query()->get_attr( 'mode', $id ); echo UM()->form()->display_form_type( $mode, $id ); break; } } /** * Display custom columns for Directory * * @param string $column_name * @param int $id */ function manage_um_directory_posts_custom_column( $column_name, $id ) { switch ( $column_name ) { case 'id': echo '<span class="um-admin-number">'.$id.'</span>'; break; case 'shortcode': $is_default = UM()->query()->get_attr( 'is_default', $id ); if ( $is_default ) { echo UM()->shortcodes()->get_default_shortcode( $id ); } else { echo UM()->shortcodes()->get_shortcode( $id ); } break; case 'is_default': $is_default = UM()->query()->get_attr( 'is_default', $id ); echo empty( $is_default ) ? __( 'No', 'ultimate-member' ) : __( 'Yes', 'ultimate-member' ); break; } } /** * Add a post display state for special UM pages in the page list table. * * @param array $post_states An array of post display states. * @param WP_Post $post The current post object. * * @return mixed */ public function add_display_post_states( $post_states, $post ) { foreach ( UM()->config()->core_pages as $page_key => $page_value ) { $page_id = UM()->options()->get( UM()->options()->get_predefined_page_option_key( $page_key ) ); if ( $page_id == $post->ID ) { $post_states[ 'um_core_page_' . $page_key ] = sprintf( 'UM %s', $page_value['title'] ); } } return $post_states; } } } includes/admin/core/class-admin-forms.php 0000644 00000202760 15252504435 0014436 0 ustar 00 <?php namespace um\admin\core; if ( ! defined( 'ABSPATH' ) ) exit; if ( ! class_exists( 'um\admin\core\Admin_Forms' ) ) { /** * Class Admin_Forms * @package um\admin\core */ class Admin_Forms { /** * @var bool */ var $form_data; /** * Admin_Forms constructor. * @param bool $form_data */ function __construct( $form_data = false ) { if ( $form_data ) { $this->form_data = $form_data; } } /** * Set Form Data * * @param $data * * @return $this */ function set_data( $data ) { $this->form_data = $data; return $this; } /** * Render form * * * @param bool $echo * @return string */ public function render_form( $echo = true ) { if ( empty( $this->form_data['fields'] ) ) { return ''; } $class = 'form-table um-form-table ' . ( ! empty( $this->form_data['class'] ) ? $this->form_data['class'] : '' ); $class_attr = ' class="' . $class . '" '; ob_start(); foreach ( $this->form_data['fields'] as $field_data ) { if ( isset( $field_data['type'] ) && 'hidden' === $field_data['type'] ) { echo $this->render_form_row( $field_data ); } } if ( empty( $this->form_data['without_wrapper'] ) ) { ?> <table <?php echo $class_attr ?>> <tbody> <?php } foreach ( $this->form_data['fields'] as $field_data ) { if ( isset( $field_data['type'] ) && 'hidden' != $field_data['type'] ) { echo $this->render_form_row( $field_data ); } } if ( empty( $this->form_data['without_wrapper'] ) ) { ?> </tbody> </table> <?php } if ( $echo ) { ob_get_flush(); return ''; } else { return ob_get_clean(); } } /** * @param array $data * * @return string */ public function render_form_row( $data ) { if ( empty( $data['type'] ) ) { return ''; } if ( ! empty( $data['value'] ) && $data['type'] != 'email_template' ) { $data['value'] = wp_unslash( $data['value'] ); /*for multi_text*/ if ( ! is_array( $data['value'] ) && ! in_array( $data['type'], array('info_text','wp_editor' ) ) ) { $data['value'] = esc_attr( $data['value'] ); } if ( 'info_text' === $data['type'] ) { $arr_kses = array( 'a' => array( 'href' => array(), 'title' => array(), 'target' => array(), 'class' => array(), 'onclick' => array(), ), 'button' => array( 'class' => array(), ), 'i' => array( 'class' => array(), ), 'span' => array( 'class' => array(), ), 'br' => array(), 'em' => array(), 'strong' => array( 'style' => array() ), ); $data['value'] = wp_kses( $data['value'], $arr_kses ); } } $conditional = ! empty( $data['conditional'] ) ? 'data-conditional="' . esc_attr( json_encode( $data['conditional'] ) ) . '"' : ''; $prefix_attr = ! empty( $this->form_data['prefix_id'] ) ? ' data-prefix="' . esc_attr( $this->form_data['prefix_id'] ) . '" ' : ''; $type_attr = ' data-field_type="' . esc_attr( $data['type'] ) . '" '; $html = ''; if ( $data['type'] != 'hidden' ) { if ( ! empty( $this->form_data['div_line'] ) ) { if ( strpos( $this->form_data['class'], 'um-top-label' ) !== false ) { $html .= '<div class="form-field um-forms-line" ' . $conditional . $prefix_attr . $type_attr . '>' . $this->render_field_label( $data ); if ( method_exists( $this, 'render_' . $data['type'] ) ) { $html .= call_user_func( array( &$this, 'render_' . $data['type'] ), $data ); } else { $html .= $this->render_field_by_hook( $data ); } if ( ! empty( $data['description'] ) ) { $html .= '<p class="description">' . $data['description'] . '</p>'; } $html .= '</div>'; } else { if ( ! empty( $data['without_label'] ) ) { $html .= '<div class="form-field um-forms-line" ' . $conditional . $prefix_attr . $type_attr . '>'; if ( method_exists( $this, 'render_' . $data['type'] ) ) { $html .= call_user_func( array( &$this, 'render_' . $data['type'] ), $data ); } else { $html .= $this->render_field_by_hook( $data ); } if ( ! empty( $data['description'] ) ) { $html .= '<p class="description">' . $data['description'] . '</p>'; } $html .= '</div>'; } else { $html .= '<div class="form-field um-forms-line" ' . $conditional . $prefix_attr . $type_attr . '>' . $this->render_field_label( $data ); if ( method_exists( $this, 'render_' . $data['type'] ) ) { $html .= call_user_func( array( &$this, 'render_' . $data['type'] ), $data ); } else { $html .= $this->render_field_by_hook( $data ); } if ( ! empty( $data['description'] ) ) { $html .= '<p class="description">' . $data['description'] . '</p>'; } $html .= '</div>'; } } } else { if ( strpos( $this->form_data['class'], 'um-top-label' ) !== false ) { $html .= '<tr class="um-forms-line" ' . $conditional . $prefix_attr . $type_attr . '> <td>' . $this->render_field_label( $data ); if ( method_exists( $this, 'render_' . $data['type'] ) ) { $html .= call_user_func( array( &$this, 'render_' . $data['type'] ), $data ); } else { $html .= $this->render_field_by_hook( $data ); } if ( ! empty( $data['description'] ) ) { $html .= '<div class="clear"></div><p class="description">' . $data['description'] . '</p>'; } $html .= '</td></tr>'; } else { if ( ! empty( $data['without_label'] ) ) { $html .= '<tr class="um-forms-line" ' . $conditional . $prefix_attr . $type_attr . '> <td colspan="2">'; if ( method_exists( $this, 'render_' . $data['type'] ) ) { $html .= call_user_func( array( &$this, 'render_' . $data['type'] ), $data ); } else { $html .= $this->render_field_by_hook( $data ); } if ( ! empty( $data['description'] ) ) { $html .= '<div class="clear"></div><p class="description">' . $data['description'] . '</p>'; } $html .= '</td></tr>'; } else { $html .= '<tr class="um-forms-line" ' . $conditional . $prefix_attr . $type_attr . '> <th>' . $this->render_field_label( $data ) . '</th> <td>'; if ( method_exists( $this, 'render_' . $data['type'] ) ) { $html .= call_user_func( array( &$this, 'render_' . $data['type'] ), $data ); } else { $html .= $this->render_field_by_hook( $data ); } if ( ! empty( $data['description'] ) ) { $html .= '<div class="clear"></div><p class="description">' . $data['description'] . '</p>'; } $html .= '</td></tr>'; } } } } else { $html .= $this->render_hidden( $data ); } return $html; } /** * @param $data * * @return mixed|void */ function render_field_by_hook( $data ) { /** * UM hook * * @type filter * @title um_render_field_type_{$type} * @description Render admin form field by hook * @input_vars * [{"var":"$html","type":"string","desc":"Field's HTML"}, * {"var":"$data","type":"array","desc":"Field's data"}, * {"var":"$form_data","type":"array","desc":"Form data"}, * {"var":"$admin_form","type":"object","desc":"Admin_Forms class object"}] * @change_log * ["Since: 2.0"] * @usage add_filter( 'um_render_field_type_{$type}', 'function_name', 10, 4 ); * @example * <?php * add_filter( 'um_render_field_type_{$type}', 'my_render_field_type', 10, 4 ); * function my_render_field_type( $html, $data, $form_data, $admin_form ) { * // your code here * return $html; * } * ?> */ return apply_filters( 'um_render_field_type_' . $data['type'], '', $data, $this->form_data, $this ); } /** * @param $data * * @return bool|string */ function render_field_label( $data ) { if ( empty( $data['label'] ) ) { return false; } $id = ! empty( $data['id1'] ) ? $data['id1'] : $data['id']; $id = ( ! empty( $this->form_data['prefix_id'] ) ? $this->form_data['prefix_id'] : '' ) . '_' . $id; $for_attr = ' for="' . esc_attr( $id ) . '" '; $label = $data['label']; if ( isset( $data['required'] ) && $data['required'] ) { $label = $label . '<span class="um-req" title="' . esc_attr__( 'Required', 'ultimate-member' ) . '">*</span>'; } $tooltip = ! empty( $data['tooltip'] ) ? UM()->tooltip( $data['tooltip'], false, false ) : ''; return "<label $for_attr>$label $tooltip</label>"; } /** * @param $field_data * * @return bool|string */ function render_hidden( $field_data ) { if ( empty( $field_data['id'] ) ) { return ''; } $id = ( ! empty( $this->form_data['prefix_id'] ) ? $this->form_data['prefix_id'] : '' ) . '_' . $field_data['id']; $id_attr = ' id="' . esc_attr( $id ) . '" '; $class = ! empty( $field_data['class'] ) ? $field_data['class'] : ''; $class_attr = ' class="um-forms-field ' . esc_attr( $class ) . '" '; $data = array( 'field_id' => $field_data['id'] ); $data_attr = ''; foreach ( $data as $key => $value ) { $data_attr .= ' data-' . $key . '="' . esc_attr( $value ) . '" '; } $name = $field_data['id']; $name = ! empty( $this->form_data['prefix_id'] ) ? $this->form_data['prefix_id'] . '[' . $name . ']' : $name; $name_attr = ' name="' . $name . '" '; $value = $this->get_field_value( $field_data ); $value_attr = ' value="' . $value . '" '; $html = "<input type=\"hidden\" $id_attr $class_attr $name_attr $data_attr $value_attr />"; return $html; } /** * Render text field * * @param $field_data * * @return bool|string */ function render_text( $field_data ) { if ( empty( $field_data['id'] ) ) { return false; } $id = ( ! empty( $this->form_data['prefix_id'] ) ? $this->form_data['prefix_id'] : '' ) . '_' . $field_data['id']; $id_attr = ' id="' . esc_attr( $id ) . '" '; $class = ! empty( $field_data['class'] ) ? $field_data['class'] : ''; $class .= ! empty( $field_data['size'] ) ? 'um-' . $field_data['size'] . '-field' : 'um-long-field'; $class_attr = ' class="um-forms-field ' . esc_attr( $class ) . '" '; $data = array( 'field_id' => $field_data['id'] ); if ( ! empty( $field_data['attr'] ) && is_array( $field_data['attr'] ) ){ $data = array_merge( $data, $field_data['attr'] ); } $data_attr = ''; foreach ( $data as $key => $value ) { $data_attr .= ' data-' . $key . '="' . esc_attr( $value ) . '" '; } $placeholder_attr = ! empty( $field_data['placeholder'] ) ? ' placeholder="' . esc_attr( $field_data['placeholder'] ) . '"' : ''; $name = $field_data['id']; $name = ! empty( $this->form_data['prefix_id'] ) ? $this->form_data['prefix_id'] . '[' . $name . ']' : $name; $name_attr = ' name="' . $name . '" '; $value = $this->get_field_value( $field_data ); $value_attr = ' value="' . esc_attr( $value ) . '" '; $html = "<input type=\"text\" $id_attr $class_attr $name_attr $data_attr $value_attr $placeholder_attr />"; return $html; } /** * Render API key field. * * A masked/secret field with a show/hide toggle. The real value is stored in a hidden input * (submitted as um_options[<id>], exactly like a `text` field); a single visible, read-only * display input shows either the partially-masked value (first/last characters kept, middle * bulleted) or, once the eye button is toggled, the full editable value. Because only one * input is ever visible, the field can never look duplicated even if the stylesheet is stale. * * Extra field config keys: `reveal_prefix` (int, default 6), `reveal_suffix` (int, default 4). * * @param array $field_data * * @return bool|string */ function render_api_key( $field_data ) { if ( empty( $field_data['id'] ) ) { return false; } $id = ( ! empty( $this->form_data['prefix_id'] ) ? $this->form_data['prefix_id'] : '' ) . '_' . $field_data['id']; $id_attr = ' id="' . esc_attr( $id ) . '" '; $mask_id_attr = ' id="' . esc_attr( $id ) . '_masked" '; $size_class = ! empty( $field_data['size'] ) ? 'um-' . $field_data['size'] . '-field' : 'um-long-field'; $data = array( 'field_id' => $field_data['id'], ); if ( ! empty( $field_data['attr'] ) && is_array( $field_data['attr'] ) ) { $data = array_merge( $data, $field_data['attr'] ); } $data_attr = ''; foreach ( $data as $key => $value ) { $data_attr .= ' data-' . $key . '="' . esc_attr( $value ) . '" '; } $placeholder_attr = ! empty( $field_data['placeholder'] ) ? ' placeholder="' . esc_attr( $field_data['placeholder'] ) . '"' : ''; $name = $field_data['id']; $name = ! empty( $this->form_data['prefix_id'] ) ? $this->form_data['prefix_id'] . '[' . $name . ']' : $name; $name_attr = ' name="' . $name . '" '; $value = $this->get_field_value( $field_data ); $value_attr = ' value="' . esc_attr( $value ) . '" '; $readonly = ''; $title = ''; if ( ! empty( $value ) ) { $title = ' title="' . esc_attr__( 'You can change the value only in the visible mode.', 'ultimate-member' ) . '" '; $readonly = ' readonly '; } $prefix = isset( $field_data['reveal_prefix'] ) ? absint( $field_data['reveal_prefix'] ) : 6; $suffix = isset( $field_data['reveal_suffix'] ) ? absint( $field_data['reveal_suffix'] ) : 4; $show_label = esc_attr__( 'Show key', 'ultimate-member' ); // Inline layout so the input + toggle stay on one line even if the stylesheet is cached/stale. $html = '<span class="um-api-key-field" style="display:flex;align-items:center;gap:6px;max-width:100%" data-reveal-prefix="' . esc_attr( $prefix ) . '" data-reveal-suffix="' . esc_attr( $suffix ) . '">'; // Real value carrier — the only element submitted as um_options[<id>]. Never shown. $html .= "<input type=\"hidden\" $id_attr $name_attr $data_attr $value_attr class=\"um-forms-field um-api-key-value\" />"; // Single visible display input (no name → not submitted). JS fills/masks it and toggles readonly. $html .= "<input type=\"text\" $mask_id_attr $data_attr class=\"um-api-key-display " . esc_attr( $size_class ) . "\" autocomplete=\"off\" spellcheck=\"false\"" . $placeholder_attr . $readonly . $title . ' />'; // Show/hide toggle. $html .= '<button type="button" class="button um-api-key-toggle" aria-label="' . $show_label . '" title="' . $show_label . '"><span class="dashicons dashicons-visibility"></span></button>'; $html .= '</span>'; return $html; } /** * Render text field * * @param $field_data * * @return bool|string */ function render_number( $field_data ) { if ( empty( $field_data['id'] ) ) { return false; } $id = ( ! empty( $this->form_data['prefix_id'] ) ? $this->form_data['prefix_id'] : '' ) . '_' . $field_data['id']; $id_attr = ' id="' . esc_attr( $id ) . '" '; $class = ! empty( $field_data['class'] ) ? $field_data['class'] : ''; $class .= ! empty( $field_data['size'] ) ? 'um-' . $field_data['size'] . '-field' : 'um-long-field'; $class_attr = ' class="um-forms-field ' . esc_attr( $class ) . '" '; $data = array( 'field_id' => $field_data['id'] ); if ( ! empty( $field_data['attr'] ) && is_array( $field_data['attr'] ) ){ $data = array_merge( $data, $field_data['attr'] ); } $data_attr = ''; foreach ( $data as $key => $value ) { $data_attr .= ' data-' . $key . '="' . esc_attr( $value ) . '" '; } $placeholder_attr = ! empty( $field_data['placeholder'] ) ? ' placeholder="' . esc_attr( $field_data['placeholder'] ) . '"' : ''; $name = $field_data['id']; $name = ! empty( $this->form_data['prefix_id'] ) ? $this->form_data['prefix_id'] . '[' . $name . ']' : $name; $name_attr = ' name="' . $name . '" '; $value = $this->get_field_value( $field_data ); $value_attr = ' value="' . esc_attr( $value ) . '" '; $html = "<input type=\"number\" $id_attr $class_attr $name_attr $data_attr $value_attr $placeholder_attr />"; return $html; } /** * @param $field_data * * @return bool|string */ function render_color( $field_data ) { if ( empty( $field_data['id'] ) ) { return false; } $id = ( ! empty( $this->form_data['prefix_id'] ) ? $this->form_data['prefix_id'] : '' ) . '_' . $field_data['id']; $id_attr = ' id="' . esc_attr( $id ) . '" '; $class = ! empty( $field_data['class'] ) ? $field_data['class'] : ''; $class .= ! empty( $field_data['size'] ) ? ' um-' . $field_data['size'] . '-field ' : ' um-long-field '; $class .= ' um-admin-colorpicker '; $class_attr = ' class="um-forms-field ' . esc_attr( $class ) . '" '; $data = array( 'field_id' => $field_data['id'] ); $data_attr = ''; foreach ( $data as $key => $value ) { $data_attr .= ' data-' . $key . '="' . esc_attr( $value ) . '" '; } $placeholder_attr = ! empty( $field_data['placeholder'] ) ? ' placeholder="' . esc_attr( $field_data['placeholder'] ) . '"' : ''; $name = $field_data['id']; $name = ! empty( $this->form_data['prefix_id'] ) ? $this->form_data['prefix_id'] . '[' . $name . ']' : $name; $name_attr = ' name="' . $name . '" '; $value = $this->get_field_value( $field_data ); $value_attr = ' value="' . $value . '" '; $html = "<input type=\"text\" $id_attr $class_attr $name_attr $data_attr $value_attr $placeholder_attr />"; return $html; } /** * @param $field_data * * @return bool|string */ public function render_icon( $field_data ) { if ( empty( $field_data['id'] ) ) { return false; } $html = ''; $id = ( ! empty( $this->form_data['prefix_id'] ) ? $this->form_data['prefix_id'] : '' ) . '_' . $field_data['id']; $id_attr = ' id="' . esc_attr( $id ) . '" '; $name = $field_data['id']; $name = ! empty( $this->form_data['prefix_id'] ) ? $this->form_data['prefix_id'] . '[' . $name . ']' : $name; $name_attr = ' name="' . esc_attr( $name ) . '" '; $value = $this->get_field_value( $field_data ); $value_attr = ' value="' . esc_attr( $value ) . '" '; UM()->setup()->set_icons_options(); $um_icons_list = get_option( 'um_icons_list' ); $first_activation_date = get_option( 'um_first_activation_date', false ); // @todo new version if ( empty( $first_activation_date ) || $first_activation_date >= 1716336000 || empty( $value ) || array_key_exists( $value, $um_icons_list ) ) { $html .= '<select ' . $name_attr . ' ' . $id_attr . ' class="um-icon-select-field" data-placeholder="' . esc_attr__( 'Select Icon', 'ultimate-member' ) . '" ><option value="">' . esc_html__( 'Select Icon', 'ultimate-member' ) . '</option>'; if ( ! empty( $value ) && array_key_exists( $value, $um_icons_list ) ) { $html .= '<option ' . $value_attr . ' selected>' . esc_html( $um_icons_list[ $value ]['label'] ) . '</option>'; } $html .= '</select>'; } else { // Required modal scripts for proper functioning UM()->admin()->enqueue()->load_modal(); $html .= '<select name="um_ui_icon_new" id="um_ui_icon_new" class="um-icon-select-field" data-placeholder="' . esc_attr__( 'Select Icon', 'ultimate-member' ) . '" ><option value="">' . esc_html__( 'Select Icon', 'ultimate-member' ) . '</option>'; $html .= '</select>'; $html .= '<span class="um_admin_fonticon_wrapper"><span>' . esc_html__( 'The selected icon is using an outdated version. Please select the icon above to use latest version.', 'ultimate-member' ) . '</span> <span class="um-admin-icon-value">'; $html .= '<i class="' . esc_attr( $value ) . '"></i>'; $html .= '</span><input type="hidden" ' . $name_attr . ' ' . $id_attr . ' ' . $value_attr . ' class="um_old_icon_field_value"/>'; $html .= '<span class="um-admin-icon-clear show"><i class="um-icon-android-cancel"></i></span>'; $html .= '</span></span>'; // Required include the fonticons modal *.php file. UM()->metabox()->init_icon = true; } return $html; } /** * @param $field_data * * @return bool|string */ public function render_users_dropdown( $field_data ) { if ( empty( $field_data['id'] ) ) { return false; } $multiple = ! empty( $field_data['multi'] ) ? 'multiple' : ''; $id = ( ! empty( $this->form_data['prefix_id'] ) ? $this->form_data['prefix_id'] : '' ) . '_' . $field_data['id']; $id_attr = ' id="' . esc_attr( $id ) . '" '; $class = ! empty( $field_data['class'] ) ? $field_data['class'] . ' ' : ' '; $class .= ! empty( $field_data['size'] ) ? 'um-' . $field_data['size'] . '-field' : 'um-long-field'; $class_attr = ' class="um-forms-field um-user-select-field' . esc_attr( $class ) . '" '; $data = array( 'field_id' => $field_data['id'], 'avatar' => ! empty( $field_data['avatar'] ) ? 1 : 0, ); if ( ! empty( $field_data['data'] ) && is_array( $field_data['data'] ) ) { $data = array_merge( $data, $field_data['data'] ); } $data_attr = ''; foreach ( $data as $key => $value ) { $data_attr .= ' data-' . $key . '="' . esc_attr( $value ) . '" '; } $name = $field_data['id']; $name = ! empty( $this->form_data['prefix_id'] ) ? $this->form_data['prefix_id'] . '[' . $name . ']' : $name; $hidden_name_attr = ' name="' . $name . '" '; $name = $name . ( ! empty( $field_data['multi'] ) ? '[]' : '' ); $name_attr = ' name="' . $name . '" '; $value = $this->get_field_value( $field_data ); $users = array(); if ( ! empty( $value ) ) { $users = get_users( array( 'include' => $value, 'fields' => array( 'ID', 'user_login' ), ) ); } $options = ''; if ( ! empty( $users ) ) { foreach ( $users as $user ) { if ( ! empty( $field_data['avatar'] ) ) { $url = get_avatar_url( $user->ID, 'size=20' ); $options .= '<option data-img="' . esc_url( $url ) . '" value="' . esc_attr( $user->ID ) . '" selected>' . esc_html( $user->user_login . ' (#' . $user->ID . ')' ) . '</option>'; } else { $options .= '<option value="' . esc_attr( $user->ID ) . '" selected>' . esc_html( $user->user_login . ' (#' . $user->ID . ')' ) . '</option>'; } } } $placeholder = ! empty( $field_data['placeholder'] ) ? $field_data['placeholder'] : __( 'Select Users', 'ultimate-member' ); $hidden = ''; if ( ! empty( $multiple ) ) { $hidden = "<input type=\"hidden\" $hidden_name_attr value=\"\" />"; } else { $options = '<option></option>' . $options; } $html = "$hidden<select $multiple $id_attr $name_attr $class_attr $data_attr data-placeholder=\"" . esc_attr( $placeholder ) . "\" placeholder=\"" . esc_attr( $placeholder ) . "\">$options</select>"; return $html; } /** * @param $field_data * * @return bool|string */ function render_sortable_items( $field_data ) { if ( empty( $field_data['id'] ) ) { return false; } if ( empty( $field_data['items'] ) ) { return false; } $id = ( ! empty( $this->form_data['prefix_id'] ) ? $this->form_data['prefix_id'] : '' ) . '_' . $field_data['id']; $id_attr = ' id="' . esc_attr( $id ) . '" '; $size = ! empty( $field_data['size'] ) ? ' um-' . $field_data['size'] . '-field ' : ' um-long-field'; $name = $field_data['id']; $name = ! empty( $this->form_data['prefix_id'] ) ? $this->form_data['prefix_id'] . '[' . $name . ']' : $name; $name_attr = ' name="' . $name . '" '; $value = $this->get_field_value( $field_data ); $value_attr = ' value="' . $value . '" '; $data = array( 'field_id' => $field_data['id'] ); $data_attr = ''; foreach ( $data as $key => $val ) { $data_attr .= ' data-' . $key . '="' . esc_attr( $val ) . '" '; } $html = '<input class="um-sortable-items-value" type="hidden" ' . $name_attr . ' ' . $id_attr . ' ' . $value_attr . ' ' . $data_attr . ' />'; $html .= '<ul class="um-sortable-items-field' . esc_attr( $size ) . '">'; if ( ! empty( $value ) ) { $value_array = explode( ',', $value ); uksort( $field_data['items'], function( $a, $b ) use ( $value_array ) { $arr_flip = array_flip( $value_array ); if ( ! isset( $arr_flip[ $b ] ) ) { return 1; } if ( ! isset( $arr_flip[ $a ] ) ) { return -1; } if ( $arr_flip[ $a ] == $arr_flip[ $b ] ) { return 0; } return ( $arr_flip[ $a ] < $arr_flip[ $b ] ) ? -1 : 1; } ); } foreach ( $field_data['items'] as $tab_id => $tab_name ) { $content = apply_filters( 'um_render_sortable_items_item_html', $tab_name, $tab_id, $field_data ); $html .= '<li data-tab-id="' . esc_attr( $tab_id ) . '" class="um-sortable-item"><span class="um-field-icon"><i class="um-faicon-sort"></i></span>' . $content . '</li>'; } $html .= '</ul>'; return $html; } /** * @param $field_data * * @return bool|string */ function render_datepicker( $field_data ) { if ( empty( $field_data['id'] ) ) { return false; } $id = ( ! empty( $this->form_data['prefix_id'] ) ? $this->form_data['prefix_id'] : '' ) . '_' . $field_data['id']; $id_attr = ' id="' . esc_attr( $id ) . '" '; $class = ! empty( $field_data['class'] ) ? $field_data['class'] : ''; $class .= ! empty( $field_data['size'] ) ? 'um-' . $field_data['size'] . '-field' : 'um-long-field'; $class_attr = ' class="um-forms-field ' . esc_attr( $class ) . '" '; $data = array( 'field_id' => $field_data['id'] ); $data_attr = ''; foreach ( $data as $key => $value ) { $data_attr .= ' data-' . $key . '="' . esc_attr( $value ) . '" '; } $placeholder_attr = ! empty( $field_data['placeholder'] ) ? ' placeholder="' . esc_attr( $field_data['placeholder'] ) . '"' : ''; $name = $field_data['id']; $name = ! empty( $this->form_data['prefix_id'] ) ? $this->form_data['prefix_id'] . '[' . $name . ']' : $name; $name_attr = ' name="' . $name . '" '; $value = $this->get_field_value( $field_data ); $value_attr = ' value="' . $value . '" '; $html = "<input type=\"date\" $id_attr $class_attr $name_attr $data_attr $value_attr $placeholder_attr />"; return $html; } /** * @param $field_data * * @return bool|string */ function render_inline_texts( $field_data ) { if ( empty( $field_data['id1'] ) ) { return false; } $i = 1; $fields = array(); while( ! empty( $field_data['id' . $i] ) ) { $id = ( ! empty( $this->form_data['prefix_id'] ) ? $this->form_data['prefix_id'] : '' ) . '_' . $field_data['id'. $i]; $id_attr = ' id="' . $id . '" '; $class = ! empty( $field_data['class'] ) ? $field_data['class'] : ''; $class .= ! empty( $field_data['size'] ) ? 'um-' . $field_data['size'] . '-field' : 'um-long-field'; $class_attr = ' class="um-forms-field ' . esc_attr( $class ) . '" '; $data = array( 'field_id' => $field_data[ 'id'. $i ] ); $data_attr = ''; foreach ( $data as $key => $value ) { $data_attr .= ' data-' . $key . '="' . esc_attr( $value ) . '" '; } $placeholder_attr = ! empty( $field_data['placeholder'] ) ? ' placeholder="' . $field_data['placeholder'] . '"' : ''; $name = $field_data[ 'id'. $i ]; $name = ! empty( $this->form_data['prefix_id'] ) ? $this->form_data['prefix_id'] . '[' . $name . ']' : $name; $name_attr = ' name="' . $name . '" '; $value = $this->get_field_value( $field_data, $i ); $value_attr = ' value="' . $value . '" '; $fields[$i] = "<input type=\"text\" $id_attr $class_attr $name_attr $data_attr $value_attr $placeholder_attr style=\"display:inline;\"/>"; $i++; } $html = vsprintf( $field_data['mask'], $fields ); return $html; } /** * @param $field_data * * @return bool|string */ function render_textarea( $field_data ) { if ( empty( $field_data['id'] ) ) { return false; } $id = ( ! empty( $this->form_data['prefix_id'] ) ? $this->form_data['prefix_id'] : '' ) . '_' . $field_data['id']; $id_attr = ' id="' . esc_attr( $id ) . '" '; $class = ! empty( $field_data['class'] ) ? $field_data['class'] : ''; $class .= ! empty( $field_data['size'] ) ? $field_data['size'] : 'um-long-field'; $class_attr = ' class="um-forms-field ' . esc_attr( $class ) . '" '; $data = array( 'field_id' => $field_data['id'] ); $data_attr = ''; foreach ( $data as $key => $value ) { $data_attr .= ' data-' . $key . '="' . esc_attr( $value ) . '" '; } $rows = ! empty( $field_data['args']['textarea_rows'] ) ? ' rows="' . $field_data['args']['textarea_rows'] . '" ' : ''; $name = $field_data['id']; $name = ! empty( $this->form_data['prefix_id'] ) ? $this->form_data['prefix_id'] . '[' . $name . ']' : $name; $name_attr = ' name="' . $name . '" '; $value = $this->get_field_value( $field_data ); $html = "<textarea $id_attr $class_attr $name_attr $data_attr $rows>$value</textarea>"; return $html; } /** * @param $field_data * * @return bool|string */ function render_wp_editor( $field_data ) { if ( empty( $field_data['id'] ) ) { return false; } $id = ( ! empty( $this->form_data['prefix_id'] ) ? $this->form_data['prefix_id'] : '' ) . '_' . $field_data['id']; $class = ! empty( $field_data['class'] ) ? $field_data['class'] : ''; $class .= ! empty( $field_data['size'] ) ? $field_data['size'] : 'um-long-field'; $data = array( 'field_id' => $field_data['id'] ); $data_attr = ''; foreach ( $data as $key => $value ) { $data_attr .= ' data-' . $key . '="' . esc_attr( $value ) . '" '; } $name = $field_data['id']; $name = ! empty( $this->form_data['prefix_id'] ) ? $this->form_data['prefix_id'] . '[' . $name . ']' : $name; $value = $this->get_field_value( $field_data ); add_filter( 'wp_default_editor', array( &$this, 'set_default_editor_fix' ) ); ob_start(); wp_editor( $value, $id, array( 'textarea_name' => $name, 'textarea_rows' => 20, 'editor_height' => 425, 'wpautop' => false, 'media_buttons' => false, 'editor_class' => $class, ) ); $html = ob_get_clean(); remove_filter( 'wp_default_editor', array( &$this, 'set_default_editor_fix' ) ); return $html; } /** * Fix the displaying wp_editor on macOS * * @return string */ public function set_default_editor_fix() { return 'html'; } /** * @param $field_data * * @return bool|string */ public function render_checkbox( $field_data ) { if ( empty( $field_data['id'] ) ) { return false; } $id = ( ! empty( $this->form_data['prefix_id'] ) ? $this->form_data['prefix_id'] : '' ) . '_' . $field_data['id']; $id_attr = ' id="' . esc_attr( $id ) . '" '; $id_attr_hidden = ' id="' . esc_attr( $id ) . '_hidden" '; $class = ! empty( $field_data['class'] ) ? $field_data['class'] : ''; $class .= ! empty( $field_data['size'] ) ? $field_data['size'] : 'um-long-field'; $class_attr = ' class="um-forms-field ' . esc_attr( $class ) . '" '; $data = array( 'field_id' => $field_data['id'], ); if ( ! empty( $field_data['data'] ) ) { $data = array_merge( $data, $field_data['data'] ); } $data_attr = ''; foreach ( $data as $key => $value ) { $data_attr .= ' data-' . $key . '="' . esc_attr( $value ) . '" '; } $name = $field_data['id']; $name = ! empty( $this->form_data['prefix_id'] ) ? $this->form_data['prefix_id'] . '[' . $name . ']' : $name; $name_attr = ' name="' . $name . '" '; $value = $this->get_field_value( $field_data ); $checkbox_label = ! empty( $field_data['checkbox_label'] ) ? $field_data['checkbox_label'] : ''; $field_html = "<input type=\"checkbox\" $id_attr $class_attr $name_attr $data_attr " . checked( $value, true, false ) . " value=\"1\" " . disabled( ! empty( $field_data['disabled'] ), true, false ) . " />"; if ( '' !== $checkbox_label ) { $field_html = "<label>$field_html $checkbox_label</label>"; } $html = "<input type=\"hidden\" $id_attr_hidden $name_attr value=\"0\" " . disabled( ! empty( $field_data['disabled'] ), true, false ) . " />{$field_html}"; return apply_filters( 'um_admin_render_checkbox_field_html', $html, $field_data ); } /** * @param $field_data * * @return bool|string */ public function render_same_page_update( $field_data ) { if ( empty( $field_data['id'] ) ) { return false; } $id = ( ! empty( $this->form_data['prefix_id'] ) ? $this->form_data['prefix_id'] : '' ) . '_' . $field_data['id']; $id_attr = ' id="' . esc_attr( $id ) . '" '; $id_attr_hidden = ' id="' . esc_attr( $id ) . '_hidden" '; $class = ! empty( $field_data['class'] ) ? $field_data['class'] : ''; $class .= ! empty( $field_data['size'] ) ? $field_data['size'] : 'um-long-field'; $class_attr = ' class="um-forms-field ' . esc_attr( $class ) . '" '; $data = array( 'field_id' => $field_data['id'], ); if ( ! empty( $field_data['data'] ) ) { $data = array_merge( $data, $field_data['data'] ); } $data_attr = ''; foreach ( $data as $key => $value ) { $data_attr .= ' data-' . $key . '="' . esc_attr( $value ) . '" '; } if ( ! empty( $field_data['upgrade_cb'] ) ) { $data_attr .= ' data-log-object="' . esc_attr( $field_data['upgrade_cb'] ) . '" '; } $name = $field_data['id']; $name = ! empty( $this->form_data['prefix_id'] ) ? $this->form_data['prefix_id'] . '[' . $name . ']' : $name; $name_attr = ' name="' . $name . '" '; $value = $this->get_field_value( $field_data ); $checkbox_label = ! empty( $field_data['checkbox_label'] ) ? $field_data['checkbox_label'] : ''; $field_html = "<input type=\"checkbox\" $id_attr $class_attr $name_attr $data_attr " . checked( $value, true, false ) . " value=\"1\" " . disabled( ! empty( $field_data['disabled'] ), true, false ) . " />"; if ( '' !== $checkbox_label ) { $field_html = "<label>$field_html $checkbox_label</label>"; } $html = "<input type=\"hidden\" $id_attr_hidden $name_attr value=\"0\" " . disabled( ! empty( $field_data['disabled'] ), true, false ) . " />{$field_html}"; if ( ! empty( $field_data['upgrade_cb'] ) ) { $html .= '<div class="um-same-page-update-wrapper um-same-page-update-' . esc_attr( $field_data['upgrade_cb'] ) . '"><div class="um-same-page-update-description">' . $field_data['upgrade_description'] . '</div><input type="button" data-upgrade_cb="' . $field_data['upgrade_cb'] . '" class="button button-primary um-admin-form-same-page-update" value="' . esc_attr__( 'Run', 'ultimate-member' ) . '"/> <div class="upgrade_log"></div></div>'; } return $html; } /** * @param $field_data * * @return bool|string */ function render_select( $field_data ) { if ( empty( $field_data['id'] ) ) { return false; } $multiple = ! empty( $field_data['multi'] ) ? 'multiple' : ''; $id = ( ! empty( $this->form_data['prefix_id'] ) ? $this->form_data['prefix_id'] : '' ) . '_' . $field_data['id']; $id_attr = ' id="' . esc_attr( $id ) . '" '; $class = ! empty( $field_data['class'] ) ? $field_data['class'] . ' ' : ' '; $class .= ! empty( $field_data['size'] ) ? 'um-' . $field_data['size'] . '-field' : 'um-long-field'; $class_attr = ' class="um-forms-field ' . esc_attr( $class ) . '" '; $data = array( 'field_id' => $field_data['id'] ); $data_attr = ''; foreach ( $data as $key => $value ) { $data_attr .= ' data-' . $key . '="' . esc_attr( $value ) . '" '; } $name = $field_data['id']; $name = ! empty( $this->form_data['prefix_id'] ) ? $this->form_data['prefix_id'] . '[' . $name . ']' : $name; $hidden_name_attr = ' name="' . $name . '" '; $name = $name . ( ! empty( $field_data['multi'] ) ? '[]' : '' ); $name_attr = ' name="' . $name . '" '; $value = $this->get_field_value( $field_data ); $options = ''; if ( ! empty( $field_data['options'] ) ) { foreach ( $field_data['options'] as $key => $option ) { if ( ! empty( $field_data['multi'] ) ) { if ( ! is_array( $value ) || empty( $value ) ) { $value = array(); } $options .= '<option value="' . $key . '" ' . selected( in_array( $key, $value ), true, false ) . '>' . esc_html( $option ) . '</option>'; } else { $options .= '<option value="' . $key . '" ' . selected( (string)$key == $value, true, false ) . '>' . esc_html( $option ) . '</option>'; } } } $hidden = ''; if ( ! empty( $multiple ) ) { $hidden = "<input type=\"hidden\" $hidden_name_attr value=\"\" />"; } $html = "$hidden<select $multiple $id_attr $name_attr $class_attr $data_attr>$options</select>"; return $html; } /** * @param $field_data * * @since 2.8.3 * * @return bool|string */ public function render_page_select( $field_data ) { if ( empty( $field_data['id'] ) ) { return false; } $multiple = ! empty( $field_data['multi'] ) ? 'multiple' : ''; $id = ( ! empty( $this->form_data['prefix_id'] ) ? sanitize_title( $this->form_data['prefix_id'] ) : '' ) . '_' . $field_data['id']; $id_attr = ' id="' . esc_attr( $id ) . '" '; $class = ! empty( $field_data['class'] ) ? $field_data['class'] . ' ' : ' '; $class .= ! empty( $field_data['size'] ) ? 'um-' . $field_data['size'] . '-field' : 'um-long-field'; $class_attr = ' class="um-forms-field um-pages-select2 ' . esc_attr( $class ) . '" '; $data = array( 'field_id' => $field_data['id'], ); if ( ! empty( $field_data['placeholder'] ) ) { $data['placeholder'] = $field_data['placeholder']; } $data_attr = ''; foreach ( $data as $key => $value ) { $data_attr .= ' data-' . $key . '="' . esc_attr( $value ) . '" '; } $name = $field_data['id']; $name = ! empty( $this->form_data['prefix_id'] ) ? $this->form_data['prefix_id'] . '[' . $name . ']' : $name; $hidden_name_attr = ' name="' . $name . '" '; $name = $name . ( ! empty( $field_data['multi'] ) ? '[]' : '' ); $name_attr = ' name="' . $name . '" '; $value = $this->get_field_value( $field_data ); $options = '<option value="">' . esc_html( $data['placeholder'] ) . '</option>'; if ( ! empty( $field_data['options'] ) ) { foreach ( $field_data['options'] as $key => $option ) { if ( ! empty( $field_data['multi'] ) ) { if ( ! is_array( $value ) || empty( $value ) ) { $value = array(); } $options .= '<option value="' . $key . '" ' . selected( in_array( $key, $value ), true, false ) . '>' . esc_html( $option ) . '</option>'; } else { $options .= '<option value="' . $key . '" ' . selected( (string)$key == $value, true, false ) . '>' . esc_html( $option ) . '</option>'; } } } $hidden = ''; if ( ! empty( $multiple ) ) { $hidden = "<input type=\"hidden\" $hidden_name_attr value=\"\" />"; } $button = ''; if ( ! array_key_exists( 'predefined', $field_data ) || false !== $field_data['predefined'] ) { $slug = str_replace( 'core_', '', $field_data['id'] ); if ( ! um_get_predefined_page_id( $slug ) || 'publish' !== get_post_status( um_get_predefined_page_id( $slug ) ) ) { $button = ' <a href="' . esc_url( add_query_arg( array( 'um_adm_action' => 'install_predefined_page', 'um_page_slug' => $slug, '_wpnonce' => wp_create_nonce( 'install_predefined_page' ), ) ) ) . '" class="button button-primary">' . esc_html__( 'Create Default', 'ultimate-member' ) . '</a>'; } } $html = "$hidden<select $multiple $id_attr $name_attr $class_attr $data_attr>$options</select>$button"; return $html; } /** * @param $field_data * * @return bool|string */ function render_multi_selects( $field_data ) { if ( empty( $field_data['id'] ) ) { return false; } $id = ( ! empty( $this->form_data['prefix_id'] ) ? $this->form_data['prefix_id'] : '' ) . '_' . $field_data['id']; $sorting = ! empty( $field_data['sorting'] ) ? $field_data['sorting'] : false; $class = ! empty( $field_data['class'] ) ? $field_data['class'] : ''; $class .= ! empty( $field_data['size'] ) ? $field_data['size'] : 'um-long-field'; $class .= ! empty( $sorting ) ? 'um-sorting-enabled' : ''; $class_attr = ' class="um-forms-field ' . $class . '" '; $data = array( 'field_id' => $field_data['id'], 'id_attr' => $id ); $data_attr = ''; foreach ( $data as $key => $value ) { $data_attr .= ' data-' . $key . '="' . esc_attr( $value ) . '" '; } $name = $field_data['id']; $name = ! empty( $this->form_data['prefix_id'] ) ? $this->form_data['prefix_id'] . '[' . $name . ']' : $name; $name = "{$name}[]"; $name_attr = ' name="' . $name . '" '; $values = $this->get_field_value( $field_data ); $options = ''; foreach ( $field_data['options'] as $key => $option ) { $options .= '<option value="' . $key . '">' . $option . '</option>'; } $html = "<select class=\"um-hidden-multi-selects\" $data_attr>$options</select>"; $html .= "<ul class=\"um-multi-selects-list" . ( ! empty( $sorting ) ? ' um-sortable-multi-selects' : '' ) . "\" $data_attr>"; if ( $sorting && is_array( $values ) ) { ksort( $values ); } if ( ! empty( $values ) && is_array( $values ) ) { foreach ( $values as $k => $value ) { if ( ! in_array( $value, array_keys( $field_data['options'] ) ) ) { continue ; } $id_attr = ' id="' . esc_attr( $id . '-' . $k ) . '" '; $options = ''; foreach ( $field_data['options'] as $key => $option ) { $options .= '<option value="' . $key . '" ' . selected( $key == $value, true, false ) . '>' . $option . '</option>'; } $html .= '<li class="um-multi-selects-option-line' . ( ! empty( $sorting ) ? ' um-admin-drag-fld' : '' ) . '">'; if ( $sorting ) { $html .= '<span class="um-field-icon"><i class="um-faicon-sort"></i></span>'; } $html .= "<span class=\"um-field-wrapper\"> <select $id_attr $name_attr $class_attr $data_attr>$options</select></span> <span class=\"um-field-control\"><a href=\"javascript:void(0);\" class=\"um-select-delete\">" . __( 'Remove', 'ultimate-member' ) . "</a></span></li>"; } } elseif ( ! empty( $field_data['show_default_number'] ) && is_numeric( $field_data['show_default_number'] ) && $field_data['show_default_number'] > 0 ) { $i = 0; while ( $i < $field_data['show_default_number'] ) { $id_attr = ' id="' . $id . '-' . $i . '" '; $options = ''; foreach ( $field_data['options'] as $key => $option ) { $options .= '<option value="' . $key . '">' . $option . '</option>'; } $html .= '<li class="um-multi-selects-option-line' . ( ! empty( $sorting ) ? ' um-admin-drag-fld' : '' ) . '">'; if ( $sorting ) { $html .= '<span class="um-field-icon"><i class="um-faicon-sort"></i></span>'; } $html .= "<span class=\"um-field-wrapper\"> <select $id_attr $name_attr $class_attr $data_attr>$options</select></span> <span class=\"um-field-control\"><a href=\"javascript:void(0);\" class=\"um-select-delete\">" . __( 'Remove', 'ultimate-member' ) . "</a></span></li>"; $i++; } } $html .= "</ul><a href=\"javascript:void(0);\" class=\"button button-primary um-multi-selects-add-option\" data-name=\"$name\">{$field_data['add_text']}</a>"; return $html; } /** * @param $field_data * * @return bool|string */ function render_multi_checkbox( $field_data ) { if ( empty( $field_data['id'] ) ) { return false; } $id = ( ! empty( $this->form_data['prefix_id'] ) ? $this->form_data['prefix_id'] : '' ) . '_' . $field_data['id']; $class = ! empty( $field_data['class'] ) ? $field_data['class'] : ''; $class .= ! empty( $field_data['size'] ) ? $field_data['size'] : 'um-long-field'; $class_attr = ' class="um-forms-field ' . esc_attr( $class ) . '" '; $name = $field_data['id']; $name = ! empty( $this->form_data['prefix_id'] ) ? $this->form_data['prefix_id'] . '[' . $name . ']' : $name; $values = $this->get_field_value( $field_data ); if ( empty( $values ) ) { $values = array(); } $i = 0; $html = ''; $columns = ( ! empty( $field_data['columns'] ) && is_numeric( $field_data['columns'] ) ) ? $field_data['columns'] : 1; while ( $i < $columns ) { $per_page = ceil( count( $field_data['options'] ) / $columns ); $section_fields_per_page = array_slice( $field_data['options'], $i * $per_page, $per_page, true ); $html .= '<span class="um-form-fields-section" style="width:' . floor( 100 / $columns ) . '% !important;">'; foreach ( $section_fields_per_page as $k => $title ) { $id_attr = ' id="' . esc_attr( $id . '_' . $k ) . '" '; $for_attr = ' for="' . esc_attr( $id . '_' . $k ) . '" '; if ( ! empty( $field_data['assoc'] ) ) { $name_attr = ' name="' . esc_attr( $name ) . '[]" '; $value_attr = ' value="' . esc_attr( $k ) . '" '; } else { $name_attr = ' name="' . esc_attr( $name ) . '[' . esc_attr( $k ) . ']" '; $value_attr = ' value="1" '; } $disabed_attr = ''; $data = array( 'field_id' => $field_data['id'] . '_' . $k, ); if ( ! empty( $field_data['data'] ) ) { $data = array_merge( $data, $field_data['data'] ); } $data_attr = ''; foreach ( $data as $key => $value ) { if ( 'checkbox_key' === $value ) { $value = $k; } $data_attr .= ' data-' . $key . '="' . esc_attr( $value ) . '" '; } if ( isset( $field_data['options_disabled'] ) && in_array( $k, $field_data['options_disabled'], true ) ) { $disabed_attr = 'disabled="disabled"'; } $html .= "<label $for_attr> <input type=\"checkbox\" " . checked( in_array( $k, $values, true ), true, false ) . "$disabed_attr $id_attr $name_attr $data_attr $value_attr $class_attr> <span>$title</span> </label>"; } $html .= '</span>'; $i++; } return $html; } /** * @param $field_data * * @return bool|string */ function render_multi_text( $field_data ) { if ( empty( $field_data['id'] ) ) { return false; } $id = ( ! empty( $this->form_data['prefix_id'] ) ? $this->form_data['prefix_id'] : '' ) . '_' . $field_data['id']; $size = ! empty( $field_data['size'] ) ? 'um-' . $field_data['size'] . '-field' : 'um-long-field'; $class = ! empty( $field_data['class'] ) ? $field_data['class'] : ''; $class_attr = ' class="um-forms-field ' . esc_attr( $class ) . '" '; $data = array( 'field_id' => $field_data['id'], 'id_attr' => $id, 'item_class' => "um-multi-text-option-line {$size}", ); $data_attr = ''; foreach ( $data as $key => $value ) { $data_attr .= ' data-' . $key . '="' . esc_attr( $value ) . '" '; } $name = $field_data['id']; $name = ! empty( $this->form_data['prefix_id'] ) ? $this->form_data['prefix_id'] . '[' . $name . ']' : $name; $name = "{$name}[]"; $name_attr = ' name="' . $name . '" '; $values = $this->get_field_value( $field_data ); $html = "<input type=\"text\" class=\"um-hidden-multi-text\" $data_attr />"; $html .= "<ul class=\"um-multi-text-list\" $data_attr>"; if ( ! empty( $values ) ) { foreach ( $values as $k => $value ) { $value = esc_attr( $value ); $id_attr = ' id="' . esc_attr( $id . '-' . $k ) . '" '; $html .= "<li class=\"um-multi-text-option-line {$size}\"><span class=\"um-field-wrapper\"> <input type=\"text\" $id_attr $name_attr $class_attr $data_attr value=\"$value\" /></span> <span class=\"um-field-control\"><a href=\"javascript:void(0);\" class=\"um-text-delete\">" . __( 'Remove', 'ultimate-member' ) . "</a></span></li>"; } } elseif ( ! empty( $field_data['show_default_number'] ) && is_numeric( $field_data['show_default_number'] ) && $field_data['show_default_number'] > 0 ) { $i = 0; while( $i < $field_data['show_default_number'] ) { $id_attr = ' id="' . esc_attr( $id . '-' . $i ) . '" '; $html .= "<li class=\"um-multi-text-option-line {$size}\"><span class=\"um-field-wrapper\"> <input type=\"text\" $id_attr $name_attr $class_attr $data_attr value=\"\" /></span> <span class=\"um-field-control\"><a href=\"javascript:void(0);\" class=\"um-text-delete\">" . __( 'Remove', 'ultimate-member' ) . "</a></span></li>"; $i++; } } $html .= "</ul><a href=\"javascript:void(0);\" class=\"button button-primary um-multi-text-add-option\" data-name=\"$name\">{$field_data['add_text']}</a>"; return $html; } /** * @param $field_data * * @return bool|string */ function render_media( $field_data ) { if ( empty( $field_data['id'] ) ) { return false; } $id = ( ! empty( $this->form_data['prefix_id'] ) ? $this->form_data['prefix_id'] : '' ) . '_' . $field_data['id']; $class = ! empty( $field_data['class'] ) ? $field_data['class'] : ''; $class .= ! empty( $field_data['size'] ) ? $field_data['size'] : 'um-long-field'; $class_attr = ' class="um-forms-field um-media-upload-data-url ' . $class . '"'; $data = array( 'field_id' => $field_data['id'] . '_url', ); if ( ! empty( $field_data['default']['url'] ) ) { $data['default'] = esc_attr( $field_data['default']['url'] ); } $data_attr = ''; foreach ( $data as $key => $value ) { $data_attr .= " data-{$key}=\"{$value}\" "; } $name = $field_data['id']; $name = ! empty( $this->form_data['prefix_id'] ) ? $this->form_data['prefix_id'] . '[' . $name . ']' : $name; $value = $this->get_field_value( $field_data ); $upload_frame_title = ! empty( $field_data['upload_frame_title'] ) ? $field_data['upload_frame_title'] : __( 'Select media', 'ultimate-member' ); $image_id = ! empty( $value['id'] ) ? $value['id'] : ''; $image_width = ! empty( $value['width'] ) ? $value['width'] : ''; $image_height = ! empty( $value['height'] ) ? $value['height'] : ''; $image_thumbnail = ! empty( $value['thumbnail'] ) ? $value['thumbnail'] : ''; $image_url = ! empty( $value['url'] ) ? $value['url'] : ''; $wrapper_classes = array(); if ( ! isset( $field_data['preview'] ) || false !== $field_data['preview'] ) { $wrapper_classes[] = 'um-media-preview-enabled'; } $wrapper_classes = implode( ' ', $wrapper_classes ); $wrapper_classes = ! empty( $wrapper_classes ) ? ' ' . $wrapper_classes : ''; $html = '<div class="um-media-upload' . $wrapper_classes . '">' . "<input type=\"hidden\" class=\"um-media-upload-data-id\" name=\"{$name}[id]\" id=\"{$id}_id\" value=\"$image_id\">" . "<input type=\"hidden\" class=\"um-media-upload-data-width\" name=\"{$name}[width]\" id=\"{$id}_width\" value=\"$image_width\">" . "<input type=\"hidden\" class=\"um-media-upload-data-height\" name=\"{$name}[height]\" id=\"{$id}_height\" value=\"$image_height\">" . "<input type=\"hidden\" class=\"um-media-upload-data-thumbnail\" name=\"{$name}[thumbnail]\" id=\"{$id}_thumbnail\" value=\"$image_thumbnail\">" . "<input type=\"hidden\" $class_attr name=\"{$name}[url]\" id=\"{$id}_url\" value=\"$image_url\" $data_attr>"; if ( ! isset( $field_data['preview'] ) || $field_data['preview'] !== false ) { $html .= '<img src="' . $image_url . '" alt="" class="icon_preview"><div style="clear:both;"></div>'; } if ( ! empty( $field_data['url'] ) ) { $html .= '<input type="text" class="um-media-upload-url" readonly value="' . $image_url . '" /><div style="clear:both;"></div>'; } $html .= '<input type="button" class="um-set-image button button-primary" value="' . esc_attr__( 'Select', 'ultimate-member' ) . '" data-upload_frame="' . $upload_frame_title . '" /> <input type="button" class="um-clear-image button" value="' . esc_attr__( 'Clear', 'ultimate-member' ) . '" /></div>'; return $html; } /** * @param $field_data * * @return bool|string */ function render_email_template( $field_data ) { if ( empty( $field_data['id'] ) ) { return false; } $id = ( ! empty( $this->form_data['prefix_id'] ) ? $this->form_data['prefix_id'] : '' ) . '_' . $field_data['id']; $class = ! empty( $field_data['class'] ) ? $field_data['class'] : ''; $class .= ! empty( $field_data['size'] ) ? $field_data['size'] : 'um-long-field'; $data = array( 'field_id' => $field_data['id'] ); $data_attr = ''; foreach ( $data as $key => $value ) { $data_attr .= ' data-' . $key . '="' . esc_attr( $value ) . '" '; } $name = $field_data['id']; $name = ! empty( $this->form_data['prefix_id'] ) ? $this->form_data['prefix_id'] . '[' . $name . ']' : $name; $value = $this->get_field_value( $field_data ); ob_start(); ?> <div class="email_template_wrapper <?php echo $field_data['in_theme'] ? 'in_theme' : '' ?>" data-key="<?php echo $field_data['id'] ?>" style="position: relative;"> <?php wp_editor( $value, $id, array( 'textarea_name' => $name, 'textarea_rows' => 20, 'editor_height' => 425, 'wpautop' => false, 'media_buttons' => false, 'editor_class' => $class ) ); ?> <span class="description">For default text for plain-text emails please see this <a href="https://docs.ultimatemember.com/article/1342-plain-text-email-default-templates#<?php echo $field_data['id'] ?>" target="_blank">doc</a></span> </div> <?php $html = ob_get_clean(); return $html; } /** * @param $field_data * * @return bool|string */ function render_ajax_button( $field_data ) { if ( empty( $field_data['id'] ) ) return false; $id = ( ! empty( $this->form_data['prefix_id'] ) ? $this->form_data['prefix_id'] : '' ) . '_' . $field_data['id']; $id_attr = ' id="' . esc_attr( $id ) . '" '; $class = ! empty( $field_data['class'] ) ? $field_data['class'] : ''; $class_attr = ' class="um-forms-field button ' . esc_attr( $class ) . '" '; $data = array( 'field_id' => $field_data['id'] ); $data_attr = ''; foreach ( $data as $key => $value ) { $data_attr .= ' data-' . $key . '="' . esc_attr( $value ) . '" '; } $name = $field_data['id']; $name = ! empty( $this->form_data['prefix_id'] ) ? $this->form_data['prefix_id'] . '[' . $name . ']' : $name; $name_attr = ' name="' . $name . '" '; $value = $this->get_field_value( $field_data ); $value_attr = ' value="' . $value . '" '; $html = "<input type=\"button\" $id_attr $class_attr $name_attr $data_attr $value_attr /><div class='clear'></div><div class='um_setting_ajax_button_response'></div>"; return $html; } /** * @param $field_data * * @return mixed */ function render_info_text( $field_data ) { return $field_data['value']; } /** * @param $field_data * * @return string */ function render_md_default_filters( $field_data ) { if ( empty( $field_data['id'] ) ) { return false; } global $post; $id = ( ! empty( $this->form_data['prefix_id'] ) ? $this->form_data['prefix_id'] : '' ) . '_' . $field_data['id']; $class = ! empty( $field_data['class'] ) ? $field_data['class'] : ''; $class .= ! empty( $field_data['size'] ) ? $field_data['size'] : 'um-long-field'; $class_attr = ' class="um-forms-field ' . $class . '" '; $data = array( 'field_id' => $field_data['id'], 'id_attr' => $id, 'member_directory' => $post->ID ); $data_attr = ''; foreach ( $data as $key => $value ) { $data_attr .= ' data-' . $key . '="' . esc_attr( $value ) . '" '; } $name = $field_data['id']; $name = ! empty( $this->form_data['prefix_id'] ) ? $this->form_data['prefix_id'] . '[' . $name . ']' : $name; $name = "{$name}[]"; $name_attr = ' name="' . $name . '" '; $values = $this->get_field_value( $field_data ); if ( is_array( $values ) ) { $filters = array_keys( $values ); } $options = ''; foreach ( $field_data['options'] as $key => $option ) { $options .= '<option value="' . $key . '">' . $option . '</option>'; } $html = "<input type=\"hidden\" name=\"um-gmt-offset\" /><select class=\"um-hidden-md-default-filters\" $data_attr>$options</select>"; $html .= "<ul class=\"um-md-default-filters-list\" $data_attr>"; if ( ! empty( $filters ) && is_array( $filters ) ) { foreach ( $filters as $k => $value ) { if ( ! in_array( $value, array_keys( $field_data['options'] ) ) ) { continue ; } $id_attr = ' id="' . esc_attr( $id . '-' . $k ) . '" '; $options = ''; foreach ( $field_data['options'] as $key => $option ) { $options .= '<option value="' . $key . '" ' . selected( $key == $value, true, false ) . '>' . $option . '</option>'; } $html .= "<li class=\"um-md-default-filters-option-line\"><span class=\"um-field-wrapper\"> <select $id_attr $name_attr $class_attr $data_attr>$options</select></span> <span class=\"um-field-control\"><a href=\"javascript:void(0);\" class=\"um-select-delete\">" . __( 'Remove', 'ultimate-member' ) . "</a></span><span class=\"um-field-wrapper2 um\">" . UM()->member_directory()->show_filter( $value, array( 'form_id' => $post->ID ), $values[ $value ], true ) . "</span></li>"; } } elseif ( ! empty( $field_data['show_default_number'] ) && is_numeric( $field_data['show_default_number'] ) && $field_data['show_default_number'] > 0 ) { $i = 0; while ( $i < $field_data['show_default_number'] ) { $id_attr = ' id="' . $id . '-' . $i . '" '; $options = ''; foreach ( $field_data['options'] as $key => $option ) { $options .= '<option value="' . $key . '">' . $option . '</option>'; } $html .= "<li class=\"um-md-default-filters-option-line\"><span class=\"um-field-wrapper\"> <select $id_attr $name_attr $class_attr $data_attr>$options</select></span> <span class=\"um-field-control\"><a href=\"javascript:void(0);\" class=\"um-select-delete\">" . __( 'Remove', 'ultimate-member' ) . "</a></span></li>"; $i++; } } $html .= "</ul><a href=\"javascript:void(0);\" class=\"button button-primary um-md-default-filters-add-option\" data-name=\"$name\">{$field_data['add_text']}</a>"; return $html; } /** * @param $field_data * * @return string */ function render_md_sorting_fields( $field_data ) { if ( empty( $field_data['id'] ) ) { return false; } $id = ( ! empty( $this->form_data['prefix_id'] ) ? $this->form_data['prefix_id'] : '' ) . '_' . $field_data['id']; $sorting = ! empty( $field_data['sorting'] ) ? $field_data['sorting'] : false; $class = ! empty( $field_data['class'] ) ? $field_data['class'] : ''; $class .= ! empty( $field_data['size'] ) ? $field_data['size'] : 'um-long-field'; $class .= ! empty( $sorting ) ? 'um-sorting-enabled' : ''; $class_attr = ' class="um-forms-field ' . $class . '" '; $data = array( 'field_id' => $field_data['id'], 'id_attr' => $id ); $data_attr = ''; foreach ( $data as $key => $value ) { $data_attr .= ' data-' . $key . '="' . esc_attr( $value ) . '" '; } $name = $field_data['id']; $name = ! empty( $this->form_data['prefix_id'] ) ? $this->form_data['prefix_id'] . '[' . $name . ']' : $name; $name = "{$name}[]"; $name_attr = ' name="' . $name . '" '; $values = $this->get_field_value( $field_data ); $options = ''; foreach ( $field_data['options'] as $key => $option ) { $options .= '<option value="' . $key . '">' . $option . '</option>'; } $html = "<select class=\"um-hidden-multi-selects\" $data_attr>$options</select>"; $html .= "<ul class=\"um-multi-selects-list" . ( ! empty( $sorting ) ? ' um-sortable-multi-selects' : '' ) . "\" $data_attr>"; if ( $sorting && is_array( $values ) ) { ksort( $values ); } if ( ! empty( $values ) && is_array( $values ) ) { foreach ( $values as $k => $value ) { $other_key = ''; $other_label = ''; $other_type = ''; $other_order = ''; if ( is_array( $value ) ) { $keys = array_keys( $value ); $other_key = $keys[0]; if ( ! empty( $value['label'] ) ) { $other_label = $value['label']; } else { $labels = array_values( $value ); $other_label = $labels[0]; } if ( ! empty( $value['type'] ) ) { $other_type = $value['type']; } if ( ! empty( $value['order'] ) ) { $other_order = $value['order']; } } else { if ( ! array_key_exists( $value, $field_data['options'] ) ) { continue; } } $id_attr = ' id="' . esc_attr( $id . '-' . $k ) . '" '; $options = ''; foreach ( $field_data['options'] as $key => $option ) { if ( is_array( $value ) ) { $selected = selected( 'other' === $key, true, false ); } else { $selected = selected( $key == $value, true, false ); } $options .= '<option value="' . $key . '" ' . $selected . '>' . $option . '</option>'; } $html .= '<li class="um-multi-selects-option-line' . ( ! empty( $sorting ) ? ' um-admin-drag-fld' : '' ) . '">'; if ( $sorting ) { $html .= '<span class="um-field-icon"><i class="um-faicon-sort"></i></span>'; } $data_types_html = ''; foreach ( UM()->member_directory()->sort_data_types as $type_key => $type_label ) { $data_types_html .= '<option value="' . esc_attr( $type_key ) . '" ' . selected( $other_type, $type_key, false ) . '>' . esc_html( $type_label ) . '</option>'; } $html .= '<span class="um-field-wrapper"> <select ' . $id_attr . ' ' . $name_attr . ' ' . $class_attr . ' ' . $data_attr . '>' . $options . '</select></span> <span class="um-field-control"><a href="javascript:void(0);" class="um-select-delete">' . __( 'Remove', 'ultimate-member' ) . '</a></span> <span class="um-field-wrapper um-custom-order-fields"><label>' . __( 'Meta key', 'ultimate-member' ) . ': <input type="text" name="um_metadata[_um_sorting_fields][other_data][' . $k . '][meta_key]" value="' . esc_attr( $other_key ) . '" /></label></span> <span class="um-field-wrapper um-custom-order-fields"><label>' . __( 'Data type', 'ultimate-member' ) . ': <select name="um_metadata[_um_sorting_fields][other_data][' . $k . '][data_type]" />' . $data_types_html . '</select></label></span> <span class="um-field-wrapper um-custom-order-fields"><label>' . __( 'Order', 'ultimate-member' ) . ': <select name="um_metadata[_um_sorting_fields][other_data][' . $k . '][order]" /> <option value="ASC" ' . selected( $other_order, 'ASC', false ) . '>' . __( 'ASC', 'ultimate-member' ) . '</option> <option value="DESC" ' . selected( $other_order, 'DESC', false ) . '>' . __( 'DESC', 'ultimate-member' ) . '</option> </select></label></span> <span class="um-field-wrapper um-custom-order-fields"><label>' . __( 'Label', 'ultimate-member' ) . ': <input type="text" name="um_metadata[_um_sorting_fields][other_data][' . $k . '][label]" value="' . esc_attr( $other_label ) . '" /></label></span> </li>'; } } elseif ( ! empty( $field_data['show_default_number'] ) && is_numeric( $field_data['show_default_number'] ) && $field_data['show_default_number'] > 0 ) { $i = 0; while ( $i < $field_data['show_default_number'] ) { $id_attr = ' id="' . $id . '-' . $i . '" '; $options = ''; foreach ( $field_data['options'] as $key => $option ) { $options .= '<option value="' . $key . '">' . $option . '</option>'; } $html .= '<li class="um-multi-selects-option-line' . ( ! empty( $sorting ) ? ' um-admin-drag-fld' : '' ) . '">'; if ( $sorting ) { $html .= '<span class="um-field-icon"><i class="um-faicon-sort"></i></span>'; } $html .= "<span class=\"um-field-wrapper\"> <select $id_attr $name_attr $class_attr $data_attr>$options</select></span> <span class=\"um-field-control\"><a href=\"javascript:void(0);\" class=\"um-select-delete\">" . __( 'Remove', 'ultimate-member' ) . "</a></span> <span class=\"um-field-wrapper um-custom-order-fields\"><label>" . __( 'Meta key', 'ultimate-member' ) . ": <input type=\"text\" name=\"um_metadata[_um_sorting_fields][other_data][" . $i . "][meta_key]\" value=\"\" /></label></span> <span class=\"um-field-wrapper um-custom-order-fields\"><label>" . __( 'Label', 'ultimate-member' ) . ": <input type=\"text\" name=\"um_metadata[_um_sorting_fields][other_data][" . $i . "][label]\" value=\"\" /></label></span> </li>"; $i++; } } $html .= "</ul><a href=\"javascript:void(0);\" class=\"button button-primary um-multi-selects-add-option\" data-name=\"$name\">{$field_data['add_text']}</a>"; return $html; } /** * Get field value * * @param array $field_data * @param string $i * @return string|array */ function get_field_value( $field_data, $i = '' ) { $default = ''; if ( $field_data['type'] === 'multi_checkbox' ) { $default = array(); if ( isset( $field_data['default'] ) ) { $default = is_array( $field_data['default'] ) ? $field_data['default'] : array( $field_data['default'] ); } } if ( isset( $field_data[ 'default' . $i ] ) ) { $default = $field_data[ 'default' . $i ]; } if ( $field_data['type'] == 'checkbox' || $field_data['type'] == 'multi_checkbox' ) { $value = ( isset( $field_data[ 'value' . $i ] ) && '' !== $field_data[ 'value' . $i ] ) ? $field_data[ 'value' . $i ] : $default; } else { $value = isset( $field_data[ 'value' . $i ] ) ? $field_data[ 'value' . $i ] : $default; } $value = is_string( $value ) ? stripslashes( $value ) : $value; return $value; } public function render_external_link( $data ) { $defaults = array( 'url' => '', 'html' => '', ); $data = wp_parse_args( $data, $defaults ); if ( empty( $data['url'] ) || empty( $data['html'] ) ) { return ''; } ob_start(); ?> <a target="_blank" href="<?php echo esc_url( $data['url'] ); ?>"> <?php echo esc_html( $data['html'] ); ?> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24" class="um-external-link-icon" aria-hidden="true" focusable="false"><path d="M19.5 4.5h-7V6h4.44l-5.97 5.97 1.06 1.06L18 7.06v4.44h1.5v-7Zm-13 1a2 2 0 0 0-2 2v10a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2v-3H17v3a.5.5 0 0 1-.5.5h-10a.5.5 0 0 1-.5-.5v-10a.5.5 0 0 1 .5-.5h3V5.5h-3Z"></path></svg> </a> <?php return ob_get_clean(); } } } includes/admin/core/class-admin-settings.php 0000644 00000460036 15252504435 0015152 0 ustar 00 <?php namespace um\admin\core; use DateTimeZone; if ( ! defined( 'ABSPATH' ) ) { exit; } if ( ! class_exists( 'um\admin\core\Admin_Settings' ) ) { /** * Class Admin_Settings * @package um\admin\core */ class Admin_Settings { /** * @var array */ public $settings_map; /** * @var array */ public $settings_structure; /** * @var */ private $previous_licenses; /** * @var */ private $need_change_permalinks; private $gravatar_changed = false; /** * Admin_Settings constructor. */ public function __construct() { //init settings structure add_action( 'admin_init', array( &$this, 'init_variables' ), 9 ); // settings structure handlers add_action( 'um_settings_page_before_email__content', array( $this, 'settings_before_email_tab' ) ); add_filter( 'um_settings_section_custom_fields', array( $this, 'email_section_custom_fields' ), 10, 2 ); add_filter( 'um_settings_form_section_advanced_override_templates_override_templates_custom_content', array( $this, 'settings_override_templates_tab' ) ); //custom content for licenses tab add_filter( 'um_settings_section_licenses__custom_content', array( $this, 'settings_licenses_tab' ), 10, 3 ); add_filter( 'um_settings_structure', array( $this, 'sorting_licenses_options' ), 9999, 1 ); //save handlers add_action( 'admin_init', array( $this, 'save_settings_handler' ), 10 ); //save pages options add_action( 'um_settings_before_save', array( $this, 'check_permalinks_changes' ) ); add_action( 'um_settings_save', array( $this, 'on_settings_save' ) ); add_filter( 'um_change_settings_before_save', array( $this, 'save_email_templates' ) ); //save licenses options add_action( 'um_settings_before_save', array( $this, 'before_licenses_save' ) ); add_action( 'um_settings_save', array( $this, 'licenses_save' ) ); add_filter( 'um_change_settings_before_save', array( $this, 'set_default_if_empty' ), 9, 1 ); add_filter( 'um_change_settings_before_save', array( $this, 'remove_empty_values' ), 10, 1 ); } public function same_page_update_ajax() { UM()->admin()->check_ajax_nonce(); if ( empty( $_POST['cb_func'] ) ) { wp_send_json_error( __( 'Wrong callback', 'ultimate-member' ) ); } $cb_func = sanitize_key( $_POST['cb_func'] ); if ( 'um_usermeta_fields' === $cb_func ) { //first install metatable global $wpdb; $metakeys = array(); foreach ( UM()->builtin()->all_user_fields as $all_user_field ) { if ( ! array_key_exists( 'metakey', $all_user_field ) ) { continue; } $metakeys[] = $all_user_field['metakey']; } $metakeys = apply_filters( 'um_metadata_same_page_update_ajax', $metakeys, UM()->builtin()->all_user_fields ); if ( is_multisite() ) { $sites = get_sites( array( 'fields' => 'ids' ) ); foreach ( $sites as $blog_id ) { $metakeys[] = $wpdb->get_blog_prefix( $blog_id ) . 'capabilities'; $metakeys[] = 'wc_money_spent_' . rtrim( $wpdb->get_blog_prefix( $blog_id ), '_' ); // Is used since Woocommerce 9.1.0 $metakeys[] = 'wc_order_count_' . rtrim( $wpdb->get_blog_prefix( $blog_id ), '_' ); // Is used since Woocommerce 9.1.0 TODO remove as soon as used 'um_wc_order_count_' } } else { $blog_id = get_current_blog_id(); $metakeys[] = $wpdb->get_blog_prefix( $blog_id ) . 'capabilities'; $metakeys[] = 'wc_money_spent_' . rtrim( $wpdb->get_blog_prefix( $blog_id ), '_' ); // Is used since Woocommerce 9.1.0 $metakeys[] = 'wc_order_count_' . rtrim( $wpdb->get_blog_prefix( $blog_id ), '_' ); // Is used since Woocommerce 9.1.0 TODO remove as soon as used 'um_wc_order_count_' } // Member directory data $metakeys[] = 'um_member_directory_data'; $metakeys[] = '_um_verified'; $metakeys[] = '_money_spent'; // Legacy since Woocommerce 9.1.0. TODO remove as soon as stop support Woo below 9.1.0 version $metakeys[] = '_completed'; $metakeys[] = '_reviews_avg'; //myCred meta if ( function_exists( 'mycred_get_types' ) ) { $mycred_types = mycred_get_types(); if ( ! empty( $mycred_types ) ) { foreach ( array_keys( $mycred_types ) as $point_type ) { $metakeys[] = $point_type; } } } $sortby_custom_keys = $wpdb->get_col( "SELECT DISTINCT meta_value FROM {$wpdb->postmeta} WHERE meta_key='_um_sortby_custom'" ); if ( empty( $sortby_custom_keys ) ) { $sortby_custom_keys = array(); } $sortby_custom_keys2 = $wpdb->get_col( "SELECT meta_value FROM {$wpdb->postmeta} WHERE meta_key='_um_sorting_fields'" ); if ( ! empty( $sortby_custom_keys2 ) ) { foreach ( $sortby_custom_keys2 as $custom_val ) { $custom_val = maybe_unserialize( $custom_val ); foreach ( $custom_val as $sort_value ) { if ( is_array( $sort_value ) ) { $field_keys = array_keys( $sort_value ); $sortby_custom_keys[] = $field_keys[0]; } } } } if ( ! empty( $sortby_custom_keys ) ) { $sortby_custom_keys = array_unique( $sortby_custom_keys ); $metakeys = array_merge( $metakeys, $sortby_custom_keys ); } $skip_fields = UM()->builtin()->get_fields_without_metakey(); $skip_fields = array_merge( $skip_fields, UM()->member_directory()::$core_search_fields ); $real_usermeta = $wpdb->get_col( "SELECT DISTINCT meta_key FROM {$wpdb->usermeta}" ); $real_usermeta = ! empty( $real_usermeta ) ? $real_usermeta : array(); $real_usermeta = array_merge( $real_usermeta, array( 'um_member_directory_data' ) ); if ( ! empty( $sortby_custom_keys ) ) { $real_usermeta = array_merge( $real_usermeta, $sortby_custom_keys ); } $wp_usermeta_option = array_intersect( array_diff( $metakeys, $skip_fields ), $real_usermeta ); update_option( 'um_usermeta_fields', array_values( $wp_usermeta_option ) ); update_option( 'um_member_directory_update_meta', time() ); UM()->options()->update( 'member_directory_own_table', true ); wp_send_json_success(); } elseif ( 'um_get_metadata' === $cb_func ) { global $wpdb; $wp_usermeta_option = get_option( 'um_usermeta_fields', array() ); $count = $wpdb->get_var( "SELECT COUNT(*) FROM {$wpdb->usermeta} WHERE meta_key IN ('" . implode( "','", $wp_usermeta_option ) . "')" ); wp_send_json_success( array( 'count' => $count ) ); } elseif ( 'um_update_metadata_per_page' === $cb_func ) { if ( empty( $_POST['page'] ) ) { wp_send_json_error( __( 'Wrong data', 'ultimate-member' ) ); } $per_page = 500; $wp_usermeta_option = get_option( 'um_usermeta_fields', array() ); global $wpdb; $metadata = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM {$wpdb->usermeta} WHERE meta_key IN ('" . implode( "','", $wp_usermeta_option ) . "') LIMIT %d, %d", ( absint( $_POST['page'] ) - 1 ) * $per_page, $per_page ), ARRAY_A ); $values = array(); foreach ( $metadata as $metarow ) { $values[] = $wpdb->prepare( '(%d, %s, %s)', $metarow['user_id'], $metarow['meta_key'], $metarow['meta_value'] ); } // maybe create table. $table_name = $wpdb->prefix . 'um_metadata'; $query = $wpdb->prepare( 'SHOW TABLES LIKE %s', $wpdb->esc_like( $table_name ) ); if ( $wpdb->get_var( $query ) !== $table_name ) { UM()->setup()->create_db(); } if ( ! empty( $values ) ) { $wpdb->query( "INSERT INTO {$wpdb->prefix}um_metadata(user_id, um_key, um_value) VALUES " . implode( ',', $values ) ); } $from = ( absint( $_POST['page'] ) * $per_page ) - $per_page + 1; $to = absint( $_POST['page'] ) * $per_page; // translators: %1$s is a metadata from name; %2$s is a metadata to. wp_send_json_success( array( 'message' => sprintf( __( 'Metadata from %1$s to %2$s was upgraded successfully...', 'ultimate-member' ), $from, $to ) ) ); } else { do_action( 'um_same_page_update_ajax_action', $cb_func ); } } /** * */ public function init_variables() { $settings_map = array(); $general_pages_fields = array( array( 'id' => 'pages_settings', 'type' => 'hidden', 'value' => true, 'is_option' => false, ), ); foreach ( UM()->config()->get( 'predefined_pages' ) as $slug => $page ) { $page_id = UM()->options()->get_predefined_page_option_key( $slug ); $page_title = ! empty( $page['title'] ) ? $page['title'] : ''; $options = array(); $page_value = ''; $pre_result = apply_filters( 'um_admin_settings_pages_list_value', false, $page_id ); if ( false === $pre_result ) { if ( ! empty( $opt_value = UM()->options()->get( $page_id ) ) ) { if ( 'publish' === get_post_status( $opt_value ) ) { $title = get_the_title( $opt_value ); $title = ( mb_strlen( $title ) > 50 ) ? mb_substr( $title, 0, 49 ) . '...' : $title; $title = sprintf( __( '%1$s (ID: %2$s)', 'ultimate-member' ), $title, $opt_value ); $options = array( $opt_value => $title ); $page_value = $opt_value; } } } else { // `page_value` variable that we transfer from 3rd-party hook for getting filtered option value also $page_value = $pre_result['page_value']; unset( $pre_result['page_value'] ); $options = $pre_result; } $page_setting_description = ''; if ( ! empty( $page_value ) ) { $content = get_the_content( null, false, $page_value ); switch ( $slug ) { case 'account': if ( $page_value === um_get_predefined_page_id( 'user' ) ) { $page_setting_description = __( '<strong>Warning:</strong> Account page and User page must be separate pages.', 'ultimate-member' ); } elseif ( ! has_shortcode( $content, 'ultimatemember_account' ) ) { $page_setting_description = __( '<strong>Warning:</strong> Account page must contain shortcode <code>[ultimatemember_account]</code>.', 'ultimate-member' ); } elseif ( function_exists( 'wc_get_page_id' ) && wc_get_page_id( 'myaccount' ) === um_get_predefined_page_id( 'account' ) ) { $page_setting_description = __( '<strong>Warning:</strong> Account page and WooCommerce "My account" page should be separate pages.', 'ultimate-member' ); } break; case 'login': if ( $page_value === um_get_predefined_page_id( 'logout' ) ) { $page_setting_description = __( '<strong>Warning:</strong> Login page and Logout page must be separate pages.', 'ultimate-member' ); } elseif ( ! has_shortcode( $content, 'ultimatemember' ) ) { $page_setting_description = __( '<strong>Warning:</strong> Login page must contain a login form shortcode. You can get existing shortcode or create a new one <a href="edit.php?post_type=um_form" target="_blank">here</a>.', 'ultimate-member' ); } break; case 'logout': if ( $page_value === (int) get_option( 'page_on_front' ) ) { $page_setting_description = __( '<strong>Warning:</strong> Home page and Logout page must be separate pages.', 'ultimate-member' ); } elseif ( $page_value === um_get_predefined_page_id( 'login' ) ) { $page_setting_description = __( '<strong>Warning:</strong> Login page and Logout page must be separate pages.', 'ultimate-member' ); } break; case 'password-reset': if ( ! has_shortcode( $content, 'ultimatemember_password' ) ) { $page_setting_description = __( '<strong>Warning:</strong> Password Reset page must contain shortcode <code>[ultimatemember_password]</code>.', 'ultimate-member' ); } break; case 'register': if ( ! has_shortcode( $content, 'ultimatemember' ) ) { $page_setting_description = __( '<strong>Warning:</strong> Register page must contain a registration form shortcode. You can get existing shortcode or create a new one <a href="edit.php?post_type=um_form" target="_blank">here</a>.', 'ultimate-member' ); } break; case 'user': if ( $page_value === um_get_predefined_page_id( 'account' ) ) { $description = __( '<strong>Warning:</strong> Account page and User page must be separate pages.', 'ultimate-member' ); } elseif ( ! has_shortcode( $content, 'ultimatemember' ) ) { $page_setting_description = __( '<strong>Warning:</strong> User page must contain a profile form shortcode. You can get existing shortcode or create a new one <a href="edit.php?post_type=um_form" target="_blank">here</a>.', 'ultimate-member' ); } break; case 'members': if ( ! has_shortcode( $content, 'ultimatemember' ) ) { $page_setting_description = __( '<strong>Warning:</strong> Members page must contain a member directory shortcode. You can get existing shortcode or create a new one <a href="edit.php?post_type=um_directory" target="_blank">here</a>.', 'ultimate-member' ); } break; default: $page_setting_description = apply_filters( 'um_pages_settings_description', $page_setting_description, $content, $slug ); break; } } $general_pages_fields[] = array( 'id' => $page_id, 'type' => 'page_select', // translators: %s: Page title 'label' => sprintf( __( '%s page', 'ultimate-member' ), $page_title ), 'options' => $options, 'value' => $page_value, 'placeholder' => __( 'Choose a page...', 'ultimate-member' ), 'size' => 'small', 'description' => $page_setting_description, ); $settings_map[ $page_id ] = array( 'sanitize' => 'absint', ); } $appearances_profile_menu_fields = array( array( 'id' => 'profile_menu', 'type' => 'checkbox', 'label' => __( 'Profile menu', 'ultimate-member' ), 'checkbox_label' => __( 'Enable profile menu', 'ultimate-member' ), ), ); $settings_map['profile_menu'] = array( 'sanitize' => 'bool', ); $tabs = UM()->profile()->tabs(); $tabs_options = array(); $tabs_condition = array(); foreach ( $tabs as $id => $tab ) { if ( ! empty( $tab['hidden'] ) ) { continue; } if ( isset( $tab['name'] ) ) { $tabs_options[ $id ] = $tab['name']; $tabs_condition[] = 'profile_tab_' . $id; } if ( isset( $tab['default_privacy'] ) ) { $fields = array( array( 'id' => 'profile_tab_' . $id, 'type' => 'checkbox', // translators: %s: Tab title 'label' => sprintf( __( '%s Tab', 'ultimate-member' ), $tab['name'] ), // translators: %s: Tab title 'checkbox_label' => sprintf( __( 'Enable %s Tab', 'ultimate-member' ), $tab['name'] ), 'conditional' => array( 'profile_menu', '=', 1 ), 'data' => array( 'fill_profile_menu_default_tab' => $id ), ), ); $settings_map[ 'profile_tab_' . $id ] = array( 'sanitize' => 'bool', ); } else { $fields = array( array( 'id' => 'profile_tab_' . $id, 'type' => 'checkbox', // translators: %s: Tab title 'label' => sprintf( __( '%s Tab', 'ultimate-member' ), $tab['name'] ), 'checkbox_label' => sprintf( __( 'Enable %s Tab', 'ultimate-member' ), $tab['name'] ), 'conditional' => array( 'profile_menu', '=', 1 ), 'data' => array( 'fill_profile_menu_default_tab' => $id ), ), array( 'id' => 'profile_tab_' . $id . '_privacy', 'type' => 'select', // translators: %s: Tab title 'label' => sprintf( __( 'Who can see %s Tab?', 'ultimate-member' ), $tab['name'] ), 'description' => __( 'Select which users can view this tab.', 'ultimate-member' ), 'options' => UM()->profile()->tabs_privacy(), 'conditional' => array( 'profile_tab_' . $id, '=', 1 ), 'size' => 'small', ), array( 'id' => 'profile_tab_' . $id . '_roles', 'type' => 'select', 'multi' => true, 'label' => __( 'Allowed roles', 'ultimate-member' ), 'description' => __( 'Select the the user roles allowed to view this tab.', 'ultimate-member' ), 'options' => UM()->roles()->get_roles(), 'placeholder' => __( 'Choose user roles...', 'ultimate-member' ), 'conditional' => array( 'profile_tab_' . $id . '_privacy', '=', array( '4', '5' ) ), 'size' => 'small', ), ); $settings_map = array_merge( $settings_map, array( "profile_tab_{$id}" => array( 'sanitize' => 'bool', ), "profile_tab_{$id}_privacy" => array( 'sanitize' => array( UM()->admin(), 'sanitize_tabs_privacy' ), ), "profile_tab_{$id}_roles" => array( 'sanitize' => array( UM()->admin(), 'sanitize_existed_role' ), ), ) ); } $appearances_profile_menu_fields = array_merge( $appearances_profile_menu_fields, $fields ); } $appearances_profile_menu_fields[] = array( 'id' => 'profile_menu_default_tab', 'type' => 'select', 'label' => __( 'Profile menu default tab', 'ultimate-member' ), 'description' => __( 'This will be the default tab on user profile page.', 'ultimate-member' ), 'options' => $tabs_options, 'conditional' => array( implode( '|', $tabs_condition ), '~', 1 ), 'size' => 'small', ); $settings_map['profile_menu_default_tab'] = array( 'sanitize' => 'key', ); $appearances_profile_menu_fields = array_merge( $appearances_profile_menu_fields, array( array( 'id' => 'profile_menu_icons', 'type' => 'checkbox', 'label' => __( 'Menu icons in desktop view', 'ultimate-member' ), 'checkbox_label' => __( 'Enable menu icons in desktop view', 'ultimate-member' ), 'description' => __( '"Desktop view" means the profile block\'s width lower than 800px.', 'ultimate-member' ), 'conditional' => array( 'profile_menu', '=', 1 ), ), ) ); $settings_map['profile_menu_icons'] = array( 'sanitize' => 'bool', ); $post_types_options = array(); $all_post_types = get_post_types( array( 'public' => true ), 'objects' ); foreach ( $all_post_types as $key => $post_type_data ) { $post_types_options[ $key ] = $post_type_data->labels->singular_name; } $duplicates = array(); $taxonomies_options = array(); $exclude_taxonomies = UM()->excluded_taxonomies(); $all_taxonomies = get_taxonomies( array( 'public' => true, 'show_ui' => true, ), 'objects' ); foreach ( $all_taxonomies as $key => $taxonomy ) { if ( in_array( $key, $exclude_taxonomies, true ) ) { continue; } if ( ! in_array( $taxonomy->labels->singular_name, $duplicates, true ) ) { $duplicates[] = $taxonomy->labels->singular_name; $label = $taxonomy->labels->singular_name; } else { $label = $taxonomy->labels->singular_name . ' (' . $key . ')'; } $taxonomies_options[ $key ] = $label; } $restricted_access_post_metabox_value = array(); $restricted_access_post_metabox = UM()->options()->get( 'restricted_access_post_metabox' ); if ( ! empty( $restricted_access_post_metabox ) && is_array( $restricted_access_post_metabox ) ) { foreach ( $restricted_access_post_metabox as $key => $value ) { if ( $value ) { $restricted_access_post_metabox_value[] = $key; } } } $restricted_access_taxonomy_metabox_value = array(); $restricted_access_taxonomy_metabox = UM()->options()->get( 'restricted_access_taxonomy_metabox' ); if ( ! empty( $restricted_access_taxonomy_metabox ) && is_array( $restricted_access_taxonomy_metabox ) ) { foreach ( $restricted_access_taxonomy_metabox as $key => $value ) { if ( $value ) { $restricted_access_taxonomy_metabox_value[] = $key; } } } $access_fields = array( array( 'id' => 'accessible', 'type' => 'select', 'label' => __( 'Global Site Access', 'ultimate-member' ), 'description' => __( 'Globally control the access of your site, you can have separate restrict options per post/page by editing the desired item.', 'ultimate-member' ), 'options' => array( 0 => __( 'Site accessible to Everyone', 'ultimate-member' ), 2 => __( 'Site accessible to Logged In Users', 'ultimate-member' ), ), 'size' => 'medium', ), array( 'id' => 'access_redirect', 'type' => 'text', 'label' => __( 'Custom Redirect URL', 'ultimate-member' ), 'description' => __( 'A logged out user will be redirected to this url If he is not permitted to access the site.', 'ultimate-member' ), 'conditional' => array( 'accessible', '=', 2 ), ), array( 'id' => 'access_exclude_uris', 'type' => 'multi_text', 'label' => __( 'Exclude the following URLs', 'ultimate-member' ), 'description' => __( 'Here you can exclude URLs beside the redirect URI to be accessible to everyone.', 'ultimate-member' ), 'add_text' => __( 'Add New URL', 'ultimate-member' ), 'conditional' => array( 'accessible', '=', 2 ), 'show_default_number' => 0, ), array( 'id' => 'home_page_accessible', 'type' => 'checkbox', 'label' => __( 'Allow Homepage to be accessible', 'ultimate-member' ), 'checkbox_label' => __( 'Accessible Homepage', 'ultimate-member' ), 'conditional' => array( 'accessible', '=', 2 ), ), array( 'id' => 'category_page_accessible', 'type' => 'checkbox', 'label' => __( 'Allow Category pages to be accessible', 'ultimate-member' ), 'checkbox_label' => __( 'Accessible Category pages', 'ultimate-member' ), 'conditional' => array( 'accessible', '=', 2 ), ), array( 'id' => 'restricted_post_title_replace', 'type' => 'checkbox', 'label' => __( 'Restricted Post Title', 'ultimate-member' ), 'checkbox_label' => __( 'Replace the restricted Post Title', 'ultimate-member' ), 'description' => __( 'Allow to replace the restricted post title to users that do not have permission to view the content.', 'ultimate-member' ), ), array( 'id' => 'restricted_access_post_title', 'type' => 'text', 'label' => __( 'Restricted Access Post Title', 'ultimate-member' ), 'description' => __( 'If enabled, the text entered below will replace the title of the post/page/CPT for users who do not have permission to view the restricted content. Please see this doc for more information on this.', 'ultimate-member' ), 'conditional' => array( 'restricted_post_title_replace', '=', 1 ), ), array( 'id' => 'restricted_access_message', 'type' => 'wp_editor', 'label' => __( 'Restricted Access Message', 'ultimate-member' ), 'description' => __( 'This is the message shown to users that do not have permission to view the content.', 'ultimate-member' ), ), ); $settings_map = array_merge( $settings_map, array( 'accessible' => array( 'sanitize' => 'int', ), 'access_redirect' => array( 'sanitize' => 'url', ), 'access_exclude_uris' => array( 'sanitize' => 'url', ), 'home_page_accessible' => array( 'sanitize' => 'bool', ), 'category_page_accessible' => array( 'sanitize' => 'bool', ), 'restricted_post_title_replace' => array( 'sanitize' => 'bool', ), 'restricted_access_post_title' => array( 'sanitize' => 'text', ), 'restricted_access_message' => array( 'sanitize' => 'wp_kses', ), ) ); global $wp_version; if ( version_compare( $wp_version, '5.0', '>=' ) ) { $access_fields = array_merge( $access_fields, array( array( 'id' => 'restricted_blocks', 'type' => 'checkbox', 'label' => __( 'Restricted Gutenberg Blocks', 'ultimate-member' ), 'checkbox_label' => __( 'Enable the "Content Restriction" settings for the Gutenberg Blocks', 'ultimate-member' ), 'description' => __( 'If enabled then allows to set the blocks restriction settings in wp-admin.', 'ultimate-member' ), ), array( 'id' => 'restricted_block_message', 'type' => 'wp_editor', 'label' => __( 'Restricted Access Block Message', 'ultimate-member' ), 'description' => __( 'This is the message shown to users that do not have permission to view the block\'s content.', 'ultimate-member' ), 'conditional' => array( 'restricted_blocks', '=', 1 ), ), ) ); $settings_map['restricted_blocks'] = array( 'sanitize' => 'bool', ); $settings_map['restricted_block_message'] = array( 'sanitize' => 'wp_kses', ); } $access_fields = array_merge( $access_fields, array( array( 'id' => 'restricted_access_post_metabox', 'type' => 'hidden', 'value' => '', ), array( 'id' => 'restricted_access_taxonomy_metabox', 'type' => 'hidden', 'value' => '', ), array( 'id' => 'restricted_access_post_metabox', 'type' => 'multi_checkbox', 'label' => __( 'Enable the "Content Restriction" settings for post types', 'ultimate-member' ), 'description' => __( 'Check post types for which you plan to use the "Content Restriction" settings.', 'ultimate-member' ), 'options' => $post_types_options, 'columns' => 3, 'value' => $restricted_access_post_metabox_value, 'default' => UM()->options()->get_default( 'restricted_access_post_metabox' ), ), array( 'id' => 'restricted_access_taxonomy_metabox', 'type' => 'multi_checkbox', 'label' => __( 'Enable the "Content Restriction" settings for taxonomies', 'ultimate-member' ), 'description' => __( 'Check taxonomies for which you plan to use the "Content Restriction" settings.', 'ultimate-member' ), 'options' => $taxonomies_options, 'columns' => 3, 'value' => $restricted_access_taxonomy_metabox_value, 'default' => UM()->options()->get_default( 'restricted_access_taxonomy_metabox' ), ), ) ); $settings_map = array_merge( $settings_map, array( 'restricted_access_post_metabox' => array( 'sanitize' => 'key', ), 'restricted_access_taxonomy_metabox' => array( 'sanitize' => 'key', ), ) ); $latest_update = get_option( 'um_member_directory_update_meta', false ); $latest_truncate = get_option( 'um_member_directory_truncated', false ); $same_page_update = array( 'id' => 'member_directory_own_table', 'type' => 'same_page_update', 'label' => __( 'Custom usermeta table', 'ultimate-member' ), 'checkbox_label' => __( 'Enable custom table for usermeta', 'ultimate-member' ), 'description' => __( 'Check this box if you would like to enable the use of a custom table for user metadata. Improved performance for member directory searches.', 'ultimate-member' ), ); if ( empty( $latest_update ) || ( ! empty( $latest_truncate ) && $latest_truncate > $latest_update ) ) { $same_page_update['upgrade_cb'] = 'sync_metatable'; $same_page_update['upgrade_description'] = '<p>' . __( 'We recommend creating a backup of your site before running the update process. Do not exit the page before the update process has complete.', 'ultimate-member' ) . '</p> <p>' . __( 'After clicking the <strong>"Run"</strong> button, the update process will start. All information will be displayed in the field below.', 'ultimate-member' ) . '</p> <p>' . __( 'If the update was successful, you will see a corresponding message. Otherwise, contact technical support if the update failed.', 'ultimate-member' ) . '</p>'; } $settings_map = array_merge( $settings_map, array( 'permalink_base' => array( 'sanitize' => 'key', ), 'permalink_base_custom_meta' => array( 'sanitize' => 'text', ), 'display_name' => array( 'sanitize' => 'key', ), 'display_name_field' => array( 'sanitize' => 'text', ), 'author_redirect' => array( 'sanitize' => 'bool', ), 'members_page' => array( 'sanitize' => 'bool', ), 'use_gravatars' => array( 'sanitize' => 'bool', ), 'use_um_gravatar_default_builtin_image' => array( 'sanitize' => 'key', ), 'use_um_gravatar_default_image' => array( 'sanitize' => 'bool', ), 'admin_ignore_user_status' => array( 'sanitize' => 'bool', ), 'delete_comments' => array( 'sanitize' => 'bool', ), 'toggle_password' => array( 'sanitize' => 'bool', ), 'require_strongpass' => array( 'sanitize' => 'bool', ), 'require_strongpass_special_char' => array( 'sanitize' => 'bool', ), 'password_min_chars' => array( 'sanitize' => 'absint', ), 'password_max_chars' => array( 'sanitize' => 'absint', ), 'profile_noindex' => array( 'sanitize' => 'bool', ), 'activation_link_expiry_time' => array( 'sanitize' => 'empty_absint', ), 'account_tab_password' => array( 'sanitize' => 'bool', ), 'account_tab_privacy' => array( 'sanitize' => 'bool', ), 'account_tab_delete' => array( 'sanitize' => 'bool', ), 'delete_account_text' => array( 'sanitize' => 'textarea', ), 'delete_account_no_pass_required_text' => array( 'sanitize' => 'textarea', ), 'account_name' => array( 'sanitize' => 'bool', ), 'account_name_disable' => array( 'sanitize' => 'bool', ), 'account_name_require' => array( 'sanitize' => 'bool', ), 'account_email' => array( 'sanitize' => 'bool', ), 'account_general_password' => array( 'sanitize' => 'bool', ), 'account_hide_in_directory' => array( 'sanitize' => 'bool', ), 'account_hide_in_directory_default' => array( 'sanitize' => 'text', ), 'profile_photo_max_size' => array( 'sanitize' => 'absint', ), 'cover_photo_max_size' => array( 'sanitize' => 'absint', ), 'photo_thumb_sizes' => array( 'sanitize' => 'absint', ), 'cover_thumb_sizes' => array( 'sanitize' => 'absint', ), 'image_orientation_by_exif' => array( 'sanitize' => 'bool', ), 'image_compression' => array( 'sanitize' => 'absint', ), 'image_max_width' => array( 'sanitize' => 'absint', ), 'cover_min_width' => array( 'sanitize' => 'absint', ), 'enable_reset_password_limit' => array( 'sanitize' => 'bool', ), 'reset_password_limit_number' => array( 'sanitize' => 'absint', ), 'change_password_request_limit' => array( 'sanitize' => 'bool', ), 'only_approved_user_reset_password' => array( 'sanitize' => 'bool', ), 'blocked_emails' => array( 'sanitize' => 'textarea', ), 'blocked_words' => array( 'sanitize' => 'textarea', ), 'allowed_choice_callbacks' => array( 'sanitize' => 'textarea', ), 'allow_url_redirect_confirm' => array( 'sanitize' => 'bool', ), 'admin_email' => array( 'sanitize' => 'text', ), 'mail_from' => array( 'sanitize' => 'text', ), 'mail_from_addr' => array( 'sanitize' => 'text', ), 'email_html' => array( 'sanitize' => 'bool', ), 'profile_template' => array( 'sanitize' => 'text', ), 'profile_max_width' => array( 'sanitize' => 'text', ), 'profile_area_max_width' => array( 'sanitize' => 'text', ), 'profile_icons' => array( 'sanitize' => 'key', ), 'profile_primary_btn_word' => array( 'sanitize' => 'text', ), 'profile_secondary_btn' => array( 'sanitize' => 'bool', ), 'profile_secondary_btn_word' => array( 'sanitize' => 'text', ), 'default_avatar' => array( 'sanitize' => 'url', ), 'default_cover' => array( 'sanitize' => 'url', ), 'disable_profile_photo_upload' => array( 'sanitize' => 'bool', ), 'profile_photosize' => array( 'sanitize' => array( UM()->admin(), 'sanitize_photosize' ), ), 'profile_cover_enabled' => array( 'sanitize' => 'bool', ), 'profile_coversize' => array( 'sanitize' => array( UM()->admin(), 'sanitize_cover_photosize' ), ), 'profile_cover_ratio' => array( 'sanitize' => 'text', ), 'profile_show_metaicon' => array( 'sanitize' => 'bool', ), 'profile_show_name' => array( 'sanitize' => 'bool', ), 'profile_show_social_links' => array( 'sanitize' => 'bool', ), 'profile_show_bio' => array( 'sanitize' => 'bool', ), 'profile_show_html_bio' => array( 'sanitize' => 'bool', ), 'profile_bio_maxchars' => array( 'sanitize' => 'absint', ), 'profile_header_menu' => array( 'sanitize' => 'key', ), 'profile_empty_text' => array( 'sanitize' => 'bool', ), 'profile_empty_text_emo' => array( 'sanitize' => 'bool', ), 'register_template' => array( 'sanitize' => 'text', ), 'register_max_width' => array( 'sanitize' => 'text', ), 'register_align' => array( 'sanitize' => 'key', ), 'register_icons' => array( 'sanitize' => 'key', ), 'register_primary_btn_word' => array( 'sanitize' => 'text', ), 'register_secondary_btn' => array( 'sanitize' => 'bool', ), 'register_secondary_btn_word' => array( 'sanitize' => 'text', ), 'register_secondary_btn_url' => array( 'sanitize' => 'url', ), 'register_role' => array( 'sanitize' => 'key', ), 'login_template' => array( 'sanitize' => 'text', ), 'login_max_width' => array( 'sanitize' => 'text', ), 'login_align' => array( 'sanitize' => 'key', ), 'login_icons' => array( 'sanitize' => 'key', ), 'login_primary_btn_word' => array( 'sanitize' => 'text', ), 'login_secondary_btn' => array( 'sanitize' => 'bool', ), 'login_secondary_btn_word' => array( 'sanitize' => 'text', ), 'login_secondary_btn_url' => array( 'sanitize' => 'url', ), 'login_forgot_pass_link' => array( 'sanitize' => 'bool', ), 'login_show_rememberme' => array( 'sanitize' => 'bool', ), 'form_asterisk' => array( 'sanitize' => 'bool', ), 'profile_title' => array( 'sanitize' => 'text', ), 'profile_desc' => array( 'sanitize' => 'textarea', ), 'um_profile_object_cache_stop' => array( 'sanitize' => 'bool', ), 'enable_blocks' => array( 'sanitize' => 'bool', ), 'enable_as_email_sending' => array( 'sanitize' => 'bool', ), 'disable_restriction_pre_queries' => array( 'sanitize' => 'bool', ), 'um_google_maps_js_api_key' => array( 'sanitize' => 'text', ), 'um_google_lang_as_default' => array( 'sanitize' => 'bool', ), 'um_google_lang' => array( 'sanitize' => 'text', ), 'um_google_maps_api_version' => array( 'sanitize' => 'text', ), 'uninstall_on_delete' => array( 'sanitize' => 'bool', ), 'lock_register_forms' => array( 'sanitize' => 'bool', ), 'display_login_form_notice' => array( 'sanitize' => 'bool', ), 'ajax_nopriv_rate_limit' => array( 'sanitize' => 'bool', ), 'banned_capabilities' => array( 'sanitize' => array( UM()->admin(), 'sanitize_wp_capabilities_assoc' ), ), 'secure_notify_admins_banned_accounts' => array( 'sanitize' => 'bool', ), 'secure_notify_admins_banned_accounts__interval' => array( 'sanitize' => 'key', ), 'secure_allowed_redirect_hosts' => array( 'sanitize' => 'textarea', ), ) ); if ( false !== UM()->account()->is_notifications_tab_visible() ) { $settings_map['account_tab_notifications'] = array( 'sanitize' => 'bool', ); } $this->settings_map = apply_filters( 'um_settings_map', $settings_map ); /** * UM hook * * @type filter * @title um_settings_structure * @description Extend UM Settings * @input_vars * [{"var":"$settings","type":"array","desc":"UM Settings"}] * @change_log * ["Since: 2.0"] * @usage add_filter( 'um_settings_structure', 'function_name', 10, 1 ); * @example * <?php * add_filter( 'um_settings_structure', 'my_settings_structure', 10, 1 ); * function my_settings_structure( $settings ) { * // your code here * return $settings; * } * ?> */ $this->settings_structure = apply_filters( 'um_settings_structure', array( '' => array( 'title' => __( 'General', 'ultimate-member' ), 'sections' => array( '' => array( 'title' => __( 'Pages', 'ultimate-member' ), // translators: %s: Link to UM Docs 'description' => sprintf( __( 'This section enables you to assign a page to one of the core elements necessary for the plugin\'s proper function. The plugin automatically creates and configures the required pages upon installation.<br />You only need to use this tab if you accidentally deleted pages that were automatically created during the initial plugin activation. <a href="%s" target="_blank">Learn more about manually creating pages</a>.', 'ultimate-member' ), 'https://docs.ultimatemember.com/article/1903-creating-plugin-core-pages-manually' ), 'fields' => $general_pages_fields, ), 'users' => array( 'title' => __( 'Users', 'ultimate-member' ), 'form_sections' => array( 'users' => array( 'title' => __( 'Users', 'ultimate-member' ), 'description' => __( 'General users settings.', 'ultimate-member' ), 'fields' => array( array( 'id' => 'register_role', 'type' => 'select', 'label' => __( 'Registration Default Role', 'ultimate-member' ), 'description' => __( 'This will be the role assigned to users registering through Ultimate Member registration forms. By default, this setting will follow the core WordPress setting "New User Default Role" unless you specify a different role.', 'ultimate-member' ), 'default' => um_get_metadefault( 'register_role' ), 'options' => UM()->roles()->get_roles( __( 'Default', 'ultimate-member' ) ), 'size' => 'small', ), array( 'id' => 'permalink_base', 'type' => 'select', 'size' => 'small', 'label' => __( 'Profile Permalink Base', 'ultimate-member' ), // translators: %s: Profile page URL 'description' => sprintf( __( 'Here you can control the permalink structure of the user profile URL globally e.g. %s<strong>username</strong>/.', 'ultimate-member' ), trailingslashit( um_get_core_page( 'user' ) ) ), 'options' => UM()->config()->permalink_base_options, 'placeholder' => __( 'Select...', 'ultimate-member' ), ), array( 'id' => 'permalink_base_custom_meta', 'type' => 'text', 'label' => __( 'Profile Permalink Base Custom Meta Key', 'ultimate-member' ), 'description' => __( 'Specify the custom field meta key that you want to use as profile permalink base. Meta value should be unique.', 'ultimate-member' ), 'conditional' => array( 'permalink_base', '=', 'custom_meta' ), 'size' => 'medium', ), array( 'id' => 'display_name', 'type' => 'select', 'size' => 'medium', 'label' => __( 'User Display Name', 'ultimate-member' ), 'description' => __( 'This is the name that will be displayed for users on the front end of your site. Default setting uses first/last name as display name if it exists.', 'ultimate-member' ), 'options' => UM()->config()->display_name_options, 'placeholder' => __( 'Select...', 'ultimate-member' ), ), array( 'id' => 'display_name_field', 'type' => 'text', 'label' => __( 'Display Name Custom Field(s)', 'ultimate-member' ), 'description' => __( 'Specify the custom field meta key or custom fields seperated by comma that you want to use to display users name on the frontend of your site.', 'ultimate-member' ), 'conditional' => array( 'display_name', '=', 'field' ), 'size' => 'medium', ), array( 'id' => 'author_redirect', 'type' => 'checkbox', 'label' => __( 'Hide author pages', 'ultimate-member' ), 'checkbox_label' => __( 'Enable author page redirect to user profile', 'ultimate-member' ), 'description' => __( 'If enabled, author pages will automatically redirect to the user\'s profile page.', 'ultimate-member' ), ), array( 'id' => 'members_page', 'type' => 'checkbox', 'label' => __( 'Members Directory', 'ultimate-member' ), 'checkbox_label' => __( 'Enable Members Directory', 'ultimate-member' ), 'description' => __( 'Control whether to enable or disable member directories on this site.', 'ultimate-member' ), ), array( 'id' => 'use_gravatars', 'type' => 'checkbox', 'label' => __( 'Use Gravatar', 'ultimate-member' ), 'checkbox_label' => __( 'Enable Gravatar', 'ultimate-member' ), 'description' => __( 'Do you want to use Gravatar instead of the default plugin profile photo (If the user did not upload a custom profile photo/avatar)?', 'ultimate-member' ), ), array( 'id' => 'use_um_gravatar_default_builtin_image', 'type' => 'select', 'label' => __( 'Use Gravatar builtin image', 'ultimate-member' ), 'description' => __( 'Gravatar has a number of built in options which you can also use as defaults.', 'ultimate-member' ), 'options' => array( 'default' => __( 'Default', 'ultimate-member' ), '404' => __( '404 ( File Not Found response )', 'ultimate-member' ), 'mm' => __( 'Mystery Man', 'ultimate-member' ), 'identicon' => __( 'Identicon', 'ultimate-member' ), 'monsterid' => __( 'Monsterid', 'ultimate-member' ), 'wavatar' => __( 'Wavatar', 'ultimate-member' ), 'retro' => __( 'Retro', 'ultimate-member' ), 'blank' => __( 'Blank ( a transparent PNG image )', 'ultimate-member' ), ), 'conditional' => array( 'use_gravatars', '=', 1 ), 'size' => 'medium', ), array( 'id' => 'use_um_gravatar_default_image', 'type' => 'checkbox', 'label' => __( 'Replace Gravatar\'s Default avatar', 'ultimate-member' ), 'checkbox_label' => __( 'Set Default plugin avatar as Gravatar\'s Default avatar', 'ultimate-member' ), 'description' => __( 'Do you want to use the plugin default avatar instead of the gravatar default photo (If the user did not upload a custom profile photo/avatar).', 'ultimate-member' ), 'conditional' => array( 'use_um_gravatar_default_builtin_image', '=', 'default' ), ), array( 'id' => 'admin_ignore_user_status', 'type' => 'checkbox', 'label' => __( 'Ignore the "User Role > Registration Options"', 'ultimate-member' ), 'checkbox_label' => __( 'Automatically approve users from the wp-admin dashboard', 'ultimate-member' ), 'description' => __( 'Ignore registration settings and automatically approve the user if this user is added from the wp-admin dashboard.', 'ultimate-member' ), ), array( 'id' => 'delete_comments', 'type' => 'checkbox', 'label' => __( 'Delete user comments', 'ultimate-member' ), 'checkbox_label' => __( 'Enable deleting user comments after deleting a user', 'ultimate-member' ), 'description' => __( 'Do you want to automatically delete a user\'s comments when they delete their account or are removed from the admin dashboard?', 'ultimate-member' ), ), ), ), 'password' => array( 'title' => __( 'Password', 'ultimate-member' ), 'description' => __( 'Password & Security settings.', 'ultimate-member' ), 'fields' => array( array( 'id' => 'toggle_password', 'type' => 'checkbox', 'label' => __( 'Toggle Password Visibility', 'ultimate-member' ), 'checkbox_label' => __( 'Enable password show/hide icon on password field', 'ultimate-member' ), 'description' => __( 'Enable users to view their inputted password before submitting the form.', 'ultimate-member' ), ), array( 'id' => 'require_strongpass', 'type' => 'checkbox', 'label' => __( 'Require Strong Passwords', 'ultimate-member' ), 'checkbox_label' => __( 'Enable strong passwords', 'ultimate-member' ), 'description' => __( 'Enable this option to apply strong password rules to all password fields (user registration, password reset and password change).', 'ultimate-member' ), ), array( 'id' => 'require_strongpass_special_char', 'type' => 'checkbox', 'label' => __( 'Password requires special character', 'ultimate-member' ), 'checkbox_label' => __( 'Enable special character requirement', 'ultimate-member' ), 'description' => __( 'Require at least one special character (e.g. !@#$%^&*) in passwords.', 'ultimate-member' ), 'conditional' => array( 'require_strongpass', '=', '1' ), ), array( 'id' => 'password_min_chars', 'type' => 'number', 'label' => __( 'Password minimum length', 'ultimate-member' ), 'description' => __( 'Enter the minimum number of characters a user must use for their password. The default minimum characters is 8.', 'ultimate-member' ), 'size' => 'small', 'conditional' => array( 'require_strongpass', '=', '1' ), ), array( 'id' => 'password_max_chars', 'type' => 'number', 'label' => __( 'Password maximum length', 'ultimate-member' ), 'description' => __( 'Enter the maximum number of characters a user can use for their password. The default maximum characters is 30.', 'ultimate-member' ), 'size' => 'small', 'conditional' => array( 'require_strongpass', '=', '1' ), ), array( 'id' => 'activation_link_expiry_time', 'type' => 'number', 'label' => __( 'Email activation link expiration (days)', 'ultimate-member' ), 'description' => __( 'For user registrations requiring email confirmation via a link, how long should the activation link remain active before expiring? If this field is left blank, the activation link will not expire.', 'ultimate-member' ), 'size' => 'small', ), ), ), 'seo' => array( 'title' => __( 'SEO', 'ultimate-member' ), 'description' => __( 'SEO settings for the user profiles.', 'ultimate-member' ), 'fields' => array( array( 'id' => 'profile_noindex', 'type' => 'select', 'size' => 'small', 'label' => __( 'Avoid indexing profile by search engines', 'ultimate-member' ), 'description' => __( 'Hides the profile page for robots. This setting can be overridden by individual role settings.', 'ultimate-member' ), 'options' => array( '0' => __( 'No', 'ultimate-member' ), '1' => __( 'Yes', 'ultimate-member' ), ), ), array( 'id' => 'profile_title', 'type' => 'text', 'label' => __( 'User Profile Title', 'ultimate-member' ), 'description' => __( 'This is the title that is displayed on a specific user profile.', 'ultimate-member' ), 'size' => 'medium', ), array( 'id' => 'profile_desc', 'type' => 'textarea', 'label' => __( 'User Profile Dynamic Meta Description', 'ultimate-member' ), 'description' => __( 'This will be used in the meta description that is available for search-engines.', 'ultimate-member' ), 'args' => array( 'textarea_rows' => 6, ), ), ), ), ), ), 'account' => array( 'title' => __( 'Account', 'ultimate-member' ), 'form_sections' => array( 'account_tab' => array( 'title' => __( 'Main account tab', 'ultimate-member' ), 'description' => __( 'Allows you to control the fields on the main tab of Account page.', 'ultimate-member' ), 'fields' => array( array( 'id' => 'account_name', 'type' => 'checkbox', 'label' => __( 'Display First & Last name fields', 'ultimate-member' ), 'checkbox_label' => __( 'Enable to display First & Last name fields', 'ultimate-member' ), 'description' => __( 'If enabled, the First & Last name fields will be shown on the account page.', 'ultimate-member' ), ), array( 'id' => 'account_name_disable', 'type' => 'checkbox', 'label' => __( 'Disable First & Last name field editing', 'ultimate-member' ), 'checkbox_label' => __( 'Enable to prevent First & Last name editing by users', 'ultimate-member' ), 'description' => __( 'If enabled, this feature will prevent users from changing their first and last names on the account page.', 'ultimate-member' ), 'conditional' => array( 'account_name', '=', '1' ), ), array( 'id' => 'account_name_require', 'type' => 'checkbox', 'label' => __( 'Require First & Last Name', 'ultimate-member' ), 'checkbox_label' => __( 'First and last name fields are required', 'ultimate-member' ), 'description' => __( 'If enabled, users will not be allowed to remove their first or last names when updating their account information.', 'ultimate-member' ), 'conditional' => array( 'account_name', '=', '1' ), ), array( 'id' => 'account_email', 'type' => 'checkbox', 'label' => __( 'Allow users to change email', 'ultimate-member' ), 'checkbox_label' => __( 'Enable changing email via the account page', 'ultimate-member' ), 'description' => __( 'If disabled, users will not be allowed to change their email address on the account page.', 'ultimate-member' ), ), array( 'id' => 'account_general_password', 'type' => 'checkbox', 'label' => __( 'Require password to update account', 'ultimate-member' ), 'checkbox_label' => __( 'Enable required password', 'ultimate-member' ), 'description' => __( 'If enabled, users will need to enter their password when updating their information via the account page.', 'ultimate-member' ), ), ), ), 'password_tab' => array( 'title' => __( 'Change password tab', 'ultimate-member' ), 'description' => __( 'Enables you to toggle the change password tab on the account page.', 'ultimate-member' ), 'fields' => array( array( 'id' => 'account_tab_password', 'type' => 'checkbox', 'label' => __( 'Password Account Tab', 'ultimate-member' ), 'checkbox_label' => __( 'Display password change account tab', 'ultimate-member' ), 'description' => __( 'Enable or disable the "Password" tab on the account page.', 'ultimate-member' ), ), ), ), 'privacy_tab' => array( 'title' => __( 'Privacy tab', 'ultimate-member' ), 'description' => __( 'Enables you to toggle the privacy tab on the account page. Disable this tab to prevent users from altering their privacy settings.', 'ultimate-member' ), 'fields' => array( array( 'id' => 'account_tab_privacy', 'type' => 'checkbox', 'label' => __( 'Privacy Account Tab', 'ultimate-member' ), 'checkbox_label' => __( 'Display privacy account tab', 'ultimate-member' ), 'description' => __( 'Enable or disable the "Privacy" tab on the account page.', 'ultimate-member' ), ), array( 'id' => 'account_hide_in_directory', 'type' => 'checkbox', 'label' => __( 'Allow users to hide their profiles from directory', 'ultimate-member' ), 'checkbox_label' => __( 'Enable users ability to alter their profile visibility in member directories', 'ultimate-member' ), 'description' => __( 'If enabled, this will allow users to change their profile visibility in the member directory from the account page.', 'ultimate-member' ), 'conditional' => array( 'account_tab_privacy', '=', '1' ), ), array( 'id' => 'account_hide_in_directory_default', 'type' => 'select', 'label' => __( 'Hide profiles from directory by default', 'ultimate-member' ), 'description' => __( 'Set the default value for the "Hide my profile from directory" option.', 'ultimate-member' ), 'options' => array( 'No' => __( 'No', 'ultimate-member' ), 'Yes' => __( 'Yes', 'ultimate-member' ), ), 'size' => 'small', 'conditional' => array( 'account_hide_in_directory', '=', '1' ), ), ), ), 'notifications_tab' => array( 'title' => __( 'Notifications tab', 'ultimate-member' ), 'description' => __( 'Enables you to toggle the notifications tab on the account page. Disable this tab to prevent users from altering their notifications settings.', 'ultimate-member' ), 'fields' => array( array( 'id' => 'account_tab_notifications', 'type' => 'checkbox', 'label' => __( 'Notifications Account Tab', 'ultimate-member' ), 'checkbox_label' => __( 'Display notifications account tab', 'ultimate-member' ), 'description' => __( 'Enable or disable the "Notifications" tab on the account page.', 'ultimate-member' ), ), ), ), 'delete_tab' => array( 'title' => __( 'Delete tab', 'ultimate-member' ), 'description' => __( 'Enables you to enable or disable the "Delete Account" tab on the account page. Disable this tab if you wish to prevent users from being able to delete their own accounts.', 'ultimate-member' ), 'fields' => array( array( 'id' => 'account_tab_delete', 'type' => 'checkbox', 'label' => __( 'Delete Account Tab', 'ultimate-member' ), 'checkbox_label' => __( 'Display delete account tab', 'ultimate-member' ), 'description' => __( 'Enable/disable the Delete account tab in account page.', 'ultimate-member' ), ), array( 'id' => 'delete_account_text', 'type' => 'textarea', // bug with wp 4.4? should be editor 'label' => __( 'Account Deletion Text', 'ultimate-member' ), 'description' => __( 'This is the custom text that will be displayed to users before they delete their account from your website when their password is required to confirm account deletion.', 'ultimate-member' ), 'args' => array( 'textarea_rows' => 6, ), 'conditional' => array( 'account_tab_delete', '=', '1' ), ), array( 'id' => 'delete_account_no_pass_required_text', 'type' => 'textarea', 'label' => __( 'Account Deletion Text', 'ultimate-member' ), 'description' => __( 'This is the custom text that will be displayed to users before they delete their account from your website when no password is required to confirm account deletion.', 'ultimate-member' ), 'args' => array( 'textarea_rows' => 6, ), 'conditional' => array( 'account_tab_delete', '=', '1' ), ), ), ), ), ), 'uploads' => array( 'title' => __( 'Uploads', 'ultimate-member' ), 'form_sections' => array( 'uploads' => array( 'title' => __( 'Uploads', 'ultimate-member' ), 'description' => __( 'This page allows you to manage user upload options, enabling you to optimize photos for your site.', 'ultimate-member' ), 'fields' => array( array( 'id' => 'image_orientation_by_exif', 'type' => 'checkbox', 'label' => __( 'Change image orientation', 'ultimate-member' ), 'checkbox_label' => __( 'Enable getting image orientation from EXIF data', 'ultimate-member' ), 'description' => __( 'Rotate image to and use orientation by the camera EXIF data.', 'ultimate-member' ), ), array( 'id' => 'image_compression', 'type' => 'text', 'size' => 'small', 'label' => __( 'Image Quality', 'ultimate-member' ), 'description' => __( 'Quality is used to determine quality of image uploads, and ranges from 0 (worst quality, smaller file) to 100 (best quality, biggest file). The default range is 60.', 'ultimate-member' ), ), array( 'id' => 'image_max_width', 'type' => 'text', 'size' => 'small', 'label' => __( 'Image Upload Maximum Width (px)', 'ultimate-member' ), 'description' => __( 'Any image upload above this width will be resized to this limit automatically.', 'ultimate-member' ), ), ), ), 'profile_photo' => array( 'title' => __( 'Profile photo', 'ultimate-member' ), 'description' => __( 'Allows you to control the profile photos sizes, thumbnails, etc.', 'ultimate-member' ), 'fields' => array( array( 'id' => 'profile_photo_max_size', 'type' => 'text', 'size' => 'small', 'label' => __( 'Profile Photo Maximum File Size (bytes)', 'ultimate-member' ), 'description' => __( 'Sets a maximum size for the uploaded photo.', 'ultimate-member' ), ), array( 'id' => 'photo_thumb_sizes', 'type' => 'multi_text', 'size' => 'small', 'label' => __( 'Profile Photo Thumbnail Sizes (px)', 'ultimate-member' ), 'description' => __( 'Here you can define which thumbnail sizes will be created for each profile photo upload.', 'ultimate-member' ), 'validate' => 'numeric', 'add_text' => __( 'Add New Size', 'ultimate-member' ), 'show_default_number' => 1, ), ), ), 'cover_photo' => array( 'title' => __( 'Cover photo', 'ultimate-member' ), 'description' => __( 'Allows you to control the cover photos sizes, thumbnails, etc.', 'ultimate-member' ), 'fields' => array( array( 'id' => 'cover_photo_max_size', 'type' => 'text', 'size' => 'small', 'label' => __( 'Cover Photo Maximum File Size (bytes)', 'ultimate-member' ), 'description' => __( 'Sets a maximum size for the uploaded cover.', 'ultimate-member' ), ), array( 'id' => 'cover_min_width', 'type' => 'text', 'size' => 'small', 'label' => __( 'Cover Photo Minimum Width (px)', 'ultimate-member' ), 'description' => __( 'This will be the minimum width for cover photo uploads.', 'ultimate-member' ), ), array( 'id' => 'cover_thumb_sizes', 'type' => 'multi_text', 'size' => 'small', 'label' => __( 'Cover Photo Thumbnail Sizes (px)', 'ultimate-member' ), 'description' => __( 'Here you can define which thumbnail sizes will be created for each cover photo upload.', 'ultimate-member' ), 'validate' => 'numeric', 'add_text' => __( 'Add New Size', 'ultimate-member' ), 'show_default_number' => 1, ), ), ), ), ), ), ), 'access' => array( 'title' => __( 'Access', 'ultimate-member' ), 'sections' => array( '' => array( 'title' => __( 'Restriction Content', 'ultimate-member' ), 'description' => __( 'Provides settings for controlling access to your site.', 'ultimate-member' ), 'fields' => $access_fields, ), 'other' => array( 'title' => __( 'Other', 'ultimate-member' ), 'form_sections' => array( 'rp' => array( 'title' => __( 'Reset Password', 'ultimate-member' ), 'description' => __( 'Allows to manage reset password settings.', 'ultimate-member' ), 'fields' => array( array( 'id' => 'enable_reset_password_limit', 'type' => 'checkbox', 'label' => __( 'Password reset limit', 'ultimate-member' ), 'checkbox_label' => __( 'Enable the Reset Password Limit?', 'ultimate-member' ), 'description' => __( 'If enabled, this sets a limit on the number of password resets a user can do.', 'ultimate-member' ), ), array( 'id' => 'reset_password_limit_number', 'type' => 'text', 'label' => __( 'Enter password reset limit', 'ultimate-member' ), 'description' => __( 'Set the maximum reset password limit. If reached the maximum limit, user will be locked from using this.', 'ultimate-member' ), 'validate' => 'numeric', 'conditional' => array( 'enable_reset_password_limit', '=', 1 ), 'size' => 'small', ), array( 'id' => 'change_password_request_limit', 'type' => 'checkbox', 'label' => __( 'Change Password request limit', 'ultimate-member' ), 'checkbox_label' => __( 'Enable limit for changing password', 'ultimate-member' ), 'description' => __( 'This option adds rate limit when submitting the change password form in the Account page. Users are only allowed to submit 1 request per 30 minutes to prevent from any brute-force attacks or password guessing with the form.', 'ultimate-member' ), ), array( 'id' => 'only_approved_user_reset_password', 'type' => 'checkbox', 'label' => __( 'Only approved user Reset Password', 'ultimate-member' ), 'checkbox_label' => __( 'Enable reset password only for approved users', 'ultimate-member' ), 'description' => __( 'This option makes possible to reset password only for approved user. Is used to prevent from any spam email attacks from not approved users.', 'ultimate-member' ), ), ), ), 'blocked' => array( 'title' => __( 'Blocked data when sign up', 'ultimate-member' ), 'description' => __( 'Allows to manage blocked data of signed up user.', 'ultimate-member' ), 'fields' => array( array( 'id' => 'blocked_emails', 'type' => 'textarea', 'label' => __( 'Blocked Email Addresses (Enter one email per line)', 'ultimate-member' ), 'description' => __( 'This will block the specified email addresses from being able to sign up or sign in to your site. To block an entire domain, use something like `*@domain.com`.', 'ultimate-member' ), ), array( 'id' => 'blocked_words', 'type' => 'textarea', 'label' => __( 'Blacklist Words (Enter one word per line)', 'ultimate-member' ), 'description' => __( 'This option lets you specify blacklist of words to prevent anyone from signing up with such a word as their username.', 'ultimate-member' ), ), ), ), ), ), ), ), 'email' => array( 'title' => __( 'Emails', 'ultimate-member' ), 'form_sections' => array( 'email_sender' => array( 'title' => __( 'Email sender options', 'ultimate-member' ), 'description' => __( 'How the sender appears in outgoing Ultimate Member emails.', 'ultimate-member' ), 'fields' => array( array( 'id' => 'admin_email', 'type' => 'text', 'label' => __( 'Admin Email Address', 'ultimate-member' ), 'description' => __( 'e.g. admin@companyname.com.', 'ultimate-member' ), ), array( 'id' => 'mail_from', 'type' => 'text', 'label' => __( 'Mail appears from', 'ultimate-member' ), 'description' => __( 'e.g. Site Name.', 'ultimate-member' ), ), array( 'id' => 'mail_from_addr', 'type' => 'text', 'label' => __( 'Mail appears from address', 'ultimate-member' ), 'description' => __( 'e.g. admin@companyname.com.', 'ultimate-member' ), ), ), ), 'email_template' => array( 'title' => __( 'Email template', 'ultimate-member' ), 'description' => __( 'Section to customize email templates settings.', 'ultimate-member' ), 'fields' => array( array( 'id' => 'email_html', 'type' => 'checkbox', 'label' => __( 'Content type', 'ultimate-member' ), 'checkbox_label' => __( 'Enable HTML for Emails', 'ultimate-member' ), 'description' => __( 'If you plan use emails with HTML, please make sure that this option is enabled. Otherwise, HTML will be displayed as plain text.', 'ultimate-member' ), ), ), ), ), ), 'appearance' => array( 'title' => __( 'Appearance', 'ultimate-member' ), 'sections' => array( '' => array( 'title' => __( 'Profile', 'ultimate-member' ), 'form_sections' => array( 'template' => array( 'title' => __( 'Template', 'ultimate-member' ), // translators: %s: Link to UM docs 'description' => sprintf( __( 'This section allows you to customize the user profile template and size. <a href="%s" target="_blank">Learn more about custom profile template creation</a>.', 'ultimate-member' ), 'https://docs.ultimatemember.com/article/120-adding-your-custom-profile-templates' ), 'fields' => array( array( 'id' => 'profile_template', 'type' => 'select', 'label' => __( 'Profile Default Template', 'ultimate-member' ), 'description' => __( 'This will be the default template to output profile.', 'ultimate-member' ), 'default' => um_get_metadefault( 'profile_template' ), 'options' => UM()->shortcodes()->get_templates( 'profile' ), 'size' => 'small', ), array( 'id' => 'profile_max_width', 'type' => 'text', 'label' => __( 'Profile Maximum Width', 'ultimate-member' ), 'default' => um_get_metadefault( 'profile_max_width' ), 'description' => __( 'The maximum width this shortcode can take from the page width.', 'ultimate-member' ), 'size' => 'small', ), array( 'id' => 'profile_area_max_width', 'type' => 'text', 'label' => __( 'Profile Area Maximum Width', 'ultimate-member' ), 'default' => um_get_metadefault( 'profile_area_max_width' ), 'description' => __( 'The maximum width of the profile area inside profile (below profile header).', 'ultimate-member' ), 'size' => 'small', ), ), ), 'profile_photo' => array( 'title' => __( 'Profile photo', 'ultimate-member' ), 'description' => __( 'This section allows you to customize the profile photo component on the user profile.', 'ultimate-member' ), 'fields' => array( array( 'id' => 'default_avatar', 'type' => 'media', 'label' => __( 'Default Profile Photo', 'ultimate-member' ), 'description' => __( 'You can change the default profile picture globally here. Please make sure that the photo is 300x300px.', 'ultimate-member' ), 'upload_frame_title' => __( 'Select Default Profile Photo', 'ultimate-member' ), 'default' => array( 'url' => UM_URL . 'assets/img/default_avatar.jpg', ), ), array( 'id' => 'disable_profile_photo_upload', 'type' => 'checkbox', 'label' => __( 'Profile Photo Upload', 'ultimate-member' ), 'checkbox_label' => __( 'Disable Profile Photo Upload', 'ultimate-member' ), 'description' => __( 'Switch on/off the profile photo uploader.', 'ultimate-member' ), 'default' => um_get_metadefault( 'disable_profile_photo_upload' ), ), array( 'id' => 'profile_photosize', 'type' => 'select', 'label' => __( 'Profile Photo Size', 'ultimate-member' ), 'default' => um_get_metadefault( 'profile_photosize' ), 'options' => UM()->files()->get_profile_photo_size( 'photo_thumb_sizes' ), 'description' => __( 'The global default of profile photo size. This can be overridden by individual form settings.', 'ultimate-member' ), 'size' => 'small', ), ), ), 'cover_photo' => array( 'title' => __( 'Cover photo', 'ultimate-member' ), 'description' => __( 'This section allows you to customize the profile photo component on the user profile.', 'ultimate-member' ), 'fields' => array( array( 'id' => 'default_cover', 'type' => 'media', 'url' => true, 'preview' => false, 'label' => __( 'Default Cover Photo', 'ultimate-member' ), 'description' => __( 'You can change the default cover photo globally here. Please make sure that the default cover is large enough and respects the ratio you are using for cover photos.', 'ultimate-member' ), 'upload_frame_title' => __( 'Select Default Cover Photo', 'ultimate-member' ), ), array( 'id' => 'profile_cover_enabled', 'type' => 'checkbox', 'label' => __( 'Profile Cover Photos', 'ultimate-member' ), 'checkbox_label' => __( 'Enable Cover Photos', 'ultimate-member' ), 'default' => um_get_metadefault( 'profile_cover_enabled' ), 'description' => __( 'Switch on/off the profile cover photos.', 'ultimate-member' ), ), array( 'id' => 'profile_coversize', 'type' => 'select', 'label' => __( 'Profile Cover Size', 'ultimate-member' ), 'default' => um_get_metadefault( 'profile_coversize' ), 'options' => UM()->files()->get_profile_photo_size( 'cover_thumb_sizes' ), 'description' => __( 'The global default width of cover photo size. This can be overridden by individual form settings.', 'ultimate-member' ), 'conditional' => array( 'profile_cover_enabled', '=', 1 ), 'size' => 'small', ), array( 'id' => 'profile_cover_ratio', 'type' => 'select', 'label' => __( 'Profile Cover Ratio', 'ultimate-member' ), 'description' => __( 'Choose global ratio for cover photos of profiles.', 'ultimate-member' ), 'default' => um_get_metadefault( 'profile_cover_ratio' ), 'options' => array( '1.6:1' => '1.6:1', '2.7:1' => '2.7:1', '2.2:1' => '2.2:1', '3.2:1' => '3.2:1', ), 'conditional' => array( 'profile_cover_enabled', '=', 1 ), 'size' => 'small', ), ), ), 'header' => array( 'title' => __( 'Header', 'ultimate-member' ), 'description' => __( 'This section allows you to customize the user profile header component.', 'ultimate-member' ), 'fields' => array( array( 'id' => 'profile_show_metaicon', 'type' => 'checkbox', 'label' => __( 'Profile Header Meta Text Icon', 'ultimate-member' ), 'checkbox_label' => __( 'Show icons in Profile Header Meta', 'ultimate-member' ), 'default' => 0, 'description' => __( 'Display field icons for related user meta fields in header or not.', 'ultimate-member' ), ), array( 'id' => 'profile_show_name', 'type' => 'checkbox', 'label' => __( 'Display name in profile header', 'ultimate-member' ), 'checkbox_label' => __( 'Show display name in profile header', 'ultimate-member' ), 'default' => um_get_metadefault( 'profile_show_name' ), 'description' => __( 'Switch on/off the user name on profile header.', 'ultimate-member' ), ), array( 'id' => 'profile_show_social_links', 'type' => 'checkbox', 'label' => __( 'Social links in profile header', 'ultimate-member' ), 'checkbox_label' => __( 'Show social links in profile header', 'ultimate-member' ), 'default' => um_get_metadefault( 'profile_show_social_links' ), 'description' => __( 'Switch on/off the social links on profile header.', 'ultimate-member' ), ), array( 'id' => 'profile_show_bio', 'type' => 'checkbox', 'label' => __( 'User description in profile header', 'ultimate-member' ), 'checkbox_label' => __( 'Show user description in profile header', 'ultimate-member' ), 'default' => um_get_metadefault( 'profile_show_bio' ), 'description' => __( 'Switch on/off the user description on profile header.', 'ultimate-member' ), ), array( 'id' => 'profile_bio_maxchars', 'type' => 'text', 'label' => __( 'User description maximum chars', 'ultimate-member' ), 'default' => um_get_metadefault( 'profile_bio_maxchars' ), 'description' => __( 'Maximum number of characters to allow in user description field in header.', 'ultimate-member' ), 'conditional' => array( 'profile_show_bio', '=', 1 ), 'size' => 'small', ), array( 'id' => 'profile_show_html_bio', 'type' => 'checkbox', 'label' => __( 'HTML support for user description', 'ultimate-member' ), 'checkbox_label' => __( 'Enable HTML support for user description', 'ultimate-member' ), 'description' => __( 'Switch on/off to enable/disable support for HTML tags on user description.', 'ultimate-member' ), ), array( 'id' => 'profile_header_menu', 'type' => 'select', 'label' => __( 'Profile Header Menu Position', 'ultimate-member' ), 'default' => um_get_metadefault( 'profile_header_menu' ), 'description' => __( 'For incompatible themes, please make the menu open from left instead of bottom by default.', 'ultimate-member' ), 'options' => array( 'bc' => __( 'Bottom of Icon', 'ultimate-member' ), 'lc' => __( 'Left of Icon (right for RTL)', 'ultimate-member' ), ), 'size' => 'small', ), ), ), 'fields' => array( 'title' => __( 'Buttons & Fields', 'ultimate-member' ), 'description' => __( 'This section allows you to customize the user profile buttons and fields layout.', 'ultimate-member' ), 'fields' => array( array( 'id' => 'profile_primary_btn_word', 'type' => 'text', 'label' => __( 'Profile Primary Button Text', 'ultimate-member' ), 'default' => um_get_metadefault( 'profile_primary_btn_word' ), 'description' => __( 'The text that is used for updating profile button.', 'ultimate-member' ), 'size' => 'medium', ), array( 'id' => 'profile_secondary_btn', 'type' => 'checkbox', 'label' => __( 'Profile Secondary Button', 'ultimate-member' ), 'checkbox_label' => __( 'Show Profile Secondary Button', 'ultimate-member' ), 'default' => um_get_metadefault( 'profile_secondary_btn' ), 'description' => __( 'Switch on/off the secondary button display in the form.', 'ultimate-member' ), ), array( 'id' => 'profile_secondary_btn_word', 'type' => 'text', 'label' => __( 'Profile Secondary Button Text', 'ultimate-member' ), 'default' => um_get_metadefault( 'profile_secondary_btn_word' ), 'description' => __( 'The text that is used for cancelling update profile button.', 'ultimate-member' ), 'conditional' => array( 'profile_secondary_btn', '=', 1 ), 'size' => 'medium', ), array( 'id' => 'profile_icons', 'type' => 'select', 'label' => __( 'Profile Field Icons', 'ultimate-member' ), 'description' => __( 'This is applicable for edit mode only.', 'ultimate-member' ), 'default' => um_get_metadefault( 'profile_icons' ), 'options' => array( 'field' => __( 'Show inside text field', 'ultimate-member' ), 'label' => __( 'Show with label', 'ultimate-member' ), 'off' => __( 'Turn off', 'ultimate-member' ), ), 'size' => 'small', ), array( 'id' => 'profile_empty_text', 'type' => 'checkbox', 'label' => __( 'Custom message on empty profile', 'ultimate-member' ), 'checkbox_label' => __( 'Show a custom message if profile is empty', 'ultimate-member' ), 'default' => um_get_metadefault( 'profile_empty_text' ), 'description' => __( 'Switch on/off the custom message that appears when the profile is empty.', 'ultimate-member' ), ), array( 'id' => 'profile_empty_text_emo', 'type' => 'checkbox', 'label' => __( 'Custom message emoticon', 'ultimate-member' ), 'checkbox_label' => __( 'Show the emoticon', 'ultimate-member' ), 'default' => um_get_metadefault( 'profile_empty_text_emo' ), 'description' => __( 'Switch on/off the emoticon (sad face) that appears above the message.', 'ultimate-member' ), 'conditional' => array( 'profile_empty_text', '=', 1 ), ), ), ), ), ), 'profile_menu' => array( 'title' => __( 'Profile Menu', 'ultimate-member' ), 'description' => __( 'This section allows you to customize the user profiles menus on your site.', 'ultimate-member' ), 'fields' => $appearances_profile_menu_fields, ), 'registration_form' => array( 'title' => __( 'Registration Form', 'ultimate-member' ), 'form_sections' => array( 'template' => array( 'title' => __( 'Template', 'ultimate-member' ), 'description' => __( 'This section allows you to customize the user registration template and size.', 'ultimate-member' ), 'fields' => array( array( 'id' => 'register_template', 'type' => 'select', 'label' => __( 'Registration Default Template', 'ultimate-member' ), 'description' => __( 'This will be the default template to output registration.', 'ultimate-member' ), 'default' => um_get_metadefault( 'register_template' ), 'options' => UM()->shortcodes()->get_templates( 'register' ), 'size' => 'small', ), array( 'id' => 'register_max_width', 'type' => 'text', 'label' => __( 'Registration Maximum Width', 'ultimate-member' ), 'default' => um_get_metadefault( 'register_max_width' ), 'description' => __( 'The maximum width this shortcode can take from the page width.', 'ultimate-member' ), 'size' => 'small', ), array( 'id' => 'register_align', 'type' => 'select', 'label' => __( 'Registration Shortcode Alignment', 'ultimate-member' ), 'description' => __( 'The shortcode is centered by default unless you specify otherwise here.', 'ultimate-member' ), 'default' => um_get_metadefault( 'register_align' ), 'options' => array( 'center' => __( 'Centered', 'ultimate-member' ), 'left' => __( 'Left aligned', 'ultimate-member' ), 'right' => __( 'Right aligned', 'ultimate-member' ), ), 'size' => 'small', ), ), ), 'fields' => array( 'title' => __( 'Buttons & Fields', 'ultimate-member' ), 'description' => __( 'This section allows you to customize the user registration buttons and fields layout.', 'ultimate-member' ), 'fields' => array( array( 'id' => 'register_primary_btn_word', 'type' => 'text', 'label' => __( 'Registration Primary Button Text', 'ultimate-member' ), 'default' => um_get_metadefault( 'register_primary_btn_word' ), 'description' => __( 'The text that is used for primary button text.', 'ultimate-member' ), 'size' => 'medium', ), array( 'id' => 'register_secondary_btn', 'type' => 'checkbox', 'label' => __( 'Registration Secondary Button', 'ultimate-member' ), 'checkbox_label' => __( 'Show Registration Secondary Button', 'ultimate-member' ), 'default' => 1, 'description' => __( 'Switch on/off the secondary button display in the form.', 'ultimate-member' ), ), array( 'id' => 'register_secondary_btn_word', 'type' => 'text', 'label' => __( 'Registration Secondary Button Text', 'ultimate-member' ), 'default' => um_get_metadefault( 'register_secondary_btn_word' ), 'description' => __( 'The text that is used for the secondary button text.', 'ultimate-member' ), 'conditional' => array( 'register_secondary_btn', '=', 1 ), 'size' => 'medium', ), array( 'id' => 'register_secondary_btn_url', 'type' => 'text', 'label' => __( 'Registration Secondary Button URL', 'ultimate-member' ), 'default' => um_get_metadefault( 'register_secondary_btn_url' ), 'description' => __( 'You can replace default link for this button by entering custom URL.', 'ultimate-member' ), 'conditional' => array( 'register_secondary_btn', '=', 1 ), 'size' => 'medium', ), array( 'id' => 'register_icons', 'type' => 'select', 'label' => __( 'Registration Field Icons', 'ultimate-member' ), 'description' => __( 'This controls the display of field icons in the registration form.', 'ultimate-member' ), 'default' => um_get_metadefault( 'register_icons' ), 'options' => array( 'field' => __( 'Show inside text field', 'ultimate-member' ), 'label' => __( 'Show with label', 'ultimate-member' ), 'off' => __( 'Turn off', 'ultimate-member' ), ), 'size' => 'small', ), ), ), ), ), 'login_form' => array( 'title' => __( 'Login Form', 'ultimate-member' ), 'form_sections' => array( 'template' => array( 'title' => __( 'Template', 'ultimate-member' ), 'description' => __( 'This section allows you to customize the user login template and size.', 'ultimate-member' ), 'fields' => array( array( 'id' => 'login_template', 'type' => 'select', 'label' => __( 'Login Default Template', 'ultimate-member' ), 'description' => __( 'This will be the default template to output login.', 'ultimate-member' ), 'default' => um_get_metadefault( 'login_template' ), 'options' => UM()->shortcodes()->get_templates( 'login' ), 'size' => 'small', ), array( 'id' => 'login_max_width', 'type' => 'text', 'label' => __( 'Login Maximum Width', 'ultimate-member' ), 'default' => um_get_metadefault( 'login_max_width' ), 'description' => __( 'The maximum width this shortcode can take from the page width.', 'ultimate-member' ), 'size' => 'small', ), array( 'id' => 'login_align', 'type' => 'select', 'label' => __( 'Login Shortcode Alignment', 'ultimate-member' ), 'description' => __( 'The shortcode is centered by default unless you specify otherwise here.', 'ultimate-member' ), 'default' => um_get_metadefault( 'login_align' ), 'options' => array( 'center' => __( 'Centered', 'ultimate-member' ), 'left' => __( 'Left aligned', 'ultimate-member' ), 'right' => __( 'Right aligned', 'ultimate-member' ), ), 'size' => 'small', ), ), ), 'fields' => array( 'title' => __( 'Buttons & Fields', 'ultimate-member' ), 'description' => __( 'This section allows you to customize the user login buttons and fields layout.', 'ultimate-member' ), 'fields' => array( array( 'id' => 'login_primary_btn_word', 'type' => 'text', 'label' => __( 'Login Primary Button Text', 'ultimate-member' ), 'default' => um_get_metadefault( 'login_primary_btn_word' ), 'description' => __( 'The text that is used for primary button text.', 'ultimate-member' ), 'size' => 'medium', ), array( 'id' => 'login_secondary_btn', 'type' => 'checkbox', 'label' => __( 'Login Secondary Button', 'ultimate-member' ), 'checkbox_label' => __( 'Show Login Secondary Button', 'ultimate-member' ), 'default' => 1, 'description' => __( 'Switch on/off the secondary button display in the form.', 'ultimate-member' ), ), array( 'id' => 'login_secondary_btn_word', 'type' => 'text', 'label' => __( 'Login Secondary Button Text', 'ultimate-member' ), 'default' => um_get_metadefault( 'login_secondary_btn_word' ), 'description' => __( 'The text that is used for the secondary button text.', 'ultimate-member' ), 'conditional' => array( 'login_secondary_btn', '=', 1 ), 'size' => 'medium', ), array( 'id' => 'login_secondary_btn_url', 'type' => 'text', 'label' => __( 'Login Secondary Button URL', 'ultimate-member' ), 'default' => um_get_metadefault( 'login_secondary_btn_url' ), 'description' => __( 'You can replace default link for this button by entering custom URL.', 'ultimate-member' ), 'conditional' => array( 'login_secondary_btn', '=', 1 ), 'size' => 'medium', ), array( 'id' => 'login_forgot_pass_link', 'type' => 'checkbox', 'label' => __( 'Login Forgot Password Link', 'ultimate-member' ), 'checkbox_label' => __( 'Show Login Forgot Password Link', 'ultimate-member' ), 'default' => 1, 'description' => __( 'Switch on/off the forgot password link in login form.', 'ultimate-member' ), ), array( 'id' => 'login_show_rememberme', 'type' => 'checkbox', 'label' => __( '"Remember Me" checkbox', 'ultimate-member' ), 'checkbox_label' => __( 'Show "Remember Me" checkbox', 'ultimate-member' ), 'default' => 1, 'description' => __( 'Allow users to choose If they want to stay signed in even after closing the browser. If you do not show this option, the default will be to not remember login session.', 'ultimate-member' ), ), array( 'id' => 'login_icons', 'type' => 'select', 'label' => __( 'Login Field Icons', 'ultimate-member' ), 'description' => __( 'This controls the display of field icons in the login form.', 'ultimate-member' ), 'default' => um_get_metadefault( 'login_icons' ), 'options' => array( 'field' => __( 'Show inside text field', 'ultimate-member' ), 'label' => __( 'Show with label', 'ultimate-member' ), 'off' => __( 'Turn off', 'ultimate-member' ), ), 'size' => 'small', ), ), ), ), ), ), ), 'extensions' => array( 'title' => __( 'Extensions', 'ultimate-member' ), ), 'licenses' => array( 'title' => __( 'Licenses', 'ultimate-member' ), ), 'advanced' => array( 'title' => __( 'Advanced', 'ultimate-member' ), 'sections' => array( '' => array( 'title' => __( 'General', 'ultimate-member' ), // translators: %s: Link to UM docs 'description' => sprintf( __( 'Advanced settings section is designed to help you fine-tune your website or add extra features. <a href="%s" target="_blank">Learn more about advanced settings section</a>.', 'ultimate-member' ), 'https://docs.ultimatemember.com/article/1902-advanced-tab' ), 'fields' => array( array( 'id' => 'form_asterisk', 'type' => 'checkbox', 'label' => __( 'Required fields\' asterisk', 'ultimate-member' ), 'checkbox_label' => __( 'Show an asterisk for required fields', 'ultimate-member' ), ), array( 'id' => 'um_profile_object_cache_stop', 'type' => 'checkbox', 'label' => __( 'Cache User Profile', 'ultimate-member' ), 'checkbox_label' => __( 'Disable user data cache', 'ultimate-member' ), 'description' => __( 'Check this box if you would like to disable Ultimate Member user\'s cache.', 'ultimate-member' ), ), array( 'id' => 'uninstall_on_delete', 'type' => 'checkbox', 'label' => __( 'Remove Data on Uninstall?', 'ultimate-member' ), 'checkbox_label' => __( 'Enable flushing data', 'ultimate-member' ), 'description' => __( 'Check this box if you would like Ultimate Member to completely remove all of its data when the plugin/extensions are deleted.', 'ultimate-member' ), ), ), ), 'override_templates' => array( 'title' => __( 'Override templates', 'ultimate-member' ), 'form_sections' => array( 'override_templates' => array( 'title' => __( 'Override templates', 'ultimate-member' ), // translators: %s: Link to the docs article. 'description' => sprintf( __( 'Each time we release an update, you\'ll find a list of changes made to the template files. <a href="%1$s" target="_blank">Learn more about overriding templates</a>.<br />You can easily check the status of the latest templates to see if they are up-to-date or need updating. <a href="%2$s" target="_blank">Learn more about fixing outdated templates</a>.', 'ultimate-member' ), 'https://docs.ultimatemember.com/article/1516-templates-map', 'https://docs.ultimatemember.com/article/1847-fixing-outdated-ultimate-member-templates' ), 'fields' => array( array( 'id' => 'override_templates_list_table', 'type' => 'override_templates_list_table', ), ), ), ), ), 'features' => array( 'title' => __( 'Features', 'ultimate-member' ), 'form_sections' => array( 'features' => array( 'title' => __( 'Features', 'ultimate-member' ), 'description' => __( 'Start using new features that are being progressively rolled out to improve the users management experience.', 'ultimate-member' ), 'fields' => array( array( 'id' => 'enable_blocks', 'type' => 'checkbox', 'label' => __( 'Gutenberg Blocks', 'ultimate-member' ), 'checkbox_label' => __( 'Enable Gutenberg Blocks', 'ultimate-member' ), 'description' => __( 'Check this box if you would like to use Ultimate Member blocks in Gutenberg editor. Important some themes have the conflicts with Gutenberg editor.', 'ultimate-member' ), ), $same_page_update, ), ), 'beta_features' => array( 'title' => __( 'Experimental features', 'ultimate-member' ), 'description' => __( 'These features are either experimental or incomplete, enable them at your own risk!', 'ultimate-member' ), 'fields' => array( array( 'id' => 'enable_new_ui', 'type' => 'checkbox', 'label' => __( 'Design scheme', 'ultimate-member' ), 'checkbox_label' => __( 'Enable new UI (for developers only)', 'ultimate-member' ), 'description' => __( 'Check this box if you would like to enable new UI.', 'ultimate-member' ), ), array( 'id' => 'enable_new_form_builder', 'type' => 'checkbox', 'label' => __( 'Form Builder', 'ultimate-member' ), 'checkbox_label' => __( 'Enable new Form Builder (for developers only)', 'ultimate-member' ), 'description' => __( 'Check this box if you would like to enable new Form Builder.', 'ultimate-member' ), ), array( 'id' => 'enable_legacy_fonticons', 'type' => 'checkbox', 'label' => __( 'Legacy fonticons', 'ultimate-member' ), 'checkbox_label' => __( 'Enable legacy fonticons', 'ultimate-member' ), 'description' => __( 'Check this box if you would like to enable legacy Ultimate Member fonticons used outdated versions of FontAwesome and Ionicons libraries.', 'ultimate-member' ), ), ), ), 'legacy_features' => array( 'title' => __( 'Legacy features', 'ultimate-member' ), 'description' => __( 'These features are related to the legacy logic or functionality. Please enable them only for the backward compatibility.', 'ultimate-member' ), 'fields' => array( // backward compatibility option leave it disabled for better security and ability to exclude posts/terms pre-query // otherwise we're filtering only results and restricted posts/terms can be visible array( 'id' => 'disable_restriction_pre_queries', 'type' => 'checkbox', 'label' => __( 'Restriction content pre-queries', 'ultimate-member' ), 'checkbox_label' => __( 'Disable pre-queries for restriction content logic', 'ultimate-member' ), 'description' => __( 'Please enable this option only in the cases when you have big or unnecessary queries on your site with active restriction logic. If you want to exclude posts only from the results queries instead of pre_get_posts and fully-hidden post logic also please enable this option. It activates the restriction content logic until 2.2.x version without latest security enhancements.', 'ultimate-member' ), ), ), ), ), ), 'developers' => array( 'title' => __( 'Developers', 'ultimate-member' ), 'form_sections' => array( 'developers' => array( 'title' => __( 'Developers', 'ultimate-member' ), 'description' => __( 'This section is designed to modify settings that are tailored for developers. If you are not a developer, please be cautious when changing these settings.', 'ultimate-member' ), 'fields' => array( array( 'id' => 'allowed_choice_callbacks', 'type' => 'textarea', 'label' => __( 'Allowed Choice Callbacks (Enter one PHP function per line)', 'ultimate-member' ), 'description' => __( 'This option lets you specify the choice callback functions to prevent anyone from using 3rd-party functions that may put your site at risk.', 'ultimate-member' ), ), ), ), 'redirect' => array( 'title' => __( 'Redirect', 'ultimate-member' ), 'description' => __( 'Allows to manage redirect settings.', 'ultimate-member' ), 'fields' => array( array( 'id' => 'allow_url_redirect_confirm', 'type' => 'checkbox', 'label' => __( 'Allow external link redirect confirm', 'ultimate-member' ), 'checkbox_label' => __( 'Enable JS.confirm for external links', 'ultimate-member' ), 'description' => __( 'Using JS.confirm alert when you go to an external link.', 'ultimate-member' ), ), ), ), ), ), 'apis' => array( 'title' => __( 'APIs', 'ultimate-member' ), 'form_sections' => array( 'google-maps' => array( // section key `google-maps` means the API $key used for filters in code. 'title' => __( 'Google Maps', 'ultimate-member' ), 'description' => __( 'This section is designed to help you integrate Ultimate Member functionality with Google Maps API.', 'ultimate-member' ), 'fields' => array( array( 'id' => 'um_google_maps_js_api_key', 'type' => 'api_key', 'label' => __( 'Maps JavaScript API Key', 'ultimate-member' ), 'size' => 'medium', ), array( 'id' => 'um_google_lang_as_default', 'type' => 'checkbox', 'label' => __( 'Google Maps locale', 'ultimate-member' ), 'checkbox_label' => __( 'Use current site\'s locale as language for Google Maps', 'ultimate-member' ), 'description' => __( 'Disable this option if you are planning to use static locale for Google Maps API.', 'ultimate-member' ), ), array( 'id' => 'um_google_lang', 'type' => 'select', 'label' => __( 'Custom Google Maps locale', 'ultimate-member' ), 'size' => 'small', 'options' => UM()->config()->get( 'google_maps_locales' ), 'conditional' => array( 'um_google_lang_as_default', '=', 0 ), ), array( 'id' => 'um_google_maps_api_version', 'type' => 'select', 'label' => __( 'Google Maps API version', 'ultimate-member' ), 'size' => 'small', 'options' => array( '3.5' => __( 'Version 3.5x (legacy)', 'ultimate-member' ), '3.64' => __( 'Version 3.64', 'ultimate-member' ), ), 'conditional' => array( 'um_google_maps_js_api_key', '!=', '' ), ), ), ), ), ), ), ), 'system_info' => array( 'title' => __( 'System info', 'ultimate-member' ), 'link' => add_query_arg( array( 'tab' => 'debug' ), admin_url( 'site-health.php' ) ), ), ) ); if ( false === UM()->account()->is_notifications_tab_visible() ) { unset( $this->settings_structure['']['sections']['account']['form_sections']['notifications_tab'] ); } // Hide sub tab if there aren't custom templates in theme. $custom_templates = UM()->common()->theme()->get_custom_templates_list(); if ( empty( $custom_templates ) ) { unset( $this->settings_structure['advanced']['sections']['override_templates'] ); } if ( defined( 'UM_DEV_MODE' ) && UM_DEV_MODE ) { } else { unset( $this->settings_structure['advanced']['sections']['features']['form_sections']['beta_features'] ); } if ( UM()->account()->current_password_is_required( 'delete' ) ) { unset( $this->settings_structure['']['sections']['account']['form_sections']['delete_tab']['fields'][2] ); } else { unset( $this->settings_structure['']['sections']['account']['form_sections']['delete_tab']['fields'][1] ); } // Hide un-existed API foreach ( $this->settings_structure['advanced']['sections']['apis']['form_sections'] as $api => $section_data ) { if ( ! UM()->common()->apis()::has_api( $api ) ) { unset( $this->settings_structure['advanced']['sections']['apis']['form_sections'][ $api ] ); } } // Hide APIs tab when there aren't any APIs if ( count( $this->settings_structure['advanced']['sections']['apis']['form_sections'] ) < 1 ) { unset( $this->settings_structure['advanced']['sections']['apis'] ); } } /** * @param array $settings * * @return array */ public function sorting_licenses_options( $settings ) { //sorting licenses if ( ! empty( $settings['licenses']['fields'] ) ) { $licenses = $settings['licenses']['fields']; @uasort( $licenses, function ( $a, $b ) { return strnatcasecmp( $a['label'], $b['label'] ); } ); $settings['licenses']['fields'] = $licenses; } //sorting extensions by the title if ( ! empty( $settings['extensions']['sections'] ) ) { $extensions = $settings['extensions']['sections']; @uasort( $extensions, function ( $a, $b ) { return strnatcasecmp( $a['title'], $b['title'] ); } ); $keys = array_keys( $extensions ); $temp = array( '' => $extensions[ $keys[0] ], ); unset( $extensions[ $keys[0] ] ); $extensions = $temp + $extensions; $settings['extensions']['sections'] = $extensions; } return $settings; } /** * @param $tab * @param $section * * @return array */ public function get_section_fields( $tab, $section ) { $custom_section_fields = apply_filters( 'um_settings_section_custom_fields', false, $tab, $section ); if ( false !== $custom_section_fields ) { return $custom_section_fields; } if ( empty( $this->settings_structure[ $tab ] ) ) { return array(); } if ( ! empty( $this->settings_structure[ $tab ]['sections'][ $section ]['form_sections'] ) ) { return array( 'form_sections' => $this->settings_structure[ $tab ]['sections'][ $section ]['form_sections'] ); } if ( ! empty( $this->settings_structure[ $tab ]['sections'][ $section ]['fields'] ) ) { return $this->settings_structure[ $tab ]['sections'][ $section ]['fields']; } if ( ! empty( $this->settings_structure[ $tab ]['form_sections'] ) ) { return array( 'form_sections' => $this->settings_structure[ $tab ]['form_sections'] ); } if ( ! empty( $this->settings_structure[ $tab ]['fields'] ) ) { return $this->settings_structure[ $tab ]['fields']; } return array(); } /** * Settings page callback. */ public function settings_page() { $current_tab = empty( $_GET['tab'] ) ? '' : sanitize_key( $_GET['tab'] ); $current_subtab = empty( $_GET['section'] ) ? '' : sanitize_key( $_GET['section'] ); $temp_structure = $this->settings_structure; // Don't remove this temp variable. Internal workaround for Email Tab integration. $custom_content = apply_filters( 'um_settings_section_' . $current_tab . '_' . $current_subtab . '_custom_content', false, $current_tab, $current_subtab ); if ( false === $custom_content ) { $section_fields = $this->get_section_fields( $current_tab, $current_subtab ); $settings_section = $this->render_settings_section( $section_fields, $current_tab, $current_subtab ); } else { $settings_section = $custom_content; } $this->settings_structure = $temp_structure; // Don't remove this temp variable. Internal workaround for Email Tab integration. echo '<div id="um-settings-wrap" class="wrap"><h1>' . esc_html__( 'Ultimate Member - Settings', 'ultimate-member' ) . '</h1>'; echo $this->generate_tabs_menu() . $this->generate_subtabs_menu( $current_tab ); echo '<div class="clear"></div>'; /** * UM hook * * @type action * @title um_settings_page_before_{$current_tab}_{$current_subtab}_content * @description Show some content before settings page content * @change_log * ["Since: 2.0"] * @usage add_action( 'um_settings_page_before_{$current_tab}_{$current_subtab}_content', 'function_name', 10 ); * @example * <?php * add_action( 'um_settings_page_before_{$current_tab}_{$current_subtab}_content', 'my_settings_page_before', 10 ); * function my_settings_page_before() { * // your code here * } * ?> */ do_action( "um_settings_page_before_{$current_tab}_{$current_subtab}_content" ); $form_wrapper = true; if ( 'licenses' === $current_tab ) { $form_wrapper = false; } if ( 'advanced' === $current_tab && 'override_templates' === $current_subtab ) { $form_wrapper = false; } $form_wrapper = apply_filters( 'um_settings_default_form_wrapper', $form_wrapper, $current_tab, $current_subtab ); if ( $form_wrapper ) { ?> <form method="post" action="" name="um-settings-form" id="um-settings-form"> <input type="hidden" value="save" name="um-settings-action" /> <?php } /** * UM hook * * @type action * @title um_settings_page_{$current_tab}_{$current_subtab}_before_section * @description Show some content before section content at settings page * @change_log * ["Since: 2.0"] * @usage add_action( 'um_settings_page_{$current_tab}_{$current_subtab}_before_section', 'function_name', 10 ); * @example * <?php * add_action( 'um_settings_page_{$current_tab}_{$current_subtab}_before_section', 'my_settings_page_before_section', 10 ); * function my_settings_page_before_section() { * // your code here * } * ?> */ do_action( "um_settings_page_{$current_tab}_{$current_subtab}_before_section" ); echo $settings_section; if ( $form_wrapper ) { $um_settings_nonce = wp_create_nonce( 'um-settings-nonce' ); ?> <p class="submit"> <input type="submit" name="submit" id="submit" class="button button-primary" value="<?php esc_attr_e( 'Save Changes', 'ultimate-member' ); ?>" /> <input type="hidden" name="__umnonce" value="<?php echo esc_attr( $um_settings_nonce ); ?>" /> </p> </form> <?php } } /** * Generate pages tabs. * * @param string $page * @return string */ private function generate_tabs_menu( $page = 'settings' ) { $tabs = '<nav class="nav-tab-wrapper um-nav-tab-wrapper">'; switch ( $page ) { case 'settings': $menu_tabs = array(); foreach ( $this->settings_structure as $slug => $tab ) { if ( ! empty( $tab['fields'] ) ) { foreach ( $tab['fields'] as $field_key => $field_options ) { if ( isset( $field_options['is_option'] ) && false === $field_options['is_option'] ) { unset( $tab['fields'][ $field_key ] ); } } } if ( ! empty( $tab['fields'] ) || ! empty( $tab['sections'] ) || ! empty( $tab['form_sections'] ) ) { $menu_tabs[ $slug ] = $tab['title']; } elseif ( ! empty( $tab['link'] ) ) { $menu_tabs[ $slug ] = $tab['title']; } } $current_tab = empty( $_GET['tab'] ) ? '' : sanitize_key( $_GET['tab'] ); foreach ( $menu_tabs as $name => $label ) { if ( ! empty( $this->settings_structure[ $name ]['link'] ) ) { $active = ''; $tab_url = $this->settings_structure[ $name ]['link']; } else { $active = $current_tab === $name ? 'nav-tab-active' : ''; $args = array( 'page' => 'um_options' ); if ( ! empty( $name ) ) { $args['tab'] = $name; } $tab_url = add_query_arg( $args, admin_url( 'admin.php' ) ); } $tabs .= '<a href="' . esc_url( $tab_url ) . '" class="nav-tab ' . esc_attr( $active ) . '">' . esc_html( $label ) . '</a>'; } break; default: /** * UM hook * * @type filter * @title um_generate_tabs_menu_{$page} * @description Generate tabs menu * @input_vars * [{"var":"$tabs","type":"array","desc":"UM menu tabs"}] * @change_log * ["Since: 2.0"] * @usage add_filter( 'um_generate_tabs_menu_{$page}', 'function_name', 10, 1 ); * @example * <?php * add_filter( 'um_generate_tabs_menu_{$page}', 'my_tabs_menu', 10, 1 ); * function my_tabs_menu( $tabs ) { * // your code here * return $tabs; * } * ?> */ $tabs = apply_filters( 'um_generate_tabs_menu_' . $page, $tabs ); break; } return $tabs . '</nav>'; } /** * @param string $tab * * @return string */ private function generate_subtabs_menu( $tab = '' ) { if ( empty( $this->settings_structure[ $tab ]['sections'] ) ) { return ''; } $current_tab = empty( $_GET['tab'] ) ? '' : sanitize_key( $_GET['tab'] ); $current_subtab = empty( $_GET['section'] ) ? '' : sanitize_key( $_GET['section'] ); $menu_subtabs = array(); foreach ( $this->settings_structure[ $tab ]['sections'] as $slug => $subtab ) { $menu_subtabs[ $slug ] = $subtab['title']; } $subtabs = array(); foreach ( $menu_subtabs as $name => $label ) { $active = $current_subtab === $name ? 'current' : ''; $args = array( 'page' => 'um_options' ); if ( ! empty( $current_tab ) ) { $args['tab'] = $current_tab; } if ( ! empty( $name ) ) { $args['section'] = $name; } $tab_url = add_query_arg( $args, admin_url( 'admin.php' ) ); $subtabs[] = '<a href="' . esc_url( $tab_url ) . '" class="' . esc_attr( $active ) . '">' . esc_html( $label ) . '</a>'; } if ( empty( $subtabs ) ) { return ''; } return '<ul class="subsubsub"><li>' . implode( ' | </li><li>', $subtabs ) . '</li></ul>'; } /** * Handler for settings forms * when "Save Settings" button click * */ function save_settings_handler() { if ( isset( $_POST['um-settings-action'] ) && 'save' === sanitize_key( $_POST['um-settings-action'] ) && ! empty( $_POST['um_options'] ) ) { $nonce = ! empty( $_POST['__umnonce'] ) ? $_POST['__umnonce'] : ''; if ( ( ! wp_verify_nonce( $nonce, 'um-settings-nonce' ) || empty( $nonce ) ) || ! current_user_can( 'manage_options' ) ) { // This nonce is not valid. wp_die( __( 'Security Check', 'ultimate-member' ) ); } /** * UM hook * * @type action * @title um_settings_before_save * @description Before settings save action * @change_log * ["Since: 2.0"] * @usage add_action( 'um_settings_before_save', 'function_name', 10 ); * @example * <?php * add_action( 'um_settings_before_save', 'my_settings_before_save', 10 ); * function my_settings_before_save() { * // your code here * } * ?> */ do_action( 'um_settings_before_save' ); /** * UM hook * * @type filter * @title um_change_settings_before_save * @description Change settings before save * @input_vars * [{"var":"$settings","type":"array","desc":"UM Settings on save"}] * @change_log * ["Since: 2.0"] * @usage add_filter( 'um_change_settings_before_save', 'function_name', 10, 1 ); * @example * <?php * add_filter( 'um_change_settings_before_save', 'my_change_settings_before_save', 10, 1 ); * function my_change_settings_before_save( $settings ) { * // your code here * return $settings; * } * ?> */ $settings = apply_filters( 'um_change_settings_before_save', $_POST['um_options'] ); $settings = UM()->admin()->sanitize_options( $settings ); foreach ( $settings as $key => $value ) { UM()->options()->update( $key, $value ); } /** * UM hook * * @type action * @title um_settings_save * @description After settings save action * @change_log * ["Since: 2.0"] * @usage add_action( 'um_settings_save', 'function_name', 10 ); * @example * <?php * add_action( 'um_settings_save', 'my_settings_save', 10 ); * function my_settings_save() { * // your code here * } * ?> */ do_action( 'um_settings_save' ); //redirect after save settings $arg = array( 'page' => 'um_options', 'update' => 'um_settings_updated', ); if ( ! empty( $_GET['tab'] ) ) { $arg['tab'] = sanitize_key( $_GET['tab'] ); } if ( ! empty( $_GET['section'] ) ) { $arg['section'] = sanitize_key( $_GET['section'] ); } um_js_redirect( add_query_arg( $arg, admin_url( 'admin.php' ) ) ); } } public function set_default_if_empty( $settings ) { $tab = ''; if ( ! empty( $_GET['tab'] ) ) { $tab = sanitize_key( $_GET['tab'] ); } $section = ''; if ( ! empty( $_GET['section'] ) ) { $section = sanitize_key( $_GET['section'] ); } if ( 'access' === $tab && empty( $section ) ) { if ( ! array_key_exists( 'access_exclude_uris', $settings ) ) { $settings['access_exclude_uris'] = array(); } } return $settings; } /** * Remove empty values from multi text fields. * * @param array $settings * @return array */ public function remove_empty_values( $settings ) { $tab = ''; if ( ! empty( $_GET['tab'] ) ) { $tab = sanitize_key( $_GET['tab'] ); } $section = ''; if ( ! empty( $_GET['section'] ) ) { $section = sanitize_key( $_GET['section'] ); } if ( ! empty( $this->settings_structure[ $tab ]['sections'][ $section ]['form_sections'] ) ) { $fields = array(); foreach ( $this->settings_structure[ $tab ]['sections'][ $section ]['form_sections'] as $section_key => $section_data ) { if ( ! empty( $section_data['fields'] ) ) { $fields[] = $section_data['fields']; } } $fields = array_merge( ...$fields ); } elseif ( ! empty( $this->settings_structure[ $tab ]['sections'][ $section ]['fields'] ) ) { $fields = $this->settings_structure[ $tab ]['sections'][ $section ]['fields']; } elseif ( ! empty( $this->settings_structure[ $tab ]['form_sections'] ) ) { $fields = array(); foreach ( $this->settings_structure[ $tab ]['form_sections'] as $section_key => $section_data ) { if ( ! empty( $section_data['fields'] ) ) { $fields[] = $section_data['fields']; } } $fields = array_merge( ...$fields ); } elseif ( ! empty( $this->settings_structure[ $tab ]['fields'] ) ) { $fields = $this->settings_structure[ $tab ]['fields']; } if ( empty( $fields ) ) { return $settings; } $filtered_settings = array(); foreach ( $settings as $key => $value ) { $filtered_settings[ $key ] = $value; foreach ( $fields as $field ) { if ( $field['id'] === $key && array_key_exists( 'type', $field ) && 'multi_text' === $field['type'] ) { $filtered_settings[ $key ] = array_filter( $value ); } } } return $filtered_settings; } /** * */ function check_permalinks_changes() { if ( ! empty( $_POST['um_options']['permalink_base'] ) ) { if ( UM()->options()->get( 'permalink_base' ) !== $_POST['um_options']['permalink_base'] ) { $this->need_change_permalinks = true; } } // set variable if gravatar settings were changed // update for um_member_directory_data metakey if ( isset( $_POST['um_options']['use_gravatars'] ) ) { $use_gravatar = UM()->options()->get( 'use_gravatars' ); if ( ( empty( $use_gravatar ) && ! empty( $_POST['um_options']['use_gravatars'] ) ) || ( ! empty( $use_gravatar ) && empty( $_POST['um_options']['use_gravatars'] ) ) ) { $this->gravatar_changed = true; } } } /** * */ function on_settings_save() { if ( ! empty( $_POST['um_options'] ) ) { if ( ! empty( $_POST['um_options']['pages_settings'] ) ) { $post_ids = new \WP_Query( array( 'post_type' => 'page', 'meta_query' => array( array( 'key' => '_um_core', 'compare' => 'EXISTS', ), ), 'posts_per_page' => -1, 'fields' => 'ids', ) ); $post_ids = $post_ids->get_posts(); if ( ! empty( $post_ids ) ) { foreach ( $post_ids as $post_id ) { delete_post_meta( $post_id, '_um_core' ); } } foreach ( $_POST['um_options'] as $option_slug => $post_id ) { $slug = str_replace( 'core_', '', $option_slug ); update_post_meta( $post_id, '_um_core', $slug ); } // reset rewrite rules after re-save pages UM()->rewrite()->reset_rules(); } elseif ( ! empty( $_POST['um_options']['permalink_base'] ) ) { if ( ! empty( $this->need_change_permalinks ) ) { $users = get_users( array( 'fields' => 'ids', ) ); if ( ! empty( $users ) ) { foreach ( $users as $user_id ) { UM()->user()->generate_profile_slug( $user_id ); } } } // update for um_member_directory_data metakey if ( isset( $_POST['um_options']['use_gravatars'] ) ) { if ( $this->gravatar_changed ) { global $wpdb; if ( ! empty( $_POST['um_options']['use_gravatars'] ) ) { $results = $wpdb->get_col( "SELECT u.ID FROM {$wpdb->users} AS u LEFT JOIN {$wpdb->usermeta} AS um ON ( um.user_id = u.ID AND um.meta_key = 'synced_gravatar_hashed_id' ) LEFT JOIN {$wpdb->usermeta} AS um2 ON ( um2.user_id = u.ID AND um2.meta_key = 'um_member_directory_data' ) WHERE um.meta_value != '' AND um.meta_value IS NOT NULL AND um2.meta_value LIKE '%s:13:\"profile_photo\";b:0;%'" ); } else { $results = $wpdb->get_col( "SELECT u.ID FROM {$wpdb->users} AS u LEFT JOIN {$wpdb->usermeta} AS um ON ( um.user_id = u.ID AND ( um.meta_key = 'synced_profile_photo' || um.meta_key = 'profile_photo' ) ) LEFT JOIN {$wpdb->usermeta} AS um2 ON ( um2.user_id = u.ID AND um2.meta_key = 'um_member_directory_data' ) WHERE ( um.meta_value IS NULL OR um.meta_value = '' ) AND um2.meta_value LIKE '%s:13:\"profile_photo\";b:1;%'" ); } if ( ! empty( $results ) ) { foreach ( $results as $user_id ) { $md_data = get_user_meta( $user_id, 'um_member_directory_data', true ); if ( ! empty( $md_data ) && is_array( $md_data ) ) { $md_data['profile_photo'] = ! empty( $_POST['um_options']['use_gravatars'] ); update_user_meta( $user_id, 'um_member_directory_data', $md_data ); } } } } } } elseif ( isset( $_POST['um_options']['member_directory_own_table'] ) ) { if ( empty( $_POST['um_options']['member_directory_own_table'] ) ) { global $wpdb; $results = $wpdb->get_row( "SELECT * FROM {$wpdb->prefix}um_metadata LIMIT 1", ARRAY_A ); if ( ! empty( $results ) ) { $wpdb->query( "TRUNCATE TABLE {$wpdb->prefix}um_metadata" ); } update_option( 'um_member_directory_truncated', time() ); } } elseif ( isset( $_POST['um_options']['account_hide_in_directory_default'] ) ) { global $wpdb; if ( $_POST['um_options']['account_hide_in_directory_default'] === 'No' ) { $results = $wpdb->get_col( "SELECT u.ID FROM {$wpdb->users} AS u LEFT JOIN {$wpdb->usermeta} AS um ON ( um.user_id = u.ID AND um.meta_key = 'hide_in_members' ) LEFT JOIN {$wpdb->usermeta} AS um2 ON ( um2.user_id = u.ID AND um2.meta_key = 'um_member_directory_data' ) WHERE um.meta_value IS NULL AND um2.meta_value LIKE '%s:15:\"hide_in_members\";b:1;%'" ); } else { $results = $wpdb->get_col( "SELECT u.ID FROM {$wpdb->users} AS u LEFT JOIN {$wpdb->usermeta} AS um ON ( um.user_id = u.ID AND um.meta_key = 'hide_in_members' ) LEFT JOIN {$wpdb->usermeta} AS um2 ON ( um2.user_id = u.ID AND um2.meta_key = 'um_member_directory_data' ) WHERE um.meta_value IS NULL AND um2.meta_value LIKE '%s:15:\"hide_in_members\";b:0;%'" ); } if ( ! empty( $results ) ) { foreach ( $results as $user_id ) { $md_data = get_user_meta( $user_id, 'um_member_directory_data', true ); if ( ! empty( $md_data ) && is_array( $md_data ) ) { $md_data['hide_in_members'] = ( $_POST['um_options']['account_hide_in_directory_default'] === 'No' ) ? false : true; update_user_meta( $user_id, 'um_member_directory_data', $md_data ); } } } } } } /** * */ function before_licenses_save() { if ( empty( $_POST['um_options'] ) || empty( $_POST['licenses_settings'] ) ) { return; } foreach ( $_POST['um_options'] as $key => $value ) { $this->previous_licenses[ sanitize_key( $key ) ] = UM()->options()->get( $key ); } } /** * Check if license debug is enabled based on defined constants. * * @return bool */ private static function is_license_debug_enabled() { return defined( 'UM_LICENSE_REQUEST_DEBUG' ) && UM_LICENSE_REQUEST_DEBUG && defined( 'WP_DEBUG' ) && WP_DEBUG && defined( 'WP_DEBUG_LOG' ) && WP_DEBUG_LOG; } /** * */ public function licenses_save() { if ( empty( $_POST['um_options'] ) || empty( $_POST['licenses_settings'] ) ) { return; } foreach ( $_POST['um_options'] as $key => $value ) { $key = sanitize_key( $key ); $value = sanitize_text_field( $value ); $edd_action = ''; $license_key = ''; if ( empty( $this->previous_licenses[ $key ] ) && ! empty( $value ) || ( ! empty( $this->previous_licenses[ $key ] ) && ! empty( $value ) && $this->previous_licenses[ $key ] != $value ) ) { $edd_action = 'activate_license'; $license_key = $value; } elseif ( ! empty( $this->previous_licenses[ $key ] ) && empty( $value ) ) { $edd_action = 'deactivate_license'; $license_key = $this->previous_licenses[ $key ]; } elseif ( ! empty( $this->previous_licenses[ $key ] ) && ! empty( $value ) ) { $edd_action = 'check_license'; $license_key = $value; } if ( empty( $edd_action ) ) { continue; } $item_name = false; $version = false; $author = false; foreach ( $this->settings_structure['licenses']['fields'] as $field_data ) { if ( $field_data['id'] === $key ) { $item_name = ! empty( $field_data['item_name'] ) ? $field_data['item_name'] : false; $version = ! empty( $field_data['version'] ) ? $field_data['version'] : false; $author = ! empty( $field_data['author'] ) ? $field_data['author'] : false; } } $post_attr = array( 'timeout' => UM()::$request_timeout, 'sslverify' => false, 'body' => array( 'edd_action' => $edd_action, 'license' => $license_key, 'item_name' => $item_name, 'version' => $version, 'author' => $author, 'url' => home_url(), ), ); // phpcs:disable WordPress.PHP.DevelopmentFunctions.error_log_error_log -- Need to debug license requests sometimes. if ( self::is_license_debug_enabled() ) { error_log( '----- License handler starts below -----' ); error_log( '### Store URL: ' . UM()::$store_url ); error_log( '### Request:' ); error_log( maybe_serialize( $post_attr ) ); } $request = wp_remote_post( UM()::$store_url, $post_attr ); if ( empty( $request ) || is_wp_error( $request ) ) { if ( self::is_license_debug_enabled() ) { error_log( '> Got `wp_error` or empty request body, try again with `sslverify=true`' ); } $post_attr['sslverify'] = true; $request = wp_remote_post( UM()::$store_url, $post_attr ); if ( ! is_wp_error( $request ) ) { $request = json_decode( wp_remote_retrieve_body( $request ) ); } } else { $request = json_decode( wp_remote_retrieve_body( $request ) ); if ( empty( $request ) ) { if ( self::is_license_debug_enabled() ) { error_log( '> Got empty request body, try again with `sslverify=true`' ); } $post_attr['sslverify'] = true; $request = wp_remote_post( UM()::$store_url, $post_attr ); if ( ! is_wp_error( $request ) ) { $request = json_decode( wp_remote_retrieve_body( $request ) ); } } } if ( self::is_license_debug_enabled() ) { if ( is_wp_error( $request ) ) { error_log( '> Finally got `wp_error`. Details below.' ); error_log( '>> Error code: ' . $request->get_error_code() ); error_log( '>> Error message: ' . $request->get_error_message() ); } elseif ( empty( $request ) ) { error_log( '> Finally got empty UM website response.' ); } else { error_log( '### Response from UM website:' ); error_log( '>' . maybe_serialize( $request ) ); } error_log( '^^^^^^ End license handler ^^^^^^' ); } // phpcs:enable WordPress.PHP.DevelopmentFunctions.error_log_error_log -- Need to debug license requests sometimes. $request = ( $request ) ? maybe_unserialize( $request ) : false; if ( in_array( $edd_action, array( 'activate_license', 'check_license' ), true ) ) { update_option( "{$key}_edd_answer", $request ); } else { delete_option( "{$key}_edd_answer" ); } } } /** * Adds email notifications list table before the email options list. */ public function settings_before_email_tab() { $email_key = empty( $_GET['email'] ) ? '' : sanitize_key( $_GET['email'] ); $emails = UM()->config()->email_notifications; if ( empty( $email_key ) || empty( $emails[ $email_key ] ) ) { include_once UM_PATH . 'includes/admin/core/list-tables/emails-list-table.php'; } } /** * Set settings field per email notification. * * @param bool|array $section_fields * @param string $tab * * @return bool|array */ public function email_section_custom_fields( $section_fields, $tab ) { if ( 'email' !== $tab ) { return $section_fields; } $email_key = empty( $_GET['email'] ) ? '' : sanitize_key( $_GET['email'] ); $emails = UM()->config()->email_notifications; if ( empty( $email_key ) || empty( $emails[ $email_key ] ) ) { return $section_fields; } $in_theme = UM()->mail()->template_in_theme( $email_key ); $back_link = add_query_arg( array( 'page' => 'um_options', 'tab' => 'email', ), admin_url( 'admin.php' ) ); $this->settings_structure['email']['title'] = '<a class="um-back-button" href="' . esc_url( $back_link ) . '" title="' . esc_attr__( 'Back', 'ultimate-member' ) . '">←</a>' . $emails[ $email_key ]['title']; $this->settings_structure['email']['description'] = $emails[ $email_key ]['description']; $section_fields = array( array( 'id' => 'um_email_template', 'type' => 'hidden', 'value' => $email_key, ), array( 'id' => $email_key . '_on', 'type' => 'checkbox', 'label' => __( 'Enable/Disable', 'ultimate-member' ), 'checkbox_label' => __( 'Enable this email notification', 'ultimate-member' ), ), array( 'id' => $email_key . '_sub', 'type' => 'text', 'label' => __( 'Subject', 'ultimate-member' ), 'conditional' => array( $email_key . '_on', '=', 1 ), ), array( 'id' => $email_key, 'type' => 'email_template', 'label' => __( 'Email Content', 'ultimate-member' ), 'conditional' => array( $email_key . '_on', '=', 1 ), 'value' => UM()->mail()->get_email_template( $email_key ), 'in_theme' => $in_theme, ), ); /** * UM hook * * @type filter * @title um_admin_settings_email_section_fields * @description Extend UM Email Settings * @input_vars * [{"var":"$settings","type":"array","desc":"UM Email Settings"}, * {"var":"$email_key","type":"string","desc":"Email Key"}] * @change_log * ["Since: 2.0"] * @usage add_filter( 'um_admin_settings_email_section_fields', 'function_name', 10, 2 ); * @example * <?php * add_filter( 'um_admin_settings_email_section_fields', 'my_admin_settings_email_section', 10, 2 ); * function my_admin_settings_email_section( $settings, $email_key ) { * // your code here * return $settings; * } * ?> */ return apply_filters( 'um_admin_settings_email_section_fields', $section_fields, $email_key ); } /** * @param bool $html * @param string $current_tab * @param string $current_subtab * * @return bool|string */ public function settings_licenses_tab( $html, $current_tab, $current_subtab ) { $section_fields = $this->get_section_fields( $current_tab, $current_subtab ); if ( empty( $section_fields ) ) { return $html; } $um_settings_nonce = wp_create_nonce( 'um-settings-nonce' ); ob_start(); ?> <div class="wrap-licenses"> <table class="form-table um-settings-section"> <tbody> <?php foreach ( $section_fields as $field_data ) { $option_value = UM()->options()->get( $field_data['id'] ); $default_value = isset( $field_data['default'] ) ? $field_data['default'] : ''; $value = ! empty( $option_value ) ? $option_value : $default_value; $license = get_option( "{$field_data['id']}_edd_answer" ); if ( is_object( $license ) && ! empty( $value ) ) { // Activate_license 'invalid' on anything other than valid, so if there was an error capture it if ( is_wp_error( $license ) ) { $class = 'error'; $errors_data = array(); $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, $error_code_messages ); } } $errors_data = ! empty( $errors_data ) ? implode( ' ', $errors_data ) : ''; // translators: %1$s is an error data; %2$s is a support link. $messages[] = sprintf( __( 'There was an error with this license key: %1$s. Please <a href="%2$s">contact our support team</a>.', 'ultimate-member' ), $errors_data, 'https://ultimatemember.com/support' ); $license_status = 'license-' . $class . '-notice'; } elseif ( empty( $license->success ) ) { if ( ! empty( $license->error ) ) { switch ( $license->error ) { case 'expired': $class = 'expired'; $messages[] = sprintf( // translators: %1$s is an expiry date; %2$s is a renewal link. __( 'Your license key expired on %1$s. Please <a href="%2$s" target="_blank">renew your license key</a>.', 'ultimate-member' ), wp_date( get_option( 'date_format', 'F j, Y' ), strtotime( $license->expires ), new DateTimeZone( 'UTC' ) ), 'https://ultimatemember.com/checkout/?edd_license_key=' . $value . '&utm_campaign=admin&utm_source=licenses&utm_medium=expired' ); $license_status = 'license-' . $class . '-notice'; break; case 'revoked': $class = 'error'; $messages[] = sprintf( // translators: %s: support link name. __( 'Your license key has been disabled. Please <a href="%s" target="_blank">contact support</a> for more information.', 'ultimate-member' ), 'https://ultimatemember.com/support?utm_campaign=admin&utm_source=licenses&utm_medium=revoked' ); $license_status = 'license-' . $class . '-notice'; break; case 'missing': $class = 'error'; $messages[] = sprintf( // translators: %s: account page. __( 'Invalid license. Please <a href="%s" target="_blank">visit your account page</a> and verify it.', 'ultimate-member' ), 'https://ultimatemember.com/account?utm_campaign=admin&utm_source=licenses&utm_medium=missing' ); $license_status = 'license-' . $class . '-notice'; break; case 'invalid': case 'site_inactive': $class = 'error'; $messages[] = sprintf( // translators: %1$s is a item name title; %2$s is a account page. __( 'Your %1$s is not active for this URL. Please <a href="%2$s" target="_blank">visit your account page</a> to manage your license key URLs.', 'ultimate-member' ), $field_data['item_name'], 'https://ultimatemember.com/account?utm_campaign=admin&utm_source=licenses&utm_medium=invalid' ); $license_status = 'license-' . $class . '-notice'; break; case 'item_name_mismatch': $class = 'error'; // translators: %s: item name. $messages[] = sprintf( __( 'This appears to be an invalid license key for %s.', 'ultimate-member' ), $field_data['item_name'] ); $license_status = 'license-' . $class . '-notice'; break; case 'no_activations_left': $class = 'error'; // translators: %s: account link. $messages[] = sprintf( __( 'Your license key has reached its activation limit. <a href="%s">View possible upgrades</a> now.', 'ultimate-member' ), 'https://ultimatemember.com/account' ); $license_status = 'license-' . $class . '-notice'; break; case 'license_not_activable': $class = 'error'; $messages[] = __( 'The key you entered belongs to a bundle, please use the product specific license key.', 'ultimate-member' ); $license_status = 'license-' . $class . '-notice'; break; default: $class = 'error'; $error = ! empty( $license->error ) ? $license->error : __( 'unknown_error', 'ultimate-member' ); // translators: %1$s is an error; %2$s is a support link. $messages[] = sprintf( __( 'There was an error with this license key: %1$s. Please <a href="%2$s">contact our support team</a>.', 'ultimate-member' ), $error, 'https://ultimatemember.com/support' ); $license_status = 'license-' . $class . '-notice'; break; } } else { $class = 'error'; $error = ! empty( $license->error ) ? $license->error : __( 'unknown_error', 'ultimate-member' ); // translators: %1$s is an error; %2$s is a support link. $messages[] = sprintf( __( 'There was an error with this license key: %1$s. Please <a href="%2$s">contact our support team</a>.', 'ultimate-member' ), $error, 'https://ultimatemember.com/support' ); $license_status = 'license-' . $class . '-notice'; } } elseif ( ! empty( $license->errors ) ) { $errors = array_keys( $license->errors ); $errors_data = array_values( $license->errors ); $class = 'error'; $error = ! empty( $errors[0] ) ? $errors[0] : __( 'unknown_error', 'ultimate-member' ); $errors_data = ! empty( $errors_data[0][0] ) ? ', ' . $errors_data[0][0] : ''; // translators: %1$s is an error; %2$s is a error data; %3$s is a support link. $messages[] = sprintf( __( 'There was an error with this license key: %1$s%2$s. Please <a href="%3$s">contact our support team</a>.', 'ultimate-member' ), $error, $errors_data, 'https://ultimatemember.com/support' ); $license_status = 'license-' . $class . '-notice'; } else { switch ( $license->license ) { case 'expired': $class = 'expired'; $messages[] = sprintf( // translators: %1$s is a expiry date; %2$s is a renew link. __( 'Your license key expired on %1$s. Please <a href="%2$s" target="_blank">renew your license key</a>.', 'ultimate-member' ), wp_date( get_option( 'date_format', 'F j, Y' ), strtotime( $license->expires ), new DateTimeZone( 'UTC' ) ), 'https://ultimatemember.com/checkout/?edd_license_key=' . $value . '&utm_campaign=admin&utm_source=licenses&utm_medium=expired' ); $license_status = 'license-' . $class . '-notice'; break; case 'revoked': $class = 'error'; $messages[] = sprintf( // translators: %s: support link name. __( 'Your license key has been disabled. Please <a href="%s" target="_blank">contact support</a> for more information.', 'ultimate-member' ), 'https://ultimatemember.com/support?utm_campaign=admin&utm_source=licenses&utm_medium=revoked' ); $license_status = 'license-' . $class . '-notice'; break; case 'missing': $class = 'error'; $messages[] = sprintf( // translators: %s: account page. __( 'Invalid license. Please <a href="%s" target="_blank">visit your account page</a> and verify it.', 'ultimate-member' ), 'https://ultimatemember.com/account?utm_campaign=admin&utm_source=licenses&utm_medium=missing' ); $license_status = 'license-' . $class . '-notice'; break; case 'invalid': case 'site_inactive': $class = 'error'; $messages[] = sprintf( // translators: %1$s is a item name title; %2$s is a account page. __( 'Your %1$s is not active for this URL. Please <a href="%2$s" target="_blank">visit your account page</a> to manage your license key URLs.', 'ultimate-member' ), $field_data['item_name'], 'https://ultimatemember.com/account?utm_campaign=admin&utm_source=licenses&utm_medium=invalid' ); $license_status = 'license-' . $class . '-notice'; break; case 'item_name_mismatch': $class = 'error'; // translators: %s: item name. $messages[] = sprintf( __( 'This appears to be an invalid license key for %s.', 'ultimate-member' ), $field_data['item_name'] ); $license_status = 'license-' . $class . '-notice'; break; case 'no_activations_left': $class = 'error'; // translators: %s: account link. $messages[] = sprintf( __( 'Your license key has reached its activation limit. <a href="%s">View possible upgrades</a> now.', 'ultimate-member' ), 'https://ultimatemember.com/account' ); $license_status = 'license-' . $class . '-notice'; break; case 'license_not_activable': $class = 'error'; $messages[] = __( 'The key you entered belongs to a bundle, please use the product specific license key.', 'ultimate-member' ); $license_status = 'license-' . $class . '-notice'; break; case 'valid': default: $class = 'valid'; $now = time(); $expiration = strtotime( $license->expires ); if ( 'lifetime' === $license->expires ) { $messages[] = __( 'License key never expires.', 'ultimate-member' ); $license_status = 'license-lifetime-notice'; } elseif ( $expiration > $now && $expiration - $now < ( DAY_IN_SECONDS * 30 ) ) { $messages[] = sprintf( // translators: %1$s is an expiry date; %2$s is a renewal link. __( 'Your license key expires soon! It expires on %1$s. <a href="%2$s" target="_blank">Renew your license key</a>.', 'ultimate-member' ), wp_date( get_option( 'date_format', 'F j, Y' ), strtotime( $license->expires ), new DateTimeZone( 'UTC' ) ), 'https://ultimatemember.com/checkout/?edd_license_key=' . $value . '&utm_campaign=admin&utm_source=licenses&utm_medium=renew' ); $license_status = 'license-expires-soon-notice'; } else { $messages[] = sprintf( // translators: %s: expiry date. __( 'Your license key expires on %s.', 'ultimate-member' ), wp_date( get_option( 'date_format', 'F j, Y' ), strtotime( $license->expires ), new DateTimeZone( 'UTC' ) ) ); $license_status = 'license-expiration-date-notice'; } break; } } } else { $class = 'empty'; $messages[] = sprintf( // translators: %s: item name. __( 'To receive updates, please enter your valid %s license key.', 'ultimate-member' ), $field_data['item_name'] ); $license_status = null; } ?> <tr class="um-settings-line"> <th><label for="um_options_<?php echo esc_attr( $field_data['id'] ); ?>"><?php echo esc_html( $field_data['label'] ); ?></label></th> <td> <form method="post" action="" name="um-settings-form" class="um-settings-form"> <input type="hidden" value="save" name="um-settings-action" /> <input type="hidden" name="licenses_settings" value="1" /> <input type="hidden" name="__umnonce" value="<?php echo esc_attr( $um_settings_nonce ); ?>" /> <input type="text" id="um_options_<?php echo esc_attr( $field_data['id'] ); ?>" name="um_options[<?php echo esc_attr( $field_data['id'] ); ?>]" value="<?php echo esc_attr( $value ); ?>" class="um-option-field um-long-field" data-field_id="<?php echo esc_attr( $field_data['id'] ); ?>" /> <?php if ( ! empty( $field_data['description'] ) ) { ?> <div class="description"><?php echo esc_html( $field_data['description'] ); ?></div> <?php } if ( ! empty( $value ) && ( ( is_object( $license ) && isset( $license->license ) && 'valid' === $license->license ) || 'valid' === $license ) ) { ?> <input type="button" class="button um_license_deactivate" id="<?php echo esc_attr( $field_data['id'] ); ?>_deactivate" value="<?php esc_attr_e( 'Clear License', 'ultimate-member' ); ?>"/> <?php } elseif ( empty( $value ) ) { ?> <input type="submit" name="submit" id="submit" class="button button-primary um_license_activate" value="<?php esc_attr_e( 'Activate', 'ultimate-member' ); ?>" /> <?php } else { ?> <input type="submit" name="submit" id="submit" class="button button-primary um_license_reactivate" value="<?php esc_attr_e( 'Re-Activate', 'ultimate-member' ); ?>" /> <input type="button" class="button um_license_deactivate" id="<?php echo esc_attr( $field_data['id'] ); ?>_deactivate" value="<?php esc_attr_e( 'Clear License', 'ultimate-member' ); ?>"/> <?php } if ( ! empty( $messages ) ) { foreach ( $messages as $message ) { ?> <div class="edd-license-data edd-license-<?php echo esc_attr( $class . ' ' . $license_status ); ?>"> <p><?php echo wp_kses( $message, UM()->get_allowed_html( 'admin_notice' ) ); ?></p> </div> <?php } } ?> </form> </td> </tr> <?php } ?> </tbody> </table> </div> <?php return ob_get_clean(); } /** * HTML for Settings > Advanced > Override Templates tab. * * @return string */ public function settings_override_templates_tab() { $um_check_version = time(); $custom_templates = get_transient( 'um_custom_templates_list' ); if ( false !== $custom_templates && array_key_exists( 'time', $custom_templates ) ) { $um_check_version = $custom_templates['time']; } $check_url = add_query_arg( array( 'um_adm_action' => 'check_templates_version', '_wpnonce' => wp_create_nonce( 'check_templates_version' ), ) ); ob_start(); ?> <p> <a href="<?php echo esc_url( $check_url ); ?>" class="button" style="margin-right: 10px;"> <?php esc_html_e( 'Re-check templates', 'ultimate-member' ); ?> </a> <?php // translators: %s: Last checking templates time. echo esc_html( sprintf( __( 'Last update: %s. You could re-check changes manually.', 'ultimate-member' ), wp_date( get_option( 'date_format', 'F j, Y' ) . ' ' . get_option( 'time_format', 'g:i a' ), $um_check_version ) ) ); ?> </p> <div class="clear"></div> <?php include_once UM_PATH . 'includes/admin/core/list-tables/version-template-list-table.php'; return ob_get_clean(); } /** * Scan the template files. * * @param string $template_path Path to the template directory. * @return array */ public static function scan_template_files( $template_path ) { return UM()->common()->theme()::scan_template_files( $template_path ); } /** * Render settings section. * * @param array $section_fields * @param string $current_tab * @param string $current_subtab * * @return string */ public function render_settings_section( $section_fields, $current_tab, $current_subtab ) { $settings_section = ''; if ( ! empty( $section_fields['form_sections'] ) ) { foreach ( $section_fields['form_sections'] as $section_key => $form_section_fields ) { if ( empty( $form_section_fields['fields'] ) ) { continue; } $custom_form_section_content = apply_filters( "um_settings_form_section_{$current_tab}_{$current_subtab}_{$section_key}_custom_content", false ); ob_start(); if ( ! empty( $form_section_fields['title'] ) ) { ?> <h2 class="title"><?php echo wp_kses( $form_section_fields['title'], UM()->get_allowed_html( 'admin_notice' ) ); ?></h2> <?php } if ( ! empty( $form_section_fields['description'] ) ) { ?> <p><?php echo wp_kses( $form_section_fields['description'], UM()->get_allowed_html( 'admin_notice' ) ); ?></p> <?php } if ( false === $custom_form_section_content ) { UM()->admin_forms_settings( array( 'class' => 'um_options-' . $current_tab . '-' . $current_subtab . '-' . $section_key . ' um-third-column', 'prefix_id' => 'um_options', 'fields' => $form_section_fields['fields'], ) )->render_form(); } else { echo $custom_form_section_content; } $settings_section .= ob_get_clean(); } } else { $settings_structure = $this->settings_structure[ $current_tab ]; if ( ! empty( $settings_structure['sections'] ) ) { if ( ! empty( $settings_structure['sections'][ $current_subtab ] ) ) { $settings_subtab_structure = $settings_structure['sections'][ $current_subtab ]; $section_title = array_key_exists( 'title', $settings_subtab_structure ) ? $settings_subtab_structure['title'] : ''; $section_description = array_key_exists( 'description', $settings_subtab_structure ) ? $settings_subtab_structure['description'] : ''; } } else { $section_title = array_key_exists( 'title', $settings_structure ) ? $settings_structure['title'] : ''; $section_description = array_key_exists( 'description', $settings_structure ) ? $settings_structure['description'] : ''; } ob_start(); if ( ! empty( $section_title ) ) { ?> <h2 class="title"><?php echo wp_kses( $section_title, UM()->get_allowed_html( 'admin_notice' ) ); ?></h2> <?php } if ( ! empty( $section_description ) ) { ?> <p><?php echo wp_kses( $section_description, UM()->get_allowed_html( 'admin_notice' ) ); ?></p> <?php } UM()->admin_forms_settings( array( 'class' => 'um_options-' . $current_tab . '-' . $current_subtab . ' um-third-column', 'prefix_id' => 'um_options', 'fields' => $section_fields, ) )->render_form(); $settings_section .= ob_get_clean(); } return $settings_section; } /** * @param array $settings * * @return array */ public function save_email_templates( $settings ) { if ( empty( $settings['um_email_template'] ) ) { return $settings; } $wp_default_protocols = wp_allowed_protocols(); $protocols = array_merge( $wp_default_protocols, array( 'data' ) ); $template = $settings['um_email_template']; $content = wp_kses( stripslashes( $settings[ $template ] ), 'post', $protocols ); $theme_template_path = UM()->mail()->get_template_file( 'theme', $template ); if ( ! file_exists( $theme_template_path ) ) { UM()->mail()->copy_email_template( $template ); } if ( file_exists( $theme_template_path ) ) { $fp = fopen( $theme_template_path, 'w' ); $result = fputs( $fp, $content ); fclose( $fp ); } if ( isset( $result ) && $result !== false ) { unset( $settings['um_email_template'] ); unset( $settings[ $template ] ); } return $settings; } } } includes/admin/core/packages/2.5.0/functions.php 0000644 00000002242 15252504435 0015340 0 ustar 00 <?php if ( ! defined( 'ABSPATH' ) ) { exit; } function um_upgrade_phone_fields250() { UM()->admin()->check_ajax_nonce(); um_maybe_unset_time_limit(); $forms_query = new \WP_Query; $forms = $forms_query->query( array( 'post_type' => 'um_form', 'posts_per_page' => -1, 'fields' => 'ids', ) ); foreach ( $forms as $form_id ) { $forms_fields = get_post_meta( $form_id, '_um_custom_fields', true ); if ( ! is_array( $forms_fields ) ) { continue; } $need_update = false; foreach ( $forms_fields as $key => &$field ) { if ( in_array( $key, array( 'phone_number', 'mobile_number' ), true ) ) { $field['type'] = 'tel'; $need_update = true; } } if ( $need_update ) { update_post_meta( $form_id, '_um_custom_fields', $forms_fields ); } } // remove cached option with users count, don't create separate AJAX upgrade for that delete_option( 'um_cached_users_queue' ); // delete temporarily option for fields upgrade update_option( 'um_last_version_upgrade', '2.5.0' ); wp_send_json_success( array( 'message' => __( 'Phone Number and Mobile Number fields have been successfully updated.', 'ultimate-member' ) ) ); } includes/admin/core/packages/2.5.0/hooks.php 0000644 00000000145 15252504435 0014453 0 ustar 00 <?php if ( ! defined( 'ABSPATH' ) ) exit; return array( 'phone_fields250' => 'phone_fields250', ); includes/admin/core/packages/2.5.0/init.php 0000644 00000001346 15252504435 0014277 0 ustar 00 <?php if ( ! defined( 'ABSPATH' ) ) exit; ?> <script type="text/javascript"> jQuery( document ).ready( function() { um_add_upgrade_log( '<?php echo esc_js( __( 'Updated phone number fields in the UM Forms fields...', 'ultimate-member' ) ) ?>' ); jQuery.ajax({ url: wp.ajax.settings.url, type: 'POST', dataType: 'json', data: { action: 'um_phone_fields250', nonce: um_admin_scripts.nonce }, success: function( response ) { if ( typeof response.data.message != 'undefined' ) { um_add_upgrade_log( response.data.message ); //switch to the next package um_run_upgrade(); } else { um_wrong_ajax(); } }, error: function() { um_something_wrong(); } }); }); </script> includes/admin/core/packages/2.1.17-alpha/functions.php 0000644 00000011577 15252504435 0016522 0 ustar 00 <?php if ( ! defined( 'ABSPATH' ) ) exit; /** * @param $tab * * @return mixed */ function um_upgrade_get_slug2117( $tab ) { $slug = get_post_meta( $tab->ID, 'um_tab_slug', true ); if ( UM()->external_integrations()->is_wpml_active() ) { global $sitepress; $tab_id = $sitepress->get_object_id( $tab->ID, 'um_profile_tabs', true, $sitepress->get_default_language() ); if ( $tab_id && $tab_id != $tab->ID ) { $slug = get_post_meta( $tab_id, 'um_tab_slug', true ); } } return $slug; } function um_upgrade_profile_tabs2117() { UM()->admin()->check_ajax_nonce(); um_maybe_unset_time_limit(); $labels = [ 'name' => _x( 'Profile Tabs', 'Post Type General Name', 'ultimate-member' ), 'singular_name' => _x( 'Profile tab', 'Post Type Singular Name', 'ultimate-member' ), 'menu_name' => __( 'Profile Tabs', 'ultimate-member' ), 'name_admin_bar' => __( 'Profile Tabs', 'ultimate-member' ), 'archives' => __( 'Item Archives', 'ultimate-member' ), 'attributes' => __( 'Item Attributes', 'ultimate-member' ), 'parent_item_colon' => __( 'Parent Item:', 'ultimate-member' ), 'all_items' => __( 'All Items', 'ultimate-member' ), 'add_new_item' => __( 'Add New Item', 'ultimate-member' ), 'add_new' => __( 'Add New', 'ultimate-member' ), 'new_item' => __( 'New Item', 'ultimate-member' ), 'edit_item' => __( 'Edit Item', 'ultimate-member' ), 'update_item' => __( 'Update Item', 'ultimate-member' ), 'view_item' => __( 'View Item', 'ultimate-member' ), 'view_items' => __( 'View Items', 'ultimate-member' ), 'search_items' => __( 'Search Item', 'ultimate-member' ), 'not_found' => __( 'Not found', 'ultimate-member' ), ]; $args = [ 'label' => __( 'Profile Tabs', 'ultimate-member' ), 'description' => __( '', 'ultimate-member' ), 'labels' => $labels, 'supports' => ['title', 'editor' ], 'hierarchical' => false, 'public' => false, 'show_ui' => true, 'show_in_menu' => false, 'menu_position' => 5, 'show_in_admin_bar' => false, 'show_in_nav_menus' => false, 'can_export' => true, 'has_archive' => false, 'exclude_from_search' => true, 'publicly_queryable' => true, 'capability_type' => 'page', ]; register_post_type( 'um_profile_tabs', $args ); $profile_tabs = get_posts( [ 'post_type' => 'um_profile_tabs', 'orderby' => 'menu_order', 'posts_per_page' => -1, ] ); if ( ! empty( $profile_tabs ) ) { $tabs_slugs = []; foreach ( $profile_tabs as $tab ) { $slug = um_upgrade_get_slug2117( $tab ); if ( ! empty( $slug ) && in_array( $slug, $tabs_slugs ) ) { continue; } if ( preg_match( "/[a-z0-9]+$/i", urldecode( $tab->post_name ) ) ) { $tab_slug = sanitize_title( $tab->post_name ); } else { // otherwise use autoincrement and slug generator $auto_increment = UM()->options()->get( 'custom_profiletab_increment' ); $auto_increment = ! empty( $auto_increment ) ? $auto_increment : 1; $tab_slug = "custom_profiletab_{$auto_increment}"; } if ( UM()->external_integrations()->is_wpml_active() ) { global $sitepress; $tab_id = $sitepress->get_object_id( $tab->ID, 'um_profile_tabs', true, $sitepress->get_default_language() ); if ( $tab_id && $tab_id == $tab->ID ) { update_post_meta( $tab->ID, 'um_tab_slug', $tab_slug ); $tabs_slugs[] = $tab_slug; if ( isset( $auto_increment ) ) { $auto_increment++; UM()->options()->update( 'custom_profiletab_increment', $auto_increment ); } // show new profile tab by default - update UM Appearances > Profile Tabs settings if ( UM()->options()->get( 'profile_tab_' . $tab_slug ) === '' ) { UM()->options()->update( 'profile_tab_' . $tab_slug, '1' ); UM()->options()->update( 'profile_tab_' . $tab_slug . '_privacy', '0' ); } } } else { update_post_meta( $tab->ID, 'um_tab_slug', $tab_slug ); $tabs_slugs[] = $tab_slug; if ( isset( $auto_increment ) ) { $auto_increment++; UM()->options()->update( 'custom_profiletab_increment', $auto_increment ); } // show new profile tab by default - update UM Appearances > Profile Tabs settings if ( UM()->options()->get( 'profile_tab_' . $tab_slug ) === '' ) { UM()->options()->update( 'profile_tab_' . $tab_slug, '1' ); UM()->options()->update( 'profile_tab_' . $tab_slug . '_privacy', '0' ); } } } } update_option( 'um_last_version_upgrade', '2.1.17-alpha' ); if ( ! empty( $profile_tabs ) ) { wp_send_json_success( array( 'message' => __( 'Profile tabs have been updated successfully', 'ultimate-member' ) ) ); } else { wp_send_json_success( array( 'message' => __( 'Database has been updated successfully', 'ultimate-member' ) ) ); } } includes/admin/core/packages/2.1.17-alpha/hooks.php 0000644 00000000146 15252504435 0015623 0 ustar 00 <?php if ( ! defined( 'ABSPATH' ) ) exit; return array( 'profile_tabs2117' => 'profile_tabs2117', ); includes/admin/core/packages/2.1.17-alpha/init.php 0000644 00000001310 15252504435 0015435 0 ustar 00 <?php if ( ! defined( 'ABSPATH' ) ) exit; ?> <script type="text/javascript"> jQuery( document ).ready( function() { um_add_upgrade_log( '<?php echo esc_js( __( 'Upgrade profile tabs...', 'ultimate-member' ) ) ?>' ); jQuery.ajax({ url: wp.ajax.settings.url, type: 'POST', dataType: 'json', data: { action: 'um_profile_tabs2117', nonce: um_admin_scripts.nonce }, success: function( response ) { if ( typeof response.data.message != 'undefined' ) { um_add_upgrade_log( response.data.message ); //switch to the next package um_run_upgrade(); } else { um_wrong_ajax(); } }, error: function() { um_something_wrong(); } }); }); </script>