mirror of
https://github.com/openvk/openvk
synced 2025-03-14 21:45:22 +03:00
Merge remote-tracking branch 'origin/master' into feature-reports
This commit is contained in:
commit
f3570a11fd
67 changed files with 1555 additions and 679 deletions
11
CODE_OF_CONFLICT.md
Normal file
11
CODE_OF_CONFLICT.md
Normal file
|
@ -0,0 +1,11 @@
|
|||
The OpenVK development effort is a very personal process compared to "traditional" ways of developing software.
|
||||
Your code and ideas behind it will be carefully reviewed, often resulting in critique and criticism.
|
||||
The review will almost always require improvements to the code before it can be included in the repo.
|
||||
Know that this happens because everyone involved wants to see the best possible solution for the overall success of OpenVK.
|
||||
|
||||
If however, anyone feels personally abused, threatened, or otherwise uncomfortable due to this process, that is not acceptable.
|
||||
If so, please contact the community manager @WerySkok and report the issue.
|
||||
|
||||
As a reviewer of code, please strive to keep things civil and focused on the technical issues involved. We are all humans,
|
||||
and frustrations can be high on both sides of the process.
|
||||
Try to keep in mind the immortal words of Bill and Ted, "Be excellent to each other."
|
277
CODE_STYLE.md
Normal file
277
CODE_STYLE.md
Normal file
|
@ -0,0 +1,277 @@
|
|||
# Names
|
||||
## Namespace Names
|
||||
Namespaces should be written in PascalCase.
|
||||
|
||||
## File Names
|
||||
Code directories should have their name written in PascalCase. Code files should contain only one class and have the name of that class.
|
||||
In case of multiple class definitions in one file, it's name should be the same as the "primary" class name.
|
||||
Non-code directories, non-class and non-code files should be named in lisp-case.
|
||||
|
||||
## Variable Names
|
||||
Variable names should be written in camelCase. This also applies to function arguments, class instance names and methods.
|
||||
|
||||
## Constant Names
|
||||
Constants are written in SCREAMING_SNAKE_CASE, but should be declared case-insensetive.
|
||||
|
||||
## Class Names
|
||||
Classes in OpenVK should belong to `openvk\` namespace and be in the corresponding directory (according to PSR-4). Names of classes should be written in PascalCase.
|
||||
|
||||
## Function Names
|
||||
camelCase and snake_case are allowed, but first one is the recommended way. This rule does not apply to class methods, which are written in camelCase only.
|
||||
|
||||
---
|
||||
|
||||
# Coding Rules
|
||||
## File header
|
||||
All OpenVK files must start with `<?php` open-tag followed by `declare(strict_types=1);` on the same line. The next line must contain namespace.
|
||||
The lines after must contain use-declarations, each on it's own line (usage of {} operator is OK), if there is any. Then there must be an empty line. Example:
|
||||
```php
|
||||
<?php declare(strict_types=1);
|
||||
namespace openvk;
|
||||
use Chandler\Database\DatabaseConnection;
|
||||
use Nette\Utils\{Image, FileSystem};
|
||||
|
||||
class ...
|
||||
```
|
||||
|
||||
## NULL
|
||||
Null should be written as constant, all-uppercase: `NULL`.
|
||||
|
||||
## Nullable (optional) pointer arguments
|
||||
Optional pointer arguments should default to `nullptr`: `function something(&int? $myPointer = nullptr)`. `nullptr` must be written in lisp-case (lowercase).
|
||||
|
||||
## Comparing to NULL
|
||||
In OpenVK `is_null` is the preferred way to check for equality to NULL. `??` must be used in assignments and where else possible.
|
||||
In case if value can either be NULL or truthy, "boolean not" should be used to check if value is not null: `if(!$var)`.
|
||||
|
||||
## Arrays
|
||||
Arrays must be defined with modern syntax: `[1, 2, 3]` (NOT `array(1, 2, 3)`).
|
||||
Same applies to `list` construction: use `[$a, , $b] = $arr;` instead of `list($a, , $b) = $arr;`
|
||||
|
||||
## Casts
|
||||
Typecasts must be done with modern syntax where possible: `(type) $var`. Int-to-string, string-to-int, etc conversions should also be dont with modern casting
|
||||
syntax where possible, but should use `ctype_` functions where needed. `gettype`, `settype` should be used in dynamic programming only.
|
||||
|
||||
## Goto
|
||||
```goto``` should be avoided.
|
||||
|
||||
## `continue n; `
|
||||
It is preferable to use `continue n`, `break n` instead of guarding flags:
|
||||
```php
|
||||
# COOL AND GOOD
|
||||
foreach($a as $b)
|
||||
foreach($b as $c)
|
||||
if($b == $c)
|
||||
break 2;
|
||||
|
||||
# BRUH
|
||||
foreach($a as $b) {
|
||||
$shouldBreak = false;
|
||||
foreach($b as $c)
|
||||
if($b == $c)
|
||||
$shouldBreak = true;
|
||||
|
||||
if($shouldBreak)
|
||||
break;
|
||||
}
|
||||
```
|
||||
|
||||
## Comments
|
||||
In OpenVK we use Perl-style `#` for single-line comments.
|
||||
|
||||
---
|
||||
|
||||
# Formatting
|
||||
## Variables
|
||||
It is preferable to declare only one variable per line in the code.
|
||||
|
||||
## Indentation
|
||||
All things in OpenVK must be properly indented by a sequence of 4 spaces. Not tabs. \
|
||||
When there are several variable declarations listed together, line up the variables:
|
||||
```php
|
||||
# OK
|
||||
$photos = (new Photos)->where("meow", true);
|
||||
$photo = $photos->fetch();
|
||||
$arr = [
|
||||
"a" => 10,
|
||||
"bb" => true,
|
||||
];
|
||||
|
||||
# NOT OK
|
||||
$photos = (new Photos)->where("meow", true);
|
||||
$photo = $photos->fetch();
|
||||
$arr = [
|
||||
"a" => 10,
|
||||
"bb" => true,
|
||||
];
|
||||
```
|
||||
|
||||
## Tab/Space
|
||||
+ **Do not use tabs**. Use spaces, as tabs are defined differently for different editors and printers.
|
||||
+ Put one space after a comma and semicolons: `exp(1, 2)` `for($i = 1; $i < 100; $i++)`
|
||||
+ Put one space around assignment operators: `$a = 1`
|
||||
+ Always put a space around conditional operators: `$a = ($a > $b) ? $a : $b`
|
||||
+ Do not put spaces between unary operators and their operands, primary operators and keywords:
|
||||
```php
|
||||
# OK
|
||||
-$a;
|
||||
$a++;
|
||||
$b[1] = $a;
|
||||
fun($b);
|
||||
if($a) { ... }
|
||||
|
||||
# NOT OK
|
||||
- $a;
|
||||
$a ++;
|
||||
$b [1] = $a;
|
||||
fun ($b);
|
||||
if ($a) { ... }
|
||||
```
|
||||
|
||||
## Blank Lines
|
||||
+ Use blank lines to create paragraphs in the code or comments to make the code more understandable
|
||||
+ Use blank lines before `return` statement if it isn't the only statement in the block
|
||||
+ Use blank lines after shorthand if/else/etc
|
||||
```php
|
||||
# OK
|
||||
if($a)
|
||||
return $x;
|
||||
|
||||
doSomething();
|
||||
|
||||
return "yay";
|
||||
|
||||
# NOT OK
|
||||
if($a) return $x; # return must be on separate line
|
||||
doSomething(); # doSomething must be separated by an extra blank line after short if/else
|
||||
return "yay"; # do use blank lines before return statement
|
||||
```
|
||||
|
||||
|
||||
## Method/Function Arguments
|
||||
+ When all arguments for a function do not fit on one line, try to line up the first argument in each line:
|
||||

|
||||
|
||||
+ If the argument lists are still too long to fit on the line, you may line up the arguments with the method name instead.
|
||||
|
||||
## Maximum characters per line
|
||||
Lines should be no more than 80 characters long.
|
||||
|
||||
## Usage of curly braces
|
||||
+ Curly braces should be on separate line for class, method, and function definitions.
|
||||
+ In loops, if/else, try/catch, switch constructions the opening brace should be on the same line as the operator.
|
||||
+ Braces must be ommited if the block contains only one statement **AND** the related blocks are also single statemented.
|
||||
+ Nested single-statement+operator blocks must not be surrounded by braces.
|
||||
```php
|
||||
# OK
|
||||
class A
|
||||
{
|
||||
function doSomethingFunny(): int
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
if(true) {
|
||||
doSomething();
|
||||
doSomethingElse();
|
||||
} else {
|
||||
doSomethingFunny();
|
||||
}
|
||||
|
||||
if($a)
|
||||
return false;
|
||||
else
|
||||
doSomething();
|
||||
|
||||
foreach($b as $c => $d)
|
||||
if($c == $d)
|
||||
unset($b[$c]);
|
||||
|
||||
# NOT OK
|
||||
class A {
|
||||
function doSomethingFunny(): int {
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
if(true) {
|
||||
doSomething();
|
||||
doSomethingElse();
|
||||
} else
|
||||
doSomethingFunny(); # why?
|
||||
|
||||
if($a) {
|
||||
return false;
|
||||
} else {
|
||||
doSomething();
|
||||
}
|
||||
|
||||
foreach($b as $c => $d) {
|
||||
if($c == $d)
|
||||
unset($b[$c]);
|
||||
}
|
||||
|
||||
# lmao
|
||||
if($a) { doSomething(); } else doSomethingElse();
|
||||
```
|
||||
|
||||
## if/else, try/catch
|
||||
+ Operators must not be indented with space from their operands but must have 1-space margin from braces:
|
||||
```php
|
||||
# OK
|
||||
if($a) {
|
||||
doSomething();
|
||||
doSomethingElse();
|
||||
} else if($b) {
|
||||
try {
|
||||
nukeSaintPetersburg('😈');
|
||||
} finally {
|
||||
return PEACE;
|
||||
}
|
||||
}
|
||||
|
||||
# NOT OK
|
||||
if ($a) { # do not add space between control flow operator IF and it's operand
|
||||
doSomething();
|
||||
doSomethingElse();
|
||||
}elseif($b){ # do add margin from braces; also ELSE and IF should be separate here
|
||||
try{
|
||||
nukeSaintPetersburg('😈');
|
||||
}finally{
|
||||
return PEACE;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Switches
|
||||
+ `break` must be on same indentation level as the code of le case (not the case definiton itself)
|
||||
+ If there is no need to `break` a comment `# NOTICE falling through` must be places instead
|
||||
```php
|
||||
# OK
|
||||
switch($a) {
|
||||
case 1:
|
||||
echo $a;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
echo $a++;
|
||||
# NOTICE falling through
|
||||
|
||||
default:
|
||||
echo "c";
|
||||
}
|
||||
|
||||
# NOT OK
|
||||
switch($a) {
|
||||
case 1:
|
||||
echo $a;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
echo $a++;
|
||||
|
||||
default:
|
||||
echo "c";
|
||||
}
|
||||
```
|
204
Email/change-email.eml.latte
Normal file
204
Email/change-email.eml.latte
Normal file
|
@ -0,0 +1,204 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name="viewport" content="width=device-width" />
|
||||
<title>Подтверждение изменения Email</title>
|
||||
<link rel="stylesheet" href="foundation.css" />
|
||||
<style>
|
||||
.container {
|
||||
border-top: 5px solid pink;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<table class="body" data-made-with-foundation="">
|
||||
<tr>
|
||||
<td class="float-center" align="center" valign="top">
|
||||
<center>
|
||||
<table class="spacer">
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table class="container">
|
||||
<tr>
|
||||
<td>
|
||||
<table class="row header">
|
||||
<tr>
|
||||
<th class="small-12 large-12 columns first last">
|
||||
<table>
|
||||
<tr>
|
||||
<th>
|
||||
<table class="spacer">
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<h4 class="text-center">Подтверждение изменения Email</h4>
|
||||
</th>
|
||||
</tr>
|
||||
</table>
|
||||
</th>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<table class="row">
|
||||
<tr>
|
||||
<th class="small-12 large-12 columns first last">
|
||||
<table class="row">
|
||||
<tr>
|
||||
<td>
|
||||
<center>
|
||||
<img src="pictures/lock.jpeg" align="center" class="float-center" width=128 height=128 />
|
||||
</center>
|
||||
|
||||
<table class="spacer">
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<hr/>
|
||||
|
||||
<table class="spacer">
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<p class="text-left">
|
||||
Здравствуйте, {$name}! Вы вероятно изменили свой адрес электронной почты в OpenVK. Чтобы изменение вступило в силу, необходимо подтвердить ваш новый Email.
|
||||
</p>
|
||||
|
||||
<table class="spacer">
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<table class="button large expand success">
|
||||
<tr>
|
||||
<td>
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<center>
|
||||
<a href="http://{$_SERVER['HTTP_HOST']}/settings/change_email?key={rawurlencode($key)}" align="center" class="float-center">Подтвердить Email!</a>
|
||||
</center>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<table class="spacer">
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<p class="text-left">
|
||||
Если кнопка не работает, вы можете попробовать скопировать и вставить эту ссылку в адресную строку вашего веб-обозревателя:
|
||||
</p>
|
||||
|
||||
<table class="callout">
|
||||
<tr>
|
||||
<th class="callout-inner primary">
|
||||
<a href="http://{$_SERVER['HTTP_HOST']}/settings/change_email?key={$key}" style="color: #000; text-decoration: none;">
|
||||
http://{$_SERVER['HTTP_HOST']}/settings/change_email?key={$key}
|
||||
</a>
|
||||
</th>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<p class="text-left">
|
||||
Обратите внимание на то, что эту ссылку нельзя:
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li>Передавать другим людям (даже друзьям, питомцам, соседам, любимым девушкам)</li>
|
||||
<li>Использовать, если прошло более двух дней с её генерации</li>
|
||||
</ul>
|
||||
|
||||
<table class="callout">
|
||||
<tr>
|
||||
<th class="callout-inner alert">
|
||||
<p>
|
||||
Ещё раз <b>обратите внимание</b> на то, что данную ссылку или письмо <b>ни в коем случае нельзя</b> передавать другим людям! Даже если они представляются службой поддержки.<br/>
|
||||
Это письмо предназначено исключительно для одноразового, <b>непосредственного</b> использования владельцем аккаунта.
|
||||
</p>
|
||||
</th>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<table class="spacer">
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<p class="text-right">
|
||||
С уважением, овк-тян.
|
||||
</p>
|
||||
|
||||
<table class="spacer">
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<hr/>
|
||||
|
||||
<table class="spacer">
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<p class="text-left">
|
||||
<small>
|
||||
Вы получили это письмо так как кто-то или вы изменили адрес электронной почты. Это не рассылка и от неё нельзя отписаться. Если вы всё равно хотите перестать получать подобные письма, деактивируйте ваш аккаунт.
|
||||
</small>
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</th>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table class="spacer">
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</center>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
|
@ -13,9 +13,9 @@ final class Account extends VKAPIRequestHandler
|
|||
"last_name" => $this->getUser()->getLastName(),
|
||||
"home_town" => $this->getUser()->getHometown(),
|
||||
"status" => $this->getUser()->getStatus(),
|
||||
"bdate" => "1.1.1970", // TODO
|
||||
"bdate_visibility" => 0, // TODO
|
||||
"phone" => "+420 ** *** 228", // TODO
|
||||
"bdate" => "1.1.1970", # TODO
|
||||
"bdate_visibility" => 0, # TODO
|
||||
"phone" => "+420 ** *** 228", # TODO
|
||||
"relation" => $this->getUser()->getMaritalStatus(),
|
||||
"sex" => $this->getUser()->isFemale() ? 1 : 2
|
||||
];
|
||||
|
@ -25,12 +25,12 @@ final class Account extends VKAPIRequestHandler
|
|||
{
|
||||
$this->requireUser();
|
||||
|
||||
// Цiй метод є заглушка
|
||||
# Цiй метод є заглушка
|
||||
|
||||
return (object) [
|
||||
"2fa_required" => 0,
|
||||
"country" => "CZ", // TODO
|
||||
"eu_user" => false, // TODO
|
||||
"country" => "CZ", # TODO
|
||||
"eu_user" => false, # TODO
|
||||
"https_required" => 1,
|
||||
"intro" => 0,
|
||||
"community_comments" => false,
|
||||
|
@ -55,7 +55,7 @@ final class Account extends VKAPIRequestHandler
|
|||
{
|
||||
$this->requireUser();
|
||||
|
||||
// Цiй метод є заглушка
|
||||
# Цiй метод є заглушка
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -73,6 +73,6 @@ final class Account extends VKAPIRequestHandler
|
|||
"messages" => $this->getUser()->getUnreadMessagesCount()
|
||||
];
|
||||
|
||||
// TODO: Filter
|
||||
# TODO: Filter
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ final class Friends extends VKAPIRequestHandler
|
|||
$usersApi = new Users($this->getUser());
|
||||
|
||||
if (!is_null($fields)) {
|
||||
$response = $usersApi->get(implode(',', $friends), $fields, 0, $count); // FIXME
|
||||
$response = $usersApi->get(implode(',', $friends), $fields, 0, $count); # FIXME
|
||||
}
|
||||
|
||||
return (object) [
|
||||
|
|
|
@ -48,7 +48,7 @@ final class Groups extends VKAPIRequestHandler
|
|||
"name" => "DELETED",
|
||||
"deactivated" => "deleted"
|
||||
];
|
||||
}else if($clbs[$i] == null){
|
||||
}else if($clbs[$i] == NULL){
|
||||
|
||||
}else{
|
||||
$rClubs[$i] = (object)[
|
||||
|
@ -95,10 +95,10 @@ final class Groups extends VKAPIRequestHandler
|
|||
|
||||
$clubs = new ClubsRepo;
|
||||
|
||||
if ($group_ids == null && $group_id != null)
|
||||
if ($group_ids == NULL && $group_id != NULL)
|
||||
$group_ids = $group_id;
|
||||
|
||||
if ($group_ids == null && $group_id == null)
|
||||
if ($group_ids == NULL && $group_id == NULL)
|
||||
$this->fail(100, "One of the parameters specified was missing or invalid: group_ids is undefined");
|
||||
|
||||
$clbs = explode(',', $group_ids);
|
||||
|
@ -123,7 +123,7 @@ final class Groups extends VKAPIRequestHandler
|
|||
"type" => "group",
|
||||
"description" => "This group was deleted or it doesn't exist"
|
||||
];
|
||||
}else if($clbs[$i] == null){
|
||||
}else if($clbs[$i] == NULL){
|
||||
|
||||
}else{
|
||||
$response[$i] = (object)[
|
||||
|
|
|
@ -63,7 +63,7 @@ final class Likes extends VKAPIRequestHandler
|
|||
|
||||
return (object)[
|
||||
"liked" => (int) $post->hasLikeFrom($user),
|
||||
"copied" => 0 // TODO: handle this
|
||||
"copied" => 0 # TODO: handle this
|
||||
];
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -7,9 +7,9 @@ final class Users extends VKAPIRequestHandler
|
|||
{
|
||||
function get(string $user_ids = "0", string $fields = "", int $offset = 0, int $count = 100, User $authuser = null /* костыль(( */): array
|
||||
{
|
||||
// $this->requireUser();
|
||||
# $this->requireUser();
|
||||
|
||||
if($authuser == null) $authuser = $this->getUser();
|
||||
if($authuser == NULL) $authuser = $this->getUser();
|
||||
|
||||
$users = new UsersRepo;
|
||||
if($user_ids == "0")
|
||||
|
@ -34,7 +34,7 @@ final class Users extends VKAPIRequestHandler
|
|||
"last_name" => "",
|
||||
"deactivated" => "deleted"
|
||||
];
|
||||
}else if($usrs[$i] == null){
|
||||
}else if($usrs[$i] == NULL){
|
||||
|
||||
}else{
|
||||
$response[$i] = (object)[
|
||||
|
@ -73,21 +73,21 @@ final class Users extends VKAPIRequestHandler
|
|||
case 'photo_200':
|
||||
$response[$i]->photo_50 = $usr->getAvatarURL("normal");
|
||||
break;
|
||||
case 'photo_200_orig': // вообще не ебу к чему эта строка ну пусть будет кек
|
||||
case 'photo_200_orig': # вообще не ебу к чему эта строка ну пусть будет кек
|
||||
$response[$i]->photo_50 = $usr->getAvatarURL("normal");
|
||||
break;
|
||||
case 'photo_400_orig':
|
||||
$response[$i]->photo_50 = $usr->getAvatarURL("normal");
|
||||
break;
|
||||
|
||||
// Она хочет быть выебанной видя матан
|
||||
// Покайфу когда ты Виет а вокруг лишь дискриминант
|
||||
# Она хочет быть выебанной видя матан
|
||||
# Покайфу когда ты Виет а вокруг лишь дискриминант
|
||||
case 'status':
|
||||
if($usr->getStatus() != null)
|
||||
if($usr->getStatus() != NULL)
|
||||
$response[$i]->status = $usr->getStatus();
|
||||
break;
|
||||
case 'screen_name':
|
||||
if($usr->getShortCode() != null)
|
||||
if($usr->getShortCode() != NULL)
|
||||
$response[$i]->screen_name = $usr->getShortCode();
|
||||
break;
|
||||
case 'friend_status':
|
||||
|
|
|
@ -23,56 +23,21 @@ final class Wall extends VKAPIRequestHandler
|
|||
foreach ($posts->getPostsFromUsersWall((int)$owner_id, 1, $count, $offset) as $post) {
|
||||
$from_id = get_class($post->getOwner()) == "openvk\Web\Models\Entities\Club" ? $post->getOwner()->getId() * (-1) : $post->getOwner()->getId();
|
||||
|
||||
$attachments;
|
||||
foreach($post->getChildren() as $attachment)
|
||||
{
|
||||
if($attachment instanceof \openvk\Web\Models\Entities\Photo)
|
||||
{
|
||||
$attachments = [];
|
||||
foreach($post->getChildren() as $attachment) {
|
||||
if($attachment instanceof \openvk\Web\Models\Entities\Photo) {
|
||||
if($attachment->isDeleted())
|
||||
continue;
|
||||
|
||||
$attachments[] = [
|
||||
"type" => "photo",
|
||||
"photo" => [
|
||||
"album_id" => $attachment->getAlbum() ? $attachment->getAlbum()->getId() : null,
|
||||
"date" => $attachment->getPublicationTime()->timestamp(),
|
||||
"id" => $attachment->getVirtualId(),
|
||||
"album_id" => $attachment->getAlbum() ? $attachment->getAlbum()->getId() : NULL,
|
||||
"date" => $attachment->getPublicationTime()->timestamp(),
|
||||
"id" => $attachment->getVirtualId(),
|
||||
"owner_id" => $attachment->getOwner()->getId(),
|
||||
"sizes" => array(
|
||||
[
|
||||
"height" => 2560,
|
||||
"url" => $attachment->getURLBySizeId("normal"),
|
||||
"type" => "m",
|
||||
"width" => 2560,
|
||||
],
|
||||
[
|
||||
"height" => 130,
|
||||
"url" => $attachment->getURLBySizeId("tiny"),
|
||||
"type" => "o",
|
||||
"width" => 130,
|
||||
],
|
||||
[
|
||||
"height" => 604,
|
||||
"url" => $attachment->getURLBySizeId("normal"),
|
||||
"type" => "p",
|
||||
"width" => 604,
|
||||
],
|
||||
[
|
||||
"height" => 807,
|
||||
"url" => $attachment->getURLBySizeId("large"),
|
||||
"type" => "q",
|
||||
"width" => 807,
|
||||
],
|
||||
[
|
||||
"height" => 1280,
|
||||
"url" => $attachment->getURLBySizeId("larger"),
|
||||
"type" => "r",
|
||||
"width" => 1280,
|
||||
],
|
||||
[
|
||||
"height" => 75, // Для временного компросима оставляю статическое число. Если каждый раз обращаться к файлу за количеством пикселов, то наступает пuпuська полная с производительностью, так что пока так
|
||||
"url" => $attachment->getURLBySizeId("miniscule"),
|
||||
"type" => "s",
|
||||
"width" => 75,
|
||||
]),
|
||||
"text" => "",
|
||||
"sizes" => array_values($attachment->getVkApiSizes()),
|
||||
"text" => "",
|
||||
"has_tags" => false
|
||||
]
|
||||
];
|
||||
|
@ -86,10 +51,10 @@ final class Wall extends VKAPIRequestHandler
|
|||
"date" => $post->getPublicationTime()->timestamp(),
|
||||
"post_type" => "post",
|
||||
"text" => $post->getText(),
|
||||
"can_edit" => 0, // TODO
|
||||
"can_edit" => 0, # TODO
|
||||
"can_delete" => $post->canBeDeletedBy($this->getUser()),
|
||||
"can_pin" => $post->canBePinnedBy($this->getUser()),
|
||||
"can_archive" => false, // TODO MAYBE
|
||||
"can_archive" => false, # TODO MAYBE
|
||||
"is_archived" => false,
|
||||
"is_pinned" => $post->isPinned(),
|
||||
"attachments" => $attachments,
|
||||
|
@ -115,7 +80,7 @@ final class Wall extends VKAPIRequestHandler
|
|||
else
|
||||
$groups[] = $from_id * -1;
|
||||
|
||||
$attachments = null; // free attachments so it will not clone everythingg
|
||||
$attachments = NULL; # free attachments so it will not clone everythingg
|
||||
}
|
||||
|
||||
if($extended == 1)
|
||||
|
@ -170,9 +135,9 @@ final class Wall extends VKAPIRequestHandler
|
|||
];
|
||||
}
|
||||
|
||||
function getById(string $posts, int $extended = 0, string $fields = "", User $user = null)
|
||||
function getById(string $posts, int $extended = 0, string $fields = "", User $user = NULL)
|
||||
{
|
||||
if($user == null) $user = $this->getUser(); // костыли костыли крылышки
|
||||
if($user == NULL) $user = $this->getUser(); # костыли костыли крылышки
|
||||
|
||||
$items = [];
|
||||
$profiles = [];
|
||||
|
@ -195,7 +160,7 @@ final class Wall extends VKAPIRequestHandler
|
|||
$attachments[] = [
|
||||
"type" => "photo",
|
||||
"photo" => [
|
||||
"album_id" => $attachment->getAlbum() ? $attachment->getAlbum()->getId() : null,
|
||||
"album_id" => $attachment->getAlbum() ? $attachment->getAlbum()->getId() : NULL,
|
||||
"date" => $attachment->getPublicationTime()->timestamp(),
|
||||
"id" => $attachment->getVirtualId(),
|
||||
"owner_id" => $attachment->getOwner()->getId(),
|
||||
|
@ -231,7 +196,7 @@ final class Wall extends VKAPIRequestHandler
|
|||
"width" => 1280,
|
||||
],
|
||||
[
|
||||
"height" => 75, // Для временного компросима оставляю статическое число. Если каждый раз обращаться к файлу за количеством пикселов, то наступает пuпuська полная с производительностью, так что пока так
|
||||
"height" => 75, # Для временного компросима оставляю статическое число. Если каждый раз обращаться к файлу за количеством пикселов, то наступает пuпuська полная с производительностью, так что пока так
|
||||
"url" => $attachment->getURLBySizeId("miniscule"),
|
||||
"type" => "s",
|
||||
"width" => 75,
|
||||
|
@ -250,10 +215,10 @@ final class Wall extends VKAPIRequestHandler
|
|||
"date" => $post->getPublicationTime()->timestamp(),
|
||||
"post_type" => "post",
|
||||
"text" => $post->getText(),
|
||||
"can_edit" => 0, // TODO
|
||||
"can_edit" => 0, # TODO
|
||||
"can_delete" => $post->canBeDeletedBy($user),
|
||||
"can_pin" => $post->canBePinnedBy($user),
|
||||
"can_archive" => false, // TODO MAYBE
|
||||
"can_archive" => false, # TODO MAYBE
|
||||
"is_archived" => false,
|
||||
"is_pinned" => $post->isPinned(),
|
||||
"post_source" => (object)["type" => "vk"],
|
||||
|
@ -279,7 +244,7 @@ final class Wall extends VKAPIRequestHandler
|
|||
else
|
||||
$groups[] = $from_id * -1;
|
||||
|
||||
$attachments = null; // free attachments so it will not clone everythingg
|
||||
$attachments = NULL; # free attachments so it will not clone everythingg
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -370,12 +335,12 @@ final class Wall extends VKAPIRequestHandler
|
|||
if($signed == 1)
|
||||
$flags |= 0b01000000;
|
||||
|
||||
// TODO: Compatible implementation of this
|
||||
# TODO: Compatible implementation of this
|
||||
try {
|
||||
$photo = null;
|
||||
$video = null;
|
||||
$photo = NULL;
|
||||
$video = NULL;
|
||||
if($_FILES["photo"]["error"] === UPLOAD_ERR_OK) {
|
||||
$album = null;
|
||||
$album = NULL;
|
||||
if(!$anon && $owner_id > 0 && $owner_id === $this->getUser()->getId())
|
||||
$album = (new AlbumsRepo)->getUserWallAlbum($wallOwner);
|
||||
|
||||
|
|
|
@ -99,6 +99,14 @@ class Club extends RowModel
|
|||
{
|
||||
return $this->getRecord()->about;
|
||||
}
|
||||
|
||||
function getDescriptionHtml(): ?string
|
||||
{
|
||||
if(!is_null($this->getDescription()))
|
||||
return nl2br(htmlspecialchars($this->getDescription(), ENT_DISALLOWED | ENT_XHTML));
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
function getShortCode(): ?string
|
||||
{
|
||||
|
@ -302,8 +310,8 @@ class Club extends RowModel
|
|||
{
|
||||
$manager = (new Managers)->getByUserAndClub($user->getId(), $this->getId());
|
||||
|
||||
if ($ignoreHidden && $manager !== null && $manager->isHidden())
|
||||
return null;
|
||||
if ($ignoreHidden && $manager !== NULL && $manager->isHidden())
|
||||
return NULL;
|
||||
|
||||
return $manager;
|
||||
}
|
||||
|
|
|
@ -131,7 +131,7 @@ class Correspondence
|
|||
*/
|
||||
function getPreviewMessage(): ?Message
|
||||
{
|
||||
$messages = $this->getMessages(1, null, 1);
|
||||
$messages = $this->getMessages(1, NULL, 1);
|
||||
return $messages[0] ?? NULL;
|
||||
}
|
||||
|
||||
|
|
15
Web/Models/Entities/EmailChangeVerification.php
Normal file
15
Web/Models/Entities/EmailChangeVerification.php
Normal file
|
@ -0,0 +1,15 @@
|
|||
<?php declare(strict_types=1);
|
||||
namespace openvk\Web\Models\Entities;
|
||||
use openvk\Web\Models\Repositories\Users;
|
||||
use openvk\Web\Models\RowModel;
|
||||
use openvk\Web\Util\DateTime;
|
||||
|
||||
class EmailChangeVerification extends PasswordReset
|
||||
{
|
||||
protected $tableName = "email_change_verifications";
|
||||
|
||||
function getNewEmail(): string
|
||||
{
|
||||
return $this->getRecord()->new_email;
|
||||
}
|
||||
}
|
|
@ -126,7 +126,7 @@ class Message extends RowModel
|
|||
],
|
||||
"timing" => [
|
||||
"sent" => (string) $this->getSendTime()->format("%e %B %G" . tr("time_at_sp") . "%X"),
|
||||
"edited" => is_null($this->getEditTime()) ? null : (string) $this->getEditTime(),
|
||||
"edited" => is_null($this->getEditTime()) ? NULL : (string) $this->getEditTime(),
|
||||
],
|
||||
"text" => $this->getText(),
|
||||
"read" => !$this->isUnread(),
|
||||
|
|
|
@ -165,8 +165,11 @@ class Photo extends Media
|
|||
foreach($manifest->Size as $size)
|
||||
$mappings[(string) $size["id"]] = (string) $size["vkId"];
|
||||
|
||||
foreach($sizes as $id => $meta)
|
||||
$res[$mappings[$id] ?? $id] = $meta;
|
||||
foreach($sizes as $id => $meta) {
|
||||
$type = $mappings[$id] ?? $id;
|
||||
$meta->type = $type;
|
||||
$res[$type] = $meta;
|
||||
}
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
|
|
@ -87,7 +87,7 @@ abstract class Postable extends Attachable
|
|||
]));
|
||||
}
|
||||
|
||||
// TODO add pagination
|
||||
# TODO add pagination
|
||||
function getLikers(): \Traversable
|
||||
{
|
||||
$sel = DB::i()->getContext()->table("likes")->where([
|
||||
|
|
|
@ -85,6 +85,11 @@ class User extends RowModel
|
|||
{
|
||||
return (bool) $this->getRecord()->microblog;
|
||||
}
|
||||
|
||||
function getMainPage(): int
|
||||
{
|
||||
return $this->getRecord()->main_page;
|
||||
}
|
||||
|
||||
function getChandlerGUID(): string
|
||||
{
|
||||
|
@ -877,6 +882,17 @@ class User extends RowModel
|
|||
return true;
|
||||
}
|
||||
|
||||
function changeEmail(string $email): void
|
||||
{
|
||||
DatabaseConnection::i()->getContext()->table("ChandlerUsers")
|
||||
->where("id", $this->getChandlerUser()->getId())->update([
|
||||
"login" => $email
|
||||
]);
|
||||
|
||||
$this->stateChanges("email", $email);
|
||||
$this->save();
|
||||
}
|
||||
|
||||
function adminNotify(string $message): bool
|
||||
{
|
||||
$admId = OPENVK_ROOT_CONF["openvk"]["preferences"]["support"]["adminAccount"];
|
||||
|
@ -928,7 +944,7 @@ class User extends RowModel
|
|||
return $this->getRecord()->website;
|
||||
}
|
||||
|
||||
// ты устрица
|
||||
# ты устрица
|
||||
function isActivated(): bool
|
||||
{
|
||||
return (bool) $this->getRecord()->activated;
|
||||
|
|
|
@ -63,7 +63,7 @@ class Video extends Media
|
|||
|
||||
if(!file_exists($this->getFileName())) {
|
||||
if((time() - $this->getRecord()->last_checked) > 3600) {
|
||||
// TODO notify that video processor is probably dead
|
||||
# TODO notify that video processor is probably dead
|
||||
}
|
||||
|
||||
return false;
|
||||
|
|
33
Web/Models/Repositories/EmailChangeVerifications.php
Normal file
33
Web/Models/Repositories/EmailChangeVerifications.php
Normal file
|
@ -0,0 +1,33 @@
|
|||
<?php declare(strict_types=1);
|
||||
namespace openvk\Web\Models\Repositories;
|
||||
use Chandler\Database\DatabaseConnection;
|
||||
use openvk\Web\Models\Entities\EmailChangeVerification;
|
||||
use openvk\Web\Models\Entities\User;
|
||||
use Nette\Database\Table\ActiveRow;
|
||||
|
||||
class EmailChangeVerifications
|
||||
{
|
||||
private $context;
|
||||
private $verifications;
|
||||
|
||||
function __construct()
|
||||
{
|
||||
$this->context = DatabaseConnection::i()->getContext();
|
||||
$this->verifications = $this->context->table("email_change_verifications");
|
||||
}
|
||||
|
||||
function toEmailChangeVerification(?ActiveRow $ar): ?EmailChangeVerification
|
||||
{
|
||||
return is_null($ar) ? NULL : new EmailChangeVerification($ar);
|
||||
}
|
||||
|
||||
function getByToken(string $token): ?EmailChangeVerification
|
||||
{
|
||||
return $this->toEmailChangeVerification($this->verifications->where("key", $token)->fetch());
|
||||
}
|
||||
|
||||
function getLatestByUser(User $user): ?EmailChangeVerification
|
||||
{
|
||||
return $this->toEmailChangeVerification($this->verifications->where("profile", $user->getId())->order("timestamp DESC")->fetch());
|
||||
}
|
||||
}
|
|
@ -39,7 +39,7 @@ class Notes
|
|||
if(!is_null($note))
|
||||
return new Note($note);
|
||||
else
|
||||
return null;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
function getUserNotesCount(User $user): int
|
||||
|
|
|
@ -96,7 +96,7 @@ class Posts
|
|||
if(!is_null($post))
|
||||
return new Post($post);
|
||||
else
|
||||
return null;
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +1,5 @@
|
|||
<?php declare(strict_types=1);
|
||||
namespace openvk\Web\Models\Repositories;
|
||||
// use openvk\Web\Models\Entities\Ticket;
|
||||
// use openvk\Web\Models\Entities\User;
|
||||
// use openvk\Web\Models\Repositories\Users;
|
||||
use openvk\Web\Models\Entities\TicketComment;
|
||||
use Chandler\Database\DatabaseConnection;
|
||||
|
||||
|
@ -21,32 +18,6 @@ class TicketComments
|
|||
{
|
||||
foreach($this->comments->where(['ticket_id' => $ticket_id, 'deleted' => 0]) as $comment) yield new TicketComment($comment);
|
||||
}
|
||||
|
||||
// private function toTicket(?ActiveRow $ar): ?Ticket
|
||||
// {
|
||||
// return is_null($ar) ? NULL : new Ticket($ar);
|
||||
// }
|
||||
|
||||
// function getTicketsByuId(int $user_id): \Traversable
|
||||
// {
|
||||
// foreach($this->tickets->where(['user_id' => $user_id, 'deleted' => 0]) as $ticket) yield new Ticket($ticket);
|
||||
// }
|
||||
|
||||
// function getRequestById(int $req_id): ?Ticket
|
||||
// {
|
||||
// $requests = $this->tickets->where(['id' => $req_id])->fetch();
|
||||
// if(!is_null($requests))
|
||||
|
||||
// return new Req($requests);
|
||||
// else
|
||||
// return null;
|
||||
|
||||
// }
|
||||
|
||||
// function get(int $id): ?Ticket
|
||||
// {
|
||||
// return $this->toTicket($this->tickets->get($id));
|
||||
// }
|
||||
|
||||
function get(int $id): ?TicketComment
|
||||
{
|
||||
|
|
|
@ -50,7 +50,7 @@ class Tickets
|
|||
if(!is_null($requests))
|
||||
return new Req($requests);
|
||||
else
|
||||
return null;
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@ class Topics
|
|||
{
|
||||
$perPage = $perPage ?? OPENVK_DEFAULT_PER_PAGE;
|
||||
|
||||
// Get pinned topics first
|
||||
# Get pinned topics first
|
||||
$query = "SELECT `id` FROM `topics` WHERE `pinned` = 1 AND `group` = ? AND `deleted` = 0 UNION SELECT `id` FROM `topics` WHERE `pinned` = 0 AND `group` = ? AND `deleted` = 0";
|
||||
$query .= " LIMIT " . $perPage . " OFFSET " . ($page - 1) * $perPage;
|
||||
|
||||
|
|
|
@ -14,7 +14,12 @@ final class AboutPresenter extends OpenVKPresenter
|
|||
{
|
||||
if(!is_null($this->user)) {
|
||||
header("HTTP/1.1 302 Found");
|
||||
header("Location: /id" . $this->user->id);
|
||||
|
||||
if($this->user->identity->getMainPage())
|
||||
header("Location: /feed");
|
||||
else
|
||||
header("Location: /id" . $this->user->id);
|
||||
|
||||
exit;
|
||||
}
|
||||
|
||||
|
@ -85,7 +90,7 @@ final class AboutPresenter extends OpenVKPresenter
|
|||
if(is_null($lg))
|
||||
$this->throwError(404, "Not found", "Language is not found");
|
||||
header("Content-Type: application/javascript");
|
||||
echo "window.lang = " . json_encode($localizer->export($lang)) . ";"; // привет хардкод :DDD
|
||||
echo "window.lang = " . json_encode($localizer->export($lang)) . ";"; # привет хардкод :DDD
|
||||
exit;
|
||||
}
|
||||
|
||||
|
@ -120,7 +125,7 @@ final class AboutPresenter extends OpenVKPresenter
|
|||
|
||||
function renderHumansTxt(): void
|
||||
{
|
||||
// :D
|
||||
# :D
|
||||
|
||||
header("HTTP/1.1 302 Found");
|
||||
header("Location: https://github.com/openvk/openvk#readme");
|
||||
|
|
|
@ -23,7 +23,7 @@ final class AdminPresenter extends OpenVKPresenter
|
|||
private function warnIfNoCommerce(): void
|
||||
{
|
||||
if(!OPENVK_ROOT_CONF["openvk"]["preferences"]["commerce"])
|
||||
$this->flash("warn", "Коммерция отключена системным администратором", "Настройки ваучеров и подарков будут сохранены, но не будут оказывать никакого влияния.");
|
||||
$this->flash("warn", tr("admin_commerce_disabled"), tr("admin_commerce_disabled_desc"));
|
||||
}
|
||||
|
||||
private function searchResults(object $repo, &$count)
|
||||
|
@ -70,14 +70,14 @@ final class AdminPresenter extends OpenVKPresenter
|
|||
$user->setLast_Name($this->postParam("last_name"));
|
||||
$user->setPseudo($this->postParam("nickname"));
|
||||
$user->setStatus($this->postParam("status"));
|
||||
$user->setVerified(empty($this->postParam("verify") ? 0 : 1));
|
||||
if($user->onlineStatus() != $this->postParam("online")) $user->setOnline(intval($this->postParam("online")));
|
||||
if(!$user->setShortCode(empty($this->postParam("shortcode")) ? NULL : $this->postParam("shortcode")))
|
||||
$this->flash("err", tr("error"), tr("error_shorturl_incorrect"));
|
||||
$user->changeEmail($this->postParam("email"));
|
||||
if($user->onlineStatus() != $this->postParam("online")) $user->setOnline(intval($this->postParam("online")));
|
||||
$user->setVerified(empty($this->postParam("verify") ? 0 : 1));
|
||||
|
||||
$user->save();
|
||||
break;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -60,7 +60,7 @@ final class CommentPresenter extends OpenVKPresenter
|
|||
}
|
||||
}
|
||||
|
||||
// TODO move to trait
|
||||
# TODO move to trait
|
||||
try {
|
||||
$photo = NULL;
|
||||
$video = NULL;
|
||||
|
|
|
@ -89,7 +89,7 @@ final class GroupPresenter extends OpenVKPresenter
|
|||
$this->template->club = $this->clubs->get($id);
|
||||
$this->template->onlyShowManagers = $this->queryParam("onlyAdmins") == "1";
|
||||
if($this->template->onlyShowManagers) {
|
||||
$this->template->followers = null;
|
||||
$this->template->followers = NULL;
|
||||
|
||||
$this->template->managers = $this->template->club->getManagers((int) ($this->queryParam("p") ?? 1), !$this->template->club->canBeModifiedBy($this->user->identity));
|
||||
if($this->template->club->canBeModifiedBy($this->user->identity) || !$this->template->club->isOwnerHidden()) {
|
||||
|
@ -99,7 +99,7 @@ final class GroupPresenter extends OpenVKPresenter
|
|||
$this->template->count = $this->template->club->getManagersCount();
|
||||
} else {
|
||||
$this->template->followers = $this->template->club->getFollowers((int) ($this->queryParam("p") ?? 1));
|
||||
$this->template->managers = null;
|
||||
$this->template->managers = NULL;
|
||||
$this->template->count = $this->template->club->getFollowersCount();
|
||||
}
|
||||
|
||||
|
@ -116,7 +116,7 @@ final class GroupPresenter extends OpenVKPresenter
|
|||
$user = is_null($this->queryParam("user")) ? $this->postParam("user") : $this->queryParam("user");
|
||||
$comment = $this->postParam("comment");
|
||||
$removeComment = $this->postParam("removeComment") === "1";
|
||||
$hidden = ["0" => false, "1" => true][$this->queryParam("hidden")] ?? null;
|
||||
$hidden = ["0" => false, "1" => true][$this->queryParam("hidden")] ?? NULL;
|
||||
//$index = $this->queryParam("index");
|
||||
if(!$user)
|
||||
$this->badRequest();
|
||||
|
|
|
@ -80,11 +80,11 @@ final class InternalAPIPresenter extends OpenVKPresenter
|
|||
if ($postTZ != $sessionOffset || $sessionOffset == null) {
|
||||
Session::i()->set("_timezoneOffset", $postTZ ? $postTZ : 3 * MINUTE );
|
||||
$this->returnJson([
|
||||
"success" => 1 // If it's new value
|
||||
"success" => 1 # If it's new value
|
||||
]);
|
||||
} else {
|
||||
$this->returnJson([
|
||||
"success" => 2 // If it's the same value (if for some reason server will call this func)
|
||||
"success" => 2 # If it's the same value (if for some reason server will call this func)
|
||||
]);
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -106,7 +106,7 @@ final class MessengerPresenter extends OpenVKPresenter
|
|||
|
||||
$messages = [];
|
||||
$correspondence = new Correspondence($this->user->identity, $correspondent);
|
||||
foreach($correspondence->getMessages(1, $lastMsg === 0 ? null : $lastMsg) as $message)
|
||||
foreach($correspondence->getMessages(1, $lastMsg === 0 ? NULL : $lastMsg) as $message)
|
||||
$messages[] = $message->simplify();
|
||||
|
||||
header("Content-Type: application/json");
|
||||
|
|
|
@ -118,7 +118,7 @@ abstract class OpenVKPresenter extends SimplePresenter
|
|||
return ($action === "register" || $action === "login");
|
||||
}
|
||||
|
||||
return (bool) $this->user->raw->can($action)->model($model)->whichBelongsTo($context === -1 ? null : $context);
|
||||
return (bool) $this->user->raw->can($action)->model($model)->whichBelongsTo($context === -1 ? NULL : $context);
|
||||
}
|
||||
|
||||
protected function assertPermission(string $model, string $action, int $context, bool $throw = false): void
|
||||
|
@ -252,7 +252,7 @@ abstract class OpenVKPresenter extends SimplePresenter
|
|||
exit;
|
||||
}
|
||||
|
||||
// ето для емейл уже надо (и по хорошему надо бы избавится от повторяющегося кода мда)
|
||||
# ето для емейл уже надо (и по хорошему надо бы избавится от повторяющегося кода мда)
|
||||
if(!$this->user->identity->isActivated() && !$this->activationTolerant) {
|
||||
header("HTTP/1.1 403 Forbidden");
|
||||
$this->getTemplatingEngine()->render(__DIR__ . "/templates/@email.xml", [
|
||||
|
@ -290,7 +290,7 @@ abstract class OpenVKPresenter extends SimplePresenter
|
|||
|
||||
$whichbrowser = new WhichBrowser\Parser(getallheaders());
|
||||
$mobiletheme = OPENVK_ROOT_CONF["openvk"]["preferences"]["defaultMobileTheme"];
|
||||
if($mobiletheme && $whichbrowser->isType('mobile') && Session::i()->get("_tempTheme") == null)
|
||||
if($mobiletheme && $whichbrowser->isType('mobile') && Session::i()->get("_tempTheme") == NULL)
|
||||
$this->setSessionTheme($mobiletheme);
|
||||
|
||||
$theme = NULL;
|
||||
|
@ -301,7 +301,7 @@ abstract class OpenVKPresenter extends SimplePresenter
|
|||
$theme = Themepacks::i()[Session::i()->get("_sessionTheme", "ovk")];
|
||||
} else if($this->requestParam("themePreview")) {
|
||||
$theme = Themepacks::i()[$this->requestParam("themePreview")];
|
||||
} else if($this->user->identity !== null && $this->user->identity->getTheme()) {
|
||||
} else if($this->user->identity !== NULL && $this->user->identity->getTheme()) {
|
||||
$theme = $this->user->identity->getTheme();
|
||||
}
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@ final class SearchPresenter extends OpenVKPresenter
|
|||
if($query != "")
|
||||
$this->assertUserLoggedIn();
|
||||
|
||||
// https://youtu.be/pSAWM5YuXx8
|
||||
# https://youtu.be/pSAWM5YuXx8
|
||||
|
||||
$repos = [ "groups" => "clubs", "users" => "users" ];
|
||||
$repo = $repos[$type] or $this->throwError(400, "Bad Request", "Invalid search entity $type.");
|
||||
|
|
|
@ -28,6 +28,41 @@ final class SupportPresenter extends OpenVKPresenter
|
|||
$this->assertUserLoggedIn();
|
||||
$this->template->mode = in_array($this->queryParam("act"), ["faq", "new", "list"]) ? $this->queryParam("act") : "faq";
|
||||
|
||||
if($this->template->mode === "faq") {
|
||||
$lang = Session::i()->get("lang", "ru");
|
||||
$base = OPENVK_ROOT . "/data/knowledgebase/faq";
|
||||
if(file_exists("$base.$lang.md"))
|
||||
$file = "$base.$lang.md";
|
||||
else if(file_exists("$base.md"))
|
||||
$file = "$base.md";
|
||||
else
|
||||
$file = NULL;
|
||||
|
||||
if(is_null($file)) {
|
||||
$this->template->faq = [];
|
||||
} else {
|
||||
$lines = file($file);
|
||||
$faq = [];
|
||||
$index = 0;
|
||||
|
||||
foreach($lines as $line) {
|
||||
if(strpos($line, "# ") === 0)
|
||||
++$index;
|
||||
|
||||
$faq[$index][] = $line;
|
||||
}
|
||||
|
||||
$this->template->faq = array_map(function($section) {
|
||||
$title = substr($section[0], 2);
|
||||
array_shift($section);
|
||||
return [
|
||||
$title,
|
||||
(new Parsedown())->text(implode("\n", $section))
|
||||
];
|
||||
}, $faq);
|
||||
}
|
||||
}
|
||||
|
||||
$this->template->count = $this->tickets->getTicketsCountByUserId($this->user->id);
|
||||
if($this->template->mode === "list") {
|
||||
$this->template->page = (int) ($this->queryParam("p") ?? 1);
|
||||
|
@ -79,12 +114,13 @@ final class SupportPresenter extends OpenVKPresenter
|
|||
$act = $this->queryParam("act") ?? "open";
|
||||
switch($act) {
|
||||
default:
|
||||
# NOTICE falling through
|
||||
case "open":
|
||||
$state = 0;
|
||||
break;
|
||||
break;
|
||||
case "answered":
|
||||
$state = 1;
|
||||
break;
|
||||
break;
|
||||
case "closed":
|
||||
$state = 2;
|
||||
}
|
||||
|
|
|
@ -91,7 +91,7 @@ final class TopicsPresenter extends OpenVKPresenter
|
|||
$topic->setFlags($flags);
|
||||
$topic->save();
|
||||
|
||||
// TODO move to trait
|
||||
# TODO move to trait
|
||||
try {
|
||||
$photo = NULL;
|
||||
$video = NULL;
|
||||
|
|
|
@ -9,12 +9,15 @@ use openvk\Web\Models\Repositories\Albums;
|
|||
use openvk\Web\Models\Repositories\Videos;
|
||||
use openvk\Web\Models\Repositories\Notes;
|
||||
use openvk\Web\Models\Repositories\Vouchers;
|
||||
use openvk\Web\Models\Repositories\EmailChangeVerifications;
|
||||
use openvk\Web\Models\Exceptions\InvalidUserNameException;
|
||||
use openvk\Web\Util\Validator;
|
||||
use openvk\Web\Models\Entities\Notifications\{CoinsTransferNotification, RatingUpNotification};
|
||||
use openvk\Web\Models\Entities\EmailChangeVerification;
|
||||
use Chandler\Security\Authenticator;
|
||||
use lfkeitel\phptotp\{Base32, Totp};
|
||||
use chillerlan\QRCode\{QRCode, QROptions};
|
||||
use Nette\Database\UniqueConstraintViolationException;
|
||||
|
||||
final class UserPresenter extends OpenVKPresenter
|
||||
{
|
||||
|
@ -132,7 +135,7 @@ final class UserPresenter extends OpenVKPresenter
|
|||
|
||||
if(!$id)
|
||||
$this->notFound();
|
||||
|
||||
|
||||
$user = $this->users->get($id);
|
||||
if($_SERVER["REQUEST_METHOD"] === "POST") {
|
||||
$this->willExecuteWriteAction($_GET['act'] === "status");
|
||||
|
@ -300,7 +303,7 @@ final class UserPresenter extends OpenVKPresenter
|
|||
|
||||
if(!$id)
|
||||
$this->notFound();
|
||||
|
||||
|
||||
if(in_array($this->queryParam("act"), ["finance", "finance.top-up"]) && !OPENVK_ROOT_CONF["openvk"]["preferences"]["commerce"])
|
||||
$this->flashFail("err", tr("error"), tr("feature_disabled"));
|
||||
|
||||
|
@ -312,7 +315,7 @@ final class UserPresenter extends OpenVKPresenter
|
|||
if($this->postParam("old_pass") && $this->postParam("new_pass") && $this->postParam("repeat_pass")) {
|
||||
if($this->postParam("new_pass") === $this->postParam("repeat_pass")) {
|
||||
if($this->user->identity->is2faEnabled()) {
|
||||
$code = $this->postParam("code");
|
||||
$code = $this->postParam("password_change_code");
|
||||
if(!($code === (new Totp)->GenerateToken(Base32::decode($this->user->identity->get2faSecret())) || $this->user->identity->use2faBackupCode((int) $code)))
|
||||
$this->flashFail("err", tr("error"), tr("incorrect_2fa_code"));
|
||||
}
|
||||
|
@ -323,6 +326,46 @@ final class UserPresenter extends OpenVKPresenter
|
|||
$this->flashFail("err", tr("error"), tr("error_new_password"));
|
||||
}
|
||||
}
|
||||
|
||||
if($this->postParam("new_email")) {
|
||||
if(!Validator::i()->emailValid($this->postParam("new_email")))
|
||||
$this->flashFail("err", tr("invalid_email_address"), tr("invalid_email_address_comment"));
|
||||
|
||||
if(!Authenticator::verifyHash($this->postParam("email_change_pass"), $user->getChandlerUser()->getRaw()->passwordHash))
|
||||
$this->flashFail("err", tr("error"), tr("incorrect_password"));
|
||||
|
||||
if($user->is2faEnabled()) {
|
||||
$code = $this->postParam("email_change_code");
|
||||
if(!($code === (new Totp)->GenerateToken(Base32::decode($user->get2faSecret())) || $user->use2faBackupCode((int) $code)))
|
||||
$this->flashFail("err", tr("error"), tr("incorrect_2fa_code"));
|
||||
}
|
||||
|
||||
if($this->postParam("new_email") !== $user->getEmail()) {
|
||||
if (OPENVK_ROOT_CONF['openvk']['preferences']['security']['requireEmail']) {
|
||||
$request = (new EmailChangeVerifications)->getLatestByUser($user);
|
||||
if(!is_null($request) && $request->isNew())
|
||||
$this->flashFail("err", tr("forbidden"), tr("email_rate_limit_error"));
|
||||
|
||||
$verification = new EmailChangeVerification;
|
||||
$verification->setProfile($user->getId());
|
||||
$verification->setNew_Email($this->postParam("new_email"));
|
||||
$verification->save();
|
||||
|
||||
$params = [
|
||||
"key" => $verification->getKey(),
|
||||
"name" => $user->getCanonicalName(),
|
||||
];
|
||||
$this->sendmail($this->postParam("new_email"), "change-email", $params); #Vulnerability possible
|
||||
$this->flashFail("succ", tr("information_-1"), tr("email_change_confirm_message"));
|
||||
}
|
||||
|
||||
try {
|
||||
$user->changeEmail($this->postParam("new_email"));
|
||||
} catch(UniqueConstraintViolationException $ex) {
|
||||
$this->flashFail("err", tr("error"), tr("user_already_exists"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!$user->setShortCode(empty($this->postParam("sc")) ? NULL : $this->postParam("sc")))
|
||||
$this->flashFail("err", tr("error"), tr("error_shorturl_incorrect"));
|
||||
|
@ -376,6 +419,9 @@ final class UserPresenter extends OpenVKPresenter
|
|||
|
||||
if(in_array($this->postParam("nsfw"), [0, 1, 2]))
|
||||
$user->setNsfwTolerance((int) $this->postParam("nsfw"));
|
||||
|
||||
if(in_array($this->postParam("main_page"), [0, 1]))
|
||||
$user->setMain_Page((int) $this->postParam("main_page"));
|
||||
} else if($_GET['act'] === "lMenu") {
|
||||
$settings = [
|
||||
"menu_bildoj" => "photos",
|
||||
|
@ -400,11 +446,7 @@ final class UserPresenter extends OpenVKPresenter
|
|||
throw $ex;
|
||||
}
|
||||
|
||||
$this->flash(
|
||||
"succ",
|
||||
"Изменения сохранены",
|
||||
"Новые данные появятся на вашей странице."
|
||||
);
|
||||
$this->flash("succ", tr("changes_saved"), tr("changes_saved_comment"));
|
||||
}
|
||||
$this->template->mode = in_array($this->queryParam("act"), [
|
||||
"main", "privacy", "finance", "finance.top-up", "interface"
|
||||
|
@ -456,7 +498,7 @@ final class UserPresenter extends OpenVKPresenter
|
|||
$this->template->secret = $secret;
|
||||
}
|
||||
|
||||
// Why are these crutch? For some reason, the QR code is not displayed if you just pass the render output to the view
|
||||
# Why are these crutch? For some reason, the QR code is not displayed if you just pass the render output to the view
|
||||
|
||||
$issuer = OPENVK_ROOT_CONF["openvk"]["appearance"]["name"];
|
||||
$email = $this->user->identity->getEmail();
|
||||
|
@ -502,6 +544,9 @@ final class UserPresenter extends OpenVKPresenter
|
|||
$this->assertUserLoggedIn();
|
||||
$this->willExecuteWriteAction();
|
||||
|
||||
if(!OPENVK_ROOT_CONF["openvk"]["preferences"]["commerce"])
|
||||
$this->flashFail("err", tr("error"), tr("feature_disabled"));
|
||||
|
||||
$receiverAddress = $this->postParam("receiver");
|
||||
$value = (int) $this->postParam("value");
|
||||
$message = $this->postParam("message");
|
||||
|
@ -517,7 +562,7 @@ final class UserPresenter extends OpenVKPresenter
|
|||
|
||||
$receiver = $this->users->getByAddress($receiverAddress);
|
||||
if(!$receiver)
|
||||
$this->flashFail("err", tr("failed_to_tranfer_points"), tr("receiver_not_found"));
|
||||
$this->flashFail("err", tr("failed_to_tranfer_points"), tr("receiver_not_found"));
|
||||
|
||||
if($this->user->identity->getCoins() < $value)
|
||||
$this->flashFail("err", tr("failed_to_tranfer_points"), tr("you_dont_have_enough_points"));
|
||||
|
@ -574,4 +619,24 @@ final class UserPresenter extends OpenVKPresenter
|
|||
|
||||
$this->flashFail("succ", tr("information_-1"), tr("rating_increase_successful", $receiver->getURL(), htmlentities($receiver->getCanonicalName()), $value));
|
||||
}
|
||||
|
||||
function renderEmailChangeFinish(): void
|
||||
{
|
||||
$request = (new EmailChangeVerifications)->getByToken(str_replace(" ", "+", $this->queryParam("key")));
|
||||
if(!$request || !$request->isStillValid()) {
|
||||
$this->flash("err", tr("token_manipulation_error"), tr("token_manipulation_error_comment"));
|
||||
$this->redirect("/settings");
|
||||
} else {
|
||||
$request->delete(false);
|
||||
|
||||
try {
|
||||
$request->getUser()->changeEmail($request->getNewEmail());
|
||||
} catch(UniqueConstraintViolationException $ex) {
|
||||
$this->flashFail("err", tr("error"), tr("user_already_exists"));
|
||||
}
|
||||
|
||||
$this->flash("succ", tr("changes_saved"), tr("changes_saved_comment"));
|
||||
$this->redirect("/settings");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -414,7 +414,7 @@ final class WallPresenter extends OpenVKPresenter
|
|||
$post->unpin();
|
||||
}
|
||||
|
||||
// TODO localize message based on language and ?act=(un)pin
|
||||
# TODO localize message based on language and ?act=(un)pin
|
||||
$this->flashFail("succ", tr("information_-1"), tr("changes_saved_comment"));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
{script "js/l10n.js"}
|
||||
{script "js/openvk.cls.js"}
|
||||
|
||||
{if $isTimezoned == null}
|
||||
{if $isTimezoned == NULL}
|
||||
{script "js/timezone.js"}
|
||||
{/if}
|
||||
|
||||
|
@ -26,7 +26,7 @@
|
|||
{css "css/nsfw-posts.css"}
|
||||
{/if}
|
||||
|
||||
{if $theme !== null}
|
||||
{if $theme !== NULL}
|
||||
{if $theme->inheritDefault()}
|
||||
{css "css/style.css"}
|
||||
{css "css/dialog.css"}
|
||||
|
@ -103,7 +103,7 @@
|
|||
<div n:if="isset($thisUser) ? (!$thisUser->isBanned() XOR !$thisUser->isActivated()) : true" class="header_navigation">
|
||||
{ifset $thisUser}
|
||||
<div class="link">
|
||||
<a href="/" title="[Alt+Shift+,]" accesskey=",">{_header_home}</a>
|
||||
<a href="/">{_header_home}</a>
|
||||
</div>
|
||||
<div class="link">
|
||||
<a href="/search?type=groups">{_header_groups}</a>
|
||||
|
@ -161,7 +161,7 @@
|
|||
</a>
|
||||
<a n:if="$thisUser->getLeftMenuItemStatus('notes')" href="/notes{$thisUser->getId()}" class="link">{_my_notes}</a>
|
||||
<a n:if="$thisUser->getLeftMenuItemStatus('groups')" href="/groups{$thisUser->getId()}" class="link">{_my_groups}</a>
|
||||
<a n:if="$thisUser->getLeftMenuItemStatus('news')" href="/feed" class="link" title="{_my_feed} [Alt+Shift+W]" accesskey="w">{_my_feed}</a>
|
||||
<a n:if="$thisUser->getLeftMenuItemStatus('news')" href="/feed" class="link" title="{_my_feed} [Alt+Shift+,]" accesskey=",">{_my_feed}</a>
|
||||
<a href="/notifications" class="link" title="{_my_feedback} [Alt+Shift+N]" accesskey="n">{_my_feedback}
|
||||
{if $thisUser->getNotificationsCount() > 0}
|
||||
(<b>{$thisUser->getNotificationsCount()}</b>)
|
||||
|
@ -173,7 +173,7 @@
|
|||
{var $canAccessHelpdesk = $thisUser->getChandlerUser()->can("write")->model('openvk\Web\Models\Entities\TicketReply')->whichBelongsTo(0)}
|
||||
{var $menuLinksAvaiable = sizeof(OPENVK_ROOT_CONF['openvk']['preferences']['menu']['links']) > 0 && $thisUser->getLeftMenuItemStatus('links')}
|
||||
<div n:if="$canAccessAdminPanel || $canAccessHelpdesk || $menuLinksAvaiable" class="menu_divider"></div>
|
||||
<a href="/admin" class="link" n:if="$canAccessAdminPanel" title="Админ-панель [Alt+Shift+A]" accesskey="a">Админ-панель</a>
|
||||
<a href="/admin" class="link" n:if="$canAccessAdminPanel" title="{_admin} [Alt+Shift+A]" accesskey="a">{_admin}</a>
|
||||
<a href="/support/tickets" class="link" n:if="$canAccessHelpdesk">Helpdesk
|
||||
{if $helpdeskTicketNotAnsweredCount > 0}
|
||||
(<b>{$helpdeskTicketNotAnsweredCount}</b>)
|
||||
|
@ -280,6 +280,8 @@
|
|||
</p>
|
||||
</div>
|
||||
|
||||
{include "components/cookies.xml"}
|
||||
|
||||
{script "js/node_modules/msgpack-lite/dist/msgpack.min.js"}
|
||||
{script "js/node_modules/soundjs/lib/soundjs.min.js"}
|
||||
{script "js/node_modules/ky/umd.js"}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
{var $instance_name = OPENVK_ROOT_CONF['openvk']['appearance']['name']}
|
||||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
|
||||
<head>
|
||||
|
@ -6,7 +7,7 @@
|
|||
{var $css = file_get_contents(OPENVK_ROOT . "/Web/static/js/node_modules/@atlassian/aui/dist/aui/aui-prototyping.css")}
|
||||
{str_replace("fonts/", "/assets/packages/static/openvk/js/node_modules/@atlassian/aui/dist/aui/fonts/", $css)|noescape}
|
||||
</style>
|
||||
<title>{include title} - Админ-панель {=OPENVK_ROOT_CONF['openvk']['appearance']['name']}</title>
|
||||
<title>{include title} - {_admin} {$instance_name}</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="page">
|
||||
|
@ -16,23 +17,15 @@
|
|||
<div class="aui-header-primary">
|
||||
<h1 id="logo" class="aui-header-logo aui-header-logo-textonly">
|
||||
<a href="/admin">
|
||||
<span class="aui-header-logo-device">{=OPENVK_ROOT_CONF['openvk']['appearance']['name']}</span>
|
||||
<span class="aui-header-logo-device">{$instance_name}</span>
|
||||
</a>
|
||||
</h1>
|
||||
</div>
|
||||
<div n:if="$search ?? false" class="aui-header-secondary">
|
||||
<ul class="aui-nav">
|
||||
<form class="aui-quicksearch dont-default-focus ajs-dirty-warning-exempt">
|
||||
<input
|
||||
id="quickSearchInput"
|
||||
autocomplete="off"
|
||||
class="search"
|
||||
type="text"
|
||||
placeholder="{include searchTitle}"
|
||||
value="{$_GET['q'] ?? ''}"
|
||||
name="q"
|
||||
accesskey="Q" />
|
||||
<input type="hidden" value=1 name=p />
|
||||
<input id="quickSearchInput" autocomplete="off" class="search" type="text" placeholder="{include searchTitle}" value="{$_GET['q'] ?? ''}" name="q" accesskey="Q" />
|
||||
<input type="hidden" value=1 name=p />
|
||||
</form>
|
||||
</ul>
|
||||
</div>
|
||||
|
@ -46,83 +39,64 @@
|
|||
<div class="aui-navgroup-inner">
|
||||
<div class="aui-navgroup-primary">
|
||||
<div class="aui-nav-heading">
|
||||
<strong>Обзор</strong>
|
||||
<strong>{_admin_overview}</strong>
|
||||
</div>
|
||||
<ul class="aui-nav">
|
||||
<li>
|
||||
<a href="/admin">
|
||||
Сводка
|
||||
</a>
|
||||
<a href="/admin">{_admin_overview_summary}</a>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="aui-nav-heading">
|
||||
<strong>Пользовательский контент</strong>
|
||||
<strong>{_admin_content}</strong>
|
||||
</div>
|
||||
<ul class="aui-nav">
|
||||
<li>
|
||||
<a href="/admin/users">
|
||||
Пользователи
|
||||
</a>
|
||||
<a href="/admin/users">{_users}</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/admin/clubs">
|
||||
Группы
|
||||
</a>
|
||||
<a href="/admin/clubs">{_groups}</a>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="aui-nav-heading">
|
||||
<strong>Платные услуги</strong>
|
||||
<strong>{_admin_services}</strong>
|
||||
</div>
|
||||
<ul class="aui-nav">
|
||||
<li>
|
||||
<a href="/admin/vouchers">
|
||||
{_vouchers}
|
||||
</a>
|
||||
<a href="/admin/vouchers">{_vouchers}</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/admin/gifts">
|
||||
Подарки
|
||||
</a>
|
||||
<a href="/admin/gifts">{_gifts}</a>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="aui-nav-heading">
|
||||
<strong>Настройки</strong>
|
||||
<strong>{_admin_settings}</strong>
|
||||
</div>
|
||||
<ul class="aui-nav">
|
||||
<li>
|
||||
<a href="/admin/settings/tuning">
|
||||
Общие
|
||||
</a>
|
||||
<a href="/admin/settings/tuning">{_admin_settings_tuning}</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/admin/settings/appearance">
|
||||
Внешний вид
|
||||
</a>
|
||||
<a href="/admin/settings/appearance">{_admin_settings_appearance}</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/admin/settings/security">
|
||||
Безопасность
|
||||
</a>
|
||||
<a href="/admin/settings/security">{_admin_settings_security}</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/admin/settings/integrations">
|
||||
Интеграции
|
||||
</a>
|
||||
<a href="/admin/settings/integrations">{_admin_settings_integrations}</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/admin/settings/system">
|
||||
Система
|
||||
</a>
|
||||
<a href="/admin/settings/system">{_admin_settings_system}</a>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="aui-nav-heading">
|
||||
<strong>Об OpenVK</strong>
|
||||
<strong>{_admin_about}</strong>
|
||||
</div>
|
||||
<ul class="aui-nav">
|
||||
<li>
|
||||
<a href="/about:openvk">
|
||||
Версия
|
||||
</a>
|
||||
<a href="/about:openvk">{_admin_about_version}</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/about">{_admin_about_instance}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
@ -139,11 +113,11 @@
|
|||
<p>{$flashMessage->msg|noescape}</p>
|
||||
</div>
|
||||
{/ifset}
|
||||
|
||||
|
||||
{ifset preHeader}
|
||||
{include preHeader}
|
||||
{/ifset}
|
||||
|
||||
|
||||
<header class="aui-page-header">
|
||||
<div class="aui-page-header-inner">
|
||||
<div class="aui-page-header-main">
|
||||
|
@ -167,11 +141,11 @@
|
|||
</section>
|
||||
</footer>
|
||||
</div>
|
||||
|
||||
|
||||
{script "js/node_modules/jquery/dist/jquery.min.js"}
|
||||
{script "js/node_modules/@atlassian/aui/dist/aui/aui-prototyping.js"}
|
||||
<script>AJS.tabs.setup();</script>
|
||||
|
||||
|
||||
{ifset scripts}
|
||||
{include scripts}
|
||||
{/ifset}
|
||||
|
|
|
@ -1,191 +1,157 @@
|
|||
{extends "@layout.xml"}
|
||||
|
||||
{block title}
|
||||
Редактировать {$club->getCanonicalName()}
|
||||
{_edit} {$club->getCanonicalName()}
|
||||
{/block}
|
||||
|
||||
{block heading}
|
||||
{$club->getCanonicalName()}
|
||||
{/block}
|
||||
|
||||
|
||||
{block content}
|
||||
|
||||
{var $isMain = $mode === 'main'}
|
||||
{var $isBan = $mode === 'ban'}
|
||||
{var $isFollowers = $mode === 'followers'}
|
||||
{var $isMain = $mode === 'main'}
|
||||
{var $isBan = $mode === 'ban'}
|
||||
{var $isFollowers = $mode === 'followers'}
|
||||
|
||||
{if $isMain}
|
||||
|
||||
<!-- This main block -->
|
||||
|
||||
<div class="aui-tabs horizontal-tabs">
|
||||
<nav class="aui-navgroup aui-navgroup-horizontal">
|
||||
<div class="aui-navgroup-inner">
|
||||
<div class="aui-navgroup-primary">
|
||||
<ul class="aui-nav">
|
||||
<li class="aui-nav-selected"><a href="?act=main">Главное</a></li>
|
||||
<li><a href="?act=ban">Бан</a></li>
|
||||
<li><a href="?act=followers">Участники</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
<form class="aui" method="POST">
|
||||
<div class="field-group">
|
||||
<label for="avatar">
|
||||
Аватарка
|
||||
</label>
|
||||
<span id="avatar" class="aui-avatar aui-avatar-project aui-avatar-xlarge">
|
||||
<span class="aui-avatar-inner">
|
||||
<img src="{$club->getAvatarUrl('tiny')}" style="object-fit: cover;"></img>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="field-group">
|
||||
<label for="id">
|
||||
ID
|
||||
</label>
|
||||
<input class="text medium-field" type="number" id="id" disabled value="{$club->getId()}" />
|
||||
</div>
|
||||
<div class="field-group">
|
||||
<label for="id_owner">
|
||||
ID владельца
|
||||
</label>
|
||||
<input class="text medium-field" type="text" id="id_owner" name="id_owner" value="{$club->getOwner()->getId()}" />
|
||||
</div>
|
||||
<div class="field-group">
|
||||
<label for="name">
|
||||
Название
|
||||
</label>
|
||||
<input class="text medium-field" type="text" id="name" name="name" value="{$club->getName()}" />
|
||||
</div>
|
||||
<div class="field-group">
|
||||
<label for="about">
|
||||
Описание
|
||||
</label>
|
||||
<input class="text medium-field" type="text" id="about" name="about" value="{$club->getDescription()}" />
|
||||
</div>
|
||||
<div class="field-group">
|
||||
<label for="shortcode">
|
||||
Адрес
|
||||
</label>
|
||||
<input class="text medium-field" type="text" id="shortcode" name="shortcode" value="{$club->getShortCode()}" />
|
||||
</div>
|
||||
<br/>
|
||||
<div class="group">
|
||||
<input class="toggle-large" type="checkbox" id="verify" name="verify" value="1" {if $club->isVerified()} checked {/if} />
|
||||
<label for="verify">
|
||||
Верификация
|
||||
</label>
|
||||
</div>
|
||||
<div class="group">
|
||||
<input class="toggle-large" type="checkbox" id="hide_from_global_feed" name="hide_from_global_feed" value="1" {if $club->isHideFromGlobalFeedEnabled()} checked {/if} />
|
||||
<label for="hide_from_global_feed">
|
||||
Не отображать записи в глобальной ленте
|
||||
</label>
|
||||
</div>
|
||||
<hr/>
|
||||
<div class="buttons-container">
|
||||
<div class="buttons">
|
||||
<input type="hidden" name="hash" value="{$csrfToken}" />
|
||||
<input class="button submit" type="submit" value="Сохранить">
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{if $isBan}
|
||||
|
||||
<!-- This ban block -->
|
||||
|
||||
<div class="aui-tabs horizontal-tabs">
|
||||
<nav class="aui-navgroup aui-navgroup-horizontal">
|
||||
<div class="aui-navgroup-inner">
|
||||
<div class="aui-navgroup-primary">
|
||||
<ul class="aui-nav">
|
||||
<li><a href="?act=main">Главное</a></li>
|
||||
<li class="aui-nav-selected"><a href="?act=ban">Бан</a></li>
|
||||
<li><a href="?act=followers">Участники</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
<form class="aui" method="POST">
|
||||
<div class="field-group">
|
||||
<label for="ban_reason">
|
||||
Причина бана
|
||||
</label>
|
||||
<input class="text" type="text" id="text-input" name="ban_reason" value="{$club->getBanReason()}" />
|
||||
</div>
|
||||
<hr/>
|
||||
<div class="buttons-container">
|
||||
<div class="buttons">
|
||||
<input type="hidden" name="hash" value="{$csrfToken}" />
|
||||
<input class="button submit" type="submit" value="Сохранить">
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{if $isFollowers}
|
||||
|
||||
<!-- This followers block -->
|
||||
|
||||
{var $followers = iterator_to_array($followers)}
|
||||
|
||||
<div class="aui-tabs horizontal-tabs">
|
||||
<nav class="aui-navgroup aui-navgroup-horizontal">
|
||||
<div class="aui-navgroup-inner">
|
||||
<div class="aui-navgroup-primary">
|
||||
<ul class="aui-nav">
|
||||
<li><a href="?act=main">Главное</a></li>
|
||||
<li><a href="?act=ban">Бан</a></li>
|
||||
<li class="aui-nav-selected"><a href="?act=followers">Участники</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
<table rules="none" class="aui aui-table-list">
|
||||
<tbody>
|
||||
<tr n:foreach="$followers as $follower">
|
||||
<td>{$follower->getId()}</td>
|
||||
<td>
|
||||
<span class="aui-avatar aui-avatar-xsmall">
|
||||
{if $isMain}
|
||||
<div class="aui-tabs horizontal-tabs">
|
||||
<nav class="aui-navgroup aui-navgroup-horizontal">
|
||||
<div class="aui-navgroup-inner">
|
||||
<div class="aui-navgroup-primary">
|
||||
<ul class="aui-nav">
|
||||
<li class="aui-nav-selected"><a href="?act=main">{_admin_tab_main}</a></li>
|
||||
<li><a href="?act=ban">{_admin_tab_ban}</a></li>
|
||||
<li><a href="?act=followers">{_admin_tab_followers}</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
<form class="aui" method="POST">
|
||||
<div class="field-group">
|
||||
<label for="avatar">{_avatar}</label>
|
||||
<span id="avatar" class="aui-avatar aui-avatar-project aui-avatar-xlarge">
|
||||
<span class="aui-avatar-inner">
|
||||
<img src="{$follower->getAvatarUrl('miniscule')}" alt="{$follower->getCanonicalName()}" role="presentation" />
|
||||
<img src="{$club->getAvatarUrl('tiny')}" style="object-fit: cover;"></img>
|
||||
</span>
|
||||
</span>
|
||||
|
||||
<a href="{$follower->getURL()}">{$follower->getCanonicalName()}</a>
|
||||
|
||||
<span n:if="$follower->isBanned()" class="aui-lozenge aui-lozenge-subtle aui-lozenge-removed">
|
||||
заблокирован
|
||||
</span>
|
||||
</td>
|
||||
<td>{$follower->isFemale() ? "Женский" : "Мужской"}</td>
|
||||
<td>{$follower->getShortCode() ?? "(отсутствует)"}</td>
|
||||
<td>{$follower->getRegistrationTime()}</td>
|
||||
<td>
|
||||
<a class="aui-button aui-button-primary" href="/admin/users/id{$follower->getId()}">
|
||||
<span class="aui-icon aui-icon-small aui-iconfont-new-edit">Редактировать</span>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div align="right">
|
||||
{var $isLast = ((20 * (($_GET['p'] ?? 1) - 1)) + $amount) < $count}
|
||||
|
||||
<a n:if="($_GET['p'] ?? 1) > 1" class="aui-button" href="?p={($_GET['p'] ?? 1) - 1}">
|
||||
⭁ туда
|
||||
</a>
|
||||
<a n:if="$isLast" class="aui-button" href="?p={($_GET['p'] ?? 1) + 1}">
|
||||
⭇ сюда
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
<div class="field-group">
|
||||
<label for="id">ID</label>
|
||||
<input class="text medium-field" type="number" id="id" disabled value="{$club->getId()}" />
|
||||
</div>
|
||||
<div class="field-group">
|
||||
<label for="id_owner">{_admin_ownerid}</label>
|
||||
<input class="text medium-field" type="text" id="id_owner" name="id_owner" value="{$club->getOwner()->getId()}" />
|
||||
</div>
|
||||
<div class="field-group">
|
||||
<label for="name">{_admin_title}</label>
|
||||
<input class="text medium-field" type="text" id="name" name="name" value="{$club->getName()}" />
|
||||
</div>
|
||||
<div class="field-group">
|
||||
<label for="about">{_admin_description}</label>
|
||||
<input class="text medium-field" type="text" id="about" name="about" value="{$club->getDescription()}" />
|
||||
</div>
|
||||
<div class="field-group">
|
||||
<label for="shortcode">{_admin_shortcode}</label>
|
||||
<input class="text medium-field" type="text" id="shortcode" name="shortcode" value="{$club->getShortCode()}" />
|
||||
</div>
|
||||
<br/>
|
||||
<div class="group">
|
||||
<input class="toggle-large" type="checkbox" id="verify" name="verify" value="1" {if $club->isVerified()} checked {/if} />
|
||||
<label for="verify">{_admin_verification}</label>
|
||||
</div>
|
||||
<div class="group">
|
||||
<input class="toggle-large" type="checkbox" id="hide_from_global_feed" name="hide_from_global_feed" value="1" {if $club->isHideFromGlobalFeedEnabled()} checked {/if} />
|
||||
<label for="hide_from_global_feed">{_admin_club_excludeglobalfeed}</label>
|
||||
</div>
|
||||
<hr/>
|
||||
<div class="buttons-container">
|
||||
<div class="buttons">
|
||||
<input type="hidden" name="hash" value="{$csrfToken}" />
|
||||
<input class="button submit" type="submit" value="{_save}">
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{if $isBan}
|
||||
<div class="aui-tabs horizontal-tabs">
|
||||
<nav class="aui-navgroup aui-navgroup-horizontal">
|
||||
<div class="aui-navgroup-inner">
|
||||
<div class="aui-navgroup-primary">
|
||||
<ul class="aui-nav">
|
||||
<li><a href="?act=main">{_admin_tab_main}</a></li>
|
||||
<li class="aui-nav-selected"><a href="?act=ban">{_admin_tab_ban}</a></li>
|
||||
<li><a href="?act=followers">{_admin_tab_followers}</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
<form class="aui" method="POST">
|
||||
<div class="field-group">
|
||||
<label for="ban_reason">{_admin_banreason}</label>
|
||||
<input class="text" type="text" id="text-input" name="ban_reason" value="{$club->getBanReason()}" />
|
||||
</div>
|
||||
<hr/>
|
||||
<div class="buttons-container">
|
||||
<div class="buttons">
|
||||
<input type="hidden" name="hash" value="{$csrfToken}" />
|
||||
<input class="button submit" type="submit" value="{_save}">
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{if $isFollowers}
|
||||
{var $followers = iterator_to_array($followers)}
|
||||
|
||||
<div class="aui-tabs horizontal-tabs">
|
||||
<nav class="aui-navgroup aui-navgroup-horizontal">
|
||||
<div class="aui-navgroup-inner">
|
||||
<div class="aui-navgroup-primary">
|
||||
<ul class="aui-nav">
|
||||
<li><a href="?act=main">{_admin_tab_main}</a></li>
|
||||
<li><a href="?act=ban">{_admin_tab_ban}</a></li>
|
||||
<li class="aui-nav-selected"><a href="?act=followers">{_admin_tab_followers}</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
<table rules="none" class="aui aui-table-list">
|
||||
<tbody>
|
||||
<tr n:foreach="$followers as $follower">
|
||||
<td>{$follower->getId()}</td>
|
||||
<td>
|
||||
<span class="aui-avatar aui-avatar-xsmall">
|
||||
<span class="aui-avatar-inner">
|
||||
<img src="{$follower->getAvatarUrl()}" alt="{$follower->getCanonicalName()}" role="presentation" />
|
||||
</span>
|
||||
</span>
|
||||
|
||||
<a href="{$follower->getURL()}">{$follower->getCanonicalName()}</a>
|
||||
|
||||
<span n:if="$follower->isBanned()" class="aui-lozenge aui-lozenge-subtle aui-lozenge-removed">{_admin_banned}</span>
|
||||
</td>
|
||||
<td>{$follower->isFemale() ? tr("female") : tr("male")}</td>
|
||||
<td>{$follower->getShortCode() ?? "(" . tr("none") . ")"}</td>
|
||||
<td>{$follower->getRegistrationTime()}</td>
|
||||
<td>
|
||||
<a class="aui-button aui-button-primary" href="/admin/users/id{$follower->getId()}">
|
||||
<span class="aui-icon aui-icon-small aui-iconfont-new-edit">{_edit}</span>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div align="right">
|
||||
{var $isLast = ((20 * (($_GET['p'] ?? 1) - 1)) + $amount) < $count}
|
||||
|
||||
<a n:if="($_GET['p'] ?? 1) > 1" class="aui-button" href="?p={($_GET['p'] ?? 1) - 1}">«</a>
|
||||
<a n:if="$isLast" class="aui-button" href="?p={($_GET['p'] ?? 1) + 1}">»</a>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
{/block}
|
||||
|
|
|
@ -2,14 +2,16 @@
|
|||
{var $search = true}
|
||||
|
||||
{block title}
|
||||
Группы
|
||||
{_admin_club_search}
|
||||
{/block}
|
||||
|
||||
{block heading}
|
||||
Бутылки
|
||||
{_groups}
|
||||
{/block}
|
||||
|
||||
{block searchTitle}Поиск бутылок{/block}
|
||||
{block searchTitle}
|
||||
{include title}
|
||||
{/block}
|
||||
|
||||
{block content}
|
||||
{var $clubs = iterator_to_array($clubs)}
|
||||
|
@ -18,12 +20,12 @@
|
|||
<table class="aui aui-table-list">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>#</th>
|
||||
<th>Имя</th>
|
||||
<th>Автор</th>
|
||||
<th>Описание</th>
|
||||
<th>Короткий адрес</th>
|
||||
<th>Действия</th>
|
||||
<th>ID</th>
|
||||
<th>{_admin_title}</th>
|
||||
<th>{_admin_author}</th>
|
||||
<th>{_admin_description}</th>
|
||||
<th>{_admin_shortcode}</th>
|
||||
<th>{_admin_actions}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
@ -49,11 +51,11 @@
|
|||
|
||||
<a href="{$user->getURL()}">{$user->getCanonicalName()}</a>
|
||||
</td>
|
||||
<td>{$club->getDescription() ?? "(не указано)"}</td>
|
||||
<td>{$club->getDescription() ?? "(" . tr("none") . ")"}</td>
|
||||
<td>{$club->getShortCode()}</td>
|
||||
<td>
|
||||
<a class="aui-button aui-button-primary" href="/admin/clubs/id{$club->getId()}">
|
||||
<span class="aui-icon aui-icon-small aui-iconfont-new-edit">Редактировать</span>
|
||||
<span class="aui-icon aui-icon-small aui-iconfont-new-edit">{_edit}</span>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
|
@ -63,11 +65,7 @@
|
|||
<div align="right">
|
||||
{var $isLast = ((10 * (($_GET['p'] ?? 1) - 1)) + $amount) < $count}
|
||||
|
||||
<a n:if="($_GET['p'] ?? 1) > 1" class="aui-button" href="?p={($_GET['p'] ?? 1) - 1}">
|
||||
⭁ туда
|
||||
</a>
|
||||
<a n:if="$isLast" class="aui-button" href="?p={($_GET['p'] ?? 1) + 1}">
|
||||
⭇ сюда
|
||||
</a>
|
||||
<a n:if="($_GET['p'] ?? 1) > 1" class="aui-button" href="?p={($_GET['p'] ?? 1) - 1}">«</a>
|
||||
<a n:if="$isLast" class="aui-button" href="?p={($_GET['p'] ?? 1) + 1}">»</a>
|
||||
</div>
|
||||
{/block}
|
||||
|
|
|
@ -2,9 +2,9 @@
|
|||
|
||||
{block title}
|
||||
{if $form->id === 0}
|
||||
Новый подарок
|
||||
{_admin_newgift}
|
||||
{else}
|
||||
Подарок "{$form->name}"
|
||||
{_gift} "{$form->name}"
|
||||
{/if}
|
||||
{/block}
|
||||
|
||||
|
@ -16,7 +16,7 @@
|
|||
<form class="aui" method="POST" enctype="multipart/form-data">
|
||||
<div class="field-group">
|
||||
<label for="avatar">
|
||||
Изображение
|
||||
{_admin_image}
|
||||
<span n:if="$form->id === 0" class="aui-icon icon-required"></span>
|
||||
</label>
|
||||
{if $form->id === 0}
|
||||
|
@ -29,43 +29,39 @@
|
|||
</span>
|
||||
<input style="display: none;" id="picInput" type="file" name="pic" accept="image/jpeg,image/png,image/gif,image/webp" />
|
||||
<div class="description">
|
||||
<a id="picChange" href="javascript:false">Заменить изображение?</a>
|
||||
<a id="picChange" href="javascript:false">{_admin_image_replace}</a>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
|
||||
<div class="field-group">
|
||||
<label for="id">
|
||||
ID
|
||||
</label>
|
||||
<label for="id">ID</label>
|
||||
<input class="text long-field" type="number" id="id" disabled="disabled" value="{$form->id}" />
|
||||
</div>
|
||||
<div class="field-group">
|
||||
<label for="putin">
|
||||
Использований
|
||||
</label>
|
||||
<input class="text long-field" type="number" id="putin" disabled="disabled" value="{$form->usages}" />
|
||||
<label for="usages">{_admin_uses}</label>
|
||||
<input class="text long-field" type="number" id="usages" disabled="disabled" value="{$form->usages}" />
|
||||
<div n:if="$form->usages > 0" class="description">
|
||||
<a href="javascript:$('#putin').value(0);">Обнулить?</a>
|
||||
<a href="javascript:$('#usages').value(0);">{_admin_uses_reset}</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field-group">
|
||||
<label for="name">
|
||||
Внутренее имя
|
||||
{_admin_name}
|
||||
<span class="aui-icon icon-required"></span>
|
||||
</label>
|
||||
<input class="text long-field" type="text" id="name" name="name" value="{$form->name}" />
|
||||
</div>
|
||||
<div class="field-group">
|
||||
<label for="price">
|
||||
Цена
|
||||
{_admin_price}
|
||||
<span class="aui-icon icon-required"></span>
|
||||
</label>
|
||||
<input class="text long-field" type="number" id="price" name="price" min="0" value="{$form->price}" />
|
||||
</div>
|
||||
<div class="field-group">
|
||||
<label for="limit">
|
||||
Ограничение
|
||||
{_admin_limits}
|
||||
<span class="aui-icon icon-required"></span>
|
||||
</label>
|
||||
<input class="text long-field" type="number" min="-1" id="limit" name="limit" value="{$form->limit}" />
|
||||
|
@ -75,13 +71,13 @@
|
|||
<div class="checkbox" resolved="">
|
||||
<input n:attr="disabled => $form->id === 0, checked => $form->id === 0" class="checkbox" type="checkbox" name="reset_limit" id="reset_limit" />
|
||||
<span class="aui-form-glyph"></span>
|
||||
|
||||
<label for="reset_limit">Сбросить счётчик ограничений</label>
|
||||
|
||||
<label for="reset_limit">{_admin_limits_reset}</label>
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
|
||||
<input n:if="$form->id === 0" type="hidden" name="_cat" value="{$_GET['cat'] ?? 1}" />
|
||||
|
||||
|
||||
<div class="buttons-container">
|
||||
<div class="buttons">
|
||||
<input type="hidden" name="hash" value="{$csrfToken}" />
|
||||
|
@ -94,12 +90,12 @@
|
|||
{block scripts}
|
||||
<script>
|
||||
const TRANS_GIF = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7";
|
||||
|
||||
|
||||
$("#picChange").click(_ => $("#picInput").click());
|
||||
$("#picInput").bind("change", e => {
|
||||
if(typeof e.target.files[0] === "undefined")
|
||||
$("#pic").prop("src", URL.createObjectURL(TRANS_GIF));
|
||||
|
||||
|
||||
$("#pic").prop("src", URL.createObjectURL(e.target.files[0]));
|
||||
});
|
||||
</script>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{extends "@layout.xml"}
|
||||
|
||||
{block title}
|
||||
Наборы подарков
|
||||
{_admin_giftsets}
|
||||
{/block}
|
||||
|
||||
{block headingWrap}
|
||||
|
@ -9,7 +9,7 @@
|
|||
{_create}
|
||||
</a>
|
||||
|
||||
<h1>Наборы подарков</h1>
|
||||
<h1>{_admin_giftsets}</h1>
|
||||
{/block}
|
||||
|
||||
{block content}
|
||||
|
@ -27,12 +27,11 @@
|
|||
</td>
|
||||
<td style="vertical-align: middle; text-align: right;">
|
||||
<a class="aui-button aui-button-primary" href="/admin/gifts/{$cat->getSlug()}.{$cat->getId()}.meta">
|
||||
<span class="aui-icon aui-icon-small aui-iconfont-new-edit">Редактировать</span>
|
||||
<span class="aui-icon aui-icon-small aui-iconfont-new-edit">{_edit}</span>
|
||||
</a>
|
||||
|
||||
<a class="aui-button" href="/admin/gifts/{$cat->getSlug()}.{$cat->getId()}/">
|
||||
<span class="aui-icon aui-icon-small aui-iconfont-gallery">Открыть</span>
|
||||
Открыть
|
||||
<span class="aui-icon aui-icon-small aui-iconfont-gallery">{_admin_open}</span>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
|
@ -40,17 +39,13 @@
|
|||
</table>
|
||||
{else}
|
||||
<center>
|
||||
<p>Наборов подарков нету. Чтобы создать подарок, создайте набор.</p>
|
||||
<p>{_admin_giftsets_none}</p>
|
||||
</center>
|
||||
{/if}
|
||||
|
||||
<div align="right">
|
||||
{var $isLast = ((20 * (($_GET['p'] ?? 1) - 1)) + sizeof($categories)) < $count}
|
||||
<a n:if="($_GET['p'] ?? 1) > 1" class="aui-button" href="?act={$act}&p={($_GET['p'] ?? 1) - 1}">
|
||||
⭁ туда
|
||||
</a>
|
||||
<a n:if="$isLast" class="aui-button" href="?act={$act}&p={($_GET['p'] ?? 1) + 1}">
|
||||
⭇ сюда
|
||||
</a>
|
||||
<a n:if="($_GET['p'] ?? 1) > 1" class="aui-button" href="?act={$act}&p={($_GET['p'] ?? 1) - 1}">«</a>
|
||||
<a n:if="$isLast" class="aui-button" href="?act={$act}&p={($_GET['p'] ?? 1) + 1}">»</a>
|
||||
</div>
|
||||
{/block}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
{block title}
|
||||
{if $form->id === 0}
|
||||
Создать набор подарков
|
||||
{_admin_giftsets_create}
|
||||
{else}
|
||||
{$form->languages["master"]->name}
|
||||
{/if}
|
||||
|
@ -14,7 +14,7 @@
|
|||
|
||||
{block content}
|
||||
<form class="aui" method="POST">
|
||||
<h3>Общие настройки</h3>
|
||||
<h3>{_admin_commonsettings}</h3>
|
||||
<fieldset>
|
||||
<div class="field-group">
|
||||
<label for="id">
|
||||
|
@ -24,37 +24,37 @@
|
|||
</div>
|
||||
<div class="field-group">
|
||||
<label for="name_master">
|
||||
Наименование
|
||||
{_admin_name}
|
||||
<span class="aui-icon icon-required"></span>
|
||||
</label>
|
||||
<input class="text long-field" type="text" id="name_master" name="name_master" value="{$form->languages['master']->name}" />
|
||||
<div class="description">Внутреннее название набора, которое будет использоваться, если не удаётся найти название на языке пользователя.</div>
|
||||
<div class="description">{_admin_giftsets_title}</div>
|
||||
</div>
|
||||
<div class="field-group">
|
||||
<label for="description_master">
|
||||
Описание
|
||||
{_admin_description}
|
||||
<span class="aui-icon icon-required"></span>
|
||||
</label>
|
||||
<input class="text long-field" type="text" id="description_master" name="description_master" value="{$form->languages['master']->description}" />
|
||||
<div class="description">Внутреннее описание набора, которое будет использоваться, если не удаётся найти название на языке пользователя.</div>
|
||||
<div class="description">{_admin_giftsets_description}</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
<h3>Языко-зависимые настройки</h3>
|
||||
<h3>{_admin_langsettings}</h3>
|
||||
<fieldset>
|
||||
{foreach $form->languages as $locale => $data}
|
||||
{continueIf $locale === "master"}
|
||||
|
||||
<div class="field-group">
|
||||
<label for="name_{$locale}">
|
||||
Наименование
|
||||
{_admin_name}
|
||||
<img src="/assets/packages/static/openvk/img/flags/{$locale}.gif" alt="{$locale}" />
|
||||
</label>
|
||||
<input class="text long-field" type="text" id="name_{$locale}" name="name_{$locale}" value="{$data->name}" />
|
||||
</div>
|
||||
<div class="field-group">
|
||||
<label for="description_{$locale}">
|
||||
Описание
|
||||
{_admin_description}
|
||||
<img src="/assets/packages/static/openvk/img/flags/{$locale}.gif" alt="{$locale}" />
|
||||
</label>
|
||||
<input class="text long-field" type="text" id="description_{$locale}" name="description_{$locale}" value="{$data->description}" />
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
{_create}
|
||||
</a>
|
||||
|
||||
<h1>Набор "{$cat->getName()}"</h1>
|
||||
<h1>{_admin_giftset} "{$cat->getName()}"</h1>
|
||||
{/block}
|
||||
|
||||
{block content}
|
||||
|
@ -32,11 +32,11 @@
|
|||
<td style="vertical-align: middle;">
|
||||
{$gift->getName()}
|
||||
<span n:if="$gift->isFree()" class="aui-lozenge aui-lozenge-subtle aui-lozenge-success">
|
||||
бесплатный
|
||||
{_admin_price_free}
|
||||
</span>
|
||||
</td>
|
||||
<td style="vertical-align: middle;">
|
||||
{$gift->getPrice()} голосов
|
||||
{tr("points_amount", $gift->getPrice())}
|
||||
</td>
|
||||
<td style="vertical-align: middle;">
|
||||
{$gift->getUsages()} раз
|
||||
|
@ -72,11 +72,8 @@
|
|||
|
||||
<div align="right">
|
||||
{var $isLast = ((20 * (($_GET['p'] ?? 1) - 1)) + sizeof($gifts)) < $count}
|
||||
<a n:if="($_GET['p'] ?? 1) > 1" class="aui-button" href="?p={($_GET['p'] ?? 1) - 1}">
|
||||
⭁ туда
|
||||
</a>
|
||||
<a n:if="$isLast" class="aui-button" href="?p={($_GET['p'] ?? 1) + 1}">
|
||||
⭇ сюда
|
||||
</a>
|
||||
|
||||
<a n:if="($_GET['p'] ?? 1) > 1" class="aui-button" href="?p={($_GET['p'] ?? 1) - 1}">«</a>
|
||||
<a n:if="$isLast" class="aui-button" href="?p={($_GET['p'] ?? 1) + 1}">»</a>
|
||||
</div>
|
||||
{/block}
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
{extends "@layout.xml"}
|
||||
|
||||
{block title}
|
||||
Сводка
|
||||
{_admin_overview_summary}
|
||||
{/block}
|
||||
|
||||
{block heading}
|
||||
Сводка
|
||||
{_admin_overview_summary}
|
||||
{/block}
|
||||
|
||||
{block content}
|
||||
Да!
|
||||
┬─┬︵/(.□.)╯
|
||||
{/block}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{extends "@layout.xml"}
|
||||
|
||||
{block title}
|
||||
Редактировать {$user->getCanonicalName()}
|
||||
{_edit} {$user->getCanonicalName()}
|
||||
{/block}
|
||||
|
||||
{block heading}
|
||||
|
@ -10,95 +10,70 @@
|
|||
|
||||
{block content}
|
||||
<div class="aui-tabs horizontal-tabs">
|
||||
<form class="aui" method="POST">
|
||||
<div class="field-group">
|
||||
<label for="avatar">
|
||||
Аватарка
|
||||
</label>
|
||||
<span id="avatar" class="aui-avatar aui-avatar-project aui-avatar-xlarge">
|
||||
<span class="aui-avatar-inner">
|
||||
<img src="{$user->getAvatarUrl('tiny')}" style="object-fit: cover;"></img>
|
||||
<form class="aui" method="POST">
|
||||
<div class="field-group">
|
||||
<label for="avatar">{_avatar}</label>
|
||||
<span id="avatar" class="aui-avatar aui-avatar-project aui-avatar-xlarge">
|
||||
<span class="aui-avatar-inner">
|
||||
<img src="{$user->getAvatarUrl('tiny')}" style="object-fit: cover;"></img>
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="field-group">
|
||||
<label for="id">
|
||||
ID
|
||||
</label>
|
||||
<input class="text medium-field" type="number" id="id" disabled value="{$user->getId()}" />
|
||||
</div>
|
||||
<div class="field-group">
|
||||
<label for="guid">
|
||||
GUID
|
||||
</label>
|
||||
<input class="text medium-field" id="guid" disabled value="{$user->getChandlerUser()->getId()}" />
|
||||
</div>
|
||||
<div class="field-group">
|
||||
<label for="registration_ip">
|
||||
Первый IP
|
||||
</label>
|
||||
<input class="text medium-field" id="registration_ip" disabled value="{$user->getRegistrationIP()}" />
|
||||
</div>
|
||||
<div class="field-group">
|
||||
<label for="first_name">
|
||||
Имя
|
||||
</label>
|
||||
<input class="text medium-field" type="text" id="first_name" name="first_name" value="{$user->getFirstName()}" />
|
||||
</div>
|
||||
<div class="field-group">
|
||||
<label for="last_name">
|
||||
Фамилия
|
||||
</label>
|
||||
<input class="text medium-field" type="text" id="last_name" name="last_name" value="{$user->getLastName()}" />
|
||||
</div>
|
||||
<div class="field-group">
|
||||
<label for="nickname">
|
||||
Никнейм
|
||||
</label>
|
||||
<input class="text medium-field" type="text" id="nickname" name="nickname" value="{$user->getPseudo()}" />
|
||||
</div>
|
||||
<div class="field-group">
|
||||
<label for="status">
|
||||
Статус
|
||||
</label>
|
||||
<input class="text medium-field" type="text" id="status" name="status" value="{$user->getStatus()}" />
|
||||
</div>
|
||||
<div class="field-group">
|
||||
<label for="email">
|
||||
E-Mail
|
||||
</label>
|
||||
<input class="text medium-field" type="email" id="email" name="email" value="{$user->getEmail()}" />
|
||||
</div>
|
||||
<div class="field-group">
|
||||
<label for="shortcode">
|
||||
Адрес страницы
|
||||
</label>
|
||||
<input class="text medium-field" type="text" id="shortcode" name="shortcode" value="{$user->getShortCode()}" />
|
||||
</div>
|
||||
<hr>
|
||||
<div class="field-group">
|
||||
<label for="city">
|
||||
Верификация
|
||||
</label>
|
||||
<input class="toggle-large" type="checkbox" id="verify" name="verify" value="1" {if $user->isVerified()} checked {/if} />
|
||||
</div>
|
||||
<div class="field-group">
|
||||
<label for="city">
|
||||
Онлайн статус
|
||||
</label>
|
||||
<select name="online" class="select">
|
||||
<option value="0" {if $user->onlineStatus() > 2}selected{/if}>По-умолчанию</option>
|
||||
<option value="1" {if $user->onlineStatus() == 1}selected{/if}>Инкогнито</option>
|
||||
<option value="2" {if $user->onlineStatus() == 2}selected{/if}>Юзер умер</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="buttons-container">
|
||||
<div class="buttons">
|
||||
<input type="hidden" name="hash" value="{$csrfToken}" />
|
||||
<input class="button submit" type="submit" value="Сохранить">
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<div class="field-group">
|
||||
<label for="id">ID</label>
|
||||
<input class="text medium-field" type="number" id="id" disabled value="{$user->getId()}" />
|
||||
</div>
|
||||
<div class="field-group">
|
||||
<label for="guid">GUID</label>
|
||||
<input class="text medium-field" id="guid" disabled value="{$user->getChandlerUser()->getId()}" />
|
||||
</div>
|
||||
<div class="field-group">
|
||||
<label for="registration_ip">{_admin_first_known_ip}</label>
|
||||
<input class="text medium-field" id="guid" disabled value="{$user->getRegistrationIP()}" />
|
||||
</div>
|
||||
<div class="field-group">
|
||||
<label for="first_name">{_name}</label>
|
||||
<input class="text medium-field" type="text" id="first_name" name="first_name" value="{$user->getFirstName()}" />
|
||||
</div>
|
||||
<div class="field-group">
|
||||
<label for="last_name">{_surname}</label>
|
||||
<input class="text medium-field" type="text" id="last_name" name="last_name" value="{$user->getLastName()}" />
|
||||
</div>
|
||||
<div class="field-group">
|
||||
<label for="nickname">{_nickname}</label>
|
||||
<input class="text medium-field" type="text" id="nickname" name="nickname" value="{$user->getPseudo()}" />
|
||||
</div>
|
||||
<div class="field-group">
|
||||
<label for="status">{_status}</label>
|
||||
<input class="text medium-field" type="text" id="status" name="status" value="{$user->getStatus()}" />
|
||||
</div>
|
||||
<div class="field-group">
|
||||
<label for="email">E-Mail</label>
|
||||
<input class="text medium-field" type="email" id="email" name="email" value="{$user->getEmail()}" />
|
||||
</div>
|
||||
<div class="field-group">
|
||||
<label for="shortcode">{_admin_shortcode}</label>
|
||||
<input class="text medium-field" type="text" id="shortcode" name="shortcode" value="{$user->getShortCode()}" />
|
||||
</div>
|
||||
<hr>
|
||||
<div class="field-group">
|
||||
<label for="city">{_admin_verification}</label>
|
||||
<input class="toggle-large" type="checkbox" id="verify" name="verify" value="1" {if $user->isVerified()} checked {/if} />
|
||||
</div>
|
||||
<div class="field-group">
|
||||
<label for="city">{_admin_user_online}</label>
|
||||
<select name="online" class="select">
|
||||
<option value="0" {if $user->onlineStatus() > 2}selected{/if}>{_admin_user_online_default}</option>
|
||||
<option value="1" {if $user->onlineStatus() == 1}selected{/if}>{_admin_user_online_incognite}</option>
|
||||
<option value="2" {if $user->onlineStatus() == 2}selected{/if}>{_admin_user_online_deceased}</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="buttons-container">
|
||||
<div class="buttons">
|
||||
<input type="hidden" name="hash" value="{$csrfToken}" />
|
||||
<input class="button submit" type="submit" value="{_save}">
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
{/block}
|
||||
|
|
|
@ -2,14 +2,16 @@
|
|||
{var $search = true}
|
||||
|
||||
{block title}
|
||||
Пользователи
|
||||
{_admin_user_search}
|
||||
{/block}
|
||||
|
||||
{block heading}
|
||||
Пиздюки
|
||||
{_users}
|
||||
{/block}
|
||||
|
||||
{block searchTitle}Поиск пиздюков{/block}
|
||||
{block searchTitle}
|
||||
{include title}
|
||||
{/block}
|
||||
|
||||
{block content}
|
||||
{var $users = iterator_to_array($users)}
|
||||
|
@ -18,12 +20,12 @@
|
|||
<table class="aui aui-table-list">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>#</th>
|
||||
<th>Имя</th>
|
||||
<th>Пол</th>
|
||||
<th>Короткий адрес</th>
|
||||
<th>Дата регистрации</th>
|
||||
<th>Действия</th>
|
||||
<th>ID</th>
|
||||
<th>{_admin_name}</th>
|
||||
<th>{_gender}</th>
|
||||
<th>{_admin_shortcode}</th>
|
||||
<th>{_registration_date}</th>
|
||||
<th>{_admin_actions}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
@ -35,23 +37,21 @@
|
|||
<img src="{$user->getAvatarUrl('miniscule')}" alt="{$user->getCanonicalName()}" style="object-fit: cover;" role="presentation" />
|
||||
</span>
|
||||
</span>
|
||||
|
||||
|
||||
<a href="{$user->getURL()}">{$user->getCanonicalName()}</a>
|
||||
|
||||
<span n:if="$user->isBanned()" class="aui-lozenge aui-lozenge-subtle aui-lozenge-removed">
|
||||
заблокирован
|
||||
</span>
|
||||
|
||||
<span n:if="$user->isBanned()" class="aui-lozenge aui-lozenge-subtle aui-lozenge-removed">{_admin_banned}</span>
|
||||
</td>
|
||||
<td>{$user->isFemale() ? "Женский" : "Мужской"}</td>
|
||||
<td>{$user->getShortCode() ?? "(отсутствует)"}</td>
|
||||
<td>{$user->isFemale() ? tr("female") : tr("male")}</td>
|
||||
<td>{$user->getShortCode() ?? "(" . tr("none") . ")"}</td>
|
||||
<td>{$user->getRegistrationTime()}</td>
|
||||
<td>
|
||||
<a class="aui-button aui-button-primary" href="/admin/users/id{$user->getId()}">
|
||||
<span class="aui-icon aui-icon-small aui-iconfont-new-edit">Редактировать</span>
|
||||
<span class="aui-icon aui-icon-small aui-iconfont-new-edit">{_edit}</span>
|
||||
</a>
|
||||
{if $thisUser->getChandlerUser()->can("substitute")->model('openvk\Web\Models\Entities\User')->whichBelongsTo(0)}
|
||||
<a class="aui-button" href="/setSID/{$user->getChandlerUser()->getId()}?hash={rawurlencode($csrfToken)}">
|
||||
<span class="aui-icon aui-icon-small aui-iconfont-sign-in">Войти как</span>
|
||||
<span class="aui-icon aui-icon-small aui-iconfont-sign-in">{_admin_loginas}</span>
|
||||
</a>
|
||||
{/if}
|
||||
</td>
|
||||
|
@ -61,12 +61,8 @@
|
|||
<br/>
|
||||
<div align="right">
|
||||
{var $isLast = ((20 * (($_GET['p'] ?? 1) - 1)) + $amount) < $count}
|
||||
|
||||
<a n:if="($_GET['p'] ?? 1) > 1" class="aui-button" href="?p={($_GET['p'] ?? 1) - 1}">
|
||||
⭁ туда
|
||||
</a>
|
||||
<a n:if="$isLast" class="aui-button" href="?p={($_GET['p'] ?? 1) + 1}">
|
||||
⭇ сюда
|
||||
</a>
|
||||
|
||||
<a n:if="($_GET['p'] ?? 1) > 1" class="aui-button" href="?p={($_GET['p'] ?? 1) - 1}">«</a>
|
||||
<a n:if="$isLast" class="aui-button" href="?p={($_GET['p'] ?? 1) + 1}">»</a>
|
||||
</div>
|
||||
{/block}
|
||||
|
|
|
@ -5,45 +5,36 @@
|
|||
{/block}
|
||||
|
||||
{block heading}
|
||||
{_edit} №{$form->token ?? "undefined"}
|
||||
{_edit} #{$form->token ?? "undefined"}
|
||||
{/block}
|
||||
|
||||
{block content}
|
||||
<div style="margin: 8px -8px;" class="aui-tabs horizontal-tabs">
|
||||
<ul class="tabs-menu">
|
||||
<li class="menu-item active-tab">
|
||||
<a href="#info">Информация</a>
|
||||
<a href="#info">{_admin_tab_main}</a>
|
||||
</li>
|
||||
<li class="menu-item">
|
||||
<a href="#activators">{_voucher_activators}</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div class="tabs-pane active-pane" id="info">
|
||||
<form class="aui" method="POST">
|
||||
<div class="field-group">
|
||||
<label for="id">
|
||||
ID
|
||||
</label>
|
||||
<label for="id">ID</label>
|
||||
<input class="text long-field" type="number" id="id" name="id" disabled value="{$form->id}" />
|
||||
</div>
|
||||
<div class="field-group">
|
||||
<label for="token">
|
||||
Серийный номер
|
||||
</label>
|
||||
<label for="token">{_admin_voucher_serial}</label>
|
||||
<input class="text long-field" type="text" id="token" name="token" value="{$form->token}" />
|
||||
<div class="description">Номер состоит из 24 символов, если формат неправильный или поле не заполнено, будет назначен автоматически.</div>
|
||||
<div class="description">{_admin_voucher_serial_desc}</div>
|
||||
</div>
|
||||
<div class="field-group">
|
||||
<label for="coins">
|
||||
Количество голосов
|
||||
</label>
|
||||
<label for="coins">{_admin_voucher_coins}</label>
|
||||
<input class="text long-field" type="number" min="0" id="coins" name="coins" value="{$form->coins}" />
|
||||
</div>
|
||||
<div class="field-group">
|
||||
<label for="rating">
|
||||
Количество рейтинга
|
||||
</label>
|
||||
<label for="rating">{_admin_voucher_rating}</label>
|
||||
<input class="text long-field" type="number" min="0" id="rating" name="rating" value="{$form->rating}" />
|
||||
</div>
|
||||
<div class="field-group">
|
||||
|
@ -55,9 +46,9 @@
|
|||
{/if}
|
||||
</label>
|
||||
<input class="text long-field" type="number" min="-1" id="usages" name="usages" value="{$form->usages}" />
|
||||
<div class="description">Количество аккаунтов, которые могут использовать ваучер. Если написать -1, будет Infinity.</div>
|
||||
<div class="description">{_admin_voucher_usages_desc}</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="buttons-container">
|
||||
<div class="buttons">
|
||||
<input type="hidden" name="hash" value="{$csrfToken}" />
|
||||
|
@ -66,7 +57,6 @@
|
|||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="tabs-pane" id="activators">
|
||||
<table rules="none" class="aui aui-table-list">
|
||||
<tbody>
|
||||
|
@ -77,12 +67,10 @@
|
|||
<img src="{$user->getAvatarUrl('miniscule')}" alt="{$user->getCanonicalName()}" role="presentation" />
|
||||
</span>
|
||||
</span>
|
||||
|
||||
|
||||
<a href="{$user->getURL()}">{$user->getCanonicalName()}</a>
|
||||
|
||||
<span n:if="$user->isBanned()" class="aui-lozenge aui-lozenge-subtle aui-lozenge-removed">
|
||||
заблокирован
|
||||
</span>
|
||||
|
||||
<span n:if="$user->isBanned()" class="aui-lozenge aui-lozenge-subtle aui-lozenge-removed">{_admin_banned}</span>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
<a style="float: right;" class="aui-button aui-button-primary" href="/admin/vouchers/id0">
|
||||
{_create}
|
||||
</a>
|
||||
|
||||
|
||||
<h1>{_vouchers}</h1>
|
||||
{/block}
|
||||
|
||||
|
@ -16,13 +16,13 @@
|
|||
<table class="aui aui-table-list">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>#</th>
|
||||
<th>Серийный номер</th>
|
||||
<th>Голоса</th>
|
||||
<th>Рейгтинг</th>
|
||||
<th>Осталось использований</th>
|
||||
<th>Состояние</th>
|
||||
<th>Действия</th>
|
||||
<th>ID</th>
|
||||
<th>{_admin_voucher_serial}</th>
|
||||
<th>{_coins}</th>
|
||||
<th>{_admin_voucher_rating}</th>
|
||||
<th>{_usages_left}</th>
|
||||
<th>{_admin_voucher_status}</th>
|
||||
<th>{_admin_actions}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
@ -34,28 +34,25 @@
|
|||
<td>{$voucher->getRemainingUsages() === INF ? "∞" : $voucher->getRemainingUsages()}</td>
|
||||
<td>
|
||||
{if $voucher->isExpired()}
|
||||
<span class="aui-lozenge aui-lozenge-subtle aui-lozenge-removed">закончился</span>
|
||||
<span class="aui-lozenge aui-lozenge-subtle aui-lozenge-removed">{_admin_voucher_status_closed}</span>
|
||||
{else}
|
||||
<span class="aui-lozenge aui-lozenge-subtle aui-lozenge-success">активен</span>
|
||||
<span class="aui-lozenge aui-lozenge-subtle aui-lozenge-success">{_admin_voucher_status_opened}</span>
|
||||
{/if}
|
||||
</td>
|
||||
<td>
|
||||
<a class="aui-button aui-button-primary" href="/admin/vouchers/id{$voucher->getId()}">
|
||||
<span class="aui-icon aui-icon-small aui-iconfont-new-edit">Редактировать</span>
|
||||
<span class="aui-icon aui-icon-small aui-iconfont-new-edit">{_edit}</span>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<br/>
|
||||
|
||||
|
||||
<div align="right">
|
||||
{var $isLast = ((20 * (($_GET['p'] ?? 1) - 1)) + sizeof($vouchers)) < $count}
|
||||
<a n:if="($_GET['p'] ?? 1) > 1" class="aui-button" href="?p={($_GET['p'] ?? 1) - 1}">
|
||||
⭁ туда
|
||||
</a>
|
||||
<a n:if="$isLast" class="aui-button" href="?p={($_GET['p'] ?? 1) + 1}">
|
||||
⭇ сюда
|
||||
</a>
|
||||
|
||||
<a n:if="($_GET['p'] ?? 1) > 1" class="aui-button" href="?p={($_GET['p'] ?? 1) - 1}">«</a>
|
||||
<a n:if="$isLast" class="aui-button" href="?p={($_GET['p'] ?? 1) + 1}">»</a>
|
||||
</div>
|
||||
{/block}
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
</tr>
|
||||
<tr>
|
||||
<td><span class="nobold">{_"description"}:</span></td>
|
||||
<td>{$club->getDescription()}</td>
|
||||
<td>{$club->getDescriptionHtml()|noescape}</td>
|
||||
</tr>
|
||||
<tr n:if="!is_null($club->getWebsite())">
|
||||
<td><span class="nobold">{_"website"}: </span></td>
|
||||
|
|
|
@ -51,9 +51,9 @@
|
|||
|
||||
{if $isMain}
|
||||
<h4>{_support_faq}</h4><br />
|
||||
<div class="faq">
|
||||
<div id="faqhead">{_support_faq_title}</div>
|
||||
<div id="faqcontent">{_support_faq_content}</div>
|
||||
<div n:foreach="$faq as $section" class="faq">
|
||||
<div id="faqhead">{$section[0]}</div>
|
||||
<div id="faqcontent">{$section[1]|noescape}</div>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
|
|
|
@ -64,7 +64,7 @@
|
|||
<span class="nobold">{_"2fa_code"}</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" name="code" style="width: 100%;" />
|
||||
<input type="text" name="password_change_code" style="width: 100%;" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
@ -154,6 +154,38 @@
|
|||
{$user->getEmail()}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="120" valign="top">
|
||||
<span class="nobold">{_new_email_address}</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="email" name="new_email" style="width: 100%;" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="120" valign="top">
|
||||
<span class="nobold">{_password}</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="password" name="email_change_pass" style="width: 100%;" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr n:if="$user->is2faEnabled()">
|
||||
<td width="120" valign="top">
|
||||
<span class="nobold">{_"2fa_code"}</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" name="email_change_code" style="width: 100%;" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
<td>
|
||||
<input type="submit" value="{_save_email_address}" class="button" />
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<br/>
|
||||
|
@ -447,24 +479,35 @@
|
|||
</tr>
|
||||
<tr>
|
||||
<td width="120" valign="top">
|
||||
<span class="nobold">NSFW-контент</span>
|
||||
<span class="nobold">{_ui_settings_nsfw_content}</span>
|
||||
</td>
|
||||
<td>
|
||||
<select name="nsfw">
|
||||
<option value="0" {if $user->getNsfwTolerance() === 0}selected{/if}>Не показывать в глобальной ленте</option>
|
||||
<option value="1" {if $user->getNsfwTolerance() === 1}selected{/if}>Только замазывать</option>
|
||||
<option value="2" {if $user->getNsfwTolerance() === 2}selected{/if}>Показывать</option>
|
||||
<option value="0" {if $user->getNsfwTolerance() === 0}selected{/if}>{_ui_settings_nsfw_content_dont_show}</option>
|
||||
<option value="1" {if $user->getNsfwTolerance() === 1}selected{/if}>{_ui_settings_nsfw_content_blur}</option>
|
||||
<option value="2" {if $user->getNsfwTolerance() === 2}selected{/if}>{_ui_settings_nsfw_content_show}</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="120" valign="top">
|
||||
<span class="nobold">Вид постов</span>
|
||||
<span class="nobold">{_ui_settings_view_of_posts}</span>
|
||||
</td>
|
||||
<td>
|
||||
<select name="microblog">
|
||||
<option value="0" {if !$user->hasMicroblogEnabled()}selected{/if}>Старый</option>
|
||||
<option value="1" {if $user->hasMicroblogEnabled()}selected{/if}>Микроблог</option>
|
||||
<option value="0" {if !$user->hasMicroblogEnabled()}selected{/if}>{_ui_settings_view_of_posts_old}</option>
|
||||
<option value="1" {if $user->hasMicroblogEnabled()}selected{/if}>{_ui_settings_view_of_posts_microblog}</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="120" valign="top">
|
||||
<span class="nobold">{_ui_settings_main_page}</span>
|
||||
</td>
|
||||
<td>
|
||||
<select name="main_page">
|
||||
<option value="0" {if !$user->getMainPage()}selected{/if}>{_my_page}</option>
|
||||
<option value="1" {if $user->getMainPage()}selected{/if}>{_my_feed}</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
|
|
35
Web/Presenters/templates/components/cookies.xml
Normal file
35
Web/Presenters/templates/components/cookies.xml
Normal file
|
@ -0,0 +1,35 @@
|
|||
<div class="cookies-popup" style="display: none;">
|
||||
<div class="contanier">
|
||||
<div class="text">
|
||||
{tr("cookies_popup_content")|noescape}
|
||||
</div>
|
||||
<div class="buttons">
|
||||
<a href="javascript:agreeWithCookies()" class="button">
|
||||
{_cookies_popup_agree}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
let cookie = decodeURIComponent(document.cookie).split(";");
|
||||
let cookiesAgreed = false;
|
||||
for(let i = 0; i < cookie.length; i++) {
|
||||
let c = cookie[i];
|
||||
while (c.charAt(0) == ' ') {
|
||||
c = c.substring(1);
|
||||
}
|
||||
if(c == "cookiesAgreed=true") {
|
||||
cookiesAgreed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!cookiesAgreed) {
|
||||
u(".cookies-popup").nodes[0].style.display = "block";
|
||||
}
|
||||
|
||||
function agreeWithCookies() {
|
||||
document.cookie = "cookiesAgreed=true";
|
||||
u(".cookies-popup").nodes[0].style.display = "none";
|
||||
}
|
||||
</script>
|
|
@ -2,7 +2,7 @@
|
|||
{var $comments = $post->getLastComments(3)}
|
||||
{var $commentsCount = $post->getCommentsCount()}
|
||||
|
||||
{var $commentTextAreaId = $post === null ? rand(1,300) : $post->getId()}
|
||||
{var $commentTextAreaId = $post === NULL ? rand(1,300) : $post->getId()}
|
||||
|
||||
<table border="0" style="font-size: 11px;" n:class="post, !$compact ? post-divider, $post->isExplicit() ? post-nsfw">
|
||||
<tbody>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{php if(!isset($GLOBALS["textAreaCtr"])) $GLOBALS["textAreaCtr"] = 10;}
|
||||
{var $textAreaId = ($post ?? NULL) === null ? (++$GLOBALS["textAreaCtr"]) : $post->getId()}
|
||||
{var $textAreaId = ($post ?? NULL) === NULL ? (++$GLOBALS["textAreaCtr"]) : $post->getId()}
|
||||
|
||||
<div id="write" style="padding: 5px 0;" onfocusin="expand_wall_textarea({$textAreaId});">
|
||||
<form action="{$route}" method="post" enctype="multipart/form-data" style="margin:0;">
|
||||
|
|
|
@ -73,6 +73,8 @@ routes:
|
|||
handler: "User->disableTwoFactorAuth"
|
||||
- url: "/settings/reset_theme"
|
||||
handler: "User->resetThemepack"
|
||||
- url: "/settings/change_email"
|
||||
handler: "User->emailChangeFinish"
|
||||
- url: "/coins_transfer"
|
||||
handler: "User->coinsTransfer"
|
||||
- url: "/increase_social_credits"
|
||||
|
|
|
@ -1913,4 +1913,25 @@ table td[width="120"] {
|
|||
border-bottom: 1.5px solid #707070;
|
||||
text-align: center;
|
||||
user-select: none;
|
||||
}
|
||||
}
|
||||
|
||||
.cookies-popup {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
background: linear-gradient(#fff, #eee);
|
||||
box-shadow: inset 0px 1px 0px #bbb, inset 0px 2px 0px #ddd;
|
||||
}
|
||||
|
||||
.cookies-popup .contanier {
|
||||
width: 760px;
|
||||
display: flex;
|
||||
margin: 0 auto;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.cookies-popup .contanier .text {
|
||||
width: 100%;
|
||||
}
|
||||
|
|
|
@ -2,32 +2,12 @@ Function.noop = () => {};
|
|||
|
||||
var _n_counter = 0;
|
||||
|
||||
var _activeWindow = true;
|
||||
|
||||
const _pageTitle = u("title").nodes[0].innerText;
|
||||
|
||||
var counter = 0;
|
||||
|
||||
/* this fucking dumb shit is broken :c
|
||||
|
||||
window.addEventListener('focus', () => {
|
||||
_activeWindow = true;
|
||||
closeAllNotifications();
|
||||
window.addEventListener("focus", () => {
|
||||
document.title = document.title.replace(/^\([0-9]+\) /, ""); // remove notification counter xD
|
||||
});
|
||||
|
||||
window.addEventListener('blur', () => {_activeWindow = false});
|
||||
|
||||
function closeAllNotifications() {
|
||||
var notifications = u(".notifications_global_wrap").nodes[0].children;
|
||||
for (var i = 0; i < notifications.length; i++) {
|
||||
setTimeout(() => {
|
||||
console.log(i);
|
||||
notifications.item(i).classList.add('disappears');
|
||||
setTimeout(() => {notifications.item(i).remove()}, 500).bind(this);
|
||||
}, 5000).bind(this);
|
||||
}
|
||||
} */
|
||||
|
||||
function NewNotification(title, body, avatar = null, callback = () => {}, time = 5000, count = true) {
|
||||
if(avatar != null) {
|
||||
avatar = '<avatar>' +
|
||||
|
@ -62,18 +42,19 @@ function NewNotification(title, body, avatar = null, callback = () => {}, time =
|
|||
}
|
||||
|
||||
function __closeNotification() {
|
||||
if(document.visibilityState != "visible")
|
||||
return setTimeout(() => {__closeNotification()}, time); // delay notif deletion
|
||||
|
||||
getPrototype().addClass('disappears');
|
||||
setTimeout(() => {getPrototype().remove()}, 500);
|
||||
return setTimeout(() => {getPrototype().remove()}, 500);
|
||||
}
|
||||
|
||||
if(count == true) {
|
||||
counter++;
|
||||
document.title = `(${counter}) ${_pageTitle}`;
|
||||
document.title = `(${counter}) ${document.title}`;
|
||||
}
|
||||
|
||||
/* if(_activeWindow == true) { */
|
||||
setTimeout(() => {__closeNotification()}, time);
|
||||
/* } */
|
||||
setTimeout(() => {__closeNotification()}, time);
|
||||
|
||||
notification.children('notification_title').children('a.close').on('click', function(e) {
|
||||
__closeNotification();
|
||||
|
|
|
@ -171,7 +171,7 @@ function repostPost(id, hash) {
|
|||
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
|
||||
xhr.onload = (function() {
|
||||
if(xhr.responseText.indexOf("wall_owner") === -1)
|
||||
MessageBox(tr('error'), tr('error_repost_fail'), tr('ok'), [Function.noop]);
|
||||
MessageBox(tr('error'), tr('error_repost_fail'), [tr('ok')], [Function.noop]);
|
||||
else {
|
||||
let jsonR = JSON.parse(xhr.responseText);
|
||||
NewNotification(tr('information_-1'), tr('shared_succ'), null, () => {window.location.href = "/wall" + jsonR.wall_owner});
|
||||
|
|
|
@ -136,7 +136,7 @@ function isLanguageAvailable($lg): bool
|
|||
|
||||
function getBrowsersLanguage(): array
|
||||
{
|
||||
if ($_SERVER['HTTP_ACCEPT_LANGUAGE'] != null) return mb_split(",", mb_split(";", $_SERVER['HTTP_ACCEPT_LANGUAGE'])[0]);
|
||||
if ($_SERVER['HTTP_ACCEPT_LANGUAGE'] != NULL) return mb_split(",", mb_split(";", $_SERVER['HTTP_ACCEPT_LANGUAGE'])[0]);
|
||||
else return array();
|
||||
}
|
||||
|
||||
|
@ -144,7 +144,7 @@ function eventdb(): ?DatabaseConnection
|
|||
{
|
||||
$conf = OPENVK_ROOT_CONF["openvk"]["credentials"]["eventDB"];
|
||||
if(!$conf["enable"])
|
||||
return null;
|
||||
return NULL;
|
||||
|
||||
$db = (object) $conf["database"];
|
||||
return DatabaseConnection::connect([
|
||||
|
@ -216,8 +216,8 @@ return (function() {
|
|||
|
||||
setlocale(LC_TIME, "POSIX");
|
||||
|
||||
// TODO: Default language in config
|
||||
if(Session::i()->get("lang") == null) {
|
||||
# TODO: Default language in config
|
||||
if(Session::i()->get("lang") == NULL) {
|
||||
$languages = array_reverse(getBrowsersLanguage());
|
||||
foreach($languages as $lg) {
|
||||
if(isLanguageAvailable($lg)) setLanguage($lg);
|
||||
|
@ -233,7 +233,7 @@ return (function() {
|
|||
else
|
||||
$ver = "Public Technical Preview 3";
|
||||
|
||||
// Unix time constants
|
||||
# Unix time constants
|
||||
define('MINUTE', 60);
|
||||
define('HOUR', 60 * MINUTE);
|
||||
define('DAY', 24 * HOUR);
|
||||
|
|
2
data/knowledgebase/faq.md
Normal file
2
data/knowledgebase/faq.md
Normal file
|
@ -0,0 +1,2 @@
|
|||
# Who is this website for?
|
||||
The site is designed to find friends and acquaintances, as well as view user data. It is like a city directory, through which people can quickly find relevant information about a person.
|
2
data/knowledgebase/faq.ru.md
Normal file
2
data/knowledgebase/faq.ru.md
Normal file
|
@ -0,0 +1,2 @@
|
|||
# Для кого этот сайт?
|
||||
Сайт предназначен для поиска друзей и знакомых, а также для просмотра данных пользователя. Это как справочник города, с помощью которого люди могут быстро найти актуальную информацию о человеке.
|
8
install/sqls/00023-email-change.sql
Normal file
8
install/sqls/00023-email-change.sql
Normal file
|
@ -0,0 +1,8 @@
|
|||
CREATE TABLE IF NOT EXISTS `email_change_verifications` (
|
||||
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`profile` bigint(20) unsigned NOT NULL,
|
||||
`key` char(64) COLLATE utf8mb4_unicode_520_ci NOT NULL,
|
||||
`new_email` varchar(90) COLLATE utf8mb4_unicode_520_ci DEFAULT NULL,
|
||||
`timestamp` bigint(20) unsigned NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_520_ci;
|
1
install/sqls/00024-main-page-setting.sql
Normal file
1
install/sqls/00024-main-page-setting.sql
Normal file
|
@ -0,0 +1 @@
|
|||
ALTER TABLE `profiles` ADD COLUMN `main_page` tinyint(3) unsigned NOT NULL DEFAULT 0 AFTER `microblog`;
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
"home" = "Գլխավոր";
|
||||
"welcome" = "Բարի գալուստ";
|
||||
"to_top" = "Վերև";
|
||||
|
||||
/* Login */
|
||||
|
||||
|
@ -381,7 +382,6 @@
|
|||
|
||||
"left_menu_donate" = "Աջակցել";
|
||||
|
||||
|
||||
"footer_about_instance" = "հոսքի մասին";
|
||||
"footer_blog" = "բլոգ";
|
||||
"footer_help" = "օգնություն";
|
||||
|
@ -410,6 +410,8 @@
|
|||
"style" = "Ոճ";
|
||||
|
||||
"default" = "Սովորական";
|
||||
|
||||
"arbitrary_avatars" = "Կամայական";
|
||||
"cut" = "Կտրվածք";
|
||||
"round_avatars" = "Կլոր ավատար";
|
||||
|
||||
|
@ -519,6 +521,8 @@
|
|||
"videos_many" = "$1 տեսանյութ";
|
||||
"videos_other" = "$1 տեսանյութ";
|
||||
|
||||
"view_video" = "Դիտում";
|
||||
|
||||
/* Notifications */
|
||||
|
||||
"feedback" = "Հետադարձ կապ";
|
||||
|
@ -624,6 +628,21 @@
|
|||
"receiver_not_found" = "Ստացողը չի գտնվել։";
|
||||
"you_dont_have_enough_points" = "Դուք չունե՛ք բավական ձայն։";
|
||||
|
||||
"increase_rating" = "Բարձրացնել վարկանիշը";
|
||||
"increase_rating_button" = "Բարձրացնել";
|
||||
"to_whom" = "Ում";
|
||||
"increase_by" = "Բարձրացնել";
|
||||
"price" = "Արժողություն";
|
||||
|
||||
"you_have_unused_votes" = "Ձեր մոտ $1 չօգտագործված ձայն կա հաշվի վրա։";
|
||||
"apply_voucher" = "Կիրառել վաուչեր";
|
||||
|
||||
"failed_to_increase_rating" = "Չհաջողվե՛ց բարձրացնել վարկանիշը";
|
||||
"rating_increase_successful" = "Դուք հաջողությամբ բարձրացրեցիք Ձեր վարկանիշը <b><a href=\"$1\">$2</a></b> <b>$3%</b>-ով։";
|
||||
"negative_rating_value" = "Կներե՛ք, մենք չենք կարող գողանալ ուրիշի վարկանիշը։";
|
||||
|
||||
"increased_your_rating_by" = "բարձրացրել է վարկանիշը";
|
||||
|
||||
/* Gifts */
|
||||
|
||||
"gift" = "Նվեր";
|
||||
|
@ -703,6 +722,9 @@
|
|||
"ticket_changed" = "Տոմսը փոփոխված է";
|
||||
"ticket_changed_comment" = "Փոփոխությունները ուժի մեջ կմտնեն մի քանի վայրկյանից։";
|
||||
|
||||
"banned_in_support_1" = "Կներե՛ք, <b>$1</b>, բայց հիմա Ձեզ թույլատրված չէ դիմումներ ստեղծել։";
|
||||
"banned_in_support_2" = "Դրա պատճառաբանությունը սա է․ <b>$1</b>։ Ցավո՛ք, այդ հնարավորությունը մենք Ձեզնից վերցրել ենք առհավետ։";
|
||||
|
||||
/* Invite */
|
||||
|
||||
"invite" = "Հրավիրել";
|
||||
|
@ -711,9 +733,9 @@
|
|||
|
||||
/* Banned */
|
||||
|
||||
"banned_title" = "Բլոկավորված եք";
|
||||
"banned_header" = "Ձեզ կասեցրել է կառլենի անհաջող բոցը։";
|
||||
"banned_alt" = "Օգտատերը բլոկավորված է";
|
||||
"banned_title" = "Արգելափակված եք";
|
||||
"banned_header" = "Ձեզ կասեցրել է կարլենի անհաջող բոցը։";
|
||||
"banned_alt" = "Օգտատերը արգելափակված է";
|
||||
"banned_1" = "Կներե՛ք, <b>$1</b>, բայց Դուք կասեցված եք։";
|
||||
"banned_2" = "Պատճառը հետևյալն է․ <b>$1</b>. Ափսոս, բայց մենք ստիպված Ձեզ հավերժ ենք կասեցրել;";
|
||||
"banned_3" = "Դուք դեռ կարող եք <a href=\"/support?act=new\">գրել նամակ աջակցության ծառայությանը</a>, եթե համարում եք որ դա սխալմունք է, կամ էլ կարող եք <a href=\"/logout?hash=$1\">դուրս գալ</a>։";
|
||||
|
@ -835,6 +857,7 @@
|
|||
"captcha_error" = "Սխալ են գրված սիմվոլները";
|
||||
"captcha_error_comment" = "Խնդրում ենք համոզվել, որ ճիշտ եք ներմուծել կապտչայի սիմվոլները։";
|
||||
|
||||
|
||||
/* Admin actions */
|
||||
|
||||
"login_as" = "Մտնել ինչպես $1";
|
||||
|
@ -843,7 +866,84 @@
|
|||
"ban_user_action" = "Բլոկավորել օգտվողին";
|
||||
"warn_user_action" = "Զգուշացնել օգտվողին";
|
||||
|
||||
/* Paginator (subject to delete) */
|
||||
|
||||
/* Admin panel */
|
||||
|
||||
"admin" = "Ադմին-վահանակ";
|
||||
|
||||
"admin_ownerid" = "Տիրոջ ID";
|
||||
"admin_author" = "Հեղինակ";
|
||||
"admin_name" = "Անուն";
|
||||
"admin_title" = "Անվանում";
|
||||
"admin_description" = "Նկարագրություն";
|
||||
"admin_first_known_ip" = "Առաջին IP";
|
||||
"admin_shortcode" = "Կարճ հասցե";
|
||||
"admin_verification" = "Վերիֆիկացիա";
|
||||
"admin_banreason" = "Արգելափակման պատճառ";
|
||||
"admin_banned" = "արգելափակված է";
|
||||
"admin_actions" = "Գործողություններ";
|
||||
"admin_image" = "Նկար";
|
||||
"admin_image_replace" = "Փոխե՞լ նկարը";
|
||||
"admin_uses" = "Օգտագործումներ";
|
||||
"admin_uses_reset" = "Զրոյացնե՞լ օգտագործումների քանակը";
|
||||
"admin_limits" = "Սահմանափակումներ";
|
||||
"admin_limits_reset" = "Զրոյացնել օգտագործումների քանակը";
|
||||
"admin_open" = "Բացել";
|
||||
"admin_loginas" = "Մուտք գործել ինչպես...";
|
||||
"admin_commonsettings" = "Ընդհանուր կարգավորումներ";
|
||||
"admin_langsettings" = "Լեզվից կախված կարգավորումներ";
|
||||
|
||||
"admin_tab_main" = "Գլխավոր";
|
||||
"admin_tab_ban" = "Բլոկավորում";
|
||||
"admin_tab_followers" = "Մասնակիցներ";
|
||||
|
||||
"admin_overview" = "Դիտում";
|
||||
"admin_overview_summary" = "Ամփոփում";
|
||||
|
||||
"admin_content" = "Օգտատիրային կոնտենտ";
|
||||
"admin_user_search" = "Օգտատերերի որոնում";
|
||||
"admin_user_online" = "Օնլայն վիճակ";
|
||||
"admin_user_online_default" = "Ըստ նախնականի";
|
||||
"admin_user_online_incognito" = "Ինկոգնիտո";
|
||||
"admin_user_online_deceased" = "Հանգուցյալ";
|
||||
"admin_club_search" = "Խմբերի որոնում";
|
||||
"admin_club_excludeglobalfeed" = "Չ՛ցույց տալ գլոբալ ժապավենում";
|
||||
|
||||
"admin_services" = "Վճարովի ծառայություններ";
|
||||
"admin_newgift" = "Նոր նվեր";
|
||||
"admin_price" = "Գին";
|
||||
"admin_giftset" = "Նվերների հավաքախու";
|
||||
"admin_giftsets" = "Նվերների հավաքախուներ";
|
||||
"admin_giftsets_none" = "Նվերների հավաքածու չկա։ Ստեղծե՛ք հավաքածու նվեր ավելացնելու համար։";
|
||||
"admin_giftsets_create" = "Ստեղծել նվերների հավաքածու";
|
||||
"admin_giftsets_title" = "Հավաքածույի ներքին անվանում, եթե չի հաջողվում որոնել այն օգտատիրոջ լեզվով";
|
||||
"admin_giftsets_description" = "Հավաքածույի ներքին նկարագրություն, եթե չի հաջողվում որոնել այն օգտատիրոջ լեզվով";
|
||||
"admin_price_free" = "անվճար";
|
||||
"admin_voucher_rating" = "Վարկանիշ";
|
||||
"admin_voucher_serial" = "Սերիական համար";
|
||||
"admin_voucher_serial_desc" = "Համարը բաղկացած է 24 նշից։ Եթե Դուք այն սխալ գրեք, այն կտրվի ավտոմատ։";
|
||||
"admin_voucher_coins" = "Ձայների քանակ";
|
||||
"admin_voucher_rating" = "Վարկանշի քանակ";
|
||||
"admin_voucher_usages_desc" = "Վաուչերը օգտագործող ակկաունտների քանակ։ Եթե գրեք -1, ապա այն կլինի օգտագործել անվերջ։";
|
||||
"admin_voucher_status" = "Կարգավիճակ";
|
||||
"admin_voucher_status_opened" = "ակտիվ է";
|
||||
"admin_voucher_status_closed" = "վերջացել է";
|
||||
|
||||
"admin_settings" = "Կարգավորումներ";
|
||||
"admin_settings_tuning" = "Ընդհանուր";
|
||||
"admin_settings_appearance" = "Արտաքին տեսք";
|
||||
"admin_settings_security" = "Անվտանգություն";
|
||||
"admin_settings_integrations" = "Ինտեգրացիաներ";
|
||||
"admin_settings_system" = "Համակարգ";
|
||||
|
||||
"admin_about" = "OpenVK-ի մասին";
|
||||
"admin_about_version" = "Վերսիա";
|
||||
"admin_about_instance" = "Հոսք";
|
||||
|
||||
"admin_commerce_disabled" = "Կոմմերցիան անջատված է համակարգային ադմինիստրատորի կողմից";
|
||||
"admin_commerce_disabled_desc" = "Վաուչերների և նվերների կարգավորումները կպահպանվեն, բայց ոչ մի ազդեցություն չեն ունենա։";
|
||||
|
||||
/* Paginator (deprecated) */
|
||||
|
||||
"paginator_back" = "Հետ";
|
||||
"paginator_page" = "$1 էջ";
|
||||
|
@ -857,6 +957,8 @@
|
|||
"rules" = "Կանոններ";
|
||||
"most_popular_groups" = "Ամենահայտնի խմբերը";
|
||||
"on_this_instance_are" = "Այս հոսքում․";
|
||||
"about_links" = "Հղումներ";
|
||||
"instance_links" = "Հոսքերի հղումներ․";
|
||||
|
||||
"about_users_one" = "<b>Մեկ</b> օգտատեր";
|
||||
"about_users_few" = "<b>$1</b> օգտատեր";
|
||||
|
|
|
@ -470,3 +470,7 @@
|
|||
"comment" = "Каментарый";
|
||||
"sender" = "Адпраўнік";
|
||||
|
||||
/* Cookies pop-up */
|
||||
|
||||
"cookies_popup_content" = "Усе хлопчыкi любяць пэчыва, таму гэты вэб-сайт выкарыстоўвае Cookies для таго, каб ідэнтыфікаваць вашу сесію і нічога болей. Звяртайцеся да нашай <a href='/privacy'>палiтыкi канфiдэнцыальнастi</a> для палучэння поўнай iнфармацыi.";
|
||||
"cookies_popup_agree" = "Прынiмаю";
|
||||
|
|
|
@ -444,6 +444,8 @@
|
|||
"your_page_address" = "Your address page";
|
||||
"page_address" = "Address page";
|
||||
"current_email_address" = "Current email address";
|
||||
"new_email_address" = "New email address";
|
||||
"save_email_address" = "Save email address";
|
||||
"page_id" = "Page ID";
|
||||
"you_can_also" = "You can also";
|
||||
"delete_your_page" = "delete your page";
|
||||
|
@ -454,10 +456,20 @@
|
|||
"ui_settings_rating" = "Rating";
|
||||
"ui_settings_rating_show" = "Show";
|
||||
"ui_settings_rating_hide" = "Hide";
|
||||
"ui_settings_nsfw_content" = "NSFW content";
|
||||
"ui_settings_nsfw_content_dont_show" = "Don't show in global feed";
|
||||
"ui_settings_nsfw_content_blur" = "Just blur";
|
||||
"ui_settings_nsfw_content_show" = "Show";
|
||||
"ui_settings_view_of_posts" = "View of posts";
|
||||
"ui_settings_view_of_posts_old" = "Old";
|
||||
"ui_settings_view_of_posts_microblog" = "Microblog";
|
||||
"ui_settings_main_page" = "Main page";
|
||||
|
||||
"additional_links" = "Additional links";
|
||||
"ad_poster" = "Ad poster";
|
||||
|
||||
"email_change_confirm_message" = "Please confirm your new email address for the change to take effect. We have sent instructions to it.";
|
||||
|
||||
/* Two-factor authentication */
|
||||
|
||||
"two_factor_authentication" = "Two-factor authentication";
|
||||
|
@ -661,9 +673,6 @@
|
|||
"support_list" = "List of tickets";
|
||||
"support_new" = "New ticket";
|
||||
|
||||
"support_faq_title" = "Who is this website for?";
|
||||
"support_faq_content" = "The site is designed to find friends and acquaintances, as well as view user data. It is like a city directory, through which people can quickly find relevant information about a person.";
|
||||
|
||||
"support_new_title" = "Enter the topic of your ticket";
|
||||
"support_new_content" = "Describe the issue or suggestion";
|
||||
|
||||
|
@ -847,6 +856,84 @@
|
|||
"ban_in_support_user_action" = "Ban in support";
|
||||
"unban_in_support_user_action" = "Unban in support";
|
||||
|
||||
/* Admin panel */
|
||||
|
||||
"admin" = "Admin panel";
|
||||
|
||||
"admin_ownerid" = "Owner ID";
|
||||
"admin_author" = "Author";
|
||||
"admin_name" = "Name";
|
||||
"admin_title" = "Title";
|
||||
"admin_description" = "Description";
|
||||
"admin_first_known_ip" = "First known IP";
|
||||
"admin_shortcode" = "Short code";
|
||||
"admin_verification" = "Verification";
|
||||
"admin_banreason" = "Ban reason";
|
||||
"admin_banned" = "banned";
|
||||
"admin_gender" = "Gender";
|
||||
"admin_registrationdate" = "Registration date";
|
||||
"admin_actions" = "Actions";
|
||||
"admin_image" = "Image";
|
||||
"admin_image_replace" = "Replace the image?";
|
||||
"admin_uses" = "Uses";
|
||||
"admin_uses_reset" = "Reset the number of uses?";
|
||||
"admin_limits" = "Limits";
|
||||
"admin_limits_reset" = "Reset the number of limits";
|
||||
"admin_open" = "Open";
|
||||
"admin_loginas" = "Login as...";
|
||||
"admin_commonsettings" = "Common settings";
|
||||
"admin_langsettings" = "Language-dependent settings";
|
||||
|
||||
"admin_tab_main" = "General";
|
||||
"admin_tab_ban" = "Ban";
|
||||
"admin_tab_followers" = "Followers";
|
||||
|
||||
"admin_overview" = "Overview";
|
||||
"admin_overview_summary" = "Summary";
|
||||
|
||||
"admin_content" = "User-generated content";
|
||||
"admin_user_search" = "Search for users";
|
||||
"admin_user_online" = "Online status";
|
||||
"admin_user_online_default" = "Default";
|
||||
"admin_user_online_incognito" = "Incognito";
|
||||
"admin_user_online_deceased" = "Deceased";
|
||||
"admin_club_search" = "Search for groups";
|
||||
"admin_club_excludeglobalfeed" = "Do not display posts in the global feed";
|
||||
|
||||
"admin_services" = "Paid services";
|
||||
"admin_newgift" = "New gift";
|
||||
"admin_price" = "Price";
|
||||
"admin_giftset" = "Gift set";
|
||||
"admin_giftsets" = "Gift sets";
|
||||
"admin_giftsets_none" = "There are no gift sets. Create a set to create a gift.";
|
||||
"admin_giftsets_create" = "Create a gift set";
|
||||
"admin_giftsets_title" = "The internal name of the set, which will be used if no name can be found in the user's language.";
|
||||
"admin_giftsets_description" = "The internal description of the set, which will be used if no name can be found in the user's language.";
|
||||
"admin_price_free" = "free";
|
||||
"admin_voucher_rating" = "Rating";
|
||||
"admin_voucher_serial" = "Serial number";
|
||||
"admin_voucher_serial_desc" = "The number consists of 24 characters. If the format is incorrect or the field is not filled in, it will be assigned automatically.";
|
||||
"admin_voucher_coins" = "Number of votes";
|
||||
"admin_voucher_rating" = "Number of rating";
|
||||
"admin_voucher_usages_desc" = "The number of accounts that can use the voucher. If you type -1, it will be infinity.";
|
||||
"admin_voucher_status" = "Status";
|
||||
"admin_voucher_status_opened" = "active";
|
||||
"admin_voucher_status_closed" = "closed";
|
||||
|
||||
"admin_settings" = "Settings";
|
||||
"admin_settings_tuning" = "General";
|
||||
"admin_settings_appearance" = "Appearance";
|
||||
"admin_settings_security" = "Security";
|
||||
"admin_settings_integrations" = "Integrations";
|
||||
"admin_settings_system" = "System";
|
||||
|
||||
"admin_about" = "About OpenVK";
|
||||
"admin_about_version" = "Version";
|
||||
"admin_about_instance" = "Instance";
|
||||
|
||||
"admin_commerce_disabled" = "Commerce has been disabled by the system administrator";
|
||||
"admin_commerce_disabled_desc" = "The voucher and gift settings will be saved, but will have no effect.";
|
||||
|
||||
/* Paginator (deprecated) */
|
||||
|
||||
"paginator_back" = "Back";
|
||||
|
@ -895,3 +982,8 @@
|
|||
/* User alerts */
|
||||
|
||||
"user_alert_scam" = "This account has been reported a lot for scam. Please be careful, especially if he asked for money.";
|
||||
|
||||
/* Cookies pop-up */
|
||||
|
||||
"cookies_popup_content" = "All kids love cookie, so this website uses Cookies to identify your session and nothing more. Check <a href='/privacy'>our privacy policy</a> for more information.";
|
||||
"cookies_popup_agree" = "Accept";
|
||||
|
|
|
@ -472,6 +472,8 @@
|
|||
"your_page_address" = "Адрес Вашей страницы";
|
||||
"page_address" = "Адрес страницы";
|
||||
"current_email_address" = "Текущий адрес";
|
||||
"new_email_address" = "Новый адрес";
|
||||
"save_email_address" = "Сохранить адрес";
|
||||
"page_id" = "ID страницы";
|
||||
"you_can_also" = "Вы также можете";
|
||||
"delete_your_page" = "удалить свою страницу";
|
||||
|
@ -482,10 +484,20 @@
|
|||
"ui_settings_rating" = "Рейтинг";
|
||||
"ui_settings_rating_show" = "Показывать";
|
||||
"ui_settings_rating_hide" = "Скрывать";
|
||||
"ui_settings_nsfw_content" = "NSFW-контент";
|
||||
"ui_settings_nsfw_content_dont_show" = "Не показывать в глобальной ленте";
|
||||
"ui_settings_nsfw_content_blur" = "Только замазывать";
|
||||
"ui_settings_nsfw_content_show" = "Показывать";
|
||||
"ui_settings_view_of_posts" = "Вид постов";
|
||||
"ui_settings_view_of_posts_old" = "Старый";
|
||||
"ui_settings_view_of_posts_microblog" = "Микроблог";
|
||||
"ui_settings_main_page" = "Главная страница";
|
||||
|
||||
"additional_links" = "Дополнительные ссылки";
|
||||
"ad_poster" = "Рекламный плакат";
|
||||
|
||||
"email_change_confirm_message" = "Чтобы изменение вступило в силу, подтвердите ваш новый адрес электронной почты. Мы отправили инструкции на него.";
|
||||
|
||||
/* Two-factor authentication */
|
||||
|
||||
"two_factor_authentication" = "Двухфакторная аутентификация";
|
||||
|
@ -698,9 +710,6 @@
|
|||
"support_list" = "Список обращений";
|
||||
"support_new" = "Новое обращение";
|
||||
|
||||
"support_faq_title" = "Для кого этот сайт?";
|
||||
"support_faq_content" = "Сайт предназначен для поиска друзей и знакомых, а также для просмотра данных пользователя. Это как справочник города, с помощью которого люди могут быстро найти актуальную информацию о человеке.";
|
||||
|
||||
"support_new_title" = "Введите тему вашего обращения";
|
||||
"support_new_content" = "Опишите проблему или предложение";
|
||||
|
||||
|
@ -890,6 +899,82 @@
|
|||
"ban_in_support_user_action" = "Заблокировать в поддержке";
|
||||
"unban_in_support_user_action" = "Разблокировать в поддержке";
|
||||
|
||||
/* Admin panel */
|
||||
|
||||
"admin" = "Админ-панель";
|
||||
|
||||
"admin_ownerid" = "ID владельца";
|
||||
"admin_author" = "Автор";
|
||||
"admin_name" = "Имя";
|
||||
"admin_title" = "Название";
|
||||
"admin_description" = "Описание";
|
||||
"admin_first_known_ip" = "Первый IP";
|
||||
"admin_shortcode" = "Короткий адрес";
|
||||
"admin_verification" = "Верификация";
|
||||
"admin_banreason" = "Причина блокировки";
|
||||
"admin_banned" = "заблокирован";
|
||||
"admin_actions" = "Действия";
|
||||
"admin_image" = "Изображение";
|
||||
"admin_image_replace" = "Заменить изображение?";
|
||||
"admin_uses" = "Использований";
|
||||
"admin_uses_reset" = "Сбросить количество использований?";
|
||||
"admin_limits" = "Ограничения";
|
||||
"admin_limits_reset" = "Сбросить количество ограничений";
|
||||
"admin_open" = "Открыть";
|
||||
"admin_loginas" = "Войти как...";
|
||||
"admin_commonsettings" = "Общие настройки";
|
||||
"admin_langsettings" = "Языко-зависимые настройки";
|
||||
|
||||
"admin_tab_main" = "Главное";
|
||||
"admin_tab_ban" = "Блокировка";
|
||||
"admin_tab_followers" = "Участники";
|
||||
|
||||
"admin_overview" = "Обзор";
|
||||
"admin_overview_summary" = "Сводка";
|
||||
|
||||
"admin_content" = "Пользовательский контент";
|
||||
"admin_user_search" = "Поиск пользователей";
|
||||
"admin_user_online" = "Онлайн статус";
|
||||
"admin_user_online_default" = "По-умолчанию";
|
||||
"admin_user_online_incognito" = "Инкогнито";
|
||||
"admin_user_online_deceased" = "Покойник";
|
||||
"admin_club_search" = "Поиск групп";
|
||||
"admin_club_excludeglobalfeed" = "Не отображать записи в глобальной ленте";
|
||||
|
||||
"admin_services" = "Платные услуги";
|
||||
"admin_newgift" = "Новый подарок";
|
||||
"admin_price" = "Цена";
|
||||
"admin_giftset" = "Набор подарков";
|
||||
"admin_giftsets" = "Наборы подарков";
|
||||
"admin_giftsets_none" = "Нет наборов подарков. Создайте набор, чтобы создать подарок.";
|
||||
"admin_giftsets_create" = "Создать набор подарков";
|
||||
"admin_giftsets_title" = "Внутреннее название набора, которое будет использоваться, если не удаётся найти название на языке пользователя.";
|
||||
"admin_giftsets_description" = "Внутреннее описание набора, которое будет использоваться, если не удаётся найти название на языке пользователя.";
|
||||
"admin_price_free" = "бесплатный";
|
||||
"admin_voucher_rating" = "Рейтинг";
|
||||
"admin_voucher_serial" = "Серийный номер";
|
||||
"admin_voucher_serial_desc" = "Номер состоит из 24 символов. Если формат неправильный или поле не заполнено, будет назначен автоматически.";
|
||||
"admin_voucher_coins" = "Количество голосов";
|
||||
"admin_voucher_rating" = "Количество рейтинга";
|
||||
"admin_voucher_usages_desc" = "Количество аккаунтов, которые могут использовать ваучер. Если написать -1, будет бесконечность.";
|
||||
"admin_voucher_status" = "Состояние";
|
||||
"admin_voucher_status_opened" = "активен";
|
||||
"admin_voucher_status_closed" = "закончился";
|
||||
|
||||
"admin_settings" = "Настройки";
|
||||
"admin_settings_tuning" = "Общее";
|
||||
"admin_settings_appearance" = "Внешний вид";
|
||||
"admin_settings_security" = "Безопасность";
|
||||
"admin_settings_integrations" = "Интеграции";
|
||||
"admin_settings_system" = "Система";
|
||||
|
||||
"admin_about" = "Об OpenVK";
|
||||
"admin_about_version" = "Версия";
|
||||
"admin_about_instance" = "Инстанция";
|
||||
|
||||
"admin_commerce_disabled" = "Коммерция отключена системным администратором";
|
||||
"admin_commerce_disabled_desc" = "Настройки ваучеров и подарков будут сохранены, но не будут оказывать никакого влияния.";
|
||||
|
||||
/* Paginator (deprecated) */
|
||||
|
||||
"paginator_back" = "Назад";
|
||||
|
@ -948,3 +1033,8 @@
|
|||
/* User alerts */
|
||||
|
||||
"user_alert_scam" = "На этот аккаунт много жаловались в связи с мошенничеством. Пожалуйста, будьте осторожны, особенно если у вас попросят денег.";
|
||||
|
||||
/* Cookies pop-up */
|
||||
|
||||
"cookies_popup_content" = "Все дети любят печенье, поэтому этот веб-сайт использует Cookies для того, чтобы идентифицировать вашу сессию и ничего более. Ознакомьтесь с нашей <a href='/privacy'>политикой конфиденциальности</a> для получения дополнительной информации.";
|
||||
"cookies_popup_agree" = "Согласен";
|
||||
|
|
Loading…
Reference in a new issue