From 8f9486ddecbb355dc48ad417fd859a6e21aed883 Mon Sep 17 00:00:00 2001 From: Joseph McGuire Date: Wed, 19 Oct 2011 17:23:32 +0100 Subject: [PATCH] Added support for Queue API so that requests for short urls can be optionally queued and processed by a background process [#1313274] --- shorten.admin.inc | 15 ++++++- shorten.install | 3 +- shorten.module | 119 ++++++++++++++++++++++++++++++++++++++++++---------- 3 files changed, 112 insertions(+), 25 deletions(-) diff --git a/shorten.admin.inc b/shorten.admin.inc index c4e705d..7450fb6 100644 --- a/shorten.admin.inc +++ b/shorten.admin.inc @@ -87,6 +87,19 @@ function shorten_admin($form_state) { '#description' => t('Allow users to choose which service to use in the Shorten URLs block and page.'), ); } + $queue_module_url = 'http://drupal.org/project/drupal_queue'; + $form['shorten_workflow'] = array( + '#type' => 'radios', + '#title' => t('When to process'), + '#description' => t('The default is to request short URLs when a page is rendered which can slow down the time it take to deliver a page. If you have the Queue API module enabled then you can also queue request to process at a later time.'), + '#options' => array( + 'render' => t('Request while the page is rendered.'), + 'queue' => t('Queue requests to fetch at a later time. Requires Queue API.', array('@queue_module_url' => $queue_module_url)), + ), + '#default_value' => module_exists('drupal_queue') ? variable_get('shorten_workflow', 'render') : 'render', + '#disabled' => module_exists('drupal_queue') ? FALSE : TRUE, + ); + if (module_exists('token')) { $form['shorten_generate_token'] = array( '#type' => 'checkbox', @@ -258,4 +271,4 @@ function shorten_keys($form_state) { '#default_value' => variable_get('shorten_redirec', ''), ); return system_settings_form($form); -} \ No newline at end of file +} diff --git a/shorten.install b/shorten.install index ddf5a2e..a74525f 100644 --- a/shorten.install +++ b/shorten.install @@ -47,6 +47,7 @@ function shorten_uninstall() { variable_del('shorten_service_backup'); variable_del('shorten_invisible_services'); variable_del('shorten_cache_fail_duration'); + variable_del('shorten_workflow'); } /** @@ -96,4 +97,4 @@ function shorten_update_6102() { variable_set('shorten_service_backup', 'Drupal ShortURL module'); } return array(); -} \ No newline at end of file +} diff --git a/shorten.module b/shorten.module index 6f88dfc..16b6b65 100644 --- a/shorten.module +++ b/shorten.module @@ -109,6 +109,17 @@ function shorten_flush_caches() { } /** + * Implementation of hook_cron_queue_info(). + */ +function shorten_cron_queue_info() { + $queues['shorten'] = array( + 'worker callback' => 'shorten_url_cron_queue', + 'time' => 60, + ); + return $queues; +} + +/** * Retrieves and beautifies the abbreviated URL. * This is the main API function of this module. * @@ -118,22 +129,87 @@ function shorten_flush_caches() { * @param $service * The service to use to abbreviate the URL. * For services available by default, see shorten_shorten_service(). + * * @return * An abbreviated URL. */ -function shorten_url($original = '', $service = '') { +function shorten_url($original = '', $service = '', $options = array()) { + + $default_options = array( + 'use queue' => TRUE, + 'check cache' => TRUE, + ); + $options = array_merge($default_options, $options); + if (!$original) { $original = url($_GET['q'], array('absolute' => TRUE, 'alias' => !variable_get('shorten_use_alias', 1))); } if (!$service) { $service = variable_get('shorten_service', 'is.gd'); } - //First try to retrieve a value from the cache. - $cached = cache_get($original, 'cache_shorten'); - if (!empty($cached->data) && time() < $cached->expire) { - return $cached->data; + + if ($options['check cache']) { + $cached = cache_get($original, 'cache_shorten'); + if (!empty($cached->data)) { + return $cached->data; + } } - //We don't have anything cached for this URL, so try the primary service (or the one explicitly requested in the $service parameter). + + // If queueing requests is supported and enabled then create an item and + // cache the original to avoid multiple queue items being created. + if ($options['use queue'] && variable_get('shorten_workflow', 'render') == 'queue' && module_exists('drupal_queue')) { + _shorten_queue_item($original, $service); + cache_set($original, $original, 'cache_shorten', CACHE_TEMPORARY); + return $original; + } + + // There was no suitable cache and the queue is not being used so now we can + // request the short URL and cache the results. + if ($url = _shorten_url($original, $service)) { + $cache_duration = variable_get('shorten_cache_duration', 1814400); + $expire = is_numeric($cache_duration) ? (time() + $cache_duration) : CACHE_PERMANENT; + } + else { + // The URL failed to be shortened so cache the original for a short time. + $cache_duration = variable_get('shorten_cache_fail_duration', 1800); + $expire = time() + $cache_duration; + $url = $original; + } + cache_set($original, $url, 'cache_shorten', $expire); + + // Announce that we have a new short URL and return it. + module_invoke_all('shorten_create', $original, $url, $service); + return $url; +} + +/** + * Helper function to create a shorten Queue API item. + */ +function _shorten_queue_item($original, $service) { + $queue = DrupalQueue::get('shorten'); + $item = array( + 'original' => $original, + 'service' => $service, + ); + $queue->createItem($item); +} + +/** + * Helper function to call the shortening service. + * + * Method also check a secondary service if the first fails. + * + * @param $original + * The URL of the page for which to create the abbreviated URL. If not passed + * uses the current page. + * @param $service + * The service to use to abbreviate the URL. + * For services available by default, see shorten_shorten_service(). + * + * @return + * An abbreviated URL or FALSE if one could not be generated. + */ +function _shorten_url($original, $service) { $services = module_invoke_all('shorten_service'); if (isset($services[$service])) { $url = _shorten_get_url($original, $services[$service], $service); @@ -144,9 +220,9 @@ function shorten_url($original = '', $service = '') { if (isset($services[$service])) { $url = _shorten_get_url($original, $services[$service], $service); } - //If the secondary service fails, use the original URL. + //If the secondary service fails return FALSE. if (!$url) { - $url = $original; + return FALSE; } } $url = trim($url); //Redundant for most services. @@ -165,20 +241,6 @@ function shorten_url($original = '', $service = '') { } } } - //Cache the result for a limited time. - $cache_duration = variable_get('shorten_cache_duration', 1814400); - if ($url == $original) { - $expire = time() + variable_get('shorten_cache_fail_duration', 1800); - } - elseif (is_numeric($cache_duration)) { - $expire = time() + $cache_duration; - } - else { - $expire = CACHE_PERMANENT; - } - cache_set($original, $url, 'cache_shorten', $expire); - //Announce that we have a new short URL and return it. - module_invoke_all('shorten_create', $original, $url, $service); return $url; } @@ -242,6 +304,17 @@ function _shorten_get_url($original, $api, $service) { } /** + * Queue API Worker. + */ +function shorten_url_cron_queue($item) { + $options = array( + 'use queue' => FALSE, + 'check cache' => FALSE, + ); + shorten_url($item['original'], $item['service'], $options); +} + +/** * Implementation of hook_shorten_service(). */ function shorten_shorten_service() { @@ -670,4 +743,4 @@ function shorten_token_values($type, $data = NULL, $options = array()) { 'url' => shorten_url(url('node/'. $data->nid, array('absolute' => TRUE, 'alias' => variable_get('shorten_use_alias', 1)))), ); } -} \ No newline at end of file +} -- 1.7.4.1