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
← All changes | classes/class-helper.php +173 -13 152158 View file →
@@ -442,9 +442,9 @@
442 442 $setup_amz_tracking_id = boolval( get_option( Enum::SETUP_AMZ_TRACKING_ID ) ) ? 15 : 0;
443 443 $follow_on_twitter = boolval( get_option( Enum::FOLLOW_ON_TWITTER ) ) ? 10 : 0;
444 444 $share_on_twitter = boolval( get_option( Enum::SHARE_ON_TWITTER ) ) ? 10 : 0;
445 445 $leave_a_review = boolval( get_option( Enum::LEAVE_A_REVIEW ) ) ? 5 : 0;
446 - $is_show_review_note = ! $leave_a_review && $total_links >= 20 && $enable_support && $setup_amz_tracking_id && $follow_on_twitter && $share_on_twitter ? 1 : 0;
446 + $is_show_review_note = ! $leave_a_review && $total_links >= 5 && $enable_support && $setup_amz_tracking_id && $follow_on_twitter && $share_on_twitter ? 1 : 0;
447 447 $progress = $enable_support + $setup_amz_tracking_id + $follow_on_twitter + $share_on_twitter + ( $links * 2 ) + $leave_a_review;
448 448 $progress = $progress ? $progress / 100 : 0;
449 449 $open_modal_add_link = $links < 20 ? 'btn-add-20-links' : '';
450 450
@@ -469,8 +469,74 @@
469 469 return $data;
470 470 }
471 471
472 472 /**
473 + * Whitelist landing-cookie attribution keys for Lite plugin signup (#788).
474 + *
475 + * @param mixed $raw POST attribution object or JSON string.
476 + * @return array|null Sanitized payload or null when no signal.
477 + */
478 + public static function sanitize_signup_attribution( $raw ) {
479 + $allowed_keys = array(
480 + 'url',
481 + 'ref',
482 + 'utm_source',
483 + 'utm_medium',
484 + 'utm_campaign',
485 + 'utm_content',
486 + 'ref_code',
487 + 'dt',
488 + );
489 + $signal_keys = array(
490 + 'utm_source',
491 + 'utm_medium',
492 + 'utm_campaign',
493 + 'utm_content',
494 + 'ref_code',
495 + );
496 +
497 + if ( is_string( $raw ) ) {
498 + $raw = json_decode( $raw, true );
499 + }
500 + if ( ! is_array( $raw ) || empty( $raw ) ) {
501 + return null;
502 + }
503 +
504 + $payload = array();
505 + foreach ( $allowed_keys as $key ) {
506 + if ( ! isset( $raw[ $key ] ) || ! is_scalar( $raw[ $key ] ) ) {
507 + continue;
508 + }
509 + $text = trim( (string) $raw[ $key ] );
510 + if ( '' === $text ) {
511 + continue;
512 + }
513 + if ( in_array( $key, array( 'url', 'ref' ), true ) ) {
514 + $payload[ $key ] = substr( $text, 0, 2048 );
515 + } else {
516 + $payload[ $key ] = substr( $text, 0, 500 );
517 + }
518 + }
519 +
520 + if ( empty( $payload ) ) {
521 + return null;
522 + }
523 +
524 + $has_signal = false;
525 + foreach ( $signal_keys as $key ) {
526 + if ( ! empty( $payload[ $key ] ) ) {
527 + $has_signal = true;
528 + break;
529 + }
530 + }
531 + if ( ! $has_signal && empty( $payload['url'] ) ) {
532 + return null;
533 + }
534 +
535 + return $payload;
536 + }
537 +
538 + /**
473 539 * Send request
474 540 *
475 541 * @param string $method Method (get or post). Default to get.
476 542 * @param string $url URL. Default to empty.
@@ -1256,8 +1322,87 @@
1256 1322 return ! empty( ( new Lasso_DB() )->get_import_plugins( true ) ) ? true : false;
1257 1323 }
1258 1324
1259 1325 /**
1326 + * Ordered onboarding step ids (tab-item data-step values).
1327 + *
1328 + * @return string[]
1329 + */
1330 + public static function get_onboarding_step_ids() {
1331 + return array( 'welcome', 'display', 'amazon', 'connect-lasso', 'import' );
1332 + }
1333 +
1334 + /**
1335 + * @param string $step Step id.
1336 + * @return bool
1337 + */
1338 + public static function is_valid_onboarding_step( $step ) {
1339 + return in_array( $step, self::get_onboarding_step_ids(), true );
1340 + }
1341 +
1342 + /**
1343 + * Last saved onboarding tab for in-progress FTUE.
1344 + *
1345 + * @param bool $include_import Whether the import step is available for this install.
1346 + * @return string
1347 + */
1348 + public static function get_onboarding_current_step( $include_import = true ) {
1349 + $step = (string) self::get_option( Enum::ONBOARDING_CURRENT_STEP, '' );
1350 + if ( ! self::is_valid_onboarding_step( $step ) ) {
1351 + return 'welcome';
1352 + }
1353 + if ( 'import' === $step && ! $include_import ) {
1354 + return 'connect-lasso';
1355 + }
1356 + return $step;
1357 + }
1358 +
1359 + /**
1360 + * @param string $step Step id.
1361 + * @return bool
1362 + */
1363 + public static function save_onboarding_current_step( $step ) {
1364 + if ( ! self::is_valid_onboarding_step( $step ) ) {
1365 + return false;
1366 + }
1367 + return self::update_option( Enum::ONBOARDING_CURRENT_STEP, $step );
1368 + }
1369 +
1370 + /**
1371 + * @return bool
1372 + */
1373 + public static function clear_onboarding_current_step() {
1374 + return self::update_option( Enum::ONBOARDING_CURRENT_STEP, '' );
1375 + }
1376 +
1377 + /**
1378 + * FTUE gate complete: stop redirecting to onboarding and drop saved step.
1379 + *
1380 + * Cleared after first link creation or an explicit Hub Connect skip.
1381 + *
1382 + * @return void
1383 + */
1384 + public static function mark_onboarding_welcome_complete() {
1385 + self::update_option( Enum::IS_VISITED_WELCOME_PAGE, 1 );
1386 + self::clear_onboarding_current_step();
1387 + }
1388 +
1389 + /**
1390 + * Reset FTUE onboarding state for QA (`reset-onboarding=1`).
1391 + *
1392 + * @return void
1393 + */
1394 + public static function reset_onboarding_for_testing() {
1395 + self::update_option( Enum::IS_VISITED_WELCOME_PAGE, 0 );
1396 + self::clear_onboarding_current_step();
1397 + update_option( Enum::LASSO_LITE_ACTIVE, 1 );
1398 + self::update_option( Constant::LASSO_ACCOUNT_EMAIL, '' );
1399 + self::update_option( Constant::LASSO_ACCOUNT_API_KEY, '' );
1400 + self::update_option( Constant::LASSO_ACCOUNT_USER_ID, 0 );
1401 + self::update_option( Constant::LASSO_OPTION_IS_CONNECTED_AFFILIATE, '0' );
1402 + }
1403 +
1404 + /**
1260 1405 * Get brag icon
1261 1406 *
1262 1407 * @param bool $force_to_show Force to show the brag. Default to false.
1263 1408 */
@@ -1446,10 +1591,11 @@
1446 1591 $lasso_review_allow = self::cast_to_boolean( self::get_option( Constant::LASSO_OPTION_REVIEW_ALLOW, '1' ) );
1447 1592 $lasso_review_snooze = self::cast_to_boolean( self::get_option( Constant::LASSO_OPTION_REVIEW_SNOOZE, '0' ) );
1448 1593 $lasso_review_link_count = intval( self::get_option( Constant::LASSO_OPTION_REVIEW_LINK_COUNT, $link_count ) );
1449 1594
1450 - $show = ! $lasso_review_snooze && $link_count >= 20;
1451 - $snooze_but_show = $lasso_review_snooze && $link_count - $lasso_review_link_count >= 20;
1595 + // Ask after early success (enough links to be real usage), not after a large catalog.
1596 + $show = ! $lasso_review_snooze && $link_count >= 5;
1597 + $snooze_but_show = $lasso_review_snooze && $link_count - $lasso_review_link_count >= 5;
1452 1598
1453 1599 if ( ! $lasso_review_allow ) {
1454 1600 return false;
1455 1601 }
@@ -1626,8 +1772,15 @@
1626 1772 $query['refresh_image'] = 1;
1627 1773 }
1628 1774
1629 1775 $request_url = Constant::LASSO_LINK . '/link/status/?' . http_build_query( $query, '', '&', PHP_QUERY_RFC3986 );
1776 + if ( ! $is_lasso_save && defined( 'DOING_CRON' ) && DOING_CRON && ! Cron::should_send_scheduled_data_request( $url ) ) {
1777 + return $get_res ? array(
1778 + 'status_code' => 200,
1779 + 'response' => array(),
1780 + ) : 200;
1781 + }
1782 + Cron::maybe_pace_background_request( $url, $is_lasso_save );
1630 1783 $res = self::send_request( 'get', $request_url, array(), $headers );
1631 1784
1632 1785 // phpcs:ignore
1633 1786 // $res = self::send_request( 'get', LASSO_LINK . '/link/status/?' . $encrypted_base64, array(), $headers );
@@ -1705,12 +1858,15 @@
1705 1858 return $query;
1706 1859 }
1707 1860
1708 1861 /**
1709 - * Remove all the script code from the HTML.
1710 - * Remove script tags and event attributes (e.g., onload, onsubmit, etc.)
1862 + * Sanitize HTML for safe display (formerly regex-based script strip).
1863 + * Now delegates to wp_kses_post so event handlers and javascript: URLs are removed.
1711 1864 *
1712 - * @param string $html HTML code.
1865 + * Falsy input (null, false, empty string) is returned unchanged.
1866 + *
1867 + * @param string|null|false $html HTML code.
1868 + * @return string|null|false Sanitized HTML, or the original falsy value.
1713 1869 */
1714 1870 public static function sanitize_script( $html ) {
1715 1871 if ( ! $html ) {
1716 1872 return $html;
@@ -1715,15 +1871,9 @@
1715 1871 if ( ! $html ) {
1716 1872 return $html;
1717 1873 }
1718 1874
1719 - // ? Remove <script> tags and their variations
1720 - $html = preg_replace( '/<script\b[^>]*>.*?<\/script\s*>/is', '', $html );
1721 -
1722 - // ? Remove event attributes (e.g., onload, onsubmit, etc.) and their values
1723 - $html = preg_replace( '/\s+on\w+\s*=\s*["\'][^"\']*["\']/', ' ', $html );
1724 -
1725 - return $html;
1875 + return wp_kses_post( (string) $html );
1726 1876 }
1727 1877
1728 1878 /**
1729 1879 * Verify access and nonce, then return wp_send_json_error if unverified.
@@ -1894,13 +2044,23 @@
1894 2044 $use_bls = true;
1895 2045 }
1896 2046
1897 2047 if ( is_wp_error( $res ) || $use_bls || 403 === $status_code ) {
2048 + $allow_bls = $is_lasso_save
2049 + || ! defined( 'DOING_CRON' )
2050 + || ! DOING_CRON
2051 + || Cron::should_send_scheduled_data_request( $url );
2052 + if ( ! $allow_bls ) {
2053 + $result = $get_page_title ? array( $url, $page_title ) : $url;
2054 + Cache_Per_Process::get_instance()->set_cache( $cache_prefix . md5( $url ) . $get_page_title, $result );
2055 + return $result;
2056 + }
1898 2057 $headers = self::get_headers();
1899 2058 $data = array(
1900 2059 'url' => $url,
1901 2060 );
1902 2061 $encrypted_base64 = http_build_query( $data );
2062 + Cron::maybe_pace_background_request( $url, $is_lasso_save );
1903 2063 $res = self::send_request( 'get', Constant::LASSO_LINK . '/link/final-url/?' . $encrypted_base64, array(), $headers );
1904 2064
1905 2065 $bls_response = ( isset( $res['response'] ) && is_object( $res['response'] ) ) ? $res['response'] : null;
1906 2066 $final_url = ( null !== $bls_response ) ? ( $bls_response->finalUrl ?? $url ) : $url;