/**
	 * Checks if the given comment is valid for posting.
	 * @param $comment Comment to validate.
	 * @return False if comment is valid, error message identifier otherwise.
	 */
	protected static function validateComment( WikilogComment &$comment ) {
		global $wgWikilogMaxCommentSize;

		$length = strlen( $comment->mText );

		if ( $length == 0 ) {
			return 'wikilog-comment-is-empty';
		}
		if ( $length > $wgWikilogMaxCommentSize ) {
			return 'wikilog-comment-too-long';
		}

		if ( $comment->mUserID == 0 ) {
			$anonname = User::getCanonicalName( $comment->mAnonName, 'usable' );
			if ( !$anonname ) {
				return 'wikilog-comment-invalid-name';
			}
			$comment->setAnon( $anonname );
		}

		return false;
	}
	/**
	 * Creates a new comment object for a new comment, given the text and
	 * the parent comment.
	 * @param $item Wikilog article object this is a comment for.
	 * @param $text Comment wikitext as a string.
	 * @param $parent Parent comment id.
	 * @return New WikilogComment object.
	 */
	public static function newFromText( &$item, $text, $parent = null ) {
		$ts = wfTimestamp( TS_MW );
		$comment = new WikilogComment( $item );
		$comment->mParent    = $parent;
		$comment->mStatus    = self::S_OK;
		$comment->mTimestamp = $ts;
		$comment->mUpdated   = $ts;
		$comment->setText( $text );
		return $comment;
	}
	/**
	 * Organizes all the query information and constructs the table and
	 * field lists that will later form the SQL SELECT statement.
	 * @param $db Database object.
	 * @param $opts Array with query options. Keys are option names, values
	 *   are option values.
	 * @return Array with tables, fields, conditions, options and join
	 *   conditions, to be used in a call to $db->select(...).
	 */
	public function getQueryInfo( $db, $opts = array() ) {
		$this->setOptions( $opts );

		$join_wlp = false;

		# Basic defaults.
		$wlc_tables = WikilogComment::selectTables( $db );
		$q_tables = $wlc_tables['tables'];
		$q_fields = WikilogComment::selectFields();
		$q_conds = array();
		$q_options = array();
		$q_joins = $wlc_tables['join_conds'];

		# Invalid filter.
		if ( $this->mEmpty ) {
			$q_conds[] = '0=1';
		}

		# Filter by moderation status.
		if ( $this->mModStatus == self::MS_ACCEPTED ) {
			$q_conds['wlc_status'] = 'OK';
		} elseif ( $this->mModStatus == self::MS_PENDING ) {
			$q_conds['wlc_status'] = 'PENDING';
		} elseif ( $this->mModStatus == self::MS_NOTDELETED ) {
			$q_conds[] = "wlc_status <> " . $db->addQuotes( 'DELETED' );
		} elseif ( $this->mModStatus == self::MS_NOTPENDING ) {
			$q_conds[] = "wlc_status <> " . $db->addQuotes( 'PENDING' );
		}

		# Filter by article or wikilog.
		if ( $this->mItem !== null ) {
			$q_conds['wlc_post'] = $this->mItem->getID();
			if ( $this->mThread ) {
				$q_conds[] = "wlc_thread " . $db->buildLike( $this->mThread . '/', $db->anyString() );
			}
		} elseif ( $this->mWikilog !== null ) {
			$join_wlp = true;
			$q_conds['wlp_parent'] = $this->mWikilog->getArticleId();
		} elseif ( $this->mNamespace !== false ) {
			$q_conds['c.page_namespace'] = $this->mNamespace;
		}

		# Filter by author.
		if ( $this->mAuthor ) {
			$q_conds['wlc_user_text'] = $this->mAuthor;
		}

		# Filter by date.
		if ( $this->mDate ) {
			$q_conds[] = 'wlc_timestamp >= ' . $db->addQuotes( $this->mDate->start );
			$q_conds[] = 'wlc_timestamp < ' . $db->addQuotes( $this->mDate->end );
		}

		# Additional data.
		if ( $this->getOption( 'include-item' ) ) {
			$wlp_tables = WikilogItem::selectTables( $db );
			$q_tables = array_merge( $q_tables, $wlp_tables['tables'] );
			$q_joins['wikilog_posts'] = array( 'JOIN', 'wlp_page = wlc_post' );
			$q_joins += $wlp_tables['join_conds'];
			$q_fields = array_merge( $q_fields, WikilogItem::selectFields() );
		} elseif ( $join_wlp ) {
			$q_tables[] = 'wikilog_posts';
			$q_joins['wikilog_posts'] = array( 'JOIN', 'wlp_page = wlc_post' );
		}

		return array(
			'tables' => $q_tables,
			'fields' => $q_fields,
			'conds' => $q_conds,
			'options' => $q_options,
			'join_conds' => $q_joins
		);
	}
	/**
	 * Creates an unique ID for a feed entry. Tries to use $wgTaggingEntity
	 * if possible in order to create an RFC 4151 tag, otherwise, we use the
	 * page URL.
	 */
	public static function makeEntryId( WikilogComment $comment ) {
		global $wgTaggingEntity;
		if ( $wgTaggingEntity ) {
			$qstr = wfArrayToCGI( array( 'wk' => wfWikiID(), 'id' => $comment->getID() ) );
			return "tag:{$wgTaggingEntity}:/MediaWiki/Wikilog/comment?{$qstr}";
		} else {
			return $comment->getCommentArticleTitle()->getFullUrl();
		}
	}
	public function formatRow( $row ) {
		# Retrieve comment data.
		$item = $this->mSingleItem ? $this->mSingleItem : WikilogItem::newFromRow( $row );
		$comment = WikilogComment::newFromRow( $item, $row );
		$comment->loadText();

		$doReply = $this->mReplyTrigger && $comment->mID == $this->mReplyTrigger;

		$html = $this->mFormatter->startCommentThread( $comment );
		$html .= $this->mFormatter->formatComment( $comment, $doReply );

		if ( $doReply && is_callable( $this->mReplyCallback ) ) {
			if ( ( $res = call_user_func( $this->mReplyCallback, $comment ) ) ) {
				$html .= WikilogUtils::wrapDiv( 'wl-indent', $res );
			}
		}
		return $html;
	}