mirror of
https://github.com/Karaka-Management/oms-Workflow.git
synced 2026-01-10 14:28:40 +00:00
crash backup
This commit is contained in:
parent
0fe6db40b6
commit
6ee722b038
|
|
@ -1,18 +1,18 @@
|
|||
{
|
||||
"triggers": [
|
||||
"PRE:Module:Workflow:workflow_template-create",
|
||||
"POST:Module:Workflow:workflow_template-create",
|
||||
"PRE:Module:Workflow:workflow_template-update",
|
||||
"POST:Module:Workflow:workflow_template-update",
|
||||
"PRE:Module:Workflow:workflow_template-delete",
|
||||
"POST:Module:Workflow:workflow_template-delete",
|
||||
"PRE:Workflow:workflow_template-create",
|
||||
"POST:Workflow:workflow_template-create",
|
||||
"PRE:Workflow:workflow_template-update",
|
||||
"POST:Workflow:workflow_template-update",
|
||||
"PRE:Workflow:workflow_template-delete",
|
||||
"POST:Workflow:workflow_template-delete",
|
||||
|
||||
"PRE:Module:Workflow:workflow_instance-create",
|
||||
"POST:Module:Workflow:workflow_instance-create",
|
||||
"PRE:Module:Workflow:workflow_instance-update",
|
||||
"POST:Module:Workflow:workflow_instance-update",
|
||||
"PRE:Module:Workflow:workflow_instance-delete",
|
||||
"POST:Module:Workflow:workflow_instance-delete"
|
||||
"PRE:Workflow:workflow_instance-create",
|
||||
"POST:Workflow:workflow_instance-create",
|
||||
"PRE:Workflow:workflow_instance-update",
|
||||
"POST:Workflow:workflow_instance-update",
|
||||
"PRE:Workflow:workflow_instance-delete",
|
||||
"POST:Workflow:workflow_instance-delete"
|
||||
],
|
||||
"actions": {
|
||||
"1005500001": {
|
||||
|
|
@ -270,9 +270,9 @@
|
|||
"default": null,
|
||||
"pattern": null,
|
||||
"examples": [
|
||||
"PRE:Module:Billing:bill-create",
|
||||
"PRE:Module:Billing:bill-update.*",
|
||||
"PRE:Module:Billing:bill-update-{$id}"
|
||||
"PRE:Billing:bill-create",
|
||||
"PRE:Billing:bill-update.*",
|
||||
"PRE:Billing:bill-update-{$id}"
|
||||
],
|
||||
"required": true,
|
||||
"title": {
|
||||
|
|
|
|||
|
|
@ -15,6 +15,11 @@
|
|||
"default": null,
|
||||
"null": true
|
||||
},
|
||||
"workflow_template_type": {
|
||||
"name": "workflow_template_type",
|
||||
"type": "INT",
|
||||
"null": false
|
||||
},
|
||||
"workflow_template_status": {
|
||||
"name": "workflow_template_status",
|
||||
"type": "INT",
|
||||
|
|
@ -38,6 +43,14 @@
|
|||
"default": null,
|
||||
"null": true
|
||||
},
|
||||
"workflow_template_module": {
|
||||
"name": "workflow_template_module",
|
||||
"type": "VARCHAR(190)",
|
||||
"null": true,
|
||||
"default": null,
|
||||
"foreignTable": "module",
|
||||
"foreignKey": "module_id"
|
||||
},
|
||||
"workflow_template_media": {
|
||||
"name": "workflow_template_media",
|
||||
"type": "INT",
|
||||
|
|
@ -73,8 +86,7 @@
|
|||
"workflow_instance_title": {
|
||||
"name": "workflow_instance_title",
|
||||
"type": "VARCHAR(255)",
|
||||
"default": null,
|
||||
"null": true
|
||||
"null": false
|
||||
},
|
||||
"workflow_instance_status": {
|
||||
"name": "workflow_instance_status",
|
||||
|
|
@ -86,6 +98,16 @@
|
|||
"type": "TEXT",
|
||||
"null": false
|
||||
},
|
||||
"workflow_instance_int": {
|
||||
"name": "workflow_instance_int",
|
||||
"type": "INT",
|
||||
"null": false
|
||||
},
|
||||
"workflow_instance_ref": {
|
||||
"name": "workflow_instance_ref",
|
||||
"type": "INT",
|
||||
"null": false
|
||||
},
|
||||
"workflow_instance_template": {
|
||||
"name": "workflow_instance_template",
|
||||
"type": "INT",
|
||||
|
|
@ -112,5 +134,64 @@
|
|||
"foreignKey": "account_id"
|
||||
}
|
||||
}
|
||||
},
|
||||
"workflow_step": {
|
||||
"name": "workflow_step",
|
||||
"fields": {
|
||||
"workflow_step_id": {
|
||||
"name": "workflow_step_id",
|
||||
"type": "INT",
|
||||
"null": false,
|
||||
"primary": true,
|
||||
"autoincrement": true
|
||||
},
|
||||
"workflow_step_order": {
|
||||
"name": "workflow_step_order",
|
||||
"type": "INT",
|
||||
"null": false
|
||||
},
|
||||
"workflow_step_status": {
|
||||
"name": "workflow_step_status",
|
||||
"type": "INT",
|
||||
"null": false
|
||||
},
|
||||
"workflow_step_comment": {
|
||||
"name": "workflow_step_comment",
|
||||
"type": "TEXT",
|
||||
"null": false
|
||||
},
|
||||
"workflow_step_data": {
|
||||
"name": "workflow_step_data",
|
||||
"type": "TEXT",
|
||||
"null": false
|
||||
},
|
||||
"workflow_step_instance": {
|
||||
"name": "workflow_step_instance",
|
||||
"type": "INT",
|
||||
"null": false,
|
||||
"foreignTable": "workflow_instance",
|
||||
"foreignKey": "workflow_instance_id"
|
||||
},
|
||||
"workflow_step_media": {
|
||||
"name": "workflow_step_media",
|
||||
"type": "INT",
|
||||
"null": true,
|
||||
"default": null,
|
||||
"foreignTable": "media",
|
||||
"foreignKey": "media_id"
|
||||
},
|
||||
"workflow_step_created_at": {
|
||||
"name": "workflow_step_created_at",
|
||||
"type": "DATETIME",
|
||||
"null": false
|
||||
},
|
||||
"workflow_step_created_by": {
|
||||
"name": "workflow_step_created_by",
|
||||
"type": "INT",
|
||||
"null": false,
|
||||
"foreignTable": "account",
|
||||
"foreignKey": "account_id"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -104,39 +104,16 @@ final class Installer extends InstallerAbstract
|
|||
|
||||
self::createTriggers($apiApp, $workflowData['triggers'] ?? []);
|
||||
self::createActions($apiApp, $workflowData['actions'] ?? []);
|
||||
self::createWorkflows($apiApp, $workflowData['workflows'] ?? []);
|
||||
|
||||
// Workflows possible to also define in the ui
|
||||
self::installWorkflow($apiApp, $workflowData['workflows'] ?? []);
|
||||
|
||||
// Workflows only programmable
|
||||
self::installWorkflow($apiApp, $workflowData['templates'] ?? []);
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a workflow template
|
||||
*
|
||||
* @param ApplicationAbstract $app Application
|
||||
* @param array $data Workflow schemas
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
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();
|
||||
|
||||
$request->header->account = 1;
|
||||
$request->setData('name', $name);
|
||||
$request->setData('schema', \json_encode($workflow));
|
||||
|
||||
$module->apiWorkflowTemplateCreate($request, $response);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Install trigger.
|
||||
*
|
||||
|
|
@ -216,12 +193,23 @@ final class Installer extends InstallerAbstract
|
|||
/** @var \Modules\Workflow\Controller\ApiController $module */
|
||||
$module = $app->moduleManager->get('Workflow');
|
||||
|
||||
foreach ($data as $template) {
|
||||
foreach ($data as $id => $template) {
|
||||
$response = new HttpResponse();
|
||||
$request = new HttpRequest();
|
||||
|
||||
$request->header->account = 1;
|
||||
$request->setData('name', $template['name']);
|
||||
if (($temlate['name'] ?? null) !== null) {
|
||||
$request->setData('name', $template['name']);
|
||||
} else {
|
||||
$request->setData('name', $id);
|
||||
$request->setData('schema', \json_encode($template));
|
||||
}
|
||||
|
||||
if (($template['path'] ?? null) == null) {
|
||||
$module->apiWorkflowTemplateCreate($request, $response);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
$tempPath = __DIR__ . '/../../../temp/';
|
||||
|
||||
|
|
|
|||
|
|
@ -16,7 +16,42 @@ omsApp.Modules.Workflow = class {
|
|||
|
||||
bind (id)
|
||||
{
|
||||
mermaid.initialize({ startOnLoad: true });
|
||||
const mermaidElements = document.querySelectorAll('.mermaid');
|
||||
if (mermaidElements.length === 0) return; // Exit if no .mermaid elements are found
|
||||
|
||||
mermaidElements.forEach((mermaidElement) => {
|
||||
const observer = new MutationObserver((mutationsList, observer) => {
|
||||
if (mermaidElement.offsetParent !== null) {
|
||||
initializeMermaid();
|
||||
observer.disconnect();
|
||||
}
|
||||
});
|
||||
|
||||
observer.observe(mermaidElement, {
|
||||
attributes: true,
|
||||
attributeFilter: ['style', 'class'],
|
||||
});
|
||||
});
|
||||
|
||||
function initializeMermaid() {
|
||||
if (typeof mermaid !== 'undefined') {
|
||||
mermaid.run({
|
||||
querySelector: '.mermaid',
|
||||
postRenderCallback: (id) => {
|
||||
const svgs = d3.selectAll('.mermaid svg');
|
||||
svgs.each(function () {
|
||||
const svg = d3.select(this);
|
||||
svg.html('<g>' + svg.html() + '</g>');
|
||||
const inner = svg.select('g');
|
||||
const zoom = d3.zoom().on('zoom', function (event) {
|
||||
inner.attr('transform', event.transform);
|
||||
});
|
||||
svg.call(zoom);
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
bindElement (chart)
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ use Modules\Workflow\Models\WorkflowInstanceAbstract;
|
|||
use Modules\Workflow\Models\WorkflowInstanceAbstractMapper;
|
||||
use Modules\Workflow\Models\WorkflowTemplate;
|
||||
use Modules\Workflow\Models\WorkflowTemplateMapper;
|
||||
use Modules\Workflow\Models\WorkflowTemplateStatus;
|
||||
use phpOMS\Account\PermissionType;
|
||||
use phpOMS\Autoloader;
|
||||
use phpOMS\DataStorage\Database\Schema\Builder as SchemaBuilder;
|
||||
|
|
@ -98,7 +99,7 @@ final class ApiController extends Controller
|
|||
->with('template/source')
|
||||
->with('template/source/sources')
|
||||
->with('createdBy')
|
||||
->where('id', (int) $request->getData('id'))
|
||||
->where('id', $request->getDataInt('id') ?? 0)
|
||||
->execute();
|
||||
|
||||
$accountId = $request->header->account;
|
||||
|
|
@ -165,7 +166,7 @@ final class ApiController extends Controller
|
|||
private function setWorkflowResponseHeader(View $view, string $name, RequestAbstract $request, ResponseAbstract $response) : void
|
||||
{
|
||||
/** @var array{lang?:\Modules\Media\Models\Media, cfg?:\Modules\Media\Models\Media, excel?:\Modules\Media\Models\Media, word?:\Modules\Media\Models\Media, powerpoint?:\Modules\Media\Models\Media, pdf?:\Modules\Media\Models\Media, csv?:\Modules\Media\Models\Media, json?:\Modules\Media\Models\Media, template?:\Modules\Media\Models\Media, css?:array<string, \Modules\Media\Models\Media>, js?:array<string, \Modules\Media\Models\Media>, db?:array<string, \Modules\Media\Models\Media>, other?:array<string, \Modules\Media\Models\Media>} $tcoll */
|
||||
$tcoll = $view->getData('tcoll') ?? [];
|
||||
$tcoll = $view->data['tcoll'] ?? [];
|
||||
|
||||
switch ($request->getData('type')) {
|
||||
case 'pdf':
|
||||
|
|
@ -669,7 +670,7 @@ final class ApiController extends Controller
|
|||
$template = WorkflowTemplateMapper::get()
|
||||
->with('source')
|
||||
->with('source/sources')
|
||||
->where('id', (int) $request->getData('template'))
|
||||
->where('id', $request->getDataInt('template'))
|
||||
->execute();
|
||||
|
||||
$instance = $this->createInstanceFromRequest($request, $template);
|
||||
|
|
@ -739,4 +740,143 @@ final class ApiController extends Controller
|
|||
public function apiWorkflowImport(HttpRequest $request, HttpResponse $response, mixed $data = null) : void
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Api method to handle the bill workflow
|
||||
*
|
||||
* @param int $account Account who created the model
|
||||
* @param mixed $old Old value
|
||||
* @param mixed $new New value (unused, should be null)
|
||||
* @param int $type Module model type
|
||||
* @param string $trigger What triggered this log?
|
||||
* @param string $module Module name
|
||||
* @param string $ref Reference to other model
|
||||
* @param string $content Message
|
||||
* @param string $ip Ip
|
||||
*
|
||||
* @return mixed
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function hookWorkflowChangeState(
|
||||
int $account,
|
||||
mixed $old,
|
||||
mixed $new,
|
||||
?int $type = null,
|
||||
string $trigger = '',
|
||||
?string $module = null,
|
||||
?string $ref = null,
|
||||
?string $content = null,
|
||||
?string $ip = null
|
||||
) : mixed
|
||||
{
|
||||
$template = WorkflowTemplateMapper::get()
|
||||
->with('source')
|
||||
->with('source/sources')
|
||||
->where('module', $module)
|
||||
->where('type', $type ?? 0)
|
||||
->executeGet();
|
||||
|
||||
if ($template->id === 0) {
|
||||
$template = WorkflowTemplateMapper::get()
|
||||
->with('source')
|
||||
->with('source/sources')
|
||||
->where('module', $module)
|
||||
->executeGet();
|
||||
}
|
||||
|
||||
if ($template->id === 0 || $template->status != WorkflowTemplateStatus::ACTIVE) {
|
||||
return null;
|
||||
}
|
||||
|
||||
require_once $template->source->findFile('WorkflowController.php')->getPath();
|
||||
|
||||
/** @var WorkflowControllerInterface $controller */
|
||||
$controller = new \Modules\Workflow\Controller\WorkflowController($this->app, $template);
|
||||
return $controller->hookChangeState(
|
||||
$template,
|
||||
$account,
|
||||
$old,
|
||||
$new,
|
||||
$type,
|
||||
$trigger,
|
||||
$module,
|
||||
$ref,
|
||||
$content,
|
||||
$ip
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Api method to handle the bill workflow
|
||||
*
|
||||
* @param int $account Account who created the model
|
||||
* @param mixed $old Old value
|
||||
* @param mixed $new New value (unused, should be null)
|
||||
* @param int $type Module model type
|
||||
* @param string $trigger What triggered this log?
|
||||
* @param string $module Module name
|
||||
* @param string $ref Reference to other model
|
||||
* @param string $content Message
|
||||
* @param string $ip Ip
|
||||
*
|
||||
* @return mixed
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function apiWorkflowHandleState(
|
||||
int $account,
|
||||
mixed $old,
|
||||
mixed $new,
|
||||
?int $type = null,
|
||||
string $trigger = '',
|
||||
?string $module = null,
|
||||
?string $ref = null,
|
||||
?string $content = null,
|
||||
?string $ip = null
|
||||
) : mixed
|
||||
{
|
||||
$template = WorkflowTemplateMapper::get()
|
||||
->with('source')
|
||||
->with('source/sources')
|
||||
->where('module', $module)
|
||||
->where('type', $type ?? 0)
|
||||
->executeGet();
|
||||
|
||||
if ($template->id === 0) {
|
||||
$template = WorkflowTemplateMapper::get()
|
||||
->with('source')
|
||||
->with('source/sources')
|
||||
->where('module', $module)
|
||||
->executeGet();
|
||||
}
|
||||
|
||||
if ($template->id === 0 || $template->status != WorkflowTemplateStatus::ACTIVE) {
|
||||
return null;
|
||||
}
|
||||
|
||||
require_once $template->source->findFile('WorkflowController.php')->getPath();
|
||||
|
||||
$response = new HttpResponse();
|
||||
$request = new HttpRequest();
|
||||
$request->header->account = $account;
|
||||
|
||||
/** @var WorkflowControllerInterface $controller */
|
||||
$controller = new \Modules\Workflow\Controller\WorkflowController($this->app, $template);
|
||||
return $controller->apiHandleState(
|
||||
$request,
|
||||
$response,
|
||||
[
|
||||
'template' => $template,
|
||||
'old' => $old,
|
||||
'new' => $new,
|
||||
'type' => $type,
|
||||
'trigger' => $trigger,
|
||||
'module' => $module,
|
||||
'ref' => $ref,
|
||||
'content' => $content,
|
||||
'ip' => $ip
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -103,6 +103,7 @@ final class BackendController extends Controller
|
|||
$head = $response->data['Content']->head;
|
||||
$nonce = $this->app->appSettings->getOption('script-nonce');
|
||||
|
||||
$head->addAsset(AssetType::JSLATE, 'Resources/d3/d3.min.js?v=' . $this->app->version, ['nonce' => $nonce]);
|
||||
$head->addAsset(AssetType::JSLATE, 'Resources/mermaid/mermaid.min.js?v=' . $this->app->version, ['nonce' => $nonce]);
|
||||
$head->addAsset(AssetType::JSLATE, 'Modules/Workflow/Controller.js?v=' . self::VERSION, ['nonce' => $nonce, 'type' => 'module']);
|
||||
|
||||
|
|
@ -114,7 +115,7 @@ final class BackendController extends Controller
|
|||
->with('source')
|
||||
->with('source/sources')
|
||||
->with('createdBy')
|
||||
->where('id', (int) $request->getData('id'))
|
||||
->where('id', $request->getDataInt('id') ?? 0)
|
||||
->execute();
|
||||
|
||||
$view->data['template'] = $template;
|
||||
|
|
@ -217,7 +218,7 @@ final class BackendController extends Controller
|
|||
$view = new View($this->app->l11nManager, $request, $response);
|
||||
|
||||
$view->data['instance'] = WorkflowInstanceAbstractMapper::get()
|
||||
->where('id', (int) $request->getData('id'))
|
||||
->where('id', $request->getDataInt('id') ?? 0)
|
||||
->execute();
|
||||
|
||||
if ($view->data['instance']->id === 0) {
|
||||
|
|
|
|||
|
|
@ -49,9 +49,15 @@ final class CliController extends Controller
|
|||
*/
|
||||
public function runWorkflowFromHook(mixed ...$data) : void
|
||||
{
|
||||
// @performance This seems incredibly bad.
|
||||
// We are loading always ALL workflows to find the correct one
|
||||
/** @var \Modules\Workflow\Models\WorkflowTemplate[] $workflows */
|
||||
$workflows = WorkflowTemplateMapper::getAll()->where('status', WorkflowStatus::ACTIVE)->executeGetArray();
|
||||
$workflows = WorkflowTemplateMapper::getAll()
|
||||
->where('status', WorkflowStatus::ACTIVE)
|
||||
->executeGetArray();
|
||||
|
||||
foreach ($workflows as $workflow) {
|
||||
// @todo This isn't even implemented (see getHooks function, which is empty)
|
||||
$hooks = $workflow->getHooks();
|
||||
|
||||
foreach ($hooks as $hook) {
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -1 +1 @@
|
|||
["PRE:Module:Workflow:workflow_template-create","POST:Module:Workflow:workflow_template-create","PRE:Module:Workflow:workflow_template-update","POST:Module:Workflow:workflow_template-update","PRE:Module:Workflow:workflow_template-delete","POST:Module:Workflow:workflow_template-delete","PRE:Module:Workflow:workflow_instance-create","POST:Module:Workflow:workflow_instance-create","PRE:Module:Workflow:workflow_instance-update","POST:Module:Workflow:workflow_instance-update","PRE:Module:Workflow:workflow_instance-delete","POST:Module:Workflow:workflow_instance-delete","PRE:Module:Billing:bill_media-create","POST:Module:Billing:bill_media-create","PRE:Module:Billing:bill_media-update","POST:Module:Billing:bill_media-update","PRE:Module:Billing:bill_media-delete","POST:Module:Billing:bill_media-delete","PRE:Module:Billing:bill_note-create","POST:Module:Billing:bill_note-create","PRE:Module:Billing:bill_note-update","POST:Module:Billing:bill_note-update","PRE:Module:Billing:bill_note-delete","POST:Module:Billing:bill_note-delete"]
|
||||
["PRE:Workflow:workflow_template-create","POST:Workflow:workflow_template-create","PRE:Workflow:workflow_template-update","POST:Workflow:workflow_template-update","PRE:Workflow:workflow_template-delete","POST:Workflow:workflow_template-delete","PRE:Workflow:workflow_instance-create","POST:Workflow:workflow_instance-create","PRE:Workflow:workflow_instance-update","POST:Workflow:workflow_instance-update","PRE:Workflow:workflow_instance-delete","POST:Workflow:workflow_instance-delete","PRE:Billing:bill_media-create","POST:Billing:bill_media-create","PRE:Billing:bill_media-update","POST:Billing:bill_media-update","PRE:Billing:bill_media-delete","POST:Billing:bill_media-delete","PRE:Billing:bill_note-create","POST:Billing:bill_note-create","PRE:Billing:bill_note-update","POST:Billing:bill_note-update","PRE:Billing:bill_note-delete","POST:Billing:bill_note-delete"]
|
||||
|
|
@ -14,9 +14,6 @@ A `States.php` file contains all workflow states. This is especially important i
|
|||
|
||||
The `Workflow.php` file is the heart of every workflow. This file is responsible for executing state driven actions and it can also be seen as the API for a workflow. All workflow related actions will be forwarded to this file and can be handled inside including database queries.
|
||||
|
||||
##
|
||||
|
||||
|
||||
1. Workflow gets installed with a trigger (either hook or cron job)
|
||||
2. Trigger is fired
|
||||
3. Hook loads CliApplication::installWorkflowTemplate with template ID, action ID and Hook
|
||||
|
|
@ -24,3 +21,22 @@ The `Workflow.php` file is the heart of every workflow. This file is responsible
|
|||
5. Installer calls CliApplication::runWorkflow with template, action ID, Hook, instance, and element for every element on this level.
|
||||
6. runWorkflow executes the element by calling the respective function
|
||||
7. runWorkflow calls itself with all child elements
|
||||
|
||||
Results can be stored in the workflow_instance_data field or in a workflow_step_data. The step data is if you want to store information for a specific step of a workflow instance.
|
||||
|
||||
## Install file explanations
|
||||
|
||||
### Triggers
|
||||
|
||||
Which internal event triggers exists. This allows workflows to bind actions to any of these possible triggers.
|
||||
|
||||
### Actions
|
||||
|
||||
These are the workflow actions that the module exposes. These can be used to create your own workflow by chaining multiple actions together
|
||||
|
||||
## Workflow definition
|
||||
|
||||
1. You can define workflows based on the above mentioned triggers and actions
|
||||
2. You can create programmed workflows using hooks which then trigger a workflow
|
||||
3. You can create "forms" that function as workflows ()
|
||||
|
||||
|
|
|
|||
46
Models/NullWorkflowStep.php
Normal file
46
Models/NullWorkflowStep.php
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
<?php
|
||||
/**
|
||||
* Jingga
|
||||
*
|
||||
* PHP Version 8.2
|
||||
*
|
||||
* @package Modules\Workflow\Models
|
||||
* @copyright Dennis Eichhorn
|
||||
* @license OMS License 2.2
|
||||
* @version 1.0.0
|
||||
* @link https://jingga.app
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Modules\Workflow\Models;
|
||||
|
||||
/**
|
||||
* Null model
|
||||
*
|
||||
* @package Modules\Workflow\Models
|
||||
* @license OMS License 2.2
|
||||
* @link https://jingga.app
|
||||
* @since 1.0.0
|
||||
*/
|
||||
final class NullWorkflowStep extends WorkflowStep
|
||||
{
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param int $id Model id
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function __construct(int $id = 0)
|
||||
{
|
||||
$this->id = $id;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function jsonSerialize() : mixed
|
||||
{
|
||||
return ['id' => $this->id];
|
||||
}
|
||||
}
|
||||
|
|
@ -64,6 +64,52 @@ interface WorkflowControllerInterface
|
|||
*/
|
||||
public function apiChangeState(RequestAbstract $request, ResponseAbstract $response, $data = null) : void;
|
||||
|
||||
/**
|
||||
* Change workflow instance state based on a hook
|
||||
*
|
||||
* @param WorkflowTemplate $template Workflow template
|
||||
* @param int $account Account who created the model
|
||||
* @param mixed $old Old value
|
||||
* @param mixed $new New value (unused, should be null)
|
||||
* @param int $type Module model type
|
||||
* @param string $trigger What triggered this log?
|
||||
* @param string $module Module name
|
||||
* @param string $ref Reference to other model
|
||||
* @param string $content Message
|
||||
* @param string $ip Ip
|
||||
*
|
||||
* @return mixed
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function hookChangeState(
|
||||
WorkflowTemplate $template,
|
||||
int $account,
|
||||
mixed $old,
|
||||
mixed $new,
|
||||
?int $type = null,
|
||||
string $trigger = '',
|
||||
?string $module = null,
|
||||
?string $ref = null,
|
||||
?string $content = null,
|
||||
?string $ip = null
|
||||
) : mixed;
|
||||
|
||||
/**
|
||||
* Handle workflow instance state
|
||||
*
|
||||
* This can be used to determine if a certain action is allowed or not based on the current state
|
||||
*
|
||||
* @param RequestAbstract $request Request
|
||||
* @param ResponseAbstract $response Response
|
||||
* @param null|mixed $data Data
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function apiHandleState(RequestAbstract $request, ResponseAbstract $response, $data = null) : void;
|
||||
|
||||
/**
|
||||
* Store instance model in the database
|
||||
*
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ use Modules\Admin\Models\NullAccount;
|
|||
* @link https://jingga.app
|
||||
* @since 1.0.0
|
||||
*/
|
||||
class WorkflowInstanceAbstract
|
||||
class WorkflowInstanceAbstract implements \JsonSerializable
|
||||
{
|
||||
/**
|
||||
* ID.
|
||||
|
|
@ -51,6 +51,22 @@ class WorkflowInstanceAbstract
|
|||
*/
|
||||
public string $data = '';
|
||||
|
||||
/**
|
||||
* Instance data.
|
||||
*
|
||||
* @var int
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public int $data_int = 0;
|
||||
|
||||
/**
|
||||
* Reference.
|
||||
*
|
||||
* @var int
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public int $ref = 0;
|
||||
|
||||
/**
|
||||
* Instance status.
|
||||
*
|
||||
|
|
@ -67,6 +83,14 @@ class WorkflowInstanceAbstract
|
|||
*/
|
||||
public WorkflowTemplate $template;
|
||||
|
||||
/**
|
||||
* Workflow steps.
|
||||
*
|
||||
* @var WorkflowStep[]
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public array $steps = [];
|
||||
|
||||
/**
|
||||
* Creator.
|
||||
*
|
||||
|
|
@ -102,4 +126,27 @@ class WorkflowInstanceAbstract
|
|||
$this->createdBy = new NullAccount();
|
||||
$this->createdAt = new \DateTimeImmutable('now');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function toArray() : array
|
||||
{
|
||||
return [
|
||||
'id' => $this->id,
|
||||
'title' => $this->title,
|
||||
'createdAt' => $this->createdAt,
|
||||
'data' => $this->data,
|
||||
'data_int' => $this->data_int,
|
||||
'ref' => $this->ref,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function jsonSerialize() : mixed
|
||||
{
|
||||
return $this->toArray();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,6 +41,8 @@ final class WorkflowInstanceAbstractMapper extends DataMapperFactory
|
|||
'workflow_instance_title' => ['name' => 'workflow_instance_title', 'type' => 'string', 'internal' => 'title'],
|
||||
'workflow_instance_status' => ['name' => 'workflow_instance_status', 'type' => 'int', 'internal' => 'status'],
|
||||
'workflow_instance_data' => ['name' => 'workflow_instance_data', 'type' => 'string', 'internal' => 'data'],
|
||||
'workflow_instance_int' => ['name' => 'workflow_instance_int', 'type' => 'int', 'internal' => 'data_int'],
|
||||
'workflow_instance_ref' => ['name' => 'workflow_instance_ref', 'type' => 'int', 'internal' => 'ref'],
|
||||
'workflow_instance_template' => ['name' => 'workflow_instance_template', 'type' => 'int', 'internal' => 'template'],
|
||||
'workflow_instance_created_at' => ['name' => 'workflow_instance_created_at', 'type' => 'DateTimeImmutable', 'internal' => 'createdAt', 'readonly' => true],
|
||||
'workflow_instance_created_by' => ['name' => 'workflow_instance_created_by', 'type' => 'int', 'internal' => 'createdBy', 'readonly' => true],
|
||||
|
|
@ -63,6 +65,21 @@ final class WorkflowInstanceAbstractMapper extends DataMapperFactory
|
|||
],
|
||||
];
|
||||
|
||||
/**
|
||||
* Has many relation.
|
||||
*
|
||||
* @var array<string, array{mapper:class-string, table:string, self?:?string, external?:?string, column?:string}>
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public const HAS_MANY = [
|
||||
'steps' => [
|
||||
'mapper' => WorkflowStepMapper::class,
|
||||
'table' => 'workflow_step',
|
||||
'self' => 'workflow_step_instance',
|
||||
'external' => null,
|
||||
],
|
||||
];
|
||||
|
||||
/**
|
||||
* Primary table.
|
||||
*
|
||||
|
|
|
|||
126
Models/WorkflowStep.php
Normal file
126
Models/WorkflowStep.php
Normal file
|
|
@ -0,0 +1,126 @@
|
|||
<?php
|
||||
/**
|
||||
* Jingga
|
||||
*
|
||||
* PHP Version 8.2
|
||||
*
|
||||
* @package Modules\Workflow\Models
|
||||
* @copyright Dennis Eichhorn
|
||||
* @license OMS License 2.2
|
||||
* @version 1.0.0
|
||||
* @link https://jingga.app
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Modules\Workflow\Models;
|
||||
|
||||
use Modules\Admin\Models\Account;
|
||||
use Modules\Admin\Models\NullAccount;
|
||||
use Modules\Media\Models\Collection;
|
||||
use Modules\Media\Models\NullCollection;
|
||||
|
||||
/**
|
||||
* Workflow template class.
|
||||
*
|
||||
* @package Modules\Workflow\Models
|
||||
* @license OMS License 2.2
|
||||
* @link https://jingga.app
|
||||
* @since 1.0.0
|
||||
*/
|
||||
class WorkflowStep
|
||||
{
|
||||
/**
|
||||
* ID.
|
||||
*
|
||||
* @var int
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public int $id = 0;
|
||||
|
||||
/**
|
||||
* Order.
|
||||
*
|
||||
* @var int
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public int $order = 0;
|
||||
|
||||
/**
|
||||
* Comment.
|
||||
*
|
||||
* @var string
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public string $comment = '';
|
||||
|
||||
/**
|
||||
* Data.
|
||||
*
|
||||
* @var string
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public string $data = '';
|
||||
|
||||
/**
|
||||
* Status.
|
||||
*
|
||||
* @var int
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public int $status = 0;
|
||||
|
||||
/**
|
||||
* Creator.
|
||||
*
|
||||
* @var Account
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public Account $createdBy;
|
||||
|
||||
/**
|
||||
* Created.
|
||||
*
|
||||
* @var \DateTimeImmutable
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public \DateTimeImmutable $createdAt;
|
||||
|
||||
/**
|
||||
* Instance.
|
||||
*
|
||||
* @var WorkflowInstanceAbstract
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public WorkflowInstanceAbstract $instance;
|
||||
|
||||
/**
|
||||
* Media.
|
||||
*
|
||||
* @var null|Collection
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public ?Collection $media = null;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->createdBy = new NullAccount();
|
||||
$this->createdAt = new \DateTimeImmutable('now');
|
||||
$this->instance = new NullWorkflowInstanceAbstract();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get hooks
|
||||
*
|
||||
* @return array
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function getHooks() : array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
}
|
||||
107
Models/WorkflowStepMapper.php
Normal file
107
Models/WorkflowStepMapper.php
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
<?php
|
||||
/**
|
||||
* Jingga
|
||||
*
|
||||
* PHP Version 8.2
|
||||
*
|
||||
* @package Modules\Workflow\Models
|
||||
* @copyright Dennis Eichhorn
|
||||
* @license OMS License 2.2
|
||||
* @version 1.0.0
|
||||
* @link https://jingga.app
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Modules\Workflow\Models;
|
||||
|
||||
use Modules\Admin\Models\AccountMapper;
|
||||
use Modules\Admin\Models\ModuleMapper;
|
||||
use Modules\Media\Models\CollectionMapper;
|
||||
use phpOMS\DataStorage\Database\Mapper\DataMapperFactory;
|
||||
|
||||
/**
|
||||
* WorkflowStep mapper class.
|
||||
*
|
||||
* @package Modules\Workflow\Models
|
||||
* @license OMS License 2.2
|
||||
* @link https://jingga.app
|
||||
* @since 1.0.0
|
||||
*
|
||||
* @template T of WorkflowStep
|
||||
* @extends DataMapperFactory<T>
|
||||
*/
|
||||
final class WorkflowStepMapper extends DataMapperFactory
|
||||
{
|
||||
/**
|
||||
* Columns.
|
||||
*
|
||||
* @var array<string, array{name:string, type:string, internal:string, autocomplete?:bool, readonly?:bool, writeonly?:bool, annotations?:array}>
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public const COLUMNS = [
|
||||
'workflow_step_id' => ['name' => 'workflow_step_id', 'type' => 'int', 'internal' => 'id'],
|
||||
'workflow_step_status' => ['name' => 'workflow_step_status', 'type' => 'int', 'internal' => 'status'],
|
||||
'workflow_step_order' => ['name' => 'workflow_step_order', 'type' => 'int', 'internal' => 'order'],
|
||||
'workflow_step_type' => ['name' => 'workflow_step_type', 'type' => 'int', 'internal' => 'type'],
|
||||
'workflow_step_comment' => ['name' => 'workflow_step_comment', 'type' => 'string', 'internal' => 'comment'],
|
||||
'workflow_step_data' => ['name' => 'workflow_step_data', 'type' => 'string', 'internal' => 'data'],
|
||||
'workflow_step_instance' => ['name' => 'workflow_step_instance', 'type' => 'Json', 'internal' => 'instance'],
|
||||
'workflow_step_media' => ['name' => 'workflow_step_media', 'type' => 'int', 'internal' => 'media'],
|
||||
'workflow_step_created_at' => ['name' => 'workflow_step_created_at', 'type' => 'DateTimeImmutable', 'internal' => 'createdAt', 'readonly' => true],
|
||||
'workflow_step_created_by' => ['name' => 'workflow_step_created_by', 'type' => 'int', 'internal' => 'createdBy', 'readonly' => true],
|
||||
];
|
||||
|
||||
/**
|
||||
* Has one relation.
|
||||
*
|
||||
* @var array<string, array{mapper:class-string, external:string, by?:string, column?:string, conditional?:bool}>
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public const OWNS_ONE = [
|
||||
'media' => [
|
||||
'mapper' => CollectionMapper::class,
|
||||
'external' => 'workflow_step_media',
|
||||
],
|
||||
];
|
||||
|
||||
/**
|
||||
* Belongs to.
|
||||
*
|
||||
* @var array<string, array{mapper:class-string, external:string, column?:string, by?:string}>
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public const BELONGS_TO = [
|
||||
'createdBy' => [
|
||||
'mapper' => AccountMapper::class,
|
||||
'external' => 'workflow_step_created_by',
|
||||
],
|
||||
'instance' => [
|
||||
'mapper' => ModuleMapper::class,
|
||||
'external' => 'workflow_step_instance',
|
||||
],
|
||||
];
|
||||
|
||||
/**
|
||||
* Primary table.
|
||||
*
|
||||
* @var string
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public const TABLE = 'workflow_step';
|
||||
|
||||
/**
|
||||
* Created at.
|
||||
*
|
||||
* @var string
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public const CREATED_AT = 'workflow_step_created_at';
|
||||
|
||||
/**
|
||||
* Primary field name.
|
||||
*
|
||||
* @var string
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public const PRIMARYFIELD = 'workflow_step_id';
|
||||
}
|
||||
|
|
@ -15,7 +15,9 @@ declare(strict_types=1);
|
|||
namespace Modules\Workflow\Models;
|
||||
|
||||
use Modules\Admin\Models\Account;
|
||||
use Modules\Admin\Models\Module;
|
||||
use Modules\Admin\Models\NullAccount;
|
||||
use Modules\Admin\Models\NullModule;
|
||||
use Modules\Media\Models\Collection;
|
||||
use Modules\Media\Models\NullCollection;
|
||||
|
||||
|
|
@ -45,6 +47,17 @@ class WorkflowTemplate
|
|||
*/
|
||||
public string $name = '';
|
||||
|
||||
/**
|
||||
* Type.
|
||||
*
|
||||
* This is only for internal usage per module.
|
||||
* Modules may use this to internally handle workflows
|
||||
*
|
||||
* @var int
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public int $type = 0;
|
||||
|
||||
/**
|
||||
* Description.
|
||||
*
|
||||
|
|
@ -85,6 +98,14 @@ class WorkflowTemplate
|
|||
*/
|
||||
public \DateTimeImmutable $createdAt;
|
||||
|
||||
/**
|
||||
* Module.
|
||||
*
|
||||
* @var null|Module
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public ?Module $module = null;
|
||||
|
||||
/**
|
||||
* Template source.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ declare(strict_types=1);
|
|||
namespace Modules\Workflow\Models;
|
||||
|
||||
use Modules\Admin\Models\AccountMapper;
|
||||
use Modules\Admin\Models\ModuleMapper;
|
||||
use Modules\Media\Models\CollectionMapper;
|
||||
use phpOMS\DataStorage\Database\Mapper\DataMapperFactory;
|
||||
|
||||
|
|
@ -40,10 +41,12 @@ final class WorkflowTemplateMapper extends DataMapperFactory
|
|||
public const COLUMNS = [
|
||||
'workflow_template_id' => ['name' => 'workflow_template_id', 'type' => 'int', 'internal' => 'id'],
|
||||
'workflow_template_status' => ['name' => 'workflow_template_status', 'type' => 'int', 'internal' => 'status'],
|
||||
'workflow_template_type' => ['name' => 'workflow_template_type', 'type' => 'int', 'internal' => 'type'],
|
||||
'workflow_template_name' => ['name' => 'workflow_template_name', 'type' => 'string', 'internal' => 'name'],
|
||||
'workflow_template_desc' => ['name' => 'workflow_template_desc', 'type' => 'string', 'internal' => 'description'],
|
||||
'workflow_template_descRaw' => ['name' => 'workflow_template_descRaw', 'type' => 'string', 'internal' => 'descriptionRaw'],
|
||||
'workflow_template_schema' => ['name' => 'workflow_template_schema', 'type' => 'Json', 'internal' => 'schema'],
|
||||
'workflow_template_module' => ['name' => 'workflow_template_module', 'type' => 'string', 'internal' => 'module'],
|
||||
'workflow_template_media' => ['name' => 'workflow_template_media', 'type' => 'int', 'internal' => 'source'],
|
||||
'workflow_template_created_at' => ['name' => 'workflow_template_created_at', 'type' => 'DateTimeImmutable', 'internal' => 'createdAt', 'readonly' => true],
|
||||
'workflow_template_created_by' => ['name' => 'workflow_template_created_by', 'type' => 'int', 'internal' => 'createdBy', 'readonly' => true],
|
||||
|
|
@ -73,6 +76,10 @@ final class WorkflowTemplateMapper extends DataMapperFactory
|
|||
'mapper' => AccountMapper::class,
|
||||
'external' => 'workflow_template_created_by',
|
||||
],
|
||||
'module' => [
|
||||
'mapper' => ModuleMapper::class,
|
||||
'external' => 'workflow_template_module',
|
||||
],
|
||||
];
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ $accountDir = $account->id . ' ' . $account->login;
|
|||
|
||||
/** @var \Modules\Media\Models\Collection[] */
|
||||
$collections = $this->data['collections'];
|
||||
$mediaPath = \urldecode($this->getData('path') ?? '/');
|
||||
$mediaPath = \urldecode($this->data['path'] ?? '/');
|
||||
|
||||
$previous = empty($templates) ? 'workflow/template/list' : '{/base}/workflow/template/list?{?}&offset=' . \reset($templates)->id . '&ptype=p';
|
||||
$next = empty($templates) ? 'workflow/template/list' : '{/base}/workflow/template/list?{?}&offset=' . \end($templates)->id . '&ptype=n';
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user