Skip to:
Content

BuddyPress.org

Ticket #4988: 4988.02.patch

File 4988.02.patch, 53.5 KB (added by r-a-y, 11 years ago)
  • src/bp-activity/bp-activity-classes.php

     
    275275         *     @type array $date_query An array of date_query conditions.
    276276         *                             See first parameter of WP_Date_Query::__construct()
    277277         *                             for description.
     278         *     @type array $filter_query An array of activity query conditions.
     279         *                               See BP_Activity_Query::__construct()
     280         *                               for description.
    278281         *     @type array $filter See BP_Activity_Activity::get_filter_sql().
    279282         *     @type string $search_terms Limit results by a search term.
    280283         *                                Default: false.
     
    327330                        'in'                => false,      // Array of ids to limit query by (IN)
    328331                        'meta_query'        => false,      // Filter by activitymeta
    329332                        'date_query'        => false,      // Filter by date
     333                        'filter_query'      => false,      // Advanced filtering - see BP_Activity_Query
    330334                        'filter'            => false,      // See self::get_filter_sql()
     335                        'scope'             => false,      // Preset activity arguments
    331336                        'search_terms'      => false,      // Terms to search by
    332337                        'display_comments'  => false,      // Whether to include activity comments
    333338                        'show_hidden'       => false,      // Show items marked hide_sitewide
     
    336341                        'count_total'       => false,
    337342                );
    338343                $r = wp_parse_args( $args, $defaults );
    339                 extract( $r );
    340344
    341345                // Select conditions
    342346                $select_sql = "SELECT DISTINCT a.id";
     
    351355                // Excluded types
    352356                $excluded_types = array();
    353357
     358                // Scope takes precedence
     359                if ( ! empty( $r['scope'] ) ) {
     360                        $scope_query = self::get_scope_query_sql( $r['scope'], $r );
     361
     362                        if ( ! empty( $scope_query['sql'] ) ) {
     363                                $where_conditions['scope_query_sql'] = $scope_query['sql'];
     364                        }
     365
     366                        // override some arguments if needed
     367                        if ( ! empty( $scope_query['override'] ) ) {
     368                                $r = array_replace_recursive( $r, $scope_query['override'] );
     369                        }
     370
     371                // Advanced filtering
     372                } elseif ( ! empty( $r['filter_query'] ) ) {
     373                        $filter_query = new BP_Activity_Query( $r['filter_query'] );
     374                        if ( $sql = $filter_query->get_sql() ) {
     375                                $where_conditions['filter_query_sql'] = $sql;
     376                        }
     377                }
     378
     379                // Regular filtering
     380                if ( $r['filter'] && $filter_sql = BP_Activity_Activity::get_filter_sql( $r['filter'] ) ) {
     381                        $where_conditions['filter_sql'] = $filter_sql;
     382                }
     383
    354384                // Spam
    355                 if ( 'ham_only' == $spam )
     385                if ( 'ham_only' == $r['spam'] ) {
    356386                        $where_conditions['spam_sql'] = 'a.is_spam = 0';
    357                 elseif ( 'spam_only' == $spam )
     387                } elseif ( 'spam_only' == $r['spam'] ) {
    358388                        $where_conditions['spam_sql'] = 'a.is_spam = 1';
     389                }
    359390
    360391                // Searching
    361                 if ( $search_terms ) {
    362                         $search_terms_like = '%' . bp_esc_like( $search_terms ) . '%';
     392                if ( $r['search_terms'] ) {
     393                        $search_terms_like = '%' . bp_esc_like( $r['search_terms'] ) . '%';
    363394                        $where_conditions['search_sql'] = $wpdb->prepare( 'a.content LIKE %s', $search_terms_like );
    364395                }
    365396
    366                 // Filtering
    367                 if ( $filter && $filter_sql = BP_Activity_Activity::get_filter_sql( $filter ) )
    368                         $where_conditions['filter_sql'] = $filter_sql;
    369 
    370397                // Sorting
    371                 if ( $sort != 'ASC' && $sort != 'DESC' )
     398                $sort = $r['sort'];
     399                if ( $sort != 'ASC' && $sort != 'DESC' ) {
    372400                        $sort = 'DESC';
     401                }
    373402
    374403                // Hide Hidden Items?
    375                 if ( !$show_hidden )
     404                if ( ! $r['show_hidden'] )
    376405                        $where_conditions['hidden_sql'] = "a.hide_sitewide = 0";
    377406
    378407                // Exclude specified items
    379                 if ( !empty( $exclude ) ) {
    380                         $exclude = implode( ',', wp_parse_id_list( $exclude ) );
     408                if ( ! empty( $r['exclude'] ) ) {
     409                        $exclude = implode( ',', wp_parse_id_list( $r['exclude'] ) );
    381410                        $where_conditions['exclude'] = "a.id NOT IN ({$exclude})";
    382411                }
    383412
    384413                // The specific ids to which you want to limit the query
    385                 if ( !empty( $in ) ) {
    386                         $in = implode( ',', wp_parse_id_list( $in ) );
     414                if ( ! empty( $r['in'] ) ) {
     415                        $in = implode( ',', wp_parse_id_list( $r['in'] ) );
    387416                        $where_conditions['in'] = "a.id IN ({$in})";
    388417                }
    389418
    390419                // Process meta_query into SQL
    391                 $meta_query_sql = self::get_meta_query_sql( $meta_query );
     420                $meta_query_sql = self::get_meta_query_sql( $r['meta_query'] );
    392421
    393422                if ( ! empty( $meta_query_sql['join'] ) ) {
    394423                        $join_sql .= $meta_query_sql['join'];
     
    399428                }
    400429
    401430                // Process date_query into SQL
    402                 $date_query_sql = self::get_date_query_sql( $date_query );
     431                $date_query_sql = self::get_date_query_sql( $r['date_query'] );
    403432
    404433                if ( ! empty( $date_query_sql ) ) {
    405434                        $where_conditions['date'] = $date_query_sql;
     
    408437                // Alter the query based on whether we want to show activity item
    409438                // comments in the stream like normal comments or threaded below
    410439                // the activity.
    411                 if ( false === $display_comments || 'threaded' === $display_comments ) {
     440                if ( false === $r['display_comments'] || 'threaded' === $r['display_comments'] ) {
    412441                        $excluded_types[] = 'activity_comment';
    413442                }
    414443
    415444                // Exclude 'last_activity' items unless the 'action' filter has
    416445                // been explicitly set
    417                 if ( empty( $filter['object'] ) ) {
     446                if ( empty( $r['filter']['object'] ) ) {
    418447                        $excluded_types[] = 'last_activity';
    419448                }
    420449
     
    468497                }
    469498
    470499                // Sanitize page and per_page parameters
    471                 $page     = absint( $page     );
    472                 $per_page = absint( $per_page );
     500                $page     = absint( $r['page']     );
     501                $per_page = absint( $r['per_page'] );
    473502
    474503                $retval = array(
    475504                        'activities'     => null,
     
    517546                        }
    518547
    519548                } else {
    520 
    521549                        // Query first for activity IDs
    522550                        $activity_ids_sql = "{$select_sql} {$from_sql} {$join_sql} {$where_sql} ORDER BY a.date_recorded {$sort}";
    523551
     
    559587                        $activity_ids[] = $activity->id;
    560588                }
    561589
    562                 if ( ! empty( $activity_ids ) && $update_meta_cache ) {
     590                if ( ! empty( $activity_ids ) && $r['update_meta_cache'] ) {
    563591                        bp_activity_update_meta_cache( $activity_ids );
    564592                }
    565593
    566                 if ( $activities && $display_comments )
    567                         $activities = BP_Activity_Activity::append_comments( $activities, $spam );
     594                if ( $activities && $r['display_comments'] ) {
     595                        $activities = BP_Activity_Activity::append_comments( $activities, $r['spam'] );
     596                }
    568597
    569598                // Pre-fetch data associated with activity users and other objects
    570599                BP_Activity_Activity::prefetch_object_data( $activities );
     
    589618                        $total_activities_sql = apply_filters( 'bp_activity_total_activities_sql', "SELECT count(DISTINCT a.id) FROM {$bp->activity->table_name} a {$join_sql} {$where_sql}", $where_sql, $sort );
    590619                        $total_activities     = $wpdb->get_var( $total_activities_sql );
    591620
    592                         if ( !empty( $max ) ) {
    593                                 if ( (int) $total_activities > (int) $max )
    594                                         $total_activities = $max;
     621                        if ( !empty( $r['max'] ) ) {
     622                                if ( (int) $total_activities > (int) $r['max'] )
     623                                        $total_activities = $r['max'];
    595624                        }
    596625
    597626                        $retval['total'] = $total_activities;
     
    817846        }
    818847
    819848        /**
     849         * Get the SQL for the 'scope' param in BP_Activity_Activity::get().
     850         *
     851         * A scope is a predetermined set of activity arguments.  This method is used
     852         * to grab these activity arguments and override any existing args if needed.
     853         *
     854         * Can handle multple scopes.
     855         *
     856         * @since BuddyPress (2.2.0)
     857         *
     858         * @param  string $scope The activity scope
     859         * @param  array  $r     Current activity arguments. Same as those of BP_Activity_Activity::get(),
     860         *                       but merged with defaults.
     861         * @return array 'sql' WHERE SQL string and 'override' activity args
     862         */
     863        public static function get_scope_query_sql( $scope = '', $r = array() ) {
     864                $query_args = array();
     865                $override   = array();
     866                $retval     = array();
     867
     868                $scopes = explode( ',', $scope );
     869
     870                if ( empty( $scopes ) ) {
     871                        return $sql;
     872                }
     873
     874                // helper to easily grab the 'user_id'
     875                if ( ! empty( $r['filter']['user_id'] ) ) {
     876                        $r['user_id'] = $r['filter']['user_id'];
     877                }
     878                if ( empty( $r['user_id'] ) ) {
     879                        $r['user_id'] = bp_displayed_user_id() ? bp_displayed_user_id() : bp_loggedin_user_id();
     880                }
     881
     882                // parse each scope; yes! we handle multiples!
     883                foreach ( $scopes as $scope ) {
     884                        $scope_args = array();
     885
     886                        switch ( $scope ) {
     887                                // this is new as of BP 2.2
     888                                // primarily to be used when combining with other scopes
     889                                case 'personal' :
     890                                        $scope_args = array(
     891                                                'column' => 'user_id',
     892                                                'value'  => $r['user_id']
     893                                        );
     894
     895                                        break;
     896
     897                                case 'just-me' :
     898                                        $scope_args['override']['display_comments'] = 'stream';
     899
     900                                        break;
     901
     902                                case 'favorites':
     903                                        $favs = bp_activity_get_user_favorites( $r['user_id'] );
     904                                        if ( empty( $favs ) ) {
     905                                                return $scope_args;
     906                                        }
     907
     908                                        $scope_args = array(
     909                                                'column'  => 'id',
     910                                                'compare' => 'IN',
     911                                                'value'   => implode( ',', (array) $favs )
     912                                        );
     913                                        $scope_args['override']['display_comments']  = true;
     914                                        $scope_args['override']['filter']['user_id'] = 0;
     915
     916                                        break;
     917
     918                                case 'mentions':
     919                                        // Are mentions disabled?
     920                                        if ( ! bp_activity_do_mentions() ) {
     921                                                return $scope_args;
     922                                        }
     923
     924                                        $scope_args = array(
     925                                                'column'  => 'content',
     926                                                'compare' => 'LIKE',
     927
     928                                                // Start search at @ symbol and stop search at closing tag delimiter.
     929                                                'value'   => '@' . bp_activity_get_user_mentionname( $r['user_id'] ) . '<'
     930                                        );
     931
     932                                        // wipe out current search terms if any
     933                                        // this is so the 'mentions' scope can be combined with other scopes
     934                                        $scope_args['override']['search_terms'] = false;
     935
     936                                        $scope_args['override']['display_comments'] = 'stream';
     937                                        $scope_args['override']['filter']['user_id'] = 0;
     938
     939                                        break;
     940
     941                                default :
     942                                        /**
     943                                         * Plugins can hook here to set their activity arguments for custom scopes.
     944                                         *
     945                                         * This is a dynamic filter based on the activity scope. eg:
     946                                         *   - 'bp_activity_set_groups_scope_args'
     947                                         *   - 'bp_activity_set_friends_scope_args'
     948                                         *
     949                                         * To see how this filter is used, plugin devs should check out:
     950                                         *   - bp_groups_filter_activity_scope() - used for 'groups' scope
     951                                         *   - bp_friends_filter_activity_scope() - used for 'friends' scope
     952                                         *
     953                                         * @since BuddyPress (2.2.0)
     954                                         *
     955                                         *  @param array {
     956                                         *     Activity query clauses.
     957                                         *
     958                                         *     @type array {
     959                                         *         Activity arguments for your custom scope.
     960                                         *         See {@link BP_Activity_Query::_construct()} for more details.
     961                                         *     }
     962                                         *     @type array $override Optional. Override existing activity arguments passed by $r.
     963                                         * }
     964                                         * @param array $r Current activity arguments passed in BP_Activity_Activity::get()
     965                                         */
     966                                        $scope_args = apply_filters( "bp_activity_set_{$scope}_scope_args", array(), $r );
     967                                        break;
     968                        }
     969
     970                        if ( ! empty( $scope_args ) ) {
     971                                // @todo Fix 'hide_sitewide' with multiple scopes... needs more testing
     972                                if ( 'friends' !== $scope ) {
     973                                        $scope_args['override']['show_hidden'] = ( $r['user_id'] == bp_loggedin_user_id() ) ? true : false;
     974                                }
     975
     976                                // merge override properties from other scopes
     977                                // this might be a problem...
     978                                if ( ! empty( $scope_args['override'] ) ) {
     979                                        $override = array_merge( $override, $scope_args['override'] );
     980                                        unset( $scope_args['override'] );
     981                                }
     982
     983                                // save scope args
     984                                if ( ! empty( $scope_args ) ) {
     985                                        $query_args[] = $scope_args;
     986                                }
     987                        }
     988                }
     989
     990                if ( ! empty( $query_args ) ) {
     991                        // set relation to OR
     992                        $query_args['relation'] = 'OR';
     993
     994                        $query = new BP_Activity_Query( $query_args );
     995                        if ( $sql = $query->get_sql() ) {
     996                                $retval['sql'] = $sql;
     997                        }
     998                }
     999
     1000                if ( ! empty( $override ) ) {
     1001                        $retval['override'] = $override;
     1002                }
     1003
     1004                return $retval;
     1005        }
     1006
     1007        /**
    8201008         * In BuddyPress 1.2.x, this was used to retrieve specific activity stream items (for example, on an activity's permalink page).
    8211009         *
    8221010         * As of 1.5.x, use BP_Activity_Activity::get() with an 'in' parameter instead.
     
    14971685}
    14981686
    14991687/**
     1688 * Class for generating the WHERE SQL clause for advanced activity fetching.
     1689 *
     1690 * This is notably used in {@link BP_Activity_Activity::get()} with the
     1691 * 'filter_query' parameter.
     1692 *
     1693 * @since BuddyPress (2.2.0)
     1694 */
     1695class BP_Activity_Query extends BP_Recursive_Query {
     1696        /**
     1697         * Array of activity queries.
     1698         *
     1699         * See {@see BP_Activity_Query::__construct()} for information on query arguments.
     1700         *
     1701         * @since BuddyPress (2.2.0)
     1702         * @access public
     1703         * @var array
     1704         */
     1705        public $queries = array();
     1706
     1707        /**
     1708         * Table alias.
     1709         *
     1710         * @since BuddyPress (2.2.0)
     1711         * @access public
     1712         * @var string
     1713         */
     1714        public $table_alias = '';
     1715
     1716        /**
     1717         * Supported DB columns.
     1718         *
     1719         * See the 'wp_bp_activity' DB table schema.
     1720         *
     1721         * @since BuddyPress (2.2.0)
     1722         * @access public
     1723         * @var array
     1724         */
     1725        public $db_columns = array(
     1726                'id', 'user_id', 'component', 'type', 'action', 'content',
     1727                'item_id', 'secondary_item_id', 'hide_sitewide', 'is_spam',
     1728        );
     1729
     1730        /**
     1731         * Constructor.
     1732         *
     1733         * @since BuddyPress (2.2.0)
     1734         *
     1735         * @param array $query {
     1736         *     Array of query clauses.
     1737         *
     1738         *     @type array {
     1739         *         @type string $column   Required. The column to query against. Basically, any DB column in the main
     1740         *                                'wp_bp_activity' table.
     1741         *         @type string $value    Required. Value to filter by.
     1742         *         @type string $compare  Optional. The comparison operator. Default '='.
     1743         *                                Accepts '=', '!=', '>', '>=', '<', '<=', 'IN', 'NOT IN', 'LIKE',
     1744         *                                'NOT LIKE', BETWEEN', 'NOT BETWEEN', 'REGEXP', 'NOT REGEXP', 'RLIKE'
     1745         *         @type string $relation Optional. The boolean relationship between the activity queries.
     1746         *                                Accepts 'OR', 'AND'. Default 'AND'.
     1747         *         @type array {
     1748         *             Optional. Another fully-formed activity query. See parameters above.
     1749         *         }
     1750         *     }
     1751         * }
     1752         */
     1753        public function __construct( $query = array() ) {
     1754                if ( ! is_array( $query ) ) {
     1755                        return;
     1756                }
     1757
     1758                $this->queries = $this->sanitize_query( $query );
     1759        }
     1760
     1761        /**
     1762         * Generates WHERE SQL clause to be appended to a main query.
     1763         *
     1764         * @since BuddyPress (2.2.0)
     1765         * @access public
     1766         *
     1767         * @param string $alias An existing table alias that is compatible with the current query clause.
     1768         *               Default: 'a'. BP_Activity_Activity::get() uses 'a', so we default to that.
     1769         * @return string SQL fragment to append to the main WHERE clause.
     1770         * }
     1771         */
     1772        public function get_sql( $alias = 'a' ) {
     1773                if ( ! empty( $alias ) ) {
     1774                        $this->table_alias = sanitize_title( $alias );
     1775                }
     1776
     1777                $sql = $this->get_sql_clauses();
     1778
     1779                // we only need the 'where' clause
     1780                //
     1781                // also trim trailing "AND" clause from parent BP_Recursive_Query class
     1782                // since it's not necessary for our needs
     1783                return preg_replace( '/^\sAND/', '', $sql['where'] );
     1784        }
     1785
     1786        /**
     1787         * Generate WHERE clauses for a first-order clause.
     1788         *
     1789         * @since BuddyPress (2.2.0)
     1790         * @access protected
     1791         *
     1792         * @param  array $clause       Array of arguments belonging to the clause.
     1793         * @param  array $parent_query Parent query to which the clause belongs.
     1794         * @return array {
     1795         *     @type array $where Array of subclauses for the WHERE statement.
     1796         *     @type array $join  Empty array. Not used.
     1797         * }
     1798         */
     1799        protected function get_sql_for_clause( $clause, $parent_query ) {
     1800                global $wpdb;
     1801
     1802                $sql_chunks = array(
     1803                        'where' => array(),
     1804                        'join' => array(),
     1805                );
     1806
     1807                $column = isset( $clause['column'] ) ? $this->validate_column( $clause['column'] ) : '';
     1808                $value  = isset( $clause['value'] )  ? $clause['value'] : '';
     1809                if ( empty( $column ) || ! isset( $clause['value'] ) ) {
     1810                        return $sql_chunks;
     1811                }
     1812
     1813                if ( isset( $clause['compare'] ) ) {
     1814                        $clause['compare'] = strtoupper( $clause['compare'] );
     1815                } else {
     1816                        $clause['compare'] = isset( $clause['value'] ) && is_array( $clause['value'] ) ? 'IN' : '=';
     1817                }
     1818
     1819                // default 'compare' to '=' if no valid operator is found
     1820                if ( ! in_array( $clause['compare'], array(
     1821                        '=', '!=', '>', '>=', '<', '<=',
     1822                        'LIKE', 'NOT LIKE',
     1823                        'IN', 'NOT IN',
     1824                        'BETWEEN', 'NOT BETWEEN',
     1825                        'REGEXP', 'NOT REGEXP', 'RLIKE'
     1826
     1827                        // not supporting 'EXISTS' for now
     1828                        //'EXISTS', 'NOT EXISTS',
     1829                ) ) ) {
     1830                        $clause['compare'] = '=';
     1831                }
     1832
     1833                $compare = $clause['compare'];
     1834
     1835                // we do not support EXISTS / NOT EXISTS (hence no JOINs) so the alias is
     1836                // simple for now
     1837                $alias = ! empty( $this->table_alias ) ? "{$this->table_alias}." : '';
     1838
     1839                // Next, Build the WHERE clause.
     1840                $where = '';
     1841
     1842                // value.
     1843                if ( isset( $clause['value'] ) ) {
     1844                        // we don't support 'type' yet (do we even need to? probably not.)
     1845                        //$type = $this->get_cast_for_type( isset( $clause['type'] ) ? $clause['type'] : '' );
     1846
     1847                        if ( in_array( $compare, array( 'IN', 'NOT IN', 'BETWEEN', 'NOT BETWEEN' ) ) ) {
     1848                                if ( ! is_array( $value ) ) {
     1849                                        $value = preg_split( '/[,\s]+/', $value );
     1850                                }
     1851                        } else {
     1852                                $value = trim( $value );
     1853                        }
     1854
     1855                        // tinyint
     1856                        if ( ! empty( $column ) && true === in_array( $column, array( 'hide_sitewide', 'is_spam' ) ) ) {
     1857                                $sql_chunks['where'][] = $wpdb->prepare( "{$alias}{$column} = %d", $value );
     1858
     1859                        } else {
     1860                                switch ( $compare ) {
     1861                                        // IN uses different syntax
     1862                                        case 'IN' :
     1863                                        case 'NOT IN' :
     1864                                                $in_sql = BP_Activity_Activity::get_in_operator_sql( "{$alias}{$column}", $value );
     1865
     1866                                                // 'NOT IN' operator is as easy as a string replace!
     1867                                                if ( 'NOT IN' === $compare ) {
     1868                                                        $in_sql = str_replace( 'IN', 'NOT IN', $in_sql );
     1869                                                }
     1870
     1871                                                $sql_chunks['where'][] = $in_sql;
     1872                                                break;
     1873
     1874                                        case 'BETWEEN' :
     1875                                        case 'NOT BETWEEN' :
     1876                                                $value = array_slice( $value, 0, 2 );
     1877                                                $where = $wpdb->prepare( '%s AND %s', $value );
     1878                                                break;
     1879
     1880                                        case 'LIKE' :
     1881                                        case 'NOT LIKE' :
     1882                                                $value = '%' . bp_esc_like( $value ) . '%';
     1883                                                $where = $wpdb->prepare( '%s', $value );
     1884                                                break;
     1885
     1886                                        default :
     1887                                                $where = $wpdb->prepare( '%s', $value );
     1888                                                break;
     1889
     1890                                }
     1891                        }
     1892
     1893                        if ( $where ) {
     1894                                // no 'type' yet
     1895                                //$sql_chunks['where'][] = "CAST({$alias}{$column} AS {$type}) {$compare} {$where}";
     1896
     1897                                $sql_chunks['where'][] = "{$alias}{$column} {$compare} {$where}";
     1898                        }
     1899                }
     1900
     1901                /*
     1902                 * Multiple WHERE clauses should be joined in parentheses.
     1903                 */
     1904                if ( 1 < count( $sql_chunks['where'] ) ) {
     1905                        $sql_chunks['where'] = array( '( ' . implode( ' AND ', $sql_chunks['where'] ) . ' )' );
     1906                }
     1907
     1908                return $sql_chunks;
     1909        }
     1910
     1911        /**
     1912         * Determine whether a clause is first-order.
     1913         *
     1914         * @since BuddyPress (2.2.0)
     1915         * @access protected
     1916         *
     1917         * @param  array $q Clause to check.
     1918         * @return bool
     1919         */
     1920        protected function is_first_order_clause( $query ) {
     1921                return isset( $query['column'] ) || isset( $query['value'] );
     1922        }
     1923
     1924        /**
     1925         * Validates a column name parameter.
     1926         *
     1927         * Column names are checked against a whitelist of known tables.
     1928         * See {@link BP_Activity_Query::db_tables}.
     1929         *
     1930         * @since BuddyPress (2.2.0)
     1931         * @access public
     1932         *
     1933         * @param string $column The user-supplied column name.
     1934         * @return string A validated column name value.
     1935         */
     1936        public function validate_column( $column = '' ) {
     1937                if ( in_array( $column, $this->db_columns ) ) {
     1938                        return $column;
     1939                } else {
     1940                        return '';
     1941                }
     1942        }
     1943}
     1944
     1945/**
    15001946 * Create a RSS feed using the activity component.
    15011947 *
    15021948 * You should only construct a new feed when you've validated that you're on
  • src/bp-activity/bp-activity-functions.php

     
    14171417                'search_terms'      => false,        // Pass search terms as a string
    14181418                'meta_query'        => false,        // Filter by activity meta. See WP_Meta_Query for format
    14191419                'date_query'        => false,        // Filter by date. See first parameter of WP_Date_Query for format
     1420                'filter_query'      => false,
    14201421                'show_hidden'       => false,        // Show activity items that are hidden site-wide?
    14211422                'exclude'           => false,        // Comma-separated list of activity IDs to exclude
    14221423                'in'                => false,        // Comma-separated list or array of activity IDs to which you want to limit the query
    14231424                'spam'              => 'ham_only',   // 'ham_only' (default), 'spam_only' or 'all'.
    14241425                'update_meta_cache' => true,
    14251426                'count_total'       => false,
     1427                'scope'             => false,
    14261428
    14271429                /**
    14281430                 * Pass filters as an array -- all filter items can be multiple values comma separated:
     
    14381440        ) );
    14391441
    14401442        // Attempt to return a cached copy of the first page of sitewide activity.
    1441         if ( ( 1 === (int) $r['page'] ) && empty( $r['max'] ) && empty( $r['search_terms'] ) && empty( $r['meta_query'] ) && empty( $r['date_query'] ) && empty( $r['filter'] ) && empty( $r['exclude'] ) && empty( $r['in'] ) && ( 'DESC' === $r['sort'] ) && empty( $r['exclude'] ) && ( 'ham_only' === $r['spam'] ) ) {
     1443        if ( ( 1 === (int) $r['page'] ) && empty( $r['max'] ) && empty( $r['search_terms'] ) && empty( $r['meta_query'] ) && empty( $r['date_query'] ) && empty( $r['filter_query'] ) && empty( $r['filter'] ) && empty( $r['scope'] ) && empty( $r['exclude'] ) && empty( $r['in'] ) && ( 'DESC' === $r['sort'] ) && empty( $r['exclude'] ) && ( 'ham_only' === $r['spam'] ) ) {
    14421444
    14431445                $activity = wp_cache_get( 'bp_activity_sitewide_front', 'bp' );
    14441446                if ( false === $activity ) {
     
    14511453                                'search_terms'      => $r['search_terms'],
    14521454                                'meta_query'        => $r['meta_query'],
    14531455                                'date_query'        => $r['date_query'],
     1456                                'filter_query'      => $r['filter_query'],
    14541457                                'filter'            => $r['filter'],
     1458                                'scope'             => $r['scope'],
    14551459                                'display_comments'  => $r['display_comments'],
    14561460                                'show_hidden'       => $r['show_hidden'],
    14571461                                'spam'              => $r['spam'],
     
    14711475                        'search_terms'     => $r['search_terms'],
    14721476                        'meta_query'       => $r['meta_query'],
    14731477                        'date_query'       => $r['date_query'],
     1478                        'filter_query'     => $r['filter_query'],
    14741479                        'filter'           => $r['filter'],
     1480                        'scope'            => $r['scope'],
    14751481                        'display_comments' => $r['display_comments'],
    14761482                        'show_hidden'      => $r['show_hidden'],
    14771483                        'exclude'          => $r['exclude'],
  • src/bp-activity/bp-activity-template.php

     
    201201                        'exclude'           => false,
    202202                        'in'                => false,
    203203                        'filter'            => false,
     204                        'scope'             => false,
    204205                        'search_terms'      => false,
    205206                        'meta_query'        => false,
    206207                        'date_query'        => false,
     208                        'filter_query'      => false,
    207209                        'display_comments'  => 'threaded',
    208210                        'show_hidden'       => false,
    209211                        'spam'              => 'ham_only',
     
    249251                                'search_terms'      => $search_terms,
    250252                                'meta_query'        => $meta_query,
    251253                                'date_query'        => $date_query,
     254                                'filter_query'      => $filter_query,
    252255                                'filter'            => $filter,
     256                                'scope'             => $scope,
    253257                                'show_hidden'       => $show_hidden,
    254258                                'exclude'           => $exclude,
    255259                                'in'                => $in,
     
    611615
    612616                'meta_query'        => false,        // filter on activity meta. See WP_Meta_Query for format
    613617                'date_query'        => false,        // filter by date. See first parameter of WP_Date_Query for format
     618                'filter_query'      => false,        // advanced filtering.  This overrides a lot of stuff.
    614619
    615620                // Searching
    616621                'search_terms'      => false,        // specify terms to search on
     
    635640        if ( empty( $search_terms ) && ! empty( $_REQUEST['s'] ) )
    636641                $search_terms = $_REQUEST['s'];
    637642
    638         // If you have passed a "scope" then this will override any filters you have passed.
    639         if ( 'just-me' == $scope || 'friends' == $scope || 'groups' == $scope || 'favorites' == $scope || 'mentions' == $scope ) {
    640                 if ( 'just-me' == $scope )
    641                         $display_comments = 'stream';
    642 
    643                 // determine which user_id applies
    644                 if ( empty( $user_id ) )
    645                         $user_id = bp_displayed_user_id() ? bp_displayed_user_id() : bp_loggedin_user_id();
    646 
    647                 // are we displaying user specific activity?
    648                 if ( is_numeric( $user_id ) ) {
    649                         $show_hidden = ( $user_id == bp_loggedin_user_id() && $scope != 'friends' ) ? 1 : 0;
    650 
    651                         switch ( $scope ) {
    652                                 case 'friends':
    653                                         if ( bp_is_active( 'friends' ) )
    654                                                 $friends = friends_get_friend_user_ids( $user_id );
    655                                                 if ( empty( $friends ) )
    656                                                         return false;
    657 
    658                                                 $user_id = implode( ',', (array) $friends );
    659                                         break;
    660                                 case 'groups':
    661                                         if ( bp_is_active( 'groups' ) ) {
    662                                                 $groups = groups_get_user_groups( $user_id );
    663                                                 if ( empty( $groups['groups'] ) )
    664                                                         return false;
    665 
    666                                                 $object = $bp->groups->id;
    667                                                 $primary_id = implode( ',', (array) $groups['groups'] );
    668 
    669                                                 $user_id = 0;
    670                                         }
    671                                         break;
    672                                 case 'favorites':
    673                                         $favs = bp_activity_get_user_favorites( $user_id );
    674                                         if ( empty( $favs ) )
    675                                                 return false;
    676 
    677                                         $in = implode( ',', (array) $favs );
    678                                         $display_comments = true;
    679                                         $user_id = 0;
    680                                         break;
    681                                 case 'mentions':
    682 
    683                                         // Are mentions disabled?
    684                                         if ( ! bp_activity_do_mentions() ) {
    685                                                 return false;
    686                                         }
    687 
    688                                         // Start search at @ symbol and stop search at closing tag delimiter.
    689                                         $search_terms     = '@' . bp_activity_get_user_mentionname( $user_id ) . '<';
    690                                         $display_comments = 'stream';
    691                                         $user_id = 0;
    692                                         break;
    693                         }
    694                 }
    695         }
    696 
    697643        // Do not exceed the maximum per page
    698644        if ( !empty( $max ) && ( (int) $per_page > (int) $max ) )
    699645                $per_page = $max;
     
    709655         *
    710656         * @param bool $value True if BuddyPress should enable afilter support.
    711657         */
    712         if ( isset( $_GET['afilter'] ) && apply_filters( 'bp_activity_enable_afilter_support', false ) )
     658        if ( isset( $_GET['afilter'] ) && apply_filters( 'bp_activity_enable_afilter_support', false ) ) {
    713659                $filter = array( 'object' => $_GET['afilter'] );
    714         else if ( ! empty( $user_id ) || ! empty( $object ) || ! empty( $action ) || ! empty( $primary_id ) || ! empty( $secondary_id ) || ! empty( $offset ) || ! empty( $since ) )
     660        } else if ( ! empty( $user_id ) || ! empty( $object ) || ! empty( $action ) || ! empty( $primary_id ) || ! empty( $secondary_id ) || ! empty( $offset ) || ! empty( $since ) ) {
    715661                $filter = array( 'user_id' => $user_id, 'object' => $object, 'action' => $action, 'primary_id' => $primary_id, 'secondary_id' => $secondary_id, 'offset' => $offset, 'since' => $since );
    716         else
     662        } else {
    717663                $filter = false;
     664        }
    718665
    719666        // If specific activity items have been requested, override the $hide_spam argument. This prevents backpat errors with AJAX.
    720667        if ( !empty( $include ) && ( 'ham_only' == $spam ) )
     
    731678                'exclude'           => $exclude,
    732679                'in'                => $in,
    733680                'filter'            => $filter,
     681                'scope'             => $scope,
    734682                'search_terms'      => $search_terms,
    735683                'meta_query'        => $meta_query,
    736684                'date_query'        => $date_query,
     685                'filter_query'      => $filter_query,
    737686                'display_comments'  => $display_comments,
    738687                'show_hidden'       => $show_hidden,
    739688                'spam'              => $spam,
  • src/bp-core/bp-core-classes.php

     
    27112711                return apply_filters( 'bp_members_suggestions_get_suggestions', $results, $this );
    27122712        }
    27132713}
     2714
     2715/**
     2716 * Base class for creating query classes that generate SQL fragments for filtering results based on recursive query params.
     2717 *
     2718 * @since BuddyPress (2.2.0)
     2719 */
     2720abstract class BP_Recursive_Query {
     2721
     2722        /**
     2723         * Query arguments passed to the constructor.
     2724         *
     2725         * @since BuddyPress (2.2.0)
     2726         * @access public
     2727         * @var array
     2728         */
     2729        public $queries = array();
     2730
     2731        /**
     2732         * Generate SQL clauses to be appended to a main query.
     2733         *
     2734         * Extending classes should call this method from within a publicly
     2735         * accessible get_sql() method, and manipulate the SQL as necessary.
     2736         * For example, {@link BP_XProfile_Query::get_sql()} is merely a wrapper for
     2737         * get_sql_clauses(), while {@link BP_Activity_Query::get_sql()} discards
     2738         * the empty 'join' clauses are discarded, and passes the 'where'
     2739         * clause through apply_filters().
     2740         *
     2741         * @since BuddyPress (2.2.0)
     2742         * @access protected
     2743         *
     2744         * @param  string $primary_table
     2745         * @param  string $primary_id_column
     2746         * @return array
     2747         */
     2748        protected function get_sql_clauses() {
     2749                $sql = $this->get_sql_for_query( $this->queries );
     2750
     2751                if ( ! empty( $sql['where'] ) ) {
     2752                        $sql['where'] = ' AND ' . "\n" . $sql['where'] . "\n";
     2753                }
     2754
     2755                return $sql;
     2756        }
     2757
     2758        /**
     2759         * Generate SQL clauses for a single query array.
     2760         *
     2761         * If nested subqueries are found, this method recurses the tree to
     2762         * produce the properly nested SQL.
     2763         *
     2764         * Subclasses generally do not need to call this method. It is invoked
     2765         * automatically from get_sql_clauses().
     2766         *
     2767         * @since BuddyPress (2.2.0)
     2768         * @access protected
     2769         *
     2770         * @param  array $query Query to parse.
     2771         * @param  int   $depth Optional. Number of tree levels deep we
     2772         *                      currently are. Used to calculate indentation.
     2773         * @return array
     2774         */
     2775        protected function get_sql_for_query( $query, $depth = 0 ) {
     2776                $sql_chunks = array(
     2777                        'join'  => array(),
     2778                        'where' => array(),
     2779                );
     2780
     2781                $sql = array(
     2782                        'join'  => '',
     2783                        'where' => '',
     2784                );
     2785
     2786                $indent = '';
     2787                for ( $i = 0; $i < $depth; $i++ ) {
     2788                        $indent .= "\t";
     2789                }
     2790
     2791                foreach ( $query as $key => $clause ) {
     2792                        if ( 'relation' === $key ) {
     2793                                $relation = $query['relation'];
     2794                        } else if ( is_array( $clause ) ) {
     2795                                // This is a first-order clause
     2796                                if ( $this->is_first_order_clause( $clause ) ) {
     2797                                        $clause_sql = $this->get_sql_for_clause( $clause, $query );
     2798
     2799                                        $where_count = count( $clause_sql['where'] );
     2800                                        if ( ! $where_count ) {
     2801                                                $sql_chunks['where'][] = '';
     2802                                        } else if ( 1 === $where_count ) {
     2803                                                $sql_chunks['where'][] = $clause_sql['where'][0];
     2804                                        } else {
     2805                                                $sql_chunks['where'][] = '( ' . implode( ' AND ', $clause_sql['where'] ) . ' )';
     2806                                        }
     2807
     2808                                        $sql_chunks['join'] = array_merge( $sql_chunks['join'], $clause_sql['join'] );
     2809                                // This is a subquery
     2810                                } else {
     2811                                        $clause_sql = $this->get_sql_for_query( $clause, $depth + 1 );
     2812
     2813                                        $sql_chunks['where'][] = $clause_sql['where'];
     2814                                        $sql_chunks['join'][]  = $clause_sql['join'];
     2815
     2816                                }
     2817                        }
     2818                }
     2819
     2820                // Filter empties
     2821                $sql_chunks['join']  = array_filter( $sql_chunks['join'] );
     2822                $sql_chunks['where'] = array_filter( $sql_chunks['where'] );
     2823
     2824                if ( empty( $relation ) ) {
     2825                        $relation = 'AND';
     2826                }
     2827
     2828                if ( ! empty( $sql_chunks['join'] ) ) {
     2829                        $sql['join'] = implode( ' ', array_unique( $sql_chunks['join'] ) );
     2830                }
     2831
     2832                if ( ! empty( $sql_chunks['where'] ) ) {
     2833                        $sql['where'] = '( ' . "\n\t" . $indent . implode( ' ' . "\n\t" . $indent . $relation . ' ' . "\n\t" . $indent, $sql_chunks['where'] ) . "\n" . $indent . ')' . "\n";
     2834                }
     2835
     2836                return $sql;
     2837        }
     2838
     2839        /**
     2840         * Recursive-friendly query sanitizer.
     2841         *
     2842         * Ensures that each query-level clause has a 'relation' key, and that
     2843         * each first-order clause contains all the necessary keys from
     2844         * $defaults.
     2845         *
     2846         * Extend this method if your class uses different sanitizing logic.
     2847         *
     2848         * @since BuddyPress (2.2.0)
     2849         * @access public
     2850         *
     2851         * @param  array $queries Array of query clauses.
     2852         * @return array Sanitized array of query clauses.
     2853         */
     2854        protected function sanitize_query( $queries ) {
     2855                $clean_queries = array();
     2856
     2857                if ( ! is_array( $queries ) ) {
     2858                        return $clean_queries;
     2859                }
     2860
     2861                foreach ( $queries as $key => $query ) {
     2862                        if ( 'relation' === $key ) {
     2863                                $relation = $query;
     2864
     2865                        } else if ( ! is_array( $query ) ) {
     2866                                continue;
     2867
     2868                        // First-order clause.
     2869                        } else if ( $this->is_first_order_clause( $query ) ) {
     2870                                if ( isset( $query['value'] ) && array() === $query['value'] ) {
     2871                                        unset( $query['value'] );
     2872                                }
     2873
     2874                                $clean_queries[] = $query;
     2875
     2876                        // Otherwise, it's a nested query, so we recurse.
     2877                        } else {
     2878                                $cleaned_query = $this->sanitize_query( $query );
     2879
     2880                                if ( ! empty( $cleaned_query ) ) {
     2881                                        $clean_queries[] = $cleaned_query;
     2882                                }
     2883                        }
     2884                }
     2885
     2886                if ( empty( $clean_queries ) ) {
     2887                        return $clean_queries;
     2888                }
     2889
     2890                // Sanitize the 'relation' key provided in the query.
     2891                if ( isset( $relation ) && 'OR' === strtoupper( $relation ) ) {
     2892                        $clean_queries['relation'] = 'OR';
     2893
     2894                /*
     2895                 * If there is only a single clause, call the relation 'OR'.
     2896                 * This value will not actually be used to join clauses, but it
     2897                 * simplifies the logic around combining key-only queries.
     2898                 */
     2899                } else if ( 1 === count( $clean_queries ) ) {
     2900                        $clean_queries['relation'] = 'OR';
     2901
     2902                // Default to AND.
     2903                } else {
     2904                        $clean_queries['relation'] = 'AND';
     2905                }
     2906
     2907                return $clean_queries;
     2908        }
     2909
     2910        /**
     2911         * Generate JOIN and WHERE clauses for a first-order clause.
     2912         *
     2913         * Must be overridden in a subclass.
     2914         *
     2915         * @since BuddyPress (2.2.0)
     2916         * @access protected
     2917         *
     2918         * @param  array $clause       Array of arguments belonging to the clause.
     2919         * @param  array $parent_query Parent query to which the clause belongs.
     2920         * @return array {
     2921         *     @type array $join  Array of subclauses for the JOIN statement.
     2922         *     @type array $where Array of subclauses for the WHERE statement.
     2923         * }
     2924         */
     2925        abstract protected function get_sql_for_clause( $clause, $parent_query );
     2926
     2927        /**
     2928         * Determine whether a clause is first-order.
     2929         *
     2930         * Must be overridden in a subclass.
     2931         *
     2932         * @since BuddyPress (2.2.0)
     2933         * @access protected
     2934         *
     2935         * @param  array $q Clause to check.
     2936         * @return bool
     2937         */
     2938        abstract protected function is_first_order_clause( $query );
     2939}
     2940 No newline at end of file
  • src/bp-friends/bp-friends-activity.php

     
    228228add_filter( 'bp_activity_prefetch_object_data', 'bp_friends_prefetch_activity_object_data' );
    229229
    230230/**
     231 * Set up activity arguments for use with the 'friends' scope.
     232 *
     233 * For details on the syntax, see {@link BP_Activity_Query}.
     234 *
     235 * @since BuddyPress (2.2.0)
     236 *
     237 * @param array $retval Empty array by default
     238 * @param array $filter Current activity arguments
     239 * @return array
     240 */
     241function bp_friends_filter_activity_scope( $retval, $filter ) {
     242        $friends = friends_get_friend_user_ids( $filter['user_id'] );
     243
     244        if ( empty( $friends ) ) {
     245                return $retval;
     246        }
     247
     248        $retval= array(
     249                'relation' => 'AND',
     250                array(
     251                        'column'  => 'user_id',
     252                        'compare' => 'IN',
     253                        'value'   => implode( ',', (array) $friends )
     254                ),
     255                // we should only be able to view sitewide activity content for friends
     256                array(
     257                        'column' => 'hide_sitewide',
     258                        'value'  => 0
     259                ),
     260        );
     261
     262        // wipe out the user ID
     263        $retval['override']['filter']['user_id'] = 0;
     264
     265        return $retval;
     266}
     267add_filter( 'bp_activity_set_friends_scope_args', 'bp_friends_filter_activity_scope', 10, 2 );
     268
     269/**
    231270 * Add activity stream items when one members accepts another members request
    232271 * for virtual friendship.
    233272 *
  • src/bp-groups/bp-groups-activity.php

     
    180180add_filter( 'bp_activity_prefetch_object_data', 'bp_groups_prefetch_activity_object_data' );
    181181
    182182/**
     183 * Set up activity arguments for use with the 'groups' scope.
     184 *
     185 * @since BuddyPress (2.2.0)
     186 *
     187 * @param array $retval Empty array by default
     188 * @param array $filter Current activity arguments
     189 * @return array
     190 */
     191function bp_groups_filter_activity_scope( $retval, $filter ) {
     192        $groups = groups_get_user_groups( $filter['user_id'] );
     193
     194        if ( empty( $groups['groups'] ) ) {
     195                return $retval;
     196        }
     197
     198        $retval= array(
     199                'relation' => 'AND',
     200                array(
     201                        'column' => 'component',
     202                        'value'  => buddypress()->groups->id
     203                ),
     204                array(
     205                        'column'  => 'item_id',
     206                        'compare' => 'IN',
     207                        'value'   => implode( ',', (array) $groups['groups'] )
     208                ),
     209        );
     210
     211        // wipe out the user ID
     212        $retval['override']['filter']['user_id'] = 0;
     213
     214        return $retval;
     215}
     216add_filter( 'bp_activity_set_groups_scope_args', 'bp_groups_filter_activity_scope', 10, 2 );
     217
     218/**
    183219 * Record an activity item related to the Groups component.
    184220 *
    185221 * A wrapper for {@link bp_activity_add()} that provides some Groups-specific
  • tests/phpunit/testcases/activity/template.php

     
    8989         * limiting query to user favorites
    9090         *
    9191         * @ticket BP4872
     92         * @group scope
    9293         */
    9394        public function test_bp_has_activities_favorites_action_filter() {
    9495                $user_id = $this->factory->user->create( array( 'role' => 'subscriber' ) );
     
    143144        }
    144145
    145146        /**
     147         * @group scope
     148         * @group filter_query
     149         * @group BP_Activity_Query
     150         */
     151        function test_bp_has_activities_mentions_scope() {
     152                $u1 = $this->factory->user->create();
     153                $u2 = $this->factory->user->create();
     154
     155                $now = time();
     156
     157                // mentioned activity item
     158                $mention_username = '@' . bp_activity_get_user_mentionname( $u1 );
     159                $a1 = $this->factory->activity->create( array(
     160                        'user_id' => $u2,
     161                        'type'    => 'activity_update',
     162                        'content' => "{$mention_username} - You rule, dude!",
     163                        'recorded_time' => date( 'Y-m-d H:i:s', $now ),
     164                ) );
     165
     166                // misc activity items
     167                $this->factory->activity->create( array(
     168                        'user_id'   => $u1,
     169                        'component' => 'blogs',
     170                        'item_id'   => 1,
     171                        'type'      => 'new_blog_post',
     172                        'recorded_time' => date( 'Y-m-d H:i:s', $now - 100 ),
     173                ) );
     174                $this->factory->activity->create( array(
     175                        'user_id'   => $u2,
     176                        'component' => 'activity',
     177                        'type'      => 'activity_update',
     178                        'recorded_time' => date( 'Y-m-d H:i:s', $now - 100 ),
     179                ) );
     180                $this->factory->activity->create( array(
     181                        'user_id'   => $u2,
     182                        'component' => 'groups',
     183                        'item_id'   => 324,
     184                        'type'      => 'activity_update',
     185                        'recorded_time' => date( 'Y-m-d H:i:s', $now - 100 ),
     186                ) );
     187
     188                global $activities_template;
     189
     190                // grab activities from multiple scopes
     191                bp_has_activities( array(
     192                        'user_id' => $u1,
     193                        'scope' => 'mentions',
     194                ) );
     195
     196                // assert!
     197                $this->assertEqualSets( array( $a1 ), wp_list_pluck( $activities_template->activities, 'id' ) );
     198
     199                // clean up!
     200                $activities_template = null;
     201        }
     202
     203        /**
     204         * @group scope
     205         * @group filter_query
     206         * @group BP_Activity_Query
     207         */
     208        function test_bp_has_activities_friends_and_mentions_scope() {
     209                $u1 = $this->factory->user->create();
     210                $u2 = $this->factory->user->create();
     211                $u3 = $this->factory->user->create();
     212
     213                // user 1 becomes friends with user 2
     214                friends_add_friend( $u1, $u2, true );
     215
     216                $now = time();
     217
     218                // friend status update
     219                $a1 = $this->factory->activity->create( array(
     220                        'user_id' => $u2,
     221                        'type' => 'activity_update',
     222                        'recorded_time' => date( 'Y-m-d H:i:s', $now ),
     223                ) );
     224
     225                // mentioned item by non-friend
     226                $mention_username = '@' . bp_activity_get_user_mentionname( $u1 );
     227                $a2 = $this->factory->activity->create( array(
     228                        'user_id'   => $u3,
     229                        'component' => 'activity',
     230                        'type'      => 'activity_update',
     231                        'content'   => "{$mention_username} - Oy!",
     232                        'recorded_time' => date( 'Y-m-d H:i:s', $now - 100 ),
     233                ) );
     234
     235                // misc activity items
     236                $this->factory->activity->create( array(
     237                        'user_id'   => $u1,
     238                        'component' => 'blogs',
     239                        'item_id'   => 1,
     240                        'type'      => 'new_blog_post',
     241                        'recorded_time' => date( 'Y-m-d H:i:s', $now - 100 ),
     242                ) );
     243                $this->factory->activity->create( array(
     244                        'user_id'   => $u3,
     245                        'component' => 'activity',
     246                        'type'      => 'activity_update',
     247                        'recorded_time' => date( 'Y-m-d H:i:s', $now - 100 ),
     248                ) );
     249                $this->factory->activity->create( array(
     250                        'user_id'   => $u3,
     251                        'component' => 'groups',
     252                        'item_id'   => 324,
     253                        'type'      => 'activity_update',
     254                        'recorded_time' => date( 'Y-m-d H:i:s', $now - 100 ),
     255                ) );
     256
     257                global $activities_template;
     258
     259                // grab activities from multiple scopes
     260                bp_has_activities( array(
     261                        'user_id' => $u1,
     262                        'scope' => 'mentions,friends',
     263                ) );
     264
     265                // assert!
     266                $this->assertEqualSets( array( $a1, $a2 ), wp_list_pluck( $activities_template->activities, 'id' ) );
     267
     268                // clean up!
     269                $activities_template = null;
     270        }
     271
     272        /**
     273         * @group scope
     274         * @group filter_query
     275         * @group BP_Activity_Query
     276         */
     277        function test_bp_has_activities_groups_and_friends_scope() {
     278                $u1 = $this->factory->user->create();
     279                $u2 = $this->factory->user->create();
     280                $u3 = $this->factory->user->create();
     281
     282                // user 1 becomes friends with user 2
     283                friends_add_friend( $u1, $u2, true );
     284
     285                // user 1 joins a group
     286                $g1 = $this->factory->group->create( array( 'creator_id' => $u1 ) );
     287                $g2 = $this->factory->group->create( array( 'creator_id' => $u1 ) );
     288
     289                $now = time();
     290
     291                // friend status update
     292                $a1 = $this->factory->activity->create( array(
     293                        'user_id' => $u2,
     294                        'type' => 'activity_update',
     295                        'recorded_time' => date( 'Y-m-d H:i:s', $now ),
     296                ) );
     297
     298                // group activity
     299                $a2 = $this->factory->activity->create( array(
     300                        'user_id'   => $u3,
     301                        'component' => 'groups',
     302                        'item_id'   => $g1,
     303                        'type'      => 'joined_group',
     304                        'recorded_time' => date( 'Y-m-d H:i:s', $now - 100 ),
     305                ) );
     306
     307                // misc activity items
     308                $this->factory->activity->create( array(
     309                        'user_id'   => $u3,
     310                        'component' => 'blogs',
     311                        'item_id'   => 1,
     312                        'type'      => 'new_blog_post',
     313                        'recorded_time' => date( 'Y-m-d H:i:s', $now - 100 ),
     314                ) );
     315                $this->factory->activity->create( array(
     316                        'user_id'   => $u3,
     317                        'component' => 'activity',
     318                        'type'      => 'activity_update',
     319                        'recorded_time' => date( 'Y-m-d H:i:s', $now - 100 ),
     320                ) );
     321                $this->factory->activity->create( array(
     322                        'user_id'   => $u3,
     323                        'component' => 'groups',
     324                        'item_id'   => 324,
     325                        'type'      => 'activity_update',
     326                        'recorded_time' => date( 'Y-m-d H:i:s', $now - 100 ),
     327                ) );
     328
     329                global $activities_template;
     330
     331                // grab activities from multiple scopes
     332                bp_has_activities( array(
     333                        'user_id' => $u1,
     334                        'scope' => 'groups,friends',
     335                ) );
     336
     337                // assert!
     338                $this->assertEqualSets( array( $a1, $a2 ), wp_list_pluck( $activities_template->activities, 'id' ) );
     339
     340                // clean up!
     341                $activities_template = null;
     342        }
     343
     344        /**
     345         * @group filter_query
     346         * @group BP_Activity_Query
     347         */
     348        function test_bp_has_activities_with_filter_query_nested_conditions() {
     349                $u1 = $this->factory->user->create();
     350                $u2 = $this->factory->user->create();
     351                $u3 = $this->factory->user->create();
     352
     353                $now = time();
     354
     355                $a1 = $this->factory->activity->create( array(
     356                        'user_id'   => $u3,
     357                        'component' => 'blogs',
     358                        'item_id'   => 1,
     359                        'type'      => 'new_blog_post',
     360                        'recorded_time' => date( 'Y-m-d H:i:s', $now - 100 ),
     361                ) );
     362                $a2 = $this->factory->activity->create( array(
     363                        'user_id'   => $u2,
     364                        'component' => 'activity',
     365                        'type'      => 'activity_update',
     366                        'recorded_time' => date( 'Y-m-d H:i:s', $now - 100 ),
     367                ) );
     368
     369                // misc activity items
     370                $this->factory->activity->create( array(
     371                        'user_id'   => $u3,
     372                        'component' => 'activity',
     373                        'type'      => 'activity_update',
     374                        'recorded_time' => date( 'Y-m-d H:i:s', $now - 100 ),
     375                ) );
     376                $this->factory->activity->create( array(
     377                        'user_id'   => $u3,
     378                        'component' => 'groups',
     379                        'item_id'   => 324,
     380                        'type'      => 'activity_update',
     381                        'recorded_time' => date( 'Y-m-d H:i:s', $now - 100 ),
     382                ) );
     383
     384                global $activities_template;
     385
     386                bp_has_activities( array(
     387                        'filter_query' => array(
     388                                'relation' => 'OR',
     389                                array(
     390                                        'column' => 'component',
     391                                        'value'  => 'blogs',
     392                                ),
     393                                array(
     394                                        'relation' => 'AND',
     395                                        array(
     396                                                'column' => 'type',
     397                                                'value'  => 'activity_update',
     398                                        ),
     399                                        array(
     400                                                'column' => 'user_id',
     401                                                'value'  => $u2,
     402                                        ),
     403                                ),
     404                        )
     405                ) );
     406
     407                // assert!
     408                $this->assertEqualSets( array( $a1, $a2 ), wp_list_pluck( $activities_template->activities, 'id' ) );
     409
     410                // clean up!
     411                $activities_template = null;
     412        }
     413
     414        /**
     415         * @group filter_query
     416         * @group BP_Activity_Query
     417         */
     418        function test_bp_has_activities_with_filter_query_compare_not_in_operator() {
     419                $u1 = $this->factory->user->create();
     420                $u2 = $this->factory->user->create();
     421                $u3 = $this->factory->user->create();
     422
     423                $now = time();
     424
     425                // misc activity items
     426                $a1 = $this->factory->activity->create( array(
     427                        'user_id'   => $u3,
     428                        'component' => 'blogs',
     429                        'item_id'   => 1,
     430                        'type'      => 'new_blog_post',
     431                        'recorded_time' => date( 'Y-m-d H:i:s', $now - 100 ),
     432                ) );
     433                $a2 = $this->factory->activity->create( array(
     434                        'user_id'   => $u2,
     435                        'component' => 'activity',
     436                        'type'      => 'activity_update',
     437                        'recorded_time' => date( 'Y-m-d H:i:s', $now - 100 ),
     438                ) );
     439                $a3 = $this->factory->activity->create( array(
     440                        'user_id'   => $u3,
     441                        'component' => 'activity',
     442                        'type'      => 'activity_update',
     443                        'recorded_time' => date( 'Y-m-d H:i:s', $now - 100 ),
     444                ) );
     445                $a4 = $this->factory->activity->create( array(
     446                        'user_id'   => $u3,
     447                        'component' => 'groups',
     448                        'item_id'   => 324,
     449                        'type'      => 'activity_update',
     450                        'recorded_time' => date( 'Y-m-d H:i:s', $now - 100 ),
     451                ) );
     452
     453                global $activities_template;
     454
     455                bp_has_activities( array(
     456                        'filter_query' => array(
     457                                array(
     458                                        'column'  => 'id',
     459                                        'compare' => 'NOT IN',
     460                                        'value'   => array( $a1, $a4 ),
     461                                ),
     462                        )
     463                ) );
     464
     465                // assert!
     466                $this->assertEqualSets( array( $a2, $a3 ), wp_list_pluck( $activities_template->activities, 'id' ) );
     467
     468                // clean up!
     469                $activities_template = null;
     470        }
     471
     472        /**
     473         * @group filter_query
     474         * @group BP_Activity_Query
     475         */
     476        function test_bp_has_activities_with_filter_query_compare_between_operator() {
     477                $u1 = $this->factory->user->create();
     478
     479                $now = time();
     480
     481                // misc activity items
     482                $a1 = $this->factory->activity->create( array(
     483                        'user_id'   => $u1,
     484                        'component' => 'blogs',
     485                        'item_id'   => 1,
     486                        'type'      => 'new_blog_post',
     487                        'recorded_time' => date( 'Y-m-d H:i:s', $now - 100 ),
     488                ) );
     489                $a2 = $this->factory->activity->create( array(
     490                        'user_id'   => $u1,
     491                        'component' => 'activity',
     492                        'type'      => 'activity_update',
     493                        'recorded_time' => date( 'Y-m-d H:i:s', $now - 100 ),
     494                ) );
     495                $a3 = $this->factory->activity->create( array(
     496                        'user_id'   => $u1,
     497                        'component' => 'activity',
     498                        'type'      => 'activity_update',
     499                        'recorded_time' => date( 'Y-m-d H:i:s', $now - 100 ),
     500                ) );
     501                $a4 = $this->factory->activity->create( array(
     502                        'user_id'   => $u1,
     503                        'component' => 'groups',
     504                        'item_id'   => 324,
     505                        'type'      => 'activity_update',
     506                        'recorded_time' => date( 'Y-m-d H:i:s', $now - 100 ),
     507                ) );
     508
     509                global $activities_template;
     510
     511                bp_has_activities( array(
     512                        'filter_query' => array(
     513                                array(
     514                                        'column'  => 'id',
     515                                        'compare' => 'BETWEEN',
     516                                        'value'   => array( $a3, $a4 ),
     517                                ),
     518                        )
     519                ) );
     520
     521                // assert!
     522                $this->assertEqualSets( array( $a3, $a4 ), wp_list_pluck( $activities_template->activities, 'id' ) );
     523
     524                // clean up!
     525                $activities_template = null;
     526        }
     527
     528        /**
     529         * @group filter_query
     530         * @group BP_Activity_Query
     531         */
     532        function test_bp_has_activities_with_filter_query_compare_arithmetic_comparisons() {
     533                $u1 = $this->factory->user->create();
     534
     535                $now = time();
     536
     537                // misc activity items
     538                $a1 = $this->factory->activity->create( array(
     539                        'user_id'   => $u1,
     540                        'component' => 'activity',
     541                        'item_id'   => 1,
     542                        'type'      => 'activity_update',
     543                        'recorded_time' => date( 'Y-m-d H:i:s', $now - 100 ),
     544                ) );
     545                $a2 = $this->factory->activity->create( array(
     546                        'user_id'   => $u1,
     547                        'component' => 'activity',
     548                        'item_id'   => 10,
     549                        'type'      => 'activity_update',
     550                        'recorded_time' => date( 'Y-m-d H:i:s', $now - 100 ),
     551                ) );
     552                $a3 = $this->factory->activity->create( array(
     553                        'user_id'   => $u1,
     554                        'component' => 'activity',
     555                        'item_id'   => 25,
     556                        'type'      => 'activity_update',
     557                        'recorded_time' => date( 'Y-m-d H:i:s', $now - 100 ),
     558                ) );
     559                $a4 = $this->factory->activity->create( array(
     560                        'user_id'   => $u1,
     561                        'component' => 'activity',
     562                        'item_id'   => 100,
     563                        'type'      => 'activity_update',
     564                        'recorded_time' => date( 'Y-m-d H:i:s', $now - 100 ),
     565                ) );
     566
     567                global $activities_template;
     568
     569                // greater than
     570                bp_has_activities( array(
     571                        'filter_query' => array(
     572                                array(
     573                                        'column'  => 'item_id',
     574                                        'compare' => '>',
     575                                        'value'   => 10,
     576                                ),
     577                        )
     578                ) );
     579
     580                // assert!
     581                $this->assertEqualSets( array( $a3, $a4 ), wp_list_pluck( $activities_template->activities, 'id' ) );
     582
     583                // greater or equal than
     584                bp_has_activities( array(
     585                        'filter_query' => array(
     586                                array(
     587                                        'column'  => 'item_id',
     588                                        'compare' => '>=',
     589                                        'value'   => 10,
     590                                ),
     591                        )
     592                ) );
     593
     594                // assert!
     595                $this->assertEqualSets( array( $a2, $a3, $a4 ), wp_list_pluck( $activities_template->activities, 'id' ) );
     596
     597                // less than
     598                bp_has_activities( array(
     599                        'filter_query' => array(
     600                                array(
     601                                        'column'  => 'item_id',
     602                                        'compare' => '<',
     603                                        'value'   => 10,
     604                                ),
     605                        )
     606                ) );
     607
     608                // assert!
     609                $this->assertEqualSets( array( $a1 ), wp_list_pluck( $activities_template->activities, 'id' ) );
     610
     611                // less or equal than
     612                bp_has_activities( array(
     613                        'filter_query' => array(
     614                                array(
     615                                        'column'  => 'item_id',
     616                                        'compare' => '<=',
     617                                        'value'   => 10,
     618                                ),
     619                        )
     620                ) );
     621
     622                // assert!
     623                $this->assertEqualSets( array( $a1, $a2 ), wp_list_pluck( $activities_template->activities, 'id' ) );
     624
     625                // not equal to
     626                bp_has_activities( array(
     627                        'filter_query' => array(
     628                                array(
     629                                        'column'  => 'item_id',
     630                                        'compare' => '!=',
     631                                        'value'   => 10,
     632                                ),
     633                        )
     634                ) );
     635
     636                // assert!
     637                $this->assertEqualSets( array( $a1, $a3, $a4 ), wp_list_pluck( $activities_template->activities, 'id' ) );
     638
     639                // clean up!
     640                $activities_template = null;
     641        }
     642
     643        /**
     644         * @group filter_query
     645         * @group BP_Activity_Query
     646         */
     647        function test_bp_has_activities_with_filter_query_compare_regex() {
     648                $u1 = $this->factory->user->create();
     649
     650                $now = time();
     651
     652                // misc activity items
     653                $a1 = $this->factory->activity->create( array(
     654                        'user_id'   => $u1,
     655                        'component' => 'blogs',
     656                        'item_id'   => 1,
     657                        'type'      => 'new_blog_post',
     658                        'recorded_time' => date( 'Y-m-d H:i:s', $now - 100 ),
     659                ) );
     660                $a2 = $this->factory->activity->create( array(
     661                        'user_id'   => $u1,
     662                        'component' => 'blogs',
     663                        'type'      => 'new_blog_comment',
     664                        'recorded_time' => date( 'Y-m-d H:i:s', $now - 100 ),
     665                ) );
     666                $a3 = $this->factory->activity->create( array(
     667                        'user_id'   => $u1,
     668                        'component' => 'activity',
     669                        'type'      => 'activity_update',
     670                        'recorded_time' => date( 'Y-m-d H:i:s', $now - 100 ),
     671                ) );
     672                $a4 = $this->factory->activity->create( array(
     673                        'user_id'   => $u1,
     674                        'component' => 'groups',
     675                        'item_id'   => 324,
     676                        'type'      => 'activity_update',
     677                        'recorded_time' => date( 'Y-m-d H:i:s', $now - 100 ),
     678                ) );
     679
     680                global $activities_template;
     681
     682                // REGEXP
     683                bp_has_activities( array(
     684                        'filter_query' => array(
     685                                array(
     686                                        'column'  => 'type',
     687                                        'compare' => 'REGEXP',
     688                                        'value'   => '^new_blog_',
     689                                ),
     690                        )
     691                ) );
     692
     693                // assert!
     694                $this->assertEqualSets( array( $a1, $a2 ), wp_list_pluck( $activities_template->activities, 'id' ) );
     695
     696                // RLIKE is a synonym for REGEXP
     697                bp_has_activities( array(
     698                        'filter_query' => array(
     699                                array(
     700                                        'column'  => 'type',
     701                                        'compare' => 'RLIKE',
     702                                        'value'   => '^new_blog_',
     703                                ),
     704                        )
     705                ) );
     706
     707                // assert!
     708                $this->assertEqualSets( array( $a1, $a2 ), wp_list_pluck( $activities_template->activities, 'id' ) );
     709
     710                // NOT REGEXP
     711                bp_has_activities( array(
     712                        'filter_query' => array(
     713                                array(
     714                                        'column'  => 'type',
     715                                        'compare' => 'NOT REGEXP',
     716                                        'value'   => '^new_blog_',
     717                                ),
     718                        )
     719                ) );
     720
     721                // assert!
     722                $this->assertEqualSets( array( $a3, $a4 ), wp_list_pluck( $activities_template->activities, 'id' ) );
     723
     724                // clean up!
     725                $activities_template = null;
     726        }
     727
     728        /**
    146729         * Integration test for 'meta_query' param
    147730         */
    148731        function test_bp_has_activities_with_meta_query() {