PluginProbe ʕ •ᴥ•ʔ
WooCommerce / 10.9.4
WooCommerce v10.9.4
10.9.4 10.9.3 10.9.2 10.9.1 10.9.0 10.9.0-rc.1 10.9.0-beta.2 10.9.0-beta.1 10.8.1 10.8.0 10.8.0-rc.1 10.8.0-beta.2 10.8.0-beta.1 7.8.0-beta.1 7.8.0-beta.2 7.8.0-rc.1 7.8.0-rc.2 7.8.1 7.8.2 7.8.3 7.8.4 7.9.0 7.9.0-beta.1 7.9.0-beta.2 7.9.0-rc.2 7.9.0-rc.3 7.9.1 7.9.2 8.0.0 8.0.0-beta.1 8.0.0-beta.2 8.0.0-rc.1 8.0.0-rc.2 8.0.1 8.0.2 8.0.3 8.0.4 8.0.5 8.1.0 8.1.0-beta.1 8.1.0-rc.1 8.1.0-rc.2 8.1.1 8.1.2 8.1.3 8.1.4 8.2.0 8.2.0-beta.1 8.2.0-rc.1 8.2.0-rc.2 8.2.1 8.2.2 8.2.3 8.2.4 8.2.5 8.3.0 8.3.0-beta.1 8.3.0-rc.1 8.3.0-rc.2 8.3.1 8.3.2 8.3.3 8.3.4 8.4.0 8.4.0-beta.1 8.4.0-rc.1 8.4.1 8.4.2 8.4.3 8.5.0 8.5.0-beta.1 8.5.0-rc.1 8.5.1 8.5.2 8.5.3 8.5.4 8.5.5 8.6.0 8.6.0-beta.1 8.6.0-rc.1 8.6.1 8.6.2 8.6.3 8.6.4 8.7.0 8.7.0-beta.1 8.7.0-beta.2 8.7.0-rc.1 8.7.1 8.7.2 8.7.3 8.8.0 8.8.0-beta.1 8.8.0-rc.1 8.8.1 8.8.2 8.8.3 8.8.4 8.8.5 8.8.6 8.8.7 8.9.0 8.9.0-beta.1 8.9.0-rc.1 8.9.1 8.9.2 8.9.3 8.9.4 8.9.5 9.0.0 9.0.0-beta.1 9.0.0-beta.2 9.0.0-rc.1 9.0.1 9.0.2 9.0.3 9.0.4 9.1.0 9.1.0-beta.1 9.1.0-rc.1 9.1.1 9.1.2 9.1.3 9.1.4 9.1.5 9.1.6 9.2.0 9.2.0-beta.1 9.2.0-rc.1 9.2.1 9.2.2 9.2.3 9.2.4 9.2.5 9.3.0 9.3.0-beta.1 9.3.0-rc.1 9.3.1 9.3.2 9.3.3 9.3.4 9.3.5 9.3.6 9.4.0 9.4.0-beta.1 9.4.0-beta.2 9.4.0-rc.1 9.4.0-rc.2 9.4.0-rc.3 9.4.0-rc.4 9.4.1 9.4.2 9.4.3 9.4.4 9.4.5 9.5.0 9.5.0-beta.1 9.5.0-beta.2 9.5.0-rc.1 9.5.1 9.5.2 9.5.3 9.5.4 9.6.0 9.6.0-beta.1 9.6.0-beta.2 9.6.0-rc.1 9.6.1 9.6.2 9.6.3 9.6.4 9.7.0 9.7.0-beta.1 9.7.0-rc.1 9.7.1 9.7.2 9.7.3 9.8.0 9.8.0-beta.1 9.8.0-rc.1 9.8.1 9.8.2 9.8.3 9.8.4 9.8.5 9.8.6 9.8.7 9.9.0 9.9.0-beta.1 9.9.0-rc.1 9.9.1 9.9.2 9.9.3 9.9.4 9.9.5 9.9.6 9.9.7 3.7.3 7.1.2 3.8.0 7.2.0 3.8.0-beta.1 7.2.0-beta.1 3.8.0-rc.1 7.2.0-beta.2 3.8.0-rc.2 7.2.0-rc.1 3.8.1 7.2.0-rc.2 3.8.2 7.2.1 3.8.3 7.2.2 3.9.0 7.2.3 3.9.0-beta.1 7.2.4 3.9.0-beta.2 7.3.0 3.9.0-rc.1 7.3.0-beta.1 3.9.0-rc.2 7.3.0-beta.2 3.9.0-rc.3 7.3.0-rc.1 3.9.0-rc.4 7.3.0-rc.2 3.9.1 7.3.1 3.9.2 7.4.0 3.9.3 7.4.0-beta.1 3.9.4 7.4.0-beta.2 3.9.5 7.4.0-rc.1 4.0.0 7.4.0-rc.2 4.0.0-beta.1 7.4.1 4.0.0-rc.1 7.4.2 4.0.0-rc.2 7.5.0 4.0.1 7.5.0-beta.1 4.0.2 7.5.0-beta.2 4.0.3 7.5.0-rc.1 4.0.4 7.5.1 4.1.0 7.5.2 4.1.0-beta.1 7.6.0 4.1.0-beta.2 7.6.0-beta.1 4.1.0-rc.1 7.6.0-beta.2 4.1.0-rc.2 7.6.0-rc.1 4.1.1 7.6.0-rc.2 4.1.2 7.6.0-rc.3 4.1.3 7.6.1 4.1.4 7.6.2 4.2.0 7.7.0 4.2.0-RC.1 7.7.0-beta.1 4.2.0-RC.2 7.7.0-beta.2 4.2.0-beta.1 7.7.0-rc.1 4.2.1 7.7.1 4.2.2 7.7.2 4.2.3 7.7.3 4.2.4 7.8.0 4.2.5 4.3.0 4.3.0-beta.1 4.3.0-rc.1 4.3.0-rc.2 4.3.0-rc.3 4.3.1 4.3.2 4.3.3 4.3.4 4.3.5 4.3.6 4.4.0 4.4.0-beta.1 4.4.0-rc.1 4.4.1 4.4.2 4.4.3 4.4.4 4.5.0 4.5.0-beta.1 4.5.0-rc.1 4.5.0-rc.3 4.5.1 4.5.2 4.5.3 4.5.4 4.5.5 4.6.0 4.6.0-beta.1 4.6.0-rc.1 4.6.1 4.6.2 4.6.3 4.6.4 4.6.5 4.7.0 4.7.0-beta.1 4.7.0-beta.2 4.7.0-rc.1 4.7.1 4.7.1-beta.1 4.7.2 4.7.3 4.7.4 4.8.0 4.8.0-beta.1 4.8.0-rc.1 4.8.0-rc.2 4.8.1 4.8.2 4.8.3 4.9.0 4.9.0-beta.1 4.9.0-rc.1 4.9.0-rc.2 4.9.1 4.9.2 4.9.3 4.9.4 4.9.5 5.0.0 5.0.0-beta.1 5.0.0-beta.2 5.0.0-rc.1 5.0.0-rc.2 5.0.0-rc.3 5.0.1 5.0.2 5.0.3 5.1.0 5.1.0-beta.1 5.1.0-rc.1 trunk 5.1.1 10.0.0 5.1.2 10.0.0-rc.1 5.1.3 10.0.0-rc.2 5.2.0 10.0.1 5.2.0-beta.1 10.0.2 5.2.0-rc.1 10.0.3 5.2.0-rc.2 10.0.4 5.2.1 10.0.5 5.2.2 10.0.6 5.2.3 10.1.0 5.2.4 10.1.0-rc.1 5.2.5 10.1.0-rc.2 5.3.0 10.1.0-rc.3 5.3.0-beta.1 10.1.0-rc.4 5.3.0-rc.1 10.1.1 5.3.0-rc.2 10.1.2 5.3.1 10.1.3 5.3.2 10.1.4 5.3.3 10.2.0 5.4.0 10.2.0-beta.1 5.4.0-beta.1 10.2.0-beta.2 5.4.0-rc.1 10.2.0-rc.1 5.4.1 10.2.1 5.4.2 10.2.2 5.4.3 10.2.3 5.4.4 10.2.4 5.4.5 10.3.0 5.5.0 10.3.0-beta.1 5.5.0-beta.1 10.3.0-beta.2 5.5.0-rc.1 10.3.0-rc.1 5.5.0-rc.2 10.3.0-rc.2 5.5.1 10.3.1 5.5.2 10.3.2 5.5.3 10.3.3 5.5.4 10.3.4 5.5.5 10.3.5 5.6.0 10.3.6 5.6.0-beta.1 10.3.7 5.6.0-rc.1 10.3.8 5.6.0-rc.2 10.4.0 5.6.1 10.4.0-beta.1 5.6.2 10.4.0-beta.2 5.6.3 10.4.0-rc.1 5.7.0 10.4.1 5.7.0-beta.1 10.4.2 5.7.0-rc.1 10.4.3 5.7.1 10.4.4 5.7.2 10.5.0 5.7.3 10.5.0-beta.1 5.8.0 10.5.0-beta.2 5.8.0-beta.1 10.5.0-rc.1 5.8.0-beta.2 10.5.0-rc.2 5.8.0-rc.1 10.5.0-rc.3 5.8.1 10.5.1 5.8.2 10.5.2 5.9.0 10.5.3 5.9.0-beta.1 10.6.0 5.9.0-rc.1 10.6.0-beta.1 5.9.0-rc.2 10.6.0-beta.2 5.9.1 10.6.0-rc.1 5.9.2 10.6.1 6.0.0 10.6.2 6.0.0-beta.1 10.7.0 6.0.0-rc.1 10.7.0-beta.1 6.0.1 10.7.0-beta.2 6.0.2 10.7.0-rc.1 6.1.0 3.0.0 6.1.0-beta.1 3.0.1 6.1.0-rc.1 3.0.2 6.1.0-rc.2 3.0.3 6.1.1 3.0.4 6.1.2 3.0.5 6.1.3 3.0.6 6.2.0 3.0.7 6.2.0-beta.1 3.0.8 6.2.0-rc.1 3.0.9 6.2.0-rc.2 3.1.0 6.2.1 3.1.1 6.2.2 3.1.2 6.2.3 3.2.0 6.3.0 3.2.1 6.3.0-beta.1 3.2.2 6.3.0-rc.1 3.2.3 6.3.0-rc.2 3.2.4 6.3.1 3.2.5 6.3.2 3.2.6 6.4.0 3.3.0 6.4.0-beta.1 3.3.1 6.4.0-rc.1 3.3.2 6.4.1 3.3.2-rc.1 6.4.2 3.3.3 6.5.0 3.3.4 6.5.0-beta.1 3.3.5 6.5.0-rc.1 3.3.6 6.5.0-rc.2 3.4.0 6.5.1 3.4.0-beta.1 6.5.2 3.4.0-rc.2 6.6.0 3.4.1 6.6.0-beta.1 3.4.2 6.6.0-rc.1 3.4.3 6.6.0-rc.2 3.4.4 6.6.1 3.4.5 6.6.2 3.4.6 6.7.0 3.4.7 6.7.0-beta.1 3.4.8 6.7.0-beta.2 3.5.0 6.7.0-rc.1 3.5.0-beta.1 6.7.1 3.5.0-rc.1 6.8.0 3.5.0-rc.2 6.8.0-beta.1 3.5.1 6.8.0-beta.2 3.5.10 6.8.0-rc.1 3.5.2 6.8.1 3.5.3 6.8.2 3.5.4 6.8.3 3.5.5 6.9.0 3.5.6 6.9.0-beta.1 3.5.7 6.9.0-beta.2 3.5.8 6.9.0-rc.1 3.5.9 6.9.1 3.6.0 6.9.2 3.6.0-beta.1 6.9.3 3.6.0-rc.1 6.9.4 3.6.0-rc.2 6.9.5 3.6.0-rc.3 7.0.0 3.6.1 7.0.0-beta.1 3.6.2 7.0.0-beta.2 3.6.3 7.0.0-beta.3 3.6.4 7.0.0-rc.1 3.6.5 7.0.0-rc.2 3.6.6 7.0.1 3.6.7 7.0.2 3.7.0 7.1.0 3.7.0-beta.1 7.1.0-beta.1 3.7.0-rc.1 7.1.0-beta.2 3.7.0-rc.2 7.1.0-rc.1 3.7.1 7.1.0-rc.2 3.7.2 7.1.1
woocommerce / includes / admin / settings / class-wc-settings-payment-gateways.php
woocommerce / includes / admin / settings Last commit date
views 1 month ago class-wc-settings-accounts.php 5 months ago class-wc-settings-advanced.php 1 month ago class-wc-settings-checkout.php 5 years ago class-wc-settings-emails.php 1 month ago class-wc-settings-general.php 1 month ago class-wc-settings-integrations.php 1 year ago class-wc-settings-page.php 1 week ago class-wc-settings-payment-gateways.php 1 week ago class-wc-settings-point-of-sale.php 3 months ago class-wc-settings-products.php 1 month ago class-wc-settings-shipping.php 3 months ago class-wc-settings-site-visibility.php 2 years ago class-wc-settings-tax.php 5 months ago
class-wc-settings-payment-gateways.php
480 lines
1 <?php
2 /**
3 * WooCommerce Checkout Settings
4 *
5 * @package WooCommerce\Admin
6 */
7
8 declare( strict_types = 1 );
9
10 use Automattic\WooCommerce\Admin\Settings\SettingsSectionRegistry;
11 use Automattic\WooCommerce\Internal\Admin\Loader;
12
13 defined( 'ABSPATH' ) || exit;
14
15 if ( class_exists( 'WC_Settings_Payment_Gateways', false ) ) {
16 return new WC_Settings_Payment_Gateways();
17 }
18
19 /**
20 * WC_Settings_Payment_Gateways.
21 */
22 class WC_Settings_Payment_Gateways extends WC_Settings_Page {
23
24 const TAB_NAME = 'checkout';
25
26 const MAIN_SECTION_NAME = 'main';
27 const OFFLINE_SECTION_NAME = 'offline';
28 const COD_SECTION_NAME = 'cod'; // Cash on delivery.
29 const BACS_SECTION_NAME = 'bacs'; // Direct bank transfer.
30 const CHEQUE_SECTION_NAME = 'cheque'; // Cheque payments.
31
32 /**
33 * Setting page icon.
34 *
35 * @var string
36 */
37 public $icon = 'payment';
38
39 /**
40 * Memoized list of sections to render using React.
41 *
42 * @var array|null
43 */
44 private ?array $reactified_sections_memo = null;
45
46 /**
47 * Constructor.
48 */
49 public function __construct() {
50 $this->id = self::TAB_NAME;
51 $this->label = esc_html_x( 'Payments', 'Settings tab label', 'woocommerce' );
52
53 // Add filters and actions.
54 add_filter( 'admin_body_class', array( $this, 'add_body_classes' ), 30 );
55 add_action( 'admin_head', array( $this, 'hide_help_tabs' ) );
56 // Hook in as late as possible - `in_admin_header` is the last action before the `admin_notices` action is fired.
57 // It is too risky to hook into `admin_notices` with a low priority because the callbacks might be cached.
58 add_action( 'in_admin_header', array( $this, 'suppress_admin_notices' ), PHP_INT_MAX );
59
60 // Do not show any store alerts (WC admin notes with type: 'error,update' and status: 'unactioned')
61 // on the WooCommerce Payments settings page and Reactified sections.
62 add_filter( 'woocommerce_admin_features', array( $this, 'suppress_store_alerts' ), PHP_INT_MAX );
63
64 parent::__construct();
65 }
66
67 /**
68 * Check if the given section should be rendered using React.
69 *
70 * @param mixed $section The section name to check.
71 * Since this value originates from the global `$current_section` variable,
72 * it is best to accept anything and standardize it to a string.
73 *
74 * @return bool Whether the section should be rendered using React.
75 */
76 public function should_render_react_section( $section ): bool {
77 return in_array( $this->standardize_section_name( $section ), $this->get_reactified_sections(), true );
78 }
79
80 /**
81 * Add body classes.
82 *
83 * @param string $classes The existing body classes.
84 *
85 * @return string The modified body classes.
86 */
87 public function add_body_classes( $classes ) {
88 global $current_tab, $current_section;
89
90 // Bail if the $classes variable is not a string.
91 if ( ! is_string( $classes ) ) {
92 return $classes;
93 }
94
95 // If we are not on the WooCommerce Payments settings page, return the classes as they are.
96 if ( self::TAB_NAME !== $current_tab ) {
97 return $classes;
98 }
99
100 if ( ! $this->should_render_react_section( $current_section ) ) {
101 // Add a class to indicate that the payments settings section page is rendered in legacy mode.
102 $classes .= ' woocommerce-settings-payments-section_legacy';
103 // Add a class to indicate that the current section is rendered in legacy mode.
104 $classes .= ' woocommerce_page_wc-settings-checkout-section-' . esc_attr( $this->standardize_section_name( $current_section ) ) . '_legacy';
105 }
106
107 return $classes;
108 }
109
110 /**
111 * Output the settings.
112 */
113 public function output() {
114 // phpcs:disable WordPress.Security.NonceVerification.Recommended
115 global $current_section;
116
117 // We don't want to output anything from the action for now. So we buffer it and discard it.
118 ob_start();
119 /**
120 * Fires before the payment gateways settings fields are rendered.
121 *
122 * @since 1.5.7
123 */
124 do_action( 'woocommerce_admin_field_payment_gateways' );
125 ob_end_clean();
126
127 if ( is_string( $current_section ) && $this->is_registered_settings_section( $current_section ) ) {
128 parent::output();
129 return;
130 }
131
132 if ( is_string( $current_section ) && $this->should_render_react_section( $current_section ) ) {
133 $this->render_react_section( $this->standardize_section_name( $current_section ) );
134 } elseif ( is_string( $current_section ) && ! empty( $current_section ) ) {
135 // Load gateways so we can show any global options they may have.
136 $payment_gateways = WC()->payment_gateways()->payment_gateways;
137 $this->render_classic_gateway_settings_page( $payment_gateways, $current_section );
138 } else {
139 $this->render_react_section( self::MAIN_SECTION_NAME );
140 }
141
142 parent::output();
143 //phpcs:enable
144 }
145
146 /**
147 * Get settings array.
148 *
149 * This is just for backward compatibility with the rest of the codebase (primarily API responses).
150 *
151 * @return array
152 */
153 protected function get_settings_for_default_section() {
154 return array(
155 array(
156 'type' => 'title',
157 // this is needed as <table> tag is generated by this element, even if it has no other content.
158 ),
159 array(
160 'type' => 'sectionend',
161 'id' => 'payment_gateways_options',
162 ),
163 );
164 }
165
166 /**
167 * Get the whitelist of sections to render using React.
168 *
169 * @return array List of section identifiers.
170 */
171 private function get_reactified_sections(): array {
172 if ( ! is_null( $this->reactified_sections_memo ) ) {
173 return $this->reactified_sections_memo;
174 }
175
176 // These sections are always rendered using React.
177 $reactified_sections = array(
178 self::MAIN_SECTION_NAME,
179 self::OFFLINE_SECTION_NAME,
180 );
181
182 // These sections are optional and can be modified by plugins or themes.
183 $optional_reactified_sections = array(
184 self::COD_SECTION_NAME,
185 self::BACS_SECTION_NAME,
186 self::CHEQUE_SECTION_NAME,
187 );
188
189 /**
190 * Modify the optional set of payments settings sections to be rendered using React.
191 *
192 * This filter allows plugins to add or remove optional sections (typically offline gateways)
193 * that should be rendered using React. Sections should be identified by their gateway IDs.
194 * Note: The main Payments page ("main") and the Offline overview ("offline") are always React-only
195 * and cannot be disabled via this filter.
196 *
197 * @since 9.3.0
198 *
199 * @param array $sections List of section identifiers to be rendered using React.
200 */
201 $optional_reactified_sections = apply_filters( 'experimental_woocommerce_admin_payment_reactify_render_sections', $optional_reactified_sections );
202 if ( empty( $optional_reactified_sections ) || ! is_array( $optional_reactified_sections ) ) {
203 // Sanity check: use empty array if the filter returns something unexpected.
204 $optional_reactified_sections = array();
205 } else {
206 // Enforce a list format and string-only values for section identifiers.
207 $optional_reactified_sections = array_values( array_filter( $optional_reactified_sections, 'is_string' ) );
208 }
209
210 $this->reactified_sections_memo = array_unique( array_merge( $reactified_sections, $optional_reactified_sections ) );
211
212 return $this->reactified_sections_memo;
213 }
214
215 /**
216 * Standardize the current section name.
217 *
218 * @param mixed $section The section name to standardize.
219 *
220 * @return string The standardized section name.
221 */
222 private function standardize_section_name( $section ): string {
223 $section = (string) $section;
224 // If the section is empty, we are on the main settings page/section. Use a standardized name.
225 if ( '' === $section ) {
226 return self::MAIN_SECTION_NAME;
227 }
228
229 return $section;
230 }
231
232 /**
233 * Check if a section is registered through the settings section registry.
234 *
235 * @param mixed $section Section id.
236 * @return bool
237 */
238 private function is_registered_settings_section( $section ): bool {
239 if ( '' === (string) $section ) {
240 return false;
241 }
242
243 $registry = $this->get_settings_section_registry();
244
245 return null !== $registry && null !== $registry->get_registered( self::TAB_NAME, (string) $section );
246 }
247
248 /**
249 * Render the React section.
250 *
251 * @param string $section The section to render.
252 */
253 private function render_react_section( string $section ) {
254 global $hide_save_button;
255 $hide_save_button = true;
256 echo '<div id="experimental_wc_settings_payments_' . esc_attr( $section ) . '"></div>';
257 }
258
259 /**
260 * Render the classic gateway settings page.
261 *
262 * @param array $payment_gateways The payment gateways.
263 * @param string $current_section The current section.
264 */
265 private function render_classic_gateway_settings_page( array $payment_gateways, string $current_section ) {
266 foreach ( $payment_gateways as $gateway ) {
267 if ( in_array( $current_section, array( $gateway->id, sanitize_title( get_class( $gateway ) ) ), true ) ) {
268 if ( isset( $_GET['toggle_enabled'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
269 $enabled = $gateway->get_option( 'enabled' );
270
271 if ( $enabled ) {
272 $gateway->settings['enabled'] = wc_string_to_bool( $enabled ) ? 'no' : 'yes';
273 }
274 }
275 $this->run_gateway_admin_options( $gateway );
276 break;
277 }
278 }
279 }
280
281 /**
282 * Run the 'admin_options' method on a given gateway.
283 *
284 * This method exists to help with unit testing.
285 *
286 * @param object $gateway The gateway object to run the method on.
287 */
288 protected function run_gateway_admin_options( $gateway ) {
289 $gateway->admin_options();
290 }
291
292 /**
293 * Get all sections for the current page.
294 *
295 * Reactified section pages won't have any sections.
296 * The rest of the settings pages will get the default/own section and those added via
297 * the `woocommerce_get_sections_checkout` filter.
298 *
299 * @return array The sections for this settings page.
300 */
301 public function get_sections() {
302 global $current_tab, $current_section;
303
304 // We only want to prevent sections on the main WooCommerce Payments settings page and Reactified sections.
305 if ( self::TAB_NAME === $current_tab && $this->should_render_react_section( $current_section ) ) {
306 return array();
307 }
308
309 return parent::get_sections();
310 }
311
312 /**
313 * Save settings.
314 */
315 public function save() {
316 global $current_section;
317
318 $standardized_section = $this->standardize_section_name( $current_section );
319
320 $wc_payment_gateways = WC_Payment_Gateways::instance();
321
322 $this->save_settings_for_current_section();
323
324 if ( self::MAIN_SECTION_NAME === $standardized_section ) {
325 // This makes sure 'gateway ordering' is saved.
326 $wc_payment_gateways->process_admin_options();
327 $wc_payment_gateways->init();
328 } else {
329 // This may be a gateway or some custom section.
330 foreach ( $wc_payment_gateways->payment_gateways() as $gateway ) {
331 // If the section is that of a gateway, we need to run the gateway actions and init.
332 if ( in_array( $standardized_section, array( $gateway->id, sanitize_title( get_class( $gateway ) ) ), true ) ) {
333 /**
334 * Fires update actions for payment gateways.
335 *
336 * @since 3.4.0
337 *
338 * @param int $gateway->id Gateway ID.
339 */
340 do_action( 'woocommerce_update_options_payment_gateways_' . $gateway->id );
341 $wc_payment_gateways->init();
342
343 // There is no need to run the action and gateways init again
344 // since we can't be on the section page of multiple gateways at once.
345 break;
346 }
347 }
348
349 $this->do_update_options_action();
350 }
351 }
352
353 /**
354 * Hide the help tabs.
355 */
356 public function hide_help_tabs() {
357 global $current_tab, $current_section;
358
359 $screen = get_current_screen();
360 if ( ! $screen instanceof WP_Screen || 'woocommerce_page_wc-settings' !== $screen->id ) {
361 return;
362 }
363
364 // We only want to hide the help tabs on the main WooCommerce Payments settings page and Reactified sections.
365 if ( self::TAB_NAME !== $current_tab ) {
366 return;
367 }
368 if ( ! $this->should_render_react_section( $current_section ) ) {
369 return;
370 }
371
372 $screen->remove_help_tabs();
373 }
374
375 /**
376 * Suppress WP admin notices on the WooCommerce Payments settings page.
377 */
378 public function suppress_admin_notices() {
379 global $wp_filter, $current_tab, $current_section;
380
381 $screen = get_current_screen();
382 if ( ! $screen instanceof WP_Screen || 'woocommerce_page_wc-settings' !== $screen->id ) {
383 return;
384 }
385
386 // We only want to suppress notices on the main WooCommerce Payments settings page and Reactified sections.
387 if ( self::TAB_NAME !== $current_tab ) {
388 return;
389 }
390 if ( ! $this->should_render_react_section( $current_section ) ) {
391 return;
392 }
393
394 // Generic admin notices are definitely not needed.
395 remove_all_actions( 'all_admin_notices' );
396
397 // WooCommerce uses the 'admin_notices' hook for its own notices.
398 // We will only allow WooCommerce core notices to be displayed.
399 $wp_admin_notices_hook = $wp_filter['admin_notices'] ?? null;
400 if ( ! $wp_admin_notices_hook || ! $wp_admin_notices_hook->has_filters() ) {
401 // Nothing to do if there are no actions hooked into `admin_notices`.
402 return;
403 }
404
405 $wc_admin_notices = WC_Admin_Notices::get_notices();
406 if ( empty( $wc_admin_notices ) ) {
407 // If there are no WooCommerce core notices, we can remove all actions hooked into `admin_notices`.
408 remove_all_actions( 'admin_notices' );
409 return;
410 }
411
412 // Go through the callbacks hooked into `admin_notices` and
413 // remove any that are NOT from the WooCommerce core (i.e. from the `WC_Admin_Notices` class).
414 foreach ( $wp_admin_notices_hook->callbacks as $priority => $callbacks ) {
415 if ( ! is_array( $callbacks ) ) {
416 continue;
417 }
418
419 foreach ( $callbacks as $callback ) {
420 // Ignore malformed callbacks.
421 if ( ! is_array( $callback ) ) {
422 continue;
423 }
424 // WooCommerce doesn't use closures to handle notices.
425 // WooCommerce core notices are handled by `WC_Admin_Notices` class methods.
426 // Remove plain functions or closures.
427 if ( ! is_array( $callback['function'] ) ) {
428 remove_action( 'admin_notices', $callback['function'], $priority );
429 continue;
430 }
431
432 $class_or_object = $callback['function'][0] ?? null;
433 // We need to allow Automattic\WooCommerce\Internal\Admin\Loader methods callbacks
434 // because they are used to wrap notices.
435 // @see Automattic\WooCommerce\Internal\Admin\Loader::inject_before_notices().
436 // @see Automattic\WooCommerce\Internal\Admin\Loader::inject_after_notices().
437 if (
438 (
439 // We have a class name.
440 is_string( $class_or_object ) &&
441 ! ( WC_Admin_Notices::class === $class_or_object || Loader::class === $class_or_object )
442 ) ||
443 (
444 // We have a class instance.
445 is_object( $class_or_object ) &&
446 ! ( $class_or_object instanceof WC_Admin_Notices || $class_or_object instanceof Loader )
447 )
448 ) {
449 remove_action( 'admin_notices', $callback['function'], $priority );
450 }
451 }
452 }
453 }
454
455 /**
456 * Suppress the store-alerts WCAdmin feature on the WooCommerce Payments settings page and Reactified sections.
457 *
458 * @param mixed $features The WCAdmin features list.
459 *
460 * @return mixed The modified features list.
461 */
462 public function suppress_store_alerts( $features ) {
463 global $current_tab, $current_section;
464
465 $feature_name = 'store-alerts';
466
467 if ( is_array( $features ) &&
468 in_array( $feature_name, $features, true ) &&
469 self::TAB_NAME === $current_tab &&
470 $this->should_render_react_section( $current_section ) ) {
471
472 unset( $features[ array_search( $feature_name, $features, true ) ] );
473 }
474
475 return $features;
476 }
477 }
478
479 return new WC_Settings_Payment_Gateways();
480