diff options
Diffstat (limited to 'www/wiki/extensions/Gadgets/includes/GadgetDefinitionNamespaceRepo.php')
-rw-r--r-- | www/wiki/extensions/Gadgets/includes/GadgetDefinitionNamespaceRepo.php | 167 |
1 files changed, 167 insertions, 0 deletions
diff --git a/www/wiki/extensions/Gadgets/includes/GadgetDefinitionNamespaceRepo.php b/www/wiki/extensions/Gadgets/includes/GadgetDefinitionNamespaceRepo.php new file mode 100644 index 00000000..fdecee80 --- /dev/null +++ b/www/wiki/extensions/Gadgets/includes/GadgetDefinitionNamespaceRepo.php @@ -0,0 +1,167 @@ +<?php + +use MediaWiki\Linker\LinkTarget; +use MediaWiki\MediaWikiServices; +use Wikimedia\Rdbms\Database; + +/** + * GadgetRepo implementation where each gadget has a page in + * the Gadget definition namespace, and scripts and styles are + * located in the Gadget namespace. + */ +class GadgetDefinitionNamespaceRepo extends GadgetRepo { + /** + * How long in seconds the list of gadget ids and + * individual gadgets should be cached for (1 day) + */ + const CACHE_TTL = 86400; + + /** + * @var WANObjectCache + */ + private $wanCache; + + public function __construct() { + $this->wanCache = MediaWikiServices::getInstance()->getMainWANObjectCache(); + } + + /** + * Get a list of gadget ids from cache/database + * + * @return string[] + */ + public function getGadgetIds() { + $key = $this->getGadgetIdsKey(); + + return $this->wanCache->getWithSetCallback( + $key, + self::CACHE_TTL, + function ( $oldValue, &$ttl, array &$setOpts ) { + $dbr = wfGetDB( DB_REPLICA ); + $setOpts += Database::getCacheSetOptions( $dbr ); + + return $dbr->selectFieldValues( + 'page', + 'page_title', + [ 'page_namespace' => NS_GADGET_DEFINITION ], + __METHOD__ + ); + }, + [ + 'checkKeys' => [ $key ], + 'pcTTL' => WANObjectCache::TTL_PROC_SHORT, + 'lockTSE' => 30 + ] + ); + } + + /** + * @inheritDoc + */ + public function handlePageUpdate( LinkTarget $target ) { + if ( $target->inNamespace( NS_GADGET_DEFINITION ) ) { + $this->purgeGadgetEntry( $target->getText() ); + } + } + + /** + * @inheritDoc + */ + public function handlePageCreation( LinkTarget $target ) { + if ( $target->inNamespace( NS_GADGET_DEFINITION ) ) { + $this->purgeGadgetIdsList(); + } + } + + /** + * @inheritDoc + */ + public function handlePageDeletion( LinkTarget $target ) { + if ( $target->inNamespace( NS_GADGET_DEFINITION ) ) { + $this->purgeGadgetIdsList(); + $this->purgeGadgetEntry( $target->getText() ); + } + } + + /** + * Purge the list of gadget ids when a page is deleted or if a new page is created + */ + public function purgeGadgetIdsList() { + $this->wanCache->touchCheckKey( $this->getGadgetIdsKey() ); + } + + /** + * @param string $id + * @throws InvalidArgumentException + * @return Gadget + */ + public function getGadget( $id ) { + $key = $this->getGadgetCacheKey( $id ); + $gadget = $this->wanCache->getWithSetCallback( + $key, + self::CACHE_TTL, + /** + * @suppress PhanTypeMismatchArgument + */ + function ( $old, &$ttl, array &$setOpts ) use ( $id ) { + $setOpts += Database::getCacheSetOptions( wfGetDB( DB_REPLICA ) ); + $title = Title::makeTitleSafe( NS_GADGET_DEFINITION, $id ); + if ( !$title ) { + $ttl = WANObjectCache::TTL_UNCACHEABLE; + return null; + } + + $rev = Revision::newFromTitle( $title ); + if ( !$rev ) { + $ttl = WANObjectCache::TTL_UNCACHEABLE; + return null; + } + + $content = $rev->getContent(); + if ( !$content instanceof GadgetDefinitionContent ) { + // Uhm... + $ttl = WANObjectCache::TTL_UNCACHEABLE; + return null; + } + + return Gadget::newFromDefinitionContent( $id, $content ); + }, + [ + 'checkKeys' => [ $key ], + 'pcTTL' => WANObjectCache::TTL_PROC_SHORT, + 'lockTSE' => 30 + ] + ); + + if ( $gadget === null ) { + throw new InvalidArgumentException( "No gadget registered for '$id'" ); + } + + return $gadget; + } + + /** + * Update the cache for a specific Gadget whenever it is updated + * + * @param string $id + */ + public function purgeGadgetEntry( $id ) { + $this->wanCache->touchCheckKey( $this->getGadgetCacheKey( $id ) ); + } + + /** + * @return string + */ + private function getGadgetIdsKey() { + return $this->wanCache->makeKey( 'gadgets', 'namespace', 'ids' ); + } + + /** + * @param string $id + * @return string + */ + private function getGadgetCacheKey( $id ) { + return $this->wanCache->makeKey( + 'gadgets', 'object', md5( $id ), Gadget::GADGET_CLASS_VERSION ); + } +} |