Файловый менеджер - Редактировать - /var/www/html/FeaturedFeeds.zip
Ðазад
PK ! �2YJ� � FeaturedFeeds.alias.phpnu �[��� <?php /** * Aliases for Special:FeedItem * * @file * @ingroup Extensions */ $specialPageAliases = []; /** English (English) */ $specialPageAliases['en'] = [ 'FeedItem' => [ 'FeedItem' ], ]; /** Arabic (العربية) */ $specialPageAliases['ar'] = [ 'FeedItem' => [ 'تعليق_مدخلة' ], ]; /** Egyptian Arabic (مصرى) */ $specialPageAliases['arz'] = [ 'FeedItem' => [ 'مدخله_تعليق' ], ]; /** Western Balochi (بلوچی رخشانی) */ $specialPageAliases['bgn'] = [ 'FeedItem' => [ 'آیتم_ئی_ورّگ' ], ]; /** German (Deutsch) */ $specialPageAliases['de'] = [ 'FeedItem' => [ 'Feedobjekt' ], ]; /** Zazaki (Zazaki) */ $specialPageAliases['diq'] = [ 'FeedItem' => [ 'LeteWeynayış' ], ]; /** Persian (فارسی) */ $specialPageAliases['fa'] = [ 'FeedItem' => [ 'خوراک_آیتم' ], ]; /** Hebrew (עברית) */ $specialPageAliases['he'] = [ 'FeedItem' => [ 'פריט_הזנה' ], ]; /** Italian (italiano) */ $specialPageAliases['it'] = [ 'FeedItem' => [ 'FeedElemento' ], ]; /** Japanese (日本語) */ $specialPageAliases['ja'] = [ 'FeedItem' => [ 'フィード項目' ], ]; /** Korean (한국어) */ $specialPageAliases['ko'] = [ 'FeedItem' => [ '피드항목' ], ]; /** Luxembourgish (Lëtzebuergesch) */ $specialPageAliases['lb'] = [ 'FeedItem' => [ 'Element_vun_enger_Rubrik' ], ]; /** Macedonian (македонски) */ $specialPageAliases['mk'] = [ 'FeedItem' => [ 'СтавкаОдКанал' ], ]; /** Malayalam (മലയാളം) */ $specialPageAliases['ml'] = [ 'FeedItem' => [ 'ഫീഡ്ഇനം' ], ]; /** Brazilian Portuguese (português do Brasil) */ $specialPageAliases['pt-br'] = [ 'FeedItem' => [ 'Item_de_feed' ], ]; /** Sicilian (sicilianu) */ $specialPageAliases['scn'] = [ 'FeedItem' => [ 'FeedElemento' ], ]; /** Swedish (svenska) */ $specialPageAliases['sv'] = [ 'FeedItem' => [ 'Flödesobjekt' ], ]; /** Turkish (Türkçe) */ $specialPageAliases['tr'] = [ 'FeedItem' => [ 'ÜrünBesleme' ], ]; /** Urdu (اردو) */ $specialPageAliases['ur'] = [ 'FeedItem' => [ 'فیڈ_آئٹم' ], ]; /** Vietnamese (Tiếng Việt) */ $specialPageAliases['vi'] = [ 'FeedItem' => [ 'Khoản_mục_nguồn_tin' ], ]; /** Simplified Chinese (中文(简体)) */ $specialPageAliases['zh-hans'] = [ 'FeedItem' => [ '供稿项目' ], ]; /** Traditional Chinese (中文(繁體)) */ $specialPageAliases['zh-hant'] = [ 'FeedItem' => [ '供稿項目' ], ]; PK ! �'�� � Gruntfile.jsnu �[��� /*! * Grunt file * * @package FeaturedFeeds */ /* eslint-env node */ module.exports = function ( grunt ) { var conf = grunt.file.readJSON( 'extension.json' ); grunt.loadNpmTasks( 'grunt-banana-checker' ); grunt.loadNpmTasks( 'grunt-eslint' ); grunt.loadNpmTasks( 'grunt-stylelint' ); grunt.initConfig( { eslint: { options: { cache: true }, all: [ '**/*.{js,json}', '!node_modules/**', '!vendor/**' ] }, stylelint: { all: [ '**/*.css', '!node_modules/**', '!vendor/**' ] }, banana: conf.MessagesDirs } ); grunt.registerTask( 'test', [ 'eslint', 'stylelint', 'banana' ] ); grunt.registerTask( 'default', 'test' ); }; PK ! �Y�6 6 extension.jsonnu �[��� { "name": "FeaturedFeeds", "author": [ "Max Semenik" ], "url": "https://www.mediawiki.org/wiki/Extension:FeaturedFeeds", "descriptionmsg": "ffeed-desc", "type": "other", "license-name": "WTFPL", "requires": { "MediaWiki": ">= 1.43" }, "ExtensionMessagesFiles": { "FeaturedFeedsAliases": "FeaturedFeeds.alias.php" }, "APIModules": { "featuredfeed": { "class": "MediaWiki\\Extension\\FeaturedFeeds\\ApiFeaturedFeeds", "services": [ "LanguageNameUtils" ] } }, "Hooks": { "BeforePageDisplay": "FeaturedFeedsHooks", "PageSaveComplete": "FeaturedFeedsHooks", "SidebarBeforeOutput": "FeaturedFeedsHooks" }, "HookHandlers": { "FeaturedFeedsHooks": { "class": "MediaWiki\\Extension\\FeaturedFeeds\\FeaturedFeeds" } }, "MessagesDirs": { "FeaturedFeeds": [ "i18n", "i18n/api" ] }, "config": { "DisplayFeedsInSidebar": { "value": true }, "FeaturedFeedsDefaults": { "value": { "limit": 10, "frequency": "daily", "inUserLanguage": false } }, "FeaturedFeeds": { "value": [] } }, "SpecialPages": { "FeedItem": { "class": "MediaWiki\\Extension\\FeaturedFeeds\\SpecialFeedItem", "services": [ "MainWANObjectCache" ] } }, "AutoloadNamespaces": { "MediaWiki\\Extension\\FeaturedFeeds\\": "includes/" }, "manifest_version": 2 } PK ! u7�3_ _ includes/FeaturedFeedChannel.phpnu �[��� <?php namespace MediaWiki\Extension\FeaturedFeeds; use MediaWiki\Content\TextContent; use MediaWiki\Language\Language; use MediaWiki\MediaWikiServices; use MediaWiki\Message\Message; use MediaWiki\Parser\Parser; use MediaWiki\Parser\ParserOptions; use MediaWiki\Revision\SlotRecord; use MediaWiki\SpecialPage\SpecialPage; use MediaWiki\Title\Title; use MediaWiki\Utils\MWTimestamp; use UnexpectedValueException; class FeaturedFeedChannel { /** * Class version, increment it when changing class internals. */ public const VERSION = 2; /** * @var Parser */ private static $parser; /** @var string */ private $languageCode; /** @var string */ private $name; /** @var array */ private $options; /** * @var FeaturedFeedItem[]|false */ private $items = false; /** @var string|false */ private $page = false; /** @var string|false */ private $entryName = false; /** @var Title|false */ private $titleForParse = false; /** @var string|false */ public $title = false; /** @var string|false */ public $shortTitle = false; /** @var string|false */ public $description = false; /** * @param string $name * @param array $options * @param string $languageCode */ public function __construct( $name, $options, $languageCode ) { if ( !self::$parser ) { self::$parser = MediaWikiServices::getInstance()->getParserFactory()->create(); } $this->name = $name; $this->options = $options; if ( $options['inUserLanguage'] ) { $this->languageCode = $languageCode; } else { $contLang = MediaWikiServices::getInstance()->getContentLanguage(); $this->languageCode = $contLang->getCode(); } } public static function fromArray( array $array ): self { $channel = new self( $array['name'], $array['options'], $array['lang'] ); if ( $array['items'] !== false ) { $channel->items = []; foreach ( $array['items'] as $item ) { $channel->items[] = FeaturedFeedItem::fromArray( $item ); } } $channel->page = $array['page']; $channel->entryName = $array['entryName']; $channel->titleForParse = $array['titleForParse']; $channel->title = $array['title']; $channel->shortTitle = $array['shortTitle']; $channel->description = $array['description']; return $channel; } public function toArray(): array { $items = false; if ( $this->items !== false ) { $items = []; foreach ( $this->items as $item ) { $items[] = $item->toArray(); } } return [ 'name' => $this->name, 'options' => $this->options, 'lang' => $this->languageCode, 'items' => $items, 'page' => $this->page, 'entryName' => $this->entryName, 'titleForParse' => $this->titleForParse, 'title' => $this->title, 'shortTitle' => $this->shortTitle, 'description' => $this->description, ]; } /** * @param string $key * @return Message */ private function msg( $key ) { return wfMessage( $key )->inLanguage( $this->languageCode ); } /** * @return bool */ public function isOK() { $this->init(); return $this->page !== false; } /** * Returns language used by the feed * @return Language */ public function getLanguage() { return MediaWikiServices::getInstance()->getLanguageFactory() ->getLanguage( $this->languageCode ); } public function init() { global $wgLanguageCode; if ( $this->title !== false ) { return; } $this->title = $this->msg( $this->options['title'] )->text(); $this->shortTitle = $this->msg( $this->options['short-title'] )->text(); $this->description = $this->msg( $this->options['description'] )->text(); $pageMsg = $this->msg( $this->options['page'] )->params( $this->languageCode ); if ( $pageMsg->isDisabled() ) { // fall back manually, messages can be existent but empty if ( $this->languageCode != $wgLanguageCode ) { $pageMsg = wfMessage( $this->options['page'] ) ->params( $this->languageCode ) ->inContentLanguage(); } } if ( $pageMsg->isDisabled() ) { return; } $this->page = $pageMsg->plain(); $this->page = str_replace( '$LANGUAGE', $this->languageCode, $this->page ); $this->entryName = $this->msg( $this->options['entryName'] )->plain(); } /** * @return FeaturedFeedItem[] */ public function getFeedItems() { $this->init(); if ( $this->items === false ) { $this->items = []; switch ( $this->options['frequency'] ) { case 'daily': $ratio = 1; $baseTime = FeaturedFeeds::todaysStart(); break; case 'weekly': $ratio = 7; $baseTime = FeaturedFeeds::startOfThisWeek(); break; default: throw new UnexpectedValueException( "'{$this->options['frequency']}' is not a valid frequency" ); } for ( $i = 1 - $this->options['limit']; $i <= 0; $i++ ) { $timestamp = $baseTime + $i * $ratio * 24 * 3600; $item = $this->getFeedItem( $timestamp ); if ( $item ) { $this->items[] = $item; } } } return $this->items; } /** * * @param int $date * @return FeaturedFeedItem|false */ public function getFeedItem( $date ) { $ts = new MWTimestamp( $date ); $timestamp = $ts->getTimestamp( TS_MW ); $parserOptions = ParserOptions::newFromAnon(); $parserOptions->setTimestamp( $timestamp ); $parserOptions->setUserLang( $this->getLanguage() ); if ( $this->titleForParse === false ) { // parsing with such title makes stuff like {{CURRENTMONTH}} localised $this->titleForParse = Title::newFromText( 'MediaWiki:Dummy/' . $this->languageCode ); } $titleText = self::$parser->transformMsg( $this->page, $parserOptions, $this->titleForParse ); $title = Title::newFromText( $titleText ); if ( !$title ) { return false; } $rev = MediaWikiServices::getInstance()->getRevisionLookup() ->getRevisionByTitle( $title ); if ( !$rev ) { // Page does not exist return false; } $content = $rev->getContent( SlotRecord::MAIN ); $text = ( $content instanceof TextContent ) ? $content->getText() : null; if ( !$text ) { return false; } $text = self::$parser->parse( $text, $title, $parserOptions )->runOutputPipeline( $parserOptions, [ 'enableSectionEditLinks' => false, ] )->getContentHolderText(); $url = SpecialPage::getTitleFor( 'FeedItem', $this->name . '/' . $timestamp . '/' . $this->languageCode )->getFullURL(); return new FeaturedFeedItem( self::$parser->transformMsg( $this->entryName, $parserOptions, $this->titleForParse ), wfExpandUrl( $url ), $text, $timestamp ); } /** * Returns a URL to the feed * * @param string $format Feed format, 'rss' or 'atom' * @return string */ public function getURL( $format ) { $contLang = MediaWikiServices::getInstance()->getContentLanguage(); $options = [ 'action' => 'featuredfeed', 'feed' => $this->name, 'feedformat' => $format, ]; if ( $this->options['inUserLanguage'] && $this->languageCode != $contLang->getCode() ) { $options['language'] = $this->languageCode; } return wfScript( 'api' ) . '?' . wfArrayToCgi( $options ); } } PK ! �`�� � includes/ApiFeaturedFeeds.phpnu �[��� <?php namespace MediaWiki\Extension\FeaturedFeeds; use MediaWiki\Api\ApiBase; use MediaWiki\Api\ApiFormatFeedWrapper; use MediaWiki\Api\ApiMain; use MediaWiki\Languages\LanguageNameUtils; use MediaWiki\MainConfigNames; use MediaWiki\Title\Title; use Wikimedia\ParamValidator\ParamValidator; class ApiFeaturedFeeds extends ApiBase { private LanguageNameUtils $languageNameUtils; public function __construct( ApiMain $main, string $action, LanguageNameUtils $languageNameUtils ) { parent::__construct( $main, $action ); $this->languageNameUtils = $languageNameUtils; } /** * This module uses a custom feed wrapper printer. * * @return ApiFormatFeedWrapper */ public function getCustomPrinter() { return new ApiFormatFeedWrapper( $this->getMain() ); } public function execute() { $params = $this->extractRequestParams(); $feedClasses = $this->getConfig()->get( MainConfigNames::FeedClasses ); if ( !isset( $feedClasses[$params['feedformat']] ) ) { $this->dieWithError( 'feed-invalid' ); } $language = $params['language'] ?? false; if ( $language !== false && !$this->languageNameUtils->isValidCode( $language ) ) { $language = false; } $feeds = FeaturedFeeds::getFeeds( $language ); $ourFeed = $feeds[$params['feed']]; $feedClass = new $feedClasses[$params['feedformat']] ( $ourFeed->title, $ourFeed->description, wfExpandUrl( Title::newMainPage()->getFullURL() ) ); ApiFormatFeedWrapper::setResult( $this->getResult(), $feedClass, $ourFeed->getFeedItems() ); // Cache stuff in squids $this->getMain()->setCacheMode( 'public' ); $this->getMain()->setCacheMaxAge( FeaturedFeeds::getMaxAge() ); } /** @inheritDoc */ public function getAllowedParams() { $feedFormatNames = array_keys( $this->getConfig()->get( MainConfigNames::FeedClasses ) ); $availableFeeds = array_keys( FeaturedFeeds::getFeeds( false ) ); return [ 'feedformat' => [ ParamValidator::PARAM_DEFAULT => 'rss', ParamValidator::PARAM_TYPE => $feedFormatNames ], 'feed' => [ ParamValidator::PARAM_TYPE => $availableFeeds, ParamValidator::PARAM_REQUIRED => true, ], 'language' => [ ParamValidator::PARAM_TYPE => 'string', ] ]; } /** * @see ApiBase::getExamplesMessages() * @return array */ protected function getExamplesMessages() { // attempt to find a valid feed name // if none available, just use an example value $availableFeeds = array_keys( FeaturedFeeds::getFeeds( false ) ); $feed = reset( $availableFeeds ); if ( !$feed ) { $feed = 'featured'; } return [ "action=featuredfeed&feed=$feed" => [ 'apihelp-featuredfeed-example-1', $feed ], ]; } } PK ! JE8� � includes/FeaturedFeedItem.phpnu �[��� <?php namespace MediaWiki\Extension\FeaturedFeeds; use MediaWiki\Feed\FeedItem; class FeaturedFeedItem extends FeedItem { public function __construct( string $title, string $url, string $text, string $date ) { parent::__construct( $title, $text, $url, $date ); } public static function fromArray( array $array ): self { return new self( $array['title'], $array['url'], $array['text'], $array['date'] ); } /** * @return string */ public function getRawDate() { return $this->date; } /** * @return string */ public function getRawTitle() { return $this->title; } /** * @return string */ public function getRawUrl() { return $this->url; } /** * @return string */ public function getRawText() { return $this->description; } public function toArray(): array { return [ 'title' => $this->title, 'url' => $this->url, 'text' => $this->description, 'date' => $this->date, ]; } } PK ! > �,u u includes/SpecialFeedItem.phpnu �[��� <?php namespace MediaWiki\Extension\FeaturedFeeds; use MediaWiki\SpecialPage\UnlistedSpecialPage; use MediaWiki\Utils\MWTimestamp; use Wikimedia\ObjectCache\WANObjectCache; class SpecialFeedItem extends UnlistedSpecialPage { /** @var WANObjectCache */ private $wanObjectCache; /** * @param WANObjectCache $wanObjectCache */ public function __construct( WANObjectCache $wanObjectCache ) { parent::__construct( 'FeedItem' ); $this->wanObjectCache = $wanObjectCache; } /** @inheritDoc */ public function execute( $par = '' ) { $this->setHeaders(); $out = $this->getOutput(); $parts = explode( '/', $par ); if ( count( $parts ) != 3 ) { $out->showErrorPage( 'error', 'ffeed-no-feed' ); return; } [ $feedName, $date, $langCode ] = $parts; $feeds = FeaturedFeeds::getFeeds( $langCode ); if ( !isset( $feeds[$feedName] ) ) { $out->showErrorPage( 'error', 'ffeed-feed-not-found', [ $feedName ] ); return; } $feed = $feeds[$feedName]; $timestamp = $this->parseTimestamp( $date ); if ( !$timestamp ) { $out->showErrorPage( 'error', 'ffeed-invalid-timestamp' ); return; } $date = FeaturedFeeds::startOfDay( $timestamp ); // First, search in the general cache foreach ( $feed->getFeedItems() as $item ) { if ( $item->getRawDate() == $date ) { $this->displayItem( $item ); return; } } $cache = $this->wanObjectCache; $item = $cache->getWithSetCallback( $cache->makeKey( 'featured-feed', $feedName, $date, $feed->getLanguage()->getCode() ), $cache::TTL_DAY, static function () use ( $feed, $date ) { $item = $feed->getFeedItem( $date ); if ( $item ) { return $item->toArray(); } return false; }, [ 'version' => FeaturedFeedChannel::VERSION ] ); if ( $item ) { $this->displayItem( FeaturedFeedItem::fromArray( $item ) ); } else { $out->showErrorPage( 'error', 'ffeed-entry-not-found', [ $this->getLanguage()->date( wfTimestamp( TS_UNIX, $date ), false, false ) ] ); } } /** * @param string $date * @return string|false */ private function parseTimestamp( $date ) { if ( strlen( $date ) !== 14 ) { return false; } return MWTimestamp::convert( TS_UNIX, $date ); } private function displayItem( FeaturedFeedItem $item ) { $out = $this->getOutput(); $out->setPageTitle( $item->getRawTitle() ); $out->addHTML( $item->getRawText() ); } } PK ! /�.�� � includes/Hooks/HookRunner.phpnu �[��� <?php // phpcs:disable MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName namespace MediaWiki\Extension\FeaturedFeeds\Hooks; use MediaWiki\HookContainer\HookContainer; /** * This is a hook runner class, see docs/Hooks.md in core. * @internal */ class HookRunner implements FeaturedFeedsGetFeedsHook { private HookContainer $hookContainer; public function __construct( HookContainer $hookContainer ) { $this->hookContainer = $hookContainer; } /** * @inheritDoc */ public function onFeaturedFeeds__getFeeds( array &$feedDefs ) { return $this->hookContainer->run( 'FeaturedFeeds::getFeeds', [ &$feedDefs ] ); } } PK ! �@�qk k , includes/Hooks/FeaturedFeedsGetFeedsHook.phpnu �[��� <?php // phpcs:disable MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName namespace MediaWiki\Extension\FeaturedFeeds\Hooks; /** * This is a hook handler interface, see docs/Hooks.md in core. * Use the hook name "FeaturedFeeds::getFeeds" to register handlers implementing this interface. * * @stable to implement * @ingroup Hooks */ interface FeaturedFeedsGetFeedsHook { /** * Adjust definition for featured feeds * * @param array &$feedDefs * @return bool|void True or no return value to continue or false to abort */ public function onFeaturedFeeds__getFeeds( array &$feedDefs ); } PK ! �i3j! ! includes/FeaturedFeeds.phpnu �[��� <?php namespace MediaWiki\Extension\FeaturedFeeds; use DateTime; use DateTimeZone; use MediaWiki\Extension\FeaturedFeeds\Hooks\HookRunner; use MediaWiki\Hook\SidebarBeforeOutputHook; use MediaWiki\MainConfigNames; use MediaWiki\MediaWikiServices; use MediaWiki\Output\Hook\BeforePageDisplayHook; use MediaWiki\Revision\RevisionRecord; use MediaWiki\Storage\EditResult; use MediaWiki\Storage\Hook\PageSaveCompleteHook; use MediaWiki\Title\Title; use MediaWiki\User\UserIdentity; use MediaWiki\Utils\MWTimestamp; use Skin; use Wikimedia\ObjectCache\WANObjectCache; use WikiPage; class FeaturedFeeds implements BeforePageDisplayHook, PageSaveCompleteHook, SidebarBeforeOutputHook { /** @var bool|null */ private static $allInContLang = null; /** * Returns the list of feeds * * @param string|bool $langCode Code of language to use or false if default * @return FeaturedFeedChannel[] Feeds in format of ('name' => FeedItem) */ public static function getFeeds( $langCode ) { global $wgLanguageCode; if ( !$langCode || self::allInContentLanguage() || !MediaWikiServices::getInstance()->getLanguageNameUtils()->isValidBuiltInCode( $langCode ) ) { $langCode = $wgLanguageCode; } $cache = MediaWikiServices::getInstance()->getMainWANObjectCache(); $feeds = $cache->getWithSetCallback( self::getCacheKey( $cache, $langCode ), self::getMaxAge(), function () use ( $langCode ) { return self::getFeedsInternal( $langCode ); }, [ // The "*" key is touched whenever a relevant message changes. // This avoids a slow explicit delete() of ~360 keys. 'checkKeys' => [ self::getCacheKey( $cache, '*' ) ], // Avoid I/O from repeated access 'pcGroup' => 'FeaturedFeeds:100', 'pcTTL' => $cache::TTL_PROC_LONG ] ); return self::getFeedsFromCached( $feeds ); } /** * Returns cache key for a given language * @param WANObjectCache $cache * @param string $langCode Feed language code * @return string */ private static function getCacheKey( WANObjectCache $cache, $langCode ) { return $cache->makeKey( 'featured-feeds', FeaturedFeedChannel::VERSION, $langCode ); } /** * Returns fully prepared feed definitions * @return array[] */ private static function getFeedDefinitions() { global $wgFeaturedFeeds, $wgFeaturedFeedsDefaults; static $feedDefs = false; if ( $feedDefs === false ) { $feedDefs = $wgFeaturedFeeds; ( new HookRunner( MediaWikiServices::getInstance()->getHookContainer() ) ) ->onFeaturedFeeds__getFeeds( $feedDefs ); // fill defaults self::$allInContLang = true; foreach ( $feedDefs as $name => $opts ) { foreach ( $wgFeaturedFeedsDefaults as $setting => $value ) { if ( !isset( $opts[$setting] ) ) { $feedDefs[$name][$setting] = $value; } } self::$allInContLang = self::$allInContLang && !$feedDefs[$name]['inUserLanguage']; } } return $feedDefs; } /** * Returns whether all feeds are in content language * @return bool */ public static function allInContentLanguage() { if ( self::$allInContLang === null ) { self::getFeedDefinitions(); } return self::$allInContLang; } /** * Adds feeds to the page header * * {@inheritDoc} */ public function onBeforePageDisplay( $out, $skin ): void { if ( $out->getTitle()->isMainPage() ) { $feeds = self::getFeedsQuick( $out->getLanguage()->getCode() ); $advertisedFeedTypes = $out->getConfig()->get( MainConfigNames::AdvertisedFeedTypes ); /** @var FeaturedFeedChannel $feed */ foreach ( $feeds as $feed ) { foreach ( $advertisedFeedTypes as $type ) { $out->addLink( [ 'rel' => 'alternate', 'type' => "application/$type+xml", 'title' => $feed->title, 'href' => $feed->getURL( $type ), ] ); } } } } /** * SidebarBeforeOutput hook handler * * @param Skin $skin * @param array &$sidebar */ public function onSidebarBeforeOutput( $skin, &$sidebar ): void { global $wgDisplayFeedsInSidebar, $wgAdvertisedFeedTypes; if ( !$skin->getTitle()->isMainPage() ) { return; } $msgDisabled = $skin->msg( 'ffeed-enable-sidebar-links' )->inContentLanguage()->isDisabled(); if ( !$wgDisplayFeedsInSidebar || $msgDisabled ) { return; } $feeds = self::getFeedsQuick( $skin->getLanguage()->getCode() ); $links = []; $format = $wgAdvertisedFeedTypes[0]; // @fixme: /** @var FeaturedFeedChannel $feed */ foreach ( $feeds as $feed ) { $links[] = [ 'href' => $feed->getURL( $format ), 'title' => $feed->title, 'text' => $feed->shortTitle, ]; } if ( count( $links ) ) { $sidebar['ffeed-sidebar-section'] = $links; } } /** * Purges cache on message edit * * @param WikiPage $wikiPage * @param UserIdentity $user * @param string $summary * @param int $flags * @param RevisionRecord $revisionRecord * @param EditResult $editResult */ public function onPageSaveComplete( $wikiPage, $user, $summary, $flags, $revisionRecord, $editResult ) { $title = $wikiPage->getTitle(); $cache = MediaWikiServices::getInstance()->getMainWANObjectCache(); // Although message names are configurable and can be set not to start with 'Ffeed', we // make a shortcut here to avoid running these checks on every NS_MEDIAWIKI edit if ( $title->getNamespace() == NS_MEDIAWIKI && strpos( $title->getText(), 'Ffeed-' ) === 0 ) { $baseTitle = Title::makeTitle( NS_MEDIAWIKI, $title->getBaseText() ); $messages = [ 'page', 'title', 'short-title', 'description', 'entryName' ]; foreach ( self::getFeedDefinitions() as $feed ) { foreach ( $messages as $msgType ) { $nt = Title::makeTitleSafe( NS_MEDIAWIKI, $feed[$msgType] ); if ( $nt->equals( $baseTitle ) ) { wfDebug( "FeaturedFeeds-related page {$title->getFullText()} edited, purging cache\n" ); $cache->touchCheckKey( self::getCacheKey( $cache, '*' ) ); return; } } } } } /** * Get all the feed objects without loading the items * * @param string $langCode * @return FeaturedFeedChannel[] */ private static function getFeedsQuick( $langCode ) { $feedDefs = self::getFeedDefinitions(); $feeds = []; foreach ( $feedDefs as $name => $opts ) { $feed = new FeaturedFeedChannel( $name, $opts, $langCode ); if ( !$feed->isOK() ) { continue; } $feeds[$name] = $feed; } return $feeds; } /** * @param string $langCode * @return array[] */ private static function getFeedsInternal( $langCode ) { $feeds = self::getFeedsQuick( $langCode ); $toCache = []; foreach ( $feeds as $name => $feed ) { $feed->getFeedItems(); $toCache[$name] = $feed->toArray(); } return $toCache; } /** * @param array[] $cached * @return FeaturedFeedChannel[] */ private static function getFeedsFromCached( array $cached ): array { $feeds = []; foreach ( $cached as $name => $array ) { $feeds[$name] = FeaturedFeedChannel::fromArray( $array ); } return $feeds; } /** * Returns the Unix timestamp of current day's first second * * @return int Timestamp */ public static function todaysStart() { static $time = false; if ( !$time ) { $time = self::startOfDay( time() ); } return $time; } /** * Returns the Unix timestamp of current week's first second * * @return int Timestamp */ public static function startOfThisWeek() { static $time = false; if ( !$time ) { $dt = new DateTime( 'this week', self::getTimezone() ); $dt->setTime( 0, 0, 0 ); $time = $dt->getTimestamp(); } return $time; } /** * Returns the Unix timestamp of current day's first second * * @param string|int $timestamp * @return int Timestamp */ public static function startOfDay( $timestamp ) { $dt = new DateTime( "@$timestamp", self::getTimezone() ); $dt->setTime( 0, 0, 0 ); return $dt->getTimestamp(); } /** * @return DateTimeZone */ private static function getTimezone() { global $wgLocaltimezone; static $timeZone; if ( $timeZone === null ) { $timeZone = new DateTimeZone( $wgLocaltimezone ); } return $timeZone; } /** * Returns the number of seconds a feed should stay in cache * * @return int Time in seconds */ public static function getMaxAge() { $ts = new MWTimestamp(); // add 10 seconds to cater for time deviation between servers $expiry = self::todaysStart() + 24 * 3600 - (int)$ts->getTimestamp() + 10; return min( $expiry, 3600 ); } } PK ! w=�!� � .git/info/excludenu �[��� # git ls-files --others --exclude-from=.git/info/exclude # Lines that start with '#' are comments. # For a project mostly in C, the following would be a good set of # exclude patterns (uncomment them if you want to use them): # *.[oa] # *~ PK ! s�:�� � .git/logs/HEADnu �[��� 0000000000000000000000000000000000000000 6b4a2dfe95d19a9c2866f110920eb8b19217453d root <root@wiki.beos.retro-os.live> 1734854659 -0800 clone: from https://gerrit.wikimedia.org/r/mediawiki/extensions/FeaturedFeeds PK ! s�:�� � "