| Current File : /home/jvzmxxx/wiki/extensions/Flow/maintenance/convertToText.php |
<?php
use Flow\Model\AbstractRevision;
use Flow\Import\LiquidThreadsApi\ApiBackend;
use Flow\Import\LiquidThreadsApi\RemoteApiBackend;
use Flow\Import\LiquidThreadsApi\LocalApiBackend;
require_once ( getenv( 'MW_INSTALL_PATH' ) !== false
? getenv( 'MW_INSTALL_PATH' ) . '/maintenance/Maintenance.php'
: dirname( __FILE__ ) . '/../../../maintenance/Maintenance.php' );
class ConvertToText extends Maintenance {
/**
* @var Title
*/
protected $pageTitle;
/**
* @var ApiBackend
*/
protected $api;
public function __construct() {
parent::__construct();
$this->mDescription = "Converts a specific Flow page to text";
$this->addOption( 'page', 'The page to convert', true /*required*/ );
$this->addOption( 'remoteapi', 'The api of the wiki to convert the page from (or nothing, for local wiki)', false /*required*/ );
}
public function execute() {
$pageName = $this->getOption( 'page' );
$this->pageTitle = Title::newFromText( $pageName );
if ( !$this->pageTitle ) {
$this->error( 'Invalid page title', true );
}
if ( $this->getOption( 'remoteapi' ) ) {
$this->api = new RemoteApiBackend( $this->getOption( 'remoteapi' ) );
} else {
$this->api = new LocalApiBackend();
}
$headerContent = '';
$headerData = $this->flowApi(
$this->pageTitle,
'view-header',
array( 'vhformat' => 'wikitext' ),
'header'
);
$headerRevision = $headerData['header']['revision'];
if ( isset( $headerRevision['content'] ) ) {
$headerContent = $headerRevision['content']['content'];
}
$continue = true;
$pagerParams = array( 'vtllimit' => 1 );
$topics = array();
while( $continue ) {
$continue = false;
$flowData = $this->flowApi(
$this->pageTitle,
'view-topiclist',
$pagerParams + array( 'vtlformat' => 'wikitext', 'vtlsortby' => 'newest' ),
'topiclist'
);
$topicListBlock = $flowData['topiclist'];
foreach( $topicListBlock['roots'] as $rootPostId ) {
$revisionId = reset( $topicListBlock['posts'][$rootPostId] );
$revision = $topicListBlock['revisions'][$revisionId];
$topics[] = $this->processTopic( $topicListBlock, $revision );
}
if ( isset( $topicListBlock['links']['pagination'] ) ) {
$paginationLinks = $topicListBlock['links']['pagination'];
if ( isset( $paginationLinks['fwd'] ) ) {
list( $junk, $query ) = explode( '?', $paginationLinks['fwd']['url'] );
$queryParams = wfCGIToArray( $query );
$pagerParams = array(
'vtloffset-id' => $queryParams['topiclist_offset-id'],
'vtloffset-dir' => 'fwd',
'vtloffset-limit' => '1',
);
$continue = true;
}
}
}
print $headerContent . "\n\n" . implode( "\n", array_reverse( $topics ) );
}
/**
* @param Title $title
* @param string $submodule
* @param array $request
* @param bool $requiredBlock
* @return array
* @throws MWException
*/
protected function flowApi( Title $title, $submodule, array $request, $requiredBlock = false ) {
$result = $this->api->apiCall( $request + array(
'action' => 'flow',
'submodule' => $submodule,
'page' => $title->getPrefixedText(),
) );
return $result['flow'][$submodule]['result'];
}
protected function processTopic( array $context, array $revision ) {
$topicOutput = '==' . $revision['content']['content'] . '==' . "\n";
$summaryOutput = isset( $revision['summary'] ) ? $this->processSummary( $context, $revision['summary'] ) : '';
$postsOutput = $this->processPostCollection( $context, $revision['replies'] );
$resolved = isset( $revision['moderateState'] ) && $revision['moderateState'] === AbstractRevision::MODERATED_LOCKED;
// check if "resolved" templates exist
$archiveTemplates = $this->pageExists( 'Template:Archive_top' ) && $this->pageExists( 'Template:Archive_bottom' );
$hatnoteTemplate = $this->pageExists( 'Template:Hatnote' );
if ( $archiveTemplates && $resolved ) {
return '{{Archive top|result=' . $summaryOutput . "|status=resolved}}\n\n" .
$topicOutput . $postsOutput . "{{Archive bottom}}\n\n";
} elseif ( $hatnoteTemplate && $summaryOutput ) {
return $topicOutput . '{{Hatnote|' . $summaryOutput . "}}\n\n" . $postsOutput;
} else {
// italicize summary, if there is any, to set it apart from posts
$summaryOutput = $summaryOutput ? "''" . $summaryOutput . "''" : '';
return $topicOutput . $summaryOutput . $postsOutput;
}
}
protected function loadUser( $id, $name ) {
$row = new \StdClass;
$row->user_name = $name;
$row->user_id = $id;
return User::newFromRow( $row );
}
protected function processSummary( array $context, array $summary ) {
return trim( $summary['revision']['content']['content'] ) . ' ' .
$this->getSignature( $summary['revision']['author'], $summary['revision']['timestamp'] );
}
protected function processPostCollection( array $context, array $collection, $indentLevel = 0 ) {
$indent = str_repeat( ':', $indentLevel );
$output = '';
foreach( $collection as $postId ) {
$revisionId = reset( $context['posts'][$postId] );
$revision = $context['revisions'][$revisionId];
// Skip moderated posts
if ( $revision['isModerated'] ) {
continue;
}
$thisPost = $indent . trim( $revision['content']['content'] ) . ' ' .
$this->getSignature( $revision['author'], $revision['timestamp'] );
if ( $indentLevel > 0 ) {
$thisPost = preg_replace( "/\n+/", "\n$indent", $thisPost );
}
$output .= $thisPost . "\n";
if ( isset( $revision['replies'] ) ) {
$output .= $this->processPostCollection( $context, $revision['replies'], $indentLevel + 1 );
}
if ( $indentLevel == 0 ) {
$output .= "\n";
}
}
return $output;
}
protected function getSignature( array $user, $timestamp ) {
global $wgContLang, $wgParser;
// Force unstub
StubObject::unstub( $wgParser );
$timestamp = MWTimestamp::getLocalInstance( $timestamp );
$ts = $timestamp->format( 'YmdHis' );
$tzMsg = $timestamp->format( 'T' ); # might vary on DST changeover!
# Allow translation of timezones through wiki. format() can return
# whatever crap the system uses, localised or not, so we cannot
# ship premade translations.
$key = 'timezone-' . strtolower( trim( $tzMsg ) );
$msg = wfMessage( $key )->inContentLanguage();
if ( $msg->exists() ) {
$tzMsg = $msg->text();
}
$d = $wgContLang->timeanddate( $ts, false, false ) . " ($tzMsg)";
if ( $user ) {
// create a bogus user for whom username & id is known, so we
// can generate a correct signature
$user = $this->loadUser( $user['id'], $user['name'] );
// nickname & fancysig are user options: unless we're on local wiki,
// we don't know these & can't load them to generate the signature
$nickname = $this->getOption( 'remoteapi' ) ? null : false;
$fancysig = $this->getOption( 'remoteapi' ) ? false : null;
// Parser::getUserSig can end calling `getCleanSignatures` on
// mOptions, which may not be set. Set a dummy options object so it
// doesn't fail (it'll initialise the requested value from a global
// anyway)
$options = new ParserOptions();
$old = $wgParser->Options( $options );
$signature = $wgParser->getUserSig( $user, $nickname, $fancysig ) . ' ' . $d;
$wgParser->Options( $old );
return $signature;
} else {
return "[Unknown user] $d";
}
}
protected function pageExists( $pageName ) {
static $pages = array();
if ( !isset( $pages[$pageName] ) ) {
$result = $this->api->apiCall( array( 'action' => 'query', 'titles' => $pageName ) );
$pages[$pageName] = !isset( $result['query']['pages'][-1] );
}
return $pages[$pageName];
}
}
$maintClass = "ConvertToText";
require_once( RUN_MAINTENANCE_IF_MAIN );