summaryrefslogtreecommitdiffstats
path: root/modules-available/statistics/inc/hardwarequerycolumn.inc.php
diff options
context:
space:
mode:
authorSimon Rettberg2022-01-12 17:07:42 +0100
committerSimon Rettberg2022-03-09 15:06:54 +0100
commit1bdf3d4ce66910f07842c7be1043938bccf0a462 (patch)
treed6a4e1f0185687c224e4a3a901186fe3b0cbd3d9 /modules-available/statistics/inc/hardwarequerycolumn.inc.php
parentapi: Don't use mb_strtolower (diff)
downloadslx-admin-1bdf3d4ce66910f07842c7be1043938bccf0a462.tar.gz
slx-admin-1bdf3d4ce66910f07842c7be1043938bccf0a462.tar.xz
slx-admin-1bdf3d4ce66910f07842c7be1043938bccf0a462.zip
[statistics] Make query builder a bit more OOP
Diffstat (limited to 'modules-available/statistics/inc/hardwarequerycolumn.inc.php')
-rw-r--r--modules-available/statistics/inc/hardwarequerycolumn.inc.php88
1 files changed, 88 insertions, 0 deletions
diff --git a/modules-available/statistics/inc/hardwarequerycolumn.inc.php b/modules-available/statistics/inc/hardwarequerycolumn.inc.php
new file mode 100644
index 00000000..d073530b
--- /dev/null
+++ b/modules-available/statistics/inc/hardwarequerycolumn.inc.php
@@ -0,0 +1,88 @@
+<?php
+
+class HardwareQueryColumn
+{
+ /** @var int For unique table names in join */
+ private static $id = 0;
+
+ private $global;
+ private $tableAlias;
+ private $virtualColumnName;
+ private $alias;
+ private $conditions = [];
+ private $params = [];
+ private $classId;
+
+ private static function getId(): string
+ {
+ return 't' . ++self::$id;
+ }
+
+ public function __construct(bool $global, string $column, string $alias = null)
+ {
+ $this->classId = ++self::$id;
+ $this->global = $global;
+ $this->tableAlias = self::getId();
+ $this->virtualColumnName = $column;
+ $this->alias = $alias ?? $column;
+ }
+
+ /**
+ * Add necessary conditions, joins, columns to final SQL arrays. To be called
+ * from HardwareQuery::buildQuery().
+ * @param bool $groupConcat whether to add distinct GROUP_CONCAT to column.
+ */
+ public function generate(array &$joins, array &$columns, array &$params, bool $groupConcat)
+ {
+ if ($this->global) {
+ $srcTable = 'shw';
+ $table = 'statistic_hw_prop';
+ $column = 'hwid';
+ } else {
+ $srcTable = 'mxhw';
+ $table = 'machine_x_hw_prop';
+ $column = 'machinehwid';
+ }
+ $tid = $this->tableAlias;
+ $pid = self::getId();
+ $this->conditions[] = "$srcTable.$column = $tid.$column AND $tid.prop = :$pid";
+ $params[$pid] = $this->virtualColumnName; // value of property column is our virtual column
+ // If we have just one condition, it's the join condition itself. Since we pretend we're just adding
+ // a column to the query, do a left join, so the "column" is NULL if the join doesn't match.
+ // If however any conditions were added to this class via the addCondition() method, do a regular
+ // INNER JOIN, so the result will be empty if the condition doesn't match.
+ $type = count($this->conditions) === 1 ? 'LEFT' : 'INNER';
+ $joins[] = "$type JOIN $table $tid ON (" . implode(' AND ', $this->conditions) . ")";
+ if ($groupConcat) {
+ $columns[] = "Group_Concat(DISTINCT $tid.`value` SEPARATOR ', ') AS `{$this->alias}`";
+ } else {
+ $columns[] = "$tid.`value` AS `{$this->alias}`";
+ }
+ $params += $this->params;
+ }
+
+ /**
+ * @param string $op Operator (<>=, IN, LIKE)
+ * @param string|string[]|HardwareQueryColumn $other value to compare with.
+ * Can be a literal, an array (if opererator is IN), or another Column
+ * @return void
+ */
+ public function addCondition(string $op, $other)
+ {
+ $valueCol = ($op === '<' || $op === '>' || $op === '<=' || $op === '>=') ? 'numeric' : 'value';
+ if ($other instanceof HardwareQueryColumn) {
+ $cond = "{$this->tableAlias}.`$valueCol` $op {$other->tableAlias}.`$valueCol`";
+ // Don't reference a column of a table that hasn't been joined yet
+ if ($this->classId > $other->classId) {
+ $this->conditions[] = $cond;
+ } else {
+ $other->conditions[] = $cond;
+ }
+ } else {
+ $pid = self::getId();
+ $this->conditions[] = "{$this->tableAlias}.`$valueCol` $op (:$pid)";
+ $this->params[$pid] = $other;
+ }
+ }
+
+} \ No newline at end of file