Project

General

Profile

Download (15.8 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2

    
3
// at the moment we are using a static meta.xml file
4
define ("METADATA_FILE_NAME", "meta.xml");
5
define ("STATIC_DIR", "/static/");
6
define ("ARCHIVE_ROOT_DIR", "dwca_export/");
7
define ('FILE_MAP', 'dwca_export_archive_descriptor_file_map');
8

    
9

    
10
/**
11
 * Implements hook_menu().
12
 */
13
function dwca_export_menu() {
14

    
15
	$items = array();
16

    
17
	$items['admin/config/system/dwca_export'] = array(
18
		'title' => 'Darwin Core Archive export',
19
		'description' => t('Create a DarwinCore Archive of this scratchpad.'),
20
		'page callback' => 'drupal_get_form',
21
		'page arguments' => array('dwca_export_config_form'),
22
		'access arguments' => array('access DwC-A export settings'),
23
		'type' => MENU_NORMAL_ITEM,
24
		//'file' => 'dwca_export.admin.inc'
25
	);
26

    
27

    
28
	$items['dwca_export'] = array(
29
		'page callback' => 'dwca_export_deliver_archive',
30
		'access arguments' => array('access content'),
31
		'type' => MENU_CALLBACK
32
	);
33

    
34

    
35
	return $items;
36
}
37

    
38
/**
39
 * Implementation of hook_views_api()
40
 *
41
 * drupal will load dwca_export.views_default.inc when this hook is implemented
42
 */
43
function dwca_export_views_api() {
44
	return array(
45
		'api' => 3.0
46
	);
47
}
48

    
49
/**
50
* Implementation of hook_ctools_plugin_api().
51
*/
52
function dwca_export_ctools_plugin_api(){
53
	list($module, $api) = func_get_args();
54
	if($module == "strongarm" && $api == "strongarm"){
55
		return array(
56
      "version" => 1
57
		);
58
	}
59
}
60

    
61
/**
62
 * Form function, called by drupal_get_form()
63
 * in dwca_export_menu().
64
 */
65
function dwca_export_config_form($form, &$form_state) {
66

    
67
	global $base_url;
68

    
69
	$form['dwca_export_info'] = array(
70
		'#markup' => '<p>For general information on the DarwinCore Archive format please refer to  '
71
		. l('GBIF - Standards and Tools - Darwin Core Archives', 'http://www.gbif.org/informatics/standards-and-tools/publishing-data/data-standards/darwin-core-archives/')
72
		.'</p>'
73
	);
74

    
75
	$form['dwca_export_execute'] = array(
76
		'#markup' => '<p>The DarwinCore Archive export is available at '. l('dwca_export', 'dwca_export').'</p>'
77
		//'#type' => 'button',
78
		//'#value' => t('Export Scratchpad to DarwinCore Archive'), 
79
	  //'#weight' => 19,
80
	);
81
	
82
	$form['dwca_export_view_mapping'] = dwca_export_select_view_form();
83
	
84
	
85

    
86
	$form['#submit'][] = 'dwca_export_config_form_submit';
87
	return system_settings_form($form);
88

    
89
}
90

    
91

    
92
function dwca_export_select_view_form() {
93

    
94
	$views = array(
95
    		'#type' => 'fieldset',
96
    		'#title' => t('View to file mapping'),
97
    		//'#tree' => TRUE,
98
  	);
99

    
100
	foreach(variable_get(FILE_MAP) as $dwca_filename => $view_data){
101
		
102
		if ($dwca_filename == 'description') {
103
			
104
			foreach($view_data as $dwca_filename_inner => $view_data_inner){
105
				$views[$dwca_filename][$dwca_filename_inner] = array(
106
									  	'#type' => 'textfield',
107
									  	'#title' => t($dwca_filename . '_' . $dwca_filename_inner),
108
									  	'#default_value' => $view_data_inner['view_name'],
109
									  	'#size' => 60,
110
									  	'#maxlength' => 64,
111
									  	'#description' => t('specify view for ' . $dwca_filename_inner),
112
			
113
				);
114
			}
115
			
116
		} else {
117
			$views[$dwca_filename] = array(
118
					  	'#type' => 'textfield',
119
					  	'#title' => t($dwca_filename),
120
					  	'#default_value' => $view_data['view_name'],
121
					  	'#size' => 60,
122
					  	'#maxlength' => 64,
123
					  	'#description' => t('specify view for ' . $dwca_filename),
124
			
125
			);
126
		}
127
	}
128

    
129
	return $views;
130
}
131

    
132
function dwca_export_config_form_submit($form, &$form_state) {
133

    
134
	$variables = $form_state['input'];
135
	$save_variables = '';
136
	$dwca_export_archive_descriptor_file_map = variable_get(FILE_MAP);
137

    
138
	foreach ($variables as $key => $value) {
139

    
140
		if (array_key_exists($key, $dwca_export_archive_descriptor_file_map)) {
141

    
142
			$dwca_export_archive_descriptor_file_map[$key]['view_name'] = $value;
143
			//$save_variables .= '<p>' . $key . ' ' . $value . '</p>';
144
		} else {
145

    
146
			$description_key = 'description';
147
			
148
			if (array_key_exists($description_key, $dwca_export_archive_descriptor_file_map)) {
149
				
150
				//get the inner array containing the different description data types
151
				$description_map = $dwca_export_archive_descriptor_file_map[$description_key];
152
				//if (array_key_exists($key, $dwca_export_archive_descriptor_file_map['description'])) {
153
				if (array_key_exists($key, $description_map)) {
154
					drupal_set_message(t('The ooKEY is... ') . $key . t('The ooVALUE is... ') . $value);
155
					$dwca_export_archive_descriptor_file_map[$description_key][$key]['view_name'] = $value;
156
				}
157
			}
158
		}
159
	}
160

    
161
	variable_del(FILE_MAP);
162
	variable_set(FILE_MAP, $dwca_export_archive_descriptor_file_map);
163

    
164
	//drupal_set_message(t('The classification view is ') . $save_variables);// . '<pre>' . print_r($form_state,true) . '</pre>');//$save_variables);
165
}
166

    
167

    
168

    
169

    
170
// Reports an error if view name entered by the user does not exist in the database.
171
function dwca_export_config_form_validate($form, &$form_state) {
172
	
173
	$variables = $form_state['input'];
174
	$dwca_export_archive_descriptor_file_map = variable_get(FILE_MAP);
175
	$view_names = array();
176
	$missing_view_names = '';
177
	$missing_view = false;
178
	
179
	foreach ($variables as $key => $value) {
180
		
181
		//TODO: Check whether the views for the inner array cotaining all the description views exist
182
		if (array_key_exists($key, $dwca_export_archive_descriptor_file_map)) {
183
					
184
			$view = views_get_view($value);
185
			// check whether there is a view named with this value 
186
			if(!$view) {
187
				$view_names[] = $value;
188
				$missing_view_names .= $value . ', ';
189
				$missing_view = true;
190
			}
191
		}
192
	}
193
	
194
	if ($missing_view) {
195
		form_set_error('', t('VIEW(S) ' . $missing_view_names . ' NOT FOUND. Please input another view name.'));
196
	}
197
	
198
}
199

    
200
/**
201
 * menu callback
202
 */
203
function dwca_export_deliver_archive() {
204

    
205
	$tmp_archive_file_name = dwca_export_create_archive( _dwca_export_archive_descriptor_file_map() );
206

    
207
	if($tmp_archive_file_name && file_valid_uri($tmp_archive_file_name)){
208
		file_transfer($tmp_archive_file_name, array('Content-Type' => 'application/zip'));
209
	} else {
210
		throw new Exception(t('Error creating the archive'));
211
	}
212
}
213

    
214

    
215
/**
216
 * Provides the archive_descriptor_file_map which maps dwca file name to a set of view information.
217
 * The view information contains the fields 'view_name', 'display_id', 'out_file_url'.
218
 * The 'out_file_url' is initailly empty and will be set when this function is called
219
 * with both parameters.
220
 *
221
 * @param String $file_name
222
 * @param String $out_file_url
223
 *
224
 * @return the archive_descriptor_file_map
225
 */
226
function _dwca_export_archive_descriptor_file_map($file_name = NULL, $out_file_url = null){
227
	static $file_map;
228

    
229
	if(!isset($file_map)){
230
		$file_map = variable_get(FILE_MAP);
231
	}
232
	
233
	//lorna - there's no file_name for description
234
	drupal_set_message(t('The file_name... ') . $file_name);
235

    
236
	if($file_name && $out_file_url){
237
		
238
		//lorna
239
		drupal_set_message(t('The file_name... ') . $file_name . t('The out_file_url... ') . $out_file_url);
240
		
241
		if (($file_name == 'general') || ($file_name == 'morphology')) {
242
			$file_map['description'][$file_name]['out_file_url'] = $out_file_url;
243
			//$file_map[$file_name]['morphology']['out_file_url'] = $out_file_url;
244
		} else {
245
		///
246
		$file_map[$file_name]['out_file_url'] = $out_file_url;
247
		}
248
	}
249

    
250
	return $file_map;
251
}
252

    
253

    
254
/**
255
 * Walks all view export paths defined in the $views_map.
256
 * Each file is downloaded to the tmp folder and a zip file
257
 * is bundeled of the resulting csv files plus the meta file.
258
 *
259
 * @param $views_map - maps a view paths to dwca filenames
260
 *
261
 * @return the path in the filesystem to the final archive,
262
 * or FALSE in case of an error.
263
 */
264
function dwca_export_create_archive($views_map) {
265
	
266
	// all data is exported to temporary://dwca_export_*
267
	// now we can start bundling the actual archive
268
	$tmp_archive_file_name = drupal_tempnam("temporary://", "dwca_export_archive_");
269
	
270
	// Unfortunately we cannot use drupals ArchiverZip because there ís
271
	// no way to pass in ZipArchive::CREATE to the constructor to create the archive
272
	// TODO test if zip functionality is available (i.e. if(function_exists('zip_open'))
273
	// but I don't know where the proper location for such a check would be
274
	$zip = new ZipArchive();
275
	// it is safe to use drupal_realpath as the tmp file will be certainly local
276
	// and php's ZipArchive does not handle stream URIs
277
	$result = $zip->open(drupal_realpath($tmp_archive_file_name), ZipArchive::CREATE);
278
	
279
	// there might be a better way to get at this information
280
	$module_static_dir_absolute_path = realpath(drupal_get_path('module', 'dwca_export')) . STATIC_DIR;
281
	
282
	if ($result !== TRUE) {
283
		throw new Exception(t('Could not create zip_archive %tmp_archive_file_name', array('%tmp_archive_file_name' => $tmp_archive_file_name)));
284
	}
285
	
286
	
287
	// add metadata
288
	$zip->addFile($module_static_dir_absolute_path.METADATA_FILE_NAME, ARCHIVE_ROOT_DIR.METADATA_FILE_NAME);
289

    
290
	global $base_url;
291

    
292
	// execute all views to export the data into
293
	// temporary csv files (temporary://dwca_export_*). the resulting filenames
294
	// will be stored in _dwca_export_archive_descriptor_file_map()
295
	foreach($views_map as $filename=>$view_data){
296
	
297
		//lorna
298
		if ($filename == 'description') {
299
			
300
			//lorna: this foreach iterates through all the description types in the inner array
301
			foreach($view_data as $filename_inner => $view_data_inner){
302
				$view = views_get_view($view_data_inner['view_name']);
303
					
304
				$options = array (
305
				//'output_file' => $view_data['general']['view_name']
306
			'output_file' => $filename_inner
307
				);//The filename is description, but we have mulitple description views - where do we merge them?
308
					
309
				//lorna
310
				drupal_set_message(t('CREATED A FILE NAME FOR DESCRIPTION: ') . $view_data['general']['view_name']);
311
				drupal_set_message(t('The display name is: ') . $view_data['general']['display_id']);
312
				drupal_set_message(t('The filename_inner is: ') . $filename_inner);
313
					
314
				//_dwca_export_views_data_export_override_batch($view, $view_data['general']['display_id'], $options);
315
				_dwca_export_views_data_export_override_batch($view, $view_data_inner['display_id'], $options);
316
					
317
				//$view->execute_display($view_data['general']['display_id']);
318
				$view->execute_display($view_data_inner['display_id']);
319
			}
320
			
321
		}
322
		else {
323
			$view = views_get_view($view_data['view_name']);
324
			$options = array (
325
					    'output_file' => $filename
326
			);
327
			_dwca_export_views_data_export_override_batch($view, $view_data['display_id'], $options);
328
			$view->execute_display($view_data['display_id']);			
329
		}
330
		//end lorna
331
		
332
	}
333

    
334
	// add the csv data files
335
	foreach(_dwca_export_archive_descriptor_file_map() as $dwca_filename=>$view_data){
336

    
337
		if ($dwca_filename == 'description') {
338
			
339
			_dwca_export_concatenate_description_files($view_data, $zip);
340
			
341
		} else {
342
		
343
			$view_temp_file = $view_data['out_file_url'];
344
			_dwca_export_add_files_to_zip($view_temp_file, $dwca_filename, $zip);
345
		}
346
		
347
	}
348

    
349
	$zip->close();
350

    
351
	return $tmp_archive_file_name;
352
}
353

    
354
/**
355
 * 
356
 * Combines multiple Description Views for different description types into a single file
357
 * @param $view_data The inner array containing the view data for the different description types
358
 * @param $zip The zip file for the files making up the DwC-A.
359
 */
360
function _dwca_export_concatenate_description_files($view_data, $zip){
361
	
362
	$desc_file_name = drupal_tempnam("temporary://", "description.tmp");
363
	$desc_file = fopen(drupal_realpath($desc_file_name), "w");
364

    
365
	$first_desc_file = true;
366
	foreach($view_data as $type=>$view_data_inner){
367

    
368
		$view_temp_file = $view_data_inner['out_file_url'];
369

    
370
		$theFile = fopen($view_temp_file, "r");
371

    
372
		//print column names from first file
373
		if ($first_desc_file) {
374
			$lineOfText = fgets($theFile);
375
			fputs($desc_file, $lineOfText);
376
			$first_desc_file = false;
377
		} else {
378
			fgets($theFile);
379
		}
380

    
381
		while(!feof($theFile)){
382
			$lineOfText = fgets($theFile);
383
			print "$lineOfText<br />";
384

    
385
			$items = explode(',', $lineOfText);
386

    
387
			if (!empty($items[2])) {
388

    
389
				fputs($desc_file, $lineOfText);
390
				//add an end of line if there isn't one
391
				//if (!stripos(strrev($lineOfText), '"') === 0) {
392
				//fputs($desc_file, '"' . PHP_EOL);
393
				fputs($desc_file, PHP_EOL);
394
				//}
395
			} else {
396
				fgets($theFile);
397
			}
398

    
399
			drupal_set_message($lineOfText);
400
		}
401

    
402
		fclose($theFile);
403

    
404
		//currently also adding each individual desc type to archive
405
		_dwca_export_add_files_to_zip($view_temp_file, $type, $zip);
406
	}
407
	fclose($desc_file);
408

    
409
	_dwca_export_add_files_to_zip($desc_file_name, 'description', $zip);
410
}
411

    
412
function _dwca_export_add_files_to_zip($view_temp_file = NULL, $dwca_filename, $zip){
413
	
414
	if($view_temp_file){
415
		$zip->addFile(drupal_realpath($view_temp_file), ARCHIVE_ROOT_DIR.$dwca_filename);
416
	}else{
417
		throw new Exception(t('Cannot create %file', array('%file' => $dwca_filename)));
418
	}
419
}
420

    
421
/**
422
 * Helper function that indicates that we want to
423
 * override the batch that the views_data_export view creates
424
 * on it's initial time through.
425
 *
426
 * Also provides a place to stash options that need to stay around
427
 * until the end of the batch
428
 *
429
 * adapted fom views_data_export.drush.inc
430
 */
431
function _dwca_export_views_data_export_override_batch($view = NULL, $display = NULL, $options = TRUE) {
432
	
433
	//lorna
434
	if ($view) {
435
		drupal_set_message(t('in override batch WITH VIEW '));
436
	} else {
437
	drupal_set_message(t('in override batch: '));
438
	}
439
	static $_views;
440
	if (isset($view)) {
441
		
442
		//lorna
443
		drupal_set_message(t('in override batch with view: ') . $view->name);
444
		$_views[$view->name][$display] = $options;
445
	}
446
	return $_views;
447
}
448

    
449

    
450
/**
451
 * Implementation of hook_views_data_export_batch_alter()
452
 *
453
 * adapted fom views_data_export.drush.inc
454
 *
455
 *  @see batch_process() in form.inc
456
 */
457
function dwca_export_views_data_export_batch_alter(&$batch, &$final_destination, &$querystring) {
458

    
459
	$view_name = $batch['view_name'];
460
	$display_id = $batch['display_id'];
461
	
462
	//lorna
463
	drupal_set_message(t('in batch alter 1: ') );
464

    
465
	$ok_to_override = _dwca_export_views_data_export_override_batch();
466

    
467
	// Make sure we do nothing if we are called not following the execution of
468
	// our drush command. This could happen if the file with this function in it
469
	// is included during the normal execution of the view
470
	if (!$ok_to_override[$view_name][$display_id]) {
471
		return;
472
	}
473

    
474
	$options = $ok_to_override[$view_name][$display_id];
475

    
476
	// We actually never return from the drupal_alter, but
477
	// use drush's batch system to run the same batch
478

    
479
	// Add a final callback
480
	$batch['operations'][] = array(
481
	    '_dwca_export_views_data_export_batch_finished', array($batch['eid'], $options['output_file']),
482
	);
483

    
484
	$batch['progressive'] = FALSE;
485
}
486

    
487
/**
488
* Implementation of hook_views_data_export_batch_alter()
489
*
490
* @see batch_process() in form.inc
491
*/
492
function dwca_export_batch_alter(&$batch, &$final_destination, &$querystring) {
493
	
494
	//lorna
495
	drupal_set_message(t('in batch alter 2: ') );
496
	if($batch['source_url'] == 'dwca_export'){
497
		$batch['progressive'] = FALSE;
498
	}
499
}
500

    
501

    
502

    
503
/**
504
* Get's called at the end of the drush batch process that generated our export
505
*
506
* adapted fom views_data_export.drush.inc
507
*/
508
function _dwca_export_views_data_export_batch_finished($eid, $output_file, &$context) {
509
	// Fetch export info
510
	$export = views_data_export_get($eid);
511

    
512
	// Perform cleanup
513
	$view = views_data_export_view_retrieve($eid);
514
	$view->set_display($export->view_display_id);
515
	$view->display_handler->batched_execution_state = $export;
516
	$view->display_handler->remove_index();
517

    
518
	// Get path to temp file
519
	$temp_file = $view->display_handler->outputfile_path();
520

    
521
	//lorna - there's no file_name for description
522
	drupal_set_message(t('CALLING _dwca_export_archive_descriptor_file_map WITH OUTPUT_FILE: ') . $output_file . t(' and temp_FILE: ') . $temp_file);
523
	_dwca_export_archive_descriptor_file_map($output_file, $temp_file);
524

    
525
}
(3-3/5)