Re-implemented CLI to provide help messages.
This commit is contained in:
@@ -1,9 +1,9 @@
|
||||
<?php
|
||||
/**
|
||||
* commands.php
|
||||
* cli.php
|
||||
*
|
||||
* ProcessMaker Open Source Edition
|
||||
* Copyright (C) 2010 Colosa Inc.
|
||||
* Copyright (C) 2011 Colosa Inc.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
@@ -21,6 +21,7 @@
|
||||
* For more information, contact Colosa Inc, 2566 Le Jeune Rd.,
|
||||
* Coral Gables, FL, 33134, USA, or email info@colosa.com.
|
||||
*
|
||||
* @author Alexandre Rosenfeld <alexandre@colosa.com>
|
||||
*/
|
||||
|
||||
/* Windows supports both / and \ as path separators, so use the Unix separator
|
||||
@@ -43,19 +44,30 @@
|
||||
require_once( PATH_THIRDPARTY . 'pake/pakeGetopt.class.php');
|
||||
require_once( PATH_CORE . 'config/environments.php');
|
||||
|
||||
G::LoadClass("cli");
|
||||
|
||||
/* Hide notice, otherwise we get a lot of messages */
|
||||
error_reporting(E_ALL ^ E_NOTICE);
|
||||
ini_set('display_errors', 1);
|
||||
|
||||
// register tasks
|
||||
$dir = PATH_HOME . 'engine/bin/tasks';
|
||||
$tasks = pakeFinder::type('file')->name( 'cli*.php' )->in($dir);
|
||||
|
||||
foreach ($tasks as $task) {
|
||||
include_once($task);
|
||||
// trap -V before pake
|
||||
if (in_array('-v', $argv) || in_array('-V', $argv) || in_array('--version', $argv))
|
||||
{
|
||||
printf("ProcessMaker version %s\n", pakeColor::colorize(trim(file_get_contents( PATH_GULLIVER . 'VERSION')), 'INFO'));
|
||||
exit(0);
|
||||
}
|
||||
|
||||
// run task
|
||||
pakeApp::get_instance()->run(null, null, false);
|
||||
// register tasks
|
||||
//TODO: include plugins
|
||||
$directories = array(PATH_HOME . 'engine/bin/tasks');
|
||||
|
||||
foreach ($directories as $dir) {
|
||||
foreach (glob("$dir/*.php") as $filename) {
|
||||
include_once($filename);
|
||||
}
|
||||
}
|
||||
|
||||
CLI::run();
|
||||
|
||||
exit(0);
|
||||
|
||||
|
||||
@@ -1,5 +1,27 @@
|
||||
<?php
|
||||
/**
|
||||
* cliCommon.php
|
||||
*
|
||||
* ProcessMaker Open Source Edition
|
||||
* Copyright (C) 2011 Colosa Inc.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* For more information, contact Colosa Inc, 2566 Le Jeune Rd.,
|
||||
* Coral Gables, FL, 33134, USA, or email info@colosa.com.
|
||||
*
|
||||
* @author Alexandre Rosenfeld <alexandre@colosa.com>
|
||||
* @package workflow-engine-bin-tasks
|
||||
**/
|
||||
|
||||
@@ -12,130 +34,17 @@ if(sizeof($output) == 3) {
|
||||
}
|
||||
|
||||
/**
|
||||
* From http://www.php.net/manual/en/function.getopt.php#83414
|
||||
* Parses $args for parameters and assigns them to an array.
|
||||
* Returns workspace objects from an array of workspace names.
|
||||
*
|
||||
* Supports:
|
||||
* -e
|
||||
* -e <value>
|
||||
* --long-param
|
||||
* --long-param=<value>
|
||||
* --long-param <value>
|
||||
* <value>
|
||||
*
|
||||
* @param array $noopt List of parameters without values
|
||||
* @param array $args an array of workspace names
|
||||
* @param bool $includeAll if true and no workspace is specified in args,
|
||||
* returns all available workspaces
|
||||
* @return array of workspace objects
|
||||
*/
|
||||
function parse_args($args, $noopt = array()) {
|
||||
$result = array();
|
||||
while (list($tmp, $p) = each($args)) {
|
||||
if ($p{0} == '-') {
|
||||
$pname = substr($p, 1);
|
||||
$value = true;
|
||||
if ($pname{0} == '-') {
|
||||
// long-opt (--<param>)
|
||||
$pname = substr($pname, 1);
|
||||
if (strpos($p, '=') !== false) {
|
||||
// value specified inline (--<param>=<value>)
|
||||
list($pname, $value) = explode('=', substr($p, 2), 2);
|
||||
}
|
||||
}
|
||||
// check if next parameter is a descriptor or a value
|
||||
$nextparm = current($args);
|
||||
if (!in_array($pname, $noopt) && $value === true && $nextparm !== false && $nextparm{0} != '-') list($tmp, $value) = each($args);
|
||||
$result[$pname] = $value;
|
||||
} else {
|
||||
// param doesn't belong to any option
|
||||
$result[] = $p;
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
function info($message) {
|
||||
return pakeColor::colorize($message, "INFO");
|
||||
}
|
||||
|
||||
function error($message) {
|
||||
return pakeColor::colorize($message, "ERROR");
|
||||
}
|
||||
|
||||
function prompt($message) {
|
||||
echo "$message";
|
||||
$handle = fopen ("php://stdin","r");
|
||||
$line = fgets($handle);
|
||||
return $line;
|
||||
}
|
||||
|
||||
function question($message) {
|
||||
$input = strtolower(prompt("$message [Y/n] "));
|
||||
return (array_search(trim($input), array("y", "")) !== false);
|
||||
}
|
||||
|
||||
function logging($message, $filename = NULL) {
|
||||
static $log_file = NULL;
|
||||
if (isset($filename)) {
|
||||
$log_file = fopen($filename, "a");
|
||||
fwrite($log_file, " -- " . date("c") . " " . $message . " --\n");
|
||||
} else {
|
||||
if (isset($log_file))
|
||||
fwrite($log_file, $message);
|
||||
echo $message;
|
||||
}
|
||||
}
|
||||
|
||||
function progress($done, $total, $size=30) {
|
||||
|
||||
static $start_time;
|
||||
|
||||
// if we go over our bound, just ignore it
|
||||
if($done > $total) return;
|
||||
|
||||
if(empty($start_time)) $start_time=time();
|
||||
$now = time();
|
||||
|
||||
$perc=(double)($done/$total);
|
||||
|
||||
$bar=floor($perc*$size);
|
||||
|
||||
$status_bar="\r[";
|
||||
$status_bar.=str_repeat("=", $bar);
|
||||
if($bar<$size){
|
||||
$status_bar.=">";
|
||||
$status_bar.=str_repeat(" ", $size-$bar);
|
||||
} else {
|
||||
$status_bar.="=";
|
||||
}
|
||||
|
||||
$disp=number_format($perc*100, 0);
|
||||
|
||||
$status_bar.="] $disp% $done/$total";
|
||||
|
||||
$rate = ($now-$start_time)/$done;
|
||||
$left = $total - $done;
|
||||
$eta = round($rate * $left, 2);
|
||||
|
||||
$elapsed = $now - $start_time;
|
||||
|
||||
$status_bar.= " remaining: ".number_format($eta)." sec. elapsed: ".number_format($elapsed)." sec.";
|
||||
|
||||
echo "$status_bar ";
|
||||
|
||||
flush();
|
||||
|
||||
// when done, send a newline
|
||||
if($done == $total) {
|
||||
echo "\n";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function get_workspaces_from_args($args, $includeAll = true) {
|
||||
$opts = parse_args($args);
|
||||
$workspaces = array();
|
||||
foreach ($opts as $opt => $arg) {
|
||||
if (is_int($opt)) {
|
||||
$workspaces[] = new workspaceTools($arg);
|
||||
}
|
||||
foreach ($args as $arg) {
|
||||
$workspaces[] = new workspaceTools($arg);
|
||||
}
|
||||
if (empty($workspaces) && $includeAll) {
|
||||
$workspaces = System::listWorkspaces();
|
||||
|
||||
@@ -1,60 +1,109 @@
|
||||
<?php
|
||||
/**
|
||||
* cliUpgrade.php
|
||||
*
|
||||
* ProcessMaker Open Source Edition
|
||||
* Copyright (C) 2011 Colosa Inc.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* For more information, contact Colosa Inc, 2566 Le Jeune Rd.,
|
||||
* Coral Gables, FL, 33134, USA, or email info@colosa.com.
|
||||
*
|
||||
* @author Alexandre Rosenfeld <alexandre@colosa.com>
|
||||
* @package workflow-engine-bin-tasks
|
||||
**/
|
||||
|
||||
G::LoadClass("system");
|
||||
G::LoadClass("wsTools");
|
||||
|
||||
pake_task("upgrade");
|
||||
CLI::taskName('upgrade');
|
||||
CLI::taskDescription(<<<EOT
|
||||
Upgrade workspaces.
|
||||
|
||||
This command should be run after ProcessMaker files are upgraded so that all
|
||||
workspaces are upgraded to the current version.
|
||||
EOT
|
||||
);
|
||||
CLI::taskRun(run_upgrade);
|
||||
|
||||
|
||||
/**
|
||||
* A versoni of rm_dir which does not exits on error.
|
||||
*
|
||||
* @param string $filename directory or file to remove
|
||||
* @param bool $filesOnly either to remove the containing directory as well or not
|
||||
*/
|
||||
function rm_dir($filename, $filesOnly = false) {
|
||||
if (is_file($filename)) {
|
||||
@unlink($filename) or CLI::message(CLI::error("Could not remove file $filename")."\n");;
|
||||
} else {
|
||||
foreach(glob("$filename/*") as $f) {
|
||||
rm_dir($f);
|
||||
}
|
||||
if (!$filesOnly)
|
||||
@rmdir($filename) or CLI::message(CLI::error("Could not remove directory $filename")."\n");
|
||||
}
|
||||
}
|
||||
|
||||
function run_upgrade($command, $args) {
|
||||
logging("UPGRADE", PROCESSMAKER_PATH . "upgrade.log");
|
||||
logging("Checking files integrity...\n");
|
||||
CLI::logging("UPGRADE", PROCESSMAKER_PATH . "upgrade.log");
|
||||
CLI::logging("Checking files integrity...\n");
|
||||
$checksum = System::verifyChecksum();
|
||||
if ($checksum === false) {
|
||||
logging(error("checksum.txt not found, integrity check is not possible") . "\n");
|
||||
if (!question("Integrity check failed, do you want to continue the upgrade?")) {
|
||||
logging("Upgrade failed\n");
|
||||
CLI::logging(CLI::error("checksum.txt not found, integrity check is not possible") . "\n");
|
||||
if (!CLI::question("Integrity check failed, do you want to continue the upgrade?")) {
|
||||
CLI::logging("Upgrade failed\n");
|
||||
die();
|
||||
}
|
||||
} else {
|
||||
if (!empty($checksum['missing'])) {
|
||||
logging(error("The following files were not found in the installation:")."\n");
|
||||
CLI::logging(CLI::error("The following files were not found in the installation:")."\n");
|
||||
foreach($checksum['missing'] as $missing) {
|
||||
logging(" $missing\n");
|
||||
CLI::logging(" $missing\n");
|
||||
}
|
||||
}
|
||||
if (!empty($checksum['diff'])) {
|
||||
logging(error("The following files have modifications:")."\n");
|
||||
CLI::logging(CLI::error("The following files have modifications:")."\n");
|
||||
foreach($checksum['diff'] as $diff) {
|
||||
logging(" $diff\n");
|
||||
CLI::logging(" $diff\n");
|
||||
}
|
||||
}
|
||||
if (!(empty($checksum['missing']) || empty($checksum['diff']))) {
|
||||
if (!question("Integrity check failed, do you want to continue the upgrade?")) {
|
||||
logging("Upgrade failed\n");
|
||||
if (!CLI::question("Integrity check failed, do you want to continue the upgrade?")) {
|
||||
CLI::logging("Upgrade failed\n");
|
||||
die();
|
||||
}
|
||||
}
|
||||
}
|
||||
logging("Clearing cache...\n");
|
||||
CLI::logging("Clearing cache...\n");
|
||||
if(defined('PATH_C'))
|
||||
G::rm_dir(PATH_C);
|
||||
rm_dir(PATH_C, true);
|
||||
$workspaces = get_workspaces_from_args($args);
|
||||
$count = count($workspaces);
|
||||
$first = true;
|
||||
foreach ($workspaces as $index => $workspace) {
|
||||
try {
|
||||
logging("Upgrading workspaces ($index/$count): " . info($workspace->name) . "\n");
|
||||
CLI::logging("Upgrading workspaces ($index/$count): " . CLI::info($workspace->name) . "\n");
|
||||
$workspace->upgrade($first);
|
||||
$workspace->close();
|
||||
$first = false;
|
||||
} catch (Exception $e) {
|
||||
logging("Errors upgrading workspace " . info($workspace->name) . ": " . error($e->getMessage()) . "\n");
|
||||
CLI::logging("Errors upgrading workspace " . CLI::info($workspace->name) . ": " . CLI::error($e->getMessage()) . "\n");
|
||||
}
|
||||
}
|
||||
logging("Upgrade successful\n");
|
||||
CLI::logging("Upgrade successful\n");
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
@@ -1,38 +1,160 @@
|
||||
<?php
|
||||
/**
|
||||
* cliWorkspaces.php
|
||||
*
|
||||
* ProcessMaker Open Source Edition
|
||||
* Copyright (C) 2011 Colosa Inc.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* For more information, contact Colosa Inc, 2566 Le Jeune Rd.,
|
||||
* Coral Gables, FL, 33134, USA, or email info@colosa.com.
|
||||
*
|
||||
* @author Alexandre Rosenfeld <alexandre@colosa.com>
|
||||
* @package workflow-engine-bin-tasks
|
||||
**/
|
||||
|
||||
pake_task('info');
|
||||
CLI::taskName('info');
|
||||
CLI::taskDescription(<<<EOT
|
||||
Print information about the current system and specified workspaces.
|
||||
EOT
|
||||
);
|
||||
CLI::taskArg('workspace-name', true, true);
|
||||
CLI::taskRun(run_info);
|
||||
|
||||
pake_task('workspace-upgrade');
|
||||
CLI::taskName('workspace-backup');
|
||||
CLI::taskDescription(<<<EOT
|
||||
Backup the specified workspace to an archive.
|
||||
|
||||
pake_task('workspace-backup');
|
||||
pake_task('workspace-restore');
|
||||
BACKUP-NAME is the backup filename. If it contains slashes, it will be
|
||||
treated as a filename, either absolute or relative. Otherwise it will be
|
||||
treated as a filename inside the backups directory in the 'shared' folder.
|
||||
If no BACKUP-NAME is specified, it will use the workspace name as the
|
||||
filename.
|
||||
|
||||
pake_task('translation-upgrade');
|
||||
pake_task('cacheview-upgrade');
|
||||
A backup archive will contain all information about the specified workspace
|
||||
so that it can be restored later. A database dump will be created and all
|
||||
the workspace files will be included in the archive.
|
||||
EOT
|
||||
);
|
||||
CLI::taskArg('workspace', false);
|
||||
CLI::taskArg('backup-file', true);
|
||||
CLI::taskRun(run_workspace_backup);
|
||||
|
||||
pake_task('database-upgrade');
|
||||
pake_task('database-check');
|
||||
CLI::taskName('workspace-restore');
|
||||
CLI::taskDescription(<<<EOT
|
||||
Restore a workspace from a backup.
|
||||
|
||||
pake_task('plugins-database-upgrade');
|
||||
BACKUP-NAME is the backup filename. If it contains slashes, it will be
|
||||
treated as a filename, either absolute or relative. Otherwise it will be
|
||||
treated as a filename inside the backups directory in the 'shared' folder.
|
||||
|
||||
pake_task('database-export');
|
||||
pake_task('database-import');
|
||||
If WORKSPACE is specified, it will be used as the workspace to restore to,
|
||||
otherwise the workspace will be restored using the same name as before.
|
||||
EOT
|
||||
);
|
||||
CLI::taskArg('backup-file', false);
|
||||
CLI::taskArg('workspace', true);
|
||||
CLI::taskRun(run_workspace_restore);
|
||||
|
||||
pake_task('drafts-clean');
|
||||
CLI::taskName('cacheview-repair');
|
||||
CLI::taskDescription(<<<EOT
|
||||
Create and populate APP_CACHE_VIEW
|
||||
|
||||
function run_info($command, $args) {
|
||||
You can specify as many workspaces as you want and if no workspace is
|
||||
specified, it will run the upgrade on all available workspaces.
|
||||
|
||||
In order to improve the performance, ProcessMaker includes a cache of cases
|
||||
in the table APP_CACHE_VIEW. This table must be in sync with the database
|
||||
to present the right information in the inbox. This command will create the
|
||||
table and populate it with the right information. You only need to use this
|
||||
command after upgrading or if the inbox is out of sync.
|
||||
EOT
|
||||
);
|
||||
CLI::taskArg('workspace', true, true);
|
||||
CLI::taskRun(run_cacheview_upgrade);
|
||||
|
||||
CLI::taskName('database-upgrade');
|
||||
CLI::taskDescription(<<<EOT
|
||||
Repair the database schema to the latest version
|
||||
|
||||
You can specify as many workspaces as you want and if no workspace is
|
||||
specified, it will run the upgrade on all available workspaces.
|
||||
|
||||
This command will read the system schema and attempt to modify the workspaces
|
||||
tables to this new schema. This is useful after an upgrade when the workspace
|
||||
database is not upgraded or when the database does not contain the right
|
||||
schema.
|
||||
EOT
|
||||
);
|
||||
CLI::taskArg('workspace', true, true);
|
||||
CLI::taskRun(run_database_upgrade);
|
||||
|
||||
CLI::taskName('plugins-database-upgrade');
|
||||
CLI::taskDescription(<<<EOT
|
||||
Repair the database schema to the latest version
|
||||
|
||||
You can specify as many workspaces as you want and if no workspace is
|
||||
specified, it will run the upgrade on all available workspaces.
|
||||
|
||||
The same as database-upgrade but works with schemas provided by plugins.
|
||||
This is useful if there are installed plugins that include database schemas.
|
||||
EOT
|
||||
);
|
||||
CLI::taskArg('workspace', true, true);
|
||||
CLI::taskRun(run_plugins_database_upgrade);
|
||||
|
||||
CLI::taskName('workspace-upgrade');
|
||||
CLI::taskDescription(<<<EOT
|
||||
Upgrade the workspace(s) specified.
|
||||
|
||||
If no workspace is specified, the command will be run in all workspaces. You
|
||||
can specify more then one workspace.
|
||||
|
||||
This command is a shortcut to execute all upgrade commands in this workspace.
|
||||
Upgrading a workspace will make it corresponds to this version of
|
||||
ProcessMaker. Use this command to upgrade workspaces individually, otherwise
|
||||
use the upgrade command to upgrade the entire system.
|
||||
EOT
|
||||
);
|
||||
CLI::taskArg('workspace-name', true, true);
|
||||
CLI::taskRun(run_workspace_upgrade);
|
||||
|
||||
CLI::taskName('translation-repair');
|
||||
CLI::taskDescription(<<<EOT
|
||||
Upgrade translations for the specified workspace(s).
|
||||
|
||||
If no workspace is specified, the command will be run in all workspaces. You
|
||||
can specify more then one workspace.
|
||||
|
||||
This command will go through each language installed in ProcessMaker and
|
||||
update this workspace translations to match the installed translations.
|
||||
EOT
|
||||
);
|
||||
CLI::taskArg('workspace-name', true, true);
|
||||
CLI::taskRun(run_translation_upgrade);
|
||||
|
||||
function run_info($args, $opts) {
|
||||
$workspaces = get_workspaces_from_args($args, false);
|
||||
System::printSysInfo();
|
||||
workspaceTools::printSysInfo();
|
||||
foreach ($workspaces as $workspace) {
|
||||
echo "\n";
|
||||
$workspace->printMetadata(false);
|
||||
}
|
||||
}
|
||||
|
||||
function run_workspace_upgrade($command, $args) {
|
||||
function run_workspace_upgrade($args, $opts) {
|
||||
$workspaces = get_workspaces_from_args($args);
|
||||
foreach ($workspaces as $workspace) {
|
||||
try {
|
||||
@@ -43,7 +165,7 @@ function run_workspace_upgrade($command, $args) {
|
||||
}
|
||||
}
|
||||
|
||||
function run_translation_upgrade($command, $args) {
|
||||
function run_translation_upgrade($args, $opts) {
|
||||
$workspaces = get_workspaces_from_args($args);
|
||||
$updateXml = true;
|
||||
foreach ($workspaces as $workspace) {
|
||||
@@ -57,7 +179,7 @@ function run_translation_upgrade($command, $args) {
|
||||
}
|
||||
}
|
||||
|
||||
function run_cacheview_upgrade($command, $args) {
|
||||
function run_cacheview_upgrade($args, $opts) {
|
||||
$workspaces = get_workspaces_from_args($args);
|
||||
$updateXml = true;
|
||||
foreach ($workspaces as $workspace) {
|
||||
@@ -70,34 +192,34 @@ function run_cacheview_upgrade($command, $args) {
|
||||
}
|
||||
}
|
||||
|
||||
function run_plugins_database_upgrade($command, $args) {
|
||||
function run_plugins_database_upgrade($args, $opts) {
|
||||
$workspaces = get_workspaces_from_args($args);
|
||||
foreach ($workspaces as $workspace) {
|
||||
try {
|
||||
logging("Upgrading plugins database for " . info($workspace->name) . "\n");
|
||||
CLI::logging("Upgrading plugins database for " . info($workspace->name) . "\n");
|
||||
$workspace->upgradePluginsDatabase();
|
||||
} catch (Exception $e) {
|
||||
logging("Errors upgrading plugins database: " . error($e->getMessage()));
|
||||
CLI::logging("Errors upgrading plugins database: " . error($e->getMessage()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function run_database_export($command, $args) {
|
||||
function run_database_export($args, $opts) {
|
||||
if (count($args) < 2)
|
||||
throw new Exception ("Please provide a workspace name and a directory for export");
|
||||
$workspace = new workspaceTools($args[0]);
|
||||
$workspace->exportDatabase($args[1]);
|
||||
}
|
||||
|
||||
function run_database_import($command, $args) {
|
||||
function run_database_import($args, $opts) {
|
||||
throw new Exception("Not implemented");
|
||||
}
|
||||
|
||||
function run_database_upgrade($task, $args) {
|
||||
function run_database_upgrade($args, $opts) {
|
||||
database_upgrade("upgrade", $args);
|
||||
}
|
||||
|
||||
function run_database_check($task, $args) {
|
||||
function run_database_check($args, $opts) {
|
||||
database_upgrade("check", $args);
|
||||
}
|
||||
|
||||
@@ -136,7 +258,7 @@ function delete_app_from_table($con, $tableName, $appUid, $col="APP_UID") {
|
||||
$rs = $stmt->executeQuery($sql, ResultSet::FETCHMODE_NUM);
|
||||
}
|
||||
|
||||
function run_drafts_clean($task, $args) {
|
||||
function run_drafts_clean($args, $opts) {
|
||||
echo "Cleaning drafts\n";
|
||||
|
||||
if (count($args) < 1)
|
||||
@@ -215,16 +337,25 @@ function run_drafts_clean($task, $args) {
|
||||
echo "\n";
|
||||
}
|
||||
|
||||
function run_workspace_backup($task, $args) {
|
||||
$workspace = new workspaceTools($args[0]);
|
||||
if (isset($args[1]))
|
||||
$filename = $args[1];
|
||||
else
|
||||
$filename = PATH_DATA . "backups/" . $workspace->name . ".tar";
|
||||
$workspace->backup($filename);
|
||||
function run_workspace_backup($args, $opts) {
|
||||
$workspaces = array();
|
||||
if (sizeof($args) > 2) {
|
||||
$filename = array_pop($args);
|
||||
foreach ($args as $arg) {
|
||||
$workspaces[] = new workspaceTools($arg);
|
||||
}
|
||||
} else if (sizeof($args) > 0) {
|
||||
$workspaces[] = new workspaceTools($args[0]);
|
||||
if (sizeof($args) == 2)
|
||||
$filename = $args[1];
|
||||
else
|
||||
$filename = $workspace->name . ".tar.gz";
|
||||
}
|
||||
foreach ($workspaces as $workspace)
|
||||
$workspace->backup($filename);
|
||||
}
|
||||
|
||||
function run_workspace_restore($task, $args) {
|
||||
function run_workspace_restore($args, $opts) {
|
||||
//$workspace = new workspaceTools($args[0]);
|
||||
workspaceTools::restore($args[0], $args[1]);
|
||||
}
|
||||
|
||||
245
workflow/engine/classes/class.cli.php
Normal file
245
workflow/engine/classes/class.cli.php
Normal file
@@ -0,0 +1,245 @@
|
||||
<?php
|
||||
/**
|
||||
* class.cli.php
|
||||
*
|
||||
* ProcessMaker Open Source Edition
|
||||
* Copyright (C) 2011 Colosa Inc.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* For more information, contact Colosa Inc, 2566 Le Jeune Rd.,
|
||||
* Coral Gables, FL, 33134, USA, or email info@colosa.com.
|
||||
*
|
||||
* @author Alexandre Rosenfeld <alexandre@colosa.com>
|
||||
*/
|
||||
|
||||
class CLI {
|
||||
public static $tasks = array();
|
||||
public static $currentTask = NULL;
|
||||
|
||||
/**
|
||||
* Adds a new task defined by it's name. All other task functions will
|
||||
* remember the current task defined here.
|
||||
*
|
||||
* @param string $name name of the task, used in the command-line
|
||||
*/
|
||||
public static function taskName($name) {
|
||||
self::$currentTask = $name;
|
||||
self::$tasks[$name] = array(
|
||||
'name' => $name,
|
||||
'description' => NULL,
|
||||
'args' => array(),
|
||||
'function' => NULL,
|
||||
'opt' => array('short' => '', 'long' => array())
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a description to the current task. The description should contain a
|
||||
* one-line description of the command and a few lines of text with more
|
||||
* information.
|
||||
*
|
||||
* @param string $description task description
|
||||
*/
|
||||
public static function taskDescription($description) {
|
||||
assert(self::$currentTask !== NULL);
|
||||
self::$tasks[self::$currentTask]["description"] = $description;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an argument to the current task. The options will affect how it is
|
||||
* displayed in the help command. Optional will put [] in the argument and
|
||||
* multiple will put ... in the end. Arguments are displayed together with
|
||||
* the task name in the help command.
|
||||
*
|
||||
* @param string $name argument name
|
||||
*/
|
||||
public static function taskArg($name, $optional = true, $multiple = false) {
|
||||
assert(self::$currentTask !== NULL);
|
||||
self::$tasks[self::$currentTask]["args"][$name] = array(
|
||||
'optional' => $optional,
|
||||
'multiple' => $multiple
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines short and long options as used by getopt to the current task.
|
||||
*
|
||||
* @param string $short short options
|
||||
* @param array $long long options
|
||||
*/
|
||||
public static function taskOpt($short, $long = array()) {
|
||||
assert(self::$currentTask !== NULL);
|
||||
self::$tasks[self::$currentTask]["opt"] = array('short' => $short, 'long' => $long);
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines the function to run for the current task.
|
||||
*
|
||||
* @param callback $function function to run
|
||||
*/
|
||||
public static function taskRun($function) {
|
||||
assert(self::$currentTask !== NULL);
|
||||
self::$tasks[self::$currentTask]["function"] = $function;
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays the help instructions.
|
||||
*
|
||||
* @param array $args if defined, the task name should be argument 0
|
||||
* @param array $opts options as returned by getopt
|
||||
*/
|
||||
public static function help($args, $opts) {
|
||||
global $argv;
|
||||
$scriptName = $argv[0];
|
||||
$taskName = $args[0];
|
||||
|
||||
if (!$taskName) {
|
||||
echo "usage: $scriptName <task> [options] [args]\n";
|
||||
echo "Type '$scriptName help <task-name>' for help on a specific task\n";
|
||||
echo "\nAvailable tasks:\n";
|
||||
$tasks = array();
|
||||
ksort(self::$tasks);
|
||||
foreach (self::$tasks as $name => $data) {
|
||||
$description = explode("\n", $data['description']);
|
||||
$tasks[] = " $name";
|
||||
}
|
||||
$tasks = join("\n", $tasks);
|
||||
echo $tasks . "\n\n";
|
||||
} else {
|
||||
$valid_args = array();
|
||||
foreach(self::$tasks[$taskName]['args'] as $arg => $data) {
|
||||
$arg = strtoupper($arg);
|
||||
if ($data['multiple'])
|
||||
$arg = "$arg...";
|
||||
if ($data['optional'])
|
||||
$arg = "[$arg]";
|
||||
$valid_args[] = $arg;
|
||||
}
|
||||
$valid_args = join(" ", $valid_args);
|
||||
$description = explode("\n", self::$tasks[$taskName]['description']);
|
||||
$taskDescription = trim(array_shift($description));
|
||||
$description = trim(implode("\n", $description));
|
||||
$message = <<< EOT
|
||||
$taskName: {$taskDescription}
|
||||
Usage: $scriptName $taskName $valid_args
|
||||
|
||||
$description
|
||||
|
||||
EOT;
|
||||
if ($valid_options) {
|
||||
$message .= <<< EOT
|
||||
Options:
|
||||
$valid_options
|
||||
|
||||
EOT;
|
||||
}
|
||||
echo $message . "\n";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the CLI task, which will check which command is specified and run it.
|
||||
*/
|
||||
public static function run() {
|
||||
CLI::taskName("help");
|
||||
CLI::taskRun(array('self', 'help'));
|
||||
global $argv;
|
||||
$args = $argv;
|
||||
$cliname = array_shift($args);
|
||||
$taskName = array_shift($args);
|
||||
while ($taskName{0} == '-')
|
||||
$taskName = array_shift($args);
|
||||
if (!$taskName) {
|
||||
self::help();
|
||||
return;
|
||||
}
|
||||
$taskData = NULL;
|
||||
foreach (self::$tasks as $name => $data) {
|
||||
if (strcasecmp($name, $taskName) === 0) {
|
||||
$taskData = $data;
|
||||
break;
|
||||
}
|
||||
}
|
||||
G::LoadThirdParty('pear/Console', 'Getopt');
|
||||
$short = "h" . $taskData['opt']['short'];
|
||||
$long = array_merge(array("help"), $taskData['opt']['long']);
|
||||
list($options, $arguments) = Console_GetOpt::getopt2($args, $short, $long);
|
||||
call_user_func($taskData['function'], $arguments, $options);
|
||||
die();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an information colorized version of the message.
|
||||
*
|
||||
* @param string $message the message to colorize
|
||||
*/
|
||||
public static function info($message) {
|
||||
return pakeColor::colorize($message, "INFO");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an error colorized version of the message.
|
||||
*
|
||||
* @param string $message the message to colorize
|
||||
*/
|
||||
public static function error($message) {
|
||||
return pakeColor::colorize($message, "ERROR");
|
||||
}
|
||||
|
||||
/**
|
||||
* Prompt the user for information.
|
||||
*
|
||||
* @param string $message the message to display
|
||||
* @return string the text typed by the user
|
||||
*/
|
||||
public static function prompt($message) {
|
||||
echo "$message";
|
||||
$handle = fopen ("php://stdin","r");
|
||||
$line = fgets($handle);
|
||||
return $line;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ask a question of yes or no.
|
||||
*
|
||||
* @param string $message the message to display
|
||||
* @return bool true if the user choosed no, false otherwise
|
||||
*/
|
||||
public static function question($message) {
|
||||
$input = strtolower(self::prompt("$message [Y/n] "));
|
||||
return (array_search(trim($input), array("y", "")) !== false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display a message to the user. If filename is specified, it will setup
|
||||
* a logging file where all messages will be recorded.
|
||||
*
|
||||
* @param string $message the message to display
|
||||
* @param string $filename the log file to write messages
|
||||
*/
|
||||
public static function logging($message, $filename = NULL) {
|
||||
static $log_file = NULL;
|
||||
if (isset($filename)) {
|
||||
$log_file = fopen($filename, "a");
|
||||
fwrite($log_file, " -- " . date("c") . " " . $message . " --\n");
|
||||
} else {
|
||||
if (isset($log_file))
|
||||
fwrite($log_file, $message);
|
||||
echo $message;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -8,6 +8,7 @@
|
||||
*/
|
||||
|
||||
G::LoadSystem('dbMaintenance');
|
||||
G::LoadClass("cli");
|
||||
|
||||
class workspaceTools {
|
||||
var $name = NULL;
|
||||
@@ -51,11 +52,11 @@ class workspaceTools {
|
||||
* @param bool $first true if this is the first workspace to be upgrade
|
||||
*/
|
||||
public function upgrade($first = false) {
|
||||
logging("> Updating database...\n");
|
||||
CLI::logging("> Updating database...\n");
|
||||
$this->upgradeDatabase();
|
||||
logging("> Updating translations...\n");
|
||||
CLI::logging("> Updating translations...\n");
|
||||
$this->upgradeTranslation($first);
|
||||
logging("> Updating cache view...\n");
|
||||
CLI::logging("> Updating cache view...\n");
|
||||
$this->upgradeCacheView();
|
||||
}
|
||||
|
||||
@@ -135,7 +136,7 @@ class workspaceTools {
|
||||
$this->resetDBNames = $resetDBNames;
|
||||
$this->resetDBDiff = array();
|
||||
|
||||
logging("Resetting db info\n");
|
||||
CLI::logging("Resetting db info\n");
|
||||
if (!$this->workspaceExists())
|
||||
throw new Exception("Could not find db.php in the restore");
|
||||
$sDbFile = file_get_contents($this->dbPath);
|
||||
@@ -258,7 +259,7 @@ class workspaceTools {
|
||||
G::LoadThirdParty('pear/json', 'class.json');
|
||||
$languages = new languages();
|
||||
foreach (System::listPoFiles() as $poFile) {
|
||||
logging("Updating language ".basename($poFile)."\n");
|
||||
CLI::logging("Updating language ".basename($poFile)."\n");
|
||||
$languages->importLanguage($poFile, $updateXml);
|
||||
}
|
||||
}
|
||||
@@ -389,13 +390,13 @@ class workspaceTools {
|
||||
$currentUserIsSuper = true;
|
||||
}
|
||||
|
||||
logging("Creating table");
|
||||
CLI::logging("Creating table");
|
||||
//now check if table APPCACHEVIEW exists, and it have correct number of fields, etc.
|
||||
if (!$checkOnly) {
|
||||
$res = $appCache->checkAppCacheView();
|
||||
}
|
||||
|
||||
logging(", triggers");
|
||||
CLI::logging(", triggers");
|
||||
//now check if we have the triggers installed
|
||||
$triggers = array();
|
||||
$triggers[] = $appCache->triggerAppDelegationInsert($lang, $checkOnly);
|
||||
@@ -404,12 +405,12 @@ class workspaceTools {
|
||||
$triggers[] = $appCache->triggerApplicationDelete($lang, $checkOnly);
|
||||
|
||||
if (!$checkOnly) {
|
||||
logging(", filling cache view");
|
||||
CLI::logging(", filling cache view");
|
||||
//build using the method in AppCacheView Class
|
||||
$res = $appCache->fillAppCacheView($lang);
|
||||
logging(".");
|
||||
CLI::logging(".");
|
||||
}
|
||||
logging("\n");
|
||||
CLI::logging("\n");
|
||||
//set status in config table
|
||||
$confParams = Array(
|
||||
'LANG' => $lang,
|
||||
@@ -432,7 +433,7 @@ class workspaceTools {
|
||||
foreach (System::getPlugins() as $pluginName) {
|
||||
$pluginSchema = System::getPluginSchema($pluginName);
|
||||
if ($pluginSchema !== false) {
|
||||
logging("Updating plugin " . info($pluginName) . "\n");
|
||||
CLI::logging("Updating plugin " . CLI::info($pluginName) . "\n");
|
||||
$this->upgradeSchema($pluginSchema);
|
||||
}
|
||||
}
|
||||
@@ -483,7 +484,7 @@ class workspaceTools {
|
||||
|
||||
$oDataBase->logQuery ( count ($changes ) );
|
||||
|
||||
logging( "" . count($changes['tablesToAdd']) . " tables to add");
|
||||
CLI::logging( "" . count($changes['tablesToAdd']) . " tables to add");
|
||||
foreach ($changes['tablesToAdd'] as $sTable => $aColumns) {
|
||||
$oDataBase->executeQuery($oDataBase->generateCreateTableSQL($sTable, $aColumns));
|
||||
if (isset($changes['tablesToAdd'][$sTable]['INDEXES'])) {
|
||||
@@ -493,7 +494,7 @@ class workspaceTools {
|
||||
}
|
||||
}
|
||||
|
||||
logging(", " . count($changes['tablesToAlter']) . " tables to alter");
|
||||
CLI::logging(", " . count($changes['tablesToAlter']) . " tables to alter");
|
||||
foreach ($changes['tablesToAlter'] as $sTable => $aActions) {
|
||||
foreach ($aActions as $sAction => $aAction) {
|
||||
foreach ($aAction as $sColumn => $vData) {
|
||||
@@ -512,21 +513,21 @@ class workspaceTools {
|
||||
}
|
||||
}
|
||||
|
||||
logging(", " . count($changes['tablesWithNewIndex']) . " indexes to add");
|
||||
CLI::logging(", " . count($changes['tablesWithNewIndex']) . " indexes to add");
|
||||
foreach ($changes['tablesWithNewIndex'] as $sTable => $aIndexes) {
|
||||
foreach ($aIndexes as $sIndexName => $aIndexFields ) {
|
||||
$oDataBase->executeQuery($oDataBase->generateAddKeysSQL($sTable, $sIndexName, $aIndexFields ));
|
||||
}
|
||||
}
|
||||
|
||||
logging(", " . count($changes['tablesWithNewIndex']) . " indexes to alter");
|
||||
CLI::logging(", " . count($changes['tablesWithNewIndex']) . " indexes to alter");
|
||||
foreach ($changes['tablesToAlterIndex'] as $sTable => $aIndexes) {
|
||||
foreach ($aIndexes as $sIndexName => $aIndexFields ) {
|
||||
$oDataBase->executeQuery($oDataBase->generateDropKeySQL($sTable, $sIndexName ));
|
||||
$oDataBase->executeQuery($oDataBase->generateAddKeysSQL($sTable, $sIndexName, $aIndexFields ));
|
||||
}
|
||||
}
|
||||
logging("\n");
|
||||
CLI::logging("\n");
|
||||
$this->closeDatabase();
|
||||
return true;
|
||||
}
|
||||
@@ -601,7 +602,7 @@ class workspaceTools {
|
||||
|
||||
foreach ($info as $k => $v) {
|
||||
if (is_numeric($k)) $k = "";
|
||||
logging(sprintf("%20s %s\n", $k, pakeColor::colorize($v, 'INFO')));
|
||||
CLI::logging(sprintf("%20s %s\n", $k, pakeColor::colorize($v, 'INFO')));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -615,7 +616,7 @@ class workspaceTools {
|
||||
|
||||
if ($printSysInfo) {
|
||||
workspaceTools::printSysInfo ();
|
||||
logging("\n");
|
||||
CLI::logging("\n");
|
||||
}
|
||||
|
||||
$wfDsn = $fields['DB_ADAPTER'] . '://' . $fields['DB_USER'] . ':' . $fields['DB_PASS'] . '@' . $fields['DB_HOST'] . '/' . $fields['DB_NAME'];
|
||||
@@ -633,7 +634,7 @@ class workspaceTools {
|
||||
|
||||
foreach ($info as $k => $v) {
|
||||
if (is_numeric($k)) $k = "";
|
||||
logging(sprintf("%20s %s\n", $k, pakeColor::colorize($v, 'INFO')));
|
||||
CLI::logging(sprintf("%20s %s\n", $k, pakeColor::colorize($v, 'INFO')));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -652,7 +653,7 @@ class workspaceTools {
|
||||
$dbInfo = $this->getDBCredentials($db);
|
||||
$oDbMaintainer = new DataBaseMaintenance($dbInfo["host"], $dbInfo["user"],
|
||||
$dbInfo["pass"]);
|
||||
logging("Saving database {$dbInfo["name"]}\n");
|
||||
CLI::logging("Saving database {$dbInfo["name"]}\n");
|
||||
$oDbMaintainer->connect($dbInfo["name"]);
|
||||
$oDbMaintainer->lockTables();
|
||||
$oDbMaintainer->setTempDir($path . "/");
|
||||
@@ -716,7 +717,7 @@ class workspaceTools {
|
||||
unlink($tempDirectory);
|
||||
mkdir($tempDirectory);
|
||||
$metadata = $this->getMetadata();
|
||||
logging("Backing up database...\n");
|
||||
CLI::logging("Backing up database...\n");
|
||||
$metadata["databases"] = $this->exportDatabase($tempDirectory);
|
||||
$metadata["directories"] = array("{$this->name}.files");
|
||||
$metadata["version"] = 1;
|
||||
@@ -727,9 +728,9 @@ class workspaceTools {
|
||||
file_put_contents($metaFilename,
|
||||
str_replace(array(",", "{", "}"), array(",\n ", "{\n ", "\n}\n"),
|
||||
G::json_encode($metadata)));
|
||||
logging("Copying database to backup...\n");
|
||||
CLI::logging("Copying database to backup...\n");
|
||||
$this->addToBackup($backup, $tempDirectory, $tempDirectory);
|
||||
logging("Copying files to backup...\n");
|
||||
CLI::logging("Copying files to backup...\n");
|
||||
|
||||
$this->addToBackup($backup, $this->path, $this->path, "{$this->name}.files");
|
||||
//Remove leftovers.
|
||||
@@ -764,7 +765,7 @@ class workspaceTools {
|
||||
if ($result === false)
|
||||
throw new Exception("Unable to drop user: " . mysql_error ());
|
||||
}
|
||||
logging("Creating user $username for $hostname\n");
|
||||
CLI::logging("Creating user $username for $hostname\n");
|
||||
$result = mysql_query("CREATE USER '$username'@'$hostname' IDENTIFIED BY '$password'");
|
||||
if ($result === false)
|
||||
throw new Exception("Unable to create user: " . mysql_error ());
|
||||
@@ -859,13 +860,13 @@ class workspaceTools {
|
||||
$workspace = new workspaceTools($workspaceName);
|
||||
if ($workspace->workspaceExists())
|
||||
// throw new Exception("Workspace exists");
|
||||
logging("Workspace $workspaceName already exists, overwriting!\n");
|
||||
CLI::logging("Workspace $workspaceName already exists, overwriting!\n");
|
||||
|
||||
if (file_exists($workspace->path))
|
||||
G::rm_dir($workspace->path);
|
||||
|
||||
foreach ($metadata->directories as $dir) {
|
||||
logging("Restoring directory '$dir'\n");
|
||||
CLI::logging("Restoring directory '$dir'\n");
|
||||
|
||||
if (!rename("$tempDirectory/$dir", $workspace->path)) {
|
||||
throw new Exception("There was an error copying the backup files ($tempDirectory/$dir) to the workspace directory {$workspace->path}.\n");
|
||||
@@ -879,7 +880,7 @@ class workspaceTools {
|
||||
|
||||
foreach ($metadata->databases as $db) {
|
||||
$dbName = $newDBNames[$db->name];
|
||||
logging("Restoring database {$db->name} to $dbName\n");
|
||||
CLI::logging("Restoring database {$db->name} to $dbName\n");
|
||||
$workspace->executeSQLScript($dbName, "$tempDirectory/{$db->name}.sql");
|
||||
$workspace->createDBUser($dbName, $db->pass, "localhost", $dbName);
|
||||
$workspace->createDBUser($dbName, $db->pass, "%", $dbName);
|
||||
|
||||
Reference in New Issue
Block a user