/** * @group Slow * @slowExecutionTime 0.01076 ms * The purpose of CommentsIndex cache is avoid database queries for CommentsIndex instances that were created * during the request. So here we simulate inserting the CommentsIndex to the table and then ask for that id and * make sure it's not fetched from the database */ public function testCommentsIndexCacheIsUsedForNewObjects() { $rowMock = $this->getFakeCommentsIndexRow(2); $dbMock = $this->getMock('stdClass', ['selectRow', 'replace', 'tableExists', 'timestamp']); $dbMock->expects($this->exactly(0))->method('selectRow')->will($this->returnValue($rowMock)); $dbMock->expects($this->any())->method('replace')->will($this->returnValue(true)); $dbMock->expects($this->any())->method('timestamp')->will($this->returnValue('20130102030405')); $dbMock->expects($this->any())->method('tableExists')->will($this->returnValue(true)); $ci = new CommentsIndex(['commentId' => 2, 'parentPageId' => 3, 'parentCommentId' => 4], $dbMock); $ci->addToDatabase(); //we pass the same $db connection so it's easier to compare objects $ci2 = CommentsIndex::newFromId(2, 0, $dbMock); // make sure the cached object has the same properties $this->assertEquals($ci, $ci2); //make sure we don't inherit the database connection form the original object $ci2 = CommentsIndex::newFromId(3); $this->assertNotEquals($ci, $ci2); }
/** * doPost -- static hook/entry for normal request post * * @static * @access public * * @param $text * @param User $user -- instance of User who is leaving the comment * @param Title $title -- instance of Title * * @param bool $parentId * @param array $metadata * * @return Article -- newly created article * @throws MWException */ public static function doPost($text, $user, $title, $parentId = false, $metadata = array()) { global $wgTitle; wfProfileIn(__METHOD__); if (!$text || !strlen($text)) { wfProfileOut(__METHOD__); return false; } if (wfReadOnly()) { wfProfileOut(__METHOD__); return false; } /** * title for comment is combination of article title and some 'random' data */ if ($parentId == false) { // 1st level comment $commentTitle = sprintf('%s/%s%s-%s', $title->getText(), ARTICLECOMMENT_PREFIX, $user->getName(), wfTimestampNow()); } else { $parentArticle = Article::newFromID($parentId); if (empty($parentArticle)) { $parentTitle = Title::newFromID($parentId, Title::GAID_FOR_UPDATE); // it's possible for Title to be empty at this point // if article was removed in the meantime // (for eg. when replying on Wall from old browser session // to non-existing thread) // it's fine NOT to create Article in that case if (!empty($parentTitle)) { $parentArticle = new Article($parentTitle); } // if $parentTitle is empty the logging below will be executed } // FB#2875 (log data for further debugging) if (is_null($parentArticle)) { $debugTitle = !empty($title) ? $title->getText() : '--EMPTY--'; // BugId:2646 Wikia::log(__FUNCTION__, __LINE__, "Failed to create Article object, ID={$parentId}, title={$debugTitle}, user={$user->getName()}", true); wfProfileOut(__METHOD__); return false; } $parentTitle = $parentArticle->getTitle(); // nested comment $commentTitle = sprintf('%s/%s%s-%s', $parentTitle->getText(), ARTICLECOMMENT_PREFIX, $user->getName(), wfTimestampNow()); } $commentTitleText = $commentTitle; $commentTitle = Title::newFromText($commentTitle, MWNamespace::getTalk($title->getNamespace())); /** * because we save different tile via Ajax request TODO: fix it !! */ $wgTitle = $commentTitle; if (!$commentTitle instanceof Title) { if (!empty($parentId)) { Wikia::log(__METHOD__, false, "ArticleComment::doPost (reply to " . $parentId . ") - failed to create commentTitle from " . $commentTitleText, true); } wfProfileOut(__METHOD__); return false; } /** * add article using EditPage class (for hooks) */ $article = new Article($commentTitle, 0); CommentsIndex::addCommentInfo($commentTitleText, $title, $parentId); $retval = self::doSaveAsArticle($text, $article, $user, $metadata); if ($retval->value == EditPage::AS_SUCCESS_NEW_ARTICLE) { $commentsIndex = CommentsIndex::newFromId($article->getID()); if (empty($commentsIndex)) { Wikia::log(__METHOD__, false, "ERROR ArticleComment::doPost (reply to " . $parentId . ") - empty commentsIndex for " . $commentTitleText, true); } else { wfRunHooks('EditCommentsIndex', [$article->getTitle(), $commentsIndex]); } } $res = ArticleComment::doAfterPost($retval, $article, $parentId); ArticleComment::doPurge($title, $commentTitle); wfProfileOut(__METHOD__); return [$retval, $article, $res]; }
/** * purge memc and vernish cache for pages releated to this thread * * in case of edit this hook is run two time before (WallBeforeEdit) edit and after edit (WallAction) * */ public static function onWallAction($action, $parent, $comment_id) { $title = Title::newFromId($comment_id, Title::GAID_FOR_UPDATE); if (!empty($title) && MWNamespace::getSubject($title->getNamespace()) == NS_WIKIA_FORUM_BOARD) { $threadId = empty($parent) ? $comment_id : $parent; RelatedForumDiscussionController::purgeCache($threadId); //cleare board info $commentsIndex = CommentsIndex::newFromId($comment_id); if (empty($commentsIndex)) { return true; } $board = ForumBoard::newFromId($commentsIndex->getParentPageId()); if (empty($board)) { return true; } $thread = WallThread::newFromId($threadId); if (!empty($thread)) { $thread->purgeLastMessage(); } } return true; }
/** * Hook into MW transaction that creates new article comments and execute queries that create comments_index entries * @param $dbw database connetion * @param Title $title newly created article * @param Revision $revision revision containig the lastest version of article comment * @param $flags Integer bitfield, the same as in WikiPage::doEdit method */ public static function onArticleDoEdit($dbw, Title $title, Revision $revision, $flags) { global $wgEnableWallEngine; if (!empty($wgEnableWallEngine) && WallHelper::isWallNamespace($title->getNamespace())) { if ($flags & EDIT_NEW) { $titleText = $title->getText(); if (isset(self::$commentInfoData[$titleText])) { $data = array('namespace' => self::$commentInfoData[$titleText]->userPageTitle->getNamespace(), 'parentPageId' => self::$commentInfoData[$titleText]->userPageTitle->getArticleID(), 'commentId' => $title->getArticleID(), 'parentCommentId' => intval(self::$commentInfoData[$titleText]->parentId), 'firstRevId' => $revision->getId(), 'lastRevId' => $revision->getId()); $commentsIndex = new CommentsIndex($data, $dbw); $commentsIndex->addToDatabase(); $commentsIndex->updateParentLastCommentId($data['commentId']); } } else { $commentsIndex = CommentsIndex::newFromId($title->getArticleID(), 0, $dbw); if ($commentsIndex instanceof CommentsIndex) { $commentsIndex->updateLastRevId($revision->getId()); } } } return true; }
public function getCommentsIndex() { if (false === $this->commentsIndex) { // false means we didn't call newFromId yet $this->commentsIndex = CommentsIndex::newFromId($this->getId()); // note: can return null } return $this->commentsIndex; }