XML manipulation of the EPrints Workflow using a Bazaar Package

From EPrints Documentation
Revision as of 11:50, 1 December 2010 by DaveTarrant (talk | contribs) (Created page with 'Manipulation of built in EPrint files, such as the Workflows, is currently performed using the postinst method which is run after the rest of package is installed. Likewise whe…')
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

Manipulation of built in EPrint files, such as the Workflows, is currently performed using the postinst method which is run after the rest of package is installed.

Likewise when the package is removed, the prerm method needs to call exactly the opposite set of operations to clean itself up before full removal.

As we go along we'll see that if you don't cleanup behind you, you won't even be able to re-install your same package again as the installer will detect conflicting data already in existence.


To edit EPrints XML we need an epm package containing a spec file which points to a plug-in where we are going to put out postinst and prerm methods.

Below is a simple framework for your plug-in. Remember to name it applicably and match this name with the one in the spec file.

 package EPrints::Plugin::Screen::Admin::MYNAME;
 @ISA = ( 'EPrints::Plugin::Screen' );
 use strict;
 sub new
       my( $class, %params ) = @_;
       my $self = $class->SUPER::new(%params);
       $self->{actions} = [qw/ postinst prerm /];
       return $self;
 # Can this screen be viewed?
 sub can_be_viewed
       my( $self ) = @_;
       return 0;
 # Do we have a prerm method which needs executing?
 sub allow_action_prerm
       my ( $self ) = @_;
       return 1;
 # Do we have a postinst method which needs executing?
 sub allow_action_postinst
       my( $self ) = @_;
       return 1;
 # The postinst routine
 sub action_postinst
       my ( $self ) = @_;
       my $repository = $self->{repository}->get_repository();
       # Everthing went OK (why the hell did I code this the wrong way round?)
       return (0,undef);
       # Something went wrong
       # return (1,"MUPPET!!!")
 # The prerm routine
 sub action_prerm
       my ( $self ) = @_;
       my $repository = $self->{repository}->get_repository();
       return (0,undef);
 # A render method for the screen, which we don't need unless we allow this screen to be viewed.
 # If this screen is visible you return an html fragment, or redirect somewhere else, like a config file :)
 sub render 
       my ( $self ) = @_;
       return undef;

Workflow Editing

In this exercise we are going to do some simple workflow editing exercises. These follow the standard EPrints training materials which teach you how to manually edit the workflow. Here we are going to do all the same stuff with API calls.

Adding a Divisions Stage to the Workflow

Basically we are simply editing XML so all we need to do is tell the repository which file to manipulate and then give it the stuff add to this file.

So to the postinst routine we need to add the following lines. Note that you need to manually specify your package_name

 my $filename = $repository->config( "config_path" )."/workflows/eprint/default.xml";
 # Gap for the stuff to be defined we need to add
 my $rc = 0;
 foreach my $child ( $node->getChildNodes() ) {
        $rc = EPrints::XML::add_to_xml( $filename,$child,"package_name" );

At the same time then it is worth adding the equivalent remove lines to the prerm method. Again you need to specify your package name.

 my $filename = $repository->config( "config_path" )."/workflows/eprint/default.xml";
 EPrints::XML::remove_package_from_xml( $filename, "workflow_exercise" );

Note that the remove call does not return a state as it will be able to remove anything, but it won't error if there is nothing to remove. Thus all return states are OK (this may change if someone can think of an exception)

Lastly we need to actually tell the postinst method the block of XML to add.

 my $string = '
               <stage ref="divisions"/>
       <stage name="divisions">
               <component type="Field::Subject">
                       <field ref="divisions" required="yes" />
 my $xml = EPrints::XML::parse_string( undef, $string );
 $xml = EPrints::XML::_remove_blank_nodes($xml);
 my $node = $xml->getFirstChild();

Here you can see that we can simply specify the XML as a string, then parse it. After it is parsed we then remove all the blank nodes to just leave the XML. All pretty printing is done by the API, not by you.

The XML represents the exact same tree as in the workflow XML file we are attempting to edit. You can view this by clicking the "View Configuration" button on the "Config. Tools" tab of the admin screen. Once here you will need to scroll down to find the file you specified (in this case /workflows/eprint/default.xml). Since it represents the same tree, only nodes which don't exist are added and marked as belonging to your package. This marker is how they are removed.

Alternatively you can build an XML tree using the EPrints::XML methods like make_element("flow") etc. At this point (unless you added blank nodes) you won't need the remove line, but it doesn't hurt to leave it in there.

Finally make sure you have all your variables like $rc (return code) defined and then this screen should be ready.

Divisions Phrases

For the divisions screen to work fully you will need to define a number of phrases.

As usual you need a new file, basically take a copy of cfg/lang/en/phrases/zz_webcfg in cfg/lang/en/phrases/package_name.

The clear all the defined phrases from this file and add the follow 2:

 <epp:phrase id="metapage_title_divisions">Divisions</epp:phrase>

<epp:phrase id="Plugin/InputForm/Component/Field/Subject:divisions_search_bar">


Package and Test

Finally, package all these files up and test in from the Bazaar.

You can test this package by click the "manage deposits" link in the admin toolbar and adding a new item. You should see a divisions tab.

Remember how to force remove a broken package

 perl bin/epm archive_name remove package_name --force

Exercise 2

Change this package to add a conditional element somewhere, for example:

 <epc:if test="type = 'book'">
    <field ref="pres_type"/>

Experiment with this and use the "view configuration" to see what your changes do to the workflow file each time.

Exercise 3

Here we are going to define a whole new type "epm" and a different set of stages for it.