Difference between revisions of "Altering the 'Request a copy' function"

From EPrints Documentation
Jump to: navigation, search
(Add details of overriding plugin)
(Altering the email sent to the contact_email address)
Line 67: Line 67:
 
== Altering the email sent to the <code>contact_email</code> address ==
 
== Altering the email sent to the <code>contact_email</code> address ==
  
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]].
+
There are two ways this can be achieved - depending on your version of EPrints.
Your version of EPrints uses a citation to include some information in the request email, which is easier to customise.
 
  
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!
+
=== Method A: Editing the 'requester' citation ===
 +
 
 +
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.
 +
 
 +
==== Copy requester citation to local configuration ====
 +
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).
 +
Make a copy:
 +
> mkdir [EPRINTS_ROOT]/archives/[ARCHIVE_ID]/cfg/citations/request/
 +
> cp [EPRINTS_ROOT]/lib/citations/reuqest/requester.xml [EPRINTS_ROOT]/archives/[ARCHIVE_ID]/cfg/citations/request/
 +
 
 +
==== Edit requester citation ====
 +
Add the new fields to the requester citation:
 +
 
 +
<source lang="xml">
 +
<?xml version="1.0" ?>
 +
<cite:citation xmlns="http://www.w3.org/1999/xhtml" xmlns:cite="http://eprints.org/ep3/citation" xmlns:epc="http://eprints.org/ep3/control">
 +
  <epc:print expr="requester_email"/>
 +
  <epc:if test="contact_num"><br /><epc:phrase ref="request_fieldname_contact_num" />: <epc:print expr="contact_num"/></epc:if>
 +
  <epc:if test="id_num"><br /><epc:phrase ref="request_fieldname_id_num" />: <epc:print expr="id_num"/></epc:if>
 +
</cite:citation>
 +
</source>
 +
 
 +
=== Method B: Overriding EPrints::Plugin::Screen::Public::RequestCopy ===
 +
 
 +
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!
  
 
The screen that processes the request being made (not the response to the request) is <code>EPrints::Plugin::Screen::Public::RequestCopy</code>.
 
The screen that processes the request being made (not the response to the request) is <code>EPrints::Plugin::Screen::Public::RequestCopy</code>.
Line 77: Line 100:
 
The correct 'EPrints' way to do this for a plugin is outlined here: https://wiki.eprints.org/w/Instructions_for_local_plugins
 
The correct 'EPrints' way to do this for a plugin is outlined here: https://wiki.eprints.org/w/Instructions_for_local_plugins
  
=== Understand how the current script works ===
+
==== Understand how the current script works ====
 
Take a look at <code>EPrints::Plugin::Screen::Public::RequestCopy</code> and try to understand it (a bit at least).
 
Take a look at <code>EPrints::Plugin::Screen::Public::RequestCopy</code> and try to understand it (a bit at least).
  
 
Work out which of the methods you need to work differently.
 
Work out which of the methods you need to work differently.
  
=== Make a local copy of the plugin ===
+
==== Make a local copy of the plugin ====
  
 
  mkdir -p [EPRINTS_ROOT]/archives/[ARCHIVE_ID]/cfg/plugins/EPrints/Plugins/Screen/Public/RequestCopy/
 
  mkdir -p [EPRINTS_ROOT]/archives/[ARCHIVE_ID]/cfg/plugins/EPrints/Plugins/Screen/Public/RequestCopy/
 
  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
 
  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
  
=== Edit the local copy of the plugin ===
+
==== Edit the local copy of the plugin ====
 
The package name and 'isa' need to be updated as this is a subclass of the existing plugin.
 
The package name and 'isa' need to be updated as this is a subclass of the existing plugin.
  
Line 162: Line 185:
 
requester => $request->render_citation( "requester" ),
 
requester => $request->render_citation( "requester" ),
 
### INSERTED CODE ###
 
### INSERTED CODE ###
+
# this checks whether the value is set, and returns either the rendered value, or an empty document fragment
 +
# the pins for a phrase must be XML fragments - not scalar values.
 +
# The corresponding phrase (request/request_email:body) must also be updated to expect the new data.
 +
contact_num => $request->is_set( "contact_num" ) ? $request->render_value( "contact_num" ) : $session->make_doc_fragment,
 +
id_num => $request->is_set( "id_num" ) ? $request->render_value( "id_num" ) : $session->make_doc_fragment,
 
### END INSERTED CODE ###
 
### END INSERTED CODE ###
 
reason => $request->is_set( "reason" ) ? $request->render_value( "reason" )
 
reason => $request->is_set( "reason" ) ? $request->render_value( "reason" )
Line 272: Line 299:
 
</source>
 
</source>
  
=== Add phrase ===
+
==== Add phrase ====
=== Enable plugin (map) ===
+
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.
 +
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)
 +
 
 +
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.
 +
Edit the phrase, defining places for the new pins to appear:
 +
 
 +
<source lang="xml">
 +
<epp:phrase id="request/request_email:body">
 +
  <p>This item has been requested from <epc:phrase ref="archive_name" /> by <epc:pin name="requester"/>.</p>
 +
  <p>Contact number: <epc:pin name="contact_num"/><br />
 +
    ID number: <epc:pin name="id_num"/></p>
 +
  <p>Please can you respond.</p>
 +
 
 +
  <p><epc:pin name="eprint"/><br/><epc:pin name="document"/></p>
 +
  <p>The following reason was given:</p>
 +
  <epc:pin name="reason"/>
 +
 
 +
  <p>Please consider removing restrictions or uploading the full text to the archive so that it will be available immediately to future searchers.</p>
 +
</epp:phrase>
 +
</source>
 +
 
 +
==== Enable plugin (map) ====
 +
 
 +
Finally, we have to tell EPrints to use our new plugin in place of the existing one.
 +
 
 +
Read the details in <code>[EPRINTS_ROOT]/archives/[ARCHIVE_ID]/cfg/cfg.d/plugins.pl</code>.
 +
 
 +
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>.
 +
 
 +
<source lang="perl">
 +
$c->{plugin_alias_map}->{"Screen::Public::RequestCopy"} = "Screen::Public::RequestCopy::LocalRequestCopy";
 +
$c->{plugin_alias_map}->{"Screen::Public::RequestCopy::LocalRequestCopy"} = undef;
 +
 
 +
# If this doesn't seem to work, try uncommenting this:
 +
# $c->{plugins}->{"Screen::Public::RequestCopy::LocalRequestCopy"}->{params}->{disable} = 0;
 +
</source>
  
=== INstruction when request/requestor.xml exists ===
+
==== Test everything and restart apache ====
 +
Using the same procedure as after adding the fields.
  
UNDER CONSTRUCTION!
+
If the <code>epadmin test</code> returns no errors, restart Apache, and try requesting something!
Will follow this process: https://wiki.eprints.org/w/Instructions_for_local_plugins for the Screen::Public::RequestCopy plugin, overriding the 'action_request' method.
 

Revision as of 10:45, 3 August 2018


The Request a copy function allows for some restricted items to be requested by a visitor to the repository.

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.

Adding additional fields to the request dataset

The 'requests' are dataobjects - very similar to an eprint, or a user, so you can add fields in the same way.

Add configuration for new fields

In a config file e.g. [EPRINTS_ROOT]/archives/[ARCHIVE_ID]/cfg/cfg.d/z_request_fields.pl

## Additional fields for 'Request a copy'
push @{$c->{fields}->{request}},
{
        name => "contact_num",
        type => "text",
},
{
        name => "id_num",
        type => "text",
};

After adding this file, test the config is OK (avoid syntax errors):

> [EPRINTS_ROOT]/bin/epadmin test [ARCHIVE_ID]

Add phrases for new fields

Add the phrases to e.g. [EPRINTS_ROOT]/archives/[ARCHIVE_ID]/cfg/lang/en/phrases/z_request_fields.xml:

<?xml version="1.0" encoding="utf-8" standalone="no"?>
<!DOCTYPE phrases SYSTEM "entities.dtd">
<epp:phrases xmlns="http://www.w3.org/1999/xhtml" xmlns:epp="http://eprints.org/ep3/phrase" xmlns:epc="http://eprints.org/ep3/control">
  <epp:phrase id="request_fieldname_contact_num">Contact number</epp:phrase>
  <epp:phrase id="request_fieldhelp_contact_num">A number that we can contact you on to discuss your request if necessary </epp:phrase>

  <epp:phrase id="request_fieldname_id_num">ID number</epp:phrase>
  <epp:phrase id="request_fieldhelp_id_num">The identification number from your staff/student card</epp:phrase>
</epp:phrases>

Then run:

> [EPRINTS_ROOT]/bin/epadmin update [ARCHIVE_ID]

This will add the columns to the database.

Adding fields to the workflow

By default the workflow is in the global configuration. It can be customised by copying the default request workflow to the repository config:

> mkdir [EPRINTS_ROOT]/archives/[ARCHIVE_ID]/cfg/workflows/request
> cp [EPRINTS_ROOT]/lib/workflows/request/default.xml [EPRINTS_ROOT]/archives/[ARCHIVE_ID]/cfg/workflows/request

Reload Apache

Test the config again:

> [EPRINTS_ROOT]/bin/epadmin test [ARCHIVE_ID]

Restart Apache (this command depends on which operating system you use - you may need to do something slightly different!) > sudo service httpd graceful

This should have added the fields to the 'Request a copy' workflow.

Altering the email sent to the contact_email address

There are two ways this can be achieved - depending on your version of EPrints.

Method A: Editing the 'requester' citation

If you are using a recent version of EPrints, and the file [EPRINTS_ROOT]/lib/citations/request/requester.xml 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.

Copy requester citation to local configuration

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). Make a copy:

> mkdir [EPRINTS_ROOT]/archives/[ARCHIVE_ID]/cfg/citations/request/
> cp [EPRINTS_ROOT]/lib/citations/reuqest/requester.xml [EPRINTS_ROOT]/archives/[ARCHIVE_ID]/cfg/citations/request/

Edit requester citation

Add the new fields to the requester citation:

<?xml version="1.0" ?>
<cite:citation xmlns="http://www.w3.org/1999/xhtml" xmlns:cite="http://eprints.org/ep3/citation" xmlns:epc="http://eprints.org/ep3/control">
  <epc:print expr="requester_email"/>
  <epc:if test="contact_num"><br /><epc:phrase ref="request_fieldname_contact_num" />: <epc:print expr="contact_num"/></epc:if>
  <epc:if test="id_num"><br /><epc:phrase ref="request_fieldname_id_num" />: <epc:print expr="id_num"/></epc:if>
</cite:citation>

Method B: Overriding EPrints::Plugin::Screen::Public::RequestCopy

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!

The screen that processes the request being made (not the response to the request) is EPrints::Plugin::Screen::Public::RequestCopy. 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.

The correct 'EPrints' way to do this for a plugin is outlined here: https://wiki.eprints.org/w/Instructions_for_local_plugins

Understand how the current script works

Take a look at EPrints::Plugin::Screen::Public::RequestCopy and try to understand it (a bit at least).

Work out which of the methods you need to work differently.

Make a local copy of the plugin

mkdir -p [EPRINTS_ROOT]/archives/[ARCHIVE_ID]/cfg/plugins/EPrints/Plugins/Screen/Public/RequestCopy/
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

Edit the local copy of the plugin

The package name and 'isa' need to be updated as this is a subclass of the existing plugin.

Any methods that you don't need to change can also be removed (as they'll be inherited from the main RequestCopy module).

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!

The changes are indicated with ### INSERTED CODE ### comments.

#################################
# Example taken from https://github.com/eprints/eprints/blob/v3.3.16/perl_lib/EPrints/Plugin/Screen/Public/RequestCopy.pm
#################################

package EPrints::Plugin::Screen::Public::RequestCopy::LocalRequestCopy;

@ISA = ( 'EPrints::Plugin::Screen::Public::RequestCopy' );

use strict;

sub action_request
{
	my( $self ) = @_;

	my $session = $self->{session};

	my $request = $self->{processor}->{dataobj};

	my $rc = $self->workflow->update_from_form( $self->{processor} );
	return if !$rc; # validation failed

	my $email = $request->value( "requester_email" );

	my $use_pin_security = $session->config( 'use_request_copy_pin_security' );

	my $eprint = $self->{processor}->{eprint};
	my $doc = $self->{processor}->{document};
	my $contact_email = $self->{processor}->{contact_email};

	my $user = EPrints::DataObj::User::user_with_email( $session, $contact_email );
	if( defined $user )
	{
		$request->set_value( "userid", $user->id );
	}

	$request = $self->{processor}->{dataset}->create_dataobj( $request->get_data );

	my $history_data = {
		datasetid=>"request",
		objectid=>$request->get_id,
		action=>"create",
	};
	
	if( defined $self->{processor}->{user} )
	{
		$history_data->{userid} = $self->{processor}->{user}->get_id;
	}
	else
	{
		$history_data->{actor} = $email;
	}

	# Log request creation event
	my $history_ds = $session->dataset( "history" );
	$history_ds->create_object( $session, $history_data );

	# Send request email
	my $subject = $session->phrase( "request/request_email:subject", eprint => $eprint->get_value( "title" ) );
	my $mail = $session->make_element( "mail" );
	$mail->appendChild( $session->html_phrase(
		"request/request_email:body", 
		eprint => $eprint->render_citation_link_staff,
		document => defined $doc ? $doc->render_value( "main" ) : $session->make_doc_fragment,
		requester => $request->render_citation( "requester" ),
### INSERTED CODE ###
# this checks whether the value is set, and returns either the rendered value, or an empty document fragment
# the pins for a phrase must be XML fragments - not scalar values.
# The corresponding phrase (request/request_email:body) must also be updated to expect the new data.
		contact_num => $request->is_set( "contact_num" ) ? $request->render_value( "contact_num" ) : $session->make_doc_fragment,
		id_num => $request->is_set( "id_num" ) ? $request->render_value( "id_num" ) : $session->make_doc_fragment,
### END INSERTED CODE ###
		reason => $request->is_set( "reason" ) ? $request->render_value( "reason" )
			: $session->html_phrase( "Plugin/Screen/EPrint/RequestRemoval:reason" ) ) );

	my $result;
	if( ( defined $user || $use_pin_security ) && defined $doc )
	{
		# Contact is a registered user or it doesn't matter
		# because we're using the pin security model, and
		# EPrints holds the requested document

		# Send email to contact with accept/reject links

		my $url;
		if ( $use_pin_security )
		{
			# Handle the response via a non-authenticated CGI script
			$url = $session->get_url( host => 1, path => "cgi", "respond_to_doc_request" );
			$url->query_form(
					pin => $request->get_value( 'pin' ),
				);
		}
		else
		{
			# Handle the response via cgi/users/home which is authenticated
			$url = $session->get_url( host => 1, path => "cgi", "users/home" );
			$url->query_form(
					screen => "Request::Respond",
					requestid => $request->id,
				);
		}

		$mail->appendChild( $session->html_phrase( "request/request_email:links",
			accept => $session->render_link( "$url&action=accept" ),
			reject => $session->render_link( "$url&action=reject" ) ) );

		my $to_name;
		if ( defined $user )
		{
			$to_name = EPrints::Utils::tree_to_utf8( $user->render_description );
		}
		else
		{
			$to_name = $contact_email;
		}

		$result = EPrints::Email::send_mail(
			session => $session,
			langid => $session->get_langid,
			to_name => $to_name,
			to_email => $contact_email,
			subject => $subject,
			message => $mail,
			sig => $session->html_phrase( "mail_sig" ),
			cc_list => EPrints::Utils::is_set( $session->config( "request_copy_cc" ) ) ? $session->config( "request_copy_cc" ) : [],
		);
	} 
	else
	{
		# Contact is non-registered user or EPrints holds no documents
		# Send email to contact with 'replyto'
		$result = EPrints::Email::send_mail(
			session => $session,
			langid => $session->get_langid,
			to_name => defined $user ? EPrints::Utils::tree_to_utf8( $user->render_description ) : "",
			to_email => $contact_email,
			subject => $subject,
			message => $mail,
			sig => $session->html_phrase( "mail_sig" ),
			replyto_email => $email,
			cc_list => EPrints::Utils::is_set( $session->config( "request_copy_cc" ) ) ? $session->config( "request_copy_cc" ) : [],
		);
	}

	if( !$result )
	{
		$self->{processor}->add_message( "error", $session->html_phrase( "general:email_failed" ) );
		return;
	}
		
	# Send acknowledgement to requester
	$mail = $session->make_element( "mail" );
	$mail->appendChild( $session->html_phrase(
		"request/ack_email:body", 
		document => defined $doc ? $doc->render_value( "main" ) : $session->make_doc_fragment,
		eprint	=> $eprint->render_citation_link ) );

	$result = EPrints::Email::send_mail(
		session => $session,
		langid => $session->get_langid,
		to_email => $email,
		subject => $session->phrase( "request/ack_email:subject", eprint=>$eprint->get_value( "title" ) ), 
		message => $mail,
		sig => $session->html_phrase( "mail_sig" )
	);

	if( !$result )
	{
		$self->{processor}->add_message( "error", $session->html_phrase( "general:email_failed" ) );
		return;
	}
	
	$self->{processor}->add_message( "message", $session->html_phrase( "request/ack_page", link => $session->render_link( $eprint->get_url ) ) );
	$self->{processor}->{request_sent} = 1;
}

1;

Add phrase

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. In the file [EPRINTS_ROOT]/lib/lang/en/phrases/system.xml locate the phrase request/request_email:body (see: https://github.com/eprints/eprints/blob/v3.3.16/lib/lang/en/phrases/system.xml#L3422-L3431)

Copy this phrase into an XML phrase file e.g. [EPRINTS_ROOT]/archives/[ARCHIVE_ID]/cfg/lang/en/phrases/z_request_fields.xml - used above. Edit the phrase, defining places for the new pins to appear:

<epp:phrase id="request/request_email:body">
  <p>This item has been requested from <epc:phrase ref="archive_name" /> by <epc:pin name="requester"/>.</p>
  <p>Contact number: <epc:pin name="contact_num"/><br />
     ID number: <epc:pin name="id_num"/></p>
  <p>Please can you respond.</p>

  <p><epc:pin name="eprint"/><br/><epc:pin name="document"/></p>
  <p>The following reason was given:</p>
  <epc:pin name="reason"/>

  <p>Please consider removing restrictions or uploading the full text to the archive so that it will be available immediately to future searchers.</p>
</epp:phrase>

Enable plugin (map)

Finally, we have to tell EPrints to use our new plugin in place of the existing one.

Read the details in [EPRINTS_ROOT]/archives/[ARCHIVE_ID]/cfg/cfg.d/plugins.pl.

Once you understand what need to be done, add the plugin enabling code in a suitable configuration file e.g. [EPRINTS_ROOT]/archives/[ARCHIVE_ID]/cfg/cfg.d/z_request_fields.pl.

$c->{plugin_alias_map}->{"Screen::Public::RequestCopy"} = "Screen::Public::RequestCopy::LocalRequestCopy";
$c->{plugin_alias_map}->{"Screen::Public::RequestCopy::LocalRequestCopy"} = undef;

# If this doesn't seem to work, try uncommenting this:
# $c->{plugins}->{"Screen::Public::RequestCopy::LocalRequestCopy"}->{params}->{disable} = 0;

Test everything and restart apache

Using the same procedure as after adding the fields.

If the epadmin test returns no errors, restart Apache, and try requesting something!