Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/hkd 6/integration #2505

Draft
wants to merge 37 commits into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
4a6ce7e
chore: add form modifiers
shpran Sep 9, 2024
7566e7e
chore: rename modifier, extend abstract class
shpran Sep 10, 2024
87d4100
chore: do not replace unique ID
shpran Sep 10, 2024
b1d7231
chore: use proxies instead of manager
shpran Sep 10, 2024
90660f3
chore: fix cs
shpran Sep 10, 2024
8d869cc
chore: add unit tests for modifier
shpran Sep 11, 2024
0cc5a0f
chore: add dev-dependencies
shpran Sep 11, 2024
7741895
chore: add dev-dependencies
shpran Sep 11, 2024
968daa9
chore: add event listener to set unique identifier
shpran Sep 11, 2024
ff16c56
chore: register listener
shpran Sep 11, 2024
6be1682
chore: use direct event class, add unit test
shpran Sep 12, 2024
6e7186b
chore: update unit tests in accordance with latest changes, add new u…
shpran Sep 12, 2024
33b97b0
chore: throw an exception during retrieving, update unit test
shpran Sep 12, 2024
f97c561
chore: fix cs
shpran Sep 13, 2024
f81583b
Merge pull request #2503 from oat-sa/feature/ADF-1780/create-necessar…
gabrielfs7 Sep 13, 2024
4f0f47f
feat: create translatable test
shpran Sep 13, 2024
e54c005
chore: check for empty
shpran Sep 13, 2024
a8d93d4
chore: cache resources from the test to avoid unnecessary calls to DB
shpran Sep 16, 2024
db8b62f
chore: update dependencies
gabrielfs7 Sep 16, 2024
7988cab
chore: use standard feature flag name
gabrielfs7 Sep 16, 2024
e825534
chore: use callable class
shpran Sep 17, 2024
a3b2fe8
chore: remove unnecessary import
shpran Sep 17, 2024
430218c
chore: add exception class to logs, simplify code
shpran Sep 18, 2024
799560e
chore: add unit tests
shpran Sep 18, 2024
58b0420
Merge branch 'feat/HKD-6/integration' of https://github.com/oat-sa/ex…
shpran Sep 18, 2024
147593a
chore: adapt code to new changes
shpran Sep 18, 2024
e447f2a
chore: extract unique ID form modifiers as a separate feature
shpran Sep 19, 2024
f3cdc69
Merge pull request #2506 from oat-sa/feat/ADF-1787/create-translatabl…
gabrielfs7 Sep 19, 2024
1636ccf
chore: fix unit tests
shpran Sep 19, 2024
bc709d6
chore: fix events
shpran Sep 19, 2024
4e7a750
Merge branch 'develop' of https://github.com/oat-sa/extension-tao-tes…
gabrielfs7 Oct 14, 2024
58da18b
feat: forward the translation parameters through the config
jsconan Oct 14, 2024
64839bb
feat: forward the translation parameters to the creator factory
jsconan Oct 16, 2024
27766af
Merge pull request #2516 from oat-sa/feature/ADF-1789/forward-transla…
jsconan Oct 16, 2024
b69a123
feat: render two preview buttons for translated tests
shaveko Oct 16, 2024
11ce5eb
chore: prettify code
shaveko Oct 16, 2024
4561244
Merge pull request #2517 from oat-sa/feat/ADF-1790/preview-test-trans…
shaveko Oct 17, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 28 additions & 24 deletions actions/class.Creator.php
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
<?php

/**
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; under version 2
* of the License (non-upgradable).
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Copyright (c) 2013 (original work) Open Assessment Technologies SA (under the project TAO-PRODUCT);
*/
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; under version 2
* of the License (non-upgradable).
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Copyright (c) 2013-2024 (original work) Open Assessment Technologies SA (under the project TAO-PRODUCT);
*/

use oat\taoQtiTest\models\TestCategoryPresetProvider;
use oat\taoQtiTest\models\TestModelService;
Expand Down Expand Up @@ -45,6 +45,10 @@ public function index()
$testUri = $this->getRequestParameter('uri');
$testModel = $this->getServiceManager()->get(TestModelService::SERVICE_ID);

// Add support for translation and side-by-side view
$this->setData('translation', $this->getRequestParameter('translation') ?? "false");
$this->setData('originResourceUri', json_encode($this->getRequestParameter('originResourceUri')));

$items = $testModel->getItems(new core_kernel_classes_Resource(tao_helpers_Uri::decode($testUri)));
foreach ($items as $item) {
$labels[$item->getUri()] = $item->getLabel();
Expand Down Expand Up @@ -91,9 +95,9 @@ public function index()
$this->setView('creator.tpl');
}

/**
* Get json's test content, the uri of the test must be provided in parameter
*/
/**
* Get json's test content, the uri of the test must be provided in parameter
*/
public function getTest()
{
$test = $this->getCurrentTest();
Expand All @@ -104,11 +108,11 @@ public function getTest()
$this->response = $this->getPsrResponse()->withBody(stream_for($qtiTestService->getJsonTest($test)));
}

/**
* Save a test, test uri and
* The request must use the POST method and contains
* the test uri and a json string that represents the QTI Test in the model parameter.
*/
/**
* Save a test, test uri and
* The request must use the POST method and contains
* the test uri and a json string that represents the QTI Test in the model parameter.
*/
public function saveTest()
{
$saved = false;
Expand Down
8 changes: 4 additions & 4 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,10 @@
"oat-sa/oatbox-extension-installer": "~1.1||dev-master",
"qtism/qtism": ">=0.28.3",
"oat-sa/generis": ">=15.36.4",
"oat-sa/tao-core": ">=54.21.0",
"oat-sa/extension-tao-item" : ">=12.1.0",
"oat-sa/extension-tao-itemqti" : ">=30.12.0",
"oat-sa/extension-tao-test" : ">=16.0.0",
"oat-sa/tao-core": "dev-feat/HKD-6/integration as 99",
"oat-sa/extension-tao-item" : "dev-feat/HKD-6/integration as 99",
"oat-sa/extension-tao-itemqti" : "dev-feat/HKD-6/integration as 99",
"oat-sa/extension-tao-test" : "dev-feat/HKD-6/integration as 99",
"oat-sa/extension-tao-delivery" : ">=15.0.0",
"oat-sa/extension-tao-outcome" : ">=13.0.0",
"league/flysystem": "~1.0",
Expand Down
13 changes: 8 additions & 5 deletions manifest.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,21 +23,21 @@
use oat\tao\model\user\TaoRoles;
use oat\taoQtiTest\model\Container\TestQtiServiceProvider;
use oat\taoQtiTest\models\classes\metadata\MetadataServiceProvider;
// phpcs:disable Generic.Files.LineLength
// phpcs:ignore Generic.Files.LineLength
use oat\taoQtiTest\models\classes\render\CustomInteraction\ServiceProvider\CustomInteractionPostProcessingServiceProvider;
// phpcs:enable Generic.Files.LineLength
use oat\taoQtiTest\models\render\ItemsReferencesServiceProvider;
use oat\taoQtiTest\models\TestSessionState\Container\TestSessionStateServiceProvider;
use oat\taoQtiTest\models\Translation\ServiceProvider\TranslationServiceProvider;
use oat\taoQtiTest\models\UniqueId\ServiceProvider\UniqueIdServiceProvider;
use oat\taoQtiTest\models\xmlEditor\XmlEditorInterface;
use oat\taoQtiTest\scripts\install\RegisterResultTransmissionEventHandlers;
use oat\taoQtiTest\scripts\install\SetupProvider;
use oat\taoQtiTest\scripts\install\CreateTestSessionFilesystem;
use oat\taoQtiTest\scripts\install\DisableBRSinTestAuthoring;
use oat\taoQtiTest\scripts\install\RegisterCreatorServices;
use oat\taoQtiTest\scripts\install\RegisterFrontendPaths;
use oat\taoQtiTest\scripts\install\RegisterQtiCategoryPresetProviders;
use oat\taoQtiTest\scripts\install\RegisterQtiFlysystemManager;
use oat\taoQtiTest\scripts\install\RegisterQtiPackageExporter;
use oat\taoQtiTest\scripts\install\RegisterResultTransmissionEventHandlers;
use oat\taoQtiTest\scripts\install\RegisterSectionPauseService;
use oat\taoQtiTest\scripts\install\RegisterTestCategoryPresetProviderService;
use oat\taoQtiTest\scripts\install\RegisterTestContainer;
Expand All @@ -50,6 +50,7 @@
use oat\taoQtiTest\scripts\install\SetSynchronisationService;
use oat\taoQtiTest\scripts\install\SetupDefaultTemplateConfiguration;
use oat\taoQtiTest\scripts\install\SetupEventListeners;
use oat\taoQtiTest\scripts\install\SetupProvider;
use oat\taoQtiTest\scripts\install\SetUpQueueTasks;
use oat\taoQtiTest\scripts\install\SetupStateOffloadQueue;
use oat\taoQtiTest\scripts\install\SyncChannelInstaller;
Expand Down Expand Up @@ -185,6 +186,8 @@
ItemsReferencesServiceProvider::class,
TestQtiServiceProvider::class,
TestSessionStateServiceProvider::class,
MetadataServiceProvider::class
MetadataServiceProvider::class,
TranslationServiceProvider::class,
UniqueIdServiceProvider::class,
],
];
46 changes: 46 additions & 0 deletions migrations/Version202409111328132260_taoQtiTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<?php

declare(strict_types=1);

namespace oat\taoQtiTest\migrations;

use Doctrine\DBAL\Schema\Schema;
use oat\oatbox\event\EventManager;
use oat\tao\scripts\tools\migrations\AbstractMigration;
use oat\taoQtiTest\models\UniqueId\Listener\TestCreatedEventListener;
use oat\taoTests\models\event\TestCreatedEvent;

/**
* Auto-generated Migration: Please modify to your needs!
*
* phpcs:disable Squiz.Classes.ValidClassName
*/
final class Version202409111328132260_taoQtiTest extends AbstractMigration
{
public function getDescription(): string
{
return 'Add new listener to populate translation properties';
}

public function up(Schema $schema): void
{
/** @var EventManager $eventManager */
$eventManager = $this->getServiceManager()->get(EventManager::SERVICE_ID);
$eventManager->attach(
TestCreatedEvent::class,
[TestCreatedEventListener::class, 'populateUniqueId']
);
$this->getServiceManager()->register(EventManager::SERVICE_ID, $eventManager);
}

public function down(Schema $schema): void
{
/** @var EventManager $eventManager */
$eventManager = $this->getServiceManager()->get(EventManager::SERVICE_ID);
$eventManager->detach(
TestCreatedEvent::class,
[TestCreatedEventListener::class, 'populateUniqueId']
);
$this->getServiceManager()->register(EventManager::SERVICE_ID, $eventManager);
}
}
160 changes: 160 additions & 0 deletions models/classes/Translation/Service/TestTranslator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
<?php

/**
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; under version 2
* of the License (non-upgradable).
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Copyright (c) 2024 (original work) Open Assessment Technologies SA.
*/

declare(strict_types=1);

namespace oat\taoQtiTest\models\Translation\Service;

use core_kernel_classes_Resource;
use core_kernel_persistence_Exception;
use oat\generis\model\data\Ontology;
use oat\tao\model\TaoOntology;
use oat\tao\model\Translation\Entity\ResourceTranslation;
use oat\tao\model\Translation\Exception\ResourceTranslationException;
use oat\tao\model\Translation\Query\ResourceTranslationQuery;
use oat\tao\model\Translation\Repository\ResourceTranslationRepository;
use oat\taoTests\models\TaoTestOntology;
use taoQtiTest_models_classes_QtiTestConverterException;
use taoQtiTest_models_classes_QtiTestService;
use taoQtiTest_models_classes_QtiTestServiceException;

class TestTranslator
{
private taoQtiTest_models_classes_QtiTestService $testQtiService;
private Ontology $ontology;
private ResourceTranslationRepository $resourceTranslationRepository;

public function __construct(
taoQtiTest_models_classes_QtiTestService $testQtiService,
Ontology $ontology,
ResourceTranslationRepository $resourceTranslationRepository
) {
$this->testQtiService = $testQtiService;
$this->ontology = $ontology;
$this->resourceTranslationRepository = $resourceTranslationRepository;
}

/**
* @throws taoQtiTest_models_classes_QtiTestConverterException
* @throws taoQtiTest_models_classes_QtiTestServiceException
* @throws core_kernel_persistence_Exception
* @throws ResourceTranslationException
*/
public function translate(core_kernel_classes_Resource $translationTest): core_kernel_classes_Resource
{
$this->assertIsTest($translationTest);

$originalTestUri = $translationTest->getOnePropertyValue(
$this->ontology->getProperty(TaoOntology::PROPERTY_TRANSLATION_ORIGINAL_RESOURCE_URI)
);
$originalTest = $this->ontology->getResource($originalTestUri->getUri());

$jsonTest = $this->testQtiService->getJsonTest($originalTest);
$originalTestData = json_decode($jsonTest, true, 512, JSON_THROW_ON_ERROR);

$originalItemUris = $this->collectItemUris($originalTestData);
$translationUris = $this->getItemTranslationUris($translationTest, $originalItemUris);

$translatedTestData = $this->doTranslation($originalTestData, $translationUris);

$this->testQtiService->saveJsonTest($translationTest, json_encode($translatedTestData));
$this->updateTranslationCompletionStatus($translationTest, $originalItemUris, $translationUris);

return $translationTest;
}

private function assertIsTest(core_kernel_classes_Resource $resource): void
{
if (!$resource->isInstanceOf($this->ontology->getClass(TaoOntology::CLASS_URI_TEST))) {
throw new ResourceTranslationException('Provided resources is not a Test');
}
}

private function doTranslation(array $testData, array $translationUris): array
{
foreach ($testData['testParts'] as &$testPart) {
foreach ($testPart['assessmentSections'] as &$assessmentSection) {
foreach ($assessmentSection['sectionParts'] as &$sectionPart) {
$sectionPart['href'] = $translationUris[$sectionPart['href']] ?? $sectionPart['href'];
}
}
}

return $testData;
}

private function collectItemUris(array $testData): array
{
$uris = [];

foreach ($testData['testParts'] as $testPart) {
foreach ($testPart['assessmentSections'] as $assessmentSection) {
foreach ($assessmentSection['sectionParts'] as $sectionPart) {
if (in_array($sectionPart['href'], $uris, true)) {
continue;
}

$uris[] = $sectionPart['href'];
}
}
}

return $uris;
}

/**
* @param string[] $originalItemUris
* @return array<string, string>
*/
private function getItemTranslationUris(core_kernel_classes_Resource $test, array $originalItemUris): array
{
$language = $test->getOnePropertyValue($this->ontology->getProperty(TaoOntology::PROPERTY_LANGUAGE));
$translations = $this->resourceTranslationRepository->find(
new ResourceTranslationQuery(
$originalItemUris,
$language->getUri()
)
);

$translationUris = [];

/** @var ResourceTranslation $translation */
foreach ($translations->jsonSerialize()['resources'] as $translation) {
$translationUris[$translation->getOriginResourceUri()] = $translation->getResourceUri();
}

return $translationUris;
}

private function updateTranslationCompletionStatus(
core_kernel_classes_Resource $test,
array $uniqueIds,
array $translationUris
): void {
$status = count($uniqueIds) > count($translationUris)
? TaoTestOntology::PROPERTY_VALUE_TRANSLATION_COMPLETION_MISSING_TRANSLATIONS
: TaoTestOntology::PROPERTY_VALUE_TRANSLATION_COMPLETION_TRANSLATED;

$test->editPropertyValues(
$this->ontology->getProperty(TaoTestOntology::PROPERTY_TRANSLATION_COMPLETION),
$status
);
}
}
Loading
Loading