/[drupal]/contributions/modules/bluga/bluga.module
ViewVC logotype

Contents of /contributions/modules/bluga/bluga.module

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.8 - (show annotations) (download) (as text)
Mon Nov 2 07:11:38 2009 UTC (3 weeks, 3 days ago) by hanenkamp
Branch: MAIN
CVS Tags: HEAD
Changes since 1.7: +68 -45 lines
File MIME type: text/x-php
Merging DRUPAL-6--1 into HEAD
1 <?php
2 // $Id: bluga.module,v 1.7.2.5 2009/11/02 07:06:54 hanenkamp Exp $
3
4 /**
5 * @file
6 * This module defines the basic Bluga API and the settings screen for
7 * configuring the basics. There are several functions defined in this module
8 * starting with an underscore. Your warranty is void (just kidding, there's no
9 * warranty) if you attempt to make any use of them.
10 */
11
12 $path = drupal_get_path('module', 'bluga');
13 if (file_exists("$path/bluga_api.inc")) {
14 require_once("$path/bluga_api.inc");
15 }
16
17 /**
18 * Returns the settings form. Also uses the credit status call to Bluga to show
19 * the current credits available from Bluga if the API Key has been set.
20 */
21 function bluga_settings() {
22 $form = array();
23
24 $form['bluga_api_key'] = array(
25 '#type' => 'textfield',
26 '#title' => t('API Key'),
27 '#description' => t('Get your own API key from <a href="http://webthumb.bluga.net/home">bluga.net</a>.'),
28 '#default_value' => variable_get('bluga_api_key', ''),
29 '#required' => TRUE,
30 '#maxlength' => 32,
31 '#size' => 32,
32 );
33
34 $form['bluga_webthumb_cache'] = array(
35 '#type' => 'textfield',
36 '#title' => t('Directory to Cache Webthumbs'),
37 '#description' => t('This is where the thumbs will be served from locally after they have been generated by bluga.net.'),
38 '#field_prefix' => file_directory_path() . '/',
39 '#default_value' => variable_get('bluga_webthumb_cache', ''),
40 '#required' => TRUE,
41 '#maxlength' => 100,
42 '#size' => 35,
43 );
44
45 if (variable_get('bluga_api_key', '')) {
46 $status = bluga_credit_status();
47
48 $markup = '<h3>' . t('Bluga Credit Status') . '</h3>';
49
50 $rows[] = array( t('Used this month'), $status['used'] );
51 $rows[] = array( t('Cached Easythumbs this month'), $status['cached'] );
52 $rows[] = array( t('Subscription credits'), $status['subscription'] );
53 $rows[] = array( t('Reserve credits'), $status['reserve'] );
54 $markup .= theme_table( array( t('Statistic'), t('Tokens') ), $rows );
55
56 $form['credit_status'] = array( '#value' => $markup );
57 }
58
59 return system_settings_form($form);
60 }
61
62 /**
63 * This makes sure that the given cache directory exists.
64 */
65 function bluga_settings_validate($form, &$form_state) {
66 $files_dir = file_directory_path();
67 $cache_dir = $files_dir . '/' . $form_state['values']['bluga_webthumb_cache'];
68 file_check_directory($cache_dir, TRUE, 'bluga_webthumb_cache');
69 }
70
71 /**
72 * Implements hook_menu().
73 */
74 function bluga_menu() {
75 $items = array();
76
77 $items['admin/settings/bluga'] = array(
78 'title' => 'Bluga API settings',
79 'description' => 'Setup your API key and other basic settings.',
80 'page callback' => 'drupal_get_form',
81 'page arguments' => array('bluga_settings'),
82 'access arguments' => array('administer site configuration'),
83 'type' => MENU_NORMAL_ITEM,
84 );
85
86 $items['bluga/fetch'] = array(
87 'page callback' => 'bluga_ajax_fetch',
88 'access callback' => TRUE,
89 'type' => MENU_CALLBACK,
90 );
91
92 return $items;
93 }
94
95 function _bluga_webthumb_check($url, $size, $refetch, $options) {
96 if ($refetch == 'always') {
97 return NULL;
98 }
99 elseif ($refetch == 'never') {
100 $result = db_query("SELECT * FROM {bluga_request} WHERE url = '%s'", $url);
101 }
102 else {
103 $time = strftime('%Y-%m-%d %H:%M:%S', strtotime($refetch));
104 $result = db_query("
105 SELECT *
106 FROM {bluga_request}
107 WHERE url = '%s' AND submission_time > '%s'
108 ORDER BY submission_time DESC
109 ", $url);
110 }
111
112 while ($request = db_fetch_object($result)) {
113 if (isset($options['browser']) && ($options['browser']['width'] != $request->browser_width || $options['browser']['height'] != $request->browser_height)) {
114 continue;
115 }
116 if ($options['fullthumb'] && !$request->fullthumb) {
117 continue;
118 }
119 if (isset($options['custom']) && ($options['custom']['width'] != $request->custom_width || $options['custom']['height'] != $request->custom_height)) {
120 continue;
121 }
122 if (isset($options['output_type']) && $options['output_type'] != $request->output_type) {
123 continue;
124 }
125 if (isset($options['effect']) && $options['effect'] != $request->effect) {
126 continue;
127 }
128 if (isset($options['delay']) && $options['delay'] != $request->delay) {
129 continue;
130 }
131 if (isset($options['excerpt']) && ($options['excerpt']['x'] != $request->excerpt_x || $options['excerpt']['y'] != $request->excerpt_y || $options['excerpt']['width'] != $request->excerpt_width || $options['excerpt']['height'] != $request->excerpt_height)) {
132 continue;
133 }
134
135 return $request;
136 }
137
138 return NULL;
139 }
140
141 function _bluga_webthumb_request_check($options) {
142 // Flattens options for the table
143 foreach ($options as $name => $value) {
144 if (is_array($value)) {
145 foreach ($value as $subname => $subvalue) {
146 $args[$name . '_' . $subname] = $subvalue;
147 }
148 }
149 else {
150 $args[$name] = $value;
151 }
152 }
153
154 return $args;
155 }
156
157 function _bluga_valid_request_fields($args) {
158 $valid_columns = array('rid', 'url', 'output_type', 'browser_width',
159 'browser_height', 'fullthumb', 'custom_height', 'custom_width', 'effect',
160 'delay', 'excerpt_x', 'excerpt_y', 'excerpt_width', 'excerpt_height',
161 'job_id', 'estimate', 'submission_time', 'cost', 'pickup_url',
162 'completion_time', 'filename_small', 'filename_medium', 'filename_medium2',
163 'filename_large', 'filename_excerpt', 'filename_full', 'filename_custom',
164 'filename_effect'
165 );
166
167 $keys = array_keys($args);
168 foreach ($keys as $key) {
169 if (!in_array($key, $valid_columns)) {
170 return FALSE;
171 }
172 }
173
174 return TRUE;
175 }
176
177 function _bluga_webthumb_request($options) {
178 $args = _bluga_webthumb_request_check($options);
179
180 if (!$args) {
181 return NULL;
182 }
183
184 $jobs = bluga_request($options);
185 if (is_array($jobs)) {
186 $job = array_shift($jobs);
187
188 $args['job_id'] = $job['id'];
189 $args['estimate'] = $job['estimate'];
190 $args['submission_time'] = $job['time'];
191 $args['cost'] = $job['cost'];
192
193 if (!_bluga_valid_request_fields($args)) {
194 watchdog('content', 'invalid Bluga WebThumb request', array(),
195 WATCHDOG_ERROR);
196 return FALSE;
197 }
198
199 $fields = implode(',', array_keys($args));
200 $places = implode(',', array_fill(0, count($args), "'%s'"));
201 $values = array_values($args);
202
203 $insert_result = db_query(
204 'INSERT INTO {bluga_request}(' . $fields . ') VALUES (' . $places . ')', $values
205 );
206
207 if ($insert_result) {
208 $result = db_query(
209 "SELECT * FROM {bluga_request} WHERE job_id = '%s'", $job['id']
210 );
211
212 return db_fetch_object($result);
213 }
214 else {
215 watchdog('content', 'unable to store Bluga WebThumb request for job %job_id',
216 array( '%job_id' => $job['id'] ), WATCHDOG_ERROR);
217 return NULL;
218 }
219 }
220 else {
221 watchdog('content', 'unable to complete Bluga WebThumb request: %message',
222 array( '%message' => $jobs ), WATCHDOG_ERROR);
223 return NULL;
224 }
225 }
226
227 function _bluga_webthumb_directory() {
228 $files_dir = file_directory_path();
229 return $files_dir . '/' . variable_get('bluga_webthumb_cache', '');
230 }
231
232 function _bluga_webthumb_pickup_fetch($request, $state, $size) {
233 $response = bluga_fetch($request->job_id, $size);
234
235 if ($response->error) {
236 watchdog('content', 'unable to download %size thumbnail from job %job_id for Bluga WebThumb request',
237 array('%size' => $size, '%job_id' => $request->job_id), WATCHDOG_ERROR);
238 return FALSE;
239 }
240
241 if (strlen($response->data) == 0) {
242 watchdog('content', 'response from Bluga WebThumb API is empty for size %size and job %job_id',
243 array('%size' => $size, '%job_id' => $request->job_id), WATCHDOG_ERROR);
244 return FALSE;
245 }
246
247 $cache_dir = _bluga_webthumb_directory();
248 $filename = file_create_filename($request->job_id . '_' . $size . '.' . $request->output_type, $cache_dir);
249
250 $fh = fopen($filename, 'w');
251 fwrite($fh, $response->data);
252 fclose($fh);
253
254 return $filename;
255 }
256
257 function _bluga_valid_size($size) {
258 return in_array($size, array('small', 'medium', 'medium2', 'large', 'excerpt', 'full', 'custom', 'effect'));
259 }
260
261 function _bluga_webthumb_pickup_img($request, $size) {
262 if (!_bluga_valid_size($size)) {
263 return FALSE;
264 }
265
266 $thumbnail_id = "bluga-thumbnail-" . $request->rid;
267
268 $method = 'filename_' . $size;
269 return "<img id='$thumbnail_id' class='bluga-thumbnail $size' src='" . file_create_url($request->$method) . "'/>";
270 }
271
272 function _bluga_webthumb_waiting_img($request, $size) {
273 if (!_bluga_valid_size($size)) {
274 return FALSE;
275 }
276
277 $rid = $request->rid;
278 $waiting_id = "bluga-waiting-" . $rid;
279
280 $uri = url("bluga/fetch/$rid/$size");
281 drupal_add_js("Drupal.refreshBlugaWebThumb($rid, '$uri');", 'inline');
282 return "<div id='$waiting_id' class='bluga-waiting $size'>"
283 . "<p>Waiting for your thumbnail...</p></div>";
284 }
285
286 function _bluga_webthumb_pickup($request, $size) {
287 if (!_bluga_valid_size($size)) {
288 return FALSE;
289 }
290
291 $method = 'filename_' . $size;
292 $filename = $request->$method;
293 if ($filename && file_exists($filename)) {
294 return _bluga_webthumb_pickup_img($request, $size);
295 }
296
297 else {
298 $pickup_time = new DateTime($request->submission_time);
299
300 $pickup_time->modify('+' . ($request->estimate/2) . ' seconds');
301 $now = new DateTime('now', new DateTimeZone('US/Mountain'));
302
303 if ($pickup_time < $now) {
304 $status = bluga_status($request->job_id);
305
306 if (is_array($status)) {
307 $state = $status[$request->job_id];
308 if ($state['completionTime']) {
309 $filename = _bluga_webthumb_pickup_fetch($request, $state, $size);
310 db_query("
311 UPDATE {bluga_request}
312 SET pickup_url = '%s', completion_time = '%s', filename_$size = '%s'
313 WHERE job_id = '%s'
314 ", $state['pickup'], $state['completionTime'], $filename, $request->job_id);
315
316 $request->pickup_url = $state['pickup'];
317 $request->completion_time = $state['completionTime'];
318 $request->$method = $filename;
319
320 return _bluga_webthumb_pickup_img($request, $size);
321 }
322 else {
323 return _bluga_webthumb_waiting_img($request, $size);
324 }
325 }
326 else {
327 watchdog('content', 'an error occurred while checking the status of Bluga WebThumb job %job_id',
328 array( '%job_id' => $request->job_id ), WATCHDOG_ERROR);
329 return FALSE;
330 }
331 }
332 else {
333 return _bluga_webthumb_waiting_img($request, $size);
334 }
335 }
336 }
337
338 /**
339 * This is the main function of the API. Given a URL, it will ask the Bluga web
340 * service to create a thumbnail of that web site. This method returns an
341 * IMG-tag that either contains the image that has been captured or a
342 * placeholder for it, since it takes some time to generate the clip. Additional
343 * parameters may be given for further control on the request.
344 *
345 * Whenever possible, the API will try not to cost you additional tokens by
346 * making fresh requests to Bluga. This function will attempt to use the most
347 * recent thumbnail available if doing so is possible with the given parameters.
348 * A new request will occur if any of the following are true:
349 *
350 * <ul>
351 * <li>The given $url has never been fetched before by this module</li>
352 * <li>The "browser" option is given and no previous matching request was made
353 * using the same "width" and "height" values</li>
354 * <li>The "fullthumb" option is given (or by specifying a $size of "full",
355 * which implies the same option) and no previous matching request was made with
356 * that option</li>
357 * <li>The "custom" option is given and no previous matching request was made
358 * using the same "width" and "height" values. This will occur even if the $size
359 * argument is not set to "custom".</li>
360 * <li>The "output_type" option specified has not been used for a matching
361 * request previously (even if the "effect" thumbnail, which is not effected by
362 * this option, is specified).</li>
363 * <li>The "effect" option specified has not been used for a matching request
364 * previously. This is true even if the "effect" thumbnail is not
365 * specified.</li>
366 * <li>The "delay" option is given as a different value than has been used
367 * before on a matching request.</li>
368 * <li>The "excerpt" option is given as a different value than has been used
369 * before. This causes a refetch even if the $size chosen is not "excerpt".</li>
370 * </ul>
371 *
372 * In addition to these rules, the refetch is affected by the $refetch value. If
373 * $refetch is set to "never" (this is the default behavior), a refetch will
374 * only occur if no thumbnail ever generated matches the request. If $refetch is
375 * set to "always" a new request will be made during this call. If $refetch is
376 * set to a date, the set of thumbnails examine will only be those that were
377 * completed after the given date. Thus, if no thumbnails have been generated
378 * for a given URL or if one of the other rules above causes a mismatch for all
379 * the generated thumbnails of that URL, a new request will be made.
380 *
381 * @param $url The URL that will be captured
382 * @param $size Each webthumb comes with at least 5 different sizes available
383 * and may come with up to three others (at least as of 1.1 of the Bluga API):
384 * <ul>
385 * <li>"small": This is an 80x60 thumbnail image</li>
386 * <li>"medium": This is a 160x120 thumbnail image. This is the default.</li>
387 * <li>"medium2": This is a 320x240 thumbnail image</li>
388 * <li>"large": This is a 640x480 thumbnail image</li>
389 * <li>"excerpt": This is usually a 400x150 snapshot of the web site without
390 * resizing (not actually a thumbnail). Using the "excerpt" option described
391 * below this may be customized.</li>
392 * <li>"full": This is a full size screen shot of the page. If you use this
393 * option, the "fullthumb" option of $options will be set automatically.</li>
394 * <li>"custom": This is a custom thumbnail size. If this is value is set, you
395 * must specify the "custom" option or an error will occur.</li>
396 * <li>"effect": This is a thumbnail with a special effect applied to it. If
397 * this value is chosen, you must specify the "effect" option or an error will
398 * occur.</li>
399 * </ul>
400 * @param $refetch The thumbnail that you request will be cached so that you
401 * do not use up your tokens every time you make a request. However, you may
402 * want to refresh a webthumb every so often. This option determines how often
403 * a URL will be regenerated.
404 * <ul>
405 * <li>"never": If possible, always use the existing thumbnail. This is the
406 * default behavior. However, it is possible that a refetch will occur anyway
407 * should the options given require it.</li>
408 * <li>"always": Always fetch a new thumbnail.</li>
409 * <li>A date/time string: You may also use a value that would be parsed by
410 * PHP's strtotime(). This allows you to say things like "+1 week" to say that
411 * if the current thumbnail is a week old or older, fetch a new one. You can
412 * even specify an exact date like "2008-03-15" to refetch after that date.
413 * Whatever date you give will be based upon the date the thumbnail was
414 * made.</li>
415 * </ul>
416 * @param $options This is an associative array of options. The following
417 * options are available:
418 * <ul>
419 * <li>"output_type": This must be either "jpg" or "png". If you choose "png",
420 * Bluga will charge you for 2 tokens on this request.</li>
421 * <li>"browser": This value is passed as an array, taking two values:
422 * <ul>
423 * <li>"width": This is the width of the browser window to open for the
424 * thumbnail. This must be within the range 15 to 1280.</li>
425 * <li>"height": This is the height of the browser window to open for the
426 * thumbnail. This must be within the range of 15 to 2048. If you use a browser
427 * height greater than 1024, you will be charged 2 tokens for this request.</li>
428 * </ul></li>
429 * <li>"fullthumb": This is either "0" or "1". A value of "0" is the default. If
430 * you set this to "1", you will have an additional thumbnail size "fullsize"
431 * available, which will be a fullsize screenshot of the web site at the
432 * dimensions set for the "browser" width and height.</li>
433 * <li>"custom": This value is passed as an array, taking two values. By
434 * specifying this option you will be charged 2 tokens. An extra thumbnail size
435 * will become available for this request, named "custom". The dimensions of
436 * this thumbnail will be as you specify. The values are:
437 * <ul>
438 * <li>"width": This is the pixel width you want for the custom thumbnail.</li>
439 * <li>"height": This is the pixel height you want for the custom
440 * thumbnail.</li>
441 * </ul></li>
442 * <li>"effect": By specifying this option you will be charged 2 tokens. You
443 * will be provided an additional thumbnail size named "effect". The size of
444 * that thumbnail depends upon the effect chosen. This thumbnail will always be
445 * a PNG file. The value of this option must be one of the following:
446 * <ul>
447 * <li>"mirror": This will apply a mirror effect to the thumbnail so you will
448 * see the reflection beneath the thumbnail as if it was a plate standing up
449 * perpendicular to a plane of glass. The image result will be 300x361 in
450 * size.</li>
451 * <li>"dropshadow": This will add a drop shadow behind the image. The image
452 * result will be 311x251 pixels.</li>
453 * <li>"border": This will add a thin black border around the thumbnail. The
454 * image result will be 302x242 in size.</li>
455 * </ul></li>
456 * <li>"delay": This is the delay in seconds between loading the web site and
457 * taken the snapshot. This defaults to "3" and must be within the range of 1 to
458 * 15 seconds.</li>
459 * <li>"excerpt": This value is passed as an array and allows you to modify the
460 * "excerpt" image size and location. It takes the following parameters:
461 * <ul>
462 * <li>"x": This is the horizontal position of the left edge of the
463 * excerpt.</li>
464 * <li>"y": This is the vertical position of the top edge of the excerpt.</li>
465 * <li>"width": This is the pixel width of the image to build. If this value
466 * exceeds "800" you will be charged 2 tokens.</li>
467 * <li>"height": This is the pixel height of the image to build. If this value
468 * exceeds "600" you will be charged 2 tokens.</li>
469 * </ul></li>
470 * </ul>
471 * @returns The HTML required to render the image after it has been fetched or a
472 * placeholder to show until that happens. This will also add the bluga CSS and
473 * JavaScripts to the page header. In the case of a placeholder being shown,
474 * additional JavaScript maybe added as well that will ask the client to try and
475 * replace the placeholder with the fetched image.
476 */
477 function bluga_webthumb($url, $size = 'medium', $refetch = 'never', $options = array()) {
478 $css_file = drupal_get_path('module', 'bluga') . '/bluga.css';
479 drupal_add_css($css_file);
480
481 $js_file = drupal_get_path('module', 'bluga') . '/bluga.js';
482 drupal_add_js($js_file);
483
484 $options['url'] = $url;
485
486 if ($size == 'full') {
487 $options['fullthumb'] = 1;
488 }
489
490 $request = _bluga_webthumb_check($url, $size, $refetch, $options);
491 if ($request) {
492 return _bluga_webthumb_pickup($request, $size);
493 }
494 else {
495 $request = _bluga_webthumb_request($options);
496 if ($request) {
497 return _bluga_webthumb_pickup($request, $size);
498 }
499 else {
500 watchdog('content', 'cannot locate a Bluga WebThumb request for URL %url',
501 array( '%url' => $url ), WATCHDOG_ERROR);
502 return NULL;
503 }
504 }
505 }
506
507 function bluga_ajax_fetch() {
508 $rid = arg(2);
509 $size = arg(3);
510 if (!_bluga_valid_size($size)) {
511 return FALSE;
512 }
513
514 $result = db_query(
515 "SELECT * FROM {bluga_request} WHERE rid = '%s'", $rid
516 );
517 $request = db_fetch_object($result);
518 if (!$request) {
519 watchdog('content', 'cannot locate a Bluga WebThumb request for request ID %rid',
520 array( '%rid' => $rid ), WATCHDOG_ERROR);
521 return FALSE;
522 }
523
524 print _bluga_webthumb_pickup($request, $size);
525 exit;
526 }

  ViewVC Help
Powered by ViewVC 1.1.2