View source
<?php
namespace Drupal\business_rules\Util\Flowchart;
use Drupal\business_rules\BusinessRulesItemObject;
use Drupal\business_rules\Entity\Action;
use Drupal\business_rules\Entity\BusinessRule;
use Drupal\business_rules\Entity\Condition;
use Drupal\business_rules\Entity\Variable;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\Core\Url;
class Flowchart {
use StringTranslationTrait;
private $matrix;
public function __construct() {
$this->matrix = new Matrix();
}
public function getGraph(EntityInterface $item) {
if ($item instanceof Variable || $item
->isNew() || !$this
->itemHasChildren($item)) {
$form['graph_definition'] = [
'#type' => 'textarea',
'#attributes' => [
'id' => 'graph_definition',
'style' => [
'display:none',
],
],
];
return $form;
}
$this
->mountMatrix($item);
$graph_definition = [];
$graph_definition[] = '<mxGraphModel dx="1426" dy="847" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" background="#ffffff"><root><mxCell id="0"/><mxCell id="1" parent="0"/>';
$graph_definition = array_merge($graph_definition, $this
->processMatrix());
$graph_definition[] = '</root></mxGraphModel>';
$form['graph_definition'] = [
'#type' => 'textarea',
'#value' => implode('', $graph_definition),
'#attributes' => [
'id' => 'graph_definition',
'style' => [
'display:none',
],
],
'#rows' => 0,
'#cols' => 0,
];
$form['mxGraph'] = [
'#type' => 'markup',
'#prefix' => '<div id="business_rules_workflow_graph">',
'#suffix' => '</div>',
];
return $form;
}
private function itemHasChildren(EntityInterface $item) {
if ($item instanceof BusinessRule) {
$children = $item
->getItems();
if (!is_null($children) && count($children)) {
return TRUE;
}
}
elseif ($item instanceof Action) {
$children = $item
->getSettings('items');
if (!is_null($children) && count($children)) {
return TRUE;
}
}
elseif ($item instanceof Condition) {
$success_items = $item
->getSuccessItems();
$fail_items = $item
->getFailItems();
if (count($success_items) || count($fail_items)) {
return TRUE;
}
}
return FALSE;
}
private function mountMatrix(EntityInterface $item, Element $parent = NULL, $info = '', $arrowLabel = '') {
if (empty($parent)) {
$root = new Element($item);
$this->matrix
->putRootElement($root);
}
else {
$off_x = 0;
$off_y = 0;
$direction = 'bottom';
if ($parent
->getItem() instanceof BusinessRule) {
$direction = 'bottom';
}
elseif ($parent
->getItem() instanceof Condition) {
if ($info == 'success') {
$direction = 'bottom-right';
}
elseif ($info == 'fail') {
$direction = 'bottom-left';
}
}
elseif ($parent
->getItem() instanceof Action) {
$root_cell = $this->matrix
->getCellByElementUuid($this->matrix
->getRootElement()
->getUuid());
$parent_cell = $this->matrix
->getCellByElementUuid($parent
->getUuid());
if (empty($parent
->getParent())) {
$direction = 'bottom';
}
elseif ($parent_cell['index_x'] >= $root_cell['index_x'] && $this->matrix
->rightCellIsEmpty($parent)) {
$direction = 'right';
}
else {
$direction = 'left';
}
if ($item instanceof Condition) {
if (!empty($parent
->getParent()) && $parent
->getParent()
->getItem() instanceof BusinessRule) {
if ($direction == 'right') {
if (count($item
->getFailItems())) {
$off_x = 1;
}
}
if ($direction == 'left') {
if (count($item
->getSuccessItems())) {
$off_x = -1;
}
}
}
}
}
$element = new Element($item, $parent, '', $arrowLabel);
$this->matrix
->putElement($element, $parent, $direction, $off_x, $off_y);
}
if ($this
->itemHasChildren($item)) {
if ($this->matrix
->getRootElement()
->getItem() === $item) {
$parent_element = $this->matrix
->getRootElement();
}
else {
$parent_element = $this->matrix
->getElementByItem($item);
}
if ($item instanceof BusinessRule) {
$children = $item
->getItems();
foreach ($children as $child) {
$child = $child
->loadEntity();
if (!empty($child)) {
$this
->mountMatrix($child, $parent_element);
}
}
}
elseif ($item instanceof Condition) {
$success_items = $item
->getSuccessItems();
foreach ($success_items as $success_item) {
$success_item = $success_item
->loadEntity();
$yes = $this
->t('Yes');
if (!empty($success_item)) {
$this
->mountMatrix($success_item, $parent_element, 'success', $yes
->render());
}
}
$fail_items = $item
->getFailItems();
foreach ($fail_items as $fail_item) {
$fail_item = $fail_item
->loadEntity();
$no = $this
->t('No');
if (!empty($fail_item)) {
$this
->mountMatrix($fail_item, $parent_element, 'fail', $no
->render());
}
}
}
elseif ($item instanceof Action) {
$children = $item
->getSettings('items');
if (count($children)) {
$children = BusinessRulesItemObject::itemsArrayToItemsObject($children);
foreach ($children as $child) {
$child = $child
->loadEntity();
if (!empty($child)) {
$this
->mountMatrix($child, $parent_element);
}
}
}
}
}
}
private function processMatrix() {
$root_element = $this->matrix
->getRootElement();
$root_cell = $this->matrix
->getCellByElementUuid($root_element
->getUuid());
$graph = $this
->getRootGraph($root_cell);
$cells = $this->matrix
->getAllCellWithElements();
$this
->processConnections($cells);
foreach ($cells as $cell) {
$element = $cell['element'];
if ($element
->getParent()) {
$graph[] = $this
->getConnection($cell);
}
}
foreach ($cells as $cell) {
$element = $cell['element'];
if ($element
->getParent()) {
$graph = array_merge($graph, $this
->getItemGraph($element));
}
}
return $graph;
}
private function getRootGraph(array $root) {
$item = $root['element']
->getItem();
$meta_data = self::getMetaData($item);
$x = $root['x'];
$y = $root['y'];
$label = str_replace('""', '', $item
->label());
$output = [];
$output[] = '<UserObject label="' . $label . '" link="' . $meta_data['link'] . '" id="' . $root['element']
->getUuid() . '">';
$output[] = '<mxCell style="' . $meta_data['style'] . '" parent="1" vertex="1">';
$output[] = '<mxGeometry x="' . $x . '" y="' . $y . '" width="120" height="60" as="geometry"/>';
$output[] = '</mxCell>';
$output[] = '</UserObject>';
return $output;
}
private function processConnections(array $cells) {
foreach ($cells as $cell) {
$element = $cell['element'];
$originUUid = $this
->getOriginUuid($cell);
$element
->setOriginUuid($originUUid);
}
}
private function getConnection(array $cell) {
$child_id = $cell['element']
->getUuid();
$parent_id = $cell['element']
->getOriginUuid();
$label = str_replace('"', '', $cell['element']
->getArrowLabel());
$connection = '<mxCell id="arrow-' . $child_id . '" value="' . $label . '" style="endArrow=classic;html=1;strokeWidth=3;strokeColor=#000000;fontSize=13;fontColor=#000000;fontStyle=1;labelBackgroundColor=#FFFFFF;" parent="1" source="' . $parent_id . '" target="' . $child_id . '" edge="1"><mxGeometry as="geometry"/></mxCell>';
return $connection;
}
private function getItemGraph(Element $element) {
$item = $element
->getItem();
$cell = $this->matrix
->getCellByElementUuid($element
->getUuid());
$x = $cell['x'];
$y = $cell['y'];
$meta_data = self::getMetaData($item);
$graph = [];
$graph[] = '<UserObject id="' . $element
->getUuid() . '" label="' . str_replace('"', '', $item
->label()) . '" link="' . $meta_data['link'] . '">';
$graph[] = '<mxCell style="' . $meta_data['style'] . '" parent="1" vertex="1">';
$graph[] = '<mxGeometry x="' . $x . '" y="' . $y . '" width="120" height="60" as="geometry"/>';
$graph[] = '</mxCell>';
$graph[] = '</UserObject>';
return $graph;
}
private function getMetaData(EntityInterface $item) {
$meta_data = [];
if ($item instanceof BusinessRule) {
$meta_data['style'] = 'shape=ellipse;whiteSpace=wrap;fillColor=#FFFFFF;strokeColor=#000000;strokeWidth=2;shadow=0;gradientColor=none;fontColor=#000000;';
$meta_data['link'] = Url::fromRoute('entity.business_rule.edit_form', [
'business_rule' => $item
->id(),
])
->toString();
}
elseif ($item instanceof Condition) {
$meta_data['style'] = 'shape=rhombus;html=1;whiteSpace=wrap;aspect=fixed;strokeWidth=2;fillColor=#3399FF;strokeColor=#000000;fontColor=#000000;';
$meta_data['link'] = Url::fromRoute('entity.business_rules_condition.edit_form', [
'business_rules_condition' => $item
->id(),
])
->toString();
}
elseif ($item instanceof Action) {
$meta_data['style'] = 'rounded=1;whiteSpace=wrap;html=1;fillColor=#66CC00;gradientColor=none;strokeWidth=2;strokeColor=#000000;fontColor=#000000;';
$meta_data['link'] = Url::fromRoute('entity.business_rules_action.edit_form', [
'business_rules_action' => $item
->id(),
])
->toString();
}
return $meta_data;
}
private function getOriginUuid(array $cell) {
$root_element = $this->matrix
->getRootElement();
if (empty($cell['element']
->getParent()) || $root_element
->getItem() == $cell['element']
->getParent()
->getItem() && $root_element
->getItem() instanceof BusinessRule) {
return $root_element
->getUuid();
}
else {
$parent = $cell['element']
->getParent();
$element = $cell['element'];
$element_above = $this->matrix
->getElementAbove($element);
if ($element_above instanceof Element && !empty($element_above
->getParent()) && $element_above
->getParent()
->getItem() === $parent
->getItem()) {
$cell['element']
->setArrowLabel('');
return $element_above
->getUuid();
}
else {
return $parent
->getUuid();
}
}
}
public function getGraphDefinition(EntityInterface $item) {
if ($item instanceof Variable) {
return '';
}
$this
->mountMatrix($item);
$graph_definition = [];
$graph_definition[] = '<mxGraphModel dx="1426" dy="847" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" background="#ffffff"><root><mxCell id="0"/><mxCell id="1" parent="0"/>';
$graph_definition = array_merge($graph_definition, $this
->processMatrix());
$graph_definition[] = '</root></mxGraphModel>';
return implode('', $graph_definition);
}
}