session = wu_get_session('signup'); $this->templates = [ 'signup-main.php' => __('WP Multisite WaaS Legacy Signup', 'wp-multisite-waas'), ]; // add_filter('request', array($this, 'maybe_render_legacy_signup')); add_action('wu_signup_enqueue_scripts', [$this, 'register_scripts']); add_filter('theme_page_templates', [$this, 'add_new_template']); // Add a filter to the save post to inject out template into the page cache add_filter('wp_insert_post_data', [$this, 'register_legacy_templates']); // Add a filter to the template include to determine if the page has our // template assigned and return it's path add_filter('template_include', [$this, 'view_legacy_template']); } /** * Adds our page templates to the page template dropdown. * * @since 2.0.0 * * @param array $posts_templates Existing page templates. * @return array */ public function add_new_template($posts_templates) { if (is_main_site()) { $posts_templates = array_merge($posts_templates, $this->templates); } return $posts_templates; } /** * Adds our template to the pages cache in order to trick WordPress * into thinking the template file exists where it doesn't really exist. * * @since 2.0.0 * * @param array $atts Post data. * @return array */ public function register_legacy_templates($atts) { // Create the key used for the themes cache $cache_key = 'page_templates-' . md5(get_theme_root() . '/' . get_stylesheet()); // Retrieve the cache list. // If it doesn't exist, or it's empty prepare an array $templates = wp_get_theme()->get_page_templates(); if (empty($templates)) { $templates = []; } // New cache, therefore remove the old one wp_cache_delete($cache_key, 'themes'); // Now add our template to the list of templates by merging our templates // with the existing templates array from the cache. $templates = array_merge($templates, $this->templates); // Add the modified cache to allow WordPress to pick it up for listing // available templates wp_cache_add($cache_key, $templates, 'themes', 1800); return $atts; } /** * Checks if our custom template is assigned to the page and display it. * * @since 2.0.0 * * @param string $template The template set to a given page. * @return string */ public function view_legacy_template($template) { // Return the search template if we're searching (instead of the template for the first result) if (is_search()) { return $template; } // Get global post global $post, $signup; // Return template if post is empty if (!$post) { return $template; } $template_slug = get_post_meta($post->ID, '_wp_page_template', true); // Return default template if we don't have a custom one defined if (!isset($this->templates[$template_slug])) { return $template; } $file = wu_path("views/legacy/signup/$template_slug"); // Just to be safe, we check if the file exist first if (file_exists($file)) { return $file; } // Return template return $template; } /** * Loads the necessary scripts. * * @since 2.0.0 * @return void */ public function register_scripts(): void { wp_enqueue_script('wu-block-ui'); wp_register_script('wu-legacy-signup', wu_get_asset('legacy-signup.js', 'js'), ['wu-functions']); wp_localize_script('wu-legacy-signup', 'wpu', [ 'default_pricing_option' => 1, ]); wp_enqueue_script('wu-legacy-signup'); wp_enqueue_style('legacy-signup', wu_get_asset('legacy-signup.css', 'css'), ['dashicons', 'install', 'admin-bar']); wp_enqueue_style('legacy-shortcodes', wu_get_asset('legacy-shortcodes.css', 'css'), ['dashicons', 'install']); wp_add_inline_style('legacy-signup', $this->get_legacy_dynamic_styles()); // Do not get the login if the first step if ('plan' != $this->step) { wp_enqueue_style('login'); } wp_enqueue_style('common'); } /** * Adds the additional dynamic styles. * * @since 2.0.0 * @return string */ public function get_legacy_dynamic_styles() { /** * Get the Colors to be using. */ $primary_color = wu_color(wu_get_setting('primary_color', '#00a1ff')); $accent_color = wu_color(wu_get_setting('accent_color', '#78b336')); $accent_color_2 = wu_color($accent_color->darken(4)); ob_start(); // phpcs:disable ?> .wu-content-plan .plan-tier h4 { background-color: #getHex(); ?>; color: isDark() ? "white" : "#333"; ?> !important; } .wu-content-plan .plan-tier.callout h6 { background-color: #getHex(); ?>; color: isDark() ? "#f9f9f9" : "rgba(39,65,90,.5)"; ?> !important; } .wu-content-plan .plan-tier.callout h4 { background-color: #getHex(); ?>; color: isDark() ? "white" : "#333"; ?> !important; } product = $product; } $request['pagename'] = $checkout_page_slug; return $this->legacy_signup(); } return $request; } /** * Renders the legacy checkout. * * @since 2.0.0 * @return void */ public function legacy_signup(): void { status_header(200); $this->session = wu_get_session('signup'); $this->session->set('form', ['not-empty']); // Apply a filter so we can add steps in the future $this->steps = $this->get_steps(); // Set the current step based on the get $this->step = $this->get_current_step(); $this->handle_post(); wu_get_template( 'legacy/signup/signup-main', [ 'signup' => $this, ] ); exit; } /** * Check Geolocation * * @return void */ public function check_geolocation(): void { $location = \WP_Ultimo\Geolocation::geolocate_ip(); $this->session->set('geolocation', $location); $allowed_countries = wu_get_setting('allowed_countries'); if (isset($location['country']) && $location['country'] && $allowed_countries) { if ( ! in_array($location['country'], $allowed_countries, true)) { wp_die(apply_filters('wu_geolocation_error_message', __('Sorry. Our service is not allowed in your country.', 'wp-multisite-waas'))); } } } /** * Gets the info for the current step. * * @since 2.0.0 * @return array */ protected function get_current_step_info() { return $this->steps[ $this->step ]; } /** * Handles a post submission. * * @since 2.0.0 * @return void */ protected function handle_post() { $is_save = wu_request('save_step'); $current_step = $this->get_current_step_info(); /** * If we are in the middle of a saving request, we need to call the handler */ if ($is_save || $current_step['hidden']) { /** Checks if the view has a handler of its own */ if (isset($current_step['handler']) && $current_step['handler']) { $handler_function = $current_step['handler']; } else { $handler_function = [$this, 'default_save']; } /** Allows for handler rewrite */ $handler_function = apply_filters("wu_signup_step_handler_$this->step", $handler_function); call_user_func($handler_function); } } /** * The first invisible step, handles the creation of the transient saver * * @since 1.4.0 * @return void */ public function begin_signup(): void { /** * Check Geo-location */ $this->check_geolocation(); /** Create the unique ID we well use from now on */ $uniqid = uniqid('', true); /** Initializes the content holder with the honeypot unique id */ $content = [ 'honeypot_id' => uniqid(''), ]; /** * Saves the coupon code in the request, only if that option is available */ if (isset($_REQUEST['coupon']) && $_REQUEST['coupon'] && wu_get_setting('enable_coupon_codes', 'url_and_field') != 'disabled') { // Adds to the payload $content['coupon'] = $_REQUEST['coupon']; } /** * Check if user came from a pricing select table */ if (isset($_REQUEST['plan_id']) && isset($_REQUEST['plan_freq']) && WU_Gateway::check_frequency($_REQUEST['plan_freq'])) { $content['plan_id'] = $_REQUEST['plan_id']; $content['plan_freq'] = $_REQUEST['plan_freq']; $content['skip_plan'] = true; } /** * Check if we only have one plan and the skip_plan enabled */ $plans = wu_get_plans(); if (wu_get_setting('skip_plan', false) && count($plans) === 1) { $billing_frequency = wu_get_setting('default_pricing_option', 1); $plan = reset($plans); // Append that to the content $content['plan_id'] = $plan->id; $content['plan_freq'] = $billing_frequency; $content['skip_plan'] = true; $_REQUEST['skip_plan'] = 1; } /** * Check if we are settings the template via the URL * * @since 1.7.3 */ if (isset($_REQUEST['template_id']) && wu_get_setting('allow_template')) { // Check if the template is valid $site = new WU_Site_Template($_REQUEST['template_id']); if ($site->is_template) { $content['template'] = $_REQUEST['template_id']; $content['skip_template_selection'] = true; } } $this->session->set('form', $content); /** Go to the next step */ $this->next_step(); } /** * Check if the current page is a customizer page. */ public static function is_customizer(): bool { $exclude_list = apply_filters('wu_replace_signup_urls_exclude', ['wu-signup-customizer-preview']); foreach ($exclude_list as $replace_word) { if (isset($_GET[ $replace_word ])) { return true; } } return false; } /** * Returns the first step of the signup process * * @return string */ public function get_first_step() { $keys = array_keys($this->get_steps()); if (isset($keys[1])) { return $keys[1]; } else { return false; } } /** * Get the current step * * @return string */ public function get_current_step() { $current_step = wu_request('step', current(array_keys($this->steps))); // Always get the first step for the customizer // if (static::is_customizer()) { $current_step = $this->get_first_step(); } return apply_filters('wu_current_step', $current_step); } /** * Includes the template for that particular step; If none is set (false), includes the default template * * @param string $step The current step. * @return void */ public function get_step_view($step): void { $transient = $this->session->get('form'); $geo = $this->session->get('geolocation'); /** * Set the errors */ if (null === $this->results) { $this->results = ['errors' => new \WP_Error()]; } if (empty($_POST)) { $this->results = array_merge($this->results, $transient); } /** * Builds the array containing the available elements inside the template */ $args = [ 'signup' => $this, 'transient' => $transient, 'fields' => $this->steps[ $step ]['fields'] ?? [], 'results' => $this->results, ]; /** * Checks if anything is passed to the view element */ if (isset($this->steps[ $step ]['view']) && $this->steps[ $step ]['view']) { wu_get_template('legacy/signup/steps/' . $this->steps[ $step ]['view'], $args); } else { $found = locate_template("wp-ultimo/signup/steps/step-$step.php"); /** * Let's try to locate a custom template on the user's theme. If it's there, we use it instead */ if ($found) { wu_get_template("legacy/signup/steps/step-$step", $args); } else { wu_get_template('legacy/signup/steps/step-default', $args); } } } /** * Set and return the steps and fields of each step. * * @since 2.0.0 * * @param boolean $include_hidden If we should return hidden steps as well. * @param boolean $filtered If we should apply filters. * @return array */ public function get_steps($include_hidden = true, $filtered = true) { // Set the Steps $steps = []; // Plan Selector $steps['plan'] = [ 'name' => __('Pick a Plan', 'wp-multisite-waas'), 'desc' => __('Which one of our amazing plans you want to get?', 'wp-multisite-waas'), 'view' => 'step-plans', 'handler' => [$this, 'plans_save'], 'order' => 10, 'fields' => false, 'core' => true, ]; $site_templates = [ 2, ]; // We add template selection if this has template if ($site_templates) { $steps['template'] = [ 'name' => __('Template Selection', 'wp-multisite-waas'), 'desc' => __('Select the base template of your new site.', 'wp-multisite-waas'), 'view' => 'step-template', 'order' => 20, 'handler' => false, 'core' => true, ]; } // Domain registering $steps['domain'] = [ 'name' => __('Site Details', 'wp-multisite-waas'), 'desc' => __('Ok, now it\'s time to pick your site url and title!', 'wp-multisite-waas'), 'handler' => [$this, 'domain_save'], 'view' => false, 'order' => 30, 'core' => true, 'fields' => apply_filters( 'wu_signup_fields_domain', [ 'blog_title' => [ 'order' => 10, 'name' => apply_filters('wu_signup_site_title_label', __('Site Title', 'wp-multisite-waas')), 'type' => 'text', 'default' => '', 'placeholder' => '', 'tooltip' => apply_filters('wu_signup_site_title_tooltip', __('Select the title your site is going to have.', 'wp-multisite-waas')), 'required' => true, 'core' => true, ], 'blogname' => [ 'order' => 20, 'name' => apply_filters('wu_signup_site_url_label', __('URL', 'wp-multisite-waas')), 'type' => 'text', 'default' => '', 'placeholder' => '', 'tooltip' => apply_filters('wu_signup_site_url_tooltip', __('Site urls can only contain lowercase letters (a-z) and numbers and must be at least 4 characters. .', 'wp-multisite-waas')), 'required' => true, 'core' => true, ], 'url_preview' => [ 'order' => 30, 'name' => __('Site URL Preview', 'wp-multisite-waas'), 'type' => 'html', 'content' => wu_get_template_contents('legacy/signup/steps/step-domain-url-preview'), ], 'submit' => [ 'order' => 100, 'type' => 'submit', 'name' => __('Continue to the next step', 'wp-multisite-waas'), 'core' => true, ], ] ), ]; /** * Since there are some conditional fields on the accounts step, we need to declare the variable before * so we can append items and filter it later */ $account_fields = [ 'user_name' => [ 'order' => 10, 'name' => apply_filters('wu_signup_username_label', __('Username', 'wp-multisite-waas')), 'type' => 'text', 'default' => '', 'placeholder' => '', 'tooltip' => apply_filters('wu_signup_username_tooltip', __('Username must be at least 4 characters.', 'wp-multisite-waas')), 'required' => true, 'core' => true, ], 'user_email' => [ 'order' => 20, 'name' => apply_filters('wu_signup_email_label', __('Email', 'wp-multisite-waas')), 'type' => 'email', 'default' => '', 'placeholder' => '', 'tooltip' => apply_filters('wu_signup_email_tooltip', ''), 'required' => true, 'core' => true, ], 'user_pass' => [ 'order' => 30, 'name' => apply_filters('wu_signup_password_label', __('Password', 'wp-multisite-waas')), 'type' => 'password', 'default' => '', 'placeholder' => '', 'tooltip' => apply_filters('wu_signup_password_tooltip', __('Your password should be at least 6 characters long.', 'wp-multisite-waas')), 'required' => true, 'core' => true, ], 'user_pass_conf' => [ 'order' => 40, 'name' => apply_filters('wu_signup_password_conf_label', __('Confirm Password', 'wp-multisite-waas')), 'type' => 'password', 'default' => '', 'placeholder' => '', 'tooltip' => apply_filters('wu_signup_password_conf_tooltip', ''), 'required' => true, 'core' => true, ], /** * HoneyPot Field */ 'site_url' => [ 'order' => random_int(1, 59), // Use random order for Honeypot 'name' => __('Site URL', 'wp-multisite-waas'), 'type' => 'text', 'default' => '', 'placeholder' => '', 'tooltip' => '', 'core' => true, 'wrapper_attributes' => [ 'style' => 'display: none;', ], 'attributes' => [ 'autocomplete' => 'nope', ], ], ]; /** * Check and Add Coupon Code Fields * * @since 1.4.0 */ // if (wu_get_setting('enable_coupon_codes', 'url_and_field') == 'url_and_field') { // ** // * Test default state, if we have a coupon saved // */ // $coupon = $this->has_coupon_code(); // $account_fields['has_coupon'] = array( // 'order' => 50, // 'type' => 'checkbox', // 'name' => __('Have a coupon code?', 'wp-multisite-waas'), // 'core' => true, // 'check_if' => 'coupon', // Check if the input with this name is selected // 'checked' => $coupon ? true : false, // ); // $account_fields['coupon'] = array( // 'order' => 60, // 'name' => __('Coupon Code', 'wp-multisite-waas'), // 'type' => 'text', // 'default' => '', // 'placeholder' => '', // 'tooltip' => __('The code should be an exact match. This field is case-sensitive.', 'wp-multisite-waas'), // 'requires' => array('has_coupon' => true), // 'core' => true, // ); // } // /** // * Check and Add the Terms field // * @since 1.0.4 // */ // if (wu_get_setting('enable_terms')) { // $account_fields['agree_terms'] = array( // 'order' => 70, // 'type' => 'checkbox', // 'checked' => false, // 'name' => sprintf(__('I agree with the Terms of Service', 'wp-multisite-waas'), $this->get_terms_url()), // 'core' => true, // ); // } /** * Submit Field */ $account_fields['submit'] = [ 'order' => 100, 'type' => 'submit', 'name' => __('Create Account', 'wp-multisite-waas'), 'core' => true, ]; // Account registering $steps['account'] = [ 'name' => __('Account Details', 'wp-multisite-waas'), 'view' => false, 'handler' => [$this, 'account_save'], 'order' => 40, 'core' => true, 'fields' => apply_filters('wu_signup_fields_account', $account_fields), ]; /** * Add additional steps via filters */ $steps = $filtered ? apply_filters('wp_ultimo_registration_steps', $steps) : $steps; // Sort elements based on their order uasort($steps, [$this, 'sort_steps_and_fields']); // Sorts each of the fields block foreach ($steps as &$step) { $step = wp_parse_args( $step, [ 'hidden' => false, ] ); if (isset($step['fields']) && is_array($step['fields'])) { // Sort elements based on their order uasort($step['fields'], [$this, 'sort_steps_and_fields']); } } /** * Adds the hidden step now responsible for validating data entry and the actual account creation * * @since 1.4.0 */ $begin_signup = [ 'begin-signup' => [ 'name' => __('Begin Signup Process', 'wp-multisite-waas'), 'handler' => [$this, 'begin_signup'], 'view' => false, 'hidden' => true, 'order' => 0, 'core' => true, ], ]; /** * Adds the hidden step now responsible for validating data entry and the actual account creation * * @since 1.4.0 */ $create_account = [ 'create-account' => [ 'name' => __('Creating Account', 'wp-multisite-waas'), 'handler' => [$this, 'create_account'], 'view' => false, 'hidden' => true, 'core' => true, 'order' => 1_000_000_000, ], ]; /** * Glue the required steps together with the filterable ones */ $steps = array_merge($begin_signup, $steps, $create_account); /** * Filter the hidden ones, if we need to... * * @var array */ if ( ! $include_hidden) { $steps = array_filter($steps, fn($step) => ! (isset($step['hidden']) && $step['hidden'])); } // If we need to add that if ( ! $this->has_plan_step()) { unset($steps['plan']); } return $steps; } /** * Check the transient, and if it does not exists, throw fatal * * @param bool $die If we should die when there's no transient set. * @return array The transient information */ public static function get_transient($die = true) { if (self::is_customizer()) { $transient = [ 'not-empty' => '', ]; } else { $transient = wu_get_session('signup')->get('form'); } if ($die && empty($transient)) { // wp_die(__('Try again', 'wp-multisite-waas')); } if (is_null($transient)) { return []; } return $transient; } /** * Update the transient data in out database * * @param array $transient Array containing the transient data. */ public function update_transient($transient): void { $this->session->set('form', $transient); $this->session->commit(); } /** * Checks transient data to see if the plan step is necessary */ public function has_plan_step(): bool { $transient = static::get_transient(); return ! (isset($transient['skip_plan']) && isset($transient['plan_id']) && isset($transient['plan_freq'])); } /** * Get the link for the next step * * @param array $params The params. * @return string The link for the next step */ public function get_next_step_link($params = []) { // Add CS if (isset($_GET['cs'])) { $params['cs'] = $_GET['cs']; } if (isset($_REQUEST['customized'])) { $params['customized'] = $_REQUEST['customized']; } if (isset($_REQUEST['skip_plan']) && 1 == $_REQUEST['skip_plan']) { unset($this->steps['plan']); unset($params['skip_plan']); } if (isset($_REQUEST['template_id'])) { $plan = false; if (isset($_REQUEST['plan_id'])) { $plan = wu_get_plan($_REQUEST['plan_id']); } $templates = array_keys((array) wu_get_setting('templates')); if ( ($plan && $plan->is_template_available($_REQUEST['template_id'])) || in_array($_REQUEST['template_id'], $templates)) { unset($this->steps['template']); unset($params['skip_template_selection']); } } $keys = array_keys($this->steps); $url = add_query_arg('step', $keys[ array_search($this->step, array_keys($this->steps)) + 1 ]); foreach ($params as $param => $value) { $url = add_query_arg($param, $value, $url); } return $url; } /** * Redirects the user to the next step on the signup flow * * @param array $args Arguments to build the URL. * @return void */ public function next_step($args = []): void { /** Redirect the user to the next step */ wp_safe_redirect(esc_url_raw($this->get_next_step_link($args))); /** Kill the execution after the redirect */ exit; } /** * Get the link for the previous step * * @param array $params The params. * @return string The link for the previous step */ public function get_prev_step_link($params = []) { // Add CS if (isset($_GET['cs'])) { $params['cs'] = $_GET['cs']; } if (isset($_REQUEST['customized'])) { $params['customized'] = $_REQUEST['customized']; } $keys = array_keys($this->steps); $search_key = array_search($this->step, array_keys($this->steps)) - 1 >= 0 ? array_search($this->step, array_keys($this->steps)) - 1 : false; $key = false === $search_key ? '' : $keys[ $search_key ]; if ( ! $key || 'begin-signup' == $key) { return false; } $url = add_query_arg('step', $key); foreach ($params as $param => $value) { $url = add_query_arg($param, $value, $url); } return $url; } /** * Sorts the steps. * * @param array $a Value 1. * @param array $b Value to compare against. * @return boolean */ public function sort_steps_and_fields($a, $b) { $a['order'] = isset($a['order']) ? (int) $a['order'] : 50; $b['order'] = isset($b['order']) ? (int) $b['order'] : 50; return $a['order'] - $b['order']; } /** * Display the necessary fields for the plan template * * @since 1.5.0 Takes the frequency parameter * * @param boolean $current_plan The current plan. * @param string $step The step. * @param integer $freq The freq. * @return void */ public function form_fields($current_plan = false, $step = 'plan', $freq = false): void { /** Select the default frequency */ $freq = $freq ?: wu_get_setting('default_pricing_option'); ?> domain; if (wu_get_setting('enable_multiple_domains', false) && $domain_options) { $domain = array_shift($domain_options); } $domain = rtrim($domain . $site->path, '/'); /** * Allow plugin developers to filter the URL used in the previewer * * @since 1.7.2 * @param string Default domain being used right now, useful for manipulations * @param array List of all the domain options entered in the WP Multisite WaaS Settings -> Network Settings -> Domain Options * @return string New domain to be used */ return apply_filters('get_site_url_for_previewer', $domain, $domain_options); // phpcs:ignore } /** * We pass the following info */ public function plans_save(): void { // Get transient $transient = static::get_transient(); // Check referer check_admin_referer('signup_form_1', '_signup_form'); // Errors $this->results['errors'] = new \WP_Error(); // We need now to check for plan if ( ! isset($_POST['plan_id'])) { $this->results['errors']->add('plan_id', __('You don\'t have any plan selected.', 'wp-multisite-waas')); } else { // We need now to check if the plan exists $plan = wu_get_product($_POST['plan_id']); if ( ! $plan->exists()) { $this->results['errors']->add('plan_id', __('The plan you\'ve selected doesn\'t exist.', 'wp-multisite-waas')); } } $transient = apply_filters('wp_ultimo_registration_step_plans_save_transient', $transient); // Action hook for users do_action('wp_ultimo_registration_step_plans_save', $transient); // Stay on the form if we get any errors if ($this->results['errors']->get_error_code()) { return; } /** Update Transient Content */ $transient['plan_freq'] = $_POST['plan_freq']; $transient['plan_id'] = $_POST['plan_id']; /** Update Data */ $this->update_transient($transient); /** Go to the next step */ $this->next_step(); } /** * Personal Info Settings. */ public function domain_save(): void { // Get transient $transient = static::get_transient(); // Check referer check_admin_referer('signup_form_1', '_signup_form'); /** * Make sure we trim() the contents of the form. * * @since 1.9.0 */ $_POST = array_map('trim', $_POST); // Get validation errors $this->results = validate_blog_form(); /** Sanitizes Input */ $transient = array_merge($transient, $this->filter_post_array($_POST)); // Action hook for users do_action('wp_ultimo_registration_step_domain_save', $transient); // Stay on the form if we get any errors if ($this->results['errors']->get_error_code()) { $this->results = array_merge($this->results, $_POST); return; } // Re-saves the transient $this->update_transient($transient); /** Go to the next step */ $this->next_step(); } /** * Filters the input variables and sanitizes its contents * * @param array $post The post. * @param array $exclude_list The exclude list. * @return array */ public function filter_post_array($post, $exclude_list = false) { $exclude_list = $exclude_list ?: ['_signup_form', '_wp_http_referer']; /** Filter Array */ $post = $this->array_filter_key($post, fn($element_key) => ! in_array($element_key, $exclude_list, true)); /** Sanitizes the input */ $post = array_map(fn($element) => sanitize_text_field($element), $post); return $post; } /** * Helper function to filter based on key. * * @since 2.0.0 * * @param array $array The array. * @param callable $callback The callback. */ public function array_filter_key(array $array, $callback): array { $matched_keys = array_filter(array_keys($array), $callback ?? fn($v, $k): bool => ! empty($v), null === $callback ? ARRAY_FILTER_USE_BOTH : 0); return array_intersect_key($array, array_flip($matched_keys)); } /** * Get the active until + trial days, to allow for putting subscription on hold * * @since 1.5.5 * @param string $now Time now. * @param integer $trial_days Trial days. */ public static function get_active_until_with_trial($now, $trial_days): string { $active_until = new \DateTime($now); $active_until->add(new \DateInterval('P' . $trial_days . 'D')); return $active_until->format('Y-m-d H:i:s'); } /** * Adds a new Step to the sign-up flow * * @since 1.4.0 * @param string $id The field id. * @param integer $order The field order. * @param array $step The step info. * @return void */ public function add_signup_step($id, $order, $step): void { add_filter( 'wp_ultimo_registration_steps', function ($steps) use ($id, $order, $step) { // Save new order $step['order'] = $order; // mark as not core $step['core'] = false; $steps[ $id ] = $step; return $steps; } ); } /** * Adds a new field to a step the sign-up flow * * @since 1.4.0 * @param string $step The step name. * @param string $id The field id. * @param integer $order The field order. * @param array $field The field. * @return void */ public function add_signup_field($step, $id, $order, $field): void { add_filter( 'wp_ultimo_registration_steps', function ($steps) use ($step, $id, $order, $field) { // Checks for honey-trap id if ('site_url' === $id) { wp_die(__('Please, do not use the "site_url" as one of your custom fields\' ids. We use it as a honeytrap field to prevent spam registration. Consider alternatives such as "url" or "website".', 'wp-multisite-waas')); } // Saves the order $field['order'] = $order; // mark as not core $field['core'] = false; $steps[ $step ]['fields'][ $id ] = $field; return $steps; } ); } }