PluginProbe
MailerLite – WooCommerce integration / trunk
MailerLite – WooCommerce integration vtrunk
3.1.27 3.1.25 3.1.26 3.1.24 3.1.23 3.1.22 3.1.21 3.1.20 3.1.19 3.1.18 3.1.17 3.1.16 3.1.15 1.8.7 1.8.8 2.0 2.0.1 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7 2.0.8 2.0.9 All 148 releases
woo-mailerlite / includes / services / WooMailerLiteLanguageService.php

WooMailerLiteLanguageService.php in MailerLite – WooCommerce integration trunk, at includes/services/WooMailerLiteLanguageService.php

154 lines 4.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * Resolves the shopper's language for MailerLite subscriber fields.
5 *
6 * The language is a server side value, so it is never read from the request
7 * payload. It is captured into the session while the shopper is on the site
8 * (where the multilingual context is correct) and snapshotted onto the order,
9 * so requests that run without the shopper's context (gateway callbacks,
10 * admin edits, later status changes) still report the right language.
11 */
12 class WooMailerLiteLanguageService
13 {
14 const META_KEY = '_woo_ml_language';
15
16 public static function enabled()
17 {
18 return (bool) WooMailerLiteOptions::get('settings.languageField');
19 }
20
21 /**
22 * Order meta, then the session, then the language of the current request.
23 * Only returns null for an order whose language was never captured.
24 */
25 public static function resolve($order = null)
26 {
27 // This runs inside checkout and add to cart, so a broken multilingual
28 // filter must cost the language field, never the sale.
29 try {
30 if ($order instanceof WC_Order) {
31 $language = self::normalize($order->get_meta(self::META_KEY))
32 ?: self::normalize($order->get_meta('wpml_language'));
33
34 if ($language) {
35 return $language;
36 }
37
38 // An order touched from wp-admin is not the shopper speaking: the
39 // session and locale here are the store owner's. Send nothing
40 // rather than stamp their language onto the customer.
41 if (is_admin()) {
42 return null;
43 }
44 }
45
46 if (isset(WC()->session)) {
47 $language = self::normalize(WC()->session->get(self::META_KEY));
48 if ($language) {
49 return $language;
50 }
51 }
52
53 return self::current();
54 } catch (\Throwable $e) {
55 WooMailerLiteLog()->error('languageResolve', ['error' => $e->getMessage()]);
56
57 return null;
58 }
59 }
60
61 /**
62 * Language of the request being served right now.
63 */
64 public static function current()
65 {
66 $language = self::normalize(apply_filters('wpml_current_language', null));
67
68 if (!$language && function_exists('pll_current_language')) {
69 $language = self::normalize(pll_current_language('locale'));
70 }
71
72 return $language ?: self::normalize(determine_locale());
73 }
74
75 /**
76 * Remember the language while the shopper's own context is available.
77 */
78 public static function capture()
79 {
80 try {
81 if (!self::enabled() || !isset(WC()->session)) {
82 return;
83 }
84
85 // Ajax runs in an admin context, so its locale is the site's rather
86 // than the shopper's. Let it fill a gap, never overwrite a page request.
87 if (wp_doing_ajax() && self::normalize(WC()->session->get(self::META_KEY))) {
88 return;
89 }
90
91 $language = self::current();
92 if ($language) {
93 WC()->session->set(self::META_KEY, $language);
94 }
95 } catch (\Throwable $e) {
96 WooMailerLiteLog()->error('languageCapture', ['error' => $e->getMessage()]);
97 }
98 }
99
100 /**
101 * Snapshots the language onto the order. Leaves saving to the caller so an
102 * order being built or already being saved does not pay an extra write.
103 */
104 public static function persistToOrder($order)
105 {
106 try {
107 if (!self::enabled() || !$order instanceof WC_Order || $order->get_meta(self::META_KEY)) {
108 return;
109 }
110
111 $language = self::resolve($order);
112 if ($language) {
113 $order->add_meta_data(self::META_KEY, $language, true);
114 }
115 } catch (\Throwable $e) {
116 WooMailerLiteLog()->error('languagePersistToOrder', ['error' => $e->getMessage()]);
117 }
118 }
119
120 /**
121 * Adds the language to subscriber fields. Call after syncFields filtering:
122 * the language field is opted into by its own setting, not by syncFields.
123 */
124 public static function applyTo(array $fields, $order = null)
125 {
126 if (!self::enabled()) {
127 return $fields;
128 }
129
130 $language = self::resolve($order);
131 if ($language) {
132 $fields['subscriber_language'] = $language;
133 $fields['language'] = $language;
134 }
135
136 return $fields;
137 }
138
139 /**
140 * Keeps the get_locale() style format the API already receives, and drops
141 * anything that is not a locale rather than guessing a missing region.
142 */
143 private static function normalize($locale)
144 {
145 if (!is_string($locale) || trim($locale) === '') {
146 return null;
147 }
148
149 $locale = str_replace('-', '_', trim($locale));
150
151 return preg_match('/^[a-z]{2,3}(_[a-z0-9]{2,8})*$/i', $locale) ? $locale : null;
152 }
153 }
154