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.

245 lines
7.9 KiB

5 years ago
  1. <?php
  2. namespace Zitec\RuleEngineBundle\Conditions;
  3. /**
  4. * Starter kit class for declaring conditions for a multi-value parameter.
  5. */
  6. abstract class AbstractArrayCondition implements ConditionInterface
  7. {
  8. /**
  9. * Use this operator when you want to
  10. * check that the parameter value set and configured value set have at least one element in common.
  11. */
  12. protected const INTERSECTING = 'isIn';
  13. /**
  14. * Use this operator when you want to
  15. * check that the parameter value set and configured value set have no elements in common.
  16. */
  17. protected const DISJOINT = 'isNotIn';
  18. /**
  19. * Use this operator when you want to
  20. * check that the parameter value set includes all configured values.
  21. */
  22. protected const INCLUDES = 'isAll';
  23. /**
  24. * Use this operator when you want to
  25. * check that the parameter value and configured value have exactly the same elements.
  26. */
  27. protected const IDENTICAL = 'isExact';
  28. /**
  29. * Use this operator when you want to
  30. * check that the parameter value set has no values outside the configured value set, ie. is included in it.
  31. */
  32. protected const INCLUDED = 'isOnly';
  33. /**
  34. * Use this operator when you want to
  35. * compare the number of unique elements in the parameter value set.
  36. */
  37. protected const COUNT = 'countIs';
  38. /**
  39. * Use this operator when you want to
  40. * compare the number of unique elements in the parameter value set.
  41. */
  42. protected const COMPLETED = 'isCompleted';
  43. /**
  44. * Use this operator when you want to
  45. * compare the number of unique elements in the parameter value set.
  46. */
  47. protected const NOCOMPLETED = 'isnotCompleted';
  48. /**
  49. * Use this operator when you want to
  50. * compare the parameter value with another multi-value (array) parameter's value.
  51. */
  52. protected const EQUALS_PARAM = 'eqParam';
  53. /**
  54. * @var string
  55. */
  56. protected $name;
  57. /**
  58. * @var string
  59. */
  60. protected $label;
  61. /**
  62. * @var string
  63. */
  64. protected $description;
  65. /**
  66. * @return string
  67. */
  68. public function getName(): string
  69. {
  70. return $this->name;
  71. }
  72. /**
  73. * @return string
  74. */
  75. public function getLabel(): string
  76. {
  77. return $this->label;
  78. }
  79. /**
  80. * @return array
  81. */
  82. public function getDefinitions(): array
  83. {
  84. return [
  85. 'name' => $this->name,
  86. 'label' => $this->label,
  87. 'description' => $this->description,
  88. 'operators' => $this->getOperatorDefinitions(),
  89. ];
  90. }
  91. /**
  92. * @return array
  93. */
  94. abstract protected function getOperatorDefinitions(): array;
  95. /**
  96. * @param string $parameterName
  97. * @param string $operator
  98. * @param mixed $value
  99. * @return string
  100. */
  101. public function getExpression(string $parameterName, string $operator, $value): string
  102. {
  103. if (is_null($value)) {
  104. throw new \UnexpectedValueException(
  105. sprintf('NULL value received for condition %s and operator $s', $this->name, $operator)
  106. );
  107. }
  108. $operators = $this->getOperatorDefinitions();
  109. foreach ($operators as $definition) {
  110. if ($operator == $definition['name'] && isset($definition['value_transform'])) {
  111. $value = call_user_func($definition['value_transform'], $value);
  112. break;
  113. }
  114. }
  115. switch ($operator) {
  116. case $this::INTERSECTING:
  117. if (!is_array($value)) {
  118. throw new \UnexpectedValueException('The value for the %s operator has to be an array.', $operator);
  119. }
  120. $formattedValue = implode(',', $value);
  121. return "intersecting($parameterName, '$formattedValue')";
  122. case $this::DISJOINT:
  123. if (!is_array($value)) {
  124. throw new \UnexpectedValueException('The value for the %s operator has to be an array.', $operator);
  125. }
  126. $formattedValue = implode(',', $value);
  127. return "disjoint($parameterName, '$formattedValue')";
  128. case $this::INCLUDES:
  129. if (!is_array($value)) {
  130. throw new \UnexpectedValueException('The value for the %s operator has to be an array.', $operator);
  131. }
  132. $formattedValue = implode(',', $value);
  133. return "includes($parameterName, '$formattedValue')";
  134. case $this::IDENTICAL:
  135. if (!is_array($value)) {
  136. throw new \UnexpectedValueException('The value for the %s operator has to be an array.', $operator);
  137. }
  138. $formattedValue = implode(',', $value);
  139. return "identical($parameterName, '$formattedValue')";
  140. case $this::INCLUDED:
  141. if (!is_array($value)) {
  142. throw new \UnexpectedValueException('The value for the %s operator has to be an array.', $operator);
  143. }
  144. $formattedValue = implode(',', $value);
  145. return "included($parameterName, '$formattedValue')";
  146. case $this::COUNT:
  147. if (!is_numeric($value)) {
  148. throw new \UnexpectedValueException('The value for the %s operator has to be a number.', $operator);
  149. }
  150. return "uniqount($parameterName) == $value";
  151. case $this::COMPLETED:
  152. if (!is_array($value)) {
  153. throw new \UnexpectedValueException('The value for the %s operator has to be a boolean.', $operator);
  154. }
  155. $formattedValue = implode(',', $value);
  156. return "completed($parameterName, '$formattedValue')";
  157. case $this::NOCOMPLETED:
  158. if (!is_array($value)) {
  159. throw new \UnexpectedValueException('The value for the %s operator has to be a boolean.', $operator);
  160. }
  161. $formattedValue = implode(',', $value);
  162. return "nocompleted($parameterName, '$formattedValue')";
  163. case $this::EQUALS_PARAM:
  164. if (!is_string($value)) {
  165. throw new \UnexpectedValueException('The value for the %s operator has to be a string.', $operator);
  166. }
  167. return "$parameterName == $parameterName.$value";
  168. }
  169. throw new \DomainException(sprintf('Unrecognized operator %s', $operator));
  170. }
  171. /**
  172. * @param mixed $value
  173. * @return bool
  174. */
  175. public function validateParameterValue($value): bool
  176. {
  177. return is_array($value);
  178. }
  179. /**
  180. * @param string $operator
  181. * @param $value
  182. * @return string
  183. */
  184. public function getDisplayValue(string $operator, $value): string
  185. {
  186. $operatorLabel = '';
  187. $operators = $this->getOperatorDefinitions();
  188. foreach ($operators as $definition) {
  189. if ($operator == $definition['name']) {
  190. $operatorLabel = $definition['label'];
  191. if (isset($definition['value_view_transform'])) {
  192. $value = call_user_func($definition['value_view_transform'], $value);
  193. }
  194. break;
  195. }
  196. }
  197. switch ($operator) {
  198. case $this::INTERSECTING:
  199. case $this::DISJOINT:
  200. case $this::INCLUDES:
  201. case $this::IDENTICAL:
  202. case $this::INCLUDED:
  203. $formattedValue = implode(',', $value);
  204. break;
  205. case $this::COUNT:
  206. case $this::COMPLETED:
  207. case $this::EQUALS_PARAM:
  208. $formattedValue = $value;
  209. break;
  210. default:
  211. $formattedValue = '';
  212. break;
  213. }
  214. return $this->label . ': ' . $operatorLabel . ' ' . $formattedValue;
  215. }
  216. }