| Current File : /home/jvzmxxx/wiki1/extensions/Flow/includes/Repository/UserNameBatch.php |
<?php
/**
* Provide usernames filtered by per-wiki ipblocks. Batches together
* database requests for multiple usernames when possible.
*/
namespace Flow\Repository;
use Flow\Model\UserTuple;
use MapCacheLRU;
use User;
/**
* Batch together queries for a bunch of wiki+userid -> username
*/
class UserNameBatch {
// Maximum number of usernames to cache for each wiki
const USERNAMES_PER_WIKI = 250;
/**
* @var UserName\UserNameQuery
*/
protected $query;
/**
* @var array[] map from wikiid to list of userid's to request
*/
protected $queued = array();
/**
* @var array Map from wiki id to MapCacheLRU. MapCacheLRU is a map of user ID (as
* string, though to PHP it's the same anyway...) to username.
*/
protected $usernames = array();
/**
* @param UserName\UserNameQuery $query
* @param array $queued map from wikiid to list of userid's to request
*/
public function __construct( UserName\UserNameQuery $query, array $queued = array() ) {
$this->query = $query;
foreach ( $queued as $wiki => $userIds ) {
$this->queued[$wiki] = array_map( 'intval', $userIds );
}
}
/*
* Make sure the LRU for the given wiki is in place.
*
* @param string $wiki Wiki identifier
*/
protected function ensureLRU( $wiki ) {
if ( !isset( $this->usernames[$wiki] ) ) {
$this->usernames[$wiki] = new MapCacheLRU( self::USERNAMES_PER_WIKI );
}
}
public function clear() {
$this->queued = array();
$this->usernames = array();
}
/**
* @param string $wiki
* @param integer $userId
* @param string $userName Non null to set known usernames like $wgUser
*/
public function add( $wiki, $userId, $userName = null ) {
$userId = (int)$userId;
$this->ensureLRU( $wiki );
if ( $userName !== null ) {
$this->usernames[$wiki]->set( (string) $userId, $userName );
} elseif ( !$this->usernames[$wiki]->has( (string) $userId ) ) {
$this->queued[$wiki][] = $userId;
}
}
/**
* @param UserTuple $tuple
*/
public function addFromTuple( UserTuple $tuple ) {
$this->add( $tuple->wiki, $tuple->id, $tuple->ip );
}
/**
* Get the displayable username
*
* @param string $wiki
* @param integer $userId
* @param string|boolean $userIp
* @return string|boolean false if username is not found or display is suppressed
* @todo Return something better for not found / suppressed, but what? Making
* return type string|Message would suck.
*/
public function get( $wiki, $userId, $userIp = false ) {
$userId = (int)$userId;
if ( $userId === 0 ) {
return $userIp;
}
$this->ensureLRU( $wiki );
if ( !$this->usernames[$wiki]->has( (string) $userId ) ) {
$this->queued[$wiki][] = $userId;
$this->resolve( $wiki );
}
return $this->usernames[$wiki]->get( (string) $userId );
}
/**
* @param UserTuple $tuple
* @return string|boolean false if username is not found or display is suppressed
*/
public function getFromTuple( UserTuple $tuple ) {
return $this->get( $tuple->wiki, $tuple->id, $tuple->ip );
}
/**
* Resolve all queued user ids to usernames for the given wiki
*
* @param string $wiki
*/
public function resolve( $wiki ) {
if ( empty( $this->queued[$wiki] ) ) {
return;
}
$queued = array_unique( $this->queued[$wiki] );
if ( isset( $this->usernames[$wiki] ) ) {
$queued = array_diff( $queued, $this->usernames[$wiki]->getAllKeys() );
} else {
$this->ensureLRU( $wiki );
}
$res = $this->query->execute( $wiki, $queued );
unset( $this->queued[$wiki] );
if ( $res ) {
$usernames = array();
foreach ( $res as $row ) {
$id = (int)$row->user_id;
$usernames[$id] = $row->user_name;
$this->usernames[$wiki]->set( (string) $id, $row->user_name );
}
$this->resolveUserPages( $wiki, $usernames );
$missing = array_diff( $queued, array_keys( $usernames ) );
} else {
$missing = $queued;
}
foreach ( $missing as $id ) {
$this->usernames[$wiki]->set( (string) $id, false );
}
}
/**
* Update in-process title existence cache with NS_USER and
* NS_USER_TALK pages related to the provided usernames.
*
* @param string $wiki Wiki the users belong to
* @param array $usernames List of user names
*/
protected function resolveUserPages( $wiki, array $usernames ) {
// LinkBatch currently only supports the current wiki
if ( $wiki !== wfWikiID() || !$usernames ) {
return;
}
$lb = new \LinkBatch();
foreach ( $usernames as $name ) {
$user = User::newFromName( $name );
if ( $user ) {
$lb->addObj( $user->getUserPage() );
$lb->addObj( $user->getTalkPage() );
}
}
$lb->setCaller( __METHOD__ );
$lb->execute();
}
}