Initial Commit
This commit is contained in:
336
inc/ui/class-account-summary-element.php
Normal file
336
inc/ui/class-account-summary-element.php
Normal file
@ -0,0 +1,336 @@
|
||||
<?php
|
||||
/**
|
||||
* Adds the Account Summary Element UI to the Admin Panel.
|
||||
*
|
||||
* @package WP_Ultimo
|
||||
* @subpackage UI
|
||||
* @since 2.0.0
|
||||
*/
|
||||
|
||||
namespace WP_Ultimo\UI;
|
||||
|
||||
use \WP_Ultimo\UI\Base_Element;
|
||||
|
||||
// Exit if accessed directly
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
/**
|
||||
* Adds the Checkout Element UI to the Admin Panel.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
class Account_Summary_Element extends Base_Element {
|
||||
|
||||
use \WP_Ultimo\Traits\Singleton;
|
||||
|
||||
/**
|
||||
* The id of the element.
|
||||
*
|
||||
* Something simple, without prefixes, like 'checkout', or 'pricing-tables'.
|
||||
*
|
||||
* This is used to construct shortcodes by prefixing the id with 'wu_'
|
||||
* e.g. an id checkout becomes the shortcode 'wu_checkout' and
|
||||
* to generate the Gutenberg block by prefixing it with 'wp-ultimo/'
|
||||
* e.g. checkout would become the block 'wp-ultimo/checkout'.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @var string
|
||||
*/
|
||||
public $id = 'account-summary';
|
||||
|
||||
/**
|
||||
* Controls if this is a public element to be used in pages/shortcodes by user.
|
||||
*
|
||||
* @since 2.0.24
|
||||
* @var boolean
|
||||
*/
|
||||
protected $public = true;
|
||||
|
||||
/**
|
||||
* The current site.
|
||||
*
|
||||
* @since 2.2.0
|
||||
* @var \WP_Ultimo\Models\Site
|
||||
*/
|
||||
protected $site;
|
||||
|
||||
/**
|
||||
* The current membership.
|
||||
*
|
||||
* @since 2.2.0
|
||||
* @var \WP_Ultimo\Models\Membership
|
||||
*/
|
||||
protected $membership;
|
||||
|
||||
/**
|
||||
* The current product.
|
||||
*
|
||||
* @since 2.2.0
|
||||
* @var \WP_Ultimo\Models\Product
|
||||
*/
|
||||
protected $product;
|
||||
|
||||
/**
|
||||
* The attributes to be passed to the template.
|
||||
*
|
||||
* @since 2.2.0
|
||||
* @var array
|
||||
*/
|
||||
protected $atts;
|
||||
|
||||
/**
|
||||
* The icon of the UI element.
|
||||
* e.g. return fa fa-search
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @param string $context One of the values: block, elementor or bb.
|
||||
* @return string
|
||||
*/
|
||||
public function get_icon($context = 'block') {
|
||||
|
||||
if ($context === 'elementor') {
|
||||
|
||||
return 'eicon-call-to-action';
|
||||
|
||||
} // end if;
|
||||
|
||||
return 'fa fa-search';
|
||||
|
||||
} // end get_icon;
|
||||
|
||||
/**
|
||||
* The title of the UI element.
|
||||
*
|
||||
* This is used on the Blocks list of Gutenberg.
|
||||
* You should return a string with the localized title.
|
||||
* e.g. return __('My Element', 'wp-ultimo').
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return string
|
||||
*/
|
||||
public function get_title() {
|
||||
|
||||
return __('Account Summary', 'wp-ultimo');
|
||||
|
||||
} // end get_title;
|
||||
|
||||
/**
|
||||
* The description of the UI element.
|
||||
*
|
||||
* This is also used on the Gutenberg block list
|
||||
* to explain what this block is about.
|
||||
* You should return a string with the localized title.
|
||||
* e.g. return __('Adds a checkout form to the page', 'wp-ultimo').
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return string
|
||||
*/
|
||||
public function get_description() {
|
||||
|
||||
return __('Adds a account summary block to the page.', 'wp-ultimo');
|
||||
|
||||
} // end get_description;
|
||||
|
||||
/**
|
||||
* The list of fields to be added to Gutenberg.
|
||||
*
|
||||
* If you plan to add Gutenberg controls to this block,
|
||||
* you'll need to return an array of fields, following
|
||||
* our fields interface (@see inc/ui/class-field.php).
|
||||
*
|
||||
* You can create new Gutenberg panels by adding fields
|
||||
* with the type 'header'. See the Checkout Elements for reference.
|
||||
*
|
||||
* @see inc/ui/class-checkout-element.php
|
||||
*
|
||||
* Return an empty array if you don't have controls to add.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return array
|
||||
*/
|
||||
public function fields() {
|
||||
|
||||
$fields = array();
|
||||
|
||||
$fields['header'] = array(
|
||||
'title' => __('General', 'wp-ultimo'),
|
||||
'desc' => __('General', 'wp-ultimo'),
|
||||
'type' => 'header',
|
||||
);
|
||||
|
||||
$fields['title'] = array(
|
||||
'type' => 'text',
|
||||
'title' => __('Title', 'wp-ultimo'),
|
||||
'value' => __('About this Site', 'wp-ultimo'),
|
||||
'desc' => __('Leave blank to hide the title completely.', 'wp-ultimo'),
|
||||
'tooltip' => '',
|
||||
);
|
||||
|
||||
return $fields;
|
||||
|
||||
} // end fields;
|
||||
|
||||
/**
|
||||
* The list of keywords for this element.
|
||||
*
|
||||
* Return an array of strings with keywords describing this
|
||||
* element. Gutenberg uses this to help customers find blocks.
|
||||
*
|
||||
* e.g.:
|
||||
* return array(
|
||||
* 'WP Ultimo',
|
||||
* 'Checkout',
|
||||
* 'Form',
|
||||
* 'Cart',
|
||||
* );
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return array
|
||||
*/
|
||||
public function keywords() {
|
||||
|
||||
return array(
|
||||
'WP Ultimo',
|
||||
'Account',
|
||||
'Summary',
|
||||
);
|
||||
|
||||
} // end keywords;
|
||||
|
||||
/**
|
||||
* List of default parameters for the element.
|
||||
*
|
||||
* If you are planning to add controls using the fields,
|
||||
* it might be a good idea to use this method to set defaults
|
||||
* for the parameters you are expecting.
|
||||
*
|
||||
* These defaults will be used inside a 'wp_parse_args' call
|
||||
* before passing the parameters down to the block render
|
||||
* function and the shortcode render function.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return array
|
||||
*/
|
||||
public function defaults() {
|
||||
|
||||
return array(
|
||||
'title' => __('About this Site', 'wp-ultimo'),
|
||||
);
|
||||
|
||||
} // end defaults;
|
||||
|
||||
/**
|
||||
* Runs early on the request lifecycle as soon as we detect the shortcode is present.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return void
|
||||
*/
|
||||
public function setup() {
|
||||
|
||||
$this->site = WP_Ultimo()->currents->get_site();
|
||||
|
||||
if (!$this->site || !$this->site->is_customer_allowed()) {
|
||||
|
||||
$this->set_display(false);
|
||||
|
||||
return;
|
||||
|
||||
} // end if;
|
||||
|
||||
$this->membership = $this->site->get_membership();
|
||||
|
||||
$this->product = $this->membership ? $this->membership->get_plan() : false;
|
||||
|
||||
is_multisite() && switch_to_blog($this->site->get_id());
|
||||
|
||||
$space_used = get_space_used() * 1024 * 1024;
|
||||
$space_allowed = get_space_allowed() ? get_space_allowed() * 1024 * 1024 : 1;
|
||||
$percentage = ceil($space_used / $space_allowed * 100);
|
||||
$unlimited_space = get_site_option('upload_space_check_disabled');
|
||||
$message = $unlimited_space ? '%s' : '%s / %s';
|
||||
|
||||
is_multisite() && restore_current_blog();
|
||||
|
||||
$this->atts = array(
|
||||
'site_trial' => 0, // @todo: fix this
|
||||
'space_used' => $space_used,
|
||||
'space_allowed' => $space_allowed,
|
||||
'percentage' => $percentage,
|
||||
'unlimited_space' => $unlimited_space,
|
||||
'message' => $message,
|
||||
);
|
||||
|
||||
} // end setup;
|
||||
|
||||
/**
|
||||
* Allows the setup in the context of previews.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return void
|
||||
*/
|
||||
public function setup_preview() {
|
||||
|
||||
$this->site = wu_mock_site();
|
||||
|
||||
$this->membership = wu_mock_membership();
|
||||
|
||||
$this->product = wu_mock_product();
|
||||
|
||||
$unlimited_space = get_site_option('upload_space_check_disabled');
|
||||
$message = $unlimited_space ? '%s' : '%s / %s';
|
||||
|
||||
$this->atts = array(
|
||||
'site_trial' => 30, // @todo: fix this
|
||||
'space_used' => 120 * MB_IN_BYTES,
|
||||
'space_allowed' => 1 * GB_IN_BYTES,
|
||||
'percentage' => 120 * MB_IN_BYTES / 1 * GB_IN_BYTES,
|
||||
'unlimited_space' => $unlimited_space,
|
||||
'message' => $message,
|
||||
);
|
||||
|
||||
} // end setup_preview;
|
||||
|
||||
/**
|
||||
* The content to be output on the screen.
|
||||
*
|
||||
* Should return HTML markup to be used to display the block.
|
||||
* This method is shared between the block render method and
|
||||
* the shortcode implementation.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*
|
||||
* @param array $atts Parameters of the block/shortcode.
|
||||
* @param string|null $content The content inside the shortcode.
|
||||
* @return string
|
||||
*/
|
||||
public function output($atts, $content = null) {
|
||||
|
||||
$atts = array_merge($atts, $this->atts);
|
||||
|
||||
$atts['site'] = $this->site;
|
||||
|
||||
$atts['membership'] = $this->membership;
|
||||
|
||||
$atts['product'] = $this->product;
|
||||
|
||||
return wu_get_template_contents('dashboard-widgets/account-summary', $atts);
|
||||
|
||||
} // end output;
|
||||
|
||||
/**
|
||||
* Returns the manage URL for sites, depending on the environment.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*
|
||||
* @param int $site_id A Site ID.
|
||||
* @return string
|
||||
*/
|
||||
public function get_manage_url($site_id) {
|
||||
|
||||
$base_url = \WP_Ultimo\Current::get_manage_url($site_id, 'site');
|
||||
|
||||
return is_admin() ? add_query_arg('page', 'account', $base_url . '/admin.php') : $base_url;
|
||||
|
||||
} // end get_manage_url;
|
||||
|
||||
} // end class Account_Summary_Element;
|
1387
inc/ui/class-base-element.php
Normal file
1387
inc/ui/class-base-element.php
Normal file
File diff suppressed because it is too large
Load Diff
423
inc/ui/class-billing-info-element.php
Normal file
423
inc/ui/class-billing-info-element.php
Normal file
@ -0,0 +1,423 @@
|
||||
<?php
|
||||
/**
|
||||
* Adds the Billing_Info_Element UI to the Admin Panel.
|
||||
*
|
||||
* @package WP_Ultimo
|
||||
* @subpackage UI
|
||||
* @since 2.0.0
|
||||
*/
|
||||
|
||||
namespace WP_Ultimo\UI;
|
||||
|
||||
use WP_Ultimo\UI\Base_Element;
|
||||
|
||||
// Exit if accessed directly
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
/**
|
||||
* Adds the Checkout Element UI to the Admin Panel.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
class Billing_Info_Element extends Base_Element {
|
||||
|
||||
use \WP_Ultimo\Traits\Singleton;
|
||||
|
||||
/**
|
||||
* The id of the element.
|
||||
*
|
||||
* Something simple, without prefixes, like 'checkout', or 'pricing-tables'.
|
||||
*
|
||||
* This is used to construct shortcodes by prefixing the id with 'wu_'
|
||||
* e.g. an id checkout becomes the shortcode 'wu_checkout' and
|
||||
* to generate the Gutenberg block by prefixing it with 'wp-ultimo/'
|
||||
* e.g. checkout would become the block 'wp-ultimo/checkout'.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @var string
|
||||
*/
|
||||
public $id = 'billing-info';
|
||||
|
||||
/**
|
||||
* Controls if this is a public element to be used in pages/shortcodes by user.
|
||||
*
|
||||
* @since 2.0.24
|
||||
* @var boolean
|
||||
*/
|
||||
protected $public = true;
|
||||
|
||||
/**
|
||||
* The membership object.
|
||||
*
|
||||
* @since 2.2.0
|
||||
* @var \WP_Ultimo\Membership
|
||||
*/
|
||||
protected $membership;
|
||||
|
||||
/**
|
||||
* The site object.
|
||||
*
|
||||
* @since 2.2.0
|
||||
* @var \WP_Ultimo\Site
|
||||
*/
|
||||
protected $site;
|
||||
|
||||
/**
|
||||
* The icon of the UI element.
|
||||
* e.g. return fa fa-search
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @param string $context One of the values: block, elementor or bb.
|
||||
*/
|
||||
public function get_icon($context = 'block'): string {
|
||||
|
||||
if ($context === 'elementor') {
|
||||
|
||||
return 'eicon-info-circle-o';
|
||||
|
||||
} // end if;
|
||||
|
||||
return 'fa fa-search';
|
||||
|
||||
} // end get_icon;
|
||||
|
||||
/**
|
||||
* Overload the init to add site-related forms.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return void
|
||||
*/
|
||||
public function init() {
|
||||
|
||||
parent::init();
|
||||
|
||||
wu_register_form('update_billing_address', array(
|
||||
'render' => array($this, 'render_update_billing_address'),
|
||||
'handler' => array($this, 'handle_update_billing_address'),
|
||||
'capability' => 'exist',
|
||||
));
|
||||
|
||||
} // end init;
|
||||
|
||||
/**
|
||||
* Loads the required scripts.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return void
|
||||
*/
|
||||
public function register_scripts() {
|
||||
|
||||
add_wubox();
|
||||
|
||||
} // end register_scripts;
|
||||
|
||||
/**
|
||||
* The title of the UI element.
|
||||
*
|
||||
* This is used on the Blocks list of Gutenberg.
|
||||
* You should return a string with the localized title.
|
||||
* e.g. return __('My Element', 'wp-ultimo').
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return string
|
||||
*/
|
||||
public function get_title() {
|
||||
|
||||
return __('Billing Information', 'wp-ultimo');
|
||||
|
||||
} // end get_title;
|
||||
|
||||
/**
|
||||
* The description of the UI element.
|
||||
*
|
||||
* This is also used on the Gutenberg block list
|
||||
* to explain what this block is about.
|
||||
* You should return a string with the localized title.
|
||||
* e.g. return __('Adds a checkout form to the page', 'wp-ultimo').
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return string
|
||||
*/
|
||||
public function get_description() {
|
||||
|
||||
return __('Adds a checkout form block to the page.', 'wp-ultimo');
|
||||
|
||||
} // end get_description;
|
||||
|
||||
/**
|
||||
* The list of fields to be added to Gutenberg.
|
||||
*
|
||||
* If you plan to add Gutenberg controls to this block,
|
||||
* you'll need to return an array of fields, following
|
||||
* our fields interface (@see inc/ui/class-field.php).
|
||||
*
|
||||
* You can create new Gutenberg panels by adding fields
|
||||
* with the type 'header'. See the Checkout Elements for reference.
|
||||
*
|
||||
* @see inc/ui/class-checkout-element.php
|
||||
*
|
||||
* Return an empty array if you don't have controls to add.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return array
|
||||
*/
|
||||
public function fields() {
|
||||
|
||||
$fields = array();
|
||||
|
||||
$fields['header'] = array(
|
||||
'title' => __('General', 'wp-ultimo'),
|
||||
'desc' => __('General', 'wp-ultimo'),
|
||||
'type' => 'header',
|
||||
);
|
||||
|
||||
$fields['title'] = array(
|
||||
'type' => 'text',
|
||||
'title' => __('Title', 'wp-ultimo'),
|
||||
'value' => __('Billing Address', 'wp-ultimo'),
|
||||
'desc' => __('Leave blank to hide the title completely.', 'wp-ultimo'),
|
||||
'tooltip' => '',
|
||||
);
|
||||
|
||||
return $fields;
|
||||
|
||||
} // end fields;
|
||||
|
||||
/**
|
||||
* The list of keywords for this element.
|
||||
*
|
||||
* Return an array of strings with keywords describing this
|
||||
* element. Gutenberg uses this to help customers find blocks.
|
||||
*
|
||||
* e.g.:
|
||||
* return array(
|
||||
* 'WP Ultimo',
|
||||
* 'Billing Information',
|
||||
* 'Form',
|
||||
* 'Cart',
|
||||
* );
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return array
|
||||
*/
|
||||
public function keywords() {
|
||||
|
||||
return array(
|
||||
'WP Ultimo',
|
||||
'Billing Information',
|
||||
'Form',
|
||||
'Cart',
|
||||
);
|
||||
|
||||
} // end keywords;
|
||||
|
||||
/**
|
||||
* List of default parameters for the element.
|
||||
*
|
||||
* If you are planning to add controls using the fields,
|
||||
* it might be a good idea to use this method to set defaults
|
||||
* for the parameters you are expecting.
|
||||
*
|
||||
* These defaults will be used inside a 'wp_parse_args' call
|
||||
* before passing the parameters down to the block render
|
||||
* function and the shortcode render function.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return array
|
||||
*/
|
||||
public function defaults() {
|
||||
|
||||
return array(
|
||||
'title' => __('Billing Address', 'wp-ultimo'),
|
||||
);
|
||||
|
||||
} // end defaults;
|
||||
|
||||
/**
|
||||
* Runs early on the request lifecycle as soon as we detect the shortcode is present.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return void
|
||||
*/
|
||||
public function setup() {
|
||||
|
||||
$this->membership = WP_Ultimo()->currents->get_membership();
|
||||
|
||||
if (!$this->membership) {
|
||||
|
||||
$this->set_display(false);
|
||||
|
||||
return;
|
||||
|
||||
} // end if;
|
||||
|
||||
} // end setup;
|
||||
|
||||
/**
|
||||
* Allows the setup in the context of previews.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return void
|
||||
*/
|
||||
public function setup_preview() {
|
||||
|
||||
$this->site = wu_mock_site();
|
||||
|
||||
$this->membership = wu_mock_membership();
|
||||
|
||||
} // end setup_preview;
|
||||
|
||||
/**
|
||||
* The content to be output on the screen.
|
||||
*
|
||||
* Should return HTML markup to be used to display the block.
|
||||
* This method is shared between the block render method and
|
||||
* the shortcode implementation.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*
|
||||
* @param array $atts Parameters of the block/shortcode.
|
||||
* @param string|null $content The content inside the shortcode.
|
||||
* @return string
|
||||
*/
|
||||
public function output($atts, $content = null) {
|
||||
|
||||
$atts['membership'] = $this->membership;
|
||||
|
||||
$atts['billing_address'] = $this->membership->get_billing_address();
|
||||
|
||||
$atts['update_billing_address_link'] = wu_get_form_url('update_billing_address', array(
|
||||
'membership' => $this->membership->get_hash(),
|
||||
'width' => 500,
|
||||
));
|
||||
|
||||
return wu_get_template_contents('dashboard-widgets/billing-info', $atts);
|
||||
|
||||
} // end output;
|
||||
|
||||
/**
|
||||
* Apply the placeholders to the fields.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*
|
||||
* @param array $fields The billing fields.
|
||||
* @return array
|
||||
*/
|
||||
protected function apply_placeholders($fields) {
|
||||
|
||||
foreach ($fields as &$field) {
|
||||
|
||||
$field['placeholder'] = $field['default_placeholder'];
|
||||
|
||||
} // end foreach;
|
||||
|
||||
return $fields;
|
||||
|
||||
} // end apply_placeholders;
|
||||
|
||||
/**
|
||||
* Renders the update billing address form.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return string
|
||||
*/
|
||||
public function render_update_billing_address() {
|
||||
|
||||
$membership = wu_get_membership_by_hash(wu_request('membership'));
|
||||
|
||||
if (!$membership) {
|
||||
|
||||
return '';
|
||||
|
||||
} // end if;
|
||||
|
||||
$billing_address = $membership->get_billing_address();
|
||||
|
||||
$fields = array();
|
||||
|
||||
$fields['billing-title'] = array(
|
||||
'type' => 'header',
|
||||
'order' => 1,
|
||||
'title' => __('Your Address', 'wp-ultimo'),
|
||||
'desc' => __('Enter your billing address here. This info will be used on your invoices.', 'wp-ultimo'),
|
||||
'wrapper_classes' => 'wu-col-span-2',
|
||||
);
|
||||
|
||||
$billing_fields = $this->apply_placeholders($billing_address->get_fields());
|
||||
|
||||
$fields = array_merge($fields, $billing_fields);
|
||||
|
||||
$fields['submit'] = array(
|
||||
'type' => 'submit',
|
||||
'title' => __('Save Changes', 'wp-ultimo'),
|
||||
'value' => 'save',
|
||||
'classes' => 'button button-primary wu-w-full',
|
||||
'wrapper_classes' => 'wu-col-span-2',
|
||||
);
|
||||
|
||||
$fields['membership'] = array(
|
||||
'type' => 'hidden',
|
||||
'value' => wu_request('membership'),
|
||||
);
|
||||
|
||||
$form = new \WP_Ultimo\UI\Form('edit_site', $fields, array(
|
||||
'views' => 'admin-pages/fields',
|
||||
'classes' => 'wu-modal-form wu-widget-list wu-striped wu-m-0 wu-mt-0 wu-grid-cols-2 wu-grid',
|
||||
'field_wrapper_classes' => 'wu-w-full wu-box-border wu-items-center wu-flex wu-justify-between wu-p-4 wu-m-0 wu-border-t wu-border-l-0 wu-border-r-0 wu-border-b-0 wu-border-gray-300 wu-border-solid wu-grid-col-span-2',
|
||||
'html_attr' => array(
|
||||
'data-wu-app' => 'edit_site',
|
||||
'data-state' => wu_convert_to_state(),
|
||||
),
|
||||
));
|
||||
|
||||
$form->render();
|
||||
|
||||
} // end render_update_billing_address;
|
||||
|
||||
/**
|
||||
* Handles the password reset form.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return void
|
||||
*/
|
||||
public function handle_update_billing_address() {
|
||||
|
||||
$membership = wu_get_membership_by_hash(wu_request('membership'));
|
||||
|
||||
if (!$membership) {
|
||||
|
||||
$error = new \WP_Error('membership-dont-exist', __('Something went wrong.', 'wp-ultimo'));
|
||||
|
||||
wp_send_json_error($error);
|
||||
|
||||
} // end if;
|
||||
|
||||
$billing_address = $membership->get_billing_address();
|
||||
|
||||
$billing_address->attributes($_POST);
|
||||
|
||||
$valid_address = $billing_address->validate();
|
||||
|
||||
if (is_wp_error($valid_address)) {
|
||||
|
||||
wp_send_json_error($valid_address);
|
||||
|
||||
} // end if;
|
||||
|
||||
$membership->set_billing_address($billing_address);
|
||||
|
||||
$saved = $membership->save();
|
||||
|
||||
if (is_wp_error($saved)) {
|
||||
|
||||
wp_send_json_error($saved);
|
||||
|
||||
} // end if;
|
||||
|
||||
wp_send_json_success(array(
|
||||
'redirect_url' => add_query_arg('updated', (int) $saved, $_SERVER['HTTP_REFERER']),
|
||||
));
|
||||
|
||||
} // end handle_update_billing_address;
|
||||
|
||||
} // end class Billing_Info_Element;
|
865
inc/ui/class-checkout-element.php
Normal file
865
inc/ui/class-checkout-element.php
Normal file
@ -0,0 +1,865 @@
|
||||
<?php
|
||||
/**
|
||||
* Adds the Checkout_Element UI to the Admin Panel.
|
||||
*
|
||||
* @package WP_Ultimo
|
||||
* @subpackage UI
|
||||
* @since 2.0.0
|
||||
*/
|
||||
|
||||
namespace WP_Ultimo\UI;
|
||||
|
||||
use \WP_Ultimo\UI\Base_Element;
|
||||
use \WP_Ultimo\Dependencies\ScssPhp\ScssPhp\Compiler;
|
||||
use \WP_Ultimo\Database\Memberships\Membership_Status;
|
||||
|
||||
// Exit if accessed directly
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
/**
|
||||
* Adds the Checkout Element UI to the Admin Panel.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
class Checkout_Element extends Base_Element {
|
||||
|
||||
use \WP_Ultimo\Traits\Singleton;
|
||||
|
||||
/**
|
||||
* The current signup.
|
||||
*
|
||||
* @since 2.2.0
|
||||
* @var Mocked_Signup
|
||||
*/
|
||||
protected $signup;
|
||||
|
||||
/**
|
||||
* The current checkout form steps.
|
||||
*
|
||||
* @since 2.2.0
|
||||
* @var array|false
|
||||
*/
|
||||
public $steps;
|
||||
|
||||
/**
|
||||
* The current checkout form step.
|
||||
*
|
||||
* @since 2.2.0
|
||||
* @var array
|
||||
*/
|
||||
public $step;
|
||||
|
||||
/**
|
||||
* The current checkout form step name.
|
||||
*
|
||||
* @since 2.2.0
|
||||
* @var string
|
||||
*/
|
||||
public $step_name;
|
||||
|
||||
/**
|
||||
* The id of the element.
|
||||
*
|
||||
* Something simple, without prefixes, like 'checkout', or 'pricing-tables'.
|
||||
*
|
||||
* This is used to construct shortcodes by prefixing the id with 'wu_'
|
||||
* e.g. an id checkout becomes the shortcode 'wu_checkout' and
|
||||
* to generate the Gutenberg block by prefixing it with 'wp-ultimo/'
|
||||
* e.g. checkout would become the block 'wp-ultimo/checkout'.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @var string
|
||||
*/
|
||||
public $id = 'checkout';
|
||||
|
||||
/**
|
||||
* Controls if this is a public element to be used in pages/shortcodes by user.
|
||||
*
|
||||
* @since 2.0.24
|
||||
* @var boolean
|
||||
*/
|
||||
protected $public = true;
|
||||
|
||||
/**
|
||||
* The icon of the UI element.
|
||||
* e.g. return fa fa-search
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @param string $context One of the values: block, elementor or bb.
|
||||
*/
|
||||
public function get_icon($context = 'block'): string {
|
||||
|
||||
if ($context === 'elementor') {
|
||||
|
||||
return 'eicon-cart-medium';
|
||||
|
||||
} // end if;
|
||||
|
||||
return 'fa fa-search';
|
||||
|
||||
} // end get_icon;
|
||||
|
||||
/**
|
||||
* The title of the UI element.
|
||||
*
|
||||
* This is used on the Blocks list of Gutenberg.
|
||||
* You should return a string with the localized title.
|
||||
* e.g. return __('My Element', 'wp-ultimo').
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return string
|
||||
*/
|
||||
public function get_title() {
|
||||
|
||||
return __('Checkout', 'wp-ultimo');
|
||||
|
||||
} // end get_title;
|
||||
|
||||
/**
|
||||
* The description of the UI element.
|
||||
*
|
||||
* This is also used on the Gutenberg block list
|
||||
* to explain what this block is about.
|
||||
* You should return a string with the localized title.
|
||||
* e.g. return __('Adds a checkout form to the page', 'wp-ultimo').
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return string
|
||||
*/
|
||||
public function get_description() {
|
||||
|
||||
return __('Adds a checkout form block to the page.', 'wp-ultimo');
|
||||
|
||||
} // end get_description;
|
||||
|
||||
/**
|
||||
* The list of fields to be added to Gutenberg.
|
||||
*
|
||||
* If you plan to add Gutenberg controls to this block,
|
||||
* you'll need to return an array of fields, following
|
||||
* our fields interface (@see inc/ui/class-field.php).
|
||||
*
|
||||
* You can create new Gutenberg panels by adding fields
|
||||
* with the type 'header'. See the Checkout Elements for reference.
|
||||
*
|
||||
* @see inc/ui/class-checkout-element.php
|
||||
*
|
||||
* Return an empty array if you don't have controls to add.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return array
|
||||
*/
|
||||
public function fields() {
|
||||
|
||||
$fields = array();
|
||||
|
||||
$fields['header'] = array(
|
||||
'title' => __('General', 'wp-ultimo'),
|
||||
'desc' => __('General', 'wp-ultimo'),
|
||||
'type' => 'header',
|
||||
);
|
||||
|
||||
$fields['slug'] = array(
|
||||
'title' => __('Slug', 'wp-ultimo'),
|
||||
'desc' => __('The checkout form slug.', 'wp-ultimo'),
|
||||
'type' => 'text',
|
||||
);
|
||||
|
||||
return $fields;
|
||||
|
||||
} // end fields;
|
||||
|
||||
/**
|
||||
* The list of keywords for this element.
|
||||
*
|
||||
* Return an array of strings with keywords describing this
|
||||
* element. Gutenberg uses this to help customers find blocks.
|
||||
*
|
||||
* e.g.:
|
||||
* return array(
|
||||
* 'WP Ultimo',
|
||||
* 'Checkout',
|
||||
* 'Form',
|
||||
* 'Cart',
|
||||
* );
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return array
|
||||
*/
|
||||
public function keywords() {
|
||||
|
||||
return array(
|
||||
'WP Ultimo',
|
||||
'Checkout',
|
||||
'Form',
|
||||
'Cart',
|
||||
);
|
||||
|
||||
} // end keywords;
|
||||
|
||||
/**
|
||||
* List of default parameters for the element.
|
||||
*
|
||||
* If you are planning to add controls using the fields,
|
||||
* it might be a good idea to use this method to set defaults
|
||||
* for the parameters you are expecting.
|
||||
*
|
||||
* These defaults will be used inside a 'wp_parse_args' call
|
||||
* before passing the parameters down to the block render
|
||||
* function and the shortcode render function.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return array
|
||||
*/
|
||||
public function defaults() {
|
||||
|
||||
return array(
|
||||
'slug' => 'main-form',
|
||||
'step' => false,
|
||||
'display_title' => false,
|
||||
'membership_limitations' => array(),
|
||||
);
|
||||
|
||||
} // end defaults;
|
||||
|
||||
/**
|
||||
* Checks if we are on a thank you page.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return boolean
|
||||
*/
|
||||
public function is_thank_you_page() {
|
||||
|
||||
return is_user_logged_in() && wu_request('payment') && wu_request('status') === 'done';
|
||||
|
||||
} // end is_thank_you_page;
|
||||
|
||||
/**
|
||||
* Triggers the setup event to allow the checkout class to hook in.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return void
|
||||
*/
|
||||
public function setup() {
|
||||
|
||||
if ($this->is_thank_you_page()) {
|
||||
|
||||
\WP_Ultimo\UI\Thank_You_Element::get_instance()->setup();
|
||||
|
||||
return;
|
||||
|
||||
} // end if;
|
||||
|
||||
do_action('wu_setup_checkout', $this);
|
||||
|
||||
} // end setup;
|
||||
|
||||
/**
|
||||
* Print the Custom CSS added on the checkout.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*
|
||||
* @param \WP_Ultimo\Models\Checkout_Form $checkout_form The current checkout form.
|
||||
* @return void
|
||||
*/
|
||||
public function print_custom_css($checkout_form) {
|
||||
|
||||
$scss = new Compiler();
|
||||
|
||||
$slug = $checkout_form->get_slug();
|
||||
|
||||
$custom_css = $checkout_form->get_custom_css();
|
||||
|
||||
if ($custom_css) {
|
||||
|
||||
$custom_css = $scss->compileString(".wu_checkout_form_{$slug} {
|
||||
{$custom_css}
|
||||
}")->getCss();
|
||||
|
||||
echo sprintf('<style>%s</style>', $custom_css);
|
||||
|
||||
} // end if;
|
||||
|
||||
} // end print_custom_css;
|
||||
|
||||
/**
|
||||
* Outputs thank you page.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*
|
||||
* @param array $atts Parameters of the block/shortcode.
|
||||
* @param string|null $content The content inside the shortcode.
|
||||
* @return string
|
||||
*/
|
||||
public function output_thank_you($atts, $content = null) {
|
||||
|
||||
$slug = $atts['slug'];
|
||||
|
||||
$checkout_form = wu_get_checkout_form_by_slug($slug);
|
||||
|
||||
$atts = $checkout_form->get_meta('wu_thank_you_settings');
|
||||
|
||||
$atts['checkout_form'] = $checkout_form;
|
||||
|
||||
\WP_Ultimo\UI\Thank_You_Element::get_instance()->register_scripts();
|
||||
|
||||
return \WP_Ultimo\UI\Thank_You_Element::get_instance()->output($atts, $content);
|
||||
|
||||
} // end output_thank_you;
|
||||
|
||||
/**
|
||||
* Outputs the registration form.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*
|
||||
* @param array $atts Parameters of the block/shortcode.
|
||||
* @param string|null $content The content inside the shortcode.
|
||||
* @return string
|
||||
*/
|
||||
public function output_form($atts, $content = null) {
|
||||
|
||||
$atts['step'] = wu_request('step', $atts['step']);
|
||||
|
||||
$slug = $atts['slug'];
|
||||
|
||||
$customer = wu_get_current_customer();
|
||||
|
||||
$membership = WP_Ultimo()->currents->get_membership();
|
||||
|
||||
/**
|
||||
* Allow developers bypass the output and set a new one
|
||||
*
|
||||
* @param string|boll $bypass If we should bypass the checkout form or a string to return instead of the form.
|
||||
* @param array $atts Parameters of the checkout block/shortcode.
|
||||
*/
|
||||
$bypass = apply_filters('wu_bypass_checkout_form', false, $atts);
|
||||
|
||||
if ($bypass) {
|
||||
|
||||
return is_string($bypass) ? $bypass : '';
|
||||
|
||||
} // end if;
|
||||
|
||||
if ($customer && $membership && $slug !== 'wu-finish-checkout') {
|
||||
|
||||
$published_sites = $membership->get_published_sites();
|
||||
|
||||
$pending_payment = $membership ? $membership->get_last_pending_payment() : false;
|
||||
|
||||
if ($pending_payment && !$membership->is_active() && $membership->get_status() !== Membership_Status::TRIALING) {
|
||||
/**
|
||||
* We are talking about membership with a pending payment
|
||||
*/
|
||||
|
||||
// Translators: Placeholder receives the customer display name
|
||||
$message = sprintf(__('Hi %s. You have a pending payment for your membership!', 'wp-ultimo'), $customer->get_display_name());
|
||||
|
||||
$payment_url = add_query_arg(array(
|
||||
'payment' => $pending_payment->get_hash(),
|
||||
), wu_get_registration_url());
|
||||
|
||||
// Translators: The link to registration url with payment hash
|
||||
$message .= '<br>' . sprintf(__('Click <a href="%s">here</a> to pay.', 'wp-ultimo'), $payment_url);
|
||||
|
||||
$message = '<p>' . $message . '</p>';
|
||||
|
||||
/**
|
||||
* Allow developers to change the message if membership have a pending payment
|
||||
*
|
||||
* @param string $message The HTML message to print in screen.
|
||||
* @param WP_Ultimo\Models\Membership $membership The membership in use.
|
||||
* @param WP_Ultimo\Models\Customer $customer The active customer in use.
|
||||
*/
|
||||
return apply_filters('wu_checkout_pending_payment_error_message', $message, $membership, $customer);
|
||||
|
||||
} // end if;
|
||||
|
||||
$membership_blocked_forms = array(
|
||||
'wu-add-new-site'
|
||||
);
|
||||
|
||||
if (!$membership->is_active() && $membership->get_status() !== Membership_Status::TRIALING && in_array($atts['slug'], $membership_blocked_forms, true)) {
|
||||
|
||||
// Translators: Placeholder receives the customer display name
|
||||
$message = sprintf(__('Hi %s. You cannot take action on your membership while it is not active!', 'wp-ultimo'), $customer->get_display_name());
|
||||
|
||||
if ($membership->get_status() === Membership_Status::PENDING && $customer->get_email_verification() === 'pending') {
|
||||
/**
|
||||
* Enqueue thank you page scripts to handle resend email verification link
|
||||
*/
|
||||
wp_register_script('wu-thank-you', wu_get_asset('thank-you.js', 'js'), array(), wu_get_version());
|
||||
|
||||
wp_localize_script('wu-thank-you', 'wu_thank_you', array(
|
||||
'ajaxurl' => admin_url('admin-ajax.php'),
|
||||
'resend_verification_email_nonce' => wp_create_nonce('wu_resend_verification_email_nonce'),
|
||||
'membership_hash' => $membership->get_hash(),
|
||||
'i18n' => array(
|
||||
'resending_verification_email' => __('Resending verification email...', 'wp-ultimo'),
|
||||
'email_sent' => __('Verification email sent!', 'wp-ultimo'),
|
||||
),
|
||||
));
|
||||
|
||||
wp_enqueue_script('wu-thank-you');
|
||||
|
||||
$message .= '<p>' . __('Check your inbox and verify your email address.', 'wp-ultimo') . '</p>';
|
||||
$message .= '<span class="wu-styling">';
|
||||
$message .= sprintf('<a href="#" class="wu-mr-2 wu-resend-verification-email wu-no-underline button button-primary">%s</a>', __('Resend verification email', 'wp-ultimo'));
|
||||
$message .= '</span>';
|
||||
|
||||
} // end if;
|
||||
|
||||
/**
|
||||
* Allow developers to change the message if membership have a pending payment
|
||||
*
|
||||
* @param string $message The HTML message to print in screen.
|
||||
* @param WP_Ultimo\Models\Membership $membership The membership in use.
|
||||
* @param WP_Ultimo\Models\Customer $customer The active customer in use.
|
||||
*/
|
||||
return apply_filters('wu_checkout_membership_status_error_message', $message, $membership, $customer);
|
||||
|
||||
} // end if;
|
||||
|
||||
if (!wu_multiple_memberships_enabled() && $membership) {
|
||||
|
||||
/**
|
||||
* Allow developers to add new form slugs to bypass this behaviour.
|
||||
*
|
||||
* @param array $slugs a list of form slugs to bypass.
|
||||
*/
|
||||
$allowed_forms = apply_filters('wu_get_membership_allowed_forms', array(
|
||||
'wu-checkout',
|
||||
'wu-add-new-site',
|
||||
));
|
||||
|
||||
if (!in_array($slug, $allowed_forms, true) && !wu_request('payment')) {
|
||||
|
||||
$message = sprintf('<p>%s</p>', __('You already have a membership!', 'wp-ultimo'));
|
||||
|
||||
if (isset($published_sites[0])) {
|
||||
|
||||
$account_link = get_admin_url($published_sites[0]->get_id(), 'admin.php?page=account');
|
||||
$button_text = __('Go to my account', 'wp-ultimo');
|
||||
|
||||
$message .= "<p><a class=\"wu-no-underline button button-primary\" href=\"$account_link\">$button_text</a><p>";
|
||||
|
||||
} // end if;
|
||||
|
||||
/**
|
||||
* Allow developers to change the message about the limitation of a single membership for customer.
|
||||
*
|
||||
* @param string $message The HTML message to print in screen.
|
||||
* @param WP_Ultimo\Models\Customer $customer The active customer in use.
|
||||
*/
|
||||
return apply_filters('wu_checkout_single_membership_message', $message, $customer);
|
||||
|
||||
} // end if;
|
||||
|
||||
} // end if;
|
||||
|
||||
if ($membership && $membership->get_customer_id() !== $customer->get_id()) {
|
||||
|
||||
$message = sprintf('<p>%s</p>', __('You are not allowed to change this membership!', 'wp-ultimo'));
|
||||
|
||||
/**
|
||||
* Allow developers to change the message if customer is not part of the membership
|
||||
*
|
||||
* @param string $message The HTML message to print in screen.
|
||||
* @param WP_Ultimo\Models\Membership $membership The membership in use.
|
||||
* @param WP_Ultimo\Models\Customer $customer The active customer in use.
|
||||
*/
|
||||
return apply_filters('wu_checkout_customer_error_message', $message, $membership, $customer);
|
||||
|
||||
} // end if;
|
||||
|
||||
/**
|
||||
* Now we filter the current membership for each membership_limitations
|
||||
* field in element atts to check if we can show the form, if not we show
|
||||
* a error message informing the user about and with buttons to allow
|
||||
* account upgrade and/or to buy a new membership.
|
||||
*/
|
||||
if ($membership && !empty($atts['membership_limitations'])) {
|
||||
|
||||
$limits = $membership->get_limitations();
|
||||
|
||||
foreach ($atts['membership_limitations'] as $limitation) {
|
||||
|
||||
if (!method_exists($membership, "get_$limitation")) {
|
||||
|
||||
continue;
|
||||
|
||||
} // end if;
|
||||
|
||||
$current_limit = $limits->{$limitation};
|
||||
|
||||
$limit_max = $current_limit->is_enabled() ? $current_limit->get_limit() : PHP_INT_MAX;
|
||||
|
||||
$limit_max = !empty($limit_max) ? (int) $limit_max : 1;
|
||||
|
||||
$used_limit = $membership->{"get_$limitation"}();
|
||||
|
||||
$used_limit = is_array($used_limit) ? count($used_limit) : (int) $used_limit;
|
||||
|
||||
if ($used_limit >= $limit_max) {
|
||||
|
||||
// Translators: Placeholder receives the limit name
|
||||
$message = '<p>' . sprintf(__('You reached your membership %s limit!', 'wp-ultimo'), $limitation) . '</p>';
|
||||
|
||||
$message .= '<span class="wu-styling">';
|
||||
|
||||
if (wu_multiple_memberships_enabled()) {
|
||||
|
||||
$register_page = wu_get_registration_url();
|
||||
$button_text = __('Buy a new membership', 'wp-ultimo');
|
||||
|
||||
$message .= "<a class=\"wu-no-underline button button-primary wu-mr-2\" href=\"$register_page\">$button_text</a>";
|
||||
|
||||
} // end if;
|
||||
|
||||
if ($limitation !== 'sites' || wu_get_setting('enable_multiple_sites')) {
|
||||
|
||||
$update_link = '';
|
||||
|
||||
$checkout_pages = \WP_Ultimo\Checkout\Checkout_Pages::get_instance();
|
||||
|
||||
$update_url = $checkout_pages->get_page_url('update');
|
||||
|
||||
if ($update_url) {
|
||||
|
||||
$update_link = add_query_arg(array(
|
||||
'membership' => $membership->get_hash(),
|
||||
), $update_url);
|
||||
|
||||
} elseif (is_admin()) {
|
||||
|
||||
$update_link = admin_url('admin.php?page=wu-checkout&membership=' . $membership->get_hash());
|
||||
|
||||
} elseif (isset($published_sites[0])) {
|
||||
|
||||
$update_link = get_admin_url($published_sites[0]->get_id(), 'admin.php?page=wu-checkout&membership=' . $membership->get_hash());
|
||||
|
||||
} // end if;
|
||||
|
||||
if (!empty($update_link)) {
|
||||
|
||||
$button_text = __('Upgrade your account', 'wp-ultimo');
|
||||
|
||||
$message .= "<a class=\"wu-no-underline button button-primary wu-mr-2\" href=\"$update_link\">$button_text</a>";
|
||||
|
||||
} // end if;
|
||||
|
||||
} // end if;
|
||||
|
||||
$message .= '</span>';
|
||||
|
||||
/**
|
||||
* Allow developers to change the message about the membership limit
|
||||
*
|
||||
* @param string $message The HTML message to print in screen.
|
||||
* @param string $limitation The limitation name.
|
||||
* @param int $limit_max The allowed limit.
|
||||
* @param int $used_limit The limit used in membership.
|
||||
* @param WP_Ultimo\Models\Membership $membership The membership in use.
|
||||
* @param WP_Ultimo\Models\Customer $customer The active customer in use.
|
||||
*/
|
||||
return apply_filters('wu_checkout_membership_limit_message', $message, $limitation, $limit_max, $used_limit, $membership, $customer);
|
||||
|
||||
} // end if;
|
||||
|
||||
} // end foreach;
|
||||
|
||||
} // end if;
|
||||
|
||||
} elseif (!$customer && $slug === 'wu-finish-checkout') {
|
||||
|
||||
if (is_user_logged_in()) {
|
||||
|
||||
$message = __('You need to be the account owner to complete this payment.', 'wp-ultimo');
|
||||
|
||||
} else {
|
||||
|
||||
$message = __('You need to be logged in to complete a payment', 'wp-ultimo');
|
||||
|
||||
// Translators: The link to login url with redirect_to url
|
||||
$message .= '<br>' . sprintf(__('Click <a href="%s">here</a> sign in.', 'wp-ultimo'), wp_login_url(wu_get_current_url()));
|
||||
|
||||
} // end if;
|
||||
|
||||
$message = '<p>' . $message . '</p>';
|
||||
|
||||
/**
|
||||
* Allow developers to change the message
|
||||
*
|
||||
* @param string $message The HTML message to print in screen.
|
||||
*/
|
||||
return apply_filters('wu_checkout_payment_login_error_message', $message);
|
||||
|
||||
} // end if;
|
||||
|
||||
$checkout_form = wu_get_checkout_form_by_slug($slug);
|
||||
|
||||
if (!$checkout_form) {
|
||||
|
||||
// translators: %s is the id of the form. e.g. main-form
|
||||
return sprintf(__('Checkout form %s not found.', 'wp-ultimo'), $slug);
|
||||
|
||||
} // end if;
|
||||
|
||||
if ($checkout_form->get_field_count() === 0) {
|
||||
|
||||
// translators: %s is the id of the form. e.g. main-form
|
||||
return sprintf(__('Checkout form %s contains no fields.', 'wp-ultimo'), $slug);
|
||||
|
||||
}
|
||||
|
||||
if (!$checkout_form->is_active() || !wu_get_setting('enable_registration')) {
|
||||
|
||||
return sprintf('<p>%s</p>', __('Registration is not available at this time.', 'wp-ultimo'));
|
||||
|
||||
} // end if;
|
||||
|
||||
if ($checkout_form->has_country_lock()) {
|
||||
|
||||
$geolocation = \WP_Ultimo\Geolocation::geolocate_ip('', true);
|
||||
|
||||
if (!in_array($geolocation['country'], $checkout_form->get_allowed_countries(), true)) {
|
||||
|
||||
return sprintf('<p>%s</p>', __('Registration is closed for your location.', 'wp-ultimo'));
|
||||
|
||||
} // end if;
|
||||
|
||||
} // end if;
|
||||
|
||||
$checkout = \WP_Ultimo\Checkout\Checkout::get_instance();
|
||||
|
||||
$checkout_form->get_steps_to_show();
|
||||
|
||||
$this->steps = $checkout_form->get_steps_to_show();
|
||||
|
||||
$step = $checkout_form->get_step($atts['step'], true);
|
||||
|
||||
$this->step = $step ? $step : current($this->steps);
|
||||
|
||||
$this->step = wp_parse_args($this->step, array(
|
||||
'classes' => '',
|
||||
'fields' => array(),
|
||||
));
|
||||
|
||||
$this->step_name = $this->step['id'] ?? '';
|
||||
|
||||
/*
|
||||
* Hack-y way to make signup available on the template.
|
||||
*/
|
||||
global $signup;
|
||||
|
||||
$signup = new Mocked_Signup($this->step_name, $this->steps); // phpcs:ignore
|
||||
|
||||
$this->signup = $signup;
|
||||
|
||||
add_action('wp_print_footer_scripts', function() use ($checkout_form) {
|
||||
|
||||
$this->print_custom_css($checkout_form);
|
||||
|
||||
});
|
||||
|
||||
/*
|
||||
* Load the checkout class with the parameters
|
||||
* so we can access them inside the layouts.
|
||||
*/
|
||||
$checkout->checkout_form = $checkout_form;
|
||||
$checkout->steps = $this->steps;
|
||||
$checkout->step = $this->step;
|
||||
$checkout->step_name = $this->step_name;
|
||||
$auto_submittable_field = $checkout->contains_auto_submittable_field($this->step['fields']);
|
||||
|
||||
$final_fields = wu_create_checkout_fields($this->step['fields']);
|
||||
|
||||
/*
|
||||
* Adds the product fields to keep them.
|
||||
*/
|
||||
$final_fields['products[]'] = array(
|
||||
'type' => 'hidden',
|
||||
'html_attr' => array(
|
||||
'v-for' => '(product, index) in unique_products',
|
||||
'v-model' => 'products[index]',
|
||||
'v-bind:id' => '"products-" + index',
|
||||
),
|
||||
);
|
||||
|
||||
$this->inject_inline_auto_submittable_field($auto_submittable_field);
|
||||
|
||||
$final_fields = apply_filters('wu_checkout_form_final_fields', $final_fields, $this);
|
||||
|
||||
return wu_get_template_contents('checkout/form', array(
|
||||
'step' => $this->step,
|
||||
'step_name' => $this->step_name,
|
||||
'checkout_form_name' => $atts['slug'],
|
||||
'errors' => $checkout->errors,
|
||||
'display_title' => $atts['display_title'],
|
||||
'final_fields' => $final_fields,
|
||||
));
|
||||
|
||||
} // end output_form;
|
||||
|
||||
/**
|
||||
* Injects the auto-submittable field inline snippet.
|
||||
*
|
||||
* @since 2.0.11
|
||||
*
|
||||
* @param string $auto_submittable_field The auto-submittable field.
|
||||
* @return void
|
||||
*/
|
||||
public function inject_inline_auto_submittable_field($auto_submittable_field) {
|
||||
|
||||
$callback = function() use ($auto_submittable_field) {
|
||||
|
||||
wp_add_inline_script('wu-checkout', sprintf('
|
||||
|
||||
/**
|
||||
* Set the auto-submittable field, if one exists.
|
||||
*/
|
||||
window.wu_auto_submittable_field = %s;
|
||||
|
||||
', json_encode($auto_submittable_field)), 'after');
|
||||
|
||||
};
|
||||
|
||||
if (wu_is_block_theme() && !is_admin()) {
|
||||
|
||||
add_action('wu_checkout_scripts', $callback, 100);
|
||||
|
||||
} else {
|
||||
|
||||
call_user_func($callback);
|
||||
|
||||
} // end if;
|
||||
|
||||
} // end inject_inline_auto_submittable_field;
|
||||
|
||||
/**
|
||||
* The content to be output on the screen.
|
||||
*
|
||||
* Should return HTML markup to be used to display the block.
|
||||
* This method is shared between the block render method and
|
||||
* the shortcode implementation.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*
|
||||
* @param array $atts Parameters of the block/shortcode.
|
||||
* @param string|null $content The content inside the shortcode.
|
||||
* @return string
|
||||
*/
|
||||
public function output($atts, $content = null) {
|
||||
|
||||
if (wu_is_update_page()) {
|
||||
|
||||
$atts = array(
|
||||
'slug' => apply_filters('wu_membership_update_form', 'wu-checkout'),
|
||||
'step' => false,
|
||||
'display_title' => false,
|
||||
);
|
||||
|
||||
} // end if;
|
||||
|
||||
if (wu_is_new_site_page()) {
|
||||
|
||||
$atts = array(
|
||||
'slug' => apply_filters('wu_membership_new_site_form', 'wu-add-new-site'),
|
||||
'step' => false,
|
||||
'display_title' => false,
|
||||
'membership_limitations' => array('sites'),
|
||||
);
|
||||
|
||||
} // end if;
|
||||
|
||||
if ($this->is_thank_you_page()) {
|
||||
|
||||
return $this->output_thank_you($atts, $content);
|
||||
|
||||
} // end if;
|
||||
|
||||
/**
|
||||
* Allow developers to add new update form slugs.
|
||||
*
|
||||
* @param array $slugs a list of form slugs to bypass.
|
||||
*/
|
||||
$update_forms = apply_filters('wu_membership_update_forms', array(
|
||||
'wu-checkout',
|
||||
));
|
||||
|
||||
if (!in_array($atts['slug'], $update_forms, true) && (wu_request('payment') || wu_request('payment_id'))) {
|
||||
|
||||
$atts = array(
|
||||
'slug' => 'wu-finish-checkout',
|
||||
'step' => false,
|
||||
'display_title' => false,
|
||||
);
|
||||
|
||||
} // end if;
|
||||
|
||||
if (wu_request('wu_form') && in_array(wu_request('wu_form'), $update_forms, true)) {
|
||||
|
||||
$atts = array(
|
||||
'slug' => wu_request('wu_form'),
|
||||
'step' => false,
|
||||
'display_title' => false,
|
||||
);
|
||||
|
||||
} // end if;
|
||||
|
||||
return $this->output_form($atts, $content);
|
||||
|
||||
} // end output;
|
||||
|
||||
} // end class Checkout_Element;
|
||||
|
||||
/**
|
||||
* Replacement of the old WU_Signup class for templates.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
class Mocked_Signup {
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $step;
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
public $steps;
|
||||
/**
|
||||
* Constructs the class.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*
|
||||
* @param string $step Current step.
|
||||
* @param array $steps List of all steps.
|
||||
*/
|
||||
public function __construct($step, $steps)
|
||||
{
|
||||
$this->step = $step;
|
||||
$this->steps = $steps;
|
||||
} // end __construct;
|
||||
|
||||
/**
|
||||
* Get the value of steps.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return mixed
|
||||
*/
|
||||
public function get_steps() {
|
||||
|
||||
return $this->steps;
|
||||
|
||||
} // end get_steps;
|
||||
/**
|
||||
* Deprecated: returns the prev step link.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function get_prev_step_link(): string {
|
||||
|
||||
return '';
|
||||
|
||||
} // end get_prev_step_link;
|
||||
|
||||
} // end class Mocked_Signup;
|
648
inc/ui/class-current-membership-element.php
Normal file
648
inc/ui/class-current-membership-element.php
Normal file
@ -0,0 +1,648 @@
|
||||
<?php
|
||||
/**
|
||||
* Adds the Current_Membership_Element UI to the Admin Panel.
|
||||
*
|
||||
* @package WP_Ultimo
|
||||
* @subpackage UI
|
||||
* @since 2.0.0
|
||||
*/
|
||||
|
||||
namespace WP_Ultimo\UI;
|
||||
|
||||
use \WP_Ultimo\UI\Base_Element;
|
||||
use \WP_Ultimo\Checkout\Cart;
|
||||
|
||||
// Exit if accessed directly
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
/**
|
||||
* Adds the Checkout Element UI to the Admin Panel.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
class Current_Membership_Element extends Base_Element {
|
||||
|
||||
use \WP_Ultimo\Traits\Singleton;
|
||||
|
||||
/**
|
||||
* The id of the element.
|
||||
*
|
||||
* Something simple, without prefixes, like 'checkout', or 'pricing-tables'.
|
||||
*
|
||||
* This is used to construct shortcodes by prefixing the id with 'wu_'
|
||||
* e.g. an id checkout becomes the shortcode 'wu_checkout' and
|
||||
* to generate the Gutenberg block by prefixing it with 'wp-ultimo/'
|
||||
* e.g. checkout would become the block 'wp-ultimo/checkout'.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @var string
|
||||
*/
|
||||
public $id = 'current-membership';
|
||||
|
||||
/**
|
||||
* Controls if this is a public element to be used in pages/shortcodes by user.
|
||||
*
|
||||
* @since 2.0.24
|
||||
* @var boolean
|
||||
*/
|
||||
protected $public = true;
|
||||
|
||||
/**
|
||||
* The current membership.
|
||||
*
|
||||
* @since 2.2.0
|
||||
* @var \WP_Ultimo\Models\Membership
|
||||
*/
|
||||
protected $membership;
|
||||
|
||||
/**
|
||||
* The current plan.
|
||||
*
|
||||
* @since 2.2.0
|
||||
* @var \WP_Ultimo\Models\Product
|
||||
*/
|
||||
protected $plan;
|
||||
|
||||
/**
|
||||
* Overload the init to add site-related forms.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return void
|
||||
*/
|
||||
public function init() {
|
||||
|
||||
parent::init();
|
||||
|
||||
wu_register_form('see_product_details', array(
|
||||
'render' => array($this, 'render_product_details'),
|
||||
'capability' => 'exist',
|
||||
));
|
||||
|
||||
wu_register_form('edit_membership_product_modal', array(
|
||||
'render' => array($this, 'render_edit_membership_product_modal'),
|
||||
'handler' => array($this, 'handle_edit_membership_product_modal'),
|
||||
'capability' => 'exist',
|
||||
));
|
||||
|
||||
} // end init;
|
||||
|
||||
/**
|
||||
* Loads the required scripts.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return void
|
||||
*/
|
||||
public function register_scripts() {
|
||||
|
||||
add_wubox();
|
||||
|
||||
} // end register_scripts;
|
||||
/**
|
||||
* The icon of the UI element.
|
||||
* e.g. return fa fa-search
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @param string $context One of the values: block, elementor or bb.
|
||||
*/
|
||||
public function get_icon($context = 'block'): string {
|
||||
|
||||
if ($context === 'elementor') {
|
||||
|
||||
return 'eicon-info-circle-o';
|
||||
|
||||
} // end if;
|
||||
|
||||
return 'fa fa-search';
|
||||
|
||||
} // end get_icon;
|
||||
|
||||
/**
|
||||
* The title of the UI element.
|
||||
*
|
||||
* This is used on the Blocks list of Gutenberg.
|
||||
* You should return a string with the localized title.
|
||||
* e.g. return __('My Element', 'wp-ultimo').
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return string
|
||||
*/
|
||||
public function get_title() {
|
||||
|
||||
return __('Membership', 'wp-ultimo');
|
||||
|
||||
} // end get_title;
|
||||
|
||||
/**
|
||||
* The description of the UI element.
|
||||
*
|
||||
* This is also used on the Gutenberg block list
|
||||
* to explain what this block is about.
|
||||
* You should return a string with the localized title.
|
||||
* e.g. return __('Adds a checkout form to the page', 'wp-ultimo').
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return string
|
||||
*/
|
||||
public function get_description() {
|
||||
|
||||
return __('Adds a checkout form block to the page.', 'wp-ultimo');
|
||||
|
||||
} // end get_description;
|
||||
|
||||
/**
|
||||
* The list of fields to be added to Gutenberg.
|
||||
*
|
||||
* If you plan to add Gutenberg controls to this block,
|
||||
* you'll need to return an array of fields, following
|
||||
* our fields interface (@see inc/ui/class-field.php).
|
||||
*
|
||||
* You can create new Gutenberg panels by adding fields
|
||||
* with the type 'header'. See the Checkout Elements for reference.
|
||||
*
|
||||
* @see inc/ui/class-checkout-element.php
|
||||
*
|
||||
* Return an empty array if you don't have controls to add.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return array
|
||||
*/
|
||||
public function fields() {
|
||||
|
||||
$fields = array();
|
||||
|
||||
$fields['header'] = array(
|
||||
'title' => __('General', 'wp-ultimo'),
|
||||
'desc' => __('General', 'wp-ultimo'),
|
||||
'type' => 'header',
|
||||
);
|
||||
|
||||
$fields['title'] = array(
|
||||
'type' => 'text',
|
||||
'title' => __('Title', 'wp-ultimo'),
|
||||
'value' => __('Your Membership', 'wp-ultimo'),
|
||||
'desc' => __('Leave blank to hide the title completely.', 'wp-ultimo'),
|
||||
'tooltip' => '',
|
||||
);
|
||||
|
||||
$fields['display_images'] = array(
|
||||
'type' => 'toggle',
|
||||
'title' => __('Display Product Images?', 'wp-ultimo'),
|
||||
'desc' => __('Toggle to show/hide the product images on the element.', 'wp-ultimo'),
|
||||
'tooltip' => '',
|
||||
'value' => 1,
|
||||
);
|
||||
|
||||
$fields['columns'] = array(
|
||||
'type' => 'number',
|
||||
'title' => __('Columns', 'wp-ultimo'),
|
||||
'desc' => __('How many columns to use.', 'wp-ultimo'),
|
||||
'tooltip' => '',
|
||||
'value' => 2,
|
||||
'min' => 1,
|
||||
'max' => 5,
|
||||
);
|
||||
|
||||
return $fields;
|
||||
|
||||
} // end fields;
|
||||
|
||||
/**
|
||||
* The list of keywords for this element.
|
||||
*
|
||||
* Return an array of strings with keywords describing this
|
||||
* element. Gutenberg uses this to help customers find blocks.
|
||||
*
|
||||
* e.g.:
|
||||
* return array(
|
||||
* 'WP Ultimo',
|
||||
* 'Membership',
|
||||
* 'Form',
|
||||
* 'Cart',
|
||||
* );
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return array
|
||||
*/
|
||||
public function keywords() {
|
||||
|
||||
return array(
|
||||
'WP Ultimo',
|
||||
'Membership',
|
||||
'Form',
|
||||
'Cart',
|
||||
);
|
||||
|
||||
} // end keywords;
|
||||
|
||||
/**
|
||||
* List of default parameters for the element.
|
||||
*
|
||||
* If you are planning to add controls using the fields,
|
||||
* it might be a good idea to use this method to set defaults
|
||||
* for the parameters you are expecting.
|
||||
*
|
||||
* These defaults will be used inside a 'wp_parse_args' call
|
||||
* before passing the parameters down to the block render
|
||||
* function and the shortcode render function.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return array
|
||||
*/
|
||||
public function defaults() {
|
||||
|
||||
return array(
|
||||
'title' => __('Your Membership', 'wp-ultimo'),
|
||||
'display_images' => 1,
|
||||
'columns' => 2,
|
||||
);
|
||||
|
||||
} // end defaults;
|
||||
|
||||
/**
|
||||
* Runs early on the request lifecycle as soon as we detect the shortcode is present.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return void
|
||||
*/
|
||||
public function setup() {
|
||||
|
||||
$this->membership = WP_Ultimo()->currents->get_membership();
|
||||
|
||||
if (!$this->membership) {
|
||||
|
||||
$this->set_display(false);
|
||||
|
||||
return;
|
||||
|
||||
} // end if;
|
||||
|
||||
$this->plan = $this->membership ? $this->membership->get_plan() : false;
|
||||
|
||||
} // end setup;
|
||||
|
||||
/**
|
||||
* Allows the setup in the context of previews.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return void
|
||||
*/
|
||||
public function setup_preview() {
|
||||
|
||||
$this->membership = wu_mock_membership();
|
||||
|
||||
$this->plan = wu_mock_product();
|
||||
|
||||
} // end setup_preview;
|
||||
|
||||
/**
|
||||
* The content to be output on the screen.
|
||||
*
|
||||
* Should return HTML markup to be used to display the block.
|
||||
* This method is shared between the block render method and
|
||||
* the shortcode implementation.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*
|
||||
* @param array $atts Parameters of the block/shortcode.
|
||||
* @param string|null $content The content inside the shortcode.
|
||||
* @return string
|
||||
*/
|
||||
public function output($atts, $content = null) {
|
||||
|
||||
$atts['membership'] = $this->membership;
|
||||
$atts['plan'] = $this->plan;
|
||||
$atts['element'] = $this;
|
||||
|
||||
$atts['pending_change'] = false;
|
||||
|
||||
if ($this->membership) {
|
||||
|
||||
$pending_swap_order = $this->membership->get_scheduled_swap();
|
||||
|
||||
$atts['pending_products'] = false;
|
||||
|
||||
if ($pending_swap_order) {
|
||||
|
||||
$atts['pending_change'] = $pending_swap_order->order->get_cart_descriptor();
|
||||
$atts['pending_change_date'] = wu_date($pending_swap_order->scheduled_date)->format(get_option('date_format'));
|
||||
|
||||
$swap_membership = (clone $this->membership)->swap($pending_swap_order->order);
|
||||
|
||||
$pending_products = array_map(fn($product) => array(
|
||||
'id' => $product['product']->get_id(),
|
||||
'quantity' => $product['quantity'],
|
||||
), $swap_membership->get_all_products());
|
||||
|
||||
// add the id as key
|
||||
$atts['pending_products'] = array_combine(array_column($pending_products, 'id'), $pending_products);
|
||||
|
||||
} // end if;
|
||||
|
||||
return wu_get_template_contents('dashboard-widgets/current-membership', $atts);
|
||||
|
||||
} // end if;
|
||||
|
||||
return '';
|
||||
|
||||
} // end output;
|
||||
|
||||
/**
|
||||
* Renders the product details modal window.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return void
|
||||
*/
|
||||
public function render_product_details() {
|
||||
|
||||
$product = wu_get_product_by_slug(wu_request('product'));
|
||||
|
||||
if (!$product) {
|
||||
|
||||
return;
|
||||
|
||||
} // end if;
|
||||
|
||||
$atts['product'] = $product;
|
||||
|
||||
wu_get_template('dashboard-widgets/current-membership-product-details', $atts);
|
||||
|
||||
} // end render_product_details;
|
||||
|
||||
/**
|
||||
* Renders the add/edit line items form.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return void
|
||||
*/
|
||||
public function render_edit_membership_product_modal() {
|
||||
|
||||
$membership = wu_get_membership_by_hash(wu_request('membership'));
|
||||
|
||||
$error = '';
|
||||
|
||||
if (!$membership) {
|
||||
|
||||
$error = __('Membership not selected.', 'wp-ultimo');
|
||||
|
||||
} // end if;
|
||||
|
||||
$product = wu_get_product_by_slug(wu_request('product'));
|
||||
|
||||
if (!$product) {
|
||||
|
||||
$error = __('Product not selected.', 'wp-ultimo');
|
||||
|
||||
} // end if;
|
||||
|
||||
$customer = wu_get_current_customer();
|
||||
|
||||
if (empty($error) && !is_super_admin() && (!$customer || $customer->get_id() !== $membership->get_customer_id())) {
|
||||
|
||||
$error = __('You are not allowed to do this.', 'wp-ultimo');
|
||||
|
||||
} // end if;
|
||||
|
||||
if (!empty($error)) {
|
||||
|
||||
$error_field = array(
|
||||
'error_message' => array(
|
||||
'type' => 'note',
|
||||
'desc' => $error,
|
||||
),
|
||||
);
|
||||
|
||||
$form = new \WP_Ultimo\UI\Form('cancel_payment_method', $error_field, array(
|
||||
'views' => 'admin-pages/fields',
|
||||
'classes' => 'wu-modal-form wu-widget-list wu-striped wu-m-0 wu-mt-0',
|
||||
'field_wrapper_classes' => 'wu-w-full wu-box-border wu-items-center wu-flex wu-justify-between wu-p-4 wu-m-0 wu-border-t wu-border-l-0 wu-border-r-0 wu-border-b-0 wu-border-gray-300 wu-border-solid',
|
||||
));
|
||||
|
||||
$form->render();
|
||||
|
||||
return;
|
||||
|
||||
} // end if;
|
||||
|
||||
/**
|
||||
* If there is a scheduled swap, we need to swap the membership before
|
||||
* removing the product to ensure the full change for next billing cycle.
|
||||
*/
|
||||
$existing_swap = $membership->get_scheduled_swap();
|
||||
|
||||
if ($existing_swap) {
|
||||
|
||||
$membership = $membership->swap($existing_swap->order);
|
||||
|
||||
} // end if;
|
||||
|
||||
$gateway_message = false;
|
||||
|
||||
if (!empty($membership->get_gateway())) {
|
||||
|
||||
$gateway = wu_get_gateway($membership->get_gateway());
|
||||
|
||||
$gateway_message = $gateway ? $gateway->get_amount_update_message(true) : '';
|
||||
|
||||
} // end if;
|
||||
|
||||
$existing_quantity = array_filter($membership->get_addon_products(), fn($item) => $item['product']->get_id() === $product->get_id())[0]['quantity'];
|
||||
|
||||
$fields = array(
|
||||
'membership' => array(
|
||||
'type' => 'hidden',
|
||||
'value' => wu_request('membership'),
|
||||
),
|
||||
'product' => array(
|
||||
'type' => 'hidden',
|
||||
'value' => wu_request('product'),
|
||||
),
|
||||
'quantity' => array(
|
||||
'type' => 'number',
|
||||
'title' => __('Quantity to Cancel', 'wp-ultimo'),
|
||||
'value' => 1,
|
||||
'placeholder' => 1,
|
||||
'wrapper_classes' => 'wu-w-1/2',
|
||||
'html_attr' => array(
|
||||
'min' => 1,
|
||||
'max' => $existing_quantity,
|
||||
'required' => 'required',
|
||||
),
|
||||
'wrapper_html_attr' => array(
|
||||
'v-show' => $existing_quantity > 1 ? 'true' : 'false',
|
||||
'v-cloak' => '1',
|
||||
),
|
||||
),
|
||||
'confirm' => array(
|
||||
'type' => 'toggle',
|
||||
'title' => __('Confirm Product Cancellation', 'wp-ultimo'),
|
||||
'desc' => __('This action can not be undone.', 'wp-ultimo'),
|
||||
'html_attr' => array(
|
||||
'v-model' => 'confirmed',
|
||||
),
|
||||
),
|
||||
'update_note' => array(
|
||||
'type' => 'note',
|
||||
'desc' => $gateway_message,
|
||||
'classes' => 'sm:wu-p-2 wu-bg-red-100 wu-text-red-600 wu-rounded wu-w-full',
|
||||
),
|
||||
'submit_button' => array(
|
||||
'type' => 'submit',
|
||||
'title' => __('Cancel Product Subscription', 'wp-ultimo'),
|
||||
'placeholder' => __('Cancel Product Subscription', 'wp-ultimo'),
|
||||
'value' => 'save',
|
||||
'classes' => 'wu-w-full button button-primary',
|
||||
'wrapper_classes' => 'wu-items-end',
|
||||
'html_attr' => array(
|
||||
'v-bind:disabled' => '!confirmed',
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
if (!$gateway_message) {
|
||||
|
||||
unset($fields['update_note']);
|
||||
|
||||
} // end if;
|
||||
|
||||
$form = new \WP_Ultimo\UI\Form('edit_membership_product', $fields, array(
|
||||
'views' => 'admin-pages/fields',
|
||||
'classes' => 'wu-modal-form wu-widget-list wu-striped wu-m-0 wu-mt-0',
|
||||
'field_wrapper_classes' => 'wu-w-full wu-box-border wu-items-center wu-flex wu-justify-between wu-p-4 wu-m-0 wu-border-t wu-border-l-0 wu-border-r-0 wu-border-b-0 wu-border-gray-300 wu-border-solid',
|
||||
'html_attr' => array(
|
||||
'data-wu-app' => 'edit_membership_product',
|
||||
'data-state' => wu_convert_to_state(array(
|
||||
'confirmed' => false,
|
||||
)),
|
||||
),
|
||||
));
|
||||
|
||||
$form->render();
|
||||
|
||||
} // end render_edit_membership_product_modal;
|
||||
|
||||
/**
|
||||
* Handles the membership product remove.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return void
|
||||
*/
|
||||
public function handle_edit_membership_product_modal() {
|
||||
|
||||
if (!wu_request('confirm')) {
|
||||
|
||||
$error = new \WP_Error('not-confirmed', __('Please confirm the cancellation.', 'wp-ultimo'));
|
||||
|
||||
wp_send_json_error($error);
|
||||
|
||||
} // end if;
|
||||
|
||||
$membership = wu_get_membership_by_hash(wu_request('membership'));
|
||||
|
||||
if (!$membership) {
|
||||
|
||||
$error = new \WP_Error('membership-not-found', __('Membership not found.', 'wp-ultimo'));
|
||||
|
||||
wp_send_json_error($error);
|
||||
|
||||
} // end if;
|
||||
|
||||
$product = wu_get_product_by_slug(wu_request('product'));
|
||||
|
||||
if (!$product) {
|
||||
|
||||
$error = new \WP_Error('product-not-found', __('Product not found.', 'wp-ultimo'));
|
||||
|
||||
wp_send_json_error($error);
|
||||
|
||||
} // end if;
|
||||
|
||||
$customer = wu_get_current_customer();
|
||||
|
||||
if (!is_super_admin() && (!$customer || $customer->get_id() !== $membership->get_customer_id())) {
|
||||
|
||||
$error = __('You are not allowed to do this.', 'wp-ultimo');
|
||||
|
||||
wp_send_json_error($error);
|
||||
|
||||
} // end if;
|
||||
|
||||
// Get the existing quantity by filtering the products array.
|
||||
$existing_quantity = array_filter($membership->get_addon_products(), fn($item) => $item['product']->get_id() === $product->get_id())[0]['quantity'];
|
||||
|
||||
$original_quantity = $existing_quantity;
|
||||
|
||||
/**
|
||||
* If there is a scheduled swap, we need to swap the membership before
|
||||
* removing the product to ensure the full change for next billing cycle.
|
||||
*/
|
||||
$existing_swap = $membership->get_scheduled_swap();
|
||||
|
||||
if ($existing_swap) {
|
||||
|
||||
$membership = $membership->swap($existing_swap->order);
|
||||
|
||||
$existing_quantity = array_filter($membership->get_addon_products(), fn($item) => $item['product']->get_id() === $product->get_id())[0]['quantity'];
|
||||
|
||||
} // end if;
|
||||
|
||||
$quantity = (int) wu_request('quantity', 1);
|
||||
$quantity = $quantity > $existing_quantity ? $existing_quantity : $quantity;
|
||||
|
||||
$membership->remove_product($product->get_id(), $quantity);
|
||||
|
||||
$value_to_remove = wu_get_membership_product_price($membership, $product->get_id(), $quantity);
|
||||
|
||||
if (is_wp_error($value_to_remove)) {
|
||||
|
||||
wp_send_json_error($value_to_remove);
|
||||
|
||||
} // end if;
|
||||
|
||||
$plan_price = wu_get_membership_product_price($membership, $membership->get_plan()->get_id(), 1);
|
||||
|
||||
// do not allow remove more than the plan price
|
||||
if ($plan_price < $value_to_remove) {
|
||||
|
||||
$value_to_remove = $membership->get_amount() - $plan_price;
|
||||
$value_to_remove = $value_to_remove < 0 ? 0 : $value_to_remove;
|
||||
|
||||
} // end if;
|
||||
|
||||
$membership->set_amount($membership->get_amount() - $value_to_remove);
|
||||
|
||||
$cart = wu_get_membership_new_cart($membership);
|
||||
|
||||
$existing_difference = $original_quantity - $existing_quantity;
|
||||
|
||||
$removed_quantity = $quantity + $existing_difference;
|
||||
|
||||
// translators: %1$s is the quantity removed, %2$s is the product name.
|
||||
$description = sprintf(__('remove %1$s %2$s from membership', 'wp-ultimo'), $removed_quantity, $product->get_name());
|
||||
|
||||
$cart->set_cart_descriptor($description);
|
||||
|
||||
$schedule_swap = $membership->schedule_swap($cart);
|
||||
|
||||
// Lets schedule this change as the customer already paid for this period.
|
||||
if (is_wp_error($schedule_swap)) {
|
||||
|
||||
wp_send_json_error($schedule_swap);
|
||||
|
||||
} // end if;
|
||||
|
||||
// Now we trigger the gateway update so the customer is charged for the new amount.
|
||||
$gateway = wu_get_gateway($membership->get_gateway());
|
||||
|
||||
if ($gateway) {
|
||||
|
||||
$gateway->process_membership_update($membership, $customer);
|
||||
|
||||
} // end if;
|
||||
|
||||
wp_send_json_success(array(
|
||||
'redirect_url' => add_query_arg('updated', 1, $_SERVER['HTTP_REFERER']),
|
||||
));
|
||||
|
||||
} // end handle_edit_membership_product_modal;
|
||||
|
||||
} // end class Current_Membership_Element;
|
516
inc/ui/class-current-site-element.php
Normal file
516
inc/ui/class-current-site-element.php
Normal file
@ -0,0 +1,516 @@
|
||||
<?php
|
||||
/**
|
||||
* Adds the Current_Site_Element UI to the Admin Panel.
|
||||
*
|
||||
* @package WP_Ultimo
|
||||
* @subpackage UI
|
||||
* @since 2.0.0
|
||||
*/
|
||||
|
||||
namespace WP_Ultimo\UI;
|
||||
|
||||
use WP_Ultimo\UI\Base_Element;
|
||||
|
||||
// Exit if accessed directly
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
/**
|
||||
* Adds the Checkout Element UI to the Admin Panel.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
class Current_Site_Element extends Base_Element {
|
||||
|
||||
use \WP_Ultimo\Traits\Singleton;
|
||||
|
||||
/**
|
||||
* The id of the element.
|
||||
*
|
||||
* Something simple, without prefixes, like 'checkout', or 'pricing-tables'.
|
||||
*
|
||||
* This is used to construct shortcodes by prefixing the id with 'wu_'
|
||||
* e.g. an id checkout becomes the shortcode 'wu_checkout' and
|
||||
* to generate the Gutenberg block by prefixing it with 'wp-ultimo/'
|
||||
* e.g. checkout would become the block 'wp-ultimo/checkout'.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @var string
|
||||
*/
|
||||
public $id = 'current-site';
|
||||
|
||||
/**
|
||||
* Controls if this is a public element to be used in pages/shortcodes by user.
|
||||
*
|
||||
* @since 2.0.24
|
||||
* @var boolean
|
||||
*/
|
||||
protected $public = true;
|
||||
|
||||
/**
|
||||
* The site being managed.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @var null|\WP_Ultimo\Models\Site
|
||||
*/
|
||||
public $site;
|
||||
|
||||
/**
|
||||
* The membership being managed.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @var null|\WP_Ultimo\Models\Membership
|
||||
*/
|
||||
public $membership;
|
||||
|
||||
/**
|
||||
* The icon of the UI element.
|
||||
* e.g. return fa fa-search
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @param string $context One of the values: block, elementor or bb.
|
||||
*/
|
||||
public function get_icon($context = 'block'): string {
|
||||
|
||||
if ($context === 'elementor') {
|
||||
|
||||
return 'eicon-info-circle-o';
|
||||
|
||||
} // end if;
|
||||
|
||||
return 'fa fa-search';
|
||||
|
||||
} // end get_icon;
|
||||
|
||||
/**
|
||||
* Overload the init to add site-related forms.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return void
|
||||
*/
|
||||
public function init() {
|
||||
|
||||
parent::init();
|
||||
|
||||
wu_register_form('edit_site', array(
|
||||
'render' => array($this, 'render_edit_site'),
|
||||
'handler' => array($this, 'handle_edit_site'),
|
||||
'capability' => 'exist',
|
||||
));
|
||||
|
||||
} // end init;
|
||||
|
||||
/**
|
||||
* The title of the UI element.
|
||||
*
|
||||
* This is used on the Blocks list of Gutenberg.
|
||||
* You should return a string with the localized title.
|
||||
* e.g. return __('My Element', 'wp-ultimo').
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return string
|
||||
*/
|
||||
public function get_title() {
|
||||
|
||||
return __('Site', 'wp-ultimo');
|
||||
|
||||
} // end get_title;
|
||||
|
||||
/**
|
||||
* The description of the UI element.
|
||||
*
|
||||
* This is also used on the Gutenberg block list
|
||||
* to explain what this block is about.
|
||||
* You should return a string with the localized title.
|
||||
* e.g. return __('Adds a checkout form to the page', 'wp-ultimo').
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return string
|
||||
*/
|
||||
public function get_description() {
|
||||
|
||||
return __('Adds a block to display the current site being managed.', 'wp-ultimo');
|
||||
|
||||
} // end get_description;
|
||||
|
||||
/**
|
||||
* The list of fields to be added to Gutenberg.
|
||||
*
|
||||
* If you plan to add Gutenberg controls to this block,
|
||||
* you'll need to return an array of fields, following
|
||||
* our fields interface (@see inc/ui/class-field.php).
|
||||
*
|
||||
* You can create new Gutenberg panels by adding fields
|
||||
* with the type 'header'. See the Checkout Elements for reference.
|
||||
*
|
||||
* @see inc/ui/class-checkout-element.php
|
||||
*
|
||||
* Return an empty array if you don't have controls to add.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return array
|
||||
*/
|
||||
public function fields() {
|
||||
|
||||
$fields = array();
|
||||
|
||||
$fields['header'] = array(
|
||||
'title' => __('General', 'wp-ultimo'),
|
||||
'desc' => __('General', 'wp-ultimo'),
|
||||
'type' => 'header',
|
||||
);
|
||||
|
||||
$fields['display_breadcrumbs'] = array(
|
||||
'type' => 'toggle',
|
||||
'title' => __('Display Breadcrumbs?', 'wp-ultimo'),
|
||||
'desc' => __('Toggle to show/hide the breadcrumbs block.', 'wp-ultimo'),
|
||||
'tooltip' => '',
|
||||
'value' => 1,
|
||||
);
|
||||
|
||||
$pages = get_pages(array(
|
||||
'exclude' => array(get_the_ID()),
|
||||
));
|
||||
|
||||
$pages = $pages ? $pages : array();
|
||||
|
||||
$pages_list = array(0 => __('Current Page', 'wp-ultimo'));
|
||||
|
||||
foreach ($pages as $page) {
|
||||
|
||||
$pages_list[$page->ID] = $page->post_title;
|
||||
|
||||
} // end foreach;
|
||||
|
||||
$fields['breadcrumbs_my_sites_page'] = array(
|
||||
'type' => 'select',
|
||||
'title' => __('My Sites Page', 'wp-ultimo'),
|
||||
'value' => 0,
|
||||
'desc' => __('The page with the customer sites list.', 'wp-ultimo'),
|
||||
'options' => $pages_list,
|
||||
);
|
||||
|
||||
$fields['display_description'] = array(
|
||||
'type' => 'toggle',
|
||||
'title' => __('Display Site Description?', 'wp-ultimo'),
|
||||
'desc' => __('Toggle to show/hide the site description on the element.', 'wp-ultimo'),
|
||||
'tooltip' => '',
|
||||
'value' => 0,
|
||||
);
|
||||
|
||||
$fields['display_image'] = array(
|
||||
'type' => 'toggle',
|
||||
'title' => __('Display Site Screenshot?', 'wp-ultimo'),
|
||||
'desc' => __('Toggle to show/hide the site screenshots on the element.', 'wp-ultimo'),
|
||||
'tooltip' => '',
|
||||
'value' => 1,
|
||||
);
|
||||
|
||||
$fields['screenshot_size'] = array(
|
||||
'type' => 'number',
|
||||
'title' => __('Screenshot Size', 'wp-ultimo'),
|
||||
'desc' => '',
|
||||
'tooltip' => '',
|
||||
'value' => 200,
|
||||
'min' => 100,
|
||||
'max' => 400,
|
||||
'required' => array(
|
||||
'display_image' => 1,
|
||||
),
|
||||
);
|
||||
|
||||
$fields['screenshot_position'] = array(
|
||||
'type' => 'select',
|
||||
'title' => __('Screenshot Position', 'wp-ultimo'),
|
||||
'options' => array(
|
||||
'right' => __('Right', 'wp-ultimo'),
|
||||
'left' => __('Left', 'wp-ultimo'),
|
||||
),
|
||||
'desc' => '',
|
||||
'tooltip' => '',
|
||||
'value' => 'right',
|
||||
'required' => array(
|
||||
'display_image' => 1,
|
||||
),
|
||||
);
|
||||
|
||||
$fields['show_admin_link'] = array(
|
||||
'type' => 'toggle',
|
||||
'title' => __('Show Admin Link?', 'wp-ultimo'),
|
||||
'desc' => __('Toggle to show/hide the WP admin link on the element.', 'wp-ultimo'),
|
||||
'tooltip' => '',
|
||||
'value' => 1,
|
||||
);
|
||||
|
||||
return $fields;
|
||||
|
||||
} // end fields;
|
||||
|
||||
/**
|
||||
* The list of keywords for this element.
|
||||
*
|
||||
* Return an array of strings with keywords describing this
|
||||
* element. Gutenberg uses this to help customers find blocks.
|
||||
*
|
||||
* e.g.:
|
||||
* return array(
|
||||
* 'WP Ultimo',
|
||||
* 'Site',
|
||||
* 'Form',
|
||||
* 'Cart',
|
||||
* );
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return array
|
||||
*/
|
||||
public function keywords() {
|
||||
|
||||
return array(
|
||||
'WP Ultimo',
|
||||
'Site',
|
||||
'Form',
|
||||
'Cart',
|
||||
);
|
||||
|
||||
} // end keywords;
|
||||
|
||||
/**
|
||||
* List of default parameters for the element.
|
||||
*
|
||||
* If you are planning to add controls using the fields,
|
||||
* it might be a good idea to use this method to set defaults
|
||||
* for the parameters you are expecting.
|
||||
*
|
||||
* These defaults will be used inside a 'wp_parse_args' call
|
||||
* before passing the parameters down to the block render
|
||||
* function and the shortcode render function.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return array
|
||||
*/
|
||||
public function defaults() {
|
||||
|
||||
return array(
|
||||
'display_image' => 1,
|
||||
'display_breadcrumbs' => 1,
|
||||
'display_description' => 0,
|
||||
'screenshot_size' => 200,
|
||||
'screenshot_position' => 'right',
|
||||
'breadcrumbs_my_sites_page' => 0,
|
||||
'show_admin_link' => 1,
|
||||
);
|
||||
|
||||
} // end defaults;
|
||||
|
||||
/**
|
||||
* Runs early on the request lifecycle as soon as we detect the shortcode is present.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return void
|
||||
*/
|
||||
public function setup() {
|
||||
|
||||
$this->site = WP_Ultimo()->currents->get_site();
|
||||
|
||||
if (!$this->site || !$this->site->is_customer_allowed()) {
|
||||
|
||||
$this->set_display(false);
|
||||
|
||||
return;
|
||||
|
||||
} // end if;
|
||||
|
||||
$this->membership = $this->site->get_membership();
|
||||
|
||||
} // end setup;
|
||||
|
||||
/**
|
||||
* Allows the setup in the context of previews.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return void
|
||||
*/
|
||||
public function setup_preview() {
|
||||
|
||||
$this->site = wu_mock_site();
|
||||
|
||||
$this->membership = wu_mock_membership();
|
||||
|
||||
} // end setup_preview;
|
||||
|
||||
/**
|
||||
* Loads the required scripts.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return void
|
||||
*/
|
||||
public function register_scripts() {
|
||||
|
||||
add_wubox();
|
||||
|
||||
} // end register_scripts;
|
||||
|
||||
/**
|
||||
* The content to be output on the screen.
|
||||
*
|
||||
* Should return HTML markup to be used to display the block.
|
||||
* This method is shared between the block render method and
|
||||
* the shortcode implementation.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*
|
||||
* @param array $atts Parameters of the block/shortcode.
|
||||
* @param string|null $content The content inside the shortcode.
|
||||
* @return string
|
||||
*/
|
||||
public function output($atts, $content = null) {
|
||||
|
||||
$actions = array(
|
||||
'visit_site' => array(
|
||||
'label' => __('Visit Site', 'wp-ultimo'),
|
||||
'icon_classes' => 'dashicons-wu-browser wu-align-text-bottom',
|
||||
'classes' => '',
|
||||
'href' => $this->site->get_active_site_url(),
|
||||
),
|
||||
'edit_site' => array(
|
||||
'label' => __('Edit Site', 'wp-ultimo'),
|
||||
'icon_classes' => 'dashicons-wu-edit wu-align-text-bottom',
|
||||
'classes' => 'wubox',
|
||||
'href' => wu_get_form_url('edit_site', array(
|
||||
'site' => $this->site->get_hash(),
|
||||
)),
|
||||
),
|
||||
);
|
||||
|
||||
if ($atts['show_admin_link']) {
|
||||
|
||||
$actions['site_admin'] = array(
|
||||
'label' => __('Admin Panel', 'wp-ultimo'),
|
||||
'icon_classes' => 'dashicons-wu-grid wu-align-text-bottom',
|
||||
'classes' => '',
|
||||
'href' => get_admin_url($this->site->get_id()),
|
||||
);
|
||||
|
||||
} // end if;
|
||||
|
||||
$atts['actions'] = apply_filters('wu_current_site_actions', $actions, $this->site);
|
||||
|
||||
$atts['current_site'] = $this->site;
|
||||
|
||||
$my_sites_id = $atts['breadcrumbs_my_sites_page'];
|
||||
|
||||
$my_sites_url = empty($my_sites_id) ? remove_query_arg('site') : get_page_link($my_sites_id);
|
||||
|
||||
$atts['my_sites_url'] = is_admin() ? admin_url('admin.php?page=sites') : $my_sites_url;
|
||||
|
||||
return wu_get_template_contents('dashboard-widgets/current-site', $atts);
|
||||
|
||||
} // end output;
|
||||
|
||||
/**
|
||||
* Renders the edit site modal.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return string
|
||||
*/
|
||||
public function render_edit_site() {
|
||||
|
||||
$site = wu_get_site_by_hash(wu_request('site'));
|
||||
|
||||
if (!$site) {
|
||||
|
||||
return '';
|
||||
|
||||
} // end if;
|
||||
|
||||
$fields = array(
|
||||
'site_title' => array(
|
||||
'type' => 'text',
|
||||
'title' => __('Site Title', 'wp-ultimo'),
|
||||
'placeholder' => __('e.g. My Awesome Site', 'wp-ultimo'),
|
||||
'value' => $site->get_title(),
|
||||
'html_attr' => array(
|
||||
'v-model' => 'site_title',
|
||||
),
|
||||
),
|
||||
'site_description' => array(
|
||||
'type' => 'textarea',
|
||||
'title' => __('Site Description', 'wp-ultimo'),
|
||||
'placeholder' => __('e.g. My Awesome Site description.', 'wp-ultimo'),
|
||||
'value' => $site->get_description(),
|
||||
'html_attr' => array(
|
||||
'rows' => 5,
|
||||
),
|
||||
),
|
||||
'site' => array(
|
||||
'type' => 'hidden',
|
||||
'value' => wu_request('site'),
|
||||
),
|
||||
'submit_button' => array(
|
||||
'type' => 'submit',
|
||||
'title' => __('Save Changes', 'wp-ultimo'),
|
||||
'value' => 'save',
|
||||
'classes' => 'button button-primary wu-w-full',
|
||||
'wrapper_classes' => 'wu-items-end',
|
||||
'html_attr' => array(
|
||||
'v-bind:disabled' => '!site_title.length',
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
$fields = apply_filters('wu_form_edit_site', $fields, $this);
|
||||
|
||||
$form = new \WP_Ultimo\UI\Form('edit_site', $fields, array(
|
||||
'views' => 'admin-pages/fields',
|
||||
'classes' => 'wu-modal-form wu-widget-list wu-striped wu-m-0 wu-mt-0',
|
||||
'field_wrapper_classes' => 'wu-w-full wu-box-border wu-items-center wu-flex wu-justify-between wu-p-4 wu-m-0 wu-border-t wu-border-l-0 wu-border-r-0 wu-border-b-0 wu-border-gray-300 wu-border-solid',
|
||||
'html_attr' => array(
|
||||
'data-wu-app' => 'edit_site',
|
||||
'data-state' => wu_convert_to_state(array(
|
||||
'site_title' => $site->get_title(),
|
||||
)),
|
||||
),
|
||||
));
|
||||
|
||||
$form->render();
|
||||
|
||||
} // end render_edit_site;
|
||||
|
||||
/**
|
||||
* Handles the password reset form.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return void
|
||||
*/
|
||||
public function handle_edit_site() {
|
||||
|
||||
$site = wu_get_site_by_hash(wu_request('site'));
|
||||
|
||||
if (!$site) {
|
||||
|
||||
$error = new \WP_Error('site-dont-exist', __('Something went wrong.', 'wp-ultimo'));
|
||||
|
||||
wp_send_json_error($error);
|
||||
|
||||
} // end if;
|
||||
|
||||
$new_title = wu_request('site_title');
|
||||
|
||||
if (!$new_title) {
|
||||
|
||||
$error = new \WP_Error('title_empty', __('Site title can not be empty.', 'wp-ultimo'));
|
||||
|
||||
wp_send_json_error($error);
|
||||
|
||||
} // end if;
|
||||
|
||||
$status = update_blog_option($site->get_id(), 'blogname', $new_title);
|
||||
|
||||
$status_desc = update_blog_option($site->get_id(), 'blogdescription', wu_request('site_description'));
|
||||
|
||||
wp_send_json_success(array(
|
||||
'redirect_url' => add_query_arg('updated', (int) $status, $_SERVER['HTTP_REFERER']),
|
||||
));
|
||||
|
||||
} // end handle_edit_site;
|
||||
|
||||
} // end class Current_Site_Element;
|
768
inc/ui/class-domain-mapping-element.php
Normal file
768
inc/ui/class-domain-mapping-element.php
Normal file
@ -0,0 +1,768 @@
|
||||
<?php
|
||||
/**
|
||||
* Adds the Domain Mapping Element UI to the Admin Panel.
|
||||
*
|
||||
* @package WP_Ultimo
|
||||
* @subpackage UI
|
||||
* @since 2.0.0
|
||||
*/
|
||||
|
||||
namespace WP_Ultimo\UI;
|
||||
|
||||
use \WP_Ultimo\UI\Base_Element;
|
||||
use \WP_Ultimo\Models\Domain;
|
||||
use \WP_Ultimo\Database\Domains\Domain_Stage;
|
||||
use \WP_Ultimo\Models\Site;
|
||||
use \WP_Ultimo\Models\Membership;
|
||||
|
||||
// Exit if accessed directly
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
/**
|
||||
* Adds the Checkout Element UI to the Admin Panel.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
class Domain_Mapping_Element extends Base_Element {
|
||||
|
||||
use \WP_Ultimo\Traits\Singleton;
|
||||
|
||||
/**
|
||||
* The id of the element.
|
||||
*
|
||||
* Something simple, without prefixes, like 'checkout', or 'pricing-tables'.
|
||||
*
|
||||
* This is used to construct shortcodes by prefixing the id with 'wu_'
|
||||
* e.g. an id checkout becomes the shortcode 'wu_checkout' and
|
||||
* to generate the Gutenberg block by prefixing it with 'wp-ultimo/'
|
||||
* e.g. checkout would become the block 'wp-ultimo/checkout'.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @var string
|
||||
*/
|
||||
public $id = 'domain-mapping';
|
||||
|
||||
/**
|
||||
* Controls if this is a public element to be used in pages/shortcodes by user.
|
||||
*
|
||||
* @since 2.0.24
|
||||
* @var boolean
|
||||
*/
|
||||
protected $public = true;
|
||||
|
||||
/**
|
||||
* The current site.
|
||||
*
|
||||
* @since 2.2.0
|
||||
* @var Site
|
||||
*/
|
||||
protected $site;
|
||||
|
||||
/**
|
||||
* The current membership.
|
||||
*
|
||||
* @since 2.2.0
|
||||
* @var Membership
|
||||
*/
|
||||
protected $membership;
|
||||
|
||||
/**
|
||||
* The icon of the UI element.
|
||||
* e.g. return fa fa-search
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @param string $context One of the values: block, elementor or bb.
|
||||
*/
|
||||
public function get_icon($context = 'block'): string {
|
||||
|
||||
if ($context === 'elementor') {
|
||||
|
||||
return 'eicon-url';
|
||||
|
||||
} // end if;
|
||||
|
||||
return 'fa fa-search';
|
||||
|
||||
} // end get_icon;
|
||||
|
||||
/**
|
||||
* The title of the UI element.
|
||||
*
|
||||
* This is used on the Blocks list of Gutenberg.
|
||||
* You should return a string with the localized title.
|
||||
* e.g. return __('My Element', 'wp-ultimo').
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return string
|
||||
*/
|
||||
public function get_title() {
|
||||
|
||||
return __('Domains', 'wp-ultimo');
|
||||
|
||||
} // end get_title;
|
||||
|
||||
/**
|
||||
* The description of the UI element.
|
||||
*
|
||||
* This is also used on the Gutenberg block list
|
||||
* to explain what this block is about.
|
||||
* You should return a string with the localized title.
|
||||
* e.g. return __('Adds a checkout form to the page', 'wp-ultimo').
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return string
|
||||
*/
|
||||
public function get_description() {
|
||||
|
||||
return __('Adds the site\'s domains block.', 'wp-ultimo');
|
||||
|
||||
} // end get_description;
|
||||
|
||||
/**
|
||||
* The list of fields to be added to Gutenberg.
|
||||
*
|
||||
* If you plan to add Gutenberg controls to this block,
|
||||
* you'll need to return an array of fields, following
|
||||
* our fields interface (@see inc/ui/class-field.php).
|
||||
*
|
||||
* You can create new Gutenberg panels by adding fields
|
||||
* with the type 'header'. See the Checkout Elements for reference.
|
||||
*
|
||||
* @see inc/ui/class-checkout-element.php
|
||||
*
|
||||
* Return an empty array if you don't have controls to add.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return array
|
||||
*/
|
||||
public function fields() {
|
||||
|
||||
$fields = array();
|
||||
|
||||
$fields['header'] = array(
|
||||
'title' => __('General', 'wp-ultimo'),
|
||||
'desc' => __('General', 'wp-ultimo'),
|
||||
'type' => 'header',
|
||||
);
|
||||
|
||||
$fields['title'] = array(
|
||||
'type' => 'text',
|
||||
'title' => __('Title', 'wp-ultimo'),
|
||||
'value' => __('Domains', 'wp-ultimo'),
|
||||
'desc' => __('Leave blank to hide the title completely.', 'wp-ultimo'),
|
||||
'tooltip' => '',
|
||||
);
|
||||
|
||||
return $fields;
|
||||
|
||||
} // end fields;
|
||||
|
||||
/**
|
||||
* The list of keywords for this element.
|
||||
*
|
||||
* Return an array of strings with keywords describing this
|
||||
* element. Gutenberg uses this to help customers find blocks.
|
||||
*
|
||||
* e.g.:
|
||||
* return array(
|
||||
* 'WP Ultimo',
|
||||
* 'Checkout',
|
||||
* 'Form',
|
||||
* 'Cart',
|
||||
* );
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return array
|
||||
*/
|
||||
public function keywords() {
|
||||
|
||||
return array(
|
||||
'WP Ultimo',
|
||||
'Domain',
|
||||
);
|
||||
|
||||
} // end keywords;
|
||||
|
||||
/**
|
||||
* List of default parameters for the element.
|
||||
*
|
||||
* If you are planning to add controls using the fields,
|
||||
* it might be a good idea to use this method to set defaults
|
||||
* for the parameters you are expecting.
|
||||
*
|
||||
* These defaults will be used inside a 'wp_parse_args' call
|
||||
* before passing the parameters down to the block render
|
||||
* function and the shortcode render function.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return array
|
||||
*/
|
||||
public function defaults() {
|
||||
|
||||
return array(
|
||||
'title' => __('Domains', 'wp-ultimo'),
|
||||
);
|
||||
|
||||
} // end defaults;
|
||||
|
||||
/**
|
||||
* Initializes the singleton.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return void
|
||||
*/
|
||||
public function init() {
|
||||
|
||||
parent::init();
|
||||
|
||||
if ($this->is_preview()) {
|
||||
|
||||
$this->site = wu_mock_site();
|
||||
|
||||
return;
|
||||
|
||||
} // end if;
|
||||
|
||||
$this->site = wu_get_current_site();
|
||||
|
||||
$maybe_limit_domain_mapping = true;
|
||||
|
||||
if ($this->site->has_limitations()) {
|
||||
|
||||
$maybe_limit_domain_mapping = $this->site->get_limitations()->domain_mapping->is_enabled();
|
||||
|
||||
} // end if;
|
||||
|
||||
if (!$this->site || !wu_get_setting('enable_domain_mapping') || !wu_get_setting('custom_domains') || !$maybe_limit_domain_mapping) {
|
||||
|
||||
$this->set_display(false);
|
||||
|
||||
} // end if;
|
||||
|
||||
add_action('plugins_loaded', array($this, 'register_forms'));
|
||||
|
||||
} // end init;
|
||||
|
||||
/**
|
||||
* Loads the required scripts.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return void
|
||||
*/
|
||||
public function register_scripts() {
|
||||
|
||||
add_wubox();
|
||||
|
||||
} // end register_scripts;
|
||||
|
||||
/**
|
||||
* Register ajax forms used to add a new domain.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return void
|
||||
*/
|
||||
public function register_forms() {
|
||||
/*
|
||||
* Add new Domain
|
||||
*/
|
||||
wu_register_form('user_add_new_domain', array(
|
||||
'render' => array($this, 'render_user_add_new_domain_modal'),
|
||||
'handler' => array($this, 'handle_user_add_new_domain_modal'),
|
||||
'capability' => 'exist',
|
||||
));
|
||||
|
||||
wu_register_form('user_make_domain_primary', array(
|
||||
'render' => array($this, 'render_user_make_domain_primary_modal'),
|
||||
'handler' => array($this, 'handle_user_make_domain_primary_modal'),
|
||||
'capability' => 'exist',
|
||||
));
|
||||
|
||||
wu_register_form('user_delete_domain_modal', array(
|
||||
'render' => array($this, 'render_user_delete_domain_modal'),
|
||||
'handler' => array($this, 'handle_user_delete_domain_modal'),
|
||||
'capability' => 'exist',
|
||||
));
|
||||
|
||||
} // end register_forms;
|
||||
|
||||
/**
|
||||
* Renders the add new customer modal.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return void
|
||||
*/
|
||||
public function render_user_add_new_domain_modal() {
|
||||
|
||||
$instructions = \WP_Ultimo\Managers\Domain_Manager::get_instance()->get_domain_mapping_instructions();
|
||||
|
||||
$fields = array(
|
||||
'instructions_note' => array(
|
||||
'type' => 'note',
|
||||
'desc' => sprintf('<a href="#" class="wu-no-underline" v-on:click.prevent="ready = false">%s</a>', __('← Back to the Instructions', 'wp-ultimo')),
|
||||
'wrapper_html_attr' => array(
|
||||
'v-if' => 'ready',
|
||||
'v-cloak' => '1',
|
||||
),
|
||||
),
|
||||
'instructions' => array(
|
||||
'type' => 'text-display',
|
||||
'copy' => false,
|
||||
'title' => __('Instructions', 'wp-ultimo'),
|
||||
'tooltip' => '',
|
||||
'display_value' => sprintf('<div class="wu--mt-2 wu--mb-2">%s</div>', wpautop($instructions)),
|
||||
'wrapper_html_attr' => array(
|
||||
'v-show' => '!ready',
|
||||
'v-cloak' => 1
|
||||
),
|
||||
),
|
||||
'ready' => array(
|
||||
'type' => 'submit',
|
||||
'title' => __('Next Step →', 'wp-ultimo'),
|
||||
'value' => 'save',
|
||||
'classes' => 'button button-primary wu-w-full',
|
||||
'wrapper_classes' => 'wu-items-end',
|
||||
'html_attr' => array(
|
||||
'v-on:click.prevent' => 'ready = true',
|
||||
),
|
||||
'wrapper_html_attr' => array(
|
||||
'v-show' => '!ready',
|
||||
'v-cloak' => 1
|
||||
),
|
||||
),
|
||||
'current_site' => array(
|
||||
'type' => 'hidden',
|
||||
'value' => wu_request('current_site'),
|
||||
),
|
||||
'domain' => array(
|
||||
'type' => 'text',
|
||||
'title' => __('Domain', 'wp-ultimo'),
|
||||
'placeholder' => __('mydomain.com', 'wp-ultimo'),
|
||||
'wrapper_html_attr' => array(
|
||||
'v-show' => 'ready',
|
||||
'v-cloak' => 1
|
||||
),
|
||||
),
|
||||
'primary_domain' => array(
|
||||
'type' => 'toggle',
|
||||
'title' => __('Primary Domain', 'wp-ultimo'),
|
||||
'desc' => __('Check to set this domain as the primary', 'wp-ultimo'),
|
||||
'html_attr' => array(
|
||||
'v-model' => 'primary_domain',
|
||||
),
|
||||
'wrapper_html_attr' => array(
|
||||
'v-show' => 'ready',
|
||||
'v-cloak' => 1,
|
||||
),
|
||||
),
|
||||
'primary_note' => array(
|
||||
'type' => 'note',
|
||||
'desc' => __('By making this the primary domain, we will convert the previous primary domain for this site, if one exists, into an alias domain.', 'wp-ultimo'),
|
||||
'wrapper_html_attr' => array(
|
||||
'v-if' => "require('primary_domain', true) && ready",
|
||||
'v-cloak' => 1,
|
||||
),
|
||||
),
|
||||
'submit_button_new' => array(
|
||||
'type' => 'submit',
|
||||
'title' => __('Add Domain', 'wp-ultimo'),
|
||||
'value' => 'save',
|
||||
'classes' => 'button button-primary wu-w-full',
|
||||
'wrapper_classes' => 'wu-items-end',
|
||||
'wrapper_html_attr' => array(
|
||||
'v-show' => 'ready',
|
||||
'v-cloak' => 1
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
$form = new \WP_Ultimo\UI\Form('add_new_domain', $fields, array(
|
||||
'views' => 'admin-pages/fields',
|
||||
'classes' => 'wu-modal-form wu-widget-list wu-striped wu-m-0 wu-mt-0',
|
||||
'field_wrapper_classes' => 'wu-w-full wu-box-border wu-items-center wu-flex wu-justify-between wu-p-4 wu-m-0 wu-border-t wu-border-l-0 wu-border-r-0 wu-border-b-0 wu-border-gray-300 wu-border-solid',
|
||||
'html_attr' => array(
|
||||
'data-wu-app' => 'add_new_domain',
|
||||
'data-state' => json_encode(array(
|
||||
'ready' => 0,
|
||||
'primary_domain' => false,
|
||||
)),
|
||||
),
|
||||
));
|
||||
|
||||
$form->render();
|
||||
|
||||
} // end render_user_add_new_domain_modal;
|
||||
|
||||
/**
|
||||
* Handles creation of a new customer.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return void
|
||||
*/
|
||||
public function handle_user_add_new_domain_modal() {
|
||||
|
||||
$current_user_id = get_current_user_id();
|
||||
|
||||
$current_site_id = wu_request('current_site');
|
||||
|
||||
$current_site = wu_get_site($current_site_id);
|
||||
|
||||
if (!is_super_admin() && (!$current_site || $current_user_id !== $current_site->get_customer()->get_user_id())) {
|
||||
|
||||
wp_send_json_error(
|
||||
new \WP_Error('no-permissions', __('You do not have permissions to perform this action.', 'wp-ultimo'))
|
||||
);
|
||||
|
||||
exit;
|
||||
|
||||
} // end if;
|
||||
|
||||
/*
|
||||
* Tries to create the domain
|
||||
*/
|
||||
$domain = wu_create_domain(array(
|
||||
'domain' => wu_request('domain'),
|
||||
'blog_id' => absint($current_site_id),
|
||||
'primary_domain' => (bool) wu_request('primary_domain'),
|
||||
));
|
||||
|
||||
if (is_wp_error($domain)) {
|
||||
|
||||
wp_send_json_error($domain);
|
||||
|
||||
} // end if;
|
||||
|
||||
if (wu_request('primary_domain')) {
|
||||
|
||||
$old_primary_domains = wu_get_domains(array(
|
||||
'primary_domain' => true,
|
||||
'blog_id' => $current_site_id,
|
||||
'id__not_in' => array($domain->get_id()),
|
||||
'fields' => 'ids',
|
||||
));
|
||||
|
||||
/*
|
||||
* Trigger async action to update the old primary domains.
|
||||
*/
|
||||
do_action_ref_array('wu_async_remove_old_primary_domains', array($old_primary_domains));
|
||||
|
||||
} // end if;
|
||||
|
||||
wu_enqueue_async_action('wu_async_process_domain_stage', array('domain_id' => $domain->get_id()), 'domain');
|
||||
|
||||
/**
|
||||
* Triggers when a new domain mapping is added.
|
||||
*/
|
||||
do_action('wu_domain_created', $domain, $domain->get_site(), $domain->get_site()->get_membership());
|
||||
|
||||
wp_send_json_success(array(
|
||||
'redirect_url' => wu_get_current_url(),
|
||||
));
|
||||
|
||||
exit;
|
||||
|
||||
} // end handle_user_add_new_domain_modal;
|
||||
|
||||
/**
|
||||
* Renders the domain delete action.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return void
|
||||
*/
|
||||
public function render_user_delete_domain_modal() {
|
||||
|
||||
$fields = array(
|
||||
'confirm' => array(
|
||||
'type' => 'toggle',
|
||||
'title' => __('Confirm Deletion', 'wp-ultimo'),
|
||||
'desc' => __('This action can not be undone.', 'wp-ultimo'),
|
||||
'html_attr' => array(
|
||||
'v-model' => 'confirmed',
|
||||
),
|
||||
),
|
||||
'domain_id' => array(
|
||||
'type' => 'hidden',
|
||||
'value' => wu_request('domain_id'),
|
||||
),
|
||||
'submit_button' => array(
|
||||
'type' => 'submit',
|
||||
'title' => __('Delete', 'wp-ultimo'),
|
||||
'placeholder' => __('Delete', 'wp-ultimo'),
|
||||
'value' => 'save',
|
||||
'classes' => 'button button-primary wu-w-full',
|
||||
'wrapper_classes' => 'wu-items-end',
|
||||
'html_attr' => array(
|
||||
'v-bind:disabled' => '!confirmed',
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
$form = new \WP_Ultimo\UI\Form('user_delete_domain_modal', $fields, array(
|
||||
'views' => 'admin-pages/fields',
|
||||
'classes' => 'wu-modal-form wu-widget-list wu-striped wu-m-0 wu-mt-0',
|
||||
'field_wrapper_classes' => 'wu-w-full wu-box-border wu-items-center wu-flex wu-justify-between wu-p-4 wu-m-0 wu-border-t wu-border-l-0 wu-border-r-0 wu-border-b-0 wu-border-gray-300 wu-border-solid',
|
||||
'html_attr' => array(
|
||||
'data-wu-app' => 'user_delete_domain_modal',
|
||||
'data-state' => json_encode(array(
|
||||
'confirmed' => false,
|
||||
)),
|
||||
),
|
||||
));
|
||||
|
||||
$form->render();
|
||||
|
||||
} // end render_user_delete_domain_modal;
|
||||
|
||||
/**
|
||||
* Handles deletion of the selected domain
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return void
|
||||
*/
|
||||
public function handle_user_delete_domain_modal() {
|
||||
|
||||
if (wu_request('user_id')) {
|
||||
|
||||
$customer = wu_get_customer_by_user_id(wu_request('user_id'));
|
||||
|
||||
} // end if;
|
||||
|
||||
$current_site = wu_request('current_site');
|
||||
|
||||
$get_domain = Domain::get_by_id(wu_request('domain_id'));
|
||||
|
||||
$domain = new Domain($get_domain);
|
||||
|
||||
if ($domain) {
|
||||
|
||||
$domain->delete();
|
||||
|
||||
} // end if;
|
||||
|
||||
wp_send_json_success(array(
|
||||
'redirect_url' => wu_get_current_url(),
|
||||
));
|
||||
|
||||
} // end handle_user_delete_domain_modal;
|
||||
|
||||
/**
|
||||
* Renders the domain delete action.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return void
|
||||
*/
|
||||
public function render_user_make_domain_primary_modal() {
|
||||
|
||||
$fields = array(
|
||||
'confirm' => array(
|
||||
'type' => 'toggle',
|
||||
'title' => __('Confirm Action', 'wp-ultimo'),
|
||||
'desc' => __('This action will also convert the previous primary domain (if any) to an alias to prevent unexpected behavior.', 'wp-ultimo'),
|
||||
'html_attr' => array(
|
||||
'v-model' => 'confirmed',
|
||||
),
|
||||
),
|
||||
'domain_id' => array(
|
||||
'type' => 'hidden',
|
||||
'value' => wu_request('domain_id'),
|
||||
),
|
||||
'submit_button' => array(
|
||||
'type' => 'submit',
|
||||
'title' => __('Make it Primary', 'wp-ultimo'),
|
||||
'placeholder' => __('Make it Primary', 'wp-ultimo'),
|
||||
'value' => 'save',
|
||||
'classes' => 'button button-primary wu-w-full',
|
||||
'wrapper_classes' => 'wu-items-end',
|
||||
'html_attr' => array(
|
||||
'v-bind:disabled' => '!confirmed',
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
$form = new \WP_Ultimo\UI\Form('user_delete_domain_modal', $fields, array(
|
||||
'views' => 'admin-pages/fields',
|
||||
'classes' => 'wu-modal-form wu-widget-list wu-striped wu-m-0 wu-mt-0',
|
||||
'field_wrapper_classes' => 'wu-w-full wu-box-border wu-items-center wu-flex wu-justify-between wu-p-4 wu-m-0 wu-border-t wu-border-l-0 wu-border-r-0 wu-border-b-0 wu-border-gray-300 wu-border-solid',
|
||||
'html_attr' => array(
|
||||
'data-wu-app' => 'user_delete_domain_modal',
|
||||
'data-state' => json_encode(array(
|
||||
'confirmed' => false,
|
||||
)),
|
||||
),
|
||||
));
|
||||
|
||||
$form->render();
|
||||
|
||||
} // end render_user_make_domain_primary_modal;
|
||||
|
||||
/**
|
||||
* Handles conversion to primary domain.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return void
|
||||
*/
|
||||
public function handle_user_make_domain_primary_modal() {
|
||||
|
||||
$current_site = wu_request('current_site');
|
||||
|
||||
$domain_id = wu_request('domain_id');
|
||||
|
||||
$domain = wu_get_domain($domain_id);
|
||||
|
||||
if ($domain) {
|
||||
|
||||
$domain->set_primary_domain(true);
|
||||
|
||||
$status = $domain->save();
|
||||
|
||||
if (is_wp_error($status)) {
|
||||
|
||||
wp_send_json_error($status);
|
||||
|
||||
} // end if;
|
||||
|
||||
$old_primary_domains = wu_get_domains(array(
|
||||
'primary_domain' => true,
|
||||
'blog_id' => $domain->get_blog_id(),
|
||||
'id__not_in' => array($domain->get_id()),
|
||||
'fields' => 'ids',
|
||||
));
|
||||
|
||||
/*
|
||||
* Trigger async action to update the old primary domains.
|
||||
*/
|
||||
do_action_ref_array('wu_async_remove_old_primary_domains', array($old_primary_domains));
|
||||
|
||||
wp_send_json_success(array(
|
||||
'redirect_url' => is_main_site() ? wu_get_current_url() : get_admin_url($current_site),
|
||||
));
|
||||
|
||||
} // end if;
|
||||
|
||||
wp_send_json_error(new \WP_Error('error', __('Something wrong happenned.', 'wp-ultimo')));
|
||||
|
||||
} // end handle_user_make_domain_primary_modal;
|
||||
|
||||
/**
|
||||
* Runs early on the request lifecycle as soon as we detect the shortcode is present.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return void
|
||||
*/
|
||||
public function setup() {
|
||||
|
||||
$this->site = WP_Ultimo()->currents->get_site();
|
||||
|
||||
if (!$this->site || !$this->site->is_customer_allowed()) {
|
||||
|
||||
$this->set_display(false);
|
||||
|
||||
return;
|
||||
|
||||
} // end if;
|
||||
|
||||
// Ensure admin.php is loaded as we need wu_responsive_table_row function
|
||||
require_once wu_path('inc/functions/admin.php');
|
||||
|
||||
$this->membership = $this->site->get_membership();
|
||||
|
||||
} // end setup;
|
||||
|
||||
/**
|
||||
* Allows the setup in the context of previews.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return void
|
||||
*/
|
||||
public function setup_preview() {
|
||||
|
||||
$this->site = wu_mock_site();
|
||||
|
||||
$this->membership = wu_mock_membership();
|
||||
|
||||
} // end setup_preview;
|
||||
|
||||
/**
|
||||
* The content to be output on the screen.
|
||||
*
|
||||
* Should return HTML markup to be used to display the block.
|
||||
* This method is shared between the block render method and
|
||||
* the shortcode implementation.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*
|
||||
* @param array $atts Parameters of the block/shortcode.
|
||||
* @param string|null $content The content inside the shortcode.
|
||||
* @return string
|
||||
*/
|
||||
public function output($atts, $content = null) {
|
||||
|
||||
$current_site = $this->site;
|
||||
|
||||
$all_domains = wu_get_domains(array(
|
||||
'blog_id' => $current_site->get_id(),
|
||||
'orderby' => 'primary_domain',
|
||||
'order' => 'DESC',
|
||||
));
|
||||
|
||||
$domains = array();
|
||||
|
||||
foreach ($all_domains as $key => $domain) {
|
||||
|
||||
$stage = new Domain_Stage($domain->get_stage());
|
||||
|
||||
$secure = 'dashicons-wu-lock-open';
|
||||
|
||||
$secure_message = __('Domain not secured with HTTPS', 'wp-ultimo');
|
||||
|
||||
if ($domain->is_secure()) {
|
||||
|
||||
$secure = 'dashicons-wu-lock wu-text-green-500';
|
||||
|
||||
$secure_message = __('Domain secured with HTTPS', 'wp-ultimo');
|
||||
|
||||
} // end if;
|
||||
|
||||
$url_atts = array(
|
||||
'current_site' => $current_site->get_id(),
|
||||
'domain_id' => $domain->get_id(),
|
||||
);
|
||||
|
||||
$delete_url = wu_get_form_url('user_delete_domain_modal', $url_atts);
|
||||
$primary_url = wu_get_form_url('user_make_domain_primary', $url_atts);
|
||||
|
||||
$domains[$key] = array(
|
||||
'id' => $domain->get_id(),
|
||||
'domain_object' => $domain,
|
||||
'domain' => $domain->get_domain(),
|
||||
'stage' => $stage->get_label(),
|
||||
'primary' => $domain->is_primary_domain(),
|
||||
'stage_class' => $stage->get_classes(),
|
||||
'secure_class' => $secure,
|
||||
'secure_message' => $secure_message,
|
||||
'delete_link' => $delete_url,
|
||||
'primary_link' => $primary_url,
|
||||
);
|
||||
|
||||
} // end foreach;
|
||||
|
||||
$url_atts = array(
|
||||
'current_site' => $current_site->get_ID(),
|
||||
);
|
||||
|
||||
$other_atts = array(
|
||||
'domains' => $domains,
|
||||
'modal' => array(
|
||||
'label' => __('Add Domain', 'wp-ultimo'),
|
||||
'icon' => 'wu-circle-with-plus',
|
||||
'classes' => 'wubox',
|
||||
'url' => wu_get_form_url('user_add_new_domain', $url_atts),
|
||||
),
|
||||
);
|
||||
|
||||
$atts = array_merge($other_atts, $atts);
|
||||
|
||||
return wu_get_template_contents('dashboard-widgets/domain-mapping', $atts);
|
||||
|
||||
} // end output;
|
||||
|
||||
} // end class Domain_Mapping_Element;
|
503
inc/ui/class-field.php
Normal file
503
inc/ui/class-field.php
Normal file
@ -0,0 +1,503 @@
|
||||
<?php
|
||||
/**
|
||||
* Describes a field and contains helper functions for sanitization and validation.
|
||||
*
|
||||
* @package WP_Ultimo
|
||||
* @subpackage UI
|
||||
* @since 2.0.0
|
||||
*/
|
||||
|
||||
namespace WP_Ultimo\UI;
|
||||
|
||||
// Exit if accessed directly
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
/**
|
||||
* Describes a field and contains helper functions for sanitization and validation.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
class Field implements \JsonSerializable {
|
||||
|
||||
/**
|
||||
* Holds the attributes of this field.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @var array
|
||||
*/
|
||||
protected $atts = array();
|
||||
|
||||
/**
|
||||
* Holds the value of the settings represented by this field.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @var mixed
|
||||
*/
|
||||
protected $value = null;
|
||||
|
||||
/**
|
||||
* Set and the attributes passed via the constructor.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*
|
||||
* @param string $id Field id. This is going to be used to retrieve the value from the database later.
|
||||
* @param array $atts Field attributes.
|
||||
*/
|
||||
public function __construct($id, $atts) {
|
||||
|
||||
$this->set_attributes($id, $atts);
|
||||
|
||||
} // end __construct;
|
||||
|
||||
/**
|
||||
* Set and the attributes passed via the constructor.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*
|
||||
* @param string $id Field id. This is going to be used to retrieve the value from the database later.
|
||||
* @param array $atts Field attributes.
|
||||
* @return void
|
||||
*/
|
||||
public function set_attributes($id, $atts) {
|
||||
|
||||
$this->atts = wp_parse_args($atts, array(
|
||||
'id' => $id,
|
||||
'type' => 'text',
|
||||
'icon' => 'dashicons-wu-cog',
|
||||
'action' => false,
|
||||
'form' => false,
|
||||
'title' => false,
|
||||
'img' => false,
|
||||
'desc' => false,
|
||||
'content' => false,
|
||||
'display_value' => false,
|
||||
'default_value' => false,
|
||||
'tooltip' => false,
|
||||
'args' => false,
|
||||
'sortable' => false,
|
||||
'placeholder' => false,
|
||||
'options' => false,
|
||||
'options_template' => false,
|
||||
'require' => false,
|
||||
'button' => false,
|
||||
'width' => false,
|
||||
'rules' => false,
|
||||
'min' => false,
|
||||
'max' => false,
|
||||
'allow_html' => false,
|
||||
'append' => false,
|
||||
'order' => false,
|
||||
'dummy' => false,
|
||||
'disabled' => false,
|
||||
'capability' => false,
|
||||
'edit' => false,
|
||||
'copy' => false,
|
||||
'validation' => false,
|
||||
'meter' => false,
|
||||
'href' => false,
|
||||
'raw' => false,
|
||||
'money' => false,
|
||||
'stacked' => false, // If the field is inside a restricted container
|
||||
'columns' => 1,
|
||||
'classes' => '',
|
||||
'wrapper_classes' => '',
|
||||
'html_attr' => array(),
|
||||
'wrapper_html_attr' => array(),
|
||||
'sub_fields' => array(),
|
||||
'prefix' => '',
|
||||
'suffix' => '',
|
||||
'prefix_html_attr' => array(),
|
||||
'suffix_html_attr' => array(),
|
||||
));
|
||||
|
||||
} // end set_attributes;
|
||||
|
||||
/**
|
||||
* Set a particular attribute.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*
|
||||
* @param string $att The attribute name.
|
||||
* @param mixed $value The new attribute value.
|
||||
* @return void
|
||||
*/
|
||||
public function set_attribute($att, $value) {
|
||||
|
||||
$this->atts[$att] = $value;
|
||||
|
||||
} // end set_attribute;
|
||||
|
||||
/**
|
||||
* Returns the list of field attributes.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return array
|
||||
*/
|
||||
public function get_attributes() {
|
||||
|
||||
return $this->atts;
|
||||
|
||||
} // end get_attributes;
|
||||
|
||||
/**
|
||||
* Makes sure old fields remain compatible.
|
||||
*
|
||||
* We are making some field type name changes in 2.0.
|
||||
* This method lists an array with aliases in the following format:
|
||||
*
|
||||
* - old_type_name => new_type_name.
|
||||
*
|
||||
* We throw a deprecation notice to make sure developers update their code appropriately.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return string
|
||||
*/
|
||||
public function get_compat_template_name() {
|
||||
|
||||
$aliases = array(
|
||||
'heading' => 'header',
|
||||
'heading_collapsible' => 'header',
|
||||
'select2' => 'select',
|
||||
'checkbox' => 'toggle',
|
||||
);
|
||||
|
||||
$deprecated = array(
|
||||
'heading',
|
||||
'heading_collapsible',
|
||||
'select2',
|
||||
);
|
||||
|
||||
if (array_key_exists($this->type, $aliases)) {
|
||||
|
||||
$new_type_name = $aliases[$this->type];
|
||||
|
||||
if (array_key_exists($this->type, $deprecated)) {
|
||||
|
||||
// translators: The %1$s placeholder is the old type name, the second, the new type name.
|
||||
_doing_it_wrong('wu_add_field', sprintf(__('The field type "%1$s" is no longer supported, use "%2$s" instead.'), $this->type, $new_type_name), '2.0.0');
|
||||
|
||||
} // end if;
|
||||
|
||||
/*
|
||||
* Back Compat for Select2 Fields
|
||||
*/
|
||||
if ($this->type === 'select2') {
|
||||
|
||||
$this->atts['html_attr']['data-selectize'] = 1;
|
||||
$this->atts['html_attr']['multiple'] = 1;
|
||||
|
||||
} // end if;
|
||||
|
||||
return $new_type_name;
|
||||
|
||||
} // end if;
|
||||
|
||||
return false;
|
||||
|
||||
} // end get_compat_template_name;
|
||||
|
||||
/**
|
||||
* Returns the template name for a field.
|
||||
*
|
||||
* We use this to go to the views folder and fetch the HTML template.
|
||||
* The return here is not an absolute path, as the folder depends on the view the form is using.
|
||||
*
|
||||
* @see \WP_Ultimo\UI\Forms
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return string
|
||||
*/
|
||||
public function get_template_name() {
|
||||
|
||||
$compat_name = $this->get_compat_template_name();
|
||||
|
||||
$view_name = $compat_name ? $compat_name : $this->type;
|
||||
|
||||
return str_replace('_', '-', (string) $view_name);
|
||||
|
||||
} // end get_template_name;
|
||||
|
||||
/**
|
||||
* Returns attributes as class properties.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*
|
||||
* @param string $att Attribute to retrieve.
|
||||
* @return mixed
|
||||
*/
|
||||
public function __get($att) {
|
||||
|
||||
$allowed_callable = array(
|
||||
'title',
|
||||
'desc',
|
||||
'content',
|
||||
'display_value',
|
||||
'default_value',
|
||||
'tooltip',
|
||||
'options',
|
||||
'require',
|
||||
'validation',
|
||||
'value',
|
||||
'html_attr',
|
||||
'img',
|
||||
);
|
||||
|
||||
$attr = isset($this->atts[$att]) ? $this->atts[$att] : false;
|
||||
|
||||
$allow_callable_prefix = is_string($attr) && strncmp($attr, 'wu_get_', strlen('wu_get_')) === 0 && is_callable($attr);
|
||||
$allow_callable_method = is_array($attr) && is_callable($attr);
|
||||
|
||||
if (in_array($att, $allowed_callable, true) && ($allow_callable_prefix || $allow_callable_method || is_a($attr, \Closure::class))) {
|
||||
|
||||
$attr = call_user_func($attr, $this);
|
||||
|
||||
} // end if;
|
||||
|
||||
if ($att === 'wrapper_classes' && isset($this->atts['wrapper_html_attr']['v-show'])) {
|
||||
|
||||
$this->atts['wrapper_classes'] = $this->atts['wrapper_classes'] . ' wu-requires-other';
|
||||
|
||||
} // end if;
|
||||
|
||||
if ($att === 'type' && $this->atts[$att] === 'submit') {
|
||||
|
||||
$this->atts['wrapper_classes'] = $this->atts['wrapper_classes'] . ' wu-submit-field';
|
||||
|
||||
} // end if;
|
||||
|
||||
if ($att === 'type' && $this->atts[$att] === 'tab-select') {
|
||||
|
||||
$this->atts['wrapper_classes'] = $this->atts['wrapper_classes'] . ' wu-tab-field';
|
||||
|
||||
} // end if;
|
||||
|
||||
if ($att === 'wrapper_classes' && is_a($this->form, '\\WP_Ultimo\\UI\\Form')) {
|
||||
|
||||
return $this->form->field_wrapper_classes . ' ' . $this->atts['wrapper_classes'];
|
||||
|
||||
} // end if;
|
||||
|
||||
if ($att === 'classes' && is_a($this->form, '\\WP_Ultimo\\UI\\Form')) {
|
||||
|
||||
return $this->form->field_classes . ' ' . $this->atts['classes'];
|
||||
|
||||
} // end if;
|
||||
|
||||
if ($att === 'title' && $attr === false && isset($this->atts['name'])) {
|
||||
|
||||
$attr = $this->atts['name'];
|
||||
|
||||
} // end if;
|
||||
|
||||
return $attr;
|
||||
|
||||
} // end __get;
|
||||
|
||||
/**
|
||||
* Returns the list of sanitization callbacks for each field type
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return array
|
||||
*/
|
||||
protected function sanitization_rules() {
|
||||
|
||||
$rules = array(
|
||||
'text' => 'sanitize_text_field',
|
||||
'header' => '__return_null',
|
||||
'number' => array($this, 'validate_number_field'),
|
||||
'wp_editor' => array($this, 'validate_textarea_field'),
|
||||
'textarea' => array($this, 'validate_textarea_field'),
|
||||
'checkbox' => 'wu_string_to_bool',
|
||||
'multi_checkbox' => false,
|
||||
'select2' => false,
|
||||
'multiselect' => false,
|
||||
);
|
||||
|
||||
return apply_filters('wu_settings_fields_sanitization_rules', $rules);
|
||||
|
||||
} // end sanitization_rules;
|
||||
|
||||
/**
|
||||
* Returns the value of the setting represented by this field.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return mixed
|
||||
*/
|
||||
public function get_value() {
|
||||
|
||||
return $this->value;
|
||||
|
||||
} // end get_value;
|
||||
|
||||
/**
|
||||
* Sets the value of the settings represented by this field.
|
||||
*
|
||||
* This alone won't save the setting to the database. This method also invokes the
|
||||
* sanitization callback, so we can be sure the data is ready for database insertion.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*
|
||||
* @param mixed $value Value of the settings being represented by this field.
|
||||
* @return WP_Ultimo\UI\Field
|
||||
*/
|
||||
public function set_value($value) {
|
||||
|
||||
$this->value = $value;
|
||||
|
||||
if (!$this->raw) {
|
||||
|
||||
$this->sanitize();
|
||||
|
||||
} // end if;
|
||||
|
||||
return $this;
|
||||
|
||||
} // end set_value;
|
||||
|
||||
/**
|
||||
* Runs the value of the field through the sanitization callback.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return void
|
||||
*/
|
||||
public function sanitize() {
|
||||
|
||||
$rules = $this->sanitization_rules();
|
||||
|
||||
$sanitize_method = isset($rules[$this->type]) ? $rules[$this->type] : $rules['text'];
|
||||
|
||||
if ($sanitize_method) {
|
||||
|
||||
$this->value = call_user_func($sanitize_method, $this->value);
|
||||
|
||||
} // end if;
|
||||
|
||||
} // end sanitize;
|
||||
/**
|
||||
* Sanitization callback for fields of type number.
|
||||
*
|
||||
* Checks if the new value set is between the min and max boundaries.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*
|
||||
* @param int|float $value Value of the settings being represented by this field.
|
||||
* @return int|float
|
||||
*/
|
||||
protected function validate_number_field($value) {
|
||||
|
||||
/**
|
||||
* Check if the value respects the min/max values.
|
||||
*/
|
||||
if ($this->min && $value < $this->min) {
|
||||
|
||||
return $this->min;
|
||||
|
||||
} // end if;
|
||||
|
||||
if ($this->max && $value > $this->max) {
|
||||
|
||||
return $this->max;
|
||||
|
||||
} // end if;
|
||||
|
||||
return $value;
|
||||
|
||||
} // end validate_number_field;
|
||||
|
||||
/**
|
||||
* Cleans the value submitted via a textarea or wp_editor field for database insertion.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*
|
||||
* @param string $value Value of the settings being represented by this field.
|
||||
* @return string
|
||||
*/
|
||||
protected function validate_textarea_field($value) {
|
||||
|
||||
if ($this->allow_html) {
|
||||
|
||||
return stripslashes(wp_filter_post_kses(addslashes($value)));
|
||||
|
||||
} // end if;
|
||||
|
||||
return wp_strip_all_tags(stripslashes($value));
|
||||
|
||||
} // end validate_textarea_field;
|
||||
|
||||
/**
|
||||
* Return HTML attributes for the field.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return string
|
||||
*/
|
||||
public function get_html_attributes() {
|
||||
|
||||
if (is_callable($this->atts['html_attr'])) {
|
||||
|
||||
$this->atts['html_attr'] = call_user_func($this->atts['html_attr']);
|
||||
|
||||
} // end if;
|
||||
|
||||
$attributes = $this->atts['html_attr'];
|
||||
|
||||
unset($this->atts['html_attr']['class']);
|
||||
|
||||
if ($this->type === 'number') {
|
||||
|
||||
if ($this->min !== false) {
|
||||
|
||||
$attributes['min'] = $this->min;
|
||||
|
||||
} // end if;
|
||||
|
||||
if ($this->max !== false) {
|
||||
|
||||
$attributes['max'] = $this->max;
|
||||
|
||||
} // end if;
|
||||
|
||||
} // end if;
|
||||
|
||||
/*
|
||||
* Adds money formatting and masking
|
||||
*/
|
||||
if ($this->money !== false) {
|
||||
|
||||
$attributes['v-bind'] = 'money_settings';
|
||||
|
||||
} // end if;
|
||||
|
||||
return wu_array_to_html_attrs($attributes);
|
||||
|
||||
} // end get_html_attributes;
|
||||
|
||||
/**
|
||||
* Return HTML attributes for the field.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return string
|
||||
*/
|
||||
public function get_wrapper_html_attributes() {
|
||||
|
||||
$attributes = $this->atts['wrapper_html_attr'];
|
||||
|
||||
unset($this->atts['wrapper_html_attr']['class']);
|
||||
|
||||
return wu_array_to_html_attrs($attributes);
|
||||
|
||||
} // end get_wrapper_html_attributes;
|
||||
|
||||
/**
|
||||
* Implements our on json_decode version of this object. Useful for use in vue.js
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return array
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function jsonSerialize() {
|
||||
|
||||
return $this->atts;
|
||||
|
||||
} // end jsonSerialize;
|
||||
|
||||
} // end class Field;
|
250
inc/ui/class-form.php
Normal file
250
inc/ui/class-form.php
Normal file
@ -0,0 +1,250 @@
|
||||
<?php
|
||||
/**
|
||||
* Describes a form that can be used in different contexts, with different view files for each field type.
|
||||
*
|
||||
* @package WP_Ultimo
|
||||
* @subpackage UI
|
||||
* @since 2.0.0
|
||||
*/
|
||||
|
||||
namespace WP_Ultimo\UI;
|
||||
|
||||
use \WP_Ultimo\UI\Field;
|
||||
|
||||
// Exit if accessed directly
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
/**
|
||||
* Describes a form that can be used in different contexts, with different view files for each field type.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
class Form implements \JsonSerializable {
|
||||
|
||||
/**
|
||||
* Holds the attributes of this field.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @var array
|
||||
*/
|
||||
protected $atts = array();
|
||||
|
||||
/**
|
||||
* Holds the fields we want to display using this form.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @var array
|
||||
*/
|
||||
protected $fields = array();
|
||||
|
||||
/**
|
||||
* Set and the attributes passed via the constructor.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*
|
||||
* @param string $id Form id. This is going to be used to retrieve the value from the database later.
|
||||
* @param array $fields List of arrays representing the form fields.
|
||||
* @param array $atts Form attributes.
|
||||
*/
|
||||
public function __construct($id, $fields, $atts = array()) {
|
||||
|
||||
$this->atts = apply_filters("wu_{$id}_form_atts", wp_parse_args($atts, array(
|
||||
'id' => $id,
|
||||
'method' => 'post',
|
||||
'before' => '',
|
||||
'after' => '',
|
||||
'action' => false,
|
||||
'title' => false,
|
||||
'wrap_in_form_tag' => false,
|
||||
'wrap_tag' => 'div',
|
||||
'classes' => false,
|
||||
'field_wrapper_classes' => false,
|
||||
'field_classes' => false,
|
||||
'views' => 'settings/fields',
|
||||
'variables' => array(),
|
||||
'step' => (object) array(
|
||||
'classes' => '',
|
||||
'element_id' => '',
|
||||
),
|
||||
'html_attr' => array(
|
||||
'class' => '',
|
||||
),
|
||||
)));
|
||||
|
||||
$this->set_fields($fields);
|
||||
|
||||
} // end __construct;
|
||||
|
||||
/**
|
||||
* Returns attributes as class properties.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*
|
||||
* @param string $att Attribute to retrieve.
|
||||
* @return mixed
|
||||
*/
|
||||
public function __get($att) {
|
||||
|
||||
$allowed_callable = array(
|
||||
'before',
|
||||
'after',
|
||||
);
|
||||
|
||||
$attr = isset($this->atts[$att]) ? $this->atts[$att] : false;
|
||||
|
||||
if (in_array($att, $allowed_callable, true) && is_callable($attr)) {
|
||||
|
||||
$attr = call_user_func($attr, $this);
|
||||
|
||||
} // end if;
|
||||
|
||||
return $attr;
|
||||
|
||||
} // end __get;
|
||||
|
||||
/**
|
||||
* Returns the list of field attributes.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return array
|
||||
*/
|
||||
public function get_attributes() {
|
||||
|
||||
return $this->atts;
|
||||
|
||||
} // end get_attributes;
|
||||
|
||||
/**
|
||||
* Returns the list of fields used by the form.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return array
|
||||
*/
|
||||
public function get_fields() {
|
||||
|
||||
return (array) $this->fields;
|
||||
|
||||
} // end get_fields;
|
||||
|
||||
/**
|
||||
* Casts fields to \WP_Ultimo\UI\Fields and stores them on private list.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*
|
||||
* @param array $fields List of fields of the form.
|
||||
* @return void
|
||||
*/
|
||||
public function set_fields($fields) {
|
||||
|
||||
$id = $this->id;
|
||||
|
||||
/**
|
||||
* Filters the fields on a form. The form is identified by the ID in the filter name.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*
|
||||
* @param array $fields List of fields of the form.
|
||||
*/
|
||||
$fields = apply_filters("wu_{$id}_form_fields", $fields);
|
||||
|
||||
foreach ($fields as $field_slug => $field) {
|
||||
|
||||
$field['form'] = $this;
|
||||
|
||||
$this->fields[$field_slug] = new Field($field_slug, $field);
|
||||
|
||||
} // end foreach;
|
||||
|
||||
} // end set_fields;
|
||||
|
||||
/**
|
||||
* Renders the form with its fields.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return void
|
||||
*/
|
||||
public function render() {
|
||||
|
||||
$variables = array_merge($this->variables, array(
|
||||
'form_slug' => $this->id,
|
||||
'form' => $this,
|
||||
'step' => $this->step,
|
||||
));
|
||||
|
||||
ob_start();
|
||||
|
||||
foreach ($this->get_fields() as $field_slug => $field) {
|
||||
|
||||
$template_name = $field->get_template_name();
|
||||
|
||||
if (wu_get_isset($field->wrapper_html_attr, 'id') === false) {
|
||||
|
||||
$new_wrapper_attributes = $field->wrapper_html_attr;
|
||||
|
||||
$new_wrapper_attributes['id'] = "wrapper-field-$field_slug";
|
||||
|
||||
$field->set_attribute('wrapper_html_attr', $new_wrapper_attributes);
|
||||
|
||||
} // end if;
|
||||
|
||||
wu_get_template("{$this->views}/field-{$template_name}", array(
|
||||
'field_slug' => $field_slug,
|
||||
'field' => $field,
|
||||
), "{$this->views}/field-text");
|
||||
|
||||
} // end foreach;
|
||||
|
||||
$rendered_fields = ob_get_clean();
|
||||
|
||||
$variables['rendered_fields'] = $rendered_fields;
|
||||
|
||||
wu_get_template("{$this->views}/form", $variables);
|
||||
|
||||
} // end render;
|
||||
|
||||
/**
|
||||
* Return HTML attributes for the field.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return string
|
||||
*/
|
||||
public function get_html_attributes() {
|
||||
|
||||
$attributes = $this->atts['html_attr'];
|
||||
|
||||
unset($this->atts['html_attr']['class']);
|
||||
|
||||
if ($this->type === 'number') {
|
||||
|
||||
if ($this->min !== false) {
|
||||
|
||||
$attributes['min'] = $this->min;
|
||||
|
||||
} // end if;
|
||||
|
||||
if ($this->max !== false) {
|
||||
|
||||
$attributes['max'] = $this->max;
|
||||
|
||||
} // end if;
|
||||
|
||||
} // end if;
|
||||
|
||||
return wu_array_to_html_attrs($attributes);
|
||||
|
||||
} // end get_html_attributes;
|
||||
|
||||
/**
|
||||
* Implements our on json_decode version of this object. Useful for use in vue.js
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return array
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function jsonSerialize() {
|
||||
|
||||
return $this->atts;
|
||||
|
||||
} // end jsonSerialize;
|
||||
|
||||
} // end class Form;
|
302
inc/ui/class-invoices-element.php
Normal file
302
inc/ui/class-invoices-element.php
Normal file
@ -0,0 +1,302 @@
|
||||
<?php
|
||||
/**
|
||||
* Adds the Invoices_Element UI to the Admin Panel.
|
||||
*
|
||||
* @package WP_Ultimo
|
||||
* @subpackage UI
|
||||
* @since 2.0.0
|
||||
*/
|
||||
|
||||
namespace WP_Ultimo\UI;
|
||||
|
||||
use WP_Ultimo\UI\Base_Element;
|
||||
|
||||
// Exit if accessed directly
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
/**
|
||||
* Adds the Checkout Element UI to the Admin Panel.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
class Invoices_Element extends Base_Element {
|
||||
|
||||
use \WP_Ultimo\Traits\Singleton;
|
||||
|
||||
/**
|
||||
* The id of the element.
|
||||
*
|
||||
* Something simple, without prefixes, like 'checkout', or 'pricing-tables'.
|
||||
*
|
||||
* This is used to construct shortcodes by prefixing the id with 'wu_'
|
||||
* e.g. an id checkout becomes the shortcode 'wu_checkout' and
|
||||
* to generate the Gutenberg block by prefixing it with 'wp-ultimo/'
|
||||
* e.g. checkout would become the block 'wp-ultimo/checkout'.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @var string
|
||||
*/
|
||||
public $id = 'invoices';
|
||||
|
||||
/**
|
||||
* Controls if this is a public element to be used in pages/shortcodes by user.
|
||||
*
|
||||
* @since 2.0.24
|
||||
* @var boolean
|
||||
*/
|
||||
protected $public = true;
|
||||
|
||||
/**
|
||||
* The current membership.
|
||||
*
|
||||
* @since 2.2.0
|
||||
* @var \WP_Ultimo\Models\Membership
|
||||
*/
|
||||
protected $membership;
|
||||
|
||||
/**
|
||||
* The icon of the UI element.
|
||||
* e.g. return fa fa-search
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @param string $context One of the values: block, elementor or bb.
|
||||
* @return string
|
||||
*/
|
||||
public function get_icon($context = 'block') {
|
||||
|
||||
if ($context === 'elementor') {
|
||||
|
||||
return 'eicon-price-list';
|
||||
|
||||
} // end if;
|
||||
|
||||
return 'fa fa-search';
|
||||
|
||||
} // end get_icon;
|
||||
|
||||
/**
|
||||
* The title of the UI element.
|
||||
*
|
||||
* This is used on the Blocks list of Gutenberg.
|
||||
* You should return a string with the localized title.
|
||||
* e.g. return __('My Element', 'wp-ultimo').
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return string
|
||||
*/
|
||||
public function get_title() {
|
||||
|
||||
return __('Invoices', 'wp-ultimo');
|
||||
|
||||
} // end get_title;
|
||||
|
||||
/**
|
||||
* The description of the UI element.
|
||||
*
|
||||
* This is also used on the Gutenberg block list
|
||||
* to explain what this block is about.
|
||||
* You should return a string with the localized title.
|
||||
* e.g. return __('Adds a checkout form to the page', 'wp-ultimo').
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return string
|
||||
*/
|
||||
public function get_description() {
|
||||
|
||||
return __('Adds a checkout form block to the page.', 'wp-ultimo');
|
||||
|
||||
} // end get_description;
|
||||
|
||||
/**
|
||||
* The list of fields to be added to Gutenberg.
|
||||
*
|
||||
* If you plan to add Gutenberg controls to this block,
|
||||
* you'll need to return an array of fields, following
|
||||
* our fields interface (@see inc/ui/class-field.php).
|
||||
*
|
||||
* You can create new Gutenberg panels by adding fields
|
||||
* with the type 'header'. See the Checkout Elements for reference.
|
||||
*
|
||||
* @see inc/ui/class-checkout-element.php
|
||||
*
|
||||
* Return an empty array if you don't have controls to add.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return array
|
||||
*/
|
||||
public function fields() {
|
||||
|
||||
$fields = array();
|
||||
|
||||
$fields['header'] = array(
|
||||
'title' => __('General', 'wp-ultimo'),
|
||||
'desc' => __('General', 'wp-ultimo'),
|
||||
'type' => 'header',
|
||||
);
|
||||
|
||||
$fields['title'] = array(
|
||||
'type' => 'text',
|
||||
'title' => __('Title', 'wp-ultimo'),
|
||||
'value' => __('Invoices', 'wp-ultimo'),
|
||||
'desc' => __('Leave blank to hide the title completely.', 'wp-ultimo'),
|
||||
'tooltip' => '',
|
||||
);
|
||||
|
||||
$fields['limit'] = array(
|
||||
'type' => 'int',
|
||||
'title' => __('Limit', 'wp-ultimo'),
|
||||
'value' => 10,
|
||||
'desc' => __('Limit the number of invoices to show.', 'wp-ultimo'),
|
||||
'tooltip' => '',
|
||||
);
|
||||
|
||||
return $fields;
|
||||
|
||||
} // end fields;
|
||||
|
||||
/**
|
||||
* The list of keywords for this element.
|
||||
*
|
||||
* Return an array of strings with keywords describing this
|
||||
* element. Gutenberg uses this to help customers find blocks.
|
||||
*
|
||||
* e.g.:
|
||||
* return array(
|
||||
* 'WP Ultimo',
|
||||
* 'Invoices',
|
||||
* 'Form',
|
||||
* 'Cart',
|
||||
* );
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return array
|
||||
*/
|
||||
public function keywords() {
|
||||
|
||||
return array(
|
||||
'WP Ultimo',
|
||||
'Invoices',
|
||||
'Form',
|
||||
'Cart',
|
||||
);
|
||||
|
||||
} // end keywords;
|
||||
|
||||
/**
|
||||
* List of default parameters for the element.
|
||||
*
|
||||
* If you are planning to add controls using the fields,
|
||||
* it might be a good idea to use this method to set defaults
|
||||
* for the parameters you are expecting.
|
||||
*
|
||||
* These defaults will be used inside a 'wp_parse_args' call
|
||||
* before passing the parameters down to the block render
|
||||
* function and the shortcode render function.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return array
|
||||
*/
|
||||
public function defaults() {
|
||||
|
||||
return array(
|
||||
'title' => __('Invoices', 'wp-ultimo'),
|
||||
'limit' => 0,
|
||||
);
|
||||
|
||||
} // end defaults;
|
||||
|
||||
/**
|
||||
* Loads the required scripts.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return void
|
||||
*/
|
||||
public function register_scripts() {
|
||||
|
||||
wp_enqueue_script('wu-ajax-list-table');
|
||||
|
||||
} // end register_scripts;
|
||||
|
||||
/**
|
||||
* Loads dependencies for the render.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return void
|
||||
*/
|
||||
public function dependencies() {
|
||||
|
||||
if (!function_exists('convert_to_screen')) {
|
||||
|
||||
require_once ABSPATH . 'wp-admin/includes/template.php';
|
||||
|
||||
} // end if;
|
||||
|
||||
if (!function_exists('get_column_headers')) {
|
||||
|
||||
require_once ABSPATH . 'wp-admin/includes/class-wp-screen.php';
|
||||
require_once ABSPATH . 'wp-admin/includes/screen.php';
|
||||
|
||||
} // end if;
|
||||
|
||||
if (!function_exists('wu_responsive_table_row')) {
|
||||
|
||||
require wu_path('/inc/functions/admin.php');
|
||||
|
||||
} // end if;
|
||||
|
||||
} // end dependencies;
|
||||
|
||||
/**
|
||||
* Runs early on the request lifecycle as soon as we detect the shortcode is present.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return void
|
||||
*/
|
||||
public function setup() {
|
||||
|
||||
$this->membership = WP_Ultimo()->currents->get_membership();
|
||||
|
||||
if (!$this->membership) {
|
||||
|
||||
$this->set_display(false);
|
||||
|
||||
return;
|
||||
|
||||
} // end if;
|
||||
|
||||
} // end setup;
|
||||
|
||||
/**
|
||||
* Allows the setup in the context of previews.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return void
|
||||
*/
|
||||
public function setup_preview() {
|
||||
|
||||
$this->membership = wu_mock_membership();
|
||||
|
||||
} // end setup_preview;
|
||||
|
||||
/**
|
||||
* The content to be output on the screen.
|
||||
*
|
||||
* Should return HTML markup to be used to display the block.
|
||||
* This method is shared between the block render method and
|
||||
* the shortcode implementation.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*
|
||||
* @param array $atts Parameters of the block/shortcode.
|
||||
* @param string|null $content The content inside the shortcode.
|
||||
* @return string
|
||||
*/
|
||||
public function output($atts, $content = null) {
|
||||
|
||||
$atts['membership'] = $this->membership;
|
||||
|
||||
return wu_get_template_contents('dashboard-widgets/invoices', $atts);
|
||||
|
||||
} // end output;
|
||||
|
||||
} // end class Invoices_Element;
|
598
inc/ui/class-jumper.php
Normal file
598
inc/ui/class-jumper.php
Normal file
@ -0,0 +1,598 @@
|
||||
<?php
|
||||
/**
|
||||
* Adds the Jumper UI to the Admin Panel.
|
||||
*
|
||||
* @package WP_Ultimo
|
||||
* @subpackage UI
|
||||
* @since 2.0.0
|
||||
*/
|
||||
|
||||
namespace WP_Ultimo\UI;
|
||||
|
||||
use WP_Ultimo\Logger;
|
||||
use WP_Ultimo\UI\Base_Element;
|
||||
use WP_Ultimo\License;
|
||||
|
||||
// Exit if accessed directly
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
/**
|
||||
* Adds the Jumper UI to the Admin Panel.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
class Jumper {
|
||||
|
||||
use \WP_Ultimo\Traits\Singleton;
|
||||
|
||||
/**
|
||||
* GET slug to force the jumper menu reset/fetching.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @var string
|
||||
*/
|
||||
protected $reset_slug = 'wu-rebuild-jumper';
|
||||
|
||||
/**
|
||||
* Key to save the menu list on the transient database.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @var string
|
||||
*/
|
||||
protected $transient_key = 'wu-jumper-menu-list';
|
||||
|
||||
/**
|
||||
* Element construct.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function __construct() {
|
||||
|
||||
add_action('wp_ultimo_load', array($this, 'add_settings'), 20);
|
||||
|
||||
add_action('init', array($this, 'load_jumper'));
|
||||
|
||||
} // end __construct;
|
||||
|
||||
/**
|
||||
* Checks if we should add the jumper or not.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return boolean
|
||||
*/
|
||||
protected function is_jumper_enabled() {
|
||||
|
||||
return apply_filters('wu_is_jumper_enabled', wu_get_setting('enable_jumper', true) && License::get_instance()->allowed() && current_user_can('manage_network'));
|
||||
|
||||
} // end is_jumper_enabled;
|
||||
|
||||
/**
|
||||
* Adds the Jumper trigger to the admin top pages.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*
|
||||
* @param \WP_Ultimo\Admin_Pages\Base_Admin_Page $page The current page.
|
||||
* @return void
|
||||
*/
|
||||
public function add_jumper_trigger($page) {
|
||||
|
||||
wu_get_template('ui/jumper-trigger', array(
|
||||
'page' => $page,
|
||||
'jumper' => $this,
|
||||
));
|
||||
|
||||
} // end add_jumper_trigger;
|
||||
|
||||
/**
|
||||
* Loads the necessary elements to display the Jumper.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return void
|
||||
*/
|
||||
public function load_jumper() {
|
||||
|
||||
if ($this->is_jumper_enabled() && is_admin()) {
|
||||
|
||||
add_action('wu_header_right', array($this, 'add_jumper_trigger'));
|
||||
|
||||
add_action('admin_init', array($this, 'rebuild_menu'));
|
||||
|
||||
add_action('admin_enqueue_scripts', array($this, 'enqueue_scripts'));
|
||||
|
||||
add_action('admin_enqueue_scripts', array($this, 'enqueue_styles'));
|
||||
|
||||
add_action('admin_footer', array($this, 'output'));
|
||||
|
||||
add_filter('update_footer', array($this, 'add_jumper_footer_message'), 200);
|
||||
|
||||
add_action('wu_after_save_settings', array($this, 'clear_jump_cache_on_save'));
|
||||
|
||||
add_filter('wu_link_list', array($this, 'add_wp_ultimo_extra_links'));
|
||||
|
||||
add_filter('wu_link_list', array($this, 'add_user_custom_links'));
|
||||
|
||||
} // end if;
|
||||
|
||||
} // end load_jumper;
|
||||
|
||||
/**
|
||||
* Clear the jumper menu cache on settings save
|
||||
*
|
||||
* We need to do this to make sure that we clear the menu when the admin
|
||||
* adds a new custom menu item.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*
|
||||
* @param array $settings Settings being saved.
|
||||
* @return void
|
||||
*/
|
||||
public function clear_jump_cache_on_save($settings) {
|
||||
|
||||
if (isset($settings['jumper_custom_links'])) {
|
||||
|
||||
delete_site_transient($this->transient_key);
|
||||
|
||||
} // end if;
|
||||
|
||||
} // end clear_jump_cache_on_save;
|
||||
|
||||
/**
|
||||
* Rebuilds the jumper menu via a trigger URL.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return void
|
||||
*/
|
||||
public function rebuild_menu() {
|
||||
|
||||
if (isset($_GET[$this->reset_slug]) && current_user_can('manage_network')) {
|
||||
|
||||
delete_site_transient($this->transient_key);
|
||||
|
||||
wp_redirect(network_admin_url());
|
||||
|
||||
exit;
|
||||
|
||||
} // end if;
|
||||
|
||||
} // end rebuild_menu;
|
||||
|
||||
/**
|
||||
* Retrieves the custom links added by the super admin
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return array
|
||||
*/
|
||||
public function get_user_custom_links() {
|
||||
|
||||
$treated_lines = array();
|
||||
|
||||
$saved_links = wu_get_setting('jumper_custom_links');
|
||||
|
||||
$lines = explode(PHP_EOL, (string) $saved_links);
|
||||
|
||||
foreach ($lines as $line) {
|
||||
|
||||
$link_elements = explode(':', $line, 2);
|
||||
|
||||
if (count($link_elements) === 2) {
|
||||
|
||||
$title = trim($link_elements[1]);
|
||||
|
||||
$treated_lines[$title] = trim($link_elements[0]);
|
||||
|
||||
} // end if;
|
||||
|
||||
} // end foreach;
|
||||
|
||||
return $treated_lines;
|
||||
|
||||
} // end get_user_custom_links;
|
||||
|
||||
/**
|
||||
* Add the custom links to the Jumper menu
|
||||
*
|
||||
* @since 2.0.0
|
||||
*
|
||||
* @param array $links Jumper links already saved.
|
||||
* @return array
|
||||
*/
|
||||
public function add_user_custom_links($links) {
|
||||
|
||||
$custom_links = $this->get_user_custom_links();
|
||||
|
||||
if (!empty($custom_links)) {
|
||||
|
||||
$links[__('Custom Links', 'wp-ultimo')] = $custom_links;
|
||||
|
||||
} // end if;
|
||||
|
||||
return $links;
|
||||
|
||||
} // end add_user_custom_links;
|
||||
|
||||
/**
|
||||
* Add WP Ultimo settings links to the Jumper menu.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*
|
||||
* @param array $links WP Ultimo settings array.
|
||||
* @return array
|
||||
*/
|
||||
public function add_wp_ultimo_extra_links($links) {
|
||||
|
||||
if (isset($links['WP Ultimo'])) {
|
||||
|
||||
$settings_tabs = array(
|
||||
'general' => __('General', 'wp-ultimo'),
|
||||
'network' => __('Network Settings', 'wp-ultimo'),
|
||||
'gateways' => __('Payment Gateways', 'wp-ultimo'),
|
||||
'domain_mapping' => __('Domain Mapping & SSL', 'wp-ultimo'),
|
||||
'emails' => __('Emails', 'wp-ultimo'),
|
||||
'styling' => __('Styling', 'wp-ultimo'),
|
||||
'tools' => __('Tools', 'wp-ultimo'),
|
||||
'advanced' => __('Advanced', 'wp-ultimo'),
|
||||
'activation' => __('Activation & Support', 'wp-ultimo'),
|
||||
);
|
||||
|
||||
foreach ($settings_tabs as $tab => $tab_label) {
|
||||
|
||||
$url = network_admin_url('admin.php?page=wp-ultimo-settings&wu-tab=' . $tab);
|
||||
|
||||
// translators: The placeholder represents the title of the Settings tab.
|
||||
$links['WP Ultimo'][$url] = sprintf(__('Settings: %s', 'wp-ultimo'), $tab_label);
|
||||
|
||||
} // end foreach;
|
||||
|
||||
$links['WP Ultimo'][ network_admin_url('admin.php?page=wp-ultimo-settings&wu-tab=tools') ] = __('Settings: Webhooks', 'wp-ultimo');
|
||||
|
||||
$links['WP Ultimo'][ network_admin_url('admin.php?page=wp-ultimo-system-info&wu-tab=logs') ] = __('System Info: Logs', 'wp-ultimo');
|
||||
|
||||
/**
|
||||
* Adds Main Site Dashboard
|
||||
*/
|
||||
if (isset($links[__('Sites')])) {
|
||||
|
||||
$main_site_url = get_admin_url(get_current_site()->blog_id);
|
||||
|
||||
$links[__('Sites')][$main_site_url] = __('Main Site Dashboard', 'wp-ultimo');
|
||||
|
||||
} // end if;
|
||||
|
||||
} // end if;
|
||||
|
||||
return $links;
|
||||
|
||||
} // end add_wp_ultimo_extra_links;
|
||||
/**
|
||||
* Get the trigger key defined by the user.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
function get_defined_trigger_key(): string {
|
||||
|
||||
return substr((string) wu_get_setting('jumper_key', 'g'), 0, 1);
|
||||
|
||||
} // end get_defined_trigger_key;
|
||||
|
||||
/**
|
||||
* Get the trigger key combination depending on the OS
|
||||
*
|
||||
* - For Win & Linux: ctrl + alt + key defined by user;
|
||||
* - For Mac: command + option + key defined by user.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*
|
||||
* @param string $os OS to get the key combination for. Options: win or osx.
|
||||
* @return array
|
||||
*/
|
||||
function get_keys($os = 'win') {
|
||||
|
||||
$trigger_key = $this->get_defined_trigger_key();
|
||||
|
||||
$keys = array(
|
||||
'win' => array('ctrl', 'alt', $trigger_key),
|
||||
'osx' => array('command', 'option', $trigger_key),
|
||||
);
|
||||
|
||||
return isset($keys[$os]) ? $keys[$os] : $keys['win'];
|
||||
|
||||
} // end get_keys;
|
||||
|
||||
/**
|
||||
* Changes the helper footer message about the Jumper and its trigger
|
||||
*
|
||||
* @since 2.0.0
|
||||
*
|
||||
* @param string $text The default WordPress right footer message.
|
||||
* @return string
|
||||
*/
|
||||
public function add_jumper_footer_message($text) {
|
||||
|
||||
if (!wu_get_setting('jumper_display_tip', true)) {
|
||||
|
||||
return $text;
|
||||
|
||||
} // end if;
|
||||
|
||||
$os = stristr((string) $_SERVER['HTTP_USER_AGENT'], 'mac') ? 'osx' : 'win';
|
||||
|
||||
$keys = $this->get_keys($os);
|
||||
|
||||
$html = '';
|
||||
|
||||
foreach ($keys as $key) {
|
||||
|
||||
$html .= '<span class="wu-keys-key">' . $key . '</span>+';
|
||||
|
||||
} // end foreach;
|
||||
|
||||
$html = trim($html, '+');
|
||||
|
||||
// translators: the %s placeholder is the key combination to trigger the Jumper.
|
||||
return '<span class="wu-keys">' . sprintf(__('<strong>Quick Tip:</strong> Use %s to jump between pages.', 'wp-ultimo'), $html) . '</span>' . $text;
|
||||
|
||||
} // end add_jumper_footer_message;
|
||||
|
||||
/**
|
||||
* Enqueues the JavaScript files necessary to make the jumper work.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return void
|
||||
*/
|
||||
public function enqueue_scripts() {
|
||||
|
||||
wp_register_script('wu-mousetrap', wu_get_asset('mousetrap.js', 'js/lib'), array('jquery'), wu_get_version(), true);
|
||||
|
||||
wp_register_script('wu-jumper', wu_get_asset('jumper.js', 'js'), array('jquery', 'wu-selectize', 'wu-mousetrap', 'underscore'), wu_get_version(), true);
|
||||
|
||||
wp_localize_script('wu-jumper', 'wu_jumper_vars', array(
|
||||
'not_found_message' => __('Nothing found for', 'wp-ultimo'),
|
||||
'trigger_key' => $this->get_defined_trigger_key(),
|
||||
'network_base_url' => network_admin_url(),
|
||||
'ajaxurl' => wu_ajax_url(),
|
||||
'base_url' => get_admin_url(get_current_site()->blog_id),
|
||||
));
|
||||
|
||||
wp_enqueue_script('wu-jumper');
|
||||
|
||||
wp_enqueue_style('wu-admin');
|
||||
|
||||
} // end enqueue_scripts;
|
||||
|
||||
/**
|
||||
* Enqueues the CSS files necessary to make the jumper work.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return void
|
||||
*/
|
||||
public function enqueue_styles() {
|
||||
|
||||
wp_enqueue_style('wu-jumper', wu_get_asset('jumper.css', 'css'), array(), wu_get_version());
|
||||
|
||||
} // end enqueue_styles;
|
||||
|
||||
/**
|
||||
* Outputs the actual HTML markup of the Jumper.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return void
|
||||
*/
|
||||
public function output() {
|
||||
|
||||
wu_get_template('ui/jumper', array(
|
||||
'menu_groups' => $this->get_link_list(),
|
||||
));
|
||||
|
||||
} // end output;
|
||||
/**
|
||||
* Get the full page URL for admin pages.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*
|
||||
* @param string $url URL of the menu item.
|
||||
*/
|
||||
public function get_menu_page_url($url): string {
|
||||
|
||||
$final_url = menu_page_url($url, false);
|
||||
|
||||
return str_replace(admin_url(), network_admin_url(), $final_url);
|
||||
|
||||
} // end get_menu_page_url;
|
||||
|
||||
/**
|
||||
* Returns the URL of a jumper menu item
|
||||
*
|
||||
* If the URL is an absolute URL, returns the full-url.
|
||||
* If the URL is relative, we return the full URL using WordPress url functions.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*
|
||||
* @param string $url URL of the menu item.
|
||||
* @return string
|
||||
*/
|
||||
public function get_target_url($url) {
|
||||
|
||||
if (strpos($url, 'http') !== false) {
|
||||
|
||||
return $url;
|
||||
|
||||
} // end if;
|
||||
|
||||
if (strpos($url, '.php') !== false) {
|
||||
|
||||
return network_admin_url($url);
|
||||
|
||||
} // end if;
|
||||
|
||||
return $this->get_menu_page_url($url);
|
||||
|
||||
} // end get_target_url;
|
||||
|
||||
/**
|
||||
* Builds the list of links based on the $menu and $submenu globals.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function build_link_list() {
|
||||
|
||||
return Logger::track_time('jumper', __('Regenerating Jumper menu items', 'wp-ultimo'), function() {
|
||||
|
||||
global $menu, $submenu;
|
||||
|
||||
// This variable is going to carry our options
|
||||
$choices = array();
|
||||
|
||||
// Prevent first run bug
|
||||
if (!is_array($menu) || !is_array($submenu)) {
|
||||
|
||||
return array();
|
||||
|
||||
} // end if;
|
||||
|
||||
// Loop all submenus so que can get our final
|
||||
foreach ($submenu as $menu_name => $submenu_items) {
|
||||
|
||||
$title = $this->search_recursive($menu_name, $menu);
|
||||
|
||||
$string = wu_get_isset($title, 0, '');
|
||||
|
||||
$title = preg_replace('/[0-9]+/', '', strip_tags($string));
|
||||
|
||||
// If parent does not exists, skip
|
||||
if (!empty($title) && is_array($submenu_items)) {
|
||||
|
||||
// We have to loop now each submenu
|
||||
foreach ($submenu_items as $submenu_item) {
|
||||
|
||||
$url = $this->get_target_url($submenu_item[2]);
|
||||
|
||||
// Add to our choices the admin urls
|
||||
$choices[$title][$url] = preg_replace('/[0-9]+/', '', strip_tags((string) $submenu_item[0]));
|
||||
|
||||
} // end foreach;
|
||||
|
||||
} // end if;
|
||||
|
||||
} // end foreach;
|
||||
|
||||
$choices = apply_filters('wu_link_list', $choices);
|
||||
|
||||
set_site_transient($this->transient_key, $choices, 10 * MINUTE_IN_SECONDS);
|
||||
|
||||
return $choices;
|
||||
|
||||
});
|
||||
|
||||
} // end build_link_list;
|
||||
|
||||
/**
|
||||
* Gets the cached menu list saved.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return array
|
||||
*/
|
||||
public function get_saved_menu() {
|
||||
|
||||
$saved_menu = get_site_transient($this->transient_key);
|
||||
|
||||
return $saved_menu ? $saved_menu : array();
|
||||
|
||||
} // end get_saved_menu;
|
||||
|
||||
/**
|
||||
* Returns the link list.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return array
|
||||
*/
|
||||
public function get_link_list() {
|
||||
|
||||
$should_rebuild_menu = !get_site_transient($this->transient_key);
|
||||
|
||||
return $should_rebuild_menu && is_network_admin() ? $this->build_link_list() : $this->get_saved_menu();
|
||||
|
||||
} // end get_link_list;
|
||||
|
||||
/**
|
||||
* Filter the WP Ultimo settings to add Jumper options
|
||||
*
|
||||
* @since 2.0.0
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function add_settings() {
|
||||
|
||||
wu_register_settings_section('tools', array(
|
||||
'title' => __('Tools', 'wp-ultimo'),
|
||||
'desc' => __('Tools', 'wp-ultimo'),
|
||||
'icon' => 'dashicons-wu-tools',
|
||||
));
|
||||
|
||||
wu_register_settings_field('tools', 'tools_header', array(
|
||||
'title' => __('Jumper', 'wp-ultimo'),
|
||||
'desc' => __('Spotlight-like search bar that allows you to easily access everything on your network.', 'wp-ultimo'),
|
||||
'type' => 'header',
|
||||
));
|
||||
|
||||
wu_register_settings_field('tools', 'enable_jumper', array(
|
||||
'title' => __('Enable Jumper', 'wp-ultimo'),
|
||||
'desc' => __('Turn this option on to make the Jumper available on your network.', 'wp-ultimo'),
|
||||
'type' => 'toggle',
|
||||
'default' => 1,
|
||||
));
|
||||
|
||||
wu_register_settings_field('tools', 'jumper_key', array(
|
||||
'title' => __('Trigger Key', 'wp-ultimo'),
|
||||
'desc' => __('Change the keyboard key used in conjunction with ctrl + alt (or cmd + option), to trigger the Jumper box.', 'wp-ultimo'),
|
||||
'type' => 'text',
|
||||
'default' => 'g',
|
||||
'require' => array(
|
||||
'enable_jumper' => 1,
|
||||
),
|
||||
));
|
||||
|
||||
wu_register_settings_field('tools', 'jumper_custom_links', array(
|
||||
'title' => __('Custom Links', 'wp-ultimo'),
|
||||
'desc' => __('Use this textarea to add custom links to the Jumper. Add one per line, with the format "Title : url".', 'wp-ultimo'),
|
||||
'placeholder' => __('Tile of Custom Link : http://link.com', 'wp-ultimo'),
|
||||
'type' => 'textarea',
|
||||
'html_attr' => array(
|
||||
'rows' => 4,
|
||||
),
|
||||
'require' => array(
|
||||
'enable_jumper' => 1,
|
||||
),
|
||||
));
|
||||
|
||||
} // end add_settings;
|
||||
|
||||
/**
|
||||
* Helper function to recursively seach an array.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*
|
||||
* @param string $needle String to seach recursively.
|
||||
* @param array $haystack Array to search.
|
||||
* @return mixed
|
||||
*/
|
||||
public function search_recursive($needle, $haystack) {
|
||||
|
||||
foreach ($haystack as $key => $value) {
|
||||
|
||||
$current_key = $key;
|
||||
|
||||
if ($needle === $value || (is_array($value) && $this->search_recursive($needle, $value) !== false)) {
|
||||
|
||||
return $value;
|
||||
|
||||
} // end if;
|
||||
|
||||
} // end foreach;
|
||||
|
||||
return false;
|
||||
|
||||
} // end search_recursive;
|
||||
|
||||
} // end class Jumper;
|
283
inc/ui/class-limits-element.php
Normal file
283
inc/ui/class-limits-element.php
Normal file
@ -0,0 +1,283 @@
|
||||
<?php
|
||||
/**
|
||||
* Adds the Limnits and Quotas element as BB, Elementor and Widget.
|
||||
*
|
||||
* @package WP_Ultimo
|
||||
* @subpackage UI
|
||||
* @since 2.0.0
|
||||
*/
|
||||
|
||||
namespace WP_Ultimo\UI;
|
||||
|
||||
use \WP_Ultimo\UI\Base_Element;
|
||||
|
||||
// Exit if accessed directly
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
/**
|
||||
* Adds the Limits and Quotas element as BB, Elementor and Widget.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
class Limits_Element extends Base_Element {
|
||||
|
||||
use \WP_Ultimo\Traits\Singleton;
|
||||
|
||||
/**
|
||||
* The id of the element.
|
||||
*
|
||||
* Something simple, without prefixes, like 'checkout', or 'pricing-tables'.
|
||||
*
|
||||
* This is used to construct shortcodes by prefixing the id with 'wu_'
|
||||
* e.g. an id checkout becomes the shortcode 'wu_checkout' and
|
||||
* to generate the Gutenberg block by prefixing it with 'wp-ultimo/'
|
||||
* e.g. checkout would become the block 'wp-ultimo/checkout'.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @var string
|
||||
*/
|
||||
public $id = 'limits';
|
||||
|
||||
/**
|
||||
* Controls if this is a public element to be used in pages/shortcodes by user.
|
||||
*
|
||||
* @since 2.0.24
|
||||
* @var boolean
|
||||
*/
|
||||
protected $public = true;
|
||||
|
||||
/**
|
||||
* The current site.
|
||||
*
|
||||
* @since 2.2.0
|
||||
* @var \WP_Ultimo\Models\Site
|
||||
*/
|
||||
protected $site;
|
||||
|
||||
/**
|
||||
* The icon of the UI element.
|
||||
* e.g. return fa fa-search
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @param string $context One of the values: block, elementor or bb.
|
||||
*/
|
||||
public function get_icon($context = 'block'): string {
|
||||
|
||||
if ($context === 'elementor') {
|
||||
|
||||
return 'eicon-skill-bar';
|
||||
|
||||
} // end if;
|
||||
|
||||
return 'fa fa-search';
|
||||
|
||||
} // end get_icon;
|
||||
|
||||
/**
|
||||
* The title of the UI element.
|
||||
*
|
||||
* This is used on the Blocks list of Gutenberg.
|
||||
* You should return a string with the localized title.
|
||||
* e.g. return __('My Element', 'wp-ultimo').
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return string
|
||||
*/
|
||||
public function get_title() {
|
||||
|
||||
return __('Limits & Quotas', 'wp-ultimo');
|
||||
|
||||
} // end get_title;
|
||||
|
||||
/**
|
||||
* The description of the UI element.
|
||||
*
|
||||
* This is also used on the Gutenberg block list
|
||||
* to explain what this block is about.
|
||||
* You should return a string with the localized title.
|
||||
* e.g. return __('Adds a checkout form to the page', 'wp-ultimo').
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return string
|
||||
*/
|
||||
public function get_description() {
|
||||
|
||||
return __('Adds a checkout form block to the page.', 'wp-ultimo');
|
||||
|
||||
} // end get_description;
|
||||
|
||||
/**
|
||||
* The list of fields to be added to Gutenberg.
|
||||
*
|
||||
* If you plan to add Gutenberg controls to this block,
|
||||
* you'll need to return an array of fields, following
|
||||
* our fields interface (@see inc/ui/class-field.php).
|
||||
*
|
||||
* You can create new Gutenberg panels by adding fields
|
||||
* with the type 'header'. See the Checkout Elements for reference.
|
||||
*
|
||||
* @see inc/ui/class-checkout-element.php
|
||||
*
|
||||
* Return an empty array if you don't have controls to add.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return array
|
||||
*/
|
||||
public function fields() {
|
||||
|
||||
$fields = array();
|
||||
|
||||
$fields['header'] = array(
|
||||
'title' => __('General', 'wp-ultimo'),
|
||||
'desc' => __('General', 'wp-ultimo'),
|
||||
'type' => 'header',
|
||||
);
|
||||
|
||||
$fields['title'] = array(
|
||||
'type' => 'text',
|
||||
'title' => __('Title', 'wp-ultimo'),
|
||||
'value' => __('Site Limits', 'wp-ultimo'),
|
||||
'desc' => __('Leave blank to hide the title completely.', 'wp-ultimo'),
|
||||
'tooltip' => '',
|
||||
);
|
||||
|
||||
$fields['columns'] = array(
|
||||
'type' => 'number',
|
||||
'title' => __('Columns', 'wp-ultimo'),
|
||||
'desc' => __('How many columns to use.', 'wp-ultimo'),
|
||||
'tooltip' => '',
|
||||
'value' => 1,
|
||||
'min' => 1,
|
||||
'max' => 10,
|
||||
);
|
||||
|
||||
return $fields;
|
||||
|
||||
} // end fields;
|
||||
|
||||
/**
|
||||
* The list of keywords for this element.
|
||||
*
|
||||
* Return an array of strings with keywords describing this
|
||||
* element. Gutenberg uses this to help customers find blocks.
|
||||
*
|
||||
* e.g.:
|
||||
* return array(
|
||||
* 'WP Ultimo',
|
||||
* 'Checkout',
|
||||
* 'Form',
|
||||
* 'Cart',
|
||||
* );
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return array
|
||||
*/
|
||||
public function keywords() {
|
||||
|
||||
return array(
|
||||
'WP Ultimo',
|
||||
'Account',
|
||||
'Limits',
|
||||
'Quotas',
|
||||
);
|
||||
|
||||
} // end keywords;
|
||||
|
||||
/**
|
||||
* List of default parameters for the element.
|
||||
*
|
||||
* If you are planning to add controls using the fields,
|
||||
* it might be a good idea to use this method to set defaults
|
||||
* for the parameters you are expecting.
|
||||
*
|
||||
* These defaults will be used inside a 'wp_parse_args' call
|
||||
* before passing the parameters down to the block render
|
||||
* function and the shortcode render function.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return array
|
||||
*/
|
||||
public function defaults() {
|
||||
|
||||
return array(
|
||||
'columns' => 1,
|
||||
'title' => __('Site Limits', 'wp-ultimo'),
|
||||
);
|
||||
|
||||
} // end defaults;
|
||||
|
||||
/**
|
||||
* Runs early on the request lifecycle as soon as we detect the shortcode is present.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return void
|
||||
*/
|
||||
public function setup() {
|
||||
|
||||
$this->site = WP_Ultimo()->currents->get_site();
|
||||
|
||||
if (!$this->site || !$this->site->is_customer_allowed()) {
|
||||
|
||||
$this->set_display(false);
|
||||
|
||||
} // end if;
|
||||
|
||||
} // end setup;
|
||||
|
||||
/**
|
||||
* Allows the setup in the context of previews.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return void
|
||||
*/
|
||||
public function setup_preview() {
|
||||
|
||||
$this->site = wu_mock_site();
|
||||
|
||||
} // end setup_preview;
|
||||
|
||||
/**
|
||||
* The content to be output on the screen.
|
||||
*
|
||||
* Should return HTML markup to be used to display the block.
|
||||
* This method is shared between the block render method and
|
||||
* the shortcode implementation.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*
|
||||
* @param array $atts Parameters of the block/shortcode.
|
||||
* @param string|null $content The content inside the shortcode.
|
||||
* @return string
|
||||
*/
|
||||
public function output($atts, $content = null) {
|
||||
|
||||
$post_types = get_post_types(array(
|
||||
'public' => true,
|
||||
), 'objects');
|
||||
|
||||
/*
|
||||
* Remove post types that where disabled or that are not available for display.
|
||||
*/
|
||||
$post_types = array_filter($post_types, fn($post_type_slug) => $this->site->get_limitations()->post_types->{$post_type_slug}->enabled, ARRAY_FILTER_USE_KEY);
|
||||
|
||||
/**
|
||||
* Allow developers to select which post types should be displayed.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @param array $post_types List of post types.
|
||||
* @return array New list.
|
||||
*/
|
||||
$post_types = apply_filters('wu_get_post_types', $post_types);
|
||||
|
||||
$items_to_display = wu_get_setting('limits_and_quotas');
|
||||
|
||||
$atts['site'] = $this->site;
|
||||
$atts['post_types'] = $post_types;
|
||||
$atts['items_to_display'] = $items_to_display ? array_keys($items_to_display) : false;
|
||||
$atts['post_type_limits'] = $this->site->get_limitations()->post_types;
|
||||
|
||||
return wu_get_template_contents('dashboard-widgets/limits-and-quotas', $atts);
|
||||
|
||||
} // end output;
|
||||
|
||||
} // end class Limits_Element;
|
876
inc/ui/class-login-form-element.php
Normal file
876
inc/ui/class-login-form-element.php
Normal file
@ -0,0 +1,876 @@
|
||||
<?php
|
||||
/**
|
||||
* Adds the Login Form Element UI to the Admin Panel.
|
||||
*
|
||||
* @package WP_Ultimo
|
||||
* @subpackage UI
|
||||
* @since 2.0.0
|
||||
*/
|
||||
|
||||
namespace WP_Ultimo\UI;
|
||||
|
||||
use \WP_Ultimo\UI\Base_Element;
|
||||
use \WP_Ultimo\Checkout\Checkout_Pages;
|
||||
|
||||
// Exit if accessed directly
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
/**
|
||||
* Adds the Checkout Element UI to the Admin Panel.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
class Login_Form_Element extends Base_Element {
|
||||
|
||||
use \WP_Ultimo\Traits\Singleton;
|
||||
|
||||
/**
|
||||
* The id of the element.
|
||||
*
|
||||
* Something simple, without prefixes, like 'checkout', or 'pricing-tables'.
|
||||
*
|
||||
* This is used to construct shortcodes by prefixing the id with 'wu_'
|
||||
* e.g. an id checkout becomes the shortcode 'wu_checkout' and
|
||||
* to generate the Gutenberg block by prefixing it with 'wp-ultimo/'
|
||||
* e.g. checkout would become the block 'wp-ultimo/checkout'.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @var string
|
||||
*/
|
||||
public $id = 'login-form';
|
||||
|
||||
/**
|
||||
* Controls if this is a public element to be used in pages/shortcodes by user.
|
||||
*
|
||||
* @since 2.0.24
|
||||
* @var bool
|
||||
*/
|
||||
protected $public = true;
|
||||
|
||||
/**
|
||||
* If the current user is logged in.
|
||||
*
|
||||
* @since 2.2.0
|
||||
* @var bool
|
||||
*/
|
||||
protected $logged;
|
||||
|
||||
/**
|
||||
* Initializes the singleton.
|
||||
*
|
||||
* @since 2.0.11
|
||||
* @return void
|
||||
*/
|
||||
public function init() {
|
||||
|
||||
// Handle login redirection
|
||||
add_filter('login_redirect', array($this, 'handle_redirect'), -1, 3);
|
||||
|
||||
parent::init();
|
||||
|
||||
} // end init;
|
||||
|
||||
/**
|
||||
* The icon of the UI element.
|
||||
* e.g. return fa fa-search
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @param string $context One of the values: block, elementor or bb.
|
||||
*/
|
||||
public function get_icon($context = 'block'): string {
|
||||
|
||||
if ($context === 'elementor') {
|
||||
|
||||
return 'eicon-lock-user';
|
||||
|
||||
} // end if;
|
||||
|
||||
return 'fa fa-search';
|
||||
|
||||
} // end get_icon;
|
||||
|
||||
/**
|
||||
* The title of the UI element.
|
||||
*
|
||||
* This is used on the Blocks list of Gutenberg.
|
||||
* You should return a string with the localized title.
|
||||
* e.g. return __('My Element', 'wp-ultimo').
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return string
|
||||
*/
|
||||
public function get_title() {
|
||||
|
||||
return __('Login Form', 'wp-ultimo');
|
||||
|
||||
} // end get_title;
|
||||
|
||||
/**
|
||||
* The description of the UI element.
|
||||
*
|
||||
* This is also used on the Gutenberg block list
|
||||
* to explain what this block is about.
|
||||
* You should return a string with the localized title.
|
||||
* e.g. return __('Adds a checkout form to the page', 'wp-ultimo').
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return string
|
||||
*/
|
||||
public function get_description() {
|
||||
|
||||
return __('Adds a login form to the page.', 'wp-ultimo');
|
||||
|
||||
} // end get_description;
|
||||
|
||||
/**
|
||||
* The list of fields to be added to Gutenberg.
|
||||
*
|
||||
* If you plan to add Gutenberg controls to this block,
|
||||
* you'll need to return an array of fields, following
|
||||
* our fields interface (@see inc/ui/class-field.php).
|
||||
*
|
||||
* You can create new Gutenberg panels by adding fields
|
||||
* with the type 'header'. See the Checkout Elements for reference.
|
||||
*
|
||||
* @see inc/ui/class-checkout-element.php
|
||||
*
|
||||
* Return an empty array if you don't have controls to add.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return array
|
||||
*/
|
||||
public function fields() {
|
||||
|
||||
$fields = array();
|
||||
|
||||
$fields['header'] = array(
|
||||
'title' => __('General', 'wp-ultimo'),
|
||||
'desc' => __('General', 'wp-ultimo'),
|
||||
'type' => 'header',
|
||||
);
|
||||
|
||||
$fields['display_title'] = array(
|
||||
'type' => 'toggle',
|
||||
'title' => __('Display Title?', 'wp-ultimo'),
|
||||
'desc' => __('Toggle to show/hide the title element.', 'wp-ultimo'),
|
||||
'tooltip' => '',
|
||||
'value' => 1,
|
||||
);
|
||||
|
||||
$fields['title'] = array(
|
||||
'type' => 'text',
|
||||
'title' => __('Title', 'wp-ultimo'),
|
||||
'value' => __('Login', 'wp-ultimo'),
|
||||
'desc' => '',
|
||||
'tooltip' => '',
|
||||
'required' => array(
|
||||
'display_title' => 1,
|
||||
),
|
||||
);
|
||||
|
||||
$fields['redirect_type'] = array(
|
||||
'type' => 'select',
|
||||
'title' => __('Redirect Type', 'wp-ultimo'),
|
||||
'desc' => __('The behavior after login', 'wp-ultimo'),
|
||||
'tooltip' => '',
|
||||
'default' => 'default',
|
||||
'options' => array(
|
||||
'default' => __('Wordpress Default', 'wp-ultimo'),
|
||||
'customer_site' => __('Send To Customer Site', 'wp-ultimo'),
|
||||
'main_site' => __('Send To Main Site', 'wp-ultimo'),
|
||||
),
|
||||
);
|
||||
|
||||
$fields['customer_redirect_path'] = array(
|
||||
'type' => 'text',
|
||||
'title' => __('Customer Redirect Path', 'wp-ultimo'),
|
||||
'value' => __('/wp-admin', 'wp-ultimo'),
|
||||
'desc' => __('e.g. /wp-admin', 'wp-ultimo'),
|
||||
'tooltip' => '',
|
||||
'required' => array(
|
||||
'redirect_type' => 'customer_site',
|
||||
),
|
||||
);
|
||||
|
||||
$fields['main_redirect_path'] = array(
|
||||
'type' => 'text',
|
||||
'title' => __('Main Site Redirect Path', 'wp-ultimo'),
|
||||
'value' => __('/wp-admin', 'wp-ultimo'),
|
||||
'desc' => __('e.g. /wp-admin', 'wp-ultimo'),
|
||||
'tooltip' => '',
|
||||
'required' => array(
|
||||
'redirect_type' => 'main_site',
|
||||
),
|
||||
);
|
||||
|
||||
$fields['header_username'] = array(
|
||||
'title' => __('Username Field', 'wp-ultimo'),
|
||||
'desc' => __('Username Field', 'wp-ultimo'),
|
||||
'type' => 'header',
|
||||
);
|
||||
|
||||
$fields['label_username'] = array(
|
||||
'type' => 'text',
|
||||
'title' => __('Username Field Label', 'wp-ultimo'),
|
||||
'value' => __('Username or Email Address', 'wp-ultimo'),
|
||||
'desc' => __('Leave blank to hide.', 'wp-ultimo'),
|
||||
'tooltip' => '',
|
||||
);
|
||||
|
||||
$fields['placeholder_username'] = array(
|
||||
'type' => 'text',
|
||||
'title' => __('Username Field Placeholder', 'wp-ultimo'),
|
||||
'desc' => __('e.g. Username Here', 'wp-ultimo'),
|
||||
'value' => '',
|
||||
'tooltip' => '',
|
||||
);
|
||||
|
||||
$fields['header_password'] = array(
|
||||
'title' => __('Password Field', 'wp-ultimo'),
|
||||
'desc' => __('Password Field', 'wp-ultimo'),
|
||||
'type' => 'header',
|
||||
);
|
||||
|
||||
$fields['label_password'] = array(
|
||||
'type' => 'text',
|
||||
'title' => __('Password Field Label', 'wp-ultimo'),
|
||||
'value' => __('Password', 'wp-ultimo'),
|
||||
'desc' => __('Leave blank to hide.', 'wp-ultimo'),
|
||||
'tooltip' => '',
|
||||
);
|
||||
|
||||
$fields['placeholder_password'] = array(
|
||||
'type' => 'text',
|
||||
'title' => __('Password Field Placeholder', 'wp-ultimo'),
|
||||
'desc' => __('e.g. Your Password', 'wp-ultimo'),
|
||||
'value' => '',
|
||||
'tooltip' => '',
|
||||
);
|
||||
|
||||
$fields['header_remember'] = array(
|
||||
'title' => __('Remember Me', 'wp-ultimo'),
|
||||
'desc' => __('Remember Me', 'wp-ultimo'),
|
||||
'type' => 'header',
|
||||
);
|
||||
|
||||
$fields['remember'] = array(
|
||||
'type' => 'toggle',
|
||||
'title' => __('Display Remember Toggle?', 'wp-ultimo'),
|
||||
'desc' => __('Toggle to show/hide the remember me checkbox.', 'wp-ultimo'),
|
||||
'tooltip' => '',
|
||||
'value' => 1,
|
||||
);
|
||||
|
||||
$fields['label_remember'] = array(
|
||||
'type' => 'text',
|
||||
'title' => __('Remember Me Label', 'wp-ultimo'),
|
||||
'value' => __('Remember Me'),
|
||||
'desc' => '',
|
||||
'tooltip' => '',
|
||||
'required' => array(
|
||||
'remember' => 1,
|
||||
),
|
||||
);
|
||||
|
||||
$fields['desc_remember'] = array(
|
||||
'type' => 'text',
|
||||
'title' => __('Remember Me Description', 'wp-ultimo'),
|
||||
'value' => __('Keep me logged in for two weeks.', 'wp-ultimo'),
|
||||
'desc' => '',
|
||||
'tooltip' => '',
|
||||
'required' => array(
|
||||
'remember' => 1,
|
||||
),
|
||||
);
|
||||
|
||||
$fields['header_submit'] = array(
|
||||
'title' => __('Submit Button', 'wp-ultimo'),
|
||||
'desc' => __('Submit Button', 'wp-ultimo'),
|
||||
'type' => 'header',
|
||||
);
|
||||
|
||||
$fields['label_log_in'] = array(
|
||||
'type' => 'text',
|
||||
'title' => __('Submit Button Label', 'wp-ultimo'),
|
||||
'value' => __('Log In', 'wp-ultimo'),
|
||||
'tooltip' => '',
|
||||
);
|
||||
|
||||
return $fields;
|
||||
|
||||
} // end fields;
|
||||
|
||||
/**
|
||||
* Registers scripts and styles necessary to render this.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return void
|
||||
*/
|
||||
public function register_scripts() {
|
||||
|
||||
wp_enqueue_style('wu-admin');
|
||||
|
||||
} // end register_scripts;
|
||||
|
||||
/**
|
||||
* The list of keywords for this element.
|
||||
*
|
||||
* Return an array of strings with keywords describing this
|
||||
* element. Gutenberg uses this to help customers find blocks.
|
||||
*
|
||||
* e.g.:
|
||||
* return array(
|
||||
* 'WP Ultimo',
|
||||
* 'Billing_Address',
|
||||
* 'Form',
|
||||
* 'Cart',
|
||||
* );
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return array
|
||||
*/
|
||||
public function keywords() {
|
||||
|
||||
return array(
|
||||
'WP Ultimo',
|
||||
'Login',
|
||||
'Reset Password',
|
||||
);
|
||||
|
||||
} // end keywords;
|
||||
|
||||
/**
|
||||
* List of default parameters for the element.
|
||||
*
|
||||
* If you are planning to add controls using the fields,
|
||||
* it might be a good idea to use this method to set defaults
|
||||
* for the parameters you are expecting.
|
||||
*
|
||||
* These defaults will be used inside a 'wp_parse_args' call
|
||||
* before passing the parameters down to the block render
|
||||
* function and the shortcode render function.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return array
|
||||
*/
|
||||
public function defaults() {
|
||||
|
||||
// Default 'redirect' value takes the user back to the request URI.
|
||||
$redirect_to = wu_get_current_url();
|
||||
|
||||
return array(
|
||||
'display_title' => 1,
|
||||
'title' => __('Login', 'wp-ultimo'),
|
||||
|
||||
'redirect_type' => 'default',
|
||||
'customer_redirect_path' => '/wp-admin',
|
||||
'main_redirect_path' => '/wp-admin',
|
||||
|
||||
'redirect' => $redirect_to,
|
||||
'form_id' => 'loginform',
|
||||
|
||||
'label_username' => __('Username or Email Address'),
|
||||
'placeholder_username' => '',
|
||||
|
||||
'label_password' => __('Password'),
|
||||
'placeholder_password' => '',
|
||||
|
||||
'label_remember' => __('Remember Me'),
|
||||
'desc_remember' => __('Keep me logged in for two weeks.', 'wp-ultimo'),
|
||||
|
||||
'label_log_in' => __('Log In'),
|
||||
|
||||
'id_username' => 'user_login',
|
||||
'id_password' => 'user_pass',
|
||||
'id_remember' => 'rememberme',
|
||||
'id_submit' => 'wp-submit',
|
||||
'remember' => true,
|
||||
'value_username' => '',
|
||||
'value_remember' => false, // Set 'value_remember' to true to default the "Remember me" checkbox to checked.
|
||||
);
|
||||
|
||||
} // end defaults;
|
||||
|
||||
/**
|
||||
* Runs early on the request lifecycle as soon as we detect the shortcode is present.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return void
|
||||
*/
|
||||
public function setup() {
|
||||
|
||||
$this->logged = is_user_logged_in();
|
||||
|
||||
if ($this->is_reset_password_page()) {
|
||||
|
||||
$rp_path = '/';
|
||||
|
||||
$rp_cookie = 'wp-resetpass-' . COOKIEHASH;
|
||||
|
||||
if (isset($_GET['key']) && isset($_GET['login'])) {
|
||||
|
||||
$value = sprintf('%s:%s', wp_unslash($_GET['login']), wp_unslash($_GET['key']));
|
||||
|
||||
setcookie($rp_cookie, $value, 0, $rp_path, (string) COOKIE_DOMAIN, is_ssl(), true);
|
||||
|
||||
wp_safe_redirect(remove_query_arg(array('key', 'login')));
|
||||
|
||||
exit;
|
||||
|
||||
} // end if;
|
||||
|
||||
} // end if;
|
||||
|
||||
global $post;
|
||||
|
||||
/*
|
||||
* Handles maintenance mode on Elementor.
|
||||
*/
|
||||
if ($post && $post->ID === absint(wu_get_setting('default_login_page', 0))) {
|
||||
|
||||
add_filter('elementor/maintenance_mode/is_login_page', '__return_true');
|
||||
|
||||
} // end if;
|
||||
|
||||
} // end setup;
|
||||
|
||||
/**
|
||||
* Checks if we are in a lost password form page.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return boolean
|
||||
*/
|
||||
public function is_lost_password_page() {
|
||||
|
||||
return wu_request('action') === 'lostpassword';
|
||||
|
||||
} // end is_lost_password_page;
|
||||
|
||||
/**
|
||||
* Checks if we are in the email confirm instruction page of a reset password.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return boolean
|
||||
*/
|
||||
public function is_check_email_confirm() {
|
||||
|
||||
return wu_request('checkemail') === 'confirm';
|
||||
|
||||
} // end is_check_email_confirm;
|
||||
|
||||
/**
|
||||
* Checks if we are in a reset password page.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return boolean
|
||||
*/
|
||||
public function is_reset_password_page() {
|
||||
|
||||
return wu_request('action') === 'rp' || wu_request('action') === 'resetpass';
|
||||
|
||||
} // end is_reset_password_page;
|
||||
|
||||
/**
|
||||
* Checks if we are in the the password rest confirmation page.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return boolean
|
||||
*/
|
||||
public function is_reset_confirmation_page() {
|
||||
|
||||
return wu_request('password-reset') === 'success';
|
||||
|
||||
} // end is_reset_confirmation_page;
|
||||
|
||||
/**
|
||||
* Handle custom login redirection
|
||||
*
|
||||
* @since 2.0.11
|
||||
*
|
||||
* @param string $redirect_to The redirect destination URL.
|
||||
* @param string $requested_redirect_to The requested redirect destination URL.
|
||||
* @param /WP_User|/WP_Error $user The URL to redirect user.
|
||||
* @return string
|
||||
*/
|
||||
public function handle_redirect($redirect_to, $requested_redirect_to, $user) {
|
||||
|
||||
if (is_wp_error($user)) {
|
||||
|
||||
if (wu_request('wu_login_page_url')) {
|
||||
|
||||
$redirect_to = wu_request('wu_login_page_url');
|
||||
$redirect_to = add_query_arg('error', $user->get_error_code(), $redirect_to);
|
||||
|
||||
if ($user->get_error_code() === 'invalid_username') {
|
||||
|
||||
$redirect_to = add_query_arg('username', wu_request('log'), $redirect_to);
|
||||
|
||||
} // end if;
|
||||
|
||||
// In this case, WP will not redirect, so we need to do it here
|
||||
wp_redirect($redirect_to);
|
||||
|
||||
exit;
|
||||
|
||||
} // end if;
|
||||
|
||||
return $redirect_to;
|
||||
|
||||
} // end if;
|
||||
|
||||
$redirect_type = wu_request('wu_login_form_redirect_type', 'default');
|
||||
|
||||
// If some condition match, force user redirection to the URL
|
||||
if ($redirect_type === 'query_redirect') {
|
||||
|
||||
// query_redirect is the default wp behaviour
|
||||
return $redirect_to;
|
||||
|
||||
} elseif ($redirect_type === 'customer_site') {
|
||||
|
||||
$user_site = get_active_blog_for_user( $user->ID );
|
||||
|
||||
wp_redirect($user_site->siteurl . $requested_redirect_to);
|
||||
exit;
|
||||
|
||||
} elseif ($redirect_type === 'main_site') {
|
||||
|
||||
wp_redirect(network_site_url($requested_redirect_to));
|
||||
exit;
|
||||
|
||||
} // end if;
|
||||
|
||||
return $redirect_to;
|
||||
|
||||
} // end handle_redirect;
|
||||
|
||||
/**
|
||||
* Allows the setup in the context of previews.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return void
|
||||
*/
|
||||
public function setup_preview() {
|
||||
|
||||
$this->logged = false;
|
||||
|
||||
} // end setup_preview;
|
||||
|
||||
/**
|
||||
* Returns the logout URL for the "not you bar".
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return string
|
||||
*/
|
||||
public function get_logout_url() {
|
||||
|
||||
$redirect_to = wu_get_current_url();
|
||||
|
||||
return wp_logout_url($redirect_to);
|
||||
|
||||
} // end get_logout_url;
|
||||
|
||||
/**
|
||||
* The content to be output on the screen.
|
||||
*
|
||||
* Should return HTML markup to be used to display the block.
|
||||
* This method is shared between the block render method and
|
||||
* the shortcode implementation.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*
|
||||
* @param array $atts Parameters of the block/shortcode.
|
||||
* @param string|null $content The content inside the shortcode.
|
||||
* @return string
|
||||
*/
|
||||
public function output($atts, $content = null) {
|
||||
|
||||
$view = 'dashboard-widgets/login-additional-forms';
|
||||
|
||||
/*
|
||||
* Checks if we are in the confirmation page.
|
||||
*
|
||||
* If that's the case, we show a successful message and the
|
||||
* login URL so the user can re-login with the new password.
|
||||
*/
|
||||
if ($this->is_reset_confirmation_page()) {
|
||||
|
||||
$fields = array(
|
||||
'email-activation-instructions' => array(
|
||||
'type' => 'note',
|
||||
'desc' => __('Your password has been reset.') . ' <a href="' . esc_url(wp_login_url()) . '">' . __('Log in') . '</a>',
|
||||
),
|
||||
);
|
||||
|
||||
/*
|
||||
* Check if are in the email confirmation instructions page.
|
||||
*
|
||||
* If that's the case, we show the instructions.
|
||||
*/
|
||||
} elseif ($this->is_check_email_confirm()) {
|
||||
|
||||
$fields = array(
|
||||
'email-activation-instructions' => array(
|
||||
'type' => 'note',
|
||||
'desc' => sprintf(
|
||||
/* translators: %s: Link to the login page. */
|
||||
__('Check your email for the confirmation link, then visit the <a href="%s">login page</a>.'),
|
||||
wp_login_url()
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
/*
|
||||
* Check if we are in the set new password page.
|
||||
*
|
||||
* If that's the case, we show the new password fields
|
||||
* so the user can set a new password.
|
||||
*/
|
||||
} elseif ($this->is_reset_password_page()) {
|
||||
|
||||
$rp_cookie = 'wp-resetpass-' . COOKIEHASH;
|
||||
|
||||
if (isset($_COOKIE[$rp_cookie]) && 0 < strpos((string) $_COOKIE[$rp_cookie], ':')) {
|
||||
|
||||
list($rp_login, $rp_key) = explode(':', wp_unslash($_COOKIE[$rp_cookie]), 2);
|
||||
|
||||
$user = check_password_reset_key($rp_key, $rp_login);
|
||||
|
||||
if (isset($_POST['pass1']) && !hash_equals($rp_key, $_POST['rp_key'])) {
|
||||
|
||||
$user = false;
|
||||
|
||||
} // end if;
|
||||
|
||||
} else {
|
||||
|
||||
$user = false;
|
||||
|
||||
} // end if;
|
||||
|
||||
$redirect_to = add_query_arg('password-reset', 'success', remove_query_arg(array('action', 'error')));
|
||||
|
||||
$fields = array(
|
||||
'pass1' => array(
|
||||
'type' => 'password',
|
||||
'title' => __('New password'),
|
||||
'placeholder' => '',
|
||||
'value' => '',
|
||||
'html_attr' => array(
|
||||
'size' => 24,
|
||||
'autocapitalize' => 'off',
|
||||
),
|
||||
),
|
||||
'pass2' => array(
|
||||
'type' => 'password',
|
||||
'title' => __('Confirm new password'),
|
||||
'placeholder' => '',
|
||||
'value' => '',
|
||||
'html_attr' => array(
|
||||
'size' => 24,
|
||||
'autocapitalize' => 'off',
|
||||
),
|
||||
),
|
||||
'lost-password-instructions' => array(
|
||||
'type' => 'note',
|
||||
'desc' => wp_get_password_hint(),
|
||||
'tooltip' => '',
|
||||
),
|
||||
'action' => array(
|
||||
'type' => 'hidden',
|
||||
'value' => 'resetpass',
|
||||
),
|
||||
'rp_key' => array(
|
||||
'type' => 'hidden',
|
||||
'value' => $rp_key,
|
||||
),
|
||||
'user_login' => array(
|
||||
'type' => 'hidden',
|
||||
'value' => $rp_login,
|
||||
),
|
||||
'redirect_to' => array(
|
||||
'type' => 'hidden',
|
||||
'value' => $redirect_to,
|
||||
),
|
||||
'wp-submit' => array(
|
||||
'type' => 'submit',
|
||||
'title' => __('Save Password'),
|
||||
'value' => __('Save Password'),
|
||||
'classes' => 'button button-primary wu-w-full',
|
||||
'wrapper_classes' => 'wu-items-end wu-bg-none',
|
||||
),
|
||||
);
|
||||
|
||||
/*
|
||||
* Checks if we are in the first reset password page, where the customer requests a reset.
|
||||
*
|
||||
* If that's the case, we show the username/email field, so the user can
|
||||
* get an email with the reset link.
|
||||
*/
|
||||
} elseif ($this->is_lost_password_page()) {
|
||||
|
||||
$user_login = wu_request('user_login', '');
|
||||
|
||||
if ($user_login) {
|
||||
|
||||
$user_login = wp_unslash($user_login);
|
||||
|
||||
} // end if;
|
||||
|
||||
$redirect_to = add_query_arg('checkemail', 'confirm', remove_query_arg(array('action', 'error')));
|
||||
|
||||
$fields = array(
|
||||
'lost-password-instructions' => array(
|
||||
'type' => 'note',
|
||||
'desc' => __('Please enter your username or email address. You will receive an email message with instructions on how to reset your password.'),
|
||||
'tooltip' => '',
|
||||
),
|
||||
'user_login' => array(
|
||||
'type' => 'text',
|
||||
'title' => __('Username or Email Address'),
|
||||
'placeholder' => '',
|
||||
'value' => $user_login,
|
||||
'html_attr' => array(
|
||||
'size' => 20,
|
||||
'autocapitalize' => 'off',
|
||||
),
|
||||
),
|
||||
'action' => array(
|
||||
'type' => 'hidden',
|
||||
'value' => 'lostpassword',
|
||||
),
|
||||
'redirect_to' => array(
|
||||
'type' => 'hidden',
|
||||
'value' => $redirect_to,
|
||||
),
|
||||
'wp-submit' => array(
|
||||
'type' => 'submit',
|
||||
'title' => __('Get New Password'),
|
||||
'value' => __('Get New Password'),
|
||||
'classes' => 'button button-primary wu-w-full',
|
||||
'wrapper_classes' => 'wu-items-end wu-bg-none',
|
||||
),
|
||||
);
|
||||
|
||||
} else {
|
||||
|
||||
$view = 'dashboard-widgets/login-form';
|
||||
|
||||
$fields = array(
|
||||
'log' => array(
|
||||
'type' => 'text',
|
||||
'title' => $atts['label_username'],
|
||||
'placeholder' => $atts['placeholder_username'],
|
||||
'tooltip' => '',
|
||||
),
|
||||
'pwd' => array(
|
||||
'type' => 'password',
|
||||
'title' => $atts['label_password'],
|
||||
'placeholder' => $atts['placeholder_password'],
|
||||
'tooltip' => '',
|
||||
),
|
||||
);
|
||||
|
||||
if ($atts['remember']) {
|
||||
|
||||
$fields['rememberme'] = array(
|
||||
'type' => 'toggle',
|
||||
'title' => $atts['label_remember'],
|
||||
'desc' => $atts['desc_remember'],
|
||||
);
|
||||
|
||||
} // end if;
|
||||
|
||||
$fields['redirect_to'] = array(
|
||||
'type' => 'hidden',
|
||||
'value' => $atts['redirect'],
|
||||
);
|
||||
|
||||
if (isset($_GET['redirect_to'])) {
|
||||
|
||||
$atts['redirect_type'] = 'query_redirect';
|
||||
$fields['redirect_to']['value'] = $_GET['redirect_to'];
|
||||
|
||||
} elseif ($atts['redirect_type'] === 'customer_site') {
|
||||
|
||||
$fields['redirect_to']['value'] = $atts['customer_redirect_path'];
|
||||
|
||||
} elseif ($atts['redirect_type'] === 'main_site') {
|
||||
|
||||
$fields['redirect_to']['value'] = $atts['main_redirect_path'];
|
||||
|
||||
} // end if;
|
||||
|
||||
$fields['wu_login_form_redirect_type'] = array(
|
||||
'type' => 'hidden',
|
||||
'value' => $atts['redirect_type'],
|
||||
);
|
||||
|
||||
$fields['wp-submit'] = array(
|
||||
'type' => 'submit',
|
||||
'title' => $atts['label_log_in'],
|
||||
'value' => $atts['label_log_in'],
|
||||
'classes' => 'button button-primary wu-w-full',
|
||||
'wrapper_classes' => 'wu-items-end wu-bg-none',
|
||||
);
|
||||
|
||||
$fields['lost-password'] = array(
|
||||
'type' => 'html',
|
||||
'content' => sprintf('<a class="wu-text-xs wu-block wu-text-center wu--mt-4" href="%s">%s</a>', esc_url(add_query_arg('action', 'lostpassword')), __('Lost your password?')),
|
||||
'classes' => '',
|
||||
'wrapper_classes' => 'wu-items-end wu-bg-none',
|
||||
);
|
||||
|
||||
} // end if;
|
||||
|
||||
/*
|
||||
* Check for error messages
|
||||
*
|
||||
* If we have some, we add an additional field
|
||||
* at the top of the fields array, to display the errors.
|
||||
*/
|
||||
if (wu_request('error')) {
|
||||
|
||||
$username = wu_request('username', '');
|
||||
|
||||
$error_message_field = array(
|
||||
'error_message' => array(
|
||||
'type' => 'note',
|
||||
'desc' => Checkout_Pages::get_instance()->get_error_message(wu_request('error'), $username),
|
||||
),
|
||||
);
|
||||
|
||||
$fields = array_merge($error_message_field, $fields);
|
||||
|
||||
} // end if;
|
||||
|
||||
$fields['wu_login_page_url'] = array(
|
||||
'type' => 'hidden',
|
||||
'value' => wu_get_current_url(),
|
||||
);
|
||||
|
||||
/**
|
||||
* Instantiate the form for the order details.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
$form = new \WP_Ultimo\UI\Form($this->get_id(), $fields, array(
|
||||
'action' => esc_url(site_url('wp-login.php', 'login_post')),
|
||||
'wrap_in_form_tag' => true,
|
||||
'views' => 'admin-pages/fields',
|
||||
'classes' => 'wu-p-0 wu-m-0',
|
||||
'field_wrapper_classes' => 'wu-box-border wu-items-center wu-flex wu-justify-between wu-py-4 wu-m-0',
|
||||
'html_attr' => array(
|
||||
'class' => 'wu-w-full',
|
||||
),
|
||||
));
|
||||
|
||||
$atts['logged'] = $this->logged;
|
||||
$atts['login_url'] = $this->get_logout_url();
|
||||
$atts['form'] = $form;
|
||||
|
||||
return wu_get_template_contents($view, $atts);
|
||||
|
||||
} // end output;
|
||||
|
||||
} // end class Login_Form_Element;
|
493
inc/ui/class-my-sites-element.php
Normal file
493
inc/ui/class-my-sites-element.php
Normal file
@ -0,0 +1,493 @@
|
||||
<?php
|
||||
/**
|
||||
* Adds the My_Sites_Element UI to the Admin Panel.
|
||||
*
|
||||
* @package WP_Ultimo
|
||||
* @subpackage UI
|
||||
* @since 2.0.0
|
||||
*/
|
||||
|
||||
namespace WP_Ultimo\UI;
|
||||
|
||||
use WP_Ultimo\UI\Base_Element;
|
||||
use WP_Ultimo\Models\Customer;
|
||||
|
||||
// Exit if accessed directly
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
/**
|
||||
* Adds the Checkout Element UI to the Admin Panel.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
class My_Sites_Element extends Base_Element {
|
||||
|
||||
use \WP_Ultimo\Traits\Singleton;
|
||||
|
||||
/**
|
||||
* The id of the element.
|
||||
*
|
||||
* Something simple, without prefixes, like 'checkout', or 'pricing-tables'.
|
||||
*
|
||||
* This is used to construct shortcodes by prefixing the id with 'wu_'
|
||||
* e.g. an id checkout becomes the shortcode 'wu_checkout' and
|
||||
* to generate the Gutenberg block by prefixing it with 'wp-ultimo/'
|
||||
* e.g. checkout would become the block 'wp-ultimo/checkout'.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @var string
|
||||
*/
|
||||
public $id = 'my-sites';
|
||||
|
||||
/**
|
||||
* Controls if this is a public element to be used in pages/shortcodes by user.
|
||||
*
|
||||
* @since 2.0.24
|
||||
* @var boolean
|
||||
*/
|
||||
protected $public = true;
|
||||
|
||||
/**
|
||||
* The current customer.
|
||||
*
|
||||
* @since 2.2.0
|
||||
* @var Customer
|
||||
*/
|
||||
protected $customer;
|
||||
|
||||
/**
|
||||
* The sites of the current customer.
|
||||
*
|
||||
* @since 2.2.0
|
||||
* @var array
|
||||
*/
|
||||
protected $sites;
|
||||
|
||||
/**
|
||||
* The icon of the UI element.
|
||||
* e.g. return fa fa-search
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @param string $context One of the values: block, elementor or bb.
|
||||
* @return string
|
||||
*/
|
||||
public function get_icon($context = 'block') {
|
||||
|
||||
if ($context === 'elementor') {
|
||||
|
||||
return 'eicon-info-circle-o';
|
||||
|
||||
} // end if;
|
||||
|
||||
return 'fa fa-search';
|
||||
|
||||
} // end get_icon;
|
||||
|
||||
/**
|
||||
* The title of the UI element.
|
||||
*
|
||||
* This is used on the Blocks list of Gutenberg.
|
||||
* You should return a string with the localized title.
|
||||
* e.g. return __('My Element', 'wp-ultimo').
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return string
|
||||
*/
|
||||
public function get_title() {
|
||||
|
||||
return __('My Sites', 'wp-ultimo');
|
||||
|
||||
} // end get_title;
|
||||
|
||||
/**
|
||||
* The description of the UI element.
|
||||
*
|
||||
* This is also used on the Gutenberg block list
|
||||
* to explain what this block is about.
|
||||
* You should return a string with the localized title.
|
||||
* e.g. return __('Adds a checkout form to the page', 'wp-ultimo').
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return string
|
||||
*/
|
||||
public function get_description() {
|
||||
|
||||
return __('Adds a block to display the sites owned by the current customer.', 'wp-ultimo');
|
||||
|
||||
} // end get_description;
|
||||
|
||||
/**
|
||||
* The list of fields to be added to Gutenberg.
|
||||
*
|
||||
* If you plan to add Gutenberg controls to this block,
|
||||
* you'll need to return an array of fields, following
|
||||
* our fields interface (@see inc/ui/class-field.php).
|
||||
*
|
||||
* You can create new Gutenberg panels by adding fields
|
||||
* with the type 'header'. See the Checkout Elements for reference.
|
||||
*
|
||||
* @see inc/ui/class-checkout-element.php
|
||||
*
|
||||
* Return an empty array if you don't have controls to add.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return array
|
||||
*/
|
||||
public function fields() {
|
||||
|
||||
$fields = array();
|
||||
|
||||
$fields['header'] = array(
|
||||
'title' => __('General', 'wp-ultimo'),
|
||||
'desc' => __('General', 'wp-ultimo'),
|
||||
'type' => 'header',
|
||||
);
|
||||
|
||||
$fields['site_manage_type'] = array(
|
||||
'type' => 'select',
|
||||
'title' => __('Site Manage Type', 'wp-ultimo'),
|
||||
'desc' => __('The page to manage a site.', 'wp-ultimo'),
|
||||
'tooltip' => '',
|
||||
'default' => 'default',
|
||||
'options' => array(
|
||||
'default' => __('Same Page', 'wp-ultimo'),
|
||||
'wp_admin' => __('WP Admin', 'wp-ultimo'),
|
||||
'custom_page' => __('Custom Page', 'wp-ultimo'),
|
||||
),
|
||||
);
|
||||
|
||||
$fields['site_show'] = array(
|
||||
'type' => 'select',
|
||||
'title' => __('Which sites to show?', 'wp-ultimo'),
|
||||
'desc' => __('Select which sites should be listed for user.', 'wp-ultimo'),
|
||||
'tooltip' => '',
|
||||
'default' => 'all',
|
||||
'options' => array(
|
||||
'all' => __('All', 'wp-ultimo'),
|
||||
'owned' => __('Owned', 'wp-ultimo'),
|
||||
),
|
||||
);
|
||||
|
||||
$pages = get_pages(array(
|
||||
'exclude' => array(get_the_ID()),
|
||||
));
|
||||
|
||||
$pages = $pages ? $pages : array();
|
||||
|
||||
$pages_list = array(0 => __('Current Page', 'wp-ultimo'));
|
||||
|
||||
foreach ($pages as $page) {
|
||||
|
||||
$pages_list[$page->ID] = $page->post_title;
|
||||
|
||||
} // end foreach;
|
||||
|
||||
$fields['custom_manage_page'] = array(
|
||||
'type' => 'select',
|
||||
'title' => __('Manage Redirect Page', 'wp-ultimo'),
|
||||
'value' => 0,
|
||||
'desc' => __('The page to redirect user after select a site.', 'wp-ultimo'),
|
||||
'tooltip' => '',
|
||||
'required' => array(
|
||||
'site_manage_type' => 'custom_page',
|
||||
),
|
||||
'options' => $pages_list,
|
||||
);
|
||||
|
||||
$fields['columns'] = array(
|
||||
'type' => 'number',
|
||||
'title' => __('Columns', 'wp-ultimo'),
|
||||
'desc' => __('How many columns to use.', 'wp-ultimo'),
|
||||
'tooltip' => '',
|
||||
'value' => 4,
|
||||
'min' => 1,
|
||||
'max' => 5,
|
||||
);
|
||||
|
||||
$fields['display_images'] = array(
|
||||
'type' => 'toggle',
|
||||
'title' => __('Display Site Screenshot?', 'wp-ultimo'),
|
||||
'desc' => __('Toggle to show/hide the site screenshots on the element.', 'wp-ultimo'),
|
||||
'tooltip' => '',
|
||||
'value' => 1,
|
||||
);
|
||||
|
||||
return $fields;
|
||||
|
||||
} // end fields;
|
||||
|
||||
/**
|
||||
* The list of keywords for this element.
|
||||
*
|
||||
* Return an array of strings with keywords describing this
|
||||
* element. Gutenberg uses this to help customers find blocks.
|
||||
*
|
||||
* e.g.:
|
||||
* return array(
|
||||
* 'WP Ultimo',
|
||||
* 'Site',
|
||||
* 'Form',
|
||||
* 'Cart',
|
||||
* );
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return array
|
||||
*/
|
||||
public function keywords() {
|
||||
|
||||
return array(
|
||||
'WP Ultimo',
|
||||
'Site',
|
||||
'Form',
|
||||
'Cart',
|
||||
);
|
||||
|
||||
} // end keywords;
|
||||
|
||||
/**
|
||||
* List of default parameters for the element.
|
||||
*
|
||||
* If you are planning to add controls using the fields,
|
||||
* it might be a good idea to use this method to set defaults
|
||||
* for the parameters you are expecting.
|
||||
*
|
||||
* These defaults will be used inside a 'wp_parse_args' call
|
||||
* before passing the parameters down to the block render
|
||||
* function and the shortcode render function.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return array
|
||||
*/
|
||||
public function defaults() {
|
||||
|
||||
return array(
|
||||
'columns' => 4,
|
||||
'display_images' => 1,
|
||||
'site_manage_type' => 'default',
|
||||
'custom_manage_page' => 0,
|
||||
'site_show' => 'owned',
|
||||
);
|
||||
|
||||
} // end defaults;
|
||||
|
||||
/**
|
||||
* Loads the necessary scripts and styles for this element.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return void
|
||||
*/
|
||||
public function register_scripts() {
|
||||
|
||||
wp_enqueue_style('wu-admin');
|
||||
|
||||
} // end register_scripts;
|
||||
|
||||
/**
|
||||
* Runs early on the request lifecycle as soon as we detect the shortcode is present.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return void
|
||||
*/
|
||||
public function setup() {
|
||||
|
||||
global $wpdb;
|
||||
|
||||
if (!is_user_logged_in() || WP_Ultimo()->currents->is_site_set_via_request()) {
|
||||
|
||||
$this->set_display(false);
|
||||
|
||||
return;
|
||||
|
||||
} // end if;
|
||||
|
||||
$this->customer = WP_Ultimo()->currents->get_customer();
|
||||
|
||||
} // end setup;
|
||||
|
||||
/**
|
||||
* Allows the setup in the context of previews.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return void
|
||||
*/
|
||||
public function setup_preview() {
|
||||
|
||||
$this->customer = wu_mock_customer();
|
||||
|
||||
$this->sites = array(
|
||||
wu_mock_site(1),
|
||||
wu_mock_site(2),
|
||||
);
|
||||
|
||||
} // end setup_preview;
|
||||
|
||||
/**
|
||||
* The content to be output on the screen.
|
||||
*
|
||||
* Should return HTML markup to be used to display the block.
|
||||
* This method is shared between the block render method and
|
||||
* the shortcode implementation.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*
|
||||
* @param array $atts Parameters of the block/shortcode.
|
||||
* @param string|null $content The content inside the shortcode.
|
||||
* @return string
|
||||
*/
|
||||
public function output($atts, $content = null) {
|
||||
|
||||
$atts['customer'] = $this->customer;
|
||||
|
||||
$atts['sites'] = $this->get_sites(wu_get_isset($atts, 'site_show'));
|
||||
|
||||
return wu_get_template_contents('dashboard-widgets/my-sites', $atts);
|
||||
|
||||
} // end output;
|
||||
|
||||
/**
|
||||
* Get sites to display on widget
|
||||
*
|
||||
* @param string $show The kind of output expected, i.e: all, owned.
|
||||
* @return array $sites The list of sites do display.
|
||||
*/
|
||||
protected function get_sites(?string $show = null): array {
|
||||
|
||||
if (!empty($this->sites)) {
|
||||
|
||||
return $this->sites;
|
||||
|
||||
}
|
||||
|
||||
$this->sites = apply_filters('wp_ultimo_pre_my_sites_sites', array(), $show);
|
||||
|
||||
if (!empty($this->sites)) {
|
||||
|
||||
return $this->sites;
|
||||
|
||||
}
|
||||
|
||||
if (!empty($this->customer)) {
|
||||
|
||||
$pending_sites = \WP_Ultimo\Models\Site::get_all_by_type('pending', array('customer_id' => $this->customer->get_id()));
|
||||
|
||||
$customer_sites = array_reduce(
|
||||
$this->customer->get_sites(),
|
||||
function ($customer_sites, $site) {
|
||||
$customer_sites[$site->get_id()] = $site;
|
||||
return $customer_sites;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
if ($show === 'all') {
|
||||
|
||||
$wp_user_sites = get_blogs_of_user(get_current_user_id());
|
||||
|
||||
$user_sites = array_reduce($wp_user_sites, function($user_sites, $wp_site) use ($customer_sites) {
|
||||
if (!array_key_exists($wp_site->userblog_id, $customer_sites ?? array()) && $wp_site->userblog_id !== get_main_site_id()) {
|
||||
$wu_site = wu_get_site($wp_site->userblog_id);
|
||||
$wu_site->set_membership_id(0);
|
||||
$user_sites[$wp_site->userblog_id] = $wu_site;
|
||||
}
|
||||
return $user_sites;
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
$sites = array_merge(
|
||||
$pending_sites ?? array(),
|
||||
$customer_sites ?? array(),
|
||||
$user_sites ?? array(),
|
||||
);
|
||||
|
||||
$this->sites = apply_filters('wp_ultimo_after_my_sites_sites', $sites, $show);
|
||||
|
||||
return $this->sites;
|
||||
|
||||
} // end get_sites;
|
||||
|
||||
|
||||
/**
|
||||
* Returns the manage URL for sites, depending on the environment.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*
|
||||
* @param int $site_id A Site ID.
|
||||
* @param string $type De redirection type (can be: default, wp_admin or custom_page).
|
||||
* @param string $custom_page_id The path to redirect ir using custom_page type.
|
||||
* @return string
|
||||
*/
|
||||
public function get_manage_url($site_id, $type = 'default', $custom_page_id = 0) {
|
||||
|
||||
if ($type === 'wp_admin') {
|
||||
|
||||
return get_admin_url($site_id);
|
||||
|
||||
} // end if;
|
||||
|
||||
if ($type === 'custom_page') {
|
||||
|
||||
$custom_page = get_page_link($custom_page_id);
|
||||
|
||||
$url_param = \WP_Ultimo\Current::param_key('site');
|
||||
|
||||
$site_hash = \WP_Ultimo\Helpers\Hash::encode($site_id, 'site');
|
||||
|
||||
return add_query_arg(array(
|
||||
$url_param => $site_hash,
|
||||
), $custom_page);
|
||||
|
||||
} // end if;
|
||||
|
||||
return \WP_Ultimo\Current::get_manage_url($site_id, 'site');
|
||||
|
||||
} // end get_manage_url;
|
||||
|
||||
/**
|
||||
* Returns the new site URL for site creation.
|
||||
*
|
||||
* @since 2.0.21
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_new_site_url() {
|
||||
|
||||
$membership = WP_Ultimo()->currents->get_membership();
|
||||
|
||||
$checkout_pages = \WP_Ultimo\Checkout\Checkout_Pages::get_instance();
|
||||
|
||||
$url = $checkout_pages->get_page_url('new_site');
|
||||
|
||||
if ($membership) {
|
||||
|
||||
if ($url) {
|
||||
|
||||
return add_query_arg(array(
|
||||
'membership' => $membership->get_hash(),
|
||||
), $url);
|
||||
|
||||
} // end if;
|
||||
|
||||
if (is_main_site()) {
|
||||
|
||||
$sites = $membership->get_sites(false);
|
||||
|
||||
if (!empty($sites)) {
|
||||
|
||||
return add_query_arg(array(
|
||||
'page' => 'add-new-site',
|
||||
), get_admin_url($sites[0]->get_id()));
|
||||
|
||||
} // end if;
|
||||
|
||||
return '';
|
||||
|
||||
} // end if;
|
||||
|
||||
} // end if;
|
||||
|
||||
return admin_url('admin.php?page=add-new-site');
|
||||
|
||||
} // end get_new_site_url;
|
||||
|
||||
} // end class My_Sites_Element;
|
208
inc/ui/class-payment-methods-element.php
Normal file
208
inc/ui/class-payment-methods-element.php
Normal file
@ -0,0 +1,208 @@
|
||||
<?php
|
||||
/**
|
||||
* Adds the Payment_Methods_Element UI to the Admin Panel.
|
||||
*
|
||||
* @package WP_Ultimo
|
||||
* @subpackage UI
|
||||
* @since 2.0.0
|
||||
*/
|
||||
|
||||
namespace WP_Ultimo\UI;
|
||||
|
||||
use WP_Ultimo\UI\Base_Element;
|
||||
|
||||
// Exit if accessed directly
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
/**
|
||||
* Adds the Checkout Element UI to the Admin Panel.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
class Payment_Methods_Element extends Base_Element {
|
||||
|
||||
use \WP_Ultimo\Traits\Singleton;
|
||||
|
||||
/**
|
||||
* The id of the element.
|
||||
*
|
||||
* Something simple, without prefixes, like 'checkout', or 'pricing-tables'.
|
||||
*
|
||||
* This is used to construct shortcodes by prefixing the id with 'wu_'
|
||||
* e.g. an id checkout becomes the shortcode 'wu_checkout' and
|
||||
* to generate the Gutenberg block by prefixing it with 'wp-ultimo/'
|
||||
* e.g. checkout would become the block 'wp-ultimo/checkout'.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @var string
|
||||
*/
|
||||
public $id = 'payment-methods';
|
||||
|
||||
/**
|
||||
* The icon of the UI element.
|
||||
* e.g. return fa fa-search
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @param string $context One of the values: block, elementor or bb.
|
||||
* @return string
|
||||
*/
|
||||
public function get_icon($context = 'block') {
|
||||
|
||||
if ($context === 'elementor') {
|
||||
|
||||
return 'eicon-info-circle-o';
|
||||
|
||||
} // end if;
|
||||
|
||||
return 'fa fa-search';
|
||||
|
||||
} // end get_icon;
|
||||
|
||||
/**
|
||||
* The title of the UI element.
|
||||
*
|
||||
* This is used on the Blocks list of Gutenberg.
|
||||
* You should return a string with the localized title.
|
||||
* e.g. return __('My Element', 'wp-ultimo').
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return string
|
||||
*/
|
||||
public function get_title() {
|
||||
|
||||
return __('Payment Methods', 'wp-ultimo');
|
||||
|
||||
} // end get_title;
|
||||
|
||||
/**
|
||||
* The description of the UI element.
|
||||
*
|
||||
* This is also used on the Gutenberg block list
|
||||
* to explain what this block is about.
|
||||
* You should return a string with the localized title.
|
||||
* e.g. return __('Adds a checkout form to the page', 'wp-ultimo').
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return string
|
||||
*/
|
||||
public function get_description() {
|
||||
|
||||
return __('Adds a checkout form block to the page.', 'wp-ultimo');
|
||||
|
||||
} // end get_description;
|
||||
|
||||
/**
|
||||
* The list of fields to be added to Gutenberg.
|
||||
*
|
||||
* If you plan to add Gutenberg controls to this block,
|
||||
* you'll need to return an array of fields, following
|
||||
* our fields interface (@see inc/ui/class-field.php).
|
||||
*
|
||||
* You can create new Gutenberg panels by adding fields
|
||||
* with the type 'header'. See the Checkout Elements for reference.
|
||||
*
|
||||
* @see inc/ui/class-checkout-element.php
|
||||
*
|
||||
* Return an empty array if you don't have controls to add.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return array
|
||||
*/
|
||||
public function fields() {
|
||||
|
||||
$fields = array();
|
||||
|
||||
$fields['header'] = array(
|
||||
'title' => __('General', 'wp-ultimo'),
|
||||
'desc' => __('General', 'wp-ultimo'),
|
||||
'type' => 'header',
|
||||
);
|
||||
|
||||
$fields['password_strength'] = array(
|
||||
'type' => 'toggle',
|
||||
'title' => __('Password Strength Meter', 'wp-ultimo'),
|
||||
'desc' => __('Set this customer as a VIP.', 'wp-ultimo'),
|
||||
'tooltip' => '',
|
||||
'value' => 1,
|
||||
);
|
||||
|
||||
$fields['apply_styles'] = array(
|
||||
'type' => 'toggle',
|
||||
'title' => __('Apply Styles', 'wp-ultimo'),
|
||||
'desc' => __('Set this customer as a VIP.', 'wp-ultimo'),
|
||||
'tooltip' => '',
|
||||
'value' => 1,
|
||||
);
|
||||
|
||||
return $fields;
|
||||
|
||||
} // end fields;
|
||||
|
||||
/**
|
||||
* The list of keywords for this element.
|
||||
*
|
||||
* Return an array of strings with keywords describing this
|
||||
* element. Gutenberg uses this to help customers find blocks.
|
||||
*
|
||||
* e.g.:
|
||||
* return array(
|
||||
* 'WP Ultimo',
|
||||
* 'Payment Methods',
|
||||
* 'Form',
|
||||
* 'Cart',
|
||||
* );
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return array
|
||||
*/
|
||||
public function keywords() {
|
||||
|
||||
return array(
|
||||
'WP Ultimo',
|
||||
'Payment Methods',
|
||||
'Form',
|
||||
'Cart',
|
||||
);
|
||||
|
||||
} // end keywords;
|
||||
|
||||
/**
|
||||
* List of default parameters for the element.
|
||||
*
|
||||
* If you are planning to add controls using the fields,
|
||||
* it might be a good idea to use this method to set defaults
|
||||
* for the parameters you are expecting.
|
||||
*
|
||||
* These defaults will be used inside a 'wp_parse_args' call
|
||||
* before passing the parameters down to the block render
|
||||
* function and the shortcode render function.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return array
|
||||
*/
|
||||
public function defaults() {
|
||||
|
||||
return array();
|
||||
|
||||
} // end defaults;
|
||||
|
||||
/**
|
||||
* The content to be output on the screen.
|
||||
*
|
||||
* Should return HTML markup to be used to display the block.
|
||||
* This method is shared between the block render method and
|
||||
* the shortcode implementation.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*
|
||||
* @param array $atts Parameters of the block/shortcode.
|
||||
* @param string|null $content The content inside the shortcode.
|
||||
* @return string
|
||||
*/
|
||||
public function output($atts, $content = null) {
|
||||
|
||||
return 'lol';
|
||||
|
||||
} // end output;
|
||||
|
||||
} // end class Payment_Methods_Element;
|
234
inc/ui/class-simple-text-element.php
Normal file
234
inc/ui/class-simple-text-element.php
Normal file
@ -0,0 +1,234 @@
|
||||
<?php
|
||||
/**
|
||||
* Adds the Simple Text Element UI to the Admin Panel.
|
||||
*
|
||||
* @package WP_Ultimo
|
||||
* @subpackage UI
|
||||
* @since 2.0.0
|
||||
*/
|
||||
|
||||
namespace WP_Ultimo\UI;
|
||||
|
||||
use WP_Ultimo\UI\Base_Element;
|
||||
|
||||
// Exit if accessed directly
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
/**
|
||||
* Adds the Checkout Element UI to the Admin Panel.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
class Simple_Text_Element extends Base_Element {
|
||||
|
||||
use \WP_Ultimo\Traits\Singleton;
|
||||
|
||||
/**
|
||||
* The id of the element.
|
||||
*
|
||||
* Something simple, without prefixes, like 'checkout', or 'pricing-tables'.
|
||||
*
|
||||
* This is used to construct shortcodes by prefixing the id with 'wu_'
|
||||
* e.g. an id checkout becomes the shortcode 'wu_checkout' and
|
||||
* to generate the Gutenberg block by prefixing it with 'wp-ultimo/'
|
||||
* e.g. checkout would become the block 'wp-ultimo/checkout'.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @var string
|
||||
*/
|
||||
public $id = 'simple-text';
|
||||
|
||||
/**
|
||||
* Controls if this is a public element to be used in pages/shortcodes by user.
|
||||
*
|
||||
* @since 2.0.24
|
||||
* @var boolean
|
||||
*/
|
||||
protected $public = true;
|
||||
|
||||
/**
|
||||
* Should this element be hidden by default?
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @var boolean
|
||||
*/
|
||||
protected $hidden_by_default = true;
|
||||
|
||||
/**
|
||||
* The icon of the UI element.
|
||||
* e.g. return fa fa-search
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @param string $context One of the values: block, elementor or bb.
|
||||
* @return string
|
||||
*/
|
||||
public function get_icon($context = 'block') {
|
||||
|
||||
if ($context === 'elementor') {
|
||||
|
||||
return 'eicon-lock-user';
|
||||
|
||||
} // end if;
|
||||
|
||||
return 'fa fa-search';
|
||||
|
||||
} // end get_icon;
|
||||
|
||||
/**
|
||||
* The title of the UI element.
|
||||
*
|
||||
* This is used on the Blocks list of Gutenberg.
|
||||
* You should return a string with the localized title.
|
||||
* e.g. return __('My Element', 'wp-ultimo').
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return string
|
||||
*/
|
||||
public function get_title() {
|
||||
|
||||
return __('Simple Text', 'wp-ultimo');
|
||||
|
||||
} // end get_title;
|
||||
|
||||
/**
|
||||
* The description of the UI element.
|
||||
*
|
||||
* This is also used on the Gutenberg block list
|
||||
* to explain what this block is about.
|
||||
* You should return a string with the localized title.
|
||||
* e.g. return __('Adds a checkout form to the page', 'wp-ultimo').
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return string
|
||||
*/
|
||||
public function get_description() {
|
||||
|
||||
return __('Adds a simple text block to the page.', 'wp-ultimo');
|
||||
|
||||
} // end get_description;
|
||||
|
||||
/**
|
||||
* The list of fields to be added to Gutenberg.
|
||||
*
|
||||
* If you plan to add Gutenberg controls to this block,
|
||||
* you'll need to return an array of fields, following
|
||||
* our fields interface (@see inc/ui/class-field.php).
|
||||
*
|
||||
* You can create new Gutenberg panels by adding fields
|
||||
* with the type 'header'. See the Checkout Elements for reference.
|
||||
*
|
||||
* @see inc/ui/class-checkout-element.php
|
||||
*
|
||||
* Return an empty array if you don't have controls to add.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return array
|
||||
*/
|
||||
public function fields() {
|
||||
|
||||
$fields = array();
|
||||
|
||||
$fields['header'] = array(
|
||||
'title' => __('General', 'wp-ultimo'),
|
||||
'desc' => __('General', 'wp-ultimo'),
|
||||
'type' => 'header',
|
||||
);
|
||||
|
||||
$fields['simple_text'] = array(
|
||||
'type' => 'textarea',
|
||||
'title' => __('Content', 'wp-ultimo'),
|
||||
'placeholder' => __('E.g. Text, HTML or shortcode.', 'wp-ultimo'),
|
||||
'desc' => __('You can insert plain text, HTML or a shortcode in this block.', 'wp-ultimo'),
|
||||
'tooltip' => '',
|
||||
'html_attr' => array(
|
||||
'rows' => 6,
|
||||
)
|
||||
);
|
||||
|
||||
return $fields;
|
||||
|
||||
} // end fields;
|
||||
|
||||
/**
|
||||
* Registers scripts and styles necessary to render this.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return void
|
||||
*/
|
||||
public function register_scripts() {
|
||||
|
||||
wp_enqueue_style('wu-admin');
|
||||
|
||||
} // end register_scripts;
|
||||
|
||||
/**
|
||||
* The list of keywords for this element.
|
||||
*
|
||||
* Return an array of strings with keywords describing this
|
||||
* element. Gutenberg uses this to help customers find blocks.
|
||||
*
|
||||
* e.g.:
|
||||
* return array(
|
||||
* 'WP Ultimo',
|
||||
* 'Billing_Address',
|
||||
* 'Form',
|
||||
* 'Cart',
|
||||
* );
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return array
|
||||
*/
|
||||
public function keywords() {
|
||||
|
||||
return array(
|
||||
'WP Ultimo',
|
||||
'text',
|
||||
'simple text',
|
||||
'shortcode',
|
||||
'textarea'
|
||||
);
|
||||
|
||||
} // end keywords;
|
||||
|
||||
/**
|
||||
* List of default parameters for the element.
|
||||
*
|
||||
* If you are planning to add controls using the fields,
|
||||
* it might be a good idea to use this method to set defaults
|
||||
* for the parameters you are expecting.
|
||||
*
|
||||
* These defaults will be used inside a 'wp_parse_args' call
|
||||
* before passing the parameters down to the block render
|
||||
* function and the shortcode render function.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return array
|
||||
*/
|
||||
public function defaults() {
|
||||
|
||||
return array(
|
||||
'simple_text' => __('Text, HTML or shortcode.', 'wp-ultimo'),
|
||||
);
|
||||
|
||||
} // end defaults;
|
||||
|
||||
/**
|
||||
* The content to be output on the screen.
|
||||
*
|
||||
* Should return HTML markup to be used to display the block.
|
||||
* This method is shared between the block render method and
|
||||
* the shortcode implementation.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*
|
||||
* @param array $atts Parameters of the block/shortcode.
|
||||
* @param string|null $content The content inside the shortcode.
|
||||
* @return string
|
||||
*/
|
||||
public function output($atts, $content = null) {
|
||||
|
||||
return wu_get_template_contents('dashboard-widgets/simple-text', $atts);
|
||||
|
||||
} // end output;
|
||||
|
||||
} // end class Simple_Text_Element;
|
1189
inc/ui/class-site-actions-element.php
Normal file
1189
inc/ui/class-site-actions-element.php
Normal file
File diff suppressed because it is too large
Load Diff
311
inc/ui/class-site-maintenance-element.php
Normal file
311
inc/ui/class-site-maintenance-element.php
Normal file
@ -0,0 +1,311 @@
|
||||
<?php
|
||||
/**
|
||||
* Adds the Site Maintenance Element UI to the Admin Panel.
|
||||
*
|
||||
* @package WP_Ultimo
|
||||
* @subpackage UI
|
||||
* @since 2.0.0
|
||||
*/
|
||||
|
||||
namespace WP_Ultimo\UI;
|
||||
|
||||
use WP_Ultimo\UI\Base_Element;
|
||||
|
||||
// Exit if accessed directly
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
/**
|
||||
* Adds the Checkout Element UI to the Admin Panel.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
class Site_Maintenance_Element extends Base_Element {
|
||||
|
||||
use \WP_Ultimo\Traits\Singleton;
|
||||
|
||||
/**
|
||||
* The id of the element.
|
||||
*
|
||||
* Something simple, without prefixes, like 'checkout', or 'pricing-tables'.
|
||||
*
|
||||
* This is used to construct shortcodes by prefixing the id with 'wu_'
|
||||
* e.g. an id checkout becomes the shortcode 'wu_checkout' and
|
||||
* to generate the Gutenberg block by prefixing it with 'wp-ultimo/'
|
||||
* e.g. checkout would become the block 'wp-ultimo/checkout'.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @var string
|
||||
*/
|
||||
public $id = 'site-maintenance';
|
||||
|
||||
/**
|
||||
* Controls if this is a public element to be used in pages/shortcodes by user.
|
||||
*
|
||||
* @since 2.0.24
|
||||
* @var boolean
|
||||
*/
|
||||
protected $public = true;
|
||||
|
||||
/**
|
||||
* Initializes the singleton.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return void
|
||||
*/
|
||||
public function init() {
|
||||
|
||||
if (wu_get_setting('maintenance_mode')) {
|
||||
|
||||
parent::init();
|
||||
|
||||
} // end if;
|
||||
|
||||
} // end init;
|
||||
|
||||
/**
|
||||
* The icon of the UI element.
|
||||
* e.g. return fa fa-search
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @param string $context One of the values: block, elementor or bb.
|
||||
* @return string
|
||||
*/
|
||||
public function get_icon($context = 'block') {
|
||||
|
||||
if ($context === 'elementor') {
|
||||
|
||||
return 'eicon-lock-user';
|
||||
|
||||
} // end if;
|
||||
|
||||
return 'fa fa-search';
|
||||
|
||||
} // end get_icon;
|
||||
|
||||
/**
|
||||
* The title of the UI element.
|
||||
*
|
||||
* This is used on the Blocks list of Gutenberg.
|
||||
* You should return a string with the localized title.
|
||||
* e.g. return __('My Element', 'wp-ultimo').
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return string
|
||||
*/
|
||||
public function get_title() {
|
||||
|
||||
return __('Site Maintenance', 'wp-ultimo');
|
||||
|
||||
} // end get_title;
|
||||
|
||||
/**
|
||||
* The description of the UI element.
|
||||
*
|
||||
* This is also used on the Gutenberg block list
|
||||
* to explain what this block is about.
|
||||
* You should return a string with the localized title.
|
||||
* e.g. return __('Adds a checkout form to the page', 'wp-ultimo').
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return string
|
||||
*/
|
||||
public function get_description() {
|
||||
|
||||
return __('Adds the toggle control to turn maintenance mode on.', 'wp-ultimo');
|
||||
|
||||
} // end get_description;
|
||||
|
||||
/**
|
||||
* The list of fields to be added to Gutenberg.
|
||||
*
|
||||
* If you plan to add Gutenberg controls to this block,
|
||||
* you'll need to return an array of fields, following
|
||||
* our fields interface (@see inc/ui/class-field.php).
|
||||
*
|
||||
* You can create new Gutenberg panels by adding fields
|
||||
* with the type 'header'. See the Checkout Elements for reference.
|
||||
*
|
||||
* @see inc/ui/class-checkout-element.php
|
||||
*
|
||||
* Return an empty array if you don't have controls to add.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return array
|
||||
*/
|
||||
public function fields() {
|
||||
|
||||
$fields = array();
|
||||
|
||||
$fields['header'] = array(
|
||||
'title' => __('General', 'wp-ultimo'),
|
||||
'desc' => __('General', 'wp-ultimo'),
|
||||
'type' => 'header',
|
||||
);
|
||||
|
||||
$fields['title'] = array(
|
||||
'type' => 'text',
|
||||
'title' => __('Label', 'wp-ultimo'),
|
||||
'value' => __('Toggle Maintenance Mode', 'wp-ultimo'),
|
||||
'placeholder' => __('e.g. Toggle Maintenance Mode', 'wp-ultimo'),
|
||||
'tooltip' => '',
|
||||
);
|
||||
|
||||
$fields['desc'] = array(
|
||||
'type' => 'textarea',
|
||||
'title' => __('Description', 'wp-ultimo'),
|
||||
'value' => __('Put your site on maintenance mode. When activated, the front-end will only be accessible to logged users.', 'wp-ultimo'),
|
||||
'tooltip' => '',
|
||||
);
|
||||
|
||||
return $fields;
|
||||
|
||||
} // end fields;
|
||||
|
||||
/**
|
||||
* The list of keywords for this element.
|
||||
*
|
||||
* Return an array of strings with keywords describing this
|
||||
* element. Gutenberg uses this to help customers find blocks.
|
||||
*
|
||||
* e.g.:
|
||||
* return array(
|
||||
* 'WP Ultimo',
|
||||
* 'Billing_Address',
|
||||
* 'Form',
|
||||
* 'Cart',
|
||||
* );
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return array
|
||||
*/
|
||||
public function keywords() {
|
||||
|
||||
return array(
|
||||
'WP Ultimo',
|
||||
'Login',
|
||||
'Reset Password',
|
||||
);
|
||||
|
||||
} // end keywords;
|
||||
|
||||
/**
|
||||
* List of default parameters for the element.
|
||||
*
|
||||
* If you are planning to add controls using the fields,
|
||||
* it might be a good idea to use this method to set defaults
|
||||
* for the parameters you are expecting.
|
||||
*
|
||||
* These defaults will be used inside a 'wp_parse_args' call
|
||||
* before passing the parameters down to the block render
|
||||
* function and the shortcode render function.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return array
|
||||
*/
|
||||
public function defaults() {
|
||||
|
||||
return array(
|
||||
'title' => __('Toggle Maintenance Mode', 'wp-ultimo'),
|
||||
'desc' => __('Put your site on maintenance mode. When activated, the front-end will only be accessible to logged users.', 'wp-ultimo'),
|
||||
);
|
||||
|
||||
} // end defaults;
|
||||
|
||||
/**
|
||||
* Runs early on the request lifecycle as soon as we detect the shortcode is present.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return void
|
||||
*/
|
||||
public function setup() {
|
||||
|
||||
$this->site = WP_Ultimo()->currents->get_site();
|
||||
|
||||
if (!$this->site || !$this->site->is_customer_allowed()) {
|
||||
|
||||
$this->set_display(false);
|
||||
|
||||
return;
|
||||
|
||||
} // end if;
|
||||
|
||||
} // end setup;
|
||||
|
||||
/**
|
||||
* Allows the setup in the context of previews.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return void
|
||||
*/
|
||||
public function setup_preview() {
|
||||
|
||||
$this->site = wu_mock_site();
|
||||
|
||||
} // end setup_preview;
|
||||
|
||||
/**
|
||||
* Registers scripts and styles necessary to render this.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return void
|
||||
*/
|
||||
public function register_scripts() {
|
||||
|
||||
wp_register_script('wu-site-maintenance', wu_get_asset('site-maintenance.js', 'js'), array('jquery', 'wu-functions'), wu_get_version());
|
||||
|
||||
wp_localize_script('wu-site-maintenance', 'wu_site_maintenance', array(
|
||||
'nonce' => wp_create_nonce('wu_toggle_maintenance_mode'),
|
||||
'ajaxurl' => wu_ajax_url(),
|
||||
));
|
||||
|
||||
wp_enqueue_script('wu-site-maintenance');
|
||||
|
||||
} // end register_scripts;
|
||||
|
||||
/**
|
||||
* The content to be output on the screen.
|
||||
*
|
||||
* Should return HTML markup to be used to display the block.
|
||||
* This method is shared between the block render method and
|
||||
* the shortcode implementation.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*
|
||||
* @param array $atts Parameters of the block/shortcode.
|
||||
* @param string|null $content The content inside the shortcode.
|
||||
* @return string
|
||||
*/
|
||||
public function output($atts, $content = null) {
|
||||
|
||||
$fields = array(
|
||||
'maintenance_mode' => array(
|
||||
'type' => 'toggle',
|
||||
'title' => $atts['title'],
|
||||
'desc' => $atts['desc'],
|
||||
'value' => wu_string_to_bool($this->site->get_meta('wu_maintenance_mode')),
|
||||
),
|
||||
'site_hash' => array(
|
||||
'type' => 'hidden',
|
||||
'value' => $this->site->get_hash(),
|
||||
),
|
||||
);
|
||||
|
||||
/**
|
||||
* Instantiate the form for the order details.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
$form = new \WP_Ultimo\UI\Form('maintenance-mode', $fields, array(
|
||||
'views' => 'admin-pages/fields',
|
||||
'classes' => 'wu-widget-list wu-striped wu-modal-form wu-widget-list wu-striped wu-m-0 wu-mt-0 wu-list-none wu-p-0',
|
||||
'field_wrapper_classes' => 'wu-w-full wu-box-border wu-items-center wu-flex wu-justify-between wu-p-4 wu-m-0 wu-border-t wu-border-l-0 wu-border-r-0 wu-border-b-0 wu-border-gray-300 wu-border-solid',
|
||||
'html_attr' => array(),
|
||||
));
|
||||
|
||||
$atts['form'] = $form;
|
||||
|
||||
return wu_get_template_contents('dashboard-widgets/site-maintenance', $atts);
|
||||
|
||||
} // end output;
|
||||
|
||||
} // end class Site_Maintenance_Element;
|
459
inc/ui/class-template-previewer.php
Normal file
459
inc/ui/class-template-previewer.php
Normal file
@ -0,0 +1,459 @@
|
||||
<?php
|
||||
/**
|
||||
* Adds the Template Previewer code.
|
||||
*
|
||||
* @package WP_Ultimo
|
||||
* @subpackage UI
|
||||
* @since 2.0.0
|
||||
*/
|
||||
|
||||
namespace WP_Ultimo\UI;
|
||||
|
||||
use WP_Ultimo\Database\Sites\Site_Type;
|
||||
|
||||
// Exit if accessed directly
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
/**
|
||||
* Adds the Template_Previewer UI to the Admin Panel.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
class Template_Previewer {
|
||||
|
||||
use \WP_Ultimo\Traits\Singleton;
|
||||
|
||||
/**
|
||||
* Keeps a list of the available templates for the products selected.
|
||||
*
|
||||
* @since 2.0.11
|
||||
* @var null|array
|
||||
*/
|
||||
protected $available_templates = null;
|
||||
|
||||
/**
|
||||
* Keeps the settings key for the top-bar.
|
||||
*/
|
||||
const KEY = 'top_bar_settings';
|
||||
|
||||
/**
|
||||
* Initializes the class.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return void
|
||||
*/
|
||||
public function init() {
|
||||
|
||||
add_action('wp_ultimo_load', array($this, 'hooks'));
|
||||
|
||||
} // end init;
|
||||
|
||||
/**
|
||||
* Hooks into WordPress to add the template preview.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return void
|
||||
*/
|
||||
public function hooks() {
|
||||
|
||||
if ($this->is_preview()) {
|
||||
/*
|
||||
* Remove admin bar from logged users.
|
||||
*/
|
||||
add_filter('show_admin_bar', '__return_false');
|
||||
|
||||
add_filter('wu_is_jumper_enabled', '__return_false');
|
||||
|
||||
add_filter('wu_is_toolbox_enabled', '__return_false');
|
||||
|
||||
add_filter('home_url', array($this, 'append_preview_parameter'), 9999, 4);
|
||||
|
||||
add_action('send_headers', array($this, 'send_cross_origin_headers'), 1000);
|
||||
|
||||
return;
|
||||
|
||||
} // end if;
|
||||
|
||||
if ($this->is_template_previewer()) {
|
||||
|
||||
add_action('init', array($this, 'template_previewer'));
|
||||
|
||||
add_action('wp_enqueue_scripts', array($this, 'register_scripts'));
|
||||
|
||||
add_action('wp_print_styles', array($this, 'remove_unnecessary_styles'), 0);
|
||||
|
||||
/**
|
||||
* Runs when inside the template previewer context.
|
||||
*
|
||||
* @since 2.0.4
|
||||
* @param self $template_previewer Instance of the current class.
|
||||
*/
|
||||
do_action('wu_template_previewer', $this);
|
||||
|
||||
} // end if;
|
||||
|
||||
} // end hooks;
|
||||
|
||||
/**
|
||||
* Send the cross origin headers to allow iframes to be loaded.
|
||||
*
|
||||
* @since 2.0.9
|
||||
* @return void
|
||||
*/
|
||||
public function send_cross_origin_headers() {
|
||||
|
||||
global $current_site;
|
||||
|
||||
$_SERVER['HTTP_ORIGIN'] = set_url_scheme("http://{$current_site->domain}");
|
||||
|
||||
send_origin_headers();
|
||||
|
||||
header_remove('X-Frame-Options');
|
||||
|
||||
} // end send_cross_origin_headers;
|
||||
|
||||
/**
|
||||
* Register the necessary scripts.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return void
|
||||
*/
|
||||
public function register_scripts() {
|
||||
|
||||
global $current_site;
|
||||
|
||||
$settings = $this->get_settings();
|
||||
|
||||
$bg_color = wu_color($settings['bg_color']);
|
||||
$button_bg_color = wu_color($settings['button_bg_color']);
|
||||
$button_bg_darker = wu_color($button_bg_color->darken(4));
|
||||
|
||||
wp_register_script('wu-template-previewer', wu_get_asset('template-previewer.js', 'js'), array(), wu_get_version());
|
||||
|
||||
wp_localize_script('wu-template-previewer', 'wu_template_previewer', array(
|
||||
'domain' => str_replace('www.', '', (string) $current_site->domain),
|
||||
'current_template' => wu_request($this->get_preview_parameter(), false),
|
||||
'current_url' => wu_get_current_url(),
|
||||
'query_parameter' => $this->get_preview_parameter(),
|
||||
));
|
||||
|
||||
wp_enqueue_script('wu-template-previewer');
|
||||
|
||||
wp_enqueue_style('wu-template-previewer', wu_get_asset('template-previewer.css', 'css'), array(), wu_get_version());
|
||||
|
||||
wp_add_inline_style('wu-template-previewer', wu_get_template_contents('dynamic-styles/template-previewer', array(
|
||||
'bg_color' => $bg_color,
|
||||
'button_bg_color' => $button_bg_color,
|
||||
)));
|
||||
|
||||
wp_enqueue_style('dashicons');
|
||||
|
||||
} // end register_scripts;
|
||||
|
||||
/**
|
||||
* Remove the unnecessary styles added by themes and other plugins.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return void
|
||||
*/
|
||||
public function remove_unnecessary_styles() {
|
||||
|
||||
global $wp_styles;
|
||||
|
||||
$wp_styles->queue = array(
|
||||
'wu-admin',
|
||||
'wu-template-previewer',
|
||||
'dashicons',
|
||||
);
|
||||
|
||||
} // end remove_unnecessary_styles;
|
||||
|
||||
/**
|
||||
* Append preview parameter.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*
|
||||
* @param string $url The URL.
|
||||
* @param string $path Path relative to the home URL. Blank string if no path is specified.
|
||||
* @param string|null $orig_scheme Scheme to give the home URL context. Accepts 'http', 'https',
|
||||
* 'relative', 'rest', or null.
|
||||
* @param int|null $blog_id Site ID, or null for the current site.
|
||||
* @return string
|
||||
*/
|
||||
public function append_preview_parameter($url, $path, $orig_scheme, $blog_id) {
|
||||
|
||||
$allowed_schemes = array(
|
||||
null,
|
||||
'http',
|
||||
'https',
|
||||
);
|
||||
|
||||
if (in_array($orig_scheme, $allowed_schemes, true) === false) {
|
||||
|
||||
return $url;
|
||||
|
||||
} // end if;
|
||||
|
||||
if (apply_filters('wu_append_preview_parameter', true, $this) === false) {
|
||||
|
||||
return $url;
|
||||
|
||||
} // end if;
|
||||
|
||||
return add_query_arg('wu-preview', 1, $url);
|
||||
|
||||
} // end append_preview_parameter;
|
||||
|
||||
/**
|
||||
* Returns the preview URL for the template previewer.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*
|
||||
* @param int $site_id The ID of the template site.
|
||||
* @return string
|
||||
*/
|
||||
public function get_preview_url($site_id) {
|
||||
|
||||
$args = array(
|
||||
$this->get_preview_parameter() => $site_id,
|
||||
);
|
||||
|
||||
if (wu_request('open')) {
|
||||
|
||||
$args['open'] = 1;
|
||||
|
||||
} // end if;
|
||||
|
||||
return add_query_arg($args, home_url());
|
||||
|
||||
} // end get_preview_url;
|
||||
|
||||
/**
|
||||
* Template Previewer code
|
||||
*
|
||||
* @since 1.5.5
|
||||
* @return void
|
||||
*/
|
||||
public function template_previewer() {
|
||||
|
||||
global $current_site;
|
||||
|
||||
$template_value = wu_request($this->get_preview_parameter(), false);
|
||||
|
||||
$selected_template = wu_get_site($template_value);
|
||||
|
||||
/**
|
||||
* Check if this is a site template
|
||||
*/
|
||||
if ($selected_template->get_type() !== Site_Type::SITE_TEMPLATE && !wu_request('customizer')) {
|
||||
|
||||
wp_die(__('This template is not available', 'wp-ultimo'));
|
||||
|
||||
} // end if;
|
||||
|
||||
$categories = array();
|
||||
|
||||
$settings = $this->get_settings();
|
||||
|
||||
$render_parameters = array(
|
||||
'current_site' => $current_site,
|
||||
'categories' => $categories,
|
||||
'selected_template' => $selected_template,
|
||||
'tp' => $this,
|
||||
);
|
||||
|
||||
$products_ids = isset($_COOKIE['wu_selected_products']) ? explode( ',', (string) $_COOKIE['wu_selected_products']) : array();
|
||||
|
||||
$products = array_map('wu_get_product', $products_ids);
|
||||
|
||||
// clear array
|
||||
$products = array_filter($products);
|
||||
|
||||
if (!empty($products)) {
|
||||
|
||||
$limits = new \WP_Ultimo\Objects\Limitations();
|
||||
|
||||
list($plan, $additional_products) = wu_segregate_products($products);
|
||||
|
||||
$products = array_merge(array($plan), $additional_products);
|
||||
|
||||
foreach ($products as $product) {
|
||||
|
||||
$limits = $limits->merge($product->get_limitations());
|
||||
|
||||
} // end foreach;
|
||||
|
||||
if ($limits->site_templates->get_mode() !== 'default') {
|
||||
|
||||
$site_ids = $limits->site_templates->get_available_site_templates();
|
||||
|
||||
$render_parameters['templates'] = array_map('wu_get_site', $site_ids);
|
||||
|
||||
/**
|
||||
* Check if the current site is a member of
|
||||
* the list of available templates
|
||||
*/
|
||||
if (!in_array($selected_template->get_id(), $site_ids, true)) {
|
||||
|
||||
$redirect_to = wu_get_current_url();
|
||||
|
||||
$redirect_to = add_query_arg($this->get_preview_parameter(), current($site_ids), $redirect_to);
|
||||
|
||||
wp_redirect($redirect_to);
|
||||
|
||||
exit;
|
||||
|
||||
} // end if;
|
||||
|
||||
} // end if;
|
||||
|
||||
} // end if;
|
||||
|
||||
if (!isset($render_parameters['templates'])) {
|
||||
|
||||
$render_parameters['templates'] = wu_get_site_templates();
|
||||
|
||||
} // end if;
|
||||
|
||||
$render_parameters['templates'] = array_filter((array) $render_parameters['templates'], fn($site) => $site->is_active());
|
||||
|
||||
$render_parameters = array_merge($render_parameters, $settings);
|
||||
|
||||
wu_get_template('ui/template-previewer', $render_parameters);
|
||||
|
||||
exit;
|
||||
|
||||
} // end template_previewer;
|
||||
|
||||
/**
|
||||
* Returns the preview parameter, so admins can change it.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return string
|
||||
*/
|
||||
public function get_preview_parameter() {
|
||||
|
||||
$slug = $this->get_setting('preview_url_parameter', 'template-preview');
|
||||
|
||||
return apply_filters('wu_get_template_preview_slug', $slug);
|
||||
|
||||
} // end get_preview_parameter;
|
||||
|
||||
/**
|
||||
* Checks if this is a template previewer window.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return boolean
|
||||
*/
|
||||
public function is_template_previewer() {
|
||||
|
||||
$slug = $this->get_preview_parameter();
|
||||
|
||||
return wu_request($slug);
|
||||
|
||||
} // end is_template_previewer;
|
||||
|
||||
/**
|
||||
* Check if the frame is a preview.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return boolean
|
||||
*/
|
||||
public function is_preview() {
|
||||
|
||||
return !empty(wu_request('wu-preview'));
|
||||
|
||||
} // end is_preview;
|
||||
|
||||
/**
|
||||
* Returns the settings.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return array
|
||||
*/
|
||||
public function get_settings() {
|
||||
|
||||
// Fix to issue on wp_get_attachment_url() inside core.
|
||||
// @todo report it.
|
||||
$GLOBALS['pagenow'] = '';
|
||||
|
||||
$default_settings = array(
|
||||
'bg_color' => '#f9f9f9',
|
||||
'button_bg_color' => '#00a1ff',
|
||||
'logo_url' => wu_get_network_logo(),
|
||||
'button_text' => __('Use this Template', 'wp-ultimo'),
|
||||
'preview_url_parameter' => 'template-preview',
|
||||
'display_responsive_controls' => true,
|
||||
'use_custom_logo' => false,
|
||||
'custom_logo' => false,
|
||||
'enabled' => true,
|
||||
);
|
||||
|
||||
$saved_settings = wu_get_option(Template_Previewer::KEY, array());
|
||||
|
||||
$default_settings = array_merge($default_settings, $saved_settings);
|
||||
|
||||
$server_request = $_REQUEST;
|
||||
|
||||
// Ensure that templates key does not change with request
|
||||
if (isset($server_request['templates'])) {
|
||||
|
||||
unset($server_request['templates']);
|
||||
|
||||
} // end if;
|
||||
|
||||
$parsed_args = wp_parse_args($server_request, $default_settings);
|
||||
|
||||
$parsed_args['display_responsive_controls'] = wu_string_to_bool($parsed_args['display_responsive_controls']);
|
||||
$parsed_args['use_custom_logo'] = wu_string_to_bool($parsed_args['use_custom_logo']);
|
||||
|
||||
return $parsed_args;
|
||||
|
||||
} // end get_settings;
|
||||
|
||||
/**
|
||||
* Gets a particular setting.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*
|
||||
* @param string $setting The setting key.
|
||||
* @param mixed $default Default value, if it is not found.
|
||||
* @return mixed
|
||||
*/
|
||||
public function get_setting($setting, $default = false) {
|
||||
|
||||
return wu_get_isset($this->get_settings(), $setting, $default);
|
||||
|
||||
} // end get_setting;
|
||||
|
||||
/**
|
||||
* Save settings.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*
|
||||
* @param array $settings_to_save List of settings to save.
|
||||
* @return boolean
|
||||
*/
|
||||
public function save_settings($settings_to_save) {
|
||||
|
||||
$settings = $this->get_settings();
|
||||
|
||||
foreach ($settings as $setting => $value) {
|
||||
|
||||
if ($setting === 'logo_url') {
|
||||
|
||||
$settings['logo_url'] = wu_get_network_logo();
|
||||
|
||||
continue;
|
||||
|
||||
} // end if;
|
||||
|
||||
$settings[$setting] = wu_get_isset($settings_to_save, $setting, false);
|
||||
|
||||
} // end foreach;
|
||||
|
||||
return wu_save_option(Template_Previewer::KEY, $settings);
|
||||
|
||||
} // end save_settings;
|
||||
|
||||
} // end class Template_Previewer;
|
464
inc/ui/class-template-switching-element.php
Normal file
464
inc/ui/class-template-switching-element.php
Normal file
@ -0,0 +1,464 @@
|
||||
<?php
|
||||
/**
|
||||
* Adds the Template Selection UI to the Admin Panel.
|
||||
*
|
||||
* @package WP_Ultimo
|
||||
* @subpackage UI
|
||||
* @since 2.0.0
|
||||
*/
|
||||
|
||||
namespace WP_Ultimo\UI;
|
||||
|
||||
use \WP_Ultimo\UI\Base_Element;
|
||||
use \WP_Ultimo\Managers\Field_Templates_Manager;
|
||||
|
||||
// Exit if accessed directly
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
/**
|
||||
* Adds the Template Selection Element UI to the Admin Panel.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
class Template_Switching_Element extends Base_Element {
|
||||
|
||||
use \WP_Ultimo\Traits\Singleton;
|
||||
|
||||
/**
|
||||
* The id of the element.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $id = 'template-switching';
|
||||
|
||||
/**
|
||||
* The current site element.
|
||||
*
|
||||
* @since 2.0.18
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $site;
|
||||
|
||||
/**
|
||||
* The membership object.
|
||||
*
|
||||
* @since 2.2.0
|
||||
* @var \WP_Ultimo\Membership
|
||||
*/
|
||||
protected $membership;
|
||||
|
||||
/**
|
||||
* The list of products associated with the current membership.
|
||||
*
|
||||
* @since 2.2.0
|
||||
* @var array
|
||||
*/
|
||||
protected $products;
|
||||
|
||||
/**
|
||||
* The icon of the UI element.
|
||||
* e.g. return fa fa-search
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @param string $context One of the values: block, elementor or bb.
|
||||
*/
|
||||
public function get_icon($context = 'block'): string {
|
||||
|
||||
if ($context === 'elementor') {
|
||||
|
||||
return 'eicon-cart-medium';
|
||||
|
||||
} // end if;
|
||||
|
||||
return 'fa fa-search';
|
||||
|
||||
} // end get_icon;
|
||||
|
||||
/**
|
||||
* The title of the UI element.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return string
|
||||
*/
|
||||
public function get_title() {
|
||||
|
||||
return __('Template Switching', 'wp-ultimo');
|
||||
|
||||
} // end get_title;
|
||||
|
||||
/**
|
||||
* The description of the UI element.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return string
|
||||
*/
|
||||
public function get_description() {
|
||||
|
||||
return __('Adds the template switching form to this page.', 'wp-ultimo');
|
||||
|
||||
} // end get_description;
|
||||
|
||||
/**
|
||||
* Initializes the singleton.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return void
|
||||
*/
|
||||
public function init() {
|
||||
|
||||
add_action('wu_ajax_wu_switch_template', array($this, 'switch_template'));
|
||||
|
||||
parent::init();
|
||||
|
||||
} // end init;
|
||||
|
||||
/**
|
||||
* Register element scripts.
|
||||
*
|
||||
* @since 2.0.4
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register_scripts() {
|
||||
|
||||
wp_register_script('wu-template-switching', wu_get_asset('template-switching.js', 'js'), array('jquery', 'wu-vue-apps', 'wu-selectizer', 'wp-hooks', 'wu-cookie-helpers'));
|
||||
|
||||
wp_localize_script('wu-template-switching', 'wu_template_switching_params', array(
|
||||
'ajaxurl' => wu_ajax_url(),
|
||||
));
|
||||
|
||||
wp_enqueue_script('wu-template-switching');
|
||||
|
||||
} // end register_scripts;
|
||||
|
||||
/**
|
||||
* The list of fields to be added to Gutenberg.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return array
|
||||
*/
|
||||
public function fields() {
|
||||
|
||||
$fields = array();
|
||||
|
||||
$fields['header'] = array(
|
||||
'title' => __('Layout', 'wp-ultimo'),
|
||||
'desc' => __('Layout', 'wp-ultimo'),
|
||||
'type' => 'header',
|
||||
);
|
||||
|
||||
$fields['template_selection_template'] = array(
|
||||
'type' => 'group',
|
||||
'desc' => Field_Templates_Manager::get_instance()->render_preview_block('template_selection'),
|
||||
'fields' => array(
|
||||
'template_selection_template' => array(
|
||||
'type' => 'select',
|
||||
'title' => __('Template Selector Layout', 'wp-ultimo'),
|
||||
'placeholder' => __('Select your Layout', 'wp-ultimo'),
|
||||
'default' => 'clean',
|
||||
'options' => array($this, 'get_template_selection_templates'),
|
||||
'wrapper_classes' => 'wu-flex-grow',
|
||||
'html_attr' => array(
|
||||
'v-model' => 'template_selection_template',
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
$fields['_dev_note_develop_your_own_template_1'] = array(
|
||||
'type' => 'note',
|
||||
'order' => 99,
|
||||
'wrapper_classes' => 'sm:wu-p-0 sm:wu-block',
|
||||
'classes' => '',
|
||||
'desc' => sprintf('<div class="wu-p-4 wu-bg-blue-100 wu-text-grey-600">%s</div>', __('Want to add customized template selection templates?<br><a target="_blank" class="wu-no-underline" href="https://help.wpultimo.com/article/343-customize-your-checkout-flow-using-field-templates">See how you can do that here</a>.', 'wp-ultimo')),
|
||||
);
|
||||
|
||||
return $fields;
|
||||
|
||||
} // end fields;
|
||||
|
||||
/**
|
||||
* The list of keywords for this element.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function keywords() {
|
||||
|
||||
return array(
|
||||
'WP Ultimo',
|
||||
'Template',
|
||||
'Template Switching',
|
||||
);
|
||||
|
||||
} // end keywords;
|
||||
|
||||
/**
|
||||
* List of default parameters for the element.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return array
|
||||
*/
|
||||
public function defaults() {
|
||||
|
||||
$site_template_ids = wu_get_site_templates(array(
|
||||
'fields' => 'ids',
|
||||
));
|
||||
|
||||
return array(
|
||||
'slug' => 'template-switching',
|
||||
'template_selection_template' => 'clean',
|
||||
'template_selection_sites' => implode(',', $site_template_ids),
|
||||
);
|
||||
|
||||
} // end defaults;
|
||||
|
||||
/**
|
||||
* Runs early on the request lifecycle as soon as we detect the shortcode is present.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return void
|
||||
*/
|
||||
public function setup() {
|
||||
|
||||
$this->site = wu_get_current_site();
|
||||
|
||||
if (!$this->site || !$this->site->is_customer_allowed()) {
|
||||
|
||||
$this->set_display(false);
|
||||
|
||||
return;
|
||||
|
||||
} // end if;
|
||||
|
||||
$this->membership = $this->site->get_membership();
|
||||
|
||||
$this->products = array();
|
||||
|
||||
$all_membership_products = array();
|
||||
|
||||
if ($this->membership) {
|
||||
|
||||
$all_membership_products = $this->membership->get_all_products();
|
||||
|
||||
if (is_array($all_membership_products) && $all_membership_products) {
|
||||
|
||||
foreach ($all_membership_products as $product) {
|
||||
|
||||
$this->products[] = $product['product']->get_id();
|
||||
|
||||
} // end foreach;
|
||||
|
||||
} // end if;
|
||||
|
||||
} // end if;
|
||||
|
||||
} // end setup;
|
||||
|
||||
/**
|
||||
* Runs early on the request lifecycle as soon as we detect the shortcode is present.
|
||||
*
|
||||
* @since 2.0.4
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setup_preview() {
|
||||
|
||||
$this->site = wu_mock_site();
|
||||
|
||||
} // end setup_preview;
|
||||
|
||||
/**
|
||||
* Ajax action to change the template for a given site.
|
||||
*
|
||||
* @since 2.0.4
|
||||
*
|
||||
* @return json|WP_Error Switch template response.
|
||||
*/
|
||||
public function switch_template() {
|
||||
|
||||
if (!$this->site) {
|
||||
|
||||
$this->site = wu_get_current_site();
|
||||
|
||||
} // end if;
|
||||
|
||||
$template_id = wu_request('template_id', '');
|
||||
|
||||
if (!$template_id) {
|
||||
|
||||
return new \WP_Error('template_id_required', __('You need to provide a valid template to duplicate.', 'wp-ultimo'));
|
||||
|
||||
} // end if;
|
||||
|
||||
$switch = \WP_Ultimo\Helpers\Site_Duplicator::override_site($template_id, $this->site->get_id());
|
||||
|
||||
/**
|
||||
* Allow plugin developers to hook functions after a user or super admin switches the site template
|
||||
*
|
||||
* @since 1.9.8
|
||||
* @param integer Site ID
|
||||
* @return void
|
||||
*/
|
||||
do_action('wu_after_switch_template', $this->site->get_id());
|
||||
|
||||
if ($switch) {
|
||||
|
||||
wp_send_json_success(array(
|
||||
'redirect_url' => add_query_arg(array(
|
||||
'updated' => 1,
|
||||
), $_SERVER['HTTP_REFERER']),
|
||||
));
|
||||
|
||||
} // end if;
|
||||
|
||||
} // end switch_template;
|
||||
|
||||
/**
|
||||
* The content to be output on the screen.
|
||||
*
|
||||
* Should return HTML markup to be used to display the block.
|
||||
* This method is shared between the block render method and
|
||||
* the shortcode implementation.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*
|
||||
* @param array $atts Parameters of the block/shortcode.
|
||||
* @param string|null $content The content inside the shortcode.
|
||||
* @return string
|
||||
*/
|
||||
public function output($atts, $content = null) {
|
||||
|
||||
if ($this->site) {
|
||||
|
||||
$filter_template_limits = new \WP_Ultimo\Limits\Site_Template_Limits();
|
||||
|
||||
$atts['products'] = $this->products;
|
||||
|
||||
$template_selection_field = $filter_template_limits->maybe_filter_template_selection_options($atts);
|
||||
|
||||
if (!isset($template_selection_field['sites'])) {
|
||||
|
||||
$template_selection_field['sites'] = array();
|
||||
|
||||
} // end if;
|
||||
|
||||
$atts['template_selection_sites'] = implode(',', $template_selection_field['sites']);
|
||||
|
||||
$site_list = explode(',', $atts['template_selection_sites']);
|
||||
|
||||
$sites = array_map('wu_get_site', $site_list);
|
||||
|
||||
$sites = array_filter($sites);
|
||||
|
||||
$categories = \WP_Ultimo\Models\Site::get_all_categories($sites);
|
||||
|
||||
$template_attributes = array(
|
||||
'sites' => $sites,
|
||||
'name' => '',
|
||||
'categories' => $categories,
|
||||
);
|
||||
|
||||
$reducer_class = new \WP_Ultimo\Checkout\Signup_Fields\Signup_Field_Template_Selection();
|
||||
|
||||
$template_class = Field_Templates_Manager::get_instance()->get_template_class('template_selection', $atts['template_selection_template']);
|
||||
|
||||
$content = $template_class ? $template_class->render_container($template_attributes, $reducer_class) : __('Template does not exist.', 'wp-ultimo');
|
||||
|
||||
$checkout_fields['back_to_template_selection'] = array(
|
||||
'type' => 'note',
|
||||
'order' => 0,
|
||||
'desc' => sprintf('<a href="#" class="wu-no-underline wu-mt-1 wu-uppercase wu-text-2xs wu-font-semibold wu-text-gray-600" v-on:click.prevent="template_id = original_template_id; confirm_switch = false">%s</a>', __('← Back to Template Selection', 'wp-ultimo')),
|
||||
'wrapper_html_attr' => array(
|
||||
'v-init:original_template_id' => $this->site->get_template_id(),
|
||||
'v-show' => 'template_id != original_template_id',
|
||||
'v-cloak' => '1',
|
||||
),
|
||||
);
|
||||
|
||||
$checkout_fields['template_element'] = array(
|
||||
'type' => 'note',
|
||||
'wrapper_classes' => 'wu-w-full',
|
||||
'classes' => 'wu-w-full',
|
||||
'desc' => $content,
|
||||
'wrapper_html_attr' => array(
|
||||
'v-show' => 'template_id == original_template_id',
|
||||
'v-cloak' => '1',
|
||||
),
|
||||
);
|
||||
|
||||
$checkout_fields['confirm_switch'] = array(
|
||||
'type' => 'toggle',
|
||||
'title' => __('Confirm template switch?', 'wp-ultimo'),
|
||||
'desc' => __('Switching your current template completely overwrites the content of your site with the contents of the newly chosen template. All customizations will be lost. This action cannot be undone.', 'wp-ultimo'),
|
||||
'tooltip' => '',
|
||||
'wrapper_classes' => '',
|
||||
'value' => 0,
|
||||
'html_attr' => array(
|
||||
'v-model' => 'confirm_switch'
|
||||
),
|
||||
'wrapper_html_attr' => array(
|
||||
'v-show' => 'template_id != 0 && template_id != original_template_id',
|
||||
'v-cloak' => 1,
|
||||
),
|
||||
);
|
||||
|
||||
$checkout_fields['submit_switch'] = array(
|
||||
'type' => 'link',
|
||||
'display_value' => __('Process Switch', 'wp-ultimo'),
|
||||
'wrapper_classes' => 'wu-text-right wu-bg-gray-100',
|
||||
'classes' => 'button button-primary',
|
||||
'wrapper_html_attr' => array(
|
||||
'v-cloak' => 1,
|
||||
'v-show' => 'confirm_switch',
|
||||
'v-on:click.prevent' => 'ready = true'
|
||||
),
|
||||
);
|
||||
|
||||
$checkout_fields['template_id'] = array(
|
||||
'type' => 'hidden',
|
||||
'html_attr' => array(
|
||||
'v-model' => 'template_id',
|
||||
'v-init:template_id' => $this->site->get_template_id(),
|
||||
),
|
||||
);
|
||||
|
||||
$section_slug = 'wu-template-switching-form';
|
||||
|
||||
$form = new Form($section_slug, $checkout_fields, array(
|
||||
'views' => 'admin-pages/fields',
|
||||
'classes' => 'wu-striped wu-widget-inset',
|
||||
'field_wrapper_classes' => 'wu-w-full wu-box-border wu-items-center wu-flex wu-justify-between wu-p-4 wu-py-5 wu-m-0 wu-border-t wu-border-l-0 wu-border-r-0 wu-border-b-0 wu-border-gray-300 wu-border-solid'
|
||||
));
|
||||
|
||||
ob_start();
|
||||
|
||||
$form->render();
|
||||
|
||||
return ob_get_clean();
|
||||
|
||||
} // end if;
|
||||
|
||||
return '';
|
||||
|
||||
} // end output;
|
||||
|
||||
/**
|
||||
* Returns the list of available pricing table templates.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return array
|
||||
*/
|
||||
public function get_template_selection_templates() {
|
||||
|
||||
$available_templates = Field_Templates_Manager::get_instance()->get_templates_as_options('template_selection');
|
||||
|
||||
return $available_templates;
|
||||
|
||||
} // end get_template_selection_templates;
|
||||
|
||||
} // end class Template_Switching_Element;
|
461
inc/ui/class-thank-you-element.php
Normal file
461
inc/ui/class-thank-you-element.php
Normal file
@ -0,0 +1,461 @@
|
||||
<?php
|
||||
/**
|
||||
* Adds the Thank_You_Element UI to the Admin Panel.
|
||||
*
|
||||
* @package WP_Ultimo
|
||||
* @subpackage UI
|
||||
* @since 2.0.0
|
||||
*/
|
||||
|
||||
namespace WP_Ultimo\UI;
|
||||
|
||||
use WP_Ultimo\UI\Base_Element;
|
||||
|
||||
// Exit if accessed directly
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
/**
|
||||
* Adds the Thank You Element UI to the Admin Panel.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
class Thank_You_Element extends Base_Element {
|
||||
|
||||
use \WP_Ultimo\Traits\Singleton;
|
||||
|
||||
/**
|
||||
* The id of the element.
|
||||
*
|
||||
* Something simple, without prefixes, like 'checkout', or 'pricing-tables'.
|
||||
*
|
||||
* This is used to construct shortcodes by prefixing the id with 'wu_'
|
||||
* e.g. an id checkout becomes the shortcode 'wu_checkout' and
|
||||
* to generate the Gutenberg block by prefixing it with 'wp-ultimo/'
|
||||
* e.g. checkout would become the block 'wp-ultimo/checkout'.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @var string
|
||||
*/
|
||||
public $id = 'thank-you';
|
||||
|
||||
/**
|
||||
* The payment object.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @var \WP_Ultimo\Payment
|
||||
*/
|
||||
protected $payment;
|
||||
|
||||
/**
|
||||
* The membership object.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @var \WP_Ultimo\Membership
|
||||
*/
|
||||
protected $membership;
|
||||
|
||||
/**
|
||||
* The customer object.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @var \WP_Ultimo\Customer
|
||||
*/
|
||||
protected $customer;
|
||||
|
||||
/**
|
||||
* The icon of the UI element.
|
||||
* e.g. return fa fa-search
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @param string $context One of the values: block, elementor or bb.
|
||||
*/
|
||||
public function get_icon($context = 'block'): string {
|
||||
|
||||
if ($context === 'elementor') {
|
||||
|
||||
return 'eicon-info-circle-o';
|
||||
|
||||
} // end if;
|
||||
|
||||
return 'fa fa-search';
|
||||
|
||||
} // end get_icon;
|
||||
|
||||
/**
|
||||
* Overload the init to add site-related forms.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return void
|
||||
*/
|
||||
public function init() {
|
||||
|
||||
parent::init();
|
||||
|
||||
} // end init;
|
||||
|
||||
/**
|
||||
* Replace the register page title with the Thank you title.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*
|
||||
* @param array $title_parts The title parts.
|
||||
* @return array
|
||||
*/
|
||||
public function replace_page_title($title_parts) {
|
||||
|
||||
$title_parts['title'] = $this->get_title();
|
||||
|
||||
return $title_parts;
|
||||
|
||||
} // end replace_page_title;
|
||||
|
||||
/**
|
||||
* Maybe clear the title at the content level.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*
|
||||
* @param string $title The page title.
|
||||
* @param int $id The post/page id.
|
||||
* @return string
|
||||
*/
|
||||
public function maybe_replace_page_title($title, $id) {
|
||||
|
||||
global $post;
|
||||
|
||||
if ($post && $post->ID === $id) {
|
||||
|
||||
return '';
|
||||
|
||||
} // end if;
|
||||
|
||||
return $title;
|
||||
|
||||
} // end maybe_replace_page_title;
|
||||
|
||||
/**
|
||||
* Register additional scripts for the thank you page.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return void
|
||||
*/
|
||||
public function register_scripts() {
|
||||
|
||||
$has_pending_site = $this->membership ? (bool) $this->membership->get_pending_site() : false;
|
||||
$is_publishing = $has_pending_site ? $this->membership->get_pending_site()->is_publishing() : false;
|
||||
|
||||
wp_register_script('wu-thank-you', wu_get_asset('thank-you.js', 'js'), array(), wu_get_version());
|
||||
|
||||
wp_localize_script('wu-thank-you', 'wu_thank_you', array(
|
||||
'creating' => $is_publishing,
|
||||
'has_pending_site' => $has_pending_site,
|
||||
'next_queue' => wu_get_next_queue_run(),
|
||||
'ajaxurl' => admin_url('admin-ajax.php'),
|
||||
'resend_verification_email_nonce' => wp_create_nonce('wu_resend_verification_email_nonce'),
|
||||
'membership_hash' => $this->membership ? $this->membership->get_hash() : false,
|
||||
'i18n' => array(
|
||||
'resending_verification_email' => __('Resending verification email...', 'wp-ultimo'),
|
||||
'email_sent' => __('Verification email sent!', 'wp-ultimo'),
|
||||
),
|
||||
));
|
||||
|
||||
wp_enqueue_script('wu-thank-you');
|
||||
|
||||
} // end register_scripts;
|
||||
|
||||
/**
|
||||
* The title of the UI element.
|
||||
*
|
||||
* This is used on the Blocks list of Gutenberg.
|
||||
* You should return a string with the localized title.
|
||||
* e.g. return __('My Element', 'wp-ultimo').
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return string
|
||||
*/
|
||||
public function get_title() {
|
||||
|
||||
return __('Thank You', 'wp-ultimo');
|
||||
|
||||
} // end get_title;
|
||||
|
||||
/**
|
||||
* The description of the UI element.
|
||||
*
|
||||
* This is also used on the Gutenberg block list
|
||||
* to explain what this block is about.
|
||||
* You should return a string with the localized title.
|
||||
* e.g. return __('Adds a checkout form to the page', 'wp-ultimo').
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return string
|
||||
*/
|
||||
public function get_description() {
|
||||
|
||||
return __('Adds a checkout form block to the page.', 'wp-ultimo');
|
||||
|
||||
} // end get_description;
|
||||
|
||||
/**
|
||||
* The list of fields to be added to Gutenberg.
|
||||
*
|
||||
* If you plan to add Gutenberg controls to this block,
|
||||
* you'll need to return an array of fields, following
|
||||
* our fields interface (@see inc/ui/class-field.php).
|
||||
*
|
||||
* You can create new Gutenberg panels by adding fields
|
||||
* with the type 'header'. See the Checkout Elements for reference.
|
||||
*
|
||||
* @see inc/ui/class-checkout-element.php
|
||||
*
|
||||
* Return an empty array if you don't have controls to add.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return array
|
||||
*/
|
||||
public function fields() {
|
||||
|
||||
$fields = array();
|
||||
|
||||
$fields['header'] = array(
|
||||
'title' => __('General', 'wp-ultimo'),
|
||||
'desc' => __('General', 'wp-ultimo'),
|
||||
'type' => 'header',
|
||||
);
|
||||
|
||||
$fields['title'] = array(
|
||||
'type' => 'text',
|
||||
'title' => __('Title', 'wp-ultimo'),
|
||||
'value' => __('Thank You', 'wp-ultimo'),
|
||||
'desc' => __('Leave blank to hide the title completely.', 'wp-ultimo'),
|
||||
'tooltip' => '',
|
||||
);
|
||||
|
||||
$fields['thank_you_message'] = array(
|
||||
'type' => 'textarea',
|
||||
'title' => __('Thank You Message', 'wp-ultimo'),
|
||||
'desc' => __('Shortcodes are supported.', 'wp-ultimo'),
|
||||
'value' => __('Thank you for your payment! Your transaction has been completed and a receipt for your purchase has been emailed to you.', 'wp-ultimo'),
|
||||
'tooltip' => '',
|
||||
'html_attr' => array(
|
||||
'rows' => 4,
|
||||
),
|
||||
);
|
||||
|
||||
$fields['title_pending'] = array(
|
||||
'type' => 'text',
|
||||
'title' => __('Title (Pending)', 'wp-ultimo'),
|
||||
'value' => __('Thank You', 'wp-ultimo'),
|
||||
'desc' => __('Leave blank to hide the title completely. This title is used when the payment was not yet confirmed.', 'wp-ultimo'),
|
||||
'tooltip' => '',
|
||||
);
|
||||
|
||||
$fields['thank_you_message_pending'] = array(
|
||||
'type' => 'textarea',
|
||||
'title' => __('Thank You Message (Pending)', 'wp-ultimo'),
|
||||
'desc' => __('This content is used when the payment was not yet confirmed. Shortcodes are supported.', 'wp-ultimo'),
|
||||
'value' => __('Thank you for your order! We are waiting on the payment processor to confirm your payment, which can take up to 5 minutes. We will notify you via email when your site is ready.', 'wp-ultimo'),
|
||||
'tooltip' => '',
|
||||
'html_attr' => array(
|
||||
'rows' => 4,
|
||||
),
|
||||
);
|
||||
|
||||
$fields['no_sites_message'] = array(
|
||||
'type' => 'textarea',
|
||||
'title' => __('No Sites Message', 'wp-ultimo'),
|
||||
'desc' => __('A message to show if membership has no sites. Shortcodes are supported.', 'wp-ultimo'),
|
||||
'value' => __('No sites found', 'wp-ultimo'),
|
||||
'tooltip' => '',
|
||||
'html_attr' => array(
|
||||
'rows' => 4,
|
||||
),
|
||||
);
|
||||
|
||||
return $fields;
|
||||
|
||||
} // end fields;
|
||||
|
||||
/**
|
||||
* The list of keywords for this element.
|
||||
*
|
||||
* Return an array of strings with keywords describing this
|
||||
* element. Gutenberg uses this to help customers find blocks.
|
||||
*
|
||||
* e.g.:
|
||||
* return array(
|
||||
* 'WP Ultimo',
|
||||
* 'Billing Information',
|
||||
* 'Form',
|
||||
* 'Cart',
|
||||
* );
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return array
|
||||
*/
|
||||
public function keywords() {
|
||||
|
||||
return array(
|
||||
'WP Ultimo',
|
||||
'Thank You',
|
||||
'Form',
|
||||
'Cart',
|
||||
);
|
||||
|
||||
} // end keywords;
|
||||
|
||||
/**
|
||||
* List of default parameters for the element.
|
||||
*
|
||||
* If you are planning to add controls using the fields,
|
||||
* it might be a good idea to use this method to set defaults
|
||||
* for the parameters you are expecting.
|
||||
*
|
||||
* These defaults will be used inside a 'wp_parse_args' call
|
||||
* before passing the parameters down to the block render
|
||||
* function and the shortcode render function.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return array
|
||||
*/
|
||||
public function defaults() {
|
||||
|
||||
return array(
|
||||
'title' => __('Thank You', 'wp-ultimo'),
|
||||
'thank_you_message' => __('Thank you for your payment! Your transaction has been completed and a receipt for your purchase has been emailed to you.', 'wp-ultimo'),
|
||||
'title_pending' => __('Thank You', 'wp-ultimo'),
|
||||
'thank_you_message_pending' => __('Thank you for your order! We are waiting on the payment processor to confirm your payment, which can take up to 5 minutes. We will notify you via email when your site is ready.', 'wp-ultimo'),
|
||||
'no_sites_message' => __('No sites found', 'wp-ultimo'),
|
||||
);
|
||||
|
||||
} // end defaults;
|
||||
|
||||
/**
|
||||
* Runs early on the request lifecycle as soon as we detect the shortcode is present.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return void
|
||||
*/
|
||||
public function setup() {
|
||||
|
||||
$this->payment = wu_get_payment_by_hash(wu_request('payment'));
|
||||
|
||||
if (!$this->payment) {
|
||||
|
||||
$this->set_display(false);
|
||||
|
||||
return;
|
||||
|
||||
} // end if;
|
||||
|
||||
$this->membership = $this->payment->get_membership();
|
||||
|
||||
if (!$this->membership || !$this->membership->is_customer_allowed()) {
|
||||
|
||||
$this->set_display(false);
|
||||
|
||||
return;
|
||||
|
||||
} // end if;
|
||||
|
||||
$this->customer = $this->membership->get_customer();
|
||||
|
||||
add_filter('document_title_parts', array($this, 'replace_page_title'));
|
||||
|
||||
add_filter('the_title', array($this, 'maybe_replace_page_title'), 10, 2);
|
||||
|
||||
} // end setup;
|
||||
|
||||
/**
|
||||
* Allows the setup in the context of previews.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return void
|
||||
*/
|
||||
public function setup_preview() {
|
||||
|
||||
$this->payment = wu_mock_payment();
|
||||
|
||||
$this->membership = wu_mock_membership();
|
||||
|
||||
$this->customer = wu_mock_customer();
|
||||
|
||||
} // end setup_preview;
|
||||
|
||||
/**
|
||||
* The content to be output on the screen.
|
||||
*
|
||||
* Should return HTML markup to be used to display the block.
|
||||
* This method is shared between the block render method and
|
||||
* the shortcode implementation.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*
|
||||
* @param array $atts Parameters of the block/shortcode.
|
||||
* @param string|null $content The content inside the shortcode.
|
||||
* @return string
|
||||
*/
|
||||
public function output($atts, $content = null) {
|
||||
|
||||
$atts['payment'] = $this->payment;
|
||||
|
||||
$atts['membership'] = $this->membership;
|
||||
|
||||
$atts['customer'] = $this->customer;
|
||||
|
||||
$atts = wp_parse_args($atts, $this->defaults());
|
||||
|
||||
/*
|
||||
* Deal with conversion tracking
|
||||
*/
|
||||
$conversion_snippets = $atts['checkout_form']->get_conversion_snippets();
|
||||
|
||||
if (!empty($conversion_snippets)) {
|
||||
|
||||
$product_ids = array();
|
||||
|
||||
foreach ($this->payment->get_line_items() as $line_item) {
|
||||
|
||||
if ($line_item->get_product_id()) {
|
||||
|
||||
$product_ids[] = (string) $line_item->get_product_id();
|
||||
|
||||
} // end if;
|
||||
|
||||
} // end foreach;
|
||||
|
||||
$conversion_placeholders = apply_filters( 'wu_conversion_placeholders', array(
|
||||
'CUSTOMER_ID' => $this->customer->get_id(),
|
||||
'CUSTOMER_EMAIL' => $this->customer->get_email_address(),
|
||||
'MEMBERSHIP_DURATION' => $this->membership->get_recurring_description(),
|
||||
'MEMBERSHIP_PLAN' => $this->membership->get_plan_id(),
|
||||
'MEMBERSHIP_AMOUNT' => $this->membership->get_amount(),
|
||||
'ORDER_ID' => $this->payment->get_hash(),
|
||||
'ORDER_CURRENCY' => $this->payment->get_currency(),
|
||||
'ORDER_PRODUCTS' => array_values($product_ids),
|
||||
'ORDER_AMOUNT' => $this->payment->get_total(),
|
||||
));
|
||||
|
||||
foreach ($conversion_placeholders as $placeholder => $value) {
|
||||
|
||||
$conversion_snippets = preg_replace('/\%\%\s?' . $placeholder . '\s?\%\%/', json_encode($value), (string) $conversion_snippets);
|
||||
|
||||
} // end foreach;
|
||||
|
||||
add_action('wp_print_footer_scripts', function() use ($conversion_snippets) {
|
||||
|
||||
echo $conversion_snippets;
|
||||
|
||||
});
|
||||
|
||||
} // end if;
|
||||
|
||||
/*
|
||||
* Account for the 'className' Gutenberg attribute.
|
||||
*/
|
||||
$atts['className'] = trim('wu-' . $this->id . ' ' . wu_get_isset($atts, 'className', ''));
|
||||
|
||||
return wu_get_template_contents('dashboard-widgets/thank-you', $atts);
|
||||
|
||||
} // end output;
|
||||
|
||||
} // end class Thank_You_Element;
|
113
inc/ui/class-toolbox.php
Normal file
113
inc/ui/class-toolbox.php
Normal file
@ -0,0 +1,113 @@
|
||||
<?php
|
||||
/**
|
||||
* Adds the Toolbox UI to the Admin Panel.
|
||||
*
|
||||
* @package WP_Ultimo
|
||||
* @subpackage UI
|
||||
* @since 2.0.0
|
||||
*/
|
||||
|
||||
namespace WP_Ultimo\UI;
|
||||
|
||||
use WP_Ultimo\Logger;
|
||||
use WP_Ultimo\UI\Base_Element;
|
||||
use WP_Ultimo\License;
|
||||
|
||||
// Exit if accessed directly
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
/**
|
||||
* Adds the Toolbox UI to the Admin Panel.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
class Toolbox {
|
||||
|
||||
use \WP_Ultimo\Traits\Singleton;
|
||||
|
||||
/**
|
||||
* Element construct.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function __construct() {
|
||||
|
||||
add_action('init', array($this, 'load_toolbox'));
|
||||
|
||||
} // end __construct;
|
||||
|
||||
/**
|
||||
* Checks if we should add the toolbox or not.
|
||||
*
|
||||
* @todo fix the check for license activation.
|
||||
* @since 2.0.0
|
||||
* @return boolean
|
||||
*/
|
||||
protected function is_toolbox_enabled() {
|
||||
|
||||
$can_see_toolbox = current_user_can('manage_network');
|
||||
|
||||
if (class_exists('\user_switching') && !$can_see_toolbox) {
|
||||
|
||||
$old_user = \user_switching::get_old_user();
|
||||
|
||||
$can_see_toolbox = user_can($old_user, 'manage_network');
|
||||
|
||||
} // end if;
|
||||
|
||||
return apply_filters('wu_is_toolbox_enabled', wu_get_setting('enable_jumper', true) && License::get_instance()->allowed() && $can_see_toolbox && !is_network_admin());
|
||||
|
||||
} // end is_toolbox_enabled;
|
||||
|
||||
/**
|
||||
* Loads the necessary elements to display the Toolbox.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return void
|
||||
*/
|
||||
public function load_toolbox() {
|
||||
|
||||
if ($this->is_toolbox_enabled()) {
|
||||
|
||||
add_action('wp_footer', array($this, 'output'));
|
||||
|
||||
add_action('admin_footer', array($this, 'output'));
|
||||
|
||||
add_action('wp_enqueue_scripts', array($this, 'enqueue_styles'));
|
||||
|
||||
} // end if;
|
||||
|
||||
} // end load_toolbox;
|
||||
|
||||
/**
|
||||
* Adds the admin styles to make sure the tooltip renders.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return void
|
||||
*/
|
||||
public function enqueue_styles() {
|
||||
|
||||
wp_enqueue_style('wu-admin');
|
||||
|
||||
} // end enqueue_styles;
|
||||
|
||||
/**
|
||||
* Outputs the actual HTML markup of the Toolbox.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return void
|
||||
*/
|
||||
public function output() {
|
||||
|
||||
$current_site = wu_get_current_site();
|
||||
|
||||
wu_get_template('ui/toolbox', array(
|
||||
'toolbox' => $this,
|
||||
'current_site' => $current_site,
|
||||
'customer' => $current_site ? $current_site->get_customer() : false,
|
||||
'membership' => $current_site ? $current_site->get_membership() : false,
|
||||
));
|
||||
|
||||
} // end output;
|
||||
|
||||
} // end class Toolbox;
|
176
inc/ui/class-tours.php
Normal file
176
inc/ui/class-tours.php
Normal file
@ -0,0 +1,176 @@
|
||||
<?php
|
||||
/**
|
||||
* Adds the Tours UI to the Admin Panel.
|
||||
*
|
||||
* @package WP_Ultimo
|
||||
* @subpackage UI
|
||||
* @since 2.0.0
|
||||
*/
|
||||
|
||||
namespace WP_Ultimo\UI;
|
||||
|
||||
// Exit if accessed directly
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
/**
|
||||
* Adds the Tours UI to the Admin Panel.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
class Tours {
|
||||
|
||||
use \WP_Ultimo\Traits\Singleton;
|
||||
|
||||
/**
|
||||
* Registered tours.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @var array
|
||||
*/
|
||||
protected $tours = array();
|
||||
|
||||
/**
|
||||
* Element construct.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function __construct() {
|
||||
|
||||
add_action('wp_ajax_wu_mark_tour_as_finished', array($this, 'mark_as_finished'));
|
||||
|
||||
add_action('admin_enqueue_scripts', array($this, 'register_scripts'));
|
||||
|
||||
add_action('in_admin_footer', array($this, 'enqueue_scripts'));
|
||||
|
||||
} // end __construct;
|
||||
|
||||
/**
|
||||
* Mark the tour as finished for a particular user.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return void
|
||||
*/
|
||||
public function mark_as_finished() {
|
||||
|
||||
check_ajax_referer('wu_tour_finished', 'nonce');
|
||||
|
||||
$id = wu_request('tour_id');
|
||||
|
||||
if ($id) {
|
||||
|
||||
set_user_setting("wu_tour_$id", true);
|
||||
|
||||
wp_send_json_success();
|
||||
|
||||
} // end if;
|
||||
|
||||
wp_send_json_error();
|
||||
|
||||
} // end mark_as_finished;
|
||||
|
||||
/**
|
||||
* Register the necessary scripts.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return void
|
||||
*/
|
||||
public function register_scripts() {
|
||||
|
||||
WP_Ultimo()->scripts->register_script('wu-shepherd', wu_get_asset('lib/shepherd.js', 'js'), array());
|
||||
|
||||
WP_Ultimo()->scripts->register_script('wu-tours', wu_get_asset('tours.js', 'js'), array('wu-shepherd', 'underscore'));
|
||||
|
||||
} // end register_scripts;
|
||||
|
||||
/**
|
||||
* Enqueues the scripts, if we need to.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return void
|
||||
*/
|
||||
public function enqueue_scripts() {
|
||||
|
||||
if ($this->has_tours()) {
|
||||
|
||||
wp_localize_script('wu-tours', 'wu_tours', $this->tours);
|
||||
|
||||
wp_localize_script('wu-tours', 'wu_tours_vars', array(
|
||||
'ajaxurl' => wu_ajax_url(),
|
||||
'nonce' => wp_create_nonce('wu_tour_finished'),
|
||||
'i18n' => array(
|
||||
'next' => __('Next', 'wp-ultimo'),
|
||||
'finish' => __('Close', 'wp-ultimo')
|
||||
),
|
||||
));
|
||||
|
||||
wp_enqueue_script('wu-tours');
|
||||
|
||||
} // end if;
|
||||
|
||||
} // end enqueue_scripts;
|
||||
|
||||
/**
|
||||
* Checks if we have registered tours.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return boolean
|
||||
*/
|
||||
public function has_tours() {
|
||||
|
||||
return !empty($this->tours);
|
||||
|
||||
} // end has_tours;
|
||||
|
||||
/**
|
||||
* Register a new tour.
|
||||
*
|
||||
* @see https://shepherdjs.dev/docs/
|
||||
*
|
||||
* @since 2.0.0
|
||||
*
|
||||
* @param string $id The id of the tour.
|
||||
* @param array $steps The tour definition. Check shepherd.js docs.
|
||||
* @param boolean $once Whether or not we will show this more than once.
|
||||
* @return void
|
||||
*/
|
||||
public function create_tour($id, $steps = array(), $once = true) {
|
||||
|
||||
if (did_action('in_admin_header')) {
|
||||
|
||||
return;
|
||||
|
||||
} // end if;
|
||||
|
||||
add_action('in_admin_header', function() use ($id, $steps, $once) {
|
||||
|
||||
$force_hide = wu_get_setting('hide_tours', false);
|
||||
|
||||
if ($force_hide) {
|
||||
|
||||
return;
|
||||
|
||||
} // end if;
|
||||
|
||||
$finished = (bool) get_user_setting("wu_tour_$id", false);
|
||||
|
||||
$finished = apply_filters('wu_tour_finished', $finished, $id, get_current_user_id());
|
||||
|
||||
if (!$finished || !$once) {
|
||||
|
||||
foreach ($steps as &$step) {
|
||||
|
||||
$step['text'] = is_array($step['text']) ? implode('</p><p>', $step['text']) : $step['text'];
|
||||
|
||||
$step['text'] = sprintf('<p>%s</p>', $step['text']);
|
||||
|
||||
} // end foreach;
|
||||
|
||||
$this->tours[$id] = $steps;
|
||||
|
||||
} // end if;
|
||||
|
||||
});
|
||||
|
||||
} // end create_tour;
|
||||
|
||||
} // end class Tours;
|
Reference in New Issue
Block a user