From 2469a74e0fcd7ecd66e86833d6d9d6f6fb0cfa6e Mon Sep 17 00:00:00 2001 From: David Callizaya Date: Fri, 14 Jun 2024 16:44:33 -0400 Subject: [PATCH 1/7] Enable apiClient 1.1 --- resources/js/bootstrap.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/resources/js/bootstrap.js b/resources/js/bootstrap.js index 36adc17e16..e4017c36bf 100644 --- a/resources/js/bootstrap.js +++ b/resources/js/bootstrap.js @@ -233,6 +233,17 @@ if (token) { } window.ProcessMaker.apiClient.defaults.baseURL = "/api/1.0/"; +// If requested url starts with "/api/1.1/" use "/api/1.1/" +window.ProcessMaker.apiClient.interceptors.request.use((config) => { + if (config.url.startsWith("/api/1.1/")) { + config.baseURL = "/api/1.1/"; + config.url = config.url.replace("/api/1.1/", ""); + } else { + config.baseURL = "/api/1.0/"; + } + return config; +}); + // Set the default API timeout let apiTimeout = 5000; From e0f1746d9a9fa47b9712a6f5781f4e651634fb5a Mon Sep 17 00:00:00 2001 From: David Callizaya Date: Fri, 14 Jun 2024 16:54:45 -0400 Subject: [PATCH 2/7] Add resources version 1.1 --- ProcessMaker/Http/Resources/Task.php | 26 --- .../Http/Resources/V1_1/TaskResource.php | 177 ++++++++++++++++++ ProcessMaker/Traits/TaskResourceIncludes.php | 31 ++- 3 files changed, 207 insertions(+), 27 deletions(-) create mode 100644 ProcessMaker/Http/Resources/V1_1/TaskResource.php diff --git a/ProcessMaker/Http/Resources/Task.php b/ProcessMaker/Http/Resources/Task.php index 186c6ab89f..11008405d0 100644 --- a/ProcessMaker/Http/Resources/Task.php +++ b/ProcessMaker/Http/Resources/Task.php @@ -113,20 +113,6 @@ private function addAssignableUsers(&$array, $include) } } - private function loadUserRequestPermission(ProcessRequest $request, User $user, array $permissions) - { - $permissions[] = [ - 'process_request_id' => $request->id, - 'allowed' => $user ? $user->can('view', $request) : false, - ]; - - if ($request->parentRequest && $user) { - $permissions = $this->loadUserRequestPermission($request->parentRequest, $user, $permissions); - } - - return $permissions; - } - private function getAssignedUsers($users) { foreach ($users as $user) { @@ -148,16 +134,4 @@ private function getAssignedGroupMembers($groups) return $assignedUsers; } - - private function getData() - { - if ($this->loadedData) { - return $this->loadedData; - } - $dataManager = new DataManager(); - $task = $this->resource->loadTokenInstance(); - $this->loadedData = $dataManager->getData($task); - - return $this->loadedData; - } } diff --git a/ProcessMaker/Http/Resources/V1_1/TaskResource.php b/ProcessMaker/Http/Resources/V1_1/TaskResource.php new file mode 100644 index 0000000000..437296e855 --- /dev/null +++ b/ProcessMaker/Http/Resources/V1_1/TaskResource.php @@ -0,0 +1,177 @@ + ['id', 'firstname', 'lastname', 'email', 'username', 'avatar'], + 'requestor' => ['id', 'first_name', 'last_name', 'email'], + 'processRequest' => ['id', 'process_id', 'status'], + 'draft' => ['id', 'task_id', 'data'], + // 'component' => ['id', 'name', 'type', 'version'], + 'screen' => ['id', 'config'], + // 'requestData', + // 'loopContext', + // 'definition' + // 'bpmnTagName', + // 'interstitial', + // 'userRequestPermission', + 'process' => ['id', 'name'], + ]; + + /** + * Transform the resource into an array. + * + * @param \Illuminate\Http\Request + * @return array + */ + public function toArray($request) + { + $array = [ + 'id' => $this->id, + 'element_name' => $this->element_name, + 'element_id' => $this->element_id, + 'due_at' => $this->due_at, + 'advancedStatus' => $this->advanceStatus, + ]; + + return $this->processInclude($request, $array); + } + + private static function addRelationshipKeyColumn(Builder $query, string $relationship): bool + { + $model = $query->getModel(); + if (!method_exists($model, $relationship)) { + return false; + } + $relationshipObject = $model->$relationship(); + if (!($relationshipObject instanceof Relation)) { + return false; + } + + if ($relationshipObject instanceof BelongsTo) { + $relationshipKey = $relationshipObject->getForeignKeyName(); + $query->addSelect($relationshipKey); + } + + return true; + } + + private static function addRelationship(ProcessRequestToken $model, string $relationship): bool + { + if (!method_exists($model, $relationship)) { + return false; + } + $relationshipObject = $model->$relationship(); + if (!($relationshipObject instanceof Relation)) { + return false; + } + + // $singleRelationship = $relationshipObject instanceof HasOne || $relationshipObject instanceof BelongsTo; + $relationshipColumns = self::$defaultFieldsFor[$relationship] ?? ['id']; + $model->$relationship = $relationshipObject->select($relationshipColumns)->get(); + + return true; + } + + public static function preprocessInclude(Request $request, Builder $query): self + { + foreach (self::$defaultFields as $field) { + $query->addSelect($field); + } + + $include = $request->query('include', []); + if ($include) { + $include = explode(',', $include); + } + $include[] = 'process'; + $include[] = 'advanceStatus'; + + if (in_array('data', $include)) { + $query->addSelect('process_request_id'); + } + + foreach (self::$includeMethods as $key) { + if (!in_array($key, $include)) { + continue; + } + + self::addRelationshipKeyColumn($query, $key); + } + + $model = $query->first(); + foreach (self::$includeMethods as $key) { + if (!in_array($key, $include)) { + continue; + } + + self::addRelationship($model, $key); + } + + return new static($query->first()); + } + + private function processInclude(Request $request, array $array) + { + // http://pm4.local:8089/api/1.1/tasks/2963612?include=data,user,draft,requestor,processRequest,component,requestData,loopContext,bpmnTagName,interstitial,definition,userRequestPermission + $include = $request->query('include', []); + if ($include) { + $include = explode(',', $include); + } + + foreach (self::$includeMethods as $key) { + if (!in_array($key, $include)) { + continue; + } + + $method = "include" . ucfirst($key); + if (method_exists($this, $method)) { + $attributes = $this->$method(); + $array = array_merge($array, $attributes); + } else { + $array[$key] = $this->$key; + } + } + return $array; + } +} diff --git a/ProcessMaker/Traits/TaskResourceIncludes.php b/ProcessMaker/Traits/TaskResourceIncludes.php index 429e0c6603..467190244a 100644 --- a/ProcessMaker/Traits/TaskResourceIncludes.php +++ b/ProcessMaker/Traits/TaskResourceIncludes.php @@ -6,7 +6,9 @@ use ProcessMaker\Http\Resources\ScreenVersion as ScreenVersionResource; use ProcessMaker\Http\Resources\Users; use ProcessMaker\Managers\DataManager; +use ProcessMaker\Models\ProcessRequest; use ProcessMaker\Models\TaskDraft; +use ProcessMaker\Models\User; use ProcessMaker\ProcessTranslations\ProcessTranslation; use StdClass; @@ -14,6 +16,19 @@ trait TaskResourceIncludes { use TaskScreenResourceTrait; + + private function getData() + { + if ($this->loadedData) { + return $this->loadedData; + } + $dataManager = new DataManager(); + $task = $this->resource->loadTokenInstance(); + $this->loadedData = $dataManager->getData($task); + + return $this->loadedData; + } + private function includeData() { return ['data' => $this->getData()]; @@ -131,7 +146,7 @@ private function includeInterstitial() // Remove inspector metadata $interstitial['interstitial_screen']['config'] = $this->removeInspectorMetadata( - $interstitial['interstitial_screen']['config'] + $interstitial['interstitial_screen']['config'] ?: [] ); return [ @@ -146,4 +161,18 @@ private function includeUserRequestPermission() return ['user_request_permission' => $userRequestPermission]; } + + private function loadUserRequestPermission(ProcessRequest $request, User $user, array $permissions) + { + $permissions[] = [ + 'process_request_id' => $request->id, + 'allowed' => $user ? $user->can('view', $request) : false, + ]; + + if ($request->parentRequest && $user) { + $permissions = $this->loadUserRequestPermission($request->parentRequest, $user, $permissions); + } + + return $permissions; + } } From 405b140236b1ed41aeb124e8744460468d69f500 Mon Sep 17 00:00:00 2001 From: David Callizaya Date: Fri, 14 Jun 2024 17:01:38 -0400 Subject: [PATCH 3/7] Fix issues --- ProcessMaker/Http/Resources/V1_1/TaskResource.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/ProcessMaker/Http/Resources/V1_1/TaskResource.php b/ProcessMaker/Http/Resources/V1_1/TaskResource.php index 437296e855..dd9c7f4184 100644 --- a/ProcessMaker/Http/Resources/V1_1/TaskResource.php +++ b/ProcessMaker/Http/Resources/V1_1/TaskResource.php @@ -107,7 +107,6 @@ private static function addRelationship(ProcessRequestToken $model, string $rela return false; } - // $singleRelationship = $relationshipObject instanceof HasOne || $relationshipObject instanceof BelongsTo; $relationshipColumns = self::$defaultFieldsFor[$relationship] ?? ['id']; $model->$relationship = $relationshipObject->select($relationshipColumns)->get(); @@ -153,7 +152,6 @@ public static function preprocessInclude(Request $request, Builder $query): self private function processInclude(Request $request, array $array) { - // http://pm4.local:8089/api/1.1/tasks/2963612?include=data,user,draft,requestor,processRequest,component,requestData,loopContext,bpmnTagName,interstitial,definition,userRequestPermission $include = $request->query('include', []); if ($include) { $include = explode(',', $include); From 9469f0ac39647b2f0949c44965b7469f802ba597 Mon Sep 17 00:00:00 2001 From: David Callizaya Date: Fri, 14 Jun 2024 17:03:46 -0400 Subject: [PATCH 4/7] Fix code review issues --- ProcessMaker/Http/Resources/V1_1/TaskResource.php | 7 ------- 1 file changed, 7 deletions(-) diff --git a/ProcessMaker/Http/Resources/V1_1/TaskResource.php b/ProcessMaker/Http/Resources/V1_1/TaskResource.php index dd9c7f4184..80b8e49bd4 100644 --- a/ProcessMaker/Http/Resources/V1_1/TaskResource.php +++ b/ProcessMaker/Http/Resources/V1_1/TaskResource.php @@ -48,14 +48,7 @@ class TaskResource extends ApiResource 'requestor' => ['id', 'first_name', 'last_name', 'email'], 'processRequest' => ['id', 'process_id', 'status'], 'draft' => ['id', 'task_id', 'data'], - // 'component' => ['id', 'name', 'type', 'version'], 'screen' => ['id', 'config'], - // 'requestData', - // 'loopContext', - // 'definition' - // 'bpmnTagName', - // 'interstitial', - // 'userRequestPermission', 'process' => ['id', 'name'], ]; From da6aa2fbd9bcf52c86dc4dd4e51951ed740720cf Mon Sep 17 00:00:00 2001 From: David Callizaya Date: Fri, 14 Jun 2024 17:15:30 -0400 Subject: [PATCH 5/7] Fix code review observations --- ProcessMaker/Http/Resources/V1_1/TaskResource.php | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/ProcessMaker/Http/Resources/V1_1/TaskResource.php b/ProcessMaker/Http/Resources/V1_1/TaskResource.php index 80b8e49bd4..3e7c611102 100644 --- a/ProcessMaker/Http/Resources/V1_1/TaskResource.php +++ b/ProcessMaker/Http/Resources/V1_1/TaskResource.php @@ -43,6 +43,11 @@ class TaskResource extends ApiResource 'due_at', ]; + protected static $defaultIncludes = [ + 'process', + 'advanceStatus', + ]; + protected static $defaultFieldsFor = [ 'user' => ['id', 'firstname', 'lastname', 'email', 'username', 'avatar'], 'requestor' => ['id', 'first_name', 'last_name', 'email'], @@ -116,8 +121,7 @@ public static function preprocessInclude(Request $request, Builder $query): self if ($include) { $include = explode(',', $include); } - $include[] = 'process'; - $include[] = 'advanceStatus'; + $include = array_merge($include, self::$defaultIncludes); if (in_array('data', $include)) { $query->addSelect('process_request_id'); @@ -140,7 +144,7 @@ public static function preprocessInclude(Request $request, Builder $query): self self::addRelationship($model, $key); } - return new static($query->first()); + return new static($model); } private function processInclude(Request $request, array $array) From 521374d001f2178fd1499506e68e5008c5efaa35 Mon Sep 17 00:00:00 2001 From: David Callizaya Date: Fri, 14 Jun 2024 17:17:29 -0400 Subject: [PATCH 6/7] Use constant for prefix --- ProcessMaker/Http/Resources/V1_1/TaskResource.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ProcessMaker/Http/Resources/V1_1/TaskResource.php b/ProcessMaker/Http/Resources/V1_1/TaskResource.php index 3e7c611102..7877910217 100644 --- a/ProcessMaker/Http/Resources/V1_1/TaskResource.php +++ b/ProcessMaker/Http/Resources/V1_1/TaskResource.php @@ -19,6 +19,8 @@ class TaskResource extends ApiResource { use TaskResourceIncludes; + const INCLUDE_PREFIX = 'include'; + protected static $includeMethods = [ 'data', 'user', @@ -159,7 +161,7 @@ private function processInclude(Request $request, array $array) continue; } - $method = "include" . ucfirst($key); + $method = self::INCLUDE_PREFIX . ucfirst($key); if (method_exists($this, $method)) { $attributes = $this->$method(); $array = array_merge($array, $attributes); From 7e054a2384199f822773071cc4356cdad8cfb7b6 Mon Sep 17 00:00:00 2001 From: David Callizaya Date: Fri, 14 Jun 2024 17:28:35 -0400 Subject: [PATCH 7/7] Improve the code to setup multiple version --- resources/js/bootstrap.js | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/resources/js/bootstrap.js b/resources/js/bootstrap.js index e4017c36bf..7b5dde41a1 100644 --- a/resources/js/bootstrap.js +++ b/resources/js/bootstrap.js @@ -232,19 +232,31 @@ if (token) { console.error("CSRF token not found: https://laravel.com/docs/csrf#csrf-x-csrf-token"); } +// Setup api versions +const apiVersionConfig = [ + { version: "1.0", baseURL: "/api/1.0/" }, + { version: "1.1", baseURL: "/api/1.1/" }, +]; + window.ProcessMaker.apiClient.defaults.baseURL = "/api/1.0/"; -// If requested url starts with "/api/1.1/" use "/api/1.1/" window.ProcessMaker.apiClient.interceptors.request.use((config) => { - if (config.url.startsWith("/api/1.1/")) { - config.baseURL = "/api/1.1/"; - config.url = config.url.replace("/api/1.1/", ""); - } else { - config.baseURL = "/api/1.0/"; + if (typeof config.url !== "string" || !config.url) { + throw new Error("Invalid URL in the request configuration"); } + + apiVersionConfig.forEach(({ version, baseURL }) => { + const versionPrefix = `/api/${version}/`; + if (config.url.startsWith(versionPrefix)) { + // eslint-disable-next-line no-param-reassign + config.baseURL = baseURL; + // eslint-disable-next-line no-param-reassign + config.url = config.url.replace(versionPrefix, ""); + } + }); + return config; }); - // Set the default API timeout let apiTimeout = 5000; if (window.Processmaker && window.Processmaker.apiTimeout !== undefined) {