use Time::Piece; # attempt to set hoa_date_acc and hoa_date_pub from various sources $c->add_dataset_trigger( 'eprint', EPrints::Const::EP_TRIGGER_BEFORE_COMMIT, sub { my( %args ) = @_; my( $repo, $eprint, $changed ) = @args{qw( repository dataobj changed )}; # trigger only applies to repos with hefce_oa plugin enabled return unless $eprint->dataset->has_field( 'hoa_compliant' ); my( $acc_date, $pub_date, $pub_online_date ); # default EPrints date field - only one of these will match if( $eprint->is_set( 'date' ) && $eprint->is_set( 'date_type' ) ) { if( $eprint->value( 'date_type' ) eq 'published' ) { $pub_date = $eprint->value( 'date' ); } elsif( $eprint->value( 'date_type' ) eq 'published_online' ) { $pub_online_date = $eprint->value( 'date' ); } elsif( $eprint->value( 'date_type' ) eq 'accepted' ) { $acc_date = $eprint->value( 'date' ); } } # datesdatesdates - v.1.0.5 with 'published_online' option if( $eprint->exists_and_set( 'dates' ) ) { my $dates = $eprint->value( 'dates' ); if( ref($dates) eq 'ARRAY' ) # check for expected structure { for(@$dates) { next unless ref($_) eq 'HASH'; next unless EPrints::Utils::is_set( $_->{date} ) && EPrints::Utils::is_set( defined $_->{date_type} ); if( $_->{date_type} eq 'published' ) { $pub_date = $_->{date}; } elsif( $_->{date_type} eq 'published_online' ) { $pub_online_date = $_->{date}; } elsif( $_->{date_type} eq 'accepted' ) { $acc_date = $_->{date}; } } } } # rioxx2 - will prefer 'published' to 'published_online' - REF_CC prefers it the other way round if( $eprint->exists_and_set( 'rioxx2_dateAccepted' ) ) { $acc_date = $eprint->value( 'rioxx2_dateAccepted' ); } if( $eprint->exists_and_set( 'rioxx2_publication_date' ) ) { my $rioxx_pub = $eprint->value( 'rioxx2_publication_date' ); if( $rioxx_pub =~ /^\d{4}-\d{2}-\d{2}$/ ) #check rioxx override is valid date format { $pub_date = $eprint->value( 'rioxx2_publication_date' ); } } # now set the values - date of acceptance my $acc_year = substr $acc_date, 0, 4 if defined $acc_date; #ensure year is post 1900 to prevent Time::Piece crash if( defined $acc_date && $acc_year >= 1900 ) { $eprint->set_value( 'hoa_date_acc', $acc_date ); } #prefer a published_online date if( defined $pub_online_date ) { my $pub_year = substr $pub_online_date, 0, 4; $eprint->set_value( 'hoa_date_pub', $pub_online_date ) if $pub_year >= 1900; } elsif( defined $pub_date ) #but use a published date if that's not available. { my $pub_year = substr $pub_date, 0, 4; $eprint->set_value( 'hoa_date_pub', $pub_date ) if $pub_year >= 1900; } }, priority => 100 ); # needs to be called before the compliance flag is set # attempt to set hoa_emb_len $c->add_dataset_trigger( 'eprint', EPrints::Const::EP_TRIGGER_BEFORE_COMMIT, sub { my( %args ) = @_; my( $repo, $eprint, $changed ) = @args{qw( repository dataobj changed )}; # trigger only applies to repos with hefce_oa plugin enabled return unless $eprint->dataset->has_field( 'hoa_compliant' ); my $doc = $repo->call( [qw( hefce_oa select_document )], $repo, $eprint ); my $hoa_pub = $eprint->value( 'hoa_date_pub' ); if( $doc && $hoa_pub && !$eprint->is_set( "hoa_date_foa" ) ) { if( $doc->exists_and_set( 'date_embargo' ) ) { my $pub_time; if( $repo->can_call( "hefce_oa", "handle_possibly_incomplete_date" ) ) { $pub_time = $repo->call( [ "hefce_oa", "handle_possibly_incomplete_date" ], $hoa_pub ); } if( !defined( $pub_time ) ) #above call can return undef - fallback to default { $pub_time = Time::Piece->strptime( $hoa_pub , "%Y-%m-%d" ); } my $emb_time; if( $repo->can_call( "hefce_oa", "handle_possibly_incomplete_date" ) ) { $emb_time = $repo->call( [ "hefce_oa", "handle_possibly_incomplete_date" ], $doc->value( 'date_embargo' ) ); } if( !defined( $emb_time ) ) #above call can return undef - fallback to default { my $emb_date = $doc->value( 'date_embargo' ); if( $emb_date =~ /^(\d{4})/ ) { $emb_time = Time::Piece->strptime( $emb_date, "%Y-%m-%d" ) if $1 >= 1900; } } if( $emb_time > $pub_time ) #embargo date must come after publication date { #get embargo length my $len = $emb_time-$pub_time; $eprint->set_value( 'hoa_emb_len', sprintf "%.0f", $len->months ); } } else { $eprint->set_value( 'hoa_emb_len', undef ); } } }, priority => 250 ); #adapted from RIOXX2 plugin $c->{hefce_oa}->{select_document} = sub { my( $repo, $eprint ) = @_; my @docs = $eprint->get_all_documents; # no docs? return unless scalar @docs; # @possible_docs meet 'content' selection criteria - by default accepted or published, but can now be # overridden in config. See triggers file. my $good_content = $repo->config( "hefce_oa", "document_content" ) || [ qw/ accepted published / ]; my @possible_docs = grep { my $doc = $_; $doc->is_set( "content" ) && grep { my $content = $doc->value( "content" ); /^$content$/; } @$good_content; } @docs; return unless scalar @possible_docs; # if there's only one possible doc, it's the best (by default) return $possible_docs[0] if scalar @possible_docs == 1; # prefer published over accepted when other tests are equal my %pref = ( published => 1, accepted => 2, ); # the final 'spaceship sort' below will prefer an undef value over a set one - which might # not be expected (I realise this will be a very niche case) foreach( @$good_content ){ next if defined $pref{$_}; $pref{$_} = 10; # less preferred than standard options } # this sort statement might be slow when dealing with lots of documents. # we've already pared the array down to only accepted/published versions. # If necessary, some of the methods for pre-calculation on http://www.sysarch.com/Perl/sort_paper.html # may be useful @possible_docs = sort { #pre-calculate embargo dates my( $ade, $bde ); $ade = $bde = localtime; #same date if both embargoes are undefined. if( $repo->can_call( "hefce_oa", "handle_possibly_incomplete_date" ) ){ $ade = $repo->call( [ "hefce_oa", "handle_possibly_incomplete_date" ], $a->value( 'date_embargo' ) ) if $a->is_set( 'date_embargo'); $bde = $repo->call( [ "hefce_oa", "handle_possibly_incomplete_date" ], $b->value( 'date_embargo' ) ) if $b->is_set( 'date_embargo'); } # public is best. NB Can't use $doc->is_public here, is it checks EPrint is in 'archive' too. ($b->is_set( "security" ) && $b->value( "security" ) eq "public" ) <=> ($a->is_set( "security" ) && $a->value( "security" ) eq "public" ) or # something not public, but with an embargo set is better than a permanently embargoed item # again, with $a and $b swapped as is_set returns 1 or 0. $b->is_set( "date_embargo" ) <=> $a->is_set( "date_embargo" ) or # The embargo date will both be set, or both be undef here. # If both are undef, $ade and $bde will be equal # What has the shortest embargo? $ade <=> $bde or $pref{$a->value( "content" )} <=> $pref{$b->value( "content" )} } @possible_docs; return $possible_docs[0]; }; $c->{hefce_oa}->{handle_possibly_incomplete_date} = sub { # returns a Time::Piece object or undef. # # $epdate is value from EPrints DataObj field. # setting $default_to_start_of_period = 1 will return the 1st of the month/year for incomplete dates rather than the end. my( $epdate, $default_to_start_of_period ) = @_; return undef if !defined $epdate; $default_to_start_of_period ||= 0; # complete date - return Time::Piece object if( $epdate =~ /^0*(\d{2}|\d{4})\-(\d{2})\-(\d{2})/ ) { if( length($1) == 2) { return Time::Piece->strptime( "$1-$2-$3", "%y-%m-%d" ); } elsif( length($1) == 4 && $1 >= 1900 ) { return Time::Piece->strptime( "$1-$2-$3", "%Y-%m-%d" ); } } if( $epdate =~ /^(\d{4})\-\d{2}$/ ) { if( $1 >= 1900 ) { my $tp = Time::Piece->strptime( $epdate, "%Y-%m" ); #defaults to start of month return $tp if $default_to_start_of_period; # looks like there's no way to $tp->set_day( $tp->month_last-day ). # I think this is the least-silly option.!? return Time::Piece->strptime( "$epdate-".$tp->month_last_day, "%Y-%m-%d" ); } } # only year supplied - default to start or end of year as flagged return Time::Piece->strptime( "$epdate-01-01", "%Y-%m-%d" ) if $epdate =~ /^\d{4}$/ && $default_to_start_of_period && $epdate >= 1900; return Time::Piece->strptime( "$epdate-12-31", "%Y-%m-%d" ) if $epdate =~ /^\d{4}$/ && $epdate >= 1900; return undef; }; $c->{hefce_oa}->{calculate_last_compliant_foa_date} = sub { my( $repo, $eprint ) = @_; my $len = $eprint->value( "hoa_emb_len" ) || 0; # $len will be tested to see whether it is a compliant number of months in ACC_EMBARGO if( $len > 0 ) { #need pub date to calculate embargo release date return undef unless $eprint->is_set( "hoa_date_pub" ); my $pub = $repo->call(["hefce_oa", "handle_possibly_incomplete_date"], $eprint->value( "hoa_date_pub" ), "Y-%m-%d" ); my $end = $pub->add_months( $len ); # embargo end $end = $end->add_months( 1 ); #1-month grace period return $end; } else # no embargo { return undef unless $eprint->is_set( "hoa_date_fcd" ); my $fcd = Time::Piece->strptime( $eprint->value( "hoa_date_fcd" ), "%Y-%m-%d" ); # oa with one month of deposit my $end = $fcd->add_months( 1 ); return $end; } #returns if no last foa date can be calculated };