summaryrefslogtreecommitdiffstats
path: root/modules-available/statistics/inc/hardwarequerycolumn.inc.php
diff options
context:
space:
mode:
Diffstat (limited to 'modules-available/statistics/inc/hardwarequerycolumn.inc.php')
-rw-r--r--modules-available/statistics/inc/hardwarequerycolumn.inc.php94
1 files changed, 94 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..01e32978
--- /dev/null
+++ b/modules-available/statistics/inc/hardwarequerycolumn.inc.php
@@ -0,0 +1,94 @@
+<?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 string[] $groupConcat if column name is NOT in this array, add as distinct GROUP_CONCAT to column.
+ */
+ public function generate(array &$joins, array &$columns, array &$params, array $groupConcat = [], string $globalSrcTableAlias = null)
+ {
+ if ($this->global) {
+ $srcTable = $globalSrcTableAlias ?? '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 (!empty($groupConcat) && !in_array($this->alias, $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;
+ }
+ } elseif ($op === '~' || $op === '!~') {
+ $op = $op === '~' ? 'LIKE' : 'NOT LIKE';
+ $other = str_replace(array('=', '_', '%', '*', '?'), array('==', '=_', '=%', '%', '_'), $other);
+ $pid = self::getId();
+ $this->conditions[] = "{$this->tableAlias}.`$valueCol` $op (:$pid) ESCAPE '='";
+ $this->params[$pid] = $other;
+ } else {
+ $pid = self::getId();
+ $this->conditions[] = "{$this->tableAlias}.`$valueCol` $op (:$pid)";
+ $this->params[$pid] = $other;
+ }
+ }
+
+}