PluginProbe
GTM Kit – Google Tag Manager & GA4 integration / 1.12
GTM Kit – Google Tag Manager & GA4 integration v1.12
2.18.1 2.18.0 2.17.0 2.16.4 2.16.3 2.16.0 2.16.1 2.15.0 2.14.1 2.14.0 2.13.0 2.13.1 2.12.0 2.11.0 2.10.0 2.9.0 trunk 1.0 1.1 1.1.1 1.10 1.11 1.11.1 1.12 1.12.1 All 100 releases
gtm-kit / src / Options.php

Options.php in GTM Kit – Google Tag Manager & GA4 integration 1.12, at src/Options.php

390 lines 8.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace TLA_Media\GTM_Kit;
4
5
6 final class Options {
7
8 /**
9 * The option_name in wp_options table.
10 *
11 * @var string
12 */
13 const OPTION_NAME = 'gtmkit';
14
15 /**
16 * All the options.
17 *
18 * @var array
19 */
20 private $options;
21
22 /**
23 * Map of all the default options
24 *
25 * @var array
26 */
27 private static $map = [
28 'general' => [
29 'gtm_id',
30 'container_active',
31 'script_implementation',
32 'noscript_implementation',
33 ],
34 'integrations' => [
35 'woocommerce_shipping_info',
36 'woocommerce_payment_info',
37 'woocommerce_variable_product_tracking',
38 'cf7_load_js',
39 ],
40
41 ];
42
43 /**
44 * Construct
45 */
46 public function __construct() {
47 $this->options = get_option( self::OPTION_NAME, [] );
48
49 add_filter( 'pre_update_option_gtmkit', [ $this, 'pre_update_option' ], 10, 2 );
50 }
51
52 function pre_update_option( $new_value, $old_value ): array {
53
54 if ( ! is_array( $new_value ) ) {
55 return $new_value;
56 }
57
58 foreach ( $new_value as $group => $settings ) {
59 $old_value[ $group ] = $settings;
60 }
61
62 return $old_value;
63 }
64
65 /**
66 * Initialize options
67 *
68 * @return Options
69 * @example Options::init()->get('general', 'gtm_id');
70 *
71 */
72 public static function init(): Options {
73
74 static $instance;
75
76 if ( ! $instance ) {
77 $instance = new self();
78 }
79
80 return $instance;
81 }
82
83 /**
84 * Default options that are saved on first installation.
85 *
86 * @return array
87 */
88 public static function get_defaults(): array {
89
90 return [
91 'general' => [
92 'gtm_id' => '',
93 'script_implementation' => '0',
94 'noscript_implementation' => '0',
95 'container_active' => 'on',
96 ],
97 'integrations' => []
98 ];
99 }
100
101 /**
102 * Get options by a group and a key.
103 *
104 * @param string $group The option group.
105 * @param string $key The option key.
106 * @param bool $strip_slashes If the slashes should be stripped from string values.
107 *
108 * @return mixed|null Null if value doesn't exist anywhere: in constants, in DB, in a map. So it's completely custom or a typo.
109 * @example Options::init()->get( 'general', 'gtm_id' ).
110 *
111 */
112 public function get( string $group, string $key, bool $strip_slashes = true ) {
113
114 $value = null;
115
116 $value = $this->get_const_value( $group, $key, $value );
117
118 if ( $value === null ) {
119 // Ordinary database or default values.
120 if ( isset( $this->options[ $group ] ) ) {
121 $value = $this->options[ $group ][ $key ] ?? $this->postprocess_key_defaults( $key );
122 } else {
123 if (
124 isset( self::$map[ $group ] ) &&
125 in_array( $key, self::$map[ $group ], true )
126 ) {
127 $value = $this->postprocess_key_defaults( $key );
128 }
129 }
130 }
131
132 // Conditionally strip slashes only from values saved in DB. Constants should be processed as is.
133 if ( $strip_slashes && is_string( $value ) && ! $this->is_const_defined( $group, $key ) ) {
134 $value = stripslashes( $value );
135 }
136
137 return $value;
138 }
139
140 /**
141 * Postprocess options.
142 *
143 * @param string $key
144 *
145 * @return int|string
146 */
147 protected function postprocess_key_defaults( string $key ) {
148
149 $value = '';
150
151 switch ( $key ) {
152 case 'woocommerce_shipping_info':
153 case 'woocommerce_payment_info':
154 case 'cf7_load_js':
155 $value = '1';
156 break;
157
158 case 'woocommerce_variable_product_tracking':
159 $value = 0;
160 break;
161 }
162
163 return $value;
164 }
165
166 /**
167 * Get constant value if defined.
168 *
169 * @param string $group
170 * @param string $key
171 * @param mixed $value
172 *
173 * @return mixed
174 */
175 protected function get_const_value( string $group, string $key, $value ) {
176
177 if ( ! $this->is_const_enabled() ) {
178 return $value;
179 }
180
181 $return = null;
182
183 switch ( $group ) {
184 case 'general':
185 switch ( $key ) {
186 case 'gtm_id':
187 /** @noinspection PhpUndefinedConstantInspection */
188 $return = $this->is_const_defined( $group, $key ) ? GTMKIT_CONTAINER_ID : $value;
189 break;
190 case 'container_active':
191 /** @noinspection PhpUndefinedConstantInspection */
192 $return = $this->is_const_defined( $group, $key ) ? GTMKIT_CONTAINER_ACTIVE : $value;
193 break;
194 case 'console_log':
195 /** @noinspection PhpUndefinedConstantInspection */
196 $return = $this->is_const_defined( $group, $key ) ? GTMKIT_CONSOLE_LOG : $value;
197 break;
198 }
199 break;
200 default:
201 $return = $value;
202 }
203
204 return $return;
205 }
206
207 /**
208 * Is overriding options with constants enabled or not.
209 *
210 * @return bool
211 */
212 public function is_const_enabled(): bool {
213
214 return defined( 'GTMKIT_ON' ) && GTMKIT_ON === true;
215
216 }
217
218 /**
219 * Is constant defined.
220 *
221 * @param string $group
222 * @param string $key
223 *
224 * @return bool
225 */
226 public function is_const_defined( string $group, string $key ): bool {
227
228 if ( ! $this->is_const_enabled() ) {
229 return false;
230 }
231
232 $return = false;
233
234 switch ( $group ) {
235 case 'general':
236 switch ( $key ) {
237 case 'gtm_id':
238 /** @noinspection PhpUndefinedConstantInspection */
239 $return = defined( 'GTMKIT_CONTAINER_ID' ) && GTMKIT_CONTAINER_ID;
240 break;
241 case 'container_active':
242 /** @noinspection PhpUndefinedConstantInspection */
243 $return = defined( 'GTMKIT_CONTAINER_ACTIVE' ) && ( GTMKIT_CONTAINER_ACTIVE === false || GTMKIT_CONTAINER_ACTIVE === true );
244 break;
245 case 'console_log':
246 /** @noinspection PhpUndefinedConstantInspection */
247 $return = defined( 'GTMKIT_CONSOLE_LOG' ) && ( GTMKIT_CONTAINER_ACTIVE === false || GTMKIT_CONSOLE_LOG === true );
248 break;
249 }
250
251 break;
252 case 'integration':
253 if ( $key == 'woocommerce_debug_track_purchase' ) {
254 $return = defined( 'GTMKIT_WC_DEBUG_TRACK_PURCHASE' ) && GTMKIT_WC_DEBUG_TRACK_PURCHASE === true;
255 }
256
257 break;
258 }
259
260 return $return;
261 }
262
263 /**
264 * Set plugin options.
265 *
266 * @param array $options Plugin options.
267 * @param bool $once Update existing options or only add once.
268 * @param bool $overwrite_existing Overwrite existing settings or merge.
269 */
270 public function set( array $options, bool $once = false, bool $overwrite_existing = true ): void {
271
272 if ( ! $overwrite_existing ) {
273 $options = self::array_merge_recursive( $this->get_all_raw(), $options );
274 }
275
276 $options = $this->process_genericoptions( $options );
277
278 // Whether to update existing options or to add these options only once if they don't exist yet.
279 if ( $once ) {
280 add_option( self::OPTION_NAME, $options, '', 'no' ); // Do not autoload these options.
281 } else {
282 if ( is_multisite() ) {
283 update_blog_option( get_main_site_id(), self::OPTION_NAME, $options );
284 } else {
285 update_option( self::OPTION_NAME, $options, 'no' );
286 }
287 }
288
289 // Now we need to re-cache values.
290 $this->options = get_option( self::OPTION_NAME, [] );
291
292 }
293
294 /**
295 * Process the generic plugin options.
296 *
297 * @param array $options The options array.
298 *
299 * @return array
300 */
301 private function process_genericoptions( array $options ): array {
302
303 foreach ( $options as $group => $keys ) {
304 foreach ( $keys as $option_name => $option_value ) {
305 switch ( $group ) {
306 case 'general':
307 if ( $option_name == 'gtm_id' ) {
308 $options[ $group ][ $option_name ] = sanitize_text_field( $option_value );
309 }
310 break;
311
312 case 'debug_events':
313 if ( $option_name == 'email_debug' ) {
314 $options[ $group ][ $option_name ] = (bool) $option_value;
315 }
316 }
317 }
318 }
319
320 if (!isset($options['integrations'])) $options['integrations'] = [];
321
322 return $options;
323 }
324
325 /**
326 * Merge recursively, including a proper substitution of values in sub-arrays when keys are the same.
327 *
328 * @return array
329 */
330 public static function array_merge_recursive(): array {
331
332 $arrays = func_get_args();
333
334 if ( count( $arrays ) < 2 ) {
335 return $arrays[0] ?? array();
336 }
337
338 $merged = array();
339
340 while ( $arrays ) {
341 $array = array_shift( $arrays );
342
343 if ( ! is_array( $array ) ) {
344 return array();
345 }
346
347 if ( empty( $array ) ) {
348 continue;
349 }
350
351 foreach ( $array as $key => $value ) {
352 if ( is_string( $key ) ) {
353 if (
354 is_array( $value ) &&
355 array_key_exists( $key, $merged ) &&
356 is_array( $merged[ $key ] )
357 ) {
358 $merged[ $key ] = call_user_func( __METHOD__, $merged[ $key ], $value );
359 } else {
360 $merged[ $key ] = $value;
361 }
362 } else {
363 $merged[] = $value;
364 }
365 }
366 }
367
368 return $merged;
369 }
370
371 /**
372 * Get all the options, but without stripping the slashes.
373 *
374 * @return array
375 */
376 public function get_all_raw(): array {
377
378 $options = $this->options;
379
380 foreach ( $options as $group => $g_value ) {
381 foreach ( $g_value as $key => $value ) {
382 $options[ $group ][ $key ] = $this->get( $group, $key, false );
383 }
384 }
385
386 return $options;
387 }
388
389 }
390