Compare commits
57 commits
release-1.
...
main
Author | SHA1 | Date | |
---|---|---|---|
|
f4cb133e46 | ||
|
540e643e9a | ||
|
e82faca521 | ||
|
dea3e88c38 | ||
|
8681ba9060 | ||
|
cfab1d2e96 | ||
|
118968739c | ||
|
04373e197c | ||
|
847ebb32be | ||
|
0275ff30c6 | ||
|
b41ec07317 | ||
|
e9655f6463 | ||
|
8b8cedf6c1 | ||
|
303d70d1a3 | ||
|
c31617fd10 | ||
|
4ee7f4b79b | ||
|
0581edcc3d | ||
|
83b0e8ccc9 | ||
|
1dab03afe8 | ||
|
be2963117a | ||
|
b5ff9d1998 | ||
|
3360b9d208 | ||
|
52dbf10d3d | ||
|
be85a9531a | ||
|
13f06db887 | ||
|
22e0fe0cec | ||
|
b0c8b51fe6 | ||
|
020ec19124 | ||
|
2e5c8ffbb0 | ||
|
8087b7c720 | ||
|
2918dd347b | ||
|
a665b92e11 | ||
|
07a6a41468 | ||
|
61c0e0cc9e | ||
|
dce7aa906a | ||
|
3078238206 | ||
|
69706f7df6 | ||
|
ab9b61c3ea | ||
|
3d03ccce6f | ||
|
9774d329fd | ||
|
3b3efb4c84 | ||
|
33ce890c07 | ||
|
558a5cb4c0 | ||
|
82888d6e06 | ||
|
5ecb218306 | ||
|
16322d1664 | ||
|
a4922fed39 | ||
|
6c2e8b46a5 | ||
|
a193a702d7 | ||
|
a57d779caf | ||
|
8d0ccdeaa3 | ||
|
1caedf698b | ||
|
cc193f35ab | ||
|
0226560702 | ||
|
0eb4b6735e | ||
|
b9e6278d0a | ||
|
3455e55f71 |
4
.gitignore
vendored
|
@ -6,10 +6,12 @@
|
||||||
/ngallery.yaml
|
/ngallery.yaml
|
||||||
ngallery.yaml
|
ngallery.yaml
|
||||||
/cdn/
|
/cdn/
|
||||||
*.yaml
|
|
||||||
ngallery.yaml
|
ngallery.yaml
|
||||||
/views/pages/t.php
|
/views/pages/t.php
|
||||||
views/pages/t.php
|
views/pages/t.php
|
||||||
rules.txt
|
rules.txt
|
||||||
rules.txt
|
rules.txt
|
||||||
/uploads/*
|
/uploads/*
|
||||||
|
t.php
|
||||||
|
logs
|
||||||
|
.txt
|
22
README.md
|
@ -1,8 +1,9 @@
|
||||||
# NativeGallery
|
# NativeGallery
|
||||||

|

|
||||||
NativeGallery - это реверсивный open-source движок популярного сайта transphoto.org (СТТС) и ему подобных.
|
NativeGallery - это реверсивный open-source движок популярного сайта transphoto.org (СТТС), RailGallery, Fotobus и ему подобных.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### ❗ Движок находится в разработке. Некоторые функции, которые присутствуют на оригинальных галереях могут отличаться от функционала NativeGallery или отсуствовать совсем. Пожалуйста, оставляйте найденные баги и свои пожелания в Issues.
|
|
||||||
|
|
||||||
# Почему я должен использовать ваш движок?
|
# Почему я должен использовать ваш движок?
|
||||||
* **Свобода**: СТТС не предоставляет всем свой исходный код для создания отдельных подобных ему сайтов. С NativeGallery вы сможете обойти это предпятствие!
|
* **Свобода**: СТТС не предоставляет всем свой исходный код для создания отдельных подобных ему сайтов. С NativeGallery вы сможете обойти это предпятствие!
|
||||||
|
@ -13,7 +14,7 @@ NativeGallery - это реверсивный open-source движок попу
|
||||||
Мы настоятельно рекомендуем устанавливать движок на VPS/VDS/выделенный сервер. Поддержка на Shared-хостингах не осуществляется!
|
Мы настоятельно рекомендуем устанавливать движок на VPS/VDS/выделенный сервер. Поддержка на Shared-хостингах не осуществляется!
|
||||||
|
|
||||||
**Операционная система**: Ubuntu 20.04 и выше\
|
**Операционная система**: Ubuntu 20.04 и выше\
|
||||||
**PHP:** 8.3 и выше
|
**PHP:** 8.3 и выше\
|
||||||
**База данных**: MySQL 8.0 и выше
|
**База данных**: MySQL 8.0 и выше
|
||||||
|
|
||||||
# Статус функционала
|
# Статус функционала
|
||||||
|
@ -21,20 +22,20 @@ NativeGallery - это реверсивный open-source движок попу
|
||||||
- [x] Авторизация, Регистрация
|
- [x] Авторизация, Регистрация
|
||||||
- [x] Просмотр профилей
|
- [x] Просмотр профилей
|
||||||
- [ ] Публикация фото:
|
- [ ] Публикация фото:
|
||||||
- [ ] Привязка сущности (Транспортное Средство, Поезд, Самокат, Камень и прочее)
|
- [x] Привязка сущности (Транспортное Средство, Поезд, Самокат, Камень и прочее)
|
||||||
- [x] Загрузка фото
|
- [x] Загрузка фото
|
||||||
- [ ] GeoDB
|
- [x] GeoDB
|
||||||
- [x] Геометка
|
- [x] Геометка
|
||||||
- [ ] Направление съёмки
|
- [ ] Направление съёмки
|
||||||
- [ ] Состояние фотографии
|
- [ ] Состояние фотографии
|
||||||
- [ ] Временная публикация
|
- [x] Временная публикация
|
||||||
- [ ] Условная публикация
|
- [x] Условная публикация
|
||||||
- [ ] Техническая публикация
|
- [x] Техническая публикация
|
||||||
- [ ] Требует исправления
|
- [ ] Требует исправления
|
||||||
- [ ] Возможность создания своих статусов
|
- [ ] Возможность создания своих статусов
|
||||||
- [x] Галереи
|
- [x] Галереи
|
||||||
- [x] Вид сущности (Трамвай, Метрополитен, Троллейбус и т.д)
|
- [x] Вид сущности (Трамвай, Метрополитен, Троллейбус и т.д)
|
||||||
- [ ] GeoDB
|
- [x] GeoDB
|
||||||
- [ ] Фотоконкурс
|
- [ ] Фотоконкурс
|
||||||
- [ ] Поиск
|
- [ ] Поиск
|
||||||
- [ ] Поиск по критериям
|
- [ ] Поиск по критериям
|
||||||
|
@ -51,10 +52,9 @@ NativeGallery - это реверсивный open-source движок попу
|
||||||
- [x] Комментирование
|
- [x] Комментирование
|
||||||
- [x] Рейтинг комментариев
|
- [x] Рейтинг комментариев
|
||||||
- [x] Избранные фотографии
|
- [x] Избранные фотографии
|
||||||
- [ ] Полноценный EXIF
|
- [x] Полноценный EXIF
|
||||||
- [x] Модерация
|
- [x] Модерация
|
||||||
- [ ] Редактирование
|
- [ ] Редактирование
|
||||||
- [ ] Примечания (для сущностей)
|
|
||||||
- [ ] Обновления:
|
- [ ] Обновления:
|
||||||
- [x] Новые фотографии
|
- [x] Новые фотографии
|
||||||
- [x] Новые фотографии из подписок
|
- [x] Новые фотографии из подписок
|
||||||
|
|
31
app/Controllers/Api/Admin/Contests/Create.php
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Controllers\Api\Admin\Contests;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
use App\Services\{Auth, Router, GenerateRandomStr, DB, Json, EXIF};
|
||||||
|
use App\Models\{User, Vote, Photo};
|
||||||
|
|
||||||
|
|
||||||
|
class Create
|
||||||
|
{
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$openprdate = strtotime($_POST['openpretendsdate']);
|
||||||
|
$closeprdate = strtotime($_POST['closepretendsdate']);
|
||||||
|
$opendate = strtotime($_POST['opendate']);
|
||||||
|
$closedate = strtotime($_POST['closedate']);
|
||||||
|
|
||||||
|
if ($_POST['startContestNow'] === "1") {
|
||||||
|
$opendate = $closeprdate;
|
||||||
|
}
|
||||||
|
DB::query('INSERT INTO contests VALUES (\'0\', :themeid, :openprdate, :closeprdate, :opendate, :closedate, 0)', array(':themeid' => $_POST['themeid'], ':openprdate' => $openprdate, ':closeprdate'=>$closeprdate, ':opendate' => $opendate, ':closedate'=>$closedate));
|
||||||
|
echo json_encode(
|
||||||
|
array(
|
||||||
|
'errorcode' => 0,
|
||||||
|
'error' => 0
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
28
app/Controllers/Api/Admin/Contests/CreateTheme.php
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Controllers\Api\Admin\Contests;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
use App\Services\{Auth, Router, GenerateRandomStr, DB, Json, EXIF};
|
||||||
|
use App\Models\{User, Vote, Photo};
|
||||||
|
|
||||||
|
|
||||||
|
class CreateTheme
|
||||||
|
{
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
if ($_POST['active'] === "1") {
|
||||||
|
$status = 1;
|
||||||
|
} else {
|
||||||
|
$status = 0;
|
||||||
|
}
|
||||||
|
DB::query('INSERT INTO contests_themes VALUES (\'0\', :title, :status)', array(':title' => $_POST['body'], ':status' => $status));
|
||||||
|
echo json_encode(
|
||||||
|
array(
|
||||||
|
'errorcode' => 0,
|
||||||
|
'error' => 0
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
23
app/Controllers/Api/Admin/GeoDB/Create.php
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Controllers\Api\Admin\GeoDB;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
use App\Services\{Auth, Router, GenerateRandomStr, DB, Json, EXIF};
|
||||||
|
use App\Models\{User, Vote, Photo};
|
||||||
|
|
||||||
|
|
||||||
|
class Create
|
||||||
|
{
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
DB::query('INSERT INTO geodb VALUES (\'0\', :body)', array(':body' => $_POST['body']));
|
||||||
|
echo json_encode(
|
||||||
|
array(
|
||||||
|
'errorcode' => 0,
|
||||||
|
'error' => 0
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
23
app/Controllers/Api/Admin/GeoDB/Delete.php
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Controllers\Api\Admin\GeoDB;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
use App\Services\{Auth, Router, GenerateRandomStr, DB, Json, EXIF};
|
||||||
|
use App\Models\{User, Vote, Photo};
|
||||||
|
|
||||||
|
|
||||||
|
class Delete
|
||||||
|
{
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
DB::query('DELETE FROM geodb WHERE id=:id', array(':id' => $_GET['id']));
|
||||||
|
echo json_encode(
|
||||||
|
array(
|
||||||
|
'errorcode' => 0,
|
||||||
|
'error' => 0
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
24
app/Controllers/Api/Admin/GeoDB/Load.php
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Controllers\Api\Admin\GeoDB;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
use App\Services\{Auth, Router, GenerateRandomStr, DB, Json, EXIF, Date};
|
||||||
|
use App\Models\{User, Vote, Photo};
|
||||||
|
|
||||||
|
|
||||||
|
class Load
|
||||||
|
{
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$geodb = DB::query('SELECT * FROM geodb');
|
||||||
|
foreach ($geodb as $u) {
|
||||||
|
echo '<tr>
|
||||||
|
<th>' . $u['id'] . '</th>
|
||||||
|
<td>' . $u['title'] . '</td>
|
||||||
|
<td><div class="cmt-submit"><a class="btn btn-sm btn-primary" href="/admin?type=UserEdit&user_id=' . $u['id'] . '">Редактировать</a><a style="margin-left: 15px;" class="btn btn-sm btn-danger" href="/admin?type=UserEdit&user_id=' . $u['id'] . '">Удалить</a></div></td>
|
||||||
|
</tr>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -12,18 +12,27 @@ class SetVisibility
|
||||||
{
|
{
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
|
$priority = 0;
|
||||||
$photo = new Photo($_GET['id']);
|
$photo = new Photo($_GET['id']);
|
||||||
$data = json_decode($photo->i('content'), true);
|
$data = json_decode($photo->i('content'), true);
|
||||||
|
|
||||||
if (!array_key_exists('declineReason', $data)) {
|
if (!array_key_exists('declineReason', $data)) {
|
||||||
$data['declineReason'] = null;
|
$data['declineReason'] = null;
|
||||||
}
|
}
|
||||||
$data['declineReason'] = $_GET['decline_reason'];
|
if ($_POST['comment'] != null) {
|
||||||
|
$data['declineComment'] = $_POST['comment'];
|
||||||
|
}
|
||||||
|
if ($_GET['mod'] != 1) {
|
||||||
|
$data['declineReason'] = $_GET['reason'];
|
||||||
|
} else {
|
||||||
|
$priority = $_GET['reason'];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
$updatedJsonString = json_encode($data);
|
$updatedJsonString = json_encode($data);
|
||||||
|
|
||||||
|
|
||||||
DB::query('UPDATE photos SET moderated=:mod, timeupload=:time, content=:c WHERE id=:id', array(':id'=>$_GET['id'], ':mod'=>$_GET['mod'], ':time'=>time(), ':c'=>$updatedJsonString));
|
DB::query('UPDATE photos SET moderated=:mod, timeupload=:time, priority=:pr, content=:c WHERE id=:id', array(':id'=>$_GET['id'], ':mod'=>$_GET['mod'], ':time'=>time(), ':pr'=>$priority, ':c'=>$updatedJsonString));
|
||||||
$uid = DB::query('SELECT user_id FROM photos WHERE id=:id', array(':id'=>$_GET['id']))[0]['user_id'];
|
$uid = DB::query('SELECT user_id FROM photos WHERE id=:id', array(':id'=>$_GET['id']))[0]['user_id'];
|
||||||
if ($_GET['mod'] === 1) {
|
if ($_GET['mod'] === 1) {
|
||||||
$followers = DB::query('SELECT * FROM followers WHERE user_id=:uid', array(':uid'=>$uid));
|
$followers = DB::query('SELECT * FROM followers WHERE user_id=:uid', array(':uid'=>$uid));
|
||||||
|
|
37
app/Controllers/Api/Admin/Settings/TaskManager.php
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Controllers\Api\Admin\Settings;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
use App\Services\{Auth, Router, GenerateRandomStr, DB, Json, EXIF, TaskScheduler};
|
||||||
|
use App\Models\{User, Vote, Photo};
|
||||||
|
|
||||||
|
|
||||||
|
class TaskManager
|
||||||
|
{
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$task = new TaskScheduler();
|
||||||
|
foreach (NGALLERY_TASKS as $t) {
|
||||||
|
$id = $_GET['id'];
|
||||||
|
if (isset($t['id']) && $t['id'] == $id) {
|
||||||
|
if ($_GET['type'] === 0) {
|
||||||
|
$task->removeTask($t['id'], "php ".$_SERVER['DOCUMENT_ROOT'].$t['handler']);
|
||||||
|
} else {
|
||||||
|
$task->addTask(
|
||||||
|
$t['id'],
|
||||||
|
"php ".$_SERVER['DOCUMENT_ROOT'].$t['handler']." >> ".$_SERVER['DOCUMENT_ROOT'].NGALLERY['root']['logslocation']." 2>&1",
|
||||||
|
"* * * * *"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
echo json_encode(
|
||||||
|
array(
|
||||||
|
'errorcode' => 0,
|
||||||
|
'error' => 0
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
59
app/Controllers/Api/Contests/GetInfo.php
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Controllers\Api\Contests;
|
||||||
|
|
||||||
|
use App\Services\{DB, Json};
|
||||||
|
|
||||||
|
class GetInfo
|
||||||
|
{
|
||||||
|
private array $contest;
|
||||||
|
private string $pretendsStatus;
|
||||||
|
private string $publicStatus;
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->fetchContest();
|
||||||
|
$this->setStatuses();
|
||||||
|
$this->outputJson();
|
||||||
|
}
|
||||||
|
|
||||||
|
private function fetchContest(): void
|
||||||
|
{
|
||||||
|
$statuses = [0, 1, 2];
|
||||||
|
foreach ($statuses as $status) {
|
||||||
|
$contest = DB::query('SELECT * FROM contests WHERE status = :status', [':status' => $status]);
|
||||||
|
if (!empty($contest)) {
|
||||||
|
$this->contest = $contest[0];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function setStatuses(): void
|
||||||
|
{
|
||||||
|
$time = time();
|
||||||
|
$status = $this->contest['status'] ?? null;
|
||||||
|
|
||||||
|
if ($status === 0) {
|
||||||
|
$this->pretendsStatus = ($this->contest['openpretendsdate'] > $time) ? 'waiting' : 'waitingforserver';
|
||||||
|
$this->publicStatus = 'closed';
|
||||||
|
} elseif ($status === 1) {
|
||||||
|
$this->pretendsStatus = ($this->contest['closepretendsdate'] > $time) ? 'opened' : 'waitingforserver';
|
||||||
|
$this->publicStatus = 'closed';
|
||||||
|
} elseif ($status === 2) {
|
||||||
|
$this->pretendsStatus = 'closed';
|
||||||
|
$this->publicStatus = ($this->contest['closedate'] <= $time) ? 'waitingforserver' : 'opened';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function outputJson(): void
|
||||||
|
{
|
||||||
|
echo json_encode(array(
|
||||||
|
'contest' => $this->contest,
|
||||||
|
'statuses' => [
|
||||||
|
'pretends' => $this->pretendsStatus,
|
||||||
|
'public' => $this->publicStatus,
|
||||||
|
]
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
26
app/Controllers/Api/GeoDB/Search.php
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Controllers\Api\GeoDB;
|
||||||
|
|
||||||
|
use App\Services\{Auth, Router, GenerateRandomStr, DB, Json, EXIF, Date};
|
||||||
|
use App\Models\{User, Vote, Photo};
|
||||||
|
|
||||||
|
class Search
|
||||||
|
{
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$query = $_GET['place'];
|
||||||
|
|
||||||
|
if ($query) {
|
||||||
|
$addresses = DB::query('SELECT title FROM geodb WHERE LOWER(title) LIKE LOWER(:query)', array(':query' => "%$query%"));
|
||||||
|
|
||||||
|
$titles = array_map(function($address) {
|
||||||
|
return $address['title'];
|
||||||
|
}, $addresses);
|
||||||
|
|
||||||
|
echo json_encode($titles, JSON_UNESCAPED_UNICODE);
|
||||||
|
} else {
|
||||||
|
echo json_encode(["error" => "No query provided"], JSON_UNESCAPED_UNICODE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,15 +4,15 @@ namespace App\Controllers\Api\Images\Comments;
|
||||||
|
|
||||||
use App\Services\{Auth, Router, GenerateRandomStr, DB, Json, Files, Shell};
|
use App\Services\{Auth, Router, GenerateRandomStr, DB, Json, Files, Shell};
|
||||||
use App\Models\Notification;
|
use App\Models\Notification;
|
||||||
|
use App\Services\Upload as Upload;
|
||||||
class Create
|
class Create
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
|
static $filesrc;
|
||||||
private static function create($content, $id)
|
private static function create($content, $id)
|
||||||
{
|
{
|
||||||
DB::query('INSERT INTO photos_comments VALUES (\'0\', :userid, :postid, :postbody, :time, :content)', array('postid' => $_POST['id'], ':postbody' => $_POST['wtext'], ':userid' => Auth::userid(), ':time' => time(), ':content'=>''));
|
DB::query('INSERT INTO photos_comments VALUES (\'0\', :userid, :postid, :postbody, :time, :content)', array('postid' => $_POST['id'], ':postbody' => $_POST['wtext'], ':userid' => Auth::userid(), ':time' => time(), ':content'=>$content));
|
||||||
}
|
}
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
|
@ -21,15 +21,54 @@ class Create
|
||||||
if ((int)$id === DB::query('SELECT id FROM photos WHERE id=:id', array(':id' => $id))[0]['id']) {
|
if ((int)$id === DB::query('SELECT id FROM photos WHERE id=:id', array(':id' => $id))[0]['id']) {
|
||||||
|
|
||||||
|
|
||||||
$content = Json::return(
|
if ($_FILES['filebody']['error'] != 4) {
|
||||||
array(
|
$finfo = finfo_open(FILEINFO_MIME_TYPE);
|
||||||
'type' => 'none',
|
$mime = finfo_file($finfo, $_FILES['filebody']['tmp_name']);
|
||||||
'by' => 'user'
|
finfo_close($finfo);
|
||||||
)
|
$filename = GenerateRandomStr::gen_uuid();
|
||||||
);
|
if (preg_match('/^image\//', $mime)) {
|
||||||
|
$info = getimagesize($_FILES['filebody']['tmp_name']);
|
||||||
|
|
||||||
if (strlen($postbody) < 4096 || strlen($postbody) > 1) {
|
if ($info['mime'] == 'image/jpeg')
|
||||||
if (trim($postbody) != '') {
|
$image = imagecreatefromjpeg($_FILES['filebody']['tmp_name']);
|
||||||
|
elseif ($info['mime'] == 'image/gif')
|
||||||
|
$image = imagecreatefromgif($_FILES['filebody']['tmp_name']);
|
||||||
|
elseif ($info['mime'] == 'image/png')
|
||||||
|
$image = imagecreatefrompng($_FILES['filebody']['tmp_name']);
|
||||||
|
$type = 'img';
|
||||||
|
$destination = '/cdn/temp/'.$filename.'.jpg';
|
||||||
|
imagejpeg($image, $_SERVER['DOCUMENT_ROOT'].$destination, 60);
|
||||||
|
|
||||||
|
} else if (preg_match('/^audio\//', $mime)) {
|
||||||
|
return "Аудио";
|
||||||
|
} else if (preg_match('/^video\//', $mime)) {
|
||||||
|
if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
|
||||||
|
$ffmpeg = \FFMpeg\FFMpeg::create(array(
|
||||||
|
'ffmpeg.binaries' => $_SERVER['DOCUMENT_ROOT'] . '/app/Controllers/Exec/ffmpeg.exe',
|
||||||
|
'ffprobe.binaries' => $_SERVER['DOCUMENT_ROOT'] . '/app/Controllers/Exec/ffprobe.exe',
|
||||||
|
'timeout' => 3600, // The timeout for the underlying process
|
||||||
|
'ffmpeg.threads' => 12, // The number of threads that FFMpeg should use
|
||||||
|
), $logger);
|
||||||
|
} else {
|
||||||
|
$ffmpeg = \FFMpeg\FFMpeg::create();
|
||||||
|
}
|
||||||
|
$video = $ffmpeg->open($_FILES['filebody']['tmp_name']);
|
||||||
|
$video->save(new \FFMpeg\Format\Video\X264(), $_SERVER['DOCUMENT_ROOT'] . "/cdn/temp/" . $filename . '.mp4');
|
||||||
|
$video->frame(\FFMpeg\Coordinate\TimeCode::fromSeconds(1))->save($_SERVER['DOCUMENT_ROOT'] . "/cdn/temp/VIDPRV_" . $filename . '.jpg');
|
||||||
|
$type = 'video';
|
||||||
|
$destination = '/cdn/temp/'.$filename.'.mp4';
|
||||||
|
$destination_vidprv = '/cdn/temp/VIDPRV'.$filename.'.jpg';
|
||||||
|
} else {
|
||||||
|
return "Неизвестный тип файла";
|
||||||
|
}
|
||||||
|
|
||||||
|
$upload = new Upload($_SERVER['DOCUMENT_ROOT'].$destination, 'cdn/'.$type.'/');
|
||||||
|
self::$filesrc = $upload->getSrc();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if ((strlen($postbody) < 4096 || strlen($postbody) > 1) || $_FILES['filebody']['error'] != 4) {
|
||||||
|
if (trim($postbody) != '' || $_FILES['filebody']['error'] != 4) {
|
||||||
$postbody = ltrim($postbody);
|
$postbody = ltrim($postbody);
|
||||||
echo json_encode(
|
echo json_encode(
|
||||||
array(
|
array(
|
||||||
|
@ -48,17 +87,24 @@ class Create
|
||||||
} else {
|
} else {
|
||||||
die(json_encode(
|
die(json_encode(
|
||||||
array(
|
array(
|
||||||
'errorcode' => '1',
|
'errorcode' => '2',
|
||||||
'error' => 1
|
'error' => 1
|
||||||
)
|
)
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
$content = Json::return(
|
||||||
|
array(
|
||||||
|
'type' => 'none',
|
||||||
|
'by' => 'user',
|
||||||
|
'filetype' => $type,
|
||||||
|
'src' => self::$filesrc
|
||||||
|
)
|
||||||
|
);
|
||||||
self::create($content, $id);
|
self::create($content, $id);
|
||||||
} else {
|
} else {
|
||||||
die(json_encode(
|
die(json_encode(
|
||||||
array(
|
array(
|
||||||
'errorcode' => '1',
|
'errorcode' => '3',
|
||||||
'error' => 1
|
'error' => 1
|
||||||
)
|
)
|
||||||
));
|
));
|
||||||
|
|
|
@ -5,7 +5,7 @@ namespace App\Controllers\Api\Images\Comments;
|
||||||
|
|
||||||
|
|
||||||
use App\Services\{Auth, Router, GenerateRandomStr, DB, Json, EXIF};
|
use App\Services\{Auth, Router, GenerateRandomStr, DB, Json, EXIF};
|
||||||
use App\Models\{User, Vote, Comment};
|
use App\Models\{User, Vote, Comment, Photo};
|
||||||
|
|
||||||
|
|
||||||
class Load
|
class Load
|
||||||
|
@ -13,10 +13,12 @@ class Load
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
|
|
||||||
$comments = DB::query('SELECT * FROM photos_comments WHERE photo_id=:pid', array(':pid' => explode('/', $_SERVER['REQUEST_URI'])[4]));
|
$photo = new Photo(explode('/', $_SERVER['REQUEST_URI'])[4]);
|
||||||
|
$comments = DB::query('SELECT * FROM photos_comments WHERE photo_id=:pid ORDER BY CASE WHEN id = :pinnedid THEN 0 ELSE 1 END, id ASC', array(':pid' => explode('/', $_SERVER['REQUEST_URI'])[4], ':pinnedid' => $photo->i('pinnedcomment_id')));
|
||||||
$number = 1;
|
$number = 1;
|
||||||
foreach ($comments as $c) {
|
foreach ($comments as $c) {
|
||||||
$comm = new Comment($c);
|
$comm = new Comment($c);
|
||||||
|
$photo = new Photo($c['photo_id']);
|
||||||
if ($comm->content('deleted') != 'true') {
|
if ($comm->content('deleted') != 'true') {
|
||||||
if ($number % 2 == 0) {
|
if ($number % 2 == 0) {
|
||||||
$class = 's11';
|
$class = 's11';
|
||||||
|
|
41
app/Controllers/Api/Images/Comments/Pin.php
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Controllers\Api\Images\Comments;
|
||||||
|
|
||||||
|
use App\Services\{Auth, Router, GenerateRandomStr, DB, Json};
|
||||||
|
|
||||||
|
class Pin
|
||||||
|
{
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
|
||||||
|
$postId = explode('/', $_SERVER['REQUEST_URI'])[4];
|
||||||
|
$cpostid = DB::query('SELECT photo_id FROM photos_comments WHERE id=:id', array(':id' => $postId))[0]['photo_id'];
|
||||||
|
if (DB::query('SELECT user_id FROM photos WHERE id=:id', array(':id' => $cpostid))[0]['user_id'] === Auth::userid()) {
|
||||||
|
|
||||||
|
$data = DB::query('SELECT * FROM photos WHERE id=:id', array(':id'=>$cpostid))[0];
|
||||||
|
if ($data['pinnedcomment_id'] === (int)$postId) {
|
||||||
|
DB::query('UPDATE photos SET pinnedcomment_id=0 WHERE id=:id', array(':id'=>$cpostid));
|
||||||
|
echo json_encode(
|
||||||
|
array(
|
||||||
|
'errorcode' => '0',
|
||||||
|
'error' => 0,
|
||||||
|
'action' => 'unpin',
|
||||||
|
)
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
DB::query('UPDATE photos SET pinnedcomment_id=:pid WHERE id=:id', array(':pid'=>$postId, ':id'=>$cpostid));
|
||||||
|
echo json_encode(
|
||||||
|
array(
|
||||||
|
'errorcode' => '0',
|
||||||
|
'error' => 0,
|
||||||
|
'action' => 'pin',
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
46
app/Controllers/Api/Images/Contests/Rate.php
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Controllers\Api\Images\Contests;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
use App\Services\{Auth, Router, GenerateRandomStr, DB, Json, EXIF};
|
||||||
|
use App\Models\{User, Vote, Photo};
|
||||||
|
|
||||||
|
|
||||||
|
class Rate
|
||||||
|
{
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$count = 3;
|
||||||
|
$uservotes = DB::query('SELECT COUNT(*) FROM contests_rates WHERE user_id=:uid AND contest_id=:cid', array(':uid' => Auth::userid(), ':cid' => $_GET['kid']))[0]['COUNT(*)'];
|
||||||
|
$countvotes = $count - $uservotes;
|
||||||
|
$contest = DB::query('SELECT * FROM contests WHERE id=:id', array(":id" => $_GET['kid']))[0];
|
||||||
|
$photo = new Photo($_GET['pid']);
|
||||||
|
if ($contest['status'] != 2) {
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
if ($photo->i('on_contest') != 1 && $photo->i('contest_id') != $_GET['kid']) {
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
if ((int)DB::query('SELECT photo_id FROM contests_rates WHERE photo_id=:pid AND user_id=:uid AND contest_id=:cid', array(':uid' => Auth::userid(), ':pid' => $_GET['pid'], ':cid' => $_GET['kid']))[0]['photo_id'] === (int)$_GET['pid']) {
|
||||||
|
DB::query('DELETE FROM contests_rates WHERE user_id=:uid AND photo_id=:pid AND contest_id=:cid', array(':pid' => $_GET['pid'], ':uid' => Auth::userid(), ':cid' => $_GET['kid']));
|
||||||
|
$status = 0;
|
||||||
|
$newval = $countvotes + 1;
|
||||||
|
} else {
|
||||||
|
$newval = $countvotes - 1;
|
||||||
|
if ($newval >= 0) {
|
||||||
|
DB::query('INSERT INTO contests_rates VALUES (\'0\', :pid, :uid, :cid)', array(':pid' => $_GET['pid'], ':uid' => Auth::userid(), ':cid' => $_GET['kid']));
|
||||||
|
$status = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($newval < 0) {
|
||||||
|
$text = 'Вы можете выбрать максимум 3 фотографии.';
|
||||||
|
} else if ($newval === 0) {
|
||||||
|
$text = 'Вы выбрали 3 фотографии. Спасибо за голосование!';
|
||||||
|
} else {
|
||||||
|
$text = "Вы можете выбрать ещё {$newval} фото.";
|
||||||
|
}
|
||||||
|
echo '[{"' . $_GET['pid'] . '":'.$status.'},"' . $text . '"]';
|
||||||
|
}
|
||||||
|
}
|
34
app/Controllers/Api/Images/Contests/SendPretend.php
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Controllers\Api\Images\Contests;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
use App\Services\{Auth, Router, GenerateRandomStr, DB, Json, EXIF};
|
||||||
|
use App\Models\{User, Vote};
|
||||||
|
|
||||||
|
|
||||||
|
class SendPretend
|
||||||
|
{
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
if (isset($_POST['cid'])) {
|
||||||
|
if (DB::query('SELECT contest_id FROM photos WHERE user_id=:uid', array(':uid' => Auth::userid()))[0]['contest_id'] != $_POST['cid']) {
|
||||||
|
DB::query('UPDATE photos SET on_contest=1, contest_id=:id WHERE id=:idd', array(':id' => $_POST['cid'], ':idd' => $_POST['photo_id']));
|
||||||
|
echo json_encode(
|
||||||
|
array(
|
||||||
|
'errorcode' => 0,
|
||||||
|
'error' => 0
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
echo json_encode(
|
||||||
|
array(
|
||||||
|
'errorcode' => 1,
|
||||||
|
'error' => 0
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -13,7 +13,7 @@ class LoadRecent
|
||||||
$response = [];
|
$response = [];
|
||||||
|
|
||||||
if ($_POST['serverhost'] != 'transphoto.org') {
|
if ($_POST['serverhost'] != 'transphoto.org') {
|
||||||
$photos = DB::query('SELECT * FROM photos WHERE moderated=1 ORDER BY id DESC LIMIT 30');
|
$photos = DB::query('SELECT * FROM photos WHERE moderated=1 AND id<:id ORDER BY id DESC LIMIT 30', array(':id'=>$_GET['lastpid']));
|
||||||
|
|
||||||
|
|
||||||
foreach ($photos as $p) {
|
foreach ($photos as $p) {
|
||||||
|
@ -23,7 +23,7 @@ class LoadRecent
|
||||||
$date = Date::zmdate($p['posted_at']);
|
$date = Date::zmdate($p['posted_at']);
|
||||||
}
|
}
|
||||||
$user = DB::query('SELECT * FROM users WHERE id=:id', array(':id' => $p['user_id']))[0];
|
$user = DB::query('SELECT * FROM users WHERE id=:id', array(':id' => $p['user_id']))[0];
|
||||||
|
$comments = DB::query('SELECT COUNT(*) FROM photos_comments WHERE photo_id=:pid', array(':pid'=>$p['id']))[0]['COUNT(*)'];
|
||||||
$response[] = [
|
$response[] = [
|
||||||
'id' => $p['id'],
|
'id' => $p['id'],
|
||||||
'place' => htmlspecialchars($p['place']),
|
'place' => htmlspecialchars($p['place']),
|
||||||
|
@ -31,7 +31,8 @@ class LoadRecent
|
||||||
'user_name' => $user['username'],
|
'user_name' => $user['username'],
|
||||||
'user_id' => $p['user_id'],
|
'user_id' => $p['user_id'],
|
||||||
'photourl' => $p['photourl'],
|
'photourl' => $p['photourl'],
|
||||||
'photourl_small' => 'https://' . $_SERVER['SERVER_NAME'] . '/api/photo/compress?url=' . $p['photourl']
|
'photourl_small' => 'https://' . $_SERVER['SERVER_NAME'] . '/api/photo/compress?url=' . $p['photourl'],
|
||||||
|
'ccnt' => $comments
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -2,69 +2,103 @@
|
||||||
|
|
||||||
namespace App\Controllers\Api\Images;
|
namespace App\Controllers\Api\Images;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
use App\Services\{Auth, Router, GenerateRandomStr, DB, Json, EXIF};
|
use App\Services\{Auth, Router, GenerateRandomStr, DB, Json, EXIF};
|
||||||
use App\Models\{User, Vote};
|
use App\Models\{User, Vote, VoteContest};
|
||||||
|
|
||||||
|
|
||||||
class Rate
|
class Rate
|
||||||
{
|
{
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
|
|
||||||
if (isset($_GET['vote']) && isset($_GET['pid'])) {
|
if (isset($_GET['vote']) && isset($_GET['pid'])) {
|
||||||
if (Vote::photo(Auth::userid(), $_GET['pid']) === -1) {
|
$userId = Auth::userid();
|
||||||
DB::query('INSERT INTO photos_rates VALUES (\'0\', :id, :pid, :type)', array(':id'=>Auth::userid(), ':pid' => $_GET['pid'], ':type'=>$_GET['vote']));
|
$photoId = $_GET['pid'];
|
||||||
if (Vote::photo(Auth::userid(), $_GET['pid']) != $_GET['vote']) {
|
$voteType = (int) $_GET['vote'];
|
||||||
DB::query('DELETE FROM photos_rates WHERE user_id=:id AND photo_id=:pid AND type=:type', array(':id'=>Auth::userid(), ':pid' => $_GET['pid'], ':type'=>Vote::photo(Auth::userid(), $_GET['pid'])));
|
$contest = (isset($_GET['action']) && $_GET['action'] === 'vote-konk') ? 1 : 0;
|
||||||
}
|
$contestId = $_GET['cid'];
|
||||||
} else if (Vote::photo(Auth::userid(), $_GET['pid']) === (int)$_GET['vote']) {
|
|
||||||
DB::query('DELETE FROM photos_rates WHERE user_id=:id AND photo_id=:pid', array(':id'=>Auth::userid(), ':pid' => $_GET['pid']));
|
|
||||||
} else {
|
|
||||||
DB::query('UPDATE photos_rates SET type=:type WHERE user_id=:id AND photo_id=:pid', array(':id'=>Auth::userid(), ':pid' => $_GET['pid'], ':type'=>$_GET['vote']));
|
|
||||||
|
|
||||||
}
|
|
||||||
$votes = DB::query('SELECT * FROM photos_rates WHERE photo_id=:id ORDER BY id DESC', array(':id' => $_GET['pid']));
|
|
||||||
|
|
||||||
|
if ($contest === 1) {
|
||||||
|
if (VoteContest::photo($userId, $photoId, $contestId) === -1) {
|
||||||
|
DB::query(
|
||||||
|
'INSERT INTO photos_rates_contest (id, user_id, photo_id, type, contest_id) VALUES (NULL, :id, :pid, :type, :cid)',
|
||||||
|
[':id' => $userId, ':pid' => $photoId, ':type' => $voteType, ':cid'=>$contestId]
|
||||||
|
);
|
||||||
|
if (VoteContest::photo($userId, $photoId, $contestId) != $voteType) {
|
||||||
|
DB::query(
|
||||||
|
'DELETE FROM photos_rates_contest WHERE user_id=:id AND photo_id=:pid AND type=:type AND contest_id=:cid',
|
||||||
|
[':id' => $userId, ':pid' => $photoId, ':type' => VoteContest::photo($userId, $photoId, $contestId), ':cid'=>$contestId]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} elseif (VoteContest::photo($userId, $photoId, $contestId) === $voteType) {
|
||||||
|
DB::query(
|
||||||
|
'DELETE FROM photos_rates_contest WHERE user_id=:id AND photo_id=:pid AND contest_id=:cid',
|
||||||
|
[':id' => $userId, ':pid' => $photoId, ':cid'=>$contestId]
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
DB::query(
|
||||||
|
'UPDATE photos_rates_contest SET type=:type WHERE user_id=:id AND photo_id=:pid AND contest_id=:cid',
|
||||||
|
[':id' => $userId, ':pid' => $photoId, ':type' => $voteType, ':cid'=>$contestId]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (Vote::photo($userId, $photoId) === -1) {
|
||||||
|
DB::query(
|
||||||
|
'INSERT INTO photos_rates (id, user_id, photo_id, type, contest) VALUES (NULL, :id, :pid, :type, 0)',
|
||||||
|
[':id' => $userId, ':pid' => $photoId, ':type' => $voteType]
|
||||||
|
);
|
||||||
|
if (Vote::photo($userId, $photoId) != $voteType) {
|
||||||
|
DB::query(
|
||||||
|
'DELETE FROM photos_rates WHERE user_id=:id AND photo_id=:pid AND type=:type AND contest=0',
|
||||||
|
[':id' => $userId, ':pid' => $photoId, ':type' => Vote::photo($userId, $photoId)]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} elseif (Vote::photo($userId, $photoId) === $voteType) {
|
||||||
|
DB::query(
|
||||||
|
'DELETE FROM photos_rates WHERE user_id=:id AND photo_id=:pid AND contest=0',
|
||||||
|
[':id' => $userId, ':pid' => $photoId]
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
DB::query(
|
||||||
|
'UPDATE photos_rates SET type=:type WHERE user_id=:id AND photo_id=:pid AND contest=0',
|
||||||
|
[':id' => $userId, ':pid' => $photoId, ':type' => $voteType]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$votes = DB::query('SELECT * FROM photos_rates WHERE photo_id=:id ORDER BY id DESC', [':id' => $photoId]);
|
||||||
$formattedVotesPos = [];
|
$formattedVotesPos = [];
|
||||||
$formattedVotesNeg = [];
|
$formattedVotesNeg = [];
|
||||||
|
|
||||||
foreach ($votes as $vote) {
|
foreach ($votes as $vote) {
|
||||||
$user = new User($vote['user_id']);
|
$user = new User($vote['user_id']);
|
||||||
if ($vote['type'] === 0) {
|
if ($vote['type'] === 0) {
|
||||||
$type = 0;
|
$formattedVotesNeg[] = [$vote['user_id'], $user->i('username'), 0];
|
||||||
$formattedVotesNeg[] = [$vote['user_id'], $user->i('username'), $type];
|
} elseif ($vote['type'] === 1) {
|
||||||
} else if ($vote['type'] === 1) {
|
$formattedVotesPos[] = [$vote['user_id'], $user->i('username'), 1];
|
||||||
$type = 1;
|
|
||||||
$formattedVotesPos[] = [$vote['user_id'], $user->i('username'), $type];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Vote::photo(Auth::userid(), $_GET['pid']) === 0) {
|
$currentVote = Vote::photo($userId, $photoId);
|
||||||
$negbtn = true;
|
$contCurrentVote = VoteContest::photo($userId, $photoId, $contestId);
|
||||||
$posbtn = false;
|
|
||||||
} else if (Vote::photo(Auth::userid(), $_GET['pid']) === 1) {
|
if ($contest === 0) {
|
||||||
$negbtn = false;
|
$count = Vote::count($photoId);
|
||||||
$posbtn = true;
|
|
||||||
} else {
|
} else {
|
||||||
$negbtn = false;
|
$count = VoteContest::count($photoId, $contestId);
|
||||||
$posbtn = false;
|
|
||||||
}
|
}
|
||||||
$result = [
|
$result = [
|
||||||
'buttons' => [$negbtn, $posbtn],
|
'buttons' => [
|
||||||
|
'negbtn' => $currentVote === 0,
|
||||||
|
'posbtn' => $currentVote === 1,
|
||||||
|
'negbtn_contest' => $contCurrentVote === 0,
|
||||||
|
'posbtn_contest' => $contCurrentVote === 1,
|
||||||
|
],
|
||||||
'errors' => '',
|
'errors' => '',
|
||||||
'rating' => Vote::count($_GET['pid'])
|
'rating' => $count,
|
||||||
|
'votes' => [
|
||||||
|
1 => $formattedVotesPos,
|
||||||
|
0 => $formattedVotesNeg
|
||||||
|
]
|
||||||
];
|
];
|
||||||
$votes = [];
|
|
||||||
$votes[1] = $formattedVotesPos;
|
|
||||||
$votes[0] = $formattedVotesNeg;
|
|
||||||
|
|
||||||
if (!empty($votes)) {
|
|
||||||
$result['votes'] = $votes;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
header('Content-Type: application/json');
|
header('Content-Type: application/json');
|
||||||
echo json_encode($result, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
|
echo json_encode($result, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
|
||||||
|
|
|
@ -37,7 +37,7 @@ class Upload
|
||||||
} else {
|
} else {
|
||||||
$moderated = 1;
|
$moderated = 1;
|
||||||
}
|
}
|
||||||
DB::query('INSERT INTO photos VALUES (\'0\', :userid, :postbody, :photourl, :time, :timeup, :exif, 0, :moderated, :place, 0, :gallery, :entityid, :content)', array(':postbody' => $postbody, ':userid' => Auth::userid(), ':time' => mktime(0, 0, 0, $_POST['month'], $_POST['day'], $_POST['year']), ':content' => $content, ':photourl' => self::$photourl, ':exif' => $exif, ':place' => $_POST['place'], ':timeup' => time(), ':moderated' => $moderated, ':gallery'=>$_POST['gallery'], ':entityid'=>self::$entitydata_id));
|
DB::query('INSERT INTO photos VALUES (\'0\', :userid, :postbody, :photourl, :time, :timeup, :exif, 0, :moderated, :place, 0, :gallery, :entityid, 0, 0, 0, :content)', array(':postbody' => $postbody, ':userid' => Auth::userid(), ':time' => mktime(0, 0, 0, $_POST['month'], $_POST['day'], $_POST['year']), ':content' => $content, ':photourl' => self::$photourl, ':exif' => $exif, ':place' => $_POST['place'], ':timeup' => time(), ':moderated' => $moderated, ':gallery'=>$_POST['gallery'], ':entityid'=>self::$entitydata_id));
|
||||||
if (($moderated === 1) && (self::$subsnotify != 'disabled')) {
|
if (($moderated === 1) && (self::$subsnotify != 'disabled')) {
|
||||||
$followers = DB::query('SELECT * FROM followers WHERE user_id=:uid', array(':uid' => Auth::userid()));
|
$followers = DB::query('SELECT * FROM followers WHERE user_id=:uid', array(':uid' => Auth::userid()));
|
||||||
foreach ($followers as $f) {
|
foreach ($followers as $f) {
|
||||||
|
|
|
@ -7,7 +7,9 @@ use \App\Controllers\ExceptionRegister;
|
||||||
use \App\Core\Page;
|
use \App\Core\Page;
|
||||||
|
|
||||||
use donatj\UserAgent\UserAgentParser;
|
use donatj\UserAgent\UserAgentParser;
|
||||||
|
use PHPMailer\PHPMailer\PHPMailer;
|
||||||
|
use PHPMailer\PHPMailer\Exception;
|
||||||
|
use Beeyev\DisposableEmailFilter\DisposableEmailFilter;
|
||||||
|
|
||||||
class Register
|
class Register
|
||||||
{
|
{
|
||||||
|
@ -294,6 +296,7 @@ class Register
|
||||||
$password = $_POST['password'];
|
$password = $_POST['password'];
|
||||||
$email = $_POST['email'];
|
$email = $_POST['email'];
|
||||||
$forbusernames = explode(',', NGALLERY['root']['registration']['prohibited_usernames']);
|
$forbusernames = explode(',', NGALLERY['root']['registration']['prohibited_usernames']);
|
||||||
|
$status = 0;
|
||||||
if (!self::checkforb($_POST['username'], $forbusernames)) {
|
if (!self::checkforb($_POST['username'], $forbusernames)) {
|
||||||
|
|
||||||
if (!strcasecmp(DB::query('SELECT username FROM users WHERE (LOWER(username) LIKE :username)', array(':username' => '%' . $username . '%'))[0]['username'], $username) === false) {
|
if (!strcasecmp(DB::query('SELECT username FROM users WHERE (LOWER(username) LIKE :username)', array(':username' => '%' . $username . '%'))[0]['username'], $username) === false) {
|
||||||
|
@ -315,11 +318,107 @@ class Register
|
||||||
'regdate' => time()
|
'regdate' => time()
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
if (NGALLERY['root']['registration']['emailverify'] === true) {
|
||||||
DB::query('INSERT INTO users VALUES (\'0\', :username, :email, :password, :photourl, 5, :online, 0, 0, :content)', array(':username' => ltrim($username), ':password' => password_hash(ltrim($password), PASSWORD_BCRYPT), ':photourl' => '/static/img/avatar.png', ':email' => $email, ':content' => $content, ':online' => time()));
|
$status === 3;
|
||||||
$cstrong = True;
|
}
|
||||||
$token = GenerateRandomStr::gen_uuid();
|
$token = GenerateRandomStr::gen_uuid();
|
||||||
|
DB::query('INSERT INTO users VALUES (\'0\', :username, :email, :password, :photourl, 5, :online, 0, :status, :content)', array(':username' => ltrim($username), ':password' => password_hash(ltrim($password), PASSWORD_BCRYPT), ':photourl' => '/static/img/avatar.png', ':email' => $email, ':content' => $content, ':online' => time(), ':status'=>$status));
|
||||||
$user_id = DB::query('SELECT id FROM users WHERE username=:username', array(':username' => $username))[0]['id'];
|
$user_id = DB::query('SELECT id FROM users WHERE username=:username', array(':username' => $username))[0]['id'];
|
||||||
|
if (NGALLERY['root']['registration']['emailverify'] === true) {
|
||||||
|
$disposableEmailFilter = new DisposableEmailFilter();
|
||||||
|
if ($disposableEmailFilter->isDisposableEmailAddress($_POST['email'])) {
|
||||||
|
echo json_encode(
|
||||||
|
array(
|
||||||
|
'errorcode' => '9',
|
||||||
|
'errortitle' => 'Почта запрещена для регистрации',
|
||||||
|
'error' => 1
|
||||||
|
)
|
||||||
|
);
|
||||||
|
die();
|
||||||
|
}
|
||||||
|
$key = GenerateRandomStr::gen_uuid();
|
||||||
|
$content = Json::return(
|
||||||
|
array(
|
||||||
|
'user_id' => $user_id
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$mail = new PHPMailer(true);
|
||||||
|
DB::query('INSERT INTO servicekeys VALUES (\'0\', :token, :type, 1, :content)', array(':token'=>$key, ':type'=>'EMAILVERIFY', ':content'=>$content));
|
||||||
|
try {
|
||||||
|
$mail->isSMTP();
|
||||||
|
$mail->Host = NGALLERY['root']['email']['credentials']['host'];
|
||||||
|
$mail->SMTPAuth = true;
|
||||||
|
$mail->CharSet = "UTF-8";
|
||||||
|
$mail->Username = NGALLERY['root']['email']['credentials']['username'];
|
||||||
|
$mail->Password = NGALLERY['root']['email']['credentials']['password'];
|
||||||
|
$mail->SMTPSecure = PHPMailer::ENCRYPTION_SMTPS;
|
||||||
|
$mail->Port = NGALLERY['root']['email']['credentials']['port'];
|
||||||
|
|
||||||
|
$mail->setFrom(NGALLERY['root']['email']['from']['address'], NGALLERY['root']['title']);
|
||||||
|
$mail->addAddress($_POST['email']);
|
||||||
|
|
||||||
|
$mail->isHTML(true);
|
||||||
|
$mail->Subject = 'Подтверждение регистрации | '.NGALLERY['root']['title'];
|
||||||
|
|
||||||
|
$mail->Body = '
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="ru">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
font-family: Arial, sans-serif;
|
||||||
|
background-color: #f4f4f4;
|
||||||
|
margin: 0;
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
.container {
|
||||||
|
background-color: #ffffff;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
|
||||||
|
padding: 20px;
|
||||||
|
max-width: 600px;
|
||||||
|
margin: auto;
|
||||||
|
}
|
||||||
|
h1 {
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
.code {
|
||||||
|
font-size: 24px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #007bff;
|
||||||
|
margin: 20px 0;
|
||||||
|
}
|
||||||
|
.footer {
|
||||||
|
margin-top: 20px;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #777;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="container">
|
||||||
|
<h1>Подтверждение регистрации</h1>
|
||||||
|
<p>Это письмо было отправлено на ваш почтовый ящик, так как оно было указано при регистрации на '.NGALLERY['root']['title'].' ('.$_SERVER['HTTP_HOST'].')<br>Если вы его не запрашивали, проигнорируйте его.</p><br><br>Ссылка для подтверждения адреса: <a href="https://'.$_SERVER['HTTP_HOST'].'/api/users/emailverify?token='.$key.'">https://'.$_SERVER['HTTP_HOST'].'/api/users/emailverify?token='.$key.'</a>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>';
|
||||||
|
|
||||||
|
|
||||||
|
$mail->send();
|
||||||
|
} catch (Exception $e) {
|
||||||
|
echo json_encode(
|
||||||
|
array(
|
||||||
|
'errorcode' => '8',
|
||||||
|
'errortitle' => 'Не удалось отправить письмо: '.$mail->ErrorInfo,
|
||||||
|
'error' => 1,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
die();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
|
if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
|
||||||
$ip = $_SERVER['HTTP_CLIENT_IP'];
|
$ip = $_SERVER['HTTP_CLIENT_IP'];
|
||||||
|
@ -328,19 +427,11 @@ class Register
|
||||||
} else {
|
} else {
|
||||||
$ip = $_SERVER['REMOTE_ADDR'];
|
$ip = $_SERVER['REMOTE_ADDR'];
|
||||||
}
|
}
|
||||||
|
|
||||||
$parser = new UserAgentParser();
|
|
||||||
|
|
||||||
$ua = $parser->parse();
|
|
||||||
$ua = $parser();
|
|
||||||
|
|
||||||
$servicekey = GenerateRandomStr::gen_uuid();
|
|
||||||
$url = 'http://ip-api.com/json/' . $ip;
|
$url = 'http://ip-api.com/json/' . $ip;
|
||||||
|
|
||||||
$response = file_get_contents($url);
|
$response = file_get_contents($url);
|
||||||
|
|
||||||
$data = json_decode($response, true);
|
$data = json_decode($response, true);
|
||||||
$loc = $data['country'] . ', ' . $data['city'];
|
|
||||||
DB::query('INSERT INTO login_tokens VALUES (\'0\', :token, :user_id)', array(
|
DB::query('INSERT INTO login_tokens VALUES (\'0\', :token, :user_id)', array(
|
||||||
':token' => $token,
|
':token' => $token,
|
||||||
':user_id' => $user_id,
|
':user_id' => $user_id,
|
||||||
|
@ -350,7 +441,6 @@ class Register
|
||||||
setcookie("NGALLERYSESS", $token, time() + 120 * 180 * 240 * 720, '/', NULL, NULL, TRUE);
|
setcookie("NGALLERYSESS", $token, time() + 120 * 180 * 240 * 720, '/', NULL, NULL, TRUE);
|
||||||
setcookie("NGALLERYSESS_", '1', time() + 120 * 180 * 240 * 360, '/', NULL, NULL, TRUE);
|
setcookie("NGALLERYSESS_", '1', time() + 120 * 180 * 240 * 360, '/', NULL, NULL, TRUE);
|
||||||
setcookie("NGALLERYID", $user_id, time() + 10 * 10 * 24 * 72, '/', NULL, NULL, TRUE);
|
setcookie("NGALLERYID", $user_id, time() + 10 * 10 * 24 * 72, '/', NULL, NULL, TRUE);
|
||||||
|
|
||||||
echo json_encode(
|
echo json_encode(
|
||||||
array(
|
array(
|
||||||
'errorcode' => '0',
|
'errorcode' => '0',
|
||||||
|
|
25
app/Controllers/Api/Users/EmailVerify.php
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Controllers\Api\Users;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
use App\Services\{Auth, Router, GenerateRandomStr, DB, Json, EXIF};
|
||||||
|
use App\Models\{User, Vote};
|
||||||
|
use \App\Core\Page;
|
||||||
|
|
||||||
|
class EmailVerify
|
||||||
|
{
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
if (isset($_GET['token'])) {
|
||||||
|
$data = DB::query('SELECT * FROM servicekeys WHERE token=:token AND type="EMAILVERIFY"', array(':token'=>$_GET['token']))[0];
|
||||||
|
$user_id = json_decode($data['content'], true)['user_id'];
|
||||||
|
if ($data['status'] != 0) {
|
||||||
|
DB::query('UPDATE users SET status=0 WHERE id=:id', [':id' => $user_id]);
|
||||||
|
DB::query('UPDATE servicekeys SET status=0 WHERE token=:id', [':id' => $_GET['token']]);
|
||||||
|
Page::set('System/EmailVerify');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -16,15 +16,28 @@ use \App\Controllers\Api\Images\Stats as PhotoStats;
|
||||||
use \App\Controllers\Api\Images\Comments\Create as PhotoComment;
|
use \App\Controllers\Api\Images\Comments\Create as PhotoComment;
|
||||||
use \App\Controllers\Api\Images\Comments\Edit as PhotoCommentEdit;
|
use \App\Controllers\Api\Images\Comments\Edit as PhotoCommentEdit;
|
||||||
use \App\Controllers\Api\Images\Comments\Delete as PhotoCommentDelete;
|
use \App\Controllers\Api\Images\Comments\Delete as PhotoCommentDelete;
|
||||||
|
use \App\Controllers\Api\Images\Comments\Pin as PhotoCommentPin;
|
||||||
use \App\Controllers\Api\Images\Comments\Load as PhotoCommentLoad;
|
use \App\Controllers\Api\Images\Comments\Load as PhotoCommentLoad;
|
||||||
use \App\Controllers\Api\Images\Comments\Rate as PhotoCommentVote;
|
use \App\Controllers\Api\Images\Comments\Rate as PhotoCommentVote;
|
||||||
|
use \App\Controllers\Api\Images\Contests\SendPretend as PhotoContestsSendPretend;
|
||||||
|
use \App\Controllers\Api\Images\Contests\Rate as PhotoContestsRate;
|
||||||
|
use \App\Controllers\Api\Contests\GetInfo as ContestsGetInfo;
|
||||||
|
use \App\Controllers\Api\GeoDB\Search as GeoDBSearch;
|
||||||
use \App\Controllers\Api\Vehicles\Load as VehiclesLoad;
|
use \App\Controllers\Api\Vehicles\Load as VehiclesLoad;
|
||||||
use \App\Controllers\Api\Profile\Update as ProfileUpdate;
|
use \App\Controllers\Api\Profile\Update as ProfileUpdate;
|
||||||
use \App\Controllers\Api\Users\LoadUser as UserLoad;
|
use \App\Controllers\Api\Users\LoadUser as UserLoad;
|
||||||
|
use \App\Controllers\Api\Users\EmailVerify as EmailVerify;
|
||||||
use \App\Controllers\Api\Admin\Images\SetVisibility as AdminPhotoSetVisibility;
|
use \App\Controllers\Api\Admin\Images\SetVisibility as AdminPhotoSetVisibility;
|
||||||
use \App\Controllers\Api\Admin\CreateNews as AdminCreateNews;
|
use \App\Controllers\Api\Admin\CreateNews as AdminCreateNews;
|
||||||
use \App\Controllers\Api\Admin\LoadNews as AdminLoadNews;
|
use \App\Controllers\Api\Admin\LoadNews as AdminLoadNews;
|
||||||
use \App\Controllers\Api\Admin\GetVehicleInputs as AdminGetVehicleInputs;
|
use \App\Controllers\Api\Admin\GetVehicleInputs as AdminGetVehicleInputs;
|
||||||
|
use \App\Controllers\Api\Admin\GeoDB\Create as AdminGeoDBCreate;
|
||||||
|
use \App\Controllers\Api\Admin\GeoDB\Load as AdminGeoDBLoad;
|
||||||
|
use \App\Controllers\Api\Admin\GeoDB\Delete as AdminGeoDBDelete;
|
||||||
|
use \App\Controllers\Api\Admin\Contests\CreateTheme as AdminContestsCreateTheme;
|
||||||
|
use \App\Controllers\Api\Admin\Contests\Create as AdminContestsCreate;
|
||||||
|
use \App\Controllers\Api\Admin\Settings\TaskManager as AdminTaskManager;
|
||||||
|
|
||||||
class ApiController
|
class ApiController
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -38,9 +51,15 @@ class ApiController
|
||||||
public static function upload() {
|
public static function upload() {
|
||||||
return new Upload();
|
return new Upload();
|
||||||
}
|
}
|
||||||
|
public static function emailverify() {
|
||||||
|
return new EmailVerify();
|
||||||
|
}
|
||||||
public static function photovote() {
|
public static function photovote() {
|
||||||
return new PhotoVote();
|
return new PhotoVote();
|
||||||
}
|
}
|
||||||
|
public static function photovotecontest() {
|
||||||
|
return new PhotoContestsRate();
|
||||||
|
}
|
||||||
public static function photofavorite() {
|
public static function photofavorite() {
|
||||||
return new PhotoFavorite();
|
return new PhotoFavorite();
|
||||||
}
|
}
|
||||||
|
@ -53,6 +72,9 @@ class ApiController
|
||||||
public static function photocommentdelete() {
|
public static function photocommentdelete() {
|
||||||
return new PhotoCommentDelete();
|
return new PhotoCommentDelete();
|
||||||
}
|
}
|
||||||
|
public static function photocommentpin() {
|
||||||
|
return new PhotoCommentPin();
|
||||||
|
}
|
||||||
public static function photocommentvote() {
|
public static function photocommentvote() {
|
||||||
return new PhotoCommentVote();
|
return new PhotoCommentVote();
|
||||||
}
|
}
|
||||||
|
@ -65,6 +87,9 @@ class ApiController
|
||||||
public static function photocompress() {
|
public static function photocompress() {
|
||||||
return new PhotoCompress();
|
return new PhotoCompress();
|
||||||
}
|
}
|
||||||
|
public static function geodbsearch() {
|
||||||
|
return new GeoDBSearch();
|
||||||
|
}
|
||||||
public static function adminsetvis() {
|
public static function adminsetvis() {
|
||||||
return new AdminPhotoSetVisibility();
|
return new AdminPhotoSetVisibility();
|
||||||
}
|
}
|
||||||
|
@ -77,6 +102,9 @@ class ApiController
|
||||||
public static function recentphotos() {
|
public static function recentphotos() {
|
||||||
return new PhotoLoadRecent();
|
return new PhotoLoadRecent();
|
||||||
}
|
}
|
||||||
|
public static function sendpretendphoto() {
|
||||||
|
return new PhotoContestsSendPretend();
|
||||||
|
}
|
||||||
public static function loaduser() {
|
public static function loaduser() {
|
||||||
return new UserLoad();
|
return new UserLoad();
|
||||||
}
|
}
|
||||||
|
@ -92,9 +120,30 @@ class ApiController
|
||||||
public static function admingetvehicleinputs() {
|
public static function admingetvehicleinputs() {
|
||||||
return new AdminGetVehicleInputs();
|
return new AdminGetVehicleInputs();
|
||||||
}
|
}
|
||||||
|
public static function admincontestscreatetheme() {
|
||||||
|
return new AdminContestsCreateTheme();
|
||||||
|
}
|
||||||
|
public static function admincontestscreate() {
|
||||||
|
return new AdminContestsCreate();
|
||||||
|
}
|
||||||
|
public static function admingeodbcreate() {
|
||||||
|
return new AdminGeoDBCreate();
|
||||||
|
}
|
||||||
|
public static function admingeodbload() {
|
||||||
|
return new AdminGeoDBLoad();
|
||||||
|
}
|
||||||
|
public static function admingeodbdelete() {
|
||||||
|
return new AdminGeoDBDelete();
|
||||||
|
}
|
||||||
|
public static function admintaskmanager() {
|
||||||
|
return new AdminTaskManager();
|
||||||
|
}
|
||||||
public static function vehiclesload() {
|
public static function vehiclesload() {
|
||||||
return new VehiclesLoad();
|
return new VehiclesLoad();
|
||||||
}
|
}
|
||||||
|
public static function contestsgetinfo() {
|
||||||
|
return new ContestsGetInfo();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
31
app/Controllers/ContestsController.php
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
<?php
|
||||||
|
namespace App\Controllers;
|
||||||
|
|
||||||
|
use \App\Services\{Router, Auth, DB, Json};
|
||||||
|
use \App\Controllers\ExceptionRegister;
|
||||||
|
use \App\Core\Page;
|
||||||
|
|
||||||
|
class ContestsController
|
||||||
|
{
|
||||||
|
public static function results()
|
||||||
|
{
|
||||||
|
Page::set('Contests/VotingResults');
|
||||||
|
|
||||||
|
}
|
||||||
|
public static function index()
|
||||||
|
{
|
||||||
|
Page::set('Contests/VotingIndex');
|
||||||
|
|
||||||
|
}
|
||||||
|
public static function waiting()
|
||||||
|
{
|
||||||
|
Page::set('Contests/VotingWaiting');
|
||||||
|
|
||||||
|
}
|
||||||
|
public static function sendpretend()
|
||||||
|
{
|
||||||
|
Page::set('Contests/VotingSendPretend');
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
27
app/Controllers/Exec/RenderVideo.ps1
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
|
||||||
|
$tempfile = $args[0]
|
||||||
|
$weburl = $args[1]
|
||||||
|
$id = $args[2]
|
||||||
|
|
||||||
|
#$tempfile = 'G:\video.mp4'
|
||||||
|
#$weburl = 'kandle.loc'
|
||||||
|
#$id = '40'
|
||||||
|
|
||||||
|
$hash = -join (((48..57)+(65..90)+(97..122)) * 80 |Get-Random -Count 32 |%{[char]$_})
|
||||||
|
$hashT = -join (((48..57)+(65..90)+(97..122)) * 80 |Get-Random -Count 222 |%{[char]$_})
|
||||||
|
$temp = [System.IO.Path]::GetTempFileName()
|
||||||
|
|
||||||
|
$shell = Get-WmiObject Win32_process -filter "ProcessId = $PID"
|
||||||
|
$shell.SetPriority(16384)
|
||||||
|
|
||||||
|
Copy-Item $tempfile E:\$hash
|
||||||
|
|
||||||
|
E:\Maksim\kandle\app\Controllers\Video\Exec\ffmpeg.exe -i E:\$hash -c:v libx264 -q:v 7 -c:a libmp3lame -q:a 4 -tune zerolatency -y C:\kandletemp\$hashT.mp4
|
||||||
|
|
||||||
|
$uri = 'http://'+$weburl+'/api/video/exec/upload?file=C:\kandletemp\'+$hashT+'.mp4&videoid='+$id
|
||||||
|
|
||||||
|
Invoke-WebRequest -Uri $uri
|
||||||
|
|
||||||
|
Remove-Item C:\kandletemp\$hashT.mp4
|
||||||
|
|
||||||
|
|
14
app/Controllers/Exec/RenderVideo.sh
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
tmpfile="$RANDOM-$(date +%s%N)"
|
||||||
|
copyfile="$0"
|
||||||
|
weburl="$1"
|
||||||
|
videoid="$2"
|
||||||
|
|
||||||
|
#copyfile='/var/www/fastuser/data/www/kandle.cats.ovh/video.mp4'
|
||||||
|
#weburl='kandle.loc'
|
||||||
|
#videoid='1'
|
||||||
|
|
||||||
|
cp $1 "/tmp/vid_$tmpfile.bin"
|
||||||
|
|
||||||
|
nice -n 20 ffmpeg -i "/tmp/vid_$tmpfile.bin" -c:v libx264 -q:v 7 -c:a libmp3lame -q:a 4 -tune zerolatency -y "$4/cdn/temp/ffmOi$tmpfile.mp4"
|
||||||
|
|
||||||
|
curl "http://$2/api/video/exec/upload?file=$4/cdn/temp/ffmOi$tmpfile.mp4&videoid=$3"
|
186
app/Controllers/Exec/Tasks/ExecContests.php
Normal file
|
@ -0,0 +1,186 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Controllers\Exec\Tasks;
|
||||||
|
require_once __DIR__ . '/../../../../vendor/autoload.php';
|
||||||
|
use Symfony\Component\Yaml\Yaml;
|
||||||
|
define("NGALLERY", Yaml::parse(file_get_contents(__DIR__ . '/../../../../ngallery.yaml'))['ngallery']);
|
||||||
|
use App\Services\{Router, Auth, DB, Json, Date};
|
||||||
|
use App\Controllers\ExceptionRegister;
|
||||||
|
use App\Core\Page;
|
||||||
|
|
||||||
|
class ExecContests
|
||||||
|
{
|
||||||
|
public static function run()
|
||||||
|
{
|
||||||
|
if (NGALLERY['root']['contests']['enabled'] != true) {
|
||||||
|
echo "Contests on this server disabled. Skip...";
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
$contests = DB::query('SELECT * FROM contests WHERE status < 3');
|
||||||
|
foreach ($contests as $contest) {
|
||||||
|
self::processContest($contest);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function processContest(array $contest)
|
||||||
|
{
|
||||||
|
echo "Checking contest ID {$contest['id']}\n";
|
||||||
|
|
||||||
|
switch ($contest['status']) {
|
||||||
|
case 0:
|
||||||
|
self::handleOpenPretends($contest);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
self::handleClosePretends($contest);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
self::handleClosingContest($contest);
|
||||||
|
break;
|
||||||
|
case 02:
|
||||||
|
self::handleClosePretendsByTime($contest);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function handleOpenPretends(array $contest)
|
||||||
|
{
|
||||||
|
if (self::isAnotherContestInStatus(1)) {
|
||||||
|
echo "[{$contest['id']}] Waiting for another contest to complete dialing. Skip...\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($contest['openpretendsdate'] <= time()) {
|
||||||
|
DB::query('UPDATE contests SET status = 1 WHERE id = :id', [':id' => $contest['id']]);
|
||||||
|
echo "[{$contest['id']}] Opened for pretends.\n";
|
||||||
|
} else {
|
||||||
|
echo "[{$contest['id']}] Not ready for open pretends. Skip...\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function handleClosePretends(array $contest)
|
||||||
|
{
|
||||||
|
if (self::isAnotherContestInStatus(2) || self::isAnotherContestInStatus(02)) {
|
||||||
|
echo "[{$contest['id']}] Waiting for another contest to end. Skip...\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($contest['closepretendsdate'] <= time()) {
|
||||||
|
DB::query('UPDATE photos SET on_contest=2 WHERE on_contest=1 AND contest_id=:id', array(':id'=>$contest['id']));
|
||||||
|
if ($contest['opendate'] <= time()) {
|
||||||
|
DB::query('UPDATE contests SET status = 2 WHERE id = :id', [':id' => $contest['id']]);
|
||||||
|
echo "[{$contest['id']}] Opened.\n";
|
||||||
|
} else {
|
||||||
|
DB::query('UPDATE contests SET status = 02 WHERE id = :id', [':id' => $contest['id']]);
|
||||||
|
}
|
||||||
|
echo "[{$contest['id']}] Closed for pretends.\n";
|
||||||
|
} else {
|
||||||
|
echo "[{$contest['id']}] Not closed for pretends. Skip...\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function handleClosePretendsByTime(array $contest)
|
||||||
|
{
|
||||||
|
echo "[{$contest['id']}] Cheking for Open by time...\n";
|
||||||
|
if ($contest['opendate'] <= time()) {
|
||||||
|
DB::query('UPDATE contests SET status = 2 WHERE id = :id', [':id' => $contest['id']]);
|
||||||
|
echo "[{$contest['id']}] .\n";
|
||||||
|
} else {
|
||||||
|
echo "[{$contest['id']}] not opened by time. Skip...\n";
|
||||||
|
}
|
||||||
|
echo "[{$contest['id']}] Opened.\n";
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function handleClosingContest(array $contest)
|
||||||
|
{
|
||||||
|
if ($contest['closedate'] > time()) {
|
||||||
|
echo "[{$contest['id']}] Waiting for end time. Skip...\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "[{$contest['id']}] Ready for closing!\n";
|
||||||
|
self::processVotes($contest);
|
||||||
|
DB::query('UPDATE contests SET status = 3 WHERE id = :id', [':id' => $contest['id']]);
|
||||||
|
DB::query('UPDATE photos SET contest_id = 0, on_contest = 0 WHERE contest_id = :id', [':id' => $contest['id']]);
|
||||||
|
echo "[{$contest['id']}] Closed.\n";
|
||||||
|
if (NGALLERY['root']['contests']['autonew']['enabled'] === true) {
|
||||||
|
echo "Creating new contest...";
|
||||||
|
$theme = DB::query('SELECT * FROM contests_themes WHERE status=1 ORDER BY RAND() LIMIT 1')[0];
|
||||||
|
if (count($theme) <= 0) {
|
||||||
|
echo "Not found themes for autocreating Contest. Skip...\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$time = time();
|
||||||
|
if (NGALLERY['root']['contests']['autonew']['times']['pretendsopen'] === 'now') {
|
||||||
|
$pretendsopen = $time;
|
||||||
|
$status = 1;
|
||||||
|
} else {
|
||||||
|
$status = 0;
|
||||||
|
$pretendsopen = Date::addTime(NGALLERY['root']['contests']['autonew']['times']['pretendsopen']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$pretendsclose = Date::addTime(NGALLERY['root']['contests']['autonew']['times']['pretendsclose']);
|
||||||
|
if (NGALLERY['root']['contests']['autonew']['times']['open'] === 'now') {
|
||||||
|
$contestopen = $pretendsclose;
|
||||||
|
} else {
|
||||||
|
$contestopen = Date::addTime(NGALLERY['root']['contests']['autonew']['times']['open']);
|
||||||
|
}
|
||||||
|
$contestclose = Date::addTime(NGALLERY['root']['contests']['autonew']['times']['close']);
|
||||||
|
DB::query('INSERT INTO contests VALUES (\'0\', :themeid, :openprdate, :closeprdate, :opendate, :closedate, :status)', array(':themeid'=>$theme['id'], ':openprdate'=>$pretendsopen, ':closeprdate'=>$pretendsclose, ':opendate'=>$contestopen, ':closedate'=>$contestclose, ':status'=>$status));
|
||||||
|
echo "Contest created! Continue...";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function processVotes(array $contest)
|
||||||
|
{
|
||||||
|
$votes = DB::query(
|
||||||
|
'SELECT user_id, photo_id, COUNT(*) AS vote_count
|
||||||
|
FROM contests_rates WHERE contest_id = :id
|
||||||
|
GROUP BY user_id ORDER BY vote_count DESC LIMIT 10',
|
||||||
|
[':id' => $contest['id']]
|
||||||
|
);
|
||||||
|
|
||||||
|
$place = 1;
|
||||||
|
foreach ($votes as $vote) {
|
||||||
|
self::updatePhotoContent($vote, $contest, $place);
|
||||||
|
$place++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function updatePhotoContent(array $vote, array $contest, int $place)
|
||||||
|
{
|
||||||
|
$photo = DB::query('SELECT * FROM photos WHERE id = :id', [':id' => $vote['photo_id']])[0];
|
||||||
|
$photoData = json_decode($photo['content'], true);
|
||||||
|
|
||||||
|
if (!isset($photoData['contests']) || !is_array($photoData['contests'])) {
|
||||||
|
$photoData['contests'] = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
$theme = DB::query('SELECT title FROM contests_themes WHERE id = :id', [':id' => $contest['themeid']])[0]['title'];
|
||||||
|
|
||||||
|
$photoData['contests'][] = [
|
||||||
|
'id' => $contest['id'],
|
||||||
|
'contesttheme' => $theme,
|
||||||
|
'votenum' => $vote['vote_count'],
|
||||||
|
'place' => $place
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
DB::query('INSERT INTO contests_winners VALUES (\'0\', :photo_id, :place, :contest_id, :date)', array(':photo_id'=>$vote['photo_id'], ':place'=>$place, ':contest_id'=>$contest['id'], ':date'=>time()));
|
||||||
|
|
||||||
|
DB::query('UPDATE photos SET content = :content, on_contest=0, contest_id=0 WHERE id = :id', [
|
||||||
|
':id' => $vote['photo_id'],
|
||||||
|
':content' => json_encode($photoData, JSON_UNESCAPED_UNICODE)
|
||||||
|
]);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function isAnotherContestInStatus(int $status): bool
|
||||||
|
{
|
||||||
|
return !empty(DB::query('SELECT status FROM contests WHERE status = :status', [':status' => $status]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (php_sapi_name() === 'cli') {
|
||||||
|
ExecContests::run();
|
||||||
|
}
|
4
app/Controllers/Exec/Tasks/ngallery-tasks.yaml
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
tasks:
|
||||||
|
- id: "ExecContests"
|
||||||
|
type: "cron"
|
||||||
|
handler: "/app/Controllers/Exec/Tasks/ExecContests.php"
|
BIN
app/Controllers/Exec/ffmpeg.exe
Normal file
BIN
app/Controllers/Exec/ffprobe.exe
Normal file
|
@ -16,6 +16,11 @@ class MainController
|
||||||
{
|
{
|
||||||
Page::set('Main');
|
Page::set('Main');
|
||||||
|
|
||||||
|
}
|
||||||
|
public static function page()
|
||||||
|
{
|
||||||
|
Page::set('Page');
|
||||||
|
|
||||||
}
|
}
|
||||||
public static function about()
|
public static function about()
|
||||||
{
|
{
|
||||||
|
@ -47,11 +52,6 @@ class MainController
|
||||||
{
|
{
|
||||||
Page::set('Top30');
|
Page::set('Top30');
|
||||||
|
|
||||||
}
|
|
||||||
public static function vehicle()
|
|
||||||
{
|
|
||||||
Page::set('Vehicle');
|
|
||||||
|
|
||||||
}
|
}
|
||||||
public static function feed()
|
public static function feed()
|
||||||
{
|
{
|
||||||
|
@ -72,6 +72,21 @@ class MainController
|
||||||
{
|
{
|
||||||
Page::set('FavAuthors');
|
Page::set('FavAuthors');
|
||||||
|
|
||||||
|
}
|
||||||
|
public static function emailverify()
|
||||||
|
{
|
||||||
|
Page::set('Errors/EmailVerify');
|
||||||
|
|
||||||
|
}
|
||||||
|
public static function comments()
|
||||||
|
{
|
||||||
|
Page::set('Comments/Index');
|
||||||
|
|
||||||
|
}
|
||||||
|
public static function tour()
|
||||||
|
{
|
||||||
|
Page::set('Tour');
|
||||||
|
|
||||||
}
|
}
|
||||||
public static function robots() {
|
public static function robots() {
|
||||||
echo 'User-Agent: *
|
echo 'User-Agent: *
|
||||||
|
|
|
@ -9,7 +9,7 @@ class SearchController
|
||||||
{
|
{
|
||||||
public static function i()
|
public static function i()
|
||||||
{
|
{
|
||||||
Page::set('Search');
|
Page::set('Search/Index');
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
23
app/Controllers/VehicleController.php
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Controllers;
|
||||||
|
|
||||||
|
use \App\Services\{Router, Auth, DB, Json};
|
||||||
|
use \App\Controllers\ExceptionRegister;
|
||||||
|
use \App\Core\Page;
|
||||||
|
|
||||||
|
class VehicleController
|
||||||
|
{
|
||||||
|
public static function i()
|
||||||
|
{
|
||||||
|
Page::set('Vehicle/Index');
|
||||||
|
}
|
||||||
|
public static function iedit()
|
||||||
|
{
|
||||||
|
Page::set('Vehicle/IndexEdit');
|
||||||
|
}
|
||||||
|
public static function dbedit()
|
||||||
|
{
|
||||||
|
Page::set('Vehicle/DBEdit');
|
||||||
|
}
|
||||||
|
}
|
|
@ -17,39 +17,46 @@ class Routes
|
||||||
Router::get('/register', 'RegisterController@i');
|
Router::get('/register', 'RegisterController@i');
|
||||||
Router::get('/photo/$id', 'PhotoController@i');
|
Router::get('/photo/$id', 'PhotoController@i');
|
||||||
Router::get('/author/$id', 'ProfileController@i');
|
Router::get('/author/$id', 'ProfileController@i');
|
||||||
|
Router::get('/page/$id', 'MainController@page');
|
||||||
Router::post('/api/login', 'ApiController@login');
|
Router::post('/api/login', 'ApiController@login');
|
||||||
Router::post('/api/register', 'ApiController@register');
|
Router::post('/api/register', 'ApiController@register');
|
||||||
Router::get('/api/photo/stats', 'ApiController@photostats');
|
Router::get('/api/photo/stats', 'ApiController@photostats');
|
||||||
Router::get('/about', 'MainController@about');
|
Router::get('/about', 'MainController@about');
|
||||||
Router::get('/rules', 'MainController@rules');
|
Router::get('/rules', 'MainController@rules');
|
||||||
Router::get('/vehicle/$id', 'MainController@vehicle');
|
|
||||||
Router::get('/rules/pub', 'MainController@publicationRules');
|
Router::get('/rules/pub', 'MainController@publicationRules');
|
||||||
Router::get('/rules/photo', 'MainController@photoRules');
|
Router::get('/rules/photo', 'MainController@photoRules');
|
||||||
Router::get('/rules/video', 'MainController@videoRules');
|
Router::get('/rules/video', 'MainController@videoRules');
|
||||||
Router::get('/feed', 'MainController@feed');
|
Router::get('/feed', 'MainController@feed');
|
||||||
|
Router::get('/tour', 'MainController@tour');
|
||||||
Router::get('/update', 'MainController@update');
|
Router::get('/update', 'MainController@update');
|
||||||
Router::get('/top30', 'MainController@top30');
|
Router::get('/top30', 'MainController@top30');
|
||||||
Router::get('/photoext', 'PhotoController@photoext');
|
Router::get('/photoext', 'PhotoController@photoext');
|
||||||
Router::get('/api/photo/compress', 'ApiController@photocompress');
|
Router::get('/api/photo/compress', 'ApiController@photocompress');
|
||||||
Router::get('/api/photo/loadrecent', 'ApiController@recentphotos');
|
Router::get('/api/photo/loadrecent', 'ApiController@recentphotos');
|
||||||
Router::get('/api/users/load/$id', 'ApiController@loaduser');
|
Router::get('/api/users/load/$id', 'ApiController@loaduser');
|
||||||
|
Router::get('/api/users/emailverify', 'ApiController@emailverify');
|
||||||
Router::get('/article/$id', 'MainController@gallery');
|
Router::get('/article/$id', 'MainController@gallery');
|
||||||
|
Router::get('/voting', 'ContestsController@index');
|
||||||
|
Router::get('/voting/results', 'ContestsController@results');
|
||||||
|
Router::get('/voting/waiting', 'ContestsController@waiting');
|
||||||
|
Router::get('/comments', 'MainController@comments');
|
||||||
if (Auth::userid() > 0) {
|
if (Auth::userid() > 0) {
|
||||||
$user = new \App\Models\User(Auth::userid());
|
$user = new \App\Models\User(Auth::userid());
|
||||||
|
|
||||||
Router::get('/lk', 'ProfileController@lk');
|
Router::get('/lk', 'ProfileController@lk');
|
||||||
Router::get('/lk/upload', 'ProfileController@upload');
|
Router::get('/lk/upload', 'ProfileController@upload');
|
||||||
Router::get('/lk/history', 'ProfileController@lkhistory');
|
Router::get('/lk/history', 'ProfileController@lkhistory');
|
||||||
Router::get('/lk/profile', 'ProfileController@lkprofile');
|
Router::get('/lk/profile', 'ProfileController@lkprofile');
|
||||||
Router::get('/lk/pday', 'ProfileController@photoindexhistory');
|
Router::get('/lk/pday', 'ProfileController@photoindexhistory');
|
||||||
|
|
||||||
Router::get('/fav_authors', 'MainController@favauthors');
|
Router::get('/fav_authors', 'MainController@favauthors');
|
||||||
|
|
||||||
Router::get('/search', 'SearchController@i');
|
Router::get('/search', 'SearchController@i');
|
||||||
|
|
||||||
Router::get('/fav', 'MainController@fav');
|
Router::get('/fav', 'MainController@fav');
|
||||||
|
Router::get('/voting/sendpretend', 'ContestsController@sendpretend');
|
||||||
|
|
||||||
|
Router::get('/vehicle/edit', 'VehicleController@iedit');
|
||||||
|
Router::get('/vehicle/dbedit', 'VehicleController@dbedit');
|
||||||
Router::post('/api/upload', 'ApiController@upload');
|
Router::post('/api/upload', 'ApiController@upload');
|
||||||
Router::post('/api/profile/update', 'ApiController@updateprofile');
|
Router::post('/api/profile/update', 'ApiController@updateprofile');
|
||||||
Router::post('/api/photo/comment', 'ApiController@photocomment');
|
Router::post('/api/photo/comment', 'ApiController@photocomment');
|
||||||
|
@ -61,18 +68,29 @@ class Routes
|
||||||
Router::get('/api/photo/comment/rate', 'ApiController@photocommentvote');
|
Router::get('/api/photo/comment/rate', 'ApiController@photocommentvote');
|
||||||
Router::post('/api/photo/comment/$id/edit', 'ApiController@photocommentedit');
|
Router::post('/api/photo/comment/$id/edit', 'ApiController@photocommentedit');
|
||||||
Router::post('/api/photo/comment/$id/delete', 'ApiController@photocommentdelete');
|
Router::post('/api/photo/comment/$id/delete', 'ApiController@photocommentdelete');
|
||||||
|
Router::post('/api/photo/comment/$id/pin', 'ApiController@photocommentpin');
|
||||||
|
Router::post('/api/photo/contests/sendpretend', 'ApiController@sendpretendphoto');
|
||||||
|
Router::get('/api/photo/contests/rate', 'ApiController@photovotecontest');
|
||||||
|
Router::get('/api/contests/getinfo', 'ApiController@contestsgetinfo');
|
||||||
Router::get('/api/vehicles/load', 'ApiController@vehiclesload');
|
Router::get('/api/vehicles/load', 'ApiController@vehiclesload');
|
||||||
|
Router::get('/api/geodb/search', 'ApiController@geodbsearch');
|
||||||
if ($user->i('admin') > 0) {
|
if ($user->i('admin') > 0) {
|
||||||
Router::any('/admin', 'AdminController@index');
|
Router::any('/admin', 'AdminController@index');
|
||||||
Router::any('/api/admin/images/setvisibility', 'ApiController@adminsetvis');
|
Router::any('/api/admin/images/setvisibility', 'ApiController@adminsetvis');
|
||||||
Router::any('/api/admin/createnews', 'ApiController@admincreatenews');
|
Router::any('/api/admin/createnews', 'ApiController@admincreatenews');
|
||||||
Router::any('/api/admin/loadnews', 'ApiController@adminloadnews');
|
Router::any('/api/admin/loadnews', 'ApiController@adminloadnews');
|
||||||
Router::any('/api/admin/getvehicleinputs/$id', 'ApiController@admingetvehicleinputs');
|
Router::any('/api/admin/getvehicleinputs/$id', 'ApiController@admingetvehicleinputs');
|
||||||
|
Router::any('/api/admin/geodb/create', 'ApiController@admingeodbcreate');
|
||||||
|
Router::any('/api/admin/geodb/load', 'ApiController@admingeodbload');
|
||||||
|
Router::any('/api/admin/contests/createtheme', 'ApiController@admincontestscreatetheme');
|
||||||
|
Router::any('/api/admin/contests/create', 'ApiController@admincontestscreate');
|
||||||
|
Router::any('/api/admin/settings/taskmanager', 'ApiController@admintaskmanager');
|
||||||
}
|
}
|
||||||
Router::get('/logout', 'MainController@logout');
|
Router::get('/logout', 'MainController@logout');
|
||||||
Router::get('/404', 'ExceptionRegister@notfound');
|
Router::get('/404', 'ExceptionRegister@notfound');
|
||||||
} else {
|
} else {
|
||||||
Router::redirect('/login?return='.$_SERVER['HTTP_REFERER']);
|
Router::redirect('/login?return='.$_SERVER['HTTP_REFERER']);
|
||||||
}
|
}
|
||||||
|
Router::get('/vehicle/$id', 'VehicleController@i');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,68 +1,91 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
use \App\Services\{DB, Date, Auth};
|
use \App\Services\{DB, Date, Auth};
|
||||||
use \App\Models\{User, Photo, Vote};
|
use \App\Models\{User, Photo, Vote};
|
||||||
|
|
||||||
class Comment {
|
class Comment
|
||||||
|
{
|
||||||
|
|
||||||
public $commentid;
|
public $commentid;
|
||||||
public $c;
|
public $c;
|
||||||
public $class;
|
public $class;
|
||||||
function __construct($user_id) {
|
function __construct($user_id)
|
||||||
|
{
|
||||||
$this->c = $user_id;
|
$this->c = $user_id;
|
||||||
}
|
}
|
||||||
public function class($class) {
|
public function class($class)
|
||||||
|
{
|
||||||
$this->class = $class;
|
$this->class = $class;
|
||||||
}
|
}
|
||||||
public function content($table) {
|
public function content($table)
|
||||||
|
{
|
||||||
$content = json_decode($this->c['content'], true);
|
$content = json_decode($this->c['content'], true);
|
||||||
return $content[$table];
|
return $content[$table];
|
||||||
}
|
}
|
||||||
public function i() {
|
public function i()
|
||||||
|
{
|
||||||
$user = new User($this->c['user_id']);
|
$user = new User($this->c['user_id']);
|
||||||
$content = json_decode($this->c['content'], true);
|
$content = json_decode($this->c['content'], true);
|
||||||
echo '<div class="'.$this->class.' comment" wid="'.$this->c['id'].'">
|
$photo = new \App\Models\Photo($this->c['photo_id']);
|
||||||
|
|
||||||
|
$pinc = 'Закрепить';
|
||||||
|
echo '<div class="' . $this->class . ' comment" wid="' . $this->c['id'] . '">';
|
||||||
|
if ($photo->i('pinnedcomment_id') === $this->c['id']) {
|
||||||
|
echo '<i style="padding-bottom: 15px;">Комментарий закреплён</i>';
|
||||||
|
$pinc = 'Открепить';
|
||||||
|
}
|
||||||
|
echo '
|
||||||
<div style="float:right; text-align:right" class="sm">
|
<div style="float:right; text-align:right" class="sm">
|
||||||
<span class="message_date">'.Date::zmdate($this->c['posted_at']).'</span><br>
|
<span class="message_date">' . Date::zmdate($this->c['posted_at']) . '</span><br>
|
||||||
<a href="#" class="quoteLink dot">Цитировать</a>
|
<a href="#" class="quoteLink dot">Цитировать</a>
|
||||||
·
|
·
|
||||||
<a href="#'.$this->c['id'].'" class="cmLink dot">Ссылка</a>
|
<a href="#' . $this->c['id'] . '" class="cmLink dot">Ссылка</a>
|
||||||
';
|
';
|
||||||
|
|
||||||
echo '
|
echo '
|
||||||
</div>
|
</div>
|
||||||
<a name="2681468"></a><a name="last"></a>
|
<a name="2681468"></a><a name="last"></a>
|
||||||
<div><img src="'.$user->i('photourl').'" width="32" style="border-radius: 3px; margin-right: 5px;"><b><a href="/author/'.$this->c['user_id'].'/" class="message_author">'.htmlspecialchars($user->i('username')).'</a></b> ·
|
<div><img src="' . $user->i('photourl') . '" width="32" style="border-radius: 3px; margin-right: 5px;"><b><a href="/author/' . $this->c['user_id'] . '/" class="message_author">' . htmlspecialchars($user->i('username')) . '</a></b> ·
|
||||||
<span class="flag">';
|
<span class="flag">';
|
||||||
if (json_decode($user->i('content'), true)['aboutrid']['value'] != null) {
|
if (json_decode($user->i('content'), true)['aboutrid']['value'] != null) {
|
||||||
echo '<img src="/static/img/flags/'.json_decode($user->i('content'), true)['aboutrid']['value'].'.gif">';
|
echo '<img src="/static/img/flags/' . json_decode($user->i('content'), true)['aboutrid']['value'] . '.gif">';
|
||||||
}
|
}
|
||||||
if (json_decode($user->i('content'), true)['aboutlive']['value'] != null) {
|
if (json_decode($user->i('content'), true)['aboutlive']['value'] != null) {
|
||||||
echo ' '.htmlspecialchars(json_decode($user->i('content'), true)['aboutlive']['value']);
|
echo ' ' . htmlspecialchars(json_decode($user->i('content'), true)['aboutlive']['value']);
|
||||||
}
|
}
|
||||||
if ($content['edited'] === 'true') {
|
if ($content['edited'] === 'true') {
|
||||||
echo '<br>(отредактировано)';
|
echo '<br>(отредактировано)';
|
||||||
}
|
}
|
||||||
if ($user->i('admin') === 1) {
|
if ($user->i('admin') === 1) {
|
||||||
$admintype = ' · Администратор сервера';
|
$admintype = ' · Администратор сервера';
|
||||||
} else if ($user->i('admin') === 2) {
|
} else if ($user->i('admin') === 2) {
|
||||||
$admintype = ' · Фотомодератор';
|
$admintype = ' · Фотомодератор';
|
||||||
}
|
}
|
||||||
if ((int)Vote::countcommrates($this->c['id'], -1) >= 1) {
|
if ((int)Vote::countcommrates($this->c['id'], -1) >= 1) {
|
||||||
$commclass = 'pro';
|
$commclass = 'pro';
|
||||||
$symb = '+';
|
$symb = '+';
|
||||||
} else if ((int)Vote::countcommrates($this->c['id'], -1) < 0) {
|
} else if ((int)Vote::countcommrates($this->c['id'], -1) < 0) {
|
||||||
$commclass = 'con';
|
$commclass = 'con';
|
||||||
$symb = '';
|
$symb = '';
|
||||||
} else if ((int)Vote::countcommrates($this->c['id'], -1) === 0) {
|
} else if ((int)Vote::countcommrates($this->c['id'], -1) === 0) {
|
||||||
$commclass = '';
|
$commclass = '';
|
||||||
}
|
}
|
||||||
echo '</span></div>
|
echo '</span></div>
|
||||||
<div class="rank">Фото: '.Photo::fetchAll($this->c['user_id']).' '.$admintype.'</div>
|
<div class="rank">Фото: ' . Photo::fetchAll($this->c['user_id']) . ' ' . $admintype . '</div>
|
||||||
<div class="message-text">'.preg_replace("~(?:[\p{M}]{1})([\p{M}])+?~uis","", htmlspecialchars($this->c['body'])).'</div>
|
<div class="message-text">' . preg_replace("~(?:[\p{M}]{1})([\p{M}])+?~uis", "", htmlspecialchars($this->c['body'])) . '</div>
|
||||||
|
';
|
||||||
|
if ($content['filetype'] === 'img') {
|
||||||
|
echo '<div class="message-text"><img src="'.$content['src'].'" width="250"></div>';
|
||||||
|
}
|
||||||
|
if ($content['filetype'] === 'video') {
|
||||||
|
echo '<div class="message-text"><video controls src="'.$content['src'].'" width="250"></div>';
|
||||||
|
}
|
||||||
|
echo '
|
||||||
<div class="comment-votes-block">
|
<div class="comment-votes-block">
|
||||||
';
|
';
|
||||||
echo '<style>
|
echo '<style>
|
||||||
.dropdown {
|
.dropdown {
|
||||||
position: relative;
|
position: relative;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
|
@ -82,34 +105,39 @@ class Comment {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
</style>';
|
</style>';
|
||||||
if ($this->c['user_id'] === Auth::userid()) {
|
if ($this->c['user_id'] === Auth::userid() || $photo->i('user_id') === Auth::userid()) {
|
||||||
echo '
|
echo '
|
||||||
<div class="dropdown">
|
<div class="dropdown">
|
||||||
<a style="color: #000" class="compl" href="/lk/ticket.php?action=add&wid=3252565">...</a>
|
<a style="color: #000" class="compl" href="#">...</a>
|
||||||
<div class="dropdown-content">'; ?>
|
<div class="dropdown-content">';
|
||||||
<a style="margin-bottom: 10px;" href="#" onclick="createModal(<?=$this->c['id']?>, 'EDIT_COMMENT', '<?=htmlspecialchars($this->c['body'])?>', 'modaledit<?=$this->c['id']?>'); return false;">Редактировать</a><br>
|
|
||||||
<a href="#" onclick="createModal(<?=$this->c['id']?>, 'DELETE_COMMENT', '', 'modaldel<?=$this->c['id']?>'); return false;">Удалить</a>
|
|
||||||
<?php
|
?>
|
||||||
echo '
|
|
||||||
|
<a href="#" onclick="pinComment(<?= $this->c['id'] ?>); return false;"><?=$pinc?></a><br>
|
||||||
|
<?php
|
||||||
|
if ($this->c['user_id'] === Auth::userid()) { ?>
|
||||||
|
<a style="margin-bottom: 10px;" href="#" onclick="createModal(<?= $this->c['id'] ?>, 'EDIT_COMMENT', '<?= htmlspecialchars($this->c['body']) ?>', 'modaledit<?= $this->c['id'] ?>'); return false;">Редактировать</a><br>
|
||||||
|
<a href="#" onclick="createModal(<?= $this->c['id'] ?>, 'DELETE_COMMENT', '', 'modaldel<?= $this->c['id'] ?>'); return false;">Удалить</a>
|
||||||
|
<?php }
|
||||||
|
|
||||||
|
echo '
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
';
|
';
|
||||||
}
|
}
|
||||||
echo '
|
echo '
|
||||||
<div class="wvote" wid="'.$this->c['id'].'">
|
<div class="wvote" wid="' . $this->c['id'] . '">
|
||||||
<a href="#" vote="1" class="w-btn s2"><span>+</span></a>
|
<a href="#" vote="1" class="w-btn s2"><span>+</span></a>
|
||||||
|
|
||||||
<div class="w-rating '.$commclass.' active">'.$symb.Vote::countcommrates($this->c['id'], -1).'</div>
|
<div class="w-rating ' . $commclass . ' active">' . $symb . Vote::countcommrates($this->c['id'], -1) . '</div>
|
||||||
|
|
||||||
<div class="w-rating-ext">
|
<div class="w-rating-ext">
|
||||||
<div><span class="pro">+'.Vote::countcommrates($this->c['id'], 1).'</span> / <span class="con">'.Vote::countcommrates($this->c['id'], 0).'</span></div>
|
<div><span class="pro">+' . Vote::countcommrates($this->c['id'], 1) . '</span> / <span class="con">' . Vote::countcommrates($this->c['id'], 0) . '</span></div>
|
||||||
</div>
|
</div>
|
||||||
<a href="#" vote="0" class="w-btn s5"><span>–</span></a>
|
<a href="#" vote="0" class="w-btn s5"><span>–</span></a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>';
|
</div>';
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ use \App\Services\DB;
|
||||||
class Photo {
|
class Photo {
|
||||||
|
|
||||||
public $photoid;
|
public $photoid;
|
||||||
function __construct(int $user_id) {
|
function __construct($user_id) {
|
||||||
$this->photoid = $user_id;
|
$this->photoid = $user_id;
|
||||||
}
|
}
|
||||||
public function i($table) {
|
public function i($table) {
|
||||||
|
@ -37,6 +37,9 @@ class Photo {
|
||||||
case 5:
|
case 5:
|
||||||
return 'Расчленёнка';
|
return 'Расчленёнка';
|
||||||
break;
|
break;
|
||||||
|
case 6:
|
||||||
|
return 'Файл сломан';
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return 'Не подходит для сайта';
|
return 'Не подходит для сайта';
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -5,7 +5,7 @@ use \App\Services\DB;
|
||||||
class User {
|
class User {
|
||||||
|
|
||||||
public $userid;
|
public $userid;
|
||||||
function __construct(int $user_id) {
|
function __construct($user_id) {
|
||||||
$this->userid = $user_id;
|
$this->userid = $user_id;
|
||||||
}
|
}
|
||||||
public function i($table) {
|
public function i($table) {
|
||||||
|
|
|
@ -7,7 +7,23 @@ class Vote
|
||||||
{
|
{
|
||||||
public static function photo($user_id, $pid)
|
public static function photo($user_id, $pid)
|
||||||
{
|
{
|
||||||
$result = DB::query('SELECT type FROM photos_rates WHERE user_id=:uid AND photo_id=:pid', array(':uid' => $user_id, ':pid' => $pid));
|
$result = DB::query('SELECT type FROM photos_rates WHERE user_id=:uid AND photo_id=:pid AND contest=0', array(':uid' => $user_id, ':pid' => $pid));
|
||||||
|
if (!empty($result)) {
|
||||||
|
$type = $result[0]['type'];
|
||||||
|
if ($type < 0) {
|
||||||
|
$type = -1;
|
||||||
|
}
|
||||||
|
return $type;
|
||||||
|
} else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function photoContest($user_id, $pid)
|
||||||
|
{
|
||||||
|
$result = DB::query('SELECT type FROM photos_rates WHERE user_id=:uid AND photo_id=:pid AND contest=1', array(':uid' => $user_id, ':pid' => $pid));
|
||||||
if (!empty($result)) {
|
if (!empty($result)) {
|
||||||
$type = $result[0]['type'];
|
$type = $result[0]['type'];
|
||||||
if ($type < 0) {
|
if ($type < 0) {
|
||||||
|
|
37
app/Models/VoteContest.php
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
<?php
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use App\Services\{DB, GenerateRandomStr};
|
||||||
|
|
||||||
|
class VoteContest
|
||||||
|
{
|
||||||
|
public static function photo($user_id, $pid, $cid)
|
||||||
|
{
|
||||||
|
$result = DB::query('SELECT type FROM photos_rates_contest WHERE user_id=:uid AND photo_id=:pid AND contest_id=:id', array(':uid' => $user_id, ':pid' => $pid, ':id'=>$cid));
|
||||||
|
if (!empty($result)) {
|
||||||
|
$type = $result[0]['type'];
|
||||||
|
if ($type < 0) {
|
||||||
|
$type = -1;
|
||||||
|
}
|
||||||
|
return $type;
|
||||||
|
} else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function count($pid, $cid) {
|
||||||
|
$result = DB::query('SELECT * FROM photos_rates_contest WHERE photo_id=:pid AND contest_id=:id', array(':pid' => $pid, ':id'=>$cid));
|
||||||
|
$votes = 0;
|
||||||
|
foreach ($result as $r) {
|
||||||
|
if ($r['type'] === 1) {
|
||||||
|
$votes++;
|
||||||
|
} else {
|
||||||
|
$votes--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $votes;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
?>
|
|
@ -1,5 +1,6 @@
|
||||||
<?php
|
<?php
|
||||||
namespace App\Services;
|
namespace App\Services;
|
||||||
|
use InvalidArgumentException;
|
||||||
|
|
||||||
class Date
|
class Date
|
||||||
{
|
{
|
||||||
|
@ -65,5 +66,38 @@ class Date
|
||||||
);
|
);
|
||||||
return $formattedDate;
|
return $formattedDate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function addTime($timeString, int $baseTime = null)
|
||||||
|
{
|
||||||
|
if ($baseTime === null) {
|
||||||
|
$baseTime = time();
|
||||||
|
}
|
||||||
|
|
||||||
|
preg_match('/^(\d+)([smhdwMy])$/', $timeString, $matches);
|
||||||
|
|
||||||
|
if (!$matches) {
|
||||||
|
throw new InvalidArgumentException("Неверный формат времени: $timeString");
|
||||||
|
}
|
||||||
|
|
||||||
|
[$fullMatch, $amount, $unit] = $matches;
|
||||||
|
$amount = (int) $amount;
|
||||||
|
|
||||||
|
$multipliers = [
|
||||||
|
's' => 1, // секунды
|
||||||
|
'm' => 60, // минуты
|
||||||
|
'h' => 3600, // часы
|
||||||
|
'd' => 86400, // дни
|
||||||
|
'w' => 604800, // недели
|
||||||
|
'M' => 2629743, // месяцы (среднее значение)
|
||||||
|
'y' => 31556926 // годы (среднее значение)
|
||||||
|
];
|
||||||
|
|
||||||
|
if (!isset($multipliers[$unit])) {
|
||||||
|
throw new InvalidArgumentException("Неизвестная единица измерения: $unit");
|
||||||
|
}
|
||||||
|
|
||||||
|
return $baseTime + ($amount * $multipliers[$unit]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
?>
|
?>
|
||||||
|
|
52
app/Services/KeyTranslation.php
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Services;
|
||||||
|
|
||||||
|
class KeyTranslation
|
||||||
|
{
|
||||||
|
|
||||||
|
public static function key($key)
|
||||||
|
{
|
||||||
|
switch ($key) {
|
||||||
|
case 'title':
|
||||||
|
return 'Название сервера';
|
||||||
|
break;
|
||||||
|
case 'adminemail':
|
||||||
|
return 'Почта Администратора';
|
||||||
|
break;
|
||||||
|
case 'showtitle':
|
||||||
|
return 'Отображать название в заголовке';
|
||||||
|
break;
|
||||||
|
case 'logo':
|
||||||
|
return 'Расположение логотипа';
|
||||||
|
break;
|
||||||
|
case 'description':
|
||||||
|
return 'Описание сервера';
|
||||||
|
break;
|
||||||
|
case 'keywords':
|
||||||
|
return 'Ключевые слова (для SEO)';
|
||||||
|
break;
|
||||||
|
case 'maintenance':
|
||||||
|
return 'Режим технических работ';
|
||||||
|
break;
|
||||||
|
case 'debug':
|
||||||
|
return 'Дебаг';
|
||||||
|
break;
|
||||||
|
case 'access':
|
||||||
|
return 'Доступ к сайту';
|
||||||
|
break;
|
||||||
|
case 'type':
|
||||||
|
return 'Тип';
|
||||||
|
break;
|
||||||
|
case 'countries':
|
||||||
|
return 'Страны';
|
||||||
|
break;
|
||||||
|
case 'cloudflare-caching':
|
||||||
|
return 'Кэширование Cloudflare (и прочих CDN)';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return $key;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
152
app/Services/TaskScheduler.php
Normal file
|
@ -0,0 +1,152 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Services;
|
||||||
|
class TaskScheduler {
|
||||||
|
public function __construct() {}
|
||||||
|
|
||||||
|
private function isWindows() {
|
||||||
|
return strtoupper(substr(PHP_OS, 0, 3)) === 'WIN';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function addTask($taskName, $command, $interval = "* * * * *") {
|
||||||
|
return $this->isWindows() ? $this->addWindowsTask($taskName, $command) : $this->addLinuxTask($command, $interval);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isTaskExists($taskName = null, $command = null) {
|
||||||
|
return $this->isWindows() ? $this->isWindowsTaskExists($taskName) : $this->isLinuxTaskExists($command);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function removeTask($taskName = null, $command = null) {
|
||||||
|
return $this->isWindows() ? $this->removeWindowsTask($taskName) : $this->removeLinuxTask($command);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getTaskStatus($taskName, $command = null) {
|
||||||
|
if (!$this->isTaskExists($taskName, $command)) {
|
||||||
|
return "❌ Не работает (задача отсутствует)";
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->isWindows() ? $this->getWindowsTaskStatus($taskName) : $this->getLinuxTaskStatus($command);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function findHandlerById($array, $id) {
|
||||||
|
foreach ($array as $item) {
|
||||||
|
if (isset($item['id']) && $item['id'] === $id) {
|
||||||
|
return $item['handler'] ?? null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function addLinuxTask($command, $interval) {
|
||||||
|
$cronJob = "{$interval} {$command}";
|
||||||
|
if ($this->isLinuxTaskExists($command)) {
|
||||||
|
return "✅ Cron-задача уже установлена.";
|
||||||
|
}
|
||||||
|
|
||||||
|
exec("crontab -l 2>&1", $output, $return_var);
|
||||||
|
if ($return_var !== 0) {
|
||||||
|
$output = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
$output[] = $cronJob;
|
||||||
|
file_put_contents("/tmp/my_cron", implode(PHP_EOL, $output) . PHP_EOL);
|
||||||
|
exec("crontab /tmp/my_cron");
|
||||||
|
unlink("/tmp/my_cron");
|
||||||
|
|
||||||
|
return "✅ Cron-задача добавлена!";
|
||||||
|
}
|
||||||
|
|
||||||
|
private function isLinuxTaskExists($command = null) {
|
||||||
|
exec("crontab -l 2>&1", $output);
|
||||||
|
foreach ($output as $line) {
|
||||||
|
if (strpos($line, $command) !== false) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function removeLinuxTask($command = null) {
|
||||||
|
exec("crontab -l 2>&1", $output, $return_var);
|
||||||
|
if ($return_var !== 0) {
|
||||||
|
return "❌ Нет задач для удаления.";
|
||||||
|
}
|
||||||
|
|
||||||
|
$filteredOutput = array_filter($output, function ($line) use ($command) {
|
||||||
|
return strpos($line, $command) === false;
|
||||||
|
});
|
||||||
|
|
||||||
|
file_put_contents("/tmp/my_cron", implode(PHP_EOL, $filteredOutput) . PHP_EOL);
|
||||||
|
exec("crontab /tmp/my_cron");
|
||||||
|
unlink("/tmp/my_cron");
|
||||||
|
|
||||||
|
return "✅ Cron-задача удалена!";
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getLinuxTaskStatus($command) {
|
||||||
|
exec("ps aux | grep '" . escapeshellarg($command) . "' | grep -v grep", $output, $return_code);
|
||||||
|
|
||||||
|
if (empty($output)) {
|
||||||
|
return "⚠ Не работает (ошибка: процесс не найден)";
|
||||||
|
}
|
||||||
|
|
||||||
|
return "✅ Работает корректно";
|
||||||
|
}
|
||||||
|
|
||||||
|
private function addWindowsTask($taskName, $command) {
|
||||||
|
if ($this->isWindowsTaskExists($taskName)) {
|
||||||
|
return "✅ Задача уже существует в Windows.";
|
||||||
|
}
|
||||||
|
|
||||||
|
$cmd = "schtasks /Create /SC MINUTE /MO 1 /TN \"{$taskName}\" /TR \"{$command}\" /F";
|
||||||
|
exec($cmd, $output, $return_code);
|
||||||
|
|
||||||
|
return ($return_code === 0) ? "✅ Задача добавлена в Windows!" : "❌ Ошибка при добавлении задачи.";
|
||||||
|
}
|
||||||
|
|
||||||
|
private function isWindowsTaskExists($taskName = null) {
|
||||||
|
exec("schtasks /Query /TN \"". ($taskName) ."\" 2>&1", $output, $return_var);
|
||||||
|
return $return_var === 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function removeWindowsTask($taskName = null) {
|
||||||
|
if (!$this->isWindowsTaskExists($taskName)) {
|
||||||
|
return "❌ Задача не найдена в Windows.";
|
||||||
|
}
|
||||||
|
|
||||||
|
exec("schtasks /Delete /TN \"". ($taskName) ."\" /F", $output, $return_code);
|
||||||
|
return ($return_code === 0) ? "✅ Задача удалена из Windows!" : "❌ Ошибка при удалении задачи.";
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getWindowsTaskStatus($taskName) {
|
||||||
|
exec("schtasks /Query /TN \"{$taskName}\" /FO LIST /V", $output, $return_var);
|
||||||
|
|
||||||
|
if ($return_var !== 0) {
|
||||||
|
return "❌ Не работает (задача отсутствует)";
|
||||||
|
}
|
||||||
|
|
||||||
|
$status = "⚠ Не работает (ошибка: неизвестно)";
|
||||||
|
|
||||||
|
$output = array_map(function($line) {
|
||||||
|
return iconv('Windows-1251', 'UTF-8', $line);
|
||||||
|
}, $output);
|
||||||
|
|
||||||
|
// Ищем статус задачи
|
||||||
|
foreach ($output as $line) {
|
||||||
|
if (strpos($line, "Статус:") !== false) {
|
||||||
|
if (stripos($line, "Выполняется") !== false) {
|
||||||
|
$status = "✅ Работает корректно";
|
||||||
|
} elseif (stripos($line, "Готово") !== false) {
|
||||||
|
$status = "⚠ Не работает (но активна)";
|
||||||
|
} elseif (stripos($line, "Не удалось запустить") !== false) {
|
||||||
|
$status = "⚠ Не работает (ошибка: не удалось запустить)";
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $status;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
?>
|
|
@ -28,7 +28,7 @@ class Upload
|
||||||
$tmpname = $file['tmp_name'];
|
$tmpname = $file['tmp_name'];
|
||||||
$type = explode('/', $file['type'])[0];
|
$type = explode('/', $file['type'])[0];
|
||||||
$name = $file['name'];
|
$name = $file['name'];
|
||||||
$fileext = pathinfo($file['name']);
|
$fileext = pathinfo($file['name'], PATHINFO_EXTENSION);
|
||||||
} else {
|
} else {
|
||||||
$tmpname = $file;
|
$tmpname = $file;
|
||||||
$type = filetype($file);
|
$type = filetype($file);
|
||||||
|
@ -64,7 +64,7 @@ class Upload
|
||||||
],
|
],
|
||||||
'endpoint' => NGALLERY['root']['storage']['s3']['domains']['gateway'],
|
'endpoint' => NGALLERY['root']['storage']['s3']['domains']['gateway'],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$s3->putObject([
|
$s3->putObject([
|
||||||
'Bucket' => NGALLERY['root']['storage']['s3']['credentials']['bucket'],
|
'Bucket' => NGALLERY['root']['storage']['s3']['credentials']['bucket'],
|
||||||
'Key' => $location.$filecdn,
|
'Key' => $location.$filecdn,
|
||||||
|
@ -77,18 +77,16 @@ class Upload
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
$location = "your-location";
|
$location = "your-location";
|
||||||
$folder = "{$location}/" . basename($tmpname);
|
$folder = "{$location}/" . basename($tmpname);
|
||||||
|
|
||||||
$uploadDir = "{$_SERVER['DOCUMENT_ROOT']}/uploads/{$location}";
|
$uploadDir = "{$_SERVER['DOCUMENT_ROOT']}/uploads/{$location}";
|
||||||
|
|
||||||
if (!is_dir($uploadDir)) {
|
if (!is_dir($uploadDir)) {
|
||||||
mkdir($uploadDir, 0777, true);
|
mkdir($uploadDir, 0777, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
$destination = "{$uploadDir}/" . basename($tmpname);
|
$destination = "{$uploadDir}/" . basename($tmpname);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
$this->type = $type;
|
$this->type = $type;
|
||||||
$this->src = "/uploads/{$folder}";
|
$this->src = "/uploads/{$folder}";
|
||||||
|
|
|
@ -20,6 +20,11 @@
|
||||||
"donatj/phpuseragentparser": "^1.8",
|
"donatj/phpuseragentparser": "^1.8",
|
||||||
"php-ffmpeg/php-ffmpeg": "^1.2",
|
"php-ffmpeg/php-ffmpeg": "^1.2",
|
||||||
"chriskonnertz/bbcode": "^1.1",
|
"chriskonnertz/bbcode": "^1.1",
|
||||||
"paquettg/php-html-parser": "^2.2"
|
"paquettg/php-html-parser": "^2.2",
|
||||||
|
"phpmailer/phpmailer": "^6.9",
|
||||||
|
"beeyev/disposable-email-filter-php": "^1.3"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"phpstan/phpstan": "*"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
221
composer.lock
generated
|
@ -4,7 +4,7 @@
|
||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "31de33165b326f2edef27c1fc9ae5b08",
|
"content-hash": "844a94a4ce9ce290e30dd5845c27ed3f",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "aws/aws-crt-php",
|
"name": "aws/aws-crt-php",
|
||||||
|
@ -155,6 +155,77 @@
|
||||||
},
|
},
|
||||||
"time": "2024-07-03T18:12:51+00:00"
|
"time": "2024-07-03T18:12:51+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "beeyev/disposable-email-filter-php",
|
||||||
|
"version": "v1.3.83",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/beeyev/disposable-email-filter-php.git",
|
||||||
|
"reference": "9ee8422c390d0ce0fff25ff5616a4b9654f73bb0"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/beeyev/disposable-email-filter-php/zipball/9ee8422c390d0ce0fff25ff5616a4b9654f73bb0",
|
||||||
|
"reference": "9ee8422c390d0ce0fff25ff5616a4b9654f73bb0",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": "^7.2 || ^8.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"ext-json": "*",
|
||||||
|
"friendsofphp/php-cs-fixer": "^3.4",
|
||||||
|
"kubawerlos/php-cs-fixer-custom-fixers": "^3.7",
|
||||||
|
"phpstan/phpstan": "^1.11",
|
||||||
|
"phpstan/phpstan-phpunit": "^1.3",
|
||||||
|
"phpstan/phpstan-strict-rules": "^1.5",
|
||||||
|
"phpunit/phpunit": "^8.5 || ^9",
|
||||||
|
"symplify/phpstan-rules": "^12.3"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"laravel": {
|
||||||
|
"aliases": {
|
||||||
|
"DisposableEmail": "Beeyev\\DisposableEmailFilter\\Adapters\\Laravel\\Facades\\DisposableEmail"
|
||||||
|
},
|
||||||
|
"providers": [
|
||||||
|
"Beeyev\\DisposableEmailFilter\\Adapters\\Laravel\\DisposableEmailFilterServiceProvider"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Beeyev\\DisposableEmailFilter\\": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Alexander Tebiev",
|
||||||
|
"email": "alexander.tebiev@gmail.com",
|
||||||
|
"homepage": "https://github.com/beeyev/"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Disposable (temporary/throwaway/fake) email detection library. Automatically updated every week.",
|
||||||
|
"homepage": "https://github.com/beeyev/disposable-email-filter-php",
|
||||||
|
"keywords": [
|
||||||
|
"disposable",
|
||||||
|
"email",
|
||||||
|
"fake",
|
||||||
|
"temporary",
|
||||||
|
"throwaway"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"docs": "https://github.com/beeyev/disposable-email-filter-php/",
|
||||||
|
"issues": "https://github.com/beeyev/disposable-email-filter-php/issues",
|
||||||
|
"rss": "https://github.com/beeyev/disposable-email-filter-php/releases.atom",
|
||||||
|
"source": "https://github.com/beeyev/disposable-email-filter-php.git"
|
||||||
|
},
|
||||||
|
"time": "2025-02-05T14:49:14+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "chriskonnertz/bbcode",
|
"name": "chriskonnertz/bbcode",
|
||||||
"version": "v1.1.2",
|
"version": "v1.1.2",
|
||||||
|
@ -913,6 +984,87 @@
|
||||||
},
|
},
|
||||||
"time": "2024-01-02T10:37:01+00:00"
|
"time": "2024-01-02T10:37:01+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "phpmailer/phpmailer",
|
||||||
|
"version": "v6.9.3",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/PHPMailer/PHPMailer.git",
|
||||||
|
"reference": "2f5c94fe7493efc213f643c23b1b1c249d40f47e"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/2f5c94fe7493efc213f643c23b1b1c249d40f47e",
|
||||||
|
"reference": "2f5c94fe7493efc213f643c23b1b1c249d40f47e",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"ext-ctype": "*",
|
||||||
|
"ext-filter": "*",
|
||||||
|
"ext-hash": "*",
|
||||||
|
"php": ">=5.5.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"dealerdirect/phpcodesniffer-composer-installer": "^1.0",
|
||||||
|
"doctrine/annotations": "^1.2.6 || ^1.13.3",
|
||||||
|
"php-parallel-lint/php-console-highlighter": "^1.0.0",
|
||||||
|
"php-parallel-lint/php-parallel-lint": "^1.3.2",
|
||||||
|
"phpcompatibility/php-compatibility": "^9.3.5",
|
||||||
|
"roave/security-advisories": "dev-latest",
|
||||||
|
"squizlabs/php_codesniffer": "^3.7.2",
|
||||||
|
"yoast/phpunit-polyfills": "^1.0.4"
|
||||||
|
},
|
||||||
|
"suggest": {
|
||||||
|
"decomplexity/SendOauth2": "Adapter for using XOAUTH2 authentication",
|
||||||
|
"ext-mbstring": "Needed to send email in multibyte encoding charset or decode encoded addresses",
|
||||||
|
"ext-openssl": "Needed for secure SMTP sending and DKIM signing",
|
||||||
|
"greew/oauth2-azure-provider": "Needed for Microsoft Azure XOAUTH2 authentication",
|
||||||
|
"hayageek/oauth2-yahoo": "Needed for Yahoo XOAUTH2 authentication",
|
||||||
|
"league/oauth2-google": "Needed for Google XOAUTH2 authentication",
|
||||||
|
"psr/log": "For optional PSR-3 debug logging",
|
||||||
|
"symfony/polyfill-mbstring": "To support UTF-8 if the Mbstring PHP extension is not enabled (^1.2)",
|
||||||
|
"thenetworg/oauth2-azure": "Needed for Microsoft XOAUTH2 authentication"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"PHPMailer\\PHPMailer\\": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"LGPL-2.1-only"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Marcus Bointon",
|
||||||
|
"email": "phpmailer@synchromedia.co.uk"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Jim Jagielski",
|
||||||
|
"email": "jimjag@gmail.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Andy Prevost",
|
||||||
|
"email": "codeworxtech@users.sourceforge.net"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Brent R. Matzelle"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "PHPMailer is a full-featured email creation and transfer class for PHP",
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/PHPMailer/PHPMailer/issues",
|
||||||
|
"source": "https://github.com/PHPMailer/PHPMailer/tree/v6.9.3"
|
||||||
|
},
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://github.com/Synchro",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"time": "2024-11-24T18:04:13+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "psr/cache",
|
"name": "psr/cache",
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
|
@ -2096,13 +2248,72 @@
|
||||||
"time": "2024-04-29T11:44:00+00:00"
|
"time": "2024-04-29T11:44:00+00:00"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"packages-dev": [],
|
"packages-dev": [
|
||||||
|
{
|
||||||
|
"name": "phpstan/phpstan",
|
||||||
|
"version": "2.1.5",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/phpstan/phpstan.git",
|
||||||
|
"reference": "451b17f9665481ee502adc39be987cb71067ece2"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/451b17f9665481ee502adc39be987cb71067ece2",
|
||||||
|
"reference": "451b17f9665481ee502adc39be987cb71067ece2",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": "^7.4|^8.0"
|
||||||
|
},
|
||||||
|
"conflict": {
|
||||||
|
"phpstan/phpstan-shim": "*"
|
||||||
|
},
|
||||||
|
"bin": [
|
||||||
|
"phpstan",
|
||||||
|
"phpstan.phar"
|
||||||
|
],
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"files": [
|
||||||
|
"bootstrap.php"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"description": "PHPStan - PHP Static Analysis Tool",
|
||||||
|
"keywords": [
|
||||||
|
"dev",
|
||||||
|
"static analysis"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"docs": "https://phpstan.org/user-guide/getting-started",
|
||||||
|
"forum": "https://github.com/phpstan/phpstan/discussions",
|
||||||
|
"issues": "https://github.com/phpstan/phpstan/issues",
|
||||||
|
"security": "https://github.com/phpstan/phpstan/security/policy",
|
||||||
|
"source": "https://github.com/phpstan/phpstan-src"
|
||||||
|
},
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://github.com/ondrejmirtes",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://github.com/phpstan",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"time": "2025-02-13T12:49:56+00:00"
|
||||||
|
}
|
||||||
|
],
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
"minimum-stability": "stable",
|
"minimum-stability": "stable",
|
||||||
"stability-flags": [],
|
"stability-flags": {},
|
||||||
"prefer-stable": false,
|
"prefer-stable": false,
|
||||||
"prefer-lowest": false,
|
"prefer-lowest": false,
|
||||||
"platform": [],
|
"platform": {},
|
||||||
"platform-dev": [],
|
"platform-dev": {},
|
||||||
"plugin-api-version": "2.6.0"
|
"plugin-api-version": "2.6.0"
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@ class App
|
||||||
|
|
||||||
if (file_exists($_SERVER['DOCUMENT_ROOT'] . '/ngallery.yaml')) {
|
if (file_exists($_SERVER['DOCUMENT_ROOT'] . '/ngallery.yaml')) {
|
||||||
define("NGALLERY", Yaml::parse(file_get_contents($_SERVER['DOCUMENT_ROOT'] . '/ngallery.yaml'))['ngallery']);
|
define("NGALLERY", Yaml::parse(file_get_contents($_SERVER['DOCUMENT_ROOT'] . '/ngallery.yaml'))['ngallery']);
|
||||||
|
define("NGALLERY_TASKS", Yaml::parse(file_get_contents($_SERVER['DOCUMENT_ROOT'] . '/app/Controllers/Exec/Tasks/ngallery-tasks.yaml'))['tasks']);
|
||||||
if (NGALLERY['root']['debug'] === true) {
|
if (NGALLERY['root']['debug'] === true) {
|
||||||
Debugger::enable();
|
Debugger::enable();
|
||||||
}
|
}
|
||||||
|
@ -37,4 +38,4 @@ class App
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
App::start();
|
App::start();
|
|
@ -13,6 +13,14 @@ ngallery:
|
||||||
type: 'allow'
|
type: 'allow'
|
||||||
countries: ''
|
countries: ''
|
||||||
cloudflare-caching: false
|
cloudflare-caching: false
|
||||||
|
email:
|
||||||
|
credentials:
|
||||||
|
host: 'example@mail.com'
|
||||||
|
username: ''
|
||||||
|
password: ''
|
||||||
|
port: 465
|
||||||
|
from:
|
||||||
|
address:
|
||||||
db:
|
db:
|
||||||
name: ''
|
name: ''
|
||||||
host: ''
|
host: ''
|
||||||
|
@ -40,6 +48,7 @@ ngallery:
|
||||||
proxy: true
|
proxy: true
|
||||||
percent: 50
|
percent: 50
|
||||||
registration:
|
registration:
|
||||||
|
emailverify: false
|
||||||
prohibited_usernames: ''
|
prohibited_usernames: ''
|
||||||
access:
|
access:
|
||||||
public: true
|
public: true
|
||||||
|
@ -59,5 +68,12 @@ ngallery:
|
||||||
allowgif: true
|
allowgif: true
|
||||||
comments:
|
comments:
|
||||||
premoderation: false
|
premoderation: false
|
||||||
|
contests:
|
||||||
|
enabled: true
|
||||||
|
autonew:
|
||||||
|
enabled: true
|
||||||
|
times:
|
||||||
|
pretendsopen: 'now'
|
||||||
|
pretendsclose: '2d'
|
||||||
|
open: 'now'
|
||||||
|
close: '2d'
|
||||||
|
|
|
@ -57,7 +57,7 @@ CREATE TABLE `login_tokens` (
|
||||||
`id` int NOT NULL,
|
`id` int NOT NULL,
|
||||||
`token` text NOT NULL,
|
`token` text NOT NULL,
|
||||||
`user_id` int NOT NULL
|
`user_id` int NOT NULL
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
|
||||||
-- --------------------------------------------------------
|
-- --------------------------------------------------------
|
||||||
|
|
||||||
|
@ -90,7 +90,7 @@ CREATE TABLE `photos` (
|
||||||
`place` text NOT NULL,
|
`place` text NOT NULL,
|
||||||
`endmoderation` int NOT NULL DEFAULT '0',
|
`endmoderation` int NOT NULL DEFAULT '0',
|
||||||
`content` text NOT NULL
|
`content` text NOT NULL
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
|
||||||
-- --------------------------------------------------------
|
-- --------------------------------------------------------
|
||||||
|
|
||||||
|
@ -104,7 +104,7 @@ CREATE TABLE `photos_comments` (
|
||||||
`photo_id` int NOT NULL,
|
`photo_id` int NOT NULL,
|
||||||
`body` text NOT NULL,
|
`body` text NOT NULL,
|
||||||
`posted_at` int NOT NULL
|
`posted_at` int NOT NULL
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
|
||||||
-- --------------------------------------------------------
|
-- --------------------------------------------------------
|
||||||
|
|
||||||
|
@ -117,7 +117,7 @@ CREATE TABLE `photos_comments_rates` (
|
||||||
`user_id` int NOT NULL,
|
`user_id` int NOT NULL,
|
||||||
`comment_id` int NOT NULL,
|
`comment_id` int NOT NULL,
|
||||||
`type` int NOT NULL
|
`type` int NOT NULL
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
|
||||||
-- --------------------------------------------------------
|
-- --------------------------------------------------------
|
||||||
|
|
||||||
|
@ -130,7 +130,7 @@ CREATE TABLE `photos_rates` (
|
||||||
`user_id` int NOT NULL,
|
`user_id` int NOT NULL,
|
||||||
`photo_id` int NOT NULL,
|
`photo_id` int NOT NULL,
|
||||||
`type` int NOT NULL
|
`type` int NOT NULL
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
|
||||||
-- --------------------------------------------------------
|
-- --------------------------------------------------------
|
||||||
|
|
||||||
|
@ -162,7 +162,7 @@ CREATE TABLE `users` (
|
||||||
`admin` int NOT NULL DEFAULT '0',
|
`admin` int NOT NULL DEFAULT '0',
|
||||||
`status` int NOT NULL DEFAULT '0',
|
`status` int NOT NULL DEFAULT '0',
|
||||||
`content` text NOT NULL
|
`content` text NOT NULL
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Индексы сохранённых таблиц
|
-- Индексы сохранённых таблиц
|
||||||
|
|
|
@ -7,7 +7,7 @@ CREATE TABLE IF NOT EXISTS `entities` (
|
||||||
`sampledata` text NOT NULL,
|
`sampledata` text NOT NULL,
|
||||||
`color` text NOT NULL,
|
`color` text NOT NULL,
|
||||||
PRIMARY KEY (`id`)
|
PRIMARY KEY (`id`)
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS `entities_data` (
|
CREATE TABLE IF NOT EXISTS `entities_data` (
|
||||||
`id` int NOT NULL AUTO_INCREMENT,
|
`id` int NOT NULL AUTO_INCREMENT,
|
||||||
|
@ -17,21 +17,21 @@ CREATE TABLE IF NOT EXISTS `entities_data` (
|
||||||
`comment` text NOT NULL,
|
`comment` text NOT NULL,
|
||||||
`content` text NOT NULL,
|
`content` text NOT NULL,
|
||||||
PRIMARY KEY (`id`)
|
PRIMARY KEY (`id`)
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS `galleries` (
|
CREATE TABLE IF NOT EXISTS `galleries` (
|
||||||
`id` int NOT NULL AUTO_INCREMENT,
|
`id` int NOT NULL AUTO_INCREMENT,
|
||||||
`title` text NOT NULL,
|
`title` text NOT NULL,
|
||||||
`opened` int NOT NULL,
|
`opened` int NOT NULL,
|
||||||
PRIMARY KEY (`id`)
|
PRIMARY KEY (`id`)
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS `photos_favorite` (
|
CREATE TABLE IF NOT EXISTS `photos_favorite` (
|
||||||
`id` int NOT NULL AUTO_INCREMENT,
|
`id` int NOT NULL AUTO_INCREMENT,
|
||||||
`photo_id` int NOT NULL,
|
`photo_id` int NOT NULL,
|
||||||
`user_id` int NOT NULL,
|
`user_id` int NOT NULL,
|
||||||
PRIMARY KEY (`id`)
|
PRIMARY KEY (`id`)
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS `uploadindex_history` (
|
CREATE TABLE IF NOT EXISTS `uploadindex_history` (
|
||||||
`id` int NOT NULL AUTO_INCREMENT,
|
`id` int NOT NULL AUTO_INCREMENT,
|
||||||
|
@ -42,7 +42,7 @@ CREATE TABLE IF NOT EXISTS `uploadindex_history` (
|
||||||
`type` int NOT NULL,
|
`type` int NOT NULL,
|
||||||
`photo_id` int NOT NULL,
|
`photo_id` int NOT NULL,
|
||||||
PRIMARY KEY (`id`)
|
PRIMARY KEY (`id`)
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
|
||||||
-- Изменение существующих таблиц
|
-- Изменение существующих таблиц
|
||||||
|
|
||||||
|
@ -61,7 +61,7 @@ MODIFY COLUMN `online` int NOT NULL DEFAULT '0',
|
||||||
MODIFY COLUMN `admin` int NOT NULL;
|
MODIFY COLUMN `admin` int NOT NULL;
|
||||||
|
|
||||||
-- Обновление кодировки для таблиц, использующих utf8
|
-- Обновление кодировки для таблиц, использующих utf8
|
||||||
ALTER TABLE `followers` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
|
ALTER TABLE `followers` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||||
ALTER TABLE `followers_notifications` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
|
ALTER TABLE `followers_notifications` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||||
ALTER TABLE `news` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
|
ALTER TABLE `news` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||||
ALTER TABLE `photos_views` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
|
ALTER TABLE `photos_views` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
38
sqlcore/sql_0002.sql
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
-- Migration script to update database schema
|
||||||
|
|
||||||
|
-- Add new tables from 222.sql that don't exist in 111.sql
|
||||||
|
CREATE TABLE IF NOT EXISTS `contests` (
|
||||||
|
`id` int(10) NOT NULL AUTO_INCREMENT,
|
||||||
|
`themeid` int(10) NOT NULL,
|
||||||
|
`opendate` int(100) NOT NULL,
|
||||||
|
`closedate` int(10) NOT NULL,
|
||||||
|
`status` int(10) NOT NULL,
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS `geodb` (
|
||||||
|
`id` int(10) NOT NULL AUTO_INCREMENT,
|
||||||
|
`title` text NOT NULL,
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS `servicekeys` (
|
||||||
|
`id` int(10) NOT NULL AUTO_INCREMENT,
|
||||||
|
`token` text NOT NULL,
|
||||||
|
`type` text NOT NULL,
|
||||||
|
`status` int(10) NOT NULL,
|
||||||
|
`content` text NOT NULL,
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
-- Modify existing tables to add new columns
|
||||||
|
-- Using proper ALTER TABLE syntax for MySQL
|
||||||
|
ALTER TABLE `photos` ADD COLUMN `pinnedcomment_id` int(10) NOT NULL DEFAULT 0 AFTER `entitydata_id`;
|
||||||
|
|
||||||
|
-- Set AUTO_INCREMENT values for the new tables
|
||||||
|
ALTER TABLE `contests` AUTO_INCREMENT = 1;
|
||||||
|
ALTER TABLE `geodb` AUTO_INCREMENT = 1;
|
||||||
|
ALTER TABLE `servicekeys` AUTO_INCREMENT = 1;
|
||||||
|
|
||||||
|
-- Commit the changes
|
||||||
|
COMMIT;
|
162
sqlcore/sql_0003.sql
Normal file
|
@ -0,0 +1,162 @@
|
||||||
|
-- Add new tables for contest functionality
|
||||||
|
CREATE TABLE IF NOT EXISTS `contests_pretends` (
|
||||||
|
`id` int(10) NOT NULL AUTO_INCREMENT,
|
||||||
|
`photo_id` int(10) NOT NULL,
|
||||||
|
`contest_id` int(10) NOT NULL,
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS `contests_rates` (
|
||||||
|
`id` int(10) NOT NULL AUTO_INCREMENT,
|
||||||
|
`photo_id` int(10) NOT NULL,
|
||||||
|
`user_id` int(10) NOT NULL,
|
||||||
|
`contest_id` int(10) NOT NULL,
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS `contests_themes` (
|
||||||
|
`id` int(10) NOT NULL AUTO_INCREMENT,
|
||||||
|
`title` text NOT NULL,
|
||||||
|
`status` int(10) NOT NULL,
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS `contests_winners` (
|
||||||
|
`id` int(10) NOT NULL AUTO_INCREMENT,
|
||||||
|
`photo_id` int(10) NOT NULL,
|
||||||
|
`place` int(10) NOT NULL,
|
||||||
|
`contest_id` int(10) NOT NULL,
|
||||||
|
`date` int(10) NOT NULL,
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS `photos_rates_contest` (
|
||||||
|
`id` int(10) NOT NULL AUTO_INCREMENT,
|
||||||
|
`photo_id` int(10) NOT NULL,
|
||||||
|
`user_id` int(10) NOT NULL,
|
||||||
|
`contest_id` int(10) NOT NULL,
|
||||||
|
`type` int(10) NOT NULL,
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
-- Add new pages table
|
||||||
|
CREATE TABLE IF NOT EXISTS `pages` (
|
||||||
|
`id` int(10) NOT NULL AUTO_INCREMENT,
|
||||||
|
`title` text NOT NULL,
|
||||||
|
`body` text NOT NULL,
|
||||||
|
`created_by` int(10) NOT NULL,
|
||||||
|
`created_at` int(10) NOT NULL,
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
-- Modify existing tables
|
||||||
|
|
||||||
|
-- Update contests table
|
||||||
|
SET @s = (SELECT IF(
|
||||||
|
EXISTS(
|
||||||
|
SELECT * FROM INFORMATION_SCHEMA.COLUMNS
|
||||||
|
WHERE TABLE_SCHEMA = DATABASE()
|
||||||
|
AND TABLE_NAME = 'contests'
|
||||||
|
AND COLUMN_NAME = 'openpretendsdate'
|
||||||
|
),
|
||||||
|
'SELECT 1',
|
||||||
|
'ALTER TABLE `contests` ADD COLUMN `openpretendsdate` int(10) NOT NULL AFTER `themeid`'
|
||||||
|
));
|
||||||
|
PREPARE stmt FROM @s;
|
||||||
|
EXECUTE stmt;
|
||||||
|
DEALLOCATE PREPARE stmt;
|
||||||
|
|
||||||
|
SET @s = (SELECT IF(
|
||||||
|
EXISTS(
|
||||||
|
SELECT * FROM INFORMATION_SCHEMA.COLUMNS
|
||||||
|
WHERE TABLE_SCHEMA = DATABASE()
|
||||||
|
AND TABLE_NAME = 'contests'
|
||||||
|
AND COLUMN_NAME = 'closepretendsdate'
|
||||||
|
),
|
||||||
|
'SELECT 1',
|
||||||
|
'ALTER TABLE `contests` ADD COLUMN `closepretendsdate` int(10) NOT NULL AFTER `openpretendsdate`'
|
||||||
|
));
|
||||||
|
PREPARE stmt FROM @s;
|
||||||
|
EXECUTE stmt;
|
||||||
|
DEALLOCATE PREPARE stmt;
|
||||||
|
|
||||||
|
-- Update entities table
|
||||||
|
ALTER TABLE `entities` MODIFY `createdate` bigint(20) NOT NULL;
|
||||||
|
|
||||||
|
-- Update news table
|
||||||
|
ALTER TABLE `news` MODIFY `body` mediumtext NOT NULL;
|
||||||
|
|
||||||
|
-- Update photos table
|
||||||
|
SET @s = (SELECT IF(
|
||||||
|
EXISTS(
|
||||||
|
SELECT * FROM INFORMATION_SCHEMA.COLUMNS
|
||||||
|
WHERE TABLE_SCHEMA = DATABASE()
|
||||||
|
AND TABLE_NAME = 'photos'
|
||||||
|
AND COLUMN_NAME = 'on_contest'
|
||||||
|
),
|
||||||
|
'SELECT 1',
|
||||||
|
'ALTER TABLE `photos` ADD COLUMN `on_contest` int(10) NOT NULL DEFAULT 0 AFTER `pinnedcomment_id`'
|
||||||
|
));
|
||||||
|
PREPARE stmt FROM @s;
|
||||||
|
EXECUTE stmt;
|
||||||
|
DEALLOCATE PREPARE stmt;
|
||||||
|
|
||||||
|
SET @s = (SELECT IF(
|
||||||
|
EXISTS(
|
||||||
|
SELECT * FROM INFORMATION_SCHEMA.COLUMNS
|
||||||
|
WHERE TABLE_SCHEMA = DATABASE()
|
||||||
|
AND TABLE_NAME = 'photos'
|
||||||
|
AND COLUMN_NAME = 'contest_id'
|
||||||
|
),
|
||||||
|
'SELECT 1',
|
||||||
|
'ALTER TABLE `photos` ADD COLUMN `contest_id` int(10) NOT NULL DEFAULT 0 AFTER `on_contest`'
|
||||||
|
));
|
||||||
|
PREPARE stmt FROM @s;
|
||||||
|
EXECUTE stmt;
|
||||||
|
DEALLOCATE PREPARE stmt;
|
||||||
|
|
||||||
|
-- Update charset and collation for tables
|
||||||
|
ALTER TABLE `entities`
|
||||||
|
CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
ALTER TABLE `entities_data`
|
||||||
|
CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
ALTER TABLE `followers`
|
||||||
|
CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
ALTER TABLE `followers_notifications`
|
||||||
|
CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
ALTER TABLE `galleries`
|
||||||
|
CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
ALTER TABLE `news`
|
||||||
|
CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
ALTER TABLE `photos_favorite`
|
||||||
|
CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
ALTER TABLE `photos_views`
|
||||||
|
CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
ALTER TABLE `uploadindex_history`
|
||||||
|
CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
ALTER TABLE `login_tokens`
|
||||||
|
CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
ALTER TABLE `photos`
|
||||||
|
CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
ALTER TABLE `photos_comments`
|
||||||
|
CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
ALTER TABLE `photos_comments_rates`
|
||||||
|
CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
ALTER TABLE `photos_rates`
|
||||||
|
CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
ALTER TABLE `users`
|
||||||
|
CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
BIN
static/2.mp4
7
static/css/jquery-ui-1.8.20.custom.css
vendored
Normal file
115
static/css/mobile.css
Normal file
|
@ -0,0 +1,115 @@
|
||||||
|
body, td, p, li, input, select, optgroup, option, button { font-size:14px; }
|
||||||
|
|
||||||
|
#title { font-family:var(--narrow-font); font-size:32px; padding:5px 7px; position:relative; z-index:2001; }
|
||||||
|
#title img { margin:0 8px 0 -2px; }
|
||||||
|
#title2 { padding-right:5px; }
|
||||||
|
|
||||||
|
.main, .adframe { padding:0 5px 10px; }
|
||||||
|
.footer { padding:10px 5px; }
|
||||||
|
|
||||||
|
.p20, .p20i { padding-left:15px; padding-right:15px; }
|
||||||
|
|
||||||
|
h1 { font-size:24px; }
|
||||||
|
h2 { font-size:20px; }
|
||||||
|
h3 { font-size:17px; }
|
||||||
|
h4 { font-size:17px; margin-bottom:5px; }
|
||||||
|
|
||||||
|
.f, .fv3, .pb-photo, .temp, .hpshade { width:125px; }
|
||||||
|
.fv2, .fv1, .fv, .fv > .f { width:115px; }
|
||||||
|
.pb-photo { padding:5px; }
|
||||||
|
|
||||||
|
.mm-mobile-btn { display:flex; justify-content:center; align-items:center; position:absolute; top:0; right:0; z-index:2002; box-sizing:border-box; width:56px; height:54px; background-color:rgba(0,0,0,0.2); color:#fff; font-size:28px; }
|
||||||
|
.mm-mobile-btn.active { background-color:rgba(255,255,255,0.2); }
|
||||||
|
#mm-user-btn { right:57px; }
|
||||||
|
#mm-bars-btn { right:0; }
|
||||||
|
|
||||||
|
.mm { position:absolute; top:54px; width:100%; z-index:2002; border-bottom:solid 1px var(--theme-bg-color); box-shadow:0 8px 8px #0007; }
|
||||||
|
.mm-bar ul, .mm-bar { list-style-type:none; padding:0; margin:0; }
|
||||||
|
.mm-bar ul { display:none; background:linear-gradient(rgba(0,0,0,0.2),rgba(0,0,0,0.2)) var(--theme-bg-color); }
|
||||||
|
.mm ul { margin:0 10px 7px; }
|
||||||
|
|
||||||
|
.mm-bar-item li { display:flex; flex-direction:column; align-items:center; justify-content:center; position:relative; box-sizing:border-box; border-top:solid 1px var(--theme-bg-color); font-family:var(--narrow-font); font-size:28px; }
|
||||||
|
.mm-bar-item li div { box-sizing:border-box; width:100%; background-color:#eee; }
|
||||||
|
.mm-bar-item li div::before { content:'>'; color:#fff; display:block; position:absolute; top:7px; left:10px; z-index:2003; transform:scaleX(0.8); transition:transform .1s ease-out; }
|
||||||
|
.mm-level-3 > div::before { top:1px; }
|
||||||
|
|
||||||
|
a.mm-item, label.mm-item { color:#fff; }
|
||||||
|
.mm-item { box-sizing:border-box; width:100%; min-height:50px; padding:5px 0; text-align:center; border:none; }
|
||||||
|
.mm-level-2 .mm-item { min-height: 42px; font-size: 22px; }
|
||||||
|
.mm-level-3 .mm-item { min-height: 34px; font-size: 16px; }
|
||||||
|
|
||||||
|
.mm-bar-item label:hover { border:none; }
|
||||||
|
|
||||||
|
.mm-bar-item input[type="checkbox"] { display:none; }
|
||||||
|
.mm-bar-item input[type="checkbox"]:checked + div > ul { display:flex; flex-direction:column; }
|
||||||
|
.mm-bar-item input[type="checkbox"]:checked + div::before { transform:scaleY(0.8) rotate(90deg); }
|
||||||
|
|
||||||
|
span.mm-icon, span.mm-right-icon { display:block; position:absolute; z-index:2003; }
|
||||||
|
.mm-icon { top:7px; left:10px; }
|
||||||
|
.mm-right-icon { top:5px; right:10px; }
|
||||||
|
|
||||||
|
.mm-notify { position: absolute; right: 7px; bottom: 7px; }
|
||||||
|
.mm-level-1 .mm-notify { top: 10px; font-size: 16px; line-height: 16px; height: 30px; min-width: 30px; }
|
||||||
|
.mm-level-2 .mm-notify { top: 9px; font-size: 12px; line-height: 12px; height: 24px; min-width: 24px; }
|
||||||
|
|
||||||
|
|
||||||
|
#idx-main { margin-top:5px; }
|
||||||
|
#idx-column-center { padding:0; }
|
||||||
|
#idx-column-menu { display:none; position:absolute; top:54px; right:0; padding:5px 10px; background-color:#f7f7f7; width:300px; border-left:solid 1px #ddd; border-bottom:solid 1px #ddd; z-index:2001; }
|
||||||
|
|
||||||
|
|
||||||
|
.idx-donate { margin-right:-10px; }
|
||||||
|
.idx-donate > a { padding-right:15px; }
|
||||||
|
|
||||||
|
|
||||||
|
.ix-photos-oneline { width:100vw; min-height:70px; margin:0 -5px 7px; overflow-x:auto; }
|
||||||
|
.ix-photos-oneline:before, .ix-photos-oneline:after { content:''; width:5px; flex-shrink:0; background-color:var(--theme-main-color); }
|
||||||
|
.ix-photos-oneline > a { flex-grow:0; flex-shrink:0; flex-basis:auto; width:100px; }
|
||||||
|
|
||||||
|
.ix-photos-multiline { min-height:210px; margin-bottom:10px; }
|
||||||
|
.ix-photos-multiline > a { flex-basis:100px; }
|
||||||
|
|
||||||
|
.prw-animate, .prw-grid-item { height:70px; }
|
||||||
|
.prw-animate:hover { animation:none; }
|
||||||
|
|
||||||
|
#morerand { top:4px; }
|
||||||
|
#loadmore { height:auto; padding-bottom:4px; margin-bottom:7px; }
|
||||||
|
|
||||||
|
|
||||||
|
.rtable { box-sizing:border-box; width:100vw; margin:0 -5px; overflow-x:auto; }
|
||||||
|
.rtable > :first-child { margin:0 5px; }
|
||||||
|
|
||||||
|
|
||||||
|
[type="text"],
|
||||||
|
[type="password"],
|
||||||
|
[type="color"],
|
||||||
|
[type="date"],
|
||||||
|
[type="datetime"],
|
||||||
|
[type="datetime-local"],
|
||||||
|
[type="email"],
|
||||||
|
[type="number"],
|
||||||
|
[type="search"],
|
||||||
|
[type="tel"],
|
||||||
|
[type="time"],
|
||||||
|
[type="url"],
|
||||||
|
[type="month"],
|
||||||
|
[type="week"],
|
||||||
|
select,
|
||||||
|
textarea {
|
||||||
|
box-shadow:none;
|
||||||
|
-moz-box-shadow:none;
|
||||||
|
-webkit-box-shadow:none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mf-center-block-wide,
|
||||||
|
.mf-center-block-x-wide {
|
||||||
|
width:calc(100% + 10px);
|
||||||
|
margin-left: -5px;
|
||||||
|
margin-right:-5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cmt-showall { display:block; text-align:center; margin-bottom:-5px; }
|
||||||
|
|
||||||
|
.mark-btn { margin-bottom:7px; }
|
||||||
|
.mid-btn { margin:7px 0; }
|
||||||
|
.mark-btn a, .mid-btn a { width:100%; }
|
|
@ -371,10 +371,10 @@ table.nospaces > tbody > tr > td.lcol { padding:2px 6px 0; }
|
||||||
.flag-left { padding-left:26px !important; }
|
.flag-left { padding-left:26px !important; }
|
||||||
.input-flag { margin:-2px -26px 0 5px; position:relative; z-index:11; }
|
.input-flag { margin:-2px -26px 0 5px; position:relative; z-index:11; }
|
||||||
|
|
||||||
.contestBtn { display:block; cursor:pointer; width:56px; height:28px; margin:10px; background:url('/img/vote_contest.gif') no-repeat; opacity:0.7; }
|
.contestBtn { display:block; cursor:pointer; width:56px; height:28px; margin:10px; background:url('/static/img/vote_contest.gif') no-repeat; opacity:0.7; }
|
||||||
.contestBtn:hover { opacity:1; }
|
.contestBtn:hover { opacity:1; }
|
||||||
.contestBtn.voted { opacity:1; background:url('/img/vote_contest_pressed.gif') no-repeat; }
|
.contestBtn.voted { opacity:1; background:url('/static/img/vote_contest_pressed.gif') no-repeat; }
|
||||||
.contestBtn.loading { opacity:1; background:url('/img/vote_contest_loading.gif') no-repeat; }
|
.contestBtn.loading { opacity:1; background:url('/static/img/vote_contest_loading.gif') no-repeat; }
|
||||||
|
|
||||||
.died { border:solid 1px black; padding:0 2px; }
|
.died { border:solid 1px black; padding:0 2px; }
|
||||||
|
|
||||||
|
|
89
static/css/tabs.css
Normal file
|
@ -0,0 +1,89 @@
|
||||||
|
.v-header {
|
||||||
|
/**
|
||||||
|
* Redefine media queries, because header mobile styles are enabled
|
||||||
|
* when page width is less than two-columns layout width (~960px)
|
||||||
|
*/
|
||||||
|
--border-radius: 8px;
|
||||||
|
--offset-x: var(--island-offset-x, 20px);
|
||||||
|
--offset-y: 24px;
|
||||||
|
border-radius: var(--border-radius);
|
||||||
|
padding: var(--offset-y) var(--offset-x);
|
||||||
|
font-size: 16px;
|
||||||
|
line-height: 1.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 999px) {
|
||||||
|
.v-header {
|
||||||
|
--offset-x: var(--island-offset-x, 16px);
|
||||||
|
--offset-y: 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.v-header__tabs {
|
||||||
|
margin-bottom: calc(var(--offset-y)* -1);
|
||||||
|
margin-left: calc(var(--offset-x)* -1);
|
||||||
|
margin-right: calc(var(--offset-x)* -1);
|
||||||
|
}
|
||||||
|
.v-tabs {
|
||||||
|
--height: 63px;
|
||||||
|
--nav-size: 36px;
|
||||||
|
--tab-offset: 12px;
|
||||||
|
font-size: var(--font-size);
|
||||||
|
height: var(--height);
|
||||||
|
position: relative;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
.v-tabs__scroll {
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow-x: hidden;
|
||||||
|
overflow-y: hidden;
|
||||||
|
-webkit-overflow-scrolling: touch;
|
||||||
|
}
|
||||||
|
.v-header__tabs .v-tabs__content {
|
||||||
|
padding-left: var(--offset-x);
|
||||||
|
padding-right: var(--offset-x);
|
||||||
|
}
|
||||||
|
.v-tabs__content {
|
||||||
|
display: -ms-inline-flexbox;
|
||||||
|
display: inline-flex;
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
.v-tab:first-child {
|
||||||
|
padding-left: 0;
|
||||||
|
}
|
||||||
|
.v-tab--active {
|
||||||
|
pointer-events: none;
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
.v-tab {
|
||||||
|
padding: 0 var(--tab-offset);
|
||||||
|
-ms-flex-negative: 0;
|
||||||
|
flex-shrink: 0;
|
||||||
|
cursor: pointer;
|
||||||
|
color: #000000;
|
||||||
|
font-weight: 400;
|
||||||
|
}
|
||||||
|
.v-tab--active .v-tab__label {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
.v-tab__label {
|
||||||
|
display: -ms-flexbox;
|
||||||
|
display: flex;
|
||||||
|
-ms-flex-align: baseline;
|
||||||
|
align-items: baseline;
|
||||||
|
height: var(--height);
|
||||||
|
line-height: calc(var(--height) + 1px);
|
||||||
|
}
|
||||||
|
.v-tab--active .v-tab__label::after {
|
||||||
|
content: '';
|
||||||
|
width: 100%;
|
||||||
|
height: 3px;
|
||||||
|
background-color: #306bff;
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
border-radius: 500px;
|
||||||
|
}
|
||||||
|
.active__block, .active__blockm {
|
||||||
|
display: block !important;
|
||||||
|
transition: 0.3s all;
|
||||||
|
}
|
BIN
static/img/cond.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
static/img/loader_wb.gif
Normal file
After Width: | Height: | Size: 6.7 KiB |
Before Width: | Height: | Size: 300 KiB After Width: | Height: | Size: 215 KiB |
BIN
static/img/star_people.png
Normal file
After Width: | Height: | Size: 528 B |
BIN
static/img/tour1.png
Normal file
After Width: | Height: | Size: 34 KiB |
BIN
static/img/tour2.png
Normal file
After Width: | Height: | Size: 52 KiB |
BIN
static/img/tour3.png
Normal file
After Width: | Height: | Size: 802 KiB |
BIN
static/img/vote_contest.gif
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
static/img/vote_contest_loading.gif
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
static/img/vote_contest_pressed.gif
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
static/img/vs1.png
Normal file
After Width: | Height: | Size: 542 B |
BIN
static/img/vs2.png
Normal file
After Width: | Height: | Size: 494 B |
BIN
static/img/vs3.png
Normal file
After Width: | Height: | Size: 544 B |
|
@ -31,7 +31,7 @@ function createModal(id, type, value, modalid) {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>`;
|
</div>`;
|
||||||
}
|
}
|
||||||
document.body.innerHTML += modal;
|
document.body.innerHTML += modal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,6 +59,50 @@ document.addEventListener("click", function(event) {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const pinComment = (postId) => {
|
||||||
|
$(document).ready(function() {
|
||||||
|
$.ajax({
|
||||||
|
type: "POST",
|
||||||
|
url: '/api/photo/comment/'+postId+'/pin',
|
||||||
|
success: function(response) {
|
||||||
|
var jsonData = JSON.parse(response);
|
||||||
|
|
||||||
|
console.log(response);
|
||||||
|
if (jsonData.errorcode == "1") {
|
||||||
|
Notify.noty('danger', JSON.stringify(response));
|
||||||
|
} else {
|
||||||
|
if (jsonData.action == "pin") {
|
||||||
|
Notify.noty('success', 'Успешно закреплено!');
|
||||||
|
} else {
|
||||||
|
Notify.noty('success', 'Успешно откреплено!');
|
||||||
|
}
|
||||||
|
|
||||||
|
const url = window.location.pathname;
|
||||||
|
const segments = url.split('/');
|
||||||
|
const id = segments[2];
|
||||||
|
console.log(segments);
|
||||||
|
$.ajax({
|
||||||
|
|
||||||
|
|
||||||
|
type: "POST",
|
||||||
|
url: "/api/photo/getcomments/"+id,
|
||||||
|
processData: false,
|
||||||
|
async: true,
|
||||||
|
success: function(r) {
|
||||||
|
$('#posts').html(r)
|
||||||
|
|
||||||
|
|
||||||
|
},
|
||||||
|
error: function(r) {
|
||||||
|
console.log(r)
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const editComment = (postId, body, modalid) => {
|
const editComment = (postId, body, modalid) => {
|
||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
|
@ -78,7 +122,7 @@ const editComment = (postId, body, modalid) => {
|
||||||
Notify.noty('success', 'Успешно отредактировано!');
|
Notify.noty('success', 'Успешно отредактировано!');
|
||||||
const url = window.location.pathname;
|
const url = window.location.pathname;
|
||||||
const segments = url.split('/');
|
const segments = url.split('/');
|
||||||
const id = segments[segments.length - 1];
|
const id = segments[2];
|
||||||
$.ajax({
|
$.ajax({
|
||||||
|
|
||||||
|
|
||||||
|
|
39
static/js/changeTab.js
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
function changeTab(id) {
|
||||||
|
const $activeTabs = $('.v-tab-b.v-tab--active');
|
||||||
|
const $activeBlocks = $('.active__block');
|
||||||
|
const $newTab = $('#' + id);
|
||||||
|
|
||||||
|
if ($activeTabs.length) {
|
||||||
|
$activeTabs.removeClass('v-tab--active');
|
||||||
|
}
|
||||||
|
|
||||||
|
$newTab.addClass('v-tab--active');
|
||||||
|
|
||||||
|
if ($activeBlocks.length) {
|
||||||
|
$activeBlocks.stop(true, true).animate({
|
||||||
|
opacity: 0,
|
||||||
|
}, 200, function () {
|
||||||
|
$(this).css('display', 'none').removeClass('active__block');
|
||||||
|
|
||||||
|
const $newBlock = $('#' + id + '__block');
|
||||||
|
$newBlock.css({
|
||||||
|
display: 'block',
|
||||||
|
opacity: 0
|
||||||
|
}).animate({
|
||||||
|
opacity: 1
|
||||||
|
}, 150, function () {
|
||||||
|
$(this).addClass('active__block');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// Если нет активных блоков, сразу показываем новый блок
|
||||||
|
$('#' + id + '__block').css({
|
||||||
|
display: 'block',
|
||||||
|
opacity: 0
|
||||||
|
}).animate({
|
||||||
|
opacity: 1
|
||||||
|
}, 150, function () {
|
||||||
|
$(this).addClass('active__block');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -165,8 +165,20 @@ $(document).ready(function()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
var placeElement = document.getElementById('place');
|
||||||
|
if (placeElement) {
|
||||||
|
$('#place').autocompleteHL({
|
||||||
|
minLength: 3,
|
||||||
|
source: function(request, response)
|
||||||
|
{
|
||||||
|
var cid = $('#search_cid').val();
|
||||||
|
if (cid != 0)
|
||||||
|
$.getJSON('/api/geodb/search', { place: request.term }, response).fail(function(jx) { alert(jx.responseText); });
|
||||||
|
else response(null);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
$('#image').click(function()
|
$('#image').click(function()
|
||||||
|
@ -223,7 +235,6 @@ $(document).ready(function()
|
||||||
$('#day, #month, #year').on('change', function() { $('#dateAbsent').hide(); });
|
$('#day, #month, #year').on('change', function() { $('#dateAbsent').hide(); });
|
||||||
|
|
||||||
|
|
||||||
$('#search_type').on('change', function() { changeColor(this); }).change();
|
|
||||||
|
|
||||||
|
|
||||||
// Комментарий
|
// Комментарий
|
||||||
|
@ -318,7 +329,7 @@ document.onclick = function(e)
|
||||||
{
|
{
|
||||||
e = e || window.event;
|
e = e || window.event;
|
||||||
E = e.target || e.srcElement;
|
E = e.target || e.srcElement;
|
||||||
if (E.id != 'phint' && E.parentNode.id != 'phint' && E != _getID('mform').place) $('#phint').slideUp();
|
|
||||||
|
|
||||||
if (E.className != 'searchVehiclesBtn' && E.id != 'vlist_table' && E.className != 'num' && $('#vlist').css('display') == 'block') $('#vlist').hide().html('');
|
if (E.className != 'searchVehiclesBtn' && E.id != 'vlist_table' && E.className != 'num' && $('#vlist').css('display') == 'block') $('#vlist').hide().html('');
|
||||||
|
|
||||||
|
@ -349,6 +360,7 @@ function artClick()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function loadGalleries(cid)
|
function loadGalleries(cid)
|
||||||
{
|
{
|
||||||
if (cid == gal_cid) return;
|
if (cid == gal_cid) return;
|
||||||
|
@ -414,7 +426,6 @@ function setDate(d, m, y)
|
||||||
function showHint(id) { $('#'+id+'_hint').fadeIn() }
|
function showHint(id) { $('#'+id+'_hint').fadeIn() }
|
||||||
function hideHint(id) { $('#'+id+'_hint').fadeOut() }
|
function hideHint(id) { $('#'+id+'_hint').fadeOut() }
|
||||||
|
|
||||||
function changeColor(sel) { sel.className = sel.options[sel.selectedIndex].className }
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -121,7 +121,7 @@ function searchVehicles()
|
||||||
|
|
||||||
function AddPhotoToBlock(block, arr, prepend)
|
function AddPhotoToBlock(block, arr, prepend)
|
||||||
{
|
{
|
||||||
block[prepend ? 'prepend' : 'append']('<div class="prw-grid-item"><div class="prw-wrapper">' + arr.links + '<div>' + arr.pdate + '</div></div><a href="/photo/' + arr.pid + '/" target="_blank" class="prw-animate" style="background-image:url(\'' + arr.prw + '\')">' + (arr.ccnt != 0 ? '<div class="hdshade"><div class="com-icon">' + arr.ccnt + '</div></div>' : '') + '</a></div>');
|
block[prepend ? 'prepend' : 'append']('<div class="prw-grid-item"><div class="prw-wrapper">' + arr.place + '<div>' + arr.date + '</div></div><a href="/photo/' + arr.id + '/" target="_blank" class="prw-animate" style="background-image:url(\'' + arr.photourl_small + '\')">' + (arr.ccnt != 0 ? '<div class="hdshade"><div class="com-icon">' + arr.ccnt + '</div></div>' : '') + '</a></div>');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -166,24 +166,59 @@ function LoadRecentPhotos()
|
||||||
|
|
||||||
loadmore.prop('disabled', true).addClass('loader-button').val(' ');
|
loadmore.prop('disabled', true).addClass('loader-button').val(' ');
|
||||||
|
|
||||||
$.getJSON('/api.php', { action: 'get-recent-photos', width: width, lastpid: lastpid, hidden: hidden.length }, function(data)
|
$.getJSON('/api/photo/loadrecent', { lastpid: lastpid }, function(data)
|
||||||
{
|
{
|
||||||
if (data)
|
if (data)
|
||||||
{
|
{
|
||||||
if (lastpid == 0) recent.attr('firstpid', data[0].pid);
|
if (lastpid == 0) recent.attr('firstpid', data[0].id);
|
||||||
hidden.show();
|
hidden.show();
|
||||||
|
|
||||||
for (var i = 0; i < data.length; i++) AddPhotoToBlock(recent, data[i]);
|
for (var i = 0; i < data.length; i++) AddPhotoToBlock(recent, data[i]);
|
||||||
recent.attr('lastpid', data[i-1].pid);
|
recent.attr('lastpid', data[i-1].id);
|
||||||
}
|
}
|
||||||
else recent.append('Load error');
|
else recent.append('Load error');
|
||||||
|
|
||||||
loadmore.prop('disabled', false).removeClass('loader-button').val(_text['IX_LOADMORE']);
|
loadmore.prop('disabled', false).removeClass('loader-button').val('Загрузить ещё');
|
||||||
})
|
})
|
||||||
.fail(function(jx) { if (jx.responseText != '') console.log(jx.responseText); });
|
.fail(function(jx) { if (jx.responseText != '') console.log(jx.responseText); });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function startCountdown(unixTimestamp) {
|
||||||
|
function padZero(num) {
|
||||||
|
return num < 10 ? '0' + num : num;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getWord(num, words) {
|
||||||
|
if (num % 10 === 1 && num % 100 !== 11) return words[0];
|
||||||
|
if (num % 10 >= 2 && num % 10 <= 4 && (num % 100 < 10 || num % 100 >= 20)) return words[1];
|
||||||
|
return words[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateTimer() {
|
||||||
|
const now = Math.floor(Date.now() / 1000);
|
||||||
|
const diff = unixTimestamp - now;
|
||||||
|
|
||||||
|
if (diff <= 0) {
|
||||||
|
clearInterval(interval);
|
||||||
|
document.getElementById('countdown').textContent = "00 дней 00 часов 00 минут 00 секунд";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const days = Math.floor(diff / 86400);
|
||||||
|
const hours = Math.floor((diff % 86400) / 3600);
|
||||||
|
const minutes = Math.floor((diff % 3600) / 60);
|
||||||
|
const seconds = diff % 60;
|
||||||
|
|
||||||
|
document.getElementById('countdown').textContent =
|
||||||
|
`${padZero(days)} ${getWord(days, ['день', 'дня', 'дней'])} ` +
|
||||||
|
`${padZero(hours)} ${getWord(hours, ['час', 'часа', 'часов'])} ` +
|
||||||
|
`${padZero(minutes)} ${getWord(minutes, ['минута', 'минуты', 'минут'])} ` +
|
||||||
|
`${padZero(seconds)} ${getWord(seconds, ['секунда', 'секунды', 'секунд'])}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
updateTimer(); // сразу обновляем отображение
|
||||||
|
const interval = setInterval(updateTimer, 1000);
|
||||||
|
}
|
||||||
|
|
||||||
function LoadPubPhotos()
|
function LoadPubPhotos()
|
||||||
{
|
{
|
||||||
|
|
|
@ -87,9 +87,8 @@ $(document).ready(function()
|
||||||
}
|
}
|
||||||
|
|
||||||
$('#votes').html(html)[html == '' ? 'hide' : 'show']();
|
$('#votes').html(html)[html == '' ? 'hide' : 'show']();
|
||||||
|
$('.vote[pid="' + pid + '"][vote="1"]')[data.buttons.posbtn ? 'addClass' : 'removeClass']('voted');
|
||||||
$('.vote_btn[vote="1"]')[data.buttons[1] ? 'addClass' : 'removeClass']('voted');
|
$('.vote[pid="' + pid + '"][vote="0"]')[data.buttons.negbtn ? 'addClass' : 'removeClass']('voted')
|
||||||
$('.vote_btn[vote="0"]')[data.buttons[0] ? 'addClass' : 'removeClass']('voted');
|
|
||||||
|
|
||||||
var rating = parseInt(data.rating);
|
var rating = parseInt(data.rating);
|
||||||
if (rating > 0) $('#rating').html('+' + rating); else
|
if (rating > 0) $('#rating').html('+' + rating); else
|
||||||
|
@ -119,7 +118,7 @@ $(document).ready(function()
|
||||||
if (vote != 0 && vote != 1 || $(this).is('.locked')) return false;
|
if (vote != 0 && vote != 1 || $(this).is('.locked')) return false;
|
||||||
|
|
||||||
var pid = $(this).closest('.vote').attr('pid');
|
var pid = $(this).closest('.vote').attr('pid');
|
||||||
|
var cid = $(this).closest('.vote').attr('cid');
|
||||||
var savedClass1 = $('.vote[pid="' + pid + '"] .konk_btn[vote="1"]').attr('class');
|
var savedClass1 = $('.vote[pid="' + pid + '"] .konk_btn[vote="1"]').attr('class');
|
||||||
var savedClass0 = $('.vote[pid="' + pid + '"] .konk_btn[vote="0"]').attr('class');
|
var savedClass0 = $('.vote[pid="' + pid + '"] .konk_btn[vote="0"]').attr('class');
|
||||||
|
|
||||||
|
@ -127,19 +126,19 @@ $(document).ready(function()
|
||||||
|
|
||||||
$(this).toggleClass('voted');
|
$(this).toggleClass('voted');
|
||||||
if ($(this).is('.voted')) $('.vote[pid="' + pid + '"] .konk_btn[vote="' + Number(!Number(vote)) + '"]').removeClass('voted');
|
if ($(this).is('.voted')) $('.vote[pid="' + pid + '"] .konk_btn[vote="' + Number(!Number(vote)) + '"]').removeClass('voted');
|
||||||
|
var self_p = 0;
|
||||||
if (!self_p) // Чужие фото
|
if (!self_p) // Чужие фото
|
||||||
{
|
{
|
||||||
$(this).closest('.p20p').removeAttr('class').css('padding', '6px 6px 5px');
|
$(this).closest('.p20p').removeAttr('class').css('padding', '6px 6px 5px');
|
||||||
|
|
||||||
$.getJSON('/api.php', { action: 'vote-konk', pid: pid, vote: vote }, function (data)
|
$.getJSON('/api/photo/vote', { action: 'vote-konk', pid: pid, vote: vote, cid: cid }, function (data)
|
||||||
{
|
{
|
||||||
if (data && !data.errors)
|
if (data && !data.errors)
|
||||||
{
|
{
|
||||||
$('.star[pid="' + pid + '"]').html(data.star ? '<img src="/img/star_' + data.star + '.png" alt="" />' : '');
|
$('.star[pid="' + pid + '"]').html(data.star ? '<img src="/img/star_' + data.star + '.png" alt="" />' : '');
|
||||||
|
$('.vote[pid="' + pid + '"] .konk_btn[vote="1"]')[data.buttons.posbtn_contest ? 'addClass' : 'removeClass']('voted');
|
||||||
|
$('.vote[pid="' + pid + '"] .konk_btn[vote="0"]')[data.buttons.negbtn_contest ? 'addClass' : 'removeClass']('voted');
|
||||||
|
|
||||||
$('.vote[pid="' + pid + '"] .konk_btn[vote="1"]')[data.buttons[1] ? 'addClass' : 'removeClass']('voted');
|
|
||||||
$('.vote[pid="' + pid + '"] .konk_btn[vote="0"]')[data.buttons[0] ? 'addClass' : 'removeClass']('voted');
|
|
||||||
|
|
||||||
var rat = $('.s_rating[pid="' + pid + '"]');
|
var rat = $('.s_rating[pid="' + pid + '"]');
|
||||||
if (rat.length)
|
if (rat.length)
|
||||||
|
@ -164,14 +163,14 @@ $(document).ready(function()
|
||||||
}
|
}
|
||||||
else // Свои фото
|
else // Свои фото
|
||||||
{
|
{
|
||||||
$.getJSON('/api.php', { action: 'vote-author', pid: pid, vote: vote }, function (data)
|
$.getJSON('/api/photo/vote', { action: 'vote-author', pid: pid, vote: vote }, function (data)
|
||||||
{
|
{
|
||||||
if (data && !data.errors)
|
if (data && !data.errors)
|
||||||
{
|
{
|
||||||
$('#star[pid="' + pid + '"]').html(data.star ? '<img src="/img/star_' + data.star + '.png" alt="" />' : '');
|
$('#star[pid="' + pid + '"]').html(data.star ? '<img src="/img/star_' + data.star + '.png" alt="" />' : '');
|
||||||
|
|
||||||
$('.konk_btn[vote="1"]')[data.buttons[1] ? 'addClass' : 'removeClass']('voted');
|
$('.vote[pid="' + pid + '"] .konk_btn[vote="1"]')[data.buttons.posbtn_contest ? 'addClass' : 'removeClass']('voted');
|
||||||
$('.konk_btn[vote="0"]')[data.buttons[0] ? 'addClass' : 'removeClass']('voted');
|
$('.vote[pid="' + pid + '"] .konk_btn[vote="0"]')[data.buttons.negbtn_contest ? 'addClass' : 'removeClass']('voted');
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -4,7 +4,7 @@ use \App\Core\Page;
|
||||||
use \App\Services\DB;
|
use \App\Services\DB;
|
||||||
$nonreviewedimgs = DB::query('SELECT COUNT(*) FROM photos WHERE moderated=0')[0]['COUNT(*)'];
|
$nonreviewedimgs = DB::query('SELECT COUNT(*) FROM photos WHERE moderated=0')[0]['COUNT(*)'];
|
||||||
if ($nonreviewedimgs > 0) {
|
if ($nonreviewedimgs > 0) {
|
||||||
$nonr = '<span class="mm-notify notify-count">'.$nonreviewedimgs.'</span>';
|
$nonr = '<span class="badge text-bg-danger">'.$nonreviewedimgs.'</span>';
|
||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
<link rel="stylesheet" href="https://rsms.me/inter/inter.css">
|
<link rel="stylesheet" href="https://rsms.me/inter/inter.css">
|
||||||
|
@ -15,11 +15,13 @@ body {
|
||||||
}
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
<script src="/static/js/changeTab.js" defer></script>
|
||||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/boxicons@latest/css/boxicons.min.css">
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/boxicons@latest/css/boxicons.min.css">
|
||||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-gH2yIJqKdNHPEq0n4Mqa/HGKIhSkIHeL5AyhkYV8i59U5AR6csBvApHHNl/vI1Bx" crossorigin="anonymous">
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-gH2yIJqKdNHPEq0n4Mqa/HGKIhSkIHeL5AyhkYV8i59U5AR6csBvApHHNl/vI1Bx" crossorigin="anonymous">
|
||||||
<script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.11.5/dist/umd/popper.min.js" integrity="sha384-Xe+8cL9oJa6tN/veChSP7q+mnSPaj5Bcu9mPX5F5xIGE0DVittaqT5lorf0EI7Vk" crossorigin="anonymous"></script>
|
<script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.11.5/dist/umd/popper.min.js" integrity="sha384-Xe+8cL9oJa6tN/veChSP7q+mnSPaj5Bcu9mPX5F5xIGE0DVittaqT5lorf0EI7Vk" crossorigin="anonymous"></script>
|
||||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0/dist/js/bootstrap.min.js" integrity="sha384-ODmDIVzN+pFdexxHEHFBQH3/9/vQ9uori45z4JjnFsRydbmQbmL5t1tQ0culUzyK" crossorigin="anonymous"></script>
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0/dist/js/bootstrap.min.js" integrity="sha384-ODmDIVzN+pFdexxHEHFBQH3/9/vQ9uori45z4JjnFsRydbmQbmL5t1tQ0culUzyK" crossorigin="anonymous"></script>
|
||||||
<link rel="stylesheet" href="/static/css/header.admin.css">
|
<link rel="stylesheet" href="/static/css/header.admin.css">
|
||||||
|
<link rel="stylesheet" href="/static/css/tabs.css">
|
||||||
<div class="layout__left-column layout__sticky">
|
<div class="layout__left-column layout__sticky">
|
||||||
<header style="background-color: #0d1012;" class="header">
|
<header style="background-color: #0d1012;" class="header">
|
||||||
<div class="header__container">
|
<div class="header__container">
|
||||||
|
@ -37,7 +39,7 @@ body {
|
||||||
|
|
||||||
<nav class="nav__container">
|
<nav class="nav__container">
|
||||||
<div>
|
<div>
|
||||||
<a href="#" class="nav__link nav__logo">
|
<a href="/admin" class="nav__link nav__logo">
|
||||||
<h5><b><?=NGALLERY['root']['title']?></b></h5>
|
<h5><b><?=NGALLERY['root']['title']?></b></h5>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
|
@ -56,7 +58,7 @@ body {
|
||||||
</a>
|
</a>
|
||||||
<a href="/admin?type=Photo" class="nav__link">
|
<a href="/admin?type=Photo" class="nav__link">
|
||||||
<i class="bx bx-camera nav__icon"></i>
|
<i class="bx bx-camera nav__icon"></i>
|
||||||
<span class="nav__name">Фотографии</span>
|
<span class="nav__name">Фотографии<?=$nonr?></span>
|
||||||
</a>
|
</a>
|
||||||
<a href="/admin?type=Galleries" class="nav__link">
|
<a href="/admin?type=Galleries" class="nav__link">
|
||||||
<i class="bx bx-images nav__icon"></i>
|
<i class="bx bx-images nav__icon"></i>
|
||||||
|
@ -66,6 +68,10 @@ body {
|
||||||
<i class="bx bx-news nav__icon"></i>
|
<i class="bx bx-news nav__icon"></i>
|
||||||
<span class="nav__name">Новости сайта</span>
|
<span class="nav__name">Новости сайта</span>
|
||||||
</a>
|
</a>
|
||||||
|
<a href="/admin?type=Contests" class="nav__link">
|
||||||
|
<i class="bx bx-party nav__icon"></i>
|
||||||
|
<span class="nav__name">Фотоконкурсы <span class="badge text-bg-warning">BETA</span></span>
|
||||||
|
</a>
|
||||||
<a href="/admin?type=Entities" class="nav__link">
|
<a href="/admin?type=Entities" class="nav__link">
|
||||||
<i class="bx bx-package nav__icon"></i>
|
<i class="bx bx-package nav__icon"></i>
|
||||||
<span class="nav__name">Сущности</span>
|
<span class="nav__name">Сущности</span>
|
||||||
|
@ -74,7 +80,18 @@ body {
|
||||||
<i class="bx bx-data nav__icon"></i>
|
<i class="bx bx-data nav__icon"></i>
|
||||||
<span class="nav__name">База моделей</span>
|
<span class="nav__name">База моделей</span>
|
||||||
</a>
|
</a>
|
||||||
|
<a href="/admin?type=GeoDB" class="nav__link">
|
||||||
|
<i class="bx bx-world nav__icon"></i>
|
||||||
|
<span class="nav__name">GeoDB<span class="badge text-bg-warning">BETA</span></span>
|
||||||
|
</a>
|
||||||
|
<!--a href="/admin?type=Pages" class="nav__link">
|
||||||
|
<i class="bx bx-file-blank nav__icon"></i>
|
||||||
|
<span class="nav__name">Страницы</span>
|
||||||
|
</!--a-->
|
||||||
|
<a href="/admin?type=Settings" class="nav__link">
|
||||||
|
<i class="bx bx-cog nav__icon"></i>
|
||||||
|
<span class="nav__name">Настройки<span class="badge text-bg-warning">BETA</span></span>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<meta http-equiv="content-type" content="text/html;charset=UTF-8">
|
<meta http-equiv="content-type" content="text/html;charset=UTF-8">
|
||||||
<meta name="viewport" content="width=1000,user-scalable=yes">
|
<meta name="viewport" content="width=1000,user-scalable=yes">
|
||||||
<title>NativeGallery</title>
|
<title><?=NGALLERY['root']['title']?></title>
|
||||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||||
<link href="https://fonts.googleapis.com/css2?family=PT+Sans+Narrow:wght@400;700&display=swap" rel="stylesheet">
|
<link href="https://fonts.googleapis.com/css2?family=PT+Sans+Narrow:wght@400;700&display=swap" rel="stylesheet">
|
||||||
|
@ -12,11 +12,14 @@
|
||||||
<link rel="stylesheet" href="/static/css/notie.css<?php if (NGALLERY['root']['cloudflare-caching'] === true) { echo '?'.time(); } ?>">
|
<link rel="stylesheet" href="/static/css/notie.css<?php if (NGALLERY['root']['cloudflare-caching'] === true) { echo '?'.time(); } ?>">
|
||||||
<link rel="stylesheet" href="/static/css/comments.css<?php if (NGALLERY['root']['cloudflare-caching'] === true) { echo '?'.time(); } ?>">
|
<link rel="stylesheet" href="/static/css/comments.css<?php if (NGALLERY['root']['cloudflare-caching'] === true) { echo '?'.time(); } ?>">
|
||||||
<link rel="stylesheet" href="/static/css/map.css<?php if (NGALLERY['root']['cloudflare-caching'] === true) { echo '?'.time(); } ?>">
|
<link rel="stylesheet" href="/static/css/map.css<?php if (NGALLERY['root']['cloudflare-caching'] === true) { echo '?'.time(); } ?>">
|
||||||
|
<link rel="stylesheet" href="/static/css/jquery-ui-1.8.20.custom.css<?php if (NGALLERY['root']['cloudflare-caching'] === true) { echo '?'.time(); } ?>">
|
||||||
<script src="/static/js/jquery.js<?php if (NGALLERY['root']['cloudflare-caching'] === true) { echo '?'.time(); } ?>"></script>
|
<script src="/static/js/jquery.js<?php if (NGALLERY['root']['cloudflare-caching'] === true) { echo '?'.time(); } ?>"></script>
|
||||||
<script src="/static/js/jquery-ui.js<?php if (NGALLERY['root']['cloudflare-caching'] === true) { echo '?'.time(); } ?>"></script>
|
|
||||||
<script src="/static/js/jquery.form.min.js<?php if (NGALLERY['root']['cloudflare-caching'] === true) { echo '?'.time(); } ?>"></script>
|
<script src="/static/js/jquery.form.min.js<?php if (NGALLERY['root']['cloudflare-caching'] === true) { echo '?'.time(); } ?>"></script>
|
||||||
<script src="/static/js/core.js<?php if (NGALLERY['root']['cloudflare-caching'] === true) { echo '?'.time(); } ?>"></script>
|
<script src="/static/js/core.js<?php if (NGALLERY['root']['cloudflare-caching'] === true) { echo '?'.time(); } ?>"></script>
|
||||||
<script src="/static/js/core_lk.js<?php if (NGALLERY['root']['cloudflare-caching'] === true) { echo '?'.time(); } ?>"></script>
|
<script src="/static/js/index.js<?php if (NGALLERY['root']['cloudflare-caching'] === true) { echo '?'.time(); } ?>"></script>
|
||||||
|
<script src="/static/js/jquery-ui.js<?php if (NGALLERY['root']['cloudflare-caching'] === true) { echo '?'.time(); } ?>"></script>
|
||||||
|
<script src="/static/js/selector.js<?php if (NGALLERY['root']['cloudflare-caching'] === true) { echo '?'.time(); } ?>"></script>
|
||||||
|
<script src="/static/js/selector2.js<?php if (NGALLERY['root']['cloudflare-caching'] === true) { echo '?'.time(); } ?>"></script>
|
||||||
<script src="/static/js/imageupload.js<?php if (NGALLERY['root']['cloudflare-caching'] === true) { echo '?'.time(); } ?>"></script>
|
<script src="/static/js/imageupload.js<?php if (NGALLERY['root']['cloudflare-caching'] === true) { echo '?'.time(); } ?>"></script>
|
||||||
<script src="/static/js/progress.js<?php if (NGALLERY['root']['cloudflare-caching'] === true) { echo '?'.time(); } ?>"></script>
|
<script src="/static/js/progress.js<?php if (NGALLERY['root']['cloudflare-caching'] === true) { echo '?'.time(); } ?>"></script>
|
||||||
<script src="/static/js/notie.js<?php if (NGALLERY['root']['cloudflare-caching'] === true) { echo '?'.time(); } ?>"></script>
|
<script src="/static/js/notie.js<?php if (NGALLERY['root']['cloudflare-caching'] === true) { echo '?'.time(); } ?>"></script>
|
||||||
|
@ -24,9 +27,9 @@
|
||||||
<script src="/static/js/comments.js<?php if (NGALLERY['root']['cloudflare-caching'] === true) { echo '?'.time(); } ?>"></script>
|
<script src="/static/js/comments.js<?php if (NGALLERY['root']['cloudflare-caching'] === true) { echo '?'.time(); } ?>"></script>
|
||||||
<script src="/static/js/newcore.js<?php if (NGALLERY['root']['cloudflare-caching'] === true) { echo '?'.time(); } ?>"></script>
|
<script src="/static/js/newcore.js<?php if (NGALLERY['root']['cloudflare-caching'] === true) { echo '?'.time(); } ?>"></script>
|
||||||
<script src="/static/js/act.js<?php if (NGALLERY['root']['cloudflare-caching'] === true) { echo '?'.time(); } ?>"></script>
|
<script src="/static/js/act.js<?php if (NGALLERY['root']['cloudflare-caching'] === true) { echo '?'.time(); } ?>"></script>
|
||||||
<script src="/static/js/selector2.js<?php if (NGALLERY['root']['cloudflare-caching'] === true) { echo '?'.time(); } ?>"></script>
|
<script src="/static/js/core_lk.js<?php if (NGALLERY['root']['cloudflare-caching'] === true) { echo '?'.time(); } ?>"></script>
|
||||||
<script src="/static/js/selector.js<?php if (NGALLERY['root']['cloudflare-caching'] === true) { echo '?'.time(); } ?>"></script>
|
|
||||||
<script src="/static/js/tablesort.js<?php if (NGALLERY['root']['cloudflare-caching'] === true) { echo '?'.time(); } ?>"></script>
|
<script src="/static/js/tablesort.js<?php if (NGALLERY['root']['cloudflare-caching'] === true) { echo '?'.time(); } ?>"></script>
|
||||||
|
<link href='https://unpkg.com/boxicons@2.1.4/css/boxicons.min.css' rel='stylesheet'>
|
||||||
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
|
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
|
||||||
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/themes/smoothness/jquery-ui.css">
|
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/themes/smoothness/jquery-ui.css">
|
||||||
<div class="progress-container fixed-top">
|
<div class="progress-container fixed-top">
|
||||||
|
|
|
@ -28,6 +28,12 @@ if ($noncheckedimgs > 0) {
|
||||||
|
|
||||||
?>
|
?>
|
||||||
<tr>
|
<tr>
|
||||||
|
<?php
|
||||||
|
if (NGALLERY['root']['registration']['emailverify'] === true && $user->i('status') === 3) { ?>
|
||||||
|
<div class="label-orange" style="padding:10px; margin:0 -20px; color:#fff">
|
||||||
|
<center><h4 style="color:#fff; margin-bottom:3px">Пожалуйста, подтвердите свою почту</h4>
|
||||||
|
<div>Так мы сможем убедиться, что Вы настоящий человек. После подтверждения, Вам будет доступен полностью функционал сайта.<br><br><b>Письмо с ссылкой для подтверждения почты была отправлена на Ваш ящик, указанный при регистрации.</b></div></center></div>
|
||||||
|
<?php } ?>
|
||||||
<td class="mm-bar">
|
<td class="mm-bar">
|
||||||
<?php
|
<?php
|
||||||
if (explode('/', $_SERVER['REQUEST_URI'])[1] === 'photo') { ?>
|
if (explode('/', $_SERVER['REQUEST_URI'])[1] === 'photo') { ?>
|
||||||
|
@ -45,7 +51,7 @@ if ($noncheckedimgs > 0) {
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
<li><a href="/comments.php" class="mm-item"><span class="mm-label">Комментарии</span></a></li>
|
<li><a href="/comments" class="mm-item"><span class="mm-label">Комментарии</span></a></li>
|
||||||
<li><a href="#" onclick="return false" class="mm-item"><span class="mm-label">Обновления</span><?=$nonrw?></a>
|
<li><a href="#" onclick="return false" class="mm-item"><span class="mm-label">Обновления</span><?=$nonrw?></a>
|
||||||
<div>
|
<div>
|
||||||
<ul class="mm-level-2">
|
<ul class="mm-level-2">
|
||||||
|
@ -100,11 +106,13 @@ if ($noncheckedimgs > 0) {
|
||||||
?>
|
?>
|
||||||
|
|
||||||
<li><a href="/admin" class="mm-item"><span class="mm-icon"><i class="fas fa-sm fa-fw fa-info-circle"></i></span><span class="mm-label">Admin</span><?=$nonr?></a></li>
|
<li><a href="/admin" class="mm-item"><span class="mm-icon"><i class="fas fa-sm fa-fw fa-info-circle"></i></span><span class="mm-label">Admin</span><?=$nonr?></a></li>
|
||||||
<?php } ?>
|
<?php }
|
||||||
|
if (NGALLERY['root']['registration']['emailverify'] != true || $user->i('status') != 3) { ?>
|
||||||
<li><a href="/lk/upload" class="mm-item"><span class="mm-icon"><i class="fas fa-sm fa-fw fa-plus-square"></i></span><span class="mm-label"><b>Предложить медиа</b></span></a></li>
|
<li><a href="/lk/upload" class="mm-item"><span class="mm-icon"><i class="fas fa-sm fa-fw fa-plus-square"></i></span><span class="mm-label"><b>Предложить медиа</b></span></a></li>
|
||||||
|
<?php } ?>
|
||||||
<li><a href="/lk/history" class="mm-item"><span class="mm-icon"><i class="fas fa-sm fa-fw fa-images"></i></span><span class="mm-label">Журнал</span></a></li>
|
<li><a href="/lk/history" class="mm-item"><span class="mm-icon"><i class="fas fa-sm fa-fw fa-images"></i></span><span class="mm-label">Журнал</span></a></li>
|
||||||
<li><a href="/lk/konkurs.php" class="mm-item"><span class="mm-icon"><i class="fas fa-sm fa-fw fa-compass"></i></span><span class="mm-label">Конкурс</span></a></li>
|
<li><a href="/lk/konkurs.php" class="mm-item"><span class="mm-icon"><i class="fas fa-sm fa-fw fa-compass"></i></span><span class="mm-label">Конкурс</span></a></li>
|
||||||
<li><a href="/lk/vehicles.php" class="mm-item"><span class="mm-icon"><i class="fas fa-sm fa-fw fa-folder-plus"></i></span><span class="mm-label"><b>Правка БД</b></span></a></li>
|
<li><a href="/vehicle/edit" class="mm-item"><span class="mm-icon"><i class="fas fa-sm fa-fw fa-folder-plus"></i></span><span class="mm-label"><b>Правка БД</b></span></a></li>
|
||||||
<li><a href="/lk/ticket.php" class="mm-item"><span class="mm-icon"><i class="fas fa-sm fa-fw fa-question-circle"></i></span><span class="mm-label">Мои заявки</span></a></li>
|
<li><a href="/lk/ticket.php" class="mm-item"><span class="mm-icon"><i class="fas fa-sm fa-fw fa-question-circle"></i></span><span class="mm-label">Мои заявки</span></a></li>
|
||||||
<li><a href="/lk/profile" class="mm-item"><span class="mm-icon"><i class="fas fa-sm fa-fw fa-cog"></i></span><span class="mm-label">Настройки профиля</span></a></li>
|
<li><a href="/lk/profile" class="mm-item"><span class="mm-icon"><i class="fas fa-sm fa-fw fa-cog"></i></span><span class="mm-label">Настройки профиля</span></a></li>
|
||||||
<li><a href="/search?id=<?=Auth::userid()?>" class="mm-item"><span class="mm-icon"><i class="far fa-sm fa-fw fa-images"></i></span><span class="mm-label">Мои фотографии</span></a></li>
|
<li><a href="/search?id=<?=Auth::userid()?>" class="mm-item"><span class="mm-icon"><i class="far fa-sm fa-fw fa-images"></i></span><span class="mm-label">Мои фотографии</span></a></li>
|
||||||
|
|
260
views/pages/Admin/Contests.php
Normal file
|
@ -0,0 +1,260 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use \App\Services\{Auth, DB, Date, TaskScheduler};
|
||||||
|
use \App\Models\User;
|
||||||
|
|
||||||
|
$task = new TaskScheduler();
|
||||||
|
|
||||||
|
$contestCreate = true;
|
||||||
|
if (!$task->isTaskExists("ExecContests", "php ".$_SERVER['DOCUMENT_ROOT'].$task->findHandlerById(NGALLERY_TASKS, 'ExecContests'))) {
|
||||||
|
$contestCreate = false;
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td class="main">
|
||||||
|
<h1><b>Фотоконкурсы</b></h1>
|
||||||
|
<div class="v-header__tabs">
|
||||||
|
<div class="v-tabs">
|
||||||
|
<div class="v-tabs__scroll">
|
||||||
|
<div class="v-tabs__content"><a href="#" onclick="changeTab('contests')" id="contests" class="v-tab v-tab-b v-tab--active"><span class="v-tab__label">
|
||||||
|
Конкурсы
|
||||||
|
</span></a><a href="#" onclick="changeTab('categories')" id="categories" class="v-tab v-tab-b"><span class="v-tab__label">
|
||||||
|
Категории
|
||||||
|
|
||||||
|
</span></a>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="kandle__block active__block" id="contests__block">
|
||||||
|
<div class="p20w" style="display:block">
|
||||||
|
<a data-bs-toggle="modal" data-bs-target="#createContest" href="#" class="btn btn-primary mt-3 <?php if ($contestCreate === false) {
|
||||||
|
echo 'disabled';
|
||||||
|
} ?>">Провести новый</a>
|
||||||
|
<table class="table">
|
||||||
|
<?php
|
||||||
|
if ($contestCreate === false) {
|
||||||
|
echo "<div class='alert alert-warning mt-3' role='alert'>У вас не добавлена задача на проведение конкурсов. Без неё, сервер не сможет завершать конкурс и проводить новый автоматически.<a href='/admin?type=Settings' type='button' style='margin-left: 5px;' class='btn btn-sm btn-outline-dark'>Включить</a></div>";
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<th width="100">ID</th>
|
||||||
|
<th width="25%">Тема</th>
|
||||||
|
<th>Дата начала отбора</th>
|
||||||
|
<th>Дата конца отбора</th>
|
||||||
|
<th>Дата начала</th>
|
||||||
|
<th>Дата конца</th>
|
||||||
|
<th>Статус</th>
|
||||||
|
<th></th>
|
||||||
|
</tr>
|
||||||
|
<?php
|
||||||
|
$themes = DB::query('SELECT * FROM contests ORDER BY id DESC');
|
||||||
|
foreach ($themes as $t) {
|
||||||
|
$themetitle = DB::query('SELECT title FROM contests_themes WHERE id=:id', array(':id' => $t['themeid']))[0]['title'];
|
||||||
|
if ($t['status'] === 0) {
|
||||||
|
$status = 'Ещё не проведён';
|
||||||
|
} else if ($t['status'] === 1) {
|
||||||
|
$status = 'Отбор кандидатов';
|
||||||
|
} else if ($t['status'] === 02) {
|
||||||
|
$status = 'Ещё не открыт для отбора победителей';
|
||||||
|
} else if ($t['status'] === 2) {
|
||||||
|
$status = 'Отбор победителей';
|
||||||
|
} else if ($t['status'] === 3) {
|
||||||
|
$status = 'Завершён';
|
||||||
|
} else {
|
||||||
|
$status = 'Сбой';
|
||||||
|
}
|
||||||
|
echo '<tr class="' . $color . '">
|
||||||
|
<td>' . $t['id'] . '</td>
|
||||||
|
<td>' . $themetitle . '</td>
|
||||||
|
<td>' . Date::zmdate($t['openpretendsdate']) . '</td>
|
||||||
|
<td>' . Date::zmdate($t['closepretendsdate']) . '</td>
|
||||||
|
<td>' . Date::zmdate($t['opendate']) . '</td>
|
||||||
|
<td>' . Date::zmdate($t['closedate']) . '</td>
|
||||||
|
<td>' . $status . '</td>
|
||||||
|
</tr>';
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="kandle__block" style="display: none;" id="categories__block">
|
||||||
|
<div class="p20w" style="display:block">
|
||||||
|
<a data-bs-toggle="modal" data-bs-target="#createContestTheme" href="#" class="btn btn-primary mt-3">Создать</a>
|
||||||
|
<table class="table">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<th width="100">ID</th>
|
||||||
|
<th width="50%">Название</th>
|
||||||
|
<th>В автоматическом отборе</th>
|
||||||
|
<th></th>
|
||||||
|
</tr>
|
||||||
|
<?php
|
||||||
|
$themes = DB::query('SELECT * FROM contests_themes');
|
||||||
|
foreach ($themes as $t) {
|
||||||
|
if ($t['status'] === 1) {
|
||||||
|
$auto = 'Да';
|
||||||
|
} else {
|
||||||
|
$auto = 'Нет';
|
||||||
|
}
|
||||||
|
echo '<tr class="' . $color . '">
|
||||||
|
<td>' . $t['id'] . '</td>
|
||||||
|
<td>' . $t['title'] . '</td>
|
||||||
|
<td>' . $auto . '</td>
|
||||||
|
</tr>';
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<div class="modal fade" id="createContest" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
|
||||||
|
<div class="modal-dialog">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h1 class="modal-title fs-5" id="exampleModalLabel"><b>Создание конкурса</b></h1>
|
||||||
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<form id="contest">
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="exampleFormControlTextarea1" class="form-label">Тематика</label>
|
||||||
|
<select name="themeid" class="form-select" aria-label="Default select example">
|
||||||
|
<?php
|
||||||
|
$themes = DB::query('SELECT * FROM contests_themes');
|
||||||
|
foreach ($themes as $t) {
|
||||||
|
echo '<option value="'.$t['id'].'">'.$t['title'].'</option>';
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="exampleFormControlTextarea1" class="form-label">Дата начала отбора претенднетов</label>
|
||||||
|
<input name="openpretendsdate" type="datetime-local" class="form-select">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="exampleFormControlTextarea1" class="form-label">Дата конца отбора претенднетов</label>
|
||||||
|
<input name="closepretendsdate" type="datetime-local" class="form-select">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<div class="form-check">
|
||||||
|
<input name="startContestNow" class="form-check-input" type="checkbox" value="1" id="startContestNow">
|
||||||
|
<label class="form-check-label" for="startContestNow">
|
||||||
|
Провести конкурс сразу после конца отбора претендентов
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="contestStart" class="form-label">Дата начала проведения конкурса</label>
|
||||||
|
<input id="contestStartInput" name="opendate" type="datetime-local" class="form-select">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="exampleFormControlTextarea1" class="form-label">Дата конца проведения конкурса</label>
|
||||||
|
<input name="closedate" type="datetime-local" class="form-select">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<a type="button" class="btn btn-secondary" data-bs-dismiss="modal">Отмена</a>
|
||||||
|
<a href="#" onclick="createContest(); return false;" data-bs-dismiss="modal" class="btn btn-primary">Добавить</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="modal fade" id="createContestTheme" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
|
||||||
|
<div class="modal-dialog">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h1 class="modal-title fs-5" id="exampleModalLabel"><b>Добавление категории конкурса</b></h1>
|
||||||
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<form id="contestTheme">
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="exampleFormControlTextarea1" class="form-label">Название</label>
|
||||||
|
<input class="form-control" id="exampleFormControlTextarea1" name="body">
|
||||||
|
</div>
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input" type="checkbox" value="1" name="active" id="flexCheckChecked" checked>
|
||||||
|
<label class="form-check-label" for="flexCheckChecked">
|
||||||
|
Активна для автоматического подбора
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<a type="button" class="btn btn-secondary" data-bs-dismiss="modal">Отмена</a>
|
||||||
|
<a href="#" onclick="createContestTheme(); return false;" data-bs-dismiss="modal" class="btn btn-primary">Добавить</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<script>
|
||||||
|
$(document).ready(function() {
|
||||||
|
$('#startContestNow').on('change', function() {
|
||||||
|
$('#contestStartInput').prop('disabled', $(this).is(':checked'));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
function createContestTheme() {
|
||||||
|
var formData = new FormData(document.getElementById("contestTheme"));
|
||||||
|
$.ajax({
|
||||||
|
type: "POST",
|
||||||
|
url: '/api/admin/contests/createtheme',
|
||||||
|
data: formData,
|
||||||
|
success: function(response) {
|
||||||
|
var jsonData = JSON.parse(response);
|
||||||
|
|
||||||
|
Notify.noty('success', 'OK!');
|
||||||
|
|
||||||
|
|
||||||
|
},
|
||||||
|
cache: false,
|
||||||
|
contentType: false,
|
||||||
|
processData: false
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function createContest() {
|
||||||
|
var formData = new FormData(document.getElementById("contest"));
|
||||||
|
$.ajax({
|
||||||
|
type: "POST",
|
||||||
|
url: '/api/admin/contests/create',
|
||||||
|
data: formData,
|
||||||
|
success: function(response) {
|
||||||
|
var jsonData = JSON.parse(response);
|
||||||
|
|
||||||
|
Notify.noty('success', 'OK!');
|
||||||
|
|
||||||
|
|
||||||
|
},
|
||||||
|
cache: false,
|
||||||
|
contentType: false,
|
||||||
|
processData: false
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
</script>
|
87
views/pages/Admin/GeoDB.php
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use \App\Services\{Auth, DB};
|
||||||
|
use \App\Models\User;
|
||||||
|
?>
|
||||||
|
<h1><b>GeoDB</b></h1>
|
||||||
|
<a data-bs-toggle="modal" data-bs-target="#createGeoDB" href="#" class="btn btn-primary">Создать</a>
|
||||||
|
<table class="table" style="margin-top: 15px;">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th scope="col">ID</th>
|
||||||
|
<th scope="col">Название</th>
|
||||||
|
<th scope="col"></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<?php
|
||||||
|
$geodb = DB::query('SELECT * FROM geodb');
|
||||||
|
foreach ($geodb as $u) {
|
||||||
|
echo '<tr id="geodb'.$u['id'].'">
|
||||||
|
<th>' . $u['id'] . '</th>
|
||||||
|
<td>' . $u['title'] . '</td>
|
||||||
|
<td><div class="cmt-submit"><a style="margin-left: 15px;" class="btn btn-sm btn-danger" onclick="deleteGeoDB(`'.$u['id'].'`); return false;">Удалить</a></div></td>
|
||||||
|
</tr>';
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div class="modal fade" id="createGeoDB" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
|
||||||
|
<div class="modal-dialog">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h1 class="modal-title fs-5" id="exampleModalLabel"><b>Добавление элемента GeoDB</b></h1>
|
||||||
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="exampleFormControlTextarea1" class="form-label">Содержание</label>
|
||||||
|
<textarea class="form-control" id="exampleFormControlTextarea1" name="body" rows="3"></textarea>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<a type="button" class="btn btn-secondary" data-bs-dismiss="modal">Отмена</a>
|
||||||
|
<a href="#" onclick="createGeoDB(document.querySelector(`textarea[name='body']`).value); return false;" data-bs-dismiss="modal" class="btn btn-primary">Добавить</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<script>
|
||||||
|
function createGeoDB(body) {
|
||||||
|
$.ajax({
|
||||||
|
type: "POST",
|
||||||
|
url: '/api/admin/geodb/create',
|
||||||
|
data: {
|
||||||
|
body: body
|
||||||
|
},
|
||||||
|
success: function(response) {
|
||||||
|
Notify.noty('success', 'OK!');
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function deleteGeoDB(id) {
|
||||||
|
$.ajax({
|
||||||
|
type: "POST",
|
||||||
|
url: '/api/admin/geodb/delete?id='+id,
|
||||||
|
data: $(this).serialize(),
|
||||||
|
success: function(response) {
|
||||||
|
$('#geodb'+id).remove();
|
||||||
|
Notify.noty('success', 'OK!');
|
||||||
|
//$("#result").html("<div class='alert alert-successnew container mt-5' role='alert'>Успешный вход!</div>");
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
</script>
|
151
views/pages/Admin/PageCreate.php
Normal file
|
@ -0,0 +1,151 @@
|
||||||
|
|
||||||
|
<script>
|
||||||
|
function submitUpload() {
|
||||||
|
$('#buttonUpload').html('<button style="border-radius: 10px 0px 0px 10px !important;" type="submit" id="createpost" class="btn btn-primary mb-3 mt-3" disabled><span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span> Загружаем...</button>');
|
||||||
|
$('#buttonUploadModal').html('<button type="submit" id="createpost" class="btn btn-primary" disabled><span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span> Загружаем...</button>');
|
||||||
|
$('#buttonPreView').html('<button style="border-radius: 0px 10px 10px 0px !important;" type="submit" id="createpost" class="btn btn-primarynew mb-3 mt-3" disabled>Предпросмотр</button>');
|
||||||
|
$.ajax({
|
||||||
|
|
||||||
|
type: "POST",
|
||||||
|
url: '/exapi/dialogs/create',
|
||||||
|
data: JSON.stringify( { "bodypost":$("#bodypost").val(), "title": $("#title").val(), "did": '00000' } ),
|
||||||
|
dataType: "json",
|
||||||
|
success: function(response) {
|
||||||
|
var jsonData = JSON.parse(JSON.stringify(response));
|
||||||
|
|
||||||
|
console.log(jsonData);
|
||||||
|
if (jsonData.errorcode == "1") {
|
||||||
|
$('#buttonUpload').html('<button href="#" data-bs-toggle="modal" data-bs-target="#createDialogModal" style="border-radius: 10px 0px 0px 10px !important;" type="submit" id="createpost" class="btn btn-primary mb-3 mt-3">Опубликовать</button>');
|
||||||
|
$('#buttonPreView').html('<button onclick="submitPreview()" style="border-radius: 0px 10px 10px 0px !important;" type="submit" id="createpost" class="btn btn-primarynew mb-3 mt-3">Предпросмотр</button>');
|
||||||
|
$('#buttonUploadModal').html('<button onclick="submitUpload()"type="submit" class="btn btn-primary">Да, я уверен</button>');
|
||||||
|
Notify.noty('danger', 'Мало контента!');
|
||||||
|
} else {
|
||||||
|
$('#buttonUpload').html('<button href="#" data-bs-toggle="modal" data-bs-target="#createDialogModal" style="border-radius: 10px 0px 0px 10px !important;" type="submit" id="createpost" class="btn btn-primary mb-3 mt-3">Опубликовать</button>');
|
||||||
|
$('#buttonPreView').html('<button onclick="submitPreview()" style="border-radius: 0px 10px 10px 0px !important;" type="submit" id="createpost" class="btn btn-primarynew mb-3 mt-3">Предпросмотр</button>');
|
||||||
|
$('#buttonUploadModal').html('<button onclick="submitUpload()"type="submit" class="btn btn-primary">Да, я уверен</button>');
|
||||||
|
window.location.replace("/dialogs/<?=$id_dialog?>/topic/<?=$id_topic?>/post/"+jsonData.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function submitPreview() {
|
||||||
|
$('#buttonUpload').html('<button style="border-radius: 10px 0px 0px 10px !important;" type="submit" id="createpost" class="btn btn-primary mb-3 mt-3" disabled>Опубликовать</button>');
|
||||||
|
$('#buttonPreView').html('<button style="border-radius: 0px 10px 10px 0px !important;" type="submit" id="createpost" class="btn btn-primarynew mb-3 mt-3" disabled><span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span> Загружаем...</button>');
|
||||||
|
$.ajax({
|
||||||
|
|
||||||
|
type: "POST",
|
||||||
|
url: '/exapi/dialogs/createPreview',
|
||||||
|
data: JSON.stringify( { "bodypost":$("#bodypost").val(), "title": $("#title").val() } ),
|
||||||
|
dataType: "json",
|
||||||
|
success: function(response) {
|
||||||
|
var jsonData = JSON.parse(JSON.stringify(response));
|
||||||
|
|
||||||
|
console.log(response);
|
||||||
|
console.log(jsonData);
|
||||||
|
if (jsonData.errorcode == "1") {
|
||||||
|
$('#buttonUpload').html('<button href="#" data-bs-toggle="modal" data-bs-target="#createDialogModal" style="border-radius: 10px 0px 0px 10px !important;" type="submit" id="createpost" class="btn btn-primary mb-3 mt-3">Опубликовать</button>');
|
||||||
|
$('#buttonPreView').html('<button onclick="submitPreview()" style="border-radius: 0px 10px 10px 0px !important;" type="submit" id="createpost" class="btn btn-primarynew mb-3 mt-3">Предпросмотр</button>');
|
||||||
|
$("#result").html("<div class='alert alert-dangernew container' role='alert'>Может, что-нибудь напишите в свой пост?</div>");
|
||||||
|
} else {
|
||||||
|
$('#buttonUpload').html('<button href="#" data-bs-toggle="modal" data-bs-target="#createDialogModal" style="border-radius: 10px 0px 0px 10px !important;" type="submit" id="createpost" class="btn btn-primary mb-3 mt-3">Опубликовать</button>');
|
||||||
|
$('#buttonPreView').html('<button onclick="submitPreview()" style="border-radius: 0px 10px 10px 0px !important;" type="submit" id="createpost" class="btn btn-primarynew mb-3 mt-3">Предпросмотр</button>');
|
||||||
|
window.open('/dialogs/preview?id='+jsonData.preid, '_blank');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="exampleFormControlInput1" class="form-label">Заголовок</label>
|
||||||
|
<input name="title" id="title" type="text" class="form-control" id="exampleFormControlInput1">
|
||||||
|
</div>
|
||||||
|
<div class="col-md-auto d-flex align-items-center">
|
||||||
|
<button onclick="document.getElementById('bodypost').value += '[b] [/b]';" type="button" class="btn btn-primary btn-sm mb-2" style="margin-right: 6px;"><i class="bx bx-bold"></i></button>
|
||||||
|
<button onclick="document.getElementById('bodypost').value += '[i] [/i]';" type="button" class="btn btn-primary btn-sm mb-2" style="margin-right: 6px;"><i class="bx bx-italic"></i></button>
|
||||||
|
<button onclick="document.getElementById('bodypost').value += '[u] [/u]';" type="button" class="btn btn-primary btn-sm mb-2" style="margin-right: 6px;"><i class="bx bx-underline"></i></button>
|
||||||
|
<button onclick="document.getElementById('bodypost').value += '[s] [/s]';" type="button" class="btn btn-primary btn-sm mb-2" style="margin-right: 6px;"><i class="bx bx-strikethrough"></i></button>
|
||||||
|
<button onclick="document.getElementById('bodypost').value += '[link=] [/link]';" type="button" class="btn btn-primary btn-sm mb-2" style="margin-right: 36px;"><i class="bx bx-link"></i></button>
|
||||||
|
<button href="#" data-bs-toggle="modal" data-bs-target="#pickImageModal" type="button" class="btn btn-primary btn-sm mb-2" style="margin-right: 6px;"><i class="bx bx-image-alt"></i></button>
|
||||||
|
<button href="#" data-bs-toggle="modal" data-bs-target="#pickVideoModal" type="button" class="btn btn-primary btn-sm mb-2" style="margin-right: 6px;"><i class="bx bx-video"></i></button>
|
||||||
|
<button href="#" data-bs-toggle="modal" data-bs-target="#pickMusicModal" type="button" class="btn btn-primary btn-sm mb-2" style="margin-right: 6px;"><i class="bx bx-music"></i></button>
|
||||||
|
</div>
|
||||||
|
<textarea id="bodypost" class="form-control" name="bodypost" placeholder="Вы можете написать свою историю" cols="30" rows="10"></textarea>
|
||||||
|
<div class="btn-group" role="group" aria-label="Basic example">
|
||||||
|
<div id="buttonUpload">
|
||||||
|
<button href="#" data-bs-toggle="modal" data-bs-target="#createDialogModal" style="border-radius: 10px 0px 0px 10px !important;" type="submit" id="createpost" class="btn btn-primary mb-3 mt-3">Опубликовать</button>
|
||||||
|
</div>
|
||||||
|
<div id="buttonPreView">
|
||||||
|
<button onclick="submitPreview()" style="border-radius: 0px 10px 10px 0px !important;" type="submit" id="createpost" class="btn btn-outline-primary mb-3 mt-3">Предпросмотр</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</form>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div class="modal fade" id="pickImageModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
|
||||||
|
<div class="modal-dialog modal-dialog-centered">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h5 class="modal-title">Прикрепление фотографии</h5>
|
||||||
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
|
</div>
|
||||||
|
<form enctype="multipart/form-data" id="pickImageForm">
|
||||||
|
<div class="modal-body">
|
||||||
|
<div class="mb-3">
|
||||||
|
<input id="filebody" type="file" name="filebodyImage" class="form-control" type="file">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<div><button type="button" class="btn-r btn-secondary" data-bs-dismiss="modal">Отмена</button></div>
|
||||||
|
<div id="r"><button id="t" type="submit" class="btn btn-primary" data-bs-dismiss="modal">Прикрепить</button></div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="modal fade" id="pickMusicModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
|
||||||
|
<div class="modal-dialog modal-dialog-centered">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h5 class="modal-title">Прикрепление музыки</h5>
|
||||||
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<div class="mb-3">
|
||||||
|
<input id="filebody" type="file" name="filebody" class="form-control" type="file">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<div><button type="button" class="btn-r btn-secondary" data-bs-dismiss="modal">Отмена</button></div>
|
||||||
|
<div id="r"><button id="t" type="submit" class="btn btn-primary">Прикрепить</button></div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="modal fade" id="pickVideoModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
|
||||||
|
<div class="modal-dialog modal-dialog-centered">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h5 class="modal-title">Прикрепление видео</h5>
|
||||||
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
|
</div>
|
||||||
|
<form enctype="multipart/form-data" id="pickVideoForm">
|
||||||
|
<div class="modal-body">
|
||||||
|
<div class="mb-3">
|
||||||
|
<input id="filebody" type="file" name="filebodyVideo" class="form-control" type="file">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<div><button type="button" class="btn-r btn-secondary" data-bs-dismiss="modal">Отмена</button></div>
|
||||||
|
<div id="r"><button id="t" type="submit" class="btn btn-primary" data-bs-dismiss="modal">Прикрепить</button></div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
19
views/pages/Admin/Pages.php
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use \App\Services\{Auth, DB, Date};
|
||||||
|
use \App\Models\User;
|
||||||
|
|
||||||
|
?>
|
||||||
|
|
||||||
|
|
||||||
|
<h1><b>Страницы</b></h1>
|
||||||
|
<a href="?type=PageCreate" class="btn btn-primary mb-3">Создать</a>
|
||||||
|
|
||||||
|
<div id="pages">
|
||||||
|
<?php
|
||||||
|
$pages = DB::query('SELECT * FROM pages ORDER BY id');
|
||||||
|
foreach ($pages as $p) {
|
||||||
|
echo '<div class="card mb-3"><div class="card-body">' . Date::zmdate($n['time']) . '<br>' . $n['body'] . '</div></div>';
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
</div>
|
|
@ -35,10 +35,26 @@ use \App\Models\User;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<td class="main">
|
<td class="main">
|
||||||
<h1><b>Журнал</b></h1>
|
<h1><b>Фотографии</b></h1>
|
||||||
|
<div class="v-header__tabs">
|
||||||
|
<div class="v-tabs">
|
||||||
|
<div class="v-tabs__scroll">
|
||||||
|
<div class="v-tabs__content"><!--a href="#" onclick="changeTab('full')" id="full" class="v-tab v-tab-b"><span class="v-tab__label">
|
||||||
|
Полный список
|
||||||
|
|
||||||
|
</span></!--a--><a href="#" onclick="changeTab('moderate')" id="moderate" class="v-tab v-tab-b v-tab--active"><span class="v-tab__label">
|
||||||
|
Ожидают модерации
|
||||||
|
|
||||||
|
</span></a>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<script src="/js/diff.js"></script>
|
<script src="/js/diff.js"></script>
|
||||||
<script src="/js/pwrite-compare.js"></script>
|
<script src="/js/pwrite-compare.js"></script>
|
||||||
<br clear="all"><br>
|
<div id="moderate__block"class="active__block" >
|
||||||
<div class="p20w" style="display:block">
|
<div class="p20w" style="display:block">
|
||||||
<table class="table">
|
<table class="table">
|
||||||
<tbody>
|
<tbody>
|
||||||
|
@ -47,6 +63,7 @@ use \App\Models\User;
|
||||||
<th width="50%">Информация</th>
|
<th width="50%">Информация</th>
|
||||||
<th>Действия</th>
|
<th>Действия</th>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
<?php
|
<?php
|
||||||
$photos = DB::query('SELECT * FROM photos WHERE moderated=0 ORDER BY id DESC');
|
$photos = DB::query('SELECT * FROM photos WHERE moderated=0 ORDER BY id DESC');
|
||||||
|
@ -74,7 +91,7 @@ use \App\Models\User;
|
||||||
<td class="c">
|
<td class="c">
|
||||||
';
|
';
|
||||||
if ($p['moderated'] === 0) {
|
if ($p['moderated'] === 0) {
|
||||||
echo '<a href="/api/admin/images/setvisibility?id='.$p['id'].'&mod=1" class="btn btn-primary">Принять</a>
|
echo '<a data-bs-toggle="modal" data-bs-target="#acceptPhotoModal'.$p['id'].'" href="#" class="btn btn-primary">Принять</a>
|
||||||
<a data-bs-toggle="modal" data-bs-target="#declinePhotoModal'.$p['id'].'" href="#" class="btn btn-danger">Отклонить</a>';
|
<a data-bs-toggle="modal" data-bs-target="#declinePhotoModal'.$p['id'].'" href="#" class="btn btn-danger">Отклонить</a>';
|
||||||
}
|
}
|
||||||
echo '
|
echo '
|
||||||
|
@ -84,6 +101,56 @@ use \App\Models\User;
|
||||||
}
|
}
|
||||||
echo '
|
echo '
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
<div class="modal fade" id="acceptPhotoModal'.$p['id'].'" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
|
||||||
|
<div class="modal-dialog">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h1 class="modal-title fs-5" id="exampleModalLabel"><b>Принятие фотографии</b></h1>
|
||||||
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<div class="form-check">
|
||||||
|
<input name="accept'.$p['id'].'" value="0" class="form-check-input" type="radio" name="flexRadioDefault" id="acceptReason1" checked>
|
||||||
|
<label class="form-check-label" for="acceptReason1">
|
||||||
|
Нормальная публикация
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="form-check">
|
||||||
|
<input name="accept'.$p['id'].'" value="1" class="form-check-input" type="radio" name="flexRadioDefault" id="acceptReason3">
|
||||||
|
<label class="form-check-label" for="acceptReason3">
|
||||||
|
Условная публикация
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="form-check">
|
||||||
|
<input name="accept'.$p['id'].'" value="2" class="form-check-input" type="radio" name="flexRadioDefault" id="acceptReason2">
|
||||||
|
<label class="form-check-label" for="acceptReason2">
|
||||||
|
Временная публикация
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="form-check">
|
||||||
|
<input name="accept'.$p['id'].'" value="3" class="form-check-input" type="radio" name="flexRadioDefault" id="acceptReason4">
|
||||||
|
<label class="form-check-label" for="acceptReason4">
|
||||||
|
Техническая публикация
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<h6 class="mt-3">Другие действия</h6>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="exampleFormControlTextarea1" class="form-label">Дополнительный комментарий</label>
|
||||||
|
<textarea class="form-control" id="exampleFormControlTextarea1" name="comment" rows="3"></textarea>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<a type="button" class="btn btn-secondary" data-bs-dismiss="modal">Отмена</a>'; ?>
|
||||||
|
<a href="#" onclick="photoAction(<?=$p['id']?>, document.querySelector(`input[name='accept<?=$p['id']?>']:checked`).value, 1); return false;" data-bs-dismiss="modal" class="btn btn-primary">Сохранить</a>
|
||||||
|
<?php echo '
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div class="modal fade" id="declinePhotoModal'.$p['id'].'" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
|
<div class="modal fade" id="declinePhotoModal'.$p['id'].'" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
|
||||||
<div class="modal-dialog">
|
<div class="modal-dialog">
|
||||||
|
@ -123,7 +190,17 @@ use \App\Models\User;
|
||||||
Расчленёнка
|
Расчленёнка
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="form-check">
|
||||||
|
<input name="decline'.$p['id'].'" value="6" class="form-check-input" type="radio" name="flexRadioDefault" id="declineReason6">
|
||||||
|
<label class="form-check-label" for="declineReason6">
|
||||||
|
Файл сломан
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="exampleFormControlTextarea1" class="form-label">Дополнительный комментарий</label>
|
||||||
|
<textarea class="form-control" id="exampleFormControlTextarea1" name="comment" rows="3"></textarea>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<a type="button" class="btn btn-secondary" data-bs-dismiss="modal">Отмена</a>'; ?>
|
<a type="button" class="btn btn-secondary" data-bs-dismiss="modal">Отмена</a>'; ?>
|
||||||
|
@ -141,7 +218,10 @@ use \App\Models\User;
|
||||||
|
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div><br>
|
</div></div>
|
||||||
|
<div style="display: none;" id="full__block">
|
||||||
|
fgdfg
|
||||||
|
</div>
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -149,7 +229,7 @@ use \App\Models\User;
|
||||||
function photoAction(photo_id, decline_reason, mod) {
|
function photoAction(photo_id, decline_reason, mod) {
|
||||||
$.ajax({
|
$.ajax({
|
||||||
type: "GET",
|
type: "GET",
|
||||||
url: '/api/admin/images/setvisibility?id='+photo_id+'&mod='+mod+'&decline_reason='+decline_reason,
|
url: '/api/admin/images/setvisibility?id='+photo_id+'&mod='+mod+'&reason='+decline_reason,
|
||||||
data: $(this).serialize(),
|
data: $(this).serialize(),
|
||||||
success: function(response) {
|
success: function(response) {
|
||||||
$('#pht'+photo_id).remove();
|
$('#pht'+photo_id).remove();
|
||||||
|
|
171
views/pages/Admin/Settings.php
Normal file
|
@ -0,0 +1,171 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use \App\Services\{KeyTranslation, TaskScheduler};
|
||||||
|
use \App\Models\User;
|
||||||
|
|
||||||
|
use Symfony\Component\Yaml\Yaml;
|
||||||
|
|
||||||
|
$task = new TaskScheduler();
|
||||||
|
$yamlFile = $_SERVER['DOCUMENT_ROOT'] . '/ngallery.yaml';
|
||||||
|
function renderInputs($data, $prefix = '')
|
||||||
|
{
|
||||||
|
foreach ($data as $key => $value) {
|
||||||
|
$name = $prefix ? "{$prefix}[{$key}]" : $key;
|
||||||
|
$key = KeyTranslation::key($key);
|
||||||
|
|
||||||
|
if (is_string($value) || is_bool($value)) {
|
||||||
|
|
||||||
|
if ($value === true || $value === false) {
|
||||||
|
$value = $value ? 'true' : 'false';
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($value === 'true' || $value === 'false') {
|
||||||
|
echo "<div class='mb-2'>
|
||||||
|
<label>{$key}</label>
|
||||||
|
<select class='form-control' name='{$name}'>
|
||||||
|
<option value='true' " . ($value === 'true' ? 'selected' : '') . ">true</option>
|
||||||
|
<option value='false' " . ($value === 'false' ? 'selected' : '') . ">false</option>
|
||||||
|
</select>
|
||||||
|
</div>";
|
||||||
|
} else {
|
||||||
|
echo "<div class='mb-2'>
|
||||||
|
<label>{$key}</label>
|
||||||
|
<input class='form-control' type='text' name='{$name}' value='" . htmlspecialchars($value, ENT_QUOTES) . "'>
|
||||||
|
</div>";
|
||||||
|
}
|
||||||
|
} elseif (is_numeric($value)) {
|
||||||
|
echo "<div class='mb-2'>
|
||||||
|
<label>{$key}</label>
|
||||||
|
<input class='form-control' type='number' name='{$name}' value='{$value}'>
|
||||||
|
</div>";
|
||||||
|
} elseif (is_array($value)) {
|
||||||
|
echo "<fieldset class='mb-3 p-2 border'><legend>{$key}</legend>";
|
||||||
|
renderInputs($value, $name);
|
||||||
|
echo "</fieldset>";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
?>
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="ru">
|
||||||
|
<script src="https://code.jquery.com/jquery-3.7.1.js"></script>
|
||||||
|
<link rel="stylesheet" href="/static/css/notie.css<?php if (NGALLERY['root']['cloudflare-caching'] === true) {
|
||||||
|
echo '?' . time();
|
||||||
|
} ?>">
|
||||||
|
<script src="/static/js/notie.js<?php if (NGALLERY['root']['cloudflare-caching'] === true) {
|
||||||
|
echo '?' . time();
|
||||||
|
} ?>"></script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
notie.setOptions({
|
||||||
|
transitionCurve: 'cubic-bezier(0.2, 0, 0.2, 1)'
|
||||||
|
});
|
||||||
|
var Notify = {
|
||||||
|
noty: function(status, text) {
|
||||||
|
|
||||||
|
if (status == 'danger') status = 'error';
|
||||||
|
|
||||||
|
return notie.alert({
|
||||||
|
type: status,
|
||||||
|
text: text
|
||||||
|
})
|
||||||
|
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div class="container">
|
||||||
|
|
||||||
|
<?= \App\Controllers\AdminController::loadMenu(); ?>
|
||||||
|
<?= \App\Controllers\AdminController::loadContent(); ?>
|
||||||
|
|
||||||
|
<h1><b>Настройки</b></h1>
|
||||||
|
<div class="v-header__tabs">
|
||||||
|
<div class="v-tabs">
|
||||||
|
<div class="v-tabs__scroll">
|
||||||
|
<div class="v-tabs__content"><!--a href="#" onclick="changeTab('config')" id="config" class="v-tab v-tab-b v-tab--active"><span class="v-tab__label">
|
||||||
|
Конфиг сервера
|
||||||
|
|
||||||
|
</span></!--a--><a href="#" onclick="changeTab('tasks')" id="tasks" class="v-tab v-tab-b v-tab--active"><span class="v-tab__label">
|
||||||
|
Задачи
|
||||||
|
|
||||||
|
</span></a>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="config__block" style="display: none;" >
|
||||||
|
<div class="alert alert-warning" role="alert">
|
||||||
|
Изменяйте только на свой страх и риск.
|
||||||
|
</div>
|
||||||
|
<div class="p20w" style="display:block">
|
||||||
|
<?php
|
||||||
|
// Вывод формы
|
||||||
|
echo '<form method="post">';
|
||||||
|
foreach (NGALLERY as $ng) {
|
||||||
|
renderInputs($ng);
|
||||||
|
}
|
||||||
|
echo '<button type="submit">Сохранить</button>';
|
||||||
|
echo '</form>';
|
||||||
|
?>
|
||||||
|
</div><br>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="active__block"id="tasks__block">
|
||||||
|
<table class="table">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<th width="100">ID</th>
|
||||||
|
<th width="50%">Статус</th>
|
||||||
|
<th>Действия</th>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
<?php
|
||||||
|
foreach (NGALLERY_TASKS as $nt) {
|
||||||
|
$nt = $nt;
|
||||||
|
echo '<tr><td>
|
||||||
|
|
||||||
|
'.$nt['id'].'
|
||||||
|
</td><td>
|
||||||
|
'.$task->getTaskStatus($nt['id'], "php {$nt['handler']}").'
|
||||||
|
</td><td class="c">
|
||||||
|
<a onclick="taskManager(`'.$nt['id'].'`, 1)" class="btn btn-sm btn-primary">Запустить</a> <a onclick="taskManager(`'.$nt['id'].'`, 0)" class="btn btn-sm btn-danger">Остановить</a>
|
||||||
|
</td> <tr>';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
?>
|
||||||
|
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</body>
|
||||||
|
<script>
|
||||||
|
function taskManager(id, type) {
|
||||||
|
$.ajax({
|
||||||
|
type: "GET",
|
||||||
|
url: '/api/admin/settings/taskmanager?id='+id+'&type='+type,
|
||||||
|
success: function(response) {
|
||||||
|
Notify.noty('success', 'OK!');
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</html>
|
167
views/pages/Comments/Index.php
Normal file
|
@ -0,0 +1,167 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use \App\Services\{Auth, DB, Date};
|
||||||
|
use \App\Models\{User, Photo, Vote};
|
||||||
|
|
||||||
|
|
||||||
|
?>
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="ru">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<?php include($_SERVER['DOCUMENT_ROOT'] . '/views/components/LoadHead.php'); ?>
|
||||||
|
|
||||||
|
|
||||||
|
</head>
|
||||||
|
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div id="backgr"></div>
|
||||||
|
<table class="tmain">
|
||||||
|
<?php include($_SERVER['DOCUMENT_ROOT'] . '/views/components/Navbar.php'); ?>
|
||||||
|
<tr>
|
||||||
|
<td class="main">
|
||||||
|
<h1>Лента комментариев</h1>
|
||||||
|
<script src="/js/jquery-ui.js?1633005526"></script>
|
||||||
|
<script src="/js/selector.js?1730197663"></script>
|
||||||
|
<script>
|
||||||
|
$(document).ready(function() {
|
||||||
|
$('#cname').citySelector('cid', {
|
||||||
|
defaultLabel: 'Все города'
|
||||||
|
});
|
||||||
|
$('#type').val(0).change(function() {
|
||||||
|
$(this).attr('class', $('option:selected', this).attr('class'));
|
||||||
|
}).change();
|
||||||
|
|
||||||
|
$('#applyFilter').on('click', function() {
|
||||||
|
var cid = $('#cid').val();
|
||||||
|
var type = $('#type').val();
|
||||||
|
var redir = '/comments.php';
|
||||||
|
|
||||||
|
if (cid > 0 || type > 0) {
|
||||||
|
redir = redir + '?';
|
||||||
|
if (cid > 0) {
|
||||||
|
redir = redir + 'cid=' + cid;
|
||||||
|
if (type > 0) redir = redir + '&';
|
||||||
|
}
|
||||||
|
if (type > 0) redir = redir + 't=' + type;
|
||||||
|
}
|
||||||
|
|
||||||
|
window.location.href = redir;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
<div id="upd_anchor"></div>
|
||||||
|
<?php
|
||||||
|
$comments = DB::query('SELECT * FROM photos_comments ORDER BY id DESC LIMIT 30');
|
||||||
|
foreach ($comments as $c) {
|
||||||
|
$user = new User($c['user_id']);
|
||||||
|
$content = json_decode($c['content'], true);
|
||||||
|
$photo = new Photo($c['photo_id']);
|
||||||
|
if ($user->i('admin') === 1) {
|
||||||
|
$admintype = ' · Администратор сервера';
|
||||||
|
} else if ($user->i('admin') === 2) {
|
||||||
|
$admintype = ' · Фотомодератор';
|
||||||
|
}
|
||||||
|
if ((int)Vote::countcommrates($c['id'], -1) >= 1) {
|
||||||
|
$commclass = 'pro';
|
||||||
|
$symb = '+';
|
||||||
|
} else if ((int)Vote::countcommrates($c['id'], -1) < 0) {
|
||||||
|
$commclass = 'con';
|
||||||
|
$symb = '';
|
||||||
|
} else if ((int)Vote::countcommrates($c['id'], -1) === 0) {
|
||||||
|
$commclass = '';
|
||||||
|
}
|
||||||
|
echo '<div class="p-comment p20p">
|
||||||
|
<div class="pc-photo"><a href="/photo/'.$c['photo_id'].'/?top=1" target="_blank" class="prw"><img src="/api/photo/compress?url='.$photo->i('photourl').'" class="f"></a></div>
|
||||||
|
<div class="pc-content">
|
||||||
|
<a class="pc-topost" href="/photo/'.$c['photo_id'].'/?top=1#' . $c['id'] . '" target="_blank">Ссылка</a>
|
||||||
|
<div class="pc-text">
|
||||||
|
<div><span class="cmt-aname">
|
||||||
|
<b><a href="/author/'.$c['user_id'].'/">'.$user->i('username').'</a></b></span> · <span class="sm nw">'.Date::zmdate($c['posted_at']).'</span>
|
||||||
|
<div class="rank">Фото: '.Photo::fetchAll($c['user_id']).''.$admintype.'</div>
|
||||||
|
<div class="message-text feed">'.$c['body'].'</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="pc-compl">
|
||||||
|
<div class="comment-votes-block">
|
||||||
|
|
||||||
|
<div class="wvote" wid="' . $c['id'] . '">
|
||||||
|
<a href="#" vote="1" class="w-btn s2"><span>+</span></a>
|
||||||
|
<div class="w-rating '.$commclass.' active">' . $symb . Vote::countcommrates($c['id'], -1) . '</div>
|
||||||
|
<div class="w-rating-ext">
|
||||||
|
<div><span class="pro">+' . Vote::countcommrates($c['id'], 1) . '</span> / <span class="con">' . Vote::countcommrates($c['id'], 0) . '</span></div>
|
||||||
|
</div>
|
||||||
|
<a href="#" vote="0" class="w-btn s5"><span>–</span></a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>';
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div id="scroll_anchor"></div>
|
||||||
|
<script src="/js/endless.js?031021"></script>
|
||||||
|
<script>
|
||||||
|
var ltime = 1739362440;
|
||||||
|
var last_k = 20;
|
||||||
|
var st = 20;
|
||||||
|
var cnt = -1;
|
||||||
|
var ajaxQuery = '/comments.php?ajax=1&cnt=-1';
|
||||||
|
</script>
|
||||||
|
<script>
|
||||||
|
var ftime = 1739367547;
|
||||||
|
|
||||||
|
function markAllRead(force) {
|
||||||
|
if (confirm('Вы действительно хотите отметить эти комментарии как прочитанные?')) {
|
||||||
|
var ts = force ? 0 : ltime + 1;
|
||||||
|
window.location.href = '?markread=' + ts;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var k = 20;
|
||||||
|
var new_cnt = 0;
|
||||||
|
|
||||||
|
function updateTitle() {
|
||||||
|
document.title = (new_cnt ? '(' + new_cnt + ') ' : '') + $('h1').text();
|
||||||
|
}
|
||||||
|
|
||||||
|
var updateInterval = setInterval(function() {
|
||||||
|
$.get('/comments.php?ajax=1&upd=1', {
|
||||||
|
ltime: ftime
|
||||||
|
}, function(r) {
|
||||||
|
if (!r) return;
|
||||||
|
|
||||||
|
if (r == 'logout') {
|
||||||
|
clearInterval(updateInterval);
|
||||||
|
document.location.href = '/login.php';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($(window).scrollTop() > 100) {
|
||||||
|
var diff = $(document).height();
|
||||||
|
var wrapper = $('<div id="wrapper" style="display:none">' + r + '</div>').insertAfter('#upd_anchor');
|
||||||
|
|
||||||
|
$(window).scrollTop($(window).scrollTop() + wrapper.height());
|
||||||
|
|
||||||
|
wrapper.show();
|
||||||
|
wrapper.children().eq(0).unwrap();
|
||||||
|
} else $('#upd_anchor').after(r);
|
||||||
|
}, 'html');
|
||||||
|
}, 30000);
|
||||||
|
</script>
|
||||||
|
<div id="loader-anchor"></div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<?php include($_SERVER['DOCUMENT_ROOT'] . '/views/components/Footer.php'); ?>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
186
views/pages/Contests/VotingIndex.php
Normal file
|
@ -0,0 +1,186 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use \App\Services\{Auth, DB, Date};
|
||||||
|
use \App\Models\{User};
|
||||||
|
|
||||||
|
?>
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="ru">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<?php include($_SERVER['DOCUMENT_ROOT'] . '/views/components/LoadHead.php'); ?>
|
||||||
|
|
||||||
|
|
||||||
|
</head>
|
||||||
|
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div id="backgr"></div>
|
||||||
|
<table class="tmain">
|
||||||
|
<?php include($_SERVER['DOCUMENT_ROOT'] . '/views/components/Navbar.php'); ?>
|
||||||
|
<script>
|
||||||
|
|
||||||
|
var kid = <?=DB::query('SELECT id FROM contests WHERE status=2')[0]['id']?>;
|
||||||
|
var tipTimeout = null;
|
||||||
|
|
||||||
|
|
||||||
|
function hideTip()
|
||||||
|
{
|
||||||
|
$('#tip').fadeOut('fast', function()
|
||||||
|
{
|
||||||
|
$(this).attr('lock', 0);
|
||||||
|
$('#img').html('');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
$(document).ready(function()
|
||||||
|
{
|
||||||
|
$('.contestBtn').click(function()
|
||||||
|
{
|
||||||
|
var pid = $(this).attr('pid');
|
||||||
|
var savedClass = $(this).attr('class');
|
||||||
|
$(this).addClass('loading');
|
||||||
|
|
||||||
|
$.getJSON('/api/photo/contests/rate', { action: 'vote-contest', kid: kid, pid: pid }, function (data)
|
||||||
|
{
|
||||||
|
if (data[0])
|
||||||
|
{
|
||||||
|
for (var pid in data[0])
|
||||||
|
$('.contestBtn[pid="' + pid + '"]').attr('class', 'contestBtn' + (data[0][pid] == 0 ? '' : ' voted'));
|
||||||
|
}
|
||||||
|
else $('.contestBtn[pid="' + pid + '"]').attr('class', savedClass);
|
||||||
|
|
||||||
|
if (data[1]) alert(data[1]);
|
||||||
|
})
|
||||||
|
.fail(function(jx) { alert(jx.responseText); });
|
||||||
|
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
$(document).on('mouseenter', '.f', function()
|
||||||
|
{
|
||||||
|
var hidden_img = $(this).closest('.p20p').prev('img');
|
||||||
|
$('#img').html('<a href="/photo/' + hidden_img.attr('pid') + '/" target="_blank"><img src="' + (hidden_img.length ? hidden_img.attr('src') : this.src.replace('_s', '')) + '"></a>');
|
||||||
|
$('#tip').css('top', $(window).scrollTop() + 20).show();
|
||||||
|
})
|
||||||
|
.on('mouseenter', '.f, #tip', function()
|
||||||
|
{
|
||||||
|
clearTimeout(tipTimeout);
|
||||||
|
var lock = Math.min(parseInt($('#tip').attr('lock')) + 1, 2);
|
||||||
|
$('#tip').attr('lock', lock);
|
||||||
|
})
|
||||||
|
.on('mouseleave', '.f, #tip', function()
|
||||||
|
{
|
||||||
|
var lock = Math.max(parseInt($('#tip').attr('lock')) - 1, 0);
|
||||||
|
$('#tip').attr('lock', lock);
|
||||||
|
tipTimeout = setTimeout(function() { if ($('#tip').attr('lock') == 0) hideTip(); }, 100);
|
||||||
|
})
|
||||||
|
.on('mousemove', '.f, #tip', function(e)
|
||||||
|
{
|
||||||
|
if (e.pageX > $(document).width() * 0.5) hideTip();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
<tr>
|
||||||
|
<td class="main">
|
||||||
|
|
||||||
|
<center>
|
||||||
|
<h1>Фотоконкурс</h1>
|
||||||
|
|
||||||
|
<p class="narrow" style="font-size:19px"><b>Голосование</b> · <a href="/voting/results">Победители</a> · <a href="/voting/rating">Рейтинг</a> · <a href="/voting/waiting">Претенденты</a></p>
|
||||||
|
<div style="margin-top:20px">Чтобы проголосовать, отметьте одну, две или три фотографии, которые Вам понравились</div><br><br>
|
||||||
|
<?php
|
||||||
|
if (DB::query('SELECT status FROM contests WHERE status=2')[0]['status'] != 2) {
|
||||||
|
$contest = DB::query('SELECT * FROM contests WHERE status=1')[0];
|
||||||
|
echo '<div class="p20">
|
||||||
|
<h4>Сейчас конкурс не проводится. Пожалуйста, заходите позже.</h4>
|
||||||
|
</div>
|
||||||
|
<script>startCountdown(' . $contest['openpretendsdate'] . ');</script>
|
||||||
|
<h2>Следующий Фотоконкурс будет через:</h2>
|
||||||
|
<h1 id="countdown"></h1>';
|
||||||
|
} else { ?>
|
||||||
|
<div id="tip" lock="0"><span id="img"></span></div>
|
||||||
|
<?php
|
||||||
|
$contest = DB::query('SELECT * FROM contests WHERE status=2')[0];
|
||||||
|
$photos_contest = DB::query('SELECT * FROM photos WHERE on_contest=2 AND contest_id=:id', array(':id'=>$contest['id']));
|
||||||
|
|
||||||
|
foreach ($photos_contest as $pc) {
|
||||||
|
$user = new User($pc['user_id']);
|
||||||
|
$class = '';
|
||||||
|
if ((int)DB::query('SELECT photo_id FROM contests_rates WHERE photo_id=:pid AND user_id=:uid AND contest_id=:cid', array(':uid' => Auth::userid(), ':pid' => $pc['id'], ':cid' => $contest['id']))[0]['photo_id'] === (int)$pc['id']) {
|
||||||
|
$class = ' voted';
|
||||||
|
}
|
||||||
|
echo '<img pid="'.$pc['id'].'" src="'.$pc['photourl'].'" style="display:none">
|
||||||
|
<div class="p20p">
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<td><a href="#" pid="'.$pc['id'].'" class="contestBtn'.$class.'"></a></td>
|
||||||
|
<td class="pb_photo" id="p2068176"><a href="/photo/'.$pc['id'].'/" target="_blank" class="prw"><img class="f" src="/api/photo/compress?url='.$pc['photourl'].'" data-src="/api/photo/compress?url='.$pc['photourl'].'" alt="630 КБ">
|
||||||
|
<div class="hpshade">
|
||||||
|
<div class="eye-icon">'.DB::query('SELECT COUNT(*) FROM photos_views WHERE photo_id=:id', array(':id'=>$pc['id']))[0]['COUNT(*)'].'</div>
|
||||||
|
</div>
|
||||||
|
</a></td>
|
||||||
|
<td class="pb_descr">
|
||||||
|
<p>'.htmlspecialchars($pc['postbody']).'</p>
|
||||||
|
<p><b class="pw-place">'.htmlspecialchars($pc['place']).'</b></p>
|
||||||
|
<p class="sm"><b>'.Date::zmdate($pc['posted_at']).'</b><br>Автор: <a href="/author/'.$pc['user_id'].'/">'.$user->i('username').'</a></p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>';
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
<br>Число проголосовавших: <b><?=DB::query('SELECT COUNT(DISTINCT user_id) AS unique_user_count FROM contests_rates WHERE contest_id=:id', array(':id'=>$contest['id']))[0]['unique_user_count']?></b><br>Число голосов: <b><?=DB::query('SELECT COUNT(*) FROM contests_rates WHERE contest_id=:id', array(':id'=>$contest['id']))[0]['COUNT(*)']?></b><br><br>
|
||||||
|
|
||||||
|
</center>
|
||||||
|
|
||||||
|
|
||||||
|
<?php }
|
||||||
|
?>
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
</center>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<?php include($_SERVER['DOCUMENT_ROOT'] . '/views/components/Footer.php'); ?>
|
||||||
|
|
||||||
|
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<script>
|
||||||
|
// Установите дату и время, до которого нужно отсчитывать
|
||||||
|
const countdownDate = new Date("Mar 1, 2025 00:00:00").getTime();
|
||||||
|
|
||||||
|
// Обновляем отсчет каждую секунду
|
||||||
|
const x = setInterval(function() {
|
||||||
|
|
||||||
|
// Получаем текущее время
|
||||||
|
const now = new Date().getTime();
|
||||||
|
|
||||||
|
// Вычисляем разницу между целевой датой и текущим временем
|
||||||
|
const distance = countdownDate - now;
|
||||||
|
|
||||||
|
// Вычисляем дни, часы, минуты и секунды
|
||||||
|
const days = Math.floor(distance / (1000 * 60 * 60 * 24));
|
||||||
|
const hours = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
|
||||||
|
const minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60));
|
||||||
|
const seconds = Math.floor((distance % (1000 * 60)) / 1000);
|
||||||
|
|
||||||
|
// Отображаем результат в элементе с id "countdown"
|
||||||
|
document.getElementById("countdown").innerHTML =
|
||||||
|
days + ":" + hours + ":" + minutes + ":" + seconds;
|
||||||
|
|
||||||
|
// Если отсчет завершен, выводим сообщение
|
||||||
|
if (distance < 0) {
|
||||||
|
clearInterval(x);
|
||||||
|
document.getElementById("countdown").innerHTML = "Время истекло!";
|
||||||
|
}
|
||||||
|
}, 1000);
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
0
views/pages/Contests/VotingRating.php
Normal file
84
views/pages/Contests/VotingResults.php
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use \App\Services\{Auth, DB, Date};
|
||||||
|
use \App\Models\{User, Photo};
|
||||||
|
|
||||||
|
?>
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="ru">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<?php include($_SERVER['DOCUMENT_ROOT'] . '/views/components/LoadHead.php'); ?>
|
||||||
|
|
||||||
|
|
||||||
|
</head>
|
||||||
|
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div id="backgr"></div>
|
||||||
|
<table class="tmain">
|
||||||
|
<?php include($_SERVER['DOCUMENT_ROOT'] . '/views/components/Navbar.php'); ?>
|
||||||
|
<?php
|
||||||
|
|
||||||
|
?>
|
||||||
|
<tr>
|
||||||
|
<td class="main">
|
||||||
|
<center>
|
||||||
|
<h1>Победители фотоконкурса</h1>
|
||||||
|
<p class="narrow" style="font-size:19px"><a href="/voting">Голосование</a> · <b>Победители</b> · <a href="/voting/rating">Рейтинг</a> · <a href="/voting/waiting">Претенденты</a></p>
|
||||||
|
<?php
|
||||||
|
$photos = DB::query("SELECT * FROM contests_winners
|
||||||
|
WHERE place BETWEEN 1 AND 3
|
||||||
|
ORDER BY contest_id, place;
|
||||||
|
|
||||||
|
");
|
||||||
|
|
||||||
|
$grouped = [];
|
||||||
|
foreach ($photos as $row) {
|
||||||
|
$grouped[$row['contest_id']][] = $row;
|
||||||
|
}
|
||||||
|
$final_result = [];
|
||||||
|
foreach ($grouped as $contest_id => $rows) {
|
||||||
|
$chunks = array_chunk($rows, 3);
|
||||||
|
foreach ($chunks as $chunk) {
|
||||||
|
$final_result[] = $chunk;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($final_result as $fc) {
|
||||||
|
$themeid = DB::query('SELECT themeid FROM contests WHERE id=:id', array(':id'=>$fc[0]['contest_id']))[0]['themeid'];
|
||||||
|
$theme = DB::query('SELECT title FROM contests_themes WHERE id=:id', array(':id'=>$themeid))[0]['title'];
|
||||||
|
echo '<p><span class="narrow" style="font-size:21px"><b><a href="?show=table&date=2025-02-04" title="Подробный отчёт о конкурсе">'.date('d.m.Y', $fc[0]['date']).'</a></b></span><br><span class="sm">'.$theme.'</span></p>
|
||||||
|
<table>
|
||||||
|
<tr>';
|
||||||
|
foreach ($fc as $f) {
|
||||||
|
$photo = new Photo($f['photo_id']);
|
||||||
|
if ($f['place'] === 1) {
|
||||||
|
$img = 'vs3';
|
||||||
|
} else if ($f['place'] === 2) {
|
||||||
|
$img = 'vs2';
|
||||||
|
} else if ($f['place'] === 3) {
|
||||||
|
$img = 'vs1';
|
||||||
|
}
|
||||||
|
echo '<a href="/photo/'.$f['photo_id'].'/" class="p20" style="display:table-cell; text-align:center; vertical-align:bottom; padding:20px 20px 10px; font-size:17px"><img src="'.$photo->i('photourl').'" class="f" style="margin-bottom:7px"><br><img src="/static/img/'.$img.'.png" style="position:relative; top:-2px"> </a>';
|
||||||
|
}
|
||||||
|
echo '
|
||||||
|
</tr>
|
||||||
|
</table><br>';
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
|
<p class="narrow" style="font-size:19px"><a href="/voting">Голосование</a> · <b>Победители</b> · <a href="/voting/rating">Рейтинг</a> · <a href="/voting/waiting">Претенденты</a></p>
|
||||||
|
</center>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<?php include($_SERVER['DOCUMENT_ROOT'] . '/views/components/Footer.php'); ?>
|
||||||
|
|
||||||
|
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
190
views/pages/Contests/VotingSendPretend.php
Normal file
|
@ -0,0 +1,190 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use \App\Services\{Auth, DB, Date};
|
||||||
|
use \App\Models\{Vehicle, User};
|
||||||
|
|
||||||
|
function convertUnixToRussianDateTime($unixTime)
|
||||||
|
{
|
||||||
|
// Создаем объект DateTime из Unix-времени
|
||||||
|
$dateTime = new DateTime("@$unixTime");
|
||||||
|
|
||||||
|
// Устанавливаем временную зону (можно изменить на нужную)
|
||||||
|
$dateTime->setTimezone(new DateTimeZone('Europe/Moscow'));
|
||||||
|
|
||||||
|
// Форматируем дату и время с использованием IntlDateFormatter
|
||||||
|
$formatter = new IntlDateFormatter(
|
||||||
|
'ru_RU',
|
||||||
|
IntlDateFormatter::LONG,
|
||||||
|
IntlDateFormatter::NONE,
|
||||||
|
'Europe/Moscow',
|
||||||
|
IntlDateFormatter::GREGORIAN,
|
||||||
|
'd MMMM yyyy года в H:mm'
|
||||||
|
);
|
||||||
|
|
||||||
|
return $formatter->format($dateTime);
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="ru">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<?php include($_SERVER['DOCUMENT_ROOT'] . '/views/components/LoadHead.php'); ?>
|
||||||
|
|
||||||
|
|
||||||
|
</head>
|
||||||
|
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div id="backgr"></div>
|
||||||
|
<table class="tmain">
|
||||||
|
<?php include($_SERVER['DOCUMENT_ROOT'] . '/views/components/Navbar.php'); ?>
|
||||||
|
<tr>
|
||||||
|
<td class="main">
|
||||||
|
<h1>Принять участие в Фотоконкурсе</h1>
|
||||||
|
<script src="/js/jquery-ui.js?1633005526"></script>
|
||||||
|
<script src="/js/selector.js?1730197663"></script>
|
||||||
|
|
||||||
|
<form id="sendForm" method="post" id="mform">
|
||||||
|
|
||||||
|
<h4>В каком Фотоконкурсе вы хотите принять участие?</h4>
|
||||||
|
<div class="p20w">
|
||||||
|
<table>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<th></th>
|
||||||
|
<th>Тематика</th>
|
||||||
|
<th>Старт набора претендентов</th>
|
||||||
|
<th>Закрытие набора претендентов</th>
|
||||||
|
<th>Начало проведения</th>
|
||||||
|
<th>Итоги и победители</th>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<?php
|
||||||
|
$entities = DB::query('SELECT * FROM contests WHERE closepretendsdate>=:id', array(':id' => time()));
|
||||||
|
foreach ($entities as $e) {
|
||||||
|
$theme = DB::query('SELECT * FROM contests_themes WHERE id=:id', array(':id' => $e['themeid']))[0];
|
||||||
|
echo '<tr>
|
||||||
|
<td class="ds"><input type="radio" name="cid" id="n' . $e['id'] . '" value="' . $e['id'] . '" onclick="fillFields(' . $e['id'] . ')"></td>
|
||||||
|
<td class="n">' . $theme['title'] . '</td>
|
||||||
|
<td class="ds">' . convertUnixToRussianDateTime($e['openpretendsdate']) . '</td>
|
||||||
|
<td class="ds">' . convertUnixToRussianDateTime($e['closepretendsdate']) . '</td>
|
||||||
|
<td class="ds">' . convertUnixToRussianDateTime($e['opendate']) . '</td>
|
||||||
|
<td class="ds">' . convertUnixToRussianDateTime($e['closedate']) . '</td>
|
||||||
|
</tr>';
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
|
||||||
|
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<br clear="all"><br>
|
||||||
|
|
||||||
|
<div class="p20" style="padding-left:5px; margin-bottom:15px">
|
||||||
|
<table class="nospaces" width="100%">
|
||||||
|
<tbody>
|
||||||
|
<?php
|
||||||
|
$vehicle = DB::query('SELECT * FROM entities WHERE id=:id', array(':id' => $_GET['type']))[0];
|
||||||
|
$data = json_decode($vehicle['sampledata'], true);
|
||||||
|
$count = 1;
|
||||||
|
foreach ($data as $d) {
|
||||||
|
|
||||||
|
if ($d['important'] === "1") {
|
||||||
|
$imp = 'required';
|
||||||
|
}
|
||||||
|
echo '
|
||||||
|
<tr>
|
||||||
|
<td class="lcol">' . $d['name'] . '</td>
|
||||||
|
<td style="padding-bottom:15px"><input type="text" name="modelinput_' . $count . '" id="num" style="width:80px" maxlength="21" value=""></td>
|
||||||
|
</tr>';
|
||||||
|
$count++;
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
<tr>
|
||||||
|
<td style="width: 10%"></td>
|
||||||
|
|
||||||
|
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<tr>
|
||||||
|
<td class="lcol">Фотография, которую вы хотите отправить на Фотоконкурс</td>
|
||||||
|
<td style="padding-bottom:15px">
|
||||||
|
<select id="photoId" name="photo_id">
|
||||||
|
<option value="'.$p['id'].'" disabled selected>Выберите фотографию</option>
|
||||||
|
<?php
|
||||||
|
$photos = DB::query('SELECT * FROM photos WHERE user_id=:uid AND on_contest=0', array(':uid' => Auth::userid()));
|
||||||
|
foreach ($photos as $p) {
|
||||||
|
$content = json_decode($p['content'], true);
|
||||||
|
if (($content['video'] === null || $content['type'] === 'image') && $p['moderated'] === 1) {
|
||||||
|
echo '<option photourl="/api/photo/compress?url=' . $p['photourl'] . '" value="' . $p['id'] . '">[ID: ' . $p['id'] . '] ' . $p['place'] . '</option>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
</select>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
<td>
|
||||||
|
<div id="result"></div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<br>
|
||||||
|
<input type="submit" value=" Отправить ">
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<script>
|
||||||
|
|
||||||
|
$('#sendForm').submit(function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
$.ajax({
|
||||||
|
type: "POST",
|
||||||
|
url: '/api/photo/contests/sendpretend',
|
||||||
|
data: $(this).serialize(),
|
||||||
|
success: function(response) {
|
||||||
|
var jsonData = JSON.parse(response);
|
||||||
|
if (jsonData.errorcode === 0) {
|
||||||
|
alert('Фотография успешно отправлена на претенденты на Фотоконкурс');
|
||||||
|
} else {
|
||||||
|
alert('Пожалуйста, выберите Фотоконкурс на который вы хотите отправить фотографию!');
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
document.getElementById('photoId').addEventListener('change', function() {
|
||||||
|
const selectedOption = this.options[this.selectedIndex];
|
||||||
|
const photoUrl = selectedOption.getAttribute('photourl');
|
||||||
|
|
||||||
|
if (photoUrl) {
|
||||||
|
const imgElement = document.createElement('img');
|
||||||
|
imgElement.src = photoUrl;
|
||||||
|
imgElement.alt = 'Изображение';
|
||||||
|
imgElement.style.maxWidth = '500px';
|
||||||
|
|
||||||
|
const resultDiv = document.getElementById('result');
|
||||||
|
resultDiv.innerHTML = '';
|
||||||
|
resultDiv.appendChild(imgElement);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
<tr>
|
||||||
|
|
||||||
|
<?php include($_SERVER['DOCUMENT_ROOT'] . '/views/components/Footer.php'); ?>
|
||||||
|
|
||||||
|
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
140
views/pages/Contests/VotingWaiting.php
Normal file
|
@ -0,0 +1,140 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use \App\Services\{Auth, DB, Date};
|
||||||
|
use \App\Models\{User, VoteContest, Vote};
|
||||||
|
|
||||||
|
?>
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="ru">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<?php include($_SERVER['DOCUMENT_ROOT'] . '/views/components/LoadHead.php'); ?>
|
||||||
|
|
||||||
|
|
||||||
|
</head>
|
||||||
|
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div id="backgr"></div>
|
||||||
|
<table class="tmain">
|
||||||
|
<?php include($_SERVER['DOCUMENT_ROOT'] . '/views/components/Navbar.php'); ?>
|
||||||
|
<tr>
|
||||||
|
<td class="main">
|
||||||
|
<center>
|
||||||
|
<h1>Претенденты на участие в конкурсе</h1>
|
||||||
|
<script>
|
||||||
|
var self_p = false;
|
||||||
|
var pid = 0;
|
||||||
|
</script>
|
||||||
|
<p class="narrow" style="font-size:19px"><a href="/voting">Голосование</a> · <a href="/voting/results">Победители</a> · <a href="/voting/rating">Рейтинг</a> · <b>Претенденты</b></p>
|
||||||
|
<p style="margin:20px">На этой странице собраны фотографии, предложенные для участия в конкурсе их авторами либо пользователями сайта, для того, чтобы Вы проголосовали за их участие или против. Снимки отсортированы по времени публикации.<br><br>Пожалуйста, не стесняйтесь нажимать синюю кнопку.</p>
|
||||||
|
<?php
|
||||||
|
if (DB::query('SELECT status FROM contests WHERE status=1')[0]['status'] === 1) {
|
||||||
|
$contest = DB::query('SELECT * FROM contests WHERE status=1')[0];
|
||||||
|
$photos_contest = DB::query('SELECT p.*, COUNT(prc.photo_id) AS rates_count
|
||||||
|
FROM photos p
|
||||||
|
LEFT JOIN photos_rates_contest prc ON p.id = prc.photo_id
|
||||||
|
WHERE p.on_contest = 1 AND p.contest_id = :id
|
||||||
|
GROUP BY p.id
|
||||||
|
ORDER BY rates_count DESC;
|
||||||
|
', array(':id'=>$contest['id']));
|
||||||
|
|
||||||
|
foreach ($photos_contest as &$photo) {
|
||||||
|
$photo['votes'] = VoteContest::count($pc['id'], $contest['id']);
|
||||||
|
}
|
||||||
|
|
||||||
|
usort($photos_contest, function ($a, $b) {
|
||||||
|
return $b['votes'] <=> $a['votes'];
|
||||||
|
});
|
||||||
|
foreach ($photos_contest as $pc) {
|
||||||
|
$user = new User($pc['user_id']);
|
||||||
|
if (VoteContest::photo(Auth::userid(), $pc['id'], $contest['id']) === 1) {
|
||||||
|
$classp = 'voted';
|
||||||
|
} else if (VoteContest::photo(Auth::userid(), $pc['id'], $contest['id']) === 0) {
|
||||||
|
$classm = 'voted';
|
||||||
|
}
|
||||||
|
echo '<div class="p20p">
|
||||||
|
<table>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td class="pb_pre vote" style="padding-left:15px; padding-right:10px; display:table-cell" cid="'.$contest['id'].'" pid="'.$pc['id'].'">
|
||||||
|
<a href="#" vote="1" class="konk_btn '.$classp.'"><span>Красиво, на конкурс!</span></a>
|
||||||
|
<table style="margin:5px 0 7px; width:100px">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td style="width:20px"><img class="loader" pid="2072294" src="/img/loader.gif"></td>
|
||||||
|
<td align="center" style="padding:2px"><b class="s_rating" pid="'.$pc['id'].'">'.VoteContest::count($pc['id'], $contest['id']).'</b></td>
|
||||||
|
<td style="width:20px; display:table-cell" class="star" pid="2072294"><img src="/img/star_people.png" alt=""></td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<a href="#" vote="0" class="konk_btn '.$classm.'"><span>Неконкурсное фото</span></a>
|
||||||
|
</td>
|
||||||
|
<td class="pb_photo" id="p2072294"><a href="/photo/'.$pc['id'].'" target="_blank" class="prw"><img class="f" src="/api/photo/compress?url='.$pc['photourl'].'" alt="597 КБ" style="display: inline;">
|
||||||
|
<div class="hpshade">
|
||||||
|
<div class="eye-icon">'.DB::query('SELECT COUNT(*) FROM photos_views WHERE photo_id=:id', array(':id'=>$pc['id']))[0]['COUNT(*)'].'</div>
|
||||||
|
</div>
|
||||||
|
</a></td>
|
||||||
|
<td class="pb_descr">
|
||||||
|
<p>'.htmlspecialchars($pc['postbody']).'</p>
|
||||||
|
<p><b class="pw-place">'.htmlspecialchars($pc['place']).'</b></p>
|
||||||
|
<p class="sm"><b>'.Date::zmdate($pc['posted_at']).'</b><br>Автор: <a href="/author/'.$pc['user_id'].'/">'.$user->i('username').'</a></p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>';
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
echo '<h2><b>Следующего конкурса нет. Пожалуйста, заходите сюда позже.</b></h2>';
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<br>
|
||||||
|
<p class="narrow" style="font-size:19px"><a href="/voting">Голосование</a> · <a href="/voting/results">Победители</a> · <a href="/voting/rating">Рейтинг</a> · <b>Претенденты</b></p>
|
||||||
|
</center>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<?php include($_SERVER['DOCUMENT_ROOT'] . '/views/components/Footer.php'); ?>
|
||||||
|
|
||||||
|
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<script>
|
||||||
|
// Установите дату и время, до которого нужно отсчитывать
|
||||||
|
const countdownDate = new Date("Mar 1, 2025 00:00:00").getTime();
|
||||||
|
|
||||||
|
// Обновляем отсчет каждую секунду
|
||||||
|
const x = setInterval(function() {
|
||||||
|
|
||||||
|
// Получаем текущее время
|
||||||
|
const now = new Date().getTime();
|
||||||
|
|
||||||
|
// Вычисляем разницу между целевой датой и текущим временем
|
||||||
|
const distance = countdownDate - now;
|
||||||
|
|
||||||
|
// Вычисляем дни, часы, минуты и секунды
|
||||||
|
const days = Math.floor(distance / (1000 * 60 * 60 * 24));
|
||||||
|
const hours = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
|
||||||
|
const minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60));
|
||||||
|
const seconds = Math.floor((distance % (1000 * 60)) / 1000);
|
||||||
|
|
||||||
|
// Отображаем результат в элементе с id "countdown"
|
||||||
|
document.getElementById("countdown").innerHTML =
|
||||||
|
days + ":" + hours + ":" + minutes + ":" + seconds;
|
||||||
|
|
||||||
|
// Если отсчет завершен, выводим сообщение
|
||||||
|
if (distance < 0) {
|
||||||
|
clearInterval(x);
|
||||||
|
document.getElementById("countdown").innerHTML = "Время истекло!";
|
||||||
|
}
|
||||||
|
}, 1000);
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
|
@ -1,46 +0,0 @@
|
||||||
<?php
|
|
||||||
header("HTTP/1.1 403 Forbidden");
|
|
||||||
?>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<style>body {
|
|
||||||
font-family: sans-serif;
|
|
||||||
position: relative;
|
|
||||||
height: 100vh;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
#dbErrorBody {
|
|
||||||
position: absolute;
|
|
||||||
top: 50%;
|
|
||||||
left: 50%;
|
|
||||||
margin-right: -50%;
|
|
||||||
transform: translate(-50%, -50%);
|
|
||||||
width: 400px;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
#dbErrorBody h1 {
|
|
||||||
margin-top: 5px;
|
|
||||||
margin-bottom: 2px;
|
|
||||||
}
|
|
||||||
#dbErrorBody span {
|
|
||||||
color: grey;
|
|
||||||
}
|
|
||||||
#dbErrorBody img {
|
|
||||||
max-width: 256px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
<title>Resource Busy</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div id="dbErrorBody">
|
|
||||||
<img src="/static/img/busy.png" alt="Error">
|
|
||||||
<h1>Вы не участвуете в программе тестирования Birux Streams</h1>
|
|
||||||
<span>К сожалению, мы уже набрали достаточное количество участников. Следующая волна заявок будет скоро — следите в Telegram-канале
|
|
||||||
<a href="https://t.me/biruxch">Birux</a>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,44 +0,0 @@
|
||||||
<?php
|
|
||||||
header("HTTP/1.1 403 Forbidden");
|
|
||||||
?>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<style>body {
|
|
||||||
font-family: sans-serif;
|
|
||||||
position: relative;
|
|
||||||
height: 100vh;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
#dbErrorBody {
|
|
||||||
position: absolute;
|
|
||||||
top: 50%;
|
|
||||||
left: 50%;
|
|
||||||
margin-right: -50%;
|
|
||||||
transform: translate(-50%, -50%);
|
|
||||||
width: 400px;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
#dbErrorBody h1 {
|
|
||||||
margin-top: 5px;
|
|
||||||
margin-bottom: 2px;
|
|
||||||
}
|
|
||||||
#dbErrorBody span {
|
|
||||||
color: grey;
|
|
||||||
}
|
|
||||||
#dbErrorBody img {
|
|
||||||
max-width: 256px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
<title>Resource Busy</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div id="dbErrorBody">
|
|
||||||
<img src="/static/img/busy.png" alt="Error">
|
|
||||||
<h1>Доступ запрещён!</h1>
|
|
||||||
<span>Такие дела. Эфир не принадлежит вам.</span>
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
0
views/pages/Live.php
Normal file
|
@ -78,7 +78,11 @@ LIMIT 10;');
|
||||||
<img width="250" src="/api/photo/compress?url=' . $p['photourl'] . '">
|
<img width="250" src="/api/photo/compress?url=' . $p['photourl'] . '">
|
||||||
<div class="hpshade">
|
<div class="hpshade">
|
||||||
<div class="eye-icon">+' . $pd['view_count'] . '</div>
|
<div class="eye-icon">+' . $pd['view_count'] . '</div>
|
||||||
</div>
|
</div>';
|
||||||
|
if ((int)$p['priority'] === 1) {
|
||||||
|
echo '<div class="temp" style="background-image:url(/static/img/cond.png)"></div>';
|
||||||
|
}
|
||||||
|
echo '
|
||||||
</a>';
|
</a>';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -118,6 +122,85 @@ LIMIT 10;');
|
||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
</div>
|
</div>
|
||||||
|
<style>
|
||||||
|
#contestNotify {
|
||||||
|
background-size: 550px 211.2px;
|
||||||
|
background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 550 211.2" width="550" height="211.2" style="opacity: 0.3; filter: grayscale(0);"><text x="0em" y="1em" font-size="88" transform="rotate(17 55 52.8)">🎁</text><text x="1.25em" y="2em" font-size="88" transform="rotate(17 165 140.8)">🎈</text><text x="2.5em" y="1em" font-size="88" transform="rotate(17 275 52.8)">🎀</text><text x="3.75em" y="2em" font-size="88" transform="rotate(17 385 140.8)">🎊</text><text x="5em" y="1em" font-size="88" transform="rotate(17 495 52.8)">🎉</text></svg>');
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<?php
|
||||||
|
if (DB::query('SELECT status FROM contests WHERE status=2')[0]['status'] === 2) {
|
||||||
|
$contest = DB::query('SELECT * FROM contests WHERE status=2')[0];
|
||||||
|
$theme = DB::query('SELECT * FROM contests_themes WHERE id=:id', array(':id' => $contest['themeid']))[0];
|
||||||
|
echo ' <div id="contestNotify" style="float:left; border:solid 1px #171022; padding:6px 10px 7px; margin-bottom:13px; background-color:#E5D6FF"><h4>Фотоконкурс!</h4>
|
||||||
|
<span id="timett">Закончится через:</span> <b id="countdown"></b><br>
|
||||||
|
Тематика: <b>' . $theme['title'] . '</b><br>
|
||||||
|
<b style="color: #412378;">Голосуйте за лучшие фотографии, которые должны стать победителями сегодняшнего конкурса!</b><br><br>
|
||||||
|
<div id="contestBtns"><a href="/voting" style="background-color: #37009D; color: #fff;" type="button">Голосовать!</a></div>
|
||||||
|
<script>startCountdown(' . $contest['closedate'] . ');</script>';
|
||||||
|
} else if (DB::query('SELECT status FROM contests WHERE status=1')[0]['status'] === 1) {
|
||||||
|
$contest = DB::query('SELECT * FROM contests WHERE status=1')[0];
|
||||||
|
$theme = DB::query('SELECT * FROM contests_themes WHERE id=:id', array(':id' => $contest['themeid']))[0];
|
||||||
|
echo ' <div id="contestNotify" style="float:left; border:solid 1px #171022; padding:6px 10px 7px; margin-bottom:13px; background-color:#E5D6FF"><h4>Фотоконкурс!</h4>
|
||||||
|
<span id="timett">Начнётся через:</span> <b id="countdown"></b><br>
|
||||||
|
Тематика: <b>' . $theme['title'] . '</b><br>
|
||||||
|
<b id="textContest" style="color: #412378;">Лучшие фотографии по мнению сообщества ' . NGALLERY['root']['title'] . ' будут отмечены</b><br><br>
|
||||||
|
<div id="contestBtns"><a href="/voting/sendpretend" style="background-color: #37009D; color: #fff;" type="button">Участвовать!</a> <a href="/voting/waiting" style="background-color: #37009D; color: #fff;" type="button">Голосовать за претендентов</a></div>
|
||||||
|
<script>
|
||||||
|
$(document).ready(function () {
|
||||||
|
let unixThreshold = '.$contest['closepretendsdate'].'; // Задайте нужное значение UNIX
|
||||||
|
let checkInterval = 1000; // Интервал проверки в миллисекундах (1 секунда)
|
||||||
|
let isRequestSent = false;
|
||||||
|
|
||||||
|
function checkUnixTime() {
|
||||||
|
let currentUnixTime = Math.floor(Date.now() / 1000);
|
||||||
|
|
||||||
|
if (currentUnixTime > unixThreshold) {
|
||||||
|
$("#countdown").text("Ожидаем ответ от сервера...");
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
url: "/api/contests/getinfo", // Укажите свой URL
|
||||||
|
method: "GET",
|
||||||
|
success: function (response) {
|
||||||
|
|
||||||
|
let data = typeof response === "string" ? JSON.parse(response) : response;
|
||||||
|
if (data.statuses.pretends === "closed" && data.statuses.public === "opened") {
|
||||||
|
clearInterval(pingInterval); // Останавливаем старый пинг
|
||||||
|
$("#textContest").text("Голосуйте за лучшие фотографии, которые должны стать победителями сегодняшнего конкурса!");
|
||||||
|
$("#timett").text("Закончится через:");
|
||||||
|
$("#contestBtns").html(`<a href="/voting" style="background-color: #37009D; color: #fff;" type="button">Голосовать!</a>`)
|
||||||
|
unixThreshold = data.contest.closedate;
|
||||||
|
startCountdown(data.contest.closedate);
|
||||||
|
pingInterval = setInterval(checkUnixTime, checkInterval);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
error: function (xhr, status, error) {
|
||||||
|
console.error("Ошибка запроса:", error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
console.log(currentUnixTime);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Запускаем периодический пинг
|
||||||
|
let pingInterval = setInterval(checkUnixTime, checkInterval);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
</script>';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
?>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -125,42 +208,32 @@ LIMIT 10;');
|
||||||
|
|
||||||
|
|
||||||
<h4 style="clear:both"><a href="/update">Недавно добавленные фотографии</a></h4>
|
<h4 style="clear:both"><a href="/update">Недавно добавленные фотографии</a></h4>
|
||||||
<div id="recent-photos" class="ix-photos ix-photos-multiline" lastpid="1970527" firstpid="1970550">
|
|
||||||
<?php
|
|
||||||
$photos = DB::query('SELECT * FROM photos WHERE moderated=1 ORDER BY id DESC LIMIT 30');
|
|
||||||
foreach ($photos as $p) {
|
|
||||||
if ($p['posted_at'] === 943909200 || Date::zmdate($p['posted_at']) === '30 ноября 1999 в 00:00') {
|
|
||||||
$date = 'дата не указана';
|
|
||||||
} else {
|
|
||||||
$date = Date::zmdate($p['posted_at']);
|
|
||||||
}
|
|
||||||
$bck = 'background-image:url("/api/photo/compress?url=' . $p['photourl'] . '")';
|
|
||||||
echo ' <div class="prw-grid-item">
|
|
||||||
<div class="prw-wrapper"><span style="word-spacing:-1px"><b>' . htmlspecialchars($p['place']) . '</b></span>
|
|
||||||
<div>' . $date . '</div>
|
|
||||||
</div>
|
|
||||||
'; ?>
|
|
||||||
<a href="/photo/<?= $p['id'] ?>" target="_blank" class="prw-animate" style='background-image:url("/api/photo/compress?url=<?= $p['photourl'] ?>")'></a>
|
|
||||||
</div>
|
|
||||||
<?php }
|
|
||||||
?>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h4>Сейчас на сайте (<?= DB::query('SELECT COUNT(*) FROM users WHERE online>=:time-300 ORDER BY online DESC', array(':time' => time()))[0]['COUNT(*)'] ?>)</h4>
|
|
||||||
<div>
|
|
||||||
<?php
|
<?php
|
||||||
$online = DB::query('SELECT * FROM users WHERE online>=:time-300 ORDER BY online DESC', array(':time' => time()));
|
$photos = DB::query('SELECT * FROM photos WHERE moderated=1 ORDER BY id DESC LIMIT 30');
|
||||||
foreach ($online as $o) {
|
|
||||||
echo '<a href="/author/' . $o['id'] . '/">' . htmlspecialchars($o['username']) . '</a>, ';
|
|
||||||
}
|
|
||||||
?>
|
|
||||||
|
|
||||||
</div>
|
$first_id = $photos[0]['id'];
|
||||||
|
$last_id = end($photos)['id'];
|
||||||
|
?>
|
||||||
|
<div id="recent-photos" class="ix-photos ix-photos-multiline" lastpid="<?= $first_id + 1 ?>" firstpid="<?= $last_id ?>">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div style="text-align:center; margin:10px 0"><input type="button" name="button" id="loadmore" class="" value="Загрузить ещё"></div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h4>Сейчас на сайте (<?= DB::query('SELECT COUNT(*) FROM users WHERE online>=:time-300 ORDER BY online DESC', array(':time' => time()))[0]['COUNT(*)'] ?>)</h4>
|
||||||
|
<div>
|
||||||
|
<?php
|
||||||
|
$online = DB::query('SELECT * FROM users WHERE online>=:time-300 ORDER BY online DESC', array(':time' => time()));
|
||||||
|
foreach ($online as $o) {
|
||||||
|
echo '<a href="/author/' . $o['id'] . '/">' . htmlspecialchars($o['username']) . '</a>, ';
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
|
||||||
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td style="padding-left:20px; width:254px; vertical-align:top">
|
<td style="padding-left:20px; width:254px; vertical-align:top">
|
||||||
|
|
||||||
|
@ -169,8 +242,8 @@ LIMIT 10;');
|
||||||
<?php
|
<?php
|
||||||
$news = DB::query('SELECT * FROM news ORDER BY id DESC LIMIT 10');
|
$news = DB::query('SELECT * FROM news ORDER BY id DESC LIMIT 10');
|
||||||
foreach ($news as $n) {
|
foreach ($news as $n) {
|
||||||
echo '<div class="ix-news-item"><b>'.Date::zmdate($n['time']).'</b>
|
echo '<div class="ix-news-item"><b>' . Date::zmdate($n['time']) . '</b>
|
||||||
<div class="break-links" style="padding-top:3px">'.$n['body'].'</div>
|
<div class="break-links" style="padding-top:3px">' . $n['body'] . '</div>
|
||||||
</div>';
|
</div>';
|
||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
|
|
0
views/pages/Page.php
Normal file
|
@ -125,6 +125,25 @@ if ($photo->i('id') !== null) {
|
||||||
<img onerror="errimg(); this.onerror = null;" id="ph" src="<?= $photo->i('photourl') ?>" alt="" title="Фотография">
|
<img onerror="errimg(); this.onerror = null;" id="ph" src="<?= $photo->i('photourl') ?>" alt="" title="Фотография">
|
||||||
<?php
|
<?php
|
||||||
}
|
}
|
||||||
|
if ($photo->i('on_contest') === 2) { ?>
|
||||||
|
<a class="underphoto" href="/voting"><img style="margin-top:-4px" src="/static/img/star_people.png"> Фотография участвует в голосовании</a>
|
||||||
|
|
||||||
|
<?php }
|
||||||
|
|
||||||
|
foreach ($photo->content('contests') as $c) {
|
||||||
|
if ($c['place'] === 1) {
|
||||||
|
$img = '3';
|
||||||
|
}
|
||||||
|
if ($c['place'] === 2) {
|
||||||
|
$img = '2';
|
||||||
|
}
|
||||||
|
if ($c['place'] === 3) {
|
||||||
|
$img = '1';
|
||||||
|
}
|
||||||
|
echo '<a class="underphoto" style="font-weight:bold" href="/pk.php?pid=2068816&type=d"><img style="margin-top:-4px" src="/static/img/vs'.$img.'.png"> '.$c['place'].'-е место на фотоконкурсе</a>';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if ($photo->i('priority') === 1) { ?>
|
if ($photo->i('priority') === 1) { ?>
|
||||||
<div class="underphoto s17" style="cursor:help" title="Фотография не удовлетворяет действующим на момент публикации критериям качества снимков."><i style="position:relative; top:1px" class="fas fa-info-circle"></i> <b class="dot">Условная публикация</b></div>
|
<div class="underphoto s17" style="cursor:help" title="Фотография не удовлетворяет действующим на момент публикации критериям качества снимков."><i style="position:relative; top:1px" class="fas fa-info-circle"></i> <b class="dot">Условная публикация</b></div>
|
||||||
<?php } else if ($photo->i('priority') === 2) { ?>
|
<?php } else if ($photo->i('priority') === 2) { ?>
|
||||||
|
@ -172,8 +191,8 @@ if ($photo->i('id') !== null) {
|
||||||
<table class="pwrite">
|
<table class="pwrite">
|
||||||
<tr>
|
<tr>
|
||||||
<?php
|
<?php
|
||||||
if ($photo->i('postbody') != null) { ?>
|
if ($photo->i('place') != null) { ?>
|
||||||
<td class="nw" valign="top" align="right"><b><?= htmlspecialchars($photo->i('postbody')) ?></b></td>
|
<td class="nw" valign="top" align="right"><b><?= htmlspecialchars($photo->i('place')) ?></b></td>
|
||||||
<?php } ?>
|
<?php } ?>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
@ -197,7 +216,7 @@ if ($photo->i('id') !== null) {
|
||||||
<?php } ?>
|
<?php } ?>
|
||||||
<div>
|
<div>
|
||||||
<?php
|
<?php
|
||||||
if ($photo->content('comment') != null) { ?>
|
if ($photo->content('comment') != null) { ?>
|
||||||
<div style="padding-top:8px"><?= htmlspecialchars($photo->content('comment')) ?></div>
|
<div style="padding-top:8px"><?= htmlspecialchars($photo->content('comment')) ?></div>
|
||||||
<?php } ?>
|
<?php } ?>
|
||||||
</div><br>
|
</div><br>
|
||||||
|
@ -222,6 +241,8 @@ if ($photo->i('id') !== null) {
|
||||||
<a href="/photoext?id=<?= $id ?>">Подробная информация</a>
|
<a href="/photoext?id=<?= $id ?>">Подробная информация</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<?php
|
||||||
|
if (Auth::userid() > 0) { ?>
|
||||||
<div class="p0" id="pp-item-tools">
|
<div class="p0" id="pp-item-tools">
|
||||||
<h4 class="pp-item-header">Инструменты</h4>
|
<h4 class="pp-item-header">Инструменты</h4>
|
||||||
<div class="pp-item-body" style="margin:7px 5px">
|
<div class="pp-item-body" style="margin:7px 5px">
|
||||||
|
@ -239,6 +260,7 @@ if ($photo->i('id') !== null) {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<?php } ?>
|
||||||
<?php if ($photo->i('moderated') === 1 && $photo->content('rating') != 'disabled') { ?>
|
<?php if ($photo->i('moderated') === 1 && $photo->content('rating') != 'disabled') { ?>
|
||||||
<div class="p20a" id="pp-item-vote">
|
<div class="p20a" id="pp-item-vote">
|
||||||
<h4 class="pp-item-header">Оценка</h4>
|
<h4 class="pp-item-header">Оценка</h4>
|
||||||
|
@ -247,7 +269,7 @@ if ($photo->i('id') !== null) {
|
||||||
<div class="rtext">Рейтинг: <b id="rating"><?= Vote::count($id) ?></b></div>
|
<div class="rtext">Рейтинг: <b id="rating"><?= Vote::count($id) ?></b></div>
|
||||||
<div class="star" pid="1361063"></div>
|
<div class="star" pid="1361063"></div>
|
||||||
<?php
|
<?php
|
||||||
if (Auth::userid() > 0) { ?>
|
if (Auth::userid() > 0 && (NGALLERY['root']['registration']['emailverify'] != true || $user->i('status') != 3)) { ?>
|
||||||
<div class="vote" pid="<?= $id ?>">
|
<div class="vote" pid="<?= $id ?>">
|
||||||
<a href="#" vote="1" class="vote_btn <?php if (Vote::photo(Auth::userid(), $id) === 1) {
|
<a href="#" vote="1" class="vote_btn <?php if (Vote::photo(Auth::userid(), $id) === 1) {
|
||||||
echo 'voted';
|
echo 'voted';
|
||||||
|
@ -255,14 +277,24 @@ if ($photo->i('id') !== null) {
|
||||||
<a href="#" vote="0" class="vote_btn <?php if (Vote::photo(Auth::userid(), $id) === 0) {
|
<a href="#" vote="0" class="vote_btn <?php if (Vote::photo(Auth::userid(), $id) === 0) {
|
||||||
echo 'voted';
|
echo 'voted';
|
||||||
} ?>"><span>Мне не нравится</span></a>
|
} ?>"><span>Мне не нравится</span></a>
|
||||||
<!--a class="konk_btn" vote="1" href="#"><span>Красиво, на конкурс!</span></!--a>
|
<?php
|
||||||
<a-- href="#" vote="0" class="konk_btn"><span>Неконкурсное фото</span></a-->
|
if (($photo->content('video') === null && $photo->i('user_id') != Auth::userid()) || $photo->i('on_contest') != 2) { ?>
|
||||||
|
<a class="konk_btn <?php if (Vote::photoContest(Auth::userid(), $id) === 1) {
|
||||||
|
echo 'voted';
|
||||||
|
} ?>" vote="1" href="#"><span>Красиво, на конкурс!</span></a>
|
||||||
|
<a href="#" vote="0" class="konk_btn <?php if (Vote::photoContest(Auth::userid(), $id) === 0) {
|
||||||
|
echo 'voted';
|
||||||
|
} ?>"><span>Неконкурсное фото</span></a>
|
||||||
|
<?php } else if ($photo->i('user_id') === Auth::userid() && $photo->i('on_contest') != 2) { ?>
|
||||||
|
|
||||||
|
<a href="#" vote="1" class="konk_btn"><span>Выставить на конкурс</span></a><a href="#" vote="0" class="konk_btn"><span>Не участвовать в конкурсе</span></a></div>
|
||||||
|
<?php } ?>
|
||||||
</div>
|
</div>
|
||||||
<?php } ?>
|
<?php } ?>
|
||||||
<div id="votes" class="votes">
|
<div id="votes" class="votes">
|
||||||
<table class="vblock pro">
|
<table class="vblock pro">
|
||||||
<?php
|
<?php
|
||||||
$votespos = DB::query('SELECT * FROM photos_rates WHERE photo_id=:pid AND type=1 ORDER BY id DESC', array(':pid' => $id));
|
$votespos = DB::query('SELECT * FROM photos_rates WHERE photo_id=:pid AND type=1 AND contest=0 ORDER BY id DESC', array(':pid' => $id));
|
||||||
foreach ($votespos as $ps) {
|
foreach ($votespos as $ps) {
|
||||||
$uservote = new User($ps['user_id']);
|
$uservote = new User($ps['user_id']);
|
||||||
echo ' <tr>
|
echo ' <tr>
|
||||||
|
@ -275,7 +307,7 @@ if ($photo->i('id') !== null) {
|
||||||
</table>
|
</table>
|
||||||
<table class="vblock coN">
|
<table class="vblock coN">
|
||||||
<?php
|
<?php
|
||||||
$votespos = DB::query('SELECT * FROM photos_rates WHERE photo_id=:pid AND type=0 ORDER BY id DESC', array(':pid' => $id));
|
$votespos = DB::query('SELECT * FROM photos_rates WHERE photo_id=:pid AND type=0 AND contest=0 ORDER BY id DESC', array(':pid' => $id));
|
||||||
foreach ($votespos as $ps) {
|
foreach ($votespos as $ps) {
|
||||||
$uservote = new User($ps['user_id']);
|
$uservote = new User($ps['user_id']);
|
||||||
echo ' <tr>
|
echo ' <tr>
|
||||||
|
@ -330,8 +362,9 @@ if ($photo->i('id') !== null) {
|
||||||
</colgroup>
|
</colgroup>
|
||||||
<tbody>
|
<tbody>
|
||||||
<?php
|
<?php
|
||||||
|
$entity = DB::query('SELECT * FROM entities_data WHERE id=:id', array(':id'=>$photo->i('entitydata_id')))[0];
|
||||||
$vehiclevariables = json_decode($vehicle->i('sampledata'), true);
|
$vehiclevariables = json_decode($vehicle->i('sampledata'), true);
|
||||||
$vehicledatavariables = json_decode($vehicle->i('content'), true);
|
$vehicledatavariables = json_decode($entity['content'], true);
|
||||||
$num = 1;
|
$num = 1;
|
||||||
foreach ($vehiclevariables as $vb) {
|
foreach ($vehiclevariables as $vb) {
|
||||||
echo ' <tr class="s11 h21">
|
echo ' <tr class="s11 h21">
|
||||||
|
@ -583,7 +616,7 @@ if ($photo->i('id') !== null) {
|
||||||
|
|
||||||
<?php
|
<?php
|
||||||
if ($photo->i('moderated') === 1) {
|
if ($photo->i('moderated') === 1) {
|
||||||
$comments = DB::query('SELECT * FROM photos_comments WHERE photo_id=:pid', array(':pid' => $id));
|
$comments = DB::query('SELECT * FROM photos_comments WHERE photo_id=:pid ORDER BY CASE WHEN id = :pinnedid THEN 0 ELSE 1 END, id ASC', array(':pid' => $id, ':pinnedid' => $photo->i('pinnedcomment_id')));
|
||||||
$commcount = 0;
|
$commcount = 0;
|
||||||
foreach ($comments as $c) {
|
foreach ($comments as $c) {
|
||||||
if (json_decode($c['content'], true)['deleted'] != 'true') {
|
if (json_decode($c['content'], true)['deleted'] != 'true') {
|
||||||
|
@ -616,21 +649,100 @@ if ($photo->i('id') !== null) {
|
||||||
</div>
|
</div>
|
||||||
<div class="cmt-write s1">
|
<div class="cmt-write s1">
|
||||||
<h4 class="pp-item-header">Ваш комментарий</h4>
|
<h4 class="pp-item-header">Ваш комментарий</h4>
|
||||||
|
|
||||||
<div style="padding:0 11px 11px">
|
<div style="padding:0 11px 11px">
|
||||||
<form action="/comment.php" method="post" id="f1">
|
<?php
|
||||||
|
if (Auth::userid() > 0) {
|
||||||
|
if (NGALLERY['root']['registration']['emailverify'] != true || $user->i('status') != 3) { ?>
|
||||||
|
<form action="/comment.php" method="post" id="f1" enctype="multipart/form-data">
|
||||||
<input type="hidden" name="sid" value="hgdl6old9r9qodmvkn1r4t7d6h">
|
<input type="hidden" name="sid" value="hgdl6old9r9qodmvkn1r4t7d6h">
|
||||||
<input type="hidden" name="last_comment_rand" value="893329610">
|
<input type="hidden" name="last_comment_rand" value="893329610">
|
||||||
<input type="hidden" name="id" id="id" value="<?= $id ?>">
|
<input type="hidden" name="id" id="id" value="<?= $id ?>">
|
||||||
<input type="hidden" name="subj" id="subj" value="p">
|
<input type="hidden" name="subj" id="subj" value="p">
|
||||||
<textarea name="wtext" id="wtext"></textarea><br>
|
<textarea name="wtext" id="wtext"></textarea><br>
|
||||||
|
<div id="fileList" class="mt-3"></div>
|
||||||
<p id="statusSend" style="display: none;">Ошибка</p>
|
<p id="statusSend" style="display: none;">Ошибка</p>
|
||||||
<div class="cmt-submit"><input type="submit" value="Добавить комментарий" id="sbmt">  Ctrl + Enter
|
<div class="cmt-submit"><input type="submit" value="Добавить комментарий" id="sbmt"><button style="display: inline;" type="button" id="attachFile"><i class='bx bx-paperclip bx-rotate-90' ></i></button>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
|
<?php } else {
|
||||||
|
echo 'Комментарии могут оставлять только пользователи с подтверждённой почтой.';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
echo 'Комментарии могут оставлять только зарегистрированные пользователи.';
|
||||||
|
}
|
||||||
|
?>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<script>
|
||||||
|
document.addEventListener("DOMContentLoaded", function () {
|
||||||
|
const form = document.getElementById("f1");
|
||||||
|
if (!form) {
|
||||||
|
console.error("Форма #f1 не найдена!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const fileInput = document.createElement("input");
|
||||||
|
fileInput.type = "file";
|
||||||
|
fileInput.name = "filebody"; // Устанавливаем имя filebody
|
||||||
|
fileInput.style.display = "none";
|
||||||
|
|
||||||
|
form.appendChild(fileInput); // Добавляем input внутрь формы
|
||||||
|
|
||||||
|
const button = document.getElementById("attachFile");
|
||||||
|
const fileList = document.getElementById("fileList");
|
||||||
|
|
||||||
|
button.addEventListener("click", function () {
|
||||||
|
fileInput.click();
|
||||||
|
});
|
||||||
|
|
||||||
|
fileInput.addEventListener("change", function () {
|
||||||
|
const file = fileInput.files[0];
|
||||||
|
if (!file) return;
|
||||||
|
|
||||||
|
const maxSize = 100 * 1024 * 1024; // 100 MB
|
||||||
|
const forbiddenExtensions = [".html", ".php", ".htm", ".exe", ".com", ".cmd", ".bash", ".sh"];
|
||||||
|
|
||||||
|
const fileName = file.name.toLowerCase();
|
||||||
|
const fileSize = file.size;
|
||||||
|
|
||||||
|
if (fileSize > maxSize) {
|
||||||
|
alert("Файл превышает 100 МБ.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (forbiddenExtensions.some(ext => fileName.endsWith(ext))) {
|
||||||
|
alert("Расширение не поддерживается.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const fileItem = document.createElement("div");
|
||||||
|
fileItem.setAttribute("style", "border:solid 1px #bbb; width:max-content; font-size: 12px; padding:3px 10px 3px; margin-bottom:13px; background-color:#e2e2e2");
|
||||||
|
fileItem.textContent = file.name;
|
||||||
|
|
||||||
|
const removeBtn = document.createElement("a");
|
||||||
|
removeBtn.classList.add("compl");
|
||||||
|
removeBtn.setAttribute("style", "display: inline-block; margin-left: 5px; color:#292929; cursor: pointer;");
|
||||||
|
removeBtn.textContent = "✖";
|
||||||
|
removeBtn.addEventListener("click", function () {
|
||||||
|
fileItem.remove();
|
||||||
|
fileInput.value = "";
|
||||||
|
});
|
||||||
|
|
||||||
|
fileItem.appendChild(removeBtn);
|
||||||
|
fileList.appendChild(fileItem);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</script>
|
||||||
<?php } else { ?>
|
<?php } else { ?>
|
||||||
<div class="p0" id="pp-item-comments">
|
<div class="p0" id="pp-item-comments">
|
||||||
|
|
||||||
|
@ -663,67 +775,64 @@ if ($photo->i('id') !== null) {
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
<script>
|
<script>
|
||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
$('#f1').submit(function(e) {
|
$('#f1').submit(function(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
$.ajax({
|
|
||||||
type: "POST",
|
|
||||||
url: '/api/photo/comment',
|
|
||||||
data: $(this).serialize(),
|
|
||||||
success: function(response) {
|
|
||||||
var jsonData = JSON.parse(response);
|
|
||||||
if (jsonData.errorcode == "1") {
|
|
||||||
$('#statusSend').css({
|
|
||||||
display: 'block',
|
|
||||||
color: 'red'
|
|
||||||
});
|
|
||||||
$('#statusSend').text('Комментарий некорректен');
|
|
||||||
//Notify.noty('danger', 'Комментарий неккоректен');
|
|
||||||
//$("#result").html("<div class='alert alert-dangernew container mt-5' role='alert'>Неправильная почта или пароль!</div>");
|
|
||||||
} else if (jsonData.errorcode == "2") {
|
|
||||||
$('#statusSend').css({
|
|
||||||
display: 'block',
|
|
||||||
color: 'yellow'
|
|
||||||
});
|
|
||||||
$('#statusSend').text('Пожалуйста, подождите...');
|
|
||||||
//Notify.noty('warning', 'Пожалуйста, подождите...');
|
|
||||||
setTimeout(function() {
|
|
||||||
window.location.replace(jsonData.twofaurl);
|
|
||||||
}, 1000);
|
|
||||||
} else if (jsonData.errorcode == "0") {
|
|
||||||
$('#wtext').val('');
|
|
||||||
$('#statusSend').css({
|
|
||||||
display: 'block',
|
|
||||||
color: 'green'
|
|
||||||
});
|
|
||||||
$('#statusSend').text('Комментарий отправлен!');
|
|
||||||
//Notify.noty('success', 'Комментарий отправлен!');
|
|
||||||
//$("#result").html("<div class='alert alert-successnew container mt-5' role='alert'>Успешный вход!</div>");
|
|
||||||
$.ajax({
|
|
||||||
|
|
||||||
|
var formData = new FormData(this); // Собираем данные из формы, включая filebody
|
||||||
|
|
||||||
type: "POST",
|
$.ajax({
|
||||||
url: "/api/photo/getcomments/<?= $id ?>",
|
type: "POST",
|
||||||
processData: false,
|
url: "/api/photo/comment",
|
||||||
async: true,
|
data: formData,
|
||||||
success: function(r) {
|
processData: false, // Не обрабатывать данные (важно для файлов)
|
||||||
$('#posts').html(r)
|
contentType: false, // Не устанавливать заголовок Content-Type (браузер сделает сам)
|
||||||
|
success: function(response) {
|
||||||
|
var jsonData = JSON.parse(response);
|
||||||
|
|
||||||
|
if (jsonData.errorcode == "1") {
|
||||||
|
$('#statusSend').css({
|
||||||
|
display: 'block',
|
||||||
|
color: 'red'
|
||||||
|
}).text('Комментарий некорректен');
|
||||||
|
} else if (jsonData.errorcode == "2") {
|
||||||
|
$('#statusSend').css({
|
||||||
|
display: 'block',
|
||||||
|
color: 'yellow'
|
||||||
|
}).text('Пожалуйста, подождите...');
|
||||||
|
setTimeout(function() {
|
||||||
|
window.location.replace(jsonData.twofaurl);
|
||||||
|
}, 1000);
|
||||||
|
} else if (jsonData.errorcode == "0") {
|
||||||
|
$('#wtext').val('');
|
||||||
|
$('#statusSend').css({
|
||||||
|
display: 'block',
|
||||||
|
color: 'green'
|
||||||
|
}).text('Комментарий отправлен!');
|
||||||
|
|
||||||
},
|
$.ajax({
|
||||||
error: function(r) {
|
type: "POST",
|
||||||
console.log(r)
|
url: "/api/photo/getcomments/<?= $id ?>",
|
||||||
}
|
processData: false,
|
||||||
|
async: true,
|
||||||
});
|
success: function(r) {
|
||||||
|
$('#posts').html(r);
|
||||||
} else {
|
},
|
||||||
Notify.noty('danger', 'Неизвестная ошибка');
|
error: function(r) {
|
||||||
|
console.log(r);
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
});
|
} else {
|
||||||
});
|
alert('Неизвестная ошибка');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
error: function(err) {
|
||||||
|
console.error("Ошибка при отправке формы", err);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
function errimg() {
|
function errimg() {
|
||||||
const content = `<center>
|
const content = `<center>
|
||||||
|
|
|
@ -15,6 +15,8 @@ $photo = new \App\Models\Photo($_GET['id']);
|
||||||
<div id="backgr"></div>
|
<div id="backgr"></div>
|
||||||
<table class="tmain">
|
<table class="tmain">
|
||||||
<?php include($_SERVER['DOCUMENT_ROOT'] . '/views/components/Navbar.php'); ?>
|
<?php include($_SERVER['DOCUMENT_ROOT'] . '/views/components/Navbar.php'); ?>
|
||||||
|
<?php
|
||||||
|
if ($photo->i('moderated') === 1) { ?>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="main">
|
<td class="main">
|
||||||
<center>
|
<center>
|
||||||
|
@ -61,7 +63,19 @@ $photo = new \App\Models\Photo($_GET['id']);
|
||||||
</center>
|
</center>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<?php } else { ?>
|
||||||
|
<tr>
|
||||||
|
<td class="main">
|
||||||
|
<center>
|
||||||
|
<h1>Изображение не найдено</h1>
|
||||||
|
<div class="p20w" style="margin-bottom:20px; padding:10px 30px">
|
||||||
|
<img src="/static/img/pnp.jpg" alt="Пусто" width="400" height="205" border="0">
|
||||||
|
<p>Изображения с таким номером нет на сайте.<br />Может быть, его здесь никогда и не было.<br />Если Вы уверены, что что-то здесь всё-таки было, значит, администратор по каким-то причинам это удалил.</p>
|
||||||
|
</div>
|
||||||
|
</center>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<?php } ?>
|
||||||
<tr>
|
<tr>
|
||||||
<?php include($_SERVER['DOCUMENT_ROOT'] . '/views/components/Footer.php'); ?>
|
<?php include($_SERVER['DOCUMENT_ROOT'] . '/views/components/Footer.php'); ?>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
|
@ -225,7 +225,7 @@ $birthdate = json_decode($userprofile->i('content'), true)['aboutbirthday']['val
|
||||||
<div class="p20" style="margin-top: 8px; background-color: white !important;">
|
<div class="p20" style="margin-top: 8px; background-color: white !important;">
|
||||||
<h4>О себе</h4>
|
<h4>О себе</h4>
|
||||||
<?=
|
<?=
|
||||||
$about
|
htmlspecialchars($about)
|
||||||
?>
|
?>
|
||||||
</div>
|
</div>
|
||||||
<?php } else if ($usercttc === True) {
|
<?php } else if ($usercttc === True) {
|
||||||
|
|
|
@ -69,6 +69,9 @@ use \App\Models\{User, Photo};
|
||||||
if ($p['moderated'] === 2) {
|
if ($p['moderated'] === 2) {
|
||||||
echo '<p class="sm"><b>Причина отклонения: '.$photo->declineReason((int)$photo->content('declineReason')).'</b></p>';
|
echo '<p class="sm"><b>Причина отклонения: '.$photo->declineReason((int)$photo->content('declineReason')).'</b></p>';
|
||||||
}
|
}
|
||||||
|
if ($photo->content('declineComment') != null) {
|
||||||
|
echo '<p class="sm"><b>Комментарий: </b> '.$photo->content('declineComment').'</p>';
|
||||||
|
}
|
||||||
echo '
|
echo '
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
|
|
|
@ -43,6 +43,9 @@ $user = new User(Auth::userid());
|
||||||
var pub_pid = 0;
|
var pub_pid = 0;
|
||||||
</script>
|
</script>
|
||||||
<td class="main">
|
<td class="main">
|
||||||
|
<?php if (NGALLERY['root']['registration']['emailverify'] != false || $user->i('status') === 3) {
|
||||||
|
die('Чтобы публиковать Фотографии и Видео, нужно подтвердить почту.');
|
||||||
|
} ?>
|
||||||
<h1>Предложить медиа на публикацию</h1>
|
<h1>Предложить медиа на публикацию</h1>
|
||||||
<p>Ваш текущий индекс загрузки: <b><?= $user->i('uploadindex') ?></b></p>
|
<p>Ваш текущий индекс загрузки: <b><?= $user->i('uploadindex') ?></b></p>
|
||||||
|
|
||||||
|
|
|
@ -90,7 +90,7 @@ if (Auth::userid() > 0) {
|
||||||
</div>
|
</div>
|
||||||
<div style="color:#e00" id="err_email"></div>
|
<div style="color:#e00" id="err_email"></div>
|
||||||
<div class="styled-input">
|
<div class="styled-input">
|
||||||
<input name="password" id="password" type="text" required="">
|
<input name="password" id="password" type="password" required="">
|
||||||
<label for="password">Ваш пароль</label>
|
<label for="password">Ваш пароль</label>
|
||||||
</div>
|
</div>
|
||||||
<div style="color:#e00" id="err_password"></div>
|
<div style="color:#e00" id="err_password"></div>
|
||||||
|
@ -98,6 +98,7 @@ if (Auth::userid() > 0) {
|
||||||
|
|
||||||
<input type="button" id="regbtn" class="mf-button-wide" style="margin-top:15px" value="Зарегистрироваться">
|
<input type="button" id="regbtn" class="mf-button-wide" style="margin-top:15px" value="Зарегистрироваться">
|
||||||
<p>Регистрируясь на сервере <?= NGALLERY['root']['title'] ?>, вы <a href="/rules">принимаете его правила.</a></p>
|
<p>Регистрируясь на сервере <?= NGALLERY['root']['title'] ?>, вы <a href="/rules">принимаете его правила.</a></p>
|
||||||
|
<p><b><a href="/tour">Вы можете пройти экскурсию по сайту.</a></b></p>
|
||||||
</form><br><br>
|
</form><br><br>
|
||||||
|
|
||||||
<br>
|
<br>
|
||||||
|
@ -150,7 +151,7 @@ if (Auth::userid() > 0) {
|
||||||
</center>
|
</center>
|
||||||
<?php } else { ?>
|
<?php } else { ?>
|
||||||
<center>
|
<center>
|
||||||
<h1>К сожалению, регистрация на сервере <?= NGALLERY['root']['title'] ?> запрещена.</h1>
|
<h1>К сожалению, регистрация на сервере <?= NGALLERY['root']['title'] ?> закрыта.</h1>
|
||||||
</center?
|
</center?
|
||||||
<?php } ?>
|
<?php } ?>
|
||||||
</td>
|
</td>
|
||||||
|
|
|
@ -1,58 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
use App\Services\{Router, Auth, DB, Date};
|
|
||||||
?>
|
|
||||||
<html lang="ru">
|
|
||||||
|
|
||||||
|
|
||||||
<head>
|
|
||||||
<?php include($_SERVER['DOCUMENT_ROOT'] . '/views/components/LoadHead.php'); ?>
|
|
||||||
|
|
||||||
|
|
||||||
</head>
|
|
||||||
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<div id="backgr"></div>
|
|
||||||
<table class="tmain">
|
|
||||||
<?php include($_SERVER['DOCUMENT_ROOT'] . '/views/components/Navbar.php'); ?>
|
|
||||||
<tr>
|
|
||||||
<td class="main">
|
|
||||||
<h1>Результаты поиска</h1>
|
|
||||||
<div>Найдено изображений: <b><?=DB::query('SELECT COUNT(*) FROM photos WHERE user_id=:uid AND moderated=1 ORDER BY id DESC', array(':uid'=>$_GET['id']))[0]['COUNT(*)']?></b> · <a href="#sf">Новый поиск</a></div><br>
|
|
||||||
<?php
|
|
||||||
$photos = DB::query('SELECT * FROM photos WHERE user_id=:uid AND moderated=1 ORDER BY id DESC', array(':uid'=>$_GET['id']));
|
|
||||||
foreach ($photos as $p) {
|
|
||||||
echo '<div class="p20p">
|
|
||||||
<table>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td class="pb_photo" id="p1936120"><a href="/photo/'.$p['id'].'" target="_blank" class="prw"><img class="f" src="'.$p['photourl'].'">
|
|
||||||
<div class="hpshade">
|
|
||||||
';
|
|
||||||
if (DB::query('SELECT COUNT(*) FROM photos_comments WHERE photo_id=:id', array(':id'=>$p['id']))[0]['COUNT(*)'] >= 1) {
|
|
||||||
echo '<div class="com-icon">'.DB::query('SELECT COUNT(*) FROM photos_comments WHERE photo_id=:id', array(':id'=>$p['id']))[0]['COUNT(*)'].'</div>';
|
|
||||||
}
|
|
||||||
echo '
|
|
||||||
<div class="eye-icon">'.DB::query('SELECT COUNT(*) FROM photos_views WHERE photo_id=:id', array(':id'=>$p['id']))[0]['COUNT(*)'].'</div></div>
|
|
||||||
</a></td>
|
|
||||||
<td class="pb_descr">
|
|
||||||
|
|
||||||
<p><b class="pw-place">'.htmlspecialchars($p['place']).'</b></p>
|
|
||||||
<span class="pw-descr">'.htmlspecialchars($p['postbody']).'</span>
|
|
||||||
<p class="sm"><b>'.Date::zmdate($p['timeupload']).'</b><br>Автор: <a href="/author/'.$p['user_id'].'/">'.htmlspecialchars($p['username']).'</a></p>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>';
|
|
||||||
}
|
|
||||||
?>
|
|
||||||
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|