| 1 |
<?php |
| 2 |
|
| 3 |
defined('ABSPATH') || die(); |
| 4 |
|
| 5 |
class HashFormLoader { |
| 6 |
|
| 7 |
public function __construct() { |
| 8 |
add_filter('admin_body_class', array($this, 'add_admin_class'), 999); |
| 9 |
add_action('admin_enqueue_scripts', array($this, 'admin_init'), 11); |
| 10 |
add_action('wp_enqueue_scripts', array($this, 'enqueue_styles'), 11); |
| 11 |
add_action('wp_enqueue_scripts', array($this, 'enqueue_scripts')); |
| 12 |
add_action('elementor/editor/after_enqueue_styles', array($this, 'elementor_editor_styles')); |
| 13 |
add_action('elementor/preview/enqueue_styles', array($this, 'elementor_preview_styles')); |
| 14 |
} |
| 15 |
|
| 16 |
public static function add_admin_class($classes) { |
| 17 |
if (HashFormHelper::is_form_builder_page()) { |
| 18 |
$full_screen_on = self::get_full_screen_setting(); |
| 19 |
if ($full_screen_on) { |
| 20 |
$classes .= ' is-fullscreen-mode'; |
| 21 |
wp_enqueue_style('wp-edit-post'); // Load the CSS for .is-fullscreen-mode. |
| 22 |
} |
| 23 |
} |
| 24 |
return $classes; |
| 25 |
} |
| 26 |
|
| 27 |
private static function get_full_screen_setting() { |
| 28 |
global $wpdb; |
| 29 |
$meta_key = $wpdb->get_blog_prefix() . 'persisted_preferences'; |
| 30 |
$prefs = get_user_meta(get_current_user_id(), $meta_key, true); |
| 31 |
if ($prefs && isset($prefs['core/edit-post']['fullscreenMode'])) |
| 32 |
return $prefs['core/edit-post']['fullscreenMode']; |
| 33 |
return true; |
| 34 |
} |
| 35 |
|
| 36 |
public static function admin_init() { |
| 37 |
$page = HashFormHelper::get_var('page', 'sanitize_title'); |
| 38 |
|
| 39 |
// The style-template editor is a regular post screen but is driven by |
| 40 |
// the same admin assets (color picker, chosen, live preview, ...). |
| 41 |
$screen = function_exists('get_current_screen') ? get_current_screen() : null; |
| 42 |
$is_style_template_screen = ($screen && 'hashform-styles' === $screen->post_type) |
| 43 |
|| HashFormStyleBuilder::is_builder(); |
| 44 |
|
| 45 |
// Everything below is only useful on the plugin's own screens; do not |
| 46 |
// weigh down the rest of wp-admin with it. |
| 47 |
if (strpos($page, 'hashform') !== 0 && !$is_style_template_screen) { |
| 48 |
return; |
| 49 |
} |
| 50 |
|
| 51 |
/* |
| 52 |
* The style builder's slug begins with hashform too, but it is a style |
| 53 |
* screen and not the form builder: loading the form builder's scripts |
| 54 |
* there would put them somewhere they have never run before. |
| 55 |
*/ |
| 56 |
if (strpos($page, 'hashform') === 0 && !HashFormStyleBuilder::is_builder()) { |
| 57 |
wp_enqueue_script('hashform-builder', HASHFORM_URL . 'js/builder.js', array('jquery', 'jquery-ui-core', 'jquery-ui-draggable', 'jquery-ui-droppable', 'jquery-ui-sortable', 'wp-i18n', 'wp-hooks', 'jquery-ui-dialog', 'hashform-select2'), HASHFORM_VERSION, true); |
| 58 |
wp_enqueue_script('hashform-backend', HASHFORM_URL . 'js/backend.js', array('jquery', 'jquery-ui-core', 'jquery-ui-draggable', 'jquery-ui-droppable', 'jquery-ui-sortable', 'wp-i18n', 'wp-hooks', 'jquery-ui-dialog', 'jquery-ui-datepicker'), HASHFORM_VERSION, true); |
| 59 |
|
| 60 |
wp_localize_script('hashform-backend', 'hashform_backend_js', array( |
| 61 |
'nonce' => wp_create_nonce('hashform_backend_ajax'), |
| 62 |
'entry_nonce' => wp_create_nonce('hashform_entry_action'), |
| 63 |
'note_saved' => esc_html__('Note saved.', 'hash-form'), |
| 64 |
'note_error' => esc_html__('The note could not be saved.', 'hash-form'), |
| 65 |
'resend_confirm' => esc_html__('Send the notification emails for this entry again?', 'hash-form'), |
| 66 |
'generic_error' => esc_html__('Something went wrong. Please reload the page and try again.', 'hash-form'), |
| 67 |
'form_name_required' => esc_html__('Please give the form a name.', 'hash-form'), |
| 68 |
/* translators: %s: the spacer's height in pixels, filled in by the builder. */ |
| 69 |
'spacer_label' => sprintf(esc_html__('Spacer · %spx', 'hash-form'), '%d'), |
| 70 |
'search_fields' => esc_html__('Search fields', 'hash-form'), |
| 71 |
'no_tag_fields' => esc_html__('This form has no field to insert here yet.', 'hash-form'), |
| 72 |
'no_tag_matches' => esc_html__('No field matches that.', 'hash-form'), |
| 73 |
'invalid_email' => esc_html__('Enter a valid email address.', 'hash-form'), |
| 74 |
)); |
| 75 |
|
| 76 |
wp_localize_script('hashform-builder', 'hashform_backend_js', array( |
| 77 |
'nonce' => wp_create_nonce('hashform_backend_ajax'), |
| 78 |
)); |
| 79 |
|
| 80 |
// Kept separate from hashform_backend_js: the backend script |
| 81 |
// declares that same global afterwards, which would drop any key |
| 82 |
// only the builder had set. |
| 83 |
wp_localize_script('hashform-builder', 'hashform_builder_js', array( |
| 84 |
'drop_field_here' => esc_html__('Drop a field here', 'hash-form'), |
| 85 |
'move' => esc_html__('Move Row', 'hash-form'), |
| 86 |
'delete' => esc_html__('Delete Row', 'hash-form'), |
| 87 |
'delete_row' => esc_html__('Delete this row?', 'hash-form'), |
| 88 |
'delete_row_with_fields' => esc_html__('Delete this row and the fields in it?', 'hash-form'), |
| 89 |
)); |
| 90 |
} |
| 91 |
|
| 92 |
if (strpos($page, 'hashform-smtp') === 0) { |
| 93 |
wp_enqueue_script('plugin-install'); |
| 94 |
wp_enqueue_script('updates'); |
| 95 |
} |
| 96 |
|
| 97 |
wp_enqueue_script('hashform-chosen', HASHFORM_URL . 'js/chosen.jquery.js', array('jquery'), HASHFORM_VERSION, true); |
| 98 |
wp_enqueue_script('hashform-select2', HASHFORM_URL . 'js/select2.min.js', array('jquery'), HASHFORM_VERSION, true); |
| 99 |
wp_enqueue_script('jquery-condition', HASHFORM_URL . 'js/jquery-condition.js', array('jquery'), HASHFORM_VERSION, true); |
| 100 |
wp_enqueue_script('wp-color-picker-alpha', HASHFORM_URL . 'js/wp-color-picker-alpha.js', array('wp-color-picker'), HASHFORM_VERSION, true); |
| 101 |
wp_enqueue_script('hashform-admin-settings', HASHFORM_URL . 'js/admin-settings.js', array('jquery'), HASHFORM_VERSION, true); |
| 102 |
|
| 103 |
wp_localize_script('hashform-admin-settings', 'hashform_admin_js_obj', array( |
| 104 |
'ajax_url' => admin_url('admin-ajax.php'), |
| 105 |
'nonce' => wp_create_nonce('hashform_admin_settings_ajax'), |
| 106 |
'installing_text' => esc_html__('Installing WP Mail SMTP', 'hash-form'), |
| 107 |
'activating_text' => esc_html__('Activating WP Mail SMTP', 'hash-form'), |
| 108 |
'error' => esc_html__('Error! Reload the page and try again.', 'hash-form'), |
| 109 |
)); |
| 110 |
|
| 111 |
wp_enqueue_style('wp-color-picker'); |
| 112 |
wp_enqueue_style('materialdesignicons', HASHFORM_URL . 'fonts/materialdesignicons.css', array(), HASHFORM_VERSION); |
| 113 |
wp_enqueue_style('hashform-chosen', HASHFORM_URL . 'css/chosen.css', array(), HASHFORM_VERSION); |
| 114 |
wp_enqueue_style('hashform-select2', HASHFORM_URL . 'css/select2.min.css', array(), HASHFORM_VERSION); |
| 115 |
// Tokens load first and are a dependency of everything else, so any |
| 116 |
// stylesheet can rely on the custom properties being defined. |
| 117 |
wp_enqueue_style('hashform-tokens', HASHFORM_URL . 'css/design-tokens.css', array(), HASHFORM_VERSION); |
| 118 |
wp_enqueue_style('hashform-admin', HASHFORM_URL . 'css/admin-style.css', array('hashform-tokens'), HASHFORM_VERSION); |
| 119 |
|
| 120 |
// Loaded after the legacy sheet so the reworked screens win without |
| 121 |
// having to unpick admin-style.css in one go. |
| 122 |
wp_enqueue_style('hashform-builder-ui', HASHFORM_URL . 'css/builder.css', array('hashform-admin'), HASHFORM_VERSION); |
| 123 |
wp_enqueue_style('hashform-file-uploader', HASHFORM_URL . 'css/file-uploader.css', array(), HASHFORM_VERSION); |
| 124 |
wp_enqueue_style('hashform-admin-settings', HASHFORM_URL . 'css/admin-settings.css', array(), HASHFORM_VERSION); |
| 125 |
wp_enqueue_style('hashform-style', HASHFORM_URL . 'css/style.css', array(), HASHFORM_VERSION); |
| 126 |
|
| 127 |
// Forms and Entries lists. Scoped to .hf-list-screen, so it is inert |
| 128 |
// on the screens that do not carry that wrapper. |
| 129 |
wp_enqueue_style('hashform-list-screens', HASHFORM_URL . 'css/list-screens.css', array('hashform-admin'), HASHFORM_VERSION); |
| 130 |
|
| 131 |
$fonts_url = HashFormStyles::fonts_url(); |
| 132 |
|
| 133 |
// Load Fonts if necessary. |
| 134 |
if ($fonts_url) { |
| 135 |
wp_enqueue_style('hashform-fonts', $fonts_url, array(), HASHFORM_VERSION); |
| 136 |
} |
| 137 |
} |
| 138 |
|
| 139 |
public static function elementor_editor_styles() { |
| 140 |
/* |
| 141 |
* One rule, built from the same drawing the field icons come from, so |
| 142 |
* the widget mark cannot drift from the rest of the set. This replaced |
| 143 |
* a 65 KB icon font that was loaded here to draw exactly one glyph. |
| 144 |
*/ |
| 145 |
wp_register_style('hashform-elementor-icon', false, array(), HASHFORM_VERSION); |
| 146 |
wp_enqueue_style('hashform-elementor-icon'); |
| 147 |
wp_add_inline_style('hashform-elementor-icon', HashFormFieldIcons::elementor_icon_css()); |
| 148 |
} |
| 149 |
|
| 150 |
// Frontend assets are only registered here; they are enqueued by |
| 151 |
// enqueue_form_assets() when a form is actually rendered, so pages |
| 152 |
// without a form load none of them. |
| 153 |
public static function enqueue_styles() { |
| 154 |
// The stock jquery.timepicker stylesheet is deliberately not registered. |
| 155 |
// The time picker is styled in style.css alongside the date picker so |
| 156 |
// the two share one set of tokens. |
| 157 |
wp_register_style('hashform-file-uploader', HASHFORM_URL . 'css/file-uploader.css', array(), HASHFORM_VERSION); |
| 158 |
wp_register_style('materialdesignicons', HASHFORM_URL . 'fonts/materialdesignicons.css', array(), HASHFORM_VERSION); |
| 159 |
wp_register_style('hashform-style', HASHFORM_URL . 'css/style.css', array(), HASHFORM_VERSION); |
| 160 |
|
| 161 |
$fonts_url = HashFormStyles::fonts_url(); |
| 162 |
if ($fonts_url) { |
| 163 |
wp_register_style('hashform-fonts', $fonts_url, array(), HASHFORM_VERSION); |
| 164 |
} |
| 165 |
} |
| 166 |
|
| 167 |
public static function enqueue_scripts() { |
| 168 |
wp_register_script('jquery-timepicker', HASHFORM_URL . 'js/jquery.timepicker.min.js', array('jquery'), HASHFORM_VERSION, true); |
| 169 |
wp_register_script('hashform-file-uploader', HASHFORM_URL . 'js/file-uploader.js', array(), HASHFORM_VERSION, true); |
| 170 |
wp_localize_script('hashform-file-uploader', 'hashform_file_vars', array( |
| 171 |
'remove_txt' => esc_html__('Remove', 'hash-form') |
| 172 |
)); |
| 173 |
wp_register_script('frontend', HASHFORM_URL . 'js/frontend.js', array('jquery', 'jquery-ui-datepicker', 'jquery-timepicker', 'hashform-file-uploader'), HASHFORM_VERSION, true); |
| 174 |
wp_localize_script('frontend', 'hashform_vars', array( |
| 175 |
'ajaxurl' => admin_url('admin-ajax.php'), |
| 176 |
'ajax_nounce' => wp_create_nonce('hashform-upload-ajax-nonce'), |
| 177 |
'preview_img' => '', |
| 178 |
// Shown when a submission is refused without a usable message of |
| 179 |
// its own, so the visitor is never left with a silent form. |
| 180 |
'generic_error' => esc_html__('Your submission could not be sent. Please try again.', 'hash-form'), |
| 181 |
)); |
| 182 |
} |
| 183 |
|
| 184 |
/** |
| 185 |
* Everything a rendered form needs to look right. |
| 186 |
* |
| 187 |
* Split out from enqueue_form_assets() because the Elementor editor needs |
| 188 |
* these without the scripts - see elementor_preview_styles(). |
| 189 |
*/ |
| 190 |
public static function enqueue_form_styles() { |
| 191 |
wp_enqueue_style('dashicons'); |
| 192 |
wp_enqueue_style('hashform-file-uploader'); |
| 193 |
wp_enqueue_style('materialdesignicons'); |
| 194 |
wp_enqueue_style('hashform-style'); |
| 195 |
wp_enqueue_style('hashform-fonts'); |
| 196 |
} |
| 197 |
|
| 198 |
/** |
| 199 |
* The form's stylesheet inside the Elementor editor's preview iframe. |
| 200 |
* |
| 201 |
* Elementor builds the widgets client-side there - the preview page arrives |
| 202 |
* with no element markup at all - so the widget's render(), which is what |
| 203 |
* enqueues the form assets, never runs. The form was then injected by the |
| 204 |
* editor with no stylesheet behind it, and every style control looked like |
| 205 |
* it did nothing: the css variables they set had no rules to act on. |
| 206 |
* |
| 207 |
* Styles only. The scripts would bind the submit handler and start hiding |
| 208 |
* fields by conditional logic inside the editor, which is not something |
| 209 |
* anyone laying out a page wants to fight with. |
| 210 |
* |
| 211 |
* Elementor fires this at wp_enqueue_scripts priority 20, and these handles |
| 212 |
* are registered at 11, so they are always there to enqueue by now. |
| 213 |
*/ |
| 214 |
public static function elementor_preview_styles() { |
| 215 |
self::enqueue_form_styles(); |
| 216 |
} |
| 217 |
|
| 218 |
public static function enqueue_form_assets() { |
| 219 |
self::enqueue_form_styles(); |
| 220 |
|
| 221 |
wp_enqueue_script('jquery-ui-slider'); |
| 222 |
wp_enqueue_script('jquery-timepicker'); |
| 223 |
wp_enqueue_script('hashform-file-uploader'); |
| 224 |
// Core's own copy, registered by WordPress since 4.6. The plugin used |
| 225 |
// to ship an identical build of the same version, which WordPress |
| 226 |
// ignored anyway: wp_register_script() will not take a handle that is |
| 227 |
// already registered. |
| 228 |
wp_enqueue_script('moment'); |
| 229 |
wp_enqueue_script('frontend'); |
| 230 |
} |
| 231 |
|
| 232 |
} |
| 233 |
|
| 234 |
new HashFormLoader(); |
| 235 |
|