From 9ca4df959af6f5dfe98e5e0daaf9457813f9dab1 Mon Sep 17 00:00:00 2001 From: David Callizaya Date: Thu, 16 Jan 2025 16:19:47 -0400 Subject: [PATCH 1/3] Add test for retrieving process variables from screens with pagination --- .../V1_1/ProcessVariableControllerTest.php | 90 +++++++++++++++++++ 1 file changed, 90 insertions(+) diff --git a/tests/Feature/Api/V1_1/ProcessVariableControllerTest.php b/tests/Feature/Api/V1_1/ProcessVariableControllerTest.php index 00e286bc12..beaa6e8c8e 100644 --- a/tests/Feature/Api/V1_1/ProcessVariableControllerTest.php +++ b/tests/Feature/Api/V1_1/ProcessVariableControllerTest.php @@ -89,6 +89,58 @@ public function test_can_get_process_variables_with_pagination(): void $this->assertEquals(30, $responseData['meta']['total']); } + /** + * Test successful variables retrieval with pagination + */ + public function test_can_get_process_variables_from_process_screens_with_pagination(): void + { + $bpmn = file_get_contents(base_path('tests/Feature/Api/bpmnPatterns/SimpleTaskProcess.bpmn')); + ProcessVariableController::mock(false); + $screen1 = $this->createScreenWithFields(1, 10); + $screen2 = $this->createScreenWithFields(2, 10); + $screen3 = $this->createScreenWithFields(3, 10); + Process::factory()->create(['id' => 1, 'bpmn' => str_replace('pm:screenRef="2"', 'pm:screenRef="' . $screen1->id . '"', $bpmn)]); + Process::factory()->create(['id' => 2, 'bpmn' => str_replace('pm:screenRef="2"', 'pm:screenRef="' . $screen2->id . '"', $bpmn)]); + Process::factory()->create(['id' => 3, 'bpmn' => str_replace('pm:screenRef="2"', 'pm:screenRef="' . $screen3->id . '"', $bpmn)]); + + // Make request to the endpoint + $response = $this->apiCall('GET', '/api/1.1/processes/variables?processIds=1,2,3&page=1&per_page=15'); + + // Assert response structure and status + $response->assertStatus(200) + ->assertJsonStructure([ + 'data' => [ + '*' => [ + //'id', + //'process_id', + 'format', + 'label', + 'field', + 'default', + //'created_at', + //'updated_at', + ] + ], + 'meta' => [ + 'current_page', + 'from', + 'last_page', + 'path', + 'per_page', + 'to', + 'total', + ] + ]); + + // Assert pagination works correctly + $responseData = $response->json(); + $this->assertEquals(15, $responseData['meta']['per_page']); + $this->assertEquals(1, $responseData['meta']['current_page']); + + // Since we're generating 10 variables per process (3 processes = 30 total) + $this->assertEquals(30, $responseData['meta']['total']); + } + private function mockVariableFinder(array $processIds, $excludeSavedSearch) { // Create a cache key based on process IDs @@ -281,4 +333,42 @@ public function test_saved_search_id_filtering(): void // Check that the total count is reduced by the number of excluded fields $this->assertEquals(8, $responseData['meta']['total']); // 10 total - 2 excluded } + + /** + * Create a screen with a given number of fields + * + * @param int $processId + * @param int $fieldsCount + * + * @return Screen + */ + private function createScreenWithFields(int $processId, int $fieldsCount) + { + $items = []; + for ($i = 1; $i <= $fieldsCount; $i++) { + $items[] = [ + 'component' => 'FormInput', + 'config' => [ + 'name' => "var_{$processId}_{$i}", + 'type' => 'text', + 'label' => "Variable {$i} for Process {$processId}", + 'helper' => null, + 'dataFormat' => 'string', + 'validation' => null, + 'placeholder' => null, + ], + ]; + } + + return Screen::factory()->create([ + 'config' => [ + [ + [ + 'name' => 'screen name', + 'items' => $items, + ], + ] + ], + ]); + } } From db815ecf2debda72af13823ac122b6590367ec44 Mon Sep 17 00:00:00 2001 From: David Callizaya Date: Thu, 16 Jan 2025 16:20:20 -0400 Subject: [PATCH 2/3] Implement retrieval of process variables from screens and enhance pagination support --- .../Api/V1_1/ProcessVariableController.php | 55 +++++++++++++++++-- 1 file changed, 51 insertions(+), 4 deletions(-) diff --git a/ProcessMaker/Http/Controllers/Api/V1_1/ProcessVariableController.php b/ProcessMaker/Http/Controllers/Api/V1_1/ProcessVariableController.php index f7729443da..4e7664aba3 100644 --- a/ProcessMaker/Http/Controllers/Api/V1_1/ProcessVariableController.php +++ b/ProcessMaker/Http/Controllers/Api/V1_1/ProcessVariableController.php @@ -10,6 +10,9 @@ use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Schema; +use ProcessMaker\Managers\ExportManager; +use ProcessMaker\Models\Process; +use ProcessMaker\Models\Screen; use ProcessMaker\Package\SavedSearch\Models\SavedSearch; use ProcessMaker\Package\VariableFinder\Models\ProcessVariable; @@ -202,7 +205,7 @@ public function getProcessesVariables(array $processIds, $excludeSavedSearch, $p { // If the classes or tables do not exist, fallback to a saved search approach. if (!class_exists(ProcessVariable::class) || !Schema::hasTable('process_variables')) { - return $this->getProcessesVariablesFromSavedSearch($processIds); + return $this->getProcessesVariablesFrom($processIds); } // Determine which columns to exclude based on the saved search @@ -219,7 +222,8 @@ public function getProcessesVariables(array $processIds, $excludeSavedSearch, $p $query = DB::table('var_finder_variables AS vfv') ->join('asset_variables AS av', 'vfv.asset_variable_id', '=', 'av.id') ->join('process_variables AS pv', 'av.id', '=', 'pv.asset_variable_id') - ->whereIn('pv.process_id', $processIds); + ->whereIn('pv.process_id', $processIds) + ->orderBy('vfv.id'); if (!empty($activeColumns)) { $query->whereNotIn('vfv.field', $activeColumns); @@ -243,8 +247,51 @@ public function getProcessesVariables(array $processIds, $excludeSavedSearch, $p * * @return void */ - public static function mock() + public static function mock(bool $value = true) { - static::$mockData = true; + static::$mockData = $value; + } + + /** + * Retrieve process variables from its screens. + * + * @param array $processIds + * + * @return LengthAwarePaginator + */ + private function getProcessesVariablesFrom(array $processIds) + { + // Get screens used in the processes + $processes = Process::whereIn('id', $processIds)->get(); + $ids = collect([]); + foreach ($processes as $process) { + $manager = app(ExportManager::class); + try { + $ids = $ids->merge($manager->getDependenciesOfType(Screen::class, $process)); + } catch (\Exception $e) { + $ids = collect([]); + } + } + + // Get columns from screens + $columns = collect([]); + $screens = Screen::whereIn('id', $ids->unique())->where('type', '!=', 'DISPLAY')->get(); + foreach ($screens as $screen) { + $screenColumns = $screen->fields->map(function ($item) { + $item->field = "data.{$item->field}"; + + return $item; + }); + + $columns = $columns->merge($screenColumns); + } + + // Paginate the result + $page = request()->get('page', 1); + $perPage = request()->get('per_page', 20); + $total = $columns->count(); + $items = $columns->forPage($page, $perPage); + + return new LengthAwarePaginator($items, $total, $perPage, $page); } } From 2d419d1bfc29b451a127296eb4b60d1c63348efd Mon Sep 17 00:00:00 2001 From: David Callizaya Date: Fri, 17 Jan 2025 14:39:12 -0400 Subject: [PATCH 3/3] Add validation for processIds input and ensure pagination parameters are handled correctly --- .../Controllers/Api/V1_1/ProcessVariableController.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/ProcessMaker/Http/Controllers/Api/V1_1/ProcessVariableController.php b/ProcessMaker/Http/Controllers/Api/V1_1/ProcessVariableController.php index 4e7664aba3..660bf9f31a 100644 --- a/ProcessMaker/Http/Controllers/Api/V1_1/ProcessVariableController.php +++ b/ProcessMaker/Http/Controllers/Api/V1_1/ProcessVariableController.php @@ -261,6 +261,12 @@ public static function mock(bool $value = true) */ private function getProcessesVariablesFrom(array $processIds) { + $perPage = request()->get('per_page', 20); + // Validate processIds input is required + if (empty($processIds)) { + return new LengthAwarePaginator([], 0, $perPage, 1); + } + // Get screens used in the processes $processes = Process::whereIn('id', $processIds)->get(); $ids = collect([]); @@ -288,7 +294,6 @@ private function getProcessesVariablesFrom(array $processIds) // Paginate the result $page = request()->get('page', 1); - $perPage = request()->get('per_page', 20); $total = $columns->count(); $items = $columns->forPage($page, $perPage);