File "class-hustle-module-page-abstract.php"
Full Path: /home/londdqdw/public_html/06/wp-content/plugins/wordpress-popup/inc/class-hustle-module-page-abstract.php
File size: 43.16 KB
MIME-type: text/x-php
Charset: utf-8
<?php
/**
* File for Hustle_Module_Page_Abstract class.
*
* @package Hustle
* @since 4.0.1
*/
/**
* Class Hustle_Module_Page.
* Base model for the listing pages and their wizards.
*
* @since 4.0.1
*/
abstract class Hustle_Module_Page_Abstract extends Hustle_Admin_Page_Abstract {
/**
* Edit page slug defined by WordPress when registering the page.
*
* @since 4.3.1
* @var string
*/
private $page_edit_slug;
/**
* Wizard page slug assigned by us.
*
* @since 4.0.1
* @var string
*/
protected $page_edit;
/**
* Wizard page title.
*
* @since 4.0.1
* @var string
*/
protected $page_edit_title;
/**
* Capability required for the wizard page to be available.
*
* @since 4.0.1
* @var string
*/
protected $page_edit_capability;
/**
* Path to the wizard's template page relative to the 'views' folder.
*
* @since 4.0.1
* @var string
*/
protected $page_edit_template_path;
/**
* Current module. Only set on wizards when the module exists.
*
* @since 4.0.3
* @var integer
*/
protected $module = false;
/**
* Count of the active module of the current type.
*
* @since 4.2.0
* @var integer
*/
private $module_count_type;
/**
* Module type this page belongs to.
*
* @since 4.2.0
* @var string
*/
public $module_type;
/**
* Established the properties for the page.
*
* @since 4.0.1
*/
protected function init() {
$this->set_page_properties();
$this->page_menu_title = $this->page_title;
$this->page = Hustle_Data::get_listing_page_by_module_type( $this->module_type );
$this->page_capability = 'hustle_edit_module';
$this->page_edit = Hustle_Data::get_wizard_page_by_module_type( $this->module_type );
$this->page_edit_capability = 'hustle_edit_module';
/* translators: module's type */
$this->page_edit_title = sprintf( esc_html__( 'New %s', 'hustle' ), Opt_In_Utils::get_module_type_display_name( $this->module_type ) );
add_filter( 'submenu_file', array( $this, 'admin_submenu_file' ), 10, 2 );
add_action( 'admin_head', array( $this, 'hide_unwanted_submenus' ) );
// Admin-menu-editor compatibility.
add_action( 'admin_menu_editor-menu_replaced', array( $this, 'hide_unwanted_submenus' ) );
// Actions to perform when the current page is the listing or the wizard page.
if ( ! empty( $this->current_page ) && ( $this->current_page === $this->page || $this->current_page === $this->page_edit ) ) {
$this->on_listing_and_wizard_actions();
}
}
/**
* Set up the page's own properties
* Like the current module type, page title, path to the listing page and wizard page template.
*
* @since 4.0.2
*/
abstract protected function set_page_properties();
/**
* Actions to be performed on Dashboard page.
*
* @since 4.0.4
*/
protected function on_listing_and_wizard_actions() {
if ( $this->page_edit === $this->current_page ) {
$this->on_wizard_only_actions();
} else {
$this->on_listing_only_actions();
}
}
/**
* Actions to run on listing pages only
*
* @since 4.2.0
*/
private function on_listing_only_actions() {
add_filter( 'removable_query_args', array( $this, 'maybe_remove_paged' ) );
add_action( 'admin_enqueue_scripts', array( $this, 'register_listing_scripts' ), 99 );
}
/**
* Remove paged get attribute if there isn't a module and it's not the first page
*
* @since 4.0.0
* @param array $removable_query_args URL query args to be removed.
* @return array
*/
public function maybe_remove_paged( $removable_query_args ) {
$paged = filter_input( INPUT_GET, 'paged', FILTER_VALIDATE_INT );
$module_type = $this->module_type;
if ( $paged && 1 !== $paged && $module_type ) {
$args = array(
'module_type' => $module_type,
'page' => $paged,
);
$entries_per_page = Hustle_Settings_Admin::get_per_page( 'module' );
$modules = Hustle_Module_Collection::instance()->get_all( null, $args, $entries_per_page );
if ( empty( $modules ) ) {
$_SERVER['REQUEST_URI'] = remove_query_arg( 'paged' );
$removable_query_args[] = 'paged';
unset( $_GET['paged'] ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
}
}
if ( $module_type ) {
self::maybe_view_stats( $module_type );
}
return $removable_query_args;
}
/**
* Change pagination page to the relevant one for View Stats links
*
* @param string $module_type Module type.
*/
private static function maybe_view_stats( $module_type ) {
$module_id = filter_input( INPUT_GET, 'view-stats', FILTER_VALIDATE_INT );
if ( ! $module_id ) {
return;
}
$module_id = (string) $module_id;
$args = array(
'module_type' => $module_type,
'fields' => 'ids',
);
$entries_per_page = Hustle_Settings_Admin::get_per_page( 'module' );
$modules = Hustle_Module_Collection::instance()->get_all( null, $args );
$i = array_search( $module_id, $modules, true );
if ( false === $i ) {
return;
}
$paged = ceil( ( $i + 1 ) / $entries_per_page );
if ( 1 < $paged ) {
$_GET['paged'] = $paged;
}
}
/**
* Actions to run on wizard pages only
*
* @since 4.0.3
*/
private function on_wizard_only_actions() {
// Set the current module on Wizards, abort if invalid.
$module_id = filter_input( INPUT_GET, 'id', FILTER_VALIDATE_INT );
$module = Hustle_Module_Collection::instance()->return_model_from_id( $module_id );
if ( is_wp_error( $module ) ) {
// Redirect asap.
add_action( 'admin_init', array( $this, 'redirect_module_not_found' ) );
return;
}
$this->module = $module;
// Scripts for all wizards.
add_action( 'admin_enqueue_scripts', array( $this, 'register_wizard_scripts' ) );
if ( Hustle_Module_Model::SOCIAL_SHARING_MODULE !== $this->module_type ) {
// Scripts for non ssharing wizards.
add_action( 'admin_enqueue_scripts', array( $this, 'register_non_sshare_wizard_scripts' ) );
// Allow rich editor in.
add_filter( 'user_can_richedit', '__return_true' );
// Set up all the filters and buttons for tinymce editors.
$this->set_up_tinymce();
// Add hustle's button to tinymce editor.
add_filter( 'mce_buttons', array( $this, 'register_tinymce_buttons' ) );
add_filter( 'mce_external_plugins', array( $this, 'add_hustle_tinymce_button_and_remove_externals' ) );
}
}
/**
* Scripts used in all wizards
* They used to be enqueued by Hustle_Module_Admin.
*
* @since 4.2.0
*/
public function register_wizard_scripts() {
wp_enqueue_script( 'jquery-ui-sortable' );
wp_enqueue_script( 'fast_wistia', '//fast.wistia.com/assets/external/E-v1.js', array(), '1', true );
self::add_color_picker();
}
/**
* Scripts used in all listings.
* They used to be enqueued by Hustle_Module_Admin.
*
* @since 4.2.0
*/
public function register_listing_scripts() {
wp_enqueue_script(
'chartjs',
Opt_In::$plugin_url . 'assets/js/vendor/chartjs/chart.min.js',
array(),
'2.7.2',
true
);
}
/**
* Register the scripts used in wizards, but not in the Ssharing one
* Scripts used to be enqueued by Hustle_Module_Admin.
*
* @since 4.2.0
*/
public function register_non_sshare_wizard_scripts() {
wp_enqueue_script( 'thickbox' );
wp_enqueue_media();
wp_enqueue_script( 'media-upload' );
Opt_In_Utils::maybe_add_scripts_for_ie();
// Datepicker and timpicker for automated email in optins.
wp_enqueue_script( 'jquery-ui-datepicker' );
wp_enqueue_script(
'jquery-ui-timepicker',
Opt_In::$plugin_url . 'assets/js/vendor/jquery.timepicker.min.js',
array( 'jquery' ),
'1.3.5',
true
);
wp_enqueue_style(
'jquery-ui-timepicker',
Opt_In::$plugin_url . 'assets/css/jquery.timepicker.min.css',
array(),
'1.3.5'
);
// Register moment.js and its timezone extension.
// Used for schedule, to calculate time with timezones on client side.
wp_enqueue_script(
'hustle-moment',
Opt_In::$plugin_url . 'assets/js/vendor/moment.min.js',
array( 'jquery' ),
Opt_In::VERSION,
true
);
wp_enqueue_script(
'hustle-moment-timezone',
Opt_In::$plugin_url . 'assets/js/vendor/moment-timezone-with-data.min.js',
array( 'hustle-moment' ),
Opt_In::VERSION,
true
);
}
/**
* Removing all MCE external plugins which often break our pages and add Hustle's button
*
* @since 3.0.8
* @param array $external_plugins External plugins.
* @return array
*/
public function add_hustle_tinymce_button_and_remove_externals( $external_plugins ) {
remove_all_filters( 'mce_external_plugins' );
$external_plugins = array();
$external_plugins['hustle'] = Opt_In::$plugin_url . 'assets/js/vendor/tiny-mce-button.js';
add_action( 'admin_footer', array( $this, 'add_tinymce_variables' ) );
return $external_plugins;
}
/**
* Add the current fields to the editor's selector
*
* @since 3.0.8
*/
public function add_tinymce_variables() {
$var_button = array();
$saved_fields = $this->module->get_form_fields();
$var_button = array();
if ( is_array( $saved_fields ) && ! empty( $saved_fields ) ) {
$fields = array();
$ignored_fields = Hustle_Entry_Model::ignored_fields();
foreach ( $saved_fields as $field_name => $data ) {
if ( ! in_array( $data['type'], $ignored_fields, true ) ) {
$fields[ $field_name ] = esc_html( $data['label'] );
}
}
// Add Unsubscribe Link.
$fields['hustle_unsubscribe_link'] = esc_html__( 'Unsubscribe Link', 'hustle' );
$available_editors = array( 'success_message', 'email_body' );
/**
* Print JS details for the custom TinyMCE "Insert Variable" button
*
* @see assets/js/vendor/tiny-mce-button.js
*/
$var_button = array(
/* translators: Plugin name */
'button_title' => sprintf( __( 'Add %s Fields', 'hustle' ), Opt_In_Utils::get_plugin_name() ),
'fields' => $fields,
'available_editors' => $available_editors,
);
}
printf(
'<script>window.hustleData = %s;</script>',
wp_json_encode( $var_button )
);
}
/**
* Register hustle's button for tinymce
*
* @since 4.0.0
* @since 4.2.0 Moved from Hustle_Module_Admin to this class.
*
* @param array $buttons Registered buttons.
* @return array
*/
public function register_tinymce_buttons( $buttons ) {
array_unshift( $buttons, 'hustlefields' );
return $buttons;
}
/**
* Register the listing page and its wizard
*
* @return void
*/
public function register_admin_menu() {
parent::register_admin_menu();
$this->page_edit_slug = add_submenu_page( 'hustle', $this->page_edit_title, $this->page_edit_title, $this->page_edit_capability, $this->page_edit, array( $this, 'render_edit_page' ) );
add_action( 'load-' . $this->page_edit_slug, array( $this, 'current_page_loaded' ) );
}
/**
* Get the arguments used when rendering the main page.
*
* @since 4.0.1
* @return array
*/
protected function get_page_template_args() {
$entries_per_page = Hustle_Settings_Admin::get_per_page( 'module' );
$capability = array(
'hustle_create' => current_user_can( 'hustle_create' ),
'hustle_access_emails' => current_user_can( 'hustle_access_emails' ),
);
// Don't use filter_input() here, because of see Hustle_Module_Admin::maybe_remove_paged function.
$paged = ! empty( $_GET['paged'] ) ? (int) $_GET['paged'] : 1; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
$args = array(
'module_type' => $this->module_type,
'page' => $paged,
'filter' => array( 'can_edit' => true ),
);
$search = filter_input( INPUT_GET, 'q' );
if ( $search ) {
$args['filter']['q'] = $search;
}
$modules = Hustle_Module_Collection::instance()->get_all(
null,
$args,
$entries_per_page
);
$active_modules = Hustle_Module_Collection::instance()->get_all(
true,
array(
'module_type' => $this->module_type,
'count_only' => true,
)
);
return array(
'total' => $this->get_total_count_modules_current_type(),
'active' => $active_modules,
'modules' => $modules,
'is_free' => Opt_In_Utils::is_free(),
'capability' => $capability,
'entries_per_page' => $entries_per_page,
'message' => filter_input( INPUT_GET, 'message', FILTER_SANITIZE_SPECIAL_CHARS ),
'sui' => $this->get_sui_summary_config( '' ),
);
}
/**
* Hide module's edit pages from the submenu on dashboard.
*
* @since 4.0.1
*/
public function hide_unwanted_submenus() {
remove_submenu_page( 'hustle', $this->page_edit );
}
/**
* Highlight submenu's parent on admin page.
*
* @since 4.0.1
*
* @param string $submenu_file The submenu file.
* @param string $parent_file The submenu item's parent file.
*
* @return string
*/
public function admin_submenu_file( $submenu_file, $parent_file ) {
global $plugin_page;
if ( 'hustle' !== $parent_file ) {
return $submenu_file;
}
if ( $this->page_edit === $plugin_page ) {
$submenu_file = $this->page;
}
return $submenu_file;
}
/**
* Redirect to the listing page when in wizard and the module wasn't found.
*
* @since 4.0.0
*/
public function redirect_module_not_found() {
// We're on wizard, but the current module isn't valid. Aborting.
$url = add_query_arg(
array(
'page' => $this->page,
'show-notice' => 'error',
'notice' => 'module-not-found',
'notice-close' => 'false',
),
'admin.php'
);
wp_safe_redirect( $url );
exit;
}
/**
* Add data to the current json array.
*
* @since 4.3.1
*
* @return array
*/
protected function get_vars_to_localize() {
$current_array = parent::get_vars_to_localize();
// Wizard page only.
if ( $this->module ) {
$data = $this->module->get_data();
$module_metas = $this->module->get_module_metas_as_array();
$current_array = $this->register_visibility_conditions_js_vars( $current_array );
$current_array += $this->get_wizard_js_variables_to_localize();
$current_array['current'] = array_merge(
$module_metas,
array(
'is_optin' => 'optin' === $this->module->module_mode,
'listing_page' => $this->page,
'wizard_page' => $this->page_edit,
'section' => $this->get_current_section(),
'data' => $data,
'shortcode_id' => $this->module->get_shortcode_id(),
)
);
$type_capitalized = Opt_In_Utils::get_module_type_display_name( $this->module_type, false, true );
$type_lowercase = Opt_In_Utils::get_module_type_display_name( $this->module_type );
$messages = array(
'module_error' => esc_html__( "Couldn't save your module settings because there were some errors on {page} tab(s). Please fix those errors and try again.", 'hustle' ),
'module_error_reload' => esc_html__( 'Something went wrong. Please reload this page and try saving again', 'hustle' ),
'module_created' => /* translators: 1. module type capitalized, 2. module type in lowercase */ sprintf( esc_html__( '%1$s created successfully. Get started by adding content to your new %2$s below.', 'hustle' ), $type_capitalized, $type_lowercase ), // only when 'is_new'.
);
$current_array['single_module_action_nonce'] = wp_create_nonce( 'hustle_single_action' );
$current_array['messages'] = array_merge( $current_array['messages'], $messages );
// Listing page only.
} elseif ( $this->page === $this->current_page ) {
$current_array['current'] = array(
'wizard_page' => $this->page_edit,
'module_type' => $this->module_type,
);
$current_array['labels'] = array(
'submissions' => Hustle_Module_Model::SOCIAL_SHARING_MODULE !== $this->module_type
? /* translators: number of conversions */ esc_html__( '%d Conversions', 'hustle' )
: /* translators: number of shares */ esc_html__( '%d Shares', 'hustle' ),
/* translators: number of views */
'views' => esc_html__( '%d Views', 'hustle' ),
);
// Also defined in dashboard.
$current_array['single_module_action_nonce'] = wp_create_nonce( 'hustle_single_action' );
$total_modules = $this->get_total_count_modules_current_type();
$module_not_found_message = esc_html__( "Oops! The module you are looking for doesn't exist.", 'hustle' );
if ( 0 < $total_modules && current_user_can( 'hustle_create' ) ) {
$module_not_found_message .= sprintf(
/* translators: 1. opening 'a' tag for adding a new module, 2. closing 'a' tag, 3. opening 'a' tag for importing */
esc_html__( ' You can %1$screate%2$s a new module or %3$simport%2$s an existing module.', 'hustle' ),
'<a href="#" class="hustle-create-module">',
'</a>',
'<a href="#" class="hustle-import-module-button">'
);
}
$messages = array(
'module_imported' => esc_html__( 'Module successfully imported.', 'hustle' ),
'module_duplicated' => esc_html__( 'Module successfully duplicated.', 'hustle' ),
'module_tracking_reset' => esc_html__( "Module's tracking data successfully reset.", 'hustle' ),
'module_purge_emails' => esc_html__( "Module's Email List successfully purged.", 'hustle' ),
'module-not-found' => $module_not_found_message,
);
$current_array['messages'] = array_merge( $current_array['messages'], $messages );
}
// Both Wizard and Listing pages.
$current_array['messages']['days_and_months'] = array(
'days_full' => Hustle_Time_Helper::get_week_days(),
'days_short' => Hustle_Time_Helper::get_week_days( 'short' ),
'days_min' => Hustle_Time_Helper::get_week_days( 'min' ),
'months_full' => Hustle_Time_Helper::get_months(),
'months_short' => Hustle_Time_Helper::get_months( 'short' ),
);
$current_array['module_tabs'] = array(
'services' => esc_html__( 'Services', 'hustle' ),
'display' => esc_html__( 'Display Options', 'hustle' ),
);
return $current_array;
}
/**
* Include the visibility conditions variables required in js side.
* These used to be registered in Hustle_Module_Admin before 4.0.3.
*
* @since 4.0.3
*
* @param array $vars Current registered variables.
* @return array
*/
private function register_visibility_conditions_js_vars( $vars ) {
$post_ids = array();
$page_ids = array();
$tag_ids = array();
$cat_ids = array();
$wc_cat_ids = array();
$wc_tag_ids = array();
$tags = array();
$cats = array();
$wc_cats = array();
$wc_tags = array();
$module = new Hustle_Module_Model( filter_input( INPUT_GET, 'id', FILTER_VALIDATE_INT ) );
if ( ! is_wp_error( $module ) ) {
$settings = $module->get_visibility()->to_array();
$post_ids = $this->get_conditions_ids( $settings, 'posts' );
$page_ids = $this->get_conditions_ids( $settings, 'pages' );
$tag_ids = $this->get_conditions_ids( $settings, 'tags' );
$cat_ids = $this->get_conditions_ids( $settings, 'categories' );
if ( Opt_In_Utils::is_woocommerce_active() ) {
$wc_cat_ids = $this->get_conditions_ids( $settings, 'wc_categories' );
$wc_tag_ids = $this->get_conditions_ids( $settings, 'wc_tags' );
}
}
if ( $tag_ids ) {
$tags = array_map(
array( $this, 'terms_to_select2_data' ),
get_categories(
array(
'hide_empty' => false,
'include' => $tag_ids,
'taxonomy' => 'post_tag',
)
)
);
}
if ( $cat_ids ) {
$cats = array_map(
array( $this, 'terms_to_select2_data' ),
get_categories(
array(
'include' => $cat_ids,
'hide_empty' => false,
)
)
);
}
if ( $wc_cat_ids ) {
$wc_cats = array_map(
array( $this, 'terms_to_select2_data' ),
get_categories(
array(
'include' => $wc_cat_ids,
'hide_empty' => false,
'taxonomy' => 'product_cat',
)
)
);
}
if ( $wc_tag_ids ) {
$wc_tags = array_map(
array( $this, 'terms_to_select2_data' ),
get_categories(
array(
'include' => $wc_tag_ids,
'hide_empty' => false,
'taxonomy' => 'product_tag',
)
)
);
}
$posts = Opt_In_Utils::get_select2_data( 'post', $post_ids );
$pages = Opt_In_Utils::get_select2_data( 'page', $page_ids );
/**
* Add all custom post types
*/
$post_types = array();
$cpts = get_post_types(
array(
'public' => true,
'_builtin' => false,
),
'objects'
);
foreach ( $cpts as $cpt ) {
// Skip ms_invoice.
if ( 'ms_invoice' === $cpt->name ) {
continue;
}
$cpt_ids = $this->get_conditions_ids( $settings, $cpt->name );
$cpt_array['name'] = $cpt->name;
$cpt_array['label'] = $cpt->label;
$cpt_array['data'] = Opt_In_Utils::get_select2_data( $cpt->name, $cpt_ids );
$post_types[ $cpt->name ] = $cpt_array;
}
$vars['cats'] = $cats;
$vars['wc_cats'] = $wc_cats;
$vars['wc_tags'] = $wc_tags;
$vars['tags'] = $tags;
$vars['posts'] = $posts;
$vars['post_types'] = $post_types;
$vars['pages'] = $pages;
$vars['countries'] = Opt_In_Utils::get_countries();
$vars['roles'] = Opt_In_Utils::get_user_roles();
$vars['templates'] = Opt_In_Utils::hustle_get_page_templates();
$vars['type_singular_lower'] = Opt_In_Utils::get_module_type_display_name( $this->module_type );
// Visibility conditions titles, labels and bodies.
$vars['messages']['conditions'] = array(
'visitor_logged_in' => __( 'Logged in status', 'hustle' ),
'shown_less_than' => __( 'Number of times visitor has seen this module', 'hustle' ),
'only_on_mobile' => __( "Visitor's Device", 'hustle' ),
'from_specific_ref' => __( 'Referrer', 'hustle' ),
'from_search_engine' => __( 'Source of Arrival', 'hustle' ),
'on_specific_url' => __( 'Specific URL', 'hustle' ),
'on_specific_browser' => __( "Visitor's Browser", 'hustle' ),
'visitor_has_never_commented' => __( 'Visitor Commented Before', 'hustle' ),
'not_in_a_country' => __( "Visitor's Country", 'hustle' ),
'on_specific_roles' => __( 'User Roles', 'hustle' ),
'wp_conditions' => __( 'Static Pages', 'hustle' ),
'archive_pages' => __( 'Archive Pages', 'hustle' ),
'on_specific_templates' => __( 'Page Templates', 'hustle' ),
'user_registration' => __( 'After Registration', 'hustle' ),
'page_404' => __( '404 page', 'hustle' ),
'posts' => __( 'Posts', 'hustle' ),
'pages' => __( 'Pages', 'hustle' ),
'categories' => __( 'Categories', 'hustle' ),
'tags' => __( 'Tags', 'hustle' ),
'wc_pages' => __( 'WooCommerce Pages', 'hustle' ),
'wc_categories' => __( 'WooCommerce Categories', 'hustle' ),
'wc_tags' => __( 'WooCommerce Tags', 'hustle' ),
'wc_archive_pages' => __( 'WooCommerce Archives', 'hustle' ),
'wc_static_pages' => __( 'WooCommerce Static Pages', 'hustle' ),
'cookie_set' => __( 'Browser Cookie', 'hustle' ),
);
$vars['messages']['condition_labels'] = array(
'mobile_only' => __( 'Mobile only', 'hustle' ),
'desktop_only' => __( 'Desktop only', 'hustle' ),
'any_conditions' => __( '{number} condition(s)', 'hustle' ),
'number_views' => '< {number}',
'number_views_more' => '> {number}',
'any' => __( 'Any', 'hustle' ),
'all' => __( 'All', 'hustle' ),
'no' => __( 'No', 'hustle' ),
'none' => __( 'None', 'hustle' ),
'true' => __( 'True', 'hustle' ),
'false' => __( 'False', 'hustle' ),
'logged_in' => __( 'Logged in', 'hustle' ),
'logged_out' => __( 'Logged out', 'hustle' ),
'only_these' => __( 'Only {number}', 'hustle' ),
'except_these' => __( 'All except {number}', 'hustle' ),
'reg_date' => __( 'Day {number} ', 'hustle' ),
'immediately' => __( 'Immediately', 'hustle' ),
'forever' => __( 'Forever', 'hustle' ),
'cookie_anything' => __( '{name} is anything', 'hustle' ),
'cookie_doesnt_exist' => __( '{name} does not exist', 'hustle' ),
'cookie_value' => __( '{name} {value_condition} {value}', 'hustle' ),
);
$vars['wp_conditions'] = array(
'is_front_page' => __( 'Front page', 'hustle' ),
'is_404' => __( '404 page', 'hustle' ),
'is_search' => __( 'Search results', 'hustle' ),
);
$vars['wc_static_pages'] = array(
'is_cart' => __( 'Cart', 'hustle' ),
'is_checkout' => __( 'Checkout', 'hustle' ),
'is_order_received' => __( 'Order Received', 'hustle' ),
'is_account_page' => __( 'My account', 'hustle' ),
);
$vars['archive_pages'] = array(
'is_category' => __( 'Category archive', 'hustle' ),
'is_tag' => __( 'Tag archive', 'hustle' ),
'is_author' => __( 'Author archive', 'hustle' ),
'is_date' => __( 'Date archive', 'hustle' ),
'is_post_type_archive' => __( 'Custom post archive', 'hustle' ),
);
$vars['wc_archive_pages'] = array(
'is_shop' => __( 'Shop', 'hustle' ),
'is_product_category' => __( 'Product Category', 'hustle' ),
'is_product_tag' => __( 'Product Tag', 'hustle' ),
);
$vars['less_than_expiration'] = array(
1 => __( 'Day', 'hustle' ),
7 => __( 'Week', 'hustle' ),
30 => __( 'Month', 'hustle' ),
365 => __( 'Year', 'hustle' ),
);
$vars['wp_cookie_set'] = array(
'anything' => __( 'is anything', 'hustle' ),
'equals' => __( 'equals', 'hustle' ),
'contains' => __( 'contains', 'hustle' ),
'matches_pattern' => __( 'matches a pattern', 'hustle' ),
'doesnt_equals' => __( 'does not equals', 'hustle' ),
'doesnt_contain' => __( 'does not contain', 'hustle' ),
'doesnt_match_pattern' => __( 'does not match a pattern', 'hustle' ),
'less_than' => __( 'is less than', 'hustle' ),
'less_equal_than' => __( 'is less or equal to', 'hustle' ),
'greater_than' => __( 'is greater than', 'hustle' ),
'greater_equal_than' => __( 'is greater or equal to', 'hustle' ),
);
$vars['roles'] = Opt_In_Utils::get_user_roles();
$vars['browsers'] = Opt_In_Utils::get_browsers();
$vars['countries'] = Opt_In_Utils::get_countries();
$vars['templates'] = Opt_In_Utils::hustle_get_page_templates();
return $vars;
}
/**
* Gets the JS variables to be localized in Wizard for non-ssharing modules.
* This method is overwritten in Hustle_Sshare_Admin.
*
* @since 4.3.0
*
* @return array
*/
protected function get_wizard_js_variables_to_localize() {
$is_optin = Hustle_Module_Model::OPTIN_MODE === $this->module->module_mode;
$variables = array(
'form_fields' => $this->get_form_fields_js_vars(),
'schedule' => $this->get_schedule_js_vars(),
'palettes' => Hustle_Palettes_Helper::get_all_palettes( $is_optin ),
'integrations' => array(
'action_nonce' => wp_create_nonce( 'hustle_provider_action' ), // Also defined in integrations.
'fetching_list' => esc_html__( 'Fetching integration list…', 'hustle' ),
),
'typography' => array(
'global_font_applied' => esc_html__( 'Your font was correctly applied to all elements', 'hustle' ),
'fetch_nonce' => wp_create_nonce( 'hustle_fetch_font_families' ),
),
'media_uploader' => array(
'select_or_upload' => esc_html__( 'Select or Upload Image', 'hustle' ),
'use_this_image' => esc_html__( 'Use this image', 'hustle' ),
),
'triggers' => array(
'immediately_tag' => esc_html__( 'Immediately', 'hustle' ),
'seconds' => esc_html__( 'seconds', 'hustle' ),
'minutes' => esc_html__( 'minutes', 'hustle' ),
'hours' => esc_html__( 'hours', 'hustle' ),
/* translators: 1. {time} tag to replace, 2. {unit} tag to replace */
'delayed_tag' => sprintf( esc_html__( 'Delay %1$s %2$s', 'hustle' ), '{time}', '{unit}' ),
/* translators: {value}% tag to replace */
'scroll_percentage_tag' => sprintf( esc_html__( '%s page scroll', 'hustle' ), '{value}%' ),
/* translators: {value} tag to replace */
'scroll_element_tag' => sprintf( esc_html__( 'Scroll to %s', 'hustle' ), '{value}' ),
),
);
$variables['defaults'] = $this->get_defaults_settings();
return $variables;
}
/**
* Return default design settings
*
* @return array
*/
private function get_defaults_settings() {
$defaults = $this->module->get_design()->get_border_spacing_shadow_defaults( 'desktop' );
$defaults += $this->module->get_design()->get_typography_defaults( 'desktop' );
$defaults += $this->module->get_design()->get_border_spacing_shadow_defaults( 'mobile' );
$defaults += $this->module->get_design()->get_typography_defaults( 'mobile' );
$design_settings = $this->module->get_design()->to_array();
if ( ! empty( $design_settings['base_template'] ) ) {
// Return template settings if the module was created based on one.
$templates_helper = new Hustle_Templates_Helper();
$template_settings = $templates_helper->get_template( $design_settings['base_template'], $this->module->module_mode );
if ( ! empty( $template_settings['design'] ) ) {
$defaults = array_merge( $defaults, $template_settings['design'] );
}
}
if ( ! empty( $design_settings['base_template'] ) ) {
$defaults['base_template'] = $design_settings['base_template'];
}
return $defaults;
}
/**
* Include the form fields variables required in js side.
* These used to be registered in Hustle_Module_Admin before 4.0.3.
*
* @since 4.0.3
*
* @return array
*/
private function get_form_fields_js_vars() {
$renderer = $this->get_renderer();
$no_fields_notice_args = array(
array(
'type' => 'inline_notice',
'icon' => 'info',
'value' => __( 'You don\'t have any {field_type} field in your opt-in form.', 'hustle' ),
),
);
$variables = array(
'no_fields_of_type_notice' => $renderer->get_html_for_options( $no_fields_notice_args, true ),
'is_required' => __( '{field} is required.', 'hustle' ),
'cant_empty' => __( 'This field can\'t be empty.', 'hustle' ),
'url_required_error_message' => __( 'Your website url is required.', 'hustle' ),
'required_error_message' => __( 'Your {field} is required.', 'hustle' ),
'date_validation_message' => __( 'Please enter a valid date.', 'hustle' ),
'time_validation_message' => __( 'Please enter a valid time.', 'hustle' ),
'validation_message' => __( 'Please enter a valid {field}.', 'hustle' ),
'recaptcha_error_message' => __( 'reCAPTCHA verification failed. Please try again.', 'hustle' ),
'recaptcha_validation_message' => __( 'reCAPTCHA verification failed. Please try again.', 'hustle' ),
'gdpr_required_error_message' => __( 'Please accept the terms and try again.', 'hustle' ),
/* translators: 1. opening 'a' tag, 2. closing 'a' tag */
'gdpr_message' => sprintf( __( 'I\'ve read and accept the %1$sterms & conditions%2$s', 'hustle' ), '<a href="#">', '</a>' ),
'label' => array(
'placeholder' => __( 'Enter placeholder here', 'hustle' ),
'name_label' => __( 'Name', 'hustle' ),
'name_placeholder' => __( 'E.g. John', 'hustle' ),
'email_label' => __( 'Email Address', 'hustle' ),
'enail_placeholder' => __( 'E.g. john@doe.com', 'hustle' ),
'phone_label' => __( 'Phone Number', 'hustle' ),
'phone_placeholder' => __( 'E.g. +1 300 400 500', 'hustle' ),
'address_label' => __( 'Address', 'hustle' ),
'address_placeholder' => '',
'hidden_label' => __( 'Hidden Field', 'hustle' ),
'hidden_placeholder' => '',
'url_label' => __( 'Website', 'hustle' ),
'url_placeholder' => __( 'E.g. https://example.com', 'hustle' ),
'text_label' => __( 'Text', 'hustle' ),
'text_placeholder' => __( 'E.g. Enter your nick name', 'hustle' ),
'number_label' => __( 'Number', 'hustle' ),
'number_placeholder' => __( 'E.g. 1', 'hustle' ),
'datepicker_label' => __( 'Date', 'hustle' ),
'datepicker_placeholder' => __( 'Choose date', 'hustle' ),
'timepicker_label' => __( 'Time', 'hustle' ),
'timepicker_placeholder' => '',
'recaptcha_label' => 'reCAPTCHA',
'recaptcha_placeholder' => '',
'gdpr_label' => __( 'GDPR', 'hustle' ),
),
'recaptcha_badge_replacement' => sprintf(
/* translators: 1: closing 'a' tag, 2: opening privacy 'a' tag, 3: opening terms 'a' tag */
__( 'This site is protected by reCAPTCHA and the Google %2$sPrivacy Policy%1$s and %3$sTerms of Service%1$s apply.', 'hustle' ),
'</a>',
'<a href="https://policies.google.com/privacy" target="_blank">',
'<a href="https://policies.google.com/terms" target="_blank">'
),
);
return $variables;
}
/**
* Includes the variables used for the Schedule functionality.
*
* @since 4.3.0
*
* @return array
*/
private function get_schedule_js_vars() {
$type_lowercase = Opt_In_Utils::get_module_type_display_name( $this->module_type );
return array(
'wp_gmt_offset' => get_option( 'gmt_offset' ),
'new_schedule_set' => sprintf(
/* translators: 1. module type in lowercase */
esc_html__( 'Successfully added a schedule for your %1$s. However, make sure to save changes and publish your %1$s for it to start appearing as per your schedule.', 'hustle' ),
esc_html( $type_lowercase )
),
'months' => Hustle_Time_Helper::get_months(),
'week_days' => Hustle_Time_Helper::get_week_days( 'short' ),
'meridiem' => Hustle_Time_Helper::get_meridiam_periods(),
);
}
/**
* Gets the conditions ID.
*
* @since 3.0.7
* @since 4.0.3 moved from Hustle_Modules_Admin to here.
*
* @param array $settings Display settings.
* @param string $type posts|pages|tags|categories|{cpt}.
* @return array
*/
private function get_conditions_ids( $settings, $type ) {
$ids = array();
if ( ! empty( $settings['conditions'] ) ) {
foreach ( $settings['conditions'] as $conditions ) {
if ( ! empty( $conditions[ $type ] )
&& ( ! empty( $conditions[ $type ][ $type ] )
|| ! empty( $conditions[ $type ]['selected_cpts'] ) ) ) {
$new_ids = ! empty( $conditions[ $type ][ $type ] )
? $conditions[ $type ][ $type ]
: $conditions[ $type ]['selected_cpts'];
$ids = array_merge( $ids, $new_ids );
}
}
}
return array_unique( $ids );
}
/**
* Converts term object to usable object for select2
*
* @since 4.0.3 moved from Hustle_Modules_Admin to here.
* @param stdClass $term Term.
* @return stdClass
*/
public static function terms_to_select2_data( $term ) {
$obj = new stdClass();
$obj->id = $term->term_id;
$obj->text = $term->name;
return $obj;
}
/**
* Render the module's wizard page.
*
* @since 4.0.1
*/
public function render_edit_page() {
$template_args = $this->get_page_edit_template_args();
$allowed = Opt_In_Utils::is_user_allowed( 'hustle_edit_module', $template_args['module_id'] );
if ( ! $allowed ) {
wp_die( esc_html__( 'Sorry, you are not allowed to access this page.' ), 403 );
}
if ( Hustle_Module_Model::SOCIAL_SHARING_MODULE !== $this->module_type ) {
wp_enqueue_editor();
}
$main_class = $this->get_sui_wrap_class();
?>
<main class="<?php echo esc_attr( $main_class ); ?>">
<?php
$renderer = $this->get_renderer();
$renderer->render( $this->page_edit_template_path, $template_args );
?>
</main>
<?php
}
/**
* Get the args for the wizard page.
*
* @since 4.0.1
* @return array
*/
protected function get_page_edit_template_args() {
return array(
'section' => $this->get_current_section( 'content' ),
'module_id' => $this->module->module_id,
'module' => $this->module,
'is_active' => (bool) $this->module->active,
'is_optin' => ( 'optin' === $this->module->module_mode ),
);
}
/**
* Gets the count of the modules (both active and non active) of the current type.
*
* @since 4.2.0
* @return int
*/
private function get_total_count_modules_current_type() {
if ( is_null( $this->module_count_type ) ) {
$args = array(
'module_type' => $this->module_type,
'count_only' => true,
);
$search = filter_input( INPUT_GET, 'q' );
if ( $search ) {
$args['filter']['q'] = $search;
}
$this->module_count_type = Hustle_Module_Collection::instance()->get_all(
null,
$args
);
}
return $this->module_count_type;
}
/**
* Get data needed for rendering the tracking charts in the listing pages
* Retrieved via AJAX.
*
* @since 4.0.4
* @since 4.2.0 Moved from Hustle_Module_Model to this class, and $module_id param added.
*
* @param int $module_id ID of the requested module.
*/
public static function get_tracking_charts_markup( $module_id ) {
$module = Hustle_Model::get_module( $module_id );
if ( is_wp_error( $module ) ) {
return '';
}
$tracking_model = Hustle_Tracking_Model::get_instance();
$total_module_conversions = $tracking_model->count_tracking_data( $module_id, 'all_conversion' );
$total_module_views = $tracking_model->count_tracking_data( $module_id, 'view' );
$last_entry_time = $tracking_model->get_latest_conversion_time_by_module_id( $module_id );
$rate = $total_module_views ? round( ( $total_module_conversions * 100 ) / $total_module_views, 1 ) : 0;
$module_sub_types = $module->get_sub_types( true );
$multiple_charts = array();
// Get each sub type's tracking data if the module type has sub types.
if ( ! empty( $module_sub_types ) ) {
foreach ( $module_sub_types as $slug => $display_name ) {
$subtype = $module->module_type . '_' . $slug;
$views = $tracking_model->count_tracking_data( $module_id, 'view', $subtype );
$conversions = $tracking_model->count_tracking_data( $module_id, 'all_conversion', $subtype );
$conversion_rate = $views ? round( ( $conversions * 100 ) / $views, 1 ) : 0;
$multiple_charts[ $slug ] = array(
'display_name' => $display_name,
'last_entry_time' => $tracking_model->get_latest_conversion_time_by_module_id( $module_id, $subtype ),
'views' => $views,
'conversions' => $conversions,
'conversion_rate' => $conversion_rate,
);
}
}
$render_arguments = array(
'module' => $module,
'total_module_views' => $total_module_views,
'total_module_conversions' => $total_module_conversions,
'tracking_types' => $module->get_tracking_types(),
'last_entry_time' => $last_entry_time,
'rate' => $rate,
);
if ( $module->get_content()->has_cta() ) {
$notice_for_old_data = $tracking_model->has_old_tracking_data( $module_id );
$render_arguments['notice_for_old_data'] = $notice_for_old_data;
}
ob_start();
$renderer = new Hustle_Layout_Helper();
// ELEMENT: Tracking data.
$renderer->render(
'admin/commons/sui-listing/elements/tracking-data',
array(
'render_arguments' => $render_arguments,
'multiple_charts' => $multiple_charts,
)
);
$html = ob_get_clean();
$charts_data = self::get_charts_data( array_keys( $module_sub_types ), $total_module_views, $module );
$data = array(
'html' => $html,
'charts_data' => $charts_data,
);
return $data;
}
/**
* Get tracking data for building charts on listing page
*
* @since 4.0.4
* @since 4.2.0 Move from Hustle_Module_Model to this class. $module param added.
*
* @param array $sub_types Module's sub types.
* @param int $views Module's views count.
* @param Hustle_Model $module Instance of the module to get the charts data for.
* @return array
*/
private static function get_charts_data( $sub_types, $views, Hustle_Model $module ) {
$sql_month_start_date = date( 'Y-m-d H:i:s', strtotime( '-30 days midnight' ) );// phpcs:ignore WordPress.DateTime.RestrictedFunctions.date_date
$tracking_model = Hustle_Tracking_Model::get_instance();
$days_array = array();
$default_array = array();
for ( $h = 30; $h >= 0; $h-- ) {
$time = strtotime( '-' . $h . ' days' );
$date = date( 'Y-m-d', $time );// phpcs:ignore WordPress.DateTime.RestrictedFunctions.date_date
$default_array[ $date ] = 0;
$days_array[] = date( 'M j, Y', $time );// phpcs:ignore WordPress.DateTime.RestrictedFunctions.date_date
}
$sub_types[] = 'overall';
$conversion_types = array( 'all' );
if ( Hustle_Module_Model::SOCIAL_SHARING_MODULE !== $module->module_type ) {
$conversion_types[] = 'cta';
$conversion_types[] = 'cta_2';
if ( Hustle_Module_Model::OPTIN_MODE === $module->module_mode ) {
$conversion_types[] = 'optin';
}
}
$data = array();
foreach ( $sub_types as $sub_type ) {
$chart_container_id = sprintf(
'hustle-%1$s-%2$s-stats--%3$s',
$module->module_type,
$module->module_id,
$sub_type
);
$data[ $sub_type ] = array(
'id' => $chart_container_id,
'days' => $days_array,
);
foreach ( $conversion_types as $conversion_type ) {
$last_month_conversions = $tracking_model->get_form_latest_tracking_data_count_grouped_by_day( $module->module_id, $sql_month_start_date, $conversion_type . '_conversion', $module->module_type, $sub_type );
$last_month_views = $tracking_model->get_form_latest_tracking_data_count_grouped_by_day( $module->module_id, $sql_month_start_date, 'view', $module->module_type, $sub_type );
if ( ! $last_month_conversions ) {
$submissions_data = $default_array;
} else {
$submissions_array = wp_list_pluck( $last_month_conversions, 'tracked_count', 'date_created' );
$submissions_data = array_merge( $default_array, array_intersect_key( $submissions_array, $default_array ) );
}
if ( ! $last_month_views ) {
$views_data = $default_array;
} else {
$views_array = wp_list_pluck( $last_month_views, 'tracked_count', 'date_created' );
$views_data = array_merge( $default_array, array_intersect_key( $views_array, $default_array ) );
}
$query_sub_type = 'overall' === $sub_type ? null : $module->module_type . '_' . $sub_type;
$query_conversion_type = $conversion_type . '_conversion';
$sub_type_conversions = $tracking_model->count_tracking_data( $module->module_id, $query_conversion_type, $query_sub_type );
$data[ $sub_type ][ $conversion_type ] = array(
'conversions_count' => $sub_type_conversions,
'conversion_rate' => $views ? round( ( $sub_type_conversions * 100 ) / $views, 1 ) : 0,
'conversions' => array_values( $submissions_data ),
);
}
$data[ $sub_type ]['views'] = array_values( $views_data );
$data[ $sub_type ]['conversions'] = array_values( $submissions_data );
}
return $data;
}
/**
* Returns whether the current module is optin.
* This method should be only used in Wizard pages
* because $this->module is only defined within Wizards.
*
* @since 4.3.0
* @return boolean
*/
public function is_optin_module() {
return ! empty( $this->module ) && 'optin' === $this->module->module_mode;
}
/**
* Gets the font family names.
* Used for rendering the selects.
*
* @since 4.3.0
* @return array
*/
public function get_font_families() {
return Hustle_Meta_Base_Design::get_font_families_names();
}
}