diff --git a/lib/equal/orm/Entity.class.php b/lib/equal/orm/Entity.class.php
index 836c89d8..6b9b50df 100644
--- a/lib/equal/orm/Entity.class.php
+++ b/lib/equal/orm/Entity.class.php
@@ -6,7 +6,10 @@
Licensed under GNU LGPL 3 license
*/
namespace equal\orm;
-
+use Exception;
+use ReflectionClass;
+use ReflectionMethod;
+use ReflectionException;
class Entity {
/**
* @var string
@@ -103,4 +106,135 @@ public function getFullFilePath(): string {
}
return $filepath;
}
+
+
+ public function updateMethod(string $methodName, array $newData) {
+ try {
+ $class = new ReflectionClass($this->full_name);
+
+ if (!$class->hasMethod($methodName)) {
+ throw new Exception("missing_method", QN_ERROR_UNKNOWN);
+ }
+
+ $method_code = " public static function $methodName() {\n" .
+ " return " . (empty($newData) ? '[]' : $this->arrayExport($newData, 4, 2, true)) . ";\n" .
+ " }";
+
+ $this->updateMethodCode($class, $methodName, $method_code);
+ } catch (ReflectionException $e) {
+ throw new Exception("reflection_error: " . $e->getMessage(), QN_ERROR_UNKNOWN);
+ }
+ }
+
+ public function updateMethodLine(string $methodName, string $newKey, $defaultValue = []) {
+ try {
+ $class = new ReflectionClass($this->full_name);
+
+ if (!$class->hasMethod($methodName)) {
+ throw new Exception("missing_method", QN_ERROR_UNKNOWN);
+ }
+
+ $oldData = call_user_func([$this->full_name, $methodName]);
+ if (!is_array($oldData)) {
+ $oldData = [];
+ }
+
+ if (!array_key_exists($newKey, $oldData)) {
+ $oldData[$newKey] = $defaultValue;
+ }
+
+ $method_code = " public static function $methodName() {\n" .
+ " return " . $this->arrayExport($oldData, 4, 2, true) . ";\n" .
+ " }";
+
+ $this->updateMethodCode($class, $methodName, $method_code);
+ } catch (ReflectionException $e) {
+ throw new Exception("reflection_error: " . $e->getMessage(), QN_ERROR_UNKNOWN);
+ }
+ }
+
+
+ private function updateMethodCode(ReflectionClass $class, string $methodName, string $newCode) {
+ try {
+ $file = $class->getFileName();
+ if (!$file || !file_exists($file)) {
+ throw new Exception("File not found: $file", QN_ERROR_UNKNOWN);
+ }
+
+ $code = file_get_contents($file);
+ if ($code === false) {
+ throw new Exception("Failed to read file: $file", QN_ERROR_UNKNOWN);
+ }
+
+ $lines = explode("\n", $code);
+
+ try {
+ $method = new ReflectionMethod($class->getName(), $methodName);
+ } catch (ReflectionException $e) {
+ throw new Exception("Method $methodName not found in class " . $class->getName(), QN_ERROR_UNKNOWN);
+ }
+
+ $start_index = $method->getStartLine() - 1;
+ $end_index = $method->getEndLine() - 1;
+
+ if ($start_index < 0 || $end_index < 0 || $end_index < $start_index) {
+ throw new Exception("Invalid method boundaries for $methodName", QN_ERROR_UNKNOWN);
+ }
+
+ $result = '';
+ foreach ($lines as $index => $line) {
+ if ($index < $start_index) {
+ $result .= $line . "\n";
+ } elseif ($index == $start_index) {
+ $result .= $newCode . "\n";
+ } elseif ($index > $end_index) {
+ $result .= $line . "\n";
+ }
+ }
+
+ if (file_put_contents($file, rtrim($result) . "\n") === false) {
+ throw new Exception("Failed to write to file: $file", QN_ERROR_UNKNOWN);
+ }
+ } catch (Exception $e) {
+ error_log("Error in updateMethodCode: " . $e->getMessage());
+ throw $e;
+ }
+ }
+
+
+
+
+ private function arrayExport($array, $indent_spaces = 4, $pad_indents = 0, $ignore_first_indent = false) {
+ if (!is_array($array)) {
+ return '';
+ }
+
+ $export = var_export($array, true);
+
+ $patterns = [
+ "/array \(/" => '[',
+ "/^([ ]*)\)(,?)$/m" => '$1]$2',
+ "/=>[ ]?\n[ ]+\[/" => '=> [',
+ "/([ ]*)(\'[^\']+\') => ([\[\'])/" => '$1$2 => $3',
+ "/[0-9]+ => /" => ''
+ ];
+
+ $result = preg_replace(array_keys($patterns), array_values($patterns), $export);
+ if (empty($result)) {
+ return '';
+ }
+
+ $lines = explode("\n", $result);
+ foreach ($lines as $index => $line) {
+ if (!$ignore_first_indent || $index > 0) {
+ $code = ltrim($line);
+ $indents = (strlen($line) - strlen($code)) / 2;
+ $lines[$index] = str_pad('', $pad_indents * $indent_spaces, ' ') .
+ str_pad('', $indents * $indent_spaces, ' ') .
+ $code;
+ }
+ }
+
+ return implode("\n", $lines);
+ }
}
\ No newline at end of file
diff --git a/packages/core/actions/config/create-actions.php b/packages/core/actions/config/create-actions.php
new file mode 100644
index 00000000..ac78c398
--- /dev/null
+++ b/packages/core/actions/config/create-actions.php
@@ -0,0 +1,73 @@
+
+ Some Rights Reserved, eQual framework, 2010-2024
+ Original author(s): Cédric FRANCOYS
+ Licensed under GNU LGPL 3 license
+*/
+
+list($params, $providers) = eQual::announce([
+ 'description' => "Add an empty actions to the given class by creating a `getActions()` method (if not defined yet).",
+ 'params' => [
+ 'entity' => [
+ 'description' => 'Full name (including namespace) of the class to look into (e.g. \'core\\User\').',
+ 'type' => 'string',
+ 'required' => true
+ ]
+ ],
+ 'response' => [
+ 'content-type' => 'text',
+ 'charset' => 'utf-8',
+ 'accept-origin' => '*'
+ ],
+ 'access' => [
+ 'visibility' => 'protected',
+ 'groups' => ['admins']
+ ],
+ 'providers' => ['context', 'orm']
+]);
+
+/**
+ * @var \equal\php\Context $context
+ * @var \equal\orm\ObjectManager $orm
+ */
+list($context, $orm) = [ $providers['context'], $providers['orm'] ];
+
+// force class autoload
+$entity = $orm->getModel($params['entity']);
+if(!$entity) {
+ throw new Exception("unknown_entity", QN_ERROR_INVALID_PARAM);
+}
+
+$class = new ReflectionClass($entity::getType());
+if($class->getMethod('getActions')->class == $entity::getType()) {
+ throw new Exception("duplicate_method", QN_ERROR_INVALID_PARAM);
+}
+
+$file = $class->getFileName();
+$code = file_get_contents($file);
+
+// generate replacement code for the getActions method
+$actions_code = ''.
+ " public static function getActions() {\n".
+ " return [];\n".
+ " }\n".
+ "\n";
+
+// find the closing curly-bracket of the class
+$pos = strrpos($code, '}');
+
+if($pos === false) {
+ throw new Exception('malformed_file', QN_ERROR_UNKNOWN);
+}
+
+$result = substr_replace($code, $actions_code, $pos, 0);
+
+// write back the code to the source file
+if(file_put_contents($file, rtrim($result)."\n") === false) {
+ throw new Exception('io_error', QN_ERROR_UNKNOWN);
+}
+
+$context->httpResponse()
+ ->status(204)
+ ->send();
diff --git a/packages/core/actions/config/create-policies.php b/packages/core/actions/config/create-policies.php
new file mode 100644
index 00000000..b441b54a
--- /dev/null
+++ b/packages/core/actions/config/create-policies.php
@@ -0,0 +1,73 @@
+
+ Some Rights Reserved, eQual framework, 2010-2024
+ Original author(s): Cédric FRANCOYS
+ Licensed under GNU LGPL 3 license
+*/
+
+list($params, $providers) = eQual::announce([
+ 'description' => "Add an empty policies to the given class by creating a `getPolicies()` method (if not defined yet).",
+ 'params' => [
+ 'entity' => [
+ 'description' => 'Full name (including namespace) of the class to look into (e.g. \'core\\User\').',
+ 'type' => 'string',
+ 'required' => true
+ ]
+ ],
+ 'response' => [
+ 'content-type' => 'text',
+ 'charset' => 'utf-8',
+ 'accept-origin' => '*'
+ ],
+ 'access' => [
+ 'visibility' => 'protected',
+ 'groups' => ['admins']
+ ],
+ 'providers' => ['context', 'orm']
+]);
+
+/**
+ * @var \equal\php\Context $context
+ * @var \equal\orm\ObjectManager $orm
+ */
+list($context, $orm) = [ $providers['context'], $providers['orm'] ];
+
+// force class autoload
+$entity = $orm->getModel($params['entity']);
+if(!$entity) {
+ throw new Exception("unknown_entity", QN_ERROR_INVALID_PARAM);
+}
+
+$class = new ReflectionClass($entity::getType());
+if($class->getMethod('getPolicies')->class == $entity::getType()) {
+ throw new Exception("duplicate_method", QN_ERROR_INVALID_PARAM);
+}
+
+$file = $class->getFileName();
+$code = file_get_contents($file);
+
+// generate replacement code for the getPolicies method
+$policies_code = ''.
+ " public static function getPolicies() {\n".
+ " return [];\n".
+ " }\n".
+ "\n";
+
+// find the closing curly-bracket of the class
+$pos = strrpos($code, '}');
+
+if($pos === false) {
+ throw new Exception('malformed_file', QN_ERROR_UNKNOWN);
+}
+
+$result = substr_replace($code, $policies_code, $pos, 0);
+
+// write back the code to the source file
+if(file_put_contents($file, rtrim($result)."\n") === false) {
+ throw new Exception('io_error', QN_ERROR_UNKNOWN);
+}
+
+$context->httpResponse()
+ ->status(204)
+ ->send();
diff --git a/packages/core/actions/config/create-policy.php b/packages/core/actions/config/create-policy.php
new file mode 100644
index 00000000..ef75bdd9
--- /dev/null
+++ b/packages/core/actions/config/create-policy.php
@@ -0,0 +1,58 @@
+ "create a new policy",
+ 'help' => "This controller relies on the PHP binary. Ensure the PHP binary is present in the PATH.",
+ 'params' => [
+ 'entity' => [
+ 'description' => 'Name of the entity (class).',
+ 'type' => 'string',
+ 'required' => true
+ ],
+ 'name' => [
+ 'description' => 'Name of the policy',
+ 'type' => 'string',
+ 'required' => true
+ ]
+ ],
+ 'response' => [
+ 'content-type' => 'text/plain',
+ 'charset' => 'UTF-8',
+ 'accept-origin' => '*'
+ ],
+ 'providers' => ['context', 'orm']
+]);
+
+/**
+ * @var \equal\php\Context $context
+ * @var \equal\orm\ObjectManager $orm
+ */
+
+list($context, $orm) = [$providers['context'], $providers['orm']];
+
+
+$entity = new Entity($params['entity']);
+$new_policy = $params['name'];
+// force class autoload
+$entityInstance = $orm->getModel($entity->getFullName());
+if(!$entityInstance) {
+ throw new Exception("unknown_entity", QN_ERROR_INVALID_PARAM);
+}
+
+$method_name = 'getPolicies' ;
+$structure= [
+'description' =>'',
+'function' => ''
+];
+$class = new ReflectionClass($entityInstance::getType());
+if(!($class->getMethod($method_name)->class == $entityInstance::getType())) {
+ equal::run('do','core_config_create-policies',['entity' => $entity->getFullName()], true);
+}
+
+$entity->updateMethodLine($method_name,$new_policy, $structure);
+
+
+$context->httpResponse()
+ ->status(204)
+ ->send();
diff --git a/packages/core/actions/config/create-roles.php b/packages/core/actions/config/create-roles.php
new file mode 100644
index 00000000..d1a3c326
--- /dev/null
+++ b/packages/core/actions/config/create-roles.php
@@ -0,0 +1,73 @@
+
+ Some Rights Reserved, eQual framework, 2010-2024
+ Original author(s): Cédric FRANCOYS
+ Licensed under GNU LGPL 3 license
+*/
+
+list($params, $providers) = eQual::announce([
+ 'description' => "Add an empty roles to the given class by creating a `getRoles()` method (if not defined yet).",
+ 'params' => [
+ 'entity' => [
+ 'description' => 'Full name (including namespace) of the class to look into (e.g. \'core\\User\').',
+ 'type' => 'string',
+ 'required' => true
+ ]
+ ],
+ 'response' => [
+ 'content-type' => 'text',
+ 'charset' => 'utf-8',
+ 'accept-origin' => '*'
+ ],
+ 'access' => [
+ 'visibility' => 'protected',
+ 'groups' => ['admins']
+ ],
+ 'providers' => ['context', 'orm']
+]);
+
+/**
+ * @var \equal\php\Context $context
+ * @var \equal\orm\ObjectManager $orm
+ */
+list($context, $orm) = [ $providers['context'], $providers['orm'] ];
+
+// force class autoload
+$entity = $orm->getModel($params['entity']);
+if(!$entity) {
+ throw new Exception("unknown_entity", QN_ERROR_INVALID_PARAM);
+}
+
+$class = new ReflectionClass($entity::getType());
+if($class->getMethod('getRoles')->class == $entity::getType()) {
+ throw new Exception("duplicate_method", QN_ERROR_INVALID_PARAM);
+}
+
+$file = $class->getFileName();
+$code = file_get_contents($file);
+
+// generate replacement code for the getRoles method
+$actions_code = ''.
+ " public static function getRoles() {\n".
+ " return [];\n".
+ " }\n".
+ "\n";
+
+// find the closing curly-bracket of the class
+$pos = strrpos($code, '}');
+
+if($pos === false) {
+ throw new Exception('malformed_file', QN_ERROR_UNKNOWN);
+}
+
+$result = substr_replace($code, $actions_code, $pos, 0);
+
+// write back the code to the source file
+if(file_put_contents($file, rtrim($result)."\n") === false) {
+ throw new Exception('io_error', QN_ERROR_UNKNOWN);
+}
+
+$context->httpResponse()
+ ->status(204)
+ ->send();
diff --git a/packages/core/actions/config/update-actions.php b/packages/core/actions/config/update-actions.php
new file mode 100644
index 00000000..29e58cab
--- /dev/null
+++ b/packages/core/actions/config/update-actions.php
@@ -0,0 +1,52 @@
+ "Update the getActions() return function of an entity",
+ 'help' => "This controller relies on the PHP binary. Ensure the PHP binary is present in the PATH.",
+ 'params' => [
+ 'entity' => [
+ 'description' => 'Name of the entity (class).',
+ 'type' => 'string',
+ 'required' => true
+ ],
+ 'payload' => [
+ 'description' => 'Actions definition.',
+ 'type' => 'array',
+ 'required' => true
+ ]
+ ],
+ 'response' => [
+ 'content-type' => 'text/plain',
+ 'charset' => 'UTF-8',
+ 'accept-origin' => '*'
+ ],
+ 'providers' => ['context', 'orm']
+]);
+
+/**
+ * @var \equal\php\Context $context
+ * @var \equal\orm\ObjectManager $orm
+ */
+
+list($context, $orm) = [$providers['context'], $providers['orm']];
+
+$entity = new Entity($params['entity']);
+
+// force class autoload
+$entityInstance = $orm->getModel($params['entity']);
+if(!$entityInstance) {
+ throw new Exception("unknown_entity", QN_ERROR_INVALID_PARAM);
+}
+
+$method_name = 'getActions' ;
+$class = new ReflectionClass($entityInstance::getType());
+if(!($class->getMethod($method_name)->class == $entityInstance::getType())) {
+ equal::run('do','core_config_create-roles',['entity' => $entity->getFullName()], true);
+}
+
+$entity->updateMethod($method_name,$params['payload']);
+
+$context->httpResponse()
+ ->status(204)
+ ->send();
\ No newline at end of file
diff --git a/packages/core/actions/config/update-policies.php b/packages/core/actions/config/update-policies.php
new file mode 100644
index 00000000..76822c37
--- /dev/null
+++ b/packages/core/actions/config/update-policies.php
@@ -0,0 +1,54 @@
+ "Update the getPolicies() return function of an entity",
+ 'help' => "This controller relies on the PHP binary. Ensure the PHP binary is present in the PATH.",
+ 'params' => [
+ 'entity' => [
+ 'description' => 'Name of the entity (class).',
+ 'type' => 'string',
+ 'required' => true
+ ],
+ 'payload' => [
+ 'description' => 'Actions definition.',
+ 'type' => 'array',
+ 'required' => true
+ ]
+ ],
+ 'response' => [
+ 'content-type' => 'text/plain',
+ 'charset' => 'UTF-8',
+ 'accept-origin' => '*'
+ ],
+ 'providers' => ['context', 'orm']
+]);
+
+/**
+ * @var \equal\php\Context $context
+ * @var \equal\orm\ObjectManager $orm
+ */
+
+list($context, $orm) = [$providers['context'], $providers['orm']];
+
+$entity = new Entity($params['entity']);
+
+// force class autoload
+$entityInstance = $orm->getModel($params['entity']);
+if(!$entityInstance) {
+ throw new Exception("unknown_entity", QN_ERROR_INVALID_PARAM);
+}
+
+$method_name = 'getPolicies' ;
+$class = new ReflectionClass($entityInstance::getType());
+if(!($class->getMethod($method_name)->class == $entityInstance::getType())) {
+ equal::run('do','core_config_create-policies',['entity' => $entity->getFullName()], true);
+}
+
+$entity->updateMethod($method_name,$params['payload']);
+
+$context->httpResponse()
+ ->status(204)
+ ->send();
+
diff --git a/packages/core/actions/config/update-roles.php b/packages/core/actions/config/update-roles.php
new file mode 100644
index 00000000..679da266
--- /dev/null
+++ b/packages/core/actions/config/update-roles.php
@@ -0,0 +1,55 @@
+ "Update the getRoles() return function of an entity",
+ 'help' => "This controller relies on the PHP binary. Ensure the PHP binary is present in the PATH.",
+ 'params' => [
+ 'entity' => [
+ 'description' => 'Name of the entity (class).',
+ 'type' => 'string',
+ 'required' => true
+ ],
+ 'payload' => [
+ 'description' => 'Actions definition.',
+ 'type' => 'array',
+ 'required' => false
+ ]
+ ],
+ 'response' => [
+ 'content-type' => 'text/plain',
+ 'charset' => 'UTF-8',
+ 'accept-origin' => '*'
+ ],
+ 'providers' => ['context', 'orm']
+]);
+
+/**
+ * @var \equal\php\Context $context
+ * @var \equal\orm\ObjectManager $orm
+ */
+
+list($context, $orm) = [$providers['context'], $providers['orm']];
+
+
+$entity = new Entity($params['entity']);
+
+// force class autoload
+$entityInstance = $orm->getModel($params['entity']);
+if(!$entityInstance) {
+ throw new Exception("unknown_entity", QN_ERROR_INVALID_PARAM);
+}
+
+$method_name = 'getRoles' ;
+$class = new ReflectionClass($entityInstance::getType());
+if(!($class->getMethod($method_name)->class == $entityInstance::getType())) {
+ equal::run('do','core_config_create-roles',['entity' => $entity->getFullName()], true);
+}
+
+
+$entity->updateMethod($method_name,$params['payload']);
+
+$context->httpResponse()
+ ->status(204)
+ ->send();
+
diff --git a/packages/core/data/model/pipeline-load.php b/packages/core/data/model/pipeline-load.php
new file mode 100644
index 00000000..9e9c6108
--- /dev/null
+++ b/packages/core/data/model/pipeline-load.php
@@ -0,0 +1,126 @@
+ "Load a full pipeline with its nodes, metadata, links and parameters.",
+ 'params' => [
+ 'name' => [
+ 'description' => "Pipeline name",
+ 'type' => 'string',
+ 'required' => true
+ ]
+ ],
+ 'response' => [
+ 'content-type' => 'application/json',
+ 'charset' => 'utf-8',
+ 'accept-origin' => '*'
+ ],
+ 'providers' => ['context']
+]);
+
+/** @var Context $context */
+$context = $providers['context'];
+
+// Step 1: Get pipeline by name
+$pipelineList = \eQual::run('get', 'model_collect', [
+ 'entity' => 'core\\pipeline\\Pipeline',
+ 'domain' => [['name', '=', $params['name']]],
+ 'fields' => ['id', 'name', 'nodes_ids'],
+ 'nolimit' => true
+], true);
+
+if (count($pipelineList) === 0) {
+ throw new \Exception("pipeline_not_found");
+}
+
+$pipeline = $pipelineList[0];
+$nodes_ids = $pipeline['nodes_ids'] ?? [];
+
+$result = [
+ 'pipeline' => [
+ 'id' => $pipeline['id'],
+ 'name' => $pipeline['name']
+ ],
+ 'nodes' => [],
+ 'links' => [],
+ 'parameters' => []
+];
+
+// Step 2: Load all nodes
+$nodes = \eQual::run('get', 'model_collect', [
+ 'entity' => 'core\\pipeline\\Node',
+ 'domain' => [['id', 'in', $nodes_ids]],
+ 'fields' => [
+ 'id', 'name', 'description',
+ 'out_links_ids', 'in_links_ids',
+ 'operation_controller', 'operation_type',
+ 'params_ids'
+ ],
+ 'nolimit' => true
+], true);
+
+// Step 3: Load Meta for nodes
+$metaList = \eQual::run('get', 'model_collect', [
+ 'entity' => 'core\\Meta',
+ 'domain' => [['reference', 'in', array_map(fn($id) => 'node.' . $id, $nodes_ids)]],
+ 'fields' => ['reference', 'value'],
+ 'nolimit' => true
+], true);
+
+$metaMap = [];
+foreach ($metaList as $meta) {
+ $nodeId = (int) str_replace('node.', '', $meta['reference']);
+ $metaMap[$nodeId] = json_decode($meta['value'], true);
+}
+
+$linkIds = [];
+$paramIds = [];
+
+// Step 4: Process nodes and collect link/param IDs
+foreach ($nodes as $node) {
+ $nodeId = $node['id'];
+
+ $result['nodes'][] = [
+ ...$node,
+ 'meta' => $metaMap[$nodeId] ?? ['position' => ['x' => 0, 'y' => 0], 'icon' => '', 'color' => '']
+ ];
+
+ $linkIds = array_merge($linkIds, $node['in_links_ids'], $node['out_links_ids']);
+ $paramIds = array_merge($paramIds, $node['params_ids']);
+}
+
+// Step 5: Load links
+$linkIds = array_unique($linkIds);
+if (!empty($linkIds)) {
+ $links = \eQual::run('get', 'model_collect', [
+ 'entity' => 'core\\pipeline\\NodeLink',
+ 'domain' => [['id', 'in', $linkIds]],
+ 'fields' => ['id', 'reference_node_id', 'source_node_id', 'target_node_id', 'target_param'],
+ 'nolimit' => true
+ ], true);
+ $result['links'] = $links;
+}
+
+// Step 6: Load parameters
+$paramIds = array_unique($paramIds);
+if (!empty($paramIds)) {
+ $params = \eQual::run('get', 'model_collect', [
+ 'entity' => 'core\\pipeline\\Parameter',
+ 'domain' => [['id', 'in', $paramIds]],
+ 'fields' => ['id', 'node_id', 'param', 'value'],
+ 'nolimit' => true
+ ], true);
+
+ // Decode values
+ foreach ($params as &$p) {
+ $p['value'] = json_decode($p['value'], true);
+ }
+
+ $result['parameters'] = $params;
+}
+
+$context->httpResponse()
+ ->body($result)
+ ->send();
\ No newline at end of file
diff --git a/packages/core/data/run-pipeline.php b/packages/core/data/run-pipeline.php
index 06a5be8a..e297a13d 100644
--- a/packages/core/data/run-pipeline.php
+++ b/packages/core/data/run-pipeline.php
@@ -67,8 +67,21 @@
foreach ($node['params_ids'] as $param) {
$parameters[$param['param']] = json_decode($param['value']);
}
- $result_map[$node['id']] = eQual::run($node['operation_type'], $node['operation_controller'], $parameters, true);
- $count++;
+ try {
+ $result_map[$node['id']] = eQual::run($node['operation_type'], $node['operation_controller'], $parameters, true);
+ $count++;
+ } catch (Exception $e) {
+ // Retourner les résultats partiels et l'erreur
+ $context->httpResponse()
+ ->status(500)
+ ->body([
+ 'error' => 'Pipeline execution failed at node: ' . $node['name'],
+ 'message' => $e->getMessage(),
+ 'partial_results' => $result_map
+ ])
+ ->send();
+ return;
+ }
}
}
}
@@ -90,8 +103,20 @@
foreach ($node['params_ids'] as $param) {
$parameters[$param['param']] = json_decode($param['value']);
}
- $result_map[$node['id']] = eQual::run($node['operation_type'], $node['operation_controller'], $parameters, true);
- $count++;
+ try {
+ $result_map[$node['id']] = eQual::run($node['operation_type'], $node['operation_controller'], $parameters, true);
+ $count++;
+ } catch (Exception $e) {
+ $context->httpResponse()
+ ->status(200)
+ ->body([
+ - 'error' => 'Pipeline execution failed at node: ' . $node['name'],
+ 'message' => $e->getMessage(),
+ 'partial_results' => $result_map
+ ])
+ ->send();
+ return;
+ }
}
}
}
@@ -106,3 +131,4 @@
$context->httpResponse()
->body($res)
->send();
+?>