00001 <?php
00023 class StatsTable {
00025 protected $lang;
00027 protected $translate;
00029 protected $mainColumnHeader;
00031 protected $extraColumns = array();
00032
00033 public function __construct() {
00034 $this->lang = RequestContext::getMain()->getLanguage();
00035 $this->translate = SpecialPage::getTitleFor( 'Translate' );
00036 }
00037
00046 public function element( $in, $bgcolor = '', $sort = '' ) {
00047 $attributes = array();
00048
00049 if ( $sort ) {
00050 $attributes['data-sort-value'] = $sort;
00051 }
00052
00053 if ( $bgcolor ) {
00054 $attributes['style'] = "background-color: #" . $bgcolor;
00055 $attributes['class'] = 'hover-color';
00056 }
00057
00058 $element = Html::element( 'td', $attributes, $in );
00059
00060 return $element;
00061 }
00062
00063 public function getBackgroundColor( $subset, $total, $fuzzy = false ) {
00064 wfSuppressWarnings();
00065 $v = round( 255 * $subset / $total );
00066 wfRestoreWarnings();
00067
00068 if ( $fuzzy ) {
00069
00070 $v = $v * 20;
00071
00072 if ( $v > 255 ) {
00073 $v = 255;
00074 }
00075
00076 $v = 255 - $v;
00077 }
00078
00079 if ( $v < 128 ) {
00080
00081 $red = 'FF';
00082 $green = sprintf( '%02X', 2 * $v );
00083 } else {
00084
00085 $red = sprintf( '%02X', 2 * ( 255 - $v ) );
00086 $green = 'FF';
00087 }
00088 $blue = '00';
00089
00090 return $red . $green . $blue;
00091 }
00092
00093 public function getMainColumnHeader() {
00094 return $this->mainColumnHeader;
00095 }
00096
00097 public function setMainColumnHeader( Message $msg ) {
00098 $this->mainColumnHeader = $this->createColumnHeader( $msg );
00099 }
00100
00101 public function createColumnHeader( Message $msg ) {
00102 return Html::element( 'th', array(), $msg->text() );
00103 }
00104
00105 public function addExtraColumn( Message $column ) {
00106 $this->extraColumns[] = $column;
00107 }
00108
00109 public function getOtherColumnHeaders() {
00110 return array_merge( array(
00111 wfMessage( 'translate-total' ),
00112 wfMessage( 'translate-untranslated' ),
00113 wfMessage( 'translate-percentage-complete' ),
00114 wfMessage( 'translate-percentage-fuzzy' ),
00115 ), $this->extraColumns );
00116 }
00117
00118 public function createHeader() {
00119
00120 $out = Html::openElement(
00121 'table',
00122 array( 'class' => "statstable wikitable mw-sp-translate-table" )
00123 );
00124
00125 $out .= "\n\t" . Html::openElement( 'thead' );
00126 $out .= "\n\t" . Html::openElement( 'tr' );
00127
00128 $out .= "\n\t\t" . $this->getMainColumnHeader();
00129 foreach ( $this->getOtherColumnHeaders() as $label ) {
00130 $out .= "\n\t\t" . $this->createColumnHeader( $label );
00131 }
00132 $out .= "\n\t" . Html::closeElement( 'tr' );
00133 $out .= "\n\t" . Html::closeElement( 'thead' );
00134 $out .= "\n\t" . Html::openElement( 'tbody' );
00135
00136 return $out;
00137 }
00138
00145 public function makeTotalRow( Message $message, $stats ) {
00146 $out = "\t" . Html::openElement( 'tr' );
00147 $out .= "\n\t\t" . Html::element( 'td', array(), $message->text() );
00148 $out .= $this->makeNumberColumns( $stats );
00149 $out .= "\n\t" . Xml::closeElement( 'tr' ) . "\n";
00150
00151 return $out;
00152 }
00153
00159 public function makeNumberColumns( $stats ) {
00160 $total = $stats[MessageGroupStats::TOTAL];
00161 $translated = $stats[MessageGroupStats::TRANSLATED];
00162 $fuzzy = $stats[MessageGroupStats::FUZZY];
00163
00164 if ( $total === null ) {
00165 $na = "\n\t\t" . Html::element( 'td', array( 'data-sort-value' => -1 ), '...' );
00166 $nap = "\n\t\t" . $this->element( '...', 'AFAFAF', -1 );
00167 $out = $na . $na . $nap . $nap;
00168
00169 return $out;
00170 }
00171
00172 $out = "\n\t\t" . Html::element( 'td',
00173 array( 'data-sort-value' => $total ),
00174 $this->lang->formatNum( $total ) );
00175
00176 $out .= "\n\t\t" . Html::element( 'td',
00177 array( 'data-sort-value' => $total - $translated ),
00178 $this->lang->formatNum( $total - $translated ) );
00179
00180 if ( $total === 0 ) {
00181 $transRatio = 0;
00182 $fuzzyRatio = 0;
00183 } else {
00184 $transRatio = $translated / $total;
00185 $fuzzyRatio = $fuzzy / $total;
00186 }
00187
00188 $out .= "\n\t\t" . $this->element( $this->formatPercentage( $transRatio, 'floor' ),
00189 $this->getBackgroundColor( $translated, $total ),
00190 sprintf( '%1.5f', $transRatio ) );
00191
00192 $out .= "\n\t\t" . $this->element( $this->formatPercentage( $fuzzyRatio, 'ceil' ),
00193 $this->getBackgroundColor( $fuzzy, $total, true ),
00194 sprintf( '%1.5f', $fuzzyRatio ) );
00195
00196 return $out;
00197 }
00198
00205 public function formatPercentage( $num, $to = 'floor' ) {
00206 $num = $to === 'floor' ? floor( 100 * $num ) : ceil( 100 * $num );
00207 $fmt = $this->lang->formatNum( $num );
00208
00209 return wfMessage( 'percent', $fmt )->text();
00210 }
00211
00217 public function getGroupLabel( MessageGroup $group ) {
00218 $groupLabel = htmlspecialchars( $group->getLabel() );
00219
00220
00221 if ( $group->isMeta() ) {
00222 $groupLabel = Html::rawElement( 'b', array(), $groupLabel );
00223 }
00224
00225 return $groupLabel;
00226 }
00227
00235 public function makeGroupLink( MessageGroup $group, $code, $params ) {
00236 $queryParameters = $params + array(
00237 'group' => $group->getId(),
00238 'language' => $code
00239 );
00240
00241 $attributes = array(
00242 'title' => $this->getGroupDescription( $group )
00243 );
00244
00245 $translateGroupLink = Linker::link(
00246 $this->translate, $this->getGroupLabel( $group ), $attributes, $queryParameters
00247 );
00248
00249 return $translateGroupLink;
00250 }
00251
00258 public function getGroupDescription( MessageGroup $group ) {
00259 $code = $this->lang->getCode();
00260
00261 $cache = wfGetCache( CACHE_ANYTHING );
00262 $key = wfMemckey( "translate-groupdesc-$code-" . $group->getId() );
00263 $desc = $cache->get( $key );
00264
00265 if ( is_string( $desc ) ) {
00266 return $desc;
00267 }
00268
00269 $realFunction = array( 'MessageCache', 'singleton' );
00270
00271 if ( is_callable( $realFunction ) ) {
00272 $mc = MessageCache::singleton();
00273 } else {
00274 global $wgMessageCache;
00275
00276 $mc = $wgMessageCache;
00277 }
00278
00279 $desc = $mc->transform( $group->getDescription(), true, $this->lang );
00280 $cache->set( $key, $desc );
00281
00282 return $desc;
00283 }
00284
00292 public function isBlacklisted( $groupId, $code ) {
00293 global $wgTranslateBlacklist;
00294
00295 $blacklisted = null;
00296
00297 $checks = array(
00298 $groupId,
00299 strtok( $groupId, '-' ),
00300 '*'
00301 );
00302
00303 foreach ( $checks as $check ) {
00304 if ( isset( $wgTranslateBlacklist[$check] ) && isset( $wgTranslateBlacklist[$check][$code] ) ) {
00305 $blacklisted = $wgTranslateBlacklist[$check][$code];
00306 }
00307
00308 if ( $blacklisted !== null ) {
00309 break;
00310 }
00311 }
00312
00313 $group = MessageGroups::getGroup( $groupId );
00314 $languages = $group->getTranslatableLanguages();
00315 if ( $languages !== null && !isset( $languages[$code] ) ) {
00316 $blacklisted = true;
00317 }
00318
00319 $include = wfRunHooks( 'Translate:MessageGroupStats:isIncluded', array( $groupId, $code ) );
00320 if ( !$include ) {
00321 $blacklisted = true;
00322 }
00323
00324 return $blacklisted;
00325 }
00326
00333 public static function formatTooltip( $text ) {
00334 $wordSeparator = wfMessage( 'word-separator' )->text();
00335
00336 $text = strtr( $text, array(
00337 "\n" => $wordSeparator,
00338 "\r" => $wordSeparator,
00339 "\t" => $wordSeparator,
00340 ) );
00341
00342 return $text;
00343 }
00344 }