Skip to content

Commit 223cc11

Browse files
committed
feat: add 'do_not_update' field to environment variables for import/export logic
1 parent cf75c38 commit 223cc11

13 files changed

Lines changed: 237 additions & 4 deletions

File tree

‎ProcessMaker/Http/Controllers/Api/EnvironmentVariablesController.php‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ public function update(EnvironmentVariable $environment_variable, Request $reque
182182
validator($data, EnvironmentVariable::rules($environment_variable), EnvironmentVariable::messages())->validate();
183183
$linkedAsset = EnvironmentVariable::validateAssetLinkConsistency($data);
184184

185-
$fields = ['name', 'description', 'asset_type'];
185+
$fields = ['name', 'description', 'asset_type', 'do_not_update'];
186186
if ($linkedAsset) {
187187
// Guarantee value is always the selected asset's ID on this instance.
188188
$data['value'] = (string) $linkedAsset->id;

‎ProcessMaker/ImportExport/Exporters/EnvironmentVariableExporter.php‎

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

33
namespace ProcessMaker\ImportExport\Exporters;
44

5+
use Illuminate\Database\Eloquent\Model;
56
use Illuminate\Support\Facades\Log;
67
use ProcessMaker\Enums\ExporterMap;
78
use ProcessMaker\ImportExport\DependentType;
9+
use ProcessMaker\ImportExport\Manifest;
10+
use ProcessMaker\ImportExport\Options;
11+
use ProcessMaker\ImportExport\Psudomodels\Psudomodel;
812

913
class EnvironmentVariableExporter extends ExporterBase
1014
{
@@ -16,6 +20,18 @@ class EnvironmentVariableExporter extends ExporterBase
1620

1721
public $incrementStringSeparator = '_';
1822

23+
public function __construct(
24+
Model|Psudomodel|null $model,
25+
Manifest $manifest,
26+
Options $options,
27+
$ignoreExplicitDiscard
28+
) {
29+
parent::__construct($model, $manifest, $options, $ignoreExplicitDiscard);
30+
31+
// PHP does not allow closures as property defaults.
32+
$this->discard = fn ($envVar) => (bool) ($envVar->do_not_update ?? false);
33+
}
34+
1935
public function export() : void
2036
{
2137
$this->addReference(DependentType::ENVIRONMENT_VARIABLE_VALUE, $this->model->value);

‎ProcessMaker/ImportExport/Exporters/ExporterBase.php‎

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,12 @@ abstract class ExporterBase implements ExporterInterface
4747

4848
public $hidden = false;
4949

50+
/**
51+
* When true (or a callable returning true), this asset is explicitly discarded.
52+
* Callables receive the model: fn (Model $model): bool
53+
*
54+
* @var bool|callable
55+
*/
5056
public $discard = false;
5157

5258
public static $forceUpdate = false;
@@ -135,7 +141,7 @@ public function uuid() : string
135141

136142
public function include() : bool
137143
{
138-
if ($this->discard) { // Explicit Discard (not from passed-in options)
144+
if ($this->isExplicitlyDiscarded()) { // Explicit Discard (not from passed-in options)
139145
if (!$this->ignoreExplicitDiscard) {
140146
return false;
141147
}
@@ -148,6 +154,32 @@ public function include() : bool
148154
return true;
149155
}
150156

157+
/**
158+
* Resolve $discard whether it is a boolean or a callable checked against the model.
159+
*/
160+
public function isExplicitlyDiscarded(): bool
161+
{
162+
if (is_callable($this->discard)) {
163+
return (bool) ($this->discard)($this->model);
164+
}
165+
166+
return (bool) $this->discard;
167+
}
168+
169+
/**
170+
* Import-time check: should an existing target model be discarded (not overwritten)?
171+
*/
172+
public static function shouldDiscardExistingModel(?Model $model): bool
173+
{
174+
if (!$model || !$model->exists) {
175+
return false;
176+
}
177+
178+
$exporter = new static($model, new Manifest(), new Options([]), false);
179+
180+
return $exporter->isExplicitlyDiscarded();
181+
}
182+
151183
public function addDependent(string $type, Model|Psudomodel $dependentModel, string $exporterClass, $meta = null)
152184
{
153185
$uuid = $dependentModel->uuid;
@@ -304,7 +336,7 @@ public function toArray()
304336
'hidden' => $this->hidden,
305337
'mode' => $this->mode,
306338
'saveAssetsMode' => $this->saveAssetsMode,
307-
'explicit_discard' => $this->discard,
339+
'explicit_discard' => $this->isExplicitlyDiscarded(),
308340
'dependents' => array_map(fn ($d) => $d->toArray(), $this->dependents),
309341
'name' => $this->getName($this->model),
310342
'description' => $this->getDescription(),

‎ProcessMaker/ImportExport/Manifest.php‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,11 @@ public static function getModel($uuid, $assetInfo, $mode, $exporterClass, $isRoo
158158
$mode = 'discard';
159159
}
160160

161+
// Per-asset explicit discard (e.g. env vars with do_not_update on the target).
162+
if ($model && $exporterClass::shouldDiscardExistingModel($model)) {
163+
$mode = 'discard';
164+
}
165+
161166
if ($exporterClass::$forceUpdate) {
162167
$mode = 'update';
163168
}

‎ProcessMaker/Models/EnvironmentVariable.php‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
* @OA\Property(property="description", type="string"),
1818
* @OA\Property(property="value", type="string"),
1919
* @OA\Property(property="asset_type", type="string", nullable=true),
20+
* @OA\Property(property="do_not_update", type="boolean"),
2021
* ),
2122
* @OA\Schema(
2223
* schema="EnvironmentVariable",
@@ -41,6 +42,11 @@ class EnvironmentVariable extends ProcessMakerModel
4142
'description',
4243
'value',
4344
'asset_type',
45+
'do_not_update',
46+
];
47+
48+
protected $casts = [
49+
'do_not_update' => 'boolean',
4450
];
4551

4652
protected $hidden = [
@@ -102,6 +108,7 @@ public static function rules($existing = null)
102108
'string',
103109
Rule::in($allowedAssetTypes),
104110
],
111+
'do_not_update' => 'boolean',
105112
];
106113
}
107114

‎database/factories/ProcessMaker/Models/EnvironmentVariableFactory.php‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ public function definition()
1818
'name' => $this->faker->word(),
1919
'description' => $this->faker->sentence(),
2020
'value' => $this->faker->sentence(),
21+
'do_not_update' => false,
2122
];
2223
}
2324
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?php
2+
3+
use Illuminate\Database\Migrations\Migration;
4+
use Illuminate\Database\Schema\Blueprint;
5+
use Illuminate\Support\Facades\Schema;
6+
7+
return new class extends Migration
8+
{
9+
/**
10+
* Run the migrations.
11+
*/
12+
public function up(): void
13+
{
14+
Schema::table('environment_variables', function (Blueprint $table) {
15+
$table->boolean('do_not_update')->default(false)->after('asset_type');
16+
});
17+
}
18+
19+
/**
20+
* Reverse the migrations.
21+
*/
22+
public function down(): void
23+
{
24+
Schema::table('environment_variables', function (Blueprint $table) {
25+
$table->dropColumn('do_not_update');
26+
});
27+
}
28+
};

‎resources/js/processes/environment-variables/components/CreateEnvironmentVariableModal.vue‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,16 +41,18 @@
4141
:value.sync="value"
4242
:errors="errors"
4343
/>
44+
<do-not-update-switch v-model="doNotUpdate" />
4445
</modal>
4546
</div>
4647
</template>
4748

4849
<script>
4950
import { FormErrorsMixin, Modal, Required } from "SharedComponents";
5051
import AssetLinkFields from "./AssetLinkFields.vue";
52+
import DoNotUpdateSwitch from "./DoNotUpdateSwitch.vue";
5153
5254
export default {
53-
components: { Modal, Required, AssetLinkFields },
55+
components: { Modal, Required, AssetLinkFields, DoNotUpdateSwitch },
5456
mixins: [ FormErrorsMixin ],
5557
data: function() {
5658
return {
@@ -59,6 +61,7 @@
5961
description: '',
6062
value: '',
6163
assetType: null,
64+
doNotUpdate: false,
6265
disabled: false,
6366
}
6467
},
@@ -68,6 +71,7 @@
6871
this.description = '';
6972
this.value = '';
7073
this.assetType = null;
74+
this.doNotUpdate = false;
7175
this.errors = {};
7276
this.disabled = false;
7377
},
@@ -83,6 +87,7 @@
8387
description: this.description,
8488
value: this.value,
8589
asset_type: this.assetType,
90+
do_not_update: this.doNotUpdate,
8691
})
8792
.then(response => {
8893
ProcessMaker.alert(this.$t('The environment variable was created.'), 'success');
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<template>
2+
<div class="do-not-update-switch pt-3 mt-2 border-top">
3+
<div class="d-flex align-items-start">
4+
<b-form-checkbox
5+
class="mt-1"
6+
switch
7+
:checked="value"
8+
@input="$emit('input', $event)"
9+
/>
10+
<div class="ml-2">
11+
<div class="font-weight-bold">
12+
<i class="fas fa-lock text-primary mr-1" aria-hidden="true"></i>
13+
{{ $t("Do not overwrite this environment variable on import/DevLink") }}
14+
</div>
15+
<small class="form-text text-muted mb-0">
16+
{{ $t("When enabled, the value of this variable will not be overwritten during imports or DevLink synchronization, even if a variable with the same name exists in the source environment.") }}
17+
</small>
18+
</div>
19+
</div>
20+
</div>
21+
</template>
22+
23+
<script>
24+
export default {
25+
props: {
26+
value: {
27+
type: Boolean,
28+
default: false,
29+
},
30+
},
31+
};
32+
</script>

‎resources/js/processes/environment-variables/edit.js‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
import Vue from "vue";
22
import AssetLinkFields from "./components/AssetLinkFields.vue";
3+
import DoNotUpdateSwitch from "./components/DoNotUpdateSwitch.vue";
34

45
const initial = window.ProcessMaker.EnvironmentVariableEdit || {};
56

67
new Vue({
78
el: "#editEnvironmentVariable",
89
components: {
910
AssetLinkFields,
11+
DoNotUpdateSwitch,
1012
},
1113
data() {
1214
return {
@@ -16,6 +18,7 @@ new Vue({
1618
description: initial.description,
1719
value: initial.value || null,
1820
asset_type: initial.asset_type || null,
21+
do_not_update: !!initial.do_not_update,
1922
},
2023
errors: {
2124
name: null,
@@ -44,6 +47,7 @@ new Vue({
4447
description: this.formData.description,
4548
asset_type: this.formData.asset_type,
4649
value: this.formData.value,
50+
do_not_update: this.formData.do_not_update,
4751
};
4852
ProcessMaker.apiClient.put(`environment_variables/${this.formData.id}`, payload)
4953
.then(() => {

0 commit comments

Comments
 (0)