Escape everything that should be escaped. Add nonce checks where needed. Sanitize all inputs. Apply Code style changes across the codebase. Correct many deprecation notices. Optimize load order of many filters.
1347 lines
33 KiB
PHP
1347 lines
33 KiB
PHP
<?php
|
|
/**
|
|
* Handles the processing of new membership purchases.
|
|
*
|
|
* @package WP_Ultimo
|
|
* @subpackage Checkout
|
|
* @since 2.0.0
|
|
*/
|
|
|
|
// phpcs:disable
|
|
|
|
namespace WP_Ultimo\Checkout;
|
|
|
|
// Exit if accessed directly
|
|
defined('ABSPATH') || exit;
|
|
|
|
use \WP_Ultimo\Checkout\Cart;
|
|
|
|
/**
|
|
* Handles the processing of new membership purchases.
|
|
*
|
|
* @since 2.0.0
|
|
*/
|
|
class Legacy_Checkout {
|
|
|
|
use \WP_Ultimo\Traits\Singleton;
|
|
|
|
/**
|
|
* Holds checkout errors.
|
|
*
|
|
* @since 2.0.0
|
|
* @var \WP_Error|null
|
|
*/
|
|
public $errors;
|
|
|
|
/**
|
|
* Holds checkout errors.
|
|
*
|
|
* @since 2.0.0
|
|
* @var \WP_Error|null
|
|
*/
|
|
public $results;
|
|
|
|
/**
|
|
* Current step of the signup flow.
|
|
*
|
|
* @since 2.0.0
|
|
* @var string
|
|
*/
|
|
public $step;
|
|
|
|
/**
|
|
* List of steps for the signup flow.
|
|
*
|
|
* @since 2.0.0
|
|
* @var array
|
|
*/
|
|
public $steps;
|
|
|
|
/**
|
|
* Product being purchased, if that exists.
|
|
*
|
|
* @since 2.0.0
|
|
* @var null|\WP_Ultimo\Models\Product
|
|
*/
|
|
public $product;
|
|
|
|
/**
|
|
* Session object.
|
|
*
|
|
* @since 2.0.0
|
|
* @var \WP_Ultimo\Session.
|
|
*/
|
|
protected $session;
|
|
|
|
/**
|
|
* Page templates to add.
|
|
*
|
|
* We use this to inject the legacy-signup.php page template option
|
|
* onto the post/page edit page on the main site.
|
|
*
|
|
* @since 2.0.0
|
|
* @var array
|
|
*/
|
|
protected $templates;
|
|
|
|
/**
|
|
* Initializes the Checkout singleton and adds hooks.
|
|
*
|
|
* @since 2.0.0
|
|
* @return void
|
|
*/
|
|
public function init(): void {
|
|
|
|
$this->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: #<?php echo $primary_color->getHex(); ?>;
|
|
color: <?php echo $primary_color->isDark() ? "white" : "#333"; ?> !important;
|
|
}
|
|
|
|
.wu-content-plan .plan-tier.callout h6 {
|
|
background-color: #<?php echo $accent_color->getHex(); ?>;
|
|
color: <?php echo $accent_color->isDark() ? "#f9f9f9" : "rgba(39,65,90,.5)"; ?> !important;
|
|
}
|
|
|
|
.wu-content-plan .plan-tier.callout h4 {
|
|
background-color: #<?php echo $accent_color_2->getHex(); ?>;
|
|
color: <?php echo $accent_color->isDark() ? "white" : "#333"; ?> !important;
|
|
}
|
|
|
|
<?php
|
|
|
|
// phpcs:enable
|
|
|
|
return ob_get_clean();
|
|
}
|
|
|
|
/**
|
|
* Checks if we should pre-fill checkout fields based on the request.
|
|
*
|
|
* We do a couple of clever things here:
|
|
* 1. We check for a plan slug right after the checkout/slug of the main page.
|
|
*
|
|
* @since 2.0.0
|
|
*
|
|
* @param array $request WordPress request.
|
|
* @return array
|
|
*/
|
|
public function maybe_render_legacy_signup($request) {
|
|
|
|
$checkout_page_slug = 'register';
|
|
|
|
$page_name = $request['pagename'] ?? '';
|
|
|
|
if (str_starts_with((string) $page_name, $checkout_page_slug)) {
|
|
$page = explode('/', (string) $page_name);
|
|
|
|
/**
|
|
* Product passed
|
|
*
|
|
* @todo needs to check for frequency and unit.
|
|
*/
|
|
if (isset($page[1])) {
|
|
$product_slug = $page[1];
|
|
|
|
$product = wu_get_product_by_slug($product_slug);
|
|
|
|
$this->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 <a href="%s" target="_blank">Terms of Service</a>', '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');
|
|
|
|
?>
|
|
|
|
<?php if ('plan' == $step) { ?>
|
|
|
|
<input type="hidden" name="wu_action" value="wu_new_user">
|
|
<input type="hidden" id="wu_plan_freq" name="plan_freq" value="<?php echo $freq; ?>">
|
|
|
|
<?php
|
|
}
|
|
?>
|
|
|
|
<input type="hidden" name="save_step" value="1">
|
|
|
|
<?php wp_nonce_field('signup_form_1', '_signup_form'); ?>
|
|
|
|
<!-- if this is a change plan, let us know -->
|
|
<?php if ($current_plan) : ?>
|
|
|
|
<input type="hidden" name="changing-plan" value="1">
|
|
|
|
<?php endif; ?>
|
|
|
|
<?php
|
|
}
|
|
|
|
/**
|
|
* Get the primary site URL we will use on the URL previewer, during sign-up
|
|
*
|
|
* @since 1.7.2
|
|
* @return string
|
|
*/
|
|
public function get_site_url_for_previewer() {
|
|
|
|
$domain_options = [];
|
|
|
|
$site = get_current_site();
|
|
|
|
$domain = $site->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;
|
|
}
|
|
);
|
|
}
|
|
}
|