authorizer icon indicating copy to clipboard operation
authorizer copied to clipboard

Sync User Profile Photo

Open nyulawbrian opened this issue 3 years ago • 1 comments

This is a feature request to add support for pulling the user's photo for their WP profile. For example, in an LDAP connection to Microsoft Active Directory, this would be the thumbnailPhoto attribute (byte encoded). The string would need to be converted to an image file and set as the user's profile photo. This would need to be updated upon login, same as first and last name.

Thanks so much!

nyulawbrian avatar Feb 11 '23 03:02 nyulawbrian

By default WordPress uses gravatar for profile photos so there's not a built-in way of editing profile images. That said, you should be able to get this behavior using a few filters:

Tell Authorizer to fetch the thumbnailPhoto attribute:

add_filter( 'authorizer_additional_ldap_attributes_to_retrieve', function ( $attributes ) {
	$attributes[] = 'thumbnailPhoto';

	return $attributes;
} );

Upload that photo to wp-content/uploads/ldap/01/profile-photo-{username}.jpg on login:

add_filter( 'authorizer_custom_role', function ( $default_role, $user_data ) {
	if ( ! empty( $user_data['ldap_attributes'][ 0 ]['thumbnailphoto'][ 0 ] ) ) {
		$jpeg_data      = $user_data['ldap_attributes'][ 0 ]['thumbnailphoto'][ 0 ];
		$filename       = 'profile-photo-' . $user_data['username'] . '.jpg';
		$uploads_subdir = 'ldap/01';
		$uploads_dir    = wp_upload_dir();
		$full_path      = $uploads_dir['basedir'] . '/' . $uploads_subdir . '/' . $filename;
		if ( file_exists( $full_path ) ) {
			wp_delete_file( $full_path );
		}
		$file = wp_upload_bits( $filename, null, $jpeg_data, $uploads_subdir );
	}

	return $default_role;
}, 10, 2 );

Override the gravatar with the custom photo (if it exists):

add_filter( 'pre_get_avatar_data', function ( $args, $id_or_email ) {
	// Process the user identifier.
	$user = false;
	if ( is_numeric( $id_or_email ) ) {
		$user = get_user_by( 'id', absint( $id_or_email ) );
	} elseif ( is_string( $id_or_email ) ) {
		if ( ! strpos( $id_or_email, '@md5.gravatar.com' ) ) {
			$user = get_user_by( 'email', $id_or_email );
		}
	} elseif ( $id_or_email instanceof WP_User ) {
		// User object.
		$user = $id_or_email;
	} elseif ( $id_or_email instanceof WP_Post ) {
		// Post object.
		$user = get_user_by( 'id', (int) $id_or_email->post_author );
	} elseif ( $id_or_email instanceof WP_Comment && is_avatar_comment_type( get_comment_type( $id_or_email ) ) ) {
		if ( ! empty( $id_or_email->user_id ) ) {
			$user = get_user_by( 'id', (int) $id_or_email->user_id );
		}
		if ( ( ! $user || is_wp_error( $user ) ) && ! empty( $id_or_email->comment_author_email ) ) {
			$user = get_user_by( 'email', $id_or_email->comment_author_email );
		}
	}

	if ( ! empty( $user->user_login ) ) {
		$filename       = 'profile-photo-' . $user->user_login . '.jpg';
		$uploads_subdir = 'ldap/01';
		$uploads_dir    = wp_upload_dir();
		$full_path      = $uploads_dir['basedir'] . '/' . $uploads_subdir . '/' . $filename;
		$full_url       = $uploads_dir['baseurl'] . '/' . $uploads_subdir . '/' . $filename;
		if ( file_exists( $full_path ) ) {
			$args['url'] = $full_url;
			$image_size = getimagesize( $full_path );
			// If not 1:1 aspect ratio, update width/height to prevent stretching.
			if ( $image_size[ 1 ] > $image_size[ 0 ] ) {
				$args['height'] = $args['size'];
				$args['width']  = $args['size'] * $image_size[ 0 ] / $image_size[ 1 ];
			} else {
				$args['height'] = $args['size'] * $image_size[ 1 ] / $image_size[ 0 ];
				$args['width']  = $args['size'];
			}
		}
	}

	return $args;
}, 10, 2 );

I tested that on OpenLDAP which uses jpegPhoto attribute and it worked. There may be a few differences for AD, you might have to inspect some of that data.

figureone avatar Mar 01 '23 23:03 figureone