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

Contents of /contributions/modules/bitcache/bitcache.module

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


Revision 1.36 - (show annotations) (download) (as text)
Wed Jul 29 13:06:51 2009 UTC (3 months, 3 weeks ago) by arto
Branch: MAIN
CVS Tags: HEAD
Changes since 1.35: +2 -0 lines
File MIME type: text/x-php
Ensure that file system repositories are created when invoked from hook_enable() in dependent modules (patch by miglius).
1 <?php
2 // $Id$
3
4 //////////////////////////////////////////////////////////////////////////////
5 // Module settings
6
7 define('BITCACHE_LINK', 'http://bitcache.org/');
8 define('BITCACHE_ROOT', variable_get('bitcache_root', file_directory_path() . '/bitcache'));
9 define('BITCACHE_BASE', 'bitcache');
10 define('BITCACHE_ALIAS', drupal_get_path_alias(BITCACHE_BASE));
11 define('BITCACHE_CRON', trim(variable_get('bitcache_cron', '')));
12
13 define('BITCACHE_SERVER', variable_get('bitcache_server', TRUE));
14 define('BITCACHE_TRANSFER_METHOD', variable_get('bitcache_transfer_method', 'read4k'));
15 define('BITCACHE_URL', url(BITCACHE_ALIAS . '/', array('absolute' => TRUE, 'prefix' => '', 'language' => (object)array('language' => ''))));
16 define('BITCACHE_DEPTH', variable_get('bitcache_depth', 0));
17 define('BITCACHE_WIDTH', variable_get('bitcache_width', 0));
18
19 define('BITCACHE_EXEC', variable_get('bitcache_exec', drupal_get_path('module', 'bitcache') . '/tools/bin/bit'));
20 define('BITCACHE_TABLE_DEFAULT', 'bitcache_data');
21 define('BITCACHE_TABLE_PREFIX', 'bitcache_data_');
22
23 //////////////////////////////////////////////////////////////////////////////
24 // Core API hooks
25
26 /**
27 * Implementation of hook_perm().
28 */
29 function bitcache_help($path) {
30 switch ($path) {
31 case 'admin/help#bitcache':
32 return '<p>'. t('<a href="@bitcache" target="_blank">Bitcache</a> is a distributed <a href="http://en.wikipedia.org/wiki/Content-addressable_storage" target="_blank">content-addressable storage</a> (CAS) system. It provides repository storage for bitstreams (colloquially known as <a href="http://en.wikipedia.org/wiki/Binary_large_object" target="_blank">blobs</a>) of any length, each uniquely identified and addressed by a digital fingerprint derived through a secure <a href="http://en.wikipedia.org/wiki/Cryptographic_hash_function" target="_blank">cryptographic hash algorithm</a>.', array('@bitcache' => BITCACHE_LINK)) .'</p>'.
33 '<p>'. t('This module provides a Bitcache-compatible data storage repository for Drupal and implements the Bitcache <a href="http://en.wikipedia.org/wiki/Representational_State_Transfer" target="_blank" title="Representational State Transfer">REST</a> <acronym title="Application Programming Interface">API</acronym> for interoperability with the standalone Bitcache command-line and synchronization tools.') .'</p>'.
34 '<p>'. t('For more information please refer to the <a href="@project">drupal.org project page</a>.', array('@project' => 'http://drupal.org/project/bitcache')) .'</p>';
35 case 'admin/settings/bitcache':
36 return '<p>'. t('<a href="@bitcache" target="_blank">Bitcache</a> provides a distributed, content-addressable repository for data storage.', array('@bitcache' => BITCACHE_LINK)) .'</p>';
37 case 'admin/settings/bitcache/repositories':
38 return '<p>'. t('Below is a list of all configured Bitcache repositories available to this Drupal site.') .'</p>';
39 }
40 }
41
42 /**
43 * Implementation of hook_perm().
44 */
45 function bitcache_perm() {
46 return array(
47 'administer bitcache',
48 'list bitstreams',
49 'access bitstreams',
50 'upload bitstreams',
51 'delete bitstreams',
52 );
53 }
54
55 /**
56 * Implementation of hook_menu().
57 */
58 function bitcache_menu() {
59 return array(
60 // Bitcache HTTP API endpoint
61 BITCACHE_BASE => array(
62 'title' => 'Bitcache API',
63 'type' => MENU_CALLBACK,
64 'access arguments' => array('list bitstreams'),
65 'page callback' => 'bitcache_server',
66 'file' => 'bitcache.server.inc',
67 ),
68 BITCACHE_ALIAS . '/%' => array(
69 'type' => MENU_CALLBACK,
70 'access arguments' => array('access bitstreams'),
71 'page callback' => 'bitcache_server',
72 'page arguments' => array(1),
73 'file' => 'bitcache.server.inc',
74 ),
75
76 // Administer >> Content management >> Bitstreams
77 'admin/content/bitcache' => array(
78 'title' => 'Bitstreams',
79 'description' => 'Manage Bitcache data.',
80 'access arguments' => array('administer bitcache'),
81 'page callback' => 'drupal_get_form',
82 'page arguments' => array('bitcache_admin_bitstreams'),
83 'file' => 'bitcache.admin.inc',
84 ),
85 'admin/content/bitcache/list' => array(
86 'title' => 'List',
87 'type' => MENU_DEFAULT_LOCAL_TASK,
88 'weight' => -10,
89 ),
90 'admin/content/bitcache/upload' => array(
91 'title' => 'Upload bitstream',
92 'type' => MENU_LOCAL_TASK,
93 'access arguments' => array('administer bitcache'),
94 'page callback' => 'drupal_get_form',
95 'page arguments' => array('bitcache_admin_bitstream_upload'),
96 'file' => 'bitcache.admin.inc',
97 'weight' => 10,
98 ),
99 'admin/content/bitcache/fetch' => array(
100 'title' => 'Fetch bitstream from URL',
101 'type' => MENU_LOCAL_TASK,
102 'access arguments' => array('administer bitcache'),
103 'page callback' => 'drupal_get_form',
104 'page arguments' => array('bitcache_admin_bitstream_fetch'),
105 'file' => 'bitcache.admin.inc',
106 'weight' => 20,
107 ),
108 'admin/content/bitcache/view/%' => array(
109 'title' => 'View bitstream',
110 'type' => MENU_CALLBACK,
111 'access arguments' => array('administer bitcache'),
112 'page callback' => 'bitcache_admin_bitstream_view',
113 'page arguments' => array(4),
114 'file' => 'bitcache.admin.inc',
115 ),
116 'admin/content/bitcache/delete/%' => array(
117 'title' => 'Delete bitstream',
118 'type' => MENU_CALLBACK,
119 'access arguments' => array('administer bitcache'),
120 'page callback' => 'drupal_get_form',
121 'page arguments' => array('bitcache_admin_bitstream_delete', 4),
122 'file' => 'bitcache.admin.inc',
123 ),
124
125 // Administer >> Site configuration >> Data storage
126 'admin/settings/bitcache' => array(
127 'title' => 'Data storage',
128 'description' => 'Settings for Bitcache.',
129 'access arguments' => array('administer bitcache'),
130 'page callback' => 'drupal_get_form',
131 'page arguments' => array('bitcache_admin_settings'),
132 'file' => 'bitcache.admin.inc',
133 ),
134 'admin/settings/bitcache/config' => array(
135 'title' => 'Settings',
136 'type' => MENU_DEFAULT_LOCAL_TASK,
137 'weight' => -10,
138 ),
139 'admin/settings/bitcache/repositories' => array(
140 'title' => 'Repositories',
141 'type' => MENU_LOCAL_TASK,
142 'access arguments' => array('administer bitcache'),
143 'page callback' => 'drupal_get_form',
144 'page arguments' => array('bitcache_admin_repos'),
145 'file' => 'bitcache.admin.inc',
146 ),
147 'admin/settings/bitcache/repository/add' => array(
148 'title' => 'Add repository',
149 'type' => MENU_LOCAL_TASK,
150 'parent' => 'admin/settings/bitcache',
151 'weight' => 1,
152 'access arguments' => array('administer bitcache'),
153 'page callback' => 'bitcache_admin_repo_create',
154 'file' => 'bitcache.admin.inc',
155 ),
156 'admin/settings/bitcache/repository/edit' => array(
157 'title' => 'Configure repository',
158 'type' => MENU_CALLBACK,
159 'access arguments' => array('administer bitcache'),
160 'page callback' => 'bitcache_admin_repo_edit',
161 'file' => 'bitcache.admin.inc',
162 ),
163 'admin/settings/bitcache/repository/delete' => array(
164 'title' => 'Delete repository',
165 'type' => MENU_CALLBACK,
166 'access arguments' => array('administer bitcache'),
167 'page callback' => 'drupal_get_form',
168 'page arguments' => array('bitcache_admin_repo_delete'),
169 'file' => 'bitcache.admin.inc',
170 ),
171 );
172 }
173
174 /**
175 * Implementation of hook_init().
176 */
177 function bitcache_init() {
178 foreach (array('token', 'services'/*, 'rules'*/) as $module) {
179 if (module_exists($module)) {
180 module_load_include('inc', 'bitcache', 'bitcache.' . $module);
181 }
182 }
183 }
184
185 /**
186 * Implementation of hook_form_alter().
187 */
188 function bitcache_form_alter(&$form, $form_state, $form_id) {
189 switch ($form_id) {
190 case 'globalredirect_settings':
191 // Display a prominent warning on the Global Redirect settings page if
192 // the 'Deslash' option has been enabled:
193 if (module_exists('globalredirect')) {
194 if (BITCACHE_SERVER && variable_get('globalredirect_deslash', GLOBALREDIRECT_DESLASH_ENABLED) == GLOBALREDIRECT_DESLASH_ENABLED) {
195 drupal_set_message(t('Warning: the Global Redirect deslash setting is incompatible with the Bitcache REST API.'), 'warning');
196 }
197 }
198 break;
199 }
200 }
201
202 /**
203 * Implementation of hook_theme().
204 */
205 function bitcache_theme() {
206 return array(
207 'bitcache_admin_bitstreams' => array(
208 'arguments' => array('form' => NULL),
209 'file' => 'bitcache.admin.inc',
210 ),
211 'bitcache_admin_settings' => array(
212 'arguments' => array('form' => NULL),
213 'file' => 'bitcache.admin.inc',
214 ),
215 'bitcache_admin_repos' => array(
216 'arguments' => array('form' => NULL),
217 'file' => 'bitcache.admin.inc',
218 ),
219 );
220 }
221
222 /**
223 * Implementation of hook_hook_info().
224 */
225 function bitcache_hook_info() {
226 return array(
227 'bitcache' => array(
228 'bitcache' => array(
229 'insert' => array(
230 'runs when' => t('After uploading a new bitstream'),
231 ),
232 'delete' => array(
233 'runs when' => t('After deleting an existing bitstream'),
234 ),
235 ),
236 ),
237 );
238 }
239
240 /**
241 * Implementation of hook_action_info().
242 */
243 function bitcache_action_info() {
244 return array(
245 'bitcache_cron_action' => array(
246 'description' => t('Execute cron script'),
247 'type' => 'bitcache',
248 'configurable' => FALSE,
249 'hooks' => array(
250 'bitcache' => array('insert', 'delete'),
251 ),
252 ),
253 'bitcache_sync_action' => array(
254 'description' => t('Synchronize with Bitcache server'),
255 'type' => 'bitcache',
256 'configurable' => TRUE,
257 'hooks' => array(
258 'bitcache' => array('insert', 'delete'),
259 )
260 )
261 );
262 }
263
264 function bitcache_sync_action_form($context) {
265 $form = array();
266 /*$form['url'] = array(
267 '#type' => 'textfield',
268 '#title' => t('URL'),
269 '#description' => t('The URL of the Bitcache server.'),
270 '#default_value' => isset($context['url']) ? $context['url'] : '',
271 '#required' => TRUE,
272 );*/
273 /*$form['mode'] = array(
274 '#type' => 'checkboxes',
275 '#title' => t('Direction'),
276 '#default_value' => !empty($context['mode']) ? $context['mode'] : array(),
277 '#options' => array('push' => t('Push'), 'pull' => t('Pull')),
278 '#description' => t('Which direction the synchronization should be performed in.'),
279 '#required' => TRUE,
280 );*/
281 // TODO
282 return $form;
283 }
284
285 function bitcache_sync_action_submit($form, &$form_state) {
286 return array(
287 'url' => $form_state['values']['url'],
288 );
289 }
290
291 function bitcache_sync_action(&$object, array $context = array()) {
292 //$context['url']
293 }
294
295 /**
296 * Implementation of hook_cron().
297 */
298 function bitcache_cron() {
299 if (strlen(BITCACHE_CRON) > 0) {
300 exec(BITCACHE_CRON .' 2>&1', $output, $retval);
301 if ($retval == 0) {
302 watchdog('bitcache', 'Cron script completed.');
303 }
304 else {
305 watchdog('bitcache', 'Cron script failed with return value %retval and output: %output', array('%retval' => $retval, '%output' => implode("\n", $output)), WATCHDOG_ERROR, l('configure', 'admin/settings/bitcache'));
306 }
307 }
308 }
309
310 function bitcache_cron_action(&$object, array $context = array()) {
311 bitcache_cron();
312 }
313
314 //////////////////////////////////////////////////////////////////////////////
315 // Bitcache API hooks
316
317 /**
318 * Implementation of hook_bitcache().
319 */
320 function bitcache_bitcache($op, $id, &$stream = NULL) {
321 static $ops = array('insert', 'delete');
322 if (!in_array($op, $ops)) {
323 return;
324 }
325
326 if (module_exists('rules')) {
327 rules_invoke_event('bitcache_' . $op, array('stream' => &$stream));
328 }
329
330 if (module_exists('trigger')) {
331 $object = (object)array('id' => $id);
332 $context = array('hook' => 'bitcache', 'op' => $op, 'stream' => &$stream);
333 foreach (_trigger_get_hook_aids('bitcache', $op) as $aid => $action_info) {
334 if ($action_info['type'] == 'bitcache') {
335 actions_do($aid, $object, $context); // trigger action
336 }
337 }
338 }
339 }
340
341 /**
342 * Implementation of hook_bitcache_adapters().
343 */
344 function bitcache_bitcache_adapters() {
345 return array(
346 'sql' => array(
347 'title' => t('Database'),
348 'description' => t('Stores data in a Drupal database table.'),
349 'enabled' => TRUE,
350 'file' => drupal_get_path('module', 'bitcache') . '/adapters/sql.inc',
351 'class' => 'Bitcache_SQLRepository',
352 ),
353 'pdo' => array(
354 'title' => t('Database (PDO)'),
355 'description' => t('Stores data in a <a href="http://php.net/manual/en/book.pdo.php" target="_blank">PHP Data Objects (PDO)</a> database.'),
356 'enabled' => extension_loaded('pdo'),
357 'file' => drupal_get_path('module', 'bitcache') . '/adapters/pdo.inc',
358 'class' => 'Bitcache_PDORepository',
359 ),
360 'gdbm' => array(
361 'title' => t('Database (GDBM)'),
362 'description' => t('Stores data in a <a href="http://www.vivtek.com/gdbm/" target="_blank">GDBM</a> database.'),
363 'enabled' => extension_loaded('dba') && in_array('gdbm', dba_handlers()),
364 'file' => drupal_get_path('module', 'bitcache') . '/adapters/dba.inc',
365 'class' => 'Bitcache_DBARepository',
366 ),
367 'file' => array(
368 'title' => t('File system'),
369 'description' => t('Stores data in a file system directory.'),
370 'enabled' => TRUE,
371 'file' => drupal_get_path('module', 'bitcache') . '/adapters/file.inc',
372 'class' => 'Bitcache_FileRepository',
373 ),
374 'aws_s3' => array(
375 'title' => t('Amazon S3'),
376 'description' => t('Stores data in an <a href="https://s3.amazonaws.com/">Amazon Simple Storage Service (S3)</a> bucket.'),
377 'enabled' => file_exists(drupal_get_path('module', 'bitcache') . '/vendor/tarzan/tarzan.class.php'),
378 'file' => drupal_get_path('module', 'bitcache') . '/adapters/aws-s3.inc',
379 'class' => 'Bitcache_S3Repository',
380 ),
381 );
382 }
383
384 /**
385 * Implementation of hook_bitcache_algorithms().
386 */
387 function bitcache_bitcache_algorithms($op) {
388 $available = $algorithms = array();
389 switch ($op) {
390 case 'fingerprint':
391 case 'hash':
392 $available = function_exists('hash_algos') ? hash_algos() : array('md5', 'sha1');
393 $algorithms = array(
394 'md5' => t('MD5 (128-bit)'),
395 'sha1' => t('SHA-1 (160-bit)'),
396 'sha256' => t('SHA-256 (256-bit)'),
397 'sha384' => t('SHA-384 (384-bit)'),
398 'sha512' => t('SHA-512 (512-bit)'),
399 );
400 break;
401 case 'encode':
402 case 'decode':
403 $algorithms = array(
404 'base16' => t('Base 16 (0-9, a-f; hexadecimal)'),
405 //'base32' => t('Base 32 (A-Z, 2-7; RFC 4648)'),
406 'base36' => t('Base 36 (0-9, a-z)'),
407 'base62' => t('Base 62 (0-9, A-Z, a-z)'),
408 );
409 $available = array_keys($algorithms);
410 break;
411 case 'encrypt':
412 case 'decrypt':
413 $available = function_exists('mcrypt_list_algorithms') ? mcrypt_list_algorithms() : array();
414 $algorithms = array(
415 'rijndael-128' => t('AES-128'),
416 'rijndael-192' => t('AES-192'),
417 'rijndael-256' => t('AES-256'),
418 );
419 break;
420 case 'compress':
421 case 'decompress':
422 if (function_exists('gzencode')) {
423 $available[] = 'gzip';
424 }
425 if (function_exists('bzcompress')) {
426 $available[] = 'bzip2';
427 }
428 $algorithms = array(
429 'gzip' => t('gzip'),
430 'bzip2' => t('bzip2'),
431 );
432 break;
433 }
434 return array_intersect_key($algorithms, array_flip($available));
435 }
436
437 //////////////////////////////////////////////////////////////////////////////
438 // Bitcache repository API
439
440 /**
441 * Returns information on available cryptographic algorithms.
442 */
443 function bitcache_get_algorithms($op) {
444 return module_invoke_all('bitcache_algorithms', $op);
445 }
446
447 /**
448 * Returns information about modules that implement hook_bitcache().
449 */
450 function bitcache_get_modules($op = NULL) {
451 switch ($op) {
452 case 'info':
453 $modules = bitcache_get_modules('names');
454 if (!empty($modules)) {
455 $result = db_query("SELECT name, info FROM {system} WHERE type = 'module' AND name IN (" . db_placeholders($modules, 'varchar') . ") ORDER BY weight ASC", $modules);
456 while ($row = db_fetch_object($result)) {
457 $info = (object)unserialize($row->info);
458 $info->title = $info->name;
459 $info->name = $row->name;
460 $modules[$row->name] = $info;
461 }
462 }
463 return $modules;
464 case 'titles':
465 $modules = bitcache_get_modules('info');
466 foreach ($modules as $name => $info) {
467 $modules[$name] = $info->title;
468 }
469 return $modules;
470 case 'names':
471 default:
472 $modules = module_implements('bitcache');
473 $modules = empty($modules) ? $modules : array_combine($modules, $modules);
474 unset($modules['bitcache']); // ignore self
475 return $modules;
476 }
477 }
478
479 /**
480 * Returns information on the supported and enabled REST API methods.
481 */
482 function bitcache_get_features() {
483 static $default = array('index', 'get', 'post', 'put', 'delete');
484 return array_filter(variable_get('bitcache_features', array_combine($default, $default)), 'is_string');
485 }
486
487 /**
488 * Returns information on the available storage adapters (repository backends).
489 */
490 function bitcache_get_adapters($op = NULL, $enabled_only = FALSE) {
491 static $adapters = array();
492 if (empty($adapters)) {
493 foreach (module_implements('bitcache_adapters') as $module) {
494 foreach (module_invoke($module, 'bitcache_adapters') as $name => $info) {
495 $info['name'] = $name;
496 $info['module'] = $module;
497 $info['enabled'] = isset($info['enabled']) ? (bool)$info['enabled'] : TRUE;
498 $adapters[$name] = (object)$info;
499 }
500 }
501 }
502
503 $result = array();
504 foreach ($adapters as $name => $info) {
505 if (!$enabled_only || !empty($info->enabled)) {
506 switch ($op) {
507 case 'titles':
508 $result[$name] = $info->title;
509 break;
510 default:
511 $result[$name] = $info;
512 break;
513 }
514 }
515 }
516 return $result;
517 }
518
519 /**
520 * Determines if a storage adapter is available.
521 */
522 function bitcache_has_adapter($adapter) {
523 $adapters = bitcache_get_adapters();
524 return isset($adapters[$adapter]) && !empty($adapters[$adapter]->enabled);
525 }
526
527 /**
528 * Returns a storage adapter class.
529 */
530 function bitcache_get_adapter_class($adapter, $load = TRUE) {
531 $adapters = bitcache_get_adapters();
532 if (isset($adapters[$adapter]) && ($adapter = $adapters[$adapter])) {
533 if ($load && isset($adapter->file) && ($file = './' . $adapter->file) && is_file($file)) {
534 require_once $file;
535 }
536 return $adapter->class;
537 }
538 }
539
540 /**
541 * Returns a list of database-backed repositories' table names.
542 */
543 function bitcache_get_repository_tables($refresh = FALSE) {
544 static $tables;
545 if (!is_array($tables) || $refresh) {
546 $result = db_query("SELECT name FROM {bitcache_repositories} WHERE adapter = 'sql' AND name != 'bitcache' ORDER BY weight ASC, name ASC");
547 $tables = array('bitcache' => BITCACHE_TABLE_DEFAULT);
548 while ($row = db_fetch_object($result)) {
549 if (db_table_exists($table = BITCACHE_TABLE_PREFIX . $row->name)) {
550 $tables[$row->name] = $table;
551 }
552 }
553 }
554 return $tables;
555 }
556
557 /**
558 * Returns the Bitcache database schema for a given table.
559 */
560 function bitcache_get_schema($table = BITCACHE_TABLE_DEFAULT, $rebuild = FALSE) {
561 if (!($schema = drupal_get_schema($table, $rebuild))) {
562 module_load_include('install', 'bitcache');
563 $schema = bitcache_schema();
564 $schema = isset($schema[$table]) ? $schema[$table] : array();
565 }
566 return $schema;
567 }
568
569 /**
570 * Returns information on the available Bitcache repositories.
571 */
572 function bitcache_get_repositories($op = 'info') {
573 static $repos = array();
574 if (empty($repos)) {
575 $result = db_query("SELECT name FROM {bitcache_repositories} ORDER BY weight ASC, name ASC");
576 while ($row = db_fetch_object($result)) {
577 $repos[$row->name] = bitcache_get_repository($row->name);
578 }
579 }
580
581 $result = $repos;
582 switch ($op) {
583 case 'names':
584 case 'adapters':
585 case 'modules':
586 case 'titles':
587 case 'weights':
588 $property = substr($op, 0, -1);
589 foreach ($repos as $name => $repo) {
590 $result[$name] = $repo->options[$property];
591 }
592 break;
593 case 'options':
594 case 'settings':
595 case 'info':
596 foreach ($repos as $name => $repo) {
597 $result[$name] = $repo->options;
598 }
599 break;
600 case 'config':
601 //$repos[$name] = array('adapter' => 'file', 'path' => $settings['location'], 'enabled' => TRUE); // FIXME
602 break;
603 case 'api':
604 default:
605 break;
606 }
607
608 return $result;
609 }
610
611 /**
612 * Creates a new repository.
613 */
614 function bitcache_create_repository($name, array $options = array()) {
615 $options = array_merge(array('title' => $name, 'description' => '', 'adapter' => 'sql'), (array)$options);
616 unset($options['name'], $options['options']); // just in case
617
618 if ($options['adapter'] == 'file') {
619 $options['location'] = !empty($options['location']) ? $options['location'] : BITCACHE_ROOT . '/' . $name;
620 @mkdir(bitcache_token_replace($options['location']), 0777, TRUE);
621 }
622
623 $record = array_intersect_key($options, array_flip(array('module', 'adapter', 'enabled', 'mutable', 'indexed', 'weight')));
624 $record = array_merge(array('name' => $name, 'module' => '', 'adapter' => 'sql', 'enabled' => TRUE, 'mutable' => TRUE, 'indexed' => FALSE, 'weight' => 0,
625 'options' => serialize(array_diff_key($options, $record))), $record);
626 $record = (object)$record;
627
628 return drupal_write_record('bitcache_repositories', $record) ? bitcache_get_repository($name) : FALSE;
629 }
630
631 /**
632 * Renames a repository.
633 */
634 function bitcache_rename_repository($old_name, $new_name, array $options = array()) {
635 if (($repo = bitcache_get_repository($old_name))) {
636 if (db_query("UPDATE {bitcache_repositories} SET name = '%s' WHERE name = '%s'", $new_name, $old_name)) {
637 return is_callable(array($repo, 'rename')) ? $repo->rename($old_name, $new_name, $options) : TRUE;
638 }
639 return FALSE;
640 }
641 }
642
643 /**
644 * Updates options for a repository.
645 */
646 function bitcache_update_repository($name, array $options = array()) {
647 if (($repo = bitcache_get_repository($name))) {
648 $options = array_diff_key($options, array_flip(array('name', 'module', 'adapter', 'enabled', 'mutable', 'indexed', 'weight', 'options')));
649 return db_query("UPDATE {bitcache_repositories} SET options = '%s' WHERE name = '%s'", serialize($options), $name);
650 }
651 }
652
653 /**
654 * Deletes a repository.
655 */
656 function bitcache_delete_repository($name, array $options = array()) {
657 if (isset($GLOBALS['bitcache_repository']) && $GLOBALS['bitcache_repository'] == $name) {
658 unset($GLOBALS['bitcache_repository']);
659 }
660
661 if (($repo = bitcache_get_repository($name))) {
662 if (db_query("DELETE FROM {bitcache_repositories} WHERE name = '%s'", $name)) {
663 return is_callable(array($repo, 'destroy')) ? $repo->destroy($options) : TRUE;
664 }
665 return FALSE;
666 }
667 }
668
669 /**
670 * Returns a repository instance.
671 */
672 function bitcache_get_repository($name = 'bitcache') {
673 module_load_include('inc', 'bitcache');
674
675 if (is_null($name)) { // create repository proxy
676 return new Bitcache_AggregateRepository(bitcache_get_repositories('api'));
677 }
678
679 $repo = db_fetch_array(db_query("SELECT * FROM {bitcache_repositories} WHERE name = '%s'", $name));
680 $repo = array_merge(unserialize($repo['options']), array_diff_key($repo, array('options' => NULL)));
681 $repo = ($name == 'bitcache') ? array_merge($repo, array('table' => BITCACHE_TABLE_DEFAULT)) : $repo;
682
683 $class = bitcache_has_adapter($repo['adapter']) ? bitcache_get_adapter_class(!empty($repo['adapter']) ? $repo['adapter'] : 'file') : NULL;
684 return $class && class_exists($class) ? new $class($repo) : (object)array('options' => $repo);
685 }
686
687 /**
688 * Returns the total number of bitstreams in a repository.
689 */
690 function bitcache_get_repository_count($name = NULL) {
691 return count(bitcache_get_repository($name));
692 }
693
694 /**
695 * Returns the total byte size of a repository.
696 */
697 function bitcache_get_repository_size($name = NULL) {
698 return ($repo = bitcache_get_repository($name)) ? $repo->size() : 0;
699 }
700
701 /**
702 * Limits future queries and operations to a particular repository.
703 */
704 function bitcache_use_repository($name = NULL) {
705 if (is_null($name)) {
706 unset($GLOBALS['bitcache_repository']);
707 }
708 else {
709 $GLOBALS['bitcache_repository'] = $name;
710 }
711 }
712
713 //////////////////////////////////////////////////////////////////////////////
714 // Bitcache bitstream API
715
716 function bitcache_l($text, $id, array $options = array('absolute' => TRUE)) {
717 $options += array('prefix' => '', 'language' => array());
718 return l($text, BITCACHE_ALIAS . '/' . $id, $options);
719 }
720
721 function bitcache_resolve_id($id, array $options = array('absolute' => TRUE)) {
722 $options += array('prefix' => '', 'language' => array());
723 return url(BITCACHE_ALIAS . '/' . $id, $options);
724 }
725
726 function bitcache_resolve_uri($uri, array $options = array('absolute' => TRUE)) {
727 return ($id = bitcache_uri_to_id($uri)) ? bitcache_resolve_id($id, $options) : FALSE;
728 }
729
730 function bitcache_uri($id) {
731 return 'bitcache://' . $id;
732 }
733
734 function bitcache_uri_to_id($uri) {
735 return preg_match('!^bitcache://([0-9a-f]{40})$!', $uri, $matches) ? $matches[1] : NULL; // FIXME
736 }
737
738 function bitcache_id($data) {
739 return sha1($data); // FIXME
740 }
741
742 function bitcache_id_file($data) {
743 return sha1_file($data); // FIXME
744 }
745
746 function bitcache_exists($id) {
747 return bitcache_op('exists', $id);
748 }
749
750 function bitcache_get($id) {
751 return bitcache_op('get', $id);
752 }
753
754 function bitcache_get_stream($id) {
755 return ($stream = bitcache_get($id)) ? $stream->open('rb') : NULL;
756 }
757
758 function bitcache_get_contents($id) {
759 return ($stream = bitcache_get($id)) ? $stream->data() : NULL;
760 }
761
762 function bitcache_get_path($id, $file_only = FALSE) {
763 if (($stream = bitcache_get($id))) {
764 if (!($path = $stream->path()) && $file_only) {
765 $path = bitcache_tmpname();
766
767 if (($data = $stream->open('rb'))) {
768 stream_copy_to_stream($stream->open('rb'), $file = fopen($path, 'wb'));
769 $stream->close();
770 fclose($file);
771 }
772 else {
773 file_put_contents($path, $stream->data());
774 }
775 }
776 return $path;
777 }
778 return NULL;
779 }
780
781 function bitcache_get_size($id) {
782 return ($stream = bitcache_get($id)) ? $stream->size() : NULL;
783 }
784
785 function bitcache_get_type($id) {
786 if (module_exists('rdf')) {
787 $uri = bitcache_uri($id);
788 // TODO: query RDF if available.
789 }
790 return ($stream = bitcache_get($id)) ? $stream->type() : NULL;
791 }
792
793 function bitcache_put($id, $data) {
794 return bitcache_op('put', $id, $data);
795 }
796
797 function bitcache_put_file($id, $filepath, $move = FALSE) {
798 return bitcache_op('put_file', $id, $filepath, $move);
799 }
800
801 function bitcache_delete($id) {
802 return bitcache_op('delete', $id);
803 }
804
805 function bitcache_op($op) {
806 // TODO: static cache for repository objects.
807 $args = array_slice(func_get_args(), 1);
808 $repo = bitcache_get_repository(isset($GLOBALS['bitcache_repository']) ? $GLOBALS['bitcache_repository'] : NULL);
809 return call_user_func_array(array($repo, $op), $args);
810 }
811
812 //////////////////////////////////////////////////////////////////////////////
813 // Bitcache API helpers
814
815 /**
816 * Synchronizes repositories using the Bitcache command-line tools.
817 */
818 function bitcache_sync(array $repos = array(), array $options = array()) {
819 return bitcache_exec(BITCACHE_EXEC . ' sync', NULL, $options, implode(' ', $repos));
820 }
821
822 /**
823 * Executes a 'bit' command using exec()/popen().
824 */
825 function bitcache_exec($command, $mode = NULL, array $options = array()) {
826 $config = bitcache_get_repositories('config');
827
828 if (file_put_contents($config_file = bitcache_tmpname(), bitcache_yaml($config))) {
829 $options = array_merge(array('config' => $config_file), $options);
830
831 foreach ($options as $k => $v) {
832 $command .= ' --' . $k . ($v === TRUE ? '' : '=' . escapeshellarg((string)$v));
833 }
834 $arguments = array_slice(func_get_args(), 3);
835 $command = trim($command . ' ' . implode(' ', array_map('escapeshellarg', $arguments)));
836
837 if (!$mode) {
838 exec($command . ' 2>&1', $output, $result);
839 return $result === 0 ? $output : FALSE;
840 }
841 return popen($command, $mode);
842 }
843 }
844
845 /**
846 * Returns a string containing a Bitcache configuration file in YAML format.
847 */
848 function bitcache_yaml($config) {
849 $output = array();
850 foreach ($config as $name => $cfg) {
851 $output[] = "$name:";
852 foreach ($cfg as $key => $value) {
853 $value = !is_bool($value) ? $value : ($value ? 'yes' : 'no');
854 $output[] = " $key: $value";
855 }
856 $output[] = '';
857 }
858 return implode("\n", $output);
859 }
860
861 /**
862 * Returns a path to a temporary file in Drupal's temporary directory.
863 */
864 function bitcache_tmpname($register = TRUE) {
865 if (($path = tempnam(file_directory_temp(), 'drupal_bitcache_')) && $register) {
866 global $user;
867 db_query("INSERT INTO {files} (fid, uid, filename, filepath, filemime, filesize, status, timestamp) VALUES (NULL, %d, '%s', '%s', '%s', 0, %d, %d)", $user->uid, basename($path), $path, 'application/octet-stream', FILE_STATUS_TEMPORARY, time());
868 }
869 return $path;
870 }
871
872 function bitcache_token_replace($text) {
873 if (module_exists('token')) {
874 module_load_include('inc', 'bitcache', 'bitcache.token');
875 return token_replace($text);
876 }
877 else { // simple fallback token support
878 $tokens = array(
879 '[file-directory-path]' => file_directory_path(),
880 '[file-directory-temp]' => file_directory_temp(),
881 '[site-host]' => $_SERVER['HTTP_HOST'],
882 );
883 return str_replace(array_keys($tokens), array_values($tokens), $text);
884 }
885 }

  ViewVC Help
Powered by ViewVC 1.1.2