| Current File : /home/jvzmxxx/wiki1/extensions/Flow/maintenance/FlowFixLog.php |
<?php
use Flow\Container;
use Flow\Data\ManagerGroup;
use Flow\Exception\InvalidDataException;
use Flow\Model\PostRevision;
use Flow\Model\UUID;
use Flow\Collection\PostCollection;
$IP = getenv( 'MW_INSTALL_PATH' );
if ( $IP === false ) {
$IP = dirname( __FILE__ ) . '/../../..';
}
require_once( "$IP/maintenance/Maintenance.php" );
require_once( "$IP/includes/utils/RowUpdateGenerator.php" );
/**
* Fixes Flow log entries.
*
* @ingroup Maintenance
*/
class FlowFixLog extends LoggedUpdateMaintenance {
public function __construct() {
parent::__construct();
$this->mDescription = 'Fixes Flow log entries';
$this->setBatchSize( 300 );
}
protected function getUpdateKey() {
return 'FlowFixLog:version2';
}
protected function doDBUpdates() {
$iterator = new BatchRowIterator( wfGetDB( DB_SLAVE ), 'logging', 'log_id', $this->mBatchSize );
$iterator->setFetchColumns( array( 'log_id', 'log_params' ) );
$iterator->addConditions( array(
'log_type' => array( 'delete', 'suppress' ),
'log_action' => array(
'flow-delete-post', 'flow-suppress-post', 'flow-restore-post',
'flow-delete-topic', 'flow-suppress-topic', 'flow-restore-topic',
),
) );
$updater = new BatchRowUpdate(
$iterator,
new BatchRowWriter( wfGetDB( DB_MASTER ), 'logging' ),
new LogRowUpdateGenerator( $this )
);
$updater->setOutput( array( $this, 'output' ) );
$updater->execute();
return true;
}
/**
* parent::output() is a protected method, only way to access it from a
* callback in php5.3 is to make a public function. In 5.4 can replace with
* a Closure.
*
* @param string $out
* @param mixed $channel
*/
public function output( $out, $channel = null ) {
parent::output( $out, $channel );
}
/**
* parent::error() is a protected method, only way to access it from the
* outside is to make it public.
*
* @param string $err
* @param int $die
*/
public function error( $err, $die = 0 ) {
parent::error( $err, $die );
}
}
class LogRowUpdateGenerator implements RowUpdateGenerator {
/**
* @var FlowFixLog
*/
protected $maintenance;
/**
* @param FlowFixLog $maintenance
*/
public function __construct( FlowFixLog $maintenance ) {
$this->maintenance = $maintenance;
}
public function update( $row ) {
$updates = array();
$params = unserialize( $row->log_params );
if ( !$params ) {
$this->maintenance->error( "Failed to unserialize log_params for log_id {$row->log_id}" );
return array();
}
$topic = false;
$post = false;
if ( isset( $params['topicId'] ) ) {
$topic = $this->loadTopic( UUID::create( $params['topicId'] ) );
}
if ( isset( $params['postId'] ) ) {
$post = $this->loadPost( UUID::create( $params['postId'] ) );
$topic = $topic ?: $post->getRoot();
}
if ( !$topic ) {
$this->maintenance->error( "Missing topicId & postId for log_id {$row->log_id}" );
return array();
}
try {
// log_namespace & log_title used to be board, should be topic
$updates['log_namespace'] = $topic->getTitle()->getNamespace();
$updates['log_title'] = $topic->getTitle()->getDBkey();
} catch ( \Exception $e ) {
$this->maintenance->error( "Couldn't load Title for log_id {$row->log_id}" );
$updates = array();
}
if ( isset( $params['postId'] ) && $post ) {
// posts used to save revision id instead of post id, let's make
// sure it's actually the post id that's being saved!...
$params['postId'] = $post->getId();
}
if ( !isset( $params['topicId'] ) ) {
// posts didn't use to also store topicId, but we'll be using it to
// enrich log entries' output - might as well store it right away
$params['topicId'] = $topic->getId();
}
// we used to save (serialized) UUID objects; now we just save the
// alphanumeric representation
foreach ( $params as $key => $value ) {
$params[$key] = $value instanceof UUID ? $value->getAlphadecimal() : $value;
}
// re-serialize params (UUID used to serialize more verbose; might
// as well shrink that down now that we're updating anyway...)
$updates['log_params'] = serialize( $params );
return $updates;
}
/**
* @param UUID $topicId
* @return PostCollection
*/
protected function loadTopic( UUID $topicId ) {
return PostCollection::newFromId( $topicId );
}
/**
* @param UUID $postId
* @return PostCollection
*/
protected function loadPost( UUID $postId ) {
try {
$collection = PostCollection::newFromId( $postId );
// validate collection by attempting to fetch latest revision - if
// this fails (likely will for old data), catch will be invoked
$collection->getLastRevision();
return $collection;
} catch ( InvalidDataException $e ) {
// posts used to mistakenly store revision ID instead of post ID
/** @var ManagerGroup $storage */
$storage = Container::get( 'storage' );
$result = $storage->find(
'PostRevision',
array( 'rev_id' => $postId ),
array( 'LIMIT' => 1 )
);
if ( $result ) {
/** @var PostRevision $revision */
$revision = reset( $result );
// now build collection from real post ID
return $this->loadPost( $revision->getPostId() );
}
}
return false;
}
}
$maintClass = 'FlowFixLog';
require_once( RUN_MAINTENANCE_IF_MAIN );