How to control eprint workflow based on a user field
NOTE: This has been written based on my experience of an EPrints 3.3.10 install.
Contents
What I was trying to achieve
We have many 'collections'. Each EPrint belongs to one collection.
Users can only deposit items into specific collections.
How do I control the EPrint workflow to only show the collections that a user can deposit into?
How I did it
Configuration of metafields
- Create a namedset with the collections in it:
~/archives/ARCHIVEID/cfg/namedsets/collections
# A list of collections - remember to add the relevant phrases!
library
art_gallery
university_newspapers
lab_equipment
- Add the metafield to both the eprint and the user. This can be done in a few different ways, this is one:
Edit ~/archives/ARCHIVEID/cfg/cfg.d/eprint_fields.pl, adding:
{
name => 'collection',
type => 'namedset',
set_name => "collections",
},
Edit ~/archives/ARCHIVEID/cfg/cfg.d/user_fields.pl, adding:
{
name => 'collection',
type => 'namedset',
set_name => "collections",
multiple => 1, #Allows a user to have rights to more than one collection
},
Add to user workflow
Edit ~/archives/ARCHIVEID/cfg/workflows/user/default.xml. We only want admin staff to be able to assign collections, so the field is added to the 'usertype' stage:
<stage name="usertype">
<component><field ref="usertype"/></component>
<component><field ref="username"/></component>
<component><field ref="collection"/></component>
<component><field ref="roles"/></component>
</stage>
This allows one or more collections to be assigned to a user.
Add to EPrint workflow
To render only the collections that have been assigned to a user, we need to get the 'collection's from the owning user, join them into a comma-separated string and use that as the 'options' for the eprint collection field.
<component><field ref="collection" options="{join($item{userid}.as_item(){collection},',')}"/></component>
We could also have used $current_user - which would be OK if the $current_user will have rights to more collections than the owning user.
Update database and restart webserver
Update the database how you normally do it (web interface or commandline) and reload the server config. Test it works :o)
Adding a default
If a user has no collections assigned in their profile, what should happen? We could either:
- always set a default collection in user_fields_default.pl
- use eprint_fields_default.pl to set a default collection for the eprint.
$c->{set_eprint_defaults} = sub
{
my( $data, $repository ) = @_;
my $user = $repository->current_user();
if( defined $user && $user->is_set( "collection" ) )
{
my $collections = $user->get_value( "collection" );
if( scalar @$collections == 1 ){
$data->{collection} = @$collections[0];
#We may also want to set some default metadata on items in this collection?
#Do it here - as we know we've got one collection!
if( $data->{collection} eq 'university_newspapers' ){
$data->{type} = "newspaper";
...
}
}
}
}
If a user only has access to one collection, the value should be set automatically and the field not shown in the workflow.
<flow>
<epc:choose>
<epc:when test="$STAFF_ONLY = 'TRUE'">
<!-- Allow editors to choose any collection -->
<stage ref="collection"/>
</epc:when>
<epc:otherwise test="length( $item{userid}.as_item(){collection} ) gt 1">
<!-- If someone has access to more than one collection, offer their collections -->
<stage ref="collection"/>
</epc:otherwise>
</epc:choose>
...
</flow>
<stage name="collection">
<epc:if test="$STAFF_ONLY = 'TRUE'">
<component><field ref="collection" required="yes" /></component>
</epc:if>
<epc:if test="$STAFF_ONLY != 'TRUE'">
<component><field ref="collection" required="yes" options="{join($item{userid}.as_item(){collection},',')}"/></component>
</epc:if>
</stage>