начало работы над сессиями и там дохуя чего ещё
This commit is contained in:
parent
ed5756d065
commit
b2a78519e4
|
@ -1,3 +1,3 @@
|
|||
!.gitignore
|
||||
composer.phar
|
||||
vendor
|
||||
!.gitignore
|
||||
composer.phar
|
||||
vendor
|
||||
|
|
22
LICENSE
22
LICENSE
|
@ -1,11 +1,11 @@
|
|||
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||
Version 2, December 2004
|
||||
|
||||
Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
|
||||
|
||||
Everyone is permitted to copy and distribute verbatim or modified copies of this license document, and changing it is allowed as long as the name is changed.
|
||||
|
||||
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. You just DO WHAT THE FUCK YOU WANT TO.
|
||||
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||
Version 2, December 2004
|
||||
|
||||
Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
|
||||
|
||||
Everyone is permitted to copy and distribute verbatim or modified copies of this license document, and changing it is allowed as long as the name is changed.
|
||||
|
||||
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. You just DO WHAT THE FUCK YOU WANT TO.
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
# site-account
|
||||
|
||||
# site-account
|
||||
|
||||
Site for intersite authentication
|
113
composer.json
113
composer.json
|
@ -1,57 +1,56 @@
|
|||
{
|
||||
"name": "mirzaev/site-account",
|
||||
"description": "API for intersite authentication",
|
||||
"readme": "README.md",
|
||||
"keywords": [
|
||||
"site",
|
||||
"api",
|
||||
"authentication",
|
||||
"auth"
|
||||
],
|
||||
"type": "site",
|
||||
"homepage": "https://git.mirzaev.sexy/mirzaev/site-account",
|
||||
"license": "WTFPL",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Arsen Mirzaev Tatyano-Muradovich",
|
||||
"email": "arsen@mirzaev.sexy",
|
||||
"homepage": "https://mirzaev.sexy",
|
||||
"role": "Programmer"
|
||||
}
|
||||
],
|
||||
"support": {
|
||||
"email": "arsen@mirzaev.sexy",
|
||||
"wiki": "https://git.mirzaev.sexy/mirzaev/site-account/wiki",
|
||||
"issues": "https://git.mirzaev.sexy/mirzaev/site-account/issues"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"type": "funding",
|
||||
"url": "https://fund.mirzaev.sexy"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": "~8.1",
|
||||
"ext-sodium": "~8.1",
|
||||
"mirzaev/minimal": "^2.0.x-dev",
|
||||
"mirzaev/accounts": "~1.2.x-dev",
|
||||
"mirzaev/arangodb": "^1.0.0",
|
||||
"mirzaev/vk": "^5.0",
|
||||
"triagens/arangodb": "~3.9.x-dev",
|
||||
"twig/twig": "^3.4",
|
||||
"guzzlehttp/guzzle": "^7.5"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "~9.5"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"mirzaev\\site\\account\\": "mirzaev/site/account/system"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"mirzaev\\site\\account\\tests\\": "mirzaev/site/account/tests"
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
"name": "mirzaev/site-account",
|
||||
"description": "API for intersite authentication",
|
||||
"readme": "README.md",
|
||||
"keywords": [
|
||||
"site",
|
||||
"api",
|
||||
"authentication"
|
||||
],
|
||||
"type": "site",
|
||||
"homepage": "https://git.mirzaev.sexy/mirzaev/site-account",
|
||||
"license": "WTFPL",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Arsen Mirzaev Tatyano-Muradovich",
|
||||
"email": "arsen@mirzaev.sexy",
|
||||
"homepage": "https://mirzaev.sexy",
|
||||
"role": "Programmer"
|
||||
}
|
||||
],
|
||||
"support": {
|
||||
"email": "arsen@mirzaev.sexy",
|
||||
"wiki": "https://git.mirzaev.sexy/mirzaev/site-account/wiki",
|
||||
"issues": "https://git.mirzaev.sexy/mirzaev/site-account/issues"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"type": "funding",
|
||||
"url": "https://fund.mirzaev.sexy"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": "~8.2",
|
||||
"ext-sodium": "~8.2",
|
||||
"mirzaev/minimal": "^2.0.x-dev",
|
||||
"mirzaev/accounts": "~1.2.x-dev",
|
||||
"mirzaev/arangodb": "^1.0.0",
|
||||
"mirzaev/vk": "^5.0",
|
||||
"triagens/arangodb": "~3.9.x-dev",
|
||||
"twig/twig": "^3.4",
|
||||
"guzzlehttp/guzzle": "^7.5"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "~9.5"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"mirzaev\\site\\account\\": "mirzaev/site/account/system"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"mirzaev\\site\\account\\tests\\": "mirzaev/site/account/tests"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,146 +1,146 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace mirzaev\site\account\controllers;
|
||||
|
||||
// Файлы проекта
|
||||
use mirzaev\site\account\controllers\core;
|
||||
use mirzaev\site\account\models\account_model as account;
|
||||
use mirzaev\site\account\models\session_model as session;
|
||||
use mirzaev\site\account\models\vk_model as vk;
|
||||
|
||||
// Библиотека для ArangoDB
|
||||
use ArangoDBClient\Document as _document;
|
||||
use stdClass;
|
||||
|
||||
// Фреймворк для ВКонтакте
|
||||
use mirzaev\vk\core as api;
|
||||
|
||||
/**
|
||||
* Контроллер аккаунтов
|
||||
*
|
||||
* @package mirzaev\site\account\controllers
|
||||
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
||||
*/
|
||||
final class account_controller extends core
|
||||
{
|
||||
/**
|
||||
* Страница профиля
|
||||
*
|
||||
* @param array $parameters Параметры запроса
|
||||
*/
|
||||
public function index(array $parameters = []): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Инициализация
|
||||
*
|
||||
* @param array $parameters Параметры запроса
|
||||
*/
|
||||
public function initialization(array $parameters = []): ?string
|
||||
{
|
||||
if ($this->variables['account'] instanceof _document) {
|
||||
// Найден аккаунт
|
||||
|
||||
if ($this->variables['vk'] instanceof _document) {
|
||||
// Найден аккаунт ВКонтакте
|
||||
|
||||
// Инициализация данных аккаунта ВКонтакте
|
||||
vk::parse($this->variables['vk'], $this->variables['errors']['vk']);
|
||||
}
|
||||
|
||||
// Запись кода ответа
|
||||
http_response_code(200);
|
||||
|
||||
return null;
|
||||
} else {
|
||||
// Не найден аккаунт
|
||||
|
||||
// Запись кода ответа
|
||||
http_response_code(401);
|
||||
|
||||
// Запись заголовка ответа с ключом аккаунта
|
||||
header('session: ' . $this->variables['session']->hash);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// Запись кода ответа
|
||||
http_response_code(500);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Связь аккаунта с аккаунтом ВКонтакте
|
||||
*
|
||||
* @param array $parameters Параметры запроса
|
||||
*/
|
||||
public function connect(array $parameters = []): ?string
|
||||
{
|
||||
if ($this->variables['session']->hash === $parameters['state']) {
|
||||
// Совпадает хеш сессии с полученным хешем из ответа ВКонтакте
|
||||
|
||||
if (!empty($response = vk::key($parameters['code'], $this->variables['errors']['vk']))) {
|
||||
// Получены данные аккаунта ВКонтакте
|
||||
|
||||
if (($this->variables['vk'] = vk::initialization($response, $this->variables['errors']['vk'])) instanceof _document) {
|
||||
// Инициализирован аккаунт ВКонтакте
|
||||
|
||||
if (($this->variables['account'] = vk::account($this->variables['vk'])) instanceof _document) {
|
||||
// Найден аккаунт (существующий)
|
||||
|
||||
if (session::connect($this->variables['session'], $this->variables['account'], $this->variables['errors']['session'])) {
|
||||
// Связана сессия с аккаунтом
|
||||
}
|
||||
} else if (($this->variables['account'] = account::create($this->variables['errors']['account'])) instanceof _document) {
|
||||
// Найден аккаунт (создан новый)
|
||||
|
||||
if (session::connect($this->variables['session'], $this->variables['account'], $this->variables['errors']['session'])) {
|
||||
// Связана сессия с аккаунтом
|
||||
|
||||
if (account::connect($this->variables['account'], $this->variables['vk'], $this->variables['errors']['account'])) {
|
||||
// Связан аккаунт с аккаунтом ВКонтакте
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Инициализация робота для аккаунта ВКонтакте
|
||||
$this->vk = api::init()->user(key: $this->variables['vk']->access['key']);
|
||||
|
||||
if ($this->variables['vk'] instanceof _document) {
|
||||
// Инициализирован робот для аккаунта ВКонтакте
|
||||
|
||||
// Инициализация данных аккаунта ВКонтакте
|
||||
$data = vk::parse($this->vk, $this->variables['errors']['vk']);
|
||||
var_dump($data); die;
|
||||
|
||||
if ($data instanceof stdClass) {
|
||||
// Получены данные ВКонтакте
|
||||
|
||||
// Запись в базу данных
|
||||
vk::update($this->variables['vk'], $data, $this->variables['errors']['vk']);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Генерация представления
|
||||
return $this->view->render(DIRECTORY_SEPARATOR . 'account' . DIRECTORY_SEPARATOR . 'vk.html', $this->variables);
|
||||
}
|
||||
|
||||
/**
|
||||
* Генерация панели аккаунта
|
||||
*
|
||||
* @param array $parameters Параметры запроса
|
||||
*/
|
||||
public function panel(array $parameters = []): ?string
|
||||
{
|
||||
// Генерация представления
|
||||
return $this->view->render(DIRECTORY_SEPARATOR . 'account' . DIRECTORY_SEPARATOR . 'panel.html', $this->variables);
|
||||
}
|
||||
}
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace mirzaev\site\account\controllers;
|
||||
|
||||
// Файлы проекта
|
||||
use mirzaev\site\account\controllers\core;
|
||||
use mirzaev\site\account\models\account_model as account;
|
||||
use mirzaev\site\account\models\session_model as session;
|
||||
use mirzaev\site\account\models\vk_model as vk;
|
||||
|
||||
// Библиотека для ArangoDB
|
||||
use ArangoDBClient\Document as _document;
|
||||
use stdClass;
|
||||
|
||||
// Фреймворк для ВКонтакте
|
||||
use mirzaev\vk\core as api;
|
||||
|
||||
/**
|
||||
* Контроллер аккаунтов
|
||||
*
|
||||
* @package mirzaev\site\account\controllers
|
||||
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
||||
*/
|
||||
final class account_controller extends core
|
||||
{
|
||||
/**
|
||||
* Страница профиля
|
||||
*
|
||||
* @param array $parameters Параметры запроса
|
||||
*/
|
||||
public function index(array $parameters = []): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Инициализация
|
||||
*
|
||||
* @param array $parameters Параметры запроса
|
||||
*/
|
||||
public function initialization(array $parameters = []): ?string
|
||||
{
|
||||
if ($this->variables['account'] instanceof _document) {
|
||||
// Найден аккаунт
|
||||
|
||||
if ($this->variables['vk'] instanceof _document) {
|
||||
// Найден аккаунт ВКонтакте
|
||||
|
||||
// Инициализация данных аккаунта ВКонтакте
|
||||
vk::parse($this->variables['vk'], $this->variables['errors']['vk']);
|
||||
}
|
||||
|
||||
// Запись кода ответа
|
||||
http_response_code(200);
|
||||
|
||||
return null;
|
||||
} else {
|
||||
// Не найден аккаунт
|
||||
|
||||
// Запись кода ответа
|
||||
http_response_code(401);
|
||||
|
||||
// Запись заголовка ответа с ключом аккаунта
|
||||
header('session: ' . $this->variables['session']->hash);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// Запись кода ответа
|
||||
http_response_code(500);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Связь аккаунта с аккаунтом ВКонтакте
|
||||
*
|
||||
* @param array $parameters Параметры запроса
|
||||
*/
|
||||
public function connect(array $parameters = []): ?string
|
||||
{
|
||||
if ($this->variables['session']->hash === $parameters['state']) {
|
||||
// Совпадает хеш сессии с полученным хешем из ответа ВКонтакте
|
||||
|
||||
if (!empty($response = vk::key($parameters['code'], $this->variables['errors']['vk']))) {
|
||||
// Получены данные аккаунта ВКонтакте
|
||||
|
||||
if (($this->variables['vk'] = vk::initialization($response, $this->variables['errors']['vk'])) instanceof _document) {
|
||||
// Инициализирован аккаунт ВКонтакте
|
||||
|
||||
if (($this->variables['account'] = vk::account($this->variables['vk'])) instanceof _document) {
|
||||
// Найден аккаунт (существующий)
|
||||
|
||||
if (session::connect($this->variables['session'], $this->variables['account'], $this->variables['errors']['session'])) {
|
||||
// Связана сессия с аккаунтом
|
||||
}
|
||||
} else if (($this->variables['account'] = account::create($this->variables['errors']['account'])) instanceof _document) {
|
||||
// Найден аккаунт (создан новый)
|
||||
|
||||
if (session::connect($this->variables['session'], $this->variables['account'], $this->variables['errors']['session'])) {
|
||||
// Связана сессия с аккаунтом
|
||||
|
||||
if (account::connect($this->variables['account'], $this->variables['vk'], $this->variables['errors']['account'])) {
|
||||
// Связан аккаунт с аккаунтом ВКонтакте
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Инициализация робота для аккаунта ВКонтакте
|
||||
$this->vk = api::init()->user(key: $this->variables['vk']->access['key']);
|
||||
|
||||
if ($this->variables['vk'] instanceof _document) {
|
||||
// Инициализирован робот для аккаунта ВКонтакте
|
||||
|
||||
// Инициализация данных аккаунта ВКонтакте
|
||||
$data = vk::parse($this->vk, $this->variables['errors']['vk']);
|
||||
var_dump($data); die;
|
||||
|
||||
if ($data instanceof stdClass) {
|
||||
// Получены данные ВКонтакте
|
||||
|
||||
// Запись в базу данных
|
||||
vk::update($this->variables['vk'], $data, $this->variables['errors']['vk']);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Генерация представления
|
||||
return $this->view->render(DIRECTORY_SEPARATOR . 'account' . DIRECTORY_SEPARATOR . 'vk.html', $this->variables);
|
||||
}
|
||||
|
||||
/**
|
||||
* Генерация панели аккаунта
|
||||
*
|
||||
* @param array $parameters Параметры запроса
|
||||
*/
|
||||
public function panel(array $parameters = []): ?string
|
||||
{
|
||||
// Генерация представления
|
||||
return $this->view->render(DIRECTORY_SEPARATOR . 'account' . DIRECTORY_SEPARATOR . 'panel.html', $this->variables);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -61,7 +61,7 @@ class core extends controller
|
|||
$expires = time() + 604800;
|
||||
|
||||
// Инициализация сессии (без журналирования)
|
||||
$this->variables['session'] = session::initialization($_COOKIE["session"] ?? null, $expires) ?? header('Location: https://mirzaev.sexy/error?code=500&text=Не+удалось+инициализировать+сессию');
|
||||
$this->variables['session'] = new session($_COOKIE["session"] ?? null, $expires) ?? header('Location: https://mirzaev.sexy/error?code=500&text=Не+удалось+инициализировать+сессию');
|
||||
|
||||
if ($_COOKIE["session"] ?? null !== $this->variables['session']->hash) {
|
||||
// Изменился хеш сессии (подразумевается, что сессия устарела)
|
||||
|
@ -78,7 +78,7 @@ class core extends controller
|
|||
}
|
||||
|
||||
// Инициализация аккаунта (без журналирования)
|
||||
$this->variables['account'] = session::account($this->variables['session']);
|
||||
$this->variables['account'] = $this->variables['session']->account();
|
||||
|
||||
if ($this->variables['account'] instanceof _document) {
|
||||
// Инициализирован аккаунт
|
||||
|
|
|
@ -1,44 +1,44 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace mirzaev\site\account\controllers;
|
||||
|
||||
// Файлы проекта
|
||||
use mirzaev\site\account\controllers\core;
|
||||
|
||||
/**
|
||||
* Контроллер ошибок
|
||||
*
|
||||
* @package mirzaev\site\account\controllers
|
||||
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
||||
*/
|
||||
final class error_controller extends core
|
||||
{
|
||||
/**
|
||||
* Страница с ошибкой
|
||||
*
|
||||
* @param array $parameters
|
||||
*/
|
||||
public function index(array $parameters = []): ?string
|
||||
{
|
||||
// Запись текста ошибки в переменную окружения
|
||||
$this->variables['text'] = $parameters['text'] ?? null;
|
||||
|
||||
if (isset($parameters['code'])) {
|
||||
// Получен код ошибки
|
||||
|
||||
// Запись кода ошибки в переменную окружения
|
||||
$this->variables['code'] = $parameters['code'];
|
||||
|
||||
// Запись кода ответа
|
||||
http_response_code($parameters['code']);
|
||||
|
||||
// Генерация представления
|
||||
return $this->view->render(DIRECTORY_SEPARATOR . 'errors' . DIRECTORY_SEPARATOR . 'index.html', $this->variables);
|
||||
}
|
||||
|
||||
// Генерация представления
|
||||
return $this->view->render(DIRECTORY_SEPARATOR . 'errors' . DIRECTORY_SEPARATOR . ($parameters['code'] ?? 'index') . '.html', $this->variables);
|
||||
}
|
||||
}
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace mirzaev\site\account\controllers;
|
||||
|
||||
// Файлы проекта
|
||||
use mirzaev\site\account\controllers\core;
|
||||
|
||||
/**
|
||||
* Контроллер ошибок
|
||||
*
|
||||
* @package mirzaev\site\account\controllers
|
||||
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
||||
*/
|
||||
final class error_controller extends core
|
||||
{
|
||||
/**
|
||||
* Страница с ошибкой
|
||||
*
|
||||
* @param array $parameters
|
||||
*/
|
||||
public function index(array $parameters = []): ?string
|
||||
{
|
||||
// Запись текста ошибки в переменную окружения
|
||||
$this->variables['text'] = $parameters['text'] ?? null;
|
||||
|
||||
if (isset($parameters['code'])) {
|
||||
// Получен код ошибки
|
||||
|
||||
// Запись кода ошибки в переменную окружения
|
||||
$this->variables['code'] = $parameters['code'];
|
||||
|
||||
// Запись кода ответа
|
||||
http_response_code($parameters['code']);
|
||||
|
||||
// Генерация представления
|
||||
return $this->view->render(DIRECTORY_SEPARATOR . 'errors' . DIRECTORY_SEPARATOR . 'index.html', $this->variables);
|
||||
}
|
||||
|
||||
// Генерация представления
|
||||
return $this->view->render(DIRECTORY_SEPARATOR . 'errors' . DIRECTORY_SEPARATOR . ($parameters['code'] ?? 'index') . '.html', $this->variables);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,59 +1,59 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace mirzaev\site\account\controllers;
|
||||
|
||||
// Файлы проекта
|
||||
use mirzaev\site\account\controllers\core;
|
||||
|
||||
/**
|
||||
* Контроллер графика
|
||||
*
|
||||
* @package mirzaev\site\account\controllers
|
||||
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
||||
*/
|
||||
final class graph_controller extends core
|
||||
{
|
||||
/**
|
||||
* Страница с графиком
|
||||
*
|
||||
* Можно использовать совместно с элементом <iframe> для изоляции
|
||||
* содержимого бегущей строки от поисковых роботов
|
||||
*
|
||||
* @param array $parameters
|
||||
*/
|
||||
public function index(array $parameters = []): ?string
|
||||
{
|
||||
// Инициализация элементов для генерации в головном элементе
|
||||
$this->variables['head'] = [
|
||||
'title' => 'Бегущая строка',
|
||||
'metas' => [
|
||||
[
|
||||
'attributes' => [
|
||||
'name' => 'robots',
|
||||
'content' => 'nofollow'
|
||||
]
|
||||
]
|
||||
]
|
||||
];
|
||||
|
||||
// Инициализация бегущей строки
|
||||
$this->variables['graph'] = [
|
||||
'id' => $this->variables['request']['id'] ?? 'graph'
|
||||
];
|
||||
|
||||
// Инициализация аттрибутов бегущей строки
|
||||
$this->variables['graph']['attributes'] = [
|
||||
|
||||
];
|
||||
|
||||
// Инициализация элементов бегущей строки
|
||||
$this->variables['graph']['elements'] = [
|
||||
];
|
||||
|
||||
// Генерация представления
|
||||
return $this->view->render(DIRECTORY_SEPARATOR . 'graph' . DIRECTORY_SEPARATOR . 'index.html', $this->variables);
|
||||
}
|
||||
|
||||
}
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace mirzaev\site\account\controllers;
|
||||
|
||||
// Файлы проекта
|
||||
use mirzaev\site\account\controllers\core;
|
||||
|
||||
/**
|
||||
* Контроллер графика
|
||||
*
|
||||
* @package mirzaev\site\account\controllers
|
||||
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
||||
*/
|
||||
final class graph_controller extends core
|
||||
{
|
||||
/**
|
||||
* Страница с графиком
|
||||
*
|
||||
* Можно использовать совместно с элементом <iframe> для изоляции
|
||||
* содержимого бегущей строки от поисковых роботов
|
||||
*
|
||||
* @param array $parameters
|
||||
*/
|
||||
public function index(array $parameters = []): ?string
|
||||
{
|
||||
// Инициализация элементов для генерации в головном элементе
|
||||
$this->variables['head'] = [
|
||||
'title' => 'Бегущая строка',
|
||||
'metas' => [
|
||||
[
|
||||
'attributes' => [
|
||||
'name' => 'robots',
|
||||
'content' => 'nofollow'
|
||||
]
|
||||
]
|
||||
]
|
||||
];
|
||||
|
||||
// Инициализация бегущей строки
|
||||
$this->variables['graph'] = [
|
||||
'id' => $this->variables['request']['id'] ?? 'graph'
|
||||
];
|
||||
|
||||
// Инициализация аттрибутов бегущей строки
|
||||
$this->variables['graph']['attributes'] = [
|
||||
|
||||
];
|
||||
|
||||
// Инициализация элементов бегущей строки
|
||||
$this->variables['graph']['elements'] = [
|
||||
];
|
||||
|
||||
// Генерация представления
|
||||
return $this->view->render(DIRECTORY_SEPARATOR . 'graph' . DIRECTORY_SEPARATOR . 'index.html', $this->variables);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,82 +1,82 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace mirzaev\site\account\controllers;
|
||||
|
||||
// Файлы проекта
|
||||
use mirzaev\site\account\controllers\core;
|
||||
|
||||
/**
|
||||
* Контроллер бегущей строки
|
||||
*
|
||||
* @package mirzaev\site\account\controllers
|
||||
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
||||
*/
|
||||
final class hotline_controller extends core
|
||||
{
|
||||
/**
|
||||
* Страница с бегущей строкой
|
||||
*
|
||||
* Можно использовать совместно с элементом <iframe> для изоляции
|
||||
* содержимого бегущей строки от поисковых роботов
|
||||
*
|
||||
* @param array $parameters
|
||||
*/
|
||||
public function index(array $parameters = []): ?string
|
||||
{
|
||||
// Инициализация элементов для генерации в головном элементе
|
||||
$this->variables['head'] = [
|
||||
'title' => 'Бегущая строка',
|
||||
'metas' => [
|
||||
[
|
||||
'attributes' => [
|
||||
'name' => 'robots',
|
||||
'content' => 'nofollow'
|
||||
]
|
||||
]
|
||||
]
|
||||
];
|
||||
|
||||
// Инициализация бегущей строки
|
||||
$this->variables['hotline'] = [
|
||||
'id' => $this->variables['request']['id'] ?? 'hotline'
|
||||
];
|
||||
|
||||
// Инициализация параметров бегущей строки
|
||||
$this->variables['hotline']['parameters'] = [
|
||||
// 'step' => 2
|
||||
];
|
||||
|
||||
// Инициализация аттрибутов бегущей строки
|
||||
$this->variables['hotline']['attributes'] = [
|
||||
|
||||
];
|
||||
|
||||
// Инициализация элементов бегущей строки
|
||||
$this->variables['hotline']['elements'] = [
|
||||
['content' => '1'],
|
||||
[
|
||||
'tag' => 'article',
|
||||
'content' => '2'
|
||||
],
|
||||
['content' => '3'],
|
||||
['content' => '4'],
|
||||
['content' => '5'],
|
||||
['content' => '6'],
|
||||
['content' => '7'],
|
||||
['content' => '8'],
|
||||
['content' => '9'],
|
||||
['content' => '10'],
|
||||
['content' => '11'],
|
||||
['content' => '12'],
|
||||
['content' => '13'],
|
||||
['content' => '14'],
|
||||
['content' => '15']
|
||||
];
|
||||
|
||||
// Генерация представления
|
||||
return $this->view->render(DIRECTORY_SEPARATOR . 'hotline' . DIRECTORY_SEPARATOR . 'index.html', $this->variables);
|
||||
}
|
||||
|
||||
}
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace mirzaev\site\account\controllers;
|
||||
|
||||
// Файлы проекта
|
||||
use mirzaev\site\account\controllers\core;
|
||||
|
||||
/**
|
||||
* Контроллер бегущей строки
|
||||
*
|
||||
* @package mirzaev\site\account\controllers
|
||||
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
||||
*/
|
||||
final class hotline_controller extends core
|
||||
{
|
||||
/**
|
||||
* Страница с бегущей строкой
|
||||
*
|
||||
* Можно использовать совместно с элементом <iframe> для изоляции
|
||||
* содержимого бегущей строки от поисковых роботов
|
||||
*
|
||||
* @param array $parameters
|
||||
*/
|
||||
public function index(array $parameters = []): ?string
|
||||
{
|
||||
// Инициализация элементов для генерации в головном элементе
|
||||
$this->variables['head'] = [
|
||||
'title' => 'Бегущая строка',
|
||||
'metas' => [
|
||||
[
|
||||
'attributes' => [
|
||||
'name' => 'robots',
|
||||
'content' => 'nofollow'
|
||||
]
|
||||
]
|
||||
]
|
||||
];
|
||||
|
||||
// Инициализация бегущей строки
|
||||
$this->variables['hotline'] = [
|
||||
'id' => $this->variables['request']['id'] ?? 'hotline'
|
||||
];
|
||||
|
||||
// Инициализация параметров бегущей строки
|
||||
$this->variables['hotline']['parameters'] = [
|
||||
// 'step' => 2
|
||||
];
|
||||
|
||||
// Инициализация аттрибутов бегущей строки
|
||||
$this->variables['hotline']['attributes'] = [
|
||||
|
||||
];
|
||||
|
||||
// Инициализация элементов бегущей строки
|
||||
$this->variables['hotline']['elements'] = [
|
||||
['content' => '1'],
|
||||
[
|
||||
'tag' => 'article',
|
||||
'content' => '2'
|
||||
],
|
||||
['content' => '3'],
|
||||
['content' => '4'],
|
||||
['content' => '5'],
|
||||
['content' => '6'],
|
||||
['content' => '7'],
|
||||
['content' => '8'],
|
||||
['content' => '9'],
|
||||
['content' => '10'],
|
||||
['content' => '11'],
|
||||
['content' => '12'],
|
||||
['content' => '13'],
|
||||
['content' => '14'],
|
||||
['content' => '15']
|
||||
];
|
||||
|
||||
// Генерация представления
|
||||
return $this->view->render(DIRECTORY_SEPARATOR . 'hotline' . DIRECTORY_SEPARATOR . 'index.html', $this->variables);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,85 +1,80 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace mirzaev\site\account\controllers;
|
||||
|
||||
// Файлы проекта
|
||||
use mirzaev\site\account\controllers\core;
|
||||
|
||||
/**
|
||||
* Контроллер основной страницы
|
||||
*
|
||||
* @package mirzaev\site\account\controllers
|
||||
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
||||
*/
|
||||
final class index_controller extends core
|
||||
{
|
||||
/**
|
||||
* Главная страница
|
||||
*
|
||||
* @param array $parameters Параметры запроса
|
||||
*/
|
||||
public function index(array $parameters = []): ?string
|
||||
{
|
||||
// Инициализация загружаемых категорий
|
||||
$this->variables['include'] = [
|
||||
'head' => ['self'],
|
||||
'body' => ['self']
|
||||
];
|
||||
|
||||
// Инициализация бегущей строки
|
||||
$this->variables['hotline'] = [
|
||||
'id' => $this->variables['request']['id'] ?? 'hotline'
|
||||
];
|
||||
|
||||
// Инициализация параметров бегущей строки
|
||||
$this->variables['hotline']['parameters'] = [
|
||||
// 'step' => 2
|
||||
];
|
||||
|
||||
// Инициализация аттрибутов бегущей строки
|
||||
$this->variables['hotline']['attributes'] = [
|
||||
|
||||
];
|
||||
|
||||
// Инициализация элементов бегущей строки
|
||||
$this->variables['hotline']['elements'] = [
|
||||
['content' => '1'],
|
||||
[
|
||||
'tag' => 'article',
|
||||
'content' => '2'
|
||||
],
|
||||
['content' => '3'],
|
||||
['content' => '4'],
|
||||
['content' => '5'],
|
||||
['content' => '6'],
|
||||
['content' => '7'],
|
||||
['content' => '8'],
|
||||
['content' => '9'],
|
||||
['content' => '10'],
|
||||
['content' => '11'],
|
||||
['content' => '12'],
|
||||
['content' => '13'],
|
||||
['content' => '14'],
|
||||
['content' => '15']
|
||||
];
|
||||
|
||||
// Инициализация бегущей строки
|
||||
$this->variables['graph'] = [
|
||||
'id' => $this->variables['request']['id'] ?? 'graph'
|
||||
];
|
||||
|
||||
// Инициализация аттрибутов бегущей строки
|
||||
$this->variables['graph']['attributes'] = [
|
||||
|
||||
];
|
||||
|
||||
// Инициализация элементов бегущей строки
|
||||
$this->variables['graph']['elements'] = [
|
||||
];
|
||||
|
||||
// Генерация представления
|
||||
return $this->view->render(DIRECTORY_SEPARATOR . 'index.html', $this->variables);
|
||||
}
|
||||
}
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace mirzaev\site\account\controllers;
|
||||
|
||||
// Файлы проекта
|
||||
use mirzaev\site\account\controllers\core;
|
||||
|
||||
/**
|
||||
* Контроллер основной страницы
|
||||
*
|
||||
* @package mirzaev\site\account\controllers
|
||||
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
||||
*/
|
||||
final class index_controller extends core
|
||||
{
|
||||
/**
|
||||
* Главная страница
|
||||
*
|
||||
* @param array $parameters Параметры запроса
|
||||
*/
|
||||
public function index(array $parameters = []): ?string
|
||||
{
|
||||
// Инициализация загружаемых категорий
|
||||
$this->variables['include'] = [
|
||||
'head' => ['self'],
|
||||
'body' => ['self']
|
||||
];
|
||||
|
||||
// Инициализация бегущей строки
|
||||
$this->variables['hotline'] = [
|
||||
'id' => $this->variables['request']['id'] ?? 'hotline'
|
||||
];
|
||||
|
||||
// Инициализация параметров бегущей строки
|
||||
$this->variables['hotline']['parameters'] = [
|
||||
// 'step' => 2
|
||||
];
|
||||
|
||||
// Инициализация аттрибутов бегущей строки
|
||||
$this->variables['hotline']['attributes'] = [];
|
||||
|
||||
// Инициализация элементов бегущей строки
|
||||
$this->variables['hotline']['elements'] = [
|
||||
['content' => '1'],
|
||||
[
|
||||
'tag' => 'article',
|
||||
'content' => '2'
|
||||
],
|
||||
['content' => '3'],
|
||||
['content' => '4'],
|
||||
['content' => '5'],
|
||||
['content' => '6'],
|
||||
['content' => '7'],
|
||||
['content' => '8'],
|
||||
['content' => '9'],
|
||||
['content' => '10'],
|
||||
['content' => '11'],
|
||||
['content' => '12'],
|
||||
['content' => '13'],
|
||||
['content' => '14'],
|
||||
['content' => '15']
|
||||
];
|
||||
|
||||
// Инициализация бегущей строки
|
||||
$this->variables['graph'] = [
|
||||
'id' => $this->variables['request']['id'] ?? 'graph'
|
||||
];
|
||||
|
||||
// Инициализация аттрибутов бегущей строки
|
||||
$this->variables['graph']['attributes'] = [];
|
||||
|
||||
// Инициализация элементов бегущей строки
|
||||
$this->variables['graph']['elements'] = [];
|
||||
|
||||
// Генерация представления
|
||||
return $this->view->render(DIRECTORY_SEPARATOR . 'index.html', $this->variables);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,169 +1,169 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace mirzaev\site\account\models;
|
||||
|
||||
// Файлы проекта
|
||||
use mirzaev\site\account\models\vk_model as vk;
|
||||
|
||||
// Фреймворк ArangoDB
|
||||
use mirzaev\arangodb\collection,
|
||||
mirzaev\arangodb\document;
|
||||
|
||||
// Библиотека для ArangoDB
|
||||
use ArangoDBClient\Document as _document;
|
||||
|
||||
// Встроенные библиотеки
|
||||
use exception;
|
||||
|
||||
/**
|
||||
* Модель регистрации, аутентификации и авторизации
|
||||
*
|
||||
* @package mirzaev\site\account\models
|
||||
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
||||
*/
|
||||
final class account_model extends core
|
||||
{
|
||||
/**
|
||||
* Коллекция
|
||||
*/
|
||||
public const COLLECTION = 'account';
|
||||
|
||||
/**
|
||||
* Создать
|
||||
*
|
||||
* @param array &$errors Журнал ошибок
|
||||
*
|
||||
* @return ?_document Инстанция аккаунта, если удалось создать
|
||||
*/
|
||||
public static function create(array &$errors = []): ?_document
|
||||
{
|
||||
try {
|
||||
if (collection::init(static::$db->session, self::COLLECTION)) {
|
||||
// Инициализирована коллекция
|
||||
|
||||
// Запись аккаунта в базу данных
|
||||
$_id = document::write(static::$db->session, self::COLLECTION);
|
||||
|
||||
if ($account = collection::search(static::$db->session, sprintf(
|
||||
<<<AQL
|
||||
FOR d IN %s
|
||||
FILTER d._id == '$_id'
|
||||
RETURN d
|
||||
AQL,
|
||||
self::COLLECTION
|
||||
))) {
|
||||
// Найден созданный аккаунт
|
||||
|
||||
return $account;
|
||||
} else throw new exception('Не удалось создать аккаунт');
|
||||
} else throw new exception('Не удалось инициализировать коллекцию');
|
||||
} catch (exception $e) {
|
||||
// Запись в журнал ошибок
|
||||
$errors[] = [
|
||||
'text' => $e->getMessage(),
|
||||
'file' => $e->getFile(),
|
||||
'line' => $e->getLine(),
|
||||
'stack' => $e->getTrace()
|
||||
];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Связь аккаунта с аккаунтом ВКонтакте
|
||||
*
|
||||
* @param _document $account Инстанция аккаунта
|
||||
* @param _document $vk Инстанция аккаунта ВКонтакте
|
||||
* @param array &$errors Журнал ошибок
|
||||
*
|
||||
* @return bool Статус выполнения
|
||||
*/
|
||||
public static function connect(_document $account, _document $vk, array &$errors = []): bool
|
||||
{
|
||||
try {
|
||||
if (
|
||||
collection::init(static::$db->session, self::COLLECTION)
|
||||
&& collection::init(static::$db->session, vk::COLLECTION)
|
||||
&& collection::init(static::$db->session, self::COLLECTION . '_edge_' . vk::COLLECTION, true)
|
||||
) {
|
||||
// Инициализированы коллекции
|
||||
|
||||
if (document::write(static::$db->session, self::COLLECTION . '_edge_' . vk::COLLECTION, [
|
||||
'_from' => $account->getId(),
|
||||
'_to' => $vk->getId()
|
||||
])) {
|
||||
// Создано ребро: account -> vk
|
||||
|
||||
return true;
|
||||
} else throw new exception('Не удалось создать ребро: account -> vk');
|
||||
} else throw new exception('Не удалось инициализировать коллекцию');
|
||||
} catch (exception $e) {
|
||||
// Запись в журнал ошибок
|
||||
$errors[] = [
|
||||
'text' => $e->getMessage(),
|
||||
'file' => $e->getFile(),
|
||||
'line' => $e->getLine(),
|
||||
'stack' => $e->getTrace()
|
||||
];
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Поиск связанного аккаунта ВКонтакте
|
||||
*
|
||||
* @param _document $account Инстанция аккаунта
|
||||
* @param array &$errors Журнал ошибок
|
||||
*
|
||||
* @return ?_document Инстанция аккаунта, если удалось найти
|
||||
*/
|
||||
public static function vk(_document $account, array &$errors = []): ?_document
|
||||
{
|
||||
try {
|
||||
if (
|
||||
collection::init(static::$db->session, self::COLLECTION)
|
||||
&& collection::init(static::$db->session, vk::COLLECTION)
|
||||
&& collection::init(static::$db->session, self::COLLECTION . '_edge_' . vk::COLLECTION, true)
|
||||
) {
|
||||
// Инициализирована коллекция
|
||||
|
||||
if ($vk = collection::search(static::$db->session, sprintf(
|
||||
<<<AQL
|
||||
FOR document IN %s
|
||||
LET edge = (
|
||||
FOR edge IN %s
|
||||
FILTER edge._from == '%s'
|
||||
SORT edge._key DESC
|
||||
LIMIT 1
|
||||
RETURN edge
|
||||
)
|
||||
FILTER document._id == edge[0]._to
|
||||
LIMIT 1
|
||||
RETURN document
|
||||
AQL,
|
||||
vk::COLLECTION,
|
||||
self::COLLECTION . '_edge_' . vk::COLLECTION,
|
||||
$account->getId()
|
||||
))) {
|
||||
// Найден аккаунт ВКонтакте
|
||||
|
||||
return $vk;
|
||||
} else throw new exception('Не удалось найти аккаунт ВКонтакте');
|
||||
} else throw new exception('Не удалось инициализировать коллекцию');
|
||||
} catch (exception $e) {
|
||||
// Запись в журнал ошибок
|
||||
$errors[] = [
|
||||
'text' => $e->getMessage(),
|
||||
'file' => $e->getFile(),
|
||||
'line' => $e->getLine(),
|
||||
'stack' => $e->getTrace()
|
||||
];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace mirzaev\site\account\models;
|
||||
|
||||
// Файлы проекта
|
||||
use mirzaev\site\account\models\vk_model as vk;
|
||||
|
||||
// Фреймворк ArangoDB
|
||||
use mirzaev\arangodb\collection,
|
||||
mirzaev\arangodb\document;
|
||||
|
||||
// Библиотека для ArangoDB
|
||||
use ArangoDBClient\Document as _document;
|
||||
|
||||
// Встроенные библиотеки
|
||||
use exception;
|
||||
|
||||
/**
|
||||
* Модель регистрации, аутентификации и авторизации
|
||||
*
|
||||
* @package mirzaev\site\account\models
|
||||
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
||||
*/
|
||||
final class account_model extends core
|
||||
{
|
||||
/**
|
||||
* Коллекция
|
||||
*/
|
||||
public const COLLECTION = 'account';
|
||||
|
||||
/**
|
||||
* Создать
|
||||
*
|
||||
* @param array &$errors Журнал ошибок
|
||||
*
|
||||
* @return ?_document Инстанция аккаунта, если удалось создать
|
||||
*/
|
||||
public static function create(array &$errors = []): ?_document
|
||||
{
|
||||
try {
|
||||
if (collection::init(static::$db->session, self::COLLECTION)) {
|
||||
// Инициализирована коллекция
|
||||
|
||||
// Запись аккаунта в базу данных
|
||||
$_id = document::write(static::$db->session, self::COLLECTION);
|
||||
|
||||
if ($account = collection::search(static::$db->session, sprintf(
|
||||
<<<AQL
|
||||
FOR d IN %s
|
||||
FILTER d._id == '$_id'
|
||||
RETURN d
|
||||
AQL,
|
||||
self::COLLECTION
|
||||
))) {
|
||||
// Найден созданный аккаунт
|
||||
|
||||
return $account;
|
||||
} else throw new exception('Не удалось создать аккаунт');
|
||||
} else throw new exception('Не удалось инициализировать коллекцию');
|
||||
} catch (exception $e) {
|
||||
// Запись в журнал ошибок
|
||||
$errors[] = [
|
||||
'text' => $e->getMessage(),
|
||||
'file' => $e->getFile(),
|
||||
'line' => $e->getLine(),
|
||||
'stack' => $e->getTrace()
|
||||
];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Связь аккаунта с аккаунтом ВКонтакте
|
||||
*
|
||||
* @param _document $account Инстанция аккаунта
|
||||
* @param _document $vk Инстанция аккаунта ВКонтакте
|
||||
* @param array &$errors Журнал ошибок
|
||||
*
|
||||
* @return bool Статус выполнения
|
||||
*/
|
||||
public static function connect(_document $account, _document $vk, array &$errors = []): bool
|
||||
{
|
||||
try {
|
||||
if (
|
||||
collection::init(static::$db->session, self::COLLECTION)
|
||||
&& collection::init(static::$db->session, vk::COLLECTION)
|
||||
&& collection::init(static::$db->session, self::COLLECTION . '_edge_' . vk::COLLECTION, true)
|
||||
) {
|
||||
// Инициализированы коллекции
|
||||
|
||||
if (document::write(static::$db->session, self::COLLECTION . '_edge_' . vk::COLLECTION, [
|
||||
'_from' => $account->getId(),
|
||||
'_to' => $vk->getId()
|
||||
])) {
|
||||
// Создано ребро: account -> vk
|
||||
|
||||
return true;
|
||||
} else throw new exception('Не удалось создать ребро: account -> vk');
|
||||
} else throw new exception('Не удалось инициализировать коллекцию');
|
||||
} catch (exception $e) {
|
||||
// Запись в журнал ошибок
|
||||
$errors[] = [
|
||||
'text' => $e->getMessage(),
|
||||
'file' => $e->getFile(),
|
||||
'line' => $e->getLine(),
|
||||
'stack' => $e->getTrace()
|
||||
];
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Поиск связанного аккаунта ВКонтакте
|
||||
*
|
||||
* @param _document $account Инстанция аккаунта
|
||||
* @param array &$errors Журнал ошибок
|
||||
*
|
||||
* @return ?_document Инстанция аккаунта, если удалось найти
|
||||
*/
|
||||
public static function vk(_document $account, array &$errors = []): ?_document
|
||||
{
|
||||
try {
|
||||
if (
|
||||
collection::init(static::$db->session, self::COLLECTION)
|
||||
&& collection::init(static::$db->session, vk::COLLECTION)
|
||||
&& collection::init(static::$db->session, self::COLLECTION . '_edge_' . vk::COLLECTION, true)
|
||||
) {
|
||||
// Инициализирована коллекция
|
||||
|
||||
if ($vk = collection::search(static::$db->session, sprintf(
|
||||
<<<AQL
|
||||
FOR document IN %s
|
||||
LET edge = (
|
||||
FOR edge IN %s
|
||||
FILTER edge._from == '%s'
|
||||
SORT edge._key DESC
|
||||
LIMIT 1
|
||||
RETURN edge
|
||||
)
|
||||
FILTER document._id == edge[0]._to
|
||||
LIMIT 1
|
||||
RETURN document
|
||||
AQL,
|
||||
vk::COLLECTION,
|
||||
self::COLLECTION . '_edge_' . vk::COLLECTION,
|
||||
$account->getId()
|
||||
))) {
|
||||
// Найден аккаунт ВКонтакте
|
||||
|
||||
return $vk;
|
||||
} else throw new exception('Не удалось найти аккаунт ВКонтакте');
|
||||
} else throw new exception('Не удалось инициализировать коллекцию');
|
||||
} catch (exception $e) {
|
||||
// Запись в журнал ошибок
|
||||
$errors[] = [
|
||||
'text' => $e->getMessage(),
|
||||
'file' => $e->getFile(),
|
||||
'line' => $e->getLine(),
|
||||
'stack' => $e->getTrace()
|
||||
];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,143 +1,143 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace mirzaev\site\account\models;
|
||||
|
||||
use mirzaev\minimal\model;
|
||||
|
||||
use mirzaev\arangodb\connection;
|
||||
|
||||
use exception;
|
||||
|
||||
/**
|
||||
* Ядро моделей
|
||||
*
|
||||
* @package mirzaev\site\account\models
|
||||
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
||||
*/
|
||||
class core extends model
|
||||
{
|
||||
/**
|
||||
* Коллекция в которой хранятся аккаунты
|
||||
*/
|
||||
public const SETTINGS = '../settings/arangodb.php';
|
||||
|
||||
/**
|
||||
* Соединение с базой данных
|
||||
*/
|
||||
protected static connection $db;
|
||||
|
||||
public function __construct(connection $db = null)
|
||||
{
|
||||
if (isset($db)) {
|
||||
// Получена инстанция соединения с базой данных
|
||||
|
||||
// Запись и инициализация соединения с базой данных
|
||||
$this->__set('db', $db);
|
||||
} else {
|
||||
// Не получена инстанция соединения с базой данных
|
||||
|
||||
// Инициализация соединения с базой данных по умолчанию
|
||||
$this->__get('db');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Записать свойство
|
||||
*
|
||||
* @param string $name Название
|
||||
* @param mixed $value Значение
|
||||
*/
|
||||
public function __set(string $name, mixed $value = null): void
|
||||
{
|
||||
match ($name) {
|
||||
'db' => (function () use ($value) {
|
||||
if ($this->__isset('db')) {
|
||||
// Свойство уже было инициализировано
|
||||
|
||||
// Выброс исключения (неудача)
|
||||
throw new exception('Запрещено реинициализировать соединение с базой данных ($this->db)', 500);
|
||||
} else {
|
||||
// Свойство ещё не было инициализировано
|
||||
|
||||
if ($value instanceof connection) {
|
||||
// Передано подходящее значение
|
||||
|
||||
// Запись свойства (успех)
|
||||
self::$db = $value;
|
||||
} else {
|
||||
// Передано неподходящее значение
|
||||
|
||||
// Выброс исключения (неудача)
|
||||
throw new exception('Соединение с базой данных ($this->db) должен быть инстанцией mirzaev\arangodb\connection', 500);
|
||||
}
|
||||
}
|
||||
})(),
|
||||
default => parent::__set($name, $value)
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Прочитать свойство
|
||||
*
|
||||
* @param string $name Название
|
||||
*
|
||||
* @return mixed Содержимое
|
||||
*/
|
||||
public function __get(string $name): mixed
|
||||
{
|
||||
return match ($name) {
|
||||
'db' => (function () {
|
||||
if (!$this->__isset('db')) {
|
||||
// Свойство не инициализировано
|
||||
|
||||
// Инициализация значения по умолчанию исходя из настроек
|
||||
$this->__set('db', new connection(require static::SETTINGS));
|
||||
}
|
||||
|
||||
return self::$db;
|
||||
})(),
|
||||
default => parent::__get($name)
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Проверить свойство на инициализированность
|
||||
*
|
||||
* @param string $name Название
|
||||
*/
|
||||
public function __isset(string $name): bool
|
||||
{
|
||||
return match ($name) {
|
||||
default => parent::__isset($name)
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Удалить свойство
|
||||
*
|
||||
* @param string $name Название
|
||||
*/
|
||||
public function __unset(string $name): void
|
||||
{
|
||||
match ($name) {
|
||||
default => parent::__isset($name)
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Статический вызов
|
||||
*
|
||||
* @param string $name Название
|
||||
* @param array $arguments Параметры
|
||||
*/
|
||||
public static function __callStatic(string $name, array $arguments): mixed
|
||||
{
|
||||
match ($name) {
|
||||
'db' => (new static)->__get('db'),
|
||||
default => throw new exception("Не найдено свойство или функция: $name", 500)
|
||||
};
|
||||
}
|
||||
}
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace mirzaev\site\account\models;
|
||||
|
||||
use mirzaev\minimal\model;
|
||||
|
||||
use mirzaev\arangodb\connection;
|
||||
|
||||
use exception;
|
||||
|
||||
/**
|
||||
* Ядро моделей
|
||||
*
|
||||
* @package mirzaev\site\account\models
|
||||
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
||||
*/
|
||||
class core extends model
|
||||
{
|
||||
/**
|
||||
* Коллекция в которой хранятся аккаунты
|
||||
*/
|
||||
public const SETTINGS = '../settings/arangodb.php';
|
||||
|
||||
/**
|
||||
* Соединение с базой данных
|
||||
*/
|
||||
protected static connection $db;
|
||||
|
||||
public function __construct(connection $db = null)
|
||||
{
|
||||
if (isset($db)) {
|
||||
// Получена инстанция соединения с базой данных
|
||||
|
||||
// Запись и инициализация соединения с базой данных
|
||||
$this->__set('db', $db);
|
||||
} else {
|
||||
// Не получена инстанция соединения с базой данных
|
||||
|
||||
// Инициализация соединения с базой данных по умолчанию
|
||||
$this->__get('db');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Записать свойство
|
||||
*
|
||||
* @param string $name Название
|
||||
* @param mixed $value Значение
|
||||
*/
|
||||
public function __set(string $name, mixed $value = null): void
|
||||
{
|
||||
match ($name) {
|
||||
'db' => (function () use ($value) {
|
||||
if ($this->__isset('db')) {
|
||||
// Свойство уже было инициализировано
|
||||
|
||||
// Выброс исключения (неудача)
|
||||
throw new exception('Запрещено реинициализировать соединение с базой данных ($this->db)', 500);
|
||||
} else {
|
||||
// Свойство ещё не было инициализировано
|
||||
|
||||
if ($value instanceof connection) {
|
||||
// Передано подходящее значение
|
||||
|
||||
// Запись свойства (успех)
|
||||
self::$db = $value;
|
||||
} else {
|
||||
// Передано неподходящее значение
|
||||
|
||||
// Выброс исключения (неудача)
|
||||
throw new exception('Соединение с базой данных ($this->db) должен быть инстанцией mirzaev\arangodb\connection', 500);
|
||||
}
|
||||
}
|
||||
})(),
|
||||
default => parent::__set($name, $value)
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Прочитать свойство
|
||||
*
|
||||
* @param string $name Название
|
||||
*
|
||||
* @return mixed Содержимое
|
||||
*/
|
||||
public function __get(string $name): mixed
|
||||
{
|
||||
return match ($name) {
|
||||
'db' => (function () {
|
||||
if (!$this->__isset('db')) {
|
||||
// Свойство не инициализировано
|
||||
|
||||
// Инициализация значения по умолчанию исходя из настроек
|
||||
$this->__set('db', new connection(require static::SETTINGS));
|
||||
}
|
||||
|
||||
return self::$db;
|
||||
})(),
|
||||
default => parent::__get($name)
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Проверить свойство на инициализированность
|
||||
*
|
||||
* @param string $name Название
|
||||
*/
|
||||
public function __isset(string $name): bool
|
||||
{
|
||||
return match ($name) {
|
||||
default => parent::__isset($name)
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Удалить свойство
|
||||
*
|
||||
* @param string $name Название
|
||||
*/
|
||||
public function __unset(string $name): void
|
||||
{
|
||||
match ($name) {
|
||||
default => parent::__isset($name)
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Статический вызов
|
||||
*
|
||||
* @param string $name Название
|
||||
* @param array $arguments Параметры
|
||||
*/
|
||||
public static function __callStatic(string $name, array $arguments): mixed
|
||||
{
|
||||
match ($name) {
|
||||
'db' => (new static)->__get('db'),
|
||||
default => throw new exception("Не найдено свойство или функция: $name", 500)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,213 +1,249 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace mirzaev\site\account\models;
|
||||
|
||||
// Файлы проекта
|
||||
use mirzaev\site\account\models\account_model as account;
|
||||
|
||||
// Фреймворк ArangoDB
|
||||
use mirzaev\arangodb\collection,
|
||||
mirzaev\arangodb\document;
|
||||
|
||||
// Библиотека для ArangoDB
|
||||
use ArangoDBClient\Document as _document;
|
||||
|
||||
// Встроенные библиотеки
|
||||
use exception;
|
||||
|
||||
/**
|
||||
* Модель сессий
|
||||
*
|
||||
* @package mirzaev\site\account\models
|
||||
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
||||
*/
|
||||
final class session_model extends core
|
||||
{
|
||||
/**
|
||||
* Коллекция
|
||||
*/
|
||||
public const COLLECTION = 'session';
|
||||
|
||||
/**
|
||||
* Инициализация
|
||||
*
|
||||
* @param ?string $hash Хеш сессии в базе данных
|
||||
* @param ?int $expires Дата окончания работы сессии (используется при создании новой сессии)
|
||||
* @param array &$errors Журнал ошибок
|
||||
*
|
||||
* @return ?_document Инстанция сессии, если удалось найти или создать
|
||||
*/
|
||||
public static function initialization(?string $hash = null, ?int $expires = null, array &$errors = []): ?_document
|
||||
{
|
||||
try {
|
||||
if (collection::init(static::$db->session, self::COLLECTION)) {
|
||||
// Инициализирована коллекция
|
||||
|
||||
if (isset($hash) && $session = collection::search(static::$db->session, sprintf(
|
||||
<<<AQL
|
||||
FOR d IN %s
|
||||
FILTER d.hash == '$hash' && d.expires > %d
|
||||
RETURN d
|
||||
AQL,
|
||||
self::COLLECTION,
|
||||
time()
|
||||
))) {
|
||||
// Найдена сессия по хешу
|
||||
|
||||
// Возврат сессии
|
||||
return $session;
|
||||
} else if ($session = collection::search(static::$db->session, sprintf(
|
||||
<<<AQL
|
||||
FOR d IN %s
|
||||
FILTER d.ip == '%s' && d.expires > %d
|
||||
RETURN d
|
||||
AQL,
|
||||
self::COLLECTION,
|
||||
$_SERVER['REMOTE_ADDR'],
|
||||
time()
|
||||
))) {
|
||||
// Найдена сессия по данным пользователя
|
||||
|
||||
// Возврат сессии
|
||||
return $session;
|
||||
} else {
|
||||
// Не найдена сессия
|
||||
|
||||
// Запись сессии в базу данных
|
||||
$_id = document::write(static::$db->session, self::COLLECTION, [
|
||||
'ip' => $_SERVER['REMOTE_ADDR'],
|
||||
'expires' => $expires ?? time() + 604800
|
||||
]);
|
||||
|
||||
if ($session = collection::search(static::$db->session, sprintf(
|
||||
<<<AQL
|
||||
FOR d IN %s
|
||||
FILTER d._id == '$_id' && d.expires > %d
|
||||
RETURN d
|
||||
AQL,
|
||||
self::COLLECTION,
|
||||
time()
|
||||
))) {
|
||||
// Найдена созданная сессия
|
||||
|
||||
// Запись хеша
|
||||
$session->hash = sodium_bin2hex(sodium_crypto_generichash($_id));
|
||||
|
||||
if (document::update(static::$db->session, $session)) {
|
||||
// Записано обновление
|
||||
|
||||
return $session;
|
||||
} else throw new exception('Не удалось записать данные сессии');
|
||||
} else throw new exception('Не удалось создать или найти созданную сессию');
|
||||
}
|
||||
} else throw new exception('Не удалось инициализировать коллекцию');
|
||||
} catch (exception $e) {
|
||||
// Запись в журнал ошибок
|
||||
$errors[] = [
|
||||
'text' => $e->getMessage(),
|
||||
'file' => $e->getFile(),
|
||||
'line' => $e->getLine(),
|
||||
'stack' => $e->getTrace()
|
||||
];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Связь сессии с аккаунтом
|
||||
*
|
||||
* @param _document $session Инстанция сессии
|
||||
* @param _document $account Инстанция аккаунта
|
||||
* @param array &$errors Журнал ошибок
|
||||
*
|
||||
* @return bool Статус выполнения
|
||||
*/
|
||||
public static function connect(_document $session, _document $account, array &$errors = []): bool
|
||||
{
|
||||
try {
|
||||
if (
|
||||
collection::init(static::$db->session, self::COLLECTION)
|
||||
&& collection::init(static::$db->session, account::COLLECTION)
|
||||
&& collection::init(static::$db->session, self::COLLECTION . '_edge_' . account::COLLECTION, true)
|
||||
) {
|
||||
// Инициализирована коллекция
|
||||
|
||||
if (document::write(static::$db->session, self::COLLECTION . '_edge_' . account::COLLECTION, [
|
||||
'_from' => $session->getId(),
|
||||
'_to' => $account->getId()
|
||||
])) {
|
||||
// Создано ребро: session -> account
|
||||
|
||||
return true;
|
||||
} else throw new exception('Не удалось создать ребро: session -> account');
|
||||
} else throw new exception('Не удалось инициализировать коллекцию');
|
||||
} catch (exception $e) {
|
||||
// Запись в журнал ошибок
|
||||
$errors[] = [
|
||||
'text' => $e->getMessage(),
|
||||
'file' => $e->getFile(),
|
||||
'line' => $e->getLine(),
|
||||
'stack' => $e->getTrace()
|
||||
];
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Поиск связанного аккаунта
|
||||
*
|
||||
* @param _document $session Инстанция сессии
|
||||
* @param array &$errors Журнал ошибок
|
||||
*
|
||||
* @return ?_document Инстанция аккаунта, если удалось найти
|
||||
*/
|
||||
public static function account(_document $session, array &$errors = []): ?_document
|
||||
{
|
||||
try {
|
||||
if (
|
||||
collection::init(static::$db->session, self::COLLECTION)
|
||||
&& collection::init(static::$db->session, account::COLLECTION)
|
||||
&& collection::init(static::$db->session, self::COLLECTION . '_edge_' . account::COLLECTION, true)
|
||||
) {
|
||||
// Инициализированы коллекции
|
||||
|
||||
if ($account = collection::search(static::$db->session, sprintf(
|
||||
<<<AQL
|
||||
FOR document IN %s
|
||||
LET edge = (
|
||||
FOR edge IN %s
|
||||
FILTER edge._from == '%s'
|
||||
SORT edge._key DESC
|
||||
LIMIT 1
|
||||
RETURN edge
|
||||
)
|
||||
FILTER document._id == edge[0]._to
|
||||
LIMIT 1
|
||||
RETURN document
|
||||
AQL,
|
||||
account::COLLECTION,
|
||||
self::COLLECTION . '_edge_' . account::COLLECTION,
|
||||
$session->getId()
|
||||
))) {
|
||||
// Найден аккаунт
|
||||
|
||||
return $account;
|
||||
} else throw new exception('Не удалось найти аккаунт');
|
||||
} else throw new exception('Не удалось инициализировать коллекцию');
|
||||
} catch (exception $e) {
|
||||
// Запись в журнал ошибок
|
||||
$errors[] = [
|
||||
'text' => $e->getMessage(),
|
||||
'file' => $e->getFile(),
|
||||
'line' => $e->getLine(),
|
||||
'stack' => $e->getTrace()
|
||||
];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace mirzaev\site\account\models;
|
||||
|
||||
// Файлы проекта
|
||||
use mirzaev\site\account\models\account_model as account;
|
||||
|
||||
// Фреймворк ArangoDB
|
||||
use mirzaev\arangodb\collection,
|
||||
mirzaev\arangodb\document;
|
||||
|
||||
// Библиотека для ArangoDB
|
||||
use ArangoDBClient\Document as _document;
|
||||
|
||||
// Встроенные библиотеки
|
||||
use exception;
|
||||
|
||||
/**
|
||||
* Модель сессий
|
||||
*
|
||||
* @package mirzaev\site\account\models
|
||||
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
||||
*/
|
||||
final class session_model extends core
|
||||
{
|
||||
/**
|
||||
* Коллекция
|
||||
*/
|
||||
public const COLLECTION = 'session';
|
||||
|
||||
/**
|
||||
* Данные сессии из базы данных
|
||||
*/
|
||||
public _document $document;
|
||||
|
||||
/**
|
||||
* Конструктор
|
||||
*
|
||||
* Инициализация сессии и запись в свойство $this->document
|
||||
*
|
||||
* @param ?string $hash Хеш сессии в базе данных
|
||||
* @param ?int $expires Дата окончания работы сессии (используется при создании новой сессии)
|
||||
* @param array &$errors Журнал ошибок
|
||||
*
|
||||
* @return static Инстанция сессии
|
||||
*/
|
||||
public function __construct(?string $hash = null, ?int $expires = null, array &$errors = [])
|
||||
{
|
||||
try {
|
||||
if (collection::init(static::$db->session, self::COLLECTION)) {
|
||||
// Инициализирована коллекция
|
||||
|
||||
if (isset($hash) && $session = collection::search(static::$db->session, sprintf(
|
||||
<<<AQL
|
||||
FOR d IN %s
|
||||
FILTER d.hash == '$hash' && d.expires > %d
|
||||
RETURN d
|
||||
AQL,
|
||||
self::COLLECTION,
|
||||
time()
|
||||
))) {
|
||||
// Найдена сессия по хешу
|
||||
|
||||
// Запись в свойство
|
||||
$this->document = $session;
|
||||
} else if ($session = collection::search(static::$db->session, sprintf(
|
||||
<<<AQL
|
||||
FOR d IN %s
|
||||
FILTER d.ip == '%s' && d.expires > %d
|
||||
RETURN d
|
||||
AQL,
|
||||
self::COLLECTION,
|
||||
$_SERVER['REMOTE_ADDR'],
|
||||
time()
|
||||
))) {
|
||||
// Найдена сессия по данным пользователя
|
||||
|
||||
// Запись в свойство
|
||||
$this->document = $session;
|
||||
} else {
|
||||
// Не найдена сессия
|
||||
|
||||
// Запись сессии в базу данных
|
||||
$_id = document::write(static::$db->session, self::COLLECTION, [
|
||||
'ip' => $_SERVER['REMOTE_ADDR'],
|
||||
'expires' => $expires ?? time() + 604800
|
||||
]);
|
||||
|
||||
if ($session = collection::search(static::$db->session, sprintf(
|
||||
<<<AQL
|
||||
FOR d IN %s
|
||||
FILTER d._id == '$_id' && d.expires > %d
|
||||
RETURN d
|
||||
AQL,
|
||||
self::COLLECTION,
|
||||
time()
|
||||
))) {
|
||||
// Найдена созданная сессия
|
||||
|
||||
// Запись хеша
|
||||
$session->hash = sodium_bin2hex(sodium_crypto_generichash($_id));
|
||||
|
||||
if (document::update(static::$db->session, $session)) {
|
||||
// Записано обновление
|
||||
|
||||
// Запись в свойство
|
||||
$this->document = $session;
|
||||
} else throw new exception('Не удалось записать данные сессии');
|
||||
} else throw new exception('Не удалось создать или найти созданную сессию');
|
||||
}
|
||||
} else throw new exception('Не удалось инициализировать коллекцию');
|
||||
} catch (exception $e) {
|
||||
// Запись в журнал ошибок
|
||||
$errors[] = [
|
||||
'text' => $e->getMessage(),
|
||||
'file' => $e->getFile(),
|
||||
'line' => $e->getLine(),
|
||||
'stack' => $e->getTrace()
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Связь сессии с аккаунтом
|
||||
*
|
||||
* @param _document $account Инстанция аккаунта
|
||||
* @param array &$errors Журнал ошибок
|
||||
*
|
||||
* @return bool Статус выполнения
|
||||
*/
|
||||
public function connect(_document $account, array &$errors = []): bool
|
||||
{
|
||||
try {
|
||||
if (
|
||||
collection::init(static::$db->session, self::COLLECTION)
|
||||
&& collection::init(static::$db->session, account::COLLECTION)
|
||||
&& collection::init(static::$db->session, self::COLLECTION . '_edge_' . account::COLLECTION, true)
|
||||
) {
|
||||
// Инициализирована коллекция
|
||||
|
||||
if (document::write(static::$db->session, self::COLLECTION . '_edge_' . account::COLLECTION, [
|
||||
'_from' => $this->document->getId(),
|
||||
'_to' => $account->getId()
|
||||
])) {
|
||||
// Создано ребро: session -> account
|
||||
|
||||
return true;
|
||||
} else throw new exception('Не удалось создать ребро: session -> account');
|
||||
} else throw new exception('Не удалось инициализировать коллекцию');
|
||||
} catch (exception $e) {
|
||||
// Запись в журнал ошибок
|
||||
$errors[] = [
|
||||
'text' => $e->getMessage(),
|
||||
'file' => $e->getFile(),
|
||||
'line' => $e->getLine(),
|
||||
'stack' => $e->getTrace()
|
||||
];
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Поиск связанного аккаунта
|
||||
*
|
||||
* @param array &$errors Журнал ошибок
|
||||
*
|
||||
* @return ?_document Инстанция аккаунта, если удалось найти
|
||||
*/
|
||||
public function account(array &$errors = []): ?_document
|
||||
{
|
||||
try {
|
||||
if (
|
||||
collection::init(static::$db->session, self::COLLECTION)
|
||||
&& collection::init(static::$db->session, account::COLLECTION)
|
||||
&& collection::init(static::$db->session, self::COLLECTION . '_edge_' . account::COLLECTION, true)
|
||||
) {
|
||||
// Инициализированы коллекции
|
||||
|
||||
if ($account = collection::search(static::$db->session, sprintf(
|
||||
<<<AQL
|
||||
FOR document IN %s
|
||||
LET edge = (
|
||||
FOR edge IN %s
|
||||
FILTER edge._from == '%s'
|
||||
SORT edge._key DESC
|
||||
LIMIT 1
|
||||
RETURN edge
|
||||
)
|
||||
FILTER document._id == edge[0]._to
|
||||
LIMIT 1
|
||||
RETURN document
|
||||
AQL,
|
||||
account::COLLECTION,
|
||||
self::COLLECTION . '_edge_' . account::COLLECTION,
|
||||
$this->document->getId()
|
||||
))) {
|
||||
// Найден аккаунт
|
||||
|
||||
return $account;
|
||||
} else throw new exception('Не удалось найти аккаунт');
|
||||
} else throw new exception('Не удалось инициализировать коллекцию');
|
||||
} catch (exception $e) {
|
||||
// Запись в журнал ошибок
|
||||
$errors[] = [
|
||||
'text' => $e->getMessage(),
|
||||
'file' => $e->getFile(),
|
||||
'line' => $e->getLine(),
|
||||
'stack' => $e->getTrace()
|
||||
];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Записать
|
||||
*
|
||||
* Ищет свойство, если не находит, то ищет его в инстанции документа сессии из базы данных,
|
||||
* затем записывает в него переданные данные. Инициализация новых свойств происходит в инстанции
|
||||
* документа сессии из базы данных
|
||||
*
|
||||
* @param string $name Название
|
||||
* @param mixed $value Содержимое
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __set(string $name, mixed $value = null): void
|
||||
{
|
||||
if (isset($this->{$name})) $this->{$name} = $value;
|
||||
else $this->document->{$name} = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Прочитать
|
||||
*
|
||||
* Ищет свойство, если не находит, то ищет его в инстанции документа сессии из базы данных
|
||||
*
|
||||
* @param string $name Название
|
||||
*
|
||||
* @return mixed Данные свойства инстанции сессии или инстанции документа сессии из базы данных
|
||||
*/
|
||||
public function __get(string $name): mixed
|
||||
{
|
||||
return $this->{$name} ?? $this->document->{$name};
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,182 +1,182 @@
|
|||
@keyframes glare {
|
||||
|
||||
2%,
|
||||
100% {
|
||||
left : 130%;
|
||||
bottom : -200%;
|
||||
width : 120px;
|
||||
opacity: 0.7;
|
||||
}
|
||||
}
|
||||
|
||||
section#authentication {
|
||||
z-index : 1000;
|
||||
width : 400px;
|
||||
position : relative;
|
||||
margin : 25vh auto;
|
||||
display : flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
section#authentication>section.header {
|
||||
z-index : 1000;
|
||||
height : 100px;
|
||||
margin-left : -50px;
|
||||
padding : 30px 0;
|
||||
display : flex;
|
||||
clip-path : url(#authentication-header-mask);
|
||||
border-radius : 3px 3px 0 0;
|
||||
animation-duration: 120s;
|
||||
}
|
||||
|
||||
section#authentication>section.header>img.avatar {
|
||||
z-index : 1500;
|
||||
left : 6px;
|
||||
top : 36px;
|
||||
width : 88px;
|
||||
height : 88px;
|
||||
position : absolute;
|
||||
margin : auto;
|
||||
object-fit : cover;
|
||||
border-radius : 100%;
|
||||
cursor : pointer;
|
||||
image-rendering : smooth;
|
||||
box-shadow : 0px 0px 12px 0px rgba(0, 0, 0, 0.5);
|
||||
-webkit-box-shadow: 0px 0px 12px 0px rgba(0, 0, 0, 0.5);
|
||||
-moz-box-shadow : 0px 0px 12px 0px rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
|
||||
section#authentication>section.header>img.avatar:hover {
|
||||
left : 0;
|
||||
top : 30px;
|
||||
width : 100px;
|
||||
height : 100px;
|
||||
box-shadow : 0px 0px 8px 0px rgba(0, 0, 0, 0.3);
|
||||
-webkit-box-shadow: 0px 0px 8px 0px rgba(0, 0, 0, 0.3);
|
||||
-moz-box-shadow : 0px 0px 8px 0px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
section#authentication>section.header>img.cover {
|
||||
z-index : -5000;
|
||||
left : -50px;
|
||||
top : 0;
|
||||
position : absolute;
|
||||
width : calc(100% + 100px);
|
||||
height : 100%;
|
||||
object-position: 0px 30%;
|
||||
object-fit : cover;
|
||||
clip-path : polygon(50px 0, calc(100% - 50px) 0, calc(100% - 50px) 100%, 50px 100%);
|
||||
border-radius : 0 0 3px 3px;
|
||||
background : var(--background-above);
|
||||
}
|
||||
|
||||
section#authentication>section.header>div.glare {
|
||||
z-index : 3000;
|
||||
left : -30px;
|
||||
top : -300px;
|
||||
width : 30px;
|
||||
height : 400%;
|
||||
position : absolute;
|
||||
rotate : 25deg;
|
||||
opacity : 0.2;
|
||||
filter : unset;
|
||||
pointer-events : none;
|
||||
animation-name : glare;
|
||||
animation-duration : 32s;
|
||||
animation-delay : 2s;
|
||||
animation-fill-mode : forwards;
|
||||
animation-timing-function: linear;
|
||||
background-color : #fff;
|
||||
}
|
||||
|
||||
section#authentication>section.header>div {
|
||||
animation-duration: 80s;
|
||||
}
|
||||
|
||||
section#authentication>section.header>a {
|
||||
margin : auto;
|
||||
width : 100%;
|
||||
margin-left : 110px;
|
||||
padding-bottom: 0.5ex;
|
||||
white-space : nowrap;
|
||||
overflow-x : hidden;
|
||||
text-overflow : ellipsis;
|
||||
font-size : 1.3em;
|
||||
font-weight : bold;
|
||||
color : var(--text-inverse);
|
||||
text-shadow : 0 0 8px #00000080;
|
||||
}
|
||||
|
||||
|
||||
section#authentication>section.body {
|
||||
margin-top : -160px;
|
||||
padding : 180px 30px 20px 30px;
|
||||
gap : 3ex;
|
||||
display : flex;
|
||||
flex-direction : column;
|
||||
border-radius : 3px;
|
||||
background-color : var(--background-above);
|
||||
/* background-image : radial-gradient(circle at 70% 20%, #000000A0 0%, var(--background-above) 75%); */
|
||||
box-shadow : 0px 0px 8px 0px rgba(0, 0, 0, 0.2);
|
||||
-webkit-box-shadow : 0px 0px 8px 0px rgba(0, 0, 0, 0.2);
|
||||
-moz-box-shadow : 0px 0px 8px 0px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
section#authentication>section.body>ul {
|
||||
margin : unset;
|
||||
margin-left : 10%;
|
||||
margin-bottom: 1ex;
|
||||
}
|
||||
|
||||
section#authentication>section.body ul ul {
|
||||
padding-top: 1ex;
|
||||
}
|
||||
|
||||
section#authentication>section.body ul li:not(:last-child) {
|
||||
margin-bottom: 1ex;
|
||||
}
|
||||
|
||||
section#authentication>section.body div.buttons {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
section#authentication>section.body div.buttons>button {
|
||||
padding : 1ex 2ex;
|
||||
cursor : pointer;
|
||||
border-radius : 3px;
|
||||
font-size : 0.9em;
|
||||
background-color: unset;
|
||||
}
|
||||
|
||||
section#authentication>section.body div.buttons>button:hover {
|
||||
color: var(--text-hover);
|
||||
}
|
||||
|
||||
section#authentication>section.body div.buttons>button:active {
|
||||
color : var(--text-active);
|
||||
transition: unset;
|
||||
}
|
||||
|
||||
section#authentication>section.body div.buttons>button:first-of-type {
|
||||
margin-left : auto;
|
||||
margin-right: 5%;
|
||||
}
|
||||
|
||||
section#authentication>section.body div.buttons>button:last-of-type {
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
section#authentication>section.body div.buttons>button.accept {
|
||||
padding : 1ex 5ex;
|
||||
color : var(--text-inverse);
|
||||
background-color: #63954d;
|
||||
}
|
||||
|
||||
section#authentication>section.body div.buttons>button.accept:hover {
|
||||
color : var(--text-inverse-above);
|
||||
background-color: #6fa259;
|
||||
}
|
||||
|
||||
section#authentication>section.body div.buttons>button.accept:active {
|
||||
background-color: #63954d;
|
||||
}
|
||||
@keyframes glare {
|
||||
|
||||
2%,
|
||||
100% {
|
||||
left : 130%;
|
||||
bottom : -200%;
|
||||
width : 120px;
|
||||
opacity: 0.7;
|
||||
}
|
||||
}
|
||||
|
||||
section#authentication {
|
||||
z-index : 1000;
|
||||
width : 400px;
|
||||
position : relative;
|
||||
margin : 25vh auto;
|
||||
display : flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
section#authentication>section.header {
|
||||
z-index : 1000;
|
||||
height : 100px;
|
||||
margin-left : -50px;
|
||||
padding : 30px 0;
|
||||
display : flex;
|
||||
clip-path : url(#authentication-header-mask);
|
||||
border-radius : 3px 3px 0 0;
|
||||
animation-duration: 120s;
|
||||
}
|
||||
|
||||
section#authentication>section.header>img.avatar {
|
||||
z-index : 1500;
|
||||
left : 6px;
|
||||
top : 36px;
|
||||
width : 88px;
|
||||
height : 88px;
|
||||
position : absolute;
|
||||
margin : auto;
|
||||
object-fit : cover;
|
||||
border-radius : 100%;
|
||||
cursor : pointer;
|
||||
image-rendering : smooth;
|
||||
box-shadow : 0px 0px 12px 0px rgba(0, 0, 0, 0.5);
|
||||
-webkit-box-shadow: 0px 0px 12px 0px rgba(0, 0, 0, 0.5);
|
||||
-moz-box-shadow : 0px 0px 12px 0px rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
|
||||
section#authentication>section.header>img.avatar:hover {
|
||||
left : 0;
|
||||
top : 30px;
|
||||
width : 100px;
|
||||
height : 100px;
|
||||
box-shadow : 0px 0px 8px 0px rgba(0, 0, 0, 0.3);
|
||||
-webkit-box-shadow: 0px 0px 8px 0px rgba(0, 0, 0, 0.3);
|
||||
-moz-box-shadow : 0px 0px 8px 0px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
section#authentication>section.header>img.cover {
|
||||
z-index : -5000;
|
||||
left : -50px;
|
||||
top : 0;
|
||||
position : absolute;
|
||||
width : calc(100% + 100px);
|
||||
height : 100%;
|
||||
object-position: 0px 30%;
|
||||
object-fit : cover;
|
||||
clip-path : polygon(50px 0, calc(100% - 50px) 0, calc(100% - 50px) 100%, 50px 100%);
|
||||
border-radius : 0 0 3px 3px;
|
||||
background : var(--background-above);
|
||||
}
|
||||
|
||||
section#authentication>section.header>div.glare {
|
||||
z-index : 3000;
|
||||
left : -30px;
|
||||
top : -300px;
|
||||
width : 30px;
|
||||
height : 400%;
|
||||
position : absolute;
|
||||
rotate : 25deg;
|
||||
opacity : 0.2;
|
||||
filter : unset;
|
||||
pointer-events : none;
|
||||
animation-name : glare;
|
||||
animation-duration : 32s;
|
||||
animation-delay : 2s;
|
||||
animation-fill-mode : forwards;
|
||||
animation-timing-function: linear;
|
||||
background-color : #fff;
|
||||
}
|
||||
|
||||
section#authentication>section.header>div {
|
||||
animation-duration: 80s;
|
||||
}
|
||||
|
||||
section#authentication>section.header>a {
|
||||
margin : auto;
|
||||
width : 100%;
|
||||
margin-left : 110px;
|
||||
padding-bottom: 0.5ex;
|
||||
white-space : nowrap;
|
||||
overflow-x : hidden;
|
||||
text-overflow : ellipsis;
|
||||
font-size : 1.3em;
|
||||
font-weight : bold;
|
||||
color : var(--text-inverse);
|
||||
text-shadow : 0 0 8px #00000080;
|
||||
}
|
||||
|
||||
|
||||
section#authentication>section.body {
|
||||
margin-top : -160px;
|
||||
padding : 180px 30px 20px 30px;
|
||||
gap : 3ex;
|
||||
display : flex;
|
||||
flex-direction : column;
|
||||
border-radius : 3px;
|
||||
background-color : var(--background-above);
|
||||
/* background-image : radial-gradient(circle at 70% 20%, #000000A0 0%, var(--background-above) 75%); */
|
||||
box-shadow : 0px 0px 8px 0px rgba(0, 0, 0, 0.2);
|
||||
-webkit-box-shadow : 0px 0px 8px 0px rgba(0, 0, 0, 0.2);
|
||||
-moz-box-shadow : 0px 0px 8px 0px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
section#authentication>section.body>ul {
|
||||
margin : unset;
|
||||
margin-left : 10%;
|
||||
margin-bottom: 1ex;
|
||||
}
|
||||
|
||||
section#authentication>section.body ul ul {
|
||||
padding-top: 1ex;
|
||||
}
|
||||
|
||||
section#authentication>section.body ul li:not(:last-child) {
|
||||
margin-bottom: 1ex;
|
||||
}
|
||||
|
||||
section#authentication>section.body div.buttons {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
section#authentication>section.body div.buttons>button {
|
||||
padding : 1ex 2ex;
|
||||
cursor : pointer;
|
||||
border-radius : 3px;
|
||||
font-size : 0.9em;
|
||||
background-color: unset;
|
||||
}
|
||||
|
||||
section#authentication>section.body div.buttons>button:hover {
|
||||
color: var(--text-hover);
|
||||
}
|
||||
|
||||
section#authentication>section.body div.buttons>button:active {
|
||||
color : var(--text-active);
|
||||
transition: unset;
|
||||
}
|
||||
|
||||
section#authentication>section.body div.buttons>button:first-of-type {
|
||||
margin-left : auto;
|
||||
margin-right: 5%;
|
||||
}
|
||||
|
||||
section#authentication>section.body div.buttons>button:last-of-type {
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
section#authentication>section.body div.buttons>button.accept {
|
||||
padding : 1ex 5ex;
|
||||
color : var(--text-inverse);
|
||||
background-color: #63954d;
|
||||
}
|
||||
|
||||
section#authentication>section.body div.buttons>button.accept:hover {
|
||||
color : var(--text-inverse-above);
|
||||
background-color: #6fa259;
|
||||
}
|
||||
|
||||
section#authentication>section.body div.buttons>button.accept:active {
|
||||
background-color: #63954d;
|
||||
}
|
||||
|
|
|
@ -1,134 +1,134 @@
|
|||
@keyframes red {
|
||||
25% {
|
||||
left: -240%;
|
||||
top : -130%;
|
||||
}
|
||||
|
||||
50% {
|
||||
left: -100%;
|
||||
top : -120%;
|
||||
}
|
||||
|
||||
75% {
|
||||
left: -160%;
|
||||
top : -230%;
|
||||
}
|
||||
|
||||
100% {
|
||||
left: -250%;
|
||||
top : -300%;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes blue {
|
||||
25% {
|
||||
left: -180%;
|
||||
top : -100%;
|
||||
}
|
||||
|
||||
50% {
|
||||
left: -120%;
|
||||
top : -250%;
|
||||
}
|
||||
|
||||
75% {
|
||||
left: -250%;
|
||||
top : -300%;
|
||||
}
|
||||
|
||||
100% {
|
||||
left: -280%;
|
||||
top : -80%;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes green {
|
||||
25% {
|
||||
left: -120%;
|
||||
top : -250%;
|
||||
}
|
||||
|
||||
50% {
|
||||
left: -250%;
|
||||
top : -300%;
|
||||
}
|
||||
|
||||
75% {
|
||||
left: -280%;
|
||||
top : -80%;
|
||||
}
|
||||
|
||||
100% {
|
||||
left: -180%;
|
||||
top : -100%;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes wrap-background {
|
||||
25% {
|
||||
background-color: #9395ff;
|
||||
}
|
||||
|
||||
50% {
|
||||
background-color: #fff393;
|
||||
}
|
||||
|
||||
75% {
|
||||
background-color: #534eff;
|
||||
}
|
||||
|
||||
100% {
|
||||
background-color: #ff5c5c;
|
||||
}
|
||||
}
|
||||
|
||||
:is(div, section).gradient {
|
||||
position : relative;
|
||||
overflow : hidden;
|
||||
animation-duration : 30s;
|
||||
animation-name : wrap-background;
|
||||
animation-iteration-count: infinite;
|
||||
background-repeat : no-repeat;
|
||||
animation-timing-function: ease-in-out;
|
||||
background-color : #ff5c5c;
|
||||
}
|
||||
|
||||
:is(div, section).gradient>div:not(.gradient) {
|
||||
z-index : -1000;
|
||||
width : 500%;
|
||||
height : 500%;
|
||||
position : absolute;
|
||||
pointer-events : none;
|
||||
filter : blur(200px);
|
||||
animation-duration : 12s;
|
||||
background-repeat : no-repeat;
|
||||
animation-timing-function: ease-in-out;
|
||||
animation-iteration-count: infinite;
|
||||
}
|
||||
|
||||
:is(div, section).gradient>div.red {
|
||||
left : -250%;
|
||||
top : -300%;
|
||||
animation-name: red;
|
||||
background-image: radial-gradient(circle,
|
||||
rgba(255, 25, 25, 1) 0%,
|
||||
rgba(0, 0, 0, 0) 35%);
|
||||
}
|
||||
|
||||
:is(div, section).gradient>div.blue {
|
||||
left : -280%;
|
||||
top : -80%;
|
||||
animation-name: blue;
|
||||
background-image: radial-gradient(circle,
|
||||
rgba(25, 25, 255, 0.6) 0%,
|
||||
rgba(0, 0, 0, 0) 35%);
|
||||
}
|
||||
|
||||
:is(div, section).gradient>div.green {
|
||||
left : -180%;
|
||||
top : -100%;
|
||||
animation-name: green;
|
||||
background-image: radial-gradient(circle,
|
||||
rgba(25, 255, 25, 1) 0%,
|
||||
rgba(0, 0, 0, 0) 35%);
|
||||
}
|
||||
@keyframes red {
|
||||
25% {
|
||||
left: -240%;
|
||||
top : -130%;
|
||||
}
|
||||
|
||||
50% {
|
||||
left: -100%;
|
||||
top : -120%;
|
||||
}
|
||||
|
||||
75% {
|
||||
left: -160%;
|
||||
top : -230%;
|
||||
}
|
||||
|
||||
100% {
|
||||
left: -250%;
|
||||
top : -300%;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes blue {
|
||||
25% {
|
||||
left: -180%;
|
||||
top : -100%;
|
||||
}
|
||||
|
||||
50% {
|
||||
left: -120%;
|
||||
top : -250%;
|
||||
}
|
||||
|
||||
75% {
|
||||
left: -250%;
|
||||
top : -300%;
|
||||
}
|
||||
|
||||
100% {
|
||||
left: -280%;
|
||||
top : -80%;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes green {
|
||||
25% {
|
||||
left: -120%;
|
||||
top : -250%;
|
||||
}
|
||||
|
||||
50% {
|
||||
left: -250%;
|
||||
top : -300%;
|
||||
}
|
||||
|
||||
75% {
|
||||
left: -280%;
|
||||
top : -80%;
|
||||
}
|
||||
|
||||
100% {
|
||||
left: -180%;
|
||||
top : -100%;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes wrap-background {
|
||||
25% {
|
||||
background-color: #9395ff;
|
||||
}
|
||||
|
||||
50% {
|
||||
background-color: #fff393;
|
||||
}
|
||||
|
||||
75% {
|
||||
background-color: #534eff;
|
||||
}
|
||||
|
||||
100% {
|
||||
background-color: #ff5c5c;
|
||||
}
|
||||
}
|
||||
|
||||
:is(div, section).gradient {
|
||||
position : relative;
|
||||
overflow : hidden;
|
||||
animation-duration : 30s;
|
||||
animation-name : wrap-background;
|
||||
animation-iteration-count: infinite;
|
||||
background-repeat : no-repeat;
|
||||
animation-timing-function: ease-in-out;
|
||||
background-color : #ff5c5c;
|
||||
}
|
||||
|
||||
:is(div, section).gradient>div:not(.gradient) {
|
||||
z-index : -1000;
|
||||
width : 500%;
|
||||
height : 500%;
|
||||
position : absolute;
|
||||
pointer-events : none;
|
||||
filter : blur(200px);
|
||||
animation-duration : 12s;
|
||||
background-repeat : no-repeat;
|
||||
animation-timing-function: ease-in-out;
|
||||
animation-iteration-count: infinite;
|
||||
}
|
||||
|
||||
:is(div, section).gradient>div.red {
|
||||
left : -250%;
|
||||
top : -300%;
|
||||
animation-name: red;
|
||||
background-image: radial-gradient(circle,
|
||||
rgba(255, 25, 25, 1) 0%,
|
||||
rgba(0, 0, 0, 0) 35%);
|
||||
}
|
||||
|
||||
:is(div, section).gradient>div.blue {
|
||||
left : -280%;
|
||||
top : -80%;
|
||||
animation-name: blue;
|
||||
background-image: radial-gradient(circle,
|
||||
rgba(25, 25, 255, 0.6) 0%,
|
||||
rgba(0, 0, 0, 0) 35%);
|
||||
}
|
||||
|
||||
:is(div, section).gradient>div.green {
|
||||
left : -180%;
|
||||
top : -100%;
|
||||
animation-name: green;
|
||||
background-image: radial-gradient(circle,
|
||||
rgba(25, 255, 25, 1) 0%,
|
||||
rgba(0, 0, 0, 0) 35%);
|
||||
}
|
||||
|
|
|
@ -1,245 +1,245 @@
|
|||
@keyframes node-select {
|
||||
from {
|
||||
outline-offset: 0px;
|
||||
}
|
||||
|
||||
to {
|
||||
outline : 2px solid var(--grey-light);
|
||||
outline-offset: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes node-select-revert {
|
||||
from {
|
||||
outline : 2px solid var(--grey-light);
|
||||
outline-offset: 10px;
|
||||
}
|
||||
|
||||
to {
|
||||
outline-offset: 0px;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes description-select {
|
||||
from {
|
||||
outline-offset: 0px;
|
||||
}
|
||||
|
||||
to {
|
||||
outline : 2px solid var(--grey);
|
||||
outline-offset: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes description-select-revert {
|
||||
from {
|
||||
outline : 2px solid var(--grey);
|
||||
outline-offset: 10px;
|
||||
}
|
||||
|
||||
to {
|
||||
outline-offset: 0px;
|
||||
}
|
||||
}
|
||||
|
||||
section.graph {
|
||||
z-index : 0;
|
||||
width : 100vw;
|
||||
height : 100vh;
|
||||
position : absolute;
|
||||
transition: unset;
|
||||
}
|
||||
|
||||
section.graph * {
|
||||
transition: unset;
|
||||
}
|
||||
|
||||
section.graph:active {
|
||||
cursor: move;
|
||||
}
|
||||
|
||||
section.graph article.node {
|
||||
z-index : 500;
|
||||
position : absolute;
|
||||
display : flex;
|
||||
cursor : grab;
|
||||
border-radius : 100%;
|
||||
background-color : var(--node-background);
|
||||
}
|
||||
|
||||
section.graph article.node.animated {
|
||||
animation-duration : 0.1s;
|
||||
animation-name : node-select-revert;
|
||||
animation-fill-mode : forwards;
|
||||
}
|
||||
|
||||
section.graph article.node.animated:hover {
|
||||
animation-duration : 0.1s;
|
||||
animation-name : node-select;
|
||||
animation-fill-mode : forwards;
|
||||
}
|
||||
|
||||
section.graph article.node:active {
|
||||
cursor : grabbing;
|
||||
background-color: var(--node-background-important);
|
||||
}
|
||||
|
||||
section.graph article.node>h4.title {
|
||||
margin : auto;
|
||||
text-align: center;
|
||||
cursor : pointer;
|
||||
}
|
||||
|
||||
section.graph article.node>div.description {
|
||||
z-index : 1000;
|
||||
position : absolute;
|
||||
text-align : justify;
|
||||
text-align-last : center;
|
||||
border-radius : 100%;
|
||||
overflow : hidden;
|
||||
background-color: var(--node-background-completed);
|
||||
}
|
||||
|
||||
/* section.graph article.node>div.description.animated {
|
||||
animation-duration : 0.1s;
|
||||
animation-name : description-select-revert;
|
||||
animation-fill-mode : forwards;
|
||||
}
|
||||
|
||||
section.graph article.node>div.description.animated:hover {
|
||||
animation-duration : 0.1s;
|
||||
animation-name : description-select;
|
||||
animation-fill-mode : forwards;
|
||||
} */
|
||||
|
||||
section.graph article.node * {
|
||||
transition: 0.1s ease-in;
|
||||
}
|
||||
|
||||
section.graph article.node>div.description>span.wrapper {
|
||||
width : 50%;
|
||||
height : 100%;
|
||||
shape-margin: 15px;
|
||||
}
|
||||
|
||||
section.graph article.node>div.description>span.left.wrapper {
|
||||
float : left;
|
||||
shape-outside: polygon(100% 0%, 0% 0%, 0% 100%, 100% 100%, 68% 98%, 38% 90%, 10% 72%, 0% 50%, 10% 28%, 20% 20%, 100% 20%);
|
||||
}
|
||||
|
||||
section.graph article.node>div.description>span.right.wrapper {
|
||||
float : right;
|
||||
shape-outside: polygon(0% 100%, 100% 100%, 100% 0%, 0% 0%, 0% 20%, 82% 20%, 90% 28%, 100% 50%, 90% 72%, 60% 90%, 32% 98%);
|
||||
}
|
||||
|
||||
section.graph article.node>div.description>p {
|
||||
z-index : 1500;
|
||||
position : relative;
|
||||
margin : 0;
|
||||
opacity : 0;
|
||||
word-break: break-all;
|
||||
color : var(--text-inverse);
|
||||
}
|
||||
|
||||
section.graph article.node>div.description:hover>p {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
section.graph article.node>div.description>a.source {
|
||||
z-index : 2000;
|
||||
top : calc(20% - 1.3em + (1em - 1.3ex));
|
||||
left : 0;
|
||||
position : absolute;
|
||||
font-weight: bold;
|
||||
font-size : 1.3em;
|
||||
opacity : 0;
|
||||
}
|
||||
|
||||
section.graph article.node.white>div.description>a.source {
|
||||
color: var(--text-inverse);
|
||||
}
|
||||
|
||||
section.graph article.node.white>div.description>a.source:active {
|
||||
color: var(--text-inverse-active);
|
||||
}
|
||||
|
||||
section.graph article.node.white>div.description>a.source:hover {
|
||||
color: var(--text-inverse-hover);
|
||||
}
|
||||
|
||||
section.graph article.node.red>div.description>a.source {
|
||||
color: var(--text-red);
|
||||
}
|
||||
|
||||
section.graph article.node.red>div.description>a.source:active {
|
||||
color: var(--text-red-active);
|
||||
}
|
||||
|
||||
section.graph article.node.red>div.description>a.source:hover {
|
||||
color: var(--text-red-hover);
|
||||
}
|
||||
|
||||
section.graph article.node>div.description>a.source.red:active {
|
||||
color: var(--text-red-active);
|
||||
}
|
||||
|
||||
section.graph article.node>div.description:hover>a.source {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
section.graph article.node>div.description>a.source:visited ::after {
|
||||
content : '';
|
||||
width : 100%;
|
||||
height : 100%;
|
||||
background-color: var(--node-background-completed);
|
||||
}
|
||||
|
||||
section.graph article.node>div.description>img.cover {
|
||||
left : 0;
|
||||
top : 0;
|
||||
position : absolute;
|
||||
width : 100%;
|
||||
height : 100%;
|
||||
object-fit : cover;
|
||||
pointer-events: none;
|
||||
filter : unset;
|
||||
}
|
||||
|
||||
section.graph article.node>div.description:hover>img.cover {
|
||||
filter: blur(5px) brightness(0.5);
|
||||
}
|
||||
|
||||
section.graph article.node>i.close {
|
||||
z-index : -2000;
|
||||
top : -10%;
|
||||
right : -10%;
|
||||
position : absolute;
|
||||
scale : 0;
|
||||
opacity : 0;
|
||||
cursor : pointer;
|
||||
color : var(--text);
|
||||
transition: 0.2s ease-out;
|
||||
}
|
||||
|
||||
section.graph article.node>i.close:hover {
|
||||
scale : 1.4 !important;
|
||||
color : var(--text-hover);
|
||||
transition: 0.1s ease-in;
|
||||
}
|
||||
|
||||
section.graph article.node>i.close:active {
|
||||
scale : 1.2 !important;
|
||||
color : var(--text-active);
|
||||
transition: unset;
|
||||
}
|
||||
|
||||
section.graph svg.connection {
|
||||
z-index : -500;
|
||||
position: absolute;
|
||||
width : 100%;
|
||||
height : 100%;
|
||||
}
|
||||
|
||||
section.graph svg.connection>line {
|
||||
stroke: var(--connection);
|
||||
}
|
||||
@keyframes node-select {
|
||||
from {
|
||||
outline-offset: 0px;
|
||||
}
|
||||
|
||||
to {
|
||||
outline : 2px solid var(--grey-light);
|
||||
outline-offset: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes node-select-revert {
|
||||
from {
|
||||
outline : 2px solid var(--grey-light);
|
||||
outline-offset: 10px;
|
||||
}
|
||||
|
||||
to {
|
||||
outline-offset: 0px;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes description-select {
|
||||
from {
|
||||
outline-offset: 0px;
|
||||
}
|
||||
|
||||
to {
|
||||
outline : 2px solid var(--grey);
|
||||
outline-offset: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes description-select-revert {
|
||||
from {
|
||||
outline : 2px solid var(--grey);
|
||||
outline-offset: 10px;
|
||||
}
|
||||
|
||||
to {
|
||||
outline-offset: 0px;
|
||||
}
|
||||
}
|
||||
|
||||
section.graph {
|
||||
z-index : 0;
|
||||
width : 100vw;
|
||||
height : 100vh;
|
||||
position : absolute;
|
||||
transition: unset;
|
||||
}
|
||||
|
||||
section.graph * {
|
||||
transition: unset;
|
||||
}
|
||||
|
||||
section.graph:active {
|
||||
cursor: move;
|
||||
}
|
||||
|
||||
section.graph article.node {
|
||||
z-index : 500;
|
||||
position : absolute;
|
||||
display : flex;
|
||||
cursor : grab;
|
||||
border-radius : 100%;
|
||||
background-color : var(--node-background);
|
||||
}
|
||||
|
||||
section.graph article.node.animated {
|
||||
animation-duration : 0.1s;
|
||||
animation-name : node-select-revert;
|
||||
animation-fill-mode : forwards;
|
||||
}
|
||||
|
||||
section.graph article.node.animated:hover {
|
||||
animation-duration : 0.1s;
|
||||
animation-name : node-select;
|
||||
animation-fill-mode : forwards;
|
||||
}
|
||||
|
||||
section.graph article.node:active {
|
||||
cursor : grabbing;
|
||||
background-color: var(--node-background-important);
|
||||
}
|
||||
|
||||
section.graph article.node>h4.title {
|
||||
margin : auto;
|
||||
text-align: center;
|
||||
cursor : pointer;
|
||||
}
|
||||
|
||||
section.graph article.node>div.description {
|
||||
z-index : 1000;
|
||||
position : absolute;
|
||||
text-align : justify;
|
||||
text-align-last : center;
|
||||
border-radius : 100%;
|
||||
overflow : hidden;
|
||||
background-color: var(--node-background-completed);
|
||||
}
|
||||
|
||||
/* section.graph article.node>div.description.animated {
|
||||
animation-duration : 0.1s;
|
||||
animation-name : description-select-revert;
|
||||
animation-fill-mode : forwards;
|
||||
}
|
||||
|
||||
section.graph article.node>div.description.animated:hover {
|
||||
animation-duration : 0.1s;
|
||||
animation-name : description-select;
|
||||
animation-fill-mode : forwards;
|
||||
} */
|
||||
|
||||
section.graph article.node * {
|
||||
transition: 0.1s ease-in;
|
||||
}
|
||||
|
||||
section.graph article.node>div.description>span.wrapper {
|
||||
width : 50%;
|
||||
height : 100%;
|
||||
shape-margin: 15px;
|
||||
}
|
||||
|
||||
section.graph article.node>div.description>span.left.wrapper {
|
||||
float : left;
|
||||
shape-outside: polygon(100% 0%, 0% 0%, 0% 100%, 100% 100%, 68% 98%, 38% 90%, 10% 72%, 0% 50%, 10% 28%, 20% 20%, 100% 20%);
|
||||
}
|
||||
|
||||
section.graph article.node>div.description>span.right.wrapper {
|
||||
float : right;
|
||||
shape-outside: polygon(0% 100%, 100% 100%, 100% 0%, 0% 0%, 0% 20%, 82% 20%, 90% 28%, 100% 50%, 90% 72%, 60% 90%, 32% 98%);
|
||||
}
|
||||
|
||||
section.graph article.node>div.description>p {
|
||||
z-index : 1500;
|
||||
position : relative;
|
||||
margin : 0;
|
||||
opacity : 0;
|
||||
word-break: break-all;
|
||||
color : var(--text-inverse);
|
||||
}
|
||||
|
||||
section.graph article.node>div.description:hover>p {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
section.graph article.node>div.description>a.source {
|
||||
z-index : 2000;
|
||||
top : calc(20% - 1.3em + (1em - 1.3ex));
|
||||
left : 0;
|
||||
position : absolute;
|
||||
font-weight: bold;
|
||||
font-size : 1.3em;
|
||||
opacity : 0;
|
||||
}
|
||||
|
||||
section.graph article.node.white>div.description>a.source {
|
||||
color: var(--text-inverse);
|
||||
}
|
||||
|
||||
section.graph article.node.white>div.description>a.source:active {
|
||||
color: var(--text-inverse-active);
|
||||
}
|
||||
|
||||
section.graph article.node.white>div.description>a.source:hover {
|
||||
color: var(--text-inverse-hover);
|
||||
}
|
||||
|
||||
section.graph article.node.red>div.description>a.source {
|
||||
color: var(--text-red);
|
||||
}
|
||||
|
||||
section.graph article.node.red>div.description>a.source:active {
|
||||
color: var(--text-red-active);
|
||||
}
|
||||
|
||||
section.graph article.node.red>div.description>a.source:hover {
|
||||
color: var(--text-red-hover);
|
||||
}
|
||||
|
||||
section.graph article.node>div.description>a.source.red:active {
|
||||
color: var(--text-red-active);
|
||||
}
|
||||
|
||||
section.graph article.node>div.description:hover>a.source {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
section.graph article.node>div.description>a.source:visited ::after {
|
||||
content : '';
|
||||
width : 100%;
|
||||
height : 100%;
|
||||
background-color: var(--node-background-completed);
|
||||
}
|
||||
|
||||
section.graph article.node>div.description>img.cover {
|
||||
left : 0;
|
||||
top : 0;
|
||||
position : absolute;
|
||||
width : 100%;
|
||||
height : 100%;
|
||||
object-fit : cover;
|
||||
pointer-events: none;
|
||||
filter : unset;
|
||||
}
|
||||
|
||||
section.graph article.node>div.description:hover>img.cover {
|
||||
filter: blur(5px) brightness(0.5);
|
||||
}
|
||||
|
||||
section.graph article.node>i.close {
|
||||
z-index : -2000;
|
||||
top : -10%;
|
||||
right : -10%;
|
||||
position : absolute;
|
||||
scale : 0;
|
||||
opacity : 0;
|
||||
cursor : pointer;
|
||||
color : var(--text);
|
||||
transition: 0.2s ease-out;
|
||||
}
|
||||
|
||||
section.graph article.node>i.close:hover {
|
||||
scale : 1.4 !important;
|
||||
color : var(--text-hover);
|
||||
transition: 0.1s ease-in;
|
||||
}
|
||||
|
||||
section.graph article.node>i.close:active {
|
||||
scale : 1.2 !important;
|
||||
color : var(--text-active);
|
||||
transition: unset;
|
||||
}
|
||||
|
||||
section.graph svg.connection {
|
||||
z-index : -500;
|
||||
position: absolute;
|
||||
width : 100%;
|
||||
height : 100%;
|
||||
}
|
||||
|
||||
section.graph svg.connection>line {
|
||||
stroke: var(--connection);
|
||||
}
|
||||
|
|
|
@ -1,31 +1,31 @@
|
|||
section.hotline {
|
||||
display: inline-flex;
|
||||
height : 100%;
|
||||
}
|
||||
|
||||
section.hotline * {
|
||||
transition: unset;
|
||||
}
|
||||
|
||||
section.hotline:last-child {
|
||||
margin-bottom: unset;
|
||||
}
|
||||
|
||||
section.hotline>article {
|
||||
margin-right : 18px;
|
||||
width : 140px;
|
||||
height : 190px;
|
||||
display : flex;
|
||||
align-self : flex-end;
|
||||
border-radius : 3px;
|
||||
background-color: var(--background-light-1);
|
||||
box-shadow : 0px -6px 6px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
section.hotline>article:last-child {
|
||||
margin-right: unset;
|
||||
}
|
||||
|
||||
section.hotline>article>* {
|
||||
margin: auto;
|
||||
}
|
||||
section.hotline {
|
||||
display: inline-flex;
|
||||
height : 100%;
|
||||
}
|
||||
|
||||
section.hotline * {
|
||||
transition: unset;
|
||||
}
|
||||
|
||||
section.hotline:last-child {
|
||||
margin-bottom: unset;
|
||||
}
|
||||
|
||||
section.hotline>article {
|
||||
margin-right : 18px;
|
||||
width : 140px;
|
||||
height : 190px;
|
||||
display : flex;
|
||||
align-self : flex-end;
|
||||
border-radius : 3px;
|
||||
background-color: var(--background-light-1);
|
||||
box-shadow : 0px -6px 6px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
section.hotline>article:last-child {
|
||||
margin-right: unset;
|
||||
}
|
||||
|
||||
section.hotline>article>* {
|
||||
margin: auto;
|
||||
}
|
||||
|
|
|
@ -1,29 +1,29 @@
|
|||
.icon.close {
|
||||
box-sizing : border-box;
|
||||
position : relative;
|
||||
display : block;
|
||||
transform : scale(var(--ggs, 1));
|
||||
width : 22px;
|
||||
height : 22px;
|
||||
border : 2px solid transparent;
|
||||
border-radius: 40px
|
||||
}
|
||||
|
||||
.icon.close::after,
|
||||
.icon.close::before {
|
||||
content : "";
|
||||
display : block;
|
||||
box-sizing : border-box;
|
||||
position : absolute;
|
||||
width : 16px;
|
||||
height : 2px;
|
||||
background : currentColor;
|
||||
transform : rotate(45deg);
|
||||
border-radius: 5px;
|
||||
top : 8px;
|
||||
left : 1px
|
||||
}
|
||||
|
||||
.icon.close::after {
|
||||
transform: rotate(-45deg)
|
||||
}
|
||||
.icon.close {
|
||||
box-sizing : border-box;
|
||||
position : relative;
|
||||
display : block;
|
||||
transform : scale(var(--ggs, 1));
|
||||
width : 22px;
|
||||
height : 22px;
|
||||
border : 2px solid transparent;
|
||||
border-radius: 40px
|
||||
}
|
||||
|
||||
.icon.close::after,
|
||||
.icon.close::before {
|
||||
content : "";
|
||||
display : block;
|
||||
box-sizing : border-box;
|
||||
position : absolute;
|
||||
width : 16px;
|
||||
height : 2px;
|
||||
background : currentColor;
|
||||
transform : rotate(45deg);
|
||||
border-radius: 5px;
|
||||
top : 8px;
|
||||
left : 1px
|
||||
}
|
||||
|
||||
.icon.close::after {
|
||||
transform: rotate(-45deg)
|
||||
}
|
||||
|
|
|
@ -1,225 +1,225 @@
|
|||
@import url('/fonts/comissioner.ttf');
|
||||
|
||||
@media (prefers-color-scheme: light) {
|
||||
:root {
|
||||
--background-above-1 : #fff;
|
||||
--background-above : #fff6f6;
|
||||
--background : #e8dada;
|
||||
--background-below : #d7c5c5;
|
||||
--background-inverse : #221e1e;
|
||||
--background-inverse-dark : #120f0f;
|
||||
--node-background-important: #c3eac3;
|
||||
--node-background-completed: #b0c0b0;
|
||||
--node-background : #bdb;
|
||||
--connection : #b2b7b2;
|
||||
--connection-completed : #d1d1d1;
|
||||
--text : #151313;
|
||||
--text-hover : #463e3e;
|
||||
--text-active : #0e0e0e;
|
||||
--text-inverse-above : #fff;
|
||||
--text-inverse : #efefef;
|
||||
--text-inverse-below : #d0d0d0;
|
||||
--text-red : #f8a2a2;
|
||||
--text-red-hover : #ffbcbc;
|
||||
--text-red-active : #e69191;
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--background-above-1: #322d2d;
|
||||
--background-above : #2b2525;
|
||||
--background : #221e1e;
|
||||
--background-below : #121010;
|
||||
--node-background : #221e1e;
|
||||
--text : #e6e6e6;
|
||||
--text-hover : #fff;
|
||||
--text-active : #d0d0d0;
|
||||
--text-inverse : 'dark';
|
||||
--red-light-1 : #dc4343;
|
||||
--red-light : #bf3737;
|
||||
--red : #a43333;
|
||||
--red-dark : #8d2a2a;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes page-background-gradient {
|
||||
25% {
|
||||
left: -350%;
|
||||
top : 0%;
|
||||
}
|
||||
|
||||
50% {
|
||||
left: 0%;
|
||||
top : 0%;
|
||||
}
|
||||
|
||||
75% {
|
||||
left: 0%;
|
||||
top : -350%;
|
||||
}
|
||||
|
||||
to {
|
||||
left: -350%;
|
||||
top : -350%;
|
||||
}
|
||||
}
|
||||
|
||||
:root {
|
||||
--link : #3c76ff;
|
||||
--link-hover : #6594ff;
|
||||
--link-active: #3064dd;
|
||||
}
|
||||
|
||||
* {
|
||||
text-decoration: none;
|
||||
outline : none;
|
||||
border : none;
|
||||
color : var(--text);
|
||||
font-family : 'Commissioner', sans-serif;
|
||||
transition : 0.1s ease-out;
|
||||
}
|
||||
|
||||
.unselectable {
|
||||
-webkit-touch-callout: none;
|
||||
-webkit-user-select : none;
|
||||
-khtml-user-select : none;
|
||||
-moz-user-select : none;
|
||||
-ms-user-select : none;
|
||||
user-select : none;
|
||||
}
|
||||
|
||||
a {
|
||||
color: var(--link);
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: var(--link-hover);
|
||||
}
|
||||
|
||||
a:active {
|
||||
color : var(--link-active);
|
||||
transition: unset;
|
||||
}
|
||||
|
||||
body {
|
||||
height : 100vh;
|
||||
margin : 0;
|
||||
overflow : hidden;
|
||||
background-color: var(--background);
|
||||
}
|
||||
|
||||
body>div.background {
|
||||
z-index : -50000;
|
||||
left : -350%;
|
||||
top : -350%;
|
||||
width : 500%;
|
||||
height : 500%;
|
||||
position : absolute;
|
||||
filter : blur(200px);
|
||||
animation-duration : 15s;
|
||||
animation-name : page-background-gradient;
|
||||
animation-iteration-count: infinite;
|
||||
background-repeat : no-repeat;
|
||||
animation-timing-function: linear;
|
||||
background-image : radial-gradient(circle, var(--background-above) 0%, rgba(0, 0, 0, 0) 100%);
|
||||
}
|
||||
|
||||
aside {
|
||||
z-index : 500;
|
||||
grid-column: 1/ 4;
|
||||
grid-row : 2;
|
||||
overflow : hidden;
|
||||
}
|
||||
|
||||
header {
|
||||
z-index : 5000;
|
||||
position : absolute;
|
||||
display : flex;
|
||||
flex-direction: column;
|
||||
box-shadow : 2px 0 5px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
header>menu {
|
||||
margin : unset;
|
||||
padding : 20px;
|
||||
display : flex;
|
||||
flex-direction : column;
|
||||
flex-grow : 1;
|
||||
background-color: var(--background-light-1);
|
||||
}
|
||||
|
||||
header>#account>button#login {
|
||||
z-index: 1500;
|
||||
}
|
||||
|
||||
header>menu a {
|
||||
margin-bottom: 8px;
|
||||
display : flex;
|
||||
align-items : center;
|
||||
}
|
||||
|
||||
header>menu a:last-child {
|
||||
margin-bottom: unset;
|
||||
}
|
||||
|
||||
header>menu a svg {
|
||||
margin-right: 8px;
|
||||
height : 1.2rem;
|
||||
position : relative;
|
||||
}
|
||||
|
||||
header>menu a:hover svg {
|
||||
margin-left : -5px;
|
||||
margin-right: 13px;
|
||||
}
|
||||
|
||||
header>menu a svg path {
|
||||
fill: var(--text);
|
||||
}
|
||||
|
||||
header>section {
|
||||
background-color: var(--background-light-1);
|
||||
}
|
||||
|
||||
header :is(button, a[type="button"]) {
|
||||
width : 100%;
|
||||
height : 40px;
|
||||
display : flex;
|
||||
justify-content : center;
|
||||
align-items : center;
|
||||
cursor : pointer;
|
||||
background-color: var(--red);
|
||||
transition : unset;
|
||||
}
|
||||
|
||||
header button {
|
||||
font-weight : bold;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
header :is(button, a[type="button"]):hover {
|
||||
background-color: var(--red-light);
|
||||
}
|
||||
|
||||
header :is(button, a[type="button"]):active {
|
||||
background-color: var(--red-dark);
|
||||
}
|
||||
|
||||
header>nav {
|
||||
margin-top : auto;
|
||||
display : flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
main {
|
||||
z-index : 1000;
|
||||
height : 100%;
|
||||
display : flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
footer {
|
||||
z-index : 3000;
|
||||
position: absolute;
|
||||
}
|
||||
@import url('/fonts/commissioner.ttf');
|
||||
|
||||
@media (prefers-color-scheme: light) {
|
||||
:root {
|
||||
--background-above-1 : #fff;
|
||||
--background-above : #fff6f6;
|
||||
--background : #e8dada;
|
||||
--background-below : #d7c5c5;
|
||||
--background-inverse : #221e1e;
|
||||
--background-inverse-dark : #120f0f;
|
||||
--node-background-important: #c3eac3;
|
||||
--node-background-completed: #b0c0b0;
|
||||
--node-background : #bdb;
|
||||
--connection : #b2b7b2;
|
||||
--connection-completed : #d1d1d1;
|
||||
--text : #151313;
|
||||
--text-hover : #463e3e;
|
||||
--text-active : #0e0e0e;
|
||||
--text-inverse-above : #fff;
|
||||
--text-inverse : #efefef;
|
||||
--text-inverse-below : #d0d0d0;
|
||||
--text-red : #f8a2a2;
|
||||
--text-red-hover : #ffbcbc;
|
||||
--text-red-active : #e69191;
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--background-above-1: #322d2d;
|
||||
--background-above : #2b2525;
|
||||
--background : #221e1e;
|
||||
--background-below : #121010;
|
||||
--node-background : #221e1e;
|
||||
--text : #e6e6e6;
|
||||
--text-hover : #fff;
|
||||
--text-active : #d0d0d0;
|
||||
--text-inverse : 'dark';
|
||||
--red-light-1 : #dc4343;
|
||||
--red-light : #bf3737;
|
||||
--red : #a43333;
|
||||
--red-dark : #8d2a2a;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes page-background-gradient {
|
||||
25% {
|
||||
left: -350%;
|
||||
top : 0%;
|
||||
}
|
||||
|
||||
50% {
|
||||
left: 0%;
|
||||
top : 0%;
|
||||
}
|
||||
|
||||
75% {
|
||||
left: 0%;
|
||||
top : -350%;
|
||||
}
|
||||
|
||||
to {
|
||||
left: -350%;
|
||||
top : -350%;
|
||||
}
|
||||
}
|
||||
|
||||
:root {
|
||||
--link : #3c76ff;
|
||||
--link-hover : #6594ff;
|
||||
--link-active: #3064dd;
|
||||
}
|
||||
|
||||
* {
|
||||
text-decoration: none;
|
||||
outline : none;
|
||||
border : none;
|
||||
color : var(--text);
|
||||
font-family : 'Commissioner', sans-serif;
|
||||
transition : 0.1s ease-out;
|
||||
}
|
||||
|
||||
.unselectable {
|
||||
-webkit-touch-callout: none;
|
||||
-webkit-user-select : none;
|
||||
-khtml-user-select : none;
|
||||
-moz-user-select : none;
|
||||
-ms-user-select : none;
|
||||
user-select : none;
|
||||
}
|
||||
|
||||
a {
|
||||
color: var(--link);
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: var(--link-hover);
|
||||
}
|
||||
|
||||
a:active {
|
||||
color : var(--link-active);
|
||||
transition: unset;
|
||||
}
|
||||
|
||||
body {
|
||||
height : 100vh;
|
||||
margin : 0;
|
||||
overflow : hidden;
|
||||
background-color: var(--background);
|
||||
}
|
||||
|
||||
body>div.background {
|
||||
z-index : -50000;
|
||||
left : -350%;
|
||||
top : -350%;
|
||||
width : 500%;
|
||||
height : 500%;
|
||||
position : absolute;
|
||||
filter : blur(200px);
|
||||
animation-duration : 15s;
|
||||
animation-name : page-background-gradient;
|
||||
animation-iteration-count: infinite;
|
||||
background-repeat : no-repeat;
|
||||
animation-timing-function: linear;
|
||||
background-image : radial-gradient(circle, var(--background-above) 0%, rgba(0, 0, 0, 0) 100%);
|
||||
}
|
||||
|
||||
aside {
|
||||
z-index : 500;
|
||||
grid-column: 1/ 4;
|
||||
grid-row : 2;
|
||||
overflow : hidden;
|
||||
}
|
||||
|
||||
header {
|
||||
z-index : 5000;
|
||||
position : absolute;
|
||||
display : flex;
|
||||
flex-direction: column;
|
||||
box-shadow : 2px 0 5px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
header>menu {
|
||||
margin : unset;
|
||||
padding : 20px;
|
||||
display : flex;
|
||||
flex-direction : column;
|
||||
flex-grow : 1;
|
||||
background-color: var(--background-light-1);
|
||||
}
|
||||
|
||||
header>#account>button#login {
|
||||
z-index: 1500;
|
||||
}
|
||||
|
||||
header>menu a {
|
||||
margin-bottom: 8px;
|
||||
display : flex;
|
||||
align-items : center;
|
||||
}
|
||||
|
||||
header>menu a:last-child {
|
||||
margin-bottom: unset;
|
||||
}
|
||||
|
||||
header>menu a svg {
|
||||
margin-right: 8px;
|
||||
height : 1.2rem;
|
||||
position : relative;
|
||||
}
|
||||
|
||||
header>menu a:hover svg {
|
||||
margin-left : -5px;
|
||||
margin-right: 13px;
|
||||
}
|
||||
|
||||
header>menu a svg path {
|
||||
fill: var(--text);
|
||||
}
|
||||
|
||||
header>section {
|
||||
background-color: var(--background-light-1);
|
||||
}
|
||||
|
||||
header :is(button, a[type="button"]) {
|
||||
width : 100%;
|
||||
height : 40px;
|
||||
display : flex;
|
||||
justify-content : center;
|
||||
align-items : center;
|
||||
cursor : pointer;
|
||||
background-color: var(--red);
|
||||
transition : unset;
|
||||
}
|
||||
|
||||
header button {
|
||||
font-weight : bold;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
header :is(button, a[type="button"]):hover {
|
||||
background-color: var(--red-light);
|
||||
}
|
||||
|
||||
header :is(button, a[type="button"]):active {
|
||||
background-color: var(--red-dark);
|
||||
}
|
||||
|
||||
header>nav {
|
||||
margin-top : auto;
|
||||
display : flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
main {
|
||||
z-index : 1000;
|
||||
height : 100%;
|
||||
display : flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
footer {
|
||||
z-index : 3000;
|
||||
position: absolute;
|
||||
}
|
||||
|
|
|
@ -1,26 +1,26 @@
|
|||
"use strict";
|
||||
|
||||
class account {
|
||||
static async initialization() {
|
||||
// Запрос
|
||||
return fetch('https://auth.mirzaev.sexy/account/initialization', {
|
||||
method: 'GET'
|
||||
});
|
||||
}
|
||||
|
||||
static authentication() {
|
||||
// Инициализация аккаунта
|
||||
alert(1);
|
||||
this.initialization()
|
||||
.then(
|
||||
(response) => {
|
||||
alert(2);
|
||||
}
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static deauthentication() {
|
||||
}
|
||||
}
|
||||
"use strict";
|
||||
|
||||
class account {
|
||||
static async initialization() {
|
||||
// Запрос
|
||||
return fetch('https://auth.mirzaev.sexy/account/initialization', {
|
||||
method: 'GET'
|
||||
});
|
||||
}
|
||||
|
||||
static authentication() {
|
||||
// Инициализация аккаунта
|
||||
alert(1);
|
||||
this.initialization()
|
||||
.then(
|
||||
(response) => {
|
||||
alert(2);
|
||||
}
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static deauthentication() {
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,127 +1,127 @@
|
|||
"use strict";
|
||||
|
||||
class troller {
|
||||
static what = {
|
||||
enable() {
|
||||
document.body.onmouseleave = function () {
|
||||
// if (Math.random() > 0.90) {
|
||||
// 10%
|
||||
|
||||
troller.what.start();
|
||||
// }
|
||||
};
|
||||
|
||||
document.body.onmouseenter = function () {
|
||||
troller.what.end();
|
||||
};
|
||||
},
|
||||
disable() {
|
||||
document.body.onmouseleave = document.body.onmouseenter = undefined;
|
||||
},
|
||||
start() {
|
||||
// Отображение изображения
|
||||
document.getElementById('what_image').classList.add('active');
|
||||
|
||||
// Инициализация элемента со звуком
|
||||
const what_sound = document.getElementById('what_sound');
|
||||
|
||||
// Воспроизведение звука
|
||||
what_sound.currentTime = 0;
|
||||
what_sound.play();
|
||||
},
|
||||
end() {
|
||||
// Сокрытие изображения
|
||||
document.getElementById('what_image').classList.remove('active');
|
||||
|
||||
// Остановка звука
|
||||
document.getElementById('what_sound').pause();
|
||||
},
|
||||
single(event = 'onmouseleave') {
|
||||
if (typeof event === 'string') {
|
||||
// Получены обязательные входные параметры
|
||||
// Отображение изображения
|
||||
document.getElementById('what_image').classList.add('active');
|
||||
|
||||
// Инициализация элемента со звуком
|
||||
const what_sound = document.getElementById('what_sound');
|
||||
|
||||
// Воспроизведение звука
|
||||
what_sound.currentTime = 0;
|
||||
what_sound.play();
|
||||
|
||||
document.body[event] = function () {
|
||||
troller.what.end();
|
||||
|
||||
document.body[event] = undefined;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static vk() {
|
||||
setInterval(function () {
|
||||
const sound = document.getElementById('sound_vk');
|
||||
|
||||
if (Math.random() > 0.95) {
|
||||
// 5%
|
||||
|
||||
// Воспроизведение звука
|
||||
sound.currentTime = 0;
|
||||
sound.play();
|
||||
}
|
||||
}, 85000);
|
||||
}
|
||||
|
||||
static whatsapp() {
|
||||
setInterval(function () {
|
||||
const sound = document.getElementById('sound_whatsup');
|
||||
|
||||
if (Math.random() > 0.97) {
|
||||
// 3%
|
||||
|
||||
// Воспроизведение звука
|
||||
sound.currentTime = 0;
|
||||
sound.play();
|
||||
}
|
||||
}, 125000);
|
||||
}
|
||||
|
||||
static iphone() {
|
||||
setInterval(function () {
|
||||
const sound = document.getElementById('sound_iphone');
|
||||
|
||||
if (Math.random() > 0.98) {
|
||||
// 2%
|
||||
|
||||
// Воспроизведение звука
|
||||
sound.currentTime = 0;
|
||||
sound.play();
|
||||
}
|
||||
}, 265000);
|
||||
}
|
||||
}
|
||||
|
||||
if (Math.random() > 0.90) {
|
||||
// 10%
|
||||
|
||||
troller.what.enable();
|
||||
}
|
||||
|
||||
if (Math.random() > 0.90) {
|
||||
// 10%
|
||||
|
||||
troller.vk();
|
||||
}
|
||||
|
||||
|
||||
if (Math.random() > 0.90) {
|
||||
// 10%
|
||||
|
||||
troller.whatsapp();
|
||||
}
|
||||
|
||||
if (Math.random() > 0.90) {
|
||||
// 10%
|
||||
|
||||
troller.iphone();
|
||||
}
|
||||
"use strict";
|
||||
|
||||
class troller {
|
||||
static what = {
|
||||
enable() {
|
||||
document.body.onmouseleave = function () {
|
||||
// if (Math.random() > 0.90) {
|
||||
// 10%
|
||||
|
||||
troller.what.start();
|
||||
// }
|
||||
};
|
||||
|
||||
document.body.onmouseenter = function () {
|
||||
troller.what.end();
|
||||
};
|
||||
},
|
||||
disable() {
|
||||
document.body.onmouseleave = document.body.onmouseenter = undefined;
|
||||
},
|
||||
start() {
|
||||
// Отображение изображения
|
||||
document.getElementById('what_image').classList.add('active');
|
||||
|
||||
// Инициализация элемента со звуком
|
||||
const what_sound = document.getElementById('what_sound');
|
||||
|
||||
// Воспроизведение звука
|
||||
what_sound.currentTime = 0;
|
||||
what_sound.play();
|
||||
},
|
||||
end() {
|
||||
// Сокрытие изображения
|
||||
document.getElementById('what_image').classList.remove('active');
|
||||
|
||||
// Остановка звука
|
||||
document.getElementById('what_sound').pause();
|
||||
},
|
||||
single(event = 'onmouseleave') {
|
||||
if (typeof event === 'string') {
|
||||
// Получены обязательные входные параметры
|
||||
// Отображение изображения
|
||||
document.getElementById('what_image').classList.add('active');
|
||||
|
||||
// Инициализация элемента со звуком
|
||||
const what_sound = document.getElementById('what_sound');
|
||||
|
||||
// Воспроизведение звука
|
||||
what_sound.currentTime = 0;
|
||||
what_sound.play();
|
||||
|
||||
document.body[event] = function () {
|
||||
troller.what.end();
|
||||
|
||||
document.body[event] = undefined;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static vk() {
|
||||
setInterval(function () {
|
||||
const sound = document.getElementById('sound_vk');
|
||||
|
||||
if (Math.random() > 0.95) {
|
||||
// 5%
|
||||
|
||||
// Воспроизведение звука
|
||||
sound.currentTime = 0;
|
||||
sound.play();
|
||||
}
|
||||
}, 85000);
|
||||
}
|
||||
|
||||
static whatsapp() {
|
||||
setInterval(function () {
|
||||
const sound = document.getElementById('sound_whatsup');
|
||||
|
||||
if (Math.random() > 0.97) {
|
||||
// 3%
|
||||
|
||||
// Воспроизведение звука
|
||||
sound.currentTime = 0;
|
||||
sound.play();
|
||||
}
|
||||
}, 125000);
|
||||
}
|
||||
|
||||
static iphone() {
|
||||
setInterval(function () {
|
||||
const sound = document.getElementById('sound_iphone');
|
||||
|
||||
if (Math.random() > 0.98) {
|
||||
// 2%
|
||||
|
||||
// Воспроизведение звука
|
||||
sound.currentTime = 0;
|
||||
sound.play();
|
||||
}
|
||||
}, 265000);
|
||||
}
|
||||
}
|
||||
|
||||
if (Math.random() > 0.90) {
|
||||
// 10%
|
||||
|
||||
troller.what.enable();
|
||||
}
|
||||
|
||||
if (Math.random() > 0.90) {
|
||||
// 10%
|
||||
|
||||
troller.vk();
|
||||
}
|
||||
|
||||
|
||||
if (Math.random() > 0.90) {
|
||||
// 10%
|
||||
|
||||
troller.whatsapp();
|
||||
}
|
||||
|
||||
if (Math.random() > 0.90) {
|
||||
// 10%
|
||||
|
||||
troller.iphone();
|
||||
}
|
||||
|
|
|
@ -1 +1 @@
|
|||
arangodb.php
|
||||
arangodb.php
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
'endpoint' => 'unix:///var/run/arangodb3/arango.sock',
|
||||
'database' => '',
|
||||
'name' => '',
|
||||
'password' => ''
|
||||
];
|
||||
<?php
|
||||
|
||||
return [
|
||||
'endpoint' => 'unix:///var/run/arangodb3/arango.sock',
|
||||
'database' => '',
|
||||
'name' => '',
|
||||
'password' => ''
|
||||
];
|
||||
|
|
|
@ -1,53 +0,0 @@
|
|||
{% block css %}
|
||||
<link type="text/css" rel="stylesheet" href="/css/account.css">
|
||||
<link type="text/css" rel="stylesheet" href="/css/gradient.css">
|
||||
{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<section id="authentication">
|
||||
{% if account %}
|
||||
{{ account.getKey() }}
|
||||
{% if vk %}
|
||||
{{ vk.mail }}
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<section class="header gradient unselectable">
|
||||
<div class="glare"></div>
|
||||
<img class="avatar unselectable" src="/images/what.png" alt="Пользователь" draggable="false">
|
||||
<a href="https://mirzaev.sexy">Нейрожурнал Мирзаева</a>
|
||||
<div class="red"></div>
|
||||
<div class="green"></div>
|
||||
<div class="blue"></div>
|
||||
<img class="cover unselectable" src="/images/heh.gif" alt="Нейрожурнал Мирзаева" draggable="false"></img>
|
||||
</section>
|
||||
<section class="body">
|
||||
<ul>
|
||||
<li>Подпункт 2.1.</li>
|
||||
<li>Подпункт 2.2.
|
||||
<ul>
|
||||
<li>Подпункт 2.2.1.</li>
|
||||
<li>Подпункт 2.2.2.</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>Подпункт 2.3.</li>
|
||||
</ul>
|
||||
<div class="buttons">
|
||||
<button class="accept">Разрешить</button>
|
||||
<button>Запретить</button>
|
||||
</div>
|
||||
</section>
|
||||
{% endif %}
|
||||
<svg width="0" height="0">
|
||||
<defs>
|
||||
<clipPath id="authentication-header-mask">
|
||||
<path
|
||||
d="M50,160 L50,130 C22,130 0,107.612 0,80 C0,52 22,30 50,30 L50,3 C50,1.3 51.3,0 53,0 L447,0 C448,0 450,1.5 450,3 L450,160 L50,160 Z" />
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
</section>
|
||||
{% endblock %}
|
||||
|
||||
{% block js %}
|
||||
<script type="text/javascript" src="/js/account.js"></script>
|
||||
{% endblock %}
|
|
@ -1,14 +1,14 @@
|
|||
|
||||
{% block css %}
|
||||
{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<aside>
|
||||
</aside>
|
||||
{% endblock %}
|
||||
|
||||
{% block js %}
|
||||
{% endblock %}
|
||||
|
||||
{% block js_init %}
|
||||
{% endblock %}
|
||||
|
||||
{% block css %}
|
||||
{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<aside>
|
||||
</aside>
|
||||
{% endblock %}
|
||||
|
||||
{% block js %}
|
||||
{% endblock %}
|
||||
|
||||
{% block js_init %}
|
||||
{% endblock %}
|
||||
|
|
|
@ -1,33 +1,33 @@
|
|||
<!doctype html>
|
||||
|
||||
<html lang="ru">
|
||||
|
||||
<head>
|
||||
{% use 'head.html' with title as head_title, meta as head_meta, css as head_css %}
|
||||
|
||||
{% block title %}
|
||||
{{ block('head_title') }}
|
||||
{% endblock %}
|
||||
|
||||
{% block meta %}
|
||||
{{ block('head_meta') }}
|
||||
{% endblock %}
|
||||
|
||||
{% block css %}
|
||||
{{ block('head_css') }}
|
||||
{% endblock %}
|
||||
</head>
|
||||
|
||||
<body>
|
||||
{% block body %}
|
||||
{% endblock %}
|
||||
|
||||
{% block js %}
|
||||
{% include 'js.html' %}
|
||||
{% endblock %}
|
||||
|
||||
{% block js_init %}
|
||||
{% endblock %}
|
||||
</body>
|
||||
|
||||
</html>
|
||||
<!doctype html>
|
||||
|
||||
<html lang="ru">
|
||||
|
||||
<head>
|
||||
{% use 'head.html' with title as head_title, meta as head_meta, css as head_css %}
|
||||
|
||||
{% block title %}
|
||||
{{ block('head_title') }}
|
||||
{% endblock %}
|
||||
|
||||
{% block meta %}
|
||||
{{ block('head_meta') }}
|
||||
{% endblock %}
|
||||
|
||||
{% block css %}
|
||||
{{ block('head_css') }}
|
||||
{% endblock %}
|
||||
</head>
|
||||
|
||||
<body>
|
||||
{% block body %}
|
||||
{% endblock %}
|
||||
|
||||
{% block js %}
|
||||
{% include 'js.html' %}
|
||||
{% endblock %}
|
||||
|
||||
{% block js_init %}
|
||||
{% endblock %}
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<footer>
|
||||
<!-- <p><a href="http://www.anybrowser.org/campaign/"><img src="/img/logos/any_browser.gif" width="278" height="44" alt="Доступно на любом браузере" /></a></p> -->
|
||||
<!-- <p><a href="/browsers"><img src="/img/logos/any_browser.gif" width="278" height="44" alt="Доступно на любом браузере" /></a></p> -->
|
||||
</footer>
|
||||
<footer>
|
||||
<!-- <p><a href="http://www.anybrowser.org/campaign/"><img src="/img/logos/any_browser.gif" width="278" height="44" alt="Доступно на любом браузере" /></a></p> -->
|
||||
<!-- <p><a href="/browsers"><img src="/img/logos/any_browser.gif" width="278" height="44" alt="Доступно на любом браузере" /></a></p> -->
|
||||
</footer>
|
||||
|
|
|
@ -1,86 +1,86 @@
|
|||
{% block css %}
|
||||
<link type="text/css" rel="stylesheet" href="/css/graph.css">
|
||||
<link type="text/css" rel="stylesheet" href="/css/icon_close.css" />
|
||||
{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
{% if graph.id != empty %}
|
||||
<section id="{{ graph.id }}" class="graph unselectable" {% for name, value in graph.attributes %} {{ name }}="{{value}}"
|
||||
{% endfor %}>
|
||||
{% for element in graph.elements %}
|
||||
<{{element.tag??'article'}}>{{ element.content }}</{{element.tag??'article'}}>
|
||||
{% endfor %}
|
||||
</section>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block js %}
|
||||
<script type="module" src="/js/victor.js" defer></script>
|
||||
<script type="module" src="/js/graph.js" defer></script>
|
||||
{% endblock %}
|
||||
|
||||
{% block js_init %}
|
||||
<script>
|
||||
document.addEventListener('graph.loaded', function (e) {
|
||||
// Инициализация графика
|
||||
{% if graph.id != empty %}
|
||||
const core = new e.detail.graph(document.getElementById('{{ graph.id }}'));
|
||||
|
||||
core.write({
|
||||
title: 'бебра'
|
||||
});
|
||||
const mirzaev = core.write({
|
||||
title: 'Арсен Мирзаев',
|
||||
description: ' абабабаба абабабабаабабабабаабабабабаабабабаба абабабаба абабабаба абабабабаабабабаба абабабаба абабабаба абабабабабабаба абабабабаабабабабабаба абабабабаабабабабабаба абабабабаабабабабабаба абабабабаабабабабабаба абабабабаабабабабабаба абабабабаабабабабабаба абабабабаабабабабабаба абабабабаабабабабабаба абабабабаабабабабабаба абабабабаабабаба',
|
||||
cover: 'https://sun9-east.userapi.com/sun9-27/s/v1/ig2/qOBvWvsDwPmMjOTqQbl0TuGHaoMwWQhhd81nxD847v32dT-pyYa9kxw2MY7moQBVBoN4iVLnUZx6WmE4x4HnIwAu.jpg?size=810x1080&quality=95&type=album',
|
||||
link: {
|
||||
name: 'Арсен Мирзаев',
|
||||
title: 'Читать статью полностью',
|
||||
href: 'https://google.com',
|
||||
class: ['source']
|
||||
},
|
||||
popup: 'Для подробной информации читайте статью полностью',
|
||||
color: 'red'
|
||||
});
|
||||
const berbi = core.write({
|
||||
title: 'берби'
|
||||
});
|
||||
const anarchy = core.write({
|
||||
title: 'анархия'
|
||||
});
|
||||
core.connect(
|
||||
berbi,
|
||||
mirzaev);
|
||||
core.connect(
|
||||
anarchy,
|
||||
mirzaev);
|
||||
core.connect(
|
||||
core.write({
|
||||
title: 'бабы'
|
||||
}),
|
||||
mirzaev);
|
||||
core.connect(
|
||||
core.write({
|
||||
title: 'Ксения Велькович',
|
||||
description: 'А меня вписать в кружочек?',
|
||||
cover: 'https://storage.mirzaev.sexy/2022/mirzaev.sexy/nodes/ksenia_velkovich.jpg',
|
||||
link: {
|
||||
name: 'Ксения Велькович',
|
||||
title: 'Страница ВКонтакте',
|
||||
href: 'https://vk.com/id720261644',
|
||||
class: ['source']
|
||||
}
|
||||
}),
|
||||
mirzaev);
|
||||
core.connect(
|
||||
core.write({
|
||||
title: 'чокопайки'
|
||||
}),
|
||||
mirzaev);
|
||||
core.connect(
|
||||
anarchy,
|
||||
berbi);
|
||||
{% endif %}
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
{% block css %}
|
||||
<link type="text/css" rel="stylesheet" href="/css/graph.css">
|
||||
<link type="text/css" rel="stylesheet" href="/css/icon_close.css" />
|
||||
{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
{% if graph.id != empty %}
|
||||
<section id="{{ graph.id }}" class="graph unselectable" {% for name, value in graph.attributes %} {{ name }}="{{value}}"
|
||||
{% endfor %}>
|
||||
{% for element in graph.elements %}
|
||||
<{{element.tag??'article'}}>{{ element.content }}</{{element.tag??'article'}}>
|
||||
{% endfor %}
|
||||
</section>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block js %}
|
||||
<script type="module" src="/js/victor.js" defer></script>
|
||||
<script type="module" src="/js/graph.js" defer></script>
|
||||
{% endblock %}
|
||||
|
||||
{% block js_init %}
|
||||
<script>
|
||||
document.addEventListener('graph.loaded', function (e) {
|
||||
// Инициализация графика
|
||||
{% if graph.id != empty %}
|
||||
const core = new e.detail.graph(document.getElementById('{{ graph.id }}'));
|
||||
|
||||
core.write({
|
||||
title: 'бебра'
|
||||
});
|
||||
const mirzaev = core.write({
|
||||
title: 'Арсен Мирзаев',
|
||||
description: ' абабабаба абабабабаабабабабаабабабабаабабабаба абабабаба абабабаба абабабабаабабабаба абабабаба абабабаба абабабабабабаба абабабабаабабабабабаба абабабабаабабабабабаба абабабабаабабабабабаба абабабабаабабабабабаба абабабабаабабабабабаба абабабабаабабабабабаба абабабабаабабабабабаба абабабабаабабабабабаба абабабабаабабабабабаба абабабабаабабаба',
|
||||
cover: 'https://sun9-east.userapi.com/sun9-27/s/v1/ig2/qOBvWvsDwPmMjOTqQbl0TuGHaoMwWQhhd81nxD847v32dT-pyYa9kxw2MY7moQBVBoN4iVLnUZx6WmE4x4HnIwAu.jpg?size=810x1080&quality=95&type=album',
|
||||
link: {
|
||||
name: 'Арсен Мирзаев',
|
||||
title: 'Читать статью полностью',
|
||||
href: 'https://google.com',
|
||||
class: ['source']
|
||||
},
|
||||
popup: 'Для подробной информации читайте статью полностью',
|
||||
color: 'red'
|
||||
});
|
||||
const berbi = core.write({
|
||||
title: 'берби'
|
||||
});
|
||||
const anarchy = core.write({
|
||||
title: 'анархия'
|
||||
});
|
||||
core.connect(
|
||||
berbi,
|
||||
mirzaev);
|
||||
core.connect(
|
||||
anarchy,
|
||||
mirzaev);
|
||||
core.connect(
|
||||
core.write({
|
||||
title: 'бабы'
|
||||
}),
|
||||
mirzaev);
|
||||
core.connect(
|
||||
core.write({
|
||||
title: 'Ксения Велькович',
|
||||
description: 'А меня вписать в кружочек?',
|
||||
cover: 'https://storage.mirzaev.sexy/2022/mirzaev.sexy/nodes/ksenia_velkovich.jpg',
|
||||
link: {
|
||||
name: 'Ксения Велькович',
|
||||
title: 'Страница ВКонтакте',
|
||||
href: 'https://vk.com/id720261644',
|
||||
class: ['source']
|
||||
}
|
||||
}),
|
||||
mirzaev);
|
||||
core.connect(
|
||||
core.write({
|
||||
title: 'чокопайки'
|
||||
}),
|
||||
mirzaev);
|
||||
core.connect(
|
||||
anarchy,
|
||||
berbi);
|
||||
{% endif %}
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
{% block title %}
|
||||
<title>{% if head.title != empty %}{{head.title}}{% else %}Управление аккаунтом{% endif %}</title>
|
||||
{% endblock %}
|
||||
|
||||
{% block meta %}
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
{% for meta in head.metas %}
|
||||
<meta {% for name, value in meta.attributes %}{{name}}="{{value}}" {% endfor %}>
|
||||
{% endfor %}
|
||||
{% endblock %}
|
||||
|
||||
{% block css %}
|
||||
<link type="text/css" rel="stylesheet" href="/css/main.css" />
|
||||
{% endblock %}
|
||||
{% block title %}
|
||||
<title>{% if head.title != empty %}{{head.title}}{% else %}Управление аккаунтом{% endif %}</title>
|
||||
{% endblock %}
|
||||
|
||||
{% block meta %}
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
{% for meta in head.metas %}
|
||||
<meta {% for name, value in meta.attributes %}{{name}}="{{value}}" {% endfor %}>
|
||||
{% endfor %}
|
||||
{% endblock %}
|
||||
|
||||
{% block css %}
|
||||
<link type="text/css" rel="stylesheet" href="/css/main.css" />
|
||||
{% endblock %}
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
{% block css %}
|
||||
{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<header>
|
||||
</header>
|
||||
{% endblock %}
|
||||
|
||||
{% block js %}
|
||||
{% endblock %}
|
||||
|
||||
{% block js_init %}
|
||||
{% endblock %}
|
||||
{% block css %}
|
||||
{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<header>
|
||||
</header>
|
||||
{% endblock %}
|
||||
|
||||
{% block js %}
|
||||
{% endblock %}
|
||||
|
||||
{% block js_init %}
|
||||
{% endblock %}
|
||||
|
|
|
@ -1,28 +1,28 @@
|
|||
{% block css %}
|
||||
<link type="text/css" rel="stylesheet" href="/css/hotline.css">
|
||||
{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
{% if hotline.id != empty %}
|
||||
<section id="{{ hotline.id }}" class="hotline unselectable" data-hotline="true" {% for name, value in hotline.parameters
|
||||
%} data-hotline-{{ name }}="{{value}}" {% endfor %} {% for name, value in hotline.attributes %} {{ name
|
||||
}}="{{value}}" {% endfor %}>
|
||||
{% for element in hotline.elements %}
|
||||
<{{element.tag??'article'}}>{{ element.content }}</{{element.tag??'article'}}>
|
||||
{% endfor %}
|
||||
</section>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block js %}
|
||||
<script type="text/javascript" src="/js/hotline.js" defer></script>
|
||||
{% endblock %}
|
||||
|
||||
{% block js_init %}
|
||||
<script>
|
||||
document.addEventListener('hotline.loaded', function (e) {
|
||||
// Запуск препроцессора бегущих строк
|
||||
e.detail.hotline.preprocessing();
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
{% block css %}
|
||||
<link type="text/css" rel="stylesheet" href="/css/hotline.css">
|
||||
{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
{% if hotline.id != empty %}
|
||||
<section id="{{ hotline.id }}" class="hotline unselectable" data-hotline="true" {% for name, value in hotline.parameters
|
||||
%} data-hotline-{{ name }}="{{value}}" {% endfor %} {% for name, value in hotline.attributes %} {{ name
|
||||
}}="{{value}}" {% endfor %}>
|
||||
{% for element in hotline.elements %}
|
||||
<{{element.tag??'article'}}>{{ element.content }}</{{element.tag??'article'}}>
|
||||
{% endfor %}
|
||||
</section>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block js %}
|
||||
<script type="text/javascript" src="/js/hotline.js" defer></script>
|
||||
{% endblock %}
|
||||
|
||||
{% block js_init %}
|
||||
<script>
|
||||
document.addEventListener('hotline.loaded', function (e) {
|
||||
// Запуск препроцессора бегущих строк
|
||||
e.detail.hotline.preprocessing();
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
|
|
@ -1,47 +1,47 @@
|
|||
{% extends "core.html" %}
|
||||
|
||||
{% use 'account/element.html' with css as account_css, body as account_body, js as account_js %}
|
||||
{% use "core.html" with css as core_css, body as core_body, js as core_js, js_init as core_js_init %}
|
||||
{% use "header.html" with css as header_css, body as header_body, js as header_js, js_init as header_js_init %}
|
||||
{% use "aside.html" with css as aside_css, body as aside_body, js as aside_js, js_init as aside_js_init %}
|
||||
{% use 'graph/index.html' with css as graph_css, body as graph_body, js as graph_js, js_init as graph_js_init %}
|
||||
|
||||
{% block css %}
|
||||
{{ block('core_css') }}
|
||||
{{ block('header_css') }}
|
||||
{{ block('aside_css') }}
|
||||
{{ block('graph_css') }}
|
||||
{{ block('account_css') }}
|
||||
{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
{{ block('core_body') }}
|
||||
{{ block('aside_body') }}
|
||||
{{ block('header_body') }}
|
||||
|
||||
<main>
|
||||
<noscript>К сожалению мой сайт ещё пока не готов для работы без javascript</noscript>
|
||||
{% block main %}
|
||||
{{ block('account_body') }}
|
||||
{% endblock %}
|
||||
{{ block('graph_body') }}
|
||||
</main>
|
||||
|
||||
{# {% include 'footer.html' %} #}
|
||||
{# <div class="background"></div> #}
|
||||
{% endblock %}
|
||||
|
||||
{% block js %}
|
||||
{{ block('core_js') }}
|
||||
{{ block('header_js') }}
|
||||
{{ block('aside_js') }}
|
||||
{{ block('graph_js') }}
|
||||
{{ block('account_js') }}
|
||||
{% endblock %}
|
||||
|
||||
{% block js_init %}
|
||||
{{ block('core_js_init') }}
|
||||
{{ block('header_js_init') }}
|
||||
{{ block('aside_js_init') }}
|
||||
{{ block('graph_js_init') }}
|
||||
{% endblock %}
|
||||
{% extends "core.html" %}
|
||||
|
||||
{% use 'nodes/account.html' with css as account_css, body as account_body, js as account_js %}
|
||||
{% use "core.html" with css as core_css, body as core_body, js as core_js, js_init as core_js_init %}
|
||||
{% use "header.html" with css as header_css, body as header_body, js as header_js, js_init as header_js_init %}
|
||||
{% use "aside.html" with css as aside_css, body as aside_body, js as aside_js, js_init as aside_js_init %}
|
||||
{% use 'graph/index.html' with css as graph_css, body as graph_body, js as graph_js, js_init as graph_js_init %}
|
||||
|
||||
{% block css %}
|
||||
{{ block('core_css') }}
|
||||
{{ block('header_css') }}
|
||||
{{ block('aside_css') }}
|
||||
{{ block('graph_css') }}
|
||||
{{ block('account_css') }}
|
||||
{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
{{ block('core_body') }}
|
||||
{{ block('aside_body') }}
|
||||
{{ block('header_body') }}
|
||||
|
||||
<main>
|
||||
<noscript>К сожалению мой сайт ещё пока не готов для работы без javascript</noscript>
|
||||
{% block main %}
|
||||
{{ block('account_body') }}
|
||||
{% endblock %}
|
||||
{{ block('graph_body') }}
|
||||
</main>
|
||||
|
||||
{# {% include 'footer.html' %} #}
|
||||
{# <div class="background"></div> #}
|
||||
{% endblock %}
|
||||
|
||||
{% block js %}
|
||||
{{ block('core_js') }}
|
||||
{{ block('header_js') }}
|
||||
{{ block('aside_js') }}
|
||||
{{ block('graph_js') }}
|
||||
{{ block('account_js') }}
|
||||
{% endblock %}
|
||||
|
||||
{% block js_init %}
|
||||
{{ block('core_js_init') }}
|
||||
{{ block('header_js_init') }}
|
||||
{{ block('aside_js_init') }}
|
||||
{{ block('graph_js_init') }}
|
||||
{% endblock %}
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
{% block js %}
|
||||
<script type="text/javascript" src="/js/js.cookie.min.js" defer></script>
|
||||
{% endblock %}
|
||||
{% block js %}
|
||||
<script type="text/javascript" src="/js/js.cookie.min.js" defer></script>
|
||||
{% endblock %}
|
||||
|
|
|
@ -1,25 +1,25 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace mirzaev\site\account\views;
|
||||
|
||||
use mirzaev\minimal\controller;
|
||||
|
||||
use Twig\Loader\FilesystemLoader;
|
||||
use Twig\Environment as view;
|
||||
|
||||
/**
|
||||
* Менеджер представлений
|
||||
*
|
||||
* @package mirzaev\site\account\controllers
|
||||
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
||||
*/
|
||||
final class manager extends controller
|
||||
{
|
||||
public function render(string $file, array $vars = []): ?string
|
||||
{
|
||||
// Генерация представления
|
||||
return (new view(new FilesystemLoader(VIEWS)))->render($file, $vars);
|
||||
}
|
||||
}
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace mirzaev\site\account\views;
|
||||
|
||||
use mirzaev\minimal\controller;
|
||||
|
||||
use Twig\Loader\FilesystemLoader;
|
||||
use Twig\Environment as view;
|
||||
|
||||
/**
|
||||
* Менеджер представлений
|
||||
*
|
||||
* @package mirzaev\site\account\controllers
|
||||
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
||||
*/
|
||||
final class manager extends controller
|
||||
{
|
||||
public function render(string $file, array $vars = []): ?string
|
||||
{
|
||||
// Генерация представления
|
||||
return (new view(new FilesystemLoader(VIEWS)))->render($file, $vars);
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,53 @@
|
|||
{% block css %}
|
||||
<link type="text/css" rel="stylesheet" href="/css/account.css">
|
||||
<link type="text/css" rel="stylesheet" href="/css/gradient.css">
|
||||
{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<section id="authentication">
|
||||
{% if account %}
|
||||
{{ account.getKey() }}
|
||||
{% if vk %}
|
||||
{{ vk.mail }}
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<section class="header gradient unselectable">
|
||||
<div class="glare"></div>
|
||||
<img class="avatar unselectable" src="/images/what.png" alt="Пользователь" draggable="false">
|
||||
<a href="https://mirzaev.sexy">{{ name ?? session.ip ?? session.hash ?? 'Ты кто?'}}</a>
|
||||
<div class="red"></div>
|
||||
<div class="green"></div>
|
||||
<div class="blue"></div>
|
||||
<img class="cover unselectable" src="/images/heh.gif" alt="Нейрожурнал Мирзаева" draggable="false"></img>
|
||||
</section>
|
||||
<section class="body">
|
||||
<ul>
|
||||
<li>Подпункт 2.1.</li>
|
||||
<li>Подпункт 2.2.
|
||||
<ul>
|
||||
<li>Подпункт 2.2.1.</li>
|
||||
<li>Подпункт 2.2.2.</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>Подпункт 2.3.</li>
|
||||
</ul>
|
||||
<div class="buttons">
|
||||
<button class="accept">Разрешить</button>
|
||||
<button>Запретить</button>
|
||||
</div>
|
||||
</section>
|
||||
{% endif %}
|
||||
<svg width="0" height="0">
|
||||
<defs>
|
||||
<clipPath id="authentication-header-mask">
|
||||
<path
|
||||
d="M50,160 L50,130 C22,130 0,107.612 0,80 C0,52 22,30 50,30 L50,3 C50,1.3 51.3,0 53,0 L447,0 C448,0 450,1.5 450,3 L450,160 L50,160 Z" />
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
</section>
|
||||
{% endblock %}
|
||||
|
||||
{% block js %}
|
||||
<script type="text/javascript" src="/js/account.js"></script>
|
||||
{% endblock %}
|
|
@ -0,0 +1,53 @@
|
|||
{% block css %}
|
||||
<link type="text/css" rel="stylesheet" href="/css/account.css">
|
||||
<link type="text/css" rel="stylesheet" href="/css/gradient.css">
|
||||
{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<section id="authentication">
|
||||
{% if account %}
|
||||
{{ account.getKey() }}
|
||||
{% if vk %}
|
||||
{{ vk.mail }}
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<section class="header gradient unselectable">
|
||||
<div class="glare"></div>
|
||||
<img class="avatar unselectable" src="/images/what.png" alt="Пользователь" draggable="false">
|
||||
<a href="https://mirzaev.sexy">Нейрожурнал Мирзаева</a>
|
||||
<div class="red"></div>
|
||||
<div class="green"></div>
|
||||
<div class="blue"></div>
|
||||
<img class="cover unselectable" src="/images/heh.gif" alt="Нейрожурнал Мирзаева" draggable="false"></img>
|
||||
</section>
|
||||
<section class="body">
|
||||
<ul>
|
||||
<li>Подпункт 2.1.</li>
|
||||
<li>Подпункт 2.2.
|
||||
<ul>
|
||||
<li>Подпункт 2.2.1.</li>
|
||||
<li>Подпункт 2.2.2.</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>Подпункт 2.3.</li>
|
||||
</ul>
|
||||
<div class="buttons">
|
||||
<button class="accept">Разрешить</button>
|
||||
<button>Запретить</button>
|
||||
</div>
|
||||
</section>
|
||||
{% endif %}
|
||||
<svg width="0" height="0">
|
||||
<defs>
|
||||
<clipPath id="authentication-header-mask">
|
||||
<path
|
||||
d="M50,160 L50,130 C22,130 0,107.612 0,80 C0,52 22,30 50,30 L50,3 C50,1.3 51.3,0 53,0 L447,0 C448,0 450,1.5 450,3 L450,160 L50,160 Z" />
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
</section>
|
||||
{% endblock %}
|
||||
|
||||
{% block js %}
|
||||
<script type="text/javascript" src="/js/account.js"></script>
|
||||
{% endblock %}
|
Loading…
Reference in New Issue