519 lines
19 KiB
PHP
519 lines
19 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.
|
|
*
|
|
*/
|
|
|
|
namespace oat\taoDeliveryRdf\controller;
|
|
|
|
use common_exception_RestApi;
|
|
use core_kernel_classes_Class;
|
|
use oat\generis\model\kernel\persistence\smoothsql\search\ComplexSearchService;
|
|
use oat\oatbox\event\EventManager;
|
|
use oat\search\base\exception\SearchGateWayExeption;
|
|
use oat\tao\model\taskQueue\QueueDispatcher;
|
|
use oat\tao\model\taskQueue\TaskLog\Broker\TaskLogBrokerInterface;
|
|
use oat\tao\model\taskQueue\TaskLog\Entity\EntityInterface;
|
|
use oat\tao\model\taskQueue\TaskLog\TaskLogFilter;
|
|
use oat\tao\model\taskQueue\TaskLogActionTrait;
|
|
use oat\tao\model\taskQueue\TaskLogInterface;
|
|
use oat\taoDeliveryRdf\model\Delete\DeliveryDeleteTask;
|
|
use oat\taoDeliveryRdf\model\DeliveryAssemblyService;
|
|
use oat\generis\model\OntologyRdfs;
|
|
use oat\taoDeliveryRdf\model\DeliveryFactory;
|
|
use oat\taoDeliveryRdf\model\tasks\CompileDelivery;
|
|
use oat\taoDeliveryRdf\model\tasks\UpdateDelivery;
|
|
|
|
class RestDelivery extends \tao_actions_RestController
|
|
{
|
|
use TaskLogActionTrait;
|
|
|
|
const REST_DELIVERY_TEST_ID = 'test';
|
|
const REST_DELIVERY_SEARCH_PARAMS = 'searchParams';
|
|
const REST_DELIVERY_ID = 'delivery';
|
|
const REST_DELIVERY_CLASS_URI = 'delivery-uri';
|
|
const REST_DELIVERY_CLASS_LABEL = 'delivery-label';
|
|
const REST_DELIVERY_CLASS_PARENT = 'delivery-parent';
|
|
const REST_DELIVERY_CLASS_COMMENT = 'delivery-comment';
|
|
const TASK_ID_PARAM = 'id';
|
|
|
|
const CLASS_LABEL_PARAM = 'delivery-label';
|
|
const CLASS_COMMENT_PARAM = 'delivery-comment';
|
|
const PARENT_CLASS_URI_PARAM = 'delivery-parent';
|
|
|
|
/**
|
|
* @return EventManager
|
|
*/
|
|
protected function getEventManager()
|
|
{
|
|
return $this->getServiceLocator()->get(EventManager::SERVICE_ID);
|
|
}
|
|
|
|
/**
|
|
* Generate a delivery from test uri
|
|
* Test uri has to be set and existing
|
|
*/
|
|
public function generate()
|
|
{
|
|
try {
|
|
if (!$this->hasRequestParameter(self::REST_DELIVERY_TEST_ID)) {
|
|
throw new \common_exception_MissingParameter(self::REST_DELIVERY_TEST_ID, $this->getRequestURI());
|
|
}
|
|
|
|
$test = $this->getResource($this->getRequestParameter(self::REST_DELIVERY_TEST_ID));
|
|
if (!$test->exists()) {
|
|
throw new common_exception_RestApi('Unable to find a test associated to the given uri.');
|
|
}
|
|
|
|
$label = 'Delivery of ' . $test->getLabel();
|
|
$deliveryClass = $this->getDeliveryClassByParameters();
|
|
|
|
$deliveryFactory = $this->getServiceManager()->get(DeliveryFactory::SERVICE_ID);
|
|
/** @var \common_report_Report $report */
|
|
$report = $deliveryFactory->create($deliveryClass, $test, $label);
|
|
|
|
if ($report->getType() == \common_report_Report::TYPE_ERROR) {
|
|
$this->logInfo('Unable to generate delivery execution ' .
|
|
'into taoDeliveryRdf::RestDelivery for test uri ' . $test->getUri());
|
|
throw new \common_Exception('Unable to generate delivery execution.');
|
|
}
|
|
$delivery = $report->getData();
|
|
|
|
/** @var DeliveryFactory $deliveryFactoryService */
|
|
$deliveryFactoryService = $this->getServiceManager()->get(DeliveryFactory::SERVICE_ID);
|
|
$initialProperties = $deliveryFactoryService->getInitialPropertiesFromRequest($this->getRequest());
|
|
$delivery = $deliveryFactoryService->setInitialProperties($initialProperties, $delivery);
|
|
$this->returnSuccess(['delivery' => $delivery->getUri()]);
|
|
} catch (\Exception $e) {
|
|
$this->returnFailure($e);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Put task to generate a delivery from test uri to the task queue
|
|
* Test uri has to be set and existing
|
|
*/
|
|
public function generateDeferred()
|
|
{
|
|
try {
|
|
if (! $this->hasRequestParameter(self::REST_DELIVERY_TEST_ID)) {
|
|
throw new \common_exception_MissingParameter(self::REST_DELIVERY_TEST_ID, $this->getRequestURI());
|
|
}
|
|
|
|
$test = $this->getResource($this->getRequestParameter(self::REST_DELIVERY_TEST_ID));
|
|
if (! $test->exists()) {
|
|
throw new common_exception_RestApi('Unable to find a test associated to the given uri.');
|
|
}
|
|
|
|
$deliveryClass = $this->getDeliveryClassByParameters();
|
|
|
|
/** @var DeliveryFactory $deliveryFactoryService */
|
|
$deliveryFactoryService = $this->getServiceManager()->get(DeliveryFactory::SERVICE_ID);
|
|
$initialProperties = $deliveryFactoryService->getInitialPropertiesFromRequest($this->getRequest());
|
|
|
|
$task = CompileDelivery::createTask($test, $deliveryClass, $initialProperties);
|
|
|
|
$result = [
|
|
'reference_id' => $task->getId()
|
|
];
|
|
|
|
/** @var TaskLogInterface $taskLog */
|
|
$taskLog = $this->getServiceManager()->get(TaskLogInterface::SERVICE_ID);
|
|
|
|
$report = $taskLog->getReport($task->getId());
|
|
|
|
if (!empty($report)) {
|
|
if ($report instanceof \common_report_Report) {
|
|
//serialize report to array
|
|
$report = json_decode($report);
|
|
}
|
|
$result['common_report_Report'] = $report;
|
|
}
|
|
|
|
return $this->returnSuccess($result);
|
|
} catch (\Exception $e) {
|
|
$this->returnFailure($e);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Update delivery by parameters
|
|
*/
|
|
public function update()
|
|
{
|
|
try {
|
|
if ($this->getRequestMethod() !== \Request::HTTP_POST) {
|
|
throw new \common_exception_NotImplemented('Only post method is accepted to updating delivery');
|
|
}
|
|
|
|
if (! $this->hasRequestParameter(self::REST_DELIVERY_SEARCH_PARAMS)) {
|
|
throw new \common_exception_MissingParameter(self::REST_DELIVERY_SEARCH_PARAMS, $this->getRequestURI());
|
|
}
|
|
|
|
$where = json_decode(html_entity_decode($this->getRequestParameter(self::REST_DELIVERY_SEARCH_PARAMS)), true);
|
|
$propertyValues = $this->getRequestParameters();
|
|
unset($propertyValues[self::REST_DELIVERY_SEARCH_PARAMS]);
|
|
|
|
$deliveryModelClass = $this->getDeliveryRootClass();
|
|
$deliveries = $deliveryModelClass->searchInstances($where, ['like' => false, 'recursive' => true]);
|
|
|
|
$response = [];
|
|
|
|
/** @var \core_kernel_classes_Resource $delivery */
|
|
foreach ($deliveries as $key => $delivery) {
|
|
foreach ($propertyValues as $rdfKey => $rdfValue) {
|
|
$rdfKey = \tao_helpers_Uri::decode($rdfKey);
|
|
$property = $this->getProperty($rdfKey);
|
|
$delivery->editPropertyValues($property, $rdfValue);
|
|
}
|
|
$response[] = ['delivery' => $delivery->getUri()];
|
|
}
|
|
$this->returnSuccess($response);
|
|
} catch (\Exception $e) {
|
|
$this->returnFailure($e);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Update delivery by parameters
|
|
*/
|
|
public function updateDeferred()
|
|
{
|
|
try {
|
|
if ($this->getRequestMethod() !== \Request::HTTP_POST) {
|
|
throw new \common_exception_NotImplemented('Only post method is accepted to updating delivery');
|
|
}
|
|
if (! $this->hasRequestParameter(self::REST_DELIVERY_SEARCH_PARAMS)) {
|
|
throw new \common_exception_MissingParameter(self::REST_DELIVERY_SEARCH_PARAMS, $this->getRequestURI());
|
|
}
|
|
$where = json_decode(html_entity_decode($this->getRequestParameter(self::REST_DELIVERY_SEARCH_PARAMS)), true);
|
|
$propertyValues = $this->getRequestParameters();
|
|
unset($propertyValues[self::REST_DELIVERY_SEARCH_PARAMS]);
|
|
|
|
$task = UpdateDelivery::createTask($where, $propertyValues);
|
|
|
|
$result = [
|
|
'reference_id' => $task->getId()
|
|
];
|
|
|
|
/** @var TaskLogInterface $taskLog */
|
|
$taskLog = $this->getServiceManager()->get(TaskLogInterface::SERVICE_ID);
|
|
$report = $taskLog->getReport($task->getId());
|
|
if (!empty($report)) {
|
|
if ($report instanceof \common_report_Report) {
|
|
//serialize report to array
|
|
$report = json_decode($report);
|
|
}
|
|
$result['common_report_Report'] = $report;
|
|
}
|
|
return $this->returnSuccess($result);
|
|
} catch (\Exception $e) {
|
|
$this->returnFailure($e);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Delete delivery by URI
|
|
*/
|
|
public function deleteDeferred()
|
|
{
|
|
try {
|
|
if ($this->getRequestMethod() !== \Request::HTTP_DELETE) {
|
|
throw new \common_exception_NotImplemented('Only delete method is accepted to deleting delivery');
|
|
}
|
|
|
|
if (!$this->hasRequestParameter('uri')) {
|
|
throw new \common_exception_MissingParameter('uri', $this->getRequestURI());
|
|
}
|
|
|
|
$uri = $this->getRequestParameter('uri');
|
|
$delivery = $this->getResource($uri);
|
|
|
|
if (!$delivery->exists()) {
|
|
$this->returnFailure(new \common_exception_NotFound('Delivery has not been found'));
|
|
}
|
|
|
|
/** @var QueueDispatcher $queueDispatcher */
|
|
$queueDispatcher = $this->getServiceManager()->get(QueueDispatcher::SERVICE_ID);
|
|
|
|
$task = new DeliveryDeleteTask();
|
|
$task->setServiceLocator($this->getServiceLocator());
|
|
$taskParameters = ['deliveryId' => $uri];
|
|
|
|
$task = $queueDispatcher->createTask($task, $taskParameters, __('Deleting of "%s"', $delivery->getLabel()), null, true);
|
|
|
|
$data = $this->getTaskLogReturnData(
|
|
$task->getId(),
|
|
DeliveryDeleteTask::class
|
|
);
|
|
$this->returnSuccess($data);
|
|
} catch (\Exception $e) {
|
|
$this->returnFailure($e);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* List all deliveries or paginated range
|
|
*/
|
|
public function get()
|
|
{
|
|
try {
|
|
if ($this->getRequestMethod() !== \Request::HTTP_GET) {
|
|
throw new \common_exception_NotImplemented('Only get method is accepted to getting deliveries');
|
|
}
|
|
|
|
$limit = 0;
|
|
if ($this->hasRequestParameter('limit')) {
|
|
$limit = $this->getRequestParameter('limit');
|
|
if (!is_numeric($limit) || (int)$limit != $limit || $limit < 0) {
|
|
throw new \common_exception_ValidationFailed('limit', '\'Limit\' should be a positive integer');
|
|
}
|
|
}
|
|
|
|
$offset = 0;
|
|
if ($this->hasRequestParameter('offset')) {
|
|
$offset = $this->getRequestParameter('offset');
|
|
if (!is_numeric($offset) || (int)$offset != $offset || $offset < 0) {
|
|
throw new \common_exception_ValidationFailed('offset', '\'Offset\' should be a positive integer');
|
|
}
|
|
}
|
|
|
|
$service = DeliveryAssemblyService::singleton();
|
|
|
|
/** @var \core_kernel_classes_Resource[] $deliveries */
|
|
$deliveries = $service->getAllAssemblies();
|
|
$overallCount = count($deliveries);
|
|
if ($offset || $limit) {
|
|
if ($overallCount <= $offset) {
|
|
throw new \common_exception_ValidationFailed('offset', '\'Offset\' is too large');
|
|
}
|
|
$deliveries = array_slice($deliveries, $offset, $limit);
|
|
}
|
|
|
|
$mappedDeliveries = [];
|
|
foreach ($deliveries as $delivery) {
|
|
$mappedDeliveries[] = [
|
|
'uri' => $delivery->getUri(),
|
|
'label' => $delivery->getLabel(),
|
|
];
|
|
}
|
|
|
|
$response = [
|
|
'items' => $mappedDeliveries,
|
|
'overallCount' => $overallCount,
|
|
];
|
|
$this->returnSuccess($response);
|
|
} catch (\Exception $e) {
|
|
$this->returnFailure($e);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Action to retrieve test compilation task status from queue
|
|
*/
|
|
public function getStatus()
|
|
{
|
|
try {
|
|
if (!$this->hasRequestParameter(self::TASK_ID_PARAM)) {
|
|
throw new \common_exception_MissingParameter(self::TASK_ID_PARAM, $this->getRequestURI());
|
|
}
|
|
|
|
$data = $this->getTaskLogReturnData(
|
|
$this->getRequestParameter(self::TASK_ID_PARAM),
|
|
CompileDelivery::class
|
|
);
|
|
$children = $this->getStatusesForChildren($this->getRequestParameter(self::TASK_ID_PARAM));
|
|
$data['children'] = $children;
|
|
$this->returnSuccess($data);
|
|
} catch (\Exception $e) {
|
|
$this->returnFailure($e);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param $taskId
|
|
* @return array
|
|
*/
|
|
protected function getStatusesForChildren($taskId)
|
|
{
|
|
/** @var TaskLogInterface $taskLog */
|
|
$taskLog = $this->getServiceManager()->get(TaskLogInterface::SERVICE_ID);
|
|
$filter = (new TaskLogFilter())
|
|
->eq(TaskLogBrokerInterface::COLUMN_PARENT_ID, $taskId);
|
|
$collection = $taskLog->search($filter);
|
|
$response = [];
|
|
if ($collection->isEmpty()) {
|
|
return $response;
|
|
}
|
|
/** @var EntityInterface $item */
|
|
foreach ($collection as $item) {
|
|
$response[] = [
|
|
'id' => $this->getTaskId($item),
|
|
'label' => $item->getLabel(),
|
|
'status' => $this->getTaskStatus($item),
|
|
'report' => $item->getReport() ? $this->getTaskReport($item) : []
|
|
];
|
|
}
|
|
return $response;
|
|
}
|
|
|
|
/**
|
|
* Return 'Success' instead of 'Completed', required by the specified API.
|
|
*
|
|
* @param EntityInterface $taskLogEntity
|
|
* @return string
|
|
*/
|
|
protected function getTaskStatus(EntityInterface $taskLogEntity)
|
|
{
|
|
if ($taskLogEntity->getStatus()->isCreated()) {
|
|
return 'In Progress';
|
|
} elseif ($taskLogEntity->getStatus()->isCompleted()) {
|
|
return 'Success';
|
|
}
|
|
|
|
return $taskLogEntity->getStatus()->getLabel();
|
|
}
|
|
|
|
/**
|
|
* @param EntityInterface $taskLogEntity
|
|
* @return array
|
|
*/
|
|
protected function addExtraReturnData(EntityInterface $taskLogEntity)
|
|
{
|
|
$data = [];
|
|
|
|
if ($taskLogEntity->getReport()) {
|
|
$plainReport = $this->getPlainReport($taskLogEntity->getReport());
|
|
|
|
//the second report is the report of the compilation test
|
|
if (isset($plainReport[1]) && isset($plainReport[1]->getData()['uriResource'])) {
|
|
$data['delivery'] = $plainReport[1]->getData()['uriResource'];
|
|
}
|
|
}
|
|
|
|
return $data;
|
|
}
|
|
|
|
|
|
/**
|
|
* Create a Delivery Class
|
|
*
|
|
* Label parameter is mandatory
|
|
* If parent class parameter is an uri of valid delivery class, new class will be created under it
|
|
* If not parent class parameter is provided, class will be created under root class
|
|
* Comment parameter is not mandatory, used to describe new created class
|
|
*
|
|
* @return core_kernel_classes_Class
|
|
*/
|
|
public function createClass()
|
|
{
|
|
try {
|
|
$class = $this->createSubClass($this->getDeliveryRootClass());
|
|
|
|
$result = [
|
|
'message' => __('Class successfully created.'),
|
|
'delivery-uri' => $class->getUri(),
|
|
];
|
|
|
|
$this->returnSuccess($result);
|
|
} catch (\common_exception_ClassAlreadyExists $e) {
|
|
$result = [
|
|
'message' => $e->getMessage(),
|
|
'delivery-uri' => $e->getClass()->getUri(),
|
|
];
|
|
$this->returnSuccess($result);
|
|
} catch (\Exception $e) {
|
|
$this->returnFailure($e);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get a delivery class based on parameters
|
|
*
|
|
* If an uri parameter is provided, and it is a delivery class, this delivery class is returned
|
|
* If a label parameter is provided, and only one delivery class has this label, this delivery class is returned
|
|
*
|
|
* @return core_kernel_classes_Class
|
|
* @throws SearchGateWayExeption
|
|
* @throws common_exception_RestApi
|
|
*/
|
|
protected function getDeliveryClassByParameters()
|
|
{
|
|
$rootDeliveryClass = $this->getDeliveryRootClass();
|
|
|
|
// If an uri is provided, check if it's an existing delivery class
|
|
if ($this->hasRequestParameter(self::REST_DELIVERY_CLASS_URI)) {
|
|
$deliveryClass = $this->getClass($this->getRequestParameter(self::REST_DELIVERY_CLASS_URI));
|
|
if (
|
|
$deliveryClass == $rootDeliveryClass
|
|
|| ($deliveryClass->exists() && $deliveryClass->isSubClassOf($rootDeliveryClass))
|
|
) {
|
|
return $deliveryClass;
|
|
}
|
|
throw new common_exception_RestApi(__('Delivery class uri provided is not a valid delivery class.'));
|
|
}
|
|
|
|
if ($this->hasRequestParameter(self::REST_DELIVERY_CLASS_LABEL)) {
|
|
$label = $this->getRequestParameter(self::REST_DELIVERY_CLASS_LABEL);
|
|
|
|
$deliveryClasses = $rootDeliveryClass->getSubClasses(true);
|
|
$classes = [$rootDeliveryClass->getUri()];
|
|
foreach ($deliveryClasses as $class) {
|
|
$classes[] = $class->getUri();
|
|
}
|
|
|
|
/** @var ComplexSearchService $search */
|
|
$search = $this->getServiceManager()->get(ComplexSearchService::SERVICE_ID);
|
|
$queryBuilder = $search->query();
|
|
$criteria = $queryBuilder->newQuery()
|
|
->add(OntologyRdfs::RDFS_LABEL)->equals($label)
|
|
->add(OntologyRdfs::RDFS_SUBCLASSOF)->in($classes)
|
|
;
|
|
$queryBuilder->setCriteria($criteria);
|
|
$result = $search->getGateway()->search($queryBuilder);
|
|
|
|
switch ($result->count()) {
|
|
case 0:
|
|
throw new common_exception_RestApi(__('Delivery with label "%s" not found', $label));
|
|
case 1:
|
|
return $this->getClass($result->current()->getUri());
|
|
default:
|
|
$availableClasses = [];
|
|
foreach ($result as $raw) {
|
|
$availableClasses[] = $raw->getUri();
|
|
}
|
|
throw new common_exception_RestApi(__(
|
|
'Multiple delivery class found for label "%s": %s',
|
|
$label,
|
|
implode(',', $availableClasses)
|
|
));
|
|
}
|
|
}
|
|
|
|
return $rootDeliveryClass;
|
|
}
|
|
|
|
/**
|
|
* Get the delivery root class
|
|
*
|
|
* @return core_kernel_classes_Class
|
|
*/
|
|
protected function getDeliveryRootClass()
|
|
{
|
|
return $this->getClass(DeliveryAssemblyService::CLASS_URI);
|
|
}
|
|
}
|