PMC-570
This commit is contained in:
@@ -519,13 +519,15 @@ class database extends database_base
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* execute a sql query
|
* Execute a sql query
|
||||||
*
|
*
|
||||||
* @param string $query
|
* @param string $query
|
||||||
|
* @param bool $throwError
|
||||||
|
*
|
||||||
* @return array
|
* @return array
|
||||||
* @throws Exception
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
public function executeQuery($query)
|
public function executeQuery($query, $throwError = false)
|
||||||
{
|
{
|
||||||
$this->logQuery($query);
|
$this->logQuery($query);
|
||||||
|
|
||||||
@@ -545,9 +547,13 @@ class database extends database_base
|
|||||||
return $result;
|
return $result;
|
||||||
} catch (Exception $exception) {
|
} catch (Exception $exception) {
|
||||||
$this->logQuery($exception->getMessage());
|
$this->logQuery($exception->getMessage());
|
||||||
|
if ($throwError) {
|
||||||
|
throw $exception;
|
||||||
|
} else {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* close the current connection
|
* close the current connection
|
||||||
|
|||||||
@@ -36,6 +36,8 @@ CLI::taskArg('workspace');
|
|||||||
/*----------------------------------********---------------------------------*/
|
/*----------------------------------********---------------------------------*/
|
||||||
CLI::taskRun("run_unify_database");
|
CLI::taskRun("run_unify_database");
|
||||||
/*----------------------------------********---------------------------------*/
|
/*----------------------------------********---------------------------------*/
|
||||||
|
CLI::taskName('upgrade-query');
|
||||||
|
CLI::taskRun('runUpgradeQuery');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Execute the upgrade
|
* Execute the upgrade
|
||||||
@@ -299,3 +301,25 @@ function run_unify_database($args)
|
|||||||
$flag = G::isPMUnderUpdating(0);
|
$flag = G::isPMUnderUpdating(0);
|
||||||
}
|
}
|
||||||
/*----------------------------------********---------------------------------*/
|
/*----------------------------------********---------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute a query, used internally for upgrade process
|
||||||
|
*
|
||||||
|
* @param array $options
|
||||||
|
*/
|
||||||
|
function runUpgradeQuery($options)
|
||||||
|
{
|
||||||
|
// Initializing variables
|
||||||
|
$workspaceName = $options[0];
|
||||||
|
$query = base64_decode($options[1]);
|
||||||
|
$isRbac = (bool)$options[2];
|
||||||
|
|
||||||
|
// Creating a new instance of the extended class
|
||||||
|
$workspace = new WorkspaceTools($workspaceName);
|
||||||
|
|
||||||
|
// Execute the query
|
||||||
|
$workspace->upgradeQuery($query, $isRbac);
|
||||||
|
|
||||||
|
// Terminate without error
|
||||||
|
exit('success');
|
||||||
|
}
|
||||||
|
|||||||
@@ -4623,4 +4623,16 @@ class WorkspaceTools
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute a query, used internally for the upgrade process
|
||||||
|
*
|
||||||
|
* @param string $query
|
||||||
|
* @param bool $rbac
|
||||||
|
*/
|
||||||
|
public function upgradeQuery($query, $rbac)
|
||||||
|
{
|
||||||
|
$database = $this->getDatabase($rbac);
|
||||||
|
$database->executeQuery($query, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
98
workflow/engine/src/ProcessMaker/Core/ProcessesManager.php
Normal file
98
workflow/engine/src/ProcessMaker/Core/ProcessesManager.php
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace ProcessMaker\Core;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class to manage the processes that runs in the shell
|
||||||
|
*/
|
||||||
|
class ProcessesManager
|
||||||
|
{
|
||||||
|
// Class properties
|
||||||
|
private $processes;
|
||||||
|
private $sleepTime = 1;
|
||||||
|
private $terminated = [];
|
||||||
|
private $errors = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class constructor
|
||||||
|
*
|
||||||
|
* @param array $processes
|
||||||
|
*/
|
||||||
|
public function __construct(array $processes)
|
||||||
|
{
|
||||||
|
$this->processes = $processes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the list of terminated processes
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getTerminated()
|
||||||
|
{
|
||||||
|
return $this->terminated;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the list of processes with errors
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getErrors()
|
||||||
|
{
|
||||||
|
return $this->errors;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the sleep time after each statuses revision
|
||||||
|
*
|
||||||
|
* @param int $sleepTime
|
||||||
|
*/
|
||||||
|
public function setSleepTime($sleepTime)
|
||||||
|
{
|
||||||
|
$this->sleepTime = $sleepTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run the processes
|
||||||
|
*/
|
||||||
|
public function run()
|
||||||
|
{
|
||||||
|
// Start all processes
|
||||||
|
foreach ($this->processes as $process) {
|
||||||
|
$process->run();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Manage the processes
|
||||||
|
$this->manage();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Manage all started processes
|
||||||
|
*/
|
||||||
|
private function manage()
|
||||||
|
{
|
||||||
|
do {
|
||||||
|
// Check all remaining processes
|
||||||
|
foreach ($this->processes as $index => $process) {
|
||||||
|
// If the process has finished, save the info and destroy it
|
||||||
|
if ($process->getStatus() === RunProcess::TERMINATED || $process->getStatus() === RunProcess::ERROR) {
|
||||||
|
$processInfo = ['command' => $process->getCommand(), 'rawAnswer' => $process->getRawAnswer()];
|
||||||
|
if ($process->getStatus() === RunProcess::TERMINATED) {
|
||||||
|
// Processes completed successfully
|
||||||
|
$this->terminated[] = $processInfo;
|
||||||
|
} else {
|
||||||
|
// Processes completed with errors
|
||||||
|
$this->errors[] = $processInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Destroy the process
|
||||||
|
unset($this->processes[$index]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Waiting...
|
||||||
|
sleep($this->sleepTime);
|
||||||
|
} while (!empty($this->processes));
|
||||||
|
}
|
||||||
|
}
|
||||||
146
workflow/engine/src/ProcessMaker/Core/RunProcess.php
Normal file
146
workflow/engine/src/ProcessMaker/Core/RunProcess.php
Normal file
@@ -0,0 +1,146 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace ProcessMaker\Core;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class run a command in shell and stores the pointer to him
|
||||||
|
*/
|
||||||
|
class RunProcess
|
||||||
|
{
|
||||||
|
// Class constants
|
||||||
|
const TERMINATED = 'terminated';
|
||||||
|
const RUNNING = 'running';
|
||||||
|
const NOT_RUNNING = 'not_running';
|
||||||
|
const ERROR = 'error';
|
||||||
|
|
||||||
|
// This constant can be overrides in the child class according to the command response, always should be have a value
|
||||||
|
const EXPECTED_ANSWER = '1';
|
||||||
|
|
||||||
|
// Class properties
|
||||||
|
private $resource;
|
||||||
|
private $command;
|
||||||
|
private $rawAnswer;
|
||||||
|
private $status;
|
||||||
|
private $exitCode;
|
||||||
|
private $pipes;
|
||||||
|
private $descriptors = [
|
||||||
|
['pipe', 'r'],
|
||||||
|
['pipe', 'w'],
|
||||||
|
['pipe', 'w']
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class constructor
|
||||||
|
*
|
||||||
|
* @param string $command
|
||||||
|
*/
|
||||||
|
public function __construct($command)
|
||||||
|
{
|
||||||
|
$this->command = $command;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class destructor, the resource created should be closed
|
||||||
|
*/
|
||||||
|
public function __destruct()
|
||||||
|
{
|
||||||
|
if (is_resource($this->resource)) {
|
||||||
|
proc_close($this->resource);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the command
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getCommand()
|
||||||
|
{
|
||||||
|
return $this->command;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the raw response
|
||||||
|
*
|
||||||
|
* @return string|null
|
||||||
|
*/
|
||||||
|
public function getRawAnswer()
|
||||||
|
{
|
||||||
|
return $this->rawAnswer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the status
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getStatus()
|
||||||
|
{
|
||||||
|
// If already exist a status return this value
|
||||||
|
if ($this->status !== null) {
|
||||||
|
return $this->status;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If doesn't exists a resource the process is not running
|
||||||
|
if (!is_resource($this->resource)) {
|
||||||
|
return self::NOT_RUNNING;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the process is running return this value
|
||||||
|
if ($this->isRunning()) {
|
||||||
|
return self::RUNNING;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the process is not running, parse the response to determine the status
|
||||||
|
$this->rawAnswer = stream_get_contents($this->pipes[1]);
|
||||||
|
$this->status = $this->parseAnswer();
|
||||||
|
|
||||||
|
return $this->status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the exit code
|
||||||
|
*
|
||||||
|
* @return string|null
|
||||||
|
*/
|
||||||
|
public function getExitCode()
|
||||||
|
{
|
||||||
|
return $this->exitCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run the command
|
||||||
|
*/
|
||||||
|
public function run()
|
||||||
|
{
|
||||||
|
$this->resource = proc_open($this->command, $this->descriptors, $this->pipes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process is running?
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function isRunning()
|
||||||
|
{
|
||||||
|
// Get the process status
|
||||||
|
$status = proc_get_status($this->resource);
|
||||||
|
|
||||||
|
// If process is not running get the exit code
|
||||||
|
if ($status['running'] === false) {
|
||||||
|
$this->exitCode = $status['exitcode'];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $status['running'];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process the raw response and compare with the expected answer in order to determine the status
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function parseAnswer()
|
||||||
|
{
|
||||||
|
return $this->rawAnswer === self::EXPECTED_ANSWER ? self::TERMINATED : self::ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace ProcessMaker\Upgrade;
|
||||||
|
|
||||||
|
use ProcessMaker\Core\RunProcess;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extended class to manage the processes that executes a queries in the upgrade process
|
||||||
|
*/
|
||||||
|
class RunProcessUpgradeQuery extends RunProcess
|
||||||
|
{
|
||||||
|
// Class constants
|
||||||
|
const SUCCESS = 'success';
|
||||||
|
const CMD = PHP_BINARY . ' processmaker upgrade-query %s %s %s';
|
||||||
|
const RBAC = '1';
|
||||||
|
const NO_RBAC = '0';
|
||||||
|
|
||||||
|
// Class properties
|
||||||
|
private $workspace;
|
||||||
|
private $sql;
|
||||||
|
private $isRbac;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class constructor
|
||||||
|
*
|
||||||
|
* @param string $workspace
|
||||||
|
* @param string $sql
|
||||||
|
* @param bool $isRbac
|
||||||
|
*/
|
||||||
|
public function __construct($workspace, $sql, $isRbac = false)
|
||||||
|
{
|
||||||
|
// Set properties values
|
||||||
|
$this->workspace = $workspace;
|
||||||
|
$this->sql = $sql;
|
||||||
|
$this->isRbac = $isRbac;
|
||||||
|
|
||||||
|
// Build the command and send to the parent class
|
||||||
|
parent::__construct($this->buildCommand());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Override the parent method in order to compare the raw response with the SUCCESS value
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function parseAnswer()
|
||||||
|
{
|
||||||
|
return $this->getRawAnswer() === self::SUCCESS ? parent::TERMINATED : parent::ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build the command to execute a query for the upgrade process
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
private function buildCommand()
|
||||||
|
{
|
||||||
|
return sprintf(self::CMD, $this->workspace, base64_encode($this->sql),
|
||||||
|
($this->isRbac ? self::RBAC : self::NO_RBAC));
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user