1457 lines
34 KiB
PHP
1457 lines
34 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() {
|
|
|
|
$this->session = wu_get_session('signup');
|
|
|
|
$this->templates = array(
|
|
'signup-main.php' => __('WP Multisite WaaS Legacy Signup', 'wp-ultimo'),
|
|
);
|
|
|
|
// add_filter('request', array($this, 'maybe_render_legacy_signup'));
|
|
|
|
add_action('wu_signup_enqueue_scripts', array($this, 'register_scripts'));
|
|
|
|
add_filter('theme_page_templates', array($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', array($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', array($this, 'view_legacy_template'));
|
|
|
|
} // end init;
|
|
|
|
/**
|
|
* 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);
|
|
|
|
} // end if;
|
|
|
|
return $posts_templates;
|
|
|
|
} // end add_new_template;
|
|
|
|
/**
|
|
* 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 = array();
|
|
|
|
} // end if;
|
|
|
|
// 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;
|
|
|
|
} // end register_legacy_templates;
|
|
|
|
/**
|
|
* 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;
|
|
|
|
} // end if;
|
|
|
|
// Get global post
|
|
global $post, $signup;
|
|
|
|
// Return template if post is empty
|
|
if (!$post) {
|
|
|
|
return $template;
|
|
|
|
} // end if;
|
|
|
|
$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;
|
|
|
|
} // end if;
|
|
|
|
$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;
|
|
|
|
} // end if;
|
|
|
|
// Return template
|
|
return $template;
|
|
|
|
} // end view_legacy_template;
|
|
|
|
/**
|
|
* Loads the necessary scripts.
|
|
*
|
|
* @since 2.0.0
|
|
* @return void
|
|
*/
|
|
public function register_scripts() {
|
|
|
|
wp_enqueue_script('wu-block-ui');
|
|
|
|
wp_register_script('wu-legacy-signup', wu_get_asset('legacy-signup.js', 'js'), array('wu-functions'));
|
|
|
|
wp_localize_script('wu-legacy-signup', 'wpu', array(
|
|
'default_pricing_option' => 1,
|
|
));
|
|
|
|
wp_enqueue_script('wu-legacy-signup');
|
|
|
|
wp_enqueue_style('legacy-signup', wu_get_asset('legacy-signup.css', 'css'), array('dashicons', 'install', 'admin-bar'));
|
|
|
|
wp_enqueue_style('legacy-shortcodes', wu_get_asset('legacy-shortcodes.css', 'css'), array('dashicons', 'install'));
|
|
|
|
wp_add_inline_style('legacy-signup', $this->get_legacy_dynamic_styles());
|
|
|
|
// Do not get the login if the first step
|
|
if ($this->step != 'plan') {
|
|
|
|
wp_enqueue_style('login');
|
|
|
|
} // end if;
|
|
|
|
wp_enqueue_style('common');
|
|
|
|
} // end register_scripts;
|
|
|
|
/**
|
|
* 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();
|
|
|
|
} // end get_legacy_dynamic_styles;
|
|
|
|
/**
|
|
* 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 = isset($request['pagename']) ? $request['pagename'] : '';
|
|
|
|
if (strncmp((string) $page_name, $checkout_page_slug, strlen($checkout_page_slug)) === 0) {
|
|
|
|
$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;
|
|
|
|
} // end if;
|
|
|
|
$request['pagename'] = $checkout_page_slug;
|
|
|
|
return $this->legacy_signup();
|
|
|
|
} // end if;
|
|
|
|
return $request;
|
|
|
|
} // end maybe_render_legacy_signup;
|
|
|
|
/**
|
|
* Renders the legacy checkout.
|
|
*
|
|
* @since 2.0.0
|
|
* @return void
|
|
*/
|
|
public function legacy_signup() {
|
|
|
|
status_header(200);
|
|
|
|
$this->session = wu_get_session('signup');
|
|
|
|
$this->session->set('form', array('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', array(
|
|
'signup' => $this,
|
|
));
|
|
|
|
exit;
|
|
|
|
} // end legacy_signup;
|
|
|
|
/**
|
|
* Check Geolocation
|
|
*
|
|
* @return void
|
|
*/
|
|
public function check_geolocation() {
|
|
|
|
$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-ultimo')));
|
|
|
|
} // end if;
|
|
|
|
} // end if;
|
|
|
|
} // end check_geolocation;
|
|
|
|
/**
|
|
* Gets the info for the current step.
|
|
*
|
|
* @since 2.0.0
|
|
* @return array
|
|
*/
|
|
protected function get_current_step_info() {
|
|
|
|
return $this->steps[$this->step];
|
|
|
|
} // end get_current_step_info;
|
|
|
|
/**
|
|
* 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 = array($this, 'default_save');
|
|
|
|
} // end if;
|
|
|
|
/** Allows for handler rewrite */
|
|
$handler_function = apply_filters("wu_signup_step_handler_$this->step", $handler_function);
|
|
|
|
call_user_func($handler_function);
|
|
|
|
} // end if;
|
|
|
|
} // end handle_post;
|
|
|
|
/**
|
|
* The first invisible step, handles the creation of the transient saver
|
|
*
|
|
* @since 1.4.0
|
|
* @return void
|
|
*/
|
|
public function begin_signup() {
|
|
|
|
/**
|
|
* 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 = array(
|
|
'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'];
|
|
|
|
} // end if;
|
|
|
|
/**
|
|
* 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;
|
|
|
|
} // end if;
|
|
|
|
/**
|
|
* 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;
|
|
|
|
} // end if;
|
|
|
|
/**
|
|
* 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;
|
|
|
|
} // end if;
|
|
|
|
} // end if;
|
|
|
|
$this->session->set('form', $content);
|
|
|
|
/** Go to the next step */
|
|
$this->next_step();
|
|
|
|
} // end begin_signup;
|
|
/**
|
|
* Check if the current page is a customizer page.
|
|
*/
|
|
public static function is_customizer(): bool {
|
|
|
|
$exclude_list = apply_filters('wu_replace_signup_urls_exclude', array('wu-signup-customizer-preview'));
|
|
|
|
foreach ($exclude_list as $replace_word) {
|
|
|
|
if (isset($_GET[$replace_word])) {
|
|
|
|
return true;
|
|
|
|
} // end if;
|
|
|
|
} // end foreach;
|
|
|
|
return false;
|
|
|
|
} // end is_customizer;
|
|
|
|
/**
|
|
* 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;
|
|
|
|
} // end if;
|
|
|
|
} // end get_first_step;
|
|
|
|
/**
|
|
* 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 ($this->is_customizer()) {
|
|
|
|
$current_step = $this->get_first_step();
|
|
|
|
} // end if;
|
|
|
|
return apply_filters('wu_current_step', $current_step);
|
|
|
|
} // end get_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) {
|
|
|
|
$transient = $this->session->get('form');
|
|
$geo = $this->session->get('geolocation');
|
|
|
|
/**
|
|
* Set the errors
|
|
*/
|
|
if ($this->results === null) {
|
|
|
|
$this->results = array('errors' => new \WP_Error);
|
|
|
|
} // end if;
|
|
|
|
if (empty($_POST)) {
|
|
|
|
$this->results = array_merge($this->results, $transient);
|
|
|
|
} // end if;
|
|
|
|
/**
|
|
* Builds the array containing the available elements inside the template
|
|
*/
|
|
$args = array(
|
|
'signup' => $this,
|
|
'transient' => $transient,
|
|
'fields' => isset($this->steps[$step]['fields']) ? $this->steps[$step]['fields'] : array(),
|
|
'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);
|
|
|
|
} // end if;
|
|
|
|
} // end if;
|
|
|
|
} // end get_step_view;
|
|
|
|
/**
|
|
* 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 = array();
|
|
|
|
// Plan Selector
|
|
$steps['plan'] = array(
|
|
'name' => __('Pick a Plan', 'wp-ultimo'),
|
|
'desc' => __('Which one of our amazing plans you want to get?', 'wp-ultimo'),
|
|
'view' => 'step-plans',
|
|
'handler' => array($this, 'plans_save'),
|
|
'order' => 10,
|
|
'fields' => false,
|
|
'core' => true,
|
|
);
|
|
|
|
$site_templates = array(
|
|
2,
|
|
);
|
|
|
|
// We add template selection if this has template
|
|
if ($site_templates) {
|
|
|
|
$steps['template'] = array(
|
|
'name' => __('Template Selection', 'wp-ultimo'),
|
|
'desc' => __('Select the base template of your new site.', 'wp-ultimo'),
|
|
'view' => 'step-template',
|
|
'order' => 20,
|
|
'handler' => false,
|
|
'core' => true,
|
|
);
|
|
|
|
} // end if;
|
|
|
|
// Domain registering
|
|
$steps['domain'] = array(
|
|
'name' => __('Site Details', 'wp-ultimo'),
|
|
'desc' => __('Ok, now it\'s time to pick your site url and title!', 'wp-ultimo'),
|
|
'handler' => array($this, 'domain_save'),
|
|
'view' => false,
|
|
'order' => 30,
|
|
'core' => true,
|
|
'fields' => apply_filters('wu_signup_fields_domain', array(
|
|
'blog_title' => array(
|
|
'order' => 10,
|
|
'name' => apply_filters('wu_signup_site_title_label', __('Site Title', 'wp-ultimo')),
|
|
'type' => 'text',
|
|
'default' => '',
|
|
'placeholder' => '',
|
|
'tooltip' => apply_filters('wu_signup_site_title_tooltip', __('Select the title your site is going to have.', 'wp-ultimo')),
|
|
'required' => true,
|
|
'core' => true,
|
|
),
|
|
'blogname' => array(
|
|
'order' => 20,
|
|
'name' => apply_filters('wu_signup_site_url_label', __('URL', 'wp-ultimo')),
|
|
'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-ultimo')),
|
|
'required' => true,
|
|
'core' => true,
|
|
),
|
|
'url_preview' => array(
|
|
'order' => 30,
|
|
'name' => __('Site URL Preview', 'wp-ultimo'),
|
|
'type' => 'html',
|
|
'content' => wu_get_template_contents('legacy/signup/steps/step-domain-url-preview'),
|
|
),
|
|
'submit' => array(
|
|
'order' => 100,
|
|
'type' => 'submit',
|
|
'name' => __('Continue to the next step', 'wp-ultimo'),
|
|
'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 = array(
|
|
|
|
'user_name' => array(
|
|
'order' => 10,
|
|
'name' => apply_filters('wu_signup_username_label', __('Username', 'wp-ultimo')),
|
|
'type' => 'text',
|
|
'default' => '',
|
|
'placeholder' => '',
|
|
'tooltip' => apply_filters('wu_signup_username_tooltip', __('Username must be at least 4 characters.', 'wp-ultimo')),
|
|
'required' => true,
|
|
'core' => true,
|
|
),
|
|
|
|
'user_email' => array(
|
|
'order' => 20,
|
|
'name' => apply_filters('wu_signup_email_label', __('Email', 'wp-ultimo')),
|
|
'type' => 'email',
|
|
'default' => '',
|
|
'placeholder' => '',
|
|
'tooltip' => apply_filters('wu_signup_email_tooltip', ''),
|
|
'required' => true,
|
|
'core' => true,
|
|
),
|
|
|
|
'user_pass' => array(
|
|
'order' => 30,
|
|
'name' => apply_filters('wu_signup_password_label', __('Password', 'wp-ultimo')),
|
|
'type' => 'password',
|
|
'default' => '',
|
|
'placeholder' => '',
|
|
'tooltip' => apply_filters('wu_signup_password_tooltip', __('Your password should be at least 6 characters long.', 'wp-ultimo')),
|
|
'required' => true,
|
|
'core' => true,
|
|
),
|
|
|
|
'user_pass_conf' => array(
|
|
'order' => 40,
|
|
'name' => apply_filters('wu_signup_password_conf_label', __('Confirm Password', 'wp-ultimo')),
|
|
'type' => 'password',
|
|
'default' => '',
|
|
'placeholder' => '',
|
|
'tooltip' => apply_filters('wu_signup_password_conf_tooltip', ''),
|
|
'required' => true,
|
|
'core' => true,
|
|
),
|
|
|
|
/**
|
|
* HoneyPot Field
|
|
*/
|
|
'site_url' => array(
|
|
'order' => rand(1, 59), // Use random order for Honeypot
|
|
'name' => __('Site URL', 'wp-ultimo'),
|
|
'type' => 'text',
|
|
'default' => '',
|
|
'placeholder' => '',
|
|
'tooltip' => '',
|
|
'core' => true,
|
|
'wrapper_attributes' => array(
|
|
'style' => 'display: none;',
|
|
),
|
|
'attributes' => array(
|
|
'autocomplete' => 'nope',
|
|
)
|
|
),
|
|
|
|
); // end first account fields;
|
|
|
|
/**
|
|
* 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-ultimo'),
|
|
// '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-ultimo'),
|
|
// 'type' => 'text',
|
|
// 'default' => '',
|
|
// 'placeholder' => '',
|
|
// 'tooltip' => __('The code should be an exact match. This field is case-sensitive.', 'wp-ultimo'),
|
|
// 'requires' => array('has_coupon' => true),
|
|
// 'core' => true,
|
|
// );
|
|
// } // end if;
|
|
// /**
|
|
// * 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-ultimo'), $this->get_terms_url()),
|
|
// 'core' => true,
|
|
// );
|
|
// } // end if;
|
|
|
|
/**
|
|
* Submit Field
|
|
*/
|
|
$account_fields['submit'] = array(
|
|
'order' => 100,
|
|
'type' => 'submit',
|
|
'name' => __('Create Account', 'wp-ultimo'),
|
|
'core' => true,
|
|
);
|
|
|
|
// Account registering
|
|
$steps['account'] = array(
|
|
'name' => __('Account Details', 'wp-ultimo'),
|
|
'view' => false,
|
|
'handler' => array($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, array($this, 'sort_steps_and_fields'));
|
|
|
|
// Sorts each of the fields block
|
|
foreach ($steps as &$step) {
|
|
|
|
$step = wp_parse_args($step, array(
|
|
'hidden' => false,
|
|
));
|
|
|
|
if (isset($step['fields']) && is_array($step['fields'])) {
|
|
|
|
// Sort elements based on their order
|
|
uasort($step['fields'], array($this, 'sort_steps_and_fields'));
|
|
|
|
} // end if;
|
|
|
|
} // end foreach;
|
|
|
|
/**
|
|
* Adds the hidden step now responsible for validating data entry and the actual account creation
|
|
*
|
|
* @since 1.4.0
|
|
*/
|
|
$begin_signup = array(
|
|
'begin-signup' => array(
|
|
'name' => __('Begin Signup Process', 'wp-ultimo'),
|
|
'handler' => array($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 = array(
|
|
'create-account' => array(
|
|
'name' => __('Creating Account', 'wp-ultimo'),
|
|
'handler' => array($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']));
|
|
|
|
} // end if;
|
|
|
|
// If we need to add that
|
|
if (!$this->has_plan_step()) {
|
|
|
|
unset($steps['plan']);
|
|
|
|
} // end if;
|
|
|
|
return $steps;
|
|
|
|
} // end get_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 = array(
|
|
'not-empty' => '',
|
|
);
|
|
|
|
} else {
|
|
|
|
$transient = wu_get_session('signup')->get('form');
|
|
|
|
} // end if;
|
|
|
|
if ($die && empty($transient)) {
|
|
|
|
// wp_die(__('Try again', 'wp-ultimo'));
|
|
|
|
} // end if;
|
|
|
|
if (is_null($transient)) {
|
|
|
|
return array();
|
|
|
|
} // end if;
|
|
|
|
return $transient;
|
|
|
|
} // end get_transient;
|
|
|
|
/**
|
|
* Update the transient data in out database
|
|
*
|
|
* @param array $transient Array containing the transient data.
|
|
*/
|
|
public function update_transient($transient) {
|
|
|
|
$this->session->set('form', $transient);
|
|
|
|
$this->session->commit();
|
|
|
|
} // end update_transient;
|
|
/**
|
|
* Checks transient data to see if the plan step is necessary
|
|
*/
|
|
public function has_plan_step(): bool {
|
|
|
|
$transient = $this->get_transient();
|
|
|
|
if (isset($transient['skip_plan']) && isset($transient['plan_id']) && isset($transient['plan_freq'])) {
|
|
|
|
return false;
|
|
|
|
} // end if;
|
|
|
|
return true;
|
|
|
|
} // end has_plan_step;
|
|
|
|
/**
|
|
* 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 = array()) {
|
|
|
|
// Add CS
|
|
if (isset($_GET['cs'])) {
|
|
|
|
$params['cs'] = $_GET['cs'];
|
|
|
|
} // end if;
|
|
|
|
if (isset($_REQUEST['customized'])) {
|
|
|
|
$params['customized'] = $_REQUEST['customized'];
|
|
|
|
} // end if;
|
|
|
|
if (isset($_REQUEST['skip_plan']) && $_REQUEST['skip_plan'] == 1) {
|
|
|
|
unset($this->steps['plan']);
|
|
unset($params['skip_plan']);
|
|
|
|
} // end if;
|
|
|
|
if (isset($_REQUEST['template_id'])) {
|
|
|
|
$plan = false;
|
|
|
|
if (isset($_REQUEST['plan_id'])) {
|
|
|
|
$plan = wu_get_plan($_REQUEST['plan_id']);
|
|
|
|
} // end if;
|
|
|
|
$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']);
|
|
|
|
} // end if;
|
|
|
|
} // end if;
|
|
|
|
$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);
|
|
|
|
} // end foreach;
|
|
|
|
return $url;
|
|
|
|
} // end get_next_step_link;
|
|
|
|
/**
|
|
* 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 = array()) {
|
|
|
|
/** Redirect the user to the next step */
|
|
wp_redirect(esc_url_raw($this->get_next_step_link( $args )));
|
|
|
|
/** Kill the execution after the redirect */
|
|
exit;
|
|
|
|
} // end next_step;
|
|
|
|
/**
|
|
* 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 = array()) {
|
|
|
|
// Add CS
|
|
if (isset($_GET['cs'])) {
|
|
|
|
$params['cs'] = $_GET['cs'];
|
|
|
|
} // end if;
|
|
|
|
if (isset($_REQUEST['customized'])) {
|
|
|
|
$params['customized'] = $_REQUEST['customized'];
|
|
|
|
} // end if;
|
|
|
|
$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 = $search_key === false ? '' : $keys[$search_key];
|
|
|
|
if (!$key || $key == 'begin-signup') {
|
|
|
|
return false;
|
|
|
|
} // end if;
|
|
|
|
$url = add_query_arg('step', $key);
|
|
|
|
foreach ($params as $param => $value) {
|
|
|
|
$url = add_query_arg($param, $value, $url);
|
|
|
|
} // end foreach;
|
|
|
|
return $url;
|
|
|
|
} // end get_prev_step_link;
|
|
|
|
/**
|
|
* 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'];
|
|
|
|
} // end sort_steps_and_fields;
|
|
|
|
/**
|
|
* 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) {
|
|
|
|
/** Select the default frequency */
|
|
$freq = $freq ? $freq : wu_get_setting('default_pricing_option');
|
|
|
|
?>
|
|
|
|
<?php if ($step == 'plan') { ?>
|
|
|
|
<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
|
|
} // end if;
|
|
?>
|
|
|
|
<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
|
|
|
|
} // end form_fields;
|
|
|
|
/**
|
|
* 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 = array();
|
|
|
|
$site = get_current_site();
|
|
|
|
$domain = $site->domain;
|
|
|
|
if (wu_get_setting('enable_multiple_domains', false) && $domain_options) {
|
|
|
|
$domain = array_shift($domain_options);
|
|
|
|
} // end if;
|
|
|
|
$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
|
|
|
|
} // end get_site_url_for_previewer;
|
|
|
|
/**
|
|
* We pass the following info
|
|
*/
|
|
public function plans_save() {
|
|
|
|
// Get transient
|
|
$transient = $this->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-ultimo'));
|
|
} 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-ultimo'));
|
|
} // end if;
|
|
} // end if;
|
|
|
|
$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;
|
|
} // end if;
|
|
|
|
/** 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();
|
|
|
|
} // end plans_save;
|
|
|
|
/**
|
|
* Personal Info Settings.
|
|
*/
|
|
public function domain_save() {
|
|
|
|
// Get transient
|
|
$transient = $this->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;
|
|
|
|
} // end if;
|
|
|
|
// Re-saves the transient
|
|
$this->update_transient($transient);
|
|
|
|
/** Go to the next step */
|
|
$this->next_step();
|
|
|
|
} // end domain_save;
|
|
|
|
/**
|
|
* 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 ? $exclude_list : array('_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;
|
|
|
|
} // end filter_post_array;
|
|
/**
|
|
* 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 === null ? fn($v, $k): bool => !empty($v) : $callback, $callback === null ? ARRAY_FILTER_USE_BOTH : 0);
|
|
|
|
return array_intersect_key($array, array_flip($matched_keys));
|
|
|
|
} // end array_filter_key;
|
|
/**
|
|
* 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');
|
|
|
|
} // end get_active_until_with_trial;
|
|
|
|
/**
|
|
* 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) {
|
|
|
|
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;
|
|
|
|
});
|
|
|
|
} // end add_signup_step;
|
|
|
|
/**
|
|
* 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) {
|
|
|
|
add_filter('wp_ultimo_registration_steps', function($steps) use ($step, $id, $order, $field) {
|
|
|
|
// Checks for honey-trap id
|
|
if ($id === 'site_url') {
|
|
|
|
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-ultimo'));
|
|
|
|
} // end if;
|
|
|
|
// Saves the order
|
|
$field['order'] = $order;
|
|
|
|
// mark as not core
|
|
$field['core'] = false;
|
|
|
|
$steps[$step]['fields'][$id] = $field;
|
|
|
|
return $steps;
|
|
|
|
});
|
|
|
|
} // end add_signup_field;
|
|
|
|
} // end class Legacy_Checkout;
|