PluginProbe
Lasso Lite – Affiliate Link Manager & Product Displays / 158
Lasso Lite – Affiliate Link Manager & Product Displays v158
158 157 155 156 154 153 152 151 150 149 148 trunk 0.9.9 104 105 106 107 108 109 110 111 112 113 114 115 All 57 releases
simple-urls / pages / class-hook.php

class-hook.php in Lasso Lite – Affiliate Link Manager & Product Displays 158, at pages/class-hook.php

1,552 lines 52.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * SURLs - Hook.
4 *
5 * @package Pages
6 */
7
8 namespace LassoLite\Pages;
9
10 use LassoLite\Admin\Constant;
11
12 use LassoLite\Classes\Amazon_Api;
13 use LassoLite\Classes\Beacon_Proxy;
14 use LassoLite\Classes\Enum;
15 use LassoLite\Classes\Helper;
16 use LassoLite\Classes\Page;
17 use LassoLite\Classes\Setting;
18 use LassoLite\Classes\Shortcode;
19 use LassoLite\Classes\License;
20 use LassoLite\Classes\Realtime_Click;
21
22 /**
23 * Hook.
24 */
25 class Hook {
26 /**
27 * Current template
28 *
29 * @var string $current_template
30 */
31 public $current_template = '';
32
33 /**
34 * Is show old menus
35 *
36 * @var bool $show_old_menus
37 */
38 private $show_old_menus = false;
39
40 /**
41 * Register hooks
42 */
43 public function register_hooks() {
44 add_action( 'admin_init', array( $this, 'amazon_api_pre_populated_automatically' ) );
45 add_action( 'init', array( $this, 'register_taxonomy' ) );
46 add_action( 'admin_menu', array( $this, 'build_admin_menu' ), 2 );
47 add_action( 'init', array( $this, 'lasso_register_connect_snippet_rewrite' ) );
48 add_action( 'init', array( $this, 'maybe_flush_vanity_rewrites_on_upgrade' ), 20 );
49 add_action( 'upgrader_process_complete', array( $this, 'lasso_connect_snippet_flush_on_upgrade' ), 10, 2 );
50
51 $lasso_shortcode = new Shortcode();
52 add_shortcode( 'lasso', array( $lasso_shortcode, 'lasso_lite_core_shortcode' ) );
53 add_filter( 'pre_do_shortcode_tag', array( $this, 'filter_pre_do_shortcode_lasso_lite' ), 10, 4 );
54
55 add_action( 'wp_head', array( $this, 'lasso_custom_css' ) ); // ? frontend
56 add_action( 'admin_head', array( $this, 'lasso_custom_css' ) ); // ? admin
57 add_action( 'admin_head', array( $this, 'lasso_custom_menu' ) ); // ? admin
58 add_action( 'wp_enqueue_scripts', array( $this, 'add_scripts_frontend' ) ); // ? frontend
59 add_filter( 'body_class', array( $this, 'filter_body_class_lasso_lite_version' ) ); // ? frontend
60
61 add_action( 'admin_enqueue_scripts', array( $this, 'add_scripts' ) );
62 add_action( 'admin_enqueue_scripts', array( $this, 'add_styles' ) );
63
64 // ? re-order submenu pages
65 add_filter( 'custom_menu_order', array( $this, 'lasso_order_submenu' ) );
66
67 // ? lasso gutenberg block
68 add_action( 'enqueue_block_assets', array( $this, 'lasso_block_editor_css_variables' ) );
69 add_action( 'enqueue_block_editor_assets', array( $this, 'lasso_lite_gutenberg_block' ) );
70
71 // ? Elementor
72 add_action( 'elementor/init', array( $this, 'elementor_init' ) );
73
74 // ? add Lasso button into TinyMCE
75 add_filter( 'mce_external_plugins', array( $this, 'lasso_add_tinymce_plugin' ) );
76 add_filter( 'mce_buttons', array( $this, 'lasso_lite_register_my_tc_button' ) );
77
78 add_filter( 'simple_urls_redirect_url', array( $this, 'lasso_lite_redirect' ), 10, 1 );
79
80 add_action( 'admin_footer', array( $this, 'lasso_lite_admin_footer_editor_gutenberg' ) );
81
82 add_filter( 'rest_pre_echo_response', array( $this, 'update_post_type_gutenberg' ), 200, 3 );
83
84 add_filter( 'wp_link_query', array( $this, 'update_post_type_classic_editor' ), 10, 1 );
85 add_filter( 'update_footer', '__return_empty_string', 11 );
86
87 // ? WP Rocket
88 add_filter( 'rocket_exclude_js', array( $this, 'exclude_lasso_performance_js_from_rocket_cache' ) );
89
90 add_filter( 'query_vars', array( $this, 'lasso_connect_snippet_query_var' ) );
91
92 // Serve vanity JS path /js/snippet.min.js via plugin handler (run as early as possible)
93 add_action( 'template_redirect', array( $this, 'serve_connect_snippet' ), 0 );
94 add_action( 'template_redirect', array( $this, 'serve_beacon_proxy' ), 0 );
95
96 $setting = new Setting();
97 if ( $setting->is_surls_page() ) {
98 // ? plugin: Pretty Links Pro
99 if ( class_exists( 'PrliUpdateController' ) ) {
100 Helper::remove_action( 'admin_notices', array( 'PrliUpdateController', 'activation_warning' ) );
101 }
102 }
103
104 // ? FIX: CONFLICT WITH OTHER PLUGINS
105 // ? remove js files from other plugins in Lasso pages
106 if ( $setting->is_surls_page() ) {
107 // ? plugin: SEO Booster
108 if ( class_exists( 'Seobooster2' ) ) {
109 remove_action( 'admin_print_footer_scripts', array( 'Seobooster2', 'admin_print_footer_scripts' ) );
110 }
111
112 // ? plugin: ShortPixel Adaptive Images
113 if ( class_exists( 'ShortPixel\AI\Notice' ) && class_exists( 'ShortPixelAI' ) ) {
114 $spai = \ShortPixelAI::_();
115 $spain = \ShortPixel\AI\Notice::_( $spai );
116 remove_action( 'admin_footer', array( $spain, 'enqueueAdminScripts' ) );
117 remove_action( 'admin_bar_menu', array( $spai, 'toolbar_styles' ), 999 );
118 }
119
120 // ? plugin: WZone - WooCommerce Amazon Affiliates (WooZone)
121 if ( class_exists( 'WooZone' ) ) {
122 global $WooZone; // phpcs:ignore
123 remove_action( 'init', array( $WooZone, 'initThePlugin' ), 5 ); // phpcs:ignore
124 }
125
126 // ? plugin: Client Portal
127 $lasso_page = Helper::GET()['page'] ?? ''; // phpcs:ignore
128 if ( class_exists( 'CCGClientPortal' ) && Helper::add_prefix_page( Enum::PAGE_DASHBOARD ) === $lasso_page ) {
129 global $zohopwp; // phpcs:ignore
130 remove_action( 'admin_menu', array( $zohopwp, 'ccgclientportal_admin_menu' ) ); // phpcs:ignore
131 }
132
133 if ( class_exists( 'wpe_admin_pointers' ) ) {
134 global $wpe_admin_pointers; // phpcs:ignore
135 remove_action( 'admin_enqueue_scripts', array( $wpe_admin_pointers, 'custom_admin_pointers_header' ) ); // phpcs:ignore
136 }
137
138 // ? plugin: tagDiv Composer
139 if ( function_exists( 'td_change_backbone_js_hook' ) ) {
140 remove_action( 'print_media_templates', 'td_change_backbone_js_hook' );
141 }
142
143 // ? plugin: Pretty Links Pro
144 if ( class_exists( 'PrliUpdateController' ) ) {
145 Helper::remove_action( 'admin_notices', array( 'PrliUpdateController', 'activation_warning' ) );
146 }
147
148 if ( Helper::is_earnist_plugin_loaded() ) {
149 Helper::remove_action( 'admin_print_footer_scripts', array( 'EarnistProductPicker', 'register_tinymce_quicktags' ) );
150 }
151 if ( Helper::is_shortcode_start_rating_plugin_loaded() ) {
152 global $ShortcodeStarRating; // phpcs:ignore
153 remove_action( 'admin_print_footer_scripts', array( $ShortcodeStarRating, 'appthemes_add_quicktags' ) ); // phpcs:ignore
154 }
155 if ( Helper::is_plugin_easy_table_of_contents_activated() ) {
156 add_action( 'admin_enqueue_scripts', array( $this, 'remove_easy_table_of_content_action_admin_print_footer_scripts' ), 20 ); // ? admin
157 }
158
159 remove_all_actions( 'admin_footer' );
160 add_action( 'admin_footer', array( $this, 'lasso_print_media_templates' ) );
161 add_action( 'admin_footer', array( $this, 'lasso_organize_menu' ), 100 );
162 }
163
164 // ? fix conflict with plugin Affiliate URL Automation
165 if ( class_exists( 'AffiliateURLs' ) ) {
166 global $AffiliateURLs; // phpcs:ignore
167 remove_filter( 'the_content', array( &$AffiliateURLs, 'the_content' ), 12 ); // phpcs:ignore
168 }
169
170 // ? remove js files from other plugins in WP post/page pages
171 if ( Helper::is_wordpress_post() ) {
172 if ( class_exists( 'WooZone' ) ) {
173 global $WooZone; // phpcs:ignore
174 remove_action( 'init', array( $WooZone, 'initThePlugin' ), 5 ); // phpcs:ignore
175 }
176 }
177
178 if ( Helper::is_gravity_perks_plugin_active() ) {
179 remove_action( 'admin_print_footer_scripts', array( 'GWPerks', 'welcome_pointer_script' ), 10 ); // phpcs:ignore
180 }
181
182 $license_active = License::get_license_status();
183 if ( false === $license_active ) {
184 add_action( 'admin_notices', array( $this, 'lasso_lite_custom_dashboard_banner' ) );
185 }
186
187 add_action( 'wp_footer', array( $this, 'lasso_lite_event_tracking' ) );
188 add_action( 'admin_footer', array( $this, 'open_links_in_new_tab' ) );
189 }
190
191
192 /**
193 * Check if Lasso Lite shortcode then render, else return false to running the next shortcode processes
194 *
195 * @param boolean $false This is the default value that will be returned if the shortcode is not found.
196 * @param string $tag The shortcode tag.
197 * @param array $attr The attributes passed to the shortcode like so: [shortcode attr1="value" /].
198 * @param array $m The regex for the shortcode.
199 *
200 * @return string|boolean return value is the output of the lasso_lite_core_shortcode function.
201 */
202 public function filter_pre_do_shortcode_lasso_lite( $false, $tag, $attr, $m ) {
203 if ( 'lasso' === $tag ) {
204 return ( new Shortcode() )->lasso_lite_core_shortcode( $attr );
205 }
206
207 return false;
208 }
209
210 /**
211 * Admin menu
212 */
213 public function build_admin_menu() {
214 $get_page = Helper::GET()['page'] ?? '';
215 $post_type = Helper::GET()['post_type'] ?? '';
216
217 $dashboard_slug = Helper::add_prefix_page( Enum::PAGE_DASHBOARD );
218 // ? Switch to new/old UI: We should easy redirect to the suitable dashboard.
219 if ( 'switch-new-ui' === $get_page ) {
220 update_option( Enum::SWITCH_TO_NEW_UI, 1 );
221 wp_redirect( Page::get_page_url( $dashboard_slug ) ); // phpcs:ignore
222 exit;
223 } elseif ( 'switch-old-ui' === $get_page ) {
224 update_option( Enum::LASSO_LITE_ACTIVE, 0 ); // ? fix conflict with L.235
225 update_option( Enum::SWITCH_TO_NEW_UI, 0 );
226 wp_redirect( Page::get_page_url() ); // phpcs:ignore
227 exit;
228 }
229
230 // ? Reset onboarding for testing (one-shot: strip QA param so step persistence works on reload)
231 $reset_onboarding = Helper::GET()[ Enum::RESET_WELCOME_PAGE ] ?? '';
232 if ( $reset_onboarding ) {
233 Helper::reset_onboarding_for_testing();
234
235 wp_safe_redirect( remove_query_arg( Enum::RESET_WELCOME_PAGE ) ); // phpcs:ignore WordPress.Security.SafeRedirect.wp_redirect_wp_redirect
236 exit;
237 }
238
239 // ? Reset request review for testing
240 $reset_review = Helper::GET()[ Enum::RESET_REQUEST_REVIEW ] ?? '';
241 if ( $reset_review ) {
242 Helper::update_option( Constant::LASSO_OPTION_REVIEW_ALLOW, 1 );
243 Helper::update_option( Constant::LASSO_OPTION_REVIEW_SNOOZE, 0 );
244 Helper::update_option( Constant::LASSO_OPTION_REVIEW_LINK_COUNT, 0 );
245 }
246
247 // ? The new Lasso Lite active should be redirect to welcome page
248 $onboarding_page = Helper::add_prefix_page( Enum::PAGE_ONBOARDING );
249 $should_redirect_to_welcome_page = self::should_redirect_to_welcome_page();
250 if ( SIMPLE_URLS_SLUG === $post_type && $onboarding_page !== $get_page && $should_redirect_to_welcome_page ) {
251 wp_redirect( Page::get_page_url( $onboarding_page ) ); // phpcs:ignore
252 exit;
253 } elseif ( $onboarding_page === $get_page && ! $should_redirect_to_welcome_page ) {
254 wp_redirect( Page::get_page_url( $dashboard_slug ) ); // phpcs:ignore
255 exit;
256 }
257
258 // ? Redirect to dashboard page if page is "surl-dashboard" and missing "post_type" parameter
259 if ( $dashboard_slug === $get_page && ! $post_type ) {
260 wp_redirect( Page::get_page_url( $dashboard_slug ) ); // phpcs:ignore
261 exit;
262 }
263
264 // ? If the customer install from new UI, we should only show the new UI's menus without switch UI feature
265 if ( get_option( Enum::LASSO_LITE_ACTIVE ) ) {
266 update_option( Enum::SWITCH_TO_NEW_UI, 1 );
267 $this->apply_new_ui_menus();
268 } else { // ? The old client that upgrade to the new UI
269 $switch_ui = 'switch-old-ui';
270 $page_title = 'Switch to old UI';
271
272 // ? The client was switched to new UI by click "Switch To New UI"
273 if ( Helper::is_lite_using_new_ui() ) {
274 $this->apply_new_ui_menus();
275 } else { // ? The client was still using the old UI
276 $this->show_old_menus = true;
277 $switch_ui = 'switch-new-ui';
278 $page_title = 'Switch to new UI';
279 }
280
281 add_submenu_page(
282 'edit.php?post_type=' . SIMPLE_URLS_SLUG,
283 $page_title,
284 $page_title,
285 'manage_options',
286 Page::get_page_url( $switch_ui )
287 );
288 }
289 }
290
291 /**
292 * Apply new UI's menus
293 */
294 private function apply_new_ui_menus() {
295 $get_page = Helper::GET()['page'] ?? '';
296 $post_type = Helper::GET()['post_type'] ?? '';
297
298 // ? Redirect to new UI's Dashboard if new UI enabled and the link is old UI
299 if ( SIMPLE_URLS_SLUG === $post_type && ! $get_page ) {
300 wp_redirect( Page::get_lite_page_url( Enum::PAGE_DASHBOARD ) ); // phpcs:ignore
301 exit;
302 }
303
304 $new_ui_pages = Helper::available_pages();
305 $parent_slug = 'edit.php?post_type=' . SIMPLE_URLS_SLUG;
306 foreach ( $new_ui_pages as $page ) {
307 if ( $get_page === $page->slug ) {
308 $this->current_template = $page->template;
309 }
310
311 add_submenu_page(
312 $parent_slug,
313 $page->title,
314 $page->title,
315 'manage_options',
316 $page->slug,
317 array( $this, 'render_html' )
318 );
319 }
320 }
321
322
323 /**
324 * Render html for pages
325 */
326 public function render_html() {
327 Helper::include_with_variables( Helper::get_path_views_folder() . $this->current_template, array(), false );
328 }
329
330 /**
331 * Load css files
332 */
333 public function add_styles() {
334 if ( ! Helper::is_lite_using_new_ui() ) {
335 return;
336 }
337
338 $setting = new Setting();
339 // @codingStandardsIgnoreStart
340
341 // ? Everywhere in the Lasso Lite post-type (add/edit/reports/settings/wizard)
342 if ( $setting->is_surls_page() ) {
343 Helper::enqueue_style( 'bootstrap-css', 'bootstrap.min.css' );
344 Helper::enqueue_style( 'bootstrap-select-css', 'bootstrap-select.min.css' );
345 Helper::enqueue_style( 'simple-panigation-css', 'simplePagination.css' );
346 Helper::enqueue_style( 'select2-css', 'select2.min.css' );
347 Helper::enqueue_style( 'lasso-quill', 'quill.snow.css' );
348 Helper::enqueue_style( 'lasso-lite', 'lasso-lite.css' );
349 Helper::enqueue_style( 'lasso-display-modal', 'lasso-display-modal.css' );
350 Helper::enqueue_style( 'lasso-dashboard', 'lasso-dashboard.css' );
351 Helper::enqueue_style( 'lasso-lite-custom', 'lite-custom.css' );
352 }
353
354 if ( $setting->is_setting_amazon_page() ) {
355 Helper::enqueue_style( 'settings-amazon-modal', 'settings-amazon-modal.css', array( SIMPLE_URLS_SLUG . '-lasso-lite-custom' ) );
356 }
357
358 if ( $setting->is_setting_display_page() || $setting->is_setting_onboarding_page() ) {
359 Helper::enqueue_style( 'spectrum', 'spectrum.min.css' );
360 }
361
362 // ? LOAD LASSO DISPLAY MODAL CSS ON POST AND PAGE EDIT ONLY
363 if ( $setting->is_wordpress_post() || $setting->is_custom_post() ) {
364 Helper::enqueue_style( 'bootstrap-grid-css', 'bootstrap-grid.min.css' );
365 Helper::enqueue_style( 'lasso-display-modal', 'lasso-display-modal.css' );
366 Helper::enqueue_style( 'simple-pagination', 'simplePagination.css' );
367 Helper::enqueue_style( 'lasso-quill', 'quill.snow.css' );
368 Helper::enqueue_style( 'lasso-lite', 'lasso-lite.css' );
369 Helper::enqueue_style( 'lasso-modal-css', 'lasso-modal.css' );
370 }
371
372 global $pagenow; // phpcs:ignore
373 if ( 'index.php' === $pagenow && $this->should_show_dashboard_promo_banner() ) {
374 Helper::enqueue_style( 'lasso-lite-admin', 'lasso-lite-admin.css' );
375 }
376
377 // @codingStandardsIgnoreEnd
378 }
379
380 /**
381 * Load js files
382 */
383 public function add_scripts() {
384 if ( ! Helper::is_lite_using_new_ui() ) {
385 return;
386 }
387 global $pagenow; // phpcs:ignore
388
389 $get = Helper::GET(); // phpcs:ignore
390 $page = $get['page'] ?? false;
391 $setting = new Setting();
392 $post_type = $setting->get['post_type'] ?? false;
393 $setting_data = Setting::get_settings();
394 $support_enabled = $setting_data[ Enum::SUPPORT_ENABLED ] ?? false;
395 $support_enabled = ! $support_enabled ? 1 : 0;
396 $data_passed_to_js = array(
397 'ajax_url' => admin_url( 'admin-ajax.php' ),
398 'site_url' => site_url(),
399 'plugin_url' => SIMPLE_URLS_URL,
400 'lasso_link' => Constant::LASSO_LINK,
401 'lasso_hub_url' => Constant::get_lasso_hub_url(),
402 'upgrade_url' => Constant::LASSO_UPGRADE_URL,
403 'rewrite_slug_default' => Enum::REWRITE_SLUG_DEFAULT,
404 'simple_urls_slug' => SIMPLE_URLS_SLUG,
405 'page_url_details' => Enum::PAGE_URL_DETAILS,
406 'setup_progress' => Helper::get_setup_progress_information(),
407 'optionsNonce' => wp_create_nonce( Constant::LASSO_LITE_NONCE . wp_salt() ),
408 'should_open_support_modal' => $support_enabled,
409 'amazon_tracking_id_regex' => Amazon_Api::TRACKING_ID_REGEX,
410 'is_onboard_page' => $setting->is_setting_onboarding_page(),
411 'onboarding_current_step' => $setting->is_setting_onboarding_page()
412 ? Helper::get_onboarding_current_step( Helper::should_show_import_page() )
413 : 'welcome',
414 'block_customize' => Constant::BLOCK_CUSTOMIZE,
415 'userId' => Helper::get_option( Constant::LASSO_ACCOUNT_USER_ID ),
416 );
417 $data_passed_to_js['realtime'] = Realtime_Click::get_js_config();
418
419 if ( $setting->is_setting_amazon_page() ) {
420 // Amazon settings only: edit.php?post_type=surl&page=surl-settings-amazon
421 $data_passed_to_js['lite_account_existing_always_post'] = true;
422 $data_passed_to_js['lite_amazon_settings_post_signup_verify_creators'] = true;
423 }
424
425 if ( SIMPLE_URLS_SLUG === $post_type ) {
426 wp_dequeue_script( 'up_admin_script' ); // ? fix js conflict with plugin: Download plugin
427 }
428
429 // @codingStandardsIgnoreStart
430 if ( 'index.php' === $pagenow && $this->should_show_dashboard_promo_banner() ) {
431 $data_passed_to_js = array(
432 'ajax_url' => admin_url( 'admin-ajax.php' ),
433 'optionsNonce' => wp_create_nonce( Constant::LASSO_LITE_NONCE . wp_salt() ),
434 );
435 wp_enqueue_script( 'jquery' );
436 wp_localize_script( 'jquery', 'lassoLiteOptionsData', $data_passed_to_js );
437 Helper::enqueue_script( 'lasso-lite-admin-js', 'lasso-lite-admin.js', array( 'jquery' ), false );
438 }
439
440 if ( $setting->is_wordpress_post() || $setting->is_surls_page() || $setting->is_custom_post() ) {
441 wp_enqueue_script( 'jquery-migrate' ); // ? fix jQuery(...).live is not a function
442 wp_enqueue_script( 'jquery' );
443 wp_enqueue_script( 'jquery-effects-core' );
444 wp_enqueue_script( 'jquery-ui-core' );
445 wp_enqueue_script( 'jquery-ui-sortable' );
446 wp_enqueue_script( 'jquery-ui-tooltip' );
447
448 Helper::enqueue_script( 'lasso-icons', 'fontawesome.min.js', array( 'jquery' ) );
449 Helper::enqueue_script( 'lasso-icons-regular', 'regular.min.js', array( 'jquery' ) );
450 Helper::enqueue_script( 'lasso-icons-solid', 'solid.min.js', array( 'jquery' ) );
451 Helper::enqueue_script( 'lasso-icons-brands', 'brands.min.js', array( 'jquery' ) );
452 Helper::enqueue_script( 'circle-progress', 'circle-progress.min.js', array( 'jquery' ) );
453
454 Helper::enqueue_script( 'lasso-quill', 'quill.min.js' );
455 Helper::enqueue_script( 'lasso-modal-js', 'lasso-modal.js' );
456
457 if ( ! Helper::is_classic_editor() && ( $setting->is_wordpress_post() || $setting->is_custom_post() ) ) {
458 Helper::enqueue_script( 'lasso-lite-display-modal', 'lasso-lite-display-modal.js' );
459 }
460
461 wp_enqueue_media();
462 Helper::enqueue_script( 'moment-js', 'moment.min.js', array( 'jquery' ) );
463 Helper::enqueue_script( 'select2-js', 'select2.full.min.js', array( 'jquery' ) );
464 Helper::enqueue_script( SIMPLE_URLS_SLUG . '-jq-auto-complete-js', 'jquery-autocomplete.js' );
465
466 Helper::enqueue_script( 'popper-js', 'popper.min.js', array( 'jquery' ) );
467 Helper::enqueue_script( 'bootstrap-js', 'bootstrap.min.js', array( 'jquery' ) );
468 Helper::enqueue_script( 'bootstrap-select-js', 'bootstrap-select.min.js', array( 'jquery' ) );
469 Helper::enqueue_script( 'pagination-js', 'jquery.simplePagination.js', array( 'jquery' ) );
470 Helper::enqueue_script( 'jsrender', 'jsrender.min.js' );
471
472 wp_localize_script( 'jquery', 'lassoLiteOptionsData', $data_passed_to_js );
473 Helper::enqueue_script( 'lasso-helper', 'lasso-helper.js', array( 'jquery' ) );
474 Helper::enqueue_script( 'url-add', 'url-add.js', array( 'jquery' ) );
475 Helper::enqueue_script( 'support', 'support.js', array( 'jquery' ) );
476
477 if ( ! $setting->is_setting_onboarding_page() && ! $setting->is_setting_amazon_page() ) {
478 Helper::enqueue_script( 'lasso-signup', 'lasso-signup.js', array( 'jquery' ) );
479 }
480
481 if ( SIMPLE_URLS_SLUG . '-' . Enum::PAGE_URL_DETAILS === $page ) {
482 Helper::enqueue_script( 'url-details', 'url-details.js', array( 'jquery' ) );
483 }
484 }
485
486 if ( $setting->is_dashboard_page() ) {
487 Helper::enqueue_script( 'dashboard', 'dashboard.js', array( 'jquery' ) );
488 }
489
490 if ( $setting->is_opportunities_page() ) {
491 Helper::enqueue_script( 'opportunities', 'opportunities.js', array( 'jquery' ) );
492 }
493
494 if ( $setting->is_tables_page() ) {
495 Helper::enqueue_script( 'tables', 'tables.js', array( 'jquery' ) );
496 }
497
498 if ( $setting->is_setting_display_page() || $setting->is_setting_onboarding_page() ) {
499 Helper::enqueue_script( 'spectrum-js', 'spectrum.min.js', array( 'jquery' ) );
500 Helper::enqueue_script( 'settings-display-js', 'settings-display.js', array( 'jquery' ) );
501 }
502
503 if ( $setting->is_setting_amazon_page() ) {
504 Helper::enqueue_script( 'lasso-signup', 'lasso-signup.js', array( 'jquery' ) );
505 Helper::enqueue_script( 'settings-amazon', 'settings-amazon.js', array( 'jquery', SIMPLE_URLS_SLUG . '-lasso-signup' ) );
506 } elseif ( $setting->is_setting_onboarding_page() ) {
507 Helper::enqueue_script( 'settings-amazon', 'settings-amazon.js', array( 'jquery' ) );
508 }
509
510 if ( $setting->is_import_page() || $setting->is_setting_onboarding_page() ) {
511 Helper::enqueue_script( 'settings-import', 'settings-import.js', array( 'jquery' ) );
512 }
513
514 if ( $setting->is_setting_onboarding_page() ) {
515 Helper::enqueue_script( 'onboarding-js', 'onboarding.js', array( 'jquery' ) );
516 Helper::enqueue_script( 'settings-js', 'settings.js', array( 'jquery' ) );
517 Helper::enqueue_script( 'settings-display-js', 'settings-display.js', array( 'jquery' ) );
518 Helper::enqueue_script( 'lasso-signup', 'lasso-signup.js', array( 'jquery' ) );
519 }
520
521 if ( $setting->is_setting_general_page() ) {
522 Helper::enqueue_script( 'settings-general', 'settings-general.js', array( 'jquery' ) );
523 }
524
525 if ( $setting->is_setting_page() ) {
526 Helper::enqueue_script( 'settings-unsaved-guard', 'settings-unsaved-guard.js', array( 'jquery', SIMPLE_URLS_SLUG . '-lasso-helper' ) );
527 }
528
529 if ( $setting->is_group_detail_page() || $setting->is_group_page() ) {
530 Helper::enqueue_script( 'groups', 'groups.js', array( 'jquery' ) );
531 }
532
533 // @codingStandardsIgnoreEnd
534 }
535
536 /**
537 * DISPLAYS CSS FOR FRONTEND OF SITE
538 */
539 public function add_scripts_frontend() {
540 Helper::enqueue_style( 'lasso-lite', 'lasso-lite.css' );
541 }
542
543 /**
544 * DISPLAYS CUSTOM CSS FOR FRONTEND OF SITE
545 */
546 public function lasso_custom_css() {
547 if ( ! Helper::is_lite_using_new_ui() ) {
548 return;
549 }
550
551 // @codingStandardsIgnoreStart
552 echo '<style type="text/css">' . Helper::get_lasso_display_css_variables( true ) . '</style>';
553
554 // fix fontawesome js render svg (from other plugins) instead of using css
555 echo '
556 <script type="text/javascript">
557 // Notice how this gets configured before we load Font Awesome
558 window.FontAwesomeConfig = { autoReplaceSvg: false }
559 </script>
560 ';
561 // @codingStandardsIgnoreEnd
562 }
563
564 /**
565 * Order menu and submenu of Lasso
566 *
567 * @param boolean $custom_menu Whether custom ordering is enabled. Default false.
568 */
569 public function lasso_order_submenu( $custom_menu ) {
570 global $submenu;
571
572 $new_submenu = array();
573 $menu_key = 'edit.php?post_type=' . SIMPLE_URLS_SLUG;
574 $lasso_lite_submenu = @$submenu[ $menu_key ]; // phpcs:ignore
575
576 $parent_slug = 'edit.php?post_type=' . SIMPLE_URLS_SLUG;
577 $hide_menu = array(
578 SIMPLE_URLS_SLUG . '-' . Enum::PAGE_SETTINGS_GENERAL,
579 SIMPLE_URLS_SLUG . '-' . Enum::PAGE_SETTINGS_AMAZON,
580 SIMPLE_URLS_SLUG . '-' . Enum::PAGE_URL_DETAILS,
581 SIMPLE_URLS_SLUG . '-' . Enum::PAGE_OPPORTUNITIES,
582 SIMPLE_URLS_SLUG . '-' . Enum::PAGE_TABLES,
583 SIMPLE_URLS_SLUG . '-' . Enum::PAGE_GROUPS,
584 SIMPLE_URLS_SLUG . '-' . Enum::PAGE_GROUP_DETAIL,
585 );
586 $surl_dashboard = array(
587 SIMPLE_URLS_SLUG . '-' . Enum::PAGE_DASHBOARD,
588 'post-new.php?post_type=' . SIMPLE_URLS_SLUG,
589 );
590
591 if ( ! empty( $lasso_lite_submenu ) ) {
592 foreach ( $lasso_lite_submenu as $subpage ) {
593 // ? Show the new menus
594 if ( ! $this->show_old_menus && in_array( $subpage[2], $surl_dashboard, true ) ) { // ? Hide "Add new" and SURL Dashboard
595 continue;
596 } elseif ( ! $this->show_old_menus && $parent_slug === $subpage[2] ) { // ? Change title of root dashboard(all posts) menu
597 $subpage[0] = 'Dashboard';
598 $new_submenu[] = $subpage;
599 } elseif ( ! in_array( $subpage[2], $hide_menu, true ) ) {
600 if ( SIMPLE_URLS_SLUG . '-' . Enum::PAGE_SETTINGS_DISPLAY === $subpage[2] ) {
601 $subpage[0] = 'Settings';
602 }
603
604 $new_submenu[] = $subpage;
605 }
606 }
607
608 $new_submenu[90] = array(
609 'Support',
610 'manage_options',
611 Constant::LASSO_SUPPORT_URL,
612 );
613
614 $new_submenu[93] = array(
615 'Analytics',
616 'manage_options',
617 Constant::LASSO_ANALYTICS_URL,
618 );
619
620 $new_submenu[95] = array(
621 'Marketplace',
622 'manage_options',
623 Constant::LASSO_AFFILIATE_PLUS_URL,
624 );
625
626 $new_submenu[100] = array(
627 '<b class="green">Upgrade to Pro</b>',
628 'manage_options',
629 Constant::LASSO_UPGRADE_URL,
630 );
631 }
632
633 // ? ERROR | Overriding WordPress globals is prohibited. Found assignment to $submenu
634 // phpcs:ignore
635 $submenu[ $menu_key ] = $new_submenu;
636 }
637
638 /**
639 * Lasso display styles + color variables inside the block editor iframe (WP 7+).
640 *
641 * admin_enqueue_scripts only loads into the parent editor chrome; shortcode HTML
642 * preview renders in the editor canvas iframe and needs enqueue_block_assets.
643 *
644 * @codeCoverageIgnore Coverage ignore.
645 */
646 public function lasso_block_editor_css_variables() {
647 if ( ! is_admin() || Helper::is_lasso_pro_installed() || ! Helper::is_lite_using_new_ui() ) {
648 return;
649 }
650
651 $setting = new Setting();
652 if ( ! $setting->is_wordpress_post() && ! $setting->is_custom_post() ) {
653 return;
654 }
655
656 Helper::enqueue_style( 'bootstrap-grid-css', 'bootstrap-grid.min.css' );
657 Helper::enqueue_style( 'lasso-lite', 'lasso-lite.css' );
658 wp_add_inline_style( SIMPLE_URLS_SLUG . '-lasso-lite', Helper::get_lasso_display_css_variables( true ) );
659 }
660
661 /**
662 * Load lasso js file in Gutenberg editor
663 */
664 public function lasso_lite_gutenberg_block() {
665 if ( ! Helper::is_lasso_pro_installed() ) {
666 Helper::enqueue_script(
667 'lasso-lite-gutenberg-block',
668 'lasso-lite-gutenberg-block.js',
669 array( 'wp-blocks', 'wp-block-editor', 'wp-element', 'wp-components', 'wp-compose' ),
670 true
671 );
672 Helper::enqueue_script( 'display-add', 'display-add.js', array( 'jquery' ) );
673 Helper::enqueue_script( 'url-add', 'url-add.js', array( 'jquery' ) );
674 }
675 }
676
677 /**
678 * Load lasso js file in Classic editor (TinyMCE)
679 *
680 * @param array $plugin_array An array of external TinyMCE plugins.
681 */
682 public function lasso_add_tinymce_plugin( $plugin_array ) {
683 if ( ! Helper::is_lasso_pro_plugin_active() ) {
684 $lasso_setting = new Setting();
685 if ( Helper::is_classic_editor() && ( $lasso_setting->is_wordpress_post() || $lasso_setting->is_custom_post() ) ) {
686 $plugin_array['lasso_lite_tc_button'] = SIMPLE_URLS_URL . '/admin/assets/js/lasso-lite-display-modal.js?v=' . strval( @filemtime( SIMPLE_URLS_DIR . '/admin/assets/js/lasso-lite-display-modal.js' ) ); // phpcs:ignore
687 Helper::enqueue_script( 'display-add', 'display-add.js', array( 'jquery' ) );
688 Helper::enqueue_script( 'url-add', 'url-add.js', array( 'jquery' ) );
689 }
690 }
691
692 return $plugin_array;
693 }
694
695 /**
696 * Add Lasso button to Classic editor (TinyMCE)
697 *
698 * @param array $buttons First-row list of buttons.
699 */
700 public function lasso_lite_register_my_tc_button( $buttons ) {
701 if ( ! Helper::is_lasso_pro_plugin_active() ) {
702 array_push( $buttons, 'lasso_lite_tc_button' );
703 array_push( $buttons, 'lasso_grid_button' );
704 }
705
706 return $buttons;
707 }
708
709 /**
710 * Render template in admin footer on screen editor Gutenberg
711 */
712 public function lasso_lite_admin_footer_editor_gutenberg() {
713 if ( ! Helper::is_lasso_pro_plugin_active() ) {
714 $lasso_setting = new Setting();
715
716 if ( $lasso_setting->is_wordpress_post() || $lasso_setting->is_custom_post() ) {
717 $current_screen = get_current_screen();
718 // ? Check to make sure render html only block editor Gutenberg
719 if ( ( method_exists( $current_screen, 'is_block_editor' ) && $current_screen->is_block_editor() )
720 || ( function_exists( 'is_gutenberg_page' ) && is_gutenberg_page() )
721 ) {
722 echo Helper::get_display_modal_html(); // phpcs:ignore
723 }
724 }
725 }
726 }
727
728 /**
729 * Custom target menu
730 */
731 public function lasso_custom_menu() {
732 ?>
733 <script type="text/javascript">
734 jQuery( document ).ready( function( $ ) {
735 jQuery( "ul#adminmenu a[href$='<?php echo Constant::LASSO_SUPPORT_URL; // phpcs:ignore ?>']" ).attr( 'target', '_blank' );
736 jQuery( "ul#adminmenu a[href$='<?php echo Constant::LASSO_UPGRADE_URL; // phpcs:ignore ?>']" ).attr( 'target', '_blank' );
737 } );
738 </script>
739 <?php
740 }
741
742 /**
743 * Add Amazon tracking id to redirect link
744 *
745 * @param string $redirect Redirect link.
746 */
747 public function lasso_lite_redirect( $redirect ) {
748 if ( Amazon_Api::is_amazon_url( $redirect ) ) {
749 $redirect = Amazon_Api::get_amazon_product_url( $redirect );
750 }
751
752 return $redirect;
753 }
754
755 /**
756 * Pull Amazon API information is stored in AAWP, or Amalinks Pro automatically.
757 *
758 * @return $this
759 */
760 public function amazon_api_pre_populated_automatically() {
761 if ( Helper::get_option( Enum::IS_PRE_POPULATED_AMAZON_API ) ) {
762 return $this;
763 }
764
765 $api_key = '';
766 $api_secret = '';
767 $country = '';
768 $tracking_id = '';
769
770 // ? AAWP plugin
771 if ( Helper::is_aawp_active() ) {
772 $aawp_api = get_option( 'aawp_api' );
773
774 $api_key = $aawp_api['key'] ?? '';
775 $api_secret = $aawp_api['secret'] ?? '';
776 $country = $aawp_api['country'] ?? '';
777 $tracking_id = $aawp_api['associate_tag'] ?? '';
778 }
779
780 // ? AmaLinksPro plugin
781 if ( empty( $api_key ) && empty( $api_secret ) && empty( $tracking_id ) && Helper::is_amalinks_pro_active() ) {
782 $api_key = get_option( 'amalinkspro-options_amazon_api_access_key', '' );
783 $api_secret = get_option( 'amalinkspro-options_amazon_api_secret_key', '' );
784 $country = get_option( 'amalinkspro-options_default_amazon_search_locale', '' );
785 if ( ! empty( $country ) ) {
786 $tracking_id = get_option( 'amalinkspro-options_' . $country . '_amazon_associate_ids_0_associate_id', '' );
787 }
788 }
789
790 $lasso_options = Setting::get_settings();
791 $amazon_access_key_id = $lasso_options['amazon_access_key_id'] ?? '';
792 $amazon_secret_key = $lasso_options['amazon_secret_key'] ?? '';
793 $amazon_tracking_id = $lasso_options['amazon_tracking_id'] ?? '';
794
795 if ( empty( $amazon_access_key_id ) && empty( $amazon_secret_key ) && empty( $amazon_tracking_id )
796 && ! empty( $api_key ) && ! empty( $api_secret ) && ! empty( $tracking_id ) && ! empty( $country )
797 ) {
798 $country = strtolower( $country );
799
800 Setting::set_setting( 'amazon_access_key_id', $api_key );
801 Setting::set_setting( 'amazon_secret_key', $api_secret );
802 Setting::set_setting( 'amazon_default_tracking_country', $country );
803 Setting::set_setting( 'amazon_tracking_id', $tracking_id );
804
805 Helper::update_option( Enum::IS_PRE_POPULATED_AMAZON_API, 1 );
806 }
807
808 return $this;
809 }
810
811 /**
812 * Remove action "admin_print_footer_scripts" of "Easy Table of Contents" plugin
813 */
814 public function remove_easy_table_of_content_action_admin_print_footer_scripts() {
815 Helper::remove_action( 'admin_print_footer_scripts', array( 'eztoc_pointers', 'admin_print_footer_scripts' ) );
816 }
817
818 /**
819 * Prints the templates used in the media manager.
820 */
821 public function lasso_print_media_templates() {
822 if ( file_exists( ABSPATH . WPINC . '/media-template.php' ) && ! function_exists( 'wp_print_media_templates' ) ) {
823 require_once ABSPATH . WPINC . '/media-template.php';
824 }
825 wp_print_media_templates();
826 }
827
828 /**
829 * Add active class to the current page
830 */
831 public function lasso_organize_menu() {
832 $setting_page = ( new Setting() )->is_setting_page();
833 ?>
834 <script>
835 jQuery(document).ready(function(){
836 var lasso_menu = jQuery('#menu-posts-surl');
837 if(lasso_menu.is('.wp-has-current-submenu, .wp-menu-open')){
838 var submenu = lasso_menu.find('ul.wp-submenu').find('li');
839 if(submenu != undefined) {
840 if(!submenu.hasClass('current') || submenu.hasClass('current').length == 0) {
841 submenu.eq(1).addClass('current');
842 }
843
844 // add class `current` for Settings menu
845 if('<?php echo (int) $setting_page; ?>' == '1') {
846 submenu.removeClass('current');
847 lasso_menu.find('ul.wp-submenu').find('li:contains("Settings")').addClass('current');
848 }
849 }
850 }
851 });
852 </script>
853 <?php
854 }
855
856 /**
857 * Register a category
858 */
859 public function register_taxonomy() {
860 // ? register custom taxonomy
861 register_taxonomy(
862 Constant::LASSO_CATEGORY,
863 Constant::LASSO_POST_TYPE,
864 array(
865 'label' => __( 'Lasso Categories' ),
866 'rewrite' => array( 'slug' => Constant::LASSO_CATEGORY ),
867 'hierarchical' => false,
868 'public' => false,
869 'labels' => array(
870 'add_new_item' => __( 'Add New Category' ),
871 'edit_item' => __( 'Edit Categories' ),
872 ),
873 )
874 );
875 }
876
877 /**
878 * Use Amazon product url instead Lasso url when search/insert a link into a post/page
879 *
880 * @param array $response Response data to send to the client.
881 * @param object $server (WP_REST_Server) Server instance.
882 * @param object $request (WP_REST_Request) Request used to generate the response.
883 */
884 public function update_post_type_gutenberg( $response, $server, $request ) {
885 $params = $request->get_params();
886 $type = $params['type'] ?? '';
887 if ( 'post' === $type && is_array( $response ) && '/wp/v2/search' === $request->get_route() && count( $response ) > 0 ) {
888 foreach ( $response as $key => $post ) {
889 if ( 'post' === $post['type'] && Constant::LASSO_POST_TYPE === $post['subtype'] ) {
890 $response[ $key ]['subtype'] = Constant::LASSO_PRO_POST_TYPE; // ? update post type to Pro
891 }
892 }
893 }
894
895 return $response;
896 }
897
898 /**
899 * Custom post type to Lasso Branding
900 *
901 * @param array $results Search results.
902 *
903 * @return mixed
904 */
905 public function update_post_type_classic_editor( $results ) {
906 if ( ! empty( $results ) ) {
907 foreach ( $results as &$result ) {
908 $type = get_post_type( $result['ID'] );
909 if ( Constant::LASSO_POST_TYPE === $type ) {
910 $result['info'] = Constant::LASSO_BRAND;
911 }
912 }
913 }
914 return $results;
915 }
916
917 /**
918 * Update the text in the footer
919 *
920 * @param string $text Text.
921 */
922 public function admin_footer( $text ) {
923 global $current_screen;
924
925 $setting = new Setting();
926
927 if ( ! empty( $current_screen->id ) && $setting->is_surls_page() ) {
928 $url = Enum::LASSO_REVIEW_URL;
929 $text = sprintf(
930 wp_kses(
931 'Enjoying %1$s? Please rate <a href="%2$s" target="_blank" rel="noopener noreferrer">&#9733;&#9733;&#9733;&#9733;&#9733;</a> on <a href="%3$s" target="_blank" rel="noopener">WordPress.org</a> to help us spread the word. Thanks from the Lasso team!',
932 array(
933 'a' => array(
934 'href' => array(),
935 'target' => array(),
936 'rel' => array(),
937 ),
938 )
939 ),
940 '<strong>Lasso Lite</strong>',
941 $url,
942 $url
943 );
944 }
945
946 return $text;
947 }
948
949 /**
950 * Open Affiliate+ in new tab
951 */
952 public function open_links_in_new_tab() {
953 ?>
954 <script type="text/javascript">
955 jQuery(document).ready(function($) {
956 $('a[href="https://app.getlasso.co/plus/"]').attr('target', '_blank');
957 });
958 </script>
959 <?php
960 }
961
962 /**
963 * Whether Lite onboarding should redirect admin users to the welcome flow.
964 *
965 * @return bool
966 */
967 public static function should_redirect_to_welcome_page() {
968 return (bool) get_option( Enum::LASSO_LITE_ACTIVE ) && ! Helper::get_option( Enum::IS_VISITED_WELCOME_PAGE );
969 }
970
971 /**
972 * Whether the affiliate promo dashboard banner should render.
973 *
974 * @return bool
975 */
976 private function should_show_dashboard_promo_banner() {
977 global $pagenow;
978
979 if ( 'index.php' !== $pagenow || ! Helper::is_lite_using_new_ui() ) {
980 return false;
981 }
982
983 $license_active = License::get_license_status();
984 $is_connected_aff = intval( Helper::get_option( Constant::LASSO_OPTION_IS_CONNECTED_AFFILIATE, '0' ) );
985
986 return ! $license_active
987 && 0 === $is_connected_aff
988 && ! intval( Helper::get_option( Constant::LASSO_OPTION_DISMISS_PROMOTIONS, 0 ) );
989 }
990
991 /**
992 * Show Performance promotion
993 *
994 * @return void
995 */
996 public function lasso_lite_custom_dashboard_banner() {
997 if ( ! $this->should_show_dashboard_promo_banner() ) {
998 echo ''; // phpcs:ignore
999 return;
1000 }
1001
1002 $setting_data = Setting::get_settings();
1003 $support_enabled = $setting_data[ Enum::SUPPORT_ENABLED ] ?? false;
1004 if ( ! $support_enabled ) {
1005 $template_path = '/admin/views/notifications/affiliate-promotions-no-intercom.php';
1006 } else {
1007 $template_path = '/admin/views/notifications/affiliate-promotions-intercom.php';
1008 }
1009
1010 $html = Helper::include_with_variables(
1011 SIMPLE_URLS_DIR . $template_path,
1012 array(
1013 'dismiss' => 0,
1014 'option_name' => Constant::LASSO_OPTION_DISMISS_PROMOTIONS,
1015 )
1016 );
1017
1018 echo $html; // phpcs:ignore
1019 }
1020
1021 /**
1022 * Print JS script for Lasso event tracking.
1023 */
1024 public function lasso_lite_event_tracking() {
1025 if ( is_admin() || strpos( Helper::get_server_param( 'REQUEST_URI' ), 'wp-admin' )
1026 || strpos( Helper::get_server_param( 'REQUEST_URI' ), 'elementor-preview' )
1027 || Helper::is_lasso_pro_installed()
1028 ) {
1029 return;
1030 }
1031
1032 $process_lasso_event_tracking = apply_filters( 'lasso_lite_event_tracking', true );
1033
1034 if ( ! $process_lasso_event_tracking ) {
1035 return;
1036 }
1037
1038 $lasso_options = Setting::get_settings();
1039 $is_ip_anonymization = false;
1040 $lsid = Helper::build_lsid();
1041 $realtime_ingest = null;
1042 if ( Realtime_Click::is_ingest_enabled() ) {
1043 $ingest_secret = Realtime_Click::get_ingest_secret();
1044 $channel_id = Realtime_Click::get_channel_id();
1045 if ( is_string( $ingest_secret ) && '' !== $ingest_secret && is_string( $channel_id ) && '' !== $channel_id ) {
1046 $beacon = Realtime_Click::get_beacon_credentials( $channel_id, $ingest_secret );
1047 $realtime_ingest = array(
1048 'ajaxUrl' => admin_url( 'admin-ajax.php' ),
1049 'action' => 'lasso_lite_realtime_ingest',
1050 'channelId' => $channel_id,
1051 'beaconToken' => $beacon['token'],
1052 'beaconBucket' => $beacon['bucket'],
1053 );
1054 }
1055 }
1056
1057 $current_date = gmdate( 'Ymd' );
1058 $js_version = LASSO_LITE_VERSION . '.' . $current_date;
1059
1060 // Prefer clean path when permalinks are enabled; fall back to query when using Plain
1061 $snippet_query = Helper::get_snippet_query();
1062 $performance_url_hash = add_query_arg(
1063 array(
1064 $snippet_query => '1',
1065 'ver' => $js_version,
1066 ),
1067 home_url( '/' )
1068 );
1069
1070 $default_js_domain = 'https://js.codedrink.com';
1071
1072 $dynamic_js_domain = Helper::get_option( 'js_domain', $default_js_domain );
1073 $full_dynamic_js_domain = Helper::get_option( 'full_js_domain', "$dynamic_js_domain/snippet.min.js" );
1074
1075 $dynamic_performance_url_external = $full_dynamic_js_domain . '?ver=' . $js_version; // load external js
1076
1077 // @codeCoverageIgnoreStart
1078 if ( $lasso_options['performance_event_tracking'] ) :
1079 ?>
1080
1081 <script type="text/javascript">
1082 (function () {
1083 // Prevent double-insert
1084 if (window.LS_AFF_IS_LOADED || window.__LS_SEQ_LOADER__) {
1085 return;
1086 }
1087 window.__LS_SEQ_LOADER__ = true;
1088 var lsSources = [
1089 <?php echo wp_json_encode( $dynamic_performance_url_external ); ?>,
1090 <?php echo wp_json_encode( $performance_url_hash ); ?>
1091 ];
1092
1093 var lsScriptLoadTimeoutMs = 2500;
1094 var lsIndex = 0, lsTimeoutMs = lsScriptLoadTimeoutMs;
1095
1096 function lsLoadNext() {
1097 if (window.LS_AFF_IS_LOADED || lsIndex >= lsSources.length) {
1098 return;
1099 }
1100
1101 var lsUrl = lsSources[lsIndex++];
1102 var lsScript = document.createElement('script');
1103 lsScript.src = lsUrl;
1104 lsScript.onerror = function () {
1105 try { lsScript.remove(); } catch (_) {}
1106 if (!window.LS_AFF_IS_LOADED) lsLoadNext();
1107 };
1108 var lsTimer = setTimeout(function () {
1109 if (!window.LS_AFF_IS_LOADED) {
1110 try { lsScript.remove(); } catch (_) {}
1111 lsLoadNext();
1112 }
1113 }, lsTimeoutMs);
1114 lsScript.onload = (function (orig) {
1115 return function () {
1116 clearTimeout(lsTimer);
1117 if (orig) orig();
1118 };
1119 })(lsScript.onload);
1120 (document.head || document.documentElement).appendChild(lsScript);
1121 }
1122
1123 lsLoadNext();
1124 })();
1125 </script>
1126 <script type="text/javascript">
1127 (function(){
1128 <?php if ( null !== $realtime_ingest ) : ?>
1129 window.LASSO_LITE_REALTIME_INGEST = <?php echo wp_json_encode( $realtime_ingest ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>;
1130 <?php endif; ?>
1131 var lsInitialized = false;
1132 function lsDoInit(detail){
1133 if (lsInitialized) return;
1134 lsInitialized = true;
1135 try {
1136 (detail && detail.init ? detail : (window.LSAFFEvents || {})).init({
1137 'lsid': '<?php echo $lsid; // phpcs:ignore ?>',
1138 'pid': '<?php echo get_the_ID(); // phpcs:ignore ?>',
1139 'ipa': '<?php echo $is_ip_anonymization; // phpcs:ignore ?>',
1140 'performance': '1',
1141 'matching': '<?php echo $lasso_options['auto_upgrade_eligible_links'] ? 1 : 0; ?>',
1142 });
1143 } catch (err) {
1144 }
1145 }
1146
1147 var lsPollCount = 0;
1148 var lsMaxPollAttempts = 50;
1149 var lsPollTimer = null;
1150 function lsStartPolling() {
1151 if (lsPollTimer) return;
1152 lsPollTimer = setInterval(function(){
1153 if (lsInitialized) { clearInterval(lsPollTimer); return; }
1154 if (window.LSAFFEvents && typeof window.LSAFFEvents.init === 'function') {
1155 lsDoInit(window.LSAFFEvents);
1156 clearInterval(lsPollTimer);
1157 return;
1158 }
1159 lsPollCount++;
1160 if (lsPollCount > lsMaxPollAttempts) { // ~5s at 100ms
1161 clearInterval(lsPollTimer);
1162 }
1163 }, 100);
1164 }
1165
1166 if (window.LSAFFEvents && typeof window.LSAFFEvents.init === 'function') {
1167 lsDoInit(window.LSAFFEvents);
1168 } else {
1169 document.addEventListener('LSAFFEventLoaded', function(e){
1170 lsDoInit(e.detail);
1171 }, { once: true });
1172 lsStartPolling();
1173 }
1174 })();
1175 </script>
1176 <?php
1177 endif;
1178 // @codeCoverageIgnoreEnd
1179 }
1180
1181 /**
1182 * Elementor Init Hook
1183 *
1184 * @codeCoverageIgnore Coverage ignore.
1185 */
1186 public function elementor_init() {
1187 // ? This runs on elementor/init only — Pro owns Elementor when affiliate-plugin is active.
1188 if ( Helper::is_lasso_pro_installed() ) {
1189 return;
1190 }
1191
1192 // ? Do not gate on is_plugin_active( 'elementor/elementor.php' ): custom paths / load order can false-negative while Elementor is clearly bootstrapped (this hook).
1193 if ( class_exists( 'Elementor\Widget_Base' ) && class_exists( 'Elementor\Controls_Manager' ) ) {
1194 add_action( 'elementor/widgets/register', array( $this, 'register_widget_lasso_shortcode' ) );
1195 add_action( 'elementor/editor/before_enqueue_styles', array( $this, 'elementor_editor_styles' ) );
1196 add_action( 'elementor/editor/before_enqueue_scripts', array( $this, 'elementor_editor_scripts' ) );
1197 }
1198
1199 // ? Move the scan post into the "elementor/document/after_save" action
1200 add_action( 'elementor/document/after_save', array( $this, 'after_elementor_document_save' ), 10, 1 );
1201 }
1202
1203 /**
1204 * Register lasso widget
1205 *
1206 * @param object $widgets_manager Widget manager.
1207 *
1208 * @codeCoverageIgnore Coverage ignore.
1209 */
1210 public function register_widget_lasso_shortcode( $widgets_manager ) {
1211 require_once SIMPLE_URLS_PLUGIN_PATH . '/libs/elementor/widgets/lasso-shortcode.php';
1212 $widgets_manager->register( new \Widget_Lasso_Shortcode() );
1213 }
1214
1215 /**
1216 * Elementor load css
1217 *
1218 * @codeCoverageIgnore Coverage ignore.
1219 */
1220 public function elementor_editor_styles() {
1221 wp_enqueue_style( 'wp-pointer' );
1222 Helper::enqueue_style( 'lasso-elementor', 'lasso-elementor.css' );
1223 }
1224
1225 /**
1226 * Elementor editor scripts (parity with Pro wp-pointer).
1227 *
1228 * @codeCoverageIgnore Coverage ignore.
1229 */
1230 public function elementor_editor_scripts() {
1231 wp_enqueue_script( 'wp-pointer' );
1232 if ( ! Helper::is_lite_using_new_ui() ) {
1233 return;
1234 }
1235 wp_enqueue_script( 'jquery' );
1236 Helper::enqueue_script( 'lasso-modal-js', 'lasso-modal.js', array( 'jquery' ), true );
1237 Helper::enqueue_script( 'lasso-elementor', 'lasso-elementor.js', array( 'jquery', SIMPLE_URLS_SLUG . '-lasso-modal-js' ), true );
1238 Helper::enqueue_script( 'lasso-lite-display-modal', 'lasso-lite-display-modal.js', array( 'jquery', SIMPLE_URLS_SLUG . '-lasso-elementor' ), true );
1239 }
1240
1241 /**
1242 * Move the scan post into the "elementor/document/after_save" action
1243 *
1244 * @param object $document Elementor document.
1245 *
1246 * @codeCoverageIgnore Coverage ignore.
1247 */
1248 public function after_elementor_document_save( $document ) {
1249 $post = $document->get_post();
1250 }
1251
1252 /**
1253 * Exclude Lasso performance JS from WP Rocket cache
1254 *
1255 * @param array $excluded_js Excluded JS.
1256 * @return array
1257 */
1258 public function exclude_lasso_performance_js_from_rocket_cache( $excluded_js ) {
1259 $excluded_js[] = 'lasso-performance.min.js';
1260 return $excluded_js;
1261 }
1262
1263 /**
1264 * Check is Elementor editor page
1265 *
1266 * @return bool
1267 */
1268 public static function is_editor() {
1269 $http_referer = Helper::get_server_param( 'HTTP_REFERER' );
1270 $query_str = wp_parse_url( $http_referer, PHP_URL_QUERY );
1271 parse_str( $query_str, $query_params );
1272
1273 return isset( $query_params['action'] ) && 'elementor' === $query_params['action'];
1274 }
1275
1276 /**
1277 * Register rewrite rule for /js/connect-snippet.min.js
1278 */
1279 public static function lasso_register_connect_snippet_rewrite() {
1280 $snippet_query = Helper::get_snippet_query();
1281 add_rewrite_rule( '^js/snippet\.min\.js$', 'index.php?' . $snippet_query . '=1', 'top' );
1282
1283 $beacon_path = ltrim( LASSO_BEACON_VANITY_PATH, '/' );
1284 $beacon_rule = '^' . preg_quote( $beacon_path, '/' ) . '$';
1285 add_rewrite_rule( $beacon_rule, 'index.php?' . LASSO_BEACON_QUERY . '=1', 'top' );
1286 }
1287
1288 /**
1289 * Flush rewrites after plugin upgrades via WP upgrader
1290 *
1291 * @param object $upgrader Upgrader instance.
1292 * @param array $options Upgrader options.
1293 * @return void
1294 */
1295 public function lasso_connect_snippet_flush_on_upgrade( $upgrader, $options ) {
1296 if ( empty( $options['type'] ) || 'plugin' !== $options['type'] ) {
1297 return;
1298 }
1299
1300 // ? Supported actions: update (bulk/single) and install (upload .zip)
1301 $action = isset( $options['action'] ) ? $options['action'] : '';
1302 if ( ! in_array( $action, array( 'update', 'install' ), true ) ) {
1303 return;
1304 }
1305
1306 $targets = array();
1307 if ( ! empty( $options['plugins'] ) && is_array( $options['plugins'] ) ) {
1308 $targets = $options['plugins'];
1309 } elseif ( ! empty( $options['plugin'] ) && is_string( $options['plugin'] ) ) {
1310 $targets = array( $options['plugin'] );
1311 }
1312
1313 // ? Fallback detection using Plugin_Upgrader->new_plugin_data when targets are missing
1314 if ( empty( $targets ) && is_object( $upgrader ) && $upgrader instanceof \Plugin_Upgrader ) {
1315 $plugin_data = isset( $upgrader->new_plugin_data ) ? $upgrader->new_plugin_data : array();
1316 $plugin_name = is_array( $plugin_data ) && isset( $plugin_data['Name'] ) ? $plugin_data['Name'] : '';
1317 if ( 'Lasso Lite' === $plugin_name ) {
1318 $this->lasso_register_connect_snippet_rewrite();
1319 flush_rewrite_rules();
1320 return;
1321 }
1322 }
1323
1324 if ( empty( $targets ) ) {
1325 return;
1326 }
1327
1328 $plugin_file = plugin_basename( SIMPLE_URLS_PLUGIN_PATH . '/plugin.php' );
1329 if ( in_array( $plugin_file, $targets, true ) ) {
1330 $this->lasso_register_connect_snippet_rewrite();
1331 flush_rewrite_rules();
1332 }
1333 }
1334
1335 /**
1336 * One-time rewrite flush after upgrade so /js/e is persisted (upgrader runs old code).
1337 *
1338 * @return void
1339 */
1340 public function maybe_flush_vanity_rewrites_on_upgrade() {
1341 if ( '1' !== (string) Helper::get_option( 'pending_vanity_rewrite_flush', '0' ) ) {
1342 return;
1343 }
1344
1345 self::lasso_register_connect_snippet_rewrite();
1346 flush_rewrite_rules();
1347 Helper::update_option( 'pending_vanity_rewrite_flush', '0' );
1348 }
1349
1350 /**
1351 * Allow lasso_connect_snippet as query var
1352 *
1353 * @param array $vars Query vars.
1354 * @return array
1355 */
1356 public function lasso_connect_snippet_query_var( $vars ) {
1357 $snippet_query = Helper::get_snippet_query();
1358 $vars[] = $snippet_query;
1359 $vars[] = LASSO_BEACON_QUERY;
1360 return $vars;
1361 }
1362
1363 /**
1364 * Serve vanity JS: /js/connect-snippet.min.js
1365 *
1366 * Outputs the connect-snippet.min.js from plugin assets with proper caching headers.
1367 */
1368 public function serve_connect_snippet() {
1369 $snippet_query = Helper::get_snippet_query();
1370 // Allow serving by pretty path even if rewrite rules aren't flushed yet
1371 $req_uri = Helper::get_server_param( 'REQUEST_URI' );
1372 $req_path = is_string( $req_uri ) ? wp_parse_url( $req_uri, PHP_URL_PATH ) : '';
1373 $is_snippet_path = is_string( $req_path ) && rtrim( $req_path, '/' ) === LASSO_SNIPPET_VANITY_PATH_LITE;
1374 if ( intval( get_query_var( $snippet_query ) ) !== 1 && ! $is_snippet_path ) {
1375 return;
1376 }
1377
1378 $file_path = LASSO_CONNECT_SNIPPET_FILE_LITE;
1379 if ( ! file_exists( $file_path ) ) {
1380 status_header( 404 );
1381 exit;
1382 }
1383
1384 // Headers
1385 header( 'Content-Type: application/javascript; charset=UTF-8' );
1386 header( 'X-Content-Type-Options: nosniff' );
1387
1388 // Cache headers with support for 304
1389 $last_modified = gmdate( 'D, d M Y H:i:s', filemtime( $file_path ) ) . ' GMT';
1390 $etag = 'W/"' . md5( $last_modified . filesize( $file_path ) ) . '"';
1391
1392 header( 'Last-Modified: ' . $last_modified );
1393 header( 'ETag: ' . $etag );
1394
1395 // Cache: If version query is present, cache for 1 day; else short TTL
1396 $ver = isset( $_GET['ver'] ) ? sanitize_text_field( wp_unslash( $_GET['ver'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
1397 if ( ! empty( $ver ) ) {
1398 header( 'Cache-Control: public, max-age=86400' );
1399 } else {
1400 header( 'Cache-Control: public, max-age=300' );
1401 }
1402
1403 // Handle conditional requests
1404 $if_none_match = isset( $_SERVER['HTTP_IF_NONE_MATCH'] ) ? sanitize_text_field( trim( wp_unslash( $_SERVER['HTTP_IF_NONE_MATCH'] ) ) ) : '';
1405 $if_modified_since = isset( $_SERVER['HTTP_IF_MODIFIED_SINCE'] ) ? sanitize_text_field( trim( wp_unslash( $_SERVER['HTTP_IF_MODIFIED_SINCE'] ) ) ) : '';
1406
1407 if ( $if_none_match === $etag || $if_modified_since === $last_modified ) {
1408 status_header( 304 );
1409 exit;
1410 }
1411
1412 ob_start();
1413 $read_result = @readfile( $file_path );
1414 if ( false === $read_result ) {
1415 if ( ob_get_length() ) {
1416 ob_end_clean();
1417 }
1418 status_header( 500 );
1419 exit;
1420 }
1421 ob_end_flush();
1422 exit;
1423 }
1424
1425 /**
1426 * Resolve a beacon proxy request when path or query var matches.
1427 *
1428 * @param string|null $raw_body Optional body override for tests; null reads php://input.
1429 * @return array{status:int,body:string}|null Null when not a beacon request.
1430 */
1431 public function resolve_beacon_proxy_request( $raw_body = null ) {
1432 $req_uri = Helper::get_server_param( 'REQUEST_URI' );
1433 $req_path = is_string( $req_uri ) ? wp_parse_url( $req_uri, PHP_URL_PATH ) : '';
1434 $is_path = is_string( $req_path ) && rtrim( $req_path, '/' ) === LASSO_BEACON_VANITY_PATH;
1435 $is_query = 1 === intval( get_query_var( LASSO_BEACON_QUERY ) );
1436 if ( ! $is_path && ! $is_query ) {
1437 return null;
1438 }
1439
1440 $method = Helper::get_server_param( 'REQUEST_METHOD' );
1441 if ( null === $raw_body ) {
1442 $raw_body = Beacon_Proxy::read_bounded_body();
1443 }
1444
1445 return $this->handle_beacon_proxy( $method ? $method : 'GET', $raw_body );
1446 }
1447
1448 /**
1449 * Send beacon proxy HTTP response (no exit).
1450 *
1451 * @param array{status:int,body:string} $result Response from handle_beacon_proxy.
1452 * @return void
1453 */
1454 public function emit_beacon_proxy_response( $result ) {
1455 status_header( intval( $result['status'] ) );
1456 header( 'Content-Type: text/plain; charset=UTF-8' );
1457 header( 'Cache-Control: no-store' );
1458 if ( '' !== $result['body'] ) {
1459 echo $result['body']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
1460 }
1461 }
1462
1463 /**
1464 * First-party POST /js/e → codedrink.com/js/e (EasyPrivacy).
1465 */
1466 public function serve_beacon_proxy() {
1467 $result = $this->resolve_beacon_proxy_request();
1468 if ( null === $result ) {
1469 return;
1470 }
1471
1472 $this->emit_beacon_proxy_response( $result );
1473 exit;
1474 }
1475
1476 /**
1477 * Plan and forward a beacon request (testable core of serve_beacon_proxy).
1478 *
1479 * @param string $method HTTP method.
1480 * @param string $raw_body Raw request body.
1481 * @return array{status:int,body:string}
1482 */
1483 public function handle_beacon_proxy( $method, $raw_body ) {
1484 $plan = Beacon_Proxy::plan( $method, is_string( $raw_body ) ? $raw_body : '' );
1485
1486 if ( empty( $plan['ok'] ) ) {
1487 return array(
1488 'status' => intval( $plan['status'] ),
1489 'body' => '',
1490 );
1491 }
1492
1493 $response = wp_remote_post(
1494 $plan['upstream'],
1495 array(
1496 'timeout' => 3,
1497 'sslverify' => true,
1498 'headers' => array(
1499 'Content-Type' => 'text/plain; charset=utf-8',
1500 ),
1501 'body' => $plan['body'],
1502 )
1503 );
1504
1505 if ( is_wp_error( $response ) ) {
1506 return array(
1507 'status' => 200,
1508 'body' => '',
1509 );
1510 }
1511
1512 $status = intval( wp_remote_retrieve_response_code( $response ) );
1513 if ( $status < 200 || $status > 299 ) {
1514 return array(
1515 'status' => 200,
1516 'body' => '',
1517 );
1518 }
1519
1520 return array(
1521 'status' => $status,
1522 'body' => (string) wp_remote_retrieve_body( $response ),
1523 );
1524 }
1525
1526 /**
1527 * Add stable frontend body class from LASSO_LITE_VERSION (e.g. lasso-lite-v145).
1528 *
1529 * @param array<int, string> $classes Body classes.
1530 * @return array<int, string>
1531 */
1532 public function filter_body_class_lasso_lite_version( $classes ) {
1533 $extra = $this->get_lasso_lite_version_body_class();
1534 if ( '' !== $extra ) {
1535 $classes[] = $extra;
1536 }
1537 return $classes;
1538 }
1539
1540 /**
1541 * CSS-safe class segment: lasso-lite-v{version}.
1542 *
1543 * @return string
1544 */
1545 private function get_lasso_lite_version_body_class() {
1546 if ( ! defined( 'LASSO_LITE_VERSION' ) ) {
1547 return '';
1548 }
1549 return 'lasso-lite-v' . sanitize_html_class( str_replace( '.', '-', (string) LASSO_LITE_VERSION ) );
1550 }
1551 }
1552