Mattflaschen has uploaded a new change for review.

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

Change subject: Add script to fix inconsistent state for board name
......................................................................

Add script to fix inconsistent state for board name

This loops through all Flow boards (optionally with a namespace
constraint).  It checks the JSON workflow ID, loads the workflow
from that, then checks that the Flow title matches the core (page
table) title.

You can optionally limit the number of boards modified in each run.

There is also a dry run mode.

Small supporting changes elsewhere, including renaming a parameter
in another maintenance script to match.

Bug: T148057
Change-Id: I6a1a410db0893049651fbbbd6f9b9f13360c34c3
---
M Hooks.php
M includes/BoardMover.php
M includes/WorkflowLoaderFactory.php
A maintenance/FlowFixInconsistentBoards.php
M maintenance/convertNamespaceFromWikitext.php
5 files changed, 146 insertions(+), 5 deletions(-)


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

diff --git a/Hooks.php b/Hooks.php
index 0ef70bd..072f17e 100644
--- a/Hooks.php
+++ b/Hooks.php
@@ -280,6 +280,9 @@
                require_once __DIR__.'/maintenance/FlowPopulateRefId.php';
                $updater->addPostDatabaseUpdateMaintenance( 'FlowPopulateRefId' 
);
 
+               require_once 
__DIR__.'/maintenance/FlowFixInconsistentBoards.php';
+               $updater->addPostDatabaseUpdateMaintenance( 
'FlowFixInconsistentBoards' );
+
                /*
                 * Add primary key, but only after we've made sure the newly 
added
                 * column has been populated (otherwise they'd all be null 
values)
diff --git a/includes/BoardMover.php b/includes/BoardMover.php
index b0978a7..979408f 100644
--- a/includes/BoardMover.php
+++ b/includes/BoardMover.php
@@ -51,9 +51,8 @@
 
        /**
         * Collects the workflow and header (if it exists) and puts them into 
the database. Does
-        * not commit yet. It is intended for begin to be called at the 
beginning of the
-        * transaction, move to be called for each move, and commit to be 
called at the end
-        * the core transaction, via a hook.
+        * not commit yet. It is intended for move to be called for each move, 
and commit
+        * to be called at the end the core transaction, via a hook.
         *
         * @param int $oldPageId Page ID before move/change
         * @param Title $newPage Page after move/change
diff --git a/includes/WorkflowLoaderFactory.php 
b/includes/WorkflowLoaderFactory.php
index 647ece0..fd52375 100644
--- a/includes/WorkflowLoaderFactory.php
+++ b/includes/WorkflowLoaderFactory.php
@@ -113,7 +113,7 @@
         * @throws InvalidInputException
         * @throws UnknownWorkflowIdException
         */
-       protected function loadWorkflowById( /* Title or false */ $title, 
$workflowId ) {
+       public function loadWorkflowById( /* Title or false */ $title, 
$workflowId ) {
                /** @var Workflow $workflow */
                $workflow = $this->storage->getStorage( 'Workflow' )->get( 
$workflowId );
                if ( !$workflow ) {
diff --git a/maintenance/FlowFixInconsistentBoards.php 
b/maintenance/FlowFixInconsistentBoards.php
new file mode 100644
index 0000000..885dc64
--- /dev/null
+++ b/maintenance/FlowFixInconsistentBoards.php
@@ -0,0 +1,139 @@
+<?php
+
+use Flow\Content\BoardContent;
+use Flow\Container;
+use Flow\Exception\UnknownWorkflowIdException;
+
+require_once ( getenv( 'MW_INSTALL_PATH' ) !== false
+       ? getenv( 'MW_INSTALL_PATH' ) . '/maintenance/Maintenance.php'
+       : dirname( __FILE__ ) . '/../../../maintenance/Maintenance.php' );
+
+/**
+ * Changes Flow boards and their topics to be associated with their current 
title, based on the JSON content
+ * Fixes inconsistent bugs like T138310.
+ *
+ * There is a dry run available.
+ *
+ * @ingroup Maintenance
+ */
+class FlowFixInconsistentBoards extends LoggedUpdateMaintenance {
+       /**
+        * @var DbFactory $dbFactory
+        */
+       protected $dbFactory;
+
+       /**
+        * @var WorkflowLoaderFactory $workflowLoaderFactory
+        */
+       protected $workflowLoaderFactory;
+
+       public function __construct() {
+               parent::__construct();
+
+               $this->mDescription = 'Changes Flow boards and their topics to 
be associated with their current title, based on the JSON content.  Must be run 
separately for each affected wiki.';
+
+               $this->addOption( 'dry-run', 'Only prints the board names, 
without changing anything.' );
+               $this->addOption( 'namespaceName', 'Name of namespace to check, 
otherwise all', false, true );
+               $this->addOption( 'limit', 'Limit of inconsistent pages to 
identify (and fix if not a dry run).  Defaults to no limit', false, true );
+
+               $this->setBatchSize( 300 );
+       }
+
+       protected function getUpdateKey() {
+               return 'FlowFixInconsistentBoards:version1';
+       }
+
+       public function doDBUpdates() {
+               global $wgLang;
+
+               $this->dbFactory = Container::get( 'db.factory' );
+               $this->workflowLoaderFactory = Container::get( 
'factory.loader.workflow' );
+
+               $this->boardMover = Container::get( 'board_mover' );
+
+               $dryRun = $this->hasOption( 'dry-run' );
+
+               $limit = $this->getOption( 'limit' );
+
+               $wikiDbw = $this->dbFactory->getWikiDB( DB_MASTER );
+
+               $iterator = new BatchRowIterator( $wikiDbw, 'page', 'page_id', 
$this->mBatchSize );
+               $iterator->setFetchColumns( [ 'page_namespace', 'page_title', 
'page_latest' ] );
+               $iterator->addConditions( [
+                       'page_content_model' => CONTENT_MODEL_FLOW_BOARD,
+               ] );
+
+               if ( $this->hasOption( 'namespaceName' ) ) {
+                       $namespaceName = $this->getOption( 'namespaceName' );
+                       $namespaceId = $wgLang->getNsIndex( $namespaceName );
+
+                       if ( !$namespaceId ) {
+                               $this->error( "'$namespaceName' is not a valid 
namespace name" );
+                               return;
+                       }
+
+                       if ( $namespaceId == NS_TOPIC ) {
+                               $this->error( 'This script can not be run on 
the Flow topic namespace' );
+                               return;
+                       }
+
+                       $iterator->addConditions( [
+                               'page_namespace' => $namespaceId,
+                       ] );
+               } else {
+                       $iterator->addConditions( [
+                               'page_namespace != ' . NS_TOPIC,
+                       ] );
+               }
+
+               $checkedCount = 0;
+               $inconsistentCount = 0;
+               foreach ( $iterator as $rows ) {
+                       foreach ( $rows as $row ) {
+                               $checkedCount++;
+                               $coreTitle = Title::makeTitle( 
$row->page_namespace, $row->page_title );
+                               $revision = Revision::newFromId( 
$row->page_latest );
+                               $content = $revision->getContent( Revision::RAW 
);
+                               if ( !$content instanceof BoardContent ) {
+                                       $actualClass = get_class( $content );
+                                       $this->error( "ERROR: '$coreTitle' 
content is a '$actualClass', but should be '" . BoardContent::class . "'." );
+                                       continue;
+                               }
+                               $workflowId = $content->getWorkflowId();
+                               $workflowIdAlphadecimal = 
$workflowId->getAlphadecimal();
+                               try {
+                                       $workflow = 
$this->workflowLoaderFactory->loadWorkflowById( false, $workflowId );
+                               } catch ( UnknownWorkflowIdException $ex ) {
+                                       // This is a different error (a core 
page refers to
+                                       // a non-existent workflow), which this 
script can not fix.
+                                       $this->error( "ERROR: '$coreTitle' 
refers to workflow ID '$workflowIdAlphadecimal', which could not be found." );
+                                       continue;
+                               }
+                               if ( !$workflow->matchesTitle( $coreTitle ) ) {
+                                       $workflowTitle = 
$workflow->getOwnerTitle();
+                                       $this->output( "INCONSISTENT: Core 
title for '$workflowIdAlphadecimal' is '$coreTitle', but Flow title is 
'$workflowTitle'\n" );
+
+                                       if ( !$dryRun ) {
+                                               $this->boardMover->move( 
(int)$row->page_id, $coreTitle );
+                                               $this->boardMover->commit();
+                                               $this->output( "FIXED: Updated 
'$workflowIdAlphadecimal' to match core title, '$coreTitle'\n" );
+                                       }
+
+                                       $inconsistentCount++;
+                                       if ( $limit !== null && 
$inconsistentCount >= $limit ) {
+                                               break;
+                                       }
+                               }
+                       }
+
+                       $action = $dryRun ? 'Identified' : 'Fixed';
+                       $this->output( "Checked a total of $checkedCount Flow 
boards.  $action a total of $inconsistentCount inconsistent boards.\n" );
+                       if ( $limit !== null && $inconsistentCount >= $limit ) {
+                               break;
+                       }
+               }
+       }
+}
+
+$maintClass = 'FlowFixInconsistentBoards';
+require_once( RUN_MAINTENANCE_IF_MAIN );
diff --git a/maintenance/convertNamespaceFromWikitext.php 
b/maintenance/convertNamespaceFromWikitext.php
index 064cd5f..303cee7 100644
--- a/maintenance/convertNamespaceFromWikitext.php
+++ b/maintenance/convertNamespaceFromWikitext.php
@@ -15,7 +15,7 @@
        public function __construct() {
                parent::__construct();
                $this->mDescription = "Converts a single namespace of wikitext 
talk pages to Flow";
-               $this->addArg( 'namespace', 'Name of the namespace to convert' 
);
+               $this->addArg( 'namespaceName', 'Name of the namespace to 
convert' );
                $this->addOption(
                        'no-convert-templates',
                        'Comma-separated list of templates that indicate a page 
should not be converted',

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

Gerrit-MessageType: newchange
Gerrit-Change-Id: I6a1a410db0893049651fbbbd6f9b9f13360c34c3
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/Flow
Gerrit-Branch: master
Gerrit-Owner: Mattflaschen <mflasc...@wikimedia.org>

_______________________________________________
MediaWiki-commits mailing list
MediaWiki-commits@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to