Ticket #6570: 6570.02.markup-changes.patch
File 6570.02.markup-changes.patch, 60.7 KB (added by , 10 years ago) |
---|
-
src/bp-core/bp-core-attachments.php
diff --git src/bp-core/bp-core-attachments.php src/bp-core/bp-core-attachments.php index 1fadb11..a652386 100644
function bp_attachments_enqueue_scripts( $class = '' ) { 257 257 * @param string $object the object the avatar belongs to (eg: user or group) 258 258 */ 259 259 $settings['nav'] = bp_sort_by_key( apply_filters( 'bp_attachments_avatar_nav', $avatar_nav, $object ), 'order', 'num' ); 260 261 // Specific to BuddyPress cover images 262 } elseif ( 'bp_cover_image_upload' === $defaults['multipart_params']['action'] ) { 263 264 // Cover images only need 1 file and 1 only! 265 $defaults['multi_selection'] = false; 266 267 // Default cover component is xprofile 268 $cover_component = 'xprofile'; 269 270 // Get the object we're editing the cover image of 271 $object = $defaults['multipart_params']['bp_params']['object']; 272 273 // Set the cover component according to the object 274 if ( 'group' === $object ) { 275 $cover_component = 'groups'; 276 } elseif ( 'user' !== $object ) { 277 $cover_component = apply_filters( 'bp_attachments_cover_image_ui_component', $cover_component ); 278 } 279 // Get cover image advised dimensions 280 $cover_dimensions = bp_attachments_get_cover_image_dimensions( $cover_component ); 281 282 // Set warning messages 283 $strings['cover_image_warnings'] = apply_filters( 'bp_attachments_cover_image_ui_warnings', array( 284 'dimensions' => sprintf( 285 __( 'For better results, make sure to upload an image having a width >= %1$s px and a height >= %2$s px.', 'buddypress' ), 286 (int) $cover_dimensions['width'], 287 (int) $cover_dimensions['height'] 288 ), 289 ) ); 260 290 } 261 291 262 292 // Set Plupload settings … … function bp_attachments_enqueue_scripts( $class = '' ) { 317 347 function bp_attachments_current_user_can( $capability, $args = array() ) { 318 348 $can = false; 319 349 320 if ( 'edit_avatar' === $capability ) {350 if ( 'edit_avatar' === $capability || 'edit_cover_image' === $capability ) { 321 351 /** 322 352 * Needed avatar arguments are set. 323 353 */ … … function bp_attachments_get_template_part( $slug ) { 410 440 bp_get_template_part( $attachment_template_part ); 411 441 } 412 442 } 443 444 /** Cover Image ***************************************************************/ 445 446 /** 447 * Get the cover image settings 448 * 449 * @since BuddyPress (2.4.0) 450 * 451 * @param string $component the component to get the settings for ("xprofile" for user or "groups") 452 * @return array the cover image settings 453 */ 454 function bp_attachments_get_cover_image_settings( $component = 'xprofile' ) { 455 // Default parameters 456 $args = array(); 457 458 // First look in BP Theme Compat 459 $cover_image = bp_get_theme_compat_feature( 'cover_image' ); 460 461 if ( ! empty( $cover_image ) ) { 462 $args = (array) $cover_image; 463 } 464 465 /** 466 * Then let people override/set the feature using this dynamic filter 467 * 468 * eg: for the user's profile cover image use : 469 * add_filter( 'bp_before_xprofile_cover_image_settings_parse_args', 'your_filter', 10, 1 ); 470 * 471 * @since BuddyPress (2.4.0) 472 * 473 * @param array $settings the cover image settings 474 */ 475 $settings = bp_parse_args( $args, array( 476 'components' => array(), 477 'width' => 1300, 478 'height' => 225, 479 'callback' => '', 480 'theme_handle' => '', 481 'default_cover' => '', 482 ), $component . '_cover_image_settings' ); 483 484 if ( empty( $settings['components'] ) || empty( $settings['callback'] ) || empty( $settings['theme_handle'] ) ) { 485 return false; 486 } 487 488 // Current component is not supported 489 if ( ! in_array( $component, $settings['components'] ) ) { 490 return false; 491 } 492 493 // Finally return the settings 494 return $settings; 495 } 496 497 /** 498 * Get cover image Width and Height 499 * 500 * @since BuddyPress (2.4.0) 501 * 502 * @param string $component the BuddyPress component concerned ("xprofile" for user or "groups") 503 * @return array an associative array containing the advised width and height for the cover image 504 */ 505 function bp_attachments_get_cover_image_dimensions( $component = 'xprofile' ) { 506 // Let's prevent notices when setting the warning strings 507 $default = array( 'width' => 0, 'height' => 0 ); 508 509 $settings = bp_attachments_get_cover_image_settings( $component ); 510 511 if ( empty( $settings ) ) { 512 return false; 513 } 514 515 // Get width and height 516 $wh = array_intersect_key( $settings, $default ); 517 518 /** 519 * Filter here to edit the cover image dimensions if needed. 520 * 521 * @since BuddyPress (2.4.0) 522 * 523 * @param array $wh an associative array containing the width and height values 524 * @param array $settings an associative array containing all the feature settings 525 * @param string $compnent the requested component 526 */ 527 return apply_filters( 'bp_attachments_get_cover_image_dimensions', $wh, $settings, $component ); 528 } 529 530 /** 531 * Are we on a page to edit a cover image ? 532 * 533 * @since BuddyPress (2.4.0) 534 * 535 * @todo The Groups single item part 536 * @return bool True if on a page to edit a cover image, false otherwise 537 */ 538 function bp_attachments_cover_image_is_edit() { 539 $retval = false; 540 541 $current_component = bp_current_component(); 542 if ( 'profile' === $current_component ) { 543 $current_component = 'xprofile'; 544 } 545 546 if ( ! bp_is_active( $current_component, 'cover_image' ) ) { 547 return $retval; 548 } 549 550 if ( bp_is_user_change_cover_image() ) { 551 $retval = ! bp_disable_avatar_uploads(); 552 } 553 554 /** 555 * @todo 556 * if ( bp_is_group_change_cover_image() ) $retval = ! bp_disable_group_avatar_uploads(); 557 */ 558 559 return apply_filters( 'bp_attachments_cover_image_is_edit', $retval, $current_component ); 560 } 561 562 /** 563 * Get the url or the path for a type of attachment 564 * 565 * @since BuddyPress (2.4.0) 566 * 567 * @param string $data whether to get the url or the path 568 * @param array $args { 569 * @type string $object_dir The object dir (eg: members/groups). Defaults to members. 570 * @type int $item_id The object id (eg: a user or a group id). Defaults to current user. 571 * @type string $type The type of the attachment which is also the subdir where files are saved. 572 * Defaults to 'cover-image' 573 * @type string $file The name of the file. 574 * } 575 * @return string|bool the url or the path to the attachment, false otherwise 576 */ 577 function bp_attachments_get_attachment( $data = 'url', $args = array() ) { 578 // Default value 579 $attachment_data = false; 580 581 $r = bp_parse_args( $args, array( 582 'object_dir' => 'members', 583 'item_id' => bp_loggedin_user_id(), 584 'type' => 'cover-image', 585 'file' => '', 586 ), 'attachments_get_attachment_src' ); 587 588 // Get BuddyPress Upload Dir 589 $bp_upload_dir = bp_upload_dir(); 590 591 $type_subdir = 'buddypress/' . $r['object_dir'] . '/' . $r['item_id'] . '/' . $r['type']; 592 $type_dir = trailingslashit( $bp_upload_dir['basedir'] ) . $type_subdir; 593 594 if ( ! is_dir( $type_dir ) ) { 595 return $attachment_data; 596 } 597 598 if ( ! empty( $r['file'] ) ) { 599 if ( ! file_exists( trailingslashit( $type_dir ) . $r['file'] ) ) { 600 return $attachment_data; 601 } 602 603 if ( 'url' === $data ) { 604 $attachment_data = trailingslashit( $bp_upload_dir['baseurl'] ) . $type_subdir . '/' . $r['file']; 605 } else { 606 $attachment_data = trailingslashit( $type_dir ) . $r['file']; 607 } 608 609 } else { 610 $file = false; 611 612 // Open the directory and get the first file 613 if ( $att_dir = opendir( $type_dir ) ) { 614 615 while ( false !== ( $attachment_file = readdir( $att_dir ) ) ) { 616 // Look for the first file having the type in its name 617 if ( false !== strpos( $attachment_file, $r['type'] ) && empty( $file ) ) { 618 $file = $attachment_file; 619 break; 620 } 621 } 622 } 623 624 if ( empty( $file ) ) { 625 return $attachment_data; 626 } 627 628 if ( 'url' === $data ) { 629 $attachment_data = trailingslashit( $bp_upload_dir['baseurl'] ) . $type_subdir . '/' . $file; 630 } else { 631 $attachment_data = trailingslashit( $type_dir ) . $file; 632 } 633 } 634 635 return $attachment_data; 636 } 637 638 /** 639 * Does the user has a cover image ? 640 * 641 * @since BuddyPress (2.4.0) 642 * 643 * @param int $user_id 644 * @return bool True if the user has a cover image, false otherwise 645 */ 646 function bp_attachments_get_user_has_cover_image( $user_id = 0 ) { 647 if ( empty( $user_id ) ) { 648 $user_id = bp_displayed_user_id(); 649 } 650 651 $cover_src = bp_attachments_get_attachment( 'url', array( 652 'item_id' => $user_id, 653 ) ); 654 655 return (bool) apply_filters( 'bp_attachments_get_user_has_cover_image', $cover_src, $user_id ); 656 } 657 658 /** 659 * Does the group has a cover image ? 660 * 661 * @since BuddyPress (2.4.0) 662 * 663 * @param int $group_id 664 * @return bool True if the group has a cover image, false otherwise 665 */ 666 function bp_attachments_get_group_has_cover_image( $group_id = 0 ) { 667 if ( empty( $group_id ) ) { 668 $group_id = bp_get_current_group_id(); 669 } 670 671 $cover_src = bp_attachments_get_attachment( 'url', array( 672 'object_dir' => 'groups', 673 'item_id' => $group_id, 674 ) ); 675 676 return (bool) apply_filters( 'bp_attachments_get_user_has_cover_image', $cover_src, $group_id ); 677 } 678 679 /** 680 * Delete an attachment for the given arguments 681 * 682 * @since BuddyPress (2.4.0) 683 * 684 * @param array $args 685 * @see bp_attachments_get_attachment() For more information on accepted arguments. 686 * @return bool True if the attachment was deleted, false otherwise 687 */ 688 function bp_attachments_delete_file( $args = array() ) { 689 $cover_path = bp_attachments_get_attachment( 'path', $args ); 690 691 if ( empty( $cover_path ) ) { 692 return false; 693 } 694 695 @unlink( $cover_path ); 696 return true; 697 } 698 699 /** 700 * Ajax Upload and set a cover image 701 * 702 * @since BuddyPress (2.4.0) 703 * 704 * @return string|null A json object containing success data if the upload succeeded 705 * error message otherwise. 706 */ 707 function bp_attachments_cover_image_ajax_upload() { 708 // Bail if not a POST action 709 if ( 'POST' !== strtoupper( $_SERVER['REQUEST_METHOD'] ) ) { 710 wp_die(); 711 } 712 713 /** 714 * Sending the json response will be different if 715 * the current Plupload runtime is html4 716 */ 717 $is_html4 = false; 718 if ( ! empty( $_POST['html4' ] ) ) { 719 $is_html4 = true; 720 } 721 722 // Check the nonce 723 check_admin_referer( 'bp-uploader' ); 724 725 // Init the BuddyPress parameters 726 $bp_params = array(); 727 728 // We need it to carry on 729 if ( ! empty( $_POST['bp_params' ] ) ) { 730 $bp_params = bp_parse_args( $_POST['bp_params' ], array( 731 'object' => 'user', 732 'item_id' => bp_loggedin_user_id(), 733 ), 'attachments_cover_image_ajax_upload' ); 734 } else { 735 bp_attachments_json_response( false, $is_html4 ); 736 } 737 738 // We need the object to set the uploads dir filter 739 if ( empty( $bp_params['object'] ) ) { 740 bp_attachments_json_response( false, $is_html4 ); 741 } 742 743 // Capability check 744 if ( ! bp_attachments_current_user_can( 'edit_cover_image', $bp_params ) ) { 745 bp_attachments_json_response( false, $is_html4 ); 746 } 747 748 $cover_image_attachment = new BP_Attachment_Cover_Image(); 749 $uploaded = $cover_image_attachment->upload( $_FILES ); 750 751 if ( ! empty( $uploaded['error'] ) ) { 752 // Upload error response 753 bp_attachments_json_response( false, $is_html4, array( 754 'type' => 'upload_error', 755 'message' => sprintf( __( 'Upload Failed! Error was: %s', 'buddypress' ), $uploaded['error'] ), 756 ) ); 757 } 758 759 // Default object data 760 $object_data = array( 'dir' => 'members', 'component' => 'xprofile' ); 761 if ( 'group' === $bp_params['object'] ) { 762 $object_data = array( 'dir' => 'groups', 'component' => 'groups' ); 763 } elseif ( 'user' !== $bp_params['object'] ) { 764 $object_data = apply_filters( 'bp_attachments_cover_image_object_dir', $object_data, $bp_params['object'] ); 765 } 766 767 // Get advised dimensions for the cover image 768 $dimensions = bp_attachments_get_cover_image_dimensions( $object_data['component'] ); 769 770 // Resize the image so that it fit with the cover image dimensions 771 $cover_image = $cover_image_attachment->fit( $uploaded['file'], $dimensions ); 772 $is_too_small = false; 773 774 // Image is too small in width and height 775 if ( empty( $cover_image ) ) { 776 $cover_file = $cover_image_attachment->generate_filename( $uploaded['file'] ); 777 @rename( $uploaded['file'], $cover_file ); 778 779 // It's too small! 780 $is_too_small = true; 781 } elseif ( ! empty( $cover_image['path'] ) ) { 782 $cover_file = $cover_image['path']; 783 784 if ( $cover_image['width'] < $dimensions['width'] || $cover_image['height'] < $dimensions['height'] ) { 785 $is_too_small = true; 786 } 787 } 788 789 // Default error message 790 $error_message = __( 'There was a problem uploading the cover image.', 'buddypress' ); 791 792 if ( empty( $cover_file ) ) { 793 // Upload error response 794 bp_attachments_json_response( false, $is_html4, array( 795 'type' => 'upload_error', 796 'message' => __( 'There was a problem uploading the cover image.', 'buddypress' ), 797 ) ); 798 } 799 800 // Set the basename for the cover file 801 $cover_basename = wp_basename( $cover_file ); 802 803 // Get BuddyPress Upload Dir 804 $bp_upload_dir = bp_upload_dir(); 805 806 $cover_subdir = 'buddypress/' . $object_data['dir'] . '/' . $bp_params['item_id'] . '/cover-image'; 807 $cover_dir = trailingslashit( $bp_upload_dir['basedir'] ) . $cover_subdir; 808 809 if ( ! is_dir( $cover_dir ) ) { 810 // Upload error response 811 bp_attachments_json_response( false, $is_html4, array( 812 'type' => 'upload_error', 813 'message' => $error_message, 814 ) ); 815 } 816 817 // Clean up the cover dir to only keep the uploaded cover image 818 if ( $att_dir = opendir( $cover_dir ) ) { 819 while ( false !== ( $attachment_file = readdir( $att_dir ) ) ) { 820 // skip directories and the new cover image 821 if ( 2 < strlen( $attachment_file ) && 0 !== strpos( $attachment_file, '.' ) && $cover_basename !== $attachment_file ) { 822 @unlink( $cover_dir . '/' . $attachment_file ); 823 } 824 } 825 } 826 827 // Build the url to the file 828 $cover_url = trailingslashit( $bp_upload_dir['baseurl'] ) . $cover_subdir . '/' . $cover_basename; 829 830 // Init Feedback code, 1 is success 831 $feedback_code = 1; 832 833 // 0 is the size warning 834 if ( $is_too_small ) { 835 $feedback_code = 0; 836 } 837 838 // Set the name of the file 839 $name = $_FILES['file']['name']; 840 $name_parts = pathinfo( $name ); 841 $name = trim( substr( $name, 0, - ( 1 + strlen( $name_parts['extension'] ) ) ) ); 842 843 // Build the successful response 844 $response = array( 845 'name' => $name, 846 'url' => $cover_url, 847 'feedback_code' => $feedback_code, 848 ); 849 850 // User already has a cover image 851 if ( "true" === $bp_params['has_cover_image'] ) { 852 $response['had_cover_image'] = true; 853 854 // Get the style in case it's not already loaded 855 } else { 856 $response['header'] = bp_buffer_template_part( 'members/single/cover-image-header', null, false ); 857 $response['inline_style'] = bp_add_cover_image_inline_css( true ); 858 } 859 860 // Finally return the cover image to the UI 861 bp_attachments_json_response( true, $is_html4, $response ); 862 } 863 add_action( 'wp_ajax_bp_cover_image_upload', 'bp_attachments_cover_image_ajax_upload' ); 864 865 /** 866 * Ajax delete a cover image for a given object and item id. 867 * 868 * @since BuddyPress (2.4.0) 869 * 870 * @return string|null A json object containing success data if the cover image was deleted 871 * error message otherwise. 872 */ 873 function bp_attachments_cover_image_ajax_delete() { 874 // Bail if not a POST action. 875 if ( 'POST' !== strtoupper( $_SERVER['REQUEST_METHOD'] ) ) { 876 wp_send_json_error(); 877 } 878 879 $cover_image_data = $_POST; 880 881 if ( empty( $cover_image_data['object'] ) || empty( $cover_image_data['item_id'] ) ) { 882 wp_send_json_error(); 883 } 884 885 // Check the nonce 886 check_admin_referer( 'bp_delete_cover_image', 'nonce' ); 887 888 // Capability check 889 if ( ! bp_attachments_current_user_can( 'edit_cover_image', $cover_image_data ) ) { 890 wp_send_json_error(); 891 } 892 893 // Set object for the user's case 894 if ( 'user' === $cover_image_data['object'] ) { 895 $object = 'member'; 896 897 // Set it for any other cases 898 } else { 899 $object = $cover_image_data['object']; 900 } 901 902 // Set the object dir 903 $dir = $object . 's'; 904 905 // Handle delete 906 if ( bp_attachments_delete_file( array( 'item_id' => $cover_image_data['item_id'], 'object_dir' => $dir, 'type' => 'cover-image' ) ) ) { 907 908 wp_send_json_success( array( 909 'header' => bp_buffer_template_part( $dir . '/single/' . $object . '-header', null, false ), 910 'feedback_code' => 3, 911 ) ); 912 } else { 913 wp_send_json_error( array( 914 'feedback_code' => 2, 915 ) ); 916 } 917 } 918 add_action( 'wp_ajax_bp_cover_image_delete', 'bp_attachments_cover_image_ajax_delete' ); -
src/bp-core/bp-core-classes.php
diff --git src/bp-core/bp-core-classes.php src/bp-core/bp-core-classes.php index 7d1e0be..0da6fbb 100644
require dirname( __FILE__ ) . '/classes/class-bp-recursive-query.php'; 23 23 require dirname( __FILE__ ) . '/classes/class-bp-media-extractor.php'; 24 24 require dirname( __FILE__ ) . '/classes/class-bp-attachment.php'; 25 25 require dirname( __FILE__ ) . '/classes/class-bp-attachment-avatar.php'; 26 require dirname( __FILE__ ) . '/classes/class-bp-attachment-cover-image.php'; -
src/bp-core/bp-core-cssjs.php
diff --git src/bp-core/bp-core-cssjs.php src/bp-core/bp-core-cssjs.php index 392f926..7933f43 100644
function bp_core_register_common_scripts() { 43 43 'bp-avatar' => array( 'file' => "{$url}avatar{$min}.js", 'dependencies' => array( 'jcrop' ), 'footer' => true ), 44 44 'bp-webcam' => array( 'file' => "{$url}webcam{$min}.js", 'dependencies' => array( 'bp-avatar' ), 'footer' => true ), 45 45 46 // 2.4 47 'bp-cover-image' => array( 'file' => "{$url}cover-image{$min}.js", 'dependencies' => array(), 'footer' => true ), 48 46 49 ) ); 47 50 48 51 $version = bp_get_version(); … … function bp_core_avatar_scripts() { 140 143 add_action( 'bp_enqueue_scripts', 'bp_core_avatar_scripts' ); 141 144 142 145 /** 146 * Enqueues the css and js required by the Cover Image UI. 147 * 148 * @since BuddyPress (2.4.0) 149 */ 150 function bp_core_cover_image_scripts() { 151 if ( ! bp_attachments_cover_image_is_edit() ) { 152 return false; 153 } 154 155 // Enqueue the Attachments scripts for the Cover Image UI 156 bp_attachments_enqueue_scripts( 'BP_Attachment_Cover_Image' ); 157 } 158 add_action( 'bp_enqueue_scripts', 'bp_core_cover_image_scripts' ); 159 160 /** 143 161 * Enqueues jCrop library and hooks BP's custom cropper JS. 144 162 */ 145 163 function bp_core_add_jquery_cropper() { … … function bp_core_get_js_dependencies() { 337 355 'bp-jquery-scroll-to' 338 356 ) ); 339 357 } 358 359 /** 360 * Add inline css to display the component's single item cover image 361 * 362 * @since BuddyPress (2.4.0) 363 * 364 * @param bool $return true to get the inline css 365 * @return string|array the inline css or an associative array containing 366 * the css rules and the style handle 367 */ 368 function bp_add_cover_image_inline_css( $return = false ) { 369 $bp = buddypress(); 370 371 // Find the component of the current item 372 if ( bp_is_user() ) { 373 374 // No user uploads, no need to carry on 375 if ( bp_disable_avatar_uploads() ) { 376 return; 377 } 378 379 $cover_image_object = array( 380 'component' => 'xprofile', 381 'object' => $bp->displayed_user 382 ); 383 } elseif ( bp_is_group() ) { 384 385 // No user uploads, no need to carry on 386 if ( bp_disable_group_avatar_uploads() ) { 387 return; 388 } 389 390 $cover_image_object = array( 391 'component' =>'groups', 392 'object' => $bp->groups->current_group 393 ); 394 } else { 395 $cover_image_object = apply_filters( 'bp_current_cover_image_object_inline_css', array() ); 396 } 397 398 // Bail if no component were found. 399 if ( empty( $cover_image_object['component'] ) || empty( $cover_image_object['object'] ) || ! bp_is_active( $cover_image_object['component'], 'cover_image' ) ) { 400 return; 401 } 402 403 // Get the settings of the cover image feature for the current component 404 $params = bp_attachments_get_cover_image_settings( $cover_image_object['component'] ); 405 406 // Bail if no params. 407 if ( empty( $params ) ) { 408 return; 409 } 410 411 // Try to call the callback 412 if ( is_callable( $params['callback'] ) ) { 413 414 $object_dir = $cover_image_object['component']; 415 416 if ( 'xprofile' === $object_dir ) { 417 $object_dir = 'members'; 418 } 419 420 $cover_image = bp_attachments_get_attachment( 'url', array( 421 'object_dir' => $object_dir, 422 'item_id' => $cover_image_object['object']->id, 423 ) ); 424 425 if ( empty( $cover_image ) ) { 426 if ( ! empty( $params['default_cover'] ) ) { 427 $cover_image = $params['default_cover']; 428 } 429 } 430 431 // Object has a cover so update it! 432 $cover_image_object['object']->has_cover_image = true; 433 434 $inline_css = call_user_func_array( $params['callback'], array( array( 435 'cover_image' => esc_url( $cover_image ), 436 'component' => sanitize_key( $cover_image_object['component'] ), 437 'object_id' => (int) $cover_image_object['object']->id, 438 'width' => (int) $params['width'], 439 'height' => (int) $params['height'], 440 ) ) ); 441 442 // Finally add the inline css to the handle 443 if ( ! empty( $inline_css ) ) { 444 445 // Used to get the css when Ajax setting the cover image 446 if ( true === $return ) { 447 return array( 448 'css_rules' => '<style type="text/css">' . "\n" . $inline_css . "\n" . '</style>', 449 'handle' => $params['theme_handle'], 450 ); 451 } 452 453 wp_add_inline_style( $params['theme_handle'], $inline_css ); 454 } else { 455 return false; 456 } 457 } 458 } 459 add_action( 'bp_enqueue_scripts', 'bp_add_cover_image_inline_css', 11 ); -
src/bp-core/bp-core-template.php
diff --git src/bp-core/bp-core-template.php src/bp-core/bp-core-template.php index 52bae24..ef740f5 100644
function bp_is_active( $component = '', $feature = '' ) { 1934 1934 1935 1935 // Is feature active? 1936 1936 if ( ! empty( $feature ) ) { 1937 // The xProfile component is specific 1938 if ( 'xprofile' === $component ) { 1939 $component = 'profile'; 1940 } 1941 1937 1942 if ( empty( buddypress()->$component->features ) || false === in_array( $feature, buddypress()->$component->features, true ) ) { 1938 1943 $retval = false; 1939 1944 } … … function bp_is_user_change_avatar() { 2247 2252 } 2248 2253 2249 2254 /** 2255 * Is the current page the a user's change cover image profile page? 2256 * 2257 * Eg http://example.com/members/joe/profile/change-cover-image/ (or a subpage thereof). 2258 * 2259 * @since BuddyPress (2.4.0) 2260 * 2261 * @return True if the current page is a user's profile edit cover image page. 2262 */ 2263 function bp_is_user_change_cover_image() { 2264 return (bool) ( bp_is_profile_component() && bp_is_current_action( 'change-cover-image' ) ); 2265 } 2266 2267 /** 2250 2268 * Is this a user's forums page? 2251 2269 * 2252 2270 * Eg http://example.com/members/joe/forums/ (or a subpage thereof). -
src/bp-core/bp-core-theme-compatibility.php
diff --git src/bp-core/bp-core-theme-compatibility.php src/bp-core/bp-core-theme-compatibility.php index 897b775..9240936 100644
function bp_set_theme_compat_original_template( $template = '' ) { 437 437 } 438 438 439 439 /** 440 * Set a theme compat feature 441 * 442 * @since BuddyPress (2.4.0) 443 * 444 * @param string $theme_id the theme id (eg: legacy) 445 * @param array $feature an associative array (eg: array( name => 'feature_name', 'settings' => array() )) 446 */ 447 function bp_set_theme_compat_feature( $theme_id, $feature = array() ) { 448 if ( empty( $theme_id ) || empty( $feature['name'] ) ) { 449 return; 450 } 451 452 // Get BuddyPress instance 453 $bp = buddypress(); 454 455 // Get current theme compat theme 456 $theme_compat_theme = $bp->theme_compat->theme; 457 458 // Bail if theme is not in use 459 if ( $theme_id !== $theme_compat_theme->id ) { 460 return; 461 } 462 463 $features = $theme_compat_theme->__get( 'features' ); 464 if ( empty( $features ) ) { 465 $features = array(); 466 } 467 468 // Bail if the feature is already registered or no settings were provided 469 if ( isset( $features[ $feature['name'] ] ) || empty( $feature['settings'] ) ) { 470 return; 471 } 472 473 // Add the feature 474 $features[ $feature['name'] ] = (object) $feature['settings']; 475 476 // The feature is attached to components 477 if ( isset( $features[ $feature['name'] ]->components ) ) { 478 // Set the feature for each concerned component 479 foreach ( (array) $features[ $feature['name'] ]->components as $component ) { 480 // The xProfile component is specific 481 if ( 'xprofile' === $component ) { 482 $component = 'profile'; 483 } 484 485 if ( isset( $bp->{$component} ) ) { 486 if ( isset( $bp->{$component}->features ) ) { 487 $bp->{$component}->features[] = $feature['name']; 488 } else { 489 $bp->{$component}->features = array( $feature['name'] ); 490 } 491 } 492 } 493 } 494 495 // Finally update the theme compat features 496 $theme_compat_theme->__set( 'features', $features ); 497 } 498 499 /** 500 * Get a theme compat feature 501 * 502 * @since BuddyPress (2.4.0) 503 * 504 * @param string $feature the feature (eg: cover_image) 505 * @return object the feature settings. 506 */ 507 function bp_get_theme_compat_feature( $feature = '' ) { 508 // Get current theme compat theme 509 $theme_compat_theme = buddypress()->theme_compat->theme; 510 511 // Get features 512 $features = $theme_compat_theme->__get( 'features' ); 513 514 if ( ! isset( $features[ $feature ] ) ) { 515 return false; 516 } 517 518 return $features[ $feature ]; 519 } 520 521 /** 440 522 * Check whether a given template is the one that WP originally selected to display current page. 441 523 * 442 524 * @since BuddyPress (1.7.0) -
new file src/bp-core/classes/class-bp-attachment-cover-image.php
diff --git src/bp-core/classes/class-bp-attachment-cover-image.php src/bp-core/classes/class-bp-attachment-cover-image.php new file mode 100644 index 0000000..0b8a741
- + 1 <?php 2 /** 3 * Core Cover Image attachment class. 4 * 5 * @package BuddyPress 6 * @subpackage Core 7 */ 8 9 // Exit if accessed directly 10 defined( 'ABSPATH' ) || exit; 11 12 /** 13 * BP Attachment Cover Image class. 14 * 15 * Extends BP Attachment to manage the cover images uploads. 16 * 17 * @since BuddyPress (2.4.0) 18 */ 19 class BP_Attachment_Cover_Image extends BP_Attachment { 20 /** 21 * The constuctor 22 * 23 * @since BuddyPress (2.4.0) 24 */ 25 public function __construct() { 26 parent::__construct( array( 27 'action' => 'bp_cover_image_upload', 28 'file_input' => 'file', 29 'base_dir' => 'buddypress', 30 'required_wp_files' => array( 'file', 'image' ), 31 32 /* @todo use a custom error, like we are doing for avatars */ 33 'allowed_mime_types' => array( 'jpg', 'png', 'gif' ), 34 ) ); 35 } 36 37 /** 38 * Set the directory when uploading a file 39 * 40 * @since BuddyPress (2.4.0) 41 * 42 * @return array upload data (path, url, basedir...) 43 */ 44 public function upload_dir_filter() { 45 // Default values are for profiles 46 $object_id = bp_displayed_user_id(); 47 48 if ( empty( $object_id ) ) { 49 $object_id = bp_loggedin_user_id(); 50 } 51 52 $object_directory = 'members'; 53 54 // We're in a group, edit default values 55 if ( bp_is_group() ) { 56 $object_id = bp_get_current_group_id(); 57 $object_directory = 'groups'; 58 } 59 60 // Set the subdir 61 $subdir = '/' . $object_directory . '/' . $object_id . '/cover-image'; 62 63 return apply_filters( 'bp_attachments_cover_image_upload_datas', array( 64 'path' => $this->upload_path . $subdir, 65 'url' => $this->url . $subdir, 66 'subdir' => $subdir, 67 'basedir' => $this->upload_path, 68 'baseurl' => $this->url, 69 'error' => false 70 ) ); 71 } 72 73 /** 74 * Adjust the cover image to fit with advised width & height. 75 * 76 * @since BuddyPress (2.4.0) 77 * 78 * @param string $file the absolute path to the file. 79 * @return mixed 80 */ 81 public function fit( $file = '', $dimensions = array() ) { 82 if ( empty( $dimensions['width'] ) || empty( $dimensions['height'] ) ) { 83 return false; 84 } 85 86 // Get image size 87 $size = @getimagesize( $file ); 88 $retval = false; 89 90 // Check image size and shrink if too large 91 if ( $size[0] > $dimensions['width'] || $size[1] > $dimensions['height'] ) { 92 $editor = wp_get_image_editor( $file ); 93 94 if ( ! is_wp_error( $editor ) ) { 95 $editor->set_quality( 100 ); 96 97 $resized = $editor->resize( $dimensions['width'], $dimensions['height'], true ); 98 if ( ! is_wp_error( $resized ) ) { 99 $cover = $editor->save( $this->generate_filename( $file ) ); 100 } else { 101 $retval = $resized; 102 } 103 104 // Check for cover creation errors 105 if ( ( false === $retval ) && is_wp_error( $cover ) ) { 106 $retval = $cover; 107 } 108 109 // Cover is good so proceed 110 if ( false === $retval ) { 111 $retval = $cover; 112 } 113 114 } else { 115 $retval = $editor; 116 } 117 } 118 119 return $retval; 120 } 121 122 /** 123 * Generate a filename for the cover image 124 * 125 * @since BuddyPress (2.4.0) 126 * 127 * @param string $file the absolute path to the file. 128 * @return string the absolute path to the new file name 129 */ 130 public function generate_filename( $file = '' ) { 131 if ( empty( $file ) || ! file_exists( $file ) ) { 132 return false; 133 } 134 135 $info = pathinfo( $file ); 136 $dir = $info['dirname']; 137 $ext = strtolower( $info['extension'] ); 138 $name = wp_hash( $file . time() ) . '-bp-cover-image'; 139 140 return trailingslashit( $dir ) . "{$name}.{$ext}"; 141 } 142 143 /** 144 * Build script datas for the Uploader UI 145 * 146 * @since BuddyPress (2.4.0) 147 * 148 * @return array the javascript localization data 149 */ 150 public function script_data() { 151 // Get default script data 152 $script_data = parent::script_data(); 153 154 if ( bp_is_user() ) { 155 $item_id = bp_displayed_user_id(); 156 157 $script_data['bp_params'] = array( 158 'object' => 'user', 159 'item_id' => $item_id, 160 'has_cover_image' => bp_attachments_get_user_has_cover_image( $item_id ), 161 'nonces' => array( 162 'remove' => wp_create_nonce( 'bp_delete_cover_image' ), 163 ), 164 ); 165 166 // Set feedback messages 167 $script_data['feedback_messages'] = array( 168 1 => __( 'Your new cover image was uploaded successfully.', 'buddypress' ), 169 2 => __( 'There was a problem deleting your cover image. Please try again.', 'buddypress' ), 170 3 => __( 'Your cover image was deleted successfully!', 'buddypress' ), 171 ); 172 } elseif ( bp_is_group() ) { 173 $item_id = bp_get_current_group_id(); 174 175 $script_data['bp_params'] = array( 176 'object' => 'group', 177 'item_id' => bp_get_current_group_id(), 178 'has_cover_image' => bp_attachments_get_group_has_cover_image( $item_id ), 179 'nonces' => array( 180 'remove' => wp_create_nonce( 'bp_delete_cover_image' ), 181 ), 182 ); 183 184 // Set feedback messages 185 $script_data['feedback_messages'] = array( 186 1 => __( 'The group cover image was uploaded successfully.', 'buddypress' ), 187 2 => __( 'There was a problem deleting the group cover image. Please try again.', 'buddypress' ), 188 3 => __( 'The group cover image was deleted successfully!', 'buddypress' ), 189 ); 190 } else { 191 /** 192 * Use this filter to include specific BuddyPress params for your object. 193 * e.g. Cover image for blogs single item. 194 * 195 * @since BuddyPress (2.4.0) 196 * 197 * @param array $value The cover image specific BuddyPress parameters. 198 */ 199 $script_data['bp_params'] = apply_filters( 'bp_attachment_cover_image_params', array() ); 200 } 201 202 // Include our specific js & css 203 $script_data['extra_js'] = array( 'bp-cover-image' ); 204 $script_data['extra_css'] = array( 'bp-avatar' ); 205 206 return apply_filters( 'bp_attachments_cover_image_script_data', $script_data ); 207 } 208 } -
src/bp-core/css/avatar.css
diff --git src/bp-core/css/avatar.css src/bp-core/css/avatar.css index 385852f..2986dff 100644
1 div.bp-avatar-status { 1 div.bp-avatar-status, 2 div.bp-cover-image-status { 2 3 clear: both; 3 4 margin: 1em 0; 4 5 } 5 6 6 div.bp-avatar-status p.updated { 7 div.bp-avatar-status p.updated, 8 div.bp-cover-image-status p.updated { 7 9 display: block; 8 10 padding: 10px 15px; 9 11 } 10 12 11 div.bp-avatar-status p.success { 13 div.bp-avatar-status p.success, 14 div.bp-cover-image-status p.success { 12 15 background-color: #efc; 13 16 border: 1px solid #591; 14 17 color: #250; 15 18 } 16 19 17 div.bp-avatar-status p.error { 20 div.bp-avatar-status p.error, 21 div.bp-cover-image-status p.error { 18 22 background-color: #fdc; 19 23 border: 1px solid #a00; 20 24 color: #800; 21 25 } 22 26 23 div.bp-avatar-status .bp-progress { 27 div.bp-avatar-status .bp-progress, 28 div.bp-cover-image-status .bp-progress { 24 29 background: none; 25 30 border: 1px solid #d1d1d1; 26 31 float: right; … … div.bp-avatar-status .bp-progress { 33 38 width: 200px; 34 39 } 35 40 36 div.bp-avatar-status .bp-bar { 41 div.bp-avatar-status .bp-bar, 42 div.bp-cover-image-status .bp-bar { 37 43 background-color: #c3ff88; 38 44 width: 0; 39 45 height: 100%; -
new file src/bp-core/js/cover-image.js
diff --git src/bp-core/js/cover-image.js src/bp-core/js/cover-image.js new file mode 100644 index 0000000..b8c466b
- + 1 /* global bp, BP_Uploader, _, Backbone */ 2 3 window.bp = window.bp || {}; 4 5 ( function( exports, $ ) { 6 7 // Bail if not set 8 if ( typeof BP_Uploader === 'undefined' ) { 9 return; 10 } 11 12 bp.Models = bp.Models || {}; 13 bp.Collections = bp.Collections || {}; 14 bp.Views = bp.Views || {}; 15 16 bp.CoverImage = { 17 start: function() { 18 19 // Init some vars 20 this.views = new Backbone.Collection(); 21 this.warning = null; 22 23 // Set up views 24 this.uploaderView(); 25 26 // Inform about the needed dimensions 27 this.displayWarning( BP_Uploader.strings.cover_image_warnings.dimensions ); 28 29 // Set up the delete view if needed 30 if ( true === BP_Uploader.settings.defaults.multipart_params.bp_params.has_cover_image ) { 31 this.deleteView(); 32 } 33 }, 34 35 uploaderView: function() { 36 // Listen to the Queued uploads 37 bp.Uploader.filesQueue.on( 'add', this.uploadProgress, this ); 38 39 // Create the BuddyPress Uploader 40 var uploader = new bp.Views.Uploader(); 41 42 // Add it to views 43 this.views.add( { id: 'upload', view: uploader } ); 44 45 // Display it 46 uploader.inject( '.bp-cover-image' ); 47 }, 48 49 uploadProgress: function() { 50 // Create the Uploader status view 51 var coverImageUploadProgress = new bp.Views.coverImageUploadProgress( { collection: bp.Uploader.filesQueue } ); 52 53 if ( ! _.isUndefined( this.views.get( 'status' ) ) ) { 54 this.views.set( { id: 'status', view: coverImageUploadProgress } ); 55 } else { 56 this.views.add( { id: 'status', view: coverImageUploadProgress } ); 57 } 58 59 // Display it 60 coverImageUploadProgress.inject( '.bp-cover-image-status' ); 61 }, 62 63 deleteView: function() { 64 // Create the delete model 65 var delete_model = new Backbone.Model( _.pick( BP_Uploader.settings.defaults.multipart_params.bp_params, 66 'object', 67 'item_id', 68 'nonces' 69 ) ); 70 71 // Do not add it if already there! 72 if ( ! _.isUndefined( this.views.get( 'delete' ) ) ) { 73 return; 74 } 75 76 // Create the delete view 77 var deleteView = new bp.Views.DeleteCoverImage( { model: delete_model } ); 78 79 // Add it to views 80 this.views.add( { id: 'delete', view: deleteView } ); 81 82 // Display it 83 deleteView.inject( '.bp-cover-image-manage' ); 84 }, 85 86 deleteCoverImage: function( model ) { 87 var self = this, 88 deleteView; 89 90 // Remove the delete view 91 if ( ! _.isUndefined( this.views.get( 'delete' ) ) ) { 92 deleteView = this.views.get( 'delete' ); 93 deleteView.get( 'view' ).remove(); 94 this.views.remove( { id: 'delete', view: deleteView } ); 95 } 96 97 // Remove the cover image ! 98 bp.ajax.post( 'bp_cover_image_delete', { 99 json: true, 100 item_id: model.get( 'item_id' ), 101 object: model.get( 'object' ), 102 nonce: model.get( 'nonces' ).remove 103 } ).done( function( response ) { 104 var coverImageStatus = new bp.Views.CoverImageStatus( { 105 value : BP_Uploader.strings.feedback_messages[ response.feedback_code ], 106 type : 'success' 107 } ); 108 109 self.views.add( { 110 id : 'status', 111 view : coverImageStatus 112 } ); 113 114 coverImageStatus.inject( '.bp-cover-image-status' ); 115 116 // Reset the item header 117 $( '#item-header' ).html( response.header ); 118 119 // Reset the has_cover_image bp_param 120 BP_Uploader.settings.defaults.multipart_params.bp_params.has_cover_image = false; 121 122 } ).fail( function( response ) { 123 var feedback = BP_Uploader.strings.default_error; 124 if ( ! _.isUndefined( response ) ) { 125 feedback = BP_Uploader.strings.feedback_messages[ response.feedback_code ]; 126 } 127 128 var coverImageStatus = new bp.Views.CoverImageStatus( { 129 value : feedback, 130 type : 'error' 131 } ); 132 133 self.views.add( { 134 id : 'status', 135 view : coverImageStatus 136 } ); 137 138 coverImageStatus.inject( '.bp-cover-image-status' ); 139 140 // Put back the delete view 141 bp.CoverImage.deleteView(); 142 } ); 143 }, 144 145 removeWarning: function() { 146 if ( ! _.isNull( this.warning ) ) { 147 this.warning.remove(); 148 } 149 }, 150 151 displayWarning: function( message ) { 152 this.removeWarning(); 153 154 this.warning = new bp.Views.uploaderWarning( { 155 value: message 156 } ); 157 158 this.warning.inject( '.bp-cover-image-status' ); 159 }, 160 161 // Dynamically set the cover without a page reload 162 setCover: function( cover ) { 163 if ( ! _.isUndefined( cover.had_cover_image ) ) { 164 $( '#header-cover-image' ).css( { 165 'background-image': 'url( ' + cover.url + ' )' 166 } ); 167 } else if ( ! _.isUndefined( cover.header ) ) { 168 if ( ! $( '#header-cover-image' ).length ) { 169 $( '#item-header' ).html( cover.header ); 170 171 // Check we have everything we need 172 if ( ! _.isUndefined( cover.inline_style.handle ) && ! _.isUndefined( cover.inline_style.css_rules ) ) { 173 if ( ! $( '#' + cover.inline_style.handle + '-inline-css').length ) { 174 $( '#item-header' ).prepend( cover.inline_style.css_rules ); 175 } 176 } 177 178 } else { 179 $( '#header-cover-image' ).css( { 180 'background-image': 'url( ' + cover.url + ' )' 181 } ); 182 } 183 } 184 } 185 }; 186 187 // Custom Uploader Files view 188 bp.Views.coverImageUploadProgress = bp.Views.uploaderStatus.extend( { 189 className: 'files', 190 191 initialize: function() { 192 bp.Views.uploaderStatus.prototype.initialize.apply( this, arguments ); 193 194 this.collection.on( 'change:url', this.uploadResult, this ); 195 }, 196 197 uploadResult: function( model ) { 198 var message, type; 199 200 if ( ! _.isUndefined( model.get( 'url' ) ) ) { 201 202 // Image is too small 203 if ( 0 === model.get( 'feedback_code' ) ) { 204 message = BP_Uploader.strings.cover_image_warnings.dimensions; 205 type = 'warning'; 206 207 // Success, Rock n roll! 208 } else { 209 message = BP_Uploader.strings.feedback_messages[ model.get( 'feedback_code' ) ]; 210 type = 'success'; 211 } 212 213 this.views.set( '.bp-uploader-progress', new bp.Views.CoverImageStatus( { 214 value : message, 215 type : type 216 } ) ); 217 218 // Update the header 219 bp.CoverImage.setCover( _.pick( model.attributes, 'url', 'had_cover_image', 'inline_style', 'header' ) ); 220 221 // Add the delete view 222 bp.CoverImage.deleteView(); 223 } 224 } 225 } ); 226 227 // BuddyPress Cover Image Feedback view 228 bp.Views.CoverImageStatus = bp.View.extend( { 229 tagName: 'p', 230 className: 'updated', 231 id: 'bp-cover-image-feedback', 232 233 initialize: function() { 234 this.el.className += ' ' + this.options.type; 235 this.value = this.options.value; 236 }, 237 238 render: function() { 239 this.$el.html( this.value ); 240 return this; 241 } 242 } ); 243 244 // BuddyPress Cover Image Delete view 245 bp.Views.DeleteCoverImage = bp.View.extend( { 246 tagName: 'div', 247 id: 'bp-delete-cover-image-container', 248 template: bp.template( 'bp-cover-image-delete' ), 249 250 events: { 251 'click #bp-delete-cover-image': 'deleteCoverImage' 252 }, 253 254 deleteCoverImage: function( event ) { 255 event.preventDefault(); 256 257 bp.CoverImage.deleteCoverImage( this.model ); 258 } 259 } ); 260 261 bp.CoverImage.start(); 262 263 })( bp, jQuery ); -
src/bp-members/bp-members-template.php
diff --git src/bp-members/bp-members-template.php src/bp-members/bp-members-template.php index f4d482f..ee11912 100644
function bp_get_displayed_user_nav() { 1467 1467 } 1468 1468 } 1469 1469 1470 /** Cover image ***************************************************************/ 1471 1472 /** 1473 * Does the displayed user has a cover image 1474 * 1475 * @since BuddyPress (2.4.0) 1476 * 1477 * @return bool True if the displayed user has a cover image, 1478 * False otherwise 1479 */ 1480 function bp_displayed_user_has_cover_image() { 1481 $bp = buddypress(); 1482 1483 /** 1484 * Filters the displayed user's check about his cover image. 1485 * 1486 * @since BuddyPress (2.4.0) 1487 * 1488 * @param bool $value whether the user has a cover image or not. 1489 */ 1490 return (bool) apply_filters( 'bp_displayed_user_has_cover_image', ! empty( $bp->displayed_user->has_cover_image ) ); 1491 } 1492 1470 1493 /** Avatars *******************************************************************/ 1471 1494 1472 1495 /** -
src/bp-templates/bp-legacy/buddypress-functions.php
diff --git src/bp-templates/bp-legacy/buddypress-functions.php src/bp-templates/bp-legacy/buddypress-functions.php index fb7cdb4..d9fc574 100644
class BP_Legacy extends BP_Theme_Compat { 58 58 * @access private 59 59 */ 60 60 protected function setup_globals() { 61 $bp = buddypress(); 62 $this->id = 'legacy'; 63 $this->name = __( 'BuddyPress Legacy', 'buddypress' ); 64 $this->version = bp_get_version(); 65 $this->dir = trailingslashit( $bp->themes_dir . '/bp-legacy' ); 66 $this->url = trailingslashit( $bp->themes_url . '/bp-legacy' ); 61 $bp = buddypress(); 62 $this->id = 'legacy'; 63 $this->name = __( 'BuddyPress Legacy', 'buddypress' ); 64 $this->version = bp_get_version(); 65 $this->dir = trailingslashit( $bp->themes_dir . '/bp-legacy' ); 66 $this->url = trailingslashit( $bp->themes_url . '/bp-legacy' ); 67 68 // Set Up theme features 69 $this->setup_features(); 70 } 71 72 /** 73 * Setup the theme's features 74 * 75 * @since BuddyPress (2.4.0) 76 * @access public 77 * 78 * @global $content_width the content width of the theme 79 */ 80 public function setup_features() { 81 global $content_width; 82 83 // Get the theme 84 $current_theme = wp_get_theme(); 85 $theme_handle = $current_theme->get_stylesheet(); 86 $parent = $current_theme->parent(); 87 88 if ( $parent ) { 89 $theme_handle = $parent->get_stylesheet(); 90 } 91 92 /** 93 * Since Companion stylesheets, the $content_width is smaller 94 * than the width used by BuddyPress, so we need to manually set the 95 * content width for the concerned themes. 96 * 97 * array( stylesheet => content width used by BuddyPress ) 98 */ 99 $bp_content_widths = array( 100 'twentyfifteen' => 1300, 101 'twentyfourteen' => 955, 102 'twentythirteen' => 890, 103 ); 104 105 // Default values 106 $bp_content_width = (int) $content_width; 107 $bp_handle = 'bp-legacy-css'; 108 109 // Specific to themes having companion stylesheets 110 if ( isset( $bp_content_widths[ $theme_handle ] ) ) { 111 $bp_content_width = $bp_content_widths[ $theme_handle ]; 112 $bp_handle = 'bp-' . $theme_handle; 113 } 114 115 if ( is_rtl() ) { 116 $bp_handle .= '-rtl'; 117 } 118 119 $top_offset = 150; 120 $avatar_height = apply_filters( 'bp_core_avatar_full_height', $top_offset ); 121 122 if ( $avatar_height > $top_offset ) { 123 $top_offset = $avatar_height; 124 } 125 126 bp_set_theme_compat_feature( $this->id, array( 127 'name' => 'cover_image', 128 'settings' => array( 129 'components' => array( 'xprofile', 'groups' ), 130 'width' => $bp_content_width, 131 'height' => $top_offset + round( $avatar_height / 2 ), 132 'callback' => 'bp_legacy_theme_cover_image', 133 'theme_handle' => $bp_handle, 134 ), 135 ) ); 67 136 } 68 137 69 138 /** … … function bp_legacy_theme_ajax_messages_star_handler() { 1717 1786 echo '-1'; 1718 1787 die(); 1719 1788 } 1789 1790 /** 1791 * BP Legacy's callback for the cover image feature 1792 * 1793 * @since BuddyPress (2.4.0) 1794 * 1795 * @param array $params the current component's feature parameters 1796 * @return array an array to inform about the css handle to attach the css rules to 1797 */ 1798 function bp_legacy_theme_cover_image( $params = array() ) { 1799 if ( empty( $params ) ) { 1800 return; 1801 } 1802 1803 // avatar height - padding - 1/2 avatar height 1804 $avatar_offset = $params['height'] - 5 - round( (int) bp_core_avatar_full_height() / 2 ); 1805 1806 // header content offset + spacing 1807 $top_offset = bp_core_avatar_full_height() - 10; 1808 $left_offset = bp_core_avatar_full_width() + 20; 1809 1810 $cover_image = isset( $params['cover_image'] ) ? 'background-image: url(' . $params['cover_image'] . ');' : ''; 1811 1812 /** 1813 * @todo groups single item rules, most of the css should be in companion stylesheets.. 1814 */ 1815 return ' 1816 /* Cover image */ 1817 #buddypress #header-cover-image { 1818 height: ' . $params["height"] . 'px; 1819 ' . $cover_image . ' 1820 } 1821 1822 .bp-user #buddypress #item-header { 1823 padding-top: 0; 1824 } 1825 1826 #buddypress #item-header-cover-image #item-header-avatar { 1827 margin-top: '. $avatar_offset .'px; 1828 float: none; 1829 overflow:visible; 1830 width:auto; 1831 } 1832 1833 #buddypress div#item-header #item-header-cover-image #item-header-content { 1834 clear: both; 1835 float: left; 1836 margin-left: ' . $left_offset . 'px; 1837 margin-top: -' . $top_offset . 'px; 1838 width:auto; 1839 } 1840 1841 /* This should only happen on regular screens */ 1842 #buddypress div#item-header-cover-image h2 a, 1843 #buddypress div#item-header-cover-image h2 { 1844 color: #FFF; 1845 text-rendering: optimizelegibility; 1846 text-shadow: 0px 0px 3px rgba( 0, 0, 0, 0.8 ); 1847 margin: 0; 1848 font-size:200%; 1849 } 1850 1851 #buddypress #item-header-cover-image #item-header-avatar img.avatar { 1852 border: solid 2px #FFF; 1853 background: rgba( 255, 255, 255, 0.8 ); 1854 } 1855 1856 #buddypress #item-header-cover-image #item-buttons { 1857 overflow:hidden; 1858 margin: 20px 0 10px; 1859 padding: 0 0 5px; 1860 } 1861 1862 #buddypress #item-header-cover-image #item-buttons:before { 1863 content:"\00a0"; 1864 } 1865 1866 @media screen and (max-width: 782px) { 1867 #buddypress #item-header-cover-image #item-header-avatar, 1868 .bp-user #buddypress #item-header #item-header-cover-image #item-header-avatar, 1869 #buddypress div#item-header #item-header-cover-image #item-header-content { 1870 width:100%; 1871 text-align:center; 1872 } 1873 1874 #buddypress #item-header-cover-image #item-header-avatar a { 1875 display:inline-block; 1876 } 1877 1878 #buddypress #item-header-cover-image #item-header-avatar img { 1879 margin:0; 1880 } 1881 1882 #buddypress div#item-header #item-header-cover-image #item-header-content { 1883 margin:0; 1884 } 1885 1886 #buddypress div#item-header-cover-image h2 a, 1887 #buddypress div#item-header-cover-image h2 { 1888 color: inherit; 1889 text-shadow: none; 1890 margin:25px 0 0; 1891 font-size:200%; 1892 } 1893 1894 #buddypress #item-header-cover-image #item-buttons div { 1895 float:none; 1896 display:inline-block; 1897 } 1898 1899 #buddypress #item-header-cover-image #item-buttons:before { 1900 content:""; 1901 } 1902 1903 #buddypress #item-header-cover-image #item-buttons { 1904 margin: 5px 0; 1905 } 1906 } 1907 '; 1908 } -
new file src/bp-templates/bp-legacy/buddypress/assets/_attachments/cover-images/index.php
diff --git src/bp-templates/bp-legacy/buddypress/assets/_attachments/cover-images/index.php src/bp-templates/bp-legacy/buddypress/assets/_attachments/cover-images/index.php new file mode 100644 index 0000000..a552682
- + 1 <?php 2 /** 3 * BuddyPress Cover Images main template 4 * 5 * This template is used to inject the BuddyPress Backbone views 6 * dealing with cover images. 7 * It's also used to create the common Backbone views 8 * 9 * @since 2.4 10 * 11 * @package BuddyPress 12 * @subpackage bp-attachments 13 */ 14 ?> 15 16 <div class="bp-cover-image"></div> 17 <div class="bp-cover-image-status"></div> 18 <div class="bp-cover-image-manage"></div> 19 20 <?php bp_attachments_get_template_part( 'uploader' ); ?> 21 22 <script id="tmpl-bp-cover-image-delete" type="text/html"> 23 <# if ( 'user' === data.object ) { #> 24 <p><?php _e( "If you'd like to delete your current cover image but not upload a new one, please use the delete Cover Image button.", 'buddypress' ); ?></p> 25 <p><a class="button edit" id="bp-delete-cover-image" href="#" title="<?php esc_attr_e( 'Delete Cover Image', 'buddypress' ); ?>"><?php esc_html_e( 'Delete My Cover Image', 'buddypress' ); ?></a></p> 26 <# } else if ( 'group' === data.object ) { #> 27 <p><?php _e( "If you'd like to remove the existing group cover image but not upload a new one, please use the delete group cover image button.", 'buddypress' ); ?></p> 28 <p><a class="button edit" id="bp-delete-cover-image" href="#" title="<?php esc_attr_e( 'Delete Cover Image', 'buddypress' ); ?>"><?php esc_html_e( 'Delete Group Cover Image', 'buddypress' ); ?></a></p> 29 <# } else { #> 30 <?php do_action( 'bp_attachments_cover_image_delete_template' ); ?> 31 <# } #> 32 </script> 33 34 <?php do_action( 'bp_attachments_cover_image_main_template' ); ?> -
new file src/bp-templates/bp-legacy/buddypress/members/single/cover-image-header.php
diff --git src/bp-templates/bp-legacy/buddypress/members/single/cover-image-header.php src/bp-templates/bp-legacy/buddypress/members/single/cover-image-header.php new file mode 100644 index 0000000..d59cb47
- + 1 <?php 2 3 /** 4 * BuddyPress - Users Cover Image Header 5 * 6 * @package BuddyPress 7 * @subpackage bp-legacy 8 */ 9 10 ?> 11 12 <?php 13 14 /** 15 * Fires before the display of a member's header. 16 * 17 * @since BuddyPress (1.2.0) 18 */ 19 do_action( 'bp_before_member_header' ); ?> 20 21 <a id="header-cover-image" href="<?php bp_displayed_user_link(); ?>"></a> 22 23 <div id="item-header-cover-image"> 24 <div id="item-header-avatar"> 25 <a href="<?php bp_displayed_user_link(); ?>"> 26 27 <?php bp_displayed_user_avatar( 'type=full' ); ?> 28 29 </a> 30 </div><!-- #item-header-avatar --> 31 32 <div id="item-header-content"> 33 34 <?php if ( bp_is_active( 'activity' ) && bp_activity_do_mentions() ) : ?> 35 <h2 class="user-nicename">@<?php bp_displayed_user_mentionname(); ?></h2> 36 <?php endif; ?> 37 38 <div id="item-buttons"> 39 40 <?php 41 42 /** 43 * Fires in the member header actions section. 44 * 45 * @since BuddyPress (1.2.6) 46 */ 47 do_action( 'bp_member_header_actions' ); ?> 48 49 </div><!-- #item-buttons --> 50 51 <span class="activity"><?php bp_last_activity( bp_displayed_user_id() ); ?></span> 52 53 <?php 54 55 /** 56 * Fires before the display of the member's header meta. 57 * 58 * @since BuddyPress (1.2.0) 59 */ 60 do_action( 'bp_before_member_header_meta' ); ?> 61 62 <div id="item-meta"> 63 64 <?php if ( bp_is_active( 'activity' ) ) : ?> 65 66 <div id="latest-update"> 67 68 <?php bp_activity_latest_update( bp_displayed_user_id() ); ?> 69 70 </div> 71 72 <?php endif; ?> 73 74 <?php 75 76 /** 77 * Fires after the group header actions section. 78 * 79 * If you'd like to show specific profile fields here use: 80 * bp_member_profile_data( 'field=About Me' ); -- Pass the name of the field 81 * 82 * @since BuddyPress (1.2.0) 83 */ 84 do_action( 'bp_profile_header_meta' ); 85 86 ?> 87 88 </div><!-- #item-meta --> 89 90 </div><!-- #item-header-content --> 91 92 </div><!-- #item-header-cover-image --> 93 94 <?php 95 96 /** 97 * Fires after the display of a member's header. 98 * 99 * @since BuddyPress (1.2.0) 100 */ 101 do_action( 'bp_after_member_header' ); ?> 102 103 <?php 104 105 /** This action is documented in bp-templates/bp-legacy/buddypress/activity/index.php */ 106 do_action( 'template_notices' ); ?> -
src/bp-templates/bp-legacy/buddypress/members/single/home.php
diff --git src/bp-templates/bp-legacy/buddypress/members/single/home.php src/bp-templates/bp-legacy/buddypress/members/single/home.php index 6b9f04c..03a59cc 100644
11 11 12 12 <div id="item-header" role="complementary"> 13 13 14 <?php bp_get_template_part( 'members/single/member-header' ) ?> 14 <?php 15 /** 16 * Since 2.4.0, we display the cover image header by default. 17 */ 18 if ( bp_is_active( 'xprofile', 'cover_image' ) ) : 19 bp_get_template_part( 'members/single/cover-image-header' ); 20 else : 21 bp_get_template_part( 'members/single/member-header' ); 22 endif; 23 ?> 15 24 16 25 </div><!-- #item-header --> 17 26 -
src/bp-templates/bp-legacy/buddypress/members/single/profile.php
diff --git src/bp-templates/bp-legacy/buddypress/members/single/profile.php src/bp-templates/bp-legacy/buddypress/members/single/profile.php index 165cd17..f419718 100644
do_action( 'bp_before_profile_content' ); ?> 38 38 bp_get_template_part( 'members/single/profile/change-avatar' ); 39 39 break; 40 40 41 // Change Cover Image 42 case 'change-cover-image' : 43 bp_get_template_part( 'members/single/profile/change-cover-image' ); 44 break; 45 41 46 // Compose 42 47 case 'public' : 43 48 -
new file src/bp-templates/bp-legacy/buddypress/members/single/profile/change-cover-image.php
diff --git src/bp-templates/bp-legacy/buddypress/members/single/profile/change-cover-image.php src/bp-templates/bp-legacy/buddypress/members/single/profile/change-cover-image.php new file mode 100644 index 0000000..a114aee
- + 1 <h4><?php _e( 'Change Cover Image', 'buddypress' ); ?></h4> 2 3 <?php 4 5 /** 6 * Fires before the display of profile cover image upload content. 7 * 8 * @since BuddyPress (2.4.0) 9 */ 10 do_action( 'bp_before_profile_cover_image_upload_content' ); ?> 11 12 <p><?php _e( 'Your Cover Image will be used to customize the header of your profile.', 'buddypress' ); ?></p> 13 14 <?php bp_attachments_get_template_part( 'cover-images/index' ); ?> 15 16 <?php 17 18 /** 19 * Fires after the display of profile cover image upload content. 20 * 21 * @since BuddyPress (2.4.0) 22 */ 23 do_action( 'bp_after_profile_cover_image_upload_content' ); ?> -
src/bp-templates/bp-legacy/css/buddypress.css
diff --git src/bp-templates/bp-legacy/css/buddypress.css src/bp-templates/bp-legacy/css/buddypress.css index aca34c6..c6712ff 100644
Hello, this is the BuddyPress Legacy stylesheet. 19 19 3.6 - Ajax Loading 20 20 3.7 - Topics and Tables - Forums and General 21 21 3.8 - Headers, Lists and Tabs - Activity, Groups, Blogs, Forums 22 3.8.1 - Cover Image 22 23 3.9 - Private Messaging Threads 23 24 3.10 - Extended Profiles 24 25 3.11 - Widgets … … a.bp-title-button { 1168 1169 } 1169 1170 #buddypress div#item-header { 1170 1171 overflow: hidden; 1172 position: relative; 1171 1173 } 1172 1174 #buddypress div#item-header div#item-header-content { 1173 1175 float: left; … … body.activity-permalink #buddypress ul.item-list li.activity-item { 1393 1395 list-style: none; 1394 1396 } 1395 1397 1398 /*-------------------------------------------------------------- 1399 3.8.1 - Cover Image 1400 --------------------------------------------------------------*/ 1401 1402 #buddypress #header-cover-image { 1403 background-color: #c5c5c5; 1404 background-position: center top; 1405 background-repeat: no-repeat; 1406 background-size: cover; 1407 border: 0; 1408 display: block; 1409 left: 0; 1410 margin: 0; 1411 padding: 0; 1412 position: absolute; 1413 top: 0; 1414 width: 100%; 1415 z-index: 1; 1416 } 1417 1418 #buddypress #item-header-cover-image { 1419 padding: 0 1em; 1420 position: relative; 1421 z-index: 999; 1422 } 1396 1423 1397 1424 /*-------------------------------------------------------------- 1398 1425 3.9 - Private Messaging Threads -
src/bp-templates/bp-legacy/css/twentyfifteen.css
diff --git src/bp-templates/bp-legacy/css/twentyfifteen.css src/bp-templates/bp-legacy/css/twentyfifteen.css index 7c9eabf..d56436c 100644
http://codex.buddypress.org/themes/buddypress-companion-stylesheets/ 957 957 958 958 .bp-user #buddypress #item-header #item-header-avatar img.avatar, 959 959 .bp-user #buddypress #item-header #item-header-avatar a { 960 border-bottom : 0;960 border-bottom-color: #fff; 961 961 display: inline-block; 962 962 float: none; 963 963 } … … http://codex.buddypress.org/themes/buddypress-companion-stylesheets/ 967 967 float: left; 968 968 width: 20%; 969 969 } 970 .bp-user #buddypress #item-header #item-header-avatar img.avatar, 970 971 971 .bp-user #buddypress #item-header #item-header-avatar a { 972 float: left;973 width: 100%;974 972 } 975 973 .bp-user #buddypress #item-header #item-header-content { 976 974 float: right; -
src/bp-templates/bp-legacy/css/twentyfifteen.scss
diff --git src/bp-templates/bp-legacy/css/twentyfifteen.scss src/bp-templates/bp-legacy/css/twentyfifteen.scss index 22c7eba..267a0d1 100644
http://codex.buddypress.org/themes/buddypress-companion-stylesheets/ 1199 1199 text-align: center; 1200 1200 width: 100%; 1201 1201 1202 img.avatar,1203 1202 a { 1204 1203 border-bottom: 0; 1205 1204 display: inline-block; -
src/bp-templates/bp-legacy/css/twentyfourteen.css
diff --git src/bp-templates/bp-legacy/css/twentyfourteen.css src/bp-templates/bp-legacy/css/twentyfourteen.css index b00e3fe..833cbfa 100644
body.activity-permalink #buddypress { 782 782 text-align: left; 783 783 width: 20%; 784 784 } 785 .bp-user #buddypress #item-header #item-header-avatar img {786 margin: 0;787 }788 785 .bp-user #buddypress #item-header #item-header-content { 789 786 float: right; 790 787 width: 78%; -
src/bp-templates/bp-legacy/css/twentyfourteen.scss
diff --git src/bp-templates/bp-legacy/css/twentyfourteen.scss src/bp-templates/bp-legacy/css/twentyfourteen.scss index 8b9872f..dcf6ed7 100644
body.activity-permalink { 1100 1100 overflow: hidden; 1101 1101 text-align: left; 1102 1102 width: 20%; 1103 1104 img {margin: 0;}1105 1103 } 1106 1104 1107 1105 #item-header-content { -
src/bp-templates/bp-legacy/css/twentythirteen.css
diff --git src/bp-templates/bp-legacy/css/twentythirteen.css src/bp-templates/bp-legacy/css/twentythirteen.css index d2eb95e..0405201 100644
http://codex.buddypress.org/themes/buddypress-companion-stylesheets/ 943 943 944 944 .bp-user #buddypress #item-header #item-header-avatar img.avatar, 945 945 .bp-user #buddypress #item-header #item-header-avatar a { 946 border-bottom: 0;947 946 display: inline-block; 948 947 float: none; 949 948 } … … http://codex.buddypress.org/themes/buddypress-companion-stylesheets/ 953 952 float: left; 954 953 width: 20%; 955 954 } 956 .bp-user #buddypress #item-header #item-header-avatar img.avatar, 955 957 956 .bp-user #buddypress #item-header #item-header-avatar a { 958 float: left;959 width: 100%;960 957 } 961 958 .bp-user #buddypress #item-header #item-header-content { 962 959 float: right; -
src/bp-templates/bp-legacy/css/twentythirteen.scss
diff --git src/bp-templates/bp-legacy/css/twentythirteen.scss src/bp-templates/bp-legacy/css/twentythirteen.scss index 427a724..17a26f0 100644
http://codex.buddypress.org/themes/buddypress-companion-stylesheets/ 1267 1267 float: left; 1268 1268 width: 20%; 1269 1269 1270 img.avatar,1271 1270 a { 1272 1271 float: left; 1273 width: 100%;1274 1272 } 1275 1273 } 1276 1274 -
src/bp-xprofile/bp-xprofile-loader.php
diff --git src/bp-xprofile/bp-xprofile-loader.php src/bp-xprofile/bp-xprofile-loader.php index a38b21b..79364d3 100644
class BP_XProfile_Component extends BP_Component { 226 226 'position' => 30, 227 227 'user_has_access' => $access 228 228 ); 229 230 // Change Cover image 231 if ( ! bp_disable_avatar_uploads() && bp_is_active( $this->id, 'cover_image' ) ) { 232 $sub_nav[] = array( 233 'name' => _x( 'Change Cover Image', 'Profile header sub menu', 'buddypress' ), 234 'slug' => 'change-cover-image', 235 'parent_url' => $profile_link, 236 'parent_slug' => $slug, 237 'screen_function' => 'xprofile_screen_change_cover_image', 238 'position' => 40, 239 'user_has_access' => $access 240 ); 241 } 229 242 } 230 243 231 244 // The Settings > Profile nav item can only be set up after … … class BP_XProfile_Component extends BP_Component { 314 327 'title' => _x( 'Change Profile Photo', 'My Account Profile sub nav', 'buddypress' ), 315 328 'href' => trailingslashit( $profile_link . 'change-avatar' ) 316 329 ); 317 }318 330 331 if ( ! bp_disable_avatar_uploads() && bp_is_active( $this->id, 'cover_image' ) ) { 332 $wp_admin_nav[] = array( 333 'parent' => 'my-account-' . $this->id, 334 'id' => 'my-account-' . $this->id . '-change-cover-image', 335 'title' => _x( 'Change Cover Image', 'My Account Profile sub nav', 'buddypress' ), 336 'href' => trailingslashit( $profile_link . 'change-cover-image' ) 337 ); 338 } 339 } 319 340 } 320 341 321 342 parent::setup_admin_bar( $wp_admin_nav ); -
src/bp-xprofile/bp-xprofile-screens.php
diff --git src/bp-xprofile/bp-xprofile-screens.php src/bp-xprofile/bp-xprofile-screens.php index afb4604..6650f00 100644
function xprofile_screen_change_avatar() { 292 292 } 293 293 294 294 /** 295 * Displays the change cover image page. 296 * 297 * @package BuddyPress XProfile 298 * 299 * @since BuddyPress (2.4.0) 300 */ 301 function xprofile_screen_change_cover_image() { 302 303 // Bail if not the correct screen 304 if ( ! bp_is_my_profile() && ! bp_current_user_can( 'bp_moderate' ) ) { 305 return false; 306 } 307 308 /** 309 * Fires right before the loading of the XProfile change cover image screen template file. 310 * 311 * @since BuddyPress (2.4.0) 312 */ 313 do_action( 'xprofile_screen_change_cover_image' ); 314 315 /** 316 * Filters the template to load for the XProfile cover image screen. 317 * 318 * @since BuddyPress (2.4.0) 319 * 320 * @param string $template Path to the XProfile cover image template to load. 321 */ 322 bp_core_load_template( apply_filters( 'xprofile_template_cover_image', 'members/single/home' ) ); 323 } 324 325 /** 295 326 * Show the xprofile settings template 296 327 * 297 328 * @since BuddyPress (2.0.0)