tao-test/app/taoDelivery/model/execution/AbstractStateService.php

179 lines
5.8 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;
*
*/
namespace oat\taoDelivery\model\execution;
use common_exception_NotFound;
use oat\oatbox\event\Event;
use oat\oatbox\event\EventManager;
use oat\oatbox\log\LoggerAwareTrait;
use oat\oatbox\service\ConfigurableService;
use oat\oatbox\session\SessionService;
use oat\oatbox\user\User;
use oat\taoDelivery\models\classes\execution\event\DeliveryExecutionCreated;
use oat\taoDelivery\models\classes\execution\event\DeliveryExecutionReactivated;
use oat\taoDelivery\models\classes\execution\event\DeliveryExecutionState as DeliveryExecutionStateEvent;
/**
* Class AbstractStateService
* @package oat\taoDelivery
* @author Aleh Hutnikau, <hutnikau@1pt.com>
*/
abstract class AbstractStateService extends ConfigurableService implements StateServiceInterface
{
use LoggerAwareTrait;
public const OPTION_REACTIVABLE_STATES = 'reactivableStates';
private const DEFAULT_REACTIVABLE_STATES = [
DeliveryExecutionInterface::STATE_TERMINATED,
];
private const INTERACTIVE_STATES = [
DeliveryExecutionInterface::STATE_ACTIVE,
DeliveryExecutionInterface::STATE_PAUSED,
];
/**
* Legacy function to ensure all calls to setState use
* the correct transition instead
*
* @param DeliveryExecution $deliveryExecution
* @param string $state
*
* @return bool
*/
abstract public function legacyTransition(DeliveryExecution $deliveryExecution, $state);
/**
* Get the status new delivery executions should be started with
*
* @param string $deliveryId
* @param User $user
*
* @return string
*/
abstract public function getInitialStatus($deliveryId, User $user);
/**
* @inheritDoc
*/
public function createDeliveryExecution($deliveryId, User $user, $label)
{
$status = $this->getInitialStatus($deliveryId, $user);
$deliveryExecution = $this->getStorageEngine()->spawnDeliveryExecution($label, $deliveryId, $user->getIdentifier(), $status);
// trigger event
$event = new DeliveryExecutionCreated($deliveryExecution, $user);
$this->getEventManager()->trigger($event);
return $deliveryExecution;
}
/**
* @inheritDoc
*/
public function reactivateExecution(DeliveryExecution $deliveryExecution, $reason = null)
{
$executionState = $deliveryExecution->getState()->getUri();
$result = false;
if (in_array($executionState, $this->getReactivableStates(), true)) {
$this->setState($deliveryExecution, DeliveryExecution::STATE_PAUSED, $reason);
$result = true;
}
return $result;
}
/**
* @param DeliveryExecution $deliveryExecution
* @param string $state
* @param string|array|null $reason
*
* @return bool
*
* @throws common_exception_NotFound
*/
protected function setState(DeliveryExecution $deliveryExecution, string $state, $reason = null): bool
{
$previousState = $deliveryExecution->getState()->getUri();
if ($previousState === $state) {
$this->logWarning('Delivery execution ' . $deliveryExecution->getIdentifier() . ' already in state ' . $state);
return false;
}
$result = $deliveryExecution->getImplementation()->setState($state);
$this->emitEvent(new DeliveryExecutionStateEvent($deliveryExecution, $state, $previousState));
$this->logDebug(sprintf('DeliveryExecutionState from %s to %s triggered', $previousState, $state));
if (!$this->isStateInteractive($previousState) && $this->isStateInteractive($state)) {
$this->emitEvent(
new DeliveryExecutionReactivated(
$deliveryExecution,
$this->getSessionService()->getCurrentUser(),
$reason
)
);
}
return $result;
}
protected function getStorageEngine(): DeliveryExecutionService
{
/** @noinspection PhpIncompatibleReturnTypeInspection */
return $this->getServiceLocator()->get(DeliveryExecutionService::SERVICE_ID);
}
private function getSessionService(): SessionService
{
/** @noinspection PhpIncompatibleReturnTypeInspection */
return $this->getServiceLocator()->get(SessionService::SERVICE_ID);
}
private function getEventManager(): EventManager
{
/** @noinspection PhpIncompatibleReturnTypeInspection */
return $this->getServiceLocator()->get(EventManager::SERVICE_ID);
}
private function emitEvent(Event $event): void
{
$this->getEventManager()->trigger($event);
}
private function getReactivableStates(): array
{
if (!$this->hasOption(self::OPTION_REACTIVABLE_STATES)) {
return self::DEFAULT_REACTIVABLE_STATES;
}
return $this->getOption(self::OPTION_REACTIVABLE_STATES);
}
private function isStateInteractive(string $state): bool
{
return in_array($state, self::INTERACTIVE_STATES, true);
}
}