Licitator 1.0
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

124 lines
4.0 KiB

5 years ago
  1. <?php
  2. namespace Zitec\RuleEngineBundle\Service;
  3. /**
  4. * Class ExpressionConverter
  5. * Converts an array of conditions to an expression language string.
  6. */
  7. class RuleJsonConverter
  8. {
  9. protected const ITEM_GROUP = 'group';
  10. protected const ITEM_CONDITION = 'cond';
  11. protected const NODE_AND = 'all';
  12. protected const NODE_OR = 'any';
  13. protected const NODE_NEITHER = 'none';
  14. protected const NODE_NAME = 'name';
  15. protected const NODE_OPERATOR = 'operator';
  16. protected const NODE_VALUE = 'value';
  17. /**
  18. * @param string $json
  19. * @param RuleConditionsManager $ruleManager
  20. * @return array
  21. */
  22. public function formatForDisplay(string $json, RuleConditionsManager $ruleManager): array
  23. {
  24. $rule = $json ? json_decode($json, true) : [];
  25. if (empty($rule)) {
  26. return [];
  27. }
  28. foreach ($rule['items'] as &$item) {
  29. $this->formatItemForDisplay($item, $ruleManager);
  30. }
  31. return [
  32. 'item_type' => $this::ITEM_GROUP,
  33. 'data' => $rule,
  34. ];
  35. }
  36. /**
  37. * @param array $item
  38. * @param RuleConditionsManager $ruleManager
  39. */
  40. protected function formatItemForDisplay(array &$item, RuleConditionsManager $ruleManager)
  41. {
  42. switch ($item['item_type']) {
  43. case $this::ITEM_GROUP:
  44. foreach ($item['data']['items'] as &$subItem) {
  45. $this->formatItemForDisplay($subItem, $ruleManager);
  46. }
  47. break;
  48. case $this::ITEM_CONDITION:
  49. $item['data'] = $ruleManager->getCondition($item['data'][$this::NODE_NAME])
  50. ->getDisplayValue($item['data'][$this::NODE_OPERATOR], $item['data'][$this::NODE_VALUE]);
  51. break;
  52. }
  53. }
  54. /**
  55. * @param string $json
  56. * @param RuleConditionsManager $ruleManager
  57. * @return string
  58. */
  59. public function generateExpression(string $json, RuleConditionsManager $ruleManager)
  60. {
  61. $rule = $json ? json_decode($json, true) : [];
  62. $stringExpression = '';
  63. if (!empty($rule)) {
  64. $stringExpression .= $this->getGroupExpressionPart($rule, $ruleManager);
  65. }
  66. return $stringExpression ?: 'true';
  67. }
  68. /**
  69. * @param array $group
  70. * @param RuleConditionsManager $ruleManager
  71. * @return string
  72. */
  73. protected function getGroupExpressionPart(array $group, RuleConditionsManager $ruleManager)
  74. {
  75. $stringExpression = '';
  76. $prefixExpression = '';
  77. $logicalOperator = '';
  78. switch ($group['logic_operator']) {
  79. case self::NODE_OR:
  80. $logicalOperator = ' or ';
  81. break;
  82. case self::NODE_AND:
  83. $logicalOperator = ' and ';
  84. break;
  85. case self::NODE_NEITHER:
  86. $logicalOperator = ' and ';
  87. $prefixExpression = ' not ';
  88. break;
  89. }
  90. $expressionParts = [];
  91. foreach ($group['items'] as $item) {
  92. switch ($item['item_type']) {
  93. case $this::ITEM_GROUP:
  94. $expressionParts[] = $this->getGroupExpressionPart($item['data'], $ruleManager);
  95. break;
  96. case $this::ITEM_CONDITION:
  97. $name = $item['data'][$this::NODE_NAME];
  98. $operator = $item['data'][$this::NODE_OPERATOR];
  99. $value = $item['data'][$this::NODE_VALUE];
  100. $contextObjectName = $ruleManager->getContext()->getContextObjectKey();
  101. $methodName = $ruleManager->getContext()->getMethodName($name);
  102. $expresion=$ruleManager->getCondition($name)->getExpression("$contextObjectName.$methodName()", $operator, $value);
  103. $expressionParts[] = $expresion;
  104. break;
  105. }
  106. }
  107. if ($expressionParts) {
  108. $stringExpression .= ($prefixExpression . '(' . implode($logicalOperator, $expressionParts) . ')');
  109. }
  110. return $stringExpression;
  111. }
  112. }