MediaWiki  REL1_20
GenderCache.php
Go to the documentation of this file.
00001 <?php
00030 class GenderCache {
00031         protected $cache = array();
00032         protected $default;
00033         protected $misses = 0;
00034         protected $missLimit = 1000;
00035 
00039         public static function singleton() {
00040                 static $that = null;
00041                 if ( $that === null ) {
00042                         $that = new self();
00043                 }
00044                 return $that;
00045         }
00046 
00047         protected function __construct() {}
00048 
00053         protected function getDefault() {
00054                 if ( $this->default === null ) {
00055                         $this->default = User::getDefaultOption( 'gender' );
00056                 }
00057                 return $this->default;
00058         }
00059 
00066         public function getGenderOf( $username, $caller = '' ) {
00067                 global $wgUser;
00068 
00069                 if( $username instanceof User ) {
00070                         $username = $username->getName();
00071                 }
00072 
00073                 $username = self::normalizeUsername( $username );
00074                 if ( !isset( $this->cache[$username] ) ) {
00075 
00076                         if ( $this->misses >= $this->missLimit && $wgUser->getName() !== $username ) {
00077                                 if( $this->misses === $this->missLimit ) {
00078                                         $this->misses++;
00079                                         wfDebug( __METHOD__ . ": too many misses, returning default onwards\n" );
00080                                 }
00081                                 return $this->getDefault();
00082 
00083                         } else {
00084                                 $this->misses++;
00085                                 $this->doQuery( $username, $caller );
00086                         }
00087 
00088                 }
00089 
00090                 /* Undefined if there is a valid username which for some reason doesn't
00091                  * exist in the database.
00092                  */
00093                 return isset( $this->cache[$username] ) ? $this->cache[$username] : $this->getDefault();
00094         }
00095 
00102         public function doLinkBatch( $data, $caller = '' ) {
00103                 $users = array();
00104                 foreach ( $data as $ns => $pagenames ) {
00105                         if ( !MWNamespace::hasGenderDistinction( $ns ) ) continue;
00106                         foreach ( array_keys( $pagenames ) as $username ) {
00107                                 $users[$username] = true;
00108                         }
00109                 }
00110 
00111                 $this->doQuery( array_keys( $users ), $caller );
00112         }
00113 
00121         public function doTitlesArray( $titles, $caller = '' ) {
00122                 $users = array();
00123                 foreach ( $titles as $title ) {
00124                         $titleObj = is_string( $title ) ? Title::newFromText( $title ) : $title;
00125                         if ( !$titleObj ) {
00126                                 continue;
00127                         }
00128                         if ( !MWNamespace::hasGenderDistinction( $titleObj->getNamespace() ) ) {
00129                                 continue;
00130                         }
00131                         $users[] = $titleObj->getText();
00132                 }
00133 
00134                 $this->doQuery( $users, $caller );
00135         }
00136 
00142         public function doQuery( $users, $caller = '' ) {
00143                 $default = $this->getDefault();
00144 
00145                 $usersToCheck = array();
00146                 foreach ( (array) $users as $value ) {
00147                         $name = self::normalizeUsername( $value );
00148                         // Skip users whose gender setting we already know
00149                         if ( !isset( $this->cache[$name] ) ) {
00150                                 // For existing users, this value will be overwritten by the correct value
00151                                 $this->cache[$name] = $default;
00152                                 // query only for valid names, which can be in the database
00153                                 if( User::isValidUserName( $name ) ) {
00154                                         $usersToCheck[] = $name;
00155                                 }
00156                         }
00157                 }
00158 
00159                 if ( count( $usersToCheck ) === 0 ) {
00160                         return;
00161                 }
00162 
00163                 $dbr = wfGetDB( DB_SLAVE );
00164                 $table = array( 'user', 'user_properties' );
00165                 $fields = array( 'user_name', 'up_value' );
00166                 $conds = array( 'user_name' => $usersToCheck );
00167                 $joins = array( 'user_properties' =>
00168                         array( 'LEFT JOIN', array( 'user_id = up_user', 'up_property' => 'gender' ) ) );
00169 
00170                 $comment = __METHOD__;
00171                 if ( strval( $caller ) !== '' ) {
00172                         $comment .= "/$caller";
00173                 }
00174                 $res = $dbr->select( $table, $fields, $conds, $comment, array(), $joins );
00175 
00176                 foreach ( $res as $row ) {
00177                         $this->cache[$row->user_name] = $row->up_value ? $row->up_value : $default;
00178                 }
00179         }
00180 
00181         private static function normalizeUsername( $username ) {
00182                 // Strip off subpages
00183                 $indexSlash = strpos( $username, '/' );
00184                 if ( $indexSlash !== false ) {
00185                         $username = substr( $username, 0, $indexSlash );
00186                 }
00187                 // normalize underscore/spaces
00188                 return strtr( $username, '_', ' ' );
00189         }
00190 }