Skip to content

Commit d46c124

Browse files
Merge branch 'develop' of github.com:ProcessMaker/processmaker into task/FOUR-26812-b
2 parents 8a47405 + 492e4a5 commit d46c124

189 files changed

Lines changed: 9307 additions & 2543 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.env.example

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,14 @@ SCRIPT_MICROSERVICE_PUSHER_SCHEME=
6565
SCRIPT_MICROSERVICE_PUSHER_HOST=
6666
SCRIPT_MICROSERVICE_PUSHER_PORT=
6767

68+
# FrankenPHP workers ignore CLI php.ini. Use Caddyfile + --caddyfile=Caddyfile.
69+
# OCTANE_MEMORY_LIMIT=512M
70+
# OCTANE_MAX_EXECUTION_TIME=90
71+
# OCTANE_POST_MAX_SIZE=200M
72+
# OCTANE_UPLOAD_MAX_FILESIZE=200M
73+
# OCTANE_MAX_INPUT_VARS=9000
74+
# OCTANE_MAX_INPUT_TIME=90
75+
6876
KEYCLOAK_CLIENT_ID=
6977
KEYCLOAK_CLIENT_SECRET=
7078
KEYCLOAK_BASE_URL=

.github/workflows/deploy-pm4.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,12 @@ on:
66
- cron: '30 2 * * *' # run daily
77
workflow_dispatch:
88
workflow_call:
9+
10+
# Cancel superseded PR runs (including nested deploy-pm4). Do not cancel a close/delete.
11+
concurrency:
12+
group: deploy-pm4-${{ github.repository }}-${{ github.event.pull_request.number || github.ref }}
13+
cancel-in-progress: ${{ github.event_name == 'pull_request' && github.event.action != 'closed' }}
14+
915
jobs:
1016
run:
1117
name: Run PM4-workflow

.gitignore

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ storage/ssl
3434
storage/api/*
3535
storage/data-sources/logs/*
3636
storage/decision-tables/*
37+
storage/saved_search_advanced_configuration/*
3738
npm.sh
3839
laravel-echo-server.lock
3940
public/.htaccess
@@ -51,4 +52,7 @@ devhub/pm-font/dist
5152
test-db-snapshot.db
5253
snapshot_*.db
5354
storage/transitions
54-
.envrc
55+
.envrc
56+
**/caddy
57+
frankenphp
58+
frankenphp-worker.php

Caddyfile

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
{
2+
{$CADDY_GLOBAL_OPTIONS}
3+
4+
frankenphp {
5+
# FrankenPHP workers ignore CLI php.ini / PHPRC. Set PHP limits here.
6+
php_ini memory_limit {$OCTANE_MEMORY_LIMIT:3072M}
7+
php_ini max_execution_time {$OCTANE_MAX_EXECUTION_TIME:90}
8+
php_ini post_max_size {$OCTANE_POST_MAX_SIZE:200M}
9+
php_ini upload_max_filesize {$OCTANE_UPLOAD_MAX_FILESIZE:200M}
10+
php_ini max_input_vars {$OCTANE_MAX_INPUT_VARS:9000}
11+
php_ini max_input_time {$OCTANE_MAX_INPUT_TIME:90}
12+
13+
worker {
14+
file "{$APP_PUBLIC_PATH}/frankenphp-worker.php"
15+
{$CADDY_SERVER_WORKER_DIRECTIVE}
16+
}
17+
}
18+
}
19+
20+
{$CADDY_SERVER_SERVER_NAME} {
21+
route {
22+
root * "{$APP_PUBLIC_PATH}"
23+
24+
php_server {
25+
index frankenphp-worker.php
26+
try_files {path} frankenphp-worker.php
27+
resolve_root_symlink
28+
}
29+
}
30+
}
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
<?php
2+
3+
namespace ProcessMaker\Assets;
4+
5+
use DOMXPath;
6+
use ProcessMaker\Models\Process;
7+
use ProcessMaker\Providers\WorkflowServiceProvider;
8+
9+
class DataSourcesInProcess
10+
{
11+
public $type = 'ProcessMaker\Packages\Connectors\DataSources\Models\DataSource';
12+
13+
public $owner = Process::class;
14+
15+
/**
16+
* Get the data sources used in a process
17+
*
18+
* @param Process $process
19+
* @param array $dataSources
20+
*
21+
* @return array
22+
*/
23+
public function referencesToExport(Process $process, array $dataSources = [])
24+
{
25+
// Data Sources used in BPMN Service Tasks
26+
$xpath = new DOMXPath($process->getDefinitions());
27+
$xpath->registerNamespace('pm', WorkflowServiceProvider::PROCESS_MAKER_NS);
28+
29+
// Find all nodes with pm:config
30+
$nodes = $xpath->query("//*[@pm:config!='']");
31+
foreach ($nodes as $node) {
32+
$configString = $node->getAttributeNS(WorkflowServiceProvider::PROCESS_MAKER_NS, 'config');
33+
$config = json_decode($configString, true);
34+
if (isset($config['dataSource']) && is_numeric($config['dataSource'])) {
35+
$dataSources[] = [$this->type, (int) $config['dataSource']];
36+
}
37+
}
38+
39+
return $dataSources;
40+
}
41+
42+
/**
43+
* Update references used in an imported process
44+
*
45+
* @param Process $process
46+
* @param array $references
47+
*
48+
* @return void
49+
*/
50+
public function updateReferences(Process $process, array $references = [])
51+
{
52+
$definitions = $process->getDefinitions();
53+
$xpath = new DOMXPath($definitions);
54+
$xpath->registerNamespace('pm', WorkflowServiceProvider::PROCESS_MAKER_NS);
55+
56+
$nodes = $xpath->query("//*[@pm:config!='']");
57+
foreach ($nodes as $node) {
58+
$configString = $node->getAttributeNS(WorkflowServiceProvider::PROCESS_MAKER_NS, 'config');
59+
$config = json_decode($configString, true);
60+
if (isset($config['dataSource']) && is_numeric($config['dataSource'])) {
61+
$oldRef = $config['dataSource'];
62+
if (isset($references[$this->type][$oldRef])) {
63+
$newRef = $references[$this->type][$oldRef]->getKey();
64+
$config['dataSource'] = $newRef;
65+
$node->setAttributeNS(WorkflowServiceProvider::PROCESS_MAKER_NS, 'config', json_encode($config));
66+
}
67+
}
68+
}
69+
$process->bpmn = $definitions->saveXML();
70+
$process->save();
71+
}
72+
}
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
<?php
2+
3+
namespace ProcessMaker\Assets;
4+
5+
use ProcessMaker\Managers\ExportManager;
6+
use ProcessMaker\Models\Screen;
7+
use Illuminate\Support\Arr;
8+
9+
class DataSourcesInScreen
10+
{
11+
public $type = 'ProcessMaker\Packages\Connectors\DataSources\Models\DataSource';
12+
13+
public $owner = Screen::class;
14+
15+
/**
16+
* Get the data sources (ex. watchers) used in a screen
17+
*
18+
* @param Screen $screen
19+
* @param array $dataSources
20+
*
21+
* @return array
22+
*/
23+
public function referencesToExport(Screen $screen, array $dataSources = [])
24+
{
25+
$watchers = $screen->watchers;
26+
if (is_array($watchers)) {
27+
$this->findInArray($watchers, function ($item) use (&$dataSources) {
28+
if (is_array($item)) {
29+
$scriptId = (string) ($item['script_id'] ?? '');
30+
$id = (string) ($item['script']['id'] ?? '');
31+
if (str_starts_with($scriptId, 'data_source-') || str_starts_with($id, 'data_source-')) {
32+
$numericId = str_replace('data_source-', '', str_starts_with($scriptId, 'data_source-') ? $scriptId : $id);
33+
if (is_numeric($numericId)) {
34+
$dataSources[] = [$this->type, (int) $numericId];
35+
}
36+
}
37+
}
38+
});
39+
}
40+
41+
$config = $screen->versionFor(null)->config;
42+
if (is_array($config)) {
43+
$this->findInArray($config, function ($item) use (&$dataSources) {
44+
if (is_array($item) && isset($item['component']) && $item['component'] === 'FormSelectList' && !empty($item['config']['options']['selectedDataSource'])) {
45+
$dataSources[] = [$this->type, (int) $item['config']['options']['selectedDataSource']];
46+
}
47+
});
48+
}
49+
50+
return $dataSources;
51+
}
52+
53+
/**
54+
* Update references used in an imported screen
55+
*
56+
* @param Screen $screen
57+
* @param array $references
58+
* @param ExportManager $exportManager
59+
*
60+
* @return void
61+
*/
62+
public function updateReferences(Screen $screen, array $references, ExportManager $exportManager)
63+
{
64+
$watches = $screen->watchers;
65+
if (is_array($watches)) {
66+
foreach ($watches as &$watcher) {
67+
$id = (string) ($watcher['script']['id'] ?? '');
68+
if (str_starts_with($id, 'data_source-')) {
69+
$oldRef = str_replace('data_source-', '', $id);
70+
if (isset($references[$this->type][$oldRef])) {
71+
$newRef = $references[$this->type][$oldRef]->getKey();
72+
} else {
73+
$newRef = null;
74+
$exportManager->addLogMessage(
75+
'DataSourcesInScreen:references',
76+
__(
77+
'Imported file does not contain the data source #:dataSource assigned to a watcher',
78+
['dataSource' => $oldRef]
79+
),
80+
false,
81+
__("Missing watcher's data source")
82+
);
83+
}
84+
if ($newRef) {
85+
$watcher['script_id'] = $newRef;
86+
$watcher['script']['id'] = "data_source-$newRef";
87+
$watcher['script']['title'] = $references[$this->type][$oldRef]->name;
88+
}
89+
}
90+
}
91+
}
92+
$screen->watchers = $watches;
93+
94+
$config = $screen->config;
95+
if (is_array($config)) {
96+
$this->findInArray($config, function ($item, $keyDotNotation) use ($references, &$config) {
97+
if (is_array($item) && isset($item['component']) && $item['component'] === 'FormSelectList' && !empty($item['config']['options']['selectedDataSource'])) {
98+
$oldRef = $item['config']['options']['selectedDataSource'];
99+
if (isset($references[$this->type][$oldRef])) {
100+
$newRef = $references[$this->type][$oldRef]->getKey();
101+
Arr::set($config, "$keyDotNotation.config.options.selectedDataSource", $newRef);
102+
}
103+
}
104+
});
105+
$screen->config = $config;
106+
}
107+
108+
$screen->save();
109+
}
110+
111+
/**
112+
* Find recursively in an array
113+
*
114+
* @param array $array
115+
* @param callable $callback
116+
* @param array $path
117+
*
118+
* @return void
119+
*/
120+
private function findInArray(array $array, callable $callback, array $path = [])
121+
{
122+
call_user_func($callback, $array, implode('.', $path));
123+
foreach ($array as $key => $item) {
124+
if (is_array($item)) {
125+
$this->findInArray($item, $callback, array_merge($path, [$key]));
126+
} else {
127+
call_user_func($callback, $item, implode('.', array_merge($path, [$key])));
128+
}
129+
}
130+
}
131+
}

ProcessMaker/Assets/ScriptsInProcess.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,10 @@ public function referencesToExport(Process $process, array $scripts = [])
3030
// Used in scriptRef
3131
$nodes = $xpath->query("//*[@pm:scriptRef!='']");
3232
foreach ($nodes as $node) {
33-
$scripts[] = [Script::class, $node->getAttributeNS(WorkflowServiceProvider::PROCESS_MAKER_NS, 'scriptRef')];
33+
$scriptId = $node->getAttributeNS(WorkflowServiceProvider::PROCESS_MAKER_NS, 'scriptRef');
34+
if (!str_starts_with((string) $scriptId, 'data_source-')) {
35+
$scripts[] = [Script::class, $scriptId];
36+
}
3437
}
3538

3639
return $scripts;
@@ -54,6 +57,9 @@ public function updateReferences(Process $process, array $references = [])
5457
$nodes = $xpath->query("//*[@pm:scriptRef!='']");
5558
foreach ($nodes as $node) {
5659
$oldRef = $node->getAttributeNS(WorkflowServiceProvider::PROCESS_MAKER_NS, 'scriptRef');
60+
if (str_starts_with((string) $oldRef, 'data_source-')) {
61+
continue;
62+
}
5763
$newRef = $references[Script::class][$oldRef]->getKey();
5864
$node->setAttributeNS(WorkflowServiceProvider::PROCESS_MAKER_NS, 'scriptRef', $newRef);
5965
}

ProcessMaker/Assets/ScriptsInScreen.php

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,11 @@ public function referencesToExport(Screen $screen, array $scripts = [])
2626
if (is_array($config)) {
2727
$this->findInArray($config, function ($item) use (&$scripts) {
2828
if (is_array($item) && !empty($item['script_id'])) {
29-
$scripts[] = [Script::class, $item['script_id']];
29+
$scriptId = (string) $item['script_id'];
30+
$id = (string) ($item['script']['id'] ?? '');
31+
if (!str_starts_with($scriptId, 'data_source-') && !str_starts_with($id, 'data_source-')) {
32+
$scripts[] = [Script::class, $item['script_id']];
33+
}
3034
}
3135
});
3236
}
@@ -47,11 +51,12 @@ public function updateReferences(Screen $screen, array $references, ExportManage
4751
$watches = $screen->watchers;
4852
if (is_array($watches)) {
4953
foreach ($watches as &$watcher) {
50-
$refParts = explode('-', $watcher['script_id']);
51-
if ($refParts[0] === 'data_source') {
54+
$scriptId = (string) ($watcher['script_id'] ?? '');
55+
$id = (string) ($watcher['script']['id'] ?? '');
56+
if (str_starts_with($scriptId, 'data_source-') || str_starts_with($id, 'data_source-')) {
5257
continue;
5358
}
54-
$oldRef = $refParts[1];
59+
$oldRef = $scriptId;
5560
if (isset($references[Script::class][$oldRef])) {
5661
$newRef = $references[Script::class][$oldRef]->getKey();
5762
} else {
@@ -82,17 +87,18 @@ public function updateReferences(Screen $screen, array $references, ExportManage
8287
*
8388
* @param array $array
8489
* @param callable $callback
90+
* @param array $path
8591
*
8692
* @return void
8793
*/
88-
private function findInArray(array $array, callable $callback)
94+
private function findInArray(array $array, callable $callback, array $path = [])
8995
{
90-
call_user_func($callback, $array);
91-
foreach ($array as $item) {
96+
call_user_func($callback, $array, implode('.', $path));
97+
foreach ($array as $key => $item) {
9298
if (is_array($item)) {
93-
$this->findInArray($item, $callback);
99+
$this->findInArray($item, $callback, array_merge($path, [$key]));
94100
} else {
95-
call_user_func($callback, $item);
101+
call_user_func($callback, $item, implode('.', array_merge($path, [$key])));
96102
}
97103
}
98104
}

0 commit comments

Comments
 (0)