first commit
This commit is contained in:
@@ -0,0 +1,168 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @defgroup tools Tools
|
||||
* Implements command-line management tools for PKP software.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file classes/cliTool/CommandLineTool.php
|
||||
*
|
||||
* Copyright (c) 2014-2021 Simon Fraser University
|
||||
* Copyright (c) 2000-2021 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class CommandLineTool
|
||||
*
|
||||
* @ingroup tools
|
||||
*
|
||||
* @brief Initialization code for command-line scripts.
|
||||
*
|
||||
* FIXME: Write a PKPCliRequest and PKPCliRouter class and use the dispatcher
|
||||
* to bootstrap and route tool requests.
|
||||
*/
|
||||
|
||||
namespace PKP\cliTool;
|
||||
|
||||
use APP\core\Application;
|
||||
use APP\core\PageRouter;
|
||||
use APP\facades\Repo;
|
||||
use PKP\core\Registry;
|
||||
use PKP\plugins\PluginRegistry;
|
||||
use PKP\security\Role;
|
||||
use PKP\session\SessionManager;
|
||||
use PKP\user\User;
|
||||
use PKP\config\Config;
|
||||
|
||||
/** Initialization code */
|
||||
define('PWD', getcwd());
|
||||
chdir(dirname(INDEX_FILE_LOCATION)); /* Change to base directory */
|
||||
if (!defined('STDIN')) {
|
||||
define('STDIN', fopen('php://stdin', 'r'));
|
||||
}
|
||||
require_once './lib/pkp/includes/bootstrap.php';
|
||||
SessionManager::disable();
|
||||
|
||||
class CommandLineTool
|
||||
{
|
||||
/** @var string the script being executed */
|
||||
public $scriptName;
|
||||
|
||||
/** @vary array Command-line arguments */
|
||||
public $argv;
|
||||
|
||||
/** @var string the username provided */
|
||||
public ?string $username = null;
|
||||
|
||||
/** @var \PKP\user\User the user provided */
|
||||
public ?User $user = null;
|
||||
|
||||
public function __construct($argv = [])
|
||||
{
|
||||
// Initialize the request object with a page router
|
||||
$application = Application::get();
|
||||
$request = $application->getRequest();
|
||||
|
||||
// FIXME: Write and use a CLIRouter here (see classdoc)
|
||||
$router = new PageRouter();
|
||||
$router->setApplication($application);
|
||||
$request->setRouter($router);
|
||||
|
||||
// Initialize the locale and load generic plugins.
|
||||
PluginRegistry::loadCategory('generic');
|
||||
|
||||
$this->argv = isset($argv) && is_array($argv) ? $argv : [];
|
||||
|
||||
if (isset($_SERVER['SERVER_NAME'])) {
|
||||
exit('This script can only be executed from the command-line');
|
||||
}
|
||||
|
||||
$this->scriptName = isset($this->argv[0]) ? array_shift($this->argv) : '';
|
||||
|
||||
if (Config::getVar('general', 'installed')) $this->checkArgsForUsername();
|
||||
|
||||
if (isset($this->argv[0]) && $this->argv[0] == '-h') {
|
||||
$this->exitWithUsageMessage();
|
||||
}
|
||||
}
|
||||
|
||||
public function usage()
|
||||
{
|
||||
}
|
||||
|
||||
private function checkArgsForUsername()
|
||||
{
|
||||
$usernameKeyPos = array_search('--user_name', $this->argv);
|
||||
if (!$usernameKeyPos) {
|
||||
$usernameKeyPos = array_search('-u', $this->argv);
|
||||
}
|
||||
|
||||
if ($usernameKeyPos) {
|
||||
$usernamePos = $usernameKeyPos + 1;
|
||||
if (count($this->argv) >= $usernamePos + 1) {
|
||||
$this->username = $this->argv[$usernamePos];
|
||||
|
||||
unset($this->argv[$usernamePos]);
|
||||
}
|
||||
|
||||
unset($this->argv[$usernameKeyPos]);
|
||||
}
|
||||
|
||||
if ($this->username) {
|
||||
$user = Repo::user()->getByUsername($this->username, true);
|
||||
|
||||
$this->setUser($user);
|
||||
}
|
||||
|
||||
if (!$this->user) {
|
||||
$adminGroups = Repo::userGroup()->getArrayIdByRoleId(Role::ROLE_ID_SITE_ADMIN);
|
||||
|
||||
if (count($adminGroups)) {
|
||||
$groupUsers = Repo::user()->getCollector()
|
||||
->filterByUserGroupIds([$adminGroups[0]])
|
||||
->getMany();
|
||||
|
||||
if ($groupUsers->isNotEmpty()) {
|
||||
$this->setUser($groupUsers->first());
|
||||
} else {
|
||||
$this->exitWithUsageMessage();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the user for the CLI Tool
|
||||
*
|
||||
* @param \PKP\user\User $user The user to set as the execution user of this CLI command
|
||||
*/
|
||||
public function setUser($user)
|
||||
{
|
||||
$registeredUser = Registry::get('user', true, null);
|
||||
if (!isset($registeredUser)) {
|
||||
/**
|
||||
* This is used in order to reconcile with possible $request->getUser()
|
||||
* used inside import processes, when the import is done by CLI tool.
|
||||
*/
|
||||
if ($user) {
|
||||
Registry::set('user', $user);
|
||||
$this->user = $user;
|
||||
}
|
||||
} else {
|
||||
$this->user = $registeredUser;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Exit the CLI tool if an error occurs
|
||||
*/
|
||||
public function exitWithUsageMessage()
|
||||
{
|
||||
$this->usage();
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
if (!PKP_STRICT_MODE) {
|
||||
class_alias('\PKP\cliTool\CommandLineTool', '\CommandLineTool');
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file lib/pkp/classes/cliTool/ConvertLogFileTool.php
|
||||
*
|
||||
* Copyright (c) 2022 Simon Fraser University
|
||||
* Copyright (c) 2022 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class ConvertLogFileTool
|
||||
*
|
||||
* @ingroup tools
|
||||
*
|
||||
* @brief Tool to convert usage stats log file (used in releases < 3.4) into the new format.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace PKP\cliTool;
|
||||
|
||||
use PKP\cliTool\traits\ConvertLogFile;
|
||||
|
||||
abstract class ConvertLogFileTool extends \PKP\cliTool\CommandLineTool
|
||||
{
|
||||
use ConvertLogFile;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param array $argv command-line arguments (see usage)
|
||||
*/
|
||||
public function __construct($argv = [])
|
||||
{
|
||||
parent::__construct($argv);
|
||||
$this->__constructTrait();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,261 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/cliTool/InstallTool.php
|
||||
*
|
||||
* Copyright (c) 2014-2021 Simon Fraser University
|
||||
* Copyright (c) 2000-2021 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class installTool
|
||||
*
|
||||
* @ingroup tools
|
||||
*
|
||||
* @brief CLI tool for installing a PKP app.
|
||||
*/
|
||||
|
||||
namespace PKP\cliTool;
|
||||
|
||||
use APP\install\Install;
|
||||
use PKP\install\form\InstallForm;
|
||||
|
||||
class InstallTool extends \PKP\cliTool\CommandLineTool
|
||||
{
|
||||
/** @var array installation parameters */
|
||||
public $params;
|
||||
|
||||
/**
|
||||
* Print command usage information.
|
||||
*/
|
||||
public function usage()
|
||||
{
|
||||
echo "Install tool\n"
|
||||
. "Usage: {$this->scriptName}\n";
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the script.
|
||||
*/
|
||||
public function execute()
|
||||
{
|
||||
if ($this->readParams()) {
|
||||
$this->install();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform installation.
|
||||
*/
|
||||
public function install()
|
||||
{
|
||||
$installer = new Install($this->params);
|
||||
$installer->setLogger($this);
|
||||
|
||||
if ($installer->execute()) {
|
||||
if (count($installer->getNotes()) > 0) {
|
||||
printf("\nRelease Notes\n");
|
||||
printf("----------------------------------------\n");
|
||||
foreach ($installer->getNotes() as $note) {
|
||||
printf("%s\n\n", $note);
|
||||
}
|
||||
}
|
||||
|
||||
if (!$installer->wroteConfig()) {
|
||||
printf("\nNew config.inc.php:\n");
|
||||
printf("----------------------------------------\n");
|
||||
echo $installer->getConfigContents();
|
||||
printf("----------------------------------------\n");
|
||||
}
|
||||
|
||||
$newVersion = $installer->getNewVersion();
|
||||
printf("Successfully installed version %s\n", $newVersion->getVersionString(false));
|
||||
} else {
|
||||
printf("ERROR: Installation failed: %s\n", $installer->getErrorString());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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()
|
||||
{
|
||||
$installForm = new InstallForm(null); // Request object not available to CLI
|
||||
|
||||
// Locale Settings
|
||||
$this->printTitle('installer.localeSettings');
|
||||
$this->readParamOptions('locale', 'locale.primary', $installForm->supportedLocales, 'en');
|
||||
$this->readParamOptions('additionalLocales', 'installer.additionalLocales', $installForm->supportedLocales, '', true);
|
||||
|
||||
// File Settings
|
||||
$this->printTitle('installer.fileSettings');
|
||||
$this->readParam('filesDir', 'installer.filesDir');
|
||||
|
||||
// Administrator Account
|
||||
$this->printTitle('installer.administratorAccount');
|
||||
$this->readParam('adminUsername', 'user.username');
|
||||
@`/bin/stty -echo`;
|
||||
do {
|
||||
$this->readParam('adminPassword', 'user.password');
|
||||
printf("\n");
|
||||
$this->readParam('adminPassword2', 'user.repeatPassword');
|
||||
printf("\n");
|
||||
} while ($this->params['adminPassword'] != $this->params['adminPassword2']);
|
||||
@`/bin/stty echo`;
|
||||
$this->readParam('adminEmail', 'user.email');
|
||||
|
||||
// Database Settings
|
||||
$this->printTitle('installer.databaseSettings');
|
||||
$this->readParamOptions('databaseDriver', 'installer.databaseDriver', $installForm->getDatabaseDriversOptions());
|
||||
$this->readParam('databaseHost', 'installer.databaseHost', '');
|
||||
$this->readParam('databaseUsername', 'installer.databaseUsername', '');
|
||||
$this->readParam('databasePassword', 'installer.databasePassword', '');
|
||||
$this->readParam('databaseName', 'installer.databaseName');
|
||||
|
||||
// Miscellaneous Settings
|
||||
$this->printTitle('installer.miscSettings');
|
||||
$this->readParam('oaiRepositoryId', 'installer.oaiRepositoryId');
|
||||
|
||||
$this->readParamBoolean('enableBeacon', 'installer.beacon.enable', 'Y');
|
||||
|
||||
printf("\n*** ");
|
||||
}
|
||||
|
||||
/**
|
||||
* Print input section title.
|
||||
*
|
||||
* @param string $title
|
||||
*/
|
||||
public function printTitle($title)
|
||||
{
|
||||
printf("\n%s\n%s\n%s\n", str_repeat('-', 80), __($title), str_repeat('-', 80));
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a line of user input.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function readInput()
|
||||
{
|
||||
$value = trim(fgets(STDIN));
|
||||
if ($value === false || feof(STDIN)) {
|
||||
printf("\n");
|
||||
exit(0);
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a string parameter.
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $prompt
|
||||
* @param string $defaultValue
|
||||
*/
|
||||
public function readParam($name, $prompt, $defaultValue = null)
|
||||
{
|
||||
do {
|
||||
if (isset($defaultValue)) {
|
||||
printf('%s (%s): ', __($prompt), $defaultValue !== '' ? $defaultValue : __('common.none'));
|
||||
} else {
|
||||
printf('%s: ', __($prompt));
|
||||
}
|
||||
|
||||
$value = $this->readInput();
|
||||
|
||||
if ($value === '' && isset($defaultValue)) {
|
||||
$value = $defaultValue;
|
||||
}
|
||||
} while ($value === '' && $defaultValue !== '');
|
||||
$this->params[$name] = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prompt user for yes/no input.
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $prompt
|
||||
* @param string $default default value, 'Y' or 'N'
|
||||
*/
|
||||
public function readParamBoolean($name, $prompt, $default = 'N')
|
||||
{
|
||||
if ($default == 'N') {
|
||||
printf('%s [y/N] ', __($prompt));
|
||||
$value = $this->readInput();
|
||||
$this->params[$name] = (int)(strtolower(substr(trim($value), 0, 1)) == 'y');
|
||||
} else {
|
||||
printf('%s [Y/n] ', __($prompt));
|
||||
$value = $this->readInput();
|
||||
$this->params[$name] = (int)(strtolower(substr(trim($value), 0, 1)) != 'n');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a parameter from a set of options.
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $prompt
|
||||
* @param array $options
|
||||
* @param null|mixed $defaultValue
|
||||
*/
|
||||
public function readParamOptions($name, $prompt, $options, $defaultValue = null, $allowMultiple = false)
|
||||
{
|
||||
do {
|
||||
printf("%s\n", __($prompt));
|
||||
foreach ($options as $k => $v) {
|
||||
printf(" %-10s %s\n", '[' . $k . ']', $v);
|
||||
}
|
||||
if ($allowMultiple) {
|
||||
printf(" (%s)\n", __('installer.form.separateMultiple'));
|
||||
}
|
||||
if (isset($defaultValue)) {
|
||||
printf('%s (%s): ', __('common.select'), $defaultValue !== '' ? $defaultValue : __('common.none'));
|
||||
} else {
|
||||
printf('%s: ', __('common.select'));
|
||||
}
|
||||
|
||||
$value = $this->readInput();
|
||||
|
||||
if ($value === '' && isset($defaultValue)) {
|
||||
$value = $defaultValue;
|
||||
}
|
||||
|
||||
$values = [];
|
||||
if ($value !== '') {
|
||||
if ($allowMultiple) {
|
||||
$values = ($value === '' ? [] : preg_split('/\s*,\s*/', $value));
|
||||
} else {
|
||||
$values = [$value];
|
||||
}
|
||||
foreach ($values as $k) {
|
||||
if (!isset($options[$k])) {
|
||||
$value = '';
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} while ($value === '' && $defaultValue !== '');
|
||||
|
||||
if ($allowMultiple) {
|
||||
$this->params[$name] = $values;
|
||||
} else {
|
||||
$this->params[$name] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Log install message to stdout.
|
||||
*
|
||||
* @param string $message
|
||||
*/
|
||||
public function log($message)
|
||||
{
|
||||
printf("[%s]\n", $message);
|
||||
}
|
||||
}
|
||||
|
||||
if (!PKP_STRICT_MODE) {
|
||||
class_alias('\PKP\cliTool\InstallTool', '\InstallTool');
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file lib/pkp/classes/cliTool/MergeUsersTool.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.
|
||||
*/
|
||||
|
||||
namespace PKP\cliTool;
|
||||
|
||||
use APP\facades\Repo;
|
||||
|
||||
class MergeUsersTool extends \PKP\cliTool\CommandLineTool
|
||||
{
|
||||
/** @var string $targetSpecifier */
|
||||
public $targetSpecifier;
|
||||
|
||||
/** @var array $mergeSpecifier */
|
||||
public $mergeSpecifiers;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param array $argv command-line arguments
|
||||
*/
|
||||
public function __construct($argv = [])
|
||||
{
|
||||
parent::__construct($argv);
|
||||
|
||||
if (!isset($this->argv[0]) || !isset($this->argv[1])) {
|
||||
$this->usage();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
$this->targetSpecifier = $this->argv[0];
|
||||
$this->mergeSpecifiers = array_slice($this->argv, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Print command usage information.
|
||||
*/
|
||||
public function usage()
|
||||
{
|
||||
echo "Merge users tool\n"
|
||||
. "Use this tool to merge two or more user accounts.\n\n"
|
||||
. "Usage: {$this->scriptName} targetUsername mergeUsername1 [mergeUsername2] [...]\n"
|
||||
. "targetUsername: The target username for assets to be transferred to.\n"
|
||||
. "mergeUsername1: The username for the account to be merged. All assets (e.g.\n"
|
||||
. " submissions) associated with this user account will be\n"
|
||||
. " transferred to the user account that corresponds to\n"
|
||||
. " targetUsername. The user account that corresponds\n"
|
||||
. " to mergeUsername1 will be deleted.\n\n"
|
||||
. "Multiple users to merge can be specified in the same command, e.g.:\n\n"
|
||||
. "{$this->scriptName} myUsername spamUser1 spamUser2 spamUser3\n\n"
|
||||
. "This will merge users with username \"spamUser1\", \"spamUser2\", and\n"
|
||||
. "\"spamUser3\" into the account with username \"myUsername\".\n\n"
|
||||
. "Users can be specified by ID by entering usernames of the form \"id=x\"\n"
|
||||
. "with the user ID in place of \"x\", e.g.:\n\n"
|
||||
. "{$this->scriptName} myUsername id=234 id=456\n\n"
|
||||
. "Usernames and IDs may be mixed as desired.\n";
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the merge users command.
|
||||
*/
|
||||
public function execute()
|
||||
{
|
||||
$targetUser = $this->_getUserBySpecifier($this->targetSpecifier);
|
||||
if (!$targetUser) {
|
||||
echo "Error: \"{$this->targetSpecifier}\" does not specify a valid user.\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Build a list of usernames and IDs, checking for missing users before doing anything.
|
||||
$mergeArray = [];
|
||||
foreach ($this->mergeSpecifiers as $specifier) {
|
||||
$mergeUser = $this->_getUserBySpecifier($specifier);
|
||||
if (!$mergeUser) {
|
||||
echo "Error: \"{$specifier}\" does not specify a valid user.\n";
|
||||
exit(2);
|
||||
}
|
||||
if ($mergeUser->getId() == $targetUser->getId()) {
|
||||
echo "Error: Cannot merge an account into itself.\n";
|
||||
exit(3);
|
||||
}
|
||||
$mergeArray[$mergeUser->getId()] = $mergeUser->getUsername();
|
||||
}
|
||||
|
||||
// Merge the accounts.
|
||||
foreach ($mergeArray as $userId => $username) {
|
||||
Repo::user()->mergeUsers((int) $userId, $targetUser->getId());
|
||||
}
|
||||
|
||||
if (count($mergeArray) == 1) {
|
||||
echo "Merge completed: \"{$username}\" merged into \"" . $targetUser->getUsername() . "\".\n";
|
||||
} else {
|
||||
echo 'Merge completed: ' . count($mergeArray) . ' users merged into "' . $targetUser->getUsername() . "\".\n";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a username by specifier, i.e. username or id=xyz.
|
||||
*
|
||||
* @param string $specifier The specifier
|
||||
*
|
||||
* @return \PKP\user\User|null
|
||||
*/
|
||||
protected function _getUserBySpecifier($specifier)
|
||||
{
|
||||
if (substr($specifier, 0, 3) == 'id=') {
|
||||
$userId = substr($specifier, 3);
|
||||
if (!ctype_digit($userId)) {
|
||||
return null;
|
||||
}
|
||||
return Repo::user()->get((int) $userId, true);
|
||||
}
|
||||
return Repo::user()->getByUsername($specifier, true);
|
||||
}
|
||||
}
|
||||
|
||||
if (!PKP_STRICT_MODE) {
|
||||
class_alias('\PKP\cliTool\MergeUsersTool', '\MergeUsersTool');
|
||||
}
|
||||
@@ -0,0 +1,140 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/cliTool/ScheduledTaskTool.php
|
||||
*
|
||||
* Copyright (c) 2014-2021 Simon Fraser University
|
||||
* Copyright (c) 2000-2021 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class ScheduledTaskTool
|
||||
*
|
||||
* @ingroup tools
|
||||
*
|
||||
* @brief CLI tool to execute a set of scheduled tasks.
|
||||
*/
|
||||
|
||||
namespace PKP\cliTool;
|
||||
|
||||
use PKP\db\DAORegistry;
|
||||
use PKP\config\Config;
|
||||
use PKP\scheduledTask\ScheduledTaskDAO;
|
||||
use PKP\scheduledTask\ScheduledTaskHelper;
|
||||
use PKP\xml\PKPXMLParser;
|
||||
|
||||
/** Default XML tasks file to parse if none is specified */
|
||||
define('TASKS_REGISTRY_FILE', 'registry/scheduledTasks.xml');
|
||||
|
||||
class ScheduledTaskTool extends \PKP\cliTool\CommandLineTool
|
||||
{
|
||||
/** @var string the XML file listing the tasks to be executed */
|
||||
public $file;
|
||||
|
||||
/** @var ScheduledTaskDAO the DAO object */
|
||||
public $taskDao;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param array $argv command-line arguments
|
||||
* If specified, the first parameter should be the path to
|
||||
* a tasks XML descriptor file (other than the default)
|
||||
*/
|
||||
public function __construct($argv = [])
|
||||
{
|
||||
parent::__construct($argv);
|
||||
|
||||
if (isset($this->argv[0])) {
|
||||
$this->file = $this->argv[0];
|
||||
} else {
|
||||
$this->file = TASKS_REGISTRY_FILE;
|
||||
}
|
||||
|
||||
if (!file_exists($this->file) || !is_readable($this->file)) {
|
||||
printf("Tasks file \"%s\" does not exist or is not readable!\n", $this->file);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
$this->taskDao = DAORegistry::getDAO('ScheduledTaskDAO');
|
||||
}
|
||||
|
||||
/**
|
||||
* Print command usage information.
|
||||
*/
|
||||
public function usage()
|
||||
{
|
||||
echo "Script to run a set of scheduled tasks\n"
|
||||
. "Usage: {$this->scriptName} [tasks_file]\n";
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse and execute the scheduled tasks.
|
||||
*/
|
||||
public function execute()
|
||||
{
|
||||
// Application is set to sandbox mode and will not run any schedule tasks
|
||||
if (Config::getVar('general', 'sandbox', false)) {
|
||||
error_log('Application is set to sandbox mode and will not run any schedule tasks');
|
||||
return;
|
||||
}
|
||||
|
||||
$this->parseTasks($this->file);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse and execute the scheduled tasks in the specified file.
|
||||
*
|
||||
* @param string $file
|
||||
*/
|
||||
public function parseTasks($file)
|
||||
{
|
||||
$xmlParser = new PKPXMLParser();
|
||||
$tree = $xmlParser->parse($file);
|
||||
|
||||
if (!$tree) {
|
||||
printf("Unable to parse file \"%s\"!\n", $file);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
foreach ($tree->getChildren() as $task) {
|
||||
$className = $task->getAttribute('class');
|
||||
|
||||
$frequency = $task->getChildByName('frequency');
|
||||
if (isset($frequency)) {
|
||||
$canExecute = ScheduledTaskHelper::checkFrequency($className, $frequency);
|
||||
} else {
|
||||
// Always execute if no frequency is specified
|
||||
$canExecute = true;
|
||||
}
|
||||
|
||||
if ($canExecute) {
|
||||
$this->executeTask($className, ScheduledTaskHelper::getTaskArgs($task));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the specified task.
|
||||
*
|
||||
* @param string $className the class name to execute
|
||||
* @param array $args the array of arguments to pass to the class constructors
|
||||
*/
|
||||
public function executeTask($className, $args)
|
||||
{
|
||||
// Load and execute the task
|
||||
if (preg_match('/^[a-zA-Z0-9_.]+$/', $className)) {
|
||||
// DEPRECATED as of 3.4.0: Use old class.name.style and import() function (pre-PSR classloading) pkp/pkp-lib#8186
|
||||
if (!is_object($task = instantiate($className, null, null, 'execute', $args))) {
|
||||
fatalError('Cannot instantiate task class.');
|
||||
}
|
||||
} else {
|
||||
$task = new $className($args);
|
||||
}
|
||||
$this->taskDao->updateLastRunTime($className);
|
||||
$task->execute();
|
||||
}
|
||||
}
|
||||
|
||||
if (!PKP_STRICT_MODE) {
|
||||
class_alias('\PKP\cliTool\ScheduledTaskTool', '\ScheduledTaskTool');
|
||||
}
|
||||
@@ -0,0 +1,237 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/cliTool/UpgradeTool.php
|
||||
*
|
||||
* Copyright (c) 2014-2021 Simon Fraser University
|
||||
* Copyright (c) 2000-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 the system.
|
||||
*
|
||||
* Note: Some functions require fopen wrappers to be enabled.
|
||||
*/
|
||||
|
||||
namespace PKP\cliTool;
|
||||
|
||||
use APP\core\Application;
|
||||
use APP\install\Upgrade;
|
||||
use PKP\site\VersionCheck;
|
||||
|
||||
Application::upgrade();
|
||||
|
||||
class UpgradeTool extends \PKP\cliTool\CommandLineTool
|
||||
{
|
||||
/** @var string command to execute (check|upgrade|download) */
|
||||
public $command;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param array $argv command-line arguments
|
||||
*/
|
||||
public function __construct($argv = [])
|
||||
{
|
||||
parent::__construct($argv);
|
||||
|
||||
if (!isset($this->argv[0]) || !in_array($this->argv[0], ['check', 'latest', 'upgrade', 'download'])) {
|
||||
$this->usage();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
$this->command = $this->argv[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Print command usage information.
|
||||
*/
|
||||
public function usage()
|
||||
{
|
||||
echo "Upgrade tool\n"
|
||||
. "Usage: {$this->scriptName} command\n"
|
||||
. "Supported commands:\n"
|
||||
. " check perform version check\n"
|
||||
. " latest display latest version info\n"
|
||||
. " upgrade execute upgrade script\n"
|
||||
. " download download latest version (does not unpack/install)\n";
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the specified command.
|
||||
*/
|
||||
public function execute()
|
||||
{
|
||||
$command = $this->command;
|
||||
$this->$command();
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform version check against latest available version.
|
||||
*/
|
||||
public function check()
|
||||
{
|
||||
$this->checkVersion(VersionCheck::getLatestVersion());
|
||||
}
|
||||
|
||||
/**
|
||||
* Print information about the latest available version.
|
||||
*/
|
||||
public function latest()
|
||||
{
|
||||
$this->checkVersion(VersionCheck::getLatestVersion(), true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Run upgrade script.
|
||||
*/
|
||||
public function upgrade()
|
||||
{
|
||||
$installer = new Upgrade([]);
|
||||
$installer->setLogger($this);
|
||||
|
||||
if ($installer->execute()) {
|
||||
if (count($installer->getNotes()) > 0) {
|
||||
printf("\nRelease Notes\n");
|
||||
printf("----------------------------------------\n");
|
||||
foreach ($installer->getNotes() as $note) {
|
||||
printf("%s\n\n", $note);
|
||||
}
|
||||
}
|
||||
|
||||
$newVersion = $installer->getNewVersion();
|
||||
printf("Successfully upgraded to version %s\n", $newVersion->getVersionString(false));
|
||||
} else {
|
||||
printf("ERROR: Upgrade failed: %s\n", $installer->getErrorString());
|
||||
exit(2);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Download latest package.
|
||||
*/
|
||||
public function download()
|
||||
{
|
||||
$versionInfo = VersionCheck::getLatestVersion();
|
||||
if (!$versionInfo) {
|
||||
$application = Application::get();
|
||||
printf("Failed to load version info from %s\n", $application->getVersionDescriptorUrl());
|
||||
exit(3);
|
||||
}
|
||||
|
||||
$download = $versionInfo['package'];
|
||||
$outFile = basename($download);
|
||||
|
||||
printf("Download: %s\n", $download);
|
||||
printf("File will be saved to: %s\n", $outFile);
|
||||
|
||||
if (!$this->promptContinue()) {
|
||||
exit(0);
|
||||
}
|
||||
|
||||
$out = fopen($outFile, 'wb');
|
||||
if (!$out) {
|
||||
printf("Failed to open %s for writing\n", $outFile);
|
||||
exit(5);
|
||||
}
|
||||
|
||||
$in = fopen($download, 'rb');
|
||||
if (!$in) {
|
||||
printf("Failed to open %s for reading\n", $download);
|
||||
fclose($out);
|
||||
exit(6);
|
||||
}
|
||||
|
||||
printf('Downloading file...');
|
||||
|
||||
while (($data = fread($in, 4096)) !== '') {
|
||||
printf('.');
|
||||
fwrite($out, $data);
|
||||
}
|
||||
|
||||
printf("done\n");
|
||||
|
||||
fclose($in);
|
||||
fclose($out);
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform version check.
|
||||
*
|
||||
* @param array $versionInfo latest version info
|
||||
* @param bool $displayInfo just display info, don't perform check
|
||||
*/
|
||||
public function checkVersion($versionInfo, $displayInfo = false)
|
||||
{
|
||||
if (!$versionInfo) {
|
||||
$application = Application::get();
|
||||
printf("Failed to load version info from %s\n", $application->getVersionDescriptorUrl());
|
||||
exit(7);
|
||||
}
|
||||
|
||||
$dbVersion = VersionCheck::getCurrentDBVersion();
|
||||
$codeVersion = VersionCheck::getCurrentCodeVersion();
|
||||
$latestVersion = $versionInfo['version'];
|
||||
|
||||
printf("Code version: %s\n", $codeVersion->getVersionString(false));
|
||||
printf("Database version: %s\n", $dbVersion->getVersionString(false));
|
||||
printf("Latest version: %s\n", $latestVersion->getVersionString(false));
|
||||
|
||||
$compare1 = $codeVersion->compare($latestVersion);
|
||||
$compare2 = $dbVersion->compare($codeVersion);
|
||||
|
||||
if (!$displayInfo) {
|
||||
if ($compare2 < 0) {
|
||||
printf("Database version is older than code version\n");
|
||||
printf("Run \"{$this->scriptName} upgrade\" to update\n");
|
||||
} elseif ($compare2 > 0) {
|
||||
printf("Database version is newer than code version!\n");
|
||||
} elseif ($compare1 == 0) {
|
||||
printf("Your system is up-to-date\n");
|
||||
} elseif ($compare1 < 0) {
|
||||
printf("A newer version is available:\n");
|
||||
$displayInfo = true;
|
||||
} else {
|
||||
printf("Current version is newer than latest!\n");
|
||||
}
|
||||
}
|
||||
|
||||
if ($displayInfo) {
|
||||
printf(" tag: %s\n", $versionInfo['tag']);
|
||||
printf(" date: %s\n", $versionInfo['date']);
|
||||
printf(" info: %s\n", $versionInfo['info']);
|
||||
printf(" package: %s\n", $versionInfo['package']);
|
||||
}
|
||||
|
||||
return $compare1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prompt user for yes/no input (default no).
|
||||
*
|
||||
* @param string $prompt
|
||||
*/
|
||||
public function promptContinue($prompt = 'Continue?')
|
||||
{
|
||||
printf('%s [y/N] ', $prompt);
|
||||
$continue = fread(STDIN, 255);
|
||||
return (strtolower(substr(trim($continue), 0, 1)) == 'y');
|
||||
}
|
||||
|
||||
/**
|
||||
* Log install message to stdout.
|
||||
*
|
||||
* @param string $message
|
||||
*/
|
||||
public function log($message)
|
||||
{
|
||||
printf("%s [%s]\n", date('Y-m-d H:i:s'), $message);
|
||||
}
|
||||
}
|
||||
|
||||
if (!PKP_STRICT_MODE) {
|
||||
class_alias('\PKP\cliTool\UpgradeTool', '\UpgradeTool');
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user