Skip to content
Open
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
ed17145
Feature: Save google profile picture during account creation
mi5t4n May 5, 2025
573693b
fix: phpcs errors
mi5t4n May 5, 2025
cdb6f84
Merge branch 'develop' into feature/save-google-profile-picture-durin…
mi5t4n May 15, 2025
63a2c9b
Check for wp_filesystem as well
mi5t4n May 16, 2025
86f6ffc
Merge branch 'develop' into feature/save-google-profile-picture-durin…
mchirag2002 Oct 30, 2025
489c68b
fix: typo
mi5t4n Dec 3, 2025
0479da9
Remove leading forward slash
mi5t4n Dec 3, 2025
7bc0631
fix: typo
mi5t4n Dec 3, 2025
f01033a
refactor
mi5t4n Dec 3, 2025
c6659bb
added error handling
mi5t4n Dec 3, 2025
877990d
handle empty user picture field from the response
mi5t4n Dec 3, 2025
68cc83c
Passing 0 as post id to media_handle_sideload
mi5t4n Dec 3, 2025
15820bd
refactor
mi5t4n Dec 3, 2025
62c8c18
handle error when moving file fails
mi5t4n Dec 3, 2025
55118bc
handle error when profile picture downloading fails
mi5t4n Dec 3, 2025
4d93934
Merge remote-tracking branch 'refs/remotes/origin/feature/save-google…
mi5t4n Dec 3, 2025
d0e204b
fix typo
mi5t4n Dec 3, 2025
d8d9d61
fix typo
mi5t4n Dec 3, 2025
daec6ee
Added since doc
mi5t4n Dec 3, 2025
5b1dedb
update the save user profile picture filter name
mi5t4n Dec 3, 2025
23098e0
created user profile edit template
mi5t4n Dec 4, 2025
17dbdc3
fix: google user profile display on user edit page
mi5t4n Dec 4, 2025
1a367d7
Conditionally render the google avatar
mi5t4n Dec 4, 2025
f8679f5
Save the avatar source user profile options
mi5t4n Dec 4, 2025
c36f21e
handle default google avatar source
mi5t4n Dec 4, 2025
f8ac4e9
Set avatar source as google for the first login with google
mi5t4n Dec 4, 2025
64e44b3
refactor
mi5t4n Dec 4, 2025
f6aa442
update the google profile picture if it's been changed
mi5t4n Dec 9, 2025
0d17dba
update the code such that the profile picture is not syned
mi5t4n Dec 10, 2025
458e84c
show user can set the google profile picture notice
mi5t4n Dec 10, 2025
df906b2
fix: typo
mi5t4n Dec 10, 2025
bcf6db9
do not display notice if google picture doesn't exists
mi5t4n Dec 10, 2025
1e6f6f7
fix: phpcs errors
mi5t4n Dec 10, 2025
964f6cf
Apply suggestions from code review
mi5t4n Dec 10, 2025
2f04b1f
Update src/Modules/UserProfile.php
mi5t4n Dec 10, 2025
b651a08
Update src/Modules/UserProfile.php
mi5t4n Dec 10, 2025
9d4693d
fix: prefix
mi5t4n Dec 10, 2025
d53d4f8
fix: phpcs errors
mi5t4n Dec 10, 2025
f94397e
fix: phpcs errors
mi5t4n Dec 10, 2025
268d19b
Update src/Utils/Authenticator.php
mi5t4n Dec 10, 2025
c1b6635
Update src/Modules/UserProfile.php
mi5t4n Dec 10, 2025
9a5a33b
Update src/Modules/UserProfile.php
mi5t4n Dec 10, 2025
e1f2707
Update src/Modules/UserProfile.php
mi5t4n Dec 10, 2025
3f975d5
fix: pcp errors
mi5t4n Dec 11, 2025
596427b
added more parameters to the filter
mi5t4n Dec 11, 2025
f45b753
updated the readme.md with new filters
mi5t4n Dec 11, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 49 additions & 0 deletions src/Plugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,8 @@ public function run(): void {
add_action( 'init', [ $this, 'load_translations' ] );

add_action( 'plugin_action_links_' . plugin_basename( $this->path ) . '/login-with-google.php', [ $this, 'add_plugin_action_links' ] );

add_action( 'get_avatar_url', [ $this, 'return_avatar_url' ], 10, 3 );
}

/**
Expand Down Expand Up @@ -162,4 +164,51 @@ public function add_plugin_action_links( $actions ) {

return array_merge( $new_actions, $actions );
}

/**
* Return the stored profile picture during the account creation.
*
* @param string $url The URL of the avatar.
* @param mixed $id_or_email The avatar to retrieve. Accepts a user ID, Gravatar SHA-256 or MD5 hash, user email, WP_User object, WP_Post object, or WP_Comment object.
* @param array $args Arguments passed to get_avatar_data() , after processing.
*
* @return string The URL of the avatar.
*/
public function return_avatar_url( $url, $id_or_email, $args ): string {
/**
* Filter to bypass the use of saved profile picture for avatar.
*
* @since n.e.x.t
*
* @param boolean $use_saved_profile_picture_for_avatar Whether to bypass the use of the saved profile picture for avatar or not.
Comment thread
mi5t4n marked this conversation as resolved.
Outdated
*/
$use_avatar_url = apply_filters( 'rtcamp.google_use_saved_profile_picture_for_avatar', true );

if ( ! $use_avatar_url ) {
return $url;
}

$wp_user = null;
if ( is_int( $id_or_email ) ) {
$wp_user = get_user_by( 'id', $id_or_email );
} elseif ( is_string( $id_or_email ) && is_email( $id_or_email ) ) {
$wp_user = get_user_by( 'email', $id_or_email );
Comment thread
mi5t4n marked this conversation as resolved.
Outdated
}
Comment thread
mi5t4n marked this conversation as resolved.
Outdated

if ( $wp_user ) {
$width = isset( $args['width'] ) ? absint( $args['width'] ) : 64;
$height = isset( $args['height'] ) ? absint( $args['height'] ) : 64;

$profile_picture_id = get_user_meta( $wp_user->ID, 'rtlwg_profile_picture_id', true );

if ( ! empty( $profile_picture_id ) ) {
$profile_picture_url = wp_get_attachment_image_url( $profile_picture_id, [ $width, $height ] );
if ( $profile_picture_url ) {
$url = $profile_picture_url;
}
}
}

return $url;
}
Comment thread
mi5t4n marked this conversation as resolved.
Outdated
}
79 changes: 79 additions & 0 deletions src/Utils/Authenticator.php
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,21 @@ public function register( stdClass $user ): ?WP_User {
]
);

/**
* Filter to bypass the profile picture saving process.
*
* @since n.e.x.t
*
* @param boolean $save Whether to save profile picture or not.
* @param int $uid WP User ID.
Comment thread
mi5t4n marked this conversation as resolved.
Outdated
* @param \stdClass User object returned by Google.
Comment thread
mi5t4n marked this conversation as resolved.
Outdated
*/
$save_profile_picture = apply_filters( 'rtcamp.google_save_user_profile_picture', true, $uid, $user );

if ( $save_profile_picture ) {
$this->save_user_profile_picture( $uid, $user );
}
Comment thread
mi5t4n marked this conversation as resolved.
Outdated

/**
* Fires once the user has been registered successfully.
*/
Expand Down Expand Up @@ -179,4 +194,68 @@ private function can_register_with_email( string $email ): bool {

return in_array( $email_parts[1], $whitelisted_domains, true );
}

/**
* Save user profile picture.
*
* @param int $user_id WP User ID.
* @param \stdClass $user User object returned by google.
Comment thread
mi5t4n marked this conversation as resolved.
Outdated
Comment thread
mi5t4n marked this conversation as resolved.
Outdated
* @return void
*/
private function save_user_profile_picture( $user_id, $user ): void {
global $wp_filesystem;

if ( is_null( $wp_filesystem ) ) {
require_once ABSPATH . 'wp-admin/includes/file.php';
WP_Filesystem();
}

if ( ! function_exists( 'media_handle_sideload' ) ) {
require_once ABSPATH . 'wp-admin/includes/media.php';
require_once ABSPATH . 'wp-admin/includes/file.php';
require_once ABSPATH . 'wp-admin/includes/image.php';
}

if ( ! isset( $user->picture ) || empty( $user->picture ) ) {
return;
}

// Using larger image size. By default, profile picture has 96 width size with cropped.
Comment thread
mi5t4n marked this conversation as resolved.
$profile_picture_url = str_replace( '=s96-c', '', $user->picture );

Comment thread
mi5t4n marked this conversation as resolved.
$profile_picture_filename = download_url( $profile_picture_url );
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we add a check for WPVIP? and if the site is hosted on WPVIP we directly use wpcom_vip_download_image() this function.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@SH4LIN Yes, it can be a bit unclear—I’ll look into it further to make it more straightforward. As for re-syncing the image at each login, should we also extend this to include the First Name and Last Name, since those fields can also be updated?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@SH4LIN Regarding vip check, that is a good catch. I will promptly implement this.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we also extend this to include the First Name and Last Name, since those fields can also be updated?

In WordPress, we have the option to update the first name and last name. So, if they want to customize it, they can do so from the settings. However, there is no option in the WordPress dashboard to change the image.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we add a check for WPVIP? and if the site is hosted on WPVIP we directly use wpcom_vip_download_image() this function.

I tried to use this function, it seems it won't work in our scenario. I got the following error while trying to use it .
2025-05-15_15-38

The function was expecting a POST request, but Google calls the redirect URL using the GET method instead. We could try to change the global variables to make it work, but that would be a hacky solution. So, I decided to remove the function for now.


Comment thread
mi5t4n marked this conversation as resolved.
Comment thread
mi5t4n marked this conversation as resolved.
if ( str_ends_with( $profile_picture_filename, '.tmp' ) && $wp_filesystem ) {
$profile_picture_mime_type = wp_get_image_mime( $profile_picture_filename );

Comment thread
mi5t4n marked this conversation as resolved.
$profile_picture_extension = 'jpg'; // Default extension.
Comment thread
mi5t4n marked this conversation as resolved.
Outdated
$mime_types = wp_get_mime_types();
foreach ( $mime_types as $ext => $mime_type ) {
if ( $profile_picture_mime_type === $mime_type ) {
$profile_picture_extension = current( explode( '|', $ext ) );
Comment thread
mi5t4n marked this conversation as resolved.
break;
}
}
Comment thread
mi5t4n marked this conversation as resolved.

$new_profile_picture_filename = str_replace( '.tmp', ".{$profile_picture_extension}", $profile_picture_filename );
$wp_filesystem->move( $profile_picture_filename, $new_profile_picture_filename, true );

Comment thread
mi5t4n marked this conversation as resolved.
Outdated
$profile_picture_filename = $new_profile_picture_filename;
}

$file_array = array(
'name' => basename( $profile_picture_filename ),
'tmp_name' => $profile_picture_filename,
);

$attachment_id = media_handle_sideload( $file_array );
Comment thread
mi5t4n marked this conversation as resolved.
Outdated

Comment thread
mi5t4n marked this conversation as resolved.
Outdated
if ( is_wp_error( $attachment_id ) ) {
// Cleanup temporary file.
$wp_filesystem->delete( $profile_picture_filename );
return;
}

update_user_meta( $user_id, 'rtlwg_profile_picture_id', $attachment_id );
Comment thread
mi5t4n marked this conversation as resolved.
Outdated
}
Comment thread
mi5t4n marked this conversation as resolved.
Comment thread
mi5t4n marked this conversation as resolved.
}