Ticket #4988: 4988.02.patch
| File 4988.02.patch, 53.5 KB (added by , 11 years ago) |
|---|
-
src/bp-activity/bp-activity-classes.php
275 275 * @type array $date_query An array of date_query conditions. 276 276 * See first parameter of WP_Date_Query::__construct() 277 277 * for description. 278 * @type array $filter_query An array of activity query conditions. 279 * See BP_Activity_Query::__construct() 280 * for description. 278 281 * @type array $filter See BP_Activity_Activity::get_filter_sql(). 279 282 * @type string $search_terms Limit results by a search term. 280 283 * Default: false. … … 327 330 'in' => false, // Array of ids to limit query by (IN) 328 331 'meta_query' => false, // Filter by activitymeta 329 332 'date_query' => false, // Filter by date 333 'filter_query' => false, // Advanced filtering - see BP_Activity_Query 330 334 'filter' => false, // See self::get_filter_sql() 335 'scope' => false, // Preset activity arguments 331 336 'search_terms' => false, // Terms to search by 332 337 'display_comments' => false, // Whether to include activity comments 333 338 'show_hidden' => false, // Show items marked hide_sitewide … … 336 341 'count_total' => false, 337 342 ); 338 343 $r = wp_parse_args( $args, $defaults ); 339 extract( $r );340 344 341 345 // Select conditions 342 346 $select_sql = "SELECT DISTINCT a.id"; … … 351 355 // Excluded types 352 356 $excluded_types = array(); 353 357 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 354 384 // Spam 355 if ( 'ham_only' == $ spam )385 if ( 'ham_only' == $r['spam'] ) { 356 386 $where_conditions['spam_sql'] = 'a.is_spam = 0'; 357 elseif ( 'spam_only' == $spam )387 } elseif ( 'spam_only' == $r['spam'] ) { 358 388 $where_conditions['spam_sql'] = 'a.is_spam = 1'; 389 } 359 390 360 391 // 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'] ) . '%'; 363 394 $where_conditions['search_sql'] = $wpdb->prepare( 'a.content LIKE %s', $search_terms_like ); 364 395 } 365 396 366 // Filtering367 if ( $filter && $filter_sql = BP_Activity_Activity::get_filter_sql( $filter ) )368 $where_conditions['filter_sql'] = $filter_sql;369 370 397 // Sorting 371 if ( $sort != 'ASC' && $sort != 'DESC' ) 398 $sort = $r['sort']; 399 if ( $sort != 'ASC' && $sort != 'DESC' ) { 372 400 $sort = 'DESC'; 401 } 373 402 374 403 // Hide Hidden Items? 375 if ( ! $show_hidden)404 if ( ! $r['show_hidden'] ) 376 405 $where_conditions['hidden_sql'] = "a.hide_sitewide = 0"; 377 406 378 407 // 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'] ) ); 381 410 $where_conditions['exclude'] = "a.id NOT IN ({$exclude})"; 382 411 } 383 412 384 413 // 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'] ) ); 387 416 $where_conditions['in'] = "a.id IN ({$in})"; 388 417 } 389 418 390 419 // 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'] ); 392 421 393 422 if ( ! empty( $meta_query_sql['join'] ) ) { 394 423 $join_sql .= $meta_query_sql['join']; … … 399 428 } 400 429 401 430 // 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'] ); 403 432 404 433 if ( ! empty( $date_query_sql ) ) { 405 434 $where_conditions['date'] = $date_query_sql; … … 408 437 // Alter the query based on whether we want to show activity item 409 438 // comments in the stream like normal comments or threaded below 410 439 // the activity. 411 if ( false === $ display_comments || 'threaded' === $display_comments) {440 if ( false === $r['display_comments'] || 'threaded' === $r['display_comments'] ) { 412 441 $excluded_types[] = 'activity_comment'; 413 442 } 414 443 415 444 // Exclude 'last_activity' items unless the 'action' filter has 416 445 // been explicitly set 417 if ( empty( $ filter['object'] ) ) {446 if ( empty( $r['filter']['object'] ) ) { 418 447 $excluded_types[] = 'last_activity'; 419 448 } 420 449 … … 468 497 } 469 498 470 499 // 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'] ); 473 502 474 503 $retval = array( 475 504 'activities' => null, … … 517 546 } 518 547 519 548 } else { 520 521 549 // Query first for activity IDs 522 550 $activity_ids_sql = "{$select_sql} {$from_sql} {$join_sql} {$where_sql} ORDER BY a.date_recorded {$sort}"; 523 551 … … 559 587 $activity_ids[] = $activity->id; 560 588 } 561 589 562 if ( ! empty( $activity_ids ) && $ update_meta_cache) {590 if ( ! empty( $activity_ids ) && $r['update_meta_cache'] ) { 563 591 bp_activity_update_meta_cache( $activity_ids ); 564 592 } 565 593 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 } 568 597 569 598 // Pre-fetch data associated with activity users and other objects 570 599 BP_Activity_Activity::prefetch_object_data( $activities ); … … 589 618 $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 ); 590 619 $total_activities = $wpdb->get_var( $total_activities_sql ); 591 620 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']; 595 624 } 596 625 597 626 $retval['total'] = $total_activities; … … 817 846 } 818 847 819 848 /** 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 /** 820 1008 * In BuddyPress 1.2.x, this was used to retrieve specific activity stream items (for example, on an activity's permalink page). 821 1009 * 822 1010 * As of 1.5.x, use BP_Activity_Activity::get() with an 'in' parameter instead. … … 1497 1685 } 1498 1686 1499 1687 /** 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 */ 1695 class 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 /** 1500 1946 * Create a RSS feed using the activity component. 1501 1947 * 1502 1948 * You should only construct a new feed when you've validated that you're on -
src/bp-activity/bp-activity-functions.php
1417 1417 'search_terms' => false, // Pass search terms as a string 1418 1418 'meta_query' => false, // Filter by activity meta. See WP_Meta_Query for format 1419 1419 'date_query' => false, // Filter by date. See first parameter of WP_Date_Query for format 1420 'filter_query' => false, 1420 1421 'show_hidden' => false, // Show activity items that are hidden site-wide? 1421 1422 'exclude' => false, // Comma-separated list of activity IDs to exclude 1422 1423 'in' => false, // Comma-separated list or array of activity IDs to which you want to limit the query 1423 1424 'spam' => 'ham_only', // 'ham_only' (default), 'spam_only' or 'all'. 1424 1425 'update_meta_cache' => true, 1425 1426 'count_total' => false, 1427 'scope' => false, 1426 1428 1427 1429 /** 1428 1430 * Pass filters as an array -- all filter items can be multiple values comma separated: … … 1438 1440 ) ); 1439 1441 1440 1442 // 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'] ) ) { 1442 1444 1443 1445 $activity = wp_cache_get( 'bp_activity_sitewide_front', 'bp' ); 1444 1446 if ( false === $activity ) { … … 1451 1453 'search_terms' => $r['search_terms'], 1452 1454 'meta_query' => $r['meta_query'], 1453 1455 'date_query' => $r['date_query'], 1456 'filter_query' => $r['filter_query'], 1454 1457 'filter' => $r['filter'], 1458 'scope' => $r['scope'], 1455 1459 'display_comments' => $r['display_comments'], 1456 1460 'show_hidden' => $r['show_hidden'], 1457 1461 'spam' => $r['spam'], … … 1471 1475 'search_terms' => $r['search_terms'], 1472 1476 'meta_query' => $r['meta_query'], 1473 1477 'date_query' => $r['date_query'], 1478 'filter_query' => $r['filter_query'], 1474 1479 'filter' => $r['filter'], 1480 'scope' => $r['scope'], 1475 1481 'display_comments' => $r['display_comments'], 1476 1482 'show_hidden' => $r['show_hidden'], 1477 1483 'exclude' => $r['exclude'], -
src/bp-activity/bp-activity-template.php
201 201 'exclude' => false, 202 202 'in' => false, 203 203 'filter' => false, 204 'scope' => false, 204 205 'search_terms' => false, 205 206 'meta_query' => false, 206 207 'date_query' => false, 208 'filter_query' => false, 207 209 'display_comments' => 'threaded', 208 210 'show_hidden' => false, 209 211 'spam' => 'ham_only', … … 249 251 'search_terms' => $search_terms, 250 252 'meta_query' => $meta_query, 251 253 'date_query' => $date_query, 254 'filter_query' => $filter_query, 252 255 'filter' => $filter, 256 'scope' => $scope, 253 257 'show_hidden' => $show_hidden, 254 258 'exclude' => $exclude, 255 259 'in' => $in, … … 611 615 612 616 'meta_query' => false, // filter on activity meta. See WP_Meta_Query for format 613 617 '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. 614 619 615 620 // Searching 616 621 'search_terms' => false, // specify terms to search on … … 635 640 if ( empty( $search_terms ) && ! empty( $_REQUEST['s'] ) ) 636 641 $search_terms = $_REQUEST['s']; 637 642 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 applies644 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 697 643 // Do not exceed the maximum per page 698 644 if ( !empty( $max ) && ( (int) $per_page > (int) $max ) ) 699 645 $per_page = $max; … … 709 655 * 710 656 * @param bool $value True if BuddyPress should enable afilter support. 711 657 */ 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 ) ) { 713 659 $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 ) ) { 715 661 $filter = array( 'user_id' => $user_id, 'object' => $object, 'action' => $action, 'primary_id' => $primary_id, 'secondary_id' => $secondary_id, 'offset' => $offset, 'since' => $since ); 716 else662 } else { 717 663 $filter = false; 664 } 718 665 719 666 // If specific activity items have been requested, override the $hide_spam argument. This prevents backpat errors with AJAX. 720 667 if ( !empty( $include ) && ( 'ham_only' == $spam ) ) … … 731 678 'exclude' => $exclude, 732 679 'in' => $in, 733 680 'filter' => $filter, 681 'scope' => $scope, 734 682 'search_terms' => $search_terms, 735 683 'meta_query' => $meta_query, 736 684 'date_query' => $date_query, 685 'filter_query' => $filter_query, 737 686 'display_comments' => $display_comments, 738 687 'show_hidden' => $show_hidden, 739 688 'spam' => $spam, -
src/bp-core/bp-core-classes.php
2711 2711 return apply_filters( 'bp_members_suggestions_get_suggestions', $results, $this ); 2712 2712 } 2713 2713 } 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 */ 2720 abstract 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
228 228 add_filter( 'bp_activity_prefetch_object_data', 'bp_friends_prefetch_activity_object_data' ); 229 229 230 230 /** 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 */ 241 function 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 } 267 add_filter( 'bp_activity_set_friends_scope_args', 'bp_friends_filter_activity_scope', 10, 2 ); 268 269 /** 231 270 * Add activity stream items when one members accepts another members request 232 271 * for virtual friendship. 233 272 * -
src/bp-groups/bp-groups-activity.php
180 180 add_filter( 'bp_activity_prefetch_object_data', 'bp_groups_prefetch_activity_object_data' ); 181 181 182 182 /** 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 */ 191 function 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 } 216 add_filter( 'bp_activity_set_groups_scope_args', 'bp_groups_filter_activity_scope', 10, 2 ); 217 218 /** 183 219 * Record an activity item related to the Groups component. 184 220 * 185 221 * A wrapper for {@link bp_activity_add()} that provides some Groups-specific -
tests/phpunit/testcases/activity/template.php
89 89 * limiting query to user favorites 90 90 * 91 91 * @ticket BP4872 92 * @group scope 92 93 */ 93 94 public function test_bp_has_activities_favorites_action_filter() { 94 95 $user_id = $this->factory->user->create( array( 'role' => 'subscriber' ) ); … … 143 144 } 144 145 145 146 /** 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 /** 146 729 * Integration test for 'meta_query' param 147 730 */ 148 731 function test_bp_has_activities_with_meta_query() {