View source
<?php
namespace Drupal\business_rules\Util\Flowchart;
use Drupal\business_rules\Entity\BusinessRule;
use Drupal\Core\Entity\EntityInterface;
class Matrix {
protected $numberOfRootItems = 0;
private $matrix = [];
private $rootElement;
public function __construct() {
for ($y = 0; $y <= 100; $y++) {
for ($x = 0; $x <= 100; $x++) {
$this->matrix[$x][$y] = [
'x' => $x * 170 + 10,
'y' => $y * 90 + 10,
'index_x' => $x,
'index_y' => $y,
'element' => NULL,
];
}
}
}
public function getAllCellWithElements() {
$cells = [];
for ($y = 0; $y <= 100; $y++) {
for ($x = 0; $x <= 100; $x++) {
if (is_object($this->matrix[$x][$y]['element'])) {
$cells[] = $this->matrix[$x][$y];
}
}
}
return $cells;
}
public function getElementAbove(Element $element) {
$cell = $this
->getCellByElementUuid($element
->getUuid());
$x = $cell['index_x'];
$y = $cell['index_y'];
if ($y === 0) {
return NULL;
}
$cell_above = $this->matrix[$x][$y - 1];
if ($cell_above['element'] instanceof Element) {
return $cell_above['element'];
}
else {
return NULL;
}
}
public function getCellByElementUuid($uuid) {
for ($y = 0; $y <= 100; $y++) {
for ($x = 0; $x <= 100; $x++) {
$element = $this->matrix[$x][$y]['element'];
if ($element instanceof Element) {
if ($element
->getUuid() == $uuid) {
return $this->matrix[$x][$y];
}
}
}
}
return NULL;
}
public function getElementByItem(EntityInterface $item) {
for ($y = 0; $y <= 100; $y++) {
for ($x = 0; $x <= 100; $x++) {
if (is_object($this->matrix[$x][$y]['element'])) {
if ($this->matrix[$x][$y]['element']
->getItem() === $item) {
return $this->matrix[$x][$y]['element'];
}
}
}
}
}
public function isCellEmpty($x, $y) {
if (is_null($this->matrix[$x][$y]['element'])) {
return TRUE;
}
else {
return FALSE;
}
}
public function putElement(Element $element, Element $parent, $direction, $off_x = 0, $off_y = 0) {
if ($parent
->getItem() === $this
->getRootElement()
->getItem()) {
$parent_cell = $this
->getCellByElementUuid($this
->getRootElement()
->getUuid());
}
else {
$parent_cell = $this
->getCellByElementUuid($parent
->getUuid());
}
if (is_null($parent_cell)) {
throw new \Exception('Could not load parent');
}
$parent_x = $parent_cell['index_x'];
$parent_y = $parent_cell['index_y'];
$root = $this
->getRootElement();
$root_cel = $this
->getCellByElementUuid($root
->getUuid());
$root_x = $root_cel['index_x'];
switch ($direction) {
case 'bottom':
if ($this->numberOfRootItems >= $parent_y && $root_x === $parent_x && $element
->getParent() !== $root) {
$off_x++;
}
if (is_null($this->matrix[$parent_x + $off_x][$parent_y + 1 + $off_y]['element'])) {
$this
->putElementInPosition($element, $parent_x + $off_x, $parent_y + 1 + $off_y);
}
else {
$this
->putElement($element, $parent, $direction, $off_x, $off_y + 1);
}
break;
case 'right':
if ($this->numberOfRootItems >= $parent_y && $root_x === $parent_x + 1 + $off_x) {
$off_x++;
}
if (is_null($this->matrix[$parent_x + 1 + $off_x][$parent_y + $off_y]['element'])) {
$this
->putElementInPosition($element, $parent_x + 1 + $off_x, $parent_y + $off_y);
}
else {
$this
->putElement($element, $parent, $direction, $off_x, $off_y + 1);
}
break;
case 'left':
if ($this->numberOfRootItems >= $parent_y && $root_x === $parent_x - 1 + $off_x) {
$off_x--;
}
if ($parent_x - 1 + $off_x < 0 || is_null($this->matrix[$parent_x - 1 + $off_x][$parent_y + $off_y]['element'])) {
$this
->putElementInPosition($element, $parent_x - 1 + $off_x, $parent_y + $off_y);
}
else {
$this
->putElement($element, $parent, $direction, $off_x, $off_y + 1);
}
break;
case 'bottom-right':
if ($this->numberOfRootItems >= $parent_y && $root_x === $parent_x + 1 + $off_x) {
$off_x++;
}
if (is_null($this->matrix[$parent_x + 1 + $off_x][$parent_y + 1 + $off_y]['element'])) {
$this
->putElementInPosition($element, $parent_x + 1 + $off_x, $parent_y + 1 + $off_y);
}
else {
$this
->putElement($element, $parent, $direction, $off_x, $off_y + 1);
}
break;
case 'bottom-left':
if ($this->numberOfRootItems >= $parent_y && $root_x === $parent_x - 1 + $off_x) {
$off_x--;
}
if ($parent_x - 1 + $off_x < 0 || is_null($this->matrix[$parent_x - 1 + $off_x][$parent_y + 1 + $off_y]['element'])) {
$this
->putElementInPosition($element, $parent_x - 1 + $off_x, $parent_y + 1 + $off_y);
}
else {
$this
->putElement($element, $parent, $direction, $off_x, $off_y + 1);
}
break;
}
}
public function getRootElement() {
return $this->rootElement;
}
private function putElementInPosition(Element $element, $x, $y) {
if ($x < 0) {
$this
->shitAlToRight(-$x);
$x = 0;
}
if (is_null($this->matrix[$x][$y]['element'])) {
$this->matrix[$x][$y]['element'] = $element;
}
else {
throw new \Exception("The position {$x}, {$y} is not empty.");
}
}
private function shitAlToRight($distance = 1) {
for ($y = 0; $y <= 100; $y++) {
for ($x = 100; $x >= 0; $x--) {
$cell = $this->matrix[$x][$y];
if (!is_null($cell['element'])) {
$this
->putElementInPosition($cell['element'], $x + $distance, $y);
$this->matrix[$x][$y]['element'] = NULL;
}
}
}
}
public function putRootElement(Element $element) {
$this
->putElementInPosition($element, 0, 0);
$this->rootElement = $element;
if ($element
->getItem() instanceof BusinessRule) {
$this->numberOfRootItems = count($element
->getItem()
->getItems());
}
}
public function shift(Element $element, $direction, $distance = 1) {
switch ($direction) {
case 'bottom':
$cells = $this
->getBottomCells($element);
$cells = array_reverse($cells);
foreach ($cells as $cell) {
$x = $cell['index_x'];
$y = $cell['index_y'];
$element = $cell['element'];
$this
->putElementInPosition($element, $x, $y + $distance);
$this->matrix[$x][$y]['element'] = NULL;
}
break;
case 'right':
$cells = $this
->getRightCells($element);
$cells = array_reverse($cells);
foreach ($cells as $cell) {
$x = $cell['index_x'];
$y = $cell['index_y'];
$element = $cell['element'];
$this
->putElementInPosition($element, $x + $distance, $y);
$this->matrix[$x][$y]['element'] = NULL;
}
break;
case 'left':
$cells = $this
->getLeftCells($element);
foreach ($cells as $cell) {
$x = $cell['index_x'];
$y = $cell['index_y'];
$element = $cell['element'];
$this
->putElementInPosition($element, $x - $distance, $y);
$this->matrix[$x][$y]['element'] = NULL;
}
break;
}
}
private function getBottomCells(Element $element) {
$cell = $this
->getCellByElementUuid($element
->getUuid());
$index_x = $cell['index_x'];
$index_y = $cell['index_y'];
$elements[] = $cell;
for ($y = $index_y; $y < 100; $y++) {
if (!is_null($this->matrix[$index_x][$y + 1])) {
$elements[] = $this->matrix[$index_x][$y + 1];
}
else {
return $elements;
}
}
return $elements;
}
private function getRightCells(Element $element) {
$cell = $this
->getCellByElementUuid($element
->getUuid());
$index_x = $cell['index_x'];
$index_y = $cell['index_y'];
$elements[] = $cell;
for ($x = $index_x; $x < 100; $x++) {
if (!is_null($this->matrix[$x + 1])) {
$elements[] = $this->matrix[$x + 1][$index_y];
}
else {
return $elements;
}
}
return $elements;
}
private function getLeftCells(Element $element) {
$cell = $this
->getCellByElementUuid($element
->getUuid());
$index_x = $cell['index_x'];
$index_y = $cell['index_y'];
$elements = [];
for ($x = $index_x; $x >= 0; $x--) {
if (!is_null($this->matrix[$x - 1])) {
$elements[] = $this->matrix[$x - 1][$index_y];
}
else {
return $elements;
}
}
return $elements;
}
public function rightCellIsEmpty(Element $element) {
$cell = $this
->getCellByElementUuid($element
->getUuid());
$index_x = $cell['index_x'];
$index_y = $cell['index_y'];
$right_cell = $this
->getCellByPosition($index_x + 1, $index_y);
if (empty($right_cell['element'])) {
$empty = TRUE;
}
else {
$empty = FALSE;
}
return $empty;
}
public function getCellByPosition($x, $y) {
return $this->matrix[$x][$y];
}
public function leftCellIsEmpty(Element $element) {
$cell = $this
->getCellByElementUuid($element
->getUuid());
$index_x = $cell['index_x'];
$index_y = $cell['index_y'];
if ($index_x == 0) {
return TRUE;
}
$left_cell = $this
->getCellByPosition($index_x - 1, $index_y);
if (empty($left_cell['element'])) {
$empty = TRUE;
}
else {
$empty = FALSE;
}
return $empty;
}
}