Skip to:
Content

BuddyPress.org

Changeset 9256


Ignore:
Timestamp:
12/22/2014 09:38:24 PM (11 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.