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/aut 3590/add metadata check on import #2454

Merged
merged 37 commits into from
May 7, 2024
Merged
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
59a426f
feat: export test will inject properties description in root metadata…
bartlomiejmarszal Apr 9, 2024
393bdbb
feat: fix phpcs issues
bartlomiejmarszal Apr 9, 2024
d0b57ba
feat: fix phpcs issues
bartlomiejmarszal Apr 9, 2024
f946de0
feat: add Feature Flag
bartlomiejmarszal Apr 9, 2024
9dac940
feat: extract checksum to service, remove interface
bartlomiejmarszal Apr 10, 2024
129d4bc
feat: phpcs fix
bartlomiejmarszal Apr 10, 2024
5b0794d
feat: add import metametadata
Karol-Stelmaczonek Apr 10, 2024
8d0bb00
chore: add debug for checksum
Karol-Stelmaczonek Apr 11, 2024
aacccee
feat: add sorting and to lower for checksum
Karol-Stelmaczonek Apr 11, 2024
232ac35
Merge branch 'feat/AUT-3589/add-properties-in-root-ims-manifest' into…
Karol-Stelmaczonek Apr 11, 2024
926c553
feat: additional fixes for checksum
Karol-Stelmaczonek Apr 11, 2024
edccf52
Merge branch 'feat/AUT-3589/add-properties-in-root-ims-manifest' into…
Karol-Stelmaczonek Apr 11, 2024
4d88aed
chore: refactor & rename
Karol-Stelmaczonek Apr 12, 2024
95b2336
chore: phpcbf fixes
Karol-Stelmaczonek Apr 15, 2024
0bc78b6
chore: phpcbf fixes
Karol-Stelmaczonek Apr 15, 2024
3e30b13
feat: add metadata import for items and tests
bartlomiejmarszal Apr 16, 2024
2ac9845
feat: Merge branch 'feat/aut-3590/add-metadata-check-on-import' into …
bartlomiejmarszal Apr 16, 2024
bea3f55
feat: Remove MetaMetadataValidator. Move business logic into matcher
bartlomiejmarszal Apr 18, 2024
aa3aa6b
feat: phpsbf fix
bartlomiejmarszal Apr 18, 2024
f1f6616
feat: move ChecksumGenerator to taoQtiItems
bartlomiejmarszal Apr 18, 2024
52cb224
chore: remove unused code
Karol-Stelmaczonek Apr 18, 2024
d0e78fc
feat: GenericLomOntologyExtractorTest
bartlomiejmarszal Apr 18, 2024
26007e9
Merge remote-tracking branch 'origin/feat/aut-3590/add-metadata-check…
Karol-Stelmaczonek Apr 18, 2024
818b02f
Merge remote-tracking branch 'origin/feat/aut-3590/add-metadata-check…
Karol-Stelmaczonek Apr 18, 2024
4cf0215
feat: temp composer fix
bartlomiejmarszal Apr 18, 2024
81c31d4
Merge branch 'feat/aut-3590/add-metadata-check-on-import' of https://…
bartlomiejmarszal Apr 18, 2024
959026a
chore: phpcbf fixes
Karol-Stelmaczonek Apr 18, 2024
394deab
Merge remote-tracking branch 'origin/feat/aut-3590/add-metadata-check…
Karol-Stelmaczonek Apr 18, 2024
9a6a205
feat: add form checkbox in import test form
bartlomiejmarszal May 2, 2024
a480dd7
Merge branch 'feat/aut-3590/add-metadata-check-on-import' of https://…
bartlomiejmarszal May 2, 2024
b516f30
feat: phpcbf automatic fix
bartlomiejmarszal May 2, 2024
361b66d
feat: When importing a test, item metadata values are imported
bartlomiejmarszal May 2, 2024
ad82c29
feat: Export using this same FF
bartlomiejmarszal May 3, 2024
16ee3c9
fix: define default array
bartlomiejmarszal May 6, 2024
cd9a9a1
fix: Connect test import form
bartlomiejmarszal May 7, 2024
431778f
fix: Decorate form with metadata. Overload getTaskParams
bartlomiejmarszal May 7, 2024
effe9f7
fix: oat-sa/extension-tao-itemqti - 30.10.0 dependency
bartlomiejmarszal May 7, 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
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@
"oat-sa/generis" : ">=15.22",
"oat-sa/tao-core": ">=54.0.0",
"oat-sa/extension-tao-item" : ">=12.1.0",
"oat-sa/extension-tao-itemqti" : ">=30.0.0",
"oat-sa/extension-tao-itemqti" : ">=30.10.0",
"oat-sa/extension-tao-test" : ">=16.0.0",
"oat-sa/extension-tao-delivery" : ">=15.0.0",
"oat-sa/extension-tao-outcome" : ">=13.0.0",
Expand Down
4 changes: 3 additions & 1 deletion manifest.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

use oat\tao\model\user\TaoRoles;
use oat\taoQtiTest\model\Container\TestQtiServiceProvider;
use oat\taoQtiTest\models\classes\metadata\MetadataServiceProvider;
// phpcs:disable Generic.Files.LineLength
use oat\taoQtiTest\models\classes\render\CustomInteraction\ServiceProvider\CustomInteractionPostProcessingServiceProvider;
// phpcs:enable Generic.Files.LineLength
Expand Down Expand Up @@ -182,6 +183,7 @@
CustomInteractionPostProcessingServiceProvider::class,
ItemsReferencesServiceProvider::class,
TestQtiServiceProvider::class,
TestSessionStateServiceProvider::class
TestSessionStateServiceProvider::class,
MetadataServiceProvider::class
],
];
67 changes: 62 additions & 5 deletions models/classes/class.QtiTestService.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,12 @@
use oat\taoItems\model\Command\DeleteItemCommand;
use oat\taoQtiItem\model\qti\ImportService;
use oat\taoQtiItem\model\qti\metadata\importer\MetadataImporter;
use oat\taoQtiItem\model\qti\metadata\imsManifest\MetaMetadataExtractor;
use oat\taoQtiItem\model\qti\metadata\importer\MetaMetadataImportMapper;
use oat\taoQtiItem\model\qti\metadata\importer\PropertyDoesNotExistException;
use oat\taoQtiItem\model\qti\metadata\MetadataGuardianResource;
use oat\taoQtiItem\model\qti\metadata\MetadataService;
use oat\taoQtiItem\model\qti\metadata\ontology\MappedMetadataInjector;
use oat\taoQtiItem\model\qti\Resource;
use oat\taoQtiItem\model\qti\Service;
use oat\taoQtiTest\models\cat\AdaptiveSectionInjectionException;
Expand All @@ -50,6 +54,8 @@
use qtism\data\storage\xml\XmlDocument;
use qtism\data\storage\xml\XmlStorageException;
use taoTests_models_classes_TestsService as TestService;
use oat\oatbox\reporting\Report;
use taoQtiTest_models_classes_import_TestImportForm as TestImportForm;

/**
* the QTI TestModel service.
Expand Down Expand Up @@ -349,7 +355,8 @@ public function importMultipleTests(
core_kernel_classes_Class $targetClass,
$file,
bool $overwriteTest = false,
?string $itemClassUri = null
?string $itemClassUri = null,
array $form = []
) {
$testClass = $targetClass;
$report = new common_report_Report(common_report_Report::TYPE_INFO);
Expand Down Expand Up @@ -417,7 +424,8 @@ public function importMultipleTests(
$folder,
$alreadyImportedQtiResources,
$overwriteTest,
$itemClassUri
$itemClassUri,
!empty($form[TestImportForm::METADATA_FORM_ELEMENT_NAME]) ?? false
);
$report->add($importTestReport);

Expand Down Expand Up @@ -537,7 +545,8 @@ protected function importTest(
$folder,
array $ignoreQtiResources = [],
bool $overwriteTest = false,
?string $itemClassUri = null
?string $itemClassUri = null,
bool $importMetadata = false
) {
/** @var ImportService $itemImportService */
$itemImportService = $this->getServiceLocator()->get(ImportService::SERVICE_ID);
Expand Down Expand Up @@ -585,6 +594,8 @@ protected function importTest(
$reportCtx->testMetadata = $metadataValues[$qtiTestResourceIdentifier] ?? [];
$reportCtx->createdClasses = [];



// 'uriResource' key is needed by javascript in tao/views/templates/form/import.tpl
$reportCtx->uriResource = $testResource->getUri();

Expand Down Expand Up @@ -630,6 +641,15 @@ protected function importTest(
$targetItemClass->label = $testLabel;

$reportCtx->itemClass = $targetItemClass;

$mappedProperties = $this->getMappedProperties(
$importMetadata,
$domManifest,
$reportCtx,
$testClass,
$targetItemClass
);

// -- Load all items related to test.
$itemError = false;

Expand Down Expand Up @@ -679,7 +699,6 @@ protected function importTest(
);
}
}

// Skip if $qtiFile already imported (multiple assessmentItemRef "hrefing" the same
// file).
if (array_key_exists($qtiFile, $alreadyImportedTestItemFiles) === false) {
Expand All @@ -697,7 +716,9 @@ protected function importTest(
$this->useMetadataValidators,
$this->itemMustExist,
$this->itemMustBeOverwritten,
$reportCtx->overwrittenItems
$reportCtx->overwrittenItems,
$mappedProperties['itemProperties'] ?? [],
$importMetadata
);

$reportCtx->createdClasses = array_merge(
Expand Down Expand Up @@ -780,6 +801,11 @@ protected function importTest(
// 4. Import metadata for the resource (use same mechanics as item resources).
// Metadata will be set as property values.
$this->getMetadataImporter()->inject($qtiTestResource->getIdentifier(), $testResource);
$this->getServiceManager()->getContainer()->get(MappedMetadataInjector::class)->inject(
$mappedProperties['testProperties'] ?? [],
$metadataValues[$qtiTestResourceIdentifier],
$testResource
);

// 5. if $targetClass does not contain any instances
// (because everything resolved by class lookups),
Expand Down Expand Up @@ -833,6 +859,9 @@ protected function importTest(

$msg = __("Error found in the IMS QTI Test:\n%s", $finalErrorString);
$report->add(common_report_Report::createFailure($msg));
} catch (PropertyDoesNotExistException $e) {
$reportCtx->itemClass = $targetItemClass;
$report->add(Report::createError($e->getMessage()));
} catch (CatEngineNotFoundException $e) {
$report->add(
new common_report_Report(
Expand Down Expand Up @@ -1411,6 +1440,12 @@ protected function getMetadataImporter()
return $this->metadataImporter;
}

private function getMetaMetadataExtractor(): MetaMetadataExtractor
{
return $this->getPsrContainer()->get(MetaMetadataExtractor::class);
return $this->getServiceManager()->getContainer()->get(MetaMetadataExtractor::class);
}

private function getSecureResourceService(): SecureResourceServiceInterface
{
return $this->getServiceLocator()->get(SecureResourceServiceInterface::SERVICE_ID);
Expand Down Expand Up @@ -1488,4 +1523,26 @@ private function getPsrContainer(): ContainerInterface
{
return $this->getServiceLocator()->getContainer();
}

private function getMetaMetadataImporter(): MetaMetadataImportMapper
{
return $this->getServiceManager()->getContainer()->get(MetaMetadataImportMapper::class);
}

private function getMappedProperties(
bool $importMetadata,
DOMDocument $domManifest,
stdClass $reportCtx,
core_kernel_classes_Class $testClass,
core_kernel_classes_Class $targetItemClass
): array {
if ($importMetadata === true) {
$metaMetadataValues = $this->getMetaMetadataExtractor()->extract($domManifest);
$reportCtx->metaMetadata = $metaMetadataValues;
return $this->getMetaMetadataImporter()
->mapMetaMetadataToProperties($metaMetadataValues, $targetItemClass, $testClass);
}

return [];
}
}
20 changes: 20 additions & 0 deletions models/classes/export/AbstractQtiTestExporter.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@
use DOMXPath;
use oat\oatbox\reporting\Report;
use oat\oatbox\reporting\ReportInterface;
use oat\tao\model\featureFlag\FeatureFlagChecker;
use oat\taoQtiTest\models\classes\metadata\GenericLomOntologyExtractor;
use oat\taoQtiTest\models\classes\metadata\MetadataLomService;
use qtism\data\storage\xml\marshalling\MarshallingException;
use qtism\data\storage\xml\XmlDocument;
use oat\oatbox\filesystem\Directory;
Expand Down Expand Up @@ -174,6 +177,13 @@ public function export(array $options = []): Report
// 3. Export test metadata to manifest
$this->getMetadataExporter()->export($this->getItem(), $this->getManifest());

if ($this->getFeatureFlagChecker()->isEnabled(MetadataLomService::FEATURE_FLAG)) {
$this->genericLomOntologyExtractor()->extract(
array_merge([$this->getItem()], $this->getItems()),
$this->getManifest()
);
}

// 4. Persist manifest in archive.
$this->getZip()->addFromString('imsmanifest.xml', $this->getManifest()->saveXML());

Expand Down Expand Up @@ -350,4 +360,14 @@ protected function getServiceManager(): ServiceManager
{
return ServiceManager::getServiceManager();
}

private function genericLomOntologyExtractor(): GenericLomOntologyExtractor
{
return $this->getServiceManager()->getContainer()->get(GenericLomOntologyExtractor::class);
}

private function getFeatureFlagChecker(): FeatureFlagChecker
{
return $this->getServiceManager()->getContainer()->get(FeatureFlagChecker::class);
}
}
40 changes: 38 additions & 2 deletions models/classes/import/class.TestImport.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,14 @@
use oat\oatbox\event\EventManagerAwareTrait;
use oat\oatbox\PhpSerializable;
use oat\oatbox\PhpSerializeStateless;
use oat\tao\model\featureFlag\FeatureFlagChecker;
use oat\tao\model\import\ImportHandlerHelperTrait;
use oat\tao\model\import\TaskParameterProviderInterface;
use oat\tao\model\upload\UploadService;
use oat\taoQtiTest\models\classes\metadata\MetadataLomService;
use oat\taoQtiTest\models\event\QtiTestImportEvent;
use Zend\ServiceManager\ServiceLocatorAwareInterface;
use taoQtiTest_models_classes_import_TestImportForm as TestImportForm;

/**
* Import handler for QTI packages
Expand All @@ -44,6 +48,9 @@ class taoQtiTest_models_classes_import_TestImport implements
use EventManagerAwareTrait;
use ImportHandlerHelperTrait;

public const DISABLED_FIELDS = 'disabledFields';
public const METADATA_FIELD = 'metadataImport';

/**
* (non-PHPdoc)
* @see tao_models_classes_import_ImportHandler::getLabel()
Expand All @@ -59,7 +66,7 @@ public function getLabel()
*/
public function getForm()
{
$form = new taoQtiTest_models_classes_import_TestImportForm();
$form = new taoQtiTest_models_classes_import_TestImportForm([], $this->getFormOptions());

return $form->getForm();
}
Expand All @@ -78,7 +85,8 @@ public function import($class, $form, $userId = null)
// The zip extraction is a long process that can exceed the 30s timeout
helpers_TimeOutHelper::setTimeOutLimit(helpers_TimeOutHelper::LONG);

$report = taoQtiTest_models_classes_QtiTestService::singleton()->importMultipleTests($class, $uploadedFile);
$report = taoQtiTest_models_classes_QtiTestService::singleton()
->importMultipleTests($class, $uploadedFile, false, null, $form);

helpers_TimeOutHelper::reset();

Expand All @@ -93,4 +101,32 @@ public function import($class, $form, $userId = null)
return common_report_Report::createFailure($e->getMessage());
}
}
public function getTaskParameters(tao_helpers_form_Form $importForm)
{
$file = $this->getUploadService()->getUploadedFlyFile($importForm->getValue('importFile')
?: $importForm->getValue('source')['uploaded_file']);

return [
'uploaded_file' => $file->getPrefix(), // because of Async, we need the full path of the uploaded file
TestImportForm::METADATA_FORM_ELEMENT_NAME => $importForm->getValue('metadata'),
];
}

private function getFeatureFlagChecker(): FeatureFlagChecker
{
return $this->serviceLocator->getContainer()->get(FeatureFlagChecker::class);
}

private function getFormOptions(): array
{
$options = [];
if (!$this->getFeatureFlagChecker()->isEnabled(MetadataLomService::FEATURE_FLAG)) {
$options[self::DISABLED_FIELDS] = [self::METADATA_FIELD];
}
return $options;
}
private function getUploadService()
{
return $this->serviceLocator->get(UploadService::SERVICE_ID);
}
}
43 changes: 31 additions & 12 deletions models/classes/import/class.TestImportForm.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,8 @@
*/
class taoQtiTest_models_classes_import_TestImportForm extends tao_helpers_form_FormContainer
{
// --- ASSOCIATIONS ---
public const METADATA_FORM_ELEMENT_NAME = 'metadata';


// --- ATTRIBUTES ---

// --- OPERATIONS ---
/**
* (non-PHPdoc)
* @see tao_helpers_form_FormContainer::initForm()
Expand Down Expand Up @@ -99,18 +95,41 @@ public function initElements()
)
]);


$this->form->addElement($fileElt);

/*
$disableValidationElt = tao_helpers_form_FormFactory::getElement("disable_validation", 'Checkbox');
$disableValidationElt->setDescription(__("Disable validation"));
$disableValidationElt->setOptions(array("on" => ""));
$this->form->addElement($disableValidationElt);
*/
$this->form->createGroup('file', __('Import a QTI/APIP Content Package'), ['source']);
$this->form->createGroup(
'file',
__('Import a QTI/APIP Content Package'),
[
'source',
]
);

$this->addMetadataImportElement();
$qtiSentElt = tao_helpers_form_FormFactory::getElement('import_sent_qti', 'Hidden');
$qtiSentElt->setValue(1);
$this->form->addElement($qtiSentElt);
}

private function isMetadataDisabled(): bool
{
return isset($this->options[taoQtiTest_models_classes_import_TestImport::DISABLED_FIELDS]) &&
in_array(
taoQtiTest_models_classes_import_TestImport::METADATA_FIELD,
$this->options[taoQtiTest_models_classes_import_TestImport::DISABLED_FIELDS]
);
}

private function addMetadataImportElement()
{
if (!$this->isMetadataDisabled()) {
$metadataImport = tao_helpers_form_FormFactory::getElement(self::METADATA_FORM_ELEMENT_NAME, 'Checkbox');
$metadataImport->setOptions([self::METADATA_FORM_ELEMENT_NAME => __('Import metadata or fail')]);
$metadataImport->setDescription(__('Metadata import'));
$metadataImport->setLevel(1);
$this->form->addElement($metadataImport);
$this->form->addToGroup('file', self::METADATA_FORM_ELEMENT_NAME);
}
}
}
Loading
Loading