first commit
This commit is contained in:
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file tools/bootstrap.php
|
||||
*
|
||||
* Copyright (c) 2014-2021 Simon Fraser University
|
||||
* Copyright (c) 2003-2021 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @ingroup tools
|
||||
*
|
||||
* @brief application-specific configuration common to all tools (corresponds
|
||||
* to index.php for web requests).
|
||||
*/
|
||||
|
||||
define('INDEX_FILE_LOCATION', dirname(__FILE__, 2) . '/index.php');
|
||||
require dirname(__FILE__, 2) . '/lib/pkp/classes/cliTool/CommandLineTool.php';
|
||||
@@ -0,0 +1,144 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file tools/cleanReviewerInterests.php
|
||||
*
|
||||
* Copyright (c) 2014-2021 Simon Fraser University
|
||||
* Copyright (c) 2003-2021 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class ReviewerInterestsDeletionTool
|
||||
*
|
||||
* @ingroup tools
|
||||
*
|
||||
* @brief CLI tool to remove user interests that are not referenced by any user accounts.
|
||||
*/
|
||||
|
||||
require(dirname(__FILE__) . '/bootstrap.php');
|
||||
|
||||
use PKP\cliTool\CommandLineTool;
|
||||
use PKP\controlledVocab\ControlledVocabDAO;
|
||||
use PKP\controlledVocab\ControlledVocabEntryDAO;
|
||||
use PKP\db\DAORegistry;
|
||||
use PKP\user\InterestDAO;
|
||||
|
||||
class ReviewerInterestsDeletionTool extends CommandLineTool
|
||||
{
|
||||
public array $parameters;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param array $argv command-line arguments
|
||||
*/
|
||||
public function __construct($argv = [])
|
||||
{
|
||||
parent::__construct($argv);
|
||||
|
||||
if (!sizeof($this->argv)) {
|
||||
$this->usage();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
$this->parameters = $this->argv;
|
||||
}
|
||||
|
||||
/**
|
||||
* Print command usage information.
|
||||
*/
|
||||
public function usage()
|
||||
{
|
||||
echo "Permanently removes user interests that are not referenced by any user accounts. USE WITH CARE.\n"
|
||||
. "Usage:\n"
|
||||
. "\t{$this->scriptName} --show : Display user interests not referenced\n"
|
||||
. "\t{$this->scriptName} --remove : Permanently delete user interests not referenced\n";
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove user interests that are not referenced by any user account
|
||||
*/
|
||||
public function execute()
|
||||
{
|
||||
$orphans = $this->_getOrphanVocabInterests();
|
||||
if (!count($orphans)) {
|
||||
echo "No user interests to remove.\n";
|
||||
exit(0);
|
||||
}
|
||||
|
||||
$command = $this->parameters[0];
|
||||
switch ($command) {
|
||||
case '--show':
|
||||
$interests = array_map(function ($entry) {
|
||||
return $entry->getData(InterestDAO::CONTROLLED_VOCAB_INTEREST);
|
||||
}, $orphans);
|
||||
echo "Below are the user interests that are not referenced by any user account.\n";
|
||||
echo "\t" . join("\n\t", $interests) . "\n";
|
||||
break;
|
||||
|
||||
case '--remove':
|
||||
/** @var ControlledVocabEntryDAO */
|
||||
$vocabEntryDao = DAORegistry::getDAO('ControlledVocabEntryDAO');
|
||||
foreach ($orphans as $orphanVocab) {
|
||||
$vocabEntryDao->deleteObject($orphanVocab);
|
||||
}
|
||||
echo count($orphans) . " entries deleted\n";
|
||||
break;
|
||||
|
||||
default:
|
||||
echo "Invalid command.\n";
|
||||
$this->usage();
|
||||
exit(2);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns user interests that are not referenced
|
||||
*
|
||||
* @return array array of ControlledVocabEntry object
|
||||
*/
|
||||
protected function _getOrphanVocabInterests()
|
||||
{
|
||||
/** @var InterestDAO */
|
||||
$interestDao = DAORegistry::getDAO('InterestDAO');
|
||||
/** @var ControlledVocabDAO */
|
||||
$vocabDao = DAORegistry::getDAO('ControlledVocabDAO');
|
||||
/** @var ControlledVocabEntryDAO */
|
||||
$vocabEntryDao = DAORegistry::getDAO('ControlledVocabEntryDAO');
|
||||
|
||||
$interestVocab = $vocabDao->getBySymbolic(InterestDAO::CONTROLLED_VOCAB_INTEREST);
|
||||
$vocabEntryIterator = $vocabEntryDao->getByControlledVocabId($interestVocab->getId());
|
||||
$vocabEntryList = $vocabEntryIterator->toArray();
|
||||
|
||||
// list of vocab interests in db
|
||||
$allInterestVocabIds = array_map(
|
||||
function ($entry) {
|
||||
return $entry->getId();
|
||||
},
|
||||
$vocabEntryList
|
||||
);
|
||||
|
||||
// list of vocabs associated to users
|
||||
$interests = $interestDao->getAllInterests();
|
||||
$userInterestVocabIds = array_map(
|
||||
function ($interest) {
|
||||
return $interest->getId();
|
||||
},
|
||||
$interests->toArray()
|
||||
);
|
||||
|
||||
// get the difference
|
||||
$diff = array_diff($allInterestVocabIds, $userInterestVocabIds);
|
||||
|
||||
$orphans = array_filter(
|
||||
$vocabEntryList,
|
||||
function ($entry) use ($diff) {
|
||||
return in_array($entry->getId(), $diff);
|
||||
}
|
||||
);
|
||||
|
||||
return $orphans;
|
||||
}
|
||||
}
|
||||
|
||||
$tool = new ReviewerInterestsDeletionTool($argv ?? []);
|
||||
$tool->execute();
|
||||
@@ -0,0 +1,69 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file tools/deleteSubmissions.php
|
||||
*
|
||||
* Copyright (c) 2014-2021 Simon Fraser University
|
||||
* Copyright (c) 2003-2021 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class SubmissionDeletionTool
|
||||
*
|
||||
* @ingroup tools
|
||||
*
|
||||
* @brief CLI tool to delete submissions
|
||||
*/
|
||||
|
||||
use APP\facades\Repo;
|
||||
use PKP\cliTool\CommandLineTool;
|
||||
|
||||
require(dirname(__FILE__) . '/bootstrap.php');
|
||||
|
||||
class SubmissionDeletionTool extends CommandLineTool
|
||||
{
|
||||
public array $parameters;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param array $argv command-line arguments
|
||||
*/
|
||||
public function __construct($argv = [])
|
||||
{
|
||||
parent::__construct($argv);
|
||||
|
||||
if (!sizeof($this->argv)) {
|
||||
$this->usage();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
$this->parameters = $this->argv;
|
||||
}
|
||||
|
||||
/**
|
||||
* Print command usage information.
|
||||
*/
|
||||
public function usage()
|
||||
{
|
||||
echo "Permanently removes submission(s) and associated information. USE WITH CARE.\n"
|
||||
. "Usage: {$this->scriptName} submission_id [...]\n";
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete submission data and associated files
|
||||
*/
|
||||
public function execute()
|
||||
{
|
||||
foreach ($this->parameters as $articleId) {
|
||||
$article = Repo::submission()->get($articleId);
|
||||
if (!isset($article)) {
|
||||
printf("Error: Skipping {$articleId}. Unknown submission.\n");
|
||||
continue;
|
||||
}
|
||||
Repo::submission()->delete($article);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$tool = new SubmissionDeletionTool($argv ?? []);
|
||||
$tool->execute();
|
||||
@@ -0,0 +1,83 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file tools/importExport.php
|
||||
*
|
||||
* Copyright (c) 2014-2021 Simon Fraser University
|
||||
* Copyright (c) 2003-2021 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class importExport
|
||||
*
|
||||
* @ingroup tools
|
||||
*
|
||||
* @brief CLI tool to perform import/export tasks
|
||||
*/
|
||||
|
||||
require(dirname(__FILE__) . '/bootstrap.php');
|
||||
|
||||
use PKP\cliTool\CommandLineTool;
|
||||
use PKP\plugins\ImportExportPlugin;
|
||||
use PKP\plugins\PluginRegistry;
|
||||
|
||||
class importExport extends CommandLineTool
|
||||
{
|
||||
public $command;
|
||||
/** @var ImportExportPlugin */
|
||||
public $plugin;
|
||||
public $parameters;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param array $argv command-line arguments (see usage)
|
||||
*/
|
||||
public function __construct($argv = [])
|
||||
{
|
||||
parent::__construct($argv);
|
||||
$this->command = array_shift($this->argv);
|
||||
$this->parameters = $this->argv;
|
||||
}
|
||||
|
||||
/**
|
||||
* Print command usage information.
|
||||
*/
|
||||
public function usage()
|
||||
{
|
||||
echo "Command-line tool for import/export tasks\n"
|
||||
. "Usage:\n"
|
||||
. "\t{$this->scriptName} list: List available plugins\n"
|
||||
. "\t{$this->scriptName} [pluginName] usage: Display usage information for a plugin\n"
|
||||
. "\t{$this->scriptName} [pluginName] [params...]: Invoke a plugin\n";
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse and execute the import/export task.
|
||||
*/
|
||||
public function execute()
|
||||
{
|
||||
$plugins = PluginRegistry::loadCategory('importexport');
|
||||
if ($this->command === 'list') {
|
||||
echo "Available plugins:\n";
|
||||
if (empty($plugins)) {
|
||||
echo "\t(None)\n";
|
||||
} else {
|
||||
foreach ($plugins as $plugin) {
|
||||
if ($plugin->supportsCLI()) {
|
||||
echo "\t" . $plugin->getName() . "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
/** @var ImportExportPlugin $plugin */
|
||||
if ($this->command == 'usage' || $this->command == 'help' || $this->command == '' || ($plugin = PluginRegistry::getPlugin('importexport', $this->command)) === null || !$plugin->supportsCLI()) {
|
||||
$this->usage();
|
||||
return;
|
||||
}
|
||||
return $plugin->executeCLI($this->scriptName, $this->parameters);
|
||||
}
|
||||
}
|
||||
|
||||
$tool = new importExport($argv ?? []);
|
||||
$tool->execute();
|
||||
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file tools/install.php
|
||||
*
|
||||
* Copyright (c) 2014-2021 Simon Fraser University
|
||||
* Copyright (c) 2003-2021 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class OJSInstallTool
|
||||
*
|
||||
* @ingroup tools
|
||||
*
|
||||
* @brief CLI tool for installing OJS.
|
||||
*/
|
||||
|
||||
require(dirname(__FILE__) . '/bootstrap.php');
|
||||
|
||||
class OJSInstallTool extends \PKP\cliTool\InstallTool
|
||||
{
|
||||
/**
|
||||
* Read installation parameters from stdin.
|
||||
* FIXME: May want to implement an abstract "CLIForm" class handling input/validation.
|
||||
* FIXME: Use readline if available?
|
||||
*/
|
||||
public function readParams()
|
||||
{
|
||||
printf("%s\n", __('installer.appInstallation'));
|
||||
|
||||
parent::readParams();
|
||||
|
||||
$this->readParamBoolean('install', 'installer.installApplication');
|
||||
|
||||
return $this->params['install'];
|
||||
}
|
||||
}
|
||||
|
||||
$tool = new OJSInstallTool($argv ?? []);
|
||||
$tool->execute();
|
||||
@@ -0,0 +1,7 @@
|
||||
./lib/pkp/lib
|
||||
./plugins/paymethod/paypal/vendor
|
||||
./plugins/generic/citationStyleLanguage/lib
|
||||
./plugins/generic/plagiarism/vendor
|
||||
./node_modules
|
||||
./lib/ui-library/node_modules
|
||||
./lib/pkp/js/lib
|
||||
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file tools/mergeUsers.php
|
||||
*
|
||||
* Copyright (c) 2014-2021 Simon Fraser University
|
||||
* Copyright (c) 2003-2021 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class mergeUsers
|
||||
*
|
||||
* @ingroup tools
|
||||
*
|
||||
* @brief CLI tool for merging two user accounts.
|
||||
*/
|
||||
|
||||
require(dirname(__FILE__) . '/bootstrap.php');
|
||||
|
||||
$tool = new \PKP\cliTool\MergeUsersTool($argv ?? []);
|
||||
$tool->execute();
|
||||
@@ -0,0 +1,89 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file tools/rebuildSearchIndex.php
|
||||
*
|
||||
* Copyright (c) 2014-2021 Simon Fraser University
|
||||
* Copyright (c) 2003-2021 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class rebuildSearchIndex
|
||||
*
|
||||
* @ingroup tools
|
||||
*
|
||||
* @brief CLI tool to rebuild the article keyword search database.
|
||||
*/
|
||||
|
||||
require dirname(__FILE__) . '/bootstrap.php';
|
||||
|
||||
use APP\core\Application;
|
||||
use APP\journal\JournalDAO;
|
||||
use PKP\cliTool\CommandLineTool;
|
||||
use PKP\config\Config;
|
||||
use PKP\db\DAORegistry;
|
||||
use PKP\plugins\Hook;
|
||||
|
||||
class rebuildSearchIndex extends CommandLineTool
|
||||
{
|
||||
/**
|
||||
* Print command usage information.
|
||||
*/
|
||||
public function usage(): void
|
||||
{
|
||||
echo "Script to rebuild article search index\n"
|
||||
. "Usage: {$this->scriptName} [options] [journal_path]\n\n"
|
||||
. "options: The standard index implementation does\n"
|
||||
. " not support any options. For other\n"
|
||||
. " implementations please see the corresponding\n"
|
||||
. " plugin documentation (e.g. 'plugins/generic/\n"
|
||||
. " lucene/README').\n";
|
||||
}
|
||||
|
||||
/**
|
||||
* Rebuild the search index for all articles in all journals.
|
||||
*/
|
||||
public function execute(): void
|
||||
{
|
||||
// Check whether we have (optional) switches.
|
||||
$switches = [];
|
||||
while (count($this->argv) && substr($this->argv[0], 0, 1) === '-') {
|
||||
$switches[] = array_shift($this->argv);
|
||||
}
|
||||
|
||||
// If we have another argument that this must be a journal path.
|
||||
$journal = null;
|
||||
if (count($this->argv)) {
|
||||
$journalPath = array_shift($this->argv);
|
||||
/** @var JournalDAO */
|
||||
$journalDao = DAORegistry::getDAO('JournalDAO');
|
||||
$journal = $journalDao->getByPath($journalPath);
|
||||
if (!$journal) {
|
||||
exit(__('search.cli.rebuildIndex.unknownJournal', ['journalPath' => $journalPath]) . "\n");
|
||||
}
|
||||
}
|
||||
|
||||
// Register a router hook so that we can construct
|
||||
// useful URLs to journal content.
|
||||
Hook::add('Request::getBaseUrl', [$this, 'callbackBaseUrl']);
|
||||
|
||||
// Let the search implementation re-build the index.
|
||||
$articleSearchIndex = Application::getSubmissionSearchIndex();
|
||||
$articleSearchIndex->rebuildIndex(true, $journal, $switches);
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback to patch the base URL which will be required
|
||||
* when constructing galley/supp file download URLs.
|
||||
*
|
||||
* @see \APP\core\Request::getBaseUrl()
|
||||
*/
|
||||
public function callbackBaseUrl(string $hookName, array $params): bool
|
||||
{
|
||||
$baseUrl = & $params[0];
|
||||
$baseUrl = Config::getVar('general', 'base_url');
|
||||
return Hook::ABORT;
|
||||
}
|
||||
}
|
||||
|
||||
$tool = new rebuildSearchIndex($argv ?? []);
|
||||
$tool->execute();
|
||||
@@ -0,0 +1,114 @@
|
||||
#!/bin/bash
|
||||
|
||||
#
|
||||
# tools/release.sh
|
||||
#
|
||||
# Copyright (c) 2014-2021 Simon Fraser University
|
||||
# Copyright (c) 2003-2021 John Willinsky
|
||||
# Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
#
|
||||
# Script to create an automated (incremental) release of OJS.
|
||||
#
|
||||
# Usage: release.sh <stable-branch> <distrib dir> <github access token>
|
||||
# <stable_branch>: the stable branch to release from (e.g. ojs-stable-2_4_5)
|
||||
# <distrib dir>: a directory containing prior tarballs to use in generating
|
||||
# patches
|
||||
# <github access token>: an API token from
|
||||
# https://github.com/settings/applications
|
||||
#
|
||||
# NOTE: This script CANNOT currently be used to release a first build of a
|
||||
# revision (i.e. a -0 build). It can only be used to release -1 and subsequent
|
||||
# builds of a revision.
|
||||
|
||||
# Fail on first error
|
||||
set -e
|
||||
|
||||
# Check for proper usage
|
||||
if [ -z "$3" ]; then
|
||||
echo "Usage: $0 <stable-branch> <distrib dir> <github access token>";
|
||||
exit 1;
|
||||
fi
|
||||
BRANCH=$1
|
||||
DISTRIBDIR=$2
|
||||
ACCESSTOKEN=$3
|
||||
|
||||
# Make sure we're at the head of the stable branch
|
||||
git checkout ${BRANCH}
|
||||
git pull
|
||||
cd lib/pkp
|
||||
git checkout ${BRANCH}
|
||||
git pull
|
||||
cd ../..
|
||||
|
||||
# Determine the tag of the last release on this branch (e.g. ojs-2_4_5-0)
|
||||
LASTTAG=`git describe --tags --abbrev=0 $BRANCH`
|
||||
|
||||
# Parse the version number information from the tag
|
||||
[[ $LASTTAG =~ ([a-z]+)-([0-9]+)_([0-9]+)_([0-9]+)-([0-9]+) ]] && APPLICATION="${BASH_REMATCH[1]}" && MAJOR="${BASH_REMATCH[2]}" && MINOR="${BASH_REMATCH[3]}" && REVISION="${BASH_REMATCH[4]}" && LASTBUILD="${BASH_REMATCH[5]}"
|
||||
THISBUILD=$((LASTBUILD+1))
|
||||
|
||||
# Calculate the tag of the next release (e.g. ojs-2_4_5-1
|
||||
THISTAG=`echo $LASTTAG | sed -r 's/(.*-)([0-9]+)/echo \1$((\2+1))/ge'`
|
||||
|
||||
# Other useful bits and pieces
|
||||
BUILDDATE=`date +%Y-%m-%d`
|
||||
APPLICATION_UPPER=`echo ${APPLICATION} | tr '[:lower:]' '[:upper:]'`
|
||||
|
||||
# Update the version descriptor
|
||||
LASTPATCHSUFFIX="${MAJOR}.${MINOR}.${REVISION}"
|
||||
[[ ${LASTBUILD} -ne "" ]] && LASTPATCHSUFFIX="${LASTPATCHSUFFIX}-${LASTBUILD}"
|
||||
sed -i -e "s/<tag>.*<\/tag>/<tag>${THISTAG}<\/tag>/" \
|
||||
-e "s/<release>.*<\/release>/<release>${MAJOR}.${MINOR}.${REVISION}.${THISBUILD}<\/release>/" \
|
||||
-e "s/<date>.*<\/date>/<date>${BUILDDATE}<\/date>/" \
|
||||
-e "s/<package>.*<\/package>/<package>http:\/\/pkp.sfu.ca\/${APPLICATION}\/download\/${APPLICATION}-${MAJOR}.${MINOR}.${REVISION}-${THISBUILD}.tar.gz<\/package>/" \
|
||||
-e "s/\(<patch .*_to_\).*\(\.patch\.gz.*\)/\1${MAJOR}.${MINOR}.${REVISION}-${THISBUILD}.patch.gz/" \
|
||||
dbscripts/xml/version.xml
|
||||
git add dbscripts/xml/version.xml
|
||||
|
||||
# Update the upgrade and install descriptors
|
||||
sed -i -e "s/<install version=\".*\">/<install version=\"${MAJOR}.${MINOR}.${REVISION}.${THISBUILD}\">/" \
|
||||
dbscripts/xml/upgrade.xml dbscripts/xml/install.xml
|
||||
git add dbscripts/xml/upgrade.xml dbscripts/xml/install.xml
|
||||
|
||||
# Update the README.md
|
||||
sed -i -e "s/=== Version: .*/=== Version: ${MAJOR}.${MINOR}.${REVISION}-${THISBUILD}/" \
|
||||
-e "s/=== GIT tag: .*/=== GIT tag: ${THISTAG}/" \
|
||||
-e "s/=== Release date: .*/=== Release date: ${BUILDDATE}/" \
|
||||
docs/README.md
|
||||
git add docs/README.md
|
||||
|
||||
# Update the Doxygen config file
|
||||
sed -i -e "s/^\(PROJECT_NUMBER.*= \).*/\1${MAJOR}.${MINOR}.${REVISION}-${THISBUILD}/" \
|
||||
docs/dev/*.doxygen
|
||||
|
||||
# Generate the release notes
|
||||
echo -n "Generating release notes"
|
||||
echo "
|
||||
Automated Build ${MAJOR}-${MINOR}-${REVISION}.${THISBUILD}
|
||||
-----------------------
|
||||
This automated build adds the following fixes to the base release of ${APPLICATION_UPPER} ${MAJOR}.${MINOR}.${REVISION}:
|
||||
" >> docs/RELEASE
|
||||
|
||||
# Get the bug IDs and titles for issues referenced in this release
|
||||
for ISSUENUM in `(git log --pretty=oneline ${LASTTAG}..HEAD && cd lib/pkp && git log --pretty=oneline ${LASTTAG}..HEAD) | sed -n -e "s/.*pkp\/pkp-lib#\([0-9]\+\).*/\1/p" | sort -n | uniq`; do
|
||||
ISSUETITLE=`wget --auth-no-challenge --user=${ACCESSTOKEN} --password=x-oauth-basic -q -O - "https://api.github.com/repos/pkp/pkp-lib/issues/${ISSUENUM}" | php -r "echo trim(json_decode(file_get_contents('php://stdin'))->title);"`
|
||||
echo " #${ISSUENUM}: ${ISSUETITLE}" >> docs/RELEASE
|
||||
echo -n "." # Status
|
||||
done
|
||||
RELEASE_ALTCOPY="docs/release-notes/README-${MAJOR}.${MINOR}.${REVISION}"
|
||||
cp docs/RELEASE ${RELEASE_ALTCOPY}
|
||||
git add docs/RELEASE ${RELEASE_ALTCOPY}
|
||||
echo " Done."
|
||||
|
||||
# Commit the last changes
|
||||
git add lib/pkp
|
||||
git commit -m "Automated commits for ${APPLICATION_UPPER} ${MAJOR}.${MINOR}.${REVISION}-${THISBUILD}"
|
||||
cd lib/pkp
|
||||
git tag ${THISTAG}
|
||||
git push --tags
|
||||
cd ../..
|
||||
git tag ${THISTAG}
|
||||
git push --tags
|
||||
|
||||
# Build the package
|
||||
bash tools/buildpkg.sh ${MAJOR}.${MINOR}.${REVISION}-${THISBUILD} ${THISTAG} ${DISTRIBDIR}
|
||||
@@ -0,0 +1,185 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Query\Builder;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
require(dirname(__FILE__) . '/bootstrap.php');
|
||||
|
||||
class resolveAgencyDuplicates extends \PKP\cliTool\CommandLineTool
|
||||
{
|
||||
private string|null $command = null;
|
||||
private string|null $agency_name = null;
|
||||
private bool $forceFlag = false;
|
||||
/**
|
||||
* List of potential agencies to choose from along with related fields for resolution.
|
||||
*
|
||||
* Array shape should look like:
|
||||
* `['agency_name' => [
|
||||
* 'status' => 'agency_name::status',
|
||||
* 'additionalFields': [...],
|
||||
* ]
|
||||
* ]`
|
||||
*/
|
||||
private array $agencies = [
|
||||
'crossref' => [
|
||||
'status' => 'crossref::status',
|
||||
'additionalFields' => [
|
||||
'crossref::registeredDoi',
|
||||
'crossref::batchId',
|
||||
'crossref::failedMsg',
|
||||
],
|
||||
],
|
||||
'datacite' => [
|
||||
'status' => 'datacite::status',
|
||||
'additionalFields' => [
|
||||
'datacite::registeredDoi',
|
||||
],
|
||||
],
|
||||
'medra' => [
|
||||
'status' => 'medra::status',
|
||||
'additionalFields' => [
|
||||
'medra::registeredDoi',
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
public function __construct($argv = [])
|
||||
{
|
||||
parent::__construct($argv);
|
||||
|
||||
$forceFlagIndex = array_search('--force', $this->argv);
|
||||
if ($forceFlagIndex) {
|
||||
$this->forceFlag = true;
|
||||
array_splice($this->argv, $forceFlagIndex, 1);
|
||||
}
|
||||
|
||||
if (sizeof($this->argv) == 0) {
|
||||
$this->exitWithUsageMessage();
|
||||
}
|
||||
$this->command = array_shift($this->argv);
|
||||
$this->agency_name = array_shift($this->argv);
|
||||
|
||||
if (
|
||||
$this->command === 'resolve' &&
|
||||
($this->agency_name === null || !in_array($this->agency_name, array_keys($this->agencies)))
|
||||
) {
|
||||
$this->exitWithUsageMessage();
|
||||
}
|
||||
}
|
||||
|
||||
public function usage()
|
||||
{
|
||||
$agencies = implode(', ', array_keys($this->agencies));
|
||||
echo "Script to resolve DOI registration agency duplication pre-3.4.\n"
|
||||
. "NB: If a conflict exists for a submission, the corresponding publication objects (galleys, etc.) will also be cleaned up.\n\n"
|
||||
. "Usage:\n"
|
||||
. "{$this->scriptName} resolve [agency_name] --force : Remove conflicting DOI registration info, keeping agency_name.\n"
|
||||
. "{$this->scriptName} test : Returns list of conflicting items\n\n"
|
||||
. "Options:\n"
|
||||
. "agency_name One of: {$agencies}.\n"
|
||||
. "--force Force resolve operation. Will not delete data without it.\n";
|
||||
}
|
||||
|
||||
public function execute(): void
|
||||
{
|
||||
switch ($this->command) {
|
||||
case 'resolve':
|
||||
$this->resolve();
|
||||
break;
|
||||
case 'test':
|
||||
$this->test();
|
||||
break;
|
||||
default:
|
||||
$this->exitWithUsageMessage();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private function resolve(): void
|
||||
{
|
||||
if (!$this->forceFlag) {
|
||||
$this->print('Warning! This is a destructive operation. Ensure you have a database backup and re-run this command with the `--force` flag.');
|
||||
exit(0);
|
||||
}
|
||||
|
||||
$agencies = array_filter($this->agencies, fn ($key) => $key !== $this->agency_name, ARRAY_FILTER_USE_KEY);
|
||||
$this->print('Removing duplicate registration info for ' . implode(', ', array_keys($agencies)) . '...');
|
||||
|
||||
$agencyFields = array_reduce($agencies, fn ($carry, $item) => array_merge($carry, [$item['status']], $item['additionalFields']), []);
|
||||
$submissionIds = $this->getSubmissionIds();
|
||||
$galleyIds = $this->getGalleyIds();
|
||||
$issueIds = $this->getIssueIds();
|
||||
|
||||
DB::table('submission_settings')
|
||||
->whereIn('setting_name', $agencyFields)
|
||||
->whereIn('submission_id', $submissionIds)
|
||||
->delete();
|
||||
$this->print("Removed duplicates for {$submissionIds->count()} submission(s)");
|
||||
|
||||
DB::table('publication_galley_settings')
|
||||
->whereIn('setting_name', $agencyFields)
|
||||
->whereIn('galley_id', $galleyIds)
|
||||
->delete();
|
||||
$this->print("Removed duplicates for {$galleyIds->count()} galley(s)");
|
||||
|
||||
DB::table('issue_settings')
|
||||
->whereIn('setting_name', $agencyFields)
|
||||
->whereIn('issue_id', $issueIds)
|
||||
->delete();
|
||||
$this->print("Removed duplicates for {$issueIds->count()} issues(s)");
|
||||
}
|
||||
|
||||
private function test(): void
|
||||
{
|
||||
$this->print('IDs with duplicate DOI registration metadata:');
|
||||
$this->print("Submissions: {$this->getSubmissionIds()}");
|
||||
$this->print("Galleys: {$this->getGalleyIds()}");
|
||||
$this->print("Issues: {$this->getIssueIds()}");
|
||||
}
|
||||
|
||||
private function getSubmissionIds(): Collection
|
||||
{
|
||||
return DB::table('submission_settings')
|
||||
->whereIn('setting_name', array_map(fn ($item) => $item['status'], $this->agencies))
|
||||
->groupBy('submission_id')
|
||||
->havingRaw('COUNT(submission_id) > 1')
|
||||
->pluck('submission_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets galley IDs that have duplicates OR are associated with submissions with conflicts
|
||||
*/
|
||||
private function getGalleyIds(): Collection
|
||||
{
|
||||
return DB::table('publication_galley_settings')
|
||||
->whereIn('setting_name', array_map(fn ($item) => $item['status'], $this->agencies))
|
||||
->orWhereIn('galley_id', function (Builder $q) {
|
||||
$q->select('pg.galley_id')
|
||||
->from('publication_galleys', 'pg')
|
||||
->leftJoin('publications as p', 'pg.publication_id', '=', 'p.publication_id')
|
||||
->leftJoin('submissions as s', 'p.submission_id', '=', 's.submission_id')
|
||||
->whereIn('s.submission_id', $this->getSubmissionIds());
|
||||
})
|
||||
->groupBy('galley_id')
|
||||
->havingRaw('COUNT(galley_id) > 1')
|
||||
->pluck('galley_id');
|
||||
}
|
||||
|
||||
private function getIssueIds(): Collection
|
||||
{
|
||||
return DB::table('issue_settings')
|
||||
->whereIn('setting_name', array_map(fn ($item) => $item['status'], $this->agencies))
|
||||
->groupBy('issue_id')
|
||||
->havingRaw('COUNT(issue_id) > 1')
|
||||
->pluck('issue_id');
|
||||
}
|
||||
|
||||
protected function print(string $message): void
|
||||
{
|
||||
echo $message . PHP_EOL;
|
||||
}
|
||||
}
|
||||
|
||||
$tool = new resolveAgencyDuplicates($argv ?? []);
|
||||
$tool->execute();
|
||||
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file tools/runScheduledTasks.php
|
||||
*
|
||||
* Copyright (c) 2014-2021 Simon Fraser University
|
||||
* Copyright (c) 2003-2021 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class runScheduledTasks
|
||||
*
|
||||
* @ingroup tools
|
||||
*
|
||||
* @brief CLI tool to execute a set of scheduled tasks.
|
||||
*/
|
||||
|
||||
require(dirname(__FILE__) . '/bootstrap.php');
|
||||
|
||||
class runScheduledTasks extends \PKP\cliTool\ScheduledTaskTool
|
||||
{
|
||||
}
|
||||
|
||||
$tool = new runScheduledTasks($argv ?? []);
|
||||
$tool->execute();
|
||||
@@ -0,0 +1,123 @@
|
||||
#!/bin/bash
|
||||
|
||||
parseRepositoryName () {
|
||||
local url=$1
|
||||
if [ -z "$url" ]; then
|
||||
echo "You should pass a URL" >&2
|
||||
exit 2;
|
||||
fi;
|
||||
|
||||
echo $(basename "${url}" .git)
|
||||
}
|
||||
|
||||
getSubmodulesList () {
|
||||
local option=$1
|
||||
if [ -z "$option" ]; then
|
||||
echo "You should select an option" >&2
|
||||
exit 2;
|
||||
fi;
|
||||
|
||||
echo $(git config --file .gitmodules --get-regexp ${option} | awk '{ print $2 }');
|
||||
}
|
||||
|
||||
existsFork () {
|
||||
local username=$1
|
||||
local repository=$2
|
||||
local branch=$3
|
||||
if [ -z "$username" ]
|
||||
then
|
||||
echo "Username should be pass as first parameter." >&2
|
||||
exit 2;
|
||||
fi;
|
||||
|
||||
if [ -z "$repository" ]
|
||||
then
|
||||
echo "Repository should be pass as second parameter." >&2
|
||||
exit 2;
|
||||
fi;
|
||||
|
||||
if [ -z "$branch" ]
|
||||
then
|
||||
echo "Branch should be pass as third parameter." >&2
|
||||
exit 2;
|
||||
fi;
|
||||
|
||||
result=$(git ls-remote --quiet --exit-code -h https://github.com/${username}/${repository} ${branch});
|
||||
|
||||
if [ ! -z "$result" ]
|
||||
then
|
||||
echo 1;
|
||||
else
|
||||
echo 0;
|
||||
fi;
|
||||
}
|
||||
|
||||
git config --global user.email "pkp@mailinator.com"
|
||||
git config --global user.name "PKP"
|
||||
echo "1 - Retrieving git user:"
|
||||
gitUser=$(cat .git/config | grep -A2 "remote \"origin\"" | grep "url" | cut -f2 -d":" | cut -f4 -d"/")
|
||||
echo " Gituser: $gitUser"
|
||||
echo "2 - Verifying if we have a merge commit in HEAD:"
|
||||
isMergeCommit=$(git log -m --pretty=oneline -n1 | grep -P "Merge [0-9a-z]{40} into [0-9a-z]{40}")
|
||||
echo " Merge commit message: $isMergeCommit"
|
||||
if [ \( -n "$isMergeCommit" \) -a \( "$gitUser" = "pkp" \) ]; then
|
||||
commitHash=$(git log -m --pretty=oneline -n2 | sed -n 2p | grep -Po "^[0-9a-z]{40}")
|
||||
echo " HEAD points to a merge commit."
|
||||
echo " HEAD^ points to a common commit with hash $commitHash"
|
||||
else
|
||||
commitHash=$(git log -m --pretty=oneline -n1 | grep -Po "^[0-9a-z]{40}")
|
||||
echo " HEAD points to a common commit with hash $commitHash"
|
||||
fi
|
||||
echo "3 - Verifying if last non merge commit is a subproject commit:"
|
||||
libModuleHashes=$(git show "$commitHash" | grep "+Subproject commit" | cut -f3 -d" ")
|
||||
strLength=${#libModuleHashes}
|
||||
echo " Subproject commit hash: $libModuleHashes"
|
||||
if [ \( -n "$libModuleHashes" \) -a \( "$strLength" -ge 40 \) ]; then
|
||||
echo " Last non merge commit is subproject commit."
|
||||
echo "4 - Trying to get user and branch from commit message:"
|
||||
userAndBranch=$(git log --pretty=oneline -1 "$commitHash" | grep -o "##.*##" | sed "s:^##\(.*\)##$:\1:")
|
||||
gitUser=$(echo "$userAndBranch" | cut -f1 -d"/")
|
||||
branch=$(echo "$userAndBranch" | cut -f2- -d"/")
|
||||
echo " User and branch: $userAndBranch - User: $gitUser - Branch: $branch"
|
||||
if [ \( -n "$gitUser" \) -a \( -n "$branch" \) ]; then
|
||||
echo " Found user and branch in commit message."
|
||||
echo "5 - Reseting the subproject commit in application."
|
||||
git reset --hard "$commitHash"^
|
||||
echo "6 - Initializing and updating submodule from official."
|
||||
git submodule update --init --recursive
|
||||
submoduleList=$(getSubmodulesList path)
|
||||
|
||||
declare -A submodulesArr
|
||||
for submodule in $submoduleList
|
||||
do
|
||||
rawUrl=$(getSubmodulesList "submodule.${submodule}.url")
|
||||
submodulesArr[$submodule]=$(parseRepositoryName $rawUrl)
|
||||
done;
|
||||
|
||||
rootDir=$(pwd)
|
||||
currentSubmoduleIteration=1
|
||||
|
||||
for submoduleName in ${!submodulesArr[@]};
|
||||
do
|
||||
submoduleUrlBasename=${submodulesArr[${submoduleName}]};
|
||||
submoduleLocalPath=$submoduleName
|
||||
printf "\nThis is the submodule: ${submoduleName}\n"
|
||||
printf "\tLocal path for repository should be %s\n" "${submoduleLocalPath}"
|
||||
printf "\tURL path for repository should be %s\n" "${submoduleUrlBasename}"
|
||||
printf "\tExists fork for it?\n"
|
||||
existsForkForSubmodule=$(existsFork ${gitUser} ${submoduleUrlBasename} ${branch})
|
||||
if [[ $existsForkForSubmodule == 1 ]]
|
||||
then
|
||||
echo "7 - Updating $submoduleLocalPath with code from $gitUser repository, $branch branch."
|
||||
cd ${submoduleLocalPath}
|
||||
git remote add "$gitUser" https://github.com/"$gitUser"/"$submoduleUrlBasename"
|
||||
git reset --hard HEAD
|
||||
git pull --rebase "$gitUser" "$branch"
|
||||
cd ${rootDir}
|
||||
((currentSubmoduleIteration=currentSubmoduleIteration+1))
|
||||
fi;
|
||||
done
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
git submodule update --init --recursive
|
||||
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file tools/upgrade.php
|
||||
*
|
||||
* Copyright (c) 2014-2021 Simon Fraser University
|
||||
* Copyright (c) 2003-2021 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class upgradeTool
|
||||
*
|
||||
* @ingroup tools
|
||||
*
|
||||
* @brief CLI tool for upgrading OJS.
|
||||
*
|
||||
* Note: Some functions require fopen wrappers to be enabled.
|
||||
*/
|
||||
|
||||
require(dirname(__FILE__) . '/bootstrap.php');
|
||||
|
||||
$tool = new \PKP\cliTool\UpgradeTool($argv ?? []);
|
||||
$tool->execute();
|
||||
@@ -0,0 +1,14 @@
|
||||
./files/
|
||||
./tests/
|
||||
./lib/pkp/tests/phpunit.xml
|
||||
./lib/pkp/lib
|
||||
./lib/pkp/tests/classes/xslt
|
||||
./lib/pkp/js/lib
|
||||
./plugins/generic/citationStyleLanguage/lib/vendor
|
||||
./plugins/oaiMetadataFormats/dc/tests/expectedResult.xml
|
||||
./plugins/importexport/users/sample.xml
|
||||
./plugins/paymethod/paypal/vendor
|
||||
./lib/pkp/tests
|
||||
./node_modules
|
||||
./lib/ui-library/node_modules
|
||||
./cypress/fixtures/export-issues.xml
|
||||
Reference in New Issue
Block a user