iThenticate one account per journal?


I am just looking for confirmation that the iThenticate plugin works per OJS install, not per journal.
We are running OJS

Thank you,

Hi @gabriela,

Currently it’s configured (e.g. credentials) per installation, but it’s enabled/disabled separately on each journal. (There’s a request to give more control to each journal here: multiple journal support · Issue #8 · asmecher/plagiarism · GitHub)

Alec Smecher
Public Knowledge Project Team

Thank you Alec.

Best wishes,

Hi @asmecher, we are having the same problem described in github, and we tried to fix it with the support of crossref and iThenticate. We failed, but now we have an idea for a (we hope) minor change of the plugin that we think could fix the problem.
In iThenticate there is the possibility to share folders, but only the submission folders and not the first.level journal-named folders: if the journal folders were shareable, we could create in iThenticate one user for each journal, share with this user the journal folder and that user could see all (and only) the submission subfolders related to his journal.
I had a look to the file of the plugin, and I think that a change could be made between rows 91 and 100 to make the plugin create a journal-named folder between the “folder group” (you name this way in row 85 the unshareable folder, I suppose) and the submission folders.
This change will result in a iThenticate strcture like this:

  • folder group (journal-named, unshareable, actually created by the plugin)
    – journal folder (journal-named, shareable, actually the plugin doesn’t create it)
    — submission folders (submission+submissionID-named, actually created by the plugin)
    I hope I was clear and that the change I suggest is possible: if you think so and give some advise I can try and test the change myself.
    Best regards
1 Like

Hi, we made some tests and iThenticate does not allow the creation of subfolders.
@asmecher, can you give some hints on the effort needed for giving more control to each journal as requested here, so we can see if we can work on it?
Best regards

Hi @bolelligallevi,

At the moment, the iThenticate credentials are fetched from the OJS configuration file:

My recommendation would be to add a settings form for the plugin, e.g. following the pattern used by plugins like the Google Analytics plugin (settings form class), so that when a journal has a settings form with values entered into it they override the settings. Happy to review pull requests to achieve this!

Alec Smecher
Public Knowledge Project Team


I made changes in this plugin to have one different account for every journal.

you need to add these lines to file “” into callback function:

        $journal = & $request->getJournal();
        $journalId = $journal->getId();
        $user = $this->getSetting($journalId, 'ithenticate_user');
        $pass = $this->getSetting($journalId, 'ithenticate_pass');

Then it looks like this:

 public function callback($hookName, $args) {
        $request = Application::getRequest();
        $context = $request->getContext();
        $submissionDao = Application::getSubmissionDAO();
        $submission = $submissionDao->getById($request->getUserVar('submissionId'));
        $publication = $submission->getCurrentPublication();

        require_once(dirname(__FILE__) . '/vendor/autoload.php');
        $journal = & $request->getJournal();
        $journalId = $journal->getId();
        $user = $this->getSetting($journalId, 'ithenticate_user');
        $pass = $this->getSetting($journalId, 'ithenticate_pass');
        $ithenticate = new \bsobbe\ithenticate\Ithenticate(

And add some new functions there:

     * @copydoc Plugin::getActions()
    function getActions($request, $verb) {
        $router = $request->getRouter();
        return array_merge(
                $this->getEnabled() ? array(
            new LinkAction(
                    new AjaxModal(
                            $router->url($request, null, null, 'manage', null, array('verb' => 'settings', 'plugin' => $this->getName(), 'category' => 'generic')),
                ) : array(),
                parent::getActions($request, $verb)

     * @copydoc Plugin::manage()
    function manage($args, $request) {
        switch ($request->getUserVar('verb')) {
            case 'settings':
                $context = $request->getContext();

                AppLocale::requireComponents(LOCALE_COMPONENT_APP_COMMON, LOCALE_COMPONENT_PKP_MANAGER);
                $templateMgr = TemplateManager::getManager($request);
                $templateMgr->registerPlugin('function', 'plugin_url', array($this, 'smartyPluginUrl'));

                $form = new PlagiarismSettingsForm($this, $context->getId());

                if ($request->getUserVar('save')) {
                    if ($form->validate()) {
                        return new JSONMessage(true);
                } else {
                return new JSONMessage(true, $form->fetch($request));
        return parent::manage($args, $request);

Now you need files for handle plugin settings and setting template file.
So into the plugin folder you need to add file “


class PlagiarismSettingsForm extends Form {

	/** @var int */
	var $_journalId;

	/** @var object */
	var $_plugin;

	 * Constructor
	 * @param $plugin CitedByPlugin
	 * @param $journalId int
	function __construct($plugin, $journalId) {
		$this->_journalId = $journalId;
		$this->_plugin = $plugin;

                $this->addCheck(new FormValidator($this, 'ithenticate_user', 'required', 'plugins.generic.plagiarism.manager.settings.usernameRequired'));
		$this->addCheck(new FormValidator($this, 'ithenticate_pass', 'required', 'plugins.generic.plagiarism.manager.settings.passwordRequired'));

		$this->addCheck(new FormValidatorPost($this));
		$this->addCheck(new FormValidatorCSRF($this));

	 * Initialize form data.
	function initData() {
		$this->_data = array(
                        'ithenticate_user' => $this->_plugin->getSetting($this->_journalId, 'ithenticate_user'),
			'ithenticate_pass' => $this->_plugin->getSetting($this->_journalId, 'ithenticate_pass'),

	 * Assign form data to user-submitted data.
	function readInputData() {

	 * @copydoc Form::fetch()
	function fetch($request, $template = null, $display = false) {
		$templateMgr = TemplateManager::getManager($request);
		$templateMgr->assign('pluginName', $this->_plugin->getName());
		return parent::fetch($request, $template, $display);

	 * @copydoc Form::execute()
	function execute(...$functionArgs) {
                $this->_plugin->updateSetting($this->_journalId, 'ithenticate_user', trim($this->getData('ithenticate_user'), "\"\';"), 'string');
		$this->_plugin->updateSetting($this->_journalId, 'ithenticate_pass', trim($this->getData('ithenticate_pass'), "\"\';"), 'string');

And add template file into subfolder “templates/settingsForm.tpl

	$(function() {ldelim}
		// Attach the form handler.

<form class="pkp_form" id="plagiarismSettingsForm" method="post" action="{url router=$smarty.const.ROUTE_COMPONENT op="manage" category="generic" plugin=$pluginName verb="settings" save=true}">
	{include file="controllers/notification/inPlaceNotification.tpl" notificationId="plagiarismSettingsFormNotification"}

	<div id="description">{translate key="plugins.generic.plagiarism.manager.settings.description"}</div>

	{fbvFormArea id="webFeedSettingsFormArea"}
            {fbvElement type="text" id="ithenticate_user" value=$ithenticate_user label="plugins.generic.plagiarism.manager.settings.username"}
            {fbvElement type="text" id="ithenticate_pass" value=$ithenticate_pass label="plugins.generic.plagiarism.manager.settings.password"}


	<p><span class="formRequired">{translate key="common.requiredField"}</span></p>

This fork for us :slight_smile:
Your welcome,