1558 lines
37 KiB
PHP
1558 lines
37 KiB
PHP
<?php
|
|
/**
|
|
* The Checkout Form model for the Checkout_Form Mappings.
|
|
*
|
|
* @package WP_Ultimo
|
|
* @subpackage Models
|
|
* @since 2.0.0
|
|
*/
|
|
|
|
namespace WP_Ultimo\Models;
|
|
|
|
use WP_Ultimo\Models\Base_Model;
|
|
use Arrch\Arrch as Array_Search;
|
|
|
|
// Exit if accessed directly
|
|
defined('ABSPATH') || exit;
|
|
|
|
/**
|
|
* Checkout Form model class. Implements the Base Model.
|
|
*
|
|
* @since 2.0.0
|
|
*/
|
|
class Checkout_Form extends Base_Model {
|
|
|
|
/**
|
|
* @var array<string, int>|array<string, string>
|
|
*/
|
|
public $meta;
|
|
/**
|
|
* The name of the checkout form.
|
|
*
|
|
* @since 2.0.0
|
|
* @var string
|
|
*/
|
|
protected $name;
|
|
|
|
/**
|
|
* Slug of the checkout form.
|
|
*
|
|
* @since 2.0.0
|
|
* @var string
|
|
*/
|
|
protected $slug = '';
|
|
|
|
/**
|
|
* Is this checkout form active?
|
|
*
|
|
* @since 2.0.0
|
|
* @var boolean
|
|
*/
|
|
protected $active = true;
|
|
|
|
/**
|
|
* Payload of the event.
|
|
*
|
|
* @since 2.0.0
|
|
* @var object
|
|
*/
|
|
protected $settings;
|
|
|
|
/**
|
|
* Custom CSS code.
|
|
*
|
|
* @since 2.0.0
|
|
* @var string
|
|
*/
|
|
protected $custom_css;
|
|
|
|
/**
|
|
* Countries allowed on this checkout.
|
|
*
|
|
* @since 2.0.0
|
|
* @var string
|
|
*/
|
|
protected $allowed_countries;
|
|
|
|
/**
|
|
* Thank you page id, if set.
|
|
*
|
|
* @since 2.0.0
|
|
* @var int
|
|
*/
|
|
protected $thank_you_page_id;
|
|
|
|
/**
|
|
* Custom Snippets code.
|
|
*
|
|
* @since 2.0.0
|
|
* @var string
|
|
*/
|
|
protected $conversion_snippets;
|
|
|
|
/**
|
|
* Set a template to use.
|
|
*
|
|
* @since 2.0.0
|
|
* @var string can be either 'blank', 'single-step' or 'multi-step'
|
|
*/
|
|
protected $template;
|
|
|
|
/**
|
|
* Query Class to the static query methods.
|
|
*
|
|
* @since 2.0.0
|
|
* @var string
|
|
*/
|
|
protected $query_class = '\\WP_Ultimo\\Database\\Checkout_Forms\\Checkout_Form_Query';
|
|
|
|
/**
|
|
* The steps to show to user in checkout form.
|
|
*
|
|
* @since 2.0.19
|
|
* @var array
|
|
*/
|
|
protected $steps_to_show;
|
|
|
|
/**
|
|
* Set the validation rules for this particular model.
|
|
*
|
|
* To see how to setup rules, check the documentation of the
|
|
* validation library we are using: https://github.com/rakit/validation
|
|
*
|
|
* @since 2.0.0
|
|
* @link https://github.com/rakit/validation
|
|
* @return array
|
|
*/
|
|
public function validation_rules() {
|
|
|
|
$id = $this->get_id();
|
|
|
|
return array(
|
|
'name' => 'required',
|
|
'slug' => "required|unique:\WP_Ultimo\Models\Checkout_Form,slug,{$id}|min:3",
|
|
'active' => 'required|default:1',
|
|
'custom_css' => 'default:',
|
|
'settings' => 'checkout_steps',
|
|
'allowed_countries' => 'default:',
|
|
'thank_you_page_id' => 'integer',
|
|
'conversion_snippets' => 'nullable|default:',
|
|
'template' => 'in:blank,single-step,multi-step',
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Get the object type associated with this event.
|
|
*
|
|
* @since 2.0.0
|
|
* @return string
|
|
*/
|
|
public function get_slug() {
|
|
|
|
return $this->slug;
|
|
}
|
|
|
|
/**
|
|
* Set the checkout form slug
|
|
*
|
|
* @since 2.0.0
|
|
*
|
|
* @param string $slug The checkout form slug. It needs to be unique and preferably make it clear what it is about. E.g. my_checkout_form.
|
|
* @return void
|
|
*/
|
|
public function set_slug($slug) {
|
|
|
|
$this->slug = $slug;
|
|
}
|
|
|
|
/**
|
|
* Get the name of the checkout form.
|
|
*
|
|
* @since 2.0.0
|
|
* @return string
|
|
*/
|
|
public function get_name() {
|
|
|
|
return $this->name;
|
|
}
|
|
|
|
/**
|
|
* Set the name of the checkout form.
|
|
*
|
|
* @since 2.0.0
|
|
* @param string $name Your checkout form name, which is used as checkout form title as well.
|
|
* @return void
|
|
*/
|
|
public function set_name($name) {
|
|
|
|
$this->name = $name;
|
|
}
|
|
|
|
/**
|
|
* Get is this checkout form active?
|
|
*
|
|
* @since 2.0.0
|
|
* @return boolean
|
|
*/
|
|
public function is_active() {
|
|
|
|
return (bool) $this->active;
|
|
}
|
|
|
|
/**
|
|
* Set is this checkout form active?
|
|
*
|
|
* @since 2.0.0
|
|
* @param boolean $active Set this checkout form as active (true), which means available to be used, or inactive (false).
|
|
* @return void
|
|
*/
|
|
public function set_active($active) {
|
|
|
|
$this->active = (bool) $active;
|
|
}
|
|
|
|
/**
|
|
* Get custom CSS code.
|
|
*
|
|
* @since 2.0.0
|
|
* @return string
|
|
*/
|
|
public function get_custom_css() {
|
|
|
|
return $this->custom_css;
|
|
}
|
|
|
|
/**
|
|
* Set custom CSS code.
|
|
*
|
|
* @since 2.0.0
|
|
* @param string $custom_css Custom CSS code for the checkout form.
|
|
* @return void
|
|
*/
|
|
public function set_custom_css($custom_css) {
|
|
|
|
$this->custom_css = $custom_css;
|
|
}
|
|
|
|
/**
|
|
* Get settings of the event.
|
|
*
|
|
* @since 2.0.0
|
|
* @return mixed
|
|
*/
|
|
public function get_settings() {
|
|
|
|
if (empty($this->settings)) {
|
|
return array();
|
|
}
|
|
|
|
if (is_string($this->settings)) {
|
|
$this->settings = maybe_unserialize($this->settings);
|
|
}
|
|
|
|
return $this->settings;
|
|
}
|
|
|
|
/**
|
|
* Set settings of the checkout form.
|
|
*
|
|
* @since 2.0.0
|
|
* @param object $settings The checkout form settings and configurations.
|
|
* @return void
|
|
*/
|
|
public function set_settings($settings) {
|
|
|
|
if (is_string($settings)) { // @phpstan-ignore-line
|
|
|
|
try {
|
|
$settings = maybe_unserialize(stripslashes($settings));
|
|
} catch (\Throwable $exception) {
|
|
|
|
// Silence is golden.
|
|
}
|
|
}
|
|
|
|
$this->settings = $settings;
|
|
}
|
|
/**
|
|
* Returns a specific step by the step name.
|
|
*
|
|
* @since 2.0.0
|
|
*
|
|
* @param string $step_name Name of the step. E.g. 'account'.
|
|
* @param bool $to_show If we want the steps to show in a form.
|
|
* @return mixed[]|false
|
|
*/
|
|
public function get_step($step_name, $to_show = false) {
|
|
|
|
$settings = $to_show ? $this->get_steps_to_show() : $this->get_settings();
|
|
|
|
$step_key = array_search($step_name, array_column($settings, 'id'), true);
|
|
|
|
$step = $step_key !== false ? $settings[ $step_key ] : false;
|
|
|
|
if ($step) {
|
|
$step = wp_parse_args(
|
|
$step,
|
|
array(
|
|
'logged' => 'always',
|
|
'fields' => array(),
|
|
)
|
|
);
|
|
}
|
|
|
|
return $step;
|
|
}
|
|
/**
|
|
* Returns the steps to show in current form
|
|
*
|
|
* @since 2.0.19
|
|
* @return mixed[]|false
|
|
*/
|
|
public function get_steps_to_show() {
|
|
|
|
if ($this->steps_to_show) {
|
|
return $this->steps_to_show;
|
|
}
|
|
|
|
$steps = $this->get_settings();
|
|
|
|
$user_exists = is_user_logged_in();
|
|
|
|
$final_steps = array();
|
|
|
|
$non_data_fields = array(
|
|
'submit_button',
|
|
'period_selection',
|
|
'steps',
|
|
);
|
|
|
|
$hidden_fields = array(
|
|
'hidden',
|
|
);
|
|
|
|
$final_data_fields = array();
|
|
|
|
foreach ($steps as $key => $step) {
|
|
$logged = wu_get_isset($step, 'logged', 'always');
|
|
|
|
$show = $logged === 'always';
|
|
|
|
if ($logged === 'guests_only' && ! $user_exists) {
|
|
$show = true;
|
|
} elseif ($logged === 'logged_only' && $user_exists) {
|
|
$show = true;
|
|
}
|
|
|
|
if ( ! $show) {
|
|
continue;
|
|
}
|
|
|
|
$data_fields = array_filter($step['fields'], fn($field) => ! in_array($field['type'], $non_data_fields, true));
|
|
|
|
$not_hidden_fields = array_filter($data_fields, fn($field) => ! in_array($field['type'], $hidden_fields, true) && ! wu_should_hide_form_field($field));
|
|
|
|
if (empty($not_hidden_fields)) {
|
|
$final_data_fields = array_merge($final_data_fields, $data_fields);
|
|
} else {
|
|
$final_steps[] = $step;
|
|
}
|
|
}
|
|
|
|
if ( ! empty($final_steps) && ! empty($final_data_fields)) {
|
|
$key = array_key_last($final_steps);
|
|
|
|
$final_steps[ $key ]['fields'] = array_merge($final_data_fields, $final_steps[ $key ]['fields']);
|
|
}
|
|
|
|
$this->steps_to_show = $final_steps;
|
|
|
|
return $final_steps;
|
|
}
|
|
/**
|
|
* Returns a specific field by the step name and field name.
|
|
*
|
|
* @since 2.0.0
|
|
*
|
|
* @param string $step_name Name of the step. E.g. 'account'.
|
|
* @param string $field_name Name of the field. E.g. 'username'.
|
|
* @return mixed[]|false
|
|
*/
|
|
public function get_field($step_name, $field_name) {
|
|
|
|
$step = $this->get_step($step_name);
|
|
|
|
if ( ! is_array($step)) {
|
|
return false;
|
|
}
|
|
|
|
$field_key = array_search($field_name, array_column($step['fields'], 'id'), true);
|
|
|
|
return $field_key !== false ? $step['fields'][ $field_key ] : false;
|
|
}
|
|
|
|
/**
|
|
* Returns all the fields from all steps.
|
|
*
|
|
* @since 2.0.0
|
|
* @return array
|
|
*/
|
|
public function get_all_fields() {
|
|
|
|
$settings = $this->get_settings();
|
|
|
|
if ( ! is_array($settings)) {
|
|
return array();
|
|
}
|
|
|
|
$fields = array_column($settings, 'fields');
|
|
|
|
if (empty($fields)) {
|
|
return array();
|
|
}
|
|
|
|
return call_user_func_array('array_merge', $fields);
|
|
}
|
|
|
|
/**
|
|
* Get all fields of a given type.
|
|
*
|
|
* @since 2.0.11
|
|
*
|
|
* @param string|array $type The field type or types to search for.
|
|
* @return array
|
|
*/
|
|
public function get_all_fields_by_type($type) {
|
|
|
|
$all_fields = $this->get_all_fields();
|
|
|
|
$types = (array) $type;
|
|
|
|
return Array_Search::find(
|
|
$all_fields,
|
|
array(
|
|
'where' => array(
|
|
array('type', $types),
|
|
),
|
|
)
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Get fields that are meta-related.
|
|
*
|
|
* @since 2.0.0
|
|
*
|
|
* @param string $meta_type The meta type.
|
|
* @return array
|
|
*/
|
|
public function get_all_meta_fields($meta_type = 'customer_meta') {
|
|
|
|
$all_fields = $this->get_all_fields();
|
|
|
|
$types = apply_filters('wu_checkout_form_meta_fields_list', array('text', 'select', 'color', 'color_picker', 'textarea', 'checkbox'), $this);
|
|
|
|
return Array_Search::find(
|
|
$all_fields,
|
|
array(
|
|
'where' => array(
|
|
array('type', $types),
|
|
array('save_as', $meta_type),
|
|
),
|
|
)
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Returns the number of steps in this form.
|
|
*
|
|
* @since 2.0.0
|
|
* @return int
|
|
*/
|
|
public function get_step_count() {
|
|
|
|
$steps = $this->get_settings();
|
|
|
|
return is_array($steps) ? count($steps) : 0;
|
|
}
|
|
|
|
/**
|
|
* Returns the number of fields on this form.
|
|
*
|
|
* @since 2.0.0
|
|
* @return int
|
|
*/
|
|
public function get_field_count() {
|
|
|
|
$fields = $this->get_all_fields();
|
|
|
|
return is_array($fields) ? count($fields) : 0;
|
|
}
|
|
/**
|
|
* Returns the shortcode that needs to be placed to embed this form.
|
|
*
|
|
* @since 2.0.0
|
|
*/
|
|
public function get_shortcode(): string {
|
|
|
|
return sprintf('[wu_checkout slug="%s"]', $this->get_slug());
|
|
}
|
|
|
|
/**
|
|
* Sets an template for blank.
|
|
*
|
|
* @since 2.0.0
|
|
*
|
|
* @param string $template The type of the template.
|
|
* @return void
|
|
*/
|
|
public function use_template($template = 'single-step') {
|
|
|
|
$fields = array();
|
|
|
|
if ($template === 'multi-step') {
|
|
$fields = $this->get_multi_step_template();
|
|
|
|
$this->set_settings($fields);
|
|
} elseif ($template === 'single-step') {
|
|
$fields = $this->get_single_step_template();
|
|
}
|
|
|
|
$this->set_settings($fields);
|
|
}
|
|
|
|
/**
|
|
* Get the contents of the single step template.
|
|
*
|
|
* @since 2.0.0
|
|
* @return array
|
|
*/
|
|
private function get_single_step_template() {
|
|
|
|
$steps = array(
|
|
array(
|
|
'id' => 'checkout',
|
|
'name' => __('Checkout', 'wp-ultimo'),
|
|
'desc' => '',
|
|
'fields' => array(
|
|
array(
|
|
'step' => 'checkout',
|
|
'name' => __('Plans', 'wp-ultimo'),
|
|
'type' => 'pricing_table',
|
|
'id' => 'pricing_table',
|
|
'required' => true,
|
|
'pricing_table_products' => implode(',', wu_get_plans(array('fields' => 'ids'))),
|
|
'pricing_table_template' => 'list',
|
|
),
|
|
array(
|
|
'step' => 'checkout',
|
|
'name' => __('Email', 'wp-ultimo'),
|
|
'type' => 'email',
|
|
'id' => 'email_address',
|
|
'required' => true,
|
|
'placeholder' => '',
|
|
'tooltip' => '',
|
|
),
|
|
array(
|
|
'step' => 'checkout',
|
|
'name' => __('Username', 'wp-ultimo'),
|
|
'type' => 'username',
|
|
'id' => 'username',
|
|
'required' => true,
|
|
'placeholder' => '',
|
|
'tooltip' => '',
|
|
'auto_generate' => false,
|
|
),
|
|
array(
|
|
'step' => 'checkout',
|
|
'name' => __('Password', 'wp-ultimo'),
|
|
'type' => 'password',
|
|
'id' => 'password',
|
|
'required' => true,
|
|
'placeholder' => '',
|
|
'tooltip' => '',
|
|
'password_strength_meter' => '1',
|
|
'password_confirm_field' => '1',
|
|
),
|
|
array(
|
|
'step' => 'checkout',
|
|
'name' => __('Site Title', 'wp-ultimo'),
|
|
'type' => 'site_title',
|
|
'id' => 'site_title',
|
|
'required' => true,
|
|
'placeholder' => '',
|
|
'tooltip' => '',
|
|
'auto_generate' => false,
|
|
),
|
|
array(
|
|
'step' => 'checkout',
|
|
'name' => __('Site URL', 'wp-ultimo'),
|
|
'type' => 'site_url',
|
|
'id' => 'site_url',
|
|
'placeholder' => '',
|
|
'tooltip' => '',
|
|
'required' => true,
|
|
'auto_generate' => false,
|
|
'display_url_preview' => true,
|
|
),
|
|
array(
|
|
'step' => 'checkout',
|
|
'name' => __('Your Order', 'wp-ultimo'),
|
|
'type' => 'order_summary',
|
|
'id' => 'order_summary',
|
|
'order_summary_template' => 'clean',
|
|
'table_columns' => 'simple',
|
|
),
|
|
array(
|
|
'step' => 'checkout',
|
|
'name' => __('Payment Method', 'wp-ultimo'),
|
|
'type' => 'payment',
|
|
'id' => 'payment',
|
|
),
|
|
array(
|
|
'step' => 'checkout',
|
|
'name' => __('Billing Address', 'wp-ultimo'),
|
|
'type' => 'billing_address',
|
|
'id' => 'billing_address',
|
|
'required' => true,
|
|
'zip_and_country' => '1',
|
|
),
|
|
array(
|
|
'step' => 'checkout',
|
|
'name' => __('Checkout', 'wp-ultimo'),
|
|
'type' => 'submit_button',
|
|
'id' => 'checkout',
|
|
),
|
|
),
|
|
),
|
|
);
|
|
|
|
return apply_filters('wu_checkout_form_single_step_template', $steps);
|
|
}
|
|
|
|
/**
|
|
* Get the contents of the multi step template.
|
|
*
|
|
* @since 2.0.0
|
|
* @return array
|
|
*/
|
|
private function get_multi_step_template() {
|
|
|
|
$steps = array(
|
|
array(
|
|
'id' => 'checkout',
|
|
'name' => __('Checkout', 'wp-ultimo'),
|
|
'desc' => '',
|
|
'fields' => array(
|
|
array(
|
|
'step' => 'checkout',
|
|
'name' => 'Plans',
|
|
'type' => 'pricing_table',
|
|
'id' => 'pricing_table',
|
|
'required' => true,
|
|
'pricing_table_products' => implode(',', wu_get_plans(array('fields' => 'ids'))),
|
|
'pricing_table_template' => 'list',
|
|
),
|
|
array(
|
|
'step' => 'checkout',
|
|
'name' => __('Next Step', 'wp-ultimo'),
|
|
'type' => 'submit_button',
|
|
'id' => 'next_step',
|
|
),
|
|
),
|
|
),
|
|
array(
|
|
'id' => 'site',
|
|
'name' => __('Site Info', 'wp-ultimo'),
|
|
'desc' => '',
|
|
'fields' => array(
|
|
array(
|
|
'step' => 'checkout',
|
|
'name' => __('Site Title', 'wp-ultimo'),
|
|
'type' => 'site_title',
|
|
'id' => 'site_title',
|
|
'required' => true,
|
|
'placeholder' => '',
|
|
'tooltip' => '',
|
|
'auto_generate' => false,
|
|
),
|
|
array(
|
|
'step' => 'checkout',
|
|
'name' => __('Site URL', 'wp-ultimo'),
|
|
'type' => 'site_url',
|
|
'id' => 'site_url',
|
|
'required' => true,
|
|
'placeholder' => '',
|
|
'tooltip' => '',
|
|
'auto_generate' => false,
|
|
'display_url_preview' => true,
|
|
),
|
|
array(
|
|
'step' => 'site',
|
|
'name' => __('Next Step', 'wp-ultimo'),
|
|
'type' => 'submit_button',
|
|
'id' => 'next_step_site',
|
|
),
|
|
),
|
|
),
|
|
array(
|
|
'id' => 'user',
|
|
'name' => __('User Info', 'wp-ultimo'),
|
|
'logged' => 'guests_only',
|
|
'desc' => '',
|
|
'fields' => array(
|
|
array(
|
|
'step' => 'checkout',
|
|
'name' => __('Email', 'wp-ultimo'),
|
|
'type' => 'email',
|
|
'id' => 'email_address',
|
|
'required' => true,
|
|
'placeholder' => '',
|
|
'tooltip' => '',
|
|
),
|
|
array(
|
|
'step' => 'checkout',
|
|
'name' => __('Username', 'wp-ultimo'),
|
|
'type' => 'username',
|
|
'id' => 'username',
|
|
'required' => true,
|
|
'placeholder' => '',
|
|
'tooltip' => '',
|
|
'auto_generate' => false,
|
|
),
|
|
array(
|
|
'step' => 'checkout',
|
|
'name' => __('Password', 'wp-ultimo'),
|
|
'type' => 'password',
|
|
'id' => 'password',
|
|
'required' => true,
|
|
'placeholder' => '',
|
|
'tooltip' => '',
|
|
'password_strength_meter' => '1',
|
|
'password_confirm_field' => '1',
|
|
),
|
|
array(
|
|
'step' => 'user',
|
|
'name' => __('Next Step', 'wp-ultimo'),
|
|
'type' => 'submit_button',
|
|
'id' => 'next_step_user',
|
|
),
|
|
),
|
|
),
|
|
array(
|
|
'id' => 'payment',
|
|
'name' => __('Payment', 'wp-ultimo'),
|
|
'desc' => '',
|
|
'fields' => array(
|
|
array(
|
|
'step' => 'checkout',
|
|
'name' => __('Your Order', 'wp-ultimo'),
|
|
'type' => 'order_summary',
|
|
'id' => 'order_summary',
|
|
'order_summary_template' => 'clean',
|
|
'table_columns' => 'simple',
|
|
),
|
|
array(
|
|
'step' => 'checkout',
|
|
'name' => __('Payment Method', 'wp-ultimo'),
|
|
'type' => 'payment',
|
|
'id' => 'payment',
|
|
),
|
|
array(
|
|
'step' => 'checkout',
|
|
'name' => __('Billing Address', 'wp-ultimo'),
|
|
'type' => 'billing_address',
|
|
'id' => 'billing_address',
|
|
'required' => true,
|
|
'zip_and_country' => '1',
|
|
),
|
|
array(
|
|
'step' => 'checkout',
|
|
'name' => __('Checkout', 'wp-ultimo'),
|
|
'type' => 'submit_button',
|
|
'id' => 'checkout',
|
|
),
|
|
),
|
|
),
|
|
);
|
|
|
|
return apply_filters('wu_checkout_form_multi_step_template', $steps);
|
|
}
|
|
|
|
/**
|
|
* Converts the steps from classic WP Multisite WaaS 1.X to the 2.0 format.
|
|
*
|
|
* @since 2.0.0
|
|
*
|
|
* @param array $steps The steps to convert.
|
|
* @param array $old_settings The old settings.
|
|
* @return array
|
|
*/
|
|
public static function convert_steps_to_v2($steps, $old_settings = array()) {
|
|
|
|
$exclude_steps = array(
|
|
'begin-signup',
|
|
'create-account',
|
|
);
|
|
|
|
$old_template_list = wu_get_isset($old_settings, 'templates', array());
|
|
|
|
if (empty($old_template_list)) {
|
|
$exclude_steps[] = 'template';
|
|
}
|
|
|
|
$new_format = array();
|
|
|
|
foreach ($steps as $step_id => $step) {
|
|
if (in_array($step_id, $exclude_steps, true)) {
|
|
continue;
|
|
}
|
|
|
|
/**
|
|
* Deal with special cases.
|
|
*/
|
|
if ($step_id === 'plan') {
|
|
$products_list = wu_get_plans(
|
|
array(
|
|
'fields' => 'ids',
|
|
)
|
|
);
|
|
|
|
/*
|
|
* Calculate the period selector
|
|
*/
|
|
$available_periods = array();
|
|
|
|
$period_options = array(
|
|
'enable_price_1' => array(
|
|
'duration' => '1',
|
|
'duration_unit' => 'month',
|
|
'label' => __('Monthly', 'wp-ultimo'),
|
|
),
|
|
'enable_price_3' => array(
|
|
'duration' => '3',
|
|
'duration_unit' => 'month',
|
|
'label' => __('Quarterly', 'wp-ultimo'),
|
|
),
|
|
'enable_price_12' => array(
|
|
'duration' => '1',
|
|
'duration_unit' => 'year',
|
|
'label' => __('Yearly', 'wp-ultimo'),
|
|
),
|
|
);
|
|
|
|
foreach ($period_options as $period_option_key => $period_option) {
|
|
$has_period_option = wu_get_isset($old_settings, $period_option_key, true);
|
|
|
|
if ($has_period_option) {
|
|
$available_periods[] = $period_option;
|
|
}
|
|
}
|
|
|
|
$step['fields'] = array();
|
|
|
|
if ($available_periods && count($available_periods) > 1) {
|
|
$step['fields']['period_selection'] = array(
|
|
'type' => 'period_selection',
|
|
'id' => 'period_selection',
|
|
'period_selection_template' => 'legacy',
|
|
'period_options_header' => '',
|
|
'period_options' => $available_periods,
|
|
);
|
|
}
|
|
|
|
$step['fields']['pricing_table'] = array(
|
|
'name' => __('Pricing Tables', 'wp-ultimo'),
|
|
'id' => 'pricing_table',
|
|
'type' => 'pricing_table',
|
|
'pricing_table_template' => 'legacy',
|
|
'pricing_table_products' => implode(',', $products_list),
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Deal with special cases.
|
|
*/
|
|
if ($step_id === 'template' && wu_get_isset($old_settings, 'allow_template', true)) {
|
|
$templates = array();
|
|
|
|
foreach (wu_get_site_templates() as $site) {
|
|
$templates[] = $site->get_id();
|
|
}
|
|
|
|
$old_template_list = is_array($old_template_list) ? $old_template_list : array();
|
|
|
|
$template_list = array_flip($old_template_list);
|
|
|
|
$template_list = ! empty($template_list) ? $template_list : $templates;
|
|
|
|
$step['fields'] = array(
|
|
'template_selection' => array(
|
|
'name' => __('Template Selection', 'wp-ultimo'),
|
|
'id' => 'template_selection',
|
|
'type' => 'template_selection',
|
|
'template_selection_template' => 'legacy',
|
|
'template_selection_sites' => implode(',', $template_list),
|
|
),
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Remove unnecessary callbacks
|
|
*/
|
|
unset($step['handler']);
|
|
unset($step['view']);
|
|
unset($step['hidden']);
|
|
|
|
$new_fields = array();
|
|
|
|
$step['id'] = $step_id;
|
|
|
|
$fields_to_skip = array(
|
|
'user_pass_conf',
|
|
'url_preview',
|
|
'site_url', // Despite the name, this is the Honeypot field.
|
|
);
|
|
|
|
foreach ($step['fields'] as $field_id => $field) {
|
|
if (in_array($field_id, $fields_to_skip, true)) {
|
|
unset($step['fields'][ $field_id ]);
|
|
|
|
continue;
|
|
}
|
|
|
|
/**
|
|
* Format specific fields.
|
|
*/
|
|
switch ($field_id) {
|
|
case 'user_name':
|
|
$field['type'] = 'username';
|
|
$field['id'] = 'username';
|
|
break;
|
|
|
|
case 'user_pass':
|
|
$field['type'] = 'password';
|
|
$field['id'] = 'password';
|
|
$field['password_strength_meter'] = false;
|
|
$field['password_confirm_field'] = true;
|
|
$field['password_confirm_label'] = wu_get_isset($step['fields']['user_pass_conf'], 'name', __('Confirm Password', 'wp-ultimo'));
|
|
break;
|
|
|
|
case 'user_email':
|
|
$field['display_notices'] = false;
|
|
$field['id'] = 'email_address';
|
|
break;
|
|
|
|
case 'blog_title':
|
|
$field['type'] = 'site_title';
|
|
$field['id'] = 'site_title';
|
|
$field['auto_generate'] = false;
|
|
break;
|
|
|
|
case 'blogname':
|
|
$field['type'] = 'site_url';
|
|
$field['id'] = 'site_url';
|
|
$field['url_preview_template'] = 'legacy/signup/steps/step-domain-url-preview';
|
|
$field['auto_generate'] = false;
|
|
$field['display_url_preview'] = true;
|
|
$field['required'] = true;
|
|
$field['display_field_attachments'] = false;
|
|
$field['enable_domain_selection'] = wu_get_isset($old_settings, 'enable_multiple_domains', false);
|
|
$field['available_domains'] = wu_get_isset($old_settings, 'domain_options', array());
|
|
break;
|
|
|
|
case 'submit':
|
|
$field['type'] = 'submit_button';
|
|
$field['id'] = 'submit_button';
|
|
|
|
if ($step_id === 'account') {
|
|
$field['name'] = __('Continue to the Next Step', 'wp-ultimo');
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
$field['id'] = $field_id;
|
|
|
|
$new_fields[] = $field;
|
|
}
|
|
|
|
$step['fields'] = $new_fields;
|
|
|
|
$new_format[] = $step;
|
|
}
|
|
|
|
/**
|
|
* Add Checkout step
|
|
*/
|
|
$new_format[] = array(
|
|
'id' => 'payment',
|
|
'name' => __('Checkout', 'wp-ultimo'),
|
|
'fields' => array(
|
|
array(
|
|
'name' => __('Order Summary', 'wp-ultimo'),
|
|
'type' => 'order_summary',
|
|
'id' => 'order_summary',
|
|
'order_summary_template' => 'clean',
|
|
'table_columns' => 'simple',
|
|
),
|
|
array(
|
|
'name' => __('Billing Address', 'wp-ultimo'),
|
|
'type' => 'billing_address',
|
|
'id' => 'billing_address',
|
|
'zip_and_country' => true,
|
|
),
|
|
array(
|
|
'type' => 'discount_code',
|
|
'id' => 'discount_code',
|
|
'name' => __('Coupon Code', 'wp-ultimo'),
|
|
'tooltip' => __('Coupon Code', 'wp-ultimo'),
|
|
'display_checkbox' => true,
|
|
),
|
|
array(
|
|
'name' => __('Payment Methods', 'wp-ultimo'),
|
|
'type' => 'payment',
|
|
'id' => 'payment',
|
|
),
|
|
array(
|
|
'type' => 'submit_button',
|
|
'id' => 'submit_button',
|
|
'name' => __('Pay & Create Account', 'wp-ultimo'),
|
|
),
|
|
),
|
|
);
|
|
|
|
return $new_format;
|
|
}
|
|
|
|
/**
|
|
* Checks if this signup has limitations on countries.
|
|
*
|
|
* @since 2.0.0
|
|
* @return boolean
|
|
*/
|
|
public function has_country_lock() {
|
|
|
|
return ! empty($this->get_allowed_countries());
|
|
}
|
|
|
|
/**
|
|
* Get countries allowed on this checkout.
|
|
*
|
|
* @since 2.0.0
|
|
* @return array
|
|
*/
|
|
public function get_allowed_countries() {
|
|
|
|
if (is_string($this->allowed_countries)) {
|
|
$this->allowed_countries = maybe_unserialize(stripslashes($this->allowed_countries));
|
|
}
|
|
|
|
return maybe_unserialize($this->allowed_countries);
|
|
}
|
|
|
|
/**
|
|
* Set countries allowed on this checkout.
|
|
*
|
|
* @since 2.0.0
|
|
* @param string $allowed_countries The allowed countries that can access this checkout.
|
|
* @return void
|
|
*/
|
|
public function set_allowed_countries($allowed_countries) {
|
|
|
|
$this->allowed_countries = $allowed_countries;
|
|
}
|
|
|
|
/**
|
|
* Checks if this checkout form has a custom thank you page.
|
|
*
|
|
* @since 2.0.0
|
|
* @return boolean
|
|
*/
|
|
public function has_thank_you_page() {
|
|
|
|
$page_id = $this->get_thank_you_page_id();
|
|
|
|
return $page_id && get_post($page_id);
|
|
}
|
|
|
|
/**
|
|
* Get custom thank you page, if set.
|
|
*
|
|
* @since 2.0.0
|
|
* @return string
|
|
*/
|
|
public function get_thank_you_page_id() {
|
|
|
|
if ($this->thank_you_page_id === null) {
|
|
$this->thank_you_page_id = $this->get_meta('wu_thank_you_page_id', '');
|
|
}
|
|
|
|
return $this->thank_you_page_id;
|
|
}
|
|
|
|
/**
|
|
* Set custom thank you page, if set.
|
|
*
|
|
* @since 2.0.0
|
|
* @param int $thank_you_page_id The thank you page ID. This page is shown after a successful purchase.
|
|
* @return void
|
|
*/
|
|
public function set_thank_you_page_id($thank_you_page_id) {
|
|
|
|
$this->meta['wu_thank_you_page_id'] = $thank_you_page_id;
|
|
|
|
$this->thank_you_page_id = $thank_you_page_id;
|
|
}
|
|
|
|
/**
|
|
* Get Snippets to run on thank you page.
|
|
*
|
|
* @since 2.0.0
|
|
* @return string
|
|
*/
|
|
public function get_conversion_snippets() {
|
|
|
|
if ($this->conversion_snippets === null) {
|
|
$this->conversion_snippets = $this->get_meta('wu_conversion_snippets', '');
|
|
}
|
|
|
|
return $this->conversion_snippets;
|
|
}
|
|
|
|
/**
|
|
* Set snippets to run on thank you page.
|
|
*
|
|
* @since 2.0.0
|
|
* @param string $conversion_snippets Snippets to run on thank you page.
|
|
* @return void
|
|
*/
|
|
public function set_conversion_snippets($conversion_snippets) {
|
|
|
|
$this->meta['wu_conversion_snippets'] = $conversion_snippets;
|
|
|
|
$this->conversion_snippets = $conversion_snippets;
|
|
}
|
|
|
|
/**
|
|
* Save (create or update) the model on the database.
|
|
*
|
|
* Overrides the save method to set the template.
|
|
* This is used on CLI creation.
|
|
*
|
|
* @since 2.0.0
|
|
*
|
|
* @return bool
|
|
*/
|
|
public function save() {
|
|
|
|
$step_types = array(
|
|
'multi-step',
|
|
'single-step',
|
|
);
|
|
|
|
if ($this->template && in_array($this->template, $step_types, true)) {
|
|
$this->use_template($this->template);
|
|
}
|
|
|
|
return parent::save();
|
|
}
|
|
|
|
/**
|
|
* Get can be either 'blank', 'single-step' or 'multi-step'.
|
|
*
|
|
* @since 2.0.0
|
|
* @return string
|
|
*/
|
|
public function get_template() {
|
|
|
|
return $this->template;
|
|
}
|
|
|
|
/**
|
|
* Set the template mode. THis is mostly used on CLI.
|
|
*
|
|
* @since 2.0.0
|
|
* @param string $template Template mode. Can be either 'blank', 'single-step' or 'multi-step'.
|
|
* @options blank,single-step,multi-step
|
|
* @return void
|
|
*/
|
|
public function set_template($template) {
|
|
|
|
$this->template = $template;
|
|
}
|
|
|
|
/**
|
|
* Custom fields to allow customer to finish a payment intent.
|
|
*
|
|
* @since 2.0.18
|
|
* @return array
|
|
*/
|
|
public static function finish_checkout_form_fields() {
|
|
|
|
$payment = wu_get_payment_by_hash(wu_request('payment'));
|
|
|
|
if ( ! $payment && wu_request('payment_id')) {
|
|
$payment = wu_get_payment(wu_request('payment_id'));
|
|
}
|
|
|
|
if ( ! $payment && current_user_can('manage_options')) {
|
|
$payment = wu_mock_payment();
|
|
}
|
|
|
|
if ( ! $payment) {
|
|
return array();
|
|
}
|
|
|
|
$fields = array(
|
|
array(
|
|
'step' => 'checkout',
|
|
'name' => __('Your Order', 'wp-ultimo'),
|
|
'type' => 'order_summary',
|
|
'id' => 'order_summary',
|
|
'order_summary_template' => 'clean',
|
|
'table_columns' => 'simple',
|
|
),
|
|
array(
|
|
'step' => 'checkout',
|
|
'name' => __('Payment Method', 'wp-ultimo'),
|
|
'type' => 'payment',
|
|
'id' => 'payment',
|
|
),
|
|
array(
|
|
'step' => 'checkout',
|
|
'name' => __('Finish Payment', 'wp-ultimo'),
|
|
'type' => 'submit_button',
|
|
'id' => 'checkout',
|
|
'order' => 0,
|
|
),
|
|
);
|
|
|
|
$steps = array(
|
|
array(
|
|
'id' => 'checkout',
|
|
'name' => __('Checkout', 'wp-ultimo'),
|
|
'desc' => '',
|
|
'fields' => $fields,
|
|
),
|
|
);
|
|
|
|
return apply_filters('wu_checkout_form_finish_checkout_form_fields', $steps);
|
|
}
|
|
|
|
/**
|
|
* Custom fields for back-end upgrade/downgrades and such.
|
|
*
|
|
* @since 2.0.0
|
|
* @return array
|
|
*/
|
|
public static function membership_change_form_fields() {
|
|
|
|
$membership = WP_Ultimo()->currents->get_membership();
|
|
|
|
if ( ! $membership && wu_request('membership_id')) {
|
|
$membership = wu_get_membership(wu_request('membership_id'));
|
|
}
|
|
|
|
if ( ! $membership && current_user_can('manage_options')) {
|
|
$membership = wu_mock_membership();
|
|
}
|
|
|
|
if ( ! $membership) {
|
|
return array();
|
|
}
|
|
|
|
$fields = array();
|
|
|
|
/*
|
|
* Adds the addons
|
|
* selected on the plan.
|
|
*/
|
|
$plan = $membership->get_plan();
|
|
|
|
if ($plan) {
|
|
/*
|
|
* Get the group
|
|
*/
|
|
$group = $plan->get_group();
|
|
|
|
$search_arguments = array(
|
|
'fields' => 'ids',
|
|
);
|
|
|
|
if ($group) {
|
|
$search_arguments['product_group'] = $group;
|
|
} else {
|
|
/*
|
|
* If there isn't a group available
|
|
* limit the return to 3.
|
|
*/
|
|
$search_arguments['number'] = 3;
|
|
}
|
|
|
|
$plans = wu_get_plans($search_arguments);
|
|
|
|
$products = array_map('wu_get_product', $plans);
|
|
|
|
$period_selection = array();
|
|
|
|
$should_use_period_selector = false;
|
|
|
|
/**
|
|
* Lets see if we need a period selector
|
|
* and witch selectors we need
|
|
*/
|
|
foreach ($products as $product) {
|
|
$days_in_cycle = wu_get_days_in_cycle($product->get_duration_unit(), $product->get_duration());
|
|
|
|
$label = sprintf(
|
|
// translators: %1$s the duration, and %2$s the duration unit (day, week, month, etc)
|
|
_n('%2$s', '%1$s %2$s', $product->get_duration(), 'wp-ultimo'), // phpcs:ignore
|
|
$product->get_duration(),
|
|
wu_get_translatable_string($product->get_duration() <= 1 ? $product->get_duration_unit() : $product->get_duration_unit() . 's')
|
|
);
|
|
|
|
$period_selection[ $days_in_cycle ] = array(
|
|
'duration' => $product->get_duration(),
|
|
'duration_unit' => $product->get_duration_unit(),
|
|
'label' => $label,
|
|
);
|
|
|
|
$variations = $product->get_price_variations();
|
|
|
|
if (empty($variations)) {
|
|
continue;
|
|
}
|
|
|
|
/**
|
|
* We have different variations on same product
|
|
*/
|
|
|
|
$should_use_period_selector = true;
|
|
|
|
foreach ($variations as $variation) {
|
|
/**
|
|
* Get variations for selector
|
|
*/
|
|
$days_in_cycle = wu_get_days_in_cycle($variation['duration_unit'], $variation['duration']);
|
|
|
|
$label = sprintf(
|
|
// translators: %1$s the duration, and %2$s the duration unit (day, week, month, etc)
|
|
_n('%2$s', '%1$s %2$s', $variation['duration'], 'wp-ultimo'), // phpcs:ignore
|
|
$variation['duration'],
|
|
wu_get_translatable_string($variation['duration'] <= 1 ? $variation['duration_unit'] : $variation['duration_unit'] . 's')
|
|
);
|
|
|
|
$period_selection[ $days_in_cycle ] = array(
|
|
'duration' => $variation['duration'],
|
|
'duration_unit' => $variation['duration_unit'],
|
|
'label' => $label,
|
|
);
|
|
}
|
|
}
|
|
|
|
ksort($period_selection);
|
|
|
|
if ($should_use_period_selector) {
|
|
$fields[] = array(
|
|
'step' => 'checkout',
|
|
'name' => '',
|
|
'type' => 'period_selection',
|
|
'id' => 'period_selection',
|
|
'period_selection_template' => 'clean',
|
|
'period_options' => array_values($period_selection),
|
|
);
|
|
}
|
|
|
|
$fields[] = array(
|
|
'step' => 'checkout',
|
|
'name' => __('Plans', 'wp-ultimo'),
|
|
'type' => 'pricing_table',
|
|
'id' => 'pricing_table',
|
|
'required' => true,
|
|
'pricing_table_products' => implode(',', $plans),
|
|
'pricing_table_template' => 'list',
|
|
'force_different_durations' => (int) ! $should_use_period_selector,
|
|
);
|
|
|
|
$available_addons = (array) $plan->get_available_addons();
|
|
|
|
foreach ($available_addons as $addon_id) {
|
|
if ( ! $addon_id) {
|
|
continue;
|
|
}
|
|
|
|
$addon = wu_get_product($addon_id);
|
|
|
|
if ( ! $addon) {
|
|
continue;
|
|
}
|
|
|
|
$fields[] = array(
|
|
'id' => "order_bump_{$addon_id}",
|
|
'type' => 'order_bump',
|
|
'name' => $addon->get_name(),
|
|
'product' => $addon_id,
|
|
'display_product_image' => true,
|
|
);
|
|
}
|
|
}
|
|
|
|
$end_fields = array(
|
|
array(
|
|
'step' => 'checkout',
|
|
'name' => __('Your Order', 'wp-ultimo'),
|
|
'type' => 'order_summary',
|
|
'id' => 'order_summary',
|
|
'order_summary_template' => 'clean',
|
|
'table_columns' => 'simple',
|
|
),
|
|
array(
|
|
'step' => 'checkout',
|
|
'name' => __('Payment Method', 'wp-ultimo'),
|
|
'type' => 'payment',
|
|
'id' => 'payment',
|
|
),
|
|
array(
|
|
'step' => 'checkout',
|
|
'name' => __('Complete Checkout', 'wp-ultimo'),
|
|
'type' => 'submit_button',
|
|
'id' => 'checkout',
|
|
'order' => 0,
|
|
),
|
|
);
|
|
|
|
$fields = array_merge($fields, $end_fields);
|
|
|
|
$steps = array(
|
|
array(
|
|
'id' => 'checkout',
|
|
'name' => __('Checkout', 'wp-ultimo'),
|
|
'desc' => '',
|
|
'fields' => $fields,
|
|
),
|
|
);
|
|
|
|
return apply_filters('wu_checkout_form_membership_change_form_fields', $steps);
|
|
}
|
|
|
|
/**
|
|
* Custom fields to add to the add new site screen.
|
|
*
|
|
* @since 2.0.11
|
|
* @return array
|
|
*/
|
|
public static function add_new_site_form_fields() {
|
|
|
|
$membership = WP_Ultimo()->currents->get_membership();
|
|
|
|
if ( ! $membership) {
|
|
return array();
|
|
}
|
|
|
|
/*
|
|
* Adds the addons
|
|
* selected on the plan.
|
|
*/
|
|
$plan = $membership->get_plan();
|
|
|
|
$steps = array();
|
|
|
|
// As this limit is not membership based, we need to exclude from verification here
|
|
if ($membership->get_limitations(true, true)->site_templates->is_enabled()) {
|
|
$template_selection_fields = array(
|
|
array(
|
|
'step' => 'template',
|
|
'name' => __('Template Selection', 'wp-ultimo'),
|
|
'type' => 'template_selection',
|
|
'id' => 'template_selection',
|
|
'cols' => 4,
|
|
'template_selection_template' => 'clean',
|
|
'order' => 0,
|
|
),
|
|
array(
|
|
'step' => 'template',
|
|
'type' => 'hidden',
|
|
'id' => 'create-new-site',
|
|
'fixed_value' => wp_create_nonce('create-new-site'),
|
|
),
|
|
);
|
|
|
|
$steps[] = array(
|
|
'id' => 'template',
|
|
'name' => __('Template Selection', 'wp-ultimo'),
|
|
'desc' => '',
|
|
'fields' => $template_selection_fields,
|
|
);
|
|
}
|
|
|
|
$final_fields = array(
|
|
array(
|
|
'step' => 'create',
|
|
'type' => 'products',
|
|
'id' => 'products',
|
|
'products' => $plan->get_id(),
|
|
),
|
|
array(
|
|
'step' => 'create',
|
|
'type' => 'hidden',
|
|
'id' => 'membership_id',
|
|
'fixed_value' => $membership->get_id(),
|
|
),
|
|
array(
|
|
'step' => 'create',
|
|
'type' => 'hidden',
|
|
'id' => 'create-new-site',
|
|
'fixed_value' => wp_create_nonce('create-new-site'),
|
|
),
|
|
array(
|
|
'step' => 'create',
|
|
'type' => 'hidden',
|
|
'id' => 'redirect_url',
|
|
'fixed_value' => wu_request('redirect_url'),
|
|
),
|
|
);
|
|
|
|
$final_fields[] = array(
|
|
'step' => 'create',
|
|
'id' => 'site_title',
|
|
'name' => __('Site Title', 'wp-ultimo'),
|
|
'tooltip' => '',
|
|
'placeholder' => '',
|
|
'type' => 'site_title',
|
|
);
|
|
|
|
$domain_options = wu_get_available_domain_options();
|
|
|
|
$final_fields[] = array(
|
|
'step' => 'create',
|
|
'id' => 'site_url',
|
|
'name' => __('Site URL', 'wp-ultimo'),
|
|
'tooltip' => '',
|
|
'placeholder' => '',
|
|
'display_field_attachments' => false,
|
|
'type' => 'site_url',
|
|
'enable_domain_selection' => ! empty($domain_options),
|
|
'available_domains' => implode(PHP_EOL, $domain_options),
|
|
);
|
|
|
|
$final_fields[] = array(
|
|
'step' => 'create',
|
|
'name' => __('Create Site', 'wp-ultimo'),
|
|
'type' => 'submit_button',
|
|
'id' => 'checkout',
|
|
'order' => 0,
|
|
);
|
|
|
|
$steps[] = array(
|
|
'id' => 'create',
|
|
'name' => __('Create Site', 'wp-ultimo'),
|
|
'desc' => '',
|
|
'classes' => 'wu-max-w-sm',
|
|
'fields' => $final_fields,
|
|
);
|
|
|
|
return apply_filters('wu_checkout_form_add_new_site_form_fields', $steps);
|
|
}
|
|
}
|