summaryrefslogtreecommitdiff
path: root/www/wiki/extensions/Gadgets/includes/GadgetDefinitionNamespaceRepo.php
diff options
context:
space:
mode:
Diffstat (limited to 'www/wiki/extensions/Gadgets/includes/GadgetDefinitionNamespaceRepo.php')
-rw-r--r--www/wiki/extensions/Gadgets/includes/GadgetDefinitionNamespaceRepo.php167
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 );
+ }
+}