Ticket #8581: 8581.2.patch
File 8581.2.patch, 61.9 KB (added by , 3 years ago) |
---|
-
src/bp-activity/bp-activity-functions.php
diff --git src/bp-activity/bp-activity-functions.php src/bp-activity/bp-activity-functions.php index 97a2d5dea..658e916eb 100644
function bp_activity_type_supports( $activity_type = '', $feature = '' ) { 709 709 $retval = true; 710 710 } 711 711 break; 712 713 /** 714 * Does this activity type support `generated-content` ? 715 */ 716 case 'generated-content' : 717 $retval = in_array( $activity_type, array( 'new_avatar', 'friendship_created', 'created_group', 'joined_group' ), true ); 718 break; 712 719 } 713 720 714 721 return $retval; -
src/bp-activity/bp-activity-template.php
diff --git src/bp-activity/bp-activity-template.php src/bp-activity/bp-activity-template.php index 16ee47d86..be3eb6a57 100644
function bp_activity_action( $args = array() ) { 1384 1384 * Output the activity content body. 1385 1385 * 1386 1386 * @since 1.2.0 1387 * @since 10.0.0 Added the `$context` parameter & introduced `type-parts` templating for activity content. 1387 1388 * 1389 * @param string $context The context the template tag is being used. Defaults to 'front'. 1388 1390 */ 1389 function bp_activity_content_body() { 1391 function bp_activity_content_body( $context = 'front' ) { 1392 $located = ''; 1393 $type = bp_get_activity_type(); 1394 $allowed_context = false; 1395 1396 if ( 'front' === $context ) { 1397 $allowed_context = ! is_admin() || wp_doing_ajax(); 1398 } 1399 1400 /** 1401 * Filter here to edit whether the use of Activity type parts is allowed. 1402 * 1403 * @since 10.0.0 1404 * 1405 * @param bool $allowed_context True if the use of Activity type parts is allowed. False otherwise. 1406 * @param string $type The Actvity type. 1407 */ 1408 $use_type_parts = apply_filters( 'bp_activity_use_type_parts', $allowed_context, $type ); 1409 1410 if ( $use_type_parts ) { 1411 $type_part = str_replace( '_', '-', $type ) . '.php'; 1412 $located = bp_locate_template( array( 'activity/type-parts/' . $type_part ), false, true ); 1413 } 1414 1415 if ( $located ) { 1416 $slug = wp_basename( $located, '.php' ); 1417 1418 /** 1419 * Let plugins adding an action to bp_get_template_part get it from here 1420 * 1421 * The dynamic portion of the hook is the activity type, eg: `activity_update`. 1422 * 1423 * @since 10.0.0 1424 * 1425 * @param string $slug Template part slug requested. 1426 * @param string $context The context the template tag is being used. Defaults to 'front'. 1427 */ 1428 do_action( "bp_get_activity_type_part_{$type}", $slug, $context ); 1429 1430 load_template( $located, false ); 1431 } else { 1432 echo bp_get_activity_content_body(); 1433 } 1434 } 1435 1436 /** 1437 * Template tag to directly output the Activity content body. 1438 * 1439 * Unlike `bp_activity_content_body()` this template tag is not 1440 * checking for potential type parts to output the activity. 1441 * 1442 * @since 10.0.0 1443 */ 1444 function bp_activity_the_content_body() { 1390 1445 echo bp_get_activity_content_body(); 1391 1446 } 1392 1447 … … function bp_activity_content_body() { 1430 1485 function bp_activity_has_content() { 1431 1486 global $activities_template; 1432 1487 1433 if ( ! empty( $activities_template->activity->content ) ) { 1434 return true; 1488 $has_content = ! empty( $activities_template->activity->content ); 1489 if ( ! $has_content ) { 1490 $activity_type = bp_get_activity_type(); 1491 1492 if ( bp_activity_type_supports( $activity_type, 'generated-content' ) ) { 1493 $bp = buddypress(); 1494 $generated_content = new stdClass(); 1495 $activity = $activities_template->activity; 1496 $user_id = $activity->user_id; 1497 1498 // Set generated content properties. 1499 if ( 'new_avatar' === $activity_type ) { 1500 $avatars = bp_avatar_get_version_src( $user_id, bp_get_activity_date_recorded() ); 1501 1502 if ( $avatars && 1 === count( $avatars ) ) { 1503 $avatar = reset( $avatars ); 1504 $historical_avatar = trailingslashit( $avatar->parent_dir_url ) . $avatar->name; 1505 1506 // Add historical avatar to the current activity. 1507 $generated_content->user_profile_photo = array( 1508 'value' => $historical_avatar, 1509 'sanitize_callback' => 'esc_url', 1510 ); 1511 1512 // Do not use a generated content. 1513 } else { 1514 return false; 1515 } 1516 } 1517 1518 if ( 'friendship_created' === $activity_type ) { 1519 $user_id = $activity->secondary_item_id; 1520 1521 if ( isset( $bp->avatar->show_avatars ) && $bp->avatar->show_avatars ) { 1522 $generated_content->user_profile_photo = array( 1523 'value' => bp_core_fetch_avatar( 1524 array( 1525 'item_id' => $user_id, 1526 'object' => 'user', 1527 'type' => 'full', 1528 'width' => bp_core_avatar_full_width(), 1529 'height' => bp_core_avatar_full_height(), 1530 'html' => false, 1531 ) 1532 ), 1533 'sanitize_callback' => 'esc_url', 1534 ); 1535 } 1536 } 1537 1538 // Set common generated content properties. 1539 if ( 'new_avatar' === $activity_type || 'friendship_created' === $activity_type ) { 1540 $generated_content->user_url = array( 1541 'value' => bp_core_get_user_domain( $user_id ), 1542 'sanitize_callback' => 'esc_url', 1543 ); 1544 1545 $generated_content->user_display_name = array( 1546 'value' => bp_core_get_user_displayname( $user_id ), 1547 'sanitize_callback' => 'esc_html', 1548 ); 1549 1550 $generated_content->user_mention_name = array( 1551 'value' => bp_activity_get_user_mentionname( $user_id ), 1552 'sanitize_callback' => 'esc_html', 1553 ); 1554 1555 $generated_content->user_mention_url = array( 1556 'value' => wp_nonce_url( 1557 add_query_arg( 1558 array( 1559 'r' => $generated_content->user_mention_name['value'], 1560 ), 1561 bp_get_activity_directory_permalink() 1562 ) 1563 ), 1564 'sanitize_callback' => 'esc_url', 1565 ); 1566 1567 if ( bp_displayed_user_use_cover_image_header() ) { 1568 $generated_content->user_cover_image = array( 1569 'value' => bp_attachments_get_attachment( 1570 'url', 1571 array( 1572 'object_dir' => 'members', 1573 'item_id' => $user_id, 1574 ) 1575 ), 1576 'sanitize_callback' => 'esc_url', 1577 ); 1578 } 1579 } 1580 1581 if ( 'created_group' === $activity_type || 'joined_group' === $activity_type ) { 1582 $group = bp_get_group( $activity->item_id ); 1583 1584 if ( isset( $bp->avatar->show_avatars ) && $bp->avatar->show_avatars && ! bp_disable_group_avatar_uploads() ) { 1585 $generated_content->group_profile_photo = array( 1586 'value' => bp_core_fetch_avatar( 1587 array( 1588 'item_id' => $group->id, 1589 'object' => 'group', 1590 'type' => 'full', 1591 'width' => bp_core_avatar_full_width(), 1592 'height' => bp_core_avatar_full_height(), 1593 'html' => false, 1594 ) 1595 ), 1596 'sanitize_callback' => 'esc_url', 1597 ); 1598 } 1599 1600 $generated_content->group_url = array( 1601 'value' => bp_get_group_permalink( $group ), 1602 'sanitize_callback' => 'esc_url', 1603 ); 1604 1605 $generated_content->group_name = array( 1606 'value' => bp_get_group_name( $group ), 1607 'sanitize_callback' => 'esc_html', 1608 ); 1609 1610 if ( bp_group_use_cover_image_header() ) { 1611 $generated_content->group_cover_image = array( 1612 'value' => bp_get_group_cover_url( $group ), 1613 'sanitize_callback' => 'esc_url', 1614 ); 1615 } 1616 } 1617 1618 // Update the corresponding entry into the activities template global. 1619 if ( get_object_vars( $generated_content ) ) { 1620 $activity_id = $activities_template->activity->id; 1621 $activity_index = 0; 1622 1623 // Find the activity index. 1624 while ( (int) $activities_template->activities[ $activity_index ]->id !== (int) $activity_id ) { 1625 $activity_index++; 1626 } 1627 1628 // Add the generated content object. 1629 $activities_template->activities[ $activity_index ]->generated_content = $generated_content; 1630 $has_content = true; 1631 } 1632 } 1435 1633 } 1436 1634 1437 return false; 1635 return $has_content; 1636 } 1637 1638 /** 1639 * Does this property has been generated? 1640 * 1641 * @since 10.0.0 1642 * 1643 * @param string $property The name of the property to check into the generated content. 1644 * @return bool True if the property is not empty. False otherwise. 1645 */ 1646 function bp_activity_has_generated_content_part( $property = '' ) { 1647 return bp_activity_get_generated_content_part( $property, 'boolean' ); 1648 } 1649 1650 /** 1651 * Outputs a property of the activity generated content. 1652 * 1653 * @since 10.0.0 1654 * 1655 * @param string $property The name of the property to check into the generated content. 1656 */ 1657 function bp_activity_generated_content_part( $property = '' ) { 1658 echo bp_activity_get_generated_content_part( $property ); 1438 1659 } 1439 1660 1661 /** 1662 * Returns the property of the activity generated content. 1663 * 1664 * @since 10.0.0 1665 * 1666 * @param string $property The name of the property to check into the generated content. 1667 * @param string $return Whether to return the property value or a boolean to check it exists. 1668 * @return bool|string A boolean when requested, false if there is no value, the HTML output otherwise. 1669 */ 1670 function bp_activity_get_generated_content_part( $property = '', $return = '' ) { 1671 global $activities_template; 1672 1673 if ( ! isset( $activities_template->activity->generated_content->{$property} ) ) { 1674 return false; 1675 } 1676 1677 $content_part = $activities_template->activity->generated_content->{$property}; 1678 1679 if ( ! isset( $content_part['value'] ) || ! $content_part['value'] ) { 1680 return false; 1681 } 1682 1683 if ( 'boolean' === $return ) { 1684 return true; 1685 } 1686 1687 /** 1688 * Filter here to edit the generated content part. 1689 * 1690 * @since 10.0.0 1691 * 1692 * @param string $value The generated content part. 1693 * @param string $property The property the content part is attached to. 1694 */ 1695 $value = apply_filters( 'bp_activity_get_generated_content_part', $content_part['value'], $property ); 1696 1697 if ( isset( $content_part['sanitize_callback'] ) && $content_part['sanitize_callback'] ) { 1698 return call_user_func( $content_part['sanitize_callback'], $value ); 1699 } 1700 1701 return $value; 1702 } 1703 1440 1704 /** 1441 1705 * Output the activity content. 1442 1706 * -
src/bp-activity/classes/class-bp-activity-feed.php
diff --git src/bp-activity/classes/class-bp-activity-feed.php src/bp-activity/classes/class-bp-activity-feed.php index bb984c1fa..b474a8f22 100644
class BP_Activity_Feed { 298 298 * @since 1.8.0 299 299 */ 300 300 protected function feed_content() { 301 bp_activity_content_body( );301 bp_activity_content_body( 'feed' ); 302 302 303 303 switch ( $this->id ) { 304 304 -
src/bp-blogs/classes/class-bp-blogs-recent-posts-widget.php
diff --git src/bp-blogs/classes/class-bp-blogs-recent-posts-widget.php src/bp-blogs/classes/class-bp-blogs-recent-posts-widget.php index 16a63af01..5d5a083c0 100644
class BP_Blogs_Recent_Posts_Widget extends WP_Widget { 102 102 103 103 <?php if ( bp_get_activity_content_body() ) : ?> 104 104 105 <div class="activity-inner"><?php bp_activity_content_body( ); ?></div>105 <div class="activity-inner"><?php bp_activity_content_body( 'widget' ); ?></div> 106 106 107 107 <?php endif; ?> 108 108 -
src/bp-core/bp-core-attachments.php
diff --git src/bp-core/bp-core-attachments.php src/bp-core/bp-core-attachments.php index e99ed0c14..a74069de5 100644
function bp_attachments_create_item_type( $type = 'avatar', $args = array() ) { 409 409 410 410 // It's an avatar, we need to crop it. 411 411 if ( 'avatar' === $type ) { 412 $created = bp_core_avatar_handle_crop( array( 413 'object' => $r['object'], 414 'avatar_dir' => trim( dirname( $attachment_data['subdir'] ), '/' ), 415 'item_id' => (int) $r['item_id'], 416 'original_file' => trailingslashit( $attachment_data['subdir'] ) . $image_file_name, 417 'crop_w' => $r['crop_w'], 418 'crop_h' => $r['crop_h'], 419 'crop_x' => $r['crop_x'], 420 'crop_y' => $r['crop_y'] 421 ) ); 412 $created = bp_core_avatar_handle_crop( 413 array( 414 'object' => $r['object'], 415 'avatar_dir' => trim( dirname( $attachment_data['subdir'] ), '/' ), 416 'item_id' => (int) $r['item_id'], 417 'original_file' => trailingslashit( $attachment_data['subdir'] ) . $image_file_name, 418 'crop_w' => $r['crop_w'], 419 'crop_h' => $r['crop_h'], 420 'crop_x' => $r['crop_x'], 421 'crop_y' => $r['crop_y'] 422 ) 423 ); 422 424 423 425 // It's a cover image we need to fit it to feature's dimensions. 424 426 } elseif ( 'cover_image' === $type ) { 425 $cover_image = bp_attachments_cover_image_generate_file( array( 426 'file' => $image_file_path, 427 'component' => $r['component'], 428 'cover_image_dir' => $attachment_data['path'] 429 ) ); 427 $cover_image = bp_attachments_cover_image_generate_file( 428 array( 429 'file' => $image_file_path, 430 'component' => $r['component'], 431 'cover_image_dir' => $attachment_data['path'] 432 ) 433 ); 430 434 431 435 $created = ! empty( $cover_image['cover_file'] ); 432 436 } … … function bp_attachments_cover_image_ajax_delete() { 1597 1601 } 1598 1602 } 1599 1603 add_action( 'wp_ajax_bp_cover_image_delete', 'bp_attachments_cover_image_ajax_delete' ); 1604 1605 /** 1606 * List the files of a directory. 1607 * 1608 * @since 10.0.0 1609 * 1610 * @param string $directory_path Absolute path of a directory. 1611 * @return array The list of the files inside the directory. 1612 */ 1613 function bp_attachments_list_directory_files( $directory_path = '' ) { 1614 if ( ! is_dir( $directory_path ) ) { 1615 return array(); 1616 } 1617 1618 $files = array(); 1619 $iterator = new FilesystemIterator( $directory_path, FilesystemIterator::SKIP_DOTS ); 1620 1621 foreach ( $iterator as $file ) { 1622 $_file = new stdClass(); 1623 1624 $_file->name = $file->getfilename(); 1625 $_file->path = $file->getPathname(); 1626 $_file->size = $file->getSize(); 1627 $_file->type = $file->getType(); 1628 $_file->mime_type = mime_content_type( $_file->path ); 1629 $_file->last_modified = $file->getMTime(); 1630 $_file->latest_access_date = $file->getATime(); 1631 $_file->id = pathinfo( $_file->name, PATHINFO_FILENAME ); 1632 $files[ $_file->id ] = $_file; 1633 } 1634 1635 return $files; 1636 } 1637 1638 /** 1639 * List the files of a directory recursively and eventually find a file using its ID. 1640 * 1641 * @since 10.0.0 1642 * 1643 * @param string $directory_path Absolute path of a directory. 1644 * @param string $find The file ID to find into the directory or its children. 1645 * @return array The list of the files. 1646 */ 1647 function bp_attachments_list_directory_files_recursively( $directory_path = '', $find = '' ) { 1648 if ( ! is_dir( $directory_path ) ) { 1649 return array(); 1650 } 1651 1652 $files = array(); 1653 $directory = new RecursiveDirectoryIterator( $directory_path, FilesystemIterator::SKIP_DOTS ); 1654 $iterator = new RecursiveIteratorIterator( $directory, RecursiveIteratorIterator::CHILD_FIRST ); 1655 $bp_upload = bp_upload_dir(); 1656 1657 foreach ( $iterator as $file ) { 1658 $_file = new stdClass(); 1659 1660 $_file->name = $file->getfilename(); 1661 $_file->path = $file->getPathname(); 1662 $_file->size = $file->getSize(); 1663 $_file->type = $file->getType(); 1664 $_file->mime_type = mime_content_type( $_file->path ); 1665 $_file->last_modified = $file->getMTime(); 1666 $_file->latest_access_date = $file->getATime(); 1667 $_file->parent_dir_path = dirname( $_file->path ); 1668 $_file->parent_dir_url = str_replace( $bp_upload['basedir'], $bp_upload['baseurl'], $_file->parent_dir_path ); 1669 $_file->id = pathinfo( $_file->name, PATHINFO_FILENAME ); 1670 1671 // Ensure URL is https if SSL is set/forced. 1672 if ( is_ssl() ) { 1673 $_file->parent_dir_url = str_replace( 'http://', 'https://', $_file->parent_dir_url ); 1674 } 1675 1676 $file_id = $_file->id; 1677 if ( $_file->parent_dir_path !== $directory_path ) { 1678 $file_id = trailingslashit( str_replace( trailingslashit( $directory_path ), '', $_file->parent_dir_path ) ) . $file_id; 1679 } 1680 1681 $files[ $file_id ] = $_file; 1682 } 1683 1684 if ( $find ) { 1685 return wp_filter_object_list( $files, array( 'id' => $find ) ); 1686 } 1687 1688 return $files; 1689 } -
src/bp-core/bp-core-avatars.php
diff --git src/bp-core/bp-core-avatars.php src/bp-core/bp-core-avatars.php index 301c6bfdc..7336c6d3b 100644
add_action( 'wp_ajax_bp_avatar_upload', 'bp_avatar_ajax_upload' ); 1176 1176 * Handle avatar webcam capture. 1177 1177 * 1178 1178 * @since 2.3.0 1179 * @since 10.0.0 Adds the `$return` param to eventually return the crop result. 1179 1180 * 1180 1181 * @param string $data Base64 encoded image. 1181 1182 * @param int $item_id Item to associate. 1182 * @return bool True on success, false on failure. 1183 * @param string $return Whether to get the crop `array` or a `boolean`. Defaults to `boolean`. 1184 * @return array|bool True on success, false on failure. 1183 1185 */ 1184 function bp_avatar_handle_capture( $data = '', $item_id = 0 ) {1186 function bp_avatar_handle_capture( $data = '', $item_id = 0, $return = 'boolean' ) { 1185 1187 if ( empty( $data ) || empty( $item_id ) ) { 1186 1188 return false; 1187 1189 } … … function bp_avatar_handle_capture( $data = '', $item_id = 0 ) { 1237 1239 // Crop to default values. 1238 1240 $crop_args = array( 'item_id' => $item_id, 'original_file' => $avatar_to_crop, 'crop_x' => 0, 'crop_y' => 0 ); 1239 1241 1242 if ( 'array' === $return ) { 1243 return bp_core_avatar_handle_crop( $crop_args, 'array' ); 1244 } 1245 1240 1246 return bp_core_avatar_handle_crop( $crop_args ); 1241 1247 } else { 1242 1248 return false; … … function bp_avatar_handle_capture( $data = '', $item_id = 0 ) { 1247 1253 * Crop an uploaded avatar. 1248 1254 * 1249 1255 * @since 1.1.0 1256 * @since 10.0.0 Adds the `$return` param to eventually return the crop result. 1250 1257 * 1251 1258 * @param array|string $args { 1252 1259 * Array of function parameters. … … function bp_avatar_handle_capture( $data = '', $item_id = 0 ) { 1265 1272 * @type int $crop_x The horizontal starting point of the crop. Default: 0. 1266 1273 * @type int $crop_y The vertical starting point of the crop. Default: 0. 1267 1274 * } 1268 * @return bool True on success, false on failure. 1275 * @param string $return Whether to get the crop `array` or a `boolean`. Defaults to `boolean`. 1276 * @return array|bool True or the crop result on success, false on failure. 1269 1277 */ 1270 function bp_core_avatar_handle_crop( $args = '' ) {1278 function bp_core_avatar_handle_crop( $args = '', $return = 'boolean' ) { 1271 1279 1272 1280 $r = bp_parse_args( 1273 1281 $args, … … function bp_core_avatar_handle_crop( $args = '' ) { 1306 1314 return false; 1307 1315 } 1308 1316 1317 if ( 'array' === $return ) { 1318 return $cropped; 1319 } 1320 1309 1321 return true; 1310 1322 } 1311 1323 … … function bp_avatar_ajax_set() { 1352 1364 $webcam_avatar = base64_decode( $webcam_avatar ); 1353 1365 } 1354 1366 1355 if ( ! bp_avatar_handle_capture( $webcam_avatar, $avatar_data['item_id'] ) ) { 1367 $cropped_webcam_avatar = bp_avatar_handle_capture( $webcam_avatar, $avatar_data['item_id'], 'array' ); 1368 1369 if ( ! $cropped_webcam_avatar ) { 1356 1370 wp_send_json_error( array( 1357 1371 'feedback_code' => 1 1358 1372 ) ); 1359 1373 1360 1374 } else { 1361 1375 $return = array( 1362 'avatar' => esc_url( bp_core_fetch_avatar( array( 1363 'object' => $avatar_data['object'], 1364 'item_id' => $avatar_data['item_id'], 1365 'html' => false, 1366 'type' => 'full', 1367 ) ) ), 1376 'avatar' => esc_url( 1377 bp_core_fetch_avatar( 1378 array( 1379 'object' => $avatar_data['object'], 1380 'item_id' => $avatar_data['item_id'], 1381 'html' => false, 1382 'type' => 'full', 1383 ) 1384 ) 1385 ), 1368 1386 'feedback_code' => 2, 1369 1387 'item_id' => $avatar_data['item_id'], 1370 1388 ); … … function bp_avatar_ajax_set() { 1376 1394 * Fires if the new avatar was successfully captured. 1377 1395 * 1378 1396 * @since 6.0.0 1397 * @since 10.0.0 Adds a new param: an array containing the full, thumb avatar and the timestamp. 1379 1398 * 1380 * @param string $item_id Inform about the user id the avatar was set for. 1381 * @param string $type Inform about the way the avatar was set ('camera'). 1382 * @param array $avatar_data Array of parameters passed to the avatar handler. 1399 * @param string $item_id Inform about the user id the avatar was set for. 1400 * @param string $type Inform about the way the avatar was set ('camera'). 1401 * @param array $avatar_data Array of parameters passed to the crop handler. 1402 * @param array $cropped_webcam_avatar Array containing the full, thumb avatar and the timestamp. 1383 1403 */ 1384 do_action( 'bp_members_avatar_uploaded', (int) $avatar_data['item_id'], $avatar_data['type'], $avatar_data );1404 do_action( 'bp_members_avatar_uploaded', (int) $avatar_data['item_id'], $avatar_data['type'], $avatar_data, $cropped_webcam_avatar ); 1385 1405 1386 1406 wp_send_json_success( $return ); 1387 1407 } … … function bp_avatar_ajax_set() { 1413 1433 ); 1414 1434 1415 1435 // Handle crop. 1416 if ( bp_core_avatar_handle_crop( $r ) ) { 1436 $cropped_avatar = bp_core_avatar_handle_crop( $r, 'array' ); 1437 1438 if ( $cropped_avatar ) { 1417 1439 $return = array( 1418 'avatar' => esc_url( bp_core_fetch_avatar( array( 1419 'object' => $avatar_data['object'], 1420 'item_id' => $avatar_data['item_id'], 1421 'html' => false, 1422 'type' => 'full', 1423 ) ) ), 1440 'avatar' => esc_url( 1441 bp_core_fetch_avatar( 1442 array( 1443 'object' => $avatar_data['object'], 1444 'item_id' => $avatar_data['item_id'], 1445 'html' => false, 1446 'type' => 'full', 1447 ) 1448 ) 1449 ), 1424 1450 'feedback_code' => 2, 1425 1451 'item_id' => $avatar_data['item_id'], 1426 1452 ); … … function bp_avatar_ajax_set() { 1430 1456 do_action_deprecated( 'xprofile_avatar_uploaded', array( (int) $avatar_data['item_id'], $avatar_data['type'], $r ), '6.0.0', 'bp_members_avatar_uploaded' ); 1431 1457 1432 1458 /** This action is documented in bp-core/bp-core-avatars.php */ 1433 do_action( 'bp_members_avatar_uploaded', (int) $avatar_data['item_id'], $avatar_data['type'], $r );1459 do_action( 'bp_members_avatar_uploaded', (int) $avatar_data['item_id'], $avatar_data['type'], $r, $cropped_avatar ); 1434 1460 } elseif ( 'group' === $avatar_data['object'] ) { 1435 1461 /** This action is documented in bp-groups/bp-groups-screens.php */ 1436 do_action( 'groups_avatar_uploaded', (int) $avatar_data['item_id'], $avatar_data['type'], $r );1462 do_action( 'groups_avatar_uploaded', (int) $avatar_data['item_id'], $avatar_data['type'], $r, $cropped_avatar ); 1437 1463 } 1438 1464 1439 1465 wp_send_json_success( $return ); … … function bp_avatar_template_check() { 2122 2148 bp_attachments_get_template_part( 'avatars/index' ); 2123 2149 } 2124 2150 } 2151 2152 /** 2153 * Get a specific version of an avatar from its history 2154 * 2155 * @since 10.0.0 2156 * 2157 * @param int $user_id The user ID we need the avatar version for. 2158 * @param int|string $timestamp An integer Unix timestamp or a date string of the format 'Y-m-d h:i:s'. 2159 * @param string $type The type of avatar we need. Possible values are `thumb` and `full`. 2160 * @return array A list of matching results, an empty array if no avatars were found. 2161 */ 2162 function bp_avatar_get_version_src( $user_id = 0, $timestamp = '', $type = 'full' ) { 2163 if ( ! $user_id || ! $timestamp ) { 2164 return array(); 2165 } 2166 2167 if ( ! is_numeric( $timestamp ) ) { 2168 $timestamp = strtotime( $timestamp ); 2169 } 2170 2171 $avatar_id = $timestamp . '-bpfull'; 2172 if ( 'full' !== $type ) { 2173 $avatar_id = $timestamp . '-bpthumb'; 2174 } 2175 2176 // The user avatar directory we are looking into to get the avatar url. 2177 $user_avatar_dir = trailingslashit( bp_core_avatar_upload_path() ) . 'avatars/' . $user_id; 2178 2179 return bp_attachments_list_directory_files_recursively( $user_avatar_dir, $avatar_id ); 2180 } -
src/bp-core/classes/class-bp-attachment-avatar.php
diff --git src/bp-core/classes/class-bp-attachment-avatar.php src/bp-core/classes/class-bp-attachment-avatar.php index d95ad4c4c..926feda30 100644
class BP_Attachment_Avatar extends BP_Attachment { 199 199 * @see BP_Attachment::crop for the list of parameters 200 200 * 201 201 * @param array $args Array of arguments for the cropping. 202 * @return array The cropped avatars (full and thumb).202 * @return array The cropped avatars (full, thumb and the timestamp). 203 203 */ 204 204 public function crop( $args = array() ) { 205 205 // Bail if the original file is missing. … … class BP_Attachment_Avatar extends BP_Attachment { 255 255 256 256 /** 257 257 * Check that the new avatar doesn't have the same name as the 258 * old one before deleting258 * old one before moving the previous one into history. 259 259 */ 260 260 if ( ! empty( $existing_avatar ) && $existing_avatar !== $this->url . $relative_path ) { 261 bp_core_delete_existing_avatar( array( 'object' => $args['object'], 'item_id' => $args['item_id'], 'avatar_path' => $avatar_folder_dir ) ); 261 // Add a new revision for the existing avatar. 262 $avatars = bp_attachments_list_directory_files( $avatar_folder_dir ); 263 264 if ( $avatars ) { 265 foreach ( $avatars as $avatar_file ) { 266 if ( ! isset( $avatar_file->name, $avatar_file->id, $avatar_file->path ) ) { 267 continue; 268 } 269 270 $is_full = preg_match( "/-bpfull/", $avatar_file->name ); 271 $is_thumb = preg_match( "/-bpthumb/", $avatar_file->name ); 272 273 if ( $is_full || $is_thumb ) { 274 $revision = $this->add_revision( 275 'avatar', 276 array( 277 'file_abspath' => $avatar_file->path, 278 'file_id' => $avatar_file->id, 279 ) 280 ); 281 282 if ( is_wp_error( $revision ) ) { 283 error_log( $revision->get_error_message() ); 284 } 285 } 286 } 287 } 262 288 } 263 289 264 290 // Make sure we at least have minimal data for cropping. … … class BP_Attachment_Avatar extends BP_Attachment { 272 298 273 299 // Get the file extension. 274 300 $data = @getimagesize( $absolute_path ); 275 $ext = $data['mime'] == 'image/png' ? 'png' : 'jpg';301 $ext = $data['mime'] === 'image/png' ? 'png' : 'jpg'; 276 302 277 303 $args['original_file'] = $absolute_path; 278 304 $args['src_abs'] = false; 279 $avatar_types = array( 'full' => '', 'thumb' => '' ); 305 306 $avatar_types = array( 307 'full' => '', 308 'thumb' => '', 309 ); 310 $timestamp = bp_core_current_time( true, 'timestamp' ); 280 311 281 312 foreach ( $avatar_types as $key_type => $type ) { 282 313 if ( 'thumb' === $key_type ) { … … class BP_Attachment_Avatar extends BP_Attachment { 287 318 $args['dst_h'] = bp_core_avatar_full_height(); 288 319 } 289 320 290 $filename = wp_unique_filename( $avatar_folder_dir, uniqid(). "-bp{$key_type}.{$ext}" );321 $filename = wp_unique_filename( $avatar_folder_dir, $timestamp . "-bp{$key_type}.{$ext}" ); 291 322 $args['dst_file'] = $avatar_folder_dir . '/' . $filename; 292 323 293 324 $avatar_types[ $key_type ] = parent::crop( $args ); … … class BP_Attachment_Avatar extends BP_Attachment { 296 327 // Remove the original. 297 328 @unlink( $absolute_path ); 298 329 299 // Return the full and thumb cropped avatars. 300 return $avatar_types; 330 // Return the full, thumb cropped avatars and the timestamp. 331 return array_merge( 332 $avatar_types, 333 array( 334 'timestamp' => $timestamp, 335 ) 336 ); 301 337 } 302 338 303 339 /** -
src/bp-core/classes/class-bp-attachment.php
diff --git src/bp-core/classes/class-bp-attachment.php src/bp-core/classes/class-bp-attachment.php index 9362a6c12..248c44946 100644
abstract class BP_Attachment { 559 559 return $script_data; 560 560 } 561 561 562 /** 563 * Adds a new revision of a file. 564 * 565 * @since 10.0.0 566 * 567 * @param string $attachment_type The attachement type (eg: avatar). 568 * @param array $args { 569 * @type string $file_abspath The source file (absolute path) for the attachment. 570 * @type string $file_id Optional. The file ID to use as a suffix for the revision directory. 571 * } 572 * @return object|WP_Error An object informing about the URL an Path to a revision file, a WP_Error object on failure. 573 */ 574 public function add_revision( $attachment_type, $args = array() ) { 575 $r = bp_parse_args( 576 $args, 577 array( 578 'file_abspath' => '', 579 'file_id' => '', 580 ), 581 'attachment_' . $attachment_type . '_add_revision' 582 ); 583 584 if ( ! $r['file_abspath'] ) { 585 return new WP_Error( 'missing_parameter', __( 'The absolute path to your file is missing.', 'buddypress' ) ); 586 587 // Make sure it's coming from an uploaded file. 588 } elseif ( false === strpos( $r['file_abspath'], $this->upload_path ) ) { 589 return new WP_Error( 'forbidden_path', __( 'The absolute path to your file is not allowed.', 'buddypress' ) ); 590 591 } else { 592 $filepath = $r['file_abspath']; 593 } 594 595 $dirname = trailingslashit( dirname( $filepath ) ); 596 $filename = sanitize_file_name( wp_basename( $filepath ) ); 597 598 if ( ! $r['file_id'] ) { 599 $r['file_id'] = $filename; 600 } 601 602 $file_id = wp_hash( $r['file_id'] ); 603 604 // Set the revision name & dir. 605 $revision_name = ''; 606 $revision_dir = $dirname . '._revisions_' . $file_id; 607 608 // Avatars and Cover Images are specific attachments. 609 if ( 'avatar' === $attachment_type || 'cover_image' === $attachment_type ) { 610 $revision_dir = $dirname . 'history'; 611 } 612 613 // Create the revision directory if it doesn't exist yet. 614 if ( ! is_dir( $revision_dir ) ) { 615 mkdir( $revision_dir ); 616 } 617 618 $revision_name = wp_unique_filename( $revision_dir, $filename ); 619 $revision_path = trailingslashit( $revision_dir ) . $revision_name; 620 621 if ( ! rename( $filepath, $revision_path ) ) { 622 return new WP_Error( 'missing_parameter', __( 'An unexpected error occured while adding the revision.', 'buddypress' ) ); 623 } 624 625 return (object) array( 626 'url' => str_replace( trailingslashit( $this->upload_path ), trailingslashit( $this->url ), $revision_path ), 627 'path' => $revision_path, 628 ); 629 } 630 562 631 /** 563 632 * Get full data for an image 564 633 * -
src/bp-groups/actions/create.php
diff --git src/bp-groups/actions/create.php src/bp-groups/actions/create.php index 132429bd1..54e2cc589 100644
function groups_action_create_group() { 270 270 'crop_h' => $_POST['h'] 271 271 ); 272 272 273 if ( ! bp_core_avatar_handle_crop( $args ) ) { 273 $cropped_avatar = bp_core_avatar_handle_crop( $args, 'array' ); 274 275 if ( ! $cropped_avatar ) { 274 276 bp_core_add_message( __( 'There was an error saving the group profile photo, please try uploading again.', 'buddypress' ), 'error' ); 275 277 } else { 276 278 /** 277 279 * Fires after a group avatar is uploaded. 278 280 * 279 281 * @since 2.8.0 282 * @since 10.0.0 Adds a new param: an array containing the full, thumb avatar and the timestamp. 280 283 * 281 * @param int $group_id ID of the group. 282 * @param string $type Avatar type. 'crop' or 'full'. 283 * @param array $args Array of parameters passed to the avatar handler. 284 * @param int $group_id ID of the group. 285 * @param string $type Avatar type. 'crop' or 'camera'. 286 * @param array $args Array of parameters passed to the crop handler. 287 * @param array $cropped_avatar Array containing the full, thumb avatar and the timestamp. 284 288 */ 285 do_action( 'groups_avatar_uploaded', bp_get_current_group_id(), 'crop', $args );289 do_action( 'groups_avatar_uploaded', bp_get_current_group_id(), 'crop', $args, $cropped_avatar ); 286 290 287 291 bp_core_add_message( __( 'The group profile photo was uploaded successfully.', 'buddypress' ) ); 288 292 } -
src/bp-groups/screens/single/admin/group-avatar.php
diff --git src/bp-groups/screens/single/admin/group-avatar.php src/bp-groups/screens/single/admin/group-avatar.php index 3e2927a1e..57fc59451 100644
function groups_screen_group_admin_avatar() { 74 74 'crop_h' => $_POST['h'] 75 75 ); 76 76 77 if ( !bp_core_avatar_handle_crop( $args ) ) { 77 $cropped_avatar = bp_core_avatar_handle_crop( $args, 'array' ); 78 79 if ( ! $cropped_avatar ) { 78 80 bp_core_add_message( __( 'There was a problem cropping the group profile photo.', 'buddypress' ), 'error' ); 79 81 } else { 80 82 /** 81 83 * Fires after a group avatar is uploaded. 82 84 * 83 85 * @since 2.8.0 86 * @since 10.0.0 Adds a new param: an array containing the full, thumb avatar and the timestamp. 84 87 * 85 * @param int $group_id ID of the group. 86 * @param string $type Avatar type. 'crop' or 'full'. 87 * @param array $args Array of parameters passed to the avatar handler. 88 * @param int $group_id ID of the group. 89 * @param string $type Avatar type. 'crop' or 'camera'. 90 * @param array $args Array of parameters passed to the avatar handler. 91 * @param array $cropped_avatar Array containing the full, thumb avatar and the timestamp. 88 92 */ 89 do_action( 'groups_avatar_uploaded', bp_get_current_group_id(), 'crop', $args );93 do_action( 'groups_avatar_uploaded', bp_get_current_group_id(), 'crop', $args, $cropped_avatar ); 90 94 bp_core_add_message( __( 'The new group profile photo was uploaded successfully.', 'buddypress' ) ); 91 95 } 92 96 } … … function groups_screen_group_admin_avatar() { 109 113 */ 110 114 bp_core_load_template( apply_filters( 'groups_template_group_admin_avatar', 'groups/single/home' ) ); 111 115 } 112 add_action( 'bp_screens', 'groups_screen_group_admin_avatar' ); 113 No newline at end of file 116 add_action( 'bp_screens', 'groups_screen_group_admin_avatar' ); -
src/bp-members/bp-members-activity.php
diff --git src/bp-members/bp-members-activity.php src/bp-members/bp-members-activity.php index 890ff2317..1645c1542 100644
add_action( 'bp_core_activated_user', 'bp_core_new_user_activity' ); 166 166 * Adds an activity stream item when a user has uploaded a new avatar. 167 167 * 168 168 * @since 8.0.0 169 * @since 10.0.0 Adds the `$type`, `$crop_data` and `$cropped_avatar` parameters. 169 170 * 170 * @param int $user_id The user id the avatar was set for. 171 * @param int $user_id The user id the avatar was set for. 172 * @param string $type The way the avatar was set ('camera' or `crop`). 173 * @param array $crop_data Array of parameters passed to the crop handler. 174 * @param array $cropped_avatar Array containing the full, thumb avatar and the timestamp. 171 175 */ 172 function bp_members_new_avatar_activity( $user_id = 0 ) {176 function bp_members_new_avatar_activity( $user_id = 0, $type = '', $crop_data = array(), $cropped_avatar = array() ) { 173 177 174 178 // Bail if activity component is not active. 175 179 if ( ! bp_is_active( 'activity' ) ) { … … function bp_members_new_avatar_activity( $user_id = 0 ) { 230 234 } 231 235 } 232 236 237 $recorded_time = ''; 238 if ( isset( $cropped_avatar['timestamp'] ) && $cropped_avatar['timestamp'] ) { 239 $recorded_time = date( 'Y-m-d H:i:s', $cropped_avatar['timestamp'] ); 240 } 241 233 242 // Add the activity. 234 bp_activity_add(243 $activity_id = bp_activity_add( 235 244 array( 236 'user_id' => $user_id, 237 'component' => $bp->members->id, 238 'type' => 'new_avatar', 245 'user_id' => $user_id, 246 'component' => $bp->members->id, 247 'type' => 'new_avatar', 248 'recorded_time' => $recorded_time, 239 249 ) 240 250 ); 241 251 } 242 add_action( 'bp_members_avatar_uploaded', 'bp_members_new_avatar_activity' );252 add_action( 'bp_members_avatar_uploaded', 'bp_members_new_avatar_activity', 10, 4 ); -
src/bp-members/screens/change-avatar.php
diff --git src/bp-members/screens/change-avatar.php src/bp-members/screens/change-avatar.php index 5c4bcf440..6a421ec77 100644
function bp_members_screen_change_avatar() { 61 61 'crop_h' => $_POST['h'] 62 62 ); 63 63 64 if ( ! bp_core_avatar_handle_crop( $args ) ) { 64 // Handle crop. 65 $cropped_avatar = bp_core_avatar_handle_crop( $r, 'array' ); 66 67 if ( ! $cropped_avatar ) { 65 68 bp_core_add_message( __( 'There was a problem cropping your profile photo.', 'buddypress' ), 'error' ); 66 69 } else { 67 70 … … function bp_members_screen_change_avatar() { 72 75 * Fires right before the redirect, after processing a new avatar. 73 76 * 74 77 * @since 6.0.0 78 * @since 10.0.0 Adds a new param: an array containing the full, thumb avatar and the timestamp. 75 79 * 76 * @param string $item_id Inform about the user id the avatar was set for. 77 * @param string $value Inform about the way the avatar was set ('crop'). 80 * @param string $item_id Inform about the user id the avatar was set for. 81 * @param string $type Inform about the way the avatar was set ('camera'). 82 * @param array $args Array of parameters passed to the crop handler. 83 * @param array $cropped_avatar Array containing the full, thumb avatar and the timestamp. 78 84 */ 79 do_action( 'bp_members_avatar_uploaded', (int) $args['item_id'], 'crop' );85 do_action( 'bp_members_avatar_uploaded', (int) $args['item_id'], 'crop', $args, $cropped_avatar ); 80 86 81 87 bp_core_add_message( __( 'Your new profile photo was uploaded successfully.', 'buddypress' ) ); 82 88 bp_core_redirect( bp_displayed_user_domain() ); -
new file src/bp-templates/bp-legacy/buddypress/activity/type-parts/created-group.php
diff --git src/bp-templates/bp-legacy/buddypress/activity/type-parts/created-group.php src/bp-templates/bp-legacy/buddypress/activity/type-parts/created-group.php new file mode 100644 index 000000000..af25c0b34
- + 1 <?php 2 /** 3 * BuddyPress - `created_group` activity type content part. 4 * 5 * This template is only used to display the `created_group` activity type content. 6 * 7 * @since 1O.0.0 8 * @version 10.0.0 9 */ 10 ?> 11 <div class="bp-group-activity-preview"> 12 13 <?php if ( bp_activity_has_generated_content_part( 'group_cover_image' ) ) : ?> 14 <div class="bp-group-preview-cover"> 15 <a href="<?php bp_activity_generated_content_part( 'group_url' ); ?>"> 16 <img src="<?php bp_activity_generated_content_part( 'group_cover_image' ); ?>" alt=""/> 17 </a> 18 </div> 19 <?php endif; ?> 20 21 <div class="bp-group-short-description"> 22 <?php if ( bp_activity_has_generated_content_part( 'group_profile_photo' ) ) : ?> 23 <div class="bp-group-avatar-content <?php echo bp_activity_has_generated_content_part( 'group_cover_image' ) ? 'has-cover-image' : ''; ?>"> 24 <a href="<?php bp_activity_generated_content_part( 'group_url' ); ?>"> 25 <img src="<?php bp_activity_generated_content_part( 'group_profile_photo' ); ?>" class="profile-photo avatar" alt=""/> 26 </a> 27 </div> 28 <?php endif; ?> 29 30 <p class="bp-group-short-description-title"> 31 <a href="<?php bp_activity_generated_content_part( 'group_url' ); ?>"><?php bp_activity_generated_content_part( 'group_name' ); ?></a> 32 </p> 33 34 <div class="bp-profile-button"> 35 <a href="<?php bp_activity_generated_content_part( 'group_url' ); ?>" class="button large primary button-primary" role="button"><?php esc_html_e( 'Visit group', 'buddypress'); ?></a> 36 </div> 37 </div> 38 </div> -
new file src/bp-templates/bp-legacy/buddypress/activity/type-parts/friendship-created.php
diff --git src/bp-templates/bp-legacy/buddypress/activity/type-parts/friendship-created.php src/bp-templates/bp-legacy/buddypress/activity/type-parts/friendship-created.php new file mode 100644 index 000000000..b4ba00655
- + 1 <?php 2 /** 3 * BuddyPress - `friendship_created` activity type content part. 4 * 5 * This template is only used to display the `friendship_created` activity type content. 6 * 7 * @since 1O.0.0 8 * @version 10.0.0 9 */ 10 11 bp_get_template_part( 'activity/type-parts/new-avatar' ); -
new file src/bp-templates/bp-legacy/buddypress/activity/type-parts/joined-group.php
diff --git src/bp-templates/bp-legacy/buddypress/activity/type-parts/joined-group.php src/bp-templates/bp-legacy/buddypress/activity/type-parts/joined-group.php new file mode 100644 index 000000000..c83469b9d
- + 1 <?php 2 /** 3 * BuddyPress - `joined_group` activity type content part. 4 * 5 * This template is only used to display the `joined_group` activity type content. 6 * 7 * @since 1O.0.0 8 * @version 10.0.0 9 */ 10 11 bp_get_template_part( 'activity/type-parts/created-group' ); -
new file src/bp-templates/bp-legacy/buddypress/activity/type-parts/new-avatar.php
diff --git src/bp-templates/bp-legacy/buddypress/activity/type-parts/new-avatar.php src/bp-templates/bp-legacy/buddypress/activity/type-parts/new-avatar.php new file mode 100644 index 000000000..c4976130b
- + 1 <?php 2 /** 3 * BuddyPress - `new_avatar` activity type content part. 4 * 5 * This template is only used to display the `new_avatar` activity type content. 6 * 7 * @since 1O.0.0 8 * @version 10.0.0 9 */ 10 ?> 11 <div class="bp-member-activity-preview"> 12 13 <?php if ( bp_activity_has_generated_content_part( 'user_cover_image' ) ) : ?> 14 <div class="bp-member-preview-cover"> 15 <a href="<?php bp_activity_generated_content_part( 'user_url' ); ?>"> 16 <img src="<?php bp_activity_generated_content_part( 'user_cover_image' ); ?>" alt=""/> 17 </a> 18 </div> 19 <?php endif; ?> 20 21 <div class="bp-member-short-description"> 22 <?php if ( bp_activity_has_generated_content_part( 'user_profile_photo' ) ) : ?> 23 <div class="bp-member-avatar-content <?php echo bp_activity_has_generated_content_part( 'user_cover_image' ) ? 'has-cover-image' : ''; ?>"> 24 <a href="<?php bp_activity_generated_content_part( 'user_url' ); ?>"> 25 <img src="<?php bp_activity_generated_content_part( 'user_profile_photo' ); ?>" class="profile-photo avatar" alt=""/> 26 </a> 27 </div> 28 <?php endif; ?> 29 30 <p class="bp-member-short-description-title"> 31 <a href="<?php bp_activity_generated_content_part( 'user_url' ); ?>"><?php bp_activity_generated_content_part( 'user_display_name' ); ?></a> 32 </p> 33 34 <p class="bp-member-nickname"> 35 <a href="<?php is_user_logged_in() ? bp_activity_generated_content_part( 'user_mention_url' ) : bp_activity_generated_content_part( 'user_url' ); ?>">@<?php bp_activity_generated_content_part( 'user_mention_name' ); ?></a> 36 </p> 37 38 <div class="bp-profile-button"> 39 <a href="<?php bp_activity_generated_content_part( 'user_url' ); ?>" class="button large primary button-primary" role="button"><?php esc_html_e( 'View Profile', 'buddypress'); ?></a> 40 </div> 41 </div> 42 </div> -
src/bp-templates/bp-legacy/css/buddypress-rtl.css
diff --git src/bp-templates/bp-legacy/css/buddypress-rtl.css src/bp-templates/bp-legacy/css/buddypress-rtl.css index d99591d63..5e889c519 100644
Hello, this is the BuddyPress Legacy stylesheet. 30 30 4.1 - Smartphones Landscape 31 31 4.2 - Smartphones Portrait 32 32 4.3 - Smartphones - smaller screen sizes 33 5.0 - Activity Types. 33 34 --------------------------------------------------------------*/ 34 35 35 36 /*-------------------------------------------------------------- … … body.register #buddypress div.page ul { 2281 2282 margin: 10px 0 20px; 2282 2283 } 2283 2284 } 2285 2286 /*-------------------------------------------------------------- 2287 5.0 - Activity Types 2288 --------------------------------------------------------------*/ 2289 .bp-member-preview-cover, 2290 .bp-group-preview-cover { 2291 position: relative; 2292 min-height: 150px; 2293 background: #c5c5c5; 2294 } 2295 2296 .bp-member-preview-cover img, 2297 .bp-group-preview-cover img { 2298 background: #c5c5c5; 2299 -o-object-fit: cover; 2300 object-fit: cover; 2301 border: 0; 2302 display: block; 2303 margin: 0; 2304 padding: 0; 2305 width: 100%; 2306 z-index: 1; 2307 height: 150px; 2308 } 2309 2310 .bp-member-avatar-content, 2311 .bp-group-avatar-content { 2312 float: right; 2313 width: 120px; 2314 position: relative; 2315 z-index: 2; 2316 } 2317 2318 .bp-member-avatar-content.has-cover-image, 2319 .bp-group-avatar-content.has-cover-image { 2320 width: 200px; 2321 margin-top: -75px; 2322 } 2323 2324 .bp-member-avatar-content img.profile-photo, 2325 .bp-group-avatar-content img.group-photo { 2326 border: solid 2px #fff; 2327 background: rgba(255, 255, 255, 0.8); 2328 margin-right: 20px; 2329 height: 80px; 2330 width: 80px; 2331 } 2332 2333 .bp-member-avatar-content.has-cover-image img.profile-photo, 2334 .bp-member-avatar-content.has-cover-image img.group-photo, 2335 .bp-group-avatar-content.has-cover-image img.profile-photo, 2336 .bp-group-avatar-content.has-cover-image img.group-photo { 2337 height: inherit; 2338 width: inherit; 2339 } 2340 2341 .bp-member-short-description-title a, 2342 .bp-group-short-description-title a { 2343 font-weight: 600; 2344 } 2345 2346 @media screen and (max-width: 46.8em) { 2347 2348 .bp-member-short-description, 2349 .bp-group-short-description { 2350 text-align: center; 2351 } 2352 2353 .bp-member-avatar-content, 2354 .bp-group-avatar-content { 2355 float: none; 2356 width: 100%; 2357 margin-right: auto; 2358 margin-left: auto; 2359 margin-bottom: 15px; 2360 } 2361 2362 .bp-member-avatar-content img.profile-photo, 2363 .bp-group-avatar-content img.group-photo { 2364 margin: auto; 2365 } 2366 2367 .bp-profile-button { 2368 margin-top: 15px; 2369 } 2370 } 2371 2372 @media screen and (min-width: 46.8em) { 2373 2374 .bp-profile-button { 2375 text-align: left; 2376 } 2377 } -
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 be7270d71..e7efa2db9 100644
Hello, this is the BuddyPress Legacy stylesheet. 30 30 4.1 - Smartphones Landscape 31 31 4.2 - Smartphones Portrait 32 32 4.3 - Smartphones - smaller screen sizes 33 5.0 - Activity Types. 33 34 --------------------------------------------------------------*/ 34 35 35 36 /*-------------------------------------------------------------- … … body.register #buddypress div.page ul { 2281 2282 margin: 10px 0 20px; 2282 2283 } 2283 2284 } 2285 2286 /*-------------------------------------------------------------- 2287 5.0 - Activity Types 2288 --------------------------------------------------------------*/ 2289 .bp-member-preview-cover, 2290 .bp-group-preview-cover { 2291 position: relative; 2292 min-height: 150px; 2293 background: #c5c5c5; 2294 } 2295 2296 .bp-member-preview-cover img, 2297 .bp-group-preview-cover img { 2298 background: #c5c5c5; 2299 -o-object-fit: cover; 2300 object-fit: cover; 2301 border: 0; 2302 display: block; 2303 margin: 0; 2304 padding: 0; 2305 width: 100%; 2306 z-index: 1; 2307 height: 150px; 2308 } 2309 2310 .bp-member-avatar-content, 2311 .bp-group-avatar-content { 2312 float: left; 2313 width: 120px; 2314 position: relative; 2315 z-index: 2; 2316 } 2317 2318 .bp-member-avatar-content.has-cover-image, 2319 .bp-group-avatar-content.has-cover-image { 2320 width: 200px; 2321 margin-top: -75px; 2322 } 2323 2324 .bp-member-avatar-content img.profile-photo, 2325 .bp-group-avatar-content img.group-photo { 2326 border: solid 2px #fff; 2327 background: rgba(255, 255, 255, 0.8); 2328 margin-left: 20px; 2329 height: 80px; 2330 width: 80px; 2331 } 2332 2333 .bp-member-avatar-content.has-cover-image img.profile-photo, 2334 .bp-member-avatar-content.has-cover-image img.group-photo, 2335 .bp-group-avatar-content.has-cover-image img.profile-photo, 2336 .bp-group-avatar-content.has-cover-image img.group-photo { 2337 height: inherit; 2338 width: inherit; 2339 } 2340 2341 .bp-member-short-description-title a, 2342 .bp-group-short-description-title a { 2343 font-weight: 600; 2344 } 2345 2346 @media screen and (max-width: 46.8em) { 2347 2348 .bp-member-short-description, 2349 .bp-group-short-description { 2350 text-align: center; 2351 } 2352 2353 .bp-member-avatar-content, 2354 .bp-group-avatar-content { 2355 float: none; 2356 width: 100%; 2357 margin-left: auto; 2358 margin-right: auto; 2359 margin-bottom: 15px; 2360 } 2361 2362 .bp-member-avatar-content img.profile-photo, 2363 .bp-group-avatar-content img.group-photo { 2364 margin: auto; 2365 } 2366 2367 .bp-profile-button { 2368 margin-top: 15px; 2369 } 2370 } 2371 2372 @media screen and (min-width: 46.8em) { 2373 2374 .bp-profile-button { 2375 text-align: right; 2376 } 2377 } -
new file src/bp-templates/bp-nouveau/buddypress/activity/type-parts/created-group.php
diff --git src/bp-templates/bp-nouveau/buddypress/activity/type-parts/created-group.php src/bp-templates/bp-nouveau/buddypress/activity/type-parts/created-group.php new file mode 100644 index 000000000..af25c0b34
- + 1 <?php 2 /** 3 * BuddyPress - `created_group` activity type content part. 4 * 5 * This template is only used to display the `created_group` activity type content. 6 * 7 * @since 1O.0.0 8 * @version 10.0.0 9 */ 10 ?> 11 <div class="bp-group-activity-preview"> 12 13 <?php if ( bp_activity_has_generated_content_part( 'group_cover_image' ) ) : ?> 14 <div class="bp-group-preview-cover"> 15 <a href="<?php bp_activity_generated_content_part( 'group_url' ); ?>"> 16 <img src="<?php bp_activity_generated_content_part( 'group_cover_image' ); ?>" alt=""/> 17 </a> 18 </div> 19 <?php endif; ?> 20 21 <div class="bp-group-short-description"> 22 <?php if ( bp_activity_has_generated_content_part( 'group_profile_photo' ) ) : ?> 23 <div class="bp-group-avatar-content <?php echo bp_activity_has_generated_content_part( 'group_cover_image' ) ? 'has-cover-image' : ''; ?>"> 24 <a href="<?php bp_activity_generated_content_part( 'group_url' ); ?>"> 25 <img src="<?php bp_activity_generated_content_part( 'group_profile_photo' ); ?>" class="profile-photo avatar" alt=""/> 26 </a> 27 </div> 28 <?php endif; ?> 29 30 <p class="bp-group-short-description-title"> 31 <a href="<?php bp_activity_generated_content_part( 'group_url' ); ?>"><?php bp_activity_generated_content_part( 'group_name' ); ?></a> 32 </p> 33 34 <div class="bp-profile-button"> 35 <a href="<?php bp_activity_generated_content_part( 'group_url' ); ?>" class="button large primary button-primary" role="button"><?php esc_html_e( 'Visit group', 'buddypress'); ?></a> 36 </div> 37 </div> 38 </div> -
new file src/bp-templates/bp-nouveau/buddypress/activity/type-parts/friendship-created.php
diff --git src/bp-templates/bp-nouveau/buddypress/activity/type-parts/friendship-created.php src/bp-templates/bp-nouveau/buddypress/activity/type-parts/friendship-created.php new file mode 100644 index 000000000..b4ba00655
- + 1 <?php 2 /** 3 * BuddyPress - `friendship_created` activity type content part. 4 * 5 * This template is only used to display the `friendship_created` activity type content. 6 * 7 * @since 1O.0.0 8 * @version 10.0.0 9 */ 10 11 bp_get_template_part( 'activity/type-parts/new-avatar' ); -
new file src/bp-templates/bp-nouveau/buddypress/activity/type-parts/joined-group.php
diff --git src/bp-templates/bp-nouveau/buddypress/activity/type-parts/joined-group.php src/bp-templates/bp-nouveau/buddypress/activity/type-parts/joined-group.php new file mode 100644 index 000000000..c83469b9d
- + 1 <?php 2 /** 3 * BuddyPress - `joined_group` activity type content part. 4 * 5 * This template is only used to display the `joined_group` activity type content. 6 * 7 * @since 1O.0.0 8 * @version 10.0.0 9 */ 10 11 bp_get_template_part( 'activity/type-parts/created-group' ); -
new file src/bp-templates/bp-nouveau/buddypress/activity/type-parts/new-avatar.php
diff --git src/bp-templates/bp-nouveau/buddypress/activity/type-parts/new-avatar.php src/bp-templates/bp-nouveau/buddypress/activity/type-parts/new-avatar.php new file mode 100644 index 000000000..c4976130b
- + 1 <?php 2 /** 3 * BuddyPress - `new_avatar` activity type content part. 4 * 5 * This template is only used to display the `new_avatar` activity type content. 6 * 7 * @since 1O.0.0 8 * @version 10.0.0 9 */ 10 ?> 11 <div class="bp-member-activity-preview"> 12 13 <?php if ( bp_activity_has_generated_content_part( 'user_cover_image' ) ) : ?> 14 <div class="bp-member-preview-cover"> 15 <a href="<?php bp_activity_generated_content_part( 'user_url' ); ?>"> 16 <img src="<?php bp_activity_generated_content_part( 'user_cover_image' ); ?>" alt=""/> 17 </a> 18 </div> 19 <?php endif; ?> 20 21 <div class="bp-member-short-description"> 22 <?php if ( bp_activity_has_generated_content_part( 'user_profile_photo' ) ) : ?> 23 <div class="bp-member-avatar-content <?php echo bp_activity_has_generated_content_part( 'user_cover_image' ) ? 'has-cover-image' : ''; ?>"> 24 <a href="<?php bp_activity_generated_content_part( 'user_url' ); ?>"> 25 <img src="<?php bp_activity_generated_content_part( 'user_profile_photo' ); ?>" class="profile-photo avatar" alt=""/> 26 </a> 27 </div> 28 <?php endif; ?> 29 30 <p class="bp-member-short-description-title"> 31 <a href="<?php bp_activity_generated_content_part( 'user_url' ); ?>"><?php bp_activity_generated_content_part( 'user_display_name' ); ?></a> 32 </p> 33 34 <p class="bp-member-nickname"> 35 <a href="<?php is_user_logged_in() ? bp_activity_generated_content_part( 'user_mention_url' ) : bp_activity_generated_content_part( 'user_url' ); ?>">@<?php bp_activity_generated_content_part( 'user_mention_name' ); ?></a> 36 </p> 37 38 <div class="bp-profile-button"> 39 <a href="<?php bp_activity_generated_content_part( 'user_url' ); ?>" class="button large primary button-primary" role="button"><?php esc_html_e( 'View Profile', 'buddypress'); ?></a> 40 </div> 41 </div> 42 </div> -
src/bp-templates/bp-nouveau/buddypress/activity/widget.php
diff --git src/bp-templates/bp-nouveau/buddypress/activity/widget.php src/bp-templates/bp-nouveau/buddypress/activity/widget.php index 70cd0da60..6ff93a9e0 100644
21 21 <?php if ( bp_activity_has_content() ) : ?> 22 22 23 23 <div class="<?php bp_activity_css_class(); ?>"> 24 <?php bp_activity_content_body( ); ?>24 <?php bp_activity_content_body( 'widget' ); ?> 25 25 </div> 26 26 27 27 <footer> -
src/bp-templates/bp-nouveau/common-styles/_bp_activity_entries.scss
diff --git src/bp-templates/bp-nouveau/common-styles/_bp_activity_entries.scss src/bp-templates/bp-nouveau/common-styles/_bp_activity_entries.scss index edd598f92..68fc4eaea 100644
body.activity-permalink { 436 436 437 437 } 438 438 } 439 440 // Activity Types Entry View 441 .bp-member-preview-cover, 442 .bp-group-preview-cover { 443 position: relative; 444 min-height: 150px; 445 background: #c5c5c5; 446 447 img { 448 background: #c5c5c5; 449 object-fit: cover; 450 border: 0; 451 display: block; 452 margin: 0; 453 padding: 0; 454 width: 100%; 455 z-index: 1; 456 height: 150px; 457 } 458 } 459 460 .bp-member-avatar-content, 461 .bp-group-avatar-content { 462 float: left; 463 width: 120px; 464 position: relative; 465 z-index: 2; 466 467 img.profile-photo, 468 img.group-photo { 469 border: solid 2px #fff; 470 background: rgba(255, 255, 255, 0.8); 471 margin-left: 20px; 472 height: 80px; 473 width: 80px; 474 } 475 476 &.has-cover-image { 477 width: 200px; 478 margin-top: -75px; 479 480 img.profile-photo, 481 img.group-photo { 482 height: inherit; 483 width: inherit; 484 } 485 } 486 } 487 488 .bp-member-short-description-title a, 489 .bp-group-short-description-title a { 490 font-weight: 600; 491 } 492 493 @include medium-max() { 494 495 .bp-member-short-description, 496 .bp-group-short-description { 497 text-align: center; 498 } 499 500 .bp-member-avatar-content, 501 .bp-group-avatar-content { 502 float: none; 503 width: 100%; 504 margin-left: auto; 505 margin-right: auto; 506 margin-bottom: 15px; 507 508 img.profile-photo, 509 img.group-photo { 510 margin: auto; 511 } 512 } 513 514 .bp-profile-button { 515 margin-top: 15px; 516 } 517 518 } // close @media 519 520 @include medium-up { 521 522 .bp-profile-button { 523 text-align: right; 524 } 525 526 } // close @media -
src/bp-templates/bp-nouveau/css/buddypress-rtl.css
diff --git src/bp-templates/bp-nouveau/css/buddypress-rtl.css src/bp-templates/bp-nouveau/css/buddypress-rtl.css index e67c2b8f0..809cee962 100644
body.activity-permalink .activity-list .activity-comments { 1587 1587 } 1588 1588 } 1589 1589 1590 .bp-member-preview-cover, 1591 .bp-group-preview-cover { 1592 position: relative; 1593 min-height: 150px; 1594 background: #c5c5c5; 1595 } 1596 1597 .bp-member-preview-cover img, 1598 .bp-group-preview-cover img { 1599 background: #c5c5c5; 1600 -o-object-fit: cover; 1601 object-fit: cover; 1602 border: 0; 1603 display: block; 1604 margin: 0; 1605 padding: 0; 1606 width: 100%; 1607 z-index: 1; 1608 height: 150px; 1609 } 1610 1611 .bp-member-avatar-content, 1612 .bp-group-avatar-content { 1613 float: right; 1614 width: 120px; 1615 position: relative; 1616 z-index: 2; 1617 } 1618 1619 .bp-member-avatar-content img.profile-photo, 1620 .bp-member-avatar-content img.group-photo, 1621 .bp-group-avatar-content img.profile-photo, 1622 .bp-group-avatar-content img.group-photo { 1623 border: solid 2px #fff; 1624 background: rgba(255, 255, 255, 0.8); 1625 margin-right: 20px; 1626 height: 80px; 1627 width: 80px; 1628 } 1629 1630 .bp-member-avatar-content.has-cover-image, 1631 .bp-group-avatar-content.has-cover-image { 1632 width: 200px; 1633 margin-top: -75px; 1634 } 1635 1636 .bp-member-avatar-content.has-cover-image img.profile-photo, 1637 .bp-member-avatar-content.has-cover-image img.group-photo, 1638 .bp-group-avatar-content.has-cover-image img.profile-photo, 1639 .bp-group-avatar-content.has-cover-image img.group-photo { 1640 height: inherit; 1641 width: inherit; 1642 } 1643 1644 .bp-member-short-description-title a, 1645 .bp-group-short-description-title a { 1646 font-weight: 600; 1647 } 1648 1649 @media screen and (max-width: 46.8em) { 1650 .bp-member-short-description, 1651 .bp-group-short-description { 1652 text-align: center; 1653 } 1654 .bp-member-avatar-content, 1655 .bp-group-avatar-content { 1656 float: none; 1657 width: 100%; 1658 margin-right: auto; 1659 margin-left: auto; 1660 margin-bottom: 15px; 1661 } 1662 .bp-member-avatar-content img.profile-photo, 1663 .bp-member-avatar-content img.group-photo, 1664 .bp-group-avatar-content img.profile-photo, 1665 .bp-group-avatar-content img.group-photo { 1666 margin: auto; 1667 } 1668 .bp-profile-button { 1669 margin-top: 15px; 1670 } 1671 } 1672 1673 @media screen and (min-width: 46.8em) { 1674 .bp-profile-button { 1675 text-align: left; 1676 } 1677 } 1678 1590 1679 /** 1591 1680 *----------------------------------------------------- 1592 1681 * @section 3.1.3 - Activity Comments -
src/bp-templates/bp-nouveau/css/buddypress.css
diff --git src/bp-templates/bp-nouveau/css/buddypress.css src/bp-templates/bp-nouveau/css/buddypress.css index 526ff907e..31ae2f545 100644
body.activity-permalink .activity-list .activity-comments { 1587 1587 } 1588 1588 } 1589 1589 1590 .bp-member-preview-cover, 1591 .bp-group-preview-cover { 1592 position: relative; 1593 min-height: 150px; 1594 background: #c5c5c5; 1595 } 1596 1597 .bp-member-preview-cover img, 1598 .bp-group-preview-cover img { 1599 background: #c5c5c5; 1600 -o-object-fit: cover; 1601 object-fit: cover; 1602 border: 0; 1603 display: block; 1604 margin: 0; 1605 padding: 0; 1606 width: 100%; 1607 z-index: 1; 1608 height: 150px; 1609 } 1610 1611 .bp-member-avatar-content, 1612 .bp-group-avatar-content { 1613 float: left; 1614 width: 120px; 1615 position: relative; 1616 z-index: 2; 1617 } 1618 1619 .bp-member-avatar-content img.profile-photo, 1620 .bp-member-avatar-content img.group-photo, 1621 .bp-group-avatar-content img.profile-photo, 1622 .bp-group-avatar-content img.group-photo { 1623 border: solid 2px #fff; 1624 background: rgba(255, 255, 255, 0.8); 1625 margin-left: 20px; 1626 height: 80px; 1627 width: 80px; 1628 } 1629 1630 .bp-member-avatar-content.has-cover-image, 1631 .bp-group-avatar-content.has-cover-image { 1632 width: 200px; 1633 margin-top: -75px; 1634 } 1635 1636 .bp-member-avatar-content.has-cover-image img.profile-photo, 1637 .bp-member-avatar-content.has-cover-image img.group-photo, 1638 .bp-group-avatar-content.has-cover-image img.profile-photo, 1639 .bp-group-avatar-content.has-cover-image img.group-photo { 1640 height: inherit; 1641 width: inherit; 1642 } 1643 1644 .bp-member-short-description-title a, 1645 .bp-group-short-description-title a { 1646 font-weight: 600; 1647 } 1648 1649 @media screen and (max-width: 46.8em) { 1650 .bp-member-short-description, 1651 .bp-group-short-description { 1652 text-align: center; 1653 } 1654 .bp-member-avatar-content, 1655 .bp-group-avatar-content { 1656 float: none; 1657 width: 100%; 1658 margin-left: auto; 1659 margin-right: auto; 1660 margin-bottom: 15px; 1661 } 1662 .bp-member-avatar-content img.profile-photo, 1663 .bp-member-avatar-content img.group-photo, 1664 .bp-group-avatar-content img.profile-photo, 1665 .bp-group-avatar-content img.group-photo { 1666 margin: auto; 1667 } 1668 .bp-profile-button { 1669 margin-top: 15px; 1670 } 1671 } 1672 1673 @media screen and (min-width: 46.8em) { 1674 .bp-profile-button { 1675 text-align: right; 1676 } 1677 } 1678 1590 1679 /** 1591 1680 *----------------------------------------------------- 1592 1681 * @section 3.1.3 - Activity Comments -
new file tests/phpunit/testcases/core/attachments.php
diff --git tests/phpunit/testcases/core/attachments.php tests/phpunit/testcases/core/attachments.php new file mode 100644 index 000000000..4acbf496a
- + 1 <?php 2 3 /** 4 * @group core 5 */ 6 7 class BP_Tests_Core_Attachments extends BP_UnitTestCase { 8 /** 9 * @group bp_attachments_list_directory_files_recursively 10 */ 11 public function test_bp_attachments_list_directory_files_recursively() { 12 $files = bp_attachments_list_directory_files_recursively( BP_TESTS_DIR . 'assets', 'index' ); 13 14 $this->assertTrue( 1 === count( $files ) ); 15 $this->assertTrue( isset( $files['templates/index'] ) ); 16 } 17 } -
tests/phpunit/testcases/core/class-bp-attachment.php
diff --git tests/phpunit/testcases/core/class-bp-attachment.php tests/phpunit/testcases/core/class-bp-attachment.php index fae4e150d..6bb1c308b 100644
class BP_Tests_BP_Attachment_TestCases extends BP_UnitTestCase { 406 406 $this->clean_files( 'shrink' ); 407 407 } 408 408 409 /** 410 * @group add_revision 411 */ 412 public function test_bp_attachment_add_revision() { 413 if ( false === _wp_image_editor_choose() || version_compare( phpversion(), '7.0' , '<' ) ) { 414 $this->markTestSkipped( 'This test requires PHP >= 7.0 and to have a valid image editor that is compatible with WordPress.' ); 415 } 416 417 $image = BP_TESTS_DIR . 'assets/upside-down.jpg'; 418 419 $attachment = new BPTest_Attachment_Extension( 420 array( 421 'base_dir' => 'add_revision', 422 'action' => 'attachment_action', 423 'file_input' => 'attachment_file_input', 424 ) 425 ); 426 427 $abs_path_copy = $attachment->upload_path . '/upside-down.jpg'; 428 copy( $image, $abs_path_copy ); 429 430 $revision = $attachment->add_revision( 431 'media', 432 array( 433 'file_abspath' => $abs_path_copy, 434 'file_id' => 'media', 435 ) 436 ); 437 438 $this->assertFalse( file_exists( $abs_path_copy ) ); 439 $this->assertTrue( file_exists( $revision->path ) ); 440 441 // Cleanup 442 @unlink( $revision->path ); 443 @rmdir( dirname( $revision->path ) ); 444 $this->clean_files( 'add_revision' ); 445 } 446 447 /** 448 * @group add_revision 449 * @group avatars 450 */ 451 public function test_bp_attachment_add_avatar_history() { 452 if ( false === _wp_image_editor_choose() || version_compare( phpversion(), '7.0' , '<' ) ) { 453 $this->markTestSkipped( 'This test requires PHP >= 7.0 and to have a valid image editor that is compatible with WordPress.' ); 454 } 455 456 $image = BP_TESTS_DIR . 'assets/upside-down.jpg'; 457 458 $attachment = new BPTest_Attachment_Extension( 459 array( 460 'base_dir' => 'add_history', 461 'action' => 'attachment_action', 462 'file_input' => 'attachment_file_input', 463 ) 464 ); 465 466 $abs_path_copy = $attachment->upload_path . '/upside-down.jpg'; 467 copy( $image, $abs_path_copy ); 468 469 $revision = $attachment->add_revision( 470 'avatar', 471 array( 472 'file_abspath' => $abs_path_copy, 473 'file_id' => 'avatar', 474 ) 475 ); 476 477 $this->assertFalse( file_exists( $abs_path_copy ) ); 478 $this->assertTrue( file_exists( $revision->path ) ); 479 $this->assertSame( $attachment->url . '/history/upside-down.jpg', $revision->url ); 480 481 // Cleanup 482 @unlink( $revision->path ); 483 @rmdir( dirname( $revision->path ) ); 484 $this->clean_files( 'add_history' ); 485 } 486 409 487 public function limit_to_50px( $max_width ) { 410 488 return 50; 411 489 }