make id public, organigram impl. media password/encryption, settings bug fix, Money->FloatInt change, ...

This commit is contained in:
Dennis Eichhorn 2023-05-06 11:42:06 +00:00
parent 5c4b7d05db
commit 08e06fb260
12 changed files with 143 additions and 137 deletions

View File

@ -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",

View File

@ -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.
*

View File

@ -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();

View File

@ -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 */

View File

@ -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);
}
}
}

View File

@ -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.
*

View File

@ -35,7 +35,7 @@ class WorkflowTemplate
* @var int
* @since 1.0.0
*/
protected int $id = 0;
public int $id = 0;
/**
* Name.

View File

@ -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',
]];

View File

@ -31,7 +31,7 @@ echo $this->getData('nav')->render(); ?>
<?php
$c = 0;
foreach ($instances as $key => $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);
?>
<tr data-href="<?= $url; ?>">
<td><a href="<?= $url; ?>"><?= $this->printHtml((string) $instance->getStatus()); ?></a>

View File

@ -31,7 +31,7 @@ echo $this->getData('nav')->render(); ?>
<?php
$c = 0;
foreach ($instances as $key => $instance) : ++$c;
$url = \phpOMS\Uri\UriFactory::build('workflow/instance/profile?{?}&id=' . $instance->getId());
$url = \phpOMS\Uri\UriFactory::build('workflow/instance/profile?{?}&id=' . $instance->id);
?>
<tr data-href="<?= $url; ?>">
<td><a href="<?= $url; ?>"><?= $this->printHtml((string) $instance->getStatus()); ?></a>

View File

@ -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(); ?>
<div class="row">
@ -94,7 +94,7 @@ echo $this->getData('nav')->render(); ?>
<td>
<?php endif; ?>
<?php $count = 0; foreach ($templates as $key => $template) : ++$count;
$url = UriFactory::build('{/base}/workflow/template/profile?{?}&id=' . $template->getId()); ?>
$url = UriFactory::build('{/base}/workflow/template/profile?{?}&id=' . $template->id); ?>
<tr tabindex="0" data-href="<?= $url; ?>">
<td><label class="checkbox" for="workflowTemplateList-<?= $key; ?>">
<input type="checkbox" id="workflowTemplateList-<?= $key; ?>" name="templateselect">
@ -102,7 +102,7 @@ echo $this->getData('nav')->render(); ?>
</label>
<td>
<td data-label="<?= $this->getHtml('Name'); ?>"><a href="<?= $url; ?>"><?= $this->printHtml($template->name); ?></a>
<td data-label="<?= $this->getHtml('Creator'); ?>"><a class="content" href="<?= UriFactory::build('{/base}/profile/single?{?}&for=' . $template->createdBy->getId()); ?>"><?= $this->printHtml($this->renderUserName('%3$s %2$s %1$s', [$template->createdBy->name1, $template->createdBy->name2, $template->createdBy->name3, $template->createdBy->login ?? ''])); ?></a>
<td data-label="<?= $this->getHtml('Creator'); ?>"><a class="content" href="<?= UriFactory::build('{/base}/profile/single?{?}&for=' . $template->createdBy->id); ?>"><?= $this->printHtml($this->renderUserName('%3$s %2$s %1$s', [$template->createdBy->name1, $template->createdBy->name2, $template->createdBy->name3, $template->createdBy->login ?? ''])); ?></a>
<td data-label="<?= $this->getHtml('Updated'); ?>"><a href="<?= $url; ?>"><?= $this->printHtml($template->createdAt->format('Y-m-d')); ?></a>
<?php endforeach; ?>
<?php if ($count === 0) : ?>

View File

@ -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 <<<NEWDOC
<li>
<span>
<div class="portlet-head">{$actions[(int) $e['id']]['name']}</div>
<div class="portlet-body">
<div class="form-group">
<label for="iId">Module</label>
<input type="text" value="{$actions[(int) $e['id']]['module']}" disabled>
</div>
foreach ($leaf as $key => $e) {
$type = $e['id'] === '1005500001'
? 'if'
: 'standard';
<div class="form-group">
<label for="iId">Type</label>
<input type="text" value="{$actions[(int) $e['id']]['function_type']}" disabled>
</div>
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";
<div class="form-group">
<label for="iId">Internal Function</label>
<input type="text" value="{$actions[(int) $e['id']]['function']}" disabled>
</div>
NEWDOC;
foreach ($actions[(int) $e['id']]['settings'] ?? [] as $key => $setting) {
echo '<div class="form-group">'
, '<label for="iId">' , $setting['title']['en'] , '</label>'
, '<input name="' , $key , '" type="text" value="' , ($e['settings'][$key] ?? '') , '">'
, '</div>';
}
renderLeaf($e['children'], ($parent === null ? '' : $parent . ':') . $key . ':' . $e['id']);
echo '</div><div class="portlet-foot">'
, '<input name="save" type="Submit" value="Save">'
, '<input name="delete" class="cancel" type="Submit" value="Delete">'
, '</div></span>';
if (!empty($e['children'])) {
echo '<ul>';
renderWorkflow($e['children'], $actions);
echo '</ul>';
}
echo '</li>';
}
}
@ -53,7 +76,7 @@ function renderElements(array $leaf, array $actions)
echo <<<NEWDOC
<section class="portlet">
<div class="portlet-body">{$name}</div>
<div class="portlet-head">{$name}</div>
<div class="portlet-body"></div>
</section>
NEWDOC;
@ -69,29 +92,22 @@ if (!empty($template->schema)) :
$level = $template->schema;
?>
<div class="row">
<div class="col-md-6 col-xs-12">
<div class="col-md-9 col-xs-12">
<section class="portlet sticky">
<div class="portlet-head"><?= $this->getHtml('Workflow'); ?></div>
<div class="portlet-body">
<div class="mermaid">
graph TD;
<?php renderLeaf($level, null); ?>
</div>
<ul class="tree center">
<?php
renderWorkflow($level, $actions);
?>
</ul>
</div>
</section>
</div>
<div class="col-md-3 col-xs-12">
<section class="portlet">
<div class="portlet-head"><?= $this->getHtml('Active'); ?></div>
</section>
<?php renderElements($level, $actions); ?>
</div>
<div class="col-md-3 col-xs-12">
<section class="portlet">
<div class="portlet-head"><?= $this->getHtml('Available'); ?></div>
<div class="portlet-body"><?= $this->getHtml('Available'); ?></div>
</section>
<?php foreach ($actions as $action) : ?>