<?php
namespace App\Controller\Scheduler;
use App\Service\SycoreService;
use Psr\Log\LoggerInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
class SchedulerController extends AbstractController
{
public function __construct(SycoreService $sycoreService) {
$this->sycoreService = $sycoreService;
}
// ------------------------------------------------------------------------
//
// ------------------------------------------------------------------------
private function getWorkflowParameters(int $workflowId): array {
$em = $this->getDoctrine()->getManager();
$sql = <<<SQL
SELECT param_name, param_value, param_type, flag_file
FROM sybot.chklst_template_parameters
WHERE chklst_id = :workflowId
SQL;
$query = $em->getConnection()->executeQuery($sql, ['workflowId' => $workflowId]);
$result = $query->fetchAllAssociative();
// Attenzione: valuelist ABUSA del campo "param_value" per contenere
// la lista delle opzioni. Per aggirare questo gravissimo errore
// logico (la lista delle opzioni è il DOMINIO, non il valore!)
// dobbiamo creare un nuovo campo "param_options" e spostare lì
// il contenuto di "param_value". Il campo "param_value" va azzerato.
foreach ($result as &$p) {
if ($p['param_type'] === 'valuelist') {
$p['param_options'] = $p['param_value'];
$p['param_value'] = null;
}
}
return $result;
}
// ------------------------------------------------------------------------
// QUERY
// ------------------------------------------------------------------------
public function queryAction(Request $request, LoggerInterface $logger, ParameterBagInterface $params) {
$em = $this->getDoctrine()->getManager();
try
{
$workflowId = $request->query->get("workflowId");
$sql = <<<SQL
SELECT *
FROM sybot.wfl_schedule
WHERE workflow_id = :workflowId
ORDER BY created ASC
SQL;
$query = $em->getConnection()->executeQuery($sql, ['workflowId' => $workflowId]);
$result = $query->fetchAllAssociative();
// Attenzione! la lista dei parametri del workflow potrebbe essere
// stato modificata dopo la creazione della schedulazione, quindi
// la lista dei parametri salvati (nella schedulazione) potrebbe
// essere disallineata!
// I parametri che *devono* esserci sono quelli attuali del workflow,
// inizializzati con i valori salvati nella schedulazione (se presenti)
// (tutti gli altri vanno eliminati)
$parameters = $this->getWorkflowParameters($workflowId);
foreach ($result as $index => $row) {
// Lista dei parametri correntemente associati alla schedulazione
$savedParametersList = json_decode($row['parameters'], true);
$savedParametersMap = [];
foreach ($savedParametersList as $p) {
$savedParametersMap[$p['param_name']] = $p;
}
// Attraversiamo la lista completa dei parametri del workflow
// recuperata prima e costruiamo una nuova lista di parametri
// per la schedulazione corrente, sovrascrivendo i valori con
// quelli salvati (se presenti)
$parametersOfSchedule = [];
foreach ($parameters as &$p) {
$paramName = $p['param_name'];
if (array_key_exists($paramName, $savedParametersMap)) {
$p['param_value'] = $savedParametersMap[$paramName]['param_value'];
$p['param_options'] = $savedParametersMap[$paramName]['param_options'] ?? null;
}
$parametersOfSchedule[] = $p;
}
$result[$index]['parameters'] = $parametersOfSchedule;
}
return new JsonResponse($result);
} catch (\Exception $e) {
$logger->error("Errore durante il recupero delle schedulazioni: " . $e->getMessage());
return new JsonResponse(['error' => 'Impossibile recuperare le schedulazioni'], 500);
}
}
// ------------------------------------------------------------------------
// POST
// ------------------------------------------------------------------------
public function postAction(int $workflowId, Request $request, LoggerInterface $logger) {
$em = $this->getDoctrine()->getManager();
$payload = json_decode($request->getContent(),true);
$csrftoken=$payload['csrftoken'];
if (!$this->isCsrfTokenValid('scheduler_route', $csrftoken)) {
throw new \Exception('Csrf token not valid');
}
$parameters = $this->getWorkflowParameters($workflowId);
$sql = <<<SQL
SELECT * FROM sybot.chklst_template_parameters WHERE workflow_id = :workflowId
SQL;
$user = $this->getUser();
$userId = $user->getID();
$now = new \DateTime();
$nowString = $now->format('Y-m-d H:i:s');
$sycore_info = $this->sycoreService->getSycoreInfo();
$sycore_instance_uuid = $sycore_info ? $sycore_info->instance_uuid : null;
$defaults = [
'workflow_id' => $workflowId,
'from_date' => $nowString,
'to_date' => null,
'enabled' => 'false',
'parameters' => json_encode($parameters),
'label' => "Nuova schedulazione",
'cron' => '* * * * *',
'created' => $nowString,
'created_by' => $userId,
'modified' => $nowString,
'modified_by' => $userId,
'sycore_instance_uuid' => $sycore_instance_uuid
];
$sql = <<<SQL
INSERT INTO sybot.wfl_schedule (
workflow_id, from_date, to_date, enabled, parameters, label, cron, created, created_by, modified, modified_by, sycore_instance_uuid
) VALUES (
:workflow_id, :from_date, :to_date, :enabled, :parameters, :label, :cron, :created, :created_by, :modified, :modified_by, :sycore_instance_uuid
)
SQL;
try {
$em->getConnection()->executeQuery($sql, $defaults);
$newId = $em->getConnection()->lastInsertId();
$logger->info("Creato nuovo schedule con ID: $newId");
return new JsonResponse([
'status' => 'success',
'id' => $newId
], Response::HTTP_CREATED);
} catch (\Exception $e) {
$logger->error("Error: " . $e->getMessage());
return new JsonResponse(['error' => 'Impossibile creare una nuova schedulazione'], 500);
}
}
// ------------------------------------------------------------------------
// PUT
// ------------------------------------------------------------------------
public function putAction(int $scheduleId, Request $request, LoggerInterface $logger) {
$em = $this->getDoctrine()->getManager();
$payload = json_decode($request->getContent(),true);
$schedule=$payload['schedule'];
$csrftoken=$payload['csrftoken'];
if (!$this->isCsrfTokenValid('scheduler_route', $csrftoken)) {
throw new \Exception('Csrf token not valid');
}
if (!$schedule) {
return new JsonResponse(['error' => 'JSON malformato'], Response::HTTP_BAD_REQUEST);
}
$sql = <<<SQL
UPDATE sybot.wfl_schedule
SET from_date = :from_date,
to_date = :to_date,
enabled = :enabled,
parameters = :parameters,
label = :label,
cron = :cron,
modified = :modified,
modified_by = :modified_by
WHERE schedule_id = :schedule_id
SQL;
$user = $this->getUser();
$userId = $user->getID();
$modifiedAt = (new \DateTime())->format('Y-m-d H:i:s');
try {
$em->getConnection()->executeQuery($sql, [
'schedule_id' => $scheduleId,
'from_date' => $schedule['from_date'],
'to_date' => $schedule['to_date'],
'enabled' => $schedule['enabled'] ? 'true' : 'false',
'parameters' => json_encode($schedule['parameters']),
'label' => $schedule['label'],
'cron' => $schedule['cron'],
'modified' => $modifiedAt,
'modified_by' => $userId
]);
return new JsonResponse([
'status' => 'success',
'modified' => $modifiedAt
], Response::HTTP_OK);
} catch (\Exception $e) {
$logger->error("Errore " . $e->getMessage());
return new JsonResponse(['error' => $e->getMessage()], 500);
}
}
// ------------------------------------------------------------------------
// DELETE
// ------------------------------------------------------------------------
public function deleteAction(int $scheduleId, Request $request, LoggerInterface $logger) {
$em = $this->getDoctrine()->getManager();
$payload = json_decode($request->getContent(),true);
$csrftoken=$payload['csrftoken'];
if (!$this->isCsrfTokenValid('scheduler_route', $csrftoken)) {
throw new \Exception('Csrf token not valid');
}
try {
$sql = <<< SQL
DELETE FROM sybot.wfl_schedule WHERE schedule_id = :scheduleId
SQL;
$query = $em->getConnection()->executeQuery($sql, ['scheduleId' => $scheduleId]);
return new JsonResponse([
"status" => "success"
], Response::HTTP_OK);
} catch (\Exception $e) {
$logger->error("Errore" . $e->getMessage());
return new JsonResponse(['error' => $e->getMessage()], 500);
}
}
// ------------------------------------------------------------------------
// runAction
// ------------------------------------------------------------------------
public function runAction(int $scheduleId, Request $request, LoggerInterface $logger, ParameterBagInterface $params)
{
$em = $this->getDoctrine()->getManager();
$logger->debug("Chiamata runAction per schedulazione ID: $scheduleId");
try {
$sql = <<<SQL
SELECT * FROM sybot.wfl_schedule WHERE schedule_id = :scheduleId
SQL;
$query = $em->getConnection()->executeQuery($sql, ['scheduleId' => $scheduleId]);
$queryResult = $query->fetchAssociative();
$workflowId = $queryResult['workflow_id'];
$request->request->set('template_id', $workflowId );
$request->request->set('remote_api', 'SCHEDULER' );
$request->request->set('params', $queryResult['parameters'] );
$logger->debug("Invoco ChecklistController:runChecklistAction...");
$logger->debug("Request");
$logger->debug(print_r($request->request->all(), true));
$response = $this->forward('App\Controller\ChecklistController:runChecklistAction',
array(
"request" => $request,
"logger" => $logger,
"params" => $params,
"method" => "internal" // <-- ??????
)
);
$logger->debug("ChecklistController:runChecklistAction eseguito con risposta: " . $response->getContent());
// $res = json_decode($response->getContent(), true);
} catch (\Exception $e) {
$logger->error("Errore durante l'esecuzione della schedulazione ID: $scheduleId - " . $e->getMessage());
return new JsonResponse(['error' => 'Impossibile eseguire la schedulazione'], 500);
}
return new JsonResponse(['status' => 'success'], Response::HTTP_OK);
}
}
?>