SQL CaseWhen/Sum + ContactRequest API fix
This commit is contained in:
parent
7506a81514
commit
896bbe76b4
@ -11,6 +11,8 @@ namespace Api {
|
|||||||
public function __construct(User $user, bool $externalCall, array $params) {
|
public function __construct(User $user, bool $externalCall, array $params) {
|
||||||
parent::__construct($user, $externalCall, $params);
|
parent::__construct($user, $externalCall, $params);
|
||||||
$this->messageId = null;
|
$this->messageId = null;
|
||||||
|
$this->csrfTokenRequired = false;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function sendMail(string $name, ?string $fromEmail, string $subject, string $message, ?string $to = null): bool {
|
protected function sendMail(string $name, ?string $fromEmail, string $subject, string $message, ?string $to = null): bool {
|
||||||
@ -23,6 +25,7 @@ namespace Api {
|
|||||||
"to" => $to
|
"to" => $to
|
||||||
));
|
));
|
||||||
|
|
||||||
|
$this->lastError = $request->getLastError();
|
||||||
if ($this->success) {
|
if ($this->success) {
|
||||||
$this->messageId = $request->getResult()["messageId"];
|
$this->messageId = $request->getResult()["messageId"];
|
||||||
}
|
}
|
||||||
@ -39,6 +42,9 @@ namespace Api\Contact {
|
|||||||
use Api\Parameter\StringType;
|
use Api\Parameter\StringType;
|
||||||
use Api\VerifyCaptcha;
|
use Api\VerifyCaptcha;
|
||||||
use Driver\SQL\Condition\Compare;
|
use Driver\SQL\Condition\Compare;
|
||||||
|
use Driver\SQL\Condition\CondNot;
|
||||||
|
use Driver\SQL\Expression\CaseWhen;
|
||||||
|
use Driver\SQL\Expression\Sum;
|
||||||
use Objects\User;
|
use Objects\User;
|
||||||
|
|
||||||
class Request extends ContactAPI {
|
class Request extends ContactAPI {
|
||||||
@ -219,9 +225,10 @@ namespace Api\Contact {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$sql = $this->user->getSQL();
|
$sql = $this->user->getSQL();
|
||||||
$res = $sql->select("ContactRequest.uid", "from_name", "from_email", "from_name", $sql->sum("read"))
|
$res = $sql->select("ContactRequest.uid", "from_name", "from_email", "from_name",
|
||||||
|
new Sum(new CaseWhen(new CondNot("ContactMessage.read"), 1, 0), "unread"))
|
||||||
->from("ContactRequest")
|
->from("ContactRequest")
|
||||||
->groupBy("uid")
|
->groupBy("ContactRequest.uid")
|
||||||
->leftJoin("ContactMessage", "ContactRequest.uid", "ContactMessage.request_id")
|
->leftJoin("ContactMessage", "ContactRequest.uid", "ContactMessage.request_id")
|
||||||
->execute();
|
->execute();
|
||||||
|
|
||||||
|
@ -187,7 +187,7 @@ namespace Api\Mail {
|
|||||||
$sql = $this->user->getSQL();
|
$sql = $this->user->getSQL();
|
||||||
|
|
||||||
$query = $sql->insert("ContactMessage", ["request_id", "user_id", "message", "messageId", "created_at"])
|
$query = $sql->insert("ContactMessage", ["request_id", "user_id", "message", "messageId", "created_at"])
|
||||||
->onDuplicateKeyStrategy(new UpdateStrategy(["message_id"], ["message" => new Column("message")]));
|
->onDuplicateKeyStrategy(new UpdateStrategy(["messageId"], ["message" => new Column("message")]));
|
||||||
|
|
||||||
$entityIds = [];
|
$entityIds = [];
|
||||||
foreach ($messages as $message) {
|
foreach ($messages as $message) {
|
||||||
@ -279,6 +279,7 @@ namespace Api\Mail {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private function runSearch($mbox, string $searchCriteria, ?\DateTime $lastSyncDateTime, array $messageIds, array &$messages) {
|
private function runSearch($mbox, string $searchCriteria, ?\DateTime $lastSyncDateTime, array $messageIds, array &$messages) {
|
||||||
|
|
||||||
$result = @imap_search($mbox, $searchCriteria);
|
$result = @imap_search($mbox, $searchCriteria);
|
||||||
if ($result === false) {
|
if ($result === false) {
|
||||||
$err = imap_last_error(); // might return false, if not messages were found, so we can just abort without throwing an error
|
$err = imap_last_error(); // might return false, if not messages were found, so we can just abort without throwing an error
|
||||||
@ -309,7 +310,9 @@ namespace Api\Mail {
|
|||||||
foreach ($structure->parts as $part) {
|
foreach ($structure->parts as $part) {
|
||||||
$disposition = (property_exists($part, "disposition") ? $part->disposition : null);
|
$disposition = (property_exists($part, "disposition") ? $part->disposition : null);
|
||||||
if ($disposition === "attachment") {
|
if ($disposition === "attachment") {
|
||||||
$fileName = array_filter($part->dparameters, function($param) { return $param->attribute === "filename"; });
|
$fileName = array_filter($part->dparameters, function ($param) {
|
||||||
|
return $param->attribute === "filename";
|
||||||
|
});
|
||||||
if (count($fileName) > 0) {
|
if (count($fileName) > 0) {
|
||||||
$attachments[] = $fileName[0]->value;
|
$attachments[] = $fileName[0]->value;
|
||||||
}
|
}
|
||||||
@ -320,7 +323,8 @@ namespace Api\Mail {
|
|||||||
$body = imap_fetchbody($mbox, $msgNo, "1");
|
$body = imap_fetchbody($mbox, $msgNo, "1");
|
||||||
$body = $this->parseBody($body);
|
$body = $this->parseBody($body);
|
||||||
|
|
||||||
$messages[] = [
|
if (!isset($messageId[$messageId])) {
|
||||||
|
$messages[$messageId] = [
|
||||||
"messageId" => $messageId,
|
"messageId" => $messageId,
|
||||||
"requestId" => $requestId,
|
"requestId" => $requestId,
|
||||||
"timestamp" => $date->getTimestamp(),
|
"timestamp" => $date->getTimestamp(),
|
||||||
@ -331,6 +335,7 @@ namespace Api\Mail {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
23
core/Driver/SQL/Expression/CaseWhen.class.php
Normal file
23
core/Driver/SQL/Expression/CaseWhen.class.php
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Driver\SQL\Expression;
|
||||||
|
|
||||||
|
use Driver\SQL\Condition\Condition;
|
||||||
|
|
||||||
|
class CaseWhen extends Expression {
|
||||||
|
|
||||||
|
private Condition $condition;
|
||||||
|
private $trueCase;
|
||||||
|
private $falseCase;
|
||||||
|
|
||||||
|
public function __construct(Condition $condition, $trueCase, $falseCase) {
|
||||||
|
$this->condition = $condition;
|
||||||
|
$this->trueCase = $trueCase;
|
||||||
|
$this->falseCase = $falseCase;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getCondition(): Condition { return $this->condition; }
|
||||||
|
public function getTrueCase() { return $this->trueCase; }
|
||||||
|
public function getFalseCase() { return $this->falseCase; }
|
||||||
|
|
||||||
|
}
|
20
core/Driver/SQL/Expression/Sum.class.php
Normal file
20
core/Driver/SQL/Expression/Sum.class.php
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Driver\SQL\Expression;
|
||||||
|
|
||||||
|
use Driver\SQL\Condition\Condition;
|
||||||
|
|
||||||
|
class Sum extends Expression {
|
||||||
|
|
||||||
|
private $value;
|
||||||
|
private string $alias;
|
||||||
|
|
||||||
|
public function __construct($value, string $alias) {
|
||||||
|
$this->value = $value;
|
||||||
|
$this->alias = $alias;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getValue() { return $this->value; }
|
||||||
|
public function getAlias(): string { return $this->alias; }
|
||||||
|
|
||||||
|
}
|
@ -290,7 +290,7 @@ class MySQL extends SQL {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function addValue($val, &$params = NULL) {
|
public function addValue($val, &$params = NULL, bool $unsafe = false) {
|
||||||
if ($val instanceof Keyword) {
|
if ($val instanceof Keyword) {
|
||||||
return $val->getValue();
|
return $val->getValue();
|
||||||
} else if ($val instanceof CurrentColumn) {
|
} else if ($val instanceof CurrentColumn) {
|
||||||
@ -299,11 +299,15 @@ class MySQL extends SQL {
|
|||||||
return $this->columnName($val->getName());
|
return $this->columnName($val->getName());
|
||||||
} else if ($val instanceof Expression) {
|
} else if ($val instanceof Expression) {
|
||||||
return $this->createExpression($val, $params);
|
return $this->createExpression($val, $params);
|
||||||
|
} else {
|
||||||
|
if ($unsafe) {
|
||||||
|
return $this->getUnsafeValue($val);
|
||||||
} else {
|
} else {
|
||||||
$params[] = $val;
|
$params[] = $val;
|
||||||
return "?";
|
return "?";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public function tableName($table): string {
|
public function tableName($table): string {
|
||||||
if (is_array($table)) {
|
if (is_array($table)) {
|
||||||
@ -403,7 +407,7 @@ class MySQL extends SQL {
|
|||||||
return $query;
|
return $query;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function createExpression(Expression $exp, array &$params) {
|
protected function createExpression(Expression $exp, array &$params): ?string {
|
||||||
if ($exp instanceof DateAdd || $exp instanceof DateSub) {
|
if ($exp instanceof DateAdd || $exp instanceof DateSub) {
|
||||||
$lhs = $this->addValue($exp->getLHS(), $params);
|
$lhs = $this->addValue($exp->getLHS(), $params);
|
||||||
$rhs = $this->addValue($exp->getRHS(), $params);
|
$rhs = $this->addValue($exp->getRHS(), $params);
|
||||||
|
@ -276,7 +276,7 @@ class PostgreSQL extends SQL {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function addValue($val, &$params = NULL) {
|
public function addValue($val, &$params = NULL, bool $unsafe = false) {
|
||||||
if ($val instanceof Keyword) {
|
if ($val instanceof Keyword) {
|
||||||
return $val->getValue();
|
return $val->getValue();
|
||||||
} else if ($val instanceof CurrentTable) {
|
} else if ($val instanceof CurrentTable) {
|
||||||
@ -287,11 +287,15 @@ class PostgreSQL extends SQL {
|
|||||||
return $this->columnName($val->getName());
|
return $this->columnName($val->getName());
|
||||||
} else if ($val instanceof Expression) {
|
} else if ($val instanceof Expression) {
|
||||||
return $this->createExpression($val, $params);
|
return $this->createExpression($val, $params);
|
||||||
|
} else {
|
||||||
|
if ($unsafe) {
|
||||||
|
return $this->getUnsafeValue($val);
|
||||||
} else {
|
} else {
|
||||||
$params[] = is_bool($val) ? ($val ? "TRUE" : "FALSE") : $val;
|
$params[] = is_bool($val) ? ($val ? "TRUE" : "FALSE") : $val;
|
||||||
return '$' . count($params);
|
return '$' . count($params);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public function tableName($table): string {
|
public function tableName($table): string {
|
||||||
if (is_array($table)) {
|
if (is_array($table)) {
|
||||||
@ -419,7 +423,7 @@ class PostgreSQL extends SQL {
|
|||||||
return $query;
|
return $query;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function createExpression(Expression $exp, array &$params) {
|
protected function createExpression(Expression $exp, array &$params): ?string {
|
||||||
if ($exp instanceof DateAdd || $exp instanceof DateSub) {
|
if ($exp instanceof DateAdd || $exp instanceof DateSub) {
|
||||||
$lhs = $this->addValue($exp->getLHS(), $params);
|
$lhs = $this->addValue($exp->getLHS(), $params);
|
||||||
$rhs = $this->addValue($exp->getRHS(), $params);
|
$rhs = $this->addValue($exp->getRHS(), $params);
|
||||||
|
@ -8,7 +8,7 @@ use Driver\SQL\SQL;
|
|||||||
|
|
||||||
class Select extends Query {
|
class Select extends Query {
|
||||||
|
|
||||||
private array $columns;
|
private array $selectValues;
|
||||||
private array $tables;
|
private array $tables;
|
||||||
private array $conditions;
|
private array $conditions;
|
||||||
private array $joins;
|
private array $joins;
|
||||||
@ -18,9 +18,9 @@ class Select extends Query {
|
|||||||
private int $limit;
|
private int $limit;
|
||||||
private int $offset;
|
private int $offset;
|
||||||
|
|
||||||
public function __construct($sql, ...$columns) {
|
public function __construct($sql, ...$selectValues) {
|
||||||
parent::__construct($sql);
|
parent::__construct($sql);
|
||||||
$this->columns = (!empty($columns) && is_array($columns[0])) ? $columns[0] : $columns;
|
$this->selectValues = (!empty($selectValues) && is_array($selectValues[0])) ? $selectValues[0] : $selectValues;
|
||||||
$this->tables = array();
|
$this->tables = array();
|
||||||
$this->conditions = array();
|
$this->conditions = array();
|
||||||
$this->joins = array();
|
$this->joins = array();
|
||||||
@ -85,7 +85,7 @@ class Select extends Query {
|
|||||||
return $this->sql->executeQuery($this, true);
|
return $this->sql->executeQuery($this, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getColumns(): array { return $this->columns; }
|
public function getSelectValues(): array { return $this->selectValues; }
|
||||||
public function getTables(): array { return $this->tables; }
|
public function getTables(): array { return $this->tables; }
|
||||||
public function getConditions(): array { return $this->conditions; }
|
public function getConditions(): array { return $this->conditions; }
|
||||||
public function getJoins(): array { return $this->joins; }
|
public function getJoins(): array { return $this->joins; }
|
||||||
@ -96,11 +96,21 @@ class Select extends Query {
|
|||||||
public function getGroupBy(): array { return $this->groupColumns; }
|
public function getGroupBy(): array { return $this->groupColumns; }
|
||||||
|
|
||||||
public function build(array &$params): ?string {
|
public function build(array &$params): ?string {
|
||||||
$columns = $this->sql->columnName($this->getColumns());
|
|
||||||
|
$selectValues = [];
|
||||||
|
foreach ($this->selectValues as $value) {
|
||||||
|
if (is_string($value)) {
|
||||||
|
$selectValues[] = $this->sql->columnName($value);
|
||||||
|
} else {
|
||||||
|
$selectValues[] = $this->sql->addValue($value, $params);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$tables = $this->getTables();
|
$tables = $this->getTables();
|
||||||
|
$selectValues = implode(",", $selectValues);
|
||||||
|
|
||||||
if (!$tables) {
|
if (!$tables) {
|
||||||
return "SELECT $columns";
|
return "SELECT $selectValues";
|
||||||
}
|
}
|
||||||
|
|
||||||
$tables = $this->sql->tableName($tables);
|
$tables = $this->sql->tableName($tables);
|
||||||
@ -135,6 +145,6 @@ class Select extends Query {
|
|||||||
|
|
||||||
$limit = ($this->getLimit() > 0 ? (" LIMIT " . $this->getLimit()) : "");
|
$limit = ($this->getLimit() > 0 ? (" LIMIT " . $this->getLimit()) : "");
|
||||||
$offset = ($this->getOffset() > 0 ? (" OFFSET " . $this->getOffset()) : "");
|
$offset = ($this->getOffset() > 0 ? (" OFFSET " . $this->getOffset()) : "");
|
||||||
return "SELECT $columns FROM $tables$joinStr$where$groupBy$orderBy$limit$offset";
|
return "SELECT $selectValues FROM $tables$joinStr$where$groupBy$orderBy$limit$offset";
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -15,8 +15,10 @@ use Driver\SQL\Constraint\Constraint;
|
|||||||
use \Driver\SQL\Constraint\Unique;
|
use \Driver\SQL\Constraint\Unique;
|
||||||
use \Driver\SQL\Constraint\PrimaryKey;
|
use \Driver\SQL\Constraint\PrimaryKey;
|
||||||
use \Driver\SQL\Constraint\ForeignKey;
|
use \Driver\SQL\Constraint\ForeignKey;
|
||||||
|
use Driver\SQL\Expression\CaseWhen;
|
||||||
use Driver\SQL\Expression\CurrentTimeStamp;
|
use Driver\SQL\Expression\CurrentTimeStamp;
|
||||||
use Driver\SQL\Expression\Expression;
|
use Driver\SQL\Expression\Expression;
|
||||||
|
use Driver\SQL\Expression\Sum;
|
||||||
use Driver\SQL\Query\AlterTable;
|
use Driver\SQL\Query\AlterTable;
|
||||||
use Driver\SQL\Query\CreateProcedure;
|
use Driver\SQL\Query\CreateProcedure;
|
||||||
use Driver\SQL\Query\CreateTable;
|
use Driver\SQL\Query\CreateTable;
|
||||||
@ -187,8 +189,10 @@ abstract class SQL {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected function getUnsafeValue($value): ?string {
|
protected function getUnsafeValue($value): ?string {
|
||||||
if (is_string($value) || is_numeric($value) || is_bool($value)) {
|
if (is_string($value)) {
|
||||||
return "'" . addslashes("$value") . "'"; // unsafe operation here...
|
return "'" . addslashes("$value") . "'"; // unsafe operation here...
|
||||||
|
} else if (is_numeric($value) || is_bool($value)) {
|
||||||
|
return $value;
|
||||||
} else if ($value instanceof Column) {
|
} else if ($value instanceof Column) {
|
||||||
return $this->columnName($value);
|
return $this->columnName($value);
|
||||||
} else if ($value === null) {
|
} else if ($value === null) {
|
||||||
@ -200,7 +204,7 @@ abstract class SQL {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected abstract function getValueDefinition($val);
|
protected abstract function getValueDefinition($val);
|
||||||
public abstract function addValue($val, &$params = NULL);
|
public abstract function addValue($val, &$params = NULL, bool $unsafe = false);
|
||||||
protected abstract function buildUnsafe(Query $statement): string;
|
protected abstract function buildUnsafe(Query $statement): string;
|
||||||
|
|
||||||
public abstract function tableName($table): string;
|
public abstract function tableName($table): string;
|
||||||
@ -222,12 +226,6 @@ abstract class SQL {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function sum($col): Keyword {
|
|
||||||
$sumCol = strtolower(str_replace(".","_", $col)) . "_sum";
|
|
||||||
$col = $this->columnName($col);
|
|
||||||
return new Keyword("SUM($col) AS $sumCol");
|
|
||||||
}
|
|
||||||
|
|
||||||
public function distinct($col): Keyword {
|
public function distinct($col): Keyword {
|
||||||
$col = $this->columnName($col);
|
$col = $this->columnName($col);
|
||||||
return new Keyword("DISTINCT($col)");
|
return new Keyword("DISTINCT($col)");
|
||||||
@ -312,11 +310,23 @@ abstract class SQL {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function createExpression(Expression $exp, array &$params) {
|
protected function createExpression(Expression $exp, array &$params): ?string {
|
||||||
if ($exp instanceof Column) {
|
if ($exp instanceof Column) {
|
||||||
return $this->columnName($exp);
|
return $this->columnName($exp);
|
||||||
} else if ($exp instanceof Query) {
|
} else if ($exp instanceof Query) {
|
||||||
return "(" . $exp->build($params) . ")";
|
return "(" . $exp->build($params) . ")";
|
||||||
|
} else if ($exp instanceof CaseWhen) {
|
||||||
|
$condition = $this->buildCondition($exp->getCondition(), $params);
|
||||||
|
|
||||||
|
// psql requires constant values here
|
||||||
|
$trueCase = $this->addValue($exp->getTrueCase(), $params, true);
|
||||||
|
$falseCase = $this->addValue($exp->getFalseCase(), $params, true);
|
||||||
|
|
||||||
|
return "CASE WHEN $condition THEN $trueCase ELSE $falseCase END";
|
||||||
|
} else if ($exp instanceof Sum) {
|
||||||
|
$value = $this->addValue($exp->getValue(), $params);
|
||||||
|
$alias = $exp->getAlias();
|
||||||
|
return "SUM($value) AS $alias";
|
||||||
} else {
|
} else {
|
||||||
$this->lastError = "Unsupported expression type: " . get_class($exp);
|
$this->lastError = "Unsupported expression type: " . get_class($exp);
|
||||||
return null;
|
return null;
|
||||||
|
Loading…
Reference in New Issue
Block a user