Skip to content

Commit c05ee9b

Browse files
committed
Merge remote-tracking branch 'origin/feature/FOUR-11378' into FOUR-11416
2 parents 19c582b + a55891d commit c05ee9b

107 files changed

Lines changed: 4697 additions & 849 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.

‎ProcessMaker/Ai/Handlers/LanguageTranslationHandler.php‎

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ public function __construct()
1818
{
1919
parent::__construct();
2020
$this->config = [
21-
'model' => 'text-davinci-003',
22-
'max_tokens' => 2200,
21+
'model' => 'gpt-3.5-turbo-16k',
22+
'max_tokens' => 6000,
2323
'temperature' => 0,
2424
'top_p' => 1,
2525
'n' => 1,
@@ -57,6 +57,10 @@ public function generatePrompt(String $type = null, String $json_list) : Object
5757
$prompt = $this->replaceLanguage($prompt, $this->targetLanguage['humanLanguage']);
5858
$prompt = $this->replaceStopSequence($prompt);
5959
$this->config['prompt'] = $prompt;
60+
$this->config['messages'] = [[
61+
'role' => 'user',
62+
'content' => $prompt,
63+
]];
6064

6165
return $this;
6266
}
@@ -66,17 +70,25 @@ public function execute()
6670
$listCharCount = strlen($this->json_list);
6771
$totalChars = $listCharCount * 3;
6872
$currentChunkCount = 0;
73+
$config = $this->getConfig();
74+
unset($config['prompt']);
6975

7076
$client = app(Client::class);
7177
$stream = $client
72-
->completions()
73-
->createStreamed(array_merge($this->getConfig()));
78+
->chat()
79+
->createStreamed(array_merge($config));
7480

7581
$fullResponse = '';
7682
foreach ($stream as $response) {
77-
$currentChunkCount += strlen($response->choices[0]->text);
78-
self::sendResponse($response->choices[0]->text, $currentChunkCount, $totalChars);
79-
$fullResponse .= $response->choices[0]->text;
83+
if (array_key_exists('content', $response->choices[0]->toArray()['delta'])) {
84+
$currentChunkCount += strlen($response->choices[0]->toArray()['delta']['content']);
85+
self::sendResponse(
86+
$response->choices[0]->toArray()['delta']['content'],
87+
$currentChunkCount,
88+
$totalChars
89+
);
90+
$fullResponse .= $response->choices[0]->toArray()['delta']['content'];
91+
}
8092
}
8193

8294
return $this->formatResponse($fullResponse);
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
<?php
2+
3+
namespace ProcessMaker\Console\Commands;
4+
5+
use CodeGreenCreative\SamlIdp\Console\CreateCertificate;
6+
7+
class CreateSamlCertificate extends CreateCertificate
8+
{
9+
/**
10+
* The name and signature of the console command.
11+
*
12+
* @var string
13+
*/
14+
protected $signature = 'samlidp:cert
15+
{--days=7300 : Number of days to add from today as the expiration date}
16+
{--keyname=key.pem : Full name of the certificate key file}
17+
{--certname=cert.pem : Full name to the certificate file}
18+
{--subject= : Set subject of request or cert '
19+
. '(e.g. /C=US/ST=New York/L=New York City/O=Example Inc/CN=example.com)}';
20+
21+
/**
22+
* The console command description.
23+
*
24+
* @var string
25+
*/
26+
protected $description = 'Create new certificate and private key for your IdP';
27+
28+
/**
29+
* Execute the console command.
30+
*/
31+
public function handle()
32+
{
33+
$storagePath = storage_path('samlidp');
34+
$days = $this->option('days');
35+
$keyName = $this->option('keyname');
36+
$certName = $this->option('certname');
37+
$subject = $this->option('subject');
38+
39+
// Create storage/samlidp directory
40+
if (!file_exists($storagePath)) {
41+
mkdir($storagePath, 0755, true);
42+
}
43+
44+
$key = sprintf('%s/%s', $storagePath, $keyName);
45+
$cert = sprintf('%s/%s', $storagePath, $certName);
46+
$question = 'The name chosen for the PEM files already exist. Would you like to overwrite existing PEM files?';
47+
48+
if ((!file_exists($key) && !file_exists($cert)) || $this->confirm($question)) {
49+
$command = 'openssl req -x509 -sha256 -nodes -days %s -newkey rsa:2048 -keyout %s -out %s';
50+
$args = [$days, $key, $cert];
51+
52+
if (!is_null($subject)) {
53+
$command .= ' -subj "%s"';
54+
$args[] = $subject;
55+
}
56+
57+
exec(vsprintf($command, $args));
58+
}
59+
}
60+
}

‎ProcessMaker/Exception/PackageNotInstalledException.php‎

Lines changed: 0 additions & 9 deletions
This file was deleted.

‎ProcessMaker/Filters/Filter.php‎

Lines changed: 225 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,225 @@
1+
<?php
2+
3+
namespace ProcessMaker\Filters;
4+
5+
use Illuminate\Database\Eloquent\Builder;
6+
use Illuminate\Support\Arr;
7+
use ProcessMaker\Models\ProcessRequestToken;
8+
use ProcessMaker\Models\User;
9+
10+
class Filter
11+
{
12+
const TYPE_PARTICIPANTS = 'Participants';
13+
14+
const TYPE_STATUS = 'Status';
15+
16+
const TYPE_FIELD = 'Field';
17+
18+
const TYPE_PROCESS = 'Process';
19+
20+
public string|null $subjectValue;
21+
22+
public string $subjectType;
23+
24+
public string $operator;
25+
26+
public $value;
27+
28+
public array $or;
29+
30+
public static function filter(Builder $query, string $filterDefinitions)
31+
{
32+
$filterDefinitions = json_decode($filterDefinitions, true);
33+
$query->where(function ($query) use ($filterDefinitions) {
34+
foreach ($filterDefinitions as $filter) {
35+
(new self($filter))->addToQuery($query);
36+
}
37+
});
38+
}
39+
40+
public function __construct($definition)
41+
{
42+
$this->subjectType = $definition['subject']['type'];
43+
$this->subjectValue = Arr::get($definition, 'subject.value');
44+
$this->operator = $definition['operator'];
45+
$this->value = $definition['value'];
46+
$this->or = Arr::get($definition, 'or', []);
47+
}
48+
49+
public function addToQuery(Builder $query)
50+
{
51+
if (!empty($this->or)) {
52+
$query->where(function ($query) {
53+
$this->apply($query);
54+
});
55+
} else {
56+
$this->apply($query);
57+
}
58+
}
59+
60+
private function apply($query)
61+
{
62+
if ($valueAliasMethod = $this->valueAliasMethod()) {
63+
$this->valueAliasAdapter($valueAliasMethod, $query);
64+
} elseif ($this->subjectType === self::TYPE_PROCESS) {
65+
$this->filterByProcessId($query);
66+
} else {
67+
$this->applyQueryBuilderMethod($query);
68+
}
69+
70+
if (!empty($this->or)) {
71+
$query->orWhere(function ($orQuery) {
72+
foreach ($this->or as $or) {
73+
(new self($or))->addToQuery($orQuery);
74+
}
75+
});
76+
}
77+
}
78+
79+
private function applyQueryBuilderMethod($query)
80+
{
81+
$method = $this->method();
82+
83+
if (in_array($method, ['whereIn', 'whereBetween', 'whereJsonContains'])) {
84+
$query->$method(
85+
$this->subject(),
86+
$this->value(),
87+
);
88+
} else {
89+
$query->$method(
90+
$this->subject(),
91+
$this->operator(),
92+
$this->value(),
93+
);
94+
}
95+
}
96+
97+
private function operator()
98+
{
99+
if ($this->operator === 'contains' || $this->operator === 'starts_with') {
100+
return 'like';
101+
}
102+
103+
return $this->operator;
104+
}
105+
106+
private function method()
107+
{
108+
switch($this->operator) {
109+
case 'in':
110+
$method = 'whereIn';
111+
if ($this->isJsonData()) {
112+
$method = 'whereJsonContains';
113+
}
114+
break;
115+
case 'between':
116+
$method = 'whereBetween';
117+
break;
118+
default:
119+
$method = 'where';
120+
}
121+
122+
return $method;
123+
}
124+
125+
private function isJsonData()
126+
{
127+
return $this->subjectType === self::TYPE_FIELD && str_starts_with($this->subjectValue, 'data.');
128+
}
129+
130+
private function subject()
131+
{
132+
if ($this->isJsonData()) {
133+
return str_replace('.', '->', $this->subjectValue);
134+
}
135+
136+
if ($this->subjectType === self::TYPE_PARTICIPANTS) {
137+
return 'user_id';
138+
}
139+
140+
if ($this->subjectType === self::TYPE_PROCESS) {
141+
return 'process_id';
142+
}
143+
144+
return $this->subjectValue;
145+
}
146+
147+
private function value()
148+
{
149+
if ($this->operator === 'contains') {
150+
return '%' . $this->value . '%';
151+
}
152+
153+
if ($this->operator === 'starts_with') {
154+
return $this->value . '%';
155+
}
156+
157+
return $this->value;
158+
}
159+
160+
/**
161+
* Forward Status and Participant subjects to PMQL methods on the models.
162+
*
163+
* For now, we only need Participants and Status because Request and Requester
164+
* are columns on the tables (process_request_id and user_id).
165+
*/
166+
private function valueAliasMethod()
167+
{
168+
$method = null;
169+
170+
switch ($this->subjectType) {
171+
case self::TYPE_PARTICIPANTS:
172+
$method = 'valueAliasParticipant';
173+
break;
174+
case self::TYPE_STATUS:
175+
$method = 'valueAliasStatus';
176+
break;
177+
}
178+
179+
return $method;
180+
}
181+
182+
private function valueAliasAdapter(string $method, Builder $query)
183+
{
184+
$operator = $this->operator();
185+
if ($operator === 'in') {
186+
$operator = '=';
187+
}
188+
$values = (array) $this->value();
189+
190+
$expression = (object) ['operator' => $operator];
191+
192+
$model = $query->getModel();
193+
194+
if ($method === 'valueAliasParticipant') {
195+
$values = $this->convertUserIdsToUsernames($values);
196+
}
197+
198+
foreach ($values as $i => $value) {
199+
if ($i === 0) {
200+
$query->where($model->$method($value, $expression));
201+
} else {
202+
$query->orWhere($model->$method($value, $expression));
203+
}
204+
}
205+
}
206+
207+
private function convertUserIdsToUsernames($values)
208+
{
209+
return array_map(function ($value) {
210+
return User::find($value)?->username;
211+
}, $values);
212+
}
213+
214+
private function filterByProcessId(Builder $query)
215+
{
216+
if ($query->getModel() instanceof ProcessRequestToken) {
217+
$query->whereIn('process_request_id', function ($query) {
218+
$query->select('id')->from('process_requests')
219+
->whereIn('process_id', (array) $this->value());
220+
});
221+
} else {
222+
$this->applyQueryBuilderMethod($query);
223+
}
224+
}
225+
}

0 commit comments

Comments
 (0)