MediaWiki  REL1_22
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             if ( $this->misses >= $this->missLimit && $wgUser->getName() !== $username ) {
00076                 if ( $this->misses === $this->missLimit ) {
00077                     $this->misses++;
00078                     wfDebug( __METHOD__ . ": too many misses, returning default onwards\n" );
00079                 }
00080                 return $this->getDefault();
00081 
00082             } else {
00083                 $this->misses++;
00084                 $this->doQuery( $username, $caller );
00085             }
00086         }
00087 
00088         /* Undefined if there is a valid username which for some reason doesn't
00089          * exist in the database.
00090          */
00091         return isset( $this->cache[$username] ) ? $this->cache[$username] : $this->getDefault();
00092     }
00093 
00100     public function doLinkBatch( $data, $caller = '' ) {
00101         $users = array();
00102         foreach ( $data as $ns => $pagenames ) {
00103             if ( !MWNamespace::hasGenderDistinction( $ns ) ) {
00104                 continue;
00105             }
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 }