Index: branches/wmf/1.17wmf1/extensions/GoogleNewsSitemap/GoogleNewsSitemap_body.php |
— | — | @@ -0,0 +1,545 @@ |
| 2 | +<?php |
| 3 | +if ( !defined( 'MEDIAWIKI' ) ) die(); |
| 4 | + |
| 5 | +/** |
| 6 | + * Class googlenewssitemap creates Atom/RSS feeds for Wikinews |
| 7 | + ** |
| 8 | + * Simple feed using Atom/RSS coupled to DynamicPageList category searching. |
| 9 | + * |
| 10 | + * To use: http://wiki.url/Special:GoogleNewsSitemap?[paramter=value][¶meter2=value]&... |
| 11 | + * |
| 12 | + * Implemented parameters are marked with an @ |
| 13 | + ** |
| 14 | + * Parameters |
| 15 | + * * categories = string ; default = Published |
| 16 | + * * notcategories = string ; default = null |
| 17 | + * * namespace = string ; default = null |
| 18 | + * * count = integer ; default = $wgGNSMmaxResultCount = 50 |
| 19 | + * * hourcont = integer ; default -1 (disabled), how many hours before cutoff |
| 20 | + * * order = string ; default = descending |
| 21 | + * * ordermethod = string ; default = categoryadd |
| 22 | + * * redirects = string ; default = exclude |
| 23 | + * * stablepages = string ; default = null |
| 24 | + * * qualitypages = string ; default = null |
| 25 | + * * feed = string ; default = sitemap |
| 26 | + **/ |
| 27 | + |
| 28 | +class GoogleNewsSitemap extends SpecialPage { |
| 29 | + |
| 30 | + var $maxCacheTime = 43200; // 12 hours. Chosen rather arbitrarily for now. Might want to tweak. |
| 31 | + |
| 32 | + const OPT_INCLUDE = 0; |
| 33 | + const OPT_ONLY = 1; |
| 34 | + const OPT_EXCLUDE = 2; |
| 35 | + |
| 36 | + /** |
| 37 | + * Constructor |
| 38 | + **/ |
| 39 | + public function __construct() { |
| 40 | + parent::__construct( 'GoogleNewsSitemap' ); |
| 41 | + } |
| 42 | + |
| 43 | + /** |
| 44 | + * main() |
| 45 | + **/ |
| 46 | + public function execute( $par ) { |
| 47 | + global $wgContLang, $wgFeedClasses, |
| 48 | + $wgLanguageCode, $wgMemc, $wgOut, $wgGNSMsmaxage; |
| 49 | + |
| 50 | + list( $params, $categories, $notCategories ) = $this->getParams(); |
| 51 | + |
| 52 | + // if there's an error parsing the params, bail out and return |
| 53 | + if ( isset( $params['error'] ) ) { |
| 54 | + wfHttpError( 500, "Internal Server Error", $params['error'] ); |
| 55 | + return; |
| 56 | + } |
| 57 | + |
| 58 | + // Check to make sure that feed type is supported. |
| 59 | + if ( FeedUtils::checkFeedOutput( $params['feed'] ) ) { |
| 60 | + $feed = new $wgFeedClasses[ $params['feed'] ]( |
| 61 | + wfMsgExt( 'googlenewssitemap_feedtitle', |
| 62 | + array( 'parsemag', 'content' ), |
| 63 | + $wgContLang->getLanguageName( $wgLanguageCode ), |
| 64 | + $wgContLang->uc( $params['feed'] ), |
| 65 | + $wgLanguageCode |
| 66 | + ), |
| 67 | + wfMsgExt( 'tagline', array( 'parsemag', 'content') ), |
| 68 | + Title::newMainPage()->getFullUrl() |
| 69 | + ); |
| 70 | + } else { |
| 71 | + // FeedUtils outputs an error if wrong feed type. |
| 72 | + // So nothing else to do at this point |
| 73 | + return; |
| 74 | + } |
| 75 | + |
| 76 | + $wgOut->setSquidMaxage( $wgGNSMsmaxage ); |
| 77 | + |
| 78 | + $cacheInvalidationInfo = $this->getCacheInvalidationInfo( $params, |
| 79 | + $categories, $notCategories ); |
| 80 | + |
| 81 | + $cacheKey = $this->getCacheKey( $params, $categories, $notCategories ); |
| 82 | + |
| 83 | + // The way this does caching is based on ChangesFeed::execute. |
| 84 | + $cached = $this->getCachedVersion( $cacheKey, $cacheInvalidationInfo ); |
| 85 | + if ( $cached !== false ) { |
| 86 | + $feed->httpHeaders(); |
| 87 | + echo $cached; |
| 88 | + echo "<!-- From cache: $cacheKey -->"; |
| 89 | + } else { |
| 90 | + $res = $this->getCategories( $params, $categories, $notCategories ); |
| 91 | + ob_start(); |
| 92 | + $this->makeFeed( $feed, $res ); |
| 93 | + $output = ob_get_contents(); |
| 94 | + ob_end_flush(); |
| 95 | + echo "<!-- Not cached. Saved as: $cacheKey -->"; |
| 96 | + $wgMemc->set( $cacheKey, |
| 97 | + array( $cacheInvalidationInfo, $output ), |
| 98 | + $this->maxCacheTime |
| 99 | + ); |
| 100 | + } |
| 101 | + |
| 102 | + } |
| 103 | + |
| 104 | + /** |
| 105 | + * Get the cache key to cache this request. |
| 106 | + * @return String the key. |
| 107 | + */ |
| 108 | + private function getCacheKey( $params, $categories, $notCategories ) { |
| 109 | + global $wgRenderHashAppend; |
| 110 | + // Note, the implode relies on Title::__toString, which needs php > 5.2 |
| 111 | + // Which I think is above the minimum we support. |
| 112 | + $sum = md5( serialize( $params ) |
| 113 | + . implode( "|", $categories ) . "||" |
| 114 | + . implode( "|", $notCategories ) |
| 115 | + ); |
| 116 | + return wfMemcKey( "GNSM", $sum, $wgRenderHashAppend ); |
| 117 | + } |
| 118 | + |
| 119 | + /** |
| 120 | + * Get the cached version of the feed if possible. |
| 121 | + * Checks to see if the cached version is still valid. |
| 122 | + * |
| 123 | + * Note, this doesn't take into account changes to the keyword |
| 124 | + * mapping message (See getKeywords). I don't think that's a major issue. |
| 125 | + * |
| 126 | + * @param $key String Cache key |
| 127 | + * @param $invalidInfo String String to check if cache is clean from getCacheInvalidationInfo. |
| 128 | + * @return Mixed String or Boolean: The cached feed, or false. |
| 129 | + */ |
| 130 | + private function getCachedVersion ( $key, $invalidInfo ) { |
| 131 | + global $wgMemc, $wgRequest; |
| 132 | + $action = $wgRequest->getVal( 'action', 'view' ); |
| 133 | + if ( $action === 'purge' ) { |
| 134 | + return false; |
| 135 | + } |
| 136 | + |
| 137 | + $cached = $wgMemc->get( $key ); |
| 138 | + |
| 139 | + if ( !$cached |
| 140 | + || ( count( $cached ) !== 2 ) |
| 141 | + || ( $cached[0] !== $invalidInfo ) ) |
| 142 | + { |
| 143 | + // Cache is dirty or doesn't exist. |
| 144 | + return false; |
| 145 | + } |
| 146 | + return $cached[1]; |
| 147 | + } |
| 148 | + |
| 149 | + /** |
| 150 | + * Actually output a feed. |
| 151 | + * @param ChannelFeed $feed Feed object. |
| 152 | + * @param $res Result of sql query |
| 153 | + */ |
| 154 | + private function makeFeed( $feed, $res ) { |
| 155 | + global $wgGNSMcommentNamespace; |
| 156 | + $feed->outHeader(); |
| 157 | + foreach ( $res as $row ) { |
| 158 | + $title = Title::makeTitle( $row->page_namespace, $row->page_title ); |
| 159 | + |
| 160 | + if ( !$title ) { |
| 161 | + $feed->outFooter(); |
| 162 | + return; |
| 163 | + } |
| 164 | + |
| 165 | + // Fixme: Under what circumstance would cl_timestamp not be set? |
| 166 | + // possibly worth an exception if that happens. |
| 167 | + $pubDate = isset( $row->cl_timestamp ) ? $row->cl_timestamp : wfTimestampNow(); |
| 168 | + |
| 169 | + $feedItem = new FeedSMItem( |
| 170 | + $title, |
| 171 | + $pubDate, |
| 172 | + $this->getKeywords( $title ), |
| 173 | + $wgGNSMcommentNamespace |
| 174 | + ); |
| 175 | + $feed->outItem( $feedItem ); |
| 176 | + } |
| 177 | + $feed->outFooter(); |
| 178 | + } |
| 179 | + |
| 180 | + /** |
| 181 | + * Tries to determine if the cached version of the feed is still |
| 182 | + * good. Does this by checking the cl_timestamp of the latest article |
| 183 | + * in each category we're using (Which will be different if category added) |
| 184 | + * and the total pages in Category (Protect against an article being removed) |
| 185 | + * The first check (cl_timestamp) is needed to protect against someone removing |
| 186 | + * one article and adding another article (the page count would stay the same). |
| 187 | + * |
| 188 | + * When we save to cache, we save a two element array with this value and the feed. |
| 189 | + * If the value from this function doesn't match the value from the cache, we throw |
| 190 | + * out the cache. |
| 191 | + * |
| 192 | + * @param $params Array Parsed url parameters |
| 193 | + * @param $categories Array of Title |
| 194 | + * @param $notCategories Array of Title |
| 195 | + * |
| 196 | + * @return String All the above info concatenated. |
| 197 | + */ |
| 198 | + private function getCacheInvalidationInfo ( $params, $categories, $notCategories ) { |
| 199 | + $dbr = wfGetDB( DB_SLAVE ); |
| 200 | + $cacheInfo = ''; |
| 201 | + $categoriesKey = array(); |
| 202 | + $tsQueries = array(); |
| 203 | + |
| 204 | + // This would perhaps be nicer just using a Category object, |
| 205 | + // but this way can do all at once. |
| 206 | + |
| 207 | + // Add each category and notcategory to the query. |
| 208 | + for ( $i = 0; $i < $params['catCount']; $i++ ) { |
| 209 | + $key = $categories[$i]->getDBkey(); |
| 210 | + $categoriesKey[] = $key; |
| 211 | + $tsQueries[] = $dbr->selectSQLText( |
| 212 | + 'categorylinks', |
| 213 | + 'MAX(cl_timestamp) as ts', |
| 214 | + array( 'cl_to' => $key ), |
| 215 | + __METHOD__ |
| 216 | + ); |
| 217 | + } |
| 218 | + for ( $i = 0; $i < $params['notCatCount']; $i++ ) { |
| 219 | + $key = $notCategories[$i]->getDBkey(); |
| 220 | + $categoriesKey[] = $key; |
| 221 | + $tsQueries[] = $dbr->selectSQLText( |
| 222 | + 'categorylinks', |
| 223 | + 'MAX(cl_timestamp) AS ts', |
| 224 | + array( 'cl_to' => $key ), |
| 225 | + __METHOD__ |
| 226 | + ); |
| 227 | + } |
| 228 | + |
| 229 | + // phase 1: How many pages in each cat. |
| 230 | + // cat_pages includes all pages (even images/subcats). |
| 231 | + $res = $dbr->select( 'category', 'cat_pages', |
| 232 | + array( 'cat_title' => $categoriesKey ), |
| 233 | + __METHOD__, |
| 234 | + array( 'ORDER BY' => 'cat_title' ) |
| 235 | + ); |
| 236 | + |
| 237 | + foreach ( $res as $row ) { |
| 238 | + $cacheInfo .= $row->cat_pages . '!'; |
| 239 | + } |
| 240 | + |
| 241 | + $cacheInfo .= '|'; |
| 242 | + |
| 243 | + // Part 2: cl_timestamp: |
| 244 | + // TODO: Double check that the order of the result of union queries |
| 245 | + // is one after another from the order you specified the queries in. |
| 246 | + $res2 = $dbr->query($dbr->unionQueries( $tsQueries, true ), __METHOD__); |
| 247 | + |
| 248 | + foreach ( $res2 as $row ) { |
| 249 | + if ( is_null($row->ts) ) { |
| 250 | + $ts = "empty"; |
| 251 | + } else { |
| 252 | + $ts = wfTimestamp( TS_MW, $row->ts ); |
| 253 | + } |
| 254 | + $cacheInfo .= $ts . '!'; |
| 255 | + } |
| 256 | + |
| 257 | + return $cacheInfo; |
| 258 | + } |
| 259 | + /** |
| 260 | + * Build and execute sql |
| 261 | + * @param Array $param All the parameters except cats/notcats |
| 262 | + * @return Result of query. |
| 263 | + */ |
| 264 | + public function getCategories( $params, $categories, $notCategories ) { |
| 265 | + |
| 266 | + $dbr = wfGetDB( DB_SLAVE ); |
| 267 | + |
| 268 | + $tables[] = $dbr->tableName( 'page' ); |
| 269 | + |
| 270 | + // this is a little hacky, c1 is dynamically defined as the first category |
| 271 | + // so this can't ever work with uncategorized articles |
| 272 | + $fields = array( 'page_namespace', 'page_title', 'page_id', 'c1.cl_timestamp' ); |
| 273 | + $conditions = array(); |
| 274 | + |
| 275 | + if ( $params['namespace'] !== false ) { |
| 276 | + $conditions['page_namespace'] = $params['namespace']; |
| 277 | + } |
| 278 | + |
| 279 | + wfRunHooks('GoogleNewsSitemap::Query', array($params, &$joins, &$conditions)); |
| 280 | + |
| 281 | + switch ( $params['redirects'] ) { |
| 282 | + case self::OPT_ONLY: |
| 283 | + $conditions['page_is_redirect'] = 1; |
| 284 | + break; |
| 285 | + case self::OPT_EXCLUDE: |
| 286 | + $conditions['page_is_redirect'] = 0; |
| 287 | + break; |
| 288 | + } |
| 289 | + |
| 290 | + if ( $params['hourCount'] > 0 |
| 291 | + && $params['orderMethod'] !== 'lastedit' ) |
| 292 | + { |
| 293 | + // Limit to last X number of hours added to category, |
| 294 | + // if hourcont is positive and we're sorting by |
| 295 | + // category add date. |
| 296 | + // This feature is here because the Google News |
| 297 | + // Sitemap usecase is only supposed to have |
| 298 | + // articles published in last 2 days on it. |
| 299 | + // Don't do anything with lastedit, since this option |
| 300 | + // doesn't make sense with it (Do we even need that order method?) |
| 301 | + $timeOffset = wfTimestamp( TS_UNIX ) - ( $params['hourCount'] * 3600 ); |
| 302 | + $MWTimestamp = wfTimestamp( TS_MW, $timeOffset ); |
| 303 | + if ( $MWTimestamp ) { |
| 304 | + $conditions[] = 'c1.cl_timestamp > ' . $MWTimestamp; |
| 305 | + } |
| 306 | + } |
| 307 | + |
| 308 | + $currentTableNumber = 1; |
| 309 | + $categorylinks = $dbr->tableName( 'categorylinks' ); |
| 310 | + |
| 311 | + $joins = array(); |
| 312 | + for ( $i = 0; $i < $params['catCount']; $i++ ) { |
| 313 | + $joins["$categorylinks AS c$currentTableNumber"] = array( 'INNER JOIN', |
| 314 | + array( "page_id = c{$currentTableNumber}.cl_from", |
| 315 | + "c{$currentTableNumber}.cl_to={$dbr->addQuotes( $categories[$i]->getDBKey() ) }" |
| 316 | + ) |
| 317 | + ); |
| 318 | + $tables[] = "$categorylinks AS c$currentTableNumber"; |
| 319 | + $currentTableNumber++; |
| 320 | + } |
| 321 | + |
| 322 | + for ( $i = 0; $i < $params['notCatCount']; $i++ ) { |
| 323 | + $joins["$categorylinks AS c$currentTableNumber"] = array( 'LEFT OUTER JOIN', |
| 324 | + array( "page_id = c{$currentTableNumber}.cl_from", |
| 325 | + "c{$currentTableNumber}.cl_to={$dbr->addQuotes( $notCategories[$i]->getDBKey() ) }" |
| 326 | + ) |
| 327 | + ); |
| 328 | + $tables[] = "$categorylinks AS c$currentTableNumber"; |
| 329 | + $conditions[] = "c{$currentTableNumber}.cl_to IS NULL"; |
| 330 | + $currentTableNumber++; |
| 331 | + } |
| 332 | + |
| 333 | + if ( $params['order'] === 'descending' ) { |
| 334 | + $sortOrder = 'DESC'; |
| 335 | + } else { |
| 336 | + $sortOrder = 'ASC'; |
| 337 | + } |
| 338 | + |
| 339 | + if ( $params['orderMethod'] === 'lastedit' ) { |
| 340 | + $options['ORDER BY'] = 'page_touched ' . $sortOrder; |
| 341 | + } else { |
| 342 | + $options['ORDER BY'] = 'c1.cl_timestamp ' . $sortOrder; |
| 343 | + } |
| 344 | + |
| 345 | + |
| 346 | + // earlier validation logic ensures this is a reasonable number |
| 347 | + $options['LIMIT'] = $params['count']; |
| 348 | + |
| 349 | + return $dbr->select( $tables, $fields, $conditions, __METHOD__, $options, $joins ); |
| 350 | + } |
| 351 | + |
| 352 | + /** |
| 353 | + * Parse parameters, populates $params |
| 354 | + * @return Array containing the $params, $categories and $notCategories |
| 355 | + * variables that make up the request. |
| 356 | + **/ |
| 357 | + public function getParams() { |
| 358 | + global $wgContLang, $wgRequest, $wgGNSMmaxCategories, |
| 359 | + $wgGNSMmaxResultCount, $wgGNSMfallbackCategory; |
| 360 | + |
| 361 | + $params = array(); |
| 362 | + |
| 363 | + $categories = $this->getCatRequestArray( 'categories', $wgGNSMfallbackCategory, $wgGNSMmaxCategories ); |
| 364 | + $notCategories = $this->getCatRequestArray( 'notcategories', '', $wgGNSMmaxCategories ); |
| 365 | + |
| 366 | + $params['namespace'] = $this->getNS( $wgRequest->getVal( 'namespace', 0 ) ); |
| 367 | + |
| 368 | + $params['count'] = $wgRequest->getInt( 'count', $wgGNSMmaxResultCount ); |
| 369 | + $params['hourCount'] = $wgRequest->getInt( 'hourcount', -1 ); |
| 370 | + |
| 371 | + if ( ( $params['count'] > $wgGNSMmaxResultCount ) |
| 372 | + || ( $params['count'] < 1 ) ) |
| 373 | + { |
| 374 | + $params['count'] = $wgGNSMmaxResultCount; |
| 375 | + } |
| 376 | + |
| 377 | + $params['order'] = $wgRequest->getVal( 'order', 'descending' ); |
| 378 | + $params['orderMethod'] = $wgRequest->getVal( 'ordermethod', 'categoryadd' ); |
| 379 | + |
| 380 | + $params['redirects'] = $this->getIEOVal( 'redirects', self::OPT_EXCLUDE ); |
| 381 | + $params['stable'] = $this->getIEOVal( 'stable', self::OPT_ONLY ); |
| 382 | + $params['quality'] = $this->getIEOVal( 'qualitypages', self::OPT_ONLY ); |
| 383 | + |
| 384 | + // feed parameter is validated later in the execute method. |
| 385 | + $params['feed'] = $wgRequest->getVal( 'feed', 'sitemap' ); |
| 386 | + |
| 387 | + $params['catCount'] = count( $categories ); |
| 388 | + $params['notCatCount'] = count( $notCategories ); |
| 389 | + $totalCatCount = $params['catCount'] + $params['notCatCount']; |
| 390 | + |
| 391 | + if ( $params['catCount'] < 1 ) { |
| 392 | + // Always require at least one include category. |
| 393 | + // Without an include category, cl_timestamp will be null. |
| 394 | + // Which will probably manifest as a weird bug. |
| 395 | + $fallBack = Title::newFromText( $wgGNSMfallbackCategory, NS_CATEGORY ); |
| 396 | + if ( $fallBack ) { |
| 397 | + $categories[] = $fallBack; |
| 398 | + $params['catCount'] = count( $categories ); |
| 399 | + } else { |
| 400 | + throw new MWException( 'Default fallback category ($wgGNSMfallbackCategory) is not a valid title!' ); |
| 401 | + } |
| 402 | + } |
| 403 | + |
| 404 | + if ( $totalCatCount > $wgGNSMmaxCategories ) { |
| 405 | + // Causes a 500 error later on. |
| 406 | + $params['error'] = htmlspecialchars( wfMsg( 'googlenewssitemap_toomanycats' ) ); |
| 407 | + } |
| 408 | + return array( $params, $categories, $notCategories ); |
| 409 | + } |
| 410 | + |
| 411 | + /** |
| 412 | + * Turn an include, exclude, or only (I, E, or O) parameter into |
| 413 | + * a class constant. |
| 414 | + * @param $val String the name of the url parameter |
| 415 | + * @param $default Integer Class constant to return if none match |
| 416 | + * @return Integer Class constant corresponding to value. |
| 417 | + */ |
| 418 | + private function getIEOVal ( $valName, $default = self::OPT_INCLUDE ) { |
| 419 | + global $wgRequest; |
| 420 | + $val = $wgRequest->getVal( $valName ); |
| 421 | + switch ( $val ) { |
| 422 | + case 'only': |
| 423 | + return self::OPT_ONLY; |
| 424 | + case 'include': |
| 425 | + return self::OPT_INCLUDE; |
| 426 | + case 'exclude': |
| 427 | + return self::OPT_EXCLUDE; |
| 428 | + default: |
| 429 | + return $default; |
| 430 | + } |
| 431 | + } |
| 432 | + /** |
| 433 | + * Decode the namespace url parameter. |
| 434 | + * @param $ns String Either numeric ns number, ns name, or special value :all: |
| 435 | + * @return Mixed Integer or false Namespace number or false for no ns filtering. |
| 436 | + */ |
| 437 | + private function getNS ( $ns ) { |
| 438 | + global $wgContLang; |
| 439 | + |
| 440 | + $nsNumb = $wgContLang->getNsIndex( $ns ); |
| 441 | + |
| 442 | + if ( $nsNumb !== false ) { |
| 443 | + // If they specified something like Talk or Image. |
| 444 | + return $nsNumb; |
| 445 | + } else if ( is_numeric( $ns ) ) { |
| 446 | + // If they specified a number. |
| 447 | + $nsVal = intval( $ns ); |
| 448 | + if ( $nsVal >= 0 && MWNamespace::exists( $nsVal ) ) { |
| 449 | + return $nsVal; |
| 450 | + } else { |
| 451 | + wfDebug( __METHOD__ . ' Invalid numeric ns number. Using main.' ); |
| 452 | + return 0; |
| 453 | + } |
| 454 | + } else if ( $ns === ':all:' ) { |
| 455 | + // Need someway to denote no namespace filtering, |
| 456 | + // This seems as good as any since a namespace can't |
| 457 | + // have colons in it. |
| 458 | + return false; |
| 459 | + } else { |
| 460 | + // Default of main only if user gives bad input. |
| 461 | + // Note, this branch is only reached on bad input. Omitting |
| 462 | + // the namespace parameter is like saying namespace=0. |
| 463 | + wfDebug( __METHOD__ . ' Invalid (non-numeric) ns. Using main.' ); |
| 464 | + return 0; |
| 465 | + } |
| 466 | + |
| 467 | + } |
| 468 | + |
| 469 | + /** |
| 470 | + * Turn a pipe-separated list from a url parameter into an array. |
| 471 | + * Verifying each element would be a valid title in Category namespace. |
| 472 | + * @param String $name Parameter to retrieve from web reqeust. |
| 473 | + * @param String $default |
| 474 | + * @param Integer $max Maximum size of resulting array. |
| 475 | + * @return Array of Title objects. The Titles passed in the parameter $name. |
| 476 | + */ |
| 477 | + private function getCatRequestArray( $name, $default, $max ) { |
| 478 | + global $wgRequest; |
| 479 | + |
| 480 | + $value = $wgRequest->getText( $name, $default ); |
| 481 | + $arr = explode( "|", $value, $max + 2 ); |
| 482 | + $res = array(); |
| 483 | + foreach ( $arr as $name ) { |
| 484 | + $catTitle = Title::newFromText( $name, NS_CATEGORY ); |
| 485 | + if ( $catTitle ) { |
| 486 | + $res[] = $catTitle; |
| 487 | + } |
| 488 | + } |
| 489 | + return $res; |
| 490 | + } |
| 491 | + |
| 492 | + /** |
| 493 | + * Given a title, figure out what keywords. Use the message googlenewssitemap_categorymap |
| 494 | + * to map local categories to Google News Keywords. |
| 495 | + * |
| 496 | + * The format of this message is *Category name|What to map to |
| 497 | + * or *Category name|__MASK__ to hide the category completely. |
| 498 | + * |
| 499 | + * @see http://www.google.com/support/news_pub/bin/answer.py?answer=116037 |
| 500 | + * @param Title $title |
| 501 | + * @return Array of String: list of keywords |
| 502 | + */ |
| 503 | + public function getKeywords ( $title ) { |
| 504 | + $cats = $title->getParentCategories(); |
| 505 | + $res = array(); |
| 506 | + |
| 507 | + # the following code is based (stolen) from r56954 of flagged revs. |
| 508 | + $catMap = array(); |
| 509 | + $catMask = array(); |
| 510 | + if ( !wfEmptyMsg( 'googlenewssitemap_categorymap' ) ) { |
| 511 | + $msg = wfMsgForContent( 'googlenewssitemap_categorymap' ); |
| 512 | + $list = explode( "\n*", "\n$msg" ); |
| 513 | + foreach ( $list as $item ) { |
| 514 | + $mapping = explode( '|', $item, 2 ); |
| 515 | + if ( count( $mapping ) == 2 ) { |
| 516 | + |
| 517 | + $targetTitle = Title::newFromText( $mapping[0], NS_CATEGORY ); |
| 518 | + if ( !$targetTitle ) { |
| 519 | + continue; |
| 520 | + } |
| 521 | + $target = $targetTitle->getPrefixedDBkey(); |
| 522 | + $mapTo = trim( $mapping[1] ); |
| 523 | + |
| 524 | + if ( $mapTo === '__MASK__' ) { |
| 525 | + $catMask[$target] = true; |
| 526 | + } else { |
| 527 | + $catMap[$target] = $mapTo; |
| 528 | + } |
| 529 | + } |
| 530 | + } |
| 531 | + } |
| 532 | + foreach ( $cats as $cat => $val ) { |
| 533 | + if ( !isset( $catMask[$cat] ) ) { |
| 534 | + if ( isset( $catMap[$cat] ) ) { |
| 535 | + // Its mapped. |
| 536 | + $res[] = $catMap[$cat]; |
| 537 | + } else { |
| 538 | + // No mapping, so use just page name sans namespace. |
| 539 | + $cTitle = Title::newFromText( $cat ); |
| 540 | + $res[] = $cTitle->getText(); |
| 541 | + } |
| 542 | + } |
| 543 | + } |
| 544 | + return $res; |
| 545 | + } |
| 546 | +} |
Property changes on: branches/wmf/1.17wmf1/extensions/GoogleNewsSitemap/GoogleNewsSitemap_body.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 547 | + native |
Index: branches/wmf/1.17wmf1/extensions/GoogleNewsSitemap/GoogleNewsSitemap.i18n.php |
— | — | @@ -0,0 +1,567 @@ |
| 2 | +<?php |
| 3 | +/** |
| 4 | + * Internationalisation file for extension special page GoogleNewsSitemap |
| 5 | + * New version of DynamicPageList extension for use by Wikinews projects |
| 6 | + * |
| 7 | + * @file |
| 8 | + * @ingroup Extensions |
| 9 | + */ |
| 10 | + |
| 11 | +$messages = array(); |
| 12 | + |
| 13 | +/** English |
| 14 | + * @author Amgine |
| 15 | + */ |
| 16 | + |
| 17 | +$messages['en'] = array( |
| 18 | + 'googlenewssitemap' => 'Google News Sitemap', |
| 19 | + 'googlenewssitemap-desc' => 'Outputs an Atom/RSS feed as a Google News Sitemap', |
| 20 | + 'googlenewssitemap_categorymap' => '', # Default empty. List of categories to map to keywords. Do not translate. |
| 21 | + 'googlenewssitemap_toomanycats' => 'Error: Too many categories!', |
| 22 | + 'googlenewssitemap_feedtitle' => '$1 {{SITENAME}} $2 feed.' |
| 23 | +); |
| 24 | + |
| 25 | +/** Message documentation (Message documentation) |
| 26 | + * @author Raymond |
| 27 | + * @author Umherirrender |
| 28 | + */ |
| 29 | +$messages['qqq'] = array( |
| 30 | + 'googlenewssitemap-desc' => '{{desc}}', |
| 31 | + 'googlenewssitemap_toomanycats' => 'Error given when maximum amount of categories specified is exceeded. Default max is 6.', |
| 32 | + 'googlenewssitemap_feedtitle' => 'Title for the RSS/ATOM feeds produced (does not appear in sitemap XML documents). |
| 33 | +*$1 is language name (like English) |
| 34 | +*$2 is feed type (RSS or ATOM) |
| 35 | +*$3 is language code (like en)', |
| 36 | +); |
| 37 | + |
| 38 | +/** Afrikaans (Afrikaans) |
| 39 | + * @author Naudefj |
| 40 | + */ |
| 41 | +$messages['af'] = array( |
| 42 | + 'googlenewssitemap' => 'Google Nuus Sitemap', |
| 43 | + 'googlenewssitemap-desc' => 'Eksporteer \'n Atom/RSS-voer as \'n Google "News Sitemap"', |
| 44 | + 'googlenewssitemap_toomanycats' => 'Fout: Te veel kategorieë!', |
| 45 | + 'googlenewssitemap_toofewcats' => 'Fout: Te min kategorieë!', |
| 46 | + 'googlenewssitemap_noresults' => 'Fout: Geen resultate!', |
| 47 | + 'googlenewssitemap_noincludecats' => "Fout: U moet ten minste een kategorie insluit, of spesifiseer 'n naamspasie!", |
| 48 | +); |
| 49 | + |
| 50 | +/** Azerbaijani (Azərbaycanca) |
| 51 | + * @author Wertuose |
| 52 | + */ |
| 53 | +$messages['az'] = array( |
| 54 | + 'googlenewssitemap_toomanycats' => 'Xəta: Kateqoriya sayı həddindən çoxdur!', |
| 55 | +); |
| 56 | + |
| 57 | +/** Belarusian (Taraškievica orthography) (Беларуская (тарашкевіца)) |
| 58 | + * @author EugeneZelenko |
| 59 | + * @author Jim-by |
| 60 | + * @author Wizardist |
| 61 | + */ |
| 62 | +$messages['be-tarask'] = array( |
| 63 | + 'googlenewssitemap' => 'Мапа сайту Google News', |
| 64 | + 'googlenewssitemap-desc' => 'Выводзіць стужкі Atom/RSS у выглядзе мапы сайту Google News', |
| 65 | + 'googlenewssitemap_toomanycats' => 'Памылка: зашмат катэгорыяў!', |
| 66 | + 'googlenewssitemap_feedtitle' => '$1 {{SITENAME}} стужка $2.', |
| 67 | +); |
| 68 | + |
| 69 | +/** Bulgarian (Български) |
| 70 | + * @author DCLXVI |
| 71 | + */ |
| 72 | +$messages['bg'] = array( |
| 73 | + 'googlenewssitemap_noresults' => 'Грешка: Няма резултати!', |
| 74 | +); |
| 75 | + |
| 76 | +/** Breton (Brezhoneg) |
| 77 | + * @author Fohanno |
| 78 | + * @author Fulup |
| 79 | + * @author Y-M D |
| 80 | + */ |
| 81 | +$messages['br'] = array( |
| 82 | + 'googlenewssitemap' => "Steuñvenn lec'hienn Keleier Google", |
| 83 | + 'googlenewssitemap-desc' => "Krouiñ a ra ul lanvad Atom/RSS evel steuñvenn ul lec'hienn Keleier Google", |
| 84 | + 'googlenewssitemap_toomanycats' => 'Fazi : Re a rummadoù !', |
| 85 | + 'googlenewssitemap_feedtitle' => 'Lanvad roadennoù $2 eus {{SITENAME}} e $1.', |
| 86 | +); |
| 87 | + |
| 88 | +/** Bosnian (Bosanski) |
| 89 | + * @author CERminator |
| 90 | + */ |
| 91 | +$messages['bs'] = array( |
| 92 | + 'googlenewssitemap' => 'Google News mapa stranice', |
| 93 | + 'googlenewssitemap-desc' => 'Daje izlaz atom/RSS fida kao Google News mapa stranice', |
| 94 | + 'googlenewssitemap_toomanycats' => 'Greška: Previše kategorija!', |
| 95 | + 'googlenewssitemap_feedtitle' => '$1 {{SITENAME}} $2 fid.', |
| 96 | +); |
| 97 | + |
| 98 | +/** Catalan (Català) |
| 99 | + * @author Aleator |
| 100 | + * @author Davidpar |
| 101 | + * @author Paucabot |
| 102 | + */ |
| 103 | +$messages['ca'] = array( |
| 104 | + 'googlenewssitemap' => 'Mapa del lloc Google News', |
| 105 | + 'googlenewssitemap-desc' => 'Fes sortir un Atom/RSS feed com a Google News Sitemap', |
| 106 | + 'googlenewssitemap_toomanycats' => 'Error: Massa categories!', |
| 107 | + 'googlenewssitemap_toofewcats' => 'Error: Massa poques categories!', |
| 108 | + 'googlenewssitemap_noresults' => 'Error: Cap resultat!', |
| 109 | + 'googlenewssitemap_noincludecats' => "Error: Heu d'incloure almenys una categoria o especificar un espai de noms!", |
| 110 | + 'googlenewssitemap_badfeedobject' => '$feed no és un objecte.', |
| 111 | +); |
| 112 | + |
| 113 | +/** German (Deutsch) |
| 114 | + * @author Kghbln |
| 115 | + * @author McDutchie |
| 116 | + */ |
| 117 | +$messages['de'] = array( |
| 118 | + 'googlenewssitemap' => 'Ermöglicht eine Sitemap für „Google News“', |
| 119 | + 'googlenewssitemap-desc' => 'Gibt Atom/RSS-Feeds in Form einer Sitemap für Google News aus.', |
| 120 | + 'googlenewssitemap_toomanycats' => 'Fehler: Zu viele Kategorien!', |
| 121 | + 'googlenewssitemap_feedtitle' => '$1 {{SITENAME}} $2-Feed.', |
| 122 | +); |
| 123 | + |
| 124 | +/** Lower Sorbian (Dolnoserbski) |
| 125 | + * @author Michawiki |
| 126 | + */ |
| 127 | +$messages['dsb'] = array( |
| 128 | + 'googlenewssitemap' => 'Sedłowy pśeglěd Google Nowosći', |
| 129 | + 'googlenewssitemap-desc' => 'Wudawa kanal Atom/RSS ako sedłowy pśeglěd Google Nowosći', |
| 130 | + 'googlenewssitemap_toomanycats' => 'Zmólka: Pśewjele kategorijow!', |
| 131 | + 'googlenewssitemap_toofewcats' => 'Zmólka: Pśemało kategorijow!', |
| 132 | + 'googlenewssitemap_noresults' => 'Zmólka: Žedne wuslědki!', |
| 133 | + 'googlenewssitemap_noincludecats' => 'Zmólka: Musyš nanejmjenjej jadnu kategoriju zapśěgnuś abo mjenjowy rum pódaś!', |
| 134 | + 'googlenewssitemap_badfeedobject' => '$feed njejo objekt.', |
| 135 | +); |
| 136 | + |
| 137 | +/** Greek (Ελληνικά) |
| 138 | + * @author Περίεργος |
| 139 | + */ |
| 140 | +$messages['el'] = array( |
| 141 | + 'googlenewssitemap' => 'Χάρτης Ειδήσεων της Google', |
| 142 | + 'googlenewssitemap-desc' => 'Βγάζει το Χάρτη Ειδήσεων της Google ως Atom/RSS', |
| 143 | + 'googlenewssitemap_toomanycats' => 'Σφάλμα: Υπερβολικά πολλές κατηγορίες!', |
| 144 | + 'googlenewssitemap_toofewcats' => 'Σφάλμα: Υπερβολικά λίγες κατηγορίες!', |
| 145 | + 'googlenewssitemap_noresults' => 'Σφάλμα: Δεν υπάρχουν αποτελέσματα!', |
| 146 | + 'googlenewssitemap_noincludecats' => 'Σφάλμα: Χρειάζεται να συμπεριλάβετε τουλάχιστον μια κατηγορία, ή να προσδιορίσετε μια περιοχή ονομάτων!', |
| 147 | +); |
| 148 | + |
| 149 | +/** Esperanto (Esperanto) |
| 150 | + * @author Yekrats |
| 151 | + */ |
| 152 | +$messages['eo'] = array( |
| 153 | + 'googlenewssitemap' => 'Retmapo de Google-Aktualaĵoj', |
| 154 | + 'googlenewssitemap-desc' => 'Generas Atom aŭ RSS retfluon kiel Retmapo de Google-Aktualaĵoj', |
| 155 | + 'googlenewssitemap_toomanycats' => 'Eraro: Tro da kategorioj!', |
| 156 | + 'googlenewssitemap_toofewcats' => 'Eraro: Tro malmultaj da kategorioj!', |
| 157 | + 'googlenewssitemap_noresults' => 'Eraro: Neniuj rezultoj!', |
| 158 | + 'googlenewssitemap_noincludecats' => 'Eraro: Vi devas inkluzivi almenaŭ unu kategorio, aŭ specifigu nomspacon!', |
| 159 | +); |
| 160 | + |
| 161 | +/** Spanish (Español) |
| 162 | + * @author Translationista |
| 163 | + */ |
| 164 | +$messages['es'] = array( |
| 165 | + 'googlenewssitemap' => 'Mapa del sitio Google Noticias', |
| 166 | + 'googlenewssitemap-desc' => 'Genera una fuenteAtom/RSS como un mapa de sitio de Google Noticias', |
| 167 | + 'googlenewssitemap_toomanycats' => 'Error: ¡Demasiadas categorías!', |
| 168 | + 'googlenewssitemap_toofewcats' => 'Error: ¡Muy pocas categorías!', |
| 169 | + 'googlenewssitemap_noresults' => 'Error: ¡No hay resultados!', |
| 170 | + 'googlenewssitemap_noincludecats' => 'Error: ¡Es necesario incluir al menos una categoría o especificar un espacio de nombres!', |
| 171 | +); |
| 172 | + |
| 173 | +/** Basque (Euskara) |
| 174 | + * @author An13sa |
| 175 | + */ |
| 176 | +$messages['eu'] = array( |
| 177 | + 'googlenewssitemap' => 'Google News Gunearen mapa', |
| 178 | + 'googlenewssitemap-desc' => 'Atom/RSS iturria zehazten du Google News Gunearen maparentzat', |
| 179 | + 'googlenewssitemap_toomanycats' => 'Errorea: Kategoria gehiegi!', |
| 180 | + 'googlenewssitemap_toofewcats' => 'Errorea: Kategoria gutxiegi!', |
| 181 | + 'googlenewssitemap_noresults' => 'Errorea: Emaitzarik ez!', |
| 182 | + 'googlenewssitemap_noincludecats' => 'Errorea: Gutxienez kategoria bat gehitu edo izen bat zehaztu behar duzu!', |
| 183 | +); |
| 184 | + |
| 185 | +/** Finnish (Suomi) |
| 186 | + * @author Centerlink |
| 187 | + * @author Crt |
| 188 | + */ |
| 189 | +$messages['fi'] = array( |
| 190 | + 'googlenewssitemap' => 'Google News -sivukartta', |
| 191 | + 'googlenewssitemap-desc' => 'Tulostaa Atom/RSS-syötteen Google-uutissivukarttana', |
| 192 | + 'googlenewssitemap_toomanycats' => 'Virhe: Liian monta luokkaa.', |
| 193 | + 'googlenewssitemap_toofewcats' => 'Virhe: Liian vähän luokkia.', |
| 194 | + 'googlenewssitemap_noresults' => 'Virhe: Ei tuloksia.', |
| 195 | + 'googlenewssitemap_noincludecats' => 'Error: Lisää vähintään yksi luokka tai määritä nimiavaruus.', |
| 196 | +); |
| 197 | + |
| 198 | +/** French (Français) |
| 199 | + * @author Amgine |
| 200 | + * @author McDutchie |
| 201 | + * @author Sherbrooke |
| 202 | + */ |
| 203 | +$messages['fr'] = array( |
| 204 | + 'googlenewssitemap' => 'Plan du site Google News', |
| 205 | + 'googlenewssitemap-desc' => 'Crée un flux de données Atom ou RSS ressemblant à un plan de site pour Google News', |
| 206 | + 'googlenewssitemap_toomanycats' => 'Erreur: Trop de catégories!', |
| 207 | + 'googlenewssitemap_feedtitle' => 'Flux de données $2 du {{SITENAME}} en $1.', |
| 208 | +); |
| 209 | + |
| 210 | +/** Galician (Galego) |
| 211 | + * @author Toliño |
| 212 | + */ |
| 213 | +$messages['gl'] = array( |
| 214 | + 'googlenewssitemap' => 'Mapa do sitio das novas do Google', |
| 215 | + 'googlenewssitemap-desc' => 'Dá como resultado unha fonte de novas Atom/RSS como un mapa do sitio das novas do Google', |
| 216 | + 'googlenewssitemap_toomanycats' => 'Erro: hai moitas categorías!', |
| 217 | + 'googlenewssitemap_feedtitle' => 'Fonte de novas $2 de {{SITENAME}} en $1.', |
| 218 | +); |
| 219 | + |
| 220 | +/** Swiss German (Alemannisch) |
| 221 | + * @author Als-Holder |
| 222 | + */ |
| 223 | +$messages['gsw'] = array( |
| 224 | + 'googlenewssitemap' => 'Google Nejigkeite Sytenibersicht', |
| 225 | + 'googlenewssitemap-desc' => 'Liferet e Atom/RSS-feed as Google Nejigkeite Sytenibersicht', |
| 226 | + 'googlenewssitemap_toomanycats' => 'Fähler: z vil Kategorie!', |
| 227 | + 'googlenewssitemap_feedtitle' => '$1 {{SITENAME}} $2-Feed.', |
| 228 | +); |
| 229 | + |
| 230 | +/** Hebrew (עברית) |
| 231 | + * @author Amire80 |
| 232 | + * @author YaronSh |
| 233 | + */ |
| 234 | +$messages['he'] = array( |
| 235 | + 'googlenewssitemap' => 'מפת אתר לפי Google News', |
| 236 | + 'googlenewssitemap-desc' => 'יצוא הזנת Atom/RSS בתור מפת אתר ל־Google News', |
| 237 | + 'googlenewssitemap_toomanycats' => 'שגיאה: יותר מדי קטגוריות!', |
| 238 | + 'googlenewssitemap_feedtitle' => 'הזנת $2 מאתר {{SITENAME}} ב{{GRAMMAR:תחילית|$1}}', |
| 239 | +); |
| 240 | + |
| 241 | +/** Upper Sorbian (Hornjoserbsce) |
| 242 | + * @author Michawiki |
| 243 | + */ |
| 244 | +$messages['hsb'] = array( |
| 245 | + 'googlenewssitemap' => 'Sydłowa přehlad Google Nowinki', |
| 246 | + 'googlenewssitemap-desc' => 'Wudawa kanal Atom/RSS jako sydłowy přehlad Google Nowinki', |
| 247 | + 'googlenewssitemap_toomanycats' => 'Zmylk: Přewjele kategorijow!', |
| 248 | + 'googlenewssitemap_feedtitle' => '$1 {{SITENAME}} kanal $2.', |
| 249 | +); |
| 250 | + |
| 251 | +/** Hungarian (Magyar) |
| 252 | + * @author Glanthor Reviol |
| 253 | + */ |
| 254 | +$messages['hu'] = array( |
| 255 | + 'googlenewssitemap' => 'Google hírek oldaltérkép', |
| 256 | + 'googlenewssitemap-desc' => 'Atom/RSS hírcsatornát készít Google hírek oldaltérképként', |
| 257 | + 'googlenewssitemap_toomanycats' => 'Hiba: túl sok kategória!', |
| 258 | + 'googlenewssitemap_toofewcats' => 'Hiba: túl kevés kategória!', |
| 259 | + 'googlenewssitemap_noresults' => 'Hiba: nincs találat!', |
| 260 | + 'googlenewssitemap_noincludecats' => 'Hiba: legalább egy kategóriát vagy névteret meg kell adnod!', |
| 261 | +); |
| 262 | + |
| 263 | +/** Interlingua (Interlingua) |
| 264 | + * @author McDutchie |
| 265 | + */ |
| 266 | +$messages['ia'] = array( |
| 267 | + 'googlenewssitemap' => 'Sitemap de Google News', |
| 268 | + 'googlenewssitemap-desc' => 'Converte un syndication Atom/RSS in un Sitemap de Google News', |
| 269 | + 'googlenewssitemap_toomanycats' => 'Error: Troppo de categorias!', |
| 270 | + 'googlenewssitemap_feedtitle' => 'Syndication $2 de {{SITENAME}} in $1.', |
| 271 | +); |
| 272 | + |
| 273 | +/** Indonesian (Bahasa Indonesia) |
| 274 | + * @author IvanLanin |
| 275 | + * @author Iwan Novirion |
| 276 | + * @author Kenrick95 |
| 277 | + */ |
| 278 | +$messages['id'] = array( |
| 279 | + 'googlenewssitemap' => 'Petasitus Baru Google', |
| 280 | + 'googlenewssitemap-desc' => 'Hasil dari Atom/RSS feed sebagai Petasitus Baru Google', |
| 281 | + 'googlenewssitemap_toomanycats' => 'Kesalahan: Terlalu banyak kategori!', |
| 282 | + 'googlenewssitemap_feedtitle' => 'Umpan $2 $1 {{SITENAME}}.', |
| 283 | +); |
| 284 | + |
| 285 | +/** Italian (Italiano) |
| 286 | + * @author Beta16 |
| 287 | + */ |
| 288 | +$messages['it'] = array( |
| 289 | + 'googlenewssitemap_toomanycats' => 'Errore: Numero di categorie eccessivo!', |
| 290 | + 'googlenewssitemap_toofewcats' => 'Errore: Troppe poche categorie!', |
| 291 | + 'googlenewssitemap_noresults' => 'Errore: Nessun risultato.', |
| 292 | + 'googlenewssitemap_noincludecats' => 'Errore: È necessario includere almeno una categoria oppure specificare un namespace!', |
| 293 | +); |
| 294 | + |
| 295 | +/** Japanese (日本語) |
| 296 | + * @author Hosiryuhosi |
| 297 | + * @author Naohiro19 |
| 298 | + * @author Ohgi |
| 299 | + */ |
| 300 | +$messages['ja'] = array( |
| 301 | + 'googlenewssitemap' => 'Google ニュース サイトマップ', |
| 302 | + 'googlenewssitemap-desc' => 'Google ニュースのサイトマップからAtom/RSSフィードを出力', |
| 303 | + 'googlenewssitemap_toomanycats' => 'エラー: カテゴリが多すぎです!', |
| 304 | + 'googlenewssitemap_toofewcats' => 'エラー:カテゴリが少なすぎです!', |
| 305 | + 'googlenewssitemap_noresults' => 'エラー:結果はありません!', |
| 306 | + 'googlenewssitemap_noincludecats' => 'エラー:少なくとも1つのカテゴリまたは名前空間を指定する必要があります!', |
| 307 | + 'googlenewssitemap_badfeedobject' => '$feedは変更対象ではありません。', |
| 308 | +); |
| 309 | + |
| 310 | +/** Colognian (Ripoarisch) |
| 311 | + * @author Purodha |
| 312 | + */ |
| 313 | +$messages['ksh'] = array( |
| 314 | + 'googlenewssitemap' => '<i lang="en">Google News Sitemap</i>', |
| 315 | + 'googlenewssitemap-desc' => 'Deiht ene <i lang="en">Atom</i> udder <i lang="en">RSS</i>-Kanaal als en <i lang="en">Google News Sitemap</i> ußjävve.', |
| 316 | + 'googlenewssitemap_toomanycats' => 'Fähler: Zoh vill Saachjroppe!', |
| 317 | + 'googlenewssitemap_feedtitle' => '{{ucfirst:{{GRAMMAR:Genitive iere male|{{SITENAME}}}}}} <i lang="en">$2</i> Kanaal op $1', |
| 318 | +); |
| 319 | + |
| 320 | +/** Luxembourgish (Lëtzebuergesch) |
| 321 | + * @author Robby |
| 322 | + */ |
| 323 | +$messages['lb'] = array( |
| 324 | + 'googlenewssitemap' => 'Google News Plang vum Site', |
| 325 | + 'googlenewssitemap-desc' => 'Produzéiert en Atom/RSS feed als Google News Sitemap', |
| 326 | + 'googlenewssitemap_toomanycats' => 'Feeler: Zevill Kategorien!', |
| 327 | + 'googlenewssitemap_feedtitle' => '$1 {{SITENAME}} $2-Feed.', |
| 328 | +); |
| 329 | + |
| 330 | +/** Macedonian (Македонски) |
| 331 | + * @author Bjankuloski06 |
| 332 | + */ |
| 333 | +$messages['mk'] = array( |
| 334 | + 'googlenewssitemap' => 'План на страницата Google Вести', |
| 335 | + 'googlenewssitemap-desc' => 'Дава Atom/RSS канал како план на страницата Google Вести', |
| 336 | + 'googlenewssitemap_toomanycats' => 'Грешка: Премногу категории!', |
| 337 | + 'googlenewssitemap_feedtitle' => '$2-канал на {{SITENAME}} на $1.', |
| 338 | +); |
| 339 | + |
| 340 | +/** Dutch (Nederlands) |
| 341 | + * @author McDutchie |
| 342 | + * @author Mihxil |
| 343 | + * @author Siebrand |
| 344 | + */ |
| 345 | +$messages['nl'] = array( |
| 346 | + 'googlenewssitemap' => 'Google Nieuws Sitemap', |
| 347 | + 'googlenewssitemap-desc' => 'Levert een Atom/RSS-feed als Google Nieuws Sitemap', |
| 348 | + 'googlenewssitemap_toomanycats' => 'Fout: te veel categorieën!', |
| 349 | + 'googlenewssitemap_feedtitle' => '$2-feed van {{SITENAME}} in het $1', |
| 350 | +); |
| 351 | + |
| 352 | +/** Norwegian Nynorsk (Norsk (nynorsk)) |
| 353 | + * @author Harald Khan |
| 354 | + */ |
| 355 | +$messages['nn'] = array( |
| 356 | + 'googlenewssitemap_toomanycats' => 'Feil: For mange kategoriar.', |
| 357 | + 'googlenewssitemap_toofewcats' => 'Feil: For få kategoriar.', |
| 358 | + 'googlenewssitemap_noresults' => 'Feil: Ingen resultat', |
| 359 | + 'googlenewssitemap_noincludecats' => 'Feil: Du lyt inkludera minst éin kategori eller oppgje eit namnerom.', |
| 360 | +); |
| 361 | + |
| 362 | +/** Norwegian (bokmål) (Norsk (bokmål)) |
| 363 | + * @author Nghtwlkr |
| 364 | + */ |
| 365 | +$messages['no'] = array( |
| 366 | + 'googlenewssitemap' => 'Nettstedskart for Google News', |
| 367 | + 'googlenewssitemap-desc' => 'Gir ut en Atom/RSS-mating som et nettstedskart for Google News', |
| 368 | + 'googlenewssitemap_toomanycats' => 'Feil: For mange kategorier!', |
| 369 | + 'googlenewssitemap_feedtitle' => '$1 {{SITENAME}} $2-mating.', |
| 370 | +); |
| 371 | + |
| 372 | +/** Occitan (Occitan) |
| 373 | + * @author Cedric31 |
| 374 | + */ |
| 375 | +$messages['oc'] = array( |
| 376 | + 'googlenewssitemap' => 'Google nòvas Sitemap', |
| 377 | + 'googlenewssitemap-desc' => 'Crèa un Atom o RSS feed coma un plan Sitemap per Google', |
| 378 | + 'googlenewssitemap_toomanycats' => 'Error : Tròp de categorias !', |
| 379 | + 'googlenewssitemap_toofewcats' => 'Error : Pas pro de categorias !', |
| 380 | + 'googlenewssitemap_noresults' => 'Error : Pas cap de resultat !', |
| 381 | + 'googlenewssitemap_noincludecats' => 'Error : Vos cal inclure almens una categoria, o especificar un espaci de noms !', |
| 382 | +); |
| 383 | + |
| 384 | +/** Polish (Polski) |
| 385 | + * @author Sp5uhe |
| 386 | + */ |
| 387 | +$messages['pl'] = array( |
| 388 | + 'googlenewssitemap' => 'Mapa serwisu dla Google News', |
| 389 | + 'googlenewssitemap-desc' => 'Treść kanałów Atom i RSS w formie mapy witryny dla Google News', |
| 390 | + 'googlenewssitemap_toomanycats' => 'Błąd – zbyt wiele kategorii!', |
| 391 | + 'googlenewssitemap_feedtitle' => '{{SITENAME}} ($1) – kanał $2.', |
| 392 | +); |
| 393 | + |
| 394 | +/** Piedmontese (Piemontèis) |
| 395 | + * @author Borichèt |
| 396 | + * @author Dragonòt |
| 397 | + */ |
| 398 | +$messages['pms'] = array( |
| 399 | + 'googlenewssitemap' => 'Pian dël sit dle Neuve ëd Google', |
| 400 | + 'googlenewssitemap-desc' => 'A scriv un fluss Atom/RSS com pian dël Sit ëd le Neuve ëd Google', |
| 401 | + 'googlenewssitemap_toomanycats' => 'Eror: Tròpe categorìe!', |
| 402 | + 'googlenewssitemap_feedtitle' => '$1 {{SITENAME}} $2 feed.', |
| 403 | +); |
| 404 | + |
| 405 | +/** Portuguese (Português) |
| 406 | + * @author Hamilton Abreu |
| 407 | + */ |
| 408 | +$messages['pt'] = array( |
| 409 | + 'googlenewssitemap' => 'Google News Sitemap', |
| 410 | + 'googlenewssitemap-desc' => 'Converte um feed Atom/RSS para um Google News Sitemap', |
| 411 | + 'googlenewssitemap_toomanycats' => 'Erro: Categorias a mais!', |
| 412 | + 'googlenewssitemap_feedtitle' => 'Feed $2 da {{SITENAME}} em $1.', |
| 413 | +); |
| 414 | + |
| 415 | +/** Brazilian Portuguese (Português do Brasil) |
| 416 | + * @author Daemorris |
| 417 | + * @author Raylton P. Sousa |
| 418 | + */ |
| 419 | +$messages['pt-br'] = array( |
| 420 | + 'googlenewssitemap' => 'Mapa de Site de Notícias Google', |
| 421 | + 'googlenewssitemap-desc' => 'Produz um alimentador Atom/RSS como um Mapa de Site de Notícias Google', |
| 422 | + 'googlenewssitemap_toomanycats' => 'Erro: Categorias demais!', |
| 423 | + 'googlenewssitemap_toofewcats' => 'Erro: Categorias de menos!', |
| 424 | + 'googlenewssitemap_noresults' => 'Erro: Sem resultados!', |
| 425 | + 'googlenewssitemap_noincludecats' => 'Erro: Você precisa incluir pelo menos uma categoria, ou especificar um espaço nominal!', |
| 426 | + 'googlenewssitemap_badfeedobject' => '$feed não é um objecto.', |
| 427 | +); |
| 428 | + |
| 429 | +/** Romanian (Română) |
| 430 | + * @author Stelistcristi |
| 431 | + */ |
| 432 | +$messages['ro'] = array( |
| 433 | + 'googlenewssitemap_toomanycats' => 'Eroare: Prea multe categorii!', |
| 434 | + 'googlenewssitemap_toofewcats' => 'Eroare: pre', |
| 435 | + 'googlenewssitemap_noresults' => 'Eroare: Niciun rezultat!', |
| 436 | +); |
| 437 | + |
| 438 | +/** Russian (Русский) |
| 439 | + * @author Александр Сигачёв |
| 440 | + */ |
| 441 | +$messages['ru'] = array( |
| 442 | + 'googlenewssitemap' => 'Карта сайта для Google News', |
| 443 | + 'googlenewssitemap-desc' => 'Подготавливает канал Atom/RSS в виде карты сайта для Google News', |
| 444 | + 'googlenewssitemap_toomanycats' => 'Ошибка. Слишком много категорий!', |
| 445 | + 'googlenewssitemap_feedtitle' => '{{SITENAME}}. $1 $2 канал.', |
| 446 | +); |
| 447 | + |
| 448 | +/** Slovenian (Slovenščina) |
| 449 | + * @author Dbc334 |
| 450 | + */ |
| 451 | +$messages['sl'] = array( |
| 452 | + 'googlenewssitemap' => 'Zemljevid strani Google News', |
| 453 | + 'googlenewssitemap-desc' => 'Izpiše vir Atom/RSS kot zemljevid strani Google News', |
| 454 | + 'googlenewssitemap_toomanycats' => 'Napaka: Preveč kategorij!', |
| 455 | + 'googlenewssitemap_feedtitle' => 'Vir $1 {{SITENAME}} $2.', |
| 456 | +); |
| 457 | + |
| 458 | +/** Serbian Cyrillic ekavian (Српски (ћирилица)) |
| 459 | + * @author Михајло Анђелковић |
| 460 | + */ |
| 461 | +$messages['sr-ec'] = array( |
| 462 | + 'googlenewssitemap_toomanycats' => 'Грешка: Превише категорија!', |
| 463 | + 'googlenewssitemap_toofewcats' => 'Грешка: Премало категорија!', |
| 464 | + 'googlenewssitemap_noresults' => 'Грешка: Нема резултата!', |
| 465 | +); |
| 466 | + |
| 467 | +/** Serbian Latin ekavian (Srpski (latinica)) */ |
| 468 | +$messages['sr-el'] = array( |
| 469 | + 'googlenewssitemap_toomanycats' => 'Greška: Previše kategorija!', |
| 470 | + 'googlenewssitemap_toofewcats' => 'Greška: Premalo kategorija!', |
| 471 | + 'googlenewssitemap_noresults' => 'Greška: Nema rezultata!', |
| 472 | +); |
| 473 | + |
| 474 | +/** Swedish (Svenska) |
| 475 | + * @author Fredrik |
| 476 | + * @author Per |
| 477 | + * @author WikiPhoenix |
| 478 | + */ |
| 479 | +$messages['sv'] = array( |
| 480 | + 'googlenewssitemap' => 'Webbkarta för Google nyheter', |
| 481 | + 'googlenewssitemap-desc' => 'Visar ett Atom-/RSS-flöde som en webbkarta för Google nyheter', |
| 482 | + 'googlenewssitemap_toomanycats' => 'Fel: För många kategorier!', |
| 483 | + 'googlenewssitemap_toofewcats' => 'Fel: För få kategorier!', |
| 484 | + 'googlenewssitemap_noresults' => 'Fel: Inget resultat!', |
| 485 | + 'googlenewssitemap_noincludecats' => 'Fel: Du måste inkludera minst en kategori eller specificera en namnrymd!', |
| 486 | + 'googlenewssitemap_badfeedobject' => '$feed är inte ett objekt.', |
| 487 | +); |
| 488 | + |
| 489 | +/** Telugu (తెలుగు) |
| 490 | + * @author Veeven |
| 491 | + */ |
| 492 | +$messages['te'] = array( |
| 493 | + 'googlenewssitemap' => 'గూగుల్ వార్తల సైటుపటం', |
| 494 | + 'googlenewssitemap_toomanycats' => 'పొరపాటు: చాలా ఎక్కువ వర్గాలు!', |
| 495 | + 'googlenewssitemap_toofewcats' => 'పొరపాటు: చాలా తక్కువ వర్గాలు!', |
| 496 | + 'googlenewssitemap_noresults' => 'పొరపాటు: ఫలితాలు లేవు!', |
| 497 | +); |
| 498 | + |
| 499 | +/** Thai (ไทย) |
| 500 | + * @author Woraponboonkerd |
| 501 | + */ |
| 502 | +$messages['th'] = array( |
| 503 | + 'googlenewssitemap_toomanycats' => 'เกิดความผิดพลาด: เลือกประเภทมากเกินไป!', |
| 504 | + 'googlenewssitemap_toofewcats' => 'เกิดความผิดพลาด: เลือกประเภทน้อยเกินไป!', |
| 505 | + 'googlenewssitemap_noresults' => 'เกิดความผิดพลาด: ไม่พบข้อมูล!', |
| 506 | + 'googlenewssitemap_noincludecats' => 'เกิดความผิดพลาด: คุณต้องเลือกอย่างน้อยหนึ่งประเภท หรือกำหนด Namespace!', |
| 507 | +); |
| 508 | + |
| 509 | +/** Tagalog (Tagalog) |
| 510 | + * @author AnakngAraw |
| 511 | + */ |
| 512 | +$messages['tl'] = array( |
| 513 | + 'googlenewssitemap' => 'Mapang Pangsityo ng Balitang Google', |
| 514 | + 'googlenewssitemap-desc' => 'Naglalabas ng pakaing Atom/RSS bilang Mapa sa Sityo ng Balitang Google', |
| 515 | + 'googlenewssitemap_toomanycats' => 'Mali: Napakaraming mga kategorya!', |
| 516 | + 'googlenewssitemap_feedtitle' => '$1 na {{SITENAME}} $2 na pakain.', |
| 517 | +); |
| 518 | + |
| 519 | +/** Turkish (Türkçe) |
| 520 | + * @author Joseph |
| 521 | + * @author Tarikozket |
| 522 | + */ |
| 523 | +$messages['tr'] = array( |
| 524 | + 'googlenewssitemap' => 'Google Haberler Site haritası', |
| 525 | + 'googlenewssitemap-desc' => 'Bir Atom/RSS beslemesini Google Haberler Site haritası olarak çıktılar', |
| 526 | + 'googlenewssitemap_toomanycats' => 'Hata: Çok fazla kategori!', |
| 527 | + 'googlenewssitemap_toofewcats' => 'Hata: Çok az kategori!', |
| 528 | + 'googlenewssitemap_noresults' => 'Hata: Sonuç yok!', |
| 529 | + 'googlenewssitemap_noincludecats' => 'Hata: En az bir kategori girmeli, ya da bir ad alanı belirtmelisiniz!', |
| 530 | + 'googlenewssitemap_badfeedobject' => '$feed bir nesne değil.', |
| 531 | +); |
| 532 | + |
| 533 | +/** Ukrainian (Українська) |
| 534 | + * @author Arturyatsko |
| 535 | + */ |
| 536 | +$messages['uk'] = array( |
| 537 | + 'googlenewssitemap' => 'Карта сайту для Google News', |
| 538 | + 'googlenewssitemap-desc' => 'Виводить канал Atom/RSS у вигляді карти сайту для Google News', |
| 539 | + 'googlenewssitemap_toomanycats' => 'Помилка: Надто багато категорій!', |
| 540 | + 'googlenewssitemap_toofewcats' => 'Помилка: Надто мало категорії!', |
| 541 | + 'googlenewssitemap_noresults' => 'Помилка: не знайдено!', |
| 542 | + 'googlenewssitemap_noincludecats' => 'Помилка: Ви повинні включити хоча б одну категорію, або вказати простір імен!', |
| 543 | +); |
| 544 | + |
| 545 | +/** Simplified Chinese (中文(简体)) |
| 546 | + * @author Gaoxuewei |
| 547 | + */ |
| 548 | +$messages['zh-hans'] = array( |
| 549 | + 'googlenewssitemap' => 'Google 资讯站点地图', |
| 550 | + 'googlenewssitemap-desc' => '输出一个Google 资讯站点地图的Atom/RSS文件', |
| 551 | + 'googlenewssitemap_toomanycats' => '错误:分类过多!', |
| 552 | + 'googlenewssitemap_toofewcats' => '错误:分类过少!', |
| 553 | + 'googlenewssitemap_noresults' => '错误:没有结果!', |
| 554 | + 'googlenewssitemap_noincludecats' => '错误:您需要包含至少一个分类,或者指定一个名称空间!', |
| 555 | +); |
| 556 | + |
| 557 | +/** Traditional Chinese (中文(繁體)) |
| 558 | + * @author Mark85296341 |
| 559 | + */ |
| 560 | +$messages['zh-hant'] = array( |
| 561 | + 'googlenewssitemap' => 'Google 資訊站點地圖', |
| 562 | + 'googlenewssitemap-desc' => '輸出一個 Google 資訊站點地圖的 Atom/RSS 文件', |
| 563 | + 'googlenewssitemap_toomanycats' => '錯誤:分類過多!', |
| 564 | + 'googlenewssitemap_toofewcats' => '錯誤:分類過少!', |
| 565 | + 'googlenewssitemap_noresults' => '錯誤:沒有結果!', |
| 566 | + 'googlenewssitemap_noincludecats' => '錯誤:您需要包含至少一個分類,或者指定一個名稱空間!', |
| 567 | +); |
| 568 | + |
Property changes on: branches/wmf/1.17wmf1/extensions/GoogleNewsSitemap/GoogleNewsSitemap.i18n.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 569 | + native |
Index: branches/wmf/1.17wmf1/extensions/GoogleNewsSitemap/GoogleNewsSitemap.php |
— | — | @@ -0,0 +1,90 @@ |
| 2 | +<?php |
| 3 | +if ( !defined( 'MEDIAWIKI' ) ) { |
| 4 | + echo <<<EOT |
| 5 | +To install GoogleNewsSitemap extension, an extension special page, put the following line in LocalSettings.php: |
| 6 | +require_once( dirname(__FILE__) . '/extensions/GoogleNewsSitemap/GoogleNewsSitemap.php' ); |
| 7 | +EOT; |
| 8 | + exit( 1 ); |
| 9 | +} |
| 10 | + |
| 11 | +/** |
| 12 | + * Outputs feed xml |
| 13 | + ** |
| 14 | + * A Special Page extension to produce: |
| 15 | + * Google News sitemap output - http://www.google.com/support/news_pub/bin/answer.py?hl=en&answer=74288 |
| 16 | + * - http://www.sitemaps.org/protocol.php |
| 17 | + * RSS feed output - 2.0 http://www.rssboard.org/rss-specification |
| 18 | + * - 0.92 http://www.rssboard.org/rss-0-9-2 |
| 19 | + * Atom feed output - 2005 http://tools.ietf.org/html/rfc4287 |
| 20 | + ** |
| 21 | + * This page can be accessed from Special:GoogleNewsSitemap[/][|category=Catname] |
| 22 | + * [|notcategory=OtherCatName][|namespace=0][|notnamespace=User] |
| 23 | + * [|feed=sitemap][|count=10][|mode=ul][|ordermethod=lastedit] |
| 24 | + * [|order=ascending] as well as being included like |
| 25 | + * {{Special:GoogleNewsSitemap/[options][...]}} |
| 26 | + ** |
| 27 | + * This program is free software; you can redistribute it and/or modify it |
| 28 | + * under the terms of the GNU General Public License as published by the Free |
| 29 | + * Software Foundation; either version 2 of the License, or (at your option) |
| 30 | + * any later version. |
| 31 | + * |
| 32 | + * This program is distributed in the hope that it will be useful, but WITHOUT |
| 33 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| 34 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
| 35 | + * more details. |
| 36 | + * |
| 37 | + * You should have received a copy of the GNU General Public License along with |
| 38 | + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple |
| 39 | + * Place - Suite 330, Boston, MA 02111-1307, USA. |
| 40 | + * http://www.gnu.org/copyleft/gpl.html |
| 41 | + ** |
| 42 | + * Contributors |
| 43 | + * This script is based on Extension:DynamicPageList (Wikimedia), originally |
| 44 | + * developed by: |
| 45 | + * wikt:en:User:Amgine http://en.wiktionary.org/wiki/User:Amgine |
| 46 | + * n:en:User:IlyaHaykinson http://en.wikinews.org/wiki/User:IlyaHaykinson |
| 47 | + ** |
| 48 | + * FIXME requests |
| 49 | + * use=Mediawiki:GoogleNewsSitemap_Feedname Parameter to allow on-site control of feed |
| 50 | + ** |
| 51 | + * @addtogroup Extensions |
| 52 | + * |
| 53 | + * @author Amgine <amgine.saewyc@gmail.com> |
| 54 | + * @copyright Copyright © 2009, Amgine |
| 55 | + * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License 2.0 or later |
| 56 | + */ |
| 57 | +$wgExtensionCredits['specialpage'][] = array( |
| 58 | + 'path' => __FILE__, |
| 59 | + 'name' => 'GoogleNewsSitemap', |
| 60 | + 'author' => 'Amgine', |
| 61 | + 'descriptionmsg' => 'googlenewssitemap-desc', |
| 62 | + 'url' => 'http://www.mediawiki.org/wiki/Extension:GoogleNewsSitemap', |
| 63 | +); |
| 64 | + |
| 65 | +$dir = dirname( __FILE__ ) . '/'; |
| 66 | +$wgExtensionMessagesFiles['GoogleNewsSitemap'] = $dir . 'GoogleNewsSitemap.i18n.php'; |
| 67 | +$wgExtensionAliasesFiles['GoogleNewsSitemap'] = $dir . 'GoogleNewsSitemap.alias.php'; |
| 68 | +$wgAutoloadClasses['GoogleNewsSitemap'] = $dir . 'GoogleNewsSitemap_body.php'; |
| 69 | +$wgAutoloadClasses['FeedSMItem'] = $dir . 'FeedSMItem.php'; |
| 70 | +$wgAutoloadClasses['SitemapFeed'] = $dir . 'SitemapFeed.php'; |
| 71 | +$wgSpecialPages['GoogleNewsSitemap'] = 'GoogleNewsSitemap'; |
| 72 | +$wgFeedClasses['sitemap'] = 'SitemapFeed'; |
| 73 | + |
| 74 | +// Configuration options: |
| 75 | +$wgGNSMmaxCategories = 6; // Maximum number of categories to look for |
| 76 | +$wgGNSMmaxResultCount = 50; // Maximum number of results to allow |
| 77 | + |
| 78 | +// Fallback category if no categories are specified. |
| 79 | +$wgGNSMfallbackCategory = 'Published'; |
| 80 | + |
| 81 | +// How long to put in squid cache. Note also cached using wgMemc (for 12 hours), |
| 82 | +// but the wgMemc entries are checked to see if they are still relevant, where |
| 83 | +// the squid cache is not checked. So this should be a small number. |
| 84 | +$wgGNSMsmaxage = 1800; // = 30 minutes |
| 85 | + |
| 86 | +// $wgGNSMcommentNamespace can be false to mean do not include a <comments> element in the feeds, |
| 87 | +// or it can be true, to mean use the talk page of the relevent page as the comments page |
| 88 | +// or it can be a specific namespace number ( or NS_BLAH constant) to denote a specific namespace. |
| 89 | +// For example, on many Wikinews sites, the comment namespace is Comments (102), not talk. |
| 90 | +$wgGNSMcommentNamespace = true; |
| 91 | + |
Property changes on: branches/wmf/1.17wmf1/extensions/GoogleNewsSitemap/GoogleNewsSitemap.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 92 | + native |
Index: branches/wmf/1.17wmf1/extensions/GoogleNewsSitemap/FeedSMItem.php |
— | — | @@ -0,0 +1,111 @@ |
| 2 | +<?php |
| 3 | +if ( !defined( 'MEDIAWIKI' ) ) die(); |
| 4 | + |
| 5 | +/** |
| 6 | + * FeedSMItem Class |
| 7 | + ** |
| 8 | + * Base class for basic SiteMap support, for building url containers. |
| 9 | + **/ |
| 10 | +class FeedSMItem extends FeedItem { |
| 11 | + |
| 12 | + private $keywords = array(); |
| 13 | + |
| 14 | + /** |
| 15 | + * @var Title |
| 16 | + */ |
| 17 | + private $title; |
| 18 | + |
| 19 | + /** |
| 20 | + * @param Title $title Title object that this entry is for. |
| 21 | + * @param String $pubDate Publish date formattable by wfTimestamp. |
| 22 | + * @param Array $keywords list of (String) keywords |
| 23 | + * @param Mixed Boolean or Integer. Namespace containing comments page for entry. |
| 24 | + * True for the corresponding talk page of $title |
| 25 | + * False for none |
| 26 | + * An integer for the page name of $title in the specific namespace denoted by that integer. |
| 27 | + */ |
| 28 | + public function __construct( $title, $pubDate, $keywords = '', $comment = true ) { |
| 29 | + |
| 30 | + if ( !$title ) { |
| 31 | + // Paranoia |
| 32 | + throw new MWException( "Invalid title object passed to FeedSMItem" ); |
| 33 | + } |
| 34 | + |
| 35 | + $commentsURL = ''; |
| 36 | + if ( $comment === true ) { |
| 37 | + // The comment ns is this article's talk namespace. |
| 38 | + $commentsURL = $title->getTalkPage()->getFullUrl(); |
| 39 | + } else if ( is_int( $comment ) ) { |
| 40 | + // There's a specific comments namespace. |
| 41 | + $commentsTitle = Title::makeTitle( $comment, $title->getDBkey() ); |
| 42 | + if ( $commentsTitle ) { |
| 43 | + $commentsURL = $commentsTitle->getFullUrl(); |
| 44 | + } |
| 45 | + } |
| 46 | + |
| 47 | + $this->title = $title; |
| 48 | + $this->keywords = $keywords; |
| 49 | + |
| 50 | + parent::__construct( $title->getText(), '' /* Description */, |
| 51 | + $title->getFullUrl(), $pubDate, '' /* Author */, $commentsURL ); |
| 52 | + } |
| 53 | + |
| 54 | + /** |
| 55 | + * Convert a FeedItem to an FeedSMItem. |
| 56 | + * This is to make sitemap feed get along with normal MediaWiki feeds. |
| 57 | + * @param FeedItem Original item. |
| 58 | + * @return FeedSMItem Converted item. |
| 59 | + */ |
| 60 | + static public function newFromFeedItem( FeedItem $item ) { |
| 61 | + // FIXME: This is borked (esp. on history), but better than a fatal (not by much). |
| 62 | + // maybe try and get title from url? |
| 63 | + $title = Title::newFromText( $item->getTitle() ); |
| 64 | + if ( !$title ) { |
| 65 | + throw new MWException( "Error getting title object from string in FeedItem." ); |
| 66 | + } |
| 67 | + $date = $item->getDate(); |
| 68 | + return new FeedSMItem( $title, $date ); |
| 69 | + } |
| 70 | + |
| 71 | + public function getLastMod() { |
| 72 | + return $this->title->getTouched(); |
| 73 | + } |
| 74 | + |
| 75 | + public function getKeywords() { |
| 76 | + // Note, not using $wgContLang->commaList, as this is for |
| 77 | + // computers not humans, so we don't want to vary with |
| 78 | + // language conventions. |
| 79 | + return $this->xmlEncode( implode( ', ', $this->keywords ) ); |
| 80 | + } |
| 81 | + |
| 82 | + /** |
| 83 | + * Overrides parent class. Meant to be used in rss feed. |
| 84 | + * Currently return the article, its debatable if thats a good idea |
| 85 | + * or not, but not sure of what better to do. Could regex the wikitext |
| 86 | + * and try to return the first paragraph, but thats iffy. |
| 87 | + * |
| 88 | + * Note, this is only called by the atom/rss feed output, not by |
| 89 | + * the sitemap output. |
| 90 | + * @return String |
| 91 | + */ |
| 92 | + public function getDescription() { |
| 93 | + // This is probably rather inefficient to do for several pages |
| 94 | + // but not much worse than the rest of this extension. |
| 95 | + $req = new FauxRequest( array( |
| 96 | + 'action' => 'parse', |
| 97 | + 'page' => $this->title->getPrefixedDBKey(), |
| 98 | + 'prop' => 'text', |
| 99 | + ) ); |
| 100 | + $main = new ApiMain( $req ); |
| 101 | + $main->execute(); |
| 102 | + $data = $main->getResultData(); |
| 103 | + if ( isset( $data['parse']['text']['*'] ) ) { |
| 104 | + return $this->xmlEncode( |
| 105 | + $data['parse']['text']['*'] |
| 106 | + ); |
| 107 | + } else { |
| 108 | + return ''; |
| 109 | + } |
| 110 | + } |
| 111 | +} |
| 112 | + |
Property changes on: branches/wmf/1.17wmf1/extensions/GoogleNewsSitemap/FeedSMItem.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 113 | + native |
Index: branches/wmf/1.17wmf1/extensions/GoogleNewsSitemap/GoogleNewsSitemap.alias.php |
— | — | @@ -0,0 +1,76 @@ |
| 2 | +<?php |
| 3 | +/** |
| 4 | + * Aliases for Special:GoogleNewsSitemap |
| 5 | + * |
| 6 | + * @file |
| 7 | + * @ingroup Extensions |
| 8 | + */ |
| 9 | + |
| 10 | +$specialPageAliases = array(); |
| 11 | + |
| 12 | +/** English |
| 13 | + * @author Amgine |
| 14 | + */ |
| 15 | +$specialPageAliases['en'] = array( |
| 16 | + 'GoogleNewsSitemap' => array( 'GoogleNewsSitemap' ), |
| 17 | +); |
| 18 | + |
| 19 | +/** Arabic (العربية) */ |
| 20 | +$specialPageAliases['ar'] = array( |
| 21 | + 'GoogleNewsSitemap' => array( 'خريطة_موقع_أخبار_جوجل' ), |
| 22 | +); |
| 23 | + |
| 24 | +/** Egyptian Spoken Arabic (مصرى) */ |
| 25 | +$specialPageAliases['arz'] = array( |
| 26 | + 'GoogleNewsSitemap' => array( 'خريطة_سايت_اخبار_جوجل' ), |
| 27 | +); |
| 28 | + |
| 29 | +/** Persian (فارسی) */ |
| 30 | +$specialPageAliases['fa'] = array( |
| 31 | + 'GoogleNewsSitemap' => array( 'نقشه_وبگاه_گوگل_نیوز' ), |
| 32 | +); |
| 33 | + |
| 34 | +/** Hungarian (Magyar) */ |
| 35 | +$specialPageAliases['hu'] = array( |
| 36 | + 'GoogleNewsSitemap' => array( 'Google_Hírek_oldaltérkép' ), |
| 37 | +); |
| 38 | + |
| 39 | +/** Interlingua (Interlingua) */ |
| 40 | +$specialPageAliases['ia'] = array( |
| 41 | + 'GoogleNewsSitemap' => array( 'Mappa_de_sito_Google_News' ), |
| 42 | +); |
| 43 | + |
| 44 | +/** Indonesian (Bahasa Indonesia) */ |
| 45 | +$specialPageAliases['id'] = array( |
| 46 | + 'GoogleNewsSitemap' => array( 'Peta_situs_Google_News', 'PetaSitusGoogleNews' ), |
| 47 | +); |
| 48 | + |
| 49 | +/** Japanese (日本語) */ |
| 50 | +$specialPageAliases['ja'] = array( |
| 51 | + 'GoogleNewsSitemap' => array( 'Googleニュースサイトマップ' ), |
| 52 | +); |
| 53 | + |
| 54 | +/** Ladino (Ladino) */ |
| 55 | +$specialPageAliases['lad'] = array( |
| 56 | + 'GoogleNewsSitemap' => array( 'Mapa_de_sitio_de_GoogleJhabberes' ), |
| 57 | +); |
| 58 | + |
| 59 | +/** Malayalam (മലയാളം) */ |
| 60 | +$specialPageAliases['ml'] = array( |
| 61 | + 'GoogleNewsSitemap' => array( 'ഗൂഗിൾവാർത്തകൾസൈറ്റ്മാപ്പ്' ), |
| 62 | +); |
| 63 | + |
| 64 | +/** Norwegian (bokmål) (Norsk (bokmål)) */ |
| 65 | +$specialPageAliases['no'] = array( |
| 66 | + 'GoogleNewsSitemap' => array( 'Google_nyheter-sidekart' ), |
| 67 | +); |
| 68 | + |
| 69 | +/** Polish (Polski) */ |
| 70 | +$specialPageAliases['pl'] = array( |
| 71 | + 'GoogleNewsSitemap' => array( 'Mapa_strony_dla_Google_News' ), |
| 72 | +); |
| 73 | + |
| 74 | +/** |
| 75 | + * For backwards compatibility with MediaWiki 1.15 and earlier. |
| 76 | + */ |
| 77 | +$aliases =& $specialPageAliases; |
\ No newline at end of file |
Property changes on: branches/wmf/1.17wmf1/extensions/GoogleNewsSitemap/GoogleNewsSitemap.alias.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 78 | + native |
Index: branches/wmf/1.17wmf1/extensions/GoogleNewsSitemap/SitemapFeed.php |
— | — | @@ -0,0 +1,115 @@ |
| 2 | +<?php |
| 3 | +if ( !defined( 'MEDIAWIKI' ) ) die(); |
| 4 | + |
| 5 | +class SitemapFeed extends ChannelFeed { |
| 6 | + private $writer; |
| 7 | + private $publicationName; |
| 8 | + private $publicationLang; |
| 9 | + |
| 10 | + function __construct() { |
| 11 | + global $wgSitename, $wgLanguageCode; |
| 12 | + |
| 13 | + $this->writer = new XMLWriter(); |
| 14 | + $this->publicationName = $wgSitename; |
| 15 | + $this->publicationLang = $wgLanguageCode; |
| 16 | + } |
| 17 | + |
| 18 | + /** |
| 19 | + * Set the publication language code. Only used if different from |
| 20 | + * $wgLanguageCode, which could happen if google disagrees with us |
| 21 | + * on say what code zh gets. |
| 22 | + * @param String $lang Language code (like en) |
| 23 | + */ |
| 24 | + public function setPublicationLang( $lang ) { |
| 25 | + $this->publicationLang = $lang; |
| 26 | + } |
| 27 | + |
| 28 | + /** |
| 29 | + * Set the publication name. Normally $wgSitename, but could |
| 30 | + * need to be changed, if Google gives the publication a different |
| 31 | + * name then $wgSitename. |
| 32 | + * @param String $name The name of the publication |
| 33 | + */ |
| 34 | + public function setPublicationName( $name ) { |
| 35 | + $this->publicationName = $name; |
| 36 | + } |
| 37 | + |
| 38 | + function contentType() { |
| 39 | + return 'application/xml'; |
| 40 | + } |
| 41 | + |
| 42 | + /** |
| 43 | + * Output feed headers. |
| 44 | + */ |
| 45 | + public function outHeader() { |
| 46 | + $this->httpHeaders(); |
| 47 | + |
| 48 | + $this->writer->openURI( 'php://output' ); |
| 49 | + $this->writer->setIndent( true ); |
| 50 | + $this->writer->startDocument( "1.0", "UTF-8" ); |
| 51 | + $this->writer->startElement( "urlset" ); |
| 52 | + $this->writer->writeAttribute( "xmlns", "http://www.sitemaps.org/schemas/sitemap/0.9" ); |
| 53 | + $this->writer->writeAttribute( "xmlns:news", "http://www.google.com/schemas/sitemap-news/0.9" ); |
| 54 | + } |
| 55 | + |
| 56 | + /** |
| 57 | + * Output a SiteMap 0.9 item |
| 58 | + * @param FeedSMItem $item to be output |
| 59 | + */ |
| 60 | + public function outItem( $item ) { |
| 61 | + |
| 62 | + if ( !( $item instanceof FeedItem ) ) { |
| 63 | + throw new MWException( "Requires a FeedItem or subclass." ); |
| 64 | + } |
| 65 | + if ( !( $item instanceof FeedSMItem ) ) { |
| 66 | + $item = FeedSMItem::newFromFeedItem( $item ); |
| 67 | + } |
| 68 | + |
| 69 | + $this->writer->startElement( "url" ); |
| 70 | + |
| 71 | + $this->writer->startElement( "loc" ); |
| 72 | + $this->writer->text( $item->getUrl() ); |
| 73 | + $this->writer->endElement(); |
| 74 | + |
| 75 | + $this->writer->startElement( "news:news" ); |
| 76 | + |
| 77 | + $this->writer->startElement( "news:publication_date" ); |
| 78 | + $this->writer->text( wfTimestamp( TS_ISO_8601, $item->getDate() ) ); |
| 79 | + $this->writer->endElement(); |
| 80 | + |
| 81 | + $this->writer->startElement( "news:title" ); |
| 82 | + $this->writer->text( $item->getTitle() ); |
| 83 | + $this->writer->endElement(); |
| 84 | + |
| 85 | + $this->writer->startElement( "news:publication" ); |
| 86 | + $this->writer->startElement( "news:name" ); |
| 87 | + $this->writer->text( $this->publicationName ); |
| 88 | + $this->writer->endElement(); |
| 89 | + $this->writer->startElement( "news:language" ); |
| 90 | + $this->writer->text( $this->publicationLang ); |
| 91 | + $this->writer->endElement(); |
| 92 | + $this->writer->endElement(); |
| 93 | + |
| 94 | + if ( $item->getKeywords() ) { |
| 95 | + $this->writer->startElement( "news:keywords" ); |
| 96 | + $this->writer->text( $item->getKeywords() ); |
| 97 | + $this->writer->endElement(); |
| 98 | + } |
| 99 | + |
| 100 | + $this->writer->endElement(); // end news:news |
| 101 | + if ( $item->getLastMod() ) { |
| 102 | + $this->writer->startElement( "lastmod" ); |
| 103 | + $this->writer->text( wfTimestamp( TS_ISO_8601, $item->getLastMod() ) ); |
| 104 | + $this->writer->endElement(); |
| 105 | + } |
| 106 | + $this->writer->endElement(); // end url |
| 107 | + } |
| 108 | + |
| 109 | + /** |
| 110 | + * Output SiteMap 0.9 footer |
| 111 | + */ |
| 112 | + public function outFooter() { |
| 113 | + $this->writer->endDocument(); |
| 114 | + $this->writer->flush(); |
| 115 | + } |
| 116 | +} |
Property changes on: branches/wmf/1.17wmf1/extensions/GoogleNewsSitemap/SitemapFeed.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 117 | + native |