diff --git a/wp-content/upgrade-temp-backup/plugins/simple-local-avatars/dist/simple-local-avatars.asset.php b/wp-content/upgrade-temp-backup/plugins/simple-local-avatars/dist/simple-local-avatars.asset.php new file mode 100644 index 00000000..97728613 --- /dev/null +++ b/wp-content/upgrade-temp-backup/plugins/simple-local-avatars/dist/simple-local-avatars.asset.php @@ -0,0 +1 @@ + array(), 'version' => 'aa61da036e6891c324d0'); diff --git a/wp-content/upgrade-temp-backup/plugins/simple-local-avatars/dist/simple-local-avatars.js b/wp-content/upgrade-temp-backup/plugins/simple-local-avatars/dist/simple-local-avatars.js new file mode 100644 index 00000000..1332c741 --- /dev/null +++ b/wp-content/upgrade-temp-backup/plugins/simple-local-avatars/dist/simple-local-avatars.js @@ -0,0 +1 @@ +(()=>{let a,e,t,i,r,s,l,o,n,c=!1;function m(a){void 0===e&&(t=document.getElementById("simple-local-avatar-ratings"),e=jQuery(document.getElementById("simple-local-avatar-spinner")),i=document.getElementById("simple-local-avatar-photo"),r=jQuery(t).closest("form").find("input[type=submit]")),"unlock"===a?(c=!1,r.removeAttr("disabled"),e.hide(),e.hasClass("is-active")&&e.removeClass("is-active")):(c=!0,r.attr("disabled","disabled"),e.show(),jQuery(i).html(e),e.hasClass("is-active")||e.addClass("is-active"))}function p(a,e){const t=e.get("control"),i=a.get("width"),r=a.get("height");let s=parseInt(t.params.width,10),l=parseInt(t.params.height,10);const o=s/l;e.set("canSkipCrop",!0);const n=s,c=l;i/r>o?(l=r,s=l*o):(s=i,l=s/o);const m=(i-s)/2,p=(r-l)/2;return{handles:!0,keys:!0,instance:!0,persistent:!0,imageWidth:i,imageHeight:r,minWidth:n>s?s:n,minHeight:c>l?l:c,x1:m,y1:p,x2:s+m,y2:l+p,aspectRatio:`${s}:${l}`}}function d(a,e,r,s){const l={};l.url=a,l.thumbnail_url=a,l.timestamp=_.now(),e&&(l.attachment_id=e),r&&(l.width=r),s&&(l.height=s),m("lock"),jQuery.post(i10n_SimpleLocalAvatars.ajaxurl,{action:"assign_simple_local_avatar_media",media_id:e,user_id:i10n_SimpleLocalAvatars.user_id,_wpnonce:i10n_SimpleLocalAvatars.mediaNonce}).done((function(a){""!==a&&(i.innerHTML=a,jQuery("#simple-local-avatar-remove").show(),t.disabled=!1)})).always((function(){m("unlock")}))}jQuery(document).ready((function(e){l=e("#simple-local-avatar"),s=e("#simple-local-avatar-photo img"),n=s.attr("src"),t=e("#simple-local-avatar-ratings"),i=e("#simple-local-avatar-photo"),e("#simple-local-avatar-media").on("click",(function(e){if(e.preventDefault(),c)return;const r={id:"control-id",params:{flex_width:!0,flex_height:!0,width:200,height:200}};a=wp.media({button:{text:i10n_SimpleLocalAvatars.selectCrop,close:!1},states:[new wp.media.controller.Library({title:i10n_SimpleLocalAvatars.selectCrop,library:wp.media.query({type:"image"}),multiple:!1,date:!1,priority:20,suggestedWidth:200,suggestedHeight:200}),new wp.media.controller.CustomizeImageCropper({imgSelectOptions:p,control:r})]}),a.on("cropped",(function(a){const{url:e}=a;d(e,a.id,a.width,a.height)})),a.on("skippedcrop",(function(a){const e=a.get("url"),t=a.get("width"),i=a.get("height");d(e,a.id,t,i)})),a.on("select",(function(){const e=a.state().get("selection").first().toJSON();var s;r.params.width!==e.width||r.params.height!==e.height||r.params.flex_width||r.params.flex_height?a.setState("cropper"):(e.dst_width=e.width,e.dst_height=e.height,s=e,m("lock"),jQuery.post(i10n_SimpleLocalAvatars.ajaxurl,{action:"assign_simple_local_avatar_media",media_id:s.id,user_id:i10n_SimpleLocalAvatars.user_id,_wpnonce:i10n_SimpleLocalAvatars.mediaNonce}).done((function(a){""!==a&&(i.innerHTML=a,jQuery("#simple-local-avatar-remove").show(),t.disabled=!1,m("unlock"))})).always((function(){m("unlock")})),a.close())})),a.open()})),e("#simple-local-avatar-remove").on("click",(function(a){a.preventDefault(),c||(m("lock"),e.get(i10n_SimpleLocalAvatars.ajaxurl,{action:"remove_simple_local_avatar",user_id:i10n_SimpleLocalAvatars.user_id,_wpnonce:i10n_SimpleLocalAvatars.deleteNonce}).done((function(a){""!==a&&(i.innerHTML=a,e("#simple-local-avatar-remove").hide(),t.disabled=!0)})).always((function(){m("unlock")})))})),l.on("change",(function(a){s.attr("srcset",""),s.attr("height","auto"),URL.revokeObjectURL(o),a.target.files.length>0?(o=URL.createObjectURL(a.target.files[0]),s.attr("src",o)):s.attr("src",n)})),e(document.getElementById("simple-local-avatars-migrate-from-wp-user-avatar")).on("click",(function(a){a.preventDefault(),jQuery.post(i10n_SimpleLocalAvatars.ajaxurl,{action:"migrate_from_wp_user_avatar",migrateFromWpUserAvatarNonce:i10n_SimpleLocalAvatars.migrateFromWpUserAvatarNonce}).always((function(){e(".simple-local-avatars-migrate-from-wp-user-avatar-progress").empty(),e(".simple-local-avatars-migrate-from-wp-user-avatar-progress").text(i10n_SimpleLocalAvatars.migrateFromWpUserAvatarProgress)})).done((function(a){e(".simple-local-avatars-migrate-from-wp-user-avatar-progress").empty();const t=e.parseJSON(a).count;0===t&&e(".simple-local-avatars-migrate-from-wp-user-avatar-progress").text(i10n_SimpleLocalAvatars.migrateFromWpUserAvatarFailure),t>0&&e(".simple-local-avatars-migrate-from-wp-user-avatar-progress").text(i10n_SimpleLocalAvatars.migrateFromWpUserAvatarSuccess+": "+t),setTimeout((function(){e(".simple-local-avatars-migrate-from-wp-user-avatar-progress").empty()}),5e3)}))}));const r=e("#clear_cache_btn"),u=e("#clear_cache_message"),v=e("#simple-local-avatar-default"),g=e("#simple-local-avatar-file-url"),h=e("#simple-local-avatar-file-id");function _(){r.find("span").remove(),r.removeClass("disabled")}function f(a,t){t.step=a,e.ajax({url:i10n_SimpleLocalAvatars.ajaxurl,dataType:"json",data:t,method:"POST",success:function(a){if(a.success)return"done"===a.data.step?(u.text(a.data.message),_()):(u.text(a.data.message),f(parseInt(a.data.step,10),t)),!1;u.text(i10n_SimpleLocalAvatars.clearCacheError),_()},error:function(){u.text(i10n_SimpleLocalAvatars.clearCacheError),_()}})}if(r.on("click",(function(a){a.preventDefault(),r.addClass("disabled"),r.append(''),f(1,{action:"sla_clear_user_cache",nonce:i10n_SimpleLocalAvatars.cacheNonce})})),v.click((function(a){a.preventDefault();var t=e(this),i=wp.media({title:i10n_SimpleLocalAvatars.insertMediaTitle,multiple:!1,library:{type:"image"}}).open().on("select",(function(a){var e=i.state().get("selection").first(),r=(e=e.toJSON())?.sizes?.thumbnail?.url;void 0===r&&(r=e.url);var s=t.parent().find("img.avatar");s.show(),s.attr("src",r),s.attr("srcset",r),g.val(r),h.val(e.id)}))})),g.length&&""!==g.val()){var w=g.parent().find("img.avatar");w.attr("src",g.val()),w.attr("srcset",g.val())}""===h.val()&&h.parent().find("img.avatar").hide()}))})(); \ No newline at end of file diff --git a/wp-content/upgrade-temp-backup/plugins/simple-local-avatars/includes/class-simple-local-avatars.php b/wp-content/upgrade-temp-backup/plugins/simple-local-avatars/includes/class-simple-local-avatars.php new file mode 100644 index 00000000..09cf948a --- /dev/null +++ b/wp-content/upgrade-temp-backup/plugins/simple-local-avatars/includes/class-simple-local-avatars.php @@ -0,0 +1,1664 @@ +add_hooks(); + + $this->options = (array) get_option( 'simple_local_avatars' ); + $this->user_key = 'simple_local_avatar'; + $this->rating_key = 'simple_local_avatar_rating'; + + if ( + ! $this->is_avatar_shared() // Are we sharing avatars? + && ( + ( // And either an ajax request not in the network admin. + defined( 'DOING_AJAX' ) && DOING_AJAX + && isset( $_SERVER['HTTP_REFERER'] ) && ! preg_match( '#^' . network_admin_url() . '#i', $_SERVER['HTTP_REFERER'] ) + ) + || + ( // Or normal request not in the network admin. + ( ! defined( 'DOING_AJAX' ) || ! DOING_AJAX ) + && ! is_network_admin() + ) + ) + && is_multisite() + ) { + $this->user_key = sprintf( $this->user_key . '_%d', get_current_blog_id() ); + $this->rating_key = sprintf( $this->rating_key . '_%d', get_current_blog_id() ); + } + } + + /** + * Register actions and filters. + */ + public function add_hooks() { + global $pagenow; + global $wp_version; + + add_filter( 'plugin_action_links_' . SLA_PLUGIN_BASENAME, array( $this, 'plugin_filter_action_links' ) ); + + add_filter( 'pre_get_avatar_data', array( $this, 'get_avatar_data' ), 10, 2 ); + add_filter( 'pre_option_simple_local_avatars', array( $this, 'pre_option_simple_local_avatars' ), 10, 1 ); + + add_action( 'admin_init', array( $this, 'admin_init' ) ); + add_action( 'init', array( $this, 'define_avatar_ratings' ) ); + + // Load the JS on BE & FE both, in order to support third party plugins like bbPress. + add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_scripts' ) ); + add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_scripts' ) ); + + add_action( 'show_user_profile', array( $this, 'edit_user_profile' ) ); + add_action( 'edit_user_profile', array( $this, 'edit_user_profile' ) ); + + add_action( 'personal_options_update', array( $this, 'edit_user_profile_update' ) ); + add_action( 'edit_user_profile_update', array( $this, 'edit_user_profile_update' ) ); + add_action( 'admin_action_remove-simple-local-avatar', array( $this, 'action_remove_simple_local_avatar' ) ); + add_action( 'wp_ajax_assign_simple_local_avatar_media', array( $this, 'ajax_assign_simple_local_avatar_media' ) ); + add_action( 'wp_ajax_remove_simple_local_avatar', array( $this, 'action_remove_simple_local_avatar' ) ); + add_action( 'user_edit_form_tag', array( $this, 'user_edit_form_tag' ) ); + + add_action( 'rest_api_init', array( $this, 'register_rest_fields' ) ); + + add_action( 'wp_ajax_migrate_from_wp_user_avatar', array( $this, 'ajax_migrate_from_wp_user_avatar' ) ); + + if ( defined( 'WP_CLI' ) && WP_CLI ) { + WP_CLI::add_command( 'simple-local-avatars migrate wp-user-avatar', array( $this, 'wp_cli_migrate_from_wp_user_avatar' ) ); + } + + add_action( 'wp_ajax_sla_clear_user_cache', array( $this, 'sla_clear_user_cache' ) ); + + add_filter( 'avatar_defaults', array( $this, 'add_avatar_default_field' ) ); + if ( version_compare( $wp_version, '5.1', '<' ) ) { + add_action( 'wpmu_new_blog', array( $this, 'set_defaults' ) ); + } else { + add_action( 'wp_initialize_site', array( $this, 'set_defaults' ) ); + } + + if ( 'profile.php' === $pagenow ) { + add_filter( + 'media_view_strings', + function ( $strings ) { + $strings['skipCropping'] = esc_html__( 'Default Crop', 'simple-local-avatars' ); + + return $strings; + }, + 10, + 1 + ); + } + + // Fix: An error occurred cropping the image (https://github.com/10up/simple-local-avatars/issues/141). + if ( isset( $_POST['action'] ) && 'crop-image' === $_POST['action'] && is_admin() && wp_doing_ajax() ) { + add_action( + 'plugins_loaded', + function () { + remove_all_actions( 'setup_theme' ); + } + ); + } + } + + /** + * Determine if plugin is network activated. + * + * @param string $plugin The plugin slug to check. + * + * @return boolean + */ + public static function is_network( $plugin ) { + $plugins = get_site_option( 'active_sitewide_plugins', array() ); + + if ( is_multisite() && isset( $plugins[ $plugin ] ) ) { + return true; + } + + return false; + } + + /** + * Get current plugin network mode + */ + public function get_network_mode() { + if ( SLA_IS_NETWORK ) { + return get_site_option( 'simple_local_avatars_mode', 'default' ); + } + + return 'default'; + } + + /** + * Determines if settings handling is enforced on a network level + * + * Important: this is only meant for admin UI purposes. + * + * @return boolean + */ + public function is_enforced() { + if ( + ( ! is_network_admin() && ( SLA_IS_NETWORK && 'enforce' === $this->get_network_mode() ) ) + ) { + return true; + } + + return false; + } + + /** + * Determine if avatars should be shared + * + * @return boolean + */ + public function is_avatar_shared() { + if ( ! is_multisite() ) { + return false; + } + + if ( + ! isset( $this->options['shared'] ) // Our shared option doesn't exist. + || 1 === $this->options['shared'] // Or our shared option is set. + ) { + return true; + } + + return false; + } + + /** + * Add the settings action link to the plugin page. + * + * @param array $links The Action links for the plugin. + * + * @return array + */ + public function plugin_filter_action_links( $links ) { + + if ( ! is_array( $links ) ) { + return $links; + } + + $links['settings'] = sprintf( + ' %s ', + esc_url( admin_url( 'options-discussion.php' ) ), + __( 'Settings', 'simple-local-avatars' ) + ); + + return $links; + } + + /** + * Retrieve the local avatar for a user who provided a user ID, email address or post/comment object. + * + * @param string $avatar Avatar return by original function + * @param int|string|object $id_or_email A user ID, email address, or post/comment object + * @param int $size Size of the avatar image + * @param string $default URL to a default image to use if no avatar is available + * @param string $alt Alternative text to use in image tag. Defaults to blank + * @param array $args Optional. Extra arguments to retrieve the avatar. + * + * @return string tag for the user's avatar + */ + public function get_avatar( $avatar = '', $id_or_email = '', $size = 96, $default = '', $alt = '', $args = array() ) { + return apply_filters( 'simple_local_avatar', get_avatar( $id_or_email, $size, $default, $alt, $args ) ); + } + + /** + * Filter avatar data early to add avatar url if needed. This filter hooks + * before Gravatar setup to prevent wasted requests. + * + * @since 2.2.0 + * + * @param array $args Arguments passed to get_avatar_data(), after processing. + * @param mixed $id_or_email The Gravatar to retrieve. Accepts a user ID, Gravatar MD5 hash, + * user email, WP_User object, WP_Post object, or WP_Comment object. + */ + public function get_avatar_data( $args, $id_or_email ) { + if ( ! empty( $args['force_default'] ) ) { + return $args; + } + + $simple_local_avatar_url = $this->get_simple_local_avatar_url( $id_or_email, $args['size'] ); + if ( $simple_local_avatar_url ) { + $args['url'] = $simple_local_avatar_url; + } + + // Local only mode + if ( ! $simple_local_avatar_url && ! empty( $this->options['only'] ) ) { + $args['url'] = $this->get_default_avatar_url( $args['size'] ); + } + + if ( ! empty( $args['url'] ) ) { + $args['found_avatar'] = true; + + // If custom alt text isn't passed, pull alt text from the local image. + if ( empty( $args['alt'] ) ) { + $args['alt'] = $this->get_simple_local_avatar_alt( $id_or_email ); + } + } + + return $args; + } + + /** + * Get a user ID from certain possible values. + * + * @since 2.5.0 + * + * @param mixed $id_or_email The Gravatar to retrieve. Accepts a user ID, Gravatar MD5 hash, + * user email, WP_User object, WP_Post object, or WP_Comment object. + * @return int|false + */ + public function get_user_id( $id_or_email ) { + $user_id = false; + + if ( is_numeric( $id_or_email ) ) { + $user_id = (int) $id_or_email; + } elseif ( is_object( $id_or_email ) && ! empty( $id_or_email->user_id ) ) { + $user_id = (int) $id_or_email->user_id; + } elseif ( $id_or_email instanceof WP_User ) { + $user_id = $id_or_email->ID; + } elseif ( $id_or_email instanceof WP_Post && ! empty( $id_or_email->post_author ) ) { + $user_id = (int) $id_or_email->post_author; + } elseif ( is_string( $id_or_email ) ) { + $user = get_user_by( 'email', $id_or_email ); + $user_id = $user ? $user->ID : ''; + } + + return $user_id; + } + + /** + * Get local avatar url. + * + * @since 2.2.0 + * + * @param mixed $id_or_email The Gravatar to retrieve. Accepts a user ID, Gravatar MD5 hash, + * user email, WP_User object, WP_Post object, or WP_Comment object. + * @param int $size Requested avatar size. + */ + public function get_simple_local_avatar_url( $id_or_email, $size ) { + $user_id = $this->get_user_id( $id_or_email ); + $size = (int) $size; + + if ( empty( $user_id ) ) { + return ''; + } + + $local_avatars = get_user_meta( $user_id, $this->user_key, true ); + + // Return avatar if exists. + if ( is_array( $local_avatars ) && array_key_exists( $size, $local_avatars ) && ( strpos( $local_avatars[ $size ], content_url() ) === 0 ) ) { + return esc_url( $local_avatars[ $size ] ); + } + + // Fetch local avatar from meta and make sure it's properly set. + if ( empty( $local_avatars['media_id'] ) ) { + return ''; + } + + // check rating + $avatar_rating = get_user_meta( $user_id, $this->rating_key, true ); + $site_rating = get_option( 'avatar_rating' ); + if ( ! empty( $avatar_rating ) && 'G' !== $avatar_rating && $site_rating ) { + $ratings = array_keys( $this->avatar_ratings ); + $site_rating_weight = array_search( $site_rating, $ratings, true ); + $avatar_rating_weight = array_search( $avatar_rating, $ratings, true ); + if ( false !== $avatar_rating_weight && $avatar_rating_weight > $site_rating_weight ) { + return ''; + } + } + + /** + * Filter the URL of an avatar for the given user and size. + * + * This filters is applied before Simple Local Avatars validates the value of the + * `$local_avatars` array which comes from the user meta field. This allows the URL + * to be short-circuited, for example by a dynamic image resizing service. + * + * @param string|null $url The URL of the avatar. If null, the URL will be + * generated by Simple Local Avatars. + * @param int $user_id The user ID. + * @param int $size Requested avatar size. + * @param array $local_avatars The local avatars for the user. + * @return string|null The URL of the avatar, or null to allow Simple Local Avatars to + * generate the URL. + */ + $url = apply_filters( 'pre_simple_local_avatar_url', null, $user_id, $size, $local_avatars ); + + if ( is_string( $url ) ) { + return esc_url( $url ); + } + + // handle "real" media + // If using shared avatars, make sure we validate the URL on the main site. + if ( $this->is_avatar_shared() ) { + $origin_blog_id = ! empty( $local_avatars['blog_id'] ) ? $local_avatars['blog_id'] : get_main_site_id(); + switch_to_blog( $origin_blog_id ); + } + + $avatar_full_path = get_attached_file( $local_avatars['media_id'] ); + + if ( $this->is_avatar_shared() ) { + restore_current_blog(); + } + + // has the media been deleted? + if ( ! $avatar_full_path ) { + return ''; + } + + // Use dynamic full url in favour of host/domain change. + $local_avatars['full'] = wp_get_attachment_image_url( $local_avatars['media_id'], 'full' ); + + // Generate a new size. + // Just in case of failure elsewhere, set the full size as default. + $local_avatars[ $size ] = $local_avatars['full']; + + // allow automatic rescaling to be turned off + if ( apply_filters( 'simple_local_avatars_dynamic_resize', true ) ) : + + $upload_path = wp_upload_dir(); + + // get path for image by converting URL, unless its already been set, thanks to using media library approach + if ( ! isset( $avatar_full_path ) ) { + $avatar_full_path = str_replace( $upload_path['baseurl'], $upload_path['basedir'], $local_avatars['full'] ); + } + + // generate the new size + $editor = wp_get_image_editor( $avatar_full_path ); + if ( ! is_wp_error( $editor ) ) { + $resized = $editor->resize( $size, $size, true ); + if ( ! is_wp_error( $resized ) ) { + $dest_file = $editor->generate_filename(); + $saved = $editor->save( $dest_file ); + if ( ! is_wp_error( $saved ) ) { + // Transform the destination file path into URL. + $dest_file_url = ''; + if ( false !== strpos( $dest_file, $upload_path['basedir'] ) ) { + $dest_file_url = str_replace( $upload_path['basedir'], $upload_path['baseurl'], $dest_file ); + } elseif ( is_multisite() && false !== strpos( $dest_file, ABSPATH . 'wp-content/uploads' ) ) { + $dest_file_url = str_replace( ABSPATH . 'wp-content/uploads', network_site_url( '/wp-content/uploads' ), $dest_file ); + } + + $local_avatars[ $size ] = $dest_file_url; + } + } + } + + // save updated avatar sizes + update_user_meta( $user_id, $this->user_key, $local_avatars ); + endif; + + if ( strpos( $local_avatars[ $size ], 'http' ) !== 0 ) { + $local_avatars[ $size ] = home_url( $local_avatars[ $size ] ); + } + + return esc_url( $local_avatars[ $size ] ); + } + + /** + * Get local avatar alt text. + * + * @since 2.5.0 + * + * @param mixed $id_or_email The Gravatar to retrieve. Accepts a user ID, Gravatar MD5 hash, + * user email, WP_User object, WP_Post object, or WP_Comment object. + * @return string + */ + public function get_simple_local_avatar_alt( $id_or_email ) { + $user_id = $this->get_user_id( $id_or_email ); + + /** + * Filter the default avatar alt text. + * + * @param string $alt Default alt text. + * @return string + */ + $default_alt = apply_filters( 'simple_local_avatars_default_alt', __( 'Avatar photo', 'simple-local-avatars' ) ); + + if ( empty( $user_id ) ) { + return $default_alt; + } + + // Fetch local avatar from meta and make sure we have a media ID. + $local_avatars = get_user_meta( $user_id, 'simple_local_avatar', true ); + if ( empty( $local_avatars['media_id'] ) ) { + $alt = ''; + // If no avatar is set, check if we are using a default avatar with alt text. + if ( 'simple_local_avatar' === get_option( 'avatar_default' ) ) { + $default_avatar_id = get_option( 'simple_local_avatar_default', '' ); + if ( ! empty( $default_avatar_id ) ) { + $alt = get_post_meta( $default_avatar_id, '_wp_attachment_image_alt', true ); + } + } + + return $alt ? $alt : $default_alt; + } + + $alt = get_post_meta( $local_avatars['media_id'], '_wp_attachment_image_alt', true ); + + return $alt ? $alt : $default_alt; + } + + /** + * Get default avatar url + * + * @since 2.2.0 + * + * @param int $size Requested avatar size. + */ + public function get_default_avatar_url( $size ) { + if ( empty( $default ) ) { + $avatar_default = get_option( 'avatar_default' ); + if ( empty( $avatar_default ) ) { + $default = 'mystery'; + } else { + $default = $avatar_default; + } + } + + $host = is_ssl() ? 'https://secure.gravatar.com' : 'http://0.gravatar.com'; + + if ( 'mystery' === $default ) { + $default = "$host/avatar/ad516503a11cd5ca435acc9bb6523536?s={$size}"; // ad516503a11cd5ca435acc9bb6523536 == md5('unknown@gravatar.com') + } elseif ( 'blank' === $default ) { + $default = includes_url( 'images/blank.gif' ); + } elseif ( 'gravatar_default' === $default ) { + $default = "$host/avatar/?s={$size}"; + } elseif ( 'simple_local_avatar' === $default ) { + $default = "$host/avatar/?d=$default&s={$size}"; + $default_avatar_id = get_option( 'simple_local_avatar_default', '' ); + if ( ! empty( $default_avatar_id ) ) { + $default = wp_get_attachment_image_url( $default_avatar_id ); + } + } else { + $default = "$host/avatar/?d=$default&s={$size}"; + } + + return $default; + } + + /** + * Define the ratings avatar ratings. + * + * The ratings need to be defined after the languages have been loaded so + * they can be translated. This method exists to define the ratings + * after that has been done. + * + * @since 2.7.3 + */ + public function define_avatar_ratings() { + /* + * Avatar ratings. + * + * The key should not be translated as it's used by WP Core in it's + * english form (G, PG, etc). + * + * The values should be translated, these include the initial rating + * name and the description for display to users. + */ + $this->avatar_ratings = array( + /* translators: Content suitability rating: https://en.wikipedia.org/wiki/Motion_Picture_Association_of_America_film_rating_system */ + 'G' => __( 'G — Suitable for all audiences' ), + /* translators: Content suitability rating: https://en.wikipedia.org/wiki/Motion_Picture_Association_of_America_film_rating_system */ + 'PG' => __( 'PG — Possibly offensive, usually for audiences 13 and above' ), + /* translators: Content suitability rating: https://en.wikipedia.org/wiki/Motion_Picture_Association_of_America_film_rating_system */ + 'R' => __( 'R — Intended for adult audiences above 17' ), + /* translators: Content suitability rating: https://en.wikipedia.org/wiki/Motion_Picture_Association_of_America_film_rating_system */ + 'X' => __( 'X — Even more mature than above' ), + ); + } + + /** + * Register admin settings. + */ + public function admin_init() { + $this->define_avatar_ratings(); + // upgrade pre 2.0 option + $old_ops = get_option( 'simple_local_avatars_caps' ); + if ( $old_ops ) { + if ( ! empty( $old_ops['simple_local_avatars_caps'] ) ) { + update_option( 'simple_local_avatars', array( 'caps' => 1 ) ); + } + + delete_option( 'simple_local_avatar_caps' ); + } + + register_setting( 'discussion', 'simple_local_avatars', array( $this, 'sanitize_options' ) ); + add_settings_field( + 'simple-local-avatars-only', + __( 'Local Avatars Only', 'simple-local-avatars' ), + array( $this, 'avatar_settings_field' ), + 'discussion', + 'avatars', + array( + 'class' => 'simple-local-avatars', + 'key' => 'only', + 'desc' => __( 'Only allow local avatars (still uses Gravatar for default avatars)', 'simple-local-avatars' ), + ) + ); + add_settings_field( + 'simple-local-avatars-caps', + __( 'Local Upload Permissions', 'simple-local-avatars' ), + array( $this, 'avatar_settings_field' ), + 'discussion', + 'avatars', + array( + 'class' => 'simple-local-avatars', + 'key' => 'caps', + 'desc' => __( 'Only allow users with file upload capabilities to upload local avatars (Authors and above)', 'simple-local-avatars' ), + ) + ); + + if ( is_multisite() ) { + add_settings_field( + 'simple-local-avatars-shared', + __( 'Shared network avatars', 'simple-local-avatars' ), + array( $this, 'avatar_settings_field' ), + 'discussion', + 'avatars', + array( + 'class' => 'simple-local-avatars', + 'key' => 'shared', + 'desc' => __( 'Uploaded avatars will be shared across the entire network, instead of being unique per site', 'simple-local-avatars' ), + 'default' => 1, + ) + ); + } + + add_action( 'load-options-discussion.php', array( $this, 'load_discussion_page' ) ); + + // This is for network site settings. + if ( SLA_IS_NETWORK && is_network_admin() ) { + add_action( 'load-settings.php', array( $this, 'load_network_settings' ) ); + } + + add_settings_field( + 'simple-local-avatars-migration', + __( 'Migrate Other Local Avatars', 'simple-local-avatars' ), + array( $this, 'migrate_from_wp_user_avatar_settings_field' ), + 'discussion', + 'avatars' + ); + add_settings_field( + 'simple-local-avatars-clear', + esc_html__( 'Clear local avatar cache', 'simple-local-avatars' ), + array( $this, 'avatar_settings_field' ), + 'discussion', + 'avatars', + array( + 'key' => 'clear_cache', + 'desc' => esc_html__( 'Clear cache of stored avatars', 'simple-local-avatars' ), + ) + ); + + // Save default avatar file. + $this->save_default_avatar_file_id(); + } + + /** + * Fire code on the Discussion page + */ + public function load_discussion_page() { + add_action( 'admin_print_styles', array( $this, 'admin_print_styles' ) ); + add_filter( 'admin_body_class', array( $this, 'admin_body_class' ) ); + } + + /** + * Load needed hooks to handle network settings + */ + public function load_network_settings() { + $this->options = (array) get_site_option( 'simple_local_avatars', array() ); + + add_action( 'wpmu_options', array( $this, 'show_network_settings' ) ); + add_action( 'update_wpmu_options', array( $this, 'save_network_settings' ) ); + } + + /** + * Show the network settings + */ + public function show_network_settings() { + $mode = $this->get_network_mode(); + ?> + +

+ + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
+ + + avatar_settings_field( + array( + 'key' => 'only', + 'desc' => __( 'Only allow local avatars (still uses Gravatar for default avatars) ', 'simple-local-avatars' ), + ) + ); + ?> +
+ + + avatar_settings_field( + array( + 'key' => 'caps', + 'desc' => __( 'Only allow users with file upload capabilities to upload local avatars (Authors and above)', 'simple-local-avatars' ), + ) + ); + ?> +
+ + + avatar_settings_field( + array( + 'key' => 'shared', + 'desc' => __( 'Uploaded avatars will be shared across the entire network, instead of being unique per site', 'simple-local-avatars' ), + 'default' => 1, + ) + ); + ?> +
+ + remove_nonce = wp_create_nonce( 'remove_simple_local_avatar_nonce' ); + + wp_enqueue_script( 'simple-local-avatars', plugins_url( '', dirname( __FILE__ ) ) . '/dist/simple-local-avatars.js', array( 'jquery' ), SLA_VERSION, true ); + wp_localize_script( + 'simple-local-avatars', + 'i10n_SimpleLocalAvatars', + array( + 'ajaxurl' => admin_url( 'admin-ajax.php' ), + 'user_id' => $user_id, + 'insertIntoPost' => __( 'Set as avatar', 'simple-local-avatars' ), + 'selectCrop' => __( 'Select avatar and Crop', 'simple-local-avatars' ), + 'deleteNonce' => $this->remove_nonce, + 'cacheNonce' => wp_create_nonce( 'sla_clear_cache_nonce' ), + 'mediaNonce' => wp_create_nonce( 'assign_simple_local_avatar_nonce' ), + 'migrateFromWpUserAvatarNonce' => wp_create_nonce( 'migrate_from_wp_user_avatar_nonce' ), + 'clearCacheError' => esc_html__( 'Something went wrong while clearing cache, please try again.', 'simple-local-avatars' ), + 'insertMediaTitle' => esc_html__( 'Choose default avatar', 'simple-local-avatars' ), + 'migrateFromWpUserAvatarSuccess' => __( 'Number of avatars successfully migrated from WP User Avatar', 'simple-local-avatars' ), + 'migrateFromWpUserAvatarFailure' => __( 'No avatars were migrated from WP User Avatar.', 'simple-local-avatars' ), + 'migrateFromWpUserAvatarProgress' => __( 'Migration in progress.', 'simple-local-avatars' ), + ) + ); + } + + /** + * Sanitize new settings field before saving + * + * @param array|string $input Passed input values to sanitize + * @return array|string Sanitized input fields + */ + public function sanitize_options( $input ) { + $new_input['caps'] = empty( $input['caps'] ) ? 0 : 1; + $new_input['only'] = empty( $input['only'] ) ? 0 : 1; + + if ( is_multisite() ) { + $new_input['shared'] = empty( $input['shared'] ) ? 0 : 1; + } + + return $new_input; + } + + /** + * Settings field for avatar upload capabilities + * + * @param array $args Field arguments + */ + public function avatar_settings_field( $args ) { + $args = wp_parse_args( + $args, + array( + 'key' => '', + 'desc' => '', + 'default' => 0, + ) + ); + + if ( ! isset( $this->options[ $args['key'] ] ) ) { + $this->options[ $args['key'] ] = $args['default']; + } + + if ( 'clear_cache' !== $args['key'] ) { + echo ' + + '; + } else { + echo '
'; + echo ''; + } + + // Output warning if needed. + if ( + SLA_IS_NETWORK // If network activated. + && $this->is_enforced() // And in enforce mode. + && 'shared' === $args['key'] // And we are displaying the last setting. + ) { + echo ' +
+

' . esc_html__( 'Simple Local Avatar settings are currently enforced across all sites on the network.', 'simple-local-avatars' ) . '

+
+ '; + } + } + + /** + * Settings field for migrating avatars away from WP User Avatar + */ + public function migrate_from_wp_user_avatar_settings_field() { + printf( + '

', + esc_attr( 'simple-local-avatars-migrate-from-wp-user-avatar' ), + esc_html__( 'Migrate avatars from WP User Avatar to Simple Local Avatars', 'simple-local-avatars' ) + ); + } + + /** + * Output new Avatar fields to user editing / profile screen + * + * @param object $profileuser User object + */ + public function edit_user_profile( $profileuser ) { + ?> +
+

+ + + + + + + + + + +
+
+
+ ID ) ); + remove_filter( 'pre_option_avatar_rating', '__return_empty_string' ); + ?> + +
+
+ options['caps'] ); + } + + if ( $upload_rights ) { + do_action( 'simple_local_avatar_notices' ); + wp_nonce_field( 'simple_local_avatar_nonce', '_simple_local_avatar_nonce', false ); + $remove_url = add_query_arg( + array( + 'action' => 'remove-simple-local-avatar', + 'user_id' => $profileuser->ID, + '_wpnonce' => $this->remove_nonce, + ) + ); + ?> + +

+
+ +

+ +

+ +   + + simple_local_avatar ) ? ' style="display:none;"' : ''; ?>> + + +

+ simple_local_avatar ) ) { + echo '' . esc_html__( 'No local avatar is set. Set up your avatar at Gravatar.com.', 'simple-local-avatars' ) . ''; + } else { + echo '' . esc_html__( 'You do not have media management permissions. To change your local avatar, contact the blog administrator.', 'simple-local-avatars' ) . ''; + } + } + ?> +
+
+
+
simple_local_avatar ) ); ?>> + + simple_local_avatar_rating ) || ! array_key_exists( $profileuser->simple_local_avatar_rating, $this->avatar_ratings ) ) { + $profileuser->simple_local_avatar_rating = 'G'; + } + + foreach ( $this->avatar_ratings as $key => $rating ) : + echo "\n\t
'; + endforeach; + ?> +

+
+
+
+ avatar_delete( $user_id ); // delete old images if successful. + + $meta_value = array(); + + // set the new avatar + if ( is_numeric( $url_or_media_id ) ) { + $meta_value['media_id'] = $url_or_media_id; + $url_or_media_id = wp_get_attachment_url( $url_or_media_id ); + } + + $meta_value['full'] = $url_or_media_id; + $meta_value['blog_id'] = get_current_blog_id(); + + update_user_meta( $user_id, $this->user_key, $meta_value ); // save user information (overwriting old). + + /** + * Enable themes and other plugins to react to changes to a user's avatar. + * + * @since 2.6.0 + * + * @param int $user_id Id of the user who's avatar was updated + */ + do_action( 'simple_local_avatar_updated', $user_id ); + } + + /** + * Save any changes to the user profile + * + * @param int $user_id ID of user being updated + */ + public function edit_user_profile_update( $user_id ) { + // check nonces + if ( empty( $_POST['_simple_local_avatar_nonce'] ) || ! wp_verify_nonce( $_POST['_simple_local_avatar_nonce'], 'simple_local_avatar_nonce' ) ) { + return; + } + + // check for uploaded files + if ( ! empty( $_FILES['simple-local-avatar']['name'] ) && 0 === $_FILES['simple-local-avatar']['error'] ) : + + // need to be more secure since low privelege users can upload + $allowed_mime_types = wp_get_mime_types(); + $file_mime_type = strtolower( $_FILES['simple-local-avatar']['type'] ); + + if ( ! ( 0 === strpos( $file_mime_type, 'image/' ) ) || ! in_array( $file_mime_type, $allowed_mime_types, true ) ) { + $this->avatar_upload_error = __( 'Only images can be uploaded as an avatar', 'simple-local-avatars' ); + add_action( 'user_profile_update_errors', array( $this, 'user_profile_update_errors' ) ); + return; + } + + $max_upload_size = $this->upload_size_limit( wp_max_upload_size() ); + if ( $_FILES['simple-local-avatar']['size'] > $max_upload_size ) { + $this->avatar_upload_error = sprintf( __( 'Max allowed avatar size is %s', 'simple-local-avatars' ), size_format( $max_upload_size ) ); + add_action( 'user_profile_update_errors', array( $this, 'user_profile_update_errors' ) ); + return; + } + + // front end (theme my profile etc) support + if ( ! function_exists( 'media_handle_upload' ) ) { + include_once ABSPATH . 'wp-admin/includes/media.php'; + } + + // front end (plugin bbPress etc) support + if ( ! function_exists( 'wp_handle_upload' ) ) { + include_once ABSPATH . 'wp-admin/includes/file.php'; + } + if ( ! function_exists( 'wp_generate_attachment_metadata' ) ) { + include_once ABSPATH . 'wp-admin/includes/image.php'; + } + + $this->user_id_being_edited = $user_id; // make user_id known to unique_filename_callback function + $avatar_id = media_handle_upload( + 'simple-local-avatar', + 0, + array(), + array( + 'mimes' => array( + 'jpg|jpeg|jpe' => 'image/jpeg', + 'gif' => 'image/gif', + 'png' => 'image/png', + ), + 'test_form' => false, + 'unique_filename_callback' => array( $this, 'unique_filename_callback' ), + ) + ); + + if ( is_wp_error( $avatar_id ) ) { // handle failures. + $this->avatar_upload_error = '' . __( 'There was an error uploading the avatar:', 'simple-local-avatars' ) . ' ' . esc_html( $avatar_id->get_error_message() ); + add_action( 'user_profile_update_errors', array( $this, 'user_profile_update_errors' ) ); + + return; + } + + $this->assign_new_user_avatar( $avatar_id, $user_id ); + + endif; + + // Handle ratings + if ( isset( $avatar_id ) || get_user_meta( $user_id, $this->user_key, true ) ) { + if ( empty( $_POST['simple_local_avatar_rating'] ) || ! array_key_exists( $_POST['simple_local_avatar_rating'], $this->avatar_ratings ) ) { + $_POST['simple_local_avatar_rating'] = key( $this->avatar_ratings ); + } + + update_user_meta( $user_id, $this->rating_key, $_POST['simple_local_avatar_rating'] ); + } + } + + /** + * Allow developers to override the maximum allowable file size for avatar uploads + * + * @param int $bytes WordPress default byte size check + * @return int Maximum byte size + */ + public function upload_size_limit( $bytes ) { + return apply_filters( 'simple_local_avatars_upload_limit', $bytes ); + } + + /** + * Runs when a user clicks the Remove button for the avatar + */ + public function action_remove_simple_local_avatar() { + if ( ! empty( $_GET['user_id'] ) && ! empty( $_GET['_wpnonce'] ) && wp_verify_nonce( $_GET['_wpnonce'], 'remove_simple_local_avatar_nonce' ) ) { + $user_id = (int) $_GET['user_id']; + + if ( ! current_user_can( 'edit_user', $user_id ) ) { + wp_die( esc_html__( 'You do not have permission to edit this user.', 'simple-local-avatars' ) ); + } + + $this->avatar_delete( $user_id ); // delete old images if successful + + /** + * Enable themes and other plugins to react to avatar deletions. + * + * @since 2.6.0 + * + * @param int $user_id Id of the user who's avatar was deleted. + */ + do_action( 'simple_local_avatar_deleted', $user_id ); + + if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) { + echo wp_kses_post( get_simple_local_avatar( $user_id ) ); + } + } + + if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) { + die; + } + } + + /** + * AJAX callback for assigning media ID fetched from media library to user + */ + public function ajax_assign_simple_local_avatar_media() { + // check required information and permissions + if ( empty( $_POST['user_id'] ) || empty( $_POST['media_id'] ) || ! current_user_can( 'upload_files' ) || ! current_user_can( 'edit_user', $_POST['user_id'] ) || empty( $_POST['_wpnonce'] ) || ! wp_verify_nonce( $_POST['_wpnonce'], 'assign_simple_local_avatar_nonce' ) ) { + die; + } + + $media_id = (int) $_POST['media_id']; + $user_id = (int) $_POST['user_id']; + + // ensure the media is real is an image + if ( wp_attachment_is_image( $media_id ) ) { + $this->assign_new_user_avatar( $media_id, $user_id ); + } + + echo wp_kses_post( get_simple_local_avatar( $user_id ) ); + + die; + } + + /** + * Delete avatars based on a user_id + * + * @param int $user_id User ID. + */ + public function avatar_delete( $user_id ) { + $old_avatars = (array) get_user_meta( $user_id, $this->user_key, true ); + + if ( empty( $old_avatars ) ) { + return; + } + + // if it was uploaded media, don't erase the full size or try to erase an the ID + if ( array_key_exists( 'media_id', $old_avatars ) ) { + unset( $old_avatars['media_id'], $old_avatars['full'] ); + } + + if ( ! empty( $old_avatars ) ) { + $upload_path = wp_upload_dir(); + + foreach ( $old_avatars as $old_avatar ) { + // derive the path for the file based on the upload directory + $old_avatar_path = str_replace( $upload_path['baseurl'], $upload_path['basedir'], $old_avatar ); + if ( file_exists( $old_avatar_path ) ) { + unlink( $old_avatar_path ); + } + } + } + + delete_user_meta( $user_id, $this->user_key ); + delete_user_meta( $user_id, $this->rating_key ); + } + + /** + * Creates a unique, meaningful file name for uploaded avatars. + * + * @param string $dir Path for file + * @param string $name Filename + * @param string $ext File extension (e.g. ".jpg") + * @return string Final filename + */ + public function unique_filename_callback( $dir, $name, $ext ) { + $user = get_user_by( 'id', (int) $this->user_id_being_edited ); + $name = $base_name = sanitize_file_name( $user->display_name . '_avatar_' . time() ); //phpcs:ignore + + // ensure no conflicts with existing file names + $number = 1; + while ( file_exists( $dir . "/$name$ext" ) ) { + $name = $base_name . '_' . $number; + $number ++; + } + + return $name . $ext; + } + + /** + * Adds errors based on avatar upload problems. + * + * @param WP_Error $errors Error messages for user profile screen. + */ + public function user_profile_update_errors( WP_Error $errors ) { + $errors->add( 'avatar_error', $this->avatar_upload_error ); + } + + /** + * Registers the simple_local_avatar field in the REST API. + */ + public function register_rest_fields() { + register_rest_field( + 'user', + 'simple_local_avatar', + array( + 'get_callback' => array( $this, 'get_avatar_rest' ), + 'update_callback' => array( $this, 'set_avatar_rest' ), + 'schema' => array( + 'description' => 'The users simple local avatar', + 'type' => 'object', + ), + ) + ); + } + + /** + * Returns the simple_local_avatar meta key for the given user. + * + * @param object $user User object + */ + public function get_avatar_rest( $user ) { + $local_avatar = get_user_meta( $user['id'], $this->user_key, true ); + if ( empty( $local_avatar ) ) { + return; + } + + return $local_avatar; + } + + /** + * Updates the simple local avatar from a REST request. + * + * Since we are just adding a field to the existing user endpoint + * we don't need to worry about ensuring the calling user has proper permissions. + * Only the user or an administrator would be able to change the avatar. + * + * @param array $input Input submitted via REST request. + * @param object $user The user making the request. + */ + public function set_avatar_rest( $input, $user ) { + $this->assign_new_user_avatar( $input['media_id'], $user->ID ); + } + + /** + * Short-circuit filter the `simple_local_avatars` option to match network if necessary + * + * @param bool $value Value of `simple_local_avatars` option, typically false. + * + * @return array + */ + public function pre_option_simple_local_avatars( $value ) { + if ( SLA_IS_NETWORK && 'enforce' === $this->get_network_mode() ) { + $value = get_site_option( 'simple_local_avatars', array() ); + } + + return $value; + } + + /** + * Set plugin defaults for a new site + * + * @param int|WP_Site $blog_id Blog ID or object. + */ + public function set_defaults( $blog_id ) { + if ( 'enforce' === $this->get_network_mode() ) { + return; + } + + if ( $blog_id instanceof WP_Site ) { + $blog_id = (int) $blog_id->blog_id; + } + + switch_to_blog( $blog_id ); + update_option( 'simple_local_avatars', $this->sanitize_options( $this->options ) ); + restore_current_blog(); + } + + /** + * Add some basic styling on the Discussion page + */ + public function admin_print_styles() { + ?> + + is_enforced() ) { + $classes .= ' sla-enforced'; + } + + return $classes; + } + + /** + * Clear user cache. + */ + public function sla_clear_user_cache() { + check_ajax_referer( 'sla_clear_cache_nonce', 'nonce' ); + $step = isset( $_REQUEST['step'] ) ? intval( $_REQUEST['step'] ) : 1; + + // Setup defaults. + $users_per_page = 50; + $offset = ( $step - 1 ) * $users_per_page; + + $users_query = new \WP_User_Query( + array( + 'fields' => array( 'ID' ), + 'number' => $users_per_page, + 'offset' => $offset, + ) + ); + + // Total users in the site. + $total_users = $users_query->get_total(); + + // Get the users. + $users = $users_query->get_results(); + + if ( ! empty( $users ) ) { + foreach ( $users as $user ) { + $user_id = $user->ID; + $local_avatars = get_user_meta( $user_id, 'simple_local_avatar', true ); + $media_id = isset( $local_avatars['media_id'] ) ? $local_avatars['media_id'] : ''; + $this->clear_user_avatar_cache( $local_avatars, $user_id, $media_id ); + } + + wp_send_json_success( + array( + 'step' => $step + 1, + 'message' => sprintf( + /* translators: 1: Offset, 2: Total users */ + esc_html__( 'Processing %1$s/%2$s users...', 'simple-local-avatars' ), + $offset, + $total_users + ), + ) + ); + } + + wp_send_json_success( + array( + 'step' => 'done', + 'message' => sprintf( + /* translators: %s Total users */ + esc_html__( 'Completed clearing cache for all %s user(s) avatars.', 'simple-local-avatars' ), + $total_users + ), + ) + ); + } + + /** + * Clear avatar cache for given user. + * + * @param array $local_avatars Local avatars. + * @param int $user_id User ID. + * @param mixed $media_id Media ID. + */ + private function clear_user_avatar_cache( $local_avatars, $user_id, $media_id ) { + if ( ! empty( $media_id ) ) { + // In order to support WP 4.9. + if ( function_exists( 'wp_get_original_image_path' ) ) { + $file_name_data = pathinfo( wp_get_original_image_path( $media_id ) ); + } else { + $file_name_data = pathinfo( get_attached_file( $media_id ) ); + } + + $file_dir_name = $file_name_data['dirname']; + $file_name = $file_name_data['filename']; + $file_ext = $file_name_data['extension']; + foreach ( $local_avatars as $local_avatars_key => $local_avatar_value ) { + if ( ! in_array( $local_avatars_key, [ 'media_id', 'full' ], true ) ) { + $file_size_path = sprintf( '%1$s/%2$s-%3$sx%3$s.%4$s', $file_dir_name, $file_name, $local_avatars_key, $file_ext ); + if ( ! file_exists( $file_size_path ) ) { + unset( $local_avatars[ $local_avatars_key ] ); + } + } + } + + // Update meta, remove sizes that don't exist. + update_user_meta( $user_id, 'simple_local_avatar', $local_avatars ); + } + } + + /** + * Add default avatar upload file field. + * + * @param array $defaults Default options for avatar. + * + * @return array Default options of avatar. + */ + public function add_avatar_default_field( $defaults ) { + $default_avatar_file_url = ''; + $default_avatar_file_id = get_option( 'simple_local_avatar_default', '' ); + if ( ! empty( $default_avatar_file_id ) ) { + $default_avatar_file_url = wp_get_attachment_image_url( $default_avatar_file_id ); + } + ob_start(); + ?> + + + + blog_id = 1; + $sites = array( $site ); + } + + // Bail early if we don't find sites. + if ( empty( $sites ) ) { + return $count; + } + + foreach ( $sites as $site ) { + // Get the blog ID to use in the meta key and user query. + $blog_id = isset( $site->blog_id ) ? $site->blog_id : 1; + + // Get the name of the meta key for WP User Avatar. + $meta_key = $wpdb->get_blog_prefix( $blog_id ) . 'user_avatar'; + + // Get processed users from database. + $migrations = get_option( 'simple_local_avatars_migrations', array() ); + $processed_users = isset( $migrations['wp_user_avatar'] ) ? $migrations['wp_user_avatar'] : array(); + + // Get all users that have a local avatar. + $users = get_users( + array( + 'blog_id' => $blog_id, + 'exclude' => $processed_users, + 'meta_key' => $meta_key, + 'meta_compare' => 'EXISTS', + ) + ); + + // Bail early if we don't find users. + if ( empty( $users ) ) { + continue; + } + + foreach ( $users as $user ) { + // Get the existing avatar media ID. + $avatar_id = get_user_meta( $user->ID, $meta_key, true ); + + // Attach the user and media to Simple Local Avatars. + $sla = new Simple_Local_Avatars(); + $sla->assign_new_user_avatar( (int) $avatar_id, $user->ID ); + + // Check that it worked. + $is_migrated = get_user_meta( $user->ID, 'simple_local_avatar', true ); + + if ( ! empty( $is_migrated ) ) { + // Build array of user IDs. + $migrations['wp_user_avatar'][] = $user->ID; + + // Record the user IDs so we don't process a second time. + $is_saved = update_option( 'simple_local_avatars_migrations', $migrations ); + + // Record how many avatars we migrate to be used in our messaging. + if ( $is_saved ) { + $count ++; + } + } + } + } + + return $count; + } + + /** + * Migrate the user's avatar data away from WP User Avatar/ProfilePress via the dashboard. + * + * Sends the number of avatars processed back to the AJAX response before stopping execution. + * + * @return void + */ + public function ajax_migrate_from_wp_user_avatar() { + // Bail early if nonce is not available. + if ( empty( sanitize_text_field( $_POST['migrateFromWpUserAvatarNonce'] ) ) ) { + die; + } + + // Bail early if nonce is invalid. + if ( ! wp_verify_nonce( sanitize_text_field( $_POST['migrateFromWpUserAvatarNonce'] ), 'migrate_from_wp_user_avatar_nonce' ) ) { + die(); + } + + // Run the migration script and store the number of avatars processed. + $count = $this->migrate_from_wp_user_avatar(); + + // Create the array we send back to javascript here. + $array_we_send_back = array( 'count' => $count ); + + // Make sure to json encode the output because that's what it is expecting. + echo wp_json_encode( $array_we_send_back ); + + // Make sure you die when finished doing ajax output. + wp_die(); + + } + + /** + * Migrate the user's avatar data from WP User Avatar/ProfilePress via the command line. + * + * ## OPTIONS + * + * [--yes] + * : Skips the confirmations (for automated systems). + * + * ## EXAMPLES + * + * $ wp simple-local-avatars migrate wp-user-avatar + * Success: Number of avatars successfully migrated from WP User Avatar: 5 + * + * @param array $args The arguments. + * @param array $assoc_args The associative arguments. + * + * @return void + */ + public function wp_cli_migrate_from_wp_user_avatar( $args, $assoc_args ) { + + // Argument --yes to prevent confirmation (for automated systems). + if ( ! isset( $assoc_args['yes'] ) ) { + WP_CLI::confirm( esc_html__( 'Do you want to migrate avatars from WP User Avatar?', 'simple-local-avatars' ) ); + } + + // Run the migration script and store the number of avatars processed. + $count = $this->migrate_from_wp_user_avatar(); + + // Error out if we don't process any avatars. + if ( 0 === absint( $count ) ) { + WP_CLI::error( esc_html__( 'No avatars were migrated from WP User Avatar.', 'simple-local-avatars' ) ); + } + + WP_CLI::success( + sprintf( + '%s: %s', + esc_html__( 'Number of avatars successfully migrated from WP User Avatar', 'simple-local-avatars' ), + esc_html( $count ) + ) + ); + } +} diff --git a/wp-content/upgrade-temp-backup/plugins/simple-local-avatars/readme.txt b/wp-content/upgrade-temp-backup/plugins/simple-local-avatars/readme.txt new file mode 100644 index 00000000..8327a85e --- /dev/null +++ b/wp-content/upgrade-temp-backup/plugins/simple-local-avatars/readme.txt @@ -0,0 +1,254 @@ +=== Simple Local Avatars === +Contributors: jakemgold, 10up, thinkoomph, jeffpaul, faisal03 +Donate link: https://10up.com/plugins/simple-local-avatars-wordpress/ +Tags: avatar, gravatar, user photos, users, profile +Requires at least: 5.7 +Tested up to: 6.4 +Requires PHP: 7.4 +Stable tag: 2.7.6 +License: GPLv2 or later +License URI: http://www.gnu.org/licenses/gpl-2.0.html + +Adds an avatar upload field to user profiles. Generates requested sizes on demand just like Gravatar! + +== Description == + +Adds an avatar upload field to user profiles if the current user has media permissions. Generates requested sizes on demand just like Gravatar! Simple and lightweight. + +Just edit a user profile, and scroll down to the new "Avatar" field. The plug-in will take care of cropping and sizing! + +1. Stores avatars in the "uploads" folder where all of your other media is kept. +2. Has a simple, native interface. +3. Fully supports Gravatar and default avatars if no local avatar is set for the user - but also allows you turn off Gravatar. +4. Generates the requested avatar size on demand (and stores the new size for efficiency), so it looks great, just like Gravatar! +5. Lets you decide whether lower privilege users (subscribers, contributors) can upload their own avatar. +6. Enables rating of local avatars, just like Gravatar. + +== Installation == + +1. Install easily with the WordPress plugin control panel or manually download the plugin and upload the extracted folder to the `/wp-content/plugins/` directory +1. Activate the plugin through the 'Plugins' menu in WordPress +1. If you only want users with file upload capabilities to upload avatars, check the applicable option under Settings > Discussion +1. Start uploading avatars by editing user profiles! + +Use avatars in your theme using WordPress' built in `get_avatar()` function: [http://codex.wordpress.org/Function_Reference/get_avatar](http://codex.wordpress.org/Function_Reference/get_avatar "get_avatar function") + +You can also use `get_simple_local_avatar()` (with the same arguments) to retreive local avatars a bit faster, but this will make your theme dependent on this plug-in. + +== Frequently Asked Questions == + += Does Simple Local Avatars collect personal data of website visitors? = + +No. Simple Local Avatars neither collects, stores, nor sends any PII data of visitors or avatar users on the host site or to 10up or other services. + +== Screenshots == + +1. Avatar upload field on a user profile page + +== Changelog == + += 2.7.6 - 2023-11-30 = +* **Added:** Check for minimum required PHP version before loading the plugin (props [@kmgalanakis](https://github.com/kmgalanakis), [@faisal-alvi](https://github.com/faisal-alvi) via [#226](https://github.com/10up/simple-local-avatars/pull/226)). +* **Added:** `pre_simple_local_avatar_url` filter to allow an avatar image to be short-circuited before Simple Local Avatars processes it (props [@johnbillion](https://github.com/johnbillion), [@peterwilsoncc](https://github.com/peterwilsoncc) via [#237](https://github.com/10up/simple-local-avatars/pull/237)). +* **Added:** Repo Automator GitHub Action (props [@iamdharmesh](https://github.com/iamdharmesh), [@faisal-alvi](https://github.com/faisal-alvi) via [#228](https://github.com/10up/simple-local-avatars/pull/228)). +* **Added:** E2E test for checking the front end of avatars (props [@Firestorm980](https://github.com/Firestorm980), [@iamdharmesh](https://github.com/iamdharmesh) via [#219](https://github.com/10up/simple-local-avatars/pull/219)). +* **Changed:** Bumped WordPress "tested up to" version 6.4 (props [@zamanq](https://github.com/zamanq), [@ankitguptaindia](https://github.com/ankitguptaindia), [@faisal-alvi](https://github.com/faisal-alvi), [@qasumitbagthariya](https://github.com/qasumitbagthariya) via [#230](https://github.com/10up/simple-local-avatars/pull/230), [#244](https://github.com/10up/simple-local-avatars/pull/244)). +* **Changed:** Update the Dependency Review GitHub Action to leverage our org-wide config file to check for GPL-compatible licenses (props [@jeffpaul](https://github.com/jeffpaul), [@faisal-alvi](https://github.com/faisal-alvi) via [#215](https://github.com/10up/simple-local-avatars/pull/215)). +* **Changed:** Documentation updates (props [@jeffpaul](https://github.com/jeffpaul), [@faisal-alvi](https://github.com/faisal-alvi) via [#242](https://github.com/10up/simple-local-avatars/pull/242)). +* **Fixed:** Address conflicts with other plugins and loading the media API (props [@EHLOVader](https://github.com/EHLOVader), [@dkotter](https://github.com/dkotter) via [#218](https://github.com/10up/simple-local-avatars/pull/218)). +* **Fixed:** Prevent PHP fatal error when switching from a multisite to single site installation (props [@ocean90](https://github.com/ocean90), [@ravinderk](https://github.com/ravinderk), [@faisal-alvi](https://github.com/faisal-alvi) via [#222](https://github.com/10up/simple-local-avatars/pull/222)). +* **Fixed:** Local avatar urls remain old after domain/host change (props [@jayedul](https://github.com/jayedul), [@ravinderk](https://github.com/ravinderk), [@jeffpaul](https://github.com/jeffpaul), [@faisal-alvi](https://github.com/faisal-alvi) via [#216](https://github.com/10up/simple-local-avatars/pull/216)). +* **Security:** Bump `word-wrap` from 1.2.3 to 1.2.4 (props [@dependabot](https://github.com/apps/dependabot), [@faisal-alvi](https://github.com/faisal-alvi) via [#223](https://github.com/10up/simple-local-avatars/pull/223)). +* **Security:** Bump `tough-cookie` from 4.1.2 to 4.1.3 (props [@dependabot](https://github.com/apps/dependabot), [@faisal-alvi](https://github.com/faisal-alvi) via [#225](https://github.com/10up/simple-local-avatars/pull/225)). +* **Security:** Bump `@cypress/request` from 2.88.10 to 3.0.0 (props [@dependabot](https://github.com/apps/dependabot), [@faisal-alvi](https://github.com/faisal-alvi) via [#225](https://github.com/10up/simple-local-avatars/pull/225), [#234](https://github.com/10up/simple-local-avatars/pull/234)). +* **Security:** Bump `cypress` from 11.2.0 to 13.2.0 (props [@dependabot](https://github.com/apps/dependabot), [@faisal-alvi](https://github.com/faisal-alvi), [@iamdharmesh](https://github.com/iamdharmesh) via [#234](https://github.com/10up/simple-local-avatars/pull/234), [#236](https://github.com/10up/simple-local-avatars/pull/236)). +* **Security:** Bump `postcss` from 8.4.21 to 8.4.31 (props [@dependabot](https://github.com/apps/dependabot), [@faisal-alvi](https://github.com/faisal-alvi) via [#238](https://github.com/10up/simple-local-avatars/pull/238)). +* **Security:** Bump `@babel/traverse` from 7.20.12 to 7.23.2 (props [@dependabot](https://github.com/apps/dependabot), [@faisal-alvi](https://github.com/faisal-alvi) via [#240](https://github.com/10up/simple-local-avatars/pull/240)). +* **Security:** Bump `@10up/cypress-wp-utils` version to 0.2.0 (props [@iamdharmesh](https://github.com/iamdharmesh), [@faisal-alvi](https://github.com/faisal-alvi) via [#236](https://github.com/10up/simple-local-avatars/pull/236)). +* **Security:** Bump `@wordpress/env` version from 5.2.0 to 8.7.0 (props [@iamdharmesh](https://github.com/iamdharmesh), [@faisal-alvi](https://github.com/faisal-alvi) via [#236](https://github.com/10up/simple-local-avatars/pull/236)). +* **Security:** Bump `cypress-mochawesome-reporter` version from 3.0.1 to 3.6.0 (props [@iamdharmesh](https://github.com/iamdharmesh), [@faisal-alvi](https://github.com/faisal-alvi) via [#236](https://github.com/10up/simple-local-avatars/pull/236)). + += 2.7.5 - 2023-05-15 = +* **Added:** Ajax loading animation during process of uploading and deleting local avatars (props [@lllopo](https://github.com/lllopo), [@BhargavBhandari90](https://github.com/BhargavBhandari90), [@faisal-alvi](https://github.com/faisal-alvi) via [#204](https://github.com/10up/simple-local-avatars/pull/204)). +* **Changed:** Avatar removal button text (props [@jayedul](https://github.com/jayedul), [@jeffpaul](https://github.com/jeffpaul), [@dkotter](https://github.com/dkotter), [@faisal-alvi](https://github.com/faisal-alvi) via [#208](https://github.com/10up/simple-local-avatars/pull/208)). +* **Changed:** WordPress "tested up to" version 6.2 (props [@jayedul](https://github.com/jayedul), [@faisal-alvi](https://github.com/faisal-alvi) via [#210](https://github.com/10up/simple-local-avatars/pull/210)). +* **Changed:** Run E2E tests on the zip generated by "Build release zip" action (props [@jayedul](https://github.com/jayedul), [@iamdharmesh](https://github.com/iamdharmesh), [@faisal-alvi](https://github.com/faisal-alvi) via [#205](https://github.com/10up/simple-local-avatars/pull/205)). +* **Security:** Bump `webpack` from 5.75.0 to 5.76.1 (props [@dependabot](https://github.com/dependabot), [@faisal-alvi](https://github.com/faisal-alvi) via [#207](https://github.com/10up/simple-local-avatars/pull/207)). + += 2.7.4 - 2023-02-23 = +* **Fixed:** Support passing `WP_User` to `get_avatar()` (props [@mattheu](https://github.com/mattheu), [@faisal-alvi](https://github.com/faisal-alvi) via [#193](https://github.com/10up/simple-local-avatars/pull/193)). +* **Fixed:** Remove trailing commas in function calls (props [@patrixer](https://github.com/patrixer), [@dkotter](https://github.com/dkotter), [@sekra24](https://github.com/sekra24), [@faisal-alvi](https://github.com/faisal-alvi) via [#196](https://github.com/10up/simple-local-avatars/pull/196)). +* **Security:** Bump `simple-git` from 3.15.1 to 3.16.0 (props [@dependabot](https://github.com/dependabot), [@faisal-alvi](https://github.com/faisal-alvi) via [#191](https://github.com/10up/simple-local-avatars/pull/191)). +* **Security:** Bump `http-cache-semantics` from 4.1.0 to 4.1.1 (props [@dependabot](https://github.com/dependabot), [@faisal-alvi](https://github.com/faisal-alvi) via [#197](https://github.com/10up/simple-local-avatars/pull/197)). + += 2.7.3 - 2023-01-16 = +* **Fixed:** Issue causing fatal errors when avatars used on front end of site (props [@Rottinator](https://github.com/Rottinator), [@peterwilsoncc](https://github.com/peterwilsoncc), [@ravinderk](https://github.com/ravinderk), [@faisal-alvi](https://github.com/faisal-alvi) via [#187](https://github.com/10up/simple-local-avatars/pull/187)). +* **Fixed:** Deprecation error in admin on PHP 8.0 and later (props [@Rottinator](https://github.com/Rottinator), [@peterwilsoncc](https://github.com/peterwilsoncc), [@ravinderk](https://github.com/ravinderk), [@faisal-alvi](https://github.com/faisal-alvi) via [#187](https://github.com/10up/simple-local-avatars/pull/187)). + += 2.7.2 - 2023-01-13 = +* **Added:** Filter hook `simple_local_avatars_upload_limit` to restrict image upload size & image file checking enhanced (props [@Shirkit](https://github.com/Shirkit), [@jayedul](https://github.com/jayedul), [@faisal-alvi](https://github.com/faisal-alvi), [@jeffpaul](https://github.com/jeffpaul) via [#171](https://github.com/10up/simple-local-avatars/pull/171)). +* **Added:** GitHub Actions summary on Cypress e2e test runs (props [@faisal-alvi](https://github.com/faisal-alvi), [@jeffpaul](https://github.com/jeffpaul), [@iamdharmesh](https://github.com/iamdharmesh) via [#174](https://github.com/10up/simple-local-avatars/pull/174)). +* **Changed:** Cypress integration migrated from 9.5.4 to 11.2.0 (props [@iamdharmesh](https://github.com/iamdharmesh), [@jayedul](https://github.com/jayedul), [@faisal-alvi](https://github.com/faisal-alvi) via [#172](https://github.com/10up/simple-local-avatars/pull/172)). +* **Fixed:** PHP8 support for `assign_new_user_avatar` (props [@lllopo](https://github.com/lllopo), [@mattwatsoncodes](https://github.com/mattwatsoncodes), [@faisal-alvi](https://github.com/faisal-alvi) via [#183](https://github.com/10up/simple-local-avatars/pull/183)). +* **Fixed:** Fixed the user profile language not respected issue (props [@dkotter](https://github.com/dkotter), [@lllopo](https://github.com/lllopo), [@faisal-alvi](https://github.com/faisal-alvi), [@jeffpaul](https://github.com/jeffpaul) via [#175](https://github.com/10up/simple-local-avatars/pull/175)). +* **Removed:** textdomain from the core strings and the function `update_avatar_ratings` as it's not required anymore (props [@dkotter](https://github.com/dkotter), [@lllopo](https://github.com/lllopo), [@faisal-alvi](https://github.com/faisal-alvi), [@jeffpaul](https://github.com/jeffpaul) via [#175](https://github.com/10up/simple-local-avatars/pull/175)). +* **Security:** Bump `json5` from 1.0.1 to 1.0.2 (props [@dependabot](https://github.com/dependabot), [@faisal-alvi](https://github.com/faisal-alvi) via [#182](https://github.com/10up/simple-local-avatars/pull/182)). + += 2.7.1 - 2022-12-08 = +* **Added:** Added missing files from the last release and changed the readme file to fix the bullet points and added fullstops. + += 2.7.0 - 2022-12-08 = +* **Added:** Added `Build release zip` GitHub Action (props [@peterwilsoncc](https://github.com/peterwilsoncc), [@faisal-alvi](https://github.com/faisal-alvi) via [#168](https://github.com/10up/simple-local-avatars/pull/168)). +* **Changed:** Set plugin defaults on `wp_initialize_site` instead of deprecated action `wpmu_new_blog` (props [@kadamwhite](https://github.com/kadamwhite), [@faisal-alvi](https://github.com/faisal-alvi) via [#156](https://github.com/10up/simple-local-avatars/pull/156)). +* **Changed:** Support Level from Active to Stable (props [@jeffpaul](https://github.com/jeffpaul), [@dkotter](https://github.com/dkotter) via [#159](https://github.com/10up/simple-local-avatars/pull/159)). +* **Changed:** Build tools: Allow PHPCS installer plugin to run without prompting user (props [@peterwilsoncc](https://github.com/peterwilsoncc), [@jeffpaul](https://github.com/jeffpaul) via [#164](https://github.com/10up/simple-local-avatars/pull/164)). +* **Changed:** WP tested up to version bump to 6.1 (props [@peterwilsoncc](https://github.com/peterwilsoncc), [@faisal-alvi](https://github.com/faisal-alvi) via [#165](https://github.com/10up/simple-local-avatars/pull/165)). +* **Fixed:** Non admin users can not crop avatar (props [@jayedul](https://github.com/jayedul), [@faisal-alvi](https://github.com/faisal-alvi), [@zamanq](https://github.com/zamanq), [@dkotter](https://github.com/dkotter), [@jeffpaul](https://github.com/jeffpaul) via [#155](https://github.com/10up/simple-local-avatars/pull/155)). +* **Security:** Bump `@wordpress/env` from 4.9.0 to 5.2.0 and `got` from 10.7.0 to 11.8.5 (props [@dependabot](https://github.com/dependabot), [@faisal-alvi](https://github.com/faisal-alvi) via [#153](https://github.com/10up/simple-local-avatars/pull/153)). +* **Security:** Bump `loader-utils` from 2.0.2 to 2.0.3 (props [@dependabot](https://github.com/dependabot), [@faisal-alvi](https://github.com/faisal-alvi) via [#160](https://github.com/10up/simple-local-avatars/pull/160)). +* **Security:** Bump `loader-utils` from 2.0.3 to 2.0.4 (props [@dependabot](https://github.com/dependabot), [@peterwilsoncc](https://github.com/peterwilsoncc) via [#162](https://github.com/10up/simple-local-avatars/pull/162)). +* **Security:** Bump `simple-git` from 3.9.0 to 3.15.1 (props [@dependabot](https://github.com/dependabot) via [#176](https://github.com/10up/simple-local-avatars/pull/176)). + += 2.6.0 - 2022-09-13 = +**Note that this release bumps the minimum required version of WordPress from 4.6 to 5.7 and PHP from 5.6 to 7.4.** + +* **Added:** If a default avatar image is used, ensure that outputs alt text. This will either be default text (Avatar photo) or the alt text from the uploaded default image (props [@dkotter](https://github.com/dkotter), [@faisal-alvi](https://github.com/faisal-alvi) via [#147](https://github.com/10up/simple-local-avatars/pull/147)) +* **Added:** Two hooks, `simple_local_avatar_updated` and `simple_local_avatar_deleted`, (props [@t-lock](https://github.com/t-lock), [@faisal-alvi](https://github.com/faisal-alvi), [@dkotter](https://github.com/dkotter) via [#149](https://github.com/10up/simple-local-avatars/pull/149)) +* **Changed:** Bump minimum required version of WordPress from 4.6 to 5.7 (props [@vikrampm1](https://github.com/vikrampm1), [@faisal-alvi](https://github.com/faisal-alvi), [@cadic](https://github.com/cadic) via [#143](https://github.com/10up/simple-local-avatars/pull/143)). +* **Changed:** Bump minimum required version of PHP from 5.6 to 7.4 (props [@vikrampm1](https://github.com/vikrampm1), [@faisal-alvi](https://github.com/faisal-alvi), [@cadic](https://github.com/cadic) via [#143](https://github.com/10up/simple-local-avatars/pull/143)). +* **Changed:**The plugin is now available via Composer without any additional steps required (props [@faisal-alvi](https://github.com/faisal-alvi), [@kovshenin](https://github.com/kovshenin), [@jeffpaul](https://github.com/jeffpaul) via [#145](https://github.com/10up/simple-local-avatars/pull/145)) +* **Security:** Bump `terser` from 5.14.1 to 5.14.2 (props [@dependabot](https://github.com/dependabot), [@faisal-alvi](https://github.com/faisal-alvi) via [#142](https://github.com/10up/simple-local-avatars/pull/142)) + += 2.5.0 - 2022-06-24 = +* **Added:** Skip cropping button (props [@dkotter](https://github.com/dkotter), [@faisal-alvi](https://github.com/faisal-alvi), [@cadic](https://github.com/cadic), [@jeffpaul](https://github.com/jeffpaul), [@dinhtungdu](https://github.com/dinhtungdu) via [#130](https://github.com/10up/simple-local-avatars/pull/130))! +* **Added:** Updated the button name from "Skip Crop" to "Default Crop" only on the edit profile page (props [@faisal-alvi](https://github.com/faisal-alvi), [@peterwilsoncc](https://github.com/peterwilsoncc) via [#136](https://github.com/10up/simple-local-avatars/pull/136)). +* **Added:** If an image used for a local avatar has alt text assigned, ensure that alt text is used when rendering the image (props [@dkotter](https://github.com/dkotter), [@pixelloop](https://github.com/pixelloop), [@faisal-alvi](https://github.com/faisal-alvi) via [#127](https://github.com/10up/simple-local-avatars/pull/127)). +* **Added:** Support for bbPress by loading the JS at FE on the profile edit page (props [@foliovision](https://github.com/foliovision), [@faisal-alvi](https://github.com/faisal-alvi), [@iamdharmesh](https://github.com/iamdharmesh) via [#134](https://github.com/10up/simple-local-avatars/pull/134)). +* **Added:** Cypress E2E tests (props [@faisal-alvi](https://github.com/faisal-alvi), [@vikrampm1](https://github.com/vikrampm1), [@Sidsector9](https://github.com/Sidsector9) via [#115](https://github.com/10up/simple-local-avatars/pull/115)). +* **Fixed:** Broken avatar URLs for network-configured shared avatars with non-standard thumbnail sizes (props [@vladolaru](https://github.com/vladolaru), [@faisal-alvi](https://github.com/faisal-alvi) via [#125](https://github.com/10up/simple-local-avatars/pull/125)). +* **Fixed:** `HTTP_REFERER` is null and causing PHP warning (props [@alireza-salehi](https://github.com/alireza-salehi), [@faisal-alvi](https://github.com/faisal-alvi), [@peterwilsoncc](https://github.com/peterwilsoncc) via [#129](https://github.com/10up/simple-local-avatars/pull/129)). + += 2.4.0 - 2022-05-10 = +* **Added:** Ability to set a default avatar. (props [@mehulkaklotar](https://github.com/mehulkaklotar), [@jeffpaul](https://github.com/jeffpaul), [@dinhtungdu](https://github.com/dinhtungdu), [@faisal-alvi](https://github.com/faisal-alvi) via [#96](https://github.com/10up/simple-local-avatars/pull/96)). +* **Fixed:** Correct plugin name in changelog. (props [@grappler](https://github.com/grappler), [@jeffpaul](https://github.com/jeffpaul) via [#117](https://github.com/10up/simple-local-avatars/pull/117)). +* **Fixed:** Avatar cache not being cleared. (props [@thefrosty](https://github.com/thefrosty), [@jeffpaul](https://github.com/jeffpaul), [@faisal-alvi](https://github.com/faisal-alvi), [@peterwilsoncc](https://github.com/peterwilsoncc) via [#118](https://github.com/10up/simple-local-avatars/pull/118) & [#120](https://github.com/10up/simple-local-avatars/pull/120)). +* **Security:** Dev dependency `@wordpress/scripts` upgraded to resolve deeper level dependency security issues. (props [@jeffpaul](https://github.com/jeffpaul), [@faisal-alvi](https://github.com/faisal-alvi), [@cadic](https://github.com/cadic) via [#119](https://github.com/10up/simple-local-avatars/pull/119)). + += 2.3.0 - 2022-04-25 = +* **Added:** Crop screen (props [@jeffpaul](https://github.com/jeffpaul), [@helen](https://github.com/helen), [@ajmaurya99](https://github.com/ajmaurya99), [@Antonio-Laguna](https://github.com/Antonio-Laguna), [@faisal-alvi](https://github.com/faisal-alvi)). +* **Added:** Avatar preview for Subscribers (props [@ankitguptaindia](https://github.com/ankitguptaindia), [@dinhtungdu](https://github.com/dinhtungdu), [@dkotter](https://github.com/dkotter)). +* **Added:** More robust multisite support and shared avatar setting (props [@adamsilverstein](https://github.com/adamsilverstein), [@helen](https://github.com/helen), [@jeffpaul](https://github.com/jeffpaul), [@dkotter](https://github.com/dkotter), [@faisal-alvi](https://github.com/faisal-alvi), [@holle75](https://github.com/holle75)). +* **Added:** Settings link to plugin action links (props [@rahulsprajapati](https://github.com/rahulsprajapati), [@jeffpaul](https://github.com/jeffpaul), [@iamdharmesh](https://github.com/iamdharmesh)). +* **Added:** Dashboard setting and WP-CLI command to migrate avatars from [WP User Avatar](https://wordpress.org/plugins/wp-user-avatar/) (props [@jeffpaul](https://github.com/jeffpaul), [@claytoncollie](https://github.com/claytoncollie), [@helen](https://github.com/helen), [@faisal-alvi](https://github.com/faisal-alvi)). +* **Added:** Option to clear cache of user meta to remove image sizes that do not exist (props [@jeffpaul](https://github.com/jeffpaul), [@ituk](https://github.com/ituk), [@dinhtungdu](https://github.com/dinhtungdu), [@sparkbold](https://github.com/sparkbold), [@thrijith](https://github.com/thrijith)). +* **Added:** Package file (props [@faisal-alvi](https://github.com/faisal-alvi), [@jeffpaul](https://github.com/jeffpaul), [@claytoncollie](https://github.com/claytoncollie), [@cadic](https://github.com/cadic)). +* **Added:** PHP Unit Tests (props [@faisal-alvi](https://github.com/faisal-alvi), [@iamdharmesh](https://github.com/iamdharmesh)). +* **Added:** "No Response" GitHub Action (props [@jeffpaul](https://github.com/jeffpaul)). +* **Changed:** Bump WordPress "tested up to" version to 5.9 (props [@jeffpaul](https://github.com/jeffpaul), [@ankitguptaindia](https://github.com/ankitguptaindia), [@dinhtungdu](https://github.com/dinhtungdu), [@phpbits](https://github.com/phpbits)). +* **Changed:** Bump WordPress "tested up to" version to 6.0 (props [@ajmaurya99](https://github.com/ajmaurya99) via [#110](https://github.com/10up/simple-local-avatars/pull/110)). +* **Changed:** Format admin script (props [@thrijith](https://github.com/thrijith), [@dinhtungdu](https://github.com/dinhtungdu)). +* **Fixed:** Media ID as string in REST API (props [@diodoe](https://github.com/diodoe), [@dinhtungdu](https://github.com/dinhtungdu), [@dkotter](https://github.com/dkotter)). +* **Fixed:** Avatar rating text is not translated properly if a user has a custom language Set (props [@ActuallyConnor](https://github.com/ActuallyConnor), [@faisal-alvi](https://github.com/faisal-alvi)). +* **Security:** PHP 8 compatibility (props [@faisal-alvi](https://github.com/faisal-alvi), [@dkotter](https://github.com/dkotter), [@Sidsector9](https://github.com/Sidsector9)). +* **Security:** Bump `rmccue/requests` from 1.7.0 to 1.8.0 (props [dependabot@](https://github.com/dependabot)). +* **Security:** Bump `nanoid` from 3.1.28 to 3.2.0 (props [dependabot@](https://github.com/dependabot)). +* **Security:** Bump `minimist` from 1.2.5 to 1.2.6 (props [dependabot@](https://github.com/dependabot)). + += 2.2.0 - 2020-10-27 = +* **Added:** `$args` parameter to `get_simple_local_avatar` function (props [@dinhtungdu](https://profiles.wordpress.org/dinhtungdu/), [@heyjones](https://github.com/heyjones), [@dkotter](https://profiles.wordpress.org/dkotter/), [@sumnercreations](https://github.com/sumnercreations), [@dshanske](https://profiles.wordpress.org/dshanske/)). +* **Added:** `Simple_Local_Avatars::get_avatar_data()`, `Simple_Local_Avatars::get_simple_local_avatar_url()`, and `Simple_Local_Avatars::get_default_avatar_url()` methods (props [@dinhtungdu](https://profiles.wordpress.org/dinhtungdu/), [@heyjones](https://github.com/heyjones), [@dkotter](https://profiles.wordpress.org/dkotter/), [@sumnercreations](https://github.com/sumnercreations), [@dshanske](https://profiles.wordpress.org/dshanske/)). +* **Added:** Ability to retrieve avatar with `WP_Post` object (props [@oscarssanchez](https://profiles.wordpress.org/oscarssanchez), [@blobaugh](https://profiles.wordpress.org/blobaugh)). +* **Added:** class and ID to Avatar section on Profile Page to allow easier styling (props [@dinhtungdu](https://profiles.wordpress.org/dinhtungdu/)). +* **Added:** [WP Acceptance](https://github.com/10up/wpacceptance/) test coverage (props [@dinhtungdu](https://profiles.wordpress.org/dinhtungdu/)). +* **Changed:** Switched to `pre_get_avatar_data` filter (props [@dinhtungdu](https://profiles.wordpress.org/dinhtungdu/), [@heyjones](https://github.com/heyjones), [@dkotter](https://profiles.wordpress.org/dkotter/), [@sumnercreations](https://github.com/sumnercreations), [@dshanske](https://profiles.wordpress.org/dshanske/)). +* **Changed:** `assign_new_user_avatar` function to public (props [@tripflex](https://profiles.wordpress.org/tripflex/)). +* **Changed:** Split the main class into its own file, added unit tests, and set up testing GitHub action (props [@dinhtungdu](https://profiles.wordpress.org/dinhtungdu/), [@helen](https://profiles.wordpress.org/helen/), [@stevegrunwell](https://profiles.wordpress.org/stevegrunwell/)). +* **Changed:** New plugin banner and icon (props [@JackieKjome](https://profiles.wordpress.org/jackiekjome/)). +* **Changed:** Bump WordPress version "tested up to" 5.5 (props [@Waka867](https://github.com/Waka867), [@tmoorewp](https://profiles.wordpress.org/tmoorewp), [@jeffpaul](https://profiles.wordpress.org/jeffpaul), [@dinhtungdu](https://profiles.wordpress.org/dinhtungdu/)). +* **Changed:** GitHub Actions from HCL to YAML workflow syntax (props [@jeffpaul](https://profiles.wordpress.org/jeffpaul)). +* **Changed:** Documentation updates (props [@jeffpaul](https://profiles.wordpress.org/jeffpaul)). +* **Fixed:** Initialize `Simple_Local_Avatars` on the `$simple_local_avatars` global, enabling bundling plugin with composer (props [@pauldewouters](https://profiles.wordpress.org/pauldewouters/), [@adamsilverstein](https://profiles.wordpress.org/adamsilverstein)). +* **Removed:** `get_avatar` function that overrides the core function (props [@dinhtungdu](https://profiles.wordpress.org/dinhtungdu/), [@heyjones](https://github.com/heyjones), [@dkotter](https://profiles.wordpress.org/dkotter/), [@sumnercreations](https://github.com/sumnercreations), [@dshanske](https://profiles.wordpress.org/dshanske/)). + += 2.1.1 - 2019-05-07 = +* Fixed: Do not delete avatars just because they don't exist on the local filesystem. This was occasionally dumping avatars when WordPress uploads were stored elsewhere, e.g. a cloud service. + += 2.1 - 2018-10-24 = +* *New:* All avatar uploads now go into the media library. Don't worry - users without the ability to upload files cannot otherwise see the contents of your media library. This allows local avatars to respect other functionality your site may have around uploaded images, such as external hosting. +* *New:* REST API support for getting and updating. +* *New:* Use .org language packs rather than bundling translations. +* *Fixed:* Avoid an `ArgumentCountError`. +* *Fixed:* A couple of internationalization issues. + += 2.0 - 2013-06-02 = +* Choose or upload an avatar from the media library (for users with appropriate capabilities)! +* Local avatars are rated for appropriateness, just like Gravatar +* A new setting under Discussion enables administrators to turn off Gravatar (only use local avatars) +* Delete the local avatar with a single button click (like everywhere else in WordPress) +* Uploaded avatar file names are appended with the timestamp, addressing browser image caching issues +* New developer filter for preventing automatic rescaling: simple_local_avatars_dynamic_resize +* New developer filter for limiting upload size: simple_local_avatars_upload_limit +* Upgraded functions deprecated since WordPress 3.5 +* Fixed translations not working on front end (although translations are now a bit out of date...) +* Hungarian translation added (needs further updating again with new version) +* Assorted refactoring / improvements under the hood + += 1.3.1 - 2011-12-29 = +* Brazilian Portuguese and Belarusian translations +* Bug fixes (most notably correct naming of image files based on user display name) +* Optimization for WordPress 3.2 / 3.3 (substitutes deprecated function) + += 1.3 - 2011-09-22 = +* Avatar file name saved as "user-display-name_avatar" (or other image extension) +* Russian localization added +* Assorted minor code optimizations + += 1.2.4 - 2011-07-02 = +* Support for front end avatar uploads (e.g. Theme My Profile) + += 1.2.3 - 2011-04-04 = +* Russian localization + += 1.2.2 - 2011-03-25 = +* Fix for avatars uploaded pre-1.2.1 having a broken path after upgrade + += 1.2.1 - 2011-01-26 = +* French localization +* Simplify uninstall code + += 1.2 - 2011-01-26 = +* Fix path issues on some IIS servers (resulting in missing avatar images) +* Fix rare uninstall issues related to deleted avatars +* Spanish localization +* Other minor under the hood optimizations + += 1.1.3 - 2011-01-20 = +* Properly deletes old avatars upon changing avatar +* Fixes "foreach" warning in debug mode when updating avatar image + += 1.1.2 - 2011-01-18 = +* Norwegian localization + += 1.1.1 - 2011-01-18 = +* Italian localization + += 1.1 - 2011-01-18 = +* All users (regardless of capabilities) can upload avatars by default. To limit avatar uploading to users with upload files capabilities (Authors and above), check the applicable option under Settings > Discussion. This was the default behavior in 1.0. +* Localization support; German included + += 1.0 - 2011-01-18 = +* Initial release. + +== Upgrade Notice == + += 2.6.0 = +**Note that this release bumps the minimum required version of WordPress from 4.6 to 5.7 and PHP from 5.6 to 7.4.** + += 2.1 = +*Important note:* All avatar uploads now go into the media library. Don't worry - users without the ability to upload files cannot otherwise see the contents of your media library. This allows local avatars to respect other functionality your site may have around uploaded images, such as external hosting. + += 2.0 = +Upgraded to take advantage of *WordPress 3.5 and newer*. Does not support older versions! This has also *not* been tested with front end profile plug-ins - feedback welcome. Note that several language strings have been added or modified - revised translations would be welcome! + += 1.3.1 = +Like WordPress 3.2, now *REQUIRES* PHP 5.2 or newer. diff --git a/wp-content/upgrade-temp-backup/plugins/simple-local-avatars/simple-local-avatars.php b/wp-content/upgrade-temp-backup/plugins/simple-local-avatars/simple-local-avatars.php new file mode 100644 index 00000000..b05ea1bc --- /dev/null +++ b/wp-content/upgrade-temp-backup/plugins/simple-local-avatars/simple-local-avatars.php @@ -0,0 +1,120 @@ +=' ); +} + +// Try to load the plugin files, ensuring our PHP version is met first. +if ( ! site_meets_php_requirements() ) { + add_action( + 'admin_notices', + function() { + ?> +
+

+ +

+
+ tag for the user's avatar + */ +function get_simple_local_avatar( $id_or_email, $size = 96, $default = '', $alt = '', $args = array() ) { + return apply_filters( 'simple_local_avatar', get_avatar( $id_or_email, $size, $default, $alt, $args ) ); +} + +register_uninstall_hook( __FILE__, 'simple_local_avatars_uninstall' ); +/** + * On uninstallation, remove the custom field from the users and delete the local avatars + */ +function simple_local_avatars_uninstall() { + $simple_local_avatars = new Simple_Local_Avatars(); + $users = get_users( + array( + 'meta_key' => 'simple_local_avatar', + 'fields' => 'ids', + ) + ); + + foreach ( $users as $user_id ) : + $simple_local_avatars->avatar_delete( $user_id ); + endforeach; + + delete_option( 'simple_local_avatars' ); + delete_option( 'simple_local_avatars_migrations' ); +}