Merge pull request #23814 from civicrm/5.51
[civicrm-core.git] / Civi / Api4 / Query / SqlEquation.php
CommitLineData
f4138bc4
CW
1<?php
2/*
3 +--------------------------------------------------------------------+
4 | Copyright CiviCRM LLC. All rights reserved. |
5 | |
6 | This work is published under the GNU AGPLv3 license with some |
7 | permitted exceptions and without any warranty. For full license |
8 | and copyright information, see https://civicrm.org/licensing |
9 +--------------------------------------------------------------------+
10 */
11
12namespace Civi\Api4\Query;
13
14/**
15 * Numeric sql expression
16 */
17class SqlEquation extends SqlExpression {
18
19 /**
20 * @var array
21 */
22 protected $args = [];
23
24 /**
25 * @var string[]
26 */
27 public static $arithmeticOperators = [
28 '+',
29 '-',
30 '*',
31 '/',
32 ];
33
34 /**
35 * @var string[]
36 */
37 public static $comparisonOperators = [
38 '<=',
39 '>=',
40 '<',
41 '>',
42 '=',
43 '!=',
44 '<=>',
45 'IS NOT',
46 'IS',
47 'BETWEEN',
48 'AND',
49 ];
50
51 protected function initialize() {
52 $arg = trim(substr($this->expr, strpos($this->expr, '(') + 1, -1));
53 $permitted = ['SqlField', 'SqlString', 'SqlNumber', 'SqlNull'];
54 $operators = array_merge(self::$arithmeticOperators, self::$comparisonOperators);
55 while (strlen($arg)) {
9e9feedf 56 $this->args = array_merge($this->args, $this->captureExpressions($arg, $permitted, 1));
f4138bc4
CW
57 $op = $this->captureKeyword($operators, $arg);
58 if ($op) {
59 $this->args[] = $op;
60 }
61 }
62 }
63
64 /**
65 * Render the expression for insertion into the sql query
66 *
3dbd3926 67 * @param Civi\Api4\Query\Api4SelectQuery $query
f4138bc4
CW
68 * @return string
69 */
3dbd3926 70 public function render(Api4SelectQuery $query): string {
f4138bc4
CW
71 $output = [];
72 foreach ($this->args as $arg) {
a2086e29
CW
73 // Just an operator
74 if (is_string($arg)) {
75 $output[] = $arg;
76 }
77 // Surround fields with COALESCE to handle null values
78 elseif (is_a($arg, SqlField::class)) {
3dbd3926 79 $output[] = 'COALESCE(' . $arg->render($query) . ', 0)';
a2086e29
CW
80 }
81 else {
3dbd3926 82 $output[] = $arg->render($query);
a2086e29 83 }
f4138bc4
CW
84 }
85 return '(' . implode(' ', $output) . ')';
86 }
87
88 /**
89 * Returns the alias to use for SELECT AS.
90 *
91 * @return string
92 */
93 public function getAlias(): string {
94 return $this->alias ?? \CRM_Utils_String::munge(trim($this->expr, ' ()'), '_', 256);
95 }
96
97 /**
98 * Change $dataType according to operator used in equation
99 *
100 * @see \Civi\Api4\Utils\FormattingUtil::formatOutputValues
101 * @param string $value
102 * @param string $dataType
103 * @return string
104 */
105 public function formatOutputValue($value, &$dataType) {
106 foreach (self::$comparisonOperators as $op) {
107 if (strpos($this->expr, " $op ")) {
108 $dataType = 'Boolean';
109 }
110 }
111 foreach (self::$arithmeticOperators as $op) {
112 if (strpos($this->expr, " $op ")) {
113 $dataType = 'Float';
114 }
115 }
116 return $value;
117 }
118
4e161794
CW
119 public static function getTitle(): string {
120 return ts('Equation');
121 }
122
f4138bc4 123}