Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 33 additions & 34 deletions ProcessMaker/Services/ConditionalRedirectService.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,24 @@

namespace ProcessMaker\Services;

use Illuminate\Support\Facades\Log;
use InvalidArgumentException;
use ProcessMaker\Contracts\ConditionalRedirectServiceInterface;
use ProcessMaker\Managers\DataManager;
use ProcessMaker\Models\Comment;
use ProcessMaker\Models\FormalExpression;
use ProcessMaker\Models\ProcessRequest;
use ProcessMaker\Models\ProcessRequestToken;

/**
* ConditionalRedirectService
*
*
* This service handles the evaluation of conditional redirects in ProcessMaker workflows.
* It processes a set of conditions and returns the first condition that evaluates to true,
* along with its associated redirect configuration.
*
*
* The service uses FEEL (Friendly Enough Expression Language) expressions to evaluate
* conditions against process data, allowing for dynamic routing based on runtime data.
*
* @package ProcessMaker\Services
*
* @since 4.0.0
*/
class ConditionalRedirectService implements ConditionalRedirectServiceInterface
Expand All @@ -29,7 +28,7 @@ class ConditionalRedirectService implements ConditionalRedirectServiceInterface
* @var FormalExpression
*/
private FormalExpression $feel;

/**
* @var DataManager
*/
Expand All @@ -39,7 +38,7 @@ class ConditionalRedirectService implements ConditionalRedirectServiceInterface

/**
* Constructor
*
*
* Initializes the service with required dependencies for expression evaluation
* and data management.
*/
Expand All @@ -51,11 +50,11 @@ public function __construct()

/**
* Process a set of conditional redirects and return the first condition that evaluates to true
*
*
* This method iterates through an array of conditional redirect configurations,
* evaluating each condition using FEEL expressions against the provided data.
* Returns the first condition that evaluates to true, or null if no conditions match.
*
*
* @param array $conditionalRedirect Array of conditional redirect configurations
* Each item must contain a 'condition' key with a FEEL expression
* Example: [
Expand All @@ -73,15 +72,15 @@ public function __construct()
* @param array $data Process data to evaluate conditions against
* Contains variables from the process instance
* Example: ['amount' => 1500, 'status' => 'urgent', 'user' => 'john']
*
*
* @return array|null The first matching conditional redirect configuration, or null if none match
*
*
* @throws InvalidArgumentException When a condition item is missing the required 'condition' key
*
*
* @example
* ```php
* $service = new ConditionalRedirectService();
*
*
* $conditionalRedirect = [
* [
* 'condition' => 'amount > 1000',
Expand All @@ -94,9 +93,9 @@ public function __construct()
* 'value' => null
* ]
* ];
*
*
* $data = ['amount' => 1500, 'status' => 'pending'];
*
*
* $result = $service->resolve($conditionalRedirect, $data);
* // Returns: ['condition' => 'amount > 1000', 'type' => 'externalURL', 'value' => 'https://example.com/approval']
* ```
Expand Down Expand Up @@ -128,13 +127,13 @@ public function resolve(array $conditionalRedirect, array $data): ?array

/**
* Process conditional redirects for a specific process request token
*
*
* This method is a convenience wrapper that automatically retrieves process data
* from a ProcessRequestToken and evaluates conditional redirects against that data.
* It's commonly used when you have a token and want to determine the appropriate
* redirect based on the current process state and data, it also considers
* multi-instance tasks.
*
*
* @param array $conditionalRedirect Array of conditional redirect configurations
* Each item must contain a 'condition' key with a FEEL expression
* Example: [
Expand All @@ -151,16 +150,16 @@ public function resolve(array $conditionalRedirect, array $data): ?array
* ]
* @param ProcessRequestToken $token The process request token to evaluate conditions against
* The token contains the process instance data and context
*
*
* @return array|null The first matching conditional redirect configuration, or null if none match
*
*
* @throws InvalidArgumentException When a condition item is missing the required 'condition' key
*
*
* @example
* ```php
* $service = new ConditionalRedirectService();
* $token = ProcessRequestToken::find(123);
*
*
* $conditionalRedirect = [
* [
* 'condition' => 'taskStatus = "completed"',
Expand All @@ -173,11 +172,11 @@ public function resolve(array $conditionalRedirect, array $data): ?array
* 'value' => null
* ]
* ];
*
*
* $result = $service->resolveForToken($conditionalRedirect, $token);
* // Returns the appropriate redirect configuration based on the token's data
* ```
*
*
* @see resolve() For detailed parameter documentation
*/
public function resolveForToken(array $conditionalRedirect, ProcessRequestToken $token): ?array
Expand All @@ -187,9 +186,10 @@ public function resolveForToken(array $conditionalRedirect, ProcessRequestToken
if ($this->errors) {
$case_number = $this->getCaseNumber($token);
foreach ($this->errors as $error) {
$this->addLogComment($token, $error, $case_number);
$this->logError($token, $error, $case_number);
}
}

return $result;
}

Expand All @@ -206,16 +206,15 @@ private function getCaseNumber(ProcessRequestToken $token): ?int
return $case_number;
}

private function addLogComment(ProcessRequestToken $token, string $error, string $case_number)
/**
* Log an error when evaluating conditional redirects
*
* @param ProcessRequestToken $token
* @param string $error
* @param string $case_number
*/
private function logError(ProcessRequestToken $token, string $error, int $case_number)
{
Comment::create([
'body' => $error,
'user_id' => null,
'subject' => $error,
'type' => 'LOG',
'case_number' => $case_number,
'commentable_type' => ProcessRequest::class,
'commentable_id' => $token->process_request_id,
]);
Log::error('Conditional Redirect: ', ['error' => $error, 'case_number' => $case_number, 'token' => $token->id]);
}
}
Loading