[ Index ] |
PHP Cross Reference of BuddyPress |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * BuddyPress Attachments functions. 4 * 5 * @package BuddyPress 6 * @subpackage Attachments 7 * @since 2.3.0 8 */ 9 10 // Exit if accessed directly. 11 defined( 'ABSPATH' ) || exit; 12 13 /** 14 * Get the Attachments Uploads dir data. 15 * 16 * @since 2.4.0 17 * 18 * @param string $data The data to get. Possible values are: 'dir', 'basedir' & 'baseurl'. 19 * Leave empty to get all datas. 20 * @return string|array The needed Upload dir data. 21 */ 22 function bp_attachments_uploads_dir_get( $data = '' ) { 23 $attachments_dir = 'buddypress'; 24 $retval = ''; 25 26 if ( 'dir' === $data ) { 27 $retval = $attachments_dir; 28 } else { 29 $upload_data = bp_upload_dir(); 30 31 // Return empty string, if Uploads data are not available. 32 if ( ! $upload_data ) { 33 return $retval; 34 } 35 36 // Build the Upload data array for BuddyPress attachments. 37 foreach ( $upload_data as $key => $value ) { 38 if ( 'basedir' === $key || 'baseurl' === $key ) { 39 $upload_data[ $key ] = trailingslashit( $value ) . $attachments_dir; 40 41 // Fix for HTTPS. 42 if ( 'baseurl' === $key && is_ssl() ) { 43 $upload_data[ $key ] = str_replace( 'http://', 'https://', $upload_data[ $key ] ); 44 } 45 } else { 46 unset( $upload_data[ $key ] ); 47 } 48 } 49 50 // Add the dir to the array. 51 $upload_data['dir'] = $attachments_dir; 52 53 if ( empty( $data ) ) { 54 $retval = $upload_data; 55 } elseif ( isset( $upload_data[ $data ] ) ) { 56 $retval = $upload_data[ $data ]; 57 } 58 } 59 60 /** 61 * Filter here to edit the Attachments upload dir data. 62 * 63 * @since 2.4.0 64 * 65 * @param string|array $retval The needed Upload dir data or the full array of data 66 * @param string $data The data requested 67 */ 68 return apply_filters( 'bp_attachments_uploads_dir_get', $retval, $data ); 69 } 70 71 /** 72 * Gets the upload dir array for cover images. 73 * 74 * @since 3.0.0 75 * 76 * @return array See wp_upload_dir(). 77 */ 78 function bp_attachments_cover_image_upload_dir( $args = array() ) { 79 // Default values are for members. 80 $object_id = bp_displayed_user_id(); 81 82 if ( empty( $object_id ) ) { 83 $object_id = bp_loggedin_user_id(); 84 } 85 86 $object_directory = 'members'; 87 88 // We're in a group, edit default values. 89 if ( bp_is_group() || bp_is_group_create() ) { 90 $object_id = bp_get_current_group_id(); 91 $object_directory = 'groups'; 92 } 93 94 $r = bp_parse_args( $args, array( 95 'object_id' => $object_id, 96 'object_directory' => $object_directory, 97 ), 'cover_image_upload_dir' ); 98 99 100 // Set the subdir. 101 $subdir = '/' . $r['object_directory'] . '/' . $r['object_id'] . '/cover-image'; 102 103 $upload_dir = bp_attachments_uploads_dir_get(); 104 105 /** 106 * Filters the cover image upload directory. 107 * 108 * @since 2.4.0 109 * 110 * @param array $value Array containing the path, URL, and other helpful settings. 111 * @param array $upload_dir The original Uploads dir. 112 */ 113 return apply_filters( 'bp_attachments_cover_image_upload_dir', array( 114 'path' => $upload_dir['basedir'] . $subdir, 115 'url' => set_url_scheme( $upload_dir['baseurl'] ) . $subdir, 116 'subdir' => $subdir, 117 'basedir' => $upload_dir['basedir'], 118 'baseurl' => set_url_scheme( $upload_dir['baseurl'] ), 119 'error' => false, 120 ), $upload_dir ); 121 } 122 123 /** 124 * Get the max upload file size for any attachment. 125 * 126 * @since 2.4.0 127 * 128 * @param string $type A string to inform about the type of attachment 129 * we wish to get the max upload file size for. 130 * @return int Max upload file size for any attachment. 131 */ 132 function bp_attachments_get_max_upload_file_size( $type = '' ) { 133 $fileupload_maxk = bp_core_get_root_option( 'fileupload_maxk' ); 134 135 if ( '' === $fileupload_maxk ) { 136 $fileupload_maxk = 5120000; // 5mb; 137 } else { 138 $fileupload_maxk = $fileupload_maxk * 1024; 139 } 140 141 /** 142 * Filter here to edit the max upload file size. 143 * 144 * @since 2.4.0 145 * 146 * @param int $fileupload_maxk Max upload file size for any attachment. 147 * @param string $type The attachment type (eg: 'avatar' or 'cover_image'). 148 */ 149 return apply_filters( 'bp_attachments_get_max_upload_file_size', $fileupload_maxk, $type ); 150 } 151 152 /** 153 * Get allowed types for any attachment. 154 * 155 * @since 2.4.0 156 * 157 * @param string $type The extension types to get. 158 * Default: 'avatar'. 159 * @return array The list of allowed extensions for attachments. 160 */ 161 function bp_attachments_get_allowed_types( $type = 'avatar' ) { 162 // Defaults to BuddyPress supported image extensions. 163 $exts = array( 'jpeg', 'gif', 'png' ); 164 165 /** 166 * It's not a BuddyPress feature, get the allowed extensions 167 * matching the $type requested. 168 */ 169 if ( 'avatar' !== $type && 'cover_image' !== $type ) { 170 // Reset the default exts. 171 $exts = array(); 172 173 switch ( $type ) { 174 case 'video' : 175 $exts = wp_get_video_extensions(); 176 break; 177 178 case 'audio' : 179 $exts = wp_get_video_extensions(); 180 break; 181 182 default: 183 $allowed_mimes = get_allowed_mime_types(); 184 185 /** 186 * Search for allowed mimes matching the type. 187 * 188 * Eg: using 'application/vnd.oasis' as the $type 189 * parameter will get all OpenOffice extensions supported 190 * by WordPress and allowed for the current user. 191 */ 192 if ( '' !== $type ) { 193 $allowed_mimes = preg_grep( '/' . addcslashes( $type, '/.+-' ) . '/', $allowed_mimes ); 194 } 195 196 $allowed_types = array_keys( $allowed_mimes ); 197 198 // Loop to explode keys using '|'. 199 foreach ( $allowed_types as $allowed_type ) { 200 $t = explode( '|', $allowed_type ); 201 $exts = array_merge( $exts, (array) $t ); 202 } 203 break; 204 } 205 } 206 207 /** 208 * Filter here to edit the allowed extensions by attachment type. 209 * 210 * @since 2.4.0 211 * 212 * @param array $exts List of allowed extensions. 213 * @param string $type The requested file type. 214 */ 215 return apply_filters( 'bp_attachments_get_allowed_types', $exts, $type ); 216 } 217 218 /** 219 * Get allowed attachment mime types. 220 * 221 * @since 2.4.0 222 * 223 * @param string $type The extension types to get (Optional). 224 * @param array $allowed_types List of allowed extensions. 225 * @return array List of allowed mime types. 226 */ 227 function bp_attachments_get_allowed_mimes( $type = '', $allowed_types = array() ) { 228 if ( empty( $allowed_types ) ) { 229 $allowed_types = bp_attachments_get_allowed_types( $type ); 230 } 231 232 $validate_mimes = wp_match_mime_types( join( ',', $allowed_types ), wp_get_mime_types() ); 233 $allowed_mimes = array_map( 'implode', $validate_mimes ); 234 235 /** 236 * Include jpg type if jpeg is set 237 */ 238 if ( isset( $allowed_mimes['jpeg'] ) && ! isset( $allowed_mimes['jpg'] ) ) { 239 $allowed_mimes['jpg'] = $allowed_mimes['jpeg']; 240 } 241 242 return $allowed_mimes; 243 } 244 245 /** 246 * Check the uploaded attachment type is allowed. 247 * 248 * @since 2.4.0 249 * 250 * @param string $file Full path to the file. 251 * @param string $filename The name of the file (may differ from $file due to $file being 252 * in a tmp directory). 253 * @param array $allowed_mimes The attachment allowed mimes (Required). 254 * @return bool True if the attachment type is allowed. False otherwise 255 */ 256 function bp_attachments_check_filetype( $file, $filename, $allowed_mimes ) { 257 $filetype = wp_check_filetype_and_ext( $file, $filename, $allowed_mimes ); 258 259 if ( ! empty( $filetype['ext'] ) && ! empty( $filetype['type'] ) ) { 260 return true; 261 } 262 263 return false; 264 } 265 266 /** 267 * Use the absolute path to an image to set an attachment type for a given item. 268 * 269 * @since 2.4.0 270 * 271 * @param string $type The attachment type to create (avatar or cover_image). Default: avatar. 272 * @param array $args { 273 * @type int $item_id The ID of the object (Required). Default: 0. 274 * @type string $object The object type (eg: group, user, blog) (Required). Default: 'user'. 275 * @type string $component The component for the object (eg: groups, members, blogs). Default: ''. 276 * @type string $image The absolute path to the image (Required). Default: ''. 277 * @type int $crop_w Crop width. Default: 0. 278 * @type int $crop_h Crop height. Default: 0. 279 * @type int $crop_x The horizontal starting point of the crop. Default: 0. 280 * @type int $crop_y The vertical starting point of the crop. Default: 0. 281 * } 282 * @return bool True on success, false otherwise. 283 */ 284 function bp_attachments_create_item_type( $type = 'avatar', $args = array() ) { 285 if ( empty( $type ) || ( $type !== 'avatar' && $type !== 'cover_image' ) ) { 286 return false; 287 } 288 289 $r = bp_parse_args( $args, array( 290 'item_id' => 0, 291 'object' => 'user', 292 'component' => '', 293 'image' => '', 294 'crop_w' => 0, 295 'crop_h' => 0, 296 'crop_x' => 0, 297 'crop_y' => 0 298 ), 'create_item_' . $type ); 299 300 if ( empty( $r['item_id'] ) || empty( $r['object'] ) || ! file_exists( $r['image'] ) || ! @getimagesize( $r['image'] ) ) { 301 return false; 302 } 303 304 // Make sure the file path is safe. 305 if ( 1 === validate_file( $r['image'] ) ) { 306 return false; 307 } 308 309 // Set the component if not already done. 310 if ( empty( $r['component'] ) ) { 311 if ( 'user' === $r['object'] ) { 312 $r['component'] = 'members'; 313 } else { 314 $r['component'] = $r['object'] . 's'; 315 } 316 } 317 318 // Get allowed mimes for the Attachment type and check the image one is. 319 $allowed_mimes = bp_attachments_get_allowed_mimes( $type ); 320 $is_allowed = wp_check_filetype( $r['image'], $allowed_mimes ); 321 322 // It's not an image. 323 if ( ! $is_allowed['ext'] ) { 324 return false; 325 } 326 327 // Init the Attachment data. 328 $attachment_data = array(); 329 330 if ( 'avatar' === $type ) { 331 // Set crop width for the avatar if not given. 332 if ( empty( $r['crop_w'] ) ) { 333 $r['crop_w'] = bp_core_avatar_full_width(); 334 } 335 336 // Set crop height for the avatar if not given. 337 if ( empty( $r['crop_h'] ) ) { 338 $r['crop_h'] = bp_core_avatar_full_height(); 339 } 340 341 if ( is_callable( $r['component'] . '_avatar_upload_dir' ) ) { 342 $dir_args = array( $r['item_id'] ); 343 344 // In case of members, we need an extra argument. 345 if ( 'members' === $r['component'] ) { 346 $dir_args = array( false, $r['item_id'] ); 347 } 348 349 $attachment_data = call_user_func_array( $r['component'] . '_avatar_upload_dir', $dir_args ); 350 } 351 } elseif ( 'cover_image' === $type ) { 352 $attachment_data = bp_attachments_cover_image_upload_dir(); 353 354 // The BP Attachments Uploads Dir is not set, stop. 355 if ( ! $attachment_data ) { 356 return false; 357 } 358 359 // Default to members for xProfile. 360 $object_subdir = 'members'; 361 362 if ( 'members' !== $r['component'] ) { 363 $object_subdir = sanitize_key( $r['component'] ); 364 } 365 366 // Set Subdir. 367 $attachment_data['subdir'] = $object_subdir . '/' . $r['item_id'] . '/cover-image'; 368 369 // Set Path. 370 $attachment_data['path'] = trailingslashit( $attachment_data['basedir'] ) . $attachment_data['subdir']; 371 } 372 373 if ( ! isset( $attachment_data['path'] ) || ! isset( $attachment_data['subdir'] ) ) { 374 return false; 375 } 376 377 // It's not a regular upload, we may need to create some folders. 378 if ( ! is_dir( $attachment_data['path'] ) ) { 379 if ( ! wp_mkdir_p( $attachment_data['path'] ) ) { 380 return false; 381 } 382 } 383 384 // Set the image name and path. 385 $image_file_name = wp_unique_filename( $attachment_data['path'], basename( $r['image'] ) ); 386 $image_file_path = $attachment_data['path'] . '/' . $image_file_name; 387 388 // Copy the image file into the avatar dir. 389 if ( ! copy( $r['image'], $image_file_path ) ) { 390 return false; 391 } 392 393 // Init the response. 394 $created = false; 395 396 // It's an avatar, we need to crop it. 397 if ( 'avatar' === $type ) { 398 $created = bp_core_avatar_handle_crop( array( 399 'object' => $r['object'], 400 'avatar_dir' => trim( dirname( $attachment_data['subdir'] ), '/' ), 401 'item_id' => (int) $r['item_id'], 402 'original_file' => trailingslashit( $attachment_data['subdir'] ) . $image_file_name, 403 'crop_w' => $r['crop_w'], 404 'crop_h' => $r['crop_h'], 405 'crop_x' => $r['crop_x'], 406 'crop_y' => $r['crop_y'] 407 ) ); 408 409 // It's a cover image we need to fit it to feature's dimensions. 410 } elseif ( 'cover_image' === $type ) { 411 $cover_image = bp_attachments_cover_image_generate_file( array( 412 'file' => $image_file_path, 413 'component' => $r['component'], 414 'cover_image_dir' => $attachment_data['path'] 415 ) ); 416 417 $created = ! empty( $cover_image['cover_file'] ); 418 } 419 420 // Remove copied file if it fails. 421 if ( ! $created ) { 422 @unlink( $image_file_path ); 423 } 424 425 // Return the response. 426 return $created; 427 } 428 429 /** 430 * Get the url or the path for a type of attachment. 431 * 432 * @since 2.4.0 433 * 434 * @param string $data whether to get the url or the path. 435 * @param array $args { 436 * @type string $object_dir The object dir (eg: members/groups). Defaults to members. 437 * @type int $item_id The object id (eg: a user or a group id). Defaults to current user. 438 * @type string $type The type of the attachment which is also the subdir where files are saved. 439 * Defaults to 'cover-image' 440 * @type string $file The name of the file. 441 * } 442 * @return string|bool The url or the path to the attachment, false otherwise 443 */ 444 function bp_attachments_get_attachment( $data = 'url', $args = array() ) { 445 // Default value. 446 $attachment_data = false; 447 448 $r = bp_parse_args( $args, array( 449 'object_dir' => 'members', 450 'item_id' => bp_loggedin_user_id(), 451 'type' => 'cover-image', 452 'file' => '', 453 ), 'attachments_get_attachment_src' ); 454 455 /** 456 * Filters whether or not to handle fetching a BuddyPress image attachment. 457 * 458 * If you want to override this function, make sure you return false. 459 * 460 * @since 2.5.1 461 * 462 * @param null|string $value If null is returned, proceed with default behaviour. Otherwise, value returned verbatim. 463 * @param array $r { 464 * @type string $object_dir The object dir (eg: members/groups). Defaults to members. 465 * @type int $item_id The object id (eg: a user or a group id). Defaults to current user. 466 * @type string $type The type of the attachment which is also the subdir where files are saved. 467 * Defaults to 'cover-image' 468 * @type string $file The name of the file. 469 * } 470 */ 471 $pre_filter = apply_filters( 'bp_attachments_pre_get_attachment', null, $r ); 472 if ( $pre_filter !== null ) { 473 return $pre_filter; 474 } 475 476 // Get BuddyPress Attachments Uploads Dir datas. 477 $bp_attachments_uploads_dir = bp_attachments_uploads_dir_get(); 478 479 // The BP Attachments Uploads Dir is not set, stop. 480 if ( ! $bp_attachments_uploads_dir ) { 481 return $attachment_data; 482 } 483 484 $type_subdir = $r['object_dir'] . '/' . $r['item_id'] . '/' . $r['type']; 485 $type_dir = trailingslashit( $bp_attachments_uploads_dir['basedir'] ) . $type_subdir; 486 487 if ( 1 === validate_file( $type_dir ) || ! is_dir( $type_dir ) ) { 488 return $attachment_data; 489 } 490 491 if ( ! empty( $r['file'] ) ) { 492 if ( ! file_exists( trailingslashit( $type_dir ) . $r['file'] ) ) { 493 return $attachment_data; 494 } 495 496 if ( 'url' === $data ) { 497 $attachment_data = trailingslashit( $bp_attachments_uploads_dir['baseurl'] ) . $type_subdir . '/' . $r['file']; 498 } else { 499 $attachment_data = trailingslashit( $type_dir ) . $r['file']; 500 } 501 502 } else { 503 $file = false; 504 505 // Open the directory and get the first file. 506 if ( $att_dir = opendir( $type_dir ) ) { 507 508 while ( false !== ( $attachment_file = readdir( $att_dir ) ) ) { 509 // Look for the first file having the type in its name. 510 if ( false !== strpos( $attachment_file, $r['type'] ) && empty( $file ) ) { 511 $file = $attachment_file; 512 break; 513 } 514 } 515 } 516 517 if ( empty( $file ) ) { 518 return $attachment_data; 519 } 520 521 if ( 'url' === $data ) { 522 $attachment_data = trailingslashit( $bp_attachments_uploads_dir['baseurl'] ) . $type_subdir . '/' . $file; 523 } else { 524 $attachment_data = trailingslashit( $type_dir ) . $file; 525 } 526 } 527 528 return $attachment_data; 529 } 530 531 /** 532 * Delete an attachment for the given arguments 533 * 534 * @since 2.4.0 535 * 536 * @see bp_attachments_get_attachment() For more information on accepted arguments. 537 * 538 * @param array $args Array of arguments for the attachment deletion. 539 * @return bool True if the attachment was deleted, false otherwise. 540 */ 541 function bp_attachments_delete_file( $args = array() ) { 542 $attachment_path = bp_attachments_get_attachment( 'path', $args ); 543 544 /** 545 * Filters whether or not to handle deleting an existing BuddyPress attachment. 546 * 547 * If you want to override this function, make sure you return false. 548 * 549 * @since 2.5.1 550 * 551 * @param bool $value Whether or not to delete the BuddyPress attachment. 552 * @param array $args Array of arguments for the attachment deletion. 553 */ 554 if ( ! apply_filters( 'bp_attachments_pre_delete_file', true, $args ) ) { 555 return true; 556 } 557 558 if ( empty( $attachment_path ) ) { 559 return false; 560 } 561 562 @unlink( $attachment_path ); 563 return true; 564 } 565 566 /** 567 * Get the BuddyPress Plupload settings. 568 * 569 * @since 2.3.0 570 * 571 * @return array List of BuddyPress Plupload settings. 572 */ 573 function bp_attachments_get_plupload_default_settings() { 574 575 $max_upload_size = wp_max_upload_size(); 576 577 if ( ! $max_upload_size ) { 578 $max_upload_size = 0; 579 } 580 581 $defaults = array( 582 'runtimes' => 'html5,flash,silverlight,html4', 583 'file_data_name' => 'file', 584 'multipart_params' => array( 585 'action' => 'bp_upload_attachment', 586 '_wpnonce' => wp_create_nonce( 'bp-uploader' ), 587 ), 588 'url' => admin_url( 'admin-ajax.php', 'relative' ), 589 'flash_swf_url' => includes_url( 'js/plupload/plupload.flash.swf' ), 590 'silverlight_xap_url' => includes_url( 'js/plupload/plupload.silverlight.xap' ), 591 'filters' => array( 592 'max_file_size' => $max_upload_size . 'b', 593 ), 594 'multipart' => true, 595 'urlstream_upload' => true, 596 ); 597 598 // WordPress is not allowing multi selection for iOs 7 device.. See #29602. 599 if ( wp_is_mobile() && strpos( $_SERVER['HTTP_USER_AGENT'], 'OS 7_' ) !== false && 600 strpos( $_SERVER['HTTP_USER_AGENT'], 'like Mac OS X' ) !== false ) { 601 602 $defaults['multi_selection'] = false; 603 } 604 605 $settings = array( 606 'defaults' => $defaults, 607 'browser' => array( 608 'mobile' => wp_is_mobile(), 609 'supported' => _device_can_upload(), 610 ), 611 'limitExceeded' => is_multisite() && ! is_upload_space_available(), 612 ); 613 614 /** 615 * Filter the BuddyPress Plupload default settings. 616 * 617 * @since 2.3.0 618 * 619 * @param array $settings Default Plupload parameters array. 620 */ 621 return apply_filters( 'bp_attachments_get_plupload_default_settings', $settings ); 622 } 623 624 /** 625 * Builds localization strings for the BuddyPress Uploader scripts. 626 * 627 * @since 2.3.0 628 * 629 * @return array Plupload default localization strings. 630 */ 631 function bp_attachments_get_plupload_l10n() { 632 /** 633 * Use this filter to edit localization strings. 634 * 635 * @since 2.3.0 636 * 637 * @param array $value An associative array of the localization strings. 638 */ 639 return apply_filters( 640 'bp_attachments_get_plupload_l10n', 641 array( 642 'queue_limit_exceeded' => __( 'You have attempted to queue too many files.', 'buddypress' ), 643 644 /* translators: %s: File name. */ 645 'file_exceeds_size_limit' => __( '%s exceeds the maximum upload size for this site.', 'buddypress' ), 646 'zero_byte_file' => __( 'This file is empty. Please try another.', 'buddypress' ), 647 'invalid_filetype' => __( 'This file type is not allowed. Please try another.', 'buddypress' ), 648 'not_an_image' => __( 'This file is not an image. Please try another.', 'buddypress' ), 649 'image_memory_exceeded' => __( 'Memory exceeded. Please try another smaller file.', 'buddypress' ), 650 'image_dimensions_exceeded' => __( 'This is larger than the maximum size. Please try another.', 'buddypress' ), 651 'default_error' => __( 'An error occurred. Please try again later.', 'buddypress' ), 652 'missing_upload_url' => __( 'There was a configuration error. Please contact the server administrator.', 'buddypress' ), 653 'upload_limit_exceeded' => __( 'You may only upload 1 file.', 'buddypress' ), 654 'http_error' => __( 'HTTP error.', 'buddypress' ), 655 'upload_failed' => __( 'Upload failed.', 'buddypress' ), 656 657 /* translators: 1: Opening link tag, 2: Closing link tag. */ 658 'big_upload_failed' => __( 'Please try uploading this file with the %1$sbrowser uploader%2$s.', 'buddypress' ), 659 660 /* translators: %s: File name. */ 661 'big_upload_queued' => __( '%s exceeds the maximum upload size for the multi-file uploader when used in your browser.', 'buddypress' ), 662 'io_error' => __( 'IO error.', 'buddypress' ), 663 'security_error' => __( 'Security error.', 'buddypress' ), 664 'file_cancelled' => __( 'File canceled.', 'buddypress' ), 665 'upload_stopped' => __( 'Upload stopped.', 'buddypress' ), 666 'dismiss' => __( 'Dismiss', 'buddypress' ), 667 'crunching' => __( 'Crunching…', 'buddypress' ), 668 'unique_file_warning' => __( 'Make sure to upload a unique file', 'buddypress' ), 669 670 /* translators: %s: File name. */ 671 'error_uploading' => __( '“%s” has failed to upload.', 'buddypress' ), 672 'has_avatar_warning' => __( 'If you'd like to delete the existing profile photo but not upload a new one, please use the delete tab.', 'buddypress' ) 673 ) 674 ); 675 } 676 677 /** 678 * Enqueues the script needed for the Uploader UI. 679 * 680 * @since 2.3.0 681 * 682 * @see BP_Attachment::script_data() && BP_Attachment_Avatar::script_data() for examples showing how 683 * to set specific script data. 684 * 685 * @param string $class Name of the class extending BP_Attachment (eg: BP_Attachment_Avatar). 686 * @return null|WP_Error 687 */ 688 function bp_attachments_enqueue_scripts( $class = '' ) { 689 // Enqueue me just once per page, please. 690 if ( did_action( 'bp_attachments_enqueue_scripts' ) ) { 691 return; 692 } 693 694 if ( ! $class || ! class_exists( $class ) ) { 695 return new WP_Error( 'missing_parameter' ); 696 } 697 698 // Get an instance of the class and get the script data. 699 $attachment = new $class; 700 $script_data = $attachment->script_data(); 701 702 $args = bp_parse_args( $script_data, array( 703 'action' => '', 704 'file_data_name' => '', 705 'max_file_size' => 0, 706 'browse_button' => 'bp-browse-button', 707 'container' => 'bp-upload-ui', 708 'drop_element' => 'drag-drop-area', 709 'bp_params' => array(), 710 'extra_css' => array(), 711 'extra_js' => array(), 712 'feedback_messages' => array(), 713 ), 'attachments_enqueue_scripts' ); 714 715 if ( empty( $args['action'] ) || empty( $args['file_data_name'] ) ) { 716 return new WP_Error( 'missing_parameter' ); 717 } 718 719 // Get the BuddyPress uploader strings. 720 $strings = bp_attachments_get_plupload_l10n(); 721 722 // Get the BuddyPress uploader settings. 723 $settings = bp_attachments_get_plupload_default_settings(); 724 725 // Set feedback messages. 726 if ( ! empty( $args['feedback_messages'] ) ) { 727 $strings['feedback_messages'] = $args['feedback_messages']; 728 } 729 730 // Use a temporary var to ease manipulation. 731 $defaults = $settings['defaults']; 732 733 // Set the upload action. 734 $defaults['multipart_params']['action'] = $args['action']; 735 736 // Set BuddyPress upload parameters if provided. 737 if ( ! empty( $args['bp_params'] ) ) { 738 $defaults['multipart_params']['bp_params'] = $args['bp_params']; 739 } 740 741 // Merge other arguments. 742 $ui_args = array_intersect_key( $args, array( 743 'file_data_name' => true, 744 'browse_button' => true, 745 'container' => true, 746 'drop_element' => true, 747 ) ); 748 749 $defaults = array_merge( $defaults, $ui_args ); 750 751 if ( ! empty( $args['max_file_size'] ) ) { 752 $defaults['filters']['max_file_size'] = $args['max_file_size'] . 'b'; 753 } 754 755 // Specific to BuddyPress Avatars. 756 if ( 'bp_avatar_upload' === $defaults['multipart_params']['action'] ) { 757 758 // Include the cropping informations for avatars. 759 $settings['crop'] = array( 760 'full_h' => bp_core_avatar_full_height(), 761 'full_w' => bp_core_avatar_full_width(), 762 ); 763 764 // Avatar only need 1 file and 1 only! 765 $defaults['multi_selection'] = false; 766 767 // Does the object already has an avatar set. 768 $has_avatar = $defaults['multipart_params']['bp_params']['has_avatar']; 769 770 // What is the object the avatar belongs to. 771 $object = $defaults['multipart_params']['bp_params']['object']; 772 773 // Init the Avatar nav. 774 $avatar_nav = array( 775 'upload' => array( 'id' => 'upload', 'caption' => __( 'Upload', 'buddypress' ), 'order' => 0 ), 776 777 // The delete view will only show if the object has an avatar. 778 'delete' => array( 'id' => 'delete', 'caption' => __( 'Delete', 'buddypress' ), 'order' => 100, 'hide' => (int) ! $has_avatar ), 779 ); 780 781 // Create the Camera Nav if the WebCam capture feature is enabled. 782 if ( bp_avatar_use_webcam() && 'user' === $object ) { 783 $avatar_nav['camera'] = array( 'id' => 'camera', 'caption' => __( 'Take Photo', 'buddypress' ), 'order' => 10 ); 784 785 // Set warning messages. 786 $strings['camera_warnings'] = array( 787 'requesting' => __( 'Please allow us to access to your camera.', 'buddypress'), 788 'loading' => __( 'Please wait as we access your camera.', 'buddypress' ), 789 'loaded' => __( 'Camera loaded. Click on the "Capture" button to take your photo.', 'buddypress' ), 790 'noaccess' => __( 'It looks like you do not have a webcam or we were unable to get permission to use your webcam. Please upload a photo instead.', 'buddypress' ), 791 'errormsg' => __( 'Your browser is not supported. Please upload a photo instead.', 'buddypress' ), 792 'videoerror' => __( 'Video error. Please upload a photo instead.', 'buddypress' ), 793 'ready' => __( 'Your profile photo is ready. Click on the "Save" button to use this photo.', 'buddypress' ), 794 'nocapture' => __( 'No photo was captured. Click on the "Capture" button to take your photo.', 'buddypress' ), 795 ); 796 } 797 798 /** 799 * Use this filter to add a navigation to a custom tool to set the object's avatar. 800 * 801 * @since 2.3.0 802 * 803 * @param array $avatar_nav { 804 * An associative array of available nav items where each item is an array organized this way: 805 * $avatar_nav[ $nav_item_id ]. 806 * @type string $nav_item_id The nav item id in lower case without special characters or space. 807 * @type string $caption The name of the item nav that will be displayed in the nav. 808 * @type int $order An integer to specify the priority of the item nav, choose one. 809 * between 1 and 99 to be after the uploader nav item and before the delete nav item. 810 * @type int $hide If set to 1 the item nav will be hidden 811 * (only used for the delete nav item). 812 * } 813 * @param string $object The object the avatar belongs to (eg: user or group). 814 */ 815 $settings['nav'] = bp_sort_by_key( apply_filters( 'bp_attachments_avatar_nav', $avatar_nav, $object ), 'order', 'num' ); 816 817 // Specific to BuddyPress cover images. 818 } elseif ( 'bp_cover_image_upload' === $defaults['multipart_params']['action'] ) { 819 820 // Cover images only need 1 file and 1 only! 821 $defaults['multi_selection'] = false; 822 823 // Default cover component is members. 824 $cover_component = 'members'; 825 826 // Get the object we're editing the cover image of. 827 $object = $defaults['multipart_params']['bp_params']['object']; 828 829 // Set the cover component according to the object. 830 if ( 'group' === $object ) { 831 $cover_component = 'groups'; 832 } elseif ( 'user' !== $object ) { 833 $cover_component = apply_filters( 'bp_attachments_cover_image_ui_component', $cover_component ); 834 } 835 // Get cover image advised dimensions. 836 $cover_dimensions = bp_attachments_get_cover_image_dimensions( $cover_component ); 837 838 // Set warning messages. 839 $strings['cover_image_warnings'] = apply_filters( 'bp_attachments_cover_image_ui_warnings', array( 840 'dimensions' => sprintf( 841 /* translators: 1: the advised width size in pixels. 2: the advised height size in pixels. */ 842 __( 'For better results, make sure to upload an image that is larger than %1$spx wide, and %2$spx tall.', 'buddypress' ), 843 (int) $cover_dimensions['width'], 844 (int) $cover_dimensions['height'] 845 ), 846 ) ); 847 } 848 849 // Set Plupload settings. 850 $settings['defaults'] = $defaults; 851 852 /** 853 * Enqueue some extra styles if required 854 * 855 * Extra styles need to be registered. 856 */ 857 if ( ! empty( $args['extra_css'] ) ) { 858 foreach ( (array) $args['extra_css'] as $css ) { 859 if ( empty( $css ) ) { 860 continue; 861 } 862 863 wp_enqueue_style( $css ); 864 } 865 } 866 867 wp_enqueue_script ( 'bp-plupload' ); 868 wp_localize_script( 'bp-plupload', 'BP_Uploader', array( 'strings' => $strings, 'settings' => $settings ) ); 869 870 /** 871 * Enqueue some extra scripts if required 872 * 873 * Extra scripts need to be registered. 874 */ 875 if ( ! empty( $args['extra_js'] ) ) { 876 foreach ( (array) $args['extra_js'] as $js ) { 877 if ( empty( $js ) ) { 878 continue; 879 } 880 881 wp_enqueue_script( $js ); 882 } 883 } 884 885 /** 886 * Fires at the conclusion of bp_attachments_enqueue_scripts() 887 * to avoid the scripts to be loaded more than once. 888 * 889 * @since 2.3.0 890 */ 891 do_action( 'bp_attachments_enqueue_scripts' ); 892 } 893 894 /** 895 * Check the current user's capability to edit an avatar for a given object. 896 * 897 * @since 2.3.0 898 * 899 * @param string $capability The capability to check. 900 * @param array $args An array containing the item_id and the object to check. 901 * @return bool 902 */ 903 function bp_attachments_current_user_can( $capability, $args = array() ) { 904 $can = false; 905 906 if ( 'edit_avatar' === $capability || 'edit_cover_image' === $capability ) { 907 /** 908 * Needed avatar arguments are set. 909 */ 910 if ( isset( $args['item_id'] ) && isset( $args['object'] ) ) { 911 // Group profile photo. 912 if ( bp_is_active( 'groups' ) && 'group' === $args['object'] ) { 913 if ( bp_is_group_create() ) { 914 $can = (bool) groups_is_user_creator( bp_loggedin_user_id(), $args['item_id'] ) || bp_current_user_can( 'bp_moderate' ); 915 } else { 916 $can = (bool) groups_is_user_admin( bp_loggedin_user_id(), $args['item_id'] ) || bp_current_user_can( 'bp_moderate' ); 917 } 918 // User profile photo. 919 } elseif ( bp_is_active( 'members' ) && 'user' === $args['object'] ) { 920 $can = bp_loggedin_user_id() === (int) $args['item_id'] || bp_current_user_can( 'bp_moderate' ); 921 } 922 /** 923 * No avatar arguments, fallback to bp_user_can_create_groups() 924 * or bp_is_item_admin() 925 */ 926 } else { 927 if ( bp_is_group_create() ) { 928 $can = bp_user_can_create_groups(); 929 } else { 930 $can = bp_is_item_admin(); 931 } 932 } 933 } 934 935 return apply_filters( 'bp_attachments_current_user_can', $can, $capability, $args ); 936 } 937 938 /** 939 * Send a JSON response back to an Ajax upload request. 940 * 941 * @since 2.3.0 942 * 943 * @param bool $success True for a success, false otherwise. 944 * @param bool $is_html4 True if the Plupload runtime used is html4, false otherwise. 945 * @param mixed $data Data to encode as JSON, then print and die. 946 */ 947 function bp_attachments_json_response( $success, $is_html4 = false, $data = null ) { 948 $response = array( 'success' => $success ); 949 950 if ( isset( $data ) ) { 951 $response['data'] = $data; 952 } 953 954 // Send regular json response. 955 if ( ! $is_html4 ) { 956 wp_send_json( $response ); 957 958 /** 959 * Send specific json response 960 * the html4 Plupload handler requires a text/html content-type for older IE. 961 * See https://core.trac.wordpress.org/ticket/31037 962 */ 963 } else { 964 echo wp_json_encode( $response ); 965 966 wp_die(); 967 } 968 } 969 970 /** 971 * Get an Attachment template part. 972 * 973 * @since 2.3.0 974 * 975 * @param string $slug Template part slug. eg 'uploader' for 'uploader.php'. 976 * @return bool 977 */ 978 function bp_attachments_get_template_part( $slug ) { 979 $switched = false; 980 981 /* 982 * Use bp-legacy attachment template part for older bp-default themes or if in 983 * admin area. 984 */ 985 if ( ! bp_use_theme_compat_with_current_theme() || ( is_admin() && ( ! defined( 'DOING_AJAX' ) || ! DOING_AJAX ) ) ) { 986 $current = bp_get_theme_compat_id(); 987 if ( 'legacy' !== $current ) { 988 $switched = true; 989 bp_setup_theme_compat( 'legacy' ); 990 } 991 } 992 993 // Load the template part. 994 bp_get_template_part( 'assets/_attachments/' . $slug ); 995 996 if ( $switched ) { 997 bp_setup_theme_compat( $current ); 998 } 999 } 1000 1001 /** Cover Image ***************************************************************/ 1002 1003 /** 1004 * Get the cover image settings 1005 * 1006 * @since 2.4.0 1007 * 1008 * @param string $component The component to get the settings for ("members" for user or "groups"). 1009 * @return false|array The cover image settings in array, false on failure. 1010 */ 1011 function bp_attachments_get_cover_image_settings( $component = 'members' ) { 1012 // Default parameters. 1013 $args = array(); 1014 1015 // First look in BP Theme Compat. 1016 $cover_image = bp_get_theme_compat_feature( 'cover_image' ); 1017 1018 if ( ! empty( $cover_image ) ) { 1019 $args = (array) $cover_image; 1020 } 1021 1022 // Set default args. 1023 $default_args = wp_parse_args( 1024 $args, 1025 array( 1026 'components' => array(), 1027 'width' => 1300, 1028 'height' => 225, 1029 'callback' => '', 1030 'theme_handle' => '', 1031 'default_cover' => '', 1032 ) 1033 ); 1034 1035 // Handle deprecated xProfile fitler. 1036 if ( 'members' === $component ) { 1037 /** This filter is documented in wp-includes/deprecated.php */ 1038 $args = apply_filters_deprecated( 'bp_before_xprofile_cover_image_settings_parse_args', array( $default_args ), '6.0.0', 'bp_before_members_cover_image_settings_parse_args' ); 1039 } 1040 1041 /** 1042 * Then let people override/set the feature using this dynamic filter 1043 * 1044 * Eg: for the user's profile cover image use: 1045 * add_filter( 'bp_before_members_cover_image_settings_parse_args', 'your_filter', 10, 1 ); 1046 * 1047 * @since 2.4.0 1048 * 1049 * @param array $settings The cover image settings 1050 */ 1051 $settings = bp_parse_args( $args, $default_args, $component . '_cover_image_settings' ); 1052 1053 // Handle deprecated xProfile fitler. 1054 if ( 'members' === $component ) { 1055 /** This filter is documented in wp-includes/deprecated.php */ 1056 $settings = apply_filters_deprecated( 'bp_after_xprofile_cover_image_settings_parse_args', array( $settings ), '6.0.0', 'bp_after_members_cover_image_settings_parse_args' ); 1057 } 1058 1059 if ( empty( $settings['components'] ) || empty( $settings['callback'] ) || empty( $settings['theme_handle'] ) ) { 1060 return false; 1061 } 1062 1063 // Current component is not supported. 1064 if ( ! in_array( $component, $settings['components'] ) ) { 1065 return false; 1066 } 1067 1068 // Finally return the settings. 1069 return $settings; 1070 } 1071 1072 /** 1073 * Get cover image Width and Height. 1074 * 1075 * @since 2.4.0 1076 * 1077 * @param string $component The BuddyPress component concerned ("members" for user or "groups"). 1078 * @return array|bool An associative array containing the advised width and height for the cover image. False if settings are empty. 1079 */ 1080 function bp_attachments_get_cover_image_dimensions( $component = 'members' ) { 1081 // Let's prevent notices when setting the warning strings. 1082 $default = array( 'width' => 0, 'height' => 0 ); 1083 1084 $settings = bp_attachments_get_cover_image_settings( $component ); 1085 1086 if ( empty( $settings ) ) { 1087 return false; 1088 } 1089 1090 // Get width and height. 1091 $wh = array_intersect_key( $settings, $default ); 1092 1093 /** 1094 * Filter here to edit the cover image dimensions if needed. 1095 * 1096 * @since 2.4.0 1097 * 1098 * @param array $wh An associative array containing the width and height values. 1099 * @param array $settings An associative array containing all the feature settings. 1100 * @param string $compnent The requested component. 1101 */ 1102 return apply_filters( 'bp_attachments_get_cover_image_dimensions', $wh, $settings, $component ); 1103 } 1104 1105 /** 1106 * Are we on a page to edit a cover image? 1107 * 1108 * @since 2.4.0 1109 * 1110 * @return bool True if on a page to edit a cover image, false otherwise. 1111 */ 1112 function bp_attachments_cover_image_is_edit() { 1113 $retval = false; 1114 1115 $current_component = bp_current_component(); 1116 if ( bp_is_user() ) { 1117 $current_component = 'members'; 1118 } 1119 1120 if ( ! bp_is_active( $current_component, 'cover_image' ) ) { 1121 return $retval; 1122 } 1123 1124 if ( bp_is_user_change_cover_image() ) { 1125 $retval = ! bp_disable_cover_image_uploads(); 1126 } 1127 1128 if ( ( bp_is_group_admin_page() && 'group-cover-image' == bp_get_group_current_admin_tab() ) 1129 || ( bp_is_group_create() && bp_is_group_creation_step( 'group-cover-image' ) ) ) { 1130 $retval = ! bp_disable_group_cover_image_uploads(); 1131 } 1132 1133 return apply_filters( 'bp_attachments_cover_image_is_edit', $retval, $current_component ); 1134 } 1135 1136 /** 1137 * Does the user has a cover image? 1138 * 1139 * @since 2.4.0 1140 * 1141 * @param int $user_id User ID to retrieve cover image for. 1142 * @return bool True if the user has a cover image, false otherwise. 1143 */ 1144 function bp_attachments_get_user_has_cover_image( $user_id = 0 ) { 1145 if ( empty( $user_id ) ) { 1146 $user_id = bp_displayed_user_id(); 1147 } 1148 1149 $cover_src = bp_attachments_get_attachment( 'url', array( 1150 'item_id' => $user_id, 1151 ) ); 1152 1153 return (bool) apply_filters( 'bp_attachments_get_user_has_cover_image', $cover_src, $user_id ); 1154 } 1155 1156 /** 1157 * Does the group has a cover image? 1158 * 1159 * @since 2.4.0 1160 * @since 6.0.0 Renamed the filter coherently. 1161 * 1162 * @param int $group_id Group ID to check cover image existence for. 1163 * @return bool True if the group has a cover image, false otherwise. 1164 */ 1165 function bp_attachments_get_group_has_cover_image( $group_id = 0 ) { 1166 if ( empty( $group_id ) ) { 1167 $group_id = bp_get_current_group_id(); 1168 } 1169 1170 $cover_src = bp_attachments_get_attachment( 'url', array( 1171 'object_dir' => 'groups', 1172 'item_id' => $group_id, 1173 ) ); 1174 1175 return (bool) apply_filters( 'bp_attachments_get_group_has_cover_image', $cover_src, $group_id ); 1176 } 1177 1178 /** 1179 * Generate the cover image file. 1180 * 1181 * @since 2.4.0 1182 * 1183 * @param array $args { 1184 * @type string $file The absolute path to the image. Required. 1185 * @type string $component The component for the object (eg: groups, members). Required. 1186 * @type string $cover_image_dir The Cover image dir to write the image into. Required. 1187 * } 1188 * @param BP_Attachment_Cover_Image|null $cover_image_class The class to use to fit the cover image. 1189 * @return false|array An array containing cover image data on success, false otherwise. 1190 */ 1191 function bp_attachments_cover_image_generate_file( $args = array(), $cover_image_class = null ) { 1192 // Bail if an argument is missing. 1193 if ( empty( $args['file'] ) || empty( $args['component'] ) || empty( $args['cover_image_dir'] ) ) { 1194 return false; 1195 } 1196 1197 // Get advised dimensions for the cover image. 1198 $dimensions = bp_attachments_get_cover_image_dimensions( $args['component'] ); 1199 1200 // No dimensions or the file does not match with the cover image dir, stop! 1201 if ( false === $dimensions || $args['file'] !== $args['cover_image_dir'] . '/' . wp_basename( $args['file'] ) ) { 1202 return false; 1203 } 1204 1205 if ( ! is_a( $cover_image_class, 'BP_Attachment_Cover_Image' ) ) { 1206 $cover_image_class = new BP_Attachment_Cover_Image(); 1207 } 1208 1209 $upload_dir = bp_attachments_cover_image_upload_dir(); 1210 1211 // Make sure the file is inside the Cover Image Upload path. 1212 if ( false === strpos( $args['file'], $upload_dir['basedir'] ) ) { 1213 return false; 1214 } 1215 1216 // Resize the image so that it fit with the cover image dimensions. 1217 $cover_image = $cover_image_class->fit( $args['file'], $dimensions ); 1218 $is_too_small = false; 1219 1220 // Image is too small in width and height. 1221 if ( empty( $cover_image ) ) { 1222 $cover_file = $cover_image_class->generate_filename( $args['file'] ); 1223 @rename( $args['file'], $cover_file ); 1224 1225 // It's too small! 1226 $is_too_small = true; 1227 } elseif ( ! empty( $cover_image['path'] ) ) { 1228 $cover_file = $cover_image['path']; 1229 1230 // Image is too small in width or height. 1231 if ( $cover_image['width'] < $dimensions['width'] || $cover_image['height'] < $dimensions['height'] ) { 1232 $is_too_small = true; 1233 } 1234 } 1235 1236 // We were not able to generate the cover image file. 1237 if ( empty( $cover_file ) ) { 1238 return false; 1239 } 1240 1241 // Do some clean up with old cover image, now a new one is set. 1242 $cover_basename = wp_basename( $cover_file ); 1243 1244 if ( $att_dir = opendir( $args['cover_image_dir'] ) ) { 1245 while ( false !== ( $attachment_file = readdir( $att_dir ) ) ) { 1246 // Skip directories and the new cover image. 1247 if ( 2 < strlen( $attachment_file ) && 0 !== strpos( $attachment_file, '.' ) && $cover_basename !== $attachment_file ) { 1248 @unlink( $args['cover_image_dir'] . '/' . $attachment_file ); 1249 } 1250 } 1251 } 1252 1253 // Finally return needed data. 1254 return array( 1255 'cover_file' => $cover_file, 1256 'cover_basename' => $cover_basename, 1257 'is_too_small' => $is_too_small 1258 ); 1259 } 1260 1261 /** 1262 * Ajax Upload and set a cover image 1263 * 1264 * @since 2.4.0 1265 * 1266 * @return string|null A json object containing success data if the upload succeeded, 1267 * error message otherwise. 1268 */ 1269 function bp_attachments_cover_image_ajax_upload() { 1270 if ( ! bp_is_post_request() ) { 1271 wp_die(); 1272 } 1273 1274 check_admin_referer( 'bp-uploader' ); 1275 1276 // Sending the json response will be different if the current Plupload runtime is html4. 1277 $is_html4 = ! empty( $_POST['html4' ] ); 1278 1279 if ( empty( $_POST['bp_params'] ) ) { 1280 bp_attachments_json_response( false, $is_html4 ); 1281 } 1282 1283 $bp_params = bp_parse_args( $_POST['bp_params'], array( 1284 'object' => 'user', 1285 'item_id' => bp_loggedin_user_id(), 1286 ), 'attachments_cover_image_ajax_upload' ); 1287 1288 $bp_params['item_id'] = (int) $bp_params['item_id']; 1289 $bp_params['object'] = sanitize_text_field( $bp_params['object'] ); 1290 1291 // We need the object to set the uploads dir filter. 1292 if ( empty( $bp_params['object'] ) ) { 1293 bp_attachments_json_response( false, $is_html4 ); 1294 } 1295 1296 // Capability check. 1297 if ( ! bp_attachments_current_user_can( 'edit_cover_image', $bp_params ) ) { 1298 bp_attachments_json_response( false, $is_html4 ); 1299 } 1300 1301 $bp = buddypress(); 1302 $needs_reset = array(); 1303 1304 // Member's cover image. 1305 if ( 'user' === $bp_params['object'] ) { 1306 $object_data = array( 'dir' => 'members', 'component' => 'members' ); 1307 1308 if ( ! bp_displayed_user_id() && ! empty( $bp_params['item_id'] ) ) { 1309 $needs_reset = array( 'key' => 'displayed_user', 'value' => $bp->displayed_user ); 1310 $bp->displayed_user->id = $bp_params['item_id']; 1311 } 1312 1313 // Group's cover image. 1314 } elseif ( 'group' === $bp_params['object'] ) { 1315 $object_data = array( 'dir' => 'groups', 'component' => 'groups' ); 1316 1317 if ( ! bp_get_current_group_id() && ! empty( $bp_params['item_id'] ) ) { 1318 $needs_reset = array( 'component' => 'groups', 'key' => 'current_group', 'value' => $bp->groups->current_group ); 1319 $bp->groups->current_group = groups_get_group( $bp_params['item_id'] ); 1320 } 1321 1322 // Other object's cover image. 1323 } else { 1324 $object_data = apply_filters( 'bp_attachments_cover_image_object_dir', array(), $bp_params['object'] ); 1325 } 1326 1327 // Stop here in case of a missing parameter for the object. 1328 if ( empty( $object_data['dir'] ) || empty( $object_data['component'] ) ) { 1329 bp_attachments_json_response( false, $is_html4 ); 1330 } 1331 1332 /** 1333 * Filters whether or not to handle cover image uploading. 1334 * 1335 * If you want to override this function, make sure you return an array with the 'result' key set. 1336 * 1337 * @since 2.5.1 1338 * 1339 * @param array $value 1340 * @param array $bp_params 1341 * @param array $needs_reset Stores original value of certain globals we need to revert to later. 1342 * @param array $object_data 1343 */ 1344 $pre_filter = apply_filters( 'bp_attachments_pre_cover_image_ajax_upload', array(), $bp_params, $needs_reset, $object_data ); 1345 if ( isset( $pre_filter['result'] ) ) { 1346 bp_attachments_json_response( $pre_filter['result'], $is_html4, $pre_filter ); 1347 } 1348 1349 $cover_image_attachment = new BP_Attachment_Cover_Image(); 1350 $uploaded = $cover_image_attachment->upload( $_FILES ); 1351 1352 // Reset objects. 1353 if ( ! empty( $needs_reset ) ) { 1354 if ( ! empty( $needs_reset['component'] ) ) { 1355 $bp->{$needs_reset['component']}->{$needs_reset['key']} = $needs_reset['value']; 1356 } else { 1357 $bp->{$needs_reset['key']} = $needs_reset['value']; 1358 } 1359 } 1360 1361 if ( ! empty( $uploaded['error'] ) ) { 1362 // Upload error response. 1363 bp_attachments_json_response( false, $is_html4, array( 1364 'type' => 'upload_error', 1365 'message' => sprintf( 1366 /* translators: %s: the upload error message */ 1367 __( 'Upload Failed! Error was: %s', 'buddypress' ), 1368 $uploaded['error'] 1369 ), 1370 ) ); 1371 } 1372 1373 $error_message = __( 'There was a problem uploading the cover image.', 'buddypress' ); 1374 1375 $bp_attachments_uploads_dir = bp_attachments_cover_image_upload_dir(); 1376 1377 // The BP Attachments Uploads Dir is not set, stop. 1378 if ( ! $bp_attachments_uploads_dir ) { 1379 bp_attachments_json_response( false, $is_html4, array( 1380 'type' => 'upload_error', 1381 'message' => $error_message, 1382 ) ); 1383 } 1384 1385 $cover_subdir = $object_data['dir'] . '/' . $bp_params['item_id'] . '/cover-image'; 1386 $cover_dir = trailingslashit( $bp_attachments_uploads_dir['basedir'] ) . $cover_subdir; 1387 1388 if ( 1 === validate_file( $cover_dir ) || ! is_dir( $cover_dir ) ) { 1389 // Upload error response. 1390 bp_attachments_json_response( false, $is_html4, array( 1391 'type' => 'upload_error', 1392 'message' => $error_message, 1393 ) ); 1394 } 1395 1396 /* 1397 * Generate the cover image so that it fit to feature's dimensions 1398 * 1399 * Unlike the avatar, uploading and generating the cover image is happening during 1400 * the same Ajax request, as we already instantiated the BP_Attachment_Cover_Image 1401 * class, let's use it. 1402 */ 1403 $cover = bp_attachments_cover_image_generate_file( array( 1404 'file' => $uploaded['file'], 1405 'component' => $object_data['component'], 1406 'cover_image_dir' => $cover_dir 1407 ), $cover_image_attachment ); 1408 1409 if ( ! $cover ) { 1410 bp_attachments_json_response( false, $is_html4, array( 1411 'type' => 'upload_error', 1412 'message' => $error_message, 1413 ) ); 1414 } 1415 1416 $cover_url = trailingslashit( $bp_attachments_uploads_dir['baseurl'] ) . $cover_subdir . '/' . $cover['cover_basename']; 1417 1418 // 1 is success. 1419 $feedback_code = 1; 1420 1421 // 0 is the size warning. 1422 if ( $cover['is_too_small'] ) { 1423 $feedback_code = 0; 1424 } 1425 1426 // Set the name of the file. 1427 $name = $_FILES['file']['name']; 1428 $name_parts = pathinfo( $name ); 1429 $name = trim( substr( $name, 0, - ( 1 + strlen( $name_parts['extension'] ) ) ) ); 1430 1431 // Set some arguments for filters. 1432 $item_id = (int) $bp_params['item_id']; 1433 $component = $object_data['component']; 1434 1435 /** 1436 * Fires if the new cover image was successfully uploaded. 1437 * 1438 * The dynamic portion of the hook will be members in case of a user's 1439 * cover image, groups in case of a group's cover image. For instance: 1440 * Use add_action( 'members_cover_image_uploaded' ) to run your specific 1441 * code once the user has set his cover image. 1442 * 1443 * @since 2.4.0 1444 * @since 3.0.0 Added $cover_url, $name, $feedback_code arguments. 1445 * 1446 * @param int $item_id Inform about the item id the cover image was set for. 1447 * @param string $name Filename. 1448 * @param string $cover_url URL to the image. 1449 * @param int $feedback_code If value not 1, an error occured. 1450 */ 1451 do_action( 1452 $component . '_cover_image_uploaded', 1453 $item_id, 1454 $name, 1455 $cover_url, 1456 $feedback_code 1457 ); 1458 1459 // Handle deprecated xProfile action. 1460 if ( 'members' === $component ) { 1461 /** This filter is documented in wp-includes/deprecated.php */ 1462 do_action_deprecated( 1463 'xprofile_cover_image_uploaded', 1464 array( 1465 $item_id, 1466 $name, 1467 $cover_url, 1468 $feedback_code, 1469 ), 1470 '6.0.0', 1471 'members_cover_image_deleted' 1472 ); 1473 } 1474 1475 // Finally return the cover image url to the UI. 1476 bp_attachments_json_response( true, $is_html4, array( 1477 'name' => $name, 1478 'url' => $cover_url, 1479 'feedback_code' => $feedback_code, 1480 ) ); 1481 } 1482 add_action( 'wp_ajax_bp_cover_image_upload', 'bp_attachments_cover_image_ajax_upload' ); 1483 1484 /** 1485 * Ajax delete a cover image for a given object and item id. 1486 * 1487 * @since 2.4.0 1488 * 1489 * @return string|null A json object containing success data if the cover image was deleted 1490 * error message otherwise. 1491 */ 1492 function bp_attachments_cover_image_ajax_delete() { 1493 if ( ! bp_is_post_request() ) { 1494 wp_send_json_error(); 1495 } 1496 1497 if ( empty( $_POST['object'] ) || empty( $_POST['item_id'] ) || ( ! ctype_digit( $_POST['item_id'] ) && ! is_int( $_POST['item_id'] ) ) ) { 1498 wp_send_json_error(); 1499 } 1500 1501 $args = array( 1502 'object' => sanitize_text_field( $_POST['object'] ), 1503 'item_id' => (int) $_POST['item_id'], 1504 ); 1505 1506 // Check permissions. 1507 check_admin_referer( 'bp_delete_cover_image', 'nonce' ); 1508 if ( ! bp_attachments_current_user_can( 'edit_cover_image', $args ) ) { 1509 wp_send_json_error(); 1510 } 1511 1512 // Set object for the user's case. 1513 if ( 'user' === $args['object'] ) { 1514 $component = 'members'; 1515 $dir = 'members'; 1516 1517 // Set it for any other cases. 1518 } else { 1519 $component = $args['object'] . 's'; 1520 $dir = $component; 1521 } 1522 1523 // Handle delete. 1524 if ( bp_attachments_delete_file( array( 'item_id' => $args['item_id'], 'object_dir' => $dir, 'type' => 'cover-image' ) ) ) { 1525 $item_id = (int) $args['item_id']; 1526 1527 /** 1528 * Fires if the cover image was successfully deleted. 1529 * 1530 * The dynamic portion of the hook will be members in case of a user's 1531 * cover image, groups in case of a group's cover image. For instance: 1532 * Use add_action( 'members_cover_image_deleted' ) to run your specific 1533 * code once the user has deleted his cover image. 1534 * 1535 * @since 2.8.0 1536 * 1537 * @param int $item_id Inform about the item id the cover image was deleted for. 1538 */ 1539 do_action( "{$component}_cover_image_deleted", $item_id ); 1540 1541 // Handle deprecated xProfile action. 1542 if ( 'members' === $component ) { 1543 /** This filter is documented in wp-includes/deprecated.php */ 1544 do_action_deprecated( 'xprofile_cover_image_deleted', array( $item_id ), '6.0.0', 'members_cover_image_deleted' ); 1545 } 1546 1547 $response = array( 1548 'reset_url' => '', 1549 'feedback_code' => 3, 1550 ); 1551 1552 // Get cover image settings in case there's a default header. 1553 $cover_params = bp_attachments_get_cover_image_settings( $component ); 1554 1555 // Check if there's a default cover. 1556 if ( ! empty( $cover_params['default_cover'] ) ) { 1557 $response['reset_url'] = $cover_params['default_cover']; 1558 } 1559 1560 wp_send_json_success( $response ); 1561 1562 } else { 1563 wp_send_json_error( array( 1564 'feedback_code' => 2, 1565 ) ); 1566 } 1567 } 1568 add_action( 'wp_ajax_bp_cover_image_delete', 'bp_attachments_cover_image_ajax_delete' );
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Sat Mar 6 01:01:37 2021 | Cross-referenced by PHPXref 0.7.1 |