Merged in feature/PMC-563 (pull request #6868)
PMC-563 Approved-by: Paula Quispe <paula.quispe@processmaker.com> Approved-by: Julio Cesar Laura Avendaño <contact@julio-laura.com>
This commit is contained in:
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;
|
||||
}
|
||||
}
|
||||
@@ -243,39 +243,6 @@ class System
|
||||
return $items;
|
||||
}
|
||||
|
||||
/**
|
||||
* Review the checksum.txt
|
||||
*
|
||||
* @return array $result
|
||||
*/
|
||||
public static function verifyChecksum()
|
||||
{
|
||||
if (!file_exists(PATH_TRUNK . "checksum.txt")) {
|
||||
return false;
|
||||
}
|
||||
$lines = explode("\n", file_get_contents(PATH_TRUNK . "checksum.txt"));
|
||||
$result = array("diff" => array(), "missing" => array()
|
||||
);
|
||||
foreach ($lines as $line) {
|
||||
if (empty($line)) {
|
||||
continue;
|
||||
}
|
||||
list ($checksum, $empty, $filename) = explode(" ", $line);
|
||||
//Skip xmlform because these files always change.
|
||||
if (strpos($filename, "/xmlform/") !== false) {
|
||||
continue;
|
||||
}
|
||||
if (file_exists(realpath($filename))) {
|
||||
if (strcmp($checksum, G::encryptFileOld(realpath($filename))) != 0) {
|
||||
$result['diff'][] = $filename;
|
||||
}
|
||||
} else {
|
||||
$result['missing'][] = $filename;
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function checks files to do updated to pm
|
||||
*
|
||||
|
||||
@@ -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