Index: trunk/extensions/Translate/Translate.php |
— | — | @@ -11,7 +11,7 @@ |
12 | 12 | * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License 2.0 or later |
13 | 13 | */ |
14 | 14 | |
15 | | -define( 'TRANSLATE_VERSION', '9 (2008-07-13:1)' ); |
| 15 | +define( 'TRANSLATE_VERSION', '9 (2008-07-13:2)' ); |
16 | 16 | |
17 | 17 | $wgExtensionCredits['specialpage'][] = array( |
18 | 18 | 'name' => 'Translate', |
Index: trunk/extensions/Translate/Stats.php |
— | — | @@ -13,11 +13,11 @@ |
14 | 14 | |
15 | 15 | |
16 | 16 | $opts = new FormOptions(); |
17 | | - $opts->add( 'language', 'en' ); |
| 17 | + $opts->add( 'language', '' ); |
18 | 18 | $opts->add( 'days', 30 ); |
19 | 19 | $opts->add( 'width', 600 ); |
20 | 20 | $opts->add( 'height', 400 ); |
21 | | - $opts->add( 'ts', 0 ); |
| 21 | + $opts->add( 'group', '' ); |
22 | 22 | $opts->fetchValuesFromRequest( $wgRequest ); |
23 | 23 | |
24 | 24 | $pars = explode( ';', $par ); |
— | — | @@ -33,7 +33,7 @@ |
34 | 34 | $opts->validateIntBounds( 'height', 200, 1000 ); |
35 | 35 | |
36 | 36 | $title = $this->getTitle(); |
37 | | - $cgiparams = wfArrayToCgi( array( 'ts' => time() ), $opts->getAllValues() ); |
| 37 | + $cgiparams = wfArrayToCgi( $opts->getAllValues() ); |
38 | 38 | $href = $title->getLocalUrl( $cgiparams ); |
39 | 39 | |
40 | 40 | |
— | — | @@ -48,16 +48,10 @@ |
49 | 49 | ) |
50 | 50 | ); |
51 | 51 | } else { |
52 | | - if ( $opts['ts'] === 0 ) { |
53 | | - $wgOut->redirect( $href ); |
54 | | - return; |
55 | | - } |
| 52 | + // Cache for two hours |
| 53 | + $lastMod = $wgOut->checkLastModified( wfTimestamp( TS_MW, time() - 2*3600 ) ); |
| 54 | + if ( $lastMod ) return; |
56 | 55 | |
57 | | - if ( time() - $opts['ts'] < 3600*2 ) { |
58 | | - $lastMod = $wgOut->checkLastModified( wfTimestamp( TS_MW, $opts['ts'] ) ); |
59 | | - if ( $lastMod ) return; |
60 | | - } |
61 | | - |
62 | 56 | $wgOut->disable(); |
63 | 57 | |
64 | 58 | if ( !class_exists('PHPlot') ) { |
— | — | @@ -78,36 +72,55 @@ |
79 | 73 | $cutoff = $now - ( 3600 * 24 * $opts->getValue('days') -1 ); |
80 | 74 | $cutoff -= ($cutoff % 86400); |
81 | 75 | $cutoffDb = $dbr->timestamp( $cutoff ); |
82 | | - $code = $dbr->escapeLike( $opts->getValue('language') ); |
83 | 76 | |
84 | | - $res = $dbr->select( |
85 | | - 'recentchanges', |
86 | | - 'rc_timestamp', |
87 | | - array( |
88 | | - "rc_timestamp >= '$cutoffDb'", |
89 | | - 'rc_namespace' => $wgTranslateMessageNamespaces, |
90 | | - "rc_title like '%%/$code'", |
91 | | - 'rc_bot' => 0 |
92 | | - ), |
93 | | - __METHOD__, |
94 | | - array( 'ORDER BY' => 'rc_timestamp' ) |
| 77 | + $so = new TranslatePerLanguageStats( $opts ); |
| 78 | + |
| 79 | + |
| 80 | + $tables = array( 'recentchanges' ); |
| 81 | + $fields = array( 'rc_timestamp' ); |
| 82 | + |
| 83 | + $conds = array( |
| 84 | + "rc_timestamp >= '$cutoffDb'", |
| 85 | + 'rc_namespace' => $wgTranslateMessageNamespaces, |
| 86 | + 'rc_bot' => 0 |
95 | 87 | ); |
96 | 88 | |
| 89 | + $type = __METHOD__; |
| 90 | + $options = array( 'ORDER BY' => 'rc_timestamp' ); |
| 91 | + |
| 92 | + $so->preQuery( $tables, $fields, $conds, $type, $options ); |
| 93 | + $res = $dbr->select( $tables, $fields, $conds, $type, $options ); |
| 94 | + |
| 95 | + |
| 96 | + // Initialisations |
| 97 | + $so->postQuery( $res ); |
| 98 | + |
97 | 99 | $data = array(); |
98 | 100 | while ( $cutoff < $now ) { |
99 | 101 | $date = $wgLang->sprintfDate( 'Y-m-d', wfTimestamp( TS_MW, $cutoff ) ); |
100 | | - $data[$date] = 0; |
| 102 | + $so->preProcess( $data[$date] ); |
101 | 103 | $cutoff += 24 * 3600; |
102 | 104 | } |
103 | 105 | |
| 106 | + // Processing |
104 | 107 | foreach ( $res as $row ) { |
105 | 108 | $date = $wgLang->sprintfDate( 'Y-m-d', $row->rc_timestamp ); |
106 | | - if ( !isset($data[$date]) ) $data[$date] = 0; |
107 | | - $data[$date]++; |
| 109 | + $index = $so->indexOf( $row ); |
| 110 | + if ( $index < 0 ) continue; |
| 111 | + |
| 112 | + if ( !isset($data[$date][$index]) ) $data[$date][$index] = 0; |
| 113 | + $data[$date][$index]++; |
108 | 114 | } |
109 | 115 | |
110 | | - return $data; |
| 116 | + $labels = null; |
| 117 | + if ( $opts['type'] === 'userlang' ) { |
| 118 | + $labels = @array_keys($usercache); |
| 119 | + } |
| 120 | + $so->labels( $labels ); |
111 | 121 | |
| 122 | + //var_dump( $data ); |
| 123 | + return array($labels, $data); |
| 124 | + |
112 | 125 | } |
113 | 126 | |
114 | 127 | public function draw( FormOptions $opts ) { |
— | — | @@ -118,9 +131,8 @@ |
119 | 132 | $height = $opts->getValue( 'height' ); |
120 | 133 | //Define the object |
121 | 134 | $plot = new PHPlot($width, $height); |
122 | | - $code = 'nl'; |
123 | 135 | |
124 | | - $resData = $this->getData($opts); |
| 136 | + list( $legend, $resData ) = $this->getData($opts); |
125 | 137 | $count = count($resData); |
126 | 138 | $skip = intval($count / ($width/60) -1); |
127 | 139 | $i = $count; |
— | — | @@ -128,13 +140,18 @@ |
129 | 141 | if ( $skip > 0 ) { |
130 | 142 | if ( ($count-$i)%$skip !== 0 ) { $date = ''; } |
131 | 143 | } |
132 | | - $data[] = array( $date, $edits ); |
| 144 | + array_unshift( $edits, $date ); |
| 145 | + $data[] = $edits; |
133 | 146 | $i--; |
134 | 147 | } |
135 | 148 | |
136 | 149 | $plot->SetDefaultTTFont($wgTranslatePHPlotFont); |
137 | 150 | |
138 | 151 | $plot->SetDataValues( $data ); |
| 152 | + |
| 153 | + if ( $legend !== null ) |
| 154 | + $plot->SetLegend($legend); |
| 155 | + |
139 | 156 | $plot->setFont( 'x_label', null, 8 ); |
140 | 157 | $plot->setFont( 'y_label', null, 8 ); |
141 | 158 | |
— | — | @@ -144,7 +161,7 @@ |
145 | 162 | $plot->SetXTickPos('none'); |
146 | 163 | $plot->SetXLabelAngle(45); |
147 | 164 | |
148 | | - $max = max( $resData ); |
| 165 | + $max = max( array_map( 'max', $resData ) ); |
149 | 166 | $yTick = 5; |
150 | 167 | while ( $max / $yTick > $height/20 ) $yTick *= 2; |
151 | 168 | |
— | — | @@ -159,4 +176,90 @@ |
160 | 177 | |
161 | 178 | } |
162 | 179 | |
| 180 | +} |
| 181 | + |
| 182 | + |
| 183 | +class TranslatePerLanguageStats { |
| 184 | + protected $opts; |
| 185 | + protected $cache; |
| 186 | + protected $index; |
| 187 | + protected $filters; |
| 188 | + |
| 189 | + public function __construct( FormOptions $opts ) { |
| 190 | + $this->opts = $opts; |
| 191 | + } |
| 192 | + |
| 193 | + public function preQuery( &$tables, &$fields, &$conds, &$type, &$options ) { |
| 194 | + $db = wfGetDb(); |
| 195 | + |
| 196 | + $groups = array_map( 'trim', explode(',', $this->opts['group']) ); |
| 197 | + $codes = array_map( 'trim', explode(',', $this->opts['language']) ); |
| 198 | + |
| 199 | + $filters['language'] = trim($this->opts['language']) !== ''; |
| 200 | + $filters['group'] = trim($this->opts['group']) !== ''; |
| 201 | + |
| 202 | + foreach ( $groups as $group ) |
| 203 | + foreach ( $codes as $code ) |
| 204 | + $this->cache[$group . $code] = count($this->cache); |
| 205 | + |
| 206 | + if ( $filters['language'] ) { |
| 207 | + $myconds = array(); |
| 208 | + foreach( $codes as $code ) { |
| 209 | + $myconds[] = 'rc_title like \'%%/' . $db->escapeLike( $code ) . "'"; |
| 210 | + } |
| 211 | + |
| 212 | + $conds[] = $db->makeList( $myconds, LIST_OR ); |
| 213 | + } |
| 214 | + |
| 215 | + if ( max($filters) ) $fields[] = 'rc_title'; |
| 216 | + if ( $filters['group'] ) $fields[] = 'rc_namespace'; |
| 217 | + |
| 218 | + $type .= '-perlang'; |
| 219 | + |
| 220 | + $this->filters = $filters; |
| 221 | + |
| 222 | + } |
| 223 | + |
| 224 | + public function postQuery( $rows ) {} |
| 225 | + |
| 226 | + public function preProcess( &$initial ) { |
| 227 | + $initial = array_pad( array(), max(1, count($this->cache)), 0 ); |
| 228 | + } |
| 229 | + |
| 230 | + public function indexOf( $row ) { |
| 231 | + global $wgContLang; |
| 232 | + |
| 233 | + if ( max($this->filters) === 0 ) return 0; |
| 234 | + if ( strpos( $row->rc_title, '/' ) === false ) return -1; |
| 235 | + |
| 236 | + list( $key, $code ) = explode('/', $wgContLang->lcfirst($row->rc_title), 2); |
| 237 | + $indexKey = ''; |
| 238 | + |
| 239 | + if ( $this->filters['group'] ) { |
| 240 | + if ( $this->index === null ) $this->index = TranslateUtils::messageIndex(); |
| 241 | + |
| 242 | + $key = strtolower($row->rc_namespace. ':' . $key); |
| 243 | + $group = @$this->index[$key]; |
| 244 | + if ( is_null($group) ) return -1; |
| 245 | + $indexKey .= $group; |
| 246 | + } |
| 247 | + |
| 248 | + if ( $this->filters['language'] ) { |
| 249 | + $indexKey .= $code; |
| 250 | + } |
| 251 | + |
| 252 | + |
| 253 | + if ( count($this->cache) > 1 ) { |
| 254 | + return isset($this->cache[$indexKey]) ? $this->cache[$indexKey] : -1; |
| 255 | + } else { |
| 256 | + return 0; |
| 257 | + } |
| 258 | + } |
| 259 | + |
| 260 | + public function labels( &$labels ) { |
| 261 | + if ( count($this->cache) > 1 ) { |
| 262 | + $labels = array_keys($this->cache); |
| 263 | + } |
| 264 | + } |
| 265 | + |
163 | 266 | } |
\ No newline at end of file |
Index: trunk/extensions/Translate/README |
— | — | @@ -34,6 +34,7 @@ |
35 | 35 | |
36 | 36 | == Changes in version 10 == |
37 | 37 | |
| 38 | +* 2008-07-13:2 group filter for graphs |
38 | 39 | * 2008-07-13:1 experimental alias-export for extensions |
39 | 40 | * 2008-07-08:1 simple edit stats with phplot |
40 | 41 | * 2008-07-05:1 fuzzy.php was ignoring the namespace |