Example #1
0
	/**
	 * Insert a new empty page record for this article.
	 * This *must* be followed up by creating a revision
	 * and running $this->updateRevisionOn( ... );
	 * or else the record will be left in a funky state.
	 * Best if all done inside a transaction.
	 *
	 * @param $dbw DatabaseBase
	 * @return int The newly created page_id key, or false if the title already existed
	 */
	public function insertOn( $dbw ) {
		wfProfileIn( __METHOD__ );

		$page_id = $dbw->nextSequenceValue( 'page_page_id_seq' );
		$dbw->insert( 'page', array(
			'page_id'           => $page_id,
			'page_namespace'    => $this->mTitle->getNamespace(),
			'page_title'        => $this->mTitle->getDBkey(),
			'page_counter'      => 0,
			'page_restrictions' => '',
			'page_is_redirect'  => 0, // Will set this shortly...
			'page_is_new'       => 1,
			'page_random'       => wfRandom(),
			'page_touched'      => $dbw->timestamp(),
			'page_latest'       => 0, // Fill this in shortly...
			'page_len'          => 0, // Fill this in shortly...
		), __METHOD__, 'IGNORE' );

		$affected = $dbw->affectedRows();

		if ( $affected ) {
			$newid = $dbw->insertId();
			$this->mId = $newid;
			$this->mTitle->resetArticleID( $newid );
		}
		wfProfileOut( __METHOD__ );

		return $affected ? $newid : false;
	}
Example #2
0
 /**
  *
  * @return Title
  */
 public function &getTitle()
 {
     if ($this->mTitle === false) {
         $this->mTitle = Title::makeTitle($this->mAttribs['rc_namespace'], $this->mAttribs['rc_title']);
         # Make sure the correct page ID is process cached
         $this->mTitle->resetArticleID($this->mAttribs['rc_cur_id']);
     }
     return $this->mTitle;
 }
Example #3
0
 /**
  * Insert a new empty page record for this article.
  * This *must* be followed up by creating a revision
  * and running $this->updateRevisionOn( ... );
  * or else the record will be left in a funky state.
  * Best if all done inside a transaction.
  *
  * @param IDatabase $dbw
  * @return int|bool The newly created page_id key; false if the title already existed
  */
 public function insertOn($dbw)
 {
     $dbw->insert('page', array('page_id' => $dbw->nextSequenceValue('page_page_id_seq'), 'page_namespace' => $this->mTitle->getNamespace(), 'page_title' => $this->mTitle->getDBkey(), 'page_restrictions' => '', 'page_is_redirect' => 0, 'page_is_new' => 1, 'page_random' => wfRandom(), 'page_touched' => $dbw->timestamp(), 'page_latest' => 0, 'page_len' => 0), __METHOD__, 'IGNORE');
     if ($dbw->affectedRows() > 0) {
         $newid = $dbw->insertId();
         $this->mId = $newid;
         $this->mTitle->resetArticleID($newid);
         return $newid;
     } else {
         return false;
         // nothing changed
     }
 }
Example #4
0
 /**
  * Do some database updates after deletion
  *
  * @param $id Int: page_id value of the page being deleted (B/C, currently unused)
  * @param $content Content: optional page content to be used when determining the required updates.
  *        This may be needed because $this->getContent() may already return null when the page proper was deleted.
  */
 public function doDeleteUpdates($id, Content $content = null)
 {
     # update site status
     DeferredUpdates::addUpdate(new SiteStatsUpdate(0, 1, -(int) $this->isCountable(), -1));
     # remove secondary indexes, etc
     $updates = $this->getDeletionUpdates($content);
     DataUpdate::runUpdates($updates);
     # Clear caches
     WikiPage::onArticleDelete($this->mTitle);
     # Reset this object
     $this->clear();
     # Clear the cached article id so the interface doesn't act like we exist
     $this->mTitle->resetArticleID(0);
 }
Example #5
0
 /**
  *
  * @return Title
  */
 public function &getTitle()
 {
     if ($this->mTitle === false) {
         $this->mTitle = Title::makeTitle($this->mAttribs['rc_namespace'], $this->mAttribs['rc_title']);
         /* Wikia change begin - @author: garth */
         # Don't reset here if the FastLinkCache is enabled.  Calling
         # resetArticleID clears this memcached key when its likely we
         # just set it earlier in this request.  BugID 42735
         global $wgEnableFastLinkCache;
         if (empty($wgEnableFastLinkCache)) {
             # Make sure the correct page ID is process cached
             $this->mTitle->resetArticleID($this->mAttribs['rc_cur_id']);
         }
         /* Wikia change - end */
     }
     return $this->mTitle;
 }
Example #6
0
 /**
  * Do some database updates after deletion
  *
  * @param $id Int: page_id value of the page being deleted
  */
 public function doDeleteUpdates($id)
 {
     DeferredUpdates::addUpdate(new SiteStatsUpdate(0, 1, -(int) $this->isCountable(), -1));
     $dbw = wfGetDB(DB_MASTER);
     # Delete restrictions for it
     $dbw->delete('page_restrictions', array('pr_page' => $id), __METHOD__);
     # Fix category table counts
     $cats = array();
     $res = $dbw->select('categorylinks', 'cl_to', array('cl_from' => $id), __METHOD__);
     foreach ($res as $row) {
         $cats[] = $row->cl_to;
     }
     $this->updateCategoryCounts(array(), $cats);
     # If using cascading deletes, we can skip some explicit deletes
     if (!$dbw->cascadingDeletes()) {
         $dbw->delete('revision', array('rev_page' => $id), __METHOD__);
         # Delete outgoing links
         $dbw->delete('pagelinks', array('pl_from' => $id), __METHOD__);
         $dbw->delete('imagelinks', array('il_from' => $id), __METHOD__);
         $dbw->delete('categorylinks', array('cl_from' => $id), __METHOD__);
         $dbw->delete('templatelinks', array('tl_from' => $id), __METHOD__);
         $dbw->delete('externallinks', array('el_from' => $id), __METHOD__);
         $dbw->delete('langlinks', array('ll_from' => $id), __METHOD__);
         $dbw->delete('iwlinks', array('iwl_from' => $id), __METHOD__);
         $dbw->delete('redirect', array('rd_from' => $id), __METHOD__);
         $dbw->delete('page_props', array('pp_page' => $id), __METHOD__);
     }
     # If using cleanup triggers, we can skip some manual deletes
     if (!$dbw->cleanupTriggers()) {
         # Clean up recentchanges entries...
         $dbw->delete('recentchanges', array('rc_type != ' . RC_LOG, 'rc_namespace' => $this->mTitle->getNamespace(), 'rc_title' => $this->mTitle->getDBkey()), __METHOD__);
         $dbw->delete('recentchanges', array('rc_type != ' . RC_LOG, 'rc_cur_id' => $id), __METHOD__);
     }
     # Clear caches
     self::onArticleDelete($this->mTitle);
     # Clear the cached article id so the interface doesn't act like we exist
     $this->mTitle->resetArticleID(0);
 }
Example #7
0
 /**
  * Back-end article deletion
  * Deletes the article with database consistency, writes logs, purges caches
  *
  * @param $reason string delete reason for deletion log
  * @param suppress bitfield
  * 	Revision::DELETED_TEXT
  * 	Revision::DELETED_COMMENT
  * 	Revision::DELETED_USER
  * 	Revision::DELETED_RESTRICTED
  * @param $id int article ID
  * @param $commit boolean defaults to true, triggers transaction end
  * @param &$errors Array of errors to append to
  * @param $user User The relevant user
  * @return boolean true if successful
  */
 public function doDeleteArticle($reason, $suppress = false, $id = 0, $commit = true, &$error = '', User $user = null)
 {
     global $wgDeferredUpdateList, $wgUseTrackbacks, $wgUser;
     $user = is_null($user) ? $wgUser : $user;
     wfDebug(__METHOD__ . "\n");
     if (!wfRunHooks('ArticleDelete', array(&$this, &$user, &$reason, &$error))) {
         return false;
     }
     $dbw = wfGetDB(DB_MASTER);
     $t = $this->mTitle->getDBkey();
     $id = $id ? $id : $this->mTitle->getArticleID(Title::GAID_FOR_UPDATE);
     if ($t === '' || $id == 0) {
         return false;
     }
     $u = new SiteStatsUpdate(0, 1, -(int) $this->isCountable(), -1);
     array_push($wgDeferredUpdateList, $u);
     // Bitfields to further suppress the content
     if ($suppress) {
         $bitfield = 0;
         // This should be 15...
         $bitfield |= Revision::DELETED_TEXT;
         $bitfield |= Revision::DELETED_COMMENT;
         $bitfield |= Revision::DELETED_USER;
         $bitfield |= Revision::DELETED_RESTRICTED;
     } else {
         $bitfield = 'rev_deleted';
     }
     $dbw->begin();
     // For now, shunt the revision data into the archive table.
     // Text is *not* removed from the text table; bulk storage
     // is left intact to avoid breaking block-compression or
     // immutable storage schemes.
     //
     // For backwards compatibility, note that some older archive
     // table entries will have ar_text and ar_flags fields still.
     //
     // In the future, we may keep revisions and mark them with
     // the rev_deleted field, which is reserved for this purpose.
     $dbw->insertSelect('archive', array('page', 'revision'), array('ar_namespace' => 'page_namespace', 'ar_title' => 'page_title', 'ar_comment' => 'rev_comment', 'ar_user' => 'rev_user', 'ar_user_text' => 'rev_user_text', 'ar_timestamp' => 'rev_timestamp', 'ar_minor_edit' => 'rev_minor_edit', 'ar_rev_id' => 'rev_id', 'ar_text_id' => 'rev_text_id', 'ar_text' => '\'\'', 'ar_flags' => '\'\'', 'ar_len' => 'rev_len', 'ar_page_id' => 'page_id', 'ar_deleted' => $bitfield), array('page_id' => $id, 'page_id = rev_page'), __METHOD__);
     # Delete restrictions for it
     $dbw->delete('page_restrictions', array('pr_page' => $id), __METHOD__);
     # Now that it's safely backed up, delete it
     $dbw->delete('page', array('page_id' => $id), __METHOD__);
     $ok = $dbw->affectedRows() > 0;
     // getArticleId() uses slave, could be laggy
     if (!$ok) {
         $dbw->rollback();
         return false;
     }
     # Fix category table counts
     $cats = array();
     $res = $dbw->select('categorylinks', 'cl_to', array('cl_from' => $id), __METHOD__);
     foreach ($res as $row) {
         $cats[] = $row->cl_to;
     }
     $this->updateCategoryCounts(array(), $cats);
     # If using cascading deletes, we can skip some explicit deletes
     if (!$dbw->cascadingDeletes()) {
         $dbw->delete('revision', array('rev_page' => $id), __METHOD__);
         if ($wgUseTrackbacks) {
             $dbw->delete('trackbacks', array('tb_page' => $id), __METHOD__);
         }
         # Delete outgoing links
         $dbw->delete('pagelinks', array('pl_from' => $id));
         $dbw->delete('imagelinks', array('il_from' => $id));
         $dbw->delete('categorylinks', array('cl_from' => $id));
         $dbw->delete('templatelinks', array('tl_from' => $id));
         $dbw->delete('externallinks', array('el_from' => $id));
         $dbw->delete('langlinks', array('ll_from' => $id));
         $dbw->delete('iwlinks', array('iwl_from' => $id));
         $dbw->delete('redirect', array('rd_from' => $id));
     }
     # If using cleanup triggers, we can skip some manual deletes
     if (!$dbw->cleanupTriggers()) {
         # Clean up recentchanges entries...
         $dbw->delete('recentchanges', array('rc_type != ' . RC_LOG, 'rc_namespace' => $this->mTitle->getNamespace(), 'rc_title' => $this->mTitle->getDBkey()), __METHOD__);
         $dbw->delete('recentchanges', array('rc_type != ' . RC_LOG, 'rc_cur_id' => $id), __METHOD__);
     }
     # Clear caches
     self::onArticleDelete($this->mTitle);
     # Clear the cached article id so the interface doesn't act like we exist
     $this->mTitle->resetArticleID(0);
     # Log the deletion, if the page was suppressed, log it at Oversight instead
     $logtype = $suppress ? 'suppress' : 'delete';
     $log = new LogPage($logtype);
     # Make sure logging got through
     $log->addEntry('delete', $this->mTitle, $reason, array());
     if ($commit) {
         $dbw->commit();
     }
     wfRunHooks('ArticleDeleteComplete', array(&$this, &$user, $reason, $id));
     return true;
 }
Example #8
0
 /**
  * Move page to a title which is either a redirect to the
  * source page or nonexistent
  *
  * @fixme This was basically directly moved from Title, it should be split into smaller functions
  * @param User $user the User doing the move
  * @param Title $nt The page to move to, which should be a redirect or nonexistent
  * @param string $reason The reason for the move
  * @param bool $createRedirect Whether to leave a redirect at the old title. Does not check
  *   if the user has the suppressredirect right
  * @throws MWException
  */
 private function moveToInternal(User $user, &$nt, $reason = '', $createRedirect = true)
 {
     global $wgContLang;
     if ($nt->exists()) {
         $moveOverRedirect = true;
         $logType = 'move_redir';
     } else {
         $moveOverRedirect = false;
         $logType = 'move';
     }
     if ($createRedirect) {
         if ($this->oldTitle->getNamespace() == NS_CATEGORY && !wfMessage('category-move-redirect-override')->inContentLanguage()->isDisabled()) {
             $redirectContent = new WikitextContent(wfMessage('category-move-redirect-override')->params($nt->getPrefixedText())->inContentLanguage()->plain());
         } else {
             $contentHandler = ContentHandler::getForTitle($this->oldTitle);
             $redirectContent = $contentHandler->makeRedirectContent($nt, wfMessage('move-redirect-text')->inContentLanguage()->plain());
         }
         // NOTE: If this page's content model does not support redirects, $redirectContent will be null.
     } else {
         $redirectContent = null;
     }
     // Figure out whether the content model is no longer the default
     $oldDefault = ContentHandler::getDefaultModelFor($this->oldTitle);
     $contentModel = $this->oldTitle->getContentModel();
     $newDefault = ContentHandler::getDefaultModelFor($nt);
     $defaultContentModelChanging = $oldDefault !== $newDefault && $oldDefault === $contentModel;
     // bug 57084: log_page should be the ID of the *moved* page
     $oldid = $this->oldTitle->getArticleID();
     $logTitle = clone $this->oldTitle;
     $logEntry = new ManualLogEntry('move', $logType);
     $logEntry->setPerformer($user);
     $logEntry->setTarget($logTitle);
     $logEntry->setComment($reason);
     $logEntry->setParameters(array('4::target' => $nt->getPrefixedText(), '5::noredir' => $redirectContent ? '0' : '1'));
     $formatter = LogFormatter::newFromEntry($logEntry);
     $formatter->setContext(RequestContext::newExtraneousContext($this->oldTitle));
     $comment = $formatter->getPlainActionText();
     if ($reason) {
         $comment .= wfMessage('colon-separator')->inContentLanguage()->text() . $reason;
     }
     # Truncate for whole multibyte characters.
     $comment = $wgContLang->truncate($comment, 255);
     $dbw = wfGetDB(DB_MASTER);
     $oldpage = WikiPage::factory($this->oldTitle);
     $oldcountable = $oldpage->isCountable();
     $newpage = WikiPage::factory($nt);
     if ($moveOverRedirect) {
         $newid = $nt->getArticleID();
         $newcontent = $newpage->getContent();
         # Delete the old redirect. We don't save it to history since
         # by definition if we've got here it's rather uninteresting.
         # We have to remove it so that the next step doesn't trigger
         # a conflict on the unique namespace+title index...
         $dbw->delete('page', array('page_id' => $newid), __METHOD__);
         $newpage->doDeleteUpdates($newid, $newcontent);
     }
     # Save a null revision in the page's history notifying of the move
     $nullRevision = Revision::newNullRevision($dbw, $oldid, $comment, true, $user);
     if (!is_object($nullRevision)) {
         throw new MWException('No valid null revision produced in ' . __METHOD__);
     }
     $nullRevision->insertOn($dbw);
     # Change the name of the target page:
     $dbw->update('page', array('page_namespace' => $nt->getNamespace(), 'page_title' => $nt->getDBkey()), array('page_id' => $oldid), __METHOD__);
     // clean up the old title before reset article id - bug 45348
     if (!$redirectContent) {
         WikiPage::onArticleDelete($this->oldTitle);
     }
     $this->oldTitle->resetArticleID(0);
     // 0 == non existing
     $nt->resetArticleID($oldid);
     $newpage->loadPageData(WikiPage::READ_LOCKING);
     // bug 46397
     $newpage->updateRevisionOn($dbw, $nullRevision);
     Hooks::run('NewRevisionFromEditComplete', array($newpage, $nullRevision, $nullRevision->getParentId(), $user));
     $newpage->doEditUpdates($nullRevision, $user, array('changed' => false, 'moved' => true, 'oldcountable' => $oldcountable));
     // If the default content model changes, we need to populate rev_content_model
     if ($defaultContentModelChanging) {
         $dbw->update('revision', array('rev_content_model' => $contentModel), array('rev_page' => $nt->getArticleID(), 'rev_content_model IS NULL'), __METHOD__);
     }
     if (!$moveOverRedirect) {
         WikiPage::onArticleCreate($nt);
     }
     # Recreate the redirect, this time in the other direction.
     if ($redirectContent) {
         $redirectArticle = WikiPage::factory($this->oldTitle);
         $redirectArticle->loadFromRow(false, WikiPage::READ_LOCKING);
         // bug 46397
         $newid = $redirectArticle->insertOn($dbw);
         if ($newid) {
             // sanity
             $this->oldTitle->resetArticleID($newid);
             $redirectRevision = new Revision(array('title' => $this->oldTitle, 'page' => $newid, 'user_text' => $user->getName(), 'user' => $user->getId(), 'comment' => $comment, 'content' => $redirectContent));
             $redirectRevision->insertOn($dbw);
             $redirectArticle->updateRevisionOn($dbw, $redirectRevision, 0);
             Hooks::run('NewRevisionFromEditComplete', array($redirectArticle, $redirectRevision, false, $user));
             $redirectArticle->doEditUpdates($redirectRevision, $user, array('created' => true));
         }
     }
     # Log the move
     $logid = $logEntry->insert();
     $logEntry->publish($logid);
 }
Example #9
0
 /**
  * Propagate an article move
  * Sets xml property and calls the abstract function propagateMoveData($newTitle)
  * @param Title $newTitle title article has been moved to
  * @return bool true if propagate succeeded
  */
 public function propagateMove($newTitle)
 {
     global $wgUser, $wrBotUserID;
     $result = true;
     // we do propagate bot edits
     //	   if ($wgUser->getID() != $wrBotUserID) {
     // remove the title from the link cache and re-created it so it has the right page id
     //$linkCache =& LinkCache::singleton();
     //$linkCache->clearBadLink($newTitle->getPrefixedDBkey());
     //$newTitle = Title::makeTitle($newTitle->getNamespace(), $newTitle->getDBkey());
     $newTitle->resetArticleID(0);
     // clears link cache
     $newTitle->getArticleID(GAID_FOR_UPDATE);
     // make sure you read the master db for the pageid
     $newTitleString = $newTitle->getText();
     $newNs = $newTitle->getNamespace();
     $revision = StructuredData::getRevision($newTitle, false, true);
     if (!$revision) {
         error_log("Revision being moved not found!\n");
         return true;
     }
     $text =& $revision->getText();
     $this->xml = StructuredData::getXml($this->tagName, $text);
     $textChanged = false;
     $result = $this->propagateMoveDeleteUndelete($newTitleString, $newNs, $text, $textChanged);
     if ($result && $textChanged) {
         // should change only if moving namespaces (which is currently only allowed for source -> repo)
         $article = new Article($newTitle, 0);
         PropagationManager::enablePropagation(false);
         $result = $article->doEdit($text, self::PROPAGATE_MOVE_MESSAGE, PROPAGATE_EDIT_FLAGS);
         PropagationManager::enablePropagation(true);
     }
     if (!$result) {
         error_log("ERROR propagateMove failed for {$this->title->getPrefixedText()} -> {$newTitle->getPrefixedText()}\n");
     }
     //	   }
     return true;
 }