Skip to:
Content

BuddyPress.org

Ticket #4988: 4988.04.patch

File 4988.04.patch, 49.2 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
     
    350355                // Excluded types
    351356                $excluded_types = array();
    352357
     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
    353379                // Regular filtering
    354380                if ( $r['filter'] && $filter_sql = BP_Activity_Activity::get_filter_sql( $r['filter'] ) ) {
    355381                        $where_conditions['filter_sql'] = $filter_sql;
     
    520546                        }
    521547
    522548                } else {
    523 
    524549                        // Query first for activity IDs
    525550                        $activity_ids_sql = "{$select_sql} {$from_sql} {$join_sql} {$where_sql} ORDER BY a.date_recorded {$sort}";
    526551
     
    821846        }
    822847
    823848        /**
     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                if ( ! is_array( $scope ) ) {
     869                        $scopes = explode( ',', $scope );
     870                } else {
     871                        $scopes = $scope;
     872                }
     873
     874                if ( empty( $scopes ) ) {
     875                        return $sql;
     876                }
     877
     878                // helper to easily grab the 'user_id'
     879                if ( ! empty( $r['filter']['user_id'] ) ) {
     880                        $r['user_id'] = $r['filter']['user_id'];
     881                }
     882
     883                // parse each scope; yes! we handle multiples!
     884                foreach ( $scopes as $scope ) {
     885                        $scope_args = array();
     886
     887                        switch ( $scope ) {
     888                                case 'just-me' :
     889                                        $scope_args = array(
     890                                                'column' => 'user_id',
     891                                                'value'  => $r['user_id']
     892                                        );
     893
     894                                        $scope_args['override']['display_comments'] = 'stream';
     895
     896                                        // wipe out the user ID
     897                                        $scope_args['override']['filter']['user_id'] = 0;
     898
     899                                        break;
     900
     901                                case 'favorites':
     902                                        $favs = bp_activity_get_user_favorites( $r['user_id'] );
     903                                        if ( empty( $favs ) ) {
     904                                                return $scope_args;
     905                                        }
     906
     907                                        $scope_args = array(
     908                                                'column'  => 'id',
     909                                                'compare' => 'IN',
     910                                                'value'   => (array) $favs
     911                                        );
     912                                        $scope_args['override']['display_comments']  = true;
     913
     914                                        // wipe out the user ID
     915                                        $scope_args['override']['filter']['user_id'] = 0;
     916
     917                                        break;
     918
     919                                case 'mentions':
     920                                        // Are mentions disabled?
     921                                        if ( ! bp_activity_do_mentions() ) {
     922                                                return $scope_args;
     923                                        }
     924
     925                                        $scope_args = array(
     926                                                'column'  => 'content',
     927                                                'compare' => 'LIKE',
     928
     929                                                // Start search at @ symbol and stop search at closing tag delimiter.
     930                                                'value'   => '@' . bp_activity_get_user_mentionname( $r['user_id'] ) . '<'
     931                                        );
     932
     933                                        // wipe out current search terms if any
     934                                        // this is so the 'mentions' scope can be combined with other scopes
     935                                        $scope_args['override']['search_terms'] = false;
     936
     937                                        $scope_args['override']['display_comments'] = 'stream';
     938                                        $scope_args['override']['filter']['user_id'] = 0;
     939
     940                                        break;
     941
     942                                default :
     943                                        /**
     944                                         * Plugins can hook here to set their activity arguments for custom scopes.
     945                                         *
     946                                         * This is a dynamic filter based on the activity scope. eg:
     947                                         *   - 'bp_activity_set_groups_scope_args'
     948                                         *   - 'bp_activity_set_friends_scope_args'
     949                                         *
     950                                         * To see how this filter is used, plugin devs should check out:
     951                                         *   - bp_groups_filter_activity_scope() - used for 'groups' scope
     952                                         *   - bp_friends_filter_activity_scope() - used for 'friends' scope
     953                                         *
     954                                         * @since BuddyPress (2.2.0)
     955                                         *
     956                                         *  @param array {
     957                                         *     Activity query clauses.
     958                                         *
     959                                         *     @type array {
     960                                         *         Activity arguments for your custom scope.
     961                                         *         See {@link BP_Activity_Query::_construct()} for more details.
     962                                         *     }
     963                                         *     @type array $override Optional. Override existing activity arguments passed by $r.
     964                                         * }
     965                                         * @param array $r Current activity arguments passed in BP_Activity_Activity::get()
     966                                         */
     967                                        $scope_args = apply_filters( "bp_activity_set_{$scope}_scope_args", array(), $r );
     968                                        break;
     969                        }
     970
     971                        if ( ! empty( $scope_args ) ) {
     972                                // merge override properties from other scopes
     973                                // this might be a problem...
     974                                if ( ! empty( $scope_args['override'] ) ) {
     975                                        $override = array_merge( $override, $scope_args['override'] );
     976                                        unset( $scope_args['override'] );
     977                                }
     978
     979                                // save scope args
     980                                if ( ! empty( $scope_args ) ) {
     981                                        $query_args[] = $scope_args;
     982                                }
     983                        }
     984                }
     985
     986                if ( ! empty( $query_args ) ) {
     987                        // set relation to OR
     988                        $query_args['relation'] = 'OR';
     989
     990                        $query = new BP_Activity_Query( $query_args );
     991                        if ( $sql = $query->get_sql() ) {
     992                                $retval['sql'] = $sql;
     993                        }
     994                }
     995
     996                if ( ! empty( $override ) ) {
     997                        $retval['override'] = $override;
     998                }
     999
     1000                return $retval;
     1001        }
     1002
     1003        /**
    8241004         * In BuddyPress 1.2.x, this was used to retrieve specific activity stream items (for example, on an activity's permalink page).
    8251005         *
    8261006         * As of 1.5.x, use BP_Activity_Activity::get() with an 'in' parameter instead.
     
    15011681}
    15021682
    15031683/**
     1684 * Class for generating the WHERE SQL clause for advanced activity fetching.
     1685 *
     1686 * This is notably used in {@link BP_Activity_Activity::get()} with the
     1687 * 'filter_query' parameter.
     1688 *
     1689 * @since BuddyPress (2.2.0)
     1690 */
     1691class BP_Activity_Query extends BP_Recursive_Query {
     1692        /**
     1693         * Array of activity queries.
     1694         *
     1695         * See {@see BP_Activity_Query::__construct()} for information on query arguments.
     1696         *
     1697         * @since BuddyPress (2.2.0)
     1698         * @access public
     1699         * @var array
     1700         */
     1701        public $queries = array();
     1702
     1703        /**
     1704         * Table alias.
     1705         *
     1706         * @since BuddyPress (2.2.0)
     1707         * @access public
     1708         * @var string
     1709         */
     1710        public $table_alias = '';
     1711
     1712        /**
     1713         * Supported DB columns.
     1714         *
     1715         * See the 'wp_bp_activity' DB table schema.
     1716         *
     1717         * @since BuddyPress (2.2.0)
     1718         * @access public
     1719         * @var array
     1720         */
     1721        public $db_columns = array(
     1722                'id', 'user_id', 'component', 'type', 'action', 'content',
     1723                'item_id', 'secondary_item_id', 'hide_sitewide', 'is_spam',
     1724        );
     1725
     1726        /**
     1727         * Constructor.
     1728         *
     1729         * @since BuddyPress (2.2.0)
     1730         *
     1731         * @param array $query {
     1732         *     Array of query clauses.
     1733         *
     1734         *     @type array {
     1735         *         @type string $column   Required. The column to query against. Basically, any DB column in the main
     1736         *                                'wp_bp_activity' table.
     1737         *         @type string $value    Required. Value to filter by.
     1738         *         @type string $compare  Optional. The comparison operator. Default '='.
     1739         *                                Accepts '=', '!=', '>', '>=', '<', '<=', 'IN', 'NOT IN', 'LIKE',
     1740         *                                'NOT LIKE', BETWEEN', 'NOT BETWEEN', 'REGEXP', 'NOT REGEXP', 'RLIKE'
     1741         *         @type string $relation Optional. The boolean relationship between the activity queries.
     1742         *                                Accepts 'OR', 'AND'. Default 'AND'.
     1743         *         @type array {
     1744         *             Optional. Another fully-formed activity query. See parameters above.
     1745         *         }
     1746         *     }
     1747         * }
     1748         */
     1749        public function __construct( $query = array() ) {
     1750                if ( ! is_array( $query ) ) {
     1751                        return;
     1752                }
     1753
     1754                $this->queries = $this->sanitize_query( $query );
     1755        }
     1756
     1757        /**
     1758         * Generates WHERE SQL clause to be appended to a main query.
     1759         *
     1760         * @since BuddyPress (2.2.0)
     1761         * @access public
     1762         *
     1763         * @param string $alias An existing table alias that is compatible with the current query clause.
     1764         *               Default: 'a'. BP_Activity_Activity::get() uses 'a', so we default to that.
     1765         * @return string SQL fragment to append to the main WHERE clause.
     1766         * }
     1767         */
     1768        public function get_sql( $alias = 'a' ) {
     1769                if ( ! empty( $alias ) ) {
     1770                        $this->table_alias = sanitize_title( $alias );
     1771                }
     1772
     1773                $sql = $this->get_sql_clauses();
     1774
     1775                // we only need the 'where' clause
     1776                //
     1777                // also trim trailing "AND" clause from parent BP_Recursive_Query class
     1778                // since it's not necessary for our needs
     1779                return preg_replace( '/^\sAND/', '', $sql['where'] );
     1780        }
     1781
     1782        /**
     1783         * Generate WHERE clauses for a first-order clause.
     1784         *
     1785         * @since BuddyPress (2.2.0)
     1786         * @access protected
     1787         *
     1788         * @param  array $clause       Array of arguments belonging to the clause.
     1789         * @param  array $parent_query Parent query to which the clause belongs.
     1790         * @return array {
     1791         *     @type array $where Array of subclauses for the WHERE statement.
     1792         *     @type array $join  Empty array. Not used.
     1793         * }
     1794         */
     1795        protected function get_sql_for_clause( $clause, $parent_query ) {
     1796                global $wpdb;
     1797
     1798                $sql_chunks = array(
     1799                        'where' => array(),
     1800                        'join' => array(),
     1801                );
     1802
     1803                $column = isset( $clause['column'] ) ? $this->validate_column( $clause['column'] ) : '';
     1804                $value  = isset( $clause['value'] )  ? $clause['value'] : '';
     1805                if ( empty( $column ) || ! isset( $clause['value'] ) ) {
     1806                        return $sql_chunks;
     1807                }
     1808
     1809                if ( isset( $clause['compare'] ) ) {
     1810                        $clause['compare'] = strtoupper( $clause['compare'] );
     1811                } else {
     1812                        $clause['compare'] = isset( $clause['value'] ) && is_array( $clause['value'] ) ? 'IN' : '=';
     1813                }
     1814
     1815                // default 'compare' to '=' if no valid operator is found
     1816                if ( ! in_array( $clause['compare'], array(
     1817                        '=', '!=', '>', '>=', '<', '<=',
     1818                        'LIKE', 'NOT LIKE',
     1819                        'IN', 'NOT IN',
     1820                        'BETWEEN', 'NOT BETWEEN',
     1821                        'REGEXP', 'NOT REGEXP', 'RLIKE'
     1822                ) ) ) {
     1823                        $clause['compare'] = '=';
     1824                }
     1825
     1826                $compare = $clause['compare'];
     1827
     1828                $alias = ! empty( $this->table_alias ) ? "{$this->table_alias}." : '';
     1829
     1830                // Next, Build the WHERE clause.
     1831                $where = '';
     1832
     1833                // value.
     1834                if ( isset( $clause['value'] ) ) {
     1835                        if ( in_array( $compare, array( 'IN', 'NOT IN', 'BETWEEN', 'NOT BETWEEN' ) ) ) {
     1836                                if ( ! is_array( $value ) ) {
     1837                                        $value = preg_split( '/[,\s]+/', $value );
     1838                                }
     1839                        }
     1840
     1841                        // tinyint
     1842                        if ( ! empty( $column ) && true === in_array( $column, array( 'hide_sitewide', 'is_spam' ) ) ) {
     1843                                $sql_chunks['where'][] = $wpdb->prepare( "{$alias}{$column} = %d", $value );
     1844
     1845                        } else {
     1846                                switch ( $compare ) {
     1847                                        // IN uses different syntax
     1848                                        case 'IN' :
     1849                                        case 'NOT IN' :
     1850                                                $in_sql = BP_Activity_Activity::get_in_operator_sql( "{$alias}{$column}", $value );
     1851
     1852                                                // 'NOT IN' operator is as easy as a string replace!
     1853                                                if ( 'NOT IN' === $compare ) {
     1854                                                        $in_sql = str_replace( 'IN', 'NOT IN', $in_sql );
     1855                                                }
     1856
     1857                                                $sql_chunks['where'][] = $in_sql;
     1858                                                break;
     1859
     1860                                        case 'BETWEEN' :
     1861                                        case 'NOT BETWEEN' :
     1862                                                $value = array_slice( $value, 0, 2 );
     1863                                                $where = $wpdb->prepare( '%s AND %s', $value );
     1864                                                break;
     1865
     1866                                        case 'LIKE' :
     1867                                        case 'NOT LIKE' :
     1868                                                $value = '%' . bp_esc_like( $value ) . '%';
     1869                                                $where = $wpdb->prepare( '%s', $value );
     1870                                                break;
     1871
     1872                                        default :
     1873                                                $where = $wpdb->prepare( '%s', $value );
     1874                                                break;
     1875
     1876                                }
     1877                        }
     1878
     1879                        if ( $where ) {
     1880                                $sql_chunks['where'][] = "{$alias}{$column} {$compare} {$where}";
     1881                        }
     1882                }
     1883
     1884                /*
     1885                 * Multiple WHERE clauses should be joined in parentheses.
     1886                 */
     1887                if ( 1 < count( $sql_chunks['where'] ) ) {
     1888                        $sql_chunks['where'] = array( '( ' . implode( ' AND ', $sql_chunks['where'] ) . ' )' );
     1889                }
     1890
     1891                return $sql_chunks;
     1892        }
     1893
     1894        /**
     1895         * Determine whether a clause is first-order.
     1896         *
     1897         * @since BuddyPress (2.2.0)
     1898         * @access protected
     1899         *
     1900         * @param  array $q Clause to check.
     1901         * @return bool
     1902         */
     1903        protected function is_first_order_clause( $query ) {
     1904                return isset( $query['column'] ) || isset( $query['value'] );
     1905        }
     1906
     1907        /**
     1908         * Validates a column name parameter.
     1909         *
     1910         * Column names are checked against a whitelist of known tables.
     1911         * See {@link BP_Activity_Query::db_tables}.
     1912         *
     1913         * @since BuddyPress (2.2.0)
     1914         * @access public
     1915         *
     1916         * @param string $column The user-supplied column name.
     1917         * @return string A validated column name value.
     1918         */
     1919        public function validate_column( $column = '' ) {
     1920                if ( in_array( $column, $this->db_columns ) ) {
     1921                        return $column;
     1922                } else {
     1923                        return '';
     1924                }
     1925        }
     1926}
     1927
     1928/**
    15041929 * Create a RSS feed using the activity component.
    15051930 *
    15061931 * 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.  See BP_Activity_Query for format
    614619
    615620                // Searching
    616621                'search_terms'      => false,        // specify terms to search on
     
    632637                $page = 0;
    633638        }
    634639
    635         if ( empty( $search_terms ) && ! empty( $_REQUEST['s'] ) )
     640        // Search terms
     641        if ( empty( $search_terms ) && ! empty( $_REQUEST['s'] ) ) {
    636642                $search_terms = $_REQUEST['s'];
     643        }
    637644
    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        // Set some default arguments when using a scope
     646        if ( ! empty( $scope ) ) {
     647                // Determine which user ID applies
     648                if ( empty( $user_id ) ) {
    645649                        $user_id = bp_displayed_user_id() ? bp_displayed_user_id() : bp_loggedin_user_id();
     650                }
    646651
    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                         }
     652                // Should we show all items regardless of sitewide visibility?
     653                if ( ! empty( $user_id ) ) {
     654                        $show_hidden = ( $user_id == bp_loggedin_user_id() ) ? 1 : 0;
    694655                }
    695656        }
    696657
    697658        // Do not exceed the maximum per page
    698         if ( !empty( $max ) && ( (int) $per_page > (int) $max ) )
     659        if ( ! empty( $max ) && ( (int) $per_page > (int) $max ) ) {
    699660                $per_page = $max;
     661        }
    700662
    701663        /**
    702664         * Filters whether BuddyPress should enable afilter support.
     
    709671         *
    710672         * @param bool $value True if BuddyPress should enable afilter support.
    711673         */
    712         if ( isset( $_GET['afilter'] ) && apply_filters( 'bp_activity_enable_afilter_support', false ) )
     674        if ( isset( $_GET['afilter'] ) && apply_filters( 'bp_activity_enable_afilter_support', false ) ) {
    713675                $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 ) )
     676        } else if ( ! empty( $user_id ) || ! empty( $object ) || ! empty( $action ) || ! empty( $primary_id ) || ! empty( $secondary_id ) || ! empty( $offset ) || ! empty( $since ) ) {
    715677                $filter = array( 'user_id' => $user_id, 'object' => $object, 'action' => $action, 'primary_id' => $primary_id, 'secondary_id' => $secondary_id, 'offset' => $offset, 'since' => $since );
    716         else
     678        } else {
    717679                $filter = false;
     680        }
    718681
    719682        // If specific activity items have been requested, override the $hide_spam argument. This prevents backpat errors with AJAX.
    720         if ( !empty( $include ) && ( 'ham_only' == $spam ) )
     683        if ( ! empty( $include ) && ( 'ham_only' == $spam ) ) {
    721684                $spam = 'all';
     685        }
    722686
    723687        $template_args = array(
    724688                'page'              => $page,
     
    731695                'exclude'           => $exclude,
    732696                'in'                => $in,
    733697                'filter'            => $filter,
     698                'scope'             => $scope,
    734699                'search_terms'      => $search_terms,
    735700                'meta_query'        => $meta_query,
    736701                'date_query'        => $date_query,
     702                'filter_query'      => $filter_query,
    737703                'display_comments'  => $display_comments,
    738704                'show_hidden'       => $show_hidden,
    739705                'spam'              => $spam,
  • src/bp-core/bp-core-classes.php

     
    27542754                return apply_filters( 'bp_members_suggestions_get_suggestions', $results, $this );
    27552755        }
    27562756}
     2757
     2758/**
     2759 * Base class for creating query classes that generate SQL fragments for filtering results based on recursive query params.
     2760 *
     2761 * @since BuddyPress (2.2.0)
     2762 */
     2763abstract class BP_Recursive_Query {
     2764
     2765        /**
     2766         * Query arguments passed to the constructor.
     2767         *
     2768         * @since BuddyPress (2.2.0)
     2769         * @access public
     2770         * @var array
     2771         */
     2772        public $queries = array();
     2773
     2774        /**
     2775         * Generate SQL clauses to be appended to a main query.
     2776         *
     2777         * Extending classes should call this method from within a publicly
     2778         * accessible get_sql() method, and manipulate the SQL as necessary.
     2779         * For example, {@link BP_XProfile_Query::get_sql()} is merely a wrapper for
     2780         * get_sql_clauses(), while {@link BP_Activity_Query::get_sql()} discards
     2781         * the empty 'join' clauses are discarded, and passes the 'where'
     2782         * clause through apply_filters().
     2783         *
     2784         * @since BuddyPress (2.2.0)
     2785         * @access protected
     2786         *
     2787         * @param  string $primary_table
     2788         * @param  string $primary_id_column
     2789         * @return array
     2790         */
     2791        protected function get_sql_clauses() {
     2792                $sql = $this->get_sql_for_query( $this->queries );
     2793
     2794                if ( ! empty( $sql['where'] ) ) {
     2795                        $sql['where'] = ' AND ' . "\n" . $sql['where'] . "\n";
     2796                }
     2797
     2798                return $sql;
     2799        }
     2800
     2801        /**
     2802         * Generate SQL clauses for a single query array.
     2803         *
     2804         * If nested subqueries are found, this method recurses the tree to
     2805         * produce the properly nested SQL.
     2806         *
     2807         * Subclasses generally do not need to call this method. It is invoked
     2808         * automatically from get_sql_clauses().
     2809         *
     2810         * @since BuddyPress (2.2.0)
     2811         * @access protected
     2812         *
     2813         * @param  array $query Query to parse.
     2814         * @param  int   $depth Optional. Number of tree levels deep we
     2815         *                      currently are. Used to calculate indentation.
     2816         * @return array
     2817         */
     2818        protected function get_sql_for_query( $query, $depth = 0 ) {
     2819                $sql_chunks = array(
     2820                        'join'  => array(),
     2821                        'where' => array(),
     2822                );
     2823
     2824                $sql = array(
     2825                        'join'  => '',
     2826                        'where' => '',
     2827                );
     2828
     2829                $indent = '';
     2830                for ( $i = 0; $i < $depth; $i++ ) {
     2831                        $indent .= "\t";
     2832                }
     2833
     2834                foreach ( $query as $key => $clause ) {
     2835                        if ( 'relation' === $key ) {
     2836                                $relation = $query['relation'];
     2837                        } else if ( is_array( $clause ) ) {
     2838                                // This is a first-order clause
     2839                                if ( $this->is_first_order_clause( $clause ) ) {
     2840                                        $clause_sql = $this->get_sql_for_clause( $clause, $query );
     2841
     2842                                        $where_count = count( $clause_sql['where'] );
     2843                                        if ( ! $where_count ) {
     2844                                                $sql_chunks['where'][] = '';
     2845                                        } else if ( 1 === $where_count ) {
     2846                                                $sql_chunks['where'][] = $clause_sql['where'][0];
     2847                                        } else {
     2848                                                $sql_chunks['where'][] = '( ' . implode( ' AND ', $clause_sql['where'] ) . ' )';
     2849                                        }
     2850
     2851                                        $sql_chunks['join'] = array_merge( $sql_chunks['join'], $clause_sql['join'] );
     2852                                // This is a subquery
     2853                                } else {
     2854                                        $clause_sql = $this->get_sql_for_query( $clause, $depth + 1 );
     2855
     2856                                        $sql_chunks['where'][] = $clause_sql['where'];
     2857                                        $sql_chunks['join'][]  = $clause_sql['join'];
     2858
     2859                                }
     2860                        }
     2861                }
     2862
     2863                // Filter empties
     2864                $sql_chunks['join']  = array_filter( $sql_chunks['join'] );
     2865                $sql_chunks['where'] = array_filter( $sql_chunks['where'] );
     2866
     2867                if ( empty( $relation ) ) {
     2868                        $relation = 'AND';
     2869                }
     2870
     2871                if ( ! empty( $sql_chunks['join'] ) ) {
     2872                        $sql['join'] = implode( ' ', array_unique( $sql_chunks['join'] ) );
     2873                }
     2874
     2875                if ( ! empty( $sql_chunks['where'] ) ) {
     2876                        $sql['where'] = '( ' . "\n\t" . $indent . implode( ' ' . "\n\t" . $indent . $relation . ' ' . "\n\t" . $indent, $sql_chunks['where'] ) . "\n" . $indent . ')' . "\n";
     2877                }
     2878
     2879                return $sql;
     2880        }
     2881
     2882        /**
     2883         * Recursive-friendly query sanitizer.
     2884         *
     2885         * Ensures that each query-level clause has a 'relation' key, and that
     2886         * each first-order clause contains all the necessary keys from
     2887         * $defaults.
     2888         *
     2889         * Extend this method if your class uses different sanitizing logic.
     2890         *
     2891         * @since BuddyPress (2.2.0)
     2892         * @access public
     2893         *
     2894         * @param  array $queries Array of query clauses.
     2895         * @return array Sanitized array of query clauses.
     2896         */
     2897        protected function sanitize_query( $queries ) {
     2898                $clean_queries = array();
     2899
     2900                if ( ! is_array( $queries ) ) {
     2901                        return $clean_queries;
     2902                }
     2903
     2904                foreach ( $queries as $key => $query ) {
     2905                        if ( 'relation' === $key ) {
     2906                                $relation = $query;
     2907
     2908                        } else if ( ! is_array( $query ) ) {
     2909                                continue;
     2910
     2911                        // First-order clause.
     2912                        } else if ( $this->is_first_order_clause( $query ) ) {
     2913                                if ( isset( $query['value'] ) && array() === $query['value'] ) {
     2914                                        unset( $query['value'] );
     2915                                }
     2916
     2917                                $clean_queries[] = $query;
     2918
     2919                        // Otherwise, it's a nested query, so we recurse.
     2920                        } else {
     2921                                $cleaned_query = $this->sanitize_query( $query );
     2922
     2923                                if ( ! empty( $cleaned_query ) ) {
     2924                                        $clean_queries[] = $cleaned_query;
     2925                                }
     2926                        }
     2927                }
     2928
     2929                if ( empty( $clean_queries ) ) {
     2930                        return $clean_queries;
     2931                }
     2932
     2933                // Sanitize the 'relation' key provided in the query.
     2934                if ( isset( $relation ) && 'OR' === strtoupper( $relation ) ) {
     2935                        $clean_queries['relation'] = 'OR';
     2936
     2937                /*
     2938                 * If there is only a single clause, call the relation 'OR'.
     2939                 * This value will not actually be used to join clauses, but it
     2940                 * simplifies the logic around combining key-only queries.
     2941                 */
     2942                } else if ( 1 === count( $clean_queries ) ) {
     2943                        $clean_queries['relation'] = 'OR';
     2944
     2945                // Default to AND.
     2946                } else {
     2947                        $clean_queries['relation'] = 'AND';
     2948                }
     2949
     2950                return $clean_queries;
     2951        }
     2952
     2953        /**
     2954         * Generate JOIN and WHERE clauses for a first-order clause.
     2955         *
     2956         * Must be overridden in a subclass.
     2957         *
     2958         * @since BuddyPress (2.2.0)
     2959         * @access protected
     2960         *
     2961         * @param  array $clause       Array of arguments belonging to the clause.
     2962         * @param  array $parent_query Parent query to which the clause belongs.
     2963         * @return array {
     2964         *     @type array $join  Array of subclauses for the JOIN statement.
     2965         *     @type array $where Array of subclauses for the WHERE statement.
     2966         * }
     2967         */
     2968        abstract protected function get_sql_for_clause( $clause, $parent_query );
     2969
     2970        /**
     2971         * Determine whether a clause is first-order.
     2972         *
     2973         * Must be overridden in a subclass.
     2974         *
     2975         * @since BuddyPress (2.2.0)
     2976         * @access protected
     2977         *
     2978         * @param  array $q Clause to check.
     2979         * @return bool
     2980         */
     2981        abstract protected function is_first_order_clause( $query );
     2982}
     2983 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'   => (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        // make sure we aren't limiting items by 'hide_sitewide' since we're already
     266        // limiting it above
     267        $scope_args['override']['show_hidden'] = true;
     268
     269        return $retval;
     270}
     271add_filter( 'bp_activity_set_friends_scope_args', 'bp_friends_filter_activity_scope', 10, 2 );
     272
     273/**
    231274 * Add activity stream items when one members accepts another members request
    232275 * for virtual friendship.
    233276 *
  • src/bp-groups/bp-groups-activity.php

     
    234234add_filter( 'bp_activity_prefetch_object_data', 'bp_groups_prefetch_activity_object_data' );
    235235
    236236/**
     237 * Set up activity arguments for use with the 'groups' scope.
     238 *
     239 * @since BuddyPress (2.2.0)
     240 *
     241 * @param array $retval Empty array by default
     242 * @param array $filter Current activity arguments
     243 * @return array
     244 */
     245function bp_groups_filter_activity_scope( $retval, $filter ) {
     246        $groups = groups_get_user_groups( $filter['user_id'] );
     247
     248        if ( empty( $groups['groups'] ) ) {
     249                return $retval;
     250        }
     251
     252        $retval= array(
     253                'relation' => 'AND',
     254                array(
     255                        'column' => 'component',
     256                        'value'  => buddypress()->groups->id
     257                ),
     258                array(
     259                        'column'  => 'item_id',
     260                        'compare' => 'IN',
     261                        'value'   => (array) $groups['groups']
     262                ),
     263        );
     264
     265        // wipe out the user ID
     266        $retval['override']['filter']['user_id'] = 0;
     267
     268        return $retval;
     269}
     270add_filter( 'bp_activity_set_groups_scope_args', 'bp_groups_filter_activity_scope', 10, 2 );
     271
     272/**
    237273 * Record an activity item related to the Groups component.
    238274 *
    239275 * 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() {