Bsitu has uploaded a new change for review.

  https://gerrit.wikimedia.org/r/111671

Change subject: Add *_user_wiki to all the *_user_id columns
......................................................................

Add *_user_wiki to all the *_user_id columns

This is to distinguish users and ips from different wikis especially
for pages like contributions.

This still needs some more thorough testing

Change-Id: I439b102e9125c4e6aed988032a21d51b1079f93b
---
M Hooks.php
M container.php
A db_patches/patch-add-wiki.sql
M flow.sql
M includes/Data/RevisionStorage.php
M includes/Data/UserNameBatch.php
M includes/Model/AbstractRevision.php
M includes/Model/PostRevision.php
M includes/Model/Workflow.php
A maintenance/FlowUpdateUserWiki.php
10 files changed, 382 insertions(+), 28 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/Flow 
refs/changes/71/111671/1

diff --git a/Hooks.php b/Hooks.php
index b63f64f..ae43c22 100644
--- a/Hooks.php
+++ b/Hooks.php
@@ -61,6 +61,7 @@
                $updater->modifyExtensionField( 'recentchanges', 'rc_source', 
"$dir/db_patches/patch-rc_source.sql" );
                $updater->modifyExtensionField( 'flow_revision', 
'rev_change_type', "$dir/db_patches/patch-censor_to_suppress.sql" );
                $updater->addExtensionField( 'flow_workflow', 
'workflow_user_ip', "$dir/db_patches/patch-remove_usernames.sql" );
+               $updater->addExtensionField( 'flow_workflow', 
'workflow_user_wiki', "$dir/db_patches/patch-add-wiki.sql" );
 
                require_once 
__DIR__.'/maintenance/FlowInsertDefaultDefinitions.php';
                $updater->addPostDatabaseUpdateMaintenance( 
'FlowInsertDefaultDefinitions' );
diff --git a/container.php b/container.php
index 3ac3c69..514c4b5 100644
--- a/container.php
+++ b/container.php
@@ -151,8 +151,7 @@
        $lifecycle = array(
                new Flow\Data\UserNameListener(
                        $c['repository.username'],
-                       array( 'workflow_user_id' ),
-                       'workflow_wiki'
+                       array( 'workflow_user_id' => 'workflow_user_wiki' )
                ),
                // $c['storage.user_subs.user_index']
        );
@@ -231,11 +230,11 @@
                $c['storage.board_history.index'],
                new Flow\Data\UserNameListener(
                        $c['repository.username'],
-                       array( 'rev_user_id', 'rev_mod_user_id', 
'rev_edit_user_id' ),
-                       null,
-                       // @todo composite wiki id + user columns, for now this
-                       // works as we only display content from this wiki
-                       wfWikiId()
+                       array(
+                               'rev_user_id' => 'rev_user_wiki',
+                               'rev_mod_user_id' => 'rev_mod_user_wiki',
+                               'rev_edit_user_id' => 'rev_edit_user_wiki'
+                       )
                ),
        );
 
@@ -318,11 +317,12 @@
                $c['storage.board_history.index'],
                new Flow\Data\UserNameListener(
                        $c['repository.username'],
-                       array( 'rev_user_id', 'rev_mod_user_id', 
'rev_edit_user_id', 'tree_orig_user_id' ),
-                       null,
-                       // @todo composite wiki id + user columns, for now this
-                       // works as we only display content from this wiki
-                       wfWikiId()
+                       array(
+                               'rev_user_id' => 'rev_user_wiki',
+                               'rev_mod_user_id' => 'rev_mod_user_wiki',
+                               'rev_edit_user_id' => 'rev_edit_user_wiki',
+                               'tree_orig_user_id' => 'tree_orig_user_wiki'
+                       )
                ),
        );
 
diff --git a/db_patches/patch-add-wiki.sql b/db_patches/patch-add-wiki.sql
new file mode 100644
index 0000000..fe8d057
--- /dev/null
+++ b/db_patches/patch-add-wiki.sql
@@ -0,0 +1,18 @@
+
+ALTER TABLE /*_*/flow_workflow ADD workflow_user_wiki varchar(32) binary not 
null;
+
+ALTER TABLE /*_*/flow_subscription ADD subscription_user_wiki varchar(32) 
binary not null;
+
+ALTER TABLE /*_*/flow_tree_revision ADD tree_orig_user_wiki varchar(32) binary 
not null;
+
+ALTER TABLE /*_*/flow_revision ADD rev_user_wiki varchar(32) binary not null;
+
+ALTER TABLE /*_*/flow_revision ADD rev_mod_user_wiki varchar(32) binary not 
null;
+
+ALTER TABLE /*_*/flow_revision ADD rev_edit_user_wiki varchar(32) binary not 
null;
+
+DROP INDEX /*i*/flow_subscription_unique_user_workflow ON 
/*_*/flow_subscription;
+CREATE UNIQUE INDEX /*i*/flow_subscription_unique_user_workflow ON 
/*_*/flow_subscription (subscription_workflow_id, subscription_user_id, 
subscription_user_wiki );
+
+DROP INDEX /*i*/flow_subscription_lookup ON /*_*/flow_subscription;
+CREATE INDEX /*i*/flow_subscription_lookup ON /*_*/flow_subscription 
(subscription_user_id, subscription_user_wiki, subscription_last_updated, 
subscription_workflow_id);
diff --git a/flow.sql b/flow.sql
index 77058fa..ec2d694 100644
--- a/flow.sql
+++ b/flow.sql
@@ -22,6 +22,7 @@
        -- TODO: check what the new global user ids need for storage
        workflow_user_id bigint unsigned not null,
        workflow_user_ip varbinary(39) default null,
+       workflow_user_wiki varchar(32) binary not null,
        -- TODO: is this usefull as a bitfield?  may be premature optimization, 
a string
        -- or list of strings may be simpler and use only a little more space.
        workflow_lock_state int unsigned not null,
@@ -34,12 +35,13 @@
 CREATE TABLE /*_*/flow_subscription (
   subscription_workflow_id int unsigned not null,
   subscription_user_id bigint unsigned not null,
+  subscription_user_wiki varchar(32) binary not null,
   subscription_create_timestamp varchar(14) binary not null,
   subscription_last_updated varchar(14) binary not null
 ) /*$wgDBTableOptions*/;
 
-CREATE UNIQUE INDEX /*i*/flow_subscription_unique_user_workflow ON 
/*_*/flow_subscription (subscription_workflow_id, subscription_user_id);
-CREATE INDEX /*i*/flow_subscription_lookup ON /*_*/flow_subscription 
(subscription_user_id, subscription_last_updated, subscription_workflow_id);
+CREATE UNIQUE INDEX /*i*/flow_subscription_unique_user_workflow ON 
/*_*/flow_subscription (subscription_workflow_id, subscription_user_id, 
subscription_user_wiki );
+CREATE INDEX /*i*/flow_subscription_lookup ON /*_*/flow_subscription 
(subscription_user_id, subscription_user_wiki, subscription_last_updated, 
subscription_workflow_id);
 
 -- TopicList Tables
 CREATE TABLE /*_*/flow_topic_list (
@@ -61,6 +63,7 @@
        tree_orig_create_time varchar(12) binary not null,
        tree_orig_user_id bigint unsigned not null,
        tree_orig_user_ip varbinary(39) default null,
+       tree_orig_user_wiki varchar(32) binary not null,
        -- denormalize post parent as well? Prevents an extra query when 
building
        -- tree from closure table.  unnecessary?
        tree_parent_id binary(16),
@@ -102,6 +105,7 @@
        -- user id creating the revision
        rev_user_id bigint unsigned not null,
        rev_user_ip varbinary(39) default null,
+       rev_user_wiki varchar(32) binary not null,
        -- rev_id of parent or null if no previous revision
        rev_parent_id binary(16),
        -- comma separated set of ascii flags.
@@ -116,6 +120,7 @@
        -- moderated by who?
        rev_mod_user_id bigint unsigned,
        rev_mod_user_ip varbinary(39) default null,
+       rev_mod_user_wiki varchar(32) binary not null,
        rev_mod_timestamp varchar(14) binary,
        -- moderated why? (coming soon: how?, where? and what?)
        rev_mod_reason varchar(255) binary,
@@ -124,6 +129,7 @@
        rev_last_edit_id binary(16) null,
        rev_edit_user_id bigint unsigned,
        rev_edit_user_ip varbinary(39) default null,
+       rev_edit_user_wiki varchar(32) binary not null,
 
        PRIMARY KEY (rev_id)
 ) /*$wgDBTableOptions*/;
diff --git a/includes/Data/RevisionStorage.php 
b/includes/Data/RevisionStorage.php
index c887e10..4ffce9a 100644
--- a/includes/Data/RevisionStorage.php
+++ b/includes/Data/RevisionStorage.php
@@ -16,6 +16,7 @@
                'rev_mod_state',
                'rev_mod_user_id',
                'rev_mod_user_ip',
+               'rev_mod_user_wiki',
                'rev_mod_timestamp',
                'rev_mod_reason',
        );
diff --git a/includes/Data/UserNameBatch.php b/includes/Data/UserNameBatch.php
index 86ba77d..c34d986 100644
--- a/includes/Data/UserNameBatch.php
+++ b/includes/Data/UserNameBatch.php
@@ -20,16 +20,15 @@
 
        /**
         * @param UserNameBatch $batch
-        * @param array $keys A list of keys from storage that contain user ids
+        * @param array $keys key - a list of keys from storage that contain 
user ids, value - the wiki for the user id lookup, default to $wiki if null
         * @param string|null $wikiKey A key from the storage row that contains 
the wiki id.
         * @param string|null $wiki The wikiid to use when $wikiKey is null. If 
both are null wfWikiId() is used
         */
-       public function __construct( UserNameBatch $batch, array $keys, 
$wikiKey = null, $wiki = null ) {
+       public function __construct( UserNameBatch $batch, array $keys, $wiki = 
null ) {
                $this->batch = $batch;
                $this->keys = $keys;
-               if ( $wikiKey !== null ) {
-                       $this->wikiKey = $wikiKey;
-               } elseif ( $wiki === null ) {
+
+               if ( $wiki === null ) {
                        $this->wiki = wfWikiId();
                } else {
                        $this->wiki = $wiki;
@@ -40,16 +39,21 @@
         * Load any user ids in $row into the username batch
         */
        public function onAfterLoad( $object, array $row ) {
-               if ( $this->wikiKey === null ) {
-                       $wiki = $this->wiki;
-               } elseif( isset( $row[$this->wikiKey] ) ) {
-                       $wiki = $row[$this->wikiKey];
-               } else {
-                       wfDebugLog( __CLASS__, __METHOD__ . ": could not detect 
wiki with {$this->wikiKey}" );
-                       return;
-               }
-               foreach ( $this->keys as $key ) {
+               foreach ( $this->keys as $key => $wiki ) {
+                       // check if the user id key exists in the data array 
and 
+                       // make sure it has a non-zero value
                        if ( isset( $row[$key] ) && $row[$key] != 0 ) {
+                               // the wiki for the user id lookup is specified,
+                               // check if it exists in the data array
+                               if ( $wiki ) {
+                                       if ( !isset( $row[$wiki] ) ) {
+                                               wfDebugLog( __CLASS__, 
__METHOD__ . ": could not detect wiki with " . $wiki );
+                                               continue;
+                                       }
+                               // no wiki lookup is specified, defalult to 
$this->wiki
+                               } else {
+                                       $wiki = $this->wiki;
+                               }
                                $this->batch->add( $wiki, $row[$key] );
                        }
                }
diff --git a/includes/Model/AbstractRevision.php 
b/includes/Model/AbstractRevision.php
index b3af131..19eb042 100644
--- a/includes/Model/AbstractRevision.php
+++ b/includes/Model/AbstractRevision.php
@@ -53,6 +53,8 @@
         */
        protected $userIp;
 
+       protected $userWiki;
+
        /**
         * Array of flags strictly related to the content. Flags are reset when
         * content changes.
@@ -101,6 +103,8 @@
         */
        protected $moderatedByUserIp;
 
+       protected $moderatedByUserWiki;
+
        protected $moderatedReason;
 
        /**
@@ -119,6 +123,8 @@
         */
        protected $lastEditUserIp;
 
+       protected $lastEditUserWiki;
+
        static public function fromStorageRow( array $row, $obj = null ) {
                if ( $obj === null ) {
                        $obj = new static;
@@ -133,6 +139,7 @@
                } elseif ( isset( $row['rev_user_text'] ) && $obj->userId === 0 
) {
                        $obj->userIp = $row['rev_user_text'];
                }
+               $obj->userWiki = $row['rev_user_wiki'];
                $obj->prevRevision = UUID::create( $row['rev_parent_id'] );
                $obj->changeType = $row['rev_change_type'];
                $obj->flags = array_filter( explode( ',', $row['rev_flags'] ) );
@@ -149,6 +156,7 @@
                } elseif ( isset( $row['rev_mod_user_text'] ) && 
$obj->moderatedByUserId === 0 ) {
                        $obj->moderatedByUserIp = $row['rev_mod_user_text'];
                }
+               $obj->moderatedByUserWiki = $row['rev_mod_user_wiki'];
                $obj->moderationTimestamp = $row['rev_mod_timestamp'];
                $obj->moderatedReason = isset( $row['rev_mod_reason'] ) ? 
$row['rev_mod_reason'] : null;
 
@@ -167,6 +175,7 @@
                        $obj->lastEditUserIp = $row['rev_edit_user_text'];
                }
                $obj->lastEditUserIp = isset( $row['rev_edit_user_ip'] ) ? 
$row['rev_edit_user_ip'] : null;
+               $obj->lastEditUserWiki = $row['rev_edit_user_wiki'];
 
                return $obj;
        }
@@ -176,6 +185,7 @@
                        'rev_id' => $obj->revId->getBinary(),
                        'rev_user_id' => $obj->userId,
                        'rev_user_ip' => $obj->userIp,
+                       'rev_user_wiki' => $obj->userWiki,
                        'rev_parent_id' => $obj->prevRevision ? 
$obj->prevRevision->getBinary() : null,
                        'rev_change_type' => $obj->changeType,
                        'rev_type' => $obj->getRevisionType(),
@@ -187,12 +197,14 @@
                        'rev_mod_state' => $obj->moderationState,
                        'rev_mod_user_id' => $obj->moderatedByUserId,
                        'rev_mod_user_ip' => $obj->moderatedByUserIp,
+                       'rev_mod_user_wiki' => $obj->moderatedByUserWiki,
                        'rev_mod_timestamp' => $obj->moderationTimestamp,
                        'rev_mod_reason' => $obj->moderatedReason,
 
                        'rev_last_edit_id' => $obj->lastEditId ? 
$obj->lastEditId->getBinary() : null,
                        'rev_edit_user_id' => $obj->lastEditUserId,
                        'rev_edit_user_ip' => $obj->lastEditUserIp,
+                       'rev_edit_user_wiki' => $obj->lastEditUserWiki,
                );
        }
 
@@ -373,6 +385,10 @@
                return $this->userIp;
        }
 
+       public function getUserWiki() {
+               return $this->userWiki;
+       }
+
        /**
         * Should only be used for setting the initial content.  To set 
subsequent content
         * use self::setNextContent
@@ -532,6 +548,10 @@
                return $this->lastEditUserIp;
        }
 
+       public function getLastContentEditUserWiki() {
+               return $this->lastEditUserWiki;
+       }
+
        public function getModeratedByUserId() {
                return $this->moderatedByUserId;
        }
@@ -540,6 +560,10 @@
                return $this->moderatedByUserIp;
        }
 
+       public function getModeratedByUserWiki() {
+               return $this->moderatedByUserWiki;
+       }
+
        /**
         * Return a (userId, userIp) tuple for the given
         * user object.  userIp is null for userId != 0
diff --git a/includes/Model/PostRevision.php b/includes/Model/PostRevision.php
index 023d602..54889f9 100644
--- a/includes/Model/PostRevision.php
+++ b/includes/Model/PostRevision.php
@@ -15,6 +15,7 @@
        protected $origCreateTime;
        protected $origUserId;
        protected $origUserIp;
+       protected $origUserWiki;
        protected $replyToId;
 
        /**
@@ -102,6 +103,7 @@
                $obj->postId = $uuid;
                $obj->origUserId = $obj->userId = $user->getId();
                $obj->origUserIp = $obj->userIp = $user->getName();
+               $obj->origUserWiki = wfWikiId();
                $obj->origCreateTime = wfTimestampNow();
                $obj->setReplyToId( null ); // not a reply to anything
                $obj->prevRevision = null; // no parent revision
@@ -126,6 +128,7 @@
                } elseif ( isset( $row['tree_orig_user_text'] ) && 
$obj->origUserId === 0 ) {
                        $obj->origUserIp = $row['tree_orig_user_text'];
                }
+               $obj->origUserWiki = $row['tree_orig_user_wiki'];
                return $obj;
        }
 
@@ -138,6 +141,7 @@
                        'tree_orig_create_time' => $rev->origCreateTime,
                        'tree_orig_user_id' => $rev->origUserId,
                        'tree_orig_user_ip' => $rev->origUserIp,
+                       'tree_orig_user_wiki' => $rev->origUserWiki,
                );
        }
 
@@ -148,6 +152,7 @@
                list( $reply->userId, $reply->userIp ) = self::userFields( 
$user );
                $reply->origUserId = $reply->userId;
                $reply->origUserIp = $reply->userIp;
+               $reply->origUserWiki = wfWikiId();
                $reply->origCreateTime = wfTimestampNow();
                $reply->replyToId = $this->postId;
                $reply->setContent( $content );
@@ -172,6 +177,10 @@
                return $this->origUserId;
        }
 
+       public function getCreatorWiki() {
+               return $this->origUserWiki;     
+       }
+
        /**
         * Get the user ip of the user who created this post if it
         * was created by an anonymous user
diff --git a/includes/Model/Workflow.php b/includes/Model/Workflow.php
index e5cbe5e..61dc1bb 100644
--- a/includes/Model/Workflow.php
+++ b/includes/Model/Workflow.php
@@ -19,6 +19,7 @@
        protected $titleText;
        protected $userId;
        protected $userIp;
+       protected $userWiki;
        // lock state is a list of state updates, the final state
        // is the active state.
        protected $lockState;
@@ -46,6 +47,7 @@
                } elseif ( isset( $row['workflow_user_text'] ) && $obj->userId 
=== 0 ) {
                        $obj->userIp = $row['workflow_user_text'];
                }
+               $obj->userWiki = $row['workflow_user_wiki'];
                $obj->lockState = $row['workflow_lock_state'];
                $obj->definitionId = UUID::create( 
$row['workflow_definition_id'] );
                $obj->lastModified = $row['workflow_last_update_timestamp'];
@@ -61,6 +63,7 @@
                        'workflow_title_text' => $obj->titleText,
                        'workflow_user_id' => $obj->userId,
                        'workflow_user_ip' => $obj->userIp,
+                       'workflow_user_wiki' => $obj->userWiki,
                        'workflow_lock_state' => $obj->lockState,
                        'workflow_definition_id' => 
$obj->definitionId->getBinary(),
                        'workflow_last_update_timestamp' => $obj->lastModified,
@@ -107,6 +110,7 @@
        public function getDefinitionId() { return $this->definitionId; }
        public function getUserId() { return $this->userId; }
        public function getUserIp() { return $this->userIp; }
+       public function getUserWiki() { return $this->userWiki; }
        public function getLastModified() { return $this->lastModified; }
        public function getLastModifiedObj() { return new MWTimestamp( 
$this->lastModified ); }
 
diff --git a/maintenance/FlowUpdateUserWiki.php 
b/maintenance/FlowUpdateUserWiki.php
new file mode 100644
index 0000000..4779786
--- /dev/null
+++ b/maintenance/FlowUpdateUserWiki.php
@@ -0,0 +1,287 @@
+<?php
+
+use Flow\Container;
+use Flow\Model\UUID;
+use Flow\Model\Header;
+use Flow\Model\PostRevision;
+
+$IP = getenv( 'MW_INSTALL_PATH' );
+if ( $IP === false ) {
+       $IP = dirname( __FILE__ ) . '/../../..';
+}
+require_once( "$IP/maintenance/Maintenance.php" );
+
+/**
+ * Update all xxx_user_wiki field to have the correct wiki name
+ *
+ * @ingroup Maintenance
+ */
+class FlowUpdateUserWiki extends Maintenance {
+
+       /**
+        * Max number of records to process at a time
+        *
+        * @var int
+        */
+       private $batchSize = 300;
+
+       /**
+        * Use to track the number of updated count
+        */
+       private $updatedCount = 0;
+
+       public function __construct() {
+               parent::__construct();
+               $this->mDescription = "Update xxx_user_wiki field in talbes: 
flow_workflow, flow_subscription, flow_tree_revision, flow_revision";
+       }
+
+       /**
+        * This is a top-to-bottom update, the process is like this:
+        * workflow -> header -> header revision -> history
+        * workflow -> topic list -> post tree revision -> post revision -> 
history
+        */
+       public function execute() {
+               $id = '';
+               $count = $this->batchSize;
+               $dbw= Container::get( 'db.factory' )->getDB( DB_MASTER );
+               
+               while ( $count == $this->batchSize ) {
+                       $count = 0;
+                       $res = $dbw->select(
+                               array( 'flow_workflow', 'flow_definition' ),
+                               array( 'workflow_wiki', 'workflow_id', 
'definition_type' ),
+                               array(
+                                       'workflow_id > ' . $dbw->addQuotes( $id 
),
+                                       'workflow_definition_id = definition_id'
+                               ),
+                               __METHOD__,
+                               array( 'ORDER BY' => 'workflow_id ASC', 'LIMIT' 
=> $this->batchSize )
+                       );
+                       if ( $res ) {
+                               foreach ( $res as $row ) {
+                                       $count++;
+                                       $id = $row->workflow_id;
+                                       $uuid = UUID::create( $row->workflow_id 
);
+                                       $workflow = Container::get( 
'storage.workflow' )->get( $uuid );
+                                       if ( $workflow ) {
+                                               // definition type 'topic' is 
always under a 'discussion' and they
+                                               // will be handled while 
processing 'discussion'
+                                               if ( $row->definition_type == 
'discussion' ) {
+                                                       $this->updateHeader( 
$workflow, $row->workflow_wiki );
+                                                       $this->updateTopicList( 
$workflow, $row->workflow_wiki );
+                                               }
+                                               // update workflow at last step 
so this can start from over again
+                                               // in case there is an error in 
the middle of updating others
+                                               $this->updateWorkflow( 
$workflow, $row->workflow_wiki );
+                                       }
+                               }
+                               $this->output( "processed $count records in " . 
__METHOD__ . "\n" );
+                       } else {
+                               throw new \MWException( 'SQL error in 
maintenance script ' . __CLASS__ . '::' . __METHOD__ );
+                       }
+               }
+       }
+
+       /**
+        * Update workflow
+        */
+       private function updateWorkflow( $wf, $wiki ) {
+               $storage = Container::get( 'storage.workflow' );
+               $reflection = new ReflectionClass( $wf );
+               $prop = $reflection->getProperty( 'userWiki' );
+               $prop->setAccessible( true );
+               $prop->setValue( $wf, $wiki );
+               
+               $reflection = new ReflectionClass( $storage );
+               $method = $reflection->getMethod( 'update' );
+               $method->setAccessible( true );
+               $method->invoke( $storage, $wf );
+               
+               
+               $this->output( "processing workflow: " . $wf->getId()->getHex() 
. ' in ' . __METHOD__ . "\n" );
+               $this->checkForSlave();
+       }
+
+       /**
+        * Update header
+        */
+       protected function updateHeader( $workflow, $wiki ) {
+               $id = '';
+               $count = $this->batchSize;
+               $dbw = Container::get( 'db.factory' )->getDB( DB_MASTER );
+
+               while ( $count == $this->batchSize ) {
+                       $count = 0;
+                       $res = $dbw->select(
+                               array( 'flow_header_revision', 'flow_revision' 
),
+                               array( 'rev_id', 'rev_type' ),
+                               array(
+                                       'rev_id > ' . $dbw->addQuotes( $id ),
+                                       'header_rev_id = rev_id',
+                                       'header_workflow_id' => 
$workflow->getId()->getBinary()
+                               ),
+                               __METHOD__,
+                               array( 'ORDER BY' => 'header_rev_id ASC', 
'LIMIT' => $this->batchSize )
+                       );
+                       if ( $res ) {
+                               foreach ( $res as $row ) {
+                                       $count++;
+                                       $id = $row->rev_id;
+                                       $revision = Container::get( 
'storage.header' )->get( UUID::create( $row->rev_id ) );
+                                       if ( $revision ) {
+                                               $this->updateHistory( 
$revision, $wiki, $revision );
+                                               $this->updateRevision( 
$revision, $wiki );
+                                       }
+                               }
+                       } else {
+                               throw new \MWException( 'SQL error in 
maintenance script ' . __CLASS__ . '::' . __METHOD__ );
+                       }
+
+                       $this->output( "processed $count records in " . 
__METHOD__ . "\n" );
+               }
+       }
+       
+       /**
+        * Update topic list
+        */
+       protected function updateTopicList( $workflow, $wiki ) {
+               $id = '';
+               $count = $this->batchSize;
+               $dbw = Container::get( 'db.factory' )->getDB( DB_MASTER );
+
+               while ( $count == $this->batchSize ) {
+                       $count = 0;
+                       $res = $dbw->select(
+                               array( 'flow_topic_list' ),
+                               array( 'topic_id' ),
+                               array( 'topic_list_id' => 
$workflow->getId()->getBinary() ),
+                               __METHOD__,
+                               array( 'ORDER BY' => 'topic_id ASC', 'LIMIT' => 
$this->batchSize )
+                       );
+                       if ( $res ) {
+                               $index = 0;
+                               foreach ( $res as $row ) {
+                                       $count++;
+                                       $index++;
+                                       $id = $row->topic_id;
+                                       $post = Container::get( 
'loader.root_post' )->get( UUID::create( $row->topic_id ) );
+                                       if ( $post ) {
+                                               $post->setRootPost( $post );
+                                               $this->updatePost( $post, 
$wiki, $post );
+                                       }
+                               }
+                               $this->output( "processed $index topics in " . 
__METHOD__ . "\n" );
+                       } else {
+                               throw new \MWException( 'SQL error in 
maintenance script ' . __CLASS__ . '::' . __METHOD__ );   
+                       }
+                       $this->output( "processed $count records in " . 
__METHOD__ . "\n" );
+               }
+       }
+
+       /**
+        * Update post
+        */
+       protected function updatePost( $post, $wiki, $root ) {
+               $this->updateHistory( $post, $wiki, $root );
+               $this->updateRevision( $post, $wiki );
+               foreach ( $post->getChildren() as $child ) {
+                       $this->updatePost( $child, $wiki, $root );
+               }
+       }
+
+       /**
+        * Update history revision
+        */
+       protected function updateHistory( $post, $wiki, $root ) {
+               if ( $post->getPrevRevisionId() ) {
+                       $parent = null;
+                       if ( $post->getRevisionType() === 'header' ) {
+                               $parent = Container::get( 'storage.header' 
)->get( UUID::create( $post->getPrevRevisionId() ) );
+                       } elseif ( $post->getRevisionType() === 'post' ) {
+                               $parent = Container::get( 'storage.post' 
)->get( UUID::create( $post->getPrevRevisionId() ) );
+                       }
+                       if ( $parent ) {
+                               if ( $post->getRevisionType() === 'post' ) {
+                                       // DOUBLE CHECK THIS, some index like 
TopicHistoryIndex::onAfterUpdate()
+                                       // requires a rootPost, would this 
overwrite the cache with an older history?
+                                       $parent->setRootPost( $root );
+                               }
+                               $this->updateRevision( $parent, $wiki );
+                               $this->updateHistory( $parent, $wiki, $root );
+                       }
+               }
+       }
+       
+       /**
+        * Update either header or post revision
+        */
+       protected function updateRevision( $revision, $wiki ) {
+               $type = $revision->getRevisionType();
+               if ( $type === 'post' ) {
+                       $storage = Container::get( 'storage.post' );
+               } elseif ( $type === 'header' ) {
+                       $storage = Container::get( 'storage.header' );
+               }
+
+               if ( !$revision ) {
+                       return;
+               }
+
+               $reflection = new ReflectionClass( $revision );
+
+               $prop = $reflection->getProperty( 'userWiki' );
+               $prop->setAccessible( true );
+               $prop->setValue( $revision, $wiki );
+
+               $prop = $reflection->getProperty( 'moderatedByUserWiki' );
+               $prop->setAccessible( true );
+               $prop->setValue( $revision, $wiki );
+
+               $prop = $reflection->getProperty( 'lastEditUserWiki' );
+               $prop->setAccessible( true );
+               $prop->setValue( $revision, $wiki );
+
+               if ( $type === 'post' ) {
+                       $prop = $reflection->getProperty( 'origUserWiki' );
+                       $prop->setAccessible( true );
+                       $prop->setValue( $revision, $wiki );
+               }
+
+               $reflection = new ReflectionClass( '\Flow\Data\RevisionStorage' 
);
+               $prop = $reflection->getProperty( 'allowedUpdateColumns' );
+               $prop->setAccessible( true );
+               $prop->setValue( array(
+                               'rev_mod_state',
+                               'rev_mod_user_id',
+                               'rev_mod_user_ip',
+                               'rev_mod_user_wiki',
+                               'rev_mod_timestamp',
+                               'rev_mod_reason',
+                               'rev_user_wiki',
+                               'rev_mod_user_wiki',
+                               'rev_edit_user_wiki',
+                               'tree_orig_user_wiki'
+                       )
+               );
+               
+               $reflection = new ReflectionClass( $storage );
+               $method = $reflection->getMethod( 'update' );
+               $method->setAccessible( true );
+
+               $method->invoke( $storage, $revision );
+
+               $this->output( "processing $type: " . 
$revision->getRevisionId()->getHex() . ' in ' . __METHOD__ . "\n" );
+               $this->checkForSlave();
+       }
+
+       private function checkForSlave() {
+               $this->updatedCount++;
+               if ( $this->updatedCount > $this->batchSize ) {
+                       wfWaitForSlaves();
+                       $this->updatedCount = 0;
+               }
+       }
+}
+
+$maintClass = "FlowUpdateUserWiki";
+require_once( DO_MAINTENANCE );

-- 
To view, visit https://gerrit.wikimedia.org/r/111671
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I439b102e9125c4e6aed988032a21d51b1079f93b
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/Flow
Gerrit-Branch: master
Gerrit-Owner: Bsitu <[email protected]>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to