tao-test/app/taoQtiTest/models/classes/runner/OfflineQtiRunnerService.php

155 lines
5.0 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) 2019 (original work) Open Assessment Technologies SA ;
*/
/**
* @author Péter Halász <peter@taotesting.com>
*/
namespace oat\taoQtiTest\models\runner;
use oat\oatbox\service\ConfigurableService;
use oat\taoQtiTest\models\runner\map\RunnerMap;
/**
* Service class for the offline version of Qti Test Runner
*/
class OfflineQtiRunnerService extends ConfigurableService
{
const SERVICE_ID = 'taoQtiTest/OfflineQtiRunnerService';
/**
* Returns an array of items, containing also confident data, like branching and response processing rules
*
* @param RunnerServiceContext $serviceContext
* @return array
* @throws \common_Exception
* @throws \common_exception_Error
* @throws \common_exception_InconsistentData
* @throws \common_exception_InvalidArgumentType
*/
public function getItems(RunnerServiceContext $serviceContext)
{
$this->getRunnerService()->assertQtiRunnerServiceContext($serviceContext);
$runnerService = $this->getRunnerService();
$testMap = $runnerService->getTestMap($serviceContext);
$items = [];
foreach ($this->getItemIdentifiersFromTestMap($testMap) as $itemIdentifier) {
$itemRef = $runnerService->getItemHref($serviceContext, $itemIdentifier);
$itemState = $runnerService->getItemState($serviceContext, $itemIdentifier);
if (is_array($itemState) && (0 === count($itemState))) {
$itemState = null;
}
/** @var QtiRunnerServiceContext $serviceContext */
$items[$itemIdentifier] = [
'baseUrl' => $runnerService->getItemPublicUrl($serviceContext, $itemRef),
'itemData' => $this->getItemData($serviceContext, $itemRef),
'itemState' => $itemState,
'itemIdentifier' => $itemIdentifier,
'portableElements' => $runnerService->getItemPortableElements($serviceContext, $itemRef),
];
}
return $items;
}
/**
* Returns the itemData, extending with the variable elements
*
* @param RunnerServiceContext $context
* @param string $itemRef
* @return array
* @throws \common_exception_InvalidArgumentType
* @throws \common_Exception
*/
private function getItemData(RunnerServiceContext $context, $itemRef)
{
$this->getRunnerService()->assertQtiRunnerServiceContext($context);
$itemData = $this->getRunnerService()->getItemData($context, $itemRef);
$itemDataVariable = $this->getRunnerService()->getItemVariableElementsData($context, $itemRef);
$responses = $itemData['data']['responses'];
foreach (array_keys($responses) as $responseId) {
if (array_key_exists($responseId, $itemDataVariable)) {
$itemData['data']['responses'][$responseId] = array_merge(...[
$responses[$responseId],
$itemDataVariable[$responseId],
]);
}
}
return $itemData;
}
/**
* Returns the item identifiers
*
* @param array $testMap
* @return array
*/
private function getItemIdentifiersFromTestMap($testMap)
{
return $this->getSubIdentifiersRecursively($testMap, [
RunnerMap::MAP_ATTRIBUTE_PARTS,
RunnerMap::MAP_ATTRIBUTE_SECTIONS,
RunnerMap::MAP_ATTRIBUTE_ITEMS,
]);
}
/**
* Calls itself recursively to return identifiers from nested arrays
*
* @param $array
* @param $identifiers
* @return array
*/
private function getSubIdentifiersRecursively($array, $identifiers)
{
$identifier = array_shift($identifiers);
if (count($identifiers) > 0) {
$result = [];
foreach ($array[$identifier] as $key => $value) {
$result[] = $this->getSubIdentifiersRecursively(
$array[$identifier][$key],
$identifiers
);
}
return array_merge(...$result);
}
return array_keys($array[$identifier]);
}
/**
* @return ConfigurableService|QtiRunnerService
*/
private function getRunnerService()
{
return $this->getServiceLocator()->get(QtiRunnerService::SERVICE_ID);
}
}