4 my $add_publication_page = CXGN
::Chado
::AddPublicationPage
->new();
6 package CXGN
::Chado
::AddPublicationPage
;
10 use CXGN
::Page
::FormattingHelpers qw
/ info_section_html page_title_html html_optional_show/;
11 use CXGN
::Chado
::Publication
;
12 use CXGN
::Phenome
::Locus
;
13 use CXGN
::Phenome
::Allele
;
17 use CXGN
::Tools
::Pubmed
;
18 use CXGN
::Tools
::Text qw
/ sanitize_string /;
19 use Bio
::Chado
::Schema
;
20 use CXGN
::Chado
::Stock
;
21 use CatalystX
::GlobalContext
qw( $c );
23 use base qw / CXGN::Page::Form::SimpleFormPage /;
27 my $self = $class->SUPER::new(@_);
28 $self->set_script_name("add_publication.pl");
36 # call set_object_id, set_object and set_primary_key here
37 # with the appropriate parameters.
39 my %args = $self->get_args();
40 $self->set_object_id($args{pub_id});
41 $self->set_object(CXGN::Chado::Publication->new( $self->get_dbh(), $self->get_object_id() )
43 $self->set_primary_key("pub_id");
44 # $self->set_object_owner($self->get_object()->get_sp_person_id); #publications do not have owners, but object_dbxref linking tables do!
46 $self->set_owners( ());
47 $self->set_schema($c->dbic_schema('Bio::Chado::Schema', 'sgn_chado') );
50 # override store to check if a publication with the submitted ID (pubmed accession?) already exists
55 my $publication = $self->get_object();
56 my $sp_person_id=$self->get_user()->get_sp_person_id();
58 my %args = $self->get_args();
61 my $action=$args{action};
62 my $refering_page=$args{refering_page};
63 my $type= $args{type}; #locus or allele or stock...?
64 my $type_id = $args{type_id}; #the database id of the refering object (locus..)
65 my $accession= sanitize_string($args{accession});
66 my $script_name= $self->get_script_name();
68 my ($locus, $allele, $pop, $ind, $stock);
70 if ($type eq 'locus') { $locus= CXGN::Phenome::Locus->new($self->get_dbh(), $type_id); }
71 elsif ($type eq 'allele') { $allele= CXGN::Phenome::Allele->new($self->get_dbh(), $type_id); }
72 elsif ($type eq 'stock') { $stock= CXGN::Chado::Stock->new($self->get_schema(), $type_id); }
76 my $existing_publication= CXGN::Chado::Publication->get_pub_by_accession($self->get_dbh(),$accession );
77 if ($pub_id = $existing_publication->get_pub_id) {
78 #if the publication is already stored in dbxref, we need it's dbxref_id for storing it in the object_dbxref linking table
79 $publication=CXGN::Chado::Publication->new($self->get_dbh(), $pub_id);
80 $dbxref_id= $publication->get_dbxref_id_by_db('PMID');
82 $publication->set_accession($accession);
83 $publication->add_dbxref("PMID:$accession");
86 my $dbxref= CXGN::Chado::Dbxref->new($self->get_dbh(), $dbxref_id);
88 #now check if the publication exists and associated and if it has been obsoleted..
89 my ($associated_publication, $obsolete);
92 if ($type eq 'locus') {
93 $associated_publication= $locus->get_locus_dbxref($dbxref)->get_object_dbxref_id();
94 $obsolete = $locus->get_locus_dbxref($dbxref)->get_obsolete();
95 }elsif ($type eq 'allele') {
96 $associated_publication= $allele->get_allele_dbxref($dbxref)->get_allele_dbxref_id();
97 $obsolete = $allele->get_allele_dbxref($dbxref)->get_obsolete();
99 # ##the publication exists but not associated with the object
101 if ($type eq 'locus') {$locus->add_locus_dbxref($dbxref, $associated_publication, $sp_person_id); }
102 elsif ($type eq 'allele') { $allele->add_allele_dbxref($dbxref, $associated_publication, $sp_person_id);}
103 elsif ($type eq 'stock') { $stock->get_object_row->find_or_create_related('stock_pubs' , {
104 pub_id => $pub_id } );
106 $self->send_publication_email();
107 if (!$type && !$type_id) {
108 $self->get_page()->client_redirect("/publication/$pub_id/view");
110 $self->get_page()->client_redirect("$script_name?type=$type&type_id=$type_id&refering_page=$refering_page&action=new");
113 #fetch the publication from pubmed:
114 my $pubmed= CXGN::Tools::Pubmed->new($publication);
115 my $e_id = $publication->get_eid;
117 $publication->add_dbxref("DOI:$e_id");
119 $self->SUPER::store(1); #this gives the publication a dbxref id, and stores it in pub, pub_dbxref pubabstract(change to pubprop!!), and pub_author
121 #instantiate a new dbxref object
122 my $dbxref= CXGN::Chado::Dbxref->new($self->get_dbh(), $publication->get_dbxref_id_by_db('PMID') );
124 #store the new locus_dbxref..
125 if ($type eq 'locus') { $locus->add_locus_dbxref($dbxref, undef, $sp_person_id); }
126 elsif ($type eq 'allele') { $allele->add_allele_dbxref($dbxref, undef, $sp_person_id); }
127 elsif ($type eq 'stock') { $stock->get_object_row->find_or_create_related('stock_pubs' , {
128 pub_id => $publication->get_pub_id } );
130 $self->send_publication_email();
131 if ($type && $type_id) { #if the publication is also associated with another object
132 $self->get_page()->client_redirect("$script_name?type=$type&type_id=$type_id&refering_page=$refering_page&action=new");
134 my $pub_id = $publication->get_pub_id();
135 $self->get_page()->client_redirect("/publication/$pub_id/view");
142 $self->check_modify_privileges();
143 my $script_name= $self->get_script_name();
144 my %args= $self->get_args();
145 my $type= $args{type};
146 my $type_id= $args{type_id};
147 my $refering_page=$args{refering_page};
149 my $publication = $self->get_object();
151 if ($type eq 'locus') {
152 my $locus_dbxref_obj=CXGN::Phenome::LocusDbxref->new($self->get_dbh, $args{object_dbxref_id});
153 $locus_dbxref_obj->obsolete();
155 } elsif ($type eq 'allele') {
156 my $allele_dbxref_obj=CXGN::Phenome::AlleleDbxref->new($self->get_dbh, $args{object_dbxref_id});
157 $allele_dbxref_obj->delete();
159 } elsif ($type eq 'stock') {
160 #need to pass the stock_pub_id as object_pub_id arg
161 $self->get_schema->resultset("Stock::StockPub")->find( { stock_pub_id => $args{object_pub_id} } )
164 }else { print qq | <h3> What are you trying to delete here? </h3>| };
166 $self->send_publication_email();
167 $self->get_page()->client_redirect("$script_name?type=$type&type_id=$type_id&refering_page=$refering_page&action=new");
173 my %args = $self->get_args();
174 $self->check_modify_privileges();
177 my $object_name = shift;
178 my $field_name = shift;
179 my $object_id = shift;
181 my $type = $args{type};
182 my $type_id= $args{type_id}; #the id of the object we want to associate to the publication
185 my $object_pub_id = $args{object_pub_id};
186 my $object_dbxref_id= $args{object_dbxref_id};
188 if ( $object_dbxref_id ) {
189 if ($type eq 'locus') {
190 my $locus = CXGN::Phenome::Locus->new($self->get_dbh(), $type_id);
191 $object_name = $locus->get_locus_name();
192 }elsif ($type eq 'allele') {
193 my $allele = CXGN::Phenome::Allele->new($self->get_dbh(), $type_id);
194 $object_name = $allele->get_allele_name();
196 $object_dbxref_id= $args{object_dbxref_id};
198 if ( $object_pub_id ) {
199 if ($type eq 'stock') {
200 my $stock = $self->get_schema->resultset("Stock::Stock")->find( {
201 stock_id => $type_id } );
202 $object_name = $stock->name;
205 my $back_link= qq |<a href="javascript:history.back(1)">Go back without deleting</a> |;
207 $self->get_page()->header();
212 Delete publication association with $type ($object_name)?
213 <input type="hidden" name="action" value="delete" />
214 <input type="hidden" name="$field_name" value="$object_id" />
215 <input type="hidden" name="type" value="$type" />
216 <input type="hidden" name="type_id" value="$type_id" />
217 <input type="hidden" name="object_dbxref_id" value="$object_dbxref_id" />
218 <input type="hidden" name="object_pub_id" value="$object_pub_id" />
219 <input type="hidden" name="refering_page" value="$args{refering_page}" />
220 <input type="submit" value="Delete" />
226 $self->get_page()->footer();
233 my %args = $self->get_args();
234 my $publication = $self->get_object();
235 my $pub_id = $self->get_object_id();
239 # generate the form with the appropriate values filled in.
240 # if we view, then take the data straight out of the database
241 # if we edit, take data from database and override with what's
242 # in the submitted form parameters.
243 # if we store, only take the form parameters into account.
244 # for new, we don't do anything - we present an empty form.
249 $self->get_form()->add_field(display_name=>"Enter a PubMed ID: ",
250 field_name=>"accession",
252 object=>$publication,
253 getter=>"get_accession",
254 setter=>"set_accession",
259 $self->get_form()->add_hidden( field_name=>"action", contents=>"confirm_store" );
260 $self->get_form()->add_hidden( field_name=>"pub_id", contents=>$pub_id );
262 $self->get_form()->add_hidden( field_name=>"type_id",
263 contents=>$args{type_id} );
265 $self->get_form()->add_hidden( field_name=>"type",
266 contents=>$args{type} );
268 $self->get_form()->add_hidden( field_name=>"refering_page",
269 contents=>$args{refering_page} );
272 if ($self->get_action()=~/store/i) {
273 $self->get_form()->from_request(%args);
281 my %args = $self->get_args();
282 #my $cvterm_name = $args{cvterm_name};
283 # generate an appropriate edit link
286 $self->get_page->jsan_use("CXGN.Phenome.Tools");
287 $self->get_page->jsan_use("MochiKit.DOM");
288 $self->get_page->jsan_use("Prototype");
290 my $script_name = $self->get_script_name();
291 my @publications = ();
293 my ($locus, $allele, $pop, $ind, @dbxref_objs, $object_dbxref_id, $obsolete, $name_dbxref_id, $stock, $pubs); #add vars here if you want this script to work with other object types..
296 $self->get_page()->header();
298 print page_title_html( qq { SGN publication upload page } );
300 print qq { <b> Publications list</b> };
302 if ($args{type} eq 'locus') {
303 $locus = CXGN::Phenome::Locus->new($self->get_dbh(), $args{type_id});
304 @dbxref_objs= $locus->get_dbxrefs(); #array of dbxref objects
305 print "for locus '".$locus->get_locus_name()."'<br /><br />\n";
307 }elsif ($args{type} eq 'allele') {
308 $allele = CXGN::Phenome::Allele->new($self->get_dbh(), $args{type_id});
309 @dbxref_objs=$allele->get_all_allele_dbxrefs(); #array of dbxref objects
310 print "for allele '".$allele->get_allele_name()."'<br /><br />\n";
312 elsif ($args{type} eq 'stock') {
313 $stock = CXGN::Chado::Stock->new($self->get_schema, $args{type_id});
314 $pubs = $stock->get_object_row->search_related('stock_pubs');
315 $pubs = $pubs->search_related('pub') if $pubs;
316 print "for stock '".$stock->get_name ."'<br /><br />\n";
318 while (my $pub = $pubs->next ) {
319 my $pub_id = $pub->pub_id;
320 my $db_name = $pub->pub_dbxrefs->first->dbxref->db->name;
321 my $accession = $pub->pub_dbxrefs->first->dbxref->accession;
322 my $author_string = $self->author_string($pub);
323 my $object_pub_id = $stock->get_object_row->search_related('stock_pubs', pub_id => $pub_id)->first->stock_pub_id if $stock;
324 print "<a href= /publication/$pub_id/view>$db_name:$accession</a> " . $pub->title() . " (" . $pub->pyear() . ") <b>" . $author_string . "</b>" . qq { \n <a href="add_publication.pl?pub_id=$pub_id&type=$args{type}&type_id=$args{type_id}&object_pub_id=$object_pub_id&action=confirm_delete&refering_page=$args{refering_page}">[Remove]</a> <br /><br />\n };
328 foreach my $dbxref (@dbxref_objs) {
329 my $db_name=$dbxref->get_db_name();
330 my $pub= $dbxref->get_publication();
332 my $pub_id = $pub->get_pub_id();
333 my $accession= $dbxref->get_accession();
335 if ($args{type} eq 'locus') {
336 #$name_dbxref_id= 'locus_dbxref_id';
337 $object_dbxref_id= $locus->get_locus_dbxref($dbxref)->get_object_dbxref_id();
338 $obsolete= $locus->get_locus_dbxref($dbxref)->get_obsolete();
339 }elsif ($args{type} eq 'allele') {
340 #$name_dbxref_id= 'allele_dbxref_id';
341 $object_dbxref_id= $allele->get_allele_dbxref($dbxref)->get_allele_dbxref_id();
342 $obsolete= $allele->get_allele_dbxref($dbxref)->get_obsolete();
344 if ($db_name eq 'SGN_ref') { $accession= $pub_id; }
345 if ($obsolete eq 'f') {
346 if ($pub_id && $object_dbxref_id) {print "<a href= /publication/$pub_id/view>$db_name:$accession</a>" . $pub->get_title() . " (" . $pub->get_pyear() . ") <b>" . $pub->get_authors_as_string() . "</b>" . qq { \n <a href="add_publication.pl?pub_id=$pub_id&type=$args{type}&type_id=$args{type_id}&object_dbxref_id=$object_dbxref_id&action=confirm_delete&refering_page=$args{refering_page}">[Remove]</a> <br /><br />\n }; }
348 push @obsoleted, [$pub, $object_dbxref_id] ; #an array of obsoletes pub objects
352 if (@obsoleted) { $self->print_obsoleted($args{type}, $args{type_id}, @obsoleted) ; }
354 print qq { <br /><br /><b>Associate a publication with this $args{type}</b>: };
355 print qq { <center> };
356 $self->get_form()->as_table();
357 print qq { </center> };
359 print qq {<br /> <br /><b> For publications not in Pubmed <a href="/publication/0/new">click here</a> <br /> };
361 if ($args{refering_page}) { print "<a href=\"$args{refering_page}\">[Go back]</a><br /><br />\n"; }
363 $self->get_page()->footer();
367 sub print_obsoleted {
373 foreach my $ref (@publications) {
375 my $pub_id= $pub->get_pub_id();
376 my $db_name= ($pub->get_dbxrefs())[0]->get_db_name();
377 my $uniquename= $pub->get_uniquename();
378 my ($accession, $title)= split ':', $uniquename;
379 #if ($db_name eq 'SGN_ref') { $accession= $pub_id;}
380 my $url="/publication/$pub_id/view";
381 $obsoleted_pubs .= qq |<a href= $url target=blank>$db_name:$accession</a> $uniquename | . $self->unobsolete_pub($type, $ref->[1])."<br />";
384 html_optional_show('obsoleted_pubs',
386 qq|<div class="minorbox">$obsoleted_pubs</div> |,
389 print $print_obsoleted;
390 #return $print_obsoleted;
396 my $type_dbxref_id= shift;
397 my $unobsolete_link = "";
399 if (($self->get_user()->get_user_type() eq 'submitter') || ($self->get_user()->get_user_type() eq 'curator') || ($self->get_user()->get_user_type() eq 'sequencer')) {
401 <a href="javascript:Tools.unobsoleteAnnot('$type', '$type_dbxref_id')">[unobsolete]</a>
403 <div id='unobsoleteAnnotationForm' style="display: none">
404 <div id='type_dbxref_id_hidden'>
406 value=$type_dbxref_id
407 id="$type_dbxref_id">
412 return $unobsolete_link;
418 my %args=$self->get_args();
419 my $refering_page=$args{refering_page};
420 my $type= $args{type}; #locus or allele or stock...?
421 my $type_id = $args{type_id}; #the database id of the refering object (locus..)
422 my $accession= sanitize_string($args{accession});
424 my $publication= $self->get_object();
425 $publication->set_accession($accession);
430 #need to check if the publication is already in the database and associated with the object (locus..)
431 my $existing_publication= CXGN::Chado::Publication->get_pub_by_accession($self->get_dbh(),$accession) ;
433 if (my $pub_id = $existing_publication->get_pub_id) {
434 my $publication=CXGN::Chado::Publication->new($self->get_dbh(), $pub_id);
435 if($publication->is_associated_publication($type, $type_id)) {
436 $self->get_page()->header();
437 print "<h3>Publication '$accession' is already associated with $args{type} $args{type_id} </h3>";
438 print qq { <a href="javascript:history.back(1)">back to publications</a> };
439 $self->get_page()->footer();
441 else { #the publication isn't associated with this object
442 if (!$type && !$type_id) {
443 $self->get_page()->client_redirect("/publication/$pub_id/view");
445 $self->get_page()->header();
446 $self->print_confirm_form();
449 } else { # the publication doesn't exist in our database
450 $self->get_page()->header();
451 $self->print_confirm_form();
458 sub print_confirm_form {
460 my %args= $self->get_args();
461 my $refering_page=$args{refering_page};
462 my $type= $args{type}; #locus or...?
463 my $type_id = $args{type_id}; #the database id of the refering object (locus..)
464 my $accession= sanitize_string($args{accession});
466 my $script_name= $self->get_script_name();
468 my $publication= $self->get_object();
469 $publication->set_accession($accession);
474 #first fetch the publication from pubmed:
476 my $pubmed= CXGN::Tools::Pubmed->new($publication);
477 my $pub_title=$publication->get_title();
479 #check if NCBI server is down (See CXGN::Tools::Pubmed for set_message($message)
480 if ($publication->get_message() ) { $self->get_page->message_page( $publication->get_message() ); }
481 #add pubmed verification step
483 print qq |<h3> $accession is not a valid pubmed ID. </h3> |;
484 print qq |<a href="$script_name?type=$type&type_id=$type_id&refering_page=$refering_page&action=new">Go back</a>|;
485 $self->get_page()->footer();
491 my $print_publication ="";
492 my @authors= $publication->get_authors();
493 foreach my $a (@authors) {
494 $print_publication .=$a .", ";
497 chop $print_publication;
498 chop $print_publication;
499 $print_publication .= ". (" . $publication->get_pyear() . ") " . $publication->get_title() . " " . $publication->get_series_name(). " (" . $publication->get_volume() . "):" . $publication->get_pages() . ".";
501 my $pyear= $publication->get_pyear(); #) $publication->get_title(). $publication->get_series_name() . $publication->get_volume() : $publication->get_pages() . |;
503 my $print_associations;
505 my $publication_exists= CXGN::Chado::Publication->get_pub_by_accession($self->get_dbh(), $accession);
506 $publication->set_pub_id($publication_exists->get_pub_id()) if $publication_exists;
508 if ($type eq 'locus') {
509 my $locus= CXGN::Phenome::Locus->new($self->get_dbh(), $type_id);
510 my $is_associated= $locus->associated_publication($accession);
511 if ($publication && !$is_associated) {
512 my @associated_with_loci = $publication->get_loci();
513 if (@associated_with_loci) {
514 $print_associations .= "<br> this publication is already associated with locus:<br> ";
515 foreach my $a(@associated_with_loci) {
516 my $a_locus_id= $a->get_locus_id;
517 my $a_locus_name=$a->get_locus_name;
518 $print_associations .= qq | <a href= "/phenome/locus_display.pl?locus_id=$a_locus_id">$a_locus_name<br></a> |;
523 print qq | <br/> <h3>The following publication will be stored in the database and associated with $args{type} $args{type_id}: </h3> $print_publication <br> <b> $print_associations </b>|;
529 $self->get_form()->add_hidden( field_name=>"accession", contents=>$accession );
530 $self->get_form()->add_hidden( field_name=>"type", contents=>$args{type} );
531 $self->get_form()->add_hidden( field_name=>"type_id", contents=>$args{type_id} );
532 $self->get_form()->add_hidden( field_name=>"refering_page", contents=>$args{refering_page} );
535 $self->get_form()->add_hidden( field_name=>"action", contents=>"store" );
537 page_title_html("Confirm store");
541 $self->get_form()->as_table();
543 if ($self->get_action()=~/store/i) {
544 $self->get_form()->from_request(%args);
549 print qq | <BR> <a href="javascript:history.back(1)">Go back without storing the publication</a> | ;
551 $self->get_page()->footer();
555 sub send_publication_email {
558 my %args= $self->get_args();
559 my $refering_page=$args{refering_page};
560 my $type= $args{type}; #locus or...?
561 my $type_id = $args{type_id}; #the database id of the refering object (locus..)
562 my $accession= sanitize_string($args{accession});
563 my $deleted_pubid = $args{pub_id};
566 my $action= $self->get_action();
568 my $username= $self->get_user()->get_first_name()." ".$self->get_user()->get_last_name();
569 my $sp_person_id=$self->get_user()->get_sp_person_id();
571 if ($type eq 'locus') {
572 $type_link = qq | solgenomics.net/locus/$type_id/view|;
574 elsif ($type eq 'allele') {
575 $type_link = qq | solgenomics.net/phenome/allele.pl?allele_id=$type_id|;
577 elsif ($type eq 'stock') {
578 $type_link = qq | solgenomics.net/stock/view/id/$type_id|;
581 my $user_link = qq | solgenomics.net/solpeople/personal-info.pl?sp_person_id=$sp_person_id|;
583 my $usermail=$self->get_user()->get_contact_email();
587 my $pubmed_link = qq | http://www.ncbi.nlm.nih.gov/pubmed/$accession |;
589 if ($action eq 'store') {
591 $subject="[New publication associated with $type: $type_id]";
592 $fdbk_body="$username ($user_link) has associated publication $pubmed_link \n with $type: $type_link";
594 elsif($action eq 'delete') {
596 my $deleted_pub = CXGN::Chado::Publication->new($self->get_dbh(), $deleted_pubid);
597 my $deleted_acc = $deleted_pub->get_accession();
598 my $deleted_pubmed = qq | http://www.ncbi.nlm.nih.gov/pubmed/$deleted_acc |;
599 $subject="[A publication-$type association removed from $type: $type_id]";
600 $fdbk_body="$username ($user_link) has removed publication $deleted_pubmed \n from $type: $type_link";
603 CXGN::Contact::send_email($subject,$fdbk_body, 'sgn-db-curation@sgn.cornell.edu');
610 return $self->{schema};
615 $self->{schema} = shift;
619 my ($self, $pub) = @_;
621 my $authors = $pub->search_related('pubauthors' , {}, { order_by => 'rank' } );
622 while (my $author = $authors->next) {
623 my $last_name = $author->surname();
624 my $first_names = $author->givennames();
626 my ($first_name, $name) = split (/,/, $first_names);
628 $string .="$last_name, $name. ";
629 } else { $string .= "$last_name, $first_name. "; }