jenkins-bot has submitted this change and it was merged. Change subject: Special:EnableFlow archives pre-existing talk page ......................................................................
Special:EnableFlow archives pre-existing talk page Enabling flow on an existing talk page is now accepted. It tries to archive the talk page to a subpage. The name of the archive is configurable using a new form field. The default value is %s/Archive_%d and it is localized. It uses a template named "Wikitext talk page converted to Flow" to add a reference to the archive page at the top of the flow board. It uses a template named "Archive for converted wikitext talk page" to add a reference to the flow board at the top of the archive page. Bug: T72073 Change-Id: If3b23383e4289290cde1237b74a4bbbb6bdcb455 --- M autoload.php M container.php M i18n/en.json M i18n/qqq.json M includes/Import/Converter.php M includes/Import/Importer.php M includes/Import/Wikitext/ConversionStrategy.php M includes/Import/Wikitext/ImportSource.php A includes/Log/DefaultLogger.php M includes/Specials/SpecialEnableFlow.php M maintenance/convertLqt.php M maintenance/convertLqtPageOnLocalWiki.php M maintenance/convertNamespaceFromWikitext.php 13 files changed, 170 insertions(+), 57 deletions(-) Approvals: Matthias Mullie: Looks good to me, approved jenkins-bot: Verified diff --git a/autoload.php b/autoload.php index ff9e156..c66d2ac 100644 --- a/autoload.php +++ b/autoload.php @@ -216,6 +216,7 @@ 'Flow\\Import\\Wikitext\\ImportSource' => __DIR__ . '/includes/Import/Wikitext/ImportSource.php', 'Flow\\LinksTableUpdater' => __DIR__ . '/includes/LinksTableUpdater.php', 'Flow\\Log\\ActionFormatter' => __DIR__ . '/includes/Log/ActionFormatter.php', + 'Flow\\Log\\DefaultLogger' => __DIR__ . '/includes/Log/DefaultLogger.php', 'Flow\\Log\\LogQuery' => __DIR__ . '/includes/Log/Query.php', 'Flow\\Log\\LqtImportFormatter' => __DIR__ . '/includes/Log/LqtImportFormatter.php', 'Flow\\Log\\ModerationLogger' => __DIR__ . '/includes/Log/ModerationLogger.php', diff --git a/container.php b/container.php index cb286b4..fb590f4 100644 --- a/container.php +++ b/container.php @@ -1219,4 +1219,13 @@ ); }; +$c['parser'] = function() { + global $wgParser; + return $wgParser; +}; + +$c['default_logger'] = function() { + return new Flow\Log\DefaultLogger(); +}; + return $c; diff --git a/i18n/en.json b/i18n/en.json index 005d542..e9448d9 100644 --- a/i18n/en.json +++ b/i18n/en.json @@ -392,7 +392,10 @@ "flow-special-enableflow-header": "Initial description of Flow board (wikitext)", "flow-special-enableflow-board-already-exists": "There is already a Flow board at [[$1]].", "flow-special-enableflow-invalid-title": "The provided page is not a valid page title", - "flow-special-enableflow-page-already-exists": "There is already a non-Flow page at [[$1]]. If you still want to locate a Flow board there, please move the existing page to an archive, delete the redirect, then use Special:EnableFlow again. Include the archive name in the description.", + "flow-special-enableflow-archive-title-format": "Where to archive existing content", + "flow-special-enableflow-archive-title-format-default-value": "%s/Archive_%d", + "flow-special-enableflow-board-creation-not-allowed": "You are not allowed to create a Flow board at [[:$1]].", + "flow-special-enableflow-page-is-liquidthreads": "There is a LiquidThreads page at [[:$1]].", "flow-special-enableflow-confirmation": "You have successfully created a Flow board at [[$1]].", "flow-spam-confirmedit-form": "Please confirm you are a human by solving the below captcha: $1", "flow-embedding-unsupported": "Discussions cannot be embedded yet.", diff --git a/i18n/qqq.json b/i18n/qqq.json index e29ac96..7823fd6 100644 --- a/i18n/qqq.json +++ b/i18n/qqq.json @@ -394,10 +394,13 @@ "flow-special-invalid-uuid": "Error message shown on the redirector special page if the specified type / UUID combination is invalid", "flow-special-enableflow-legend": "Legend for Special:EnableFlow form", "flow-special-enableflow-page": "Label for the page field of Special:EnableFlow", + "flow-special-enableflow-archive-title-format": "Label for the archive format field of Special:EnableFlow", + "flow-special-enableflow-archive-title-format-default-value": "Default value for the archive format field of Special:EnableFlow. This is a format string. %s and %d should be present. %s represents the title of the page where Flow is being enabled. %d represents a number that will be incremented if an archive page with the same name already exist.", "flow-special-enableflow-header": "Label for the header field of Special:EnableFlow", "flow-special-enableflow-board-already-exists": "Error given on Special:EnableFlow if board already exists at requested page name. Parameters:\n$1 - Page name where user requested to put Flow board", "flow-special-enableflow-invalid-title": "Error given on Special:EnableFlow if the provided page is not a valid page name.", - "flow-special-enableflow-page-already-exists": "Error given on Special:EnableFlow if a non-Flow page already exists at requested page name. Parameters:\n$1 - Page name where user requested to put Flow board", + "flow-special-enableflow-board-creation-not-allowed": "Error given on Special:EnableFlow if the current user is not allowed to create a Flow board. Parameters:\n$1 - Page name where user requested to put Flow board", + "flow-special-enableflow-page-is-liquidthreads": "Error given on Special:EnableFlow if the page to enable Flow on is a LiquidThreads page. Parameters:\n$1 - Page name where user requested to put Flow board", "flow-special-enableflow-confirmation": "Confirmation message on Special:EnableFlow saying that you have successfully created a board Parameters:\n$1 - Page name of new Flow board", "flow-spam-confirmedit-form": "Error message when ConfirmEdit flagged the submitted content (because an anonymous user submitted external links, possibly spam). A captcha will be displayed after this error message. Parameters:\n* $1 - the HTML for the captcha form.", "flow-embedding-unsupported": "Error message displayed if a user tries to transclude a Flow page.", diff --git a/includes/Import/Converter.php b/includes/Import/Converter.php index bd5e019..5e1e6cb 100644 --- a/includes/Import/Converter.php +++ b/includes/Import/Converter.php @@ -4,6 +4,7 @@ use DatabaseBase; use Flow\Repository\TitleRepository; +use Flow\Exception\FlowException; use MovePage; use MWExceptionHandler; use Psr\Log\LoggerInterface; @@ -31,7 +32,7 @@ */ class Converter { /** - * @var DatabaseBase Slave database of the current wiki. Required + * @var DatabaseBase Master database of the current wiki. Required * to lookup past page moves. */ protected $dbw; @@ -96,22 +97,15 @@ } /** + * Converts multiple pages into Flow boards + * * @param Traversable<Title>|array $titles */ - public function convert( $titles ) { + public function convertAll( $titles ) { /** @var Title $title */ foreach ( $titles as $title ) { try { - $movedFrom = $this->getPageMovedFrom( $title ); - if ( ! $this->isAllowed( $title, $movedFrom ) ) { - continue; - } - - if ( $this->strategy->isConversionFinished( $title, $movedFrom ) ) { - continue; - } - - $this->doConversion( $title, $movedFrom ); + $this->convert( $title ); } catch ( \Exception $e ) { MWExceptionHandler::logException( $e ); $this->logger->error( "Exception while importing: {$title}" ); @@ -120,6 +114,25 @@ } } + /** + * Converts a page into a Flow board + * + * @param Title $title + */ + public function convert( Title $title ) { + $movedFrom = $this->getPageMovedFrom( $title ); + if ( ! $this->isAllowed( $title, $movedFrom ) ) { + throw new FlowException( "Not allowed to convert: {$title}" ); + } + + // conversion is already done + if ( $this->strategy->isConversionFinished( $title, $movedFrom ) ) { + return; + } + + $this->doConversion( $title, $movedFrom ); + } + protected function isAllowed( Title $title, Title $movedFrom = null ) { // Only make changes to wikitext pages if ( $title->getContentModel() !== CONTENT_MODEL_WIKITEXT ) { diff --git a/includes/Import/Importer.php b/includes/Import/Importer.php index 740eeb4..8b56617 100644 --- a/includes/Import/Importer.php +++ b/includes/Import/Importer.php @@ -18,6 +18,7 @@ use Flow\Model\Workflow; use Flow\OccupationController; use Flow\WorkflowLoaderFactory; +use Flow\Container; use IP; use MWCryptRand; use Psr\Log\LoggerInterface; @@ -522,6 +523,7 @@ public function import( PageImportState $state ) { $destinationTitle = $state->boardWorkflow->getArticleTitle(); $state->logger->info( 'Importing to ' . $destinationTitle->getPrefixedText() ); + if ( $state->boardWorkflow->isNew() ) { $this->occupationController->allowCreation( $destinationTitle, @@ -531,6 +533,7 @@ new Article( $destinationTitle ), $state->boardWorkflow ); + $state->put( $state->boardWorkflow, array() ); } diff --git a/includes/Import/Wikitext/ConversionStrategy.php b/includes/Import/Wikitext/ConversionStrategy.php index 546c9d8..e4339c6 100644 --- a/includes/Import/Wikitext/ConversionStrategy.php +++ b/includes/Import/Wikitext/ConversionStrategy.php @@ -38,12 +38,39 @@ protected $parser; /** + * @var array $archiveTitleSuggestions + */ + protected $archiveTitleSuggestions; + + /** + * @var string $headerSuffix + */ + protected $headerSuffix; + + /** * @param Parser|StubObject $parser * @param ImportSourceStore $sourceStore */ - public function __construct( $parser, ImportSourceStore $sourceStore ) { + public function __construct( + $parser, + ImportSourceStore $sourceStore, + $preferredArchiveTitle = null, + $headerSuffix = null + ) { $this->parser = $parser; $this->sourceStore = $sourceStore; + $this->headerSuffix = $headerSuffix; + + if ( isset( $preferredArchiveTitle ) && !empty( $preferredArchiveTitle ) ) { + $this->archiveTitleSuggestions = array( $preferredArchiveTitle ); + } else { + $this->archiveTitleSuggestions = array( + '%s/Archive %d', + '%s/Archive%d', + '%s/archive %d', + '%s/archive%d', + ); + } } /** @@ -83,19 +110,14 @@ * {@inheritDoc} */ public function createImportSource( Title $title ) { - return new ImportSource( $title, $this->parser ); + return new ImportSource( $title, $this->parser, $this->headerSuffix ); } /** * {@inheritDoc} */ public function decideArchiveTitle( Title $source ) { - return Converter::decideArchiveTitle( $source, array( - '%s/Archive %d', - '%s/Archive%d', - '%s/archive %d', - '%s/archive%d', - ) ); + return Converter::decideArchiveTitle( $source, $this->archiveTitleSuggestions ); } /** diff --git a/includes/Import/Wikitext/ImportSource.php b/includes/Import/Wikitext/ImportSource.php index 4b737cc..6a61388 100644 --- a/includes/Import/Wikitext/ImportSource.php +++ b/includes/Import/Wikitext/ImportSource.php @@ -25,14 +25,16 @@ /** * @param Title $title * @param Parser|StubObject $parser + * @param string $headerSuffix * @throws ImportException When $title is an external title */ - public function __construct( Title $title, $parser ) { + public function __construct( Title $title, $parser, $headerSuffix = null ) { if ( $title->isExternal() ) { throw new ImportException( "Invalid non-local title: $title" ); } $this->title = $title; $this->parser = $parser; + $this->headerSuffix = $headerSuffix; } /** @@ -67,6 +69,10 @@ ) ); $content .= "\n\n{{{$template}|$arguments}}"; + if ( $this->headerSuffix && !empty( $this->headerSuffix ) ) { + $content .= "\n\n{$this->headerSuffix}"; + } + return new ImportHeader( array( new ObjectRevision( $content, diff --git a/includes/Log/DefaultLogger.php b/includes/Log/DefaultLogger.php new file mode 100644 index 0000000..17fb916 --- /dev/null +++ b/includes/Log/DefaultLogger.php @@ -0,0 +1,20 @@ +<?php + +namespace Flow\Log; + +use Psr\Log\AbstractLogger; +use Psr\Log\LogLevel; + +class DefaultLogger extends AbstractLogger { + + /** + * Sends everything to wfDebugLog for now. + * + * @param string $logLevel + * @param string $message + * @param array $context + */ + public function log( $logLevel, $message, array $context = array() ) { + wfDebugLog( 'Flow ', $logLevel . ' ' . $message . ' ' . implode( ',', $context ) ); + } +} diff --git a/includes/Specials/SpecialEnableFlow.php b/includes/Specials/SpecialEnableFlow.php index d6f22fb..e89282d 100644 --- a/includes/Specials/SpecialEnableFlow.php +++ b/includes/Specials/SpecialEnableFlow.php @@ -6,6 +6,9 @@ use Status; use Title; use Flow\Container; +use Flow\Import\Converter; +use Flow\Import\Wikitext\ConversionStrategy; +use Flow\Import\NullImportSourceStore; /** * A special page that allows users with the flow-create-board right to create @@ -38,6 +41,11 @@ 'type' => 'text', 'label-message' => 'flow-special-enableflow-page', ), + 'archive-title-format' => array( + 'type' => 'text', + 'label-message' => 'flow-special-enableflow-archive-title-format', + 'default' => $this->msg( 'flow-special-enableflow-archive-title-format-default-value' )->text(), + ), 'header' => array( 'type' => 'textarea', 'label-message' => 'flow-special-enableflow-header' @@ -54,7 +62,8 @@ } /** - * Check that Flow board does not exist, then create it + * Creates a flow board. + * Archives any pre-existing wikitext talk page. * * @param array $data Form data * @return Status Status indicating result @@ -73,44 +82,68 @@ return Status::newFatal( 'flow-special-enableflow-board-already-exists', $page ); } - if ( !$this->occupationController->allowCreation( $title, $this->getUser() ) ) { - // This is the only plausible reason this method would return false here. - // If there is another possible reason, we should have the method return a - // Status. - return Status::newFatal( 'flow-special-enableflow-page-already-exists', $page ); + if ( !$this->occupationController->allowCreation( $title, $this->getUser(), false ) ) { + return Status::newFatal( 'flow-special-enableflow-board-creation-not-allowed', $page ); } - - $loader = $this->loaderFactory->createWorkflowLoader( $title ); - $blocks = $loader->getBlocks(); - - $action = 'edit-header'; - - $params = array( - 'header' => array( - 'content' => $data['header'], - 'format' => 'wikitext', - ), - ); - - $blocksToCommit = $loader->handleSubmit( - $this->getContext(), - $action, - $params - ); $status = Status::newGood(); - foreach( $blocks as $block ) { - if ( $block->hasErrors() ) { - $errors = $block->getErrors(); + if ( $title->exists() ) { - foreach( $errors as $errorKey ) { - $status->fatal( $block->getErrorMessage( $errorKey ) ); + if ( class_exists( 'LqtDispatch' ) && LqtDispatch::isLqtPage( $title ) ) { + return Status::newFatal( 'flow-special-enableflow-page-is-liquidthreads', $page ); + } + + $converter = new Converter( + wfGetDB( DB_MASTER ), + Container::get( 'importer' ), + Container::get( 'default_logger' ), + $this->occupationController->getTalkpageManager(), + new ConversionStrategy( + Container::get( 'parser' ), + new NullImportSourceStore(), + $data['archive-title-format'], + $data['header'] + ) + ); + + try { + $converter->convert( $title ); + } catch ( \Exception $e ) { + \MWExceptionHandler::logException( $e ); + $status->fatal( 'flow-error-external', $e->getMessage() ); + } + + } else { + $loader = $this->loaderFactory->createWorkflowLoader( $title ); + $blocks = $loader->getBlocks(); + + $action = 'edit-header'; + $params = array( + 'header' => array( + 'content' => $data['header'], + 'format' => 'wikitext', + ), + ); + + $blocksToCommit = $loader->handleSubmit( + $this->getContext(), + $action, + $params + ); + + foreach( $blocks as $block ) { + if ( $block->hasErrors() ) { + $errors = $block->getErrors(); + + foreach( $errors as $errorKey ) { + $status->fatal( $block->getErrorMessage( $errorKey ) ); + } } } - } - $loader->commit( $blocksToCommit ); + $loader->commit( $blocksToCommit ); + } $this->page = $data['page']; return $status; diff --git a/maintenance/convertLqt.php b/maintenance/convertLqt.php index e2e69ab..9b57a2d 100644 --- a/maintenance/convertLqt.php +++ b/maintenance/convertLqt.php @@ -60,7 +60,7 @@ $logger->info( "Starting full wiki LQT conversion" ); $titles = new PagesWithPropertyIterator( $dbw, 'use-liquid-threads', $startId, $stopId ); - $converter->convert( $titles ); + $converter->convertAll( $titles ); } } diff --git a/maintenance/convertLqtPageOnLocalWiki.php b/maintenance/convertLqtPageOnLocalWiki.php index 8f25bee..a1e6070 100644 --- a/maintenance/convertLqtPageOnLocalWiki.php +++ b/maintenance/convertLqtPageOnLocalWiki.php @@ -72,7 +72,7 @@ $logger->info( "Starting LQT conversion of page $srcPageName" ); $srcTitle = \Title::newFromText( $srcPageName ); - $converter->convert( array( + $converter->convertAll( array( $srcTitle, ) ); } diff --git a/maintenance/convertNamespaceFromWikitext.php b/maintenance/convertNamespaceFromWikitext.php index 65198dd..0cbc425 100644 --- a/maintenance/convertNamespaceFromWikitext.php +++ b/maintenance/convertNamespaceFromWikitext.php @@ -67,7 +67,7 @@ } ); } - $converter->convert( $it ); + $converter->convertAll( $it ); } } -- To view, visit https://gerrit.wikimedia.org/r/205284 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: merged Gerrit-Change-Id: If3b23383e4289290cde1237b74a4bbbb6bdcb455 Gerrit-PatchSet: 15 Gerrit-Project: mediawiki/extensions/Flow Gerrit-Branch: master Gerrit-Owner: Sbisson <sbis...@wikimedia.org> Gerrit-Reviewer: EBernhardson <ebernhard...@wikimedia.org> Gerrit-Reviewer: Mattflaschen <mflasc...@wikimedia.org> Gerrit-Reviewer: Matthias Mullie <mmul...@wikimedia.org> Gerrit-Reviewer: Sbisson <sbis...@wikimedia.org> Gerrit-Reviewer: Siebrand <siebr...@kitano.nl> Gerrit-Reviewer: jenkins-bot <> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits