Initial commit
This commit is contained in:
@@ -0,0 +1,214 @@
|
||||
<?php
|
||||
/***********************************************************************************
|
||||
* The contents of this file are subject to the Extension License Agreement
|
||||
* ("Agreement") which can be viewed at
|
||||
* https://www.espocrm.com/extension-license-agreement/.
|
||||
* By copying, installing downloading, or using this file, You have unconditionally
|
||||
* agreed to the terms and conditions of the Agreement, and You may not use this
|
||||
* file except in compliance with the Agreement. Under the terms of the Agreement,
|
||||
* You shall not license, sublicense, sell, resell, rent, lease, lend, distribute,
|
||||
* redistribute, market, publish, commercialize, or otherwise transfer rights or
|
||||
* usage to the software or any modified version or derivative work of the software
|
||||
* created by or for you.
|
||||
*
|
||||
* Copyright (C) 2015-2025 EspoCRM, Inc.
|
||||
*
|
||||
* License ID: 19bc86a68a7bb01f458cb391d43a9212
|
||||
************************************************************************************/
|
||||
|
||||
namespace Espo\Modules\Advanced\Hooks\BpmnFlowchart;
|
||||
|
||||
use Espo\Modules\Advanced\Entities\BpmnFlowchart;
|
||||
use Espo\Modules\Advanced\Entities\Workflow;
|
||||
use Espo\ORM\Entity;
|
||||
use Espo\ORM\EntityManager;
|
||||
|
||||
class CreateWorkflows
|
||||
{
|
||||
public function __construct(private EntityManager $entityManager)
|
||||
{}
|
||||
|
||||
/**
|
||||
* @param BpmnFlowchart $entity
|
||||
*/
|
||||
public function afterSave(Entity $entity): void
|
||||
{
|
||||
$workflowList = $this->entityManager
|
||||
->getRDBRepositoryByClass(Workflow::class)
|
||||
->where([
|
||||
'flowchartId' => $entity->getId(),
|
||||
'isInternal' => true,
|
||||
])
|
||||
->find();
|
||||
|
||||
$workflowsToRecreate = false;
|
||||
|
||||
if (
|
||||
!$entity->isNew() &&
|
||||
json_encode($entity->get('data')) !== json_encode($entity->getFetched('data'))
|
||||
) {
|
||||
$workflowsToRecreate = true;
|
||||
}
|
||||
|
||||
if ($entity->isNew() || $workflowsToRecreate) {
|
||||
$this->removeWorkflows($entity);
|
||||
|
||||
$data = $entity->get('data');
|
||||
|
||||
if (isset($data->list) && is_array($data->list)) {
|
||||
foreach ($data->list as $item) {
|
||||
if (!is_object($item)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$itId = $item->id ?? null;
|
||||
$itType = $item->type ?? null;
|
||||
$itTriggerType = $item->triggerType ?? null;
|
||||
$itSignal = $item->signal ?? null;
|
||||
|
||||
if (
|
||||
$itType === 'eventStartConditional' &&
|
||||
in_array($itTriggerType, [
|
||||
'afterRecordCreated',
|
||||
'afterRecordSaved',
|
||||
'afterRecordUpdated',
|
||||
])
|
||||
) {
|
||||
$workflow = $this->entityManager->getNewEntity(Workflow::ENTITY_TYPE);
|
||||
|
||||
$conditionsAll = [];
|
||||
|
||||
if (isset($item->conditionsAll)) {
|
||||
$conditionsAll = $item->conditionsAll;
|
||||
}
|
||||
|
||||
$conditionsAny = [];
|
||||
|
||||
if (isset($item->conditionsAny)) {
|
||||
$conditionsAny = $item->conditionsAny;
|
||||
}
|
||||
|
||||
$conditionsFormula = null;
|
||||
|
||||
if (isset($item->conditionsFormula)) {
|
||||
$conditionsFormula = $item->conditionsFormula;
|
||||
}
|
||||
|
||||
$workflow->set([
|
||||
'type' => $itTriggerType,
|
||||
'entityType' => $entity->get('targetType'),
|
||||
'isInternal' => true,
|
||||
'flowchartId' => $entity->getId(),
|
||||
'isActive' => $entity->get('isActive'),
|
||||
'conditionsAll' => $conditionsAll,
|
||||
'conditionsAny' => $conditionsAny,
|
||||
'conditionsFormula' => $conditionsFormula,
|
||||
'actions' => [
|
||||
(object) [
|
||||
'type' => 'startBpmnProcess',
|
||||
'flowchartId' => $entity->getId(),
|
||||
'elementId' => $itId,
|
||||
'cid' => 0,
|
||||
]
|
||||
],
|
||||
'processOrder' => 100,
|
||||
]);
|
||||
|
||||
$this->entityManager->saveEntity($workflow);
|
||||
}
|
||||
|
||||
if (
|
||||
$itType === 'eventStartSignal' &&
|
||||
$itSignal
|
||||
) {
|
||||
$workflow = $this->entityManager->getNewEntity(Workflow::ENTITY_TYPE);
|
||||
|
||||
$workflow->set([
|
||||
'type' => Workflow::TYPE_SIGNAL,
|
||||
'signalName' => $itSignal,
|
||||
'entityType' => $entity->get('targetType'),
|
||||
'isInternal' => true,
|
||||
'flowchartId' => $entity->get('id'),
|
||||
'isActive' => $entity->get('isActive'),
|
||||
'actions' => [
|
||||
(object) [
|
||||
'type' => 'startBpmnProcess',
|
||||
'flowchartId' => $entity->getId(),
|
||||
'elementId' => $itId,
|
||||
'cid' => 0,
|
||||
]
|
||||
],
|
||||
'processOrder' => 150,
|
||||
]);
|
||||
|
||||
$this->entityManager->saveEntity($workflow);
|
||||
}
|
||||
|
||||
if (
|
||||
$itType === 'eventStartTimer' &&
|
||||
!empty($item->targetReportId) &&
|
||||
!empty($item->scheduling)
|
||||
) {
|
||||
$workflow = $this->entityManager->getNewEntity(Workflow::ENTITY_TYPE);
|
||||
|
||||
$workflow->set([
|
||||
'type' => Workflow::TYPE_SCHEDULED,
|
||||
'entityType' => $entity->get('targetType'),
|
||||
'isInternal' => true,
|
||||
'flowchartId' => $entity->getId(),
|
||||
'isActive' => $entity->get('isActive'),
|
||||
'scheduling' => $item->scheduling,
|
||||
'schedulingApplyTimezone' => $item->schedulingApplyTimezone ?? false,
|
||||
'targetReportId' => $item->targetReportId,
|
||||
'targetReportName' => $item->targetReportId,
|
||||
'actions' => [
|
||||
(object) [
|
||||
'type' => 'startBpmnProcess',
|
||||
'flowchartId' => $entity->getId(),
|
||||
'elementId' => $itId,
|
||||
'cid' => 0,
|
||||
]
|
||||
],
|
||||
'processOrder' => 100,
|
||||
]);
|
||||
|
||||
$this->entityManager->saveEntity($workflow);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
$entity->isAttributeChanged('isActive') &&
|
||||
!$entity->isNew() &&
|
||||
!$workflowsToRecreate
|
||||
) {
|
||||
foreach ($workflowList as $workflow) {
|
||||
if ($workflow->get('isActive') !== $entity->get('isActive')) {
|
||||
$workflow->set('isActive', $entity->get('isActive'));
|
||||
|
||||
$this->entityManager->saveEntity($workflow);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function removeWorkflows(Entity $entity): void
|
||||
{
|
||||
$workflowList = $this->entityManager
|
||||
->getRDBRepository(Workflow::ENTITY_TYPE)
|
||||
->where([
|
||||
'flowchartId' => $entity->getId(),
|
||||
'isInternal' => true,
|
||||
])
|
||||
->find();
|
||||
|
||||
foreach ($workflowList as $workflow) {
|
||||
$this->entityManager->removeEntity($workflow);
|
||||
|
||||
$this->entityManager
|
||||
->getRDBRepository(Workflow::ENTITY_TYPE)
|
||||
->deleteFromDb($workflow->getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
58
custom/Espo/Modules/Advanced/Hooks/BpmnFlowchart/Prepare.php
Normal file
58
custom/Espo/Modules/Advanced/Hooks/BpmnFlowchart/Prepare.php
Normal file
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
/***********************************************************************************
|
||||
* The contents of this file are subject to the Extension License Agreement
|
||||
* ("Agreement") which can be viewed at
|
||||
* https://www.espocrm.com/extension-license-agreement/.
|
||||
* By copying, installing downloading, or using this file, You have unconditionally
|
||||
* agreed to the terms and conditions of the Agreement, and You may not use this
|
||||
* file except in compliance with the Agreement. Under the terms of the Agreement,
|
||||
* You shall not license, sublicense, sell, resell, rent, lease, lend, distribute,
|
||||
* redistribute, market, publish, commercialize, or otherwise transfer rights or
|
||||
* usage to the software or any modified version or derivative work of the software
|
||||
* created by or for you.
|
||||
*
|
||||
* Copyright (C) 2015-2025 EspoCRM, Inc.
|
||||
*
|
||||
* License ID: 19bc86a68a7bb01f458cb391d43a9212
|
||||
************************************************************************************/
|
||||
|
||||
namespace Espo\Modules\Advanced\Hooks\BpmnFlowchart;
|
||||
|
||||
use Espo\Modules\Advanced\Core\Bpmn\Utils\Helper;
|
||||
use Espo\Modules\Advanced\Entities\BpmnFlowchart;
|
||||
use Espo\ORM\Entity;
|
||||
|
||||
class Prepare
|
||||
{
|
||||
/**
|
||||
* @param BpmnFlowchart $entity
|
||||
*/
|
||||
public function beforeSave(Entity $entity): void
|
||||
{
|
||||
$handleFlowchartData = false;
|
||||
|
||||
if (
|
||||
$entity->isNew() ||
|
||||
json_encode($entity->get('data')) !== json_encode($entity->getFetched('data'))
|
||||
) {
|
||||
$handleFlowchartData = true;
|
||||
}
|
||||
|
||||
if (!$handleFlowchartData) {
|
||||
return;
|
||||
}
|
||||
|
||||
$data = $entity->get('data') ?? (object) [];
|
||||
|
||||
$eData = Helper::getElementsDataFromFlowchartData($data);
|
||||
|
||||
$elementsDataHash = $eData['elementsDataHash'];
|
||||
$eventStartIdList = $eData['eventStartIdList'];
|
||||
$eventStartAllIdList = $eData['eventStartAllIdList'];
|
||||
|
||||
$entity->set('elementsDataHash', $elementsDataHash);
|
||||
$entity->set('hasNoneStartEvent', count($eventStartIdList) > 0);
|
||||
$entity->set('eventStartIdList', $eventStartIdList);
|
||||
$entity->set('eventStartAllIdList', $eventStartAllIdList);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
/***********************************************************************************
|
||||
* The contents of this file are subject to the Extension License Agreement
|
||||
* ("Agreement") which can be viewed at
|
||||
* https://www.espocrm.com/extension-license-agreement/.
|
||||
* By copying, installing downloading, or using this file, You have unconditionally
|
||||
* agreed to the terms and conditions of the Agreement, and You may not use this
|
||||
* file except in compliance with the Agreement. Under the terms of the Agreement,
|
||||
* You shall not license, sublicense, sell, resell, rent, lease, lend, distribute,
|
||||
* redistribute, market, publish, commercialize, or otherwise transfer rights or
|
||||
* usage to the software or any modified version or derivative work of the software
|
||||
* created by or for you.
|
||||
*
|
||||
* Copyright (C) 2015-2025 EspoCRM, Inc.
|
||||
*
|
||||
* License ID: 19bc86a68a7bb01f458cb391d43a9212
|
||||
************************************************************************************/
|
||||
|
||||
namespace Espo\Modules\Advanced\Hooks\BpmnFlowchart;
|
||||
|
||||
use Espo\ORM\Entity;
|
||||
|
||||
use Espo\Modules\Advanced\Entities\WorkflowRoundRobin;
|
||||
use Espo\ORM\EntityManager;
|
||||
|
||||
class RemoveRoundRobin
|
||||
{
|
||||
/** @var int */
|
||||
public static $order = 9;
|
||||
|
||||
public function __construct(private EntityManager $entityManager)
|
||||
{}
|
||||
|
||||
public function afterRemove(Entity $entity): void
|
||||
{
|
||||
$roundRobinList = $this->entityManager
|
||||
->getRDBRepository(WorkflowRoundRobin::ENTITY_TYPE)
|
||||
->where(['flowchartId' => $entity->getId()])
|
||||
->find();
|
||||
|
||||
foreach ($roundRobinList as $item) {
|
||||
$this->entityManager->removeEntity($item);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
/***********************************************************************************
|
||||
* The contents of this file are subject to the Extension License Agreement
|
||||
* ("Agreement") which can be viewed at
|
||||
* https://www.espocrm.com/extension-license-agreement/.
|
||||
* By copying, installing downloading, or using this file, You have unconditionally
|
||||
* agreed to the terms and conditions of the Agreement, and You may not use this
|
||||
* file except in compliance with the Agreement. Under the terms of the Agreement,
|
||||
* You shall not license, sublicense, sell, resell, rent, lease, lend, distribute,
|
||||
* redistribute, market, publish, commercialize, or otherwise transfer rights or
|
||||
* usage to the software or any modified version or derivative work of the software
|
||||
* created by or for you.
|
||||
*
|
||||
* Copyright (C) 2015-2025 EspoCRM, Inc.
|
||||
*
|
||||
* License ID: 19bc86a68a7bb01f458cb391d43a9212
|
||||
************************************************************************************/
|
||||
|
||||
namespace Espo\Modules\Advanced\Hooks\BpmnFlowchart;
|
||||
|
||||
use Espo\Modules\Advanced\Entities\Workflow;
|
||||
use Espo\ORM\Entity;
|
||||
use Espo\ORM\EntityManager;
|
||||
|
||||
class RemoveWorkflows
|
||||
{
|
||||
private EntityManager $entityManager;
|
||||
|
||||
public function __construct(EntityManager $entityManager)
|
||||
{
|
||||
$this->entityManager = $entityManager;
|
||||
}
|
||||
|
||||
public function afterRemove(Entity $entity): void
|
||||
{
|
||||
$workflowList = $this->entityManager
|
||||
->getRDBRepository(Workflow::ENTITY_TYPE)
|
||||
->where([
|
||||
'flowchartId' => $entity->getId(),
|
||||
'isInternal' => true,
|
||||
])
|
||||
->find();
|
||||
|
||||
foreach ($workflowList as $workflow) {
|
||||
$this->entityManager->removeEntity($workflow);
|
||||
|
||||
$this->entityManager->getRDBRepository(Workflow::ENTITY_TYPE)
|
||||
->deleteFromDb($workflow->getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
/***********************************************************************************
|
||||
* The contents of this file are subject to the Extension License Agreement
|
||||
* ("Agreement") which can be viewed at
|
||||
* https://www.espocrm.com/extension-license-agreement/.
|
||||
* By copying, installing downloading, or using this file, You have unconditionally
|
||||
* agreed to the terms and conditions of the Agreement, and You may not use this
|
||||
* file except in compliance with the Agreement. Under the terms of the Agreement,
|
||||
* You shall not license, sublicense, sell, resell, rent, lease, lend, distribute,
|
||||
* redistribute, market, publish, commercialize, or otherwise transfer rights or
|
||||
* usage to the software or any modified version or derivative work of the software
|
||||
* created by or for you.
|
||||
*
|
||||
* Copyright (C) 2015-2025 EspoCRM, Inc.
|
||||
*
|
||||
* License ID: 19bc86a68a7bb01f458cb391d43a9212
|
||||
************************************************************************************/
|
||||
|
||||
namespace Espo\Modules\Advanced\Hooks\BpmnProcess;
|
||||
|
||||
use Espo\Modules\Advanced\Entities\BpmnFlowNode;
|
||||
use Espo\ORM\Entity;
|
||||
use Espo\ORM\EntityManager;
|
||||
|
||||
class RejectFlowNodes
|
||||
{
|
||||
private EntityManager $entityManager;
|
||||
|
||||
public function __construct(EntityManager $entityManager)
|
||||
{
|
||||
$this->entityManager = $entityManager;
|
||||
}
|
||||
|
||||
public function afterRemove(Entity $entity): void
|
||||
{
|
||||
$flowNodeList = $this->entityManager
|
||||
->getRDBRepositoryByClass(BpmnFlowNode::class)
|
||||
->where([
|
||||
'processId' => $entity->getId(),
|
||||
'status!=' => [
|
||||
BpmnFlowNode::STATUS_PROCESSED,
|
||||
BpmnFlowNode::STATUS_REJECTED,
|
||||
BpmnFlowNode::STATUS_FAILED,
|
||||
],
|
||||
])
|
||||
->find();
|
||||
|
||||
foreach ($flowNodeList as $flowNode) {
|
||||
$flowNode->setStatus(BpmnFlowNode::STATUS_REJECTED);
|
||||
|
||||
$this->entityManager->saveEntity($flowNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
/***********************************************************************************
|
||||
* The contents of this file are subject to the Extension License Agreement
|
||||
* ("Agreement") which can be viewed at
|
||||
* https://www.espocrm.com/extension-license-agreement/.
|
||||
* By copying, installing downloading, or using this file, You have unconditionally
|
||||
* agreed to the terms and conditions of the Agreement, and You may not use this
|
||||
* file except in compliance with the Agreement. Under the terms of the Agreement,
|
||||
* You shall not license, sublicense, sell, resell, rent, lease, lend, distribute,
|
||||
* redistribute, market, publish, commercialize, or otherwise transfer rights or
|
||||
* usage to the software or any modified version or derivative work of the software
|
||||
* created by or for you.
|
||||
*
|
||||
* Copyright (C) 2015-2025 EspoCRM, Inc.
|
||||
*
|
||||
* License ID: 19bc86a68a7bb01f458cb391d43a9212
|
||||
************************************************************************************/
|
||||
|
||||
namespace Espo\Modules\Advanced\Hooks\BpmnProcess;
|
||||
|
||||
use Espo\Modules\Advanced\Entities\BpmnProcess;
|
||||
use Espo\ORM\Entity;
|
||||
|
||||
class RootProcess
|
||||
{
|
||||
/**
|
||||
* @param BpmnProcess $entity
|
||||
*/
|
||||
public function beforeSave(Entity $entity): void
|
||||
{
|
||||
if (!$entity->isNew()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($entity->getRootProcessId()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$entity->set('rootProcessId', $entity->getId());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
/***********************************************************************************
|
||||
* The contents of this file are subject to the Extension License Agreement
|
||||
* ("Agreement") which can be viewed at
|
||||
* https://www.espocrm.com/extension-license-agreement/.
|
||||
* By copying, installing downloading, or using this file, You have unconditionally
|
||||
* agreed to the terms and conditions of the Agreement, and You may not use this
|
||||
* file except in compliance with the Agreement. Under the terms of the Agreement,
|
||||
* You shall not license, sublicense, sell, resell, rent, lease, lend, distribute,
|
||||
* redistribute, market, publish, commercialize, or otherwise transfer rights or
|
||||
* usage to the software or any modified version or derivative work of the software
|
||||
* created by or for you.
|
||||
*
|
||||
* Copyright (C) 2015-2025 EspoCRM, Inc.
|
||||
*
|
||||
* License ID: 19bc86a68a7bb01f458cb391d43a9212
|
||||
************************************************************************************/
|
||||
|
||||
namespace Espo\Modules\Advanced\Hooks\BpmnProcess;
|
||||
|
||||
use Espo\Core\Exceptions\Error;
|
||||
use Espo\Core\InjectableFactory;
|
||||
use Espo\Modules\Advanced\Core\Bpmn\BpmnManager;
|
||||
use Espo\Modules\Advanced\Entities\BpmnProcess;
|
||||
use Espo\ORM\Entity;
|
||||
|
||||
class StartProcess
|
||||
{
|
||||
public function __construct(
|
||||
private InjectableFactory $injectableFactory
|
||||
) {}
|
||||
|
||||
/**
|
||||
* @param BpmnProcess $entity
|
||||
* @param array<string, mixed> $options
|
||||
* @throws Error
|
||||
*/
|
||||
public function afterSave(Entity $entity, array $options): void
|
||||
{
|
||||
if (!$entity->isNew()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!empty($options['skipStartProcessFlow'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
$manager = $this->injectableFactory->create(BpmnManager::class);
|
||||
|
||||
$manager->startCreatedProcess($entity);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
<?php
|
||||
/***********************************************************************************
|
||||
* The contents of this file are subject to the Extension License Agreement
|
||||
* ("Agreement") which can be viewed at
|
||||
* https://www.espocrm.com/extension-license-agreement/.
|
||||
* By copying, installing downloading, or using this file, You have unconditionally
|
||||
* agreed to the terms and conditions of the Agreement, and You may not use this
|
||||
* file except in compliance with the Agreement. Under the terms of the Agreement,
|
||||
* You shall not license, sublicense, sell, resell, rent, lease, lend, distribute,
|
||||
* redistribute, market, publish, commercialize, or otherwise transfer rights or
|
||||
* usage to the software or any modified version or derivative work of the software
|
||||
* created by or for you.
|
||||
*
|
||||
* Copyright (C) 2015-2025 EspoCRM, Inc.
|
||||
*
|
||||
* License ID: 19bc86a68a7bb01f458cb391d43a9212
|
||||
************************************************************************************/
|
||||
|
||||
namespace Espo\Modules\Advanced\Hooks\BpmnProcess;
|
||||
|
||||
use Espo\Core\InjectableFactory;
|
||||
use Espo\Modules\Advanced\Core\Bpmn\BpmnManager;
|
||||
use Espo\Modules\Advanced\Entities\BpmnProcess;
|
||||
use Espo\ORM\Entity;
|
||||
use Espo\ORM\EntityManager;
|
||||
|
||||
class StopProcess
|
||||
{
|
||||
public function __construct(
|
||||
private InjectableFactory $injectableFactory,
|
||||
private EntityManager $entityManager
|
||||
) {}
|
||||
|
||||
/**
|
||||
* @param BpmnProcess $entity
|
||||
* @param array<string, mixed> $options
|
||||
*/
|
||||
public function afterSave(Entity $entity, array $options): void
|
||||
{
|
||||
if (!empty($options['skipStopProcess'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($entity->isNew()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!$entity->isAttributeChanged('status')) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($entity->getStatus() !== BpmnProcess::STATUS_STOPPED) {
|
||||
return;
|
||||
}
|
||||
|
||||
$manager = $this->injectableFactory->create(BpmnManager::class);
|
||||
|
||||
$manager->stopProcess($entity);
|
||||
|
||||
$subProcessList = $this->entityManager
|
||||
->getRDBRepositoryByClass(BpmnProcess::class)
|
||||
->where(['parentProcessId' => $entity->getId()])
|
||||
->find();
|
||||
|
||||
foreach ($subProcessList as $e) {
|
||||
$manager->stopProcess($e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
/***********************************************************************************
|
||||
* The contents of this file are subject to the Extension License Agreement
|
||||
* ("Agreement") which can be viewed at
|
||||
* https://www.espocrm.com/extension-license-agreement/.
|
||||
* By copying, installing downloading, or using this file, You have unconditionally
|
||||
* agreed to the terms and conditions of the Agreement, and You may not use this
|
||||
* file except in compliance with the Agreement. Under the terms of the Agreement,
|
||||
* You shall not license, sublicense, sell, resell, rent, lease, lend, distribute,
|
||||
* redistribute, market, publish, commercialize, or otherwise transfer rights or
|
||||
* usage to the software or any modified version or derivative work of the software
|
||||
* created by or for you.
|
||||
*
|
||||
* Copyright (C) 2015-2025 EspoCRM, Inc.
|
||||
*
|
||||
* License ID: 19bc86a68a7bb01f458cb391d43a9212
|
||||
************************************************************************************/
|
||||
|
||||
namespace Espo\Modules\Advanced\Hooks\BpmnProcess;
|
||||
|
||||
use Espo\Modules\Advanced\Entities\BpmnProcess;
|
||||
use Espo\ORM\Entity;
|
||||
use Espo\ORM\EntityManager;
|
||||
|
||||
class SubProcesses
|
||||
{
|
||||
public function __construct(private EntityManager $entityManager)
|
||||
{}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $options
|
||||
*/
|
||||
public function afterRemove(Entity $entity, array $options): void
|
||||
{
|
||||
$subProcessList = $this->entityManager
|
||||
->getRDBRepository(BpmnProcess::ENTITY_TYPE)
|
||||
->where(['parentProcessId' => $entity->getId()])
|
||||
->find();
|
||||
|
||||
foreach ($subProcessList as $e) {
|
||||
$this->entityManager->removeEntity($e, $options);
|
||||
}
|
||||
}
|
||||
}
|
||||
47
custom/Espo/Modules/Advanced/Hooks/BpmnUserTask/Prepare.php
Normal file
47
custom/Espo/Modules/Advanced/Hooks/BpmnUserTask/Prepare.php
Normal file
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
/***********************************************************************************
|
||||
* The contents of this file are subject to the Extension License Agreement
|
||||
* ("Agreement") which can be viewed at
|
||||
* https://www.espocrm.com/extension-license-agreement/.
|
||||
* By copying, installing downloading, or using this file, You have unconditionally
|
||||
* agreed to the terms and conditions of the Agreement, and You may not use this
|
||||
* file except in compliance with the Agreement. Under the terms of the Agreement,
|
||||
* You shall not license, sublicense, sell, resell, rent, lease, lend, distribute,
|
||||
* redistribute, market, publish, commercialize, or otherwise transfer rights or
|
||||
* usage to the software or any modified version or derivative work of the software
|
||||
* created by or for you.
|
||||
*
|
||||
* Copyright (C) 2015-2025 EspoCRM, Inc.
|
||||
*
|
||||
* License ID: 19bc86a68a7bb01f458cb391d43a9212
|
||||
************************************************************************************/
|
||||
|
||||
namespace Espo\Modules\Advanced\Hooks\BpmnUserTask;
|
||||
|
||||
use Espo\Modules\Advanced\Entities\BpmnUserTask;
|
||||
use Espo\ORM\Entity;
|
||||
|
||||
class Prepare
|
||||
{
|
||||
/**
|
||||
* @param BpmnUserTask $entity
|
||||
*/
|
||||
public function beforeSave(Entity $entity): void
|
||||
{
|
||||
if (
|
||||
!$entity->get('isResolved') &&
|
||||
$entity->get('resolution') &&
|
||||
$entity->isAttributeChanged('resolution')
|
||||
) {
|
||||
$entity->set('isResolved', true);
|
||||
}
|
||||
|
||||
if (
|
||||
!$entity->get('isResolved') &&
|
||||
$entity->get('isCanceled') &&
|
||||
$entity->isAttributeChanged('isCanceled')
|
||||
) {
|
||||
$entity->set('resolution', BpmnUserTask::RESOLUTION_CANCELED);
|
||||
}
|
||||
}
|
||||
}
|
||||
69
custom/Espo/Modules/Advanced/Hooks/BpmnUserTask/Resolve.php
Normal file
69
custom/Espo/Modules/Advanced/Hooks/BpmnUserTask/Resolve.php
Normal file
@@ -0,0 +1,69 @@
|
||||
<?php
|
||||
/***********************************************************************************
|
||||
* The contents of this file are subject to the Extension License Agreement
|
||||
* ("Agreement") which can be viewed at
|
||||
* https://www.espocrm.com/extension-license-agreement/.
|
||||
* By copying, installing downloading, or using this file, You have unconditionally
|
||||
* agreed to the terms and conditions of the Agreement, and You may not use this
|
||||
* file except in compliance with the Agreement. Under the terms of the Agreement,
|
||||
* You shall not license, sublicense, sell, resell, rent, lease, lend, distribute,
|
||||
* redistribute, market, publish, commercialize, or otherwise transfer rights or
|
||||
* usage to the software or any modified version or derivative work of the software
|
||||
* created by or for you.
|
||||
*
|
||||
* Copyright (C) 2015-2025 EspoCRM, Inc.
|
||||
*
|
||||
* License ID: 19bc86a68a7bb01f458cb391d43a9212
|
||||
************************************************************************************/
|
||||
|
||||
namespace Espo\Modules\Advanced\Hooks\BpmnUserTask;
|
||||
|
||||
use Espo\Core\InjectableFactory;
|
||||
use Espo\Modules\Advanced\Core\Bpmn\BpmnManager;
|
||||
use Espo\Modules\Advanced\Entities\BpmnFlowNode;
|
||||
use Espo\Modules\Advanced\Entities\BpmnUserTask;
|
||||
use Espo\ORM\Entity;
|
||||
use Espo\ORM\EntityManager;
|
||||
|
||||
class Resolve
|
||||
{
|
||||
private EntityManager $entityManager;
|
||||
private InjectableFactory $injectableFactory;
|
||||
|
||||
public function __construct(
|
||||
EntityManager $entityManager,
|
||||
InjectableFactory $injectableFactory
|
||||
) {
|
||||
$this->entityManager = $entityManager;
|
||||
$this->injectableFactory = $injectableFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param BpmnUserTask $entity
|
||||
*/
|
||||
public function afterSave(Entity $entity): void
|
||||
{
|
||||
$flowNodeId = $entity->get('flowNodeId');
|
||||
|
||||
if (!$flowNodeId) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!$entity->getFetched('isResolved') && $entity->get('isResolved')) {
|
||||
/** @var ?BpmnFlowNode $flowNode */
|
||||
$flowNode = $this->entityManager->getEntityById(BpmnFlowNode::ENTITY_TYPE, $flowNodeId);
|
||||
|
||||
if (!$flowNode) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($flowNode->getStatus() !== BpmnFlowNode::STATUS_IN_PROCESS) {
|
||||
return;
|
||||
}
|
||||
|
||||
$manager = $this->injectableFactory->create(BpmnManager::class);
|
||||
|
||||
$manager->completeFlow($flowNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
<?php
|
||||
/***********************************************************************************
|
||||
* The contents of this file are subject to the Extension License Agreement
|
||||
* ("Agreement") which can be viewed at
|
||||
* https://www.espocrm.com/extension-license-agreement/.
|
||||
* By copying, installing downloading, or using this file, You have unconditionally
|
||||
* agreed to the terms and conditions of the Agreement, and You may not use this
|
||||
* file except in compliance with the Agreement. Under the terms of the Agreement,
|
||||
* You shall not license, sublicense, sell, resell, rent, lease, lend, distribute,
|
||||
* redistribute, market, publish, commercialize, or otherwise transfer rights or
|
||||
* usage to the software or any modified version or derivative work of the software
|
||||
* created by or for you.
|
||||
*
|
||||
* Copyright (C) 2015-2025 EspoCRM, Inc.
|
||||
*
|
||||
* License ID: 19bc86a68a7bb01f458cb391d43a9212
|
||||
************************************************************************************/
|
||||
|
||||
namespace Espo\Modules\Advanced\Hooks\CampaignTrackingUrl;
|
||||
|
||||
use Espo\Modules\Advanced\Core\SignalManager;
|
||||
use Espo\ORM\Entity;
|
||||
use Espo\ORM\EntityManager;
|
||||
|
||||
/**
|
||||
* @noinspection PhpUnused
|
||||
*/
|
||||
class Signal
|
||||
{
|
||||
/** @var int */
|
||||
public static $order = 100;
|
||||
|
||||
public function __construct(
|
||||
private EntityManager $entityManager,
|
||||
private SignalManager $signalManager
|
||||
) {}
|
||||
|
||||
/**
|
||||
* @noinspection PhpUnused
|
||||
* @param array<string, mixed> $options
|
||||
* @param array<string, mixed> $hookData
|
||||
*/
|
||||
public function afterClick(Entity $entity, array $options, array $hookData): void
|
||||
{
|
||||
if (!empty($options['skipWorkflow'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!empty($options['skipSignal'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!empty($options['silent'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
$uid = $hookData['uid'] ?? null;
|
||||
|
||||
if ($uid) {
|
||||
$this->signalManager->trigger(
|
||||
implode('.', ['clickUniqueUrl', $uid])
|
||||
);
|
||||
}
|
||||
|
||||
$targetType = $hookData['targetType'] ?? null;
|
||||
$targetId = $hookData['targetId'] ?? null;
|
||||
|
||||
if (!$targetType || !$targetId) {
|
||||
return;
|
||||
}
|
||||
|
||||
$target = $this->entityManager->getEntityById($targetType, $targetId);
|
||||
|
||||
if (!$target) {
|
||||
return;
|
||||
}
|
||||
|
||||
$signalManager = $this->signalManager;
|
||||
|
||||
$signalManager->trigger(implode('.', ['@clickUrl', $entity->getId()]), $target);
|
||||
$signalManager->trigger(implode('.', ['@clickUrl']), $target);
|
||||
|
||||
$signalManager->trigger(implode('.', ['clickUrl', $targetType, $targetId, $entity->getId()]));
|
||||
$signalManager->trigger(implode('.', ['clickUrl', $targetType, $targetId]));
|
||||
}
|
||||
}
|
||||
633
custom/Espo/Modules/Advanced/Hooks/Common/Signal.php
Normal file
633
custom/Espo/Modules/Advanced/Hooks/Common/Signal.php
Normal file
@@ -0,0 +1,633 @@
|
||||
<?php
|
||||
/***********************************************************************************
|
||||
* The contents of this file are subject to the Extension License Agreement
|
||||
* ("Agreement") which can be viewed at
|
||||
* https://www.espocrm.com/extension-license-agreement/.
|
||||
* By copying, installing downloading, or using this file, You have unconditionally
|
||||
* agreed to the terms and conditions of the Agreement, and You may not use this
|
||||
* file except in compliance with the Agreement. Under the terms of the Agreement,
|
||||
* You shall not license, sublicense, sell, resell, rent, lease, lend, distribute,
|
||||
* redistribute, market, publish, commercialize, or otherwise transfer rights or
|
||||
* usage to the software or any modified version or derivative work of the software
|
||||
* created by or for you.
|
||||
*
|
||||
* Copyright (C) 2015-2025 EspoCRM, Inc.
|
||||
*
|
||||
* License ID: 19bc86a68a7bb01f458cb391d43a9212
|
||||
************************************************************************************/
|
||||
|
||||
namespace Espo\Modules\Advanced\Hooks\Common;
|
||||
|
||||
use Espo\Core\ORM\Entity as CoreEntity;
|
||||
use Espo\Core\Utils\Config;
|
||||
use Espo\Core\Utils\Metadata;
|
||||
use Espo\Entities\EmailAddress;
|
||||
use Espo\Entities\LeadCapture;
|
||||
use Espo\Entities\Note;
|
||||
use Espo\Entities\Notification;
|
||||
use Espo\Entities\PhoneNumber;
|
||||
use Espo\Modules\Advanced\Core\SignalManager;
|
||||
use Espo\Modules\Crm\Entities\Meeting;
|
||||
use Espo\ORM\Entity;
|
||||
|
||||
/**
|
||||
* @noinspection PhpUnused
|
||||
*/
|
||||
class Signal
|
||||
{
|
||||
/** @var int */
|
||||
public static $order = 100;
|
||||
|
||||
/** @var string[] */
|
||||
private $ignoreEntityTypeList = [
|
||||
Notification::ENTITY_TYPE,
|
||||
EmailAddress::ENTITY_TYPE,
|
||||
PhoneNumber::ENTITY_TYPE,
|
||||
];
|
||||
|
||||
/** @var string[] */
|
||||
private $ignoreRegularEntityTypeList = [
|
||||
Note::ENTITY_TYPE,
|
||||
];
|
||||
|
||||
public function __construct(
|
||||
private Metadata $metadata,
|
||||
private Config $config,
|
||||
private SignalManager $signalManager
|
||||
) {}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $options
|
||||
*/
|
||||
public function afterSave(Entity $entity, array $options): void
|
||||
{
|
||||
if ($this->toSkipSignal($options)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($this->config->get('signalCrudHooksDisabled')) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (in_array($entity->getEntityType(), $this->ignoreEntityTypeList)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!$entity instanceof CoreEntity) {
|
||||
return;
|
||||
}
|
||||
|
||||
$ignoreRegular = in_array($entity->getEntityType(), $this->ignoreRegularEntityTypeList);
|
||||
|
||||
$signalManager = $this->signalManager;
|
||||
|
||||
if ($entity->isNew()) {
|
||||
$signalManager->trigger('@create', $entity, $options);
|
||||
|
||||
if (!$ignoreRegular) {
|
||||
$signalManager->trigger(['create', $entity->getEntityType()]);
|
||||
}
|
||||
|
||||
if (
|
||||
$entity->getEntityType() === Note::ENTITY_TYPE &&
|
||||
$entity->get('type') === Note::TYPE_POST
|
||||
) {
|
||||
$parentId = $entity->get('parentId');
|
||||
$parentType = $entity->get('parentType');
|
||||
|
||||
if ($parentType && $parentId) {
|
||||
$signalManager->trigger([
|
||||
'streamPost',
|
||||
$parentType,
|
||||
$parentId
|
||||
]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$signalManager->trigger('@update', $entity, $options);
|
||||
|
||||
if (!$ignoreRegular) {
|
||||
$signalManager->trigger([
|
||||
'update',
|
||||
$entity->getEntityType(),
|
||||
$entity->getId()
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
if ($ignoreRegular) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($entity->getRelationList() as $relation) {
|
||||
$type = $entity->getRelationType($relation);
|
||||
|
||||
if ($type === Entity::BELONGS_TO_PARENT && $entity->isNew()) {
|
||||
$parentId = $entity->get($relation . 'Id');
|
||||
$parentType = $entity->get($relation . 'Type');
|
||||
|
||||
if (!$parentType || !$parentId) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!$this->metadata->get(['scopes', $parentType, 'object'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$signalManager->trigger([
|
||||
'createChild',
|
||||
$parentType,
|
||||
$parentId,
|
||||
$entity->getEntityType()
|
||||
]);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($type === Entity::BELONGS_TO) {
|
||||
$idAttribute = $relation . 'Id';
|
||||
$idValue = $entity->get($idAttribute);
|
||||
|
||||
if (!$entity->isNew()) {
|
||||
if (!$entity->isAttributeChanged($idAttribute)) {
|
||||
continue;
|
||||
}
|
||||
} else if (!$idValue) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$foreignEntityType = $entity->getRelationParam($relation, 'entity');
|
||||
$foreign = $entity->getRelationParam($relation, 'foreign');
|
||||
|
||||
if (!$foreignEntityType) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!$foreign) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (in_array($foreignEntityType, ['User', 'Team'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!$this->metadata->get(['scopes', $foreignEntityType, 'object'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($entity->isNew()) {
|
||||
$signalManager->trigger([
|
||||
'createRelated',
|
||||
$foreignEntityType,
|
||||
$idValue,
|
||||
$foreign
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $options
|
||||
*/
|
||||
public function afterRemove(Entity $entity, array $options): void
|
||||
{
|
||||
if ($this->toSkipSignal($options)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($this->config->get('signalCrudHooksDisabled')) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (in_array($entity->getEntityType(), $this->ignoreEntityTypeList)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$ignoreRegular = in_array($entity->getEntityType(), $this->ignoreRegularEntityTypeList);
|
||||
|
||||
$signalManager = $this->signalManager;
|
||||
|
||||
$signalManager->trigger('@delete', $entity, $options);
|
||||
|
||||
if (!$ignoreRegular) {
|
||||
$signalManager->trigger([
|
||||
'delete',
|
||||
$entity->getEntityType(),
|
||||
$entity->getId()
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $options
|
||||
* @param array<string, mixed> $hookData
|
||||
*/
|
||||
public function afterRelate(Entity $entity, array $options, array $hookData): void
|
||||
{
|
||||
if ($this->toSkipSignal($options)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($this->config->get('signalCrudHooksDisabled')) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (in_array($entity->getEntityType(), $this->ignoreEntityTypeList)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!$entity instanceof CoreEntity) {
|
||||
return;
|
||||
}
|
||||
|
||||
$ignoreRegular = in_array($entity->getEntityType(), $this->ignoreRegularEntityTypeList);
|
||||
|
||||
if ($entity->isNew()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$signalManager = $this->signalManager;
|
||||
|
||||
$foreign = $hookData['foreignEntity'] ?? null;
|
||||
$link = $hookData['relationName'] ?? null;
|
||||
|
||||
if (!$foreign || !$link) {
|
||||
return;
|
||||
}
|
||||
|
||||
$foreignId = $foreign->getId();
|
||||
|
||||
$relationType = $entity->getRelationParam($link, 'type');
|
||||
|
||||
if ($relationType !== Entity::MANY_MANY) {
|
||||
$ignoreRegular = true;
|
||||
}
|
||||
|
||||
$signalManager->trigger(['@relate', $link, $foreignId], $entity, $options);
|
||||
$signalManager->trigger(['@relate', $link], $entity, $options, ['id' => $foreignId]);
|
||||
|
||||
if (!$ignoreRegular) {
|
||||
$signalManager->trigger([
|
||||
'relate',
|
||||
$entity->getEntityType(),
|
||||
$entity->getId(),
|
||||
$link,
|
||||
$foreignId
|
||||
]);
|
||||
|
||||
$signalManager->trigger([
|
||||
'relate',
|
||||
$entity->getEntityType(),
|
||||
$entity->getId(),
|
||||
$link
|
||||
]);
|
||||
}
|
||||
|
||||
$foreignLink = $entity->getRelationParam($link, 'foreign');
|
||||
|
||||
if (!$foreignLink) {
|
||||
return;
|
||||
}
|
||||
|
||||
$signalManager->trigger(['@relate', $foreignLink, $entity->getId()], $foreign);
|
||||
$signalManager->trigger(['@relate', $foreignLink], $foreign, [], ['id' => $entity->getId()]);
|
||||
|
||||
if ($ignoreRegular) {
|
||||
return;
|
||||
}
|
||||
|
||||
$signalManager->trigger([
|
||||
'relate',
|
||||
$foreign->getEntityType(),
|
||||
$foreign->getId(),
|
||||
$foreignLink,
|
||||
$entity->getId()
|
||||
]);
|
||||
|
||||
$signalManager->trigger([
|
||||
'relate',
|
||||
$foreign->getEntityType(),
|
||||
$foreign->getId(),
|
||||
$foreignLink
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $options
|
||||
* @param array<string, mixed> $hookData
|
||||
*/
|
||||
public function afterUnrelate(Entity $entity, array $options, array $hookData): void
|
||||
{
|
||||
if ($this->toSkipSignal($options)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($this->config->get('signalCrudHooksDisabled')) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (in_array($entity->getEntityType(), $this->ignoreEntityTypeList)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!$entity instanceof CoreEntity) {
|
||||
return;
|
||||
}
|
||||
|
||||
$ignoreRegular = in_array($entity->getEntityType(), $this->ignoreRegularEntityTypeList);
|
||||
|
||||
if ($entity->isNew()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$signalManager = $this->signalManager;
|
||||
|
||||
$foreign = $hookData['foreignEntity'] ?? null;
|
||||
$link = $hookData['relationName'] ?? null;
|
||||
|
||||
if (!$foreign || !$link) {
|
||||
return;
|
||||
}
|
||||
|
||||
$foreignId = $foreign->getId();
|
||||
|
||||
$relationType = $entity->getRelationParam($link, 'type');
|
||||
|
||||
if ($relationType !== Entity::MANY_MANY) {
|
||||
$ignoreRegular = true;
|
||||
}
|
||||
|
||||
$signalManager->trigger(['@unrelate', $link, $foreignId], $entity, $options);
|
||||
$signalManager->trigger(['@unrelate', $link], $entity, $options, ['id' => $foreignId]);
|
||||
|
||||
if (!$ignoreRegular) {
|
||||
$signalManager->trigger([
|
||||
'unrelate',
|
||||
$entity->getEntityType(),
|
||||
$entity->getId(),
|
||||
$link,
|
||||
$foreignId
|
||||
]);
|
||||
|
||||
$signalManager->trigger([
|
||||
'unrelate',
|
||||
$entity->getEntityType(),
|
||||
$entity->getId(),
|
||||
$link
|
||||
]);
|
||||
}
|
||||
|
||||
$foreignLink = $entity->getRelationParam($link, 'foreign');
|
||||
|
||||
if (!$foreignLink) {
|
||||
return;
|
||||
}
|
||||
|
||||
$signalManager->trigger(['@unrelate', $foreignLink, $entity->getId()], $foreign);
|
||||
$signalManager->trigger(['@unrelate', $foreignLink], $foreign, [], ['id' => $entity->getId()]);
|
||||
|
||||
$signalManager->trigger([
|
||||
'unrelate',
|
||||
$foreign->getEntityType(),
|
||||
$foreign->getId(),
|
||||
$foreignLink,
|
||||
$entity->getId()
|
||||
]);
|
||||
|
||||
$signalManager->trigger([
|
||||
'unrelate',
|
||||
$foreign->getEntityType(),
|
||||
$foreign->getId(),
|
||||
$foreignLink
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $options
|
||||
* @param array<string, mixed> $hookData
|
||||
* @noinspection PhpUnused
|
||||
*/
|
||||
public function afterMassRelate(Entity $entity, array $options, array $hookData): void
|
||||
{
|
||||
if ($this->toSkipSignal($options)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($this->config->get('signalCrudHooksDisabled')) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (in_array($entity->getEntityType(), $this->ignoreEntityTypeList)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$link = $hookData['relationName'] ?? null;
|
||||
|
||||
if (!$link) {
|
||||
return;
|
||||
}
|
||||
|
||||
$signalManager = $this->signalManager;
|
||||
|
||||
$signalManager->trigger(['@relate', $link], $entity, $options);
|
||||
|
||||
$signalManager->trigger([
|
||||
'relate',
|
||||
$entity->getEntityType(),
|
||||
$entity->getId(),
|
||||
$link
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $options
|
||||
* @param array<string, mixed> $hookData
|
||||
* @noinspection PhpUnused
|
||||
*/
|
||||
public function afterLeadCapture(Entity $entity, array $options, array $hookData): void
|
||||
{
|
||||
if ($this->toSkipSignal($options)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($entity->getEntityType() === LeadCapture::ENTITY_TYPE) {
|
||||
return;
|
||||
}
|
||||
|
||||
$id = $hookData['leadCaptureId'];
|
||||
|
||||
$signalManager = $this->signalManager;
|
||||
|
||||
$signalManager->trigger(['@leadCapture', $id], $entity);
|
||||
$signalManager->trigger(['@leadCapture'], $entity);
|
||||
|
||||
$signalManager->trigger([
|
||||
'leadCapture',
|
||||
$entity->getEntityType(),
|
||||
$entity->getId(),
|
||||
$id
|
||||
]);
|
||||
|
||||
$signalManager->trigger([
|
||||
'leadCapture',
|
||||
$entity->getEntityType(),
|
||||
$entity->getId()
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $options
|
||||
* @param array<string, mixed> $hookData
|
||||
* @noinspection PhpUnused
|
||||
*/
|
||||
public function afterConfirmation(Entity $entity, array $options, array $hookData): void
|
||||
{
|
||||
if ($this->toSkipSignal($options)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$eventEntityType = $entity->getEntityType();
|
||||
$eventId = $entity->getId();
|
||||
$status = $hookData['status'];
|
||||
$entityType = $hookData['inviteeType'];
|
||||
$id = $hookData['inviteeId'];
|
||||
|
||||
$signalManager = $this->signalManager;
|
||||
|
||||
if ($status === Meeting::ATTENDEE_STATUS_ACCEPTED) {
|
||||
$signalManager->trigger(['@eventAccepted', $entityType], $entity, [], ['id' => $id]);
|
||||
|
||||
$signalManager->trigger([
|
||||
'eventAccepted',
|
||||
$entityType,
|
||||
$id,
|
||||
$eventEntityType,
|
||||
$eventId
|
||||
]);
|
||||
|
||||
$signalManager->trigger([
|
||||
'eventAccepted',
|
||||
$entityType,
|
||||
$id,
|
||||
$eventEntityType
|
||||
]);
|
||||
}
|
||||
|
||||
if ($status === Meeting::ATTENDEE_STATUS_TENTATIVE) {
|
||||
$signalManager->trigger(['@eventTentative', $entityType], $entity, [], ['id' => $id]);
|
||||
|
||||
$signalManager->trigger([
|
||||
'eventTentative',
|
||||
$entityType,
|
||||
$id,
|
||||
$eventEntityType,
|
||||
$eventId
|
||||
]);
|
||||
|
||||
$signalManager->trigger([
|
||||
'eventTentative',
|
||||
$entityType,
|
||||
$id,
|
||||
$eventEntityType
|
||||
]);
|
||||
}
|
||||
|
||||
if ($status === Meeting::ATTENDEE_STATUS_DECLINED) {
|
||||
$signalManager->trigger(['@eventDeclined', $entityType], $entity, [], ['id' => $id]);
|
||||
|
||||
$signalManager->trigger([
|
||||
'eventDeclined',
|
||||
$entityType,
|
||||
$id,
|
||||
$eventEntityType,
|
||||
$eventId
|
||||
]);
|
||||
|
||||
$signalManager->trigger([
|
||||
'eventDeclined',
|
||||
$entityType,
|
||||
$id,
|
||||
$eventEntityType
|
||||
]);
|
||||
}
|
||||
|
||||
if (
|
||||
$status === Meeting::ATTENDEE_STATUS_ACCEPTED ||
|
||||
$status === Meeting::ATTENDEE_STATUS_TENTATIVE
|
||||
) {
|
||||
$signalManager->trigger(['@eventAcceptedTentative', $entityType], $entity, [], ['id' => $id]);
|
||||
|
||||
$signalManager->trigger([
|
||||
'eventAcceptedTentative',
|
||||
$entityType,
|
||||
$id,
|
||||
$eventEntityType,
|
||||
$eventId
|
||||
]);
|
||||
|
||||
$signalManager->trigger([
|
||||
'eventAcceptedTentative',
|
||||
$entityType,
|
||||
$id,
|
||||
$eventEntityType
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $options
|
||||
* @param array<string, mixed> $hookData
|
||||
* @noinspection PhpUnused
|
||||
* @noinspection PhpUnusedParameterInspection
|
||||
*/
|
||||
public function afterOptOut(Entity $entity, array $options, array $hookData): void
|
||||
{
|
||||
if ($this->toSkipSignal($options)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$signalManager = $this->signalManager;
|
||||
|
||||
$signalManager->trigger(['@optOut'], $entity);
|
||||
|
||||
$signalManager->trigger([
|
||||
'optOut',
|
||||
$entity->getEntityType(),
|
||||
$entity->getId()
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $options
|
||||
* @param array<string, mixed> $hookData
|
||||
* @noinspection PhpUnused
|
||||
* @noinspection PhpUnusedParameterInspection
|
||||
*/
|
||||
public function afterCancelOptOut(Entity $entity, array $options, array $hookData): void
|
||||
{
|
||||
if ($this->toSkipSignal($options)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$signalManager = $this->signalManager;
|
||||
|
||||
$signalManager->trigger(['@cancelOptOut'], $entity);
|
||||
|
||||
$signalManager->trigger([
|
||||
'cancelOptOut',
|
||||
$entity->getEntityType(),
|
||||
$entity->getId()
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $options
|
||||
*/
|
||||
private function toSkipSignal(array $options): bool
|
||||
{
|
||||
return !empty($options['skipWorkflow']) ||
|
||||
!empty($options['skipSignal']) ||
|
||||
!empty($options['silent']);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
<?php
|
||||
/***********************************************************************************
|
||||
* The contents of this file are subject to the Extension License Agreement
|
||||
* ("Agreement") which can be viewed at
|
||||
* https://www.espocrm.com/extension-license-agreement/.
|
||||
* By copying, installing downloading, or using this file, You have unconditionally
|
||||
* agreed to the terms and conditions of the Agreement, and You may not use this
|
||||
* file except in compliance with the Agreement. Under the terms of the Agreement,
|
||||
* You shall not license, sublicense, sell, resell, rent, lease, lend, distribute,
|
||||
* redistribute, market, publish, commercialize, or otherwise transfer rights or
|
||||
* usage to the software or any modified version or derivative work of the software
|
||||
* created by or for you.
|
||||
*
|
||||
* Copyright (C) 2015-2025 EspoCRM, Inc.
|
||||
*
|
||||
* License ID: 19bc86a68a7bb01f458cb391d43a9212
|
||||
************************************************************************************/
|
||||
|
||||
namespace Espo\Modules\Advanced\Hooks\Common;
|
||||
|
||||
use Espo\Core\Utils\Metadata;
|
||||
use Espo\Modules\Advanced\Entities\BpmnFlowNode;
|
||||
use Espo\ORM\Entity;
|
||||
use Espo\ORM\EntityManager;
|
||||
|
||||
class UpdateDeferredFlowNodes
|
||||
{
|
||||
/** @var int */
|
||||
private const LIMIT = 10;
|
||||
|
||||
public function __construct(
|
||||
private EntityManager $entityManager,
|
||||
private Metadata $metadata
|
||||
) {}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $options
|
||||
*/
|
||||
public function afterSave(Entity $entity, array $options): void
|
||||
{
|
||||
// To skip if updated from a BPM process.
|
||||
if (!empty($options['skipWorkflow'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!empty($options['workflowId'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!empty($options['silent'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
$entityType = $entity->getEntityType();
|
||||
|
||||
if (!$this->metadata->get(['scopes', $entityType, 'object'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
$nodeList = $this->entityManager
|
||||
->getRDBRepository(BpmnFlowNode::ENTITY_TYPE)
|
||||
->where([
|
||||
'targetId' => $entity->getId(),
|
||||
'targetType' => $entityType,
|
||||
'status' => [
|
||||
BpmnFlowNode::STATUS_PENDING,
|
||||
BpmnFlowNode::STATUS_STANDBY,
|
||||
],
|
||||
'isDeferred' => true,
|
||||
])
|
||||
->limit(0, self::LIMIT)
|
||||
->find();
|
||||
|
||||
foreach ($nodeList as $node) {
|
||||
$node->set('isDeferred', false);
|
||||
|
||||
$this->entityManager->saveEntity($node, [
|
||||
'silent' => true,
|
||||
'skipAll' => true,
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
55
custom/Espo/Modules/Advanced/Hooks/Common/Workflow.php
Normal file
55
custom/Espo/Modules/Advanced/Hooks/Common/Workflow.php
Normal file
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
/***********************************************************************************
|
||||
* The contents of this file are subject to the Extension License Agreement
|
||||
* ("Agreement") which can be viewed at
|
||||
* https://www.espocrm.com/extension-license-agreement/.
|
||||
* By copying, installing downloading, or using this file, You have unconditionally
|
||||
* agreed to the terms and conditions of the Agreement, and You may not use this
|
||||
* file except in compliance with the Agreement. Under the terms of the Agreement,
|
||||
* You shall not license, sublicense, sell, resell, rent, lease, lend, distribute,
|
||||
* redistribute, market, publish, commercialize, or otherwise transfer rights or
|
||||
* usage to the software or any modified version or derivative work of the software
|
||||
* created by or for you.
|
||||
*
|
||||
* Copyright (C) 2015-2025 EspoCRM, Inc.
|
||||
*
|
||||
* License ID: 19bc86a68a7bb01f458cb391d43a9212
|
||||
************************************************************************************/
|
||||
|
||||
namespace Espo\Modules\Advanced\Hooks\Common;
|
||||
|
||||
use Espo\Core\Formula\Exceptions\Error;
|
||||
use Espo\Modules\Advanced\Core\WorkflowManager;
|
||||
use Espo\ORM\Entity;
|
||||
|
||||
class Workflow
|
||||
{
|
||||
/** @var int */
|
||||
public static $order = 99;
|
||||
|
||||
public function __construct(private WorkflowManager $workflowManager) {}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $options
|
||||
* @throws Error
|
||||
* @throws \Espo\Core\Exceptions\Error
|
||||
*/
|
||||
public function afterSave(Entity $entity, array $options): void
|
||||
{
|
||||
if (!empty($options['skipWorkflow'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!empty($options['silent'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($entity->isNew()) {
|
||||
$this->workflowManager->process($entity, WorkflowManager::AFTER_RECORD_CREATED, $options);
|
||||
} else {
|
||||
$this->workflowManager->process($entity, WorkflowManager::AFTER_RECORD_UPDATED, $options);
|
||||
}
|
||||
|
||||
$this->workflowManager->process($entity, WorkflowManager::AFTER_RECORD_SAVED, $options);
|
||||
}
|
||||
}
|
||||
110
custom/Espo/Modules/Advanced/Hooks/Report/Prepare.php
Normal file
110
custom/Espo/Modules/Advanced/Hooks/Report/Prepare.php
Normal file
@@ -0,0 +1,110 @@
|
||||
<?php
|
||||
/***********************************************************************************
|
||||
* The contents of this file are subject to the Extension License Agreement
|
||||
* ("Agreement") which can be viewed at
|
||||
* https://www.espocrm.com/extension-license-agreement/.
|
||||
* By copying, installing downloading, or using this file, You have unconditionally
|
||||
* agreed to the terms and conditions of the Agreement, and You may not use this
|
||||
* file except in compliance with the Agreement. Under the terms of the Agreement,
|
||||
* You shall not license, sublicense, sell, resell, rent, lease, lend, distribute,
|
||||
* redistribute, market, publish, commercialize, or otherwise transfer rights or
|
||||
* usage to the software or any modified version or derivative work of the software
|
||||
* created by or for you.
|
||||
*
|
||||
* Copyright (C) 2015-2025 EspoCRM, Inc.
|
||||
*
|
||||
* License ID: 19bc86a68a7bb01f458cb391d43a9212
|
||||
************************************************************************************/
|
||||
|
||||
namespace Espo\Modules\Advanced\Hooks\Report;
|
||||
|
||||
use Espo\Modules\Advanced\Entities\Report;
|
||||
use Espo\Modules\Advanced\Entities\Report as ReportEntity;
|
||||
use Espo\ORM\Entity;
|
||||
|
||||
class Prepare
|
||||
{
|
||||
/**
|
||||
* @param Report $entity
|
||||
*/
|
||||
public function beforeSave(Entity $entity): void
|
||||
{
|
||||
if (
|
||||
$entity->isAttributeChanged('emailSendingInterval') ||
|
||||
$entity->isAttributeChanged('emailSendingTime') ||
|
||||
$entity->isAttributeChanged('emailSendingSettingWeekdays') ||
|
||||
$entity->isAttributeChanged('emailSendingSettingDay')
|
||||
) {
|
||||
/** @noinspection PhpRedundantOptionalArgumentInspection */
|
||||
$entity->set('emailSendingLastDateSent', null);
|
||||
}
|
||||
|
||||
if (
|
||||
$entity->get('type') === ReportEntity::TYPE_GRID &&
|
||||
($entity->has('chartOneColumns') || $entity->has('chartOneY2Columns'))
|
||||
) {
|
||||
$this->handleChartDataList($entity);
|
||||
}
|
||||
}
|
||||
|
||||
private function handleChartDataList(Report $entity): void
|
||||
{
|
||||
$groupBy = $entity->getGroupBy();
|
||||
|
||||
if (count($groupBy) > 1) {
|
||||
/** @noinspection PhpRedundantOptionalArgumentInspection */
|
||||
$entity->set('chartDataList', null);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$chartDataList = $entity->get('chartDataList');
|
||||
|
||||
$y = null;
|
||||
$y2 = null;
|
||||
|
||||
if ($chartDataList && count($chartDataList) !== 0) {
|
||||
$y = $chartDataList[0]->columnList ?? null;
|
||||
$y2 = $chartDataList[0]->y2ColumnList ?? null;
|
||||
}
|
||||
|
||||
$newY = $y ?? null;
|
||||
$newY2 = $y2 ?? null;
|
||||
|
||||
if ($entity->has('chartOneColumns')) {
|
||||
$newY = $entity->get('chartOneColumns') ?? [];
|
||||
|
||||
if ($newY && count($newY) === 0) {
|
||||
$newY = null;
|
||||
}
|
||||
}
|
||||
|
||||
if ($entity->has('chartOneY2Columns')) {
|
||||
$newY2 = $entity->get('chartOneY2Columns') ?? [];
|
||||
|
||||
if ($newY2 && count($newY2) === 0) {
|
||||
$newY2 = null;
|
||||
}
|
||||
}
|
||||
|
||||
$chartType = $entity->get('chartType');
|
||||
|
||||
if (!in_array($chartType, ['BarVertical', 'BarHorizontal', 'Line'])) {
|
||||
$newY2 = null;
|
||||
}
|
||||
|
||||
if ($newY || $newY2) {
|
||||
$newItem = (object) [
|
||||
'columnList' => $newY,
|
||||
'y2ColumnList' => $newY2,
|
||||
];
|
||||
|
||||
$entity->set('chartDataList', [$newItem]);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/** @noinspection PhpRedundantOptionalArgumentInspection */
|
||||
$entity->set('chartDataList', null);
|
||||
}
|
||||
}
|
||||
98
custom/Espo/Modules/Advanced/Hooks/TargetList/Signal.php
Normal file
98
custom/Espo/Modules/Advanced/Hooks/TargetList/Signal.php
Normal file
@@ -0,0 +1,98 @@
|
||||
<?php
|
||||
/***********************************************************************************
|
||||
* The contents of this file are subject to the Extension License Agreement
|
||||
* ("Agreement") which can be viewed at
|
||||
* https://www.espocrm.com/extension-license-agreement/.
|
||||
* By copying, installing downloading, or using this file, You have unconditionally
|
||||
* agreed to the terms and conditions of the Agreement, and You may not use this
|
||||
* file except in compliance with the Agreement. Under the terms of the Agreement,
|
||||
* You shall not license, sublicense, sell, resell, rent, lease, lend, distribute,
|
||||
* redistribute, market, publish, commercialize, or otherwise transfer rights or
|
||||
* usage to the software or any modified version or derivative work of the software
|
||||
* created by or for you.
|
||||
*
|
||||
* Copyright (C) 2015-2025 EspoCRM, Inc.
|
||||
*
|
||||
* License ID: 19bc86a68a7bb01f458cb391d43a9212
|
||||
************************************************************************************/
|
||||
|
||||
namespace Espo\Modules\Advanced\Hooks\TargetList;
|
||||
|
||||
use Espo\Modules\Advanced\Core\SignalManager;
|
||||
use Espo\ORM\Entity;
|
||||
use Espo\ORM\EntityManager;
|
||||
|
||||
class Signal
|
||||
{
|
||||
/** @var int */
|
||||
public static $order = 100;
|
||||
|
||||
public function __construct(
|
||||
private SignalManager $signalManager,
|
||||
private EntityManager $entityManager
|
||||
) {}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $options
|
||||
* @param array<string, mixed> $hookData
|
||||
*/
|
||||
public function afterOptOut(Entity $entity, array $options, array $hookData): void
|
||||
{
|
||||
if (!empty($options['skipWorkflow'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!empty($options['skipSignal'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!empty($options['silent'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
$targetType = $hookData['targetType'];
|
||||
$targetId = $hookData['targetId'];
|
||||
|
||||
$target = $this->entityManager->getEntityById($targetType, $targetId);
|
||||
|
||||
if (!$target) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->signalManager->trigger(implode('.', ['@optOut', $entity->getId()]), $target);
|
||||
$this->signalManager->trigger(
|
||||
implode('.', ['optOut', $target->getEntityType(), $target->getId(), $entity->getId()]));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $options
|
||||
* @param array<string, mixed> $hookData
|
||||
*/
|
||||
public function afterCancelOptOut(Entity $entity, array $options, array $hookData): void
|
||||
{
|
||||
if (!empty($options['skipWorkflow'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!empty($options['skipSignal'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!empty($options['silent'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
$targetType = $hookData['targetType'];
|
||||
$targetId = $hookData['targetId'];
|
||||
|
||||
$target = $this->entityManager->getEntityById($targetType, $targetId);
|
||||
|
||||
if (!$target) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->signalManager->trigger(implode('.', ['@cancelOptOut', $entity->getId()]), $target);
|
||||
$this->signalManager->trigger(
|
||||
implode('.', ['cancelOptOut', $target->getEntityType(), $target->getId(), $entity->getId()]));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
/***********************************************************************************
|
||||
* The contents of this file are subject to the Extension License Agreement
|
||||
* ("Agreement") which can be viewed at
|
||||
* https://www.espocrm.com/extension-license-agreement/.
|
||||
* By copying, installing downloading, or using this file, You have unconditionally
|
||||
* agreed to the terms and conditions of the Agreement, and You may not use this
|
||||
* file except in compliance with the Agreement. Under the terms of the Agreement,
|
||||
* You shall not license, sublicense, sell, resell, rent, lease, lend, distribute,
|
||||
* redistribute, market, publish, commercialize, or otherwise transfer rights or
|
||||
* usage to the software or any modified version or derivative work of the software
|
||||
* created by or for you.
|
||||
*
|
||||
* Copyright (C) 2015-2025 EspoCRM, Inc.
|
||||
*
|
||||
* License ID: 19bc86a68a7bb01f458cb391d43a9212
|
||||
************************************************************************************/
|
||||
|
||||
namespace Espo\Modules\Advanced\Hooks\Workflow;
|
||||
|
||||
use Espo\Modules\Advanced\Core\WorkflowManager;
|
||||
use Espo\ORM\Entity;
|
||||
|
||||
class ReloadWorkflows
|
||||
{
|
||||
/** @var int */
|
||||
public static $order = 9;
|
||||
|
||||
public function __construct(private WorkflowManager $workflowManager)
|
||||
{}
|
||||
|
||||
public function afterSave(Entity $entity): void
|
||||
{
|
||||
$this->workflowManager->loadWorkflows(true);
|
||||
}
|
||||
|
||||
public function afterRemove(Entity $entity): void
|
||||
{
|
||||
$this->workflowManager->loadWorkflows(true);
|
||||
}
|
||||
}
|
||||
65
custom/Espo/Modules/Advanced/Hooks/Workflow/RemoveJobs.php
Normal file
65
custom/Espo/Modules/Advanced/Hooks/Workflow/RemoveJobs.php
Normal file
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
/***********************************************************************************
|
||||
* The contents of this file are subject to the Extension License Agreement
|
||||
* ("Agreement") which can be viewed at
|
||||
* https://www.espocrm.com/extension-license-agreement/.
|
||||
* By copying, installing downloading, or using this file, You have unconditionally
|
||||
* agreed to the terms and conditions of the Agreement, and You may not use this
|
||||
* file except in compliance with the Agreement. Under the terms of the Agreement,
|
||||
* You shall not license, sublicense, sell, resell, rent, lease, lend, distribute,
|
||||
* redistribute, market, publish, commercialize, or otherwise transfer rights or
|
||||
* usage to the software or any modified version or derivative work of the software
|
||||
* created by or for you.
|
||||
*
|
||||
* Copyright (C) 2015-2025 EspoCRM, Inc.
|
||||
*
|
||||
* License ID: 19bc86a68a7bb01f458cb391d43a9212
|
||||
************************************************************************************/
|
||||
|
||||
namespace Espo\Modules\Advanced\Hooks\Workflow;
|
||||
|
||||
use Espo\Entities\Job;
|
||||
use Espo\Modules\Advanced\Entities\Workflow;
|
||||
use Espo\Modules\Advanced\Tools\Workflow\Jobs\RunScheduledWorkflow as RunScheduledWorkflowJob;
|
||||
use Espo\ORM\Entity;
|
||||
use Espo\ORM\EntityManager;
|
||||
|
||||
class RemoveJobs
|
||||
{
|
||||
private EntityManager $entityManager;
|
||||
|
||||
public function __construct(EntityManager $entityManager)
|
||||
{
|
||||
$this->entityManager = $entityManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Workflow $entity
|
||||
*/
|
||||
public function afterSave(Entity $entity): void
|
||||
{
|
||||
$toRemove = $entity->getType() === Workflow::TYPE_SCHEDULED &&
|
||||
(
|
||||
$entity->isAttributeChanged('scheduling') ||
|
||||
$entity->isAttributeChanged('schedulingApplyTimezone')
|
||||
);
|
||||
|
||||
if (!$toRemove) {
|
||||
return;
|
||||
}
|
||||
|
||||
$pendingJobList = $this->entityManager
|
||||
->getRDBRepository(Job::ENTITY_TYPE)
|
||||
->where([
|
||||
'className' => RunScheduledWorkflowJob::class,
|
||||
'status' => 'Pending',
|
||||
'targetType' => Workflow::ENTITY_TYPE,
|
||||
'targetId' => $entity->getId(),
|
||||
])
|
||||
->find();
|
||||
|
||||
foreach ($pendingJobList as $pendingJob) {
|
||||
$this->entityManager->removeEntity($pendingJob);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
/***********************************************************************************
|
||||
* The contents of this file are subject to the Extension License Agreement
|
||||
* ("Agreement") which can be viewed at
|
||||
* https://www.espocrm.com/extension-license-agreement/.
|
||||
* By copying, installing downloading, or using this file, You have unconditionally
|
||||
* agreed to the terms and conditions of the Agreement, and You may not use this
|
||||
* file except in compliance with the Agreement. Under the terms of the Agreement,
|
||||
* You shall not license, sublicense, sell, resell, rent, lease, lend, distribute,
|
||||
* redistribute, market, publish, commercialize, or otherwise transfer rights or
|
||||
* usage to the software or any modified version or derivative work of the software
|
||||
* created by or for you.
|
||||
*
|
||||
* Copyright (C) 2015-2025 EspoCRM, Inc.
|
||||
*
|
||||
* License ID: 19bc86a68a7bb01f458cb391d43a9212
|
||||
************************************************************************************/
|
||||
|
||||
namespace Espo\Modules\Advanced\Hooks\Workflow;
|
||||
|
||||
use Espo\Modules\Advanced\Entities\WorkflowRoundRobin;
|
||||
use Espo\ORM\Entity;
|
||||
use Espo\ORM\EntityManager;
|
||||
|
||||
class RemoveRoundRobin
|
||||
{
|
||||
/** @var int */
|
||||
public static $order = 9;
|
||||
|
||||
public function __construct(private EntityManager $entityManager)
|
||||
{}
|
||||
|
||||
public function afterRemove(Entity $entity): void
|
||||
{
|
||||
$roundRobinList = $this->entityManager
|
||||
->getRDBRepository(WorkflowRoundRobin::ENTITY_TYPE)
|
||||
->where(['workflowId' => $entity->getId()])
|
||||
->find();
|
||||
|
||||
foreach ($roundRobinList as $item) {
|
||||
$this->entityManager->removeEntity($item);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user