PluginProbe ʕ •ᴥ•ʔ
WPML Multilingual & Multicurrency for WooCommerce / 5.5.7
WPML Multilingual & Multicurrency for WooCommerce v5.5.7
5.5.7 5.3.8 5.3.9 5.4.3 5.4.4 5.4.5 5.5.1 5.5.1.1 5.5.2.2 5.5.2.3 5.5.3 5.5.3.1 5.5.4 5.5.5 5.5.6 trunk 0.9 1.0 1.1 1.2 1.3 1.4 1.5 2.0 2.2 2.3 2.3.1 2.3.2 3.0 3.0.1 3.1 3.2 3.2.1 3.2.2 3.3 3.3.1 3.3.2 3.3.3 3.3.4 3.4 3.4.1 3.4.2 3.4.3 3.5 3.5.1 3.5.2 3.5.3 3.5.4 3.5.5 3.6 3.6.1 3.6.10 3.6.11 3.6.2 3.6.3 3.6.4 3.6.5 3.6.5.1 3.6.6 3.6.7 3.6.8 3.6.9 3.7 3.7.1 3.7.10 3.7.11 3.7.12 3.7.13 3.7.14 3.7.15 3.7.16 3.7.2 3.7.3 3.7.4 3.7.5 3.7.6 3.7.7 3.7.8 3.7.9 3.8.0 3.8.1 3.8.2 3.8.3 3.8.4 3.8.5 3.8.6 3.9.0 3.9.1 3.9.1.1 3.9.2 3.9.3 3.9.4 3.9.5 4.0.0 4.0.1 4.0.2 4.0.3 4.0.4 4.1.0 4.1.1 4.1.2 4.1.3 4.1.4 4.10.0 4.10.1 4.10.2 4.10.3 4.10.4 4.11.2 4.11.3.2 4.11.5 4.11.6 4.12.1 4.12.4 4.12.5 4.12.6 4.2.0 4.2.0.1 4.2.1 4.2.1.1 4.2.10 4.2.2 4.2.3 4.2.4 4.2.5 4.2.6 4.2.7 4.2.7.1 4.2.8 4.2.8.1 4.2.9 4.3.0 4.3.1 4.3.2 4.3.2.1 4.3.3 4.3.4 4.3.5 4.3.6 4.3.7 4.4.0 4.4.1 4.4.2 4.4.2.1 4.5.0 4.6.0 4.6.1 4.6.2 4.6.2.1 4.6.3 4.6.5 4.6.6 4.6.7 4.7.0 4.7.1 4.7.2 4.7.3 4.7.4 4.7.5 4.7.6 4.7.7 4.7.8 4.7.9 4.8.0 4.9.0 4.9.1 5.0.1 5.0.2 5.1.1 5.1.2 5.1.3 5.2.0 5.2.1 5.3.2 5.3.3.1 5.3.4 5.3.5 5.3.6 5.3.7
woocommerce-multilingual / classes / PaymentGateways / Hooks.php
woocommerce-multilingual / classes / PaymentGateways Last commit date
Settings 1 week ago BlockHooks.php 1 week ago BlockHooksFactory.php 1 week ago Factory.php 1 year ago Hooks.php 1 week ago Strings.php 1 week ago
Hooks.php
289 lines
1 <?php
2
3 namespace WCML\PaymentGateways;
4
5 use IWPML_Backend_Action;
6 use IWPML_Frontend_Action;
7 use IWPML_DIC_Action;
8 use WCML\MultiCurrency\Geolocation;
9 use WCML\StandAlone\IStandAloneAction;
10 use WCML\Utilities\Resources;
11 use WCML\Utilities\AdminUrl;
12 use WPML\API\Sanitize;
13 use WPML\FP\Fns;
14 use WPML\FP\Logic;
15 use WPML\FP\Maybe;
16 use WPML\FP\Obj;
17 use WPML\FP\Relation;
18 use WPML\FP\Str;
19 use WPML\FP\Type;
20
21 class Hooks implements IWPML_Backend_Action, IWPML_Frontend_Action, IWPML_DIC_Action, IStandAloneAction {
22
23 const OPTION_KEY = 'wcml_payment_gateways';
24 const PRIORITY = 1000;
25
26 public function add_hooks() {
27
28 if ( is_admin() ) {
29 if ( $this->isWCGatewaysSettingsScreen() ) {
30 add_action( 'woocommerce_update_options_checkout', [ $this, 'updateSettingsOnSave' ], self::PRIORITY );
31 add_action( 'woocommerce_settings_checkout', [ $this, 'outputInSettings' ], self::PRIORITY );
32 add_action( 'woocommerce_after_settings_checkout', [ $this, 'outputAfterSettings' ], self::PRIORITY );
33 if( $this->isWooC10_1_Spa() ) {
34 add_action( 'admin_enqueue_scripts', [ $this, 'loadSPAAssets' ] );
35 } else {
36 add_action( 'admin_enqueue_scripts', [ $this, 'loadClassicAssets' ] );
37 }
38 }
39 add_action( 'admin_notices', [ $this, 'maybeAddNotice' ] );
40 add_action( 'wp_ajax_wcml_save_payment_gateways', [ $this, 'updateSettingsOnAjaxSave' ] );
41 } else {
42 add_filter( 'woocommerce_available_payment_gateways', [ $this, 'filterByCountry' ], self::PRIORITY );
43 }
44 }
45
46 public function updateSettingsOnSave() {
47
48 if ( isset( $_POST[ self::OPTION_KEY ] ) ) {
49
50 $gatewaySettings = $_POST[ self::OPTION_KEY ];
51 $gatewayId = Sanitize::stringProp( 'ID', $gatewaySettings );
52
53 $this->updateGatewaySettings( $gatewayId, $gatewaySettings );
54 }
55 }
56
57 public function updateSettingsOnAjaxSave() {
58 $nonce = array_key_exists( 'nonce', $_POST ) ? sanitize_text_field( $_POST['nonce'] ) : false;
59 if ( ! $nonce || ! wp_verify_nonce( $nonce, self::OPTION_KEY ) ) {
60 wp_send_json_error();
61 }
62
63 $data = json_decode( stripslashes( Obj::propOr( '{}', 'data', $_POST ) ), true );
64 $gatewayId = Obj::prop( 'gatewayId', $data );
65 $gatewaySettings = Obj::prop( 'settings', $data );
66
67 $updated = $this->updateGatewaySettings( $gatewayId, $gatewaySettings );
68
69 if ( $updated ) {
70 wp_send_json_success();
71 } else {
72 wp_send_json_error();
73 }
74
75 }
76
77 private function updateGatewaySettings( $gatewayId, $gatewaySettings ) {
78 $settings = $this->getSettings();
79 $settingsSignature = maybe_serialize( $settings );
80
81 $settings[ $gatewayId ]['mode'] = isset( $gatewaySettings['mode'] ) && in_array( $gatewaySettings['mode'], [
82 'all',
83 'exclude',
84 'include'
85 ], true ) ? $gatewaySettings['mode'] : 'all';
86
87 $countries = Logic::ifElse(
88 Type::isString(),
89 Str::split( ',' ),
90 Fns::identity(),
91 Obj::propOr( [], 'countries', $gatewaySettings )
92 );
93
94 $validCountries = wpml_collect( WC()->countries->get_countries() )->keys()->toArray();
95
96 $isValidCountry = function( $country ) use ( $validCountries ) {
97 return in_array( $country, $validCountries, true );
98 };
99
100 $settings[ $gatewayId ]['countries'] = wpml_collect( $countries )
101 ->filter( $isValidCountry )
102 ->values()
103 ->toArray();
104
105 $updatedSettingsSignature = maybe_serialize( $settings );
106
107 if ( $settingsSignature === $updatedSettingsSignature ) {
108 return true;
109 }
110
111 return $this->updateSettings( $settings );
112 }
113
114 public function loadClassicAssets() {
115 $enqueue = Resources::enqueueApp( 'paymentGatewaysAdmin' );
116 $gatewayId = sanitize_title( $_GET['section'] );
117
118 $enqueue( [
119 'name' => 'wcmlPaymentGateways',
120 'data' => [
121 'endpoint' => self::OPTION_KEY,
122 'gatewayId' => $gatewayId,
123 'allCountries' => $this->getAllCountries(),
124 'strings' => $this->getStrings(),
125 'settings' => $this->getGatewaySettings( $gatewayId ),
126 ],
127 ] );
128
129 wp_register_style( 'wcml-payment-gateways', WCML_PLUGIN_URL . '/res/css/wcml-payment-gateways.css', [], WCML_VERSION );
130 wp_enqueue_style( 'wcml-payment-gateways' );
131 }
132
133 public function loadSpaAssets() {
134 $enqueue = Resources::enqueueApp( 'paymentGatewaysAdminSPA' );
135
136 $allGatewaySettings = get_option( self::OPTION_KEY, [] );
137 $allGatewaySettings['_default'] = [ 'mode' => 'all', 'countries' => [] ];
138
139 $enqueue( [
140 'name' => 'wcmlPaymentGateways',
141 'data' => [
142 'endpoint' => self::OPTION_KEY,
143 'gatewayId' => null,
144 'allCountries' => $this->getAllCountries(),
145 'strings' => $this->getStrings(),
146 'settings' => $allGatewaySettings,
147 ],
148 ] );
149
150 wp_register_style( 'wcml-payment-gateways', WCML_PLUGIN_URL . '/res/css/wcml-payment-gateways.css', [], WCML_VERSION );
151 wp_enqueue_style( 'wcml-payment-gateways' );
152 }
153
154 private function getStrings() {
155 return [
156 'translationInstructions' => Strings::getTranslationInstructions(),
157 'labelAvailability' => __( 'Country availability', 'woocommerce-multilingual' ),
158 'labelAllCountries' => __( 'All countries', 'woocommerce-multilingual' ),
159 'labelAllCountriesExcept' => __( 'All countries except', 'woocommerce-multilingual' ),
160 'labelAllCountriesExceptDots' => __( 'All countries except...', 'woocommerce-multilingual' ),
161 'labelSpecificCountries' => __( 'Specific countries', 'woocommerce-multilingual' ),
162 'tooltip' => __( 'Configure per country availability for this payment gateway', 'woocommerce-multilingual' ),
163 'submitButton' => [
164 'label' => __( 'Save changes', 'woocommerce-multilingual' ),
165 'success' => __( 'Settings saved.', 'woocommerce-multilingual' ),
166 'error' => __( 'Error saving settings.', 'woocommerce-multilingual' ),
167 ],
168 ];
169 }
170
171 private function getAllCountries() {
172
173 $buildCountry = function ( $label, $code ) {
174 return (object) [
175 'code' => $code,
176 'label' => html_entity_decode( $label ),
177 ];
178 };
179
180 return wpml_collect( WC()->countries->get_countries() )->map( $buildCountry )->values()->toArray();
181 }
182
183 private function isSubmitButtonHidden() {
184 return ! empty( $GLOBALS['hide_save_button'] );
185 }
186
187 public function outputInSettings() {
188 if ( ! $this->isSubmitButtonHidden() ) {
189 $this->output();
190 }
191 }
192
193 public function outputAfterSettings() {
194 if ( $this->isSubmitButtonHidden() ) {
195 ?>
196 <div id="wcml-after-mainform">
197 <?php
198 $this->output();
199 ?>
200 </div>
201 <?php
202 }
203 }
204
205 public function output() {
206 ?><h2>WPML Multilingual & Multicurrency for WooCommerce</h2><div id="wcml-payment-gateways"></div><?php
207 }
208
209 public function filterByCountry( $payment_gateways ) {
210
211 $customer_country = Geolocation::getUserCountry();
212
213 if ( $customer_country ) {
214
215 $ifExceptCountries = function ( $gateway ) use ( $customer_country ) {
216 $gatewaySettings = $this->getGatewaySettings( $gateway->id );
217
218 return $gatewaySettings['mode'] == 'exclude' && in_array( $customer_country, $gatewaySettings['countries'] );
219 };
220
221 $ifNotIncluded = function ( $gateway ) use ( $customer_country ) {
222 $gatewaySettings = $this->getGatewaySettings( $gateway->id );
223
224 return $gatewaySettings['mode'] == 'include' && ! in_array( $customer_country, $gatewaySettings['countries'] );
225 };
226
227 return wpml_collect( $payment_gateways )
228 ->reject( $ifExceptCountries )
229 ->reject( $ifNotIncluded )
230 ->toArray();
231 }
232
233 return $payment_gateways;
234 }
235
236 public function maybeAddNotice(){
237 if( class_exists( 'WooCommerce_Gateways_Country_Limiter' ) ) {
238 echo $this->getNoticeText();
239 }
240 }
241
242 private function getNoticeText(){
243
244 $text = '<div id="message" class="updated error">';
245 $text .= '<p>';
246 $text .= __( 'We noticed that you\'re using WooCommerce Gateways Country Limiter plugin which is now integrated into WPML Multilingual & Multicurrency for WooCommerce. Please remove it!', 'woocommerce-multilingual' );
247 $text .= '</p>';
248 $text .= '</div>';
249
250 return $text;
251 }
252
253 private function getGatewaySettings( $gatewayId ) {
254 return Maybe::fromNullable( get_option( self::OPTION_KEY, false ) )
255 ->map( Obj::prop( $gatewayId ) )
256 ->getOrElse( [ 'mode' => 'all', 'countries' => [] ] );
257 }
258
259 private function getSettings() {
260 return get_option( self::OPTION_KEY, [] );
261 }
262
263 private function updateSettings( $settings ) {
264 return update_option( self::OPTION_KEY, $settings );
265 }
266
267 private function isWCGatewaysSettingsScreen() {
268 if ( $this->isWooC10_1_Spa() ) {
269 return $this->isWCGatewaysSettingsScreenSPA();
270 }
271
272 return Obj::prop( 'section', $_GET )
273 && Relation::equals( AdminUrl::PAGE_WOO_SETTINGS, Obj::prop( 'page', $_GET ) )
274 && Relation::equals( 'checkout', Obj::prop( 'tab', $_GET ) )
275 && ! Relation::propEq( 'section', 'offline', $_GET );
276 }
277
278 private function isWooC10_1_Spa(): bool {
279 return (bool) Obj::prop( 'path', $_GET );
280 }
281
282 private function isWCGatewaysSettingsScreenSPA(): bool {
283 return Obj::prop( 'path', $_GET )
284 && Relation::equals( AdminUrl::PAGE_WOO_SETTINGS, Obj::prop( 'page', $_GET ) )
285 && Relation::equals( 'checkout', Obj::prop( 'tab', $_GET ) );
286 }
287
288 }
289