From 58e9f8bdb62a3fd989aa35c8007d780d3c169d6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustavo=20Bascop=C3=A9?= Date: Mon, 15 Sep 2025 15:25:25 -0400 Subject: [PATCH 1/2] Added a method to replace copied variables with new ones in the script --- .../ImportExport/Exporters/ScriptExporter.php | 184 +++++++++++++++++- 1 file changed, 180 insertions(+), 4 deletions(-) diff --git a/ProcessMaker/ImportExport/Exporters/ScriptExporter.php b/ProcessMaker/ImportExport/Exporters/ScriptExporter.php index 48ef0fabd4..21c151e6d8 100644 --- a/ProcessMaker/ImportExport/Exporters/ScriptExporter.php +++ b/ProcessMaker/ImportExport/Exporters/ScriptExporter.php @@ -2,6 +2,8 @@ namespace ProcessMaker\ImportExport\Exporters; +use Illuminate\Support\Facades\DB; +use Illuminate\Support\Facades\Log; use ProcessMaker\ImportExport\DependentType; use ProcessMaker\Models\EnvironmentVariable; use ProcessMaker\Models\ScriptCategory; @@ -46,16 +48,19 @@ public function import() : bool $this->model->script_executor_id = $executor->id; } + // Update environment variable references in script code + $this->updateEnvironmentVariableReferences(); + // Pre-save cleanup for data source scripts to prevent constraint violations if ($this->mode === 'update' && $this->model->exists) { // Check if this script has any data source relationships that might cause conflicts - $hasDataSourceRelationships = \DB::table('data_source_scripts') + $hasDataSourceRelationships = DB::table('data_source_scripts') ->where('script_id', $this->model->id) ->exists(); if ($hasDataSourceRelationships) { // Clean up any conflicting records in data_source_scripts - \DB::table('data_source_scripts') + DB::table('data_source_scripts') ->where('script_id', $this->model->id) ->where('id', '!=', $this->model->id) ->delete(); @@ -72,11 +77,182 @@ private function getEnvironmentVariables() : array // Search for environment variable present in the code foreach ($environmentVariables as $variable) { - if (preg_match('/[^a-zA-Z0-9\s]' . $variable->name . '[^a-zA-Z0-9\s]?/', $this->model->code)) { - $environmentVariablesFound[] = $variable; + // Multiple patterns to catch different usage styles + $patterns = [ + // JavaScript patterns + '/\bprocess\.env\.' . preg_quote($variable->name, '/') . '\b/', // process.env.VAR + '/\bprocess\.env\[\s*[\'"]' . preg_quote($variable->name, '/') . '[\'"]\s*\]/', // process.env['VAR'] + + // PHP patterns + '/\bconfig\s*\(\s*[\'"]' . preg_quote($variable->name, '/') . '[\'"]\s*\)/', // config('VAR') + '/\benv\s*\(\s*[\'"]' . preg_quote($variable->name, '/') . '[\'"]\s*\)/', // env('VAR') + '/\$_ENV\s*\[\s*[\'"]' . preg_quote($variable->name, '/') . '[\'"]\s*\]/', // $_ENV['VAR'] + '/\$_SERVER\s*\[\s*[\'"]' . preg_quote($variable->name, '/') . '[\'"]\s*\]/', // $_SERVER['VAR'] + + // Java patterns + '/\bSystem\.getenv\s*\(\s*[\'"]' . preg_quote($variable->name, '/') . '[\'"]\s*\)/', // System.getenv("VAR") + '/\bSystem\.getProperty\s*\(\s*[\'"]' . preg_quote($variable->name, '/') . '[\'"]\s*\)/', // System.getProperty("VAR") + + // C# patterns + '/\bEnvironment\.GetEnvironmentVariable\s*\(\s*[\'"]' . preg_quote($variable->name, '/') . '[\'"]\s*\)/', // Environment.GetEnvironmentVariable("VAR") + '/\bConfigurationManager\.AppSettings\s*\[\s*[\'"]' . preg_quote($variable->name, '/') . '[\'"]\s*\]/', // ConfigurationManager.AppSettings["VAR"] + + // Python patterns + '/\bos\.environ\s*\[\s*[\'"]' . preg_quote($variable->name, '/') . '[\'"]\s*\]/', // os.environ['VAR'] + '/\bos\.environ\.get\s*\(\s*[\'"]' . preg_quote($variable->name, '/') . '[\'"]\s*\)/', // os.environ.get('VAR') + '/\bos\.getenv\s*\(\s*[\'"]' . preg_quote($variable->name, '/') . '[\'"]\s*\)/', // os.getenv('VAR') + ]; + + foreach ($patterns as $pattern) { + if (preg_match($pattern, $this->model->code)) { + $environmentVariablesFound[] = $variable; + break; + } } } return $environmentVariablesFound; } + + /** + * Update environment variable references in script code when variables are renamed during import + * + * Note: This is a basic implementation. For a complete solution, you would need to: + * 1. Track original variable names during export phase + * 2. Map original names to new names after duplicate handling + * 3. Update all references in the script code + */ + private function updateEnvironmentVariableReferences(): void + { + // Only process in copy mode where variables might be renamed + if ($this->mode !== 'copy') { + return; + } + + // Get the original variables that were detected during export + $originalVariables = $this->getEnvironmentVariables(); + $variableMapping = []; + + // Compare with the imported variables to detect name changes + foreach ($this->getDependents(DependentType::ENVIRONMENT_VARIABLES, true) as $dependent) { + $importedVar = $dependent->model; + + // Find matching original variable by comparing the base name + foreach ($originalVariables as $originalVar) { + $mapped = false; + + // Check if this is a renamed version (has suffix like _1, _2, etc.) + if (preg_match('/^' . preg_quote($originalVar->name) . '_\d+$/', $importedVar->name)) { + $variableMapping[$originalVar->name] = $importedVar->name; + $mapped = true; + } + // Check if it's exactly the same name (no rename needed) + elseif ($originalVar->name === $importedVar->name) { + // Don't add to mapping since no replacement is needed + $mapped = true; + } + // Check if it has other suffixes like _copy, _duplicate, etc. + elseif (preg_match('/^' . preg_quote($originalVar->name) . '_(copy|duplicate|\d+)$/i', $importedVar->name)) { + $variableMapping[$originalVar->name] = $importedVar->name; + $mapped = true; + } + + if ($mapped) { + break; + } + } + } + + // Update script code with new variable names + if (!empty($variableMapping)) { + $updatedCode = $this->model->code; + + foreach ($variableMapping as $oldName => $newName) { + // Update common patterns for environment variable access + $patterns = [ + // JavaScript patterns - process.env.VARIABLE_NAME → process.env.VARIABLE_NAME_1 + '/\bprocess\.env\.' . preg_quote($oldName, '/') . '\b/', + '/\bprocess\.env\[\s*[\'"]' . preg_quote($oldName, '/') . '[\'"]\s*\]/', + '/\bprocess\.env\[\s*"' . preg_quote($oldName, '/') . '"\s*\]/', // Double quotes + + // PHP patterns + // config('VARIABLE_NAME') → config('VARIABLE_NAME_1') + '/\bconfig\s*\(\s*[\'"]' . preg_quote($oldName, '/') . '[\'"]\s*\)/', + // env('VARIABLE_NAME') → env('VARIABLE_NAME_1') + '/\benv\s*\(\s*[\'"]' . preg_quote($oldName, '/') . '[\'"]\s*\)/', + // $_ENV['VARIABLE_NAME'] → $_ENV['VARIABLE_NAME_1'] + '/\$_ENV\s*\[\s*[\'"]' . preg_quote($oldName, '/') . '[\'"]\s*\]/', + // $_SERVER['VARIABLE_NAME'] → $_SERVER['VARIABLE_NAME_1'] + '/\$_SERVER\s*\[\s*[\'"]' . preg_quote($oldName, '/') . '[\'"]\s*\]/', + // getenv('VARIABLE_NAME') → getenv('VARIABLE_NAME_1') + '/\bgetenv\s*\(\s*[\'"]' . preg_quote($oldName, '/') . '[\'"]\s*\)/', + // Config::get('VARIABLE_NAME') → Config::get('VARIABLE_NAME_1') + '/\bConfig\s*::\s*get\s*\(\s*[\'"]' . preg_quote($oldName, '/') . '[\'"]\s*\)/', + + // Java patterns + // System.getenv("VARIABLE_NAME") → System.getenv("VARIABLE_NAME_1") + '/\bSystem\.getenv\s*\(\s*[\'"]' . preg_quote($oldName, '/') . '[\'"]\s*\)/', + // System.getProperty("VARIABLE_NAME") → System.getProperty("VARIABLE_NAME_1") + '/\bSystem\.getProperty\s*\(\s*[\'"]' . preg_quote($oldName, '/') . '[\'"]\s*\)/', + + // C# patterns + // Environment.GetEnvironmentVariable("VARIABLE_NAME") → Environment.GetEnvironmentVariable("VARIABLE_NAME_1") + '/\bEnvironment\.GetEnvironmentVariable\s*\(\s*[\'"]' . preg_quote($oldName, '/') . '[\'"]\s*\)/', + // ConfigurationManager.AppSettings["VARIABLE_NAME"] → ConfigurationManager.AppSettings["VARIABLE_NAME_1"] + '/\bConfigurationManager\.AppSettings\s*\[\s*[\'"]' . preg_quote($oldName, '/') . '[\'"]\s*\]/', + + // Python patterns + // os.environ['VARIABLE_NAME'] → os.environ['VARIABLE_NAME_1'] + '/\bos\.environ\s*\[\s*[\'"]' . preg_quote($oldName, '/') . '[\'"]\s*\]/', + // os.environ.get('VARIABLE_NAME') → os.environ.get('VARIABLE_NAME_1') + '/\bos\.environ\.get\s*\(\s*[\'"]' . preg_quote($oldName, '/') . '[\'"]\s*\)/', + // os.getenv('VARIABLE_NAME') → os.getenv('VARIABLE_NAME_1') + '/\bos\.getenv\s*\(\s*[\'"]' . preg_quote($oldName, '/') . '[\'"]\s*\)/', + ]; + + foreach ($patterns as $patternIndex => $pattern) { + $updatedCode = preg_replace_callback($pattern, function ($matches) use ($oldName, $newName, $patternIndex) { + $original = $matches[0]; + + // Handle different replacement patterns + switch ($patternIndex) { + case 0: // process.env.VARIABLE_NAME + return str_replace('process.env.' . $oldName, 'process.env.' . $newName, $original); + case 1: // process.env['VARIABLE_NAME'] + case 2: // process.env["VARIABLE_NAME"] + return str_replace($oldName, $newName, $original); + case 6: // System.getenv for Java + return str_replace($oldName, $newName, $original); + case 7: // System.getProperty for Java + return str_replace($oldName, $newName, $original); + case 8: // Environment.GetEnvironmentVariable for C# + return str_replace($oldName, $newName, $original); + case 9: // ConfigurationManager.AppSettings for C# + return str_replace($oldName, $newName, $original); + case 10: // os.environ for Python + case 11: // os.environ.get for Python + case 12: // os.getenv for Python + return str_replace($oldName, $newName, $original); + default: // All other patterns (PHP) + return str_replace($oldName, $newName, $original); + } + }, $updatedCode); + } + } + + // Only update if changes were made + if ($updatedCode !== $this->model->code) { + $this->model->code = $updatedCode; + + // Log the variable name changes (summary) + Log::info('ScriptExporter: Updated variable references in script', [ + 'script_id' => $this->model->id, + 'script_title' => $this->model->title, + 'variables_updated' => count($variableMapping), + 'mappings' => $variableMapping, + 'mode' => $this->mode, + ]); + } + } + } } From f8e108b144e0ef175f7e2515419bda6575fe42b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustavo=20Bascop=C3=A9?= Date: Tue, 16 Sep 2025 10:31:15 -0400 Subject: [PATCH 2/2] fix php-unit tests --- ProcessMaker/ImportExport/Exporters/ScriptExporter.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ProcessMaker/ImportExport/Exporters/ScriptExporter.php b/ProcessMaker/ImportExport/Exporters/ScriptExporter.php index 21c151e6d8..c1083bbca5 100644 --- a/ProcessMaker/ImportExport/Exporters/ScriptExporter.php +++ b/ProcessMaker/ImportExport/Exporters/ScriptExporter.php @@ -101,6 +101,9 @@ private function getEnvironmentVariables() : array '/\bos\.environ\s*\[\s*[\'"]' . preg_quote($variable->name, '/') . '[\'"]\s*\]/', // os.environ['VAR'] '/\bos\.environ\.get\s*\(\s*[\'"]' . preg_quote($variable->name, '/') . '[\'"]\s*\)/', // os.environ.get('VAR') '/\bos\.getenv\s*\(\s*[\'"]' . preg_quote($variable->name, '/') . '[\'"]\s*\)/', // os.getenv('VAR') + + // Additional PHP patterns + '/\bgetenv\s*\(\s*[\'"]' . preg_quote($variable->name, '/') . '[\'"]\s*\)/', // getenv('VAR') ]; foreach ($patterns as $pattern) {