diff --git a/ProcessMaker/Http/Controllers/TaskController.php b/ProcessMaker/Http/Controllers/TaskController.php index fa4c945454..d45ffbb12a 100755 --- a/ProcessMaker/Http/Controllers/TaskController.php +++ b/ProcessMaker/Http/Controllers/TaskController.php @@ -78,12 +78,12 @@ public function edit(ProcessRequestToken $task, string $preview = '') MarkNotificationAsRead::dispatch([['url', '=', '/' . Request::path()]], ['read_at' => Carbon::now()]); $manager = app(ScreenBuilderManager::class); - event(new ScreenBuilderStarting($manager, $task->getScreenVersion() ? $task->getScreenVersion()->type : 'FORM')); + $screenVersion = $task->getScreenVersion(); + event(new ScreenBuilderStarting($manager, $screenVersion ? $screenVersion->type : 'FORM')); $submitUrl = route('api.tasks.update', $task->id); $task->processRequest; $task->user; - $screenVersion = $task->getScreenVersion(); $task->component = $screenVersion ? $screenVersion->parent->renderComponent() : null; $task->screen = $screenVersion ? $screenVersion->toArray() : null; $task->request_data = $dataManager->getData($task); @@ -98,6 +98,11 @@ public function edit(ProcessRequestToken $task, string $preview = '') $screenFields = $screenVersion ? $screenVersion->screenFilteredFields() : []; $taskDraftsEnabled = TaskDraft::draftsEnabled(); + // Remove screen parent to reduce the size of the response + $screen = $task->screen; + $screen['parent'] = null; + $task->screen = $screen; + if ($element instanceof ScriptTaskInterface) { return redirect(route('requests.show', ['request' => $task->processRequest->getKey()])); } else { diff --git a/ProcessMaker/Traits/HasScreenFields.php b/ProcessMaker/Traits/HasScreenFields.php index f64dbc79b1..909cc13ddd 100644 --- a/ProcessMaker/Traits/HasScreenFields.php +++ b/ProcessMaker/Traits/HasScreenFields.php @@ -4,6 +4,7 @@ use Illuminate\Support\Arr; use Log; +use ProcessMaker\Cache\Screens\ScreenCacheFactory; use ProcessMaker\Models\Column; use ProcessMaker\Models\Screen; @@ -19,10 +20,7 @@ public function getFieldsAttribute() { if (empty($this->parsedFields)) { try { - $this->parsedFields = collect([]); - if ($this->config) { - $this->walkArray($this->config); - } + $this->loadScreenFields(); } catch (\Throwable $e) { Log::error("Error encountered while retrieving fields for screen #{$this->id}", [ 'message' => $e->getMessage(), @@ -39,6 +37,40 @@ public function getFieldsAttribute() return $this->parsedFields->unique('field'); } + /** + * Load the fields for the screen and cache them + * + * @return void + */ + private function loadScreenFields() + { + $screenCache = ScreenCacheFactory::getScreenCache(); + // Create cache key + $screenId = $this instanceof Screen ? $this->id : $this->screen_id; + $screenVersionId = $this instanceof Screen ? 0 : $this->id; + $key = $screenCache->createKey([ + 'process_id' => 0, + 'process_version_id' => 0, + 'language' => 'all', + 'screen_id' => (int) $screenId, + 'screen_version_id' => (int) $screenVersionId, + ]) . '_fields'; + + // Try to get the screen fields from cache + $parsedFields = $screenCache->get($key); + + if (!$parsedFields || collect($parsedFields)->isEmpty()) { + $this->parsedFields = collect([]); + if ($this->config) { + $this->walkArray($this->config); + } + + $screenCache->set($key, $this->parsedFields); + } else { + $this->parsedFields = collect($parsedFields); + } + } + public function parseNestedScreen($node) { $nested = Screen::find($node['config']['screen']); diff --git a/tests/unit/ProcessMaker/HasScreenFieldsTest.php b/tests/unit/ProcessMaker/HasScreenFieldsTest.php new file mode 100644 index 0000000000..69d0b6a7bc --- /dev/null +++ b/tests/unit/ProcessMaker/HasScreenFieldsTest.php @@ -0,0 +1,142 @@ +create([ + 'id' => 1, + 'config' => [ + [ + 'items' => [ + [ + 'component' => 'FormInput', + 'config' => [ + 'name' => 'field1', + 'label' => 'Field 1', + 'dataFormat' => 'string', + ], + ], + [ + 'component' => 'FormInput', + 'config' => [ + 'name' => 'field2', + 'label' => 'Field 2', + 'dataFormat' => 'string', + ], + ], + ], + ], + ], + ]); + $expectedFields = [ + [ + 'label' => 'Field 1', + 'field' => 'field1', + 'sortable' => true, + 'default' => false, + 'format' => 'string', + 'mask' => null, + 'isSubmitButton' => false, + 'encryptedConfig' => null, + ], + [ + 'label' => 'Field 2', + 'field' => 'field2', + 'sortable' => true, + 'default' => false, + 'format' => 'string', + 'mask' => null, + 'isSubmitButton' => false, + 'encryptedConfig' => null, + ], + ]; + $key = $screenCache->createKey([ + 'process_id' => 0, + 'process_version_id' => 0, + 'language' => 'all', + 'screen_id' => (int) $screen->id, + 'screen_version_id' => 0, + ]) . '_fields'; + $screenCache->set($key, null); + + $fields = json_decode(json_encode($screen->fields), true); + + $cacheFields = json_decode(json_encode($screenCache->get($key)), true); + + $this->assertEquals($expectedFields, $fields); + $this->assertEquals($expectedFields, $cacheFields); + } + + public function testLoadScreenFieldsFromCache() + { + $screenCache = ScreenCacheFactory::getScreenCache(); + $screen = Screen::factory()->create([ + 'id' => 1, + 'config' => [ + [ + 'items' => [ + [ + 'component' => 'FormInput', + 'config' => [ + 'name' => 'field1', + 'label' => 'Field 1', + 'dataFormat' => 'string', + ], + ], + [ + 'component' => 'FormInput', + 'config' => [ + 'name' => 'field2', + 'label' => 'Field 2', + 'dataFormat' => 'string', + ], + ], + ], + ], + ], + ]); + $expectedFields = [ + [ + 'label' => 'Field 1 (cached)', + 'field' => 'field1', + 'sortable' => true, + 'default' => false, + 'format' => 'string', + 'mask' => null, + 'isSubmitButton' => false, + 'encryptedConfig' => null, + ], + [ + 'label' => 'Field 2 (cached)', + 'field' => 'field2', + 'sortable' => true, + 'default' => false, + 'format' => 'string', + 'mask' => null, + 'isSubmitButton' => false, + 'encryptedConfig' => null, + ], + ]; + $key = $screenCache->createKey([ + 'process_id' => 0, + 'process_version_id' => 0, + 'language' => 'all', + 'screen_id' => (int) $screen->id, + 'screen_version_id' => 0, + ]) . '_fields'; + $screenCache->set($key, $expectedFields); + + $fields = json_decode(json_encode($screen->fields), true); + + $cacheFields = json_decode(json_encode($screenCache->get($key)), true); + + $this->assertEquals($expectedFields, $fields); + $this->assertEquals($expectedFields, $cacheFields); + } +}