Merge pull request #5230 from solgenomics/topic/open_pollinated
[sgn.git] / lib / SGN / Controller / Locus.pm
blobd6d07d21498011dad0f821215733bb82ea525cac
1 package SGN::Controller::Locus;
3 =head1 NAME
5 SGN::Controller::Locus - Catalyst controller for the locus page
6 (replacing the old cgi script)
8 =cut
10 use Moose;
11 use namespace::autoclean;
13 use URI::FromHash 'uri';
15 use CXGN::Phenome::Locus;
16 use CXGN::Phenome::Schema;
17 use CXGN::Tools::Organism;
18 use CXGN::Phenome::Locus::LinkageGroup;
20 BEGIN { extends 'Catalyst::Controller' }
21 with 'Catalyst::Component::ApplicationAttribute';
24 has 'schema' => (
25 is => 'rw',
26 isa => 'DBIx::Class::Schema',
27 lazy_build => 1,
32 sub locus_search : Path('/search/locus') Args(0) {
33 my $self = shift;
34 my $c = shift;
35 my ($organism_names_ref, $organism_ids_ref)=CXGN::Tools::Organism::get_existing_organisms( $c->dbc->dbh);
37 unshift @$organism_names_ref, '';
38 unshift @$organism_ids_ref, '';
39 my @organism_ref;
40 my $index;
41 for my $id ( @$organism_ids_ref ) {
42 push( @organism_ref, [$id, $organism_names_ref->[$index]] );
43 $index++;
45 my $lg_names_ref = CXGN::Phenome::Locus::LinkageGroup::get_all_lgs( $c->dbc->dbh );
46 $c->stash(
47 template => '/search/loci.mas',
48 organism_ref => \@organism_ref,
49 lg_names_ref => $lg_names_ref,
55 sub _build_schema {
56 shift->_app->dbic_schema( 'CXGN::Phenome::Schema' )
60 =head2 new_locus
62 Public path: /locus/0/new
64 Create a new locus.
66 Chained off of L</get_locus> below.
68 =cut
70 sub new_locus : Chained('get_locus') PathPart('new') Args(0) {
71 my ( $self, $c ) = @_;
72 $c->stash(
73 template => '/locus/index.mas',
75 locusref => {
76 action => "new",
77 locus_id => 0 ,
78 locus => $c->stash->{locus},
79 schema => $self->schema,
85 sub view_by_name : Path('/locus/view/') Args(0) {
87 my ($self, $c) = @_;
89 my $symbol = $c->req->param("symbol");
90 my $locusname = $c->req->param("locus");
91 my $species = $c->req->param("species");
93 my $locus_id = undef;
94 my $locus = undef;
95 if ($symbol && $species) {
96 $locus = $c->stash->{locus} = CXGN::Phenome::Locus->new_with_symbol_and_species($c->dbc->dbh, $symbol, $species);
99 if ($locusname) {
100 $locus = $c->stash->{locus} = CXGN::Phenome::Locus->new_with_locusname($c->dbc->dbh, $locusname);
103 if (defined($locus) && defined($locus->get_locus_id())) {
104 $locus_id = $locus->get_locus_id();
105 my $url = "/locus/$locus_id/view";
106 $c->res->redirect($url, 301);
108 else {
109 $c->stash->{template} = 'generic_message.mas';
110 $c->stash->{message} = "No locus was found for the identifier provided ($symbol $locusname $species).";
111 # forward to search page ?
118 =head2 view_locus
120 Public path: /locus/<locus_id>/view
122 View a locus detail page.
124 Chained off of L</get_locus> below.
126 =cut
128 sub view_locus : Chained('get_locus') PathPart('view') Args(0) {
129 my ( $self, $c, $action) = @_;
130 my $locus = $c->stash->{locus};
131 if( $locus ) {
132 $c->forward('get_locus_extended_info');
135 my $logged_user = $c->user;
136 my $person_id = $logged_user->get_object->get_sp_person_id if $logged_user;
137 my $curator = $logged_user->check_roles('curator') if $logged_user;
138 my $submitter = $logged_user->check_roles('submitter') if $logged_user;
139 my $sequencer = $logged_user->check_roles('sequencer') if $logged_user;
140 my $dbh = $c->dbc->dbh;
142 my $trait_db_name => $c->get_conf('trait_ontology_db_name');
143 ##################
145 ###Check if a locus page can be printed###
146 my $locus_id = $locus ? $locus->get_locus_id : undef ;
148 print STDERR "LOCUS_ID: $locus_id ACTION: $action\n\n";
150 # print message if locus_id is not valid
151 unless ( ( $locus_id =~ m /^\d+$/ ) || ($action eq 'new' && !$locus_id) ) {
152 $c->throw_404( "No locus exists for that identifier." );
154 unless ( $locus || !$locus_id && $action && $action eq 'new' ) {
155 $c->throw_404( "No locus exists for that identifier." );
158 # print message if the locus is obsolete
159 my $obsolete = $locus->get_obsolete();
160 if ( $obsolete eq 't' && !$curator ) {
161 $c->throw(is_client_error => 0,
162 title => 'Obsolete locus',
163 message => "Locus $locus_id is obsolete!",
164 developer_message => 'only curators can see obsolete loci',
165 notify => 0, #< does not send an error email
170 # print message if locus_id does not exist
171 if ( !$locus && $action ne 'new' && $action ne 'store' ) {
172 $c->throw_404('No locus exists for this identifier');
175 ####################
176 my $is_owner;
177 my $owner_ids = $c->stash->{owner_ids} || [] ;
178 if ( $locus && ($curator || $person_id && ( grep /^$person_id$/, @$owner_ids ) ) ) {
179 $is_owner = 1;
181 my $dbxrefs = $self->locus_dbxrefs_by_db( $c );
182 my $pubs = $self->_locus_pubs( $c);
183 my $image_ids = $locus->get_figure_ids;
184 my $cview_tmp_dir = $c->tempfiles_subdir('cview');
186 #########
187 my @locus_xrefs =
188 # 4. look up xrefs for all of them
189 map $c->feature_xrefs( $_, { exclude => 'locuspages' } ),
190 # 3. plus primary locus name
191 $locus->get_locus_name,
192 # 2. list of locus alias strings
193 map $_->get_locus_alias,
194 # 1. list of locus alias objects
195 $locus->get_locus_aliases( 'f', 'f' );
196 #########
197 my ($feature, $src_feature) = $locus->get_src_feature;
198 ################
199 $c->stash(
200 template => '/locus/index.mas',
201 locusref => {
202 action => $action,
203 locus_id => $locus_id ,
204 curator => $curator,
205 submitter => $submitter,
206 sequencer => $sequencer,
207 person_id => $person_id,
208 user => $logged_user,
209 locus => $locus,
210 dbh => $dbh,
211 is_owner => $is_owner,
212 owners => $owner_ids,
213 dbxrefs => $dbxrefs,
214 pubs => $pubs,
215 cview_tmp_dir => $cview_tmp_dir,
216 cview_basepath => $c->get_conf('basepath'),
217 image_ids => $image_ids,
218 xrefs => \@locus_xrefs,
219 trait_db_name => $trait_db_name,
220 feature => $feature,
221 src_feature => $src_feature,
223 locus_add_uri => $c->uri_for( '/ajax/locus/associate_locus' )->relative(),
224 cvterm_add_uri => $c->uri_for( '/ajax/locus/associate_ontology')->relative(),
225 assign_owner_uri => $c->uri_for( '/ajax/locus/assign_owner' )->relative(),
230 =head1 PRIVATE ACTIONS
232 =head2 get_locus
234 Chain root for fetching a locus object to operate on.
236 Path part: /locus/<locus_id>
238 =cut
240 sub get_locus : Chained('/') PathPart('locus') CaptureArgs(1) {
241 my ($self, $c, $locus_id) = @_;
243 my $identifier_type = $c->stash->{identifier_type}
244 || $locus_id =~ /[^-\d]/ ? 'locus' : 'locus_id';
246 if( $identifier_type eq 'locus_id' ) {
247 if ( $locus_id == 0 ) {
248 $c->stash->{locus} = CXGN::Phenome::Locus->new($c->dbc->dbh);
249 return 1;
250 } elsif ( $locus_id < 0 ) {
251 $c->throw_client_error( public_message => 'Locus ID must be a positive integer.' );
254 #remove version numbers from locus name locus123.1.2
255 while ( $locus_id =~ m/.*\.\d+/ ) {
256 $locus_id =~ s/(.*)(\.\d+)/$1/ ;
259 my $matching_loci = $self->schema->resultset('Locus')->search(
261 $identifier_type => $locus_id,
262 obsolete => 'f'
263 } );
265 if( $matching_loci->count > 1 ) {
266 $c->throw_client_error( public_message => 'Multiple matching loci' );
269 my ( $locus ) = $matching_loci->all
270 or $c->throw_404( "Locus not found" );
271 my $found_locus_id = $locus->locus_id;
273 $c->stash->{locus} = CXGN::Phenome::Locus->new($c->dbc->dbh, $found_locus_id);
276 return 1;
282 sub get_locus_owner_ids : Private {
283 my ( $self, $c ) = @_;
284 my $locus = $c->stash->{locus};
285 my @owner_ids = $locus ? $locus->get_owners : ();
286 $c->stash->{owner_ids} = \@owner_ids;
289 sub get_locus_owner_objects : Private {
290 my ( $self, $c ) = @_;
291 my $locus = $c->stash->{locus};
292 my $owner_objects = $locus ? $locus->get_owners(1) : ();
293 $c->stash->{owner_objects} = $owner_objects;
296 sub get_locus_extended_info : Private {
297 my ( $self, $c ) = @_;
298 $c->forward('get_locus_owner_ids');
303 #add the locus_dbxrefs to the stash.
304 sub get_locus_dbxrefs : Private {
305 my ( $self, $c ) = @_;
306 my $locus = $c->stash->{locus};
307 my $locus_dbxrefs = $locus->get_dbxrefs;
308 $c->stash->{locus_dbxrefs} = $locus_dbxrefs;
311 sub locus_dbxrefs_by_db : Private {
312 my ( $self, $c ) = @_;
313 my $locus = $c->stash->{locus};
314 my %locus_dbxrefs = $locus->get_all_dbxrefs;
315 $c->stash->{locus_dbxrefs_by_db} = \%locus_dbxrefs;
319 sub _locus_pubs : Private {
320 my ($self, $c ) = @_;
321 my $dbxrefs = $c->stash->{locus_dbxrefs_by_db};
323 my @sorted_pubs = ${$dbxrefs}{PMID} ? sort { $a->[0]->get_accession() <=> $b->[0]->get_accession() } @{ ${$dbxrefs}{PMID} } : () ;
324 my @sgn_ref = ${$dbxrefs}{SGN_ref} ? @{ ${$dbxrefs}{SGN_ref} } : () ;
326 my @cxgn_pubs;
327 my @pub_dbxrefs = ( @sorted_pubs, @sgn_ref );
328 foreach my $d ( @pub_dbxrefs) {
329 if ( $d->[1] eq '0') { #if the dbxref is not obsolete
330 my $pub = CXGN::Chado::Publication->new( $c->dbc->dbh, $d->[0]->get_publication()->get_pub_id() );
331 push @cxgn_pubs, $pub;
334 $c->stash->{pubs} = \@cxgn_pubs;
336 __PACKAGE__->meta->make_immutable;