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