370 lines
13 KiB
PHP
370 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) 2015 (original work) Open Assessment Technologies SA ;
|
||
|
*
|
||
|
*/
|
||
|
|
||
|
namespace oat\taoProctoring\controller;
|
||
|
|
||
|
use common_Exception;
|
||
|
use common_exception_Error;
|
||
|
use common_exception_NotFound;
|
||
|
use common_ext_ExtensionException;
|
||
|
use oat\generis\model\OntologyAwareTrait;
|
||
|
use oat\oatbox\service\exception\InvalidServiceManagerException;
|
||
|
use oat\oatbox\service\ServiceNotFoundException;
|
||
|
use oat\tao\model\accessControl\AclProxy;
|
||
|
use oat\tao\model\mvc\DefaultUrlService;
|
||
|
use oat\taoProctoring\helpers\DeliveryHelper;
|
||
|
use oat\taoProctoring\model\AssessmentResultsService;
|
||
|
use oat\taoProctoring\model\datatable\DeliveriesMonitorDatatable;
|
||
|
use oat\taoProctoring\model\execution\DeliveryExecutionManagerService;
|
||
|
use oat\taoProctoring\model\GuiSettingsService;
|
||
|
use oat\taoProctoring\model\implementation\DeliveryExecutionStateService;
|
||
|
use oat\taoProctoring\model\TestSessionConnectivityStatusService;
|
||
|
use oat\taoProctoring\model\TestSessionHistoryService;
|
||
|
use oat\taoQtiTest\models\QtiTestExtractionFailedException;
|
||
|
|
||
|
/**
|
||
|
* Monitoring Delivery controller
|
||
|
*
|
||
|
* @author Open Assessment Technologies SA
|
||
|
* @package taoProctoring
|
||
|
* @license GPL-2.0
|
||
|
*
|
||
|
*/
|
||
|
class Monitor extends SimplePageModule
|
||
|
{
|
||
|
use OntologyAwareTrait;
|
||
|
|
||
|
const ERROR_AUTHORIZE_EXECUTIONS = 1;
|
||
|
const ERROR_PAUSE_EXECUTIONS = 2;
|
||
|
const ERROR_TERMINATE_EXECUTIONS = 3;
|
||
|
const ERROR_REPORT_IRREGULARITIES = 4;
|
||
|
const ERROR_SET_EXTRA_TIME = 5;
|
||
|
const ERROR_ADJUST_TIME = 6;
|
||
|
|
||
|
/**
|
||
|
* Returns the currently proctored delivery
|
||
|
*
|
||
|
* @return \core_kernel_classes_Resource
|
||
|
*/
|
||
|
protected function getCurrentDelivery()
|
||
|
{
|
||
|
return $this->hasRequestParameter('delivery')
|
||
|
? $this->getResource($this->getRequestParameter('delivery'))
|
||
|
: null;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Gets the view parameters and data to display
|
||
|
* @return array
|
||
|
* @throws common_exception_Error
|
||
|
*/
|
||
|
protected function getViewData()
|
||
|
{
|
||
|
$user = \common_session_SessionManager::getSession()->getUser();
|
||
|
$hasAccessToReactivate = AclProxy::hasAccess($user, MonitorProctorAdministrator::class, 'reactivateExecutions', array());
|
||
|
$delivery = $this->getCurrentDelivery();
|
||
|
/** @var GuiSettingsService $guiSettingsService */
|
||
|
$guiSettingsService = $this->getServiceLocator()->get(GuiSettingsService::SERVICE_ID);
|
||
|
$assessmentResultsService = $this->getServiceLocator()->get(AssessmentResultsService::SERVICE_ID);
|
||
|
$data = [
|
||
|
'ismanageable' => false,
|
||
|
'set' => [],
|
||
|
'extrafields' => DeliveryHelper::getExtraFields(),
|
||
|
'categories' => DeliveryHelper::getAllReasonsCategories($hasAccessToReactivate),
|
||
|
'printReportButton' => $assessmentResultsService->getOption(AssessmentResultsService::OPTION_PRINT_REPORT_BUTTON),
|
||
|
'printReportUrl' => $assessmentResultsService->getScoreReportUrlParts(),
|
||
|
'timeHandling' => $this->getServiceLocator()->get(DeliveryExecutionStateService::SERVICE_ID)->getOption(DeliveryExecutionStateService::OPTION_TIME_HANDLING),
|
||
|
'historyUrl' => $this->getServiceLocator()->get(TestSessionHistoryService::SERVICE_ID)->getHistoryUrl($delivery),
|
||
|
'onlineStatus' => $this->getServiceLocator()->get(TestSessionConnectivityStatusService::SERVICE_ID)->hasOnlineMode(),
|
||
|
'hasAccessToReactivate' => $hasAccessToReactivate
|
||
|
];
|
||
|
|
||
|
$data = array_merge($data, $guiSettingsService->asArray());
|
||
|
|
||
|
if (!is_null($delivery)) {
|
||
|
$data['delivery'] = $delivery->getUri();
|
||
|
}
|
||
|
if ($this->hasRequestParameter('context')) {
|
||
|
$data['context'] = $this->getRequestParameter('context');
|
||
|
}
|
||
|
|
||
|
return $data;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Monitoring view of a selected delivery
|
||
|
*/
|
||
|
public function index()
|
||
|
{
|
||
|
$this->setData('homeUrl', $this->getServiceManager()->get(DefaultUrlService::SERVICE_ID)->getUrl('ProctoringHome'));
|
||
|
$this->setData('logout', $this->getServiceManager()->get(DefaultUrlService::SERVICE_ID)->getUrl('ProctoringLogout'));
|
||
|
$this->composeView('delivery-monitoring', null, 'pages/index.tpl', 'tao');
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Lists all available deliveries
|
||
|
*/
|
||
|
public function monitor()
|
||
|
{
|
||
|
$this->returnJson([
|
||
|
'success' => true,
|
||
|
'data' => $this->getViewData(),
|
||
|
]);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Gets the list of current executions for a delivery
|
||
|
*
|
||
|
* @throws common_Exception
|
||
|
*/
|
||
|
public function deliveryExecutions()
|
||
|
{
|
||
|
$dataTable = new DeliveriesMonitorDatatable($this->getCurrentDelivery(), $this->getRequest());
|
||
|
$this->getServiceManager()->propagate($dataTable);
|
||
|
$this->returnJson($dataTable);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Authorises a delivery execution
|
||
|
*
|
||
|
* @throws common_Exception
|
||
|
* @throws \oat\oatbox\service\ServiceNotFoundException
|
||
|
*/
|
||
|
public function authoriseExecutions()
|
||
|
{
|
||
|
$deliveryExecution = $this->getRequestParameter('execution');
|
||
|
$reason = $this->getRequestParameter('reason');
|
||
|
$testCenter = $this->getRequestParameter('testCenter');
|
||
|
|
||
|
if (!is_array($deliveryExecution)) {
|
||
|
$deliveryExecution = array($deliveryExecution);
|
||
|
}
|
||
|
|
||
|
try {
|
||
|
|
||
|
$data = DeliveryHelper::authoriseExecutions($deliveryExecution, $reason, $testCenter);
|
||
|
|
||
|
$response = [
|
||
|
'success' => !count($data['unprocessed']),
|
||
|
'data' => $data
|
||
|
];
|
||
|
|
||
|
if (!$response['success']) {
|
||
|
$response['errorCode'] = self::ERROR_AUTHORIZE_EXECUTIONS;
|
||
|
$response['errorMsg'] = __('Some delivery executions have not been authorized');
|
||
|
}
|
||
|
|
||
|
$this->returnJson($response);
|
||
|
} catch (QtiTestExtractionFailedException $e) {
|
||
|
$response = [
|
||
|
'success' => false,
|
||
|
'data' => [],
|
||
|
'errorCode' => self::ERROR_AUTHORIZE_EXECUTIONS,
|
||
|
'errorMsg' => __('Decryption failed because of using the wrong customer app key.'),
|
||
|
];
|
||
|
|
||
|
$this->returnJson($response);
|
||
|
} catch (ServiceNotFoundException $e) {
|
||
|
\common_Logger::w('No delivery service defined for proctoring');
|
||
|
$this->returnError('Proctoring interface not available');
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Terminates delivery executions
|
||
|
*
|
||
|
* @throws common_Exception
|
||
|
* @throws \oat\oatbox\service\ServiceNotFoundException
|
||
|
*/
|
||
|
public function terminateExecutions()
|
||
|
{
|
||
|
$deliveryExecution = $this->getRequestParameter('execution');
|
||
|
$reason = $this->getRequestParameter('reason');
|
||
|
|
||
|
if (!is_array($deliveryExecution)) {
|
||
|
$deliveryExecution = array($deliveryExecution);
|
||
|
}
|
||
|
|
||
|
try {
|
||
|
$data = DeliveryHelper::terminateExecutions($deliveryExecution, $reason);
|
||
|
|
||
|
$response = [
|
||
|
'success' => !count($data['unprocessed']),
|
||
|
'data' => $data
|
||
|
];
|
||
|
|
||
|
if (!$response['success']) {
|
||
|
$response['errorCode'] = self::ERROR_TERMINATE_EXECUTIONS;
|
||
|
$response['errorMsg'] = __('Some delivery executions have not been terminated');
|
||
|
}
|
||
|
|
||
|
$this->returnJson($response);
|
||
|
} catch (ServiceNotFoundException $e) {
|
||
|
\common_Logger::w('No delivery service defined for proctoring');
|
||
|
$this->returnError('Proctoring interface not available');
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Pauses delivery executions
|
||
|
*
|
||
|
* @throws common_Exception
|
||
|
* @throws \oat\oatbox\service\ServiceNotFoundException
|
||
|
*/
|
||
|
public function pauseExecutions()
|
||
|
{
|
||
|
$deliveryExecution = $this->getRequestParameter('execution');
|
||
|
$reason = $this->getRequestParameter('reason');
|
||
|
|
||
|
if (!is_array($deliveryExecution)) {
|
||
|
$deliveryExecution = array($deliveryExecution);
|
||
|
}
|
||
|
|
||
|
try {
|
||
|
$data = DeliveryHelper::pauseExecutions($deliveryExecution, $reason);
|
||
|
|
||
|
$response = [
|
||
|
'success' => !count($data['unprocessed']),
|
||
|
'data' => $data
|
||
|
];
|
||
|
|
||
|
if (!$response['success']) {
|
||
|
$response['errorCode'] = self::ERROR_PAUSE_EXECUTIONS;
|
||
|
$response['errorMsg'] = __('Some delivery executions have not been paused');
|
||
|
}
|
||
|
|
||
|
$this->returnJson($response);
|
||
|
} catch (ServiceNotFoundException $e) {
|
||
|
\common_Logger::w('No delivery service defined for proctoring');
|
||
|
$this->returnError('Proctoring interface not available');
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Report irregularities in delivery executions
|
||
|
*
|
||
|
* @throws common_Exception
|
||
|
* @throws \oat\oatbox\service\ServiceNotFoundException
|
||
|
*/
|
||
|
public function reportExecutions()
|
||
|
{
|
||
|
$deliveryExecution = $this->getRequestParameter('execution');
|
||
|
$reason = $this->getRequestParameter('reason');
|
||
|
|
||
|
if (!is_array($deliveryExecution)) {
|
||
|
$deliveryExecution = array($deliveryExecution);
|
||
|
}
|
||
|
|
||
|
try {
|
||
|
$data = DeliveryHelper::reportExecutions($deliveryExecution, $reason);
|
||
|
|
||
|
$response = [
|
||
|
'success' => !count($data['unprocessed']),
|
||
|
'data' => $data
|
||
|
];
|
||
|
|
||
|
if (!$response['success']) {
|
||
|
$response['errorCode'] = self::ERROR_REPORT_IRREGULARITIES;
|
||
|
$response['errorMsg'] = __('Some delivery executions have not been reported');
|
||
|
}
|
||
|
|
||
|
$this->returnJson($response);
|
||
|
} catch (ServiceNotFoundException $e) {
|
||
|
\common_Logger::w('No delivery service defined for proctoring');
|
||
|
$this->returnError('Proctoring interface not available');
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Extra Time handling: add or remove time on delivery executions
|
||
|
*
|
||
|
* @throws common_Exception
|
||
|
*/
|
||
|
public function extraTime()
|
||
|
{
|
||
|
$deliveryExecution = $this->getRequestParameter('execution');
|
||
|
$extraTime = floatval($this->getRequestParameter('time'));
|
||
|
|
||
|
if (!is_array($deliveryExecution)) {
|
||
|
$deliveryExecution = array($deliveryExecution);
|
||
|
}
|
||
|
|
||
|
try {
|
||
|
/** @var DeliveryExecutionManagerService $deliveryExecutionManagerService */
|
||
|
$deliveryExecutionManagerService = $this->getServiceLocator()->get(DeliveryExecutionManagerService::SERVICE_ID);
|
||
|
$data = $deliveryExecutionManagerService->setExtraTime($deliveryExecution, $extraTime);
|
||
|
|
||
|
$response = [
|
||
|
'success' => !count($data['unprocessed']),
|
||
|
'data' => $data
|
||
|
];
|
||
|
|
||
|
if (!$response['success']) {
|
||
|
$response['errorCode'] = self::ERROR_SET_EXTRA_TIME;
|
||
|
$response['errorMsg'] = __('Some delivery executions have not been updated');
|
||
|
}
|
||
|
|
||
|
$this->returnJson($response);
|
||
|
} catch (ServiceNotFoundException $e) {
|
||
|
\common_Logger::w('No delivery service defined for proctoring');
|
||
|
$this->returnError('Proctoring interface not available');
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @throws QtiTestExtractionFailedException
|
||
|
* @throws common_Exception
|
||
|
* @throws common_exception_Error
|
||
|
* @throws common_exception_NotFound
|
||
|
* @throws common_ext_ExtensionException
|
||
|
* @throws InvalidServiceManagerException
|
||
|
*/
|
||
|
public function adjustTime(): void
|
||
|
{
|
||
|
$deliveryExecutions = $this->getPostParameter('execution');
|
||
|
$seconds = $this->getPostParameter('time');
|
||
|
$reason = [
|
||
|
'reasons' => $this->getPostParameter('reasons', []),
|
||
|
'comment' => $this->getPostParameter('comment', ''),
|
||
|
];
|
||
|
|
||
|
if (!is_array($deliveryExecutions)) {
|
||
|
$deliveryExecutions = [$deliveryExecutions];
|
||
|
}
|
||
|
|
||
|
/** @var DeliveryExecutionManagerService $deliveryExecutionManagerService */
|
||
|
$deliveryExecutionManagerService = $this->getServiceLocator()->get(DeliveryExecutionManagerService::SERVICE_ID);
|
||
|
$data = $deliveryExecutionManagerService->adjustTimers($deliveryExecutions, $seconds, $reason);
|
||
|
|
||
|
$response = [
|
||
|
'success' => !count($data['unprocessed']),
|
||
|
'data' => $data
|
||
|
];
|
||
|
|
||
|
if (!$response['success']) {
|
||
|
$response['errorCode'] = self::ERROR_ADJUST_TIME;
|
||
|
$response['errorMsg'] = __('Some delivery executions have not been updated');
|
||
|
}
|
||
|
|
||
|
$this->returnJson($response);
|
||
|
}
|
||
|
}
|