Plugin Directory

Changeset 3722272


Ignore:
Timestamp:
10/01/2026 01:57:50 AM (3 weeks ago)
Author:
webguyio
Message:

Ver 0.3

Location:
local-profile-pics/trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • local-profile-pics/trunk/local-profile-pics.php

    r3371709 r3722272  
    33Plugin Name: Local Profile Pics
    44Description: Allows users of your site to set custom profile pics from the local media library.
    5 Version: 0.2
    6 Requires at least: 5.0
     5Version: 0.3
     6Requires at least: 5.3
    77Requires PHP: 7.4
    88Author: Web Guy
    … …  
    2020class Local_Profile_Pics {
    2121        private $profile_pics_meta_key = 'profile_pics_custom_avatar';
     22        private $profile_pics_upload_error = null;
    2223
    2324        public function __construct() {
     25                add_action( 'activated_plugin', [ $this, 'profile_pics_migrate' ] );
    2426                add_action( 'admin_enqueue_scripts', [ $this, 'profile_pics_enqueue_media_scripts' ] );
    2527                add_action( 'show_user_profile', [ $this, 'profile_pics_add_avatar_field' ] );
    2628                add_action( 'edit_user_profile', [ $this, 'profile_pics_add_avatar_field' ] );
     29                add_action( 'user_edit_form_tag', [ $this, 'profile_pics_form_enctype' ] );
    2730                add_action( 'personal_options_update', [ $this, 'profile_pics_save_avatar' ] );
    2831                add_action( 'edit_user_profile_update', [ $this, 'profile_pics_save_avatar' ] );
     32                add_action( 'user_profile_update_errors', [ $this, 'profile_pics_upload_errors' ] );
     33                add_filter( 'get_avatar_data', [ $this, 'profile_pics_square_avatar' ] );
    2934                add_filter( 'get_avatar_url', [ $this, 'profile_pics_modify_avatar_url' ], 10, 3 );
     35        }
     36
     37        public function profile_pics_migrate( $plugin ) {
     38                if ( plugin_basename( __FILE__ ) !== $plugin ) {
     39                        return;
     40                }
     41                global $wpdb;
     42                $keys = [ 'simple_local_avatar', 'simple_local_avatar_' . get_current_blog_id(), $wpdb->get_blog_prefix() . 'user_avatar', 'wp_user_avatars', $wpdb->get_blog_prefix() . 'metronet_image_id', 'avatar_manager_custom_avatar' ];
     43                $users = get_users( [
     44                        'fields'     => 'ID',
     45                        'meta_query' => [ [ 'key' => $keys, 'compare_key' => 'IN' ] ], // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query
     46                ] );
     47                update_meta_cache( 'user', $users );
     48                foreach ( $users as $user_id ) {
     49                        if ( get_user_meta( $user_id, $this->profile_pics_meta_key, true ) ) {
     50                                continue;
     51                        }
     52                        foreach ( $keys as $key ) {
     53                                $value = get_user_meta( $user_id, $key, true );
     54                                $pic_id = is_array( $value ) ? absint( $value['media_id'] ?? 0 ) : absint( $value );
     55                                if ( $pic_id && wp_attachment_is_image( $pic_id ) ) {
     56                                        update_user_meta( $user_id, $this->profile_pics_meta_key, $pic_id );
     57                                        break;
     58                                }
     59                        }
     60                }
     61        }
     62
     63        public function profile_pics_form_enctype() {
     64                echo ' enctype="multipart/form-data"';
    3065        }
    3166
    … …  
    3469                        return;
    3570                }
    36                 $user_id = isset( $_GET['user_id'] ) ? absint( $_GET['user_id'] ) : get_current_user_id();
    37                 wp_enqueue_media();
     71                global $user_id;
     72                if ( current_user_can( 'upload_files' ) ) {
     73                        wp_enqueue_media();
     74                        wp_enqueue_script( 'imgareaselect' );
     75                        wp_enqueue_style( 'imgareaselect' );
     76                }
    3877                wp_add_inline_script(
    39                         'jquery', 
    40                         $this->profile_pics_get_media_script( $user_id ), 
     78                        'jquery',
     79                        $this->profile_pics_get_media_script( $user_id ),
    4180                        'after'
    4281                );
    … …  
    4887                                $(".user-profile-picture").after(
    4988                                        \'<tr><th></th><td><input type="hidden" id="profile-pic-id" name="%1$s" value="%2$s">\' +
    50                                         \'<button type="button" id="profile-pic-button" class="button">%3$s</button>\' +
    51                                         \'%4$s</td></tr>\'
     89                                        \'%6$s\' +
     90                                        \'%4$s<small><em id="profile-pic-status" role="status" data-msg="%5$s" style="color:#8a6100;line-height:30px;margin-left:10px"></em></small></td></tr>\'
    5291                                );
     92                                function profilePicStatus(url) {
     93                                        var status = $("#profile-pic-status");
     94                                        status.text(status.data("msg"));
     95                                        if (url) {
     96                                                $(".user-profile-picture img").attr("src", url).removeAttr("srcset");
     97                                        }
     98                                }
     99                                $("#profile-pic-remove").on("change", function() {
     100                                        profilePicStatus();
     101                                });
     102                                $("#profile-pic-file").on("change", function() {
     103                                        if (this.files[0]) {
     104                                                profilePicStatus(URL.createObjectURL(this.files[0]));
     105                                        }
     106                                });
    53107                                $("#profile-pic-button").on("click", function(e) {
    54108                                        e.preventDefault();
     109                                        var Cropper = wp.media.controller.Cropper.extend({
     110                                                doCrop: function(attachment) {
     111                                                        var details = attachment.get("cropDetails");
     112                                                        details.dst_width = details.width;
     113                                                        details.dst_height = details.width;
     114                                                        return wp.ajax.post("crop-image", {
     115                                                                nonce: attachment.get("nonces").edit,
     116                                                                id: attachment.get("id"),
     117                                                                context: "local-profile-pics",
     118                                                                cropDetails: details
     119                                                        });
     120                                                }
     121                                        });
    55122                                        var frame = wp.media({
    56                                                 title: "%3$s",
    57                                                 button: { text: "%3$s" },
    58                                                 multiple: false
    59                                         });
     123                                                button: { text: "%3$s", close: false },
     124                                                states: [
     125                                                        new wp.media.controller.Library({
     126                                                                title: "%3$s",
     127                                                                library: wp.media.query({ type: "image" }),
     128                                                                multiple: false
     129                                                        }),
     130                                                        new Cropper({
     131                                                                canSkipCrop: true,
     132                                                                imgSelectOptions: function(attachment) {
     133                                                                        var w = attachment.get("width"), h = attachment.get("height"), size = Math.min(w, h);
     134                                                                        return {
     135                                                                                handles: true,
     136                                                                                keys: true,
     137                                                                                instance: true,
     138                                                                                persistent: true,
     139                                                                                aspectRatio: "1:1",
     140                                                                                imageWidth: w,
     141                                                                                imageHeight: h,
     142                                                                                x1: Math.round((w - size) / 2),
     143                                                                                y1: Math.round((h - size) / 2),
     144                                                                                x2: Math.round((w + size) / 2),
     145                                                                                y2: Math.round((h + size) / 2)
     146                                                                        };
     147                                                                }
     148                                                        })
     149                                                ]
     150                                        });
     151                                        function profilePicSet(attachment) {
     152                                                $("#profile-pic-id").val(attachment.id);
     153                                                profilePicStatus(attachment.sizes && attachment.sizes.thumbnail ? attachment.sizes.thumbnail.url : attachment.url);
     154                                        }
    60155                                        frame.on("select", function() {
    61                                                 var attachment = frame.state().get("selection").first().toJSON();
    62                                                 $("#profile-pic-id").val(attachment.id);
     156                                                frame.setState("cropper");
     157                                        });
     158                                        frame.on("cropped", profilePicSet);
     159                                        frame.on("skippedcrop", function(selection) {
     160                                                profilePicSet(selection.toJSON());
    63161                                        });
    64162                                        frame.open();
    … …  
    68166                        esc_attr( get_user_meta( $user_id, $this->profile_pics_meta_key, true ) ),
    69167                        esc_html__( 'Select Profile Pic', 'local-profile-pics' ),
    70                         get_user_meta( $user_id, $this->profile_pics_meta_key, true ) ? sprintf( '<label style="line-height:30px;margin-left:10px"><input type="checkbox" name="%s" value="1"><small>%s</small></label>', esc_attr( $this->profile_pics_meta_key . '_remove' ), esc_html__( 'Remove Profile Pic', 'local-profile-pics' ) ) : ''
     168                        get_user_meta( $user_id, $this->profile_pics_meta_key, true ) ? sprintf( '<label style="line-height:30px;margin-left:10px"><input type="checkbox" id="profile-pic-remove" name="%s" value="1"><small>%s</small></label>', esc_attr( $this->profile_pics_meta_key . '_remove' ), esc_html__( 'Remove Profile Pic', 'local-profile-pics' ) ) : '',
     169                        esc_attr__( 'Unsaved: Click Update Below', 'local-profile-pics' ),
     170                        current_user_can( 'upload_files' ) ? sprintf( '<button type="button" id="profile-pic-button" class="button">%s</button>', esc_html__( 'Select Profile Pic', 'local-profile-pics' ) ) : sprintf( '<input type="file" id="profile-pic-file" name="%s" accept="image/jpeg,image/png,image/gif,image/webp" aria-label="%s">', esc_attr( $this->profile_pics_meta_key . '_file' ), esc_attr__( 'Select Profile Pic', 'local-profile-pics' ) )
    71171                );
    72172        }
    … …  
    82182                if ( !empty( $_POST[ $this->profile_pics_meta_key . '_remove' ] ) ) {
    83183                        delete_user_meta( $user_id, $this->profile_pics_meta_key );
    84                 } else {
    85                         $pic_id = absint( $_POST[ $this->profile_pics_meta_key ] ?? 0 );
     184                        return;
     185                }
     186                $pic_id = absint( $_POST[ $this->profile_pics_meta_key ] ?? 0 );
     187                if ( !empty( $_FILES[ $this->profile_pics_meta_key . '_file' ]['name'] ) ) {
     188                        $pic_id = media_handle_upload( $this->profile_pics_meta_key . '_file', 0, [], [ 'test_form' => false, 'mimes' => [ 'jpg|jpeg|jpe' => 'image/jpeg', 'png' => 'image/png', 'gif' => 'image/gif', 'webp' => 'image/webp' ] ] );
     189                        if ( is_wp_error( $pic_id ) ) {
     190                                $this->profile_pics_upload_error = $pic_id;
     191                                return;
     192                        }
     193                }
     194                if ( !$pic_id ) {
     195                        delete_user_meta( $user_id, $this->profile_pics_meta_key );
     196                } elseif ( wp_attachment_is_image( $pic_id ) ) {
    86197                        update_user_meta( $user_id, $this->profile_pics_meta_key, $pic_id );
    87198                }
     199        }
     200
     201        public function profile_pics_upload_errors( $errors ) {
     202                if ( $this->profile_pics_upload_error ) {
     203                        $errors->add( 'profile_pics_upload', $this->profile_pics_upload_error->get_error_message() );
     204                }
     205        }
     206
     207        public function profile_pics_square_avatar( $args ) {
     208                $args['extra_attr'] .= ' style="aspect-ratio:1;object-fit:cover"';
     209                return $args;
    88210        }
    89211
    … …  
    97219                } elseif ( $id_or_email instanceof WP_User ) {
    98220                        $user_id = $id_or_email->ID;
     221                } elseif ( $id_or_email instanceof WP_Post ) {
     222                        $user_id = (int) $id_or_email->post_author;
    99223                } elseif ( is_object( $id_or_email ) && !empty( $id_or_email->user_id ) ) {
    100224                        $user_id = (int) $id_or_email->user_id;
  • local-profile-pics/trunk/readme.txt

    r3444135 r3722272  
    44Donate link: https://webguy.io/donate
    55Tags: avatars, profile pics, user icons
    6 Requires at least: 5.0
    7 Tested up to: 6.8
     6Requires at least: 5.3
     7Tested up to: 7.1
    88Requires PHP: 7.4
    9 Stable tag: 0.2
     9Stable tag: 0.3
    1010License: CC0
    1111License URI: https://creativecommons.org/public-domain/cc0/
    1212
    13 Allows users of your site to set custom profile pics from the local media library.
     13Allow users of your site to set custom profile pics from the local media library.
    1414
    1515== Description ==
    … …  
    1717[💬 Ask Question](https://github.com/webguyio/support) | [📧 Email Me](mailto:webguywork@gmail.com)
    1818
    19 Allows users of your site to set custom profile pics from the local media library.
     19The simplest avatar plugin that just gets it done without all the bloat, upselling, or privacy issues.
     20
     21Allow users of your site to set custom profile pics from the local media library.
    2022
    2123Set a profile pic under: *Users > Profile > Profile Picture > Select Profile Pic*
     24
     25Automatic migration for: Simple Local Avatars, WP User Avatar, WP User Avatars, One User Avatar, User Profile Picture, and Avatar Manager. If you previously used any of these plugins, the avatar image links for users who set a custom pic will automatically migrate over in the background when you activate Local Profile Pics.
    2226
    2327== Installation ==
    … …  
    3943== Changelog ==
    4044
     45= 0.3 =
     46* Added migration support for Simple Local Avatars, WP User Avatar, WP User Avatars, One User Avatar, User Profile Picture, Avatar Manager
     47* Improved permissions, cropping, and error handling
     48
    4149= 0.2 =
    4250* Minor UX improvement
Note: See TracChangeset for help on using the changeset viewer.