%PDF- %PDF-
| Direktori : /proc/self/root/home/bitrix/www/bitrix/modules/bizproc/classes/general/ |
| Current File : //proc/self/root/home/bitrix/www/bitrix/modules/bizproc/classes/general/activity.php |
<?
IncludeModuleLangFile(__FILE__);
abstract class CBPActivity
{
public $parent = null;
public $executionStatus = CBPActivityExecutionStatus::Initialized;
public $executionResult = CBPActivityExecutionResult::None;
private $arStatusChangeHandlers = array();
const StatusChangedEvent = 0;
const ExecutingEvent = 1;
const CancelingEvent = 2;
const ClosedEvent = 3;
const FaultingEvent = 4;
const ValuePattern = '#^\s*\{=\s*(?<object>[a-z0-9_]+)\s*\:\s*(?<field>[a-z0-9_\.]+)(\s*>\s*(?<mod1>[a-z0-9_\:]+)(\s*,\s*(?<mod2>[a-z0-9_]+))?)?\s*\}\s*$#i';
const ValueInlinePattern = '#\{=\s*(?<object>[a-z0-9_]+)\s*\:\s*(?<field>[a-z0-9_\.]+)(\s*>\s*(?<mod1>[a-z0-9_\:]+)(\s*,\s*(?<mod2>[a-z0-9_]+))?)?\s*\}#i';
/** Internal pattern used in calc.php */
const ValueInternalPattern = '\{=\s*([a-z0-9_]+)\s*\:\s*([a-z0-9_\.]+)(\s*>\s*([a-z0-9_\:]+)(\s*,\s*([a-z0-9_]+))?)?\s*\}';
const CalcPattern = '#^\s*(=\s*(.*)|\{\{=\s*(.*)\s*\}\})\s*$#is';
const CalcInlinePattern = '#\{\{=\s*(.*?)\s*\}\}([^\}]|$)#is';
protected $arProperties = array();
protected $arPropertiesTypes = array();
protected $name = "";
/** @var CBPWorkflow $workflow */
public $workflow = null;
public $arEventsMap = array();
/************************ PROPERTIES ************************************************/
public function GetDocumentId()
{
$rootActivity = $this->GetRootActivity();
return $rootActivity->GetDocumentId();
}
public function SetDocumentId($documentId)
{
$rootActivity = $this->GetRootActivity();
$rootActivity->SetDocumentId($documentId);
}
public function GetDocumentType()
{
$rootActivity = $this->GetRootActivity();
if (!is_array($rootActivity->documentType) || count($rootActivity->documentType) <= 0)
{
/** @var CBPDocumentService $documentService */
$documentService = $this->workflow->GetService("DocumentService");
$rootActivity->documentType = $documentService->GetDocumentType($rootActivity->documentId);
}
return $rootActivity->documentType;
}
public function SetDocumentType($documentType)
{
$rootActivity = $this->GetRootActivity();
$rootActivity->documentType = $documentType;
}
public function getDocumentEventType()
{
$rootActivity = $this->GetRootActivity();
return (int)$rootActivity->getRawProperty(CBPDocument::PARAM_DOCUMENT_EVENT_TYPE);
}
public function GetWorkflowStatus()
{
$rootActivity = $this->GetRootActivity();
return $rootActivity->GetWorkflowStatus();
}
public function SetWorkflowStatus($status)
{
$rootActivity = $this->GetRootActivity();
$rootActivity->SetWorkflowStatus($status);
}
public function SetFieldTypes($arFieldTypes = array())
{
if (count($arFieldTypes) > 0)
{
$rootActivity = $this->GetRootActivity();
foreach ($arFieldTypes as $key => $value)
$rootActivity->arFieldTypes[$key] = $value;
}
}
public function GetWorkflowTemplateId()
{
$rootActivity = $this->GetRootActivity();
//prevent recursion by checking setter
if (method_exists($rootActivity, 'SetWorkflowTemplateId'))
{
return $rootActivity->GetWorkflowTemplateId();
}
return 0;
}
/**********************************************************/
protected function ClearProperties()
{
$rootActivity = $this->GetRootActivity();
$documentId = $rootActivity->GetDocumentId();
$documentType = $this->GetDocumentType();
/** @var CBPDocumentService $documentService */
$documentService = $this->workflow->GetService("DocumentService");
if (is_array($rootActivity->arPropertiesTypes) && count($rootActivity->arPropertiesTypes) > 0
&& is_array($rootActivity->arFieldTypes) && count($rootActivity->arFieldTypes) > 0)
{
foreach ($rootActivity->arPropertiesTypes as $key => $value)
{
if ($rootActivity->arFieldTypes[$value["Type"]]["BaseType"] == "file")
{
foreach ((array) $rootActivity->arProperties[$key] as $v)
{
if (intval($v) > 0)
{
$iterator = \CFile::getByID($v);
if ($file = $iterator->fetch())
{
if ($file['MODULE_ID'] === 'bizproc')
CFile::Delete($v);
}
}
}
}
$fieldType = \Bitrix\Bizproc\FieldType::normalizeProperty($value);
if ($fieldTypeObject = $documentService->getFieldTypeObject($documentType, $fieldType))
{
$fieldTypeObject->setDocumentId($documentId)
->clearValue($rootActivity->arProperties[$key]);
}
}
}
}
public function GetPropertyBaseType($propertyName)
{
$rootActivity = $this->GetRootActivity();
return $rootActivity->arFieldTypes[$rootActivity->arPropertiesTypes[$propertyName]["Type"]]["BaseType"];
}
public function getTemplatePropertyType($propertyName)
{
$rootActivity = $this->GetRootActivity();
return $rootActivity->arPropertiesTypes[$propertyName];
}
public function SetProperties($arProperties = array())
{
if (count($arProperties) > 0)
{
foreach ($arProperties as $key => $value)
$this->arProperties[$key] = $value;
}
}
public function SetPropertiesTypes($arPropertiesTypes = array())
{
if (count($arPropertiesTypes) > 0)
{
foreach ($arPropertiesTypes as $key => $value)
$this->arPropertiesTypes[$key] = $value;
}
}
/**********************************************************/
protected function ClearVariables()
{
$rootActivity = $this->GetRootActivity();
$documentId = $rootActivity->GetDocumentId();
$documentType = $this->GetDocumentType();
/** @var CBPDocumentService $documentService */
$documentService = $this->workflow->GetService("DocumentService");
if (is_array($rootActivity->arVariablesTypes) && count($rootActivity->arVariablesTypes) > 0
&& is_array($rootActivity->arFieldTypes) && count($rootActivity->arFieldTypes) > 0)
{
foreach ($rootActivity->arVariablesTypes as $key => $value)
{
if ($rootActivity->arFieldTypes[$value["Type"]]["BaseType"] == "file")
{
foreach ((array) $rootActivity->arVariables[$key] as $v)
{
if (intval($v) > 0)
{
$iterator = \CFile::getByID($v);
if ($file = $iterator->fetch())
{
if ($file['MODULE_ID'] === 'bizproc')
CFile::Delete($v);
}
}
}
}
$fieldType = \Bitrix\Bizproc\FieldType::normalizeProperty($value);
if ($fieldTypeObject = $documentService->getFieldTypeObject($documentType, $fieldType))
{
$fieldTypeObject->setDocumentId($documentId)
->clearValue($rootActivity->arVariables[$key]);
}
}
}
}
public function GetVariableBaseType($variableName)
{
$rootActivity = $this->GetRootActivity();
return $rootActivity->arFieldTypes[$rootActivity->arVariablesTypes[$variableName]["Type"]]["BaseType"];
}
public function SetVariables($arVariables = array())
{
if (count($arVariables) > 0)
{
$rootActivity = $this->GetRootActivity();
foreach ($arVariables as $key => $value)
$rootActivity->arVariables[$key] = $value;
}
}
public function SetVariablesTypes($arVariablesTypes = array())
{
if (count($arVariablesTypes) > 0)
{
$rootActivity = $this->GetRootActivity();
foreach ($arVariablesTypes as $key => $value)
$rootActivity->arVariablesTypes[$key] = $value;
}
}
public function SetVariable($name, $value)
{
$rootActivity = $this->GetRootActivity();
$rootActivity->arVariables[$name] = $value;
}
public function GetVariable($name)
{
$rootActivity = $this->GetRootActivity();
if (array_key_exists($name, $rootActivity->arVariables))
return $rootActivity->arVariables[$name];
return null;
}
public function getVariableType($name)
{
$rootActivity = $this->GetRootActivity();
return isset($rootActivity->arVariablesTypes[$name]) ? $rootActivity->arVariablesTypes[$name] : null;
}
private function GetConstantTypes()
{
$rootActivity = $this->GetRootActivity();
if (method_exists($rootActivity, 'GetWorkflowTemplateId'))
{
$templateId = $rootActivity->GetWorkflowTemplateId();
if ($templateId > 0)
{
return CBPWorkflowTemplateLoader::getTemplateConstants($templateId);
}
}
return null;
}
public function GetConstant($name)
{
$constants = $this->GetConstantTypes();
if (isset($constants[$name]['Default']))
return $constants[$name]['Default'];
return null;
}
public function GetConstantType($name)
{
$constants = $this->GetConstantTypes();
if (isset($constants[$name]))
return $constants[$name];
return array('Type' => null, 'Multiple' => false, 'Required' => false, 'Options' => null);
}
public function IsVariableExists($name)
{
$rootActivity = $this->GetRootActivity();
return array_key_exists($name, $rootActivity->arVariables);
}
/************************************************/
public function GetName()
{
return $this->name;
}
public function GetRootActivity()
{
$p = $this;
while ($p->parent != null)
$p = $p->parent;
return $p;
}
public function SetWorkflow(CBPWorkflow $workflow)
{
$this->workflow = $workflow;
}
public function GetWorkflowInstanceId()
{
return $this->workflow->GetInstanceId();
}
public function SetStatusTitle($title = '')
{
$rootActivity = $this->GetRootActivity();
$stateService = $this->workflow->GetService("StateService");
if ($rootActivity instanceof CBPStateMachineWorkflowActivity)
{
$arState = $stateService->GetWorkflowState($this->GetWorkflowInstanceId());
$arActivities = $rootActivity->CollectNestedActivities();
/** @var CBPActivity $activity */
foreach ($arActivities as $activity)
if ($activity->GetName() == $arState["STATE_NAME"])
break;
$stateService->SetStateTitle(
$this->GetWorkflowInstanceId(),
$activity->Title.($title != '' ? ": ".$title : '')
);
}
else
{
if ($title != '')
{
$stateService->SetStateTitle(
$this->GetWorkflowInstanceId(),
$title
);
}
}
}
public function AddStatusTitle($title = '')
{
if ($title == '')
return;
$stateService = $this->workflow->GetService("StateService");
$mainTitle = $stateService->GetStateTitle($this->GetWorkflowInstanceId());
$mainTitle .= ((strpos($mainTitle, ": ") !== false) ? ", " : ": ").$title;
$stateService->SetStateTitle($this->GetWorkflowInstanceId(), $mainTitle);
}
public function DeleteStatusTitle($title = '')
{
if ($title == '')
return;
$stateService = $this->workflow->GetService("StateService");
$mainTitle = $stateService->GetStateTitle($this->GetWorkflowInstanceId());
$ar1 = explode(":", $mainTitle);
if (count($ar1) <= 1)
return;
$newTitle = "";
$ar2 = explode(",", $ar1[1]);
foreach ($ar2 as $a)
{
$a = trim($a);
if ($a != $title)
{
if (strlen($newTitle) > 0)
$newTitle .= ", ";
$newTitle .= $a;
}
}
$result = $ar1[0].(strlen($newTitle) > 0 ? ": " : "").$newTitle;
$stateService->SetStateTitle($this->GetWorkflowInstanceId(), $result);
}
private function GetPropertyValueRecursive($val, $convertToType = null)
{
// array(2, 5, array("SequentialWorkflowActivity1", "DocumentApprovers"))
// array("Document", "IBLOCK_ID")
// array("Workflow", "id")
// "Hello, {=SequentialWorkflowActivity1:DocumentApprovers}, {=Document:IBLOCK_ID}!"
$parsed = $this->parseValueExpression($val);
if ($parsed)
{
$result = null;
if ($convertToType)
$parsed['modifiers'][] = $convertToType;
$this->GetRealParameterValue($parsed['object'], $parsed['field'], $result, $parsed['modifiers']);
return array(1, $result);
}
elseif (is_array($val))
{
$b = true;
$r = array();
$keys = array_keys($val);
$i = 0;
foreach ($keys as $key)
{
if ($key."!" != $i."!")
{
$b = false;
break;
}
$i++;
}
foreach ($keys as $key)
{
list($t, $a) = $this->GetPropertyValueRecursive($val[$key], $convertToType);
if ($b)
{
if ($t == 1 && is_array($a))
$r = array_merge($r, $a);
else
$r[] = $a;
}
else
{
$r[$key] = $a;
}
}
if (count($r) == 2)
{
$keys = array_keys($r);
if ($keys[0] == 0 && $keys[1] == 1 && is_string($r[0]) && is_string($r[1]))
{
$result = null;
$modifiers = $convertToType ? array($convertToType) : array();
if ($this->GetRealParameterValue($r[0], $r[1], $result, $modifiers))
return array(1, $result);
}
}
return array(2, $r);
}
else
{
if (is_string($val))
{
$typeClass = null;
$fieldTypeObject = null;
if ($convertToType)
{
/** @var CBPDocumentService $documentService */
$documentService = $this->workflow->GetService("DocumentService");
$documentType = $this->GetDocumentType();
$typesMap = $documentService->getTypesMap($documentType);
$convertToType = strtolower($convertToType);
if (isset($typesMap[$convertToType]))
{
$typeClass = $typesMap[$convertToType];
$fieldTypeObject = $documentService->getFieldTypeObject(
$documentType,
array('Type' => \Bitrix\Bizproc\FieldType::STRING)
);
}
}
$calc = new CBPCalc($this);
if (preg_match(self::CalcPattern, $val))
{
$r = $calc->Calculate($val);
if ($r !== null)
{
if ($typeClass && $fieldTypeObject)
{
if (is_array($r))
$fieldTypeObject->setMultiple(true);
$r = $fieldTypeObject->convertValue($r, $typeClass);
}
return array(is_array($r)? 1 : 2, $r);
}
}
//parse inline calculator
$val = preg_replace_callback(
static::CalcInlinePattern,
function($matches) use ($calc)
{
$r = $calc->Calculate($matches[1]);
if (is_array($r))
$r = implode(', ', CBPHelper::MakeArrayFlat($r));
return $r !== null? $r.$matches[2] : $matches[0];
},
$val
);
//parse properties
$val = preg_replace_callback(
static::ValueInlinePattern,
array($this, "ParseStringParameter"),
$val
);
//converting...
if ($typeClass && $fieldTypeObject)
{
$val = $fieldTypeObject->convertValue($val, $typeClass);
}
}
return array(2, $val);
}
}
private function GetRealParameterValue($objectName, $fieldName, &$result, array $modifiers = null)
{
$return = true;
$property = null;
if ($objectName == "Document")
{
$rootActivity = $this->GetRootActivity();
$documentId = $rootActivity->GetDocumentId();
/** @var CBPDocumentService $documentService */
$documentService = $this->workflow->GetService("DocumentService");
$documentType = $this->GetDocumentType();
$document = $documentService->GetDocument($documentId, $documentType);
$documentFields = $documentService->GetDocumentFields($documentType);
//check aliases
$documentFieldsAliasesMap = CBPDocument::getDocumentFieldsAliasesMap($documentFields);
if (!isset($document[$fieldName]) && strtoupper(substr($fieldName, -strlen('_PRINTABLE'))) == '_PRINTABLE')
{
$fieldName = substr($fieldName, 0, -strlen('_PRINTABLE'));
if (!in_array('printable', $modifiers))
$modifiers[] = 'printable';
}
if (!isset($document[$fieldName]) && isset($documentFieldsAliasesMap[$fieldName]))
{
$fieldName = $documentFieldsAliasesMap[$fieldName];
}
$result = '';
if (isset($document[$fieldName]))
{
$result = $document[$fieldName];
if (is_array($result) && strtoupper(substr($fieldName, -strlen('_PRINTABLE'))) == '_PRINTABLE')
$result = implode(", ", CBPHelper::MakeArrayFlat($result));
if (!empty($modifiers))
{
$property = isset($documentFields[$fieldName]) ? $documentFields[$fieldName] : null;
}
}
}
elseif ($objectName == 'Template' || $objectName == 'Variable' || $objectName == 'Constant')
{
$rootActivity = $this->GetRootActivity();
if (substr($fieldName, -strlen("_printable")) == "_printable")
{
$fieldName = substr($fieldName, 0, strlen($fieldName) - strlen("_printable"));
$modifiers = array('printable');
}
switch ($objectName)
{
case 'Variable':
$result = $rootActivity->GetVariable($fieldName);
$property = $rootActivity->getVariableType($fieldName);
break;
case 'Constant':
$result = $rootActivity->GetConstant($fieldName);
$property = $rootActivity->GetConstantType($fieldName);
break;
default:
$result = $rootActivity->{$fieldName};
$property = $rootActivity->getTemplatePropertyType($fieldName);
}
}
elseif ($objectName == "Workflow")
{
$result = $this->GetWorkflowInstanceId();
$property = array('Type' => 'string');
}
elseif ($objectName == "User")
{
$result = 0;
if (isset($GLOBALS["USER"]) && is_object($GLOBALS["USER"]) && $GLOBALS["USER"]->isAuthorized())
$result = "user_".$GLOBALS["USER"]->GetID();
$property = array('Type' => 'user');
}
elseif ($objectName == "System")
{
global $DB;
$result = null;
$property = array('Type' => 'datetime');
$systemField = strtolower($fieldName);
if ($systemField === 'now')
$result = date($DB->DateFormatToPHP(CSite::GetDateFormat("FULL")));
elseif ($systemField === 'nowlocal')
{
$result = time();
if (CTimeZone::Enabled())
$result += CTimeZone::GetOffset();
$result = date($DB->DateFormatToPHP(CSite::GetDateFormat("FULL")), $result);
}
elseif ($systemField == 'date')
{
$result = date($DB->DateFormatToPHP(CSite::GetDateFormat("SHORT")));
$property = array('Type' => 'date');
}
if ($result === null)
$return = false;
}
elseif ($objectName)
{
$activity = $this->workflow->GetActivityByName($objectName);
if ($activity)
{
$result = $activity->{$fieldName};
//if mapping is set, we can apply modifiers (type converting & formating like `printable`, `bool` etc.)
if (isset($activity->arPropertiesTypes[$fieldName]))
{
$property = $activity->arPropertiesTypes[$fieldName];
}
}
else
$return = false;
}
else
$return = false;
if ($return)
$result = $this->applyPropertyValueModifiers($fieldName, $property, $result, $modifiers);
return $return;
}
private function applyPropertyValueModifiers($fieldName, $property, $value, array $modifiers)
{
if (empty($property) || empty($modifiers) || !is_array($property))
return $value;
$typeName = $typeClass = $format = null;
$rootActivity = $this->GetRootActivity();
$documentId = $rootActivity->GetDocumentId();
/** @var CBPDocumentService $documentService */
$documentService = $this->workflow->GetService("DocumentService");
$documentType = $this->GetDocumentType();
$typesMap = $documentService->getTypesMap($documentType);
foreach ($modifiers as $m)
{
$m = strtolower($m);
if (isset($typesMap[$m]))
{
$typeName = $m;
$typeClass = $typesMap[$m];
}
else
{
$format = $m;
}
}
if ($typeName === \Bitrix\Bizproc\FieldType::STRING && $format === 'printable')
{
$typeClass = null;
}
if ($typeClass || $format)
{
$fieldTypeObject = $documentService->getFieldTypeObject($documentType, $property);
if ($fieldTypeObject)
{
$fieldTypeObject->setDocumentId($documentId);
if ($typeClass)
$value = $fieldTypeObject->convertValue($value, $typeClass);
if ($format)
$value = $fieldTypeObject->formatValue($value, $format);
}
elseif ($format == 'printable') // compatibility: old printable style
{
$value = $documentService->GetFieldValuePrintable(
$documentId,
$fieldName,
$property['Type'],
$value,
$property
);
if (is_array($value))
$value = implode(", ", CBPHelper::MakeArrayFlat($value));
}
}
return $value;
}
private function ParseStringParameter($matches)
{
$result = "";
$modifiers = array();
if (!empty($matches['mod1']))
$modifiers[] = $matches['mod1'];
if (!empty($matches['mod2']))
$modifiers[] = $matches['mod2'];
if (empty($modifiers))
$modifiers[] = \Bitrix\Bizproc\FieldType::STRING;
if ($this->GetRealParameterValue($matches['object'], $matches['field'], $result, $modifiers))
{
if (is_array($result))
$result = implode(", ", CBPHelper::MakeArrayFlat($result));
}
else
{
$result = $matches[0];
}
return $result;
}
/**
* @param $text
* @return array|bool
*/
private function parseValueExpression($text)
{
$matches = null;
if (is_string($text) && preg_match(static::ValuePattern, $text, $matches))
{
$result = array(
'object' => $matches['object'],
'field' => $matches['field'],
'modifiers' => array()
);
if (!empty($matches['mod1']))
$result['modifiers'][] = $matches['mod1'];
if (!empty($matches['mod2']))
$result['modifiers'][] = $matches['mod2'];
return $result;
}
return false;
}
public function ParseValue($value, $convertToType = null)
{
list($t, $r) = $this->GetPropertyValueRecursive($value, $convertToType);
return $r;
}
protected function getRawProperty($name)
{
if (isset($this->arProperties[$name]))
{
return $this->arProperties[$name];
}
return null;
}
function __get($name)
{
$property = $this->getRawProperty($name);
if ($property !== null)
{
list($t, $r) = $this->GetPropertyValueRecursive($property);
return $r;
}
return null;
}
function __set($name, $val)
{
if (array_key_exists($name, $this->arProperties))
$this->arProperties[$name] = $val;
//else
//throw new Exception(str_replace("#NAME#", htmlspecialcharsbx($name), GetMessage("BPCGACT_NO_PROPERTY")));
}
public function IsPropertyExists($name)
{
return array_key_exists($name, $this->arProperties);
}
public function CollectNestedActivities()
{
return null;
}
/************************ CONSTRUCTORS *****************************************************/
public function __construct($name)
{
$this->name = $name;
}
/************************ DEBUG ***********************************************************/
public function ToString()
{
return $this->name.
" [".get_class($this)."] (status=".
CBPActivityExecutionStatus::Out($this->executionStatus).
", result=".
CBPActivityExecutionResult::Out($this->executionResult).
", count(ClosedEvent)=".
count($this->arStatusChangeHandlers[self::ClosedEvent]).
")";
}
public function Dump($level = 3)
{
$result = str_repeat(" ", $level).$this->ToString()."\n";
if (is_subclass_of($this, "CBPCompositeActivity"))
{
/** @var CBPActivity $activity */
foreach ($this->arActivities as $activity)
$result .= $activity->Dump($level + 1);
}
return $result;
}
/************************ PROCESS ***********************************************************/
public function Initialize()
{
}
public function Finalize()
{
}
public function Execute()
{
return CBPActivityExecutionStatus::Closed;
}
protected function ReInitialize()
{
$this->executionStatus = CBPActivityExecutionStatus::Initialized;
$this->executionResult = CBPActivityExecutionResult::None;
}
public function Cancel()
{
return CBPActivityExecutionStatus::Closed;
}
public function HandleFault(Exception $exception)
{
return CBPActivityExecutionStatus::Closed;
}
/************************ LOAD / SAVE *******************************************************/
public function FixUpParentChildRelationship(CBPActivity $nestedActivity)
{
$nestedActivity->parent = $this;
}
public static function Load($stream)
{
if (strlen($stream) <= 0)
throw new Exception("stream");
$pos = strpos($stream, ";");
$strUsedActivities = substr($stream, 0, $pos);
$stream = substr($stream, $pos + 1);
$runtime = CBPRuntime::GetRuntime();
$arUsedActivities = explode(",", $strUsedActivities);
foreach ($arUsedActivities as $activityCode)
{
$runtime->IncludeActivityFile($activityCode);
}
return unserialize($stream);
}
protected function GetACNames()
{
return array(substr(get_class($this), 3));
}
private static function SearchUsedActivities(CBPActivity $activity, &$arUsedActivities)
{
$arT = $activity->GetACNames();
foreach ($arT as $t)
{
if (!in_array($t, $arUsedActivities))
{
$arUsedActivities[] = $t;
}
}
if ($arNestedActivities = $activity->CollectNestedActivities())
{
foreach ($arNestedActivities as $nestedActivity)
{
self::SearchUsedActivities($nestedActivity, $arUsedActivities);
}
}
}
public function Save()
{
$usedActivities = [];
self::SearchUsedActivities($this, $usedActivities);
$strUsedActivities = implode(",", $usedActivities);
return $strUsedActivities.";".serialize($this);
}
/************************ STATUS CHANGE HANDLERS **********************************************/
public function AddStatusChangeHandler($event, $eventHandler)
{
if (!is_array($this->arStatusChangeHandlers))
$this->arStatusChangeHandlers = array();
if (!array_key_exists($event, $this->arStatusChangeHandlers))
$this->arStatusChangeHandlers[$event] = array();
$this->arStatusChangeHandlers[$event][] = $eventHandler;
}
public function RemoveStatusChangeHandler($event, $eventHandler)
{
if (!is_array($this->arStatusChangeHandlers))
$this->arStatusChangeHandlers = array();
if (!array_key_exists($event, $this->arStatusChangeHandlers))
$this->arStatusChangeHandlers[$event] = array();
$index = array_search($eventHandler, $this->arStatusChangeHandlers[$event], true);
if ($index !== false)
unset($this->arStatusChangeHandlers[$event][$index]);
}
/************************ EVENTS **********************************************************************/
private function FireStatusChangedEvents($event, $arEventParameters = array())
{
if (array_key_exists($event, $this->arStatusChangeHandlers) && is_array($this->arStatusChangeHandlers[$event]))
{
foreach ($this->arStatusChangeHandlers[$event] as $eventHandler)
call_user_func_array(array($eventHandler, "OnEvent"), array($this, $arEventParameters));
}
}
public function SetStatus($newStatus, $arEventParameters = array())
{
$this->executionStatus = $newStatus;
$this->FireStatusChangedEvents(self::StatusChangedEvent, $arEventParameters);
switch ($newStatus)
{
case CBPActivityExecutionStatus::Executing:
$this->FireStatusChangedEvents(self::ExecutingEvent, $arEventParameters);
break;
case CBPActivityExecutionStatus::Canceling:
$this->FireStatusChangedEvents(self::CancelingEvent, $arEventParameters);
break;
case CBPActivityExecutionStatus::Closed:
$this->FireStatusChangedEvents(self::ClosedEvent, $arEventParameters);
break;
case CBPActivityExecutionStatus::Faulting:
$this->FireStatusChangedEvents(self::FaultingEvent, $arEventParameters);
break;
default:
return;
}
}
/************************ CREATE *****************************************************************/
public static function IncludeActivityFile($code)
{
$runtime = CBPRuntime::GetRuntime();
return $runtime->IncludeActivityFile($code);
}
public static function CreateInstance($code, $data)
{
if (preg_match("#[^a-zA-Z0-9_]#", $code))
throw new Exception("Activity '".$code."' is not valid");
$classname = 'CBP'.$code;
if (class_exists($classname))
return new $classname($data);
else
return null;
}
public static function CallStaticMethod($code, $method, $arParameters = array())
{
$runtime = CBPRuntime::GetRuntime();
if (!$runtime->IncludeActivityFile($code))
return array(array("code" => "ActivityNotFound", "parameter" => $code, "message" => GetMessage("BPGA_ACTIVITY_NOT_FOUND", array('#ACTIVITY#' => htmlspecialcharsbx($code)))));
if (preg_match("#[^a-zA-Z0-9_]#", $code))
throw new Exception("Activity '".$code."' is not valid");
$classname = 'CBP'.$code;
if (method_exists($classname,$method))
return call_user_func_array(array($classname, $method), $arParameters);
return false;
}
public function InitializeFromArray($arParams)
{
if (is_array($arParams))
{
foreach ($arParams as $key => $value)
{
if (array_key_exists($key, $this->arProperties))
$this->arProperties[$key] = $value;
}
}
}
/************************ MARK ****************************************************************/
public function MarkCanceled($arEventParameters = array())
{
if ($this->executionStatus != CBPActivityExecutionStatus::Closed)
{
if ($this->executionStatus != CBPActivityExecutionStatus::Canceling)
throw new Exception("InvalidCancelActivityState");
$this->executionResult = CBPActivityExecutionResult::Canceled;
$this->MarkClosed($arEventParameters);
}
}
public function MarkCompleted($arEventParameters = array())
{
$this->executionResult = CBPActivityExecutionResult::Succeeded;
$this->MarkClosed($arEventParameters);
}
public function MarkFaulted($arEventParameters = array())
{
$this->executionResult = CBPActivityExecutionResult::Faulted;
$this->MarkClosed($arEventParameters);
}
private function MarkClosed($arEventParameters = array())
{
switch ($this->executionStatus)
{
case CBPActivityExecutionStatus::Executing:
case CBPActivityExecutionStatus::Canceling:
case CBPActivityExecutionStatus::Faulting:
{
if (is_subclass_of($this, "CBPCompositeActivity"))
{
foreach ($this->arActivities as $activity)
{
if (($activity->executionStatus != CBPActivityExecutionStatus::Initialized)
&& ($activity->executionStatus != CBPActivityExecutionStatus::Closed))
{
throw new Exception("ActiveChildExist");
}
}
}
/** @var CBPTrackingService $trackingService */
$trackingService = $this->workflow->GetService("TrackingService");
$trackingService->Write($this->GetWorkflowInstanceId(), CBPTrackingType::CloseActivity, $this->name, $this->executionStatus, $this->executionResult, ($this->IsPropertyExists("Title") ? $this->Title : ""));
$this->SetStatus(CBPActivityExecutionStatus::Closed, $arEventParameters);
return;
}
}
throw new Exception("InvalidCloseActivityState");
}
protected function WriteToTrackingService($message = "", $modifiedBy = 0, $trackingType = -1)
{
/** @var CBPTrackingService $trackingService */
$trackingService = $this->workflow->GetService("TrackingService");
if ($trackingType < 0)
$trackingType = CBPTrackingType::Custom;
$trackingService->Write($this->GetWorkflowInstanceId(), $trackingType, $this->name, $this->executionStatus, $this->executionResult, ($this->IsPropertyExists("Title") ? $this->Title : ""), $message, $modifiedBy);
}
public static function ValidateProperties($arTestProperties = array(), CBPWorkflowTemplateUser $user = null)
{
return array();
}
public static function ValidateChild($childActivity, $bFirstChild = false)
{
return array();
}
public static function &FindActivityInTemplate(&$arWorkflowTemplate, $activityName)
{
return CBPWorkflowTemplateLoader::FindActivityByName($arWorkflowTemplate, $activityName);
}
public static function isExpression($text)
{
if (is_string($text))
{
$text = trim($text);
if (preg_match(static::CalcPattern, $text) || preg_match(static::ValuePattern, $text))
return true;
}
return false;
}
}