Skip to content
Merged

Wip #73

Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
156 changes: 69 additions & 87 deletions src/Repository.php
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ public function onConnection(\PDO $connection): self
* @param \PDO $connection
* @return self
*/
public function withConnectionn(\PDO $connection): self
public function withConnection(\PDO $connection): self
{
return new static($this->table, $connection);
}
Expand Down Expand Up @@ -189,9 +189,9 @@ public function find($id): array|false
/**
* @param string $sort
* @param string|null $fields
* @return void
* @return array
*/
public function getAll(string $sort = 'id ASC', string $fields = null)
public function getAll(string $sort = 'id ASC', string $fields = null): array
{
$fields = !isset($fields) ? implode(',', $this->getFields($fields)) : $fields;
$table = $this->table;
Expand All @@ -200,7 +200,7 @@ public function getAll(string $sort = 'id ASC', string $fields = null)
->orderBy($sort)
->get();

return self::qBuilder($qString);
return $this->qBuilder($qString);
}


Expand All @@ -213,9 +213,16 @@ public function numRows()
}

/**
* @param $field
* @param $value
* @return void
* Finds a single record by a specified field and value.
* The field name is validated against the actual table columns to prevent SQL injection.
* -------------------------
* Находит одну запись по указанному полю и значению.
* Имя поля проверяется по списку реальных колонок таблицы для предотвращения SQL-инъекций.
*
* @param string $field
* @param mixed $value
* @return array|false
* @throws LogicException if the field is not a valid column name
*/
public function findBy($field, $value)
{
Expand Down Expand Up @@ -376,45 +383,50 @@ public function getColumns()
* Если конкретные поля не указаны, метод извлекает все имена столбцов в зависимости от типа базы данных.
* В противном случае он разделяет предоставленную строку полей, разделённых запятыми, на массив.
*
* @param string|null $fields
* @param string|null $fields
* @return array
*/
public function getFields(string $fields = null)
public function getFields(?string $fields = null): array
{
if (!isset($fields)) {
if ($this->connection->getAttribute(\PDO::ATTR_DRIVER_NAME) === "mysql") {
foreach ($this->getColumns() as $column) {
$fields[] = $column['Field'];
}
} elseif ($this->connection->getAttribute(\PDO::ATTR_DRIVER_NAME) === "pgsql") {
foreach ($this->getColumns() as $column) {
$fields[] = $column['column_name'];
}
} elseif ($this->connection->getAttribute(\PDO::ATTR_DRIVER_NAME) === "sqlite") {
foreach ($this->getColumns() as $column) {
$fields[] = $column['name'];
}
if ($fields !== null) {
// Разделяем по запятой и убираем пробелы вокруг каждого поля
return array_map('trim', explode(',', $fields));
}

// Инициализируем как пустой массив — защита от null
$fieldList = [];

if ($this->connection->getAttribute(\PDO::ATTR_DRIVER_NAME) === "mysql") {
foreach ($this->getColumns() as $column) {
$fieldList[] = $column['Field'];
}
} elseif ($this->connection->getAttribute(\PDO::ATTR_DRIVER_NAME) === "pgsql") {
foreach ($this->getColumns() as $column) {
$fieldList[] = $column['column_name'];
}
} elseif ($this->connection->getAttribute(\PDO::ATTR_DRIVER_NAME) === "sqlite") {
foreach ($this->getColumns() as $column) {
$fieldList[] = $column['name'];
}
} else {
$fields = explode(', ', $fields);
}

return $fields;
return $fieldList;
}

/**
* Searches for records in the database based on a search term and column.
* The method prepares and executes a query to retrieve records where the specified column matches the search term.
* The column name is validated against the actual table columns to prevent SQL injection.
* Results are ordered by ID in descending order and limited to 10 records.
* -------------------------
* Выполняет поиск записей в базе данных на основе поискового запроса и указанного столбца.
* Метод подготавливает и выполняет запрос для получения записей, где указанный столбец соответствует поисковому запросу.
* Имя столбца проверяется по списку реальных колонок таблицы для предотвращения SQL-инъекций.
* Результаты сортируются по ID в порядке убывания и ограничиваются 10 записями.
*
* @param string $search
* @param string $column
* @param string|null $fields
* @return array
* @param string $search
* @param string $column
* @param string|null $fields
* @return array
* @throws LogicException if the column is not a valid column name
*/
public function search(string $search, string $column, ?string $fields = null): array
{
Expand All @@ -441,49 +453,6 @@ public function search(string $search, string $column, ?string $fields = null):
return $query->fetchAll(\PDO::FETCH_ASSOC);
}

/**
* @deprecated
* Helper method for writing a toggle.
* This method processes a toggle request, validates input data, updates the status of a record,
* and redirects to the specified URL.
* -------------------------
* Вспомогательный метод для обработки переключения (toggle).
* Этот метод обрабатывает запрос на переключение, проверяет входные данные, обновляет статус записи
* и выполняет перенаправление на указанный URL.
*
* @return void
*/
public function toggle()
{
$processed = [
'csrf_field' => $this->rudra->get(Validation::class)->sanitize($this->rudra->request()->post()->get("csrf_field"))->csrf($this->rudra->session()->get("csrf_token"))->run(),
'id' => $this->rudra->get(Validation::class)->sanitize($this->rudra->request()->put()->get('id'))->run(),
'redirect' => $this->rudra->get(Validation::class)->sanitize($this->rudra->request()->put()->get('redirect'))->run(),
];

$validated = $this->rudra->get(Validation::class)->getValidated($processed, ["csrf_field", "_method"]);

if ($this->rudra->get(Validation::class)->approve($processed)) {
$fields = ["id", "status", "updated_at"];
$updateArr = [];

foreach ($fields as $field) {
if (($field === "updated_at")) {
$updateArr[$field] = date('Y-m-d H:i:s');
continue;
}

$updateArr["status"] = ($this->rudra->request()->put()->has("checkbox")) ? "1" : "0";
$updateArr["id"] = $validated["id"];
}

$this->update($updateArr);
$this->rudra->get(Redirect::class)->run(ltrim($validated['redirect'], '/'));
} else {
dd($this->rudra->get(Validation::class)->getAlerts($processed));
}
}

/**
* Caches the result of a method call to a JSON file for a specified duration.
* If the cached file exists and is still valid (based on cache time), the cached data is returned.
Expand All @@ -499,7 +468,7 @@ public function toggle()
*/
public function cache(array $params, $cacheTime = null)
{
$directory = dirname(__DIR__, 4) . DIRECTORY_SEPARATOR . 'storage' . DIRECTORY_SEPARATOR . 'cache' . DIRECTORY_SEPARATOR . 'database';
$directory = dirname(__DIR__, 4) . DIRECTORY_SEPARATOR . 'storage' . DIRECTORY_SEPARATOR . 'cache' . DIRECTORY_SEPARATOR . 'database';
$file = "$directory/$params[0].json";
$cacheTime = $cacheTime ?? config('cache.time', 'database');

Expand All @@ -520,35 +489,48 @@ public function cache(array $params, $cacheTime = null)

/**
* Clears cached files of a specified type or all types.
* The method removes JSON cache files from the 'database' or 'view' directories,
* or clears both directories if 'all' is specified.
* If a cache key is provided, only that specific cache file is deleted.
* -------------------------
* Очищает кэшированные файлы указанного типа или всех типов.
* Метод удаляет JSON-файлы кэша из директорий 'database' или 'view',
* или очищает обе директории, если указано значение 'all'.
* Если указан ключ кэша, удаляется только этот конкретный файл.
*
* @param string $type
* @param string $type Тип кэша: 'database', 'templates', 'twig', 'routes' или 'all'
* @param string|null $key Имя кэш-файла (без .json). Если null — очистить всю папку.
* @return void
*/
public function clearCache(string $type = 'database')
public function clearCache(string $type = 'database', ?string $key = null): void
{
$baseDir = dirname(__DIR__, 4) . DIRECTORY_SEPARATOR . 'storage' . DIRECTORY_SEPARATOR . 'cache' . DIRECTORY_SEPARATOR;

if (!in_array($type, ['database', 'view', 'all'])) {

if ($type === 'all') {
$this->clearCache('database', $key);
$this->clearCache('templates', $key);
$this->clearCache('twig', $key);
$this->clearCache('routes', $key);
return;
}

if ($type === 'all') {
$this->clearCache('database');
$this->clearCache('view');
if (!in_array($type, ['database', 'templates', 'twig', 'routes'], true)) {
return;
}

$directory = $baseDir . $type;

if ($key !== null) {
// Удаляем один файл
$file = $directory . DIRECTORY_SEPARATOR . $key . '.json';
if (is_file($file)) {
unlink($file);
}
return;
}

// Удаляем все файлы в директории
if (is_dir($directory)) {
foreach (glob("$directory/*.json") as $file) {
if (is_file($file)) unlink($file);
if (is_file($file)) {
unlink($file);
}
}
}
}
Expand Down
Loading