Skip to content

Commit 108c15a

Browse files
committed
Merge branch 'develop' into epic/FOUR-25679
2 parents 6a3b230 + 92722f6 commit 108c15a

10 files changed

Lines changed: 367 additions & 162 deletions

File tree

ProcessMaker/Http/Controllers/Api/ProcessRequestController.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
use ProcessMaker\Models\ProcessRequest;
3333
use ProcessMaker\Models\ProcessRequestToken;
3434
use ProcessMaker\Models\User;
35+
use ProcessMaker\Nayra\Contracts\Bpmn\ActivityInterface;
3536
use ProcessMaker\Nayra\Contracts\Bpmn\CatchEventInterface;
3637
use ProcessMaker\Notifications\ProcessCanceledNotification;
3738
use ProcessMaker\Query\SyntaxError;
@@ -609,6 +610,19 @@ private function cancelRequestToken(ProcessRequest $request)
609610
// Close process request
610611
$request->status = 'CANCELED';
611612
$request->save();
613+
614+
// Close any token still open after status is CANCELED (race: task submit commits after CancelRequest job).
615+
ProcessRequestToken::query()
616+
->where('process_request_id', $request->getKey())
617+
->where('status', '!=', ActivityInterface::TOKEN_STATE_CLOSED)
618+
->update([
619+
'status' => ActivityInterface::TOKEN_STATE_CLOSED,
620+
'completed_at' => now(),
621+
'due_at' => null,
622+
'riskchanges_at' => null,
623+
'user_id' => null,
624+
]);
625+
612626
// Update case status
613627
CaseUpdateStatus::dispatchSync($request);
614628

ProcessMaker/ImportExport/Dependent.php

Lines changed: 51 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ public function __construct(
88
public string $type,
99
public string $uuid,
1010
public Manifest $manifest,
11-
public $meta,
11+
public mixed $meta,
1212
public string $exporterClass,
1313
public string $modelClass,
1414
public array $fallbackMatches,
@@ -45,45 +45,67 @@ public static function fromArray(array $array, Manifest $manifest)
4545
}, $array);
4646
}
4747

48-
public function __get($property)
48+
public function __get(string $property)
4949
{
5050
$asset = $this->manifest->get($this->uuid);
51+
$value = null;
5152

5253
if ($property === 'model' && !$asset) {
53-
// Attempt to reconstruct discarded model if it exists on the target instance
54-
$assetInfo = [
55-
'model' => $this->modelClass,
56-
'attributes' => $this->fallbackMatches,
57-
];
58-
59-
list($_, $model) = Manifest::getModel($this->uuid, $assetInfo, 'discard', $this->exporterClass, false);
60-
61-
// Only return the model if it is persisted in the database
62-
if ($model && $model->exists) {
63-
return $model;
64-
}
54+
$value = $this->getDiscardedModel();
55+
} elseif ($property === 'mode') {
56+
$value = $this->getMode($asset);
57+
} elseif ($property === 'name') {
58+
$value = $this->getName($asset);
59+
} elseif ($asset) {
60+
$value = $asset->$property;
6561
}
6662

67-
if ($property === 'mode') {
68-
if ($asset) {
69-
return $asset->mode;
70-
} else {
71-
return 'discard';
72-
}
63+
return $value;
64+
}
65+
66+
private function getDiscardedModel()
67+
{
68+
if ($this->canUseDiscardedDependentFinder()) {
69+
return $this->exporterClass::findDiscardedDependentModel($this);
7370
}
7471

75-
if ($property === 'name') {
76-
if ($asset) {
77-
return $asset->getName($this->model);
78-
} else {
79-
return '';
80-
}
72+
return $this->findPersistedDiscardedModel();
73+
}
74+
75+
private function canUseDiscardedDependentFinder(): bool
76+
{
77+
if (!method_exists($this->exporterClass, 'findDiscardedDependentModel')) {
78+
return false;
8179
}
8280

83-
if (!$asset) {
84-
return null;
81+
if (!method_exists($this->exporterClass, 'shouldFindDiscardedDependentModel')) {
82+
return true;
8583
}
8684

87-
return $asset->$property;
85+
return $this->exporterClass::shouldFindDiscardedDependentModel($this);
86+
}
87+
88+
private function findPersistedDiscardedModel()
89+
{
90+
// Attempt to reconstruct discarded model if it exists on the target instance
91+
$assetInfo = [
92+
'model' => $this->modelClass,
93+
'attributes' => $this->fallbackMatches,
94+
];
95+
96+
[, $model] = Manifest::getModel($this->uuid, $assetInfo, 'discard', $this->exporterClass, false);
97+
98+
// Only return the model if it is persisted in the database
99+
return $model && $model->exists ? $model : null;
100+
}
101+
102+
private function getMode(mixed $asset): string
103+
{
104+
return $asset ? $asset->mode : 'discard';
105+
}
106+
107+
private function getName(mixed $asset): string
108+
{
109+
return $asset ? $asset->getName($this->model) : '';
88110
}
89111
}

ProcessMaker/ImportExport/Exporters/GroupExporter.php

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
namespace ProcessMaker\ImportExport\Exporters;
44

55
use Illuminate\Support\Facades\Log;
6+
use ProcessMaker\ImportExport\Dependent;
7+
use ProcessMaker\ImportExport\DependentType;
8+
use ProcessMaker\Models\Group;
69
use ProcessMaker\Models\Permission;
710

811
class GroupExporter extends ExporterBase
@@ -13,6 +16,22 @@ class GroupExporter extends ExporterBase
1316

1417
public $discard = true;
1518

19+
public static function shouldFindDiscardedDependentModel(Dependent $dependent): bool
20+
{
21+
return $dependent->type === DependentType::GROUP_ASSIGNMENT;
22+
}
23+
24+
public static function findDiscardedDependentModel(Dependent $dependent): ?Group
25+
{
26+
$name = $dependent->fallbackMatches['name'] ?? null;
27+
28+
if (!$name) {
29+
return null;
30+
}
31+
32+
return Group::where('name', $name)->first();
33+
}
34+
1635
public function export() : void
1736
{
1837
// Skipping user expansion to avoid exporting entire group membership (can be tens of thousands).

ProcessMaker/Jobs/CancelRequest.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,12 @@
22

33
namespace ProcessMaker\Jobs;
44

5+
use Carbon\Carbon;
56
use Illuminate\Contracts\Queue\ShouldQueue;
67
use Illuminate\Support\Facades\Notification;
78
use ProcessMaker\Models\ProcessRequest;
9+
use ProcessMaker\Models\ProcessRequestToken;
10+
use ProcessMaker\Nayra\Contracts\Bpmn\ActivityInterface;
811
use ProcessMaker\Notifications\ProcessCanceledNotification;
912
use ProcessMaker\Repositories\ExecutionInstanceRepository;
1013
use ProcessMaker\Repositories\TokenRepository;
@@ -49,5 +52,18 @@ public function action(ProcessRequest $instance)
4952
foreach ($instance->getTokens()->toArray() as $token) {
5053
$tokenRepo->store($token);
5154
}
55+
56+
// Tokens created after the in-memory snapshot (e.g. another user submits a task while
57+
// cancel is confirmed) must still be closed so no ACTIVE task remains on a CANCELED request.
58+
ProcessRequestToken::query()
59+
->where('process_request_id', $instance->getKey())
60+
->where('status', '!=', ActivityInterface::TOKEN_STATE_CLOSED)
61+
->update([
62+
'status' => ActivityInterface::TOKEN_STATE_CLOSED,
63+
'completed_at' => Carbon::now(),
64+
'due_at' => null,
65+
'riskchanges_at' => null,
66+
'user_id' => null,
67+
]);
5268
}
5369
}

ProcessMaker/Jobs/RunNayraScriptTask.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ class RunNayraScriptTask implements ShouldQueue
3636
/**
3737
* Create a new job instance.
3838
*
39-
* @param \ProcessMaker\Models\ProcessRequestToken $token
39+
* @param ProcessRequestToken $token
4040
* @param array $data
4141
*/
4242
public function __construct(TokenInterface $token)

composer.json

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "processmaker/processmaker",
3-
"version": "2026.7.3",
3+
"version": "2026.8.2",
44
"description": "BPM PHP Software",
55
"keywords": [
66
"php bpm processmaker"
@@ -49,7 +49,7 @@
4949
"phpseclib/phpseclib": "^3.0.51",
5050
"pion/laravel-chunk-upload": "dev-master",
5151
"predis/predis": "^2.3",
52-
"processmaker/docker-executor-lua": "^1.0",
52+
"processmaker/docker-executor-lua": "1.0.1",
5353
"processmaker/docker-executor-node": "1.1.0",
5454
"processmaker/docker-executor-php": "1.4.3",
5555
"processmaker/laravel-i18next": "dev-master",
@@ -113,7 +113,7 @@
113113
"Gmail"
114114
],
115115
"processmaker": {
116-
"build": "871804b1",
116+
"build": "90d83217",
117117
"cicd-enabled": true,
118118
"custom": {
119119
"package-ellucian-ethos": "1.19.10",
@@ -144,10 +144,10 @@
144144
"package-zj-birmingham": "dev-main",
145145
"package-tce": "dev-master",
146146
"package-case-overview": "dev-main",
147-
"package-sis-integration": "dev-develop"
147+
"package-sis-integration": "dev-develop",
148+
"package-accessibility": "1.0.1"
148149
},
149150
"enterprise": {
150-
"package-accessibility": "1.0.1",
151151
"connector-docusign": "1.11.2",
152152
"connector-idp": "1.14.2",
153153
"connector-pdf-print": "1.23.3",
@@ -160,10 +160,10 @@
160160
"package-ai": "1.16.17",
161161
"package-analytics-reporting": "1.11.5",
162162
"package-auth": "1.24.15",
163-
"package-collections": "2.27.5",
163+
"package-collections": "2.27.6",
164164
"package-comments": "1.16.4",
165165
"package-conversational-forms": "1.15.2",
166-
"package-data-sources": "1.34.9",
166+
"package-data-sources": "1.34.10",
167167
"package-decision-engine": "1.16.3",
168168
"package-dynamic-ui": "1.28.4",
169169
"package-email-start-event": "1.0.11",
@@ -176,7 +176,7 @@
176176
"package-product-analytics": "1.5.11",
177177
"package-projects": "1.12.9",
178178
"package-rpa": "1.1.2",
179-
"package-savedsearch": "1.43.11",
179+
"package-savedsearch": "1.43.12",
180180
"package-slideshow": "1.4.3",
181181
"package-smart-extract": "0.0.6",
182182
"package-signature": "1.15.5",
@@ -250,4 +250,4 @@
250250
"ignore": []
251251
}
252252
}
253-
}
253+
}

0 commit comments

Comments
 (0)