/** * Stores the state object and the response set of a particular item */ public function submitItem() { $code = 200; $itemRef = $this->getRequestParameter('itemDefinition'); $itemDuration = $this->getRequestParameter('itemDuration'); $consumedExtraTime = $this->getRequestParameter('consumedExtraTime'); $data = \taoQtiCommon_helpers_Utils::readJsonPayload(); if (isset($data['itemDuration'])) { $itemDuration = $data['itemDuration']; } if (isset($data['consumedExtraTime'])) { $consumedExtraTime = $data['consumedExtraTime']; } $state = isset($data['itemState']) ? $data['itemState'] : new stdClass(); $itemResponse = isset($data['itemResponse']) ? $data['itemResponse'] : []; $emptyAllowed = isset($data['emptyAllowed']) ? $data['emptyAllowed'] : false; try { // get the service context, but do not perform the test state check, // as we need to store the item state whatever the test state is $serviceContext = $this->getServiceContext(false); if (!$this->runnerService->isTerminated($serviceContext)) { $this->runnerService->endTimer($serviceContext, $itemDuration, $consumedExtraTime); $successState = $this->runnerService->setItemState($serviceContext, $this->getStateId(), $state); } else { $successState = false; } // do not allow to store the response if the session is in a wrong state $this->runnerService->check($serviceContext); $responses = $this->runnerService->parsesItemResponse($serviceContext, $itemRef, $itemResponse); $allowed = true; $session = $serviceContext->getTestSession(); if (!$emptyAllowed && !TestRunnerUtils::doesAllowSkipping($session) && $this->runnerService->getTestConfig()->getConfigValue('enableAllowSkipping')) { $allowed = !$this->runnerService->emptyResponse($serviceContext, $responses); } if ($allowed) { $successResponse = $this->runnerService->storeItemResponse($serviceContext, $itemRef, $responses); $displayFeedback = $this->runnerService->displayFeedbacks($serviceContext); $response = ['success' => $successState && $successResponse, 'displayFeedbacks' => $displayFeedback]; if ($displayFeedback == true) { //FIXME there is here a performance issue, at the end we need the defitions only once, not at each storage $response['feedbacks'] = $this->runnerService->getFeedbacks($serviceContext, $itemRef); $response['itemSession'] = $this->runnerService->getItemSession($serviceContext); } $this->runnerService->persist($serviceContext); } else { // we need a complete service context in order to build the test context $serviceContext->init(); $response = ['success' => true, 'notAllowed' => true, 'message' => __('A response to this item is required.'), 'testContext' => $this->runnerService->getTestContext($serviceContext)]; // start the timer only after context build to avoid timing error $this->runnerService->startTimer($serviceContext); } } catch (common_Exception $e) { $response = $this->getErrorResponse($e); $code = $this->getErrorCode($e); } $this->returnJson($response, $code); }