From 3d8fdf1443f00d66730c155a3db1538dddf9f475 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julio=20Cesar=20Laura=20Avenda=C3=B1o?= Date: Mon, 18 Mar 2019 13:36:08 -0400 Subject: [PATCH 01/21] PMC-565 --- bootstrap/classaliasmap.php | 1 - workflow/engine/bin/tasks/cliUpgrade.php | 287 +++++++++--------- workflow/engine/bin/tasks/cliWorkspaces.php | 85 +----- workflow/engine/classes/Upgrade.php | 128 -------- workflow/engine/classes/WorkspaceTools.php | 273 ++++++++--------- .../engine/classes/model/AddonsManager.php | 8 +- .../engine/src/ProcessMaker/Core/System.php | 33 -- 7 files changed, 268 insertions(+), 547 deletions(-) delete mode 100644 workflow/engine/classes/Upgrade.php diff --git a/bootstrap/classaliasmap.php b/bootstrap/classaliasmap.php index 62e24f3f0..734997540 100644 --- a/bootstrap/classaliasmap.php +++ b/bootstrap/classaliasmap.php @@ -80,7 +80,6 @@ return array( 'ToolBar' => ToolBar::class, 'Tree' => PmTree::class, 'triggerLibrary' => TriggerLibrary::class, - 'Upgrade' => Upgrade::class, 'workspaceTools' => WorkspaceTools::class, 'wsBase' => WsBase::class, 'wsResponse' => WsResponse::class, diff --git a/workflow/engine/bin/tasks/cliUpgrade.php b/workflow/engine/bin/tasks/cliUpgrade.php index a1d181dcf..d09d3adff 100644 --- a/workflow/engine/bin/tasks/cliUpgrade.php +++ b/workflow/engine/bin/tasks/cliUpgrade.php @@ -5,14 +5,16 @@ use ProcessMaker\Core\System; CLI::taskName('upgrade'); CLI::taskDescription("Upgrade workspaces.\n\n This command should be run after upgrading ProcessMaker to a new version so that all workspaces are also upgraded to the\n new version."); - +CLI::taskOpt('child', "Used by the main upgrade thread", 'child', 'child'); CLI::taskOpt('buildACV', 'If this option is enabled, the Cache View is built.', 'ACV', 'buildACV'); CLI::taskOpt('noxml', 'If this option is enabled, the XML files translation is not built.', 'NoXml', 'no-xml'); +CLI::taskOpt('nomafe', 'If this option is enabled, the MAFE files translation is not built.', 'nomafe', 'no-mafe'); /*----------------------------------********---------------------------------*/ CLI::taskOpt('keep_dyn_content', "Include the DYN_CONTENT_HISTORY value. Ex: --keep_dyn_content", 'i', 'keep_dyn_content'); /*----------------------------------********---------------------------------*/ CLI::taskRun("run_upgrade"); /*----------------------------------********---------------------------------*/ + CLI::taskName('unify-database'); CLI::taskDescription( << $workspace) { - $oneWorkspace = $workspace->name; + // Initializing variables + $globalStartTime = microtime(true); + $numberOfWorkspaces = count($workspaces); + $countWorkspace = 1; + + if ($printHF) { + // Set upgrade flag + if (count($workspaces) === 1) { + // For the specific workspace send in the command + G::isPMUnderUpdating(1, $workspaces[0]->name); + } else { + // For all workspaces + G::isPMUnderUpdating(1); } + + // Print information when start the upgrade process + CLI::logging('UPGRADE LOG INITIALIZED', PROCESSMAKER_PATH . 'upgrade.log'); + CLI::logging("UPGRADE STARTED\n"); } - $flag = G::isPMUnderUpdating(1, $oneWorkspace); - //start to upgrade - $checksum = System::verifyChecksum(); - if ($checksum === false) { - 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"); - $flag = G::isPMUnderUpdating(0); - die(); - } - } else { - if (!empty($checksum['missing'])) { - CLI::logging(CLI::error("The following files were not found in the installation:")."\n"); - foreach ($checksum['missing'] as $missing) { - CLI::logging(" $missing\n"); + + foreach ($workspaces as $workspace) { + if ($mainThread) { + CLI::logging("FOLDERS AND FILES OF THE SYSTEM\n"); + // Upgrade actions for global files + CLI::logging("* Start cleaning compiled folder...\n"); + $start = microtime(true); + if (defined('PATH_C')) { + G::rm_dir(PATH_C); + G::mk_dir(PATH_C, 0777); } - } - if (!empty($checksum['diff'])) { - CLI::logging(CLI::error("The following files have modifications:")."\n"); - foreach ($checksum['diff'] as $diff) { - CLI::logging(" $diff\n"); + CLI::logging("* End cleaning compiled folder...(Completed on " . (microtime(true) - $start) . " seconds)\n"); + + CLI::logging("* Start to remove deprecated files...\n"); + $start = microtime(true); + $workspace->removeDeprecatedFiles(); + CLI::logging("* End to remove deprecated files...(Completed on " . (microtime(true) - $start) . " seconds)\n"); + + CLI::logging("* Start checking Enterprise folder/files...\n"); + $start = microtime(true); + $workspace->verifyFilesOldEnterprise(); + CLI::logging("* End checking Enterprise folder/files...(Completed on " . (microtime(true) - $start) . " seconds)\n"); + + CLI::logging("* Start checking framework paths...\n"); + $start = microtime(true); + $workspace->checkFrameworkPaths(); + CLI::logging("* End checking framework paths...(Completed on " . (microtime(true) - $start) . " seconds)\n"); + + CLI::logging("* Start fixing serialized instance in serverConf.singleton file...\n"); + $start = microtime(true); + $serverConf = ServerConf::getSingleton(); + $serverConf->updateClassNameInFile(); + CLI::logging("* End fixing serialized instance in serverConf.singleton file...(Completed on " . + (microtime(true) - $start) . " seconds)\n"); + + CLI::logging("* Start the safe upgrade for javascript files cached by the browser (Maborak, ExtJs)...\n"); + $start = microtime(true); + G::browserCacheFilesSetUid(); + CLI::logging("* End the safe upgrade for javascript files cached by the browser (Maborak, ExtJs)...(Completed on " . + (microtime(true) - $start) . " seconds)\n"); + + CLI::logging("* Start to backup patch files...\n"); + $arrayPatch = glob(PATH_TRUNK . 'patch-*'); + if ($arrayPatch) { + foreach ($arrayPatch as $value) { + if (file_exists($value)) { + // Copy patch content + $names = pathinfo($value); + $nameFile = $names['basename']; + + $contentFile = file_get_contents($value); + $contentFile = preg_replace("[\n|\r|\n\r]", '', $contentFile); + CLI::logging($contentFile . ' installed (' . $nameFile . ')', PATH_DATA . 'log/upgrades.log'); + + // Move patch file + $newFile = PATH_DATA . $nameFile; + G::rm_dir($newFile); + copy($value, $newFile); + G::rm_dir($value); + } + } } - } - if (!(empty($checksum['missing']) || empty($checksum['diff']))) { - if (!CLI::question("Integrity check failed, do you want to continue the upgrade?")) { - CLI::logging("Upgrade failed\n"); - $flag = G::isPMUnderUpdating(0); - die(); - } - } - } - CLI::logging("Clearing cache...\n"); - if (defined('PATH_C')) { - G::rm_dir(PATH_C); - G::mk_dir(PATH_C, 0777); - } + CLI::logging("* End to backup patch files...(Completed on " . (microtime(true) - $start) . " seconds)\n"); - $count = count($workspaces); - $first = true; - $errors = false; - $countWorkspace = 0; - $buildCacheView = array_key_exists('buildACV', $args); - $flagUpdateXml = !array_key_exists('noxml', $args); - $optionMigrateHistoryData = [ - /*----------------------------------********---------------------------------*/ - 'keepDynContent' => array_key_exists('keep_dyn_content', $args) - /*----------------------------------********---------------------------------*/ - ]; + CLI::logging("* Start to backup log files...\n"); + $start = microtime(true); + $workspace->backupLogFiles(); + CLI::logging("* End to backup log files... (Completed on " . (microtime(true) - $start) . " seconds)\n"); - foreach ($workspaces as $index => $workspace) { - if (empty(config("system.workspace"))) { - define("SYS_SYS", $workspace->name); - config(["system.workspace" => $workspace->name]); + // The previous actions should be executed only the first time + $mainThread = false; } + if ($numberOfWorkspaces === 1) { + // Displaying information of the current workspace to upgrade + CLI::logging("UPGRADING DATABASE AND FILES OF WORKSPACE '{$workspace->name}' ($countWorkspace/$numberOfWorkspaces)\n"); - if (!defined("PATH_DATA_SITE")) { - define("PATH_DATA_SITE", PATH_DATA . "sites" . PATH_SEP . config("system.workspace") . PATH_SEP); - } + // Build parameters + $arrayOptTranslation = [ + 'updateXml' => $updateXmlForms, + 'updateMafe' => $updateMafe + ]; + $optionMigrateHistoryData = [ + 'keepDynContent' => $keepDynContent + ]; - if (!defined('DB_ADAPTER')) { - define('DB_ADAPTER', 'mysql'); - } - - try { - $countWorkspace++; - CLI::logging("Upgrading workspaces ($countWorkspace/$count): " . CLI::info($workspace->name) . "\n"); - $workspace->upgrade($buildCacheView, $workspace->name, false, 'en', ['updateXml' => $flagUpdateXml, 'updateMafe' => $first], $optionMigrateHistoryData); + // Upgrade database and files from a specific workspace + $workspace->upgrade($workspace->name, true, SYS_LANG, $arrayOptTranslation, $optionMigrateHistoryData); $workspace->close(); - $first = false; - $flagUpdateXml = false; - } catch (Exception $e) { - CLI::logging("Errors upgrading workspace " . CLI::info($workspace->name) . ": " . CLI::error($e->getMessage()) . "\n"); - $errors = true; + } else { + // Build arguments + $args = '--child'; + $args .= $updateXmlForms ? '' : ' --no-xml'; + $args .= $updateMafe ? '' : ' --no-mafe'; + $args .= $keepDynContent ? ' --keep_dyn_content' : ''; + + // Build and execute command in another thread + $command = PHP_BINARY . ' processmaker upgrade ' . $args . ' ' . $workspace->name; + passthru($command); } + + // After the first execution is required set this values to false + $updateXmlForms = false; + $updateMafe = false; + + // Increment workspaces counter + $countWorkspace++; } - //Verify the information of the singleton ServConf by changing the name of the class if is required. - CLI::logging("\nCheck/Fix serialized instance in serverConf.singleton file\n\n"); - $serverConf = ServerConf::getSingleton(); - $serverConf->updateClassNameInFile(); + if ($printHF) { + // Print information when finish the upgrade process + CLI::logging('UPGRADE FINISHED (Completed on ' . (microtime(true) - $globalStartTime) . + ' seconds), ProcessMaker ' . System::getVersion() . ' installed)' . "\n\n"); - // SAVE Upgrades/Patches - $arrayPatch = glob(PATH_TRUNK . 'patch-*'); - - if ($arrayPatch) { - foreach ($arrayPatch as $value) { - if (file_exists($value)) { - // copy content the patch - $names = pathinfo($value); - $nameFile = $names['basename']; - - $contentFile = file_get_contents($value); - $contentFile = preg_replace("[\n|\r|\n\r]", '', $contentFile); - CLI::logging($contentFile . ' installed (' . $nameFile . ')', PATH_DATA . 'log/upgrades.log'); - - // move file of patch - $newFile = PATH_DATA . $nameFile; - G::rm_dir($newFile); - copy($value, $newFile); - G::rm_dir($value); - } - } - } else { - CLI::logging('ProcessMaker ' . System::getVersion(). ' installed', PATH_DATA . 'log/upgrades.log'); + // Delete upgrade flag + G::isPMUnderUpdating(0); } - - //Safe upgrade for JavaScript files - CLI::logging("\nSafe upgrade for files cached by the browser\n\n"); - - G::browserCacheFilesSetUid(); - - //Status - if ($errors) { - CLI::logging("Upgrade finished but there were errors upgrading workspaces.\n"); - CLI::logging(CLI::error("Please check the log above to correct any issues.") . "\n"); - } else { - CLI::logging("Upgrade successful\n"); - } - - //setting flag to false - $flag = G::isPMUnderUpdating(0); } -function listFiles($dir) -{ - $files = array(); - $lista = glob($dir.'/*'); - foreach ($lista as $valor) { - if (is_dir($valor)) { - $inner_files = listFiles($valor); - if (is_array($inner_files)) { - $files = array_merge($files, $inner_files); - } - } - if (is_file($valor)) { - array_push($files, $valor); - } - } - return $files; -} /*----------------------------------********---------------------------------*/ function run_unify_database($args) { diff --git a/workflow/engine/bin/tasks/cliWorkspaces.php b/workflow/engine/bin/tasks/cliWorkspaces.php index b6bb6cba4..c04d45158 100644 --- a/workflow/engine/bin/tasks/cliWorkspaces.php +++ b/workflow/engine/bin/tasks/cliWorkspaces.php @@ -103,26 +103,6 @@ EOT CLI::taskArg('workspace', true, true); CLI::taskRun("run_plugins_database_upgrade"); -CLI::taskName('workspace-upgrade'); -CLI::taskDescription(<<name); - } - } -} - -/** - * This function is executed only by one workspace, for the command workspace-upgrade - * - * @param array $args, workspace name for to apply the upgrade - * @param array $opts, specify additional arguments for language, flag for buildACV, flag for noxml - * - * @return void - */ -function workspace_upgrade($args, $opts) { - $first = true; - $workspaces = get_workspaces_from_args($args); - $lang = array_key_exists("lang", $opts) ? $opts['lang'] : 'en'; - $buildCacheView = array_key_exists('buildACV', $opts); - $flagUpdateXml = !array_key_exists('noxml', $opts); - - $wsName = $workspaces[key($workspaces)]->name; - Bootstrap::setConstantsRelatedWs($wsName); - //Loop, read all the attributes related to the one workspace - foreach ($workspaces as $workspace) { - try { - $workspace->upgrade( - $buildCacheView, - $workspace->name, - false, - $lang, - ['updateXml' => $flagUpdateXml, 'updateMafe' => $first] - ); - $first = false; - $flagUpdateXml = false; - } catch (Exception $e) { - G::outRes("Errors upgrading workspace " . CLI::info($workspace->name) . ": " . CLI::error($e->getMessage()) . "\n"); - } - } -} - /** * We will upgrade the CONTENT table * If we apply the command for all workspaces, we will need to execute one by one by redefining the constants @@ -1181,7 +1098,7 @@ function migrate_content($args, $opts) foreach ($workspaces as $workspace) { print_r('Regenerating content in: ' . pakeColor::colorize($workspace->name, 'INFO') . "\n"); CLI::logging("-> Regenerating content \n"); - $workspace->migrateContentRun($workspace->name, $lang); + $workspace->migrateContentRun($lang); } $stop = microtime(true); CLI::logging("<*> Optimizing content data Process took " . ($stop - $start) . " seconds.\n"); diff --git a/workflow/engine/classes/Upgrade.php b/workflow/engine/classes/Upgrade.php deleted file mode 100644 index 67fa51dcf..000000000 --- a/workflow/engine/classes/Upgrade.php +++ /dev/null @@ -1,128 +0,0 @@ -addon = $addon; - } - - public function install() - { - - $filter = new InputFilter(); - $start = microtime(1); - $filename = $this->addon->getDownloadFilename(); - $time = microtime(1); - - $archive = new Archive_Tar ($filename); - $time = microtime(1); - $extractDir = dirname($this->addon->getDownloadFilename()) . "/extract"; - $extractDir = $filter->xssFilterHard($extractDir); - $backupDir = dirname($this->addon->getDownloadFilename()) . "/backup"; - $backupDir = $filter->xssFilterHard($backupDir); - if (file_exists($extractDir)) { - G::rm_dir($extractDir); - } - if (file_exists($backupDir)) { - G::rm_dir($backupDir); - } - if (!is_dir($backupDir)) { - mkdir($backupDir); - } - - $time = microtime(1); - echo "Extracting files...\n"; - $archive->extractModify($extractDir, 'processmaker'); - $checksumFile = file_get_contents("$extractDir/checksum.txt"); - $time = microtime(1); - $checksums = array(); - foreach (explode("\n", $checksumFile) as $line) { - $checksums[trim(substr($line, 33))] = substr($line, 0, 32); - } - - $checksum = array(); - $changedFiles = array(); - $time = microtime(1); - $files = $this->ls_dir($extractDir); - - echo "Updating ProcessMaker files...\n"; - $time = microtime(1); - $checksumTime = 0; - foreach ($checksums as $filename => $checksum) { - if (is_dir("$extractDir/$filename")) { - $filename = $filter->xssFilterHard($filename); - print $filename; - continue; - } - $installedFile = PATH_TRUNK . "/$filename"; - if (!file_exists($installedFile)) { - $installedMD5 = ""; - } else { - $time = microtime(1); - $installedMD5 = G::encryptFileOld($installedFile); - $checksumTime += microtime(1) - $time; - } - $archiveMD5 = $checksum; - if (strcasecmp($archiveMD5, $installedMD5) != 0) { - $changedFiles[] = $filename; - if (!is_dir(dirname($backupDir.'/'.$filename))) { - mkdir(dirname($backupDir.'/'.$filename), 0777, true); - } - if (file_exists($installedFile) && is_file($installedFile)) { - copy($installedFile, $backupDir.'/'.$filename); - } - if (!is_dir(dirname($installedFile))) { - mkdir(dirname($installedFile), 0777, true); - } - if (!copy("$extractDir/$filename", $installedFile)) { - throw new Exception("Could not overwrite '$filename'"); - } - } - } - - printf("Updated %d files\n", count($changedFiles)); - printf("Clearing cache...\n"); - if (defined('PATH_C')) { - G::rm_dir(PATH_C); - mkdir(PATH_C, 0777, true); - } - $workspaces = System::listWorkspaces(); - $count = count($workspaces); - $first = true; - $num = 0; - foreach ($workspaces as $index => $workspace) { - try { - $num += 1; - printf("Upgrading workspaces ($num/$count): {$workspace->name}\n"); - $workspace->upgrade(false, config("system.workspace"), false, 'en', ['updateXml' => $first, 'updateMafe' => $first]); - $workspace->close(); - $first = false; - } catch (Exception $e) { - printf("Errors upgrading workspace {$workspace->name}: {$e->getMessage()}\n"); - } - } - } - - private function ls_dir($dir, $basename = null) - { - $files = array(); - if ($basename == null) { - $basename = $dir; - } - foreach (glob("$dir/*") as $filename) { - if (is_dir($filename)) { - $files = array_merge($files, $this->ls_dir($filename, $basename)); - } else { - $files[] = substr($filename, strlen($basename) + 1); - } - } - return $files; - } - -} diff --git a/workflow/engine/classes/WorkspaceTools.php b/workflow/engine/classes/WorkspaceTools.php index 3eeb7b9ae..261493b0d 100644 --- a/workflow/engine/classes/WorkspaceTools.php +++ b/workflow/engine/classes/WorkspaceTools.php @@ -218,160 +218,115 @@ class WorkspaceTools /** * Upgrade this workspace to the latest system version * - * @param bool $buildCacheView - * @param string $workSpace + * @param string $workspace * @param bool $onedb * @param string $lang * @param array $arrayOptTranslation + * @param array $optionMigrateHistoryData * * @return void */ - public function upgrade($buildCacheView = false, $workSpace = null, $onedb = false, $lang = 'en', array $arrayOptTranslation = null, $optionMigrateHistoryData = []) + public function upgrade($workspace, $onedb = false, $lang = 'en', array $arrayOptTranslation = null, $optionMigrateHistoryData = []) { - if ($workSpace === null) { - $workSpace = config("system.workspace"); - } if (is_null($arrayOptTranslation)) { $arrayOptTranslation = ['updateXml' => true, 'updateMafe' => true]; } + CLI::logging("* Start updating database schema...\n"); $start = microtime(true); - CLI::logging("> Remove deprecated files...\n"); - $this->removeDeprecatedFiles(); - $stop = microtime(true); - CLI::logging("<*> Remove deprecated files took " . ($stop - $start) . " seconds.\n"); - - $start = microtime(true); - CLI::logging("> Updating database...\n"); $this->upgradeDatabase($onedb); - $stop = microtime(true); - CLI::logging("<*> Database Upgrade Process took " . ($stop - $start) . " seconds.\n"); + CLI::logging("* End updating database schema...(Completed on " . (microtime(true) - $start) . " seconds)\n"); + CLI::logging("* Start updating translations...\n"); $start = microtime(true); - CLI::logging("> Check Intermediate Email Event...\n"); - $this->checkIntermediateEmailEvent(); - $stop = microtime(true); - CLI::logging("<*> Database Upgrade Process took " . ($stop - $start) . " seconds.\n"); - - $start = microtime(true); - CLI::logging("> Verify enterprise old...\n"); - $this->verifyFilesOldEnterprise($workSpace); - $stop = microtime(true); - CLI::logging("<*> Verify took " . ($stop - $start) . " seconds.\n"); - - $start = microtime(true); - CLI::logging("> Updating translations...\n"); $this->upgradeTranslation($arrayOptTranslation['updateXml'], $arrayOptTranslation['updateMafe']); - $stop = microtime(true); - $final = $stop - $start; - CLI::logging("<*> Updating Translations Process took $final seconds.\n"); + CLI::logging("* End updating translations...(Completed on " . (microtime(true) - $start) . " seconds)\n"); + + CLI::logging("* Start checking MAFE requirements...\n"); + $start = microtime(true); + $this->checkMafeRequirements($workspace, $lang); + CLI::logging("* End checking MAFE requirements...(Completed on " . (microtime(true) - $start) . " seconds)\n"); + + CLI::logging("* Start to update CONTENT table...\n"); + $start = microtime(true); + $this->upgradeContent($workspace); + CLI::logging("* End to update CONTENT table... (Completed on " . (microtime(true) - $start) . " seconds)\n"); $start = microtime(true); - CLI::logging("> Updating Content...\n"); - $this->upgradeContent($workSpace); - $stop = microtime(true); - $final = $stop - $start; - CLI::logging("<*> Updating Content Process took $final seconds.\n"); + CLI::logging("* Start to migrate texts/values from 'CONTENT' table to the corresponding object tables...\n"); + $this->migrateContent($lang); + CLI::logging("* End to migrate texts/values from 'CONTENT' table to the corresponding object tables... (Completed on " . + (microtime(true) - $start) . " seconds)\n"); + CLI::logging("* Start updating rows in Web Entry table for classic processes...\n"); $start = microtime(true); - CLI::logging("> Check Mafe Requirements...\n"); - $this->checkMafeRequirements($workSpace, $lang); - $stop = microtime(true); - $final = $stop - $start; - CLI::logging("<*> Check Mafe Requirements Process took $final seconds.\n"); + $this->updatingWebEntryClassicModel(true); + CLI::logging("* End updating rows in Web Entry table for classic processes...(Completed on " . + (microtime(true) - $start) . " seconds)\n"); + CLI::logging("* Start to update Files Manager...\n"); $start = microtime(true); - CLI::logging("> Updating Triggers...\n"); - $this->updateTriggers(true, $lang); - $stop = microtime(true); - $final = $stop - $start; - CLI::logging("<*> Updating Triggers Process took $final seconds.\n"); - - $start = microtime(true); - CLI::logging("> Backup log files...\n"); - $this->backupLogFiles(); - $stop = microtime(true); - $final = $stop - $start; - CLI::logging("<*> Backup log files Process took $final seconds.\n"); - - $start = microtime(true); - CLI::logging("> Optimizing content data...\n"); - $this->migrateContent($workSpace, $lang); - $stop = microtime(true); - CLI::logging("<*> Optimizing content data took " . ($stop - $start) . " seconds.\n"); - - $start = microtime(true); - CLI::logging("> Migrating and populating indexing for avoiding the use of table APP_CACHE_VIEW...\n"); - $this->migratePopulateIndexingACV($workSpace); - $stop = microtime(true); - CLI::logging("<*> Migrating an populating indexing for avoiding the use of table APP_CACHE_VIEW process took " . ($stop - $start) . " seconds.\n"); + $this->processFilesUpgrade($workspace); + CLI::logging("* End to update Files Manager... (Completed on " . (microtime(true) - $start) . " seconds)\n"); /*----------------------------------********---------------------------------*/ + CLI::logging("* Start migrating to new list tables...\n"); $start = microtime(true); - CLI::logging("> Migrate new lists...\n"); - $this->migrateList($workSpace, false, $lang); - $stop = microtime(true); - $final = $stop - $start; - CLI::logging("<*> Migrate new lists Process took $final seconds.\n"); + $this->migrateList(true, $lang); + CLI::logging("* End migrating to new list tables...(Completed on " . (microtime(true) - $start) . " seconds)\n"); /*----------------------------------********---------------------------------*/ + CLI::logging("* Start migrating and populating plugin singleton data...\n"); $start = microtime(true); - CLI::logging("> Updating Files Manager...\n"); - $this->processFilesUpgrade(); - $stop = microtime(true); - CLI::logging("<*> Updating Files Manager took " . ($stop - $start) . " seconds.\n"); + $this->migrateSingleton($workspace); + CLI::logging("* End migrating and populating plugin singleton data...(Completed on " . + (microtime(true) - $start) . " seconds)\n"); + CLI::logging("* Start cleaning expired tokens...\n"); $start = microtime(true); - CLI::logging("> Clean access and refresh tokens...\n"); - $this->cleanTokens($workSpace); - $stop = microtime(true); - CLI::logging("<*> Clean access and refresh tokens took " . ($stop - $start) . " seconds.\n"); + $this->cleanTokens(); + CLI::logging("* End cleaning expired tokens...(Completed on " . (microtime(true) - $start) . " seconds)\n"); + CLI::logging("* Start to check Intermediate Email Event...\n"); $start = microtime(true); - CLI::logging("> Optimizing Self-Service data...\n"); - $this->migrateSelfServiceRecordsRun($workSpace); - $stop = microtime(true); - CLI::logging("<*> Migrating Self-Service records Process took " . ($stop - $start) . " seconds.\n"); + $this->checkIntermediateEmailEvent(); + CLI::logging("* End to check Intermediate Email Event... (Completed on " . (microtime(true) - $start) . " seconds)\n"); + CLI::logging("* Start cleaning DYN_CONTENT in APP_HISTORY...\n"); $start = microtime(true); - CLI::logging("> Updating rows in Web Entry table for classic processes...\n"); - $this->updatingWebEntryClassicModel($workSpace); - $stop = microtime(true); - CLI::logging("<*> Updating rows in Web Entry table for classic processes took " . ($stop - $start) . " seconds.\n"); - - $start = microtime(true); - CLI::logging("> Update framework paths...\n"); - $this->updateFrameworkPaths($workSpace); - $stop = microtime(true); - CLI::logging("<*> Update framework paths took " . ($stop - $start) . " seconds.\n"); - - $start = microtime(true); - CLI::logging("> Migrating and populating plugin singleton data...\n"); - $this->migrateSingleton($workSpace); - $stop = microtime(true); - CLI::logging("<*> Migrating and populating plugin singleton data took " . ($stop - $start) . " seconds.\n"); - $keepDynContent = isset($optionMigrateHistoryData['keepDynContent']) && $optionMigrateHistoryData['keepDynContent'] === true; - //Review if we need to remove the 'History of use' from APP_HISTORY - $start = microtime(true); - CLI::logging("> Clearing History of Use from APP_HISTORY table...\n"); $this->clearDynContentHistoryData(false, $keepDynContent); - $stop = microtime(true); - CLI::logging("<*> Clearing History of Use from APP_HISTORY table took " . ($stop - $start) . " seconds.\n"); + CLI::logging("* End cleaning DYN_CONTENT in APP_HISTORY...(Completed on " . (microtime(true) - $start) . " seconds)\n"); /*----------------------------------********---------------------------------*/ + CLI::logging("* Start migrating history data...\n"); $start = microtime(true); - CLI::logging("> Migrating history data...\n"); - $this->migrateAppHistoryToAppDataChangeLog(false); - $stop = microtime(true); - CLI::logging("<*> Migrating history data took " . ($stop - $start) . " seconds.\n"); + $this->migrateAppHistoryToAppDataChangeLog(true); + CLI::logging("* End migrating history data...(Completed on " . (microtime(true) - $start) . " seconds)\n"); /*----------------------------------********---------------------------------*/ + CLI::logging("* Start migrating and populating indexing for avoiding the use of table APP_CACHE_VIEW...\n"); + $start = microtime(true); + $this->migratePopulateIndexingACV(); + CLI::logging("* End migrating and populating indexing for avoiding the use of table APP_CACHE_VIEW...(Completed on " . + (microtime(true) - $start) . " seconds)\n"); + + CLI::logging("* Start optimizing Self-Service data in table APP_ASSIGN_SELF_SERVICE_VALUE_GROUP....\n"); + $start = microtime(true); + $this->migrateSelfServiceRecordsRun(); + CLI::logging("* End optimizing Self-Service data in table APP_ASSIGN_SELF_SERVICE_VALUE_GROUP....(Completed on " . + (microtime(true) - $start) . " seconds)\n"); + + CLI::logging("* Start adding new fields and populating values in tables related to feature self service by value...\n"); $start = microtime(true); - CLI::logging("> Optimizing Self-Service data in table APP_ASSIGN_SELF_SERVICE_VALUE_GROUP....\n"); $this->upgradeSelfServiceData(); - $stop = microtime(true); - CLI::logging("<*> Optimizing Self-Service data in table APP_ASSIGN_SELF_SERVICE_VALUE_GROUP took " . ($stop - $start) . " seconds.\n"); + CLI::logging("* End adding new fields and populating values in tables related to feature self service by value...(Completed on " . + (microtime(true) - $start) . " seconds)\n"); + + CLI::logging("* Start updating MySQL triggers...\n"); + $start = microtime(true); + $this->updateTriggers(true, $lang); + CLI::logging("* End updating MySQL triggers...(" . (microtime(true) - $start) . " seconds)\n"); } /** @@ -391,6 +346,9 @@ class WorkspaceTools CLI::logging("<*> Database Upgrade Structure Process took $final seconds.\n"); } + /** + * Update the email events with the current email server + */ public function checkIntermediateEmailEvent() { $oEmailEvent = new \ProcessMaker\BusinessModel\EmailEvent(); @@ -629,9 +587,11 @@ class WorkspaceTools } /** - * Upgrade this workspace Content. + * Upgrade this workspace Content + * * @param string $workspace * @param boolean $executeRegenerateContent + * * @return void */ public function upgradeContent($workspace = null, $executeRegenerateContent = false) @@ -683,7 +643,7 @@ class WorkspaceTools } /** - * Upgrade this workspace translations from all avaliable languages. + * Upgrade the workspace translations from all available languages * * @param bool $flagXml Update XML * @param bool $flagMafe Update MAFE @@ -1055,10 +1015,12 @@ class WorkspaceTools } /** - * Upgrade this workspace database to the latest system schema + * Upgrade the workspace database to the latest system schema * - * @param bool $checkOnly only check if the upgrade is needed if true - * @return array bool upgradeSchema for more information + * @param bool $onedb Was installed in one DB or not + * @param bool $checkOnly Only check if the upgrade is needed if true + * + * @return bool upgradeSchema */ public function upgradeDatabase($onedb = false, $checkOnly = false) { @@ -2174,6 +2136,9 @@ class WorkspaceTools return $result; } + /** + * Backup the log files + */ public function backupLogFiles() { $config = System::getSystemConfiguration(); @@ -2190,6 +2155,12 @@ class WorkspaceTools } } + /** + * Check if the workspace have the clients used by MAFE registered + * + * @param string $workspace + * @param string $lang + */ public function checkMafeRequirements($workspace, $lang) { $this->initPropel(true); @@ -2266,9 +2237,8 @@ class WorkspaceTools return true; } - public function verifyFilesOldEnterprise($workspace) + public function verifyFilesOldEnterprise() { - $this->initPropel(true); $pathBackup = PATH_DATA . 'backups'; if (!file_exists($pathBackup)) { G::mk_dir($pathBackup, 0777); @@ -2382,12 +2352,12 @@ class WorkspaceTools /** * Migrate all cases to New list * - * @param string $workSpace Workspace * @param bool $flagReinsert Flag that specifies the re-insertion + * @param string $lang * * @return void */ - public function migrateList($workSpace, $flagReinsert = false, $lang = 'en') + public function migrateList($flagReinsert = false, $lang = 'en') { $this->initPropel(true); @@ -3099,19 +3069,21 @@ class WorkspaceTools } /** - * Process-Files upgrade + * Process files upgrade, store the information in the DB + * + * @param string $workspace * * return void */ - public function processFilesUpgrade() + public function processFilesUpgrade($workspace) { try { if (!defined("PATH_DATA_MAILTEMPLATES")) { - define("PATH_DATA_MAILTEMPLATES", PATH_DATA_SITE . "mailTemplates" . PATH_SEP); + define("PATH_DATA_MAILTEMPLATES", PATH_DATA . 'sites' . PATH_SEP . $workspace . PATH_SEP . "mailTemplates" . PATH_SEP); } if (!defined("PATH_DATA_PUBLIC")) { - define("PATH_DATA_PUBLIC", PATH_DATA_SITE . "public" . PATH_SEP); + define("PATH_DATA_PUBLIC", PATH_DATA . 'sites' . PATH_SEP . $workspace . PATH_SEP . "public" . PATH_SEP); } $this->initPropel(true); @@ -3624,8 +3596,12 @@ class WorkspaceTools return $response; } - - public function migrateContent($workspace, $lang = SYS_LANG) + /** + * Migrate texts/values from "CONTENT" table to the corresponding object tables + * + * @param string $lang + */ + public function migrateContent($lang = SYS_LANG) { if ((!class_exists('Memcache') || !class_exists('Memcached')) && !defined('MEMCACHED_ENABLED')) { define('MEMCACHED_ENABLED', false); @@ -3638,7 +3614,7 @@ class WorkspaceTools $blackList = $oConfig['CFG_VALUE'] == 'true' ? array('Groupwf', 'Process', 'Department', 'Task', 'InputDocument', 'Application') : unserialize($oConfig['CFG_VALUE']); } - $blackList = $this->migrateContentRun($workspace, $lang, $blackList); + $blackList = $this->migrateContentRun($lang, $blackList); $data["CFG_UID"] = 'MIGRATED_CONTENT'; $data["OBJ_UID"] = 'content'; $data["CFG_VALUE"] = serialize($blackList); @@ -3705,13 +3681,14 @@ class WorkspaceTools } /** - * Migration + * Migrate from "CONTENT" table to the corresponding object tables + * + * @param string $lang + * @param array $blackList * - * @param $workspace - * @param mixed|string $lang * @return array */ - public function migrateContentRun($workspace, $lang = SYS_LANG, $blackList = array()) + public function migrateContentRun($lang = SYS_LANG, $blackList = []) { if ((!class_exists('Memcache') || !class_exists('Memcached')) && !defined('MEMCACHED_ENABLED')) { define('MEMCACHED_ENABLED', false); @@ -3727,7 +3704,10 @@ class WorkspaceTools return $blackList; } - public function cleanTokens($workspace, $lang = SYS_LANG) + /** + * Clean the expired access and refresh tokens + */ + public function cleanTokens() { $this->initPropel(true); $oCriteria = new Criteria(); @@ -3822,7 +3802,10 @@ class WorkspaceTools } } - public function migrateSelfServiceRecordsRun($workspace) + /** + * Migrate the concatenated strings with UIDs from groups to the table "APP_ASSIGN_SELF_SERVICE_VALUE_GROUP" + */ + public function migrateSelfServiceRecordsRun() { // Initializing $this->initPropel(true); @@ -3869,7 +3852,10 @@ class WorkspaceTools CLI::logging(" Migrating Self-Service by Value Cases Done \n"); } - public function migratePopulateIndexingACV($workspace) + /** + * Populate new fields used for avoiding the use of the "APP_CACHE_VIEW" table + */ + public function migratePopulateIndexingACV() { // Migrating and populating new indexes CLI::logging("-> Migrating an populating indexing for avoiding the use of table APP_CACHE_VIEW Start \n"); @@ -4134,9 +4120,10 @@ class WorkspaceTools * It populates the WEB_ENTRY table for the classic processes, this procedure * is done to verify the execution of php files generated when the WebEntry * is configured. - * @param type $workSpace + * + * @param bool $force */ - public function updatingWebEntryClassicModel($workSpace, $force = false) + public function updatingWebEntryClassicModel($force = false) { //We obtain from the configuration the list of proUids obtained so that //we do not go through again. @@ -4232,8 +4219,9 @@ class WorkspaceTools /** * Updating triggers - * @param $flagRecreate - * @param $lang + * + * @param bool $flagRecreate + * @param string $lang */ public function updateTriggers($flagRecreate, $lang) { @@ -4242,6 +4230,8 @@ class WorkspaceTools } /** + * Migrate the data of the "plugin.singleton" file to the "PLUGIN_REGISTRY" table + * * @param $workspace */ public function migrateSingleton($workspace) @@ -4287,14 +4277,11 @@ class WorkspaceTools } /** - * Updating framework directory structure + * Check/Create framework's directories * */ - private function updateFrameworkPaths($workSpace = null) + public function checkFrameworkPaths() { - if ($workSpace === null) { - $workSpace = config("system.workspace"); - } $paths = [ PATH_DATA . 'framework' => 0770, PATH_DATA . 'framework' . DIRECTORY_SEPARATOR . 'cache' => 0770, diff --git a/workflow/engine/classes/model/AddonsManager.php b/workflow/engine/classes/model/AddonsManager.php index 06d16fedb..10691d3ac 100644 --- a/workflow/engine/classes/model/AddonsManager.php +++ b/workflow/engine/classes/model/AddonsManager.php @@ -385,13 +385,7 @@ class AddonsManager extends BaseAddonsManager $this->setState(); } else { - if ($this->getAddonType() == "core") { - $upgrade = new Upgrade($this); - - $upgrade->install(); - } else { - throw new Exception("Addon type {$this->getAddonType()} not supported."); - } + throw new Exception("Addon type {$this->getAddonType()} not supported."); } } diff --git a/workflow/engine/src/ProcessMaker/Core/System.php b/workflow/engine/src/ProcessMaker/Core/System.php index 16b21bc78..46b98042e 100644 --- a/workflow/engine/src/ProcessMaker/Core/System.php +++ b/workflow/engine/src/ProcessMaker/Core/System.php @@ -242,39 +242,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 * From 8f9ac0e22370dfdd7e7fdb73e40a94b4fa805d33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julio=20Cesar=20Laura=20Avenda=C3=B1o?= Date: Mon, 18 Mar 2019 16:17:23 -0400 Subject: [PATCH 02/21] PMC-568 --- gulliver/system/class.database_mysql.php | 12 ++++++++++++ workflow/engine/classes/WorkspaceTools.php | 21 +++++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/gulliver/system/class.database_mysql.php b/gulliver/system/class.database_mysql.php index 8191f51db..0bae312f0 100644 --- a/gulliver/system/class.database_mysql.php +++ b/gulliver/system/class.database_mysql.php @@ -1012,4 +1012,16 @@ class database extends database_base } return $flag; } + + /** + * Generate drop trigger SQL + * + * @param string $triggerName + * + * @return string + */ + public function getDropTrigger($triggerName) + { + return "DROP TRIGGER IF EXISTS `{$triggerName}`;"; + } } diff --git a/workflow/engine/classes/WorkspaceTools.php b/workflow/engine/classes/WorkspaceTools.php index 261493b0d..3eac6a1d7 100644 --- a/workflow/engine/classes/WorkspaceTools.php +++ b/workflow/engine/classes/WorkspaceTools.php @@ -4616,4 +4616,25 @@ class WorkspaceTools } } } + + /** + * Delete the triggers MySQL that causes performance issues in the upgrade process + */ + public function deleteTriggersMySql($triggersToDelete) + { + // Initialize Propel + $this->initPropel(true); + $con = Propel::getConnection('workflow'); + + // Get statement instance + $stmt = $con->createStatement(); + + // Get MySQL DB instance class + $dbInstance = $this->getDatabase(); + + // Remove triggers MySQL + foreach ($triggersToDelete as $triggerName) { + $stmt->executeQuery($dbInstance->getDropTrigger($triggerName)); + } + } } From 76a3fbc95b280de96367970738aceb69453c2969 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julio=20Cesar=20Laura=20Avenda=C3=B1o?= Date: Tue, 19 Mar 2019 12:31:29 -0400 Subject: [PATCH 03/21] PMC-569 --- workflow/engine/classes/WorkspaceTools.php | 26 ++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/workflow/engine/classes/WorkspaceTools.php b/workflow/engine/classes/WorkspaceTools.php index 3eac6a1d7..76a1d15f7 100644 --- a/workflow/engine/classes/WorkspaceTools.php +++ b/workflow/engine/classes/WorkspaceTools.php @@ -4637,4 +4637,30 @@ class WorkspaceTools $stmt->executeQuery($dbInstance->getDropTrigger($triggerName)); } } + + /** + * Delete indexes of specific tables + * + * @param array $tables + */ + public function deleteIndexes($tables) + { + // Get MySQL DB instance class + $database = $this->getDatabase(); + + foreach ($tables as $table) { + // Get all indexes of the table + $indexes = $database->executeQuery($database->generateTableIndexSQL($table)); + $indexesDeleted = []; + foreach ($indexes as $index) { + if ($index['Key_name'] != 'PRIMARY') { + if (!in_array($index['Key_name'], $indexesDeleted)) { + // Remove index + $database->executeQuery($database->generateDropKeySQL($table, $index['Key_name'])); + $indexesDeleted[] = $index['Key_name']; + } + } + } + } + } } From f3590486c84c46df5fe3b7c8ec710e1689806aef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julio=20Cesar=20Laura=20Avenda=C3=B1o?= Date: Tue, 19 Mar 2019 14:34:05 -0400 Subject: [PATCH 04/21] PMC-574 --- workflow/engine/classes/WorkspaceTools.php | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/workflow/engine/classes/WorkspaceTools.php b/workflow/engine/classes/WorkspaceTools.php index 76a1d15f7..596c95eb8 100644 --- a/workflow/engine/classes/WorkspaceTools.php +++ b/workflow/engine/classes/WorkspaceTools.php @@ -247,6 +247,20 @@ class WorkspaceTools $this->checkMafeRequirements($workspace, $lang); CLI::logging("* End checking MAFE requirements...(Completed on " . (microtime(true) - $start) . " seconds)\n"); + CLI::logging("* Start deleting MySQL triggers: APP_DELEGATION_UPDATE, APPLICATION_UPDATE, CONTENT_UPDATE...\n"); + $start = microtime(true); + $this->deleteTriggersMySQL(['APP_DELEGATION_UPDATE', 'APPLICATION_UPDATE', 'CONTENT_UPDATE']); + CLI::logging("* End deleting MySQL triggers: APP_DELEGATION_UPDATE, APPLICATION_UPDATE, CONTENT_UPDATE... (Completed on " . + (microtime(true) - $start) . " seconds)\n"); + + $bigTables = ['APPLICATION', 'APP_ASSIGN_SELF_SERVICE_VALUE_GROUP', 'APP_CACHE_VIEW', 'APP_DELEGATION', 'APP_DELAY', + 'APP_DOCUMENT', 'APP_HISTORY', 'APP_MESSAGE', 'GROUP_USER', 'LOGIN_LOG']; + CLI::logging("* Start deleting indexes from big tables: " . implode(', ', $bigTables) . "...\n"); + $start = microtime(true); + $this->deleteIndexes($bigTables); + CLI::logging("* End deleting indexes from big tables: " . implode(', ', $bigTables) . "... (Completed on " . + (microtime(true) - $start) . " seconds)\n"); + CLI::logging("* Start to update CONTENT table...\n"); $start = microtime(true); $this->upgradeContent($workspace); From a1c99b4836a41895c1dc804a0750b39f4edbf1ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julio=20Cesar=20Laura=20Avenda=C3=B1o?= Date: Wed, 20 Mar 2019 10:58:58 -0400 Subject: [PATCH 05/21] PMC-596 --- gulliver/system/class.database_mysql.php | 71 +++++++++++ workflow/engine/bin/tasks/cliUpgrade.php | 2 +- workflow/engine/classes/WorkspaceTools.php | 142 ++++++++++++--------- 3 files changed, 152 insertions(+), 63 deletions(-) diff --git a/gulliver/system/class.database_mysql.php b/gulliver/system/class.database_mysql.php index 0bae312f0..870ba954f 100644 --- a/gulliver/system/class.database_mysql.php +++ b/gulliver/system/class.database_mysql.php @@ -1024,4 +1024,75 @@ class database extends database_base { return "DROP TRIGGER IF EXISTS `{$triggerName}`;"; } + + /** + * Generate alter table with or without adding the indexes + * + * @param string $tableName + * @param array $columns + * @param array $indexes + * + * @return string + */ + public function generateAddColumnsSql($tableName, $columns, $indexes = []) + { + $indexesAlreadyAdded = []; + $sql = 'ALTER TABLE ' . $this->sQuoteCharacter . $tableName . $this->sQuoteCharacter . ' '; + foreach ($columns as $columnName => $parameters) { + if (isset($parameters['Type']) && isset($parameters['Null'])) { + $sql .= 'ADD COLUMN ' . $this->sQuoteCharacter . $columnName . $this->sQuoteCharacter . ' ' . $parameters['Type']; + if ($parameters['Null'] == 'YES') { + $sql .= ' NULL'; + } else { + $sql .= ' NOT NULL'; + } + } + if (isset($parameters['AutoIncrement']) && $parameters['AutoIncrement']) { + $sql .= ' AUTO_INCREMENT'; + } + if (isset($parameters['PrimaryKey']) && $parameters['PrimaryKey']) { + $sql .= ' PRIMARY KEY'; + $indexesAlreadyAdded[] = $columnName; + } + if (isset($parameters['Unique']) && $parameters['Unique']) { + $sql .= ' UNIQUE'; + } + + // We need to check the property AI + if (isset($parameters['AI'])) { + if ($parameters['AI'] == 1) { + $sql .= ' AUTO_INCREMENT'; + } else { + if ($parameters['Default'] != '') { + $sql .= " DEFAULT '" . $parameters['Default'] . "'"; + } + } + } else { + if (isset($parameters['Default'])) { + $sql .= " DEFAULT '" . $parameters['Default'] . "'"; + } + } + $sql .= ', '; + } + foreach ($indexes as $indexName => $indexColumns) { + $indexType = 'INDEX'; + if ($indexName === 'primaryKey' || $indexName === 'PRIMARY') { + $indexType = 'PRIMARY'; + $indexName = 'KEY'; + // If is primary key is not needed add a new index, the column already was added like primary key + if (count($indexColumns) == 1 && $indexesAlreadyAdded == $indexColumns) { + continue; + } + } + $sql .= 'ADD ' . $indexType . ' ' . $indexName . ' ('; + foreach ($indexColumns as $column) { + $sql .= $this->sQuoteCharacter . $column . $this->sQuoteCharacter . ', '; + } + $sql = substr($sql, 0, -2); + $sql .= '), '; + } + $sql = rtrim($sql, ', '); + + return $sql; + } } diff --git a/workflow/engine/bin/tasks/cliUpgrade.php b/workflow/engine/bin/tasks/cliUpgrade.php index d09d3adff..7fec63fd0 100644 --- a/workflow/engine/bin/tasks/cliUpgrade.php +++ b/workflow/engine/bin/tasks/cliUpgrade.php @@ -160,7 +160,7 @@ function run_upgrade($parameters, $args) ]; // Upgrade database and files from a specific workspace - $workspace->upgrade($workspace->name, true, SYS_LANG, $arrayOptTranslation, $optionMigrateHistoryData); + $workspace->upgrade($workspace->name, SYS_LANG, $arrayOptTranslation, $optionMigrateHistoryData); $workspace->close(); } else { // Build arguments diff --git a/workflow/engine/classes/WorkspaceTools.php b/workflow/engine/classes/WorkspaceTools.php index 596c95eb8..56a31f428 100644 --- a/workflow/engine/classes/WorkspaceTools.php +++ b/workflow/engine/classes/WorkspaceTools.php @@ -226,7 +226,7 @@ class WorkspaceTools * * @return void */ - public function upgrade($workspace, $onedb = false, $lang = 'en', array $arrayOptTranslation = null, $optionMigrateHistoryData = []) + public function upgrade($workspace, $lang = 'en', array $arrayOptTranslation = null, $optionMigrateHistoryData = []) { if (is_null($arrayOptTranslation)) { $arrayOptTranslation = ['updateXml' => true, 'updateMafe' => true]; @@ -234,7 +234,7 @@ class WorkspaceTools CLI::logging("* Start updating database schema...\n"); $start = microtime(true); - $this->upgradeDatabase($onedb); + $this->upgradeDatabase(); CLI::logging("* End updating database schema...(Completed on " . (microtime(true) - $start) . " seconds)\n"); CLI::logging("* Start updating translations...\n"); @@ -283,13 +283,6 @@ class WorkspaceTools $this->processFilesUpgrade($workspace); CLI::logging("* End to update Files Manager... (Completed on " . (microtime(true) - $start) . " seconds)\n"); - /*----------------------------------********---------------------------------*/ - CLI::logging("* Start migrating to new list tables...\n"); - $start = microtime(true); - $this->migrateList(true, $lang); - CLI::logging("* End migrating to new list tables...(Completed on " . (microtime(true) - $start) . " seconds)\n"); - /*----------------------------------********---------------------------------*/ - CLI::logging("* Start migrating and populating plugin singleton data...\n"); $start = microtime(true); $this->migrateSingleton($workspace); @@ -337,6 +330,19 @@ class WorkspaceTools CLI::logging("* End adding new fields and populating values in tables related to feature self service by value...(Completed on " . (microtime(true) - $start) . " seconds)\n"); + CLI::logging("* Start adding/replenishing all indexes...\n"); + $start = microtime(true); + $systemSchema = System::getSystemSchema($this->dbAdapter); + $this->upgradeSchema($systemSchema); + CLI::logging("* End adding/replenishing all indexes...(Completed on " . (microtime(true) - $start) . " seconds)\n"); + + /*----------------------------------********---------------------------------*/ + CLI::logging("* Start migrating to new list tables...\n"); + $start = microtime(true); + $this->migrateList(true, $lang); + CLI::logging("* End migrating to new list tables...(Completed on " . (microtime(true) - $start) . " seconds)\n"); + /*----------------------------------********---------------------------------*/ + CLI::logging("* Start updating MySQL triggers...\n"); $start = microtime(true); $this->updateTriggers(true, $lang); @@ -1030,22 +1036,17 @@ class WorkspaceTools /** * Upgrade the workspace database to the latest system schema - * - * @param bool $onedb Was installed in one DB or not - * @param bool $checkOnly Only check if the upgrade is needed if true - * - * @return bool upgradeSchema */ - public function upgradeDatabase($onedb = false, $checkOnly = false) + public function upgradeDatabase() { $this->initPropel(true); P11835::$dbAdapter = $this->dbAdapter; P11835::isApplicable(); $systemSchema = System::getSystemSchema($this->dbAdapter); - $systemSchemaRbac = System::getSystemSchemaRbac($this->dbAdapter);// get the Rbac Schema + $systemSchemaRbac = System::getSystemSchemaRbac($this->dbAdapter);// Get the RBAC Schema $this->registerSystemTables(array_merge($systemSchema, $systemSchemaRbac)); - $this->upgradeSchema($systemSchema); - $this->upgradeSchema($systemSchemaRbac, false, true, $onedb); // perform Upgrade to Rbac + $this->upgradeSchema($systemSchema, false, false, false); // Without add indexes + $this->upgradeSchema($systemSchemaRbac, false, true); // Perform upgrade to RBAC $this->upgradeData(); $this->checkRbacPermissions();//check or add new permissions $this->checkSequenceNumber(); @@ -1113,10 +1114,7 @@ class WorkspaceTools $arrayData = $emailSever->create2($arrayData); } } - P11835::execute(); - - return true; } private function setFormatRows() @@ -1137,14 +1135,18 @@ class WorkspaceTools } /** - * Upgrade this workspace database from a schema + * Upgrade the workspace database according to the schema * - * @param array $schema the schema information, such as returned from getSystemSchema - * @param bool $checkOnly only check if the upgrade is needed if true - * @return array bool the changes if checkOnly is true, else return - * true on success + * @param array $schema The schema information, such as returned from getSystemSchema + * @param bool $checkOnly Only return the diff between current database and the schema + * @param bool $rbac Is RBAC database? + * @param bool $includeIndexes Include or no indexes in new tables + * + * @return bool|array + * + * @throws Exception */ - public function upgradeSchema($schema, $checkOnly = false, $rbac = false, $onedb = false) + public function upgradeSchema($schema, $checkOnly = false, $rbac = false, $includeIndexes = true) { $dbInfo = $this->getDBInfo(); @@ -1199,11 +1201,11 @@ class WorkspaceTools CLI::logging("-> " . count($changes['tablesToAdd']) . " tables to add\n"); } - foreach ($changes['tablesToAdd'] as $sTable => $aColumns) { - $database->executeQuery($database->generateCreateTableSQL($sTable, $aColumns)); - if (isset($changes['tablesToAdd'][$sTable]['INDEXES'])) { - foreach ($changes['tablesToAdd'][$sTable]['INDEXES'] as $indexName => $aIndex) { - $database->executeQuery($database->generateAddKeysSQL($sTable, $indexName, $aIndex)); + foreach ($changes['tablesToAdd'] as $tableName => $columns) { + $database->executeQuery($database->generateCreateTableSQL($tableName, $columns)); + if (isset($changes['tablesToAdd'][$tableName]['INDEXES']) && $includeIndexes) { + foreach ($changes['tablesToAdd'][$tableName]['INDEXES'] as $indexName => $keys) { + $database->executeQuery($database->generateAddKeysSQL($tableName, $indexName, $keys)); } } } @@ -1212,46 +1214,62 @@ class WorkspaceTools CLI::logging("-> " . count($changes['tablesToAlter']) . " tables to alter\n"); } - foreach ($changes['tablesToAlter'] as $sTable => $aActions) { - foreach ($aActions as $sAction => $aAction) { - foreach ($aAction as $sColumn => $vData) { - switch ($sAction) { - case 'DROP': - $database->executeQuery($database->generateDropColumnSQL($sTable, $vData)); - break; - case 'ADD': - if ($database->checkPatchHor1787($sTable, $sColumn, $vData)) { - $database->executeQuery($database->generateCheckAddColumnSQL($sTable, $sColumn, $vData)); - $database->executeQuery($database->deleteAllIndexesIntable($sTable, $sColumn, $vData)); - } - $database->executeQuery($database->generateAddColumnSQL($sTable, $sColumn, $vData)); - break; - case 'CHANGE': - $database->executeQuery($database->generateChangeColumnSQL($sTable, $sColumn, $vData)); - break; + $tablesToAddColumns = []; + + foreach ($changes['tablesToAlter'] as $tableName => $actions) { + foreach ($actions as $action => $actionData) { + if ($action == 'ADD') { + $tablesToAddColumns[$tableName] = $actionData; + + // In a very old schema the primary key for table "LOGIN_LOG" was changed and we need to delete the + // primary index to avoid errors in the database upgrade + // TO DO: The change of a Primary Key in a table should be generic + if ($tableName == 'LOGIN_LOG' && array_key_exists('LOG_ID', $actionData)) { + $database->executeQuery('DROP INDEX `PRIMARY` ON LOGIN_LOG;'); + } + } else { + foreach ($actionData as $columnName => $meta) { + switch ($action) { + case 'DROP': + $database->executeQuery($database->generateDropColumnSQL($tableName, $meta)); + break; + case 'CHANGE': + $database->executeQuery($database->generateChangeColumnSQL($tableName, $columnName, $meta)); + break; + } } } } } - if (!empty($changes['tablesWithNewIndex'])) { - CLI::logging("-> " . count($changes['tablesWithNewIndex']) . " indexes to add\n"); - } - foreach ($changes['tablesWithNewIndex'] as $sTable => $aIndexes) { - foreach ($aIndexes as $sIndexName => $aIndexFields) { - $database->executeQuery($database->generateAddKeysSQL($sTable, $sIndexName, $aIndexFields)); + if (!empty($tablesToAddColumns)) { + foreach ($tablesToAddColumns as $tableName => $tableColumn) { + $indexes = []; + if (!empty($changes['tablesWithNewIndex'][$tableName]) && $includeIndexes) { + $indexes = $changes['tablesWithNewIndex'][$tableName]; + unset($changes['tablesWithNewIndex'][$tableName]); + } + $database->executeQuery($database->generateAddColumnsSql($tableName, $tableColumn, $indexes)); } } - if (!empty($changes['tablesToAlterIndex'])) { - CLI::logging("-> " . count($changes['tablesToAlterIndex']) . " indexes to alter\n"); - } - foreach ($changes['tablesToAlterIndex'] as $sTable => $aIndexes) { - foreach ($aIndexes as $sIndexName => $aIndexFields) { - $database->executeQuery($database->generateDropKeySQL($sTable, $sIndexName)); - $database->executeQuery($database->generateAddKeysSQL($sTable, $sIndexName, $aIndexFields)); + if (!empty($changes['tablesWithNewIndex']) && $includeIndexes) { + CLI::logging("-> " . count($changes['tablesWithNewIndex']) . " tables with indexes to add\n"); + foreach ($changes['tablesWithNewIndex'] as $tableName => $indexes) { + $database->executeQuery($database->generateAddColumnsSql($tableName, [], $indexes)); } } + + if (!empty($changes['tablesToAlterIndex']) && $includeIndexes) { + CLI::logging("-> " . count($changes['tablesToAlterIndex']) . " tables with indexes to alter\n"); + foreach ($changes['tablesToAlterIndex'] as $tableName => $indexes) { + foreach ($indexes as $indexName => $indexFields) { + $database->executeQuery($database->generateDropKeySQL($tableName, $indexName)); + $database->executeQuery($database->generateAddKeysSQL($tableName, $indexName, $indexFields)); + } + } + } + $this->closeDatabase(); return true; } From 4970e71c06782769987492a16f5f62dbf8695ef0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julio=20Cesar=20Laura=20Avenda=C3=B1o?= Date: Thu, 4 Apr 2019 14:44:33 -0400 Subject: [PATCH 06/21] PMC-570 --- gulliver/system/class.database_mysql.php | 12 +- workflow/engine/bin/tasks/cliUpgrade.php | 24 +++ workflow/engine/classes/WorkspaceTools.php | 12 ++ .../ProcessMaker/Core/ProcessesManager.php | 98 ++++++++++++ .../src/ProcessMaker/Core/RunProcess.php | 146 ++++++++++++++++++ .../Upgrade/RunProcessUpgradeQuery.php | 61 ++++++++ 6 files changed, 350 insertions(+), 3 deletions(-) create mode 100644 workflow/engine/src/ProcessMaker/Core/ProcessesManager.php create mode 100644 workflow/engine/src/ProcessMaker/Core/RunProcess.php create mode 100644 workflow/engine/src/ProcessMaker/Upgrade/RunProcessUpgradeQuery.php diff --git a/gulliver/system/class.database_mysql.php b/gulliver/system/class.database_mysql.php index 870ba954f..53888a4ae 100644 --- a/gulliver/system/class.database_mysql.php +++ b/gulliver/system/class.database_mysql.php @@ -519,13 +519,15 @@ class database extends database_base } /** - * execute a sql query + * Execute a sql query * * @param string $query + * @param bool $throwError + * * @return array * @throws Exception */ - public function executeQuery($query) + public function executeQuery($query, $throwError = false) { $this->logQuery($query); @@ -545,7 +547,11 @@ class database extends database_base return $result; } catch (Exception $exception) { $this->logQuery($exception->getMessage()); - return []; + if ($throwError) { + throw $exception; + } else { + return []; + } } } diff --git a/workflow/engine/bin/tasks/cliUpgrade.php b/workflow/engine/bin/tasks/cliUpgrade.php index 7fec63fd0..36aa2e37d 100644 --- a/workflow/engine/bin/tasks/cliUpgrade.php +++ b/workflow/engine/bin/tasks/cliUpgrade.php @@ -36,6 +36,8 @@ CLI::taskArg('workspace'); /*----------------------------------********---------------------------------*/ CLI::taskRun("run_unify_database"); /*----------------------------------********---------------------------------*/ +CLI::taskName('upgrade-query'); +CLI::taskRun('runUpgradeQuery'); /** * Execute the upgrade @@ -299,3 +301,25 @@ function run_unify_database($args) $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'); +} diff --git a/workflow/engine/classes/WorkspaceTools.php b/workflow/engine/classes/WorkspaceTools.php index 56a31f428..2100b7a3b 100644 --- a/workflow/engine/classes/WorkspaceTools.php +++ b/workflow/engine/classes/WorkspaceTools.php @@ -4695,4 +4695,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); + } } diff --git a/workflow/engine/src/ProcessMaker/Core/ProcessesManager.php b/workflow/engine/src/ProcessMaker/Core/ProcessesManager.php new file mode 100644 index 000000000..bff0c5d96 --- /dev/null +++ b/workflow/engine/src/ProcessMaker/Core/ProcessesManager.php @@ -0,0 +1,98 @@ +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)); + } +} diff --git a/workflow/engine/src/ProcessMaker/Core/RunProcess.php b/workflow/engine/src/ProcessMaker/Core/RunProcess.php new file mode 100644 index 000000000..8f2a0287f --- /dev/null +++ b/workflow/engine/src/ProcessMaker/Core/RunProcess.php @@ -0,0 +1,146 @@ +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; + } +} diff --git a/workflow/engine/src/ProcessMaker/Upgrade/RunProcessUpgradeQuery.php b/workflow/engine/src/ProcessMaker/Upgrade/RunProcessUpgradeQuery.php new file mode 100644 index 000000000..e1295c0e4 --- /dev/null +++ b/workflow/engine/src/ProcessMaker/Upgrade/RunProcessUpgradeQuery.php @@ -0,0 +1,61 @@ +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)); + } +} \ No newline at end of file From 57485cf26bd32cb1311c51cac538d1d89f0601b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julio=20Cesar=20Laura=20Avenda=C3=B1o?= Date: Fri, 12 Apr 2019 11:48:09 -0400 Subject: [PATCH 07/21] PMC-571 --- workflow/engine/classes/WorkspaceTools.php | 37 ++++++++++++++++++++-- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/workflow/engine/classes/WorkspaceTools.php b/workflow/engine/classes/WorkspaceTools.php index b62a31eba..f004bacb9 100644 --- a/workflow/engine/classes/WorkspaceTools.php +++ b/workflow/engine/classes/WorkspaceTools.php @@ -7,9 +7,11 @@ use ProcessMaker\BusinessModel\Process as BmProcess; use ProcessMaker\ChangeLog\ChangeLog; /*----------------------------------********---------------------------------*/ use ProcessMaker\Core\Installer; +use ProcessMaker\Core\ProcessesManager; use ProcessMaker\Core\System; use ProcessMaker\Plugins\Adapters\PluginAdapter; use ProcessMaker\Project\Adapter\BpmnWorkflow; +use ProcessMaker\Upgrade\RunProcessUpgradeQuery; use ProcessMaker\Util\FixReferencePath; /** @@ -1243,20 +1245,51 @@ class WorkspaceTools } if (!empty($tablesToAddColumns)) { + $upgradeQueries = []; foreach ($tablesToAddColumns as $tableName => $tableColumn) { $indexes = []; if (!empty($changes['tablesWithNewIndex'][$tableName]) && $includeIndexes) { $indexes = $changes['tablesWithNewIndex'][$tableName]; unset($changes['tablesWithNewIndex'][$tableName]); } - $database->executeQuery($database->generateAddColumnsSql($tableName, $tableColumn, $indexes)); + + // Instantiate the class to execute the query in background + $upgradeQueries[] = new RunProcessUpgradeQuery($this->name, $database->generateAddColumnsSql($tableName, $tableColumn, $indexes), $rbac); + } + + // Run queries in multiple threads + $processesManager = new ProcessesManager($upgradeQueries); + $processesManager->run(); + + // If exists an error throw an exception + if (!empty($processesManager->getErrors())) { + $errorMessage = ''; + foreach ($processesManager->getErrors() as $error) { + $errorMessage .= $error['rawAnswer'] . PHP_EOL; + } + throw new Exception($errorMessage); } } if (!empty($changes['tablesWithNewIndex']) && $includeIndexes) { CLI::logging("-> " . count($changes['tablesWithNewIndex']) . " tables with indexes to add\n"); + $upgradeQueries = []; foreach ($changes['tablesWithNewIndex'] as $tableName => $indexes) { - $database->executeQuery($database->generateAddColumnsSql($tableName, [], $indexes)); + // Instantiate the class to execute the query in background + $upgradeQueries[] = new RunProcessUpgradeQuery($this->name, $database->generateAddColumnsSql($tableName, [], $indexes), $rbac); + } + + // Run queries in multiple threads + $processesManager = new ProcessesManager($upgradeQueries); + $processesManager->run(); + + // If exists an error throw an exception + if (!empty($processesManager->getErrors())) { + $errorMessage = ''; + foreach ($processesManager->getErrors() as $error) { + $errorMessage .= $error['rawAnswer'] . PHP_EOL; + } + throw new Exception($errorMessage); } } From d9b4de1f32217573956156c719d1293e583c064a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julio=20Cesar=20Laura=20Avenda=C3=B1o?= Date: Fri, 12 Apr 2019 14:22:52 -0400 Subject: [PATCH 08/21] PMC-572 --- workflow/engine/classes/WorkspaceTools.php | 106 +++++++++++---------- 1 file changed, 56 insertions(+), 50 deletions(-) diff --git a/workflow/engine/classes/WorkspaceTools.php b/workflow/engine/classes/WorkspaceTools.php index f004bacb9..75207e566 100644 --- a/workflow/engine/classes/WorkspaceTools.php +++ b/workflow/engine/classes/WorkspaceTools.php @@ -3626,59 +3626,36 @@ class WorkspaceTools } /** - * Migrate this workspace table Content. + * Generate update rows from Content sentence * - * @param $className - * @param $fields - * @param mixed|string $lang - * @throws Exception + * @param string $tableName + * @param array $fields + * @param string $lang + * + * @return string */ - public function migrateContentWorkspace($className, $fields, $lang = SYS_LANG) + public function generateUpdateFromContent($tableName, array $fields, $lang = SYS_LANG) { - try { - $this->initPropel(true); - $fieldUidName = $fields['uid']; - $oCriteria = new Criteria(); - $oCriteria->clearSelectColumns(); - $oCriteria->addAsColumn($fieldUidName, ContentPeer::CON_ID); - $oCriteria->addSelectColumn(ContentPeer::CON_PARENT); - $oCriteria->addSelectColumn(ContentPeer::CON_CATEGORY); - $oCriteria->addSelectColumn(ContentPeer::CON_VALUE); - $oCriteria->add(ContentPeer::CON_CATEGORY, $fields['fields'], Criteria::IN); - $oCriteria->add(ContentPeer::CON_LANG, $lang); - $oDataset = ContentPeer::doSelectRS($oCriteria); - $oDataset->setFetchmode(ResultSet::FETCHMODE_ASSOC); - $methods = $fields['methods']; - while ($oDataset->next()) { - $row = $oDataset->getRow(); - $fieldName = $row['CON_CATEGORY']; - $fieldName = isset($fields['alias']) && isset($fields['alias'][$fieldName]) ? $fields['alias'][$fieldName] : $fieldName; - unset($row['CON_CATEGORY']); - $row[$fieldName] = $row['CON_VALUE']; - unset($row['CON_VALUE']); - $oTable = new $className(); - $that = array($oTable, $methods['exists']); - $params = array($row[$fieldUidName]); - if (isset($row['CON_PARENT']) && $row['CON_PARENT'] != '') { - array_push($params, $row['CON_PARENT']); - $fieldName = isset($fields['alias']) && isset($fields['alias']['CON_PARENT']) ? $fields['alias']['CON_PARENT'] : 'CON_PARENT'; - $row[$fieldName] = $row['CON_PARENT']; - } - unset($row['CON_PARENT']); - if (call_user_func_array($that, $params)) { - if (isset($methods['update'])) { - $fn = $methods['update']; - $fn($row); - } else { - $oTable->update($row); - } - } - } - $classNamePeer = class_exists($className . 'Peer') ? $className . 'Peer' : $fields['peer']; - CLI::logging("|--> Add content data in table " . $classNamePeer::TABLE_NAME . "\n"); - } catch (Exception $e) { - throw ($e); + $sql = "UPDATE " . $tableName . " AS T"; + $i = 0; + foreach ($fields['fields'] as $field) { + $i++; + $tableAlias = "C" . $i; + $sql .= " LEFT JOIN CONTENT " . $tableAlias . " ON ("; + $sql .= $tableAlias . ".CON_CATEGORY = '" . $field . "' AND "; + $sql .= $tableAlias . ".CON_ID = T." . $fields['uid'] . " AND "; + $sql .= $tableAlias . ".CON_LANG = '" . $lang . "')"; } + $sql .= ' SET '; + $i = 0; + foreach ($fields['fields'] as $field) { + $i++; + $tableAlias = "C" . $i; + $fieldName = !empty($fields['alias'][$field]) ? $fields['alias'][$field] : $field; + $sql .= $fieldName . " = " . $tableAlias . ".CON_VALUE, "; + } + $sql = rtrim($sql, ', '); + return $sql; } /** @@ -3688,6 +3665,8 @@ class WorkspaceTools * @param array $blackList * * @return array + * + * @throws Exception */ public function migrateContentRun($lang = SYS_LANG, $blackList = []) { @@ -3695,13 +3674,40 @@ class WorkspaceTools define('MEMCACHED_ENABLED', false); } $content = $this->getListContentMigrateTable(); + $contentQueries = []; foreach ($content as $className => $fields) { if (!in_array($className, $blackList)) { - $this->migrateContentWorkspace($className, $fields, $lang); + // Build class peer name + if (class_exists($className . 'Peer')) { + $classNamePeer = $className . 'Peer'; + } else { + $classNamePeer = $fields['peer']; + } + + // Build the query + $query = $this->generateUpdateFromContent($classNamePeer::TABLE_NAME, $fields, $lang); + + // Instantiate the class to execute the query in background + $contentQueries[] = new RunProcessUpgradeQuery($this->name, $query); + + // Add class to the control array $blackList[] = $className; } } + // Run queries in multiple threads + $processesManager = new ProcessesManager($contentQueries); + $processesManager->run(); + + // If exists an error throw an exception + if (!empty($processesManager->getErrors())) { + $errorMessage = ''; + foreach ($processesManager->getErrors() as $error) { + $errorMessage .= $error['rawAnswer'] . PHP_EOL; + } + throw new Exception($errorMessage); + } + return $blackList; } From 3f0f513c7cdf17db16907757a7c0066fd4f05379 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julio=20Cesar=20Laura=20Avenda=C3=B1o?= Date: Fri, 12 Apr 2019 16:17:21 -0400 Subject: [PATCH 09/21] PMC-573 --- workflow/engine/classes/WorkspaceTools.php | 159 +++++++++++++++------ 1 file changed, 115 insertions(+), 44 deletions(-) diff --git a/workflow/engine/classes/WorkspaceTools.php b/workflow/engine/classes/WorkspaceTools.php index 75207e566..e6469c78a 100644 --- a/workflow/engine/classes/WorkspaceTools.php +++ b/workflow/engine/classes/WorkspaceTools.php @@ -2421,6 +2421,13 @@ class WorkspaceTools * @param string $lang * * @return void + * + * @throws Exception + * + * @see \WorkspaceTools->upgrade + * @see \WorkspaceTools->restore + * @see workflow/engine/bin/tasks/cliWorkspaces.php:migrate_new_cases_lists() + * @link https://wiki.processmaker.com/3.3/processmaker_command#migrate-new-cases-lists */ public function migrateList($flagReinsert = false, $lang = 'en') { @@ -2433,7 +2440,7 @@ class WorkspaceTools return; } - $arrayTable1 = ['ListInbox', 'ListMyInbox', 'ListCanceled', 'ListParticipatedLast', 'ListParticipatedHistory', 'ListPaused']; + $arrayTable1 = ['ListCanceled', 'ListMyInbox', 'ListInbox', 'ListParticipatedHistory', 'ListPaused', 'ListParticipatedLast']; $arrayTable2 = ['ListUnassigned', 'ListUnassignedGroup']; $arrayTable = array_merge($arrayTable1, $arrayTable2); @@ -2458,23 +2465,57 @@ class WorkspaceTools } } + $listQueries = []; + if ($flagReinsert || !$flagListAll) { - $this->regenerateListCanceled($lang); - $this->regenerateListMyInbox(); //This list require no translation - $this->regenerateListInbox(); //This list require no translation - $this->regenerateListParticipatedHistory(); //This list require no translation - $this->regenerateListParticipatedLast(); //This list require no translation - $this->regenerateListPaused(); //This list require no translation + // Regenerate lists + $listQueries[] = new RunProcessUpgradeQuery($this->name, $this->regenerateListCanceled($lang)); + $listQueries[] = new RunProcessUpgradeQuery($this->name, $this->regenerateListMyInbox()); + $listQueries[] = new RunProcessUpgradeQuery($this->name, $this->regenerateListInbox()); + $listQueries[] = new RunProcessUpgradeQuery($this->name, $this->regenerateListParticipatedHistory()); + $listQueries[] = new RunProcessUpgradeQuery($this->name, $this->regenerateListPaused()); + $listQueries[] = new RunProcessUpgradeQuery($this->name, $this->regenerateListParticipatedLast()); } if ($flagReinsert || !$flagListUnassigned) { - $this->regenerateListUnassigned(); //This list require no translation + // This list always is truncated + $con = Propel::getConnection("workflow"); + $stmt = $con->createStatement(); + $stmt->executeQuery('TRUNCATE ' . $this->dbName . '.LIST_UNASSIGNED'); + + // Regenerate list + $listQueries[] = new RunProcessUpgradeQuery($this->name, $this->regenerateListUnassigned()); } + // Run queries in multiple threads + $processesManager = new ProcessesManager($listQueries); + $processesManager->run(); + + // If exists an error throw an exception + if (!empty($processesManager->getErrors())) { + $errorMessage = ''; + foreach ($processesManager->getErrors() as $error) { + $errorMessage .= $error['rawAnswer'] . PHP_EOL; + } + throw new Exception($errorMessage); + } + + // This query cannot be launched in parallel, requires that the table already was populated + $this->updateListParticipatedLast(); + $this->listFirstExecution('insert'); $this->listFirstExecution('insert', 'unassigned'); } + /** + * Return query to populate canceled list + * + * @param string $lang + * + * @return string + * + * @see \WorkspaceTools->migrateList() + */ public function regenerateListCanceled($lang = 'en') { $this->initPropel(true); @@ -2537,12 +2578,17 @@ class WorkspaceTools WHERE ACV.APP_STATUS = \'CANCELLED\' AND ACV.DEL_LAST_INDEX = 1'; - $con = Propel::getConnection("workflow"); - $stmt = $con->createStatement(); - $stmt->executeQuery($query); - CLI::logging("> Completed table LIST_CANCELED\n"); + + return $query; } + /** + * Return query to populate my inbox list + * + * @return string + * + * @see \WorkspaceTools->migrateList() + */ public function regenerateListMyInbox() { $this->initPropel(true); @@ -2607,12 +2653,16 @@ class WorkspaceTools ' . $this->dbName . '.USERS PRE_USR ON ACV.PREVIOUS_USR_UID = PRE_USR.USR_UID WHERE ACV.DEL_INDEX=1'; - $con = Propel::getConnection("workflow"); - $stmt = $con->createStatement(); - $stmt->executeQuery($query); - CLI::logging("> Completed table LIST_MY_INBOX\n"); + return $query; } + /** + * Return query to populate inbox list + * + * @return string + * + * @see \WorkspaceTools->migrateList() + */ public function regenerateListInbox() { $this->initPropel(true); @@ -2665,12 +2715,17 @@ class WorkspaceTools ' . $this->dbName . '.USERS USR ON ACV.PREVIOUS_USR_UID = USR.USR_UID WHERE ACV.DEL_THREAD_STATUS = \'OPEN\''; - $con = Propel::getConnection("workflow"); - $stmt = $con->createStatement(); - $stmt->executeQuery($query); - CLI::logging("> Completed table LIST_INBOX\n"); + + return $query; } + /** + * Return query to populate participated history list + * + * @return string + * + * @see \WorkspaceTools->migrateList() + */ public function regenerateListParticipatedHistory() { $this->initPropel(true); @@ -2723,12 +2778,17 @@ class WorkspaceTools ' . $this->dbName . '.USERS CUR_USR ON ACV.USR_UID = CUR_USR.USR_UID LEFT JOIN ' . $this->dbName . '.USERS PRE_USR ON ACV.PREVIOUS_USR_UID = PRE_USR.USR_UID'; - $con = Propel::getConnection("workflow"); - $stmt = $con->createStatement(); - $stmt->executeQuery($query); - CLI::logging("> Completed table LIST_PARTICIPATED_HISTORY\n"); + + return $query; } + /** + * Return query to populate participated last list + * + * @return string + * + * @see \WorkspaceTools->migrateList() + */ public function regenerateListParticipatedLast() { $this->initPropel(true); @@ -2804,10 +2864,18 @@ class WorkspaceTools ) ACV LEFT JOIN ' . $this->dbName . '.USERS PRE_USR ON ACV.PREVIOUS_USR_UID = PRE_USR.USR_UID LEFT JOIN ' . $this->dbName . '.USERS CUR_USR ON ACV.USR_UID = CUR_USR.USR_UID'; - $con = Propel::getConnection("workflow"); - $stmt = $con->createStatement(); - $stmt->executeQuery($query); - CLI::logging("> Inserted data into table LIST_PARTICIPATED_LAST\n"); + + return $query; + } + + /** + * Update participated last list + * + * @see \WorkspaceTools->migrateList() + */ + public function updateListParticipatedLast() + { + $this->initPropel(true); $query = 'UPDATE ' . $this->dbName . '.LIST_PARTICIPATED_LAST LPL, ( SELECT TASK.TAS_TITLE, @@ -2833,18 +2901,19 @@ class WorkspaceTools LPL.DEL_CURRENT_USR_LASTNAME = IFNULL(USERS_VALUES.USR_LASTNAME, \'\'), LPL.DEL_CURRENT_TAS_TITLE = IFNULL(USERS_VALUES.TAS_TITLE, \'\') WHERE LPL.APP_UID = USERS_VALUES.APP_UID'; + + CLI::logging("> Updating the current users data on table LIST_PARTICIPATED_LAST\n"); $con = Propel::getConnection("workflow"); $stmt = $con->createStatement(); - CLI::logging("> Updating the current users data on table LIST_PARTICIPATED_LAST\n"); $stmt->executeQuery($query); - CLI::logging("> Completed table LIST_PARTICIPATED_LAST\n"); } /** - * This function overwrite the table LIST_PAUSED - * Get the principal information in the tables appDelay, appDelegation - * For the labels we use the tables user, process, task and application - * @return void + * Return query to populate paused list + * + * @return string + * + * @see \WorkspaceTools->migrateList() */ public function regenerateListPaused() { @@ -2923,17 +2992,22 @@ class WorkspaceTools APP_DELAY.APP_DISABLE_ACTION_USER = "0" AND APP_DELAY.APP_TYPE = "PAUSE" '; - $con = Propel::getConnection("workflow"); - $stmt = $con->createStatement(); - $stmt->executeQuery($query); - CLI::logging("> Completed table LIST_PAUSED\n"); + + return $query; } /*----------------------------------********---------------------------------*/ + /** + * Return query to populate unassigned list + * + * @return string + * + * @see \WorkspaceTools->migrateList() + */ public function regenerateListUnassigned() { $this->initPropel(true); - $truncate = 'TRUNCATE ' . $this->dbName . '.LIST_UNASSIGNED'; + //This executeQuery is very fast than Propel $query = 'INSERT INTO ' . $this->dbName . '.LIST_UNASSIGNED (APP_UID, @@ -2977,11 +3051,8 @@ class WorkspaceTools WHERE ACV.DEL_THREAD_STATUS = \'OPEN\' AND ACV.USR_UID = \'\' '; - $con = Propel::getConnection("workflow"); - $stmt = $con->createStatement(); - $stmt->executeQuery($truncate); - $stmt->executeQuery($query); - CLI::logging("> Completed table LIST_UNASSIGNED\n"); + + return $query; } /*----------------------------------********---------------------------------*/ From 8ec6c34ecb4213e832fd8876f74883f13fb674d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julio=20Cesar=20Laura=20Avenda=C3=B1o?= Date: Tue, 23 Apr 2019 09:42:25 -0400 Subject: [PATCH 10/21] PMC-594 --- .../engine/classes/MultipleFilesBackup.php | 20 +- workflow/engine/classes/WorkspaceTools.php | 245 ++++++++++-------- 2 files changed, 152 insertions(+), 113 deletions(-) diff --git a/workflow/engine/classes/MultipleFilesBackup.php b/workflow/engine/classes/MultipleFilesBackup.php index 8e06e5852..a3ee55cba 100644 --- a/workflow/engine/classes/MultipleFilesBackup.php +++ b/workflow/engine/classes/MultipleFilesBackup.php @@ -94,11 +94,21 @@ class MultipleFilesBackup } } - /* Restore from file(s) commpressed by letsBackup function, into a temporary directory - * @ filename got the name and path of the compressed file(s), if there are many files with file extention as a numerical series, the extention should be discriminated. - * @ srcWorkspace contains the workspace to be restored. - * @ dstWorkspace contains the workspace to be overwriting. - * @ overwrite got the option true if the workspace will be overwrite. + /** + * Restore from file(s) compressed by letsBackup function, into a temporary directory + * + * @param string $filename Got the name and path of the compressed file(s), if there are many files with file extention as a numerical series, the extention should be discriminated. + * @param string $srcWorkspace Contains the workspace to be restored. + * @param bool $dstWorkspace Contains the workspace to be overwriting. + * @param bool $overwrite Got the option true if the workspace will be overwrite. + * + * @throws Exception + * + * @see workflow/engine/bin/tasks/cliWorkspaces.php::run_workspace_restore() + * + * @link https://wiki.processmaker.com/3.0/Backing_up_and_Restoring_ProcessMaker#RestoringWorkspaces + * + * @deprecated Method outdated, only run the upgrade of APP_CACHE_VIEW table */ public static function letsRestore($filename, $srcWorkspace, $dstWorkspace = null, $overwrite = true) { diff --git a/workflow/engine/classes/WorkspaceTools.php b/workflow/engine/classes/WorkspaceTools.php index e6469c78a..54dc897c6 100644 --- a/workflow/engine/classes/WorkspaceTools.php +++ b/workflow/engine/classes/WorkspaceTools.php @@ -66,6 +66,23 @@ class WorkspaceTools 'UPDATE LIST_UNASSIGNED_GROUP SET USR_ID=(SELECT USR_ID FROM USERS WHERE USERS.USR_UID=LIST_UNASSIGNED_GROUP.USR_UID)', ); + public static $triggers = [ + 'APP_DELEGATION_UPDATE', + 'APPLICATION_UPDATE', + 'CONTENT_UPDATE' + ]; + public static $bigTables = [ + 'APPLICATION', + 'APP_ASSIGN_SELF_SERVICE_VALUE_GROUP', + 'APP_CACHE_VIEW', + 'APP_DELEGATION', + 'APP_DELAY', + 'APP_DOCUMENT', + 'APP_HISTORY', + 'APP_MESSAGE', + 'GROUP_USER', + 'LOGIN_LOG' + ]; private $lastContentMigrateTable = false; private $listContentMigrateTable = []; @@ -249,18 +266,16 @@ class WorkspaceTools $this->checkMafeRequirements($workspace, $lang); CLI::logging("* End checking MAFE requirements...(Completed on " . (microtime(true) - $start) . " seconds)\n"); - CLI::logging("* Start deleting MySQL triggers: APP_DELEGATION_UPDATE, APPLICATION_UPDATE, CONTENT_UPDATE...\n"); + CLI::logging("* Start deleting MySQL triggers: " . implode(', ', self::$triggers) . "...\n"); $start = microtime(true); - $this->deleteTriggersMySQL(['APP_DELEGATION_UPDATE', 'APPLICATION_UPDATE', 'CONTENT_UPDATE']); - CLI::logging("* End deleting MySQL triggers: APP_DELEGATION_UPDATE, APPLICATION_UPDATE, CONTENT_UPDATE... (Completed on " . + $this->deleteTriggersMySQL(self::$triggers); + CLI::logging("* End deleting MySQL triggers: " . implode(', ', self::$triggers) . "... (Completed on " . (microtime(true) - $start) . " seconds)\n"); - $bigTables = ['APPLICATION', 'APP_ASSIGN_SELF_SERVICE_VALUE_GROUP', 'APP_CACHE_VIEW', 'APP_DELEGATION', 'APP_DELAY', - 'APP_DOCUMENT', 'APP_HISTORY', 'APP_MESSAGE', 'GROUP_USER', 'LOGIN_LOG']; - CLI::logging("* Start deleting indexes from big tables: " . implode(', ', $bigTables) . "...\n"); + CLI::logging("* Start deleting indexes from big tables: " . implode(', ', self::$bigTables) . "...\n"); $start = microtime(true); - $this->deleteIndexes($bigTables); - CLI::logging("* End deleting indexes from big tables: " . implode(', ', $bigTables) . "... (Completed on " . + $this->deleteIndexes(self::$bigTables); + CLI::logging("* End deleting indexes from big tables: " . implode(', ', self::$bigTables) . "... (Completed on " . (microtime(true) - $start) . " seconds)\n"); CLI::logging("* Start to update CONTENT table...\n"); @@ -1855,7 +1870,7 @@ class WorkspaceTools } /** - * restore an archive into a workspace + * Restore a workspace * * Restores any database and files included in the backup, either as a new * workspace, or overwriting a previous one @@ -1866,8 +1881,13 @@ class WorkspaceTools * @param boolean $overwrite if you need overwrite the database * @param string $lang for define the language * @param string $port of database if is empty take 3306 + * @param array $optionMigrateHistoryData * * @throws Exception + * + * @see workflow/engine/bin/tasks/cliWorkspaces.php::run_workspace_restore() + * + * @link https://wiki.processmaker.com/3.0/Backing_up_and_Restoring_ProcessMaker#RestoringWorkspaces */ public static function restore($filename, $srcWorkspace, $dstWorkspace = null, $overwrite = true, $lang = 'en', $port = '', $optionMigrateHistoryData = []) { @@ -2035,115 +2055,124 @@ class WorkspaceTools } } - $start = microtime(true); - CLI::logging("> Remove deprecated files...\n"); - $workspace->removeDeprecatedFiles(); - $stop = microtime(true); - CLI::logging("<*> Remove deprecated files took " . ($stop - $start) . " seconds.\n"); - - if (($pmVersionWorkspaceToRestore != '') && (version_compare( - $pmVersionWorkspaceToRestore . "", - $pmVersion . "", - "<" - ) || $pmVersion == "") - ) { - $start = microtime(true); - CLI::logging("> Updating database...\n"); - $workspace->upgradeDatabase($onedb); - $stop = microtime(true); - CLI::logging("<*> Database Upgrade Process took " . ($stop - $start) . " seconds.\n"); - } - - $start = microtime(true); - CLI::logging("> Verify files enterprise old...\n"); - $workspace->verifyFilesOldEnterprise($workspaceName); - $stop = microtime(true); - CLI::logging("<*> Verify took " . ($stop - $start) . " seconds.\n"); - - $start = microtime(true); - CLI::logging("> Verify License Enterprise...\n"); - $workspace->verifyLicenseEnterprise($workspaceName); - $stop = microtime(true); - CLI::logging("<*> Verify took " . ($stop - $start) . " seconds.\n"); - - $start = microtime(true); - CLI::logging("> Check Mafe Requirements...\n"); - $workspace->checkMafeRequirements($workspaceName, $lang); - $stop = microtime(true); - CLI::logging("<*> Check Mafe Requirements Process took " . ($stop - $start) . " seconds.\n"); - - if (($pmVersionWorkspaceToRestore != '') && (version_compare( - $pmVersionWorkspaceToRestore . "", - $pmVersion . "", - "<" - ) || $pmVersion == "") - ) { - $start = microtime(true); - CLI::logging("> Updating cache view...\n"); - $workspace->upgradeCacheView(true, true, $lang); - $stop = microtime(true); - CLI::logging("<*> Updating cache view Process took " . ($stop - $start) . " seconds.\n"); - } else { - $workspace->upgradeTriggersOfTables(true, $lang); - } - - if ($pmVersion == '' && strpos(strtoupper($version), 'BRANCH')) { + if (empty($pmVersion) && strpos(strtoupper($version), 'BRANCH')) { $pmVersion = 'dev-version-backup'; } - //Move the labels of content to the corresponding table - $start = microtime(true); - CLI::logging("> Optimizing content data...\n"); - $workspace->migrateContent($workspace->name, $lang); - $stop = microtime(true); - CLI::logging("<*> Optimizing content data took " . ($stop - $start) . " seconds.\n"); + if (!empty($pmVersionWorkspaceToRestore) && (version_compare( + $pmVersionWorkspaceToRestore . "", + $pmVersion . "", + "<" + ) || empty($pmVersion)) || $pmVersion == "dev-version-backup" + ) { + // Upgrade the database schema and data + CLI::logging("* Start updating database schema...\n"); + $start = microtime(true); + $workspace->upgradeDatabase(); + CLI::logging("* End updating database schema...(Completed on " . (microtime(true) - $start) . " seconds)\n"); - //Populate the new fields for replace string UID to Interger ID - $start = microtime(true); - CLI::logging("> Migrating and populating indexing for APP_CACHE_VIEW...\n"); - $workspace->migratePopulateIndexingACV($workspace->name); - $stop = microtime(true); - CLI::logging("<*> Migrating an populating indexing for APP_CACHE_VIEW process took " . ($stop - $start) . " seconds.\n"); + CLI::logging("* Start checking MAFE requirements...\n"); + $start = microtime(true); + $workspace->checkMafeRequirements($workspaceName, $lang); + CLI::logging("* End checking MAFE requirements...(Completed on " . (microtime(true) - $start) . " seconds)\n"); - //Move the data of cases to the corresponding List - /*----------------------------------********---------------------------------*/ - $start = microtime(true); - CLI::logging("> Updating List tables...\n"); - $workspace->migrateList($workspace->name, false, $lang); - $stop = microtime(true); - CLI::logging("<*> Updating List Process took " . ($stop - $start) . " seconds.\n"); - /*----------------------------------********---------------------------------*/ + CLI::logging("* Start deleting MySQL triggers: " . implode(', ', self::$triggers) . "...\n"); + $start = microtime(true); + $workspace->deleteTriggersMySQL(self::$triggers); + CLI::logging("* End deleting MySQL triggers: " . implode(', ', self::$triggers) . "... (Completed on " . + (microtime(true) - $start) . " seconds)\n"); - $start = microtime(true); - CLI::logging("> Updating Files Manager...\n"); - $workspace->processFilesUpgrade(); - $stop = microtime(true); - CLI::logging("<*> Updating Files Manager took " . ($stop - $start) . " seconds.\n"); + CLI::logging("* Start deleting indexes from big tables: " . implode(', ', self::$bigTables) . "...\n"); + $start = microtime(true); + $workspace->deleteIndexes(self::$bigTables); + CLI::logging("* End deleting indexes from big tables: " . implode(', ', self::$bigTables) . "... (Completed on " . + (microtime(true) - $start) . " seconds)\n"); - //Updating generated class files for PM Tables - passthru(PHP_BINARY . ' processmaker regenerate-pmtable-classes ' . $workspace->name); + $start = microtime(true); + CLI::logging("* Start to migrate texts/values from 'CONTENT' table to the corresponding object tables...\n"); + $workspace->migrateContent($lang); + CLI::logging("* End to migrate texts/values from 'CONTENT' table to the corresponding object tables... (Completed on " . + (microtime(true) - $start) . " seconds)\n"); - $keepDynContent = isset($optionMigrateHistoryData['keepDynContent']) && $optionMigrateHistoryData['keepDynContent'] === true; - //Review if we need to remove the 'History of use' from APP_HISTORY - $start = microtime(true); - CLI::logging("> Clearing History of Use from APP_HISTORY table...\n"); - $workspace->clearDynContentHistoryData(false, $keepDynContent); - $stop = microtime(true); - CLI::logging("<*> Clearing History of Use from APP_HISTORY table took " . ($stop - $start) . " seconds.\n"); + CLI::logging("* Start updating rows in Web Entry table for classic processes...\n"); + $start = microtime(true); + $workspace->updatingWebEntryClassicModel(true); + CLI::logging("* End updating rows in Web Entry table for classic processes...(Completed on " . + (microtime(true) - $start) . " seconds)\n"); - /*----------------------------------********---------------------------------*/ - $start = microtime(true); - CLI::logging("> Migrating history data...\n"); - $workspace->migrateAppHistoryToAppDataChangeLog(false); - $stop = microtime(true); - CLI::logging("<*> Migrating history data took " . ($stop - $start) . " seconds.\n"); - /*----------------------------------********---------------------------------*/ + CLI::logging("* Start to update Files Manager...\n"); + $start = microtime(true); + $workspace->processFilesUpgrade($workspaceName); + CLI::logging("* End to update Files Manager... (Completed on " . (microtime(true) - $start) . " seconds)\n"); + CLI::logging("* Start migrating and populating plugin singleton data...\n"); + $start = microtime(true); + $workspace->migrateSingleton($workspaceName); + CLI::logging("* End migrating and populating plugin singleton data...(Completed on " . + (microtime(true) - $start) . " seconds)\n"); + + CLI::logging("* Start to check Intermediate Email Event...\n"); + $start = microtime(true); + $workspace->checkIntermediateEmailEvent(); + CLI::logging("* End to check Intermediate Email Event... (Completed on " . (microtime(true) - $start) . " seconds)\n"); + + CLI::logging("* Start cleaning DYN_CONTENT in APP_HISTORY...\n"); + $start = microtime(true); + $keepDynContent = isset($optionMigrateHistoryData['keepDynContent']) && $optionMigrateHistoryData['keepDynContent'] === true; + $workspace->clearDynContentHistoryData(false, $keepDynContent); + CLI::logging("* End cleaning DYN_CONTENT in APP_HISTORY...(Completed on " . (microtime(true) - $start) . " seconds)\n"); + + /*----------------------------------********---------------------------------*/ + CLI::logging("* Start migrating history data...\n"); + $start = microtime(true); + $workspace->migrateAppHistoryToAppDataChangeLog(false); + CLI::logging("* End migrating history data...(Completed on " . (microtime(true) - $start) . " seconds)\n"); + /*----------------------------------********---------------------------------*/ + + CLI::logging("* Start migrating and populating indexing for avoiding the use of table APP_CACHE_VIEW...\n"); + $start = microtime(true); + $workspace->migratePopulateIndexingACV(); + CLI::logging("* End migrating and populating indexing for avoiding the use of table APP_CACHE_VIEW...(Completed on " . + (microtime(true) - $start) . " seconds)\n"); + + CLI::logging("* Start optimizing Self-Service data in table APP_ASSIGN_SELF_SERVICE_VALUE_GROUP....\n"); + $start = microtime(true); + $workspace->migrateSelfServiceRecordsRun(); + CLI::logging("* End optimizing Self-Service data in table APP_ASSIGN_SELF_SERVICE_VALUE_GROUP....(Completed on " . + (microtime(true) - $start) . " seconds)\n"); + + CLI::logging("* Start adding new fields and populating values in tables related to feature self service by value...\n"); + $start = microtime(true); + $workspace->upgradeSelfServiceData(); + CLI::logging("* End adding new fields and populating values in tables related to feature self service by value...(Completed on " . + (microtime(true) - $start) . " seconds)\n"); + + CLI::logging("* Start adding/replenishing all indexes...\n"); + $start = microtime(true); + $systemSchema = System::getSystemSchema($workspace->dbAdapter); + $workspace->upgradeSchema($systemSchema); + CLI::logging("* End adding/replenishing all indexes...(Completed on " . (microtime(true) - $start) . " seconds)\n"); + + /*----------------------------------********---------------------------------*/ + CLI::logging("* Start migrating to new list tables...\n"); + $start = microtime(true); + $workspace->migrateList(true, $lang); + CLI::logging("* End migrating to new list tables...(Completed on " . (microtime(true) - $start) . " seconds)\n"); + /*----------------------------------********---------------------------------*/ + + CLI::logging("* Start updating MySQL triggers...\n"); + $start = microtime(true); + $workspace->updateTriggers(true, $lang); + CLI::logging("* End updating MySQL triggers...(" . (microtime(true) - $start) . " seconds)\n"); + } + + CLI::logging("> Start To Verify License Enterprise...\n"); $start = microtime(true); - CLI::logging("> Optimizing Self-Service data in table APP_ASSIGN_SELF_SERVICE_VALUE_GROUP....\n"); - $workspace->upgradeSelfServiceData(); - $stop = microtime(true); - CLI::logging("<*> Optimizing Self-Service data in table APP_ASSIGN_SELF_SERVICE_VALUE_GROUP took " . ($stop - $start) . " seconds.\n"); + $workspace->verifyLicenseEnterprise($workspaceName); + CLI::logging("* End To Verify License Enterprise...(" . (microtime(true) - $start) . " seconds)\n"); + + // Updating generated class files for PM Tables + passthru(PHP_BINARY . ' processmaker regenerate-pmtable-classes ' . $workspaceName); } CLI::logging("Removing temporary files\n"); @@ -2319,7 +2348,7 @@ class WorkspaceTools CLI::logging(" Migrating Enterprise Core version...\n"); if (!file_exists($pathNewFile)) { CLI::logging(" Creating folder in $pathNewFile\n"); - G::mk_dir($newDiretory, 0777); + G::mk_dir($pathNewFile, 0777); } $shared_stat = stat(PATH_DATA); if (file_exists($pathDirectoryEnterprise)) { From b29170b87bf6534f5c3d784514a7e3cb0d847cd4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julio=20Cesar=20Laura=20Avenda=C3=B1o?= Date: Mon, 18 Mar 2019 13:36:08 -0400 Subject: [PATCH 11/21] PMC-565 --- bootstrap/classaliasmap.php | 1 - workflow/engine/bin/tasks/cliUpgrade.php | 287 +++++++++--------- workflow/engine/bin/tasks/cliWorkspaces.php | 85 +----- workflow/engine/classes/Upgrade.php | 128 -------- workflow/engine/classes/WorkspaceTools.php | 273 ++++++++--------- .../engine/classes/model/AddonsManager.php | 8 +- .../engine/src/ProcessMaker/Core/System.php | 33 -- 7 files changed, 268 insertions(+), 547 deletions(-) delete mode 100644 workflow/engine/classes/Upgrade.php diff --git a/bootstrap/classaliasmap.php b/bootstrap/classaliasmap.php index 62e24f3f0..734997540 100644 --- a/bootstrap/classaliasmap.php +++ b/bootstrap/classaliasmap.php @@ -80,7 +80,6 @@ return array( 'ToolBar' => ToolBar::class, 'Tree' => PmTree::class, 'triggerLibrary' => TriggerLibrary::class, - 'Upgrade' => Upgrade::class, 'workspaceTools' => WorkspaceTools::class, 'wsBase' => WsBase::class, 'wsResponse' => WsResponse::class, diff --git a/workflow/engine/bin/tasks/cliUpgrade.php b/workflow/engine/bin/tasks/cliUpgrade.php index a1d181dcf..d09d3adff 100644 --- a/workflow/engine/bin/tasks/cliUpgrade.php +++ b/workflow/engine/bin/tasks/cliUpgrade.php @@ -5,14 +5,16 @@ use ProcessMaker\Core\System; CLI::taskName('upgrade'); CLI::taskDescription("Upgrade workspaces.\n\n This command should be run after upgrading ProcessMaker to a new version so that all workspaces are also upgraded to the\n new version."); - +CLI::taskOpt('child', "Used by the main upgrade thread", 'child', 'child'); CLI::taskOpt('buildACV', 'If this option is enabled, the Cache View is built.', 'ACV', 'buildACV'); CLI::taskOpt('noxml', 'If this option is enabled, the XML files translation is not built.', 'NoXml', 'no-xml'); +CLI::taskOpt('nomafe', 'If this option is enabled, the MAFE files translation is not built.', 'nomafe', 'no-mafe'); /*----------------------------------********---------------------------------*/ CLI::taskOpt('keep_dyn_content', "Include the DYN_CONTENT_HISTORY value. Ex: --keep_dyn_content", 'i', 'keep_dyn_content'); /*----------------------------------********---------------------------------*/ CLI::taskRun("run_upgrade"); /*----------------------------------********---------------------------------*/ + CLI::taskName('unify-database'); CLI::taskDescription( << $workspace) { - $oneWorkspace = $workspace->name; + // Initializing variables + $globalStartTime = microtime(true); + $numberOfWorkspaces = count($workspaces); + $countWorkspace = 1; + + if ($printHF) { + // Set upgrade flag + if (count($workspaces) === 1) { + // For the specific workspace send in the command + G::isPMUnderUpdating(1, $workspaces[0]->name); + } else { + // For all workspaces + G::isPMUnderUpdating(1); } + + // Print information when start the upgrade process + CLI::logging('UPGRADE LOG INITIALIZED', PROCESSMAKER_PATH . 'upgrade.log'); + CLI::logging("UPGRADE STARTED\n"); } - $flag = G::isPMUnderUpdating(1, $oneWorkspace); - //start to upgrade - $checksum = System::verifyChecksum(); - if ($checksum === false) { - 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"); - $flag = G::isPMUnderUpdating(0); - die(); - } - } else { - if (!empty($checksum['missing'])) { - CLI::logging(CLI::error("The following files were not found in the installation:")."\n"); - foreach ($checksum['missing'] as $missing) { - CLI::logging(" $missing\n"); + + foreach ($workspaces as $workspace) { + if ($mainThread) { + CLI::logging("FOLDERS AND FILES OF THE SYSTEM\n"); + // Upgrade actions for global files + CLI::logging("* Start cleaning compiled folder...\n"); + $start = microtime(true); + if (defined('PATH_C')) { + G::rm_dir(PATH_C); + G::mk_dir(PATH_C, 0777); } - } - if (!empty($checksum['diff'])) { - CLI::logging(CLI::error("The following files have modifications:")."\n"); - foreach ($checksum['diff'] as $diff) { - CLI::logging(" $diff\n"); + CLI::logging("* End cleaning compiled folder...(Completed on " . (microtime(true) - $start) . " seconds)\n"); + + CLI::logging("* Start to remove deprecated files...\n"); + $start = microtime(true); + $workspace->removeDeprecatedFiles(); + CLI::logging("* End to remove deprecated files...(Completed on " . (microtime(true) - $start) . " seconds)\n"); + + CLI::logging("* Start checking Enterprise folder/files...\n"); + $start = microtime(true); + $workspace->verifyFilesOldEnterprise(); + CLI::logging("* End checking Enterprise folder/files...(Completed on " . (microtime(true) - $start) . " seconds)\n"); + + CLI::logging("* Start checking framework paths...\n"); + $start = microtime(true); + $workspace->checkFrameworkPaths(); + CLI::logging("* End checking framework paths...(Completed on " . (microtime(true) - $start) . " seconds)\n"); + + CLI::logging("* Start fixing serialized instance in serverConf.singleton file...\n"); + $start = microtime(true); + $serverConf = ServerConf::getSingleton(); + $serverConf->updateClassNameInFile(); + CLI::logging("* End fixing serialized instance in serverConf.singleton file...(Completed on " . + (microtime(true) - $start) . " seconds)\n"); + + CLI::logging("* Start the safe upgrade for javascript files cached by the browser (Maborak, ExtJs)...\n"); + $start = microtime(true); + G::browserCacheFilesSetUid(); + CLI::logging("* End the safe upgrade for javascript files cached by the browser (Maborak, ExtJs)...(Completed on " . + (microtime(true) - $start) . " seconds)\n"); + + CLI::logging("* Start to backup patch files...\n"); + $arrayPatch = glob(PATH_TRUNK . 'patch-*'); + if ($arrayPatch) { + foreach ($arrayPatch as $value) { + if (file_exists($value)) { + // Copy patch content + $names = pathinfo($value); + $nameFile = $names['basename']; + + $contentFile = file_get_contents($value); + $contentFile = preg_replace("[\n|\r|\n\r]", '', $contentFile); + CLI::logging($contentFile . ' installed (' . $nameFile . ')', PATH_DATA . 'log/upgrades.log'); + + // Move patch file + $newFile = PATH_DATA . $nameFile; + G::rm_dir($newFile); + copy($value, $newFile); + G::rm_dir($value); + } + } } - } - if (!(empty($checksum['missing']) || empty($checksum['diff']))) { - if (!CLI::question("Integrity check failed, do you want to continue the upgrade?")) { - CLI::logging("Upgrade failed\n"); - $flag = G::isPMUnderUpdating(0); - die(); - } - } - } - CLI::logging("Clearing cache...\n"); - if (defined('PATH_C')) { - G::rm_dir(PATH_C); - G::mk_dir(PATH_C, 0777); - } + CLI::logging("* End to backup patch files...(Completed on " . (microtime(true) - $start) . " seconds)\n"); - $count = count($workspaces); - $first = true; - $errors = false; - $countWorkspace = 0; - $buildCacheView = array_key_exists('buildACV', $args); - $flagUpdateXml = !array_key_exists('noxml', $args); - $optionMigrateHistoryData = [ - /*----------------------------------********---------------------------------*/ - 'keepDynContent' => array_key_exists('keep_dyn_content', $args) - /*----------------------------------********---------------------------------*/ - ]; + CLI::logging("* Start to backup log files...\n"); + $start = microtime(true); + $workspace->backupLogFiles(); + CLI::logging("* End to backup log files... (Completed on " . (microtime(true) - $start) . " seconds)\n"); - foreach ($workspaces as $index => $workspace) { - if (empty(config("system.workspace"))) { - define("SYS_SYS", $workspace->name); - config(["system.workspace" => $workspace->name]); + // The previous actions should be executed only the first time + $mainThread = false; } + if ($numberOfWorkspaces === 1) { + // Displaying information of the current workspace to upgrade + CLI::logging("UPGRADING DATABASE AND FILES OF WORKSPACE '{$workspace->name}' ($countWorkspace/$numberOfWorkspaces)\n"); - if (!defined("PATH_DATA_SITE")) { - define("PATH_DATA_SITE", PATH_DATA . "sites" . PATH_SEP . config("system.workspace") . PATH_SEP); - } + // Build parameters + $arrayOptTranslation = [ + 'updateXml' => $updateXmlForms, + 'updateMafe' => $updateMafe + ]; + $optionMigrateHistoryData = [ + 'keepDynContent' => $keepDynContent + ]; - if (!defined('DB_ADAPTER')) { - define('DB_ADAPTER', 'mysql'); - } - - try { - $countWorkspace++; - CLI::logging("Upgrading workspaces ($countWorkspace/$count): " . CLI::info($workspace->name) . "\n"); - $workspace->upgrade($buildCacheView, $workspace->name, false, 'en', ['updateXml' => $flagUpdateXml, 'updateMafe' => $first], $optionMigrateHistoryData); + // Upgrade database and files from a specific workspace + $workspace->upgrade($workspace->name, true, SYS_LANG, $arrayOptTranslation, $optionMigrateHistoryData); $workspace->close(); - $first = false; - $flagUpdateXml = false; - } catch (Exception $e) { - CLI::logging("Errors upgrading workspace " . CLI::info($workspace->name) . ": " . CLI::error($e->getMessage()) . "\n"); - $errors = true; + } else { + // Build arguments + $args = '--child'; + $args .= $updateXmlForms ? '' : ' --no-xml'; + $args .= $updateMafe ? '' : ' --no-mafe'; + $args .= $keepDynContent ? ' --keep_dyn_content' : ''; + + // Build and execute command in another thread + $command = PHP_BINARY . ' processmaker upgrade ' . $args . ' ' . $workspace->name; + passthru($command); } + + // After the first execution is required set this values to false + $updateXmlForms = false; + $updateMafe = false; + + // Increment workspaces counter + $countWorkspace++; } - //Verify the information of the singleton ServConf by changing the name of the class if is required. - CLI::logging("\nCheck/Fix serialized instance in serverConf.singleton file\n\n"); - $serverConf = ServerConf::getSingleton(); - $serverConf->updateClassNameInFile(); + if ($printHF) { + // Print information when finish the upgrade process + CLI::logging('UPGRADE FINISHED (Completed on ' . (microtime(true) - $globalStartTime) . + ' seconds), ProcessMaker ' . System::getVersion() . ' installed)' . "\n\n"); - // SAVE Upgrades/Patches - $arrayPatch = glob(PATH_TRUNK . 'patch-*'); - - if ($arrayPatch) { - foreach ($arrayPatch as $value) { - if (file_exists($value)) { - // copy content the patch - $names = pathinfo($value); - $nameFile = $names['basename']; - - $contentFile = file_get_contents($value); - $contentFile = preg_replace("[\n|\r|\n\r]", '', $contentFile); - CLI::logging($contentFile . ' installed (' . $nameFile . ')', PATH_DATA . 'log/upgrades.log'); - - // move file of patch - $newFile = PATH_DATA . $nameFile; - G::rm_dir($newFile); - copy($value, $newFile); - G::rm_dir($value); - } - } - } else { - CLI::logging('ProcessMaker ' . System::getVersion(). ' installed', PATH_DATA . 'log/upgrades.log'); + // Delete upgrade flag + G::isPMUnderUpdating(0); } - - //Safe upgrade for JavaScript files - CLI::logging("\nSafe upgrade for files cached by the browser\n\n"); - - G::browserCacheFilesSetUid(); - - //Status - if ($errors) { - CLI::logging("Upgrade finished but there were errors upgrading workspaces.\n"); - CLI::logging(CLI::error("Please check the log above to correct any issues.") . "\n"); - } else { - CLI::logging("Upgrade successful\n"); - } - - //setting flag to false - $flag = G::isPMUnderUpdating(0); } -function listFiles($dir) -{ - $files = array(); - $lista = glob($dir.'/*'); - foreach ($lista as $valor) { - if (is_dir($valor)) { - $inner_files = listFiles($valor); - if (is_array($inner_files)) { - $files = array_merge($files, $inner_files); - } - } - if (is_file($valor)) { - array_push($files, $valor); - } - } - return $files; -} /*----------------------------------********---------------------------------*/ function run_unify_database($args) { diff --git a/workflow/engine/bin/tasks/cliWorkspaces.php b/workflow/engine/bin/tasks/cliWorkspaces.php index 13df97e38..518d9d5a5 100644 --- a/workflow/engine/bin/tasks/cliWorkspaces.php +++ b/workflow/engine/bin/tasks/cliWorkspaces.php @@ -106,26 +106,6 @@ EOT CLI::taskArg('workspace', true, true); CLI::taskRun("run_plugins_database_upgrade"); -CLI::taskName('workspace-upgrade'); -CLI::taskDescription(<<name); - } - } -} - -/** - * This function is executed only by one workspace, for the command workspace-upgrade - * - * @param array $args, workspace name for to apply the upgrade - * @param array $opts, specify additional arguments for language, flag for buildACV, flag for noxml - * - * @return void - */ -function workspace_upgrade($args, $opts) { - $first = true; - $workspaces = get_workspaces_from_args($args); - $lang = array_key_exists("lang", $opts) ? $opts['lang'] : 'en'; - $buildCacheView = array_key_exists('buildACV', $opts); - $flagUpdateXml = !array_key_exists('noxml', $opts); - - $wsName = $workspaces[key($workspaces)]->name; - Bootstrap::setConstantsRelatedWs($wsName); - //Loop, read all the attributes related to the one workspace - foreach ($workspaces as $workspace) { - try { - $workspace->upgrade( - $buildCacheView, - $workspace->name, - false, - $lang, - ['updateXml' => $flagUpdateXml, 'updateMafe' => $first] - ); - $first = false; - $flagUpdateXml = false; - } catch (Exception $e) { - G::outRes("Errors upgrading workspace " . CLI::info($workspace->name) . ": " . CLI::error($e->getMessage()) . "\n"); - } - } -} - /** * We will upgrade the CONTENT table * If we apply the command for all workspaces, we will need to execute one by one by redefining the constants @@ -1210,7 +1127,7 @@ function migrate_content($args, $opts) foreach ($workspaces as $workspace) { print_r('Regenerating content in: ' . pakeColor::colorize($workspace->name, 'INFO') . "\n"); CLI::logging("-> Regenerating content \n"); - $workspace->migrateContentRun($workspace->name, $lang); + $workspace->migrateContentRun($lang); } $stop = microtime(true); CLI::logging("<*> Optimizing content data Process took " . ($stop - $start) . " seconds.\n"); diff --git a/workflow/engine/classes/Upgrade.php b/workflow/engine/classes/Upgrade.php deleted file mode 100644 index 67fa51dcf..000000000 --- a/workflow/engine/classes/Upgrade.php +++ /dev/null @@ -1,128 +0,0 @@ -addon = $addon; - } - - public function install() - { - - $filter = new InputFilter(); - $start = microtime(1); - $filename = $this->addon->getDownloadFilename(); - $time = microtime(1); - - $archive = new Archive_Tar ($filename); - $time = microtime(1); - $extractDir = dirname($this->addon->getDownloadFilename()) . "/extract"; - $extractDir = $filter->xssFilterHard($extractDir); - $backupDir = dirname($this->addon->getDownloadFilename()) . "/backup"; - $backupDir = $filter->xssFilterHard($backupDir); - if (file_exists($extractDir)) { - G::rm_dir($extractDir); - } - if (file_exists($backupDir)) { - G::rm_dir($backupDir); - } - if (!is_dir($backupDir)) { - mkdir($backupDir); - } - - $time = microtime(1); - echo "Extracting files...\n"; - $archive->extractModify($extractDir, 'processmaker'); - $checksumFile = file_get_contents("$extractDir/checksum.txt"); - $time = microtime(1); - $checksums = array(); - foreach (explode("\n", $checksumFile) as $line) { - $checksums[trim(substr($line, 33))] = substr($line, 0, 32); - } - - $checksum = array(); - $changedFiles = array(); - $time = microtime(1); - $files = $this->ls_dir($extractDir); - - echo "Updating ProcessMaker files...\n"; - $time = microtime(1); - $checksumTime = 0; - foreach ($checksums as $filename => $checksum) { - if (is_dir("$extractDir/$filename")) { - $filename = $filter->xssFilterHard($filename); - print $filename; - continue; - } - $installedFile = PATH_TRUNK . "/$filename"; - if (!file_exists($installedFile)) { - $installedMD5 = ""; - } else { - $time = microtime(1); - $installedMD5 = G::encryptFileOld($installedFile); - $checksumTime += microtime(1) - $time; - } - $archiveMD5 = $checksum; - if (strcasecmp($archiveMD5, $installedMD5) != 0) { - $changedFiles[] = $filename; - if (!is_dir(dirname($backupDir.'/'.$filename))) { - mkdir(dirname($backupDir.'/'.$filename), 0777, true); - } - if (file_exists($installedFile) && is_file($installedFile)) { - copy($installedFile, $backupDir.'/'.$filename); - } - if (!is_dir(dirname($installedFile))) { - mkdir(dirname($installedFile), 0777, true); - } - if (!copy("$extractDir/$filename", $installedFile)) { - throw new Exception("Could not overwrite '$filename'"); - } - } - } - - printf("Updated %d files\n", count($changedFiles)); - printf("Clearing cache...\n"); - if (defined('PATH_C')) { - G::rm_dir(PATH_C); - mkdir(PATH_C, 0777, true); - } - $workspaces = System::listWorkspaces(); - $count = count($workspaces); - $first = true; - $num = 0; - foreach ($workspaces as $index => $workspace) { - try { - $num += 1; - printf("Upgrading workspaces ($num/$count): {$workspace->name}\n"); - $workspace->upgrade(false, config("system.workspace"), false, 'en', ['updateXml' => $first, 'updateMafe' => $first]); - $workspace->close(); - $first = false; - } catch (Exception $e) { - printf("Errors upgrading workspace {$workspace->name}: {$e->getMessage()}\n"); - } - } - } - - private function ls_dir($dir, $basename = null) - { - $files = array(); - if ($basename == null) { - $basename = $dir; - } - foreach (glob("$dir/*") as $filename) { - if (is_dir($filename)) { - $files = array_merge($files, $this->ls_dir($filename, $basename)); - } else { - $files[] = substr($filename, strlen($basename) + 1); - } - } - return $files; - } - -} diff --git a/workflow/engine/classes/WorkspaceTools.php b/workflow/engine/classes/WorkspaceTools.php index 62a3713a5..cdd9e075e 100644 --- a/workflow/engine/classes/WorkspaceTools.php +++ b/workflow/engine/classes/WorkspaceTools.php @@ -218,160 +218,115 @@ class WorkspaceTools /** * Upgrade this workspace to the latest system version * - * @param bool $buildCacheView - * @param string $workSpace + * @param string $workspace * @param bool $onedb * @param string $lang * @param array $arrayOptTranslation + * @param array $optionMigrateHistoryData * * @return void */ - public function upgrade($buildCacheView = false, $workSpace = null, $onedb = false, $lang = 'en', array $arrayOptTranslation = null, $optionMigrateHistoryData = []) + public function upgrade($workspace, $onedb = false, $lang = 'en', array $arrayOptTranslation = null, $optionMigrateHistoryData = []) { - if ($workSpace === null) { - $workSpace = config("system.workspace"); - } if (is_null($arrayOptTranslation)) { $arrayOptTranslation = ['updateXml' => true, 'updateMafe' => true]; } + CLI::logging("* Start updating database schema...\n"); $start = microtime(true); - CLI::logging("> Remove deprecated files...\n"); - $this->removeDeprecatedFiles(); - $stop = microtime(true); - CLI::logging("<*> Remove deprecated files took " . ($stop - $start) . " seconds.\n"); - - $start = microtime(true); - CLI::logging("> Updating database...\n"); $this->upgradeDatabase($onedb); - $stop = microtime(true); - CLI::logging("<*> Database Upgrade Process took " . ($stop - $start) . " seconds.\n"); + CLI::logging("* End updating database schema...(Completed on " . (microtime(true) - $start) . " seconds)\n"); + CLI::logging("* Start updating translations...\n"); $start = microtime(true); - CLI::logging("> Check Intermediate Email Event...\n"); - $this->checkIntermediateEmailEvent(); - $stop = microtime(true); - CLI::logging("<*> Database Upgrade Process took " . ($stop - $start) . " seconds.\n"); - - $start = microtime(true); - CLI::logging("> Verify enterprise old...\n"); - $this->verifyFilesOldEnterprise($workSpace); - $stop = microtime(true); - CLI::logging("<*> Verify took " . ($stop - $start) . " seconds.\n"); - - $start = microtime(true); - CLI::logging("> Updating translations...\n"); $this->upgradeTranslation($arrayOptTranslation['updateXml'], $arrayOptTranslation['updateMafe']); - $stop = microtime(true); - $final = $stop - $start; - CLI::logging("<*> Updating Translations Process took $final seconds.\n"); + CLI::logging("* End updating translations...(Completed on " . (microtime(true) - $start) . " seconds)\n"); + + CLI::logging("* Start checking MAFE requirements...\n"); + $start = microtime(true); + $this->checkMafeRequirements($workspace, $lang); + CLI::logging("* End checking MAFE requirements...(Completed on " . (microtime(true) - $start) . " seconds)\n"); + + CLI::logging("* Start to update CONTENT table...\n"); + $start = microtime(true); + $this->upgradeContent($workspace); + CLI::logging("* End to update CONTENT table... (Completed on " . (microtime(true) - $start) . " seconds)\n"); $start = microtime(true); - CLI::logging("> Updating Content...\n"); - $this->upgradeContent($workSpace); - $stop = microtime(true); - $final = $stop - $start; - CLI::logging("<*> Updating Content Process took $final seconds.\n"); + CLI::logging("* Start to migrate texts/values from 'CONTENT' table to the corresponding object tables...\n"); + $this->migrateContent($lang); + CLI::logging("* End to migrate texts/values from 'CONTENT' table to the corresponding object tables... (Completed on " . + (microtime(true) - $start) . " seconds)\n"); + CLI::logging("* Start updating rows in Web Entry table for classic processes...\n"); $start = microtime(true); - CLI::logging("> Check Mafe Requirements...\n"); - $this->checkMafeRequirements($workSpace, $lang); - $stop = microtime(true); - $final = $stop - $start; - CLI::logging("<*> Check Mafe Requirements Process took $final seconds.\n"); + $this->updatingWebEntryClassicModel(true); + CLI::logging("* End updating rows in Web Entry table for classic processes...(Completed on " . + (microtime(true) - $start) . " seconds)\n"); + CLI::logging("* Start to update Files Manager...\n"); $start = microtime(true); - CLI::logging("> Updating Triggers...\n"); - $this->updateTriggers(true, $lang); - $stop = microtime(true); - $final = $stop - $start; - CLI::logging("<*> Updating Triggers Process took $final seconds.\n"); - - $start = microtime(true); - CLI::logging("> Backup log files...\n"); - $this->backupLogFiles(); - $stop = microtime(true); - $final = $stop - $start; - CLI::logging("<*> Backup log files Process took $final seconds.\n"); - - $start = microtime(true); - CLI::logging("> Optimizing content data...\n"); - $this->migrateContent($workSpace, $lang); - $stop = microtime(true); - CLI::logging("<*> Optimizing content data took " . ($stop - $start) . " seconds.\n"); - - $start = microtime(true); - CLI::logging("> Migrating and populating indexing for avoiding the use of table APP_CACHE_VIEW...\n"); - $this->migratePopulateIndexingACV($workSpace); - $stop = microtime(true); - CLI::logging("<*> Migrating an populating indexing for avoiding the use of table APP_CACHE_VIEW process took " . ($stop - $start) . " seconds.\n"); + $this->processFilesUpgrade($workspace); + CLI::logging("* End to update Files Manager... (Completed on " . (microtime(true) - $start) . " seconds)\n"); /*----------------------------------********---------------------------------*/ + CLI::logging("* Start migrating to new list tables...\n"); $start = microtime(true); - CLI::logging("> Migrate new lists...\n"); - $this->migrateList($workSpace, false, $lang); - $stop = microtime(true); - $final = $stop - $start; - CLI::logging("<*> Migrate new lists Process took $final seconds.\n"); + $this->migrateList(true, $lang); + CLI::logging("* End migrating to new list tables...(Completed on " . (microtime(true) - $start) . " seconds)\n"); /*----------------------------------********---------------------------------*/ + CLI::logging("* Start migrating and populating plugin singleton data...\n"); $start = microtime(true); - CLI::logging("> Updating Files Manager...\n"); - $this->processFilesUpgrade(); - $stop = microtime(true); - CLI::logging("<*> Updating Files Manager took " . ($stop - $start) . " seconds.\n"); + $this->migrateSingleton($workspace); + CLI::logging("* End migrating and populating plugin singleton data...(Completed on " . + (microtime(true) - $start) . " seconds)\n"); + CLI::logging("* Start cleaning expired tokens...\n"); $start = microtime(true); - CLI::logging("> Clean access and refresh tokens...\n"); - $this->cleanTokens($workSpace); - $stop = microtime(true); - CLI::logging("<*> Clean access and refresh tokens took " . ($stop - $start) . " seconds.\n"); + $this->cleanTokens(); + CLI::logging("* End cleaning expired tokens...(Completed on " . (microtime(true) - $start) . " seconds)\n"); + CLI::logging("* Start to check Intermediate Email Event...\n"); $start = microtime(true); - CLI::logging("> Optimizing Self-Service data...\n"); - $this->migrateSelfServiceRecordsRun($workSpace); - $stop = microtime(true); - CLI::logging("<*> Migrating Self-Service records Process took " . ($stop - $start) . " seconds.\n"); + $this->checkIntermediateEmailEvent(); + CLI::logging("* End to check Intermediate Email Event... (Completed on " . (microtime(true) - $start) . " seconds)\n"); + CLI::logging("* Start cleaning DYN_CONTENT in APP_HISTORY...\n"); $start = microtime(true); - CLI::logging("> Updating rows in Web Entry table for classic processes...\n"); - $this->updatingWebEntryClassicModel($workSpace); - $stop = microtime(true); - CLI::logging("<*> Updating rows in Web Entry table for classic processes took " . ($stop - $start) . " seconds.\n"); - - $start = microtime(true); - CLI::logging("> Update framework paths...\n"); - $this->updateFrameworkPaths($workSpace); - $stop = microtime(true); - CLI::logging("<*> Update framework paths took " . ($stop - $start) . " seconds.\n"); - - $start = microtime(true); - CLI::logging("> Migrating and populating plugin singleton data...\n"); - $this->migrateSingleton($workSpace); - $stop = microtime(true); - CLI::logging("<*> Migrating and populating plugin singleton data took " . ($stop - $start) . " seconds.\n"); - $keepDynContent = isset($optionMigrateHistoryData['keepDynContent']) && $optionMigrateHistoryData['keepDynContent'] === true; - //Review if we need to remove the 'History of use' from APP_HISTORY - $start = microtime(true); - CLI::logging("> Clearing History of Use from APP_HISTORY table...\n"); $this->clearDynContentHistoryData(false, $keepDynContent); - $stop = microtime(true); - CLI::logging("<*> Clearing History of Use from APP_HISTORY table took " . ($stop - $start) . " seconds.\n"); + CLI::logging("* End cleaning DYN_CONTENT in APP_HISTORY...(Completed on " . (microtime(true) - $start) . " seconds)\n"); /*----------------------------------********---------------------------------*/ + CLI::logging("* Start migrating history data...\n"); $start = microtime(true); - CLI::logging("> Migrating history data...\n"); - $this->migrateAppHistoryToAppDataChangeLog(false); - $stop = microtime(true); - CLI::logging("<*> Migrating history data took " . ($stop - $start) . " seconds.\n"); + $this->migrateAppHistoryToAppDataChangeLog(true); + CLI::logging("* End migrating history data...(Completed on " . (microtime(true) - $start) . " seconds)\n"); /*----------------------------------********---------------------------------*/ + CLI::logging("* Start migrating and populating indexing for avoiding the use of table APP_CACHE_VIEW...\n"); + $start = microtime(true); + $this->migratePopulateIndexingACV(); + CLI::logging("* End migrating and populating indexing for avoiding the use of table APP_CACHE_VIEW...(Completed on " . + (microtime(true) - $start) . " seconds)\n"); + + CLI::logging("* Start optimizing Self-Service data in table APP_ASSIGN_SELF_SERVICE_VALUE_GROUP....\n"); + $start = microtime(true); + $this->migrateSelfServiceRecordsRun(); + CLI::logging("* End optimizing Self-Service data in table APP_ASSIGN_SELF_SERVICE_VALUE_GROUP....(Completed on " . + (microtime(true) - $start) . " seconds)\n"); + + CLI::logging("* Start adding new fields and populating values in tables related to feature self service by value...\n"); $start = microtime(true); - CLI::logging("> Optimizing Self-Service data in table APP_ASSIGN_SELF_SERVICE_VALUE_GROUP....\n"); $this->upgradeSelfServiceData(); - $stop = microtime(true); - CLI::logging("<*> Optimizing Self-Service data in table APP_ASSIGN_SELF_SERVICE_VALUE_GROUP took " . ($stop - $start) . " seconds.\n"); + CLI::logging("* End adding new fields and populating values in tables related to feature self service by value...(Completed on " . + (microtime(true) - $start) . " seconds)\n"); + + CLI::logging("* Start updating MySQL triggers...\n"); + $start = microtime(true); + $this->updateTriggers(true, $lang); + CLI::logging("* End updating MySQL triggers...(" . (microtime(true) - $start) . " seconds)\n"); } /** @@ -391,6 +346,9 @@ class WorkspaceTools CLI::logging("<*> Database Upgrade Structure Process took $final seconds.\n"); } + /** + * Update the email events with the current email server + */ public function checkIntermediateEmailEvent() { $oEmailEvent = new \ProcessMaker\BusinessModel\EmailEvent(); @@ -629,9 +587,11 @@ class WorkspaceTools } /** - * Upgrade this workspace Content. + * Upgrade this workspace Content + * * @param string $workspace * @param boolean $executeRegenerateContent + * * @return void */ public function upgradeContent($workspace = null, $executeRegenerateContent = false) @@ -683,7 +643,7 @@ class WorkspaceTools } /** - * Upgrade this workspace translations from all avaliable languages. + * Upgrade the workspace translations from all available languages * * @param bool $flagXml Update XML * @param bool $flagMafe Update MAFE @@ -1055,10 +1015,12 @@ class WorkspaceTools } /** - * Upgrade this workspace database to the latest system schema + * Upgrade the workspace database to the latest system schema * - * @param bool $checkOnly only check if the upgrade is needed if true - * @return array bool upgradeSchema for more information + * @param bool $onedb Was installed in one DB or not + * @param bool $checkOnly Only check if the upgrade is needed if true + * + * @return bool upgradeSchema */ public function upgradeDatabase($onedb = false, $checkOnly = false) { @@ -2173,6 +2135,9 @@ class WorkspaceTools return $result; } + /** + * Backup the log files + */ public function backupLogFiles() { $config = System::getSystemConfiguration(); @@ -2189,6 +2154,12 @@ class WorkspaceTools } } + /** + * Check if the workspace have the clients used by MAFE registered + * + * @param string $workspace + * @param string $lang + */ public function checkMafeRequirements($workspace, $lang) { $this->initPropel(true); @@ -2265,9 +2236,8 @@ class WorkspaceTools return true; } - public function verifyFilesOldEnterprise($workspace) + public function verifyFilesOldEnterprise() { - $this->initPropel(true); $pathBackup = PATH_DATA . 'backups'; if (!file_exists($pathBackup)) { G::mk_dir($pathBackup, 0777); @@ -2381,12 +2351,12 @@ class WorkspaceTools /** * Migrate all cases to New list * - * @param string $workSpace Workspace * @param bool $flagReinsert Flag that specifies the re-insertion + * @param string $lang * * @return void */ - public function migrateList($workSpace, $flagReinsert = false, $lang = 'en') + public function migrateList($flagReinsert = false, $lang = 'en') { $this->initPropel(true); @@ -3034,19 +3004,21 @@ class WorkspaceTools } /** - * Process-Files upgrade + * Process files upgrade, store the information in the DB + * + * @param string $workspace * * return void */ - public function processFilesUpgrade() + public function processFilesUpgrade($workspace) { try { if (!defined("PATH_DATA_MAILTEMPLATES")) { - define("PATH_DATA_MAILTEMPLATES", PATH_DATA_SITE . "mailTemplates" . PATH_SEP); + define("PATH_DATA_MAILTEMPLATES", PATH_DATA . 'sites' . PATH_SEP . $workspace . PATH_SEP . "mailTemplates" . PATH_SEP); } if (!defined("PATH_DATA_PUBLIC")) { - define("PATH_DATA_PUBLIC", PATH_DATA_SITE . "public" . PATH_SEP); + define("PATH_DATA_PUBLIC", PATH_DATA . 'sites' . PATH_SEP . $workspace . PATH_SEP . "public" . PATH_SEP); } $this->initPropel(true); @@ -3559,8 +3531,12 @@ class WorkspaceTools return $response; } - - public function migrateContent($workspace, $lang = SYS_LANG) + /** + * Migrate texts/values from "CONTENT" table to the corresponding object tables + * + * @param string $lang + */ + public function migrateContent($lang = SYS_LANG) { if ((!class_exists('Memcache') || !class_exists('Memcached')) && !defined('MEMCACHED_ENABLED')) { define('MEMCACHED_ENABLED', false); @@ -3573,7 +3549,7 @@ class WorkspaceTools $blackList = $oConfig['CFG_VALUE'] == 'true' ? array('Groupwf', 'Process', 'Department', 'Task', 'InputDocument', 'Application') : unserialize($oConfig['CFG_VALUE']); } - $blackList = $this->migrateContentRun($workspace, $lang, $blackList); + $blackList = $this->migrateContentRun($lang, $blackList); $data["CFG_UID"] = 'MIGRATED_CONTENT'; $data["OBJ_UID"] = 'content'; $data["CFG_VALUE"] = serialize($blackList); @@ -3640,13 +3616,14 @@ class WorkspaceTools } /** - * Migration + * Migrate from "CONTENT" table to the corresponding object tables + * + * @param string $lang + * @param array $blackList * - * @param $workspace - * @param mixed|string $lang * @return array */ - public function migrateContentRun($workspace, $lang = SYS_LANG, $blackList = array()) + public function migrateContentRun($lang = SYS_LANG, $blackList = []) { if ((!class_exists('Memcache') || !class_exists('Memcached')) && !defined('MEMCACHED_ENABLED')) { define('MEMCACHED_ENABLED', false); @@ -3662,7 +3639,10 @@ class WorkspaceTools return $blackList; } - public function cleanTokens($workspace, $lang = SYS_LANG) + /** + * Clean the expired access and refresh tokens + */ + public function cleanTokens() { $this->initPropel(true); $oCriteria = new Criteria(); @@ -3750,7 +3730,10 @@ class WorkspaceTools } } - public function migrateSelfServiceRecordsRun($workspace) + /** + * Migrate the concatenated strings with UIDs from groups to the table "APP_ASSIGN_SELF_SERVICE_VALUE_GROUP" + */ + public function migrateSelfServiceRecordsRun() { // Initializing $this->initPropel(true); @@ -3797,7 +3780,10 @@ class WorkspaceTools CLI::logging(" Migrating Self-Service by Value Cases Done \n"); } - public function migratePopulateIndexingACV($workspace) + /** + * Populate new fields used for avoiding the use of the "APP_CACHE_VIEW" table + */ + public function migratePopulateIndexingACV() { // Migrating and populating new indexes CLI::logging("-> Migrating an populating indexing for avoiding the use of table APP_CACHE_VIEW Start \n"); @@ -4062,9 +4048,10 @@ class WorkspaceTools * It populates the WEB_ENTRY table for the classic processes, this procedure * is done to verify the execution of php files generated when the WebEntry * is configured. - * @param type $workSpace + * + * @param bool $force */ - public function updatingWebEntryClassicModel($workSpace, $force = false) + public function updatingWebEntryClassicModel($force = false) { //We obtain from the configuration the list of proUids obtained so that //we do not go through again. @@ -4160,8 +4147,9 @@ class WorkspaceTools /** * Updating triggers - * @param $flagRecreate - * @param $lang + * + * @param bool $flagRecreate + * @param string $lang */ public function updateTriggers($flagRecreate, $lang) { @@ -4170,6 +4158,8 @@ class WorkspaceTools } /** + * Migrate the data of the "plugin.singleton" file to the "PLUGIN_REGISTRY" table + * * @param $workspace */ public function migrateSingleton($workspace) @@ -4215,14 +4205,11 @@ class WorkspaceTools } /** - * Updating framework directory structure + * Check/Create framework's directories * */ - private function updateFrameworkPaths($workSpace = null) + public function checkFrameworkPaths() { - if ($workSpace === null) { - $workSpace = config("system.workspace"); - } $paths = [ PATH_DATA . 'framework' => 0770, PATH_DATA . 'framework' . DIRECTORY_SEPARATOR . 'cache' => 0770, diff --git a/workflow/engine/classes/model/AddonsManager.php b/workflow/engine/classes/model/AddonsManager.php index 06d16fedb..10691d3ac 100644 --- a/workflow/engine/classes/model/AddonsManager.php +++ b/workflow/engine/classes/model/AddonsManager.php @@ -385,13 +385,7 @@ class AddonsManager extends BaseAddonsManager $this->setState(); } else { - if ($this->getAddonType() == "core") { - $upgrade = new Upgrade($this); - - $upgrade->install(); - } else { - throw new Exception("Addon type {$this->getAddonType()} not supported."); - } + throw new Exception("Addon type {$this->getAddonType()} not supported."); } } diff --git a/workflow/engine/src/ProcessMaker/Core/System.php b/workflow/engine/src/ProcessMaker/Core/System.php index 36e3061ed..15e957e7d 100644 --- a/workflow/engine/src/ProcessMaker/Core/System.php +++ b/workflow/engine/src/ProcessMaker/Core/System.php @@ -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 * From a720cd7608154970e2e9d16b48a690afb9aac97c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julio=20Cesar=20Laura=20Avenda=C3=B1o?= Date: Mon, 18 Mar 2019 16:17:23 -0400 Subject: [PATCH 12/21] PMC-568 --- gulliver/system/class.database_mysql.php | 12 ++++++++++++ workflow/engine/classes/WorkspaceTools.php | 21 +++++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/gulliver/system/class.database_mysql.php b/gulliver/system/class.database_mysql.php index 8191f51db..0bae312f0 100644 --- a/gulliver/system/class.database_mysql.php +++ b/gulliver/system/class.database_mysql.php @@ -1012,4 +1012,16 @@ class database extends database_base } return $flag; } + + /** + * Generate drop trigger SQL + * + * @param string $triggerName + * + * @return string + */ + public function getDropTrigger($triggerName) + { + return "DROP TRIGGER IF EXISTS `{$triggerName}`;"; + } } diff --git a/workflow/engine/classes/WorkspaceTools.php b/workflow/engine/classes/WorkspaceTools.php index cdd9e075e..bb16c28b9 100644 --- a/workflow/engine/classes/WorkspaceTools.php +++ b/workflow/engine/classes/WorkspaceTools.php @@ -4544,4 +4544,25 @@ class WorkspaceTools } } } + + /** + * Delete the triggers MySQL that causes performance issues in the upgrade process + */ + public function deleteTriggersMySql($triggersToDelete) + { + // Initialize Propel + $this->initPropel(true); + $con = Propel::getConnection('workflow'); + + // Get statement instance + $stmt = $con->createStatement(); + + // Get MySQL DB instance class + $dbInstance = $this->getDatabase(); + + // Remove triggers MySQL + foreach ($triggersToDelete as $triggerName) { + $stmt->executeQuery($dbInstance->getDropTrigger($triggerName)); + } + } } From 36f9746e82336994637014ed74c2f778ffc406d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julio=20Cesar=20Laura=20Avenda=C3=B1o?= Date: Tue, 19 Mar 2019 12:31:29 -0400 Subject: [PATCH 13/21] PMC-569 --- workflow/engine/classes/WorkspaceTools.php | 26 ++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/workflow/engine/classes/WorkspaceTools.php b/workflow/engine/classes/WorkspaceTools.php index bb16c28b9..c1e210b4e 100644 --- a/workflow/engine/classes/WorkspaceTools.php +++ b/workflow/engine/classes/WorkspaceTools.php @@ -4565,4 +4565,30 @@ class WorkspaceTools $stmt->executeQuery($dbInstance->getDropTrigger($triggerName)); } } + + /** + * Delete indexes of specific tables + * + * @param array $tables + */ + public function deleteIndexes($tables) + { + // Get MySQL DB instance class + $database = $this->getDatabase(); + + foreach ($tables as $table) { + // Get all indexes of the table + $indexes = $database->executeQuery($database->generateTableIndexSQL($table)); + $indexesDeleted = []; + foreach ($indexes as $index) { + if ($index['Key_name'] != 'PRIMARY') { + if (!in_array($index['Key_name'], $indexesDeleted)) { + // Remove index + $database->executeQuery($database->generateDropKeySQL($table, $index['Key_name'])); + $indexesDeleted[] = $index['Key_name']; + } + } + } + } + } } From c109be86906d8a5094215f7aa26e09facf3763e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julio=20Cesar=20Laura=20Avenda=C3=B1o?= Date: Tue, 19 Mar 2019 14:34:05 -0400 Subject: [PATCH 14/21] PMC-574 --- workflow/engine/classes/WorkspaceTools.php | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/workflow/engine/classes/WorkspaceTools.php b/workflow/engine/classes/WorkspaceTools.php index c1e210b4e..615a9a2e2 100644 --- a/workflow/engine/classes/WorkspaceTools.php +++ b/workflow/engine/classes/WorkspaceTools.php @@ -247,6 +247,20 @@ class WorkspaceTools $this->checkMafeRequirements($workspace, $lang); CLI::logging("* End checking MAFE requirements...(Completed on " . (microtime(true) - $start) . " seconds)\n"); + CLI::logging("* Start deleting MySQL triggers: APP_DELEGATION_UPDATE, APPLICATION_UPDATE, CONTENT_UPDATE...\n"); + $start = microtime(true); + $this->deleteTriggersMySQL(['APP_DELEGATION_UPDATE', 'APPLICATION_UPDATE', 'CONTENT_UPDATE']); + CLI::logging("* End deleting MySQL triggers: APP_DELEGATION_UPDATE, APPLICATION_UPDATE, CONTENT_UPDATE... (Completed on " . + (microtime(true) - $start) . " seconds)\n"); + + $bigTables = ['APPLICATION', 'APP_ASSIGN_SELF_SERVICE_VALUE_GROUP', 'APP_CACHE_VIEW', 'APP_DELEGATION', 'APP_DELAY', + 'APP_DOCUMENT', 'APP_HISTORY', 'APP_MESSAGE', 'GROUP_USER', 'LOGIN_LOG']; + CLI::logging("* Start deleting indexes from big tables: " . implode(', ', $bigTables) . "...\n"); + $start = microtime(true); + $this->deleteIndexes($bigTables); + CLI::logging("* End deleting indexes from big tables: " . implode(', ', $bigTables) . "... (Completed on " . + (microtime(true) - $start) . " seconds)\n"); + CLI::logging("* Start to update CONTENT table...\n"); $start = microtime(true); $this->upgradeContent($workspace); From ce9eed77591954113a11e26ef22f0122154652b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julio=20Cesar=20Laura=20Avenda=C3=B1o?= Date: Wed, 20 Mar 2019 10:58:58 -0400 Subject: [PATCH 15/21] PMC-596 --- gulliver/system/class.database_mysql.php | 71 +++++++++++ workflow/engine/bin/tasks/cliUpgrade.php | 2 +- workflow/engine/classes/WorkspaceTools.php | 142 ++++++++++++--------- 3 files changed, 152 insertions(+), 63 deletions(-) diff --git a/gulliver/system/class.database_mysql.php b/gulliver/system/class.database_mysql.php index 0bae312f0..870ba954f 100644 --- a/gulliver/system/class.database_mysql.php +++ b/gulliver/system/class.database_mysql.php @@ -1024,4 +1024,75 @@ class database extends database_base { return "DROP TRIGGER IF EXISTS `{$triggerName}`;"; } + + /** + * Generate alter table with or without adding the indexes + * + * @param string $tableName + * @param array $columns + * @param array $indexes + * + * @return string + */ + public function generateAddColumnsSql($tableName, $columns, $indexes = []) + { + $indexesAlreadyAdded = []; + $sql = 'ALTER TABLE ' . $this->sQuoteCharacter . $tableName . $this->sQuoteCharacter . ' '; + foreach ($columns as $columnName => $parameters) { + if (isset($parameters['Type']) && isset($parameters['Null'])) { + $sql .= 'ADD COLUMN ' . $this->sQuoteCharacter . $columnName . $this->sQuoteCharacter . ' ' . $parameters['Type']; + if ($parameters['Null'] == 'YES') { + $sql .= ' NULL'; + } else { + $sql .= ' NOT NULL'; + } + } + if (isset($parameters['AutoIncrement']) && $parameters['AutoIncrement']) { + $sql .= ' AUTO_INCREMENT'; + } + if (isset($parameters['PrimaryKey']) && $parameters['PrimaryKey']) { + $sql .= ' PRIMARY KEY'; + $indexesAlreadyAdded[] = $columnName; + } + if (isset($parameters['Unique']) && $parameters['Unique']) { + $sql .= ' UNIQUE'; + } + + // We need to check the property AI + if (isset($parameters['AI'])) { + if ($parameters['AI'] == 1) { + $sql .= ' AUTO_INCREMENT'; + } else { + if ($parameters['Default'] != '') { + $sql .= " DEFAULT '" . $parameters['Default'] . "'"; + } + } + } else { + if (isset($parameters['Default'])) { + $sql .= " DEFAULT '" . $parameters['Default'] . "'"; + } + } + $sql .= ', '; + } + foreach ($indexes as $indexName => $indexColumns) { + $indexType = 'INDEX'; + if ($indexName === 'primaryKey' || $indexName === 'PRIMARY') { + $indexType = 'PRIMARY'; + $indexName = 'KEY'; + // If is primary key is not needed add a new index, the column already was added like primary key + if (count($indexColumns) == 1 && $indexesAlreadyAdded == $indexColumns) { + continue; + } + } + $sql .= 'ADD ' . $indexType . ' ' . $indexName . ' ('; + foreach ($indexColumns as $column) { + $sql .= $this->sQuoteCharacter . $column . $this->sQuoteCharacter . ', '; + } + $sql = substr($sql, 0, -2); + $sql .= '), '; + } + $sql = rtrim($sql, ', '); + + return $sql; + } } diff --git a/workflow/engine/bin/tasks/cliUpgrade.php b/workflow/engine/bin/tasks/cliUpgrade.php index d09d3adff..7fec63fd0 100644 --- a/workflow/engine/bin/tasks/cliUpgrade.php +++ b/workflow/engine/bin/tasks/cliUpgrade.php @@ -160,7 +160,7 @@ function run_upgrade($parameters, $args) ]; // Upgrade database and files from a specific workspace - $workspace->upgrade($workspace->name, true, SYS_LANG, $arrayOptTranslation, $optionMigrateHistoryData); + $workspace->upgrade($workspace->name, SYS_LANG, $arrayOptTranslation, $optionMigrateHistoryData); $workspace->close(); } else { // Build arguments diff --git a/workflow/engine/classes/WorkspaceTools.php b/workflow/engine/classes/WorkspaceTools.php index 615a9a2e2..3c70f78b0 100644 --- a/workflow/engine/classes/WorkspaceTools.php +++ b/workflow/engine/classes/WorkspaceTools.php @@ -226,7 +226,7 @@ class WorkspaceTools * * @return void */ - public function upgrade($workspace, $onedb = false, $lang = 'en', array $arrayOptTranslation = null, $optionMigrateHistoryData = []) + public function upgrade($workspace, $lang = 'en', array $arrayOptTranslation = null, $optionMigrateHistoryData = []) { if (is_null($arrayOptTranslation)) { $arrayOptTranslation = ['updateXml' => true, 'updateMafe' => true]; @@ -234,7 +234,7 @@ class WorkspaceTools CLI::logging("* Start updating database schema...\n"); $start = microtime(true); - $this->upgradeDatabase($onedb); + $this->upgradeDatabase(); CLI::logging("* End updating database schema...(Completed on " . (microtime(true) - $start) . " seconds)\n"); CLI::logging("* Start updating translations...\n"); @@ -283,13 +283,6 @@ class WorkspaceTools $this->processFilesUpgrade($workspace); CLI::logging("* End to update Files Manager... (Completed on " . (microtime(true) - $start) . " seconds)\n"); - /*----------------------------------********---------------------------------*/ - CLI::logging("* Start migrating to new list tables...\n"); - $start = microtime(true); - $this->migrateList(true, $lang); - CLI::logging("* End migrating to new list tables...(Completed on " . (microtime(true) - $start) . " seconds)\n"); - /*----------------------------------********---------------------------------*/ - CLI::logging("* Start migrating and populating plugin singleton data...\n"); $start = microtime(true); $this->migrateSingleton($workspace); @@ -337,6 +330,19 @@ class WorkspaceTools CLI::logging("* End adding new fields and populating values in tables related to feature self service by value...(Completed on " . (microtime(true) - $start) . " seconds)\n"); + CLI::logging("* Start adding/replenishing all indexes...\n"); + $start = microtime(true); + $systemSchema = System::getSystemSchema($this->dbAdapter); + $this->upgradeSchema($systemSchema); + CLI::logging("* End adding/replenishing all indexes...(Completed on " . (microtime(true) - $start) . " seconds)\n"); + + /*----------------------------------********---------------------------------*/ + CLI::logging("* Start migrating to new list tables...\n"); + $start = microtime(true); + $this->migrateList(true, $lang); + CLI::logging("* End migrating to new list tables...(Completed on " . (microtime(true) - $start) . " seconds)\n"); + /*----------------------------------********---------------------------------*/ + CLI::logging("* Start updating MySQL triggers...\n"); $start = microtime(true); $this->updateTriggers(true, $lang); @@ -1030,22 +1036,17 @@ class WorkspaceTools /** * Upgrade the workspace database to the latest system schema - * - * @param bool $onedb Was installed in one DB or not - * @param bool $checkOnly Only check if the upgrade is needed if true - * - * @return bool upgradeSchema */ - public function upgradeDatabase($onedb = false, $checkOnly = false) + public function upgradeDatabase() { $this->initPropel(true); P11835::$dbAdapter = $this->dbAdapter; P11835::isApplicable(); $systemSchema = System::getSystemSchema($this->dbAdapter); - $systemSchemaRbac = System::getSystemSchemaRbac($this->dbAdapter);// get the Rbac Schema + $systemSchemaRbac = System::getSystemSchemaRbac($this->dbAdapter);// Get the RBAC Schema $this->registerSystemTables(array_merge($systemSchema, $systemSchemaRbac)); - $this->upgradeSchema($systemSchema); - $this->upgradeSchema($systemSchemaRbac, false, true, $onedb); // perform Upgrade to Rbac + $this->upgradeSchema($systemSchema, false, false, false); // Without add indexes + $this->upgradeSchema($systemSchemaRbac, false, true); // Perform upgrade to RBAC $this->upgradeData(); $this->checkRbacPermissions();//check or add new permissions $this->checkSequenceNumber(); @@ -1112,10 +1113,7 @@ class WorkspaceTools $arrayData = $emailSever->create2($arrayData); } } - P11835::execute(); - - return true; } private function setFormatRows() @@ -1136,14 +1134,18 @@ class WorkspaceTools } /** - * Upgrade this workspace database from a schema + * Upgrade the workspace database according to the schema * - * @param array $schema the schema information, such as returned from getSystemSchema - * @param bool $checkOnly only check if the upgrade is needed if true - * @return array bool the changes if checkOnly is true, else return - * true on success + * @param array $schema The schema information, such as returned from getSystemSchema + * @param bool $checkOnly Only return the diff between current database and the schema + * @param bool $rbac Is RBAC database? + * @param bool $includeIndexes Include or no indexes in new tables + * + * @return bool|array + * + * @throws Exception */ - public function upgradeSchema($schema, $checkOnly = false, $rbac = false, $onedb = false) + public function upgradeSchema($schema, $checkOnly = false, $rbac = false, $includeIndexes = true) { $dbInfo = $this->getDBInfo(); @@ -1198,11 +1200,11 @@ class WorkspaceTools CLI::logging("-> " . count($changes['tablesToAdd']) . " tables to add\n"); } - foreach ($changes['tablesToAdd'] as $sTable => $aColumns) { - $database->executeQuery($database->generateCreateTableSQL($sTable, $aColumns)); - if (isset($changes['tablesToAdd'][$sTable]['INDEXES'])) { - foreach ($changes['tablesToAdd'][$sTable]['INDEXES'] as $indexName => $aIndex) { - $database->executeQuery($database->generateAddKeysSQL($sTable, $indexName, $aIndex)); + foreach ($changes['tablesToAdd'] as $tableName => $columns) { + $database->executeQuery($database->generateCreateTableSQL($tableName, $columns)); + if (isset($changes['tablesToAdd'][$tableName]['INDEXES']) && $includeIndexes) { + foreach ($changes['tablesToAdd'][$tableName]['INDEXES'] as $indexName => $keys) { + $database->executeQuery($database->generateAddKeysSQL($tableName, $indexName, $keys)); } } } @@ -1211,46 +1213,62 @@ class WorkspaceTools CLI::logging("-> " . count($changes['tablesToAlter']) . " tables to alter\n"); } - foreach ($changes['tablesToAlter'] as $sTable => $aActions) { - foreach ($aActions as $sAction => $aAction) { - foreach ($aAction as $sColumn => $vData) { - switch ($sAction) { - case 'DROP': - $database->executeQuery($database->generateDropColumnSQL($sTable, $vData)); - break; - case 'ADD': - if ($database->checkPatchHor1787($sTable, $sColumn, $vData)) { - $database->executeQuery($database->generateCheckAddColumnSQL($sTable, $sColumn, $vData)); - $database->executeQuery($database->deleteAllIndexesIntable($sTable, $sColumn, $vData)); - } - $database->executeQuery($database->generateAddColumnSQL($sTable, $sColumn, $vData)); - break; - case 'CHANGE': - $database->executeQuery($database->generateChangeColumnSQL($sTable, $sColumn, $vData)); - break; + $tablesToAddColumns = []; + + foreach ($changes['tablesToAlter'] as $tableName => $actions) { + foreach ($actions as $action => $actionData) { + if ($action == 'ADD') { + $tablesToAddColumns[$tableName] = $actionData; + + // In a very old schema the primary key for table "LOGIN_LOG" was changed and we need to delete the + // primary index to avoid errors in the database upgrade + // TO DO: The change of a Primary Key in a table should be generic + if ($tableName == 'LOGIN_LOG' && array_key_exists('LOG_ID', $actionData)) { + $database->executeQuery('DROP INDEX `PRIMARY` ON LOGIN_LOG;'); + } + } else { + foreach ($actionData as $columnName => $meta) { + switch ($action) { + case 'DROP': + $database->executeQuery($database->generateDropColumnSQL($tableName, $meta)); + break; + case 'CHANGE': + $database->executeQuery($database->generateChangeColumnSQL($tableName, $columnName, $meta)); + break; + } } } } } - if (!empty($changes['tablesWithNewIndex'])) { - CLI::logging("-> " . count($changes['tablesWithNewIndex']) . " indexes to add\n"); - } - foreach ($changes['tablesWithNewIndex'] as $sTable => $aIndexes) { - foreach ($aIndexes as $sIndexName => $aIndexFields) { - $database->executeQuery($database->generateAddKeysSQL($sTable, $sIndexName, $aIndexFields)); + if (!empty($tablesToAddColumns)) { + foreach ($tablesToAddColumns as $tableName => $tableColumn) { + $indexes = []; + if (!empty($changes['tablesWithNewIndex'][$tableName]) && $includeIndexes) { + $indexes = $changes['tablesWithNewIndex'][$tableName]; + unset($changes['tablesWithNewIndex'][$tableName]); + } + $database->executeQuery($database->generateAddColumnsSql($tableName, $tableColumn, $indexes)); } } - if (!empty($changes['tablesToAlterIndex'])) { - CLI::logging("-> " . count($changes['tablesToAlterIndex']) . " indexes to alter\n"); - } - foreach ($changes['tablesToAlterIndex'] as $sTable => $aIndexes) { - foreach ($aIndexes as $sIndexName => $aIndexFields) { - $database->executeQuery($database->generateDropKeySQL($sTable, $sIndexName)); - $database->executeQuery($database->generateAddKeysSQL($sTable, $sIndexName, $aIndexFields)); + if (!empty($changes['tablesWithNewIndex']) && $includeIndexes) { + CLI::logging("-> " . count($changes['tablesWithNewIndex']) . " tables with indexes to add\n"); + foreach ($changes['tablesWithNewIndex'] as $tableName => $indexes) { + $database->executeQuery($database->generateAddColumnsSql($tableName, [], $indexes)); } } + + if (!empty($changes['tablesToAlterIndex']) && $includeIndexes) { + CLI::logging("-> " . count($changes['tablesToAlterIndex']) . " tables with indexes to alter\n"); + foreach ($changes['tablesToAlterIndex'] as $tableName => $indexes) { + foreach ($indexes as $indexName => $indexFields) { + $database->executeQuery($database->generateDropKeySQL($tableName, $indexName)); + $database->executeQuery($database->generateAddKeysSQL($tableName, $indexName, $indexFields)); + } + } + } + $this->closeDatabase(); return true; } From 41beb8478acfea8de40f491f56b62da900924409 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julio=20Cesar=20Laura=20Avenda=C3=B1o?= Date: Thu, 4 Apr 2019 14:44:33 -0400 Subject: [PATCH 16/21] PMC-570 --- gulliver/system/class.database_mysql.php | 12 +- workflow/engine/bin/tasks/cliUpgrade.php | 24 +++ workflow/engine/classes/WorkspaceTools.php | 12 ++ .../ProcessMaker/Core/ProcessesManager.php | 98 ++++++++++++ .../src/ProcessMaker/Core/RunProcess.php | 146 ++++++++++++++++++ .../Upgrade/RunProcessUpgradeQuery.php | 61 ++++++++ 6 files changed, 350 insertions(+), 3 deletions(-) create mode 100644 workflow/engine/src/ProcessMaker/Core/ProcessesManager.php create mode 100644 workflow/engine/src/ProcessMaker/Core/RunProcess.php create mode 100644 workflow/engine/src/ProcessMaker/Upgrade/RunProcessUpgradeQuery.php diff --git a/gulliver/system/class.database_mysql.php b/gulliver/system/class.database_mysql.php index 870ba954f..53888a4ae 100644 --- a/gulliver/system/class.database_mysql.php +++ b/gulliver/system/class.database_mysql.php @@ -519,13 +519,15 @@ class database extends database_base } /** - * execute a sql query + * Execute a sql query * * @param string $query + * @param bool $throwError + * * @return array * @throws Exception */ - public function executeQuery($query) + public function executeQuery($query, $throwError = false) { $this->logQuery($query); @@ -545,7 +547,11 @@ class database extends database_base return $result; } catch (Exception $exception) { $this->logQuery($exception->getMessage()); - return []; + if ($throwError) { + throw $exception; + } else { + return []; + } } } diff --git a/workflow/engine/bin/tasks/cliUpgrade.php b/workflow/engine/bin/tasks/cliUpgrade.php index 7fec63fd0..36aa2e37d 100644 --- a/workflow/engine/bin/tasks/cliUpgrade.php +++ b/workflow/engine/bin/tasks/cliUpgrade.php @@ -36,6 +36,8 @@ CLI::taskArg('workspace'); /*----------------------------------********---------------------------------*/ CLI::taskRun("run_unify_database"); /*----------------------------------********---------------------------------*/ +CLI::taskName('upgrade-query'); +CLI::taskRun('runUpgradeQuery'); /** * Execute the upgrade @@ -299,3 +301,25 @@ function run_unify_database($args) $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'); +} diff --git a/workflow/engine/classes/WorkspaceTools.php b/workflow/engine/classes/WorkspaceTools.php index 3c70f78b0..d190b9c1f 100644 --- a/workflow/engine/classes/WorkspaceTools.php +++ b/workflow/engine/classes/WorkspaceTools.php @@ -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); + } } diff --git a/workflow/engine/src/ProcessMaker/Core/ProcessesManager.php b/workflow/engine/src/ProcessMaker/Core/ProcessesManager.php new file mode 100644 index 000000000..bff0c5d96 --- /dev/null +++ b/workflow/engine/src/ProcessMaker/Core/ProcessesManager.php @@ -0,0 +1,98 @@ +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)); + } +} diff --git a/workflow/engine/src/ProcessMaker/Core/RunProcess.php b/workflow/engine/src/ProcessMaker/Core/RunProcess.php new file mode 100644 index 000000000..8f2a0287f --- /dev/null +++ b/workflow/engine/src/ProcessMaker/Core/RunProcess.php @@ -0,0 +1,146 @@ +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; + } +} diff --git a/workflow/engine/src/ProcessMaker/Upgrade/RunProcessUpgradeQuery.php b/workflow/engine/src/ProcessMaker/Upgrade/RunProcessUpgradeQuery.php new file mode 100644 index 000000000..e1295c0e4 --- /dev/null +++ b/workflow/engine/src/ProcessMaker/Upgrade/RunProcessUpgradeQuery.php @@ -0,0 +1,61 @@ +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)); + } +} \ No newline at end of file From d3d4dd69618596f765c4d20d52a6951f1ee5ab21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julio=20Cesar=20Laura=20Avenda=C3=B1o?= Date: Fri, 12 Apr 2019 11:48:09 -0400 Subject: [PATCH 17/21] PMC-571 --- workflow/engine/classes/WorkspaceTools.php | 37 ++++++++++++++++++++-- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/workflow/engine/classes/WorkspaceTools.php b/workflow/engine/classes/WorkspaceTools.php index d190b9c1f..a926bb366 100644 --- a/workflow/engine/classes/WorkspaceTools.php +++ b/workflow/engine/classes/WorkspaceTools.php @@ -7,9 +7,11 @@ use ProcessMaker\BusinessModel\Process as BmProcess; use ProcessMaker\ChangeLog\ChangeLog; /*----------------------------------********---------------------------------*/ use ProcessMaker\Core\Installer; +use ProcessMaker\Core\ProcessesManager; use ProcessMaker\Core\System; use ProcessMaker\Plugins\Adapters\PluginAdapter; use ProcessMaker\Project\Adapter\BpmnWorkflow; +use ProcessMaker\Upgrade\RunProcessUpgradeQuery; use ProcessMaker\Util\FixReferencePath; /** @@ -1242,20 +1244,51 @@ class WorkspaceTools } if (!empty($tablesToAddColumns)) { + $upgradeQueries = []; foreach ($tablesToAddColumns as $tableName => $tableColumn) { $indexes = []; if (!empty($changes['tablesWithNewIndex'][$tableName]) && $includeIndexes) { $indexes = $changes['tablesWithNewIndex'][$tableName]; unset($changes['tablesWithNewIndex'][$tableName]); } - $database->executeQuery($database->generateAddColumnsSql($tableName, $tableColumn, $indexes)); + + // Instantiate the class to execute the query in background + $upgradeQueries[] = new RunProcessUpgradeQuery($this->name, $database->generateAddColumnsSql($tableName, $tableColumn, $indexes), $rbac); + } + + // Run queries in multiple threads + $processesManager = new ProcessesManager($upgradeQueries); + $processesManager->run(); + + // If exists an error throw an exception + if (!empty($processesManager->getErrors())) { + $errorMessage = ''; + foreach ($processesManager->getErrors() as $error) { + $errorMessage .= $error['rawAnswer'] . PHP_EOL; + } + throw new Exception($errorMessage); } } if (!empty($changes['tablesWithNewIndex']) && $includeIndexes) { CLI::logging("-> " . count($changes['tablesWithNewIndex']) . " tables with indexes to add\n"); + $upgradeQueries = []; foreach ($changes['tablesWithNewIndex'] as $tableName => $indexes) { - $database->executeQuery($database->generateAddColumnsSql($tableName, [], $indexes)); + // Instantiate the class to execute the query in background + $upgradeQueries[] = new RunProcessUpgradeQuery($this->name, $database->generateAddColumnsSql($tableName, [], $indexes), $rbac); + } + + // Run queries in multiple threads + $processesManager = new ProcessesManager($upgradeQueries); + $processesManager->run(); + + // If exists an error throw an exception + if (!empty($processesManager->getErrors())) { + $errorMessage = ''; + foreach ($processesManager->getErrors() as $error) { + $errorMessage .= $error['rawAnswer'] . PHP_EOL; + } + throw new Exception($errorMessage); } } From 7e072bbc1091b32b3d69ffa3ec121dabe5ba8216 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julio=20Cesar=20Laura=20Avenda=C3=B1o?= Date: Fri, 12 Apr 2019 14:22:52 -0400 Subject: [PATCH 18/21] PMC-572 --- workflow/engine/classes/WorkspaceTools.php | 106 +++++++++++---------- 1 file changed, 56 insertions(+), 50 deletions(-) diff --git a/workflow/engine/classes/WorkspaceTools.php b/workflow/engine/classes/WorkspaceTools.php index a926bb366..3c239afa7 100644 --- a/workflow/engine/classes/WorkspaceTools.php +++ b/workflow/engine/classes/WorkspaceTools.php @@ -3625,59 +3625,36 @@ class WorkspaceTools } /** - * Migrate this workspace table Content. + * Generate update rows from Content sentence * - * @param $className - * @param $fields - * @param mixed|string $lang - * @throws Exception + * @param string $tableName + * @param array $fields + * @param string $lang + * + * @return string */ - public function migrateContentWorkspace($className, $fields, $lang = SYS_LANG) + public function generateUpdateFromContent($tableName, array $fields, $lang = SYS_LANG) { - try { - $this->initPropel(true); - $fieldUidName = $fields['uid']; - $oCriteria = new Criteria(); - $oCriteria->clearSelectColumns(); - $oCriteria->addAsColumn($fieldUidName, ContentPeer::CON_ID); - $oCriteria->addSelectColumn(ContentPeer::CON_PARENT); - $oCriteria->addSelectColumn(ContentPeer::CON_CATEGORY); - $oCriteria->addSelectColumn(ContentPeer::CON_VALUE); - $oCriteria->add(ContentPeer::CON_CATEGORY, $fields['fields'], Criteria::IN); - $oCriteria->add(ContentPeer::CON_LANG, $lang); - $oDataset = ContentPeer::doSelectRS($oCriteria); - $oDataset->setFetchmode(ResultSet::FETCHMODE_ASSOC); - $methods = $fields['methods']; - while ($oDataset->next()) { - $row = $oDataset->getRow(); - $fieldName = $row['CON_CATEGORY']; - $fieldName = isset($fields['alias']) && isset($fields['alias'][$fieldName]) ? $fields['alias'][$fieldName] : $fieldName; - unset($row['CON_CATEGORY']); - $row[$fieldName] = $row['CON_VALUE']; - unset($row['CON_VALUE']); - $oTable = new $className(); - $that = array($oTable, $methods['exists']); - $params = array($row[$fieldUidName]); - if (isset($row['CON_PARENT']) && $row['CON_PARENT'] != '') { - array_push($params, $row['CON_PARENT']); - $fieldName = isset($fields['alias']) && isset($fields['alias']['CON_PARENT']) ? $fields['alias']['CON_PARENT'] : 'CON_PARENT'; - $row[$fieldName] = $row['CON_PARENT']; - } - unset($row['CON_PARENT']); - if (call_user_func_array($that, $params)) { - if (isset($methods['update'])) { - $fn = $methods['update']; - $fn($row); - } else { - $oTable->update($row); - } - } - } - $classNamePeer = class_exists($className . 'Peer') ? $className . 'Peer' : $fields['peer']; - CLI::logging("|--> Add content data in table " . $classNamePeer::TABLE_NAME . "\n"); - } catch (Exception $e) { - throw ($e); + $sql = "UPDATE " . $tableName . " AS T"; + $i = 0; + foreach ($fields['fields'] as $field) { + $i++; + $tableAlias = "C" . $i; + $sql .= " LEFT JOIN CONTENT " . $tableAlias . " ON ("; + $sql .= $tableAlias . ".CON_CATEGORY = '" . $field . "' AND "; + $sql .= $tableAlias . ".CON_ID = T." . $fields['uid'] . " AND "; + $sql .= $tableAlias . ".CON_LANG = '" . $lang . "')"; } + $sql .= ' SET '; + $i = 0; + foreach ($fields['fields'] as $field) { + $i++; + $tableAlias = "C" . $i; + $fieldName = !empty($fields['alias'][$field]) ? $fields['alias'][$field] : $field; + $sql .= $fieldName . " = " . $tableAlias . ".CON_VALUE, "; + } + $sql = rtrim($sql, ', '); + return $sql; } /** @@ -3687,6 +3664,8 @@ class WorkspaceTools * @param array $blackList * * @return array + * + * @throws Exception */ public function migrateContentRun($lang = SYS_LANG, $blackList = []) { @@ -3694,13 +3673,40 @@ class WorkspaceTools define('MEMCACHED_ENABLED', false); } $content = $this->getListContentMigrateTable(); + $contentQueries = []; foreach ($content as $className => $fields) { if (!in_array($className, $blackList)) { - $this->migrateContentWorkspace($className, $fields, $lang); + // Build class peer name + if (class_exists($className . 'Peer')) { + $classNamePeer = $className . 'Peer'; + } else { + $classNamePeer = $fields['peer']; + } + + // Build the query + $query = $this->generateUpdateFromContent($classNamePeer::TABLE_NAME, $fields, $lang); + + // Instantiate the class to execute the query in background + $contentQueries[] = new RunProcessUpgradeQuery($this->name, $query); + + // Add class to the control array $blackList[] = $className; } } + // Run queries in multiple threads + $processesManager = new ProcessesManager($contentQueries); + $processesManager->run(); + + // If exists an error throw an exception + if (!empty($processesManager->getErrors())) { + $errorMessage = ''; + foreach ($processesManager->getErrors() as $error) { + $errorMessage .= $error['rawAnswer'] . PHP_EOL; + } + throw new Exception($errorMessage); + } + return $blackList; } From 80cd57e97aa94fce0d664a149d8770df5fb8f0be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julio=20Cesar=20Laura=20Avenda=C3=B1o?= Date: Fri, 12 Apr 2019 16:17:21 -0400 Subject: [PATCH 19/21] PMC-573 --- workflow/engine/classes/WorkspaceTools.php | 159 +++++++++++++++------ 1 file changed, 115 insertions(+), 44 deletions(-) diff --git a/workflow/engine/classes/WorkspaceTools.php b/workflow/engine/classes/WorkspaceTools.php index 3c239afa7..5eae87c8e 100644 --- a/workflow/engine/classes/WorkspaceTools.php +++ b/workflow/engine/classes/WorkspaceTools.php @@ -2420,6 +2420,13 @@ class WorkspaceTools * @param string $lang * * @return void + * + * @throws Exception + * + * @see \WorkspaceTools->upgrade + * @see \WorkspaceTools->restore + * @see workflow/engine/bin/tasks/cliWorkspaces.php:migrate_new_cases_lists() + * @link https://wiki.processmaker.com/3.3/processmaker_command#migrate-new-cases-lists */ public function migrateList($flagReinsert = false, $lang = 'en') { @@ -2432,7 +2439,7 @@ class WorkspaceTools return; } - $arrayTable1 = ['ListInbox', 'ListMyInbox', 'ListCanceled', 'ListParticipatedLast', 'ListParticipatedHistory', 'ListPaused']; + $arrayTable1 = ['ListCanceled', 'ListMyInbox', 'ListInbox', 'ListParticipatedHistory', 'ListPaused', 'ListParticipatedLast']; $arrayTable2 = ['ListUnassigned', 'ListUnassignedGroup']; $arrayTable = array_merge($arrayTable1, $arrayTable2); @@ -2457,23 +2464,57 @@ class WorkspaceTools } } + $listQueries = []; + if ($flagReinsert || !$flagListAll) { - $this->regenerateListCanceled($lang); - $this->regenerateListMyInbox(); //This list require no translation - $this->regenerateListInbox(); //This list require no translation - $this->regenerateListParticipatedHistory(); //This list require no translation - $this->regenerateListParticipatedLast(); //This list require no translation - $this->regenerateListPaused(); //This list require no translation + // Regenerate lists + $listQueries[] = new RunProcessUpgradeQuery($this->name, $this->regenerateListCanceled($lang)); + $listQueries[] = new RunProcessUpgradeQuery($this->name, $this->regenerateListMyInbox()); + $listQueries[] = new RunProcessUpgradeQuery($this->name, $this->regenerateListInbox()); + $listQueries[] = new RunProcessUpgradeQuery($this->name, $this->regenerateListParticipatedHistory()); + $listQueries[] = new RunProcessUpgradeQuery($this->name, $this->regenerateListPaused()); + $listQueries[] = new RunProcessUpgradeQuery($this->name, $this->regenerateListParticipatedLast()); } if ($flagReinsert || !$flagListUnassigned) { - $this->regenerateListUnassigned(); //This list require no translation + // This list always is truncated + $con = Propel::getConnection("workflow"); + $stmt = $con->createStatement(); + $stmt->executeQuery('TRUNCATE ' . $this->dbName . '.LIST_UNASSIGNED'); + + // Regenerate list + $listQueries[] = new RunProcessUpgradeQuery($this->name, $this->regenerateListUnassigned()); } + // Run queries in multiple threads + $processesManager = new ProcessesManager($listQueries); + $processesManager->run(); + + // If exists an error throw an exception + if (!empty($processesManager->getErrors())) { + $errorMessage = ''; + foreach ($processesManager->getErrors() as $error) { + $errorMessage .= $error['rawAnswer'] . PHP_EOL; + } + throw new Exception($errorMessage); + } + + // This query cannot be launched in parallel, requires that the table already was populated + $this->updateListParticipatedLast(); + $this->listFirstExecution('insert'); $this->listFirstExecution('insert', 'unassigned'); } + /** + * Return query to populate canceled list + * + * @param string $lang + * + * @return string + * + * @see \WorkspaceTools->migrateList() + */ public function regenerateListCanceled($lang = 'en') { $this->initPropel(true); @@ -2536,12 +2577,17 @@ class WorkspaceTools WHERE ACV.APP_STATUS = \'CANCELLED\' AND ACV.DEL_LAST_INDEX = 1'; - $con = Propel::getConnection("workflow"); - $stmt = $con->createStatement(); - $stmt->executeQuery($query); - CLI::logging("> Completed table LIST_CANCELED\n"); + + return $query; } + /** + * Return query to populate my inbox list + * + * @return string + * + * @see \WorkspaceTools->migrateList() + */ public function regenerateListMyInbox() { $this->initPropel(true); @@ -2606,12 +2652,16 @@ class WorkspaceTools ' . $this->dbName . '.USERS PRE_USR ON ACV.PREVIOUS_USR_UID = PRE_USR.USR_UID WHERE ACV.DEL_INDEX=1'; - $con = Propel::getConnection("workflow"); - $stmt = $con->createStatement(); - $stmt->executeQuery($query); - CLI::logging("> Completed table LIST_MY_INBOX\n"); + return $query; } + /** + * Return query to populate inbox list + * + * @return string + * + * @see \WorkspaceTools->migrateList() + */ public function regenerateListInbox() { $this->initPropel(true); @@ -2664,12 +2714,17 @@ class WorkspaceTools ' . $this->dbName . '.USERS USR ON ACV.PREVIOUS_USR_UID = USR.USR_UID WHERE ACV.DEL_THREAD_STATUS = \'OPEN\''; - $con = Propel::getConnection("workflow"); - $stmt = $con->createStatement(); - $stmt->executeQuery($query); - CLI::logging("> Completed table LIST_INBOX\n"); + + return $query; } + /** + * Return query to populate participated history list + * + * @return string + * + * @see \WorkspaceTools->migrateList() + */ public function regenerateListParticipatedHistory() { $this->initPropel(true); @@ -2722,12 +2777,17 @@ class WorkspaceTools ' . $this->dbName . '.USERS CUR_USR ON ACV.USR_UID = CUR_USR.USR_UID LEFT JOIN ' . $this->dbName . '.USERS PRE_USR ON ACV.PREVIOUS_USR_UID = PRE_USR.USR_UID'; - $con = Propel::getConnection("workflow"); - $stmt = $con->createStatement(); - $stmt->executeQuery($query); - CLI::logging("> Completed table LIST_PARTICIPATED_HISTORY\n"); + + return $query; } + /** + * Return query to populate participated last list + * + * @return string + * + * @see \WorkspaceTools->migrateList() + */ public function regenerateListParticipatedLast() { $this->initPropel(true); @@ -2803,10 +2863,18 @@ class WorkspaceTools ) ACV LEFT JOIN ' . $this->dbName . '.USERS PRE_USR ON ACV.PREVIOUS_USR_UID = PRE_USR.USR_UID LEFT JOIN ' . $this->dbName . '.USERS CUR_USR ON ACV.USR_UID = CUR_USR.USR_UID'; - $con = Propel::getConnection("workflow"); - $stmt = $con->createStatement(); - $stmt->executeQuery($query); - CLI::logging("> Inserted data into table LIST_PARTICIPATED_LAST\n"); + + return $query; + } + + /** + * Update participated last list + * + * @see \WorkspaceTools->migrateList() + */ + public function updateListParticipatedLast() + { + $this->initPropel(true); $query = 'UPDATE ' . $this->dbName . '.LIST_PARTICIPATED_LAST LPL, ( SELECT TASK.TAS_TITLE, @@ -2832,18 +2900,19 @@ class WorkspaceTools LPL.DEL_CURRENT_USR_LASTNAME = IFNULL(USERS_VALUES.USR_LASTNAME, \'\'), LPL.DEL_CURRENT_TAS_TITLE = IFNULL(USERS_VALUES.TAS_TITLE, \'\') WHERE LPL.APP_UID = USERS_VALUES.APP_UID'; + + CLI::logging("> Updating the current users data on table LIST_PARTICIPATED_LAST\n"); $con = Propel::getConnection("workflow"); $stmt = $con->createStatement(); - CLI::logging("> Updating the current users data on table LIST_PARTICIPATED_LAST\n"); $stmt->executeQuery($query); - CLI::logging("> Completed table LIST_PARTICIPATED_LAST\n"); } /** - * This function overwrite the table LIST_PAUSED - * Get the principal information in the tables appDelay, appDelegation - * For the labels we use the tables user, process, task and application - * @return void + * Return query to populate paused list + * + * @return string + * + * @see \WorkspaceTools->migrateList() */ public function regenerateListPaused() { @@ -2922,17 +2991,22 @@ class WorkspaceTools APP_DELAY.APP_DISABLE_ACTION_USER = "0" AND APP_DELAY.APP_TYPE = "PAUSE" '; - $con = Propel::getConnection("workflow"); - $stmt = $con->createStatement(); - $stmt->executeQuery($query); - CLI::logging("> Completed table LIST_PAUSED\n"); + + return $query; } /*----------------------------------********---------------------------------*/ + /** + * Return query to populate unassigned list + * + * @return string + * + * @see \WorkspaceTools->migrateList() + */ public function regenerateListUnassigned() { $this->initPropel(true); - $truncate = 'TRUNCATE ' . $this->dbName . '.LIST_UNASSIGNED'; + //This executeQuery is very fast than Propel $query = 'INSERT INTO ' . $this->dbName . '.LIST_UNASSIGNED (APP_UID, @@ -2976,11 +3050,8 @@ class WorkspaceTools WHERE ACV.DEL_THREAD_STATUS = \'OPEN\' AND ACV.USR_UID = \'\' '; - $con = Propel::getConnection("workflow"); - $stmt = $con->createStatement(); - $stmt->executeQuery($truncate); - $stmt->executeQuery($query); - CLI::logging("> Completed table LIST_UNASSIGNED\n"); + + return $query; } /*----------------------------------********---------------------------------*/ From 3793f6f2fd57e8b2b389ec53b8810fc1d12d2bf2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julio=20Cesar=20Laura=20Avenda=C3=B1o?= Date: Tue, 23 Apr 2019 09:42:25 -0400 Subject: [PATCH 20/21] PMC-594 --- .../engine/classes/MultipleFilesBackup.php | 20 +- workflow/engine/classes/WorkspaceTools.php | 245 ++++++++++-------- 2 files changed, 152 insertions(+), 113 deletions(-) diff --git a/workflow/engine/classes/MultipleFilesBackup.php b/workflow/engine/classes/MultipleFilesBackup.php index 8e06e5852..a3ee55cba 100644 --- a/workflow/engine/classes/MultipleFilesBackup.php +++ b/workflow/engine/classes/MultipleFilesBackup.php @@ -94,11 +94,21 @@ class MultipleFilesBackup } } - /* Restore from file(s) commpressed by letsBackup function, into a temporary directory - * @ filename got the name and path of the compressed file(s), if there are many files with file extention as a numerical series, the extention should be discriminated. - * @ srcWorkspace contains the workspace to be restored. - * @ dstWorkspace contains the workspace to be overwriting. - * @ overwrite got the option true if the workspace will be overwrite. + /** + * Restore from file(s) compressed by letsBackup function, into a temporary directory + * + * @param string $filename Got the name and path of the compressed file(s), if there are many files with file extention as a numerical series, the extention should be discriminated. + * @param string $srcWorkspace Contains the workspace to be restored. + * @param bool $dstWorkspace Contains the workspace to be overwriting. + * @param bool $overwrite Got the option true if the workspace will be overwrite. + * + * @throws Exception + * + * @see workflow/engine/bin/tasks/cliWorkspaces.php::run_workspace_restore() + * + * @link https://wiki.processmaker.com/3.0/Backing_up_and_Restoring_ProcessMaker#RestoringWorkspaces + * + * @deprecated Method outdated, only run the upgrade of APP_CACHE_VIEW table */ public static function letsRestore($filename, $srcWorkspace, $dstWorkspace = null, $overwrite = true) { diff --git a/workflow/engine/classes/WorkspaceTools.php b/workflow/engine/classes/WorkspaceTools.php index 5eae87c8e..adc7d7714 100644 --- a/workflow/engine/classes/WorkspaceTools.php +++ b/workflow/engine/classes/WorkspaceTools.php @@ -66,6 +66,23 @@ class WorkspaceTools 'UPDATE LIST_UNASSIGNED_GROUP SET USR_ID=(SELECT USR_ID FROM USERS WHERE USERS.USR_UID=LIST_UNASSIGNED_GROUP.USR_UID)', ); + public static $triggers = [ + 'APP_DELEGATION_UPDATE', + 'APPLICATION_UPDATE', + 'CONTENT_UPDATE' + ]; + public static $bigTables = [ + 'APPLICATION', + 'APP_ASSIGN_SELF_SERVICE_VALUE_GROUP', + 'APP_CACHE_VIEW', + 'APP_DELEGATION', + 'APP_DELAY', + 'APP_DOCUMENT', + 'APP_HISTORY', + 'APP_MESSAGE', + 'GROUP_USER', + 'LOGIN_LOG' + ]; private $lastContentMigrateTable = false; private $listContentMigrateTable = []; @@ -249,18 +266,16 @@ class WorkspaceTools $this->checkMafeRequirements($workspace, $lang); CLI::logging("* End checking MAFE requirements...(Completed on " . (microtime(true) - $start) . " seconds)\n"); - CLI::logging("* Start deleting MySQL triggers: APP_DELEGATION_UPDATE, APPLICATION_UPDATE, CONTENT_UPDATE...\n"); + CLI::logging("* Start deleting MySQL triggers: " . implode(', ', self::$triggers) . "...\n"); $start = microtime(true); - $this->deleteTriggersMySQL(['APP_DELEGATION_UPDATE', 'APPLICATION_UPDATE', 'CONTENT_UPDATE']); - CLI::logging("* End deleting MySQL triggers: APP_DELEGATION_UPDATE, APPLICATION_UPDATE, CONTENT_UPDATE... (Completed on " . + $this->deleteTriggersMySQL(self::$triggers); + CLI::logging("* End deleting MySQL triggers: " . implode(', ', self::$triggers) . "... (Completed on " . (microtime(true) - $start) . " seconds)\n"); - $bigTables = ['APPLICATION', 'APP_ASSIGN_SELF_SERVICE_VALUE_GROUP', 'APP_CACHE_VIEW', 'APP_DELEGATION', 'APP_DELAY', - 'APP_DOCUMENT', 'APP_HISTORY', 'APP_MESSAGE', 'GROUP_USER', 'LOGIN_LOG']; - CLI::logging("* Start deleting indexes from big tables: " . implode(', ', $bigTables) . "...\n"); + CLI::logging("* Start deleting indexes from big tables: " . implode(', ', self::$bigTables) . "...\n"); $start = microtime(true); - $this->deleteIndexes($bigTables); - CLI::logging("* End deleting indexes from big tables: " . implode(', ', $bigTables) . "... (Completed on " . + $this->deleteIndexes(self::$bigTables); + CLI::logging("* End deleting indexes from big tables: " . implode(', ', self::$bigTables) . "... (Completed on " . (microtime(true) - $start) . " seconds)\n"); CLI::logging("* Start to update CONTENT table...\n"); @@ -1854,7 +1869,7 @@ class WorkspaceTools } /** - * restore an archive into a workspace + * Restore a workspace * * Restores any database and files included in the backup, either as a new * workspace, or overwriting a previous one @@ -1865,8 +1880,13 @@ class WorkspaceTools * @param boolean $overwrite if you need overwrite the database * @param string $lang for define the language * @param string $port of database if is empty take 3306 + * @param array $optionMigrateHistoryData * * @throws Exception + * + * @see workflow/engine/bin/tasks/cliWorkspaces.php::run_workspace_restore() + * + * @link https://wiki.processmaker.com/3.0/Backing_up_and_Restoring_ProcessMaker#RestoringWorkspaces */ public static function restore($filename, $srcWorkspace, $dstWorkspace = null, $overwrite = true, $lang = 'en', $port = '', $optionMigrateHistoryData = []) { @@ -2034,115 +2054,124 @@ class WorkspaceTools } } - $start = microtime(true); - CLI::logging("> Remove deprecated files...\n"); - $workspace->removeDeprecatedFiles(); - $stop = microtime(true); - CLI::logging("<*> Remove deprecated files took " . ($stop - $start) . " seconds.\n"); - - if (($pmVersionWorkspaceToRestore != '') && (version_compare( - $pmVersionWorkspaceToRestore . "", - $pmVersion . "", - "<" - ) || $pmVersion == "") - ) { - $start = microtime(true); - CLI::logging("> Updating database...\n"); - $workspace->upgradeDatabase($onedb); - $stop = microtime(true); - CLI::logging("<*> Database Upgrade Process took " . ($stop - $start) . " seconds.\n"); - } - - $start = microtime(true); - CLI::logging("> Verify files enterprise old...\n"); - $workspace->verifyFilesOldEnterprise($workspaceName); - $stop = microtime(true); - CLI::logging("<*> Verify took " . ($stop - $start) . " seconds.\n"); - - $start = microtime(true); - CLI::logging("> Verify License Enterprise...\n"); - $workspace->verifyLicenseEnterprise($workspaceName); - $stop = microtime(true); - CLI::logging("<*> Verify took " . ($stop - $start) . " seconds.\n"); - - $start = microtime(true); - CLI::logging("> Check Mafe Requirements...\n"); - $workspace->checkMafeRequirements($workspaceName, $lang); - $stop = microtime(true); - CLI::logging("<*> Check Mafe Requirements Process took " . ($stop - $start) . " seconds.\n"); - - if (($pmVersionWorkspaceToRestore != '') && (version_compare( - $pmVersionWorkspaceToRestore . "", - $pmVersion . "", - "<" - ) || $pmVersion == "") - ) { - $start = microtime(true); - CLI::logging("> Updating cache view...\n"); - $workspace->upgradeCacheView(true, true, $lang); - $stop = microtime(true); - CLI::logging("<*> Updating cache view Process took " . ($stop - $start) . " seconds.\n"); - } else { - $workspace->upgradeTriggersOfTables(true, $lang); - } - - if ($pmVersion == '' && strpos(strtoupper($version), 'BRANCH')) { + if (empty($pmVersion) && strpos(strtoupper($version), 'BRANCH')) { $pmVersion = 'dev-version-backup'; } - //Move the labels of content to the corresponding table - $start = microtime(true); - CLI::logging("> Optimizing content data...\n"); - $workspace->migrateContent($workspace->name, $lang); - $stop = microtime(true); - CLI::logging("<*> Optimizing content data took " . ($stop - $start) . " seconds.\n"); + if (!empty($pmVersionWorkspaceToRestore) && (version_compare( + $pmVersionWorkspaceToRestore . "", + $pmVersion . "", + "<" + ) || empty($pmVersion)) || $pmVersion == "dev-version-backup" + ) { + // Upgrade the database schema and data + CLI::logging("* Start updating database schema...\n"); + $start = microtime(true); + $workspace->upgradeDatabase(); + CLI::logging("* End updating database schema...(Completed on " . (microtime(true) - $start) . " seconds)\n"); - //Populate the new fields for replace string UID to Interger ID - $start = microtime(true); - CLI::logging("> Migrating and populating indexing for APP_CACHE_VIEW...\n"); - $workspace->migratePopulateIndexingACV($workspace->name); - $stop = microtime(true); - CLI::logging("<*> Migrating an populating indexing for APP_CACHE_VIEW process took " . ($stop - $start) . " seconds.\n"); + CLI::logging("* Start checking MAFE requirements...\n"); + $start = microtime(true); + $workspace->checkMafeRequirements($workspaceName, $lang); + CLI::logging("* End checking MAFE requirements...(Completed on " . (microtime(true) - $start) . " seconds)\n"); - //Move the data of cases to the corresponding List - /*----------------------------------********---------------------------------*/ - $start = microtime(true); - CLI::logging("> Updating List tables...\n"); - $workspace->migrateList($workspace->name, false, $lang); - $stop = microtime(true); - CLI::logging("<*> Updating List Process took " . ($stop - $start) . " seconds.\n"); - /*----------------------------------********---------------------------------*/ + CLI::logging("* Start deleting MySQL triggers: " . implode(', ', self::$triggers) . "...\n"); + $start = microtime(true); + $workspace->deleteTriggersMySQL(self::$triggers); + CLI::logging("* End deleting MySQL triggers: " . implode(', ', self::$triggers) . "... (Completed on " . + (microtime(true) - $start) . " seconds)\n"); - $start = microtime(true); - CLI::logging("> Updating Files Manager...\n"); - $workspace->processFilesUpgrade(); - $stop = microtime(true); - CLI::logging("<*> Updating Files Manager took " . ($stop - $start) . " seconds.\n"); + CLI::logging("* Start deleting indexes from big tables: " . implode(', ', self::$bigTables) . "...\n"); + $start = microtime(true); + $workspace->deleteIndexes(self::$bigTables); + CLI::logging("* End deleting indexes from big tables: " . implode(', ', self::$bigTables) . "... (Completed on " . + (microtime(true) - $start) . " seconds)\n"); - //Updating generated class files for PM Tables - passthru(PHP_BINARY . ' processmaker regenerate-pmtable-classes ' . $workspace->name); + $start = microtime(true); + CLI::logging("* Start to migrate texts/values from 'CONTENT' table to the corresponding object tables...\n"); + $workspace->migrateContent($lang); + CLI::logging("* End to migrate texts/values from 'CONTENT' table to the corresponding object tables... (Completed on " . + (microtime(true) - $start) . " seconds)\n"); - $keepDynContent = isset($optionMigrateHistoryData['keepDynContent']) && $optionMigrateHistoryData['keepDynContent'] === true; - //Review if we need to remove the 'History of use' from APP_HISTORY - $start = microtime(true); - CLI::logging("> Clearing History of Use from APP_HISTORY table...\n"); - $workspace->clearDynContentHistoryData(false, $keepDynContent); - $stop = microtime(true); - CLI::logging("<*> Clearing History of Use from APP_HISTORY table took " . ($stop - $start) . " seconds.\n"); + CLI::logging("* Start updating rows in Web Entry table for classic processes...\n"); + $start = microtime(true); + $workspace->updatingWebEntryClassicModel(true); + CLI::logging("* End updating rows in Web Entry table for classic processes...(Completed on " . + (microtime(true) - $start) . " seconds)\n"); - /*----------------------------------********---------------------------------*/ - $start = microtime(true); - CLI::logging("> Migrating history data...\n"); - $workspace->migrateAppHistoryToAppDataChangeLog(false); - $stop = microtime(true); - CLI::logging("<*> Migrating history data took " . ($stop - $start) . " seconds.\n"); - /*----------------------------------********---------------------------------*/ + CLI::logging("* Start to update Files Manager...\n"); + $start = microtime(true); + $workspace->processFilesUpgrade($workspaceName); + CLI::logging("* End to update Files Manager... (Completed on " . (microtime(true) - $start) . " seconds)\n"); + CLI::logging("* Start migrating and populating plugin singleton data...\n"); + $start = microtime(true); + $workspace->migrateSingleton($workspaceName); + CLI::logging("* End migrating and populating plugin singleton data...(Completed on " . + (microtime(true) - $start) . " seconds)\n"); + + CLI::logging("* Start to check Intermediate Email Event...\n"); + $start = microtime(true); + $workspace->checkIntermediateEmailEvent(); + CLI::logging("* End to check Intermediate Email Event... (Completed on " . (microtime(true) - $start) . " seconds)\n"); + + CLI::logging("* Start cleaning DYN_CONTENT in APP_HISTORY...\n"); + $start = microtime(true); + $keepDynContent = isset($optionMigrateHistoryData['keepDynContent']) && $optionMigrateHistoryData['keepDynContent'] === true; + $workspace->clearDynContentHistoryData(false, $keepDynContent); + CLI::logging("* End cleaning DYN_CONTENT in APP_HISTORY...(Completed on " . (microtime(true) - $start) . " seconds)\n"); + + /*----------------------------------********---------------------------------*/ + CLI::logging("* Start migrating history data...\n"); + $start = microtime(true); + $workspace->migrateAppHistoryToAppDataChangeLog(false); + CLI::logging("* End migrating history data...(Completed on " . (microtime(true) - $start) . " seconds)\n"); + /*----------------------------------********---------------------------------*/ + + CLI::logging("* Start migrating and populating indexing for avoiding the use of table APP_CACHE_VIEW...\n"); + $start = microtime(true); + $workspace->migratePopulateIndexingACV(); + CLI::logging("* End migrating and populating indexing for avoiding the use of table APP_CACHE_VIEW...(Completed on " . + (microtime(true) - $start) . " seconds)\n"); + + CLI::logging("* Start optimizing Self-Service data in table APP_ASSIGN_SELF_SERVICE_VALUE_GROUP....\n"); + $start = microtime(true); + $workspace->migrateSelfServiceRecordsRun(); + CLI::logging("* End optimizing Self-Service data in table APP_ASSIGN_SELF_SERVICE_VALUE_GROUP....(Completed on " . + (microtime(true) - $start) . " seconds)\n"); + + CLI::logging("* Start adding new fields and populating values in tables related to feature self service by value...\n"); + $start = microtime(true); + $workspace->upgradeSelfServiceData(); + CLI::logging("* End adding new fields and populating values in tables related to feature self service by value...(Completed on " . + (microtime(true) - $start) . " seconds)\n"); + + CLI::logging("* Start adding/replenishing all indexes...\n"); + $start = microtime(true); + $systemSchema = System::getSystemSchema($workspace->dbAdapter); + $workspace->upgradeSchema($systemSchema); + CLI::logging("* End adding/replenishing all indexes...(Completed on " . (microtime(true) - $start) . " seconds)\n"); + + /*----------------------------------********---------------------------------*/ + CLI::logging("* Start migrating to new list tables...\n"); + $start = microtime(true); + $workspace->migrateList(true, $lang); + CLI::logging("* End migrating to new list tables...(Completed on " . (microtime(true) - $start) . " seconds)\n"); + /*----------------------------------********---------------------------------*/ + + CLI::logging("* Start updating MySQL triggers...\n"); + $start = microtime(true); + $workspace->updateTriggers(true, $lang); + CLI::logging("* End updating MySQL triggers...(" . (microtime(true) - $start) . " seconds)\n"); + } + + CLI::logging("> Start To Verify License Enterprise...\n"); $start = microtime(true); - CLI::logging("> Optimizing Self-Service data in table APP_ASSIGN_SELF_SERVICE_VALUE_GROUP....\n"); - $workspace->upgradeSelfServiceData(); - $stop = microtime(true); - CLI::logging("<*> Optimizing Self-Service data in table APP_ASSIGN_SELF_SERVICE_VALUE_GROUP took " . ($stop - $start) . " seconds.\n"); + $workspace->verifyLicenseEnterprise($workspaceName); + CLI::logging("* End To Verify License Enterprise...(" . (microtime(true) - $start) . " seconds)\n"); + + // Updating generated class files for PM Tables + passthru(PHP_BINARY . ' processmaker regenerate-pmtable-classes ' . $workspaceName); } CLI::logging("Removing temporary files\n"); @@ -2318,7 +2347,7 @@ class WorkspaceTools CLI::logging(" Migrating Enterprise Core version...\n"); if (!file_exists($pathNewFile)) { CLI::logging(" Creating folder in $pathNewFile\n"); - G::mk_dir($newDiretory, 0777); + G::mk_dir($pathNewFile, 0777); } $shared_stat = stat(PATH_DATA); if (file_exists($pathDirectoryEnterprise)) { From 9f2a543c2d85d30982580cf667854901c40ed0a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julio=20Cesar=20Laura=20Avenda=C3=B1o?= Date: Thu, 4 Jul 2019 10:36:22 -0400 Subject: [PATCH 21/21] Resolving conflicts after merge in develop the features related to Laravel 5.7 and MySQL 5.7 (Part 2) --- workflow/engine/classes/WorkspaceTools.php | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/workflow/engine/classes/WorkspaceTools.php b/workflow/engine/classes/WorkspaceTools.php index cd70e65e7..14f117508 100644 --- a/workflow/engine/classes/WorkspaceTools.php +++ b/workflow/engine/classes/WorkspaceTools.php @@ -283,9 +283,8 @@ class WorkspaceTools $this->upgradeContent($workspace); CLI::logging("* End to update CONTENT table... (Completed on " . (microtime(true) - $start) . " seconds)\n"); - CLI::logging("* Start to update CONTENT table...\n"); - $start = microtime(true); CLI::logging("* Start to migrate texts/values from 'CONTENT' table to the corresponding object tables...\n"); + $start = microtime(true); $this->migrateContent($lang); CLI::logging("* End to migrate texts/values from 'CONTENT' table to the corresponding object tables... (Completed on " . (microtime(true) - $start) . " seconds)\n"); @@ -354,12 +353,10 @@ class WorkspaceTools $this->upgradeSchema($systemSchema); CLI::logging("* End adding/replenishing all indexes...(Completed on " . (microtime(true) - $start) . " seconds)\n"); - /*----------------------------------********---------------------------------*/ CLI::logging("* Start migrating to new list tables...\n"); $start = microtime(true); $this->migrateList(true, $lang); CLI::logging("* End migrating to new list tables...(Completed on " . (microtime(true) - $start) . " seconds)\n"); - /*----------------------------------********---------------------------------*/ CLI::logging("* Start updating MySQL triggers...\n"); $start = microtime(true); @@ -2088,8 +2085,8 @@ class WorkspaceTools CLI::logging("* End deleting indexes from big tables: " . implode(', ', self::$bigTables) . "... (Completed on " . (microtime(true) - $start) . " seconds)\n"); - $start = microtime(true); CLI::logging("* Start to migrate texts/values from 'CONTENT' table to the corresponding object tables...\n"); + $start = microtime(true); $workspace->migrateContent($lang); CLI::logging("* End to migrate texts/values from 'CONTENT' table to the corresponding object tables... (Completed on " . (microtime(true) - $start) . " seconds)\n"); @@ -2157,7 +2154,6 @@ class WorkspaceTools $start = microtime(true); $workspace->migrateList(true, $lang); CLI::logging("* End migrating to new list tables...(Completed on " . (microtime(true) - $start) . " seconds)\n"); - /*----------------------------------********---------------------------------*/ CLI::logging("* Start updating MySQL triggers...\n"); $start = microtime(true);