Skip to:
Content

BuddyPress.org

Changeset 9256


Ignore:
Timestamp:
12/22/2014 09:38:24 PM (12 years ago)
Author:
r-a-y
Message:

Activity: Introduce new class - BP_Activity_Query.

BP_Activity_Query is a helper class, which extends the
BP_Recursive_Query class, for generating complex queries against data in
the activity database table.

A 'filter_query' argument has been introduced to the bp_has_activities()
stack to support the use of BP_Activity_Query across the majority of
activity fetching functions.

See #4988.

Location:
trunk/src/bp-activity
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/bp-activity/bp-activity-classes.php

    r9254 r9256  
    271271         *     @type array       $date_query        Array of date_query conditions. See first parameter of
    272272         *                                          WP_Date_Query::__construct().
     273         *     @type array       $filter_query      Array of advanced query conditions. See BP_Activity_Query::__construct().
    273274         *     @type array       $filter            See BP_Activity_Activity::get_filter_sql().
    274275         *     @type string      $search_terms      Limit results by a search term. Default: false.
    … …  
    318319                        'meta_query'        => false,      // Filter by activitymeta
    319320                        'date_query'        => false,      // Filter by date
     321                        'filter_query'      => false,      // Advanced filtering - see BP_Activity_Query
    320322                        'filter'            => false,      // See self::get_filter_sql()
    321323                        'search_terms'      => false,      // Terms to search by
    … …  
    340342                // Excluded types
    341343                $excluded_types = array();
     344
     345                // Advanced filtering
     346                if ( ! empty( $r['filter_query'] ) ) {
     347                        $filter_query = new BP_Activity_Query( $r['filter_query'] );
     348                        if ( $sql = $filter_query->get_sql() ) {
     349                                $where_conditions['filter_query_sql'] = $sql;
     350                        }
     351                }
    342352
    343353                // Regular filtering
    … …  
    14881498
    14891499                return $wpdb->get_var( $wpdb->prepare( "UPDATE {$bp->activity->table_name} SET hide_sitewide = 1 WHERE user_id = %d", $user_id ) );
     1500        }
     1501}
     1502
     1503/**
     1504 * Class for generating the WHERE SQL clause for advanced activity fetching.
     1505 *
     1506 * This is notably used in {@link BP_Activity_Activity::get()} with the
     1507 * 'filter_query' parameter.
     1508 *
     1509 * @since BuddyPress (2.2.0)
     1510 */
     1511class BP_Activity_Query extends BP_Recursive_Query {
     1512        /**
     1513         * Array of activity queries.
     1514         *
     1515         * See {@see BP_Activity_Query::__construct()} for information on query arguments.
     1516         *
     1517         * @since BuddyPress (2.2.0)
     1518         * @access public
     1519         * @var array
     1520         */
     1521        public $queries = array();
     1522
     1523        /**
     1524         * Table alias.
     1525         *
     1526         * @since BuddyPress (2.2.0)
     1527         * @access public
     1528         * @var string
     1529         */
     1530        public $table_alias = '';
     1531
     1532        /**
     1533         * Supported DB columns.
     1534         *
     1535         * See the 'wp_bp_activity' DB table schema.
     1536         *
     1537         * @since BuddyPress (2.2.0)
     1538         * @access public
     1539         * @var array
     1540         */
     1541        public $db_columns = array(
     1542                'id', 'user_id', 'component', 'type', 'action', 'content',
     1543                'item_id', 'secondary_item_id', 'hide_sitewide', 'is_spam',
     1544        );
     1545
     1546        /**
     1547         * Constructor.
     1548         *
     1549         * @since BuddyPress (2.2.0)
     1550         *
     1551         * @param array $query {
     1552         *     Array of query clauses.
     1553         *
     1554         *     @type array {
     1555         *         @type string $column   Required. The column to query against. Basically, any DB column in the main
     1556         *                                'wp_bp_activity' table.
     1557         *         @type string $value    Required. Value to filter by.
     1558         *         @type string $compare  Optional. The comparison operator. Default '='.
     1559         *                                Accepts '=', '!=', '>', '>=', '<', '<=', 'IN', 'NOT IN', 'LIKE',
     1560         *                                'NOT LIKE', BETWEEN', 'NOT BETWEEN', 'REGEXP', 'NOT REGEXP', 'RLIKE'
     1561         *         @type string $relation Optional. The boolean relationship between the activity queries.
     1562         *                                Accepts 'OR', 'AND'. Default 'AND'.
     1563         *         @type array {
     1564         *             Optional. Another fully-formed activity query. See parameters above.
     1565         *         }
     1566         *     }
     1567         * }
     1568         */
     1569        public function __construct( $query = array() ) {
     1570                if ( ! is_array( $query ) ) {
     1571                        return;
     1572                }
     1573
     1574                $this->queries = $this->sanitize_query( $query );
     1575        }
     1576
     1577        /**
     1578         * Generates WHERE SQL clause to be appended to a main query.
     1579         *
     1580         * @since BuddyPress (2.2.0)
     1581         * @access public
     1582         *
     1583         * @param string $alias An existing table alias that is compatible with the current query clause.
     1584         *               Default: 'a'. BP_Activity_Activity::get() uses 'a', so we default to that.
     1585         * @return string SQL fragment to append to the main WHERE clause.
     1586         * }
     1587         */
     1588        public function get_sql( $alias = 'a' ) {
     1589                if ( ! empty( $alias ) ) {
     1590                        $this->table_alias = sanitize_title( $alias );
     1591                }
     1592
     1593                $sql = $this->get_sql_clauses();
     1594
     1595                // we only need the 'where' clause
     1596                //
     1597                // also trim trailing "AND" clause from parent BP_Recursive_Query class
     1598                // since it's not necessary for our needs
     1599                return preg_replace( '/^\sAND/', '', $sql['where'] );
     1600        }
     1601
     1602        /**
     1603         * Generate WHERE clauses for a first-order clause.
     1604         *
     1605         * @since BuddyPress (2.2.0)
     1606         * @access protected
     1607         *
     1608         * @param  array $clause       Array of arguments belonging to the clause.
     1609         * @param  array $parent_query Parent query to which the clause belongs.
     1610         * @return array {
     1611         *     @type array $where Array of subclauses for the WHERE statement.
     1612         *     @type array $join  Empty array. Not used.
     1613         * }
     1614         */
     1615        protected function get_sql_for_clause( $clause, $parent_query ) {
     1616                global $wpdb;
     1617
     1618                $sql_chunks = array(
     1619                        'where' => array(),
     1620                        'join' => array(),
     1621                );
     1622
     1623                $column = isset( $clause['column'] ) ? $this->validate_column( $clause['column'] ) : '';
     1624                $value  = isset( $clause['value'] )  ? $clause['value'] : '';
     1625                if ( empty( $column ) || ! isset( $clause['value'] ) ) {
     1626                        return $sql_chunks;
     1627                }
     1628
     1629                if ( isset( $clause['compare'] ) ) {
     1630                        $clause['compare'] = strtoupper( $clause['compare'] );
     1631                } else {
     1632                        $clause['compare'] = isset( $clause['value'] ) && is_array( $clause['value'] ) ? 'IN' : '=';
     1633                }
     1634
     1635                // default 'compare' to '=' if no valid operator is found
     1636                if ( ! in_array( $clause['compare'], array(
     1637                        '=', '!=', '>', '>=', '<', '<=',
     1638                        'LIKE', 'NOT LIKE',
     1639                        'IN', 'NOT IN',
     1640                        'BETWEEN', 'NOT BETWEEN',
     1641                        'REGEXP', 'NOT REGEXP', 'RLIKE'
     1642                ) ) ) {
     1643                        $clause['compare'] = '=';
     1644                }
     1645
     1646                $compare = $clause['compare'];
     1647
     1648                $alias = ! empty( $this->table_alias ) ? "{$this->table_alias}." : '';
     1649
     1650                // Next, Build the WHERE clause.
     1651                $where = '';
     1652
     1653                // value.
     1654                if ( isset( $clause['value'] ) ) {
     1655                        if ( in_array( $compare, array( 'IN', 'NOT IN', 'BETWEEN', 'NOT BETWEEN' ) ) ) {
     1656                                if ( ! is_array( $value ) ) {
     1657                                        $value = preg_split( '/[,\s]+/', $value );
     1658                                }
     1659                        }
     1660
     1661                        // tinyint
     1662                        if ( ! empty( $column ) && true === in_array( $column, array( 'hide_sitewide', 'is_spam' ) ) ) {
     1663                                $sql_chunks['where'][] = $wpdb->prepare( "{$alias}{$column} = %d", $value );
     1664
     1665                        } else {
     1666                                switch ( $compare ) {
     1667                                        // IN uses different syntax
     1668                                        case 'IN' :
     1669                                        case 'NOT IN' :
     1670                                                $in_sql = BP_Activity_Activity::get_in_operator_sql( "{$alias}{$column}", $value );
     1671
     1672                                                // 'NOT IN' operator is as easy as a string replace!
     1673                                                if ( 'NOT IN' === $compare ) {
     1674                                                        $in_sql = str_replace( 'IN', 'NOT IN', $in_sql );
     1675                                                }
     1676
     1677                                                $sql_chunks['where'][] = $in_sql;
     1678                                                break;
     1679
     1680                                        case 'BETWEEN' :
     1681                                        case 'NOT BETWEEN' :
     1682                                                $value = array_slice( $value, 0, 2 );
     1683                                                $where = $wpdb->prepare( '%s AND %s', $value );
     1684                                                break;
     1685
     1686                                        case 'LIKE' :
     1687                                        case 'NOT LIKE' :
     1688                                                $value = '%' . bp_esc_like( $value ) . '%';
     1689                                                $where = $wpdb->prepare( '%s', $value );
     1690                                                break;
     1691
     1692                                        default :
     1693                                                $where = $wpdb->prepare( '%s', $value );
     1694                                                break;
     1695
     1696                                }
     1697                        }
     1698
     1699                        if ( $where ) {
     1700                                $sql_chunks['where'][] = "{$alias}{$column} {$compare} {$where}";
     1701                        }
     1702                }
     1703
     1704                /*
     1705                 * Multiple WHERE clauses should be joined in parentheses.
     1706                 */
     1707                if ( 1 < count( $sql_chunks['where'] ) ) {
     1708                        $sql_chunks['where'] = array( '( ' . implode( ' AND ', $sql_chunks['where'] ) . ' )' );
     1709                }
     1710
     1711                return $sql_chunks;
     1712        }
     1713
     1714        /**
     1715         * Determine whether a clause is first-order.
     1716         *
     1717         * @since BuddyPress (2.2.0)
     1718         * @access protected
     1719         *
     1720         * @param  array $q Clause to check.
     1721         * @return bool
     1722         */
     1723        protected function is_first_order_clause( $query ) {
     1724                return isset( $query['column'] ) || isset( $query['value'] );
     1725        }
     1726
     1727        /**
     1728         * Validates a column name parameter.
     1729         *
     1730         * Column names are checked against a whitelist of known tables.
     1731         * See {@link BP_Activity_Query::db_tables}.
     1732         *
     1733         * @since BuddyPress (2.2.0)
     1734         * @access public
     1735         *
     1736         * @param string $column The user-supplied column name.
     1737         * @return string A validated column name value.
     1738         */
     1739        public function validate_column( $column = '' ) {
     1740                if ( in_array( $column, $this->db_columns ) ) {
     1741                        return $column;
     1742                } else {
     1743                        return '';
     1744                }
    14901745        }
    14911746}
  • trunk/src/bp-activity/bp-activity-functions.php

    r9243 r9256  
    14171417                'meta_query'        => false,        // Filter by activity meta. See WP_Meta_Query for format
    14181418                'date_query'        => false,        // Filter by date. See first parameter of WP_Date_Query for format
     1419                'filter_query'      => false,
    14191420                'show_hidden'       => false,        // Show activity items that are hidden site-wide?
    14201421                'exclude'           => false,        // Comma-separated list of activity IDs to exclude
    … …  
    14381439
    14391440        // Attempt to return a cached copy of the first page of sitewide activity.
    1440         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'] ) ) {
     1441        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['exclude'] ) && empty( $r['in'] ) && ( 'DESC' === $r['sort'] ) && empty( $r['exclude'] ) && ( 'ham_only' === $r['spam'] ) ) {
    14411442
    14421443                $activity = wp_cache_get( 'bp_activity_sitewide_front', 'bp' );
    … …  
    14511452                                'meta_query'        => $r['meta_query'],
    14521453                                'date_query'        => $r['date_query'],
     1454                                'filter_query'      => $r['filter_query'],
    14531455                                'filter'            => $r['filter'],
    14541456                                'display_comments'  => $r['display_comments'],
    … …  
    14711473                        'meta_query'       => $r['meta_query'],
    14721474                        'date_query'       => $r['date_query'],
     1475                        'filter_query'     => $r['filter_query'],
    14731476                        'filter'           => $r['filter'],
    14741477                        'display_comments' => $r['display_comments'],
  • trunk/src/bp-activity/bp-activity-template.php

    r9255 r9256  
    205205                        'meta_query'        => false,
    206206                        'date_query'        => false,
     207                        'filter_query'      => false,
    207208                        'display_comments'  => 'threaded',
    208209                        'show_hidden'       => false,
    … …  
    250251                                'meta_query'        => $meta_query,
    251252                                'date_query'        => $date_query,
     253                                'filter_query'      => $filter_query,
    252254                                'filter'            => $filter,
    253255                                'show_hidden'       => $show_hidden,
    … …  
    462464 *     @type array             $date_query       Limit by date by passing an array of date_query conditions. See first
    463465 *                                               parameter of {@link WP_Date_Query::__construct()} for syntax.
     466 *     @type array             $filter_query     Advanced activity filtering.  See {@link BP_Activity_Query::__construct()}.
    464467 *     @type string            $search_terms     Limit results by a search term. Default: false.
    465468 *     @type string            $scope            Use a BuddyPress pre-built filter.
    … …  
    589592                'meta_query'        => false,        // filter on activity meta. See WP_Meta_Query for format
    590593                'date_query'        => false,        // filter by date. See first parameter of WP_Date_Query for format
     594                'filter_query'      => false,        // advanced filtering.  See BP_Activity_Query for format
    591595
    592596                // Searching
    … …  
    712716                'meta_query'        => $meta_query,
    713717                'date_query'        => $date_query,
     718                'filter_query'      => $filter_query,
    714719                'display_comments'  => $display_comments,
    715720                'show_hidden'       => $show_hidden,
Note: See TracChangeset for help on using the changeset viewer.