How to display specific contributors

From EPrints Documentation
Revision as of 23:03, 20 May 2021 by Libjlrs (talk | contribs) (Method 3 - Custom EPScript function)
Jump to: navigation, search

Based on this question, asked on the Tech list: How can I add the field “Thesis Advisor” from Contributors to the Abstract Pages?

Note: The question on the tech list specified EPrints 3.4.2. The below is based on 3.3.16, but may be useful as a starting point.

Below are three approaches that may do what you need.

Method 1 - EPScript function

1) In EPScript, there is an undocumented function - filter_compound_list which accepts:

This can produce a text-string of one field from the compound field. If a thesis had two supervisors, the following example would produce:

Smith, John and Bond, James

  <epc:if test="contributors">
    <epc:print expr="filter_compound_list(contributors,'type','','name')" />

Method 2 - EPScript logic - foreach

This method is a bit more flexible, but you have to construct the values from the parts manually. It does allow you to reference the id sub-field if required. It also may leave empty wrapping elements in the output (e.g. the ul in the example below if there are contributors, but none are the required type.

  <epc:if test="contributors">
    <epc:foreach expr="contributors" iterator="contr">
      <epc:if test="$contr{type}=''">
          <epc:print expr="$contr{name}{given}" /> <epc:print expr="$contr{name}{family}" />
          <epc:if test="$contr{id}">(<epc:print expr="$contr{id}"/>)</epc:if>

Method 3 - Custom EPScript function

This is the most complex, but also offers the most flexibility - if you're able to understand the EPrints::Script::Compiled module and write your own functions.

There are two parts - adding custom methods to EPScript, and calling them from the citation file.

### This should be added to a file e.g. EPRINTS_ROOT/archives/ARCHIVEID/cfg/cfg.d/

# Open block

# Write into EPrints::Script::Compiled
package EPrints::Script::Compiled;

use strict;

# Example usage in citation file:
#  <epc:if test="$item.render_contributors_filtered('',1)">
#    <h2><epc:phrase ref="contributor_type_typename_"/></h2>
#    <epc:print expr="$item.render_contributors_filtered('')"/>
#  </epc:if>
# The first call includes the 'test' parameter, which can be used to determine whether surrounding
# elements need to be displayed - in the above example the <h2>.
sub run_render_contributors_filtered
        my( $self, $state, $eprint, $contributor_type, $test ) = @_;

        if( !defined $eprint->[0] || ref($eprint->[0]) ne "EPrints::DataObj::EPrint" )
                $self->runtime_error( "Can only call render_contributors_filtered() on eprint objects not ".
                        ref($eprint->[0]) );

        if( !defined $contributor_type )
                $self->runtime_error( "You need to specify a contributor type you want to render." );

        my @filtered_contributors = grep{ defined $_->{type} && $_->{type} eq $contributor_type->[0] } @{ $eprint->[0]->value( "contributors" ) };

        if( $test )
                return [ 0, "BOOLEAN" ] if( scalar @filtered_contributors < 1 );
                return [ 1, "BOOLEAN" ];

        # NB this is based on EPrints::Extras::render_related_url
        # It is over-complicated for this use-case, as we could just use
        # $state->{session}->render_name( $row->{name} )
        # but if other compound fields are being used with similar code
        # being able to get to the 'render_value' for the sub fields is useful.

        my $field = $eprint->[0]->dataset->field( "contributors" );
        my $f = $field->get_property( "fields_cache" );
        my $fmap = {};
        foreach my $field_conf ( @{$f} )
                my $fieldname = $field_conf->{name};
                my $field = $field->{dataset}->get_field( $fieldname );
                $fmap->{$field_conf->{sub_name}} = $field;

        my $ul = $state->{session}->make_element( "ul" );

        foreach my $row ( @filtered_contributors  )
                my $li = $state->{session}->make_element( "li" );
                $li->appendChild( $fmap->{name}->render_single_value( $state->{session}, $row->{name} ) );
                if( defined $row->{id} )
                        $li->appendChild( $state->{session}->make_text( " (" ) );
                        $li->appendChild( $state->{session}->make_text( $row->{id} ) );
                        $li->appendChild( $state->{session}->make_text( ")" ) );
                $ul->appendChild( $li );
        return [ $ul, "XHTML" ];

} #End block

The above example is also available at: