Skip to content

Commit 95b791e

Browse files
Improve caching and terminology.
1 parent f4b093c commit 95b791e

File tree

5 files changed

+160
-44
lines changed

5 files changed

+160
-44
lines changed

config/gist_filter.settings.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,6 @@
22
"_config_name": "gist_filter.settings",
33
"github_token": "",
44
"gist_embed_theme": "default",
5-
"enable_noscript_display": 1
5+
"enable_noscript_display": 1,
6+
"cache_clear_with_all": 0
67
}

gist_filter.info

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ description = Adds a filter to embed Gists from GitHub anywhere in your text.
33
backdrop = 1.x
44
type = module
55

6+
configure = admin/config/content/gist-filter
7+
68
package = Input filters
79
tags[] = Filters
810
tags[] = Content

gist_filter.install

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?php
2+
/**
3+
* @file
4+
* Install and uninstall functions for the Gist Filter module.
5+
*/
6+
7+
/**
8+
* Implements hook_schema().
9+
*/
10+
function gist_filter_schema() {
11+
// Define a separate cache for gists so we have more control over when
12+
// the cached gists are cleared.
13+
$schema['cache_gists'] = backdrop_get_schema_unprocessed('system', 'cache');
14+
return $schema;
15+
}

gist_filter.module

Lines changed: 128 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -32,20 +32,22 @@ function gist_filter_filter_info() {
3232
* Implements hook_filter_info_alter().
3333
*/
3434
function gist_filter_filter_info_alter(&$info) {
35+
// If the Token Filter module is enabled we need to ensure it is processed
36+
// after Gist Filter to avoid it trying to interpret the token-like structure
37+
// of an embedded Gist filter.
3538
if (module_exists('token_filter')) {
3639
$info['filter_tokens']['weight'] = 1;
3740
}
3841
}
3942

40-
4143
/**
4244
* Implements hook_menu().
4345
*
4446
*/
4547
function gist_filter_menu() {
4648
$items = array();
4749
$items['admin/config/content/gist-filter'] = array(
48-
'title' => 'Gist Filter Global settings',
50+
'title' => 'Gist Filter Global Settings',
4951
'description' => 'Enter global settings for the Gist Filter module',
5052
'page callback' => 'backdrop_get_form',
5153
'page arguments' => array('gist_filter_config_form'),
@@ -62,7 +64,7 @@ function gist_filter_permission() {
6264
return array(
6365
'administer gist filter' => array(
6466
'title' => t('Administer Gist Filter global settings'),
65-
'description' => t('Configure global settings for Gist Filter, like authentication token and embed theme.'),
67+
'description' => t('Configure global settings for Gist Filter, such as authentication, theme and cache.'),
6668
),
6769
);
6870
}
@@ -73,12 +75,59 @@ function gist_filter_permission() {
7375
function gist_filter_config_info() {
7476
return array(
7577
'gist_filter.settings' => array(
76-
'label' => t('Gist Filter global settings'),
78+
'label' => t('Gist Filter settings'),
7779
'group' => t('Configuration'),
7880
),
7981
);
8082
}
8183

84+
/**
85+
* Implements hook_flush_caches().
86+
*/
87+
function gist_filter_flush_caches() {
88+
// Only add to the list of all caches to flush if enabled in settings.
89+
$clear_with_all = config_get('gist_filter.settings', 'cache_clear_with_all');
90+
// Also check the database table exists.
91+
if (db_table_exists('cache_gists') && $clear_with_all) {
92+
return array('cache_gists');
93+
}
94+
}
95+
96+
/**
97+
* Implements hook_admin_bar_cache_info().
98+
*/
99+
function gist_filter_admin_bar_cache_info() {
100+
// Add to the list of caches in the admin menu that can be individually
101+
// cleared.
102+
$caches['cache_gists'] = array(
103+
'title' => t('Gists'),
104+
'callback' => '_cache_gists_clear',
105+
);
106+
return $caches;
107+
}
108+
109+
/**
110+
* Clear the gists cache.
111+
*/
112+
function _cache_gists_clear() {
113+
// Clear all items from the gists cache.
114+
cache('cache_gists')->flush();
115+
// Also clear the entity_node and page caches to remove gists cached within a
116+
// page.
117+
cache('cache_entity_node')->flush();
118+
cache('page')->flush();
119+
}
120+
121+
/**
122+
* Submit callback; clear gist cache.
123+
*
124+
* @ingroup forms
125+
*/
126+
function _cache_gists_clear_submit($form, &$form_state) {
127+
_cache_gists_clear();
128+
backdrop_set_message(t('Gist, page and entity_node caches cleared.'));
129+
}
130+
82131
/**
83132
* Implements hook_theme().
84133
*/
@@ -129,6 +178,40 @@ function gist_filter_config_form($form, &$form_state) {
129178
$form['#config'] = $config_file;
130179
$config = config($config_file);
131180

181+
// Container for cache settings.
182+
$cache_scenarios = array(
183+
t("A gist is embedded using the <strong>code</strong> display method."),
184+
t("A gist is embedded using the <strong>embed</strong> display method, and the site is set to display using the <strong>code</strong> method if Javascript is disabled."),
185+
);
186+
$description = array(
187+
'<p>' . t("Gist Filter keeps gists saved in the cache if they haven't changed at source. Not only does this help pages with gists on to load faster, but it also reduces the risk of your site exceeding your GitHub API rate limit.") . '</p>',
188+
'<p>' . t("Gists are saved in the cache in the following scenarios:") . '</p>',
189+
theme('item_list', array('items' => $cache_scenarios)),
190+
'<p>' . t("Once saved in the cache, a gist by default remains in the cache. If the gist is updated, the cached gist will be updated when the page cache is next cleared.") . '</p>',
191+
'<p>' . t("If the setting below is enabled, then the gists cache will be cleared when running 'Flush all caches' or 'Page and else'. Otherwise, the gists cache can be cleared by selecting 'Gists' from the 'Flush all caches' submenu or using the button below.") . '</p>',
192+
);
193+
$description = implode('', $description);
194+
$form['cache'] = array(
195+
'#type' => 'details',
196+
'#summary' => t('Cache'),
197+
'#details' => $description,
198+
'#open' => TRUE,
199+
);
200+
201+
$form['cache']['clear'] = array(
202+
'#type' => 'submit',
203+
'#value' => t('Clear gists cache'),
204+
'#submit' => array('_cache_gists_clear_submit'),
205+
);
206+
207+
// Configure whether or not gist cache is cleared when flushing all caches.
208+
$form['cache']['cache_clear_with_all'] = array(
209+
'#type' => 'checkbox',
210+
'#title' => "Clear the gist cache when flushing all caches",
211+
'#description' => t("If you have a lot of gists throughout the site displayed as 'code' (or 'embed' with 'code' when Javascript is disabled) and those gists do not change regularly, then disabling the cache clear can avoid you breaching your GitHub API rate limit."),
212+
'#default_value' => $config->get('cache_clear_with_all'),
213+
);
214+
132215
// Container for 'code' display settings.
133216
$form['code'] = array(
134217
'#type' => 'details',
@@ -138,8 +221,7 @@ function gist_filter_config_form($form, &$form_state) {
138221

139222
// Prepare description for GitHub token field.
140223
$description = array(
141-
'<p>' . t("Each time a gist is retrieved to display as 'code' (rather than 'link' or 'embed'), GitHub counts this towards your limit. Anonymous users get 60 per hour; authenticated users get 5,000 per hour and Enterprise users get 15,000 per hour.") . '</p>',
142-
'<p>' . t("If you have a lot of gists displayed as 'code', then each time the page cache expires all the gists will be retrieved at once so you could easily hit the limit without a token.") . '</p>',
224+
'<p>' . t("Each time a gist is retrieved to display as 'code', GitHub counts this towards your API rate limit. Anonymous users get 60 per hour; authenticated users get 5,000 per hour and Enterprise users get 15,000 per hour. If your number of gists is low, you probably won't need a token.") . '</p>',
143225
'<p>' . t("If you don't already have a token, you will need to go to <a href='@github-tokens' target='_blank'>your GitHub tokens page</a> and create a token.", array(
144226
'@github-tokens' => 'https://github.com/settings/tokens',
145227
)) . '</p>',
@@ -183,6 +265,7 @@ function gist_filter_config_form($form, &$form_state) {
183265
'#type' => 'select',
184266
'#title' => 'Gist Embed Theme',
185267
'#options' => $gist_themes,
268+
'#required' => TRUE,
186269
'#default_value' => $config->get('gist_embed_theme'),
187270
'#description' => t("Themes are from <a href='@developer'>Will Boyd</a> and can be previewed on <a href='@preview-page'>this page</a>.", array(
188271
'@developer' => 'https://github.com/lonekorean/gist-syntax-themes',
@@ -193,8 +276,8 @@ function gist_filter_config_form($form, &$form_state) {
193276
// Allow disabling the 'noscript' display of code block to save on API calls.
194277
$form['embed']['enable_noscript_display'] = array(
195278
'#type' => 'checkbox',
196-
'#title' => "Display 'code' version if Javascript is disabled.",
197-
'#description' => t("If Javascript is disabled, then enabling this option will use 'code' display of the gist. This may cause additional calls to the GitHub API if the gist is not in the cache."),
279+
'#title' => "Display using 'code' method if Javascript is disabled",
280+
'#description' => t("Enabling this option will include the 'code' display method of the gist to display if Javascript is disabled."),
198281
'#default_value' => $config->get('enable_noscript_display'),
199282
);
200283

@@ -357,35 +440,50 @@ function gist_filter_get_gist($id) {
357440

358441
// First, try the static cache.
359442
if (!isset($gists[$id])) {
443+
// Not in the static cache so we will check the cache tables and if it
444+
// exists, we will check to see if the source has changed. If it doesn't
445+
// exist, we will download and cache it.
446+
// Start preparing the request.
447+
// Define standard header.
448+
$headers = array();
449+
$headers['Content-Type'] = 'application/json';
450+
451+
// Include the GitHub Personal Access token if it is set.
452+
$token = config_get('gist_filter.settings', 'github_token');
453+
if (!empty($token)) {
454+
$headers['Authorization'] = 'token ' . $token;
455+
}
456+
360457
// Compile the gist cache ID.
361458
$cid = 'gist_filter:gist:' . $id;
362459
// Check if this gist is already in the cache.
363-
$gist = cache_get($cid);
364-
if ($cached = cache_get($cid)) {
460+
// $gist = cache_get($cid);
461+
if ($cached = cache_get($cid, 'cache_gists')) {
462+
// Retrieve the gist so it can be used if the source hasn't changed.
365463
$gist = $cached->data;
464+
// Retrieve the gist etag so we can check if the source has changed or
465+
// not.
466+
$gist_etag = $gist['etag'];
467+
// Prepare the header for checking against the etag.
468+
$headers['If-None-Match'] = "$gist_etag";
366469
}
367-
else {
368-
// Not available in the cache, so retrieve the gist from Github.
369-
// Define standard header.
370-
$headers = array();
371-
$headers['Content-Type'] = 'application/json';
372-
// Include the GitHub Personal Access token if it is set.
373-
$token = config_get('gist_filter.settings', 'github_token');
374-
if (!empty($token)) {
375-
$headers['Authorization'] = 'token ' . $token;
376-
}
377-
$options = array();
378-
$options['headers'] = $headers;
379-
// Compile and submit the request.
380-
$url = 'https://api.github.com/gists/' . $id;
381-
$response = backdrop_http_request($url, $options);
382-
$gist = backdrop_json_decode($response->data);
383470

384-
// Cache the gist until the next cache flush.
385-
cache_set($cid, $gist, 'cache', CACHE_PERMANENT);
471+
// Finalise the request.
472+
$options = array();
473+
$options['headers'] = $headers;
474+
// Compile and submit the request.
475+
$url = 'https://api.github.com/gists/' . $id;
476+
$response = backdrop_http_request($url, $options);
477+
478+
// Process the response.
479+
if ($response->code == "200") {
480+
$gist = backdrop_json_decode($response->data);
481+
$gist['etag'] = $response->headers['etag'];
482+
// Cache the gist.
483+
cache_set($cid, $gist, 'cache_gists', CACHE_PERMANENT);
386484
}
387-
// Return the cached or retrieved gist.
388-
$gists[$id] = $gist;
389485
}
486+
// Return the cached or retrieved gist.
487+
$gists[$id] = $gist;
390488
return $gists[$id];
391489
}

tests/gist_filter.test

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -51,12 +51,12 @@ class GistFilterTestCase extends BackdropWebTestCase {
5151
$langcode = LANGUAGE_NONE;
5252
$edit = array(
5353
"title" => $this->randomName(),
54-
"body[$langcode][0][value]" => 'Hello! [gist:865412]',
54+
"body[$langcode][0][value]" => 'Hello! [gist:6d453c053fd8677cb1f40ad1786efdac]',
5555
);
5656
$this->backdropPost('node/add/' . $this->contentType->type, $edit, t('Save'));
5757
$this->assertResponse(200);
5858
$this->assertRaw("Hello! ");
59-
$this->assertRaw('<script src="//gist.github.com/865412.js"></script>');
59+
$this->assertRaw('<script src="//gist.github.com/6d453c053fd8677cb1f40ad1786efdac.js"></script>');
6060
}
6161

6262
/**
@@ -82,12 +82,12 @@ class GistFilterTestCase extends BackdropWebTestCase {
8282
$langcode = LANGUAGE_NONE;
8383
$edit = array(
8484
"title" => $this->randomName(),
85-
"body[$langcode][0][value]" => 'Hello! [gist:865412:php_file.php]',
85+
"body[$langcode][0][value]" => 'Hello! [gist:6d453c053fd8677cb1f40ad1786efdac:php_file.php]',
8686
);
8787
$result = $this->backdropPost('node/add/' . $this->contentType->type, $edit, t('Save'));
8888
$this->assertResponse(200);
8989
$this->assertRaw("Hello! ");
90-
$this->assertRaw('<script src="//gist.github.com/865412.js?file=php_file.php"></script>');
90+
$this->assertRaw('<script src="//gist.github.com/6d453c053fd8677cb1f40ad1786efdac.js?file=php_file.php"></script>');
9191
}
9292

9393
/**
@@ -114,11 +114,11 @@ class GistFilterTestCase extends BackdropWebTestCase {
114114
$langcode = LANGUAGE_NONE;
115115
$edit = array(
116116
"title" => $this->randomName(),
117-
"body[$langcode][0][value]" => 'Hello! [gist:865412]',
117+
"body[$langcode][0][value]" => 'Hello! [gist:6d453c053fd8677cb1f40ad1786efdac]',
118118
);
119119
$result = $this->backdropPost('node/add/' . $this->contentType->type, $edit, t('Save'));
120120
$this->assertResponse(200);
121-
$this->assertRaw('Hello! <a href="https://gist.github.com/865412">https://gist.github.com/865412</a>');
121+
$this->assertRaw('Hello! <a href="https://gist.github.com/6d453c053fd8677cb1f40ad1786efdac">https://gist.github.com/6d453c053fd8677cb1f40ad1786efdac</a>');
122122

123123
}
124124

@@ -145,11 +145,11 @@ class GistFilterTestCase extends BackdropWebTestCase {
145145
$langcode = LANGUAGE_NONE;
146146
$edit = array(
147147
"title" => $this->randomName(),
148-
"body[$langcode][0][value]" => 'Hello! [gist:865412:php_file.php]',
148+
"body[$langcode][0][value]" => 'Hello! [gist:6d453c053fd8677cb1f40ad1786efdac:php_file.php]',
149149
);
150150
$result = $this->backdropPost('node/add/' . $this->contentType->type, $edit, t('Save'));
151151
$this->assertResponse(200);
152-
$this->assertRaw('Hello! <a href="https://gist.github.com/865412#file_php_file.php">https://gist.github.com/865412#file_php_file.php</a>');
152+
$this->assertRaw('Hello! <a href="https://gist.github.com/6d453c053fd8677cb1f40ad1786efdac#file_php_file.php">https://gist.github.com/6d453c053fd8677cb1f40ad1786efdac#file_php_file.php</a>');
153153

154154
}
155155

@@ -176,7 +176,7 @@ class GistFilterTestCase extends BackdropWebTestCase {
176176
$langcode = LANGUAGE_NONE;
177177
$edit = array(
178178
"title" => $this->randomName(),
179-
"body[$langcode][0][value]" => 'Hello! [gist:865412]',
179+
"body[$langcode][0][value]" => 'Hello! [gist:6d453c053fd8677cb1f40ad1786efdac]',
180180
);
181181
$result = $this->backdropPost('node/add/' . $this->contentType->type, $edit, t('Save'));
182182
$this->assertResponse(200);
@@ -190,13 +190,13 @@ class GistFilterTestCase extends BackdropWebTestCase {
190190
*/
191191
public function testGistCachingTest() {
192192
// Make sure our cache is all cleared first.
193-
cache_clear_all('gist_filter:gist', 'cache', TRUE);
194-
$this->assertFalse(cache_get('gist_filter:gist:865412'));
193+
cache('cache_gists')->flush();
194+
$this->assertFalse(cache_get('gist_filter:gist:6d453c053fd8677cb1f40ad1786efdac', 'cache_gists'));
195195

196-
gist_filter_get_gist(865412);
196+
gist_filter_get_gist('6d453c053fd8677cb1f40ad1786efdac');
197197

198198
// Now the cache should be set.
199-
$cached = cache_get('gist_filter:gist:865412');
199+
$cached = cache_get('gist_filter:gist:6d453c053fd8677cb1f40ad1786efdac', 'cache_gists');
200200
$this->assertTrue($cached->data);
201201
}
202202
}

0 commit comments

Comments
 (0)