Merge pull request #22928 from artfulrobot/artfulrobot-title-double-html-encoding
[civicrm-core.git] / Civi / Api4 / Query / SqlEquation.php
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
12 namespace Civi\Api4\Query;
13
14 /**
15 * Numeric sql expression
16 */
17 class 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)) {
56 $this->args = array_merge($this->args, $this->captureExpressions($arg, $permitted, 1));
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 *
67 * @param array $fieldList
68 * @return string
69 */
70 public function render(array $fieldList): string {
71 $output = [];
72 foreach ($this->args as $arg) {
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)) {
79 $output[] = 'COALESCE(' . $arg->render($fieldList) . ', 0)';
80 }
81 else {
82 $output[] = $arg->render($fieldList);
83 }
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
119 public static function getTitle(): string {
120 return ts('Equation');
121 }
122
123 }