<?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); } }