diff --git a/cfg/cfg.d/z_orcid_support.pl b/cfg/cfg.d/z_orcid_support.pl index 47c5381..e596226 100644 --- a/cfg/cfg.d/z_orcid_support.pl +++ b/cfg/cfg.d/z_orcid_support.pl @@ -1,6 +1,6 @@ =pod -=head1 Orcid Support +=head1 ORCID Support ORCID Support Plugin @@ -123,22 +123,208 @@ =head2 Changes #Rendering ORCIDs { +###################################################################### +# +# EPrints::Script::Compiled +# +###################################################################### +# +# +###################################################################### + +=pod + +=head1 NAME + +B - Namespace for EPrints::Script functions. + +=cut + +=head1 DESCRIPTION + +Additional function being added +to L +at the archive level via C +for ORCID support. + +=cut + package EPrints::Script::Compiled; -use strict; +use strict; +use feature qw(fc); # Available in Perl 5.16 or higher. + # Folds case for UTF-8 / Unicode friendly case insensitive comparisons. + # https://perldoc.perl.org/perlfunc#fc -sub run_people_with_orcids -{ - my( $self, $state, $value ) = @_; +use Scalar::Util qw(blessed); + +=head1 SUBROUTINES + +=over + +=item run_people_with_orcids(creators); + +Synopsis: + + # Use in a citation: + + + # Alternatively: + + +Takes a list of people (creators, editors, etc), +decides whether to display an ORCID, +depending on the context, +and the existence of a valid ORCID for that person, +and if so handles the rendering of names and ORCID numbers and badges. + +Returns an anonymous array reference containing +at index 0 an XHTML document fragment (specifically +an L object), +and at index 1 the string 'XHTML' +- presumably to identify the nature of what is at index 0. + +This subroutine requires additional files: + +=over + +=item cfg/citations/eprint/orcid_for_coversheet.xml + +This file is how the ORCID link should be rendered in coversheet tag context. + +=item cfg/citations/eprint/orcid_for_csv.xml + +This file is how the ORCID link should be rendered in csv file context. +This only ensures a correct ORCID link. +Additional processing of the citation may still be required +to strip excess white space from the citation overall before use in a csv file. + +=item cfg/citations/eprint/orcid_for_email.xml + +This file is how the ORCID link should be rendered in email context. + +=item cfg/citations/eprint/orcid_for_web.xml + +This file is how the ORCID link should be rendered in web page context. + +=back + +Strings passed from this subroutine... + + # Simplified example - current code isn't exactly like this: + my $citation_params = { + string => 'The text that makes up our string', + }; + + my $xhtml = $item->render_citation($citation_name, %{$citation_params}); + +...should be accessed in the citation as... + + # Within a html/xml/xhtml tag's attribute: + # For example only. + # No such xhtml tag as 'tag'. + + # Or standalone: + + +The C function +may be needed to avoid +the error: +C<[No type for value 'The text that makes up our string' from '$string']>. + +For more info on EPScript Functions, see: +L + +Should you edit these citation files, +and have the commandline tool C, +then it is recommended you check the files +are valid xml after editing, +by running from the commandline: - my $session = $state->{session}; - my $r = $state->{session}->make_doc_fragment; + # Individually: + xmllint orcid_for_coversheet.xml + + xmllint orcid_for_csv.xml + + xmllint orcid_for_email.xml + + xmllint orcid_for_web.xml + + # All at once: + + xmllint orcid_for*.xml + +Those examples assume +you are already in the correct directory, +typically C<< /opt/eprints3/archives/archive_name/cfg/citations/eprint >> +where C is the name of your repository folder. + +If C concludes your file has no problems, +it will output the file contents. + +Web page context is assumed by default, +unless a C, +C or C +method call is made with the +C<< for_use_in => $value >> argument / option / parameter given, +where C<$value> can be (case insensitive) +C, C, C or C, as such: + + # On an item that can render a citation ($eprint, $user, etc): + $eprint->render_citation($citation_style, for_use_in => 'email'); + +This subroutine uses the fc feature, available in Perl version 5.16 and above, +and may need to be altered to run on lower Perl versions. + +=back + +=cut + + +sub run_people_with_orcids +{ + my( $self, $state, $value ) = @_; + + my $repository = $state->{session}; + my $item = $state->{item}; + my $for_use_in = $state->{for_use_in}? $state->{for_use_in}: + q{}; + my $r = $repository->make_doc_fragment; + + + # Regular Expressions: + my $captures_valid_orcid = qr! + ^ # Start of string + (?:orcid.org/)? # Optional non-capturing orcid.org/ + (? # Start 'orcid' capturing group... + \d{4}\- # Four digits and a dash + \d{4}\- # Four digits and a dash + \d{4}\- # Four digits and a dash + \d{3} # Three digits + (?:\d|X) # another digit or the letter X + ) # ...end capturing group. + $ # End of String. + !x; # x flag - allow white space and comments as above. + my $matches_export_related = qr! + ( # Start logical group... + exportview # Matches exportview + | # ...or... + export_ # Matches export_ + | # ...or... + cgi/export/ # Matches cgi/export/ + ) # ...End logical group. + !x; # x flag - allow white space and comments as above. + my $matches_yes = qr/^(y|yes)$/i; # case insensitive y or yes and an exact match - no partial matches like yesterday. + # Originally used to assess a yaml toggle to determine $email_display_setting value. + + # Processing: + my $contributors = $value->[0]; my $field = $value->[1]; my $f = $field->get_property( "fields_cache" ); my $browse_links = {}; - my $views = $session->config( "browse_views" ); + my $views = $repository->config( "browse_views" ); foreach my $sub_field ( @{$f} ) { @@ -157,7 +343,7 @@ sub run_people_with_orcids foreach my $i ( 0..$#$contributors ) { my $contributor = @$contributors[$i]; - my $url = $session->config( "rel_path" ); + my $url = $repository->config( "rel_path" ); my $contributors = $value->[0]; @@ -167,22 +353,22 @@ sub run_people_with_orcids if( $i == $#$contributors ) { # last item - $r->appendChild( $session->make_text( " and " ) ); + $r->appendChild( $repository->make_text( " and " ) ); } else { - $r->appendChild( $session->make_text( ", " ) ); + $r->appendChild( $repository->make_text( ", " ) ); } } - my $person_span = $session->make_element( "span", "class" => "person" ); + my $person_span = $repository->make_element( "span", "class" => "person" ); # only looking for browse_link in the name sub field for now... if( defined( $browse_links->{name} ) ) { my $linkview = $browse_links->{name}->{view}; my $sub_field = $browse_links->{name}->{field}; - my $link_id = $sub_field->get_id_from_value( $session, $contributor->{name} ); + my $link_id = $sub_field->get_id_from_value( $repository, $contributor->{name} ); if( ( defined $linkview->{fields} && $linkview->{fields} =~ m/,/ ) || @@ -200,42 +386,143 @@ sub run_people_with_orcids EPrints::Utils::escape_filename( $link_id ). ".html"; } - my $a = $session->render_link( $url ); - $a->appendChild( $session->render_name( $contributor->{name} ) ); + my $a = $repository->render_link( $url ); + $a->appendChild( $repository->render_name( $contributor->{name} ) ); $person_span->appendChild( $a ); } else { - $person_span->appendChild( $session->render_name( $contributor->{name} ) ); + $person_span->appendChild( $repository->render_name( $contributor->{name} ) ); } - - my $orcid = $contributor->{orcid}; - my $uri = ""; - $uri = $session->get_request->uri if defined $session->get_request; - if( $uri !~ m/exportview/ && $uri !~ m!/export_! && $uri !~ m!/cgi/export/! && defined $orcid && $orcid =~ m/^(?:orcid.org\/)?(\d{4}\-\d{4}\-\d{4}\-\d{3}(?:\d|X))$/ ) - { - my $orcid_link = $session->make_element( "a", - "class" => "orcid", - "href" => "https://orcid.org/$1", - "target" => "_blank", - ); - $orcid_link->appendChild( $session->make_element( "img", "src" => "/images/orcid_id.svg", "class" => "orcid-icon", "alt" => "ORCID logo" ) ); - my $orcid_span = $session->make_element( "span", "class" => "orcid-tooltip" ); + # SHOWING ORCID: + + # Initial Values: + my $default_display_setting = 1; # 1 to Show ORCIDs by default + # i.e. if not "for use in" any special context + # via (for_use_in => 'special context'). + # + # Set to 0 to prevent showing ORCIDs by default + # in all contexts except special contexts + # that defer to their own display setting values. + # Final decision to show depends on value of $show_orcid variable. + + my $email_display_setting = 1; # Set to 0 to exclude ORCIDs from email flagged contexts. + my $coversheet_display_setting = 1; # Set to 0 to exclude ORCIDs from coversheet flagged contexts. + my $csv_display_setting = 1; # Set to 0 to exclude ORCIDs from csv flagged contexts. + + my $valid_orcid = defined $contributor->{orcid} + && ($contributor->{orcid} =~ $captures_valid_orcid)? $+{orcid}: + undef; - $orcid_span->appendChild( $session->make_text( "ORCID: " ) ); - $orcid_span->appendChild( $session->make_text( "https://orcid.org/$1" ) ); - $orcid_link->appendChild( $orcid_span ); + my $uri = defined $repository->get_request? $repository->get_request->uri: + q{}; - $person_span->appendChild( $session->make_text( " " ) ); - $person_span->appendChild( $orcid_link ); + my $uri_not_export_related = $uri !~ $matches_export_related; - $person_span->setAttribute( "class", "person orcid-person" ); + my $display_setting = (fc $for_use_in) eq (fc 'email')? $email_display_setting: + (fc $for_use_in) eq (fc 'coversheet')? $coversheet_display_setting: + (fc $for_use_in) eq (fc 'csv')? $csv_display_setting: + $default_display_setting; # Fallback. + + my $show_orcid = $uri_not_export_related + && $valid_orcid + && $display_setting; + + # Processing: + if ($show_orcid) + { + # Initial Values: + my @static_folder = ( + path => "static", + scheme => "https", + host => 1, + ); + + my $static_folder = $repository->get_url(@static_folder)->abs($repository->config("base_url")); + my $citation_name = (fc $for_use_in) eq (fc 'email')? 'orcid_for_email': + (fc $for_use_in) eq (fc 'coversheet')? 'orcid_for_coversheet': + (fc $for_use_in) eq (fc 'csv')? 'orcid_for_csv': + 'orcid_for_web'; # default/fallback + my $provided_citation_params = $state; + + my $our_overriding_citation_params = { + + # Essentials required: + item => $item, + session => $repository, + repository => $repository, + in => 'EPrints::Script::Compiled::run_people_with_orcids', + + # Values for use in citations: + valid_orcid => $valid_orcid, # Access in citation as {$valid_orcid.as_string()} + static_folder => $static_folder, # Access in citation as {$static_folder.as_string()} + + }; + + my $citation_params = { + %{$provided_citation_params}, + %{$our_overriding_citation_params}, + }; + + # Processing: + my $orcid_link = $item->render_citation($citation_name, %{$citation_params}); + my $valid_orcid_link = $orcid_link + && Scalar::Util::blessed($orcid_link) + && $orcid_link->isa('XML::LibXML::DocumentFragment') + && $orcid_link->can('hasChildNodes') + && $orcid_link->hasChildNodes; + + # Output: + if ($valid_orcid_link) { + $person_span->appendChild( $repository->make_text( " " ) ); + $person_span->appendChild( $orcid_link ); + + $person_span->setAttribute( "class", "person orcid-person" ); + }; } + + # Output per contributor: $r->appendChild( $person_span ); } + + # Final output: return [ $r, "XHTML" ]; } } + +=head1 COPYRIGHT + +=for COPYRIGHT BEGIN + +Copyright 2024 University of Southampton. +EPrints 3.4 is supplied by EPrints Services. + +http://www.eprints.org/eprints-3.4/ + +=for COPYRIGHT END + +=head1 LICENSE + +=for LICENSE BEGIN + +This file is part of EPrints 3.4 L. + +EPrints 3.4 and this file are released under the terms of the +GNU Lesser General Public License version 3 as published by +the Free Software Foundation unless otherwise stated. + +EPrints 3.4 is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with EPrints 3.4. +If not, see L. + +=for LICENSE END + +=cut diff --git a/cfg/citations/eprint/orcid_for_coversheet.xml b/cfg/citations/eprint/orcid_for_coversheet.xml new file mode 100644 index 0000000..0bc4e20 --- /dev/null +++ b/cfg/citations/eprint/orcid_for_coversheet.xml @@ -0,0 +1,32 @@ + + + + This is an xml snippet used by EPrints::Script::Compiled::run_people_with_orcids + which is a subroutine in the EPrints::Script::Compiled package namespace, + added to the namespace at the local archive level via inclusion + in the file z_orcid_support.pl in the cfg/cfg.d folder + - i.e. cfg/cfg.d/z_orcid_support.pl + + The xml snippet below is used to dictate how an ORCID link is rendered. + It governs the presentation of the link to orcid.org via a badge, + that is rendered next to a person's name. + It does not govern the presentation of a person's name. + + This citation is only used by method calls to + render_citation, render_citation_link or render_citation_link_staff, + that include a... + + for_use_in => 'coversheet', + + ...argument / option / parameter. + For example: + + $eprint->render_citation($citation_style, for_use_in => 'coversheet'); + + When using strings passed as citation arguments in the citation below, + it is better to use {$string.as_string()} instead of simply {$string}, + in order to avoid the error: + [No type for value 'Some stuff inside string' from '$string'] + + ORCID: https://orcid.org/ + diff --git a/cfg/citations/eprint/orcid_for_csv.xml b/cfg/citations/eprint/orcid_for_csv.xml new file mode 100644 index 0000000..4670832 --- /dev/null +++ b/cfg/citations/eprint/orcid_for_csv.xml @@ -0,0 +1,32 @@ + + + + This is an xml snippet used by EPrints::Script::Compiled::run_people_with_orcids + which is a subroutine in the EPrints::Script::Compiled package namespace, + added to the namespace at the local archive level via inclusion + in the file z_orcid_support.pl in the cfg/cfg.d folder + - i.e. cfg/cfg.d/z_orcid_support.pl + + The xml snippet below is used to dictate how an ORCID link is rendered. + It governs the presentation of the link to orcid.org via a badge, + that is rendered next to a person's name. + It does not govern the presentation of a person's name. + + This citation is only used by method calls to + render_citation, render_citation_link or render_citation_link_staff, + that include a... + + for_use_in => 'csv', + + ...argument / option / parameter. + For example: + + $eprint->render_citation($citation_style, for_use_in => 'csv'); + + When using strings passed as citation arguments in the citation below, + it is better to use {$string.as_string()} instead of simply {$string}, + in order to avoid the error: + [No type for value 'Some stuff inside string' from '$string'] + + ORCID: https://orcid.org/ + diff --git a/cfg/citations/eprint/orcid_for_email.xml b/cfg/citations/eprint/orcid_for_email.xml new file mode 100644 index 0000000..b91f25f --- /dev/null +++ b/cfg/citations/eprint/orcid_for_email.xml @@ -0,0 +1,34 @@ + + + + This is an xml snippet used by EPrints::Script::Compiled::run_people_with_orcids + which is a subroutine in the EPrints::Script::Compiled package namespace, + added to the namespace at the local archive level via inclusion + in the file z_orcid_support.pl in the cfg/cfg.d folder + - i.e. cfg/cfg.d/z_orcid_support.pl + + The xml snippet below is used to dictate how an ORCID link is rendered. + It governs the presentation of the link to orcid.org via a badge, + that is rendered next to a person's name. + It does not govern the presentation of a person's name. + + This citation is only used by method calls to + render_citation, render_citation_link or render_citation_link_staff, + that include a... + + for_use_in => 'email', + + ...argument / option / parameter. + For example: + + $eprint->render_citation($citation_style, for_use_in => 'email'); + + When using strings passed as citation arguments in the citation below, + it is better to use {$string.as_string()} instead of simply {$string}, + in order to avoid the error: + [No type for value 'Some stuff inside string' from '$string'] + + + ORCID: https://orcid.org/{$valid_orcid.as_string()} + + diff --git a/cfg/citations/eprint/orcid_for_web.xml b/cfg/citations/eprint/orcid_for_web.xml new file mode 100644 index 0000000..b784e42 --- /dev/null +++ b/cfg/citations/eprint/orcid_for_web.xml @@ -0,0 +1,43 @@ + + + + This is an xml snippet used by EPrints::Script::Compiled::run_people_with_orcids + which is a subroutine in the EPrints::Script::Compiled package namespace, + added to the namespace at the local archive level via inclusion + in the file z_orcid_support.pl in the cfg/cfg.d folder + - i.e. cfg/cfg.d/z_orcid_support.pl + + The xml snippet below is used to dictate how an ORCID link is rendered. + It governs the presentation of the link to orcid.org via a badge, + that is rendered next to a person's name. + It does not govern the presentation of a person's name. + + It is assumed this citation will be used in web page renderings. + + For example: + + $eprint->render_citation($citation_style); # Will use orcid_for_web.xml by default. + + A flag can be passed to any method rendering a citation, + to indicate a different context. + + For example: + + $eprint->render_citation($citation_style, for_use_in => 'email'); # Will use orcid_for_email.xml by default. + + So far, email, coversheet and csv are the other recognised contexts, + for which you will wish to look at their respective files: + cfg/citations/eprint/orcid_for_email.xml + cfg/citations/eprint/orcid_for_coversheet.xml + cfg/citations/eprint/orcid_for_csv.xml + + When using strings passed as citation arguments within the citation below, + it is better to use {$string.as_string()} instead of simply {$string}, + in order to avoid the error: + [No type for value 'Some stuff inside string' from '$string'] + + + ORCID logo + ORCID: https://orcid.org/ + +