PluginProbe ʕ •ᴥ•ʔ
WP 2FA – Two-factor authentication for WordPress / 1.6.0
WP 2FA – Two-factor authentication for WordPress v1.6.0
4.0.0 1.7.1 2.0.0 2.0.1 2.1.0 2.2.0 2.2.1 2.3.0 2.4.0 2.4.1 2.4.2 2.5.0 2.6.0 2.6.1 2.6.2 2.6.3 2.6.4 2.7.0 2.8.0 2.9.0 2.9.1 2.9.2 2.9.3 3.0.0 3.0.1 3.1.0 3.1.1 3.1.1.2 trunk 1.2.0 1.3.0 1.4.0 1.4.1 1.4.2 1.5.0 1.5.1 1.5.2 1.6.0 1.6.1 1.6.2 1.7.0
wp-2fa / includes / functions / core.php
wp-2fa / includes / functions Last commit date
core.php 5 years ago login-header.php 6 years ago
core.php
328 lines
1 <?php // phpcs:ignore
2
3 /**
4 * Core plugin functionality.
5 *
6 * @package WP2FA
7 */
8
9 namespace WP2FA\Core;
10
11 use \WP2FA\Admin\SettingsPage as SettingsPage;
12 use \WP2FA\Utils\UserUtils;
13
14 /**
15 * Default setup routine
16 *
17 * @return void
18 */
19 function setup() {
20 $n = function( $function ) {
21 return __NAMESPACE__ . "\\$function";
22 };
23
24 add_action( 'init', $n( 'i18n' ) );
25 add_action( 'init', $n( 'init' ) );
26 add_action( 'admin_enqueue_scripts', $n( 'admin_scripts' ) );
27 add_action( 'admin_enqueue_scripts', $n( 'admin_styles' ) );
28
29 // Hook to allow async or defer on asset loading.
30 add_filter( 'script_loader_tag', $n( 'script_loader_tag' ), 10, 2 );
31
32 do_action( 'wp_2fa_loaded' );
33 }
34
35 /**
36 * Registers the default textdomain.
37 *
38 * @return void
39 */
40 function i18n() {
41 $locale = apply_filters( 'plugin_locale', get_locale(), 'wp-2fa' );
42 load_textdomain( 'wp-2fa', WP_LANG_DIR . '/wp-2fa/wp-2fa-' . $locale . '.mo' );
43 load_plugin_textdomain( 'wp-2fa', false, plugin_basename( WP_2FA_PATH ) . '/languages/' );
44 }
45
46 /**
47 * Initializes the plugin and fires an action other plugins can hook into.
48 *
49 * @return void
50 */
51 function init() {
52 do_action( 'wp_2fa_init' );
53 }
54
55 /**
56 * Activate the plugin
57 *
58 * @return void
59 */
60 function activate() {
61 // First load the init scripts in case any rewrite functionality is being loaded.
62 init();
63 flush_rewrite_rules();
64
65 // Check if the user is allowed to manage options for the site.
66 if ( current_user_can( 'manage_options' ) ) {
67 // Add an option to let our plugin know this user has not been through the setup wizard.
68 add_option( 'wp_2fa_redirect_on_activate', true );
69 }
70
71 // Add plugin version to wp_options.
72 if ( \WP2FA\WP2FA::is_this_multisite() ) {
73 add_network_option( null, 'wp_2fa_plugin_version', WP_2FA_VERSION );
74 } else {
75 add_option( 'wp_2fa_plugin_version', WP_2FA_VERSION );
76 }
77 }
78
79 /**
80 * Deactivate the plugin
81 *
82 * Uninstall routines should be in uninstall.php
83 *
84 * @return void
85 */
86 function deactivate() {
87
88 }
89
90 /**
91 * Uninstall the plugin
92 *
93 * @return void
94 */
95 function uninstall() {
96 if ( ! empty( \WP2FA\WP2FA::get_wp2fa_setting( 'delete_data_upon_uninstall' ) ) ) {
97 // Delete settings from wp_options.
98 if ( \WP2FA\WP2FA::is_this_multisite() ) {
99 $network_id = get_current_network_id();
100 global $wpdb;
101 $wpdb->query(
102 $wpdb->prepare(
103 "
104 DELETE FROM $wpdb->sitemeta
105 WHERE meta_key LIKE %s
106 AND site_id = %d
107 ",
108 [
109 'wp_2fa_%',
110 $network_id
111 ]
112 )
113 );
114 } else {
115 global $wpdb;
116 $wpdb->query(
117 $wpdb->prepare(
118 "
119 DELETE FROM $wpdb->options
120 WHERE option_name LIKE %s
121 ",
122 [
123 'wp_2fa_%',
124 ]
125 )
126 );
127 }
128
129 $users_args = array(
130 'fields' => array( 'ID' ),
131 );
132 if ( \WP2FA\WP2FA::is_this_multisite() ) {
133 $users_args['blog_id'] = 0;
134 }
135 $settings = new SettingsPage();
136 $users = UserUtils::get_all_user_ids( 'query', $users_args );
137 if ( ! is_array( $users ) ) {
138 $users = explode( ',', $users );
139 }
140
141 foreach ( $users as $user_id ) {
142 global $wpdb;
143 $wpdb->query(
144 $wpdb->prepare(
145 "
146 DELETE FROM $wpdb->usermeta
147 WHERE user_id = %d
148 AND meta_key LIKE %s
149 ",
150 [
151 $user_id,
152 'wp_2fa_%'
153 ]
154 )
155 );
156 }
157 }
158 }
159
160 /**
161 * The list of knows contexts for enqueuing scripts/styles.
162 *
163 * @return array
164 */
165 function get_enqueue_contexts() {
166 return array( 'admin', 'frontend', 'shared' );
167 }
168
169 /**
170 * Generate an URL to a script, taking into account whether SCRIPT_DEBUG is enabled.
171 *
172 * @param string $script Script file name (no .js extension).
173 * @param string $context Context for the script ('admin', 'frontend', or 'shared').
174 *
175 * @return string|WP_Error URL
176 */
177 function script_url( $script, $context ) {
178
179 if ( ! in_array( $context, get_enqueue_contexts(), true ) ) {
180 return new \WP_Error( 'invalid_enqueue_context', 'Invalid $context specified in WP2FA script loader.' );
181 }
182
183 return WP_2FA_URL . "dist/js/${script}.js";
184
185 }
186
187 /**
188 * Generate an URL to a stylesheet, taking into account whether SCRIPT_DEBUG is enabled.
189 *
190 * @param string $stylesheet Stylesheet file name (no .css extension).
191 * @param string $context Context for the script ('admin', 'frontend', or 'shared').
192 *
193 * @return string URL
194 */
195 function style_url( $stylesheet, $context ) {
196
197 if ( ! in_array( $context, get_enqueue_contexts(), true ) ) {
198 return new \WP_Error( 'invalid_enqueue_context', 'Invalid $context specified in WP2FA stylesheet loader.' );
199 }
200
201 return WP_2FA_URL . "dist/css/${stylesheet}.css";
202
203 }
204
205 /**
206 * Enqueue scripts for admin.
207 *
208 * @return void
209 */
210 function admin_scripts() {
211
212 wp_enqueue_script(
213 'wp_2fa_admin',
214 script_url( 'admin', 'admin' ),
215 array( 'jquery-ui-widget', 'jquery-ui-core', 'jquery-ui-autocomplete', 'wp_2fa_micro_modals', 'select2' ),
216 WP_2FA_VERSION,
217 true
218 );
219
220 wp_enqueue_script(
221 'wp_2fa_micro_modals',
222 script_url( 'micro-modal', 'admin' ),
223 array(),
224 WP_2FA_VERSION,
225 true
226 );
227
228 enqueueSelect2Scripts();
229
230 if (\WP2FA\WP2FA::is_this_multisite()) {
231 enqueueMultiSelectScripts();
232 }
233
234 // Data array.
235 $data_array = array(
236 'ajaxURL' => admin_url( 'admin-ajax.php' ),
237 'roles' => \WP2FA\WP2FA::wp_2fa_get_roles(),
238 'nonce' => wp_create_nonce( 'wp-2fa-settings-nonce' ),
239 'codeValidatedHeading' => esc_html__( 'Congratulations', 'wp-2fa' ),
240 'codeValidatedText' => esc_html__( 'Your account just got more secure', 'wp-2fa' ),
241 'codeValidatedButton' => esc_html__( 'Close Wizard & Refresh', 'wp-2fa' ),
242 'processingText' => esc_html__( 'Processing Update', 'wp-2fa' ),
243 'email_sent_success' => esc_html__( 'Email successfully sent', 'wp-2fa' ),
244 'email_sent_failure' => esc_html__( 'Email delivery failed', 'wp-2fa' )
245 );
246 wp_localize_script( 'wp_2fa_admin', 'wp2faData', $data_array );
247
248 $data_array = array(
249 'ajaxURL' => admin_url( 'admin-ajax.php' ),
250 'nonce' => wp_create_nonce( 'wp2fa-verify-wizard-page' ),
251 'codesPreamble' => esc_html__( 'These are the 2FA backup codes for the user', 'wp-2fa' ),
252 'readyText' => esc_html__( 'I\'m ready', 'wp-2fa' ),
253 'codeReSentText' => esc_html__( 'New code sent', 'wp-2fa' ),
254 );
255 wp_localize_script( 'wp_2fa_admin', 'wp2faWizardData', $data_array );
256
257 }
258
259 /**
260 * Enqueue multi select for multinetwork WP
261 *
262 * @return void
263 */
264 function enqueueMultiSelectScripts() {
265
266 wp_enqueue_script( 'multi-site-select', script_url( 'multi-site-select', 'admin' ), [ 'jquery', 'select2' ] );
267 }
268
269 /**
270 * Enqueue Select2 jQuery library
271 *
272 * @return void
273 */
274 function enqueueSelect2Scripts() {
275 wp_enqueue_style( 'select2', 'https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.3/css/select2.min.css' );
276 wp_enqueue_script( 'select2', 'https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.3/js/select2.min.js', [ 'jquery' ] );
277 }
278
279 /**
280 * Enqueue styles for admin.
281 *
282 * @return void
283 */
284 function admin_styles() {
285
286 wp_enqueue_style(
287 'wp_2fa_admin',
288 style_url( 'admin-style', 'admin' ),
289 array(),
290 WP_2FA_VERSION
291 );
292
293 }
294
295 /**
296 * Add async/defer attributes to enqueued scripts that have the specified script_execution flag.
297 *
298 * @link https://core.trac.wordpress.org/ticket/12009
299 * @param string $tag The script tag.
300 * @param string $handle The script handle.
301 * @return string
302 */
303 function script_loader_tag( $tag, $handle ) {
304 $script_execution = wp_scripts()->get_data( $handle, 'script_execution' );
305
306 if ( ! $script_execution ) {
307 return $tag;
308 }
309
310 if ( 'async' !== $script_execution && 'defer' !== $script_execution ) {
311 return $tag;
312 }
313
314 // Abort adding async/defer for scripts that have this script as a dependency. _doing_it_wrong()?
315 foreach ( wp_scripts()->registered as $script ) {
316 if ( in_array( $handle, $script->deps, true ) ) {
317 return $tag;
318 }
319 }
320
321 // Add the attribute if it hasn't already been added.
322 if ( ! preg_match( ":\s$script_execution(=|>|\s):", $tag ) ) {
323 $tag = preg_replace( ':(?=></script>):', " $script_execution", $tag, 1 );
324 }
325
326 return $tag;
327 }
328