1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
|
<?php
/**
* Caches user genders when needed to use correct namespace aliases.
* @author Niklas Laxström
* @since 1.18
*/
class GenderCache {
protected $cache = array();
protected $default;
protected $misses = 0;
protected $missLimit = 1000;
/**
* @return GenderCache
*/
public static function singleton() {
static $that = null;
if ( $that === null ) {
$that = new self();
}
return $that;
}
protected function __construct() {}
/**
* Returns the default gender option in this wiki.
* @return String
*/
protected function getDefault() {
if ( $this->default === null ) {
$this->default = User::getDefaultOption( 'gender' );
}
return $this->default;
}
/**
* Returns the gender for given username.
* @param $username String: username
* @param $caller String: the calling method
* @return String
*/
public function getGenderOf( $username, $caller = '' ) {
global $wgUser;
$username = strtr( $username, '_', ' ' );
if ( !isset( $this->cache[$username] ) ) {
if ( $this->misses >= $this->missLimit && $wgUser->getName() !== $username ) {
if( $this->misses === $this->missLimit ) {
$this->misses++;
wfDebug( __METHOD__ . ": too many misses, returning default onwards\n" );
}
return $this->getDefault();
} else {
$this->misses++;
if ( !User::isValidUserName( $username ) ) {
$this->cache[$username] = $this->getDefault();
} else {
$this->doQuery( $username, $caller );
}
}
}
/* Undefined if there is a valid username which for some reason doesn't
* exist in the database.
*/
return isset( $this->cache[$username] ) ? $this->cache[$username] : $this->getDefault();
}
/**
* Wrapper for doQuery that processes raw LinkBatch data.
*
* @param $data
* @param $caller
*/
public function doLinkBatch( $data, $caller = '' ) {
$users = array();
foreach ( $data as $ns => $pagenames ) {
if ( !MWNamespace::hasGenderDistinction( $ns ) ) continue;
foreach ( array_keys( $pagenames ) as $username ) {
if ( isset( $this->cache[$username] ) ) continue;
$users[$username] = true;
}
}
$this->doQuery( array_keys( $users ), $caller );
}
/**
* Preloads genders for given list of users.
* @param $users List|String: usernames
* @param $caller String: the calling method
*/
public function doQuery( $users, $caller = '' ) {
$default = $this->getDefault();
foreach ( (array) $users as $index => $value ) {
$name = strtr( $value, '_', ' ' );
if ( isset( $this->cache[$name] ) ) {
// Skip users whose gender setting we already know
unset( $users[$index] );
} else {
$users[$index] = $name;
// For existing users, this value will be overwritten by the correct value
$this->cache[$name] = $default;
}
}
if ( count( $users ) === 0 ) {
return;
}
$dbr = wfGetDB( DB_SLAVE );
$table = array( 'user', 'user_properties' );
$fields = array( 'user_name', 'up_value' );
$conds = array( 'user_name' => $users );
$joins = array( 'user_properties' =>
array( 'LEFT JOIN', array( 'user_id = up_user', 'up_property' => 'gender' ) ) );
$comment = __METHOD__;
if ( strval( $caller ) !== '' ) {
$comment .= "/$caller";
}
$res = $dbr->select( $table, $fields, $conds, $comment, $joins, $joins );
foreach ( $res as $row ) {
$this->cache[$row->user_name] = $row->up_value ? $row->up_value : $default;
}
}
}
|