Skip to content

Commit a24762e

Browse files
committed
Adding support for pre-populating emails
1 parent 9c3a65f commit a24762e

File tree

2 files changed

+506
-0
lines changed

2 files changed

+506
-0
lines changed

projects/plugins/wpcomsh/connection/class-protected-owner-error-handler.php

Lines changed: 218 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,13 @@
1515
*
1616
* The class automatically clears errors when the required local account is created,
1717
* allowing external healing code to establish the proper Jetpack connection.
18+
*
19+
* Additionally, this class provides email prepopulation functionality for the WordPress
20+
* user creation form when creating missing protected owner accounts. It overrides the
21+
* default User_Admin class behavior to ensure the WP.com invitation checkbox is not
22+
* pre-checked when creating protected owner accounts.
23+
*
24+
* @since $$next-version$$
1825
*/
1926
class Protected_Owner_Error_Handler {
2027

@@ -42,6 +49,11 @@ private function __construct() {
4249
// Clear errors when the missing user is created or updated (allows external healing code to work)
4350
add_action( 'user_register', array( $this, 'check_and_clear_error_for_user' ) );
4451
add_action( 'profile_update', array( $this, 'check_and_clear_error_for_user' ) );
52+
53+
// Add form prepopulation functionality - run before User_Admin class (priority 0)
54+
add_action( 'user_new_form', array( $this, 'override_wpcom_invite_checkbox' ), 0 );
55+
add_action( 'user_new_form', array( $this, 'prepopulate_user_form' ) );
56+
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_form_scripts' ) );
4557
}
4658

4759
/**
@@ -184,4 +196,210 @@ public function check_and_clear_error_for_user( $user_id ) {
184196
$this->delete_error();
185197
}
186198
}
199+
200+
/**
201+
* Add form prepopulation functionality
202+
*/
203+
public function prepopulate_user_form() {
204+
$email = $this->get_prepopulation_email();
205+
206+
if ( ! $email ) {
207+
return;
208+
}
209+
210+
// Output hidden field and JavaScript to prepopulate the form
211+
?>
212+
<tr class="form-field form-required">
213+
<th scope="row">
214+
<label for="jetpack_protected_owner_notice">
215+
<?php esc_html_e( 'Jetpack Connection Owner', 'wpcomsh' ); ?>
216+
</label>
217+
</th>
218+
<td>
219+
<div class="notice notice-info inline">
220+
<p>
221+
<?php
222+
printf(
223+
/* translators: %s is the email address */
224+
esc_html__( 'Creating account for Jetpack connection owner: %s', 'wpcomsh' ),
225+
'<strong>' . esc_html( $email ) . '</strong>'
226+
);
227+
?>
228+
</p>
229+
</div>
230+
<input type="hidden" id="jetpack_prepopulate_email" value="<?php echo esc_attr( $email ); ?>" />
231+
<input type="hidden" name="jetpack_create_missing_account" value="1" />
232+
</td>
233+
</tr>
234+
235+
<script type="text/javascript">
236+
(function($) {
237+
$(document).ready(function() {
238+
// Prepopulate the email field only
239+
var email = $('#jetpack_prepopulate_email').val();
240+
if (email) {
241+
$('#email').val(email);
242+
243+
// Ensure invite checkbox is unchecked for protected owner creation
244+
$('#invite_user_wpcom').prop('checked', false);
245+
}
246+
});
247+
})(jQuery);
248+
</script>
249+
<?php
250+
}
251+
252+
/**
253+
* Enqueue form scripts
254+
*
255+
* @param string $hook The current admin page hook.
256+
*/
257+
public function enqueue_form_scripts( $hook ) {
258+
// Only load on user-new.php page
259+
if ( 'user-new.php' !== $hook ) {
260+
return;
261+
}
262+
263+
// Only enqueue if we have an email to prepopulate
264+
$email = $this->get_prepopulation_email();
265+
if ( ! $email ) {
266+
return;
267+
}
268+
269+
// Enqueue jQuery (should already be available in admin)
270+
wp_enqueue_script( 'jquery' );
271+
}
272+
273+
/**
274+
* Get the email address for prepopulation from various sources
275+
*
276+
* @return string|false Email address if available, false otherwise
277+
*/
278+
private function get_prepopulation_email() {
279+
// Check URL parameters first (from React component)
280+
// phpcs:disable WordPress.Security.NonceVerification.Recommended -- URL parameters are read-only for prepopulation, no sensitive actions performed
281+
if ( isset( $_GET['jetpack_protected_owner_email'] ) &&
282+
isset( $_GET['jetpack_create_missing_account'] ) ) {
283+
$email = sanitize_email( wp_unslash( $_GET['jetpack_protected_owner_email'] ) );
284+
if ( is_email( $email ) ) { // phpcs:ignore WordPress.PHP.StrictInArray.Missing -- This is a valid use of is_email
285+
return $email;
286+
}
287+
}
288+
// phpcs:enable WordPress.Security.NonceVerification.Recommended
289+
290+
// Check stored error data as fallback
291+
$raw_error = $this->get_active_error();
292+
if ( $raw_error && isset( $raw_error['email'] ) && is_email( $raw_error['email'] ) ) {
293+
return $raw_error['email'];
294+
}
295+
296+
return false;
297+
}
298+
299+
/**
300+
* Override the WP.com invite checkbox behavior when creating a missing protected user
301+
*
302+
* This method runs before the User_Admin class hook (priority 0) to override
303+
* the default checkbox behavior when we're creating a missing protected owner account.
304+
*
305+
* @since $$next-version$$
306+
*
307+
* @param string $type The type of new user form the hook follows.
308+
*/
309+
public function override_wpcom_invite_checkbox( $type ) {
310+
// Only override for add-new-user form type
311+
if ( 'add-new-user' !== $type ) {
312+
return;
313+
}
314+
315+
// Check if we're in a protected owner creation context
316+
$email = $this->get_prepopulation_email();
317+
if ( ! $email ) {
318+
return; // Not a protected owner creation, let the default behavior proceed
319+
}
320+
321+
// Remove the User_Admin hook that would pre-check the invitation checkbox
322+
$this->remove_user_admin_invite_checkbox_hook();
323+
324+
// Add our own version that ensures the checkbox is unchecked
325+
add_action( 'user_new_form', array( $this, 'render_unchecked_wpcom_invite_checkbox' ), 1 );
326+
}
327+
328+
/**
329+
* Remove the User_Admin class hook that renders the invite checkbox
330+
*
331+
* This is necessary to prevent the default pre-checked behavior for protected owner creation.
332+
*
333+
* @since $$next-version$$
334+
*/
335+
private function remove_user_admin_invite_checkbox_hook() {
336+
// Get all hooked functions for the user_new_form action
337+
global $wp_filter;
338+
339+
if ( ! isset( $wp_filter['user_new_form'] ) ) {
340+
return;
341+
}
342+
343+
// Look for the User_Admin class hook at priority 1
344+
if ( isset( $wp_filter['user_new_form']->callbacks[1] ) ) {
345+
foreach ( $wp_filter['user_new_form']->callbacks[1] as $callback ) {
346+
// Check if this is the User_Admin render_wpcom_invite_checkbox method
347+
if (
348+
is_array( $callback['function'] ) &&
349+
is_object( $callback['function'][0] ) &&
350+
get_class( $callback['function'][0] ) === 'Automattic\Jetpack\Connection\SSO\User_Admin' &&
351+
$callback['function'][1] === 'render_wpcom_invite_checkbox'
352+
) {
353+
// Remove the hook
354+
remove_action( 'user_new_form', $callback['function'], 1 );
355+
break;
356+
}
357+
}
358+
}
359+
}
360+
361+
/**
362+
* Render the WP.com invite checkbox in an unchecked state for protected owner creation
363+
*
364+
* This replaces the User_Admin method to ensure the checkbox is not pre-checked
365+
* when creating a missing protected owner account.
366+
*
367+
* @since $$next-version$$
368+
*
369+
* @param string $type The type of new user form the hook follows.
370+
*/
371+
public function render_unchecked_wpcom_invite_checkbox( $type ) {
372+
if ( 'add-new-user' !== $type ) {
373+
return;
374+
}
375+
376+
?>
377+
<table class="form-table">
378+
<tr class="form-field">
379+
<th scope="row">
380+
<label for="invite_user_wpcom"><?php esc_html_e( 'Invite user', 'wpcomsh' ); ?></label>
381+
</th>
382+
<td>
383+
<fieldset>
384+
<legend class="screen-reader-text">
385+
<span><?php esc_html_e( 'Invite user', 'wpcomsh' ); ?></span>
386+
</legend>
387+
<label for="invite_user_wpcom">
388+
<input
389+
name="invite_user_wpcom"
390+
type="checkbox"
391+
id="invite_user_wpcom"
392+
value="1"
393+
>
394+
<?php esc_html_e( 'Invite user to WordPress.com', 'wpcomsh' ); ?>
395+
</label>
396+
<p class="description">
397+
<?php esc_html_e( 'Note: This user is being created to resolve a Jetpack connection issue. You may choose whether to invite them to WordPress.com.', 'wpcomsh' ); ?>
398+
</p>
399+
</fieldset>
400+
</td>
401+
</tr>
402+
</table>
403+
<?php
404+
}
187405
}

0 commit comments

Comments
 (0)