X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2Fstemmaweb%2FController%2FRoot.pm;h=c77212269e40a148818483be1b5a78138e96476a;hb=8e26de0f2079f2b952536a2be1af1ba159eba5c5;hp=e62c924a3e74f25868187b282e77a7b9a3262e8e;hpb=ec2f89ffc68331cd280429698e318f9a07e940cb;p=scpubgit%2Fstemmaweb.git diff --git a/lib/stemmaweb/Controller/Root.pm b/lib/stemmaweb/Controller/Root.pm index e62c924..c772122 100644 --- a/lib/stemmaweb/Controller/Root.pm +++ b/lib/stemmaweb/Controller/Root.pm @@ -1,7 +1,7 @@ package stemmaweb::Controller::Root; use Moose; use namespace::autoclean; -use Text::Tradition::Analysis qw/ run_analysis /; +use JSON qw (); use TryCatch; use XML::LibXML; use XML::LibXML::XPathContext; @@ -144,7 +144,7 @@ sub newtradition :Local :Args(0) { $errmsg = "XML file parsing error: $err"; } if( $doc ) { - if( $doc->documentElement->nodeName eq 'GraphML' ) { + if( $doc->documentElement->nodeName eq 'graphml' ) { $type = 'CollateX'; } elsif( $doc->documentElement->nodeName ne 'TEI' ) { $errmsg = 'Unrecognized XML type ' . $doc->documentElement->nodeName; @@ -249,7 +249,7 @@ sub textinfo :Local :Args(1) { $tradition->name( $newname ); $changed = 1; } catch { - return _json_error( $c, 500, "Error setting name to $newname" ); + return _json_error( $c, 500, "Error setting name to $newname: $@" ); } } } @@ -261,7 +261,7 @@ sub textinfo :Local :Args(1) { $tradition->language( $langval ); $changed = 1; } catch { - return _json_error( $c, 500, "Error setting language to $langval" ); + return _json_error( $c, 500, "Error setting language to $langval: $@" ); } } @@ -314,17 +314,18 @@ sub textinfo :Local :Args(1) { my $textinfo = { textid => $textid, name => $tradition->name, - #language => $tradition->language, public => $tradition->public || 0, owner => $tradition->user ? $tradition->user->email : undef, witnesses => [ map { $_->sigil } $tradition->witnesses ], }; + ## TODO Make these into callbacks in the other controllers maybe? if( $tradition->can('language') ) { $textinfo->{'language'} = $tradition->language; } - my @stemmasvg = map { { name => $_->identifier, svg => $_->as_svg() } } - $tradition->stemmata; - map { $_ =~ s/\n/ /mg } @stemmasvg; + if( $tradition->can('stemweb_jobid') ) { + $textinfo->{'stemweb_jobid'} = $tradition->stemweb_jobid || 0; + } + my @stemmasvg = map { _stemma_info( $_ ) } $tradition->stemmata; $textinfo->{stemmata} = \@stemmasvg; $c->stash->{'result'} = $textinfo; $c->forward('View::JSON'); @@ -351,6 +352,22 @@ sub variantgraph :Local :Args(1) { $c->stash->{'result'} = $collation->as_svg; $c->forward('View::SVG'); } + +sub _stemma_info { + my( $stemma, $sid ) = @_; + my $ssvg = $stemma->as_svg(); + $ssvg =~ s/\n/ /mg; + my $sinfo = { + name => $stemma->identifier, + directed => _json_bool( !$stemma->is_undirected ), + svg => $ssvg }; + if( $sid ) { + $sinfo->{stemmaid} = $sid; + } + return $sinfo; +} + +## TODO Separate stemma manipulation functionality into its own controller. =head2 stemma @@ -379,11 +396,6 @@ sub stemma :Local :Args(2) { if( $c->req->method eq 'POST' ) { if( $ok eq 'full' ) { my $dot = $c->request->body_params->{'dot'}; - # Graph::Reader::Dot does not handle bare unicode. We get around this - # by wrapping all words in double quotes, as long as they aren't already - # wrapped, and as long as they aren't the initial 'digraph stemma'. - # Horrible HACK. - $dot =~ s/(?stemma_count > $stemmaid ) { $stemma = $tradition->stemma( $stemmaid ); } - my $stemma_xml = $stemma ? $stemma->as_svg() : ''; # What was requested, XML or JSON? my $return_view = 'SVG'; if( my $accept_header = $c->req->header('Accept') ) { @@ -431,11 +442,10 @@ sub stemma :Local :Args(2) { } } if( $return_view eq 'SVG' ) { - $c->stash->{'result'} = $stemma_xml; + $c->stash->{'result'} = $stemma->as_svg(); $c->forward('View::SVG'); } else { # JSON - $stemma_xml =~ s/\n/ /mg; - $c->stash->{'result'} = { 'stemmaid' => $stemmaid, 'stemmasvg' => $stemma_xml }; + $c->stash->{'result'} = { _stemma_info( $stemma, $stemmaid ) }; $c->forward('View::JSON'); } } @@ -466,28 +476,76 @@ sub stemmadot :Local :Args(2) { $c->forward('View::JSON'); } +=head2 stemmaroot + + POST /stemmaroot/$textid/$stemmaseq, { root: } + +Orients the given stemma so that the given node is the root (archetype). Returns the +information structure for the new stemma. + +=cut + +sub stemmaroot :Local :Args(2) { + my( $self, $c, $textid, $stemmaid ) = @_; + my $m = $c->model('Directory'); + my $tradition = $m->tradition( $textid ); + unless( $tradition ) { + return _json_error( $c, 404, "No tradition with ID $textid" ); + } + my $ok = _check_permission( $c, $tradition ); + if( $ok eq 'full' ) { + my $stemma = $tradition->stemma( $stemmaid ); + try { + $stemma->root_graph( $c->req->param('root') ); + $m->save( $tradition ); + } catch( Text::Tradition::Error $e ) { + return _json_error( $c, 400, $e->message ); + } catch { + return _json_error( $c, 500, "Error re-rooting stemma: $@" ); + } + $c->stash->{'result'} = _stemma_info( $stemma ); + $c->forward('View::JSON'); + } else { + return _json_error( $c, 403, + 'You do not have permission to update stemmata for this tradition' ); + } +} + =head2 download - GET /download/$textid + GET /download/$textid/$format -Returns the full XML definition of the tradition and its stemmata, if any. +Returns a file for download of the tradition in the requested format. =cut -sub download :Local :Args(1) { - my( $self, $c, $textid ) = @_; +sub download :Local :Args(2) { + my( $self, $c, $textid, $format ) = @_; my $tradition = $c->model('Directory')->tradition( $textid ); unless( $tradition ) { return _json_error( $c, 404, "No tradition with ID $textid" ); } my $ok = _check_permission( $c, $tradition ); return unless $ok; + + my $outmethod = "as_" . lc( $format ); + my $view = "View::$format"; + $c->stash->{'name'} = $tradition->name(); + $c->stash->{'download'} = 1; + my @outputargs; + if( $format eq 'SVG' ) { + # Send the list of colors through to the backend. + # TODO Think of some way not to hard-code this. + push( @outputargs, { 'show_relations' => 'all', + 'graphcolors' => [ "#5CCCCC", "#67E667", "#F9FE72", "#6B90D4", + "#FF7673", "#E467B3", "#AA67D5", "#8370D8", "#FFC173" ] } ); + } try { - $c->stash->{'result'} = $tradition->collation->as_graphml(); + $c->stash->{'result'} = $tradition->collation->$outmethod( @outputargs ); } catch( Text::Tradition::Error $e ) { return _json_error( $c, 500, $e->message ); } - $c->forward('View::GraphML'); + $c->forward( $view ); } #################### @@ -519,6 +577,10 @@ sub _json_error { return 0; } +sub _json_bool { + return $_[0] ? JSON::true : JSON::false; +} + =head2 default Standard 404 error page