1 package CXGN
::BrAPI
::v2
::Images
;
6 use File
::Slurp qw
| slurp
|;
8 use SGN
::Model
::Cvterm
;
10 use CXGN
::Image
::Search
;
13 use CXGN
::Phenotypes
::StorePhenotypes
;
14 use Scalar
::Util
qw(looks_like_number);
16 extends
'CXGN::BrAPI::v2::Common';
21 my $page_size = $self->page_size;
22 my $page = $self->page;
23 my $status = $self->status;
24 my $page_obj = CXGN
::Page
->new();
25 my $hostname = $page_obj->get_hostname();
28 my $image_ids_arrayref = $params->{imageDbId
} || ($params->{imageDbIds
} || ());
29 my $image_names_arrayref = $params->{imageName
} || ($params->{imageNames
} || ());
30 my $stock_ids_arrayref = $params->{observationUnitDbId
} || ($params->{observationUnitDbIds
} || ());
31 my $phenotype_ids_arrayref = $params->{observationDbId
} || ($params->{observationDbIds
} || ());
32 my $descriptors_arrayref = $params->{descriptiveOntologyTerm
} || ($params->{descriptiveOntologyTerms
} || ());
33 my $reference_ids_arrayref = $params->{externalReferenceId
} || ($params->{externalReferenceIds
} || ());
34 my $reference_sources_arrayref = $params->{externalReferenceSource
} || ($params->{externalReferenceSources
} || ());
35 my $imagefile_names_arrayref = $params->{imageFileNames
} || ($params->{imageFileNames
} || ());
36 my $imagefile_size_max = $params->{imageFileSizeMax
}->[0] || undef;
37 my $imagefile_size_min = $params->{imageFileSizeMin
}->[0] || undef;
38 my $image_height_max = $params->{imageHeightMax
}->[0] || undef;
39 my $image_height_min = $params->{imageHeightMin
}->[0] || undef;
40 my $image_location_arrayref = $params->{imageLocation
} || ($params->{imageLocation
} || ());
41 my $image_timestamp_end = $params->{imageTimeStampRangeEnd
}->[0] || undef;
42 my $image_timestamp_start = $params->{imageTimeStampRangeStart
}->[0] || undef;
43 my $image_width_max = $params->{imageWidthMax
}->[0] || undef;
44 my $image_width_min = $params->{imageWidthMin
}->[0] || undef;
45 my $mimetypes_arrayref = $params->{mimeTypes
} || ($params->{mimeTypes
} || ());
47 if (($phenotype_ids_arrayref && scalar(@
$phenotype_ids_arrayref)>0) || ($reference_ids_arrayref && scalar(@
$reference_ids_arrayref)>0) || ($reference_sources_arrayref && scalar(@
$reference_sources_arrayref)>0) || ($image_location_arrayref && scalar(@
$image_location_arrayref)>0)){
48 push @
$status, { 'error' => 'The following search parameters are not implemented: observationDbId, externalReferenceID, externalReferenceSources, imageLocation' };
51 my %imagefile_names_arrayref;
52 if ($imagefile_names_arrayref && scalar(@
$imagefile_names_arrayref)>0){
53 %imagefile_names_arrayref = map { $_ => 1} @
$imagefile_names_arrayref;
56 my %phenotype_ids_arrayref;
57 if ($phenotype_ids_arrayref && scalar(@
$phenotype_ids_arrayref)>0){
58 %phenotype_ids_arrayref = map { $_ => 1} @
$phenotype_ids_arrayref;
61 my %mimetypes_arrayref;
62 if ($mimetypes_arrayref && scalar(@
$mimetypes_arrayref)>0){
63 %mimetypes_arrayref = map { $_ => 1} @
$mimetypes_arrayref;
66 my $start_index = $page*$page_size;
67 my $end_index = $page*$page_size + $page_size;
69 my $limit = $end_index-$start_index;
70 my $offset = $start_index;
72 my $image_search = CXGN
::Image
::Search
->new({
73 bcs_schema
=>$self->bcs_schema(),
74 people_schema
=>$self->people_schema(),
75 phenome_schema
=>$self->phenome_schema(),
76 image_name_list
=>$image_names_arrayref,
77 description_list
=>$descriptors_arrayref,
78 stock_id_list
=>$stock_ids_arrayref,
79 image_id_list
=>$image_ids_arrayref,
80 # still need to implement in the search
81 # phenotype_id_list=>$phenotype_ids_arrayref,
82 # imagefile_names_list =>$imagefile_names_arrayref,
83 # image_location_list =>$image_location_arrayref,
84 # mimetypes_list =>$mimetypes_arrayref
88 my ($result, $total_count) = $image_search->search();
91 my $start_index = $page*$page_size;
92 my $end_index = $page*$page_size + $page_size - 1;
96 my $mimetype = _get_mimetype
($_->{'image_file_ext'});
97 if ( (%mimetypes_arrayref && !exists($mimetypes_arrayref{$mimetype}))) { next; }
98 if ( (%imagefile_names_arrayref && !exists($imagefile_names_arrayref{$_->{'image_original_filename'}}))) { next; }
99 if ( $image_timestamp_start && _to_comparable
($_->{'image_modified_date'}) lt _to_comparable
($image_timestamp_start) ) { next; }
100 if ( $image_timestamp_end && _to_comparable
($_->{'image_modified_date'}) gt _to_comparable
($image_timestamp_end) ) { next; }
102 my $image = SGN
::Image
->new($self->bcs_schema()->storage->dbh(), $_->{'image_id'});
103 my @cvterms = $image->get_cvterms();
104 my $url = $hostname . $image->get_image_url('medium');
105 my $filename = $image->get_filename();
106 my $size = (stat($filename))[7];
107 my ($width, $height) = imgsize
($filename);
109 if ( $imagefile_size_max && $size > $imagefile_size_max ) { next; }
110 if ( $imagefile_size_min && $size < $imagefile_size_min + 1 ) { next; }
111 if ( $image_height_max && $height > $image_height_max ) { next; }
112 if ( $image_height_min && $height < $image_height_min + 1 ) { next; }
113 if ( $image_width_max && $width > $image_width_max ) { next; }
114 if ( $image_width_min && $width < $image_width_min + 1 ) { next; }
119 push(@cvterm_names, $_->name);
122 # Get the observation db ids
123 my @observationDbIds;
124 my $observations_array = $_->{'observations_array'};
126 foreach (@
$observations_array) {
127 my $observationDbId = $_->{'phenotype_id'};
128 push @observationDbIds, $observationDbId
132 foreach (@
{$_->{'tags_array'}}) {
133 $unique_tags{$_->{tag_id
}} = $_;
136 foreach my $tag_id (sort keys %unique_tags) {
137 push @sorted_tags, $unique_tags{$tag_id}{name
};
140 if ($counter >= $start_index && $counter <= $end_index) {
143 observationLevel
=> $_->{'stock_type_name'},
144 observationUnitName
=> $_->{'stock_uniquename'},
145 tags
=> \
@sorted_tags,
147 copyright
=> $_->{'image_username'} . " " . substr($_->{'image_modified_date'}, 0, 4),
148 description
=> $_->{'image_description'},
149 descriptiveOntologyTerms
=> \
@cvterm_names,
150 externalReferences
=> [],
151 imageDbId
=> qq|$_->{'image_id'}|,
152 imageFileName
=> $_->{'image_original_filename'},
153 imageFileSize
=> $size,
154 imageHeight
=> $height,
155 imageWidth
=> $width,
156 imageName
=> $_->{'image_name'},
157 imageTimeStamp
=> $_->{'image_modified_date'},
159 mimeType
=> _get_mimetype
($_->{'image_file_ext'}),
160 observationUnitDbId
=> qq|$_->{'stock_id'}|,
161 # location and linked phenotypes are not yet available for images in the db
162 imageLocation
=> undef,
163 observationDbIds
=> [ @observationDbIds ],
169 my %result = (data
=> \
@data);
171 my $pagination = CXGN
::BrAPI
::Pagination
->pagination_response($total_count,$page_size,$page);
172 return CXGN
::BrAPI
::JSONResponse
->return_success(\
%result, $pagination, \
@data_files, $status, 'Image search result constructed');
178 my $page_size = $self->page_size;
179 my $page = $self->page;
180 my $status = $self->status;
181 my $page_obj = CXGN
::Page
->new();
182 my $hostname = $page_obj->get_hostname();
185 my $image = SGN
::Image
->new($self->bcs_schema()->storage->dbh(), $inputs->{image_id
});
186 my @cvterms = $image->get_cvterms();
187 my $url = $hostname . $image->get_image_url('medium');
188 my $filename = $image->get_filename();
189 my $size = (stat($filename))[7];
190 my ($width, $height) = imgsize
($filename);
193 push @image_ids, $inputs->{image_id
};
194 my $image_search = CXGN
::Image
::Search
->new({
195 bcs_schema
=>$self->bcs_schema(),
196 people_schema
=>$self->people_schema(),
197 phenome_schema
=>$self->phenome_schema(),
198 image_id_list
=>\
@image_ids
201 my ($search_result, $total_count) = $image_search->search();
204 foreach (@
$search_result) {
209 push(@cvterm_names, $_->name);
212 # Get the observation variable db ids
213 my @observationDbIds;
214 my $observations_array = $_->{'observations_array'};
216 foreach (@
$observations_array) {
217 my $observationDbId = $_->{'phenotype_id'};
218 push @observationDbIds, $observationDbId
222 foreach (@
{$_->{'tags_array'}}) {
223 $unique_tags{$_->{tag_id
}} = $_;
226 foreach my $tag_id (sort keys %unique_tags) {
227 push @sorted_tags, $unique_tags{$tag_id}{name
};
232 observationLevel
=> $_->{'stock_type_name'},
233 observationUnitName
=> $_->{'stock_uniquename'},
234 tags
=> \
@sorted_tags,
236 copyright
=> $_->{'image_username'} . " " . substr($_->{'image_modified_date'},0,4),
237 description
=> $_->{'image_description'},
238 descriptiveOntologyTerms
=> \
@cvterm_names,
239 externalReferences
=> [],
240 imageDbId
=> qq|$_->{'image_id'}|,
241 imageFileName
=> $_->{'image_original_filename'},
242 imageFileSize
=> $size,
243 imageHeight
=> $height,
244 imageWidth
=> $width,
245 imageName
=> $_->{'image_name'},
246 imageTimeStamp
=> $_->{'image_modified_date'},
248 mimeType
=> _get_mimetype
($_->{'image_file_ext'}),
249 observationUnitDbId
=> qq|$_->{'stock_id'}|,
250 # location and linked phenotypes are not yet available for images in the db
251 imageLocation
=> undef,
252 observationDbIds
=> [@observationDbIds],
257 my $pagination = CXGN
::BrAPI
::Pagination
->pagination_response($total_count,$page_size,$page);
258 return CXGN
::BrAPI
::JSONResponse
->return_success(\
%result, $pagination, \
@data_files, $status, 'Image detail constructed');
261 sub image_metadata_store
{
264 my $image_dir = shift;
266 my $user_type = shift;
267 my $image_id = shift;
269 my $page_size = $self->page_size;
270 my $page = $self->page;
271 my $status = $self->status;
272 my $dbh = $self->bcs_schema()->storage()->dbh();
273 my $page_obj = CXGN
::Page
->new();
274 my $hostname = $page_obj->get_hostname();
277 foreach my $params (@
{$data}) {
278 my $image_id = $params->{imageDbId
} ?
$params->{imageDbId
} : undef;
279 my $imageName = $params->{imageName
} ?
$params->{imageName
} : "";
280 my $description = $params->{description
} ?
$params->{description
} : "";
281 my $imageFileName = $params->{imageFileName
} ?
$params->{imageFileName
} : "";
282 print STDERR
"Image filename in metadata store is: $imageFileName\n";
283 my $mimeType = $params->{mimeType
} ?
$params->{mimeType
} : undef;
284 my $observationUnitDbId = $params->{observationUnitDbId
} ?
$params->{observationUnitDbId
} : undef;
285 my $descriptiveOntologyTerms_arrayref = $params->{descriptiveOntologyTerms
} || ();
286 my $observationDbIds_arrayref = $params->{observationDbIds
} || ();
288 # metadata store for the rest not yet implemented
289 my $imageFileSize = $params->{imageFileSize
} ?
$params->{imageFileSize
} : undef;
290 my $imageHeight = $params->{imageHeight
} ?
$params->{imageHeight
} : ();
291 my $imageWidth = $params->{imageWidth
} ?
$params->{imageWidth
} : ();
292 my $copyright = $params->{copyright
} || "";
293 my $imageTimeStamp = $params->{imageTimeStamp
} || "";
294 my $imageLocation_hashref = $params->{imageLocation
} || ();
295 my $additionalInfo_hashref = $params->{additionalInfo
} || ();
297 # Prechecks before storing
298 # Check that our observation unit db id exists. If not return error.
299 if ($observationUnitDbId) {
300 my $stock = $self->bcs_schema()->resultset("Stock::Stock")->find({ stock_id
=> $observationUnitDbId });
301 if (! defined $stock) {
302 return CXGN
::BrAPI
::JSONResponse
->return_error($self->status, 'Stock id is not valid. Cannot generate image metadata');
306 # Check that the cvterms are valid before continuing
308 foreach (@
$descriptiveOntologyTerms_arrayref) {
310 # If is like number, search for id
311 if (looks_like_number
($_)) {
312 # Check if the trait exists
313 $cvterm_id = SGN
::Model
::Cvterm
->find_trait_by_id($self->bcs_schema(), $_);
316 # else search for string
317 $cvterm_id = SGN
::Model
::Cvterm
->find_trait_by_name($self->bcs_schema(), $_);
320 if (!defined $cvterm_id) {
321 return CXGN
::BrAPI
::JSONResponse
->return_error($self->status, sprintf('Descriptive ontology term %s not found. Cannot generate image metadata', $_));
324 push(@cvterm_ids, $cvterm_id);
327 # Check that the image type they want to pass in is supported.
328 # If it is not converted, and is the same after _get_extension, it is not supported.
329 my $extension_type = _get_extension
($mimeType);
330 if ($extension_type eq $mimeType) {
331 return CXGN
::BrAPI
::JSONResponse
->return_error($self->status, sprintf('Mime type %s is not supported.', $mimeType));
334 # Check if an image id was passed in, and if that image exists
335 my $image_obj = CXGN
::Image
->new( dbh
=>$dbh, image_dir
=> $image_dir, image_id
=> $image_id);
336 if ($image_id && ! defined $image_obj->get_create_date()) {
337 return CXGN
::BrAPI
::JSONResponse
->return_error($self->status, sprintf('Image with id of %s, does not exist', $image_id));
340 # Check that the observationDbIds they passed exists
341 foreach (@
$observationDbIds_arrayref) {
342 my $phenotype = $self->bcs_schema()->resultset("Phenotype::Phenotype")->find({ phenotype_id
=> $_ });
343 if (! defined $phenotype) {
344 return CXGN
::BrAPI
::JSONResponse
->return_error($self->status, sprintf('Observation with id of %s, does not exist', $_));
351 # Assign image properties
352 unless ($image_id) { $image_obj->set_sp_person_id($user_id); }
353 $image_obj->set_name($imageName);
354 $image_obj->set_description($description);
355 $image_obj->set_original_filename($imageFileName);
356 $image_obj->set_file_ext($extension_type);
358 # Save the image to the db
359 $image_id = $image_obj->store();
361 my $image = SGN
::Image
->new($self->bcs_schema()->storage->dbh(), $image_id);
363 # Remove cvterms so we can reassign them later
364 my @prev_cvterms = $image->get_cvterms();
365 foreach (@prev_cvterms) {
366 $image->remove_associated_cvterm($_->cvterm_id);
369 # Store desceriptiveOntologyTerms in the cvterm after finding the cvterm here.
370 foreach (@cvterm_ids) {
371 $image->associate_cvterm($_);
374 # Clear previously associated stocks.
375 my @stocks = $image->get_stocks();
377 $image->remove_stock($_->stock_id);
380 # Associate our stock with the image, if a stock_id was provided.
381 if ($observationUnitDbId) {
382 my $person = CXGN
::People
::Person
->new($dbh, $user_id);
383 my $user_name = $person->get_username;
384 $image->associate_stock($observationUnitDbId, $user_name);
387 # Clear previously associated phenotypes
388 $image->remove_associated_phenotypes();
390 # Associate the image with the observations specified
391 foreach (@
$observationDbIds_arrayref) {
393 my $nd_experiment_phenotype = $self->bcs_schema()->resultset("NaturalDiversity::NdExperimentPhenotype")->find({ phenotype_id
=> $_ });
395 if ($nd_experiment_phenotype) {
396 my %image_hash = ($nd_experiment_phenotype->nd_experiment_id => $image_id);
397 $image->associate_phenotype(\
%image_hash);
399 return CXGN
::BrAPI
::JSONResponse
->return_error($self->status, sprintf('Cannot find experiment associated with observation with id of %s, does not exist', $_));
403 if ($additionalInfo_hashref) {
404 my $tag_list = $additionalInfo_hashref->{tags
};
405 if($tag_list && scalar(@
$tag_list) > 0){
407 my $image_tag_id = CXGN
::Tag
::exists_tag_named
($self->bcs_schema()->storage->dbh, $_);
409 if (!$image_tag_id) {
410 my $image_tag = CXGN
::Tag
->new($self->bcs_schema()->storage->dbh);
411 $image_tag->set_name($_);
412 $image_tag->set_description('Image: '.$_);
413 $image_tag->set_sp_person_id($user_id);
414 $image_tag_id = $image_tag->store();
416 my $image_tag = CXGN
::Tag
->new($self->bcs_schema()->storage->dbh, $image_tag_id);
419 $image->add_tag($image_tag);
424 push @image_ids, $image_id;
427 my $image_search = CXGN
::Image
::Search
->new({
428 bcs_schema
=>$self->bcs_schema(),
429 people_schema
=>$self->people_schema(),
430 phenome_schema
=>$self->phenome_schema(),
431 image_id_list
=>\
@image_ids
434 my ($result, $total_count) = $image_search->search();
440 my $mimetype = _get_mimetype
($_->{'image_file_ext'});
441 my $image = SGN
::Image
->new($self->bcs_schema()->storage->dbh(), $_->{'image_id'});
442 my @cvterms = $image->get_cvterms();
444 # my $url = $hostname . $image->get_image_url('medium');
445 # my $filename = $image->get_filename();
446 # my $size = (stat($filename))[7];
447 # my ($width, $height) = imgsize($filename);
452 push(@cvterm_names, $_->name);
455 # Get the observation db ids
456 my @observationDbIds;
457 my $observations_array = $_->{'observations_array'};
459 foreach (@
$observations_array) {
460 my $observationDbId = $_->{'phenotype_id'};
461 push @observationDbIds, $observationDbId
465 foreach (@
{$_->{'tags_array'}}) {
466 $unique_tags{$_->{tag_id
}} = $_;
469 foreach my $tag_id (sort keys %unique_tags) {
470 push @sorted_tags, $unique_tags{$tag_id}{name
};
475 observationLevel
=> $_->{'stock_type_name'},
476 observationUnitName
=> $_->{'stock_uniquename'},
477 tags
=> \
@sorted_tags,
479 copyright
=> $_->{'image_username'} . " " . substr($_->{'image_modified_date'},0,4),
480 description
=> $_->{'image_description'},
481 descriptiveOntologyTerms
=> \
@cvterm_names,
482 externalReferences
=> [],
483 imageDbId
=> qq|$_->{'image_id'}|,
484 imageFileName
=> $_->{'image_original_filename'},
485 # imageFileSize => $size,
486 # imageHeight => $height,
487 # imageWidth => $width,
488 imageName
=> $_->{'image_name'},
489 imageTimeStamp
=> $_->{'image_modified_date'},
491 mimeType
=> _get_mimetype
($_->{'image_file_ext'}),
492 observationUnitDbId
=> qq|$_->{'stock_id'}|,
493 # location and linked phenotypes are not yet available for images in the db
494 imageLocation
=> undef,
495 observationDbIds
=> [@observationDbIds],
505 $result = {data
=> \
@data};
508 my $pagination = CXGN
::BrAPI
::Pagination
->pagination_response($counter,$page_size,$page);
509 return CXGN
::BrAPI
::JSONResponse
->return_success( $result, $pagination, undef, $self->status(), 'Image metadata stored');
512 sub image_data_store
{
514 my $image_dir = shift;
515 my $image_id = shift;
517 my $content_type = shift;
519 print STDERR
"Image ID: $image_id. inputs to image metadata store: ".Dumper
($inputs);
521 # Get our image file extension type from the database
523 push @image_ids, $image_id;
524 my $image_search = CXGN
::Image
::Search
->new({
525 bcs_schema
=>$self->bcs_schema(),
526 people_schema
=>$self->people_schema(),
527 phenome_schema
=>$self->phenome_schema(),
528 image_id_list
=>\
@image_ids
531 my ($search_result, $total_count) = $image_search->search();
532 my $file_extension = @
$search_result[0]->{'image_file_ext'};
533 my $original_filename = @
$search_result[0]->{'image_original_filename'};
535 if (! defined $file_extension) {
536 return CXGN
::BrAPI
::JSONResponse
->return_error($self->status, sprintf('Unsupported image type, %s', $file_extension));
539 my $tempfile = $inputs->filename();
540 my ($filename, $tempdir, $extension) = fileparse
($tempfile);
542 my $updated_tempfile_name = $tempdir . $original_filename;
544 print STDERR
"\n\n Updated tempfile name is $updated_tempfile_name\n";
546 rename($tempfile, $updated_tempfile_name);
548 # process image data through CXGN::Image...
550 my $cxgn_img = CXGN
::Image
->new(dbh
=>$self->bcs_schema()->storage()->dbh(), image_dir
=> $image_dir, image_id
=> $image_id);
553 $cxgn_img->process_image($updated_tempfile_name);
557 print STDERR
"An error occurred during image processing... $@\n";
560 print STDERR
"Image processed successfully.\n";
563 my %result = ( image_id
=> $image_id);
565 foreach (@
$search_result) {
566 my $sgn_image = SGN
::Image
->new($self->bcs_schema()->storage->dbh(), $_->{'image_id'});
567 my $page_obj = CXGN
::Page
->new();
568 my $hostname = $page_obj->get_hostname();
569 my $url = $hostname . $sgn_image->get_image_url('medium');
570 my $filename = $sgn_image->get_filename();
571 my $size = (stat($filename))[7];
572 my ($width, $height) = imgsize
($filename);
574 # Get the observation variable db ids
575 my @observationDbIds;
576 my $observations_array = $_->{'observations_array'};
578 foreach (@
$observations_array) {
579 my $observationDbId = $_->{'phenotype_id'};
580 push @observationDbIds, $observationDbId
584 foreach (@
{$_->{'tags_array'}}) {
585 $unique_tags{$_->{tag_id
}} = $_;
588 foreach my $tag_id (sort keys %unique_tags) {
589 push @sorted_tags, $unique_tags{$tag_id}{name
};
592 my @cvterms = $sgn_image->get_cvterms();
596 push(@cvterm_names, $_->name);
601 observationLevel
=> $_->{'stock_type_name'},
602 observationUnitName
=> $_->{'stock_uniquename'},
603 tags
=> \
@sorted_tags,
605 copyright
=> $_->{'image_username'} . " " . substr($_->{'image_modified_date'},0,4),
606 description
=> $_->{'image_description'},
607 descriptiveOntologyTerms
=> \
@cvterm_names,
608 externalReferences
=> [],
609 imageDbId
=> $_->{'image_id'},
610 imageFileName
=> $_->{'image_original_filename'},
611 imageFileSize
=> $size,
612 imageHeight
=> $height,
613 imageWidth
=> $width,
614 imageName
=> $_->{'image_name'},
615 imageTimeStamp
=> $_->{'image_modified_date'},
617 mimeType
=> _get_mimetype
($_->{'image_file_ext'}),
618 observationUnitDbId
=> $_->{'stock_id'},
619 # location and linked phenotypes are not yet available for images in the db
620 imageLocation
=> undef,
621 observationDbIds
=> [@observationDbIds],
625 my $pagination = CXGN
::BrAPI
::Pagination
->pagination_response(1, 10, 0);
626 return CXGN
::BrAPI
::JSONResponse
->return_success( \
%result, $pagination, [], $self->status(), 'Image data store successful');
630 my $extension = shift || '';
632 '.jpg' => 'image/jpeg',
633 '.JPG' => 'image/jpeg',
634 '.jpeg' => 'image/jpeg',
635 '.png' => 'image/png',
636 '.gif' => 'image/gif',
637 '.svg' => 'image/svg+xml',
638 '.pdf' => 'application/pdf',
639 '.ps' => 'application/postscript',
641 if ( defined $mimetypes{$extension} ) {
642 return $mimetypes{$extension};
649 my $mimetype = shift;
651 'image/jpeg' => '.jpg',
652 'image/png' => '.png',
653 'image/gif' => '.gif',
654 'image/svg+xml' => '.svg',
655 'application/pdf' => '.pdf',
656 'application/postscript' => '.ps'
658 if ( defined $extensions{$mimetype} ) {
659 return $extensions{$mimetype};
667 my $str_date = shift;
670 $str_date =~ s/\ /+/g; #clean_inputs delete +, adding it
671 my $formatted_time = Time
::Piece
->strptime($str_date,'%Y-%m-%dT%T %z');
672 $date = $formatted_time->epoch;