diff --git a/wp-content/plugins/simple-local-avatars/dist/simple-local-avatars.asset.php b/wp-content/plugins/simple-local-avatars/dist/simple-local-avatars.asset.php new file mode 100644 index 00000000..f014bd08 --- /dev/null +++ b/wp-content/plugins/simple-local-avatars/dist/simple-local-avatars.asset.php @@ -0,0 +1 @@ + array(), 'version' => '743de2221cd3b95dfce2abc7e2a95842'); \ No newline at end of file diff --git a/wp-content/plugins/simple-local-avatars/dist/simple-local-avatars.js b/wp-content/plugins/simple-local-avatars/dist/simple-local-avatars.js new file mode 100644 index 00000000..9b3c8504 --- /dev/null +++ b/wp-content/plugins/simple-local-avatars/dist/simple-local-avatars.js @@ -0,0 +1 @@ +!function(){let a,e,t,r,i,l,s,o,n,c=!1;function p(a){void 0===e&&(t=document.getElementById("simple-local-avatar-ratings"),e=jQuery(document.getElementById("simple-local-avatar-spinner")),r=document.getElementById("simple-local-avatar-photo"),i=jQuery(t).closest("form").find("input[type=submit]")),"unlock"===a?(c=!1,i.removeAttr("disabled"),e.hide()):(c=!0,i.attr("disabled","disabled"),e.show())}function m(a,e){const t=e.get("control"),r=a.get("width"),i=a.get("height");let l=parseInt(t.params.width,10),s=parseInt(t.params.height,10);const o=l/s;e.set("canSkipCrop",!t.mustBeCropped(!1,!1,l,s,r,i));const n=l,c=s;r/i>o?(s=i,l=s*o):(l=r,s=l/o);const p=(r-l)/2,m=(i-s)/2;return{handles:!0,keys:!0,instance:!0,persistent:!0,imageWidth:r,imageHeight:i,minWidth:n>l?l:n,minHeight:c>s?s:c,x1:p,y1:m,x2:l+p,y2:s+m,aspectRatio:`${l}:${s}`}}function d(a,e,i,l){const s={};s.url=a,s.thumbnail_url=a,s.timestamp=_.now(),e&&(s.attachment_id=e),i&&(s.width=i),l&&(s.height=l),p("lock"),jQuery.post(ajaxurl,{action:"assign_simple_local_avatar_media",media_id:e,user_id:i10n_SimpleLocalAvatars.user_id,_wpnonce:i10n_SimpleLocalAvatars.mediaNonce}).done((function(a){""!==a&&(r.innerHTML=a,jQuery("#simple-local-avatar-remove").show(),t.disabled=!1)})).always((function(){p("unlock")}))}jQuery(document).ready((function(e){s=e("#simple-local-avatar"),l=e("#simple-local-avatar-photo img"),n=l.attr("src"),t=e("#simple-local-avatar-ratings"),r=e("#simple-local-avatar-photo"),e("#simple-local-avatar-media").on("click",(function(e){if(e.preventDefault(),c)return;const i={id:"control-id",params:{flex_width:!1,flex_height:!1,width:200,height:200},mustBeCropped:function(a,e,t,r,i,l){return i!==t||l!==r}};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:m,control:i})]}),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"),r=a.get("height");d(e,a.id,t,r)})),a.on("select",(function(){const e=a.state().get("selection").first().toJSON();var l;i.params.width!==e.width||i.params.height!==e.height||i.params.flex_width||i.params.flex_height?a.setState("cropper"):(e.dst_width=e.width,e.dst_height=e.height,l=e,p("lock"),jQuery.post(ajaxurl,{action:"assign_simple_local_avatar_media",media_id:l.id,user_id:i10n_SimpleLocalAvatars.user_id,_wpnonce:i10n_SimpleLocalAvatars.mediaNonce}).done((function(a){""!==a&&(r.innerHTML=a,jQuery("#simple-local-avatar-remove").show(),t.disabled=!1,p("unlock"))})).always((function(){p("unlock")})),a.close())})),a.open()})),e("#simple-local-avatar-remove").on("click",(function(a){a.preventDefault(),c||(p("lock"),e.get(ajaxurl,{action:"remove_simple_local_avatar",user_id:i10n_SimpleLocalAvatars.user_id,_wpnonce:i10n_SimpleLocalAvatars.deleteNonce}).done((function(a){""!==a&&(r.innerHTML=a,e("#simple-local-avatar-remove").hide(),t.disabled=!0)})).always((function(){p("unlock")})))})),s.on("change",(function(a){l.attr("srcset",""),l.attr("height","auto"),URL.revokeObjectURL(o),a.target.files.length>0?(o=URL.createObjectURL(a.target.files[0]),l.attr("src",o)):l.attr("src",n)})),e(document.getElementById("simple-local-avatars-migrate-from-wp-user-avatar")).on("click",(function(a){a.preventDefault(),jQuery.post(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 i=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 f(){i.find("span").remove(),i.removeClass("disabled")}function _(a,t){t.step=a,e.ajax({url:ajaxurl,dataType:"json",data:t,method:"POST",success:function(a){if(a.success)return"done"===a.data.step?(u.text(a.data.message),f()):(u.text(a.data.message),_(parseInt(a.data.step,10),t)),!1;u.text(i10n_SimpleLocalAvatars.clearCacheError),f()},error:function(){u.text(i10n_SimpleLocalAvatars.clearCacheError),f()}})}if(i.on("click",(function(a){a.preventDefault(),i.addClass("disabled"),i.append(''),_(1,{action:"sla_clear_user_cache",nonce:i10n_SimpleLocalAvatars.cacheNonce})})),v.click((function(a){a.preventDefault();var t=e(this),r=wp.media({title:i10n_SimpleLocalAvatars.insertMediaTitle,multiple:!1,library:{type:"image"}}).open().on("select",(function(a){var e,i,l,s=r.state().get("selection").first(),o=null===(e=s=s.toJSON())||void 0===e||null===(i=e.sizes)||void 0===i||null===(l=i.thumbnail)||void 0===l?void 0:l.url;void 0===o&&(o=s.url);var n=t.parent().find("img.avatar");n.show(),n.attr("src",o),n.attr("srcset",o),g.val(o),h.val(s.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/plugins/simple-local-avatars/includes/class-simple-local-avatars.php b/wp-content/plugins/simple-local-avatars/includes/class-simple-local-avatars.php index d5856284..318d0f0d 100644 --- a/wp-content/plugins/simple-local-avatars/includes/class-simple-local-avatars.php +++ b/wp-content/plugins/simple-local-avatars/includes/class-simple-local-avatars.php @@ -1,17 +1,73 @@ add_hooks(); + $this->options = (array) get_option( 'simple_local_avatars' ); + $this->user_key = 'simple_local_avatar'; + $this->rating_key = 'simple_local_avatar_rating'; $this->avatar_ratings = array( 'G' => __( 'G — Suitable for all audiences', 'simple-local-avatars' ), 'PG' => __( 'PG — Possibly offensive, usually for audiences 13 and above', 'simple-local-avatars' ), @@ -19,14 +75,35 @@ class Simple_Local_Avatars { 'X' => __( 'X — Even more mature than above', 'simple-local-avatars' ), ); - $this->add_hooks(); + if ( + ! $this->is_avatar_shared() // Are we sharing avatars? + && ( + ( // And either an ajax request not in the network admin. + defined( 'DOING_AJAX' ) && DOING_AJAX + && ! 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() { + + 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' ) ); @@ -42,6 +119,104 @@ class Simple_Local_Avatars { 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' ) ); + add_action( 'wpmu_new_blog', array( $this, 'set_defaults' ) ); + } + + /** + * 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() // Are we on multisite. + && ! isset( $this->options['shared'] ) // And our shared option doesn't exist. + || ( + isset( $this->options['shared'] ) // Or our shared option is set. + && 1 === $this->options['shared'] + ) + ) { + 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; } /** @@ -104,12 +279,13 @@ class Simple_Local_Avatars { public function get_simple_local_avatar_url( $id_or_email, $size ) { if ( is_numeric( $id_or_email ) ) { $user_id = (int) $id_or_email; - } elseif ( is_string( $id_or_email ) && ( $user = get_user_by( 'email', $id_or_email ) ) ) { - $user_id = $user->ID; } 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_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 : ''; } if ( empty( $user_id ) ) { @@ -117,17 +293,18 @@ class Simple_Local_Avatars { } // Fetch local avatar from meta and make sure it's properly set. - $local_avatars = get_user_meta( $user_id, 'simple_local_avatar', true ); + $local_avatars = get_user_meta( $user_id, $this->user_key, true ); if ( empty( $local_avatars['full'] ) ) { return ''; } // check rating - $avatar_rating = get_user_meta( $user_id, 'simple_local_avatar_rating', true ); - if ( ! empty( $avatar_rating ) && 'G' !== $avatar_rating && ( $site_rating = get_option( 'avatar_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 ); - $avatar_rating_weight = array_search( $avatar_rating, $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 ''; } @@ -135,8 +312,20 @@ class Simple_Local_Avatars { // handle "real" media if ( ! empty( $local_avatars['media_id'] ) ) { + // If using shared avatars, make sure we validate the URL on the main site. + if ( $this->is_avatar_shared() ) { + $origin_blog_id = isset( $local_avatars['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 = get_attached_file( $local_avatars['media_id'] ) ) { + if ( ! $avatar_full_path ) { return ''; } } @@ -171,7 +360,7 @@ class Simple_Local_Avatars { } // save updated avatar sizes - update_user_meta( $user_id, 'simple_local_avatar', $local_avatars ); + update_user_meta( $user_id, $this->user_key, $local_avatars ); endif; } @@ -208,6 +397,12 @@ class Simple_Local_Avatars { $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}"; } @@ -220,7 +415,8 @@ class Simple_Local_Avatars { */ public function admin_init() { // upgrade pre 2.0 option - if ( $old_ops = get_option( 'simple_local_avatars_caps' ) ) { + $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 ) ); } @@ -236,8 +432,9 @@ class Simple_Local_Avatars { 'discussion', 'avatars', array( - 'key' => 'only', - 'desc' => __( 'Only allow local avatars (still uses Gravatar for default avatars)', 'simple-local-avatars' ), + 'class' => 'simple-local-avatars', + 'key' => 'only', + 'desc' => __( 'Only allow local avatars (still uses Gravatar for default avatars)', 'simple-local-avatars' ), ) ); add_settings_field( @@ -247,10 +444,175 @@ class Simple_Local_Avatars { 'discussion', 'avatars', array( - 'key' => 'caps', - 'desc' => __( 'Only allow users with file upload capabilities to upload local avatars (Authors and above)', 'simple-local-avatars' ), + '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' ); - $script_name_append = ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '.dev' : ''; - wp_enqueue_script( 'simple-local-avatars', plugins_url( '', dirname( __FILE__ ) ) . '/simple-local-avatars' . $script_name_append . '.js', array( 'jquery' ), false, true ); + 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( - 'user_id' => $user_id, - 'insertMediaTitle' => __( 'Choose an Avatar', 'simple-local-avatars' ), - 'insertIntoPost' => __( 'Set as avatar', 'simple-local-avatars' ), - 'deleteNonce' => $this->remove_nonce, - 'mediaNonce' => wp_create_nonce( 'assign_simple_local_avatar_nonce' ), + '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' ), ) ); } @@ -295,6 +674,11 @@ class Simple_Local_Avatars { 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; } @@ -307,21 +691,51 @@ class Simple_Local_Avatars { $args = wp_parse_args( $args, array( - 'key' => '', - 'desc' => '', + 'key' => '', + 'desc' => '', + 'default' => 0, ) ); - if ( empty( $this->options[ $args['key'] ] ) ) { - $this->options[ $args['key'] ] = 0; + if ( ! isset( $this->options[ $args['key'] ] ) ) { + $this->options[ $args['key'] ] = $args['default']; } - echo ' + 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' ) + ); } /** @@ -330,92 +744,91 @@ class Simple_Local_Avatars { * @param object $profileuser User object */ public function edit_user_profile( $profileuser ) { - ?> -
-

+ ?> +
+

- - - - - + +
- ID ); - remove_filter( 'pre_option_avatar_rating', '__return_null' ); - ?> - - options['caps'] ); - } + + + + + - - - - + + + + - -
+ ID ) ); + remove_filter( 'pre_option_avatar_rating', '__return_null' ); + ?> + + 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'; - } + 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 ) ); ?>> + + update_avatar_ratings(); - foreach ( $this->avatar_ratings as $key => $rating ) : - echo "\n\t
"; - endforeach; - ?> -

-
- - 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 + $this->avatar_delete( $user_id ); // delete old images if successful. $meta_value = array(); // set the new avatar - if ( is_int( $url_or_media_id ) ) { + if ( is_int( $url_or_media_id + 0 ) ) { $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['full'] = $url_or_media_id; + $meta_value['blog_id'] = get_current_blog_id(); - update_user_meta( $user_id, 'simple_local_avatar', $meta_value ); // save user information (overwriting old) + update_user_meta( $user_id, $this->user_key, $meta_value ); // save user information (overwriting old). } /** @@ -466,6 +880,7 @@ class Simple_Local_Avatars { if ( false !== strpos( $_FILES['simple-local-avatar']['name'], '.php' ) ) { $this->avatar_upload_error = __( 'For security reasons, the extension ".php" cannot be in your file name.', 'simple-local-avatars' ); add_action( 'user_profile_update_errors', array( $this, 'user_profile_update_errors' ) ); + return; } @@ -498,6 +913,7 @@ class Simple_Local_Avatars { 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; } @@ -506,12 +922,12 @@ class Simple_Local_Avatars { endif; // Handle ratings - if ( isset( $avatar_id ) || $avatar = get_user_meta( $user_id, 'simple_local_avatar', true ) ) { + 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, 'simple_local_avatar_rating', $_POST['simple_local_avatar_rating'] ); + update_user_meta( $user_id, $this->rating_key, $_POST['simple_local_avatar_rating'] ); } } @@ -539,7 +955,7 @@ class Simple_Local_Avatars { $this->avatar_delete( $user_id ); // delete old images if successful if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) { - echo get_simple_local_avatar( $user_id ); + echo wp_kses_post( get_simple_local_avatar( $user_id ) ); } } @@ -565,7 +981,7 @@ class Simple_Local_Avatars { $this->assign_new_user_avatar( $media_id, $user_id ); } - echo get_simple_local_avatar( $user_id ); + echo wp_kses_post( get_simple_local_avatar( $user_id ) ); die; } @@ -576,7 +992,7 @@ class Simple_Local_Avatars { * @param int $user_id User ID. */ public function avatar_delete( $user_id ) { - $old_avatars = (array) get_user_meta( $user_id, 'simple_local_avatar', true ); + $old_avatars = (array) get_user_meta( $user_id, $this->user_key, true ); if ( empty( $old_avatars ) ) { return; @@ -599,8 +1015,8 @@ class Simple_Local_Avatars { } } - delete_user_meta( $user_id, 'simple_local_avatar' ); - delete_user_meta( $user_id, 'simple_local_avatar_rating' ); + delete_user_meta( $user_id, $this->user_key ); + delete_user_meta( $user_id, $this->rating_key ); } /** @@ -613,13 +1029,13 @@ class Simple_Local_Avatars { */ 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() ); + $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++; + $number ++; } return $name . $ext; @@ -658,10 +1074,11 @@ class Simple_Local_Avatars { * @param object $user User object */ public function get_avatar_rest( $user ) { - $local_avatar = get_user_meta( $user['id'], 'simple_local_avatar', true ); + $local_avatar = get_user_meta( $user['id'], $this->user_key, true ); if ( empty( $local_avatar ) ) { return; } + return $local_avatar; } @@ -678,4 +1095,378 @@ class Simple_Local_Avatars { 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 $blog_id Blog ID. + */ + public function set_defaults( $blog_id ) { + if ( 'enforce' === $this->get_network_mode() ) { + return; + } + + 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; + } + + /** + * Overwriting existing avatar_ratings so this can be called just before the rating strings would be used so that + * translations will work correctly. + * Default text-domain because the strings have already been translated + */ + private function update_avatar_ratings() { + $this->avatar_ratings = array( + 'G' => __( 'G — Suitable for all audiences' ), + 'PG' => __( 'PG — Possibly offensive, usually for audiences 13 and above' ), + 'R' => __( 'R — Intended for adult audiences above 17' ), + 'X' => __( 'X — Even more mature than above' ), + ); + } + + /** + * 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 ) ) { + $file_name_data = pathinfo( wp_get_original_image_path( $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 ) { + if ( ! did_action( 'wp_enqueue_media' ) ) { + wp_enqueue_media(); + } + $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/plugins/simple-local-avatars/readme.txt b/wp-content/plugins/simple-local-avatars/readme.txt index 5c92ee11..38a0a2f6 100644 --- a/wp-content/plugins/simple-local-avatars/readme.txt +++ b/wp-content/plugins/simple-local-avatars/readme.txt @@ -3,9 +3,9 @@ Contributors: jakemgold, 10up, thinkoomph Donate link: https://10up.com/plugins/simple-local-avatars-wordpress/ Tags: avatar, gravatar, user photos, users, profile Requires at least: 4.6 -Tested up to: 5.5 -Requires PHP: 5.3 -Stable tag: 2.2.0 +Tested up to: 6.0 +Requires PHP: 5.6 +Stable tag: 2.4.0 License: GPLv2 or later License URI: http://www.gnu.org/licenses/gpl-2.0.html @@ -41,33 +41,59 @@ You can also use `get_simple_local_avatar()` (with the same arguments) to retrei == Changelog == -= 2.2.0 = -* **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.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.1.1 = += 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-Lagun](https://github.com/Antonio-Lagun), [@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 = += 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 = += 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) @@ -80,49 +106,52 @@ You can also use `get_simple_local_avatar()` (with the same arguments) to retrei * Hungarian translation added (needs further updating again with new version) * Assorted refactoring / improvements under the hood -= 1.3.1 = += 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 = += 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 = += 1.2.4 - 2011-07-02 = * Support for front end avatar uploads (e.g. Theme My Profile) -= 1.2.3 = += 1.2.3 - 2011-04-04 = * Russian localization -= 1.2.2 = += 1.2.2 - 2011-03-25 = * Fix for avatars uploaded pre-1.2.1 having a broken path after upgrade -= 1.2.1 = += 1.2.1 - 2011-01-26 = * French localization * Simplify uninstall code -= 1.2 = += 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 = += 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 = += 1.1.2 - 2011-01-18 = * Norwegian localization -= 1.1.1 = += 1.1.1 - 2011-01-18 = * Italian localization -= 1.1 = += 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.1 = @@ -132,4 +161,4 @@ You can also use `get_simple_local_avatar()` (with the same arguments) to retrei 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. +Like WordPress 3.2, now *REQUIRES* PHP 5.2 or newer. \ No newline at end of file diff --git a/wp-content/plugins/simple-local-avatars/simple-local-avatars.dev.js b/wp-content/plugins/simple-local-avatars/simple-local-avatars.dev.js deleted file mode 100644 index 69d3d513..00000000 --- a/wp-content/plugins/simple-local-avatars/simple-local-avatars.dev.js +++ /dev/null @@ -1,76 +0,0 @@ -var simple_local_avatar_frame, avatar_spinner, avatar_ratings, avatar_container, avatar_form_button; -var avatar_working = false; - -jQuery(document).ready(function($){ - $( document.getElementById('simple-local-avatar-media') ).on( 'click', function(event) { - event.preventDefault(); - - if ( avatar_working ) - return; - - if ( simple_local_avatar_frame ) { - simple_local_avatar_frame.open(); - return; - } - - simple_local_avatar_frame = wp.media.frames.simple_local_avatar_frame = wp.media({ - title: i10n_SimpleLocalAvatars.insertMediaTitle, - button: { text: i10n_SimpleLocalAvatars.insertIntoPost }, - library : { type : 'image'}, - multiple: false - }); - - simple_local_avatar_frame.on( 'select', function() { - // We set multiple to false so only get one image from the uploader - avatar_lock('lock'); - var avatar_url = simple_local_avatar_frame.state().get('selection').first().toJSON().id; - jQuery.post( ajaxurl, { action: 'assign_simple_local_avatar_media', media_id: avatar_url, user_id: i10n_SimpleLocalAvatars.user_id, _wpnonce: i10n_SimpleLocalAvatars.mediaNonce }, function(data) { - if ( data != '' ) { - avatar_container.innerHTML = data; - $( document.getElementById('simple-local-avatar-remove') ).show(); - avatar_ratings.disabled = false; - avatar_lock('unlock'); - } - }); - }); - - simple_local_avatar_frame.open(); - }); - - $( document.getElementById('simple-local-avatar-remove') ).on('click',function(event){ - event.preventDefault(); - - if ( avatar_working ) - return; - - avatar_lock('lock'); - $.get( ajaxurl, { action: 'remove_simple_local_avatar', user_id: i10n_SimpleLocalAvatars.user_id, _wpnonce: i10n_SimpleLocalAvatars.deleteNonce }) - .done(function(data) { - if ( data != '' ) { - avatar_container.innerHTML = data; - $( document.getElementById('simple-local-avatar-remove') ).hide(); - avatar_ratings.disabled = true; - avatar_lock('unlock'); - } - }); - }); -}); - -function avatar_lock( lock_or_unlock ) { - if ( undefined == avatar_spinner ) { - avatar_ratings = document.getElementById('simple-local-avatar-ratings'); - avatar_spinner = jQuery( document.getElementById('simple-local-avatar-spinner') ); - avatar_container = document.getElementById('simple-local-avatar-photo'); - avatar_form_button = jQuery(avatar_ratings).closest('form').find('input[type=submit]'); - } - - if ( lock_or_unlock == 'unlock' ) { - avatar_working = false; - avatar_form_button.removeAttr('disabled'); - avatar_spinner.hide(); - } else { - avatar_working = true; - avatar_form_button.attr('disabled','disabled'); - avatar_spinner.show(); - } -} \ No newline at end of file diff --git a/wp-content/plugins/simple-local-avatars/simple-local-avatars.js b/wp-content/plugins/simple-local-avatars/simple-local-avatars.js deleted file mode 100644 index 1a20564f..00000000 --- a/wp-content/plugins/simple-local-avatars/simple-local-avatars.js +++ /dev/null @@ -1 +0,0 @@ -function avatar_lock(e){if(undefined==avatar_spinner){avatar_ratings=document.getElementById("simple-local-avatar-ratings");avatar_spinner=jQuery(document.getElementById("simple-local-avatar-spinner"));avatar_container=document.getElementById("simple-local-avatar-photo");avatar_form_button=jQuery(avatar_ratings).closest("form").find("input[type=submit]")}if(e=="unlock"){avatar_working=false;avatar_form_button.removeAttr("disabled");avatar_spinner.hide()}else{avatar_working=true;avatar_form_button.attr("disabled","disabled");avatar_spinner.show()}}var simple_local_avatar_frame,avatar_spinner,avatar_ratings,avatar_container,avatar_form_button;var avatar_working=false;jQuery(document).ready(function(e){e(document.getElementById("simple-local-avatar-media")).on("click",function(t){t.preventDefault();if(avatar_working)return;if(simple_local_avatar_frame){simple_local_avatar_frame.open();return}simple_local_avatar_frame=wp.media.frames.simple_local_avatar_frame=wp.media({title:i10n_SimpleLocalAvatars.insertMediaTitle,button:{text:i10n_SimpleLocalAvatars.insertIntoPost},library:{type:"image"},multiple:false});simple_local_avatar_frame.on("select",function(){avatar_lock("lock");var t=simple_local_avatar_frame.state().get("selection").first().toJSON().id;jQuery.post(ajaxurl,{action:"assign_simple_local_avatar_media",media_id:t,user_id:i10n_SimpleLocalAvatars.user_id,_wpnonce:i10n_SimpleLocalAvatars.mediaNonce},function(t){if(t!=""){avatar_container.innerHTML=t;e(document.getElementById("simple-local-avatar-remove")).show();avatar_ratings.disabled=false;avatar_lock("unlock")}})});simple_local_avatar_frame.open()});e(document.getElementById("simple-local-avatar-remove")).on("click",function(t){t.preventDefault();if(avatar_working)return;avatar_lock("lock");e.get(ajaxurl,{action:"remove_simple_local_avatar",user_id:i10n_SimpleLocalAvatars.user_id,_wpnonce:i10n_SimpleLocalAvatars.deleteNonce}).done(function(t){if(t!=""){avatar_container.innerHTML=t;e(document.getElementById("simple-local-avatar-remove")).hide();avatar_ratings.disabled=true;avatar_lock("unlock")}})})}) \ No newline at end of file diff --git a/wp-content/plugins/simple-local-avatars/simple-local-avatars.php b/wp-content/plugins/simple-local-avatars/simple-local-avatars.php index 172b5f97..30bef3f1 100644 --- a/wp-content/plugins/simple-local-avatars/simple-local-avatars.php +++ b/wp-content/plugins/simple-local-avatars/simple-local-avatars.php @@ -3,18 +3,30 @@ * Plugin Name: Simple Local Avatars * Plugin URI: https://10up.com/plugins/simple-local-avatars-wordpress/ * Description: Adds an avatar upload field to user profiles. Generates requested sizes on demand, just like Gravatar! Simple and lightweight. - * Version: 2.2.0 + * Version: 2.4.0 * Requires at least: 4.6 - * Requires PHP: 5.3 + * Requires PHP: 5.6 * Author: Jake Goldman, 10up * Author URI: https://10up.com * License: GPLv2 or later * License URI: https://www.gnu.org/licenses/gpl-2.0.html * Text Domain: simple-local-avatars + * + * @package SimpleLocalAvatars */ +define( 'SLA_PLUGIN_BASENAME', plugin_basename( __FILE__ ) ); + require_once dirname( __FILE__ ) . '/includes/class-simple-local-avatars.php'; +// Global constants. +define( 'SLA_VERSION', '2.2.0' ); +define( 'SLA_PLUGIN_URL', plugin_dir_url( __FILE__ ) ); + +if ( ! defined( 'SLA_IS_NETWORK' ) ) { + define( 'SLA_IS_NETWORK', Simple_Local_Avatars::is_network( plugin_basename( __FILE__ ) ) ); +} + /** * Init the plugin. */ @@ -57,4 +69,5 @@ function simple_local_avatars_uninstall() { endforeach; delete_option( 'simple_local_avatars' ); + delete_option( 'simple_local_avatars_migrations' ); }