From 7694c67c99fbc0eec72f5b8df18b45d529d9651b Mon Sep 17 00:00:00 2001 From: =?utf8?q?Niklas=20Laxstr=C3=B6m?= Date: Sat, 12 Feb 2011 20:40:40 +0000 Subject: [PATCH] * (bug 17160) Gender specific display text for User namespace Second attempt for this thing.. --- RELEASE-NOTES | 2 + includes/AutoLoader.php | 1 + includes/GenderCache.php | 119 ++++++++++++++++++++++++++++++ includes/LinkBatch.php | 15 ++++ includes/LocalisationCache.php | 2 +- includes/Namespace.php | 13 ++++ includes/Title.php | 7 ++ languages/Language.php | 31 ++++++++ languages/messages/MessagesEn.php | 10 +++ 9 files changed, 199 insertions(+), 1 deletion(-) create mode 100644 includes/GenderCache.php diff --git a/RELEASE-NOTES b/RELEASE-NOTES index 6b69b891ba..600dd6aaf1 100644 --- a/RELEASE-NOTES +++ b/RELEASE-NOTES @@ -176,6 +176,8 @@ MediaWiki supports over 330 languages. Many localisations are updated regularly. Below only new and removed languages are listed, as well as changes to languages because of Bugzilla reports. +* (bug 17160) Gender specific display text for User namespace + == Compatibility == MediaWiki 1.18 requires PHP 5.1 (5.2 recommended). PHP 4 is no longer diff --git a/includes/AutoLoader.php b/includes/AutoLoader.php index 1dc5e30087..198f279af6 100644 --- a/includes/AutoLoader.php +++ b/includes/AutoLoader.php @@ -98,6 +98,7 @@ $wgAutoloadLocalClasses = array( 'ForkController' => 'includes/ForkController.php', 'FormatExif' => 'includes/Exif.php', 'FormOptions' => 'includes/FormOptions.php', + 'GenderCache' => 'includes/GenderCache.php', 'GlobalDependency' => 'includes/CacheDependency.php', 'HashBagOStuff' => 'includes/BagOStuff.php', 'HashtableReplacer' => 'includes/StringUtils.php', diff --git a/includes/GenderCache.php b/includes/GenderCache.php new file mode 100644 index 0000000000..54ae60aead --- /dev/null +++ b/includes/GenderCache.php @@ -0,0 +1,119 @@ +default === null ) { + $this->default = User::getDefaultOption( 'gender' ); + } + return $this->default; + } + + /** + * Returns the gender for given username. + * @param $users 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. + */ + 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 = '' ) { + if ( count( $users ) === 0 ) return false; + + foreach ( (array) $users as $index => $value ) { + $users[$index] = strtr( $value, '_', ' ' ); + } + + $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 ); + + $default = $this->getDefault(); + foreach ( $res as $row ) { + $this->cache[$row->user_name] = $row->up_value ? $row->up_value : $default; + } + } + +} diff --git a/includes/LinkBatch.php b/includes/LinkBatch.php index 77c4edd1ce..9486815c95 100644 --- a/includes/LinkBatch.php +++ b/includes/LinkBatch.php @@ -94,6 +94,7 @@ class LinkBatch { wfProfileIn( __METHOD__ ); $res = $this->doQuery(); $ids = $this->addResultToCache( $cache, $res ); + $this->doGenderQuery(); wfProfileOut( __METHOD__ ); return $ids; } @@ -157,6 +158,20 @@ class LinkBatch { return $res; } + public function doGenderQuery() { + if ( $this->isEmpty() ) { + return false; + } + + global $wgContLang; + if ( !$wgContLang->needsGenderDistinction() ) { + return false; + } + + $genderCache = GenderCache::singleton(); + $genderCache->dolinkBatch( $this->data, $this->caller ); + } + /** * Construct a WHERE clause which will match all the given titles. * diff --git a/includes/LocalisationCache.php b/includes/LocalisationCache.php index d8551a0fb6..af2ed65ce5 100644 --- a/includes/LocalisationCache.php +++ b/includes/LocalisationCache.php @@ -87,7 +87,7 @@ class LocalisationCache { 'defaultUserOptionOverrides', 'linkTrail', 'namespaceAliases', 'dateFormats', 'datePreferences', 'datePreferenceMigrationMap', 'defaultDateFormat', 'extraUserToggles', 'specialPageAliases', - 'imageFiles', 'preloadedMessages', + 'imageFiles', 'preloadedMessages', 'namespaceGenderAliases', ); /** diff --git a/includes/Namespace.php b/includes/Namespace.php index 4753aaa411..2e4b789f4b 100644 --- a/includes/Namespace.php +++ b/includes/Namespace.php @@ -276,4 +276,17 @@ class MWNamespace { // Default to the global setting return $wgCapitalLinks; } + + /** + * Does the namespace (potentially) have different aliases for different + * genders. Not all languages make a distinction here. + * + * @since 1.18 + * @param $index int Index to check + * @return bool + */ + public static function hasGenderDistinction( $index ) { + return $index == NS_USER || $index == NS_USER_TALK; + } + } diff --git a/includes/Title.php b/includes/Title.php index 54e2dce3a3..e2e8dee67b 100644 --- a/includes/Title.php +++ b/includes/Title.php @@ -617,6 +617,13 @@ class Title { return MWNamespace::getCanonicalName( $this->mNamespace ); } } + + if ( $wgContLang->needsGenderDistinction() && + MWNamespace::hasGenderDistinction( $this->mNamespace ) ) { + $gender = GenderCache::singleton()->getGenderOf( $this->getText(), __METHOD__ ); + return $wgContLang->getGenderNsText( $this->mNamespace, $gender ); + } + return $wgContLang->getNsText( $this->mNamespace ); } diff --git a/languages/Language.php b/languages/Language.php index 50ac78ac6e..10bb29db79 100644 --- a/languages/Language.php +++ b/languages/Language.php @@ -338,6 +338,29 @@ class Language { return strtr( $ns, '_', ' ' ); } + /** + * Returns gender-dependent namespace alias if available. + * @param $index Int: namespace index + * @param $gender String: gender key (male, female... ) + * @return String + * @since 1.18 + */ + function getGenderNsText( $index, $gender ) { + $ns = self::$dataCache->getItem( $this->mCode, 'namespaceGenderAliases' ); + return isset( $ns[$index][$gender] ) ? $ns[$index][$gender] : $this->getNsText( $index ); + } + + /** + * Whether this language makes distinguishes genders for example in + * namespaces. + * @return bool + * @since 1.18 + */ + function needsGenderDistinction() { + $aliases = self::$dataCache->getItem( $this->mCode, 'namespaceGenderAliases' ); + return count( $aliases ) > 0; + } + /** * Get a namespace key by value, case insensitive. * Only matches namespace names for the current language, not the @@ -366,6 +389,14 @@ class Language { } } } + + $genders = self::$dataCache->getItem( $this->mCode, 'namespaceGenderAliases' ); + foreach ( $genders as $index => $forms ) { + foreach ( $forms as $alias ) { + $aliases[$alias] = $index; + } + } + $this->namespaceAliases = $aliases; } return $this->namespaceAliases; diff --git a/languages/messages/MessagesEn.php b/languages/messages/MessagesEn.php index 7e1fa32847..299d97806f 100644 --- a/languages/messages/MessagesEn.php +++ b/languages/messages/MessagesEn.php @@ -111,6 +111,16 @@ $namespaceNames = array( */ $namespaceAliases = array(); +/** + * Array of gender specific. namespace aliases. + * Mapping NS_xxx to array of GENDERKEY to alias. + * Example: +$namespaceGenderAliases = array( + NS_USER => array( 'male' => 'Male_user', 'female' => 'Female_user' ), +); + */ +$namespaceGenderAliases = array(); + /** * Deprecated, use the message array */ -- 2.20.1