219 lines
5.8 KiB
PHP
Executable File
219 lines
5.8 KiB
PHP
Executable File
<?php
|
||
|
||
declare(strict_types=1);
|
||
|
||
namespace mirzaev\arming_bot\models;
|
||
|
||
// Files of the project
|
||
use mirzaev\arming_bot\models\core;
|
||
|
||
// Framework for ArangoDB
|
||
use mirzaev\arangodb\collection,
|
||
mirzaev\arangodb\document;
|
||
|
||
// Library для ArangoDB
|
||
use ArangoDBClient\Document as _document;
|
||
|
||
// Built-in libraries
|
||
use exception;
|
||
|
||
/**
|
||
* Model of a product
|
||
*
|
||
* @package mirzaev\arming_bot\models
|
||
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
||
*/
|
||
final class product extends core
|
||
{
|
||
/**
|
||
* Name of the collection in ArangoDB
|
||
*/
|
||
final public const string COLLECTION = 'product';
|
||
|
||
/**
|
||
* Чтение товаров
|
||
*
|
||
* @param string|null $search Поиск
|
||
* @param string|null $filter Фильтр
|
||
* @param string|null $sort Сортировка
|
||
* @param int $page Страница
|
||
* @param int $amount Количество товаров на странице
|
||
* @param string|null $return
|
||
* @param array &$errors Registry of errors
|
||
*
|
||
* @return array Массив с найденными товарами (может быть пустым)
|
||
*/
|
||
public static function read(
|
||
?string $search = null,
|
||
?string $filter = 'd.deleted != true && d.hidden != true',
|
||
?string $sort = 'd.promotion DESC, d.position ASC, d.created DESC',
|
||
int $page = 1,
|
||
int $amount = 100,
|
||
?string $return = 'd',
|
||
array &$errors = []
|
||
): array {
|
||
try {
|
||
if (collection::init(core::$arangodb->session, self::COLLECTION)) {
|
||
// Инициализирована коллекция
|
||
|
||
// Инициализация строки запроса
|
||
$aql = sprintf(
|
||
<<<AQL
|
||
FOR d IN %s
|
||
AQL,
|
||
$search ? self::COLLECTION . 's_search' : self::COLLECTION
|
||
);
|
||
|
||
if ($search) {
|
||
// Search
|
||
$aql .= sprintf(
|
||
<<<AQL
|
||
SEARCH
|
||
LEVENSHTEIN_MATCH(
|
||
d.title.ru,
|
||
TOKENS("%s", "text_ru")[0],
|
||
1,
|
||
false
|
||
) OR
|
||
levenshtein_match(
|
||
d.description.ru,
|
||
tokens("%s", "text_ru")[0],
|
||
1,
|
||
false
|
||
) OR
|
||
levenshtein_match(
|
||
d.compatibility.ru,
|
||
tokens("%s", "text_ru")[0],
|
||
1,
|
||
false
|
||
)
|
||
AQL,
|
||
$search,
|
||
$search,
|
||
$search
|
||
);
|
||
|
||
// Adding sorting
|
||
if ($sort) $sort = "BM25(d) DESC, $sort";
|
||
else $sort = "BM25(d) DESC";
|
||
}
|
||
|
||
if ($documents = collection::search(
|
||
core::$arangodb->session,
|
||
sprintf(
|
||
$aql . <<<AQL
|
||
%s
|
||
%s
|
||
LIMIT %u, %u
|
||
RETURN %s
|
||
AQL,
|
||
empty($filter) ? '' : "FILTER $filter",
|
||
empty($sort) ? '' : "SORT $sort",
|
||
--$page <= 0 ? $page = 0 : $page * $amount,
|
||
$amount,
|
||
empty($return) ? 'd' : $return
|
||
)
|
||
)) {
|
||
// Найдены товары
|
||
|
||
// Возврат (успех)
|
||
return is_array($documents) ? $documents : [$documents];
|
||
} else return [];
|
||
} else throw new exception('Failed to initialize document collection: ' . self::COLLECTION);
|
||
} catch (exception $e) {
|
||
// Write to the registry of errors
|
||
$errors[] = [
|
||
'text' => $e->getMessage(),
|
||
'file' => $e->getFile(),
|
||
'line' => $e->getLine(),
|
||
'stack' => $e->getTrace()
|
||
];
|
||
}
|
||
|
||
// Выход (провал)
|
||
return [];
|
||
}
|
||
|
||
/**
|
||
* Запись товара
|
||
*
|
||
* @param string $title Заголовок
|
||
* @param string|null $description Описание
|
||
* @param float $cost Цена
|
||
* @param float $weight Вес
|
||
* @param array $dimensions Габариты (float)
|
||
* @param array $images Изображения (первое - обложка) (https, путь в storage, иначе будет поиск в storage)
|
||
* @param array $hierarchy Иерархия вложенности (от родителей к потомкам: [ model, model ... ])
|
||
* @param array $data Дополнительные данные
|
||
* @param array &$errors Registry of errors
|
||
*
|
||
* @return string|null Идентификатор (_id) документа (товара), если создан
|
||
*/
|
||
public static function write(
|
||
string $title,
|
||
?string $description = null,
|
||
float $cost = 0,
|
||
float $weight = 0,
|
||
array $dimensions = ['x' => 0, 'y' => 0, 'z' => 0],
|
||
array $images = [],
|
||
array $hierarchy = [],
|
||
array $data = [],
|
||
array &$errors = []
|
||
): string|null {
|
||
try {
|
||
if (collection::init(core::$arangodb->session, self::COLLECTION)) {
|
||
// Инициализирована коллекция
|
||
|
||
// Создание товара
|
||
$product = document::write(
|
||
core::$arangodb->session,
|
||
self::COLLECTION,
|
||
[
|
||
'title' => $title,
|
||
'description' => $description,
|
||
'cost' => $cost ?? 0,
|
||
'weight' => $weight ?? 0,
|
||
'dimensions' => [
|
||
'x' => $dimensions['x'] ?? 0,
|
||
'y' => $dimensions['y'] ?? 0,
|
||
'z' => $dimensions['z'] ?? 0,
|
||
],
|
||
'images' => $images,
|
||
'version' => ROBOT_VERSION
|
||
] + $data
|
||
);
|
||
|
||
if ($product) {
|
||
// Создан товар
|
||
|
||
if (collection::init(core::$arangodb->session, 'entry', true)) {
|
||
// Инициализирована коллекция
|
||
|
||
foreach ($hierarchy as $model) {
|
||
// Перебор иерархической структуры категорий
|
||
|
||
// Инициализация вложенной категории (следующей в массиве)
|
||
$next = current($hierarchy);
|
||
|
||
// Поиск ребра описывающего иерархическую связь
|
||
|
||
document::write(core::$arangodb->session, 'entry');
|
||
}
|
||
} else throw new exception('Failed to initialize document collection: ' . self::COLLECTION);
|
||
}
|
||
} else throw new exception('Failed to initialize document collection: entry');
|
||
} catch (exception $e) {
|
||
// Write to the registry of errors
|
||
$errors[] = [
|
||
'text' => $e->getMessage(),
|
||
'file' => $e->getFile(),
|
||
'line' => $e->getLine(),
|
||
'stack' => $e->getTrace()
|
||
];
|
||
}
|
||
|
||
// Выход (провал)
|
||
return null;
|
||
}
|
||
}
|