tao-test/app/taoDelivery/model/execution/implementation/KeyValueService.php

321 lines
12 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) 2016 (original work) Open Assessment Technologies SA (under the project TAO-PRODUCT);
*
*/
namespace oat\taoDelivery\model\execution\implementation;
use common_Logger;
use common_persistence_KeyValuePersistence;
use core_kernel_classes_Resource;
use oat\generis\model\OntologyRdfs;
use oat\oatbox\service\ConfigurableService;
use oat\taoDelivery\model\execution\KVDeliveryExecution;
use oat\taoDelivery\model\execution\OntologyDeliveryExecution;
use oat\taoDelivery\model\execution\DeliveryExecution as DeliveryExecutionWrapper;
use oat\taoDelivery\model\execution\Delete\DeliveryExecutionDeleteRequest;
use oat\taoDelivery\model\execution\DeliveryExecutionService;
/**
* Service to manage the execution of deliveries
*
* @access public
* @package taoDelivery
*/
class KeyValueService extends ConfigurableService implements DeliveryExecutionService
{
const OPTION_PERSISTENCE = 'persistence';
const DELIVERY_EXECUTION_PREFIX = 'kve_de_';
const USER_EXECUTIONS_PREFIX = 'kve_ue_';
const USER_DELIVERY_PREFIX = 'kve_ud_';
/**
* @var common_persistence_KeyValuePersistence
*/
private $persistence;
/**
* @return common_persistence_KeyValuePersistence
*/
protected function getPersistence()
{
if (is_null($this->persistence)) {
$persistenceOption = $this->getOption(self::OPTION_PERSISTENCE);
$this->persistence = (is_object($persistenceOption))
? $persistenceOption
: $this->getServiceLocator()->get(\common_persistence_Manager::SERVICE_ID)->getPersistenceById($persistenceOption);
}
return $this->persistence;
}
/**
* @param core_kernel_classes_Resource $compiled
* @param string $userUri
* @return array
*/
public function getUserExecutions(core_kernel_classes_Resource $compiled, $userUri)
{
$returnValue = [];
$data = $this->getPersistence()->get(self::USER_DELIVERY_PREFIX . $userUri . $compiled->getUri());
$keys = $data !== false ? json_decode($data, true) : [];
if (is_array($keys)) {
foreach ($keys as $key) {
$returnValue[$key] = $this->getDeliveryExecution($key);
}
} else {
common_Logger::w('Non array "' . gettype($keys) . '" received as active Execution Keys for user ' . $userUri . ' with delivery' . $compiled->getUri());
}
return $returnValue;
}
/**
* Spawn a new Delivery Execution
*
* @param string $label
* @param string $deliveryId
* @param string $userId
* @param string $status
* @return \oat\taoDelivery\model\execution\DeliveryExecution
*/
public function spawnDeliveryExecution($label, $deliveryId, $userId, $status)
{
$identifier = self::DELIVERY_EXECUTION_PREFIX . \common_Utils::getNewUri();
$data = [
OntologyRdfs::RDFS_LABEL => $label,
OntologyDeliveryExecution::PROPERTY_DELIVERY => $deliveryId,
OntologyDeliveryExecution::PROPERTY_SUBJECT => $userId,
OntologyDeliveryExecution::PROPERTY_TIME_START => microtime(),
OntologyDeliveryExecution::PROPERTY_STATUS => $status
];
$kvDe = new KVDeliveryExecution($this, $identifier, $data);
$this->updateDeliveryExecutionStatus($kvDe, null, $status);
$this->addDeliveryToUserExecutionList($userId, $deliveryId, $kvDe->getIdentifier());
return $this->propagate(new DeliveryExecutionWrapper($kvDe));
}
/**
* Generate a new delivery execution
* @deprecated
* @param core_kernel_classes_Resource $assembly
* @param string $userId
* @return core_kernel_classes_Resource the delivery execution
*/
public function initDeliveryExecution(core_kernel_classes_Resource $assembly, $userId)
{
common_Logger::w('Call to deprecated function ' . __FUNCTION__);
return $this->spawnDeliveryExecution($assembly->getLabel(), $assembly->getUri(), $userId, KvDeliveryExecution::STATE_ACTIVE);
}
/**
* @param $userId
* @param $assemblyId
* @param $executionId
*/
private function addDeliveryToUserExecutionList($userId, $assemblyId, $executionId)
{
$uid = self::USER_DELIVERY_PREFIX . $userId . $assemblyId;
$data = json_decode($this->getPersistence()->get($uid), true);
if (!$data) {
$data = [];
}
$data [] = $executionId;
$this->getPersistence()->set($uid, json_encode($data));
}
/**
* @param string $userUri
* @param string $status
* @return array
*/
public function getDeliveryExecutionsByStatus($userUri, $status)
{
$returnValue = [];
$data = $this->getPersistence()->get(self::USER_EXECUTIONS_PREFIX . $userUri . $status);
$keys = $data !== false ? json_decode($data, true) : [];
if (is_array($keys)) {
foreach ($keys as $key) {
$de = $this->getDeliveryExecution($key);
if ($de->getState()->getUri() !== $status) {
$this->fixStatus($de->getImplementation(), $status, $de->getState()->getUri());
} else {
$returnValue[$key] = $de;
}
}
} else {
common_Logger::w('Non array "' . gettype($keys) . '" received as active Delivery Keys for user ' . $userUri);
}
return $returnValue;
}
/**
* @param string $identifier
* @return DeliveryExecutionWrapper
*/
public function getDeliveryExecution($identifier)
{
$identifier = ($identifier instanceof core_kernel_classes_Resource) ? $identifier->getUri() : (string) $identifier;
$deImplementation = new KVDeliveryExecution($this, $identifier);
return $this->propagate(new DeliveryExecutionWrapper($deImplementation));
}
/**
* Update the collection of deliveries
*
* @param KVDeliveryExecution $deliveryExecution
* @param string $old
* @param string $new
* @return mixed
*/
public function updateDeliveryExecutionStatus(KVDeliveryExecution $deliveryExecution, $old, $new)
{
$this->update($deliveryExecution);
$userId = $deliveryExecution->getUserIdentifier();
if ($old != null) {
$oldReferences = $this->getDeliveryExecutionsByStatus($userId, $old);
foreach (array_keys($oldReferences) as $key) {
if ($oldReferences[$key]->getIdentifier() == $deliveryExecution->getIdentifier()) {
unset($oldReferences[$key]);
}
}
$this->setDeliveryExecutions($userId, $old, $oldReferences);
}
$newReferences = $this->getDeliveryExecutionsByStatus($userId, $new);
$newReferences[$deliveryExecution->getIdentifier()] = $deliveryExecution;
return $this->setDeliveryExecutions($userId, $new, $newReferences);
}
public function update(KVDeliveryExecution $de)
{
$this->getPersistence()->set($de->getIdentifier(), json_encode($de));
}
/**
* @param $deliveryExecutionId
* @return mixed
*/
public function getData($deliveryExecutionId)
{
$dataString = $this->getPersistence()->get($deliveryExecutionId);
$data = json_decode($dataString, true);
return $data;
}
/**
* @inheritdoc
*/
public function deleteDeliveryExecutionData(DeliveryExecutionDeleteRequest $request)
{
$deUri = $request->getDeliveryExecution()->getIdentifier();
$deliveryUri = $request->getDeliveryResource()->getUri();
$userUri = $request->getDeliveryExecution()->getUserIdentifier();
/** @var \common_ext_ExtensionsManager $extManager */
$extManager = $this->getServiceLocator()->get(\common_ext_ExtensionsManager::SERVICE_ID);
if ($extManager->isInstalled('taoProctoring')) {
$reflect = new \ReflectionClass(\oat\taoProctoring\model\execution\DeliveryExecution::class);
} else {
$reflect = new \ReflectionClass(\oat\taoDelivery\model\execution\DeliveryExecutionInterface::class);
}
$constants = $reflect->getConstants();
$statuses = [];
foreach ($constants as $constantName => $constantValue) {
if (strpos($constantName, 'STATE_') !== false) {
$statuses[] = $constantValue;
}
}
foreach ($statuses as $status) {
$this->getPersistence()->del(self::USER_EXECUTIONS_PREFIX . $userUri . $status);
}
$deletedDe = $this->getPersistence()->del($deUri);
$deletedUE = $this->getPersistence()->del(self::USER_DELIVERY_PREFIX . $userUri . $deliveryUri);
return $deletedDe && $deletedUE;
}
/**
* @param $userUri
* @param $status
* @param $executions
* @return mixed
*/
private function setDeliveryExecutions($userUri, $status, $executions)
{
$keys = [];
foreach ($executions as $execution) {
$keys[] = $execution->getIdentifier();
}
return $this->getPersistence()->set(self::USER_EXECUTIONS_PREFIX . $userUri . $status, json_encode($keys));
}
/**
* @param KVDeliveryExecution $deliveryExecution
* @param $old
* @param $new
*/
private function fixStatus(KVDeliveryExecution $deliveryExecution, $old, $new)
{
$userId = $deliveryExecution->getUserIdentifier();
$oldData = $this->getPersistence()->get(self::USER_EXECUTIONS_PREFIX . $userId . $old);
$oldStateKeys = $oldData !== false ? json_decode($oldData, true) : [];
$oldStateExecutions = [];
if (is_array($oldStateKeys)) {
foreach ($oldStateKeys as $key) {
$de = $this->getDeliveryExecution($key);
if ($de->getIdentifier() !== $deliveryExecution->getIdentifier()) {
$oldStateExecutions[$de->getIdentifier()] = $de;
}
}
$this->setDeliveryExecutions($userId, $old, $oldStateExecutions);
}
$newData = $this->getPersistence()->get(self::USER_EXECUTIONS_PREFIX . $userId . $new);
$newStateKeys = $newData !== false ? json_decode($newData, true) : [];
$newStateExecutions = [];
if (is_array($newStateKeys) && !isset($newStateKeys[$deliveryExecution->getIdentifier()])) {
foreach ($newStateKeys as $key) {
$de = $this->getDeliveryExecution($key);
$newStateExecutions[$de->getIdentifier()] = $de;
}
$newStateExecutions[$deliveryExecution->getIdentifier()] = $deliveryExecution;
}
$this->setDeliveryExecutions($userId, $new, $newStateExecutions);
}
/**
* @param $deliveryExecutionId
* @return bool
*/
public function exists($deliveryExecutionId)
{
return $this->getPersistence()->exists($deliveryExecutionId);
}
}