Skip to:
Content

BuddyPress.org

Ticket #6026: 6026.smaller-steps.all.02.patch

File 6026.smaller-steps.all.02.patch, 295.8 KB (added by imath, 3 years ago)
  • phpunit.xml.dist

    diff --git phpunit.xml.dist phpunit.xml.dist
    index 376a6c8..ef890b8 100644
     
    66        convertNoticesToExceptions="true"
    77        convertWarningsToExceptions="true"
    88        >
     9        <groups>
     10                <exclude>
     11                        <group>multisite</group>
     12                </exclude>
     13        </groups>
    914        <testsuites>
    1015                <testsuite>
    1116                        <directory suffix=".php">tests/phpunit/testcases/</directory>
  • src/bp-activity/bp-activity-template.php

    diff --git src/bp-activity/bp-activity-template.php src/bp-activity/bp-activity-template.php
    index c2d33b1..9d20cba 100644
    function bp_has_activities( $args = '' ) { 
    221221                $object      = $bp->groups->id;
    222222                $primary_id  = bp_get_current_group_id();
    223223                $show_hidden = (bool) ( groups_is_user_member( bp_loggedin_user_id(), $primary_id ) || bp_current_user_can( 'bp_moderate' ) );
     224        } elseif ( bp_is_site() ) {
     225                $object      = $bp->blogs->id;
     226                $primary_id  = bp_blogs_get_current_site_id();
     227                $show_hidden = false;
    224228        } else {
    225229                $object      = false;
    226230                $primary_id  = false;
    function bp_has_activities( $args = '' ) { 
    232236                ? $bp->loaded_components[ bp_current_action() ]
    233237                : bp_current_action();
    234238
     239        // Specific case for the sites subscriptions
     240        if ( 'blogs' === $scope && bp_is_user_blogs_activity() && bp_action_variable( 0 ) ) {
     241                $scope = 'site_' . sanitize_key( bp_action_variable( 0 ) );
     242        }
     243
    235244        // Support for permalinks on single item pages: /groups/my-group/activity/124/.
    236245        $include = bp_is_current_action( bp_get_activity_slug() )
    237246                ? bp_action_variable( 0 )
    function bp_activity_show_filters( $context = '' ) { 
    38003809                if ( empty( $context ) ) {
    38013810
    38023811                        // On member pages, default to 'member', unless this
    3803                         // is a user's Groups activity.
     3812                        // is a user's Groups or a user's Blogs activity.
    38043813                        if ( bp_is_user() ) {
     3814                                // Groups
    38053815                                if ( bp_is_active( 'groups' ) && bp_is_current_action( bp_get_groups_slug() ) ) {
    38063816                                        $context = 'member_groups';
     3817
     3818                                // Sites
     3819                                } elseif ( bp_is_active( 'blogs' ) && bp_is_current_action( bp_get_blogs_slug() ) ) {
     3820                                        $context = 'member_sites';
    38073821                                } else {
    38083822                                        $context = 'member';
    38093823                                }
    function bp_activity_show_filters( $context = '' ) { 
    38123826                        } elseif ( bp_is_active( 'groups' ) && bp_is_group() ) {
    38133827                                $context = 'group';
    38143828
     3829                        // On individual site pages, default to 'site'.
     3830                        } elseif ( bp_is_active( 'blogs', 'site' ) && bp_is_site() ) {
     3831                                $context = 'site';
     3832
    38153833                        // 'activity' everywhere else.
    38163834                        } else {
    38173835                                $context = 'activity';
  • src/bp-activity/classes/class-bp-activity-component.php

    diff --git src/bp-activity/classes/class-bp-activity-component.php src/bp-activity/classes/class-bp-activity-component.php
    index 4f85efb..52dd284 100644
    class BP_Activity_Component extends BP_Component { 
    233233                        );
    234234                }
    235235
     236                // Additional menu if blogs is active
     237                if ( is_multisite() && bp_is_active( 'blogs' ) ) {
     238                        $sub_nav[] = array(
     239                                'name'            => _x( 'Sites', 'Profile activity screen sub nav', 'buddypress' ),
     240                                'slug'            => bp_get_blogs_slug(),
     241                                'parent_url'      => $activity_link,
     242                                'parent_slug'     => $this->slug,
     243                                'screen_function' => 'bp_blogs_activity_screen',
     244                                'position'        => 60,
     245                                'item_css_id'     => 'activity-blogs'
     246                        );
     247                }
     248
    236249                parent::setup_nav( $main_nav, $sub_nav );
    237250        }
    238251
    class BP_Activity_Component extends BP_Component { 
    329342                                        'position' => 50
    330343                                );
    331344                        }
     345
     346                        // Blogs ?
     347                        if ( is_multisite() && bp_is_active( 'blogs' ) ) {
     348                                $wp_admin_nav[] = array(
     349                                        'parent' => 'my-account-' . $this->id,
     350                                        'id'     => 'my-account-' . $this->id . '-blogs',
     351                                        'title'  => _x( 'Sites', 'My Account Activity sub nav', 'buddypress' ),
     352                                        'href'   => trailingslashit( $activity_link . bp_get_blogs_slug() )
     353                                );
     354                        }
    332355                }
    333356
    334357                parent::setup_admin_bar( $wp_admin_nav );
  • src/bp-blogs/bp-blogs-activity.php

    diff --git src/bp-blogs/bp-blogs-activity.php src/bp-blogs/bp-blogs-activity.php
    index 5c91e83..502f138 100644
    function bp_blogs_register_activity_actions() { 
    2525                        __( 'New site created', 'buddypress' ),
    2626                        'bp_blogs_format_activity_action_new_blog',
    2727                        __( 'New Sites', 'buddypress' ),
    28                         array( 'activity', 'member' ),
     28                        array( 'activity', 'member', 'site', 'member_sites' ),
    2929                        0
    3030                );
    3131        }
    function bp_blogs_register_post_tracking_args( $params = null, $post_type = 0 ) 
    7777        $params->admin_filter    = __( 'New post published', 'buddypress' );
    7878        $params->format_callback = 'bp_blogs_format_activity_action_new_blog_post';
    7979        $params->front_filter    = __( 'Posts', 'buddypress' );
    80         $params->contexts        = array( 'activity', 'member' );
     80        $params->contexts        = array( 'activity', 'member', 'site', 'member_sites' );
    8181        $params->position        = 5;
    8282
    8383        if ( post_type_supports( $post_type, 'comments' ) ) {
    function bp_blogs_register_post_tracking_args( $params = null, $post_type = 0 ) 
    105105                        $params->comments_tracking->admin_filter    = __( 'New post comment posted', 'buddypress' );
    106106                        $params->comments_tracking->format_callback = 'bp_blogs_format_activity_action_new_blog_comment';
    107107                        $params->comments_tracking->front_filter    = __( 'Comments', 'buddypress' );
    108                         $params->comments_tracking->contexts        = array( 'activity', 'member' );
     108                        $params->comments_tracking->contexts        = array( 'activity', 'member', 'site', 'member_sites' );
    109109                        $params->comments_tracking->position        = 10;
    110110                }
    111111        }
    function bp_blogs_activity_comment_single_action( $retval, $activity ) { 
    14351435        return $retval;
    14361436}
    14371437add_filter( 'bp_get_activity_action_pre_meta', 'bp_blogs_activity_comment_single_action', 10, 2 );
     1438
     1439/**
     1440 * Set up activity arguments to use for the 'blogs' scope.
     1441 *
     1442 * @since 2.7.0
     1443 *
     1444 * @param array $retval Empty array by default
     1445 * @param array $filter Current activity arguments
     1446 * @return array
     1447 */
     1448function bp_blogs_blog_activity_scope( $retval = array(), $filter = array() ) {
     1449
     1450        // Determine the user_id
     1451        if ( ! empty( $filter['user_id'] ) ) {
     1452                $user_id = $filter['user_id'];
     1453        } else {
     1454                $user_id = bp_displayed_user_id()
     1455                        ? bp_displayed_user_id()
     1456                        : bp_loggedin_user_id();
     1457        }
     1458
     1459        // Determine blogs of user
     1460        $is_contributor = 1;
     1461        if ( 'site_subscriptions' === $filter['scope'] ) {
     1462                $is_contributor = 0;
     1463        }
     1464
     1465        $blogs = bp_blogs_get_blogs_for_user( $user_id, false, $is_contributor );
     1466
     1467        if ( empty( $blogs['blogs'] ) ) {
     1468                $blogs = array( 'blogs' => 0 );
     1469        } else {
     1470                $blogs['blogs'] = array_keys( $blogs['blogs'] );
     1471        }
     1472
     1473        // Should we show all items regardless of sitewide visibility?
     1474        $show_hidden = array();
     1475        if ( ! empty( $user_id ) && ( $user_id !== bp_loggedin_user_id() ) ) {
     1476                $show_hidden = array(
     1477                        'column' => 'hide_sitewide',
     1478                        'value'  => 0
     1479                );
     1480        }
     1481
     1482        $retval = array(
     1483                'relation' => 'AND',
     1484                array(
     1485                        'relation' => 'AND',
     1486                        array(
     1487                                'column' => 'component',
     1488                                'value'  => buddypress()->blogs->id
     1489                        ),
     1490                        array(
     1491                                'column'  => 'item_id',
     1492                                'compare' => 'IN',
     1493                                'value'   => (array) $blogs['blogs']
     1494                        ),
     1495                ),
     1496                $show_hidden,
     1497
     1498                // overrides
     1499                'override' => array(
     1500                        'filter'      => array( 'user_id' => 0 ),
     1501                        'show_hidden' => true
     1502                ),
     1503        );
     1504
     1505        return $retval;
     1506}
     1507add_filter( 'bp_activity_set_blogs_scope_args',              'bp_blogs_blog_activity_scope', 10, 2 );
     1508add_filter( 'bp_activity_set_site_subscriptions_scope_args', 'bp_blogs_blog_activity_scope', 10, 2 );
  • src/bp-blogs/bp-blogs-cache.php

    diff --git src/bp-blogs/bp-blogs-cache.php src/bp-blogs/bp-blogs-cache.php
    index 19e3391..8510497 100644
    function bp_blogs_update_meta_cache( $blog_ids = false ) { 
    4444 */
    4545function bp_blogs_clear_blog_object_cache( $blog_id = 0, $user_id = 0 ) {
    4646        if ( ! empty( $user_id ) ) {
    47                 wp_cache_delete( 'bp_blogs_of_user_'        . $user_id, 'bp' );
    48                 wp_cache_delete( 'bp_total_blogs_for_user_' . $user_id, 'bp' );
     47                wp_cache_delete( 'bp_blogs_of_user_'                     . $user_id, 'bp' );
     48                wp_cache_delete( 'bp_total_blogs_for_user_'              . $user_id, 'bp' );
     49                wp_cache_delete( 'bp_total_site_subscriptions_for_user_' . $user_id, 'bp' );
    4950        }
    5051
    5152        wp_cache_delete( 'bp_total_blogs', 'bp' );
  • src/bp-blogs/bp-blogs-classes.php

    diff --git src/bp-blogs/bp-blogs-classes.php src/bp-blogs/bp-blogs-classes.php
    index 49c55dc..30ffee4 100644
     
    1111defined( 'ABSPATH' ) || exit;
    1212
    1313require dirname( __FILE__ ) . '/classes/class-bp-blogs-blog.php';
     14
     15if ( function_exists( 'get_sites' ) ) {
     16        require dirname( __FILE__ ) . '/classes/class-bp-site-query.php';
     17}
  • src/bp-blogs/bp-blogs-filters.php

    diff --git src/bp-blogs/bp-blogs-filters.php src/bp-blogs/bp-blogs-filters.php
    index 1d0d71b..3de98b6 100644
    function bp_blogs_post_pre_publish( $return = true, $blog_id = 0, $post_id = 0, 
    121121}
    122122add_filter( 'bp_activity_post_pre_publish', 'bp_blogs_post_pre_publish', 10, 4 );
    123123add_filter( 'bp_activity_post_pre_comment', 'bp_blogs_post_pre_publish', 10, 4 );
     124
     125/**
     126 * Use the mystery site avatar for sites.
     127 *
     128 * @since 2.7.0
     129 *
     130 * @param string $avatar Current avatar src.
     131 * @param array  $params Avatar params.
     132 * @return string
     133 */
     134function bp_blogs_default_avatar( $avatar, $params ) {
     135        if ( isset( $params['object'] ) && 'blog' === $params['object'] ) {
     136                $avatar = buddypress()->plugin_url . "bp-core/images/mystery-site.svg";
     137        }
     138
     139        return $avatar;
     140}
     141add_filter( 'bp_core_avatar_default',       'bp_blogs_default_avatar', 10, 3 );
     142add_filter( 'bp_core_avatar_default_thumb', 'bp_blogs_default_avatar', 10, 3 );
     143
     144/**
     145 * Triggers to add filters to get_blogs_of_user
     146 *
     147 * @since  2.7.0
     148 */
     149function bp_blogs_get_blogs_of_user_add_filters() {
     150        add_filter( 'pre_get_blogs_of_user', 'bp_blogs_get_sites_of_user', 10, 2 );
     151        add_filter( 'get_blogs_of_user',     'bp_blogs_get_sites_of_user', 10, 2 );
     152}
     153
     154/**
     155 * Triggers to remove filters to get_blogs_of_user
     156 *
     157 * @since  2.7.0
     158 */
     159function bp_blogs_get_blogs_of_user_remove_filters() {
     160        remove_filter( 'pre_get_blogs_of_user', 'bp_blogs_get_sites_of_user', 10, 2 );
     161        remove_filter( 'get_blogs_of_user',     'bp_blogs_get_sites_of_user', 10, 2 );
     162}
  • src/bp-blogs/bp-blogs-functions.php

    diff --git src/bp-blogs/bp-blogs-functions.php src/bp-blogs/bp-blogs-functions.php
    index a9895e7..7ebb564 100644
    function bp_blogs_has_directory() { 
    3838 *     @type int         $per_page          Default: 20.
    3939 *     @type int         $page              Default: 1.
    4040 *     @type bool        $update_meta_cache Whether to pre-fetch blogmeta. Default: true.
     41 *     @type int         $is_contributor    Whether to get sites user is at least a contributor (1)
     42 *                                          or the sites he subscribed to (0). Default: 1.
    4143 * }
    4244 * @return array See {@link BP_Blogs_Blog::get()}.
    4345 */
    function bp_blogs_get_blogs( $args = '' ) { 
    5153                'search_terms'      => false,    // Limit to blogs matching these search terms
    5254                'per_page'          => 20,       // The number of results to return per page
    5355                'page'              => 1,        // The page to return if limiting per page
    54                 'update_meta_cache' => true      // Whether to pre-fetch blogmeta
     56                'update_meta_cache' => true,     // Whether to pre-fetch blogmeta,
     57                'is_contributor'    => 1,
    5558        ), 'blogs_get_blogs' );
    5659
    5760        // Get the blogs.
    function bp_blogs_get_blogs( $args = '' ) { 
    6265                $r['user_id'],
    6366                $r['search_terms'],
    6467                $r['update_meta_cache'],
    65                 $r['include_blog_ids']
     68                $r['include_blog_ids'],
     69                $r['is_contributor']
    6670        );
    6771
    6872        // Filter and return.
    function bp_blogs_is_blog_trackable( $blog_id, $user_id = 0 ) { 
    303307 */
    304308function bp_blogs_record_blog( $blog_id, $user_id, $no_activity = false ) {
    305309
    306         if ( empty( $user_id ) )
     310        if ( empty( $user_id ) ) {
    307311                $user_id = bp_loggedin_user_id();
     312        }
    308313
    309314        // If blog is not recordable, do not record the activity.
    310         if ( !bp_blogs_is_blog_recordable( $blog_id, $user_id ) )
     315        if ( ! bp_blogs_is_blog_recordable( $blog_id, $user_id ) ) {
    311316                return false;
     317        }
    312318
    313319        $name = get_blog_option( $blog_id, 'blogname' );
    314320        $url  = get_home_url( $blog_id );
    function bp_blogs_record_blog( $blog_id, $user_id, $no_activity = false ) { 
    329335                $thread_depth = 1;
    330336        }
    331337
    332         $recorded_blog          = new BP_Blogs_Blog;
     338        $recorded_blog          = new BP_Blogs_Blog( null, $user_id, $blog_id );
    333339        $recorded_blog->user_id = $user_id;
    334340        $recorded_blog->blog_id = $blog_id;
    335         $recorded_blog_id       = $recorded_blog->save();
    336         $is_recorded            = !empty( $recorded_blog_id ) ? true : false;
     341
     342        // The user is a contributor.
     343        if ( bp_user_can( $user_id, 'edit_posts', array( 'site_id' => $blog_id ) ) ) {
     344                $recorded_blog->is_contributor = 1;
     345
     346        // The user is a subscriber.
     347        } else {
     348                $recorded_blog->is_contributor = 0;
     349        }
     350
     351        $recorded_blog_id = $recorded_blog->save();
     352        $is_recorded      = false;
     353
     354        if ( ! empty( $recorded_blog_id ) ) {
     355                $is_recorded = true;
     356        }
    337357
    338358        bp_blogs_update_blogmeta( $recorded_blog->blog_id, 'url', $url );
    339359        bp_blogs_update_blogmeta( $recorded_blog->blog_id, 'name', $name );
    function bp_blogs_record_blog( $blog_id, $user_id, $no_activity = false ) { 
    343363        bp_blogs_update_blogmeta( $recorded_blog->blog_id, 'close_comments_days_old', $close_days_old );
    344364        bp_blogs_update_blogmeta( $recorded_blog->blog_id, 'thread_comments_depth', $thread_depth );
    345365
    346         $is_private = !empty( $_POST['blog_public'] ) && (int) $_POST['blog_public'] ? false : true;
    347         $is_private = !apply_filters( 'bp_is_new_blog_public', !$is_private );
     366        // Get site admins
     367        $site_admins = bp_blogs_get_blogmeta( $recorded_blog->blog_id, 'site_admins' );
     368        if ( empty( $site_admins ) && ! is_array( $site_admins ) ) {
     369                $site_admins = array();
     370        }
     371
     372        // Eventually Add the user to site admins.
     373        if ( bp_user_can( $user_id, 'manage_options', array( 'site_id' => $recorded_blog->blog_id ) ) ) {
     374                if ( empty( $site_admins ) ) {
     375                        bp_blogs_update_blogmeta( $recorded_blog->blog_id, 'site_admins', array( (int) $user_id ) );
     376                } else {
     377                        $site_admins[] = (int) $user_id;
     378                        bp_blogs_update_blogmeta( $recorded_blog->blog_id, 'site_admins', wp_parse_id_list( $site_admins ) );
     379                }
     380
     381        // If the user was an admin and no more is, remove it from site admins.
     382        } else {
     383                $was_admin = array_search( $user_id, $site_admins );
     384
     385                if ( false !== $was_admin ) {
     386                        unset( $site_admins[ $was_admin ] );
     387                        bp_blogs_update_blogmeta( $recorded_blog->blog_id, 'site_admins', $site_admins );
     388                }
     389        }
     390
     391        $is_private = true;
     392        if ( ! empty( $_POST['blog_public'] ) && (int) $_POST['blog_public'] ) {
     393                $is_private = false;
     394        }
     395
     396        $is_private = ! apply_filters( 'bp_is_new_blog_public', ! $is_private );
    348397
    349398        /**
    350399         * Fires after BuddyPress has been made aware of a new site for activity tracking.
    add_action( 'bp_activity_post_type_comment', 'bp_blogs_comment_sync_activity_com 
    769818function bp_blogs_add_user_to_blog( $user_id, $role = false, $blog_id = 0 ) {
    770819        global $wpdb;
    771820
     821        /**
     822         * WordPress is removing the user from the main blog just after
     823         * creating it on it. So we need to do the same with blog association.
     824         */
     825        if ( doing_action( 'wpmu_new_user' ) ) {
     826                BP_Blogs_Blog::delete_blog_for_user( get_current_site()->blog_id, $user_id );
     827
     828                // No need to carry on.
     829                return false;
     830        }
     831
    772832        // If no blog ID was passed, use the root blog ID.
    773833        if ( empty( $blog_id ) ) {
    774834                $blog_id = isset( $wpdb->blogid ) ? $wpdb->blogid : bp_get_root_blog_id();
    function bp_blogs_add_user_to_blog( $user_id, $role = false, $blog_id = 0 ) { 
    800860                }
    801861        }
    802862
    803         // Bail if no role was found or role is not in the allowed roles array.
    804         if ( empty( $role ) || ! in_array( $role, bp_blogs_get_allowed_roles() ) ) {
     863        // Bail if no role was found.
     864        if ( empty( $role ) ) {
     865                return false;
     866        }
     867
     868        // Bail if role is not in the allowed roles array.
     869        if ( ! in_array( $role, bp_blogs_get_allowed_roles() ) ) {
     870                $user_blog_association = new BP_Blogs_Blog( null, $user_id, $blog_id );
     871
     872                // If the user is associated to the blog remove him.
     873                if ( ! empty( $user_blog_association->id ) ) {
     874                        $user_blog_association::delete_blog_for_user( $blog_id, $user_id );
     875                }
     876
    805877                return false;
    806878        }
    807879
    808880        // Record the blog activity for this user being added to this blog.
    809881        bp_blogs_record_blog( $blog_id, $user_id, true );
    810882}
    811 add_action( 'add_user_to_blog', 'bp_blogs_add_user_to_blog', 10, 3 );
    812 add_action( 'profile_update',   'bp_blogs_add_user_to_blog'        );
    813 add_action( 'user_register',    'bp_blogs_add_user_to_blog'        );
     883add_action( 'set_user_role', 'bp_blogs_add_user_to_blog', 10, 2 );
     884add_action( 'wpmu_new_user', 'bp_blogs_add_user_to_blog', 10, 1 );
    814885
    815886/**
    816887 * The allowed blog roles a member must have to be recorded into the
    add_action( 'user_register', 'bp_blogs_add_user_to_blog' ); 
    820891 * to extend the functionality of the Blogs component.
    821892 *
    822893 * @since 2.1.0
     894 * @since 2.7.0 Add the subscriber role to the list of allowed roles if front-end subscriptions are enabled.
    823895 *
    824  * @return string
     896 * @return array The list of allowed blog roles.
    825897 */
    826898function bp_blogs_get_allowed_roles() {
    827         return apply_filters( 'bp_blogs_get_allowed_roles', array( 'contributor', 'author', 'editor', 'administrator' ) );
     899        /**
     900         * NB: All roles except the subcriber one will be saved into the User to blog association as contributors.
     901         * (the is_contributor field of the buddypress()->blogs->table_name_blogmeta will be set to 1)
     902         */
     903        $allowed_roles = array( 'contributor', 'author', 'editor', 'administrator' );
     904
     905        // If front-end subscriptions are not disabled, add the subsciber role.
     906        if ( ! bp_disable_site_subscriptions() ) {
     907                array_unshift( $allowed_roles, 'subscriber' );
     908        }
     909
     910        return apply_filters( 'bp_blogs_get_allowed_roles', $allowed_roles );
    828911}
    829912
    830913/**
    function bp_blogs_total_blogs() { 
    10641147 * Get the total number of blogs being tracked by BP for a specific user.
    10651148 *
    10661149 * @since 1.2.0
     1150 * @since 2.7.0 Now this function also gets/caches the site subscriptions count.
     1151 *              Adds the $is_contributor parameter.
    10671152 *
    10681153 * @param int $user_id ID of the user being queried. Default: on a user page,
    10691154 *                     the displayed user. Otherwise, the logged-in user.
    10701155 * @return int $count Total blog count for the user.
    10711156 */
    1072 function bp_blogs_total_blogs_for_user( $user_id = 0 ) {
     1157function bp_blogs_total_blogs_for_user( $user_id = 0, $is_contributor = 1 ) {
    10731158        if ( empty( $user_id ) ) {
    10741159                $user_id = ( bp_displayed_user_id() ) ? bp_displayed_user_id() : bp_loggedin_user_id();
    10751160        }
    function bp_blogs_total_blogs_for_user( $user_id = 0 ) { 
    10791164                return 0;
    10801165        }
    10811166
    1082         $count = wp_cache_get( 'bp_total_blogs_for_user_' . $user_id, 'bp' );
     1167        $cache = 'bp_total_blogs_for_user_' . $user_id;
     1168        if ( 0 === $is_contributor ) {
     1169                $cache = 'bp_total_site_subscriptions_for_user_' . $user_id;
     1170        }
     1171
     1172        $count = wp_cache_get( $cache, 'bp' );
    10831173        if ( false === $count ) {
    1084                 $count = BP_Blogs_Blog::total_blog_count_for_user( $user_id );
    1085                 wp_cache_set( 'bp_total_blogs_for_user_' . $user_id, $count, 'bp' );
     1174                $count = BP_Blogs_Blog::total_blog_count_for_user( $user_id, $is_contributor );
     1175                wp_cache_set( $cache, $count, 'bp' );
    10861176        }
    10871177
    10881178        return $count;
    add_action( 'delete_blog', 'bp_blogs_remove_data_for_blog', 1 ); 
    11261216 * @see BP_Blogs_Blog::get_blogs_for_user() for a description of parameters
    11271217 *      and return values.
    11281218 *
    1129  * @param int  $user_id     See {@BP_Blogs_Blog::get_blogs_for_user()}.
    1130  * @param bool $show_hidden See {@BP_Blogs_Blog::get_blogs_for_user()}.
     1219 * @since  2.7.0 Adds the $is_contributor parameter.
     1220 *
     1221 * @param int      $user_id        See {@BP_Blogs_Blog::get_blogs_for_user()}.
     1222 * @param bool     $show_hidden    See {@BP_Blogs_Blog::get_blogs_for_user()}.
     1223 * @param int|null $is_contributor See {@BP_Blogs_Blog::get_blogs_for_user()}.
    11311224 * @return array See {@BP_Blogs_Blog::get_blogs_for_user()}.
    11321225 */
    1133 function bp_blogs_get_blogs_for_user( $user_id, $show_hidden = false ) {
    1134         return BP_Blogs_Blog::get_blogs_for_user( $user_id, $show_hidden );
     1226function bp_blogs_get_blogs_for_user( $user_id, $show_hidden = false, $is_contributor = 1 ) {
     1227        return BP_Blogs_Blog::get_blogs_for_user( $user_id, $show_hidden, $is_contributor );
    11351228}
    11361229
    11371230/**
    function bp_blogs_restore_data( $user_id = 0 ) { 
    13481441        }
    13491442}
    13501443add_action( 'bp_make_ham_user', 'bp_blogs_restore_data', 10, 1 );
     1444
     1445/**
     1446 * Checks if we safely use sites subscriptions.
     1447 *
     1448 * @since  2.7.0
     1449 *
     1450 * @return bool True if Site subscriptions are active. False otherwise.
     1451 */
     1452function bp_blogs_is_site_subscriptions_active() {
     1453        return bp_is_active( 'blogs', 'site' ) && ! bp_disable_site_subscriptions();
     1454}
     1455
     1456/**
     1457 * This function is used to "replace" `get_blogs_of_user` when WordPress
     1458 * or BuddyPress are spamming users.
     1459 *
     1460 * This is making sure that if a subscriber is spammed, it won't spam all the sites
     1461 * he subscribed to!
     1462 *
     1463 * @since  2.7.0
     1464 *
     1465 * @param  array  $args {
     1466 *     Array of arguments. Accepts all arguments accepted by
     1467 *     {@link get_blogs_of_user()}. In cases function were used
     1468 *     to filter it before or after.
     1469 * }
     1470 * @return array  The list of sites the user can at least contribute to.
     1471 */
     1472function bp_blogs_get_sites_of_user( $args = array() ) {
     1473        /**
     1474         * Default user id is the displayed one, as it's possible
     1475         * to spam a user on his Profile page in BuddyPress.
     1476         */
     1477        $user_id = bp_displayed_user_id();
     1478
     1479        // Defaults to an empty array.
     1480        $sites   = array();
     1481
     1482        /**
     1483         * This function can be used to filter `pre_get_blogs_of_user`
     1484         * or `get_blogs_of_user`
     1485         */
     1486        if ( 2 === func_num_args() ) {
     1487                list( $sites, $user_id ) = func_get_args();
     1488
     1489                if ( 'get_blogs_of_user' === current_filter() ) {
     1490                        /**
     1491                         * The `pre_get_blogs_of_user` can be used as WordPress is 4.6
     1492                         * so the Blogs will already be the one the users is contributing
     1493                         * to. For WordPress < 4.6, we need remove the blogs the user has
     1494                         * subscribed to
     1495                         */
     1496                        if ( ! function_exists( 'get_sites' ) ) {
     1497                                $s_sites = BP_Blogs_Blog::get_blog_ids_for_user( $user_id, 0 );
     1498
     1499                                foreach ( $s_sites as $s_site_id ) {
     1500                                        unset( $sites[ $s_site_id ] );
     1501                                }
     1502                        }
     1503
     1504                        return $sites;
     1505                }
     1506        }
     1507
     1508        /**
     1509         * Default arguments are making sure only the sites
     1510         * the user is at least a contributor of will be returned.
     1511         */
     1512        $r = bp_parse_args( $args, array(
     1513                'user_id'          => $user_id,
     1514                'is_contributor'   => 1,
     1515                'skip_latest_post' => true,
     1516        ), 'get_sites_of_user' );
     1517
     1518        // The user id is required.
     1519        if ( empty( $r['user_id'] ) ) {
     1520                return $sites;
     1521        }
     1522
     1523        $q_sites = new BP_Site_Query( $r );
     1524
     1525        $r_sites = $q_sites->get_results();
     1526
     1527        if ( ! empty( $r_sites['blogs'] ) ) {
     1528                foreach ( $r_sites['blogs'] as $site ) {
     1529                        $sites[ $site->blog_id ] = (object) array(
     1530                                'userblog_id' => (int) $site->blog_id,
     1531                                'blogname'    => $site->name,
     1532                                'domain'      => $site->domain,
     1533                                'path'        => $site->path,
     1534                                'site_id'     => $site->site_id,
     1535                                'siteurl'     => $site->url,
     1536                                'archived'    => $site->archived,
     1537                                'mature'      => $site->mature,
     1538                                'spam'        => $site->spam,
     1539                                'deleted'     => $site->deleted,
     1540                        );
     1541                }
     1542        } elseif ( is_null( $sites ) ) {
     1543                $sites = array();
     1544        }
     1545
     1546        /**
     1547         * Filter here to edit the sites of the user.
     1548         *
     1549         * @since  2.7.0
     1550         *
     1551         * @param  array $sites An array of Site objects.
     1552         * @param  array $r     The merged arguments.
     1553         * @param  array $args  The requested arguments.
     1554         */
     1555        return apply_filters( 'bp_blogs_get_sites_of_user', $sites, $r, $args );
     1556}
  • src/bp-blogs/bp-blogs-screens.php

    diff --git src/bp-blogs/bp-blogs-screens.php src/bp-blogs/bp-blogs-screens.php
    index 371f401..bc2d8a3 100644
    function bp_blogs_screen_index() { 
    7272}
    7373add_action( 'bp_screens', 'bp_blogs_screen_index', 2 );
    7474
     75/**
     76 * Load the User's activity page.
     77 *
     78 * @since 2.7.0
     79 */
     80function bp_blogs_activity_screen() {
     81        bp_update_is_item_admin( bp_current_user_can( 'bp_moderate' ), 'activity' );
     82
     83        /**
     84         * Fires right before the loading of the "My Sites" activities screen template file.
     85         *
     86         * @since 2.7.0
     87         */
     88        do_action( 'bp_blogs_activity_screen' );
     89
     90        /**
     91         * Filters the template to load for the "My Sites"  activities screen.
     92         *
     93         * @since 2.7.0
     94         *
     95         * @param string $template Path to the activity template to load.
     96         */
     97        bp_core_load_template( apply_filters( 'bp_blogs_activity_screen_template', 'members/single/home' ) );
     98}
     99
    75100/** Theme Compatibility *******************************************************/
    76101
    77102new BP_Blogs_Theme_Compat();
  • src/bp-blogs/bp-blogs-site.php

    diff --git src/bp-blogs/bp-blogs-site.php src/bp-blogs/bp-blogs-site.php
    index e69de29..e6250e7 100644
     
     1<?php
     2/**
     3 * BuddyPress Blogs Site.
     4 *
     5 * @package BuddyPress
     6 * @subpackage BlogsSite
     7 * @since 2.7.0
     8 */
     9
     10// Exit if accessed directly.
     11defined( 'ABSPATH' ) || exit;
     12
     13require dirname( __FILE__ ) . '/site/functions.php';
     14require dirname( __FILE__ ) . '/site/screens.php';
     15require dirname( __FILE__ ) . '/site/template.php';
     16require dirname( __FILE__ ) . '/site/adminbar.php';
     17require dirname( __FILE__ ) . '/site/filters.php';
     18require dirname( __FILE__ ) . '/site/cache.php';
     19
     20if ( bp_is_active( 'activity' ) ) {
     21        require dirname( __FILE__ ) . '/site/activity.php';
     22}
     23
     24if ( bp_is_active( 'notifications' ) ) {
     25        require dirname( __FILE__ ) . '/site/notifications.php';
     26}
     27
     28if ( ! bp_disable_site_subscriptions() ) {
     29        require dirname( __FILE__ ) . '/site/subscriptions.php';
     30}
  • src/bp-blogs/bp-blogs-template.php

    diff --git src/bp-blogs/bp-blogs-template.php src/bp-blogs/bp-blogs-template.php
    index cbe37ed..af8e453 100644
    function bp_rewind_blogs() { 
    143143 *     @type int      $user_id          The ID of the user whose blogs should be retrieved.
    144144 *                                      When viewing a user profile page, 'user_id' defaults to the
    145145 *                                      ID of the displayed user. Otherwise the default is false.
     146 *     @type int      $is_contributor   Whether to get sites user is at least a contributor (1)
     147 *                                      or the sites he subscribed to (0). Default: 1.
    146148 * }
    147149 * @return bool Returns true when blogs are found, otherwise false.
    148150 */
    149151function bp_has_blogs( $args = '' ) {
    150152        global $blogs_template;
    151153
     154        $is_contributor = 1;
     155        if ( bp_is_active( 'blogs', 'site' ) && bp_is_user() && bp_is_current_action( 'my-subscriptions' ) ) {
     156                $is_contributor = 0;
     157        }
     158
    152159        // Check for and use search terms.
    153160        $search_terms_default = false;
    154161        $search_query_arg = bp_core_get_component_search_query_arg( 'blogs' );
    function bp_has_blogs( $args = '' ) { 
    168175                'user_id'           => bp_displayed_user_id(), // Pass a user_id to limit to only blogs this user is a member of.
    169176                'include_blog_ids'  => false,
    170177                'search_terms'      => $search_terms_default,
    171                 'update_meta_cache' => true
     178                'update_meta_cache' => true,
     179                'is_contributor'    => $is_contributor,
    172180        ), 'has_blogs' );
    173181
    174182        // Set per_page to maximum if max is enforced.
    function bp_has_blogs( $args = '' ) { 
    177185        }
    178186
    179187        // Get the blogs.
    180         $blogs_template = new BP_Blogs_Template( $r['type'], $r['page'], $r['per_page'], $r['max'], $r['user_id'], $r['search_terms'], $r['page_arg'], $r['update_meta_cache'], $r['include_blog_ids'] );
     188        $blogs_template = new BP_Blogs_Template( $r['type'], $r['page'], $r['per_page'], $r['max'], $r['user_id'], $r['search_terms'], $r['page_arg'], $r['update_meta_cache'], $r['include_blog_ids'], $r['is_contributor'] );
    181189
    182190        /**
    183191         * Filters whether or not there are blogs to list.
    function bp_blogs_pagination_links() { 
    287295        }
    288296
    289297/**
     298 * Returns the Site's avatar.
     299 *
     300 * @since  2.7.0
     301 *
     302 * @param array|string $args  {
     303 *     For more information about the arguments, see
     304 *     {@link bp_core_fetch_avatar()}.
     305 * }
     306 * @return string HTML output for the site's avatar.
     307 */
     308function bp_blogs_get_site_avatar( $args = array() ) {
     309        $r = wp_parse_args( $args, array(
     310                'item_id'    => 0,
     311                'title'      => '',
     312                'avatar_dir' => 'blog-avatars',
     313                'object'     => 'blog',
     314                'type'       => 'full',
     315                'alt'        => __( 'Site Photo', 'buddypress' ),
     316                'css_id'     => 0,
     317                'class'      => 'avatar site-avatar',
     318                'width'      => false,
     319                'height'     => false,
     320                'site_name'  => '',
     321        ) );
     322
     323        if ( ! empty( $r['site_name'] ) ) {
     324                $r['alt']   = sprintf( __( 'Site Photo of %s', 'buddypress' ), $r['site_name'] );
     325
     326                // Only replace the title if not set.
     327                if ( ! $r['title'] ) {
     328                        $r['title'] = $r['alt'];
     329                }
     330
     331                unset( $r['site_name'] );
     332
     333        // Only set the default title if not already set.
     334        } elseif ( ! $r['title'] ) {
     335                $r['title'] = __( 'Site Photo', 'buddypress' );
     336        }
     337
     338        return bp_core_fetch_avatar( $r );
     339}
     340
     341/**
    290342 * Output a blog's avatar.
    291343 *
    292344 * @see bp_get_blog_avatar() for description of arguments.
    function bp_blog_avatar( $args = '' ) { 
    299351        /**
    300352         * Get a blog's avatar.
    301353         *
    302          * At the moment, blog avatars are simply the user avatars of the blog
    303          * admin. Filter 'bp_get_blog_avatar_' . $blog_id to customize.
    304          *
    305354         * @since 2.4.0 Introduced `$title` argument.
    306355         *
    307356         * @see bp_core_fetch_avatar() For a description of arguments and
    308357         *      return values.
    309358         *
    310359         * @param array|string $args  {
    311          *     Arguments are listed here with an explanation of their defaults.
    312360         *     For more information about the arguments, see
    313361         *     {@link bp_core_fetch_avatar()}.
    314          *     @type string   $alt     Default: 'Profile picture of site author [user name]'.
    315          *     @type string   $class   Default: 'avatar'.
    316          *     @type string   $title   Default: 'Profile picture of site author [user name]'.
    317          *     @type string   $type    Default: 'full'.
    318          *     @type int|bool $width   Default: false.
    319          *     @type int|bool $height  Default: false.
    320          *     @type bool     $id      Currently unused.
    321          *     @type bool     $no_grav Default: true.
    322362         * }
    323          * @return string User avatar string.
     363         * @return string Site avatar string.
    324364         */
    325365        function bp_get_blog_avatar( $args = '' ) {
    326366                global $blogs_template;
    function bp_blog_avatar( $args = '' ) { 
    331371                        return false;
    332372                }
    333373
    334                 $author_displayname = bp_core_get_user_displayname( $blogs_template->blog->admin_user_id );
    335 
    336374                // Parse the arguments.
    337375                $r = bp_parse_args( $args, array(
    338                         'type'    => 'full',
    339                         'width'   => false,
    340                         'height'  => false,
    341                         'class'   => 'avatar',
    342                         'title'   => sprintf( __( 'Profile picture of site author %s', 'buddypress' ), esc_attr( $author_displayname ) ),
    343                         'id'      => false,
    344                         'alt'     => sprintf( __( 'Profile picture of site author %s', 'buddypress' ), esc_attr( $author_displayname ) ),
    345                         'no_grav' => true,
    346                 ) );
     376                        'item_id'   => $blogs_template->blog->blog_id,
     377                        'type'      => 'thumb',
     378                        'site_name' => esc_attr( bp_get_blog_name() ),
     379                        'title'     => '',
     380                ), 'get_blog_avatar' );
    347381
    348382                // Fetch the avatar.
    349                 $avatar = bp_core_fetch_avatar( array(
    350                         'item_id'    => $blogs_template->blog->admin_user_id,
    351                         'title'      => $r['title'],
    352                         // 'avatar_dir' => 'blog-avatars',
    353                         // 'object'     => 'blog',
    354                         'type'       => $r['type'],
    355                         'alt'        => $r['alt'],
    356                         'css_id'     => $r['id'],
    357                         'class'      => $r['class'],
    358                         'width'      => $r['width'],
    359                         'height'     => $r['height']
    360                 ) );
    361 
    362                 /**
    363                  * In future BuddyPress versions you will be able to set the avatar for a blog.
    364                  * Right now you can use a filter with the ID of the blog to change it if you wish.
    365                  * By default it will return the avatar for the primary blog admin.
    366                  *
    367                  * This filter is deprecated as of BuddyPress 1.5 and may be removed in a future version.
    368                  * Use the 'bp_get_blog_avatar' filter instead.
    369                  */
    370                 $avatar = apply_filters( 'bp_get_blog_avatar_' . $blogs_template->blog->blog_id, $avatar );
     383                $avatar = bp_blogs_get_site_avatar( $r );
    371384
    372385                /**
    373386                 * Filters a blog's avatar.
    function bp_blog_permalink() { 
    388401        function bp_get_blog_permalink() {
    389402                global $blogs_template;
    390403
     404                if ( is_null( $blogs_template ) ) {
     405                        return;
     406                }
     407
    391408                if ( empty( $blogs_template->blog->domain ) )
    392409                        $permalink = bp_get_root_domain() . $blogs_template->blog->path;
    393410                else {
    function bp_total_blog_count_for_user( $user_id = 0 ) { 
    900917        }
    901918        add_filter( 'bp_get_total_blog_count_for_user', 'bp_core_number_format' );
    902919
     920/**
     921 * Output the total number of site subscriptions for a given user.
     922 *
     923 * @since  2.7.0
     924 *
     925 * @param int $user_id ID of the user.
     926 */
     927function bp_total_site_subscriptions_for_user( $user_id = 0 ) {
     928        echo bp_get_total_site_subscriptions_for_user( $user_id );
     929}
     930        /**
     931         * Return the total number of site subscriptions for a given user.
     932         *
     933         * @since  2.7.0
     934         *
     935         * @param int $user_id ID of the user.
     936         * @return int Total number of site subscriptions for the user.
     937         */
     938        function bp_get_total_site_subscriptions_for_user( $user_id = 0 ) {
     939
     940                /**
     941                 * Filters the total number of site subscriptions for a given user.
     942                 *
     943                 * @since 2.7.0
     944                 *
     945                 * @param int $value   Total number of site subscriptions for a given user.
     946                 * @param int $user_id ID of the queried user.
     947                 */
     948                return apply_filters( 'bp_get_total_site_subscriptions_for_user', bp_blogs_total_blogs_for_user( $user_id, 0 ), $user_id );
     949        }
     950        add_filter( 'bp_get_total_site_subscriptions_for_user', 'bp_core_number_format' );
     951
    903952
    904953/** Blog Registration ********************************************************/
    905954
    function bp_blogs_signup_blog( $blogname = '', $blog_title = '', $errors = '' ) 
    10261075        if ( !is_subdomain_install() )
    10271076                echo '<span class="prefix_address">' . $current_site->domain . $current_site->path . '</span> <input name="blogname" type="text" id="blogname" value="'.$blogname.'" maxlength="63" /><br />';
    10281077        else
    1029                 echo '<input name="blogname" type="text" id="blogname" value="'.$blogname.'" maxlength="63" ' . bp_get_form_field_attributes( 'blogname' ) . '/> <span class="suffix_address">.' . bp_blogs_get_subdomain_base() . '</span><br />';
     1078                echo '<input name="blogname" type="text" id="blogname" value="'.$blogname.'" maxlength="63" ' . bp_get_form_field_attributes( 'blogname' ) . '/> <span class="suffix_address">.' . bp_signup_get_subdomain_base() . '</span><br />';
    10301079
    10311080        if ( !is_user_logged_in() ) {
    10321081                print '(<strong>' . __( 'Your address will be ' , 'buddypress');
    function bp_blogs_validate_blog_form() { 
    11611210 * @param int|null     $blog_id    ID of the newly created blog.
    11621211 */
    11631212function bp_blogs_confirm_blog_signup( $domain, $path, $blog_title, $user_name, $user_email = '', $meta = '', $blog_id = null ) {
    1164         switch_to_blog( $blog_id );
    1165         $blog_url  = set_url_scheme( home_url() );
    1166         $login_url = set_url_scheme( wp_login_url() );
    1167         restore_current_blog();
     1213        $site_url  = '';
     1214        $login_url = '';
     1215
     1216        if ( ! empty( $blog_id ) ) {
     1217                $site = bp_blogs_get_site( $blog_id );
     1218
     1219                if ( ! empty( $site->blog_id ) ) {
     1220                        $site_url  = $site->url;
     1221                        $login_url = $site->login_url;
     1222                }
     1223        }
    11681224
    11691225        ?>
    11701226        <p><?php _e( 'Congratulations! You have successfully registered a new site.', 'buddypress' ) ?></p>
    11711227        <p>
    1172                 <?php printf(
    1173                         '%s %s',
    1174                         sprintf(
    1175                                 __( '%s is your new site.', 'buddypress' ),
    1176                                 sprintf( '<a href="%s">%s</a>', esc_url( $blog_url ), esc_url( $blog_url ) )
    1177                         ),
    1178                         sprintf(
    1179                                 /* translators: 1: Login URL, 2: User name */
    1180                                 __( '<a href="%1$s">Log in</a> as "%2$s" using your existing password.', 'buddypress' ),
     1228                <?php
     1229                /* translators: 1: Blog URL, 2: Login Link, 2: User name */
     1230                printf( '%1$s is your new site. %2$s as "%3$s" using your existing password.',
     1231                        sprintf( '<a href="%s">%s</a>', esc_url( $site_url ), esc_url( $site_url ) ),
     1232                        sprintf( '<a href="%1$s">%2$s</a>',
    11811233                                esc_url( $login_url ),
    1182                                 esc_html( $user_name )
    1183                         )
     1234                                esc_html_x( 'Log in', 'Blog registered first login', 'buddypress' )
     1235                        ),
     1236                        esc_html( $user_name )
    11841237                ); ?>
    11851238        </p>
    11861239
    1187 <?php
     1240        <?php if ( bp_blogs_is_site_avatar_uploads_enabled() && is_user_logged_in() ) :
     1241                $community_url = bp_blogs_get_site_community_url( $site->slug );
     1242                ?>
     1243
     1244                <p>
     1245                        <?php
     1246                        /* translators: 1: Community URL for the newly created site, 2: Link to the edit Site Profile photo page. */
     1247                        printf( __( 'Discover the %1$s of your site and take a few moments to add a %2$s.', 'buddypress' ),
     1248                                sprintf( '<a href="%1$s">%2$s</a>',
     1249                                        esc_url( $community_url ),
     1250                                        esc_html_x( 'community pages', 'Link text', 'buddypress' )
     1251                                ),
     1252                                sprintf( '<a href="%1$s">%2$s</a>',
     1253                                        esc_url( trailingslashit( $community_url . 'manage/edit-avatar' ) ),
     1254                                        esc_html_x( 'Site Profile Photo', 'Link text', 'buddypress' )
     1255                                )
     1256                        ); ?>
     1257                </p>
     1258
     1259        <?php endif;
    11881260
    11891261        /**
    11901262         * Fires after the default successful blog registration message markup.
    function bp_blogs_get_profile_stats( $args = '' ) { 
    14831555         */
    14841556        return apply_filters( 'bp_blogs_get_profile_stats', $r['output'], $r );
    14851557}
     1558
     1559/**
     1560 * Displays Tabs to filter the Site's activities of the member.
     1561 *
     1562 * My sites: the activities of the sites he is at least a contributor.
     1563 * My Subscriptions: the activities of the sites he subscribed to.
     1564 *
     1565 * @since  2.7.0
     1566 *
     1567 * @return string HTML Output.
     1568 */
     1569function bp_blogs_member_tabs() {
     1570        echo join( "\n", bp_get_blogs_member_tabs() );
     1571}
     1572
     1573        /**
     1574         * Gets Tabs to filter the Site's activities of the member.
     1575         *
     1576         * @since  2.7.0
     1577         *
     1578         * @return array The list of tabs.
     1579         */
     1580        function bp_get_blogs_member_tabs() {
     1581                /**
     1582                 * Filter here to disable/edit the tabs
     1583                 *
     1584                 * @since  2.7.0
     1585                 *
     1586                 * @param array The list of User's tabs for the activity of their Sites.
     1587                 */
     1588                $tabs = apply_filters( 'bp_get_blogs_member_tabs', array(
     1589                        'blogs'         => __( 'My Sites', 'buddypress' ),
     1590                        'subscriptions' => __( 'My Subscriptions', 'buddypress' ),
     1591                ) );
     1592
     1593                // The site's feature or the Subscriptions one is disable, remove the tabs!
     1594                if ( ! bp_blogs_is_site_subscriptions_active() ) {
     1595                        unset( $tabs['subscriptions'] );
     1596
     1597                        // Nobody used the filter to add tabs, let's remove everything!
     1598                        if ( 1 === count( $tabs ) ) {
     1599                                unset( $tabs['blogs'] );
     1600                        }
     1601                }
     1602
     1603                $output = array();
     1604
     1605                if ( empty( $tabs ) ) {
     1606                        return $output;
     1607                }
     1608
     1609                $current_action = bp_action_variable( 0 );
     1610
     1611                foreach ( $tabs as $action => $tab ) {
     1612                        $selected   = '';
     1613                        $link_parts = array( trim( bp_displayed_user_domain(), '/' ), bp_get_activity_slug(), bp_get_blogs_slug() );
     1614
     1615                        if ( ! $current_action && 'blogs' === $action || $current_action === $action ) {
     1616                                $selected = ' current selected';
     1617                        }
     1618
     1619                        if ( 'blogs' !== $action ) {
     1620                                $link_parts[] = $action;
     1621                        }
     1622
     1623                        $output[ $action ] = sprintf( '<li class="activity-%1$s%2$s"><a href="%3$s" class="no-ajax">%4$s</a></li>',
     1624                                esc_attr( $action ),
     1625                                $selected,
     1626                                esc_url( trailingslashit( join( '/', $link_parts ) ) ),
     1627                                esc_html( $tab )
     1628                        );
     1629                }
     1630
     1631                /**
     1632                 * Filter here to edit the output
     1633                 *
     1634                 * @since  2.7.0
     1635                 *
     1636                 * @param array An associative array containing the links to filter the member's sites activity
     1637                 */
     1638                return apply_filters( 'bp_get_blogs_member_tabs_output', $output, $tabs );
     1639        }
  • src/bp-blogs/classes/class-bp-blogs-blog.php

    diff --git src/bp-blogs/classes/class-bp-blogs-blog.php src/bp-blogs/classes/class-bp-blogs-blog.php
    index 6e36295..a7909d8 100644
    class BP_Blogs_Blog { 
    4444        /**
    4545         * Constructor method.
    4646         *
    47          * @param int|null $id Optional. The ID of the blog.
     47         * @since  2.7.0 Add the $blog_id and $user_id parameter.
     48         *
     49         * @param int|null $id      Optional. The ID of the user blog association.
     50         * @param int      $blog_id Optional. The ID of the blog.
     51         * @param int      $user_id Optional. The ID of the user.
    4852         */
    49         public function __construct( $id = null ) {
    50                 if ( !empty( $id ) ) {
    51                         $this->id = $id;
     53        public function __construct( $id = null, $user_id = 0, $blog_id = 0 ) {
     54                $this->id      = $id;
     55                $this->user_id = $user_id;
     56                $this->blog_id = $blog_id;
     57
     58                if ( $this->id || ( $this->user_id && $this->blog_id ) ) {
    5259                        $this->populate();
    5360                }
    5461        }
    5562
    5663        /**
    5764         * Populate the object with data about the specific activity item.
     65         *
     66         * @since  2.7.0 Add the is_contributor field.
    5867         */
    5968        public function populate() {
    6069                global $wpdb;
    6170
    6271                $bp = buddypress();
    6372
    64                 $blog = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$bp->blogs->table_name} WHERE id = %d", $this->id ) );
     73                if ( ! empty( $this->id ) ) {
     74                        $blog = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$bp->blogs->table_name} WHERE id = %d", $this->id ) );
     75                } else {
     76                        $blog = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$bp->blogs->table_name} WHERE user_id = %d AND blog_id = %d", $this->user_id, $this->blog_id ) );
     77                }
    6578
    66                 $this->user_id = $blog->user_id;
    67                 $this->blog_id = $blog->blog_id;
     79                if ( empty( $blog ) ) {
     80                        $this->id = 0;
     81                        return;
     82                }
     83
     84                $this->id             = $blog->id;
     85                $this->user_id        = $blog->user_id;
     86                $this->blog_id        = $blog->blog_id;
     87                $this->is_contributor = $blog->is_contributor;
    6888        }
    6989
    7090        /**
    7191         * Save the BP blog data to the database.
    7292         *
     93         * @since  2.7.0 Add the is_contributor field.
     94         *
    7395         * @return bool True on success, false on failure.
    7496         */
    7597        public function save() {
    7698                global $wpdb;
    7799
    78                 $this->user_id = apply_filters( 'bp_blogs_blog_user_id_before_save', $this->user_id, $this->id );
    79                 $this->blog_id = apply_filters( 'bp_blogs_blog_id_before_save', $this->blog_id, $this->id );
     100                $this->user_id        = apply_filters( 'bp_blogs_blog_user_id_before_save',   $this->user_id,        $this->id );
     101                $this->blog_id        = apply_filters( 'bp_blogs_blog_id_before_save',        $this->blog_id,        $this->id );
     102                $this->is_contributor = apply_filters( 'bp_blogs_is_contributor_before_save', $this->is_contributor, $this->id );
    80103
    81104                /**
    82105                 * Fires before the current blog item gets saved.
    class BP_Blogs_Blog { 
    90113                do_action_ref_array( 'bp_blogs_blog_before_save', array( &$this ) );
    91114
    92115                // Don't try and save if there is no user ID or blog ID set.
    93                 if ( !$this->user_id || !$this->blog_id )
     116                if ( ! $this->user_id || ! $this->blog_id ) {
    94117                        return false;
     118                }
    95119
    96120                // Don't save if this blog has already been recorded for the user.
    97                 if ( !$this->id && $this->exists() )
     121                if ( ! $this->id && $this->exists() ) {
    98122                        return false;
     123                }
    99124
    100125                $bp = buddypress();
    101126
    102127                if ( $this->id ) {
    103128                        // Update.
    104                         $sql = $wpdb->prepare( "UPDATE {$bp->blogs->table_name} SET user_id = %d, blog_id = %d WHERE id = %d", $this->user_id, $this->blog_id, $this->id );
     129                        $sql = $wpdb->prepare( "UPDATE {$bp->blogs->table_name} SET user_id = %d, blog_id = %d, is_contributor = %d WHERE id = %d", $this->user_id, $this->blog_id, $this->is_contributor, $this->id );
    105130                } else {
    106131                        // Save.
    107                         $sql = $wpdb->prepare( "INSERT INTO {$bp->blogs->table_name} ( user_id, blog_id ) VALUES ( %d, %d )", $this->user_id, $this->blog_id );
     132                        $sql = $wpdb->prepare( "INSERT INTO {$bp->blogs->table_name} ( user_id, blog_id, is_contributor ) VALUES ( %d, %d, %d )", $this->user_id, $this->blog_id, $this->is_contributor );
    108133                }
    109134
    110                 if ( !$wpdb->query($sql) )
     135                if ( ! $wpdb->query( $sql ) ) {
    111136                        return false;
     137                }
    112138
    113139                /**
    114140                 * Fires after the current blog item gets saved.
    class BP_Blogs_Blog { 
    121147                 */
    122148                do_action_ref_array( 'bp_blogs_blog_after_save', array( &$this ) );
    123149
    124                 if ( $this->id )
     150                if ( $this->id ) {
    125151                        return $this->id;
    126                 else
     152                } else {
    127153                        return $wpdb->insert_id;
     154                }
    128155        }
    129156
    130157        /**
    class BP_Blogs_Blog { 
    146173        /**
    147174         * Retrieve a set of blog-user associations.
    148175         *
     176         * @since  2.7.0 Use the BP_Site_Query class if WordPress is >= 4.6
     177         *
    149178         * @param string      $type              The order in which results should be returned.
    150179         *                                       'active', 'alphabetical', 'newest', or 'random'.
    151180         * @param int|bool    $limit             Optional. The maximum records to return.
    class BP_Blogs_Blog { 
    159188         * @param bool        $update_meta_cache Whether to pre-fetch metadata for
    160189         *                                       blogs. Default: true.
    161190         * @param array|bool  $include_blog_ids  Array of blog IDs to include.
     191         * @param int         $is_contributor    Whether to get sites user is at least a contributor (1)
     192         *                                       or the sites he subscribed to (0). Default: 1.
    162193         * @return array Multidimensional results array, structured as follows:
    163194         *               'blogs' - Array of located blog objects
    164195         *               'total' - A count of the total blogs matching the filter params
    165196         */
    166         public static function get( $type, $limit = false, $page = false, $user_id = 0, $search_terms = false, $update_meta_cache = true, $include_blog_ids = false ) {
    167                 global $wpdb;
    168 
    169                 $bp = buddypress();
     197        public static function get( $type, $limit = false, $page = false, $user_id = 0, $search_terms = false, $update_meta_cache = true, $include_blog_ids = false, $is_contributor = 1 ) {
     198                // Default query vars
     199                $query_vars = array(
     200                        'public'                => 1,
     201                        'offset'                => 0,
     202                        'number'                => 20,
     203                        'update_blogmeta_cache' => $update_meta_cache,
     204                );
     205
     206                if ( bp_current_user_can( 'bp_moderate' ) || ( ! empty( $user_id ) && (int) $user_id === (int) bp_loggedin_user_id() ) ) {
     207                        unset( $query_vars['public'] );
     208                }
    170209
    171                 if ( !is_user_logged_in() || ( !bp_current_user_can( 'bp_moderate' ) && ( $user_id != bp_loggedin_user_id() ) ) )
    172                         $hidden_sql = "AND wb.public = 1";
    173                 else
    174                         $hidden_sql = '';
     210                if ( $limit && $page ) {
     211                        $query_vars = array_merge( $query_vars, array(
     212                                'offset' => (int) ( ( $page - 1 ) * $limit ),
     213                                'number' => (int) $limit,
     214                        ) );
     215                }
    175216
    176                 $pag_sql = ( $limit && $page ) ? $wpdb->prepare( " LIMIT %d, %d", intval( ( $page - 1 ) * $limit), intval( $limit ) ) : '';
     217                if ( ! empty( $user_id ) ) {
     218                        $query_vars['user_id'] = (int) $user_id;
    177219
    178                 $user_sql = !empty( $user_id ) ? $wpdb->prepare( " AND b.user_id = %d", $user_id ) : '';
     220                        if ( ! is_null( $is_contributor ) ) {
     221                                $query_vars['is_contributor'] = (int) $is_contributor;
     222                        }
     223                }
    179224
    180225                switch ( $type ) {
    181226                        case 'active': default:
    182                                 $order_sql = "ORDER BY bm.meta_value DESC";
     227                                $query_vars = array_merge( $query_vars, array(
     228                                        'orderby' => 'last_activity',
     229                                        'order'   => 'DESC',
     230                                ) );
    183231                                break;
    184232                        case 'alphabetical':
    185                                 $order_sql = "ORDER BY bm_name.meta_value ASC";
     233                                $query_vars =  array_merge( $query_vars, array(
     234                                        'orderby' => 'name',
     235                                        'order'   => 'ASC',
     236                                ) );
    186237                                break;
    187238                        case 'newest':
    188                                 $order_sql = "ORDER BY wb.registered DESC";
     239                                $query_vars = array_merge( $query_vars, array(
     240                                        'orderby' => 'registered',
     241                                        'order'   => 'DESC',
     242                                ) );
    189243                                break;
    190244                        case 'random':
    191                                 $order_sql = "ORDER BY RAND()";
     245                                $query_vars = array_merge( $query_vars, array(
     246                                        'orderby' => 'RAND()',
     247                                        'order'   => '',
     248                                ) );
    192249                                break;
    193250                }
    194251
    195                 $include_sql = '';
    196252                $include_blog_ids = array_filter( wp_parse_id_list( $include_blog_ids ) );
    197253                if ( ! empty( $include_blog_ids ) ) {
    198                         $blog_ids_sql = implode( ',', $include_blog_ids );
    199                         $include_sql  = " AND b.blog_id IN ({$blog_ids_sql})";
     254                        $query_vars['site__in'] = $include_blog_ids;
    200255                }
    201256
    202257                if ( ! empty( $search_terms ) ) {
    203                         $search_terms_like = '%' . bp_esc_like( $search_terms ) . '%';
    204                         $search_terms_sql  = $wpdb->prepare( 'AND (bm_name.meta_value LIKE %s OR bm_description.meta_value LIKE %s)', $search_terms_like, $search_terms_like );
     258                        $query_vars['search_terms'] = bp_esc_like( $search_terms );
     259                }
     260
     261                // Init empty results
     262                $results = array( 'blogs' => array(), 'total' => 0 );
     263
     264                /**
     265                 * If the WordPress version is at least 4.6, we will use BP_Site_Query
     266                 * unless you filter 'bp_blogs_use_bp_site_query' by returning false.
     267                 *
     268                 * @since  2.7.0
     269                 *
     270                 * @param  bool $value True to use BP_Site_Query. False otherwise.
     271                 */
     272                if ( true === (bool) apply_filters( 'bp_blogs_use_bp_site_query', true ) && function_exists( 'get_sites' ) ) {
     273                        $sites    = new BP_Site_Query( $query_vars );
     274                        $results  = $sites->get_results();
     275                } else {
     276                        $results = self::legacy_get( $query_vars, $type );
     277                }
     278
     279                return $results;
     280        }
     281
     282        /**
     283         * Get blogs using the legacy way.
     284         *
     285         * @since  2.7.0
     286         *
     287         * @param  array  $query_vars An array containing the query vars.
     288         * @param  string $type       The sort order type.
     289         * @return array Multidimensional results array, structured as follows:
     290         *               'blogs' - Array of located blog objects
     291         *               'total' - A count of the total blogs matching the filter params
     292         */
     293        public static function legacy_get( $query_vars = array(), $type = 'active' ) {
     294                global $wpdb;
     295
     296                $bp = buddypress();
     297
     298                $sql = array(
     299                        'select'  => 'SELECT b.blog_id, b.user_id as admin_user_id, u.user_email as admin_user_email, wb.domain, wb.path, bm.meta_value as last_activity, bm_name.meta_value as name',
     300                        'from'    => "FROM {$bp->blogs->table_name} b",
     301                        'join'    => array(
     302                                'bm'             => "{$bp->blogs->table_name_blogmeta} bm ON (b.blog_id = bm.blog_id)",
     303                                'bm_name'        => "{$bp->blogs->table_name_blogmeta} bm_name ON (b.blog_id = bm_name.blog_id)",
     304                                'bm_description' => "{$bp->blogs->table_name_blogmeta} bm_description ON (b.blog_id = bm_description.blog_id)",
     305                                'wb'             => "{$wpdb->blogs} wb ON (b.blog_id = wb.blog_id)",
     306                                'u'              => "{$wpdb->users} u ON (b.user_id = u.ID)",
     307                        ),
     308                        'where'   => array(
     309                                'common' => "wb.archived = 0 AND wb.spam = 0 AND wb.mature = 0 AND wb.deleted = 0 AND bm_name.meta_key = 'name' AND bm_description.meta_key = 'description'",
     310                                'active' => "bm.meta_key = 'last_activity'",
     311                        ),
     312                        'groupby' => 'GROUP BY b.blog_id',
     313                        'orderby' => array(
     314                                'last_activity' => 'ORDER BY bm.meta_value DESC',
     315                                'name'          => 'ORDER BY bm_name.meta_value ASC',
     316                                'registered'    => 'ORDER BY wb.registered DESC',
     317                                'RAND()'        => 'ORDER BY RAND()',
     318                        ),
     319                        'limit'   => $wpdb->prepare( "LIMIT %d, %d", $query_vars['offset'], $query_vars['number'] ),
     320                );
     321
     322                // Hide private blogs if needed
     323                if ( ! empty( $query_vars['public'] ) ) {
     324                        $sql['where']['hidden'] = 'wb.public = 1';
     325                }
     326
     327                // Limit results to blogs the user_id is a member of.
     328                if ( ! empty( $query_vars['user_id'] ) ) {
     329                        $sql['where']['user_id'] = $wpdb->prepare( 'b.user_id = %d', $query_vars['user_id'] );
     330
     331                        // Defaults to blogs user is a least a contributor of
     332                        if ( ! isset( $query_vars['is_contributor'] ) ) {
     333                                $sql['where']['is_contributor'] = 'b.is_contributor = 1';
     334                        } else {
     335                                $sql['where']['is_contributor'] = $wpdb->prepare( 'b.is_contributor = %d', $query_vars['is_contributor'] );
     336                        }
     337                }
     338
     339                // Limit results to included sites.
     340                if ( ! empty( $query_vars['site__in'] ) ) {
     341                        $sql['where']['include'] = $wpdb->prepare( 'b.blog_id IN (%s)', implode( ',', $query_vars['site__in'] ) );
     342                }
     343
     344                // Limit resultes to sites matching search terms.
     345                if ( ! empty( $query_vars['search_terms'] ) ) {
     346                        $search_terms_like      = '%' . $query_vars['search_terms'] . '%';
     347                        $sql['where']['search'] = $wpdb->prepare( '( bm_name.meta_value LIKE %s OR bm_description.meta_value LIKE %s )', $search_terms_like, $search_terms_like );
     348                }
     349
     350                // Eventually handle single site query.
     351                $single_site = ! empty( $query_vars['single_site'] );
     352
     353                if ( $single_site ) {
     354                        if ( ! empty( $query_vars['ID'] ) ) {
     355                                $sql['where']['single_site'] = $wpdb->prepare( 'wb.blog_id = %d', $query_vars['ID'] );
     356                        } elseif ( ! empty( $query_vars['domain__in'] ) ) {
     357                                $sql['where']['single_site'] = $wpdb->prepare( 'wb.domain = %s', reset( $query_vars['domain__in'] ) );
     358                        } else {
     359                                $sql['where']['single_site'] = $wpdb->prepare( 'wb.path = %s', reset( $query_vars['path__in'] ) );
     360                        }
     361                }
     362
     363                // Set a copy for the total query
     364                $total_sql = $sql;
     365
     366                // Set joins
     367                $sql['join'] = 'LEFT JOIN ' . join( ' LEFT JOIN ', $sql['join'] );
     368
     369                // Set where clauses
     370                $sql['where'] = 'WHERE ' . join( ' AND ', $sql['where'] );
     371
     372                // Set order
     373                if ( ! empty( $query_vars['orderby'] ) ) {
     374                        $sql_orderby    = array_intersect_key( $sql['orderby'], array( $query_vars['orderby'] => true ) );
     375                        $sql['orderby'] = reset( $sql_orderby );
    205376                } else {
    206                         $search_terms_sql = '';
    207                 }
    208 
    209                 $paged_blogs = $wpdb->get_results( "
    210                         SELECT b.blog_id, b.user_id as admin_user_id, u.user_email as admin_user_email, wb.domain, wb.path, bm.meta_value as last_activity, bm_name.meta_value as name
    211                         FROM
    212                           {$bp->blogs->table_name} b
    213                           LEFT JOIN {$bp->blogs->table_name_blogmeta} bm ON (b.blog_id = bm.blog_id)
    214                           LEFT JOIN {$bp->blogs->table_name_blogmeta} bm_name ON (b.blog_id = bm_name.blog_id)
    215                           LEFT JOIN {$bp->blogs->table_name_blogmeta} bm_description ON (b.blog_id = bm_description.blog_id)
    216                           LEFT JOIN {$wpdb->base_prefix}blogs wb ON (b.blog_id = wb.blog_id)
    217                           LEFT JOIN {$wpdb->users} u ON (b.user_id = u.ID)
    218                         WHERE
    219                           wb.archived = '0' AND wb.spam = 0 AND wb.mature = 0 AND wb.deleted = 0 {$hidden_sql}
    220                           AND bm.meta_key = 'last_activity' AND bm_name.meta_key = 'name' AND bm_description.meta_key = 'description'
    221                           {$search_terms_sql} {$user_sql} {$include_sql}
    222                         GROUP BY b.blog_id {$order_sql} {$pag_sql}
    223                 " );
    224 
    225                 $total_blogs = $wpdb->get_var( "
    226                         SELECT COUNT(DISTINCT b.blog_id)
    227                         FROM
    228                           {$bp->blogs->table_name} b
    229                           LEFT JOIN {$wpdb->base_prefix}blogs wb ON (b.blog_id = wb.blog_id)
    230                           LEFT JOIN {$bp->blogs->table_name_blogmeta} bm_name ON (b.blog_id = bm_name.blog_id)
    231                           LEFT JOIN {$bp->blogs->table_name_blogmeta} bm_description ON (b.blog_id = bm_description.blog_id)
    232                         WHERE
    233                           wb.archived = '0' AND wb.spam = 0 AND wb.mature = 0 AND wb.deleted = 0 {$hidden_sql}
    234                           AND
    235                           bm_name.meta_key = 'name' AND bm_description.meta_key = 'description'
    236                           {$search_terms_sql} {$user_sql} {$include_sql}
    237                 " );
    238 
    239                 $blog_ids = array();
    240                 foreach ( (array) $paged_blogs as $blog ) {
    241                         $blog_ids[] = (int) $blog->blog_id;
    242                 }
    243 
    244                 $paged_blogs = BP_Blogs_Blog::get_blog_extras( $paged_blogs, $blog_ids, $type );
    245 
    246                 if ( $update_meta_cache ) {
     377                        unset( $sql['orderby'] );
     378                }
     379
     380                $return = array(
     381                        'blogs' => $wpdb->get_results( join( ' ', $sql ) ),
     382                );
     383
     384                // Set the total sql parts
     385                if ( ! $single_site ) {
     386                        $total_sql['select'] = 'SELECT COUNT(DISTINCT b.blog_id)';
     387                        unset( $total_sql['join']['bm'], $total_sql['join']['u'], $total_sql['where']['active'], $total_sql['groupby'], $total_sql['orderby'], $total_sql['limit'] );
     388                        $total_sql['join']  = 'LEFT JOIN ' . join( ' LEFT JOIN ', $total_sql['join'] );
     389                        $total_sql['where'] = 'WHERE ' . join( ' AND ', $total_sql['where'] );
     390
     391                        $return['total'] = $wpdb->get_var( join( ' ', $total_sql ) );
     392                }
     393
     394                $blog_ids           = array_map( 'intval', wp_list_pluck( $return[ 'blogs' ], 'blog_id' ) );
     395                $return[ 'blogs' ]  = BP_Blogs_Blog::get_blog_extras( $return[ 'blogs' ], $blog_ids, $type, ! $single_site );
     396
     397                if ( ! empty( $query_vars['update_blogmeta_cache'] ) ) {
    247398                        bp_blogs_update_meta_cache( $blog_ids );
    248399                }
    249400
    250                 return array( 'blogs' => $paged_blogs, 'total' => $total_blogs );
     401                return $return;
    251402        }
    252403
    253404        /**
    class BP_Blogs_Blog { 
    277428        public static function delete_blog_for_user( $blog_id, $user_id = null ) {
    278429                global $wpdb;
    279430
    280                 if ( !$user_id )
     431                if ( ! $user_id ) {
    281432                        $user_id = bp_loggedin_user_id();
     433                }
    282434
    283435                $bp = buddypress();
    284436
    class BP_Blogs_Blog { 
    311463         * blogs that have been recorded by BuddyPress, while the WP function
    312464         * does a true query of a user's blog capabilities.
    313465         *
    314          * @param int  $user_id     Optional. ID of the user whose blogs are being
    315          *                          queried. Defaults to logged-in user.
    316          * @param bool $show_hidden Optional. Whether to include blogs that are not marked
    317          *                          public. Defaults to true when viewing one's own profile.
     466         * @since  2.7.0 Add the is_contributor parameter.
     467         *
     468         * @param int      $user_id        Optional. ID of the user whose blogs are being
     469         *                                 queried. Defaults to logged-in user.
     470         * @param bool     $show_hidden    Optional. Whether to include blogs that are not marked
     471         *                                 public. Defaults to true when viewing one's own profile.
     472         * @param int|null $is_contributor Optional. Type of blogs to get. Defaults to 1,
     473         *                                 blogs the user is a contributor of.
    318474         * @return array Multidimensional results array, structured as follows:
    319475         *               'blogs' - Array of located blog objects.
    320476         *               'total' - A count of the total blogs for the user.
    321477         */
    322         public static function get_blogs_for_user( $user_id = 0, $show_hidden = false ) {
     478        public static function get_blogs_for_user( $user_id = 0, $show_hidden = false, $is_contributor = 1 ) {
    323479                global $wpdb;
    324480
    325481                $bp = buddypress();
    326482
    327                 if ( !$user_id )
     483                if ( ! $user_id ) {
    328484                        $user_id = bp_displayed_user_id();
     485                }
     486
     487                $is_contributor_sql = '';
     488                if ( ! is_null( $is_contributor ) ) {
     489                        $is_contributor_sql = sprintf( 'AND b.is_contributor = %d', $is_contributor );
     490                }
    329491
    330492                // Show logged in users their hidden blogs.
    331                 if ( !bp_is_my_profile() && !$show_hidden )
    332                         $blogs = $wpdb->get_results( $wpdb->prepare( "SELECT DISTINCT b.blog_id, b.id, bm1.meta_value as name, wb.domain, wb.path FROM {$bp->blogs->table_name} b, {$wpdb->base_prefix}blogs wb, {$bp->blogs->table_name_blogmeta} bm1 WHERE b.blog_id = wb.blog_id AND b.blog_id = bm1.blog_id AND bm1.meta_key = 'name' AND wb.public = 1 AND wb.deleted = 0 AND wb.spam = 0 AND wb.mature = 0 AND wb.archived = '0' AND b.user_id = %d ORDER BY b.blog_id", $user_id ) );
    333                 else
    334                         $blogs = $wpdb->get_results( $wpdb->prepare( "SELECT DISTINCT b.blog_id, b.id, bm1.meta_value as name, wb.domain, wb.path FROM {$bp->blogs->table_name} b, {$wpdb->base_prefix}blogs wb, {$bp->blogs->table_name_blogmeta} bm1 WHERE b.blog_id = wb.blog_id AND b.blog_id = bm1.blog_id AND bm1.meta_key = 'name' AND wb.deleted = 0 AND wb.spam = 0 AND wb.mature = 0 AND wb.archived = '0' AND b.user_id = %d ORDER BY b.blog_id", $user_id ) );
     493                if ( ! bp_is_my_profile() && ! $show_hidden ) {
     494                        $blogs = $wpdb->get_results( $wpdb->prepare( "SELECT DISTINCT b.blog_id, b.id, bm1.meta_value as name, wb.domain, wb.path FROM {$bp->blogs->table_name} b, {$wpdb->base_prefix}blogs wb, {$bp->blogs->table_name_blogmeta} bm1 WHERE b.blog_id = wb.blog_id AND b.blog_id = bm1.blog_id AND bm1.meta_key = 'name' AND wb.public = 1 AND wb.deleted = 0 AND wb.spam = 0 AND wb.mature = 0 AND wb.archived = '0' AND b.user_id = %d {$is_contributor_sql} ORDER BY b.blog_id", $user_id ) );
     495                } else {
     496                        $blogs = $wpdb->get_results( $wpdb->prepare( "SELECT DISTINCT b.blog_id, b.id, bm1.meta_value as name, wb.domain, wb.path FROM {$bp->blogs->table_name} b, {$wpdb->base_prefix}blogs wb, {$bp->blogs->table_name_blogmeta} bm1 WHERE b.blog_id = wb.blog_id AND b.blog_id = bm1.blog_id AND bm1.meta_key = 'name' AND wb.deleted = 0 AND wb.spam = 0 AND wb.mature = 0 AND wb.archived = '0' AND b.user_id = %d {$is_contributor_sql} ORDER BY b.blog_id", $user_id ) );
     497                }
    335498
    336499                $total_blog_count = BP_Blogs_Blog::total_blog_count_for_user( $user_id );
    337500
    class BP_Blogs_Blog { 
    352515         *
    353516         * This method always includes hidden blogs.
    354517         *
    355          * @param int $user_id Optional. ID of the user whose blogs are being
    356          *                     queried. Defaults to logged-in user.
     518         * @since  2.7.0 Add the is_contributor parameter.
     519         *
     520         * @param int      $user_id        Optional. ID of the user whose blogs are being
     521         *                                 queried. Defaults to logged-in user.
     522         * @param int|null $is_contributor Optional. Type of blogs to get. Defaults to 1,
     523         *                                 blogs the user is a contributor of.
    357524         * @return int The number of blogs associated with the user.
    358525         */
    359         public static function get_blog_ids_for_user( $user_id = 0 ) {
     526        public static function get_blog_ids_for_user( $user_id = 0, $is_contributor = 1 ) {
    360527                global $wpdb;
    361528
    362529                $bp = buddypress();
    363530
    364                 if ( !$user_id )
     531                if ( ! $user_id ) {
    365532                        $user_id = bp_displayed_user_id();
     533                }
     534
     535                $where = array(
     536                        'user_id' => $wpdb->prepare( 'user_id = %d', $user_id ),
     537                );
    366538
    367                 return $wpdb->get_col( $wpdb->prepare( "SELECT blog_id FROM {$bp->blogs->table_name} WHERE user_id = %d", $user_id ) );
     539                if ( ! is_null( $is_contributor ) ) {
     540                        $where['is_contributor'] = $wpdb->prepare( 'is_contributor = %d', $is_contributor );
     541                }
     542
     543                $where = join( ' AND ', $where );
     544
     545                return $wpdb->get_col( "SELECT blog_id FROM {$bp->blogs->table_name} WHERE {$where}" );
    368546        }
    369547
    370548        /**
    class BP_Blogs_Blog { 
    389567         * $user_id parameter, or when the logged-in user has the bp_moderate
    390568         * cap.
    391569         *
    392          * @param int|null $user_id Optional. ID of the user whose blogs are being
    393          *                          queried. Defaults to logged-in user.
     570         * @since  2.7.0 Add the is_contributor parameter.
     571         *
     572         * @param int|null $user_id        Optional. ID of the user whose blogs are being
     573         *                                 queried. Defaults to logged-in user.
     574         * @param int|null $is_contributor Optional. Type of blogs to get. Defaults to 1,
     575         *                                 blogs the user is a contributor of.
    394576         * @return int Blog count for the user.
    395577         */
    396         public static function total_blog_count_for_user( $user_id = null ) {
     578        public static function total_blog_count_for_user( $user_id = null, $is_contributor = 1 ) {
    397579                global $wpdb;
    398580
    399581                $bp = buddypress();
    400582
    401                 if ( !$user_id )
     583                if ( ! $user_id ) {
    402584                        $user_id = bp_displayed_user_id();
     585                }
     586
     587                $is_contributor_sql = '';
     588                if ( ! is_null( $is_contributor ) ) {
     589                        $is_contributor_sql = sprintf( 'AND b.is_contributor = %d', $is_contributor );
     590                }
    403591
    404592                // If the user is logged in return the blog count including their hidden blogs.
    405593                if ( ( is_user_logged_in() && $user_id == bp_loggedin_user_id() ) || bp_current_user_can( 'bp_moderate' ) ) {
    406                         return $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(DISTINCT b.blog_id) FROM {$bp->blogs->table_name} b LEFT JOIN {$wpdb->base_prefix}blogs wb ON b.blog_id = wb.blog_id WHERE wb.deleted = 0 AND wb.spam = 0 AND wb.mature = 0 AND wb.archived = '0' AND user_id = %d", $user_id ) );
     594                        return $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(DISTINCT b.blog_id) FROM {$bp->blogs->table_name} b LEFT JOIN {$wpdb->base_prefix}blogs wb ON b.blog_id = wb.blog_id WHERE wb.deleted = 0 AND wb.spam = 0 AND wb.mature = 0 AND wb.archived = '0' AND user_id = %d {$is_contributor_sql}", $user_id ) );
    407595                } else {
    408                         return $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(DISTINCT b.blog_id) FROM {$bp->blogs->table_name} b LEFT JOIN {$wpdb->base_prefix}blogs wb ON b.blog_id = wb.blog_id WHERE wb.public = 1 AND wb.deleted = 0 AND wb.spam = 0 AND wb.mature = 0 AND wb.archived = '0' AND user_id = %d", $user_id ) );
     596                        return $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(DISTINCT b.blog_id) FROM {$bp->blogs->table_name} b LEFT JOIN {$wpdb->base_prefix}blogs wb ON b.blog_id = wb.blog_id WHERE wb.public = 1 AND wb.deleted = 0 AND wb.spam = 0 AND wb.mature = 0 AND wb.archived = '0' AND user_id = %d {$is_contributor_sql}", $user_id ) );
    409597                }
    410598        }
    411599
    class BP_Blogs_Blog { 
    453641         * Query will include hidden blogs if the logged-in user has the
    454642         * 'bp_moderate' cap.
    455643         *
    456          * @param int|null $limit Optional. The maximum number of items to return.
    457          *                        Default: null (no limit).
    458          * @param int|null $page  Optional. The page of results to return. Default:
    459          *                        null (no limit).
     644         * @param int|null $limit           Optional. The maximum number of items to return.
     645         *                                  Default: null (no limit).
     646         * @param int|null $page            Optional. The page of results to return. Default:
     647         *                                  null (no limit).
     648         * @param int|null $is_contributor  Optional. The type of blogs to return. Default:
     649         *                                  1 (blogs the user is a contributor of).
    460650         * @return array Multidimensional results array, structured as follows:
    461651         *               'blogs' - Array of located blog objects.
    462652         *               'total' - A count of the total blogs.
    463653         */
    464         public static function get_all( $limit = null, $page = null ) {
     654        public static function get_all( $limit = null, $page = null, $is_contributor = 1 ) {
    465655                global $wpdb;
    466656
    467657                $bp = buddypress();
    468658
    469                 $hidden_sql = !bp_current_user_can( 'bp_moderate' ) ? "AND wb.public = 1" : '';
     659                $is_contributor_sql = '';
     660                if ( ! is_null( $is_contributor ) ) {
     661                        $is_contributor_sql = sprintf( 'AND b.is_contributor = %d', $is_contributor );
     662                }
     663
     664                $hidden_sql         = "AND wb.public = 1";
     665                if ( bp_current_user_can( 'bp_moderate' ) ) {
     666                        $hidden_sql     = '';
     667                }
     668
    470669                $pag_sql    = ( $limit && $page ) ? $wpdb->prepare( " LIMIT %d, %d", intval( ( $page - 1 ) * $limit), intval( $limit ) ) : '';
    471670
    472                 $paged_blogs = $wpdb->get_results( "SELECT DISTINCT b.blog_id FROM {$bp->blogs->table_name} b LEFT JOIN {$wpdb->base_prefix}blogs wb ON b.blog_id = wb.blog_id WHERE wb.mature = 0 AND wb.spam = 0 AND wb.archived = '0' AND wb.deleted = 0 {$hidden_sql} {$pag_sql}" );
    473                 $total_blogs = $wpdb->get_var( "SELECT COUNT(DISTINCT b.blog_id) FROM {$bp->blogs->table_name} b LEFT JOIN {$wpdb->base_prefix}blogs wb ON b.blog_id = wb.blog_id WHERE wb.mature = 0 AND wb.spam = 0 AND wb.archived = '0' AND wb.deleted = 0 {$hidden_sql}" );
     671                $paged_blogs = $wpdb->get_results( "SELECT DISTINCT b.blog_id FROM {$bp->blogs->table_name} b LEFT JOIN {$wpdb->base_prefix}blogs wb ON b.blog_id = wb.blog_id WHERE wb.mature = 0 AND wb.spam = 0 AND wb.archived = '0' AND wb.deleted = 0 {$hidden_sql} {$is_contributor_sql} {$pag_sql}" );
     672                $total_blogs = $wpdb->get_var( "SELECT COUNT(DISTINCT b.blog_id) FROM {$bp->blogs->table_name} b LEFT JOIN {$wpdb->base_prefix}blogs wb ON b.blog_id = wb.blog_id WHERE wb.mature = 0 AND wb.spam = 0 AND wb.archived = '0' AND wb.deleted = 0 {$hidden_sql} {$is_contributor_sql}" );
    474673
    475674                return array( 'blogs' => $paged_blogs, 'total' => $total_blogs );
    476675        }
    class BP_Blogs_Blog { 
    495694
    496695                $bp = buddypress();
    497696
    498                 $letter_like = '%' . bp_esc_like( $letter ) . '%';
     697                $letter_like = bp_esc_like( $letter ) . '%';
    499698                $letter_sql  = $wpdb->prepare( 'bm.meta_value LIKE %s', $letter_like );
    500699
    501700                $hidden_sql = '';
    class BP_Blogs_Blog { 
    526725         * @param string|bool $type        Not currently used. Default: false.
    527726         * @return array $paged_blogs The located blogs array, with the extras added.
    528727         */
    529         public static function get_blog_extras( &$paged_blogs, &$blog_ids, $type = false ) {
     728        public static function get_blog_extras( &$paged_blogs, &$blog_ids, $type = false, $get_latest_post = true ) {
    530729                global $wpdb;
    531730
    532731                $bp = buddypress();
    533732
    534                 if ( empty( $blog_ids ) )
     733                if ( empty( $blog_ids ) ) {
    535734                        return $paged_blogs;
     735                }
    536736
    537737                $blog_ids = implode( ',', wp_parse_id_list( $blog_ids ) );
    538738
    539                 for ( $i = 0, $count = count( $paged_blogs ); $i < $count; ++$i ) {
    540                         $blog_prefix = $wpdb->get_blog_prefix( $paged_blogs[$i]->blog_id );
    541                         $paged_blogs[$i]->latest_post = $wpdb->get_row( "SELECT ID, post_content, post_title, post_excerpt, guid FROM {$blog_prefix}posts WHERE post_status = 'publish' AND post_type = 'post' AND id != 1 ORDER BY id DESC LIMIT 1" );
    542                         $images = array();
    543 
    544                         // Add URLs to any Featured Image this post might have.
    545                         if ( ! empty( $paged_blogs[$i]->latest_post ) && has_post_thumbnail( $paged_blogs[$i]->latest_post->ID ) ) {
    546 
    547                                 // Grab 4 sizes of the image. Thumbnail.
    548                                 $image = wp_get_attachment_image_src( get_post_thumbnail_id( $paged_blogs[$i]->latest_post->ID ), 'thumbnail', false );
    549                                 if ( ! empty( $image ) )
    550                                         $images['thumbnail'] = $image[0];
    551 
    552                                 // Medium.
    553                                 $image = wp_get_attachment_image_src( get_post_thumbnail_id( $paged_blogs[$i]->latest_post->ID ), 'medium', false );
    554                                 if ( ! empty( $image ) )
    555                                         $images['medium'] = $image[0];
    556 
    557                                 // Large.
    558                                 $image = wp_get_attachment_image_src( get_post_thumbnail_id( $paged_blogs[$i]->latest_post->ID ), 'large', false );
    559                                 if ( ! empty( $image ) )
    560                                         $images['large'] = $image[0];
    561 
    562                                 // Post thumbnail.
    563                                 $image = wp_get_attachment_image_src( get_post_thumbnail_id( $paged_blogs[$i]->latest_post->ID ), 'post-thumbnail', false );
    564                                 if ( ! empty( $image ) )
    565                                         $images['post-thumbnail'] = $image[0];
    566 
    567                                 // Add the images to the latest_post object.
    568                                 $paged_blogs[$i]->latest_post->images = $images;
     739                // Only get latest post in loops.
     740                if ( $get_latest_post ) {
     741
     742                        for ( $i = 0, $count = count( $paged_blogs ); $i < $count; ++$i ) {
     743                                $blog_prefix = $wpdb->get_blog_prefix( $paged_blogs[$i]->blog_id );
     744                                $paged_blogs[$i]->latest_post = $wpdb->get_row( "SELECT ID, post_content, post_title, post_excerpt, guid FROM {$blog_prefix}posts WHERE post_status = 'publish' AND post_type = 'post' AND id != 1 ORDER BY id DESC LIMIT 1" );
     745                                $images = array();
     746
     747                                // Add URLs to any Featured Image this post might have.
     748                                if ( ! empty( $paged_blogs[$i]->latest_post ) && has_post_thumbnail( $paged_blogs[$i]->latest_post->ID ) ) {
     749
     750                                        // Grab 4 sizes of the image. Thumbnail.
     751                                        $image = wp_get_attachment_image_src( get_post_thumbnail_id( $paged_blogs[$i]->latest_post->ID ), 'thumbnail', false );
     752                                        if ( ! empty( $image ) )
     753                                                $images['thumbnail'] = $image[0];
     754
     755                                        // Medium.
     756                                        $image = wp_get_attachment_image_src( get_post_thumbnail_id( $paged_blogs[$i]->latest_post->ID ), 'medium', false );
     757                                        if ( ! empty( $image ) )
     758                                                $images['medium'] = $image[0];
     759
     760                                        // Large.
     761                                        $image = wp_get_attachment_image_src( get_post_thumbnail_id( $paged_blogs[$i]->latest_post->ID ), 'large', false );
     762                                        if ( ! empty( $image ) )
     763                                                $images['large'] = $image[0];
     764
     765                                        // Post thumbnail.
     766                                        $image = wp_get_attachment_image_src( get_post_thumbnail_id( $paged_blogs[$i]->latest_post->ID ), 'post-thumbnail', false );
     767                                        if ( ! empty( $image ) )
     768                                                $images['post-thumbnail'] = $image[0];
     769
     770                                        // Add the images to the latest_post object.
     771                                        $paged_blogs[$i]->latest_post->images = $images;
     772                                }
    569773                        }
    570774                }
    571775
    class BP_Blogs_Blog { 
    622826
    623827                return $user_blog;
    624828        }
     829
     830        /**
     831         * List the User ids who are contributors or subscribers of the site.
     832         * If the detail parameter is set to true, this list will be organized
     833         * according to the contribution "power" of users.
     834         *
     835         * @since  2.7.0
     836         *
     837         * @param  int         $blog_id         The blog ID to get users for.
     838         * @param  int|null    $is_contributor  Get only contributors (1) or subscribers (0).
     839         * @param  string|null $order           Null for no order, DESC or ASC.
     840         * @return array                 The list of users of the blog
     841         */
     842        public static function get_site_user_ids( $blog_id, $is_contributor = null, $order = null ) {
     843                global $wpdb;
     844
     845                $bp = buddypress();
     846
     847                $sql = array(
     848                        'select' => "SELECT user_id, is_contributor FROM {$bp->blogs->table_name}",
     849                        'where'  => array(
     850                                'blog_id' => $wpdb->prepare( 'blog_id = %d', $blog_id ),
     851                        ),
     852                );
     853
     854                if ( ! is_null( $is_contributor ) ) {
     855                        $sql['where']['is_contributor'] = $wpdb->prepare( 'is_contributor = %d', $is_contributor );
     856                }
     857
     858                if ( 'DESC' === $order || 'ASC' === $order ) {
     859                        $sql['order'] = sprintf( 'ORDER BY id %s', $order );
     860                }
     861
     862                $sql['where'] = 'WHERE ' . join( ' AND ', $sql['where'] );
     863                $query        = join( ' ', $sql );
     864
     865                return $wpdb->get_results( $query, OBJECT_K );
     866        }
     867
     868        /**
     869         * Returns the number of recorded Users for a blog
     870         *
     871         * @since  2.7.0
     872         *
     873         * @param  int $blog_id The blog ID to get the users count for.
     874         * @return int          The number of users.
     875         */
     876        public static function get_site_users_count( $blog_id ) {
     877                global $wpdb;
     878
     879                $bp = buddypress();
     880
     881                $users_count = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT( user_id ) FROM {$bp->blogs->table_name} WHERE blog_id = %d", $blog_id ) );
     882
     883                if ( empty( $users_count ) ) {
     884                        return false;
     885                }
     886
     887                return (int) $users_count;
     888        }
    625889}
  • src/bp-blogs/classes/class-bp-blogs-component.php

    diff --git src/bp-blogs/classes/class-bp-blogs-component.php src/bp-blogs/classes/class-bp-blogs-component.php
    index 69dfe37..e956716 100644
    class BP_Blogs_Component extends BP_Component { 
    3131                        buddypress()->plugin_dir,
    3232                        array(
    3333                                'adminbar_myaccount_order' => 30,
    34                                 'search_query_arg' => 'sites_search',
     34                                'search_query_arg'         => 'sites_search',
     35                                'features'                 => array( 'site' ),
    3536                        )
    3637                );
    3738        }
    class BP_Blogs_Component extends BP_Component { 
    106107                                add_post_type_support( $post_type, 'buddypress-activity' );
    107108                        }
    108109                }
     110
     111                /** Single Site globals *******************************************************/
     112
     113                if ( is_multisite() && bp_is_blogs_component() && bp_current_action() && bp_is_active( $this->id, 'site' ) ) {
     114                        // Initialize a global placeholder for the site.
     115                        $this->site           = new stdClass;
     116                        $this->site->settings = array();
     117
     118                        // Set the current Site object
     119                        if ( bp_is_current_action( bp_blogs_get_root_site_slug() ) ) {
     120                                $this->current_site = bp_blogs_get_site( bp_get_root_blog_id() );
     121                        } else {
     122                                $this->current_site = bp_blogs_get_site( bp_current_action() );
     123                        }
     124
     125                        if ( empty( $this->current_site->blog_id ) ) {
     126                                $this->current_site = 0;
     127                                return;
     128                        }
     129
     130                        // It's a single Site
     131                        $bp->is_single_item  = true;
     132                        $bp->current_item    = $this->current_site->slug;
     133                        $bp->current_action  = bp_action_variable( 0 );
     134                        array_shift( $bp->action_variables );
     135
     136                        if ( is_super_admin() || $this->current_site->is_admin ) {
     137                                bp_update_is_item_admin( true, $bp->blogs->id );
     138                        }
     139
     140                        // By Default grant access
     141                        $this->current_site->user_has_access = true;
     142
     143                        // If the site is not public, non members can't access
     144                        if ( ! $this->current_site->public && ! $this->current_site->is_member && ! bp_is_item_admin() ) {
     145                                $this->current_site->user_has_access = false;
     146                        }
     147
     148                        // Check once if the current site has a custom front template
     149                        $this->current_site->front_template = bp_blogs_get_site_front_template( $this->current_site );
     150
     151                        // Initialize the nav for the current site.
     152                        $this->nav = new BP_Core_Nav( $this->current_site->blog_id );
     153
     154                        // Add the id property, so that it's easier for the cover image
     155                        $this->current_site->id = (int) $this->current_site->blog_id;
     156
     157                        /**
     158                         * Hook here to add your custom globals for the site feature.
     159                         * Use it to add specific settings using bp_blogs_register_site_settings()
     160                         *
     161                         * @since  2.7.0
     162                         *
     163                         * @param  int $value The current site id.
     164                         */
     165                        do_action( "bp_{$this->id}_setup_site_globals", $this->current_site->blog_id );
     166
     167                // Set current_site to 0 to prevent debug errors.
     168                } else {
     169                        $this->current_site = 0;
     170                }
     171        }
     172
     173        /**
     174         * Set up canonical stack for this component.
     175         *
     176         * @since 2.7.0
     177         */
     178        public function setup_canonical_stack() {
     179                $bp = buddypress();
     180
     181                if ( ! bp_is_blogs_component() ) {
     182                        return;
     183                }
     184
     185                if ( empty( $this->current_site ) ) {
     186                        return;
     187                }
     188
     189                if ( ! bp_current_action() ) {
     190                        $bp->current_action = 'home';
     191                }
     192
     193                // Prepare for a redirect to the canonical URL
     194                $bp->canonical_stack['base_url'] = bp_blogs_get_site_community_url( $this->current_site->slug );
     195
     196                if ( bp_current_action() ) {
     197                        $bp->canonical_stack['action'] = bp_current_action();
     198                }
     199
     200                if ( ! empty( $bp->action_variables ) ) {
     201                        $bp->canonical_stack['action_variables'] = bp_action_variables();
     202                }
     203
     204                /**
     205                 * When viewing the default extension, the canonical URL should not have
     206                 * that extension's slug, unless more has been tacked onto the URL via
     207                 * action variables
     208                 */
     209                if ( bp_is_current_action( 'home' ) && empty( $bp->action_variables ) )  {
     210                        unset( $bp->canonical_stack['action'] );
     211                }
    109212        }
    110213
    111214        /**
    class BP_Blogs_Component extends BP_Component { 
    137240
    138241                if ( is_multisite() ) {
    139242                        $includes[] = 'widgets';
     243
     244                        // Conditional includes
     245                        if ( bp_is_active( $this->id, 'site' ) ) {
     246                                $includes[] = 'site';
     247                        }
    140248                }
    141249
    142250                // Include the files.
    class BP_Blogs_Component extends BP_Component { 
    144252        }
    145253
    146254        /**
    147          * Set up component navigation for bp-blogs.
     255         * Set up component navigation for bp-blogs and for the Site's feature.
    148256         *
    149257         * @see BP_Component::setup_nav() for a description of arguments.
    150258         *
    class BP_Blogs_Component extends BP_Component { 
    170278                } elseif ( bp_loggedin_user_domain() ) {
    171279                        $user_domain = bp_loggedin_user_domain();
    172280                } else {
    173                         return;
     281                        $user_domain = false;
    174282                }
    175283
    176                 $slug       = bp_get_blogs_slug();
    177                 $parent_url = trailingslashit( $user_domain . $slug );
    178 
    179                 // Add 'Sites' to the main navigation.
    180                 $count    = (int) bp_get_total_blog_count_for_user();
    181                 $class    = ( 0 === $count ) ? 'no-count' : 'count';
    182                 $nav_text = sprintf(
    183                         /* translators: %s: Site count for the current user */
    184                         __( 'Sites %s', 'buddypress' ),
    185                         sprintf(
    186                                 '<span class="%s">%s</span>',
    187                                 esc_attr( $class ),
    188                                 bp_core_number_format( $count )
    189                         )
    190                 );
    191                 $main_nav = array(
    192                         'name'                => $nav_text,
    193                         'slug'                => $slug,
    194                         'position'            => 30,
    195                         'screen_function'     => 'bp_blogs_screen_my_blogs',
    196                         'default_subnav_slug' => 'my-sites',
    197                         'item_css_id'         => $this->id
    198                 );
     284                if ( ! empty( $user_domain ) ) {
     285                        $slug       = bp_get_blogs_slug();
     286                        $parent_url = trailingslashit( $user_domain . $slug );
     287
     288                        // Add 'Sites' to the main navigation.
     289                        $count    = (int) bp_get_total_blog_count_for_user();
     290                        $class    = ( 0 === $count ) ? 'no-count' : 'count';
     291                        $nav_text = sprintf(
     292                                /* translators: %s: Site count for the current user */
     293                                __( 'Sites %s', 'buddypress' ),
     294                                sprintf(
     295                                        '<span class="%s">%s</span>',
     296                                        esc_attr( $class ),
     297                                        bp_core_number_format( $count )
     298                                )
     299                        );
     300                        $main_nav = array(
     301                                'name'                => $nav_text,
     302                                'slug'                => $slug,
     303                                'position'            => 30,
     304                                'screen_function'     => 'bp_blogs_screen_my_blogs',
     305                                'default_subnav_slug' => 'my-sites',
     306                                'item_css_id'         => $this->id
     307                        );
    199308
    200                 $sub_nav[] = array(
    201                         'name'            => __( 'My Sites', 'buddypress' ),
    202                         'slug'            => 'my-sites',
    203                         'parent_url'      => $parent_url,
    204                         'parent_slug'     => $slug,
    205                         'screen_function' => 'bp_blogs_screen_my_blogs',
    206                         'position'        => 10
    207                 );
     309                        $sub_nav[] = array(
     310                                'name'            => __( 'My Sites', 'buddypress' ),
     311                                'slug'            => 'my-sites',
     312                                'parent_url'      => $parent_url,
     313                                'parent_slug'     => $slug,
     314                                'screen_function' => 'bp_blogs_screen_my_blogs',
     315                                'position'        => 10
     316                        );
     317
     318                        if ( bp_blogs_is_site_subscriptions_active() ) {
     319                                $sub_nav[] = array(
     320                                        'name'            => __( 'My Subscriptions', 'buddypress' ),
     321                                        'slug'            => 'my-subscriptions',
     322                                        'parent_url'      => $parent_url,
     323                                        'parent_slug'     => $slug,
     324                                        'screen_function' => 'bp_blogs_screen_my_blogs',
     325                                        'position'        => 20
     326                                );
     327                        }
     328                }
    208329
    209330                // Setup navigation.
    210331                parent::setup_nav( $main_nav, $sub_nav );
     332
     333                // Build the Site navigation
     334                if ( bp_is_blogs_component() && bp_is_single_item() ) {
     335
     336                        /** Set the Primary Navigation of the Site ************************************/
     337
     338                        /**
     339                         * Use this filter to add your public primary nav items.
     340                         *
     341                         * NB: Make sure to use a position greater than 20 for your
     342                         * custom items.
     343                         *
     344                         * @since  2.7.0
     345                         *
     346                         * @param array  $site_main_nav The list of public nav items.
     347                         * @param object $value         The current site displayed.
     348                         */
     349                        $site_main_nav = apply_filters( 'bp_blogs_setup_site_public_primary_nav', array( 'site_home' => array(
     350                                        'name'                => __( 'Home', 'buddypress' ),
     351                                        'slug'                => 'home',
     352                                        'position'            => 0,
     353                                        'screen_function'     => 'bp_blogs_screen_site_home',
     354                                        'default_subnav_slug' => false,
     355                                ),
     356                        ), $this->current_site );
     357
     358                        if ( bp_blogs_current_site_has_access() ) {
     359                                // Fix the scope for Ajax filtering when members is the home page
     360                                $site_main_nav['site_home']['item_css_id'] = 'members';
     361
     362                                if ( $this->current_site->front_template || ( bp_is_active( 'activity' ) && bp_blogs_current_site_is_public() ) ) {
     363                                        /**
     364                                         * Only add the members nav if it's not the home's nav
     365                                         */
     366                                        $site_main_nav[] = array(
     367                                                'name'                => sprintf( _x( 'Members <span>%s</span>', 'Single Site members screen nav', 'buddypress' ), $this->current_site->total_users ),
     368                                                'slug'                => 'members',
     369                                                'position'            => 20,
     370                                                'screen_function'     => 'bp_blogs_screen_site_home',
     371                                                'default_subnav_slug' => false,
     372                                        );
     373
     374                                        // Default scope is home
     375                                        $site_main_nav['site_home']['item_css_id'] = 'home';
     376
     377                                        /**
     378                                         * If the theme is using a custom front, create
     379                                         * an activity nav if the site is public
     380                                         */
     381                                        if ( $this->current_site->front_template && bp_is_active( 'activity' ) && bp_blogs_current_site_is_public() ) {
     382                                                $site_main_nav[] = array(
     383                                                        'name'                => _x( 'Activity', 'Single Site activity screen nav', 'buddypress' ),
     384                                                        'slug'                => 'activity',
     385                                                        'position'            => 10,
     386                                                        'screen_function'     => 'bp_blogs_screen_site_home',
     387                                                        'default_subnav_slug' => false,
     388                                                );
     389                                        }
     390                                }
     391
     392                                // Manage Main nav
     393                                $site_main_nav[] = array(
     394                                        'name'                => _x( 'Manage', 'Single Blog manage screen nav', 'buddypress' ),
     395                                        'slug'                => 'manage',
     396                                        'position'            => 1000,
     397                                        'screen_function'     => 'bp_blogs_screen_site_manage',
     398                                        'default_subnav_slug' => 'settings',
     399                                        'site_admin_only'     => ! bp_is_item_admin(),
     400                                );
     401
     402                                /**
     403                                 * Use this filter to add your restricted primary nav items.
     404                                 *
     405                                 * NB: Make sure to use a position greater than 20 for your
     406                                 * custom items.
     407                                 *
     408                                 * @since  2.7.0
     409                                 *
     410                                 * @param array  $site_main_nav The list of restricted nav items.
     411                                 * @param object $value         The current site displayed.
     412                                 */
     413                                $site_main_nav = apply_filters( 'bp_blogs_setup_site_restricted_primary_nav', $site_main_nav, $this->current_site );
     414                        }
     415
     416                        // Loop in nav items to create the primary nav.
     417                        foreach ( $site_main_nav as $nav_item ) {
     418                                bp_core_new_nav_item( $nav_item, 'blogs' );
     419                        }
     420
     421                        /** Set the secondary navigation of the Site **********************************/
     422
     423                        $site_link = bp_blogs_get_site_community_url( $this->current_site->slug );
     424
     425                        /**
     426                         * General settings
     427                         *
     428                         * Edit the preferences for the current site.
     429                         * Access is restricted to The site admins.
     430                         */
     431                        bp_core_new_subnav_item( array(
     432                                'name'              => _x( 'Settings', 'Single Blog setting screen', 'buddypress' ),
     433                                'slug'              => 'settings',
     434                                'parent_url'        => trailingslashit( $site_link . 'manage' ),
     435                                'parent_slug'       => 'manage',
     436                                'screen_function'   => 'bp_blogs_screen_site_manage',
     437                                'position'          => 0,
     438                                'user_has_access'   => bp_is_item_admin(),
     439                                'no_access_url'     => $site_link,
     440                                'show_in_admin_bar' => true,
     441                        ), 'blogs' );
     442
     443                        /**
     444                         * Site's Profile Photo
     445                         *
     446                         * Edit the logo for the current site.
     447                         * Access is restricted to the site admins.
     448                         */
     449                        if ( bp_blogs_is_site_avatar_uploads_enabled() ) {
     450                                bp_core_new_subnav_item( array(
     451                                        'name'              => _x( 'Profile Photo', 'Single Site edit photo screen', 'buddypress' ),
     452                                        'slug'              => 'edit-avatar',
     453                                        'parent_url'        => trailingslashit( $site_link . 'manage' ),
     454                                        'parent_slug'       => 'manage',
     455                                        'screen_function'   => 'bp_blogs_screen_site_manage',
     456                                        'position'          => 10,
     457                                        'user_has_access'   => bp_is_item_admin(),
     458                                        'no_access_url'     => $site_link,
     459                                        'show_in_admin_bar' => true,
     460                                ), 'blogs' );
     461                        }
     462
     463                        /**
     464                         * @todo Site's Cover Image
     465                         *
     466                         * Edit the cover image for the current site.
     467                         * Access is restricted to the site admins.
     468                         */
     469                        if ( bp_site_use_cover_image_header() ) {
     470                                bp_core_new_subnav_item( array(
     471                                        'name'              => _x( 'Cover Image', 'Single Blog setting screen', 'buddypress' ),
     472                                        'slug'              => 'edit-cover-image',
     473                                        'parent_url'        => trailingslashit( $site_link . 'manage' ),
     474                                        'parent_slug'       => 'manage',
     475                                        'screen_function'   => 'bp_blogs_screen_site_manage',
     476                                        'position'          => 20,
     477                                        'user_has_access'   => bp_is_item_admin(),
     478                                        'no_access_url'     => $site_link,
     479                                        'show_in_admin_bar' => true,
     480                                ), 'blogs' );
     481                        }
     482
     483                        if ( bp_blogs_current_site_can_subscribe() ) {
     484                                /**
     485                                 * Manage members.
     486                                 *
     487                                 * Eventually remove subscriptions.
     488                                 */
     489                                bp_core_new_subnav_item( array(
     490                                        'name'              => _x( 'Members', 'Single Site manage members screen', 'buddypress' ),
     491                                        'slug'              => 'members',
     492                                        'parent_url'        => trailingslashit( $site_link . 'manage' ),
     493                                        'parent_slug'       => 'manage',
     494                                        'screen_function'   => 'bp_blogs_screen_site_manage',
     495                                        'position'          => 30,
     496                                        'user_has_access'   => bp_is_item_admin(),
     497                                        'no_access_url'     => $site_link,
     498                                        'show_in_admin_bar' => true,
     499                                ), 'blogs' );
     500                        }
     501                }
     502
     503                /**
     504                 * Use this action to add your custom secondary nav items.
     505                 *
     506                 * NB: Make sure to use the parent slug of the primary nav item
     507                 * you defined filtering `bp_blogs_setup_site_public_primary_nav`
     508                 * or `bp_blogs_setup_site_restricted_primary_nav`.
     509                 *
     510                 * @since  2.7.0
     511                 *
     512                 * @param array  $site_main_nav The list of restricted nav items.
     513                 * @param object $value         The current site displayed.
     514                 */
     515                do_action( 'bp_blogs_setup_site_secondary_nav', $this->current_site );
    211516        }
    212517
    213518        /**
    class BP_Blogs_Component extends BP_Component { 
    255560                                'position' => 10
    256561                        );
    257562
     563                        if ( bp_blogs_is_site_subscriptions_active() ) {
     564                                $wp_admin_nav[] = array(
     565                                        'parent' => 'my-account-' . $this->id,
     566                                        'id'     => 'my-account-' . $this->id . '-my-subscriptions',
     567                                        'title'  => __( 'My Subscriptions', 'buddypress' ),
     568                                        'href'   => trailingslashit( $blogs_link . 'my-subscriptions' )
     569                                );
     570                        }
     571
    258572                        // Create a Site.
    259573                        if ( bp_blog_signup_enabled() ) {
    260574                                $wp_admin_nav[] = array(
    class BP_Blogs_Component extends BP_Component { 
    286600
    287601                        // If we are not viewing the logged in user, set up the current
    288602                        // users avatar and name.
    289                         } else {
     603                        } elseif ( ! bp_is_my_profile() && ! bp_is_single_item() ) {
    290604                                $bp->bp_options_avatar = bp_core_fetch_avatar( array(
    291605                                        'item_id' => bp_displayed_user_id(),
    292606                                        'type'    => 'thumb',
    293607                                        'alt'     => sprintf( __( 'Profile picture of %s', 'buddypress' ), bp_get_displayed_user_fullname() )
    294608                                ) );
    295609                                $bp->bp_options_title = bp_get_displayed_user_fullname();
     610
     611                        // Viewing a single site.
     612                        } elseif ( bp_is_single_item() ) {
     613                                $bp->bp_options_title  = $this->current_site->name;
     614                                $bp->bp_options_avatar = bp_core_fetch_avatar( array(
     615                                        'item_id'    => $this->current_site->blog_id,
     616                                        'object'     => 'blogs',
     617                                        'type'       => 'thumb',
     618                                        'avatar_dir' => 'blog-avatars',
     619                                        'alt'        => __( 'Site Profile Logo', 'buddypress' )
     620                                ) );
     621
     622                                if ( empty( $bp->bp_options_avatar ) ) {
     623                                        $bp->bp_options_avatar = '<img src="' . esc_url( bp_core_avatar_default_thumb() ) . '" alt="' . esc_attr__( 'No Site Profile Photo', 'buddypress' ) . '" class="avatar" />';
     624                                }
    296625                        }
    297626                }
    298627
    class BP_Blogs_Component extends BP_Component { 
    305634         * @since 2.2.0
    306635         */
    307636        public function setup_cache_groups() {
     637                $cache_group = array( 'blog_meta' );
     638
     639                if ( bp_is_active( 'blogs', 'site' ) ) {
     640                        $cache_group = array_merge( $cache_group, array(
     641                                'bp_site',
     642                                'bp_site_slugs',
     643                        ) );
     644                }
    308645
    309646                // Global groups.
    310                 wp_cache_add_global_groups( array(
    311                         'blog_meta'
    312                 ) );
     647                wp_cache_add_global_groups( $cache_group );
    313648
    314649                parent::setup_cache_groups();
    315650        }
  • src/bp-blogs/classes/class-bp-blogs-template.php

    diff --git src/bp-blogs/classes/class-bp-blogs-template.php src/bp-blogs/classes/class-bp-blogs-template.php
    index b203c89..710d869 100644
    class BP_Blogs_Template { 
    9696         * @param bool       $update_meta_cache Whether to pre-fetch metadata for
    9797         *                                      queried blogs.
    9898         * @param array|bool $include_blog_ids  Array of blog IDs to include.
     99         * @param int        $is_contributor    Whether to get sites user is at least a contributor (1)
     100         *                                      or the sites he subscribed to (0). Default: 1.
    99101         */
    100         public function __construct( $type, $page, $per_page, $max, $user_id, $search_terms, $page_arg = 'bpage', $update_meta_cache = true, $include_blog_ids = false ) {
     102        public function __construct( $type, $page, $per_page, $max, $user_id, $search_terms, $page_arg = 'bpage', $update_meta_cache = true, $include_blog_ids = false, $is_contributor = 1 ) {
    101103
    102104                $this->pag_arg  = sanitize_key( $page_arg );
    103105                $this->pag_page = bp_sanitize_pagination_arg( $this->pag_arg, $page     );
    class BP_Blogs_Template { 
    117119                                'search_terms'      => $search_terms,
    118120                                'update_meta_cache' => $update_meta_cache,
    119121                                'include_blog_ids'  => $include_blog_ids,
     122                                'is_contributor'    => $is_contributor,
    120123                        ) );
    121124                }
    122125
  • src/bp-blogs/classes/class-bp-blogs-theme-compat.php

    diff --git src/bp-blogs/classes/class-bp-blogs-theme-compat.php src/bp-blogs/classes/class-bp-blogs-theme-compat.php
    index 04623e5..2af4110 100644
    class BP_Blogs_Theme_Compat { 
    3232        /**
    3333         * Are we looking at something that needs Blogs theme compatibility?
    3434         *
    35          * @since 1.7.0
     35         * @since  1.7.0
     36         * @since  2.7.0 Add the site's feature theme compat.
    3637         */
    3738        public function is_blogs() {
    3839
    3940                // Bail if not looking at a group.
    40                 if ( ! bp_is_blogs_component() )
     41                if ( ! bp_is_blogs_component() ) {
    4142                        return;
     43                }
    4244
    4345                // Bail if looking at a users sites.
    44                 if ( bp_is_user() )
     46                if ( bp_is_user() ) {
    4547                        return;
     48                }
    4649
    4750                // Blog Directory.
    48                 if ( is_multisite() && ! bp_current_action() ) {
     51                if ( is_multisite() && ! bp_current_action() && ! bp_current_item() ) {
    4952                        bp_update_is_directory( true, 'blogs' );
    5053
    5154                        /**
    class BP_Blogs_Theme_Compat { 
    6164                        add_filter( 'bp_replace_the_content',                    array( $this, 'directory_content'    ) );
    6265
    6366                // Create blog.
    64                 } elseif ( is_user_logged_in() && bp_blog_signup_enabled() ) {
     67                } elseif ( is_user_logged_in() && bp_blog_signup_enabled() && bp_is_create_blog() ) {
    6568                        add_filter( 'bp_get_buddypress_template',                array( $this, 'create_template_hierarchy' ) );
    6669                        add_action( 'bp_template_include_reset_dummy_post_data', array( $this, 'create_dummy_post' ) );
    6770                        add_filter( 'bp_replace_the_content',                    array( $this, 'create_content'    ) );
     71
     72                // Single site
     73                } elseif ( bp_is_single_item() ) {
     74                        add_filter( 'bp_get_buddypress_template',                array( $this, 'single_template_hierarchy' ) );
     75                        add_action( 'bp_template_include_reset_dummy_post_data', array( $this, 'single_dummy_post' ) );
     76                        add_filter( 'bp_replace_the_content',                    array( $this, 'single_content'    ) );
    6877                }
    6978        }
    7079
    class BP_Blogs_Theme_Compat { 
    198207        public function create_content() {
    199208                return bp_buffer_template_part( 'blogs/create', null, false );
    200209        }
     210
     211        /** Single ************************************************************/
     212
     213        /**
     214         * Add custom template hierarchy to theme compat for single site pages.
     215         *
     216         * This is to mirror how WordPress has
     217         * {@link https://codex.wordpress.org/Template_Hierarchy template hierarchy}.
     218         *
     219         * @since 2.7.0
     220         *
     221         * @param string $templates The templates from bp_get_theme_compat_templates().
     222         * @return array $templates Array of custom templates to look for.
     223         */
     224        public function single_template_hierarchy( $templates ) {
     225                // Setup some variables we're going to reference in our custom templates
     226                $site = bp_blogs_get_current_site();
     227
     228                /**
     229                 * Filters the single site pages template hierarchy based on priority.
     230                 *
     231                 * @since 2.7.0
     232                 *
     233                 * @param array $value Array of default template files to use.
     234                 */
     235                $new_templates = apply_filters( 'bp_template_hierarchy_blogs_single_item', array(
     236                        'blogs/single/index-id-'     . sanitize_file_name( $site->blog_id )      . '.php',
     237                        'blogs/single/index-slug-'   . sanitize_file_name( $site->slug )         . '.php',
     238                        'blogs/single/index-action-' . sanitize_file_name( bp_current_action() ) . '.php',
     239                        'blogs/single/index.php'
     240                ) );
     241
     242                // Merge new templates with existing stack
     243                // @see bp_get_theme_compat_templates()
     244                $templates = array_merge( (array) $new_templates, $templates );
     245
     246                return $templates;
     247        }
     248
     249        /**
     250         * Update the global $post with single blog data.
     251         *
     252         * @since 2.7.0
     253         */
     254        public function single_dummy_post() {
     255                bp_theme_compat_reset_post( array(
     256                        'ID'             => 0,
     257                        'post_title'     => bp_blogs_get_current_site_name(),
     258                        'post_author'    => 0,
     259                        'post_date'      => 0,
     260                        'post_content'   => '',
     261                        'post_type'      => 'page',
     262                        'post_status'    => 'publish',
     263                        'is_page'        => true,
     264                        'comment_status' => 'closed'
     265                ) );
     266        }
     267
     268        /**
     269         * Filter the_content with the single blog template part.
     270         *
     271         * @since 2.7.0
     272         */
     273        public function single_content() {
     274                return bp_buffer_template_part( 'blogs/single/home', null, false );
     275        }
    201276}
  • src/bp-blogs/classes/class-bp-site-query.php

    diff --git src/bp-blogs/classes/class-bp-site-query.php src/bp-blogs/classes/class-bp-site-query.php
    index e69de29..7ca74e0 100644
     
     1<?php
     2/**
     3 * BuddyPress Blogs Classes.
     4 *
     5 * @package BuddyPress
     6 * @subpackage BlogsClasses
     7 * @since 2.7.0
     8 */
     9
     10// Exit if accessed directly.
     11defined( 'ABSPATH' ) || exit;
     12
     13/**
     14 * BuddyPress class used for querying sites.
     15 *
     16 * @since 2.7.0
     17 *
     18 * @see BP_Site_Query::__construct() for accepted arguments.
     19 */
     20class BP_Site_Query extends WP_Site_Query {
     21
     22        /**
     23         * Get sites of a network according to a given request.
     24         *
     25         * @since  2.7.0
     26         *
     27         * @access public
     28         *
     29         * @param string|array $query {
     30         *     Optional. Array or query string of site query parameters. Default empty.
     31         *     @see WP_Site_Query::__construct() for WordPress arguments.
     32         *     Below are arguments specific to BuddyPress.
     33         *
     34         *     @type int         $user_id        Optional. ID of the user whose blogs are being
     35         *                                       retrieved. Default: 0.
     36         *     @type string|bool $search_terms   Optional. Search by text stored in
     37         *                                       blogmeta (such as the blog name). Default: false.
     38         * }
     39         */
     40        public function __construct( $query = '' ) {
     41                // Set filters.
     42                $this->set_filters();
     43
     44                // Set defaults query vars.
     45                parent::__construct();
     46
     47                // Set BuddyPress specific query vars.
     48                $this->set_bp_query( $query );
     49
     50                // If sites are not already set, run the query
     51                if ( ! isset( $this->sites ) ) {
     52                        // Get the matching sites
     53                        $this->get_sites();
     54
     55                        // Get extra data for each found sites.
     56                        $this->get_site_extras();
     57                }
     58        }
     59
     60        /**
     61         * Set custom filters to edit WordPress query
     62         *
     63         * @since  2.7.0
     64         *
     65         * @access private
     66         */
     67        private function set_filters() {
     68                add_filter( 'sites_clauses', array( $this, 'edit_query' ), 10, 1 );
     69        }
     70
     71        /**
     72         * Get sites of a network according to a given request.
     73         *
     74         * @since  2.7.0
     75         *
     76         * @access private
     77         *
     78         * @param string|array $query Array or string of BP_Site_Query arguments. See BP_Site_Query::__construct().
     79         */
     80        private function set_bp_query( $query = '' ) {
     81                $this->query_vars = wp_parse_args( $query, array(
     82                        'offset'   => 0,
     83                        'number'   => 20,
     84                        /**
     85                         * Make sure to not display
     86                         * the following site status:
     87                         */
     88                        'mature'   => 0,
     89                        'spam'     => 0,
     90                        'archived' => 0,
     91                        'deleted'  => 0,
     92                ) );
     93
     94                // Get total for loop queries.
     95                if ( empty( $this->query_vars['single_site'] ) ) {
     96                        $this->query_vars['no_found_rows'] = false;
     97                }
     98
     99                /**
     100                 * Use the WP_Site_Query 'site__in' argument to limit fetched sites to the ones the user
     101                 * is a contributor or a subscriber of.
     102                 */
     103                if ( ! empty( $this->query_vars['user_id'] ) ) {
     104                        $is_contributor = null;
     105
     106                        // This way `null` can be used to get all contribution types.
     107                        if ( isset( $this->query_vars['is_contributor'] ) && ! is_null( $this->query_vars['is_contributor'] ) ) {
     108                                $is_contributor = (int) $this->query_vars['is_contributor'];
     109                        }
     110
     111                        $user_sites = BP_Blogs_Blog::get_blog_ids_for_user( $this->query_vars['user_id'], $is_contributor );
     112
     113                        if ( empty( $user_sites ) ) {
     114                                $this->sites       = array();
     115                                $this->found_sites = 0;
     116                                return;
     117                        }
     118
     119                        if ( ! empty( $this->query_vars['site__in'] ) ) {
     120                                $intersect = array_intersect( $user_sites, $this->query_vars['site__in'] );
     121
     122                                if ( ! empty( $intersect ) ) {
     123                                        $user_sites = $intersect;
     124                                }
     125                        }
     126
     127                        $this->query_vars['site__in'] = $user_sites;
     128                }
     129
     130                /**
     131                 * In case of a search, build a Meta Query to look inside 'name' and
     132                 * 'description' metadatas.
     133                 */
     134                if ( ! empty( $this->query_vars['search_terms'] ) ) {
     135                        $this->query_vars['meta_query'] = array(
     136                                'relation' => 'OR',
     137                                array(
     138                                        'key'     => 'name',
     139                                        'value'   => $this->query_vars['search_terms'],
     140                                        'compare' => 'LIKE',
     141                                ),
     142                                array(
     143                                        'key'     => 'description',
     144                                        'value'   => $this->query_vars['search_terms'],
     145                                        'compare' => 'LIKE',
     146                                ),
     147                        );
     148                }
     149        }
     150
     151        /**
     152         * Only get blogmeta without caching results.
     153         *
     154         * @since  2.7.0
     155         *
     156         * @access private
     157         *
     158         * @param  int   $site_id The site ID
     159         * @return array          The list of blogmeta for the requested site.
     160         */
     161        private function get_blogmeta_no_cache( $site_id = 0 ) {
     162                global $wpdb;
     163                $return = array();
     164
     165                if ( empty( $site_id ) ) {
     166                        return $return;
     167                }
     168
     169                $blogmeta_table = buddypress()->blogs->table_name_blogmeta;
     170
     171                $metas = $wpdb->get_results( $wpdb->prepare( "SELECT meta_key, meta_value FROM {$blogmeta_table} WHERE blog_id = %d", $site_id ), ARRAY_A );
     172
     173                foreach( $metas as $row ) {
     174                        if ( ! isset( $return[ $row['meta_key'] ] ) ) {
     175                                $return[ $row['meta_key'] ] = array( $row['meta_value'] );
     176                        } else {
     177                                $return[ $row['meta_key'] ][] = $row['meta_value'];
     178                        }
     179                }
     180
     181                return $return;
     182        }
     183
     184        /**
     185         * Loop in found sites to attach metadatas.
     186         *
     187         * @since  2.7.0
     188         *
     189         * @access private
     190         */
     191        private function get_site_extras() {
     192                if ( is_null( $this->sites ) ) {
     193                        return;
     194                }
     195
     196                $site_ids = $this->get_ids();
     197
     198                // It can happen when the main requests is only fetching site ids.
     199                if ( empty( $site_ids ) ) {
     200                        return;
     201                }
     202
     203                $update_meta_cache = false;
     204                if ( ! empty( $this->query_vars['update_blogmeta_cache'] ) ) {
     205                        $update_meta_cache = true;
     206                }
     207
     208                $sites = array();
     209
     210                foreach ( $this->sites as $ak => $site ) {
     211
     212                        if ( $update_meta_cache ) {
     213                                $site_metas = bp_blogs_get_blogmeta( $site->blog_id );
     214                        } else {
     215                                $site_metas = $this->get_blogmeta_no_cache( $site->blog_id );
     216                        }
     217
     218                        foreach ( $site_metas as $key => $meta ) {
     219                                // Don't fetch private blogmeta
     220                                if ( is_protected_meta( $key ) ) {
     221                                        continue;
     222                                }
     223
     224                                if ( 1 === count( $meta ) ) {
     225                                        $site->{$key} = maybe_unserialize( $meta[0] );
     226                                } else {
     227                                        $site->{$key} = array_map( 'maybe_unserialize', $meta );
     228                                }
     229
     230                                // Get the first admin to make sure the user avatar will be used.
     231                                if ( 'site_admins' === $key ) {
     232                                        $site->admin_user_id = reset( $site->{$key} );
     233                                }
     234
     235                                /**
     236                                 * Attach latest post data, if not querying for a single site
     237                                 * & if the query is not including the skip_latest_post flag
     238                                 */
     239                                if ( empty( $this->query_vars['single_site'] ) && empty( $this->query_vars['skip_latest_post'] ) ) {
     240                                        $site = $this->get_latest_post( $site );
     241                                }
     242                        }
     243
     244                        // Reindex for easier matching.
     245                        $sites[ $site->blog_id ] = $site;
     246                }
     247
     248                $this->sites = $sites;
     249        }
     250
     251        /**
     252         * Attach the latest publish post to each site.
     253         *
     254         * @since  2.7.0
     255         *
     256         * @param  WP_Site $site The site object.
     257         * @return WP_Site       The site object with its latest published post.
     258         */
     259        private function get_latest_post( WP_Site $site ) {
     260                if ( empty( $site->blog_id ) ) {
     261                        return $site;
     262                }
     263
     264                switch_to_blog( $site->blog_id );
     265
     266                $latest_post = get_posts( array(
     267                        'numberposts'      => 1,
     268                        'offset'           => 0,
     269                        'orderby'          => 'post_date',
     270                        'order'            => 'DESC',
     271                        'post_type'        => 'post',
     272                        'post_status'      => 'publish',
     273                        'suppress_filters' => true,
     274                        'exclude'          => 1,
     275                ) );
     276
     277                $site->latest_post = reset( $latest_post );
     278
     279                if ( ! $site->latest_post ) {
     280                        restore_current_blog();
     281
     282                        return $site;
     283                }
     284
     285                $post_thumbnail_id = get_post_thumbnail_id( $site->latest_post );
     286                if ( ! empty( $post_thumbnail_id ) ) {
     287                        $site->latest_post->images = array();
     288
     289                        foreach( (array) get_intermediate_image_sizes() as $size ) {
     290                                $site->latest_post->images[ $size ] = wp_get_attachment_image_url( $post_thumbnail_id, $size );
     291                        }
     292                }
     293
     294                // Only keep what BuddyPress needs
     295                $fields = array_fill_keys( array(
     296                        'ID', 'post_content', 'post_title', 'post_excerpt', 'guid', 'images'
     297                ), true );
     298
     299                foreach ( $site->latest_post as $property => $value ) {
     300                        if ( ! empty( $fields[ $property ] ) ) {
     301                                continue;
     302                        }
     303
     304                        unset( $site->latest_post->{$property} );
     305                }
     306
     307                restore_current_blog();
     308
     309                return $site;
     310        }
     311
     312        /**
     313         * Edit the query to add BuddyPress custom orders or search features.
     314         *
     315         * @since  2.7.0
     316         *
     317         * @param  array  $pieces A compacted array of site query clauses.
     318         * @return array          The same/edited compacted array of site query clauses.
     319         */
     320        public function edit_query( $pieces = array() ) {
     321                global $wpdb;
     322
     323                $buddypress_orders = array(
     324                        'last_activity' => true,
     325                        'name'          => true,
     326                        'RAND()'        => true,
     327                );
     328
     329                // Bail if we don't need to edit the query
     330                if ( empty( $this->query_vars['meta_query'] ) && empty( $this->query_vars['orderby'] ) ) {
     331                        return $pieces;
     332                }
     333
     334                // There's no WordPress blogmeta table for now but it can change!
     335                if ( isset( $wpdb->blogmeta ) ) {
     336                        $reset_blogmeta = $wpdb->blogmeta;
     337                }
     338
     339                // Use the BuddyPress metadata table
     340                $wpdb->blogmeta = buddypress()->blogs->table_name_blogmeta;
     341
     342                // Add the main table name to each existing $where clauses to avoid SQL warnings.
     343                if ( ! empty( $pieces['where' ] ) && ! empty( $this->sql_clauses['where'] ) && $pieces['where'] === join( ' AND ', $this->sql_clauses['where'] ) ) {
     344                        $possible_fields = array_diff_key( $this->query_var_defaults, array(
     345                                'fields'            => false,
     346                                'number'            => false,
     347                                'offset'            => false,
     348                                'no_found_rows'     => false,
     349                                'orderby'           => false,
     350                                'order'             => false,
     351                                'search_columns'    => false,
     352                                'count'             => false,
     353                                'date_query'        => false,
     354                                'update_site_cache' => false,
     355                        ) );
     356
     357                        $sql_clauses = array();
     358                        foreach ( array_keys( $possible_fields ) as $key ) {
     359                                if ( empty( $this->sql_clauses['where'][$key] ) ) {
     360                                        continue;
     361                                }
     362
     363                                $kc = $key;
     364
     365                                if ( 0 === strpos( $key, 'site' ) ) {
     366                                        $kc = 'blog_id';
     367                                } elseif ( 0 === strpos( $key, 'network' ) ) {
     368                                        $kc = 'site_id';
     369                                }
     370
     371                                $sql_clauses[$key] = str_replace( $kc, $wpdb->blogs . '.' . $kc,  $this->sql_clauses['where'][$key] );
     372                        }
     373
     374                        if ( ! empty( $sql_clauses ) ) {
     375                                $pieces['where' ] = join( ' AND ', $sql_clauses );
     376                        }
     377                }
     378
     379                /** Meta Queries *****************************************************/
     380
     381                if ( ! empty( $this->query_vars['meta_query'] ) ) {
     382                        $meta_query = new WP_Meta_Query( $this->query_vars['meta_query'] );
     383
     384                        $parts = $meta_query->get_sql( 'blog', $wpdb->blogs, 'blog_id' );
     385
     386                        if ( 'blog_id' === $pieces['fields'] ) {
     387                                $pieces['fields'] = "{$wpdb->blogs}.blog_id";
     388                        }
     389
     390                        if ( ! empty( $parts['join'] ) ) {
     391                                if ( ! isset( $pieces['join'] ) ) {
     392                                        $pieces['join'] = $parts['join'];
     393                                } else {
     394                                        $pieces['join'] .= $parts['join'];
     395                                }
     396                        }
     397
     398                        if ( ! empty( $parts['where'] ) ) {
     399                                if ( empty( $pieces['where'] ) ) {
     400                                        $pieces['where'] = '1=1' . $parts['where'];
     401                                } else {
     402                                        $pieces['where'] .= $parts['where'];
     403                                }
     404                        }
     405                }
     406
     407                /** Custom order *****************************************************/
     408
     409                if ( ! empty( $this->query_vars['orderby'] ) ) {
     410                        // Alphabetical or active order
     411                        if ( 'name' === $this->query_vars['orderby'] || 'last_activity' === $this->query_vars['orderby'] ) {
     412                                if ( 'blog_id' === $pieces['fields'] ) {
     413                                        $pieces['fields'] = "{$wpdb->blogs}.blog_id";
     414                                }
     415
     416                                $pieces['fields'] .= sprintf( ', bm.meta_value as %s', $this->query_vars['orderby'] );
     417                                $join = " INNER JOIN {$wpdb->blogmeta} bm ON ({$wpdb->blogs}.blog_id = bm.blog_id )";
     418
     419                                if ( empty( $pieces['join'] ) ) {
     420                                        $pieces['join']  = $join;
     421                                } else {
     422                                        $pieces['join'] .= $join;
     423                                }
     424
     425                                $where = sprintf( " AND bm.meta_key = '%s'", $this->query_vars['orderby'] );
     426
     427                                if ( empty( $pieces['where'] ) ) {
     428                                        $pieces['where'] = '1=1' . $where;
     429                                } else {
     430                                        $pieces['where'] .= $where;
     431                                }
     432
     433                                $pieces['orderby'] = ' ' . $this->query_vars['orderby'] . ' ' . $this->query_vars['order'] ;
     434
     435                        // Random order
     436                        } elseif ( 'RAND()' === $this->query_vars['orderby'] ) {
     437                                $pieces['orderby'] = $this->query_vars['orderby'];
     438                        }
     439                }
     440
     441                // Reset the global blogmeta table if needed.
     442                if ( ! empty( $reset_blogmeta ) ) {
     443                        $wpdb->blogmeta = $reset_blogmeta;
     444                }
     445
     446                return $pieces;
     447        }
     448
     449        /**
     450         * Return results as BP_Blogs_Blog::get() expects it.
     451         *
     452         * @since  2.7.0
     453         *
     454         * @return array Multidimensional results array, structured as follows:
     455         *               'blogs' - Array of located blog objects.
     456         *               'total' - A count of the total blogs matching the filter params.
     457         */
     458        public function get_results() {
     459                // Single site query.
     460                if ( $this->query_vars['no_found_rows'] ) {
     461                        return array( 'blogs' => array_values( $this->sites ) );
     462                }
     463
     464                return array( 'blogs' => array_values( $this->sites ), 'total' => $this->found_sites );
     465        }
     466
     467        /**
     468         * Return the site ids found.
     469         *
     470         * @since  2.7.0
     471         *
     472         * @return array The list of site ids.
     473         */
     474        public function get_ids() {
     475                return array_map( 'intval', wp_list_pluck( $this->sites, 'blog_id' ) );
     476        }
     477}
  • src/bp-blogs/site/activity.php

    diff --git src/bp-blogs/site/activity.php src/bp-blogs/site/activity.php
    index e69de29..74aacbc 100644
     
     1<?php
     2/**
     3 * BuddyPress Blogs Site activity.
     4 *
     5 * @package BuddyPress
     6 * @subpackage BlogsSiteActivity
     7 * @since 2.7.0
     8 */
     9
     10// Exit if accessed directly.
     11defined( 'ABSPATH' ) || exit;
     12
     13/**
     14 * Register activity actions for the site subscriptions feature.
     15 *
     16 * @since 2.7.0
     17 */
     18function bp_blogs_site_register_subscription_activity_action() {
     19        if ( bp_disable_site_subscriptions() ) {
     20                return;
     21        }
     22
     23        /**
     24         * Only add subscription actions if subscription are enabled
     25         * for current blog, or when viewing the blogs activities on
     26         * a user's profile or on the activity directory
     27         */
     28        if ( ( bp_is_site() && bp_blogs_current_site_can_subscribe() ) || bp_is_user() || bp_is_activity_directory() ) {
     29                bp_activity_set_action(
     30                        buddypress()->blogs->id,
     31                        'site_subscription',
     32                        __( 'New site subscription', 'buddypress' ),
     33                        'bp_blogs_site_format_activity_action_new_subscription',
     34                        __( 'Site Subscriptions', 'buddypress' ),
     35                        array( 'activity', 'member', 'site', 'member_sites' ),
     36                        20
     37                );
     38        }
     39}
     40add_action( 'bp_blogs_register_activity_actions', 'bp_blogs_site_register_subscription_activity_action' );
     41
     42 /**
     43 * Activity action callback for new site subscriptions
     44 *
     45 * @since 2.7.0
     46 *
     47 * @param  string                    $action   The content of the action.
     48 * @param  BP_Activity_Activity|null $activity The activity object.
     49 * @return string The content of the action.
     50 */
     51function bp_blogs_site_format_activity_action_new_subscription( $action = '', $activity = null ) {
     52        if ( empty( $activity->item_id ) ) {
     53                return $action;
     54        }
     55
     56        $user_link   = bp_core_get_userlink( $activity->user_id );
     57        $blog_name   = bp_blogs_get_blogmeta( $activity->item_id, 'name' );
     58        $blog_url    = bp_blogs_get_blogmeta( $activity->item_id, 'url' );
     59        $root_url    = trailingslashit( bp_get_root_domain() );
     60        $root_domain = get_current_site()->domain;
     61        $protocol    = 'http://';
     62        if ( is_ssl() ) {
     63                $protocol = 'https://';
     64        }
     65
     66        if ( (int) $activity->item_id !== (int) get_current_site()->blog_id ) {
     67                if ( is_subdomain_install() ) {
     68                        $slug = trim( str_replace( $root_domain, '', $blog_url ), '.' );
     69                        $slug = str_replace( $protocol, '', $slug );
     70                } else {
     71                        $slug = trim( str_replace( $root_url, '', $blog_url ), '/' );
     72                }
     73
     74                $community_link = bp_blogs_get_site_community_url( $slug );
     75        } else {
     76                $community_link = bp_blogs_get_site_community_url( bp_blogs_get_root_site_slug() );
     77        }
     78
     79        $action = sprintf(
     80                __( '%1$s subscribed to the site %2$s', 'buddypress' ),
     81                $user_link,
     82                '<a href="' . esc_url( $community_link ) . '">' . esc_html( $blog_name ) . '</a>'
     83        );
     84
     85        return apply_filters( 'bp_blogs_site_format_activity_action_new_subscription', $action, $activity );
     86}
     87
     88/**
     89 * Add an activity once the user subscribed to the site.
     90 *
     91 * @since  2.7.0
     92 *
     93 * @param  int            $user_id The user id who subscribed.
     94 * @param  WP_Site|object $site    The site object he subscribed to.
     95 */
     96function bp_blogs_site_activity_user_subcribed( $user_id, $site ) {
     97        $action = sprintf(
     98                __( '%1$s subscribed to the site %2$s', 'buddypress' ),
     99                bp_core_get_userlink( $user_id ),
     100                '<a href="' . esc_url( bp_blogs_get_site_community_url( $site->slug ) ) . '">' . esc_html( $site->name ) . '</a>'
     101        );
     102
     103        bp_blogs_record_activity( array(
     104                'action'  => $action,
     105                'type'    => 'site_subscription',
     106                'item_id' => $site->blog_id,
     107        ) );
     108
     109        // Update the blog's last activity.
     110        bp_blogs_update_blogmeta( $site->blog_id, 'last_activity', bp_core_current_time() );
     111}
     112add_action( 'bp_blogs_after_site_subscribed', 'bp_blogs_site_activity_user_subcribed', 10, 2 );
     113
     114/**
     115 * Remove an activity once the user unsubscribed to the site.
     116 *
     117 * @since  2.7.0
     118 *
     119 * @param  int                $user_id The user id who unsubscribed.
     120 * @param  WP_Site|object|int $site    The site object or site ID he unsubscribed to.
     121 */
     122function bp_blogs_site_activity_user_unsubscribed( $user_id, $site ) {
     123        $site_id = 0;
     124
     125        if ( ! is_numeric( $site ) && ! empty( $site->blog_id ) ) {
     126                $site_id = $site->blog_id;
     127        } else {
     128                $site_id = $site;
     129        }
     130
     131        if ( empty( $site_id ) ) {
     132                return false;
     133        }
     134
     135        bp_blogs_delete_activity( array(
     136                'user_id' => $user_id,
     137                'item_id' => $site_id,
     138                'type'    => 'site_subscription',
     139        ) );
     140}
     141add_action( 'bp_blogs_after_site_unsubscribed',     'bp_blogs_site_activity_user_unsubscribed', 10, 2 );
     142add_action( 'bp_blogs_after_remove_user_from_site', 'bp_blogs_site_activity_user_unsubscribed', 10, 2 );
  • src/bp-blogs/site/adminbar.php

    diff --git src/bp-blogs/site/adminbar.php src/bp-blogs/site/adminbar.php
    index e69de29..f054387 100644
     
     1<?php
     2/**
     3 * BuddyPress Blogs Site adminbar.
     4 *
     5 * @package BuddyPress
     6 * @subpackage BlogsSiteAdminbar
     7 * @since 2.7.0
     8 */
     9
     10// Exit if accessed directly.
     11defined( 'ABSPATH' ) || exit;
     12
     13// Put the code for the site adminbar here!
  • src/bp-blogs/site/cache.php

    diff --git src/bp-blogs/site/cache.php src/bp-blogs/site/cache.php
    index e69de29..eb0469d 100644
     
     1<?php
     2/**
     3 * BuddyPress Blogs Site cache.
     4 *
     5 * @package BuddyPress
     6 * @subpackage BlogsSiteCache
     7 * @since 2.7.0
     8 */
     9
     10// Exit if accessed directly.
     11defined( 'ABSPATH' ) || exit;
     12
     13/**
     14 * Update the site caches.
     15 *
     16 * @since  2.7.0
     17 *
     18 * @param  WP_Site|object $site The site object.
     19 */
     20function bp_blogs_update_site_caches( $site ) {
     21        wp_cache_add( $site->blog_id, $site,          'bp_site'       );
     22        wp_cache_add( $site->slug,    $site->blog_id, 'bp_site_slugs' );
     23}
     24
     25/**
     26 * Clean all site caches
     27 *
     28 * @since 2.7.0
     29 *
     30 * @param WP_Site|object|int $site The site object or ID to be
     31 *                                 cleaned from the cache.
     32 */
     33function bp_blogs_clean_site_caches( $site ) {
     34        if ( is_numeric( $site ) ) {
     35                $site = bp_blogs_get_site( $site );
     36        }
     37
     38        if ( empty( $site->blog_id ) ) {
     39                return;
     40        }
     41
     42        wp_cache_delete( $site->blog_id, 'bp_site'       );
     43        wp_cache_delete( $site->slug,    'bp_site_slugs' );
     44
     45        /**
     46         * Fires immediately after the given site's cache is cleaned.
     47         *
     48         * @since 2.7.0
     49         *
     50         * @param int     $blog_id The Site ID.
     51         * @param WP_User $site    The Site object.
     52         */
     53        do_action( 'bp_blogs_clean_site_caches', $site->blog_id, $site );
     54}
     55add_action( 'refresh_blog_details',          'bp_blogs_clean_site_caches' );
     56add_action( 'bp_blogs_remove_blog',          'bp_blogs_clean_site_caches' );
     57add_action( 'bp_blogs_remove_data_for_blog', 'bp_blogs_clean_site_caches' );
     58add_action( 'bp_blogs_remove_blog_for_user', 'bp_blogs_clean_site_caches' );
     59
     60/**
     61 * Clean site cache on blogmeta edits.
     62 *
     63 * @since  2.7.0
     64 *
     65 * @param  int $meta_ids ID of updated metadata entry.
     66 * @param  int $site_id  ID of the site.
     67 */
     68function bp_blogs_meta_edit_clean_caches( $meta_ids, $site_id, $meta_key ) {
     69        $meta_keys = array(
     70                'name'                   => true,
     71                'description'            => true,
     72                'last_activity'          => true,
     73                'site_admins'            => true,
     74                'disallow_subscriptions' => true,
     75        );
     76
     77        if ( empty( $meta_keys[ $meta_key ] ) ) {
     78                return;
     79        }
     80
     81        bp_blogs_clean_site_caches( $site_id );
     82}
     83add_action( 'deleted_blog_meta', 'bp_blogs_meta_edit_clean_caches', 10, 3 );
     84add_action( 'updated_blog_meta', 'bp_blogs_meta_edit_clean_caches', 10, 3 );
     85
     86/**
     87 * Bust blogs caches when a user was deleted or marked as spam
     88 *
     89 * @since 2.7.0
     90 *
     91 * @param int $user_id ID of the user whose blog cache should be cleared.
     92 */
     93function bp_blogs_user_sites_clean_caches( $user_id = 0 ) {
     94        $sites = BP_Blogs_Blog::get_blog_ids_for_user( $user_id, null );
     95
     96        if ( empty( $sites ) ) {
     97                return;
     98        }
     99
     100        foreach ( $sites as $site_id ) {
     101                bp_blogs_clean_site_caches( $site_id );
     102        }
     103}
     104add_action( 'bp_blogs_before_remove_data', 'bp_blogs_user_sites_clean_caches' );
     105add_action( 'bp_blogs_restore_data',       'bp_blogs_user_sites_clean_caches' );
     106
     107/**
     108 * Bust blog caches when a user subcribes or unsubscribe to a site
     109 *
     110 * @since 2.7.0
     111 *
     112 * @param int            $user_id ID of the user.
     113 * @param WP_Site|object $site    The site object.
     114 */
     115function bp_blogs_subscription_site_clean_caches( $user_id, $site ) {
     116        bp_blogs_clean_site_caches( $site );
     117
     118        // Totals
     119        wp_cache_delete( 'bp_total_blogs_for_user_'              . $user_id, 'bp' );
     120        wp_cache_delete( 'bp_total_site_subscriptions_for_user_' . $user_id, 'bp' );
     121}
     122add_action( 'bp_blogs_after_site_subscribed',   'bp_blogs_subscription_site_clean_caches', 10, 2 );
     123add_action( 'bp_blogs_after_site_unsubscribed', 'bp_blogs_subscription_site_clean_caches', 10, 2 );
  • src/bp-blogs/site/filters.php

    diff --git src/bp-blogs/site/filters.php src/bp-blogs/site/filters.php
    index e69de29..b915e3a 100644
     
     1<?php
     2/**
     3 * BuddyPress Blogs Site Filters
     4 *
     5 * @package BuddyPress
     6 * @subpackage BlogsSiteFilters
     7 * @since 2.7.0
     8 */
     9
     10// Exit if accessed directly.
     11defined( 'ABSPATH' ) || exit;
     12
     13add_filter( 'bp_get_site_description',          'wptexturize'       );
     14add_filter( 'bp_get_sitename',                  'wptexturize'       );
     15add_filter( 'bp_get_site_description',          'convert_smilies'   );
     16add_filter( 'bp_get_site_description',          'convert_chars'     );
     17add_filter( 'bp_get_sitename',                  'convert_chars'     );
     18add_filter( 'bp_get_site_description',          'wpautop'           );
     19add_filter( 'bp_get_site_description',          'make_clickable', 9 );
     20add_filter( 'bp_get_sitename',                  'wp_filter_kses', 1 );
     21add_filter( 'bp_get_site_description',          'wp_filter_kses', 1 );
     22add_filter( 'bp_get_site_description',          'stripslashes'      );
     23add_filter( 'bp_get_site_description_editable', 'stripslashes'      );
     24add_filter( 'bp_get_sitename',                  'stripslashes'      );
     25add_filter( 'bp_get_site_name_editable',        'stripslashes'      );
     26
     27
     28/**
     29 * Generate the avatar upload directory path for a given site.
     30 *
     31 * @since 2.7.0
     32 *
     33 * @param int $site_id Optional. ID of the blog. Default: ID of the
     34 *        current site.
     35 * @return array
     36 */
     37function blogs_avatar_upload_dir( $site_id = 0 ) {
     38
     39        if ( empty( $site_id ) ) {
     40                $site_id = bp_blogs_get_current_site_id();
     41        }
     42
     43        $directory = 'blog-avatars';
     44        $path      = bp_core_avatar_upload_path() . '/' . $directory . '/' . $site_id;
     45        $newbdir   = $path;
     46        $newurl    = bp_core_avatar_url() . '/' . $directory . '/' . $site_id;
     47        $newburl   = $newurl;
     48        $newsubdir = '/' . $directory . '/' . $site_id;
     49
     50        /**
     51         * Filters the avatar upload directory path for a given site.
     52         *
     53         * @since 2.7.0
     54         *
     55         * @param array $value Array of parts related to the blog avatar upload directory.
     56         */
     57        return apply_filters( 'blogs_avatar_upload_dir', array(
     58                'path'    => $path,
     59                'url'     => $newurl,
     60                'subdir'  => $newsubdir,
     61                'basedir' => $newbdir,
     62                'baseurl' => $newburl,
     63                'error'   => false
     64        ) );
     65}
     66
     67/**
     68 * Eventually filters get_blogs_of_user() to make sure
     69 * subscribers marked as spam won't generate the sites
     70 * to be marked as spam too.
     71 *
     72 * @since  2.7.0
     73 */
     74function bp_blogs_site_maybe_filter_get_blogs_of_user() {
     75        $action = bp_admin_list_table_current_bulk_action();
     76
     77        if ( 'spam' !== $action || 'users-network' !== get_current_screen()->id ) {
     78                return;
     79        }
     80
     81        // Trigger the filter.
     82        bp_blogs_get_blogs_of_user_add_filters();
     83}
     84add_action( 'wpmuadminedit', 'bp_blogs_site_maybe_filter_get_blogs_of_user' );
  • src/bp-blogs/site/functions.php

    diff --git src/bp-blogs/site/functions.php src/bp-blogs/site/functions.php
    index e69de29..c03c4db 100644
     
     1<?php
     2/**
     3 * BuddyPress Blogs Site functions.
     4 *
     5 * @package BuddyPress
     6 * @subpackage BlogsSiteFunctions
     7 * @since 2.7.0
     8 */
     9
     10// Exit if accessed directly.
     11defined( 'ABSPATH' ) || exit;
     12
     13/**
     14 * Return a default slug for the main site of the network.
     15 *
     16 * @since  2.7.0
     17 *
     18 * @param  string $default The default slug for the root site
     19 * @return string          The main site's slug.
     20 */
     21function bp_blogs_get_root_site_slug( $default = 'root' ) {
     22        /**
     23         * Filters the root site's slug.
     24         *
     25         * @since 2.7.0
     26         *
     27         * @param string $default the default slug (root).
     28         */
     29        return sanitize_title( apply_filters( 'bp_blogs_get_root_site_slug', $default ) );
     30}
     31
     32/**
     33 * Get the community url for a site.
     34 *
     35 * @since  2.7.0
     36 *
     37 * @param  string $slug The slug of the site.
     38 * @return string       The community url of the site.
     39 */
     40function bp_blogs_get_site_community_url( $slug = '' ) {
     41        if ( ! $slug ) {
     42                $slug = bp_blogs_get_current_site_slug();
     43        }
     44
     45        $url = trailingslashit( bp_get_root_domain() . '/' . bp_get_blogs_root_slug() . '/' . $slug );
     46
     47        /**
     48         * Filters the site's community url.
     49         *
     50         * @since 2.7.0
     51         *
     52         * @param string $url  The community url of the site.
     53         * @param string $slug The slug of the site.
     54         */
     55        return apply_filters( 'bp_blogs_get_site_community_url', $url, $slug );
     56}
     57
     58/**
     59 * Get a single site for the requested slug or ID.
     60 *
     61 * @since  2.7.0
     62 *
     63 * @param  string|int     $slug The slug or ID of the blog
     64 * @return WP_Site|object       The site object.
     65 */
     66function bp_blogs_get_site( $slug = '' ) {
     67        if ( empty( $slug ) ) {
     68                return false;
     69        }
     70
     71        $slug = trim( $slug, '/' );
     72        $query_vars = array(
     73                'single_site' => true,
     74                'offset'      => 0,
     75                'number'      => 1,
     76        );
     77
     78        if ( is_numeric( $slug ) ) {
     79                $query_vars['ID'] = (int) $slug;
     80                $site_id          = $query_vars['ID'];
     81        } else {
     82                if ( is_subdomain_install() ) {
     83                        $query_vars['domain__in'] = array( $slug . '.' . get_current_site()->domain );
     84                } else {
     85                        $query_vars['path__in'] = array( get_current_site()->path . $slug . '/' );
     86                }
     87
     88                $site_id = wp_cache_get( $slug, 'bp_site_slugs' );
     89        }
     90
     91        // Look in the cache.
     92        if ( ! empty( $site_id ) ) {
     93                $site = wp_cache_get( $site_id, 'bp_site' );
     94        }
     95
     96        // The Site wasn't found in cache, query for it.
     97        if ( empty( $site->blog_id ) ) {
     98                if ( true === (bool) apply_filters( 'bp_blogs_use_bp_site_query', true ) && function_exists( 'get_sites' ) ) {
     99                        $queried_site = new BP_Site_Query( $query_vars );
     100                        $result = $queried_site->get_results();
     101                } else {
     102                        $result = BP_Blogs_Blog::legacy_get( $query_vars );
     103                }
     104
     105                if ( empty( $result['blogs'] ) ) {
     106                        return false;
     107                }
     108
     109                $site = reset( $result['blogs'] );
     110
     111                if ( empty( $site->blog_id ) ) {
     112                        return false;
     113                }
     114
     115                if ( ! is_a( $site, 'WP_Site' ) ) {
     116                        $bp_props = clone $site;
     117
     118                        // Reset the site so that it's a WP_Site instance
     119                        $site = get_blog_details( $site->blog_id, false );
     120
     121                        foreach ( $bp_props as $bp_prop_key => $bp_prop ) {
     122                                if ( isset( $site->{$bp_prop_key} ) ) {
     123                                        continue;
     124                                }
     125
     126                                $site->{$bp_prop_key} = $bp_prop;
     127                        }
     128
     129                        $site->site_admins = bp_blogs_get_blogmeta( $site->blog_id, 'site_admins' );
     130                        $site->url         = bp_blogs_get_blogmeta( $site->blog_id, 'url' );
     131                }
     132
     133                $site->slug = '';
     134                if ( (int) bp_get_root_blog_id() === (int) $site->blog_id ) {
     135                        $site->slug = bp_blogs_get_root_site_slug();
     136                } elseif ( is_subdomain_install() ) {
     137                        $site->slug = trim( str_replace( get_current_site()->domain, '', $site->domain ), '.' );
     138                } else {
     139                        $site->slug = trim( str_replace( get_current_site()->path, '', $site->path ), '/' );
     140                }
     141
     142                // How many users ?
     143                $site->total_users = BP_Blogs_Blog::get_site_users_count( $site->blog_id );
     144
     145                // Update Site caches.
     146                bp_blogs_update_site_caches( $site );
     147        }
     148
     149        // Bail if the site is not showable.
     150        if ( 1 === (int) $site->mature || 1 === (int) $site->spam || 1 === (int) $site->archived || 1 === (int) $site->deleted ) {
     151                return false;
     152        }
     153
     154        if ( ! bp_is_blogs_component() && ! bp_current_action() ) {
     155                return $site;
     156        }
     157
     158        // Check if we need to switch the blog.
     159        $needs_switch = ! bp_is_root_blog( (int) $site->blog_id );
     160
     161        // Check the current user caps for this site
     162        if ( $needs_switch ) {
     163                switch_to_blog( $site->blog_id );
     164        }
     165
     166        $site->is_member = current_user_can( 'read' );
     167
     168        if ( current_user_can( 'manage_options' ) ) {
     169                $site->is_admin = true;
     170        } elseif ( current_user_can( 'edit_posts' ) ) {
     171                $site->is_contributor = true;
     172        }
     173
     174        // Most of the time, there will be only one admin.
     175        if ( 1 === count( $site->site_admins ) ) {
     176                $user_id = reset( $site->site_admins );
     177                $site->admins_list = array( get_user_by( 'id', $user_id ) );
     178
     179        // NB: WordPress introduced the 'role__in' parameter in 4.4
     180        } else {
     181                $site->admins_list = get_users( array(
     182                        'include' => $site->site_admins,
     183                        'orderby' => 'ID',
     184                        'order'   => 'ASC',
     185                ) );
     186        }
     187
     188        // Login url
     189        $site->login_url = wp_login_url();
     190
     191        if ( $needs_switch ) {
     192                restore_current_blog();
     193        }
     194
     195        /**
     196         * Use this filter to add properties to the site.
     197         *
     198         * @since  2.7.0
     199         *
     200         * @param  WP_Site|object $site The site object.
     201         */
     202        return apply_filters( 'bp_blogs_get_site', $site );
     203}
     204
     205/**
     206 * Get the current site displayed.
     207 *
     208 * @since  2.7.0
     209 *
     210 * @return WP_Site|object The displayed site object.
     211 */
     212function bp_blogs_get_current_site() {
     213        $bp = buddypress();
     214
     215        $current_site = false;
     216
     217        if ( isset( $bp->blogs->current_site ) ) {
     218                $current_site = $bp->blogs->current_site;
     219        }
     220
     221        /**
     222         * Filters the Site object corresponding to the current site.
     223         *
     224         * @since 2.7.0
     225         *
     226         * @param WP_Site|object $current_site Current Site object.
     227         */
     228        return apply_filters( 'bp_blogs_get_current_site', $current_site );
     229}
     230
     231/**
     232 * Get a specific property of the current site object
     233 *
     234 * @since  2.7.0
     235 *
     236 * @param  string $property The key of the property to get.
     237 * @return mixed            The value of the property.
     238 */
     239function bp_blogs_get_current_site_property( $property = '' ) {
     240        $current_site = bp_blogs_get_current_site();
     241
     242        if ( empty( $property ) || ! isset( $current_site->{$property} ) ) {
     243                return false;
     244        }
     245
     246        /**
     247         * Dynamic Filter to edit the value of the specific property
     248         *
     249         * @since 2.7.0
     250         *
     251         * @param mixed          $value        The value of the property.
     252         * @param WP_Site|object $current_site Current Site object.
     253         */
     254        return apply_filters( "bp_blogs_current_site_{$property}", $current_site->{$property}, $current_site );
     255}
     256
     257/**
     258 * Get the current site ID.
     259 *
     260 * @since  2.7.0
     261 *
     262 * @return int The current site ID.
     263 */
     264function bp_blogs_get_current_site_id() {
     265        return (int) bp_blogs_get_current_site_property( 'blog_id' );
     266}
     267
     268/**
     269 * Get the current site name.
     270 *
     271 * @since  2.7.0
     272 *
     273 * @return string The current site name.
     274 */
     275function bp_blogs_get_current_site_name() {
     276        return esc_html( bp_blogs_get_current_site_property( 'name' ) );
     277}
     278
     279/**
     280 * Get the current site slug.
     281 *
     282 * @since  2.7.0
     283 *
     284 * @return string The current site slug.
     285 */
     286function bp_blogs_get_current_site_slug() {
     287        return sanitize_user( bp_blogs_get_current_site_property( 'slug' ) );
     288}
     289
     290/**
     291 * Get the current site url.
     292 *
     293 * @since  2.7.0
     294 *
     295 * @return string The current site url.
     296 */
     297function bp_blogs_get_current_site_url() {
     298        return esc_url( bp_blogs_get_current_site_property( 'url' ) );
     299}
     300
     301/**
     302 * Get the public property of the current site.
     303 *
     304 * @since  2.7.0
     305 *
     306 * @return bool True if the site is public. False otherwise.
     307 */
     308function bp_blogs_current_site_is_public() {
     309        return (bool) bp_blogs_get_current_site_property( 'public' );
     310}
     311
     312/**
     313 * Does the current user can access to the displayed site?
     314 *
     315 * @since  2.7.0
     316 *
     317 * @return bool True if the user can access. False otherwise.
     318 */
     319function bp_blogs_current_site_has_access() {
     320        return (bool) bp_blogs_get_current_site_property( 'user_has_access' );
     321}
     322
     323/**
     324 * Return the list of Site Admin user ids.
     325 *
     326 * @since  2.7.0
     327 *
     328 * @return array The list of Site Admin user ids.
     329 */
     330function bp_blogs_current_site_get_admins() {
     331        return (array) bp_blogs_get_current_site_property( 'site_admins' );
     332}
     333
     334/**
     335 * Can users subscribe to the site?
     336 *
     337 * @since  2.7.0
     338 *
     339 * @return bool True if subscriptions are enabled. False otherwise.
     340 */
     341function bp_blogs_current_site_can_subscribe() {
     342        if ( bp_disable_site_subscriptions() ) {
     343                return false;
     344        }
     345
     346        $can = bp_blogs_current_site_is_public();
     347
     348        if ( $can ) {
     349                $can = ! bp_blogs_get_current_site_property( 'disallow_subscriptions' );
     350        }
     351
     352        /**
     353         * Filters subscriptions setting for the site
     354         *
     355         * @since 2.7.0
     356         *
     357         * @param bool $can True if subscriptions are enabled. False otherwise.
     358         */
     359        return (bool) apply_filters( 'bp_get_site_can_subscribe', $can );
     360}
     361
     362/**
     363 * Edit the BP User Query query vars to only get the site members
     364 *
     365 * @since  2.7.0
     366 *
     367 * @param  BP_User_Query|null $site_user_query The BP User Query object
     368 */
     369function bp_blogs_set_site_user_query( BP_User_Query $site_user_query = null ) {
     370        $bp = buddypress();
     371
     372        // Bail if we're not in a site members loop.
     373        if ( empty( $bp->blogs->site->members->loop_args['blog_id'] ) ) {
     374                return;
     375        }
     376
     377        $blog_id = $bp->blogs->site->members->loop_args['blog_id'];
     378
     379        $is_contributor = null;
     380        if ( isset( $bp->blogs->site->members->loop_args['is_contributor'] ) ) {
     381                $is_contributor = $bp->blogs->site->members->loop_args['is_contributor'];
     382        }
     383
     384        $order = null;
     385        if ( 'last_joined' === $bp->blogs->site->members->loop_args['type'] ) {
     386                $order = 'DESC';
     387        } elseif ( 'first_joined' === $bp->blogs->site->members->loop_args['type'] ) {
     388                $order = 'ASC';
     389        }
     390
     391        $bp->blogs->site->members->extra = BP_Blogs_Blog::get_site_user_ids( $blog_id, $is_contributor, $order );
     392
     393        if ( empty( $bp->blogs->site->members->extra ) ) {
     394                $user_ids = array( 0 );
     395        } else {
     396                $user_ids = wp_list_pluck( $bp->blogs->site->members->extra, 'user_id' );
     397
     398                if ( ! is_null( $order ) ) {
     399                        $bp->blogs->site->members->order_by = array_merge( array( 'u.id' ), wp_parse_id_list( $user_ids ) );
     400                }
     401        }
     402
     403        // Only include site members
     404        $site_user_query->query_vars_raw['include'] = $user_ids;
     405        $site_user_query->query_vars['include']     = wp_parse_id_list( $user_ids );
     406}
     407
     408/**
     409 * Edit the order of the BP User Query clause if needed.
     410 *
     411 * @since  2.7.0
     412 *
     413 * @param  BP_User_Query|null $site_user_query The BP User Query object
     414 */
     415function bp_blogs_pre_site_user_query( BP_User_Query $site_user_query = null ) {
     416        $bp = buddypress();
     417
     418        if ( empty( $bp->blogs->site->members->order_by ) ) {
     419                return;
     420        }
     421
     422        $site_user_query->uid_clauses['orderby'] = "ORDER BY FIELD(" . join( ',', $bp->blogs->site->members->order_by ) . ")";
     423}
     424
     425/**
     426 * Add specific site extra to members fetched in the BP User Query
     427 *
     428 * @since  2.7.0
     429 *
     430 * @param  BP_User_Query|null $site_user_query The BP User Query object
     431 */
     432function bp_blogs_user_query_site_populate_extras( BP_User_Query $site_user_query = null ) {
     433        $bp = buddypress();
     434
     435        if ( empty( $bp->blogs->site->members->extra ) ) {
     436                return;
     437        }
     438
     439        $admins = bp_blogs_current_site_get_admins();
     440
     441        foreach ( (array) $bp->blogs->site->members->extra as $extra ) {
     442                if ( isset( $site_user_query->results[ $extra->user_id ] ) ) {
     443                        $site_user_query->results[ $extra->user_id ]->is_contributor = (int) $extra->is_contributor;
     444
     445                        if ( ! empty( $admins ) && in_array( $extra->user_id, $admins ) ) {
     446                                $site_user_query->results[ $extra->user_id ]->is_admin = 1;
     447                        }
     448                }
     449        }
     450}
     451
     452/**
     453 * BuddyPress Restricted Blogmetas.
     454 *
     455 * @since  2.7.0
     456 *
     457 * @return array The list of restricted Blogmetas.
     458 */
     459function bp_blogs_get_restricted_options() {
     460        return array(
     461                'name',
     462                'description',
     463                'last_activity',
     464                'close_comments_for_old_posts',
     465                'close_comments_days_old',
     466                'thread_comments_depth',
     467                'site_admins',
     468                'url',
     469                'disallow_subscriptions',
     470        );
     471}
     472
     473/**
     474 * Register custom settings for the site's manage settings screen.
     475 *
     476 * @since  2.7.0
     477 *
     478 * @param  string $option_name The 'meta_key' you choose for the blogmeta
     479 * @param  array|string $args {
     480 *     An array of required arguments.
     481 *     @type string   $display_function   Required. The name of the function to use
     482 *                                        for the setting display.
     483 *     @type string   $sanitize_function  Required. The name of the function to use
     484 *                                        to sanitize the value of the option.
     485 * }
     486 * @return bool       True if the setting has been registered. False otherwise.
     487 */
     488function bp_blogs_register_site_settings( $option_name, $args = array() ) {
     489        if ( ! doing_action( 'bp_blogs_setup_site_globals' ) ) {
     490                return false;
     491        }
     492
     493        $bp           = buddypress();
     494        $core_options = bp_blogs_get_restricted_options();
     495        $option_name  = sanitize_key( $option_name );
     496
     497        $restricted = array_flip( array_merge( $core_options, wp_list_pluck( $bp->blogs->site->settings, 'option_name' ) ) );
     498
     499        if ( empty( $option_name ) || isset( $restricted[ $option_name ] ) ) {
     500                return false;
     501        }
     502
     503        $option_args = wp_parse_args( $args, array(
     504                'display_function'  => '',
     505                'sanitize_function' => '',
     506        ) );
     507
     508        $option_args['option_name'] = $option_name;
     509
     510        $bp->blogs->site->settings[ $option_name ] = (object) $option_args;
     511
     512        // Settings is registered.
     513        return true;
     514}
     515
     516/**
     517 * Get all or a specific site custom setting.
     518 *
     519 * @since  2.7.0
     520 *
     521 * @param  string             $option The 'meta_key' of the custom option.
     522 * @return array|object|false         The list of all registered settings.
     523 *                                    The specific requested setting object.
     524 *                                    False or an empty array if no settings were found.
     525 */
     526function bp_blogs_get_site_settings( $option = '' ) {
     527        $settings = buddypress()->blogs->site->settings;
     528
     529        if ( empty( $option ) ) {
     530                return $settings;
     531        } elseif ( ! isset( $settings[ $option ] ) || ! $settings[ $option ]->display_function || ! $settings[ $option ]->sanitize_function ) {
     532                return false;
     533        }
     534
     535        return $settings[ $option ];
     536}
     537
     538/**
     539 * Check if avatar uploads are enabled for the site.
     540 *
     541 * @since 2.7.0
     542 *
     543 * @return bool true if avatar uploads are enabled, false otherwise.
     544 */
     545function bp_blogs_is_site_avatar_uploads_enabled() {
     546        $bp = buddypress();
     547
     548        /**
     549         * Check if :
     550         * - user can upload site avatars
     551         * - the WordPress show avatars setting is enabled
     552         * - the new avatar UI is not disabled.
     553         */
     554        $is_avatar_enabled = ! bp_disable_site_avatar_uploads() && $bp->avatar->show_avatars && false !== (bool) apply_filters( 'bp_avatar_is_front_edit', true );
     555
     556        /**
     557         * Filters the ability to set an avatar for a given site.
     558         *
     559         * @since 2.7.0
     560         *
     561         * @param bool $is_avatar_enabled true if avatar uploads are enabled, false otherwise.
     562         */
     563        return (bool) apply_filters( 'bp_blogs_is_site_avatar_uploads_enabled', $is_avatar_enabled );
     564}
     565
     566/**
     567 * Register the Site Icon script into the common scripts.
     568 * This script is making sure we can set an avatar using a WordPress Site Icon.
     569 *
     570 * @since  2.7.0
     571 *
     572 * @param  array $scripts The BuddyPress common scripts.
     573 * @return array          The BuddyPress common scripts.
     574 */
     575function blogs_register_site_icon_script( $scripts = array() ) {
     576        $min = bp_core_get_minified_asset_suffix();
     577        $uri = buddypress()->plugin_url . 'bp-blogs/site/js/';
     578
     579        return array_merge( $scripts, array(
     580                'bp-site-icon' => array(
     581                        'file'         => sprintf( '%1$ssite-icon%2$s.js', $uri, $min ),
     582                        'dependencies' => array( 'bp-avatar' ),
     583                        'footer'       => true
     584                ),
     585        ) );
     586}
     587add_filter( 'bp_core_register_common_scripts', 'blogs_register_site_icon_script', 10, 1 );
     588
     589/**
     590 * Checks the Site Icon can be used as this feature was introduced in WordPress 4.3.
     591 *
     592 * @since  2.7.0
     593 *
     594 * @return bool True if the site icon can be used. False otherwise.
     595 */
     596function bp_blogs_is_site_icon_enabled() {
     597        /**
     598         * filter here to disable the "site icon avatar"
     599         *
     600         * @since  2.7.0
     601         *
     602         * @param  bool $value True to use the site icon, false otherwise.
     603         */
     604        return (bool) apply_filters( 'bp_blogs_is_site_icon_enabled', function_exists( 'get_site_icon_url' ) );
     605}
     606
     607/**
     608 * Set the Attachments script data for the site icon.
     609 *
     610 * @since  2.7.0
     611 *
     612 * @param  array  $script_data Script datas for the Uploader UI.
     613 * @return array               Script datas for the Uploader UI.
     614 */
     615function bp_blogs_set_site_icon_script_data( $script_data = array() ) {
     616        if ( empty( $script_data['bp_params']['item_id'] ) ) {
     617                return $script_data;
     618        }
     619
     620        // The site id.
     621        $site_id = $script_data['bp_params']['item_id'];
     622
     623        // By default, we set no icon to true.
     624        $params  = array( 'no_icon' => true );
     625        $w_max   = bp_core_avatar_full_width();
     626
     627        // Try to get the site icon
     628        $url = get_site_icon_url( $w_max, '', $site_id );
     629
     630        if ( ! empty( $url ) ) {
     631                $params = array(
     632                        'id'      => (int) get_blog_option( $site_id, 'site_icon', 0 ),
     633                        'src'     => $url,
     634                        'no_icon' => false,
     635                        'max_dim' => $w_max,
     636                        'nonce'   => $script_data['bp_params']['nonces']['set'],
     637                        'in_use'  => false,
     638                );
     639        }
     640
     641        // Check if the site icon is already used as the site logo.
     642        if ( 'site_icon' === bp_blogs_get_blogmeta( $site_id, 'avatar_type' ) ) {
     643                $params['in_use'] = true;
     644        }
     645
     646        // Include specific params for the site icon
     647        $script_data['bp_params']['site_icon'] = $params;
     648
     649        // Finally return the script data.
     650        return $script_data;
     651}
     652
     653/**
     654 * Create a new site's profile photo out of a site icon
     655 *
     656 * @since  2.7.0
     657 *
     658 * @param  int $site_id The site ID
     659 * @param  int $icon_id The ID of the site icon attachment.
     660 * @return bool True on success. False otherwise.
     661 */
     662function blogs_site_icon_create_avatar( $site_id = 0, $icon_id = 0 ) {
     663        if ( empty( $site_id ) || empty( $icon_id ) ) {
     664                return false;
     665        }
     666
     667        // Check if we need to switch the blog.
     668        $needs_switch = ! bp_is_root_blog( (int) $site_id );
     669
     670        // Eventually switch
     671        if ( $needs_switch ) {
     672                switch_to_blog( $site_id );
     673        }
     674
     675        // Get the site icon image file
     676        $icon_img = get_attached_file( $icon_id );
     677
     678        if ( $needs_switch ) {
     679                restore_current_blog();
     680        }
     681
     682        if ( empty( $icon_img ) ) {
     683                return false;
     684        }
     685
     686        $icon_data = BP_Attachment::get_image_data( $icon_img );
     687
     688        if ( empty( $icon_data['width'] ) || empty( $icon_data['height'] ) ) {
     689                return false;
     690        }
     691
     692        // Create the avatar using the site icon image.
     693        if ( ! bp_attachments_create_item_type( 'avatar', array(
     694                'item_id'   => $site_id,
     695                'object'    => 'blog',
     696                'component' => 'blogs',
     697                'image'     => $icon_img,
     698                'crop_w'    => $icon_data['width'],
     699                'crop_h'    => $icon_data['height'],
     700        ) ) ) {
     701                return false;
     702        }
     703
     704        // Set the avatar type.
     705        bp_blogs_update_blogmeta( $site_id, 'avatar_type', 'site_icon' );
     706
     707        return true;
     708}
     709
     710/**
     711 * Update the site's profile photo if the site icon was updated
     712 *
     713 * @since 2.7.0
     714 *
     715 * @param  int $option  The 'site_icon' option
     716 * @param  int $icon_id The ID of the site icon attachment.
     717 */
     718function blogs_site_icon_update_avatar( $option = 'site_icon', $icon_id = 0 ) {
     719        $icon_id = (int) $icon_id;
     720        $site_id = get_current_blog_id();
     721
     722        if ( 'site_icon' !== bp_blogs_get_blogmeta( $site_id, 'avatar_type' ) ) {
     723                return;
     724        }
     725
     726        // Delete the Site's profile photo
     727        if ( empty( $icon_id ) ) {
     728                bp_core_delete_existing_avatar( array( 'item_id' => $site_id, 'object' => 'blog' ) );
     729
     730        // Update the Site's profile photo
     731        } else {
     732                blogs_site_icon_create_avatar( $site_id, $icon_id );
     733        }
     734}
     735add_action( 'update_option_site_icon', 'blogs_site_icon_update_avatar', 10, 2 );
     736
     737/**
     738 * Check if we need to redirect the user who just registered a new site
     739 * to the Site's edit avatar manage screen.
     740 *
     741 * @since 2.7.0
     742 */
     743function bp_blogs_maybe_redirect_to_site_manage_avatar_screen() {
     744        /**
     745         * No need to carry on if Site signups are not allowed or
     746         * if the user is not logged in yet.
     747         */
     748        if ( ! bp_blog_signup_enabled() || ! is_user_logged_in() ) {
     749                return;
     750        }
     751
     752        /**
     753         * No need to carry on if the Site's feature is not active
     754         * or if avatar uploads are disabled.
     755         */
     756        if ( ! bp_is_active( 'blogs', 'site' ) || ! bp_blogs_is_site_avatar_uploads_enabled() ) {
     757                return;
     758        }
     759
     760        $transient_key = sprintf( '_bp_activation_%d_redirect', bp_loggedin_user_id() );
     761        $site_id = get_transient( $transient_key );
     762
     763        if ( empty( $site_id ) ) {
     764                return;
     765        }
     766
     767        // Delete the redirect transient
     768        delete_transient( $transient_key );
     769
     770        $site = bp_blogs_get_site( $site_id );
     771
     772        if ( empty( $site->slug ) ) {
     773                return;
     774        }
     775
     776        $redirect = trailingslashit( bp_blogs_get_site_community_url( $site->slug ) . 'manage/edit-avatar' );
     777
     778        bp_core_add_message( __( 'Welcome to the community pages of your new site, please consider adding a site profile photo for your site', 'buddypress' ) );
     779        bp_core_redirect( esc_url( $redirect ) );
     780}
     781add_action( 'bp_blogs_setup_nav', 'bp_blogs_maybe_redirect_to_site_manage_avatar_screen' );
     782
     783/**
     784 * Delete the site's avatar on site removal.
     785 *
     786 * @since  2.7.0
     787 *
     788 * @param  int $site_id The site ID
     789 */
     790function bp_blogs_remove_site_avatar( $site_id = 0 ) {
     791        bp_core_delete_existing_avatar( array( 'item_id' => $site_id, 'object' => 'blog', 'avatar_dir' => 'blog-avatars' ) );
     792}
     793add_action( 'bp_blogs_remove_blog', 'bp_blogs_remove_site_avatar', 10, 1 );
  • src/bp-blogs/site/js/site-icon.js

    diff --git src/bp-blogs/site/js/site-icon.js src/bp-blogs/site/js/site-icon.js
    index e69de29..c2ecd0f 100644
     
     1/* globals bp, _, BP_Uploader, Backbone */
     2
     3window.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        bp.Avatar      = bp.Avatar || {};
     16
     17        bp.Avatar.SiteIcon = {
     18                start: function() {
     19                        bp.Avatar.nav.on( 'bp-avatar-view:changed', _.bind( this.setView, this ) );
     20
     21                        this.site_icon = new Backbone.Model( _.extend(
     22                                _.pick( BP_Uploader.settings.defaults.multipart_params.bp_params,
     23                                        'object',
     24                                        'item_id'
     25                                ),
     26                                BP_Uploader.settings.defaults.multipart_params.bp_params.site_icon
     27                        ) );
     28
     29                        bp.Avatar.Attachment.on( 'change:url', _.bind( this.updateSiteIcon, this ) );
     30                },
     31
     32                setView: function( view ) {
     33                        if ( 'site_icon' !== view ) {
     34                                return;
     35                        }
     36
     37                        // Create the view
     38                        var siteIconView = new bp.Views.SiteIcon( { model: this.site_icon } );
     39
     40                        // Add it to Avatar views
     41                        bp.Avatar.views.add( { id: 'site_icon', view: siteIconView } );
     42
     43                        // Display it
     44                        siteIconView.inject( '.bp-avatar' );
     45                },
     46
     47                updateSiteIcon: function( model ) {
     48                        if ( ( 'deleted' === model.get( 'action' ) && true === this.site_icon.get( 'in_use' ) ) ||
     49                                ( 'uploaded' === model.get( 'action' ) && model.get( 'url' ) !== this.site_icon.get( 'src' ) )
     50                        ) {
     51                                this.site_icon.set( 'in_use', false );
     52                        }
     53                }
     54        };
     55
     56        // Main view
     57        bp.Views.SiteIcon = bp.View.extend( {
     58                tagName: 'div',
     59                id: 'bp-site-icon',
     60                template: bp.template( 'bp-avatar-site-icon' ),
     61
     62                events: {
     63                        'click .avatar-crop-submit': 'setAvatar'
     64                },
     65
     66                initialize: function() {
     67                        // The site does not have an icon
     68                        if ( true === this.model.get( 'no_icon' ) ) {
     69                                bp.Avatar.displayWarning( BP_Uploader.strings.site_icon.noicon );
     70
     71                        // Message to inform the site icon can be used as an avatar
     72                        } else if ( true === this.model.get( 'in_use' ) ) {
     73                                bp.Avatar.displayWarning( BP_Uploader.strings.site_icon.set );
     74
     75                        } else {
     76                                bp.Avatar.displayWarning( BP_Uploader.strings.site_icon.info );
     77                        }
     78                },
     79
     80                setAvatar: function( event ) {
     81                        var self = this;
     82
     83                        event.preventDefault();
     84
     85                        // Remove the site icon view
     86                        if ( ! _.isUndefined( bp.Avatar.views.get( 'site_icon' ) ) ) {
     87                                var siteIconView = bp.Avatar.views.get( 'site_icon' );
     88                                siteIconView.get( 'view' ).remove();
     89                                bp.Avatar.views.remove( { id: 'site_icon', view: siteIconView } );
     90                        }
     91
     92                        return wp.ajax.post( 'bp_avatar_set', {
     93                                item_id:       self.model.get( 'item_id' ),
     94                                object:        self.model.get( 'object' ),
     95                                original_file: self.model.get( 'id' ),
     96                                type:          'site_icon',
     97                                nonce:         self.model.get( 'nonce' )
     98                        } ).done( function( resp ) {
     99                                self.model.set( 'in_use', true );
     100
     101                                var avatarStatus = new bp.Views.AvatarStatus( {
     102                                        value : BP_Uploader.strings.site_icon[ resp.feedback_code ],
     103                                        type : 'success'
     104                                } );
     105
     106                                bp.Avatar.views.add( {
     107                                        id   : 'status',
     108                                        view : avatarStatus
     109                                } );
     110
     111                                avatarStatus.inject( '.bp-avatar-status' );
     112
     113                                // Update each avatars of the page
     114                                $( '.' + self.model.get( 'object' ) + '-' + self.model.get( 'item_id' ) + '-avatar' ).each( function() {
     115                                        $( this ).prop( 'src', self.model.get( 'src' ) );
     116                                } );
     117
     118                                // Show the delete nav
     119                                bp.Avatar.navItems.get( 'delete' ).set( { hide: 0 } );
     120
     121                                // Update the Avatar Attachment object
     122                                bp.Avatar.Attachment.set( _.extend(
     123                                        _.pick( self.model.attributes, ['object', 'item_id'] ),
     124                                        { url: self.model.get( 'src' ), action: 'uploaded' }
     125                                ) );
     126
     127                        } ).fail( function( resp ) {
     128
     129                                var avatarStatus = new bp.Views.AvatarStatus( {
     130                                        value : BP_Uploader.strings.site_icon[ resp.feedback_code ],
     131                                        type : 'error'
     132                                } );
     133
     134                                bp.Avatar.views.add( {
     135                                        id   : 'status',
     136                                        view : avatarStatus
     137                                } );
     138
     139                                avatarStatus.inject( '.bp-avatar-status' );
     140                        } );
     141                }
     142        } );
     143
     144        bp.Avatar.SiteIcon.start();
     145
     146} )( bp, jQuery );
  • src/bp-blogs/site/notifications.php

    diff --git src/bp-blogs/site/notifications.php src/bp-blogs/site/notifications.php
    index e69de29..dc7cdb5 100644
     
     1<?php
     2/**
     3 * BuddyPress Blogs Site notifications.
     4 *
     5 * @package BuddyPress
     6 * @subpackage BlogsSiteNotifications
     7 * @since 2.7.0
     8 */
     9
     10// Exit if accessed directly.
     11defined( 'ABSPATH' ) || exit;
     12
     13// Put the code for the site notifications here!
  • src/bp-blogs/site/screens.php

    diff --git src/bp-blogs/site/screens.php src/bp-blogs/site/screens.php
    index e69de29..7e96336 100644
     
     1<?php
     2/**
     3 * BuddyPress Blogs Site screens.
     4 *
     5 * @package BuddyPress
     6 * @subpackage BlogsSiteScreens
     7 * @since 2.7.0
     8 */
     9
     10// Exit if accessed directly.
     11defined( 'ABSPATH' ) || exit;
     12
     13/**
     14 * Set the site screens comparing the URI with the Site's navigation.
     15 * And eventually set the active primary an secondary nav items.
     16 *
     17 * This function is hooked to `bp_template_redirect` before `bp_redirect_canonical`
     18 * as we need to eventually edit the BuddyPress canonical stack according the Site's
     19 * navigation.
     20 *
     21 * @since  2.7.0
     22 */
     23function bp_blogs_set_site_screens() {
     24        if ( ! bp_is_site() ) {
     25                return;
     26        }
     27
     28        // Get BuddyPress instance.
     29        $bp = buddypress();
     30
     31        // Initialize the active nav
     32        $active_nav = false;
     33
     34        // Default nav arguments are about primary nav.
     35        $nav_args = array( 'slug' => bp_current_action() );
     36
     37        // If we have an action variable, it's a secondary nav.
     38        if ( bp_action_variable( 0 ) ) {
     39                $nav_args = array( 'parent_slug' => bp_current_action(), 'slug' => bp_action_variable( 0 ) );
     40        }
     41
     42        // We need to try to get the corresponding primary nav item
     43        if ( ! isset( $nav_args['parent_slug'] ) ) {
     44                $active_nav = $bp->blogs->nav->get_primary( $nav_args, false );
     45
     46        // Or the one of the secondary nav
     47        } else {
     48                $active_nav = $bp->blogs->nav->get_secondary( $nav_args, false );
     49        }
     50
     51        // No nav items matched. Redirect to Single site's home page.
     52        if ( ! $active_nav ) {
     53                if ( bp_is_current_item( bp_blogs_get_current_site_slug() ) ) {
     54                        bp_core_add_message( __( 'The page you requested is not available.', 'buddypress' ), 'error' );
     55                        bp_core_redirect( $bp->canonical_stack['base_url'] );
     56                }
     57
     58                return;
     59        }
     60
     61        // Get the matching screen function inside the active nav.
     62        $nav_id          = join( '/', $nav_args );
     63        $screen_function = $active_nav[ $nav_id ]->screen_function;
     64
     65        // If it's a secondary item nav, first check user has access to it
     66        if ( ! empty( $active_nav[ $nav_id ]->parent_slug ) ) {
     67                if ( ! $active_nav[ $nav_id ]->user_has_access ) {
     68                        if ( ! is_user_logged_in() ) {
     69                                bp_core_no_access();
     70                        } elseif ( $active_nav[ $nav_id ]->no_access_url ) {
     71                                bp_core_add_message( __( 'You must be an admin of the site to access the page you requested.', 'buddypress' ), 'error' );
     72                                bp_core_redirect( $active_nav[ $nav_id ]->no_access_url );
     73                        }
     74
     75                        return;
     76                }
     77
     78                // Edit the parent nav to get it at the same time in order to eventually update the canonical stack.
     79                $parent = bp_core_edit_nav_item( array(
     80                        'component' => 'blogs',
     81                        'slug'      => $active_nav[ $nav_id ]->parent_slug,
     82                        'params'    => array(
     83                                'item_css_class' => 'current selected',
     84                        ),
     85                ) );
     86
     87                if ( $parent->default_subnav_slug === $active_nav[ $nav_id ]->slug && ! bp_action_variable( 1 ) ) {
     88                        array_shift( $bp->canonical_stack['action_variables'] );
     89                }
     90
     91                // Finally edit the secondary item to set it as the active one.
     92                bp_core_edit_nav_item( array(
     93                        'component'   => 'blogs',
     94                        'slug'        => $active_nav[ $nav_id ]->slug,
     95                        'parent_slug' => $active_nav[ $nav_id ]->parent_slug,
     96                        'params'      => array(
     97                                'item_css_class' => 'current selected',
     98                        ),
     99                ) );
     100
     101        // It's a primary nav.
     102        } else {
     103                // Edit the primary nav to set it as the active one
     104                bp_core_edit_nav_item( array(
     105                        'component' => 'blogs',
     106                        'slug'      => $active_nav[ $nav_id ]->slug,
     107                        'params'    => array(
     108                                'item_css_class' => 'current selected',
     109                        ),
     110                ) );
     111
     112                /**
     113                 * If it's a primary item and there's no secondary item active,
     114                 * set the default subnav slug as the first action variable.
     115                 */
     116                if ( ! empty( $active_nav[ $nav_id ]->default_subnav_slug ) && ! bp_action_variable( 0 ) ) {
     117                        $bp->action_variables = array( $active_nav[ $nav_id ]->default_subnav_slug );
     118
     119                        // Edit the secondary nav to set the active one.
     120                        bp_core_edit_nav_item( array(
     121                                'component'   => 'blogs',
     122                                'slug'        => $active_nav[ $nav_id ]->default_subnav_slug,
     123                                'parent_slug' => $active_nav[ $nav_id ]->slug,
     124                                'params'      => array(
     125                                        'item_css_class' => 'current selected',
     126                                ),
     127                        ) );
     128                }
     129        }
     130
     131        // Finally hook the screen function.
     132        if ( is_callable( $screen_function ) ) {
     133                add_action( 'bp_screens', $screen_function, 3 );
     134        }
     135}
     136add_action( 'bp_template_redirect', 'bp_blogs_set_site_screens', 1 );
     137
     138/**
     139 * Screen function for the site's pages.
     140 *
     141 * @since  2.7.0
     142 */
     143function bp_blogs_screen_site_home() {
     144        if ( ! bp_is_single_item() ) {
     145                return false;
     146        }
     147
     148        /**
     149         * Hook here to run specific actions juste before
     150         * a blog's single page is displayed
     151         *
     152         * @since 2.7.0
     153         */
     154        do_action( 'bp_blogs_screen_site_home' );
     155
     156        /**
     157         * Filter here to edit the template part to use for the Single site's home.
     158         *
     159         * @since  2.7.0
     160         *
     161         * @param  string $value Relative path to the template part.
     162         */
     163        bp_core_load_template( apply_filters( 'bp_blogs_screen_site_home_template', 'blogs/single/home' ) );
     164}
     165
     166/**
     167 * Screen function for the site's manage pages.
     168 *
     169 * @since  2.7.0
     170 */
     171function bp_blogs_screen_site_manage() {
     172        if ( ! bp_is_single_item() ) {
     173                return false;
     174        }
     175
     176        if ( bp_is_site_manage_settings() ) {
     177
     178                // Update settings.
     179                if ( ! empty( $_POST['bp_site']['submit'] ) ) {
     180
     181                        check_admin_referer( 'site_manage_settings' );
     182
     183                        unset( $_POST['bp_site']['submit'] );
     184                        $options = $_POST['bp_site'];
     185
     186                        $blog_id = bp_blogs_get_current_site_id();
     187                        $referer = wp_unslash( $_POST['_wp_http_referer'] );
     188                        $message = __( 'We were not able to perform this action, please try again later', 'buddypress' );
     189                        $type    = 'error';
     190                        $name_check = empty( $options['blogname'] );
     191
     192                        if ( ! bp_is_item_admin() || empty( $blog_id ) || $name_check ) {
     193                                if ( $name_check ) {
     194                                        $message = __( 'The site title is required.', 'buddypress' );
     195                                }
     196
     197                                bp_core_add_message( $message, $type );
     198                                bp_core_redirect( $referer );
     199                        }
     200
     201                        if ( ! isset( $options['blog_public'] ) ) {
     202                                $options['blog_public'] = 0;
     203                        }
     204
     205                        // This option will only be saved in BuddyPress blog metas
     206                        if ( isset( $options['disallow_subscriptions'] ) ) {
     207                                bp_blogs_update_blogmeta( $blog_id, 'disallow_subscriptions', (int) $options['disallow_subscriptions'] );
     208                                unset( $options['disallow_subscriptions'] );
     209                        } else {
     210                                bp_blogs_delete_blogmeta( $blog_id, 'disallow_subscriptions' );
     211                        }
     212
     213                        $needs_switch = ! bp_is_root_blog( (int) $blog_id );
     214
     215                        if ( $needs_switch ) {
     216                                switch_to_blog( $blog_id );
     217                        }
     218
     219                        $whitelist_options = array(
     220                                'blogname'        => true,
     221                                'blogdescription' => true,
     222                                'blog_public'     => true,
     223                        );
     224
     225                        foreach ( $options as $key => $option ) {
     226                                if ( empty( $whitelist_options[ $key ] ) ) {
     227                                        continue;
     228                                }
     229
     230                                $sanitized_option = sanitize_option( $key, $option );
     231
     232                                update_option( $key, $sanitized_option );
     233                        }
     234
     235                        if ( isset( $needs_reset ) ) {
     236                                restore_current_blog();
     237                        }
     238
     239                        $options = array_diff_key( $options, $whitelist_options );
     240
     241                        // Now manage the options plugins can eventually add, if any.
     242                        $plugin_settings = bp_blogs_get_site_settings();
     243
     244                        if ( ! empty( $plugin_settings ) ) {
     245                                foreach ( $plugin_settings as $plugin_setting ) {
     246                                        if ( empty( $plugin_setting->sanitize_function ) || ! is_callable( $plugin_setting->sanitize_function ) ) {
     247                                                continue;
     248                                        }
     249
     250                                        if ( isset( $options[ $plugin_setting->option_name ] ) ) {
     251                                                $plugin_option = call_user_func_array( $plugin_setting->sanitize_function, array( $options[ $plugin_setting->option_name ] ) );
     252
     253                                                bp_blogs_update_blogmeta( $blog_id, $plugin_setting->option_name, $plugin_option );
     254                                        } else {
     255                                                bp_blogs_delete_blogmeta( $blog_id, $plugin_setting->option_name );
     256                                        }
     257                                }
     258                        }
     259
     260                        // Redirect the user once done
     261                        bp_core_add_message( __( 'Settings saved.', 'buddypress' ) );
     262                        bp_core_redirect( $referer );
     263                }
     264
     265        } elseif ( bp_is_site_manage_members() ) {
     266
     267                if ( 'remove' === bp_action_variable( 1 ) ) {
     268                        check_admin_referer( 'site_remove_member' );
     269
     270                        $blog_id = bp_blogs_get_current_site_id();
     271                        $user_id = (int) bp_action_variable( 2 );
     272
     273                        $referer = wp_get_referer();
     274                        $message = __( 'We were not able to perform this action, please try again later', 'buddypress' );
     275                        $type    = 'error';
     276
     277                        if ( ! bp_is_item_admin() || empty( $blog_id ) || empty( $user_id ) ) {
     278                                bp_core_add_message( $message, $type );
     279                                bp_core_redirect( $referer );
     280                        }
     281
     282                        if ( bp_user_can( $user_id, 'delete_published_posts', array( 'site_id' => $blog_id ) ) ) {
     283                                $message = __( 'Only subscribers or contributors can be removed from this screen.', 'buddypress' );
     284                                bp_core_add_message( $message, $type );
     285                                bp_core_redirect( $referer );
     286                        }
     287
     288                        /**
     289                         * Fires before the user is removed from the blog
     290                         *
     291                         * @since 2.7.0
     292                         *
     293                         * @param int $user_id the ID of the current user
     294                         * @param int $blog_id the ID of the blog
     295                         */
     296                        do_action( 'bp_blogs_before_remove_user_from_site', $user_id, $blog_id );
     297
     298                        /**
     299                         * Removing the user
     300                         */
     301                        $removed = remove_user_from_blog( $user_id, $blog_id );
     302
     303                        if ( ! is_wp_error( $removed ) ) {
     304                                $message = __( 'Member successfully removed from the site.', 'buddypress' );
     305                                $type    = '';
     306
     307                                /**
     308                                 * Fires after the user was removed from the blog
     309                                 *
     310                                 * @since 2.7.0
     311                                 *
     312                                 * @param int $user_id the ID of the current user
     313                                 * @param int $blog_id the ID of the blog
     314                                 */
     315                                do_action( 'bp_blogs_after_remove_user_from_site', $user_id, $blog_id );
     316
     317                        } else {
     318                                $message = $removed->get_error_message();
     319                                $type    = 'error';
     320                        }
     321
     322                        bp_core_add_message( $message, $type );
     323                        bp_core_redirect( $referer );
     324
     325                // Toggle involvement
     326                } elseif ( 'promote' === bp_action_variable( 1 ) || 'demote' === bp_action_variable( 1 ) ) {
     327                        $action = sanitize_key( bp_action_variable( 1 ) );
     328
     329                        check_admin_referer( "site_{$action}_member" );
     330
     331                        $blog_id = bp_blogs_get_current_site_id();
     332                        $user_id = (int) bp_action_variable( 2 );
     333
     334                        $referer = wp_get_referer();
     335                        $message = __( 'We were not able to perform this action, please try again later', 'buddypress' );
     336                        $type    = 'error';
     337
     338                        if ( ! bp_is_item_admin() || empty( $blog_id ) || empty( $user_id ) ) {
     339                                bp_core_add_message( $message, $type );
     340                                bp_core_redirect( $referer );
     341                        }
     342
     343                        $needs_switch = ! bp_is_root_blog( (int) $blog_id );
     344
     345                        if ( $needs_switch ) {
     346                                switch_to_blog( $blog_id );
     347                        }
     348
     349                        if ( user_can( $user_id, 'delete_published_posts' ) ) {
     350                                $message = __( 'Only subscribers or contributors can be managed from this screen. Please use your Site Administration to manage the role of this specific member.', 'buddypress' );
     351                                bp_core_add_message( $message, $type );
     352                                bp_core_redirect( $referer );
     353                        }
     354
     355                        /**
     356                         * Fires before the user is promoted or demoted
     357                         *
     358                         * @since 2.7.0
     359                         *
     360                         * @param int $user_id the ID of the current user
     361                         * @param int $blog_id the ID of the blog
     362                         */
     363                        do_action( "bp_blogs_before_{$action}_user_from_site", $user_id, $blog_id );
     364
     365                        $message  = __( 'Member successfully promoted to contributor.', 'buddypress' );
     366                        $userdata = array( 'ID' => $user_id, 'role' => 'contributor' );
     367
     368                        if ( 'demote' === $action ) {
     369                                $message          = __( 'Member successfully demoted to subscriber.', 'buddypress' );
     370                                $userdata['role'] = 'subscriber';
     371                        }
     372
     373                        /**
     374                         * Updating the user role
     375                         */
     376                        $updated = wp_update_user( $userdata );
     377
     378                        if ( $needs_switch ) {
     379                                restore_current_blog();
     380                        }
     381
     382                        if ( is_wp_error( $updated ) ) {
     383                                $message = $updated->get_error_message();
     384                                $type    = 'error';
     385                        } else {
     386                                $type = '';
     387
     388                                /**
     389                                 * Fires after the user was promoted or demoted.
     390                                 *
     391                                 * @since 2.7.0
     392                                 *
     393                                 * @param int $user_id the ID of the current user
     394                                 * @param int $blog_id the ID of the blog
     395                                 */
     396                                do_action( "bp_blogs_after_{$action}_user_from_site", $user_id, $blog_id );
     397                        }
     398
     399                        bp_core_add_message( $message, $type );
     400                        bp_core_redirect( $referer );
     401                }
     402        }
     403
     404        /**
     405         * Hook here to run specific actions juste before
     406         * a single site's settings page is displayed
     407         *
     408         * @since 2.7.0
     409         */
     410        do_action( 'bp_blogs_screen_site_manage' );
     411
     412        /**
     413         * Filter here to edit the template part to use for the Single site's settings page.
     414         *
     415         * @since  2.7.0
     416         *
     417         * @param  string $value Relative path to the template part.
     418         */
     419        bp_core_load_template( apply_filters( 'bp_blogs_screen_site_manage_template', 'blogs/single/home' ) );
     420}
  • src/bp-blogs/site/subscriptions.php

    diff --git src/bp-blogs/site/subscriptions.php src/bp-blogs/site/subscriptions.php
    index e69de29..8be8ce3 100644
     
     1<?php
     2/**
     3 * BuddyPress Blogs Site subscriptions.
     4 *
     5 * @package BuddyPress
     6 * @subpackage BlogsSiteSubscriptions
     7 * @since 2.7.0
     8 */
     9
     10// Exit if accessed directly.
     11defined( 'ABSPATH' ) || exit;
     12
     13/**
     14 * Displays a subscribe button for the current site.
     15 *
     16 * @since  2.7.0
     17 *
     18 * @param  WP_Site|object $site The site object.
     19 * @return string HTML Output.
     20 */
     21function bp_site_subscribe_button( $site = null ) {
     22        if ( empty( $site ) ) {
     23                $site = bp_blogs_get_current_site();
     24        }
     25
     26        echo bp_get_site_subscribe_button( $site );
     27}
     28
     29/**
     30 * Builds the arguments of the subscribe button for the current site.
     31 *
     32 * @since  2.7.0
     33 *
     34 * @param  WP_Site|object $site The site object.
     35 * @return array The button arguments.
     36 */
     37function bp_get_site_subscribe_button_args( $site = null ) {
     38        if ( empty( $site->blog_id ) ) {
     39                $site = bp_blogs_get_current_site();
     40        }
     41
     42        if ( ! $site || ! empty( $site->is_admin ) ) {
     43                return;
     44        }
     45
     46        $start_button = array(
     47                'id'                => 'subscribe_unsubscribe',
     48                'component'         => 'blogs',
     49                'must_be_logged_in' => true,
     50                'block_self'        => false,
     51        );
     52
     53        if ( ! $site->is_member ) {
     54                $end_button = array(
     55                        'wrapper_class'     => 'site-button subscribe',
     56                        'link_href'         => esc_url( wp_nonce_url(
     57                                add_query_arg( 'action', 'subscribe', bp_blogs_get_site_community_url() ),
     58                                'site_subscribe'
     59                        ) ),
     60                        'link_class'        => 'site-button subscribe',
     61                        'link_text'         => __( 'Subscribe', 'buddypress' ),
     62                );
     63        } else {
     64                $link_text = __( 'Unsubscribe', 'buddypress' );
     65
     66                // To avoid any confusion
     67                if ( ! empty( $site->is_contributor ) ) {
     68                        $link_text = __( 'Leave', 'buddypress' );
     69                }
     70
     71                $end_button = array(
     72                        'wrapper_class'     => 'site-button unsubscribe',
     73                        'link_href'         => esc_url( wp_nonce_url(
     74                                add_query_arg( 'action', 'unsubscribe', bp_blogs_get_site_community_url() ),
     75                                'site_unsubscribe'
     76                        ) ),
     77                        'link_class'        => 'site-button unsubscribe confirm',
     78                        'link_text'         => $link_text,
     79                );
     80        }
     81
     82        $button = array_merge( $start_button, $end_button );
     83
     84        /**
     85         * Filter here to edit button arguments.
     86         *
     87         * @since  2.7.0
     88         *
     89         * @param  array  $button The Button arguments.
     90         * @param  object $site   The site object.
     91         */
     92        return apply_filters( 'bp_get_site_subscribe_button_args', $button, $site );
     93}
     94
     95/**
     96 * Gets the Subscribe Button for the current site.
     97 *
     98 * @since  2.7.0
     99 *
     100 * @param  WP_Site|object $site The site object.
     101 * @return string HTML Output.
     102 */
     103function bp_get_site_subscribe_button( $site = null ) {
     104        return bp_get_button( bp_get_site_subscribe_button_args( $site ) );
     105}
     106
     107/**
     108 * Listen to the subscribe/unsubscribe actions and handle them.
     109 *
     110 * @since  2.7.0
     111 */
     112function bp_blogs_site_subscriptions_handle_actions() {
     113        if ( empty( $_GET['action'] ) || ( 'subscribe' !== $_GET['action'] && 'unsubscribe' !== $_GET['action'] ) ) {
     114                return;
     115        }
     116
     117        $action = sanitize_key( $_GET['action'] );
     118
     119        check_admin_referer( 'site_' . $action );
     120
     121        $referer = wp_get_referer();
     122        $result = array(
     123                'message' => __( 'We were not able to perform this action, please try again later', 'buddypress' ),
     124                'type'    => 'error',
     125        );
     126
     127        if ( is_user_logged_in() && is_callable( 'bp_blogs_site_' . $action ) ) {
     128                $result = call_user_func( 'bp_blogs_site_' . $action );
     129        }
     130
     131        bp_core_add_message( $result['message'], $result['type'] );
     132        bp_core_redirect( $referer );
     133}
     134add_action( 'bp_blogs_screen_site_home', 'bp_blogs_site_subscriptions_handle_actions' );
     135
     136/**
     137 * Subscribes a user to a site.
     138 *
     139 * @since  2.7.0
     140 *
     141 * @param int $user_id The ID of the user.
     142 * @param int $site_id The ID of the site.
     143 * @return array       The feedback message and type.
     144 */
     145function bp_blogs_site_subscribe( $user_id = 0, $site_id = 0 ) {
     146        if ( empty( $user_id ) ) {
     147                $user_id = bp_loggedin_user_id();
     148        }
     149
     150        if ( empty( $site_id ) ) {
     151                $site = bp_blogs_get_current_site();
     152        } else {
     153                $site = bp_blogs_get_site( $site_id );
     154        }
     155
     156        // Default result
     157        $result = array(
     158                'message' => __( 'We were not able to perform this action, please try again later', 'buddypress' ),
     159                'type'    => 'error',
     160        );
     161
     162        if ( bp_disable_site_subscriptions() || empty( $site->blog_id ) || empty( $site->public ) || ! empty( $site->disallow_subscriptions ) ) {
     163                return $result;
     164        }
     165
     166        // First make sure not to add a user that is already a subscriber of the blog.
     167        if ( bp_user_can( $user_id, 'read', array( 'site_id' => $site->blog_id ) ) ) {
     168                $result['message'] = __( 'You already subcribed to this site.', 'buddypress' );
     169                return $result;
     170        }
     171
     172        /**
     173         * Fires before the user subcribes to the site.
     174         *
     175         * @since 2.7.0
     176         *
     177         * @param int            $user_id the ID of the user.
     178         * @param WP_Site|object $site    The Site object.
     179         */
     180        do_action( 'bp_blogs_before_site_subscribe', $user_id, $site );
     181
     182        $subscribed = add_user_to_blog( $site->blog_id, $user_id, 'subscriber' );
     183
     184        if ( is_wp_error( $subscribed ) ) {
     185                $result = array(
     186                        'message' => $subscribed->get_error_message(),
     187                        'type'    => 'error',
     188                );
     189        } else {
     190                // Update Site object
     191                $site->is_member = true;
     192
     193                $result = array(
     194                        'message' => __( 'You successfully subscribed to the site.', 'buddypress' ),
     195                        'type'    => '',
     196                );
     197
     198                /**
     199                 * Fires after the user subcribed to the site.
     200                 *
     201                 * @since 2.7.0
     202                 *
     203                 * @param int            $user_id the ID of the user.
     204                 * @param WP_Site|object $site    The Site object.
     205                 */
     206                do_action( 'bp_blogs_after_site_subscribed', $user_id, $site );
     207        }
     208
     209        return $result;
     210}
     211
     212/**
     213 * Unsubscribes a user to a site.
     214 *
     215 * @since  2.7.0
     216 *
     217 * @param int $user_id The ID of the user.
     218 * @param int $site_id The ID of the site.
     219 * @return array       The feedback message and type.
     220 */
     221function bp_blogs_site_unsubscribe( $user_id = 0, $site_id = 0 ) {
     222        if ( empty( $user_id ) ) {
     223                $user_id = bp_loggedin_user_id();
     224        }
     225
     226        if ( empty( $site_id ) ) {
     227                $site = bp_blogs_get_current_site();
     228        } else {
     229                $site = bp_blogs_get_site( $site_id );
     230        }
     231
     232        // Default result
     233        $result = array(
     234                'message' => __( 'We were not able to perform this action, please try again later', 'buddypress' ),
     235                'type'    => 'error',
     236        );
     237
     238        if ( bp_disable_site_subscriptions() || empty( $site->blog_id ) || empty( $site->public ) || ! empty( $site->disallow_subscriptions ) ) {
     239                return $result;
     240        }
     241
     242        // First check the user is a subscriber.
     243        if ( ! bp_user_can( $user_id, 'read', array( 'site_id' => $site->blog_id ) ) ) {
     244                $result['message'] = __( 'You already unsubcribed to this site.', 'buddypress' );
     245                return $result;
     246        }
     247
     248        /**
     249         * Fires before the user unsubscribes to the site.
     250         *
     251         * @since 2.7.0
     252         *
     253         * @param int            $user_id The ID of the user.
     254         * @param WP_Site|object $site    The site object.
     255         */
     256        do_action( 'bp_blogs_before_site_unsubscribe', $user_id, $site );
     257
     258        $unsubscribed = remove_user_from_blog( $user_id, $site->blog_id );
     259
     260        if ( is_wp_error( $unsubscribed ) ) {
     261                $result = array(
     262                        'message' => $unsubscribed->get_error_message(),
     263                        'type'    => 'error',
     264                );
     265        } else {
     266                // Update Site object
     267                $site->is_member = false;
     268
     269                $result = array(
     270                        'message' => __( 'You successfully unsubscribed to the site.', 'buddypress' ),
     271                        'type'    => 'success',
     272                );
     273
     274                /**
     275                 * Fires after the user unsubscribed to the site.
     276                 *
     277                 * @since 2.7.0
     278                 *
     279                 * @param int            $user_id The ID of the user.
     280                 * @param WP_Site|object $site    The site object.
     281                 */
     282                do_action( 'bp_blogs_after_site_unsubscribed', $user_id, $site );
     283        }
     284
     285        return $result;
     286}
     287
  • src/bp-blogs/site/template.php

    diff --git src/bp-blogs/site/template.php src/bp-blogs/site/template.php
    index e69de29..afdb5f2 100644
     
     1<?php
     2/**
     3 * BuddyPress Blogs Site template.
     4 *
     5 * @package BuddyPress
     6 * @subpackage BlogsSiteTemplate
     7 * @since 2.7.0
     8 */
     9
     10// Exit if accessed directly.
     11defined( 'ABSPATH' ) || exit;
     12
     13/** Blogs loop template tags **************************************************/
     14
     15/**
     16 * Output the site's slug in a Blogs loop.
     17 *
     18 * @since 2.7.0.
     19 */
     20function bp_blogs_site_slug() {
     21        echo bp_get_blogs_site_slug();
     22}
     23
     24        /**
     25         * Return the site's slug in a Blogs loop.
     26         *
     27         * @since 2.7.0.
     28         *
     29         * @return $slug The site's slug.
     30         */
     31        function bp_get_blogs_site_slug() {
     32                $slug = '';
     33
     34                if ( ! empty( $GLOBALS['blogs_template'] ) ) {
     35                        $site = $GLOBALS['blogs_template']->blog;
     36                }
     37
     38                if ( empty( $site->domain ) || empty( $site->path ) ) {
     39                        return;
     40                }
     41
     42                if ( (int) bp_get_root_blog_id() === (int) bp_get_blog_id() ) {
     43                        $slug = bp_blogs_get_root_site_slug();
     44                } elseif ( is_subdomain_install() ) {
     45                        $slug = trim( str_replace( get_current_site()->domain, '', $site->domain ), '.' );
     46                } else {
     47                        $slug = trim( str_replace( get_current_site()->path, '', $site->path ), '/' );
     48                }
     49
     50                return apply_filters( 'bp_get_blogs_site_slug', $slug, $site );
     51        }
     52
     53/**
     54 * Output the button to display the site's community page.
     55 *
     56 * @see BP_Button for a the description of arguments and return
     57 *      value.
     58 *
     59 * @since  2.7.0
     60 *
     61 * @param array|string $args.
     62 */
     63function bp_blogs_site_discover_button( $args = '' ) {
     64        echo bp_get_blogs_site_discover_button( $args );
     65}
     66
     67        /**
     68         * Get the arguments of the site's community button.
     69         *
     70         * @since  2.7.0
     71         *
     72         * @param  array|string $args
     73         * @return array        The merged arguments.
     74         */
     75        function bp_blogs_get_site_discover_button_args( $args = '' ) {
     76                $r = wp_parse_args( $args, array(
     77                        'id'                => 'discover_site',
     78                        'component'         => 'blogs',
     79                        'must_be_logged_in' => false,
     80                        'block_self'        => false,
     81                        'wrapper_class'     => 'blog-button discover',
     82                        'link_href'         => bp_blogs_get_site_community_url( bp_get_blogs_site_slug() ),
     83                        'link_class'        => 'blog-button discover',
     84                        'link_text'         => __( 'Discover Site', 'buddypress' ),
     85                ) );
     86
     87                return apply_filters( 'bp_blogs_get_site_discover_button_args', $r );
     88        }
     89        /**
     90         * Return button to display the site's community page.
     91         *
     92         * @see BP_Button for a the description of arguments and return
     93         *      value.
     94         *
     95         * @since  2.7.0
     96         *
     97         * @param array|string $args
     98         * @return string The HTML for the Visit button.
     99         */
     100        function bp_get_blogs_site_discover_button( $args = '' ) {
     101                return bp_get_button( bp_blogs_get_site_discover_button_args( $args ) );
     102        }
     103
     104/** Single Site template tags *************************************************/
     105
     106/**
     107 * Load the appropriate current site's home page
     108 *
     109 * @since 2.7.0
     110 *
     111 * @param  bool           $require_once True to only include the template once. False otherwise.
     112 * @param  WP_Site|object $site         The Site object.
     113 */
     114function bp_blogs_load_site_front_template( $require_once = false, $site = null ) {
     115        $located = bp_blogs_get_site_front_template( $site );
     116
     117        if ( false !== $located ) {
     118                $slug = str_replace( '.php', '', $located );
     119
     120                /**
     121                 * Let plugins adding an action to bp_get_template_part get it from here
     122                 *
     123                 * @param string $slug Template part slug requested.
     124                 * @param string $name Template part name requested.
     125                 */
     126                do_action( 'get_template_part_' . $slug, $slug, false );
     127
     128                load_template( $located, $require_once );
     129
     130        } elseif ( bp_is_active( 'activity' ) && bp_blogs_current_site_is_public() ) {
     131                bp_get_template_part( 'blogs/single/activity' );
     132
     133        } elseif ( bp_is_active( 'members' ) ) {
     134                bp_get_template_part( 'blogs/single/members' );
     135        }
     136
     137        return $located;
     138}
     139
     140/**
     141 * Locate a site's custom front template if it exists.
     142 *
     143 * @since 2.7.0
     144 *
     145 * @param  WP_Site|object $site The Site object.
     146 */
     147function bp_blogs_get_site_front_template( $site = null ) {
     148        if ( ! is_object( $site ) ) {
     149                $site = bp_blogs_get_current_site();
     150        }
     151
     152        if ( empty( $site->blog_id ) ) {
     153                return false;
     154        }
     155
     156        if ( isset( $site->front_template ) ) {
     157                return $site->front_template;
     158        }
     159
     160        $template_names = array(
     161                'blogs/single/front-id-'   . sanitize_file_name( $site->blog_id ) . '.php',
     162                'blogs/single/front-slug-' . sanitize_file_name( $site->slug )    . '.php',
     163        );
     164
     165        $visibility = 'public';
     166        if ( ! $site->public ) {
     167                $visibility = 'private';
     168        }
     169
     170        $template_names = array_merge( $template_names, array(
     171                'blogs/single/front-visibility-' . $visibility . '.php',
     172                'blogs/single/front.php'
     173        ) );
     174
     175        /**
     176         * Filters the hierarchy of the site's front template.
     177         *
     178         * @since 2.7.0
     179         *
     180         * @param array          $template_names Array of template paths.
     181         * @param WP_Site|object $site           Site object.
     182         */
     183        return bp_locate_template( apply_filters( 'bp_blogs_get_site_front_template', $template_names, $site ), false, true );
     184}
     185
     186/**
     187 * Generic function to get the output for a primary or a secondary nav.
     188 *
     189 * @since  2.7.0
     190 *
     191 * @param  string $type Primary or Secondary?
     192 * @return array        List of li elements for the navigation.
     193 */
     194function bp_get_site_nav( $type = 'primary' ) {
     195        $bp = buddypress();
     196
     197        if ( 'secondary' === $type ) {
     198                $parent_slug = bp_current_action();
     199                $nav_items = $bp->blogs->nav->get_secondary( array( 'parent_slug' => $parent_slug ) );
     200        } else {
     201                $nav_items = $bp->blogs->nav->get_primary();
     202        }
     203
     204        if ( empty( $nav_items ) ) {
     205                return;
     206        }
     207
     208        $output = array();
     209
     210        foreach ( $nav_items as $nav_item ) {
     211                $selected = '';
     212
     213                if ( ! empty( $nav_item->item_css_class ) ) {
     214                        $selected = ' class="' . esc_attr( $nav_item->item_css_class ) . '"';
     215                }
     216
     217                $output[ $nav_item->slug ] = sprintf( '
     218                        <li id="%1$s-blogs-li"%2$s>
     219                                <a href="%3$s" id="site-%1$s">%4$s</a>
     220                        </li>
     221                        ',
     222                        esc_attr( $nav_item->css_id ),
     223                        $selected,
     224                        esc_url( $nav_item->link ),
     225                        wp_kses( $nav_item->name, array( 'span' => array( 'class' => true ) ) )
     226                );
     227        }
     228
     229        return apply_filters( 'bp_get_site_nav', $output, $nav_items, $type );
     230}
     231
     232/**
     233 * Output the Site's primary nav.
     234 *
     235 * @since  2.7.0
     236 *
     237 * @return string HTML Output.
     238 */
     239function bp_site_primary_nav() {
     240        /**
     241         * Fires before the site primary nav
     242         *
     243         * (inside an <ul> tag)
     244         *
     245         * @since  2.7.0
     246         */
     247        do_action( 'bp_before_site_primary_nav' );
     248
     249        echo join( "\n", bp_get_site_nav( 'primary' ) );
     250
     251        /**
     252         * Fires after the site primary nav
     253         *
     254         * (inside an <ul> tag)
     255         *
     256         * @since  2.7.0
     257         */
     258        do_action( 'bp_after_site_primary_nav' );
     259}
     260
     261/**
     262 * Output the Site's secondary nav.
     263 *
     264 * @since  2.7.0
     265 *
     266 * @return string HTML Output.
     267 */
     268function bp_site_secondary_nav() {
     269        /**
     270         * Fires before the site secondary nav
     271         *
     272         * (inside an <ul> tag)
     273         *
     274         * @since  2.7.0
     275         */
     276        do_action( 'bp_before_site_secondary_nav' );
     277
     278        echo join( "\n", bp_get_site_nav( 'secondary' ) );
     279
     280        /**
     281         * Fires after the site secondary nav
     282         *
     283         * (inside an <ul> tag)
     284         *
     285         * @since  2.7.0
     286         */
     287        do_action( 'bp_after_site_secondary_nav' );
     288}
     289
     290/**
     291 * Does the current user has access to this site?
     292 *
     293 * @since  2.7.0
     294 *
     295 * @return bool True if the user has access. False otherwise.
     296 */
     297function bp_site_has_access() {
     298        return bp_blogs_current_site_has_access();
     299}
     300
     301/**
     302 * Is the current site public?
     303 *
     304 * @since  2.7.0
     305 *
     306 * @return bool True if the site is public. False otherwise.
     307 */
     308function bp_site_is_public() {
     309        return bp_blogs_current_site_is_public();
     310}
     311
     312/**
     313 * Prints a message if the user has no access to the blog's content
     314 *
     315 * @since 2.7.0
     316 */
     317function bp_site_visibility_message() {
     318        $message = false;
     319
     320        // For now display a message if the blog is not public
     321        if ( ! bp_blogs_current_site_is_public() ) {
     322                $message = __( 'The details of this site are restricted to its members.', 'buddypress' );
     323        }
     324
     325        /**
     326         * Filters a message if the blog is not public.
     327         *
     328         * @since 2.7.0
     329         *
     330         * @param string $message Message to display to the current user.
     331         */
     332        echo esc_html( apply_filters( 'bp_site_visibility_message', $message ) );
     333}
     334
     335/**
     336 * Display the site name.
     337 *
     338 * @since  2.7.0
     339 *
     340 * @return string The site name.
     341 */
     342function bp_sitename() {
     343        echo bp_get_sitename();
     344}
     345
     346        /**
     347         * Get the site name to display.
     348         *
     349         * @since  2.7.0
     350         *
     351         * @return string The site name.
     352         */
     353        function bp_get_sitename() {
     354                return apply_filters( 'bp_get_sitename', bp_blogs_get_current_site_property( 'name' ) );
     355        }
     356
     357/**
     358 * Display the site description.
     359 *
     360 * @since  2.7.0
     361 *
     362 * @return string The site name.
     363 */
     364function bp_site_description() {
     365        /**
     366         * Fires before the site description
     367         *
     368         * @since  2.7.0
     369         */
     370        do_action( 'bp_before_site_description' );
     371
     372        echo bp_get_site_description();
     373
     374        /**
     375         * Fires after the site description
     376         *
     377         * @since  2.7.0
     378         */
     379        do_action( 'bp_after_site_description' );
     380}
     381
     382/**
     383 * Get the site description to display.
     384 *
     385 * @since  2.7.0
     386 *
     387 * @return string The site description.
     388 */
     389function bp_get_site_description() {
     390        return apply_filters( 'bp_get_site_description', bp_blogs_get_current_site_property( 'description' ) );
     391}
     392
     393/**
     394 * Display the site's avatar
     395 *
     396 * @since  2.7.0
     397 *
     398 * @return string The site's avatar.
     399 */
     400function bp_site_avatar() {
     401        echo bp_blogs_get_site_avatar( array(
     402                'item_id'   => bp_blogs_get_current_site_id(),
     403                'type'      => 'full',
     404                'site_name' => esc_attr( bp_get_sitename() ),
     405        ) );
     406}
     407
     408/**
     409 * Display the admins in the site's header
     410 *
     411 * @since 2.7.0
     412 *
     413 * @return string HTML output
     414 */
     415function bp_site_list_admins() {
     416        /**
     417         * Fires before the site admins list
     418         *
     419         * @since  2.7.0
     420         */
     421        do_action( 'bp_before_site_list_admins' );
     422
     423        echo bp_get_site_list_admins();
     424
     425        /**
     426         * Fires after the site admins list
     427         *
     428         * @since  2.7.0
     429         */
     430        do_action( 'bp_after_site_list_admins' );
     431}
     432        /**
     433         * Get the admins list
     434         *
     435