diff --git a/includes/.htaccess b/includes/.htaccess new file mode 100755 index 0000000..6326ab3 --- /dev/null +++ b/includes/.htaccess @@ -0,0 +1,5 @@ +## Default .htaccess file +# Displaying PHP errors +php_flag display_errors on +php_value error_reporting 6143 + diff --git a/includes/Comment.class.php b/includes/Comment.class.php index 1d56f1a..f56d93e 100644 --- a/includes/Comment.class.php +++ b/includes/Comment.class.php @@ -1,858 +1,873 @@ - tag is in - */ - public $page = null; - - /** - * @var Integer: total amount of comments by distinct commenters that the - * current page has - */ - public $commentTotal = 0; - - /** - * @var String: text of the current comment - */ - public $text = null; - - /* START Anpassung znilwiki */ - public $CommentUsernameKOK = null; /* 25.10.2013 von Kai-Ole Kirsten */ - /* ENDE Anpassung znilwiki */ - - /** - * Date when the comment was posted - * - * @var null - */ - public $date = null; - - /** - * @var Integer: internal ID number (Comments.CommentID DB field) of the - * current comment that we're dealing with - */ - public $id = 0; - - /** - * @var Integer: ID of the parent comment, if this is a child comment - */ - public $parentID = 0; - - /** - * The current vote from this user on this comment - * - * @var int|boolean: false if no vote, otherwise -1, 0, or 1 - */ - public $currentVote = false; - - /** - * @var string: comment score (SUM() of all votes) of the current comment - */ - public $currentScore = '0'; - - /** - * Username of the user who posted the comment - * - * @var string - */ - public $username = ''; - - /** - * IP of the comment poster - * - * @var string - */ - public $ip = ''; - - /** - * ID of the user who posted the comment - * - * @var int - */ - public $userID = 0; - - /** - * @TODO document - * - * @var int - */ - public $userPoints = 0; - - /** - * Comment ID of the thread this comment is in - * this is the ID of the parent comment if there is one, - * or this comment if there is not - * Used for sorting - * - * @var null - */ - public $thread = null; - - /** - * Unix timestamp when the comment was posted - * Used for sorting - * Processed from $date - * - * @var null - */ - public $timestamp = null; - - /** - * Constructor - set the page ID - * - * @param $page CommentsPage: ID number of the current page - * @param IContextSource $context - * @param $data: straight from the DB about the comment - */ - public function __construct( CommentsPage $page, $context = null, $data ) { - $this->page = $page; - - $this->setContext( $context ); - - $this->username = $data['Comment_Username']; - $this->ip = $data['Comment_IP']; - $this->text = $data['Comment_Text']; - $this->date = $data['Comment_Date']; - $this->userID = $data['Comment_user_id']; - $this->userPoints = $data['Comment_user_points']; - $this->id = $data['CommentID']; - $this->parentID = $data['Comment_Parent_ID']; - $this->thread = $data['thread']; - $this->timestamp = $data['timestamp']; - - if ( isset( $data['current_vote'] ) ) { - $vote = $data['current_vote']; - } else { - $dbr = wfGetDB( DB_SLAVE ); - $row = $dbr->selectRow( - 'Comments_Vote', - array( 'Comment_Vote_Score' ), - array( - 'Comment_Vote_ID' => $this->id, - 'Comment_Vote_Username' => $this->getUser()->getName() - ), - __METHOD__ - ); - if ( $row !== false ) { - $vote = $row->Comment_Vote_Score; - } else { - $vote = false; - } - } - - $this->currentVote = $vote; - - $this->currentScore = isset( $data['total_vote'] ) - ? $data['total_vote'] : $this->getScore(); - } - - public static function newFromID( $id ) { - $context = RequestContext::getMain(); - $dbr = wfGetDB( DB_SLAVE ); - - if ( !is_numeric( $id ) || $id == 0 ) { - return null; - } - - $tables = array(); - $params = array(); - $joinConds = array(); - - // Defaults (for non-social wikis) - $tables[] = 'Comments'; - $fields = array( - 'Comment_Username', 'Comment_IP', 'Comment_Text', - 'Comment_Date', 'Comment_Date AS timestamp', - 'Comment_user_id', 'CommentID', 'Comment_Parent_ID', - 'CommentID', 'Comment_Page_ID' - ); - - // If SocialProfile is installed, query the user_stats table too. - if ( - class_exists( 'UserProfile' ) && - $dbr->tableExists( 'user_stats' ) - ) { - $tables[] = 'user_stats'; - $fields[] = 'stats_total_points'; - $joinConds = array( - 'Comments' => array( - 'LEFT JOIN', 'Comment_user_id = stats_user_id' - ) - ); - } - - // Perform the query - $res = $dbr->select( - $tables, - $fields, - array( 'CommentID' => $id ), - __METHOD__, - $params, - $joinConds - ); - - $row = $res->fetchObject(); - - if ( $row->Comment_Parent_ID == 0 ) { - $thread = $row->CommentID; - } else { - $thread = $row->Comment_Parent_ID; - } - $data = array( - 'Comment_Username' => $row->Comment_Username, - 'Comment_IP' => $row->Comment_IP, - 'Comment_Text' => $row->Comment_Text, - 'Comment_Date' => $row->Comment_Date, - 'Comment_user_id' => $row->Comment_user_id, - 'Comment_user_points' => ( isset( $row->stats_total_points ) ? number_format( $row->stats_total_points ) : 0 ), - 'CommentID' => $row->CommentID, - 'Comment_Parent_ID' => $row->Comment_Parent_ID, - 'thread' => $thread, - 'timestamp' => wfTimestamp( TS_UNIX, $row->timestamp ) - ); - - $page = new CommentsPage( $row->Comment_Page_ID, $context ); - - return new Comment( $page, $context, $data ); - } - - /** - * Parse and return the text for this comment - * - * @return mixed|string - * @throws MWException - */ - function getText() { - global $wgParser; - - $commentText = trim( str_replace( '"', "'", $this->text ) ); - $comment_text_parts = explode( "\n", $commentText ); - $comment_text_fix = ''; - foreach ( $comment_text_parts as $part ) { - $comment_text_fix .= ( ( $comment_text_fix ) ? "\n" : '' ) . trim( $part ); - } - - if ( $this->getTitle()->getArticleID() > 0 ) { - $commentText = $wgParser->recursiveTagParse( $comment_text_fix ); - } else { - $commentText = $this->getOutput()->parse( $comment_text_fix ); - } - - // really bad hack because we want to parse=firstline, but don't want wrapping

tags - if ( substr( $commentText, 0 , 3 ) == '

' ) { - $commentText = substr( $commentText, 3 ); - } - - if ( substr( $commentText, strlen( $commentText ) -4 , 4 ) == '

' ) { - $commentText = substr( $commentText, 0, strlen( $commentText ) -4 ); - } - - // make sure link text is not too long (will overflow) - // this function changes too long links to http://www.abc....xyz.html - $commentText = preg_replace_callback( - "/(]*>)(.*?)(<\/a>)/i", - array( 'CommentFunctions', 'cutCommentLinkText' ), - $commentText - ); - - return $commentText; - } - - /** - * Adds the comment and all necessary info into the Comments table in the - * database. - * - * @param string $text: text of the comment - * @param CommentsPage $page: container page - * @param User $user: user commenting - * @param int $parentID: ID of parent comment, if this is a reply - * - * @return Comment: the added comment - */ - static function add( $text, CommentsPage $page, User $user, $parentID ) { - global $wgCommentsInRecentChanges; - $dbw = wfGetDB( DB_MASTER ); - $context = RequestContext::getMain(); - - wfSuppressWarnings(); - $commentDate = date( 'Y-m-d H:i:s' ); - wfRestoreWarnings(); - /*if ( $this->getUser()->isLoggedIn() ) { - $kok_username = $user->getName(); - } else { - $kok_username = $this->CommentUsernameKOK; - $kok_username = preg_replace('/<.*>/i', '', $kok_username); - $kok_username = preg_replace('/[^A-Za-z0-9. \-\@]/i', '', $kok_username); - $kok_username = str_replace("1'1", '', $kok_username); - $kok_username = str_replace('USER_NAME', '', $kok_username); - $kok_username = str_replace('DESC', '', $kok_username); - $kok_username = str_replace('(*)', '', $kok_username); - $kok_username = str_replace('EXEC', '', $kok_username); - }*/ - $dbw->insert( - 'Comments', - array( - 'Comment_Page_ID' => $page->id, - 'Comment_Username' => $user->getName(), - 'Comment_user_id' => $user->getId(), - 'Comment_Text' => $text, - 'Comment_Date' => $commentDate, - 'Comment_Parent_ID' => $parentID, - 'Comment_IP' => $_SERVER['REMOTE_ADDR'] - ), - __METHOD__ - ); - $commentId = $dbw->insertId(); - $dbw->commit( __METHOD__ ); // misza: added this - $id = $commentId; - - $page->clearCommentListCache(); - - // Add a log entry. - self::log( 'add', $user, $page->id, $commentId, $text ); - - $dbr = wfGetDB( DB_SLAVE ); - if ( - class_exists( 'UserProfile' ) && - $dbr->tableExists( 'user_stats' ) - ) { - $res = $dbr->select( // need this data for seeding a Comment object - 'user_stats', - 'stats_total_points', - array( 'stats_user_id' => $user->getId() ), - __METHOD__ - ); - - $row = $res->fetchObject(); - $userPoints = number_format( $row->stats_total_points ); - } else { - $userPoints = 0; - } - - if ( $parentID == 0 ) { - $thread = $id; - } else { - $thread = $parentID; - } - $data = array( - 'Comment_Username' => $user->getName(), - 'Comment_IP' => $context->getRequest()->getIP(), - 'Comment_Text' => $text, - 'Comment_Date' => $commentDate, - 'Comment_user_id' => $user->getID(), - 'Comment_user_points' => $userPoints, - 'CommentID' => $id, - 'Comment_Parent_ID' => $parentID, - 'thread' => $thread, - 'timestamp' => strtotime( $commentDate ) - ); - - $page = new CommentsPage( $page->id, $context ); - $comment = new Comment( $page, $context, $data ); - - Hooks::run( 'Comment::add', array( $comment, $commentId, $comment->page->id ) ); - /* ## START Kommentar auch per Email versenden ## 11/2014 Bernhard Linz */ - $znilpageTitle = ""; - $comment_mailto = "root@linz.email"; - $comment_mailsubject = "Neuer Kommentar von: " . $kok_username . " - IP: " . $_SERVER['REMOTE_ADDR'] . " - DNS: " . gethostbyaddr($_SERVER['REMOTE_ADDR']) ; - $comment_mailfrom = "MIME-Version: 1.0\r\n"; - $comment_mailfrom .= "Content-type: text/html; charset=utf-8\r\n"; - $comment_mailfrom .= "From: znil.net Kommentare \r\n"; - $comment_url = "http://znil.net/index.php?title={$znilpageTitle}#comment-{$commentId}"; - $comment_mailtext = $commentDate . "

" . $comment_url . "


" . "IP: " . $_SERVER['REMOTE_ADDR'] . "
" . "DNS: " . gethostbyaddr($_SERVER['REMOTE_ADDR']) ."

" . $kok_username . "

" . $text; - $comment_mailtext = nl2br($comment_mailtext); - mail($comment_mailto, $comment_mailsubject, $comment_mailtext, $comment_mailfrom); - /* ## ENDE Bernhard Linz */ - return $comment; - } - - /** - * Gets the score for this comment from the database table Comments_Vote - * - * @return string - */ - function getScore() { - $dbr = wfGetDB( DB_SLAVE ); - $row = $dbr->selectRow( - 'Comments_Vote', - array( 'SUM(Comment_Vote_Score) AS CommentScore' ), - array( 'Comment_Vote_ID' => $this->id ), - __METHOD__ - ); - $score = '0'; - if ( $row !== false && $row->CommentScore ) { - $score = $row->CommentScore; - } - return $score; - } - - /* START Anpassungen znilwiki */ - /* ## START ## 25.10.2013 Hinzugefügt von Kai-Ole */ - function setCommentUsernameKOK( $UsernameKOK ) { - $this->CommentUsernameKOK = $UsernameKOK; - } - /* ## ENDE ## 25.10.2013 Kai-Ole */ - /* ENDE Anpassungen znilwiki */ - - /** - * Adds a vote for a comment if the user hasn't voted for said comment yet. - * - * @param $value int: upvote or downvote (1 or -1) - */ - function vote( $value ) { - global $wgMemc; - $dbw = wfGetDB( DB_MASTER ); - - if ( $value < -1 ) { // limit to range -1 -> 0 -> 1 - $value = -1; - } elseif ( $value > 1 ) { - $value = 1; - } - - if ( $value == $this->currentVote ) { // user toggling off a preexisting vote - $value = 0; - } - - wfSuppressWarnings(); - $commentDate = date( 'Y-m-d H:i:s' ); - wfRestoreWarnings(); - - if ( $this->currentVote === false ) { // no vote, insert - $dbw->insert( - 'Comments_Vote', - array( - 'Comment_Vote_id' => $this->id, - 'Comment_Vote_Username' => $this->getUser()->getName(), - 'Comment_Vote_user_id' => $this->getUser()->getId(), - 'Comment_Vote_Score' => $value, - 'Comment_Vote_Date' => $commentDate, - 'Comment_Vote_IP' => $_SERVER['REMOTE_ADDR'] - ), - __METHOD__ - ); - } else { // already a vote, update - $dbw->update( - 'Comments_Vote', - array( - 'Comment_Vote_Score' => $value, - 'Comment_Vote_Date' => $commentDate, - 'Comment_Vote_IP' => $_SERVER['REMOTE_ADDR'] - ), - array( - 'Comment_Vote_id' => $this->id, - 'Comment_Vote_Username' => $this->getUser()->getName(), - 'Comment_Vote_user_id' => $this->getUser()->getId(), - ), - __METHOD__ - ); - } - $dbw->commit( __METHOD__ ); - - // update cache for comment list - // should perform better than deleting cache completely since Votes happen more frequently - $key = wfMemcKey( 'comment', 'pagethreadlist', $this->page->id ); - $comments = $wgMemc->get( $key ); - if ( $comments ) { - foreach ( $comments as &$comment ) { - if ( $comment->id == $this->id ) { - $comment->currentScore = $this->currentScore; - } - } - $wgMemc->set( $key, $comments ); - } - - $score = $this->getScore(); - - $this->currentVote = $value; - $this->currentScore = $score; - } - - /** - * Deletes entries from Comments and Comments_Vote tables and clears caches - */ - function delete() { - $dbw = wfGetDB( DB_MASTER ); - $dbw->delete( - 'Comments', - array( 'CommentID' => $this->id ), - __METHOD__ - ); - $dbw->delete( - 'Comments_Vote', - array( 'Comment_Vote_ID' => $this->id ), - __METHOD__ - ); - $dbw->commit( __METHOD__ ); - - // Log the deletion to Special:Log/comments. - self::log( 'delete', $this->getUser(), $this->page->id, $this->id ); - - // Clear memcache & Squid cache - $this->page->clearCommentListCache(); - - // Ping other extensions that may have hooked into this point (i.e. LinkFilter) - Hooks::run( 'Comment::delete', array( $this, $this->id, $this->page->id ) ); - } - - /** - * Log an action in the comment log. - * - * @param string $action Action to log, can be either 'add' or 'delete' - * @param User $user User who performed the action - * @param int $pageId Page ID of the page that contains the comment thread - * @param int $commentId Comment ID of the affected comment - * @param string $commentText Supplementary log comment, if any - */ - static function log( $action, $user, $pageId, $commentId, $commentText = null ) { - global $wgCommentsInRecentChanges; - $logEntry = new ManualLogEntry( 'comments', $action ); - $logEntry->setPerformer( $user ); - $logEntry->setTarget( Title::newFromId( $pageId ) ); - if ( $commentText !== null ) { - $logEntry->setComment( $commentText ); - } - $logEntry->setParameters( array( - '4::commentid' => $commentId - ) ); - $logId = $logEntry->insert(); - $logEntry->publish( $logId, ( $wgCommentsInRecentChanges ? 'rcandudp' : 'udp' ) ); - } - - /** - * Return the HTML for the comment vote links - * - * @param int $voteType up (+1) vote or down (-1) vote - * @return string - */ - function getVoteLink( $voteType ) { - global $wgExtensionAssetsPath; - - // Blocked users cannot vote, obviously - if ( $this->getUser()->isBlocked() ) { - return ''; - } - if ( !$this->getUser()->isAllowed( 'comment' ) ) { - return ''; - } - - $voteLink = ''; - if ( $this->getUser()->isLoggedIn() ) { - $voteLink .= ''; - } else { - $login = SpecialPage::getTitleFor( 'Userlogin' ); // Anonymous users need to log in before they can vote - $returnTo = $this->page->title->getPrefixedDBkey(); // Determine a sane returnto URL parameter - - $voteLink .= - "getLocalURL( array( 'returnto' => $returnTo ) ) ) . - "\" rel=\"nofollow\">"; - } - - $imagePath = $wgExtensionAssetsPath . '/Comments/resources/images'; - if ( $voteType == 1 ) { - if ( $this->currentVote == 1 ) { - $voteLink .= "\"+\""; - } else { - $voteLink .= "\"+\""; - } - } else { - if ( $this->currentVote == -1 ) { - $voteLink .= "\"+\""; - } else { - $voteLink .= "\"+\""; - } - } - - return $voteLink; - } - - /** - * Show the HTML for this comment and ignore section - * - * @param array $blockList list of users the current user has blocked - * @param array $anonList map of ip addresses to names like anon#1, anon#2 - * @return string html - */ - function display( $blockList, $anonList ) { - if ( $this->parentID == 0 ) { - $container_class = 'full'; - } else { - $container_class = 'reply'; - } - - $output = ''; - - if ( in_array( $this->username, $blockList ) ) { - $output .= $this->showIgnore( false, $container_class ); - $output .= $this->showComment( true, $container_class, $blockList, $anonList ); - } else { - $output .= $this->showIgnore( true, $container_class ); - $output .= $this->showComment( false, $container_class, $blockList, $anonList ); - } - - return $output; - } - - function displayForCommentOfTheDay() { - $output = ''; - - $title2 = $this->page->getTitle(); - - if ( $this->userID != 0 ) { - $title = Title::makeTitle( NS_USER, $this->username ); - $commentPoster_Display = $this->username; - $commentPoster = '' . $this->username . ''; - if ( class_exists( 'wAvatar' ) ) { - $avatar = new wAvatar( $this->userID, 's' ); - $commentIcon = $avatar->getAvatarImage(); - } else { - $commentIcon = ''; - } - } else { - $commentPoster_Display = wfMessage( 'comments-anon-name' )->plain(); - $commentPoster = wfMessage( 'comments-anon-name' )->plain(); - $commentIcon = 'default_s.gif'; - } - - $avatarHTML = ''; - if ( class_exists( 'wAvatar' ) ) { - global $wgUploadPath; - $avatarHTML = ''; - } - - $comment_text = substr( $this->text, 0, 50 - strlen( $commentPoster_Display ) ); - if ( $comment_text != $this->text ) { - $comment_text .= wfMessage( 'ellipsis' )->plain(); - } - - $output .= '
'; - $sign = ''; - if ( $this->currentScore > 0 ) { - $sign = '+'; - } elseif ( $this->currentScore < 0 ) { - $sign = '-'; // this *really* shouldn't be happening... - } - $output .= '' . $sign . $this->currentScore . - ' ' . $avatarHTML . - '' . $commentPoster . ''; - $output .= '' . $comment_text . - ''; - $output .= '
'; - - return $output; - } - - /** - * Show the box for if this comment has been ignored - * - * @param bool $hide - * @param $containerClass - * @return string - */ - function showIgnore( $hide = false, $containerClass ) { - $blockListTitle = SpecialPage::getTitleFor( 'CommentIgnoreList' ); - - $style = ''; - if ( $hide ) { - $style = " style='display:none;'"; - } - - $output = "
\n"; - $output .= wfMessage( 'comments-ignore-message' )->parse(); - $output .= '' . "\n"; - $output .= '
' . "\n"; - - return $output; - } - - /** - * Show the comment - * - * @param bool $hide: if true, comment is returned but hidden (display:none) - * @param $containerClass - * @param $blockList - * @param $anonList - * @return string - */ - function showComment( $hide = false, $containerClass, $blockList, $anonList ) { - global $wgUserLevels, $wgExtensionAssetsPath; - - $style = ''; - if ( $hide ) { - $style = " style='display:none;'"; - } - - $commentPosterLevel = ''; - - if ( $this->userID != 0 ) { - $title = Title::makeTitle( NS_USER, $this->username ); - - $commentPoster = '' . $this->username . ''; - - $CommentReplyTo = $this->username; - - if ( $wgUserLevels && class_exists( 'UserLevel' ) ) { - $user_level = new UserLevel( $this->userPoints ); - $commentPosterLevel = "{$user_level->getLevelName()}"; - } - - $user = User::newFromId( $this->userID ); - $CommentReplyToGender = $user->getOption( 'gender', 'unknown' ); - } else { - $anonMsg = $this->msg( 'comments-anon-name' )->inContentLanguage()->plain(); - $commentPoster = $anonMsg . ' #' . $anonList[$this->username]; - $CommentReplyTo = $anonMsg; - $CommentReplyToGender = 'unknown'; // Undisclosed gender as anon user - } - - // Comment delete button for privileged users - $dlt = ''; - - if ( $this->getUser()->isAllowed( 'commentadmin' ) ) { - $dlt = ' | ' . - '' . - $this->msg( 'comments-delete-link' )->plain() . ''; - } - - // Reply Link (does not appear on child comments) - $replyRow = ''; - if ( $this->getUser()->isAllowed( 'comment' ) ) { - if ( $this->parentID == 0 ) { - if ( $replyRow ) { - $replyRow .= wfMessage( 'pipe-separator' )->plain(); - } - $replyRow .= " | id}\" data-comments-safe-username=\"" . - htmlspecialchars( $CommentReplyTo, ENT_QUOTES ) . "\" data-comments-user-gender=\"" . - htmlspecialchars( $CommentReplyToGender ) . '">' . - wfMessage( 'comments-reply' )->plain() . ''; - } - } - - if ( $this->parentID == 0 ) { - $comment_class = 'f-message'; - } else { - $comment_class = 'r-message'; - } - - // Display Block icon for logged in users for comments of users - // that are already not in your block list - $blockLink = ''; - - if ( - $this->getUser()->getID() != 0 && $this->getUser()->getID() != $this->userID && - !( in_array( $this->userID, $blockList ) ) - ) { - $blockLink = ' - \"\"/ - "; - } - - // Default avatar image, if SocialProfile extension isn't enabled - global $wgCommentsDefaultAvatar; - $avatarImg = ''; - // If SocialProfile *is* enabled, then use its wAvatar class to get the avatars for each commenter - if ( class_exists( 'wAvatar' ) ) { - $avatar = new wAvatar( $this->userID, 'ml' ); - $avatarImg = $avatar->getAvatarURL() . "\n"; - } - - $output = "
" . "\n"; - $output .= "
{$avatarImg}
" . "\n"; - $output .= '
' . "\n"; - $output .= '
' . "\n"; - $output .= "{$commentPoster}"; - $output .= "{$commentPosterLevel} {$blockLink}" . "\n"; - - wfSuppressWarnings(); // E_STRICT bitches about strtotime() - $output .= '
' . - wfMessage( - 'comments-time-ago', - CommentFunctions::getTimeAgo( strtotime( $this->date ) ) - )->parse() . '
' . "\n"; - wfRestoreWarnings(); - - $output .= '
' . "\n"; - $output .= $this->getScoreHTML(); - $output .= '
' . "\n"; - - $output .= '
' . "\n"; - $output .= "
" . "\n"; - $output .= $this->getText(); - $output .= '
' . "\n"; - $output .= '
' . "\n"; - if ( $this->page->title ) { // for some reason doesn't always exist - $output .= 'id}\" rel=\"nofollow\">" . - $this->msg( 'comments-permalink' )->plain() . ' '; - } - if ( $replyRow || $dlt ) { - $output .= "{$replyRow} {$dlt}" . "\n"; - } - $output .= '
' . "\n"; - $output .= '
' . "\n"; - $output .= '
' . "\n"; - $output .= '
' . "\n"; - - return $output; - } - - /** - * Get the HTML for the comment score section of the comment - * - * @return string - */ - function getScoreHTML() { - $output = ''; - - if ( $this->page->allowMinus == true || $this->page->allowPlus == true ) { - $output .= '' . - wfMessage( 'comments-score-text' )->plain() . - " id}\">{$this->currentScore}"; - - // Voting is possible only when database is unlocked - if ( !wfReadOnly() ) { - // You can only vote for other people's comments, not for your own - if ( $this->getUser()->getName() != $this->username ) { - $output .= "id}\">"; - if ( $this->page->allowPlus == true ) { - $output .= $this->getVoteLink( 1 ); - } - - if ( $this->page->allowMinus == true ) { - $output .= $this->getVoteLink( -1 ); - } - $output .= ''; - } else { - $output .= wfMessage( 'word-separator' )->plain() . wfMessage( 'comments-you' )->plain(); - } - } - } - - return $output; - } -} + tag is in + */ + public $page = null; + + /** + * @var Integer: total amount of comments by distinct commenters that the + * current page has + */ + public $commentTotal = 0; + + /** + * @var String: text of the current comment + */ + public $text = null; + + /* START Anpassung znilwiki */ + public $CommentUsernameKOK = null; /* 25.10.2013 von Kai-Ole Kirsten */ + public $UsernameKOK = null; /* 25.10.2013 von Kai-Ole Kirsten */ + /* ENDE Anpassung znilwiki */ + + /** + * Date when the comment was posted + * + * @var null + */ + public $date = null; + + /** + * @var Integer: internal ID number (Comments.CommentID DB field) of the + * current comment that we're dealing with + */ + public $id = 0; + + /** + * @var Integer: ID of the parent comment, if this is a child comment + */ + public $parentID = 0; + + /** + * The current vote from this user on this comment + * + * @var int|boolean: false if no vote, otherwise -1, 0, or 1 + */ + public $currentVote = false; + + /** + * @var string: comment score (SUM() of all votes) of the current comment + */ + public $currentScore = '0'; + + /** + * Username of the user who posted the comment + * + * @var string + */ + public $username = ''; + + /** + * IP of the comment poster + * + * @var string + */ + public $ip = ''; + + /** + * ID of the user who posted the comment + * + * @var int + */ + public $userID = 0; + + /** + * @TODO document + * + * @var int + */ + public $userPoints = 0; + + /** + * Comment ID of the thread this comment is in + * this is the ID of the parent comment if there is one, + * or this comment if there is not + * Used for sorting + * + * @var null + */ + public $thread = null; + + /** + * Unix timestamp when the comment was posted + * Used for sorting + * Processed from $date + * + * @var null + */ + public $timestamp = null; + + /** + * Constructor - set the page ID + * + * @param $page CommentsPage: ID number of the current page + * @param IContextSource $context + * @param $data: straight from the DB about the comment + */ + public function __construct( CommentsPage $page, $context = null, $data ) { + $this->page = $page; + + $this->setContext( $context ); + + $this->username = $data['Comment_Username']; + $this->ip = $data['Comment_IP']; + $this->text = $data['Comment_Text']; + $this->date = $data['Comment_Date']; + $this->userID = $data['Comment_user_id']; + $this->userPoints = $data['Comment_user_points']; + $this->id = $data['CommentID']; + $this->parentID = $data['Comment_Parent_ID']; + $this->thread = $data['thread']; + $this->timestamp = $data['timestamp']; + + if ( isset( $data['current_vote'] ) ) { + $vote = $data['current_vote']; + } else { + $dbr = wfGetDB( DB_SLAVE ); + $row = $dbr->selectRow( + 'Comments_Vote', + array( 'Comment_Vote_Score' ), + array( + 'Comment_Vote_ID' => $this->id, + 'Comment_Vote_Username' => $this->getUser()->getName() + ), + __METHOD__ + ); + if ( $row !== false ) { + $vote = $row->Comment_Vote_Score; + } else { + $vote = false; + } + } + + $this->currentVote = $vote; + + $this->currentScore = isset( $data['total_vote'] ) + ? $data['total_vote'] : $this->getScore(); + } + + public static function newFromID( $id ) { + $context = RequestContext::getMain(); + $dbr = wfGetDB( DB_SLAVE ); + + if ( !is_numeric( $id ) || $id == 0 ) { + return null; + } + + $tables = array(); + $params = array(); + $joinConds = array(); + + // Defaults (for non-social wikis) + $tables[] = 'Comments'; + $fields = array( + 'Comment_Username', 'Comment_IP', 'Comment_Text', + 'Comment_Date', 'Comment_Date AS timestamp', + 'Comment_user_id', 'CommentID', 'Comment_Parent_ID', + 'CommentID', 'Comment_Page_ID' + ); + + // If SocialProfile is installed, query the user_stats table too. + if ( + class_exists( 'UserProfile' ) && + $dbr->tableExists( 'user_stats' ) + ) { + $tables[] = 'user_stats'; + $fields[] = 'stats_total_points'; + $joinConds = array( + 'Comments' => array( + 'LEFT JOIN', 'Comment_user_id = stats_user_id' + ) + ); + } + + // Perform the query + $res = $dbr->select( + $tables, + $fields, + array( 'CommentID' => $id ), + __METHOD__, + $params, + $joinConds + ); + + $row = $res->fetchObject(); + + if ( $row->Comment_Parent_ID == 0 ) { + $thread = $row->CommentID; + } else { + $thread = $row->Comment_Parent_ID; + } + $data = array( + 'Comment_Username' => $row->Comment_Username, + 'Comment_IP' => $row->Comment_IP, + 'Comment_Text' => $row->Comment_Text, + 'Comment_Date' => $row->Comment_Date, + 'Comment_user_id' => $row->Comment_user_id, + 'Comment_user_points' => ( isset( $row->stats_total_points ) ? number_format( $row->stats_total_points ) : 0 ), + 'CommentID' => $row->CommentID, + 'Comment_Parent_ID' => $row->Comment_Parent_ID, + 'thread' => $thread, + 'timestamp' => wfTimestamp( TS_UNIX, $row->timestamp ) + ); + + $page = new CommentsPage( $row->Comment_Page_ID, $context ); + + return new Comment( $page, $context, $data ); + } + + /** + * Parse and return the text for this comment + * + * @return mixed|string + * @throws MWException + */ + function getText() { + global $wgParser; + + $commentText = trim( str_replace( '"', "'", $this->text ) ); + $comment_text_parts = explode( "\n", $commentText ); + $comment_text_fix = ''; + foreach ( $comment_text_parts as $part ) { + $comment_text_fix .= ( ( $comment_text_fix ) ? "\n" : '' ) . trim( $part ); + } + + if ( $this->getTitle()->getArticleID() > 0 ) { + $commentText = $wgParser->recursiveTagParse( $comment_text_fix ); + } else { + $commentText = $this->getOutput()->parse( $comment_text_fix ); + } + + // really bad hack because we want to parse=firstline, but don't want wrapping

tags + if ( substr( $commentText, 0 , 3 ) == '

' ) { + $commentText = substr( $commentText, 3 ); + } + + if ( substr( $commentText, strlen( $commentText ) -4 , 4 ) == '

' ) { + $commentText = substr( $commentText, 0, strlen( $commentText ) -4 ); + } + + // make sure link text is not too long (will overflow) + // this function changes too long links to http://www.abc....xyz.html + $commentText = preg_replace_callback( + "/(]*>)(.*?)(<\/a>)/i", + array( 'CommentFunctions', 'cutCommentLinkText' ), + $commentText + ); + + return $commentText; + } + + /** + * Adds the comment and all necessary info into the Comments table in the + * database. + * + * @param string $text: text of the comment + * @param CommentsPage $page: container page + * @param User $user: user commenting + * @param int $parentID: ID of parent comment, if this is a reply + * + * @return Comment: the added comment + */ + static function add( $text, CommentsPage $page, User $user, $parentID ) { + global $wgCommentsInRecentChanges; + $dbw = wfGetDB( DB_MASTER ); + $context = RequestContext::getMain(); + + wfSuppressWarnings(); + $commentDate = date( 'Y-m-d H:i:s' ); + wfRestoreWarnings(); + // ##START## 2017-09-27 von Bernhard Linz +// if ( $this->getUser()->isLoggedIn() ) { +// $kok_username = $user->getName(); +// $kok_username = $this->UsernameKOK; +// } else { + $kok_username = preg_match('/(?<=#START#).*?(?=#ENDE#)/s', $text, $result); + $kok_username = $result[0]; + $text = str_replace('#START#' . $result[0] . '#ENDE#', '', $text); +// $kok_username = str_replace('#START#', '', $kok_username); +// $kok_username = str_replace('#ENDE#', '', $kok_username); + if ( $kok_username == "" ) { + $kok_username = $user->getName(); + } + if ( $kok_username == "none" ) { + $kok_username = $user->getName(); + } +// $kok_username = preg_replace('/<.*>/i', '', $kok_username); +// $kok_username = preg_replace('/[^A-Za-z0-9. \-\@]/i', '', $kok_username); +// $kok_username = str_replace("1'1", '', $kok_username); +// $kok_username = str_replace('USER_NAME', '', $kok_username); +// $kok_username = str_replace('DESC', '', $kok_username); +// $kok_username = str_replace('(*)', '', $kok_username); +// $kok_username = str_replace('EXEC', '', $kok_username); */ + // } + // ##ENDE## 2017-09-27 von Bernhard Linz + $dbw->insert( + 'Comments', + array( + 'Comment_Page_ID' => $page->id, + //'Comment_Username' => $user->getName(), + 'Comment_Username' => $kok_username, + 'Comment_user_id' => $user->getId(), + 'Comment_Text' => $text, + 'Comment_Date' => $commentDate, + 'Comment_Parent_ID' => $parentID, + 'Comment_IP' => $_SERVER['REMOTE_ADDR'] + ), + __METHOD__ + ); + $commentId = $dbw->insertId(); + $dbw->commit( __METHOD__ ); // misza: added this + $id = $commentId; + + $page->clearCommentListCache(); + + // Add a log entry. + self::log( 'add', $user, $page->id, $commentId, $text ); + + $dbr = wfGetDB( DB_SLAVE ); + if ( + class_exists( 'UserProfile' ) && + $dbr->tableExists( 'user_stats' ) + ) { + $res = $dbr->select( // need this data for seeding a Comment object + 'user_stats', + 'stats_total_points', + array( 'stats_user_id' => $user->getId() ), + __METHOD__ + ); + + $row = $res->fetchObject(); + $userPoints = number_format( $row->stats_total_points ); + } else { + $userPoints = 0; + } + + if ( $parentID == 0 ) { + $thread = $id; + } else { + $thread = $parentID; + } + $data = array( + 'Comment_Username' => $user->getName(), + 'Comment_IP' => $context->getRequest()->getIP(), + 'Comment_Text' => $text, + 'Comment_Date' => $commentDate, + 'Comment_user_id' => $user->getID(), + 'Comment_user_points' => $userPoints, + 'CommentID' => $id, + 'Comment_Parent_ID' => $parentID, + 'thread' => $thread, + 'timestamp' => strtotime( $commentDate ) + ); + + $page = new CommentsPage( $page->id, $context ); + $comment = new Comment( $page, $context, $data ); + + Hooks::run( 'Comment::add', array( $comment, $commentId, $comment->page->id ) ); + /* ## START Kommentar auch per Email versenden ## 11/2014 Bernhard Linz */ + $znilpageTitle = ""; + $comment_mailto = "root@linz.email"; + $comment_mailsubject = "Neuer Kommentar von: " . $kok_username . " - IP: " . $_SERVER['REMOTE_ADDR'] . " - DNS: " . gethostbyaddr($_SERVER['REMOTE_ADDR']) ; + $comment_mailfrom = "MIME-Version: 1.0\r\n"; + $comment_mailfrom .= "Content-type: text/html; charset=utf-8\r\n"; + $comment_mailfrom .= "From: znil.net Kommentare \r\n"; + $comment_url = "http://znil.net/index.php?title={$znilpageTitle}#comment-{$commentId}"; + $comment_mailtext = $commentDate . "

" . $comment_url . "


" . "IP: " . $_SERVER['REMOTE_ADDR'] . "
" . "DNS: " . gethostbyaddr($_SERVER['REMOTE_ADDR']) ."

" . $kok_username . "

" . $text; + $comment_mailtext = nl2br($comment_mailtext); + mail($comment_mailto, $comment_mailsubject, $comment_mailtext, $comment_mailfrom); + /* ## ENDE Bernhard Linz */ + return $comment; + } + + /** + * Gets the score for this comment from the database table Comments_Vote + * + * @return string + */ + function getScore() { + $dbr = wfGetDB( DB_SLAVE ); + $row = $dbr->selectRow( + 'Comments_Vote', + array( 'SUM(Comment_Vote_Score) AS CommentScore' ), + array( 'Comment_Vote_ID' => $this->id ), + __METHOD__ + ); + $score = '0'; + if ( $row !== false && $row->CommentScore ) { + $score = $row->CommentScore; + } + return $score; + } + + /* START Anpassungen znilwiki */ + /* ## START ## 25.10.2013 Hinzugefügt von Kai-Ole */ + function setCommentUsernameKOK( $UsernameKOK ) { + $this->CommentUsernameKOK = $UsernameKOK; + } + /* ## ENDE ## 25.10.2013 Kai-Ole */ + /* ENDE Anpassungen znilwiki */ + + /** + * Adds a vote for a comment if the user hasn't voted for said comment yet. + * + * @param $value int: upvote or downvote (1 or -1) + */ + function vote( $value ) { + global $wgMemc; + $dbw = wfGetDB( DB_MASTER ); + + if ( $value < -1 ) { // limit to range -1 -> 0 -> 1 + $value = -1; + } elseif ( $value > 1 ) { + $value = 1; + } + + if ( $value == $this->currentVote ) { // user toggling off a preexisting vote + $value = 0; + } + + wfSuppressWarnings(); + $commentDate = date( 'Y-m-d H:i:s' ); + wfRestoreWarnings(); + + if ( $this->currentVote === false ) { // no vote, insert + $dbw->insert( + 'Comments_Vote', + array( + 'Comment_Vote_id' => $this->id, + 'Comment_Vote_Username' => $this->getUser()->getName(), + 'Comment_Vote_user_id' => $this->getUser()->getId(), + 'Comment_Vote_Score' => $value, + 'Comment_Vote_Date' => $commentDate, + 'Comment_Vote_IP' => $_SERVER['REMOTE_ADDR'] + ), + __METHOD__ + ); + } else { // already a vote, update + $dbw->update( + 'Comments_Vote', + array( + 'Comment_Vote_Score' => $value, + 'Comment_Vote_Date' => $commentDate, + 'Comment_Vote_IP' => $_SERVER['REMOTE_ADDR'] + ), + array( + 'Comment_Vote_id' => $this->id, + 'Comment_Vote_Username' => $this->getUser()->getName(), + 'Comment_Vote_user_id' => $this->getUser()->getId(), + ), + __METHOD__ + ); + } + $dbw->commit( __METHOD__ ); + + // update cache for comment list + // should perform better than deleting cache completely since Votes happen more frequently + $key = wfMemcKey( 'comment', 'pagethreadlist', $this->page->id ); + $comments = $wgMemc->get( $key ); + if ( $comments ) { + foreach ( $comments as &$comment ) { + if ( $comment->id == $this->id ) { + $comment->currentScore = $this->currentScore; + } + } + $wgMemc->set( $key, $comments ); + } + + $score = $this->getScore(); + + $this->currentVote = $value; + $this->currentScore = $score; + } + + /** + * Deletes entries from Comments and Comments_Vote tables and clears caches + */ + function delete() { + $dbw = wfGetDB( DB_MASTER ); + $dbw->delete( + 'Comments', + array( 'CommentID' => $this->id ), + __METHOD__ + ); + $dbw->delete( + 'Comments_Vote', + array( 'Comment_Vote_ID' => $this->id ), + __METHOD__ + ); + $dbw->commit( __METHOD__ ); + + // Log the deletion to Special:Log/comments. + self::log( 'delete', $this->getUser(), $this->page->id, $this->id ); + + // Clear memcache & Squid cache + $this->page->clearCommentListCache(); + + // Ping other extensions that may have hooked into this point (i.e. LinkFilter) + Hooks::run( 'Comment::delete', array( $this, $this->id, $this->page->id ) ); + } + + /** + * Log an action in the comment log. + * + * @param string $action Action to log, can be either 'add' or 'delete' + * @param User $user User who performed the action + * @param int $pageId Page ID of the page that contains the comment thread + * @param int $commentId Comment ID of the affected comment + * @param string $commentText Supplementary log comment, if any + */ + static function log( $action, $user, $pageId, $commentId, $commentText = null ) { + global $wgCommentsInRecentChanges; + $logEntry = new ManualLogEntry( 'comments', $action ); + $logEntry->setPerformer( $user ); + $logEntry->setTarget( Title::newFromId( $pageId ) ); + if ( $commentText !== null ) { + $logEntry->setComment( $commentText ); + } + $logEntry->setParameters( array( + '4::commentid' => $commentId + ) ); + $logId = $logEntry->insert(); + $logEntry->publish( $logId, ( $wgCommentsInRecentChanges ? 'rcandudp' : 'udp' ) ); + } + + /** + * Return the HTML for the comment vote links + * + * @param int $voteType up (+1) vote or down (-1) vote + * @return string + */ + function getVoteLink( $voteType ) { + global $wgExtensionAssetsPath; + + // Blocked users cannot vote, obviously + if ( $this->getUser()->isBlocked() ) { + return ''; + } + if ( !$this->getUser()->isAllowed( 'comment' ) ) { + return ''; + } + + $voteLink = ''; + if ( $this->getUser()->isLoggedIn() ) { + $voteLink .= ''; + } else { + $login = SpecialPage::getTitleFor( 'Userlogin' ); // Anonymous users need to log in before they can vote + $returnTo = $this->page->title->getPrefixedDBkey(); // Determine a sane returnto URL parameter + + $voteLink .= + "getLocalURL( array( 'returnto' => $returnTo ) ) ) . + "\" rel=\"nofollow\">"; + } + + $imagePath = $wgExtensionAssetsPath . '/Comments/resources/images'; + if ( $voteType == 1 ) { + if ( $this->currentVote == 1 ) { + $voteLink .= "\"+\""; + } else { + $voteLink .= "\"+\""; + } + } else { + if ( $this->currentVote == -1 ) { + $voteLink .= "\"+\""; + } else { + $voteLink .= "\"+\""; + } + } + + return $voteLink; + } + + /** + * Show the HTML for this comment and ignore section + * + * @param array $blockList list of users the current user has blocked + * @param array $anonList map of ip addresses to names like anon#1, anon#2 + * @return string html + */ + function display( $blockList, $anonList ) { + if ( $this->parentID == 0 ) { + $container_class = 'full'; + } else { + $container_class = 'reply'; + } + + $output = ''; + + if ( in_array( $this->username, $blockList ) ) { + $output .= $this->showIgnore( false, $container_class ); + $output .= $this->showComment( true, $container_class, $blockList, $anonList ); + } else { + $output .= $this->showIgnore( true, $container_class ); + $output .= $this->showComment( false, $container_class, $blockList, $anonList ); + } + + return $output; + } + + function displayForCommentOfTheDay() { + $output = ''; + + $title2 = $this->page->getTitle(); + + if ( $this->userID != 0 ) { + $title = Title::makeTitle( NS_USER, $this->username ); + $commentPoster_Display = $this->username; + $commentPoster = '' . $this->username . ''; + if ( class_exists( 'wAvatar' ) ) { + $avatar = new wAvatar( $this->userID, 's' ); + $commentIcon = $avatar->getAvatarImage(); + } else { + $commentIcon = ''; + } + } else { + $commentPoster_Display = wfMessage( 'comments-anon-name' )->plain(); + $commentPoster = wfMessage( 'comments-anon-name' )->plain(); + $commentIcon = 'default_s.gif'; + } + + $avatarHTML = ''; + if ( class_exists( 'wAvatar' ) ) { + global $wgUploadPath; + $avatarHTML = ''; + } + + $comment_text = substr( $this->text, 0, 50 - strlen( $commentPoster_Display ) ); + if ( $comment_text != $this->text ) { + $comment_text .= wfMessage( 'ellipsis' )->plain(); + } + + $output .= '
'; + $sign = ''; + if ( $this->currentScore > 0 ) { + $sign = '+'; + } elseif ( $this->currentScore < 0 ) { + $sign = '-'; // this *really* shouldn't be happening... + } + $output .= '' . $sign . $this->currentScore . + ' ' . $avatarHTML . + '' . $commentPoster . ''; + $output .= '' . $comment_text . + ''; + $output .= '
'; + + return $output; + } + + /** + * Show the box for if this comment has been ignored + * + * @param bool $hide + * @param $containerClass + * @return string + */ + function showIgnore( $hide = false, $containerClass ) { + $blockListTitle = SpecialPage::getTitleFor( 'CommentIgnoreList' ); + + $style = ''; + if ( $hide ) { + $style = " style='display:none;'"; + } + + $output = "
\n"; + $output .= wfMessage( 'comments-ignore-message' )->parse(); + $output .= '' . "\n"; + $output .= '
' . "\n"; + + return $output; + } + + /** + * Show the comment + * + * @param bool $hide: if true, comment is returned but hidden (display:none) + * @param $containerClass + * @param $blockList + * @param $anonList + * @return string + */ + function showComment( $hide = false, $containerClass, $blockList, $anonList ) { + global $wgUserLevels, $wgExtensionAssetsPath; + + $style = ''; + if ( $hide ) { + $style = " style='display:none;'"; + } + + $commentPosterLevel = ''; + + if ( $this->userID != 0 ) { + $title = Title::makeTitle( NS_USER, $this->username ); + + $commentPoster = '' . $this->username . ''; + + $CommentReplyTo = $this->username; + + if ( $wgUserLevels && class_exists( 'UserLevel' ) ) { + $user_level = new UserLevel( $this->userPoints ); + $commentPosterLevel = "{$user_level->getLevelName()}"; + } + + $user = User::newFromId( $this->userID ); + $CommentReplyToGender = $user->getOption( 'gender', 'unknown' ); + } else { + $anonMsg = $this->msg( 'comments-anon-name' )->inContentLanguage()->plain(); + $commentPoster = $anonMsg . ' #' . $anonList[$this->username]; + $CommentReplyTo = $anonMsg; + $CommentReplyToGender = 'unknown'; // Undisclosed gender as anon user + } + + // Comment delete button for privileged users + $dlt = ''; + + if ( $this->getUser()->isAllowed( 'commentadmin' ) ) { + $dlt = ' | ' . + '' . + $this->msg( 'comments-delete-link' )->plain() . ''; + } + + // Reply Link (does not appear on child comments) + $replyRow = ''; + if ( $this->getUser()->isAllowed( 'comment' ) ) { + if ( $this->parentID == 0 ) { + if ( $replyRow ) { + $replyRow .= wfMessage( 'pipe-separator' )->plain(); + } + $replyRow .= " | id}\" data-comments-safe-username=\"" . + htmlspecialchars( $CommentReplyTo, ENT_QUOTES ) . "\" data-comments-user-gender=\"" . + htmlspecialchars( $CommentReplyToGender ) . '">' . + wfMessage( 'comments-reply' )->plain() . ''; + } + } + + if ( $this->parentID == 0 ) { + $comment_class = 'f-message'; + } else { + $comment_class = 'r-message'; + } + + // Display Block icon for logged in users for comments of users + // that are already not in your block list + $blockLink = ''; + + if ( + $this->getUser()->getID() != 0 && $this->getUser()->getID() != $this->userID && + !( in_array( $this->userID, $blockList ) ) + ) { + $blockLink = ' + \"\"/ + "; + } + + // Default avatar image, if SocialProfile extension isn't enabled + global $wgCommentsDefaultAvatar; + $avatarImg = ''; + // If SocialProfile *is* enabled, then use its wAvatar class to get the avatars for each commenter + if ( class_exists( 'wAvatar' ) ) { + $avatar = new wAvatar( $this->userID, 'ml' ); + $avatarImg = $avatar->getAvatarURL() . "\n"; + } + + $output = "
" . "\n"; + $output .= "
{$avatarImg}
" . "\n"; + $output .= '
' . "\n"; + $output .= '
' . "\n"; + $output .= "{$commentPoster}"; + $output .= "{$commentPosterLevel} {$blockLink}" . "\n"; + + wfSuppressWarnings(); // E_STRICT bitches about strtotime() + $output .= '
' . + wfMessage( + 'comments-time-ago', + CommentFunctions::getTimeAgo( strtotime( $this->date ) ) + )->parse() . '
' . "\n"; + wfRestoreWarnings(); + + $output .= '
' . "\n"; + $output .= $this->getScoreHTML(); + $output .= '
' . "\n"; + + $output .= '
' . "\n"; + $output .= "
" . "\n"; + $output .= $this->getText(); + $output .= '
' . "\n"; + $output .= '
' . "\n"; + if ( $this->page->title ) { // for some reason doesn't always exist + $output .= 'id}\" rel=\"nofollow\">" . + $this->msg( 'comments-permalink' )->plain() . ' '; + } + if ( $replyRow || $dlt ) { + $output .= "{$replyRow} {$dlt}" . "\n"; + } + $output .= '
' . "\n"; + $output .= '
' . "\n"; + $output .= '
' . "\n"; + $output .= '
' . "\n"; + + return $output; + } + + /** + * Get the HTML for the comment score section of the comment + * + * @return string + */ + function getScoreHTML() { + $output = ''; + + if ( $this->page->allowMinus == true || $this->page->allowPlus == true ) { + $output .= '' . + wfMessage( 'comments-score-text' )->plain() . + " id}\">{$this->currentScore}"; + + // Voting is possible only when database is unlocked + if ( !wfReadOnly() ) { + // You can only vote for other people's comments, not for your own + if ( $this->getUser()->getName() != $this->username ) { + $output .= "id}\">"; + if ( $this->page->allowPlus == true ) { + $output .= $this->getVoteLink( 1 ); + } + + if ( $this->page->allowMinus == true ) { + $output .= $this->getVoteLink( -1 ); + } + $output .= ''; + } else { + $output .= wfMessage( 'word-separator' )->plain() . wfMessage( 'comments-you' )->plain(); + } + } + } + + return $output; + } +} diff --git a/includes/CommentsPage.class.php b/includes/CommentsPage.class.php index 3887cb1..756f1f3 100644 --- a/includes/CommentsPage.class.php +++ b/includes/CommentsPage.class.php @@ -1,608 +1,614 @@ -id = $pageID; - $this->setContext( $context ); - $this->title = Title::newFromID( $pageID ); - } - - /** - * Gets the total amount of comments on this page - * - * @return int - */ - function countTotal() { - $dbr = wfGetDB( DB_SLAVE ); - $count = 0; - $s = $dbr->selectRow( - 'Comments', - array( 'COUNT(*) AS CommentCount' ), - array( 'Comment_Page_ID' => $this->id ), - __METHOD__ - ); - if ( $s !== false ) { - $count = $s->CommentCount; - } - return $count; - } - - /** - * Gets the ID number of the latest comment for the current page. - * - * @return int - */ - function getLatestCommentID() { - $latestCommentID = 0; - $dbr = wfGetDB( DB_SLAVE ); - $s = $dbr->selectRow( - 'Comments', - array( 'CommentID' ), - array( 'Comment_Page_ID' => $this->id ), - __METHOD__, - array( 'ORDER BY' => 'Comment_Date DESC', 'LIMIT' => 1 ) - ); - if ( $s !== false ) { - $latestCommentID = $s->CommentID; - } - return $latestCommentID; - } - - /** - * Set voting either totally off, or disallow "thumbs down" or disallow - * "thumbs up". - * - * @param string $voting 'OFF', 'PLUS' or 'MINUS' (will be strtoupper()ed) - */ - function setVoting( $voting ) { - $this->voting = $voting; - $voting = strtoupper( $voting ); - - if ( $voting == 'OFF' ) { - $this->allowMinus = false; - $this->allowPlus = false; - } - if ( $voting == 'PLUS' ) { - $this->allowMinus = false; - } - if ( $voting == 'MINUS' ) { - $this->allowPlus = false; - } - } - - /** - * Fetches all comments, called by display(). - * - * @return array Array containing every possible bit of information about - * a comment, including score, timestamp and more - */ - public function getComments() { - $dbr = wfGetDB( DB_SLAVE ); - - // Defaults (for non-social wikis) - $tables = array( - 'Comments', - 'vote1' => 'Comments_Vote', - 'vote2' => 'Comments_Vote', - ); - $fields = array( - 'Comment_Username', 'Comment_IP', 'Comment_Text', - 'Comment_Date', 'Comment_Date AS timestamp', - 'Comment_user_id', 'CommentID', 'Comment_Parent_ID', - 'vote1.Comment_Vote_Score AS current_vote', - 'SUM(vote2.Comment_Vote_Score) AS comment_score' - ); - $joinConds = array( - // For current user's vote - 'vote1' => array( - 'LEFT JOIN', - array( - 'vote1.Comment_Vote_ID = CommentID', - 'vote1.Comment_Vote_Username' => $this->getUser()->getName() - ) - ), - // For total vote count - 'vote2' => array( 'LEFT JOIN', 'vote2.Comment_Vote_ID = CommentID' ) - ); - $params = array( 'GROUP BY' => 'CommentID' ); - - // If SocialProfile is installed, query the user_stats table too. - if ( - class_exists( 'UserProfile' ) && - $dbr->tableExists( 'user_stats' ) - ) { - $tables[] = 'user_stats'; - $fields[] = 'stats_total_points'; - $joinConds['Comments'] = array( - 'LEFT JOIN', 'Comment_user_id = stats_user_id' - ); - } - - // Perform the query - $res = $dbr->select( - $tables, - $fields, - array( 'Comment_Page_ID' => $this->id ), - __METHOD__, - $params, - $joinConds - ); - - $comments = array(); - - foreach ( $res as $row ) { - if ( $row->Comment_Parent_ID == 0 ) { - $thread = $row->CommentID; - } else { - $thread = $row->Comment_Parent_ID; - } - $data = array( - 'Comment_Username' => $row->Comment_Username, - 'Comment_IP' => $row->Comment_IP, - 'Comment_Text' => $row->Comment_Text, - 'Comment_Date' => $row->Comment_Date, - 'Comment_user_id' => $row->Comment_user_id, - 'Comment_user_points' => ( isset( $row->stats_total_points ) ? number_format( $row->stats_total_points ) : 0 ), - 'CommentID' => $row->CommentID, - 'Comment_Parent_ID' => $row->Comment_Parent_ID, - 'thread' => $thread, - 'timestamp' => wfTimestamp( TS_UNIX, $row->timestamp ), - 'current_vote' => ( isset( $row->current_vote ) ? $row->current_vote : false ), - 'total_vote' => ( isset( $row->comment_score ) ? $row->comment_score : 0 ), - ); - - $comments[] = new Comment( $this, $this->getContext(), $data ); - } - - $commentThreads = array(); - - foreach ( $comments as $comment ) { - if ( $comment->parentID == 0 ) { - $commentThreads[$comment->id] = array( $comment ); - } else { - $commentThreads[$comment->parentID][] = $comment; - } - } - - return $commentThreads; - } - - /** - * @return int The page we are currently paged to - * not used for any API calls - */ - function getCurrentPagerPage() { - if ( $this->currentPagerPage == 0 ) { - $this->currentPagerPage = $this->getRequest()->getInt( $this->pageQuery, 1 ); - - if ( $this->currentPagerPage < 1 ) { - $this->currentPagerPage = 1; - } - } - - return $this->currentPagerPage; - } - - /** - * Display pager for the current page. - * - * @param int $pagerCurrent Page we are currently paged to - * @param int $pagesCount The maximum page number - * - * @return string: the links for paging through pages of comments - */ - function displayPager( $pagerCurrent, $pagesCount ) { - // Middle is used to "center" pages around the current page. - $pager_middle = ceil( $this->pagerLimit / 2 ); - // first is the first page listed by this pager piece (re quantity) - $pagerFirst = $pagerCurrent - $pager_middle + 1; - // last is the last page listed by this pager piece (re quantity) - $pagerLast = $pagerCurrent + $this->pagerLimit - $pager_middle; - - // Prepare for generation loop. - $i = $pagerFirst; - if ( $pagerLast > $pagesCount ) { - // Adjust "center" if at end of query. - $i = $i + ( $pagesCount - $pagerLast ); - $pagerLast = $pagesCount; - } - if ( $i <= 0 ) { - // Adjust "center" if at start of query. - $pagerLast = $pagerLast + ( 1 - $i ); - $i = 1; - } - - $output = ''; - if ( $pagesCount > 1 ) { - $output .= '
    '; - $pagerEllipsis = '
  • ...
  • '; - - // Whether to display the "Previous page" link - if ( $pagerCurrent > 1 ) { - $output .= '
  • ' . - Html::rawElement( - 'a', - array( - 'rel' => 'nofollow', - 'class' => 'c-pager-link', - 'href' => '#cfirst', - 'data-' . $this->pageQuery => ( $pagerCurrent - 1 ), - ), - '<' - ) . - '
  • '; - } - - // Whether to display the "First page" link - if ( $i > 1 ) { - $output .= '
  • ' . - Html::rawElement( - 'a', - array( - 'rel' => 'nofollow', - 'class' => 'c-pager-link', - 'href' => '#cfirst', - 'data-' . $this->pageQuery => 1, - ), - 1 - ) . - '
  • '; - } - - // When there is more than one page, create the pager list. - if ( $i != $pagesCount ) { - if ( $i > 2 ) { - $output .= $pagerEllipsis; - } - - // Now generate the actual pager piece. - for ( ; $i <= $pagerLast && $i <= $pagesCount; $i++ ) { - if ( $i == $pagerCurrent ) { - $output .= '
  • ' . - $i . '
  • '; - } else { - $output .= '
  • ' . - Html::rawElement( - 'a', - array( - 'rel' => 'nofollow', - 'class' => 'c-pager-link', - 'href' => '#cfirst', - 'data-' . $this->pageQuery => $i, - ), - $i - ) . - '
  • '; - } - } - - if ( $i < $pagesCount ) { - $output .= $pagerEllipsis; - } - } - - // Whether to display the "Last page" link - if ( $pagesCount > ( $i - 1 ) ) { - $output .= '
  • ' . - Html::rawElement( - 'a', - array( - 'rel' => 'nofollow', - 'class' => 'c-pager-link', - 'href' => '#cfirst', - 'data-' . $this->pageQuery => $pagesCount, - ), - $pagesCount - ) . - '
  • '; - } - - // Whether to display the "Next page" link - if ( $pagerCurrent < $pagesCount ) { - $output .= '
  • ' . - Html::rawElement( - 'a', - array( - 'rel' => 'nofollow', - 'class' => 'c-pager-link', - 'href' => '#cfirst', - 'data-' . $this->pageQuery => ( $pagerCurrent + 1 ), - ), - '>' - ) . - '
  • '; - } - - $output .= '
'; - } - - return $output; - } - - /** - * Get this list of anon commenters in the given list of comments, - * and return a mapped array of IP adressess to the the number anon poster - * (so anon posters can be called Anon#1, Anon#2, etc - * - * @return array - */ - function getAnonList() { - $counter = 1; - $bucket = array(); - - $commentThreads = $this->comments; - - $comments = array(); // convert 2nd threads array to a simple list of comments - foreach ( $commentThreads as $thread ) { - $comments = array_merge( $comments, $thread ); - } - usort( $comments, array( 'CommentFunctions', 'sortTime' ) ); - - foreach ( $comments as $comment ) { - if ( - !array_key_exists( $comment->username, $bucket ) && - $comment->userID == 0 - ) { - $bucket[$comment->username] = $counter; - $counter++; - } - } - - return $bucket; - } - - /** - * Sort an array of comment threads - * @param $threads - * @return mixed - */ - function sort( $threads ) { - global $wgCommentsSortDescending; - - if ( $this->orderBy ) { - usort( $threads, array( 'CommentFunctions', 'sortScore' ) ); - } elseif ( $wgCommentsSortDescending ) { - usort( $threads, array( 'CommentFunctions', 'sortDesc' ) ); - } else { - usort( $threads, array( 'CommentFunctions', 'sortAsc' ) ); - } - - return $threads; - } - - /** - * Convert an array of comment threads into an array of pages (arrays) of comment threads - * @param $comments - * @return array - */ - function page( $comments ) { - return array_chunk( $comments, $this->limit ); - } - - /** - * Display all the comments for the current page. - * CSS and JS is loaded in CommentsHooks.php - */ - function display() { - $output = ''; - - $commentThreads = $this->getComments(); - $commentThreads = $this->sort( $commentThreads ); - - $this->comments = $commentThreads; - - $commentPages = $this->page( $commentThreads ); - $currentPageNum = $this->getCurrentPagerPage(); - $numPages = count( $commentPages ); - // Suppress random E_NOTICE about "Undefined offset: 0", which seems to - // be breaking ProblemReports (at least on my local devbox, not sure - // about prod). --Jack Phoenix, 13 July 2015 - wfSuppressWarnings(); - $currentPage = $commentPages[$currentPageNum - 1]; - wfRestoreWarnings(); - - // Load complete blocked list for logged in user so they don't see their comments - $blockList = array(); - if ( $this->getUser()->getID() != 0 ) { - $blockList = CommentFunctions::getBlockList( $this->getUser()->getId() ); - } - - if ( $currentPage ) { - $pager = $this->displayPager( $currentPageNum, $numPages ); - $output .= $pager; - $output .= ''; - - $anonList = $this->getAnonList(); - - foreach ( $currentPage as $thread ) { - foreach ( $thread as $comment ) { - $output .= $comment->display( $blockList, $anonList ); - } - } - $output .= $pager; - } - - return $output; - } - - /** - * Displays the "Sort by X" form and a link to auto-refresh comments - * - * @return string HTML - */ - function displayOrderForm() { - $output = '
-
-
- -
-
- -
-
-
' . "\n"; - - return $output; - } - - /** - * Displays the form for adding new comments - * - * @return string HTML output - */ - function displayForm() { - $output = '
' . "\n"; - - if ( $this->allow ) { - $pos = strpos( - strtoupper( addslashes( $this->allow ) ), - strtoupper( addslashes( $this->getUser()->getName() ) ) - ); - } - - // 'comment' user right is required to add new comments - if ( !$this->getUser()->isAllowed( 'comment' ) ) { - $output .= wfMessage( 'comments-not-allowed' )->parse(); - } else { - // Blocked users can't add new comments under any conditions... - // and maybe there's a list of users who should be allowed to post - // comments - if ( $this->getUser()->isBlocked() == false && ( $this->allow == '' || $pos !== false ) ) { - $output .= '
' . wfMessage( 'comments-submit' )->plain() . '
' . "\n"; - $output .= '
' . "\n"; - // Show a message to anons, prompting them to register or log in - if ( !$this->getUser()->isLoggedIn() ) { - $login_title = SpecialPage::getTitleFor( 'Userlogin' ); - $register_title = SpecialPage::getTitleFor( 'Userlogin', 'signup' ); - $output .= '
' . wfMessage( - 'comments-anon-message', - htmlspecialchars( $register_title->getFullURL() ), - htmlspecialchars( $login_title->getFullURL() ) - )->text() . '
' . "\n"; - } - - $output .= '' . "\n"; - $output .= '
' . "\n"; - } - $output .= '' . "\n"; - $output .= '' . "\n"; - $output .= '' . "\n"; - $output .= '' . "\n"; - $output .= '' . "\n"; - $output .= '' . "\n"; - $output .= Html::hidden( 'token', $this->getUser()->getEditToken() ); - } - $output .= '
' . "\n"; - return $output; - } - - /** - * Purge caches (parser cache and Squid cache) - */ - function clearCommentListCache() { - wfDebug( "Clearing comments for page {$this->id} from cache\n" ); - - if ( is_object( $this->title ) ) { - $this->title->invalidateCache(); - $this->title->purgeSquid(); - } - } - -} +id = $pageID; + $this->setContext( $context ); + $this->title = Title::newFromID( $pageID ); + } + + /** + * Gets the total amount of comments on this page + * + * @return int + */ + function countTotal() { + $dbr = wfGetDB( DB_SLAVE ); + $count = 0; + $s = $dbr->selectRow( + 'Comments', + array( 'COUNT(*) AS CommentCount' ), + array( 'Comment_Page_ID' => $this->id ), + __METHOD__ + ); + if ( $s !== false ) { + $count = $s->CommentCount; + } + return $count; + } + + /** + * Gets the ID number of the latest comment for the current page. + * + * @return int + */ + function getLatestCommentID() { + $latestCommentID = 0; + $dbr = wfGetDB( DB_SLAVE ); + $s = $dbr->selectRow( + 'Comments', + array( 'CommentID' ), + array( 'Comment_Page_ID' => $this->id ), + __METHOD__, + array( 'ORDER BY' => 'Comment_Date DESC', 'LIMIT' => 1 ) + ); + if ( $s !== false ) { + $latestCommentID = $s->CommentID; + } + return $latestCommentID; + } + + /** + * Set voting either totally off, or disallow "thumbs down" or disallow + * "thumbs up". + * + * @param string $voting 'OFF', 'PLUS' or 'MINUS' (will be strtoupper()ed) + */ + function setVoting( $voting ) { + $this->voting = $voting; + $voting = strtoupper( $voting ); + + if ( $voting == 'OFF' ) { + $this->allowMinus = false; + $this->allowPlus = false; + } + if ( $voting == 'PLUS' ) { + $this->allowMinus = false; + } + if ( $voting == 'MINUS' ) { + $this->allowPlus = false; + } + } + + /** + * Fetches all comments, called by display(). + * + * @return array Array containing every possible bit of information about + * a comment, including score, timestamp and more + */ + public function getComments() { + $dbr = wfGetDB( DB_SLAVE ); + + // Defaults (for non-social wikis) + $tables = array( + 'Comments', + 'vote1' => 'Comments_Vote', + 'vote2' => 'Comments_Vote', + ); + $fields = array( + 'Comment_Username', 'Comment_IP', 'Comment_Text', + 'Comment_Date', 'Comment_Date AS timestamp', + 'Comment_user_id', 'CommentID', 'Comment_Parent_ID', + 'vote1.Comment_Vote_Score AS current_vote', + 'SUM(vote2.Comment_Vote_Score) AS comment_score' + ); + $joinConds = array( + // For current user's vote + 'vote1' => array( + 'LEFT JOIN', + array( + 'vote1.Comment_Vote_ID = CommentID', + 'vote1.Comment_Vote_Username' => $this->getUser()->getName() + ) + ), + // For total vote count + 'vote2' => array( 'LEFT JOIN', 'vote2.Comment_Vote_ID = CommentID' ) + ); + $params = array( 'GROUP BY' => 'CommentID' ); + + // If SocialProfile is installed, query the user_stats table too. + if ( + class_exists( 'UserProfile' ) && + $dbr->tableExists( 'user_stats' ) + ) { + $tables[] = 'user_stats'; + $fields[] = 'stats_total_points'; + $joinConds['Comments'] = array( + 'LEFT JOIN', 'Comment_user_id = stats_user_id' + ); + } + + // Perform the query + $res = $dbr->select( + $tables, + $fields, + array( 'Comment_Page_ID' => $this->id ), + __METHOD__, + $params, + $joinConds + ); + + $comments = array(); + + foreach ( $res as $row ) { + if ( $row->Comment_Parent_ID == 0 ) { + $thread = $row->CommentID; + } else { + $thread = $row->Comment_Parent_ID; + } + $data = array( + 'Comment_Username' => $row->Comment_Username, + 'Comment_IP' => $row->Comment_IP, + 'Comment_Text' => $row->Comment_Text, + 'Comment_Date' => $row->Comment_Date, + 'Comment_user_id' => $row->Comment_user_id, + 'Comment_user_points' => ( isset( $row->stats_total_points ) ? number_format( $row->stats_total_points ) : 0 ), + 'CommentID' => $row->CommentID, + 'Comment_Parent_ID' => $row->Comment_Parent_ID, + 'thread' => $thread, + 'timestamp' => wfTimestamp( TS_UNIX, $row->timestamp ), + 'current_vote' => ( isset( $row->current_vote ) ? $row->current_vote : false ), + 'total_vote' => ( isset( $row->comment_score ) ? $row->comment_score : 0 ), + ); + + $comments[] = new Comment( $this, $this->getContext(), $data ); + } + + $commentThreads = array(); + + foreach ( $comments as $comment ) { + if ( $comment->parentID == 0 ) { + $commentThreads[$comment->id] = array( $comment ); + } else { + $commentThreads[$comment->parentID][] = $comment; + } + } + + return $commentThreads; + } + + /** + * @return int The page we are currently paged to + * not used for any API calls + */ + function getCurrentPagerPage() { + if ( $this->currentPagerPage == 0 ) { + $this->currentPagerPage = $this->getRequest()->getInt( $this->pageQuery, 1 ); + + if ( $this->currentPagerPage < 1 ) { + $this->currentPagerPage = 1; + } + } + + return $this->currentPagerPage; + } + + /** + * Display pager for the current page. + * + * @param int $pagerCurrent Page we are currently paged to + * @param int $pagesCount The maximum page number + * + * @return string: the links for paging through pages of comments + */ + function displayPager( $pagerCurrent, $pagesCount ) { + // Middle is used to "center" pages around the current page. + $pager_middle = ceil( $this->pagerLimit / 2 ); + // first is the first page listed by this pager piece (re quantity) + $pagerFirst = $pagerCurrent - $pager_middle + 1; + // last is the last page listed by this pager piece (re quantity) + $pagerLast = $pagerCurrent + $this->pagerLimit - $pager_middle; + + // Prepare for generation loop. + $i = $pagerFirst; + if ( $pagerLast > $pagesCount ) { + // Adjust "center" if at end of query. + $i = $i + ( $pagesCount - $pagerLast ); + $pagerLast = $pagesCount; + } + if ( $i <= 0 ) { + // Adjust "center" if at start of query. + $pagerLast = $pagerLast + ( 1 - $i ); + $i = 1; + } + + $output = ''; + if ( $pagesCount > 1 ) { + $output .= '
    '; + $pagerEllipsis = '
  • ...
  • '; + + // Whether to display the "Previous page" link + if ( $pagerCurrent > 1 ) { + $output .= '
  • ' . + Html::rawElement( + 'a', + array( + 'rel' => 'nofollow', + 'class' => 'c-pager-link', + 'href' => '#cfirst', + 'data-' . $this->pageQuery => ( $pagerCurrent - 1 ), + ), + '<' + ) . + '
  • '; + } + + // Whether to display the "First page" link + if ( $i > 1 ) { + $output .= '
  • ' . + Html::rawElement( + 'a', + array( + 'rel' => 'nofollow', + 'class' => 'c-pager-link', + 'href' => '#cfirst', + 'data-' . $this->pageQuery => 1, + ), + 1 + ) . + '
  • '; + } + + // When there is more than one page, create the pager list. + if ( $i != $pagesCount ) { + if ( $i > 2 ) { + $output .= $pagerEllipsis; + } + + // Now generate the actual pager piece. + for ( ; $i <= $pagerLast && $i <= $pagesCount; $i++ ) { + if ( $i == $pagerCurrent ) { + $output .= '
  • ' . + $i . '
  • '; + } else { + $output .= '
  • ' . + Html::rawElement( + 'a', + array( + 'rel' => 'nofollow', + 'class' => 'c-pager-link', + 'href' => '#cfirst', + 'data-' . $this->pageQuery => $i, + ), + $i + ) . + '
  • '; + } + } + + if ( $i < $pagesCount ) { + $output .= $pagerEllipsis; + } + } + + // Whether to display the "Last page" link + if ( $pagesCount > ( $i - 1 ) ) { + $output .= '
  • ' . + Html::rawElement( + 'a', + array( + 'rel' => 'nofollow', + 'class' => 'c-pager-link', + 'href' => '#cfirst', + 'data-' . $this->pageQuery => $pagesCount, + ), + $pagesCount + ) . + '
  • '; + } + + // Whether to display the "Next page" link + if ( $pagerCurrent < $pagesCount ) { + $output .= '
  • ' . + Html::rawElement( + 'a', + array( + 'rel' => 'nofollow', + 'class' => 'c-pager-link', + 'href' => '#cfirst', + 'data-' . $this->pageQuery => ( $pagerCurrent + 1 ), + ), + '>' + ) . + '
  • '; + } + + $output .= '
'; + } + + return $output; + } + + /** + * Get this list of anon commenters in the given list of comments, + * and return a mapped array of IP adressess to the the number anon poster + * (so anon posters can be called Anon#1, Anon#2, etc + * + * @return array + */ + function getAnonList() { + $counter = 1; + $bucket = array(); + + $commentThreads = $this->comments; + + $comments = array(); // convert 2nd threads array to a simple list of comments + foreach ( $commentThreads as $thread ) { + $comments = array_merge( $comments, $thread ); + } + usort( $comments, array( 'CommentFunctions', 'sortTime' ) ); + + foreach ( $comments as $comment ) { + if ( + !array_key_exists( $comment->username, $bucket ) && + $comment->userID == 0 + ) { + $bucket[$comment->username] = $counter; + $counter++; + } + } + + return $bucket; + } + + /** + * Sort an array of comment threads + * @param $threads + * @return mixed + */ + function sort( $threads ) { + global $wgCommentsSortDescending; + + if ( $this->orderBy ) { + usort( $threads, array( 'CommentFunctions', 'sortScore' ) ); + } elseif ( $wgCommentsSortDescending ) { + usort( $threads, array( 'CommentFunctions', 'sortDesc' ) ); + } else { + usort( $threads, array( 'CommentFunctions', 'sortAsc' ) ); + } + + return $threads; + } + + /** + * Convert an array of comment threads into an array of pages (arrays) of comment threads + * @param $comments + * @return array + */ + function page( $comments ) { + return array_chunk( $comments, $this->limit ); + } + + /** + * Display all the comments for the current page. + * CSS and JS is loaded in CommentsHooks.php + */ + function display() { + $output = ''; + + $commentThreads = $this->getComments(); + $commentThreads = $this->sort( $commentThreads ); + + $this->comments = $commentThreads; + + $commentPages = $this->page( $commentThreads ); + $currentPageNum = $this->getCurrentPagerPage(); + $numPages = count( $commentPages ); + // Suppress random E_NOTICE about "Undefined offset: 0", which seems to + // be breaking ProblemReports (at least on my local devbox, not sure + // about prod). --Jack Phoenix, 13 July 2015 + wfSuppressWarnings(); + $currentPage = $commentPages[$currentPageNum - 1]; + wfRestoreWarnings(); + + // Load complete blocked list for logged in user so they don't see their comments + $blockList = array(); + if ( $this->getUser()->getID() != 0 ) { + $blockList = CommentFunctions::getBlockList( $this->getUser()->getId() ); + } + + if ( $currentPage ) { + $pager = $this->displayPager( $currentPageNum, $numPages ); + $output .= $pager; + $output .= ''; + + $anonList = $this->getAnonList(); + + foreach ( $currentPage as $thread ) { + foreach ( $thread as $comment ) { + $output .= $comment->display( $blockList, $anonList ); + } + } + $output .= $pager; + } + + return $output; + } + + /** + * Displays the "Sort by X" form and a link to auto-refresh comments + * + * @return string HTML + */ + function displayOrderForm() { + $output = '
+
+
+ +
+
+ +
+
+
' . "\n"; + + return $output; + } + + /** + * Displays the form for adding new comments + * + * @return string HTML output + */ + function displayForm() { + $output = '
' . "\n"; + + if ( $this->allow ) { + $pos = strpos( + strtoupper( addslashes( $this->allow ) ), + strtoupper( addslashes( $this->getUser()->getName() ) ) + ); + } + + // 'comment' user right is required to add new comments + if ( !$this->getUser()->isAllowed( 'comment' ) ) { + $output .= wfMessage( 'comments-not-allowed' )->parse(); + } else { + // Blocked users can't add new comments under any conditions... + // and maybe there's a list of users who should be allowed to post + // comments + if ( $this->getUser()->isBlocked() == false && ( $this->allow == '' || $pos !== false ) ) { + $output .= '
' . wfMessage( 'comments-submit' )->plain() . '
' . "\n"; + $output .= '
' . "\n"; + // Show a message to anons, prompting them to register or log in + if ( !$this->getUser()->isLoggedIn() ) { + $login_title = SpecialPage::getTitleFor( 'Userlogin' ); + $register_title = SpecialPage::getTitleFor( 'Userlogin', 'signup' ); + $output .= '
' . wfMessage( + 'comments-anon-message', + htmlspecialchars( $register_title->getFullURL() ), + htmlspecialchars( $login_title->getFullURL() ) + )->text() . '
' . "\n"; + } + // ##START## 27.09.2017 von Bernhard Linz + if ( !$this->getUser()->isLoggedIn() ) { + $output .= '


' . "

"; + } else { + $output .= '

Benutzer:' . $this->getUser()->getName() . '

'; + } + // ##ENDE## 27.09.2017 von Bernhard Linz + $output .= '' . "\n"; + $output .= '
' . "\n"; + } + $output .= '' . "\n"; + $output .= '' . "\n"; + $output .= '' . "\n"; + $output .= '' . "\n"; + $output .= '' . "\n"; + $output .= '' . "\n"; + $output .= Html::hidden( 'token', $this->getUser()->getEditToken() ); + } + $output .= '
' . "\n"; + return $output; + } + + /** + * Purge caches (parser cache and Squid cache) + */ + function clearCommentListCache() { + wfDebug( "Clearing comments for page {$this->id} from cache\n" ); + + if ( is_object( $this->title ) ) { + $this->title->invalidateCache(); + $this->title->purgeSquid(); + } + } + +} diff --git a/includes/api/CommentBlock.api.php b/includes/api/CommentBlock.api.php index b362649..79ae250 100644 --- a/includes/api/CommentBlock.api.php +++ b/includes/api/CommentBlock.api.php @@ -1,52 +1,56 @@ -selectRow( - 'Comments', - array( 'comment_username', 'comment_user_id' ), - array( 'CommentID' => $this->getMain()->getVal( 'commentID' ) ), - __METHOD__ - ); - if ( $s !== false ) { - $userID = $s->comment_user_id; - $username = $s->comment_username; - } - - CommentFunctions::blockUser( $this->getUser(), $userID, $username ); - - if ( class_exists( 'UserStatsTrack' ) ) { - $stats = new UserStatsTrack( $userID, $username ); - $stats->incStatField( 'comment_ignored' ); - } - - $result = $this->getResult(); - $result->addValue( $this->getModuleName(), 'ok', 'ok' ); - return true; - } - - public function needsToken() { - return 'csrf'; - } - - public function isWriteMode() { - return true; - } - - public function getAllowedParams() { - return array( - 'commentID' => array( - ApiBase::PARAM_REQUIRED => true, - ApiBase::PARAM_TYPE => 'integer' - ) - ); - } -} +selectRow( + 'Comments', + array( 'comment_username', 'comment_user_id' ), + array( 'CommentID' => $this->getMain()->getVal( 'commentID' ) ), + __METHOD__ + ); + if ( $s !== false ) { + $userID = $s->comment_user_id; + $username = $s->comment_username; + } + + CommentFunctions::blockUser( $this->getUser(), $userID, $username ); + + if ( class_exists( 'UserStatsTrack' ) ) { + $stats = new UserStatsTrack( $userID, $username ); + $stats->incStatField( 'comment_ignored' ); + } + + $result = $this->getResult(); + $result->addValue( $this->getModuleName(), 'ok', 'ok' ); + return true; + } + + public function needsToken() { + return 'csrf'; + } + + public function isWriteMode() { + return true; + } + + public function getAllowedParams() { + return array( + 'commentID' => array( + ApiBase::PARAM_REQUIRED => true, + ApiBase::PARAM_TYPE => 'integer' + ), + 'UsernameKOK' => array( + ApiBase::PARAM_REQUIRED => false, + ApiBase::PARAM_TYPE => 'string' + ) + ); + } +} diff --git a/includes/api/CommentSubmit.api.php b/includes/api/CommentSubmit.api.php index 7746bc0..9383b96 100644 --- a/includes/api/CommentSubmit.api.php +++ b/includes/api/CommentSubmit.api.php @@ -1,73 +1,79 @@ -getUser(); - // Blocked users cannot submit new comments, and neither can those users - // without the necessary privileges. Also prevent obvious cross-site request - // forgeries (CSRF) - if ( - $user->isBlocked() || - !$user->isAllowed( 'comment' ) || - wfReadOnly() - ) { - return true; - } - - $commentText = $this->getMain()->getVal( 'commentText' ); - - if ( $commentText != '' ) { - // To protect against spam, it's necessary to check the supplied text - // against spam filters (but comment admins are allowed to bypass the - // spam filters) - if ( !$user->isAllowed( 'commentadmin' ) && CommentFunctions::isSpam( $commentText ) ) { - $this->dieUsage( wfMessage( 'comments-is-spam' )->plain(), 'comments-is-spam' ); - } - - // If the comment contains links but the user isn't allowed to post - // links, reject the submission - if ( !$user->isAllowed( 'commentlinks' ) && CommentFunctions::haveLinks( $commentText ) ) { - $this->dieUsage( wfMessage( 'comments-links-are-forbidden' )->plain(), 'comments-links-are-forbidden' ); - } - - $page = new CommentsPage( $this->getMain()->getVal( 'pageID' ), $this->getContext() ); - - Comment::add( $commentText, $page, $user, $this->getMain()->getVal( 'parentID' ) ); - - if ( class_exists( 'UserStatsTrack' ) ) { - $stats = new UserStatsTrack( $user->getID(), $user->getName() ); - $stats->incStatField( 'comment' ); - } - } - - $result = $this->getResult(); - $result->addValue( $this->getModuleName(), 'ok', 'ok' ); - return true; - } - - public function needsToken() { - return 'csrf'; - } - - public function isWriteMode() { - return true; - } - - public function getAllowedParams() { - return array( - 'pageID' => array( - ApiBase::PARAM_REQUIRED => true, - ApiBase::PARAM_TYPE => 'integer' - ), - 'parentID' => array( - ApiBase::PARAM_REQUIRED => false, - ApiBase::PARAM_TYPE => 'integer' - ), - 'commentText' => array( - ApiBase::PARAM_REQUIRED => true, - ApiBase::PARAM_TYPE => 'string' - ) - ); - } -} +getUser(); + // Blocked users cannot submit new comments, and neither can those users + // without the necessary privileges. Also prevent obvious cross-site request + // forgeries (CSRF) + if ( + $user->isBlocked() || + !$user->isAllowed( 'comment' ) || + wfReadOnly() + ) { + return true; + } + + $commentText = $this->getMain()->getVal( 'commentText' ); + + if ( $commentText != '' ) { + // To protect against spam, it's necessary to check the supplied text + // against spam filters (but comment admins are allowed to bypass the + // spam filters) + if ( !$user->isAllowed( 'commentadmin' ) && CommentFunctions::isSpam( $commentText ) ) { + $this->dieUsage( wfMessage( 'comments-is-spam' )->plain(), 'comments-is-spam' ); + } + + // If the comment contains links but the user isn't allowed to post + // links, reject the submission + if ( !$user->isAllowed( 'commentlinks' ) && CommentFunctions::haveLinks( $commentText ) ) { + $this->dieUsage( wfMessage( 'comments-links-are-forbidden' )->plain(), 'comments-links-are-forbidden' ); + } + + $page = new CommentsPage( $this->getMain()->getVal( 'pageID' ), $this->getContext() ); + + Comment::add( $commentText, $page, $user, $this->getMain()->getVal( 'parentID' ) ); + + if ( class_exists( 'UserStatsTrack' ) ) { + $stats = new UserStatsTrack( $user->getID(), $user->getName() ); + $stats->incStatField( 'comment' ); + } + } + + $kok_username = $this->getMain()->getVal( 'UsernameKOK' ); + + $result = $this->getResult(); + $result->addValue( $this->getModuleName(), 'ok', 'ok' ); + return true; + } + + public function needsToken() { + return 'csrf'; + } + + public function isWriteMode() { + return true; + } + + public function getAllowedParams() { + return array( + 'pageID' => array( + ApiBase::PARAM_REQUIRED => true, + ApiBase::PARAM_TYPE => 'integer' + ), + 'parentID' => array( + ApiBase::PARAM_REQUIRED => false, + ApiBase::PARAM_TYPE => 'integer' + ), + 'commentText' => array( + ApiBase::PARAM_REQUIRED => true, + ApiBase::PARAM_TYPE => 'string' + ), + 'UsernameKOK' => array( + ApiBase::PARAM_REQUIRED => false, + ApiBase::PARAM_TYPE => 'string' + ) + ); + } +} diff --git a/resources/js/Comment.js b/resources/js/Comment.js index 427c582..2b89a2e 100644 --- a/resources/js/Comment.js +++ b/resources/js/Comment.js @@ -1,347 +1,358 @@ -/** - * JavaScript for the Comments extension. - * Rewritten by Jack Phoenix to be more - * object-oriented. - * - * @file - * @date 6 December 2013 - */ -( function ( $, mw ) { -var Comment = { - submitted: 0, - isBusy: false, - timer: '', // has to have an initial value... - updateDelay: 7000, - LatestCommentID: '', - CurLatestCommentID: '', - pause: 0, - - /** - * When a comment's author is ignored, "Show Comment" link will be - * presented to the user. - * If the user clicks on it, this function is called to show the hidden - * comment. - */ - show: function( id ) { - $( '#ignore-' + id ).hide( 300 ); - $( '#comment-' + id ).show( 300 ); - }, - - /** - * This function is called whenever a user clicks on the "block" image to - * block another user's comments. - * - * @param username String: name of the user whose comments we want to block - * @param userID Integer: user ID number of the user whose comments we - * want to block (or 0 for anonymous users) - * @param commentID Integer: comment ID number - */ - blockUser: function( username, userID, commentID ) { - var message; - - // Display a different message depending on whether we're blocking an - // anonymous user or a registered one. - if ( !userID || userID === 0 ) { - message = mw.msg( 'comments-block-warning-anon' ); - } else { - message = mw.msg( 'comments-block-warning-user', username ); - } - - if ( window.confirm( message ) ) { - ( new mw.Api() ).postWithToken( 'csrf', { - action: 'commentblock', - commentID: commentID - } ).done( function( response ) { - if ( response.commentblock.ok ) { - $( 'a.comments-block-user[data-comments-user-id=' + userID + ']' ) - .parents( '.c-item' ).hide( 300 ) - .prev().show( 300 ); - } - } ); - } - }, - - /** - * This function is called whenever a user clicks on the "Delete Comment" - * link to delete a comment. - * - * @param commentID Integer: comment ID number - */ - deleteComment: function( commentID ) { - if ( window.confirm( mw.msg( 'comments-delete-warning' ) ) ) { - ( new mw.Api() ).postWithToken( 'csrf', { - action: 'commentdelete', - commentID: commentID - } ).done( function( response ) { - if ( response.commentdelete.ok ) { - $( '#comment-' + commentID ).hide( 2000 ); - } - } ); - } - }, - - /** - * Vote for a comment. - * - * @param commentID Integer: comment ID number - * @param voteValue Integer: vote value - */ - vote: function( commentID, voteValue ) { - ( new mw.Api() ).postWithToken( 'csrf', { - action: 'commentvote', - commentID: commentID, - voteValue: voteValue - } ).done( function( response ) { - $( '#comment-' + commentID + ' .c-score' ) - .html( response.commentvote.html ) // this will still be escaped - .html( $( '#comment-' + commentID + ' .c-score' ).text() ); // unescape - } ); - }, - - /** - * @param pageID Integer: page ID - * @param order Sorting order - * @param end Scroll to bottom after? - * @param cpage Integer: comment page number (used for pagination) - */ - viewComments: function( pageID, order, end, cpage ) { - document.commentForm.cpage.value = cpage; - document.getElementById( 'allcomments' ).innerHTML = mw.msg( 'comments-loading' ) + '

'; - - $.ajax( { - url: mw.config.get( 'wgScriptPath' ) + '/api.php', - data: { 'action': 'commentlist', 'format': 'json', 'pageID': pageID, 'order': order, 'pagerPage': cpage }, - cache: false - } ).done( function( response ) { - document.getElementById( 'allcomments' ).innerHTML = response.commentlist.html; - Comment.submitted = 0; - if ( end ) { - window.location.hash = 'end'; - } - } ); - }, - - /** - * Submit a new comment. - */ - submit: function() { - if ( Comment.submitted === 0 ) { - Comment.submitted = 1; - - var pageID = document.commentForm.pageId.value; - var parentID; - if ( !document.commentForm.commentParentId.value ) { - parentID = 0; - } else { - parentID = document.commentForm.commentParentId.value; - } - var commentText = document.commentForm.commentText.value; - - ( new mw.Api() ).postWithToken( 'csrf', { - action: 'commentsubmit', - pageID: pageID, - parentID: parentID, - commentText: commentText - } ).done( function( response ) { - if ( response.commentsubmit && response.commentsubmit.ok ) { - document.commentForm.commentText.value = ''; - var end = 1; - if ( mw.config.get( 'wgCommentsSortDescending' ) ) { - end = 0; - } - Comment.viewComments( document.commentForm.pageId.value, 0, end, document.commentForm.cpage.value ); - } else { - window.alert( response.error.info ); - Comment.submitted = 0; - } - } ); - - Comment.cancelReply(); - } - }, - - /** - * Toggle comment auto-refreshing on or off - * - * @param status - */ - toggleLiveComments: function( status ) { - if ( status ) { - Comment.pause = 0; - } else { - Comment.pause = 1; - } - var msg; - if ( status ) { - msg = mw.msg( 'comments-auto-refresher-pause' ); - } else { - msg = mw.msg( 'comments-auto-refresher-enable' ); - } - - $( 'body' ).on( 'click', 'div#spy a', function() { - Comment.toggleLiveComments( ( status ) ? 0 : 1 ); - } ); - $( 'div#spy a' ).css( 'font-size', '10px' ).text( msg ); - - if ( !Comment.pause ) { - Comment.LatestCommentID = document.commentForm.lastCommentId.value; - Comment.timer = setTimeout( - function() { Comment.checkUpdate(); }, - Comment.updateDelay - ); - } - }, - - checkUpdate: function() { - if ( Comment.isBusy ) { - return; - } - var pageID = document.commentForm.pageId.value; - - $.ajax( { - url: mw.config.get( 'wgScriptPath' ) + '/api.php', - data: { 'action': 'commentlatestid', 'format': 'json', 'pageID': pageID }, - cache: false - } ).done( function( response ) { - if ( response.commentlatestid.id ) { - // Get last new ID - Comment.CurLatestCommentID = response.commentlatestid.id; - if ( Comment.CurLatestCommentID !== Comment.LatestCommentID ) { - Comment.viewComments( document.commentForm.pageId.value, 0, 1, document.commentForm.cpage.value ); - Comment.LatestCommentID = Comment.CurLatestCommentID; - } - } - - Comment.isBusy = false; - if ( !Comment.pause ) { - clearTimeout( Comment.timer ); - Comment.timer = setTimeout( - function() { Comment.checkUpdate(); }, - Comment.updateDelay - ); - } - } ); - - Comment.isBusy = true; - return false; - }, - - /** - * Show the "reply to user X" form - * - * @param parentId Integer: parent comment (the one we're replying to) ID - * @param poster String: name of the person whom we're replying to - * @param posterGender String: gender of the person whom we're replying to - */ - reply: function( parentId, poster, posterGender ) { - $( '#replyto' ).text( - mw.msg( 'comments-reply-to', poster, posterGender ) + ' (' - ); - $( '', { - class: 'comments-cancel-reply-link', - style: 'cursor:pointer', - text: mw.msg( 'comments-cancel-reply' ) - } ).appendTo( '#replyto' ); - $( '#replyto' ).append( ')
' ); - - document.commentForm.commentParentId.value = parentId; - }, - - cancelReply: function() { - document.getElementById( 'replyto' ).innerHTML = ''; - document.commentForm.commentParentId.value = ''; - } -}; - -$( function() { - // Important note: these are all using $( 'body' ) as the selector - // instead of the class/ID/whatever so that they work after viewComments() - // has been called (i.e. so that "Delete comment", reply, etc. links - // continue working after you've submitted a comment yourself) - - // "Sort by X" feature - $( 'body' ).on( 'change', 'select[name="TheOrder"]', function() { - Comment.viewComments( - mw.config.get( 'wgArticleId' ), // or we could use $( 'input[name="pid"]' ).val(), too - $( this ).val(), - 0, - document.commentForm.cpage.value - ); - } ) - - // Comment auto-refresher - .on( 'click', 'div#spy a', function() { - Comment.toggleLiveComments( 1 ); - } ) - - // Voting links - .on( 'click', 'a#comment-vote-link', function() { - var that = $( this ); - Comment.vote( - that.data( 'comment-id' ), - that.data( 'vote-type' ) - ); - } ) - - // "Block this user" links - .on( 'click', 'a.comments-block-user', function() { - var that = $( this ); - Comment.blockUser( - that.data( 'comments-safe-username' ), - that.data( 'comments-user-id' ), - that.data( 'comments-comment-id' ) - ); - } ) - - // "Delete Comment" links - .on( 'click', 'a.comment-delete-link', function() { - Comment.deleteComment( $( this ).data( 'comment-id' ) ); - } ) - - // "Show this hidden comment" -- comments made by people on the user's - // personal block list - .on( 'click', 'div.c-ignored-links a', function() { - Comment.show( $( this ).data( 'comment-id' ) ); - } ) - - // Reply links - .on( 'click', 'a.comments-reply-to', function() { - Comment.reply( - $( this ).data( 'comment-id' ), - $( this ).data( 'comments-safe-username' ), - $( this ).data( 'comments-user-gender' ) - ); - } ) - - // "Reply to " links - .on( 'click', 'a.comments-cancel-reply-link', function() { - Comment.cancelReply(); - } ) - - // Handle clicks on the submit button (previously this was an onclick attr) - .on( 'click', 'div.c-form-button input[type="button"]', function() { - Comment.submit(); - } ) - - // Change page - .on( 'click', 'li.c-pager-item a.c-pager-link', function() { - var ord = 0, - commentsBody = $( this ).parents( 'div.comments-body:first' ); - - if ( commentsBody.length > 0 ) { - var ordCrtl = commentsBody.first().find( 'select[name="TheOrder"]:first' ); - if ( ordCrtl.length > 0 ) { - ord = ordCrtl.val(); - } - } - - Comment.viewComments( - mw.config.get( 'wgArticleId' ), // or we could use $( 'input[name="pid"]' ).val(), too - ord, - 0, - $( this ).data( 'cpage' ) - ); - } ); -} ); - -}( jQuery, mediaWiki ) ); +/** + * JavaScript for the Comments extension. + * Rewritten by Jack Phoenix to be more + * object-oriented. + * + * @file + * @date 6 December 2013 + */ +( function ( $, mw ) { +var Comment = { + submitted: 0, + isBusy: false, + timer: '', // has to have an initial value... + updateDelay: 7000, + LatestCommentID: '', + CurLatestCommentID: '', + pause: 0, + + /** + * When a comment's author is ignored, "Show Comment" link will be + * presented to the user. + * If the user clicks on it, this function is called to show the hidden + * comment. + */ + show: function( id ) { + $( '#ignore-' + id ).hide( 300 ); + $( '#comment-' + id ).show( 300 ); + }, + + /** + * This function is called whenever a user clicks on the "block" image to + * block another user's comments. + * + * @param username String: name of the user whose comments we want to block + * @param userID Integer: user ID number of the user whose comments we + * want to block (or 0 for anonymous users) + * @param commentID Integer: comment ID number + */ + blockUser: function( username, userID, commentID ) { + var message; + + // Display a different message depending on whether we're blocking an + // anonymous user or a registered one. + if ( !userID || userID === 0 ) { + message = mw.msg( 'comments-block-warning-anon' ); + } else { + message = mw.msg( 'comments-block-warning-user', username ); + } + + if ( window.confirm( message ) ) { + ( new mw.Api() ).postWithToken( 'csrf', { + action: 'commentblock', + commentID: commentID + } ).done( function( response ) { + if ( response.commentblock.ok ) { + $( 'a.comments-block-user[data-comments-user-id=' + userID + ']' ) + .parents( '.c-item' ).hide( 300 ) + .prev().show( 300 ); + } + } ); + } + }, + + /** + * This function is called whenever a user clicks on the "Delete Comment" + * link to delete a comment. + * + * @param commentID Integer: comment ID number + */ + deleteComment: function( commentID ) { + if ( window.confirm( mw.msg( 'comments-delete-warning' ) ) ) { + ( new mw.Api() ).postWithToken( 'csrf', { + action: 'commentdelete', + commentID: commentID + } ).done( function( response ) { + if ( response.commentdelete.ok ) { + $( '#comment-' + commentID ).hide( 2000 ); + } + } ); + } + }, + + /** + * Vote for a comment. + * + * @param commentID Integer: comment ID number + * @param voteValue Integer: vote value + */ + vote: function( commentID, voteValue ) { + ( new mw.Api() ).postWithToken( 'csrf', { + action: 'commentvote', + commentID: commentID, + voteValue: voteValue + } ).done( function( response ) { + $( '#comment-' + commentID + ' .c-score' ) + .html( response.commentvote.html ) // this will still be escaped + .html( $( '#comment-' + commentID + ' .c-score' ).text() ); // unescape + } ); + }, + + /** + * @param pageID Integer: page ID + * @param order Sorting order + * @param end Scroll to bottom after? + * @param cpage Integer: comment page number (used for pagination) + */ + viewComments: function( pageID, order, end, cpage ) { + document.commentForm.cpage.value = cpage; + document.getElementById( 'allcomments' ).innerHTML = mw.msg( 'comments-loading' ) + '

'; + + $.ajax( { + url: mw.config.get( 'wgScriptPath' ) + '/api.php', + data: { 'action': 'commentlist', 'format': 'json', 'pageID': pageID, 'order': order, 'pagerPage': cpage }, + cache: false + } ).done( function( response ) { + document.getElementById( 'allcomments' ).innerHTML = response.commentlist.html; + Comment.submitted = 0; + if ( end ) { + window.location.hash = 'end'; + } + } ); + }, + + /** + * Submit a new comment. + */ + submit: function() { + if ( Comment.submitted === 0 ) { + Comment.submitted = 1; + + var pageID = document.commentForm.pageId.value; + var parentID; + if ( !document.commentForm.commentParentId.value ) { + parentID = 0; + } else { + parentID = document.commentForm.commentParentId.value; + } + var commentText = document.commentForm.commentText.value; + /* ## START ## 27.09.2017 von Bernhard Linz: Prüfen ob txt_username einen Wert enthält. wenn nicht, ignorieren */ + var UsernameKOK; + if (document.getElementById('txt_username')) { + // UsernameKOK = document.commentform.txt_username.value; /* Wert aus txt_username in die Variable übergeben, welche später an Comments_AjaxFunctions.php übergeben wird */ + UsernameKOK = document.getElementById('txt_username').value; + } else { + UsernameKOK = "none"; /* Wenn Feld nicht existiert Variable auf "none" setzen */ + } + commentText = commentText + "#START#" + UsernameKOK + "#ENDE#"; + //window.alert( UsernameKOK ); + /* ## ENDE ## 27.09.2017 von Bernhard Linz */ + ( new mw.Api() ).postWithToken( 'csrf', { + action: 'commentsubmit', + pageID: pageID, + parentID: parentID, + commentText: commentText + //UsernameKOK: UsernameKOK + } ).done( function( response ) { + if ( response.commentsubmit && response.commentsubmit.ok ) { + document.commentForm.commentText.value = ''; + var end = 1; + if ( mw.config.get( 'wgCommentsSortDescending' ) ) { + end = 0; + } + Comment.viewComments( document.commentForm.pageId.value, 0, end, document.commentForm.cpage.value ); + } else { + window.alert( response.error.info ); + Comment.submitted = 0; + } + } ); + + Comment.cancelReply(); + } + }, + + /** + * Toggle comment auto-refreshing on or off + * + * @param status + */ + toggleLiveComments: function( status ) { + if ( status ) { + Comment.pause = 0; + } else { + Comment.pause = 1; + } + var msg; + if ( status ) { + msg = mw.msg( 'comments-auto-refresher-pause' ); + } else { + msg = mw.msg( 'comments-auto-refresher-enable' ); + } + + $( 'body' ).on( 'click', 'div#spy a', function() { + Comment.toggleLiveComments( ( status ) ? 0 : 1 ); + } ); + $( 'div#spy a' ).css( 'font-size', '10px' ).text( msg ); + + if ( !Comment.pause ) { + Comment.LatestCommentID = document.commentForm.lastCommentId.value; + Comment.timer = setTimeout( + function() { Comment.checkUpdate(); }, + Comment.updateDelay + ); + } + }, + + checkUpdate: function() { + if ( Comment.isBusy ) { + return; + } + var pageID = document.commentForm.pageId.value; + + $.ajax( { + url: mw.config.get( 'wgScriptPath' ) + '/api.php', + data: { 'action': 'commentlatestid', 'format': 'json', 'pageID': pageID }, + cache: false + } ).done( function( response ) { + if ( response.commentlatestid.id ) { + // Get last new ID + Comment.CurLatestCommentID = response.commentlatestid.id; + if ( Comment.CurLatestCommentID !== Comment.LatestCommentID ) { + Comment.viewComments( document.commentForm.pageId.value, 0, 1, document.commentForm.cpage.value ); + Comment.LatestCommentID = Comment.CurLatestCommentID; + } + } + + Comment.isBusy = false; + if ( !Comment.pause ) { + clearTimeout( Comment.timer ); + Comment.timer = setTimeout( + function() { Comment.checkUpdate(); }, + Comment.updateDelay + ); + } + } ); + + Comment.isBusy = true; + return false; + }, + + /** + * Show the "reply to user X" form + * + * @param parentId Integer: parent comment (the one we're replying to) ID + * @param poster String: name of the person whom we're replying to + * @param posterGender String: gender of the person whom we're replying to + */ + reply: function( parentId, poster, posterGender ) { + $( '#replyto' ).text( + mw.msg( 'comments-reply-to', poster, posterGender ) + ' (' + ); + $( '
', { + class: 'comments-cancel-reply-link', + style: 'cursor:pointer', + text: mw.msg( 'comments-cancel-reply' ) + } ).appendTo( '#replyto' ); + $( '#replyto' ).append( ')
' ); + + document.commentForm.commentParentId.value = parentId; + }, + + cancelReply: function() { + document.getElementById( 'replyto' ).innerHTML = ''; + document.commentForm.commentParentId.value = ''; + } +}; + +$( function() { + // Important note: these are all using $( 'body' ) as the selector + // instead of the class/ID/whatever so that they work after viewComments() + // has been called (i.e. so that "Delete comment", reply, etc. links + // continue working after you've submitted a comment yourself) + + // "Sort by X" feature + $( 'body' ).on( 'change', 'select[name="TheOrder"]', function() { + Comment.viewComments( + mw.config.get( 'wgArticleId' ), // or we could use $( 'input[name="pid"]' ).val(), too + $( this ).val(), + 0, + document.commentForm.cpage.value + ); + } ) + + // Comment auto-refresher + .on( 'click', 'div#spy a', function() { + Comment.toggleLiveComments( 1 ); + } ) + + // Voting links + .on( 'click', 'a#comment-vote-link', function() { + var that = $( this ); + Comment.vote( + that.data( 'comment-id' ), + that.data( 'vote-type' ) + ); + } ) + + // "Block this user" links + .on( 'click', 'a.comments-block-user', function() { + var that = $( this ); + Comment.blockUser( + that.data( 'comments-safe-username' ), + that.data( 'comments-user-id' ), + that.data( 'comments-comment-id' ) + ); + } ) + + // "Delete Comment" links + .on( 'click', 'a.comment-delete-link', function() { + Comment.deleteComment( $( this ).data( 'comment-id' ) ); + } ) + + // "Show this hidden comment" -- comments made by people on the user's + // personal block list + .on( 'click', 'div.c-ignored-links a', function() { + Comment.show( $( this ).data( 'comment-id' ) ); + } ) + + // Reply links + .on( 'click', 'a.comments-reply-to', function() { + Comment.reply( + $( this ).data( 'comment-id' ), + $( this ).data( 'comments-safe-username' ), + $( this ).data( 'comments-user-gender' ) + ); + } ) + + // "Reply to " links + .on( 'click', 'a.comments-cancel-reply-link', function() { + Comment.cancelReply(); + } ) + + // Handle clicks on the submit button (previously this was an onclick attr) + .on( 'click', 'div.c-form-button input[type="button"]', function() { + Comment.submit(); + } ) + + // Change page + .on( 'click', 'li.c-pager-item a.c-pager-link', function() { + var ord = 0, + commentsBody = $( this ).parents( 'div.comments-body:first' ); + + if ( commentsBody.length > 0 ) { + var ordCrtl = commentsBody.first().find( 'select[name="TheOrder"]:first' ); + if ( ordCrtl.length > 0 ) { + ord = ordCrtl.val(); + } + } + + Comment.viewComments( + mw.config.get( 'wgArticleId' ), // or we could use $( 'input[name="pid"]' ).val(), too + ord, + 0, + $( this ).data( 'cpage' ) + ); + } ); +} ); + +}( jQuery, mediaWiki ) );