mirror of
https://github.com/Karaka-Management/phpOMS.git
synced 2026-01-14 19:18:41 +00:00
bug fixes
This commit is contained in:
parent
a7451d330d
commit
f84b33f7fa
2
.github/workflows/greetings.yml
vendored
2
.github/workflows/greetings.yml
vendored
|
|
@ -9,5 +9,5 @@ jobs:
|
|||
- uses: actions/first-interaction@v1
|
||||
with:
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
issue-message: 'Thank you for createing this issue. We will check it as soon as possible.'
|
||||
issue-message: 'Thank you for creating this issue. We will check it as soon as possible.'
|
||||
pr-message: 'Thank you for your pull request. We will check it as soon as possible.'
|
||||
|
|
|
|||
|
|
@ -392,9 +392,32 @@ class Account implements \JsonSerializable
|
|||
'permissions' => $this->permissions,
|
||||
'type' => $this->type,
|
||||
'status' => $this->status,
|
||||
'l11n' => $this->l11n,
|
||||
];
|
||||
}
|
||||
|
||||
public function from (array $account) : void
|
||||
{
|
||||
$this->id = $account['id'];
|
||||
$this->name1 = $account['name'][0];
|
||||
$this->name2 = $account['name'][1];
|
||||
$this->name3 = $account['name'][2];
|
||||
$this->email = $account['email'];
|
||||
$this->login = $account['login'];
|
||||
$this->type = $account['type'];
|
||||
$this->status = $account['status'];
|
||||
|
||||
$this->l11n = Localization::fromJson($account['l11n']);
|
||||
|
||||
foreach (($account['groups'] ?? []) as $group) {
|
||||
$this->groups[] = Group::fromJson($group);
|
||||
}
|
||||
|
||||
foreach (($account['permissions'] ?? []) as $permission) {
|
||||
$this->permissions[] = PermissionAbstract::fromJson($permission);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -109,6 +109,8 @@ class Group implements \JsonSerializable
|
|||
'description' => $this->description,
|
||||
'permissions' => $this->permissions,
|
||||
'members' => $this->members,
|
||||
'parents' => $this->parents,
|
||||
'status' => $this->status,
|
||||
];
|
||||
}
|
||||
|
||||
|
|
@ -127,4 +129,22 @@ class Group implements \JsonSerializable
|
|||
{
|
||||
return $this->toArray();
|
||||
}
|
||||
|
||||
public static function fromJson(array $group) : self
|
||||
{
|
||||
$new = new self();
|
||||
|
||||
$new->id = $group['id'];
|
||||
$new->name = $group['name'];
|
||||
$new->description = $group['description'];
|
||||
$new->members = $group['members'];
|
||||
$new->parents = $group['parents'];
|
||||
$new->status = $group['status'];
|
||||
|
||||
foreach (($group['permissions'] ?? []) as $permission) {
|
||||
$new->permissions[] = PermissionAbstract::fromJson($permission);
|
||||
}
|
||||
|
||||
return $new;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -360,7 +360,36 @@ class PermissionAbstract implements \JsonSerializable
|
|||
'category' => $this->category,
|
||||
'element' => $this->element,
|
||||
'component' => $this->component,
|
||||
'permission' => $this->getPermission(),
|
||||
'hasRead' => $this->hasRead,
|
||||
'hasModify' => $this->hasModify,
|
||||
'hasCreate' => $this->hasCreate,
|
||||
'hasDelete' => $this->hasDelete,
|
||||
'defaultCPermissions' => $this->defaultCPermissions,
|
||||
'hasPermission' => $this->hasPermission,
|
||||
'defaultPPermissions' => $this->defaultPPermissions,
|
||||
];
|
||||
}
|
||||
|
||||
public static function fromJson(array $permission) : self
|
||||
{
|
||||
$new = new self();
|
||||
|
||||
$new->id = $permission['id'];
|
||||
$new->unit = $permission['unit'];
|
||||
$new->app = $permission['app'];
|
||||
$new->module = $permission['module'];
|
||||
$new->from = $permission['from'];
|
||||
$new->category = $permission['category'];
|
||||
$new->element = $permission['element'];
|
||||
$new->component = $permission['component'];
|
||||
$new->hasRead = $permission['hasRead'];
|
||||
$new->hasModify = $permission['hasModify'];
|
||||
$new->hasCreate = $permission['hasCreate'];
|
||||
$new->hasDelete = $permission['hasDelete'];
|
||||
$new->defaultCPermissions = $permission['defaultCPermissions'];
|
||||
$new->hasPermission = $permission['hasPermission'];
|
||||
$new->defaultPPermissions = $permission['defaultPPermissions'];
|
||||
|
||||
return $new;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ declare(strict_types=1);
|
|||
|
||||
namespace phpOMS\DataStorage\Cache;
|
||||
|
||||
use phpOMS\DataStorage\Cache\Connection\ConnectionAbstract;
|
||||
use phpOMS\DataStorage\Cache\Connection\ConnectionFactory;
|
||||
use phpOMS\DataStorage\Cache\Connection\NullCache;
|
||||
use phpOMS\DataStorage\DataStorageConnectionInterface;
|
||||
|
|
@ -85,11 +86,11 @@ final class CachePool implements DataStoragePoolInterface
|
|||
*
|
||||
* @param string $key Cache to request
|
||||
*
|
||||
* @return DataStorageConnectionInterface
|
||||
* @return ConnectionAbstract
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function get(string $key = '') : DataStorageConnectionInterface
|
||||
public function get(string $key = '') : ConnectionAbstract
|
||||
{
|
||||
if ((!empty($key) && !isset($this->pool[$key])) || empty($this->pool)) {
|
||||
return new NullCache();
|
||||
|
|
|
|||
|
|
@ -53,9 +53,9 @@ class ConnectionFactory
|
|||
case CacheType::FILE:
|
||||
return new FileCache($cacheData['path'] ?? '');
|
||||
case CacheType::REDIS:
|
||||
return new RedisCache($cacheData['data'] ?? []);
|
||||
return new RedisCache($cacheData ?? []);
|
||||
case CacheType::MEMCACHED:
|
||||
return new MemCached($cacheData['data'] ?? []);
|
||||
return new MemCached($cacheData ?? []);
|
||||
default:
|
||||
throw new \InvalidArgumentException('Cache "' . ($cacheData['type'] ?? '') . '" is not supported.');
|
||||
}
|
||||
|
|
|
|||
|
|
@ -113,7 +113,7 @@ final class RedisCache extends ConnectionAbstract
|
|||
}
|
||||
|
||||
if ($expire > 0) {
|
||||
$this->con->setEx((string) $key, $expire, $this->build($value));
|
||||
$this->con->set((string) $key, $expire, $this->build($value));
|
||||
|
||||
return;
|
||||
}
|
||||
|
|
@ -131,10 +131,10 @@ final class RedisCache extends ConnectionAbstract
|
|||
}
|
||||
|
||||
if ($expire > 0) {
|
||||
return $this->con->setNx((string) $key, $this->build($value), $expire);
|
||||
return $this->con->set((string) $key, $this->build($value), $expire);
|
||||
}
|
||||
|
||||
return $this->con->setNx((string) $key, $this->build($value));
|
||||
return $this->con->set((string) $key, $this->build($value));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -35,6 +35,14 @@ abstract class BuilderAbstract
|
|||
*/
|
||||
protected bool $isReadOnly = false;
|
||||
|
||||
/**
|
||||
* Use prepared statement.
|
||||
*
|
||||
* @var bool
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public bool $usePreparedStmt = true;
|
||||
|
||||
/**
|
||||
* Database connection.
|
||||
*
|
||||
|
|
@ -59,6 +67,14 @@ abstract class BuilderAbstract
|
|||
*/
|
||||
public string $raw = '';
|
||||
|
||||
/**
|
||||
* Binds.
|
||||
*
|
||||
* @var array
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public array $binds = [];
|
||||
|
||||
/**
|
||||
* Get connection
|
||||
*
|
||||
|
|
@ -85,6 +101,27 @@ abstract class BuilderAbstract
|
|||
return $this->connection->con->quote($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Bind parameter.
|
||||
*
|
||||
* @param array $binds Binds
|
||||
* @param ?string $key Key
|
||||
*
|
||||
* @return Builder
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function bind(array $binds, ?string $key = null) : self
|
||||
{
|
||||
if ($key === null) {
|
||||
$this->binds[] = $binds;
|
||||
} else {
|
||||
$this->binds[$key] = $binds;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get query type.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -86,14 +86,14 @@ final class SQLiteConnection extends ConnectionAbstract
|
|||
$this->close();
|
||||
|
||||
try {
|
||||
if (!\is_file($this->dbdata['database'])) {
|
||||
throw new \PDOException();
|
||||
}
|
||||
|
||||
$this->con = new \PDO($this->dbdata['db'] . ':' . $this->dbdata['database']);
|
||||
$this->con->setAttribute(\PDO::ATTR_EMULATE_PREPARES, false);
|
||||
$this->con->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
|
||||
|
||||
if (!\is_file($this->dbdata['database'])) {
|
||||
throw new \PDOException();
|
||||
}
|
||||
|
||||
$this->status = DatabaseStatus::OK;
|
||||
} catch (\PDOException $_) {
|
||||
$this->con = new NullPDO();
|
||||
|
|
|
|||
|
|
@ -139,8 +139,9 @@ abstract class GrammarAbstract
|
|||
/**
|
||||
* Expressionize elements.
|
||||
*
|
||||
* @param array $elements Elements
|
||||
* @param bool $column Is column?
|
||||
* @param array $elements Elements
|
||||
* @param BuilderAbstract $query Builder
|
||||
* @param bool $column Is column?
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
|
|
@ -148,7 +149,7 @@ abstract class GrammarAbstract
|
|||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function expressionizeTableColumn(array $elements, bool $column = true) : string
|
||||
public function expressionizeTableColumn(array $elements, BuilderAbstract $query = null, bool $column = true) : string
|
||||
{
|
||||
$expression = '';
|
||||
|
||||
|
|
@ -160,6 +161,13 @@ abstract class GrammarAbstract
|
|||
$expression .= $element . ', ';
|
||||
} elseif ($element instanceof BuilderAbstract) {
|
||||
$expression .= $element->toSql() . (\is_string($key) ? ' AS ' . $key : '') . ', ';
|
||||
|
||||
if ($query->usePreparedStmt && $element->usePreparedStmt && $query !== null) {
|
||||
// If we have a subquery, we need to copy the binds over
|
||||
foreach ($element->binds as $bind) {
|
||||
$query->bind($bind);
|
||||
};
|
||||
}
|
||||
} elseif ($element instanceof \Closure) {
|
||||
$expression .= $element() . (\is_string($key) ? ' AS ' . $key : '') . ', ';
|
||||
} else {
|
||||
|
|
@ -219,6 +227,10 @@ abstract class GrammarAbstract
|
|||
/**
|
||||
* Compile value.
|
||||
*
|
||||
* If the query builder uses prepared statements it will use these prepared statements + data binds.
|
||||
* If the query builder doesn't use prepared statements but the setting usePreparedStmt is set to true
|
||||
* this function will try and convert every value that can be prepared to a prepared statement
|
||||
*
|
||||
* @param BuilderAbstract $query Query builder
|
||||
* @param mixed $value Value
|
||||
*
|
||||
|
|
@ -230,10 +242,23 @@ abstract class GrammarAbstract
|
|||
*/
|
||||
protected function compileValue(BuilderAbstract $query, mixed $value) : string
|
||||
{
|
||||
$compiled = '';
|
||||
$type = -1;
|
||||
|
||||
if (\is_string($value)) {
|
||||
return $query->quote($value);
|
||||
if ($query->usePreparedStmt) {
|
||||
$type = \PDO::PARAM_STR;
|
||||
$compiled = $value;
|
||||
} else {
|
||||
$compiled = $query->quote($value);
|
||||
}
|
||||
} elseif (\is_int($value)) {
|
||||
return (string) $value;
|
||||
if ($query->usePreparedStmt) {
|
||||
$type = \PDO::PARAM_INT;
|
||||
$compiled = $value;
|
||||
} else {
|
||||
$compiled = (string) $value;
|
||||
}
|
||||
} elseif (\is_array($value)) {
|
||||
$value = \array_values($value);
|
||||
$count = \count($value) - 1;
|
||||
|
|
@ -243,29 +268,65 @@ abstract class GrammarAbstract
|
|||
$values .= $this->compileValue($query, $value[$i]) . ', ';
|
||||
}
|
||||
|
||||
return $values . $this->compileValue($query, $value[$count]) . ')';
|
||||
} elseif ($value instanceof \DateTime || $value instanceof \DateTimeImmutable) {
|
||||
return $query->quote($value->format($this->datetimeFormat));
|
||||
$compiled = $values . $this->compileValue($query, $value[$count]) . ')';
|
||||
} elseif ($value instanceof \DateTimeInterface) {
|
||||
if ($query->usePreparedStmt) {
|
||||
$type = \PDO::PARAM_STR;
|
||||
$compiled = $value->format($this->datetimeFormat);
|
||||
} else {
|
||||
$compiled = $query->quote($value->format($this->datetimeFormat));
|
||||
}
|
||||
} elseif ($value === null) {
|
||||
return 'NULL';
|
||||
$compiled = 'NULL';
|
||||
} elseif (\is_bool($value)) {
|
||||
return (string) ((int) $value);
|
||||
if ($query->usePreparedStmt) {
|
||||
$type = \PDO::PARAM_BOOL;
|
||||
$compiled = $value;
|
||||
} else {
|
||||
$compiled = (string) ((int) $value);
|
||||
}
|
||||
} elseif (\is_float($value)) {
|
||||
return \rtrim(\rtrim(\number_format($value, 5, '.', ''), '0'), '.');
|
||||
$compiled = \rtrim(\rtrim(\number_format($value, 5, '.', ''), '0'), '.');
|
||||
} elseif ($value instanceof ColumnName) {
|
||||
return $this->compileSystem($value->name);
|
||||
$compiled = $this->compileSystem($value->name);
|
||||
} elseif ($value instanceof BuilderAbstract) {
|
||||
return '(' . \rtrim($value->toSql(), ';') . ')';
|
||||
$compiled = '(' . \rtrim($value->toSql(), ';') . ')';
|
||||
if ($query->usePreparedStmt && $value->usePreparedStmt) {
|
||||
$type = -2;
|
||||
}
|
||||
} elseif ($value instanceof \JsonSerializable) {
|
||||
$encoded = \json_encode($value);
|
||||
|
||||
return $encoded ? $encoded : 'NULL';
|
||||
if ($query->usePreparedStmt) {
|
||||
$type = $encoded ? \PDO::PARAM_STR : \PDO::PARAM_STR;
|
||||
$compiled = $encoded ? $value : null;
|
||||
} else {
|
||||
$compiled = $encoded ? $query->quote($encoded) : 'NULL';
|
||||
}
|
||||
} elseif ($value instanceof SerializableInterface) {
|
||||
return $value->serialize();
|
||||
$compiled = $value->serialize();
|
||||
} elseif ($value instanceof Parameter) {
|
||||
return $value->__toString();
|
||||
$compiled = $value->__toString();
|
||||
} else {
|
||||
throw new \InvalidArgumentException(\gettype($value));
|
||||
}
|
||||
|
||||
if ($query->usePreparedStmt && $type !== -1) {
|
||||
if ($type === -2) {
|
||||
// If we have a subquery, we need to copy the binds over
|
||||
foreach ($value->binds as $bind) {
|
||||
$query->bind($bind);
|
||||
}
|
||||
} else {
|
||||
$query->bind([
|
||||
'value' => $compiled,
|
||||
'type' => $type,
|
||||
]);
|
||||
|
||||
$compiled = '?';
|
||||
}
|
||||
}
|
||||
|
||||
return $compiled;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -102,10 +102,7 @@ final class DeleteMapper extends DataMapperAbstract
|
|||
->from($this->mapper::TABLE)
|
||||
->where($this->mapper::TABLE . '.' . $this->mapper::PRIMARYFIELD, '=', $objId);
|
||||
|
||||
$sth = $this->db->con->prepare($query->toSql());
|
||||
if ($sth !== false) {
|
||||
$sth->execute();
|
||||
}
|
||||
$query->execute();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -250,9 +247,6 @@ final class DeleteMapper extends DataMapperAbstract
|
|||
$relQuery->where($this->mapper::HAS_MANY[$member]['table'] . '.' . $this->mapper::HAS_MANY[$member]['external'], 'IN', $objIds);
|
||||
}
|
||||
|
||||
$sth = $this->db->con->prepare($relQuery->toSql());
|
||||
if ($sth !== false) {
|
||||
$sth->execute();
|
||||
}
|
||||
$relQuery->execute();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -347,9 +347,8 @@ final class ReadMapper extends DataMapperAbstract
|
|||
$results = false;
|
||||
|
||||
try {
|
||||
$sth = $this->db->con->prepare($query->toSql());
|
||||
if ($sth !== false) {
|
||||
$sth->execute();
|
||||
$sth = $query->execute();
|
||||
if ($sth !== null) {
|
||||
$results = $sth->fetchAll(\PDO::FETCH_ASSOC);
|
||||
}
|
||||
} catch (\Throwable $t) {
|
||||
|
|
@ -381,15 +380,13 @@ final class ReadMapper extends DataMapperAbstract
|
|||
$query ??= $this->getQuery();
|
||||
|
||||
try {
|
||||
$sth = $this->db->con->prepare($query->toSql());
|
||||
if ($sth === false) {
|
||||
$sth = $query->execute();
|
||||
if ($sth === null) {
|
||||
yield [];
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$sth->execute();
|
||||
|
||||
while ($row = $sth->fetch(\PDO::FETCH_ASSOC)) {
|
||||
yield $row;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -162,8 +162,8 @@ final class UpdateMapper extends DataMapperAbstract
|
|||
}
|
||||
}
|
||||
|
||||
$sth = $this->db->con->prepare($query->toSql());
|
||||
if ($sth === false) {
|
||||
$sth = $query->prepare();
|
||||
if ($sth === null) {
|
||||
throw new \Exception();
|
||||
}
|
||||
|
||||
|
|
@ -442,12 +442,11 @@ final class UpdateMapper extends DataMapperAbstract
|
|||
->on($many['table'] . '.' . $src, '=', $many['mapper']::TABLE . '.' . $many['mapper']::PRIMARYFIELD);
|
||||
}
|
||||
|
||||
$sth = $this->db->con->prepare($query->toSql());
|
||||
if ($sth === false) {
|
||||
$sth = $query->execute();
|
||||
if ($sth === null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$sth->execute();
|
||||
$result = $sth->fetchAll(\PDO::FETCH_COLUMN);
|
||||
|
||||
if ($result === false) {
|
||||
|
|
|
|||
|
|
@ -162,8 +162,8 @@ final class WriteMapper extends DataMapperAbstract
|
|||
$query->insert($this->mapper::PRIMARYFIELD)->value(0);
|
||||
}
|
||||
|
||||
$sth = $this->db->con->prepare($query->toSql());
|
||||
if ($sth === false) {
|
||||
$sth = $query->prepare();
|
||||
if ($sth === null) {
|
||||
throw new \Exception();
|
||||
}
|
||||
|
||||
|
|
@ -438,8 +438,8 @@ final class WriteMapper extends DataMapperAbstract
|
|||
$relQuery->values($src, $objId);
|
||||
}
|
||||
|
||||
$sth = $this->db->con->prepare($relQuery->toSql());
|
||||
if ($sth === false) {
|
||||
$sth = $relQuery->prepare();
|
||||
if ($sth === null) {
|
||||
throw new \Exception();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -189,14 +189,6 @@ class Builder extends BuilderAbstract
|
|||
*/
|
||||
public ?int $offset = null;
|
||||
|
||||
/**
|
||||
* Binds.
|
||||
*
|
||||
* @var array
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private array $binds = [];
|
||||
|
||||
/**
|
||||
* Union.
|
||||
*
|
||||
|
|
@ -341,26 +333,6 @@ class Builder extends BuilderAbstract
|
|||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Bind parameter.
|
||||
*
|
||||
* @param string|array $binds Binds
|
||||
*
|
||||
* @return Builder
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function bind(string | array $binds) : self
|
||||
{
|
||||
if (\is_array($binds)) {
|
||||
$this->binds += $binds;
|
||||
} else {
|
||||
$this->binds[] = $binds;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
|
|
@ -1373,6 +1345,42 @@ class Builder extends BuilderAbstract
|
|||
* {@inheritdoc}
|
||||
*/
|
||||
public function execute() : ?\PDOStatement
|
||||
{
|
||||
$sth = null;
|
||||
try {
|
||||
$sth = $this->prepare();
|
||||
if ($sth !== null) {
|
||||
$sth->execute();
|
||||
}
|
||||
} catch (\Throwable $t) {
|
||||
// @codeCoverageIgnoreStart
|
||||
\phpOMS\Log\FileLogger::getInstance()->error(
|
||||
\phpOMS\Log\FileLogger::MSG_FULL, [
|
||||
'message' => $t->getMessage() . ':' . $this->toSql(),
|
||||
'line' => __LINE__,
|
||||
'file' => self::class,
|
||||
]
|
||||
);
|
||||
|
||||
\phpOMS\Log\FileLogger::getInstance()->error(
|
||||
\phpOMS\Log\FileLogger::MSG_FULL, [
|
||||
'message' => \json_encode($this->binds),
|
||||
'line' => __LINE__,
|
||||
'file' => self::class,
|
||||
]
|
||||
);
|
||||
|
||||
$sth = null;
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
|
||||
return $sth;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function prepare() : ?\PDOStatement
|
||||
{
|
||||
$sth = null;
|
||||
$sql = '';
|
||||
|
|
@ -1384,12 +1392,12 @@ class Builder extends BuilderAbstract
|
|||
}
|
||||
|
||||
foreach ($this->binds as $key => $bind) {
|
||||
$type = self::getBindParamType($bind);
|
||||
if (!isset($bind['type'])) {
|
||||
$bind['type'] = self::getBindParamType($bind['value']);
|
||||
}
|
||||
|
||||
$sth->bindParam($key, $bind, $type);
|
||||
$sth->bindParam(\is_int($key) ? $key + 1 : $key, $bind['value'], $bind['type']);
|
||||
}
|
||||
|
||||
$sth->execute();
|
||||
} catch (\Throwable $t) {
|
||||
// @codeCoverageIgnoreStart
|
||||
\phpOMS\Log\FileLogger::getInstance()->error(
|
||||
|
|
@ -1400,6 +1408,14 @@ class Builder extends BuilderAbstract
|
|||
]
|
||||
);
|
||||
|
||||
\phpOMS\Log\FileLogger::getInstance()->error(
|
||||
\phpOMS\Log\FileLogger::MSG_FULL, [
|
||||
'message' => \json_encode($this->binds),
|
||||
'line' => __LINE__,
|
||||
'file' => self::class,
|
||||
]
|
||||
);
|
||||
|
||||
$sth = null;
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
|
|
@ -1447,7 +1463,12 @@ class Builder extends BuilderAbstract
|
|||
} elseif ($column instanceof SerializableInterface) {
|
||||
return $column->serialize();
|
||||
} elseif ($column instanceof self) {
|
||||
return \md5($column->toSql());
|
||||
$tmp = $column->usePreparedStmt;
|
||||
$column->usePreparedStmt = false;
|
||||
$hash = \md5($column->toSql());
|
||||
$column->usePreparedStmt = $tmp;
|
||||
|
||||
return $hash;
|
||||
}
|
||||
|
||||
throw new \Exception();
|
||||
|
|
|
|||
|
|
@ -156,7 +156,7 @@ class Grammar extends GrammarAbstract
|
|||
*/
|
||||
protected function compileSelects(Builder $query, array $columns) : string
|
||||
{
|
||||
$expression = $this->expressionizeTableColumn($columns, false);
|
||||
$expression = $this->expressionizeTableColumn($columns, $query, false);
|
||||
|
||||
if ($expression === '') {
|
||||
$expression = '*';
|
||||
|
|
@ -207,7 +207,7 @@ class Grammar extends GrammarAbstract
|
|||
*/
|
||||
protected function compileUpdates(Builder $query, array $table) : string
|
||||
{
|
||||
$expression = $this->expressionizeTableColumn($table);
|
||||
$expression = $this->expressionizeTableColumn($table, $query);
|
||||
|
||||
if ($expression === '') {
|
||||
return '';
|
||||
|
|
@ -243,7 +243,7 @@ class Grammar extends GrammarAbstract
|
|||
*/
|
||||
protected function compileFrom(Builder $query, array $table) : string
|
||||
{
|
||||
$expression = $this->expressionizeTableColumn($table);
|
||||
$expression = $this->expressionizeTableColumn($table, $query);
|
||||
|
||||
if ($expression === '') {
|
||||
return '';
|
||||
|
|
@ -265,76 +265,73 @@ class Grammar extends GrammarAbstract
|
|||
*/
|
||||
public function compileWheres(Builder $query, array $wheres, bool $first = true) : string
|
||||
{
|
||||
$expression = '';
|
||||
$outer = '';
|
||||
|
||||
foreach ($wheres as $where) {
|
||||
foreach ($where as $element) {
|
||||
$expression .= $this->compileWhereElement($element, $query, $first);
|
||||
$first = false;
|
||||
$expression = '';
|
||||
$prefix = '';
|
||||
|
||||
if (!$first) {
|
||||
$prefix = ' ' . \strtoupper($element['boolean']) . ' ';
|
||||
}
|
||||
|
||||
if (\is_string($element['column'])) {
|
||||
$expression .= $this->compileSystem($element['column']);
|
||||
} elseif ($element['column'] instanceof Builder) {
|
||||
$expression .= '(' . \rtrim($element['column']->toSql(), ';') . ')';
|
||||
|
||||
if ($query->usePreparedStmt && $element['column']->usePreparedStmt) {
|
||||
// If we have a subquery, we need to copy the binds over
|
||||
// BUT we are only allowed to do this once per wheres builder
|
||||
foreach ($element['column']->binds as $bind) {
|
||||
$query->bind($bind);
|
||||
};
|
||||
}
|
||||
} elseif ($element['column'] instanceof \Closure) {
|
||||
$expression .= $element['column']();
|
||||
}
|
||||
|
||||
// Handle null for IN (...)
|
||||
// This is not allowed and must be written as (IN (...) OR IS NULL)
|
||||
$isArray = \is_array($element['value']);
|
||||
$hasNull = false;
|
||||
if ($isArray && ($key = \array_search(null, $element['value'], true)) !== false) {
|
||||
$hasNull = true;
|
||||
unset($element['value'][$key]);
|
||||
|
||||
if (empty($element['value'])) {
|
||||
$element['operator'] = '=';
|
||||
$element['value'] = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($element['value']) && (!empty($element['value']) || !$isArray)) {
|
||||
if ($isArray && \count($element['value']) === 1) {
|
||||
$element['value'] = \reset($element['value']);
|
||||
$element['operator'] = '=';
|
||||
}
|
||||
|
||||
$expression .= ' ' . \strtoupper($element['operator']) . ' ' . $this->compileValue($query, $element['value']);
|
||||
|
||||
if ($hasNull) {
|
||||
$expression = '(' . $expression . ' OR ' . $this->compileSystem($element['column']) . ' IS NULL)';
|
||||
}
|
||||
} elseif ($element['value'] === null && !($element['column'] instanceof Builder)) {
|
||||
$operator = $element['operator'] === '=' ? 'IS' : 'IS NOT';
|
||||
$expression .= ' ' . $operator . ' ' . $this->compileValue($query, $element['value']);
|
||||
}
|
||||
|
||||
$outer .= $prefix . $expression;
|
||||
$first = false;
|
||||
}
|
||||
}
|
||||
|
||||
if ($expression === '') {
|
||||
if ($outer === '') {
|
||||
return '';
|
||||
}
|
||||
|
||||
return 'WHERE ' . $expression;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile where element.
|
||||
*
|
||||
* @param array $element Element data
|
||||
* @param Builder $query Query builder
|
||||
* @param bool $first Is first element (useful for nesting)
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
protected function compileWhereElement(array $element, Builder $query, bool $first = true) : string
|
||||
{
|
||||
$expression = '';
|
||||
$prefix = '';
|
||||
|
||||
if (!$first) {
|
||||
$prefix = ' ' . \strtoupper($element['boolean']) . ' ';
|
||||
}
|
||||
|
||||
if (\is_string($element['column'])) {
|
||||
$expression .= $this->compileSystem($element['column']);
|
||||
} elseif ($element['column'] instanceof Builder) {
|
||||
$expression .= '(' . \rtrim($element['column']->toSql(), ';') . ')';
|
||||
} elseif ($element['column'] instanceof \Closure) {
|
||||
$expression .= $element['column']();
|
||||
}
|
||||
|
||||
// Handle null for IN (...)
|
||||
// This is not allowed and must be written as (IN (...) OR IS NULL)
|
||||
$isArray = \is_array($element['value']);
|
||||
$hasNull = false;
|
||||
if ($isArray && ($key = \array_search(null, $element['value'], true)) !== false) {
|
||||
$hasNull = true;
|
||||
unset($element['value'][$key]);
|
||||
|
||||
if (empty($element['value'])) {
|
||||
$element['operator'] = '=';
|
||||
$element['value'] = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($element['value']) && (!empty($element['value']) || !$isArray)) {
|
||||
$expression .= ' ' . \strtoupper($element['operator']) . ' ' . $this->compileValue($query, $element['value']);
|
||||
|
||||
if ($hasNull) {
|
||||
$expression = '(' . $expression . ' OR ' . $this->compileSystem($element['column']) . ' IS NULL)';
|
||||
}
|
||||
} elseif ($element['value'] === null && !($element['column'] instanceof Builder)) {
|
||||
$operator = $element['operator'] === '=' ? 'IS' : 'IS NOT';
|
||||
$expression .= ' ' . $operator . ' ' . $this->compileValue($query, $element['value']);
|
||||
}
|
||||
|
||||
return $prefix . $expression;
|
||||
return 'WHERE ' . $outer;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -349,6 +346,16 @@ class Grammar extends GrammarAbstract
|
|||
*/
|
||||
protected function compileLimit(Builder $query, int $limit) : string
|
||||
{
|
||||
if ($query->usePreparedStmt) {
|
||||
|
||||
$query->bind([
|
||||
'value' => $limit,
|
||||
'type' => \PDO::PARAM_INT,
|
||||
]);
|
||||
|
||||
$limit = '?';
|
||||
}
|
||||
|
||||
return 'LIMIT ' . $limit;
|
||||
}
|
||||
|
||||
|
|
@ -364,6 +371,16 @@ class Grammar extends GrammarAbstract
|
|||
*/
|
||||
protected function compileOffset(Builder $query, int $offset) : string
|
||||
{
|
||||
if ($query->usePreparedStmt) {
|
||||
|
||||
$query->bind([
|
||||
'value' => $offset,
|
||||
'type' => \PDO::PARAM_INT,
|
||||
]);
|
||||
|
||||
$offset = '?';
|
||||
}
|
||||
|
||||
return 'OFFSET ' . $offset;
|
||||
}
|
||||
|
||||
|
|
@ -390,6 +407,13 @@ class Grammar extends GrammarAbstract
|
|||
$expression .= $join['table']() . (\is_string($join['alias']) ? ' as ' . $join['alias'] : '');
|
||||
} elseif ($join['table'] instanceof Builder) {
|
||||
$expression .= '(' . \rtrim($join['table']->toSql(), ';') . ')' . (\is_string($join['alias']) ? ' as ' . $join['alias'] : '');
|
||||
|
||||
if ($query->usePreparedStmt && $join['table']->usePreparedStmt) {
|
||||
// If we have a subquery, we need to copy the binds over
|
||||
foreach ($join['table']->binds as $bind) {
|
||||
$query->bind($bind);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
$expression .= $this->compileOn($query, $query->ons[$join['alias'] ?? $table]) . ' ';
|
||||
|
|
@ -453,13 +477,20 @@ class Grammar extends GrammarAbstract
|
|||
$expression .= $this->compileSystem($element['column']);
|
||||
} elseif ($element['column'] instanceof Builder) {
|
||||
$expression .= '(' . $element['column']->toSql() . ')';
|
||||
|
||||
if ($query->usePreparedStmt && $element['column']->usePreparedStmt) {
|
||||
// If we have a subquery, we need to copy the binds over
|
||||
foreach ($element['column']->binds as $bind) {
|
||||
$query->bind($bind);
|
||||
};
|
||||
}
|
||||
} elseif ($element['column'] instanceof \Closure) {
|
||||
$expression .= $element['column']();
|
||||
}
|
||||
|
||||
// @bug The on part of a join doesn't allow string values because they conflict with column name
|
||||
// Other data types are possible because they don't conflict with the data type of columns (string)
|
||||
// Consider to create a ColumnName() class.
|
||||
// Consider to create a ColumnName() class or maybe StringValue() since we use string values less often.
|
||||
// https://github.com/Karaka-Management/phpOMS/issues/369
|
||||
if (isset($element['value'])) {
|
||||
$expression .= ' ' . \strtoupper($element['operator']) . ' '
|
||||
|
|
@ -628,7 +659,7 @@ class Grammar extends GrammarAbstract
|
|||
$vals = '';
|
||||
|
||||
foreach ($values as $column => $value) {
|
||||
$expression = $this->expressionizeTableColumn([$column], false);
|
||||
$expression = $this->expressionizeTableColumn([$column], $query, false);
|
||||
|
||||
$vals .= $expression . ' = ' . $this->compileValue($query, $value) . ', ';
|
||||
}
|
||||
|
|
|
|||
|
|
@ -120,6 +120,12 @@ class Builder extends BuilderAbstract
|
|||
*/
|
||||
public array $alterAdd = [];
|
||||
|
||||
/**
|
||||
* Has post query to run.
|
||||
*
|
||||
* @var bool
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public bool $hasPostQuery = false;
|
||||
|
||||
/**
|
||||
|
|
@ -151,6 +157,32 @@ class Builder extends BuilderAbstract
|
|||
$this->grammar = $connection->getSchemaGrammar();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the column type from a variable value.
|
||||
*
|
||||
* @param mixed $value Variable value
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static function getTypeFromVariable(mixed $value) : string
|
||||
{
|
||||
if (\is_string($value)) {
|
||||
return 'TEXT';
|
||||
} elseif (\is_int($value)) {
|
||||
return 'INT';
|
||||
} elseif (\is_bool($value)) {
|
||||
return 'TINYINT(1)';
|
||||
} elseif (\is_float($value)) {
|
||||
return 'DECIMAL(10,6)';
|
||||
} elseif ($value instanceof \DateTimeInterface) {
|
||||
return 'DATETIME';
|
||||
}
|
||||
|
||||
return 'TEXT';
|
||||
}
|
||||
|
||||
/**
|
||||
* Create schema builder from schema definition.
|
||||
*
|
||||
|
|
@ -168,6 +200,7 @@ class Builder extends BuilderAbstract
|
|||
public static function createFromSchema(array $definition, ConnectionAbstract $connection) : self
|
||||
{
|
||||
$builder = new self($connection);
|
||||
$builder->usePreparedStmt = false;
|
||||
$builder->createTable($definition['name'] ?? '');
|
||||
|
||||
foreach ($definition['fields'] as $name => $def) {
|
||||
|
|
|
|||
|
|
@ -129,14 +129,14 @@ class SQLiteGrammar extends Grammar
|
|||
$fieldQuery .= ' ' . ($field['null'] ? '' : 'NOT ') . 'NULL';
|
||||
}
|
||||
|
||||
if ($field['autoincrement'] ?? false) {
|
||||
$fieldQuery .= ' AUTOINCREMENT';
|
||||
}
|
||||
|
||||
if ($field['primary'] ?? false) {
|
||||
$fieldQuery .= ' PRIMARY KEY';
|
||||
}
|
||||
|
||||
if ($field['autoincrement'] ?? false) {
|
||||
$fieldQuery .= ' AUTOINCREMENT';
|
||||
}
|
||||
|
||||
$fieldQuery .= ',';
|
||||
|
||||
if ($field['unique'] ?? false) {
|
||||
|
|
|
|||
|
|
@ -512,7 +512,9 @@ final class HttpRequest extends RequestAbstract
|
|||
{
|
||||
$useragent = $_SERVER['HTTP_USER_AGENT'] ?? '';
|
||||
|
||||
if (\preg_match('/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i', $useragent) || \preg_match('/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i', $useragent)) {
|
||||
if (\preg_match('/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i', $useragent)
|
||||
|| \preg_match('/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i', $useragent)
|
||||
) {
|
||||
return true; // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1783,7 +1783,7 @@ class Email
|
|||
$lookBack = 0;
|
||||
|
||||
do {
|
||||
$offset = $avgLength - $lookBack;
|
||||
$offset = (int) ($avgLength - $lookBack);
|
||||
$chunk = \mb_substr($str, $i, $offset, $this->charset);
|
||||
$chunk = \base64_encode($chunk);
|
||||
++$lookBack;
|
||||
|
|
|
|||
|
|
@ -526,6 +526,39 @@ abstract class ModuleAbstract
|
|||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Create duplicate model create response.
|
||||
*
|
||||
* The response object contains the following data:
|
||||
*
|
||||
* * status = Response status
|
||||
* * title = Response title (e.g. for frontend reporting)
|
||||
* * message = Response message (e.g. for frontend reporting)
|
||||
* * response = Response object (e.g. for validation/frontend reporting/form validation)
|
||||
*
|
||||
* @param RequestAbstract $request Request
|
||||
* @param ResponseAbstract $response Response
|
||||
* @param mixed $obj Response object
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function createDuplicateCreateResponse(
|
||||
RequestAbstract $request,
|
||||
ResponseAbstract $response,
|
||||
mixed $obj
|
||||
) : void
|
||||
{
|
||||
$response->header->set('Content-Type', MimeType::M_JSON . '; charset=utf-8', true);
|
||||
$response->data[$request->uri->__toString()] = [
|
||||
'status' => NotificationLevel::WARNING,
|
||||
'title' => '',
|
||||
'message' => $this->app->l11nManager->getText($response->header->l11n->language, '0', '0', 'DuplicateCreate'),
|
||||
'response' => $obj,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Create invalid model update response.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -117,11 +117,15 @@ final class Guard
|
|||
|
||||
public static function isSafeFile(string $path) : bool
|
||||
{
|
||||
if (!\str_ends_with($path, '.exe') && !self::isSafeNoneExecutable($path)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$tmp = \strtolower($path);
|
||||
if (\str_ends_with($tmp, '.csv')) {
|
||||
return self::isSafeXml($path);
|
||||
} elseif (\str_ends_with($tmp, '.xml')) {
|
||||
return self::isSafeCsv($path);
|
||||
} elseif (\str_ends_with($tmp, '.xml')) {
|
||||
return self::isSafeXml($path);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
@ -175,13 +179,15 @@ final class Guard
|
|||
return true;
|
||||
}
|
||||
|
||||
static $specialChars = ['=', '+', '-', '@'];
|
||||
|
||||
while (($row = \fgetcsv($input)) !== false) {
|
||||
foreach ($row as &$cell) {
|
||||
if (\preg_match('/^[\x00-\x08\x0B\x0C\x0E-\x1F]+/', $cell) !== false) {
|
||||
if (\preg_match('/^[\x00-\x08\x0B\x0C\x0E-\x1F]+/', $cell) === 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (\in_array($cell[0] ?? '', ['=', '+', '-', '@'])) {
|
||||
if (\in_array($cell[0] ?? '', $specialChars)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -191,4 +197,32 @@ final class Guard
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function isSafeNoneExecutable(string $path) : bool
|
||||
{
|
||||
$input = \fopen($path, 'r');
|
||||
if (!$input) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static $specialSignatures = [
|
||||
"\x4D\x5A",
|
||||
"\x7F\x45\x4C\x46",
|
||||
];
|
||||
|
||||
$line = \fgets($input, 256);
|
||||
\fclose($input);
|
||||
|
||||
if ($line === false) {
|
||||
return true;
|
||||
}
|
||||
|
||||
foreach ($specialSignatures as $sig) {
|
||||
if (\mb_stripos($line, $sig) !== false) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -62,11 +62,24 @@ class Address extends Location
|
|||
public function toArray() : array
|
||||
{
|
||||
return \array_merge(
|
||||
parent::toArray(),
|
||||
[
|
||||
'id' => $this->id,
|
||||
'name' => $this->name,
|
||||
'fao' => $this->fao,
|
||||
],
|
||||
parent::toArray()
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
public static function fromJson(array $address) : self
|
||||
{
|
||||
$new = new self();
|
||||
$new->from($address);
|
||||
|
||||
$new->id = $address['id'];
|
||||
$new->name = $address['name'];
|
||||
$new->fao = $address['fao'];
|
||||
|
||||
return $new;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -372,6 +372,19 @@ class FloatInt implements SerializableInterface
|
|||
$this->setInt((int) $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function jsonSerialize() : mixed
|
||||
{
|
||||
return \json_encode($this->getInt());
|
||||
}
|
||||
|
||||
public static function fromJson(string $json) : self
|
||||
{
|
||||
return new self((int) $json);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set money value.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -157,6 +157,8 @@ class Location implements \JsonSerializable, SerializableInterface
|
|||
public function toArray() : array
|
||||
{
|
||||
return [
|
||||
'id' => $this->id,
|
||||
'type' => $this->type,
|
||||
'postal' => $this->postal,
|
||||
'city' => $this->city,
|
||||
'country' => $this->country,
|
||||
|
|
@ -167,6 +169,19 @@ class Location implements \JsonSerializable, SerializableInterface
|
|||
];
|
||||
}
|
||||
|
||||
public function from(array $location) : void
|
||||
{
|
||||
$this->id = $location['id'];
|
||||
$this->type = $location['type'];
|
||||
$this->postal = $location['postal'];
|
||||
$this->city = $location['city'];
|
||||
$this->country = $location['country'];
|
||||
$this->address = $location['address'];
|
||||
$this->state = $location['state'];
|
||||
$this->lat = $location['lat'];
|
||||
$this->lon = $location['lon'];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
|
|
|
|||
170
System/File/SearchUtils.php
Normal file
170
System/File/SearchUtils.php
Normal file
|
|
@ -0,0 +1,170 @@
|
|||
<?php
|
||||
/**
|
||||
* Jingga
|
||||
*
|
||||
* PHP Version 8.2
|
||||
*
|
||||
* @package phpOMS\System\File
|
||||
* @copyright Dennis Eichhorn
|
||||
* @license OMS License 2.0
|
||||
* @version 1.0.0
|
||||
* @link https://jingga.app
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace phpOMS\System\File;
|
||||
|
||||
/**
|
||||
* Path exception class.
|
||||
*
|
||||
* @package phpOMS\System\File
|
||||
* @license OMS License 2.0
|
||||
* @link https://jingga.app
|
||||
* @since 1.0.0
|
||||
*/
|
||||
final class SearchUtils
|
||||
{
|
||||
public static function findInFile(string $path, array $keywords, int $distance = 500) : array
|
||||
{
|
||||
$fp = \fopen($path, "r");
|
||||
if ($fp === false) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$positions = [];
|
||||
|
||||
$globalPos = 0;
|
||||
|
||||
while (!\feof($fp)) {
|
||||
$line = \fgets($fp);
|
||||
|
||||
foreach ($keywords as $keyword) {
|
||||
$pos = \stripos($line, $keyword);
|
||||
if ($pos === false) {
|
||||
continue;
|
||||
}
|
||||
|
||||
while ($pos !== false) {
|
||||
$positions[$keyword][] = $globalPos + $pos;
|
||||
|
||||
$pos = \stripos($line, $keyword, $pos + 1);
|
||||
}
|
||||
}
|
||||
|
||||
$globalPos += \strlen($line);
|
||||
}
|
||||
|
||||
\fclose($fp);
|
||||
|
||||
if (empty($positions) || \count($keywords) !== \count($positions)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$start = \reset($keywords);
|
||||
$distances = [];
|
||||
|
||||
foreach ($positions[$start] as $pos) {
|
||||
if ($pos < 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$distance = [
|
||||
'start' => $pos,
|
||||
'end' => $pos,
|
||||
'distance' => 0,
|
||||
];
|
||||
|
||||
foreach ($positions as $keyword => $found) {
|
||||
$closestStart = null;
|
||||
$closestEnd = null;
|
||||
$inBetween = null;
|
||||
|
||||
foreach ($found as $pos2) {
|
||||
if ($pos2 < 0) {
|
||||
continue 2;
|
||||
}
|
||||
|
||||
if ($pos2 >= $distance['start'] && $pos2 <= $distance['end']) {
|
||||
$inBetween = $pos2;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if ($closestStart === null
|
||||
|| \abs($pos2 - $distance['start']) < \abs($closestStart - $distance['start'])
|
||||
) {
|
||||
$closestStart = $pos2;
|
||||
}
|
||||
|
||||
if ($closestEnd === null
|
||||
|| \abs($pos2 - $distance['end']) < \abs($closestEnd - $distance['end'])
|
||||
) {
|
||||
$closestEnd = $pos2;
|
||||
}
|
||||
}
|
||||
|
||||
// The following is only perfect for inBetween
|
||||
// For the other cases there could be a scenario where the closer value is actually bad
|
||||
// because for the next keyword the farther one would be inBetween
|
||||
if ($inBetween !== null) {
|
||||
continue; // Perfect
|
||||
} elseif ($closestStart < $distance['start']
|
||||
&& (\abs($closestStart - $distance['start']) <= \abs($closestEnd - $distance['end']) || $closestEnd > $distance['end'])) {
|
||||
$distance['start'] = \min($distance['start'], $closestStart);
|
||||
} else {
|
||||
$distance['end'] = \max($distance['end'], $closestEnd);
|
||||
}
|
||||
}
|
||||
|
||||
$distance['distance'] = $distance['end'] - $distance['start'];
|
||||
$distances[] = $distance;
|
||||
}
|
||||
|
||||
if (empty($distances)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
\uasort($distances, function (array $a, array $b) {
|
||||
return $a['distance'] <=> $b['distance'];
|
||||
});
|
||||
|
||||
return $distances;
|
||||
}
|
||||
|
||||
public static function getTextExtract(string $path, int $pos, string $start, string $end) : string
|
||||
{
|
||||
$fp = \fopen($path, "r");
|
||||
if ($fp === false) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$startPos = -1;
|
||||
while (($line = \fgets($fp)) !== false && \ftell($fp) < $pos) {
|
||||
if (\stripos($line, $start) !== false) {
|
||||
$startPos = \ftell($fp);
|
||||
}
|
||||
}
|
||||
|
||||
\fseek($fp, $pos);
|
||||
|
||||
$endPos = -1;
|
||||
while (($line = \fgets($fp)) !== false) {
|
||||
if (\stripos($line, $end) !== false) {
|
||||
$endPos = \ftell($fp);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($startPos < 0 || $endPos < 0) {
|
||||
\fclose($fp);
|
||||
return '';
|
||||
}
|
||||
|
||||
\fseek($fp, $startPos);
|
||||
$extract = \fread($fp, $endPos - $startPos);
|
||||
|
||||
\fclose($fp);
|
||||
|
||||
return $extract;
|
||||
}
|
||||
}
|
||||
|
|
@ -196,7 +196,7 @@ final class UriFactory
|
|||
{
|
||||
$success = false;
|
||||
|
||||
foreach (self::$uri as $key => $value) {
|
||||
foreach (self::$uri as $key => $_) {
|
||||
if (((bool) \preg_match('~^' . $pattern . '$~', $key))) {
|
||||
unset(self::$uri[$key]);
|
||||
$success = true;
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ namespace phpOMS\Utils\IO\Csv;
|
|||
|
||||
use phpOMS\DataStorage\Database\Connection\ConnectionAbstract;
|
||||
use phpOMS\DataStorage\Database\Query\Builder;
|
||||
use phpOMS\DataStorage\Database\Schema\Builder as SchemaBuilder;
|
||||
use phpOMS\Utils\IO\IODatabaseMapper;
|
||||
|
||||
/**
|
||||
|
|
@ -36,58 +37,60 @@ final class CsvDatabaseMapper implements IODatabaseMapper
|
|||
*/
|
||||
private ConnectionAbstract $con;
|
||||
|
||||
/**
|
||||
* Path to source or destination
|
||||
*
|
||||
* @var string
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private string $path = '';
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param ConnectionAbstract $con Database connection
|
||||
* @param string $path File path
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function __construct(ConnectionAbstract $con, string $path)
|
||||
public function __construct(ConnectionAbstract $con)
|
||||
{
|
||||
$this->con = $con;
|
||||
$this->path = $path;
|
||||
$this->con = $con;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function insert() : void
|
||||
public function createSchema(string $path, string $table = '') : void
|
||||
{
|
||||
$fp = \fopen($this->path, 'r');
|
||||
$fp = \fopen($path, 'r');
|
||||
if ($fp === false) {
|
||||
return;
|
||||
}
|
||||
|
||||
$table = \basename($this->path, '.csv');
|
||||
$table = \strtr(empty($table) ? \basename($path, '.csv') : $table, ' ', '_');
|
||||
$titles = [];
|
||||
|
||||
$delim = CsvSettings::getFileDelimiter($fp, 2);
|
||||
|
||||
// get column titles
|
||||
$titles = \fgetcsv($fp, 4096);
|
||||
$titles = \fgetcsv($fp, 4096, $delim);
|
||||
if ($titles === false) {
|
||||
\fclose($fp);
|
||||
return;
|
||||
}
|
||||
|
||||
$columns = \count($titles);
|
||||
if ($columns === 0) {
|
||||
$titles = \array_map(function(string $title) : string {
|
||||
$title = \strtr(\trim($title), ' ', '_');
|
||||
$title = \preg_replace('/[^a-zA-Z0-9_]/', '', $title);
|
||||
|
||||
return \strtr($title, ' ', '_');
|
||||
}, $titles);
|
||||
|
||||
$cells = \fgetcsv($fp, null, $delim);
|
||||
if ($cells === false) {
|
||||
\fclose($fp);
|
||||
return;
|
||||
}
|
||||
|
||||
// insert data
|
||||
$query = new Builder($this->con);
|
||||
$query->insert(...$titles)->into($table);
|
||||
$query = new SchemaBuilder($this->con);
|
||||
$query->createTable($table);
|
||||
|
||||
while (($cells = \fgetcsv($fp)) !== false) {
|
||||
$query->values(...$cells);
|
||||
foreach ($cells as $idx => $cell) {
|
||||
$datatype = SchemaBuilder::getTypeFromVariable($cell);
|
||||
|
||||
$query->field($titles[$idx], $datatype);
|
||||
}
|
||||
|
||||
$query->execute();
|
||||
|
|
@ -98,9 +101,78 @@ final class CsvDatabaseMapper implements IODatabaseMapper
|
|||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function select(array $queries) : void
|
||||
public function import(string $path, string $table = '', ?\Closure $transform = null) : void
|
||||
{
|
||||
$fp = \fopen($this->path, 'r+');
|
||||
$fp = \fopen($path, 'r');
|
||||
if ($fp === false) {
|
||||
return;
|
||||
}
|
||||
|
||||
$table = \strtr(empty($table) ? \basename($path, '.csv') : $table, ' ', '_');
|
||||
$titles = [];
|
||||
|
||||
$delim = CsvSettings::getFileDelimiter($fp, 2);
|
||||
|
||||
// get column titles
|
||||
$titles = \fgetcsv($fp, 4096, $delim);
|
||||
if ($titles === false) {
|
||||
\fclose($fp);
|
||||
return;
|
||||
}
|
||||
|
||||
$columns = \count($titles);
|
||||
if ($columns === 0) {
|
||||
\fclose($fp);
|
||||
return;
|
||||
}
|
||||
|
||||
$titles = \array_map(function(string $title) : string {
|
||||
$title = \strtr(\trim($title), ' ', '_');
|
||||
$title = \preg_replace('/[^a-zA-Z0-9_]/', '', $title);
|
||||
|
||||
return \strtr($title, ' ', '_');
|
||||
}, $titles);
|
||||
|
||||
$titleCount = \count($titles);
|
||||
|
||||
do {
|
||||
$counter = 0;
|
||||
|
||||
// insert data
|
||||
$query = new Builder($this->con);
|
||||
$query->insert(...$titles)->into($table);
|
||||
|
||||
while (($cells = \fgetcsv($fp, null, $delim)) !== false) {
|
||||
if (\count($cells) !== $titleCount) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($transform !== null) {
|
||||
foreach ($cells as $idx => $cell) {
|
||||
$cells[$idx] = $transform($titles[$idx], $cell);
|
||||
}
|
||||
}
|
||||
|
||||
$query->values(...$cells);
|
||||
++$counter;
|
||||
|
||||
if ($counter > 250) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$query->execute();
|
||||
} while ($cells !== false);
|
||||
|
||||
\fclose($fp);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function export(string $path, array $queries) : void
|
||||
{
|
||||
$fp = \fopen($path, 'r+');
|
||||
if ($fp === false) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -112,6 +184,7 @@ final class CsvDatabaseMapper implements IODatabaseMapper
|
|||
}
|
||||
|
||||
if ($key > 0) {
|
||||
\fclose($fp);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -140,27 +213,36 @@ final class CsvDatabaseMapper implements IODatabaseMapper
|
|||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function update() : void
|
||||
public function update(string $path, string $table = '') : void
|
||||
{
|
||||
$fp = \fopen($this->path, 'r+');
|
||||
$fp = \fopen($path, 'r+');
|
||||
if ($fp === false) {
|
||||
return;
|
||||
}
|
||||
|
||||
$table = \basename($this->path, '.csv');
|
||||
$table = \strtr(empty($table) ? \basename($path, '.csv') : $table, ' ', '_');
|
||||
$titles = [];
|
||||
|
||||
// get column titles
|
||||
$titles = \fgetcsv($fp, 4096);
|
||||
if ($titles === false) {
|
||||
\fclose($fp);
|
||||
return;
|
||||
}
|
||||
|
||||
$columns = \count($titles);
|
||||
if ($columns === 0) {
|
||||
\fclose($fp);
|
||||
return;
|
||||
}
|
||||
|
||||
$titles = \array_map(function(string $title) : string {
|
||||
$title = \strtr(\trim($title), ' ', '_');
|
||||
$title = \preg_replace('/[^a-zA-Z0-9_]/', '', $title);
|
||||
|
||||
return \strtr($title, ' ', '_');
|
||||
}, $titles);
|
||||
|
||||
$idCol = (string) \array_shift($titles);
|
||||
|
||||
// update data
|
||||
|
|
|
|||
|
|
@ -27,29 +27,49 @@ interface IODatabaseMapper
|
|||
/**
|
||||
* Insert data from excel sheet into database
|
||||
*
|
||||
* @param string $path File path
|
||||
* @param string $table Table name (empty = sheet name)
|
||||
* @param null|\Closure $transform Transform data before import
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function insert() : void;
|
||||
public function import(string $path, string $table = '', ?\Closure $transform = null) : void;
|
||||
|
||||
/**
|
||||
* Select data from database and store in excel sheet
|
||||
*
|
||||
* @param string $path Output path
|
||||
* @param \phpOMS\DataStorage\Database\Query\Builder[] $queries Queries to execute
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function select(array $queries) : void;
|
||||
public function export(string $path, array $queries) : void;
|
||||
|
||||
/**
|
||||
* Update data from excel sheet into database
|
||||
*
|
||||
* @param string $path File path
|
||||
* @param string $table Table name (empty = sheet name)
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function update() : void;
|
||||
public function update(string $path, string $table = '') : void;
|
||||
|
||||
/**
|
||||
* Create database schema
|
||||
*
|
||||
* @param string $path File path
|
||||
* @param string $table Table name (empty = sheet name)
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function createSchema(string $path, string $table = '') : void;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ namespace phpOMS\Utils\IO\Spreadsheet;
|
|||
|
||||
use phpOMS\DataStorage\Database\Connection\ConnectionAbstract;
|
||||
use phpOMS\DataStorage\Database\Query\Builder;
|
||||
use phpOMS\DataStorage\Database\Schema\Builder as SchemaBuilder;
|
||||
use phpOMS\Utils\IO\IODatabaseMapper;
|
||||
use phpOMS\Utils\StringUtils;
|
||||
|
||||
|
|
@ -37,57 +38,50 @@ final class SpreadsheetDatabaseMapper implements IODatabaseMapper
|
|||
*/
|
||||
private ConnectionAbstract $con;
|
||||
|
||||
/**
|
||||
* Path to source or destination
|
||||
*
|
||||
* @var string
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private string $path = '';
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param ConnectionAbstract $con Database connection
|
||||
* @param string $path File path
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function __construct(ConnectionAbstract $con, string $path)
|
||||
public function __construct(ConnectionAbstract $con)
|
||||
{
|
||||
$this->con = $con;
|
||||
$this->path = $path;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function insert() : void
|
||||
public function createSchema(string $path, string $table = '') : void
|
||||
{
|
||||
$reader = null;
|
||||
if (StringUtils::endsWith($this->path, '.xlsx')) {
|
||||
if (StringUtils::endsWith($path, '.xlsx')) {
|
||||
$reader = new \PhpOffice\PhpSpreadsheet\Reader\Xlsx();
|
||||
} elseif (StringUtils::endsWith($this->path, '.ods')) {
|
||||
} elseif (StringUtils::endsWith($path, '.ods')) {
|
||||
$reader = new \PhpOffice\PhpSpreadsheet\Reader\Ods();
|
||||
} else {
|
||||
$reader = new \PhpOffice\PhpSpreadsheet\Reader\Xls();
|
||||
}
|
||||
|
||||
$reader->setReadDataOnly(true);
|
||||
$sheet = $reader->load($this->path);
|
||||
$sheet = $reader->load($path);
|
||||
|
||||
$tables = $sheet->getSheetCount();
|
||||
for ($i = 0; $i < $tables; ++$i) {
|
||||
$sheet->setActiveSheetIndex($i);
|
||||
|
||||
$workSheet = $sheet->getSheet($i);
|
||||
$table = $workSheet->getTitle();
|
||||
$table = \strtr(empty($table) ? $workSheet->getTitle() : $table, ' ', '_');
|
||||
$titles = [];
|
||||
|
||||
// get column titles
|
||||
$column = 1;
|
||||
while (!empty($value = $workSheet->getCell(StringUtils::intToAlphabet($column) . 1)->getCalculatedValue())) {
|
||||
$value = \strtr(\trim($value), ' ', '_');
|
||||
$value = \preg_replace('/[^a-zA-Z0-9_]/', '', $value);
|
||||
$titles[] = $value;
|
||||
|
||||
++$column;
|
||||
}
|
||||
|
||||
|
|
@ -96,20 +90,22 @@ final class SpreadsheetDatabaseMapper implements IODatabaseMapper
|
|||
continue;
|
||||
}
|
||||
|
||||
// insert data
|
||||
$query = new Builder($this->con);
|
||||
$query->insert(...$titles)->into($table);
|
||||
$query = new SchemaBuilder($this->con);
|
||||
$query->createTable($table);
|
||||
|
||||
$line = 2;
|
||||
while (!empty($workSheet->getCell('A' . $line)->getCalculatedValue())) {
|
||||
$cells = [];
|
||||
for ($j = 1; $j <= $columns; ++$j) {
|
||||
$cells[] = $workSheet->getCell(StringUtils::intToAlphabet($j) . $line)->getCalculatedValue();
|
||||
}
|
||||
if (empty($workSheet->getCell('A' . $line)->getCalculatedValue())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
++$line;
|
||||
for ($j = 1; $j <= $columns; ++$j) {
|
||||
$cells[] = $workSheet->getCell(StringUtils::intToAlphabet($j) . $line)->getCalculatedValue();
|
||||
}
|
||||
|
||||
$query->values(...$cells);
|
||||
foreach ($cells as $idx => $cell) {
|
||||
$datatype = SchemaBuilder::getTypeFromVariable($cell);
|
||||
|
||||
$query->field($titles[$idx], $datatype);
|
||||
}
|
||||
|
||||
$query->execute();
|
||||
|
|
@ -119,7 +115,83 @@ final class SpreadsheetDatabaseMapper implements IODatabaseMapper
|
|||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function select(array $queries) : void
|
||||
public function import(string $path, string $table = '', ?\Closure $transform = null) : void
|
||||
{
|
||||
$reader = null;
|
||||
if (StringUtils::endsWith($path, '.xlsx')) {
|
||||
$reader = new \PhpOffice\PhpSpreadsheet\Reader\Xlsx();
|
||||
} elseif (StringUtils::endsWith($path, '.ods')) {
|
||||
$reader = new \PhpOffice\PhpSpreadsheet\Reader\Ods();
|
||||
} else {
|
||||
$reader = new \PhpOffice\PhpSpreadsheet\Reader\Xls();
|
||||
}
|
||||
|
||||
$reader->setReadDataOnly(true);
|
||||
$sheet = $reader->load($path);
|
||||
|
||||
$tables = $sheet->getSheetCount();
|
||||
for ($i = 0; $i < $tables; ++$i) {
|
||||
$sheet->setActiveSheetIndex($i);
|
||||
|
||||
$workSheet = $sheet->getSheet($i);
|
||||
$table = \strtr(empty($table) ? $workSheet->getTitle() : $table, ' ', '_');
|
||||
$titles = [];
|
||||
|
||||
// get column titles
|
||||
$column = 1;
|
||||
while (!empty($value = $workSheet->getCell(StringUtils::intToAlphabet($column) . 1)->getCalculatedValue())) {
|
||||
$value = \strtr(\trim($value), ' ', '_');
|
||||
$value = \preg_replace('/[^a-zA-Z0-9_]/', '', $value);
|
||||
$titles[] = $value;
|
||||
|
||||
++$column;
|
||||
}
|
||||
|
||||
$columns = \count($titles);
|
||||
if ($columns === 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$line = 2;
|
||||
|
||||
do {
|
||||
$counter = 0;
|
||||
|
||||
// insert data
|
||||
$query = new Builder($this->con);
|
||||
$query->insert(...$titles)->into($table);
|
||||
|
||||
while ($hasData = !empty($workSheet->getCell('A' . $line)->getCalculatedValue())) {
|
||||
$cells = [];
|
||||
for ($j = 1; $j <= $columns; ++$j) {
|
||||
$cells[] = $workSheet->getCell(StringUtils::intToAlphabet($j) . $line)->getCalculatedValue();
|
||||
}
|
||||
|
||||
if ($transform !== null) {
|
||||
foreach ($cells as $idx => $cell) {
|
||||
$cells[$idx] = $transform($titles[$idx], $cell);
|
||||
}
|
||||
}
|
||||
|
||||
++$line;
|
||||
|
||||
$query->values(...$cells);
|
||||
++$counter;
|
||||
|
||||
if ($counter > 250) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$query->execute();
|
||||
} while ($hasData);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function export(string $path, array $queries) : void
|
||||
{
|
||||
$sheet = new \PhpOffice\PhpSpreadsheet\Spreadsheet();
|
||||
$sheet->getProperties()
|
||||
|
|
@ -169,44 +241,47 @@ final class SpreadsheetDatabaseMapper implements IODatabaseMapper
|
|||
}
|
||||
}
|
||||
|
||||
if (StringUtils::endsWith($this->path, '.xlsx')) {
|
||||
(new \PhpOffice\PhpSpreadsheet\Writer\Xlsx($sheet))->save($this->path);
|
||||
} elseif (StringUtils::endsWith($this->path, '.ods')) {
|
||||
(new \PhpOffice\PhpSpreadsheet\Writer\Ods($sheet))->save($this->path);
|
||||
if (StringUtils::endsWith($path, '.xlsx')) {
|
||||
(new \PhpOffice\PhpSpreadsheet\Writer\Xlsx($sheet))->save($path);
|
||||
} elseif (StringUtils::endsWith($path, '.ods')) {
|
||||
(new \PhpOffice\PhpSpreadsheet\Writer\Ods($sheet))->save($path);
|
||||
} else {
|
||||
(new \PhpOffice\PhpSpreadsheet\Writer\Xls($sheet))->save($this->path);
|
||||
(new \PhpOffice\PhpSpreadsheet\Writer\Xls($sheet))->save($path);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function update() : void
|
||||
public function update(string $path, string $table = '') : void
|
||||
{
|
||||
$reader = null;
|
||||
if (StringUtils::endsWith($this->path, '.xlsx')) {
|
||||
if (StringUtils::endsWith($path, '.xlsx')) {
|
||||
$reader = new \PhpOffice\PhpSpreadsheet\Reader\Xlsx();
|
||||
} elseif (StringUtils::endsWith($this->path, '.ods')) {
|
||||
} elseif (StringUtils::endsWith($path, '.ods')) {
|
||||
$reader = new \PhpOffice\PhpSpreadsheet\Reader\Ods();
|
||||
} else {
|
||||
$reader = new \PhpOffice\PhpSpreadsheet\Reader\Xls();
|
||||
}
|
||||
|
||||
$reader->setReadDataOnly(true);
|
||||
$sheet = $reader->load($this->path);
|
||||
$sheet = $reader->load($path);
|
||||
|
||||
$tables = $sheet->getSheetCount();
|
||||
for ($i = 0; $i < $tables; ++$i) {
|
||||
$sheet->setActiveSheetIndex($i);
|
||||
|
||||
$workSheet = $sheet->getSheet($i);
|
||||
$table = $workSheet->getTitle();
|
||||
$table = \strtr(empty($table) ? $workSheet->getTitle() : $table, ' ', '_');
|
||||
$titles = [];
|
||||
|
||||
// get column titles
|
||||
$column = 1;
|
||||
while (!empty($value = $workSheet->getCell(StringUtils::intToAlphabet($column) . 1)->getCalculatedValue())) {
|
||||
$value = \strtr(\trim($value), ' ', '_');
|
||||
$value = \preg_replace('/[^a-zA-Z0-9_]/', '', $value);
|
||||
$titles[] = $value;
|
||||
|
||||
++$column;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3510,7 +3510,7 @@ class Markdown
|
|||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
protected function insertAbreviation(array $element) : array
|
||||
protected function insertAbbreviation(array $element) : array
|
||||
{
|
||||
if (!isset($element['text'])) {
|
||||
return $element;
|
||||
|
|
@ -3570,7 +3570,7 @@ class Markdown
|
|||
$this->currentMeaning = $meaning;
|
||||
|
||||
$inline['element'] = $this->elementApplyRecursiveDepthFirst(
|
||||
'insertAbreviation',
|
||||
'insertAbbreviation',
|
||||
$inline['element']
|
||||
);
|
||||
}
|
||||
|
|
@ -3727,7 +3727,8 @@ class Markdown
|
|||
$dom = new \DOMDocument();
|
||||
|
||||
// http://stackoverflow.com/q/11309194/200145
|
||||
$elementMarkup = \mb_convert_encoding($elementMarkup, 'HTML-ENTITIES', 'UTF-8');
|
||||
// $elementMarkup = \mb_convert_encoding($elementMarkup, 'HTML-ENTITIES', 'UTF-8'); // Deprecated
|
||||
$elementMarkup = \mb_encode_numericentity($elementMarkup, [0x80, 0x10FFFF, 0, ~0], 'UTF-8' );
|
||||
|
||||
// http://stackoverflow.com/q/4879946/200145
|
||||
$dom->loadHTML($elementMarkup);
|
||||
|
|
@ -4494,31 +4495,6 @@ class Markdown
|
|||
return $element;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle element recursively
|
||||
*
|
||||
* @param string|\Closure $closure Closure for handling element
|
||||
* @param array $element Element to handle
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
protected function elementApplyRecursive(string|\Closure $closure, array $element) : array
|
||||
{
|
||||
$element = \is_string($closure) ? $this->{$closure}($element) : $closure($element);
|
||||
|
||||
if (isset($element['elements'])) {
|
||||
foreach ($element['elements'] as &$e) {
|
||||
$e = $this->elementApplyRecursive($closure, $e);
|
||||
}
|
||||
} elseif (isset($element['element'])) {
|
||||
$element['element'] = $this->elementApplyRecursive($closure, $element['element']);
|
||||
}
|
||||
|
||||
return $element;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle element recursively
|
||||
*
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@ declare(strict_types=1);
|
|||
|
||||
namespace phpOMS\tests\DataStorage\Database\Query;
|
||||
|
||||
include_once __DIR__ . '/../../../Autoloader.php';
|
||||
|
||||
use phpOMS\DataStorage\Database\Connection\MysqlConnection;
|
||||
use phpOMS\DataStorage\Database\Connection\PostgresConnection;
|
||||
use phpOMS\DataStorage\Database\Connection\SQLiteConnection;
|
||||
|
|
@ -29,6 +31,10 @@ final class BuilderTest extends \PHPUnit\Framework\TestCase
|
|||
{
|
||||
public static function dbConnectionProvider() : array
|
||||
{
|
||||
if (!isset($GLOBALS['CONFIG'])) {
|
||||
$GLOBALS['CONFIG'] = include __DIR__ . '/../../../config.php';
|
||||
}
|
||||
|
||||
$cons = [
|
||||
[new MysqlConnection($GLOBALS['CONFIG']['db']['core']['masters']['admin'])],
|
||||
[new PostgresConnection($GLOBALS['CONFIG']['db']['core']['postgresql']['admin'])],
|
||||
|
|
@ -59,26 +65,31 @@ final class BuilderTest extends \PHPUnit\Framework\TestCase
|
|||
$iE = $con->getGrammar()->systemIdentifierEnd;
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = false;
|
||||
$sql = 'SELECT [a].[test] FROM [a] WHERE [a].[test] = 1;';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->select('a.test')->from('a')->where('a.test', '=', 1)->toSql());
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = false;
|
||||
$sql = 'SELECT [a].[test] AS t FROM [a] AS b WHERE [a].[test] = 1;';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->selectAs('a.test', 't')->fromAs('a', 'b')->where('a.test', '=', 1)->toSql());
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = false;
|
||||
$sql = 'SELECT DISTINCT [a].[test] FROM [a] WHERE [a].[test] = 1;';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->select('a.test')->distinct()->from('a')->where('a.test', '=', 1)->toSql());
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = false;
|
||||
$sql = 'SELECT [a].[test], [b].[test] FROM [a], [b] WHERE [a].[test] = \'abc\';';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->select('a.test', 'b.test')->from('a', 'b')->where('a.test', '=', 'abc')->toSql());
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = false;
|
||||
$datetime = new \DateTime('now');
|
||||
$sql = 'SELECT [a].[test], [b].[test] FROM [a], [b] WHERE [a].[test] = \'' . $datetime->format('Y-m-d H:i:s')
|
||||
. '\';';
|
||||
|
|
@ -86,6 +97,7 @@ final class BuilderTest extends \PHPUnit\Framework\TestCase
|
|||
self::assertEquals($sql, $query->select('a.test', 'b.test')->from('a', 'b')->where('a.test', '=', $datetime)->toSql());
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = false;
|
||||
$sql = 'SELECT [a].[test], [b].[test] FROM [a], [b] WHERE [a].[test] = \'abc\' ORDER BY [a].[test] ASC, [b].[test] DESC;';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql,
|
||||
|
|
@ -97,6 +109,7 @@ final class BuilderTest extends \PHPUnit\Framework\TestCase
|
|||
);
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = false;
|
||||
$sql = 'SELECT [a].[test], [b].[test] FROM [a], [b] WHERE [a].[test] = :abcValue ORDER BY [a].[test] ASC, [b].[test] DESC;';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql,
|
||||
|
|
@ -118,6 +131,7 @@ final class BuilderTest extends \PHPUnit\Framework\TestCase
|
|||
$iE = $con->getGrammar()->systemIdentifierEnd;
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = false;
|
||||
$sql = 'SELECT [a].[test] FROM [a] AS b WHERE [a].[test] = 1 ORDER BY RAND() LIMIT 1;';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->random('a.test')->fromAs('a', 'b')->where('a.test', '=', 1)->toSql());
|
||||
|
|
@ -131,6 +145,7 @@ final class BuilderTest extends \PHPUnit\Framework\TestCase
|
|||
$iE = $con->getGrammar()->systemIdentifierEnd;
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = false;
|
||||
$sql = 'SELECT [a].[test] FROM [a] AS b ORDER BY RANDOM() LIMIT 1;';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->random('a.test')->fromAs('a', 'b')->where('a.test', '=', 1)->toSql());
|
||||
|
|
@ -144,6 +159,7 @@ final class BuilderTest extends \PHPUnit\Framework\TestCase
|
|||
$iE = $con->getGrammar()->systemIdentifierEnd;
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = false;
|
||||
$sql = 'SELECT [a].[test] FROM [a] AS b ORDER BY RANDOM() LIMIT 1;';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->random('a.test')->fromAs('a', 'b')->where('a.test', '=', 1)->toSql());
|
||||
|
|
@ -157,6 +173,7 @@ final class BuilderTest extends \PHPUnit\Framework\TestCase
|
|||
$iE = $con->getGrammar()->systemIdentifierEnd;
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = false;
|
||||
$sql = 'SELECT TOP 1 [a].[test] FROM [a] AS b ORDER BY IDX FETCH FIRST 1 ROWS ONLY;';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->random('a.test')->fromAs('a', 'b')->where('a.test', '=', 1)->toSql());
|
||||
|
|
@ -177,31 +194,37 @@ final class BuilderTest extends \PHPUnit\Framework\TestCase
|
|||
$iE = $con->getGrammar()->systemIdentifierEnd;
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = false;
|
||||
$sql = 'SELECT [a].[test] FROM [a] WHERE [a].[test] = 1 ORDER BY [a].[test] DESC;';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->select('a.test')->from('a')->where('a.test', '=', 1)->newest('a.test')->toSql());
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = false;
|
||||
$sql = 'SELECT [a].[test] FROM [a] WHERE [a].[test] = 1 ORDER BY [a].[test] ASC;';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->select('a.test')->from('a')->where('a.test', '=', 1)->oldest('a.test')->toSql());
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = false;
|
||||
$sql = 'SELECT [a].[test] FROM [a] WHERE [a].[test] = 1 ORDER BY [a].[test] DESC;';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->select('a.test')->from('a')->where('a.test', '=', 1)->orderBy('a.test', 'DESC')->toSql());
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = false;
|
||||
$sql = 'SELECT [a].[test] FROM [a] WHERE [a].[test] = 1 ORDER BY [a].[test] ASC;';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->select('a.test')->from('a')->where('a.test', '=', 1)->orderBy('a.test', 'ASC')->toSql());
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = false;
|
||||
$sql = 'SELECT [a].[test] FROM [a] WHERE [a].[test] = 1 ORDER BY [a].[test] DESC, [a].[test2] DESC;';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->select('a.test')->from('a')->where('a.test', '=', 1)->orderBy(['a.test', 'a.test2'], ['DESC', 'DESC'])->toSql());
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = false;
|
||||
$sql = 'SELECT [a].[test] FROM [a] WHERE [a].[test] = 1 ORDER BY [a].[test] ASC, [a].[test2] ASC;';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->select('a.test')->from('a')->where('a.test', '=', 1)->orderBy(['a.test', 'a.test2'], 'ASC')->toSql());
|
||||
|
|
@ -222,11 +245,13 @@ final class BuilderTest extends \PHPUnit\Framework\TestCase
|
|||
$iE = $con->getGrammar()->systemIdentifierEnd;
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = false;
|
||||
$sql = 'SELECT [a].[test] FROM [a] WHERE [a].[test] = 1 LIMIT 3;';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->select('a.test')->from('a')->where('a.test', '=', 1)->limit(3)->toSql());
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = false;
|
||||
$sql = 'SELECT [a].[test] FROM [a] WHERE [a].[test] = 1 OFFSET 3;';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->select('a.test')->from('a')->where('a.test', '=', 1)->offset(3)->toSql());
|
||||
|
|
@ -247,19 +272,23 @@ final class BuilderTest extends \PHPUnit\Framework\TestCase
|
|||
$iE = $con->getGrammar()->systemIdentifierEnd;
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = false;
|
||||
$sql = 'SELECT [a].[test] FROM [a] WHERE [a].[test] = 1 GROUP BY [a];';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->select('a.test')->from('a')->where('a.test', '=', 1)->groupBy('a')->toSql());
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = false;
|
||||
$sql = 'SELECT [a].[test] FROM [a] WHERE [a].[test] = 1 GROUP BY [a], [b];';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->select('a.test')->from('a')->where('a.test', '=', 1)->groupBy('a')->groupBy('b')->toSql());
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = false;
|
||||
self::assertEquals($sql, $query->select('a.test')->from('a')->where('a.test', '=', 1)->groupBy('a', 'b')->toSql());
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = false;
|
||||
$sql = 'SELECT [a].[test] FROM [a] WHERE [a].[test] = :test GROUP BY [a], [b];';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->select('a.test')->from('a')->where('a.test', '=', new Parameter('test'))->groupBy('a', 'b')->toSql());
|
||||
|
|
@ -280,71 +309,85 @@ final class BuilderTest extends \PHPUnit\Framework\TestCase
|
|||
$iE = $con->getGrammar()->systemIdentifierEnd;
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = false;
|
||||
$sql = 'SELECT [a].[test] FROM [a] WHERE [a].[test] = 1;';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->select('a.test')->from('a')->where('a.test', '=', 1)->toSql());
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = false;
|
||||
$sql = 'SELECT [a].[test] FROM [a] WHERE [a].[test] = 0;';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->select('a.test')->from('a')->where('a.test', '=', false)->toSql());
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = false;
|
||||
$sql = 'SELECT [a].[test] FROM [a] WHERE [a].[test] = 1;';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->select('a.test')->from('a')->where('a.test', '=', true)->toSql());
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = false;
|
||||
$sql = 'SELECT [a].[test] FROM [a] WHERE [a].[test] = \'string\';';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->select('a.test')->from('a')->where('a.test', '=', 'string')->toSql());
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = false;
|
||||
$sql = 'SELECT [a].[test] FROM [a] WHERE [a].[test] = 1.23;';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->select('a.test')->from('a')->where('a.test', '=', 1.23)->toSql());
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = false;
|
||||
$sql = 'SELECT [a].[test] FROM [a] WHERE [a].[test] = 1 AND [a].[test2] = 2;';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->select('a.test')->from('a')->where('a.test', '=', 1)->where('a.test2', '=', 2, 'and')->toSql());
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = false;
|
||||
$sql = 'SELECT [a].[test] FROM [a] WHERE [a].[test] = 1 AND [a].[test2] = 2;';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->select('a.test')->from('a')->where('a.test', '=', 1)->andWhere('a.test2', '=', 2)->toSql());
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = false;
|
||||
$sql = 'SELECT [a].[test] FROM [a] WHERE [a].[test] = 1 OR [a].[test2] = 2;';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->select('a.test')->from('a')->where('a.test', '=', 1)->where('a.test2', '=', 2, 'or')->toSql());
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = false;
|
||||
$sql = 'SELECT [a].[test] FROM [a] WHERE [a].[test] = 1 OR [a].[test2] = 2;';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->select('a.test')->from('a')->where('a.test', '=', 1)->orWhere('a.test2', '=', 2)->toSql());
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = false;
|
||||
$sql = 'SELECT [a].[test] FROM [a] WHERE [a].[test] = 1 OR [a].[test2] IS NULL;';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->select('a.test')->from('a')->where('a.test', '=', 1)->whereNull('a.test2', 'or')->toSql());
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = false;
|
||||
$sql = 'SELECT [a].[test] FROM [a] WHERE [a].[test] = 1 OR [a].[test2] IS NOT NULL;';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->select('a.test')->from('a')->where('a.test', '=', 1)->whereNotNull('a.test2', 'or')->toSql());
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = false;
|
||||
$sql = 'SELECT [a].[test] FROM [a] WHERE [a].[test] = 1 OR [a].[test2] IN (1, 2, 3);';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->select('a.test')->from('a')->where('a.test', '=', 1)->whereIn('a.test2', [1, 2, 3], 'or')->toSql());
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = false;
|
||||
$sql = 'SELECT [a].[test] FROM [a] WHERE [a].[test] = 1 OR [a].[test2] IN (\'a\', \'b\', \'c\');';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->select('a.test')->from('a')->where('a.test', '=', 1)->whereIn('a.test2', ['a', 'b', 'c'], 'or')->toSql());
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = false;
|
||||
$sql = 'SELECT [a].[test] FROM [a] WHERE [a].[test] = :testWhere OR [a].[test2] IN (\'a\', :bValue, \'c\');';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->select('a.test')->from('a')->where('a.test', '=', new Parameter('testWhere'))->whereIn('a.test2', ['a', new Parameter('bValue'), 'c'], 'or')->toSql());
|
||||
|
|
@ -365,71 +408,85 @@ final class BuilderTest extends \PHPUnit\Framework\TestCase
|
|||
$iE = $con->getGrammar()->systemIdentifierEnd;
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = false;
|
||||
$sql = 'SELECT [a].[test] FROM [a] JOIN [b] ON [a].[id] = [b].[id] WHERE [a].[test] = 1;';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->select('a.test')->from('a')->join('b')->on('a.id', '=', 'b.id')->where('a.test', '=', 1)->toSql());
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = false;
|
||||
$sql = 'SELECT [a].[test] FROM [a] JOIN [b] ON [a].[id] = [b].[id] OR [a].[id2] = [b].[id2] WHERE [a].[test] = 1;';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->select('a.test')->from('a')->join('b')->on('a.id', '=', 'b.id')->orOn('a.id2', '=', 'b.id2')->where('a.test', '=', 1)->toSql());
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = false;
|
||||
$sql = 'SELECT [a].[test] FROM [a] JOIN [b] ON [a].[id] = [b].[id] AND [a].[id2] = [b].[id2] WHERE [a].[test] = 1;';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->select('a.test')->from('a')->join('b')->on('a.id', '=', 'b.id')->andOn('a.id2', '=', 'b.id2')->where('a.test', '=', 1)->toSql());
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = false;
|
||||
$sql = 'SELECT [a].[test] FROM [a] LEFT JOIN [b] ON [a].[id] = [b].[id] WHERE [a].[test] = 1;';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->select('a.test')->from('a')->leftJoin('b')->on('a.id', '=', 'b.id')->where('a.test', '=', 1)->toSql());
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = false;
|
||||
$sql = 'SELECT [a].[test] FROM [a] LEFT OUTER JOIN [b] ON [a].[id] = [b].[id] WHERE [a].[test] = 1;';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->select('a.test')->from('a')->leftOuterJoin('b')->on('a.id', '=', 'b.id')->where('a.test', '=', 1)->toSql());
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = false;
|
||||
$sql = 'SELECT [a].[test] FROM [a] LEFT INNER JOIN [b] ON [a].[id] = [b].[id] WHERE [a].[test] = 1;';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->select('a.test')->from('a')->leftInnerJoin('b')->on('a.id', '=', 'b.id')->where('a.test', '=', 1)->toSql());
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = false;
|
||||
$sql = 'SELECT [a].[test] FROM [a] RIGHT JOIN [b] ON [a].[id] = [b].[id] WHERE [a].[test] = 1;';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->select('a.test')->from('a')->rightJoin('b')->on('a.id', '=', 'b.id')->where('a.test', '=', 1)->toSql());
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = false;
|
||||
$sql = 'SELECT [a].[test] FROM [a] RIGHT OUTER JOIN [b] ON [a].[id] = [b].[id] WHERE [a].[test] = 1;';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->select('a.test')->from('a')->rightOuterJoin('b')->on('a.id', '=', 'b.id')->where('a.test', '=', 1)->toSql());
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = false;
|
||||
$sql = 'SELECT [a].[test] FROM [a] RIGHT INNER JOIN [b] ON [a].[id] = [b].[id] WHERE [a].[test] = 1;';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->select('a.test')->from('a')->rightInnerJoin('b')->on('a.id', '=', 'b.id')->where('a.test', '=', 1)->toSql());
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = false;
|
||||
$sql = 'SELECT [a].[test] FROM [a] OUTER JOIN [b] ON [a].[id] = [b].[id] WHERE [a].[test] = 1;';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->select('a.test')->from('a')->outerJoin('b')->on('a.id', '=', 'b.id')->where('a.test', '=', 1)->toSql());
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = false;
|
||||
$sql = 'SELECT [a].[test] FROM [a] INNER JOIN [b] ON [a].[id] = [b].[id] WHERE [a].[test] = 1;';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->select('a.test')->from('a')->innerJoin('b')->on('a.id', '=', 'b.id')->where('a.test', '=', 1)->toSql());
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = false;
|
||||
$sql = 'SELECT [a].[test] FROM [a] CROSS JOIN [b] ON [a].[id] = [b].[id] WHERE [a].[test] = 1;';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->select('a.test')->from('a')->crossJoin('b')->on('a.id', '=', 'b.id')->where('a.test', '=', 1)->toSql());
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = false;
|
||||
$sql = 'SELECT [a].[test] FROM [a] FULL JOIN [b] ON [a].[id] = [b].[id] WHERE [a].[test] = 1;';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->select('a.test')->from('a')->fullJoin('b')->on('a.id', '=', 'b.id')->where('a.test', '=', 1)->toSql());
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = false;
|
||||
$sql = 'SELECT [a].[test] FROM [a] FULL OUTER JOIN [b] ON [a].[id] = [b].[id] WHERE [a].[test] = 1;';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->select('a.test')->from('a')->fullOuterJoin('b')->on('a.id', '=', 'b.id')->where('a.test', '=', 1)->toSql());
|
||||
|
|
@ -450,27 +507,32 @@ final class BuilderTest extends \PHPUnit\Framework\TestCase
|
|||
$iE = $con->getGrammar()->systemIdentifierEnd;
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = false;
|
||||
$sql = 'INSERT INTO [a] VALUES (1, \'test\');';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->insert()->into('a')->values(1, 'test')->toSql());
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = false;
|
||||
$sql = 'INSERT INTO [a] VALUES (1, \'test\');';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->insert()->into('a')->value([1, 'test'])->toSql());
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = false;
|
||||
$sql = 'INSERT INTO [a] ([test], [test2]) VALUES (1, \'test\');';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->insert('test', 'test2')->into('a')->values(1, 'test')->toSql());
|
||||
self::assertEquals([[1, 'test']], $query->getValues());
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = false;
|
||||
$sql = 'INSERT INTO [a] ([test], [test2]) VALUES (1, \'test\'), (2, \'test2\');';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->insert('test', 'test2')->into('a')->values(1, 'test')->values(2, 'test2')->toSql());
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = false;
|
||||
$sql = 'INSERT INTO [a] ([test], [test2]) VALUES (:test, :test2);';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->insert('test', 'test2')->into('a')->values(new Parameter('test'), new Parameter('test2'))->toSql());
|
||||
|
|
@ -491,11 +553,13 @@ final class BuilderTest extends \PHPUnit\Framework\TestCase
|
|||
$iE = $con->getGrammar()->systemIdentifierEnd;
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = false;
|
||||
$sql = 'DELETE FROM [a] WHERE [a].[test] = 1;';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->delete()->from('a')->where('a.test', '=', 1)->toSql());
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = false;
|
||||
$sql = 'DELETE FROM [a] WHERE [a].[test] = :testVal;';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->delete()->from('a')->where('a.test', '=', new Parameter('testVal'))->toSql());
|
||||
|
|
@ -516,21 +580,571 @@ final class BuilderTest extends \PHPUnit\Framework\TestCase
|
|||
$iE = $con->getGrammar()->systemIdentifierEnd;
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = false;
|
||||
$sql = 'UPDATE [a] SET [test] = 1, [test2] = 2 WHERE [a].[test] = 1;';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->update('a')->set(['test' => 1])->set(['test2' => 2])->where('a.test', '=', 1)->toSql());
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = false;
|
||||
$sql = 'UPDATE [a] SET [test] = 1, [test2] = 2 WHERE [a].[test] = 1;';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->update('a')->sets('test', 1)->sets('test2', 2)->where('a.test', '=', 1)->toSql());
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = false;
|
||||
$sql = 'UPDATE [a] SET [test] = 1, [test2] = :test2 WHERE [a].[test] = :test3;';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->update('a')->set(['test' => 1])->set(['test2' => new Parameter('test2')])->where('a.test', '=', new Parameter('test3'))->toSql());
|
||||
}
|
||||
|
||||
#[\PHPUnit\Framework\Attributes\DataProvider('dbConnectionProvider')]
|
||||
#[\PHPUnit\Framework\Attributes\Group('framework')]
|
||||
#[\PHPUnit\Framework\Attributes\TestDox('Mysql selects form a valid query')]
|
||||
public function testSelectPrepared($con) : void
|
||||
{
|
||||
if (!$con->isInitialized()) {
|
||||
self::markTestSkipped();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$iS = $con->getGrammar()->systemIdentifierStart;
|
||||
$iE = $con->getGrammar()->systemIdentifierEnd;
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = true;
|
||||
$sql = 'SELECT [a].[test] FROM [a] WHERE [a].[test] = ?;';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->select('a.test')->from('a')->where('a.test', '=', 1)->toSql());
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = true;
|
||||
$sql = 'SELECT [a].[test] AS t FROM [a] AS b WHERE [a].[test] = ?;';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->selectAs('a.test', 't')->fromAs('a', 'b')->where('a.test', '=', 1)->toSql());
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = true;
|
||||
$sql = 'SELECT DISTINCT [a].[test] FROM [a] WHERE [a].[test] = ?;';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->select('a.test')->distinct()->from('a')->where('a.test', '=', 1)->toSql());
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = true;
|
||||
$sql = 'SELECT [a].[test], [b].[test] FROM [a], [b] WHERE [a].[test] = ?;';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->select('a.test', 'b.test')->from('a', 'b')->where('a.test', '=', 'abc')->toSql());
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = true;
|
||||
$datetime = new \DateTime('now');
|
||||
$sql = 'SELECT [a].[test], [b].[test] FROM [a], [b] WHERE [a].[test] = ?;';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->select('a.test', 'b.test')->from('a', 'b')->where('a.test', '=', $datetime)->toSql());
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = true;
|
||||
$sql = 'SELECT [a].[test], [b].[test] FROM [a], [b] WHERE [a].[test] = ? ORDER BY [a].[test] ASC, [b].[test] DESC;';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql,
|
||||
$query->select('a.test', 'b.test')
|
||||
->from('a', 'b')
|
||||
->where('a.test', '=', 'abc')
|
||||
->orderBy(['a.test', 'b.test', ], ['ASC', 'DESC', ])
|
||||
->toSql()
|
||||
);
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = true;
|
||||
$sql = 'SELECT [a].[test], [b].[test] FROM [a], [b] WHERE [a].[test] = :abcValue ORDER BY [a].[test] ASC, [b].[test] DESC;';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql,
|
||||
$query->select('a.test', 'b.test')
|
||||
->from('a', 'b')
|
||||
->where('a.test', '=', new Parameter('abcValue'))
|
||||
->orderBy(['a.test', 'b.test', ], ['ASC', 'DESC', ])
|
||||
->toSql()
|
||||
);
|
||||
|
||||
self::assertEquals($query->toSql(), $query->__toString());
|
||||
}
|
||||
|
||||
public function testRandomMysqlPrepared() : void
|
||||
{
|
||||
$con = new MysqlConnection($GLOBALS['CONFIG']['db']['core']['masters']['admin']);
|
||||
|
||||
$iS = $con->getGrammar()->systemIdentifierStart;
|
||||
$iE = $con->getGrammar()->systemIdentifierEnd;
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = true;
|
||||
$sql = 'SELECT [a].[test] FROM [a] AS b WHERE [a].[test] = ? ORDER BY RAND() LIMIT ?;';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->random('a.test')->fromAs('a', 'b')->where('a.test', '=', 1)->toSql());
|
||||
}
|
||||
|
||||
public function testRandomPostgresqlPrepared() : void
|
||||
{
|
||||
$con = new PostgresConnection($GLOBALS['CONFIG']['db']['core']['postgresql']['admin']);
|
||||
|
||||
$iS = $con->getGrammar()->systemIdentifierStart;
|
||||
$iE = $con->getGrammar()->systemIdentifierEnd;
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = true;
|
||||
$sql = 'SELECT [a].[test] FROM [a] AS b ORDER BY RANDOM() LIMIT ?;';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->random('a.test')->fromAs('a', 'b')->where('a.test', '=', 1)->toSql());
|
||||
}
|
||||
|
||||
public function testRandomSQLitePrepared() : void
|
||||
{
|
||||
$con = new SQLiteConnection($GLOBALS['CONFIG']['db']['core']['sqlite']['admin']);
|
||||
|
||||
$iS = $con->getGrammar()->systemIdentifierStart;
|
||||
$iE = $con->getGrammar()->systemIdentifierEnd;
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = true;
|
||||
$sql = 'SELECT [a].[test] FROM [a] AS b ORDER BY RANDOM() LIMIT ?;';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->random('a.test')->fromAs('a', 'b')->where('a.test', '=', 1)->toSql());
|
||||
}
|
||||
|
||||
public function testRandomSqlServerPrepared() : void
|
||||
{
|
||||
$con = new SqlServerConnection($GLOBALS['CONFIG']['db']['core']['mssql']['admin']);
|
||||
|
||||
$iS = $con->getGrammar()->systemIdentifierStart;
|
||||
$iE = $con->getGrammar()->systemIdentifierEnd;
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = true;
|
||||
$sql = 'SELECT TOP 1 [a].[test] FROM [a] AS b ORDER BY IDX FETCH FIRST 1 ROWS ONLY;';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->random('a.test')->fromAs('a', 'b')->where('a.test', '=', 1)->toSql());
|
||||
}
|
||||
|
||||
#[\PHPUnit\Framework\Attributes\DataProvider('dbConnectionProvider')]
|
||||
#[\PHPUnit\Framework\Attributes\Group('framework')]
|
||||
#[\PHPUnit\Framework\Attributes\TestDox('Mysql orders form a valid query')]
|
||||
public function testOrderPrepared($con) : void
|
||||
{
|
||||
if (!$con->isInitialized()) {
|
||||
self::markTestSkipped();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$iS = $con->getGrammar()->systemIdentifierStart;
|
||||
$iE = $con->getGrammar()->systemIdentifierEnd;
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = true;
|
||||
$sql = 'SELECT [a].[test] FROM [a] WHERE [a].[test] = ? ORDER BY [a].[test] DESC;';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->select('a.test')->from('a')->where('a.test', '=', 1)->newest('a.test')->toSql());
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = true;
|
||||
$sql = 'SELECT [a].[test] FROM [a] WHERE [a].[test] = ? ORDER BY [a].[test] ASC;';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->select('a.test')->from('a')->where('a.test', '=', 1)->oldest('a.test')->toSql());
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = true;
|
||||
$sql = 'SELECT [a].[test] FROM [a] WHERE [a].[test] = ? ORDER BY [a].[test] DESC;';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->select('a.test')->from('a')->where('a.test', '=', 1)->orderBy('a.test', 'DESC')->toSql());
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = true;
|
||||
$sql = 'SELECT [a].[test] FROM [a] WHERE [a].[test] = ? ORDER BY [a].[test] ASC;';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->select('a.test')->from('a')->where('a.test', '=', 1)->orderBy('a.test', 'ASC')->toSql());
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = true;
|
||||
$sql = 'SELECT [a].[test] FROM [a] WHERE [a].[test] = ? ORDER BY [a].[test] DESC, [a].[test2] DESC;';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->select('a.test')->from('a')->where('a.test', '=', 1)->orderBy(['a.test', 'a.test2'], ['DESC', 'DESC'])->toSql());
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = true;
|
||||
$sql = 'SELECT [a].[test] FROM [a] WHERE [a].[test] = ? ORDER BY [a].[test] ASC, [a].[test2] ASC;';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->select('a.test')->from('a')->where('a.test', '=', 1)->orderBy(['a.test', 'a.test2'], 'ASC')->toSql());
|
||||
}
|
||||
|
||||
#[\PHPUnit\Framework\Attributes\DataProvider('dbConnectionProvider')]
|
||||
#[\PHPUnit\Framework\Attributes\Group('framework')]
|
||||
#[\PHPUnit\Framework\Attributes\TestDox('Mysql offsets and limits form a valid query')]
|
||||
public function testOffsetLimitPrepared($con) : void
|
||||
{
|
||||
if (!$con->isInitialized()) {
|
||||
self::markTestSkipped();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$iS = $con->getGrammar()->systemIdentifierStart;
|
||||
$iE = $con->getGrammar()->systemIdentifierEnd;
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = true;
|
||||
$sql = 'SELECT [a].[test] FROM [a] WHERE [a].[test] = ? LIMIT ?;';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->select('a.test')->from('a')->where('a.test', '=', 1)->limit(3)->toSql());
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = true;
|
||||
$sql = 'SELECT [a].[test] FROM [a] WHERE [a].[test] = ? OFFSET ?;';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->select('a.test')->from('a')->where('a.test', '=', 1)->offset(3)->toSql());
|
||||
}
|
||||
|
||||
#[\PHPUnit\Framework\Attributes\DataProvider('dbConnectionProvider')]
|
||||
#[\PHPUnit\Framework\Attributes\Group('framework')]
|
||||
#[\PHPUnit\Framework\Attributes\TestDox('Mysql groupings form a valid query')]
|
||||
public function testGroupPrepared($con) : void
|
||||
{
|
||||
if (!$con->isInitialized()) {
|
||||
self::markTestSkipped();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$iS = $con->getGrammar()->systemIdentifierStart;
|
||||
$iE = $con->getGrammar()->systemIdentifierEnd;
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = true;
|
||||
$sql = 'SELECT [a].[test] FROM [a] WHERE [a].[test] = ? GROUP BY [a];';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->select('a.test')->from('a')->where('a.test', '=', 1)->groupBy('a')->toSql());
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = true;
|
||||
$sql = 'SELECT [a].[test] FROM [a] WHERE [a].[test] = ? GROUP BY [a], [b];';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->select('a.test')->from('a')->where('a.test', '=', 1)->groupBy('a')->groupBy('b')->toSql());
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = true;
|
||||
self::assertEquals($sql, $query->select('a.test')->from('a')->where('a.test', '=', 1)->groupBy('a', 'b')->toSql());
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = true;
|
||||
$sql = 'SELECT [a].[test] FROM [a] WHERE [a].[test] = :test GROUP BY [a], [b];';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->select('a.test')->from('a')->where('a.test', '=', new Parameter('test'))->groupBy('a', 'b')->toSql());
|
||||
}
|
||||
|
||||
#[\PHPUnit\Framework\Attributes\DataProvider('dbConnectionProvider')]
|
||||
#[\PHPUnit\Framework\Attributes\Group('framework')]
|
||||
#[\PHPUnit\Framework\Attributes\TestDox('Mysql wheres form a valid query')]
|
||||
public function testWheresPrepared($con) : void
|
||||
{
|
||||
if (!$con->isInitialized()) {
|
||||
self::markTestSkipped();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$iS = $con->getGrammar()->systemIdentifierStart;
|
||||
$iE = $con->getGrammar()->systemIdentifierEnd;
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = true;
|
||||
$sql = 'SELECT [a].[test] FROM [a] WHERE [a].[test] = ?;';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->select('a.test')->from('a')->where('a.test', '=', 1)->toSql());
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = true;
|
||||
$sql = 'SELECT [a].[test] FROM [a] WHERE [a].[test] = ?;';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->select('a.test')->from('a')->where('a.test', '=', false)->toSql());
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = true;
|
||||
$sql = 'SELECT [a].[test] FROM [a] WHERE [a].[test] = ?;';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->select('a.test')->from('a')->where('a.test', '=', true)->toSql());
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = true;
|
||||
$sql = 'SELECT [a].[test] FROM [a] WHERE [a].[test] = ?;';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->select('a.test')->from('a')->where('a.test', '=', 'string')->toSql());
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = true;
|
||||
$sql = 'SELECT [a].[test] FROM [a] WHERE [a].[test] = 1.23;';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->select('a.test')->from('a')->where('a.test', '=', 1.23)->toSql());
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = true;
|
||||
$sql = 'SELECT [a].[test] FROM [a] WHERE [a].[test] = ? AND [a].[test2] = ?;';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->select('a.test')->from('a')->where('a.test', '=', 1)->where('a.test2', '=', 2, 'and')->toSql());
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = true;
|
||||
$sql = 'SELECT [a].[test] FROM [a] WHERE [a].[test] = ? AND [a].[test2] = ?;';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->select('a.test')->from('a')->where('a.test', '=', 1)->andWhere('a.test2', '=', 2)->toSql());
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = true;
|
||||
$sql = 'SELECT [a].[test] FROM [a] WHERE [a].[test] = ? OR [a].[test2] = ?;';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->select('a.test')->from('a')->where('a.test', '=', 1)->where('a.test2', '=', 2, 'or')->toSql());
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = true;
|
||||
$sql = 'SELECT [a].[test] FROM [a] WHERE [a].[test] = ? OR [a].[test2] = ?;';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->select('a.test')->from('a')->where('a.test', '=', 1)->orWhere('a.test2', '=', 2)->toSql());
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = true;
|
||||
$sql = 'SELECT [a].[test] FROM [a] WHERE [a].[test] = ? OR [a].[test2] IS NULL;';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->select('a.test')->from('a')->where('a.test', '=', 1)->whereNull('a.test2', 'or')->toSql());
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = true;
|
||||
$sql = 'SELECT [a].[test] FROM [a] WHERE [a].[test] = ? OR [a].[test2] IS NOT NULL;';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->select('a.test')->from('a')->where('a.test', '=', 1)->whereNotNull('a.test2', 'or')->toSql());
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = true;
|
||||
$sql = 'SELECT [a].[test] FROM [a] WHERE [a].[test] = ? OR [a].[test2] IN (?, ?, ?);';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->select('a.test')->from('a')->where('a.test', '=', 1)->whereIn('a.test2', [1, 2, 3], 'or')->toSql());
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = true;
|
||||
$sql = 'SELECT [a].[test] FROM [a] WHERE [a].[test] = ? OR [a].[test2] IN (?, ?, ?);';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->select('a.test')->from('a')->where('a.test', '=', 1)->whereIn('a.test2', ['a', 'b', 'c'], 'or')->toSql());
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = true;
|
||||
$sql = 'SELECT [a].[test] FROM [a] WHERE [a].[test] = :testWhere OR [a].[test2] IN (?, :bValue, ?);';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->select('a.test')->from('a')->where('a.test', '=', new Parameter('testWhere'))->whereIn('a.test2', ['a', new Parameter('bValue'), 'c'], 'or')->toSql());
|
||||
}
|
||||
|
||||
#[\PHPUnit\Framework\Attributes\DataProvider('dbConnectionProvider')]
|
||||
#[\PHPUnit\Framework\Attributes\Group('framework')]
|
||||
#[\PHPUnit\Framework\Attributes\TestDox('Mysql joins form a valid query')]
|
||||
public function testJoinsPrepared($con) : void
|
||||
{
|
||||
if (!$con->isInitialized()) {
|
||||
self::markTestSkipped();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$iS = $con->getGrammar()->systemIdentifierStart;
|
||||
$iE = $con->getGrammar()->systemIdentifierEnd;
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = true;
|
||||
$sql = 'SELECT [a].[test] FROM [a] JOIN [b] ON [a].[id] = [b].[id] WHERE [a].[test] = ?;';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->select('a.test')->from('a')->join('b')->on('a.id', '=', 'b.id')->where('a.test', '=', 1)->toSql());
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = true;
|
||||
$sql = 'SELECT [a].[test] FROM [a] JOIN [b] ON [a].[id] = [b].[id] OR [a].[id2] = [b].[id2] WHERE [a].[test] = ?;';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->select('a.test')->from('a')->join('b')->on('a.id', '=', 'b.id')->orOn('a.id2', '=', 'b.id2')->where('a.test', '=', 1)->toSql());
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = true;
|
||||
$sql = 'SELECT [a].[test] FROM [a] JOIN [b] ON [a].[id] = [b].[id] AND [a].[id2] = [b].[id2] WHERE [a].[test] = ?;';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->select('a.test')->from('a')->join('b')->on('a.id', '=', 'b.id')->andOn('a.id2', '=', 'b.id2')->where('a.test', '=', 1)->toSql());
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = true;
|
||||
$sql = 'SELECT [a].[test] FROM [a] LEFT JOIN [b] ON [a].[id] = [b].[id] WHERE [a].[test] = ?;';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->select('a.test')->from('a')->leftJoin('b')->on('a.id', '=', 'b.id')->where('a.test', '=', 1)->toSql());
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = true;
|
||||
$sql = 'SELECT [a].[test] FROM [a] LEFT OUTER JOIN [b] ON [a].[id] = [b].[id] WHERE [a].[test] = ?;';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->select('a.test')->from('a')->leftOuterJoin('b')->on('a.id', '=', 'b.id')->where('a.test', '=', 1)->toSql());
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = true;
|
||||
$sql = 'SELECT [a].[test] FROM [a] LEFT INNER JOIN [b] ON [a].[id] = [b].[id] WHERE [a].[test] = ?;';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->select('a.test')->from('a')->leftInnerJoin('b')->on('a.id', '=', 'b.id')->where('a.test', '=', 1)->toSql());
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = true;
|
||||
$sql = 'SELECT [a].[test] FROM [a] RIGHT JOIN [b] ON [a].[id] = [b].[id] WHERE [a].[test] = ?;';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->select('a.test')->from('a')->rightJoin('b')->on('a.id', '=', 'b.id')->where('a.test', '=', 1)->toSql());
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = true;
|
||||
$sql = 'SELECT [a].[test] FROM [a] RIGHT OUTER JOIN [b] ON [a].[id] = [b].[id] WHERE [a].[test] = ?;';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->select('a.test')->from('a')->rightOuterJoin('b')->on('a.id', '=', 'b.id')->where('a.test', '=', 1)->toSql());
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = true;
|
||||
$sql = 'SELECT [a].[test] FROM [a] RIGHT INNER JOIN [b] ON [a].[id] = [b].[id] WHERE [a].[test] = ?;';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->select('a.test')->from('a')->rightInnerJoin('b')->on('a.id', '=', 'b.id')->where('a.test', '=', 1)->toSql());
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = true;
|
||||
$sql = 'SELECT [a].[test] FROM [a] OUTER JOIN [b] ON [a].[id] = [b].[id] WHERE [a].[test] = ?;';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->select('a.test')->from('a')->outerJoin('b')->on('a.id', '=', 'b.id')->where('a.test', '=', 1)->toSql());
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = true;
|
||||
$sql = 'SELECT [a].[test] FROM [a] INNER JOIN [b] ON [a].[id] = [b].[id] WHERE [a].[test] = ?;';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->select('a.test')->from('a')->innerJoin('b')->on('a.id', '=', 'b.id')->where('a.test', '=', 1)->toSql());
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = true;
|
||||
$sql = 'SELECT [a].[test] FROM [a] CROSS JOIN [b] ON [a].[id] = [b].[id] WHERE [a].[test] = ?;';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->select('a.test')->from('a')->crossJoin('b')->on('a.id', '=', 'b.id')->where('a.test', '=', 1)->toSql());
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = true;
|
||||
$sql = 'SELECT [a].[test] FROM [a] FULL JOIN [b] ON [a].[id] = [b].[id] WHERE [a].[test] = ?;';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->select('a.test')->from('a')->fullJoin('b')->on('a.id', '=', 'b.id')->where('a.test', '=', 1)->toSql());
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = true;
|
||||
$sql = 'SELECT [a].[test] FROM [a] FULL OUTER JOIN [b] ON [a].[id] = [b].[id] WHERE [a].[test] = ?;';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->select('a.test')->from('a')->fullOuterJoin('b')->on('a.id', '=', 'b.id')->where('a.test', '=', 1)->toSql());
|
||||
}
|
||||
|
||||
#[\PHPUnit\Framework\Attributes\DataProvider('dbConnectionProvider')]
|
||||
#[\PHPUnit\Framework\Attributes\Group('framework')]
|
||||
#[\PHPUnit\Framework\Attributes\TestDox('Mysql inserts form a valid query')]
|
||||
public function testInsertPrepared($con) : void
|
||||
{
|
||||
if (!$con->isInitialized()) {
|
||||
self::markTestSkipped();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$iS = $con->getGrammar()->systemIdentifierStart;
|
||||
$iE = $con->getGrammar()->systemIdentifierEnd;
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = true;
|
||||
$sql = 'INSERT INTO [a] VALUES (?, ?);';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->insert()->into('a')->values(1, 'test')->toSql());
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = true;
|
||||
$sql = 'INSERT INTO [a] VALUES (?, ?);';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->insert()->into('a')->value([1, 'test'])->toSql());
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = true;
|
||||
$sql = 'INSERT INTO [a] ([test], [test2]) VALUES (?, ?);';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->insert('test', 'test2')->into('a')->values(1, 'test')->toSql());
|
||||
self::assertEquals([[1, 'test']], $query->getValues());
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = true;
|
||||
$sql = 'INSERT INTO [a] ([test], [test2]) VALUES (?, ?), (?, ?);';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->insert('test', 'test2')->into('a')->values(1, 'test')->values(2, 'test2')->toSql());
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = true;
|
||||
$sql = 'INSERT INTO [a] ([test], [test2]) VALUES (:test, :test2);';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->insert('test', 'test2')->into('a')->values(new Parameter('test'), new Parameter('test2'))->toSql());
|
||||
}
|
||||
|
||||
#[\PHPUnit\Framework\Attributes\DataProvider('dbConnectionProvider')]
|
||||
#[\PHPUnit\Framework\Attributes\Group('framework')]
|
||||
#[\PHPUnit\Framework\Attributes\TestDox('Mysql deletes form a valid query')]
|
||||
public function testDeletePrepared($con) : void
|
||||
{
|
||||
if (!$con->isInitialized()) {
|
||||
self::markTestSkipped();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$iS = $con->getGrammar()->systemIdentifierStart;
|
||||
$iE = $con->getGrammar()->systemIdentifierEnd;
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = true;
|
||||
$sql = 'DELETE FROM [a] WHERE [a].[test] = ?;';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->delete()->from('a')->where('a.test', '=', 1)->toSql());
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = true;
|
||||
$sql = 'DELETE FROM [a] WHERE [a].[test] = :testVal;';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->delete()->from('a')->where('a.test', '=', new Parameter('testVal'))->toSql());
|
||||
}
|
||||
|
||||
#[\PHPUnit\Framework\Attributes\DataProvider('dbConnectionProvider')]
|
||||
#[\PHPUnit\Framework\Attributes\Group('framework')]
|
||||
#[\PHPUnit\Framework\Attributes\TestDox('Mysql updates form a valid query')]
|
||||
public function testUpdatePrepared($con) : void
|
||||
{
|
||||
if (!$con->isInitialized()) {
|
||||
self::markTestSkipped();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$iS = $con->getGrammar()->systemIdentifierStart;
|
||||
$iE = $con->getGrammar()->systemIdentifierEnd;
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = true;
|
||||
$sql = 'UPDATE [a] SET [test] = ?, [test2] = ? WHERE [a].[test] = ?;';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->update('a')->set(['test' => 1])->set(['test2' => 2])->where('a.test', '=', 1)->toSql());
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = true;
|
||||
$sql = 'UPDATE [a] SET [test] = ?, [test2] = ? WHERE [a].[test] = ?;';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->update('a')->sets('test', 1)->sets('test2', 2)->where('a.test', '=', 1)->toSql());
|
||||
|
||||
$query = new Builder($con);
|
||||
$query->usePreparedStmt = true;
|
||||
$sql = 'UPDATE [a] SET [test] = ?, [test2] = :test2 WHERE [a].[test] = :test3;';
|
||||
$sql = \strtr($sql, '[]', $iS . $iE);
|
||||
self::assertEquals($sql, $query->update('a')->set(['test' => 1])->set(['test2' => new Parameter('test2')])->where('a.test', '=', new Parameter('test3'))->toSql());
|
||||
}
|
||||
|
||||
#[\PHPUnit\Framework\Attributes\DataProvider('dbConnectionProvider')]
|
||||
#[\PHPUnit\Framework\Attributes\Group('framework')]
|
||||
#[\PHPUnit\Framework\Attributes\TestDox('Raw queries get output as defined')]
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ final class MarkdownTest extends \PHPUnit\Framework\TestCase
|
|||
$data = \explode('.', $file);
|
||||
|
||||
if ($data[1] === 'md'
|
||||
&& (\file_get_contents(__DIR__ . '/data/' . $data[0] . '.html') !== ($parsed = Markdown::parse(\file_get_contents(__DIR__ . '/data/' . $data[0] . '.md'))))
|
||||
&& (($expected = \file_get_contents(__DIR__ . '/data/' . $data[0] . '.html')) !== ($parsed = Markdown::parse(\file_get_contents(__DIR__ . '/data/' . $data[0] . '.md'))))
|
||||
) {
|
||||
self::assertTrue(false, $file . "\n\n" . $parsed);
|
||||
}
|
||||
|
|
|
|||
299
tests/config.php
Normal file
299
tests/config.php
Normal file
|
|
@ -0,0 +1,299 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
'db' => [
|
||||
'core' => [
|
||||
'masters' => [
|
||||
'admin' => [
|
||||
'db' => 'mysql', /* db type */
|
||||
'host' => '127.0.0.1', /* db host address */
|
||||
'port' => '3306', /* db host port */
|
||||
'login' => 'test', /* db login name */
|
||||
'password' => 'orange', /* db login password */
|
||||
'database' => 'omt', /* db name */
|
||||
'weight' => 1000, /* db table prefix */
|
||||
'datetimeformat' => 'Y-m-d H:i:s',
|
||||
],
|
||||
'insert' => [
|
||||
'db' => 'mysql', /* db type */
|
||||
'host' => '127.0.0.1', /* db host address */
|
||||
'port' => '3306', /* db host port */
|
||||
'login' => 'test', /* db login name */
|
||||
'password' => 'orange', /* db login password */
|
||||
'database' => 'omt', /* db name */
|
||||
'weight' => 1000, /* db table prefix */
|
||||
'datetimeformat' => 'Y-m-d H:i:s',
|
||||
],
|
||||
'select' => [
|
||||
'db' => 'mysql', /* db type */
|
||||
'host' => '127.0.0.1', /* db host address */
|
||||
'port' => '3306', /* db host port */
|
||||
'login' => 'test', /* db login name */
|
||||
'password' => 'orange', /* db login password */
|
||||
'database' => 'omt', /* db name */
|
||||
'weight' => 1000, /* db table prefix */
|
||||
'datetimeformat' => 'Y-m-d H:i:s',
|
||||
],
|
||||
'update' => [
|
||||
'db' => 'mysql', /* db type */
|
||||
'host' => '127.0.0.1', /* db host address */
|
||||
'port' => '3306', /* db host port */
|
||||
'login' => 'test', /* db login name */
|
||||
'password' => 'orange', /* db login password */
|
||||
'database' => 'omt', /* db name */
|
||||
'weight' => 1000, /* db table prefix */
|
||||
'datetimeformat' => 'Y-m-d H:i:s',
|
||||
],
|
||||
'delete' => [
|
||||
'db' => 'mysql', /* db type */
|
||||
'host' => '127.0.0.1', /* db host address */
|
||||
'port' => '3306', /* db host port */
|
||||
'login' => 'test', /* db login name */
|
||||
'password' => 'orange', /* db login password */
|
||||
'database' => 'omt', /* db name */
|
||||
'weight' => 1000, /* db table prefix */
|
||||
'datetimeformat' => 'Y-m-d H:i:s',
|
||||
],
|
||||
'schema' => [
|
||||
'db' => 'mysql', /* db type */
|
||||
'host' => '127.0.0.1', /* db host address */
|
||||
'port' => '3306', /* db host port */
|
||||
'login' => 'test', /* db login name */
|
||||
'password' => 'orange', /* db login password */
|
||||
'database' => 'omt', /* db name */
|
||||
'weight' => 1000, /* db table prefix */
|
||||
'datetimeformat' => 'Y-m-d H:i:s',
|
||||
],
|
||||
],
|
||||
'postgresql' => [
|
||||
'admin' => [
|
||||
'db' => 'pgsql', /* db type */
|
||||
'host' => '127.0.0.1', /* db host address */
|
||||
'port' => '5432', /* db host port */
|
||||
'login' => 'test', /* db login name */
|
||||
'password' => 'orange', /* db login password */
|
||||
'database' => 'omt', /* db name */
|
||||
'weight' => 1000, /* db table prefix */
|
||||
'datetimeformat' => 'Y-m-d H:i:s',
|
||||
],
|
||||
'insert' => [
|
||||
'db' => 'pgsql', /* db type */
|
||||
'host' => '127.0.0.1', /* db host address */
|
||||
'port' => '5432', /* db host port */
|
||||
'login' => 'test', /* db login name */
|
||||
'password' => 'orange', /* db login password */
|
||||
'database' => 'omt', /* db name */
|
||||
'weight' => 1000, /* db table prefix */
|
||||
'datetimeformat' => 'Y-m-d H:i:s',
|
||||
],
|
||||
'select' => [
|
||||
'db' => 'pgsql', /* db type */
|
||||
'host' => '127.0.0.1', /* db host address */
|
||||
'port' => '5432', /* db host port */
|
||||
'login' => 'test', /* db login name */
|
||||
'password' => 'orange', /* db login password */
|
||||
'database' => 'omt', /* db name */
|
||||
'weight' => 1000, /* db table prefix */
|
||||
'datetimeformat' => 'Y-m-d H:i:s',
|
||||
],
|
||||
'update' => [
|
||||
'db' => 'pgsql', /* db type */
|
||||
'host' => '127.0.0.1', /* db host address */
|
||||
'port' => '5432', /* db host port */
|
||||
'login' => 'test', /* db login name */
|
||||
'password' => 'orange', /* db login password */
|
||||
'database' => 'omt', /* db name */
|
||||
'weight' => 1000, /* db table prefix */
|
||||
'datetimeformat' => 'Y-m-d H:i:s',
|
||||
],
|
||||
'delete' => [
|
||||
'db' => 'pgsql', /* db type */
|
||||
'host' => '127.0.0.1', /* db host address */
|
||||
'port' => '5432', /* db host port */
|
||||
'login' => 'test', /* db login name */
|
||||
'password' => 'orange', /* db login password */
|
||||
'database' => 'omt', /* db name */
|
||||
'weight' => 1000, /* db table prefix */
|
||||
'datetimeformat' => 'Y-m-d H:i:s',
|
||||
],
|
||||
'schema' => [
|
||||
'db' => 'pgsql', /* db type */
|
||||
'host' => '127.0.0.1', /* db host address */
|
||||
'port' => '5432', /* db host port */
|
||||
'login' => 'test', /* db login name */
|
||||
'password' => 'orange', /* db login password */
|
||||
'database' => 'omt', /* db name */
|
||||
'weight' => 1000, /* db table prefix */
|
||||
'datetimeformat' => 'Y-m-d H:i:s',
|
||||
],
|
||||
],
|
||||
'sqlite' => [
|
||||
'admin' => [
|
||||
'db' => 'sqlite', /* db type */
|
||||
'database' => __DIR__ . '/../Localization/Defaults/localization.sqlite', /* db name */
|
||||
'weight' => 1000, /* db table prefix */
|
||||
'datetimeformat' => 'Y-m-d H:i:s',
|
||||
],
|
||||
'insert' => [
|
||||
'db' => 'sqlite', /* db type */
|
||||
'database' => __DIR__ . '/../Localization/Defaults/localization.sqlite', /* db name */
|
||||
'weight' => 1000, /* db table prefix */
|
||||
'datetimeformat' => 'Y-m-d H:i:s',
|
||||
],
|
||||
'select' => [
|
||||
'db' => 'sqlite', /* db type */
|
||||
'database' => __DIR__ . '/../Localization/Defaults/localization.sqlite', /* db name */
|
||||
'weight' => 1000, /* db table prefix */
|
||||
'datetimeformat' => 'Y-m-d H:i:s',
|
||||
],
|
||||
'update' => [
|
||||
'db' => 'sqlite', /* db type */
|
||||
'database' => __DIR__ . '/../Localization/Defaults/localization.sqlite', /* db name */
|
||||
'weight' => 1000, /* db table prefix */
|
||||
'datetimeformat' => 'Y-m-d H:i:s',
|
||||
],
|
||||
'delete' => [
|
||||
'db' => 'sqlite', /* db type */
|
||||
'database' => __DIR__ . '/../Localization/Defaults/localization.sqlite', /* db name */
|
||||
'weight' => 1000, /* db table prefix */
|
||||
'datetimeformat' => 'Y-m-d H:i:s',
|
||||
],
|
||||
'schema' => [
|
||||
'db' => 'sqlite', /* db type */
|
||||
'database' => __DIR__ . '/../Localization/Defaults/localization.sqlite', /* db name */
|
||||
'weight' => 1000, /* db table prefix */
|
||||
'datetimeformat' => 'Y-m-d H:i:s',
|
||||
],
|
||||
],
|
||||
'mssql' => [
|
||||
'admin' => [
|
||||
'db' => 'mssql', /* db type */
|
||||
'host' => 'localhost', /* db host address */
|
||||
'port' => '1433', /* db host port */
|
||||
'login' => 'test', /* db login name */
|
||||
'password' => 'orange', /* db login password */
|
||||
'database' => 'omt', /* db name */
|
||||
'weight' => 1000, /* db table prefix */
|
||||
'datetimeformat' => 'Y-m-d H:i:s',
|
||||
],
|
||||
'insert' => [
|
||||
'db' => 'mssql', /* db type */
|
||||
'host' => 'localhost', /* db host address */
|
||||
'port' => '1433', /* db host port */
|
||||
'login' => 'test', /* db login name */
|
||||
'password' => 'orange', /* db login password */
|
||||
'database' => 'omt', /* db name */
|
||||
'weight' => 1000, /* db table prefix */
|
||||
'datetimeformat' => 'Y-m-d H:i:s',
|
||||
],
|
||||
'select' => [
|
||||
'db' => 'mssql', /* db type */
|
||||
'host' => 'localhost', /* db host address */
|
||||
'port' => '1433', /* db host port */
|
||||
'login' => 'test', /* db login name */
|
||||
'password' => 'orange', /* db login password */
|
||||
'database' => 'omt', /* db name */
|
||||
'weight' => 1000, /* db table prefix */
|
||||
'datetimeformat' => 'Y-m-d H:i:s',
|
||||
],
|
||||
'update' => [
|
||||
'db' => 'mssql', /* db type */
|
||||
'host' => 'localhost', /* db host address */
|
||||
'port' => '1433', /* db host port */
|
||||
'login' => 'test', /* db login name */
|
||||
'password' => 'orange', /* db login password */
|
||||
'database' => 'omt', /* db name */
|
||||
'weight' => 1000, /* db table prefix */
|
||||
'datetimeformat' => 'Y-m-d H:i:s',
|
||||
],
|
||||
'delete' => [
|
||||
'db' => 'mssql', /* db type */
|
||||
'host' => 'localhost', /* db host address */
|
||||
'port' => '1433', /* db host port */
|
||||
'login' => 'test', /* db login name */
|
||||
'password' => 'orange', /* db login password */
|
||||
'database' => 'omt', /* db name */
|
||||
'weight' => 1000, /* db table prefix */
|
||||
'datetimeformat' => 'Y-m-d H:i:s',
|
||||
],
|
||||
'schema' => [
|
||||
'db' => 'mssql', /* db type */
|
||||
'host' => 'localhost', /* db host address */
|
||||
'port' => '1433', /* db host port */
|
||||
'login' => 'test', /* db login name */
|
||||
'password' => 'orange', /* db login password */
|
||||
'database' => 'omt', /* db name */
|
||||
'weight' => 1000, /* db table prefix */
|
||||
'datetimeformat' => 'Y-m-d H:i:s',
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
'cache' => [
|
||||
'redis' => [
|
||||
'db' => 1,
|
||||
'host' => '127.0.0.1',
|
||||
'port' => 6379,
|
||||
],
|
||||
'memcached' => [
|
||||
'host' => '127.0.0.1',
|
||||
'port' => 11211,
|
||||
],
|
||||
],
|
||||
'mail' => [
|
||||
'imap' => [
|
||||
'host' => '127.0.0.1',
|
||||
'port' => 143,
|
||||
'ssl' => false,
|
||||
'user' => 'test',
|
||||
'password' => '123456',
|
||||
],
|
||||
'pop3' => [
|
||||
'host' => '127.0.0.1',
|
||||
'port' => 25,
|
||||
'ssl' => false,
|
||||
'user' => 'test',
|
||||
'password' => '123456',
|
||||
],
|
||||
],
|
||||
'log' => [
|
||||
'file' => [
|
||||
'path' => __DIR__ . '/Logs',
|
||||
],
|
||||
],
|
||||
'page' => [
|
||||
'root' => '/',
|
||||
'https' => false,
|
||||
],
|
||||
'app' => [
|
||||
'path' => __DIR__,
|
||||
'default' => [
|
||||
'app' => 'Backend',
|
||||
'id' => 'backend',
|
||||
'lang' => 'en',
|
||||
'theme' => 'Backend',
|
||||
'org' => 1,
|
||||
],
|
||||
'domains' => [
|
||||
'127.0.0.1' => [
|
||||
'app' => 'Backend',
|
||||
'id' => 'backend',
|
||||
'lang' => 'en',
|
||||
'theme' => 'Backend',
|
||||
'org' => 1,
|
||||
],
|
||||
],
|
||||
],
|
||||
'socket' => [
|
||||
'master' => [
|
||||
'host' => '127.0.0.1',
|
||||
'limit' => 300,
|
||||
'port' => 4310,
|
||||
],
|
||||
],
|
||||
'language' => [
|
||||
'en',
|
||||
],
|
||||
'apis' => [
|
||||
],
|
||||
];
|
||||
Loading…
Reference in New Issue
Block a user