From 08e06fb260209ea76fba72407c65fdf7c208b4d4 Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sat, 6 May 2023 11:42:06 +0000 Subject: [PATCH] make id public, organigram impl. media password/encryption, settings bug fix, Money->FloatInt change, ... --- Admin/Install/db.json | 6 ++ Admin/Installer.php | 18 ++++ Controller/ApiController.php | 88 ++++---------------- Controller/BackendController.php | 6 +- Controller/CliController.php | 54 +++++++----- Models/WorkflowInstanceAbstract.php | 12 ++- Models/WorkflowTemplate.php | 2 +- Theme/Backend/Lang/en.lang.php | 4 + Theme/Backend/workflow-dashboard.tpl.php | 2 +- Theme/Backend/workflow-instance-list.tpl.php | 2 +- Theme/Backend/workflow-template-list.tpl.php | 10 +-- Theme/Backend/workflow-template.tpl.php | 76 ++++++++++------- 12 files changed, 143 insertions(+), 137 deletions(-) diff --git a/Admin/Install/db.json b/Admin/Install/db.json index 71fe9ef..c80f2c1 100755 --- a/Admin/Install/db.json +++ b/Admin/Install/db.json @@ -98,6 +98,12 @@ "type": "DATETIME", "null": false }, + "workflow_instance_end": { + "name": "workflow_instance_end", + "type": "DATETIME", + "null": true, + "default": null + }, "workflow_instance_created_by": { "name": "workflow_instance_created_by", "type": "INT", diff --git a/Admin/Installer.php b/Admin/Installer.php index 7ffd00a..10ebfee 100755 --- a/Admin/Installer.php +++ b/Admin/Installer.php @@ -90,10 +90,28 @@ final class Installer extends InstallerAbstract self::createTriggers($apiApp, $workflowData['triggers'] ?? []); self::createActions($apiApp, $workflowData['actions'] ?? []); + self::createWorkflows($apiApp, $workflowData['workflows'] ?? []); return []; } + private static function createWorkflows(ApplicationAbstract $app, array $data) : void + { + /** @var \Modules\Workflow\Controller\ApiController $module */ + $module = $app->moduleManager->get('Workflow'); + + foreach ($data as $name => $workflow) { + $response = new HttpResponse(); + $request = new HttpRequest(new HttpUri('')); + + $request->header->account = 1; + $request->setData('name', $name); + $request->setData('schema', \json_encode($workflow)); + + $module->apiWorkflowTemplateCreate($request, $response); + } + } + /** * Install trigger. * diff --git a/Controller/ApiController.php b/Controller/ApiController.php index 9d65f52..92c8c17 100755 --- a/Controller/ApiController.php +++ b/Controller/ApiController.php @@ -17,7 +17,6 @@ namespace Modules\Workflow\Controller; use Modules\Admin\Models\NullAccount; use Modules\Media\Models\CollectionMapper; use Modules\Media\Models\NullCollection; -use Modules\Media\Models\NullMedia; use Modules\Media\Models\PathSettings; use Modules\Workflow\Models\PermissionCategory; use Modules\Workflow\Models\WorkflowInstanceAbstract; @@ -39,6 +38,7 @@ use phpOMS\System\File\FileUtils; use phpOMS\System\MimeType; use phpOMS\Utils\Parser\Markdown\Markdown; use phpOMS\Utils\StringUtils; +use phpOMS\Utils\TaskSchedule\SchedulerAbstract; use phpOMS\Utils\TaskSchedule\SchedulerFactory; use phpOMS\Utils\TaskSchedule\TaskFactory; use phpOMS\Views\View; @@ -53,65 +53,6 @@ use phpOMS\Views\View; */ final class ApiController extends Controller { - /** - * Api method to make a call to the cli app - * - * @param mixed ...$data Generic data - * - * @return void - * - * @api - * - * @since 1.0.0 - */ - public function runWorkflowFromHook(mixed ...$data) : void - { - /** @var WorkflowTemplate[] $workflows */ - $workflows = WorkflowTemplateMapper::getAll() - ->with('source') - ->with('source/sources') - ->where('status', WorkflowStatus::ACTIVE) - ->execute(); - - foreach ($workflows as $workflow) { - $hooksFile = $workflow->source->findFile('Hooks.php'); - if ($hooksFile instanceof NullMedia) { - continue; - } - - $hooksContent = \file_get_contents($hooksFile->getAbsolutePath()); - if ($hooksContent === false) { - continue; - } - - $hooks = \json_decode($hooksContent, true); - if ($hooks === false || $hooks === null) { - continue; - } - - /** @var array $hooks */ - foreach ($hooks as $hook) { - /** @var array{'@triggerGroup'?:string} $data */ - $triggerIsRegex = \stripos($data['@triggerGroup'], '/') === 0; - $matched = false; - - if ($triggerIsRegex) { - $matched = \preg_match($data['@triggerGroup'], $hook) === 1; - } else { - $matched = $data['@triggerGroup'] === $hook; - } - - if (!$matched && \stripos($hook, '/') === 0) { - $matched = \preg_match($hook, $data['@triggerGroup']) === 1; - } - - if ($matched) { - $this->runWorkflow($workflow, $hook, $data); - } - } - } - } - /** * Api method to make a call to the cli app * @@ -166,7 +107,7 @@ final class ApiController extends Controller // is allowed to read if (!$this->app->accountManager->get($accountId)->hasPermission( - PermissionType::READ, $this->app->unitId, null, self::NAME, PermissionCategory::INSTANCE, $instance->getId() + PermissionType::READ, $this->app->unitId, null, self::NAME, PermissionCategory::INSTANCE, $instance->id ) || ($isExport && !$this->app->accountManager->get($accountId)->hasPermission( PermissionType::READ, $this->app->unitId, $this->app->appId, self::NAME, PermissionCategory::EXPORT @@ -444,7 +385,7 @@ final class ApiController extends Controller ); foreach ($uploaded as $upload) { - if ($upload instanceof NullMedia) { + if ($upload->id === 0) { continue; } @@ -459,7 +400,7 @@ final class ApiController extends Controller $request->header->account ); - if ($collection instanceof NullCollection) { + if ($collection->id === 0) { $response->header->status = RequestStatusCode::R_403; $this->fillJsonResponse($request, $response, NotificationLevel::ERROR, 'Template', 'Couldn\'t create collection for template', null); @@ -471,17 +412,16 @@ final class ApiController extends Controller $this->createModel($request->header->account, $collection, CollectionMapper::class, 'collection', $request->getOrigin()); - $collectionId = $collection->getId(); + $collectionId = $collection->id; } $template = $this->createTemplateFromRequest($request, $collectionId); - $this->createModel($request->header->account, $template, WorkflowTemplateMapper::class, 'workflow_template', $request->getOrigin()); // replace placeholders if ($collectionId > 0) { foreach ($uploaded as $upload) { - if ($upload instanceof NullMedia) { + if ($upload->id === 0) { continue; } @@ -529,7 +469,7 @@ final class ApiController extends Controller continue; } - $this->app->moduleManager->get($actions[$id]['function_install']['module'])->{$actions[$id]['function_install']['function_install_function']}($template); + $this->app->moduleManager->get($actions[$id]['function_install']['module'])->{$actions[$id]['function_install']['function']}($template, $primary); } } @@ -542,9 +482,11 @@ final class ApiController extends Controller * * @since 1.0.0 */ - public function installTimedTrigger(WorkflowTemplate $template) : void + public function installTimedTrigger(WorkflowTemplate $template, array $settings) : void { - $id = 'Workflow-' . $template->getId(); + SchedulerAbstract::guessBin(); + + $id = 'Workflow-' . $template->id; $scheduler = SchedulerFactory::create(); if (!empty($scheduler->getAllByName($id))) { @@ -553,11 +495,11 @@ final class ApiController extends Controller $job = TaskFactory::create($id); - $job->interval = $template->schema['settings']['interval'] ?? ''; + $job->interval = $settings['settings']['interval'] ?? ''; $job->command = 'php ' . FileUtils::absolute(__DIR__ . '/../../../Cli/cli.php') . ' /workflow/instance -id ' - . $template->getId() + . $template->id . ' -trigger 1005500005'; $scheduler->create($job); @@ -580,7 +522,7 @@ final class ApiController extends Controller return ''; } - $content = \str_replace('{workflow_id}', (string) $template->getId(), $content); + $content = \str_replace('{workflow_id}', (string) $template->id, $content); return $content; } @@ -644,7 +586,7 @@ final class ApiController extends Controller /** @var \Modules\Media\Models\Collection $collection */ $collection = CollectionMapper::get() ->with('sources') - ->where('id', $template->source->getId()) + ->where('id', $template->source->id) ->execute(); $files = $collection->getSources(); diff --git a/Controller/BackendController.php b/Controller/BackendController.php index ec9872e..0a49125 100755 --- a/Controller/BackendController.php +++ b/Controller/BackendController.php @@ -100,7 +100,7 @@ final class BackendController extends Controller $view->setData('template', $template); - if (!(($template->source->findFile('template-profile.tpl.php')) instanceof NullMedia)) { + if ($template->source->findFile('template-profile.tpl.php')->id > 0) { require_once $template->source->findFile('WorkflowController.php')->getPath(); /** @var WorkflowControllerInterface $controller */ @@ -217,13 +217,13 @@ final class BackendController extends Controller $template = WorkflowTemplateMapper::get() ->with('source') ->with('source/sources') - ->where('id', $instance->template->getId()) + ->where('id', $instance->template->id) ->limit() ->execute(); $view->addData('template', $template); - if (!(($template->source->findFile('instance-profile.tpl.php')) instanceof NullMedia)) { + if ($template->source->findFile('instance-profile.tpl.php')->id > 0) { require_once $template->source->findFile('WorkflowController.php')->getPath(); /** @var WorkflowControllerInterface $controller */ diff --git a/Controller/CliController.php b/Controller/CliController.php index 69a63a5..7a0240d 100755 --- a/Controller/CliController.php +++ b/Controller/CliController.php @@ -16,7 +16,7 @@ namespace Modules\Workflow\Controller; use Modules\Workflow\Models\WorkflowInstance; use Modules\Workflow\Models\WorkflowInstanceAbstract; -use Modules\Workflow\Models\WorkflowInstanceAbstractMapper; +use Modules\Workflow\Models\WorkflowInstanceMapper; use Modules\Workflow\Models\WorkflowStatus; use Modules\Workflow\Models\WorkflowTemplate; use Modules\Workflow\Models\WorkflowTemplateMapper; @@ -25,7 +25,6 @@ use phpOMS\Message\Http\RequestStatusCode; use phpOMS\Message\RequestAbstract; use phpOMS\Message\ResponseAbstract; use phpOMS\Model\Message\FormValidation; -use phpOMS\Utils\StringUtils; use phpOMS\Views\View; /** @@ -117,28 +116,19 @@ final class CliController extends Controller $response->header->status = RequestStatusCode::R_400; } - $instance = $this->createInstanceFromRequest($request); + $instance = $this->createInstanceFromRequest($request, $response); + $this->createModel($request->header->account, $instance, WorkflowInstanceMapper::class, 'instance', $request->getOrigin()); + $this->startInstance($request, $response, $instance); + + $new = clone $instance; + $new->end = new \DateTime('now'); + $this->updateModel($request->header->account, $instance, $new, WorkflowInstanceMapper::class, 'instance', $request->getOrigin()); $view->setTemplate('/Modules/Workflow/Theme/Cli/empty-command'); return $view; } - public function runWorkflowElement(array $actions, WorkflowTemplate $template, WorkflowInstanceAbstract $instance, array $element) : void - { - if (isset($actions[$element['id']])) { - $result = $this->app->moduleManager - ->get($actions[$element['id']]['modules'], $actions[$element['id']]['function_type']) - ->{$actions[$element['id']]['function']}($template); - } - - // @todo: currently all children are executed one after another, maybe consider parallel execution - foreach ($element['children'] as $child) { - // @todo: pass previous results (probably needs a populator for input variables based on previous output variables) - $this->runWorkflowElement($actions, $template, $instance, $child); - } - } - /** * Validate template create request * @@ -177,7 +167,13 @@ final class CliController extends Controller ->execute(); $instance = new WorkflowInstance(); + $instance->template = $template; + return $instance; + } + + private function startInstance(RequestAbstract $request, ResponseAbstract $response, WorkflowInstanceAbstract $instance) + { $actionString = \file_get_contents(__DIR__ . '/../Definitions/actions.json'); if ($actionString === false) { return $instance; @@ -188,14 +184,30 @@ final class CliController extends Controller return $instance; } - foreach ($template->schema as $e) { + foreach ($instance->template->schema as $e) { if ($e['id'] === $request->getDataString('trigger')) { - $this->runWorkflowElement($actions, $template, $instance, $e); + $this->runWorkflowElement($request, $response, $actions, $instance, $e); break; } } + } - return $instance; + public function runWorkflowElement( + RequestAbstract $request, ResponseAbstract $response, + array $actions, WorkflowInstanceAbstract $instance, array $element + ) : void + { + if (isset($actions[$element['id']])) { + $this->app->moduleManager + ->get($actions[$element['id']]['modules'], $actions[$element['id']]['function_type']) + ->{$actions[$element['id']]['function']}($request, $response, [$element]); + } + + // @todo: currently all children are executed one after another, maybe consider parallel execution + foreach ($element['children'] as $child) { + // @todo: pass previous results (probably needs a populator for input variables based on previous output variables) + $this->runWorkflowElement($request, $response, $actions, $instance, $child); + } } } diff --git a/Models/WorkflowInstanceAbstract.php b/Models/WorkflowInstanceAbstract.php index 67022c4..7c93bd7 100755 --- a/Models/WorkflowInstanceAbstract.php +++ b/Models/WorkflowInstanceAbstract.php @@ -33,7 +33,7 @@ class WorkflowInstanceAbstract * @var int * @since 1.0.0 */ - protected int $id = 0; + public int $id = 0; /** * Title. @@ -49,7 +49,7 @@ class WorkflowInstanceAbstract * @var int * @since 1.0.0 */ - private int $status = WorkflowInstanceStatus::WORKING; + public int $status = WorkflowInstanceStatus::WORKING; /** * Template. @@ -75,6 +75,14 @@ class WorkflowInstanceAbstract */ public \DateTimeImmutable $createdAt; + /** + * End. + * + * @var null|\DateTimeImmutable + * @since 1.0.0 + */ + public ?\DateTimeImmutable $end = null; + /** * Constructor. * diff --git a/Models/WorkflowTemplate.php b/Models/WorkflowTemplate.php index 81c8aa2..16fc749 100755 --- a/Models/WorkflowTemplate.php +++ b/Models/WorkflowTemplate.php @@ -35,7 +35,7 @@ class WorkflowTemplate * @var int * @since 1.0.0 */ - protected int $id = 0; + public int $id = 0; /** * Name. diff --git a/Theme/Backend/Lang/en.lang.php b/Theme/Backend/Lang/en.lang.php index d3035f0..8defacd 100755 --- a/Theme/Backend/Lang/en.lang.php +++ b/Theme/Backend/Lang/en.lang.php @@ -13,8 +13,11 @@ declare(strict_types=1); return ['Workflow' => [ + 'Available' => 'Available', + 'Active' => 'Active', 'CC' => 'CC', 'Created' => 'Created', + 'Name' => 'Name', 'Creator' => 'Creator', 'Due' => 'Due', 'Media' => 'Media', @@ -28,4 +31,5 @@ return ['Workflow' => [ 'Upload' => 'Upload', 'Workflow' => 'Workflow', 'Workflows' => 'Workflows', + 'Instances' => 'Instances', ]]; diff --git a/Theme/Backend/workflow-dashboard.tpl.php b/Theme/Backend/workflow-dashboard.tpl.php index c6cdb6c..a5b67b8 100755 --- a/Theme/Backend/workflow-dashboard.tpl.php +++ b/Theme/Backend/workflow-dashboard.tpl.php @@ -31,7 +31,7 @@ echo $this->getData('nav')->render(); ?> $instance) : ++$c; - $url = \phpOMS\Uri\UriFactory::build('{/base}/admin/instance/single?{?}&id=' . $instance->getId()); + $url = \phpOMS\Uri\UriFactory::build('{/base}/admin/instance/single?{?}&id=' . $instance->id); ?> printHtml((string) $instance->getStatus()); ?> diff --git a/Theme/Backend/workflow-instance-list.tpl.php b/Theme/Backend/workflow-instance-list.tpl.php index e4b1aac..426bce6 100755 --- a/Theme/Backend/workflow-instance-list.tpl.php +++ b/Theme/Backend/workflow-instance-list.tpl.php @@ -31,7 +31,7 @@ echo $this->getData('nav')->render(); ?> $instance) : ++$c; - $url = \phpOMS\Uri\UriFactory::build('workflow/instance/profile?{?}&id=' . $instance->getId()); + $url = \phpOMS\Uri\UriFactory::build('workflow/instance/profile?{?}&id=' . $instance->id); ?> printHtml((string) $instance->getStatus()); ?> diff --git a/Theme/Backend/workflow-template-list.tpl.php b/Theme/Backend/workflow-template-list.tpl.php index bf8de5c..6f7d608 100755 --- a/Theme/Backend/workflow-template-list.tpl.php +++ b/Theme/Backend/workflow-template-list.tpl.php @@ -23,14 +23,14 @@ $templates = $this->getData('reports'); /** @var \Modules\Admin\Models\Account $account */ $account = $this->getData('account'); -$accountDir = $account->getId() . ' ' . $account->login; +$accountDir = $account->id . ' ' . $account->login; /** @var \Modules\Media\Models\Collection[] */ $collections = $this->getData('collections'); $mediaPath = \urldecode($this->getData('path') ?? '/'); -$previous = empty($templates) ? 'workflow/template/list' : '{/base}/workflow/template/list?{?}&id=' . \reset($templates)->getId() . '&ptype=p'; -$next = empty($templates) ? 'workflow/template/list' : '{/base}/workflow/template/list?{?}&id=' . \end($templates)->getId() . '&ptype=n'; +$previous = empty($templates) ? 'workflow/template/list' : '{/base}/workflow/template/list?{?}&id=' . \reset($templates)->id . '&ptype=p'; +$next = empty($templates) ? 'workflow/template/list' : '{/base}/workflow/template/list?{?}&id=' . \end($templates)->id . '&ptype=n'; echo $this->getData('nav')->render(); ?>
@@ -94,7 +94,7 @@ echo $this->getData('nav')->render(); ?> $template) : ++$count; - $url = UriFactory::build('{/base}/workflow/template/profile?{?}&id=' . $template->getId()); ?> + $url = UriFactory::build('{/base}/workflow/template/profile?{?}&id=' . $template->id); ?> printHtml($template->name); ?> - printHtml($this->renderUserName('%3$s %2$s %1$s', [$template->createdBy->name1, $template->createdBy->name2, $template->createdBy->name3, $template->createdBy->login ?? ''])); ?> + printHtml($this->renderUserName('%3$s %2$s %1$s', [$template->createdBy->name1, $template->createdBy->name2, $template->createdBy->name3, $template->createdBy->login ?? ''])); ?> printHtml($template->createdAt->format('Y-m-d')); ?> diff --git a/Theme/Backend/workflow-template.tpl.php b/Theme/Backend/workflow-template.tpl.php index 7db12d4..662ae77 100755 --- a/Theme/Backend/workflow-template.tpl.php +++ b/Theme/Backend/workflow-template.tpl.php @@ -23,26 +23,49 @@ $template = $this->getData('template'); $actions = \json_decode(\file_get_contents(__DIR__ . '/../../Definitions/actions.json'), true); -function renderLeaf(array $leaf, string $parent = null) +function renderWorkflow(array $leaf, array $actions) { - $boxes = [ - 'first' => ['((', '))'], - 'standard' => ['[', ']'], - 'if' => ['{', '}'] - ]; + foreach ($leaf as $e) { + echo << + +
{$actions[(int) $e['id']]['name']}
+
+
+ + +
- foreach ($leaf as $key => $e) { - $type = $e['id'] === '1005500001' - ? 'if' - : 'standard'; +
+ + +
- if ($parent !== null) { - echo ' ' . $parent . '-->' . $parent . ':' . $key . ':' . $e['id'] . $boxes[$type][0] . $e['id'] . $boxes[$type][1] . ";\n"; - } else { - echo ' ' . $key . ':' . $e['id'] . $boxes['first'][0] . $e['id'] . $boxes['first'][1] . ";\n"; +
+ + +
+ NEWDOC; + + foreach ($actions[(int) $e['id']]['settings'] ?? [] as $key => $setting) { + echo '
' + , '' + , '' + , '
'; } - renderLeaf($e['children'], ($parent === null ? '' : $parent . ':') . $key . ':' . $e['id']); + echo '
' + , '' + , '' + , '
'; + + if (!empty($e['children'])) { + echo '
    '; + renderWorkflow($e['children'], $actions); + echo '
'; + } + + echo ''; } } @@ -53,7 +76,7 @@ function renderElements(array $leaf, array $actions) echo << -
{$name}
+
{$name}
NEWDOC; @@ -69,29 +92,22 @@ if (!empty($template->schema)) : $level = $template->schema; ?>
-
+
getHtml('Workflow'); ?>
-
- graph TD; - -
+
    + +
-
getHtml('Active'); ?>
-
- - -
- -
-
-
getHtml('Available'); ?>
+
getHtml('Available'); ?>