Altering the 'Request a copy' function

From EPrints Documentation
Revision as of 09:51, 3 August 2018 by Libjlrs (talk | contribs) (Add details of overriding plugin)
Jump to: navigation, search


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

If you are using a recent version of EPrints, and the file [EPRINTS_ROOT]/lib/citations/request/requester.xml exists, ignore this section and see other bit. 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!

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 ###
		
### 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

Enable plugin (map)

INstruction when request/requestor.xml exists

UNDER CONSTRUCTION! Will follow this process: https://wiki.eprints.org/w/Instructions_for_local_plugins for the Screen::Public::RequestCopy plugin, overriding the 'action_request' method.