[ Index ] |
PHP Cross Reference of BuddyPress |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * Core Avatars attachment class. 4 * 5 * @package BuddyPress 6 * @subpackage Core 7 * @since 2.3.0 8 */ 9 10 // Exit if accessed directly. 11 defined( 'ABSPATH' ) || exit; 12 13 /** 14 * BP Attachment Avatar class. 15 * 16 * Extends BP Attachment to manage the avatar uploads. 17 * 18 * @since 2.3.0 19 */ 20 class BP_Attachment_Avatar extends BP_Attachment { 21 22 /** 23 * Construct Upload parameters. 24 * 25 * @since 2.3.0 26 * 27 * @see BP_Attachment::__construct() for list of parameters 28 */ 29 public function __construct() { 30 // Allowed avatar types. 31 $allowed_types = bp_core_get_allowed_avatar_types(); 32 33 parent::__construct( array( 34 'action' => 'bp_avatar_upload', 35 'file_input' => 'file', 36 'original_max_filesize' => bp_core_avatar_original_max_filesize(), 37 38 // Specific errors for avatars. 39 'upload_error_strings' => array( 40 /* translators: %s: Max file size for the profile photo */ 41 9 => sprintf( _x( 'That photo is too big. Please upload one smaller than %s', 'profile photo upload error', 'buddypress' ), size_format( bp_core_avatar_original_max_filesize() ) ), 42 43 /* translators: %s: comma separated list of file types allowed for the profile photo */ 44 10 => sprintf( _nx( 'Please upload only this file type: %s.', 'Please upload only these file types: %s.', count( $allowed_types ), 'profile photo upload error', 'buddypress' ), self::get_avatar_types( $allowed_types ) ), 45 ), 46 ) ); 47 } 48 49 /** 50 * Gets the available avatar types. 51 * 52 * @since 2.3.0 53 * 54 * @param array $allowed_types Array of allowed avatar types. 55 * @return string comma separated list of allowed avatar types. 56 */ 57 public static function get_avatar_types( $allowed_types = array() ) { 58 $types = array_map( 'strtoupper', $allowed_types ); 59 $comma = _x( ',', 'avatar types separator', 'buddypress' ); 60 return join( $comma . ' ', $types ); 61 } 62 63 /** 64 * Set Upload Dir data for avatars. 65 * 66 * @since 2.3.0 67 */ 68 public function set_upload_dir() { 69 if ( bp_core_avatar_upload_path() && bp_core_avatar_url() ) { 70 $this->upload_path = bp_core_avatar_upload_path(); 71 $this->url = bp_core_avatar_url(); 72 $this->upload_dir = bp_upload_dir(); 73 } else { 74 parent::set_upload_dir(); 75 } 76 } 77 78 /** 79 * Avatar specific rules. 80 * 81 * Adds an error if the avatar size or type don't match BuddyPress needs. 82 * The error code is the index of $upload_error_strings. 83 * 84 * @since 2.3.0 85 * 86 * @param array $file the temporary file attributes (before it has been moved). 87 * @return array the file with extra errors if needed. 88 */ 89 public function validate_upload( $file = array() ) { 90 // Bail if already an error. 91 if ( ! empty( $file['error'] ) ) { 92 return $file; 93 } 94 95 // File size is too big. 96 if ( ! bp_core_check_avatar_size( array( 'file' => $file ) ) ) { 97 $file['error'] = 9; 98 99 // File is of invalid type. 100 } elseif ( ! bp_core_check_avatar_type( array( 'file' => $file ) ) ) { 101 $file['error'] = 10; 102 } 103 104 // Return with error code attached. 105 return $file; 106 } 107 108 /** 109 * Maybe shrink the attachment to fit maximum allowed width. 110 * 111 * @since 2.3.0 112 * @since 2.4.0 Add the $ui_available_width parameter, to inform about the Avatar UI width. 113 * 114 * @param string $file The absolute path to the file. 115 * @param int $ui_available_width Available width for the UI. 116 * @return false|string|WP_Image_Editor|WP_Error 117 */ 118 public static function shrink( $file = '', $ui_available_width = 0 ) { 119 // Get image size. 120 $avatar_data = parent::get_image_data( $file ); 121 122 // Init the edit args. 123 $edit_args = array(); 124 125 // Defaults to the Avatar original max width constant. 126 $original_max_width = bp_core_avatar_original_max_width(); 127 128 // The ui_available_width is defined and it's smaller than the Avatar original max width. 129 if ( ! empty( $ui_available_width ) && $ui_available_width < $original_max_width ) { 130 /** 131 * In this case, to make sure the content of the image will be fully displayed 132 * during the cropping step, let's use the Avatar UI Available width. 133 */ 134 $original_max_width = $ui_available_width; 135 136 // $original_max_width has to be larger than the avatar's full width. 137 if ( $original_max_width < bp_core_avatar_full_width() ) { 138 $original_max_width = bp_core_avatar_full_width(); 139 } 140 } 141 142 // Do we need to resize the image? 143 if ( isset( $avatar_data['width'] ) && $avatar_data['width'] > $original_max_width ) { 144 $edit_args = array( 145 'max_w' => $original_max_width, 146 'max_h' => $original_max_width, 147 ); 148 } 149 150 // Do we need to rotate the image? 151 $angles = array( 152 3 => 180, 153 6 => -90, 154 8 => 90, 155 ); 156 157 if ( isset( $avatar_data['meta']['orientation'] ) && isset( $angles[ $avatar_data['meta']['orientation'] ] ) ) { 158 $edit_args['rotate'] = $angles[ $avatar_data['meta']['orientation'] ]; 159 } 160 161 // No need to edit the avatar, original file will be used. 162 if ( empty( $edit_args ) ) { 163 return false; 164 165 // Add the file to the edit arguments. 166 } else { 167 $edit_args['file'] = $file; 168 } 169 170 return parent::edit_image( 'avatar', $edit_args ); 171 } 172 173 /** 174 * Check if the image dimensions are smaller than full avatar dimensions. 175 * 176 * @since 2.3.0 177 * 178 * 179 * @param string $file the absolute path to the file. 180 * @return bool 181 */ 182 public static function is_too_small( $file = '' ) { 183 $uploaded_image = @getimagesize( $file ); 184 $full_width = bp_core_avatar_full_width(); 185 $full_height = bp_core_avatar_full_height(); 186 187 if ( isset( $uploaded_image[0] ) && $uploaded_image[0] < $full_width || $uploaded_image[1] < $full_height ) { 188 return true; 189 } 190 191 return false; 192 } 193 194 /** 195 * Crop the avatar. 196 * 197 * @since 2.3.0 198 * 199 * @see BP_Attachment::crop for the list of parameters 200 * 201 * @param array $args Array of arguments for the cropping. 202 * @return array The cropped avatars (full, thumb and the timestamp). 203 */ 204 public function crop( $args = array() ) { 205 // Bail if the original file is missing. 206 if ( empty( $args['original_file'] ) ) { 207 return false; 208 } 209 210 if ( ! bp_attachments_current_user_can( 'edit_avatar', $args ) ) { 211 return false; 212 } 213 214 if ( 'user' === $args['object'] ) { 215 $avatar_dir = 'avatars'; 216 } else { 217 $avatar_dir = sanitize_key( $args['object'] ) . '-avatars'; 218 } 219 220 $args['item_id'] = (int) $args['item_id']; 221 222 /** 223 * Original file is a relative path to the image 224 * eg: /avatars/1/avatar.jpg 225 */ 226 $relative_path = sprintf( '/%s/%s/%s', $avatar_dir, $args['item_id'], basename( $args['original_file'] ) ); 227 $absolute_path = $this->upload_path . $relative_path; 228 229 // Bail if the avatar is not available. 230 if ( ! file_exists( $absolute_path ) ) { 231 return false; 232 } 233 234 if ( empty( $args['item_id'] ) ) { 235 236 /** This filter is documented in bp-core/bp-core-avatars.php */ 237 $avatar_folder_dir = apply_filters( 'bp_core_avatar_folder_dir', dirname( $absolute_path ), $args['item_id'], $args['object'], $args['avatar_dir'] ); 238 } else { 239 240 /** This filter is documented in bp-core/bp-core-avatars.php */ 241 $avatar_folder_dir = apply_filters( 'bp_core_avatar_folder_dir', $this->upload_path . '/' . $args['avatar_dir'] . '/' . $args['item_id'], $args['item_id'], $args['object'], $args['avatar_dir'] ); 242 } 243 244 // Bail if the avatar folder is missing for this item_id. 245 if ( ! file_exists( $avatar_folder_dir ) ) { 246 return false; 247 } 248 249 // Get the existing avatar files for the object. 250 $existing_avatar = bp_core_fetch_avatar( 251 array( 252 'object' => $args['object'], 253 'item_id' => $args['item_id'], 254 'html' => false, 255 ) 256 ); 257 258 /** 259 * Check that the new avatar doesn't have the same name as the 260 * old one before moving the previous one into history. 261 */ 262 if ( ! empty( $existing_avatar ) && $existing_avatar !== $this->url . $relative_path ) { 263 // Avatar history is disabled, simply delete the existing avatar files. 264 if ( bp_avatar_history_is_disabled() ) { 265 bp_core_delete_existing_avatar( 266 array( 267 'object' => $args['object'], 268 'item_id' => $args['item_id'], 269 'avatar_path' => $avatar_folder_dir, 270 ) 271 ); 272 } else { 273 // Add a new revision for the existing avatar. 274 $avatars = bp_attachments_list_directory_files( $avatar_folder_dir ); 275 276 if ( $avatars ) { 277 foreach ( $avatars as $avatar_file ) { 278 if ( ! isset( $avatar_file->name, $avatar_file->id, $avatar_file->path ) ) { 279 continue; 280 } 281 282 $is_full = preg_match( "/-bpfull/", $avatar_file->name ); 283 $is_thumb = preg_match( "/-bpthumb/", $avatar_file->name ); 284 285 if ( $is_full || $is_thumb ) { 286 $revision = $this->add_revision( 287 'avatar', 288 array( 289 'file_abspath' => $avatar_file->path, 290 'file_id' => $avatar_file->id, 291 ) 292 ); 293 294 if ( is_wp_error( $revision ) ) { 295 error_log( $revision->get_error_message() ); 296 } 297 } 298 } 299 } 300 } 301 } 302 303 // Make sure we at least have minimal data for cropping. 304 if ( empty( $args['crop_w'] ) ) { 305 $args['crop_w'] = bp_core_avatar_full_width(); 306 } 307 308 if ( empty( $args['crop_h'] ) ) { 309 $args['crop_h'] = bp_core_avatar_full_height(); 310 } 311 312 // Get the file extension. 313 $data = @getimagesize( $absolute_path ); 314 $ext = $data['mime'] === 'image/png' ? 'png' : 'jpg'; 315 316 $args['original_file'] = $absolute_path; 317 $args['src_abs'] = false; 318 319 $avatar_types = array( 320 'full' => '', 321 'thumb' => '', 322 ); 323 $timestamp = bp_core_current_time( true, 'timestamp' ); 324 325 foreach ( $avatar_types as $key_type => $type ) { 326 if ( 'thumb' === $key_type ) { 327 $args['dst_w'] = bp_core_avatar_thumb_width(); 328 $args['dst_h'] = bp_core_avatar_thumb_height(); 329 } else { 330 $args['dst_w'] = bp_core_avatar_full_width(); 331 $args['dst_h'] = bp_core_avatar_full_height(); 332 } 333 334 $filename = wp_unique_filename( $avatar_folder_dir, $timestamp . "-bp{$key_type}.{$ext}" ); 335 $args['dst_file'] = $avatar_folder_dir . '/' . $filename; 336 337 $avatar_types[ $key_type ] = parent::crop( $args ); 338 } 339 340 // Remove the original. 341 @unlink( $absolute_path ); 342 343 // Return the full, thumb cropped avatars and the timestamp. 344 return array_merge( 345 $avatar_types, 346 array( 347 'timestamp' => $timestamp, 348 ) 349 ); 350 } 351 352 /** 353 * Get the user id to set its avatar. 354 * 355 * @since 2.3.0 356 * 357 * @return integer The user ID. 358 */ 359 private function get_user_id() { 360 $bp = buddypress(); 361 $user_id = 0; 362 363 if ( bp_is_user() ) { 364 $user_id = bp_displayed_user_id(); 365 } 366 367 if ( ! empty( $bp->members->admin->user_id ) ) { 368 $user_id = $bp->members->admin->user_id; 369 } 370 371 return $user_id; 372 } 373 374 /** 375 * Get the group id to set its avatar. 376 * 377 * @since 2.3.0 378 * 379 * @return integer The group ID. 380 */ 381 private function get_group_id() { 382 $group_id = 0; 383 384 if ( bp_is_group() ) { 385 $group_id = bp_get_current_group_id(); 386 } 387 388 return $group_id; 389 } 390 391 /** 392 * Build script data for the Uploader UI. 393 * 394 * @since 2.3.0 395 * 396 * @return array The javascript localization data. 397 */ 398 public function script_data() { 399 // Get default script data. 400 $script_data = parent::script_data(); 401 402 // Defaults to Avatar Backbone script. 403 $js_scripts = array( 'bp-avatar' ); 404 405 // Default object. 406 $object = ''; 407 408 // Get the possible item ids. 409 $user_id = $this->get_user_id(); 410 $group_id = $this->get_group_id(); 411 412 if ( ! empty( $user_id ) ) { 413 // Should we load the the Webcam Avatar javascript file. 414 if ( bp_avatar_use_webcam() ) { 415 $js_scripts = array( 'bp-webcam' ); 416 } 417 418 $script_data['bp_params'] = array( 419 'object' => 'user', 420 'item_id' => $user_id, 421 'has_avatar' => bp_get_user_has_avatar( $user_id ), 422 'nonces' => array( 423 'set' => wp_create_nonce( 'bp_avatar_cropstore' ), 424 'remove' => wp_create_nonce( 'bp_delete_avatar_link' ), 425 ), 426 ); 427 428 // Set feedback messages. 429 $script_data['feedback_messages'] = array( 430 1 => __( 'There was a problem cropping your profile photo.', 'buddypress' ), 431 2 => __( 'Your new profile photo was uploaded successfully.', 'buddypress' ), 432 3 => __( 'There was a problem deleting your profile photo. Please try again.', 'buddypress' ), 433 4 => __( 'Your profile photo was deleted successfully!', 'buddypress' ), 434 5 => __( 'Your profile photo was recycled successfully!', 'buddypress' ), 435 6 => __( 'The profile photo was permanently deleted successfully!', 'buddypress' ), 436 ); 437 } elseif ( ! empty( $group_id ) ) { 438 $script_data['bp_params'] = array( 439 'object' => 'group', 440 'item_id' => $group_id, 441 'has_avatar' => bp_get_group_has_avatar( $group_id ), 442 'nonces' => array( 443 'set' => wp_create_nonce( 'bp_avatar_cropstore' ), 444 'remove' => wp_create_nonce( 'bp_group_avatar_delete' ), 445 ), 446 ); 447 448 // Set feedback messages. 449 $script_data['feedback_messages'] = array( 450 1 => __( 'There was a problem cropping the group profile photo.', 'buddypress' ), 451 2 => __( 'The group profile photo was uploaded successfully.', 'buddypress' ), 452 3 => __( 'There was a problem deleting the group profile photo. Please try again.', 'buddypress' ), 453 4 => __( 'The group profile photo was deleted successfully!', 'buddypress' ), 454 5 => __( 'The group profile photo was recycled successfully!', 'buddypress' ), 455 6 => __( 'The group profile photo was permanently deleted successfully!', 'buddypress' ), 456 ); 457 } else { 458 459 /** 460 * Use this filter to include specific BuddyPress params for your object. 461 * e.g. Blavatar. 462 * 463 * @since 2.3.0 464 * 465 * @param array $value The avatar specific BuddyPress parameters. 466 */ 467 $script_data['bp_params'] = apply_filters( 'bp_attachment_avatar_params', array() ); 468 } 469 470 // Include the specific css. 471 $script_data['extra_css'] = array( 'bp-avatar' ); 472 473 // Include the specific css. 474 $script_data['extra_js'] = $js_scripts; 475 476 // Set the object to contextualize the filter. 477 if ( isset( $script_data['bp_params']['object'] ) ) { 478 $object = $script_data['bp_params']['object']; 479 } 480 481 /** 482 * Use this filter to override/extend the avatar script data. 483 * 484 * @since 2.3.0 485 * 486 * @param array $script_data The avatar script data. 487 * @param string $object The object the avatar belongs to (eg: user or group). 488 */ 489 return apply_filters( 'bp_attachment_avatar_script_data', $script_data, $object ); 490 } 491 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Thu Nov 21 01:00:57 2024 | Cross-referenced by PHPXref 0.7.1 |