From 255fc1789a7ca108d8e7b10496cbc753df345cb3 Mon Sep 17 00:00:00 2001 From: Jhon Date: Wed, 9 Oct 2024 17:56:11 -0400 Subject: [PATCH 01/19] Creates response option class Issue: documentacao-e-tarefas/scielo#706 Signed-off-by: Jhon --- .../DemographicResponseOption.php | 36 ++++++++++++++++ .../DemographicResponseOptionTest.php | 42 +++++++++++++++++++ 2 files changed, 78 insertions(+) create mode 100644 classes/demographicResponseOption/DemographicResponseOption.php create mode 100644 tests/demographicResponseOption/DemographicResponseOptionTest.php diff --git a/classes/demographicResponseOption/DemographicResponseOption.php b/classes/demographicResponseOption/DemographicResponseOption.php new file mode 100644 index 0000000..d889985 --- /dev/null +++ b/classes/demographicResponseOption/DemographicResponseOption.php @@ -0,0 +1,36 @@ +getData('demographicQuestionId'); + } + + public function setDemographicQuestionId($demographicQuestionId) + { + $this->setData('demographicQuestionId', $demographicQuestionId); + } + + public function getLocalizedOptionText() + { + return $this->getLocalizedData('optionText'); + } + + public function setOptionText(string $text, string $locale) + { + $this->setData('optionText', $text, $locale); + } + + public function hasInputField(): bool + { + return $this->getData('hasInputField'); + } + + public function setHasInputField(bool $hasInputField) + { + $this->setData('hasInputField', $hasInputField); + } +} diff --git a/tests/demographicResponseOption/DemographicResponseOptionTest.php b/tests/demographicResponseOption/DemographicResponseOptionTest.php new file mode 100644 index 0000000..34f34c0 --- /dev/null +++ b/tests/demographicResponseOption/DemographicResponseOptionTest.php @@ -0,0 +1,42 @@ +demographicResponseOption = new DemographicResponseOption(); + parent::setUp(); + } + + public function testGetDemographicQuestionId(): void + { + $expectedDemographicQuestionId = 1; + $this->demographicResponseOption->setDemographicQuestionId($expectedDemographicQuestionId); + + $this->assertEquals($expectedDemographicQuestionId, $this->demographicResponseOption->getDemographicQuestionId()); + } + + public function testGetResponseOptionText(): void + { + $expectedResponseOptionText = "Less than a minimum wage"; + $this->demographicResponseOption->setOptionText($expectedResponseOptionText, 'en'); + $optionText = $this->demographicResponseOption->getLocalizedOptionText(); + + $this->assertEquals($expectedResponseOptionText, $optionText); + } + + public function testGetHasInputField(): void + { + $hasInputField = true; + $this->demographicResponseOption->setHasInputField($hasInputField); + + $this->assertEquals($hasInputField, $this->demographicResponseOption->hasInputField()); + } +} From 461a903a3145cf22fa28b69c97ff46f3496fd582 Mon Sep 17 00:00:00 2001 From: Jhon Date: Fri, 11 Oct 2024 15:28:19 -0400 Subject: [PATCH 02/19] Refactors adding of stylesheet on questionnaire page Issue: documentacao-e-tarefas/scielo#696 Signed-off-by: Jhon --- pages/demographic/QuestionnaireHandler.php | 20 ++++++++++++++++++++ templates/questionnairePage/deleteData.tpl | 1 - templates/questionnairePage/index.tpl | 1 - templates/questionnairePage/responses.tpl | 1 - 4 files changed, 20 insertions(+), 3 deletions(-) diff --git a/pages/demographic/QuestionnaireHandler.php b/pages/demographic/QuestionnaireHandler.php index ddbcb26..8a39467 100644 --- a/pages/demographic/QuestionnaireHandler.php +++ b/pages/demographic/QuestionnaireHandler.php @@ -24,6 +24,7 @@ public function index($args, $request) $queryParams = $request->getQueryArray(); $author = Repo::author()->get((int) $queryParams['authorId']); + $this->addQuestionnairePageStyleSheet($plugin, $request, $templateMgr); $demographicDataService = new DemographicDataService(); $authorToken = $queryParams['authorToken']; @@ -103,6 +104,8 @@ public function saveQuestionnaire($args, $request) $plugin = PluginRegistry::getPlugin('generic', 'demographicdataplugin'); $templateMgr = TemplateManager::getManager($request); + $this->addQuestionnairePageStyleSheet($plugin, $request, $templateMgr); + if (!$this->authorTokenIsValid($author, $authorToken)) { $templateMgr->assign('messageToDisplay', __('plugins.generic.demographicData.questionnairePage.accessDenied')); return $templateMgr->display($plugin->getTemplateResource('questionnairePage/displayMessage.tpl')); @@ -142,6 +145,8 @@ public function deleteData($args, $request) $plugin = PluginRegistry::getPlugin('generic', 'demographicdataplugin'); $templateMgr = TemplateManager::getManager($request); + $this->addQuestionnairePageStyleSheet($plugin, $request, $templateMgr); + if (!$this->authorTokenIsValid($author, $authorToken)) { $templateMgr->assign('messageToDisplay', __('plugins.generic.demographicData.questionnairePage.accessDenied')); return $templateMgr->display($plugin->getTemplateResource('questionnairePage/displayMessage.tpl')); @@ -182,6 +187,8 @@ public function orcidVerify($args, $request) $templateMgr = TemplateManager::getManager($request); $contextId = $request->getContext()->getId(); + $this->addQuestionnairePageStyleSheet($plugin, $request, $templateMgr); + if ($request->getUserVar('error') == 'access_denied') { $templateMgr->assign('messageToDisplay', __('plugins.generic.demographicData.questionnairePage.orcidAccessDenied')); return $templateMgr->display($plugin->getTemplateResource('questionnairePage/displayMessage.tpl')); @@ -220,4 +227,17 @@ public function orcidVerify($args, $request) $request->redirect(null, null, 'index', null, ['authorId' => $author->getId(), 'authorToken' => $request->getUserVar('authorToken')]); } + + private function addQuestionnairePageStyleSheet($plugin, $request, $templateMgr) + { + $templateMgr->addStyleSheet( + 'questionnairePageStyleSheet', + $request->getBaseUrl() . '/' . $plugin->getPluginPath() . '/styles/questionnairePage.css', + [ + 'priority' => TemplateManager::STYLE_SEQUENCE_LAST, + 'contexts' => ['frontend'], + 'inline' => false, + ] + ); + } } diff --git a/templates/questionnairePage/deleteData.tpl b/templates/questionnairePage/deleteData.tpl index 984f9f8..470df9c 100644 --- a/templates/questionnairePage/deleteData.tpl +++ b/templates/questionnairePage/deleteData.tpl @@ -2,7 +2,6 @@ {translate key="plugins.generic.demographicData.questionnairePage.deleteData.title"} {/capture} - {include file="frontend/components/header.tpl" pageTitleTranslated=$pageTitle}
diff --git a/templates/questionnairePage/index.tpl b/templates/questionnairePage/index.tpl index 9623c9d..1a24414 100644 --- a/templates/questionnairePage/index.tpl +++ b/templates/questionnairePage/index.tpl @@ -2,7 +2,6 @@ {translate key="plugins.generic.demographicData.questionnairePage.index.title"} {/capture} - {include file="frontend/components/header.tpl" pageTitleTranslated=$pageTitle}
diff --git a/templates/questionnairePage/responses.tpl b/templates/questionnairePage/responses.tpl index c1d388d..b350bb4 100644 --- a/templates/questionnairePage/responses.tpl +++ b/templates/questionnairePage/responses.tpl @@ -2,7 +2,6 @@ {translate key="plugins.generic.demographicData.questionnairePage.responses.title"} {/capture} - {include file="frontend/components/header.tpl" pageTitleTranslated=$pageTitle}
From c794d328539674994c65e4ba62471f649bc47315 Mon Sep 17 00:00:00 2001 From: Jhon Date: Fri, 11 Oct 2024 17:35:07 -0400 Subject: [PATCH 03/19] Creates DAO test for response option Issue: documentacao-e-tarefas/scielo#706 Signed-off-by: Jhon --- classes/demographicResponseOption/DAO.php | 71 +++++++++++++++++++++ classes/migrations/SchemaMigration.php | 32 +++++++++- schemas/demographicResponseOption.json | 20 ++++++ tests/demographicResponseOption/DAOTest.php | 64 +++++++++++++++++++ tests/helpers/TestHelperTrait.php | 10 +++ 5 files changed, 196 insertions(+), 1 deletion(-) create mode 100644 classes/demographicResponseOption/DAO.php create mode 100644 schemas/demographicResponseOption.json create mode 100644 tests/demographicResponseOption/DAOTest.php diff --git a/classes/demographicResponseOption/DAO.php b/classes/demographicResponseOption/DAO.php new file mode 100644 index 0000000..2787c1c --- /dev/null +++ b/classes/demographicResponseOption/DAO.php @@ -0,0 +1,71 @@ + 'demographic_response_option_id', + 'demographicQuestionId' => 'demographic_question_id', + ]; + + public function getParentColumn(): string + { + return 'demographic_question_id'; + } + + public function newDataObject(): DemographicResponseOption + { + return app(DemographicResponseOption::class); + } + + public function insert(DemographicResponseOption $demographicResponseOption): int + { + return parent::_insert($demographicResponseOption); + } + + public function delete(DemographicResponseOption $demographicResponseOption) + { + return parent::_delete($demographicResponseOption); + } + + public function update(DemographicResponseOption $demographicResponseOption) + { + return parent::_update($demographicResponseOption); + } + + public function getCount(Collector $query): int + { + return $query + ->getQueryBuilder() + ->count(); + } + + public function getMany(Collector $query): LazyCollection + { + $rows = $query + ->getQueryBuilder() + ->get(); + + return LazyCollection::make(function () use ($rows) { + foreach ($rows as $row) { + yield $row->demographic_response_option_id => $this->fromRow($row); + } + }); + } + + public function fromRow(object $row): DemographicResponseOption + { + return parent::fromRow($row); + } +} diff --git a/classes/migrations/SchemaMigration.php b/classes/migrations/SchemaMigration.php index cecfe54..8889c09 100644 --- a/classes/migrations/SchemaMigration.php +++ b/classes/migrations/SchemaMigration.php @@ -29,12 +29,38 @@ public function up(): void $table->string('setting_name', 255); $table->longText('setting_value')->nullable(); + $table->foreign('demographic_question_id') + ->references('demographic_question_id') + ->on('demographic_questions') + ->onDelete('cascade'); $table->index(['demographic_question_id'], 'demographic_question_settings_id'); $table->unique(['demographic_question_id', 'locale', 'setting_name'], 'demographic_question_settings_pkey'); }); + Schema::create('demographic_response_options', function (Blueprint $table) { + $table->bigInteger('demographic_response_option_id')->autoIncrement(); + $table->bigInteger('demographic_question_id'); + + $table->foreign('demographic_question_id') + ->references('demographic_question_id') + ->on('demographic_questions') + ->onDelete('cascade'); + $table->index(['demographic_question_id'], 'demographic_response_options_demographic_question_id'); + }); + + Schema::create('demographic_response_option_settings', function (Blueprint $table) { + $table->bigIncrements('demographic_response_option_setting_id'); + $table->bigInteger('demographic_response_option_id'); + $table->string('locale', 14)->default(''); + $table->string('setting_name', 255); + $table->longText('setting_value')->nullable(); + + $table->index(['demographic_response_option_id'], 'demographic_response_option_settings_id'); + $table->unique(['demographic_response_option_id', 'locale', 'setting_name'], 'demographic_response_option_settings_pkey'); + }); + Schema::create('demographic_responses', function (Blueprint $table) { - $table->bigIncrements('demographic_response_id'); + $table->bigInteger('demographic_response_id')->autoIncrement(); $table->bigInteger('demographic_question_id'); $table->bigInteger('user_id')->nullable(); $table->string('external_id', 255)->nullable(); @@ -60,6 +86,10 @@ public function up(): void $table->string('setting_name', 255); $table->longText('setting_value')->nullable(); + $table->foreign('demographic_response_id') + ->references('demographic_response_id') + ->on('demographic_responses') + ->onDelete('cascade'); $table->index(['demographic_response_id'], 'demographic_response_setting_id'); $table->unique(['demographic_response_id', 'locale', 'setting_name'], 'demographic_response_settings_pkey'); }); diff --git a/schemas/demographicResponseOption.json b/schemas/demographicResponseOption.json new file mode 100644 index 0000000..71ff3ed --- /dev/null +++ b/schemas/demographicResponseOption.json @@ -0,0 +1,20 @@ +{ + "title": "Demographic response option", + "description": "A response option for a given demographic question", + "properties": { + "id": { + "type": "integer", + "readOnly": true + }, + "demographicQuestionId": { + "type": "integer" + }, + "optionText": { + "type": "string", + "multilingual": true + }, + "hasInputField": { + "type": "boolean" + } + } +} diff --git a/tests/demographicResponseOption/DAOTest.php b/tests/demographicResponseOption/DAOTest.php new file mode 100644 index 0000000..305935e --- /dev/null +++ b/tests/demographicResponseOption/DAOTest.php @@ -0,0 +1,64 @@ +demographicResponseOptionDAO = app(DAO::class); + $this->addSchemaFile('demographicQuestion'); + $this->addSchemaFile('demographicResponseOption'); + $this->contextId = $this->createJournalMock(); + $this->demographicQuestionId = $this->createDemographicQuestion(); + $this->userId = $this->createUserMock(); + } + + public function testNewDataObjectIsInstanceOfDemographicResponseOption(): void + { + $demographicResponseOption = $this->demographicResponseOptionDAO->newDataObject(); + self::assertInstanceOf(DemographicResponseOption::class, $demographicResponseOption); + } + + public function testCreateDemographicResponseOption(): void + { + $demographicResponseOption = $this->createDemographicResponseOptionObject(); + $insertedObjectId = $this->demographicResponseOptionDAO->insert($demographicResponseOption); + + $fetchedDemographicResponseOption = $this->demographicResponseOptionDAO->get( + $insertedObjectId, + $this->demographicQuestionId + ); + + self::assertEquals([ + 'id' => $insertedObjectId, + 'demographicQuestionId' => $this->demographicQuestionId, + 'optionText' => [self::DEFAULT_LOCALE => 'First response option, with input field'], + 'hasInputField' => true, + ], $fetchedDemographicResponseOption->getAllData()); + } +} diff --git a/tests/helpers/TestHelperTrait.php b/tests/helpers/TestHelperTrait.php index 1461f4a..87e25d2 100644 --- a/tests/helpers/TestHelperTrait.php +++ b/tests/helpers/TestHelperTrait.php @@ -33,6 +33,16 @@ private function createDemographicQuestion() return $repository->add($demographicQuestion); } + private function createDemographicResponseOptionObject() + { + $demographicResponseOption = $this->demographicResponseOptionDAO->newDataObject(); + $demographicResponseOption->setDemographicQuestionId($this->demographicQuestionId); + $demographicResponseOption->setOptionText('First response option, with input field', self::DEFAULT_LOCALE); + $demographicResponseOption->setHasInputField(true); + + return $demographicResponseOption; + } + private function createDemographicResponseObject($externalAuthor = false) { $demographicResponse = $this->demographicResponseDAO->newDataObject(); From 8391ad9f6af8497fa1bf227372848d1a2571f910 Mon Sep 17 00:00:00 2001 From: Jhon Date: Fri, 11 Oct 2024 17:57:42 -0400 Subject: [PATCH 04/19] Finishes DAO test for response option Issue: documentacao-e-tarefas/scielo#706 Signed-off-by: Jhon --- tests/demographicResponseOption/DAOTest.php | 35 +++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/tests/demographicResponseOption/DAOTest.php b/tests/demographicResponseOption/DAOTest.php index 305935e..aabd947 100644 --- a/tests/demographicResponseOption/DAOTest.php +++ b/tests/demographicResponseOption/DAOTest.php @@ -61,4 +61,39 @@ public function testCreateDemographicResponseOption(): void 'hasInputField' => true, ], $fetchedDemographicResponseOption->getAllData()); } + + public function testEditDemographicResponseOption(): void + { + $demographicResponseOption = $this->createDemographicResponseOptionObject(); + $insertedObjectId = $this->demographicResponseOptionDAO->insert($demographicResponseOption); + + $fetchedDemographicResponseOption = $this->demographicResponseOptionDAO->get( + $insertedObjectId, + $this->demographicQuestionId + ); + $fetchedDemographicResponseOption->setOptionText('Updated text', self::DEFAULT_LOCALE); + + $this->demographicResponseOptionDAO->update($fetchedDemographicResponseOption); + + $objectEdited = $this->demographicResponseOptionDAO->get( + $insertedObjectId, + $this->demographicQuestionId + ); + + self::assertEquals($objectEdited->getData('optionText'), [self::DEFAULT_LOCALE => 'Updated text']); + } + + public function testDeleteDemographicResponseOption(): void + { + $demographicResponseOption = $this->createDemographicResponseOptionObject(); + $insertedObjectId = $this->demographicResponseOptionDAO->insert($demographicResponseOption); + + $fetchedDemographicResponseOption = $this->demographicResponseOptionDAO->get( + $insertedObjectId, + $this->demographicQuestionId + ); + + $this->demographicResponseOptionDAO->delete($fetchedDemographicResponseOption); + self::assertFalse($this->demographicResponseOptionDAO->exists($insertedObjectId, $this->contextId)); + } } From dc18d4344e962c7097bd15be179ae820ba5d1ea6 Mon Sep 17 00:00:00 2001 From: Jhon Date: Mon, 14 Oct 2024 15:19:50 -0400 Subject: [PATCH 05/19] Creates repository and collector for response options Issue: documentacao-e-tarefas/scielo#706 Signed-off-by: Jhon --- .../demographicResponseOption/Collector.php | 52 ++++++++++++ .../demographicResponseOption/Repository.php | 58 +++++++++++++ tests/demographicResponseOption/DAOTest.php | 2 - .../RepositoryTest.php | 83 +++++++++++++++++++ 4 files changed, 193 insertions(+), 2 deletions(-) create mode 100644 classes/demographicResponseOption/Collector.php create mode 100644 classes/demographicResponseOption/Repository.php create mode 100644 tests/demographicResponseOption/RepositoryTest.php diff --git a/classes/demographicResponseOption/Collector.php b/classes/demographicResponseOption/Collector.php new file mode 100644 index 0000000..0cb2062 --- /dev/null +++ b/classes/demographicResponseOption/Collector.php @@ -0,0 +1,52 @@ +dao = $dao; + } + + public function filterByQuestionIds(?array $questionIds): Collector + { + $this->questionIds = $questionIds; + return $this; + } + + public function getQueryBuilder(): Builder + { + $queryBuilder = DB::table($this->dao->table . ' AS dro') + ->select(['dro.*']); + + if (isset($this->questionIds)) { + $queryBuilder->whereIn('dro.demographic_question_id', $this->questionIds); + } + + return $queryBuilder; + } + + public function getCount(): int + { + return $this->dao->getCount($this); + } + + public function getIds(): Collection + { + return $this->dao->getIds($this); + } + + public function getMany(): LazyCollection + { + return $this->dao->getMany($this); + } +} diff --git a/classes/demographicResponseOption/Repository.php b/classes/demographicResponseOption/Repository.php new file mode 100644 index 0000000..810d443 --- /dev/null +++ b/classes/demographicResponseOption/Repository.php @@ -0,0 +1,58 @@ +dao = $dao; + } + + public function newDataObject(array $params = []): DemographicResponseOption + { + $object = $this->dao->newDataObject(); + if (!empty($params)) { + $object->setAllData($params); + } + return $object; + } + + public function get(int $id, int $demographicQuestionId = null): ?DemographicResponseOption + { + return $this->dao->get($id, $demographicQuestionId); + } + + public function add(DemographicResponseOption $demographicResponseOption): int + { + $id = $this->dao->insert($demographicResponseOption); + return $id; + } + + public function edit(DemographicResponseOption $demographicResponseOption, array $params) + { + $newDemographicResponseOption = clone $demographicResponseOption; + $newDemographicResponseOption->setAllData(array_merge($newDemographicResponseOption->_data, $params)); + + $this->dao->update($newDemographicResponseOption); + } + + public function delete(DemographicResponseOption $demographicResponseOption) + { + $this->dao->delete($demographicResponseOption); + } + + public function exists(int $id, int $demographicQuestionId = null): bool + { + return $this->dao->exists($id, $demographicQuestionId); + } + + public function getCollector(): Collector + { + return app(Collector::class); + } +} diff --git a/tests/demographicResponseOption/DAOTest.php b/tests/demographicResponseOption/DAOTest.php index aabd947..3619525 100644 --- a/tests/demographicResponseOption/DAOTest.php +++ b/tests/demographicResponseOption/DAOTest.php @@ -14,7 +14,6 @@ class DAOTest extends DatabaseTestCase private $demographicResponseOptionDAO; private $demographicQuestionId; private $contextId; - private $userId; protected function getAffectedTables(): array { @@ -35,7 +34,6 @@ protected function setUp(): void $this->addSchemaFile('demographicResponseOption'); $this->contextId = $this->createJournalMock(); $this->demographicQuestionId = $this->createDemographicQuestion(); - $this->userId = $this->createUserMock(); } public function testNewDataObjectIsInstanceOfDemographicResponseOption(): void diff --git a/tests/demographicResponseOption/RepositoryTest.php b/tests/demographicResponseOption/RepositoryTest.php new file mode 100644 index 0000000..282300e --- /dev/null +++ b/tests/demographicResponseOption/RepositoryTest.php @@ -0,0 +1,83 @@ +addSchemaFile('demographicQuestion'); + $this->addSchemaFile('demographicResponseOption'); + $this->demographicQuestionId = $this->createDemographicQuestion(); + $this->params = [ + 'demographicQuestionId' => $this->demographicQuestionId, + 'optionText' => [self::DEFAULT_LOCALE => 'First response option, with input field'], + 'hasInputField' => true, + ]; + } + + public function testGetNewDemographicResponseOptionObject(): void + { + $repository = app(Repository::class); + $responseOption = $repository->newDataObject(); + self::assertInstanceOf(DemographicResponseOption::class, $responseOption); + $responseOption = $repository->newDataObject($this->params); + self::assertEquals($this->params, $responseOption->_data); + } + + public function testResponseOptionCrud(): void + { + $repository = app(Repository::class); + $responseOption = $repository->newDataObject($this->params); + $insertedResponseOptionId = $repository->add($responseOption); + $this->params['id'] = $insertedResponseOptionId; + + $fetchedResponseOption = $repository->get($insertedResponseOptionId); + self::assertEquals($this->params, $fetchedResponseOption->getAllData()); + + $this->params['optionText']['en'] = 'Updated text'; + $repository->edit($responseOption, $this->params); + + $fetchedResponseOption = $repository->get($responseOption->getId()); + self::assertEquals($this->params, $fetchedResponseOption->getAllData()); + + $repository->delete($responseOption); + self::assertFalse($repository->exists($responseOption->getId())); + } + + public function testCollectorFilterByQuestion(): void + { + $repository = app(Repository::class); + $responseOption = $repository->newDataObject($this->params); + + $repository->add($responseOption); + + $responseOptions = $repository->getCollector() + ->filterByQuestionIds([$this->demographicQuestionId]) + ->getMany(); + + self::assertTrue(in_array($responseOption, $responseOptions->all())); + } +} From 65be429403fa1e6fabe314deec08db0547055628 Mon Sep 17 00:00:00 2001 From: Jhon Date: Mon, 14 Oct 2024 15:57:55 -0400 Subject: [PATCH 06/19] Removes part of possible responses from demographic questions Issue: documentacao-e-tarefas/scielo#706 Signed-off-by: Jhon --- classes/DemographicDataService.php | 17 ++--------- .../DemographicQuestion.php | 15 ---------- classes/test/DefaultTestQuestionsCreator.php | 28 ++----------------- schemas/demographicQuestion.json | 10 ------- tests/demographicQuestion/DAOTest.php | 6 +--- .../DemographicQuestionTest.php | 14 ---------- tests/demographicQuestion/RepositoryTest.php | 4 --- tests/helpers/TestHelperTrait.php | 3 -- 8 files changed, 7 insertions(+), 90 deletions(-) diff --git a/classes/DemographicDataService.php b/classes/DemographicDataService.php index 2aa9d48..9672ded 100644 --- a/classes/DemographicDataService.php +++ b/classes/DemographicDataService.php @@ -25,8 +25,7 @@ public function retrieveAllQuestions(int $contextId, bool $shouldRetrieveRespons 'type' => $demographicQuestion->getQuestionType(), 'inputType' => $demographicQuestion->getQuestionInputType(), 'title' => $demographicQuestion->getLocalizedQuestionText(), - 'description' => $demographicQuestion->getLocalizedQuestionDescription(), - 'possibleResponses' => $demographicQuestion->getLocalizedPossibleResponses() + 'description' => $demographicQuestion->getLocalizedQuestionDescription() ]; if ($shouldRetrieveResponses) { @@ -144,21 +143,11 @@ private function getResponseValueForDisplay($question, $response): string $question->getQuestionType() == DemographicQuestion::TYPE_CHECKBOXES || $question->getQuestionType() == DemographicQuestion::TYPE_RADIO_BUTTONS ) { - $possibleResponses = $question->getLocalizedPossibleResponses(); - $selectedResponsesValues = []; - - foreach ($response->getValue() as $selectedResponse) { - $selectedResponsesValues[] = $possibleResponses[$selectedResponse]; - } - - return implode(', ', $selectedResponsesValues); + return ''; } if ($question->getQuestionType() == DemographicQuestion::TYPE_DROP_DOWN_BOX) { - $possibleResponses = $question->getLocalizedPossibleResponses(); - $selectedResponse = $response->getValue(); - - return $possibleResponses[$selectedResponse]; + return ''; } return ''; diff --git a/classes/demographicQuestion/DemographicQuestion.php b/classes/demographicQuestion/DemographicQuestion.php index 43a98fa..0bafae3 100644 --- a/classes/demographicQuestion/DemographicQuestion.php +++ b/classes/demographicQuestion/DemographicQuestion.php @@ -76,19 +76,4 @@ public function setQuestionDescription($descriptionText, $locale) { $this->setData('questionDescription', $descriptionText, $locale); } - - public function getPossibleResponses($locale) - { - return $this->getData('possibleResponses', $locale); - } - - public function setPossibleResponses($possibleResponses, $locale) - { - $this->setData('possibleResponses', $possibleResponses, $locale); - } - - public function getLocalizedPossibleResponses() - { - return $this->getLocalizedData('possibleResponses'); - } } diff --git a/classes/test/DefaultTestQuestionsCreator.php b/classes/test/DefaultTestQuestionsCreator.php index d6f8c69..678bc83 100644 --- a/classes/test/DefaultTestQuestionsCreator.php +++ b/classes/test/DefaultTestQuestionsCreator.php @@ -57,41 +57,19 @@ private function getDefaultTestQuestionsData(int $contextId): array 'contextId' => $contextId, 'questionType' => DemographicQuestion::TYPE_CHECKBOXES, 'questionText' => ['en' => 'Languages'], - 'questionDescription' => ['en' => 'Which of these languages do you speak?'], - 'possibleResponses' => [ - 'en' => ['English', 'French', 'Hindi', 'Mandarin', 'Portuguese', 'Spanish'], - 'fr_CA' => ['Anglais', 'Français', 'Hindi', 'Mandarin', 'Portugais', 'Espagnol'] - ] + 'questionDescription' => ['en' => 'Which of these languages do you speak?'] ], [ 'contextId' => $contextId, 'questionType' => DemographicQuestion::TYPE_RADIO_BUTTONS, 'questionText' => ['en' => 'Nacionality'], - 'questionDescription' => ['en' => 'Which continent are you from?'], - 'possibleResponses' => [ - 'en' => ['Africa', 'America', 'Asia', 'Europe', 'Oceania'], - 'fr_CA' => ['Afrique', 'Amérique', 'Asie', 'Europe', 'Océanie'] - ] + 'questionDescription' => ['en' => 'Which continent are you from?'] ], [ 'contextId' => $contextId, 'questionType' => DemographicQuestion::TYPE_DROP_DOWN_BOX, 'questionText' => ['en' => 'Salary'], - 'questionDescription' => ['en' => 'What range is your current salary in?'], - 'possibleResponses' => [ - 'en' => [ - 'Less than a minimum wage', - 'One to three minimum wages', - 'Three to five minimum wages', - 'More than five minimum wages' - ], - 'fr_CA' => [ - "Moins qu'un salaire minimum", - 'Un à trois salaires minimums', - 'Trois à cinq salaires minimums', - 'Plus de cinq salaires minimums' - ] - ] + 'questionDescription' => ['en' => 'What range is your current salary in?'] ] ]; } diff --git a/schemas/demographicQuestion.json b/schemas/demographicQuestion.json index 63e9a7d..a030ec2 100644 --- a/schemas/demographicQuestion.json +++ b/schemas/demographicQuestion.json @@ -19,16 +19,6 @@ "questionDescription": { "type": "string", "multilingual": true - }, - "possibleResponses": { - "type": "array", - "items": { - "type": "string" - }, - "multilingual": true, - "validation": [ - "nullable" - ] } } } diff --git a/tests/demographicQuestion/DAOTest.php b/tests/demographicQuestion/DAOTest.php index 43615bb..0ace3f0 100644 --- a/tests/demographicQuestion/DAOTest.php +++ b/tests/demographicQuestion/DAOTest.php @@ -56,10 +56,7 @@ public function testCreateDemographicQuestion(): void 'contextId' => $this->contextId, 'questionType' => DemographicQuestion::TYPE_RADIO_BUTTONS, 'questionText' => [$locale => 'Test text'], - 'questionDescription' => [$locale => 'Test description'], - 'possibleResponses' => [ - $locale => ['First possible response', 'Second possible response'] - ] + 'questionDescription' => [$locale => 'Test description'] ], $fetchedDemographicQuestion->_data); } @@ -109,7 +106,6 @@ private function createDemographicQuestionObject($locale) $demographicQuestion->setQuestionType(DemographicQuestion::TYPE_RADIO_BUTTONS); $demographicQuestion->setQuestionText('Test text', $locale); $demographicQuestion->setQuestionDescription('Test description', $locale); - $demographicQuestion->setPossibleResponses(['First possible response', 'Second possible response'], $locale); return $demographicQuestion; } diff --git a/tests/demographicQuestion/DemographicQuestionTest.php b/tests/demographicQuestion/DemographicQuestionTest.php index 03de375..d177959 100644 --- a/tests/demographicQuestion/DemographicQuestionTest.php +++ b/tests/demographicQuestion/DemographicQuestionTest.php @@ -71,18 +71,4 @@ public function testGetQuestionDescription(): void $questionDescription = $this->demographicQuestion->getLocalizedQuestionDescription(); $this->assertEquals($expectedQuestionDescription, $questionDescription); } - - public function testGetQuestionPossibleResponses(): void - { - $expectedPossibleResponses = [ - 'en' => ['Black', 'Latin', 'Asian', 'Other'], - 'pt_BR' => ['Negro(a)', 'Latino(a)', 'Asiático(a)', 'Outro(a)'] - ]; - - $this->demographicQuestion->setPossibleResponses($expectedPossibleResponses['en'], 'en'); - $this->demographicQuestion->setPossibleResponses($expectedPossibleResponses['pt_BR'], 'pt_BR'); - - $this->assertEquals($expectedPossibleResponses['en'], $this->demographicQuestion->getPossibleResponses('en')); - $this->assertEquals($expectedPossibleResponses['pt_BR'], $this->demographicQuestion->getPossibleResponses('pt_BR')); - } } diff --git a/tests/demographicQuestion/RepositoryTest.php b/tests/demographicQuestion/RepositoryTest.php index ed49d70..9602218 100644 --- a/tests/demographicQuestion/RepositoryTest.php +++ b/tests/demographicQuestion/RepositoryTest.php @@ -39,9 +39,6 @@ protected function setUp(): void ], 'questionDescription' => [ $this->locale => 'Test description' - ], - 'possibleResponses' => [ - $this->locale => ['First possible response', 'Second possible response'] ] ]; $this->addSchemaFile('demographicQuestion'); @@ -68,7 +65,6 @@ public function testCrud(): void $this->params['questionText'][$this->locale] = 'Updated text'; $this->params['questionDescription'][$this->locale] = 'Updated description'; - $this->params['possibleResponses'][$this->locale] = ['New first possible response', 'New second possible response']; $repository->edit($demographicQuestion, $this->params); $fetchedDemographicQuestion = $repository->get($demographicQuestion->getId(), $this->contextId); diff --git a/tests/helpers/TestHelperTrait.php b/tests/helpers/TestHelperTrait.php index 87e25d2..9b1bda0 100644 --- a/tests/helpers/TestHelperTrait.php +++ b/tests/helpers/TestHelperTrait.php @@ -22,9 +22,6 @@ private function createDemographicQuestion() 'questionType' => DemographicQuestion::TYPE_TEXTAREA, 'questionDescription' => [ self::DEFAULT_LOCALE => 'Test description' - ], - 'possibleResponses' => [ - self::DEFAULT_LOCALE => ['First possible response', 'Second possible response'] ] ]; From 794a198d3ef9db0bb8651b9fd87ceeeb59353114 Mon Sep 17 00:00:00 2001 From: Jhon Date: Mon, 14 Oct 2024 16:15:26 -0400 Subject: [PATCH 07/19] Adds demographic response option repository in facade class Issue: documentacao-e-tarefas/scielo#706 Signed-off-by: Jhon --- classes/facades/Repo.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/classes/facades/Repo.php b/classes/facades/Repo.php index f5fc9d4..f8fc41c 100644 --- a/classes/facades/Repo.php +++ b/classes/facades/Repo.php @@ -4,6 +4,7 @@ use APP\plugins\generic\demographicData\classes\demographicQuestion\Repository as DemographicQuestionRepository; use APP\plugins\generic\demographicData\classes\demographicResponse\Repository as DemographicResponseRepository; +use APP\plugins\generic\demographicData\classes\demographicResponseOption\Repository as DemographicResponseOptionRepository; class Repo extends \APP\facades\Repo { @@ -16,4 +17,9 @@ public static function demographicResponse(): DemographicResponseRepository { return app(DemographicResponseRepository::class); } + + public static function demographicResponseOption(): DemographicResponseOptionRepository + { + return app(DemographicResponseOptionRepository::class); + } } From abd6050beb5255b7e53ccd812ad1d3c9b79578c5 Mon Sep 17 00:00:00 2001 From: Jhon Date: Mon, 14 Oct 2024 17:48:41 -0400 Subject: [PATCH 08/19] Changes test questions creation, using new response option class Also adds foreign key in response option settings table Issue: documentacao-e-tarefas/scielo#706 Signed-off-by: Jhon --- DemographicDataPlugin.php | 1 + classes/migrations/SchemaMigration.php | 6 +- classes/test/DefaultTestQuestionsCreator.php | 98 +++++++++++++++++++- 3 files changed, 100 insertions(+), 5 deletions(-) diff --git a/DemographicDataPlugin.php b/DemographicDataPlugin.php index f47cf61..0b53ea4 100644 --- a/DemographicDataPlugin.php +++ b/DemographicDataPlugin.php @@ -33,6 +33,7 @@ public function register($category, $path, $mainContextId = null): bool Hook::add('Schema::get::author', [$this, 'editAuthorSchema']); Hook::add('Schema::get::demographicQuestion', [$this, 'addCustomSchema']); Hook::add('Schema::get::demographicResponse', [$this, 'addCustomSchema']); + Hook::add('Schema::get::demographicResponseOption', [$this, 'addCustomSchema']); Hook::add('Decision::add', [$this, 'requestDataExternalContributors']); Hook::add('User::edit', [$this, 'checkMigrateResponsesOrcid']); diff --git a/classes/migrations/SchemaMigration.php b/classes/migrations/SchemaMigration.php index 8889c09..6141197 100644 --- a/classes/migrations/SchemaMigration.php +++ b/classes/migrations/SchemaMigration.php @@ -55,7 +55,11 @@ public function up(): void $table->string('setting_name', 255); $table->longText('setting_value')->nullable(); - $table->index(['demographic_response_option_id'], 'demographic_response_option_settings_id'); + $table->foreign('demographic_response_option_id', 'demographic_response_option_settings_option_id') + ->references('demographic_response_option_id') + ->on('demographic_response_options') + ->onDelete('cascade'); + $table->index(['demographic_response_option_id'], 'demographic_response_option_settings_option_id'); $table->unique(['demographic_response_option_id', 'locale', 'setting_name'], 'demographic_response_option_settings_pkey'); }); diff --git a/classes/test/DefaultTestQuestionsCreator.php b/classes/test/DefaultTestQuestionsCreator.php index 678bc83..db551fd 100644 --- a/classes/test/DefaultTestQuestionsCreator.php +++ b/classes/test/DefaultTestQuestionsCreator.php @@ -27,7 +27,15 @@ public function createDefaultTestQuestions() foreach ($defaultTestQuestions as $questionData) { $questionObject = Repo::demographicQuestion()->newDataObject($questionData); - Repo::demographicQuestion()->add($questionObject); + $demographicQuestionId = Repo::demographicQuestion()->add($questionObject); + + if (isset($questionData['responseOptions'])) { + foreach ($questionData['responseOptions'] as $optionData) { + $optionData['demographicQuestionId'] = $demographicQuestionId; + $responseOptionObject = Repo::demographicResponseOption()->newDataObject($optionData); + Repo::demographicResponseOption()->add($responseOptionObject); + } + } } } } @@ -57,19 +65,101 @@ private function getDefaultTestQuestionsData(int $contextId): array 'contextId' => $contextId, 'questionType' => DemographicQuestion::TYPE_CHECKBOXES, 'questionText' => ['en' => 'Languages'], - 'questionDescription' => ['en' => 'Which of these languages do you speak?'] + 'questionDescription' => ['en' => 'Which of these languages do you speak?'], + 'responseOptions' => [ + [ + 'optionText' => ['en' => 'English', 'fr_CA' => 'Anglais'], + 'hasInputField' => false + ], + [ + 'optionText' => ['en' => 'French', 'fr_CA' => 'Français'], + 'hasInputField' => false + ], + [ + 'optionText' => ['en' => 'Hindi', 'fr_CA' => 'Hindi'], + 'hasInputField' => false + ], + [ + 'optionText' => ['en' => 'Mandarin', 'fr_CA' => 'Mandarin'], + 'hasInputField' => false + ], + [ + 'optionText' => ['en' => 'Portuguese', 'fr_CA' => 'Portugais'], + 'hasInputField' => false + ], + [ + 'optionText' => ['en' => 'Spanish', 'fr_CA' => 'Espagnol'], + 'hasInputField' => false + ], + [ + 'optionText' => ['en' => 'Other:', 'fr_CA' => 'Autre:'], + 'hasInputField' => true + ] + ] ], [ 'contextId' => $contextId, 'questionType' => DemographicQuestion::TYPE_RADIO_BUTTONS, 'questionText' => ['en' => 'Nacionality'], - 'questionDescription' => ['en' => 'Which continent are you from?'] + 'questionDescription' => ['en' => 'Which continent are you from?'], + 'responseOptions' => [ + [ + 'optionText' => ['en' => 'Africa', 'fr_CA' => 'Afrique'], + 'hasInputField' => false + ], + [ + 'optionText' => ['en' => 'America', 'fr_CA' => 'Amérique'], + 'hasInputField' => false + ], + [ + 'optionText' => ['en' => 'Asia', 'fr_CA' => 'Asie'], + 'hasInputField' => false + ], + [ + 'optionText' => ['en' => 'Europe', 'fr_CA' => 'Europe'], + 'hasInputField' => false + ], + [ + 'optionText' => ['en' => 'Oceania', 'fr_CA' => 'Océanie'], + 'hasInputField' => false + ] + ] ], [ 'contextId' => $contextId, 'questionType' => DemographicQuestion::TYPE_DROP_DOWN_BOX, 'questionText' => ['en' => 'Salary'], - 'questionDescription' => ['en' => 'What range is your current salary in?'] + 'questionDescription' => ['en' => 'What range is your current salary in?'], + 'responseOptions' => [ + [ + 'optionText' => [ + 'en' => 'Less than a minimum wage', + 'fr_CA' => "Moins qu'un salaire minimum" + ], + 'hasInputField' => false + ], + [ + 'optionText' => [ + 'en' => 'One to three minimum wages', + 'fr_CA' => 'Un à trois salaires minimums' + ], + 'hasInputField' => false + ], + [ + 'optionText' => [ + 'en' => 'Three to five minimum wages', + 'fr_CA' => 'Trois à cinq salaires minimums' + ], + 'hasInputField' => false + ], + [ + 'optionText' => [ + 'en' => 'More than five minimum wages', + 'fr_CA' => 'Plus de cinq salaires minimums' + ], + 'hasInputField' => false + ] + ] ] ]; } From 93e8c64e1f3b0dc071aa68edd0d8c62076e77233 Mon Sep 17 00:00:00 2001 From: Jhon Date: Mon, 14 Oct 2024 18:46:06 -0400 Subject: [PATCH 09/19] Can show response options at profile editing page But still with no input field for options Issue: documentacao-e-tarefas/scielo#706 Signed-off-by: Jhon --- classes/DemographicDataService.php | 10 +++++++++- .../DemographicQuestion.php | 20 +++++++++++++++++++ templates/question.tpl | 18 ++++++++--------- 3 files changed, 38 insertions(+), 10 deletions(-) diff --git a/classes/DemographicDataService.php b/classes/DemographicDataService.php index 9672ded..f3e9811 100644 --- a/classes/DemographicDataService.php +++ b/classes/DemographicDataService.php @@ -25,9 +25,17 @@ public function retrieveAllQuestions(int $contextId, bool $shouldRetrieveRespons 'type' => $demographicQuestion->getQuestionType(), 'inputType' => $demographicQuestion->getQuestionInputType(), 'title' => $demographicQuestion->getLocalizedQuestionText(), - 'description' => $demographicQuestion->getLocalizedQuestionDescription() + 'description' => $demographicQuestion->getLocalizedQuestionDescription(), + 'responseOptions' => $demographicQuestion->getResponseOptions() ]; + if ($demographicQuestion->getQuestionType() == DemographicQuestion::TYPE_DROP_DOWN_BOX) { + $questionData['responseOptions'] = []; + foreach ($demographicQuestion->getResponseOptions() as $responseOption) { + $questionData['responseOptions'][$responseOption->getId()] = $responseOption->getLocalizedOptionText(); + } + } + if ($shouldRetrieveResponses) { $user = $request->getUser(); $response = $this->getUserResponse($demographicQuestion, $user->getId()); diff --git a/classes/demographicQuestion/DemographicQuestion.php b/classes/demographicQuestion/DemographicQuestion.php index 0bafae3..08c1804 100644 --- a/classes/demographicQuestion/DemographicQuestion.php +++ b/classes/demographicQuestion/DemographicQuestion.php @@ -2,6 +2,8 @@ namespace APP\plugins\generic\demographicData\classes\demographicQuestion; +use APP\plugins\generic\demographicData\classes\facades\Repo; + class DemographicQuestion extends \PKP\core\DataObject { public const TYPE_SMALL_TEXT_FIELD = 1; @@ -76,4 +78,22 @@ public function setQuestionDescription($descriptionText, $locale) { $this->setData('questionDescription', $descriptionText, $locale); } + + public function getResponseOptions() + { + if (is_null($this->getData('responseOptions'))) { + $responseOptions = Repo::demographicResponseOption()->getCollector() + ->filterByQuestionIds([$this->getId()]) + ->getMany(); + + $mappedResponseOptions = []; + foreach ($responseOptions as $responseOption) { + $mappedResponseOptions[$responseOption->getId()] = $responseOption; + } + + $this->setData('responseOptions', $mappedResponseOptions); + } + + return $this->getData('responseOptions'); + } } diff --git a/templates/question.tpl b/templates/question.tpl index 7f5869a..8121318 100644 --- a/templates/question.tpl +++ b/templates/question.tpl @@ -12,32 +12,32 @@ {elseif $question['type'] == $questionTypeConsts['TYPE_TEXTAREA']} {fbvElement type="textarea" multilingual="true" name=$questionId id="demographicResponses" value=$question['response'] required=true rich=false size=$fbvStyles.size.LARGE} {elseif $question['type'] == $questionTypeConsts['TYPE_CHECKBOXES']} - {foreach from=$question['possibleResponses'] key="possibleResponseValue" item="possibleResponseLabel"} + {foreach from=$question['responseOptions'] item="responseOption"} {fbvElement type="checkbox" name="{$questionId}[]" id="demographicResponses" - label=$possibleResponseLabel - value=$possibleResponseValue - checked=in_array($possibleResponseValue, $question['response']) + label=$responseOption->getLocalizedOptionText() + value=$responseOption->getId() + checked=in_array($responseOption->getId(), $question['response']) translate=false } {/foreach} {elseif $question['type'] == $questionTypeConsts['TYPE_RADIO_BUTTONS']} - {foreach from=$question['possibleResponses'] key="possibleResponseValue" item="possibleResponseLabel"} + {foreach from=$question['responseOptions'] item="responseOption"} {fbvElement type="radio" name="{$questionId}[]" id="demographicResponses" - label=$possibleResponseLabel - value=$possibleResponseValue - checked=in_array($possibleResponseValue, $question['response']) + label=$responseOption->getLocalizedOptionText() + value=$responseOption->getId() + checked=in_array($responseOption->getId(), $question['response']) required=true translate=false } {/foreach} {elseif $question['type'] == $questionTypeConsts['TYPE_DROP_DOWN_BOX']} - {fbvElement type="select" name=$questionId id="demographicResponses" from=$question['possibleResponses'] selected=$question['response'] translate=false required=true size=$fbvStyles.size.LARGE} + {fbvElement type="select" name=$questionId id="demographicResponses" from=$question['responseOptions'] selected=$question['response'] translate=false required=true size=$fbvStyles.size.LARGE} {/if} {/fbvFormSection} {/fbvFormSection} \ No newline at end of file From 3c4b8ed71200b486e1cc244f721f214f2784f183 Mon Sep 17 00:00:00 2001 From: Jhon Date: Tue, 15 Oct 2024 10:04:17 -0400 Subject: [PATCH 10/19] Can show response options at questionnaire page Issue: documentacao-e-tarefas/scielo#706 Signed-off-by: Jhon --- templates/questionnairePage/question.tpl | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/templates/questionnairePage/question.tpl b/templates/questionnairePage/question.tpl index 001acb8..62f331e 100644 --- a/templates/questionnairePage/question.tpl +++ b/templates/questionnairePage/question.tpl @@ -10,23 +10,23 @@ {elseif $question['type'] == $questionTypeConsts['TYPE_TEXTAREA']} {elseif $question['type'] == $questionTypeConsts['TYPE_CHECKBOXES']} - {foreach from=$question['possibleResponses'] key="possibleResponseValue" item="possibleResponseLabel"} + {foreach from=$question['responseOptions'] item="responseOption"}
{/foreach} {elseif $question['type'] == $questionTypeConsts['TYPE_RADIO_BUTTONS']} - {foreach from=$question['possibleResponses'] key="possibleResponseValue" item="possibleResponseLabel"} + {foreach from=$question['responseOptions'] item="responseOption"}
{/foreach} {elseif $question['type'] == $questionTypeConsts['TYPE_DROP_DOWN_BOX']} {/if} From 35a31cd5ceb1e430b020718c986f192cc057541e Mon Sep 17 00:00:00 2001 From: Jhon Date: Tue, 15 Oct 2024 15:02:34 -0400 Subject: [PATCH 11/19] External authors can view their responses back again Issue: documentacao-e-tarefas/scielo#706 Signed-off-by: Jhon --- classes/DemographicDataService.php | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/classes/DemographicDataService.php b/classes/DemographicDataService.php index f3e9811..68223ed 100644 --- a/classes/DemographicDataService.php +++ b/classes/DemographicDataService.php @@ -151,11 +151,22 @@ private function getResponseValueForDisplay($question, $response): string $question->getQuestionType() == DemographicQuestion::TYPE_CHECKBOXES || $question->getQuestionType() == DemographicQuestion::TYPE_RADIO_BUTTONS ) { - return ''; + $responseOptions = $question->getResponseOptions(); + $selectedResponseOptionsTexts = []; + + foreach ($response->getValue() as $selectedResponseOptionId) { + $selectedResponseOption = $responseOptions[$selectedResponseOptionId]; + $selectedResponseOptionsTexts[] = $selectedResponseOption->getLocalizedOptionText(); + } + + return implode(', ', $selectedResponseOptionsTexts); } if ($question->getQuestionType() == DemographicQuestion::TYPE_DROP_DOWN_BOX) { - return ''; + $responseOptions = $question->getResponseOptions(); + $selectedResponseOption = $responseOptions[$response->getValue()]; + + return $selectedResponseOption->getLocalizedOptionText(); } return ''; From e9fdc82e9c2aece7c0cb6454b0ac16a5a304d0a0 Mon Sep 17 00:00:00 2001 From: Jhon Date: Tue, 15 Oct 2024 15:42:01 -0400 Subject: [PATCH 12/19] Adds integration text - Input field for response option in profile page Issue: documentacao-e-tarefas/scielo#706 Signed-off-by: Jhon --- cypress/tests/Test1_questionsDisplaying.cy.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/cypress/tests/Test1_questionsDisplaying.cy.js b/cypress/tests/Test1_questionsDisplaying.cy.js index 6fb70bd..9a9f1ff 100644 --- a/cypress/tests/Test1_questionsDisplaying.cy.js +++ b/cypress/tests/Test1_questionsDisplaying.cy.js @@ -47,6 +47,10 @@ function answerDefaultQuestions() { cy.contains('label', 'Spanish').within(() => { cy.get('input').check(); }); + cy.contains('label', 'Other:').within(() => { + cy.get('input[type="checkbox"]').check(); + cy.get('input[type="text"]').clear().type('Japanese'); + }); cy.contains('label', 'America').within(() => { cy.get('input').check(); }); @@ -70,6 +74,10 @@ function assertResponsesToDefaultQuestions() { cy.contains('label', 'Spanish').within(() => { cy.get('input').should('be.checked'); }); + cy.contains('label', 'Other:').within(() => { + cy.get('input[type="checkbox"]').should('be.checked'); + cy.get('input[type="text"]').should('have.value', 'Japanese'); + }); cy.contains('label', 'America').within(() => { cy.get('input').should('be.checked'); }); @@ -83,6 +91,10 @@ function assertResponsesToQuestionsInFrench() { cy.contains('label', 'Espagnol').within(() => { cy.get('input').should('be.checked'); }); + cy.contains('label', 'Autre:').within(() => { + cy.get('input[type="checkbox"]').should('be.checked'); + cy.get('input[type="text"]').should('have.value', 'Japanese'); + }); cy.contains('label', 'Amérique').within(() => { cy.get('input').should('be.checked'); }); From 059ea1bb1d150a006ef2853d9f4c1bc0df9a03e9 Mon Sep 17 00:00:00 2001 From: Jhon Date: Tue, 15 Oct 2024 16:21:47 -0400 Subject: [PATCH 13/19] Adds options input value field to demographic response object Issue: documentacao-e-tarefas/scielo#706 Signed-off-by: Jhon --- classes/demographicResponse/DAO.php | 5 +++++ classes/demographicResponse/DemographicResponse.php | 10 ++++++++++ schemas/demographicResponse.json | 6 ++++++ tests/demographicResponse/DAOTest.php | 2 ++ tests/demographicResponse/DemographicResponseTest.php | 7 +++++++ tests/helpers/TestHelperTrait.php | 1 + 6 files changed, 31 insertions(+) diff --git a/classes/demographicResponse/DAO.php b/classes/demographicResponse/DAO.php index 74b6799..ea60720 100644 --- a/classes/demographicResponse/DAO.php +++ b/classes/demographicResponse/DAO.php @@ -76,6 +76,11 @@ public function fromRow(object $row): DemographicResponse $demographicResponse->setValue(unserialize($serializedValue)); } + if (@unserialize($demographicResponse->getOptionsInputValue())) { + $serializedValue = $demographicResponse->getOptionsInputValue(); + $demographicResponse->setOptionsInputValue(unserialize($serializedValue)); + } + return $demographicResponse; } } diff --git a/classes/demographicResponse/DemographicResponse.php b/classes/demographicResponse/DemographicResponse.php index 207f0fb..99617a7 100644 --- a/classes/demographicResponse/DemographicResponse.php +++ b/classes/demographicResponse/DemographicResponse.php @@ -53,4 +53,14 @@ public function setValue($responseValue) { $this->setData('responseValue', $responseValue); } + + public function getOptionsInputValue() + { + return $this->getData('optionsInputValue'); + } + + public function setOptionsInputValue($optionsInputValue) + { + $this->setData('optionsInputValue', $optionsInputValue); + } } diff --git a/schemas/demographicResponse.json b/schemas/demographicResponse.json index d6deede..808cd4a 100644 --- a/schemas/demographicResponse.json +++ b/schemas/demographicResponse.json @@ -32,6 +32,12 @@ "validation": [ "nullable" ] + }, + "optionsInputValue": { + "type": "string", + "validation": [ + "nullable" + ] } } } diff --git a/tests/demographicResponse/DAOTest.php b/tests/demographicResponse/DAOTest.php index 31f259b..c1ded02 100644 --- a/tests/demographicResponse/DAOTest.php +++ b/tests/demographicResponse/DAOTest.php @@ -58,6 +58,7 @@ public function testCreateDemographicResponse(): void 'id' => $insertedDemographicResponseId, 'demographicQuestionId' => $this->demographicQuestionId, 'responseValue' => [self::DEFAULT_LOCALE => 'Test text'], + 'optionsInputValue' => [45 => 'Aditional information for response option'], 'userId' => $this->userId, 'externalId' => null, 'externalType' => null @@ -78,6 +79,7 @@ public function testCreateDemographicResponseForExternalAuthor(): void 'id' => $insertedDemographicResponseId, 'demographicQuestionId' => $this->demographicQuestionId, 'responseValue' => [self::DEFAULT_LOCALE => 'Test text'], + 'optionsInputValue' => [45 => 'Aditional information for response option'], 'userId' => null, 'externalId' => 'external.author@lepidus.com.br', 'externalType' => 'email' diff --git a/tests/demographicResponse/DemographicResponseTest.php b/tests/demographicResponse/DemographicResponseTest.php index 814a5fe..752b36d 100644 --- a/tests/demographicResponse/DemographicResponseTest.php +++ b/tests/demographicResponse/DemographicResponseTest.php @@ -49,4 +49,11 @@ public function testGetDemographicResponseValue(): void $this->demographicResponse->setValue(['en' => "I'm from Parintins"]); $this->assertEquals($this->demographicResponse->getValue(), $expectedDemographicResponseValue); } + + public function testGetDemographicOptionsInputValue(): void + { + $expectedOptionsInputValue = [45 => 'Aditional information for response option']; + $this->demographicResponse->setOptionsInputValue([45 => 'Aditional information for response option']); + $this->assertEquals($this->demographicResponse->getOptionsInputValue(), $expectedOptionsInputValue); + } } diff --git a/tests/helpers/TestHelperTrait.php b/tests/helpers/TestHelperTrait.php index 9b1bda0..a055259 100644 --- a/tests/helpers/TestHelperTrait.php +++ b/tests/helpers/TestHelperTrait.php @@ -45,6 +45,7 @@ private function createDemographicResponseObject($externalAuthor = false) $demographicResponse = $this->demographicResponseDAO->newDataObject(); $demographicResponse->setDemographicQuestionId($this->demographicQuestionId); $demographicResponse->setValue([self::DEFAULT_LOCALE => 'Test text']); + $demographicResponse->setOptionsInputValue([45 => 'Aditional information for response option']); if ($externalAuthor) { $demographicResponse->setExternalId('external.author@lepidus.com.br'); From 78b53179f0ddf508f6d7a63bae94fae3dbcc6c92 Mon Sep 17 00:00:00 2001 From: Jhon Date: Tue, 15 Oct 2024 18:28:38 -0400 Subject: [PATCH 14/19] Can now save response option input fields in profile tab Issue: documentacao-e-tarefas/scielo#706 Signed-off-by: Jhon --- classes/DemographicDataService.php | 42 ++++++++++++++++++++++++------ classes/form/QuestionsForm.php | 7 ++++- templates/question.tpl | 34 +++++++++++++++++++----- 3 files changed, 68 insertions(+), 15 deletions(-) diff --git a/classes/DemographicDataService.php b/classes/DemographicDataService.php index 68223ed..b4804d8 100644 --- a/classes/DemographicDataService.php +++ b/classes/DemographicDataService.php @@ -38,9 +38,7 @@ public function retrieveAllQuestions(int $contextId, bool $shouldRetrieveRespons if ($shouldRetrieveResponses) { $user = $request->getUser(); - $response = $this->getUserResponse($demographicQuestion, $user->getId()); - - $questionData['response'] = $response; + $questionData['response'] = $this->getUserResponse($demographicQuestion, $user->getId()); } $questions[] = $questionData; @@ -63,17 +61,17 @@ private function getUserResponse(DemographicQuestion $question, int $userId) $question->getQuestionType() == DemographicQuestion::TYPE_CHECKBOXES || $question->getQuestionType() == DemographicQuestion::TYPE_RADIO_BUTTONS ) { - return []; + return ['value' => [], 'optionsInputValue' => []]; } - return null; + return ['value' => null]; } $firstResponse = array_shift($demographicResponses); - return $firstResponse->getValue(); + return ['value' => $firstResponse->getValue(), 'optionsInputValue' => $firstResponse->getOptionsInputValue()]; } - public function registerUserResponses(int $userId, array $responses) + public function registerUserResponses(int $userId, array $responses, array $responseOptionsInputs) { foreach ($responses as $question => $responseInput) { $questionId = explode("-", $question)[1]; @@ -84,18 +82,46 @@ public function registerUserResponses(int $userId, array $responses) ->getMany() ->toArray(); $demographicResponse = array_shift($demographicResponses); + + $optionsInputValue = $this->getResponseOptionsInputValue($questionId, $responseOptionsInputs, $responseInput); + if ($demographicResponse) { - Repo::demographicResponse()->edit($demographicResponse, ['responseValue' => $responseInput]); + Repo::demographicResponse()->edit($demographicResponse, [ + 'responseValue' => $responseInput, + 'optionsInputValue' => $optionsInputValue + ]); } else { $response = Repo::demographicResponse()->newDataObject(); $response->setUserId($userId); $response->setDemographicQuestionId($questionId); $response->setData('responseValue', $responseInput); + $response->setOptionsInputValue($optionsInputValue); Repo::demographicResponse()->add($response); } } } + private function getResponseOptionsInputValue($questionId, $responseOptionsInputs, $responseInput) + { + $demographicQuestion = Repo::demographicQuestion()->get($questionId); + + if ($demographicQuestion->getQuestionType() == DemographicQuestion::TYPE_CHECKBOXES + || $demographicQuestion->getQuestionType() == DemographicQuestion::TYPE_RADIO_BUTTONS + ) { + $responseOptionsInputValue = []; + foreach ($responseInput as $responseOptionId) { + $responseOptionInputName = "responseOptionInput-$responseOptionId"; + if (isset($responseOptionsInputs[$responseOptionInputName])) { + $responseOptionsInputValue[$responseOptionId] = $responseOptionsInputs[$responseOptionInputName]; + } + } + + return $responseOptionsInputValue; + } + + return null; + } + public function registerExternalAuthorResponses(string $externalId, string $externalType, array $responses) { $locale = Locale::getLocale(); diff --git a/classes/form/QuestionsForm.php b/classes/form/QuestionsForm.php index 0270b2f..f2945a5 100644 --- a/classes/form/QuestionsForm.php +++ b/classes/form/QuestionsForm.php @@ -35,13 +35,18 @@ public function __construct($request = null, $args = null) private function loadQuestionResponsesByForm($args) { $responses = []; + $responseOptionsInputs = []; + foreach ($args as $key => $value) { if (strpos($key, 'question-') === 0) { $responses[$key] = $value; + } elseif (strpos($key, 'responseOptionInput-') === 0) { + $responseOptionsInputs[$key] = $value; } } $this->setData('responses', $responses); + $this->setData('responseOptionsInputs', $responseOptionsInputs); } public function fetch($request, $template = null, $display = false) @@ -98,7 +103,7 @@ public function execute(...$functionArgs) $demographicDataDao->updateDemographicConsent($context->getId(), $user->getId(), $newConsent); if ($newConsent == '1') { - $demographicDataService->registerUserResponses($user->getId(), $this->getData('responses')); + $demographicDataService->registerUserResponses($user->getId(), $this->getData('responses'), $this->getData('responseOptionsInputs')); } elseif ($newConsent == '0' and $previousConsent) { $demographicDataService->deleteUserResponses($user->getId(), $context->getId()); } diff --git a/templates/question.tpl b/templates/question.tpl index 8121318..eb55974 100644 --- a/templates/question.tpl +++ b/templates/question.tpl @@ -6,11 +6,11 @@ {fbvFormSection title=$question['title'] required=true translate=false} {fbvFormSection for=$questionId description=$question['description'] translate=false list=$isListSection} {if $question['type'] == $questionTypeConsts['TYPE_SMALL_TEXT_FIELD']} - {fbvElement type="text" multilingual="true" name=$questionId id="demographicResponses" value=$question['response'] required=true size=$fbvStyles.size.SMALL} + {fbvElement type="text" multilingual="true" name=$questionId id="demographicResponses" value=$question['response']['value'] required=true size=$fbvStyles.size.SMALL} {elseif $question['type'] == $questionTypeConsts['TYPE_TEXT_FIELD']} - {fbvElement type="text" multilingual="true" name=$questionId id="demographicResponses" value=$question['response'] required=true size=$fbvStyles.size.LARGE} + {fbvElement type="text" multilingual="true" name=$questionId id="demographicResponses" value=$question['response']['value'] required=true size=$fbvStyles.size.LARGE} {elseif $question['type'] == $questionTypeConsts['TYPE_TEXTAREA']} - {fbvElement type="textarea" multilingual="true" name=$questionId id="demographicResponses" value=$question['response'] required=true rich=false size=$fbvStyles.size.LARGE} + {fbvElement type="textarea" multilingual="true" name=$questionId id="demographicResponses" value=$question['response']['value'] required=true rich=false size=$fbvStyles.size.LARGE} {elseif $question['type'] == $questionTypeConsts['TYPE_CHECKBOXES']} {foreach from=$question['responseOptions'] item="responseOption"} {fbvElement @@ -19,9 +19,20 @@ id="demographicResponses" label=$responseOption->getLocalizedOptionText() value=$responseOption->getId() - checked=in_array($responseOption->getId(), $question['response']) + checked=in_array($responseOption->getId(), $question['response']['value']) translate=false } + + {if $responseOption->hasInputField()} + {assign var="optionInputName" value="responseOptionInput-{$responseOption->getId()}"} + {if isset($question['response']['optionsInputValue'][$responseOption->getId()])} + {assign var="optionInputValue" value=$question['response']['optionsInputValue'][$responseOption->getId()]} + {else} + {assign var="optionInputValue" value=""} + {/if} + + {fbvElement type="text" name=$optionInputName id="responseOptionsInputs" value=$optionInputValue size=$fbvStyles.size.SMALL} + {/if} {/foreach} {elseif $question['type'] == $questionTypeConsts['TYPE_RADIO_BUTTONS']} {foreach from=$question['responseOptions'] item="responseOption"} @@ -31,13 +42,24 @@ id="demographicResponses" label=$responseOption->getLocalizedOptionText() value=$responseOption->getId() - checked=in_array($responseOption->getId(), $question['response']) + checked=in_array($responseOption->getId(), $question['response']['value']) required=true translate=false } + + {if $responseOption->hasInputField()} + {assign var="optionInputName" value="responseOptionInput-{$responseOption->getId()}"} + {if isset($question['response']['optionsInputValue'][$responseOption->getId()])} + {assign var="optionInputValue" value=$question['response']['optionsInputValue'][$responseOption->getId()]} + {else} + {assign var="optionInputValue" value=""} + {/if} + + {fbvElement type="text" name=$optionInputName id="responseOptionsInputs" value=$optionInputValue size=$fbvStyles.size.SMALL} + {/if} {/foreach} {elseif $question['type'] == $questionTypeConsts['TYPE_DROP_DOWN_BOX']} - {fbvElement type="select" name=$questionId id="demographicResponses" from=$question['responseOptions'] selected=$question['response'] translate=false required=true size=$fbvStyles.size.LARGE} + {fbvElement type="select" name=$questionId id="demographicResponses" from=$question['responseOptions'] selected=$question['response']['value'] translate=false required=true size=$fbvStyles.size.LARGE} {/if} {/fbvFormSection} {/fbvFormSection} \ No newline at end of file From 11122b77b269d456b6b5a5353fec03d1173d12a9 Mon Sep 17 00:00:00 2001 From: Jhon Date: Wed, 16 Oct 2024 14:38:51 -0400 Subject: [PATCH 15/19] Fixes getting of input field in integration test Issue: documentacao-e-tarefas/scielo#706 Signed-off-by: Jhon --- cypress/tests/Test1_questionsDisplaying.cy.js | 6 +- templates/question.tpl | 78 ++++++++++--------- 2 files changed, 44 insertions(+), 40 deletions(-) diff --git a/cypress/tests/Test1_questionsDisplaying.cy.js b/cypress/tests/Test1_questionsDisplaying.cy.js index 9a9f1ff..042f07e 100644 --- a/cypress/tests/Test1_questionsDisplaying.cy.js +++ b/cypress/tests/Test1_questionsDisplaying.cy.js @@ -47,7 +47,7 @@ function answerDefaultQuestions() { cy.contains('label', 'Spanish').within(() => { cy.get('input').check(); }); - cy.contains('label', 'Other:').within(() => { + cy.contains('label', 'Other:').parent().parent().within(() => { cy.get('input[type="checkbox"]').check(); cy.get('input[type="text"]').clear().type('Japanese'); }); @@ -74,7 +74,7 @@ function assertResponsesToDefaultQuestions() { cy.contains('label', 'Spanish').within(() => { cy.get('input').should('be.checked'); }); - cy.contains('label', 'Other:').within(() => { + cy.contains('label', 'Other:').parent().parent().within(() => { cy.get('input[type="checkbox"]').should('be.checked'); cy.get('input[type="text"]').should('have.value', 'Japanese'); }); @@ -91,7 +91,7 @@ function assertResponsesToQuestionsInFrench() { cy.contains('label', 'Espagnol').within(() => { cy.get('input').should('be.checked'); }); - cy.contains('label', 'Autre:').within(() => { + cy.contains('label', 'Autre:').parent().parent().within(() => { cy.get('input[type="checkbox"]').should('be.checked'); cy.get('input[type="text"]').should('have.value', 'Japanese'); }); diff --git a/templates/question.tpl b/templates/question.tpl index eb55974..181fc40 100644 --- a/templates/question.tpl +++ b/templates/question.tpl @@ -13,50 +13,54 @@ {fbvElement type="textarea" multilingual="true" name=$questionId id="demographicResponses" value=$question['response']['value'] required=true rich=false size=$fbvStyles.size.LARGE} {elseif $question['type'] == $questionTypeConsts['TYPE_CHECKBOXES']} {foreach from=$question['responseOptions'] item="responseOption"} - {fbvElement - type="checkbox" - name="{$questionId}[]" - id="demographicResponses" - label=$responseOption->getLocalizedOptionText() - value=$responseOption->getId() - checked=in_array($responseOption->getId(), $question['response']['value']) - translate=false - } +
+ {fbvElement + type="checkbox" + name="{$questionId}[]" + id="demographicResponses" + label=$responseOption->getLocalizedOptionText() + value=$responseOption->getId() + checked=in_array($responseOption->getId(), $question['response']['value']) + translate=false + } - {if $responseOption->hasInputField()} - {assign var="optionInputName" value="responseOptionInput-{$responseOption->getId()}"} - {if isset($question['response']['optionsInputValue'][$responseOption->getId()])} - {assign var="optionInputValue" value=$question['response']['optionsInputValue'][$responseOption->getId()]} - {else} - {assign var="optionInputValue" value=""} + {if $responseOption->hasInputField()} + {assign var="optionInputName" value="responseOptionInput-{$responseOption->getId()}"} + {if isset($question['response']['optionsInputValue'][$responseOption->getId()])} + {assign var="optionInputValue" value=$question['response']['optionsInputValue'][$responseOption->getId()]} + {else} + {assign var="optionInputValue" value=""} + {/if} + + {fbvElement type="text" name=$optionInputName id="responseOptionsInputs" value=$optionInputValue size=$fbvStyles.size.SMALL} {/if} - - {fbvElement type="text" name=$optionInputName id="responseOptionsInputs" value=$optionInputValue size=$fbvStyles.size.SMALL} - {/if} +
{/foreach} {elseif $question['type'] == $questionTypeConsts['TYPE_RADIO_BUTTONS']} {foreach from=$question['responseOptions'] item="responseOption"} - {fbvElement - type="radio" - name="{$questionId}[]" - id="demographicResponses" - label=$responseOption->getLocalizedOptionText() - value=$responseOption->getId() - checked=in_array($responseOption->getId(), $question['response']['value']) - required=true - translate=false - } +
+ {fbvElement + type="radio" + name="{$questionId}[]" + id="demographicResponses" + label=$responseOption->getLocalizedOptionText() + value=$responseOption->getId() + checked=in_array($responseOption->getId(), $question['response']['value']) + required=true + translate=false + } - {if $responseOption->hasInputField()} - {assign var="optionInputName" value="responseOptionInput-{$responseOption->getId()}"} - {if isset($question['response']['optionsInputValue'][$responseOption->getId()])} - {assign var="optionInputValue" value=$question['response']['optionsInputValue'][$responseOption->getId()]} - {else} - {assign var="optionInputValue" value=""} + {if $responseOption->hasInputField()} + {assign var="optionInputName" value="responseOptionInput-{$responseOption->getId()}"} + {if isset($question['response']['optionsInputValue'][$responseOption->getId()])} + {assign var="optionInputValue" value=$question['response']['optionsInputValue'][$responseOption->getId()]} + {else} + {assign var="optionInputValue" value=""} + {/if} + + {fbvElement type="text" name=$optionInputName id="responseOptionsInputs" value=$optionInputValue size=$fbvStyles.size.SMALL} {/if} - - {fbvElement type="text" name=$optionInputName id="responseOptionsInputs" value=$optionInputValue size=$fbvStyles.size.SMALL} - {/if} +
{/foreach} {elseif $question['type'] == $questionTypeConsts['TYPE_DROP_DOWN_BOX']} {fbvElement type="select" name=$questionId id="demographicResponses" from=$question['responseOptions'] selected=$question['response']['value'] translate=false required=true size=$fbvStyles.size.LARGE} From b59425514c6872f35bc6dec3398cab93cecf9df5 Mon Sep 17 00:00:00 2001 From: Jhon Date: Wed, 16 Oct 2024 14:58:48 -0400 Subject: [PATCH 16/19] Adds integration test - Response option input field on questionnaire page Issue: documentacao-e-tarefas/scielo#706 Signed-off-by: Jhon --- cypress/tests/Test1_questionsDisplaying.cy.js | 1 + cypress/tests/Test2_externalContributors.cy.js | 10 +++++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/cypress/tests/Test1_questionsDisplaying.cy.js b/cypress/tests/Test1_questionsDisplaying.cy.js index 042f07e..c3e2690 100644 --- a/cypress/tests/Test1_questionsDisplaying.cy.js +++ b/cypress/tests/Test1_questionsDisplaying.cy.js @@ -17,6 +17,7 @@ function assertDefaultQuestionsDisplay() { cy.contains('Mandarin'); cy.contains('Portuguese'); cy.contains('Spanish'); + cy.contains('Other:'); cy.contains('label', 'Nacionality'); cy.contains('.description', 'Which continent are you from?'); diff --git a/cypress/tests/Test2_externalContributors.cy.js b/cypress/tests/Test2_externalContributors.cy.js index 37b26e1..e048794 100644 --- a/cypress/tests/Test2_externalContributors.cy.js +++ b/cypress/tests/Test2_externalContributors.cy.js @@ -51,6 +51,10 @@ function answerDefaultQuestions() { cy.contains('label', 'Spanish').within(() => { cy.get('input').check(); }); + cy.contains('label', 'Other:').parent().within(() => { + cy.get('input[type="checkbox"]').check(); + cy.get('input[type="text"]').clear().type('Japanese'); + }); cy.contains('label', 'America').within(() => { cy.get('input').check(); }); @@ -66,7 +70,7 @@ function assertResponsesOfExternalAuthor(authorEmail) { cy.contains('Latin'); cy.contains('University of São Paulo'); cy.contains('University of Minas Gerais'); - cy.contains('English, Spanish'); + cy.contains('English, Spanish, Other: "Japanese"'); cy.contains('America'); cy.contains('Three to five minimum wages'); @@ -88,6 +92,10 @@ function assertResponsesOfRegisteredUser() { cy.contains('label', 'Spanish').within(() => { cy.get('input').should('be.checked'); }); + cy.contains('label', 'Other:').parent().parent().within(() => { + cy.get('input[type="checkbox"]').check(); + cy.get('input[type="text"]').clear().type('Japanese'); + }); cy.contains('label', 'America').within(() => { cy.get('input').should('be.checked'); }); From 2f7503997691ed4169c02046443a9351900c5934 Mon Sep 17 00:00:00 2001 From: Jhon Date: Wed, 16 Oct 2024 16:01:42 -0400 Subject: [PATCH 17/19] Can answer response option input fields in questionnaire page Issue: documentacao-e-tarefas/scielo#706 Signed-off-by: Jhon --- classes/DemographicDataService.php | 14 ++++++++-- pages/demographic/QuestionnaireHandler.php | 5 +++- templates/questionnairePage/question.tpl | 30 ++++++++++++++++------ 3 files changed, 38 insertions(+), 11 deletions(-) diff --git a/classes/DemographicDataService.php b/classes/DemographicDataService.php index b4804d8..e707b43 100644 --- a/classes/DemographicDataService.php +++ b/classes/DemographicDataService.php @@ -122,7 +122,7 @@ private function getResponseOptionsInputValue($questionId, $responseOptionsInput return null; } - public function registerExternalAuthorResponses(string $externalId, string $externalType, array $responses) + public function registerExternalAuthorResponses(string $externalId, string $externalType, array $responses, array $responseOptionsInputs) { $locale = Locale::getLocale(); @@ -131,10 +131,13 @@ public function registerExternalAuthorResponses(string $externalId, string $exte $questionId = $questionParts[1]; $questionType = $questionParts[2]; + $optionsInputValue = $this->getResponseOptionsInputValue($questionId, $responseOptionsInputs, $responseInput); + $response = Repo::demographicResponse()->newDataObject(); $response->setDemographicQuestionId($questionId); $response->setExternalId($externalId); $response->setExternalType($externalType); + $response->setOptionsInputValue($optionsInputValue); if ($questionType == 'text' or $questionType == 'textarea') { $response->setData('responseValue', $responseInput, $locale); @@ -182,7 +185,14 @@ private function getResponseValueForDisplay($question, $response): string foreach ($response->getValue() as $selectedResponseOptionId) { $selectedResponseOption = $responseOptions[$selectedResponseOptionId]; - $selectedResponseOptionsTexts[] = $selectedResponseOption->getLocalizedOptionText(); + $selectedResponseOptionsText = $selectedResponseOption->getLocalizedOptionText(); + + if ($selectedResponseOption->hasInputField()) { + $optionsInputValue = $response->getOptionsInputValue(); + $selectedResponseOptionsText .= ' "' . $optionsInputValue[$selectedResponseOptionId] . '"'; + } + + $selectedResponseOptionsTexts[] = $selectedResponseOptionsText; } return implode(', ', $selectedResponseOptionsTexts); diff --git a/pages/demographic/QuestionnaireHandler.php b/pages/demographic/QuestionnaireHandler.php index 8a39467..fb311d3 100644 --- a/pages/demographic/QuestionnaireHandler.php +++ b/pages/demographic/QuestionnaireHandler.php @@ -112,9 +112,12 @@ public function saveQuestionnaire($args, $request) } $responses = []; + $responseOptionsInputs = []; foreach ($request->getUserVars() as $key => $value) { if (strpos($key, 'question-') === 0) { $responses[$key] = $value; + } elseif (strpos($key, 'responseOptionInput-') === 0) { + $responseOptionsInputs[$key] = $value; } } @@ -127,7 +130,7 @@ public function saveQuestionnaire($args, $request) } $demographicDataService = new DemographicDataService(); - $demographicDataService->registerExternalAuthorResponses($responsesExternalId, $responsesExternalType, $responses); + $demographicDataService->registerExternalAuthorResponses($responsesExternalId, $responsesExternalType, $responses, $responseOptionsInputs); $templateMgr->assign([ 'authorId' => $author->getId(), diff --git a/templates/questionnairePage/question.tpl b/templates/questionnairePage/question.tpl index 62f331e..50cc0ed 100644 --- a/templates/questionnairePage/question.tpl +++ b/templates/questionnairePage/question.tpl @@ -11,17 +11,31 @@ {elseif $question['type'] == $questionTypeConsts['TYPE_CHECKBOXES']} {foreach from=$question['responseOptions'] item="responseOption"} -
+
+ + {if $responseOption->hasInputField()} + {assign var="optionInputName" value="responseOptionInput-{$responseOption->getId()}"} + + {/if} +
+
{/foreach} {elseif $question['type'] == $questionTypeConsts['TYPE_RADIO_BUTTONS']} {foreach from=$question['responseOptions'] item="responseOption"} -
+
+ + {if $responseOption->hasInputField()} + {assign var="optionInputName" value="responseOptionInput-{$responseOption->getId()}"} + + {/if} +
+
{/foreach} {elseif $question['type'] == $questionTypeConsts['TYPE_DROP_DOWN_BOX']}