columnTypes = array_map(fn($col) => $col['colType'], $table->columns); $this->table = $table; } public function select(string ...$cols): Query { if (!empty($cols)) $this->columns = $cols; return $this; } public function where(string $col, string $operator, mixed $val): Query { return $this->addCondition($col, $operator, $val, "AND"); } public function andWhere(string $col, string $operator, mixed $val): Query { return $this->addCondition($col, $operator, $val, "AND"); } public function orWhere(string $col, string $operator, mixed $val): Query { return $this->addCondition($col, $operator, $val, "OR"); } private function addCondition(string $colName, string $operator, mixed $val, string $prefix): Query { if (!isset($this->columnTypes[$colName])) throw new InvalidArgumentException("Unknown column: $colName"); $columnType = $this->columnTypes[$colName]; $castedValue = $columnType->dbCast($val); if (!empty($this->conditions)) $this->conditions[] = $prefix; $this->conditions[] = "$colName $operator $castedValue"; return $this; } public function toSql(): string { $columns = implode(", ", $this->columns); $table = $this->table->tableName; $whereClause = !empty($this->conditions) ? " WHERE " . implode(" ", $this->conditions) : ""; return esc_sql("SELECT $columns FROM $table$whereClause"); } public function query(): array { global $wpdb; $query = $this->toSql(); $results = $wpdb->get_results($wpdb->prepare($query), ARRAY_A); return $this->castResults($results); } private function castResults(array $results): array { foreach ($results as &$row) foreach ($row as $column => &$value) if (isset($this->columnTypes[$column])) $value = $this->columnTypes[$column]->valCast($value); return $results; } }