https://wiki.eprints.org/w/api.php?action=feedcontributions&user=Libjlrs&feedformat=atomEPrints Documentation - User contributions [en-gb]2024-03-28T11:15:18ZUser contributionsMediaWiki 1.31.8https://wiki.eprints.org/w/index.php?title=Adding_multilang_fields&diff=16181Adding multilang fields2024-02-08T14:00:54Z<p>Libjlrs: Add another note about return value</p>
<hr />
<div>[[Category:Howto]]<br />
<br />
EPrints' builtin fields are not multilingual, in the sense that there is only one version of each field -indirectly this means one language support. This page explains how to add multilingual versions of existing fields in EPrints and how they can be integrated with its subsystems.<br />
<br />
== Multilang fields and EPrints ==<br />
EPrints supports the '''multilang''' field type (see [[API:EPrints/MetaField/Multilang]] for more details) which allows a user to insert different content for different languages. There are a few limitations with '''multilang''' fields though:<br />
<br />
* When its value is printed it is shown in all languages containing content.<br />
* If a basic EPrints field's type is replaced to become '''multilang''' (like '''title''' and '''abstract'''), EPrints functionality breaks because it expects a single output.<br />
<br />
To address these limitations. this article explains how we can replace a basic field, the '''title''' field as an example, with a multilingual one.<br />
<br />
== Warning for already populated repositories ==<br />
Once you follow this article's procedure, '''existing titles and abstracts''' will not be copied into their multilingual counterparts and '''access to them via the API will be lost'''! The users of this plugin are requested to use EPrints API to copy the values from the old fields to the new ones. A script that copies the '''title''' value of each eprint to '''ml_title''' field's '''en''' and '''el''' languages can be found here:[https://github.com/mamalos/eprints/blob/master/help_scripts/set_ml_title.pl]. Please, use this script at your own risk and don't forget to change its content to reflect the languages of your repository. The same script can be used for copying the '''abstract''' field's values to '''ml_abstract''' '''en''' and '''el''' by replacing title with abstract in this script.<br />
<br />
== How to add a custom, multilingual field ==<br />
Replacing an EPrints basic field, like the '''title''' field, involves a few steps. First, a new field needs to be created that will be able to store information for different languages; this field will be of type '''multilang'''. Next, the basic field's type needs to be replaced with one that is able to use our newly created field as its storage place. This field type will use a function wrapper for storing and retrieving information from the '''multilang''' field, hence the '''title''' field will become a calculated field.<br />
<br />
So, in order to add multilingual support for the '''title''' field, the following actions need to take place:<br />
<br />
* A ''new field type needs to be created'' that will help our '''title''' field to implement some of EPrints logic. Our field type is called '''virtualwithvalue'''.<br />
* A ''new '''multilang''' field needs to be created'' that will store our multilingual information. We will call this field '''ml_title'''.<br />
* '''''ml_title''' field and '''title''' field's functionality need to be introduced to the EPrints system'' via a configuration file located in '''~eprints/archives/<reponame>/cfg/cfg.d/'''.<br />
* ''EPrints' database needs to be updated'' to include the new field. <br />
* ''The appropriate phrases need to be added'' for the '''ml_title''' field on each supported language.<br />
* ''The '''title''' field needs to be replaced'' with '''ml_title''' field in the workflow.<br />
* '''''ml_title''' field in the workflow will needs a custom lookup script''.<br />
* ''The '''title''' field needs to be replaced with the '''ml_title''' field in the simple and advanced search scripts''.<br />
* The ''repository needs to be reloaded''.<br />
* ''Static files need to be regenerated'' if our repository already contains data.<br />
The following sections explain each step in detail, and ''title''' and '''ml_title''' are used as our example fields. The code snippets are just for demonstration purposes - and proof of concept. If you want to see the final, working implementation, you should look at the source code of the [[MultiLang_Fields_Bazaar_Package]] plugin.<br />
<br />
== Adding a new field type (VirtualWithValue)==<br />
In order to create a multiple-language field we have to create an appropriate field type. EPrints' '''MetaField''' (see [[API:EPrints/MetaField|MetaField]] article for details) is a perfect candidate for this, and we need to extend it and override its '''get_value''' and '''set_value''' functions for the field to work properly with the rest of EPrints API, as well as its '''get_property_defaults''' function to sort out warnings for default values. The following code could be a rough implementation of such a field:<br />
<br />
<source lang="perl">package EPrints::MetaField::Virtualwithvalue;<br />
<br />
use strict;<br />
use warnings;<br />
<br />
use EPrints::MetaField;<br />
<br />
our @ISA = qw( EPrints::MetaField );<br />
<br />
use strict;<br />
<br />
sub get_property_defaults<br />
{<br />
my ( $self ) = @_;<br />
my %defaults = $self->SUPER::get_property_defaults;<br />
$defaults{get_value} = $EPrints::MetaField::UNDEF;<br />
$defaults{set_value} = $EPrints::MetaField::UNDEF;<br />
<br />
return %defaults;<br />
}<br />
<br />
sub get_value<br />
{<br />
my( $self, $object ) = @_;<br />
if ( defined $self->get_property("get_value") )<br />
{<br />
return $self->call_property( "get_value", $object);<br />
}<br />
return undef; # This is important. Using just a 'return;' or no return statement may break your repository e.g. when an EPrint revision file tried to be created.<br />
}<br />
<br />
sub set_value<br />
{<br />
my( $self, $object, $value ) = @_;<br />
if ( defined $self->get_property("set_value") )<br />
{<br />
return $self->call_property( "set_value", $object, $value);<br />
}<br />
return undef;<br />
}<br />
<br />
</source><br />
<br />
We could save this file in '''~eprints/lib/plugins/EPrints/MetaField/Virtualwithvalue.pm'''.<br />
<br />
== Introducing ml_title field in EPrints and replacing title field's type==<br />
To inform EPrints about our new field (that will be of type '''virtualwithvalue'''), we should create a configuration file, eg: '''~eprints/archives/<reponame>/cfg/cfg.d/zz_multilang_field.pl''' with content like the following:<br />
<br />
<source lang='perl'><br />
#define local fields<br />
my $local_fields = [<br />
{<br />
name => 'ml_title',<br />
type => 'multilang',<br />
multiple => 1,<br />
fields => [ { sub_name => "text", type => "longtext", input_rows => 3, make_single_value_orderkey => 'EPrints::Extras::english_title_orderkey' } ],<br />
input_add_boxes => 1,<br />
},<br />
<br />
{<br />
name => 'title',<br />
type => 'virtualwithvalue',<br />
virtual => 1,<br />
<br />
get_value => sub<br />
{<br />
my ($eprint) = @_;<br />
if ($eprint->is_set('ml_title'))<br />
{<br />
my $lang = $eprint->repository->get_langid;<br />
my $lang_set = 0;<br />
my $vals = $eprint->get_value('ml_title');<br />
my $title = '';<br />
if (!$lang)<br />
{<br />
$lang_set = 1;<br />
}<br />
else<br />
{<br />
# set the default lang's text as title<br />
foreach my $v1 (@{$vals})<br />
{<br />
if ($v1->{lang} eq $lang)<br />
{<br />
$title = $v1->{text};<br />
}<br />
}<br />
}<br />
# if the language is not set or I can't find an abstract in the <br />
# user's language, get the first object's text as abstract<br />
if ($lang_set or $title eq '')<br />
{<br />
$title = $vals->[0]->{text};<br />
}<br />
return $title;<br />
<br />
}<br />
return undef; # This is important. Using just a 'return;' or no return statement may break your repository e.g. when an EPrint revision file tried to be created.<br />
},<br />
<br />
set_value => sub<br />
{<br />
my ($eprint, $value) = @_;<br />
my $lang = 'en';<br />
#only use this on imports, NOT if the value is already set<br />
if ($eprint->is_set('ml_title'))<br />
{<br />
return;<br />
}<br />
if ($value)<br />
{<br />
$eprint->set_value('ml_title', [{lang=>$lang, text=>$value}]);<br />
}<br />
}<br />
},<br />
];<br />
<br />
#create lookup hash of local field names<br />
my $local_fieldnames = {};<br />
<br />
foreach my $f (@{$local_fields})<br />
{<br />
$local_fieldnames->{$f->{name}} = 1;<br />
}<br />
<br />
#merge in existing field configurations<br />
foreach my $f (@{$c->{fields}->{eprint}})<br />
{<br />
if (!$local_fieldnames->{$f->{name}})<br />
{<br />
push @{$local_fields}, $f;<br />
}<br />
}<br />
<br />
#overwrite original array of configured fields<br />
$c->{fields}->{eprint} = $local_fields;<br />
</source><br />
<br />
Where we can see that our new '''ml_title''' field is of type '''multilang''' and the '''title''' field's type has become '''virtualwithvalue'''. Moreover, the '''title''' field now implements the two aforementioned functions: '''get_value''' and '''set_value'''. Both these functions -whose names imply their functionality- are used by EPrints API, and their existence, as well as their return values, are critical for EPrints to work properly. The last statements of our example code show how a custom field can be added in the list of EPrints fields.<br />
<br />
What has happened in effect is that the '''title''' field has become a calculated field that gets or sets its value via its corresponding '''multilang''' field ('''ml_title'''). So, each new record now has a '''multilang''' field which it can access via the interface provided by the calculated field of type '''virtualwithvalue''', which is no other than EPrints' basic '''title''' field.<br />
<br />
The reason we didn't set the '''title''' field to be of type '''multilang''' in the first place is that many EPrints builtin functions expect only a single value from the '''title''' (and '''abstract''') field, and '''multilang''' fields don't support such functionality. Hence, doing so would cause EPrints to throw errors. By using and extending calculated fields (like '''MetaFields'''), we can calculate and produce always a single output for our '''title''' field (using the data stored in '''ml_title''' field) via its '''get_value''' function; its '''set_value''' function is used for populating our '''ml_title''' field's values. Our sample code prints output based on the user's language settings, but the programmer can do whatever they wish when overriding these functions, as long as their code return values that comply with EPrints' API.<br />
<br />
== Updating EPrints database to include the ml_title field ==<br />
EPrints database is updated when the user eprints executes (from his home directory):<br />
<source lang="bash"><br />
$ ./bin/epadmin update reponame<br />
</source><br />
<br />
== Adding the appropriate phrases ==<br />
EPrints phrases are not aware of our new field ('''ml_title'''), so we need to update them. In our example we update the phrases for the English and for the Greek languages ('''en''' and '''el''' respectively). We chose to add new files instead of changing the default ones so as to help EPrints upgrades. So, for the English language we can add the file '''~eprints/archives/reponame/cfg/lang/en/phrases/local.xml''' that contains the following information:<br />
<source lang="html4strict"><br />
<epp:phrase id="eprint_fieldname_ml_title">Title</epp:phrase><br />
<epp:phrase id="eprint_fieldname_ml_title_text">Text</epp:phrase><br />
<epp:phrase id="eprint_fieldname_ml_title_lang">Language</epp:phrase><br />
<epp:phrase id="eprint_fieldhelp_ml_title">The title of the item. The title should not end with a full stop, but may end with a question mark. There is no way to make italic text, please enter it normally. If you have a subtitle, it should be preceded with a colon [:]. Use capitals only for the first word and for proper nouns.<br />
<br/>Example: <span class="ep_form_example">A brief history of time</span><br />
<br/>Example: <span class="ep_form_example">Life: an unauthorised biography</span><br />
<br/>Example: <span class="ep_form_example">Mathematics for engineers and scientists. 5th edition</span><br />
<br/>Example: <span class="ep_form_example">Ecosystems of the world. Vol. 26. Estuaries of the world</span><br />
</epp:phrase><br />
</source><br />
<br />
Greek phrases can be added in file '''~eprints/archives/reponame/cfg/lang/el/phrases/local.xml''':<br />
<source lang="html4strict"><br />
<epp:phrase id="eprint_fieldname_ml_title">Τίτλος</epp:phrase><br />
<epp:phrase id="eprint_fieldname_ml_title_text">Κείμενο</epp:phrase><br />
<epp:phrase id="eprint_fieldname_ml_title_help">Το help τεξτ</epp:phrase><br />
<epp:phrase id="eprint_fieldname_ml_title_lang">Γλώσσα</epp:phrase><br />
<epp:phrase id="eprint_fieldhelp_ml_title">Ο τίτλος του τεκμηρίου. Ο τίτλος δεν πρέπει να τελειώνει με τελεία, αλλά μπορεί να τελειώνει με ερωτηματικό. Δεν υπάρχει τρόπος να γράψετε με πλάγια γράμματα, παρακαλώ χρησιμοποιήστε απλό κείμενο. Εάν έχετε έναν υπότιτλο, θα πρέπει να προηγείται η άνω και κάτω τελεία του υπότιτλου [:]. Χρησιμοποιήστε κεφαλαία γράμματα μόνο στην πρώτη λέξη και στα κύρια ονόματα.<br />
<br/>Παράδειγμα: <span class="ep_form_example">Μια σύντομη ιστορία</span><br />
<br/>Παράδειγμα: <span class="ep_form_example">Καβάφης: η βιογραφία</span><br />
<br/>Παράδειγμα: <span class="ep_form_example">Μαθηματικά για μηχανικούς και επιστήμονες. 5η έκδοση</span><br />
<br/>Παράδειγμα: <span class="ep_form_example">Οικοσυστήματα του πλανήτη. Τόμ. 26. Εκβολές του πλανήτη.</span><br />
</epp:phrase><br />
</source><br />
<br />
== Replacing the title field with ml_title field in the workflow ==<br />
In order to use our new '''ml_title''' field in the workflow, we need to replace the existing one ('''title'''). So, the '''title''' needs to be commented out and the new '''multilang''' should be added. This means that '''~eprints/archives/reponame/cfg/workflows/eprint/default.xml''' is edited as follows:<br />
<source lang="html4strict"><!-- <br />
<component><field ref="title" required="yes" input_lookup_url="{$config{rel_cgipath}}/users/lookup/title_duplicates" input_lookup_params="id={eprintid}&amp;dataset=eprint&amp;field=title" /></component><br />
<component><field ref="abstract"/></component><br />
--><br />
<br />
<component><field ref="ml_title" required="yes" input_lookup_url="{$config{rel_cgipath}}/users/lookup/ml_title_duplicates" input_lookup_params="id={eprintid}&amp;dataset=eprint&amp;field=ml_title"/></component><br />
<component><field ref="ml_abstract"/></component><br />
</source><br />
As can be seen, the default lookup script is replaced by the plugin's lookup script ('''ml_title_duplicates''') which supports our new '''ml_title''' field.<br />
<br />
== Adding a custom lookup script for ml_title autocompletion ==<br />
We copy the default lookup script to a new one ('''~eprints/cgi/users/lookup/ml_title_duplicates in our example'''):<br />
<source lang="bash"><br />
$ cp ~eprints/cgi/users/lookup/title_duplicates ~eprints/cgi/users/lookup/ml_title_duplicates<br />
</source><br />
and edit the SQL statement to contain '''ml_title''' instead of '''title''' (line 70 in EPrints 3.3.14):<br />
<source lang="php"><br />
my $sql = "SELECT ep.eprintid, ml_title_text FROM eprint AS ep JOIN eprint_ml_title_text AS ml ON ep.eprintid = ml.eprintid WHERE ";<br />
if ($dataset_name eq "eprint") {<br />
$sql .= " $Q_eprint_status=" . $db->quote_value( "archive" ) . " AND ";<br />
}<br />
$sql .= "ml.ml_title_text IS NOT NULL" .<br />
" AND ml.ml_title_text " .<br />
$db->sql_LIKE() .<br />
$db->quote_value( EPrints::Database::prep_like_value( $q ) . '%' );<br />
</source><br />
<br />
== Adding search support for the ml_title field ==<br />
EPrints' search functionality is only aware of the '''title''' field, so its search mechanisms -which directly search EPrints' database- has no knowledge about '''ml_title'''. To address this, we should allow our search scripts to be able to search into '''ml_title''' instead of '''title''', since '''title''' is now a calculated field and contains no information in EPrints database. To do so, we add two configuration files that add support for each search respectively. We have chosen not to change EPrints' default search configuration files, in order not to affect future EPrints' upgrades. So, for the simple search we add the file '''~eprints/archives/reponame/cfg/cfg.d/eprint_search_simple.pl''' with the content:<br />
<source lang="perl">$c->{search}->{simple} = <br />
{<br />
search_fields => [<br />
{<br />
id => "q",<br />
meta_fields => [<br />
"documents",<br />
"ml_title",<br />
"abstract",<br />
"creators_name",<br />
"date" <br />
]<br />
},<br />
],<br />
# preamble_phrase => "cgi/search:preamble",<br />
title_phrase => "cgi/search:simple_search",<br />
citation => "result",<br />
page_size => 20,<br />
order_methods => {<br />
"byyear" => "-date/creators_name/title",<br />
"byyearoldest" => "date/creators_name/title",<br />
"byname" => "creators_name/-date/title",<br />
"bytitle" => "title/creators_name/-date" <br />
},<br />
default_order => "byyear",<br />
show_zero_results => 1,<br />
};<br />
</source><br />
<br />
And for the advanced search we add the file: '''~eprints/archives/reponame/cfg/cfg.d/eprint_search_advanced_local.pl''' that reads:<br />
<source lang="perl"><br />
$c->{search}->{advanced} =<br />
{<br />
search_fields => [<br />
{ meta_fields => [ "documents" ] },<br />
{ meta_fields => [ "ml_title" ] },<br />
{ meta_fields => [ "creators_name" ] },<br />
{ meta_fields => [ "abstract" ] },<br />
{ meta_fields => [ "date" ] },<br />
{ meta_fields => [ "keywords" ] },<br />
{ meta_fields => [ "subjects" ] },<br />
{ meta_fields => [ "type" ] },<br />
{ meta_fields => [ "department" ] },<br />
{ meta_fields => [ "editors_name" ] },<br />
{ meta_fields => [ "ispublished" ] },<br />
{ meta_fields => [ "refereed" ] },<br />
{ meta_fields => [ "publication" ] },<br />
{ meta_fields => [ "documents.format" ] },<br />
],<br />
preamble_phrase => "cgi/advsearch:preamble",<br />
title_phrase => "cgi/advsearch:adv_search",<br />
citation => "result",<br />
page_size => 20,<br />
order_methods => {<br />
"byyear" => "-date/creators_name/title",<br />
"byyearoldest" => "date/creators_name/title",<br />
"byname" => "creators_name/-date/title",<br />
"bytitle" => "title/creators_name/-date" <br />
},<br />
default_order => "byyear",<br />
show_zero_results => 1,<br />
};<br />
</source><br />
<br />
== Reloading our repository ==<br />
In order for our changes to take effect, we should reload our repository by running:<br />
<source lang="bash"><br />
$ ./bin/epadmin reload reponame</source><br />
within eprints user's home directory as user eprints.<br />
<br />
== Regenerating static files and abstracts ==<br />
If our repository already contained records, we need to recreate static content such as static pages and abstracts. Hence, as eprints user we should run:<br />
<source lang="bash"><br />
$ ./bin/generate_abstracts reponame<br />
$ ./bin/generate_static reponame<br />
</source><br />
within eprints user's home directory.</div>Libjlrshttps://wiki.eprints.org/w/index.php?title=Adding_multilang_fields&diff=16180Adding multilang fields2024-02-08T14:00:01Z<p>Libjlrs: Add note about return value for 'get_value'</p>
<hr />
<div>[[Category:Howto]]<br />
<br />
EPrints' builtin fields are not multilingual, in the sense that there is only one version of each field -indirectly this means one language support. This page explains how to add multilingual versions of existing fields in EPrints and how they can be integrated with its subsystems.<br />
<br />
== Multilang fields and EPrints ==<br />
EPrints supports the '''multilang''' field type (see [[API:EPrints/MetaField/Multilang]] for more details) which allows a user to insert different content for different languages. There are a few limitations with '''multilang''' fields though:<br />
<br />
* When its value is printed it is shown in all languages containing content.<br />
* If a basic EPrints field's type is replaced to become '''multilang''' (like '''title''' and '''abstract'''), EPrints functionality breaks because it expects a single output.<br />
<br />
To address these limitations. this article explains how we can replace a basic field, the '''title''' field as an example, with a multilingual one.<br />
<br />
== Warning for already populated repositories ==<br />
Once you follow this article's procedure, '''existing titles and abstracts''' will not be copied into their multilingual counterparts and '''access to them via the API will be lost'''! The users of this plugin are requested to use EPrints API to copy the values from the old fields to the new ones. A script that copies the '''title''' value of each eprint to '''ml_title''' field's '''en''' and '''el''' languages can be found here:[https://github.com/mamalos/eprints/blob/master/help_scripts/set_ml_title.pl]. Please, use this script at your own risk and don't forget to change its content to reflect the languages of your repository. The same script can be used for copying the '''abstract''' field's values to '''ml_abstract''' '''en''' and '''el''' by replacing title with abstract in this script.<br />
<br />
== How to add a custom, multilingual field ==<br />
Replacing an EPrints basic field, like the '''title''' field, involves a few steps. First, a new field needs to be created that will be able to store information for different languages; this field will be of type '''multilang'''. Next, the basic field's type needs to be replaced with one that is able to use our newly created field as its storage place. This field type will use a function wrapper for storing and retrieving information from the '''multilang''' field, hence the '''title''' field will become a calculated field.<br />
<br />
So, in order to add multilingual support for the '''title''' field, the following actions need to take place:<br />
<br />
* A ''new field type needs to be created'' that will help our '''title''' field to implement some of EPrints logic. Our field type is called '''virtualwithvalue'''.<br />
* A ''new '''multilang''' field needs to be created'' that will store our multilingual information. We will call this field '''ml_title'''.<br />
* '''''ml_title''' field and '''title''' field's functionality need to be introduced to the EPrints system'' via a configuration file located in '''~eprints/archives/<reponame>/cfg/cfg.d/'''.<br />
* ''EPrints' database needs to be updated'' to include the new field. <br />
* ''The appropriate phrases need to be added'' for the '''ml_title''' field on each supported language.<br />
* ''The '''title''' field needs to be replaced'' with '''ml_title''' field in the workflow.<br />
* '''''ml_title''' field in the workflow will needs a custom lookup script''.<br />
* ''The '''title''' field needs to be replaced with the '''ml_title''' field in the simple and advanced search scripts''.<br />
* The ''repository needs to be reloaded''.<br />
* ''Static files need to be regenerated'' if our repository already contains data.<br />
The following sections explain each step in detail, and ''title''' and '''ml_title''' are used as our example fields. The code snippets are just for demonstration purposes - and proof of concept. If you want to see the final, working implementation, you should look at the source code of the [[MultiLang_Fields_Bazaar_Package]] plugin.<br />
<br />
== Adding a new field type (VirtualWithValue)==<br />
In order to create a multiple-language field we have to create an appropriate field type. EPrints' '''MetaField''' (see [[API:EPrints/MetaField|MetaField]] article for details) is a perfect candidate for this, and we need to extend it and override its '''get_value''' and '''set_value''' functions for the field to work properly with the rest of EPrints API, as well as its '''get_property_defaults''' function to sort out warnings for default values. The following code could be a rough implementation of such a field:<br />
<br />
<source lang="perl">package EPrints::MetaField::Virtualwithvalue;<br />
<br />
use strict;<br />
use warnings;<br />
<br />
use EPrints::MetaField;<br />
<br />
our @ISA = qw( EPrints::MetaField );<br />
<br />
use strict;<br />
<br />
sub get_property_defaults<br />
{<br />
my ( $self ) = @_;<br />
my %defaults = $self->SUPER::get_property_defaults;<br />
$defaults{get_value} = $EPrints::MetaField::UNDEF;<br />
$defaults{set_value} = $EPrints::MetaField::UNDEF;<br />
<br />
return %defaults;<br />
}<br />
<br />
sub get_value<br />
{<br />
my( $self, $object ) = @_;<br />
if ( defined $self->get_property("get_value") )<br />
{<br />
return $self->call_property( "get_value", $object);<br />
}<br />
return undef; # This is important. Using just a 'return;' or no return statement may break your repository e.g. when an EPrint revision file tried to be created.<br />
}<br />
<br />
sub set_value<br />
{<br />
my( $self, $object, $value ) = @_;<br />
if ( defined $self->get_property("set_value") )<br />
{<br />
return $self->call_property( "set_value", $object, $value);<br />
}<br />
return undef;<br />
}<br />
<br />
</source><br />
<br />
We could save this file in '''~eprints/lib/plugins/EPrints/MetaField/Virtualwithvalue.pm'''.<br />
<br />
== Introducing ml_title field in EPrints and replacing title field's type==<br />
To inform EPrints about our new field (that will be of type '''virtualwithvalue'''), we should create a configuration file, eg: '''~eprints/archives/<reponame>/cfg/cfg.d/zz_multilang_field.pl''' with content like the following:<br />
<br />
<source lang='perl'><br />
#define local fields<br />
my $local_fields = [<br />
{<br />
name => 'ml_title',<br />
type => 'multilang',<br />
multiple => 1,<br />
fields => [ { sub_name => "text", type => "longtext", input_rows => 3, make_single_value_orderkey => 'EPrints::Extras::english_title_orderkey' } ],<br />
input_add_boxes => 1,<br />
},<br />
<br />
{<br />
name => 'title',<br />
type => 'virtualwithvalue',<br />
virtual => 1,<br />
<br />
get_value => sub<br />
{<br />
my ($eprint) = @_;<br />
if ($eprint->is_set('ml_title'))<br />
{<br />
my $lang = $eprint->repository->get_langid;<br />
my $lang_set = 0;<br />
my $vals = $eprint->get_value('ml_title');<br />
my $title = '';<br />
if (!$lang)<br />
{<br />
$lang_set = 1;<br />
}<br />
else<br />
{<br />
# set the default lang's text as title<br />
foreach my $v1 (@{$vals})<br />
{<br />
if ($v1->{lang} eq $lang)<br />
{<br />
$title = $v1->{text};<br />
}<br />
}<br />
}<br />
# if the language is not set or I can't find an abstract in the <br />
# user's language, get the first object's text as abstract<br />
if ($lang_set or $title eq '')<br />
{<br />
$title = $vals->[0]->{text};<br />
}<br />
return $title;<br />
<br />
}<br />
return undef;<br />
},<br />
<br />
set_value => sub<br />
{<br />
my ($eprint, $value) = @_;<br />
my $lang = 'en';<br />
#only use this on imports, NOT if the value is already set<br />
if ($eprint->is_set('ml_title'))<br />
{<br />
return;<br />
}<br />
if ($value)<br />
{<br />
$eprint->set_value('ml_title', [{lang=>$lang, text=>$value}]);<br />
}<br />
}<br />
},<br />
];<br />
<br />
#create lookup hash of local field names<br />
my $local_fieldnames = {};<br />
<br />
foreach my $f (@{$local_fields})<br />
{<br />
$local_fieldnames->{$f->{name}} = 1;<br />
}<br />
<br />
#merge in existing field configurations<br />
foreach my $f (@{$c->{fields}->{eprint}})<br />
{<br />
if (!$local_fieldnames->{$f->{name}})<br />
{<br />
push @{$local_fields}, $f;<br />
}<br />
}<br />
<br />
#overwrite original array of configured fields<br />
$c->{fields}->{eprint} = $local_fields;<br />
</source><br />
<br />
Where we can see that our new '''ml_title''' field is of type '''multilang''' and the '''title''' field's type has become '''virtualwithvalue'''. Moreover, the '''title''' field now implements the two aforementioned functions: '''get_value''' and '''set_value'''. Both these functions -whose names imply their functionality- are used by EPrints API, and their existence, as well as their return values, are critical for EPrints to work properly. The last statements of our example code show how a custom field can be added in the list of EPrints fields.<br />
<br />
What has happened in effect is that the '''title''' field has become a calculated field that gets or sets its value via its corresponding '''multilang''' field ('''ml_title'''). So, each new record now has a '''multilang''' field which it can access via the interface provided by the calculated field of type '''virtualwithvalue''', which is no other than EPrints' basic '''title''' field.<br />
<br />
The reason we didn't set the '''title''' field to be of type '''multilang''' in the first place is that many EPrints builtin functions expect only a single value from the '''title''' (and '''abstract''') field, and '''multilang''' fields don't support such functionality. Hence, doing so would cause EPrints to throw errors. By using and extending calculated fields (like '''MetaFields'''), we can calculate and produce always a single output for our '''title''' field (using the data stored in '''ml_title''' field) via its '''get_value''' function; its '''set_value''' function is used for populating our '''ml_title''' field's values. Our sample code prints output based on the user's language settings, but the programmer can do whatever they wish when overriding these functions, as long as their code return values that comply with EPrints' API.<br />
<br />
== Updating EPrints database to include the ml_title field ==<br />
EPrints database is updated when the user eprints executes (from his home directory):<br />
<source lang="bash"><br />
$ ./bin/epadmin update reponame<br />
</source><br />
<br />
== Adding the appropriate phrases ==<br />
EPrints phrases are not aware of our new field ('''ml_title'''), so we need to update them. In our example we update the phrases for the English and for the Greek languages ('''en''' and '''el''' respectively). We chose to add new files instead of changing the default ones so as to help EPrints upgrades. So, for the English language we can add the file '''~eprints/archives/reponame/cfg/lang/en/phrases/local.xml''' that contains the following information:<br />
<source lang="html4strict"><br />
<epp:phrase id="eprint_fieldname_ml_title">Title</epp:phrase><br />
<epp:phrase id="eprint_fieldname_ml_title_text">Text</epp:phrase><br />
<epp:phrase id="eprint_fieldname_ml_title_lang">Language</epp:phrase><br />
<epp:phrase id="eprint_fieldhelp_ml_title">The title of the item. The title should not end with a full stop, but may end with a question mark. There is no way to make italic text, please enter it normally. If you have a subtitle, it should be preceded with a colon [:]. Use capitals only for the first word and for proper nouns.<br />
<br/>Example: <span class="ep_form_example">A brief history of time</span><br />
<br/>Example: <span class="ep_form_example">Life: an unauthorised biography</span><br />
<br/>Example: <span class="ep_form_example">Mathematics for engineers and scientists. 5th edition</span><br />
<br/>Example: <span class="ep_form_example">Ecosystems of the world. Vol. 26. Estuaries of the world</span><br />
</epp:phrase><br />
</source><br />
<br />
Greek phrases can be added in file '''~eprints/archives/reponame/cfg/lang/el/phrases/local.xml''':<br />
<source lang="html4strict"><br />
<epp:phrase id="eprint_fieldname_ml_title">Τίτλος</epp:phrase><br />
<epp:phrase id="eprint_fieldname_ml_title_text">Κείμενο</epp:phrase><br />
<epp:phrase id="eprint_fieldname_ml_title_help">Το help τεξτ</epp:phrase><br />
<epp:phrase id="eprint_fieldname_ml_title_lang">Γλώσσα</epp:phrase><br />
<epp:phrase id="eprint_fieldhelp_ml_title">Ο τίτλος του τεκμηρίου. Ο τίτλος δεν πρέπει να τελειώνει με τελεία, αλλά μπορεί να τελειώνει με ερωτηματικό. Δεν υπάρχει τρόπος να γράψετε με πλάγια γράμματα, παρακαλώ χρησιμοποιήστε απλό κείμενο. Εάν έχετε έναν υπότιτλο, θα πρέπει να προηγείται η άνω και κάτω τελεία του υπότιτλου [:]. Χρησιμοποιήστε κεφαλαία γράμματα μόνο στην πρώτη λέξη και στα κύρια ονόματα.<br />
<br/>Παράδειγμα: <span class="ep_form_example">Μια σύντομη ιστορία</span><br />
<br/>Παράδειγμα: <span class="ep_form_example">Καβάφης: η βιογραφία</span><br />
<br/>Παράδειγμα: <span class="ep_form_example">Μαθηματικά για μηχανικούς και επιστήμονες. 5η έκδοση</span><br />
<br/>Παράδειγμα: <span class="ep_form_example">Οικοσυστήματα του πλανήτη. Τόμ. 26. Εκβολές του πλανήτη.</span><br />
</epp:phrase><br />
</source><br />
<br />
== Replacing the title field with ml_title field in the workflow ==<br />
In order to use our new '''ml_title''' field in the workflow, we need to replace the existing one ('''title'''). So, the '''title''' needs to be commented out and the new '''multilang''' should be added. This means that '''~eprints/archives/reponame/cfg/workflows/eprint/default.xml''' is edited as follows:<br />
<source lang="html4strict"><!-- <br />
<component><field ref="title" required="yes" input_lookup_url="{$config{rel_cgipath}}/users/lookup/title_duplicates" input_lookup_params="id={eprintid}&amp;dataset=eprint&amp;field=title" /></component><br />
<component><field ref="abstract"/></component><br />
--><br />
<br />
<component><field ref="ml_title" required="yes" input_lookup_url="{$config{rel_cgipath}}/users/lookup/ml_title_duplicates" input_lookup_params="id={eprintid}&amp;dataset=eprint&amp;field=ml_title"/></component><br />
<component><field ref="ml_abstract"/></component><br />
</source><br />
As can be seen, the default lookup script is replaced by the plugin's lookup script ('''ml_title_duplicates''') which supports our new '''ml_title''' field.<br />
<br />
== Adding a custom lookup script for ml_title autocompletion ==<br />
We copy the default lookup script to a new one ('''~eprints/cgi/users/lookup/ml_title_duplicates in our example'''):<br />
<source lang="bash"><br />
$ cp ~eprints/cgi/users/lookup/title_duplicates ~eprints/cgi/users/lookup/ml_title_duplicates<br />
</source><br />
and edit the SQL statement to contain '''ml_title''' instead of '''title''' (line 70 in EPrints 3.3.14):<br />
<source lang="php"><br />
my $sql = "SELECT ep.eprintid, ml_title_text FROM eprint AS ep JOIN eprint_ml_title_text AS ml ON ep.eprintid = ml.eprintid WHERE ";<br />
if ($dataset_name eq "eprint") {<br />
$sql .= " $Q_eprint_status=" . $db->quote_value( "archive" ) . " AND ";<br />
}<br />
$sql .= "ml.ml_title_text IS NOT NULL" .<br />
" AND ml.ml_title_text " .<br />
$db->sql_LIKE() .<br />
$db->quote_value( EPrints::Database::prep_like_value( $q ) . '%' );<br />
</source><br />
<br />
== Adding search support for the ml_title field ==<br />
EPrints' search functionality is only aware of the '''title''' field, so its search mechanisms -which directly search EPrints' database- has no knowledge about '''ml_title'''. To address this, we should allow our search scripts to be able to search into '''ml_title''' instead of '''title''', since '''title''' is now a calculated field and contains no information in EPrints database. To do so, we add two configuration files that add support for each search respectively. We have chosen not to change EPrints' default search configuration files, in order not to affect future EPrints' upgrades. So, for the simple search we add the file '''~eprints/archives/reponame/cfg/cfg.d/eprint_search_simple.pl''' with the content:<br />
<source lang="perl">$c->{search}->{simple} = <br />
{<br />
search_fields => [<br />
{<br />
id => "q",<br />
meta_fields => [<br />
"documents",<br />
"ml_title",<br />
"abstract",<br />
"creators_name",<br />
"date" <br />
]<br />
},<br />
],<br />
# preamble_phrase => "cgi/search:preamble",<br />
title_phrase => "cgi/search:simple_search",<br />
citation => "result",<br />
page_size => 20,<br />
order_methods => {<br />
"byyear" => "-date/creators_name/title",<br />
"byyearoldest" => "date/creators_name/title",<br />
"byname" => "creators_name/-date/title",<br />
"bytitle" => "title/creators_name/-date" <br />
},<br />
default_order => "byyear",<br />
show_zero_results => 1,<br />
};<br />
</source><br />
<br />
And for the advanced search we add the file: '''~eprints/archives/reponame/cfg/cfg.d/eprint_search_advanced_local.pl''' that reads:<br />
<source lang="perl"><br />
$c->{search}->{advanced} =<br />
{<br />
search_fields => [<br />
{ meta_fields => [ "documents" ] },<br />
{ meta_fields => [ "ml_title" ] },<br />
{ meta_fields => [ "creators_name" ] },<br />
{ meta_fields => [ "abstract" ] },<br />
{ meta_fields => [ "date" ] },<br />
{ meta_fields => [ "keywords" ] },<br />
{ meta_fields => [ "subjects" ] },<br />
{ meta_fields => [ "type" ] },<br />
{ meta_fields => [ "department" ] },<br />
{ meta_fields => [ "editors_name" ] },<br />
{ meta_fields => [ "ispublished" ] },<br />
{ meta_fields => [ "refereed" ] },<br />
{ meta_fields => [ "publication" ] },<br />
{ meta_fields => [ "documents.format" ] },<br />
],<br />
preamble_phrase => "cgi/advsearch:preamble",<br />
title_phrase => "cgi/advsearch:adv_search",<br />
citation => "result",<br />
page_size => 20,<br />
order_methods => {<br />
"byyear" => "-date/creators_name/title",<br />
"byyearoldest" => "date/creators_name/title",<br />
"byname" => "creators_name/-date/title",<br />
"bytitle" => "title/creators_name/-date" <br />
},<br />
default_order => "byyear",<br />
show_zero_results => 1,<br />
};<br />
</source><br />
<br />
== Reloading our repository ==<br />
In order for our changes to take effect, we should reload our repository by running:<br />
<source lang="bash"><br />
$ ./bin/epadmin reload reponame</source><br />
within eprints user's home directory as user eprints.<br />
<br />
== Regenerating static files and abstracts ==<br />
If our repository already contained records, we need to recreate static content such as static pages and abstracts. Hence, as eprints user we should run:<br />
<source lang="bash"><br />
$ ./bin/generate_abstracts reponame<br />
$ ./bin/generate_static reponame<br />
</source><br />
within eprints user's home directory.</div>Libjlrshttps://wiki.eprints.org/w/index.php?title=Display_a_custom_response_during_downtime&diff=16115Display a custom response during downtime2023-09-07T09:35:00Z<p>Libjlrs: Update Apache method call (which doesn't exist in modern versions) with newer call to remote_ip</p>
<hr />
<div>[[Category:Howto]]<br />
[[Category:Management]]<br />
<br />
See also [[Creating a Maintenance Page]].<br />
<br />
We were recently migrating our database from an old server to a new one - which required a dump + load of data (rather than a replication). This meant we had a period of 3 hours where EPrints wouldn't be accessible.<br />
<br />
During this downtime, I wanted to to display a useful message, with a '503 Service unavailable' HTTP response.<br />
This is how to achieve this using EPrints triggers:<br />
'''NOTE''' if you are doing maintenance that means EPrints will not be able to connect to the database, the method below will not work, as EPrints will complain about not being able to connect to the database before processing the trigger. If you maintenance will result in the database being offline (rather than read-only), the maintenance page should be delivered using Apache. Please see https://stackoverflow.com/questions/622466/how-to-put-apache-website-to-503-temporary-down for some examples).<br />
<br />
# Create a file <code>~/archives/ARCHIVEID/cfg/cfg.d/a_MAINTENANCE.pl</code>. The name of the file isn't important - but it should be alphabetically '''before''' any other config file that defined a URL_REWRITE trigger.<br />
# Add the following to the file, altering the <code>maintenance_ip</code>, <code>maintenance_retry_after</code> and <code>maintenance_page_html</code> appropriately. I'd keep the html page quite simple, but with enough info to help a human. Remember to escape any single-quotes in the HTML block with a backslash e.g. BAD: <code>we've</code>; GOOD: <code>we\'ve</code>.:<br />
<source lang="perl"><br />
# Set maintenance to 1 to respond with a 503 for requests, except those from the maintenance_ip.<br />
$c->{maintenance} = 0;<br />
$c->{maintenance_allowed_ip} = '127.0.0.1'; #set this to your IP address<br />
<br />
# set to a date/time after your maintenance will have finished, <br />
# or a period (in seconds) that the maintenance will last for<br />
$c->{maintenance_retry_after} = 'Mon, 14 Mar 2016 12:00:00 GMT'; #set to a date/time after your maintenance will have finished<br />
<br />
use EPrints::Const;<br />
$c->add_trigger( EP_TRIGGER_URL_REWRITE, sub {<br />
my( %args ) = @_;<br />
<br />
# args passed to EP_TRIGGER_URL_REWRITE are:<br />
# request, lang, args, urlpath, cgipath, uri, secure, return_code<br />
my( $repository, $request, $return_code, $uri, $urlpath ) = @args{ qw( repository request return_code uri urlpath ) };<br />
<br />
#check we're in maintenance mode<br />
if( $repository->config( "maintenance" ) && $repository->config( "maintenance" ) == 1 ){<br />
# is there an IP we should allow through?<br />
# NB You might need to do other checks - e.g. X-Forwarded-For if you are behind a load-balancer<br />
# or for different versions of Apache (like here: https://github.com/eprints/eprints/issues/214)<br />
# if you're not sure, ask on the EPrints Tech list first!<br />
if( $repository->config( "maintenance_allowed_ip" ) && <br />
$repository->remote_ip eq $repository->config( "maintenance_allowed_ip" ) ){<br />
return EP_TRIGGER_OK;<br />
}<br />
elsif( $uri !~ /^$urlpath\/(style|images)\// ) # allow image/stylesheet requests <br />
# through - so you can display a branded 503 page<br />
{<br />
$request->custom_response( Apache2::Const::HTTP_SERVICE_UNAVAILABLE, $c->{maintenance_page_html} );<br />
if( $repository->config( "maintenance_retry_after" ) ){<br />
$request->err_headers_out->{'Retry-After'} = $repository->config( "maintenance_retry_after" );<br />
}<br />
# set the 503 response<br />
${$return_code} = EPrints::Const::HTTP_SERVICE_UNAVAILABLE;<br />
# and don't process any more EP_TRIGGER_URL_REWRITE triggers.<br />
return EP_TRIGGER_DONE;<br />
}<br />
}<br />
} );<br />
<br />
# A simple maintenance page - not using the template (which will probably link to various other pages that aren't<br />
# accessible during the maintenance window<br />
$c->{maintenance_page_html} = '<!DOCTYPE HTML><br />
<html><br />
<head><br />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><br />
<style><br />
body {<br />
font-family: sans-serif;<br />
margin: 3em;<br />
}<br />
footer {<br />
font-size: 80%;<br />
margin-top:2em;<br />
}<br />
</style><br />
<title>###REPO NAME### - Maintenance</title><br />
</head><br />
<body><br />
<header><br />
<img src="/images/sitelogo.png" /><br />
<h1>###REPO NAME### - Maintenance</h1><br />
</header><br />
<section><br />
<p><strong>Date/Time</strong> We\'re currently doing things to the system.<br /><br />
We\'ll be back soon!</p><br />
<p>If you have any questions, please contact someone@somewhere.blah</p><br />
</section><br />
<footer><br />
<p>###REPO NAME###</p><br />
</footer><br />
</body><br />
</html>';<br />
<br />
</source><br />
<br />
# Do a <code>~/bin/epadmin test ARCHIVEID</code> to make sure you haven't done anything silly in the config file.<br />
# Do a <code>~/bin/epafmin reload ARCHIVEID</code> and check that nothing's changed<br />
# When you want to turn the maintenance response on, change set: <code>$c->{maintenance} = 1;</code> and reload the archive.<br />
# Check that you can get in from the IP specified, and that you get the 503 response from other IPs.<br />
# Do a graceful restart of Apache - to stop the noisy 'repository had been reloaded' error messages.<br />
# Do the maintenance, test.<br />
# Change <code>$c->{maintenance} = 0;</code>, graceful restart Apache, test.<br />
# Done!<br />
<br />
If you want to include the default CSS files in the 503 page, include <code><link rel="stylesheet" type="text/css" href="/style/auto-3.3.14.css"></code> in the maintenance_html_page -> head section (update it for your version of EPrints!).</div>Libjlrshttps://wiki.eprints.org/w/index.php?title=Redirect_specific_eprints_to_somewhere_else&diff=15640Redirect specific eprints to somewhere else2023-02-16T21:09:59Z<p>Libjlrs: Create new page</p>
<hr />
<div>This page is based on a question posed on the [http://mailman.ecs.soton.ac.uk/pipermail/eprints-tech/2023-February/thread.html#9203 EP-Tech mailing list: Adding 301 redir_permanent for some migrated items before 404 kicks in.], around approaches to redirect specific EPrints to different URLs (e.g. where certain items have been migrated to different services).<br />
<br />
There were two solutions suggested, and an additional (untested) approach, detailed below.<br />
<br />
* use an EPrints URL rewrite trigger<br />
* use the `rewrite_exceptions` configuration, in combination with an Apache `RewriteMap`<br />
* register a new PerlTransHandler to do rewrites<br />
<br />
The best approach will depend on the size of the repository, the percentage of items that need to be redirected, whether additional aspects (e.g. mapping document-level requests or export URLs) are needed.<br />
<br />
The `EP_TRIGGER_URL_REWRITE` will be triggered on each request - so it's important to keep the code 'quick' - and return quickly for URLs that are of no interest.<br />
<br />
The `rewrite_exceptions` array is searched for each request too - so having a very large array to search through may also slow your repository down.<br />
<br />
== EPrints URL rewrite trigger ==<br />
<br />
<source lang="perl"><br />
# Save as e.g. EPRINTS_ROOT/archives/ARCHIVE_ID/cfg/cfg.d/z_url_rewrite_map.pl<br />
# source is available from: https://gist.github.com/jesusbagpuss/2e9172a2ee94d4dcfc5f23a08486f3fe <br />
# Maps specific URLs to be permanently redirected<br />
<br />
use EPrints::Const; # for trigger return values<br />
<br />
# define specific URLs that have been moved.<br />
# If all the new URLs are to the same base URL, you could have e.g 1234 => 5678 in the <br />
# hash, and prepend a static 'https://new.repo.com/' in the 'Location' line below.<br />
# the hash could also be defined by reading data in from a file (e.g. csv)<br />
<br />
$c->{z_url_rewrite_map} = {<br />
'1234' => 'https://abc.de/1/',<br />
'2345' => 'https://abc.de/9/',<br />
};<br />
<br />
$c->add_trigger( EP_TRIGGER_URL_REWRITE, sub {<br />
my( %o ) = @_;<br />
<br />
# Available hash keys in %o<br />
# request, lang (en), args ("" or "?foo=bar"), urlpath ("" or "/subdir"), cgipath ("/cgi" or "/subdir/cgi")<br />
# uri (/foo/bar), secure ( boolean ), return_code (set to trigger a return - stop stack of triggers), repository<br />
<br />
my $redirect_map = $o{repository}->get_conf( "z_url_rewrite_map" );<br />
return if !defined $redirect_map;<br />
<br />
# Optimisation over the 404 handler regex...<br />
# If you have a long-standing repository, there may be EPrint URLs out in the wild that refer to repo.com/1234 (without trailing slash).<br />
# Currently, EPrints will redirect this to repo.com/1234/ - and then m#^/(\d+)/# (from 404 handler) would capture it.<br />
# This could result in multiple redirects ( /1234 --> /1234/ --> other server ) which isn't best practice for SEO.<br />
#<br />
# The first regex below will match `/1234` , `/1234/`, `/00001234`, `/00001234/` (zero-padded IDs were from old versions of EPrints - but may still be in use.<br />
# These are currently handled in EPrints::Apache::Rewrite with a redirect, so capturing them here stops one redirect loop.<br />
#<br />
# If your repo is _really_ old, you might also want to capture repo.com/archive/1234 or repo.com/archive/00001234...<br />
# ...I guess looking in the Apache logs will indicate if this is necessary!<br />
<br />
if( defined $o{uri} && ( $o{uri} =~ m#^/0{0,9}(\d+)(?>/|$)# || $o{uri} =~ m#^/id/eprint/0{0,9}(\d+)/# ) )<br />
{ <br />
# We've got what looks like an EPrintID...<br />
# Is there a redirect map for it?<br />
if( defined $redirect_map->{$1} ){<br />
EPrints::Apache::AnApache::send_status_line( $o{request}, 301, "Moved Permanently" );<br />
EPrints::Apache::AnApache::header_out( $o{request}, "Location", "$redirect_map->{$1}" );<br />
EPrints::Apache::AnApache::send_http_header( $o{request} );<br />
<br />
${$o{return_code}} = EPrints::Const::DONE;<br />
return EP_TRIGGER_DONE;<br />
}<br />
# an EPrintID, but not redirected.<br />
}<br />
# not an EPrintID URL - just return (could explicitly set a trigger return value, but not necessary)<br />
} );<br />
</source><br />
<br />
== Apache RewriteMap solution ==<br />
<br />
By default, EPrints will process all requests, so including additional directives in the Apache config doesn't work.<br />
Luckily, EPrints provides a configuration variable for URL stubs to ''not'' be processed.<br />
<source lang="perl"><br />
# Save as e.g. EPRINTS_ROOT/archives/ARCHIVE_ID/cfg/cfg.d/z_rewrite_exceptions.pl - ***BUT CHECK YOUR CONFIG FOR AN EXISTING DEFINITION!!!***<br />
$c->{rewrite_exceptions} = [ '/1234/', '/2345/' ];<br />
</source><br />
<br />
URLs matching those specified will not be handled by the EPrints stack, allowing Apache to handle the requests.<br />
The `newid` part shows how to map the 'exception' IDs to one new system (with new IDs).<br />
The `newurl` part can be used to map the exception IDs to any URL.<br />
<br />
<source lang="apache"><br />
# In apache vhost config file<br />
RewriteMap newid "txt:/etc/apache2/newid.txt"<br />
RewriteMap newurl "txt:/etc/apache2/newurl.txt"<br />
<br />
RewriteCond ${newid:$1|Unknown} !Unknown<br />
RewriteRule "^/([0-9]+)/?$" "new.server/${newid:$1|$1}" [R,L]<br />
<br />
RewriteCond ${newurl:$1|Unknown} !Unknown<br />
RewriteRule "^/([0-9]+)/?$" "${newurl:$1}" [R,L]<br />
</source><br />
<br />
The newid.txt file would contain something like:<br />
1234 1234<br />
2345 9876<br />
<br />
The newurl.txt file would contain something like:<br />
1234 https://new.host/item1000<br />
2345 https://some.other.host/42/life<br />
<br />
The Apache RewriteMap also allows other approaches - e.g. querying a database to find matches. Just make sure it's quick and stable!<br />
<br />
== PerlTransHandler (possible solution for proper perl geeks - completely untested!) ==<br />
EPrints is added to the Apache configuration with the following config:<br />
<br />
PerlTransHandler +EPrints::Apache::Rewrite<br />
<br />
The `+` before the module name tells Apache to load the specified module before using it. It's equivalent to including a specific `PerlModule Apache::Foo` line.<br />
<br />
[https://perl.apache.org/docs/2.0/user/handlers/http.html#PerlTransHandler `PerlTransHandler`] is a [https://perl.apache.org/docs/2.0/user/handlers/intro.html#Stacked_Handlers stacked handler].<br />
This means you could write your own custom Perl module to handle the redirects:<br />
<source lang="perl"><br />
# save as e.g. EPRINTS_ROOT/lib/plugins/Custom/Rewrites.pm<br />
# THIS APPROACH IS UNTESTED! (feel free to test it, and correct it ;)<br />
package Custom::Rewrites;<br />
<br />
use strict;<br />
use warnings;<br />
<br />
use Apache2::RequestRec ();<br />
use Apache2::Const -compile => qw(DECLINED HTTP_MOVED_PERMANENTLY);<br />
<br />
# default method name used by Apache Perl handlers<br />
sub handler {<br />
my $r = shift;<br />
<br />
my ( $id ) = $r->uri =~ m#^/0{0,9}(\d+)(?>/|$)#; # matching id. could also capture pos, filename etc. if needed<br />
<br />
# get a list of IDs/Locations somehow.<br />
# do some logic to work out if $id should be redirected, and to where - $new_location<br />
if( $needs_redirection )<br />
{<br />
$r->err_headers_out->add( Location => "$new_location" );<br />
return Apache2::Const::HTTP_MOVED_PERMANENTLY;<br />
}<br />
<br />
# This ID does not need to be redirected. This handler returns 'DECLINED', and the next handler is passed the request to process<br />
return Apache2::Const::DECLINED;<br />
}<br />
1;<br />
</source><br />
<br />
The above handler can be added to the `PerlTransHandler` stack '''before''' the EPrints one in the `VirtualHost` definition:<br />
<source lang="apache"><br />
<VirtualHost *:443><br />
ServerName eprints.somehwere<br />
...<br />
...<br />
# Handle redirects with custom module first<br />
PerlTransHandler +Custom::Rewrites<br />
# then fall back to 'normal' EPrints handling<br />
PerlTransHandler +EPrints::Apache::Rewrite<br />
</VirtualHost><br />
</source><br />
<br />
== See Also ==<br />
* [[Custom handlers]]<br />
* [http://mailman.ecs.soton.ac.uk/pipermail/eprints-tech/2022-May/008931.html EP-Tech discussion]<br />
* <br />
<br />
[[Category:Howto]]</div>Libjlrshttps://wiki.eprints.org/w/index.php?title=Boolean_field&diff=15624Boolean field2023-01-26T12:11:21Z<p>Libjlrs: /* menu style */</p>
<hr />
<div>{{fieldtypes}}<br />
__NOTOC__<br />
== Inheritance ==<br />
* [[Metadata]]<br />
** [[Boolean field]]<br />
<br />
== Description ==<br />
<br />
Describes a simple yes/no value. Unless the field has the ''required'' property set, it can actually have a third setting of unset. This can be useful as it distinguishes between a "False" and a "don't know/haven't filled this in yet". For example when asking if a paper is refereed, this is a boolean field. However it's not required as often someone isn't sure, and does not want to click "no" when that's not necessarily true.<br />
<br />
== Properties ==<br />
<br />
{| border="1" cellpadding="3" cellspacing="0"<br />
| name || default || description <br />
|-<br />
| '''input_style''' || checkbox || May be one of (menu<nowiki>|</nowiki>radio<nowiki>|</nowiki>checkbox). This controls how the field is rendered in input forms. <br />
<br />
"checkbox" gives just a single HTML checkbox which can be ticked or not. It looks a bit rubbish, and does not provide a way to indicate an "unset" value.<br />
<br />
"menu" gives an HTML "select" menu with two or three options. The third is "unspecified" and only available if the field is not a required field. <br />
<br />
"radio" gives an HTML radio buttons interface. It renders an html phrase with the true and false radio buttons placed in the phrase using pins. If the field is not required then a third radio button for "unspecified" appears below this.<br />
<br />
|}<br />
<br />
== Required Phrases ==<br />
<br />
=== menu style ===<br />
<br />
If you use input_style=>"menu" then you need two phrases of the type:<br />
<br />
''datasetid'' + "_fieldopt_" + ''fieldname'' + "_TRUE"<br />
''datasetid'' + "_fieldopt_" + ''fieldname'' + "_FALSE"<br />
<br />
These control the display of the items in the menu.<br />
<br />
Example:<br />
<br />
<epp:phrase id="eprint_fieldopt_myboolean_TRUE">Certainly!</epp:phrase><br />
<epp:phrase id="eprint_fieldopt_myboolean_FALSE">No way!</epp:phrase><br />
<br />
==== optional phrase to replace 'UNSPECIFIED' text ====<br />
To overwrite the default 'UNSPECIFIED' option displayed when a boolean field is not required, a phrase with an underscore at the end can be used:<br />
<br />
''datasetid'' + "_fieldopt_" + ''fieldname'' + "_"<br />
<br />
Example:<br />
<br />
<epp:phrase id="eprint_fieldopt_myboolean_">Don't know.</epp:phrase><br />
<br />
=== radio style ===<br />
<br />
This uses a single phrase with two pins in it to indicate the locations of the radio buttons. The phrase id is:<br />
<br />
''datasetid'' + "_radio_" + ''fieldname''<br />
<br />
We suggest placing a <label> element around the radio button and it's title - as well as being good practice, this also means that in some browsers clicking on the text will select the button.<br />
<br />
For example:<br />
<br />
<epp:phrase id="eprint_radio_myboolean"><label><epc:pin name="true"/>Yes, I like cheese.</label><br/><label><epc:pin name="false"/>No, cheese is bad.</label></epp:phrase><br />
<br />
<br />
== Database ==<br />
<br />
Boolean fields are stored in the database as<br />
<br />
fieldname SET( 'TRUE', 'FALSE' )<br />
<br />
== API ==<br />
<br />
In the code these fields are stored as strings containing "TRUE", "FALSE" or ""/undef if they are not set.</div>Libjlrshttps://wiki.eprints.org/w/index.php?title=Category:User_Roles&diff=15594Category:User Roles2022-12-14T08:58:24Z<p>Libjlrs: Created page with "Collection of pages relating to User roles and how to use them."</p>
<hr />
<div>Collection of pages relating to User roles and how to use them.</div>Libjlrshttps://wiki.eprints.org/w/index.php?title=Listings_of_User_Roles_and_Privileges&diff=15593Listings of User Roles and Privileges2022-12-14T08:57:19Z<p>Libjlrs: </p>
<hr />
<div>[[Category:Plugins]]<br />
[[Category:User Roles]]<br />
This page is intended to be a near exhaustive listing of roles and privileges that can be assigned to a user to allow them to carry out certain actions.<br />
<br />
== User Roles ==<br />
;admin<br />
:[[#indexer/start|indexer/start]], [[#indexer/stop|indexer/stop]], [[#indexer/force_start|indexer/force_start]], [[#create_user|create_user]], [[#subject/edit|subject/edit]], [[#staff/user_search|staff/user_search]], [[#staff/history_search|staff/history_search]], [[#staff/issue_search|staff/issue_search]], [[#config/view/FILETYPE|config/view]], [[#config/view/FILETYPE|config/view/xml]], [[#config/view/FILETYPE|config/view/workflow]], [[#config/view/FILETYPE|config/view/citation]], [[#config/view/FILETYPE|config/view/phrase]], [[#config/view/FILETYPE|config/view/namedset]], [[#config/view/FILETYPE|config/view/template]], [[#config/view/FILETYPE|config/view/static]], [[#config/view/FILETYPE|config/view/autocomplete]], [[#config/view/FILETYPE|config/view/apache]], [[#config/view/FILETYPE|config/view/perl]], [[#config/test_email|config/test_email]], [[#config/imports|config/imports]], [[#config/add_field|config/add_field]], [[#config/remove_field|config/remove_field]],[[#config/regen_abstracts|config/regen_abstracts]], [[#config/regen_citations|config/regen_citations]], [[#config/regen_views|config/regen_views]], [[#config/edit/FILETYPE|config/edit/perl]], [[#storage/manager|storage_manager]], [[#repository/epm|repository/epm]], [[#event_queue/destroy|event_queue/destroy]], [[#event_queue/details/event_queue/details]], [[#event_queue/edit|event_queue/edit]], [[#event_queue/export|event_queue/export]], [[#event_queue/view|event_queue/view]], [[#eprint/STATUS/destroy:USERTYPE|eprint/destroy]], [[#eprint/STATUS/details:USERTYPE|eprint/details]], [[#eprint/STATUS/edit:USERTYPE|eprint/edit]], [[#eprint/STATUS/export:USERTYPE|eprint/export]], [[#eprint/STATUS/upsert:USERTYPE|eprint/upsert]], [[#eprint/STATUS/view:USERTYPE|eprint/view]], [[#eprint/STATUS/remove:USERTYPE|eprint/archive/remove]], [[#eprint/STATUS/edit:USERTYPE|eprint/archive/edit]], [[#file/destroy|file/destroy]], [[#file/export|file/export]], [[#file/view|file/view]], [[#import/view|import/view]], [[#import/edit|import/edit]], [[#saved_search/destroy|saved_search/destroy]], [[#saved_search/details|saved_search]], [[#saved_search/edit|saved_search/edit]], [[#saved_search/export|saved_search/export]], [[#saved_search/view|saved_search/view]], [[#user/remove:USERTYPE|user/remove]], [[#user/edit:USERTYPE|user/edit]], [[#user/view:USERTYPE|user/view]], [[#user/details:USERTYPE|user/details]], [[#user/destroy:USERTYPE|user/destroy]], [[#user/history:USERTYPE|user/history]], [[#user/staff/edit|user/staff/edit]], [[#repository/epm|repository/epm]]<br />
;change-email<br />
: ''Currently empty''<br />
;change-user<br />
: ''Currently empty''<br />
;deposit<br />
: [[#items|items]], [[#create_eprint|create_eprint]], [[#user/history:USERTYPE|user/history:owner]], [[#eprint/STATUS/view:USERTYPE|eprint/inbox/view:owner]], [[#eprint/STATUS/export:USERTYPE|eprint/inbox/export:owner]], [[#eprint/STATUS/summary:USERTYPE|eprint/inbox/summary:owner]], [[#eprint/STATUS/destroy:USERTYPE|eprint/inbox/destroy:owner]], [[#eprint/STATUS/deposit:USERTYPE|eprint/inbox/deposit:owner]], [[#eprint/STATUS/edit:USERTYPE|eprint/inbox/edit:owner]], [[#eprint/STATUS/remove:USERTYPE|eprint/inbox/remove:owner]], [[#eprint/STATUS/details:USERTYPE|eprint/inbox/details:owner]], [[#eprint/STATUS/history:USERTYPE|eprint/inbox/history:owner]], [[#eprint/STATUS/messages:USERTYPE|eprint/inbox/messages:owner]], [[#eprint/STATUS/issues:USERTYPE|eprint/inbox/issues:owner]], [[#eprint/STATUS/use_as_template:USERTYPE|eprint/inbox/use_as_template:owner]], [[#eprint/STATUS/derive_version:USERTYPE|eprint/inbox/derive_version:owner]], [[#eprint/STATUS/view:USERTYPE|eprint/buffer/view:owner]], [[#eprint/STATUS/export:USERTYPE|eprint/buffer/export:owner]], [[#eprint/STATUS/summary:USERTYPE|eprint/buffer/summary:owner]], [[#eprint/STATUS/move_inbox:USER_TYPE|eprint/buffer/move_inbox:owner]], [[#eprint/STATUS/details:USERTYPE|eprint/buffer/details:owner]], [[#eprint/STATUS/history:USERTYPE|eprint/buffer/history:owner]], [[#eprint/STATUS/messages:USERTYPE|eprint/buffer/messages:owner]], [[#eprint/STATUS/request_removal:USERTYPE|eprint/buffer/request_removal:owner]], [[#eprint/STATUS/use_as_template:USERTYPE|eprint/buffer/use_as_template:owner]], [[#eprint/STATUS/derive_version:USERTYPE|eprint/buffer/derive_version:owner]], [[#eprint/STATUS/view:USERTYPE|eprint/archive/view:owner]], [[#eprint/STATUS/export:USERTYPE|eprint/archive/export:owner]], [[#eprint/STATUS/summary:USERTYPE|eprint/archive/summary:owner]], [[#eprint/STATUS/details:USERTYPE|eprint/archive/details:owner]], [[#eprint/STATUS/history:USERTYPE|eprint/archive/history:owner]], [[#eprint/STATUS/messages:USERTYPE|eprint/archive/messages:owner]], [[#eprint/STATUS/request_removal:USERTYPE|eprint/archive/request_removal:owner]], [[#eprint/STATUS/use_as_template:USERTYPE|eprint/archive/use_as_template:owner]], [[#eprint/STATUS/derive_version:USERTYPE|eprint/archive/derive_version:owner]], [[#eprint/STATUS/view:USERTYPE|eprint/deletion/view:owner]], [[#eprint/STATUS/export:USERTYPE|eprint/deletion/export:owner]], [[#eprint/STATUS/summary:USERTYPE|eprint/deletion/summary:owner]], [[#eprint/STATUS/details:USERTYPE|eprint/deletion/details:owner]], [[#eprint/STATUS/history:USERTYPE|eprint/deletion/history:owner]], [[#eprint/STATUS/messages:USERTYPE|eprint/deletion/messages:owner]], [[#eprint/STATUS/use_as_template:USERTYPE|eprint/deletion/use_as_template:owner]], [[#eprint/STATUS/derive_version:USERTYPE|eprint/deletion/derive_version:owner]]<br />
;general<br />
: [[#user/view:USERTYPE|user/view:owner]], [[#user/details:USERTYPE|user/details:owner]], [[#user/history:USERTYPE|user/history:owner]]<br />
;edit-config<br />
: [[#config/edit/FILETYPE|config/edit]], [[#config/edit/FILETYPE|config/edit/xml]], [[#config/edit/FILETYPE|config/edit/workflow]], [[#config/edit/FILETYPE|config/edit/citation]], [[#config/edit/FILETYPE|config/edit/phrase]], [[#config/edit/FILETYPE|config/edit/namedset]], [[#config/edit/FILETYPE|config/edit/template]], [[#config/edit/FILETYPE|config/edit/static]], [[#config/edit/FILETYPE|config/edit/autocomplete]], [[#config/reload|config/reload]]<br />
;edit-own-record<br />
: [[#user/edit:USERTYPE|user/edit:owner]]<br />
;editor<br />
: [[#datasets|datasets]], [[#editorial_review|editorial_review]], [[#eprint/STATUS/view:USERTYPE|eprint/inbox/view:editor]], [[#eprint/STATUS/export:USERTYPE|eprint/inbox/export:editor]], [[#eprint/STATUS/summary:USERTYPE|eprint/inbox/summary:editor]], [[#eprint/STATUS/export:USERTYPE|eprint/inbox/export:editor]], [[#eprint/STATUS/details:USERTYPE|eprint/inbox/details:editor]], [[#eprint/STATUS/history:USERTYPE|eprint/inbox/history:editor]], [[#eprint/STATUS/messages:USERTYPE|eprint/inbox/messages:editor]], [[#eprint/STATUS/remove_with_email:USERTYPE|eprint/inbox/remove_with_email:editor]], [[#eprint/STATUS/move_archive:USERTYPE|eprint/inbox/move_archive:editor]], [[#eprint/STATUS/move_buffer:USERTYPE|eprint/inbox/move_buffer:editor]], [[#eprint/STATUS/use_as_template:USERTYPE|eprint/inbox/use_as_template:editor]], [[#eprint/STATUS/derive_version:USERTYPE|eprint/inbox/derive_version:editor]], [[#eprint/STATUS/edit:USERTYPE|eprint/inbox/edit:editor]], [[#eprint/STATUS/takelock:USERTYPE|eprint/inbox/takelock:editor]], [[#eprint/STATUS/view:USERTYPE|eprint/buffer/view:editor]], [[#eprint/STATUS/export:USERTYPE|eprint/buffer/export:editor]], [[#eprint/STATUS/summary:USERTYPE|eprint/buffer/summary:editor]], [[#eprint/STATUS/export:USERTYPE|eprint/buffer/export:editor]], [[#eprint/STATUS/details:USERTYPE|eprint/buffer/details:editor]], [[#eprint/STATUS/history:USERTYPE|eprint/buffer/history:editor]], [[#eprint/STATUS/messages:USERTYPE|eprint/buffer/messages:editor]], [[#eprint/STATUS/issues:USERTYPE|eprint/buffer/issues:editor]], [[#eprint/STATUS/remove_with_email:USERTYPE|eprint/buffer/remove_with_email:editor]], [[#eprint/STATUS/reject_with_email:USERTYPE|eprint/buffer/reject_with_email:editor]], [[#eprint/STATUS/move_inbox:USERTYPE|eprint/buffer/move_inbox:editor]], [[#eprint/STATUS/move_archive:USERTYPE|eprint/buffer/move_archive:editor]], [[#eprint/STATUS/use+as_template:USERTYPE|eprint/buffer/use_as_template:editor]], [[#eprint/STATUS/derive_version:USERTYPE|eprint/buffer/derive_version:editor]], [[#eprint/STATUS/edit:USERTYPE|eprint/buffer/edit:editor]], [[#eprint/STATUS/takelock:USERTYPE|eprint/buffer/takelock:editor]], [[#eprint/STATUS/view:USERTYPE|eprint/deletion/view:editor]], [[#eprint/STATUS/export:USERTYPE|eprint/deletion/export:editor]], [[#eprint/STATUS/summary:USERTYPE|eprint/deletion/summary:editor]], [[#eprint/STATUS/export:USERTYPE|eprint/deletion/export:editor]], [[#eprint/STATUS/details:USERTYPE|eprint/deletion/details:editor]], [[#eprint/STATUS/history:USERTYPE|eprint/deletion/history:editor]], [[#eprint/STATUS/messages:USERTYPE|eprint/deletion/messages:editor]], [[#eprint/STATUS/move_archive:USERTYPE|eprint/deletion/move_archive:editor]], [[#eprint/STATUS/use_as_template:USERTYPE|eprint/deletion/use_as_template:editor]], [[#eprint/STATUS/derive_version:USERTYPE|eprint/deletion/derive_version:editor]], [[#eprint/STATUS/takelock:USERTYPE|eprint/deletion/takelock:editor]], <br />
;rest<br />
: [[#eprint/STATUS/rest/get:USERTYPE|eprint/archive/rest/get:editor]], [[#eprint/STATUS/rest/put:USERTYPE|eprint/archive/rest/put:editor]], [[#eprint/STATUS/rest/get:USERTYPE|eprint/buffer/rest/get:editor]], [[#eprint/STATUS/rest/put:USERTYPE|eprint/buffer/rest/put:editor]], [[#eprint/STATUS/rest/get:USERTYPE|eprint/inbox/rest/get:editor]], [[#eprint/STATUS/rest/put:USERTYPE|eprint/inbox/rest/put:editor]], [[#eprint/STATUS/rest/get:USERTYPE|eprint/deletion/rest/get:editor]], [[#eprint/STATUS/rest/put:USERTYPE|eprint/deletion/rest/put:editor]], [[#eprint/STATUS/rest/get:USERTYPE|eprint/inbox/rest/get:owner]], [[#eprint/STATUS/rest/put:USERTYPE|eprint/inbox/rest/put:owner]], [[#eprint/STATUS/rest/get:USERTYPE|eprint/buffer/rest/get:owner]], [[#eprint/STATUS/rest/get:USERTYPE|eprint/archive/rest/get:owner]], [[#eprint/STATUS/rest/get:USERTYPE|eprint/deletion/rest/get:owner]], [[#user/rest/get:USERTYPE|user/rest/get:owner]], [[#subject/rest/get|subject/rest/get]]<br />
;saved-searches<br />
: [[#saved_search|saved_search]], [[#create_saved_search|create_saved_search]], [[#saved_search/view:USERTYPE|saved_search/view:owner]], [[#saved_search/edit:USERTYPE|saved_search/edit:owner]], [[#saved_search/destroy:USERTYPE|saved_search/destroy:owner]]<br />
;set-password<br />
: [[#set-password|set-password]]<br />
;staff-view <br />
: [[#eprint/STATUS/view:USERTYPE|eprint/inbox/view]], [[#eprint/STATUS/summary:USERTYPE|eprint/inbox/summary]], [[#eprint/STATUS/export:USERTYPE|eprint/inbox/export]], [[#eprint/STATUS/details:USERTYPE|eprint/inbox/details]], [[#eprint/STATUS/history:USERTYPE|eprint/inbox/history]], [[#eprint/STATUS/view:USERTYPE|eprint/buffer/view]], [[#eprint/STATUS/summary:USERTYPE|eprint/buffer/summary]], [[#eprint/STATUS/export:USERTYPE|eprint/buffer/export]], [[#eprint/STATUS/details:USERTYPE|eprint/buffer/details]], [[#eprint/STATUS/history:USERTYPE|eprint/buffer/history]], [[#eprint/STATUS/view:USERTYPE|eprint/archive/view]], [[#eprint/STATUS/export:USERTYPE|eprint/archive/export]], [[#eprint/STATUS/details:USERTYPE|eprint/archive/details]], [[#eprint/STATUS/history:USERTYPE|eprint/archive/history]], [[#eprint/STATUS/view:USERTYPE|eprint/deletion/view]], [[#eprint/STATUS/summary:USERTYPE|eprint/deletion/summary]], [[#eprint/STATUS/export:USERTYPE|eprint/deletion/export]], [[#eprint/STATUS/details:USERTYPE|eprint/deletion/details]], [[#eprint/STATUS/history:USERTYPE|eprint/deletion/history]], [[#eprint/search/staff:USERTYPE|eprint/search/staff]] <br />
;toolbox<br />
: [[#toolbox|toolbox]]<br />
;view-status<br />
: [[#status|status]]<br />
<br />
== Roles used by User Types (as of EPrints 3.4.x) ==<br />
;minuser<br />
:general, edit-own-record, saved-searches, set-password, lock-username-to-email<br />
;user<br />
:general, edit-own-record, saved-searches, set-password, deposit, change-email<br />
;editor<br />
:general, edit-own-record, saved-searches, set-password, deposit, change-email, editor, view-status, staff-view<br />
;admin<br />
:general, edit-own-record, saved-searches, set-password, deposit, change-email, editor, view-status, staff-view, admin, edit-config<br />
<br />
== User Privileges ==<br />
=== config ===<br />
==== config/add_field ====<br />
Add a bespoke field to a data object, using the web browser interface.<br />
==== config/delete/FILETYPE ====<br />
Delete a configuration file. This can optionally be restricted to a file of a particular '''FILETYPE''': ''autocomplete, citation, namedset, perl, phrase, static, template, workflow, xml''. Some of these types can overlap, e.g. ''workflow'' is also ''xml''.<br />
==== config/edit/FILETYPE ====<br />
Edit a configuration file. This can optionally be restricted to a file of a particular '''FILETYPE''': ''autocomplete, citation, namedset, perl, phrase, static, template, workflow, xml''. Some of these types can overlap, e.g. ''workflow'' is also ''xml''.<br />
==== config/imports ====<br />
Unused by default. Intended for managing bulk imports to a repository archive.<br />
==== config/regen_abstracts ====<br />
Drops the abstract pages cache so abstract pages can be regenerated.<br />
==== config/regen_citations ====<br />
Drops the citations cache so citations can be regenerated.<br />
==== config/regen_views ==== <br />
Drops the browse view cache so browse view pages can be regenerated.<br />
==== config/reload ====<br />
Reload the repository configuration.<br />
==== config/remove_field ====<br />
Remove a field from a data object. (Only fields created via the web browser interfaces, not pre-created through archive configuration).<br />
==== config/test_email ====<br />
View the "Send test email" page to send a test email to a specified address to confirm email sending is working as expected.<br />
==== config/view/FILETYPE ====<br />
View a configuration file. This can optionally be restricted to a file of a particular '''FILETYPE''': ''autocomplete, citation, namedset, perl, phrase, static, template, workflow, xml''. Some of these types can overlap, e.g. ''workflow'' is also ''xml''.<br />
<br />
=== eprint ===<br />
Some eprint privileges can be specialised by the '''STATUS''' of the the eprint (e.g. ''inbox'', ''buffer'', ''archive'' or ''deletion'' and the '''USERTYPE''' (e.g. ''owner'' or ''editor''). The privilege ''eprint/view'' would allow the user to view any eprint, ''eprint/archive/view'' would only allow them to view eprints in the live archive and ''eprint/inbox/view:owner'' would only allow them to view eprints in the user workarea if they were owned by the user.<br />
==== create_eprint ====<br />
Create a new eprint, which will initial appear in that user's workarea.<br />
==== eprint_search ====<br />
View and use eprint search across live archive.<br />
==== eprint/reject_with_email ====<br />
Reject the eprint under review (returning to user's workarea) and email eprint's owner about this.<br />
==== eprint/remove_once_archived ====<br />
Completely remove an eprint even if it is or has been in the live archive.<br />
==== eprint/remove_with_email ====<br />
Completely remove an eprint and email eprint's owner to about this.<br />
==== eprint/staff/search ====<br />
View and use full eprint search across all statuses of eprint.<br />
==== eprint/STATUS/deposit:USERTYPE ====<br />
Deposit an eprint. Typically this would be just changing it status from ''inbox'' to ''buffer'', so the eprint can be reviewed.<br />
==== eprint/STATUS/derive_version:USERTYPE ====<br />
Create a new version of a chosen eprint. Copying the metadata and setting the ''succeeds'' field to that of that chosen eprint.<br />
==== eprint/STATUS/destroy:USERTYPE ====<br />
Completely delete an existing eprint via "Manage records" page.<br />
<br />
==== eprint/STATUS/details:USERTYPE ====<br />
View the ''Details'' tab for an eprint.<br />
==== eprint/STATUS/edit:USERTYPE ====<br />
Edit the metadata for an eprint<br />
==== eprint/STATUS/export:USERTYPE ====<br />
Export the metadata for an eprint in one or more different formats.<br />
==== eprint/STATUS/history:USERTYPE ====<br />
View the ''History'' tab for an eprint.<br />
==== eprint/STATUS/issues:USERTYPE ====<br />
View the ''Issues'' tab for an eprint.<br />
==== eprint/STATUS/messages:USERTYPE ====<br />
View the ''Messages'' tab for an eprint.<br />
==== eprint/STATUS/move_archive:USERTYPE ====<br />
Move an eprint to the live archive. (I.e. change its status, normally from ''buffer'' to ''archive'').<br />
==== eprint/STATUS/move_buffer:USERTYPE ====<br />
Move an eprint back to the review buffer. (I.e. change its status to ''buffer'').<br />
==== eprint/STATUS/move_deletion:USERTYPE ====<br />
Retire an eprint. (I.e. change its status, normally from ''archive'' to ''deletion'').<br />
==== eprint/STATUS/move_inbox:USERTYPE ====<br />
Move an eprint back to a user's workarea. (I.e. change its status, normally from ''buffer'' to ''inbox'').<br />
==== eprint/STATUS/remove:USERTYPE ====<br />
Completely remove an eprint.<br />
==== eprint/STATUS/request_removal:USERTYPE ====<br />
Request that an existing eprint is removed, (e.g. because it is a duplicate or has been added erroneously).<br />
==== eprint/STATUS/rest/get:USERTYPE ====<br />
An eprint's metadata can be retrieved using the REST API.<br />
==== eprint/STATUS/rest/put:USERTYPE ====<br />
An eprint's metadata can be set using the REST API.<br />
==== eprint/STATUS/summary:USERTYPE ====<br />
View the ''Summary''' tab of an eprint.<br />
==== eprint/STATUS/takelock:USERTYPE ====<br />
Take the edit lock on an eprint.<br />
==== eprint/STATUS/upsert:USERTYPE ====<br />
Overwrite the existing metadata for an eprint. Typically with a PUT request via an API not through the repository's web browser interface.<br />
==== eprint/STATUS/use_as_template:USERTYPE ====<br />
Use metadata from a chosen eprint to create a new eprint, which is not a new version of that chosen eprint.<br />
==== eprint/STATUS/view:USERTYPE ====<br />
View an eprint and a rendering of its metadata<br />
<br />
=== event_queue ===<br />
==== event_queue/destroy ====<br />
Completely delete an event queue task.<br />
==== event_queue/details ====<br />
View the ''Details'' tab for an event queue task.<br />
==== event_queue/edit ====<br />
Edit an event queue task. (E.g. change the time it should run or reset its status if it has failed.)<br />
==== event_queue/export ====<br />
Export the metadata for an event queue task. <br />
==== event_queue/view ====<br />
View the metadata for an event queue task.<br />
<br />
=== file ===<br />
==== file/destroy ====<br />
Completely delete a file record via "Manage records" page.<br />
<br />
==== file/export ====<br />
Export the metadata for a file record.<br />
==== file/view ====<br />
View the metadata for a file record.<br />
<br />
=== import ===<br />
==== import/view ====<br />
View the metadata for an import.<br />
==== import/edit ====<br />
Edit the metadata for an import.<br />
<br />
=== indexer ===<br />
==== indexer/force_start ====<br />
Force start the indexer, if the repository thinks it is still running but no event queue tasks are being processed.<br />
==== indexer/start ====<br />
Start the indexer if it is not currently running.<br />
==== indexer/stop ====<br />
Stop the indexer if it is currently running.<br />
<br />
=== saved_search ===<br />
Some saved search privileges can be specialised by '''USERTYPE''' (e.g. ''owner''). The privilege ''saved_search/edit'' would allow the user to view any saved search record, ''saved_search/edit:owner'' would only allow them to edit their own saved search records.<br />
==== create_saved_search ====<br />
Create a new saved_search record.<br />
==== saved_search ==== <br />
View listing or a user's saved searches.<br />
==== saved_search/destroy:USERTYPE ====<br />
Completely delete a saved search record.<br />
==== saved_search/details:USERTYPE ==== <br />
View the ''Details'' tab for a saved search record.<br />
==== saved_search/edit:USERTYPE ====<br />
Edit the metadata for a saved search record.<br />
==== saved_search/export:USERTYPE ====<br />
Export the metadata for a saved search record.<br />
==== saved_search/view:USERTYPE ====<br />
View the metadata for a saved search record.<br />
<br />
=== staff ===<br />
==== staff/user_search ==== <br />
View and use the search over user records.<br />
==== staff/history_search ==== <br />
View and use the search over eprint history records.<br />
==== staff/issue_search ====<br />
View and use the search over eprint issue records.<br />
<br />
=== subject ===<br />
==== subject/edit ====<br />
View and edit the subject tree.<br />
==== subject/rest/get ====<br />
A subject's metadata can be retrieved using the REST API.<br />
<br />
=== user ===<br />
Some user privileges can be specialised by '''USERTYPE''' (e.g. ''owner''). The privilege ''user/edit'' would allow the user to view any user record, ''user/edit:owner'' would only allow them to edit their own user record.<br />
==== create_user ====<br />
Create a new user.<br />
==== user/destroy:USERTYPE ====<br />
Completely delete a user record.<br />
==== user/details:USERTYPE ====<br />
View the ''Details'' tab of a user.<br />
==== user/edit:USERTYPE ====<br />
Edit a user's profile.<br />
==== user/history:USERTYPE ====<br />
View the ''History'' tab of a user. This includes the changes (revisions) they made to any eprint record.<br />
==== user/mediate ====<br />
Whether a user can mediate for (i.e. act as) another user. Required feature of [[SWORD]] API.<br />
==== user/remove:USERTYPE ==== <br />
Unused by default. Intended for removing a user record. Use [[#user/destroy:USERTYPE|user/destroy:USERTYPE]] instead.<br />
<br />
==== user/staff/edit ====<br />
Unused by default. Intended for restricting parts of a user's profile to be edited by a repository admininistrator. <br />
==== user/view:USERTYPE ====<br />
View a user record's metadata.<br />
<br />
=== Miscellaneous ===<br />
==== datasets ====<br />
View the "Manage records" page.<br />
==== editorial_review ====<br />
View the "Review" page.<br />
==== items ====<br />
View the "Manage deposits" page.<br />
==== repository/epm ====<br />
View the "EPrints Bazaar" page and install Bazaar plugins.<br />
==== set-password ====<br />
Unused by default. Intended for restricting whether a user can set their own password.<br />
==== status ====<br />
View the "Status" and "Database Schema" pages.<br />
==== storage/manager ====<br />
View the "Storage Manager" page.<br />
==== toolbox ====<br />
Use the toolbox CGI script (i.e. ''/cgi/toolbox/toolbox'') to carry out a operation provided by EPrints::Toolbox. '''Dangerous''': Do not enable without good reason.<br />
<br />
== Public Role User Privileges ==<br />
These privileges available to users without them needing to login. This mainly pertains to REST requests you may or may not want accessible.<br />
;+eprint/archive/rest/get<br />
:REST request to get metadata for an eprint in the live archive<br />
;+subject/archive/rest/get<br />
:REST request to get metadata for a subject in the archive's subject tree.</div>Libjlrshttps://wiki.eprints.org/w/index.php?title=User_Roles_and_Privileges&diff=15592User Roles and Privileges2022-12-14T08:57:03Z<p>Libjlrs: </p>
<hr />
<div>[[Category:User Roles]]<br />
This page is intended to provide a useful guide on how [[EPrints Glossary#User role|user roles]] and [[EPrints Glossary#User privilege|privileges]] work within EPrints repository software, expanding on the information already available at [[user_roles.pl]].<br />
<br />
A role in EPrints is made up of 1 or more privileges. Giving a user a role gives them all the privileges associated with that role. You can also give users additional privileges without giving them the full role. <br />
<br />
==Creating a role==<br />
To create the role <code>approve-hat</code> you would do the following:<br />
<pre><br />
$c->{roles}->{"approve-hat"} = [<br />
"eprint/buffer/view:editor",<br />
"eprint/buffer/summary:editor",<br />
"eprint/buffer/details:editor",<br />
"eprint/buffer/move_archive:editor",<br />
];<br />
</pre><br />
The privileges listed above means the users given the <code>approve-hat</code> role can see the View, Summary, Details and Move to archive screen as an editor. Note because they cannot edit items [[Standard names |in the buffer]] they can't correct any mistakes they find. However they do have the power to move items to the archive. This means the <code>approve-hat</code> allows a user to see the metadata of an item and if they think it is correct move it to the archive. They cannot return it to the user or edit the metadata themselves.<br />
<br />
The quoting around the role name approve-hat is required, eprints will generate an error if the text is simply {approve-hat}.<br />
<br />
<br />
Tip: Ensure the role is in {roles} not {user_roles}!<br />
<br />
== Anatomy of a privilege ==<br />
Many pre-existing privileges have a specific structure so they can be tested for generically. Privileges on data objects use the dataset ID as the first part of the privilege and the last part as the action that can be carried out on that data object. E.g.<br />
* eprint/view<br />
* user/edit<br />
* saved_search/export<br />
As the eprint data object also has virtual datasets that are subsets of the eprint dataset, based on the status of the eprints these are often used as the second part of the privilege. E.g.<br />
* eprint/archive/view<br />
* eprint/inbox/edit<br />
* eprint/buffer/export<br />
eprint and user data objects can also have an additional modifier to restrict the context in which the privilege permits access:<br />
; eprint/inbox/view&#58;owner<br />
: A user can only view eprints that they own in the user workarea.<br />
; eprint/buffer/edit&#58;editor<br />
: Only users with editorial scope for the eprint can edit it when it is in the review buffer<br />
; user/view&#58;owner<br />
: A user can only view their own user profile.<br />
config privileges are typically use the specfic privilege they give access. E.g.<br />
* config/indexer<br />
* config/regen_abstracts<br />
* config/view<br />
However, ''config/view'' and ''config/edit'' can be specialized to allow specific types of configuration file to be viewed or edited. E.g.<br />
* config/view/phrase<br />
* config/edit/autocomplete<br />
<br />
== Creating a privilege ==<br />
There is no special step to creating a privilege, simply define it where you would like it tested for. Equally, there is no specified format for new privileges tying them to (for example) screens. As a result the following are all valid:<br />
* "eprint/coindoi"<br />
* "eprint/coindoiffff"<br />
* "eprint/coindoi:editor"<br />
However, to make sure the privilege is as intuitive as possible, it is best to stick as closely to the conventions described in "[[#Anatomy of a privilege|Anatomy of a privilege]]".<br />
<br />
==Assigning a role==<br />
Now that you have created a role you want to give that to class of users. To give every regular user of the repository the <code>approve-hat</code> you add it to the list of roles for the user.<br />
<br />
<pre><br />
$c->{user_roles}->{user} = [<br />
'general',<br />
'edit-own-record',<br />
'saved-searches',<br />
'set-password',<br />
'deposit',<br />
'change-email',<br />
'approve-hat',<br />
],<br />
</pre><br />
<br />
Rather than giving every user the role you can give it to individual users. Administer a users profile and add the name of the role to their list of additional roles.<br />
<br />
[[File:Approve-hat.jpg]]<br />
<br />
==Assigning a user privilege==<br />
You do not have to give a user a full role you can give them a privilege. The syntax is slightly different. Add the name of the privilege prefixed with a '+' to the list of roles. You can remove a privilege by prefixing it with a '-'.<br />
<br />
<pre><br />
$c->{user_roles}->{user} = [<br />
'general',<br />
'edit-own-record',<br />
'saved-searches',<br />
'set-password',<br />
'deposit',<br />
'change-email',<br />
'approve-hat',<br />
'+eprint/archive/edit:owner',<br />
],<br />
</pre><br />
<br />
You can also assign privileges to individual users through the web interface in the same way you can assign a role, remembering they will be listed as "roles". (remember the '+' or '-')<br />
<br />
There is no need for users to log in again following a privilege change, eprints will pick it up automatically.<br />
<br />
== See Also ==<br />
* [[Listings of User Roles and Privileges]] - A reference to role and privileges and what they allow a user to do.<br />
* [[User_roles.pl|user_roles.pl]] - Describe the configuration file and how it may be edited/extended to modify/add new roles and privileges.<br />
* [[How to make a Screen for the Admin Section#Making the page appear|Screen plugin visibility]] - Example of making a new Screen Plugin appear using roles.<br />
<br />
[[Category:Manual]]</div>Libjlrshttps://wiki.eprints.org/w/index.php?title=How_to_make_a_Screen_for_the_Admin_Section&diff=15591How to make a Screen for the Admin Section2022-12-14T08:56:29Z<p>Libjlrs: </p>
<hr />
<div>[[Category:Howto]]<br />
[[Category:Plugins]]<br />
[[Category:User Roles]]<br />
Known to work for EPrints 3.2+ <br />
<br />
== The basic structure ==<br />
To make a Screen plugin, you create a Perl Module in <code>[eprints]/archives/<ARCHIVE_ID>/cfg/plugins/EPrints/Plugin/Screen/</code> with the following basic structure<br />
<pre><br />
<br />
package EPrints::Plugin::Screen::Mypackage;<br />
<br />
use EPrints::Plugin::Screen;<br />
<br />
@ISA = ( 'EPrints::Plugin::Screen' );<br />
<br />
use strict;<br />
<br />
sub new<br />
{<br />
my( $class, %params ) = @_;<br />
my $self = $class->SUPER::new(%params);<br />
$self->{priv} = undef;<br />
$self->{appears} = [<br />
{ <br />
place => "admin_actions_editorial", # see notes below<br />
position => 1450, <br />
},<br />
];<br />
return $self;<br />
}<br />
<br />
sub can_be_viewed<br />
{<br />
my( $self ) = @_;<br />
return $self->allow( "my/conf/value" );<br />
}<br />
<br />
sub render<br />
{<br />
my( $self ) = @_;<br />
my $session = $self->{session};<br />
my $user = $session->current_user;<br />
<br />
my $p = $session->make_doc_fragment;<br />
<br />
# create page contents:<br />
my $h = $session->make_element( "h3" );<br />
$h->appendChild($session->make_text( "Look up organisations known to OA-RJ" ));<br />
$p->appendChild($h);<br />
<br />
return $p<br />
}<br />
</pre><br />
<br />
In theory, one should be able to have multiple bits of functionality (view a little, view a lot, edit, etc), simply by testing for different values of <code>$self->allow( "my/conf/value" )</code><br />
<br />
== The locations ==<br />
Where the link for the page appears is defined by <code>$self->{appears}->[''n'']->{place}</code> (in the <code>new</code> function.)<br />
<br />
We are defining a screen that appears in the "admin" area, and there are 4 tabs defined within the admin screen:<br />
* admin_actions_editorial<br />
* admin_actions_system<br />
* admin_actions_config<br />
* admin_actions_misc<br />
<br />
Other places the link can appear are<br />
* unknown to me<br />
<br />
== Making the page appear ==<br />
There are three steps to making a page appear:<br />
<br />
1. The screen plugin should test for ''view-ability''<br />
<pre><br />
# in EPrints::Plugin::Screen::Mypackage<br />
sub can_be_viewed<br />
{<br />
my( $self ) = @_;<br />
return $self->allow( "my/conf/value" );<br />
}<br />
</pre><br />
2 The ''User'' DataObject needs to list the privilege under a role:<br />
<pre><br />
# In EPrints::DataObj::User<br />
foo_bar => [<br />
"my/view/value",<br />
],<br />
foo_baz => [<br />
"my/view/value",<br />
"my/conf/value",<br />
],<br />
</pre><br />
3 The user_roles.pl file needs to make the role available to the user-type:<br />
<pre><br />
# in [eprints]/archive/<ARCHIVE_ID>/cfg/cfg/user_roles.pl<br />
$c->{user_roles}->{user} = [qw{<br />
// truncated<br />
foo_bar<br />
}],<br />
$c->{user_roles}->{admin} = [qw{<br />
// truncated<br />
foo_baz<br />
}],<br />
</pre><br />
<br />
Return to the main [[Screen_Plugins]] page.<br />
<br />
== See Also ==<br />
* [[Listings of User Roles and Privileges]] - A reference to role and privileges and what they allow a user to do.<br />
* [[User_roles.pl|user_roles.pl]] - Describe the configuration file and how it may be edited/extended to modify/add new roles and privileges.</div>Libjlrshttps://wiki.eprints.org/w/index.php?title=User_Roles_and_Privileges&diff=15590User Roles and Privileges2022-12-14T08:51:34Z<p>Libjlrs: </p>
<hr />
<div>This page is intended to provide a useful guide on how [[EPrints Glossary#User role|user roles]] and [[EPrints Glossary#User privilege|privileges]] work within EPrints repository software, expanding on the information already available at [[user_roles.pl]].<br />
<br />
A role in EPrints is made up of 1 or more privileges. Giving a user a role gives them all the privileges associated with that role. You can also give users additional privileges without giving them the full role. <br />
<br />
==Creating a role==<br />
To create the role <code>approve-hat</code> you would do the following:<br />
<pre><br />
$c->{roles}->{"approve-hat"} = [<br />
"eprint/buffer/view:editor",<br />
"eprint/buffer/summary:editor",<br />
"eprint/buffer/details:editor",<br />
"eprint/buffer/move_archive:editor",<br />
];<br />
</pre><br />
The privileges listed above means the users given the <code>approve-hat</code> role can see the View, Summary, Details and Move to archive screen as an editor. Note because they cannot edit items [[Standard names |in the buffer]] they can't correct any mistakes they find. However they do have the power to move items to the archive. This means the <code>approve-hat</code> allows a user to see the metadata of an item and if they think it is correct move it to the archive. They cannot return it to the user or edit the metadata themselves.<br />
<br />
The quoting around the role name approve-hat is required, eprints will generate an error if the text is simply {approve-hat}.<br />
<br />
<br />
Tip: Ensure the role is in {roles} not {user_roles}!<br />
<br />
== Anatomy of a privilege ==<br />
Many pre-existing privileges have a specific structure so they can be tested for generically. Privileges on data objects use the dataset ID as the first part of the privilege and the last part as the action that can be carried out on that data object. E.g.<br />
* eprint/view<br />
* user/edit<br />
* saved_search/export<br />
As the eprint data object also has virtual datasets that are subsets of the eprint dataset, based on the status of the eprints these are often used as the second part of the privilege. E.g.<br />
* eprint/archive/view<br />
* eprint/inbox/edit<br />
* eprint/buffer/export<br />
eprint and user data objects can also have an additional modifier to restrict the context in which the privilege permits access:<br />
; eprint/inbox/view&#58;owner<br />
: A user can only view eprints that they own in the user workarea.<br />
; eprint/buffer/edit&#58;editor<br />
: Only users with editorial scope for the eprint can edit it when it is in the review buffer<br />
; user/view&#58;owner<br />
: A user can only view their own user profile.<br />
config privileges are typically use the specfic privilege they give access. E.g.<br />
* config/indexer<br />
* config/regen_abstracts<br />
* config/view<br />
However, ''config/view'' and ''config/edit'' can be specialized to allow specific types of configuration file to be viewed or edited. E.g.<br />
* config/view/phrase<br />
* config/edit/autocomplete<br />
<br />
== Creating a privilege ==<br />
There is no special step to creating a privilege, simply define it where you would like it tested for. Equally, there is no specified format for new privileges tying them to (for example) screens. As a result the following are all valid:<br />
* "eprint/coindoi"<br />
* "eprint/coindoiffff"<br />
* "eprint/coindoi:editor"<br />
However, to make sure the privilege is as intuitive as possible, it is best to stick as closely to the conventions described in "[[#Anatomy of a privilege|Anatomy of a privilege]]".<br />
<br />
==Assigning a role==<br />
Now that you have created a role you want to give that to class of users. To give every regular user of the repository the <code>approve-hat</code> you add it to the list of roles for the user.<br />
<br />
<pre><br />
$c->{user_roles}->{user} = [<br />
'general',<br />
'edit-own-record',<br />
'saved-searches',<br />
'set-password',<br />
'deposit',<br />
'change-email',<br />
'approve-hat',<br />
],<br />
</pre><br />
<br />
Rather than giving every user the role you can give it to individual users. Administer a users profile and add the name of the role to their list of additional roles.<br />
<br />
[[File:Approve-hat.jpg]]<br />
<br />
==Assigning a user privilege==<br />
You do not have to give a user a full role you can give them a privilege. The syntax is slightly different. Add the name of the privilege prefixed with a '+' to the list of roles. You can remove a privilege by prefixing it with a '-'.<br />
<br />
<pre><br />
$c->{user_roles}->{user} = [<br />
'general',<br />
'edit-own-record',<br />
'saved-searches',<br />
'set-password',<br />
'deposit',<br />
'change-email',<br />
'approve-hat',<br />
'+eprint/archive/edit:owner',<br />
],<br />
</pre><br />
<br />
You can also assign privileges to individual users through the web interface in the same way you can assign a role, remembering they will be listed as "roles". (remember the '+' or '-')<br />
<br />
There is no need for users to log in again following a privilege change, eprints will pick it up automatically.<br />
<br />
== See Also ==<br />
* [[Listings of User Roles and Privileges]] - A reference to role and privileges and what they allow a user to do.<br />
* [[User_roles.pl|user_roles.pl]] - Describe the configuration file and how it may be edited/extended to modify/add new roles and privileges.<br />
* [[How to make a Screen for the Admin Section#Making the page appear|Screen plugin visibility]] - Example of making a new Screen Plugin appear using roles.<br />
<br />
[[Category:Manual]]</div>Libjlrshttps://wiki.eprints.org/w/index.php?title=User_Roles_and_Privileges&diff=15589User Roles and Privileges2022-12-14T08:50:56Z<p>Libjlrs: Additional see-also link</p>
<hr />
<div>This page is intended to provide a useful guide on how [[EPrints Glossary#User role|user roles]] and [[EPrints Glossary#User privilege|privileges]] work within EPrints repository software, expanding on the information already available at [[user_roles.pl]].<br />
<br />
A role in EPrints is made up of 1 or more privileges. Giving a user a role gives them all the privileges associated with that role. You can also give users additional privileges without giving them the full role. <br />
<br />
==Creating a role==<br />
To create the role <code>approve-hat</code> you would do the following:<br />
<pre><br />
$c->{roles}->{"approve-hat"} = [<br />
"eprint/buffer/view:editor",<br />
"eprint/buffer/summary:editor",<br />
"eprint/buffer/details:editor",<br />
"eprint/buffer/move_archive:editor",<br />
];<br />
</pre><br />
The privileges listed above means the users given the <code>approve-hat</code> role can see the View, Summary, Details and Move to archive screen as an editor. Note because they cannot edit items [[Standard names |in the buffer]] they can't correct any mistakes they find. However they do have the power to move items to the archive. This means the <code>approve-hat</code> allows a user to see the metadata of an item and if they think it is correct move it to the archive. They cannot return it to the user or edit the metadata themselves.<br />
<br />
The quoting around the role name approve-hat is required, eprints will generate an error if the text is simply {approve-hat}.<br />
<br />
<br />
Tip: Ensure the role is in {roles} not {user_roles}!<br />
<br />
== Anatomy of a privilege ==<br />
Many pre-existing privileges have a specific structure so they can be tested for generically. Privileges on data objects use the dataset ID as the first part of the privilege and the last part as the action that can be carried out on that data object. E.g.<br />
* eprint/view<br />
* user/edit<br />
* saved_search/export<br />
As the eprint data object also has virtual datasets that are subsets of the eprint dataset, based on the status of the eprints these are often used as the second part of the privilege. E.g.<br />
* eprint/archive/view<br />
* eprint/inbox/edit<br />
* eprint/buffer/export<br />
eprint and user data objects can also have an additional modifier to restrict the context in which the privilege permits access:<br />
; eprint/inbox/view&#58;owner<br />
: A user can only view eprints that they own in the user workarea.<br />
; eprint/buffer/edit&#58;editor<br />
: Only users with editorial scope for the eprint can edit it when it is in the review buffer<br />
; user/view&#58;owner<br />
: A user can only view their own user profile.<br />
config privileges are typically use the specfic privilege they give access. E.g.<br />
* config/indexer<br />
* config/regen_abstracts<br />
* config/view<br />
However, ''config/view'' and ''config/edit'' can be specialized to allow specific types of configuration file to be viewed or edited. E.g.<br />
* config/view/phrase<br />
* config/edit/autocomplete<br />
<br />
== Creating a privilege ==<br />
There is no special step to creating a privilege, simply define it where you would like it tested for. Equally, there is no specified format for new privileges tying them to (for example) screens. As a result the following are all valid:<br />
* "eprint/coindoi"<br />
* "eprint/coindoiffff"<br />
* "eprint/coindoi:editor"<br />
However, to make sure the privilege is as intuitive as possible, it is best to stick as closely to the conventions described in "[[#Anatomy of a privilege|Anatomy of a privilege]]".<br />
<br />
==Assigning a role==<br />
Now that you have created a role you want to give that to class of users. To give every regular user of the repository the <code>approve-hat</code> you add it to the list of roles for the user.<br />
<br />
<pre><br />
$c->{user_roles}->{user} = [<br />
'general',<br />
'edit-own-record',<br />
'saved-searches',<br />
'set-password',<br />
'deposit',<br />
'change-email',<br />
'approve-hat',<br />
],<br />
</pre><br />
<br />
Rather than giving every user the role you can give it to individual users. Administer a users profile and add the name of the role to their list of additional roles.<br />
<br />
[[File:Approve-hat.jpg]]<br />
<br />
==Assigning a user privilege==<br />
You do not have to give a user a full role you can give them a privilege. The syntax is slightly different. Add the name of the privilege prefixed with a '+' to the list of roles. You can remove a privilege by prefixing it with a '-'.<br />
<br />
<pre><br />
$c->{user_roles}->{user} = [<br />
'general',<br />
'edit-own-record',<br />
'saved-searches',<br />
'set-password',<br />
'deposit',<br />
'change-email',<br />
'approve-hat',<br />
'+eprint/archive/edit:owner',<br />
],<br />
</pre><br />
<br />
You can also assign privileges to individual users through the web interface in the same way you can assign a role, remembering they will be listed as "roles". (remember the '+' or '-')<br />
<br />
There is no need for users to log in again following a privilege change, eprints will pick it up automatically.<br />
<br />
== See Also ==<br />
* [[Listings of User Roles and Privileges]] - A reference to role and privileges and what they allow a user to do.<br />
* [[User_roles.pl|user_roles.pl]] - Describe the configuration file and how it may be edited/extended to modify/add new roles and privileges.<br />
* [[How to make a Screen for the Admin Section#Making the page appear|Screen plugin visibility]] - Example of making a new Screen Plugin appear using roles.<br />
[[Category:Manual]]</div>Libjlrshttps://wiki.eprints.org/w/index.php?title=How_to_make_a_Screen_for_the_Admin_Section&diff=15588How to make a Screen for the Admin Section2022-12-14T08:43:48Z<p>Libjlrs: Formatting changes; additional links</p>
<hr />
<div>[[Category:Howto]][[Category:Plugins]]<br />
Known to work for EPrints 3.2+ <br />
<br />
== The basic structure ==<br />
To make a Screen plugin, you create a Perl Module in <code>[eprints]/archives/<ARCHIVE_ID>/cfg/plugins/EPrints/Plugin/Screen/</code> with the following basic structure<br />
<pre><br />
<br />
package EPrints::Plugin::Screen::Mypackage;<br />
<br />
use EPrints::Plugin::Screen;<br />
<br />
@ISA = ( 'EPrints::Plugin::Screen' );<br />
<br />
use strict;<br />
<br />
sub new<br />
{<br />
my( $class, %params ) = @_;<br />
my $self = $class->SUPER::new(%params);<br />
$self->{priv} = undef;<br />
$self->{appears} = [<br />
{ <br />
place => "admin_actions_editorial", # see notes below<br />
position => 1450, <br />
},<br />
];<br />
return $self;<br />
}<br />
<br />
sub can_be_viewed<br />
{<br />
my( $self ) = @_;<br />
return $self->allow( "my/conf/value" );<br />
}<br />
<br />
sub render<br />
{<br />
my( $self ) = @_;<br />
my $session = $self->{session};<br />
my $user = $session->current_user;<br />
<br />
my $p = $session->make_doc_fragment;<br />
<br />
# create page contents:<br />
my $h = $session->make_element( "h3" );<br />
$h->appendChild($session->make_text( "Look up organisations known to OA-RJ" ));<br />
$p->appendChild($h);<br />
<br />
return $p<br />
}<br />
</pre><br />
<br />
In theory, one should be able to have multiple bits of functionality (view a little, view a lot, edit, etc), simply by testing for different values of <code>$self->allow( "my/conf/value" )</code><br />
<br />
== The locations ==<br />
Where the link for the page appears is defined by <code>$self->{appears}->[''n'']->{place}</code> (in the <code>new</code> function.)<br />
<br />
We are defining a screen that appears in the "admin" area, and there are 4 tabs defined within the admin screen:<br />
* admin_actions_editorial<br />
* admin_actions_system<br />
* admin_actions_config<br />
* admin_actions_misc<br />
<br />
Other places the link can appear are<br />
* unknown to me<br />
<br />
== Making the page appear ==<br />
There are three steps to making a page appear:<br />
<br />
1. The screen plugin should test for ''view-ability''<br />
<pre><br />
# in EPrints::Plugin::Screen::Mypackage<br />
sub can_be_viewed<br />
{<br />
my( $self ) = @_;<br />
return $self->allow( "my/conf/value" );<br />
}<br />
</pre><br />
2 The ''User'' DataObject needs to list the privilege under a role:<br />
<pre><br />
# In EPrints::DataObj::User<br />
foo_bar => [<br />
"my/view/value",<br />
],<br />
foo_baz => [<br />
"my/view/value",<br />
"my/conf/value",<br />
],<br />
</pre><br />
3 The user_roles.pl file needs to make the role available to the user-type:<br />
<pre><br />
# in [eprints]/archive/<ARCHIVE_ID>/cfg/cfg/user_roles.pl<br />
$c->{user_roles}->{user} = [qw{<br />
// truncated<br />
foo_bar<br />
}],<br />
$c->{user_roles}->{admin} = [qw{<br />
// truncated<br />
foo_baz<br />
}],<br />
</pre><br />
<br />
Return to the main [[Screen_Plugins]] page.<br />
<br />
== See Also ==<br />
* [[Listings of User Roles and Privileges]] - A reference to role and privileges and what they allow a user to do.<br />
* [[User_roles.pl|user_roles.pl]] - Describe the configuration file and how it may be edited/extended to modify/add new roles and privileges.</div>Libjlrshttps://wiki.eprints.org/w/index.php?title=Contribute:_Plugins/ImportPluginsAWS&diff=13795Contribute: Plugins/ImportPluginsAWS2021-05-24T11:13:59Z<p>Libjlrs: Code formatting</p>
<hr />
<div>[[Category:Contribute]]<br />
[[Category:Plugins]]<br />
= Import Plugin Tutorial 2: Amazon Web Services =<br />
<br />
In the [[Contribute:_Plugins/ImportPluginsCSV|last tutorial]] we created an import plugin that took data which needed very little modification to import into the respository. The column names in the [http://en.wikipedia.org/wiki/Comma-Separated_Values CSV] file matched the names of metadata fields present in the repository. In this tutorial we'll look at importing data that needs some modification to be imported, needs more error checking and is obtained in a different way.<br />
<br />
We will be using Amazon's E-Commerce Webservice to import books from their website into our respository given a list of [http://en.wikipedia.org/wiki/ASIN ASIN].<br />
<br />
We will be accessing the service using a [http://en.wikipedia.org/wiki/REST REST] approach, communicating with the server using URL parameters and retrieving an XML document in response to our request. It is also possible to access their services using [http://en.wikipedia.org/wiki/SOAP SOAP], but that will not be discussed here.<br />
<br />
= Before You Start =<br />
<br />
== Amazon Web Services ==<br />
To use Amazon's web services you must first signup for an account [http://aws.amazon.com here]. Their site has extensive documentation on the services that they offer as well as example programs including some written in Perl.<br />
<br />
== Required Modules ==<br />
To prepare for this tutorial you should make sure the [http://search.cpan.org/~gaas/libwww-perl-5.805/lib/LWP/UserAgent.pm LWP::UserAgent] module is installed. The following command as root, or using sudo should work.<br />
<br />
<pre><br />
cpan LWP::UserAgent<br />
</pre><br />
<br />
= AWS.pm = <br />
The code in the section below should be placed in a file called CSV.pm in the directory created previously, and MyPlugins should be changed to the name of that directory.<br />
<br />
<syntaxhighlight lang="perl"><br />
package EPrints::Plugin::Import::MyPlugins::AWS;<br />
<br />
use EPrints::Plugin::Import::TextFile;<br />
use strict;<br />
use URI::Escape;<br />
<br />
our @ISA = ('EPrints::Plugin::Import::TextFile');<br />
<br />
my $endpoint = 'http://ecs.amazonaws.co.uk/onca/xml';<br />
my $accesskey = '<YOURAMAZONWSKEY>';<br />
my $service = 'AWSECommerceService';<br />
my $operation = 'ItemLookup';<br />
my $version = '2007-07-16';<br />
my $responsegroup = 'Large';<br />
<br />
sub new<br />
{<br />
my( $class, %params ) = @_;<br />
my $self = $class->SUPER::new( %params );<br />
<br />
$self->{name} = 'AWS';<br />
$self->{visible} = 'all';<br />
$self->{produce} = [ 'list/eprint' , 'dataobj/eprint'];<br />
<br />
my $rc = EPrints::Utils::require_if_exists('LWP::UserAgent');<br />
unless ($rc)<br />
{<br />
$self->{visible} = '';<br />
$self->{error} = 'Unable to load required module LWP::UserAgent';<br />
}<br />
<br />
return $self;<br />
}<br />
<br />
sub input_fh<br />
{<br />
my( $plugin, %opts ) = @_;<br />
my @ids;<br />
my $fh = $opts{fh};<br />
<br />
my @records = <$fh>;<br />
foreach my $input_data (@records)<br />
{<br />
my $epdata = $plugin->convert_input($input_data);<br />
next unless defined $epdata;<br />
<br />
my $dataobj = $plugin->epdata_to_dataobj($opts{dataset},$epdata);<br />
if( defined $dataobj )<br />
{<br />
push @ids, $dataobj->get_id;<br />
}<br />
}<br />
<br />
return EPrints::List->new(<br />
dataset => $opts{dataset},<br />
session => $plugin->{session},<br />
ids=>\@ids );<br />
}<br />
<br />
sub convert_input<br />
{<br />
my ($plugin, $input) = @_;<br />
my %output = ();<br />
<br />
$input =~ m/([A-Za-z0-9]+)/;<br />
$input = $1;<br />
<br />
my $request =<br />
"$endpoint?".<br />
"Service=$service&".<br />
"AWSAccessKeyId=$accesskey&".<br />
"Operation=$operation&".<br />
"ItemId=$input&".<br />
"Version=$version&".<br />
"ResponseGroup=$responsegroup";<br />
<br />
my $ua = LWP::UserAgent->new;<br />
$ua->timeout(30);<br />
my $response = $ua->get($request);<br />
<br />
my $dom = EPrints::XML::parse_xml_string($response->content);<br />
<br />
my $rep =<br />
$dom->getElementsByTagName('Items')->item(0)-><br />
getElementsByTagName('Request')->item(0);<br />
<br />
my $reptext =<br />
EPrints::Utils::tree_to_utf8($rep->getElementsByTagName('IsValid')->item(0));<br />
<br />
unless ($reptext eq 'True') <br />
{<br />
$plugin->error('Invalid AWS Request');<br />
return undef;<br />
}<br />
<br />
#Get Item Object<br />
my $item =<br />
$dom->getElementsByTagName('Items')->item(0)-><br />
getElementsByTagName('Item')->item(0);<br />
<br />
unless (defined $item) <br />
{<br />
$plugin->error('No Item element found');<br />
return undef;<br />
}<br />
<br />
my $attr = $item->getElementsByTagName('ItemAttributes')->item(0);<br />
<br />
my $pg = EPrints::Utils::tree_to_utf8($attr->getElementsByTagName('ProductGroup')->item(0));<br />
<br />
unless ($pg eq 'Book') <br />
{<br />
$plugin->error('Product is not a book.');<br />
return undef;<br />
}<br />
<br />
$output{type} = 'book';<br />
$output{refereed} = 'FALSE';<br />
$output{ispublished} = 'pub';<br />
<br />
my $title = $attr->getElementsByTagName('Title')->item(0);<br />
$output{title} = EPrints::Utils::tree_to_utf8($title);<br />
<br />
my $url = $item->getElementsByTagName('DetailPageURL')->item(0);<br />
$output{official_url} = uri_unescape(EPrints::Utils::tree_to_utf8($url));<br />
<br />
my $isbn = $attr->getElementsByTagName('ISBN')->item(0);<br />
if (defined $isbn)<br />
{<br />
$output{isbn} = EPrints::Utils::tree_to_utf8($isbn);<br />
}<br />
<br />
my $pages = $attr->getElementsByTagName('NumberOfPages')->item(0);<br />
if (defined $pages)<br />
{<br />
$output{pages} = EPrints::Utils::tree_to_utf8($pages);<br />
}<br />
<br />
my $publisher = $attr->getElementsByTagName('Publisher')->item(0);<br />
if (defined $publisher)<br />
{<br />
$output{publisher} = EPrints::Utils::tree_to_utf8($publisher);<br />
}<br />
<br />
my $pubdate = $attr->getElementsByTagName('PublicationDate')->item(0);<br />
if (defined $pubdate)<br />
{<br />
$output{date} = EPrints::Utils::tree_to_utf8($pubdate);<br />
}<br />
<br />
return \%output;<br />
}<br />
<br />
1;<br />
</syntaxhighlight><br />
<br />
= In More Detail =<br />
We will use the URI::Escape module in this plugin. As it is included with EPrints we don't need to check if it exists first.<br />
<pre><br />
use URI::Escape;<br />
</pre><br />
<br />
Here we setup a number of values for parameters that will be part of our web service requests. The endpoint variable determines which server will be sent the request. Here we have used the UK server, but by changing the [http://en.wikipedia.org/wiki/TLD TLD] we can use the US, Canadian, German or French servers.<br />
<br />
The accesskey variable stores the access key you will have gained from signing up to Amazon earlier. You should use the normal access key and not the secret one.<br />
<br />
Here we use the ItemLookup operation of the AWSECommerceService with the 2007-07-16 version of the API. Other operations allow searching for items, but here we want to look up specific products. Finally the variable responsegroup determines the amount and nature of the information returned, we select "Large" in this case, which gives us more information about the item.<br />
<br />
<pre><br />
my $endpoint = 'http://ecs.amazonaws.co.uk/onca/xml';<br />
my $accesskey = '<YOURAMAZONWSKEY>';<br />
my $service = 'AWSECommerceService';<br />
my $operation = 'ItemLookup';<br />
my $version = '2007-07-16';<br />
my $responsegroup = 'Large';<br />
</pre><br />
<br />
== Constructor ==<br />
The constructor is similar to the one used for the [Contribute:_Plugins/ImportPluginsCSV CSV plugin], except this one will import individual eprints, given an [http://en.wikipedia.org/wiki/ASIN ASIN].<br />
<pre><br />
$self->{produce} = [ 'list/eprint' , 'dataobj/eprint'];<br />
</pre><br />
<br />
Like we imported Text::CSV in the [Contribute:_Plugins/ImportPluginsCSV last tutorial], here we import LWP::UserAgent which will be used for making requests to the web service.<br />
<pre><br />
my $rc = EPrints::Utils::require_if_exists('LWP::UserAgent');<br />
unless ($rc)<br />
{<br />
$self->{visible} = '';<br />
$self->{error} = 'Unable to load required module LWP::UserAgent';<br />
}<br />
</pre><br />
<br />
== Input ==<br />
=== input_fh ===<br />
This method is similar to the one used in the [Contribute:_Plugins/ImportPluginsCSV CSV plugin], but doesn't have to do quite so much work.<br />
<br />
First we create the array to hold our imported eprint ids.<br />
<pre><br />
my @ids;<br />
</pre><br />
<br />
Next we read all the lines in the supplied file handle into our records array.<br />
<pre><br />
my $fh = $opts{fh};<br />
<br />
my @records = <$fh>;<br />
</pre><br />
<br />
Then we iterate over each record, running convert_input on it, importing it into our repository and adding the id to our array.<br />
<pre><br />
foreach my $input_data (@records)<br />
{<br />
my $epdata = $plugin->convert_input($input_data);<br />
next unless defined $epdata;<br />
<br />
my $dataobj = $plugin->epdata_to_dataobj($opts{dataset},$epdata);<br />
if( defined $dataobj )<br />
{<br />
push @ids, $dataobj->get_id;<br />
}<br />
}<br />
</pre><br />
<br />
Then we return a List object of the items imported.<br />
<pre><br />
return EPrints::List->new(<br />
dataset => $opts{dataset},<br />
session => $plugin->{session},<br />
ids=>\@ids );<br />
</pre><br />
<br />
=== convert_input ===<br />
<br />
[http://en.wikipedia.org/wiki/ASIN ASINs] are strings which identify a product. Here we remove any non-alphanumerical characters which are surrounding the [http://en.wikipedia.org/wiki/ASIN ASIN].<br />
<pre><br />
$input =~ m/([A-Za-z0-9]+)/;<br />
$input = $1;<br />
</pre><br />
<br />
We form the request from the variables we created earlier and the [http://en.wikipedia.org/wiki/ASIN ASIN] we have just obtained.<br />
<pre><br />
my $request =<br />
"$endpoint?".<br />
"Service=$service&".<br />
"AWSAccessKeyId=$accesskey&".<br />
"Operation=$operation&".<br />
"ItemId=$input&".<br />
"Version=$version&".<br />
"ResponseGroup=$responsegroup";<br />
</pre><br />
<br />
We now send the request, by creating a new LWP::UserAgent object, setting its timeout to 30 seconds and then performing the request using HTTP GET.<br />
<pre><br />
my $ua = LWP::UserAgent->new;<br />
$ua->timeout(30);<br />
my $response = $ua->get($request);<br />
</pre><br />
<br />
We then create a [http://en.wikipedia.org/wiki/Document_Object_Model DOM] object from the XML document returned.<br />
<pre><br />
my $dom = EPrints::XML::parse_xml_string($response->content);<br />
</pre><br />
<br />
Each request contains an Items element within the root element of the document which contains a Request element. This element contains an element IsValid. This element will contain the value True or False depending on whether a valid request was made or not.<br />
<br />
Here we obtain the Request element and check that the IsValid element within it contains the value True. If it doesn't we call the error method and return undef.<br />
<pre><br />
my $rep =<br />
$dom->getElementsByTagName("Items")->item(0)-><br />
getElementsByTagName('Request')->item(0);<br />
<br />
my $reptext =<br />
EPrints::Utils::tree_to_utf8($rep->getElementsByTagName('IsValid')->item(0));<br />
<br />
unless ($reptext eq 'True') <br />
{<br />
$plugin->error('Invalid AWS Request');<br />
return undef;<br />
}<br />
</pre><br />
<br />
The product found with the ItemLookup method is contained within an Item element within the Items element. Here we attempt to get that element and raise the error and return undef if we can't.<br />
<pre><br />
my $item =<br />
$dom->getElementsByTagName('Items')->item(0)-><br />
getElementsByTagName('Item')->item(0);<br />
<br />
unless (defined $item) <br />
{<br />
$plugin->error('No Item element found');<br />
return undef;<br />
}<br />
</pre><br />
<br />
Each item contains an ItemAttributes element which contains most of the metadata about an item.<br />
<pre><br />
my $attr = $item->getElementsByTagName('ItemAttributes')->item(0);<br />
</pre><br />
<br />
For some specialised repositories it might make sense to import DVDs, computer games and electronic equipment, but we're just going to deal with books. The ProductGroup element within the ItemAttributes element tells you what sort of item we're dealing with. We're looking for the value 'Book'.<br />
<pre><br />
my $pg = EPrints::Utils::tree_to_utf8($attr->getElementsByTagName('ProductGroup')->item(0));<br />
<br />
unless ($pg eq 'Book') <br />
{<br />
$plugin->error('Product is not a book.');<br />
return undef;<br />
}<br />
</pre><br />
<br />
Here we set a few fields without consulting the imported data. We know this is a book, so we set the type. We assume that it has not been refereed. We also assume it has been published, because we can buy it. <br />
<pre><br />
$output{type} = 'book';<br />
$output{refereed} = 'FALSE';<br />
$output{ispublished} = 'pub';<br />
</pre><br />
<br />
We get and set the title.<br />
<pre><br />
my $title = $attr->getElementsByTagName('Title')->item(0);<br />
$output{title} = EPrints::Utils::tree_to_utf8($title);<br />
</pre><br />
<br />
Here we set the official URL to the Amazon product page. We have to do a bit of extra work using the uri_unescape method from the URI::Escape package to convert URI escape codes into characters.<br />
<pre><br />
my $url = $item->getElementsByTagName('DetailPageURL')->item(0);<br />
$output{official_url} = uri_unescape(EPrints::Utils::tree_to_utf8($url));<br />
</pre><br />
<br />
We can set the [http://en.wikipedia.org/wiki/ISBN ISBN]. Note that the [http://en.wikipedia.org/wiki/ISBN ISBN] is often the same as the [http://en.wikipedia.org/wiki/ASIN ASIN].<br />
<pre><br />
my $isbn = $attr->getElementsByTagName('ISBN')->item(0);<br />
if (defined $isbn)<br />
{<br />
$output{isbn} = EPrints::Utils::tree_to_utf8($isbn);<br />
}<br />
</pre><br />
<br />
We can set the number of pages.<br />
<pre><br />
my $pages = $attr->getElementsByTagName('NumberOfPages')->item(0);<br />
if (defined $pages)<br />
{<br />
$output{pages} = EPrints::Utils::tree_to_utf8($pages);<br />
}<br />
</pre><br />
<br />
We can set the publisher.<br />
<pre><br />
my $publisher = $attr->getElementsByTagName('Publisher')->item(0);<br />
if (defined $publisher)<br />
{<br />
$output{publisher} = EPrints::Utils::tree_to_utf8($publisher);<br />
}<br />
</pre><br />
<br />
We can set the publication date and finally return our output hash.<br />
<pre><br />
my $pubdate = $attr->getElementsByTagName('PublicationDate')->item(0);<br />
if (defined $pubdate)<br />
{<br />
$output{date} = EPrints::Utils::tree_to_utf8($pubdate);<br />
}<br />
<br />
return \%output;<br />
</pre><br />
<br />
= Testing Your Plugin =<br />
After restarting your webserver go to the Import Items screen from the Manage Deposits screen. If you can't find this, make sure you're logged in.<br />
<br />
We'll start by collecting a few ASINS. Go to [http://www.amazon.co.uk Amazon] and pick a few books. The URL for each project page is in the form http://www.amazon.co.uk/Combination-of-title-an-author/dp/ASIN... Collect a few different ASINS.<br />
<br />
Now we'll demonstrate importing from Amazon with a few sample ASINs.<br />
Type this into the "Cut and Paste Records" box:<br />
<pre><br />
0946719616<br />
0297843877<br />
</pre><br />
<br />
Select "AWS" from the Select import format drop down menu and click "Test Run + Import". You should end up at the Manage Deposits screen with the following message being displayed "Import completed: 2 item(s) imported.".</div>Libjlrshttps://wiki.eprints.org/w/index.php?title=Frequently_Asked_Questions&diff=13787Frequently Asked Questions2021-05-21T11:19:21Z<p>Libjlrs: Source formatting</p>
<hr />
<div>[[Category:FAQ]]<br />
[[Category:Management]]<br />
[[Category: Out of Date]]<br />
[[Category: Obsolete]]<br />
<br />
This all needs sorting out, it's just being grabbed from the old wiki for now.<br />
<br />
* [[Copyright and License FAQ]]<br />
* [[Metadata FAQ]]<br />
* [[Searching FAQ]]<br />
* [[OAI FAQ]]<br />
* [[How much will it cost?]]<br />
<br />
== What operating systems can we use? ==<br />
<br />
EPrints should work on any Linux operating system. We use Ubuntu (Debian) and Redhat Enterprise Linux.<br />
<br />
Running EPrints on Microsoft Windows is possible but strongly not recommended. It can be very difficult to get all the necessary dependencies in place. If you want to get EPrints running but do not have as computer running a Linux operating system. You could install [https://www.virtualbox.org/wiki/Downloads VirtualBox] and then create a Ubuntu or Redhat "virtual machine" (VM) to run on top of your Windows operating system. Alternatively, you could install [https://docs.docker.com/docker-for-windows/install/ Docker Desktop for Windows] and [[Installing EPrints using Docker|install EPrints using Docker]]. However, both these methods are only recommended for testing or demoing EPrints. If you intend to run EPrints long-term you should install on a dedicated Linux server or virtual machine.<br />
<br />
== What computer do we need? ==<br />
Any modern physical PC (server or desktop) or a virtual machine should be more than capable of running EPrints. A suggested minimum specification for running a live service:<br />
* 2GB RAM <br />
* 20GB disk space<br />
* 100Mb/s network speed<br />
<br />
== How much will it cost to set up? ==<br />
<br />
Most of the costs are staff time. Equipment costs are a PC, an internet connection and a BACKUP STRATEGY. Please remember to budget for backups.<br />
<br />
EPrints, and all the other software required to make it work, are available for no cost. At some point in the future EPrints may offer some pay-services, but the core software will remain zero cost and freely available to all.<br />
<br />
See [[How much will it cost?]]<br />
<br />
== How much disk space will we need? ==<br />
The main usage of disk space will be the uploaded files for the publications, (e.g. PDF, Word documents, etc.). On average an eprint item will have associated files (e.g. uploaded PDF and thumbnail and preview images of that PDF) that take up 2MB of disk space. So for every extra 500 eprint items you will need an extra 1GB of disk. However, if you intend to upload lots of videos, images, are large documents, then this requirement will be higher. On top of the space needed for uploaded documents and associated files you will need approximately 5GB for installing the operating system. The disk space required by the database is difficult to determine, as this is dependent on a number of different factors but 1MB per eprint item.<br />
=== Example usage requirements ===<br />
* Small repository: 1000 eprint items<br />
** Operating system: 5GB<br />
** Upload and associated files: 2MB x 1000 = 2GB<br />
** Database: 1MB x 1000 = 1GB<br />
** '''TOTAL:''' 8GB (15GB to give room for expansion)<br />
* Medium-sized repository: 10,000 eprint items<br />
** Operating system: 5GB<br />
** Upload and associated files: 2MB x 10,000 = 20GB<br />
** Database: 1MB x 10,000 = 10GB<br />
** '''TOTAL:''' 35GB (50GB to give room for expansion)<br />
* Large repository: 100,000 eprint items<br />
** Operating system: 5GB<br />
** Upload and associated files: 2MB x 10,000 = 200GB<br />
** Database: 1MB x 10,000 = 100GB<br />
** '''TOTAL:''' 305GB (350-400GB to give room for expansion)<br />
<br />
== Is it possible when depositing a document, to just point to an "alternative location" rather than have the full text copied and held in the eprint archive? ==<br />
<br />
Yes, and to suppress the normal warning about no documents attached look in '''[archive_root]/cfg/cfg.d/eprint_warnings.pl'''.<br />
<br />
== I need to run apache as a user other than "eprints", what do I do to make EPrints work in this situation? ==<br />
<br />
Example, apache is running as user "apache".<br />
* Make all the eprints files owned by "apache" instead of "eprints"<br />
* Edit SystemSettings?.pm to tell eprints to run as user "apache"<br />
* You'll need to run all command line scripts as user "apache"<br />
* All eprints cron jobs should be owned by user "apache" <br />
<br />
If you are installing a new copy of eprints, you can specify the user and group to use when you run 'configure'. Do<br />
<syntaxhighlight lang="bash"><br />
./configure --help <br />
</syntaxhighlight><br />
for details.<br />
<br />
== How do I get the body HTML of a page without the template around it? ==<br />
This is handy for dynamically linking EPrints content into other sites.<br />
<br />
For "view" pages you need to add the option <code>include=>1</code> to the view configuration. This will cause generate_views to make a ''.include'' page in addition to the ''.html'' page. The ''.include'' page will have no template around it.<br />
<br />
For dynamic pages, those under ''/cgi/'', you can add the cgi parameter <code>mainonly=yes</code>. E.g. <code>http://tryme.demo.eprints-hosting.org/cgi/latest?mainonly=yes</code><br />
<br />
== How do I get statistics on number of deposits per month? ==<br />
<br />
This rather grim bit of SQL should work, although datestamp is the last modified date, not the submission OR creation date, it should still give a good indication.<br />
<syntaxhighlight lang="sql"><br />
select count(*), year(datestamp), month(datestamp)<br />
from archive<br />
group by year(datestamp),month(datestamp)<br />
order by year(datestamp),month(datestamp);<br />
</syntaxhighlight><br />
<br />
== I've edited the template (or other config file) but nothing seems to have changed - why? ==<br />
<br />
While EPrints tries to automatically reload when a configuration file is changed you may need to reload the Web server for changes to take effect. See also the [[API:bin/epadmin|epadmin reload]], the [[API:bin/generate_static|generate_static]] and [[API:bin/generate_views|generate_views]] commands.<br />
<br />
= Installation Related Questions =<br />
<br />
== When running a script I get the error; "Insecure dependency in mkdir while running with -T switch" ==<br />
<br />
This usually indicates you are running an eprints script as root. Don't do that; become user 'eprints' instead.<br />
<br />
== title and fulltext search returns no results, but date search does ==<br />
<br />
The indexer daemon is probably not running or is not working correctly, see [[API:bin/indexer]].<br />
<br />
== I don't want to give epadmin my mysql root password. What is the alternative? ==<br />
<syntaxhighlight lang="sql"><br />
mysql> CREATE DATABASE myrepo;<br />
Query OK, 1 row affected (0.06 sec)<br />
<br />
mysql> GRANT ALL PRIVILEGES ON myrepo.* TO myrepo@localhost IDENTIFIED BY 'secret';<br />
Query OK, 0 rows affected (0.52 sec)<br />
</syntaxhighlight><br />
<br />
Then provide the database name, user name and password to the '''[[API:bin/epadmin|epadmin]] create''' command.<br />
<br />
== How do I get a value for a field of an eprint (without using any SQL)? ==<br />
<br />
(assuming the eprint is in the main archive, and has eprintid number 23)<br />
<br />
<syntaxhighlight lang="perl"><br />
my $ds = $repo->dataset( "eprint" );<br />
my $eprint = $ds->dataobj( 23 );<br />
my $value = $eprint->value( "editors" );<br />
</syntaxhighlight><br />
<br />
See [[API:EPrints/DataObj]].<br />
<br />
== How can I get a utf8 string of the name of a subject, given its subjectid? ==<br />
<br />
<syntaxhighlight lang="perl"><br />
sub get_subject_name_string<br />
{<br />
my( $session, $subjectid ) = @_;<br />
my $subj = EPrints::Subject->new( $session, $subjectid ); <br />
if( !defined $subj ) <br />
{<br />
return "errer, unknown subject: $subjectid";<br />
}<br />
return EPrints::Utils::tree_to_utf8( $subj->render_description() );<br />
}<br />
</syntaxhighlight></div>Libjlrshttps://wiki.eprints.org/w/index.php?title=Setting_up_HTTPS_using_Let%27s_Encrypt&diff=13786Setting up HTTPS using Let's Encrypt2021-05-21T11:15:10Z<p>Libjlrs: </p>
<hr />
<div>{{Manual}}<br />
By default EPrints does not come setup to use HTTPS. This is because you need to generate a SSL certificate and if this is not signed by a known Certificate Authority a user's web browser is likely to complain vigorously. In the past it has typically costed a fair amount of money to obtain a SSL certificate from your hosting provider. However, now there is [https://letsencrypt.org/ Let's Encrypt] it is possible to get a certificate for free. This is not to say you should use Let's Encrypt in all cases. UK academic institutions should continue to obtain their SSL certificates through Jisc and other institutions/organisations may already have similar arrangements for obtaining SSL certificates.<br />
<br />
As well as being free, Let's Encrypt has an automated way for renewing certificates. However, it should be noted that the length of its certificates is a lot shorter at just 3 months. As the renewal process is automatic, this time period is more appropriate to maximise security. Let's Encrypt's certificate generation requires your EPrints repository to be publicly accessible. Beneath are instructions on how to set up EPrints to enable HTTPS with a Let's Encrypt certificate.<br />
<br />
1. Go to the https://certbot.eff.org/ and follow the instructions for your web server and operating system (the former will almost always be Apache) and follow the instructions provided.<br />
<br />
2. When you get to the point of running the certbot command you want the certificate only so should type as the root user:<br />
<br />
<syntaxhighlight lang="bash"><br />
certbot --apache certonly<br />
</syntaxhighlight><br />
<br />
3. Take a note of the path to were your certificate, key and CA chain have been saved. This will probably be something like<br />
<br />
<syntaxhighlight lang="bash"> <br />
/etc/letsencrypt/live/YOUR-REPOSITORY-DOMAIN/<br />
</syntaxhighlight><br />
<br />
4. If you have not already done so, create an directory called <tt>ssl</tt> inside your archive's directory, i.e.<br />
<br />
<syntaxhighlight lang="bash"><br />
mkdir EPRINTS_PATH/archives/REPOID/ssl/<br />
</syntaxhighlight><br />
<br />
5. Create a file inside the new ssl directory called <tt>securevhost.conf</tt> and include the following contents, amending the <tt>ServerName</tt>, <tt>SSLCertificateFile</tt>, <tt>SSLCertificateKeyFile</tt> <tt>SSLCertificateChainFile</tt> and <tt>Include</tt> as appropriate at least. You will note that this configuration also enables [https://en.wikipedia.org/wiki/HTTP_Strict_Transport_Security HTTP Strict Transport Security (HSTS)] for additional security. This ensures that after the first time you visit HTTPS for a particular site in your web browser, all future HTTP requests for this hostname will automatically be converted by your browser to HTTPS.<br />
<br />
<syntaxhighlight lang="apache"><br />
<VirtualHost *:443><br />
<br />
ServerName YOUR-REPOSITORY-DOMAIN:443<br />
<br />
# Enable HSTS<br />
Header always set Strict-Transport-Security "max-age=63072000;"<br />
<br />
SSLEngine on<br />
SSLProtocol all -SSLv2 -SSLv3<br />
SSLHonorCipherOrder on<br />
SSLCipherSuite HIGH:!aNULL:!eNULL:!kECDH:!aDH:!RC4:!3DES:!CAMELLIA:!MD5:!PSK:!SRP:!KRB5:@STRENGTH<br />
<br />
SSLCertificateFile /etc/letsencrypt/live/YOUR-REPOSITORY-DOMAIN/cert.pem<br />
SSLCertificateKeyFile /etc/letsencrypt/live/YOUR-REPOSITORY-DOMAIN/privkey.pem<br />
SSLCertificateChainFile /etc/letsencrypt/live/YOUR-REPOSITORY-DOMAIN/chain.pem<br />
<br />
SetEnvIf User-Agent ".*MSIE.*" \<br />
nokeepalive ssl-unclean-shutdown \<br />
downgrade-1.0 force-response-1.0<br />
<br />
LogLevel warn<br />
ErrorLog logs/ssl_error_log <br />
TransferLog logs/ssl_access_log<br />
CustomLog logs/ssl_request_log \<br />
"%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"<br />
<br />
Include EPRINTS_PATHH/cfg/apache_ssl/REPOID.conf<br />
<br />
PerlTransHandler +EPrints::Apache::Rewrite<br />
<br />
</VirtualHost><br />
</syntaxhighlight><br />
<br />
6. If you have not already done so, add a configuration file at <tt>/opt/eprints3/archives/REPOID/cfg/cfg.d/https.pl</tt> with the following configuration:<br />
<br />
<syntaxhighlight lang="perl"><br />
$c->{securehost} = $c->{host};<br />
$c->{secureport} = 443;<br />
$c->{http_root} = undef;<br />
</syntaxhighlight><br />
<br />
7. Now you will need to regenerate the rest of your Apache configuration for EPrints with the following command run as the EPrints user. (Substitute the path as appropriate):<br />
<br />
<syntaxhighlight lang="bash"><br />
/opt/eprints3/bin/generate_apacheconf --system --replace<br />
</syntaxhighlight><br />
<br />
8. Apache will not yet have been setup to include the Apache configuration file you created in step 5. To include this, you will need to edit the file in your Apache configuration directory (<tt>/etc/httpd/</tt> on RHEL/CentOS/Fedora and <tt>/etc/apache2/</tt> on Debian/Ubuntu) and find the file that contains the line <tt>cfg/apache.conf</tt>, e.g.<br />
<br />
<syntaxhighlight lang="bash"><br />
cd /etc/httpd/<br />
grep -r "cfg/apache.conf" *<br />
</syntaxhighlight><br />
<br />
9. Once you have found it you will need to edit it and add the following line, changing the path as appropriate:<br />
<br />
<syntaxhighlight lang="apache"><br />
Include EPRINTS_PATH/archives/REPOID/ssl/securevhost.conf<br />
</syntaxhighlight><br />
<br />
10. Now, (as root or using sudo) test that the Apache configuration is correct and fix any issues if necessary:<br />
<br />
<syntaxhighlight lang="bash"><br />
apachectl configtest<br />
</syntaxhighlight><br />
<br />
11. Restart Apache and check whether you can access your EPrints repository using HTTPS in a web browser:<br />
<br />
<syntaxhighlight lang="bash"><br />
apachectl restart<br />
</syntaxhighlight><br />
<br />
12. If the guide on cerbot.eff.org you used in step 1 tells you to to setup a cron job then follow those instructions. The easiest way to do this is probably to run <tt>crontab -e</tt> as root and add the following cron job, substituting the minute (43) and hours (6,18) for you own choice maintaining a 12 hour gap between the hours:<br />
<br />
<syntaxhighlight lang="bash"><br />
43 6,18 * * * certbot renew<br />
</syntaxhighlight><br />
<br />
== Additional Notes ==<br />
<br />
The default EPrints Apache Rewrite handler declines any requests to a URL containing <code>/.</code>.<br />
<br />
This means that the challenge/response for a LetsEncrypt certificate renewal that uses the <code>/.well-known/acme-challenge/</code> path will fail.<br />
<br />
To make this work you could add a location block to your Apache config, to ensure the <code>/.well-known/</code> are not handled by EPrints, or use an EPrints URL rewrite trigger to handle the request:<br />
<br />
<syntaxhighlight lang="perl"><br />
#this could be saved into e.g. [EPRINTS_ROOT]/lib/cfg.d/z_rewrite_url_LetsEncrypt.pl<br />
<br />
# import Apache constant e.g. 'OK'<br />
use EPrints::Apache::AnApache;<br />
<br />
$c->add_trigger( EP_TRIGGER_URL_REWRITE, sub {<br />
my( %o ) = @_;<br />
<br />
# if the incoming request matches the LetsEncrypt challenge URL...<br />
if( $o{uri} =~ m!^${o{urlpath}}/\.well-known/acme-challenge/! )<br />
{<br />
# and the LetsEncrypt renewal process has put the file in EPRINTS_ROOT/archives/ARCHIVEID/html/.well-known/acme-challenge/<br />
if( -f $o{repository}->get_conf( "htdocs_path" ).$o{uri} )<br />
{<br />
# reply with an HTTP '200' <br />
${$o{return_code}} = OK;<br />
# and return the file reqested<br />
$o{request}->filename( $o{repository}->get_conf( "htdocs_path" ).$o{uri} );<br />
}<br />
# and say that we've handled the request - so no more triggers should be run.<br />
return EP_TRIGGER_DONE;<br />
}<br />
} );<br />
</syntaxhighlight></div>Libjlrshttps://wiki.eprints.org/w/index.php?title=Setting_up_HTTPS_using_Let%27s_Encrypt&diff=13785Setting up HTTPS using Let's Encrypt2021-05-21T11:12:34Z<p>Libjlrs: </p>
<hr />
<div>{{Manual}}<br />
By default EPrints does not come setup to use HTTPS. This is because you need to generate a SSL certificate and if this is not signed by a known Certificate Authority a user's web browser is likely to complain vigorously. In the past it has typically costed a fair amount of money to obtain a SSL certificate from your hosting provider. However, now there is [https://letsencrypt.org/ Let's Encrypt] it is possible to get a certificate for free. This is not to say you should use Let's Encrypt in all cases. UK academic institutions should continue to obtain their SSL certificates through Jisc and other institutions/organisations may already have similar arrangements for obtaining SSL certificates.<br />
<br />
As well as being free, Let's Encrypt has an automated way for renewing certificates. However, it should be noted that the length of its certificates is a lot shorter at just 3 months. As the renewal process is automatic, this time period is more appropriate to maximise security. Let's Encrypt's certificate generation requires your EPrints repository to be publicly accessible. Beneath are instructions on how to set up EPrints to enable HTTPS with a Let's Encrypt certificate.<br />
<br />
1. Go to the https://certbot.eff.org/ and follow the instructions for your web server and operating system (the former will almost always be Apache) and follow the instructions provided.<br />
<br />
2. When you get to the point of running the certbot command you want the certificate only so should type as the root user:<br />
<br />
<syntaxhighlight lang="bash"><br />
certbot --apache certonly<br />
</syntaxhighlight><br />
<br />
3. Take a note of the path to were your certificate, key and CA chain have been saved. This will probably be something like<br />
<br />
<syntaxhighlight lang="bash"> <br />
/etc/letsencrypt/live/YOUR-REPOSITORY-DOMAIN/<br />
</syntaxhighlight><br />
<br />
4. If you have not already done so, create an directory called <tt>ssl</tt> inside your archive's directory, i.e.<br />
<br />
<syntaxhighlight lang="bash"><br />
mkdir EPRINTS_PATH/archives/REPOID/ssl/<br />
</syntaxhighlight><br />
<br />
5. Create a file inside the new ssl directory called <tt>securevhost.conf</tt> and include the following contents, amending the <tt>ServerName</tt>, <tt>SSLCertificateFile</tt>, <tt>SSLCertificateKeyFile</tt> <tt>SSLCertificateChainFile</tt> and <tt>Include</tt> as appropriate at least. You will note that this configuration also enables [https://en.wikipedia.org/wiki/HTTP_Strict_Transport_Security HTTP Strict Transport Security (HSTS)] for additional security. This ensures that after the first time you visit HTTPS for a particular site in your web browser, all future HTTP requests for this hostname will automatically be converted by your browser to HTTPS.<br />
<br />
<syntaxhighlight lang="apache"><br />
<VirtualHost *:443><br />
<br />
ServerName YOUR-REPOSITORY-DOMAIN:443<br />
<br />
# Enable HSTS<br />
Header always set Strict-Transport-Security "max-age=63072000;"<br />
<br />
SSLEngine on<br />
SSLProtocol all -SSLv2 -SSLv3<br />
SSLHonorCipherOrder on<br />
SSLCipherSuite HIGH:!aNULL:!eNULL:!kECDH:!aDH:!RC4:!3DES:!CAMELLIA:!MD5:!PSK:!SRP:!KRB5:@STRENGTH<br />
<br />
SSLCertificateFile /etc/letsencrypt/live/YOUR-REPOSITORY-DOMAIN/cert.pem<br />
SSLCertificateKeyFile /etc/letsencrypt/live/YOUR-REPOSITORY-DOMAIN/privkey.pem<br />
SSLCertificateChainFile /etc/letsencrypt/live/YOUR-REPOSITORY-DOMAIN/chain.pem<br />
<br />
SetEnvIf User-Agent ".*MSIE.*" \<br />
nokeepalive ssl-unclean-shutdown \<br />
downgrade-1.0 force-response-1.0<br />
<br />
LogLevel warn<br />
ErrorLog logs/ssl_error_log <br />
TransferLog logs/ssl_access_log<br />
CustomLog logs/ssl_request_log \<br />
"%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"<br />
<br />
Include EPRINTS_PATHH/cfg/apache_ssl/REPOID.conf<br />
<br />
PerlTransHandler +EPrints::Apache::Rewrite<br />
<br />
</VirtualHost><br />
</syntaxhighlight><br />
<br />
6. If you have not already done so, add a configuration file at <tt>/opt/eprints3/archives/REPOID/cfg/cfg.d/https.pl</tt> with the following configuration:<br />
<br />
<syntaxhighlight lang="perl"><br />
$c->{securehost} = $c->{host};<br />
$c->{secureport} = 443;<br />
$c->{http_root} = undef;<br />
</syntaxhighlight><br />
<br />
7. Now you will need to regenerate the rest of your Apache configuration for EPrints with the following command run as the EPrints user. (Substitute the path as appropriate):<br />
<syntaxhighlight lang="bash"><br />
/opt/eprints3/bin/generate_apacheconf --system --replace<br />
</syntaxhighlight><br />
<br />
8. Apache will not yet have been setup to include the Apache configuration file you created in step 5. To include this, you will need to edit the file in your Apache configuration directory (<tt>/etc/httpd/</tt> on RHEL/CentOS/Fedora and <tt>/etc/apache2/</tt> on Debian/Ubuntu) and find the file that contains the line <tt>cfg/apache.conf</tt>, e.g.<br />
<br />
<syntaxhighlight lang="bash"><br />
cd /etc/httpd/<br />
grep -r "cfg/apache.conf" *<br />
</syntaxhighlight><br />
<br />
9. Once you have found it you will need to edit it and add the following line, changing the path as appropriate:<br />
<syntaxhighlight lang="apache"><br />
Include EPRINTS_PATH/archives/REPOID/ssl/securevhost.conf<br />
</syntaxhighlight><br />
10. Now, (as root or using sudo) test that the Apache configuration is correct and fix any issues if necessary:<br />
<syntaxhighlight lang="bash"><br />
apachectl configtest<br />
</syntaxhighlight><br />
<br />
11. Restart Apache and check whether you can access your EPrints repository using HTTPS in a web browser:<br />
<syntaxhighlight lang="bash"><br />
apachectl restart<br />
</syntaxhighlight><br />
<br />
12. If the guide on cerbot.eff.org you used in step 1 tells you to to setup a cron job then follow those instructions. The easiest way to do this is probably to run <tt>crontab -e</tt> as root and add the following cron job, substituting the minute (43) and hours (6,18) for you own choice maintaining a 12 hour gap between the hours:<br />
<syntaxhighlight lang="text"><br />
43 6,18 * * * certbot renew<br />
</syntaxhighlight><br />
<br />
== Additional Notes ==<br />
<br />
The default EPrints Apache Rewrite handler declines any requests to a URL containing <code>/.</code>.<br />
<br />
This means that the challenge/response for a LetsEncrypt certificate renewal that uses the <code>/.well-known/acme-challenge/</code> path will fail.<br />
<br />
To make this work you could add a location block to your Apache config, to ensure the <code>/.well-known/</code> are not handled by EPrints, or use an EPrints URL rewrite trigger to handle the request:<br />
<br />
<syntaxhighlight lang="perl"><br />
#this could be saved into e.g. [EPRINTS_ROOT]/lib/cfg.d/z_rewrite_url_LetsEncrypt.pl<br />
<br />
# import Apache constant e.g. 'OK'<br />
use EPrints::Apache::AnApache;<br />
<br />
$c->add_trigger( EP_TRIGGER_URL_REWRITE, sub {<br />
my( %o ) = @_;<br />
<br />
# if the incoming request matches the LetsEncrypt challenge URL...<br />
if( $o{uri} =~ m!^${o{urlpath}}/\.well-known/acme-challenge/! )<br />
{<br />
# and the LetsEncrypt renewal process has put the file in EPRINTS_ROOT/archives/ARCHIVEID/html/.well-known/acme-challenge/<br />
if( -f $o{repository}->get_conf( "htdocs_path" ).$o{uri} )<br />
{<br />
# reply with an HTTP '200' <br />
${$o{return_code}} = OK;<br />
# and return the file reqested<br />
$o{request}->filename( $o{repository}->get_conf( "htdocs_path" ).$o{uri} );<br />
}<br />
# and say that we've handled the request - so no more triggers should be run.<br />
return EP_TRIGGER_DONE;<br />
}<br />
} );<br />
</syntaxhighlight></div>Libjlrshttps://wiki.eprints.org/w/index.php?title=Setting_up_HTTPS_using_Let%27s_Encrypt&diff=13784Setting up HTTPS using Let's Encrypt2021-05-21T11:11:27Z<p>Libjlrs: Syntax highlighting</p>
<hr />
<div>{{Manual}}<br />
By default EPrints does not come setup to use HTTPS. This is because you need to generate a SSL certificate and if this is not signed by a known Certificate Authority a user's web browser is likely to complain vigorously. In the past it has typically costed a fair amount of money to obtain a SSL certificate from your hosting provider. However, now there is [https://letsencrypt.org/ Let's Encrypt] it is possible to get a certificate for free. This is not to say you should use Let's Encrypt in all cases. UK academic institutions should continue to obtain their SSL certificates through Jisc and other institutions/organisations may already have similar arrangements for obtaining SSL certificates.<br />
<br />
As well as being free, Let's Encrypt has an automated way for renewing certificates. However, it should be noted that the length of its certificates is a lot shorter at just 3 months. As the renewal process is automatic, this time period is more appropriate to maximise security. Let's Encrypt's certificate generation requires your EPrints repository to be publicly accessible. Beneath are instructions on how to set up EPrints to enable HTTPS with a Let's Encrypt certificate.<br />
<br />
1. Go to the https://certbot.eff.org/ and follow the instructions for your web server and operating system (the former will almost always be Apache) and follow the instructions provided.<br />
<br />
2. When you get to the point of running the certbot command you want the certificate only so should type as the root user:<br />
<br />
<syntaxhighlight lang="bash"><br />
certbot --apache certonly<br />
</syntaxhighlight><br />
<br />
3. Take a note of the path to were your certificate, key and CA chain have been saved. This will probably be something like<br />
<br />
<syntaxhighlight lang="bash"> <br />
/etc/letsencrypt/live/YOUR-REPOSITORY-DOMAIN/<br />
</syntaxhighlight><br />
<br />
4. If you have not already done so, create an directory called <tt>ssl</tt> inside your archive's directory, i.e.<br />
<br />
<syntaxhighlight lang="bash"><br />
mkdir EPRINTS_PATH/archives/REPOID/ssl/<br />
</syntaxhighlight><br />
<br />
5. Create a file inside the new ssl directory called <tt>securevhost.conf</tt> and include the following contents, amending the <tt>ServerName</tt>, <tt>SSLCertificateFile</tt>, <tt>SSLCertificateKeyFile</tt> <tt>SSLCertificateChainFile</tt> and <tt>Include</tt> as appropriate at least. You will note that this configuration also enables [https://en.wikipedia.org/wiki/HTTP_Strict_Transport_Security HTTP Strict Transport Security (HSTS)] for additional security. This ensures that after the first time you visit HTTPS for a particular site in your web browser, all future HTTP requests for this hostname will automatically be converted by your browser to HTTPS.<br />
<br />
<syntaxhighlight lang="apache"><br />
<VirtualHost *:443><br />
<br />
ServerName YOUR-REPOSITORY-DOMAIN:443<br />
<br />
# Enable HSTS<br />
Header always set Strict-Transport-Security "max-age=63072000;"<br />
<br />
SSLEngine on<br />
SSLProtocol all -SSLv2 -SSLv3<br />
SSLHonorCipherOrder on<br />
SSLCipherSuite HIGH:!aNULL:!eNULL:!kECDH:!aDH:!RC4:!3DES:!CAMELLIA:!MD5:!PSK:!SRP:!KRB5:@STRENGTH<br />
<br />
SSLCertificateFile /etc/letsencrypt/live/YOUR-REPOSITORY-DOMAIN/cert.pem<br />
SSLCertificateKeyFile /etc/letsencrypt/live/YOUR-REPOSITORY-DOMAIN/privkey.pem<br />
SSLCertificateChainFile /etc/letsencrypt/live/YOUR-REPOSITORY-DOMAIN/chain.pem<br />
<br />
SetEnvIf User-Agent ".*MSIE.*" \<br />
nokeepalive ssl-unclean-shutdown \<br />
downgrade-1.0 force-response-1.0<br />
<br />
LogLevel warn<br />
ErrorLog logs/ssl_error_log <br />
TransferLog logs/ssl_access_log<br />
CustomLog logs/ssl_request_log \<br />
"%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"<br />
<br />
Include EPRINTS_PATHH/cfg/apache_ssl/REPOID.conf<br />
<br />
PerlTransHandler +EPrints::Apache::Rewrite<br />
<br />
</VirtualHost><br />
</syntaxhighlight><br />
<br />
6. If you have not already done so, add a configuration file at <tt>/opt/eprints3/archives/REPOID/cfg/cfg.d/https.pl</tt> with the following configuration:<br />
<br />
<syntaxhighlight lang="perl"><br />
$c->{securehost} = $c->{host};<br />
$c->{secureport} = 443;<br />
$c->{http_root} = undef;<br />
</syntaxhighlight><br />
<br />
7. Now you will need to regenerate the rest of your Apache configuration for EPrints with the following command run as the EPrints user. (Substitute the path as appropriate):<br />
<syntaxhighlight lang="bash"><br />
/opt/eprints3/bin/generate_apacheconf --system --replace<br />
</syntaxhighlight><br />
<br />
8. Apache will not yet have been setup to include the Apache configuration file you created in step 5. To include this, you will need to edit the file in your Apache configuration directory (<tt>/etc/httpd/</tt> on RHEL/CentOS/Fedora and <tt>/etc/apache2/</tt> on Debian/Ubuntu) and find the file that contains the line <tt>cfg/apache.conf</tt>, e.g.<br />
<br />
<syntaxhighlight lang="bash"><br />
cd /etc/httpd/<br />
grep -r "cfg/apache.conf" *<br />
</syntaxhighlight><br />
<br />
9. Once you have found it you will need to edit it and add the following line, changing the path as appropriate:<br />
<syntaxhighlight lang="apache"><br />
Include EPRINTS_PATH/archives/REPOID/ssl/securevhost.conf<br />
</syntaxhighlight><br />
10. Now, (as root or using sudo) test that the Apache configuration is correct and fix any issues if necessary:<br />
<syntaxhighlight lang="bash"><br />
apachectl configtest<br />
</syntaxhighlight><br />
<br />
11. Restart Apache and check whether you can access your EPrints repository using HTTPS in a web browser:<br />
<syntaxhighlight lang="bash"><br />
apachectl restart<br />
</syntaxhighlight><br />
<br />
12. If the guide on cerbot.eff.org you used in step 1 tells you to to setup a cron job then follow those instructions. The easiest way to do this is probably to run <tt>crontab -e</tt> as root and add the following cron job, substituting the minute (43) and hours (6,18) for you own choice maintaining a 12 hour gap between the hours:<br />
<syntaxhighlight lang="cron"><br />
43 6,18 * * * certbot renew<br />
</syntaxhighlight><br />
<br />
== Additional Notes ==<br />
<br />
The default EPrints Apache Rewrite handler declines any requests to a URL containing <code>/.</code>.<br />
<br />
This means that the challenge/response for a LetsEncrypt certificate renewal that uses the <code>/.well-known/acme-challenge/</code> path will fail.<br />
<br />
To make this work you could add a location block to your Apache config, to ensure the <code>/.well-known/</code> are not handled by EPrints, or use an EPrints URL rewrite trigger to handle the request:<br />
<br />
<syntaxhighlight lang="perl"><br />
#this could be saved into e.g. [EPRINTS_ROOT]/lib/cfg.d/z_rewrite_url_LetsEncrypt.pl<br />
<br />
# import Apache constant e.g. 'OK'<br />
use EPrints::Apache::AnApache;<br />
<br />
$c->add_trigger( EP_TRIGGER_URL_REWRITE, sub {<br />
my( %o ) = @_;<br />
<br />
# if the incoming request matches the LetsEncrypt challenge URL...<br />
if( $o{uri} =~ m!^${o{urlpath}}/\.well-known/acme-challenge/! )<br />
{<br />
# and the LetsEncrypt renewal process has put the file in EPRINTS_ROOT/archives/ARCHIVEID/html/.well-known/acme-challenge/<br />
if( -f $o{repository}->get_conf( "htdocs_path" ).$o{uri} )<br />
{<br />
# reply with an HTTP '200' <br />
${$o{return_code}} = OK;<br />
# and return the file reqested<br />
$o{request}->filename( $o{repository}->get_conf( "htdocs_path" ).$o{uri} );<br />
}<br />
# and say that we've handled the request - so no more triggers should be run.<br />
return EP_TRIGGER_DONE;<br />
}<br />
} );<br />
</syntaxhighlight></div>Libjlrshttps://wiki.eprints.org/w/index.php?title=HTTPS-only_and_HSTS&diff=13783HTTPS-only and HSTS2021-05-21T11:06:32Z<p>Libjlrs: /* Add the HSTS header */</p>
<hr />
<div>{{manual}}<br />
<br />
[[Category:Authentication]]<br />
<br />
== HTTPS with EPrints ==<br />
<br />
See the pages in [[:Category:Authentication|Category Authentication]] for how to setup up HTTPS on EPrints, for example:<br />
<br />
*[[How_to_use_EPrints_with_HTTPS|How to use EPrints with HTTPS]]<br />
*[[Setting_up_HTTPS_using_Let%27s_Encrypt|Setting up HTTPS using Let's Encrypt]]<br />
<br />
The following is a description of how to configure EPrints so that all content, not just login pages, is served over HTTPS.<br />
<br />
== Google Best Practices for HTTPS==<br />
<br />
The following are the best practices specified by [https://support.google.com/webmasters/answer/6073543?hl=en&ref_topic=6001951 Google]<br />
<br />
* HSTS Headers on HTTPS<br />
* No “Mixed Content” warnings/errors<br />
* Links point to HTTPS locations<br />
* 301 Redirects from HTTP to HTTPS<br />
<br />
== HSTS ==<br />
<br />
To summarize how HSTS works, if a browser (Chrome, Firefix, IE) sees the HSTS header in the HTTPS response, and there are no certificate errors or mixed content warnings or anything (if it is green), then the next time a user of that browser requests the HTTP page of that site, the browser will modify the request from an HTTP to a HTTPS request. The browser will remember that setting for as long as you specify <tt>max-age</tt> to be. This means that even with HSTS, it is still possible to request and receive content over HTTP. To close that down, a server redirect is necessary, so those browsers that haven’t seen the HSTS header in the past that happen to try to go to HTTP will get that initial redirect to HTTPS.<br />
<br />
== Implementing HTTPS-only with HSTS on an EPrints repository ==<br />
<br />
=== Changes to archive's cfg.d/10_core.pl ===<br />
<br />
Initialize the following variables to be the https URL (i.e., https://<nowiki>YOUR-REPOSITORY-DOMAIN</nowiki>)<br />
<br />
<source lang="perl"><br />
$c->{host} = "YOUR-REPOSITORY-DOMAIN"; <br />
$c->{http_url} = 'https://YOUR-REPOSITORY-DOMAIN';<br />
$c->{http_cgiurl} = 'https://YOUR-REPOSITORY-DOMAIN/cgi';<br />
$c->{base_url} = "https://$c->{host}";<br />
</source><br />
<br />
=== Changes to archive's <tt>cfg/lang/LANGID/templates/default.xml</tt>, and <tt>/cfg/lang/LANGID/static/*.XPAGE</tt> files ===<br />
<br />
* Remove any hard coded links to HTTP<br />
* If you have Google Search included as an XPAGE file, call on the Google API (and any other APIs) using HTTPS.<br />
<br />
=== Changes to Apache config files ===<br />
<br />
==== Add the HSTS header ====<br />
<br />
Edit [[Template:Securevhost.conf|EPRINTS_PATH/archives/REPOID/ssl/securevhost.conf]] and add the following HSTS header after ther <tt>ServerName</tt> line. The max-age variable is a time in seconds for how long the HSTS settings should be remembered by the browser. 15780000 is six months, which is a long time, you may want to set it to a shorter time while testing.<br />
<br />
<syntaxhighlight lang="apache"><br />
Header set Strict-Transport-Security "max-age=15780000"<br />
</syntaxhighlight><br />
<br />
Include this file from the core apache conf file for the secure port (443) in <tt>/etc/</tt><br />
<br />
==== Add 301 redirects to secure port from HTTP (port 80) ====<br />
<br />
By making the above changes to the archive's <tt>cfg.d/10_core.pl</tt>, if you use [https://github.com/eprints/eprints/commit/c29574dbdcd49c67f3aea522998960f2eb19f544 this patch] or are running [https://github.com/eprints/eprints the latest revision of EPrints on GitHub], <tt>/bin/generate_apacheconf</tt> will generate an <tt>/cfg/apache/REPOID.conf</tt>, which automatically redirects HTTP to HTTPS. Otherwise, this can be achieved by modifying <tt>/cfg/apache/REPOID.conf</tt> to the following, substituting your domain as appropriate:<br />
<br />
<source lang="xml"><br />
<VirtualHost *:80><br />
RedirectPermanent / https://YOUR-REPOSITORY-DOMAIN/ <br />
</VirtualHost><br />
</source></div>Libjlrshttps://wiki.eprints.org/w/index.php?title=HTTPS-only_and_HSTS&diff=13782HTTPS-only and HSTS2021-05-21T11:04:32Z<p>Libjlrs: /* Changes to archive's cfg/lang/LANGID/templates/default.xml, and /cfg/lang/LANGID/static/*.XPAGE files */</p>
<hr />
<div>{{manual}}<br />
<br />
[[Category:Authentication]]<br />
<br />
== HTTPS with EPrints ==<br />
<br />
See the pages in [[:Category:Authentication|Category Authentication]] for how to setup up HTTPS on EPrints, for example:<br />
<br />
*[[How_to_use_EPrints_with_HTTPS|How to use EPrints with HTTPS]]<br />
*[[Setting_up_HTTPS_using_Let%27s_Encrypt|Setting up HTTPS using Let's Encrypt]]<br />
<br />
The following is a description of how to configure EPrints so that all content, not just login pages, is served over HTTPS.<br />
<br />
== Google Best Practices for HTTPS==<br />
<br />
The following are the best practices specified by [https://support.google.com/webmasters/answer/6073543?hl=en&ref_topic=6001951 Google]<br />
<br />
* HSTS Headers on HTTPS<br />
* No “Mixed Content” warnings/errors<br />
* Links point to HTTPS locations<br />
* 301 Redirects from HTTP to HTTPS<br />
<br />
== HSTS ==<br />
<br />
To summarize how HSTS works, if a browser (Chrome, Firefix, IE) sees the HSTS header in the HTTPS response, and there are no certificate errors or mixed content warnings or anything (if it is green), then the next time a user of that browser requests the HTTP page of that site, the browser will modify the request from an HTTP to a HTTPS request. The browser will remember that setting for as long as you specify <tt>max-age</tt> to be. This means that even with HSTS, it is still possible to request and receive content over HTTP. To close that down, a server redirect is necessary, so those browsers that haven’t seen the HSTS header in the past that happen to try to go to HTTP will get that initial redirect to HTTPS.<br />
<br />
== Implementing HTTPS-only with HSTS on an EPrints repository ==<br />
<br />
=== Changes to archive's cfg.d/10_core.pl ===<br />
<br />
Initialize the following variables to be the https URL (i.e., https://<nowiki>YOUR-REPOSITORY-DOMAIN</nowiki>)<br />
<br />
<source lang="perl"><br />
$c->{host} = "YOUR-REPOSITORY-DOMAIN"; <br />
$c->{http_url} = 'https://YOUR-REPOSITORY-DOMAIN';<br />
$c->{http_cgiurl} = 'https://YOUR-REPOSITORY-DOMAIN/cgi';<br />
$c->{base_url} = "https://$c->{host}";<br />
</source><br />
<br />
=== Changes to archive's <tt>cfg/lang/LANGID/templates/default.xml</tt>, and <tt>/cfg/lang/LANGID/static/*.XPAGE</tt> files ===<br />
<br />
* Remove any hard coded links to HTTP<br />
* If you have Google Search included as an XPAGE file, call on the Google API (and any other APIs) using HTTPS.<br />
<br />
=== Changes to Apache config files ===<br />
<br />
==== Add the HSTS header ====<br />
<br />
Edit [[Template:Securevhost.conf|EPRINTS_PATH/archives/REPOID/ssl/securevhost.conf]] and add the following HSTS header after ther <tt>ServerName</tt> line. The max-age variable is a time in seconds for how long the HSTS settings should be remembered by the browser. 15780000 is six months, which is a long time, you may want to set it to a shorter time while testing.<br />
<br />
Header set Strict-Transport-Security "max-age=15780000"<br />
<br />
Include this file from the core apache conf file for the secure port (443) in <tt>/etc/</tt><br />
<br />
==== Add 301 redirects to secure port from HTTP (port 80) ====<br />
<br />
By making the above changes to the archive's <tt>cfg.d/10_core.pl</tt>, if you use [https://github.com/eprints/eprints/commit/c29574dbdcd49c67f3aea522998960f2eb19f544 this patch] or are running [https://github.com/eprints/eprints the latest revision of EPrints on GitHub], <tt>/bin/generate_apacheconf</tt> will generate an <tt>/cfg/apache/REPOID.conf</tt>, which automatically redirects HTTP to HTTPS. Otherwise, this can be achieved by modifying <tt>/cfg/apache/REPOID.conf</tt> to the following, substituting your domain as appropriate:<br />
<br />
<source lang="xml"><br />
<VirtualHost *:80><br />
RedirectPermanent / https://YOUR-REPOSITORY-DOMAIN/ <br />
</VirtualHost><br />
</source></div>Libjlrshttps://wiki.eprints.org/w/index.php?title=HTTPS-only_and_HSTS&diff=13781HTTPS-only and HSTS2021-05-21T11:04:07Z<p>Libjlrs: /* Changes to archive's cfg/lang/LANGID/templates/default.xml, and /cfg/lang/LANGID/static/*.XPAGE files */</p>
<hr />
<div>{{manual}}<br />
<br />
[[Category:Authentication]]<br />
<br />
== HTTPS with EPrints ==<br />
<br />
See the pages in [[:Category:Authentication|Category Authentication]] for how to setup up HTTPS on EPrints, for example:<br />
<br />
*[[How_to_use_EPrints_with_HTTPS|How to use EPrints with HTTPS]]<br />
*[[Setting_up_HTTPS_using_Let%27s_Encrypt|Setting up HTTPS using Let's Encrypt]]<br />
<br />
The following is a description of how to configure EPrints so that all content, not just login pages, is served over HTTPS.<br />
<br />
== Google Best Practices for HTTPS==<br />
<br />
The following are the best practices specified by [https://support.google.com/webmasters/answer/6073543?hl=en&ref_topic=6001951 Google]<br />
<br />
* HSTS Headers on HTTPS<br />
* No “Mixed Content” warnings/errors<br />
* Links point to HTTPS locations<br />
* 301 Redirects from HTTP to HTTPS<br />
<br />
== HSTS ==<br />
<br />
To summarize how HSTS works, if a browser (Chrome, Firefix, IE) sees the HSTS header in the HTTPS response, and there are no certificate errors or mixed content warnings or anything (if it is green), then the next time a user of that browser requests the HTTP page of that site, the browser will modify the request from an HTTP to a HTTPS request. The browser will remember that setting for as long as you specify <tt>max-age</tt> to be. This means that even with HSTS, it is still possible to request and receive content over HTTP. To close that down, a server redirect is necessary, so those browsers that haven’t seen the HSTS header in the past that happen to try to go to HTTP will get that initial redirect to HTTPS.<br />
<br />
== Implementing HTTPS-only with HSTS on an EPrints repository ==<br />
<br />
=== Changes to archive's cfg.d/10_core.pl ===<br />
<br />
Initialize the following variables to be the https URL (i.e., https://<nowiki>YOUR-REPOSITORY-DOMAIN</nowiki>)<br />
<br />
<source lang="perl"><br />
$c->{host} = "YOUR-REPOSITORY-DOMAIN"; <br />
$c->{http_url} = 'https://YOUR-REPOSITORY-DOMAIN';<br />
$c->{http_cgiurl} = 'https://YOUR-REPOSITORY-DOMAIN/cgi';<br />
$c->{base_url} = "https://$c->{host}";<br />
</source><br />
<br />
=== Changes to archive's <tt>cfg/lang/LANGID/templates/default.xml</tt>, and <tt>/cfg/lang/LANGID/static/*.XPAGE</tt> files ===<br />
<br />
Remove any hard coded links to HTTP<br />
If you have Google Search included as an XPAGE file,<br />
call on the Google API (and any other APIs) using HTTPS.<br />
<br />
=== Changes to Apache config files ===<br />
<br />
==== Add the HSTS header ====<br />
<br />
Edit [[Template:Securevhost.conf|EPRINTS_PATH/archives/REPOID/ssl/securevhost.conf]] and add the following HSTS header after ther <tt>ServerName</tt> line. The max-age variable is a time in seconds for how long the HSTS settings should be remembered by the browser. 15780000 is six months, which is a long time, you may want to set it to a shorter time while testing.<br />
<br />
Header set Strict-Transport-Security "max-age=15780000"<br />
<br />
Include this file from the core apache conf file for the secure port (443) in <tt>/etc/</tt><br />
<br />
==== Add 301 redirects to secure port from HTTP (port 80) ====<br />
<br />
By making the above changes to the archive's <tt>cfg.d/10_core.pl</tt>, if you use [https://github.com/eprints/eprints/commit/c29574dbdcd49c67f3aea522998960f2eb19f544 this patch] or are running [https://github.com/eprints/eprints the latest revision of EPrints on GitHub], <tt>/bin/generate_apacheconf</tt> will generate an <tt>/cfg/apache/REPOID.conf</tt>, which automatically redirects HTTP to HTTPS. Otherwise, this can be achieved by modifying <tt>/cfg/apache/REPOID.conf</tt> to the following, substituting your domain as appropriate:<br />
<br />
<source lang="xml"><br />
<VirtualHost *:80><br />
RedirectPermanent / https://YOUR-REPOSITORY-DOMAIN/ <br />
</VirtualHost><br />
</source></div>Libjlrshttps://wiki.eprints.org/w/index.php?title=How_to_customise_thumbnails&diff=13780How to customise thumbnails2021-05-21T11:02:08Z<p>Libjlrs: </p>
<hr />
<div>Based on EPrints-3.3.10.<br />
<br />
To customise the size and type of thumbnails generated by eprints you can create archive-based configuration.<br />
The steps below show how to add a new thumbnail size, and render it the way *I* want it.<br />
<br />
The default thumbnails are generated by: <code>~/perl_lib/EPrints/Plugin/Convert/Thumbnails.pm</code><br />
<br />
I wanted to add a new size 160x90px, called 'homepage' (to fit in with the institution's branding).<br />
To make your own set of thumbnail sizes, edit <code>~/archives/ARCHIVEID/cfg/cfg.d/plugins.pl</code>.<br />
I added the following to the file:<br />
<syntaxhighlight lang="perl"><br />
$c->{plugins}->{'Convert::Thumbnails'}->{params}->{sizes} = {(<br />
small => [66,50],<br />
homepage => [160, 90], # new size - others are copied from Thumbnails.pm<br />
medium => [200,150],<br />
preview => [400,300],<br />
lightbox => [640,480],<br />
)};<br />
$c->{thumbnail_types} = sub {<br />
my( $list, $repo, $doc ) = @_;<br />
push @$list, qw( homepage ); # add new size to list of files to be generated<br />
};<br />
</syntaxhighlight><br />
<br />
By default this will produce a thumbnail that will fit into a box 160x90px - a proportionally scaled down version of the original. The 'small' thumbnail size produces a cropped version of the original. This is a better option for my needs, but it has a grey 1px border around it - that I don't want.<br />
<br />
To alter the thumbnails I need to add the following to <code>~/archives/ARCHIVEID/cfg/cfg.d/plugins.pl</code> - which is a slightly modified version of the <code>sub call_convert</code> copied from Thumbnails.pl<br />
<syntaxhighlight lang="perl"><br />
$c->{plugins}->{'Convert::Thumbnails'}->{params}->{call_convert} = sub {<br />
my( $self, $dir, $doc, $src, $geom, $size ) = @_;<br />
<br />
my $convert = $self->{'convert'};<br />
my $version = $self->convert_version;<br />
<br />
if (!defined($geom)) {<br />
EPrints::abort("NO GEOM");<br />
}<br />
<br />
my $fn = $size . ".jpg";<br />
my $dst = "$dir/$fn";<br />
<br />
$geom = "$geom->[0]x$geom->[1]";<br />
# JPEG<br />
# Read this: http://www.imagemagick.org/script/command-line-processing.php#geometry<br />
# for details of the convert geom options.<br />
#<br />
if( $size eq "small" )<br />
{<br />
# attempt to create a thumbnail that fits within the given dimensions<br />
# geom^ requires 6.3.8<br />
if( $version > 6.3 )<br />
{<br />
$self->_system($convert, "-strip", "-colorspace", "RGB", "-background", "white", "-thumbnail","$geom^", "-gravity", "center", "-extent", $geom, "-bordercolor", "gray", "-border", "1x1", $src."[0]", "JPEG:$dst");<br />
}<br />
else<br />
{<br />
$self->_system($convert, "-strip", "-colorspace", "RGB", "-background", "white", "-thumbnail","$geom>", "-extract", $geom, "-bordercolor", "gray", "-border", "1x1", $src."[0]", "JPEG:$dst");<br />
}<br />
}<br />
elsif( $size eq "homepage" ) # This is the new section to deal with the new 'homepage' size<br />
{<br />
# attempt to create a thumbnail that fits within the given dimensions<br />
# geom^ requires 6.3.8<br />
if( $version > 6.3 )<br />
{<br />
# homepage thumbnails don't want a border on them!<br />
$self->_system($convert, "-strip", "-colorspace", "RGB", "-background", "white", "-thumbnail","$geom^", "-gravity", "center", "-extent", $geom, "-bordercolor", "white", "-border", "0x0", $src."[0]", "JPEG:$dst");<br />
}<br />
else<br />
{<br />
# homepage thumbnails don't want a border on them!<br />
$self->_system($convert, "-strip", "-colorspace", "RGB", "-background", "white", "-thumbnail","$geom>", "-extract", $geom, "-bordercolor", "white", "-border", "0x0", $src."[0]", "JPEG:$dst");<br />
}<br />
}<br />
elsif( $size eq "medium" )<br />
{<br />
$self->_system($convert, "-strip", "-colorspace", "RGB", "-trim", "+repage", "-size", "$geom", "-thumbnail","$geom>", "-background", "white", "-gravity", "center", "-extent", $geom, "-bordercolor", "white", "-border", "0x0", $src."[0]", "JPEG:$dst");<br />
}<br />
else<br />
{<br />
$self->_system($convert, "-strip", "-colorspace", "RGB", "-background", "white", "-thumbnail","$geom>", "-extract", $geom, "-bordercolor", "white", "-border", "0x0", $src."[0]", "JPEG:$dst");<br />
}<br />
<br />
if( -s $dst )<br />
{<br />
return ($fn);<br />
}<br />
<br />
return ();<br />
};<br />
</syntaxhighlight><br />
<br />
To test the new thumbnail generation, find an eprint with some good images attached to it. In the example below I'll use '1234', and assume the original image is called 'file.jpg' and is the first document in the eprint (this only matters for the URL to view the image in the browser with).<br />
<br />
Run <code>~/bin/epadmin redo_thumbnails ARCHIVEID 1234 --verbose</code><br />
<br />
You should see the convert command being run - and the new size filename being created e.g.<br />
<syntaxhighlight lang="bash"><br />
Starting EPrints Repository.<br />
Connecting to DB ... done.<br />
Redoing thumbnails for document 1234<br />
/usr/bin/convert -strip -colorspace RGB -background white -thumbnail 160x90^ -gravity center -extent 160x90 -bordercolor white -border 0x0 /opt/eprints3/archives/digitallibrary/documents/disk0/00/00/12/34/01/file.jpg[0] JPEG:/tmp/_NyUoqmsuZ/homepage.jpg<br />
/usr/bin/convert ... JPEG:/tmp/XR51ieKBCj/lightbox.jpg<br />
/usr/bin/convert ... JPEG:/tmp/fCOP2BPoa2/preview.jpg<br />
/usr/bin/convert ... JPEG:/tmp/zLEip1ewUq/medium.jpg<br />
/usr/bin/convert ... JPEG:/tmp/weRJwQPgNT/small.jpg<br />
</syntaxhighlight><br />
<br />
NB The lines for lightbox, preview, medium and small.jpg have been truncated for clarity.<br />
<br />
You should now be able to view the new thumbnails in a browser: <br />
<code><nowiki>http://your.repo.url/1234/1.hashomepageThumbnailVersion/file.jpg</nowiki></code><br />
<br />
[[Category:Howto]][[Category:Snippets]][[Category:Contribute]]</div>Libjlrshttps://wiki.eprints.org/w/index.php?title=How_to_display_specific_contributors&diff=13778How to display specific contributors2021-05-21T10:07:41Z<p>Libjlrs: /* Method 2 - EPScript logic - foreach */</p>
<hr />
<div>Based on this question, asked on the Tech list:<br />
''How can I add the field “Thesis Advisor” from Contributors to the Abstract Pages?''<br />
<br />
'''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.<br />
<br />
Below are three approaches that may do what you need.<br />
<br />
== Method 1 - EPScript function ==<br />
1) In EPScript, there is an undocumented function - <code>filter_compound_list</code> which accepts:<br />
* a field (''contributors'')<br />
* a sub-field name to filter on (''type'')<br />
* a value to filter to (''http://www.loc.gov/loc.terms/relators/THS'') <br />
* the field to return (''name'')<br />
<br />
This can produce a text-string of one field from the compound field. If a thesis had two supervisors, the following example would produce:<br />
<br />
''Smith, John and Bond, James''<br />
<br />
<source lang="xml"><br />
<epc:if test="contributors"><br />
<epc:print expr="filter_compound_list(contributors,'type','http://www.loc.gov/loc.terms/relators/THS','name')" /><br />
</epc:if><br />
</source><br />
<br />
== Method 2 - EPScript logic - ''foreach'' ==<br />
<br />
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 <code>id</code> sub-field if required.<br />
It also may leave empty wrapping elements in the output (e.g. the <code>ul</code> in the example below if there are contributors, but none are the required type.<br />
<br />
<source lang="xml"><br />
<epc:if test="contributors"><br />
<ul><br />
<epc:foreach expr="contributors" iterator="contr"><br />
<epc:if test="$contr{type}='http://www.loc.gov/loc.terms/relators/THS'"><br />
<li><br />
<epc:print expr="$contr{name}{given}" /> <epc:print expr="$contr{name}{family}" /><br />
<epc:if test="$contr{id}">(<epc:print expr="$contr{id}"/>)</epc:if><br />
</li><br />
</epc:if><br />
</epc:foreach><br />
</ul><br />
</epc:if><br />
</source><br />
<br />
== Method 3 - Custom EPScript function ==<br />
This is the most complex, but also offers the most flexibility - if you're able to understand the <code>EPrints::Script::Compiled</code> module and write your own functions.<br />
<br />
There are two parts - adding custom methods to EPScript, and calling them from the citation file.<br />
<br />
<syntaxhighlight lang="perl" line><br />
### This should be added to a file e.g. EPRINTS_ROOT/archives/ARCHIVEID/cfg/cfg.d/z_epscript_additions.pl<br />
<br />
# Open block<br />
{<br />
<br />
# Write into EPrints::Script::Compiled<br />
package EPrints::Script::Compiled;<br />
<br />
use strict;<br />
<br />
# Example usage in citation file:<br />
#<br />
# <epc:if test="$item.render_contributors_filtered('http://www.loc.gov/loc.terms/relators/THS',1)"><br />
# <h2><epc:phrase ref="contributor_type_typename_http://www.loc.gov/loc.terms/relators/THS"/></h2><br />
# <epc:print expr="$item.render_contributors_filtered('http://www.loc.gov/loc.terms/relators/THS')"/><br />
# </epc:if><br />
#<br />
# The first call includes the 'test' parameter, which can be used to determine whether surrounding<br />
# elements need to be displayed - in the above example the <h2>.<br />
<br />
sub run_render_contributors_filtered<br />
{<br />
my( $self, $state, $eprint, $contributor_type, $test ) = @_;<br />
<br />
if( !defined $eprint->[0] || ref($eprint->[0]) ne "EPrints::DataObj::EPrint" )<br />
{<br />
$self->runtime_error( "Can only call render_contributors_filtered() on eprint objects not ".<br />
ref($eprint->[0]) );<br />
}<br />
<br />
if( !defined $contributor_type )<br />
{<br />
$self->runtime_error( "You need to specify a contributor type you want to render." );<br />
}<br />
<br />
my @filtered_contributors = grep{ defined $_->{type} && $_->{type} eq $contributor_type->[0] } @{ $eprint->[0]->value( "contributors" ) };<br />
<br />
if( $test )<br />
{<br />
return [ 0, "BOOLEAN" ] if( scalar @filtered_contributors < 1 );<br />
return [ 1, "BOOLEAN" ];<br />
}<br />
<br />
# NB this is based on EPrints::Extras::render_related_url<br />
# It is over-complicated for this use-case, as we could just use<br />
# $state->{session}->render_name( $row->{name} )<br />
# but if other compound fields are being used with similar code<br />
# being able to get to the 'render_value' for the sub fields is useful.<br />
<br />
my $field = $eprint->[0]->dataset->field( "contributors" );<br />
my $f = $field->get_property( "fields_cache" );<br />
my $fmap = {};<br />
foreach my $field_conf ( @{$f} )<br />
{<br />
my $fieldname = $field_conf->{name};<br />
my $field = $field->{dataset}->get_field( $fieldname );<br />
$fmap->{$field_conf->{sub_name}} = $field;<br />
}<br />
<br />
my $ul = $state->{session}->make_element( "ul" );<br />
<br />
foreach my $row ( @filtered_contributors )<br />
{<br />
my $li = $state->{session}->make_element( "li" );<br />
$li->appendChild( $fmap->{name}->render_single_value( $state->{session}, $row->{name} ) );<br />
if( defined $row->{id} )<br />
{<br />
$li->appendChild( $state->{session}->make_text( " (" ) );<br />
$li->appendChild( $state->{session}->make_text( $row->{id} ) );<br />
$li->appendChild( $state->{session}->make_text( ")" ) );<br />
}<br />
$ul->appendChild( $li );<br />
}<br />
return [ $ul, "XHTML" ];<br />
}<br />
<br />
} #End block<br />
</syntaxhighlight><br />
<br />
The above example is also available at: https://gist.github.com/jesusbagpuss/2efc96ed05cf9121b925063a20677120<br />
<br />
[[Category:Howto]][[Category:Snippets]][[Category:Contribute]]</div>Libjlrshttps://wiki.eprints.org/w/index.php?title=How_to_display_specific_contributors&diff=13777How to display specific contributors2021-05-21T10:06:21Z<p>Libjlrs: /* Method 3 - Custom EPScript function */</p>
<hr />
<div>Based on this question, asked on the Tech list:<br />
''How can I add the field “Thesis Advisor” from Contributors to the Abstract Pages?''<br />
<br />
'''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.<br />
<br />
Below are three approaches that may do what you need.<br />
<br />
== Method 1 - EPScript function ==<br />
1) In EPScript, there is an undocumented function - <code>filter_compound_list</code> which accepts:<br />
* a field (''contributors'')<br />
* a sub-field name to filter on (''type'')<br />
* a value to filter to (''http://www.loc.gov/loc.terms/relators/THS'') <br />
* the field to return (''name'')<br />
<br />
This can produce a text-string of one field from the compound field. If a thesis had two supervisors, the following example would produce:<br />
<br />
''Smith, John and Bond, James''<br />
<br />
<source lang="xml"><br />
<epc:if test="contributors"><br />
<epc:print expr="filter_compound_list(contributors,'type','http://www.loc.gov/loc.terms/relators/THS','name')" /><br />
</epc:if><br />
</source><br />
<br />
== Method 2 - EPScript logic - ''foreach'' ==<br />
<br />
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 <code>id</code> sub-field if required.<br />
It also may leave empty wrapping elements in the output (e.g. the <code>ul</code> in the example below if there are contributors, but none are the required type.<br />
<br />
<source lang="xml"><br />
<epc:if test="contributors"><br />
<ul><br />
<epc:foreach expr="contributors" iterator="contr"><br />
<epc:if test="$contr{type}='http://www.loc.gov/loc.terms/relators/THS'"><br />
<li><br />
<epc:print expr="$contr{name}{given}" /> <epc:print expr="$contr{name}{family}" /><br />
<epc:if test="$contr{id}">(<epc:print expr="$contr{id}"/>)</epc:if><br />
</li><br />
</epc:if><br />
</epc:foreach><br />
</ul><br />
</epc:if><br />
</source><br />
<br />
== Method 3 - Custom EPScript function ==<br />
This is the most complex, but also offers the most flexibility - if you're able to understand the <code>EPrints::Script::Compiled</code> module and write your own functions.<br />
<br />
There are two parts - adding custom methods to EPScript, and calling them from the citation file.<br />
<br />
<syntaxhighlight lang="perl" line><br />
### This should be added to a file e.g. EPRINTS_ROOT/archives/ARCHIVEID/cfg/cfg.d/z_epscript_additions.pl<br />
<br />
# Open block<br />
{<br />
<br />
# Write into EPrints::Script::Compiled<br />
package EPrints::Script::Compiled;<br />
<br />
use strict;<br />
<br />
# Example usage in citation file:<br />
#<br />
# <epc:if test="$item.render_contributors_filtered('http://www.loc.gov/loc.terms/relators/THS',1)"><br />
# <h2><epc:phrase ref="contributor_type_typename_http://www.loc.gov/loc.terms/relators/THS"/></h2><br />
# <epc:print expr="$item.render_contributors_filtered('http://www.loc.gov/loc.terms/relators/THS')"/><br />
# </epc:if><br />
#<br />
# The first call includes the 'test' parameter, which can be used to determine whether surrounding<br />
# elements need to be displayed - in the above example the <h2>.<br />
<br />
sub run_render_contributors_filtered<br />
{<br />
my( $self, $state, $eprint, $contributor_type, $test ) = @_;<br />
<br />
if( !defined $eprint->[0] || ref($eprint->[0]) ne "EPrints::DataObj::EPrint" )<br />
{<br />
$self->runtime_error( "Can only call render_contributors_filtered() on eprint objects not ".<br />
ref($eprint->[0]) );<br />
}<br />
<br />
if( !defined $contributor_type )<br />
{<br />
$self->runtime_error( "You need to specify a contributor type you want to render." );<br />
}<br />
<br />
my @filtered_contributors = grep{ defined $_->{type} && $_->{type} eq $contributor_type->[0] } @{ $eprint->[0]->value( "contributors" ) };<br />
<br />
if( $test )<br />
{<br />
return [ 0, "BOOLEAN" ] if( scalar @filtered_contributors < 1 );<br />
return [ 1, "BOOLEAN" ];<br />
}<br />
<br />
# NB this is based on EPrints::Extras::render_related_url<br />
# It is over-complicated for this use-case, as we could just use<br />
# $state->{session}->render_name( $row->{name} )<br />
# but if other compound fields are being used with similar code<br />
# being able to get to the 'render_value' for the sub fields is useful.<br />
<br />
my $field = $eprint->[0]->dataset->field( "contributors" );<br />
my $f = $field->get_property( "fields_cache" );<br />
my $fmap = {};<br />
foreach my $field_conf ( @{$f} )<br />
{<br />
my $fieldname = $field_conf->{name};<br />
my $field = $field->{dataset}->get_field( $fieldname );<br />
$fmap->{$field_conf->{sub_name}} = $field;<br />
}<br />
<br />
my $ul = $state->{session}->make_element( "ul" );<br />
<br />
foreach my $row ( @filtered_contributors )<br />
{<br />
my $li = $state->{session}->make_element( "li" );<br />
$li->appendChild( $fmap->{name}->render_single_value( $state->{session}, $row->{name} ) );<br />
if( defined $row->{id} )<br />
{<br />
$li->appendChild( $state->{session}->make_text( " (" ) );<br />
$li->appendChild( $state->{session}->make_text( $row->{id} ) );<br />
$li->appendChild( $state->{session}->make_text( ")" ) );<br />
}<br />
$ul->appendChild( $li );<br />
}<br />
return [ $ul, "XHTML" ];<br />
}<br />
<br />
} #End block<br />
</syntaxhighlight><br />
<br />
The above example is also available at: https://gist.github.com/jesusbagpuss/2efc96ed05cf9121b925063a20677120<br />
<br />
[[Category:Howto]][[Category:Snippets]][[Category:Contribute]]</div>Libjlrshttps://wiki.eprints.org/w/index.php?title=How_to_display_specific_contributors&diff=13776How to display specific contributors2021-05-20T23:03:49Z<p>Libjlrs: /* Method 3 - Custom EPScript function */</p>
<hr />
<div>Based on this question, asked on the Tech list:<br />
''How can I add the field “Thesis Advisor” from Contributors to the Abstract Pages?''<br />
<br />
'''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.<br />
<br />
Below are three approaches that may do what you need.<br />
<br />
== Method 1 - EPScript function ==<br />
1) In EPScript, there is an undocumented function - <code>filter_compound_list</code> which accepts:<br />
* a field (''contributors'')<br />
* a sub-field name to filter on (''type'')<br />
* a value to filter to (''http://www.loc.gov/loc.terms/relators/THS'') <br />
* the field to return (''name'')<br />
<br />
This can produce a text-string of one field from the compound field. If a thesis had two supervisors, the following example would produce:<br />
<br />
''Smith, John and Bond, James''<br />
<br />
<source lang="xml"><br />
<epc:if test="contributors"><br />
<epc:print expr="filter_compound_list(contributors,'type','http://www.loc.gov/loc.terms/relators/THS','name')" /><br />
</epc:if><br />
</source><br />
<br />
== Method 2 - EPScript logic - ''foreach'' ==<br />
<br />
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 <code>id</code> sub-field if required.<br />
It also may leave empty wrapping elements in the output (e.g. the <code>ul</code> in the example below if there are contributors, but none are the required type.<br />
<br />
<source lang="xml"><br />
<epc:if test="contributors"><br />
<ul><br />
<epc:foreach expr="contributors" iterator="contr"><br />
<epc:if test="$contr{type}='http://www.loc.gov/loc.terms/relators/THS'"><br />
<li><br />
<epc:print expr="$contr{name}{given}" /> <epc:print expr="$contr{name}{family}" /><br />
<epc:if test="$contr{id}">(<epc:print expr="$contr{id}"/>)</epc:if><br />
</li><br />
</epc:if><br />
</epc:foreach><br />
</ul><br />
</epc:if><br />
</source><br />
<br />
== Method 3 - Custom EPScript function ==<br />
This is the most complex, but also offers the most flexibility - if you're able to understand the <code>EPrints::Script::Compiled</code> module and write your own functions.<br />
<br />
There are two parts - adding custom methods to EPScript, and calling them from the citation file.<br />
<br />
<source lang="perl"><br />
### This should be added to a file e.g. EPRINTS_ROOT/archives/ARCHIVEID/cfg/cfg.d/z_epscript_additions.pl<br />
<br />
# Open block<br />
{<br />
<br />
# Write into EPrints::Script::Compiled<br />
package EPrints::Script::Compiled;<br />
<br />
use strict;<br />
<br />
# Example usage in citation file:<br />
#<br />
# <epc:if test="$item.render_contributors_filtered('http://www.loc.gov/loc.terms/relators/THS',1)"><br />
# <h2><epc:phrase ref="contributor_type_typename_http://www.loc.gov/loc.terms/relators/THS"/></h2><br />
# <epc:print expr="$item.render_contributors_filtered('http://www.loc.gov/loc.terms/relators/THS')"/><br />
# </epc:if><br />
#<br />
# The first call includes the 'test' parameter, which can be used to determine whether surrounding<br />
# elements need to be displayed - in the above example the <h2>.<br />
<br />
sub run_render_contributors_filtered<br />
{<br />
my( $self, $state, $eprint, $contributor_type, $test ) = @_;<br />
<br />
if( !defined $eprint->[0] || ref($eprint->[0]) ne "EPrints::DataObj::EPrint" )<br />
{<br />
$self->runtime_error( "Can only call render_contributors_filtered() on eprint objects not ".<br />
ref($eprint->[0]) );<br />
}<br />
<br />
if( !defined $contributor_type )<br />
{<br />
$self->runtime_error( "You need to specify a contributor type you want to render." );<br />
}<br />
<br />
my @filtered_contributors = grep{ defined $_->{type} && $_->{type} eq $contributor_type->[0] } @{ $eprint->[0]->value( "contributors" ) };<br />
<br />
if( $test )<br />
{<br />
return [ 0, "BOOLEAN" ] if( scalar @filtered_contributors < 1 );<br />
return [ 1, "BOOLEAN" ];<br />
}<br />
<br />
# NB this is based on EPrints::Extras::render_related_url<br />
# It is over-complicated for this use-case, as we could just use<br />
# $state->{session}->render_name( $row->{name} )<br />
# but if other compound fields are being used with similar code<br />
# being able to get to the 'render_value' for the sub fields is useful.<br />
<br />
my $field = $eprint->[0]->dataset->field( "contributors" );<br />
my $f = $field->get_property( "fields_cache" );<br />
my $fmap = {};<br />
foreach my $field_conf ( @{$f} )<br />
{<br />
my $fieldname = $field_conf->{name};<br />
my $field = $field->{dataset}->get_field( $fieldname );<br />
$fmap->{$field_conf->{sub_name}} = $field;<br />
}<br />
<br />
my $ul = $state->{session}->make_element( "ul" );<br />
<br />
foreach my $row ( @filtered_contributors )<br />
{<br />
my $li = $state->{session}->make_element( "li" );<br />
$li->appendChild( $fmap->{name}->render_single_value( $state->{session}, $row->{name} ) );<br />
if( defined $row->{id} )<br />
{<br />
$li->appendChild( $state->{session}->make_text( " (" ) );<br />
$li->appendChild( $state->{session}->make_text( $row->{id} ) );<br />
$li->appendChild( $state->{session}->make_text( ")" ) );<br />
}<br />
$ul->appendChild( $li );<br />
}<br />
return [ $ul, "XHTML" ];<br />
}<br />
<br />
} #End block<br />
</source><br />
<br />
The above example is also available at: https://gist.github.com/jesusbagpuss/2efc96ed05cf9121b925063a20677120<br />
<br />
[[Category:Howto]][[Category:Snippets]][[Category:Contribute]]</div>Libjlrshttps://wiki.eprints.org/w/index.php?title=How_to_display_specific_contributors&diff=13775How to display specific contributors2021-05-20T23:00:04Z<p>Libjlrs: Created page with "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..."</p>
<hr />
<div>Based on this question, asked on the Tech list:<br />
''How can I add the field “Thesis Advisor” from Contributors to the Abstract Pages?''<br />
<br />
'''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.<br />
<br />
Below are three approaches that may do what you need.<br />
<br />
== Method 1 - EPScript function ==<br />
1) In EPScript, there is an undocumented function - <code>filter_compound_list</code> which accepts:<br />
* a field (''contributors'')<br />
* a sub-field name to filter on (''type'')<br />
* a value to filter to (''http://www.loc.gov/loc.terms/relators/THS'') <br />
* the field to return (''name'')<br />
<br />
This can produce a text-string of one field from the compound field. If a thesis had two supervisors, the following example would produce:<br />
<br />
''Smith, John and Bond, James''<br />
<br />
<source lang="xml"><br />
<epc:if test="contributors"><br />
<epc:print expr="filter_compound_list(contributors,'type','http://www.loc.gov/loc.terms/relators/THS','name')" /><br />
</epc:if><br />
</source><br />
<br />
== Method 2 - EPScript logic - ''foreach'' ==<br />
<br />
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 <code>id</code> sub-field if required.<br />
It also may leave empty wrapping elements in the output (e.g. the <code>ul</code> in the example below if there are contributors, but none are the required type.<br />
<br />
<source lang="xml"><br />
<epc:if test="contributors"><br />
<ul><br />
<epc:foreach expr="contributors" iterator="contr"><br />
<epc:if test="$contr{type}='http://www.loc.gov/loc.terms/relators/THS'"><br />
<li><br />
<epc:print expr="$contr{name}{given}" /> <epc:print expr="$contr{name}{family}" /><br />
<epc:if test="$contr{id}">(<epc:print expr="$contr{id}"/>)</epc:if><br />
</li><br />
</epc:if><br />
</epc:foreach><br />
</ul><br />
</epc:if><br />
</source><br />
<br />
== Method 3 - Custom EPScript function ==<br />
This is the most complex, but also offers the most flexibility - if you're able to understand the <code>EPrints::Script::Compiled</code> module and write your own functions.<br />
<br />
There are two parts - adding custom methods to EPScript, and calling them from the citation file.<br />
<br />
<source lang="perl"><br />
# Open block<br />
{<br />
<br />
# Write into EPrints::Script::Compiled<br />
package EPrints::Script::Compiled;<br />
<br />
use strict;<br />
<br />
# Example usage in citation file:<br />
#<br />
# <epc:if test="$item.render_contributors_filtered('http://www.loc.gov/loc.terms/relators/THS',1)"><br />
# <h2><epc:phrase ref="contributor_type_typename_http://www.loc.gov/loc.terms/relators/THS"/></h2><br />
# <epc:print expr="$item.render_contributors_filtered('http://www.loc.gov/loc.terms/relators/THS')"/><br />
# </epc:if><br />
#<br />
# The first call includes the 'test' parameter, which can be used to determine whether surrounding<br />
# elements need to be displayed - in the above example the <h2>.<br />
<br />
sub run_render_contributors_filtered<br />
{<br />
my( $self, $state, $eprint, $contributor_type, $test ) = @_;<br />
<br />
if( !defined $eprint->[0] || ref($eprint->[0]) ne "EPrints::DataObj::EPrint" )<br />
{<br />
$self->runtime_error( "Can only call render_contributors_filtered() on eprint objects not ".<br />
ref($eprint->[0]) );<br />
}<br />
<br />
if( !defined $contributor_type )<br />
{<br />
$self->runtime_error( "You need to specify a contributor type you want to render." );<br />
}<br />
<br />
my @filtered_contributors = grep{ defined $_->{type} && $_->{type} eq $contributor_type->[0] } @{ $eprint->[0]->value( "contributors" ) };<br />
<br />
if( $test )<br />
{<br />
return [ 0, "BOOLEAN" ] if( scalar @filtered_contributors < 1 );<br />
return [ 1, "BOOLEAN" ];<br />
}<br />
<br />
# NB this is based on EPrints::Extras::render_related_url<br />
# It is over-complicated for this use-case, as we could just use<br />
# $state->{session}->render_name( $row->{name} )<br />
# but if other compound fields are being used with similar code<br />
# being able to get to the 'render_value' for the sub fields is useful.<br />
<br />
my $field = $eprint->[0]->dataset->field( "contributors" );<br />
my $f = $field->get_property( "fields_cache" );<br />
my $fmap = {};<br />
foreach my $field_conf ( @{$f} )<br />
{<br />
my $fieldname = $field_conf->{name};<br />
my $field = $field->{dataset}->get_field( $fieldname );<br />
$fmap->{$field_conf->{sub_name}} = $field;<br />
}<br />
<br />
my $ul = $state->{session}->make_element( "ul" );<br />
<br />
foreach my $row ( @filtered_contributors )<br />
{<br />
my $li = $state->{session}->make_element( "li" );<br />
$li->appendChild( $fmap->{name}->render_single_value( $state->{session}, $row->{name} ) );<br />
if( defined $row->{id} )<br />
{<br />
$li->appendChild( $state->{session}->make_text( " (" ) );<br />
$li->appendChild( $state->{session}->make_text( $row->{id} ) );<br />
$li->appendChild( $state->{session}->make_text( ")" ) );<br />
}<br />
$ul->appendChild( $li );<br />
}<br />
return [ $ul, "XHTML" ];<br />
}<br />
<br />
} #End block<br />
</source><br />
<br />
The above example is also available at: https://gist.github.com/jesusbagpuss/2efc96ed05cf9121b925063a20677120<br />
<br />
[[Category:Howto]][[Category:Snippets]][[Category:Contribute]]</div>Libjlrshttps://wiki.eprints.org/w/index.php?title=Setting_up_HTTPS_using_Let%27s_Encrypt&diff=13511Setting up HTTPS using Let's Encrypt2020-12-14T12:06:07Z<p>Libjlrs: /* Additional Notes */</p>
<hr />
<div>{{Manual}}<br />
By default EPrints does not come setup to use HTTPS. This is because you need to generate a SSL certificate and if this is not signed by a known Certificate Authority a user's web browser is likely to complain vigorously. In the past it has typically costed a fair amount of money to obtain a SSL certificate from your hosting provider. However, now there is [https://letsencrypt.org/ Let's Encrypt] it is possible to get a certificate for free. This is not to say you should use Let's Encrypt in all cases. UK academic institutions should continue to obtain their SSL certificates through Jisc and other institutions/organisations may already have similar arrangements for obtaining SSL certificates.<br />
<br />
As well as being free, Let's Encrypt has an automated way for renewing certificates. However, it should be noted that the length of its certificates is a lot shorter at just 3 months. As the renewal process is automatic, this time period is more appropriate to maximise security. Let's Encrypt's certificate generation requires your EPrints repository to be publicly accessible. Beneath are instructions on how to set up EPrints to enable HTTPS with a Let's Encrypt certificate.<br />
<br />
1. Go to the https://certbot.eff.org/ and follow the instructions for your web server and operating system (the former will almost always be Apache) and follow the instructions provided.<br />
<br />
2. When you get to the point of running the certbot command you want the certificate only so should type as the root user:<br />
<br />
certbot --apache certonly<br />
<br />
3. Take a note of the path to were your certificate, key and CA chain have been saved. This will probably be something like<br />
<br />
/etc/letsencrypt/live/YOUR-REPOSITORY-DOMAIN/<br />
<br />
4. If you have not already done so, create an directory called <tt>ssl</tt> inside your archive's directory, i.e.<br />
<br />
mkdir EPRINTS_PATH/archives/REPOID/ssl/<br />
<br />
5. Create a file inside the new ssl directory called <tt>securevhost.conf</tt> and include the following contents, amending the <tt>ServerName</tt>, <tt>SSLCertificateFile</tt>, <tt>SSLCertificateKeyFile</tt> <tt>SSLCertificateChainFile</tt> and <tt>Include</tt> as appropriate at least. You will note that this configuration also enables [https://en.wikipedia.org/wiki/HTTP_Strict_Transport_Security HTTP Strict Transport Security (HSTS)] for additional security. This ensures that after the first time you visit HTTPS for a particular site in your web browser, all future HTTP requests for this hostname will automatically be converted by your browser to HTTPS.<br />
<br />
<VirtualHost *:443><br />
<br />
ServerName YOUR-REPOSITORY-DOMAIN:443<br />
<br />
# Enable HSTS<br />
Header always set Strict-Transport-Security "max-age=63072000;"<br />
<br />
SSLEngine on<br />
SSLProtocol all -SSLv2 -SSLv3<br />
SSLHonorCipherOrder on<br />
SSLCipherSuite HIGH:!aNULL:!eNULL:!kECDH:!aDH:!RC4:!3DES:!CAMELLIA:!MD5:!PSK:!SRP:!KRB5:@STRENGTH<br />
<br />
SSLCertificateFile /etc/letsencrypt/live/YOUR-REPOSITORY-DOMAIN/cert.pem<br />
SSLCertificateKeyFile /etc/letsencrypt/live/YOUR-REPOSITORY-DOMAIN/privkey.pem<br />
SSLCertificateChainFile /etc/letsencrypt/live/YOUR-REPOSITORY-DOMAIN/chain.pem<br />
<br />
SetEnvIf User-Agent ".*MSIE.*" \<br />
nokeepalive ssl-unclean-shutdown \<br />
downgrade-1.0 force-response-1.0<br />
<br />
LogLevel warn<br />
ErrorLog logs/ssl_error_log <br />
TransferLog logs/ssl_access_log<br />
CustomLog logs/ssl_request_log \<br />
"%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"<br />
<br />
Include EPRINTS_PATHH/cfg/apache_ssl/REPOID.conf<br />
<br />
PerlTransHandler +EPrints::Apache::Rewrite<br />
<br />
</VirtualHost><br />
<br />
6. If you have not already done so, add a configuration file at <tt>/opt/eprints3/archives/REPOID/cfg/cfg.d/https.pl</tt> with the following configuration:<br />
<br />
$c->{securehost} = $c->{host};<br />
$c->{secureport} = 443;<br />
$c->{http_root} = undef;<br />
<br />
7. Now you will need to regenerate the rest of your Apache configuration for EPrints with the following command run as the EPrints user. (Substitute the path as appropriate):<br />
<br />
/opt/eprints3/bin/generate_apacheconf --system --replace<br />
<br />
8. Apache will not yet have been setup to include the Apache configuration file you created in step 5. To include this, you will need to edit the file in your Apache configuration directory (<tt>/etc/httpd/</tt> on RHEL/CentOS/Fedora and <tt>/etc/apache2/</tt> on Debian/Ubuntu) and find the file that contains the line <tt>cfg/apache.conf</tt>, e.g.<br />
<br />
cd /etc/httpd/<br />
grep -r "cfg/apache.conf" *<br />
<br />
9. Once you have found it you will need to edit it and add the following line, changing the path as appropriate:<br />
<br />
Include EPRINTS_PATH/archives/REPOID/ssl/securevhost.conf<br />
<br />
10. Now, (as root or using sudo) test that the Apache configuration is correct and fix any issues if necessary:<br />
<br />
apachectl configtest<br />
<br />
11. Restart Apache and check whether you can access your EPrints repository using HTTPS in a web browser:<br />
<br />
apachectl restart<br />
<br />
12. If the guide on cerbot.eff.org you used in step 1 tells you to to setup a cron job then follow those instructions. The easiest way to do this is probably to run <tt>crontab -e</tt> as root and add the following cron job, substituting the minute (43) and hours (6,18) for you own choice maintaining a 12 hour gap between the hours:<br />
<br />
43 6,18 * * * certbot renew<br />
<br />
<br />
== Additional Notes ==<br />
<br />
The default EPrints Apache Rewrite handler declines any requests to a URL containing <code>/.</code>.<br />
<br />
This means that the challenge/response for a LetsEncrypt certificate renewal that uses the <code>/.well-known/acme-challenge/</code> path will fail.<br />
<br />
To make this work you could add a location block to your Apache config, to ensure the <code>/.well-known/</code> are not handled by EPrints, or use an EPrints URL rewrite trigger to handle the request:<br />
<br />
<syntaxhighlight lang="perl"><br />
#this could be saved into e.g. [EPRINTS_ROOT]/lib/cfg.d/z_rewrite_url_LetsEncrypt.pl<br />
<br />
# import Apache constant e.g. 'OK'<br />
use EPrints::Apache::AnApache;<br />
<br />
$c->add_trigger( EP_TRIGGER_URL_REWRITE, sub {<br />
my( %o ) = @_;<br />
<br />
# if the incoming request matches the LetsEncrypt challenge URL...<br />
if( $o{uri} =~ m!^${o{urlpath}}/\.well-known/acme-challenge/! )<br />
{<br />
# and the LetsEncrypt renewal process has put the file in EPRINTS_ROOT/archives/ARCHIVEID/html/.well-known/acme-challenge/<br />
if( -f $o{repository}->get_conf( "htdocs_path" ).$o{uri} )<br />
{<br />
# reply with an HTTP '200' <br />
${$o{return_code}} = OK;<br />
# and return the file reqested<br />
$o{request}->filename( $o{repository}->get_conf( "htdocs_path" ).$o{uri} );<br />
}<br />
# and say that we've handled the request - so no more triggers should be run.<br />
return EP_TRIGGER_DONE;<br />
}<br />
} );<br />
</syntaxhighlight></div>Libjlrshttps://wiki.eprints.org/w/index.php?title=Category:Plan_S&diff=13499Category:Plan S2020-11-03T11:37:32Z<p>Libjlrs: Created page with "* [https://www.coalition-s.org/ cOAlition S] * [https://www.coalition-s.org/addendum-to-the-coalition-s-guidance-on-the-implementation-of-plan-s/principles-and-implementation/..."</p>
<hr />
<div>* [https://www.coalition-s.org/ cOAlition S]<br />
* [https://www.coalition-s.org/addendum-to-the-coalition-s-guidance-on-the-implementation-of-plan-s/principles-and-implementation/ Plan S Principles and Implementation]<br />
<br />
Plan S is an initiative for Open Access publishing that was launched in September 2018. The plan is supported by cOAlition S, an international consortium of research funding and performing organisations. Plan S requires that, from 2021, scientific publications that result from research funded by public grants must be published in compliant Open Access journals or platforms.</div>Libjlrshttps://wiki.eprints.org/w/index.php?title=Plan_S&diff=13498Plan S2020-11-03T11:34:37Z<p>Libjlrs: </p>
<hr />
<div>Plan S is an initiative for Open Access publishing that was launched in September 2018. The plan is supported by cOAlition S, an international consortium of research funders. Plan S requires that, from 2021, scientific publications that result from research funded by public grants must be published in compliant Open Access journals or platforms.<br />
<br />
== Requirements of Open Access Repositories ==<br />
EPrints as an Open Access repository must meet a number of requirements. Below are the mandatory and recommended conditions across all publication venues as well as specifically for Open Access repositories. EPrints already meets a lot of the requirements. This page is a work in progress but information will be added to each of the requirements below, including information on one of more of the following categories:<br />
* How EPrints already meets the requirement.<br />
* What plugin or other additional component could be installed to meet the requirement.<br />
* How EPrints could or will be modified to meet (or better meet) the requirement.<br />
* Why it is inappropriate or not possible for EPrints to meet the requirement.<br />
<br />
=== Mandatory technical conditions for all publication venues ===<br />
<br />
A1. Use of persistent identifiers (PIDs) for scholarly publications (with versioning, for example, in case of revisions), such as DOI (preferable), URN, or Handle.<br />
* EPrints provides an ''Identification number'' (''id_number'') field to store DOIs as well as other PIDs such as PubMed ID, etc. There are also separate fields for storing ISSNs and ISBNs.<br />
* Each publication record in EPrints is assigned is own URI in the format: ''http://HOSTNAME/id/eprint/NUMBER'', (e.g. http://eprints.example.org/id/eprint/1234 ).<br />
* There are plans to introduce a IDs, IDs, IDs Bazaar plugin similar to the [http://bazaar.eprints.org/449/ Dates, Dates, Dates] that will allow multiple PIDs to be stored with their types to make recording PIDs more extensible.<br />
<br />
A2. Deposition of content with a long-term digital preservation or archiving programme (such as CLOCKSS, Portico, or equivalent).<br />
<br />
A3. High-quality article level metadata in standard interoperable non-proprietary format, under a CC0 public domain dedication. Metadata must include complete and reliable information on funding provided by cOAlition S funders (including as a minimum the name of the funder and the grant number/identifier).<br />
* EPrints most comprehensive metadata export format is its EP3 XML for which an XML schema for any particular archive is available at /cgi/schema to support interoperability. EPrints also provides metadata export in many other standard interoperable non-proprietary format such as: BibTeX, EndNote, CSV, JSON, Dublin Core, RDF to name but a few. EPrints is extensible to allow repository maintainers to add additional export plugins as necessary.<br />
** For repositories connected to other data sources (e.g. CRIS systems, or paid-for services) the 'CC0' aspect may require a metadata profile that excludes some information such as abstracts, subjects or keywords.<br />
<br />
[[Plan S - A4 - Embedding data into an article|A4]]. Machine-readable information on the Open Access status and the license embedded in the article, in standard non-proprietary format.<br />
* EPrints generates a ''full_text_status'' value by analysing the content of a publication record to determine whether this value should be: ''none'', ''public'' or ''restricted''. Each document added to a publication record can be assign a license from a list of available options. Both metadata values are shown in the machine-readable EP3 XML export format and can be used.<br />
** The page [[Plan S - A4 - Embedding data into an article]] contains details of some possible approaches to this requirement.<br />
<br />
=== Strongly recommended additional criteria for all publication venues ===<br />
<br />
B1. Support for PIDs for authors (e.g., ORCID), funders, funding programmes and grants, institutions, and other relevant entities.<br />
<br />
B2. Registering the self-archiving policy of the venue in SHERPA/RoMEO.<br />
<br />
B3. Availability for download of full text for all publications (including supplementary text and data) in a machine-readable community standard format such as JATS XML.<br />
<br />
B4. Direct deposition of publications (in a machine-readable community standard format such as JATS XML, and including complete metadata as described above) by the publisher into author designated or centralised Open Access repositories that fulfil the Plan S criteria.<br />
<br />
B5. OpenAIRE compliance of the metadata.<br />
<br />
B6. Linking to data, code, and other research outputs that underlie the publication and are available in external repositories.<br />
<br />
B7. Openly accessible data on citations according to the standards by the Initiative for Open Citations (I4OC).<br />
<br />
=== Mandatory criteria for repositories ===<br />
<br />
C1. Use of PIDs for the deposited versions of the publications (with versioning, for example in case of revisions), such as DOI (preferable), URN, or Handle.<br />
* Same as A1, see above.<br />
* Clarification is provided in the [https://www.coalition-s.org/faq-theme/technical-requirements/ Plan S FAQs]: <br />
** Q: Does the Author’s Accepted Manuscript (AAM) of an article deposited into an institutional repository have to have a DOI assigned to it?<br />
** A: For cOAlition S articles all AAMs in repositories must have a unique persistent identifier (PID) assigned to them. <br />
<br />
<br />
C2. High quality article level metadata in standard interoperable non-proprietary format, under a CC0 public domain dedication. This must include information on the DOI (or other PIDs) both of the <br />
original publication and the deposited version, on the version deposited (AAM/VoR), and on the Open Access status and the license of the deposited version. Metadata must include complete and reliable information on funding provided by cOAlition S funders (including as a minimum the name of the funder and the grant number/identifier).<br />
* Mostly the same as A3, see above.<br />
* With regard to deposited version the ''Content'' field for a document within a publication record can store version of the file such as: ''Draft Version'', ''Submitted Version'', ''Accepted Version'', ''Published Version'', etc. This field could be modified to use the values such as AAM, VoR, etc. <br />
** The [http://bazaar.eprints.org/1113/ REF Compliance Checker for EPrints] Bazaar plugin provides a mapping from EPrints standard content version for documents to the standardised Open Access versions like VoR and AAM.<br />
* With regard to funder information, by default EPrints provides a field a ''Funders'' field that can indiviually store multiple different funders entered free-hand.<br />
** The [http://bazaar.eprints.org/390/ RIOXX2] Bazaar plugin provides more detailed entry to submit the project ID (i.e. grant reference) and the funders name and ID (as a DOI or ISNI ID).<br />
<br />
C3. Machine readable information on the Open Access status and the license embedded in the article, in standard non-proprietary format.<br />
* Same as A4, see above.<br />
<br />
C4. Continuous availability (uptime at least 99.7%, not taking into account scheduled downtime for maintenance or upgrades).<br />
* EPrints cannot be responsible for the maintenance of the infrastructure on which it runs. However, EPrints has been demonstrated as stable software over a number of years and should not fail and lead to unscheduled downtime in normal circumstances.<br />
<br />
C5. Helpdesk: as a minimum an email address (functional mailbox) has to be provided; a response time of no more than one business day must be ensured.<br />
* By default EPrints requires an admin email address to be set its configuration and this address can be found on the About page of the repository linked off EPrints default main menu.<br />
* EPrints cannot provide any guarantees that the email address has a functional mailbox, as that is the responsibility of the organisation managing the repository.<br />
<br />
=== Strongly recommended additional criteria for repositories ===<br />
<br />
D1. Manuscript submission system that supports both individual author uploads and bulk uploads of manuscripts (AAM or VoR) by publishers.<br />
<br />
D2. Full text stored in a machine-readable community standard format such as JATS XML.<br />
<br />
D3. Support for PIDs for authors (e.g., ORCID), funders, funding programmes and grants, institutions, and other relevant entities.<br />
<br />
D4. Openly accessible data on citations according to the standards by the Initiative for Open Citations (I4OC).<br />
<br />
D5. Open API to allow others (including machines) to access the content. A compliant API must be free to access without any barrier. A light authentication mechanism such as a token for ‘power users’ – e.g., high-traffic collaborators – is acceptable as long as there is a totally open/anonymous route too.<br />
<br />
D6. OpenAIRE compliance of the metadata.<br />
<br />
D7. Quality assurance processes to link full-text deposits with authoritative bibliographic metadata from third party systems, e.g., PubMed, Crossref, or SCOPUS where feasible.<br />
<br />
[[Category:Plan S]]</div>Libjlrshttps://wiki.eprints.org/w/index.php?title=Plan_S_-_A4_-_Embedding_data_into_an_article&diff=13497Plan S - A4 - Embedding data into an article2020-11-03T11:34:04Z<p>Libjlrs: </p>
<hr />
<div>From: https://www.coalition-s.org/technical-guidance_and_requirements/, the following appears in both the ''Mandatory technical conditions for all publication venues'' and ''Requirements for Open Access repositories'' sections:<br />
<blockquote><br />
Machine-readable information on the Open Access status and the license embedded in the article, in standard non-proprietary format.<br />
</blockquote><br />
<br />
== Landscape ==<br />
The most frequently applied licenses are Creative Commons. Their recommended approach to is to use [https://en.wikipedia.org/wiki/Extensible_Metadata_Platform XMP (eXtensible Metadata Platform)] for embedding metadata into documents: https://wiki.creativecommons.org/wiki/XMP <br />
<br />
Reading about [https://www.adobe.com/products/xmp.html XMP, with it's links to Adobe] suggested that it might not satisfy the ''standard non-proprietary format'' requirement. Initially this might have been the case, but I believe that it ''does'' now satisfy this aspect of the requirement:<br />
<br />
<blockquote><br />
''' Open standards '''<br />
<br />
By providing a standard way of tagging files with metadata across products from Adobe and other vendors, XMP is a powerful solution enabler. As an open source technology, it is freely available to developers, which means that the user community benefits from the innovations contributed by developers worldwide. The XMP SDKs are available in the downloads section. Furthermore, XMP is extensible — it can accommodate existing metadata schemas, so systems don’t need to be rebuilt from scratch. A growing number of third-party applications now support XMP.<br />
<br />
Since early 2012, XMP is also an ISO standard (16684-1).<br />
</blockquote><br />
<br />
The referenced ISO standard has been updated to [https://www.iso.org/standard/75163.html ISO 16684-1:2019 - Graphic technology — Extensible metadata platform (XMP) — Part 1: Data model, serialization and core properties (ISBN:978-0-580-99969-7)]. If you don't have access to the ISO documents, the original [https://www.adobe.com/devnet/xmp.html XMP Specification] documentation is freely available and a very good starting point.<br />
<br />
== Software that supports XMP and could be used with EPrints (and other repository platforms) ==<br />
NB This isn't a definitive list. Other reasonable options may exist. Please document them here if you are using others!<br />
<br />
Some instances of EPrints use a 'coversheets' plugin. The addition of metadata to a document could be considered as a form of 'coversheeting' (albeit a normally invisible one).<br />
Any solution should work with or without any existing coversheet plugin.<br />
<br />
=== ExifTool (Perl module and command-line tool) ===<br />
<br />
* https://exiftool.org/ <br />
* https://metacpan.org/pod/distribution/Image-ExifTool/exiftool<br />
* Available as a package for linux-based systems<br />
<br />
ExifTool can read from / write to many file formats including PDFs. It supports various metadata profiles that can be embedded with XMP and also allows creation of custom profiles to be embedded.<br />
<br />
* [https://exiftool.org/TagNames/XMP.html#cc Creative Commons]<br />
* [https://exiftool.org/TagNames/XMP.html#dc Dublin core]<br />
* [https://exiftool.org/TagNames/XMP.html#pdf PDF native]<br />
* [https://exiftool.org/TagNames/XMP.html#pdfx PDF extensions]<br />
* [https://exiftool.org/TagNames/XMP.html#xmp XML native]<br />
<br />
It seems to be actively developed (latest release 12.09 was released 2020-10-29) and is in use by others in our domain [https://blog.research-publishing.net/our-latest-development-8a89f05cfe6d Using exiftool to add extra relevant metadata in pdf files].<br />
<br />
=== PDFBox (Java) ===<br />
<br />
* https://pdfbox.apache.org/docs/2.0.2/javadocs/org/apache/xmpbox/XMPMetadata.html<br />
<br />
=== Other tools/approaches ===<br />
<br />
* PostScript / PDFMARK can add a limited set of metadata to a PDF, but not full XMP as far as I can tell.<br />
<br />
== Technical requirements ==<br />
<br />
* retain original version of document<br />
* either:<br />
** cache copy of document with embedded metadata (a 'volatile version') - similar to some coversheet plugins<br />
** add metadata at point of delivery (could result in slower downloads)<br />
* work with or without coversheet plugins<br />
* support additional metadata - not just licence information<br />
<br />
=== Suggested approach using ExifTool ===<br />
<br />
* Export or convert plugin <br />
** accepts a document<br />
** generates a command-line to call exiftool (specified in 'executables') e.g. <pre>/path/to/exiftool -XMP-dc:Rights="This work is licensed to the public under the Creative Commons Attribution-ShareAlike license http://creativecommons.org/licenses/by-sa/4.0/" -xmp:usageterms="This work is licensed to the public under the Creative Commons Attribution-ShareAlike license http://creativecommons.org/licenses/by-sa/4.0/" "file name.extension"</pre><br />
** data to be embedded controlled by a configuration method<br />
** could call e.g. Export::DC to get suitable eprint-level information<br />
<br />
* Plugin that interfaces directly with the [https://exiftool.org/ExifTool.html <code>Image::ExifTool</code>] library.<br />
<br />
== Possibly useful links ==<br />
<br />
* https://libre-software.net/edit-metadata-exiftool/<br />
<br />
[[Category:Plan S]]</div>Libjlrshttps://wiki.eprints.org/w/index.php?title=Plan_S&diff=13496Plan S2020-11-03T11:31:20Z<p>Libjlrs: Added category</p>
<hr />
<div>Plan S is an initiative for Open Access publishing that was launched in September 2018. The plan is supported by cOAlition S, an international consortium of research funders. Plan S requires that, from 2021, scientific publications that result from research funded by public grants must be published in compliant Open Access journals or platforms.<br />
<br />
== Requirements of Open Access Repositories ==<br />
EPrints as an Open Access repository must meet a number of requirements. Below are the mandatory and recommended conditions across all publication venues as well as specifically for Open Access repositories. EPrints already meets a lot of the requirements. This page is a work in progress but information will be added to each of the requirements below, including information on one of more of the following categories:<br />
* How EPrints already meets the requirement.<br />
* What plugin or other additional component could be installed to meet the requirement.<br />
* How EPrints could or will be modified to meet (or better meet) the requirement.<br />
* Why it is inappropriate or not possible for EPrints to meet the requirement.<br />
<br />
=== Mandatory technical conditions for all publication venues ===<br />
<br />
A1. Use of persistent identifiers (PIDs) for scholarly publications (with versioning, for example, in case of revisions), such as DOI (preferable), URN, or Handle.<br />
* EPrints provides an ''Identification number'' (''id_number'') field to store DOIs as well as other PIDs such as PubMed ID, etc. There are also separate fields for storing ISSNs and ISBNs.<br />
* Each publication record in EPrints is assigned is own URI in the format: ''http://HOSTNAME/id/eprint/NUMBER'', (e.g. http://eprints.example.org/id/eprint/1234 ).<br />
* There are plans to introduce a IDs, IDs, IDs Bazaar plugin similar to the [http://bazaar.eprints.org/449/ Dates, Dates, Dates] that will allow multiple PIDs to be stored with their types to make recording PIDs more extensible.<br />
<br />
A2. Deposition of content with a long-term digital preservation or archiving programme (such as CLOCKSS, Portico, or equivalent).<br />
<br />
A3. High-quality article level metadata in standard interoperable non-proprietary format, under a CC0 public domain dedication. Metadata must include complete and reliable information on funding provided by cOAlition S funders (including as a minimum the name of the funder and the grant number/identifier).<br />
* EPrints most comprehensive metadata export format is its EP3 XML for which an XML schema for any particular archive is available at /cgi/schema to support interoperability. EPrints also provides metadata export in many other standard interoperable non-proprietary format such as: BibTeX, EndNote, CSV, JSON, Dublin Core, RDF to name but a few. EPrints is extensible to allow repository maintainers to add additional export plugins as necessary.<br />
** For repositories connected to other data sources (e.g. CRIS systems, or paid-for services) the 'CC0' aspect may require a metadata profile that excludes some information such as abstracts, subjects or keywords.<br />
<br />
[[Plan S - A4 - Embedding data into an article|A4]]. Machine-readable information on the Open Access status and the license embedded in the article, in standard non-proprietary format.<br />
* EPrints generates a ''full_text_status'' value by analysing the content of a publication record to determine whether this value should be: ''none'', ''public'' or ''restricted''. Each document added to a publication record can be assign a license from a list of available options. Both metadata values are shown in the machine-readable EP3 XML export format and can be used.<br />
** The page [[Plan S - A4 - Embedding data into an article]] contains details of some possible approaches to this requirement.<br />
<br />
=== Strongly recommended additional criteria for all publication venues ===<br />
<br />
B1. Support for PIDs for authors (e.g., ORCID), funders, funding programmes and grants, institutions, and other relevant entities.<br />
<br />
B2. Registering the self-archiving policy of the venue in SHERPA/RoMEO.<br />
<br />
B3. Availability for download of full text for all publications (including supplementary text and data) in a machine-readable community standard format such as JATS XML.<br />
<br />
B4. Direct deposition of publications (in a machine-readable community standard format such as JATS XML, and including complete metadata as described above) by the publisher into author designated or centralised Open Access repositories that fulfil the Plan S criteria.<br />
<br />
B5. OpenAIRE compliance of the metadata.<br />
<br />
B6. Linking to data, code, and other research outputs that underlie the publication and are available in external repositories.<br />
<br />
B7. Openly accessible data on citations according to the standards by the Initiative for Open Citations (I4OC).<br />
<br />
=== Mandatory criteria for repositories ===<br />
<br />
C1. Use of PIDs for the deposited versions of the publications (with versioning, for example in case of revisions), such as DOI (preferable), URN, or Handle.<br />
* Same as A1, see above.<br />
* Clarification is provided in the [https://www.coalition-s.org/faq-theme/technical-requirements/ Plan S FAQs]: <br />
** Q: Does the Author’s Accepted Manuscript (AAM) of an article deposited into an institutional repository have to have a DOI assigned to it?<br />
** A: For cOAlition S articles all AAMs in repositories must have a unique persistent identifier (PID) assigned to them. <br />
<br />
<br />
C2. High quality article level metadata in standard interoperable non-proprietary format, under a CC0 public domain dedication. This must include information on the DOI (or other PIDs) both of the <br />
original publication and the deposited version, on the version deposited (AAM/VoR), and on the Open Access status and the license of the deposited version. Metadata must include complete and reliable information on funding provided by cOAlition S funders (including as a minimum the name of the funder and the grant number/identifier).<br />
* Mostly the same as A3, see above.<br />
* With regard to deposited version the ''Content'' field for a document within a publication record can store version of the file such as: ''Draft Version'', ''Submitted Version'', ''Accepted Version'', ''Published Version'', etc. This field could be modified to use the values such as AAM, VoR, etc. <br />
** The [http://bazaar.eprints.org/1113/ REF Compliance Checker for EPrints] Bazaar plugin provides a mapping from EPrints standard content version for documents to the standardised Open Access versions like VoR and AAM.<br />
* With regard to funder information, by default EPrints provides a field a ''Funders'' field that can indiviually store multiple different funders entered free-hand.<br />
** The [http://bazaar.eprints.org/390/ RIOXX2] Bazaar plugin provides more detailed entry to submit the project ID (i.e. grant reference) and the funders name and ID (as a DOI or ISNI ID).<br />
<br />
C3. Machine readable information on the Open Access status and the license embedded in the article, in standard non-proprietary format.<br />
* Same as A4, see above.<br />
<br />
C4. Continuous availability (uptime at least 99.7%, not taking into account scheduled downtime for maintenance or upgrades).<br />
* EPrints cannot be responsible for the maintenance of the infrastructure on which it runs. However, EPrints has been demonstrated as stable software over a number of years and should not fail and lead to unscheduled downtime in normal circumstances.<br />
<br />
C5. Helpdesk: as a minimum an email address (functional mailbox) has to be provided; a response time of no more than one business day must be ensured.<br />
* By default EPrints requires an admin email address to be set its configuration and this address can be found on the About page of the repository linked off EPrints default main menu.<br />
* EPrints cannot provide any guarantees that the email address has a functional mailbox, as that is the responsibility of the organisation managing the repository.<br />
<br />
=== Strongly recommended additional criteria for repositories ===<br />
<br />
D1. Manuscript submission system that supports both individual author uploads and bulk uploads of manuscripts (AAM or VoR) by publishers.<br />
<br />
D2. Full text stored in a machine-readable community standard format such as JATS XML.<br />
<br />
D3. Support for PIDs for authors (e.g., ORCID), funders, funding programmes and grants, institutions, and other relevant entities.<br />
<br />
D4. Openly accessible data on citations according to the standards by the Initiative for Open Citations (I4OC).<br />
<br />
D5. Open API to allow others (including machines) to access the content. A compliant API must be free to access without any barrier. A light authentication mechanism such as a token for ‘power users’ – e.g., high-traffic collaborators – is acceptable as long as there is a totally open/anonymous route too.<br />
<br />
D6. OpenAIRE compliance of the metadata.<br />
<br />
D7. Quality assurance processes to link full-text deposits with authoritative bibliographic metadata from third party systems, e.g., PubMed, Crossref, or SCOPUS where feasible.<br />
<br />
[[Category:PlanS]]</div>Libjlrshttps://wiki.eprints.org/w/index.php?title=Plan_S_-_A4_-_Embedding_data_into_an_article&diff=13495Plan S - A4 - Embedding data into an article2020-11-03T11:28:59Z<p>Libjlrs: Add catregory</p>
<hr />
<div>From: https://www.coalition-s.org/technical-guidance_and_requirements/, the following appears in both the ''Mandatory technical conditions for all publication venues'' and ''Requirements for Open Access repositories'' sections:<br />
<blockquote><br />
Machine-readable information on the Open Access status and the license embedded in the article, in standard non-proprietary format.<br />
</blockquote><br />
<br />
== Landscape ==<br />
The most frequently applied licenses are Creative Commons. Their recommended approach to is to use [https://en.wikipedia.org/wiki/Extensible_Metadata_Platform XMP (eXtensible Metadata Platform)] for embedding metadata into documents: https://wiki.creativecommons.org/wiki/XMP <br />
<br />
Reading about [https://www.adobe.com/products/xmp.html XMP, with it's links to Adobe] suggested that it might not satisfy the ''standard non-proprietary format'' requirement. Initially this might have been the case, but I believe that it ''does'' now satisfy this aspect of the requirement:<br />
<br />
<blockquote><br />
''' Open standards '''<br />
<br />
By providing a standard way of tagging files with metadata across products from Adobe and other vendors, XMP is a powerful solution enabler. As an open source technology, it is freely available to developers, which means that the user community benefits from the innovations contributed by developers worldwide. The XMP SDKs are available in the downloads section. Furthermore, XMP is extensible — it can accommodate existing metadata schemas, so systems don’t need to be rebuilt from scratch. A growing number of third-party applications now support XMP.<br />
<br />
Since early 2012, XMP is also an ISO standard (16684-1).<br />
</blockquote><br />
<br />
The referenced ISO standard has been updated to [https://www.iso.org/standard/75163.html ISO 16684-1:2019 - Graphic technology — Extensible metadata platform (XMP) — Part 1: Data model, serialization and core properties (ISBN:978-0-580-99969-7)]. If you don't have access to the ISO documents, the original [https://www.adobe.com/devnet/xmp.html XMP Specification] documentation is freely available and a very good starting point.<br />
<br />
== Software that supports XMP and could be used with EPrints (and other repository platforms) ==<br />
NB This isn't a definitive list. Other reasonable options may exist. Please document them here if you are using others!<br />
<br />
Some instances of EPrints use a 'coversheets' plugin. The addition of metadata to a document could be considered as a form of 'coversheeting' (albeit a normally invisible one).<br />
Any solution should work with or without any existing coversheet plugin.<br />
<br />
=== ExifTool (Perl module and command-line tool) ===<br />
<br />
* https://exiftool.org/ <br />
* https://metacpan.org/pod/distribution/Image-ExifTool/exiftool<br />
* Available as a package for linux-based systems<br />
<br />
ExifTool can read from / write to many file formats including PDFs. It supports various metadata profiles that can be embedded with XMP and also allows creation of custom profiles to be embedded.<br />
<br />
* [https://exiftool.org/TagNames/XMP.html#cc Creative Commons]<br />
* [https://exiftool.org/TagNames/XMP.html#dc Dublin core]<br />
* [https://exiftool.org/TagNames/XMP.html#pdf PDF native]<br />
* [https://exiftool.org/TagNames/XMP.html#pdfx PDF extensions]<br />
* [https://exiftool.org/TagNames/XMP.html#xmp XML native]<br />
<br />
It seems to be actively developed (latest release 12.09 was released 2020-10-29) and is in use by others in our domain [https://blog.research-publishing.net/our-latest-development-8a89f05cfe6d Using exiftool to add extra relevant metadata in pdf files].<br />
<br />
=== PDFBox (Java) ===<br />
<br />
* https://pdfbox.apache.org/docs/2.0.2/javadocs/org/apache/xmpbox/XMPMetadata.html<br />
<br />
=== Other tools/approaches ===<br />
<br />
* PostScript / PDFMARK can add a limited set of metadata to a PDF, but not full XMP as far as I can tell.<br />
<br />
== Technical requirements ==<br />
<br />
* retain original version of document<br />
* either:<br />
** cache copy of document with embedded metadata (a 'volatile version') - similar to some coversheet plugins<br />
** add metadata at point of delivery (could result in slower downloads)<br />
* work with or without coversheet plugins<br />
* support additional metadata - not just licence information<br />
<br />
=== Suggested approach using ExifTool ===<br />
<br />
* Export or convert plugin <br />
** accepts a document<br />
** generates a command-line to call exiftool (specified in 'executables') e.g. <pre>/path/to/exiftool -XMP-dc:Rights="This work is licensed to the public under the Creative Commons Attribution-ShareAlike license http://creativecommons.org/licenses/by-sa/4.0/" -xmp:usageterms="This work is licensed to the public under the Creative Commons Attribution-ShareAlike license http://creativecommons.org/licenses/by-sa/4.0/" "file name.extension"</pre><br />
** data to be embedded controlled by a configuration method<br />
** could call e.g. Export::DC to get suitable eprint-level information<br />
<br />
* Plugin that interfaces directly with the [https://exiftool.org/ExifTool.html <code>Image::ExifTool</code>] library.<br />
<br />
== Possibly useful links ==<br />
<br />
* https://libre-software.net/edit-metadata-exiftool/<br />
<br />
[[Category:PlanS]]</div>Libjlrshttps://wiki.eprints.org/w/index.php?title=Plan_S_-_A4_-_Embedding_data_into_an_article&diff=13493Plan S - A4 - Embedding data into an article2020-11-02T16:10:35Z<p>Libjlrs: /* ExifTool (Perl module and command-line tool) */</p>
<hr />
<div>From: https://www.coalition-s.org/technical-guidance_and_requirements/, the following appears in both the ''Mandatory technical conditions for all publication venues'' and ''Requirements for Open Access repositories'' sections:<br />
<blockquote><br />
Machine-readable information on the Open Access status and the license embedded in the article, in standard non-proprietary format.<br />
</blockquote><br />
<br />
== Landscape ==<br />
The most frequently applied licenses are Creative Commons. Their recommended approach to is to use [https://en.wikipedia.org/wiki/Extensible_Metadata_Platform XMP (eXtensible Metadata Platform)] for embedding metadata into documents: https://wiki.creativecommons.org/wiki/XMP <br />
<br />
Reading about [https://www.adobe.com/products/xmp.html XMP, with it's links to Adobe] suggested that it might not satisfy the ''standard non-proprietary format'' requirement. Initially this might have been the case, but I believe that it ''does'' now satisfy this aspect of the requirement:<br />
<br />
<blockquote><br />
''' Open standards '''<br />
<br />
By providing a standard way of tagging files with metadata across products from Adobe and other vendors, XMP is a powerful solution enabler. As an open source technology, it is freely available to developers, which means that the user community benefits from the innovations contributed by developers worldwide. The XMP SDKs are available in the downloads section. Furthermore, XMP is extensible — it can accommodate existing metadata schemas, so systems don’t need to be rebuilt from scratch. A growing number of third-party applications now support XMP.<br />
<br />
Since early 2012, XMP is also an ISO standard (16684-1).<br />
</blockquote><br />
<br />
The referenced ISO standard has been updated to [https://www.iso.org/standard/75163.html ISO 16684-1:2019 - Graphic technology — Extensible metadata platform (XMP) — Part 1: Data model, serialization and core properties (ISBN:978-0-580-99969-7)]. If you don't have access to the ISO documents, the original [https://www.adobe.com/devnet/xmp.html XMP Specification] documentation is freely available and a very good starting point.<br />
<br />
== Software that supports XMP and could be used with EPrints (and other repository platforms) ==<br />
NB This isn't a definitive list. Other reasonable options may exist. Please document them here if you are using others!<br />
<br />
Some instances of EPrints use a 'coversheets' plugin. The addition of metadata to a document could be considered as a form of 'coversheeting' (albeit a normally invisible one).<br />
Any solution should work with or without any existing coversheet plugin.<br />
<br />
=== ExifTool (Perl module and command-line tool) ===<br />
<br />
* https://exiftool.org/ <br />
* https://metacpan.org/pod/distribution/Image-ExifTool/exiftool<br />
* Available as a package for linux-based systems<br />
<br />
ExifTool can read from / write to many file formats including PDFs. It supports various metadata profiles that can be embedded with XMP and also allows creation of custom profiles to be embedded.<br />
<br />
* [https://exiftool.org/TagNames/XMP.html#cc Creative Commons]<br />
* [https://exiftool.org/TagNames/XMP.html#dc Dublin core]<br />
* [https://exiftool.org/TagNames/XMP.html#pdf PDF native]<br />
* [https://exiftool.org/TagNames/XMP.html#pdfx PDF extensions]<br />
* [https://exiftool.org/TagNames/XMP.html#xmp XML native]<br />
<br />
It seems to be actively developed (latest release 12.09 was released 2020-10-29) and is in use by others in our domain [https://blog.research-publishing.net/our-latest-development-8a89f05cfe6d Using exiftool to add extra relevant metadata in pdf files].<br />
<br />
=== PDFBox (Java) ===<br />
<br />
* https://pdfbox.apache.org/docs/2.0.2/javadocs/org/apache/xmpbox/XMPMetadata.html<br />
<br />
=== Other tools/approaches ===<br />
<br />
* PostScript / PDFMARK can add a limited set of metadata to a PDF, but not full XMP as far as I can tell.<br />
<br />
== Technical requirements ==<br />
<br />
* retain original version of document<br />
* either:<br />
** cache copy of document with embedded metadata (a 'volatile version') - similar to some coversheet plugins<br />
** add metadata at point of delivery (could result in slower downloads)<br />
* work with or without coversheet plugins<br />
* support additional metadata - not just licence information<br />
<br />
=== Suggested approach using ExifTool ===<br />
<br />
* Export or convert plugin <br />
** accepts a document<br />
** generates a command-line to call exiftool (specified in 'executables') e.g. <pre>/path/to/exiftool -XMP-dc:Rights="This work is licensed to the public under the Creative Commons Attribution-ShareAlike license http://creativecommons.org/licenses/by-sa/4.0/" -xmp:usageterms="This work is licensed to the public under the Creative Commons Attribution-ShareAlike license http://creativecommons.org/licenses/by-sa/4.0/" "file name.extension"</pre><br />
** data to be embedded controlled by a configuration method<br />
** could call e.g. Export::DC to get suitable eprint-level information<br />
<br />
* Plugin that interfaces directly with the [https://exiftool.org/ExifTool.html <code>Image::ExifTool</code>] library.<br />
<br />
== Possibly useful links ==<br />
<br />
* https://libre-software.net/edit-metadata-exiftool/</div>Libjlrshttps://wiki.eprints.org/w/index.php?title=Plan_S_-_A4_-_Embedding_data_into_an_article&diff=13492Plan S - A4 - Embedding data into an article2020-11-02T15:40:41Z<p>Libjlrs: /* Suggested approach using ExifTool */</p>
<hr />
<div>From: https://www.coalition-s.org/technical-guidance_and_requirements/, the following appears in both the ''Mandatory technical conditions for all publication venues'' and ''Requirements for Open Access repositories'' sections:<br />
<blockquote><br />
Machine-readable information on the Open Access status and the license embedded in the article, in standard non-proprietary format.<br />
</blockquote><br />
<br />
== Landscape ==<br />
The most frequently applied licenses are Creative Commons. Their recommended approach to is to use [https://en.wikipedia.org/wiki/Extensible_Metadata_Platform XMP (eXtensible Metadata Platform)] for embedding metadata into documents: https://wiki.creativecommons.org/wiki/XMP <br />
<br />
Reading about [https://www.adobe.com/products/xmp.html XMP, with it's links to Adobe] suggested that it might not satisfy the ''standard non-proprietary format'' requirement. Initially this might have been the case, but I believe that it ''does'' now satisfy this aspect of the requirement:<br />
<br />
<blockquote><br />
''' Open standards '''<br />
<br />
By providing a standard way of tagging files with metadata across products from Adobe and other vendors, XMP is a powerful solution enabler. As an open source technology, it is freely available to developers, which means that the user community benefits from the innovations contributed by developers worldwide. The XMP SDKs are available in the downloads section. Furthermore, XMP is extensible — it can accommodate existing metadata schemas, so systems don’t need to be rebuilt from scratch. A growing number of third-party applications now support XMP.<br />
<br />
Since early 2012, XMP is also an ISO standard (16684-1).<br />
</blockquote><br />
<br />
The referenced ISO standard has been updated to [https://www.iso.org/standard/75163.html ISO 16684-1:2019 - Graphic technology — Extensible metadata platform (XMP) — Part 1: Data model, serialization and core properties (ISBN:978-0-580-99969-7)]. If you don't have access to the ISO documents, the original [https://www.adobe.com/devnet/xmp.html XMP Specification] documentation is freely available and a very good starting point.<br />
<br />
== Software that supports XMP and could be used with EPrints (and other repository platforms) ==<br />
NB This isn't a definitive list. Other reasonable options may exist. Please document them here if you are using others!<br />
<br />
Some instances of EPrints use a 'coversheets' plugin. The addition of metadata to a document could be considered as a form of 'coversheeting' (albeit a normally invisible one).<br />
Any solution should work with or without any existing coversheet plugin.<br />
<br />
=== ExifTool (Perl module and command-line tool) ===<br />
<br />
* https://exiftool.org/ <br />
* https://metacpan.org/pod/distribution/Image-ExifTool/exiftool<br />
* Available as a package for linux-based systems<br />
<br />
ExifTool can read from / write to many file formats including PDFs. It supports various metadata profiles that can be embedded with XMP and also allows creation of custom profiles to be embedded.<br />
<br />
* [https://exiftool.org/TagNames/XMP.html#cc Creative Commons]<br />
* [https://exiftool.org/TagNames/XMP.html#dc Dublin core]<br />
* [https://exiftool.org/TagNames/XMP.html#pdf PDF native]<br />
* [https://exiftool.org/TagNames/XMP.html#pdfx PDF extensions]<br />
* [https://exiftool.org/TagNames/XMP.html#xmp XML native]<br />
<br />
It seems to be actively developed (latest release June 2020) and is in use by others in our domain [https://blog.research-publishing.net/our-latest-development-8a89f05cfe6d Using exiftool to add extra relevant metadata in pdf files].<br />
<br />
=== PDFBox (Java) ===<br />
<br />
* https://pdfbox.apache.org/docs/2.0.2/javadocs/org/apache/xmpbox/XMPMetadata.html<br />
<br />
=== Other tools/approaches ===<br />
<br />
* PostScript / PDFMARK can add a limited set of metadata to a PDF, but not full XMP as far as I can tell.<br />
<br />
== Technical requirements ==<br />
<br />
* retain original version of document<br />
* either:<br />
** cache copy of document with embedded metadata (a 'volatile version') - similar to some coversheet plugins<br />
** add metadata at point of delivery (could result in slower downloads)<br />
* work with or without coversheet plugins<br />
* support additional metadata - not just licence information<br />
<br />
=== Suggested approach using ExifTool ===<br />
<br />
* Export or convert plugin <br />
** accepts a document<br />
** generates a command-line to call exiftool (specified in 'executables') e.g. <pre>/path/to/exiftool -XMP-dc:Rights="This work is licensed to the public under the Creative Commons Attribution-ShareAlike license http://creativecommons.org/licenses/by-sa/4.0/" -xmp:usageterms="This work is licensed to the public under the Creative Commons Attribution-ShareAlike license http://creativecommons.org/licenses/by-sa/4.0/" "file name.extension"</pre><br />
** data to be embedded controlled by a configuration method<br />
** could call e.g. Export::DC to get suitable eprint-level information<br />
<br />
* Plugin that interfaces directly with the [https://exiftool.org/ExifTool.html <code>Image::ExifTool</code>] library.<br />
<br />
== Possibly useful links ==<br />
<br />
* https://libre-software.net/edit-metadata-exiftool/</div>Libjlrshttps://wiki.eprints.org/w/index.php?title=Plan_S_-_A4_-_Embedding_data_into_an_article&diff=13491Plan S - A4 - Embedding data into an article2020-11-02T15:35:29Z<p>Libjlrs: Created page with "From: https://www.coalition-s.org/technical-guidance_and_requirements/, the following appears in both the ''Mandatory technical conditions for all publication venues'' and ''R..."</p>
<hr />
<div>From: https://www.coalition-s.org/technical-guidance_and_requirements/, the following appears in both the ''Mandatory technical conditions for all publication venues'' and ''Requirements for Open Access repositories'' sections:<br />
<blockquote><br />
Machine-readable information on the Open Access status and the license embedded in the article, in standard non-proprietary format.<br />
</blockquote><br />
<br />
== Landscape ==<br />
The most frequently applied licenses are Creative Commons. Their recommended approach to is to use [https://en.wikipedia.org/wiki/Extensible_Metadata_Platform XMP (eXtensible Metadata Platform)] for embedding metadata into documents: https://wiki.creativecommons.org/wiki/XMP <br />
<br />
Reading about [https://www.adobe.com/products/xmp.html XMP, with it's links to Adobe] suggested that it might not satisfy the ''standard non-proprietary format'' requirement. Initially this might have been the case, but I believe that it ''does'' now satisfy this aspect of the requirement:<br />
<br />
<blockquote><br />
''' Open standards '''<br />
<br />
By providing a standard way of tagging files with metadata across products from Adobe and other vendors, XMP is a powerful solution enabler. As an open source technology, it is freely available to developers, which means that the user community benefits from the innovations contributed by developers worldwide. The XMP SDKs are available in the downloads section. Furthermore, XMP is extensible — it can accommodate existing metadata schemas, so systems don’t need to be rebuilt from scratch. A growing number of third-party applications now support XMP.<br />
<br />
Since early 2012, XMP is also an ISO standard (16684-1).<br />
</blockquote><br />
<br />
The referenced ISO standard has been updated to [https://www.iso.org/standard/75163.html ISO 16684-1:2019 - Graphic technology — Extensible metadata platform (XMP) — Part 1: Data model, serialization and core properties (ISBN:978-0-580-99969-7)]. If you don't have access to the ISO documents, the original [https://www.adobe.com/devnet/xmp.html XMP Specification] documentation is freely available and a very good starting point.<br />
<br />
== Software that supports XMP and could be used with EPrints (and other repository platforms) ==<br />
NB This isn't a definitive list. Other reasonable options may exist. Please document them here if you are using others!<br />
<br />
Some instances of EPrints use a 'coversheets' plugin. The addition of metadata to a document could be considered as a form of 'coversheeting' (albeit a normally invisible one).<br />
Any solution should work with or without any existing coversheet plugin.<br />
<br />
=== ExifTool (Perl module and command-line tool) ===<br />
<br />
* https://exiftool.org/ <br />
* https://metacpan.org/pod/distribution/Image-ExifTool/exiftool<br />
* Available as a package for linux-based systems<br />
<br />
ExifTool can read from / write to many file formats including PDFs. It supports various metadata profiles that can be embedded with XMP and also allows creation of custom profiles to be embedded.<br />
<br />
* [https://exiftool.org/TagNames/XMP.html#cc Creative Commons]<br />
* [https://exiftool.org/TagNames/XMP.html#dc Dublin core]<br />
* [https://exiftool.org/TagNames/XMP.html#pdf PDF native]<br />
* [https://exiftool.org/TagNames/XMP.html#pdfx PDF extensions]<br />
* [https://exiftool.org/TagNames/XMP.html#xmp XML native]<br />
<br />
It seems to be actively developed (latest release June 2020) and is in use by others in our domain [https://blog.research-publishing.net/our-latest-development-8a89f05cfe6d Using exiftool to add extra relevant metadata in pdf files].<br />
<br />
=== PDFBox (Java) ===<br />
<br />
* https://pdfbox.apache.org/docs/2.0.2/javadocs/org/apache/xmpbox/XMPMetadata.html<br />
<br />
=== Other tools/approaches ===<br />
<br />
* PostScript / PDFMARK can add a limited set of metadata to a PDF, but not full XMP as far as I can tell.<br />
<br />
== Technical requirements ==<br />
<br />
* retain original version of document<br />
* either:<br />
** cache copy of document with embedded metadata (a 'volatile version') - similar to some coversheet plugins<br />
** add metadata at point of delivery (could result in slower downloads)<br />
* work with or without coversheet plugins<br />
* support additional metadata - not just licence information<br />
<br />
=== Suggested approach using ExifTool ===<br />
<br />
* Export or convert plugin <br />
** accepts a document<br />
** generates a command-line to call exiftool (specified in 'executables') e.g. <pre>/path/to/exiftool -XMP-dc:Rights="This work is licensed to the public under the Creative Commons Attribution-ShareAlike license http://creativecommons.org/licenses/by-sa/4.0/" -xmp:usageterms="This work is licensed to the public under the Creative Commons Attribution-ShareAlike license http://creativecommons.org/licenses/by-sa/4.0/" "file name.extension"</pre><br />
** data to be embedded controlled by a configuration method<br />
** could call e.g. Export::DC to get suitable eprint-level information<br />
<br />
<br />
<br />
== Possibly useful links ==<br />
<br />
* https://libre-software.net/edit-metadata-exiftool/</div>Libjlrshttps://wiki.eprints.org/w/index.php?title=Plan_S&diff=13490Plan S2020-11-02T10:21:34Z<p>Libjlrs: Add link to A4 'Embedding' page</p>
<hr />
<div>Plan S is an initiative for Open Access publishing that was launched in September 2018. The plan is supported by cOAlition S, an international consortium of research funders. Plan S requires that, from 2021, scientific publications that result from research funded by public grants must be published in compliant Open Access journals or platforms.<br />
<br />
== Requirements of Open Access Repositories ==<br />
EPrints as an Open Access repository must meet a number of requirements. Below are the mandatory and recommended conditions across all publication venues as well as specifically for Open Access repositories. EPrints already meets a lot of the requirements. This page is a work in progress but information will be added to each of the requirements below, including information on one of more of the following categories:<br />
* How EPrints already meets the requirement.<br />
* What plugin or other additional component could be installed to meet the requirement.<br />
* How EPrints could or will be modified to meet (or better meet) the requirement.<br />
* Why it is inappropriate or not possible for EPrints to meet the requirement.<br />
<br />
=== Mandatory technical conditions for all publication venues ===<br />
<br />
A1. Use of persistent identifiers (PIDs) for scholarly publications (with versioning, for example, in case of revisions), such as DOI (preferable), URN, or Handle.<br />
* EPrints provides an ''Identification number'' (''id_number'') field to store DOIs as well as other PIDs such as PubMed ID, etc. There are also separate fields for storing ISSNs and ISBNs.<br />
* Each publication record in EPrints is assigned is own URI in the format: ''http://HOSTNAME/id/eprint/NUMBER'', (e.g. http://eprints.example.org/id/eprint/1234 ).<br />
* There are plans to introduce a IDs, IDs, IDs Bazaar plugin similar to the [http://bazaar.eprints.org/449/ Dates, Dates, Dates] that will allow multiple PIDs to be stored with their types to make recording PIDs more extensible.<br />
<br />
A2. Deposition of content with a long-term digital preservation or archiving programme (such as CLOCKSS, Portico, or equivalent).<br />
<br />
A3. High-quality article level metadata in standard interoperable non-proprietary format, under a CC0 public domain dedication. Metadata must include complete and reliable information on funding provided by cOAlition S funders (including as a minimum the name of the funder and the grant number/identifier).<br />
* EPrints most comprehensive metadata export format is its EP3 XML for which an XML schema for any particular archive is available at /cgi/schema to support interoperability. EPrints also provides metadata export in many other standard interoperable non-proprietary format such as: BibTeX, EndNote, CSV, JSON, Dublin Core, RDF to name but a few. EPrints is extensible to allow repository maintainers to add additional export plugins as necessary.<br />
** For repositories connected to other data sources (e.g. CRIS systems, or paid-for services) the 'CC0' aspect may require a metadata profile that excludes some information such as abstracts, subjects or keywords.<br />
<br />
A4. Machine-readable information on the Open Access status and the license embedded in the article, in standard non-proprietary format.<br />
* EPrints generates a ''full_text_status'' value by analysing the content of a publication record to determine whether this value should be: ''none'', ''public'' or ''restricted''. Each document added to a publication record can be assign a license from a list of available options. Both metadata values are shown in the machine-readable EP3 XML export format and can be used.<br />
** The page [[Plan S - A4 - Embedding data into an article]] contains details of some possible approaches to this requirement.<br />
<br />
=== Strongly recommended additional criteria for all publication venues ===<br />
<br />
B1. Support for PIDs for authors (e.g., ORCID), funders, funding programmes and grants, institutions, and other relevant entities.<br />
<br />
B2. Registering the self-archiving policy of the venue in SHERPA/RoMEO.<br />
<br />
B3. Availability for download of full text for all publications (including supplementary text and data) in a machine-readable community standard format such as JATS XML.<br />
<br />
B4. Direct deposition of publications (in a machine-readable community standard format such as JATS XML, and including complete metadata as described above) by the publisher into author designated or centralised Open Access repositories that fulfil the Plan S criteria.<br />
<br />
B5. OpenAIRE compliance of the metadata.<br />
<br />
B6. Linking to data, code, and other research outputs that underlie the publication and are available in external repositories.<br />
<br />
B7. Openly accessible data on citations according to the standards by the Initiative for Open Citations (I4OC).<br />
<br />
=== Mandatory criteria for repositories ===<br />
<br />
C1. Use of PIDs for the deposited versions of the publications (with versioning, for example in case of revisions), such as DOI (preferable), URN, or Handle.<br />
* Same as A1, see above.<br />
* Clarification is provided in the [https://www.coalition-s.org/faq-theme/technical-requirements/ Plan S FAQs]: <br />
** Q: Does the Author’s Accepted Manuscript (AAM) of an article deposited into an institutional repository have to have a DOI assigned to it?<br />
** A: For cOAlition S articles all AAMs in repositories must have a unique persistent identifier (PID) assigned to them. <br />
<br />
<br />
C2. High quality article level metadata in standard interoperable non-proprietary format, under a CC0 public domain dedication. This must include information on the DOI (or other PIDs) both of the <br />
original publication and the deposited version, on the version deposited (AAM/VoR), and on the Open Access status and the license of the deposited version. Metadata must include complete and reliable information on funding provided by cOAlition S funders (including as a minimum the name of the funder and the grant number/identifier).<br />
* Mostly the same as A3, see above.<br />
* With regard to deposited version the ''Content'' field for a document within a publication record can store version of the file such as: ''Draft Version'', ''Submitted Version'', ''Accepted Version'', ''Published Version'', etc. This field could be modified to use the values such as AAM, VoR, etc. <br />
** The [http://bazaar.eprints.org/1113/ REF Compliance Checker for EPrints] Bazaar plugin provides a mapping from EPrints standard content version for documents to the standardised Open Access versions like VoR and AAM.<br />
* With regard to funder information, by default EPrints provides a field a ''Funders'' field that can indiviually store multiple different funders entered free-hand.<br />
** The [http://bazaar.eprints.org/390/ RIOXX2] Bazaar plugin provides more detailed entry to submit the project ID (i.e. grant reference) and the funders name and ID (as a DOI or ISNI ID).<br />
<br />
C3. Machine readable information on the Open Access status and the license embedded in the article, in standard non-proprietary format.<br />
* Same as A4, see above.<br />
<br />
C4. Continuous availability (uptime at least 99.7%, not taking into account scheduled downtime for maintenance or upgrades).<br />
* EPrints cannot be responsible for the maintenance of the infrastructure on which it runs. However, EPrints has been demonstrated as stable software over a number of years and should not fail and lead to unscheduled downtime in normal circumstances.<br />
<br />
C5. Helpdesk: as a minimum an email address (functional mailbox) has to be provided; a response time of no more than one business day must be ensured.<br />
* By default EPrints requires an admin email address to be set its configuration and this address can be found on the About page of the repository linked off EPrints default main menu.<br />
* EPrints cannot provide any guarantees that the email address has a functional mailbox, as that is the responsibility of the organisation managing the repository.<br />
<br />
=== Strongly recommended additional criteria for repositories ===<br />
<br />
D1. Manuscript submission system that supports both individual author uploads and bulk uploads of manuscripts (AAM or VoR) by publishers.<br />
<br />
D2. Full text stored in a machine-readable community standard format such as JATS XML.<br />
<br />
D3. Support for PIDs for authors (e.g., ORCID), funders, funding programmes and grants, institutions, and other relevant entities.<br />
<br />
D4. Openly accessible data on citations according to the standards by the Initiative for Open Citations (I4OC).<br />
<br />
D5. Open API to allow others (including machines) to access the content. A compliant API must be free to access without any barrier. A light authentication mechanism such as a token for ‘power users’ – e.g., high-traffic collaborators – is acceptable as long as there is a totally open/anonymous route too.<br />
<br />
D6. OpenAIRE compliance of the metadata.<br />
<br />
D7. Quality assurance processes to link full-text deposits with authoritative bibliographic metadata from third party systems, e.g., PubMed, Crossref, or SCOPUS where feasible.</div>Libjlrshttps://wiki.eprints.org/w/index.php?title=Plan_S&diff=13488Plan S2020-10-28T12:33:12Z<p>Libjlrs: Added clarification around PIDs for documents.</p>
<hr />
<div>Plan S is an initiative for Open Access publishing that was launched in September 2018. The plan is supported by cOAlition S, an international consortium of research funders. Plan S requires that, from 2021, scientific publications that result from research funded by public grants must be published in compliant Open Access journals or platforms.<br />
<br />
== Requirements of Open Access Repositories ==<br />
EPrints as an Open Access repository must meet a number of requirements. Below are the mandatory and recommended conditions across all publication venues as well as specifically for Open Access repositories. EPrints already meets a lot of the requirements. This page is a work in progress but information will be added to each of the requirements below, including information on one of more of the following categories:<br />
* How EPrints already meets the requirement.<br />
* What plugin or other additional component could be installed to meet the requirement.<br />
* How EPrints could or will be modified to meet (or better meet) the requirement.<br />
* Why it is inappropriate or not possible for EPrints to meet the requirement.<br />
<br />
=== Mandatory technical conditions for all publication venues ===<br />
<br />
A1. Use of persistent identifiers (PIDs) for scholarly publications (with versioning, for example, in case of revisions), such as DOI (preferable), URN, or Handle.<br />
* EPrints provides an ''Identification number'' (''id_number'') field to store DOIs as well as other PIDs such as PubMed ID, etc. There are also separate fields for storing ISSNs and ISBNs.<br />
* Each publication record in EPrints is assigned is own URI in the format: ''http://HOSTNAME/id/eprint/NUMBER'', (e.g. http://eprints.example.org/id/eprint/1234 ).<br />
* There are plans to introduce a IDs, IDs, IDs Bazaar plugin similar to the [http://bazaar.eprints.org/449/ Dates, Dates, Dates] that will allow multiple PIDs to be stored with their types to make recording PIDs more extensible.<br />
<br />
A2. Deposition of content with a long-term digital preservation or archiving programme (such as CLOCKSS, Portico, or equivalent).<br />
<br />
A3. High-quality article level metadata in standard interoperable non-proprietary format, under a CC0 public domain dedication. Metadata must include complete and reliable information on funding provided by cOAlition S funders (including as a minimum the name of the funder and the grant number/identifier).<br />
* EPrints most comprehensive metadata export format is its EP3 XML for which an XML schema for any particular archive is available at /cgi/schema to support interoperability. EPrints also provides metadata export in many other standard interoperable non-proprietary format such as: BibTeX, EndNote, CSV, JSON, Dublin Core, RDF to name but a few. EPrints is extensible to allow repository maintainers to add additional export plugins as necessary.<br />
<br />
A4. Machine-readable information on the Open Access status and the license embedded in the article, in standard non-proprietary format.<br />
* EPrints generates a ''full_text_status'' value by analysing the content of a publication record to determine whether this value should be: ''none'', ''public'' or ''restricted''. Each document added to a publication record can be assign a license from a list of available options. Both metadata values are shown in the machine-readable EP3 XML export format and can be used.<br />
<br />
=== Strongly recommended additional criteria for all publication venues ===<br />
<br />
B1. Support for PIDs for authors (e.g., ORCID), funders, funding programmes and grants, institutions, and other relevant entities.<br />
<br />
B2. Registering the self-archiving policy of the venue in SHERPA/RoMEO.<br />
<br />
B3. Availability for download of full text for all publications (including supplementary text and data) in a machine-readable community standard format such as JATS XML.<br />
<br />
B4. Direct deposition of publications (in a machine-readable community standard format such as JATS XML, and including complete metadata as described above) by the publisher into author designated or centralised Open Access repositories that fulfil the Plan S criteria.<br />
<br />
B5. OpenAIRE compliance of the metadata.<br />
<br />
B6. Linking to data, code, and other research outputs that underlie the publication and are available in external repositories.<br />
<br />
B7. Openly accessible data on citations according to the standards by the Initiative for Open Citations (I4OC).<br />
<br />
=== Mandatory criteria for repositories ===<br />
<br />
C1. Use of PIDs for the deposited versions of the publications (with versioning, for example in case of revisions), such as DOI (preferable), URN, or Handle.<br />
* Same as A1, see above.<br />
* Clarification is provided in the [https://www.coalition-s.org/faq-theme/technical-requirements/ Plan S FAQs]: <br />
** Q: Does the Author’s Accepted Manuscript (AAM) of an article deposited into an institutional repository have to have a DOI assigned to it?<br />
** A: For cOAlition S articles all AAMs in repositories must have a unique persistent identifier (PID) assigned to them. <br />
<br />
<br />
C2. High quality article level metadata in standard interoperable non-proprietary format, under a CC0 public domain dedication. This must include information on the DOI (or other PIDs) both of the <br />
original publication and the deposited version, on the version deposited (AAM/VoR), and on the Open Access status and the license of the deposited version. Metadata must include complete and reliable information on funding provided by cOAlition S funders (including as a minimum the name of the funder and the grant number/identifier).<br />
* Mostly the same as A3, see above.<br />
* With regard to deposited version the ''Content'' field for a document within a publication record can store version of the file such as: ''Draft Version'', ''Submitted Version'', ''Accepted Version'', ''Published Version'', etc. This field could be modified to use the values such as AAM, VoR, etc. <br />
** The [http://bazaar.eprints.org/1113/ REF Compliance Checker for EPrints] Bazaar plugin provides a mapping from EPrints standard content version for documents to the standardised Open Access versions like VoR and AAM.<br />
* With regard to funder information, by default EPrints provides a field a ''Funders'' field that can indiviually store multiple different funders entered free-hand.<br />
** The [http://bazaar.eprints.org/390/ RIOXX2] Bazaar plugin provides more detailed entry to submit the project ID (i.e. grant reference) and the funders name and ID (as a DOI or ISNI ID).<br />
<br />
C3. Machine readable information on the Open Access status and the license embedded in the article, in standard non-proprietary format.<br />
* Same as A4, see above.<br />
<br />
C4. Continuous availability (uptime at least 99.7%, not taking into account scheduled downtime for maintenance or upgrades).<br />
* EPrints cannot be responsible for the maintenance of the infrastructure on which it runs. However, EPrints has been demonstrated as stable software over a number of years and should not fail and lead to unscheduled downtime in normal circumstances.<br />
<br />
C5. Helpdesk: as a minimum an email address (functional mailbox) has to be provided; a response time of no more than one business day must be ensured.<br />
* By default EPrints requires an admin email address to be set its configuration and this address can be found on the About page of the repository linked off EPrints default main menu.<br />
* EPrints cannot provide any guarantees that the email address has a functional mailbox, as that is the responsibility of the organisation managing the repository.<br />
<br />
=== Strongly recommended additional criteria for repositories ===<br />
<br />
D1. Manuscript submission system that supports both individual author uploads and bulk uploads of manuscripts (AAM or VoR) by publishers.<br />
<br />
D2. Full text stored in a machine-readable community standard format such as JATS XML.<br />
<br />
D3. Support for PIDs for authors (e.g., ORCID), funders, funding programmes and grants, institutions, and other relevant entities.<br />
<br />
D4. Openly accessible data on citations according to the standards by the Initiative for Open Citations (I4OC).<br />
<br />
D5. Open API to allow others (including machines) to access the content. A compliant API must be free to access without any barrier. A light authentication mechanism such as a token for ‘power users’ – e.g., high-traffic collaborators – is acceptable as long as there is a totally open/anonymous route too.<br />
<br />
D6. OpenAIRE compliance of the metadata.<br />
<br />
D7. Quality assurance processes to link full-text deposits with authoritative bibliographic metadata from third party systems, e.g., PubMed, Crossref, or SCOPUS where feasible.</div>Libjlrshttps://wiki.eprints.org/w/index.php?title=Add_repository_metrics_to_homepage&diff=13448Add repository metrics to homepage2020-08-19T14:11:38Z<p>Libjlrs: </p>
<hr />
<div>This page was created in response to a question on the EPrints Tech List.<br />
<br />
There are a number of ways to achieve this. The approach below is a fairly minimal solution. It uses a small piece of javascript to pull data back from a custom CGI script.<br />
<br />
One alternative solution would be to create an EPScript method, and include the output of that in the index page. The problem with that approach is that the index gets saved as a static document, and wouldn't by default include an up-to-date count of items.<br />
<br />
Another method would be to use [[How to enable server side includes|Server Side Includes]].<br />
<br />
== Required components ==<br />
<br />
1. Script to return paragraph element detailing total items - saved as <code>[EPRINTS_ROOT]/archives/[ARCHIVEID]/cgi/item_count</code><br />
<br />
<source lang="perl"><br />
use EPrints;<br />
<br />
use strict;<br />
<br />
my $eprints = EPrints->new;<br />
my $repo = $eprints->current_repository;<br />
exit( 0 ) unless( defined $repo );<br />
<br />
$repo->send_http_header( content_type=>"text/plain; charset=UTF-8" );<br />
<br />
my $dataset = $repo->dataset( "archive" );<br />
print sprintf("<p>There are %d records in this archive.</p>",<br />
$dataset->count);<br />
<br />
exit;<br />
</source><br />
<br />
The script above isn't perfect - it should possibly use a phrase for the returned paragraph (with the $count added using a pin).<br />
<br />
<br />
2. Addition to the index page <code>[EPRINTS_ROOT]/archives/[ARCHIVEID]/cfg/lang/en/static/index.xpage</code><br />
This calls the script above and adds the returned text to the element added<br />
<source lang="html5"><br />
<div id="item_count" /><br />
<script><br />
document.observe( "dom:loaded", function() {<br />
// The first parameter below is the id of the element added above.<br />
// The second is the URL to call<br />
// The third is a hash of Ajax options<br />
// The 'Updater' class adds the returned html to the specified element.<br />
new Ajax.Updater( "item_count", 'cgi/total_items', { 'method': 'GET' } );<br />
});<br />
</script><br />
<br />
</source> <br />
<br />
<br />
<br />
[[Category:Howto]]<br />
[[Category:Snippets]]</div>Libjlrshttps://wiki.eprints.org/w/index.php?title=How_to_enable_server_side_includes&diff=13447How to enable server side includes2020-08-19T13:55:01Z<p>Libjlrs: </p>
<hr />
<div>{{Version|since=3.2.1}}<br />
<br />
You must have the [http://httpd.apache.org/docs/2.0/howto/ssi.html Apache Server Side Includes (SSI)] module installed and enabled.<br />
<br />
This enables you to add includes to the content of static pages. If you want to add dynamic content to the template you should do this via a template part in cfg.d/dynamic_template.pl.<br />
<br />
===Configuration===<br />
<br />
Edit <tt>cfg/apache/[repoid].conf</tt> and add to the <tt><Location></tt> section <tt>AddOutputFilter</tt> and <tt>+Includes</tt>:<br />
<Location "/eprints"><br />
PerlSetVar EPrints_ArchiveID myrepo<br />
<br />
<b>AddOutputFilter INCLUDES .html</b><br />
<br />
Options +ExecCGI <b>+Includes</b><br />
Order allow,deny <br />
Allow from all<br />
</Location><br />
<br />
Restart apache.<br />
<br />
===Example===<br />
<br />
&lt;!--#include virtual="/cgi/mydynbit"--&gt;<br />
<br />
==Issues calling cgi scripts with parameters (issue seen with v3.3.16 / Apache 2.4 / Ubuntu)==<br />
<br />
When trying to include a URL with parameters, the EPrints stack will see the URL parameters of the main page, not the included request e.g. if this include:<br />
<source lang="xml"><br />
<!--#include virtual="/cgi/latest_tool?mode=test&mainonly=yes" --><br />
</source><br />
was used on the main index page, if the page was requested with no URL parameters, the <tt>latest_tool</tt> would not see the <tt>mode=test</tt>, or <tt>mainonly=yes</tt> parameters.<br />
<br />
===Solution===<br />
The cgi script needs to determine whether it is the main apache request, or a sub-request (e.g. the SSI).<br />
<br />
The following line, placed near the top of the cgi script appears to resolve the issue.<br />
<br />
<source lang="perl"><br />
local $session->{query} = CGI->new( $session->get_request ) if( !$session->get_request->is_initial_req );<br />
</source><br />
<br />
[[Category:Howto]]</div>Libjlrshttps://wiki.eprints.org/w/index.php?title=Installing_EPrints_on_RHEL/Fedora/CentOS&diff=13359Installing EPrints on RHEL/Fedora/CentOS2020-06-10T14:46:30Z<p>Libjlrs: /* Installing from EPrints 3.3.x RPM */ Clarification on rpm versions available from rpm.eprints.org</p>
<hr />
<div>[[Category:Installation]]<br />
<br />
==Requirements==<br />
<br />
* RedHat Enterprise (RHEL) / CentOS 7 or Fedora 25+. These instructions will more than likely work for RHEL / CentOS 6 but have not been as thoroughly tested.<br />
<br />
* Pre-installed MySQL server and client.<br />
** RHEL / Fedora:<br />
yum install mysql-server mysql<br />
** CentOS:<br />
yum install mariadb-server mariadb<br />
<br />
== Installing from EPrints 3.3.x RPM ==<br />
<br />
'''Please note that rpm.eprints.org is no longer fully supported. The below instructions should still work for installing EPrints up to v3.3.15 on RHEL/CentOS 6 and 7 and comparable versions of Fedora.'''<br />
<br />
'''The latest releases (3.3.16+) are not available from rpm.eprints.org, but can be downloaded as an RPM from http://files.eprints.org/'''<br />
<br />
Add the rpm.eprints.org repository key:<br />
<br />
rpm -ivh http://rpm.eprints.org/rpm-eprints-org-key-1-1.noarch.rpm<br />
<br />
Next, add the rpm.eprints.org EPrints repository:<br />
<br />
rpm -ivh http://rpm.eprints.org/eprints/noarch/rpm-eprints-org-1-1.noarch.rpm<br />
<br />
Note: if these fail to connect to the repository and you have a proxy server, try adding the parameter "--httpproxy http://your.proxy.address" (export http_proxy doesn't affect rpm call)<br />
<br />
Install required XML libraries (Use ''yum upgrade'' if these are already installed):<br />
<br />
yum install libxml2 libxslt perl-XML-LibXML perl-XML-LibXSLT<br />
<br />
Finally, install EPrints 3:<br />
<br />
yum install eprints<br />
<br />
== Installing EPrints 3.4.x from Source ==<br />
'''N.B. Installing from source is generally discouraged particularly for production repositories. However, if want to develop the EPrints code or a plugin or Bazaar package it may be useful to install from source, ideally from [https://github.com/eprints/eprints3.4 EPrints Core Git repository].'''<br />
<br />
First, install the EPEL YUM package repository and run yum repolist to ensure the GPG key is installed:<br />
<br />
yum install epel-release<br />
yum repolist<br />
<br />
Now, install all the dependencies that would be installed through the eprints RPM.<br />
<br />
yum install libxml2 libxslt httpd mod_perl perl-DBI perl-DBD-MySQL perl-IO-Socket-SSL perl-Time-HiRes \<br />
perl-CGI perl-Digest-MD5 perl-Digest-SHA perl-JSON perl-XML-LibXML perl-XML-LibXSLT perl-XML-SAX \<br />
perl-MIME-Lite perl-Text-Unidecode perl-JSON perl-Unicode-Collate perl-Pod-LaTeX perl-LWP-Protocol-https \ <br />
tetex-latex wget gzip tar ImageMagick elinks poppler-utils chkconfig unzip cpan<br />
<br />
Next, create the eprints user<br />
<br />
adduser eprints<br />
<br />
Next, clone the Git repository from GitHub to /opt/ and set the eprints user as the owner. It is probably best to checkout the latest release rather than using HEAD, which may have known issues:<br />
<br />
yum install git<br />
git clone https://github.com/eprints/eprints.git /opt/eprints3<br />
cd /opt/eprints3/<br />
git checkout tags/v3.4.1<br />
chown -R eprints:eprints . <br />
<br />
Next, as the eprints user copy /opt/eprints3/perl_lib/EPrints/SystemSettings.pm.tmpl to /opt/eprints3/perl_lib/Eprints/SystemSettings.pm<br />
<br />
EPrints is now fully installed at /opt/eprints3. However, you will not yet have a running archive. Follow the [[Getting Started with EPrints 3]] instructions to set this up.<br />
<br />
Now update Apache configuration to set it up to use the eprints user and group, by ensuring the following lines are set thus in /etc/httpd/conf/httpd.conf:<br />
<br />
User eprints<br />
Group eprints<br />
<br />
Now add the file /etc/httpd/conf.d/eprints.conf with the following line:<br />
<br />
Include /opt/eprints3/cfg/apache.conf<br />
<br />
There is a good chance your operating system will have SELinux enabled. If so, follow the instructions under Troubleshooting for how to let EPrints do what it needs to do through SELinux.<br />
<br />
Finally, restart Apache:<br />
<br />
service httpd restart<br />
<br />
You should now be able to access your vanilla repository at the hostname you specified when running '''epadmin create''' from the [[Getting Started with EPrints 3]] instructions. You should then login as the admin user you created during this process and turn on the indexer. This can be done by clicking on the '''Admin''' link under the Logged in menu, then clicking on the '''System Tools''' tab and finally the '''Start Indexer''' button.<br />
<br />
== Non-critical Dependencies ==<br />
Some of EPrints non-core functionality may not work out of the box as these dependencies are not included as part of the RPM. Here is a list of known additional packages (and the YUM repositories in which they can be found) or CPAN modules than can be installed. <br />
<br />
Some of these known additional packages are only available through the Extra Packages for Enterprise Linux (EPEL) YUM repository, which can be installed as the root user as follows:<br />
<br />
yum -y install epel-release<br />
yum repolist <br />
<br />
CPAN modules should be installed using the ''cpan'' command as the root user.<br />
<br />
* '''perl-Geo-IP (epel)''' - Allows IRstats2 to determine the location of views/downloads for publications.]<br />
* '''perl-Spreadsheet-WriteExcel (epel)''' - To allow Multiline Excel export.<br />
* '''CPAN module Text::Refer''' - Required for EndNote import.<br />
* '''CPAN module TeX::Encode''' Required for BibTex export.<br />
* '''perl-Image-ExifTool (epel)''' - Sometimes needed to support generation of thumbnails for uploaded documents/images.<br />
* '''perl-LWP-Protocol-https (base)''' - Needed by DataCite plugin to register repository DOIs.<br />
<br />
== Next steps ==<br />
<br />
Configure eprints per [[Getting_Started_with_EPrints_3]].<br />
<br />
== Operating System Version Specific Requirements ==<br />
<br />
=== RHEL / CentOS 6 ===<br />
{{:Issues with installing EPrints on RHEL 6}}<br />
<br />
=== RHEL / CentOS 7 ===<br />
No significant issues.<br />
<br />
=== RHEL / CentOS 8 ===<br />
{{:Issues with installing EPrints on RHEL 8}}<br />
<br />
== Troubleshooting ==<br />
* [[EPrints and SELinux|Advice for enabling SELinux with EPrints]]</div>Libjlrshttps://wiki.eprints.org/w/index.php?title=Setting_up_HTTPS_using_Let%27s_Encrypt&diff=13304Setting up HTTPS using Let's Encrypt2020-05-07T14:45:15Z<p>Libjlrs: Add details of URL_REWRITE trigger to handle .well-known URLS</p>
<hr />
<div>{{Manual}}<br />
By default EPrints does not come setup to use HTTPS. This is because you need to generate a SSL certificate and if this is not signed by a known Certificate Authority a user's web browser is likely to complain vigorously. In the past it has typically costed a fair amount of money to obtain a SSL certificate from your hosting provider. However, now there is [https://letsencrypt.org/ Let's Encrypt] it is possible to get a certificate for free. This is not to say you should use Let's Encrypt in all cases. UK academic institutions should continue to obtain their SSL certificates through Jisc and other institutions/organisations may already have similar arrangements for obtaining SSL certificates.<br />
<br />
As well as being free, Let's Encrypt has an automated way for renewing certificates. However, it should be noted that the length of its certificates is a lot shorter at just 3 months. As the renewal process is automatic, this time period is more appropriate to maximise security. Let's Encrypt's certificate generation requires your EPrints repository to be publicly accessible. Beneath are instructions on how to set up EPrints to enable HTTPS with a Let's Encrypt certificate.<br />
<br />
1. Go to the https://certbot.eff.org/ and follow the instructions for your web server and operating system (the former will almost always be Apache) and follow the instructions provided.<br />
<br />
2. When you get to the point of running the certbot command you want the certificate only so should type as the root user:<br />
<br />
certbot --apache certonly<br />
<br />
3. Take a note of the path to were your certificate, key and CA chain have been saved. This will probably be something like<br />
<br />
/etc/letsencrypt/live/YOUR-REPOSITORY-DOMAIN/<br />
<br />
4. If you have not already done so, create an directory called <tt>ssl</tt> inside your archive's directory, i.e.<br />
<br />
mkdir EPRINTS_PATH/archives/REPOID/ssl/<br />
<br />
5. Create a file inside the new ssl directory called <tt>securevhost.conf</tt> and include the following contents, amending the <tt>ServerName</tt>, <tt>SSLCertificateFile</tt>, <tt>SSLCertificateKeyFile</tt> <tt>SSLCertificateChainFile</tt> and <tt>Include</tt> as appropriate at least. You will note that this configuration also enables [https://en.wikipedia.org/wiki/HTTP_Strict_Transport_Security HTTP Strict Transport Security (HSTS)] for additional security. This ensures that after the first time you visit HTTPS for a particular site in your web browser, all future HTTP requests for this hostname will automatically be converted by your browser to HTTPS.<br />
<br />
<VirtualHost *:443><br />
<br />
ServerName YOUR-REPOSITORY-DOMAIN:443<br />
<br />
# Enable HSTS<br />
Header always set Strict-Transport-Security "max-age=63072000;"<br />
<br />
SSLEngine on<br />
SSLProtocol all -SSLv2 -SSLv3<br />
SSLHonorCipherOrder on<br />
SSLCipherSuite HIGH:!aNULL:!eNULL:!kECDH:!aDH:!RC4:!3DES:!CAMELLIA:!MD5:!PSK:!SRP:!KRB5:@STRENGTH<br />
<br />
SSLCertificateFile /etc/letsencrypt/live/YOUR-REPOSITORY-DOMAIN/cert.pem<br />
SSLCertificateKeyFile /etc/letsencrypt/live/YOUR-REPOSITORY-DOMAIN/privkey.pem<br />
SSLCertificateChainFile /etc/letsencrypt/live/YOUR-REPOSITORY-DOMAIN/chain.pem<br />
<br />
SetEnvIf User-Agent ".*MSIE.*" \<br />
nokeepalive ssl-unclean-shutdown \<br />
downgrade-1.0 force-response-1.0<br />
<br />
LogLevel warn<br />
ErrorLog logs/ssl_error_log <br />
TransferLog logs/ssl_access_log<br />
CustomLog logs/ssl_request_log \<br />
"%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"<br />
<br />
Include EPRINTS_PATHH/cfg/apache_ssl/REPOID.conf<br />
<br />
PerlTransHandler +EPrints::Apache::Rewrite<br />
<br />
</VirtualHost><br />
<br />
6. If you have not already done so, add a configuration file at <tt>/opt/eprints3/archives/REPOID/cfg/cfg.d/https.pl</tt> with the following configuration:<br />
<br />
$c->{securehost} = $c->{host};<br />
$c->{secureport} = 443;<br />
$c->{http_root} = undef;<br />
<br />
7. Now you will need to regenerate the rest of your Apache configuration for EPrints with the following command run as the EPrints user. (Substitute the path as appropriate):<br />
<br />
/opt/eprints3/bin/generate_apacheconf --system --replace<br />
<br />
8. Apache will not yet have been setup to include the Apache configuration file you created in step 5. To include this, you will need to edit the file in your Apache configuration directory (<tt>/etc/httpd/</tt> on RHEL/CentOS/Fedora and <tt>/etc/apache2/</tt> on Debian/Ubuntu) and find the file that contains the line <tt>cfg/apache.conf</tt>, e.g.<br />
<br />
cd /etc/httpd/<br />
grep -r "cfg/apache.conf" *<br />
<br />
9. Once you have found it you will need to edit it and add the following line, changing the path as appropriate:<br />
<br />
Include EPRINTS_PATH/archives/REPOID/ssl/securevhost.conf<br />
<br />
10. Now, (as root or using sudo) test that the Apache configuration is correct and fix any issues if necessary:<br />
<br />
apachectl configtest<br />
<br />
11. Restart Apache and check whether you can access your EPrints repository using HTTPS in a web browser:<br />
<br />
apachectl restart<br />
<br />
12. If the guide on cerbot.eff.org you used in step 1 tells you to to setup a cron job then follow those instructions. The easiest way to do this is probably to run <tt>crontab -e</tt> as root and add the following cron job, substituting the minute (43) and hours (6,18) for you own choice maintaining a 12 hour gap between the hours:<br />
<br />
43 6,18 * * * certbot renew<br />
<br />
<br />
== Additional Notes ==<br />
<br />
The default EPrints Apache Rewrite handler declines any requests to a URL containing <code>/.</code>.<br />
<br />
This means that the challenge/response for a LetsEncrypt certificate renewal that uses the <code>/.well-known/acme-challenge/</code> path will fail.<br />
<br />
To make this work you could add a location block to your Apache config, to ensure the <code>/.well-known/</code> are not handled by EPrints, or use an EPrints URL rewrite trigger to handle the request:<br />
<br />
<source lang="perl"><br />
#this could be saved into e.g. [EPRINTS_ROOT]/lib/cfg.d/z_rewrite_url_LetsEncrypt.pl<br />
<br />
# import Apache constant e.g. 'OK'<br />
use EPrints::Apache::AnApache;<br />
<br />
$c->add_trigger( EP_TRIGGER_URL_REWRITE, sub {<br />
my( %o ) = @_;<br />
<br />
# if the incoming request matches the LetsEncrypt challenge URL...<br />
if( $o{uri} =~ m!^${o{urlpath}}/\.well-known/acme-challenge/! )<br />
{<br />
# and the LetsEncrypt renewal process has put the file in EPRINTS_ROOT/archives/ARCHIVEID/html/.well-known/acme-challenge/<br />
if( -f $o{repository}->get_conf( "htdocs_path" ).$o{uri} )<br />
{<br />
# reply with an HTTP '200' <br />
${$o{return_code}} = OK;<br />
# and return the file reqested<br />
$o{request}->filename( $o{repository}->get_conf( "htdocs_path" ).$o{uri} );<br />
}<br />
# and say that we've handled the request - so no more triggers should be run.<br />
return EP_TRIGGER_DONE;<br />
}<br />
} );<br />
</source></div>Libjlrshttps://wiki.eprints.org/w/index.php?title=Add_repository_metrics_to_homepage&diff=13258Add repository metrics to homepage2019-08-13T17:13:21Z<p>Libjlrs: More properly... use dataset count</p>
<hr />
<div>This page was created in response to a question on the EPrints Tech List.<br />
<br />
There are a number of ways to achieve this. The approach below is a fairly minimal solution. It uses a small piece of javascript to pull data back from a custom CGI script.<br />
<br />
One alternative solution would be to create an EPScript method, and include the output of that in the index page. The problem with that approach is that the index gets saved as a static document, and wouldn't by default include an up-to-date count of items.<br />
<br />
<br />
== Required components ==<br />
<br />
1. Script to return paragraph element detailing total items - saved as <code>[EPRINTS_ROOT]/archives/[ARCHIVEID]/cgi/item_count</code><br />
<br />
<source lang="perl"><br />
use EPrints;<br />
<br />
use strict;<br />
<br />
my $eprints = EPrints->new;<br />
my $repo = $eprints->current_repository;<br />
exit( 0 ) unless( defined $repo );<br />
<br />
$repo->send_http_header( content_type=>"text/plain; charset=UTF-8" );<br />
<br />
my $dataset = $repo->dataset( "archive" );<br />
print sprintf("<p>There are %d records in this archive.</p>",<br />
$dataset->count);<br />
<br />
exit;<br />
</source><br />
<br />
The script above isn't perfect - it should possibly use a phrase for the returned paragraph (with the $count added using a pin).<br />
<br />
<br />
2. Addition to the index page <code>[EPRINTS_ROOT]/archives/[ARCHIVEID]/cfg/lang/en/static/index.xpage</code><br />
This calls the script above and adds the returned text to the element added<br />
<source lang="html5"><br />
<div id="item_count" /><br />
<script><br />
document.observe( "dom:loaded", function() {<br />
// The first parameter below is the id of the element added above.<br />
// The second is the URL to call<br />
// The third is a hash of Ajax options<br />
// The 'Updater' class adds the returned html to the specified element.<br />
new Ajax.Updater( "item_count", 'cgi/total_items', { 'method': 'GET' } );<br />
});<br />
</script><br />
<br />
</source> <br />
<br />
<br />
<br />
[[Category:Howto]]<br />
[[Category:Snippets]]</div>Libjlrshttps://wiki.eprints.org/w/index.php?title=Add_repository_metrics_to_homepage&diff=13257Add repository metrics to homepage2019-08-13T16:50:29Z<p>Libjlrs: Created page with "This page was created in response to a question on the EPrints Tech List. There are a number of ways to achieve this. The approach below is a fairly minimal solution. It uses..."</p>
<hr />
<div>This page was created in response to a question on the EPrints Tech List.<br />
<br />
There are a number of ways to achieve this. The approach below is a fairly minimal solution. It uses a small piece of javascript to pull data back from a custom CGI script.<br />
<br />
One alternative solution would be to create an EPScript method, and include the output of that in the index page. The problem with that approach is that the index gets saved as a static document, and wouldn't by default include an up-to-date count of items.<br />
<br />
<br />
== Required components ==<br />
<br />
1. Script to return paragraph element detailing total items - saved as <code>[EPRINTS_ROOT]/archives/[ARCHIVEID]/cgi/item_count</code><br />
<br />
<source lang="perl"><br />
use EPrints;<br />
<br />
use strict;<br />
use warnings;<br />
<br />
my $session = EPrints::Session->new();<br />
<br />
my $r = $session->get_request;<br />
<br />
my $sql = "SELECT COUNT(*) FROM eprint WHERE eprint_status = 'archive'";<br />
<br />
my $sth = $session->get_database->prepare_select( $sql );<br />
$session->get_database->execute( $sth , $sql );<br />
<br />
my ($count) = $sth->fetchrow_array;<br />
<br />
$session->send_http_header( content_type => "text/html; charset=UTF-8" );<br />
if( $count ){<br />
print "<p>There are $count records.</p>";<br />
}<br />
exit;<br />
<br />
</source><br />
<br />
The script above isn't perfect - it should possibly use a phrase for the returned paragraph (with the $count added using a pin), and the script could search the 'archive' dataset, rather than looking into the database.<br />
There is no error checking (so if the database doesn't respond, you'll probably get an ugly message).<br />
<br />
<br />
2. Addition to the index page <code>[EPRINTS_ROOT]/archives/[ARCHIVEID]/cfg/lang/en/static/index.xpage</code><br />
This calls the script above and adds the returned text to the element added<br />
<source lang="html5"><br />
<div id="item_count" /><br />
<script><br />
document.observe( "dom:loaded", function() {<br />
// The first parameter below is the id of the element added above.<br />
// The second is the URL to call<br />
// The third is a hash of Ajax options<br />
// The 'Updater' class adds the returned html to the specified element.<br />
new Ajax.Updater( "item_count", 'cgi/total_items', { 'method': 'GET' } );<br />
});<br />
</script><br />
<br />
</source> <br />
<br />
<br />
<br />
[[Category:Howto]]<br />
[[Category:Snippets]]</div>Libjlrshttps://wiki.eprints.org/w/index.php?title=Main_Page&diff=13101Main Page2018-11-20T09:49:13Z<p>Libjlrs: Re-order mailing lists - quite a few technical questions end up on the UK list where the tech list would probably be a better first port of call.</p>
<hr />
<div>[[Category:Howto]]__NOTOC__<br />
'''Welcome to the EPrints Wiki'''<br />
<br />
This wiki contains technical and user-contributed documentation for the [[Introduction|EPrints software]].<br />
<br />
[http://demoprints.eprints.org/ Demoprints] is our live, online server that allows anyone to try EPrints without having to install it first.<br />
<br />
For more information on the EPrints project and related activities visit http://eprints.org/.<br />
<br />
==New to EPrints?==<br />
<br />
On this wiki you can find:<br />
<br />
* [[:Category:Training Video|Video Training Course]]<br />
* [[EPrints_Manual|Documentation]] <br />
* [[Working Groups]]<br />
* Mailing lists - There are two mail lists that you might like to join and where you can ask for help and share ideas:<br />
** '''The EPrints Technical Mailing List''' <br />
*** Joining information for [[Contact| EPrints Tech list]]<br />
*** If you have technical questions, or a part of your EPrints installation is not working properly, this group has people who might be able to help!<br />
** '''The EPrints User Group Google Group''' https://groups.google.com/forum/#!forum/eprints-uk-user-group<br />
*** This group is for anyone involved in using EPrints. Ask questions, share ideas, hear about forthcoming meetings.<br />
* How to [[Wiki_editing_guidlines|contribute to the EPrints wiki]]<br />
* EPrints source code on GitHub:<br />
** Core and major plugins - https://github.com/eprints<br />
** Community code sharing - http://eprintsug.github.io and the repositories at https://github.com/eprintsug<br />
<br />
== Download EPrints ==<br />
<br />
{{Download}}<br />
<br />
==Installation==<br />
<br />
* [[:Category:Installation|Installing]] EPrints on various platforms<br />
<br />
==Getting Started==<br />
<br />
* [[EPrints Manual|EPrints 3 Documentation]]<br />
* [[Perl 101 for EPrints]]<br />
* [http://www.eprints.org/software/training/ Training materials] provided by EPrints Services.<br />
* [[Frequently Asked Questions]]<br />
* [[:Category:Howto|How to...]]<br />
* [[:Category:Plugins|Plugins and Bazaar packages for EPrints]]<br />
* [[:Category:Training Video|EPrints Training Course]]<br />
<br />
==Getting Support==<br />
<br />
* [http://www.eprints.org/services/ EPrints Services] - premium support, training and hosting from EPrints experts<br />
* [[Contact]] - mailing lists, bug reports etc.<br />
* [[User group meetings]] - regional meetings for users, which often have notes, presentations and information of general interest<br />
<br />
==Add-ons, patches and translations==<br />
<br />
* As of version 3.3 EPrints can now install plugins and translations through the [https://bazaar.eprints.org EPrints Bazaar] the wiki also has information about [[:Category:EPrints Bazaar|packaging plugins for the Bazaar]].<br />
* The [http://files.eprints.org/ EPrints Files Repository] contains add-on and 3rd party scripts, patches and translations. This also provides an archive of all previous EPrints releases (3.0 onwards).<br />
* [[:Category:Plugins|Plugins]]: Some Wiki pages about scripts and patches.<br />
<br />
{{Register}}<br />
<br />
==Contributing to EPrints==<br />
<br />
* [[Usability|EPrints usability]]<br />
* [[:Category:Releases|New features in EPrints]] - released and proposed<br />
* [[How to contribute|How to contribute to EPrints development]]<br />
* [http://trac.eprints.org/ EPrints Trac] - access nightly builds, tickets and changes (requires free registration to view source code)<br />
* [[EPrints4 Roadmap]]<br />
* [[EPrints3 Roadmap]] - 2016 Community Roadmap<br />
<br />
== Content management ==<br />
<br />
* [[Digital preservation]]: managing content for longer-term access and use</div>Libjlrshttps://wiki.eprints.org/w/index.php?title=ORCID&diff=12847ORCID2018-08-29T16:27:42Z<p>Libjlrs: /* OAI-PMH (Experimental) */</p>
<hr />
<div>This page has been created to gather information about how different EPrints repositories have integrated ORCID.<br />
At this time (April 2016) there doesn't seem to be a 'best practice' approach that has been adopted widely - this will hopefully change over time.<br />
<br />
==Field Recommendations==<br />
As at 2016-10-18 these are the recommended field names and types as discussed at the Jisc ORCID hack day in London - Alan Stiles, John Salter, Adam Vials Moore, Peter West, Andrew Beeken<br />
<br />
===New MetaField Type===<br />
* Type 'Orcid' is a subtype of 'id', provides validation and render methods <br />
N.B. Store the 16 digit, hyphen separated value, without the authority (host) details e.g. 'nnnn-nnnn-nnnn-nnnn' (as per the value returned by the ORCID API)<br />
<br />
===User Object===<br />
*new field named 'orcid', type 'Orcid' to store the value of the ORCID id for that user<br />
<br />
====Suggested fields====<br />
*'orcid_auth_code', type text - to hold the long authorisation token returned by the ORCID API at the end of a successful OAuth2 process<br />
*'orcid_granted_permissions', type text - to hold the permissions granted via the ORCID API during the authorisation process<br />
*'orcid_token_expires', type time - to hold the expiry timestamp for the authorisation code above (time now plus expires duration returned by the ORCID API)<br />
*'orcid_last_update_timestamp', type text - to hold the timestamp of the last time the user's ORCID record was processed, to enable quicker reprocessing in the future.<br />
*'orcid_webhook_ref', type text - to hold the value provided when configuring the webhook notification to validate new notifications have come from ORCID<br />
<br />
Also potential fields for requested permissions .e.g. boolean flags or text to capture auth codes if individual permissions captured separately? (e.g. Peter West work)<br />
<br />
===Eprints Contributors (e.g. creators, editors)===<br />
*new sub-field of contributor_orcid (e.g. creator_orcid, editor_orcid) type 'Orcid' to store the value of the ORCID id for that contributor<br />
<br />
==Bazaar package==<br />
See: https://github.com/eprints/orcid_support for an beta-release Bazaar package to help with ORCID support.<br />
<br />
==Previous Discussions==<br />
If you are looking to retrieve publications from the ORCID service, the [http://bazaar.eprints.org/354/ Import from ORCID (Tier 1 API)] Bazaar package, or the [https://github.com/eprintsug/orcidt2 ORCID Tier 2 api framework] are good places to start.<br />
<br />
2016-05-20 [[User:Alan.stiles@open.ac.uk|Alan Stiles]] at The Open University is working on a plugin to connect EPrints with ORCID via the Tier 2 Members API to retrieve ORCID ids and synchronise publications and affiliation details.<br />
<br />
Some aspects that need to be considered when adopting ORCIDs, and making them available to other systems are:<br />
<br />
* storing the ORCID (see: http://support.orcid.org/knowledgebase/articles/116780-structure-of-the-orcid-identifier)<br />
* rendering the ORCID in abstract pages (see [http://support.orcid.org/knowledgebase/articles/116780-structure-of-the-orcid-identifier link above])<br />
* exposing ORCIDs over OAI-PMH metadata profiles e.g. RIOXX<br />
<br />
NB The examples below may refer to the 'creators' field - but the same approach could be used to extend other 'person' fields - e.g. contributors.<br />
<br />
= Re-using creators.id subfield =<br />
<br />
The creators.id field is labelled 'email' by default, but as it's an 'id' type field, it can be used to store ORCIDs.<br />
To re-label the field, a simple addition to a phrase file in <code>archives/ARCHIVEID/cfg/lang/en/phrases/</code> needs to be made:<br />
<source lang="xml"><br />
<epp:phrase id="eprint_fieldname_creators_id">ORCID / Creators email (if known)</epp:phrase><br />
</source><br />
<br />
== Rendering the ORCID in a citation ==<br />
The rendering of this field then needs to be changed to accommodate an author with an ORCID. The following script adds methods that can be called via the EPScript language:<br />
<br />
<source lang="perl"><br />
# add to e.g. ~/archives/ARCHIVEID/cfg/cfg.d/z_add_to_EPrints_Script_Compiled.pl<br />
# Write into EPrints::Script::Compiled package to allow use of function in epscript<br />
{<br />
package EPrints::Script::Compiled;<br />
use strict;<br />
<br />
sub run_wrro_people_with_orcids<br />
{<br />
my( $self, $state, $value ) = @_;<br />
<br />
my $session = $state->{session};<br />
my $r = $state->{session}->make_doc_fragment;<br />
<br />
my $creators = $value->[0];<br />
<br />
foreach my $i (0..$#$creators){<br />
<br />
my $creator = @$creators[$i];<br />
<br />
if( $i > 0 ){<br />
#not first item (or only one item)<br />
if( $i == $#$creators ){<br />
#last item<br />
$r->appendChild( $session->make_text( " and " ) );<br />
} else {<br />
$r->appendChild( $session->make_text( ", " ) );<br />
}<br />
}<br />
<br />
my $person_span = $session->make_element( "span", "class" => "person" );<br />
$person_span->appendChild( $session->render_name( $creator->{name} ) );<br />
<br />
my $id = $creator->{id};<br />
if( defined $id && $id =~ m/^(?:orcid.org\/)?(\d{4}\-\d{4}\-\d{4}\-\d{3}(?:\d|X))$/ )<br />
{<br />
my $orcid_span = $session->make_element( "span", "class" => "orcid" );<br />
<br />
# According to https://orcid.org/trademark-and-id-display-guidelines<br />
# "recommended display is a hyperlinked URI preceded by the iD icon"<br />
# This looks terrible in a citation. Removed for the time being.<br />
#<br />
# my $orcid_link = $session->make_element(<br />
# "a",<br />
# "href" => "http://orcid.org/",<br />
# "target" => "_blank",<br />
# "class" => "orcid-icon"<br />
# );<br />
# $orcid_link->appendChild( $session->make_element(<br />
# "img",<br />
# "src" => "/images/orcid_16x16.png",<br />
# "title" => "ORCID"<br />
# ) );<br />
# $orcid_span->appendChild( $orcid_link );<br />
<br />
my $link = $session->make_element(<br />
"a",<br />
"href" => "http://orcid.org/$1",<br />
"target" => "_blank",<br />
);<br />
$link->appendChild( $session->make_text( "orcid.org/$1" ) );<br />
<br />
$orcid_span->appendChild( $session->make_text( "(" ) );<br />
$orcid_span->appendChild( $link );<br />
$orcid_span->appendChild( $session->make_text( ")" ) );<br />
<br />
$person_span->appendChild( $session->make_text( " " ) );<br />
$person_span->appendChild( $orcid_span );<br />
}<br />
$r->appendChild( $person_span );<br />
}<br />
<br />
return [ $r, "XHTML" ];<br />
}<br />
<br />
}<br />
# END EPrints::Script::Compiled additions<br />
</source><br />
<br />
You may also want a bit of CSS to style ORCID links<br />
<source lang="css"><br />
/* Add to e.g. ~/archives/ARCHIVEID/cfg/static/style/auto/zzz_orcid.css */<br />
.person:hover {border-bottom: 1px dashed #a6ce39;}<br />
.orcid {}<br />
.orcid a:hover {<br />
color: #a6ce39;<br />
}<br />
.orcid-icon {}<br />
.orcid-icon img { vertical-align: text-bottom; margin: 0 4px 0 2px; }<br />
</source><br />
<br />
And finally, you have to call the new EPScript function from a citation file e.g. <code>archives/ARCHIVEID/cfg/citations/eprint/default.xml</code><br />
<source lang="xml"><br />
<!-- replace reference to e.g. <print expr="creators_name"/> with this: --><br />
<print expr="wrro_people_with_orcids(creators)" /><br />
</source><br />
<br />
== Exposing the ORCID in RIOXX ==<br />
Based on re-using the creators.id field, this block of code over-writes the default <code>rioxx2_value_author</code> function.<br />
<source lang="perl"><br />
# Add to e.g. ~/archives/ARCHIVEID/cfg/cfg.d/zzz_rioxx2_overwrites.pl<br />
$c->{rioxx2_value_author} = sub {<br />
my( $eprint ) = @_;<br />
<br />
my @authors;<br />
for( @{ $eprint->value( "creators" ) } )<br />
{<br />
my $id = $_->{id}; # if you use a custom 'orcid' field, reference that here instead of 'id'<br />
if( defined $id && $id =~ m/^(?:orcid.org\/)?(\d{4}\-\d{4}\-\d{4}\-\d{3}(?:\d|X))$/ )<br />
{<br />
push @authors, {<br />
author => EPrints::Utils::make_name_string( $_->{name} ),<br />
id => "http://orcid.org/$1"<br />
};<br />
} else {<br />
push @authors, {<br />
author => EPrints::Utils::make_name_string( $_->{name} ),<br />
};<br />
}<br />
}<br />
<br />
#NB If your corp_creators has DOIs or ISNIs for the entries, a similar method could be used to include these here.<br />
foreach my $corp ( @{ $eprint->value( "corp_creators" ) } )<br />
{<br />
my $entry = {};<br />
$entry->{name} = $corp;<br />
push @authors, { author => $corp };<br />
}<br />
<br />
return \@authors;<br />
};<br />
<br />
</source><br />
<br />
= Add additional identifiers to creators =<br />
Another approach to storing ORCIDs is to add an additional sub-field to the creator field.<br />
This has been discussed on the Eprints tech list. If you know how to do this, please document it here!<br />
<br />
This is how University of Bath has done it. We're getting the ORCID data from another system, so have used a text field to capture it for display. At present there is no special rendering on it, it's just displaying as a number.<br />
<source lang="perl"><br />
{<br />
name => 'creators',<br />
type => 'compound',<br />
multiple => 1,<br />
fields => [<br />
{<br />
sub_name => 'name',<br />
type => 'name',<br />
hide_honourific => 1,<br />
hide_lineage => 1,<br />
family_first => 1,<br />
},<br />
{<br />
sub_name => 'id',<br />
type => 'text',<br />
input_cols => 20,<br />
allow_null => 1,<br />
},<br />
{<br />
sub_name => 'orcid',<br />
type => 'text',<br />
input_cols => 20,<br />
allow_null => 1,<br />
}<br />
<br />
],<br />
input_boxes => 4,<br />
},<br />
</source><br />
This is how University of Pittsburgh has done it:<br />
<source lang="perl"><br />
{<br />
'name' => 'creators',<br />
'type' => 'compound',<br />
'multiple' => 1,<br />
'fields' => [<br />
{<br />
'sub_name' => 'name',<br />
'type' => 'name',<br />
'hide_honourific' => 1,<br />
'hide_lineage' => 1,<br />
'family_first' => 1,<br />
},<br />
{<br />
'sub_name' => 'email',<br />
'type' => 'text',<br />
'input_cols' => 20,<br />
'allow_null' => 1,<br />
},<br />
{<br />
'sub_name' => 'id',<br />
'type' => 'text',<br />
'input_cols' => 20,<br />
'allow_null' => 1,<br />
},<br />
{<br />
'sub_name' => 'orcid',<br />
'type' => 'id',<br />
'input_cols' => 19,<br />
'allow_null' => 1,<br />
},<br />
],<br />
'input_boxes' => 4,<br />
'render_value' => 'custom_render_creators_with_orcid',<br />
},<br />
<br />
</source><br />
<br />
==Notes from Pittsburgh:==<br />
(Information courtesy of Brian Gregg - bdgregg@pitt.edu)<br />
<br />
We have added some ORCID functionality in our IR System here at the University of Pittsburgh. We however have not “linked” our IR with orcid.org in anyway such as we do not have a lookup user in ORCID or the ability to add publications from ORCID to our IR. The only link is the entering of the ORCID into the system so that it can be displayed.<br />
<br />
An example record is available here: [http://d-scholarship.pitt.edu/28114/ http://d-scholarship.pitt.edu/28114/]<br />
<br />
# Users have an ORCID field in their profile – user_fields.pl<br />
# Any “Creator” types have an ORCID field added to the workflow – eprint_fields.pl<br />
# We have added ORCID validation adhering to this document: [http://support.orcid.org/knowledgebase/articles/116780-structure-of-the-orcid-identifier] - eprint_validate.pl<br />
# We have added the ORCID to the “lookup” function to populate the ORCID field from any user entries in the database. – cgi/users/lookup/name<br />
# We display the ORCID as such on the input form, where the green icon links out to our own orcid.pitt.edu site, but could be to orcid.org by default.<br />
# We display the ORCID as such on the public display of the record where the ORCID is linked out to orcid.org (see [http://d-scholarship.pitt.edu/28114/ example record])<br />
<br />
ORCID Validator - snippet for eprints_validate.pl<br />
<source lang="perl"><br />
# ORCID ID Validator for individuals<br />
# Reference: http://support.orcid.org/knowledgebase/articles/116780-structure-of-the-orcid-identifier<br />
# REGEX: ^\d{4}-\d{4}-\d{4}-(\d{3}X|\d{4})$<br />
#<br />
my @name_fields = qw( creators contributors exhibitors producers conductors lyricists ); #which ever name fields you added 'orcid' to.<br />
foreach my $name_field ( @name_fields )<br />
{<br />
if( $eprint->is_set( $name_field ) )<br />
{<br />
foreach my $creator ( @{ $eprint->value( $name_field ) } )<br />
{<br />
my $orcid = $creator->{orcid};<br />
next unless defined $orcid;<br />
if ($repository->get_repository->can_call ( "validators", "isValidORCID" ) )<br />
{<br />
if (!$repository->get_repository->call( [ "validators", "isValidORCID" ], $orcid ))<br />
{<br />
my $field_text = $repository->html_phrase( "eprint_fieldname_$name_field" );<br />
my $field_frag = $repository->make_element( "span", class=>"ep_problem_field:$name_field" );<br />
$field_frag->appendChild($field_text);<br />
push @problems, $repository->html_phrase( "warnings:orcid_invalid",<br />
orcid => $repository->get_repository->make_text($orcid),<br />
field => $field_frag,<br />
);<br />
}<br />
} else {<br />
$repository->get_repository->log( "Can not call isValidORCID." );<br />
}<br />
}<br />
}<br />
}<br />
</source><br />
<br />
Phrase for "warnings:orcid_invalid":<br />
<br />
<source lang="xml"><br />
<epp:phrase id="warnings:orcid_invalid">The ORCID ID: <b><epc:pin name="orcid"/></b> is not a valid ORCID ID as it does not conform to the ORCID ID specification. Please edit the <epc:pin name="field"/> with the associated ORCID or remove it from the name completely.</epp:phrase><br />
</source><br />
<br />
<br />
Additional Function that can be placed either at the end of eprints_validate.pl (after the final };) or elsewhere:<br />
<source lang="perl"><br />
############################################<br />
# Function: isValidORCID<br />
# Description: Used to validate ORCID IDs<br />
# <br />
# From: http://support.orcid.org/knowledgebase/articles/116780-structure-of-the-orcid-identifier (Checksum)<br />
#<br />
$c->{validators}->{isValidORCID} = sub {<br />
my $ORCID = $_[0];<br />
#Check for valid length of 19 characters.<br />
my $size = length($ORCID);<br />
if ($size > 19 )<br />
{<br />
return 0;<br />
} else {<br />
#Check actual validity of the ID mathematically.<br />
$ORCID =~ s/\-//g;<br />
my @chars = split(//, $ORCID);<br />
my $total = 0;<br />
for ( my $i=0; $i<15; $i++) {<br />
$total = ($total + $chars[$i]) *2;<br />
}<br />
my $remainder = $total % 11;<br />
my $result = (12 - $remainder) % 11;<br />
return ($chars[15] == ($result==10 ? 'X' : $result))<br />
}<br />
};<br />
</source><br />
<br />
Additionally you will have to define a custom render to add the fields to be displayed in the abstract/summary page.<br />
<br />
= Rendering with Bootstrap =<br />
<br />
[[File:orcid_bootstrap.png|thumb|left|alt=ORCIDs displaying in the Bootstrap theme|ORCID and Bootstrap]]<br />
<br />
In a recent redesign of [http://eprints.whiterose.ac.uk White Rose Research Online] the [https://github.com/eprintsug/bootstrap Bootstrap theme] was used.<br />
The ORCID links are now enhanced with a tooltip and the green icon. There may be examples on the [http://eprints.whiterose.ac.uk/cgi/latest_tool latest 20 additions] page.<br />
<br />
== Bootstrap tooltop ==<br />
This block of code finds anything with a class of 'orcid', and adds the green logo to it, and a tooltip that reads 'ORCID: ''orcid-value''', as shown in the image.<br />
<br />
The example code below is based on the following rendering of a person who may have an ORCID:<br />
<source lang="html4strict"><br />
<!-- NB line-breaks added here for readability are not normally output by EPrints! --><br />
<span class="person"><br />
<span class="person_name">Castillo Ortiz, P.J.</span><br />
<a href="http://orcid.org/0000-0003-4540-1855" target="_blank" class="orcid"><br />
<span>orcid.org/0000-0003-4540-1855</span><br />
</a><br />
</span><br />
</source><br />
<br />
== jQuery ==<br />
<source lang="javascript"><br />
// selector used here depends on your rendering. You may want to use something like a[href*='orcid.org/0000-']<br />
jQuery('.orcid').tooltip({<br />
'placement': 'auto',<br />
'title': function(){ return "ORCID: "+ jQuery(this).text()},<br />
}).append('<img src="/images/orcid_16x16.png" alt="" />').find('span').hide();<br />
</source><br />
<br />
== CSS ==<br />
The green colouring is added using the following css, which also makes the background of the tooltip opaque, not semi-transparent as it is by default.<br />
<source lang="css"><br />
.person + .tooltip > .tooltip-inner,<br />
.orcid + .tooltip > .tooltip-inner {<br />
background-color: #A6CE39;<br />
border: 1px solid #000000;<br />
white-space: pre;<br />
max-width: none;<br />
}<br />
.person + .tooltip.in,<br />
.orcid + .tooltip.in {<br />
opacity: 1;<br />
filter: alpha(opacity=100);<br />
}<br />
/* This adds a green dashed line under an author's name when hovered. This helps in big author lists to tie initials and surname together */<br />
.person:hover {border-bottom: 1px dashed #a6ce39;}<br />
.orcid a:hover {<br />
color: #a6ce39;<br />
}<br />
</source><br />
<br />
= OAI-PMH (Experimental) =<br />
'''[[User:Libjlrs]] 2016-09-29 Warning: this is experimental. I hope others will read, understand, question and improve on this before it becomes some form of best practice!'''<br />
<br />
Some metadata profiles support attributes that are useful to propagate ORCIDs e.g. RIOXX (see the [[#Exposing_the_ORCID_in_RIOXX]] section above, and the 'rioxxterms:author' section on http://www.rioxx.net/profiles/v2-0-final/ ).<br />
<br />
A lot of harvesters use the oai_dc metadata profile when harvesting records. The DC schema doesn't allow attributes on the dc:creator element, so ORCIDs cannot be added in a sensible way to this profile.<br />
<br />
The details below create an additional metadata prefix that adds an attribute to the dc:creator field. The original <code>metadataPrefix=oai_dc</code> output remains unchanged. Using <code>metadataPrefix=oai_dc_orcid</code> will add the orcid attribute where available.<br />
<br />
Currently there is not an XSD that describes this change, so a harvester that validates the feed may stop when it encounters an ORCID.<br />
<br />
This example is based on the <code>EPrints::Plugin::Export::OAI_DC</code> module from EPrints 3.3.10. You may need to tweak it to make it work for you!<br />
<br />
File: <code>~/archives/ARCHIVEID/cfg/plugins/EPrints/Plugin/Export/OAI_DC_ORCID.pm</code><br />
<br />
<source lang="perl"><br />
package EPrints::Plugin::Export::OAI_DC_ORCID;<br />
<br />
use EPrints::Plugin::Export::OAI_DC;<br />
<br />
@ISA = ( "EPrints::Plugin::Export::OAI_DC", "EPrints::Plugin::Export::DC" );<br />
<br />
use strict;<br />
<br />
sub new<br />
{<br />
my( $class, %opts ) = @_;<br />
<br />
my $self = $class->SUPER::new( %opts );<br />
<br />
$self->{name} = "Dublin Core - OAI + ORCID Schema";<br />
$self->{accept} = [ 'dataobj/eprint' ];<br />
$self->{visible} = "";<br />
$self->{suffix} = ".xml";<br />
$self->{mimetype} = "text/xml";<br />
<br />
$self->{metadataPrefix} = "oai_dc_orcid";<br />
$self->{xmlns} = "http://www.openarchives.org/OAI/2.0/oai_dc/";<br />
$self->{schemaLocation} = "http://www.openarchives.org/OAI/2.0/oai_dc.xsd";<br />
<br />
return $self;<br />
}<br />
<br />
sub xml_dataobj<br />
{<br />
my( $plugin, $dataobj ) = @_;<br />
<br />
my $data = $plugin->convert_dataobj( $dataobj );<br />
<br />
my $dc = $plugin->{session}->make_element(<br />
"oai_dc:dc",<br />
"xmlns:oai_dc" => "http://www.openarchives.org/OAI/2.0/oai_dc/",<br />
"xmlns:dc" => "http://purl.org/dc/elements/1.1/",<br />
"xmlns:xsi" => "http://www.w3.org/2001/XMLSchema-instance",<br />
"xsi:schemaLocation" =><br />
"http://www.openarchives.org/OAI/2.0/oai_dc/ http://www.openarchives.org/OAI/2.0/oai_dc.xsd" );<br />
<br />
# turn the list of pairs into XML blocks (indented by 8) and add them<br />
# them to the DC element.<br />
foreach( @{$data} )<br />
{<br />
$dc->appendChild( $plugin->{session}->render_data_element( 8, "dc:".$_->[0], $_->[1], %{$_->[2]} ) );<br />
# produces <key>value</key><br />
}<br />
<br />
return $dc;<br />
}<br />
<br />
sub convert_dataobj<br />
{<br />
my( $plugin, $eprint ) = @_;<br />
<br />
my $dataset = $eprint->{dataset};<br />
<br />
my @dcdata = ();<br />
<br />
push @dcdata, $plugin->simple_value( $eprint, title => "title" );<br />
<br />
if( $eprint->exists_and_set( "creators" ) )<br />
{<br />
my $creators = $eprint->get_value( "creators" );<br />
foreach my $creator ( @$creators )<br />
{<br />
next if !defined $creator;<br />
<br />
# Add ORCID if it exists<br />
if( EPrints::Utils::is_set( $creator->{orcid} ) ){<br />
push @dcdata, [ "creator", EPrints::Utils::make_name_string( $creator->{name} ), { 'orcid' => $creator->{orcid} } ];<br />
} else {<br />
push @dcdata, [ "creator", EPrints::Utils::make_name_string( $creator->{name} ) ];<br />
}<br />
}<br />
}<br />
<br />
if( $eprint->exists_and_set( "subjects" ) )<br />
{<br />
my $subjectid;<br />
foreach $subjectid ( @{$eprint->get_value( "subjects" )} )<br />
{<br />
my $subject = EPrints::DataObj::Subject->new( $plugin->{session}, $subjectid );<br />
# avoid problems with bad subjects<br />
next unless( defined $subject );<br />
push @dcdata, [ "subject", EPrints::Utils::tree_to_utf8( $subject->render_description() ) ];<br />
}<br />
}<br />
<br />
push @dcdata, $plugin->simple_value( $eprint, abstract => "description" );<br />
push @dcdata, $plugin->simple_value( $eprint, publisher => "publisher" );<br />
<br />
if( $eprint->exists_and_set( "editors_name" ) )<br />
{<br />
my $editors = $eprint->get_value( "editors_name" );<br />
if( defined $editors )<br />
{<br />
foreach my $editor ( @{$editors} )<br />
{<br />
push @dcdata, [ "contributor", EPrints::Utils::make_name_string( $editor ) ];<br />
}<br />
}<br />
}<br />
## Date for discovery. For a month/day we don't have, assume 01.<br />
if( $eprint->exists_and_set( "date" ) )<br />
{<br />
my $date = $eprint->get_value( "date" );<br />
if( defined $date )<br />
{<br />
$date =~ s/(-0+)+$//;<br />
push @dcdata, [ "date", $date ];<br />
}<br />
}<br />
<br />
if( $eprint->exists_and_set( "type" ) )<br />
{<br />
push @dcdata, [ "type", EPrints::Utils::tree_to_utf8( $eprint->render_value( "type" ) ) ];<br />
}<br />
<br />
my $ref = "NonPeerReviewed";<br />
if( $eprint->exists_and_set( "refereed" ) && $eprint->get_value( "refereed" ) eq "TRUE" )<br />
{<br />
$ref = "PeerReviewed";<br />
}<br />
push @dcdata, [ "type", $ref ];<br />
<br />
<br />
my @documents = $eprint->get_all_documents();<br />
my $mimetypes = $plugin->{session}->get_repository->get_conf( "oai", "mime_types" );<br />
foreach( @documents )<br />
{<br />
my $format = $mimetypes->{$_->get_value("format")};<br />
$format = $_->get_value("format") unless defined $format;<br />
#$format = "application/octet-stream" unless defined $format;<br />
push @dcdata, [ "format", $format ];<br />
push @dcdata, [ "identifier", $_->get_url() ];<br />
}<br />
<br />
# Most commonly a DOI or journal link<br />
push @dcdata, $plugin->simple_value( $eprint, official_url => "relation" );<br />
<br />
# The citation for this eprint<br />
push @dcdata, [ "identifier",<br />
EPrints::Utils::tree_to_utf8( $eprint->render_citation() ) ];<br />
<br />
# The URL of the abstract page<br />
if( $eprint->is_set( "eprintid" ) )<br />
{<br />
push @dcdata, [ "relation", $eprint->get_url() ];<br />
}<br />
# dc.language not handled yet.<br />
# dc.source not handled yet.<br />
# dc.coverage not handled yet.<br />
# dc.rights not handled yet.<br />
<br />
return \@dcdata;<br />
}<br />
<br />
1;<br />
</source></div>Libjlrshttps://wiki.eprints.org/w/index.php?title=Altering_the_%27Request_a_copy%27_function&diff=12829Altering the 'Request a copy' function2018-08-06T08:47:40Z<p>Libjlrs: /* Method A: Editing the 'requester' citation (For EPrints v3.3.12 and above) */</p>
<hr />
<div>[[Category:Howto]]<br />
<br />
The ''Request a copy'' function allows for some restricted items to be requested by a visitor to the repository.<br />
<br />
If you want someone requesting an item to provide more information that the default email address and reason, you can add additional fields to the request form using the methods outlined below.<br />
<br />
== Adding additional fields to the request dataset ==<br />
<br />
The 'requests' are dataobjects - very similar to an eprint, or a user, so you can add fields in the same way.<br />
<br />
=== Add configuration for new fields ===<br />
<br />
In a config file e.g. <code>[EPRINTS_ROOT]/archives/[ARCHIVE_ID]/cfg/cfg.d/z_request_fields.pl</code><br />
<source lang="perl"><br />
## Additional fields for 'Request a copy'<br />
push @{$c->{fields}->{request}},<br />
{<br />
name => "contact_num",<br />
type => "text",<br />
},<br />
{<br />
name => "id_num",<br />
type => "text",<br />
};<br />
</source><br />
<br />
After adding this file, test the config is OK (avoid syntax errors):<br />
> [EPRINTS_ROOT]/bin/epadmin test [ARCHIVE_ID]<br />
<br />
=== Add phrases for new fields ===<br />
<br />
Add the phrases to e.g. <code>[EPRINTS_ROOT]/archives/[ARCHIVE_ID]/cfg/lang/en/phrases/z_request_fields.xml</code>:<br />
<br />
<source lang="xml"><br />
<?xml version="1.0" encoding="utf-8" standalone="no"?><br />
<!DOCTYPE phrases SYSTEM "entities.dtd"><br />
<epp:phrases xmlns="http://www.w3.org/1999/xhtml" xmlns:epp="http://eprints.org/ep3/phrase" xmlns:epc="http://eprints.org/ep3/control"><br />
<epp:phrase id="request_fieldname_contact_num">Contact number</epp:phrase><br />
<epp:phrase id="request_fieldhelp_contact_num">A number that we can contact you on to discuss your request if necessary </epp:phrase><br />
<br />
<epp:phrase id="request_fieldname_id_num">ID number</epp:phrase><br />
<epp:phrase id="request_fieldhelp_id_num">The identification number from your staff/student card</epp:phrase><br />
</epp:phrases><br />
</source><br />
<br />
Then run:<br />
> [EPRINTS_ROOT]/bin/epadmin update [ARCHIVE_ID]<br />
<br />
This will add the columns to the database.<br />
<br />
=== Adding fields to the workflow ===<br />
<br />
By default the workflow is in the global configuration. It can be customised by copying the default request workflow to the repository config:<br />
> mkdir [EPRINTS_ROOT]/archives/[ARCHIVE_ID]/cfg/workflows/request<br />
> cp [EPRINTS_ROOT]/lib/workflows/request/default.xml [EPRINTS_ROOT]/archives/[ARCHIVE_ID]/cfg/workflows/request<br />
<br />
=== Reload Apache ===<br />
<br />
Test the config again:<br />
> [EPRINTS_ROOT]/bin/epadmin test [ARCHIVE_ID]<br />
<br />
Restart Apache (this command depends on which operating system you use - you may need to do something slightly different!)<br />
> sudo service httpd graceful<br />
<br />
This should have added the fields to the 'Request a copy' workflow.<br />
<br />
== Altering the email sent to the <code>contact_email</code> address ==<br />
<br />
There are two ways this can be achieved - depending on your version of EPrints.<br />
<br />
=== Method A: Editing the 'requester' citation (EPrints v3.3.12 and above?) ===<br />
<br />
If you are using a recent version of EPrints, and the file <code>[EPRINTS_ROOT]/lib/citations/request/requester.xml</code> exists, there is a simple way to include the new fields in the email to the contact_email address. Your version of EPrints uses a citation to include some information from the request dataobject in the request email.<br />
<br />
==== Copy requester citation to local configuration ====<br />
By default the request/requester citation is defined in the global configuration. Don't edit that version (as it will be overwritten when EPrints is upgraded).<br />
Make a copy:<br />
> mkdir [EPRINTS_ROOT]/archives/[ARCHIVE_ID]/cfg/citations/request/<br />
> cp [EPRINTS_ROOT]/lib/citations/reuqest/requester.xml [EPRINTS_ROOT]/archives/[ARCHIVE_ID]/cfg/citations/request/<br />
<br />
==== Edit requester citation ====<br />
Add the new fields to the requester citation:<br />
<br />
<source lang="xml"><br />
<?xml version="1.0" ?><br />
<cite:citation xmlns="http://www.w3.org/1999/xhtml" xmlns:cite="http://eprints.org/ep3/citation" xmlns:epc="http://eprints.org/ep3/control"><br />
<epc:print expr="requester_email"/><br />
<epc:if test="contact_num"><br /><epc:phrase ref="request_fieldname_contact_num" />: <epc:print expr="contact_num"/></epc:if><br />
<epc:if test="id_num"><br /><epc:phrase ref="request_fieldname_id_num" />: <epc:print expr="id_num"/></epc:if><br />
</cite:citation><br />
</source><br />
<br />
==== Test the config, restart Apache ====<br />
Run the <code>epadmin test</code> to check everything is OK, and then restart Apache.<br />
<br />
EPrints will pick up changes within an existing XML file when you edit it, but it will not detect a new XML file (such as the local requester.xml citation) by default - so a restart (or a reload) is needed.<br />
<br />
=== Method B: Overriding EPrints::Plugin::Screen::Public::RequestCopy ===<br />
<br />
If your version of EPrints doesn't have the above file, or you need to do something more complex than just adding the fields, follow these instructions!<br />
<br />
The screen that processes the request being made (not the response to the request) is <code>EPrints::Plugin::Screen::Public::RequestCopy</code>.<br />
To include the additional data in the email sent to the contact_email address, we need to change the way this behaves - specifying the additional details to be added.<br />
<br />
The correct 'EPrints' way to do this for a plugin is outlined here: https://wiki.eprints.org/w/Instructions_for_local_plugins<br />
<br />
==== Understand how the current script works ====<br />
Take a look at <code>EPrints::Plugin::Screen::Public::RequestCopy</code> and try to understand it (a bit at least).<br />
<br />
Work out which of the methods you need to work differently.<br />
<br />
==== Make a local copy of the plugin ====<br />
<br />
mkdir -p [EPRINTS_ROOT]/archives/[ARCHIVE_ID]/cfg/plugins/EPrints/Plugins/Screen/Public/RequestCopy/<br />
cp [EPRINTS_ROOT]/perl_lib/EPrints/Plugins/Screen/Public/RequestCopy.pm [EPRINTS_ROOT]/archives/[ARCHIVE_ID]/cfg/plugins/EPrints/Plugins/Screen/Public/RequestCopy/LocalRequestCopy.pm<br />
<br />
==== Edit the local copy of the plugin ====<br />
The package name and 'isa' need to be updated as this is a subclass of the existing plugin.<br />
<br />
Any methods that you don't need to change can also be removed (as they'll be inherited from the main RequestCopy module).<br />
<br />
'''PLEASE NOTE the example code below may have been taken from a different version of EPrints to the one you are running. DO NOT just copy and paste it. Please follow the process above to take a copy of RequestCopy from your server, and edit it!'''<br />
<br />
The changes are indicated with <code>### INSERTED CODE ###</code> comments.<br />
<br />
<source lang="perl"><br />
#################################<br />
# Example taken from https://github.com/eprints/eprints/blob/v3.3.16/perl_lib/EPrints/Plugin/Screen/Public/RequestCopy.pm<br />
#################################<br />
<br />
package EPrints::Plugin::Screen::Public::RequestCopy::LocalRequestCopy;<br />
<br />
@ISA = ( 'EPrints::Plugin::Screen::Public::RequestCopy' );<br />
<br />
use strict;<br />
<br />
sub action_request<br />
{<br />
my( $self ) = @_;<br />
<br />
my $session = $self->{session};<br />
<br />
my $request = $self->{processor}->{dataobj};<br />
<br />
my $rc = $self->workflow->update_from_form( $self->{processor} );<br />
return if !$rc; # validation failed<br />
<br />
my $email = $request->value( "requester_email" );<br />
<br />
my $use_pin_security = $session->config( 'use_request_copy_pin_security' );<br />
<br />
my $eprint = $self->{processor}->{eprint};<br />
my $doc = $self->{processor}->{document};<br />
my $contact_email = $self->{processor}->{contact_email};<br />
<br />
my $user = EPrints::DataObj::User::user_with_email( $session, $contact_email );<br />
if( defined $user )<br />
{<br />
$request->set_value( "userid", $user->id );<br />
}<br />
<br />
$request = $self->{processor}->{dataset}->create_dataobj( $request->get_data );<br />
<br />
my $history_data = {<br />
datasetid=>"request",<br />
objectid=>$request->get_id,<br />
action=>"create",<br />
};<br />
<br />
if( defined $self->{processor}->{user} )<br />
{<br />
$history_data->{userid} = $self->{processor}->{user}->get_id;<br />
}<br />
else<br />
{<br />
$history_data->{actor} = $email;<br />
}<br />
<br />
# Log request creation event<br />
my $history_ds = $session->dataset( "history" );<br />
$history_ds->create_object( $session, $history_data );<br />
<br />
# Send request email<br />
my $subject = $session->phrase( "request/request_email:subject", eprint => $eprint->get_value( "title" ) );<br />
my $mail = $session->make_element( "mail" );<br />
$mail->appendChild( $session->html_phrase(<br />
"request/request_email:body", <br />
eprint => $eprint->render_citation_link_staff,<br />
document => defined $doc ? $doc->render_value( "main" ) : $session->make_doc_fragment,<br />
requester => $request->render_citation( "requester" ),<br />
### INSERTED CODE ###<br />
# this checks whether the value is set, and returns either the rendered value, or an empty document fragment<br />
# the pins for a phrase must be XML fragments - not scalar values.<br />
# The corresponding phrase (request/request_email:body) must also be updated to expect the new data.<br />
contact_num => $request->is_set( "contact_num" ) ? $request->render_value( "contact_num" ) : $session->make_doc_fragment,<br />
id_num => $request->is_set( "id_num" ) ? $request->render_value( "id_num" ) : $session->make_doc_fragment,<br />
### END INSERTED CODE ###<br />
reason => $request->is_set( "reason" ) ? $request->render_value( "reason" )<br />
: $session->html_phrase( "Plugin/Screen/EPrint/RequestRemoval:reason" ) ) );<br />
<br />
my $result;<br />
if( ( defined $user || $use_pin_security ) && defined $doc )<br />
{<br />
# Contact is a registered user or it doesn't matter<br />
# because we're using the pin security model, and<br />
# EPrints holds the requested document<br />
<br />
# Send email to contact with accept/reject links<br />
<br />
my $url;<br />
if ( $use_pin_security )<br />
{<br />
# Handle the response via a non-authenticated CGI script<br />
$url = $session->get_url( host => 1, path => "cgi", "respond_to_doc_request" );<br />
$url->query_form(<br />
pin => $request->get_value( 'pin' ),<br />
);<br />
}<br />
else<br />
{<br />
# Handle the response via cgi/users/home which is authenticated<br />
$url = $session->get_url( host => 1, path => "cgi", "users/home" );<br />
$url->query_form(<br />
screen => "Request::Respond",<br />
requestid => $request->id,<br />
);<br />
}<br />
<br />
$mail->appendChild( $session->html_phrase( "request/request_email:links",<br />
accept => $session->render_link( "$url&action=accept" ),<br />
reject => $session->render_link( "$url&action=reject" ) ) );<br />
<br />
my $to_name;<br />
if ( defined $user )<br />
{<br />
$to_name = EPrints::Utils::tree_to_utf8( $user->render_description );<br />
}<br />
else<br />
{<br />
$to_name = $contact_email;<br />
}<br />
<br />
$result = EPrints::Email::send_mail(<br />
session => $session,<br />
langid => $session->get_langid,<br />
to_name => $to_name,<br />
to_email => $contact_email,<br />
subject => $subject,<br />
message => $mail,<br />
sig => $session->html_phrase( "mail_sig" ),<br />
cc_list => EPrints::Utils::is_set( $session->config( "request_copy_cc" ) ) ? $session->config( "request_copy_cc" ) : [],<br />
);<br />
} <br />
else<br />
{<br />
# Contact is non-registered user or EPrints holds no documents<br />
# Send email to contact with 'replyto'<br />
$result = EPrints::Email::send_mail(<br />
session => $session,<br />
langid => $session->get_langid,<br />
to_name => defined $user ? EPrints::Utils::tree_to_utf8( $user->render_description ) : "",<br />
to_email => $contact_email,<br />
subject => $subject,<br />
message => $mail,<br />
sig => $session->html_phrase( "mail_sig" ),<br />
replyto_email => $email,<br />
cc_list => EPrints::Utils::is_set( $session->config( "request_copy_cc" ) ) ? $session->config( "request_copy_cc" ) : [],<br />
);<br />
}<br />
<br />
if( !$result )<br />
{<br />
$self->{processor}->add_message( "error", $session->html_phrase( "general:email_failed" ) );<br />
return;<br />
}<br />
<br />
# Send acknowledgement to requester<br />
$mail = $session->make_element( "mail" );<br />
$mail->appendChild( $session->html_phrase(<br />
"request/ack_email:body", <br />
document => defined $doc ? $doc->render_value( "main" ) : $session->make_doc_fragment,<br />
eprint => $eprint->render_citation_link ) );<br />
<br />
$result = EPrints::Email::send_mail(<br />
session => $session,<br />
langid => $session->get_langid,<br />
to_email => $email,<br />
subject => $session->phrase( "request/ack_email:subject", eprint=>$eprint->get_value( "title" ) ), <br />
message => $mail,<br />
sig => $session->html_phrase( "mail_sig" )<br />
);<br />
<br />
if( !$result )<br />
{<br />
$self->{processor}->add_message( "error", $session->html_phrase( "general:email_failed" ) );<br />
return;<br />
}<br />
<br />
$self->{processor}->add_message( "message", $session->html_phrase( "request/ack_page", link => $session->render_link( $eprint->get_url ) ) );<br />
$self->{processor}->{request_sent} = 1;<br />
}<br />
<br />
1;<br />
</source><br />
<br />
==== Add phrase ====<br />
The changes to the perl module add two new pins to the phrase. We have to update a local copy of the phrase and add places for these pins to be inserted.<br />
In the file <code>[EPRINTS_ROOT]/lib/lang/en/phrases/system.xml</code> locate the phrase <code>request/request_email:body</code> (see: https://github.com/eprints/eprints/blob/v3.3.16/lib/lang/en/phrases/system.xml#L3422-L3431)<br />
<br />
Copy this phrase into an XML phrase file e.g. <code>[EPRINTS_ROOT]/archives/[ARCHIVE_ID]/cfg/lang/en/phrases/z_request_fields.xml</code> - used above.<br />
Edit the phrase, defining places for the new pins to appear:<br />
<br />
<source lang="xml"><br />
<epp:phrase id="request/request_email:body"><br />
<p>This item has been requested from <epc:phrase ref="archive_name" /> by <epc:pin name="requester"/>.</p><br />
<p>Contact number: <epc:pin name="contact_num"/><br /><br />
ID number: <epc:pin name="id_num"/></p><br />
<p>Please can you respond.</p><br />
<br />
<p><epc:pin name="eprint"/><br/><epc:pin name="document"/></p><br />
<p>The following reason was given:</p><br />
<epc:pin name="reason"/><br />
<br />
<p>Please consider removing restrictions or uploading the full text to the archive so that it will be available immediately to future searchers.</p><br />
</epp:phrase><br />
</source><br />
<br />
==== Enable plugin (map) ====<br />
<br />
Finally, we have to tell EPrints to use our new plugin in place of the existing one.<br />
<br />
Read the details in <code>[EPRINTS_ROOT]/archives/[ARCHIVE_ID]/cfg/cfg.d/plugins.pl</code>.<br />
<br />
Once you understand what need to be done, add the plugin enabling code in a suitable configuration file e.g. <code>[EPRINTS_ROOT]/archives/[ARCHIVE_ID]/cfg/cfg.d/z_request_fields.pl</code>.<br />
<br />
<source lang="perl"><br />
$c->{plugin_alias_map}->{"Screen::Public::RequestCopy"} = "Screen::Public::RequestCopy::LocalRequestCopy";<br />
$c->{plugin_alias_map}->{"Screen::Public::RequestCopy::LocalRequestCopy"} = undef;<br />
<br />
# If this doesn't seem to work, try uncommenting this:<br />
# $c->{plugins}->{"Screen::Public::RequestCopy::LocalRequestCopy"}->{params}->{disable} = 0;<br />
</source><br />
<br />
==== Test everything and restart apache ====<br />
Using the same procedure as after adding the fields.<br />
<br />
If the <code>epadmin test</code> returns no errors, restart Apache, and try requesting something!</div>Libjlrshttps://wiki.eprints.org/w/index.php?title=Altering_the_%27Request_a_copy%27_function&diff=12828Altering the 'Request a copy' function2018-08-06T08:47:20Z<p>Libjlrs: /* Method A: Editing the 'requester' citation */</p>
<hr />
<div>[[Category:Howto]]<br />
<br />
The ''Request a copy'' function allows for some restricted items to be requested by a visitor to the repository.<br />
<br />
If you want someone requesting an item to provide more information that the default email address and reason, you can add additional fields to the request form using the methods outlined below.<br />
<br />
== Adding additional fields to the request dataset ==<br />
<br />
The 'requests' are dataobjects - very similar to an eprint, or a user, so you can add fields in the same way.<br />
<br />
=== Add configuration for new fields ===<br />
<br />
In a config file e.g. <code>[EPRINTS_ROOT]/archives/[ARCHIVE_ID]/cfg/cfg.d/z_request_fields.pl</code><br />
<source lang="perl"><br />
## Additional fields for 'Request a copy'<br />
push @{$c->{fields}->{request}},<br />
{<br />
name => "contact_num",<br />
type => "text",<br />
},<br />
{<br />
name => "id_num",<br />
type => "text",<br />
};<br />
</source><br />
<br />
After adding this file, test the config is OK (avoid syntax errors):<br />
> [EPRINTS_ROOT]/bin/epadmin test [ARCHIVE_ID]<br />
<br />
=== Add phrases for new fields ===<br />
<br />
Add the phrases to e.g. <code>[EPRINTS_ROOT]/archives/[ARCHIVE_ID]/cfg/lang/en/phrases/z_request_fields.xml</code>:<br />
<br />
<source lang="xml"><br />
<?xml version="1.0" encoding="utf-8" standalone="no"?><br />
<!DOCTYPE phrases SYSTEM "entities.dtd"><br />
<epp:phrases xmlns="http://www.w3.org/1999/xhtml" xmlns:epp="http://eprints.org/ep3/phrase" xmlns:epc="http://eprints.org/ep3/control"><br />
<epp:phrase id="request_fieldname_contact_num">Contact number</epp:phrase><br />
<epp:phrase id="request_fieldhelp_contact_num">A number that we can contact you on to discuss your request if necessary </epp:phrase><br />
<br />
<epp:phrase id="request_fieldname_id_num">ID number</epp:phrase><br />
<epp:phrase id="request_fieldhelp_id_num">The identification number from your staff/student card</epp:phrase><br />
</epp:phrases><br />
</source><br />
<br />
Then run:<br />
> [EPRINTS_ROOT]/bin/epadmin update [ARCHIVE_ID]<br />
<br />
This will add the columns to the database.<br />
<br />
=== Adding fields to the workflow ===<br />
<br />
By default the workflow is in the global configuration. It can be customised by copying the default request workflow to the repository config:<br />
> mkdir [EPRINTS_ROOT]/archives/[ARCHIVE_ID]/cfg/workflows/request<br />
> cp [EPRINTS_ROOT]/lib/workflows/request/default.xml [EPRINTS_ROOT]/archives/[ARCHIVE_ID]/cfg/workflows/request<br />
<br />
=== Reload Apache ===<br />
<br />
Test the config again:<br />
> [EPRINTS_ROOT]/bin/epadmin test [ARCHIVE_ID]<br />
<br />
Restart Apache (this command depends on which operating system you use - you may need to do something slightly different!)<br />
> sudo service httpd graceful<br />
<br />
This should have added the fields to the 'Request a copy' workflow.<br />
<br />
== Altering the email sent to the <code>contact_email</code> address ==<br />
<br />
There are two ways this can be achieved - depending on your version of EPrints.<br />
<br />
=== Method A: Editing the 'requester' citation (For EPrints v3.3.12 and above) ===<br />
<br />
If you are using a recent version of EPrints, and the file <code>[EPRINTS_ROOT]/lib/citations/request/requester.xml</code> exists, there is a simple way to include the new fields in the email to the contact_email address. Your version of EPrints uses a citation to include some information from the request dataobject in the request email.<br />
<br />
==== Copy requester citation to local configuration ====<br />
By default the request/requester citation is defined in the global configuration. Don't edit that version (as it will be overwritten when EPrints is upgraded).<br />
Make a copy:<br />
> mkdir [EPRINTS_ROOT]/archives/[ARCHIVE_ID]/cfg/citations/request/<br />
> cp [EPRINTS_ROOT]/lib/citations/reuqest/requester.xml [EPRINTS_ROOT]/archives/[ARCHIVE_ID]/cfg/citations/request/<br />
<br />
==== Edit requester citation ====<br />
Add the new fields to the requester citation:<br />
<br />
<source lang="xml"><br />
<?xml version="1.0" ?><br />
<cite:citation xmlns="http://www.w3.org/1999/xhtml" xmlns:cite="http://eprints.org/ep3/citation" xmlns:epc="http://eprints.org/ep3/control"><br />
<epc:print expr="requester_email"/><br />
<epc:if test="contact_num"><br /><epc:phrase ref="request_fieldname_contact_num" />: <epc:print expr="contact_num"/></epc:if><br />
<epc:if test="id_num"><br /><epc:phrase ref="request_fieldname_id_num" />: <epc:print expr="id_num"/></epc:if><br />
</cite:citation><br />
</source><br />
<br />
==== Test the config, restart Apache ====<br />
Run the <code>epadmin test</code> to check everything is OK, and then restart Apache.<br />
<br />
EPrints will pick up changes within an existing XML file when you edit it, but it will not detect a new XML file (such as the local requester.xml citation) by default - so a restart (or a reload) is needed.<br />
<br />
=== Method B: Overriding EPrints::Plugin::Screen::Public::RequestCopy ===<br />
<br />
If your version of EPrints doesn't have the above file, or you need to do something more complex than just adding the fields, follow these instructions!<br />
<br />
The screen that processes the request being made (not the response to the request) is <code>EPrints::Plugin::Screen::Public::RequestCopy</code>.<br />
To include the additional data in the email sent to the contact_email address, we need to change the way this behaves - specifying the additional details to be added.<br />
<br />
The correct 'EPrints' way to do this for a plugin is outlined here: https://wiki.eprints.org/w/Instructions_for_local_plugins<br />
<br />
==== Understand how the current script works ====<br />
Take a look at <code>EPrints::Plugin::Screen::Public::RequestCopy</code> and try to understand it (a bit at least).<br />
<br />
Work out which of the methods you need to work differently.<br />
<br />
==== Make a local copy of the plugin ====<br />
<br />
mkdir -p [EPRINTS_ROOT]/archives/[ARCHIVE_ID]/cfg/plugins/EPrints/Plugins/Screen/Public/RequestCopy/<br />
cp [EPRINTS_ROOT]/perl_lib/EPrints/Plugins/Screen/Public/RequestCopy.pm [EPRINTS_ROOT]/archives/[ARCHIVE_ID]/cfg/plugins/EPrints/Plugins/Screen/Public/RequestCopy/LocalRequestCopy.pm<br />
<br />
==== Edit the local copy of the plugin ====<br />
The package name and 'isa' need to be updated as this is a subclass of the existing plugin.<br />
<br />
Any methods that you don't need to change can also be removed (as they'll be inherited from the main RequestCopy module).<br />
<br />
'''PLEASE NOTE the example code below may have been taken from a different version of EPrints to the one you are running. DO NOT just copy and paste it. Please follow the process above to take a copy of RequestCopy from your server, and edit it!'''<br />
<br />
The changes are indicated with <code>### INSERTED CODE ###</code> comments.<br />
<br />
<source lang="perl"><br />
#################################<br />
# Example taken from https://github.com/eprints/eprints/blob/v3.3.16/perl_lib/EPrints/Plugin/Screen/Public/RequestCopy.pm<br />
#################################<br />
<br />
package EPrints::Plugin::Screen::Public::RequestCopy::LocalRequestCopy;<br />
<br />
@ISA = ( 'EPrints::Plugin::Screen::Public::RequestCopy' );<br />
<br />
use strict;<br />
<br />
sub action_request<br />
{<br />
my( $self ) = @_;<br />
<br />
my $session = $self->{session};<br />
<br />
my $request = $self->{processor}->{dataobj};<br />
<br />
my $rc = $self->workflow->update_from_form( $self->{processor} );<br />
return if !$rc; # validation failed<br />
<br />
my $email = $request->value( "requester_email" );<br />
<br />
my $use_pin_security = $session->config( 'use_request_copy_pin_security' );<br />
<br />
my $eprint = $self->{processor}->{eprint};<br />
my $doc = $self->{processor}->{document};<br />
my $contact_email = $self->{processor}->{contact_email};<br />
<br />
my $user = EPrints::DataObj::User::user_with_email( $session, $contact_email );<br />
if( defined $user )<br />
{<br />
$request->set_value( "userid", $user->id );<br />
}<br />
<br />
$request = $self->{processor}->{dataset}->create_dataobj( $request->get_data );<br />
<br />
my $history_data = {<br />
datasetid=>"request",<br />
objectid=>$request->get_id,<br />
action=>"create",<br />
};<br />
<br />
if( defined $self->{processor}->{user} )<br />
{<br />
$history_data->{userid} = $self->{processor}->{user}->get_id;<br />
}<br />
else<br />
{<br />
$history_data->{actor} = $email;<br />
}<br />
<br />
# Log request creation event<br />
my $history_ds = $session->dataset( "history" );<br />
$history_ds->create_object( $session, $history_data );<br />
<br />
# Send request email<br />
my $subject = $session->phrase( "request/request_email:subject", eprint => $eprint->get_value( "title" ) );<br />
my $mail = $session->make_element( "mail" );<br />
$mail->appendChild( $session->html_phrase(<br />
"request/request_email:body", <br />
eprint => $eprint->render_citation_link_staff,<br />
document => defined $doc ? $doc->render_value( "main" ) : $session->make_doc_fragment,<br />
requester => $request->render_citation( "requester" ),<br />
### INSERTED CODE ###<br />
# this checks whether the value is set, and returns either the rendered value, or an empty document fragment<br />
# the pins for a phrase must be XML fragments - not scalar values.<br />
# The corresponding phrase (request/request_email:body) must also be updated to expect the new data.<br />
contact_num => $request->is_set( "contact_num" ) ? $request->render_value( "contact_num" ) : $session->make_doc_fragment,<br />
id_num => $request->is_set( "id_num" ) ? $request->render_value( "id_num" ) : $session->make_doc_fragment,<br />
### END INSERTED CODE ###<br />
reason => $request->is_set( "reason" ) ? $request->render_value( "reason" )<br />
: $session->html_phrase( "Plugin/Screen/EPrint/RequestRemoval:reason" ) ) );<br />
<br />
my $result;<br />
if( ( defined $user || $use_pin_security ) && defined $doc )<br />
{<br />
# Contact is a registered user or it doesn't matter<br />
# because we're using the pin security model, and<br />
# EPrints holds the requested document<br />
<br />
# Send email to contact with accept/reject links<br />
<br />
my $url;<br />
if ( $use_pin_security )<br />
{<br />
# Handle the response via a non-authenticated CGI script<br />
$url = $session->get_url( host => 1, path => "cgi", "respond_to_doc_request" );<br />
$url->query_form(<br />
pin => $request->get_value( 'pin' ),<br />
);<br />
}<br />
else<br />
{<br />
# Handle the response via cgi/users/home which is authenticated<br />
$url = $session->get_url( host => 1, path => "cgi", "users/home" );<br />
$url->query_form(<br />
screen => "Request::Respond",<br />
requestid => $request->id,<br />
);<br />
}<br />
<br />
$mail->appendChild( $session->html_phrase( "request/request_email:links",<br />
accept => $session->render_link( "$url&action=accept" ),<br />
reject => $session->render_link( "$url&action=reject" ) ) );<br />
<br />
my $to_name;<br />
if ( defined $user )<br />
{<br />
$to_name = EPrints::Utils::tree_to_utf8( $user->render_description );<br />
}<br />
else<br />
{<br />
$to_name = $contact_email;<br />
}<br />
<br />
$result = EPrints::Email::send_mail(<br />
session => $session,<br />
langid => $session->get_langid,<br />
to_name => $to_name,<br />
to_email => $contact_email,<br />
subject => $subject,<br />
message => $mail,<br />
sig => $session->html_phrase( "mail_sig" ),<br />
cc_list => EPrints::Utils::is_set( $session->config( "request_copy_cc" ) ) ? $session->config( "request_copy_cc" ) : [],<br />
);<br />
} <br />
else<br />
{<br />
# Contact is non-registered user or EPrints holds no documents<br />
# Send email to contact with 'replyto'<br />
$result = EPrints::Email::send_mail(<br />
session => $session,<br />
langid => $session->get_langid,<br />
to_name => defined $user ? EPrints::Utils::tree_to_utf8( $user->render_description ) : "",<br />
to_email => $contact_email,<br />
subject => $subject,<br />
message => $mail,<br />
sig => $session->html_phrase( "mail_sig" ),<br />
replyto_email => $email,<br />
cc_list => EPrints::Utils::is_set( $session->config( "request_copy_cc" ) ) ? $session->config( "request_copy_cc" ) : [],<br />
);<br />
}<br />
<br />
if( !$result )<br />
{<br />
$self->{processor}->add_message( "error", $session->html_phrase( "general:email_failed" ) );<br />
return;<br />
}<br />
<br />
# Send acknowledgement to requester<br />
$mail = $session->make_element( "mail" );<br />
$mail->appendChild( $session->html_phrase(<br />
"request/ack_email:body", <br />
document => defined $doc ? $doc->render_value( "main" ) : $session->make_doc_fragment,<br />
eprint => $eprint->render_citation_link ) );<br />
<br />
$result = EPrints::Email::send_mail(<br />
session => $session,<br />
langid => $session->get_langid,<br />
to_email => $email,<br />
subject => $session->phrase( "request/ack_email:subject", eprint=>$eprint->get_value( "title" ) ), <br />
message => $mail,<br />
sig => $session->html_phrase( "mail_sig" )<br />
);<br />
<br />
if( !$result )<br />
{<br />
$self->{processor}->add_message( "error", $session->html_phrase( "general:email_failed" ) );<br />
return;<br />
}<br />
<br />
$self->{processor}->add_message( "message", $session->html_phrase( "request/ack_page", link => $session->render_link( $eprint->get_url ) ) );<br />
$self->{processor}->{request_sent} = 1;<br />
}<br />
<br />
1;<br />
</source><br />
<br />
==== Add phrase ====<br />
The changes to the perl module add two new pins to the phrase. We have to update a local copy of the phrase and add places for these pins to be inserted.<br />
In the file <code>[EPRINTS_ROOT]/lib/lang/en/phrases/system.xml</code> locate the phrase <code>request/request_email:body</code> (see: https://github.com/eprints/eprints/blob/v3.3.16/lib/lang/en/phrases/system.xml#L3422-L3431)<br />
<br />
Copy this phrase into an XML phrase file e.g. <code>[EPRINTS_ROOT]/archives/[ARCHIVE_ID]/cfg/lang/en/phrases/z_request_fields.xml</code> - used above.<br />
Edit the phrase, defining places for the new pins to appear:<br />
<br />
<source lang="xml"><br />
<epp:phrase id="request/request_email:body"><br />
<p>This item has been requested from <epc:phrase ref="archive_name" /> by <epc:pin name="requester"/>.</p><br />
<p>Contact number: <epc:pin name="contact_num"/><br /><br />
ID number: <epc:pin name="id_num"/></p><br />
<p>Please can you respond.</p><br />
<br />
<p><epc:pin name="eprint"/><br/><epc:pin name="document"/></p><br />
<p>The following reason was given:</p><br />
<epc:pin name="reason"/><br />
<br />
<p>Please consider removing restrictions or uploading the full text to the archive so that it will be available immediately to future searchers.</p><br />
</epp:phrase><br />
</source><br />
<br />
==== Enable plugin (map) ====<br />
<br />
Finally, we have to tell EPrints to use our new plugin in place of the existing one.<br />
<br />
Read the details in <code>[EPRINTS_ROOT]/archives/[ARCHIVE_ID]/cfg/cfg.d/plugins.pl</code>.<br />
<br />
Once you understand what need to be done, add the plugin enabling code in a suitable configuration file e.g. <code>[EPRINTS_ROOT]/archives/[ARCHIVE_ID]/cfg/cfg.d/z_request_fields.pl</code>.<br />
<br />
<source lang="perl"><br />
$c->{plugin_alias_map}->{"Screen::Public::RequestCopy"} = "Screen::Public::RequestCopy::LocalRequestCopy";<br />
$c->{plugin_alias_map}->{"Screen::Public::RequestCopy::LocalRequestCopy"} = undef;<br />
<br />
# If this doesn't seem to work, try uncommenting this:<br />
# $c->{plugins}->{"Screen::Public::RequestCopy::LocalRequestCopy"}->{params}->{disable} = 0;<br />
</source><br />
<br />
==== Test everything and restart apache ====<br />
Using the same procedure as after adding the fields.<br />
<br />
If the <code>epadmin test</code> returns no errors, restart Apache, and try requesting something!</div>Libjlrshttps://wiki.eprints.org/w/index.php?title=Altering_the_%27Request_a_copy%27_function&diff=12824Altering the 'Request a copy' function2018-08-03T10:47:43Z<p>Libjlrs: /* Method A: Editing the 'requester' citation */</p>
<hr />
<div>[[Category:Howto]]<br />
<br />
The ''Request a copy'' function allows for some restricted items to be requested by a visitor to the repository.<br />
<br />
If you want someone requesting an item to provide more information that the default email address and reason, you can add additional fields to the request form using the methods outlined below.<br />
<br />
== Adding additional fields to the request dataset ==<br />
<br />
The 'requests' are dataobjects - very similar to an eprint, or a user, so you can add fields in the same way.<br />
<br />
=== Add configuration for new fields ===<br />
<br />
In a config file e.g. <code>[EPRINTS_ROOT]/archives/[ARCHIVE_ID]/cfg/cfg.d/z_request_fields.pl</code><br />
<source lang="perl"><br />
## Additional fields for 'Request a copy'<br />
push @{$c->{fields}->{request}},<br />
{<br />
name => "contact_num",<br />
type => "text",<br />
},<br />
{<br />
name => "id_num",<br />
type => "text",<br />
};<br />
</source><br />
<br />
After adding this file, test the config is OK (avoid syntax errors):<br />
> [EPRINTS_ROOT]/bin/epadmin test [ARCHIVE_ID]<br />
<br />
=== Add phrases for new fields ===<br />
<br />
Add the phrases to e.g. <code>[EPRINTS_ROOT]/archives/[ARCHIVE_ID]/cfg/lang/en/phrases/z_request_fields.xml</code>:<br />
<br />
<source lang="xml"><br />
<?xml version="1.0" encoding="utf-8" standalone="no"?><br />
<!DOCTYPE phrases SYSTEM "entities.dtd"><br />
<epp:phrases xmlns="http://www.w3.org/1999/xhtml" xmlns:epp="http://eprints.org/ep3/phrase" xmlns:epc="http://eprints.org/ep3/control"><br />
<epp:phrase id="request_fieldname_contact_num">Contact number</epp:phrase><br />
<epp:phrase id="request_fieldhelp_contact_num">A number that we can contact you on to discuss your request if necessary </epp:phrase><br />
<br />
<epp:phrase id="request_fieldname_id_num">ID number</epp:phrase><br />
<epp:phrase id="request_fieldhelp_id_num">The identification number from your staff/student card</epp:phrase><br />
</epp:phrases><br />
</source><br />
<br />
Then run:<br />
> [EPRINTS_ROOT]/bin/epadmin update [ARCHIVE_ID]<br />
<br />
This will add the columns to the database.<br />
<br />
=== Adding fields to the workflow ===<br />
<br />
By default the workflow is in the global configuration. It can be customised by copying the default request workflow to the repository config:<br />
> mkdir [EPRINTS_ROOT]/archives/[ARCHIVE_ID]/cfg/workflows/request<br />
> cp [EPRINTS_ROOT]/lib/workflows/request/default.xml [EPRINTS_ROOT]/archives/[ARCHIVE_ID]/cfg/workflows/request<br />
<br />
=== Reload Apache ===<br />
<br />
Test the config again:<br />
> [EPRINTS_ROOT]/bin/epadmin test [ARCHIVE_ID]<br />
<br />
Restart Apache (this command depends on which operating system you use - you may need to do something slightly different!)<br />
> sudo service httpd graceful<br />
<br />
This should have added the fields to the 'Request a copy' workflow.<br />
<br />
== Altering the email sent to the <code>contact_email</code> address ==<br />
<br />
There are two ways this can be achieved - depending on your version of EPrints.<br />
<br />
=== Method A: Editing the 'requester' citation ===<br />
<br />
If you are using a recent version of EPrints, and the file <code>[EPRINTS_ROOT]/lib/citations/request/requester.xml</code> exists, there is a simple way to include the new fields in the email to the contact_email address. Your version of EPrints uses a citation to include some information from the request dataobject in the request email.<br />
<br />
==== Copy requester citation to local configuration ====<br />
By default the request/requester citation is defined in the global configuration. Don't edit that version (as it will be overwritten when EPrints is upgraded).<br />
Make a copy:<br />
> mkdir [EPRINTS_ROOT]/archives/[ARCHIVE_ID]/cfg/citations/request/<br />
> cp [EPRINTS_ROOT]/lib/citations/reuqest/requester.xml [EPRINTS_ROOT]/archives/[ARCHIVE_ID]/cfg/citations/request/<br />
<br />
==== Edit requester citation ====<br />
Add the new fields to the requester citation:<br />
<br />
<source lang="xml"><br />
<?xml version="1.0" ?><br />
<cite:citation xmlns="http://www.w3.org/1999/xhtml" xmlns:cite="http://eprints.org/ep3/citation" xmlns:epc="http://eprints.org/ep3/control"><br />
<epc:print expr="requester_email"/><br />
<epc:if test="contact_num"><br /><epc:phrase ref="request_fieldname_contact_num" />: <epc:print expr="contact_num"/></epc:if><br />
<epc:if test="id_num"><br /><epc:phrase ref="request_fieldname_id_num" />: <epc:print expr="id_num"/></epc:if><br />
</cite:citation><br />
</source><br />
<br />
==== Test the config, restart Apache ====<br />
Run the <code>epadmin test</code> to check everything is OK, and then restart Apache.<br />
<br />
EPrints will pick up changes within an existing XML file when you edit it, but it will not detect a new XML file (such as the local requester.xml citation) by default - so a restart (or a reload) is needed.<br />
<br />
=== Method B: Overriding EPrints::Plugin::Screen::Public::RequestCopy ===<br />
<br />
If your version of EPrints doesn't have the above file, or you need to do something more complex than just adding the fields, follow these instructions!<br />
<br />
The screen that processes the request being made (not the response to the request) is <code>EPrints::Plugin::Screen::Public::RequestCopy</code>.<br />
To include the additional data in the email sent to the contact_email address, we need to change the way this behaves - specifying the additional details to be added.<br />
<br />
The correct 'EPrints' way to do this for a plugin is outlined here: https://wiki.eprints.org/w/Instructions_for_local_plugins<br />
<br />
==== Understand how the current script works ====<br />
Take a look at <code>EPrints::Plugin::Screen::Public::RequestCopy</code> and try to understand it (a bit at least).<br />
<br />
Work out which of the methods you need to work differently.<br />
<br />
==== Make a local copy of the plugin ====<br />
<br />
mkdir -p [EPRINTS_ROOT]/archives/[ARCHIVE_ID]/cfg/plugins/EPrints/Plugins/Screen/Public/RequestCopy/<br />
cp [EPRINTS_ROOT]/perl_lib/EPrints/Plugins/Screen/Public/RequestCopy.pm [EPRINTS_ROOT]/archives/[ARCHIVE_ID]/cfg/plugins/EPrints/Plugins/Screen/Public/RequestCopy/LocalRequestCopy.pm<br />
<br />
==== Edit the local copy of the plugin ====<br />
The package name and 'isa' need to be updated as this is a subclass of the existing plugin.<br />
<br />
Any methods that you don't need to change can also be removed (as they'll be inherited from the main RequestCopy module).<br />
<br />
'''PLEASE NOTE the example code below may have been taken from a different version of EPrints to the one you are running. DO NOT just copy and paste it. Please follow the process above to take a copy of RequestCopy from your server, and edit it!'''<br />
<br />
The changes are indicated with <code>### INSERTED CODE ###</code> comments.<br />
<br />
<source lang="perl"><br />
#################################<br />
# Example taken from https://github.com/eprints/eprints/blob/v3.3.16/perl_lib/EPrints/Plugin/Screen/Public/RequestCopy.pm<br />
#################################<br />
<br />
package EPrints::Plugin::Screen::Public::RequestCopy::LocalRequestCopy;<br />
<br />
@ISA = ( 'EPrints::Plugin::Screen::Public::RequestCopy' );<br />
<br />
use strict;<br />
<br />
sub action_request<br />
{<br />
my( $self ) = @_;<br />
<br />
my $session = $self->{session};<br />
<br />
my $request = $self->{processor}->{dataobj};<br />
<br />
my $rc = $self->workflow->update_from_form( $self->{processor} );<br />
return if !$rc; # validation failed<br />
<br />
my $email = $request->value( "requester_email" );<br />
<br />
my $use_pin_security = $session->config( 'use_request_copy_pin_security' );<br />
<br />
my $eprint = $self->{processor}->{eprint};<br />
my $doc = $self->{processor}->{document};<br />
my $contact_email = $self->{processor}->{contact_email};<br />
<br />
my $user = EPrints::DataObj::User::user_with_email( $session, $contact_email );<br />
if( defined $user )<br />
{<br />
$request->set_value( "userid", $user->id );<br />
}<br />
<br />
$request = $self->{processor}->{dataset}->create_dataobj( $request->get_data );<br />
<br />
my $history_data = {<br />
datasetid=>"request",<br />
objectid=>$request->get_id,<br />
action=>"create",<br />
};<br />
<br />
if( defined $self->{processor}->{user} )<br />
{<br />
$history_data->{userid} = $self->{processor}->{user}->get_id;<br />
}<br />
else<br />
{<br />
$history_data->{actor} = $email;<br />
}<br />
<br />
# Log request creation event<br />
my $history_ds = $session->dataset( "history" );<br />
$history_ds->create_object( $session, $history_data );<br />
<br />
# Send request email<br />
my $subject = $session->phrase( "request/request_email:subject", eprint => $eprint->get_value( "title" ) );<br />
my $mail = $session->make_element( "mail" );<br />
$mail->appendChild( $session->html_phrase(<br />
"request/request_email:body", <br />
eprint => $eprint->render_citation_link_staff,<br />
document => defined $doc ? $doc->render_value( "main" ) : $session->make_doc_fragment,<br />
requester => $request->render_citation( "requester" ),<br />
### INSERTED CODE ###<br />
# this checks whether the value is set, and returns either the rendered value, or an empty document fragment<br />
# the pins for a phrase must be XML fragments - not scalar values.<br />
# The corresponding phrase (request/request_email:body) must also be updated to expect the new data.<br />
contact_num => $request->is_set( "contact_num" ) ? $request->render_value( "contact_num" ) : $session->make_doc_fragment,<br />
id_num => $request->is_set( "id_num" ) ? $request->render_value( "id_num" ) : $session->make_doc_fragment,<br />
### END INSERTED CODE ###<br />
reason => $request->is_set( "reason" ) ? $request->render_value( "reason" )<br />
: $session->html_phrase( "Plugin/Screen/EPrint/RequestRemoval:reason" ) ) );<br />
<br />
my $result;<br />
if( ( defined $user || $use_pin_security ) && defined $doc )<br />
{<br />
# Contact is a registered user or it doesn't matter<br />
# because we're using the pin security model, and<br />
# EPrints holds the requested document<br />
<br />
# Send email to contact with accept/reject links<br />
<br />
my $url;<br />
if ( $use_pin_security )<br />
{<br />
# Handle the response via a non-authenticated CGI script<br />
$url = $session->get_url( host => 1, path => "cgi", "respond_to_doc_request" );<br />
$url->query_form(<br />
pin => $request->get_value( 'pin' ),<br />
);<br />
}<br />
else<br />
{<br />
# Handle the response via cgi/users/home which is authenticated<br />
$url = $session->get_url( host => 1, path => "cgi", "users/home" );<br />
$url->query_form(<br />
screen => "Request::Respond",<br />
requestid => $request->id,<br />
);<br />
}<br />
<br />
$mail->appendChild( $session->html_phrase( "request/request_email:links",<br />
accept => $session->render_link( "$url&action=accept" ),<br />
reject => $session->render_link( "$url&action=reject" ) ) );<br />
<br />
my $to_name;<br />
if ( defined $user )<br />
{<br />
$to_name = EPrints::Utils::tree_to_utf8( $user->render_description );<br />
}<br />
else<br />
{<br />
$to_name = $contact_email;<br />
}<br />
<br />
$result = EPrints::Email::send_mail(<br />
session => $session,<br />
langid => $session->get_langid,<br />
to_name => $to_name,<br />
to_email => $contact_email,<br />
subject => $subject,<br />
message => $mail,<br />
sig => $session->html_phrase( "mail_sig" ),<br />
cc_list => EPrints::Utils::is_set( $session->config( "request_copy_cc" ) ) ? $session->config( "request_copy_cc" ) : [],<br />
);<br />
} <br />
else<br />
{<br />
# Contact is non-registered user or EPrints holds no documents<br />
# Send email to contact with 'replyto'<br />
$result = EPrints::Email::send_mail(<br />
session => $session,<br />
langid => $session->get_langid,<br />
to_name => defined $user ? EPrints::Utils::tree_to_utf8( $user->render_description ) : "",<br />
to_email => $contact_email,<br />
subject => $subject,<br />
message => $mail,<br />
sig => $session->html_phrase( "mail_sig" ),<br />
replyto_email => $email,<br />
cc_list => EPrints::Utils::is_set( $session->config( "request_copy_cc" ) ) ? $session->config( "request_copy_cc" ) : [],<br />
);<br />
}<br />
<br />
if( !$result )<br />
{<br />
$self->{processor}->add_message( "error", $session->html_phrase( "general:email_failed" ) );<br />
return;<br />
}<br />
<br />
# Send acknowledgement to requester<br />
$mail = $session->make_element( "mail" );<br />
$mail->appendChild( $session->html_phrase(<br />
"request/ack_email:body", <br />
document => defined $doc ? $doc->render_value( "main" ) : $session->make_doc_fragment,<br />
eprint => $eprint->render_citation_link ) );<br />
<br />
$result = EPrints::Email::send_mail(<br />
session => $session,<br />
langid => $session->get_langid,<br />
to_email => $email,<br />
subject => $session->phrase( "request/ack_email:subject", eprint=>$eprint->get_value( "title" ) ), <br />
message => $mail,<br />
sig => $session->html_phrase( "mail_sig" )<br />
);<br />
<br />
if( !$result )<br />
{<br />
$self->{processor}->add_message( "error", $session->html_phrase( "general:email_failed" ) );<br />
return;<br />
}<br />
<br />
$self->{processor}->add_message( "message", $session->html_phrase( "request/ack_page", link => $session->render_link( $eprint->get_url ) ) );<br />
$self->{processor}->{request_sent} = 1;<br />
}<br />
<br />
1;<br />
</source><br />
<br />
==== Add phrase ====<br />
The changes to the perl module add two new pins to the phrase. We have to update a local copy of the phrase and add places for these pins to be inserted.<br />
In the file <code>[EPRINTS_ROOT]/lib/lang/en/phrases/system.xml</code> locate the phrase <code>request/request_email:body</code> (see: https://github.com/eprints/eprints/blob/v3.3.16/lib/lang/en/phrases/system.xml#L3422-L3431)<br />
<br />
Copy this phrase into an XML phrase file e.g. <code>[EPRINTS_ROOT]/archives/[ARCHIVE_ID]/cfg/lang/en/phrases/z_request_fields.xml</code> - used above.<br />
Edit the phrase, defining places for the new pins to appear:<br />
<br />
<source lang="xml"><br />
<epp:phrase id="request/request_email:body"><br />
<p>This item has been requested from <epc:phrase ref="archive_name" /> by <epc:pin name="requester"/>.</p><br />
<p>Contact number: <epc:pin name="contact_num"/><br /><br />
ID number: <epc:pin name="id_num"/></p><br />
<p>Please can you respond.</p><br />
<br />
<p><epc:pin name="eprint"/><br/><epc:pin name="document"/></p><br />
<p>The following reason was given:</p><br />
<epc:pin name="reason"/><br />
<br />
<p>Please consider removing restrictions or uploading the full text to the archive so that it will be available immediately to future searchers.</p><br />
</epp:phrase><br />
</source><br />
<br />
==== Enable plugin (map) ====<br />
<br />
Finally, we have to tell EPrints to use our new plugin in place of the existing one.<br />
<br />
Read the details in <code>[EPRINTS_ROOT]/archives/[ARCHIVE_ID]/cfg/cfg.d/plugins.pl</code>.<br />
<br />
Once you understand what need to be done, add the plugin enabling code in a suitable configuration file e.g. <code>[EPRINTS_ROOT]/archives/[ARCHIVE_ID]/cfg/cfg.d/z_request_fields.pl</code>.<br />
<br />
<source lang="perl"><br />
$c->{plugin_alias_map}->{"Screen::Public::RequestCopy"} = "Screen::Public::RequestCopy::LocalRequestCopy";<br />
$c->{plugin_alias_map}->{"Screen::Public::RequestCopy::LocalRequestCopy"} = undef;<br />
<br />
# If this doesn't seem to work, try uncommenting this:<br />
# $c->{plugins}->{"Screen::Public::RequestCopy::LocalRequestCopy"}->{params}->{disable} = 0;<br />
</source><br />
<br />
==== Test everything and restart apache ====<br />
Using the same procedure as after adding the fields.<br />
<br />
If the <code>epadmin test</code> returns no errors, restart Apache, and try requesting something!</div>Libjlrshttps://wiki.eprints.org/w/index.php?title=Altering_the_%27Request_a_copy%27_function&diff=12823Altering the 'Request a copy' function2018-08-03T10:45:21Z<p>Libjlrs: /* Altering the email sent to the contact_email address */</p>
<hr />
<div>[[Category:Howto]]<br />
<br />
The ''Request a copy'' function allows for some restricted items to be requested by a visitor to the repository.<br />
<br />
If you want someone requesting an item to provide more information that the default email address and reason, you can add additional fields to the request form using the methods outlined below.<br />
<br />
== Adding additional fields to the request dataset ==<br />
<br />
The 'requests' are dataobjects - very similar to an eprint, or a user, so you can add fields in the same way.<br />
<br />
=== Add configuration for new fields ===<br />
<br />
In a config file e.g. <code>[EPRINTS_ROOT]/archives/[ARCHIVE_ID]/cfg/cfg.d/z_request_fields.pl</code><br />
<source lang="perl"><br />
## Additional fields for 'Request a copy'<br />
push @{$c->{fields}->{request}},<br />
{<br />
name => "contact_num",<br />
type => "text",<br />
},<br />
{<br />
name => "id_num",<br />
type => "text",<br />
};<br />
</source><br />
<br />
After adding this file, test the config is OK (avoid syntax errors):<br />
> [EPRINTS_ROOT]/bin/epadmin test [ARCHIVE_ID]<br />
<br />
=== Add phrases for new fields ===<br />
<br />
Add the phrases to e.g. <code>[EPRINTS_ROOT]/archives/[ARCHIVE_ID]/cfg/lang/en/phrases/z_request_fields.xml</code>:<br />
<br />
<source lang="xml"><br />
<?xml version="1.0" encoding="utf-8" standalone="no"?><br />
<!DOCTYPE phrases SYSTEM "entities.dtd"><br />
<epp:phrases xmlns="http://www.w3.org/1999/xhtml" xmlns:epp="http://eprints.org/ep3/phrase" xmlns:epc="http://eprints.org/ep3/control"><br />
<epp:phrase id="request_fieldname_contact_num">Contact number</epp:phrase><br />
<epp:phrase id="request_fieldhelp_contact_num">A number that we can contact you on to discuss your request if necessary </epp:phrase><br />
<br />
<epp:phrase id="request_fieldname_id_num">ID number</epp:phrase><br />
<epp:phrase id="request_fieldhelp_id_num">The identification number from your staff/student card</epp:phrase><br />
</epp:phrases><br />
</source><br />
<br />
Then run:<br />
> [EPRINTS_ROOT]/bin/epadmin update [ARCHIVE_ID]<br />
<br />
This will add the columns to the database.<br />
<br />
=== Adding fields to the workflow ===<br />
<br />
By default the workflow is in the global configuration. It can be customised by copying the default request workflow to the repository config:<br />
> mkdir [EPRINTS_ROOT]/archives/[ARCHIVE_ID]/cfg/workflows/request<br />
> cp [EPRINTS_ROOT]/lib/workflows/request/default.xml [EPRINTS_ROOT]/archives/[ARCHIVE_ID]/cfg/workflows/request<br />
<br />
=== Reload Apache ===<br />
<br />
Test the config again:<br />
> [EPRINTS_ROOT]/bin/epadmin test [ARCHIVE_ID]<br />
<br />
Restart Apache (this command depends on which operating system you use - you may need to do something slightly different!)<br />
> sudo service httpd graceful<br />
<br />
This should have added the fields to the 'Request a copy' workflow.<br />
<br />
== Altering the email sent to the <code>contact_email</code> address ==<br />
<br />
There are two ways this can be achieved - depending on your version of EPrints.<br />
<br />
=== Method A: Editing the 'requester' citation ===<br />
<br />
If you are using a recent version of EPrints, and the file <code>[EPRINTS_ROOT]/lib/citations/request/requester.xml</code> exists, there is a simple way to include the new fields in the email to the contact_email address. Your version of EPrints uses a citation to include some information from the request dataobject in the request email.<br />
<br />
==== Copy requester citation to local configuration ====<br />
By default the request/requester citation is defined in the global configuration. Don't edit that version (as it will be overwritten when EPrints is upgraded).<br />
Make a copy:<br />
> mkdir [EPRINTS_ROOT]/archives/[ARCHIVE_ID]/cfg/citations/request/<br />
> cp [EPRINTS_ROOT]/lib/citations/reuqest/requester.xml [EPRINTS_ROOT]/archives/[ARCHIVE_ID]/cfg/citations/request/<br />
<br />
==== Edit requester citation ====<br />
Add the new fields to the requester citation:<br />
<br />
<source lang="xml"><br />
<?xml version="1.0" ?><br />
<cite:citation xmlns="http://www.w3.org/1999/xhtml" xmlns:cite="http://eprints.org/ep3/citation" xmlns:epc="http://eprints.org/ep3/control"><br />
<epc:print expr="requester_email"/><br />
<epc:if test="contact_num"><br /><epc:phrase ref="request_fieldname_contact_num" />: <epc:print expr="contact_num"/></epc:if><br />
<epc:if test="id_num"><br /><epc:phrase ref="request_fieldname_id_num" />: <epc:print expr="id_num"/></epc:if><br />
</cite:citation><br />
</source><br />
<br />
=== Method B: Overriding EPrints::Plugin::Screen::Public::RequestCopy ===<br />
<br />
If your version of EPrints doesn't have the above file, or you need to do something more complex than just adding the fields, follow these instructions!<br />
<br />
The screen that processes the request being made (not the response to the request) is <code>EPrints::Plugin::Screen::Public::RequestCopy</code>.<br />
To include the additional data in the email sent to the contact_email address, we need to change the way this behaves - specifying the additional details to be added.<br />
<br />
The correct 'EPrints' way to do this for a plugin is outlined here: https://wiki.eprints.org/w/Instructions_for_local_plugins<br />
<br />
==== Understand how the current script works ====<br />
Take a look at <code>EPrints::Plugin::Screen::Public::RequestCopy</code> and try to understand it (a bit at least).<br />
<br />
Work out which of the methods you need to work differently.<br />
<br />
==== Make a local copy of the plugin ====<br />
<br />
mkdir -p [EPRINTS_ROOT]/archives/[ARCHIVE_ID]/cfg/plugins/EPrints/Plugins/Screen/Public/RequestCopy/<br />
cp [EPRINTS_ROOT]/perl_lib/EPrints/Plugins/Screen/Public/RequestCopy.pm [EPRINTS_ROOT]/archives/[ARCHIVE_ID]/cfg/plugins/EPrints/Plugins/Screen/Public/RequestCopy/LocalRequestCopy.pm<br />
<br />
==== Edit the local copy of the plugin ====<br />
The package name and 'isa' need to be updated as this is a subclass of the existing plugin.<br />
<br />
Any methods that you don't need to change can also be removed (as they'll be inherited from the main RequestCopy module).<br />
<br />
'''PLEASE NOTE the example code below may have been taken from a different version of EPrints to the one you are running. DO NOT just copy and paste it. Please follow the process above to take a copy of RequestCopy from your server, and edit it!'''<br />
<br />
The changes are indicated with <code>### INSERTED CODE ###</code> comments.<br />
<br />
<source lang="perl"><br />
#################################<br />
# Example taken from https://github.com/eprints/eprints/blob/v3.3.16/perl_lib/EPrints/Plugin/Screen/Public/RequestCopy.pm<br />
#################################<br />
<br />
package EPrints::Plugin::Screen::Public::RequestCopy::LocalRequestCopy;<br />
<br />
@ISA = ( 'EPrints::Plugin::Screen::Public::RequestCopy' );<br />
<br />
use strict;<br />
<br />
sub action_request<br />
{<br />
my( $self ) = @_;<br />
<br />
my $session = $self->{session};<br />
<br />
my $request = $self->{processor}->{dataobj};<br />
<br />
my $rc = $self->workflow->update_from_form( $self->{processor} );<br />
return if !$rc; # validation failed<br />
<br />
my $email = $request->value( "requester_email" );<br />
<br />
my $use_pin_security = $session->config( 'use_request_copy_pin_security' );<br />
<br />
my $eprint = $self->{processor}->{eprint};<br />
my $doc = $self->{processor}->{document};<br />
my $contact_email = $self->{processor}->{contact_email};<br />
<br />
my $user = EPrints::DataObj::User::user_with_email( $session, $contact_email );<br />
if( defined $user )<br />
{<br />
$request->set_value( "userid", $user->id );<br />
}<br />
<br />
$request = $self->{processor}->{dataset}->create_dataobj( $request->get_data );<br />
<br />
my $history_data = {<br />
datasetid=>"request",<br />
objectid=>$request->get_id,<br />
action=>"create",<br />
};<br />
<br />
if( defined $self->{processor}->{user} )<br />
{<br />
$history_data->{userid} = $self->{processor}->{user}->get_id;<br />
}<br />
else<br />
{<br />
$history_data->{actor} = $email;<br />
}<br />
<br />
# Log request creation event<br />
my $history_ds = $session->dataset( "history" );<br />
$history_ds->create_object( $session, $history_data );<br />
<br />
# Send request email<br />
my $subject = $session->phrase( "request/request_email:subject", eprint => $eprint->get_value( "title" ) );<br />
my $mail = $session->make_element( "mail" );<br />
$mail->appendChild( $session->html_phrase(<br />
"request/request_email:body", <br />
eprint => $eprint->render_citation_link_staff,<br />
document => defined $doc ? $doc->render_value( "main" ) : $session->make_doc_fragment,<br />
requester => $request->render_citation( "requester" ),<br />
### INSERTED CODE ###<br />
# this checks whether the value is set, and returns either the rendered value, or an empty document fragment<br />
# the pins for a phrase must be XML fragments - not scalar values.<br />
# The corresponding phrase (request/request_email:body) must also be updated to expect the new data.<br />
contact_num => $request->is_set( "contact_num" ) ? $request->render_value( "contact_num" ) : $session->make_doc_fragment,<br />
id_num => $request->is_set( "id_num" ) ? $request->render_value( "id_num" ) : $session->make_doc_fragment,<br />
### END INSERTED CODE ###<br />
reason => $request->is_set( "reason" ) ? $request->render_value( "reason" )<br />
: $session->html_phrase( "Plugin/Screen/EPrint/RequestRemoval:reason" ) ) );<br />
<br />
my $result;<br />
if( ( defined $user || $use_pin_security ) && defined $doc )<br />
{<br />
# Contact is a registered user or it doesn't matter<br />
# because we're using the pin security model, and<br />
# EPrints holds the requested document<br />
<br />
# Send email to contact with accept/reject links<br />
<br />
my $url;<br />
if ( $use_pin_security )<br />
{<br />
# Handle the response via a non-authenticated CGI script<br />
$url = $session->get_url( host => 1, path => "cgi", "respond_to_doc_request" );<br />
$url->query_form(<br />
pin => $request->get_value( 'pin' ),<br />
);<br />
}<br />
else<br />
{<br />
# Handle the response via cgi/users/home which is authenticated<br />
$url = $session->get_url( host => 1, path => "cgi", "users/home" );<br />
$url->query_form(<br />
screen => "Request::Respond",<br />
requestid => $request->id,<br />
);<br />
}<br />
<br />
$mail->appendChild( $session->html_phrase( "request/request_email:links",<br />
accept => $session->render_link( "$url&action=accept" ),<br />
reject => $session->render_link( "$url&action=reject" ) ) );<br />
<br />
my $to_name;<br />
if ( defined $user )<br />
{<br />
$to_name = EPrints::Utils::tree_to_utf8( $user->render_description );<br />
}<br />
else<br />
{<br />
$to_name = $contact_email;<br />
}<br />
<br />
$result = EPrints::Email::send_mail(<br />
session => $session,<br />
langid => $session->get_langid,<br />
to_name => $to_name,<br />
to_email => $contact_email,<br />
subject => $subject,<br />
message => $mail,<br />
sig => $session->html_phrase( "mail_sig" ),<br />
cc_list => EPrints::Utils::is_set( $session->config( "request_copy_cc" ) ) ? $session->config( "request_copy_cc" ) : [],<br />
);<br />
} <br />
else<br />
{<br />
# Contact is non-registered user or EPrints holds no documents<br />
# Send email to contact with 'replyto'<br />
$result = EPrints::Email::send_mail(<br />
session => $session,<br />
langid => $session->get_langid,<br />
to_name => defined $user ? EPrints::Utils::tree_to_utf8( $user->render_description ) : "",<br />
to_email => $contact_email,<br />
subject => $subject,<br />
message => $mail,<br />
sig => $session->html_phrase( "mail_sig" ),<br />
replyto_email => $email,<br />
cc_list => EPrints::Utils::is_set( $session->config( "request_copy_cc" ) ) ? $session->config( "request_copy_cc" ) : [],<br />
);<br />
}<br />
<br />
if( !$result )<br />
{<br />
$self->{processor}->add_message( "error", $session->html_phrase( "general:email_failed" ) );<br />
return;<br />
}<br />
<br />
# Send acknowledgement to requester<br />
$mail = $session->make_element( "mail" );<br />
$mail->appendChild( $session->html_phrase(<br />
"request/ack_email:body", <br />
document => defined $doc ? $doc->render_value( "main" ) : $session->make_doc_fragment,<br />
eprint => $eprint->render_citation_link ) );<br />
<br />
$result = EPrints::Email::send_mail(<br />
session => $session,<br />
langid => $session->get_langid,<br />
to_email => $email,<br />
subject => $session->phrase( "request/ack_email:subject", eprint=>$eprint->get_value( "title" ) ), <br />
message => $mail,<br />
sig => $session->html_phrase( "mail_sig" )<br />
);<br />
<br />
if( !$result )<br />
{<br />
$self->{processor}->add_message( "error", $session->html_phrase( "general:email_failed" ) );<br />
return;<br />
}<br />
<br />
$self->{processor}->add_message( "message", $session->html_phrase( "request/ack_page", link => $session->render_link( $eprint->get_url ) ) );<br />
$self->{processor}->{request_sent} = 1;<br />
}<br />
<br />
1;<br />
</source><br />
<br />
==== Add phrase ====<br />
The changes to the perl module add two new pins to the phrase. We have to update a local copy of the phrase and add places for these pins to be inserted.<br />
In the file <code>[EPRINTS_ROOT]/lib/lang/en/phrases/system.xml</code> locate the phrase <code>request/request_email:body</code> (see: https://github.com/eprints/eprints/blob/v3.3.16/lib/lang/en/phrases/system.xml#L3422-L3431)<br />
<br />
Copy this phrase into an XML phrase file e.g. <code>[EPRINTS_ROOT]/archives/[ARCHIVE_ID]/cfg/lang/en/phrases/z_request_fields.xml</code> - used above.<br />
Edit the phrase, defining places for the new pins to appear:<br />
<br />
<source lang="xml"><br />
<epp:phrase id="request/request_email:body"><br />
<p>This item has been requested from <epc:phrase ref="archive_name" /> by <epc:pin name="requester"/>.</p><br />
<p>Contact number: <epc:pin name="contact_num"/><br /><br />
ID number: <epc:pin name="id_num"/></p><br />
<p>Please can you respond.</p><br />
<br />
<p><epc:pin name="eprint"/><br/><epc:pin name="document"/></p><br />
<p>The following reason was given:</p><br />
<epc:pin name="reason"/><br />
<br />
<p>Please consider removing restrictions or uploading the full text to the archive so that it will be available immediately to future searchers.</p><br />
</epp:phrase><br />
</source><br />
<br />
==== Enable plugin (map) ====<br />
<br />
Finally, we have to tell EPrints to use our new plugin in place of the existing one.<br />
<br />
Read the details in <code>[EPRINTS_ROOT]/archives/[ARCHIVE_ID]/cfg/cfg.d/plugins.pl</code>.<br />
<br />
Once you understand what need to be done, add the plugin enabling code in a suitable configuration file e.g. <code>[EPRINTS_ROOT]/archives/[ARCHIVE_ID]/cfg/cfg.d/z_request_fields.pl</code>.<br />
<br />
<source lang="perl"><br />
$c->{plugin_alias_map}->{"Screen::Public::RequestCopy"} = "Screen::Public::RequestCopy::LocalRequestCopy";<br />
$c->{plugin_alias_map}->{"Screen::Public::RequestCopy::LocalRequestCopy"} = undef;<br />
<br />
# If this doesn't seem to work, try uncommenting this:<br />
# $c->{plugins}->{"Screen::Public::RequestCopy::LocalRequestCopy"}->{params}->{disable} = 0;<br />
</source><br />
<br />
==== Test everything and restart apache ====<br />
Using the same procedure as after adding the fields.<br />
<br />
If the <code>epadmin test</code> returns no errors, restart Apache, and try requesting something!</div>Libjlrshttps://wiki.eprints.org/w/index.php?title=Altering_the_%27Request_a_copy%27_function&diff=12822Altering the 'Request a copy' function2018-08-03T09:51:02Z<p>Libjlrs: Add details of overriding plugin</p>
<hr />
<div>[[Category:Howto]]<br />
<br />
The ''Request a copy'' function allows for some restricted items to be requested by a visitor to the repository.<br />
<br />
If you want someone requesting an item to provide more information that the default email address and reason, you can add additional fields to the request form using the methods outlined below.<br />
<br />
== Adding additional fields to the request dataset ==<br />
<br />
The 'requests' are dataobjects - very similar to an eprint, or a user, so you can add fields in the same way.<br />
<br />
=== Add configuration for new fields ===<br />
<br />
In a config file e.g. <code>[EPRINTS_ROOT]/archives/[ARCHIVE_ID]/cfg/cfg.d/z_request_fields.pl</code><br />
<source lang="perl"><br />
## Additional fields for 'Request a copy'<br />
push @{$c->{fields}->{request}},<br />
{<br />
name => "contact_num",<br />
type => "text",<br />
},<br />
{<br />
name => "id_num",<br />
type => "text",<br />
};<br />
</source><br />
<br />
After adding this file, test the config is OK (avoid syntax errors):<br />
> [EPRINTS_ROOT]/bin/epadmin test [ARCHIVE_ID]<br />
<br />
=== Add phrases for new fields ===<br />
<br />
Add the phrases to e.g. <code>[EPRINTS_ROOT]/archives/[ARCHIVE_ID]/cfg/lang/en/phrases/z_request_fields.xml</code>:<br />
<br />
<source lang="xml"><br />
<?xml version="1.0" encoding="utf-8" standalone="no"?><br />
<!DOCTYPE phrases SYSTEM "entities.dtd"><br />
<epp:phrases xmlns="http://www.w3.org/1999/xhtml" xmlns:epp="http://eprints.org/ep3/phrase" xmlns:epc="http://eprints.org/ep3/control"><br />
<epp:phrase id="request_fieldname_contact_num">Contact number</epp:phrase><br />
<epp:phrase id="request_fieldhelp_contact_num">A number that we can contact you on to discuss your request if necessary </epp:phrase><br />
<br />
<epp:phrase id="request_fieldname_id_num">ID number</epp:phrase><br />
<epp:phrase id="request_fieldhelp_id_num">The identification number from your staff/student card</epp:phrase><br />
</epp:phrases><br />
</source><br />
<br />
Then run:<br />
> [EPRINTS_ROOT]/bin/epadmin update [ARCHIVE_ID]<br />
<br />
This will add the columns to the database.<br />
<br />
=== Adding fields to the workflow ===<br />
<br />
By default the workflow is in the global configuration. It can be customised by copying the default request workflow to the repository config:<br />
> mkdir [EPRINTS_ROOT]/archives/[ARCHIVE_ID]/cfg/workflows/request<br />
> cp [EPRINTS_ROOT]/lib/workflows/request/default.xml [EPRINTS_ROOT]/archives/[ARCHIVE_ID]/cfg/workflows/request<br />
<br />
=== Reload Apache ===<br />
<br />
Test the config again:<br />
> [EPRINTS_ROOT]/bin/epadmin test [ARCHIVE_ID]<br />
<br />
Restart Apache (this command depends on which operating system you use - you may need to do something slightly different!)<br />
> sudo service httpd graceful<br />
<br />
This should have added the fields to the 'Request a copy' workflow.<br />
<br />
== Altering the email sent to the <code>contact_email</code> address ==<br />
<br />
If you are using a recent version of EPrints, and the file <code>[EPRINTS_ROOT]/lib/citations/request/requester.xml</code> exists, ignore this section and see [[other bit]].<br />
Your version of EPrints uses a citation to include some information in the request email, which is easier to customise.<br />
<br />
If your version of EPrints doesn't have the above file, or you need to do something more complex than just addin the fields, follow these instructions!<br />
<br />
The screen that processes the request being made (not the response to the request) is <code>EPrints::Plugin::Screen::Public::RequestCopy</code>.<br />
To include the additional data in the email sent to the contact_email address, we need to change the way this behaves - specifying the additional details to be added.<br />
<br />
The correct 'EPrints' way to do this for a plugin is outlined here: https://wiki.eprints.org/w/Instructions_for_local_plugins<br />
<br />
=== Understand how the current script works ===<br />
Take a look at <code>EPrints::Plugin::Screen::Public::RequestCopy</code> and try to understand it (a bit at least).<br />
<br />
Work out which of the methods you need to work differently.<br />
<br />
=== Make a local copy of the plugin ===<br />
<br />
mkdir -p [EPRINTS_ROOT]/archives/[ARCHIVE_ID]/cfg/plugins/EPrints/Plugins/Screen/Public/RequestCopy/<br />
cp [EPRINTS_ROOT]/perl_lib/EPrints/Plugins/Screen/Public/RequestCopy.pm [EPRINTS_ROOT]/archives/[ARCHIVE_ID]/cfg/plugins/EPrints/Plugins/Screen/Public/RequestCopy/LocalRequestCopy.pm<br />
<br />
=== Edit the local copy of the plugin ===<br />
The package name and 'isa' need to be updated as this is a subclass of the existing plugin.<br />
<br />
Any methods that you don't need to change can also be removed (as they'll be inherited from the main RequestCopy module).<br />
<br />
'''PLEASE NOTE the example code below may have been taken from a different version of EPrints to the one you are running. DO NOT just copy and paste it. Please follow the process above to take a copy of RequestCopy from your server, and edit it!'''<br />
<br />
The changes are indicated with <code>### INSERTED CODE ###</code> comments.<br />
<br />
<source lang="perl"><br />
#################################<br />
# Example taken from https://github.com/eprints/eprints/blob/v3.3.16/perl_lib/EPrints/Plugin/Screen/Public/RequestCopy.pm<br />
#################################<br />
<br />
package EPrints::Plugin::Screen::Public::RequestCopy::LocalRequestCopy;<br />
<br />
@ISA = ( 'EPrints::Plugin::Screen::Public::RequestCopy' );<br />
<br />
use strict;<br />
<br />
sub action_request<br />
{<br />
my( $self ) = @_;<br />
<br />
my $session = $self->{session};<br />
<br />
my $request = $self->{processor}->{dataobj};<br />
<br />
my $rc = $self->workflow->update_from_form( $self->{processor} );<br />
return if !$rc; # validation failed<br />
<br />
my $email = $request->value( "requester_email" );<br />
<br />
my $use_pin_security = $session->config( 'use_request_copy_pin_security' );<br />
<br />
my $eprint = $self->{processor}->{eprint};<br />
my $doc = $self->{processor}->{document};<br />
my $contact_email = $self->{processor}->{contact_email};<br />
<br />
my $user = EPrints::DataObj::User::user_with_email( $session, $contact_email );<br />
if( defined $user )<br />
{<br />
$request->set_value( "userid", $user->id );<br />
}<br />
<br />
$request = $self->{processor}->{dataset}->create_dataobj( $request->get_data );<br />
<br />
my $history_data = {<br />
datasetid=>"request",<br />
objectid=>$request->get_id,<br />
action=>"create",<br />
};<br />
<br />
if( defined $self->{processor}->{user} )<br />
{<br />
$history_data->{userid} = $self->{processor}->{user}->get_id;<br />
}<br />
else<br />
{<br />
$history_data->{actor} = $email;<br />
}<br />
<br />
# Log request creation event<br />
my $history_ds = $session->dataset( "history" );<br />
$history_ds->create_object( $session, $history_data );<br />
<br />
# Send request email<br />
my $subject = $session->phrase( "request/request_email:subject", eprint => $eprint->get_value( "title" ) );<br />
my $mail = $session->make_element( "mail" );<br />
$mail->appendChild( $session->html_phrase(<br />
"request/request_email:body", <br />
eprint => $eprint->render_citation_link_staff,<br />
document => defined $doc ? $doc->render_value( "main" ) : $session->make_doc_fragment,<br />
requester => $request->render_citation( "requester" ),<br />
### INSERTED CODE ###<br />
<br />
### END INSERTED CODE ###<br />
reason => $request->is_set( "reason" ) ? $request->render_value( "reason" )<br />
: $session->html_phrase( "Plugin/Screen/EPrint/RequestRemoval:reason" ) ) );<br />
<br />
my $result;<br />
if( ( defined $user || $use_pin_security ) && defined $doc )<br />
{<br />
# Contact is a registered user or it doesn't matter<br />
# because we're using the pin security model, and<br />
# EPrints holds the requested document<br />
<br />
# Send email to contact with accept/reject links<br />
<br />
my $url;<br />
if ( $use_pin_security )<br />
{<br />
# Handle the response via a non-authenticated CGI script<br />
$url = $session->get_url( host => 1, path => "cgi", "respond_to_doc_request" );<br />
$url->query_form(<br />
pin => $request->get_value( 'pin' ),<br />
);<br />
}<br />
else<br />
{<br />
# Handle the response via cgi/users/home which is authenticated<br />
$url = $session->get_url( host => 1, path => "cgi", "users/home" );<br />
$url->query_form(<br />
screen => "Request::Respond",<br />
requestid => $request->id,<br />
);<br />
}<br />
<br />
$mail->appendChild( $session->html_phrase( "request/request_email:links",<br />
accept => $session->render_link( "$url&action=accept" ),<br />
reject => $session->render_link( "$url&action=reject" ) ) );<br />
<br />
my $to_name;<br />
if ( defined $user )<br />
{<br />
$to_name = EPrints::Utils::tree_to_utf8( $user->render_description );<br />
}<br />
else<br />
{<br />
$to_name = $contact_email;<br />
}<br />
<br />
$result = EPrints::Email::send_mail(<br />
session => $session,<br />
langid => $session->get_langid,<br />
to_name => $to_name,<br />
to_email => $contact_email,<br />
subject => $subject,<br />
message => $mail,<br />
sig => $session->html_phrase( "mail_sig" ),<br />
cc_list => EPrints::Utils::is_set( $session->config( "request_copy_cc" ) ) ? $session->config( "request_copy_cc" ) : [],<br />
);<br />
} <br />
else<br />
{<br />
# Contact is non-registered user or EPrints holds no documents<br />
# Send email to contact with 'replyto'<br />
$result = EPrints::Email::send_mail(<br />
session => $session,<br />
langid => $session->get_langid,<br />
to_name => defined $user ? EPrints::Utils::tree_to_utf8( $user->render_description ) : "",<br />
to_email => $contact_email,<br />
subject => $subject,<br />
message => $mail,<br />
sig => $session->html_phrase( "mail_sig" ),<br />
replyto_email => $email,<br />
cc_list => EPrints::Utils::is_set( $session->config( "request_copy_cc" ) ) ? $session->config( "request_copy_cc" ) : [],<br />
);<br />
}<br />
<br />
if( !$result )<br />
{<br />
$self->{processor}->add_message( "error", $session->html_phrase( "general:email_failed" ) );<br />
return;<br />
}<br />
<br />
# Send acknowledgement to requester<br />
$mail = $session->make_element( "mail" );<br />
$mail->appendChild( $session->html_phrase(<br />
"request/ack_email:body", <br />
document => defined $doc ? $doc->render_value( "main" ) : $session->make_doc_fragment,<br />
eprint => $eprint->render_citation_link ) );<br />
<br />
$result = EPrints::Email::send_mail(<br />
session => $session,<br />
langid => $session->get_langid,<br />
to_email => $email,<br />
subject => $session->phrase( "request/ack_email:subject", eprint=>$eprint->get_value( "title" ) ), <br />
message => $mail,<br />
sig => $session->html_phrase( "mail_sig" )<br />
);<br />
<br />
if( !$result )<br />
{<br />
$self->{processor}->add_message( "error", $session->html_phrase( "general:email_failed" ) );<br />
return;<br />
}<br />
<br />
$self->{processor}->add_message( "message", $session->html_phrase( "request/ack_page", link => $session->render_link( $eprint->get_url ) ) );<br />
$self->{processor}->{request_sent} = 1;<br />
}<br />
<br />
1;<br />
</source><br />
<br />
=== Add phrase ===<br />
=== Enable plugin (map) ===<br />
<br />
=== INstruction when request/requestor.xml exists ===<br />
<br />
UNDER CONSTRUCTION!<br />
Will follow this process: https://wiki.eprints.org/w/Instructions_for_local_plugins for the Screen::Public::RequestCopy plugin, overriding the 'action_request' method.</div>Libjlrshttps://wiki.eprints.org/w/index.php?title=Altering_the_%27Request_a_copy%27_function&diff=12821Altering the 'Request a copy' function2018-08-02T08:49:30Z<p>Libjlrs: </p>
<hr />
<div>[[Category:Howto]]<br />
<br />
The ''Request a copy'' function allows for some restricted items to be requested by a visitor to the repository.<br />
<br />
If you want someone requesting an item to provide more information that the default email address and reason, you can add additional fields to the request form using the methods outlined below.<br />
<br />
== Adding additional fields to the request dataset ==<br />
<br />
The 'requests' are dataobjects - very similar to an eprint, or a user, so you can add fields in the same way.<br />
<br />
=== Add configuration for new fields ===<br />
<br />
In a config file e.g. <code>[EPRINTS_ROOT]/archives/[ARCHIVE_ID]/cfg/cfg.d/z_request_fields.pl</code><br />
<source lang="perl"><br />
## Additional fields for 'Request a copy'<br />
push @{$c->{fields}->{request}},<br />
{<br />
name => "contact_num",<br />
type => "text",<br />
},<br />
{<br />
name => "id_num",<br />
type => "text",<br />
};<br />
</source><br />
<br />
After adding this file, test the config is OK (avoid syntax errors):<br />
> [EPRINTS_ROOT]/bin/epadmin test [ARCHIVE_ID]<br />
<br />
=== Add phrases for new fields ===<br />
<br />
Add the phrases to e.g. <code>[EPRINTS_ROOT]/archives/[ARCHIVE_ID]/cfg/lang/en/phrases/z_request_fields.xml</code>:<br />
<br />
<source lang="xml"><br />
<?xml version="1.0" encoding="utf-8" standalone="no"?><br />
<!DOCTYPE phrases SYSTEM "entities.dtd"><br />
<epp:phrases xmlns="http://www.w3.org/1999/xhtml" xmlns:epp="http://eprints.org/ep3/phrase" xmlns:epc="http://eprints.org/ep3/control"><br />
<epp:phrase id="request_fieldname_contact_num">Contact number</epp:phrase><br />
<epp:phrase id="request_fieldhelp_contact_num">A number that we can contact you on to discuss your request if necessary </epp:phrase><br />
<br />
<epp:phrase id="request_fieldname_id_num">ID number</epp:phrase><br />
<epp:phrase id="request_fieldhelp_id_num">The identification number from your staff/student card</epp:phrase><br />
</epp:phrases><br />
</source><br />
<br />
Then run:<br />
> [EPRINTS_ROOT]/bin/epadmin update [ARCHIVE_ID]<br />
<br />
This will add the columns to the database.<br />
<br />
=== Adding fields to the workflow ===<br />
<br />
By default the workflow is in the global configuration. It can be customised by copying the default request workflow to the repository config:<br />
> mkdir [EPRINTS_ROOT]/archives/[ARCHIVE_ID]/cfg/workflows/request<br />
> cp [EPRINTS_ROOT]/lib/workflows/request/default.xml [EPRINTS_ROOT]/archives/[ARCHIVE_ID]/cfg/workflows/request<br />
<br />
=== Reload Apache ===<br />
<br />
Test the config again:<br />
> [EPRINTS_ROOT]/bin/epadmin test [ARCHIVE_ID]<br />
<br />
Restart Apache (this command depends on which operating system you use - you may need to do something slightly different!)<br />
> sudo service httpd graceful<br />
<br />
This should have added the fields to the 'Request a copy' workflow.<br />
<br />
== Altering the email sent to the <code>contact_email</code> address ==<br />
<br />
UNDER CONSTRUCTION!<br />
Will follow this process: https://wiki.eprints.org/w/Instructions_for_local_plugins for the Screen::Public::RequestCopy plugin, overriding the 'action_request' method.</div>Libjlrs