WordPress/wp-includes/class-wp-comment.php

380 lines
9.1 KiB
PHP
Raw Permalink Normal View History

<?php
/**
* Comment API: WP_Comment class
*
* @package WordPress
* @subpackage Comments
* @since 4.4.0
*/
/**
* Core class used to organize comments as instantiated objects with defined members.
*
* @since 4.4.0
*/
final class WP_Comment {
/**
* Comment ID.
*
* A numeric string, for compatibility reasons.
*
* @since 4.4.0
* @var string
*/
public $comment_ID;
/**
* ID of the post the comment is associated with.
*
* A numeric string, for compatibility reasons.
*
* @since 4.4.0
* @var string
*/
public $comment_post_ID = 0;
/**
* Comment author name.
*
* @since 4.4.0
* @var string
*/
public $comment_author = '';
/**
* Comment author email address.
*
* @since 4.4.0
* @var string
*/
public $comment_author_email = '';
/**
* Comment author URL.
*
* @since 4.4.0
* @var string
*/
public $comment_author_url = '';
/**
* Comment author IP address (IPv4 format).
*
* @since 4.4.0
* @var string
*/
public $comment_author_IP = '';
/**
* Comment date in YYYY-MM-DD HH:MM:SS format.
*
* @since 4.4.0
* @var string
*/
public $comment_date = '0000-00-00 00:00:00';
/**
* Comment GMT date in YYYY-MM-DD HH::MM:SS format.
*
* @since 4.4.0
* @var string
*/
public $comment_date_gmt = '0000-00-00 00:00:00';
/**
* Comment content.
*
* @since 4.4.0
* @var string
*/
public $comment_content;
/**
* Comment karma count.
*
* A numeric string, for compatibility reasons.
*
* @since 4.4.0
* @var string
*/
public $comment_karma = 0;
/**
* Comment approval status.
*
* @since 4.4.0
* @var string
*/
public $comment_approved = '1';
/**
* Comment author HTTP user agent.
*
* @since 4.4.0
* @var string
*/
public $comment_agent = '';
/**
* Comment type.
*
* @since 4.4.0
* @since 5.5.0 Default value changed to `comment`.
* @var string
*/
public $comment_type = 'comment';
/**
* Parent comment ID.
*
* A numeric string, for compatibility reasons.
*
* @since 4.4.0
* @var string
*/
public $comment_parent = 0;
/**
* Comment author ID.
*
* A numeric string, for compatibility reasons.
*
* @since 4.4.0
* @var string
*/
public $user_id = 0;
/**
* Comment children.
*
* @since 4.4.0
* @var array
*/
protected $children;
/**
* Whether children have been populated for this comment object.
*
* @since 4.4.0
* @var bool
*/
protected $populated_children = false;
/**
* Post fields.
*
* @since 4.4.0
* @var array
*/
protected $post_fields = array( 'post_author', 'post_date', 'post_date_gmt', 'post_content', 'post_title', 'post_excerpt', 'post_status', 'comment_status', 'ping_status', 'post_name', 'to_ping', 'pinged', 'post_modified', 'post_modified_gmt', 'post_content_filtered', 'post_parent', 'guid', 'menu_order', 'post_type', 'post_mime_type', 'comment_count' );
/**
* Retrieves a WP_Comment instance.
*
* @since 4.4.0
*
* @global wpdb $wpdb WordPress database abstraction object.
*
* @param int $id Comment ID.
* @return WP_Comment|false Comment object, otherwise false.
*/
public static function get_instance( $id ) {
global $wpdb;
$comment_id = (int) $id;
if ( ! $comment_id ) {
return false;
}
$_comment = wp_cache_get( $comment_id, 'comment' );
if ( ! $_comment ) {
$_comment = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $wpdb->comments WHERE comment_ID = %d LIMIT 1", $comment_id ) );
if ( ! $_comment ) {
return false;
}
wp_cache_add( $_comment->comment_ID, $_comment, 'comment' );
}
return new WP_Comment( $_comment );
}
/**
* Constructor.
*
* Populates properties with object vars.
*
* @since 4.4.0
*
* @param WP_Comment $comment Comment object.
*/
public function __construct( $comment ) {
foreach ( get_object_vars( $comment ) as $key => $value ) {
$this->$key = $value;
}
}
/**
* Convert object to array.
*
* @since 4.4.0
*
* @return array Object as array.
*/
public function to_array() {
return get_object_vars( $this );
}
/**
* Get the children of a comment.
*
* @since 4.4.0
*
* @param array $args {
* Array of arguments used to pass to get_comments() and determine format.
*
* @type string $format Return value format. 'tree' for a hierarchical tree, 'flat' for a flattened array.
* Default 'tree'.
* @type string $status Comment status to limit results by. Accepts 'hold' (`comment_status=0`),
* 'approve' (`comment_status=1`), 'all', or a custom comment status.
* Default 'all'.
* @type string $hierarchical Whether to include comment descendants in the results.
* 'threaded' returns a tree, with each comment's children
* stored in a `children` property on the `WP_Comment` object.
* 'flat' returns a flat array of found comments plus their children.
* Pass `false` to leave out descendants.
* The parameter is ignored (forced to `false`) when `$fields` is 'ids' or 'counts'.
* Accepts 'threaded', 'flat', or false. Default: 'threaded'.
* @type string|array $orderby Comment status or array of statuses. To use 'meta_value'
* or 'meta_value_num', `$meta_key` must also be defined.
* To sort by a specific `$meta_query` clause, use that
* clause's array key. Accepts 'comment_agent',
* 'comment_approved', 'comment_author',
* 'comment_author_email', 'comment_author_IP',
* 'comment_author_url', 'comment_content', 'comment_date',
* 'comment_date_gmt', 'comment_ID', 'comment_karma',
* 'comment_parent', 'comment_post_ID', 'comment_type',
* 'user_id', 'comment__in', 'meta_value', 'meta_value_num',
* the value of $meta_key, and the array keys of
* `$meta_query`. Also accepts false, an empty array, or
* 'none' to disable `ORDER BY` clause.
* }
* @return WP_Comment[] Array of `WP_Comment` objects.
*/
public function get_children( $args = array() ) {
$defaults = array(
'format' => 'tree',
'status' => 'all',
'hierarchical' => 'threaded',
'orderby' => '',
);
$_args = wp_parse_args( $args, $defaults );
$_args['parent'] = $this->comment_ID;
if ( is_null( $this->children ) ) {
if ( $this->populated_children ) {
$this->children = array();
} else {
$this->children = get_comments( $_args );
}
}
if ( 'flat' === $_args['format'] ) {
Force comment pagination on single posts. Previously, the 'page_comments' toggle allowed users to disable comment pagination. This toggle was only superficial, however. Even with 'page_comments' turned on, `comments_template()` loaded all of a post's comments into memory, and passed them to `wp_list_comments()` and `Walker_Comment`, the latter of which produced markup for only the current page of comments. In other words, it was possible to enable 'page_comments', thereby showing only a subset of a post's comments on a given page, but all comments continued to be loaded in the background. This technique scaled poorly. Posts with hundreds or thousands of comments would load slowly, or not at all, even when the 'comments_per_page' setting was set to a reasonable number. Recent changesets have addressed this problem through more efficient tree- walking, better descendant caching, and more selective queries for top-level post comments. The current changeset completes the project by addressing the root issue: that loading a post causes all of its comments to be loaded too. Here's the breakdown: * Comment pagination is now forced. Setting 'page_comments' to false leads to evil things when you have many comments. If you want to avoid pagination, set 'comments_per_page' to something high. * The 'page_comments' setting has been expunged from options-discussion.php, and from places in the codebase where it was referenced. For plugins relying on 'page_comments', we now force the value to `true` with a `pre_option` filter. * `comments_template()` now queries for an appropriately small number of comments. Usually, this means the `comments_per_page` value. * To preserve the current (odd) behavior for comment pagination links, some unholy hacks have been inserted into `comments_template()`. The ugliness is insulated in this function for backward compatibility and to minimize collateral damage. A side-effect is that, for certain settings of 'default_comments_page', up to 2x the value of `comments_per_page` might be fetched at a time. * In support of these changes, a `$format` parameter has been added to `WP_Comment::get_children()`. This param allows you to request a flattened array of comment children, suitable for feeding into `Walker_Comment`. * `WP_Query` loops are now informed about total available comment counts and comment pages by the `WP_Comment_Query` (`found_comments`, `max_num_pages`), instead of by `Walker_Comment`. Aside from radical performance improvements in the case of a post with many comments, this changeset fixes a bug that caused the first page of comments to be partial (`found_comments` % `comments_per_page`), rather than the last, as you'd expect. Props boonebgorges, wonderboymusic. Fixes #8071. Built from https://develop.svn.wordpress.org/trunk@34561 git-svn-id: http://core.svn.wordpress.org/trunk@34525 1a063a9b-81f0-0310-95a4-ce76da25c4cd
2015-09-25 16:40:25 -04:00
$children = array();
foreach ( $this->children as $child ) {
$child_args = $_args;
$child_args['format'] = 'flat';
// get_children() resets this value automatically.
unset( $child_args['parent'] );
$children = array_merge( $children, array( $child ), $child->get_children( $child_args ) );
Force comment pagination on single posts. Previously, the 'page_comments' toggle allowed users to disable comment pagination. This toggle was only superficial, however. Even with 'page_comments' turned on, `comments_template()` loaded all of a post's comments into memory, and passed them to `wp_list_comments()` and `Walker_Comment`, the latter of which produced markup for only the current page of comments. In other words, it was possible to enable 'page_comments', thereby showing only a subset of a post's comments on a given page, but all comments continued to be loaded in the background. This technique scaled poorly. Posts with hundreds or thousands of comments would load slowly, or not at all, even when the 'comments_per_page' setting was set to a reasonable number. Recent changesets have addressed this problem through more efficient tree- walking, better descendant caching, and more selective queries for top-level post comments. The current changeset completes the project by addressing the root issue: that loading a post causes all of its comments to be loaded too. Here's the breakdown: * Comment pagination is now forced. Setting 'page_comments' to false leads to evil things when you have many comments. If you want to avoid pagination, set 'comments_per_page' to something high. * The 'page_comments' setting has been expunged from options-discussion.php, and from places in the codebase where it was referenced. For plugins relying on 'page_comments', we now force the value to `true` with a `pre_option` filter. * `comments_template()` now queries for an appropriately small number of comments. Usually, this means the `comments_per_page` value. * To preserve the current (odd) behavior for comment pagination links, some unholy hacks have been inserted into `comments_template()`. The ugliness is insulated in this function for backward compatibility and to minimize collateral damage. A side-effect is that, for certain settings of 'default_comments_page', up to 2x the value of `comments_per_page` might be fetched at a time. * In support of these changes, a `$format` parameter has been added to `WP_Comment::get_children()`. This param allows you to request a flattened array of comment children, suitable for feeding into `Walker_Comment`. * `WP_Query` loops are now informed about total available comment counts and comment pages by the `WP_Comment_Query` (`found_comments`, `max_num_pages`), instead of by `Walker_Comment`. Aside from radical performance improvements in the case of a post with many comments, this changeset fixes a bug that caused the first page of comments to be partial (`found_comments` % `comments_per_page`), rather than the last, as you'd expect. Props boonebgorges, wonderboymusic. Fixes #8071. Built from https://develop.svn.wordpress.org/trunk@34561 git-svn-id: http://core.svn.wordpress.org/trunk@34525 1a063a9b-81f0-0310-95a4-ce76da25c4cd
2015-09-25 16:40:25 -04:00
}
} else {
$children = $this->children;
}
return $children;
}
/**
* Add a child to the comment.
*
* Used by `WP_Comment_Query` when bulk-filling descendants.
*
* @since 4.4.0
*
* @param WP_Comment $child Child comment.
*/
public function add_child( WP_Comment $child ) {
$this->children[ $child->comment_ID ] = $child;
}
/**
* Get a child comment by ID.
*
* @since 4.4.0
*
* @param int $child_id ID of the child.
* @return WP_Comment|false Returns the comment object if found, otherwise false.
*/
public function get_child( $child_id ) {
if ( isset( $this->children[ $child_id ] ) ) {
return $this->children[ $child_id ];
}
return false;
}
/**
* Set the 'populated_children' flag.
*
* This flag is important for ensuring that calling `get_children()` on a childless comment will not trigger
* unneeded database queries.
*
* @since 4.4.0
*
* @param bool $set Whether the comment's children have already been populated.
*/
public function populated_children( $set ) {
$this->populated_children = (bool) $set;
}
/**
* Check whether a non-public property is set.
*
* If `$name` matches a post field, the comment post will be loaded and the post's value checked.
*
* @since 4.4.0
*
* @param string $name Property name.
* @return bool
*/
public function __isset( $name ) {
if ( in_array( $name, $this->post_fields, true ) && 0 !== (int) $this->comment_post_ID ) {
$post = get_post( $this->comment_post_ID );
return property_exists( $post, $name );
}
}
/**
* Magic getter.
*
* If `$name` matches a post field, the comment post will be loaded and the post's value returned.
*
* @since 4.4.0
*
* @param string $name
* @return mixed
*/
public function __get( $name ) {
if ( in_array( $name, $this->post_fields, true ) ) {
$post = get_post( $this->comment_post_ID );
return $post->$name;
}
}
}