MarkTraceur has uploaded a new change for review.

  https://gerrit.wikimedia.org/r/308775

Change subject: Cache, cache, everywhere a cache
......................................................................

Cache, cache, everywhere a cache

Cache API requests and rendering for WD, WP, and Commons annotations,
because fetching data from those sites is not super efficient.

Only caching for five minutes currently, to avoid making it totally
impossible to get updated data in a timely manner. Thoughts?

Change-Id: Ic319afc11e5befdab26542616cda85b52ff61512
---
M ApiFileAnnotations.php
1 file changed, 177 insertions(+), 129 deletions(-)


  git pull 
ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/FileAnnotations 
refs/changes/75/308775/1

diff --git a/ApiFileAnnotations.php b/ApiFileAnnotations.php
index 5ac4e4f..2af9c53 100644
--- a/ApiFileAnnotations.php
+++ b/ApiFileAnnotations.php
@@ -25,6 +25,12 @@
  */
 
 class ApiFileAnnotations extends ApiQueryBase {
+       // 5 minutes - long enough to avoid crashing the servers with a lot
+       // of repeated requests for the same data, but not long enough so it's
+       // hard to update information quickly. Cache not invalidated by changes
+       // to Wikidata, Wikipedia, or Commons.
+       const CACHE_TTL = 300;
+
        public function __construct( $query, $moduleName ) {
                parent::__construct( $query, $moduleName, 'fa' );
        }
@@ -81,169 +87,211 @@
        protected function renderCommonsAnnotation( $commonsMatches, 
$commonsCategoryMatch ) {
                $categoryName = $commonsMatches[1];
 
-               $imagesApiDataStr = file_get_contents(
-                       'https://commons.wikimedia.org/w/api.php' .
-                       '?action=query' .
-                       '&prop=imageinfo' .
-                       '&generator=categorymembers' .
-                       '&gcmtype=file' .
-                       '&gcmtitle=' . urlencode( $categoryName ) .
-                       '&gcmlimit=5' .
-                       '&iiprop=url' .
-                       '&iiurlwidth=100' .
-                       '&iiurlheight=100' .
-                       '&format=json'
-               );
+               $key = wfMemcKey( 'fileannotations', 'commonscategory', 
$categoryName );
+               $cache = wfGetCache( CACHE_ANYTHING );
+               $parsed = $cache->get( $key );
 
-               $imagesApiData = json_decode( $imagesApiDataStr, true );
+               if ( $parsed === false ) {
+                       $imagesApiDataStr = file_get_contents(
+                               'https://commons.wikimedia.org/w/api.php' .
+                               '?action=query' .
+                               '&prop=imageinfo' .
+                               '&generator=categorymembers' .
+                               '&gcmtype=file' .
+                               '&gcmtitle=' . urlencode( $categoryName ) .
+                               '&gcmlimit=5' .
+                               '&iiprop=url' .
+                               '&iiurlwidth=100' .
+                               '&iiurlheight=100' .
+                               '&format=json'
+                       );
 
-               $pages = $imagesApiData['query']['pages'];
+                       $imagesApiData = json_decode( $imagesApiDataStr, true );
 
-               $imagesHtml = '<div class="category-members">';
+                       $pages = $imagesApiData['query']['pages'];
 
-               foreach ( $pages as $id => $page ) {
-                       $info = $page['imageinfo'][0];
-                       $href = $info['descriptionurl'];
-                       $src = $info['thumburl'];
+                       $imagesHtml = '<div class="category-members">';
 
-                       $imagesHtml .=
-                               '<a class="category-member" href="' . $href . 
'">' .
-                                       '<img src="' . $src . '" />' .
-                               '</a>';
+                       foreach ( $pages as $id => $page ) {
+                               $info = $page['imageinfo'][0];
+                               $href = $info['descriptionurl'];
+                               $src = $info['thumburl'];
+
+                               $imagesHtml .=
+                                       '<a class="category-member" href="' . 
$href . '">' .
+                                               '<img src="' . $src . '" />' .
+                                       '</a>';
+                       }
+
+                       $imagesHtml .= '</div>';
+
+                       $parsed =
+                               '<div class="commons-category-annotation">' .
+                                       $imagesHtml .
+                                       '<a href="' . $href . '">' .
+                                               'See more images' .
+                                       '</a>' .
+                               '</div>';
+
+                       $cache->set(
+                               $key,
+                               $parsed,
+                               self::CACHE_TTL
+                       );
                }
 
-               $imagesHtml .= '</div>';
-
-               return
-                       '<div class="commons-category-annotation">' .
-                               $imagesHtml .
-                               '<a href="' . $href . '">' .
-                                       'See more images' .
-                               '</a>' .
-                       '</div>';
+               return $parsed;
        }
 
        protected function renderWikipediaAnnotation( $wpMatches, 
$wpArticleMatch ) {
                $articleName = $wpMatches[2];
+               $language = $wpMatches[1];
 
-               $articleApiDataStr = file_get_contents(
-                       $wpMatches[1] .
-                       '/w/api.php?action=query' .
-                       '&titles=' . urlencode( $articleName ) .
-                       '&prop=pageimages|extracts' .
-                       '&piprop=thumbnail|name' .
-                       '&pithumbsize=250' .
-                       '&exsentences=4' .
-                       '&format=json'
-               );
+               $key = wfMemcKey( 'fileannotations', 'wikipediapage', 
$language, $articleName );
+               $cache = wfGetCache( CACHE_ANYTHING );
+               $parsed = $cache->get( $key );
 
-               $articleApiData = json_decode( $articleApiDataStr, true );
+               if ( $parsed === false ) {
+                       $articleApiDataStr = file_get_contents(
+                               $language .
+                               '/w/api.php?action=query' .
+                               '&titles=' . urlencode( $articleName ) .
+                               '&prop=pageimages|extracts' .
+                               '&piprop=thumbnail|name' .
+                               '&pithumbsize=250' .
+                               '&exsentences=4' .
+                               '&format=json'
+                       );
 
-               $pages = $articleApiData['query']['pages'];
+                       $articleApiData = json_decode( $articleApiDataStr, true 
);
 
-               foreach ( $pages as $id => $page ) {
-                       // There's only one page, so just do it here
-                       return
-                               '<div class="wikipedia-article-annotation">' .
-                                       $page['extract'] .
-                                       '<p class="pageimage">' .
-                                               '<img src="' .
-                                                       
$page['thumbnail']['source'] .
-                                                       '" width="' .
-                                                       
$page['thumbnail']['width'] .
-                                                       '" height="' .
-                                                       
$page['thumbnail']['height'] .
-                                               '" />' .
-                                       '</p>' .
-                               '</div>';
+                       $pages = $articleApiData['query']['pages'];
+
+                       foreach ( $pages as $id => $page ) {
+                               // There's only one page, so just do it here
+                               $parsed =
+                                       '<div 
class="wikipedia-article-annotation">' .
+                                               $page['extract'] .
+                                               '<p class="pageimage">' .
+                                                       '<img src="' .
+                                                               
$page['thumbnail']['source'] .
+                                                               '" width="' .
+                                                               
$page['thumbnail']['width'] .
+                                                               '" height="' .
+                                                               
$page['thumbnail']['height'] .
+                                                       '" />' .
+                                               '</p>' .
+                                       '</div>';
+                               break;
+                       }
+
+                       $cache->set(
+                               $key,
+                               $parsed,
+                               self::CACHE_TTL
+                       );
                }
+
+               return $parsed;
        }
 
        protected function renderWikidataAnnotation( $wdMatches, $wdEntityMatch 
) {
                $entityId = $wdMatches[2];
                $currentLang = $this->getLanguage()->getCode();
 
-               $entityApiDataStr = file_get_contents(
-                       'https://www.wikidata.org/w/api.php' .
-                       '?action=wbgetentities' .
-                       '&ids=' . $entityId .
-                       '&languages=en|' . $currentLang .
-                       '&props=labels|descriptions|claims' .
-                       '&format=json'
-               );
+               $key = wfMemcKey( 'fileannotations', 'wikidataentity', 
$currentLang, $entityId );
+               $cache = wfGetCache( CACHE_ANYTHING );
+               $parsed = $cache->get( $key );
 
-               $entityApiData = json_decode( $entityApiDataStr, true );
+               if ( $parsed === false ) {
+                       $entityApiDataStr = file_get_contents(
+                               'https://www.wikidata.org/w/api.php' .
+                               '?action=wbgetentities' .
+                               '&ids=' . $entityId .
+                               '&languages=en|' . $currentLang .
+                               '&props=labels|descriptions|claims' .
+                               '&format=json'
+                       );
 
-               $entity = $entityApiData['entities'][$entityId];
+                       $entityApiData = json_decode( $entityApiDataStr, true );
 
-               $labels = $entity['labels'];
-               $descriptions = $entity['descriptions'];
-               $claims = $entity['claims'];
+                       $entity = $entityApiData['entities'][$entityId];
 
-               $imageHtml = null;
+                       $labels = $entity['labels'];
+                       $descriptions = $entity['descriptions'];
+                       $claims = $entity['claims'];
 
-               foreach ( $claims as $claimid => $claim ) {
-                       switch ( $claimid ) {
-                               case 'P18':
-                                       // Main image. Fetch imageinfo and 
render.
-                                       $imageHtml = $this->renderWdImage(
-                                               
$claim[0]['mainsnak']['datavalue']['value']
-                                       );
-                                       break;
+                       $imageHtml = null;
 
-                               default:
-                                       continue;
-                       }
-               }
+                       foreach ( $claims as $claimid => $claim ) {
+                               switch ( $claimid ) {
+                                       case 'P18':
+                                               // Main image. Fetch imageinfo 
and render.
+                                               $imageHtml = 
$this->renderWdImage(
+                                                       
$claim[0]['mainsnak']['datavalue']['value']
+                                               );
+                                               break;
 
-               $label = null;
-               $description = null;
-
-               if ( isset( $labels[$currentLang] ) ) {
-                       $label =
-                               '<h2 class="wikidata-label">' .
-                                       $labels[$currentLang]['value'] .
-                               '</h2>';
-               } elseif ( isset( $labels['en'] ) ) {
-                       // Blatantly strange fallback, but we don't want to have
-                       // no label...hopefully this works for 99% of things.
-                       $label =
-                               '<h2 class="wikidata-label">' .
-                                       $labels['en']['value'] .
-                               '</h2>';
-               }
-
-               if ( isset( $descriptions[$currentLang] ) ) {
-                       $description =
-                               '<p class="wikidata-description">' .
-                                       $descriptions[$currentLang]['value'] .
-                               '</p>';
-               } elseif ( isset( $descriptions['en'] ) ) {
-                       $description =
-                               '<p class="wikidata-description">' .
-                                       $descriptions['en']['value'] .
-                               '</p>';
-               }
-
-               $html = '<div class="wikidata-entity-annotation">';
-
-               if ( !is_null( $imageHtml ) ) {
-                       $html .= $imageHtml;
-               }
-
-               if ( !is_null( $label ) || !is_null( $description ) ) {
-                       $html .= '<div class="text-content">';
-
-                       if ( !is_null( $label ) ) {
-                               $html .= $label;
+                                       default:
+                                               continue;
+                               }
                        }
 
-                       if ( !is_null( $description ) ) {
-                               $html .= $description;
+                       $label = null;
+                       $description = null;
+
+                       if ( isset( $labels[$currentLang] ) ) {
+                               $label =
+                                       '<h2 class="wikidata-label">' .
+                                               $labels[$currentLang]['value'] .
+                                       '</h2>';
+                       } elseif ( isset( $labels['en'] ) ) {
+                               // Blatantly strange fallback, but we don't 
want to have
+                               // no label...hopefully this works for 99% of 
things.
+                               $label =
+                                       '<h2 class="wikidata-label">' .
+                                               $labels['en']['value'] .
+                                       '</h2>';
                        }
+
+                       if ( isset( $descriptions[$currentLang] ) ) {
+                               $description =
+                                       '<p class="wikidata-description">' .
+                                               
$descriptions[$currentLang]['value'] .
+                                       '</p>';
+                       } elseif ( isset( $descriptions['en'] ) ) {
+                               $description =
+                                       '<p class="wikidata-description">' .
+                                               $descriptions['en']['value'] .
+                                       '</p>';
+                       }
+
+                       $parsed = '<div class="wikidata-entity-annotation">';
+
+                       if ( !is_null( $imageHtml ) ) {
+                               $parsed .= $imageHtml;
+                       }
+
+                       if ( !is_null( $label ) || !is_null( $description ) ) {
+                               $parsed .= '<div class="text-content">';
+
+                               if ( !is_null( $label ) ) {
+                                       $parsed .= $label;
+                               }
+
+                               if ( !is_null( $description ) ) {
+                                       $parsed .= $description;
+                               }
+                       }
+
+                       $cache->set(
+                               $key,
+                               $parsed,
+                               self::CACHE_TTL
+                       );
                }
 
-               return $html;
+               return $parsed;
        }
 
        protected function renderWdImage( $imageTitle ) {

-- 
To view, visit https://gerrit.wikimedia.org/r/308775
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: Ic319afc11e5befdab26542616cda85b52ff61512
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/FileAnnotations
Gerrit-Branch: master
Gerrit-Owner: MarkTraceur <[email protected]>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to