416 lines
13 KiB
PHP
416 lines
13 KiB
PHP
|
<?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) 2014 (original work) Open Assessment Technologies SA;
|
||
|
*/
|
||
|
|
||
|
namespace oat\taoQtiItem\test\integration;
|
||
|
|
||
|
use common_exception_Error;
|
||
|
use \common_report_Report;
|
||
|
use oat\tao\test\TaoPhpUnitTestRunner;
|
||
|
use oat\taoQtiItem\model\Export\QTIPackedItemExporter;
|
||
|
use oat\taoQtiItem\model\qti\exception\ParsingException;
|
||
|
use oat\taoQtiItem\model\qti\ImportService;
|
||
|
use oat\taoQtiItem\model\QtiItemCompiler;
|
||
|
use \taoItems_models_classes_ItemsService;
|
||
|
use \tao_models_classes_service_FileStorage;
|
||
|
use \ZipArchive;
|
||
|
use oat\taoItems\model\media\LocalItemSource;
|
||
|
use oat\taoQtiItem\model\ItemModel;
|
||
|
|
||
|
include_once dirname(__FILE__) . '/../../includes/raw_start.php';
|
||
|
/**
|
||
|
* test the item content access
|
||
|
*
|
||
|
*/
|
||
|
class ItemImportTest extends TaoPhpUnitTestRunner
|
||
|
{
|
||
|
/**
|
||
|
* @var ImportService
|
||
|
*/
|
||
|
protected $importService;
|
||
|
/**
|
||
|
* @var taoItems_models_classes_ItemsService
|
||
|
*/
|
||
|
protected $itemService;
|
||
|
/**
|
||
|
* @var array
|
||
|
*/
|
||
|
protected $exportedZips = [];
|
||
|
|
||
|
/**
|
||
|
* tests initialization
|
||
|
* load qti service
|
||
|
*/
|
||
|
public function setUp(): void
|
||
|
{
|
||
|
TaoPhpUnitTestRunner::initTest();
|
||
|
$this->importService = ImportService::singleton();
|
||
|
$this->itemService = taoItems_models_classes_ItemsService::singleton();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @return string
|
||
|
*/
|
||
|
protected function getSamplePath($relPath)
|
||
|
{
|
||
|
return __DIR__ . DIRECTORY_SEPARATOR . 'samples' . str_replace('/', DIRECTORY_SEPARATOR, $relPath);
|
||
|
}
|
||
|
|
||
|
public function testWrongPackage()
|
||
|
{
|
||
|
$this->expectException(ParsingException::class);
|
||
|
$itemClass = $this->itemService->getRootClass();
|
||
|
$report = $this->importService->importQTIPACKFile(
|
||
|
$this->getSamplePath('/package/wrong/InvalidArchive.zip'),
|
||
|
$itemClass
|
||
|
);
|
||
|
}
|
||
|
|
||
|
public function testWrongClass()
|
||
|
{
|
||
|
$this->expectException(common_exception_Error::class);
|
||
|
$itemClass = new \core_kernel_classes_Class(taoItems_models_classes_ItemsService::PROPERTY_ITEM_MODEL);
|
||
|
$report = $this->importService->importQTIPACKFile(
|
||
|
$this->getSamplePath('/package/wrong/package.zip'),
|
||
|
$itemClass
|
||
|
);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
*
|
||
|
*/
|
||
|
public function testWrongFormatClass()
|
||
|
{
|
||
|
$itemClass = $this->itemService->getRootClass();
|
||
|
|
||
|
$report = $this->importService->importQTIPACKFile(
|
||
|
$this->getSamplePath('/package/wrong/MalformedItemXml.zip'),
|
||
|
$itemClass,
|
||
|
true,
|
||
|
true
|
||
|
);
|
||
|
$this->assertEquals(\common_report_Report::TYPE_ERROR, $report->getType());
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
*
|
||
|
*/
|
||
|
public function testWrongFormatXmlClass()
|
||
|
{
|
||
|
$itemClass = $this->itemService->getRootClass();
|
||
|
|
||
|
$report = $this->importService->importQTIPACKFile(
|
||
|
$this->getSamplePath('/package/wrong/MalformedItemInTheMiddleXml.zip'),
|
||
|
$itemClass,
|
||
|
true,
|
||
|
false,
|
||
|
true
|
||
|
);
|
||
|
$this->assertEquals(\common_report_Report::TYPE_WARNING, $report->getType());
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
*
|
||
|
*/
|
||
|
public function testWrongManifest()
|
||
|
{
|
||
|
$itemClass = $this->itemService->getRootClass();
|
||
|
|
||
|
|
||
|
$report = $this->importService->importQTIPACKFile(
|
||
|
$this->getSamplePath('/package/wrong/MalformedManifest.zip'),
|
||
|
$itemClass,
|
||
|
true,
|
||
|
true
|
||
|
);
|
||
|
$this->assertEquals(\common_report_Report::TYPE_ERROR, $report->getType());
|
||
|
}
|
||
|
/**
|
||
|
*
|
||
|
*/
|
||
|
public function testWrongXml()
|
||
|
{
|
||
|
|
||
|
$itemClass = $this->itemService->getRootClass();
|
||
|
|
||
|
$report = $this->importService->importQTIPACKFile(
|
||
|
$this->getSamplePath('/package/wrong/WrongManifestFileItemHref.zip'),
|
||
|
$itemClass,
|
||
|
true,
|
||
|
true
|
||
|
);
|
||
|
$this->assertEquals(\common_report_Report::TYPE_ERROR, $report->getType());
|
||
|
}
|
||
|
|
||
|
|
||
|
public function testImportQti20()
|
||
|
{
|
||
|
$itemClass = $this->itemService->getRootClass();
|
||
|
$report = $this->importService->importQTIPACKFile(
|
||
|
$this->getSamplePath('/package/QTI/qti20.zip'),
|
||
|
$itemClass
|
||
|
);
|
||
|
$this->assertEquals(\common_report_Report::TYPE_SUCCESS, $report->getType());
|
||
|
|
||
|
$items = [];
|
||
|
foreach ($report as $itemReport) {
|
||
|
$this->assertEquals(\common_report_Report::TYPE_SUCCESS, $itemReport->getType());
|
||
|
$data = $itemReport->getData();
|
||
|
if (!is_null($data)) {
|
||
|
$items[] = $data;
|
||
|
}
|
||
|
}
|
||
|
$this->assertEquals(2, count($items));
|
||
|
$this->removeItem($items[1]);
|
||
|
|
||
|
return $items[0];
|
||
|
}
|
||
|
|
||
|
public function testImportApipv1p0Final()
|
||
|
{
|
||
|
$itemClass = $this->itemService->getRootClass();
|
||
|
$report = $this->importService->importQTIPACKFile($this->getSamplePath('/package/APIP/apip_v1p0_final.zip'), $itemClass);
|
||
|
$this->assertEquals(\common_report_Report::TYPE_SUCCESS, $report->getType());
|
||
|
|
||
|
$items = [];
|
||
|
foreach ($report as $itemReport) {
|
||
|
$this->assertEquals(\common_report_Report::TYPE_SUCCESS, $itemReport->getType());
|
||
|
$data = $itemReport->getData();
|
||
|
if ($data !== null) {
|
||
|
$items[] = $data;
|
||
|
}
|
||
|
}
|
||
|
$this->assertCount(1, $items);
|
||
|
$this->removeItem($items[0]);
|
||
|
}
|
||
|
|
||
|
public function testImportPCI()
|
||
|
{
|
||
|
$itemClass = $this->itemService->getRootClass();
|
||
|
$report = $this->importService->importQTIPACKFile(
|
||
|
$this->getSamplePath('/package/PCI/pcisample.zip'),
|
||
|
$itemClass
|
||
|
);
|
||
|
$this->assertEquals(\common_report_Report::TYPE_SUCCESS, $report->getType());
|
||
|
|
||
|
$items = [];
|
||
|
foreach ($report as $itemReport) {
|
||
|
$this->assertEquals(\common_report_Report::TYPE_SUCCESS, $itemReport->getType());
|
||
|
$data = $itemReport->getData();
|
||
|
if (!is_null($data)) {
|
||
|
$items[] = $data;
|
||
|
}
|
||
|
}
|
||
|
$this->assertEquals(1, count($items));
|
||
|
$item = \oat\taoQtiItem\model\qti\Service::singleton()->getDataItemByRdfItem($items[0], DEFAULT_LANG, false);
|
||
|
|
||
|
$itemData = $item->toArray();
|
||
|
$itemDataElemetns = current($itemData['body']['elements']);
|
||
|
|
||
|
//ensure that path prefixed with interaction identifies was not changed;
|
||
|
$this->assertEquals($itemDataElemetns['entryPoint'], "adaptiveChoiceInteraction/runtime/adaptiveChoiceInteraction.js");
|
||
|
//ensure that interaction properties imported properly
|
||
|
$this->assertTrue(isset($itemDataElemetns['properties']['choices'][0]['label']));
|
||
|
|
||
|
foreach ($items as $item) {
|
||
|
$this->itemService->deleteItem($item);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public function testImport()
|
||
|
{
|
||
|
$itemClass = $this->itemService->getRootClass();
|
||
|
$report = $this->importService->importQTIPACKFile(
|
||
|
$this->getSamplePath('/package/QTI/package.zip'),
|
||
|
$itemClass
|
||
|
);
|
||
|
|
||
|
$items = [];
|
||
|
foreach ($report as $itemReport) {
|
||
|
$data = $itemReport->getData();
|
||
|
if (!is_null($data)) {
|
||
|
$items[] = $data;
|
||
|
}
|
||
|
}
|
||
|
$this->assertEquals(1, count($items));
|
||
|
|
||
|
$item = current($items);
|
||
|
$this->assertInstanceOf('\core_kernel_classes_Resource', $item);
|
||
|
$this->assertTrue($item->exists());
|
||
|
|
||
|
$resourceManager = new LocalItemSource(
|
||
|
[ 'item' => $item,
|
||
|
'lang' => DEFAULT_LANG]
|
||
|
);
|
||
|
$data = $resourceManager->getDirectory();
|
||
|
$this->assertTrue(is_array($data));
|
||
|
$this->assertTrue(isset($data['path']));
|
||
|
$this->assertEquals('/', $data['path']);
|
||
|
|
||
|
$this->assertTrue(isset($data['children']));
|
||
|
$children = $data['children'];
|
||
|
$this->assertEquals(3, count($children));
|
||
|
|
||
|
$check = ['/images/','/style/'];
|
||
|
|
||
|
$file = null;
|
||
|
$dir = null;
|
||
|
foreach ($children as $child) {
|
||
|
if (isset($child['path'])) {
|
||
|
$this->assertContains($child['path'], $check);
|
||
|
}
|
||
|
if (isset($child['name'])) {
|
||
|
$file = $child;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
$this->assertEquals("qti.xml", $file['name']);
|
||
|
$this->assertStringContainsString("/xml", $file['mime']);
|
||
|
$this->assertTrue($file['size'] > 0);
|
||
|
|
||
|
|
||
|
return $item;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @depends testImport
|
||
|
* @param $item
|
||
|
*/
|
||
|
public function testCompile($item)
|
||
|
{
|
||
|
$storage = tao_models_classes_service_FileStorage::singleton();
|
||
|
$compiler = new QtiItemCompiler($item, $storage);
|
||
|
$compiler->setServiceLocator($this->getServiceManagerProphecy());
|
||
|
$report = $compiler->compile();
|
||
|
$this->assertEquals($report->getType(), common_report_Report::TYPE_SUCCESS);
|
||
|
$serviceCall = $report->getData();
|
||
|
$this->assertNotNull($serviceCall);
|
||
|
$this->assertInstanceOf('\tao_models_classes_service_ServiceCall', $serviceCall);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @depends testImport
|
||
|
* @param $item
|
||
|
* @throws Exception
|
||
|
* @throws \oat\taoQtiItem\model\qti\exception\ExtractException
|
||
|
* @throws \oat\taoQtiItem\model\qti\exception\ParsingException
|
||
|
* @return mixed
|
||
|
*/
|
||
|
public function testExport($item)
|
||
|
{
|
||
|
$itemClass = $this->itemService->getRootClass();
|
||
|
|
||
|
list($path, $manifest) = $this->createZipArchive($item);
|
||
|
|
||
|
$report = $this->importService->importQTIPACKFile($path, $itemClass);
|
||
|
$this->assertEquals(\common_report_Report::TYPE_SUCCESS, $report->getType());
|
||
|
$items = [];
|
||
|
foreach ($report as $itemReport) {
|
||
|
$data = $itemReport->getData();
|
||
|
if (!is_null($data)) {
|
||
|
$items[] = $data;
|
||
|
}
|
||
|
}
|
||
|
$this->assertEquals(1, count($items));
|
||
|
$item2 = current($items);
|
||
|
$this->assertInstanceOf('\core_kernel_classes_Resource', $item);
|
||
|
$this->assertTrue($item->exists());
|
||
|
|
||
|
$this->assertEquals($item->getLabel(), $item2->getLabel());
|
||
|
|
||
|
$this->removeItem($item2);
|
||
|
|
||
|
return $manifest;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @depends testImportQti20
|
||
|
* @depends testExport
|
||
|
* @param $item
|
||
|
* @param $manifest
|
||
|
* @return mixed
|
||
|
*/
|
||
|
public function testExportWithManifest($item, $manifest)
|
||
|
{
|
||
|
list($path, $manifest2) = $this->createZipArchive($item, $manifest);
|
||
|
$this->assertSame($manifest, $manifest2);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @depends testImportQti20
|
||
|
* @depends testImport
|
||
|
*/
|
||
|
public function testRemoveItem()
|
||
|
{
|
||
|
foreach (func_get_args() as $item) {
|
||
|
$this->removeItem($item);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
private function removeItem($item)
|
||
|
{
|
||
|
$this->itemService->deleteItem($item);
|
||
|
$this->assertFalse($item->exists());
|
||
|
}
|
||
|
|
||
|
public function tearDown(): void
|
||
|
{
|
||
|
|
||
|
foreach ($this->exportedZips as $path) {
|
||
|
if (file_exists($path)) {
|
||
|
$this->assertTrue(unlink($path));
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @param $item
|
||
|
* @param $manifest
|
||
|
* @return array
|
||
|
* @throws \Exception
|
||
|
*/
|
||
|
private function createZipArchive($item, $manifest = null)
|
||
|
{
|
||
|
$path = sys_get_temp_dir() . DIRECTORY_SEPARATOR . uniqid('test_') . '.zip';
|
||
|
$zipArchive = new ZipArchive();
|
||
|
if ($zipArchive->open($path, ZipArchive::CREATE) !== true) {
|
||
|
throw new \Exception('Unable to create archive at ' . $path);
|
||
|
}
|
||
|
|
||
|
if ($this->itemService->hasItemModel($item, [ItemModel::MODEL_URI])) {
|
||
|
$exporter = new QTIPackedItemExporter($item, $zipArchive, $manifest);
|
||
|
$exporter->export();
|
||
|
$manifest = $exporter->getManifest();
|
||
|
}
|
||
|
|
||
|
$this->assertTrue($this->itemService->hasItemModel($item, [ItemModel::MODEL_URI]));
|
||
|
|
||
|
$this->assertNotNull($manifest);
|
||
|
|
||
|
$this->assertEquals(ZipArchive::ER_OK, $zipArchive->status, $zipArchive->getStatusString());
|
||
|
|
||
|
$zipArchive->close();
|
||
|
$this->assertTrue(file_exists($path), 'could not find path ' . $path);
|
||
|
$this->exportedZips[] = $path;
|
||
|
return [$path, $manifest];
|
||
|
}
|
||
|
}
|