mirror of
https://github.com/claradex/nativegallery.git
synced 2025-04-23 16:43:04 +03:00
Compare commits
12 commits
be85a9531a
...
e9655f6463
Author | SHA1 | Date | |
---|---|---|---|
|
e9655f6463 | ||
|
8b8cedf6c1 | ||
|
303d70d1a3 | ||
|
c31617fd10 | ||
|
4ee7f4b79b | ||
|
0581edcc3d | ||
|
83b0e8ccc9 | ||
|
1dab03afe8 | ||
|
be2963117a | ||
|
b5ff9d1998 | ||
|
3360b9d208 | ||
|
52dbf10d3d |
27 changed files with 744 additions and 3159 deletions
5
.gitignore
vendored
5
.gitignore
vendored
|
@ -6,11 +6,12 @@
|
|||
/ngallery.yaml
|
||||
ngallery.yaml
|
||||
/cdn/
|
||||
*.yaml
|
||||
ngallery.yaml
|
||||
/views/pages/t.php
|
||||
views/pages/t.php
|
||||
rules.txt
|
||||
rules.txt
|
||||
/uploads/*
|
||||
t.php
|
||||
t.php
|
||||
logs
|
||||
.txt
|
37
app/Controllers/Api/Admin/Settings/TaskManager.php
Normal file
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
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
23
app/Controllers/Api/Images/Contests/SendPretend.php
Normal file
23
app/Controllers/Api/Images/Contests/SendPretend.php
Normal file
|
@ -0,0 +1,23 @@
|
|||
<?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()
|
||||
{
|
||||
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
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
|
@ -3,7 +3,7 @@
|
|||
namespace App\Controllers\Api\Images;
|
||||
|
||||
use App\Services\{Auth, Router, GenerateRandomStr, DB, Json, EXIF};
|
||||
use App\Models\{User, Vote};
|
||||
use App\Models\{User, Vote, VoteContest};
|
||||
|
||||
class Rate
|
||||
{
|
||||
|
@ -14,28 +14,29 @@ class Rate
|
|||
$photoId = $_GET['pid'];
|
||||
$voteType = (int) $_GET['vote'];
|
||||
$contest = (isset($_GET['action']) && $_GET['action'] === 'vote-konk') ? 1 : 0;
|
||||
$contestId = $_GET['cid'];
|
||||
|
||||
if ($contest === 1) {
|
||||
if (Vote::photoContest($userId, $photoId) === -1) {
|
||||
if (VoteContest::photo($userId, $photoId, $contestId) === -1) {
|
||||
DB::query(
|
||||
'INSERT INTO photos_rates (id, user_id, photo_id, type, contest) VALUES (NULL, :id, :pid, :type, 1)',
|
||||
[':id' => $userId, ':pid' => $photoId, ':type' => $voteType]
|
||||
'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 (Vote::photoContest($userId, $photoId) != $voteType) {
|
||||
if (VoteContest::photo($userId, $photoId, $contestId) != $voteType) {
|
||||
DB::query(
|
||||
'DELETE FROM photos_rates WHERE user_id=:id AND photo_id=:pid AND type=:type AND contest=1',
|
||||
[':id' => $userId, ':pid' => $photoId, ':type' => Vote::photo($userId, $photoId)]
|
||||
'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 (Vote::photoContest($userId, $photoId) === $voteType) {
|
||||
} elseif (VoteContest::photo($userId, $photoId, $contestId) === $voteType) {
|
||||
DB::query(
|
||||
'DELETE FROM photos_rates WHERE user_id=:id AND photo_id=:pid AND contest=1',
|
||||
[':id' => $userId, ':pid' => $photoId]
|
||||
'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 SET type=:type WHERE user_id=:id AND photo_id=:pid AND contest=1',
|
||||
[':id' => $userId, ':pid' => $photoId, ':type' => $voteType]
|
||||
'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 {
|
||||
|
@ -77,7 +78,13 @@ class Rate
|
|||
}
|
||||
|
||||
$currentVote = Vote::photo($userId, $photoId);
|
||||
$contCurrentVote = Vote::photoContest($userId, $photoId);
|
||||
$contCurrentVote = VoteContest::photo($userId, $photoId, $contestId);
|
||||
|
||||
if ($contest === 0) {
|
||||
$count = Vote::count($photoId);
|
||||
} else {
|
||||
$count = VoteContest::count($photoId, $contestId);
|
||||
}
|
||||
$result = [
|
||||
'buttons' => [
|
||||
'negbtn' => $currentVote === 0,
|
||||
|
@ -86,7 +93,7 @@ class Rate
|
|||
'posbtn_contest' => $contCurrentVote === 1,
|
||||
],
|
||||
'errors' => '',
|
||||
'rating' => Vote::count($photoId),
|
||||
'rating' => $count,
|
||||
'votes' => [
|
||||
1 => $formattedVotesPos,
|
||||
0 => $formattedVotesNeg
|
||||
|
|
0
app/Controllers/Api/Images/RateContest.php
Normal file
0
app/Controllers/Api/Images/RateContest.php
Normal file
|
@ -37,7 +37,7 @@ class Upload
|
|||
} else {
|
||||
$moderated = 1;
|
||||
}
|
||||
DB::query('INSERT INTO photos VALUES (\'0\', :userid, :postbody, :photourl, :time, :timeup, :exif, 0, :moderated, :place, 0, :gallery, :entityid, 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));
|
||||
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')) {
|
||||
$followers = DB::query('SELECT * FROM followers WHERE user_id=:uid', array(':uid' => Auth::userid()));
|
||||
foreach ($followers as $f) {
|
||||
|
|
|
@ -8,6 +8,7 @@ use \App\Controllers\Api\{Login, Register};
|
|||
use \App\Controllers\Api\Subscribe as SubscribeUser;
|
||||
use \App\Controllers\Api\Images\{Upload};
|
||||
use \App\Controllers\Api\Images\Rate as PhotoVote;
|
||||
use \App\Controllers\Api\Images\RateContest as PhotoVoteContest;
|
||||
use \App\Controllers\Api\Images\Compress as PhotoCompress;
|
||||
use \App\Controllers\Api\Images\CheckAll as PhotoCheckAll;
|
||||
use \App\Controllers\Api\Images\LoadRecent as PhotoLoadRecent;
|
||||
|
@ -19,6 +20,7 @@ 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\Rate as PhotoCommentVote;
|
||||
use \App\Controllers\Api\Images\Contests\SendPretend as PhotoContestsSendPretend;
|
||||
use \App\Controllers\Api\GeoDB\Search as GeoDBSearch;
|
||||
use \App\Controllers\Api\Vehicles\Load as VehiclesLoad;
|
||||
use \App\Controllers\Api\Profile\Update as ProfileUpdate;
|
||||
|
@ -33,6 +35,7 @@ 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
|
||||
{
|
||||
|
@ -53,6 +56,9 @@ class ApiController
|
|||
public static function photovote() {
|
||||
return new PhotoVote();
|
||||
}
|
||||
public static function photovotecontest() {
|
||||
return new PhotoVoteContest();
|
||||
}
|
||||
public static function photofavorite() {
|
||||
return new PhotoFavorite();
|
||||
}
|
||||
|
@ -95,6 +101,9 @@ class ApiController
|
|||
public static function recentphotos() {
|
||||
return new PhotoLoadRecent();
|
||||
}
|
||||
public static function sendpretendphoto() {
|
||||
return new PhotoContestsSendPretend();
|
||||
}
|
||||
public static function loaduser() {
|
||||
return new UserLoad();
|
||||
}
|
||||
|
@ -125,6 +134,9 @@ class ApiController
|
|||
public static function admingeodbdelete() {
|
||||
return new AdminGeoDBDelete();
|
||||
}
|
||||
public static function admintaskmanager() {
|
||||
return new AdminTaskManager();
|
||||
}
|
||||
public static function vehiclesload() {
|
||||
return new VehiclesLoad();
|
||||
}
|
||||
|
|
150
app/Controllers/Exec/Tasks/ExecContests.php
Normal file
150
app/Controllers/Exec/Tasks/ExecContests.php
Normal file
|
@ -0,0 +1,150 @@
|
|||
<?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;
|
||||
}
|
||||
}
|
||||
|
||||
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)) {
|
||||
echo "[{$contest['id']}] Waiting for another contest to end. Skip...\n";
|
||||
return;
|
||||
}
|
||||
|
||||
if ($contest['closepretendsdate'] <= time() && $contest['opendate'] <= time()) {
|
||||
DB::query('UPDATE photos SET on_contest=2 WHERE on_contest=1 AND contest_id=:id', array(':id'=>$contest['id']));
|
||||
DB::query('UPDATE contests SET status = 2 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 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']]);
|
||||
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];
|
||||
$time = time();
|
||||
if (NGALLERY['root']['contests']['autonew']['pretendsopen'] === 'now') {
|
||||
$pretendsopen = $time;
|
||||
} else {
|
||||
$pretendsopen = Date::addTime(NGALLERY['root']['contests']['autonew']['pretendsopen']);
|
||||
}
|
||||
|
||||
$pretendsclose = Date::addTime(NGALLERY['root']['contests']['autonew']['pretendsclose']);
|
||||
if (NGALLERY['root']['contests']['autonew']['open'] === 'now') {
|
||||
$contestopen = $pretendsclose;
|
||||
} else {
|
||||
$contestopen = Date::addTime(NGALLERY['root']['contests']['autonew']['open']);
|
||||
}
|
||||
$contestclose = Date::addTime(NGALLERY['root']['contests']['autonew']['close']);
|
||||
DB::query('INSERT INTO contests VALUES (\'0\', :themeid, :openprdate, :closeprdate, :opendate, :closedate, 0)', array(':themeid'=>$theme['id'], ':openprdate'=>$pretendsopen, ':closeprdate'=>$pretendsclose, ':opendate'=>$contestopen, ':closedate'=>$contestclose));
|
||||
echo "Contest created! Continue...";
|
||||
}
|
||||
}
|
||||
|
||||
private static function processVotes(array $contest)
|
||||
{
|
||||
$votes = DB::query(
|
||||
'SELECT user_id, photo_id, COUNT(*) AS vote_count
|
||||
FROM photos_rates_contest WHERE contest_id = :id
|
||||
GROUP BY user_id ORDER BY vote_count DESC LIMIT 3',
|
||||
[':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);
|
||||
|
||||
$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('UPDATE photos SET content = :content, on_contest=0, contest_id=0 WHERE id = :id', [
|
||||
':id' => $vote['photo_id'],
|
||||
':content' => json_encode($photoData)
|
||||
]);
|
||||
}
|
||||
|
||||
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
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"
|
|
@ -69,6 +69,7 @@ class Routes
|
|||
Router::post('/api/photo/comment/$id/edit', 'ApiController@photocommentedit');
|
||||
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/vehicles/load', 'ApiController@vehiclesload');
|
||||
Router::get('/api/geodb/search', 'ApiController@geodbsearch');
|
||||
if ($user->i('admin') > 0) {
|
||||
|
@ -81,6 +82,7 @@ class Routes
|
|||
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('/404', 'ExceptionRegister@notfound');
|
||||
|
|
37
app/Models/VoteContest.php
Normal file
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
|
||||
namespace App\Services;
|
||||
use InvalidArgumentException;
|
||||
|
||||
class Date
|
||||
{
|
||||
|
@ -65,5 +66,38 @@ class Date
|
|||
);
|
||||
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]);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
|
|
|
@ -2,42 +2,44 @@
|
|||
|
||||
namespace App\Services;
|
||||
class TaskScheduler {
|
||||
private $taskName;
|
||||
private $command;
|
||||
private $interval;
|
||||
|
||||
public function __construct() {
|
||||
// Конструктор теперь не принимает аргументы
|
||||
}
|
||||
public function __construct() {}
|
||||
|
||||
private function isWindows() {
|
||||
return strtoupper(substr(PHP_OS, 0, 3)) === 'WIN';
|
||||
}
|
||||
|
||||
// Метод для добавления задачи с параметрами
|
||||
public function addTask($taskName, $command, $interval = "* * * * *") {
|
||||
$this->taskName = $taskName;
|
||||
$this->command = $command;
|
||||
$this->interval = $interval;
|
||||
|
||||
return $this->isWindows() ? $this->addWindowsTask() : $this->addLinuxTask();
|
||||
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);
|
||||
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);
|
||||
return $this->isWindows() ? $this->removeWindowsTask($taskName) : $this->removeLinuxTask($command);
|
||||
}
|
||||
|
||||
private function addLinuxTask() {
|
||||
$cronJob = "{$this->interval} {$this->command}";
|
||||
if ($this->isLinuxTaskExists($this->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-задача уже установлена.";
|
||||
}
|
||||
|
||||
|
@ -57,7 +59,7 @@ class TaskScheduler {
|
|||
private function isLinuxTaskExists($command = null) {
|
||||
exec("crontab -l 2>&1", $output);
|
||||
foreach ($output as $line) {
|
||||
if (strpos($line, $command ?? $this->command) !== false) {
|
||||
if (strpos($line, $command) !== false) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -71,7 +73,7 @@ class TaskScheduler {
|
|||
}
|
||||
|
||||
$filteredOutput = array_filter($output, function ($line) use ($command) {
|
||||
return strpos($line, $command ?? $this->command) === false;
|
||||
return strpos($line, $command) === false;
|
||||
});
|
||||
|
||||
file_put_contents("/tmp/my_cron", implode(PHP_EOL, $filteredOutput) . PHP_EOL);
|
||||
|
@ -81,19 +83,29 @@ class TaskScheduler {
|
|||
return "✅ Cron-задача удалена!";
|
||||
}
|
||||
|
||||
private function addWindowsTask() {
|
||||
if ($this->isWindowsTaskExists($this->taskName)) {
|
||||
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.";
|
||||
}
|
||||
|
||||
$command = "schtasks /Create /SC MINUTE /MO 1 /TN \"{$this->taskName}\" /TR \"{$this->command}\" /F";
|
||||
exec($command, $output, $return_code);
|
||||
$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 ?? $this->taskName) ."\" 2>&1", $output, $return_var);
|
||||
exec("schtasks /Query /TN \"". ($taskName) ."\" 2>&1", $output, $return_var);
|
||||
return $return_var === 0;
|
||||
}
|
||||
|
||||
|
@ -102,8 +114,39 @@ class TaskScheduler {
|
|||
return "❌ Задача не найдена в Windows.";
|
||||
}
|
||||
|
||||
exec("schtasks /Delete /TN \"". ($taskName ?? $this->taskName) ."\" /F", $output, $return_code);
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
?>
|
|
@ -23,5 +23,8 @@
|
|||
"paquettg/php-html-parser": "^2.2",
|
||||
"phpmailer/phpmailer": "^6.9",
|
||||
"beeyev/disposable-email-filter-php": "^1.3"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpstan/phpstan": "*"
|
||||
}
|
||||
}
|
||||
|
|
63
composer.lock
generated
63
composer.lock
generated
|
@ -4,7 +4,7 @@
|
|||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "ec83690d34b55f6ada188bcfc6a299db",
|
||||
"content-hash": "844a94a4ce9ce290e30dd5845c27ed3f",
|
||||
"packages": [
|
||||
{
|
||||
"name": "aws/aws-crt-php",
|
||||
|
@ -2248,7 +2248,66 @@
|
|||
"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": [],
|
||||
"minimum-stability": "stable",
|
||||
"stability-flags": {},
|
||||
|
|
|
@ -15,6 +15,7 @@ class App
|
|||
|
||||
if (file_exists($_SERVER['DOCUMENT_ROOT'] . '/ngallery.yaml')) {
|
||||
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) {
|
||||
Debugger::enable();
|
||||
}
|
||||
|
|
|
@ -70,3 +70,4 @@ ngallery:
|
|||
premoderation: false
|
||||
contests:
|
||||
enabled: true
|
||||
autonew: true
|
||||
|
|
|
@ -183,7 +183,42 @@ function LoadRecentPhotos()
|
|||
.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()
|
||||
{
|
||||
|
|
|
@ -118,7 +118,7 @@ $(document).ready(function()
|
|||
if (vote != 0 && vote != 1 || $(this).is('.locked')) return false;
|
||||
|
||||
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 savedClass0 = $('.vote[pid="' + pid + '"] .konk_btn[vote="0"]').attr('class');
|
||||
|
||||
|
@ -131,7 +131,7 @@ $(document).ready(function()
|
|||
{
|
||||
$(this).closest('.p20p').removeAttr('class').css('padding', '6px 6px 5px');
|
||||
|
||||
$.getJSON('/api/photo/vote', { 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)
|
||||
{
|
||||
|
|
|
@ -88,10 +88,10 @@ body {
|
|||
<i class="bx bx-file-blank nav__icon"></i>
|
||||
<span class="nav__name">Страницы</span>
|
||||
</a>
|
||||
<!--a href="/admin?type=Settings" class="nav__link">
|
||||
<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>
|
||||
|
|
|
@ -5,9 +5,8 @@ use \App\Models\User;
|
|||
|
||||
$task = new TaskScheduler();
|
||||
|
||||
//$userprofile = new User(explode('/', $_SERVER['REQUEST_URI'])[2]);
|
||||
$contestCreate = true;
|
||||
if (!$task->isTaskExists("FinishContests", "php /path/to/finish_contests.php")) {
|
||||
if (!$task->isTaskExists("ExecContests", "php ".$_SERVER['DOCUMENT_ROOT'].$task->findHandlerById(NGALLERY_TASKS, 'ExecContests'))) {
|
||||
$contestCreate = false;
|
||||
}
|
||||
?>
|
||||
|
@ -38,16 +37,9 @@ if (!$task->isTaskExists("FinishContests", "php /path/to/finish_contests.php"))
|
|||
} ?>">Провести новый</a>
|
||||
<table class="table">
|
||||
<?php
|
||||
/*echo $task->addTask(
|
||||
"FinishContests",
|
||||
"php ".$_SERVER['DOCUMENT_ROOT']."/app/Controllers/Exec/Tasks/FinishContests.php >> ".$_SERVER['DOCUMENT_ROOT'].NGALLERY['root']['logslocation']." 2>&1",
|
||||
"* * * * *" // Каждую минуту (можно менять)
|
||||
);*/
|
||||
if ($contestCreate === false) {
|
||||
echo "<div class='alert alert-warning' role='alert'>У вас не добавлена задача на проведение конкурсов. Без неё, сервер не сможет завершать конкурс и проводить новый автоматически.</div>";
|
||||
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>";
|
||||
}
|
||||
echo $task->removeTask("FinishContests", "php /path/to/finish_contests.php");
|
||||
|
||||
?>
|
||||
<tbody>
|
||||
<tr>
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
<?php
|
||||
|
||||
use \App\Services\{KeyTranslation};
|
||||
use \App\Services\{KeyTranslation, TaskScheduler};
|
||||
use \App\Models\User;
|
||||
|
||||
use Symfony\Component\Yaml\Yaml;
|
||||
|
||||
$yamlFile = $_SERVER['DOCUMENT_ROOT'].'/ngallery.yaml';
|
||||
function renderInputs($data, $prefix = '') {
|
||||
$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);
|
||||
|
@ -79,29 +81,91 @@ function renderInputs($data, $prefix = '') {
|
|||
|
||||
<?= \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"><span class="v-tab__label">
|
||||
Задачи
|
||||
|
||||
</span></a>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="active__block" id="config__block">
|
||||
<div class="alert alert-warning" role="alert">
|
||||
Изменяйте только на свой страх и риск.
|
||||
</div>
|
||||
Изменяйте только на свой страх и риск.
|
||||
</div>
|
||||
<div class="p20w" style="display:block">
|
||||
<?php
|
||||
// Вывод формы
|
||||
echo '<form method="post">';
|
||||
<?php
|
||||
// Вывод формы
|
||||
echo '<form method="post">';
|
||||
foreach (NGALLERY as $ng) {
|
||||
renderInputs($ng);
|
||||
}
|
||||
echo '<button type="submit">Сохранить</button>';
|
||||
echo '</form>';
|
||||
?>
|
||||
echo '<button type="submit">Сохранить</button>';
|
||||
echo '</form>';
|
||||
?>
|
||||
</div><br>
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
<div style="display: none;" 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>
|
|
@ -93,30 +93,19 @@ $(document).ready(function()
|
|||
<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=0')[0];
|
||||
echo '<div class="p20">
|
||||
<h4>Сейчас конкурс не проводится. Пожалуйста, заходите позже.</h4>
|
||||
</div>';
|
||||
</div>
|
||||
<script>startCountdown(' . $contest['openpretendsdate'] . ');</script>
|
||||
<h2>Следующий Фотоконкурс будет через:</h2>
|
||||
<h1 id="countdown"></h1>';
|
||||
} else { ?>
|
||||
<div id="tip" lock="0"><span id="img"></span></div>
|
||||
<img pid="2044756" src="/photo/20/44/75/2044756.jpg?2" style="display:none">
|
||||
<div class="p20p">
|
||||
<table>
|
||||
<tr>
|
||||
<td><a href="#" pid="2044756" class="contestBtn"></a></td>
|
||||
<td class="pb_photo" id="p2044756"><a href="/photo/2044756/" target="_blank" class="prw"><img class="f" src="/img/prw-loader.gif" data-src="/photo/20/44/75/2044756_s.jpg?2" alt="1162 КБ">
|
||||
<div class="hpshade">
|
||||
<div class="eye-icon">353</div>
|
||||
</div>
|
||||
</a></td>
|
||||
<td class="pb_descr">
|
||||
<p><a href="/articles/3/" target="_blank">Фотозарисовки</a></p>
|
||||
<p><b class="pw-place">Линия 5</b> | Линия 5</p>
|
||||
<p class="sm"><b>16 января 2021 г., суббота</b><br>Автор: <a href="/author/17434/">Levis</a></p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<img pid="2068176" src="/photo/20/68/17/2068176.jpg" style="display:none">
|
||||
<?php
|
||||
$photos_contest = DB::query('SELECT * FROM photos WHERE on_contest=1');
|
||||
foreach ($photos_contest as $pc) {
|
||||
echo '<img pid="2068176" src="/photo/20/68/17/2068176.jpg" style="display:none">
|
||||
<div class="p20p">
|
||||
<table>
|
||||
<tr>
|
||||
|
@ -136,7 +125,9 @@ $(document).ready(function()
|
|||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>';
|
||||
}
|
||||
?>
|
||||
<img pid="2073198" src="/photo/20/73/19/2073198.jpg" style="display:none">
|
||||
<div class="p20p">
|
||||
<table>
|
||||
|
@ -294,8 +285,6 @@ $(document).ready(function()
|
|||
<?php }
|
||||
?>
|
||||
|
||||
<h2>Следующий Фотоконкурс будет через:</h2>
|
||||
<h1 id="countdown"></h1>
|
||||
<br>
|
||||
|
||||
</center>
|
||||
|
|
|
@ -3,23 +3,24 @@
|
|||
use \App\Services\{Auth, DB, Date};
|
||||
use \App\Models\{Vehicle, User};
|
||||
|
||||
function convertUnixToRussianDateTime($unixTime) {
|
||||
function convertUnixToRussianDateTime($unixTime)
|
||||
{
|
||||
// Создаем объект DateTime из Unix-времени
|
||||
$dateTime = new DateTime("@$unixTime");
|
||||
|
||||
|
||||
// Устанавливаем временную зону (можно изменить на нужную)
|
||||
$dateTime->setTimezone(new DateTimeZone('Europe/Moscow'));
|
||||
|
||||
|
||||
// Форматируем дату и время с использованием IntlDateFormatter
|
||||
$formatter = new IntlDateFormatter(
|
||||
'ru_RU',
|
||||
IntlDateFormatter::LONG,
|
||||
'ru_RU',
|
||||
IntlDateFormatter::LONG,
|
||||
IntlDateFormatter::NONE,
|
||||
'Europe/Moscow',
|
||||
IntlDateFormatter::GREGORIAN,
|
||||
'd MMMM yyyy года в H:mm'
|
||||
);
|
||||
|
||||
|
||||
return $formatter->format($dateTime);
|
||||
}
|
||||
?>
|
||||
|
@ -43,102 +44,8 @@ function convertUnixToRussianDateTime($unixTime) {
|
|||
<h1>Принять участие в Фотоконкурсе</h1>
|
||||
<script src="/js/jquery-ui.js?1633005526"></script>
|
||||
<script src="/js/selector.js?1730197663"></script>
|
||||
<script>
|
||||
addTexts({
|
||||
'VF_MAXLENGTH': 'Буфер обмена содержит %s знаков, но значение в этом поле не может быть длиннее %s знаков!\nВероятно, вы пытаетесь вставить некорректные данные'
|
||||
});
|
||||
|
||||
$(document).ready(function() {
|
||||
$('#mname').autocompleteSelector('mid', '/api.php?action=get-models&type=2', {
|
||||
minLength: 1,
|
||||
defaultLabel: '(модель неизвестна)',
|
||||
defaultValue: 632
|
||||
});
|
||||
$('#chname').autocompleteSelector('chid', '/api.php?action=get-chassis&type=2', {
|
||||
minLength: 1,
|
||||
defaultLabel: '(нет)'
|
||||
});
|
||||
|
||||
$('#state, #service').change(function() {
|
||||
$(this).attr('class', $('option:selected', this).attr('class'));
|
||||
}).change();
|
||||
|
||||
$('#mform').on('submit', function() {
|
||||
var built_y_len = $('#built_y').val().length;
|
||||
var scrap_y_len = $('#scrap_y').val().length;
|
||||
|
||||
if (built_y_len > 1 && built_y_len < 4 ||
|
||||
scrap_y_len > 1 && scrap_y_len < 4) {
|
||||
alert('Неверное значение в поле «год» (0, 1 либо 4 символа).');
|
||||
return false;
|
||||
}
|
||||
|
||||
var source = $('#source');
|
||||
|
||||
if (source.val().trim().length < 4) {
|
||||
alert('Не указан источник сведений. Пожалуйста, заполните соответствующее поле..');
|
||||
source[0].focus();
|
||||
return false;
|
||||
}
|
||||
|
||||
$('input[type="submit"]', this).prop('disabled', true);
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
// Фильтрация вставляемых из буфера данных
|
||||
$('#num, #gos, #zn, #vin, #cn, #start_y, #leave_y, #built_y, #scrap_y').on('paste', function(e) {
|
||||
var field = $(this);
|
||||
var text = e.originalEvent.clipboardData.getData('Text').trim();
|
||||
|
||||
var maxlength = parseInt(field.attr('maxlength'));
|
||||
if (maxlength && text.length > maxlength)
|
||||
alert(_text['VF_MAXLENGTH'].replace('%s', text.length).replace('%s', maxlength) + '.');
|
||||
else field.insertAtCaret(text);
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
// Опции даты
|
||||
$('.approx-aprx').css('font-weight', 'normal').on('change', function() {
|
||||
$(this).attr('class', 'approx-aprx ' + $('option:selected', this).attr('class'))
|
||||
}).change();
|
||||
});
|
||||
|
||||
|
||||
$.fn.insertAtCaret = function(myValue) {
|
||||
return this.each(function() {
|
||||
if (document.selection) {
|
||||
// For browsers like Internet Explorer
|
||||
this.focus();
|
||||
var sel = document.selection.createRange();
|
||||
sel.text = myValue;
|
||||
this.focus();
|
||||
} else
|
||||
if (this.selectionStart || this.selectionStart == '0') {
|
||||
// For browsers like Firefox and Webkit based
|
||||
var startPos = this.selectionStart;
|
||||
var endPos = this.selectionEnd;
|
||||
var scrollTop = this.scrollTop;
|
||||
this.value = this.value.substring(0, startPos) + myValue + this.value.substring(endPos, this.value.length);
|
||||
this.focus();
|
||||
this.selectionStart = startPos + myValue.length;
|
||||
this.selectionEnd = startPos + myValue.length;
|
||||
this.scrollTop = scrollTop;
|
||||
} else {
|
||||
this.value += myValue;
|
||||
this.focus();
|
||||
}
|
||||
})
|
||||
};
|
||||
</script>
|
||||
|
||||
<form method="post" id="mform" action="?action=write">
|
||||
<input type="hidden" name="cid" value="14">
|
||||
<input type="hidden" name="type" value="2">
|
||||
<input type="hidden" name="link_gos" value="0">
|
||||
|
||||
<input type="hidden" name="num" id="num" value="">
|
||||
<form id="sendForm" method="post" id="mform">
|
||||
|
||||
<h4>В каком Фотоконкурсе вы хотите принять участие?</h4>
|
||||
<div class="p20w">
|
||||
|
@ -152,24 +59,23 @@ function convertUnixToRussianDateTime($unixTime) {
|
|||
<th>Начало проведения</th>
|
||||
<th>Итоги и победители</th>
|
||||
</tr>
|
||||
|
||||
|
||||
<?php
|
||||
$entities = DB::query('SELECT * FROM contests WHERE closepretendsdate>=:id', array(':id'=>time()));
|
||||
$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];
|
||||
$theme = DB::query('SELECT * FROM contests_themes WHERE id=:id', array(':id' => $e['themeid']))[0];
|
||||
echo '<tr>
|
||||
<td class="ds"><input type="radio" name="base_nid" 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>
|
||||
|
||||
<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>
|
||||
|
@ -177,109 +83,102 @@ function convertUnixToRussianDateTime($unixTime) {
|
|||
|
||||
<div class="p20" style="padding-left:5px; margin-bottom:15px">
|
||||
<table class="nospaces" width="100%">
|
||||
<input type="hidden" name="did" value="27">
|
||||
<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>
|
||||
<td style="padding-bottom:15px"><input type="text" name="modelinput_' . $count . '" id="num" style="width:80px" maxlength="21" value=""></td>
|
||||
</tr>';
|
||||
$count++;
|
||||
$count++;
|
||||
}
|
||||
?>
|
||||
<tr>
|
||||
<td style="width: 10%"></td>
|
||||
|
||||
<script>
|
||||
var vdata = {};
|
||||
|
||||
vdata[0] = [0, '', '', '', 632, '(модель неизвестна)', 0, '(нет)', 0, 1, '', '', '', 0, '', 0, 0, '', 0, '', 0, '', 0, '', 0, '', 0, '', ''];
|
||||
vdata[594939] = [27, '48', '', '', 135, 'ПТЗ-5283', 0, '(нет)', 0, 5, '14', '', '', 11, '2002', 10, 0, '', 10, '2018-11-30', 10, '0000-00-00', 0, '0000-00-00', 0, '2022-00-00', 0, '', ''];
|
||||
|
||||
function setDateByYM(field, y, m, approx) {
|
||||
$('#' + field + '_m').val(m == 0 ? '' : m);
|
||||
$('#' + field + '_y').val(y == '0000' ? '' : y);
|
||||
$('#' + field + '_approx_aprx').val(approx).change();
|
||||
}
|
||||
|
||||
|
||||
function setDateByDate(field, date, approx) {
|
||||
var d = date.substring(8, 10);
|
||||
var m = date.substring(5, 7);
|
||||
var y = date.substring(0, 4);
|
||||
|
||||
$('#' + field + '_d').val(d == 0 ? '' : d);
|
||||
$('#' + field + '_m').val(m == 0 ? '' : m);
|
||||
$('#' + field + '_y').val(y == 0 ? '' : y);
|
||||
$('#' + field + '_approx_aprx').val(approx).change();
|
||||
}
|
||||
|
||||
|
||||
function fillFields(nid) {
|
||||
var i = 0;
|
||||
|
||||
$('#did').val(vdata[nid][i++]);
|
||||
$('#num').val(vdata[nid][i++]);
|
||||
$('#gos').val(vdata[nid][i++]);
|
||||
$('#nu2').val(vdata[nid][i++]);
|
||||
$('#mid').val(vdata[nid][i++]);
|
||||
$('#mname').val(vdata[nid][i++]);
|
||||
$('#chid').val(vdata[nid][i++]);
|
||||
$('#chname').val(vdata[nid][i++]);
|
||||
$('#service').val(vdata[nid][i++]).change();
|
||||
$('#state').val(vdata[nid][i++]).change();
|
||||
$('#zn').val(vdata[nid][i++]);
|
||||
$('#cn').val(vdata[nid][i++]);
|
||||
$('#vin').val(vdata[nid][i++]);
|
||||
|
||||
setDateByYM('built', vdata[nid][i + 1], vdata[nid][i], vdata[nid][i + 2]);
|
||||
i += 3;
|
||||
setDateByYM('scrap', vdata[nid][i + 1], vdata[nid][i], vdata[nid][i + 2]);
|
||||
i += 3;
|
||||
|
||||
setDateByDate('start', vdata[nid][i], vdata[nid][i + 1]);
|
||||
i += 2;
|
||||
setDateByDate('launc', vdata[nid][i], vdata[nid][i + 1]);
|
||||
i += 2;
|
||||
setDateByDate('haltd', vdata[nid][i], vdata[nid][i + 1]);
|
||||
i += 2;
|
||||
setDateByDate('leave', vdata[nid][i], vdata[nid][i + 1]);
|
||||
i += 2;
|
||||
|
||||
$('#note').val(vdata[nid][i++]);
|
||||
$('#history').val(vdata[nid][i++]);
|
||||
}
|
||||
</script>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>
|
||||
<br>
|
||||
<input type="submit" value=" Отправить ">
|
||||
<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) {
|
||||
echo '<option photourl="/api/photo/compress?url=' . $p['photourl'] . '" value="' . $p['id'] . '">[ID: ' . $p['id'] . '] ' . $p['place'] . '</option>';
|
||||
}
|
||||
}
|
||||
?>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
<td>
|
||||
<div id="result"></div>
|
||||
</td>
|
||||
<td>
|
||||
<br>
|
||||
<input type="submit" value=" Отправить ">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<?php include($_SERVER['DOCUMENT_ROOT'] . '/views/components/Footer.php'); ?>
|
||||
</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);
|
||||
|
||||
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
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>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
</body>
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -79,10 +79,10 @@ LIMIT 10;');
|
|||
<div class="hpshade">
|
||||
<div class="eye-icon">+' . $pd['view_count'] . '</div>
|
||||
</div>';
|
||||
if ((int)$p['priority'] === 1) {
|
||||
echo '<div class="temp" style="background-image:url(/static/img/cond.png)"></div>';
|
||||
}
|
||||
echo '
|
||||
if ((int)$p['priority'] === 1) {
|
||||
echo '<div class="temp" style="background-image:url(/static/img/cond.png)"></div>';
|
||||
}
|
||||
echo '
|
||||
</a>';
|
||||
}
|
||||
}
|
||||
|
@ -126,74 +126,39 @@ LIMIT 10;');
|
|||
#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) {
|
||||
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];
|
||||
$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>
|
||||
Закончится через: <b id="countdown"></b><br>
|
||||
Тематика: <b>'.$theme['title'].'</b><br>
|
||||
Тематика: <b>' . $theme['title'] . '</b><br>
|
||||
<b style="color: #412378;">Голосуйте за лучшие фотографии, которые должны стать победителями сегодняшнего конкурса!</b><br><br>
|
||||
<a href="/voting" style="background-color: #37009D; color: #fff;" type="button">Голосовать!</a>';
|
||||
<a href="/voting" style="background-color: #37009D; color: #fff;" type="button">Голосовать!</a>
|
||||
<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];
|
||||
$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>
|
||||
Начнётся через: <b id="countdown"></b><br>
|
||||
Тематика: <b>'.$theme.'</b><br>
|
||||
<b style="color: #412378;">Лучшие фотографии по мнению сообщества '.NGALLERY['root']['title'].' будут отмечены</b><br><br>
|
||||
<a href="/voting/sendpretend" style="background-color: #37009D; color: #fff;" type="button">Участвовать!</a>';
|
||||
Тематика: <b>' . $theme['title'] . '</b><br>
|
||||
<b style="color: #412378;">Лучшие фотографии по мнению сообщества ' . NGALLERY['root']['title'] . ' будут отмечены</b><br><br>
|
||||
<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>
|
||||
<script>startCountdown(' . $contest['closepretendsdate'] . ');</script>';
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
?>
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
<script>
|
||||
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, ['секунда', 'секунды', 'секунд'])}`;
|
||||
}
|
||||
</div>
|
||||
|
||||
updateTimer(); // сразу обновляем отображение
|
||||
const interval = setInterval(updateTimer, 1000);
|
||||
}
|
||||
startCountdown(1740607200);
|
||||
</script>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
@ -207,26 +172,26 @@ startCountdown(1740607200);
|
|||
$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>
|
||||
<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>, ';
|
||||
}
|
||||
?>
|
||||
<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>
|
||||
</div>
|
||||
</td>
|
||||
<td style="padding-left:20px; width:254px; vertical-align:top">
|
||||
|
||||
|
@ -235,8 +200,8 @@ startCountdown(1740607200);
|
|||
<?php
|
||||
$news = DB::query('SELECT * FROM news ORDER BY id DESC LIMIT 10');
|
||||
foreach ($news as $n) {
|
||||
echo '<div class="ix-news-item"><b>'.Date::zmdate($n['time']).'</b>
|
||||
<div class="break-links" style="padding-top:3px">'.$n['body'].'</div>
|
||||
echo '<div class="ix-news-item"><b>' . Date::zmdate($n['time']) . '</b>
|
||||
<div class="break-links" style="padding-top:3px">' . $n['body'] . '</div>
|
||||
</div>';
|
||||
}
|
||||
?>
|
||||
|
|
|
@ -151,7 +151,7 @@ if (Auth::userid() > 0) {
|
|||
</center>
|
||||
<?php } else { ?>
|
||||
<center>
|
||||
<h1>К сожалению, регистрация на сервере <?= NGALLERY['root']['title'] ?> запрещена.</h1>
|
||||
<h1>К сожалению, регистрация на сервере <?= NGALLERY['root']['title'] ?> закрыта.</h1>
|
||||
</center?
|
||||
<?php } ?>
|
||||
</td>
|
||||
|
|
Loading…
Reference in a new issue