OJS OCS OMP OHS

You are viewing the PKP Support Forum | PKP Home Wiki



Starting a new plugin

OJS development discussion, enhancement requests, third-party patches and plug-ins.

Moderators: jmacgreg, btbell, michael, bdgregg, barbarah, asmecher

Forum rules
Developer Resources:

Documentation: The OJS Technical Reference and the OJS API Reference are both available from the OJS Documentation page.

Git: You can access our public Git Repository here. Comprehensive Git usage instructions are available on the wiki.

Bugzilla: You can access our Bugzilla report tracker here.

Search: You can use our Google Custom Search to search across our main website, the support forum, and Bugzilla.

Questions and discussion are welcome, but if you have a workflow or usability question you should probably post to the OJS Editorial Support and Discussion subforum; if you have a technical support question, try the OJS Technical Support subforum.

Starting a new plugin

Postby MMeijer » Wed Apr 06, 2011 4:04 am

Hi there!
I'm trying to make a new OJS generic plugin. I've installed OJS2.3.4 locally on my pc for testing.
Of course, I can copy from a wealth of existing plugins.
But for a start, I just tried to hook to Template::Manager::Index::ManagementPages (cf. the sample plugin in the technical ref. manual).
I've tried all kinds of small variations in code, but whatever I do, OJS seems to ignore my extension to the ManagementPages item list.

Below the code for EJMEPlugin.inc.php. The plugin is recognized by OJS, as it can be enabled/disabled from the
[... > Plugin Management > Generic Plugins] page. I cleared all caches, tried the "::Users" and "::Roles" hooks as well. Nothing helps! It drives me mad..

Code: Select all
<?php
import('lib.pkp.classes.plugins.GenericPlugin');
class EJMEPlugin extends GenericPlugin {
  function register($category, $path) {
    $success = parent::register($category, $path);
    if ($success && $this->getEnabled()) {
      HookRegistry::register('Templates::Manager::Index::ManagementPages', array($this, 'callback'));
    }
    return $success;
  }
  function getDisplayName() { return 'EJME'; }
  function getDescription() { return 'EJME plugin'; }
  function callback ($hookName, $params) {
    $smarty =& $params[1];
    $output =& $params[2];
    $output .= '<li>'.$hookName.'</li>';
    return false;
  }
}

Any suggestions? Please help!
MMeijer
 
Posts: 35
Joined: Fri Nov 10, 2006 3:25 am
Location: Utrecht

Re: Starting a new plugin

Postby MMeijer » Thu Apr 07, 2011 1:26 am

One more observation:
I noticed that my "EJME Plugin" even when enabled, is placed in the sorting of the generic plugins list, as if it was disabled.

And, btw, this is the version.xml file:
Code: Select all
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE version SYSTEM "../../../lib/pkp/dtd/pluginVersion.dtd">
<version>
   <application>EJME</application>
   <type>plugins.generic</type>
   <release>1.0.0.0</release>
   <date>2011-04-06</date>
   <lazy-load>1</lazy-load>
   <class>EJMEPlugin</class>
</version>
MMeijer
 
Posts: 35
Joined: Fri Nov 10, 2006 3:25 am
Location: Utrecht

Re: Starting a new plugin

Postby MMeijer » Thu Apr 07, 2011 8:55 am

For more than a day messing around with code, browsing through documentation and forum, comparing plugins in various OJS-releases, almost on the edge of insanity - I finally added management verbs to my plugin, namely the functions getManagementVerbs() and manage(), and suddenly my plugin comes to life!
I followed the example of the Sword plugin, defining actions for 'enable' and 'disable', which execute some function $this->updateSetting(...).
Apparently, the default actions for 'enable' and 'disable' don't, I guess.
Well, on to the next problem! The OJS-plugin developer is pretty much left to his own explorations :(
MMeijer
 
Posts: 35
Joined: Fri Nov 10, 2006 3:25 am
Location: Utrecht

Re: Starting a new plugin

Postby mary » Fri Apr 08, 2011 12:16 am

Could you post the working code of your example plugin? I am in more or less the same place right now, trying to get the example plugin to work and not finding the callback ever being called.
mary
 
Posts: 8
Joined: Fri Oct 26, 2007 12:17 am

Re: Starting a new plugin

Postby MMeijer » Fri Apr 08, 2011 3:24 am

Hello Mary,
I added the functions below to my NamePlugin.inc.php (in my case 'EjmePlugin.inc.php').
They override existing class methods. I'm not completely sure that this is the solution to our problems, because I messed around with some database tables as well. E.g. I made entries for my 'ejme'-plugin in the tables 'plugin_settings' and 'versions'. At first sight without desired results, but I'm not entirely sure of that. Anyway, if adding these methods would solve your problem too, we'd have more confirmation.
(B.t.w. you might notice I changed the plugin's name from EJME to Ejme)
gr. Maarten.

UPDATE: it is essential to have a record for the plugin in table 'versions'. It should probably be done by some install procedure, but for now I made it manually.
An entry into table 'plugin_settings' is taken care of by the manage() method, below.

Code: Select all
  function getManagementVerbs() {
    $verbs = array();
    if ($this->getEnabled()) {
      $verbs[] = array(
        'disable',
        Locale::translate('manager.plugins.disable')
      );
      $verbs[] = array(
        'settings',
        Locale::translate('plugins.generic.ejme.settings')
      );
    } else {
      $verbs[] = array(
        'enable',
        Locale::translate('manager.plugins.enable')
      );
    }
    return $verbs;
  }

  function manage($verb, $args, &$message) {
    $returner = true;
    $journal =& Request::getJournal();
    $this->addLocaleData();

    switch ($verb) {
      case 'settings':
        break;
      case 'enable':
        $this->updateSetting($journal->getId(), 'enabled', true);
        $message = Locale::translate('plugins.generic.ejme.enabled');
        $returner = false;
        break;
      case 'disable':
        $this->updateSetting($journal->getId(), 'enabled', false);
        $message = Locale::translate('plugins.generic.ejme.disabled');
        $returner = false;
        break;
    }
    return $returner;
  }

MMeijer
 
Posts: 35
Joined: Fri Nov 10, 2006 3:25 am
Location: Utrecht

Re: Starting a new plugin

Postby barbarah » Tue Apr 19, 2011 11:10 am

I am writing a plugin (ours is a doc to pdf converter, which I'm planning on posting to the new plugins page when done). I'm also unable to get the example plugin to actually work. I copied and pasted the example code straight from the OJS Technical Reference doc as suggested: http://pkp.sfu.ca/ojs/docs/technicalref ... lugin.html

The plugin is listed on the "System Plugins" page in the OJS interface, and I can click to enable/disable it. However, the call to HookRegistry::register doesn't actually seem to "stick", i.e. when the hook calls the Registry::call method, it finds that the examplePlugin is not registered to this hook in the registry, so doesn't run the plugin callback method. In other words, the plugin doesn't ever actually do what it's supposed to do!

Maarten, thanks for posting the question and your code. I'm not sure what exactly the solution is though, since the code that you added to your plugin is basically already in GenericPlugin.inc.php (which ExamplePlugin extends). Also, I've noticed that some plugins are successfully registered even without having an entry in the 'versions' table. It seems to me that there needs to be a cleaner way to do this.

Can somebody (a PKP developer?) please post a working copy of an example plugin here?? I will post whatever I can figure out, but some clear guidelines as to how this works would be much appreciated! Thanks!
barbarah
 
Posts: 27
Joined: Thu Mar 24, 2011 1:25 pm
Location: California Digital Library, Oakland, California

Adding some context and extra questions

Postby mvluijt » Tue Apr 19, 2011 11:52 am

As per request from PKP's Alec and on behalf of Maarten I'm adding some context and a couple of extra questions to help the PKP developers figure out how to tackle these issues:

Supplemental file blues
In the author's article submission process, a supplemental file can be provided without actually uploading a file. Only the title, in the subsequent Supplementary File Metadata form (submission step 4a), is mandatory.

When no file is uploaded, in the submission's Summary screen, this results into an unreachable metadata edit-form, because the filename of the supplementary file is used as a link to this form. Of course, the filename could be replaced by the (mandatory) title, if this were the only problem.
During the submission process it's still possible to delete a supplemental file (and its metadata record). After submission, the delete option is no longer available. I can't see why. Will editors never have any reason to remove something?

The author's version of the Suppl. File Metadata form allows the author to replace an uploaded supplementary file with a new version, or to upload a file if none is uploaded yet. The 'Smarty'-template evaluates a boolean $suppFile for that purpose, but that variable is not correctly set, because the form always says "Replace". If no file was previously uploaded, then no file ever will! Apparently, the system insists on replacing a previous version.

It seems the developers had in mind that the uploadfile would be obligatory, if the author doesn't skip submission step 4.

But nevertheless, the user interface of the supplemental files lacks consistency. It might be more intimidating, but the author should be presented with the complete supplementary file metadata form, with the optional possibility of uploading a file, when entering submission step 4.

This form is, by the way, very much the same form the (section) editor uses to edit or add a supplemental file record, although different template files are involved. (Again, why?)

Extending the supplementary file metadata form
To add the functionality that EJME desired, we want to create a plugin that extends the functionality of the supplementary file and metadata in a way that allows author and editors to

1. upload datasets to an article, that in turn (possibly following a review process) could be uploaded to an external repository (using the SWORD protocol) returning a URI, and then deleting the supplementary file (i.e. OJS would now use the external URI to point to the file, the internal object wouldn’t be used anymore)

2. enter a URI pointing to a data source in an external repository (instead of uploading a file or filling out the metadata directly). By means of the URI the metadata could then be retrieved from the external repository.

Unfortunately, we discovered that the 'supplementary files' section of OJS does not provide any 'hooks' in templates or classes. One reason being that dedicated form classes are used, instead of the standard form classes where hooks are automatically provided.

This leaves us with the option of making patches to the original program instead of delivering a cleanly programmed, installable plugin.
mvluijt
 
Posts: 9
Joined: Fri Oct 19, 2007 5:29 am

Re: Starting a new plugin

Postby barbarah » Tue Apr 19, 2011 12:07 pm

Going back to the earlier conversation:

MMeijer wrote:UPDATE: it is essential to have a record for the plugin in table 'versions'. It should probably be done by some install procedure, but for now I made it manually.


I also added the entry for my plugin manually, and this does the trick. Maarten et al, did you ever figure out the proper way to do this via the OJS plugin infrastructure? Is there one?!
barbarah
 
Posts: 27
Joined: Thu Mar 24, 2011 1:25 pm
Location: California Digital Library, Oakland, California

Re: Starting a new plugin

Postby MMeijer » Wed Apr 20, 2011 1:15 am

barbarah wrote:Going back to the earlier conversation:

Let's stick to the topic, indeed.
barbarah wrote:I also added the entry for my plugin manually, and this does the trick. Maarten et al, did you ever figure out the proper way to do this via the OJS plugin infrastructure? Is there one?!

No more progression here. We have to await the official answers.
Last edited by MMeijer on Wed Apr 20, 2011 3:17 am, edited 1 time in total.
MMeijer
 
Posts: 35
Joined: Fri Nov 10, 2006 3:25 am
Location: Utrecht

Re: Starting a new plugin

Postby jmacgreg » Thu Apr 21, 2011 9:47 am

Hi folks,

Apologies for the delay. Regarding how to add plugin version information to the database: this information should be added to a "version.xml" file, which is stored in the plugin directory. An example version.xml file (taken from the sehl plugin):

Code: Select all
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE version SYSTEM "../../../lib/pkp/dtd/pluginVersion.dtd">

<!--
  * version.xml
  *
  * Copyright (c) 2003-2011 John Willinsky
  * Distributed under the GNU GPL v2. For full terms see the file docs/COPYING.
  *
  * Plugin version information.
  -->
<version>
        <application>sehl</application>
        <type>plugins.generic</type>
        <release>1.0.0.0</release>
        <date>2009-07-13</date>
        <lazy-load>1</lazy-load>
        <class>SehlPlugin</class>
</version>


This information can then be added to the database in a few ways. When you install a new plugin via the web, by uploading a tar.gz file from Journal Management -> System Plugins -> Install New Plugin, the version.xml file is parsed and the information it contains is added to the database. Similarly, if you need to update the plugin or your db for any reason, you can choose to "upgrade" your plugin, and upload a new tar file.

Alternatively, I believe you can also upload the plugin to the right directory via ftp, and then run OJS' upgrade script; the script finds and adds any new plugins' version.xml file information.

Of course, adding this information to the db manually is also ok.

Maarten, mvluijt, I'll get to your other questions very shortly. I'll also update the block plugin documentation to include information on the version.xml necessity as well. Thanks all, for your comments!

Cheers,
James
jmacgreg
 
Posts: 4162
Joined: Tue Feb 14, 2006 10:50 am

Re: Starting a new plugin

Postby barbarah » Thu Apr 21, 2011 1:27 pm

James, thanks for your explanation of the database update process. I will try that out and post here if any problems. It would be great if the "Plugins" section in the OJS Technical Reference doc could be updated with that crucial piece of info!

I have a question that is somewhat related to Maarten and mvluijt's, so I thought I'd post it here. Feel free to move it to its own thread if that seems better though :)

We want to create a plugin that will essentially be a button that, when clicked, converts a given file into PDF format. This new PDF file will then replace the old file as far as OJS is concerned. The old file will still exist in the system, but be marked as the 'pre pdf conversion' version of the file. The user will be still be able to access this pre-conversion file (potentially via another plugin?).

Note: We have the DOC to PDF conversion process figured out and working smoothly (using LiveDocx). At this point, it's purely the file handling part that we have questions about.

The question is: how would you recommend coding the file upload and replacement as far the backend system is concerned? I'm having a really hard time figuring out from the codebase what the clean way to do this is. There doesn't seem to be a model for uploading files to the filesystem and adding them to the database. This appears to be done differently in each case for the different kinds of article files (author submission, copyeditor and reviewer uploads, etc). Can you point me towards a model for doing this so that I'm sure to cover all of the necessary dependencies, etc?

Thanks!
barbarah
 
Posts: 27
Joined: Thu Mar 24, 2011 1:25 pm
Location: California Digital Library, Oakland, California

Re: Starting a new plugin

Postby jmacgreg » Fri Apr 22, 2011 5:25 pm

Hi all,

Maarten:

-- regarding the issue where Supplementary Files can be submitted without being uploaded, I have posted a bug report here: http://pkp.sfu.ca/bugzilla/show_bug.cgi?id=6612.

-- regarding deleting supplementary files: see viewtopic.php?f=8&t=772, but also http://pkp.sfu.ca/bugzilla/show_bug.cgi?id=6613.

I believe those two bug reports should address the problems you've found entirely, but if you think that is not the case please let us know. Thanks for catching them!

Your further questions regarding adding plugin functionality to the supplementary files pages is beyond my knowledge, so I'll be passing this thread on to a developer who will get back to you shortly.

Cheers,
James
jmacgreg
 
Posts: 4162
Joined: Tue Feb 14, 2006 10:50 am

Re: Starting a new plugin

Postby jmacgreg » Fri Apr 22, 2011 5:39 pm

Hi Barbara,

You may want to take a look at the XML Galley plugin (that's found in plugins/generic/xmlGalley). It includes a convert option that will convert an XML file to an HTML/PDF file and store that on the server. It doesn't include a delete option, and the conversion isn't triggered by a button (rather, it's triggered by a visitor viewing the galley for the first time), but it should give you some pointers. ojs/classes/article/ArticleGalleyDAO.inc.php also includes a number of galley update and delete functions. Take a look, and if you have any questions, please let us know -- at this point, a new thread would probably be helpful. :D

Cheers,
James
jmacgreg
 
Posts: 4162
Joined: Tue Feb 14, 2006 10:50 am

Re: Starting a new plugin

Postby barbarah » Mon Apr 25, 2011 12:00 pm

Thanks James. I've managed to get our PDF converter plugin working. It isn't triggered by its own button (yet), but it does successfully take a given articleFile object and update it with a PDF version of itself. For example, on our test site we have the plugin registered to the SectionEditorAction::completeFinalCopyedit hook so that when the user clicks "complete" in the the third step of the article copyedit process, the article in question is converted to a PDF. I'm planning on adding a bit more functionality (deploy as button, allow users to choose where to plug it in, etc) before sharing the plugin with the community.

I did take a look at the XML Galley Plugin a couple of weeks ago when I was starting development, but to be honest I found it pretty confusing. But maybe that's because I was getting tripped up by the plugin registry problem (the fact that the plugin needs an entry in the registry table), so couldn't make heads or tails of what part of the code was doing what.
barbarah
 
Posts: 27
Joined: Thu Mar 24, 2011 1:25 pm
Location: California Digital Library, Oakland, California

Re: Starting a new plugin

Postby jmacgreg » Wed Apr 27, 2011 11:40 am

Hi Barbara,

Good to hear that you've got it working! Again, if you need any pointers, just let us know. We'd definitely be interested in seeing the plugin when you're done, as would our community.

Cheers,
James
jmacgreg
 
Posts: 4162
Joined: Tue Feb 14, 2006 10:50 am

Next

Return to OJS Development

Who is online

Users browsing this forum: No registered users and 2 guests