tao-test/app/taoOutcomeUi/scripts/task/ExportDeliveryResults.php

267 lines
11 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) 2017 (original work) Open Assessment Technologies SA (under the project TAO-PRODUCT);
*
*/
namespace oat\taoOutcomeUi\scripts\task;
use common_report_Report as Report;
use oat\generis\model\OntologyAwareTrait;
use oat\oatbox\action\Action;
use oat\tao\model\taskQueue\Task\WorkerContextAwareInterface;
use oat\tao\model\taskQueue\Task\WorkerContextAwareTrait;
use oat\taoOutcomeUi\model\export\DeliveryResultsExporterFactoryInterface;
use oat\taoOutcomeUi\model\export\ResultsExporter;
use oat\taoOutcomeUi\model\export\DeliveryCsvResultsExporterFactory;
use oat\taoOutcomeUi\model\export\SingleDeliverySqlResultsExporter;
use oat\taoOutcomeUi\model\export\DeliverySqlResultsExporterFactory;
use oat\taoOutcomeUi\model\ResultsService;
use Zend\ServiceManager\ServiceLocatorAwareTrait;
use Zend\ServiceManager\ServiceLocatorAwareInterface;
/**
* ExportDeliveryResults action, can be called either during a http request or from cli.
*
* Usage examples for CLI:
*
* If "--dir" is omitted, the file will be saved in the task queue storage.
*
* ```
* sudo -u www-data php index.php 'oat\taoOutcomeUi\scripts\task\ExportDeliveryResults' <deliveryOrClassId>
* sudo -u www-data php index.php 'oat\taoOutcomeUi\scripts\task\ExportDeliveryResults' <deliveryOrClassId> --dir=/home/user/exports
* sudo -u www-data php index.php 'oat\taoOutcomeUi\scripts\task\ExportDeliveryResults' <deliveryOrClassId> --columns=tt,delivery,grades,responses
* sudo -u www-data php index.php 'oat\taoOutcomeUi\scripts\task\ExportDeliveryResults' <deliveryOrClassId> --columns=all
* sudo -u www-data php index.php 'oat\taoOutcomeUi\scripts\task\ExportDeliveryResults' <deliveryOrClassId> --columns=tt,delivery,grades,responses --submittedVersion=lastSubmitted
* ```
* @author Gyula Szucs <gyula@taotesting.com>
*/
class ExportDeliveryResults implements Action, ServiceLocatorAwareInterface, WorkerContextAwareInterface
{
use ServiceLocatorAwareTrait;
use OntologyAwareTrait;
use WorkerContextAwareTrait;
/**
* Possible CLI values for columns
*/
const COLUMNS_CLI_VALUE_ALL = 'all';
const COLUMNS_CLI_VALUE_TEST_TAKER = 'tt';
const COLUMNS_CLI_VALUE_DELIVERY = 'delivery';
const COLUMNS_CLI_VALUE_GRADES = 'grades';
const COLUMNS_CLI_VALUE_RESPONSES = 'responses';
/**
* @var \core_kernel_classes_Resource
*/
private $resourceToExport;
private $exporterService;
private $columns = [];
private $submittedVersion;
private $destination;
private $filters = [];
private $format;
/**
* @var DeliveryResultsExporterFactoryInterface
*/
private $deliveryResultsExporterFactory;
/**
* @param array $params
* @return Report
*/
public function __invoke($params)
{
$this->loadExtensions();
try {
$this->parseParams($params);
if ($this->submittedVersion) {
$this->getExporterService()->setVariableToExport($this->submittedVersion);
}
$fileName = $this->getExporterService()
->setColumnsToExport($this->columns)
->setFiltersToExport($this->filters)
->export($this->destination);
$msg = $fileName
? $this->isWorkerContext()
? __('Results of "%s" successfully exported', $this->resourceToExport->getLabel())
: __('Results of "%s" successfully exported into "%s"', $this->resourceToExport->getLabel(), $fileName)
: __('Nothing to export for "%s"', $this->resourceToExport->getLabel());
return Report::createSuccess($msg, $fileName);
} catch (\Exception $e) {
return Report::createFailure($e->getMessage());
}
}
/**
* @return ResultsExporter
* @throws \common_exception_NotFound
*/
private function getExporterService()
{
if (is_null($this->exporterService)) {
$this->exporterService = new ResultsExporter($this->resourceToExport, ResultsService::singleton(), $this->deliveryResultsExporterFactory);
$this->exporterService->setServiceLocator($this->getServiceLocator());
}
return $this->exporterService;
}
/**
* Load the required TAO extensions (for constants)
*/
private function loadExtensions()
{
$this->getServiceLocator()->get(\common_ext_ExtensionsManager::SERVICE_ID)->getExtensionById('taoOutcomeUi');
$this->getServiceLocator()->get(\common_ext_ExtensionsManager::SERVICE_ID)->getExtensionById('taoDeliveryRdf');
}
/**
* Checks and sets parameters.
*
* Params order:
* - $params[0]: delivery uri (required, string)
* - $params[1]: columns (optional, array|string)
* - $params[2]: submittedVersion (optional, string)
*
* @param array $params
*/
private function parseParams($params)
{
// Delivery or Class Uri
if (!isset($params[0])) {
throw new \InvalidArgumentException('Delivery or class uri missing. Please provide it as the first argument.');
}
$this->resourceToExport = $this->getResource($params[0]);
if ($this->isWorkerContext()) {
// Columns to be exported, if defined
if (isset($params[1]) && is_array($params[1])) {
$this->columns = $params[1];
}
// Submitted version of variables, if defined
if (isset($params[2])) {
$this->submittedVersion = $params[2];
}
if (isset($params[3])) {
$this->filters = $params[3];
}
if (isset($params[4]) && $params[4] === SingleDeliverySqlResultsExporter::RESULT_FORMAT) {
$this->deliveryResultsExporterFactory = new DeliverySqlResultsExporterFactory();
} else {
$this->deliveryResultsExporterFactory = new DeliveryCsvResultsExporterFactory();
}
} else {
// if the task is called from CLI
// remove first param, it is always the resource uri, no need to re-check
unset($params[0]);
// check params. running the command from CLI we have different params structure
foreach ($params as $param) {
list($option, $value) = explode('=', $param);
switch ($option) {
case '--columns':
$columns = explode(',', $value);
$invalidValues = array_diff($columns, $this->getPossibleColumnValues());
if (count($invalidValues)) {
throw new \InvalidArgumentException('Invalid columns value(s) "' . implode(', ', $invalidValues) . '". Valid options: ' . implode(', ', $this->getPossibleColumnValues()));
}
if (in_array(self::COLUMNS_CLI_VALUE_ALL, $columns)) {
// do nothing because SingleDeliveryResultsExporter will use all columns by default if no columns specified
break;
}
foreach ($columns as $column) {
switch ($column) {
case self::COLUMNS_CLI_VALUE_TEST_TAKER:
$this->columns = array_merge($this->columns, $this->getExporterService()->getTestTakerColumns());
break;
case self::COLUMNS_CLI_VALUE_DELIVERY:
$this->columns = array_merge($this->columns, $this->getExporterService()->getDeliveryColumns());
break;
case self::COLUMNS_CLI_VALUE_GRADES:
$this->columns = array_merge($this->columns, $this->getExporterService()->getGradeColumns());
break;
case self::COLUMNS_CLI_VALUE_RESPONSES:
$this->columns = array_merge($this->columns, $this->getExporterService()->getResponseColumns());
break;
}
}
break;
case '--submittedVersion':
if (!in_array($value, [ResultsService::VARIABLES_FILTER_FIRST_SUBMITTED, ResultsService::VARIABLES_FILTER_LAST_SUBMITTED])) {
throw new \InvalidArgumentException('Invalid submitted version of variables "' . $value . '". Valid options: ' . implode(', ', [ResultsService::VARIABLES_FILTER_FIRST_SUBMITTED, ResultsService::VARIABLES_FILTER_LAST_SUBMITTED]));
}
$this->submittedVersion = $value;
break;
case '--dir':
if (!is_dir($value)) {
throw new \InvalidArgumentException('Invalid directory "' . $value . '" provided.');
}
if (!is_writable($value)) {
throw new \InvalidArgumentException('Directory "' . $value . '" not writable.');
}
$this->destination = $value;
break;
case '--start-from':
$this->filters['startfrom'] = $value;
break;
case '--start-to':
$this->filters['startto'] = $value;
break;
}
}
}
}
/**
* @return array
*/
private function getPossibleColumnValues()
{
return [
self::COLUMNS_CLI_VALUE_ALL,
self::COLUMNS_CLI_VALUE_TEST_TAKER,
self::COLUMNS_CLI_VALUE_DELIVERY,
self::COLUMNS_CLI_VALUE_GRADES,
self::COLUMNS_CLI_VALUE_RESPONSES
];
}
}