Files
wp-multisite-waas/inc/models/class-checkout-form.php
2025-02-07 19:02:33 -07:00

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);
}
}