Merge "Expand SessionManager / AuthManager documentation"
[lhc/web/wiklou.git] / includes / page / WikiPage.php
index 033eb67..e1d9f99 100644 (file)
@@ -504,13 +504,13 @@ class WikiPage implements Page, IDBAccessObject {
 
        /**
         * Loads page_touched and returns a value indicating if it should be used
-        * @return bool True if not a redirect
+        * @return bool True if this page exists and is not a redirect
         */
        public function checkTouched() {
                if ( !$this->mDataLoaded ) {
                        $this->loadPageData();
                }
-               return !$this->mIsRedirect;
+               return ( $this->mId && !$this->mIsRedirect );
        }
 
        /**
@@ -2873,13 +2873,24 @@ class WikiPage implements Page, IDBAccessObject {
                        return $status;
                }
 
+               // Given the lock above, we can be confident in the title and page ID values
+               $namespace = $this->getTitle()->getNamespace();
+               $dbKey = $this->getTitle()->getDBkey();
+
                // At this point we are now comitted to returning an OK
                // status unless some DB query error or other exception comes up.
                // This way callers don't have to call rollback() if $status is bad
                // unless they actually try to catch exceptions (which is rare).
 
                // we need to remember the old content so we can use it to generate all deletion updates.
-               $content = $this->getContent( Revision::RAW );
+               try {
+                       $content = $this->getContent( Revision::RAW );
+               } catch ( Exception $ex ) {
+                       wfLogWarning( __METHOD__ . ': failed to load content during deletion! '
+                               . $ex->getMessage() );
+
+                       $content = null;
+               }
 
                // Bitfields to further suppress the content
                if ( $suppress ) {
@@ -2893,54 +2904,50 @@ class WikiPage implements Page, IDBAccessObject {
                        $bitfield = 'rev_deleted';
                }
 
-               /**
-                * 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.
-                */
-
-               $row = [
-                       '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_parent_id'  => 'rev_parent_id',
-                       'ar_text_id'    => 'rev_text_id',
-                       'ar_text'       => '\'\'', // Be explicit to appease
-                       'ar_flags'      => '\'\'', // MySQL's "strict mode"...
-                       'ar_len'        => 'rev_len',
-                       'ar_page_id'    => 'page_id',
-                       'ar_deleted'    => $bitfield,
-                       'ar_sha1'       => 'rev_sha1',
-               ];
+               // 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.
+               // In the future, we may keep revisions and mark them with
+               // the rev_deleted field, which is reserved for this purpose.
 
-               if ( $wgContentHandlerUseDB ) {
-                       $row['ar_content_model'] = 'rev_content_model';
-                       $row['ar_content_format'] = 'rev_content_format';
-               }
-
-               // Copy all the page revisions into the archive table
-               $dbw->insertSelect(
-                       'archive',
-                       [ 'page', 'revision' ],
-                       $row,
-                       [
-                               'page_id' => $id,
-                               'page_id = rev_page'
-                       ],
-                       __METHOD__
+               // Get all of the page revisions
+               $res = $dbw->select(
+                       'revision',
+                       Revision::selectFields(),
+                       [ 'rev_page' => $id ],
+                       __METHOD__,
+                       'FOR UPDATE'
                );
+               // Build their equivalent archive rows
+               $rowsInsert = [];
+               foreach ( $res as $row ) {
+                       $rowInsert = [
+                               'ar_namespace'  => $namespace,
+                               'ar_title'      => $dbKey,
+                               'ar_comment'    => $row->rev_comment,
+                               'ar_user'       => $row->rev_user,
+                               'ar_user_text'  => $row->rev_user_text,
+                               'ar_timestamp'  => $row->rev_timestamp,
+                               'ar_minor_edit' => $row->rev_minor_edit,
+                               'ar_rev_id'     => $row->rev_id,
+                               'ar_parent_id'  => $row->rev_parent_id,
+                               'ar_text_id'    => $row->rev_text_id,
+                               'ar_text'       => '',
+                               'ar_flags'      => '',
+                               'ar_len'        => $row->rev_len,
+                               'ar_page_id'    => $id,
+                               'ar_deleted'    => $bitfield,
+                               'ar_sha1'       => $row->rev_sha1,
+                       ];
+                       if ( $wgContentHandlerUseDB ) {
+                               $rowInsert['ar_content_model'] = $row->rev_content_model;
+                               $rowInsert['ar_content_format'] = $row->rev_content_format;
+                       }
+                       $rowsInsert[] = $rowInsert;
+               }
+               // Copy them into the archive table
+               $dbw->insert( 'archive', $rowsInsert, __METHOD__ );
                // Save this so we can pass it to the ArticleDeleteComplete hook.
                $archivedRevisionCount = $dbw->affectedRows();
 
@@ -3024,8 +3031,16 @@ class WikiPage implements Page, IDBAccessObject {
         *   may already return null when the page proper was deleted.
         */
        public function doDeleteUpdates( $id, Content $content = null ) {
+               try {
+                       $countable = $this->isCountable();
+               } catch ( Exception $ex ) {
+                       // fallback for deleting broken pages for which we cannot load the content for
+                       // some reason. Note that doDeleteArticleReal() already logged this problem.
+                       $countable = false;
+               }
+
                // Update site status
-               DeferredUpdates::addUpdate( new SiteStatsUpdate( 0, 1, - (int)$this->isCountable(), -1 ) );
+               DeferredUpdates::addUpdate( new SiteStatsUpdate( 0, 1, - (int)$countable, -1 ) );
 
                // Delete pagelinks, update secondary indexes, etc
                $updates = $this->getDeletionUpdates( $content );
@@ -3641,7 +3656,14 @@ class WikiPage implements Page, IDBAccessObject {
                if ( !$content ) {
                        // load content object, which may be used to determine the necessary updates.
                        // XXX: the content may not be needed to determine the updates.
-                       $content = $this->getContent( Revision::RAW );
+                       try {
+                               $content = $this->getContent( Revision::RAW );
+                       } catch ( Exception $ex ) {
+                               // If we can't load the content, something is wrong. Perhaps that's why
+                               // the user is trying to delete the page, so let's not fail in that case.
+                               // Note that doDeleteArticleReal() will already have logged an issue with
+                               // loading the content.
+                       }
                }
 
                if ( !$content ) {