PluginProbe
aBlocks – Gutenberg Blocks, User Dashboard Builder, Popup Builder, Form Builder & Animation Builder / 2.13.1
aBlocks – Gutenberg Blocks, User Dashboard Builder, Popup Builder, Form Builder & Animation Builder v2.13.1
2.13.0 2.13.1 2.12.0 2.11.1 2.11.0 2.10.0 2.9.0 2.7.4 2.7.5 2.7.6 2.7.7 2.8.0 2.8.1 2.9.1 trunk 1.0 1.0-beta1 1.0-beta2 1.0-beta3 1.0.1 1.0.2 1.0.3 1.1.0 1.1.1 1.1.2 All 80 releases
ablocks / includes / frontend / link-passthrough.php

link-passthrough.php in aBlocks – Gutenberg Blocks, User Dashboard Builder, Popup Builder, Form Builder & Animation Builder 2.13.1, at includes/frontend/link-passthrough.php

146 lines 3.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Query Param Passthrough.
4 *
5 * Carries incoming affiliate / UTM query parameters (e.g. ?ref=xyz) onto
6 * "tagged" links on the page so a visitor who lands with a tracking param keeps
7 * it as they click through the site. It is fully inert unless a tracked param
8 * exists in the current request URL AND a tagged link is present on the page.
9 *
10 * Because tagged links then carry the param forward, it persists across page
11 * views without any cookie.
12 *
13 * @package ABlocks
14 */
15
16 namespace ABlocks\Frontend;
17
18 use ABlocks\Helper;
19
20 if ( ! defined( 'ABSPATH' ) ) {
21 exit; // Exit if accessed directly.
22 }
23
24 class LinkPassthrough {
25
26 public static function init() {
27 $self = new self();
28 add_action( 'wp_enqueue_scripts', [ $self, 'enqueue_assets' ] );
29 }
30
31 /**
32 * The class a link (or a wrapping block) must carry to receive the params.
33 *
34 * @return string
35 */
36 public function get_link_class() : string {
37 $class = (string) Helper::get_settings( 'param_passthrough_class', 'aff-link' );
38 $class = trim( $class );
39 // Keep it a safe, single CSS class token.
40 $class = preg_replace( '/[^A-Za-z0-9_-]/', '', $class );
41
42 return '' === $class ? 'aff-link' : $class;
43 }
44
45 /**
46 * Which links receive the params: 'class', 'all' or 'keyword'.
47 *
48 * @return string
49 */
50 public function get_match_mode() : string {
51 $mode = (string) Helper::get_settings( 'param_passthrough_match', 'class' );
52
53 return in_array( $mode, [ 'class', 'all', 'keyword' ], true ) ? $mode : 'class';
54 }
55
56 /**
57 * Lower-cased list of words a link URL must contain in 'keyword' mode.
58 *
59 * @return string[]
60 */
61 public function get_keywords() : array {
62 $raw = (string) Helper::get_settings( 'param_passthrough_keyword', '' );
63
64 $words = array_filter(
65 array_map(
66 static function ( $word ) {
67 return strtolower( trim( $word ) );
68 },
69 explode( ',', $raw )
70 )
71 );
72
73 return array_values( array_unique( $words ) );
74 }
75
76 /**
77 * Sanitized list of query-parameter keys to carry.
78 *
79 * @return string[]
80 */
81 public function get_param_keys() : array {
82 $raw = (string) Helper::get_settings(
83 'param_passthrough_keys',
84 'ref,utm_source,utm_medium,utm_campaign,utm_term,utm_content'
85 );
86
87 $keys = array_filter(
88 array_map(
89 static function ( $key ) {
90 // Query-string keys are word-ish; strip anything unexpected.
91 return preg_replace( '/[^A-Za-z0-9_\-.]/', '', trim( $key ) );
92 },
93 explode( ',', $raw )
94 )
95 );
96
97 return array_values( array_unique( $keys ) );
98 }
99
100 public function enqueue_assets() {
101 if ( ! (bool) Helper::get_settings( 'param_passthrough_enabled', false ) ) {
102 return;
103 }
104
105 // Nothing to do in the admin / editor context.
106 if ( is_admin() ) {
107 return;
108 }
109
110 $keys = $this->get_param_keys();
111 if ( empty( $keys ) ) {
112 return;
113 }
114
115 $path = ABLOCKS_ASSETS_PATH . 'js/link-passthrough.js';
116 if ( ! file_exists( $path ) ) {
117 return;
118 }
119
120 // The payload is sub-1KB gzipped and already needs an inline config
121 // block, so it's printed inline rather than as an extra HTTP request.
122 // The readable source file stays the single source of truth.
123 $handle = 'ablocks-link-passthrough';
124 wp_register_script( $handle, false, [], ABLOCKS_VERSION, [ 'in_footer' => true ] );
125 wp_enqueue_script( $handle );
126
127 $config = [
128 'keys' => $keys,
129 'mode' => $this->get_match_mode(),
130 'linkClass' => $this->get_link_class(),
131 'keywords' => $this->get_keywords(),
132 'persist' => (bool) Helper::get_settings( 'param_passthrough_persist', true ),
133 'cookieDays' => max( 0, (int) Helper::get_settings( 'param_passthrough_cookie_days', 30 ) ),
134 ];
135
136 // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents
137 $body = (string) file_get_contents( $path );
138
139 wp_add_inline_script(
140 $handle,
141 'window.ABlocksLinkPassthrough = ' . wp_json_encode( $config ) . ";\n" . $body,
142 'after'
143 );
144 }
145 }
146