imsManifestInjector = new ImsManifestMetadataInjector(); } public function tearDown(): void { parent::tearDown(); unset($this->imsManifestInjector); } /** * @dataProvider injectionProvider * * @param string $inputFile * @param array $values * @param array $mappings */ public function testInjection($inputFile, array $values, array $mappings) { $imsManifest = new DOMDocument('1.0', 'UTF-8'); $imsManifest->load(dirname(__FILE__) . "/../samples/metadata/imsManifestInjection/${inputFile}"); // Register mappings... foreach ($mappings as $mapping) { $this->imsManifestInjector->addMapping($mapping); } $this->imsManifestInjector->inject($imsManifest, $values); $newDom = new DOMDocument('1.0', 'UTF-8'); $newDom->loadXML($imsManifest->saveXML()); $imsManifest = $newDom; $xpath = new DOMXpath($imsManifest); $xpath->registerNamespace('man', $imsManifest->documentElement->namespaceURI); // Check everything is fine regarding mappings... foreach ($mappings as $mapping) { $prefix = $mapping->getPrefix(); $ns = $mapping->getNamespace(); $sc = $mapping->getSchemaLocation(); $xpath->registerNamespace($prefix, $ns); $manifestElt = $imsManifest->documentElement; $this->assertEquals('manifest', $manifestElt->tagName, "No element found as the root XML element for file '${inputFile}'."); // Check that the namespace is correctly declared in element. $this->assertTrue($manifestElt->hasAttributeNS('http://www.w3.org/2000/xmlns/', "${prefix}"), "No namespace with prefix '${prefix}' declared in element for file '${inputFile}'."); $nsDeclaration = $manifestElt->getAttribute("xmlns:${prefix}"); $this->assertEquals($ns, $nsDeclaration, "Namespace declaration for namespace '${ns}' with prefix '${prefix}' in element does not match for file '${inputFile}'."); // Check that we get the tuple in xsi:schemaLocation. $this->assertTrue($manifestElt->hasAttribute('xsi:schemaLocation'), "No xsd:schemaLocation attribute found in element for file '${inputFile}'."); $schemaLocations = $manifestElt->getAttribute('xsi:schemaLocation'); $xsiPattern = '@' . preg_quote($ns) . "\\s+" . preg_quote($sc) . '@'; $this->assertEquals(1, preg_match($xsiPattern, $schemaLocations), "No xsi:schemaLocation found for namespace '${ns}' in file '${inputFile}'."); } foreach ($values as $resourceIdentifier => $metadataValues) { foreach ($metadataValues as $metadataValue) { $path = $metadataValue->getPath(); $query = "//man:resource[@identifier='${resourceIdentifier}']/man:metadata"; foreach ($path as $pathComponent) { $parts = explode('#', $pathComponent); $base = $parts[0]; $tag = $parts[1]; // do we have a namespace mapping for that? $mappings = $this->imsManifestInjector->getMappings(); $mapping = null; foreach ($mappings as $m) { if ($m->getNamespace() === $base) { $mapping = $m; break; } } $prefix = $mapping->getPrefix(); $query .= "/${prefix}:${tag}"; } // Do we have something at location? $elts = $xpath->query($query); $this->assertGreaterThanOrEqual(1, $elts->length, "Nothing found in XML at path '" . implode(' -> ', $path) . "' in file '${inputFile}'."); $hasLang = $metadataValue->getLanguage() !== ''; // Does one of the values contain the expected value? for ($i = 0; $i < $elts->length; $i++) { $valueMatch = $elts->item($i)->nodeValue === $metadataValue->getValue(); $langMatch = false; if ($hasLang === false || $elts->item($i)->getAttribute('xml:lang') === $metadataValue->getLanguage()) { $langMatch = true; } if ($valueMatch === true && $langMatch === true) { break; } } $this->assertLessThan($elts->length, $i, "No matching value found at path '" . implode(' -> ', $path) . "' in file '${inputFile}'."); } } } public function injectionProvider() { return [ [ 'sample1.xml', [ 'choice' => [ new SimpleMetadataValue( 'choice', [ 'http://www.imsglobal.org/xsd/imsmd_v1p2#lom', 'http://www.imsglobal.org/xsd/imsmd_v1p2#general', 'http://www.imsglobal.org/xsd/imsmd_v1p2#identifier' ], 'qti_v2_item_01' ) ] ], [ new ImsManifestMapping('http://www.imsglobal.org/xsd/imsmd_v1p2', 'imsmd', 'http://www.imsglobal.org/xsd/imsmd_v1p2p2.xsd') ] ], [ 'sample2.xml', [ 'choice' => [ new SimpleMetadataValue( 'choice', [ 'http://www.imsglobal.org/xsd/imsmd_v1p2#lom', 'http://www.imsglobal.org/xsd/imsmd_v1p2#general', 'http://www.imsglobal.org/xsd/imsmd_v1p2#identifier' ], 'qti_v2_item_01' ), new SimpleMetadataValue( 'choice', [ 'http://www.imsglobal.org/xsd/imsmd_v1p2#lom', 'http://www.imsglobal.org/xsd/imsmd_v1p2#general', 'http://www.imsglobal.org/xsd/imsmd_v1p2#title', 'http://www.imsglobal.org/xsd/imsmd_v1p2#langstring' ], 'Metadata Example Item #1', 'en' ), new SimpleMetadataValue( 'choice', [ 'http://www.imsglobal.org/xsd/imsmd_v1p2#lom', 'http://www.imsglobal.org/xsd/imsmd_v1p2#general', 'http://www.imsglobal.org/xsd/imsmd_v1p2#description', 'http://www.imsglobal.org/xsd/imsmd_v1p2#langstring' ], 'This is a dummy item', 'en' ), new SimpleMetadataValue( 'choice', [ 'http://www.imsglobal.org/xsd/imsqti_v2p0#qtiMetadata', 'http://www.imsglobal.org/xsd/imsqti_v2p0#timeDependent' ], 'false' ), new SimpleMetadataValue( 'choice', [ 'http://www.imsglobal.org/xsd/imsqti_v2p0#qtiMetadata', 'http://www.imsglobal.org/xsd/imsqti_v2p0#interactionType' ], 'choiceInteraction' ), new SimpleMetadataValue( 'choice', [ 'http://www.imsglobal.org/xsd/imsqti_v2p0#qtiMetadata', 'http://www.imsglobal.org/xsd/imsqti_v2p0#feedbackType' ], 'nonadaptive' ), new SimpleMetadataValue( 'choice', [ 'http://www.imsglobal.org/xsd/imsqti_v2p0#qtiMetadata', 'http://www.imsglobal.org/xsd/imsqti_v2p0#solutionAvailable' ], 'true' ), new SimpleMetadataValue( 'choice', [ 'http://www.imsglobal.org/xsd/imsqti_v2p0#qtiMetadata', 'http://www.imsglobal.org/xsd/imsqti_v2p0#toolName' ], 'XMLSPY' ), new SimpleMetadataValue( 'choice', [ 'http://www.imsglobal.org/xsd/imsqti_v2p0#qtiMetadata', 'http://www.imsglobal.org/xsd/imsqti_v2p0#toolVersion' ], '5.4' ), new SimpleMetadataValue( 'choice', [ 'http://www.imsglobal.org/xsd/imsqti_v2p0#qtiMetadata', 'http://www.imsglobal.org/xsd/imsqti_v2p0#toolVendor' ], 'ALTOVA' ) ], 'hybrid' => [ new SimpleMetadataValue( 'hybrid', [ 'http://www.imsglobal.org/xsd/imsmd_v1p2#lom', 'http://www.imsglobal.org/xsd/imsmd_v1p2#general', 'http://www.imsglobal.org/xsd/imsmd_v1p2#identifier' ], 'qti_v2_item_02' ), new SimpleMetadataValue( 'hybrid', [ 'http://www.imsglobal.org/xsd/imsqti_v2p0#qtiMetadata', 'http://www.imsglobal.org/xsd/imsqti_v2p0#interactionType' ], 'choiceInteraction' ), new SimpleMetadataValue( 'hybrid', [ 'http://www.imsglobal.org/xsd/imsqti_v2p0#qtiMetadata', 'http://www.imsglobal.org/xsd/imsqti_v2p0#interactionType' ], 'orderInteraction' ), ], ], [ new ImsManifestMapping('http://www.imsglobal.org/xsd/imsmd_v1p2', 'imsmd', 'http://www.imsglobal.org/xsd/imsmd_v1p2p2.xsd'), new ImsManifestMapping('http://www.imsglobal.org/xsd/imsqti_v2p0', 'imsqti', 'http://www.imsglobal.org/xsd/imsqti_v2p0.xsd') ] ], [ 'sample3.xml', [ 'Q01' => [ new SimpleMetadataValue( 'choice', [ 'http://www.taotesting.com/xsd/mpm#myprojectMetadata', 'http://www.taotesting.com/xsd/mpm#complexity' ], '4' ) ] ], [ new ImsManifestMapping('http://www.taotesting.com/xsd/mpm', 'mpm', 'http://www.taotesting.com/xsd/mpm.xsd') ] ], ]; } }