mirror of
https://github.com/openvk/openvk
synced 2024-11-15 03:31:18 +03:00
Merge from master branch
This commit is contained in:
commit
45db4188cc
125 changed files with 4892 additions and 1516 deletions
1
.github/FUNDING.yml
vendored
Normal file
1
.github/FUNDING.yml
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
custom: "https://openvk.su/donate"
|
|
@ -94,7 +94,7 @@
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<center>
|
<center>
|
||||||
<a href="http://{$_SERVER['HTTP_HOST']}/restore.pl?act=finish&key={rawurlencode($key)}" align="center" class="float-center">Сбросить пароль!</a>
|
<a href="http://{$_SERVER['HTTP_HOST']}/restore?act=finish&key={rawurlencode($key)}" align="center" class="float-center">Сбросить пароль!</a>
|
||||||
</center>
|
</center>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -118,8 +118,8 @@
|
||||||
<table class="callout">
|
<table class="callout">
|
||||||
<tr>
|
<tr>
|
||||||
<th class="callout-inner primary">
|
<th class="callout-inner primary">
|
||||||
<a href="http://{$_SERVER['HTTP_HOST']}/restore.pl?act=finish&key={$key}" style="color: #000; text-decoration: none;">
|
<a href="http://{$_SERVER['HTTP_HOST']}/restore?act=finish&key={$key}" style="color: #000; text-decoration: none;">
|
||||||
http://{$_SERVER['HTTP_HOST']}/restore.pl?act=finish&key={$key}
|
http://{$_SERVER['HTTP_HOST']}/restore?act=finish&key={$key}
|
||||||
</a>
|
</a>
|
||||||
</th>
|
</th>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
204
Email/verify-email.eml.latte
Executable file
204
Email/verify-email.eml.latte
Executable 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']}/regFinish?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']}/regFinish?key={$key}" style="color: #000; text-decoration: none;">
|
||||||
|
http://{$_SERVER['HTTP_HOST']}/regFinish?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>
|
||||||
|
Вы получили это письмо так как кто-то или вы зарегистрировались на инстансе OpenVK. Это не рассылка и от неё нельзя отписаться. Если вы всё равно хотите перестать получать подобные письма, деактивируйте ваш аккаунт.
|
||||||
|
</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>
|
33
README.md
33
README.md
|
@ -1,5 +1,7 @@
|
||||||
# <img align="right" src="https://github.com/openvk/openvk/raw/master/Web/static/img/logo_shadow.png" alt="openvk" title="openvk" width="15%">OpenVK
|
# <img align="right" src="https://github.com/openvk/openvk/raw/master/Web/static/img/logo_shadow.png" alt="openvk" title="openvk" width="15%">OpenVK
|
||||||
|
|
||||||
|
_[Русский](README_RU.md)_
|
||||||
|
|
||||||
**OpenVK** is an attempt to create a simple CMS that ~~cosplays~~ imitates old VK. Code provided here is not stable yet.
|
**OpenVK** is an attempt to create a simple CMS that ~~cosplays~~ imitates old VK. Code provided here is not stable yet.
|
||||||
|
|
||||||
VKontakte belongs to Pavel Durov and VK Group.
|
VKontakte belongs to Pavel Durov and VK Group.
|
||||||
|
@ -16,28 +18,37 @@ Updating the source code is done with this command: `git pull`
|
||||||
|
|
||||||
* **[openvk.su](https://openvk.su/)**
|
* **[openvk.su](https://openvk.su/)**
|
||||||
* [social.fetbuk.ru](http://social.fetbuk.ru/)
|
* [social.fetbuk.ru](http://social.fetbuk.ru/)
|
||||||
|
* [openvk.zavsc.pw](https://openvk.zavsc.pw/)
|
||||||
|
|
||||||
## Can I create my own OpenVK instance?
|
## Can I create my own OpenVK instance?
|
||||||
|
|
||||||
Yes! And you're very welcome to.
|
Yes! And you're very welcome to.
|
||||||
|
|
||||||
However, OVK makes use of Chandler Application Server. This software requires extensions, that may not be provided by your hosting provider (namely, sodium and yaml. this extensions are available on most of ISPManager hostings).
|
However, OVK makes use of Chandler Application Server. This software requires extensions, that may not be provided by your hosting provider (namely, sodium and yaml. this extensions are available on most of ISPManager hostings).
|
||||||
|
|
||||||
If you want, you can add your instance to the list above so that people can register there.
|
If you want, you can add your instance to the list above so that people can register there.
|
||||||
|
|
||||||
### Installation procedure
|
### Installation procedure
|
||||||
|
|
||||||
1. Install PHP 7, web-server, Composer, Node.js, Yarn and [Chandler](https://github.com/openvk/chandler)
|
1. Install PHP 7.4, web-server, Composer, Node.js, Yarn and [Chandler](https://github.com/openvk/chandler)
|
||||||
* PHP 8 has **not** yet been tested, so you should not expect it to work.
|
|
||||||
|
* PHP 8 has **not** yet been tested, so you should not expect it to work.
|
||||||
|
|
||||||
2. Install [commitcaptcha](https://github.com/openvk/commitcaptcha) and OpenVK as Chandler extensions like this:
|
2. Install [commitcaptcha](https://github.com/openvk/commitcaptcha) and OpenVK as Chandler extensions like this:
|
||||||
```
|
|
||||||
|
```bash
|
||||||
git clone https://github.com/openvk/openvk /path/to/chandler/extensions/available/openvk
|
git clone https://github.com/openvk/openvk /path/to/chandler/extensions/available/openvk
|
||||||
git clone https://github.com/openvk/commitcaptcha /path/to/chandler/extensions/available/commitcaptcha
|
git clone https://github.com/openvk/commitcaptcha /path/to/chandler/extensions/available/commitcaptcha
|
||||||
```
|
```
|
||||||
|
|
||||||
3. And enable them:
|
3. And enable them:
|
||||||
```
|
|
||||||
|
```bash
|
||||||
ln -s /path/to/chandler/extensions/available/commitcaptcha /path/to/chandler/extensions/enabled/
|
ln -s /path/to/chandler/extensions/available/commitcaptcha /path/to/chandler/extensions/enabled/
|
||||||
ln -s /path/to/chandler/extensions/available/openvk /path/to/chandler/extensions/enabled/
|
ln -s /path/to/chandler/extensions/available/openvk /path/to/chandler/extensions/enabled/
|
||||||
```
|
```
|
||||||
4. Import `install/init-static-db.sql` to **same database** you installed Chandler to
|
|
||||||
|
4. Import `install/init-static-db.sql` to **same database** you installed Chandler to and import all sqls from `install/sqls` to **same database**
|
||||||
5. Import `install/init-event-db.sql` to **separate database**
|
5. Import `install/init-event-db.sql` to **separate database**
|
||||||
6. Copy `openvk-example.yml` to `openvk.yml` and change options
|
6. Copy `openvk-example.yml` to `openvk.yml` and change options
|
||||||
7. Run `composer install` in OpenVK directory
|
7. Run `composer install` in OpenVK directory
|
||||||
|
@ -46,27 +57,31 @@ ln -s /path/to/chandler/extensions/available/openvk /path/to/chandler/extensions
|
||||||
10. Set `openvk` as your root app in `chandler.yml`
|
10. Set `openvk` as your root app in `chandler.yml`
|
||||||
|
|
||||||
Once you are done, you can login as a system administrator on the network itself (no registration required):
|
Once you are done, you can login as a system administrator on the network itself (no registration required):
|
||||||
|
|
||||||
* **Login**: `admin@localhost.localdomain6`
|
* **Login**: `admin@localhost.localdomain6`
|
||||||
* **Password**: `admin`
|
* **Password**: `admin`
|
||||||
* It is recommended to change the password before using the built-in account.
|
* It is recommended to change the password before using the built-in account.
|
||||||
|
|
||||||
Full example installation instruction for CentOS 8 is also available [here](docs/centos8_install.md).
|
Full example installation instruction for CentOS 8 is also available [here](https://docs.openvk.su/openvk_engine/centos8_installation/).
|
||||||
|
|
||||||
### If my website uses OpenVK, should I publish it's sources?
|
### If my website uses OpenVK, should I publish it's sources?
|
||||||
|
|
||||||
You are encouraged to do so. We don't enforce this though. You can keep your sources to yourself (unless you distribute your OpenVK distro to other people).
|
You are encouraged to do so. We don't enforce this though. You can keep your sources to yourself (unless you distribute your OpenVK distro to other people).
|
||||||
|
|
||||||
You also not required to publish source texts of your themepacks and plugins.
|
You also not required to publish source texts of your themepacks and plugins.
|
||||||
|
|
||||||
## Where can I get assistance?
|
## Where can I get assistance?
|
||||||
|
|
||||||
You may reach out to us via:
|
You may reach out to us via:
|
||||||
|
|
||||||
* [Bug-tracker](https://github.com/openvk/openvk/projects/1)
|
* [Bug-tracker](https://github.com/openvk/openvk/projects/1)
|
||||||
* [Ticketing system](https://openvk.su/support?act=new)
|
* [Ticketing system](https://openvk.su/support?act=new)
|
||||||
* Telegram chat: Go to [our channel](https://t.me/openvkch) and open discussion in our channel menu.
|
* Telegram chat: Go to [our channel](https://t.me/openvkenglish) and open discussion in our channel menu.
|
||||||
* [Reddit](https://www.reddit.com/r/openvk/)
|
* [Reddit](https://www.reddit.com/r/openvk/)
|
||||||
* [Discussions](https://github.com/openvk/openvk/discussions)
|
* [Discussions](https://github.com/openvk/openvk/discussions)
|
||||||
|
* Matrix chat: #openvk:matrix.org
|
||||||
|
|
||||||
**Attention**: bug tracker and telegram chat are public places. And ticketing system is being served by volunteers. If you need to report something, that shouldn't be immediately disclosed to general public (for instance, vulnerability report), please use contact us directly at this email: **openvk [at] tutanota [dot] com**
|
**Attention**: bug tracker, telegram and matrix chat are public places. And ticketing system is being served by volunteers. If you need to report something, that shouldn't be immediately disclosed to general public (for instance, vulnerability report), please use contact us directly at this email: **openvk [at] tutanota [dot] com**
|
||||||
|
|
||||||
<a href="https://codeberg.org/OpenVK/openvk">
|
<a href="https://codeberg.org/OpenVK/openvk">
|
||||||
<img alt="Get it on Codeberg" src="https://codeberg.org/Codeberg/GetItOnCodeberg/media/branch/main/get-it-on-blue-on-white.png" height="60">
|
<img alt="Get it on Codeberg" src="https://codeberg.org/Codeberg/GetItOnCodeberg/media/branch/main/get-it-on-blue-on-white.png" height="60">
|
||||||
|
|
87
README_RU.md
Normal file
87
README_RU.md
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
# <img align="right" src="https://github.com/openvk/openvk/raw/master/Web/static/img/logo_shadow.png" alt="openvk" title="openvk" width="15%">OpenVK
|
||||||
|
|
||||||
|
_[English](README.md)_
|
||||||
|
|
||||||
|
**OpenVK** это попытка создать простую CMS, которая ~~косплеит~~ имитирует старый ВКонтакте. Представленный здесь код пока не стабилен.
|
||||||
|
|
||||||
|
ВКонтакте принадлежит Павлу Дурову и VK Group.
|
||||||
|
|
||||||
|
Честно говоря, мы даже не знаем, работает ли она вообще. Однако, эта версия поддерживается, и мы будем рады принять ваши сообщения об ошибках [в нашем баг-трекере](https://github.com/openvk/openvk/projects/1). Вы также можете отправлять их через [вкладку "Помощь"](https://openvk.su/support?act=new) (для этого вам понадобится учетная запись OVK).
|
||||||
|
|
||||||
|
## Когда релиз?
|
||||||
|
|
||||||
|
Пожалуйста, используйте ветку master, так как в ней больше всего изменений.
|
||||||
|
|
||||||
|
Обновление исходного кода выполняется с помощью этой команды: `git pull`.
|
||||||
|
|
||||||
|
## Инстанции
|
||||||
|
|
||||||
|
* **[openvk.su](https://openvk.su/)**
|
||||||
|
* [social.fetbuk.ru](http://social.fetbuk.ru/)
|
||||||
|
* [openvk.zavsc.pw](https://openvk.zavsc.pw/)
|
||||||
|
|
||||||
|
## Могу ли я создать свою собственную инстанцию OpenVK?
|
||||||
|
|
||||||
|
Да! И всегда пожалуйста.
|
||||||
|
|
||||||
|
Однако, OVK использует Chandler Application Server. Это программное обеспечение требует расширений, которые могут быть не предоставлены вашим хостинг-провайдером (а именно, sodium и yaml. эти расширения доступны на большинстве хостингов ISPManager).
|
||||||
|
|
||||||
|
Если вы хотите, вы можете добавить вашу инстанцию в список выше, чтобы люди могли зарегистрироваться там.
|
||||||
|
|
||||||
|
### Процедура установки
|
||||||
|
|
||||||
|
1. Установите PHP 7.4, веб-сервер, Composer, Node.js, Yarn и [Chandler](https://github.com/openvk/chandler)
|
||||||
|
|
||||||
|
* PHP 8 еще **не** тестировался, поэтому не стоит ожидать, что он будет работать.
|
||||||
|
|
||||||
|
2. Установите [commitcaptcha](https://github.com/openvk/commitcaptcha) и OpenVK в качестве расширений Chandler следующим образом:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git clone https://github.com/openvk/openvk /path/to/chandler/extensions/available/openvk
|
||||||
|
git clone https://github.com/openvk/commitcaptcha /path/to/chandler/extensions/available/commitcaptcha
|
||||||
|
```
|
||||||
|
|
||||||
|
3. И включите их:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ln -s /path/to/chandler/extensions/available/commitcaptcha /path/to/chandler/extensions/enabled/
|
||||||
|
ln -s /path/to/chandler/extensions/available/openvk /path/to/chandler/extensions/enabled/
|
||||||
|
```
|
||||||
|
|
||||||
|
4. Импортируйте `install/init-static-db.sql` в **ту же базу данных**, в которую вы установили Chandler, и импортируйте все SQL файлы из папки `install/sqls` в **ту же базу данных**
|
||||||
|
5. Импортируйте `install/init-event-db.sql` в **отдельную базу данных**
|
||||||
|
6. Скопируйте `openvk-example.yml` в `openvk.yml` и измените параметры
|
||||||
|
7. Запустите `composer install` в директории OpenVK
|
||||||
|
8. Перейдите в `Web/static/js` и выполните `yarn install`
|
||||||
|
9. Установите `openvk` в качестве корневого приложения в файле `chandler.yml`
|
||||||
|
|
||||||
|
После этого вы можете войти как системный администратор в саму сеть (регистрация не требуется):
|
||||||
|
|
||||||
|
* **Логин**: `admin@localhost.localdomain6`
|
||||||
|
* **Пароль**: `admin`
|
||||||
|
* Перед использованием встроенной учетной записи рекомендуется сменить пароль.
|
||||||
|
|
||||||
|
Полный пример инструкции по установке CentOS 8 также доступен [здесь](https://docs.openvk.su/openvk_engine/centos8_installation/).
|
||||||
|
|
||||||
|
### Если мой сайт использует OpenVK, должен ли я публиковать его исходные тексты?
|
||||||
|
|
||||||
|
Вам рекомендуется это делать. Однако мы не следим за этим. Вы можете держать свои исходные тексты при себе (если только вы не распространяете свой дистрибутив OpenVK среди других людей).
|
||||||
|
|
||||||
|
Вы также не обязаны публиковать исходные тексты ваших тематических пакетов и плагинов.
|
||||||
|
|
||||||
|
## Где я могу получить помощь?
|
||||||
|
|
||||||
|
Вы можете связаться с нами через:
|
||||||
|
|
||||||
|
* [Баг-трекер](https://github.com/openvk/openvk/projects/1)
|
||||||
|
* [Помощь в OVK](https://openvk.su/support?act=new)
|
||||||
|
* Telegram-чат: Перейдите на [наш канал](https://t.me/openvkch) и откройте обсуждение в меню нашего канала.
|
||||||
|
* [Reddit](https://www.reddit.com/r/openvk/)
|
||||||
|
* [Обсуждения](https://github.com/openvk/openvk/discussions)
|
||||||
|
* Чат в Matrix: #ovk:matrix.org
|
||||||
|
|
||||||
|
**Внимание**: баг-трекер, телеграм- и matrix-чат являются публичными местами, и жалобы в OVK обслуживается волонтерами. Если вам нужно сообщить о чем-то, что не должно быть раскрыто широкой публике (например, сообщение об уязвимости), пожалуйста, свяжитесь с нами напрямую по этому адресу: **openvk [at] tutanota [dot] com**.
|
||||||
|
|
||||||
|
<a href="https://codeberg.org/OpenVK/openvk">
|
||||||
|
<img alt="Get it on Codeberg" src="https://codeberg.org/Codeberg/GetItOnCodeberg/media/branch/main/get-it-on-blue-on-white.png" height="60">
|
||||||
|
</a>
|
|
@ -110,7 +110,7 @@ final class Wall extends VKAPIRequestHandler
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
function post(string $owner_id, string $message, int $from_group = 0, int $signed = 0): object
|
function post(string $owner_id, string $message = "", int $from_group = 0, int $signed = 0): object
|
||||||
{
|
{
|
||||||
$this->requireUser();
|
$this->requireUser();
|
||||||
|
|
||||||
|
@ -130,12 +130,46 @@ final class Wall extends VKAPIRequestHandler
|
||||||
|
|
||||||
if($canPost == false) $this->fail(15, "Access denied");
|
if($canPost == false) $this->fail(15, "Access denied");
|
||||||
|
|
||||||
|
$anon = OPENVK_ROOT_CONF["openvk"]["preferences"]["wall"]["anonymousPosting"]["enable"];
|
||||||
|
if($wallOwner instanceof Club && $from_group == 1 && $signed != 1 && $anon) {
|
||||||
|
$manager = $wallOwner->getManager($this->getUser());
|
||||||
|
if($manager)
|
||||||
|
$anon = $manager->isHidden();
|
||||||
|
elseif($this->getUser()->getId() === $wallOwner->getOwner()->getId())
|
||||||
|
$anon = $wallOwner->isOwnerHidden();
|
||||||
|
} else {
|
||||||
|
$anon = false;
|
||||||
|
}
|
||||||
|
|
||||||
$flags = 0;
|
$flags = 0;
|
||||||
if($from_group == 1)
|
if($from_group == 1 && $wallOwner instanceof Club && $wallOwner->canBeModifiedBy($this->getUser()))
|
||||||
$flags |= 0b10000000;
|
$flags |= 0b10000000;
|
||||||
if($signed == 1)
|
if($signed == 1)
|
||||||
$flags |= 0b01000000;
|
$flags |= 0b01000000;
|
||||||
|
|
||||||
|
// TODO: Compatible implementation of this
|
||||||
|
try {
|
||||||
|
$photo = null;
|
||||||
|
$video = null;
|
||||||
|
if($_FILES["photo"]["error"] === UPLOAD_ERR_OK) {
|
||||||
|
$album = null;
|
||||||
|
if(!$anon && $owner_id > 0 && $owner_id === $this->getUser()->getId())
|
||||||
|
$album = (new AlbumsRepo)->getUserWallAlbum($wallOwner);
|
||||||
|
|
||||||
|
$photo = Photo::fastMake($this->getUser()->getId(), $message, $_FILES["photo"], $album, $anon);
|
||||||
|
}
|
||||||
|
|
||||||
|
if($_FILES["video"]["error"] === UPLOAD_ERR_OK)
|
||||||
|
$video = Video::fastMake($this->getUser()->getId(), $message, $_FILES["video"], $anon);
|
||||||
|
} catch(\DomainException $ex) {
|
||||||
|
$this->fail(-156, "The media file is corrupted");
|
||||||
|
} catch(ISE $ex) {
|
||||||
|
$this->fail(-156, "The media file is corrupted or too large ");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(empty($message) && !$photo && !$video)
|
||||||
|
$this->fail(100, "Required parameter 'message' missing.");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$post = new Post;
|
$post = new Post;
|
||||||
$post->setOwner($this->getUser()->getId());
|
$post->setOwner($this->getUser()->getId());
|
||||||
|
@ -148,6 +182,12 @@ final class Wall extends VKAPIRequestHandler
|
||||||
$this->fail(100, "One of the parameters specified was missing or invalid");
|
$this->fail(100, "One of the parameters specified was missing or invalid");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(!is_null($photo))
|
||||||
|
$post->attach($photo);
|
||||||
|
|
||||||
|
if(!is_null($video))
|
||||||
|
$post->attach($video);
|
||||||
|
|
||||||
if($wall > 0 && $wall !== $this->user->identity->getId())
|
if($wall > 0 && $wall !== $this->user->identity->getId())
|
||||||
(new WallPostNotification($wallOwner, $post, $this->user->identity))->emit();
|
(new WallPostNotification($wallOwner, $post, $this->user->identity))->emit();
|
||||||
|
|
||||||
|
|
|
@ -40,7 +40,7 @@ class Club extends RowModel
|
||||||
|
|
||||||
function getAvatarUrl(): string
|
function getAvatarUrl(): string
|
||||||
{
|
{
|
||||||
$serverUrl = ovk_scheme(true) . $_SERVER["SERVER_NAME"];
|
$serverUrl = ovk_scheme(true) . $_SERVER["HTTP_HOST"];
|
||||||
$avPhoto = $this->getAvatarPhoto();
|
$avPhoto = $this->getAvatarPhoto();
|
||||||
|
|
||||||
return is_null($avPhoto) ? "$serverUrl/assets/packages/static/openvk/img/camera_200.png" : $avPhoto->getURL();
|
return is_null($avPhoto) ? "$serverUrl/assets/packages/static/openvk/img/camera_200.png" : $avPhoto->getURL();
|
||||||
|
@ -64,16 +64,6 @@ class Club extends RowModel
|
||||||
else
|
else
|
||||||
return "/club" . $this->getId();
|
return "/club" . $this->getId();
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
function getAvatarUrl(): string
|
|
||||||
{
|
|
||||||
$avAlbum = (new Albums)->getUserAvatarAlbum($this);
|
|
||||||
$avCount = $avAlbum->getPhotosCount();
|
|
||||||
$avPhotos = $avAlbum->getPhotos($avCount, 1);
|
|
||||||
$avPhoto = iterator_to_array($avPhotos)[0] ?? NULL;
|
|
||||||
|
|
||||||
return is_null($avPhoto) ? "/assets/packages/static/openvk/img/camera_200.png" : $avPhoto->getURL();
|
|
||||||
} */
|
|
||||||
|
|
||||||
function getName(): string
|
function getName(): string
|
||||||
{
|
{
|
||||||
|
@ -140,6 +130,11 @@ class Club extends RowModel
|
||||||
return (bool) $this->getRecord()->display_topics_above_wall;
|
return (bool) $this->getRecord()->display_topics_above_wall;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isHideFromGlobalFeedEnabled(): bool
|
||||||
|
{
|
||||||
|
return (bool) $this->getRecord()->hide_from_global_feed;
|
||||||
|
}
|
||||||
|
|
||||||
function getType(): int
|
function getType(): int
|
||||||
{
|
{
|
||||||
return $this->getRecord()->type;
|
return $this->getRecord()->type;
|
||||||
|
|
10
Web/Models/Entities/EmailVerification.php
Executable file
10
Web/Models/Entities/EmailVerification.php
Executable file
|
@ -0,0 +1,10 @@
|
||||||
|
<?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 EmailVerification extends PasswordReset
|
||||||
|
{
|
||||||
|
protected $tableName = "email_verifications";
|
||||||
|
}
|
|
@ -94,4 +94,9 @@ class Note extends Postable
|
||||||
|
|
||||||
return $cached;
|
return $cached;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getSource(): string
|
||||||
|
{
|
||||||
|
return $this->getRecord()->source;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,12 +34,15 @@ class PasswordReset extends RowModel
|
||||||
*/
|
*/
|
||||||
function isNew(): bool
|
function isNew(): bool
|
||||||
{
|
{
|
||||||
return $this->getRecord()->timestamp > (time() - 301);
|
return $this->getRecord()->timestamp > (time() - (5 * MINUTE));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Token is valid only for 3 days.
|
||||||
|
*/
|
||||||
function isStillValid(): bool
|
function isStillValid(): bool
|
||||||
{
|
{
|
||||||
return $this->getRecord()->timestamp > (time() - 172801);
|
return $this->getRecord()->timestamp > (time() - (3 * DAY));
|
||||||
}
|
}
|
||||||
|
|
||||||
function verify(string $token): bool
|
function verify(string $token): bool
|
||||||
|
|
|
@ -127,5 +127,10 @@ class TicketComment extends RowModel
|
||||||
return $mark === 1;
|
return $mark === 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isDeleted(): bool
|
||||||
|
{
|
||||||
|
return (bool) $this->getRecord()->deleted;
|
||||||
|
}
|
||||||
|
|
||||||
use Traits\TRichText;
|
use Traits\TRichText;
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,10 +32,12 @@ trait TRichText
|
||||||
private function formatLinks(string &$text): string
|
private function formatLinks(string &$text): string
|
||||||
{
|
{
|
||||||
return preg_replace_callback(
|
return preg_replace_callback(
|
||||||
"%(([A-z]++):\/\/(\S*?\.\S*?))([\s)\[\]{},;\"\'<]|\.\s|$)%",
|
"%(([A-z]++):\/\/(\S*?\.\S*?))([\s)\[\]{},\"\'<]|\.\s|$)%",
|
||||||
(function (array $matches): string {
|
(function (array $matches): string {
|
||||||
$href = str_replace("#", "#", $matches[1]);
|
$href = str_replace("#", "#", $matches[1]);
|
||||||
|
$href = str_replace(";", ";", $matches[1]);
|
||||||
$link = str_replace("#", "#", $matches[3]);
|
$link = str_replace("#", "#", $matches[3]);
|
||||||
|
$link = str_replace(";", ";", $matches[3]);
|
||||||
$rel = $this->isAd() ? "sponsored" : "ugc";
|
$rel = $this->isAd() ? "sponsored" : "ugc";
|
||||||
|
|
||||||
return "<a href='$href' rel='$rel' target='_blank'>$link</a>" . htmlentities($matches[4]);
|
return "<a href='$href' rel='$rel' target='_blank'>$link</a>" . htmlentities($matches[4]);
|
||||||
|
|
|
@ -5,6 +5,7 @@ use openvk\Web\Util\DateTime;
|
||||||
use openvk\Web\Models\RowModel;
|
use openvk\Web\Models\RowModel;
|
||||||
use openvk\Web\Models\Entities\{Photo, Message, Correspondence, Gift};
|
use openvk\Web\Models\Entities\{Photo, Message, Correspondence, Gift};
|
||||||
use openvk\Web\Models\Repositories\{Users, Clubs, Albums, Gifts, Notifications};
|
use openvk\Web\Models\Repositories\{Users, Clubs, Albums, Gifts, Notifications};
|
||||||
|
use openvk\Web\Models\Exceptions\InvalidUserNameException;
|
||||||
use Nette\Database\Table\ActiveRow;
|
use Nette\Database\Table\ActiveRow;
|
||||||
use Chandler\Database\DatabaseConnection;
|
use Chandler\Database\DatabaseConnection;
|
||||||
use Chandler\Security\User as ChandlerUser;
|
use Chandler\Security\User as ChandlerUser;
|
||||||
|
@ -111,7 +112,7 @@ class User extends RowModel
|
||||||
|
|
||||||
function getAvatarUrl(bool $nullForDel = false): ?string
|
function getAvatarUrl(bool $nullForDel = false): ?string
|
||||||
{
|
{
|
||||||
$serverUrl = ovk_scheme(true) . $_SERVER["SERVER_NAME"];
|
$serverUrl = ovk_scheme(true) . $_SERVER["HTTP_HOST"];
|
||||||
|
|
||||||
if($this->getRecord()->deleted)
|
if($this->getRecord()->deleted)
|
||||||
return $nullForDel ? null : "$serverUrl/assets/packages/static/openvk/img/camera_200.png";
|
return $nullForDel ? null : "$serverUrl/assets/packages/static/openvk/img/camera_200.png";
|
||||||
|
@ -362,6 +363,7 @@ class User extends RowModel
|
||||||
"groups",
|
"groups",
|
||||||
"news",
|
"news",
|
||||||
"links",
|
"links",
|
||||||
|
"poster",
|
||||||
],
|
],
|
||||||
])->get($id);
|
])->get($id);
|
||||||
}
|
}
|
||||||
|
@ -380,6 +382,7 @@ class User extends RowModel
|
||||||
"friends.read",
|
"friends.read",
|
||||||
"friends.add",
|
"friends.add",
|
||||||
"wall.write",
|
"wall.write",
|
||||||
|
"messages.write",
|
||||||
],
|
],
|
||||||
])->get($id);
|
])->get($id);
|
||||||
}
|
}
|
||||||
|
@ -745,6 +748,27 @@ class User extends RowModel
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function setFirst_Name(string $firstName): void
|
||||||
|
{
|
||||||
|
$firstName = mb_convert_case($firstName, MB_CASE_TITLE);
|
||||||
|
if(!preg_match('%^\p{Lu}\p{Mn}?(?:\p{L&}\p{Mn}?){1,16}$%u', $firstName))
|
||||||
|
throw new InvalidUserNameException;
|
||||||
|
|
||||||
|
$this->stateChanges("first_name", $firstName);
|
||||||
|
}
|
||||||
|
|
||||||
|
function setLast_Name(string $lastName): void
|
||||||
|
{
|
||||||
|
if(!empty($lastName))
|
||||||
|
{
|
||||||
|
$lastName = mb_convert_case($lastName, MB_CASE_TITLE);
|
||||||
|
if(!preg_match('%^\p{Lu}\p{Mn}?(\p{L&}\p{Mn}?){1,16}(\-\g<1>+)?$%u', $lastName))
|
||||||
|
throw new InvalidUserNameException;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->stateChanges("last_name", $lastName);
|
||||||
|
}
|
||||||
|
|
||||||
function setNsfwTolerance(int $tolerance): void
|
function setNsfwTolerance(int $tolerance): void
|
||||||
{
|
{
|
||||||
$this->stateChanges("nsfw_tolerance", $tolerance);
|
$this->stateChanges("nsfw_tolerance", $tolerance);
|
||||||
|
@ -764,6 +788,7 @@ class User extends RowModel
|
||||||
"friends.read",
|
"friends.read",
|
||||||
"friends.add",
|
"friends.add",
|
||||||
"wall.write",
|
"wall.write",
|
||||||
|
"messages.write",
|
||||||
],
|
],
|
||||||
])->set($id, $status)->toInteger());
|
])->set($id, $status)->toInteger());
|
||||||
}
|
}
|
||||||
|
@ -780,6 +805,7 @@ class User extends RowModel
|
||||||
"groups",
|
"groups",
|
||||||
"news",
|
"news",
|
||||||
"links",
|
"links",
|
||||||
|
"poster",
|
||||||
],
|
],
|
||||||
])->set($id, (int) $status)->toInteger();
|
])->set($id, (int) $status)->toInteger();
|
||||||
|
|
||||||
|
@ -854,10 +880,10 @@ class User extends RowModel
|
||||||
|
|
||||||
function isDeleted(): bool
|
function isDeleted(): bool
|
||||||
{
|
{
|
||||||
if ($this->getRecord()->deleted == 1)
|
if ($this->getRecord()->deleted == 1)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
else
|
else
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -887,5 +913,11 @@ class User extends RowModel
|
||||||
return $this->getRecord()->website;
|
return $this->getRecord()->website;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ты устрица
|
||||||
|
function isActivated(): bool
|
||||||
|
{
|
||||||
|
return (bool) $this->getRecord()->activated;
|
||||||
|
}
|
||||||
|
|
||||||
use Traits\TSubscribable;
|
use Traits\TSubscribable;
|
||||||
}
|
}
|
||||||
|
|
7
Web/Models/Exceptions/InvalidUserNameException.php
Normal file
7
Web/Models/Exceptions/InvalidUserNameException.php
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
<?php declare(strict_types=1);
|
||||||
|
namespace openvk\Web\Models\Exceptions;
|
||||||
|
|
||||||
|
final class InvalidUserNameException extends \UnexpectedValueException
|
||||||
|
{
|
||||||
|
protected $message = "Invalid real name supplied";
|
||||||
|
}
|
|
@ -38,5 +38,23 @@ class Clubs
|
||||||
return new Util\EntityStream("Club", $result);
|
return new Util\EntityStream("Club", $result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getCount(): int
|
||||||
|
{
|
||||||
|
return sizeof(clone $this->clubs);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getPopularClubs(): \Traversable
|
||||||
|
{
|
||||||
|
$query = "SELECT ROW_NUMBER() OVER (ORDER BY `subscriptions` DESC) as `place`, `target` as `id`, COUNT(`follower`) as `subscriptions` FROM `subscriptions` WHERE `model` = \"openvk\\\Web\\\Models\\\Entities\\\Club\" GROUP BY `target` ORDER BY `subscriptions` DESC, `id` LIMIT 10;";
|
||||||
|
$entries = DatabaseConnection::i()->getConnection()->query($query);
|
||||||
|
|
||||||
|
foreach($entries as $entry)
|
||||||
|
yield (object) [
|
||||||
|
"place" => $entry["place"],
|
||||||
|
"club" => $this->get($entry["id"]),
|
||||||
|
"subscriptions" => $entry["subscriptions"],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
use \Nette\SmartObject;
|
use \Nette\SmartObject;
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,7 +37,7 @@ class Notifications
|
||||||
if(!$count) {
|
if(!$count) {
|
||||||
$query .= " ORDER BY timestamp DESC";
|
$query .= " ORDER BY timestamp DESC";
|
||||||
$query .= " LIMIT " . ($perPage ?? OPENVK_DEFAULT_PER_PAGE);
|
$query .= " LIMIT " . ($perPage ?? OPENVK_DEFAULT_PER_PAGE);
|
||||||
$query .= " OFFSET " . ((($page - 1) * $perPage) ?? OPENVK_DEFAULT_PER_PAGE);
|
$query .= " OFFSET " . (($page - 1) * ($perPage ?? OPENVK_DEFAULT_PER_PAGE));
|
||||||
}
|
}
|
||||||
|
|
||||||
return $query;
|
return $query;
|
||||||
|
|
|
@ -106,8 +106,8 @@ class Posts
|
||||||
return sizeof($this->posts->where(["wall" => $user, "deleted" => 0]));
|
return sizeof($this->posts->where(["wall" => $user, "deleted" => 0]));
|
||||||
}
|
}
|
||||||
|
|
||||||
function getCountOfAllPosts(): int
|
function getCount(): int
|
||||||
{
|
{
|
||||||
return sizeof($this->posts->where(["deleted" => 0]));
|
return sizeof(clone $this->posts);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,6 @@ namespace openvk\Web\Models\Repositories;
|
||||||
// use openvk\Web\Models\Entities\User;
|
// use openvk\Web\Models\Entities\User;
|
||||||
// use openvk\Web\Models\Repositories\Users;
|
// use openvk\Web\Models\Repositories\Users;
|
||||||
use openvk\Web\Models\Entities\TicketComment;
|
use openvk\Web\Models\Entities\TicketComment;
|
||||||
use Nette\Database\Table\ActiveRow;
|
|
||||||
use Chandler\Database\DatabaseConnection;
|
use Chandler\Database\DatabaseConnection;
|
||||||
|
|
||||||
class TicketComments
|
class TicketComments
|
||||||
|
@ -20,7 +19,7 @@ class TicketComments
|
||||||
|
|
||||||
function getCommentsById(int $ticket_id): \Traversable
|
function getCommentsById(int $ticket_id): \Traversable
|
||||||
{
|
{
|
||||||
foreach($this->comments->where(['ticket_id' => $ticket_id]) as $comment) yield new TicketComment($comment);
|
foreach($this->comments->where(['ticket_id' => $ticket_id, 'deleted' => 0]) as $comment) yield new TicketComment($comment);
|
||||||
}
|
}
|
||||||
|
|
||||||
// private function toTicket(?ActiveRow $ar): ?Ticket
|
// private function toTicket(?ActiveRow $ar): ?Ticket
|
||||||
|
|
|
@ -22,8 +22,8 @@ class Tickets
|
||||||
|
|
||||||
function getTickets(int $state = 0, int $page = 1): \Traversable
|
function getTickets(int $state = 0, int $page = 1): \Traversable
|
||||||
{
|
{
|
||||||
foreach($this->tickets->where(["deleted" => 0, "type" => $state])->order("created DESC")->page($page, OPENVK_DEFAULT_PER_PAGE) as $t)
|
foreach($this->tickets->where(["deleted" => 0, "type" => $state])->order("created DESC")->page($page, OPENVK_DEFAULT_PER_PAGE) as $ticket)
|
||||||
yield new Ticket($t);
|
yield new Ticket($ticket);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getTicketCount(int $state = 0): int
|
function getTicketCount(int $state = 0): int
|
||||||
|
@ -31,21 +31,23 @@ class Tickets
|
||||||
return sizeof($this->tickets->where(["deleted" => 0, "type" => $state]));
|
return sizeof($this->tickets->where(["deleted" => 0, "type" => $state]));
|
||||||
}
|
}
|
||||||
|
|
||||||
function getTicketsByuId(int $user_id): \Traversable
|
function getTicketsByUserId(int $userId, int $page = 1): \Traversable
|
||||||
{
|
{
|
||||||
foreach($this->tickets->where(['user_id' => $user_id, 'deleted' => 0])->order("created DESC") as $ticket) yield new Ticket($ticket);
|
foreach($this->tickets->where(["user_id" => $userId, "deleted" => 0])->order("created DESC")->page($page, OPENVK_DEFAULT_PER_PAGE) as $ticket) yield new Ticket($ticket);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getTicketsCountByuId(int $user_id, int $type = 0): int
|
function getTicketsCountByUserId(int $userId, int $type = NULL): int
|
||||||
{
|
{
|
||||||
return sizeof($this->tickets->where(['user_id' => $user_id, 'deleted' => 0, 'type' => $type]));
|
if(is_null($type))
|
||||||
|
return sizeof($this->tickets->where(["user_id" => $userId, "deleted" => 0]));
|
||||||
|
else
|
||||||
|
return sizeof($this->tickets->where(["user_id" => $userId, "deleted" => 0, "type" => $type]));
|
||||||
}
|
}
|
||||||
|
|
||||||
function getRequestById(int $req_id): ?Ticket
|
function getRequestById(int $requestId): ?Ticket
|
||||||
{
|
{
|
||||||
$requests = $this->tickets->where(['id' => $req_id])->fetch();
|
$requests = $this->tickets->where(["id" => $requestId])->fetch();
|
||||||
if(!is_null($requests))
|
if(!is_null($requests))
|
||||||
|
|
||||||
return new Req($requests);
|
return new Req($requests);
|
||||||
else
|
else
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -51,7 +51,7 @@ class Users
|
||||||
function find(string $query): Util\EntityStream
|
function find(string $query): Util\EntityStream
|
||||||
{
|
{
|
||||||
$query = "%$query%";
|
$query = "%$query%";
|
||||||
$result = $this->users->where("CONCAT_WS(' ', first_name, last_name) LIKE ?", $query);
|
$result = $this->users->where("CONCAT_WS(' ', first_name, last_name) LIKE ?", $query)->where("deleted", 0);
|
||||||
|
|
||||||
return new Util\EntityStream("User", $result);
|
return new Util\EntityStream("User", $result);
|
||||||
}
|
}
|
||||||
|
@ -84,5 +84,23 @@ class Users
|
||||||
return $this->getByShortUrl($address);
|
return $this->getByShortUrl($address);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If you need to check if the user is an instance administrator, use `$user->getChandlerUser()->can("access")->model("admin")->whichBelongsTo(NULL)`.
|
||||||
|
* This method is more suitable for instance administrators lists
|
||||||
|
*/
|
||||||
|
function getInstanceAdmins(bool $excludeHidden = true): \Traversable
|
||||||
|
{
|
||||||
|
$query = "SELECT DISTINCT(`profiles`.`id`) FROM `ChandlerACLRelations` JOIN `profiles` ON `ChandlerACLRelations`.`user` = `profiles`.`user` COLLATE utf8mb4_unicode_520_ci WHERE `ChandlerACLRelations`.`group` IN (SELECT `group` FROM `ChandlerACLGroupsPermissions` WHERE `model` = \"admin\" AND `permission` = \"access\")";
|
||||||
|
|
||||||
|
if($excludeHidden)
|
||||||
|
$query .= " AND `ChandlerACLRelations`.`user` NOT IN (SELECT `user` FROM `ChandlerACLRelations` WHERE `group` IN (SELECT `group` FROM `ChandlerACLGroupsPermissions` WHERE `model` = \"hidden_admin\" AND `permission` = \"be\"))";
|
||||||
|
|
||||||
|
$query .= " ORDER BY `profiles`.`id`;";
|
||||||
|
|
||||||
|
$result = DatabaseConnection::i()->getConnection()->query($query);
|
||||||
|
foreach($result as $entry)
|
||||||
|
yield $this->get($entry->id);
|
||||||
|
}
|
||||||
|
|
||||||
use \Nette\SmartObject;
|
use \Nette\SmartObject;
|
||||||
}
|
}
|
||||||
|
|
33
Web/Models/Repositories/Verifications.php
Executable file
33
Web/Models/Repositories/Verifications.php
Executable file
|
@ -0,0 +1,33 @@
|
||||||
|
<?php declare(strict_types=1);
|
||||||
|
namespace openvk\Web\Models\Repositories;
|
||||||
|
use Chandler\Database\DatabaseConnection;
|
||||||
|
use openvk\Web\Models\Entities\EmailVerification;
|
||||||
|
use openvk\Web\Models\Entities\User;
|
||||||
|
use Nette\Database\Table\ActiveRow;
|
||||||
|
|
||||||
|
class Verifications
|
||||||
|
{
|
||||||
|
private $context;
|
||||||
|
private $verifications;
|
||||||
|
|
||||||
|
function __construct()
|
||||||
|
{
|
||||||
|
$this->context = DatabaseConnection::i()->getContext();
|
||||||
|
$this->verifications = $this->context->table("email_verifications");
|
||||||
|
}
|
||||||
|
|
||||||
|
function toEmailVerification(?ActiveRow $ar): ?EmailVerification
|
||||||
|
{
|
||||||
|
return is_null($ar) ? NULL : new EmailVerification($ar);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getByToken(string $token): ?EmailVerification
|
||||||
|
{
|
||||||
|
return $this->toEmailVerification($this->verifications->where("key", $token)->fetch());
|
||||||
|
}
|
||||||
|
|
||||||
|
function getLatestByUser(User $user): ?EmailVerification
|
||||||
|
{
|
||||||
|
return $this->toEmailVerification($this->verifications->where("profile", $user->getId())->order("timestamp DESC")->fetch());
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,7 +5,7 @@ final class YouTubeVideoDriver extends VideoDriver
|
||||||
{
|
{
|
||||||
function getThumbnailURL(): string
|
function getThumbnailURL(): string
|
||||||
{
|
{
|
||||||
return "https://img.youtube.com/vi/$this->id/mq3.jpg";
|
return "https://img.youtube.com/vi/$this->id/mqdefault.jpg";
|
||||||
}
|
}
|
||||||
|
|
||||||
function getURL(): string
|
function getURL(): string
|
||||||
|
|
|
@ -1,13 +1,14 @@
|
||||||
<?php declare(strict_types=1);
|
<?php declare(strict_types=1);
|
||||||
namespace openvk\Web\Presenters;
|
namespace openvk\Web\Presenters;
|
||||||
use openvk\Web\Themes\Themepacks;
|
use openvk\Web\Themes\Themepacks;
|
||||||
use openvk\Web\Models\Repositories\{Users, Managers};
|
use openvk\Web\Models\Repositories\{Users, Managers, Clubs, Posts};
|
||||||
use openvk\Web\Util\Localizator;
|
use openvk\Web\Util\Localizator;
|
||||||
use Chandler\Session\Session;
|
use Chandler\Session\Session;
|
||||||
|
|
||||||
final class AboutPresenter extends OpenVKPresenter
|
final class AboutPresenter extends OpenVKPresenter
|
||||||
{
|
{
|
||||||
protected $banTolerant = true;
|
protected $banTolerant = true;
|
||||||
|
protected $activationTolerant = true;
|
||||||
|
|
||||||
function renderIndex(): void
|
function renderIndex(): void
|
||||||
{
|
{
|
||||||
|
@ -58,6 +59,15 @@ final class AboutPresenter extends OpenVKPresenter
|
||||||
$this->template->languages = getLanguages();
|
$this->template->languages = getLanguages();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function renderAboutInstance(): void
|
||||||
|
{
|
||||||
|
$this->template->usersStats = (new Users)->getStatistics();
|
||||||
|
$this->template->clubsCount = (new Clubs)->getCount();
|
||||||
|
$this->template->postsCount = (new Posts)->getCount();
|
||||||
|
$this->template->popularClubs = iterator_to_array((new Clubs)->getPopularClubs());
|
||||||
|
$this->template->admins = iterator_to_array((new Users)->getInstanceAdmins());
|
||||||
|
}
|
||||||
|
|
||||||
function renderLanguage(): void
|
function renderLanguage(): void
|
||||||
{
|
{
|
||||||
$this->template->languages = getLanguages();
|
$this->template->languages = getLanguages();
|
||||||
|
@ -83,4 +93,37 @@ final class AboutPresenter extends OpenVKPresenter
|
||||||
{
|
{
|
||||||
$this->template->languages = getLanguages();
|
$this->template->languages = getLanguages();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function renderRobotsTxt(): void
|
||||||
|
{
|
||||||
|
$text = "# robots.txt file for openvk\n"
|
||||||
|
. "#\n"
|
||||||
|
. "# this includes only those links that are not in any way\n"
|
||||||
|
. "# covered from unauthorized persons (for example, due to\n"
|
||||||
|
. "# lack of rights to access the admin panel)\n\n"
|
||||||
|
. "User-Agent: *\n"
|
||||||
|
. "Disallow: /rpc\n"
|
||||||
|
. "Disallow: /language\n"
|
||||||
|
. "Disallow: /badbrowser.php\n"
|
||||||
|
. "Disallow: /logout\n"
|
||||||
|
. "Disallow: /away.php\n"
|
||||||
|
. "Disallow: /im?\n"
|
||||||
|
. "Disallow: *query=\n"
|
||||||
|
. "Disallow: *?lg=\n"
|
||||||
|
. "Disallow: *hash=\n"
|
||||||
|
. "Disallow: *?jReturnTo=\n"
|
||||||
|
. "Disallow: /method/*\n"
|
||||||
|
. "Disallow: /token*";
|
||||||
|
header("Content-Type: text/plain");
|
||||||
|
exit($text);
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderHumansTxt(): void
|
||||||
|
{
|
||||||
|
// :D
|
||||||
|
|
||||||
|
header("HTTP/1.1 302 Found");
|
||||||
|
header("Location: https://github.com/openvk/openvk#readme");
|
||||||
|
exit;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,6 +72,8 @@ final class AdminPresenter extends OpenVKPresenter
|
||||||
$user->setStatus($this->postParam("status"));
|
$user->setStatus($this->postParam("status"));
|
||||||
$user->setVerified(empty($this->postParam("verify") ? 0 : 1));
|
$user->setVerified(empty($this->postParam("verify") ? 0 : 1));
|
||||||
if($user->onlineStatus() != $this->postParam("online")) $user->setOnline(intval($this->postParam("online")));
|
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->save();
|
$user->save();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -107,6 +109,7 @@ final class AdminPresenter extends OpenVKPresenter
|
||||||
$club->setAbout($this->postParam("about"));
|
$club->setAbout($this->postParam("about"));
|
||||||
$club->setShortCode($this->postParam("shortcode"));
|
$club->setShortCode($this->postParam("shortcode"));
|
||||||
$club->setVerified(empty($this->postParam("verify") ? 0 : 1));
|
$club->setVerified(empty($this->postParam("verify") ? 0 : 1));
|
||||||
|
$club->setHide_From_Global_Feed(empty($this->postParam("hide_from_global_feed") ? 0 : 1));
|
||||||
$club->save();
|
$club->save();
|
||||||
break;
|
break;
|
||||||
case "ban":
|
case "ban":
|
||||||
|
|
|
@ -3,9 +3,11 @@ namespace openvk\Web\Presenters;
|
||||||
use openvk\Web\Models\Entities\IP;
|
use openvk\Web\Models\Entities\IP;
|
||||||
use openvk\Web\Models\Entities\User;
|
use openvk\Web\Models\Entities\User;
|
||||||
use openvk\Web\Models\Entities\PasswordReset;
|
use openvk\Web\Models\Entities\PasswordReset;
|
||||||
|
use openvk\Web\Models\Entities\EmailVerification;
|
||||||
use openvk\Web\Models\Repositories\IPs;
|
use openvk\Web\Models\Repositories\IPs;
|
||||||
use openvk\Web\Models\Repositories\Users;
|
use openvk\Web\Models\Repositories\Users;
|
||||||
use openvk\Web\Models\Repositories\Restores;
|
use openvk\Web\Models\Repositories\Restores;
|
||||||
|
use openvk\Web\Models\Repositories\Verifications;
|
||||||
use openvk\Web\Util\Validator;
|
use openvk\Web\Util\Validator;
|
||||||
use Chandler\Session\Session;
|
use Chandler\Session\Session;
|
||||||
use Chandler\Security\User as ChandlerUser;
|
use Chandler\Security\User as ChandlerUser;
|
||||||
|
@ -16,19 +18,22 @@ use lfkeitel\phptotp\{Base32, Totp};
|
||||||
final class AuthPresenter extends OpenVKPresenter
|
final class AuthPresenter extends OpenVKPresenter
|
||||||
{
|
{
|
||||||
protected $banTolerant = true;
|
protected $banTolerant = true;
|
||||||
|
protected $activationTolerant = true;
|
||||||
|
|
||||||
private $authenticator;
|
private $authenticator;
|
||||||
private $db;
|
private $db;
|
||||||
private $users;
|
private $users;
|
||||||
private $restores;
|
private $restores;
|
||||||
|
private $verifications;
|
||||||
|
|
||||||
function __construct(Users $users, Restores $restores)
|
function __construct(Users $users, Restores $restores, Verifications $verifications)
|
||||||
{
|
{
|
||||||
$this->authenticator = Authenticator::i();
|
$this->authenticator = Authenticator::i();
|
||||||
$this->db = DatabaseConnection::i()->getContext();
|
$this->db = DatabaseConnection::i()->getContext();
|
||||||
|
|
||||||
$this->users = $users;
|
$this->users = $users;
|
||||||
$this->restores = $restores;
|
$this->restores = $restores;
|
||||||
|
$this->verifications = $verifications;
|
||||||
|
|
||||||
parent::__construct();
|
parent::__construct();
|
||||||
}
|
}
|
||||||
|
@ -96,6 +101,7 @@ final class AuthPresenter extends OpenVKPresenter
|
||||||
$user->setSince(date("Y-m-d H:i:s"));
|
$user->setSince(date("Y-m-d H:i:s"));
|
||||||
$user->setRegistering_Ip(CONNECTING_IP);
|
$user->setRegistering_Ip(CONNECTING_IP);
|
||||||
$user->setBirthday(strtotime($this->postParam("birthday")));
|
$user->setBirthday(strtotime($this->postParam("birthday")));
|
||||||
|
$user->setActivated((int) !OPENVK_ROOT_CONF['openvk']['preferences']['security']['requireEmail']);
|
||||||
$user->save();
|
$user->save();
|
||||||
|
|
||||||
if(!is_null($referer)) {
|
if(!is_null($referer)) {
|
||||||
|
@ -103,6 +109,18 @@ final class AuthPresenter extends OpenVKPresenter
|
||||||
$referer->toggleSubscription($user);
|
$referer->toggleSubscription($user);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (OPENVK_ROOT_CONF['openvk']['preferences']['security']['requireEmail']) {
|
||||||
|
$verification = new EmailVerification;
|
||||||
|
$verification->setProfile($user->getId());
|
||||||
|
$verification->save();
|
||||||
|
|
||||||
|
$params = [
|
||||||
|
"key" => $verification->getKey(),
|
||||||
|
"name" => $user->getCanonicalName(),
|
||||||
|
];
|
||||||
|
$this->sendmail($user->getEmail(), "verify-email", $params); #Vulnerability possible
|
||||||
|
}
|
||||||
|
|
||||||
$this->authenticator->authenticate($chUser->getId());
|
$this->authenticator->authenticate($chUser->getId());
|
||||||
$this->redirect("/id" . $user->getId(), static::REDIRECT_TEMPORARY);
|
$this->redirect("/id" . $user->getId(), static::REDIRECT_TEMPORARY);
|
||||||
}
|
}
|
||||||
|
@ -126,6 +144,10 @@ final class AuthPresenter extends OpenVKPresenter
|
||||||
if(!$this->authenticator->verifyCredentials($user->id, $this->postParam("password")))
|
if(!$this->authenticator->verifyCredentials($user->id, $this->postParam("password")))
|
||||||
$this->flashFail("err", tr("login_failed"), tr("invalid_username_or_password"));
|
$this->flashFail("err", tr("login_failed"), tr("invalid_username_or_password"));
|
||||||
|
|
||||||
|
$ovkUser = new User($user->related("profiles.user")->fetch());
|
||||||
|
if($ovkUser->isDeleted())
|
||||||
|
$this->flashFail("err", tr("login_failed"), tr("invalid_username_or_password"));
|
||||||
|
|
||||||
$secret = $user->related("profiles.user")->fetch()["2fa_secret"];
|
$secret = $user->related("profiles.user")->fetch()["2fa_secret"];
|
||||||
$code = $this->postParam("code");
|
$code = $this->postParam("code");
|
||||||
if(!is_null($secret)) {
|
if(!is_null($secret)) {
|
||||||
|
@ -136,7 +158,6 @@ final class AuthPresenter extends OpenVKPresenter
|
||||||
if(is_null($code))
|
if(is_null($code))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
$ovkUser = new User($user->related("profiles.user")->fetch());
|
|
||||||
if(!($code === (new Totp)->GenerateToken(Base32::decode($secret)) || $ovkUser->use2faBackupCode((int) $code))) {
|
if(!($code === (new Totp)->GenerateToken(Base32::decode($secret)) || $ovkUser->use2faBackupCode((int) $code))) {
|
||||||
$this->flash("err", tr("login_failed"), tr("incorrect_2fa_code"));
|
$this->flash("err", tr("login_failed"), tr("incorrect_2fa_code"));
|
||||||
return;
|
return;
|
||||||
|
@ -215,6 +236,9 @@ final class AuthPresenter extends OpenVKPresenter
|
||||||
|
|
||||||
function renderRestore(): void
|
function renderRestore(): void
|
||||||
{
|
{
|
||||||
|
if(!is_null($this->user))
|
||||||
|
$this->redirect("/id" . $this->user->id, static::REDIRECT_TEMPORARY);
|
||||||
|
|
||||||
if(($this->queryParam("act") ?? "default") === "finish")
|
if(($this->queryParam("act") ?? "default") === "finish")
|
||||||
$this->pass("openvk!Auth->finishRestoringPassword");
|
$this->pass("openvk!Auth->finishRestoringPassword");
|
||||||
|
|
||||||
|
@ -226,7 +250,7 @@ final class AuthPresenter extends OpenVKPresenter
|
||||||
}
|
}
|
||||||
|
|
||||||
$user = $this->users->getByChandlerUser(new ChandlerUser($uRow));
|
$user = $this->users->getByChandlerUser(new ChandlerUser($uRow));
|
||||||
if(!$user)
|
if(!$user || $user->isDeleted())
|
||||||
$this->flashFail("err", tr("error"), tr("password_reset_error"));
|
$this->flashFail("err", tr("error"), tr("password_reset_error"));
|
||||||
|
|
||||||
$request = $this->restores->getLatestByUser($user);
|
$request = $this->restores->getLatestByUser($user);
|
||||||
|
@ -247,4 +271,48 @@ final class AuthPresenter extends OpenVKPresenter
|
||||||
$this->flashFail("succ", tr("information_-1"), tr("password_reset_email_sent"));
|
$this->flashFail("succ", tr("information_-1"), tr("password_reset_email_sent"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function renderResendEmail(): void
|
||||||
|
{
|
||||||
|
if(!is_null($this->user) && $this->user->identity->isActivated())
|
||||||
|
$this->redirect("/id" . $this->user->id, static::REDIRECT_TEMPORARY);
|
||||||
|
|
||||||
|
if($_SERVER["REQUEST_METHOD"] === "POST") {
|
||||||
|
$user = $this->user->identity;
|
||||||
|
if(!$user || $user->isDeleted() || $user->isActivated())
|
||||||
|
$this->flashFail("err", tr("error"), tr("email_error"));
|
||||||
|
|
||||||
|
$request = $this->verifications->getLatestByUser($user);
|
||||||
|
if(!is_null($request) && $request->isNew())
|
||||||
|
$this->flashFail("err", tr("forbidden"), tr("email_rate_limit_error"));
|
||||||
|
|
||||||
|
$verification = new EmailVerification;
|
||||||
|
$verification->setProfile($user->getId());
|
||||||
|
$verification->save();
|
||||||
|
|
||||||
|
$params = [
|
||||||
|
"key" => $verification->getKey(),
|
||||||
|
"name" => $user->getCanonicalName(),
|
||||||
|
];
|
||||||
|
$this->sendmail($user->getEmail(), "verify-email", $params); #Vulnerability possible
|
||||||
|
|
||||||
|
$this->flashFail("succ", tr("information_-1"), tr("email_sent"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderVerifyEmail(): void
|
||||||
|
{
|
||||||
|
$request = $this->verifications->getByToken(str_replace(" ", "+", $this->queryParam("key")));
|
||||||
|
if(!$request || !$request->isStillValid()) {
|
||||||
|
$this->flash("err", tr("token_manipulation_error"), tr("token_manipulation_error_comment"));
|
||||||
|
$this->redirect("/");
|
||||||
|
} else {
|
||||||
|
$user = $request->getUser();
|
||||||
|
$user->setActivated(1);
|
||||||
|
$user->save();
|
||||||
|
|
||||||
|
$this->flash("success", tr("email_verify_success"));
|
||||||
|
$this->redirect("/");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -122,7 +122,7 @@ final class CommentPresenter extends OpenVKPresenter
|
||||||
$this->flashFail(
|
$this->flashFail(
|
||||||
"succ",
|
"succ",
|
||||||
"Успешно",
|
"Успешно",
|
||||||
"Этот комментарий больше не будет показыватся.<br/><a href='/al_comments.pl/spam?$id'>Отметить как спам</a>?"
|
"Этот комментарий больше не будет показыватся.<br/><a href='/al_comments/spam?$id'>Отметить как спам</a>?"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -207,8 +207,9 @@ final class GroupPresenter extends OpenVKPresenter
|
||||||
$club->setShortcode(empty($this->postParam("shortcode")) ? NULL : $this->postParam("shortcode"));
|
$club->setShortcode(empty($this->postParam("shortcode")) ? NULL : $this->postParam("shortcode"));
|
||||||
$club->setWall(empty($this->postParam("wall")) ? 0 : 1);
|
$club->setWall(empty($this->postParam("wall")) ? 0 : 1);
|
||||||
$club->setAdministrators_List_Display(empty($this->postParam("administrators_list_display")) ? 0 : $this->postParam("administrators_list_display"));
|
$club->setAdministrators_List_Display(empty($this->postParam("administrators_list_display")) ? 0 : $this->postParam("administrators_list_display"));
|
||||||
$club->setEveryone_Can_Create_Topics(empty($this->postParam("everyone_can_create_topics")) ? 0 : 1);
|
$club->setEveryone_Can_Create_Topics(empty($this->postParam("everyone_can_create_topics")) ? 0 : 1);
|
||||||
$club->setDisplay_Topics_Above_Wall(empty($this->postParam("display_topics_above_wall")) ? 0 : 1);;
|
$club->setDisplay_Topics_Above_Wall(empty($this->postParam("display_topics_above_wall")) ? 0 : 1);
|
||||||
|
$club->setHide_From_Global_Feed(empty($this->postParam("hide_from_global_feed")) ? 0 : 1);
|
||||||
|
|
||||||
$website = $this->postParam("website") ?? "";
|
$website = $this->postParam("website") ?? "";
|
||||||
if(empty($website))
|
if(empty($website))
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
<?php declare(strict_types=1);
|
<?php declare(strict_types=1);
|
||||||
namespace openvk\Web\Presenters;
|
namespace openvk\Web\Presenters;
|
||||||
use MessagePack\MessagePack;
|
use MessagePack\MessagePack;
|
||||||
|
use Chandler\Session\Session;
|
||||||
|
|
||||||
final class InternalAPIPresenter extends OpenVKPresenter
|
final class InternalAPIPresenter extends OpenVKPresenter
|
||||||
{
|
{
|
||||||
|
@ -68,4 +69,28 @@ final class InternalAPIPresenter extends OpenVKPresenter
|
||||||
$this->fail(-32603, "Uncaught " . get_class($ex));
|
$this->fail(-32603, "Uncaught " . get_class($ex));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function renderTimezone() {
|
||||||
|
if($_SERVER["REQUEST_METHOD"] !== "POST")
|
||||||
|
exit("ты дебил это метод апи");
|
||||||
|
|
||||||
|
$sessionOffset = Session::i()->get("_timezoneOffset");
|
||||||
|
if(is_numeric($this->postParam("timezone", false))) {
|
||||||
|
$postTZ = intval($this->postParam("timezone", false));
|
||||||
|
if ($postTZ != $sessionOffset || $sessionOffset == null) {
|
||||||
|
Session::i()->set("_timezoneOffset", $postTZ ? $postTZ : 3 * MINUTE );
|
||||||
|
$this->returnJson([
|
||||||
|
"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)
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$this->returnJson([
|
||||||
|
"success" => 0
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -124,7 +124,7 @@ final class MessengerPresenter extends OpenVKPresenter
|
||||||
}
|
}
|
||||||
|
|
||||||
$sel = $this->getCorrespondent($sel);
|
$sel = $this->getCorrespondent($sel);
|
||||||
if($sel->getId() !== $this->user->id && $sel->getSubscriptionStatus($this->user->identity) !== 3)
|
if($sel->getId() !== $this->user->id && !$sel->getPrivacyPermission('messages.write', $this->user->identity))
|
||||||
exit(header("HTTP/1.1 403 Forbidden"));
|
exit(header("HTTP/1.1 403 Forbidden"));
|
||||||
|
|
||||||
$cor = new Correspondence($this->user->identity, $sel);
|
$cor = new Correspondence($this->user->identity, $sel);
|
||||||
|
|
|
@ -67,6 +67,35 @@ final class NotesPresenter extends OpenVKPresenter
|
||||||
$note->setCreated(time());
|
$note->setCreated(time());
|
||||||
$note->setName($this->postParam("name"));
|
$note->setName($this->postParam("name"));
|
||||||
$note->setSource($this->postParam("html"));
|
$note->setSource($this->postParam("html"));
|
||||||
|
$note->setEdited(time());
|
||||||
|
$note->save();
|
||||||
|
|
||||||
|
$this->redirect("/note" . $this->user->id . "_" . $note->getVirtualId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderEdit(int $owner, int $note_id): void
|
||||||
|
{
|
||||||
|
$this->assertUserLoggedIn();
|
||||||
|
$this->willExecuteWriteAction();
|
||||||
|
|
||||||
|
$note = $this->notes->getNoteById($owner, $note_id);
|
||||||
|
|
||||||
|
if(!$note || $note->getOwner()->getId() !== $owner || $note->isDeleted())
|
||||||
|
$this->notFound();
|
||||||
|
if(is_null($this->user) || !$note->canBeModifiedBy($this->user->identity))
|
||||||
|
$this->flashFail("err", "Ошибка доступа", "Недостаточно прав для модификации данного ресурса.");
|
||||||
|
$this->template->note = $note;
|
||||||
|
|
||||||
|
if($_SERVER["REQUEST_METHOD"] === "POST") {
|
||||||
|
if(empty($this->postParam("name"))) {
|
||||||
|
$this->flashFail("err", tr("error"), tr("error_segmentation"));
|
||||||
|
}
|
||||||
|
|
||||||
|
$note->setName($this->postParam("name"));
|
||||||
|
$note->setSource($this->postParam("html"));
|
||||||
|
$note->setCached_Content(NULL);
|
||||||
|
$note->setEdited(time());
|
||||||
$note->save();
|
$note->save();
|
||||||
|
|
||||||
$this->redirect("/note" . $this->user->id . "_" . $note->getVirtualId());
|
$this->redirect("/note" . $this->user->id . "_" . $note->getVirtualId());
|
||||||
|
|
|
@ -8,11 +8,12 @@ use Latte\Engine as TemplatingEngine;
|
||||||
use openvk\Web\Models\Entities\IP;
|
use openvk\Web\Models\Entities\IP;
|
||||||
use openvk\Web\Themes\Themepacks;
|
use openvk\Web\Themes\Themepacks;
|
||||||
use openvk\Web\Models\Repositories\{IPs, Users, APITokens, Tickets};
|
use openvk\Web\Models\Repositories\{IPs, Users, APITokens, Tickets};
|
||||||
use Nette\InvalidStateException as ISE;
|
use WhichBrowser;
|
||||||
|
|
||||||
abstract class OpenVKPresenter extends SimplePresenter
|
abstract class OpenVKPresenter extends SimplePresenter
|
||||||
{
|
{
|
||||||
protected $banTolerant = false;
|
protected $banTolerant = false;
|
||||||
|
protected $activationTolerant = false;
|
||||||
protected $errorTemplate = "@error";
|
protected $errorTemplate = "@error";
|
||||||
protected $user = NULL;
|
protected $user = NULL;
|
||||||
|
|
||||||
|
@ -35,9 +36,12 @@ abstract class OpenVKPresenter extends SimplePresenter
|
||||||
]));
|
]));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function setTempTheme(string $theme): void
|
protected function setSessionTheme(string $theme, bool $once = false): void
|
||||||
{
|
{
|
||||||
Session::i()->set("_tempTheme", $theme);
|
if($once)
|
||||||
|
Session::i()->set("_tempTheme", $theme);
|
||||||
|
else
|
||||||
|
Session::i()->set("_sessionTheme", $theme);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function flashFail(string $type, string $title, ?string $message = NULL, ?int $code = NULL, bool $json = false): void
|
protected function flashFail(string $type, string $title, ?string $message = NULL, ?int $code = NULL, bool $json = false): void
|
||||||
|
@ -198,6 +202,7 @@ abstract class OpenVKPresenter extends SimplePresenter
|
||||||
$user = Authenticator::i()->getUser();
|
$user = Authenticator::i()->getUser();
|
||||||
|
|
||||||
$this->template->isXmas = intval(date('d')) >= 1 && date('m') == 12 || intval(date('d')) <= 15 && date('m') == 1 ? true : false;
|
$this->template->isXmas = intval(date('d')) >= 1 && date('m') == 12 || intval(date('d')) <= 15 && date('m') == 1 ? true : false;
|
||||||
|
$this->template->isTimezoned = Session::i()->get("_timezoneOffset");
|
||||||
|
|
||||||
if(!is_null($user)) {
|
if(!is_null($user)) {
|
||||||
$this->user = (object) [];
|
$this->user = (object) [];
|
||||||
|
@ -207,11 +212,51 @@ abstract class OpenVKPresenter extends SimplePresenter
|
||||||
$this->template->thisUser = $this->user->identity;
|
$this->template->thisUser = $this->user->identity;
|
||||||
$this->template->userTainted = $user->isTainted();
|
$this->template->userTainted = $user->isTainted();
|
||||||
|
|
||||||
|
if($this->user->identity->isDeleted()) {
|
||||||
|
/*
|
||||||
|
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣴⠶⠶⣶⠶⠶⠶⠶⠶⠶⠶⠶⠶⢶⠶⠶⠶⠤⠤⠤⠤⣄⣀⣀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||||
|
⠀⠀⠀⠀⠀⠀⠀⠀⣠⡾⠋⠀⠀⠊⠀⠀⠀⠀⠀⠀⠀⠀⠒⠒⠒⠀⠀⠀⠀⠤⢤⣤⣄⠉⠉⠛⠛⠷⣦⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||||
|
⠀⠀⠀⠀⠀⠀⠀⣰⠟⠀⠀⠀⠀⠀⠐⠋⢑⣤⣶⣶⣤⡢⡀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣠⣄⡂⠀⠀⠶⢄⠙⢷⣤⠀⠀⠀⠀⠀⠀⠀⠀
|
||||||
|
⠀⠀⠀⠀⠀⠀⣸⡿⠚⠉⡀⠀⠀⠀⠀⢰⣿⣿⣿⣿⣿⣿⡄⠀⠀⠀⢢⠀⠀⡀⣰⣿⣿⣿⣿⣦⡀⠀⠀⠡⡀⢹⡆⠀⠀⠀⠀⠀⠀⠀
|
||||||
|
⠀⠀⠀⠀⢀⣴⠏⠀⣀⣀⣀⡤⢤⣄⣠⣿⣿⣿⣿⣻⣿⣿⣷⠀⢋⣾⠈⠙⣶⠒⢿⣿⣿⣿⣿⡿⠟⠃⠀⡀⠡⠼⣧⡀⠀⠀⠀⠀⠀⠀
|
||||||
|
⠀⠀⢀⣴⣿⢃⡴⢊⢽⣶⣤⣀⠀⠊⠉⠉⡛⢿⣿⣿⣿⠿⠋⢀⡀⠁⠀⠀⢸⣁⣀⣉⣉⣉⡉⠀⠩⡡⠀⣩⣦⠀⠈⠻⣦⡀⠀⠀⠀⠀
|
||||||
|
⠀⢠⡟⢡⠇⡞⢀⠆⠀⢻⣿⣿⣷⣄⠀⢀⠈⠂⠈⢁⡤⠚⡟⠉⠀⣀⣀⠀⠈⠳⣍⠓⢆⢀⡠⢀⣨⣴⣿⣿⡏⢀⡆⠀⢸⡇⠀⠀⠀⠀
|
||||||
|
⠀⣾⠁⢸⠀⠀⢸⠀⠀⠀⠹⣿⣿⣿⣿⣶⣬⣦⣤⡈⠀⠀⠇⠀⠛⠉⣩⣤⣤⣤⣿⣤⣤⣴⣾⣿⣿⣿⣿⣿⣧⠞⠀⠀⢸⡇⠀⠀⠀⠀
|
||||||
|
⠀⢹⣆⠸⠀⠀⢸⠀⠀⠀⠀⠘⢿⣿⣿⣿⣿⣿⣿⣟⣛⠛⠛⣛⡛⠛⠛⣛⣋⡉⠉⣡⠶⢾⣿⣿⣿⣿⣿⣿⡇⠀⠀⢀⣾⠃⠀⠀⠀⠀
|
||||||
|
⠀⠀⠻⣆⡀⠀⠈⢂⠀⠀⠀⠠⡈⢻⣿⣿⣿⣿⡟⠁⠈⢧⡼⠉⠙⣆⡞⠁⠈⢹⣴⠃⠀⢸⣿⣿⣿⣿⣿⣿⠃⠀⡆⣾⠃⠀⠀⠀⠀⠀
|
||||||
|
⠀⠀⠀⠈⢻⣇⠀⠀⠀⠀⠀⠀⢡⠀⠹⣿⣿⣿⣷⡀⠀⣸⡇⠀⠀⣿⠁⠀⠀⠘⣿⠀⠀⠘⣿⣿⣿⣿⣿⣿⠀⠀⣿⡇⠀⠀⠀⠀⠀⠀
|
||||||
|
⠀⠀⠀⠀⠀⠹⣇⠀⠠⠀⠀⠀⠀⠡⠐⢬⡻⣿⣿⣿⣿⣿⣷⣶⣶⣿⣦⣤⣤⣤⣿⣦⣶⣿⣿⣿⣿⣿⣿⣿⠀⠀⣿⡇⠀⠀⠀⠀⠀⠀
|
||||||
|
⠀⠀⠀⠀⠀⠀⠹⣧⡀⠡⡀⠀⠀⠀⠑⠄⠙⢎⠻⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣦⠀⢿⡇⠀⠀⠀⠀⠀⠀
|
||||||
|
⠀⠀⠀⠀⠀⠀⠀⠈⠳⣤⡐⡄⠀⠀⠀⠈⠂⠀⠱⣌⠻⣿⣿⣿⣿⣿⣿⣿⠿⣿⠟⢻⡏⢻⣿⣿⣿⣿⣿⣿⣿⠀⢸⡇⠀⠀⠀⠀⠀⠀
|
||||||
|
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠻⢮⣦⡀⠂⠀⢀⠀⠀⠈⠳⣈⠻⣿⣿⣿⡇⠘⡄⢸⠀⠀⣇⠀⣻⣿⣿⣿⣿⣿⡏⠀⠸⡇⠀⠀⠀⠀⠀⠀
|
||||||
|
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠛⢶⣤⣄⡑⠄⠀⠀⠈⠑⠢⠙⠻⢷⣶⣵⣞⣑⣒⣋⣉⣁⣻⣿⠿⠟⠱⠃⡸⠀⣧⠀⠀⠀⠀⠀⠀
|
||||||
|
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠛⠻⣷⣄⡀⠐⠢⣄⣀⡀⠀⠉⠉⠉⠉⠛⠙⠭⠭⠄⠒⠈⠀⠐⠁⢀⣿⠀⠀⠀⠀⠀⠀
|
||||||
|
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠛⠷⢦⣤⣤⣀⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣒⡠⠄⣠⡾⠃⠀⠀⠀⠀⠀⠀
|
||||||
|
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠙⠛⠷⠶⣦⣤⣭⣤⣬⣭⣭⣴⠶⠛⠉⠀⠀⠀⠀⠀⠀⠀⠀
|
||||||
|
*/
|
||||||
|
Authenticator::i()->logout();
|
||||||
|
Session::i()->set("_su", NULL);
|
||||||
|
$this->flashFail("err", tr("error"), tr("profile_not_found"));
|
||||||
|
$this->redirect("/", static::REDIRECT_TEMPORARY);
|
||||||
|
}
|
||||||
|
|
||||||
if($this->user->identity->isBanned() && !$this->banTolerant) {
|
if($this->user->identity->isBanned() && !$this->banTolerant) {
|
||||||
header("HTTP/1.1 403 Forbidden");
|
header("HTTP/1.1 403 Forbidden");
|
||||||
$this->getTemplatingEngine()->render(__DIR__ . "/templates/@banned.xml", [
|
$this->getTemplatingEngine()->render(__DIR__ . "/templates/@banned.xml", [
|
||||||
"thisUser" => $this->user->identity,
|
"thisUser" => $this->user->identity,
|
||||||
"csrfToken" => $GLOBALS["csrfToken"],
|
"csrfToken" => $GLOBALS["csrfToken"],
|
||||||
|
"isTimezoned" => Session::i()->get("_timezoneOffset"),
|
||||||
|
]);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ето для емейл уже надо (и по хорошему надо бы избавится от повторяющегося кода мда)
|
||||||
|
if(!$this->user->identity->isActivated() && !$this->activationTolerant) {
|
||||||
|
header("HTTP/1.1 403 Forbidden");
|
||||||
|
$this->getTemplatingEngine()->render(__DIR__ . "/templates/@email.xml", [
|
||||||
|
"thisUser" => $this->user->identity,
|
||||||
|
"csrfToken" => $GLOBALS["csrfToken"],
|
||||||
|
"isTimezoned" => Session::i()->get("_timezoneOffset"),
|
||||||
]);
|
]);
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
|
@ -221,7 +266,7 @@ abstract class OpenVKPresenter extends SimplePresenter
|
||||||
$this->user->identity->save();
|
$this->user->identity->save();
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->template->ticketAnsweredCount = (new Tickets)->getTicketsCountByuId($this->user->id, 1);
|
$this->template->ticketAnsweredCount = (new Tickets)->getTicketsCountByUserId($this->user->id, 1);
|
||||||
if($user->can("write")->model("openvk\Web\Models\Entities\TicketReply")->whichBelongsTo(0))
|
if($user->can("write")->model("openvk\Web\Models\Entities\TicketReply")->whichBelongsTo(0))
|
||||||
$this->template->helpdeskTicketNotAnsweredCount = (new Tickets)->getTicketCount(0);
|
$this->template->helpdeskTicketNotAnsweredCount = (new Tickets)->getTicketCount(0);
|
||||||
}
|
}
|
||||||
|
@ -235,10 +280,17 @@ abstract class OpenVKPresenter extends SimplePresenter
|
||||||
{
|
{
|
||||||
parent::onBeforeRender();
|
parent::onBeforeRender();
|
||||||
|
|
||||||
|
$whichbrowser = new WhichBrowser\Parser(getallheaders());
|
||||||
|
$mobiletheme = OPENVK_ROOT_CONF["openvk"]["preferences"]["defaultMobileTheme"];
|
||||||
|
if($mobiletheme && $whichbrowser->isType('mobile') && Session::i()->get("_tempTheme") == null)
|
||||||
|
$this->setSessionTheme($mobiletheme);
|
||||||
|
|
||||||
$theme = NULL;
|
$theme = NULL;
|
||||||
if(Session::i()->get("_tempTheme")) {
|
if(Session::i()->get("_tempTheme")) {
|
||||||
$theme = Themepacks::i()[Session::i()->get("_tempTheme", "ovk")];
|
$theme = Themepacks::i()[Session::i()->get("_tempTheme", "ovk")];
|
||||||
Session::i()->set("_tempTheme", NULL);
|
Session::i()->set("_tempTheme", NULL);
|
||||||
|
} else if(Session::i()->get("_sessionTheme")) {
|
||||||
|
$theme = Themepacks::i()[Session::i()->get("_sessionTheme", "ovk")];
|
||||||
} else if($this->requestParam("themePreview")) {
|
} else if($this->requestParam("themePreview")) {
|
||||||
$theme = Themepacks::i()[$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()) {
|
||||||
|
|
|
@ -70,9 +70,9 @@ final class PhotosPresenter extends OpenVKPresenter
|
||||||
}
|
}
|
||||||
|
|
||||||
if($_SERVER["REQUEST_METHOD"] === "POST") {
|
if($_SERVER["REQUEST_METHOD"] === "POST") {
|
||||||
if(empty($this->postParam("name"))) {
|
if(empty($this->postParam("name")))
|
||||||
$this->flashFail("err", tr("error"), tr("error_segmentation"));
|
$this->flashFail("err", tr("error"), tr("error_segmentation"));
|
||||||
}
|
|
||||||
$album = new Album;
|
$album = new Album;
|
||||||
$album->setOwner(isset($club) ? $club->getId() * -1 : $this->user->id);
|
$album->setOwner(isset($club) ? $club->getId() * -1 : $this->user->id);
|
||||||
$album->setName($this->postParam("name"));
|
$album->setName($this->postParam("name"));
|
||||||
|
@ -80,7 +80,10 @@ final class PhotosPresenter extends OpenVKPresenter
|
||||||
$album->setCreated(time());
|
$album->setCreated(time());
|
||||||
$album->save();
|
$album->save();
|
||||||
|
|
||||||
$this->redirect("/album" . $album->getOwner()->getId() . "_" . $album->getId(), static::REDIRECT_TEMPORARY);
|
if(isset($club))
|
||||||
|
$this->redirect("/album-" . $album->getOwner()->getId() . "_" . $album->getId(), static::REDIRECT_TEMPORARY);
|
||||||
|
else
|
||||||
|
$this->redirect("/album" . $album->getOwner()->getId() . "_" . $album->getId(), static::REDIRECT_TEMPORARY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -118,10 +121,11 @@ final class PhotosPresenter extends OpenVKPresenter
|
||||||
if(is_null($this->user) || !$album->canBeModifiedBy($this->user->identity))
|
if(is_null($this->user) || !$album->canBeModifiedBy($this->user->identity))
|
||||||
$this->flashFail("err", "Ошибка доступа", "Недостаточно прав для модификации данного ресурса.");
|
$this->flashFail("err", "Ошибка доступа", "Недостаточно прав для модификации данного ресурса.");
|
||||||
|
|
||||||
$name = $album->getName();
|
$name = $album->getName();
|
||||||
|
$owner = $album->getOwner();
|
||||||
$album->delete();
|
$album->delete();
|
||||||
$this->flash("succ", "Альбом удалён", "Альбом $name был успешно удалён.");
|
$this->flash("succ", "Альбом удалён", "Альбом $name был успешно удалён.");
|
||||||
$this->redirect("/albums" . $this->user->id);
|
$this->redirect("/albums" . ($owner instanceof Club ? "-" : "") . $owner->getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderAlbum(int $owner, int $id): void
|
function renderAlbum(int $owner, int $id): void
|
||||||
|
|
|
@ -6,7 +6,7 @@ use openvk\Web\Models\Entities\TicketComment;
|
||||||
use openvk\Web\Models\Repositories\TicketComments;
|
use openvk\Web\Models\Repositories\TicketComments;
|
||||||
use openvk\Web\Util\Telegram;
|
use openvk\Web\Util\Telegram;
|
||||||
use Chandler\Session\Session;
|
use Chandler\Session\Session;
|
||||||
use Netcarver\Textile;
|
use Parsedown;
|
||||||
|
|
||||||
final class SupportPresenter extends OpenVKPresenter
|
final class SupportPresenter extends OpenVKPresenter
|
||||||
{
|
{
|
||||||
|
@ -28,17 +28,19 @@ final class SupportPresenter extends OpenVKPresenter
|
||||||
$this->assertUserLoggedIn();
|
$this->assertUserLoggedIn();
|
||||||
$this->template->mode = in_array($this->queryParam("act"), ["faq", "new", "list"]) ? $this->queryParam("act") : "faq";
|
$this->template->mode = in_array($this->queryParam("act"), ["faq", "new", "list"]) ? $this->queryParam("act") : "faq";
|
||||||
|
|
||||||
$tickets = $this->tickets->getTicketsByuId($this->user->id);
|
$this->template->count = $this->tickets->getTicketsCountByUserId($this->user->id);
|
||||||
if($tickets)
|
if($this->template->mode === "list") {
|
||||||
$this->template->tickets = $tickets;
|
$this->template->page = (int) ($this->queryParam("p") ?? 1);
|
||||||
|
$this->template->tickets = $this->tickets->getTicketsByUserId($this->user->id, $this->template->page);
|
||||||
|
}
|
||||||
|
|
||||||
if($_SERVER["REQUEST_METHOD"] === "POST") {
|
if($_SERVER["REQUEST_METHOD"] === "POST") {
|
||||||
if(!empty($this->postParam("name")) && !empty($this->postParam("text"))) {
|
if(!empty($this->postParam("name")) && !empty($this->postParam("text"))) {
|
||||||
$this->assertNoCSRF();
|
|
||||||
$this->willExecuteWriteAction();
|
$this->willExecuteWriteAction();
|
||||||
|
|
||||||
$ticket = new Ticket;
|
$ticket = new Ticket;
|
||||||
$ticket->setType(0);
|
$ticket->setType(0);
|
||||||
$ticket->setUser_id($this->user->id);
|
$ticket->setUser_Id($this->user->id);
|
||||||
$ticket->setName($this->postParam("name"));
|
$ticket->setName($this->postParam("name"));
|
||||||
$ticket->setText($this->postParam("text"));
|
$ticket->setText($this->postParam("text"));
|
||||||
$ticket->setcreated(time());
|
$ticket->setcreated(time());
|
||||||
|
@ -111,11 +113,11 @@ final class SupportPresenter extends OpenVKPresenter
|
||||||
if(!$ticket || $ticket->isDeleted() != 0 || $ticket->getUserId() !== $this->user->id && !$this->hasPermission('openvk\Web\Models\Entities\TicketReply', 'write', 0)) {
|
if(!$ticket || $ticket->isDeleted() != 0 || $ticket->getUserId() !== $this->user->id && !$this->hasPermission('openvk\Web\Models\Entities\TicketReply', 'write', 0)) {
|
||||||
$this->notFound();
|
$this->notFound();
|
||||||
} else {
|
} else {
|
||||||
header("HTTP/1.1 302 Found");
|
|
||||||
if($ticket->getUserId() !== $this->user->id && $this->hasPermission('openvk\Web\Models\Entities\TicketReply', 'write', 0))
|
if($ticket->getUserId() !== $this->user->id && $this->hasPermission('openvk\Web\Models\Entities\TicketReply', 'write', 0))
|
||||||
header("Location: /support/tickets");
|
$this->redirect("/support/tickets");
|
||||||
else
|
else
|
||||||
header("Location: /support");
|
$this->redirect("/support");
|
||||||
|
|
||||||
$ticket->delete();
|
$ticket->delete();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -136,7 +138,6 @@ final class SupportPresenter extends OpenVKPresenter
|
||||||
$ticket->setType(0);
|
$ticket->setType(0);
|
||||||
$ticket->save();
|
$ticket->save();
|
||||||
|
|
||||||
$this->assertNoCSRF();
|
|
||||||
$this->willExecuteWriteAction();
|
$this->willExecuteWriteAction();
|
||||||
|
|
||||||
$comment = new TicketComment;
|
$comment = new TicketComment;
|
||||||
|
@ -183,12 +184,11 @@ final class SupportPresenter extends OpenVKPresenter
|
||||||
$ticket->setType($this->postParam("status"));
|
$ticket->setType($this->postParam("status"));
|
||||||
$ticket->save();
|
$ticket->save();
|
||||||
|
|
||||||
$this->assertNoCSRF();
|
|
||||||
$comment = new TicketComment;
|
$comment = new TicketComment;
|
||||||
$comment->setUser_id($this->user->id);
|
$comment->setUser_id($this->user->id);
|
||||||
$comment->setUser_type(1);
|
$comment->setUser_type(1);
|
||||||
$comment->setText($this->postParam("text"));
|
$comment->setText($this->postParam("text"));
|
||||||
$comment->setTicket_id($id);
|
$comment->setTicket_Id($id);
|
||||||
$comment->setCreated(time());
|
$comment->setCreated(time());
|
||||||
$comment->save();
|
$comment->save();
|
||||||
} elseif(empty($this->postParam("text"))) {
|
} elseif(empty($this->postParam("text"))) {
|
||||||
|
@ -204,10 +204,10 @@ final class SupportPresenter extends OpenVKPresenter
|
||||||
{
|
{
|
||||||
$lang = Session::i()->get("lang", "ru");
|
$lang = Session::i()->get("lang", "ru");
|
||||||
$base = OPENVK_ROOT . "/data/knowledgebase";
|
$base = OPENVK_ROOT . "/data/knowledgebase";
|
||||||
if(file_exists("$base/$name.$lang.textile"))
|
if(file_exists("$base/$name.$lang.md"))
|
||||||
$file = "$base/$name.$lang.textile";
|
$file = "$base/$name.$lang.md";
|
||||||
else if(file_exists("$base/$name.textile"))
|
else if(file_exists("$base/$name.md"))
|
||||||
$file = "$base/$name.textile";
|
$file = "$base/$name.md";
|
||||||
else
|
else
|
||||||
$this->notFound();
|
$this->notFound();
|
||||||
|
|
||||||
|
@ -219,11 +219,34 @@ final class SupportPresenter extends OpenVKPresenter
|
||||||
array_shift($lines);
|
array_shift($lines);
|
||||||
}
|
}
|
||||||
|
|
||||||
$content = implode("\r\n", $lines);
|
$content = implode($lines);
|
||||||
|
|
||||||
$parser = new Textile\Parser;
|
$parser = new Parsedown();
|
||||||
$this->template->heading = $heading;
|
$this->template->heading = $heading;
|
||||||
$this->template->content = $parser->parse($content);
|
$this->template->content = $parser->text($content);
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderDeleteComment(int $id): void
|
||||||
|
{
|
||||||
|
$this->assertUserLoggedIn();
|
||||||
|
$this->assertNoCSRF();
|
||||||
|
|
||||||
|
$comment = $this->comments->get($id);
|
||||||
|
if(is_null($comment))
|
||||||
|
$this->notFound();
|
||||||
|
|
||||||
|
$ticket = $comment->getTicket();
|
||||||
|
|
||||||
|
if($ticket->isDeleted())
|
||||||
|
$this->notFound();
|
||||||
|
|
||||||
|
if(!($ticket->getUserId() === $this->user->id && $comment->getUType() === 0))
|
||||||
|
$this->assertPermission("openvk\Web\Models\Entities\TicketReply", "write", 0);
|
||||||
|
|
||||||
|
$this->willExecuteWriteAction();
|
||||||
|
$comment->delete();
|
||||||
|
|
||||||
|
$this->flashFail("succ", tr("ticket_changed"), tr("ticket_changed_comment"));
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderRateAnswer(int $id, int $mark): void
|
function renderRateAnswer(int $id, int $mark): void
|
||||||
|
|
|
@ -9,6 +9,7 @@ use openvk\Web\Models\Repositories\Albums;
|
||||||
use openvk\Web\Models\Repositories\Videos;
|
use openvk\Web\Models\Repositories\Videos;
|
||||||
use openvk\Web\Models\Repositories\Notes;
|
use openvk\Web\Models\Repositories\Notes;
|
||||||
use openvk\Web\Models\Repositories\Vouchers;
|
use openvk\Web\Models\Repositories\Vouchers;
|
||||||
|
use openvk\Web\Models\Exceptions\InvalidUserNameException;
|
||||||
use openvk\Web\Util\Validator;
|
use openvk\Web\Util\Validator;
|
||||||
use openvk\Web\Models\Entities\Notifications\CoinsTransferNotification;
|
use openvk\Web\Models\Entities\Notifications\CoinsTransferNotification;
|
||||||
use Chandler\Security\Authenticator;
|
use Chandler\Security\Authenticator;
|
||||||
|
@ -180,10 +181,18 @@ final class UserPresenter extends OpenVKPresenter
|
||||||
$this->willExecuteWriteAction($_GET['act'] === "status");
|
$this->willExecuteWriteAction($_GET['act'] === "status");
|
||||||
|
|
||||||
if($_GET['act'] === "main" || $_GET['act'] == NULL) {
|
if($_GET['act'] === "main" || $_GET['act'] == NULL) {
|
||||||
$user->setFirst_Name(empty($this->postParam("first_name")) ? $user->getFirstName() : $this->postParam("first_name"));
|
try {
|
||||||
$user->setLast_Name(empty($this->postParam("last_name")) ? "" : $this->postParam("last_name"));
|
$user->setFirst_Name(empty($this->postParam("first_name")) ? $user->getFirstName() : $this->postParam("first_name"));
|
||||||
|
$user->setLast_Name(empty($this->postParam("last_name")) ? "" : $this->postParam("last_name"));
|
||||||
|
} catch(InvalidUserNameException $ex) {
|
||||||
|
$this->flashFail("err", tr("error"), tr("invalid_real_name"));
|
||||||
|
}
|
||||||
|
|
||||||
$user->setPseudo(empty($this->postParam("pseudo")) ? NULL : $this->postParam("pseudo"));
|
$user->setPseudo(empty($this->postParam("pseudo")) ? NULL : $this->postParam("pseudo"));
|
||||||
$user->setStatus(empty($this->postParam("status")) ? NULL : $this->postParam("status"));
|
$user->setStatus(empty($this->postParam("status")) ? NULL : $this->postParam("status"));
|
||||||
|
$user->setHometown(empty($this->postParam("hometown")) ? NULL : $this->postParam("hometown"));
|
||||||
|
|
||||||
|
|
||||||
if (strtotime($this->postParam("birthday")) < time())
|
if (strtotime($this->postParam("birthday")) < time())
|
||||||
$user->setBirthday(strtotime($this->postParam("birthday")));
|
$user->setBirthday(strtotime($this->postParam("birthday")));
|
||||||
|
|
||||||
|
@ -372,6 +381,7 @@ final class UserPresenter extends OpenVKPresenter
|
||||||
"friends.read",
|
"friends.read",
|
||||||
"friends.add",
|
"friends.add",
|
||||||
"wall.write",
|
"wall.write",
|
||||||
|
"messages.write",
|
||||||
];
|
];
|
||||||
foreach($settings as $setting) {
|
foreach($settings as $setting) {
|
||||||
$input = $this->postParam(str_replace(".", "_", $setting));
|
$input = $this->postParam(str_replace(".", "_", $setting));
|
||||||
|
@ -395,8 +405,8 @@ final class UserPresenter extends OpenVKPresenter
|
||||||
} else if($_GET['act'] === "interface") {
|
} else if($_GET['act'] === "interface") {
|
||||||
if (isset(Themepacks::i()[$this->postParam("style")]) || $this->postParam("style") === Themepacks::DEFAULT_THEME_ID)
|
if (isset(Themepacks::i()[$this->postParam("style")]) || $this->postParam("style") === Themepacks::DEFAULT_THEME_ID)
|
||||||
{
|
{
|
||||||
$user->setStyle($this->postParam("style"));
|
if ($this->postParam("theme_for_session") != "1") $user->setStyle($this->postParam("style"));
|
||||||
$this->setTempTheme($this->postParam("style"));
|
$this->setSessionTheme($this->postParam("style"));
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->postParam("style_avatar") <= 2 && $this->postParam("style_avatar") >= 0)
|
if ($this->postParam("style_avatar") <= 2 && $this->postParam("style_avatar") >= 0)
|
||||||
|
@ -412,13 +422,14 @@ final class UserPresenter extends OpenVKPresenter
|
||||||
$user->setNsfwTolerance((int) $this->postParam("nsfw"));
|
$user->setNsfwTolerance((int) $this->postParam("nsfw"));
|
||||||
} else if($_GET['act'] === "lMenu") {
|
} else if($_GET['act'] === "lMenu") {
|
||||||
$settings = [
|
$settings = [
|
||||||
"menu_bildoj" => "photos",
|
"menu_bildoj" => "photos",
|
||||||
"menu_filmetoj" => "videos",
|
"menu_filmetoj" => "videos",
|
||||||
"menu_mesagoj" => "messages",
|
"menu_mesagoj" => "messages",
|
||||||
"menu_notatoj" => "notes",
|
"menu_notatoj" => "notes",
|
||||||
"menu_grupoj" => "groups",
|
"menu_grupoj" => "groups",
|
||||||
"menu_novajoj" => "news",
|
"menu_novajoj" => "news",
|
||||||
"menu_ligiloj" => "links",
|
"menu_ligiloj" => "links",
|
||||||
|
"menu_standardo" => "poster",
|
||||||
];
|
];
|
||||||
foreach($settings as $checkbox => $setting)
|
foreach($settings as $checkbox => $setting)
|
||||||
$user->setLeftMenuItemStatus($setting, $this->checkbox($checkbox));
|
$user->setLeftMenuItemStatus($setting, $this->checkbox($checkbox));
|
||||||
|
@ -489,11 +500,16 @@ final class UserPresenter extends OpenVKPresenter
|
||||||
$this->template->secret = $secret;
|
$this->template->secret = $secret;
|
||||||
}
|
}
|
||||||
|
|
||||||
$issuer = OPENVK_ROOT_CONF["openvk"]["appearance"]["name"];
|
// Why are these crutch? For some reason, the QR code is not displayed if you just pass the render output to the view
|
||||||
$email = $this->user->identity->getEmail();
|
|
||||||
$this->template->qrCode = substr((new QRCode(new QROptions([
|
$issuer = OPENVK_ROOT_CONF["openvk"]["appearance"]["name"];
|
||||||
|
$email = $this->user->identity->getEmail();
|
||||||
|
$qrCode = explode("base64,", (new QRCode(new QROptions([
|
||||||
"imageTransparent" => false
|
"imageTransparent" => false
|
||||||
])))->render("otpauth://totp/$issuer:$email?secret=$secret&issuer=$issuer"), 22);
|
])))->render("otpauth://totp/$issuer:$email?secret=$secret&issuer=$issuer"));
|
||||||
|
|
||||||
|
$this->template->qrCodeType = substr($qrCode[0], 5);
|
||||||
|
$this->template->qrCodeData = $qrCode[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderDisableTwoFactorAuth(): void
|
function renderDisableTwoFactorAuth(): void
|
||||||
|
|
|
@ -5,6 +5,9 @@ use openvk\Web\Models\Entities\Notifications\{RepostNotification, WallPostNotifi
|
||||||
use openvk\Web\Models\Repositories\{Posts, Users, Clubs, Albums};
|
use openvk\Web\Models\Repositories\{Posts, Users, Clubs, Albums};
|
||||||
use Chandler\Database\DatabaseConnection;
|
use Chandler\Database\DatabaseConnection;
|
||||||
use Nette\InvalidStateException as ISE;
|
use Nette\InvalidStateException as ISE;
|
||||||
|
use Bhaktaraz\RSSGenerator\Item;
|
||||||
|
use Bhaktaraz\RSSGenerator\Feed;
|
||||||
|
use Bhaktaraz\RSSGenerator\Channel;
|
||||||
|
|
||||||
final class WallPresenter extends OpenVKPresenter
|
final class WallPresenter extends OpenVKPresenter
|
||||||
{
|
{
|
||||||
|
@ -52,14 +55,14 @@ final class WallPresenter extends OpenVKPresenter
|
||||||
$canPost = $owner->getPrivacyPermission("wall.write", $this->user->identity);
|
$canPost = $owner->getPrivacyPermission("wall.write", $this->user->identity);
|
||||||
else
|
else
|
||||||
$this->flashFail("err", tr("error"), "Ошибка доступа");
|
$this->flashFail("err", tr("error"), "Ошибка доступа");
|
||||||
} else if($user < 0) {
|
} else if($user < 0) {
|
||||||
if($owner->canBeModifiedBy($this->user->identity))
|
if($owner->canBeModifiedBy($this->user->identity))
|
||||||
$canPost = true;
|
$canPost = true;
|
||||||
else
|
else
|
||||||
$canPost = $owner->canPost();
|
$canPost = $owner->canPost();
|
||||||
} else {
|
} else {
|
||||||
$canPost = false;
|
$canPost = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($embedded == true) $this->template->_template = "components/wall.xml";
|
if ($embedded == true) $this->template->_template = "components/wall.xml";
|
||||||
$this->template->oObj = $owner;
|
$this->template->oObj = $owner;
|
||||||
|
@ -83,6 +86,49 @@ final class WallPresenter extends OpenVKPresenter
|
||||||
$this->renderWall($user, true);
|
$this->renderWall($user, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function renderRSS(int $user): void
|
||||||
|
{
|
||||||
|
if(false)
|
||||||
|
exit("Ошибка доступа: " . (string) random_int(0, 255));
|
||||||
|
|
||||||
|
$owner = ($user < 0 ? (new Clubs) : (new Users))->get(abs($user));
|
||||||
|
if(is_null($this->user)) {
|
||||||
|
$canPost = false;
|
||||||
|
} else if($user > 0) {
|
||||||
|
if(!$owner->isBanned())
|
||||||
|
$canPost = $owner->getPrivacyPermission("wall.write", $this->user->identity);
|
||||||
|
else
|
||||||
|
$this->flashFail("err", tr("error"), "Ошибка доступа");
|
||||||
|
} else if($user < 0) {
|
||||||
|
if($owner->canBeModifiedBy($this->user->identity))
|
||||||
|
$canPost = true;
|
||||||
|
else
|
||||||
|
$canPost = $owner->canPost();
|
||||||
|
} else {
|
||||||
|
$canPost = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$posts = iterator_to_array($this->posts->getPostsFromUsersWall($user));
|
||||||
|
|
||||||
|
$feed = new Feed();
|
||||||
|
|
||||||
|
$channel = new Channel();
|
||||||
|
$channel->title(OPENVK_ROOT_CONF['openvk']['appearance']['name'])->url(ovk_scheme(true) . $_SERVER["SERVER_NAME"])->appendTo($feed);
|
||||||
|
|
||||||
|
foreach($posts as $post) {
|
||||||
|
$item = new Item();
|
||||||
|
$item
|
||||||
|
->title($post->getOwner()->getCanonicalName())
|
||||||
|
->description($post->getText())
|
||||||
|
->url(ovk_scheme(true).$_SERVER["SERVER_NAME"]."/wall{$post->getPrettyId()}")
|
||||||
|
->pubDate($post->getPublicationTime()->timestamp())
|
||||||
|
->appendTo($channel);
|
||||||
|
}
|
||||||
|
|
||||||
|
header("Content-Type: application/rss+xml");
|
||||||
|
exit($feed);
|
||||||
|
}
|
||||||
|
|
||||||
function renderFeed(): void
|
function renderFeed(): void
|
||||||
{
|
{
|
||||||
$this->assertUserLoggedIn();
|
$this->assertUserLoggedIn();
|
||||||
|
@ -122,24 +168,24 @@ final class WallPresenter extends OpenVKPresenter
|
||||||
|
|
||||||
$page = (int) ($_GET["p"] ?? 1);
|
$page = (int) ($_GET["p"] ?? 1);
|
||||||
$pPage = min((int) ($_GET["posts"] ?? OPENVK_DEFAULT_PER_PAGE), 50);
|
$pPage = min((int) ($_GET["posts"] ?? OPENVK_DEFAULT_PER_PAGE), 50);
|
||||||
$posts = DatabaseConnection::i()
|
|
||||||
->getContext()
|
$queryBase = "FROM `posts` LEFT JOIN `groups` ON GREATEST(`posts`.`wall`, 0) = 0 AND `groups`.`id` = ABS(`posts`.`wall`) WHERE (`groups`.`hide_from_global_feed` = 0 OR `groups`.`name` IS NULL) AND `posts`.`deleted` = 0";
|
||||||
->table("posts")
|
|
||||||
->where("deleted", 0)
|
|
||||||
->order("created DESC");
|
|
||||||
|
|
||||||
if($this->user->identity->getNsfwTolerance() === User::NSFW_INTOLERANT)
|
if($this->user->identity->getNsfwTolerance() === User::NSFW_INTOLERANT)
|
||||||
$posts = $posts->where("nsfw", false);
|
$queryBase .= " AND `nsfw` = 0";
|
||||||
|
|
||||||
|
$posts = DatabaseConnection::i()->getConnection()->query("SELECT `posts`.`id` " . $queryBase . " ORDER BY `created` DESC LIMIT " . $pPage . " OFFSET " . ($page - 1) * $pPage);
|
||||||
|
$count = DatabaseConnection::i()->getConnection()->query("SELECT COUNT(*) " . $queryBase)->fetch()->{"COUNT(*)"};
|
||||||
|
|
||||||
$this->template->_template = "Wall/Feed.xml";
|
$this->template->_template = "Wall/Feed.xml";
|
||||||
$this->template->globalFeed = true;
|
$this->template->globalFeed = true;
|
||||||
$this->template->paginatorConf = (object) [
|
$this->template->paginatorConf = (object) [
|
||||||
"count" => sizeof($posts),
|
"count" => $count,
|
||||||
"page" => (int) ($_GET["p"] ?? 1),
|
"page" => (int) ($_GET["p"] ?? 1),
|
||||||
"amount" => sizeof($posts->page($page, $pPage)),
|
"amount" => sizeof($posts),
|
||||||
"perPage" => $pPage,
|
"perPage" => $pPage,
|
||||||
];
|
];
|
||||||
foreach($posts->page($page, $pPage) as $post)
|
foreach($posts as $post)
|
||||||
$this->template->posts[] = $this->posts->get($post->id);
|
$this->template->posts[] = $this->posts->get($post->id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
19
Web/Presenters/templates/@email.xml
Executable file
19
Web/Presenters/templates/@email.xml
Executable file
|
@ -0,0 +1,19 @@
|
||||||
|
{extends "@layout.xml"}
|
||||||
|
{block title}{_ec_header}{/block}
|
||||||
|
|
||||||
|
{block header}
|
||||||
|
{_ec_header}
|
||||||
|
{/block}
|
||||||
|
|
||||||
|
{block content}
|
||||||
|
<div class="border-block center">
|
||||||
|
<h4>{_ec_title}</h4>
|
||||||
|
<p>{tr("ec_1", htmlentities($thisUser->getCanonicalName()))|noescape}<br/></p>
|
||||||
|
<p>{_ec_2}</p>
|
||||||
|
<p>
|
||||||
|
<form action="/reg/resend" method="post">
|
||||||
|
<input type="submit" class="button" value="{_ec_resend}">
|
||||||
|
</form>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
{/block}
|
|
@ -1,21 +1,23 @@
|
||||||
|
{var instance_name = OPENVK_ROOT_CONF['openvk']['appearance']['name']}
|
||||||
|
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>Произошёл троллинг... | OpenVK</title>
|
<title>An error occurred - {$instance_name}</title>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<meta name="viewport" content="width=device-width, user-scalable=no" />
|
<meta name="viewport" content="width=device-width, user-scalable=no" />
|
||||||
<style>
|
<style>
|
||||||
@keyframes gradient {
|
@keyframes gradient {
|
||||||
0% {
|
0% {
|
||||||
background-position:0% 50%
|
background-position: 0% 50%;
|
||||||
}
|
}
|
||||||
|
|
||||||
50% {
|
50% {
|
||||||
background-position:100% 50%
|
background-position: 100% 50%;
|
||||||
}
|
}
|
||||||
|
|
||||||
100% {
|
100% {
|
||||||
background-position:0% 50%
|
background-position: 0% 50%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
{var instance_name = OPENVK_ROOT_CONF['openvk']['appearance']['name']}
|
{var instance_name = OPENVK_ROOT_CONF['openvk']['appearance']['name']}
|
||||||
|
|
||||||
|
<!DOCTYPE html>
|
||||||
<html n:if="!isset($parentModule) || substr($parentModule, 0, 21) === 'libchandler:absolute.'">
|
<html n:if="!isset($parentModule) || substr($parentModule, 0, 21) === 'libchandler:absolute.'">
|
||||||
<head>
|
<head>
|
||||||
<title>
|
<title>
|
||||||
|
@ -9,28 +10,35 @@
|
||||||
<link rel="shortcut icon" href="/assets/packages/static/openvk/img/icon.ico" />
|
<link rel="shortcut icon" href="/assets/packages/static/openvk/img/icon.ico" />
|
||||||
<meta name="application-name" content="{$instance_name}" />
|
<meta name="application-name" content="{$instance_name}" />
|
||||||
<meta n:ifset="$csrfToken" name="csrf" value="{$csrfToken}" />
|
<meta n:ifset="$csrfToken" name="csrf" value="{$csrfToken}" />
|
||||||
|
|
||||||
<script src="/language/{php echo getLanguage()}.js" crossorigin="anonymous"></script>
|
<script src="/language/{php echo getLanguage()}.js" crossorigin="anonymous"></script>
|
||||||
{script "js/node_modules/jquery/dist/jquery.min.js"}
|
{script "js/node_modules/jquery/dist/jquery.min.js"}
|
||||||
{script "js/node_modules/umbrellajs/umbrella.min.js"}
|
{script "js/node_modules/umbrellajs/umbrella.min.js"}
|
||||||
{script "js/l10n.js"}
|
{script "js/l10n.js"}
|
||||||
{script "js/openvk.cls.js"}
|
{script "js/openvk.cls.js"}
|
||||||
|
|
||||||
|
{if $isTimezoned == null}
|
||||||
|
{script "js/timezone.js"}
|
||||||
|
{/if}
|
||||||
|
|
||||||
{ifset $thisUser}
|
{ifset $thisUser}
|
||||||
{if $thisUser->getNsfwTolerance() < 2}
|
{if $thisUser->getNsfwTolerance() < 2}
|
||||||
{css "css/nsfw-posts.css"}
|
{css "css/nsfw-posts.css"}
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{if $theme !== null}
|
{if $theme !== null}
|
||||||
{if $theme->inheritDefault()}
|
{if $theme->inheritDefault()}
|
||||||
{css "css/style.css"}
|
{css "css/style.css"}
|
||||||
{css "css/dialog.css"}
|
{css "css/dialog.css"}
|
||||||
{css "css/notifications.css"}
|
{css "css/notifications.css"}
|
||||||
|
|
||||||
{if $isXmas}
|
{if $isXmas}
|
||||||
{css "css/xmas.css"}
|
{css "css/xmas.css"}
|
||||||
{/if}
|
{/if}
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<link rel="stylesheet" href="/themepack/{$theme->getId()}/{$theme->getVersion()}/stylesheet/styles.css" />
|
<link rel="stylesheet" href="/themepack/{$theme->getId()}/{$theme->getVersion()}/stylesheet/styles.css" />
|
||||||
|
|
||||||
{if $isXmas}
|
{if $isXmas}
|
||||||
<link rel="stylesheet" href="/themepack/{$theme->getId()}/{$theme->getVersion()}/resource/xmas.css" />
|
<link rel="stylesheet" href="/themepack/{$theme->getId()}/{$theme->getVersion()}/resource/xmas.css" />
|
||||||
{/if}
|
{/if}
|
||||||
|
@ -38,6 +46,7 @@
|
||||||
{css "css/style.css"}
|
{css "css/style.css"}
|
||||||
{css "css/dialog.css"}
|
{css "css/dialog.css"}
|
||||||
{css "css/notifications.css"}
|
{css "css/notifications.css"}
|
||||||
|
|
||||||
{if $isXmas}
|
{if $isXmas}
|
||||||
{css "css/xmas.css"}
|
{css "css/xmas.css"}
|
||||||
{/if}
|
{/if}
|
||||||
|
@ -46,13 +55,13 @@
|
||||||
{if $thisUser->getStyleAvatar() == 1}
|
{if $thisUser->getStyleAvatar() == 1}
|
||||||
{css "css/avatar.1.css"}
|
{css "css/avatar.1.css"}
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{if $thisUser->getStyleAvatar() == 2}
|
{if $thisUser->getStyleAvatar() == 2}
|
||||||
{css "css/avatar.2.css"}
|
{css "css/avatar.2.css"}
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
|
|
||||||
{if $thisUser->hasMicroblogEnabled() == 1}
|
{if $thisUser->hasMicroblogEnabled() == 1}
|
||||||
{css "css/microblog.css"}
|
{css "css/microblog.css"}
|
||||||
{/if}
|
{/if}
|
||||||
{else}
|
{else}
|
||||||
{css "css/style.css"}
|
{css "css/style.css"}
|
||||||
|
@ -65,7 +74,9 @@
|
||||||
{/if}
|
{/if}
|
||||||
{/ifset}
|
{/ifset}
|
||||||
|
|
||||||
{ifset headIncludes}{include headIncludes}{/ifset}
|
{ifset headIncludes}
|
||||||
|
{include headIncludes}
|
||||||
|
{/ifset}
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="sudo-banner" n:if="isset($thisUser) && $userTainted">
|
<div id="sudo-banner" n:if="isset($thisUser) && $userTainted">
|
||||||
|
@ -77,57 +88,52 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div n:if="OPENVK_ROOT_CONF['openvk']['preferences']['bellsAndWhistles']['testLabel']" id="test-label">FOR TESTING PURPOSES ONLY</div>
|
<div n:if="OPENVK_ROOT_CONF['openvk']['preferences']['bellsAndWhistles']['testLabel']" id="test-label">FOR TESTING PURPOSES ONLY</div>
|
||||||
<div class="notifications_global_wrap"></div>
|
|
||||||
|
<div class="notifications_global_wrap"></div>
|
||||||
<div class="dimmer"></div>
|
<div class="dimmer"></div>
|
||||||
|
|
||||||
<div class="toTop">
|
<div class="toTop">
|
||||||
⬆ Вверх
|
⬆ {_to_top}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="layout">
|
<div class="layout">
|
||||||
<div id="xhead" class="dm"></div>
|
<div id="xhead" class="dm"></div>
|
||||||
<div class="page_header {if $instance_name != OPENVK_DEFAULT_INSTANCE_NAME}page_custom_header{/if}">
|
<div class="page_header {if $instance_name != OPENVK_DEFAULT_INSTANCE_NAME}page_custom_header{/if}">
|
||||||
<a href="/" class="home_button {if $instance_name != OPENVK_DEFAULT_INSTANCE_NAME}home_button_custom{/if}" title="{$instance_name}">{$instance_name}</a>
|
<a href="/" class="home_button {if $instance_name != OPENVK_DEFAULT_INSTANCE_NAME}home_button_custom{/if}" title="{$instance_name}">{$instance_name}</a>
|
||||||
<div n:if="isset($thisUser) ? !$thisUser->isBanned() : true" class="header_navigation">
|
<div n:if="isset($thisUser) ? (!$thisUser->isBanned() XOR !$thisUser->isActivated()) : true" class="header_navigation">
|
||||||
{ifset $thisUser}
|
{ifset $thisUser}
|
||||||
<div class="link">
|
<div class="link">
|
||||||
<a href="/">{_"header_home"}</a>
|
<a href="/">{_header_home}</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="link">
|
<div class="link">
|
||||||
<a href="/search?type=groups">{_"header_groups"}</a>
|
<a href="/search?type=groups">{_header_groups}</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="link">
|
<div class="link">
|
||||||
<a href="/search">{_"header_search"}</a>
|
<a href="/search">{_header_search}</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="link">
|
<div class="link">
|
||||||
<a href="/invite">
|
<a href="/invite">{_header_invite}</a>
|
||||||
{_"header_invite"}
|
</div>
|
||||||
</a>
|
<div class="link">
|
||||||
</div>
|
<a href="/support">{_header_help} <b n:if="$ticketAnsweredCount > 0">({$ticketAnsweredCount})</b></a>
|
||||||
<div class="link">
|
</div>
|
||||||
<a href="/support">
|
<div class="link">
|
||||||
{_"header_help"}
|
<a href="/logout?hash={urlencode($csrfToken)}">{_header_log_out}</a>
|
||||||
<b n:if="$ticketAnsweredCount > 0">({$ticketAnsweredCount})</b>
|
</div>
|
||||||
</a>
|
<div class="link">
|
||||||
</div>
|
<form action="/search" method="get">
|
||||||
<div class="link">
|
<input type="search" name="query" placeholder="{_header_search}" style="height: 20px;background: url('/assets/packages/static/openvk/img/search_icon.png') no-repeat 3px 4px; background-color: #fff; padding-left: 18px;width: 120px;" />
|
||||||
<a href="/logout?hash={urlencode($csrfToken)}">{_"header_log_out"}</a>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
<div class="link">
|
|
||||||
<form action="/search" method="get">
|
|
||||||
<input type="search" name="query" placeholder="{_"header_search"}" style="height: 20px;background: url('/assets/packages/static/openvk/img/search_icon.png') no-repeat 3px 4px; background-color: #fff; padding-left: 18px;width: 120px;" />
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
{else}
|
{else}
|
||||||
<div class="link">
|
<div class="link">
|
||||||
<a href="/login">{_"header_login"}</a>
|
<a href="/login">{_header_login}</a>
|
||||||
</div>
|
</div>
|
||||||
<div n:if="OPENVK_ROOT_CONF['openvk']['preferences']['registration']['enable']" class="link">
|
<div n:if="OPENVK_ROOT_CONF['openvk']['preferences']['registration']['enable']" class="link">
|
||||||
<a href="/reg">{_"header_registration"}</a>
|
<a href="/reg">{_header_registration}</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="link">
|
<div class="link">
|
||||||
<a href="/support">{_"header_help"}</a>
|
<a href="/support">{_header_help}</a>
|
||||||
</div>
|
</div>
|
||||||
{/ifset}
|
{/ifset}
|
||||||
</div>
|
</div>
|
||||||
|
@ -135,91 +141,77 @@
|
||||||
|
|
||||||
<div class="sidebar">
|
<div class="sidebar">
|
||||||
<div class="navigation">
|
<div class="navigation">
|
||||||
{ifset $thisUser}
|
{ifset $thisUser}
|
||||||
{if !$thisUser->isBanned()}
|
{if !$thisUser->isBanned() XOR !$thisUser->isActivated()}
|
||||||
<a href="/edit" class="link edit-button">{_"edit_button"}</a>
|
<a href="/edit" class="link edit-button">{_edit_button}</a>
|
||||||
<a href="{$thisUser->getURL()}" class="link">{_"my_page"}</a>
|
<a href="{$thisUser->getURL()}" class="link">{_my_page}</a>
|
||||||
<a href="/friends{$thisUser->getId()}" class="link">{_"my_friends"}
|
<a href="/friends{$thisUser->getId()}" class="link">{_my_friends}
|
||||||
{if $thisUser->getFollowersCount() > 0}
|
<object type="internal/link" n:if="$thisUser->getFollowersCount() > 0">
|
||||||
<object type="internal/link">
|
<a href="/friends{$thisUser->getId()}?act=incoming">
|
||||||
<a href="/friends{$thisUser->getId()}?act=incoming">
|
(<b>{$thisUser->getFollowersCount()}</b>)
|
||||||
(<b>{$thisUser->getFollowersCount()}</b>)
|
</a>
|
||||||
|
</object>
|
||||||
</a>
|
</a>
|
||||||
</object>
|
<a n:if="$thisUser->getLeftMenuItemStatus('photos')" href="/albums{$thisUser->getId()}" class="link">{_my_photos}</a>
|
||||||
{/if}</a>
|
<a n:if="$thisUser->getLeftMenuItemStatus('videos')" href="/videos{$thisUser->getId()}" class="link">{_my_videos}</a>
|
||||||
<a n:if="$thisUser->getLeftMenuItemStatus('photos')" href="/albums{$thisUser->getId()}" class="link">{_"my_photos"}</a>
|
<a n:if="$thisUser->getLeftMenuItemStatus('messages')" href="/im" class="link">{_my_messages}
|
||||||
<a n:if="$thisUser->getLeftMenuItemStatus('videos')" href="/videos{$thisUser->getId()}" class="link">{_"my_videos"}</a>
|
<object type="internal/link" n:if="$thisUser->getUnreadMessagesCount() > 0">
|
||||||
<a n:if="$thisUser->getLeftMenuItemStatus('messages')" href="/im" class="link">{_"my_messages"}
|
(<b>{$thisUser->getUnreadMessagesCount()}</b>)
|
||||||
{if $thisUser->getUnreadMessagesCount() > 0}
|
</object>
|
||||||
<object type="internal/link">
|
</a>
|
||||||
(<b>{$thisUser->getUnreadMessagesCount()}</b>)
|
<a n:if="$thisUser->getLeftMenuItemStatus('notes')" href="/notes{$thisUser->getId()}" class="link">{_my_notes}</a>
|
||||||
</object>
|
<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">{_my_feed}</a>
|
||||||
|
<a href="/notifications" class="link">{_my_feedback}
|
||||||
|
{if $thisUser->getNotificationsCount() > 0}
|
||||||
|
(<b>{$thisUser->getNotificationsCount()}</b>)
|
||||||
|
{/if}
|
||||||
|
</a>
|
||||||
|
<a href="/settings" class="link">{_my_settings}</a>
|
||||||
|
|
||||||
{/if}
|
{var canAccessAdminPanel = $thisUser->getChandlerUser()->can("access")->model("admin")->whichBelongsTo(NULL)}
|
||||||
</a>
|
{var canAccessHelpdesk = $thisUser->getChandlerUser()->can("write")->model('openvk\Web\Models\Entities\TicketReply')->whichBelongsTo(0)}
|
||||||
<a n:if="$thisUser->getLeftMenuItemStatus('notes')" href="/notes{$thisUser->getId()}" class="link">{_"my_notes"}</a>
|
{var menuLinksAvaiable = sizeof(OPENVK_ROOT_CONF['openvk']['preferences']['menu']['links']) > 0 && $thisUser->getLeftMenuItemStatus('links')}
|
||||||
<a n:if="$thisUser->getLeftMenuItemStatus('groups')" href="/groups{$thisUser->getId()}" class="link">{_"my_groups"}</a>
|
<div n:if="$canAccessAdminPanel || $canAccessHelpdesk || $menuLinksAvaiable" class="menu_divider"></div>
|
||||||
<a n:if="$thisUser->getLeftMenuItemStatus('news')" href="/feed" class="link">{_"my_feed"}</a>
|
<a href="/admin" class="link" n:if="$canAccessAdminPanel">Админ-панель</a>
|
||||||
<a href="/notifications" class="link">{_my_feedback}
|
<a href="/support/tickets" class="link" n:if="$canAccessHelpdesk">Helpdesk
|
||||||
{if $thisUser->getNotificationsCount() > 0}
|
|
||||||
(<b>{$thisUser->getNotificationsCount()}</b>)
|
|
||||||
{/if}
|
|
||||||
</a>
|
|
||||||
<a href="/settings" class="link">{_"my_settings"}</a>
|
|
||||||
{var canAccessAdminPanel = $thisUser->getChandlerUser()->can("access")->model("admin")->whichBelongsTo(NULL)}
|
|
||||||
{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>
|
|
||||||
{if $canAccessAdminPanel}
|
|
||||||
<a href="/admin" class="link">Админ-панель</a>
|
|
||||||
{/if}
|
|
||||||
{if $canAccessHelpdesk}
|
|
||||||
<a href="/support/tickets" class="link">Helpdesk
|
|
||||||
{if $helpdeskTicketNotAnsweredCount > 0}
|
{if $helpdeskTicketNotAnsweredCount > 0}
|
||||||
(<b>{$helpdeskTicketNotAnsweredCount}</b>)
|
(<b>{$helpdeskTicketNotAnsweredCount}</b>)
|
||||||
{/if}
|
{/if}
|
||||||
</a>
|
</a>
|
||||||
{/if}
|
|
||||||
<a
|
|
||||||
n:if="$thisUser->getLeftMenuItemStatus('links')"
|
|
||||||
n:foreach="OPENVK_ROOT_CONF['openvk']['preferences']['menu']['links'] as $menuItem"
|
|
||||||
href="{$menuItem['url']}"
|
|
||||||
target="_blank"
|
|
||||||
class="link">{strpos($menuItem["name"], "@") === 0 ? tr(substr($menuItem["name"], 1)) : $menuItem["name"]}</a>
|
|
||||||
<div id="_groupListPinnedGroups">
|
|
||||||
<div n:if="$thisUser->getPinnedClubCount() > 0" class="menu_divider"></div>
|
|
||||||
<a
|
|
||||||
n:foreach="$thisUser->getPinnedClubs() as $club"
|
|
||||||
href="{$club->getURL()}"
|
|
||||||
class="link group_link">{$club->getName()}</a>
|
|
||||||
|
|
||||||
</div>
|
<a n:if="$thisUser->getLeftMenuItemStatus('links')" n:foreach="OPENVK_ROOT_CONF['openvk']['preferences']['menu']['links'] as $menuItem" href="{$menuItem['url']}" target="_blank" class="link">{strpos($menuItem["name"], "@") === 0 ? tr(substr($menuItem["name"], 1)) : $menuItem["name"]}</a>
|
||||||
<a
|
|
||||||
n:if="OPENVK_ROOT_CONF['openvk']['preferences']['adPoster']['enable']"
|
<div id="_groupListPinnedGroups">
|
||||||
href="{php echo OPENVK_ROOT_CONF['openvk']['preferences']['adPoster']['link']}" >
|
<div n:if="$thisUser->getPinnedClubCount() > 0" class="menu_divider"></div>
|
||||||
<img
|
<a n:foreach="$thisUser->getPinnedClubs() as $club" href="{$club->getURL()}" class="link group_link">{$club->getName()}</a>
|
||||||
src="{php echo OPENVK_ROOT_CONF['openvk']['preferences']['adPoster']['src']}"
|
</div>
|
||||||
alt="{php echo OPENVK_ROOT_CONF['openvk']['preferences']['adPoster']['caption']}"
|
<a n:if="OPENVK_ROOT_CONF['openvk']['preferences']['adPoster']['enable'] && $thisUser->getLeftMenuItemStatus('poster')" href="{php echo OPENVK_ROOT_CONF['openvk']['preferences']['adPoster']['link']}" >
|
||||||
class="psa-poster"
|
<img src="{php echo OPENVK_ROOT_CONF['openvk']['preferences']['adPoster']['src']}" alt="{php echo OPENVK_ROOT_CONF['openvk']['preferences']['adPoster']['caption']}" class="psa-poster" style="max-width: 100%; margin-top: 50px;" />
|
||||||
style="max-width: 100%; margin-top: 50px;" />
|
</a>
|
||||||
</a>
|
{elseif !$thisUser->isActivated()}
|
||||||
|
<a href="/logout?hash={urlencode($csrfToken)}" class="link">{_menu_logout}</a>
|
||||||
|
{else}
|
||||||
|
<a href="/support" class="link">{_menu_support}
|
||||||
|
{if $ticketAnsweredCount > 0}
|
||||||
|
(<b>{$ticketAnsweredCount}</b>)
|
||||||
|
{/if}
|
||||||
|
</a>
|
||||||
|
<a href="/logout?hash={urlencode($csrfToken)}" class="link">{_menu_logout}</a>
|
||||||
|
{/if}
|
||||||
{else}
|
{else}
|
||||||
<a href="/support" class="link">{_"menu_support"}</a>
|
<form id="fastLogin" action="/login" method="POST" enctype="multipart/form-data">
|
||||||
<a href="/logout?hash={urlencode($csrfToken)}" class="link">{_"menu_logout"}</a>
|
<label for="login"><span>{_email}:</span></label>
|
||||||
{/if}
|
<input id="login" type="text" name="login" required />
|
||||||
{else}
|
<label for="password"><span>{_password}:</span></label>
|
||||||
<form id="fastLogin" action="/login" method="POST" enctype="multipart/form-data">
|
<input id="password" type="password" name="password" required />
|
||||||
<label for="login"><span>{_"email"}:</span></label>
|
<input type="hidden" name="jReturnTo" value="{$_SERVER['REQUEST_URI']}" />
|
||||||
<input id="login" type="text" name="login" required />
|
<input type="hidden" name="hash" value="{$csrfToken}" />
|
||||||
<label for="password"><span>{_"password"}:</span></label>
|
<input type="submit" value="{_log_in}" class="button" style="display: inline-block;" />
|
||||||
<input id="password" type="password" name="password" required />
|
<a n:if="OPENVK_ROOT_CONF['openvk']['preferences']['registration']['enable']" href="/reg" class="button" style="display: inline-block;">{_registration}</a><br><br>
|
||||||
<input type="hidden" name="jReturnTo" value="{$_SERVER['REQUEST_URI']}" />
|
<a href="/restore">{_forgot_password}</a>
|
||||||
<input type="hidden" name="hash" value="{$csrfToken}" />
|
</form>
|
||||||
<input type="submit" value="{_'log_in'}" class="button" style="display: inline-block;" />
|
{/ifset}
|
||||||
<a n:if="OPENVK_ROOT_CONF['openvk']['preferences']['registration']['enable']" href="/reg" class="button" style="display: inline-block;" >{_registration}</a><br><br>
|
|
||||||
<a href="/restore.pl">{_"forgot_password"}</a>
|
|
||||||
</form>
|
|
||||||
{/ifset}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -227,39 +219,34 @@
|
||||||
<div id="wrapH">
|
<div id="wrapH">
|
||||||
<div id="wrapHI">
|
<div id="wrapHI">
|
||||||
<div n:ifcontent class="page_yellowheader">
|
<div n:ifcontent class="page_yellowheader">
|
||||||
{include header}
|
{include header}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{ifset wrap}
|
{ifset wrap}
|
||||||
{ifset $flashMessage}
|
<div class="msg msg_{$flashMessage->type}" n:ifset="$flashMessage">
|
||||||
<div class="msg msg_{$flashMessage->type}">
|
<b>{$flashMessage->title}</b><br/>
|
||||||
|
{$flashMessage->msg|noescape}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{include wrap}
|
||||||
|
{else}
|
||||||
|
<div class="wrap2">
|
||||||
|
<div class="wrap1">
|
||||||
|
<div id="auth" class="page-wrap">
|
||||||
|
<div class="page_content">
|
||||||
|
<div class="msg msg_{$flashMessage->type}" n:ifset="$flashMessage">
|
||||||
<b>{$flashMessage->title}</b><br/>
|
<b>{$flashMessage->title}</b><br/>
|
||||||
{$flashMessage->msg|noescape}
|
{$flashMessage->msg|noescape}
|
||||||
</div>
|
</div>
|
||||||
{/ifset}
|
|
||||||
|
|
||||||
{include wrap}
|
{include content}
|
||||||
{else}
|
|
||||||
<div class="wrap2">
|
|
||||||
<div class="wrap1">
|
|
||||||
<div id="auth" class="page-wrap">
|
|
||||||
<div class="page_content">
|
|
||||||
{ifset $flashMessage}
|
|
||||||
<div class="msg msg_{$flashMessage->type}">
|
|
||||||
<b>{$flashMessage->title}</b><br/>
|
|
||||||
{$flashMessage->msg|noescape}
|
|
||||||
</div>
|
|
||||||
{/ifset}
|
|
||||||
|
|
||||||
{include content}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
{/ifset}
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/ifset}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -267,6 +254,7 @@
|
||||||
{var dbVersion = \Chandler\Database\DatabaseConnection::i()->getConnection()->getPdo()->getAttribute(\PDO::ATTR_SERVER_VERSION)}
|
{var dbVersion = \Chandler\Database\DatabaseConnection::i()->getConnection()->getPdo()->getAttribute(\PDO::ATTR_SERVER_VERSION)}
|
||||||
|
|
||||||
<div class="navigation_footer">
|
<div class="navigation_footer">
|
||||||
|
<a href="/about" class="link">{_footer_about_instance}</a>
|
||||||
<a href="/blog" class="link">{_footer_blog}</a>
|
<a href="/blog" class="link">{_footer_blog}</a>
|
||||||
<a href="/support" class="link">{_footer_help}</a>
|
<a href="/support" class="link">{_footer_help}</a>
|
||||||
<a href="/dev" target="_blank" class="link">{_footer_developers}</a>
|
<a href="/dev" target="_blank" class="link">{_footer_developers}</a>
|
||||||
|
@ -274,7 +262,7 @@
|
||||||
<a href="/privacy" class="link">{_footer_privacy}</a>
|
<a href="/privacy" class="link">{_footer_privacy}</a>
|
||||||
</div>
|
</div>
|
||||||
<p>OpenVK <a href="/about:openvk">{php echo OPENVK_VERSION}</a> | PHP: {phpversion()} | DB: {$dbVersion}</p>
|
<p>OpenVK <a href="/about:openvk">{php echo OPENVK_VERSION}</a> | PHP: {phpversion()} | DB: {$dbVersion}</p>
|
||||||
<p n:ifcontent="ifcontent">
|
<p n:ifcontent>
|
||||||
{php echo OPENVK_ROOT_CONF["openvk"]["appearance"]["motd"]}
|
{php echo OPENVK_ROOT_CONF["openvk"]["appearance"]["motd"]}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
@ -292,14 +280,14 @@
|
||||||
{script "js/al_notifs.js"}
|
{script "js/al_notifs.js"}
|
||||||
{/ifset}
|
{/ifset}
|
||||||
|
|
||||||
<script src="https://unpkg.com/fartscroll@1.0.0/fartscroll.js"></script>
|
{if OPENVK_ROOT_CONF['openvk']['preferences']['bellsAndWhistles']['fartscroll']}
|
||||||
<script n:if="OPENVK_ROOT_CONF['openvk']['preferences']['bellsAndWhistles']['fartscroll']">
|
<script src="https://unpkg.com/fartscroll@1.0.0/fartscroll.js"></script>
|
||||||
fartscroll(400);
|
<script>
|
||||||
</script>
|
fartscroll(400);
|
||||||
|
</script>
|
||||||
|
{/if}
|
||||||
|
|
||||||
<script n:if="OPENVK_ROOT_CONF['openvk']['telemetry']['plausible']['enable']"
|
<script n:if="OPENVK_ROOT_CONF['openvk']['telemetry']['plausible']['enable']" async defer data-domain="{php echo OPENVK_ROOT_CONF['openvk']['telemetry']['plausible']['domain']}" src="{php echo OPENVK_ROOT_CONF['openvk']['telemetry']['plausible']['server']}js/plausible.js"></script>
|
||||||
async defer data-domain="{php echo OPENVK_ROOT_CONF['openvk']['telemetry']['plausible']['domain']}"
|
|
||||||
src="{php echo OPENVK_ROOT_CONF['openvk']['telemetry']['plausible']['server']}js/plausible.js"></script>
|
|
||||||
|
|
||||||
{ifset bodyScripts}
|
{ifset bodyScripts}
|
||||||
{include bodyScripts}
|
{include bodyScripts}
|
||||||
|
|
|
@ -2,57 +2,69 @@
|
||||||
|
|
||||||
{block wrap}
|
{block wrap}
|
||||||
<div class="page_wrap">
|
<div class="page_wrap">
|
||||||
<div n:ifset="tabs" class="tabs">
|
<div n:ifset="tabs" n:ifcontent class="tabs">
|
||||||
{include tabs}
|
{include tabs}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="container_gray">
|
{ifset size}
|
||||||
{var data = is_array($iterator) ? $iterator : iterator_to_array($iterator)}
|
{include size, x => $dat}
|
||||||
|
{/ifset}
|
||||||
|
|
||||||
{if sizeof($data) > 0}
|
{ifset specpage}
|
||||||
<div class="content" n:foreach="$data as $dat">
|
{include specpage, x => $dat}
|
||||||
<table>
|
{else}
|
||||||
<tbody>
|
<div class="container_gray">
|
||||||
<tr>
|
{var data = is_array($iterator) ? $iterator : iterator_to_array($iterator)}
|
||||||
<td valign="top">
|
|
||||||
<a href="{include link, x => $dat}">
|
|
||||||
{include preview, x => $dat}
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
<td valign="top" style="width: 100%">
|
|
||||||
<a href="{include link, x => $dat}">
|
|
||||||
<b>
|
|
||||||
{include name, x => $dat}
|
|
||||||
</b>
|
|
||||||
</a>
|
|
||||||
<br/>
|
|
||||||
|
|
||||||
{include description, x => $dat}
|
{if sizeof($data) > 0}
|
||||||
</td>
|
<div class="content" n:foreach="$data as $dat">
|
||||||
<td n:ifset="actions" valign="top" class="action_links" style="width: 150px">
|
<table>
|
||||||
{include actions, x => $dat}
|
<tbody>
|
||||||
</td>
|
<tr>
|
||||||
</tr>
|
<td valign="top">
|
||||||
</tbody>
|
<a href="{include link, x => $dat}">
|
||||||
</table>
|
{include preview, x => $dat}
|
||||||
</div>
|
</a>
|
||||||
|
</td>
|
||||||
<div style="padding: 8px;">
|
<td valign="top" style="width: 100%">
|
||||||
{include "components/paginator.xml", conf => (object) [
|
{ifset infoTable}
|
||||||
"page" => $page,
|
{include infoTable, x => $dat}
|
||||||
"count" => $count,
|
{else}
|
||||||
"amount" => sizeof($data),
|
<a href="{include link, x => $dat}">
|
||||||
"perPage" => $perPage ?? OPENVK_DEFAULT_PER_PAGE,
|
<b>
|
||||||
"atBottom" => true,
|
{include name, x => $dat}
|
||||||
]}
|
</b>
|
||||||
</div>
|
</a>
|
||||||
{else}
|
<br/>
|
||||||
{ifset customErrorMessage}
|
{include description, x => $dat}
|
||||||
{include customErrorMessage}
|
{/ifset}
|
||||||
|
</td>
|
||||||
|
<td n:ifset="actions" valign="top" class="action_links" style="width: 150px; text-transform: lowercase;">
|
||||||
|
{include actions, x => $dat}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
{include "components/paginator.xml", conf => (object) [
|
||||||
|
"page" => $page,
|
||||||
|
"count" => $count,
|
||||||
|
"amount" => sizeof($data),
|
||||||
|
"perPage" => $perPage ?? OPENVK_DEFAULT_PER_PAGE,
|
||||||
|
"atBottom" => true,
|
||||||
|
]}
|
||||||
{else}
|
{else}
|
||||||
{include "components/nothing.xml"}
|
{ifset customErrorMessage}
|
||||||
{/ifset}
|
{include customErrorMessage}
|
||||||
{/if}
|
{else}
|
||||||
</div>
|
{include "components/nothing.xml"}
|
||||||
|
{/ifset}
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
{/ifset}
|
||||||
|
|
||||||
|
{ifset bottom}
|
||||||
|
{include bottom}
|
||||||
|
{/ifset}
|
||||||
</div>
|
</div>
|
||||||
{/block}
|
{/block}
|
61
Web/Presenters/templates/About/AboutInstance.xml
Normal file
61
Web/Presenters/templates/About/AboutInstance.xml
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
{extends "../@layout.xml"}
|
||||||
|
{block title}{_about_this_instance}{/block}
|
||||||
|
|
||||||
|
{block header}
|
||||||
|
{_about_this_instance}
|
||||||
|
{/block}
|
||||||
|
|
||||||
|
{block content}
|
||||||
|
<table width="100%" cellspacing="0" cellpadding="0">
|
||||||
|
<tbody>
|
||||||
|
<tr valign="top">
|
||||||
|
<td width="250" {if sizeof($admins) > 0}style="padding-right: 10px;"{/if}>
|
||||||
|
<h4>{_statistics}</h4>
|
||||||
|
<div style="margin-top: 5px;">
|
||||||
|
{_on_this_instance_are}
|
||||||
|
<ul>
|
||||||
|
<li><span>{tr("about_users", $usersStats->all)|noescape}</span></li>
|
||||||
|
<li><span>{tr("about_online_users", $usersStats->online)|noescape}</span></li>
|
||||||
|
<li><span>{tr("about_active_users", $usersStats->active)|noescape}</span></li>
|
||||||
|
<li><span>{tr("about_groups", $clubsCount)|noescape}</span></li>
|
||||||
|
<li><span>{tr("about_wall_posts", $postsCount)|noescape}</span></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td n:if="sizeof($admins) > 0">
|
||||||
|
<h4>{_administrators}</h4>
|
||||||
|
<div style="margin-left: 5px; margin-top: 5px;">
|
||||||
|
<div n:foreach="$admins as $admin" class="avatar-list-item">
|
||||||
|
<div class="avatar">
|
||||||
|
<a href="{$admin->getURL()}">
|
||||||
|
<img class="ava" src="{$admin->getAvatarUrl()}" />
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
{* Это наверное костыль, ну да ладно *}
|
||||||
|
<div n:class="info, mb_strlen($admin->getCanonicalName()) < 22 ? info-centered">
|
||||||
|
<a href="{$admin->getURL()}" class="title">{$admin->getCanonicalName()}</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
{if sizeof($popularClubs) !== 0}
|
||||||
|
<h4>{_most_popular_groups}</h4>
|
||||||
|
<ol>
|
||||||
|
<li n:foreach="$popularClubs as $entry" style="margin-top: 5px;">
|
||||||
|
<a href="{$entry->club->getURL()}">{$entry->club->getName()}</a>
|
||||||
|
<div>
|
||||||
|
{tr("participants", $entry->subscriptions)}
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
<h4>{_rules}</h4>
|
||||||
|
<div style="margin-top: 16px;">
|
||||||
|
{presenter "openvk!Support->knowledgeBaseArticle", "rules"}
|
||||||
|
</div>
|
||||||
|
{/block}
|
|
@ -6,9 +6,50 @@
|
||||||
{/block}
|
{/block}
|
||||||
|
|
||||||
{block content}
|
{block content}
|
||||||
<div class="navigation">
|
<style>
|
||||||
{foreach $languages as $language}
|
.navigation-lang {
|
||||||
<a href="language?lg={$language['code']}&hash={urlencode($csrfToken)}" class="link"><img src="/assets/packages/static/openvk/img/flags/{$language['flag']}.gif"> {$language['native_name']}</a>
|
display: grid;
|
||||||
{/foreach}
|
grid-gap: 10px;
|
||||||
|
grid-template-columns: repeat(5, 1fr);
|
||||||
|
}
|
||||||
|
|
||||||
|
.navigation-lang .link_new {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 25px 25px 20px 25px;
|
||||||
|
text-decoration: none;
|
||||||
|
border-top: 1px solid #fff;
|
||||||
|
color: #000;
|
||||||
|
border-bottom: 0;
|
||||||
|
border-left: 0;
|
||||||
|
border-right: 0;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 11px;
|
||||||
|
cursor: pointer;
|
||||||
|
background: none;
|
||||||
|
margin-bottom: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navigation-lang .link_new:hover {
|
||||||
|
background-color: #E4E4E4;
|
||||||
|
border-top: 1px solid #CCCCCC;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<div class="navigation-lang">
|
||||||
|
{foreach $languages as $language}
|
||||||
|
{var $result = preg_match("/(.+)\((.+)\)/", $language['native_name'], $name)}
|
||||||
|
|
||||||
|
<a href="language?lg={$language['code']}&hash={urlencode($csrfToken)}" class="link_new" rel="nofollow">
|
||||||
|
<center><img src="/assets/packages/static/openvk/img/flags/{$language['flag']}.gif"></center>
|
||||||
|
<br>
|
||||||
|
{if $result == 1}
|
||||||
|
{$name[1]}
|
||||||
|
<br>
|
||||||
|
<small>{$name[2]}</small>
|
||||||
|
{else}
|
||||||
|
{$language['native_name']}
|
||||||
|
{/if}
|
||||||
|
</a>
|
||||||
|
{/foreach}
|
||||||
</div>
|
</div>
|
||||||
{/block}
|
{/block}
|
||||||
|
|
|
@ -28,8 +28,7 @@
|
||||||
text-align: center !important;
|
text-align: center !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
td,
|
td, th {
|
||||||
th {
|
|
||||||
border: 1px solid #666;
|
border: 1px solid #666;
|
||||||
vertical-align: baseline;
|
vertical-align: baseline;
|
||||||
padding: 4px 5px;
|
padding: 4px 5px;
|
||||||
|
@ -62,7 +61,7 @@
|
||||||
.h {
|
.h {
|
||||||
background-color: #13599f;
|
background-color: #13599f;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
color: #fff
|
color: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.v {
|
.v {
|
||||||
|
@ -133,7 +132,7 @@
|
||||||
<tr class="v">
|
<tr class="v">
|
||||||
<td>
|
<td>
|
||||||
This program makes use of the Chandler open-source web application server:<br/>
|
This program makes use of the Chandler open-source web application server:<br/>
|
||||||
libchandler {=CHANDLER_VER} by rem-pai
|
libchandler {=CHANDLER_VER} by Celestora
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
|
@ -362,7 +361,7 @@
|
||||||
Default OpenVK look and feel.
|
Default OpenVK look and feel.
|
||||||
</td>
|
</td>
|
||||||
<td class="v">
|
<td class="v">
|
||||||
Vladimir Barinov, Konstantin Kichulkin and Daniil Myslivets
|
Vladimir Barinov, Konstantin Kichulkin and Daniel Myslivets
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr n:foreach="$themes as $theme">
|
<tr n:foreach="$themes as $theme">
|
||||||
|
@ -396,8 +395,8 @@
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="e">
|
<td class="e">
|
||||||
Vladimir Barinov (veselcraft), Alexandra Katunina (rem-pai), Konstantin Kichulkin (kosfurler),
|
Vladimir Barinov (veselcraft), Celestora, Konstantin Kichulkin (kosfurler),
|
||||||
Nikita Volkov (sup_ban), Daniel Myslivets (myslivets), Alexander Kotov (l-lacker),
|
Nikita Volkov (sup_ban), Daniel Myslivets, Alexander Kotov (l-lacker),
|
||||||
Alexey Assemblerov (BiosNod), Ilya Prokopenko (dsrev) and Maxim Leshchenko (maksales / maksalees)
|
Alexey Assemblerov (BiosNod), Ilya Prokopenko (dsrev) and Maxim Leshchenko (maksales / maksalees)
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -459,7 +458,7 @@
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="e">Initial hosting</td>
|
<td class="e">Initial hosting</td>
|
||||||
<td class="v">Ilya Prokopenko (dsrev) and Alexandra Katunina (rem-pai)</td>
|
<td class="v">Ilya Prokopenko (dsrev) and Celestora</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="e">Initial bug-tracker hosting</td>
|
<td class="e">Initial bug-tracker hosting</td>
|
||||||
|
@ -467,22 +466,18 @@
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="e">Images</td>
|
<td class="e">Images</td>
|
||||||
<td class="v">Vladimir Barinov (veselcraft), Konstantin Kichulkin (kosfurler) and Daniil Myslivets (myslivets)</td>
|
<td class="v">Vladimir Barinov (veselcraft), Konstantin Kichulkin (kosfurler) and Daniel Myslivets</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="e">Illustrations</td>
|
<td class="e">Illustrations</td>
|
||||||
<td class="v">Ash Defenders</td>
|
<td class="v">Ash Defenders, Polina Katunina (RousPhaul)</td>
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="e">Soundtrack</td>
|
|
||||||
<td class="v">Ash Defenders</td>
|
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="e">Best barmaid</td>
|
<td class="e">Best barmaid</td>
|
||||||
<td class="v">Jill</td>
|
<td class="v">Jill</td> {* I can agree ~~ dsrev *}
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="e">Helpdesk implementation</td>
|
<td class="e">Initial Helpdesk implementation</td>
|
||||||
<td class="v">Nikita Volkov (sup_ban)</td>
|
<td class="v">Nikita Volkov (sup_ban)</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
|
@ -495,8 +490,10 @@
|
||||||
</tr>
|
</tr>
|
||||||
<tr class="e">
|
<tr class="e">
|
||||||
<td>
|
<td>
|
||||||
Vladimir Lapskiy (0x7d5), Alexander Minkin (WerySkok), Polina Katunina (RousPhaul),
|
kovaltim, Vladimir Lapskiy (0x7d5), Alexander Minkin (WerySkok), Polina Katunina (RousPhaul), veth,
|
||||||
Egor Shevchenko, Dmitriy Daemon and Ilya Prokopenko (dsrev).
|
Egor Shevchenko, Vadim Korovin (yuni), Ash Defenders,
|
||||||
|
Pavel Silaev, Dmitriy Daemon, Ilya Prokopenko (dsrev),
|
||||||
|
cmed404 and unknown tester, who disappeared shortly after trying to upload post with cat.
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
{var css = file_get_contents(OPENVK_ROOT . "/Web/static/js/node_modules/@atlassian/aui/dist/aui/aui-prototyping.css")}
|
{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}
|
{str_replace("fonts/", "/assets/packages/static/openvk/js/node_modules/@atlassian/aui/dist/aui/fonts/", $css)|noescape}
|
||||||
</style>
|
</style>
|
||||||
<title>{include title}</title>
|
<title>{include title} - Админ-панель {=OPENVK_ROOT_CONF['openvk']['appearance']['name']}</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="page">
|
<div id="page">
|
||||||
|
@ -16,7 +16,7 @@
|
||||||
<div class="aui-header-primary">
|
<div class="aui-header-primary">
|
||||||
<h1 id="logo" class="aui-header-logo aui-header-logo-textonly">
|
<h1 id="logo" class="aui-header-logo aui-header-logo-textonly">
|
||||||
<a href="/admin">
|
<a href="/admin">
|
||||||
<span class="aui-header-logo-device">OVK</span>
|
<span class="aui-header-logo-device">{=OPENVK_ROOT_CONF['openvk']['appearance']['name']}</span>
|
||||||
</a>
|
</a>
|
||||||
</h1>
|
</h1>
|
||||||
</div>
|
</div>
|
||||||
|
@ -163,9 +163,7 @@
|
||||||
</div>
|
</div>
|
||||||
<footer id="footer" role="contentinfo">
|
<footer id="footer" role="contentinfo">
|
||||||
<section class="footer-body">
|
<section class="footer-body">
|
||||||
<div id="footer-logo">
|
OpenVK <a href="/about:openvk">{php echo OPENVK_VERSION}</a> | PHP: {phpversion()} | DB: {\Chandler\Database\DatabaseConnection::i()->getConnection()->getPdo()->getAttribute(\PDO::ATTR_SERVER_VERSION)}
|
||||||
OpenVK
|
|
||||||
</div>
|
|
||||||
</section>
|
</section>
|
||||||
</footer>
|
</footer>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -79,6 +79,12 @@
|
||||||
Верификация
|
Верификация
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</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/>
|
<hr/>
|
||||||
<div class="buttons-container">
|
<div class="buttons-container">
|
||||||
<div class="buttons">
|
<div class="buttons">
|
||||||
|
|
|
@ -63,6 +63,12 @@
|
||||||
</label>
|
</label>
|
||||||
<input class="text medium-field" type="email" id="email" name="email" value="{$user->getEmail()}" />
|
<input class="text medium-field" type="email" id="email" name="email" value="{$user->getEmail()}" />
|
||||||
</div>
|
</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>
|
<hr>
|
||||||
<div class="field-group">
|
<div class="field-group">
|
||||||
<label for="city">
|
<label for="city">
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
|
|
||||||
{block content}
|
{block content}
|
||||||
<div class="container_gray">
|
<div class="container_gray">
|
||||||
<form method="POST" enctype="multipart/form-data" action="/club{$club->getId()}/setAdmin.jsp">
|
<form method="POST" enctype="multipart/form-data" action="/club{$club->getId()}/setAdmin">
|
||||||
<table cellspacing="7" cellpadding="0" width="40%" border="0" align="center">
|
<table cellspacing="7" cellpadding="0" width="40%" border="0" align="center">
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
|
|
|
@ -74,7 +74,8 @@
|
||||||
<span class="nobold">{_wall}: </span>
|
<span class="nobold">{_wall}: </span>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<input type="checkbox" name="wall" value="1" {if $club->canPost()}checked{/if}/> {_group_allow_post_for_everyone}
|
<input type="checkbox" name="wall" value="1" n:attr="checked => $club->canPost()" /> {_group_allow_post_for_everyone}<br>
|
||||||
|
<input type="checkbox" name="hide_from_global_feed" value="1" n:attr="checked => $club->isHideFromGlobalFeedEnabled()" /> {_group_hide_from_global_feed}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
|
|
|
@ -109,7 +109,7 @@
|
||||||
{var user = $x instanceof $Manager ? $x->getUser() : $x}
|
{var user = $x instanceof $Manager ? $x->getUser() : $x}
|
||||||
{var manager = $x instanceof $Manager ? $x : $club->getManager($user, !$club->canBeModifiedBy($thisUser))}
|
{var manager = $x instanceof $Manager ? $x : $club->getManager($user, !$club->canBeModifiedBy($thisUser))}
|
||||||
{if $club->canBeModifiedBy($thisUser ?? NULL)}
|
{if $club->canBeModifiedBy($thisUser ?? NULL)}
|
||||||
<a class="profile_link" href="/club{$club->getId()}/setAdmin.jsp?user={$user->getId()}&hash={rawurlencode($csrfToken)}" n:if="$club->getOwner()->getId() !== $user->getId()">
|
<a class="profile_link" href="/club{$club->getId()}/setAdmin?user={$user->getId()}&hash={rawurlencode($csrfToken)}" n:if="$club->getOwner()->getId() !== $user->getId()">
|
||||||
{if $manager}
|
{if $manager}
|
||||||
{_devote}
|
{_devote}
|
||||||
{else}
|
{else}
|
||||||
|
@ -130,12 +130,12 @@
|
||||||
{_set_comment}
|
{_set_comment}
|
||||||
</a>
|
</a>
|
||||||
{if $manager}
|
{if $manager}
|
||||||
<a class="profile_link" href="/club{$club->getId()}/setAdmin.jsp?user={$user->getId()}&hidden={(int) !$manager->isHidden()}&hash={rawurlencode($csrfToken)}">
|
<a class="profile_link" href="/club{$club->getId()}/setAdmin?user={$user->getId()}&hidden={(int) !$manager->isHidden()}&hash={rawurlencode($csrfToken)}">
|
||||||
{if $manager->isHidden()}{_hidden_yes}{else}{_hidden_no}{/if}
|
{if $manager->isHidden()}{_hidden_yes}{else}{_hidden_no}{/if}
|
||||||
</a>
|
</a>
|
||||||
{/if}
|
{/if}
|
||||||
{if $club->getOwner()->getId() == $user->getId()}
|
{if $club->getOwner()->getId() == $user->getId()}
|
||||||
<a class="profile_link" href="/club{$club->getId()}/setAdmin.jsp?user={$user->getId()}&hidden={(int) !$club->isOwnerHidden()}&hash={rawurlencode($csrfToken)}">
|
<a class="profile_link" href="/club{$club->getId()}/setAdmin?user={$user->getId()}&hidden={(int) !$club->isOwnerHidden()}&hash={rawurlencode($csrfToken)}">
|
||||||
{if $club->isOwnerHidden()}{_hidden_yes}{else}{_hidden_no}{/if}
|
{if $club->isOwnerHidden()}{_hidden_yes}{else}{_hidden_no}{/if}
|
||||||
</a>
|
</a>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
|
@ -189,7 +189,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div n:if="$albumsCount > 0">
|
<div n:if="$albumsCount > 0 || ($thisUser && $club->canBeModifiedBy($thisUser))">
|
||||||
<div class="content_title_expanded" onclick="hidePanel(this, {$albumsCount});">
|
<div class="content_title_expanded" onclick="hidePanel(this, {$albumsCount});">
|
||||||
{_"albums"}
|
{_"albums"}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
<a href="/im">{_my_messages}</a> »
|
<a href="/im">{_my_messages}</a> »
|
||||||
<a href="{$correspondent->getURL()}">{$correspondent->getCanonicalName()}</a>
|
<a href="{$correspondent->getURL()}">{$correspondent->getCanonicalName()}</a>
|
||||||
<div n:if="($online = $correspondent->getOnline()->timestamp()) < time() + 2678400" style="float: right;">
|
<div n:if="($online = $correspondent->getOnline()->timestamp()) + 2505600 > time()" style="float: right;">
|
||||||
{var diff = date_diff(date_create(), date_create('@' . $online))}
|
{var diff = date_diff(date_create(), date_create('@' . $online))}
|
||||||
{if 5 >= $diff->i}
|
{if 5 >= $diff->i}
|
||||||
<span><b>{_online}</b></span>
|
<span><b>{_online}</b></span>
|
||||||
|
@ -43,7 +43,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="messenger-app--input">
|
<div class="messenger-app--input">
|
||||||
{if $correspondent->getId() === $thisUser->getId() || ($correspondent->getSubscriptionStatus($thisUser) === 3)}
|
{if $correspondent->getId() === $thisUser->getId() || $correspondent->getPrivacyPermission('messages.write', $thisUser)}
|
||||||
<img class="ava" src="{$thisUser->getAvatarUrl()}" alt="{$thisUser->getCanonicalName()}" />
|
<img class="ava" src="{$thisUser->getAvatarUrl()}" alt="{$thisUser->getCanonicalName()}" />
|
||||||
<div class="messenger-app--input---messagebox">
|
<div class="messenger-app--input---messagebox">
|
||||||
<textarea
|
<textarea
|
||||||
|
@ -54,7 +54,7 @@
|
||||||
</div>
|
</div>
|
||||||
<img class="ava" src="{$correspondent->getAvatarUrl()}" alt="{$correspondent->getCanonicalName()}" />
|
<img class="ava" src="{$correspondent->getAvatarUrl()}" alt="{$correspondent->getCanonicalName()}" />
|
||||||
{else}
|
{else}
|
||||||
<div class="blocked" data-localized-text="Вы не можете писать сообщения {$correspondent->getCanonicalName()}, так как его нет в вашем списке друзей."></div>
|
<div class="blocked" data-localized-text="Вы не можете писать сообщения {$correspondent->getCanonicalName()} из-за его настроек приватности."></div>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="container_gray">
|
<div class="container_gray">
|
||||||
<form action="/im/search.pl" method="POST" style="margin: 0;">
|
<form action="/im/search" method="POST" style="margin: 0;">
|
||||||
<input type="text" name="pattern" placeholder="Поиск сообщений" required />
|
<input type="text" name="pattern" placeholder="Поиск сообщений" required />
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
49
Web/Presenters/templates/Notes/Edit.xml
Normal file
49
Web/Presenters/templates/Notes/Edit.xml
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
{extends "../@layout.xml"}
|
||||||
|
|
||||||
|
{block title}{_edit_note}{/block}
|
||||||
|
|
||||||
|
{block header}
|
||||||
|
{var author = $note->getOwner()}
|
||||||
|
<a href="{$author->getURL()}">{$author->getCanonicalName()}</a>
|
||||||
|
»
|
||||||
|
<a href="/notes{$author->getId()}">{_notes}</a>
|
||||||
|
»
|
||||||
|
<a href="/note{$author->getId()}_{$note->getVirtualId()}">{$note->getName()}</a>
|
||||||
|
{/block}
|
||||||
|
|
||||||
|
{block content}
|
||||||
|
<form id="noteFactory" method="POST">
|
||||||
|
<input type="text" name="name" placeholder="{_name_note}" style="width:603px;" value="{$note->getName()}" />
|
||||||
|
<br/><br/>
|
||||||
|
<textarea name="html" style="display:none;"></textarea>
|
||||||
|
<div id="editor" style="width:600px;height:300px;border:1px solid grey"></div>
|
||||||
|
|
||||||
|
<p><i><a href="/kb/notes">Кое-что</a> из (X)HTML поддерживается.</i></p>
|
||||||
|
|
||||||
|
<input type="hidden" name="hash" value="{$csrfToken}" />
|
||||||
|
<button class="button">{_save}</button>
|
||||||
|
|
||||||
|
<a href="/note{$note->getOwner()->getId()}_{$note->getVirtualId()}" class="button">{_cancel}</a>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
{script "js/node_modules/monaco-editor/min/vs/loader.js"}
|
||||||
|
{script "js/node_modules/requirejs/bin/r.js"}
|
||||||
|
<script>
|
||||||
|
require.config({
|
||||||
|
paths: {
|
||||||
|
'vs': '/assets/packages/static/openvk/js/node_modules/monaco-editor/min/vs'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
require(['vs/editor/editor.main'], function() {
|
||||||
|
window._editor = monaco.editor.create(document.getElementById('editor'), {
|
||||||
|
value: {$note->getSource()},
|
||||||
|
lineNumbers: "off",
|
||||||
|
language: "html"
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
document.querySelector("#noteFactory").addEventListener("submit", function() {
|
||||||
|
document.querySelector("textarea").value = window._editor.getValue();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
{/block}
|
|
@ -5,12 +5,25 @@
|
||||||
{block title}{_notes}{/block}
|
{block title}{_notes}{/block}
|
||||||
|
|
||||||
{block header}
|
{block header}
|
||||||
<a href="{$owner->getURL()}">{$owner->getCanonicalName()}</a>
|
{if isset($thisUser) && $thisUser->getId() == $owner->getId()}
|
||||||
»
|
{_my_notes}
|
||||||
{_notes}
|
{else}
|
||||||
|
<a href="{$owner->getURL()}">
|
||||||
|
{$owner->getCanonicalName()}</a>
|
||||||
|
»
|
||||||
|
{_notes}
|
||||||
|
{/if}
|
||||||
|
{/block}
|
||||||
|
|
||||||
<div n:if="isset($thisUser) && $thisUser->getId() == $owner->getId()" style="float:right;">
|
{block size}
|
||||||
<a href="/notes/create">{_create_note}</a>
|
<div style="padding-bottom: 0px; padding-top: 0;" class="summaryBar">
|
||||||
|
<div class="summary">
|
||||||
|
{tr("notes_list", $count)}
|
||||||
|
<span n:if="isset($thisUser) && $thisUser->getId() == $owner->getId()">
|
||||||
|
|
|
||||||
|
<a href="/notes/create">{_create_note}</a>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{/block}
|
{/block}
|
||||||
|
|
||||||
|
@ -20,18 +33,66 @@
|
||||||
|
|
||||||
{* BEGIN ELEMENTS DESCRIPTION *}
|
{* BEGIN ELEMENTS DESCRIPTION *}
|
||||||
|
|
||||||
{block link|strip|stripHtml}
|
{block specpage}
|
||||||
/note{$x->getPrettyId()}
|
<div class="container_gray" style="background: white; border-top: none;">
|
||||||
{/block}
|
|
||||||
|
|
||||||
{block preview}
|
{var data = is_array($iterator) ? $iterator : iterator_to_array($iterator)}
|
||||||
<center><img src="/assets/packages/static/openvk/img/note_icon.png" alt="{_note}" style="margin-top: 17px;" /></center>
|
{if sizeof($data) > 0}
|
||||||
{/block}
|
|
||||||
|
|
||||||
{block name}
|
<div n:foreach="$data as $dat">
|
||||||
{$x->getName()}
|
<div class="profile_thumb">
|
||||||
{/block}
|
<a href="{$owner->getURL()}">
|
||||||
|
<img src="{$owner->getAvatarUrl()}" style="width: 50px;">
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<article class="note_body" id="userContent" style="width: 540px; display: inline-block; margin-bottom: 35px;">
|
||||||
|
<div class="note_header">
|
||||||
|
<div class="note_title">
|
||||||
|
<div class="note_title">
|
||||||
|
<a href="/note{$dat->getPrettyId()}">{$dat->getName()}</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="byline">
|
||||||
|
<span><a href="{$owner->getURL()}">{$owner->getCanonicalName()}</a></span> {$dat->getPublicationTime()}
|
||||||
|
<span n:if="$dat->getEditTime() > $dat->getPublicationTime()">({_edited} {$dat->getEditTime()})</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div style="margin-left: 6px;">
|
||||||
|
{$dat->getText(750)|noescape}
|
||||||
|
</div>
|
||||||
|
<div class="note_footer" style="margin: 10px 0 0;">
|
||||||
|
<div class="comments_count">
|
||||||
|
<a href="/note{$dat->getPrettyId()}">
|
||||||
|
|
||||||
{block description}
|
{if sizeof($dat->getCommentsCount()) > 0}
|
||||||
{$x->getPreview(250)}
|
{_comments} ({$dat->getCommentsCount()})
|
||||||
|
{else}
|
||||||
|
{_no_comments}
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
</a>
|
||||||
|
<span n:if="isset($thisUser) && $thisUser->getId() === $dat->getOwner()->getId()"> |
|
||||||
|
<a id="_noteDelete" href="/note{$dat->getOwner()->getId()}_{$dat->getId()}/delete">{_delete}</a>
|
||||||
|
|
|
||||||
|
<a href="/note{$dat->getOwner()->getId()}_{$dat->getVirtualId()}/edit">{_edit}</a>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{else}
|
||||||
|
{if isset($thisUser) && $thisUser->getId() == $owner->getId()}
|
||||||
|
|
||||||
|
<div style="padding: 10px 20px 20px;"><h4 style="border: none;padding-bottom: 5px;">{_welcome}</h4>{_notes_start_screen}</div>
|
||||||
|
|
||||||
|
{else}
|
||||||
|
{ifset customErrorMessage}
|
||||||
|
{include ../customErrorMessage}
|
||||||
|
{else}
|
||||||
|
{include ../components/nothing.xml}
|
||||||
|
{/ifset}
|
||||||
|
{/if}
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
{/block}
|
{/block}
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
{/block}
|
{/block}
|
||||||
|
|
||||||
{block content}
|
{block content}
|
||||||
|
{var author = $note->getOwner()}
|
||||||
<style>
|
<style>
|
||||||
#userContent img {
|
#userContent img {
|
||||||
max-width: 245pt;
|
max-width: 245pt;
|
||||||
|
@ -34,24 +35,44 @@
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<article id="userContent" style="min-height: 300pt;">
|
<article id="userContent" style="margin: 10px 10px 0;">
|
||||||
{$note->getText()|noescape}
|
<div class="note_header">
|
||||||
</article>
|
<div class="note_title">
|
||||||
|
<div class="note_title">
|
||||||
<div style="width: 100%; min-height: 100px;">
|
<a>{$note->getName()}</a>
|
||||||
<div style="float: left; min-height: 100px; width: 70%;">
|
</div>
|
||||||
{include "../components/comments.xml",
|
</div>
|
||||||
comments => $comments,
|
<div class="byline">
|
||||||
count => $cCount,
|
<span><a href="{$author->getURL()}">{$author->getCanonicalName()}</a></span> {$note->getPublicationTime()}
|
||||||
page => $cPage,
|
<span n:if="$note->getEditTime() > $note->getPublicationTime()">({_edited} {$note->getEditTime()})</span>
|
||||||
model => "notes",
|
|
||||||
parent => $note}
|
|
||||||
</div>
|
|
||||||
<div style="float: right; min-height: 100px; width: 30%;">
|
|
||||||
<h4>{_actions}</h4>
|
|
||||||
<div n:if="isset($thisUser) && $thisUser->getId() === $note->getOwner()->getId()">
|
|
||||||
<a id="_noteDelete" href="/note{$note->getOwner()->getId()}_{$note->getId()}/delete" class="profile_link" style="display:block;width:96%;">{_delete}</a>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div style="margin-left: 6px; width: 535px;">
|
||||||
|
{$note->getText()|noescape}
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
|
|
||||||
|
<div class="note_footer" style="margin: 10px 10px 0;">
|
||||||
|
<div class="comments_count">
|
||||||
|
{if sizeof($comments) > 0}
|
||||||
|
{_comments} ({$note->getCommentsCount()})
|
||||||
|
{else}
|
||||||
|
{_no_comments}
|
||||||
|
{/if}
|
||||||
|
<span n:if="isset($thisUser) && $thisUser->getId() === $note->getOwner()->getId()"> |
|
||||||
|
<a id="_noteDelete" href="/note{$note->getOwner()->getId()}_{$note->getId()}/delete">{_delete}</a>
|
||||||
|
|
|
||||||
|
<a href="/note{$note->getOwner()->getId()}_{$note->getVirtualId()}/edit">{_edit}</a>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div style="margin: 6px 10px 10px;border-top: 1px solid #ddd;">
|
||||||
|
{include "../components/comments.xml",
|
||||||
|
comments => $comments,
|
||||||
|
count => $cCount,
|
||||||
|
page => $cPage,
|
||||||
|
model => "notes",
|
||||||
|
parent => $note,
|
||||||
|
showTitle => false}
|
||||||
</div>
|
</div>
|
||||||
{/block}
|
{/block}
|
||||||
|
|
|
@ -35,7 +35,7 @@
|
||||||
<div class="album-photo">
|
<div class="album-photo">
|
||||||
<a
|
<a
|
||||||
n:if="!is_null($thisUser) && $album->canBeModifiedBy($thisUser)"
|
n:if="!is_null($thisUser) && $album->canBeModifiedBy($thisUser)"
|
||||||
href="/album{$album->getPrettyId()}/remove_photo.pl/{$photo->getId()}" class="album-photo--delete">
|
href="/album{$album->getPrettyId()}/remove_photo/{$photo->getId()}" class="album-photo--delete">
|
||||||
×
|
×
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
|
|
|
@ -28,11 +28,9 @@
|
||||||
{var cover = $x->getCoverPhoto()}
|
{var cover = $x->getCoverPhoto()}
|
||||||
{var preview = is_null($cover) ? "/assets/packages/static/openvk/img/camera_200.png" : $cover->getURL()}
|
{var preview = is_null($cover) ? "/assets/packages/static/openvk/img/camera_200.png" : $cover->getURL()}
|
||||||
|
|
||||||
<center style="height: 54pt; width: 140px;">
|
<a href="/album{$x->getPrettyId()}">
|
||||||
<a href="/album{$x->getPrettyId()}">
|
<img src="{$preview}" alt="{$x->getName()}" style="height: 130px; width: 170px; object-fit: cover" />
|
||||||
<img src="{$preview}" alt="{$x->getName()}" style="max-height: 100%; max-width: 100%;" />
|
</a>
|
||||||
</a>
|
|
||||||
</center>
|
|
||||||
{/block}
|
{/block}
|
||||||
|
|
||||||
{block name}
|
{block name}
|
||||||
|
@ -40,8 +38,8 @@
|
||||||
{/block}
|
{/block}
|
||||||
|
|
||||||
{block description}
|
{block description}
|
||||||
<span>{$x->getDescription() ?? $x->getName()}</span><br/>
|
<span>{$x->getDescription() ?? $x->getName()}</span><br />
|
||||||
<span style="color: grey;">{$x->getPhotosCount()} фотографий</span><br/>
|
<span style="color: grey;">{$x->getPhotosCount()} фотографий</span><br />
|
||||||
<span style="color: grey;">Создан {$x->getCreationTime()}</span><br/>
|
<span style="color: grey;">Обновлен {$x->getEditTime() ?? $x->getCreationTime()}</span><br />
|
||||||
<span style="color: grey;">Изменён {$x->getEditTime() ?? $x->getCreationTime()}</span>
|
<span style="color: grey;">Создан {$x->getCreationTime()}</span><br />
|
||||||
{/block}
|
{/block}
|
||||||
|
|
|
@ -39,6 +39,6 @@
|
||||||
</form>
|
</form>
|
||||||
<hr/>
|
<hr/>
|
||||||
<center>
|
<center>
|
||||||
{_"you_can_also"} <a href="/album{$album->getOwner()->getId()}_{$album->getId()}/delete.pl?hash={rawurlencode($csrfToken)}">{_"delete_album"}</a>.
|
{_"you_can_also"} <a href="/album{$album->getOwner() instanceof openvk\Web\Models\Entities\Club ? '-' : ''}{$album->getOwner()->getId()}_{$album->getId()}/delete?hash={rawurlencode($csrfToken)}">{_"delete_album"}</a>.
|
||||||
</center>
|
</center>
|
||||||
{/block}
|
{/block}
|
||||||
|
|
|
@ -6,6 +6,9 @@
|
||||||
{else}
|
{else}
|
||||||
{tr("search_for_groups")}
|
{tr("search_for_groups")}
|
||||||
{/if}
|
{/if}
|
||||||
|
{if $_GET['query']}
|
||||||
|
- {$_GET['query']}
|
||||||
|
{/if}
|
||||||
{/block}
|
{/block}
|
||||||
|
|
||||||
{block header}
|
{block header}
|
||||||
|
@ -21,12 +24,12 @@
|
||||||
|
|
||||||
{block tabs}
|
{block tabs}
|
||||||
<div {if $type === "users"}id="activetabs"{/if} class="tab">
|
<div {if $type === "users"}id="activetabs"{/if} class="tab">
|
||||||
<a {if $type === "users"}id="act_tab_a"{/if} href="/search?type=users">
|
<a {if $type === "users"}id="act_tab_a"{/if} href="/search?type=users{if $_GET['query']}&query={urlencode($_GET['query'])}{/if}">
|
||||||
{_users}
|
{_users}
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div {if $type === "groups"}id="activetabs"{/if} class="tab">
|
<div {if $type === "groups"}id="activetabs"{/if} class="tab">
|
||||||
<a {if $type === "groups"}id="act_tab_a"{/if} href="/search?type=groups">
|
<a {if $type === "groups"}id="act_tab_a"{/if} href="/search?type=groups{if $_GET['query']}&query={urlencode($_GET['query'])}{/if}">
|
||||||
{_groups}
|
{_groups}
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -6,138 +6,127 @@
|
||||||
{/block}
|
{/block}
|
||||||
|
|
||||||
{block content}
|
{block content}
|
||||||
<div class="post-author">
|
<div class="post-author">
|
||||||
<a href="#" style="font-size:13px;">
|
<a href="#" style="font-size: 13px;"><b>{$ticket->getName()}</b></a><br />
|
||||||
<b>
|
{_author}: <a href="/id{$ticket->getUser()->getId()}">{$ticket->getUser()->getFullName()}</a> | {$ticket->getUser()->getRegistrationIP()} | {_status}: {$ticket->getStatus()}.
|
||||||
{$ticket->getName()}
|
</div>
|
||||||
</b>
|
<div class="text" style="padding-top: 10px; border-bottom: #ECECEC solid 1px;">
|
||||||
</a>
|
{$ticket->getText()|noescape}
|
||||||
<br></b>{_author}: <a href="/id{$ticket->getUser()->getId()}">{$ticket->getUser()->getFullName()}</a> | {$ticket->getUser()->getRegistrationIP()} | {_status}: {$ticket->getStatus()}.
|
<br /><br />
|
||||||
</div>
|
</div>
|
||||||
<div class="text" style="padding-top: 10px;border-bottom: #ECECEC solid 1px;">
|
<div style="padding-top: 5px;">
|
||||||
{$ticket->getText()|noescape}
|
{$ticket->getTime()} |
|
||||||
<br></br>
|
<a href="/support/delete/{$id}?hash={$csrfToken}">{_delete}</a>
|
||||||
</div>
|
</div>
|
||||||
<div style="padding-top: 5px;">
|
<br />
|
||||||
{$ticket->getTime()} |
|
<div>
|
||||||
<a href="/support/delete/{$id}?hash={$csrfToken}">{_delete}</a>
|
<form action="/al_comments/create/support/reply/{$id}" method="post" style="margin: 0;">
|
||||||
</div><br/>
|
<textarea name="text" id="answer_text" style="width: 100%; resize: vertical;"></textarea>
|
||||||
<div>
|
<br />
|
||||||
<form action="/al_comments.pl/create/support/reply/{$id}" method="post" style="margin:0;">
|
<input type="hidden" name="hash" value="{$csrfToken}" />
|
||||||
<textarea name="text" id="answer_text" style="width: 100%;resize: vertical;"></textarea>
|
<br />
|
||||||
<div>
|
<div style="float: left;">
|
||||||
<!-- padding to fix <br/> bug -->
|
<input type="submit" value="{_write}" class="button" />
|
||||||
</div>
|
<select name="status" style="width: unset;">
|
||||||
<input type="hidden" name="hash" value="{$csrfToken}" />
|
<option value="1">{_support_status_1}</option>
|
||||||
<br />
|
<option value="2">{_support_status_2}</option>
|
||||||
<div style="float: left;">
|
<option value="0">{_support_status_0}</option>
|
||||||
<input type="submit" value="{_write}" class="button">
|
</select>
|
||||||
<select name="status" style="width: unset;">
|
|
||||||
<option value="1">{_support_status_1}</option>
|
|
||||||
<option value="2">{_support_status_2}</option>
|
|
||||||
<option value="0">{_support_status_0}</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<div n:if="!is_null($fastAnswers)" style="float: right;">
|
|
||||||
<a class="button" href="javascript:showSupportFastAnswerDialog(fastAnswers)">{_fast_answers}</a>
|
|
||||||
</div>
|
|
||||||
<br />
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
<br/>
|
|
||||||
<p n:if="!$comments">{_no_comments}</p>
|
|
||||||
{var $printedSupportGreeting = false}
|
|
||||||
<table n:foreach="$comments as $comment" border="0" style="font-size: 11px;" class="post">
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
{if $comment->getUType() === 0}
|
|
||||||
<td width="54" valign="top">
|
|
||||||
<img src="{$comment->getUser()->getAvatarUrl()}" width="50">
|
|
||||||
</td>
|
|
||||||
{else}
|
|
||||||
<td width="54" valign="top">
|
|
||||||
<img
|
|
||||||
src="{$comment->getAvatar()}"
|
|
||||||
style="max-width: 50px; filter: hue-rotate({$comment->getColorRotation()}deg);" />
|
|
||||||
</td>
|
|
||||||
{/if}
|
|
||||||
<td width="645" valign="top">
|
|
||||||
{if $comment->getUType() === 0}
|
|
||||||
<div class="post-author">
|
|
||||||
<a href="{$comment->getUser()->getURL()}"><b>
|
|
||||||
{$comment->getUser()->getFullName()}
|
|
||||||
</b></a> {($comment->getUser()->isFemale() ? tr("post_writes_f") : tr("post_writes_m"))}<br>
|
|
||||||
<a href="#" class="date">{$comment->getTime()}</a>
|
|
||||||
</div>
|
</div>
|
||||||
{elseif ($comment->getUType() === 1)}
|
<div n:if="!is_null($fastAnswers)" style="float: right;">
|
||||||
<div class="post-author">
|
<a class="button" href="javascript:showSupportFastAnswerDialog(fastAnswers)">{_fast_answers}</a>
|
||||||
<a href="javascript:false">
|
|
||||||
<b>
|
|
||||||
{$comment->getAuthorName()}
|
|
||||||
</b>
|
|
||||||
</a>
|
|
||||||
{if $thisUser->getChandlerUser()->can("write")->model('openvk\Web\Models\Entities\TicketReply')->whichBelongsTo(0)}
|
|
||||||
<a href="{$comment->getUser()->getURL()}">
|
|
||||||
<span class="nobold">
|
|
||||||
{var lastName = $comment->getUser()->getLastName()}
|
|
||||||
{if empty(trim($lastName))}
|
|
||||||
({$comment->getUser()->getFirstName()})
|
|
||||||
{else}
|
|
||||||
({$comment->getUser()->getFirstName()} {iconv_substr($lastName, 0, 1)}.)
|
|
||||||
{/if}
|
|
||||||
</span>
|
|
||||||
</a>
|
|
||||||
{/if}
|
|
||||||
{_post_writes_m}<br>
|
|
||||||
<a href="#" class="date">{$comment->getTime()}</a>
|
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
<br />
|
||||||
<div class="post-content" id="{$comment->getId()}">
|
</form>
|
||||||
<div class="text" id="text{$comment->getId()}">
|
</div>
|
||||||
{if $comment->getUType() === 1 && !$printedSupportGreeting}
|
<br />
|
||||||
{var $printedSupportGreeting = true}
|
<p n:if="!$comments">{_no_comments}</p>
|
||||||
{tr("support_greeting_hi", $ticket->getUser()->getFullName())}
|
{var $printedSupportGreeting = false}
|
||||||
<br/>
|
<table n:foreach="$comments as $comment" border="0" style="font-size: 11px;" class="post">
|
||||||
<br/>
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
{if $comment->getUType() === 0}
|
||||||
|
<td width="54" valign="top">
|
||||||
|
<img src="{$comment->getUser()->getAvatarUrl()}" width="50" />
|
||||||
|
</td>
|
||||||
|
{else}
|
||||||
|
<td width="54" valign="top">
|
||||||
|
<img
|
||||||
|
src="{$comment->getAvatar()}"
|
||||||
|
style="max-width: 50px; filter: hue-rotate({$comment->getColorRotation()}deg);" />
|
||||||
|
</td>
|
||||||
|
{/if}
|
||||||
|
<td width="645" valign="top">
|
||||||
|
{if $comment->getUType() === 0}
|
||||||
|
<div class="post-author">
|
||||||
|
<a href="{$comment->getUser()->getURL()}"><b>
|
||||||
|
{$comment->getUser()->getFullName()}
|
||||||
|
</b></a> {($comment->getUser()->isFemale() ? tr("post_writes_f") : tr("post_writes_m"))}<br />
|
||||||
|
<a href="#" class="date">{$comment->getTime()}</a>
|
||||||
|
</div>
|
||||||
|
{elseif ($comment->getUType() === 1)}
|
||||||
|
<div class="post-author">
|
||||||
|
<a><b>{$comment->getAuthorName()}</b></a>
|
||||||
|
{if $thisUser->getChandlerUser()->can("write")->model('openvk\Web\Models\Entities\TicketReply')->whichBelongsTo(0)}
|
||||||
|
<a href="{$comment->getUser()->getURL()}">
|
||||||
|
<span class="nobold">
|
||||||
|
{var lastName = $comment->getUser()->getLastName()}
|
||||||
|
{if empty(trim($lastName))}
|
||||||
|
({$comment->getUser()->getFirstName()})
|
||||||
|
{else}
|
||||||
|
({$comment->getUser()->getFirstName()} {iconv_substr($lastName, 0, 1)}.)
|
||||||
|
{/if}
|
||||||
|
</span>
|
||||||
|
</a>
|
||||||
|
{/if}
|
||||||
|
{_post_writes_m}<br />
|
||||||
|
<a href="#" class="date">{$comment->getTime()}</a>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
<div class="post-content" id="{$comment->getId()}">
|
||||||
|
<div class="text" id="text{$comment->getId()}">
|
||||||
|
{if $comment->getUType() === 1 && !$printedSupportGreeting}
|
||||||
|
{var $printedSupportGreeting = true}
|
||||||
|
{tr("support_greeting_hi", $ticket->getUser()->getFullName())}
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
|
||||||
{$comment->getText()|noescape}
|
{$comment->getText()|noescape}
|
||||||
<br/>
|
<br />
|
||||||
<br/>
|
<br />
|
||||||
|
|
||||||
{tr("support_greeting_regards", OPENVK_ROOT_CONF["openvk"]["appearance"]["name"])|noescape}
|
{tr("support_greeting_regards", OPENVK_ROOT_CONF["openvk"]["appearance"]["name"])|noescape}
|
||||||
{else}
|
{else}
|
||||||
{$comment->getText()|noescape}
|
{$comment->getText()|noescape}
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{if $comment->getUType() === 0}
|
<div class="post-menu">
|
||||||
<div class="post-menu">
|
<a href="/support/comment/{$comment->getId()}/delete?hash={urlencode($csrfToken)}">{_delete}</a>
|
||||||
<a href="/support/comment/{$comment->getId()}/delete">{_delete}</a>
|
</div>
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
{if $comment->getUType() === 1 && !is_null($comment->isLikedByUser())}
|
{if $comment->getUType() === 1 && !is_null($comment->isLikedByUser())}
|
||||||
<div class="post-menu">
|
<div class="post-menu">
|
||||||
<strong>
|
<strong>
|
||||||
{if $comment->isLikedByUser()}
|
{if $comment->isLikedByUser()}
|
||||||
{_support_good_answer_agent}
|
{_support_good_answer_agent}
|
||||||
{else}
|
{else}
|
||||||
{_support_bad_answer_agent}
|
{_support_bad_answer_agent}
|
||||||
|
{/if}
|
||||||
|
</strong>
|
||||||
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
</strong>
|
</div>
|
||||||
</div>
|
</td>
|
||||||
{/if}
|
</tr>
|
||||||
</div>
|
</tbody>
|
||||||
</td>
|
</table>
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
const fastAnswers = [
|
const fastAnswers = [
|
||||||
{foreach $fastAnswers as $answer}
|
{foreach $fastAnswers as $answer}
|
||||||
{$answer},
|
{$answer},
|
||||||
{/foreach}
|
{/foreach}
|
||||||
];
|
];
|
||||||
</script>
|
</script>
|
||||||
{/block}
|
{/block}
|
||||||
|
|
|
@ -6,63 +6,82 @@
|
||||||
{/block}
|
{/block}
|
||||||
|
|
||||||
{block content}
|
{block content}
|
||||||
|
{var isMain = $mode === 'faq'}
|
||||||
|
{var isNew = $mode === 'new'}
|
||||||
|
{var isList = $mode === 'list'}
|
||||||
|
|
||||||
{var isMain = $mode === 'faq'}
|
{if $thisUser}
|
||||||
{var isNew = $mode === 'new'}
|
<div class="tabs">
|
||||||
{var isList = $mode === 'list'}
|
<div n:attr="id => ($isMain ? 'activetabs' : 'ki')" class="tab">
|
||||||
|
<a n:attr="id => ($isMain ? 'act_tab_a' : 'ki')" href="/support">{_support_faq}</a>
|
||||||
{if $thisUser}
|
|
||||||
<div class="tabs">
|
|
||||||
<div n:attr="id => ($isMain ? 'activetabs' : 'ki')" class="tab">
|
|
||||||
<a n:attr="id => ($isMain ? 'act_tab_a' : 'ki')" href="/support">{_support_faq}</a>
|
|
||||||
</div>
|
|
||||||
<div n:attr="id => ($isList ? 'activetabs' : 'ki')" class="tab">
|
|
||||||
<a n:attr="id => ($isList ? 'act_tab_a' : 'ki')" href="/support?act=list">{_support_list}</a>
|
|
||||||
</div>
|
|
||||||
<div n:attr="id => ($isNew ? 'activetabs' : 'ki')" class="tab">
|
|
||||||
<a n:attr="id => ($isNew ? 'act_tab_a' : 'ki')" href="/support?act=new">{_support_new}</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<br>
|
|
||||||
|
|
||||||
{if $isNew}
|
|
||||||
<div class="new">
|
|
||||||
<form action="/support" method="post" style="margin:0;">
|
|
||||||
<center><input name="name" style="width: 80%;resize: vertical;" placeholder="{_support_new_title}"></center><br>
|
|
||||||
<center><textarea name="text" style="width: 80%;resize: vertical;" placeholder="{_support_new_content}"></textarea></center><br>
|
|
||||||
<input type="hidden" name="hash" value="{$csrfToken}" />
|
|
||||||
<center><input type="submit" value="{_write}" class="button" style="margin-left:70%;"></center><br>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
{/if}{/if}
|
|
||||||
|
|
||||||
{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>
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
{if $isList}
|
|
||||||
<table n:foreach="$tickets as $ticket" border="0" style="font-size:11px;width: 610px;" class="post">
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td width="54" valign="top">
|
|
||||||
<center><img src="/assets/packages/static/openvk/img/note_icon.png" alt="{_support_ticket}" style="margin-top: 17px;"></center>
|
|
||||||
</td>
|
|
||||||
<td width="345" valign="top">
|
|
||||||
<div class="post-author">
|
|
||||||
<a href="/support/view/{$ticket->getId()}">
|
|
||||||
<b>{$ticket->getName()}</b>
|
|
||||||
</a>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="post-content" style="padding: 4px;font-size: 11px;">
|
<div n:if="$count > 0" n:attr="id => ($isList ? 'activetabs' : 'ki')" class="tab">
|
||||||
{_status}: {$ticket->getStatus()}
|
<a n:attr="id => ($isList ? 'act_tab_a' : 'ki')" href="/support?act=list">{_support_list}</a>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
<div n:attr="id => ($isNew ? 'activetabs' : 'ki')" class="tab">
|
||||||
</tr>
|
<a n:attr="id => ($isNew ? 'act_tab_a' : 'ki')" href="/support?act=new">{_support_new}</a>
|
||||||
</tbody>
|
</div>
|
||||||
</table>
|
</div>
|
||||||
{/if}
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
{if $isNew}
|
||||||
|
<div class="new">
|
||||||
|
<form action="/support" method="post" style="margin:0;">
|
||||||
|
<center>
|
||||||
|
<input name="name" style="width: 80%; resize: vertical;" placeholder="{_support_new_title}" /><br /><br />
|
||||||
|
<textarea name="text" style="width: 80%; resize: vertical;" placeholder="{_support_new_content}"></textarea><br /><br />
|
||||||
|
<input type="hidden" name="hash" value="{$csrfToken}" />
|
||||||
|
<input type="submit" value="{_write}" class="button" style="margin-left: 70%;" /><br /><br />
|
||||||
|
</center>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
{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>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
{if $isList}
|
||||||
|
<table n:foreach="$tickets as $ticket" border="0" style="font-size: 11px; width: 610px;" class="post">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td width="54" valign="top">
|
||||||
|
<center>
|
||||||
|
<img src="/assets/packages/static/openvk/img/note_icon.png" alt="{_support_ticket}" style="margin-top: 17px;" />
|
||||||
|
</center>
|
||||||
|
</td>
|
||||||
|
<td width="345" valign="top">
|
||||||
|
<div class="post-author">
|
||||||
|
<a href="/support/view/{$ticket->getId()}">
|
||||||
|
<b>{$ticket->getName()}</b>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div class="post-content" style="padding: 4px; font-size: 11px;">
|
||||||
|
{_status}: {$ticket->getStatus()}
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
{if $count < 1}
|
||||||
|
{include "../components/nothing.xml"}
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
<div style="padding: 8px;">
|
||||||
|
{include "../components/paginator.xml", conf => (object) [
|
||||||
|
"page" => $page,
|
||||||
|
"count" => $count,
|
||||||
|
"amount" => sizeof($tickets),
|
||||||
|
"perPage" => OPENVK_DEFAULT_PER_PAGE,
|
||||||
|
"atBottom" => true,
|
||||||
|
]}
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
{/block}
|
{/block}
|
||||||
|
|
|
@ -6,144 +6,132 @@
|
||||||
{/block}
|
{/block}
|
||||||
|
|
||||||
{block content}
|
{block content}
|
||||||
<script>
|
<script>
|
||||||
function markAnswer(id, mark) {
|
function markAnswer(id, mark) {
|
||||||
let url = "/support/comment/" + id + "/rate/" + mark + "?hash=" + {urlencode($csrfToken)};
|
let url = "/support/comment/" + id + "/rate/" + mark + "?hash=" + {urlencode($csrfToken)};
|
||||||
$.ajax(url, {
|
$.ajax(url, {
|
||||||
error: errorHandler,
|
error: errorHandler,
|
||||||
success: success(id, mark)
|
success: success(id, mark)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function success(id, mark) {
|
function success(id, mark) {
|
||||||
if(mark == 1)
|
if(mark == 1)
|
||||||
document.getElementById("markText-" + id).innerHTML = {_support_good_answer_user};
|
document.getElementById("markText-" + id).innerHTML = {_support_good_answer_user};
|
||||||
else
|
else
|
||||||
document.getElementById("markText-" + id).innerHTML = {_support_bad_answer_user};
|
document.getElementById("markText-" + id).innerHTML = {_support_bad_answer_user};
|
||||||
|
|
||||||
document.getElementById("markLinks-" + id).remove();
|
document.getElementById("markLinks-" + id).remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
function errorHandler(id, mark) {
|
function errorHandler(id, mark) {
|
||||||
document.getElementById("markText-" + id).innerHTML = {_error};
|
document.getElementById("markText-" + id).innerHTML = {_error};
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
{if $ticket->isDeleted() == 0 }
|
|
||||||
<div class="post-author">
|
{if $ticket->isDeleted() == 0}
|
||||||
<a href="#" style="font-size:13px;">
|
<div class="post-author">
|
||||||
<b>
|
<a href="#" style="font-size:13px;"><b>{$ticket->getName()}</b></a>
|
||||||
{$ticket->getName()}
|
<br />{_status}: {$ticket->getStatus()}
|
||||||
</b>
|
|
||||||
</a>
|
|
||||||
<br></b>{_status}: {$ticket->getStatus()}
|
|
||||||
</div>
|
|
||||||
<div class="text" style="padding-top: 10px;border-bottom: #ECECEC solid 1px;">
|
|
||||||
{$ticket->getText()|noescape}
|
|
||||||
<br></br>
|
|
||||||
</div>
|
|
||||||
<div style="padding-top: 5px;">
|
|
||||||
{$ticket->getTime()} |
|
|
||||||
<a href="/support/delete/{$id}?hash={$csrfToken}">{_delete}</a>
|
|
||||||
</div>
|
|
||||||
{if $ticket->getType() !== 2}
|
|
||||||
<br>
|
|
||||||
<div>
|
|
||||||
<form action="/al_comments.pl/create/support/{$id}" method="post" style="margin:0;">
|
|
||||||
<textarea name="text" style="width: 100%;resize: vertical;"></textarea>
|
|
||||||
<div>
|
|
||||||
<!-- padding to fix <br/> bug -->
|
|
||||||
</div>
|
|
||||||
<input type="hidden" name="hash" value="{$csrfToken}" />
|
|
||||||
<br>
|
|
||||||
<input type="submit" value="{_write}" class="button">
|
|
||||||
</form>
|
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
<div class="text" style="padding-top: 10px; border-bottom: #ECECEC solid 1px;">
|
||||||
</br>
|
{$ticket->getText()|noescape}
|
||||||
<p n:if="!$comments">{_no_comments}</p>
|
<br /></br>
|
||||||
{var $printedSupportGreeting = false}
|
</div>
|
||||||
<table n:foreach="$comments as $comment" border="0" style="font-size: 11px;" class="post">
|
<div style="padding-top: 5px;">
|
||||||
<tbody>
|
{$ticket->getTime()} |
|
||||||
<tr>
|
<a href="/support/delete/{$id}?hash={$csrfToken}">{_delete}</a>
|
||||||
{if $comment->getUType() === 0}
|
</div>
|
||||||
<td width="54" valign="top">
|
{if $ticket->getType() !== 2}
|
||||||
<img src="{$comment->getUser()->getAvatarUrl()}" width="50">
|
<br />
|
||||||
</td>
|
<div>
|
||||||
{else}
|
<form action="/al_comments/create/support/{$id}" method="post" style="margin:0;">
|
||||||
<td width="54" valign="top">
|
<textarea name="text" style="width: 100%;resize: vertical;"></textarea><br />
|
||||||
<img
|
<input type="hidden" name="hash" value="{$csrfToken}" /><br />
|
||||||
src="{$comment->getAvatar()}"
|
<input type="submit" value="{_write}" class="button" />
|
||||||
style="max-width: 50px; filter: hue-rotate({$comment->getColorRotation()}deg);" />
|
</form>
|
||||||
</td>
|
|
||||||
{/if}
|
|
||||||
<td width="645" valign="top">
|
|
||||||
{if $comment->getUType() === 0}
|
|
||||||
<div class="post-author">
|
|
||||||
<a href="{$comment->getUser()->getURL()}"><b>
|
|
||||||
{$comment->getUser()->getFullName()}
|
|
||||||
</b></a> {($comment->getUser()->isFemale() ? tr("post_writes_f") : tr("post_writes_m"))}<br>
|
|
||||||
<a href="#" class="date">{$comment->getTime()}</a>
|
|
||||||
</div>
|
</div>
|
||||||
{elseif ($comment->getUType() === 1)}
|
{/if}
|
||||||
<div class="post-author">
|
<br />
|
||||||
<a href="javascript:false">
|
<p n:if="!$comments">{_no_comments}</p>
|
||||||
<b>
|
{var $printedSupportGreeting = false}
|
||||||
{$comment->getAuthorName()}
|
<table n:foreach="$comments as $comment" border="0" style="font-size: 11px;" class="post">
|
||||||
</b>
|
<tbody>
|
||||||
</a>
|
<tr>
|
||||||
{_post_writes_m}<br>
|
{if $comment->getUType() === 0}
|
||||||
<a href="#" class="date">{$comment->getTime()}</a>
|
<td width="54" valign="top">
|
||||||
</div>
|
<img src="{$comment->getUser()->getAvatarUrl()}" width="50" />
|
||||||
{/if}
|
</td>
|
||||||
<div class="post-content" id="{$comment->getId()}">
|
{else}
|
||||||
<div class="text" id="text{$comment->getId()}">
|
<td width="54" valign="top">
|
||||||
{if $comment->getUType() === 1 && !$printedSupportGreeting}
|
<img
|
||||||
{var $printedSupportGreeting = true}
|
src="{$comment->getAvatar()}"
|
||||||
{tr("support_greeting_hi", $ticket->getUser()->getFullName())}
|
style="max-width: 50px; filter: hue-rotate({$comment->getColorRotation()}deg);" />
|
||||||
<br/>
|
</td>
|
||||||
<br/>
|
{/if}
|
||||||
|
<td width="645" valign="top">
|
||||||
{$comment->getText()|noescape}
|
{if $comment->getUType() === 0}
|
||||||
<br/>
|
<div class="post-author">
|
||||||
<br/>
|
<a href="{$comment->getUser()->getURL()}"><b>{$comment->getUser()->getFullName()}</b></a>
|
||||||
|
{($comment->getUser()->isFemale() ? tr("post_writes_f") : tr("post_writes_m"))}<br />
|
||||||
{tr("support_greeting_regards", OPENVK_ROOT_CONF["openvk"]["appearance"]["name"])|noescape}
|
<a href="#" class="date">{$comment->getTime()}</a>
|
||||||
{else}
|
</div>
|
||||||
{$comment->getText()|noescape}
|
{elseif ($comment->getUType() === 1)}
|
||||||
{/if}
|
<div class="post-author">
|
||||||
</div>
|
<a><b>{$comment->getAuthorName()}</b></a>
|
||||||
|
{_post_writes_m}<br />
|
||||||
{if $comment->getUType() === 0}
|
<a href="#" class="date">{$comment->getTime()}</a>
|
||||||
<div class="post-menu">
|
</div>
|
||||||
<a href="/support/comment/{$comment->getId()}/delete">{_delete}</a>
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
{if $comment->getUType() === 1}
|
|
||||||
<div class="post-menu">
|
|
||||||
{var isLikedByUser = $comment->isLikedByUser()}
|
|
||||||
<strong id="markText-{$comment->getId()}">
|
|
||||||
{if !is_null($isLikedByUser)}
|
|
||||||
{if $comment->isLikedByUser()}
|
|
||||||
{_support_good_answer_user}
|
|
||||||
{else}
|
|
||||||
{_support_bad_answer_user}
|
|
||||||
{/if}
|
{/if}
|
||||||
{/if}
|
<div class="post-content" id="{$comment->getId()}">
|
||||||
</strong>
|
<div class="text" id="text{$comment->getId()}">
|
||||||
<div id="markLinks-{$comment->getId()}">
|
{if $comment->getUType() === 1 && !$printedSupportGreeting}
|
||||||
{if is_null($isLikedByUser)}
|
{var $printedSupportGreeting = true}
|
||||||
<a onClick="markAnswer({$comment->getId()}, 1)">{_support_rate_good_answer}</a>
|
{tr("support_greeting_hi", $ticket->getUser()->getFullName())}
|
||||||
|
|
<br />
|
||||||
<a onClick="markAnswer({$comment->getId()}, 2)">{_support_rate_bad_answer}</a>
|
<br />
|
||||||
{/if}
|
|
||||||
</div>
|
{$comment->getText()|noescape}
|
||||||
{/if}
|
<br />
|
||||||
</div>
|
<br />
|
||||||
</div>
|
|
||||||
</td>
|
{tr("support_greeting_regards", OPENVK_ROOT_CONF["openvk"]["appearance"]["name"])|noescape}
|
||||||
</tr>
|
{else}
|
||||||
</tbody>
|
{$comment->getText()|noescape}
|
||||||
</table>
|
{/if}
|
||||||
{/if}
|
</div>
|
||||||
|
|
||||||
|
{if $comment->getUType() === 0}
|
||||||
|
<div class="post-menu">
|
||||||
|
<a href="/support/comment/{$comment->getId()}/delete?hash={urlencode($csrfToken)}">{_delete}</a>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
{if $comment->getUType() === 1}
|
||||||
|
<div class="post-menu">
|
||||||
|
{var isLikedByUser = $comment->isLikedByUser()}
|
||||||
|
<strong id="markText-{$comment->getId()}">
|
||||||
|
{if !is_null($isLikedByUser)}
|
||||||
|
{if $comment->isLikedByUser()}
|
||||||
|
{_support_good_answer_user}
|
||||||
|
{else}
|
||||||
|
{_support_bad_answer_user}
|
||||||
|
{/if}
|
||||||
|
{/if}
|
||||||
|
</strong>
|
||||||
|
<div id="markLinks-{$comment->getId()}">
|
||||||
|
{if is_null($isLikedByUser)}
|
||||||
|
<a onClick="markAnswer({$comment->getId()}, 1)">{_support_rate_good_answer}</a>
|
||||||
|
|
|
||||||
|
<a onClick="markAnswer({$comment->getId()}, 2)">{_support_rate_bad_answer}</a>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
{/if}
|
||||||
{/block}
|
{/block}
|
||||||
|
|
|
@ -14,8 +14,8 @@
|
||||||
|
|
||||||
{block tabs}
|
{block tabs}
|
||||||
<form style="margin-left: 12px;">
|
<form style="margin-left: 12px;">
|
||||||
<input name="query" class="header_search_input" placeholder="{_"header_search"}" value="{$_GET['query'] ?? ''}" style="width: 90%" />
|
<input name="query" class="header_search_input" placeholder="{_"header_search"}" value="{$_GET['query'] ?? ''}" style="width: 86%" />
|
||||||
<input type="submit" class="button" value="{_"search_button"}" style="width: 7%" />
|
<input type="submit" class="button" value="{_"search_button"}" style="width: 7.5%" />
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<p style="margin-left: 15px;">
|
<p style="margin-left: 15px;">
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
{var isAvatar = $mode === 'avatar'}
|
{var isAvatar = $mode === 'avatar'}
|
||||||
<div n:if="$user->hasPendingNumberChange()" class="msg">
|
<div n:if="$user->hasPendingNumberChange()" class="msg">
|
||||||
<b>Подтверждение номера телефона</b><br/>
|
<b>Подтверждение номера телефона</b><br/>
|
||||||
Введите код для подтверждения смены номера: <a href="/edit/verify_phone.pl">ввести код</a>.
|
Введите код для подтверждения смены номера: <a href="/edit/verify_phone">ввести код</a>.
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="tabs">
|
<div class="tabs">
|
||||||
|
@ -80,6 +80,14 @@
|
||||||
<input type="text" name="status" value="{$user->getStatus()}" />
|
<input type="text" name="status" value="{$user->getStatus()}" />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td width="120" valign="top">
|
||||||
|
<span class="nobold">{_"hometown"}: </span>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<input type="text" name="hometown" value="{$user->getHometown()}" />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td width="120" valign="top">
|
<td width="120" valign="top">
|
||||||
<span class="nobold">{_"relationship"}: </span>
|
<span class="nobold">{_"relationship"}: </span>
|
||||||
|
@ -288,7 +296,7 @@
|
||||||
{elseif $isAvatar}
|
{elseif $isAvatar}
|
||||||
|
|
||||||
<h4>{_"profile_picture"}</h4>
|
<h4>{_"profile_picture"}</h4>
|
||||||
<form action="/al_avatars.pl" method="POST" enctype="multipart/form-data">
|
<form action="/al_avatars" method="POST" enctype="multipart/form-data">
|
||||||
<table cellspacing="7" cellpadding="0" width="60%" border="0" align="center">
|
<table cellspacing="7" cellpadding="0" width="60%" border="0" align="center">
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
|
|
|
@ -2,37 +2,45 @@
|
||||||
{var iterator = $user->getClubs($page, $admin)}
|
{var iterator = $user->getClubs($page, $admin)}
|
||||||
{var count = $user->getClubCount($admin)}
|
{var count = $user->getClubCount($admin)}
|
||||||
|
|
||||||
{block title}{_"groups"}{/block}
|
{block title}
|
||||||
|
{_groups}
|
||||||
|
{/block}
|
||||||
|
|
||||||
{block header}
|
{block header}
|
||||||
<a href="{$user->getURL()}">{$user->getCanonicalName()}</a> » {_"groups"}
|
{if !is_null($thisUser) && $user->getId() === $thisUser->getId()}
|
||||||
|
{_my_groups}
|
||||||
<div n:if="!is_null($thisUser) && $user->getId() === $thisUser->getId()" style="float:right;">
|
{else}
|
||||||
<span>
|
<a href="{$user->getURL()}">{$user->getCanonicalName()}</a> » {_groups}
|
||||||
<b>
|
{/if}
|
||||||
<a href="/groups_create">
|
|
||||||
{_"create_group"}
|
|
||||||
</a>
|
|
||||||
</b>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
{/block}
|
{/block}
|
||||||
|
|
||||||
{* BEGIN ELEMENTS DESCRIPTION *}
|
{* BEGIN ELEMENTS DESCRIPTION *}
|
||||||
|
|
||||||
{block tabs}
|
{block tabs}
|
||||||
{if !is_null($thisUser) && $user->getId() === $thisUser->getId()}
|
{if !is_null($thisUser) && $user->getId() === $thisUser->getId()}
|
||||||
<div {if !$admin}id="activetabs"{/if} class="tab">
|
<div n:attr='id => ($admin ? false : "activetabs")' class="tab">
|
||||||
<a {if !$admin}id="act_tab_a"{/if} href="/groups{$user->getId()}">
|
<a n:attr='id => ($admin ? false : "act_tab_a")' href="/groups{$user->getId()}">
|
||||||
{_groups}
|
{_groups}
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div {if $admin}id="activetabs"{/if} class="tab">
|
<div n:attr='id => (!$admin ? false : "activetabs")' class="tab">
|
||||||
<a {if $admin}id="act_tab_a"{/if} href="/groups{$user->getId()}?act=managed">
|
<a n:attr='id => (!$admin ? false : "act_tab_a")' href="/groups{$user->getId()}?act=managed">
|
||||||
{_managed}
|
{_managed}
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
{/block}
|
||||||
|
|
||||||
|
{block size}
|
||||||
|
<div n:if="!is_null($thisUser) && $user->getId() === $thisUser->getId()" style="padding-bottom: 0px; border-bottom: 0;" class="summaryBar">
|
||||||
|
<div class="summary">
|
||||||
|
{if !is_null($thisUser) && $user->getId() === $thisUser->getId()}
|
||||||
|
{tr("groups_list", $thisUser->getClubCount())}
|
||||||
|
{else}
|
||||||
|
{tr("groups", $user->getClubCount())}
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
{/block}
|
{/block}
|
||||||
|
|
||||||
{block link|strip|stripHtml}
|
{block link|strip|stripHtml}
|
||||||
|
@ -43,8 +51,21 @@
|
||||||
<img src="{$x->getAvatarUrl()}" width="75" alt="Фотография группы" />
|
<img src="{$x->getAvatarUrl()}" width="75" alt="Фотография группы" />
|
||||||
{/block}
|
{/block}
|
||||||
|
|
||||||
{block name}
|
{block name}{/block}
|
||||||
{$x->getName()}
|
|
||||||
|
{block infoTable}
|
||||||
|
<table id="basicInfo" class="ugc-table group_info" cellspacing="0" cellpadding="0" border="0">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td class="label"><span class="nobold">{_name}: </span></td>
|
||||||
|
<td class="data"><a href="{$x->getURL()}">{$x->getName()}</a></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="label"><span class="nobold">{_size}:</span></td>
|
||||||
|
<td class="data"><a href="/club{$x->getId()}/followers">{tr("participants", $x->getFollowersCount())}</a></td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
{/block}
|
{/block}
|
||||||
|
|
||||||
{block description}
|
{block description}
|
||||||
|
@ -53,13 +74,47 @@
|
||||||
|
|
||||||
{block actions}
|
{block actions}
|
||||||
{var clubPinned = $thisUser->isClubPinned($x)}
|
{var clubPinned = $thisUser->isClubPinned($x)}
|
||||||
{if $x->canBeModifiedBy($thisUser ?? NULL) && ($clubPinned || $thisUser->getPinnedClubCount() <= 10)}
|
{if $x->canBeModifiedBy($thisUser ?? NULL)}
|
||||||
<a class="profile_link" href="/groups_pin?club={$x->getId()}&hash={rawurlencode($csrfToken)}" id="_pinGroup" data-group-name="{$x->getName()}" data-group-url="{$x->getUrl()}">
|
<a style="width: 140px;" class="profile_link" href="{$x->getURL()}">
|
||||||
{if $clubPinned}
|
{_check_community}
|
||||||
{_remove_from_left_menu}
|
|
||||||
{else}
|
|
||||||
{_add_to_left_menu}
|
|
||||||
{/if}
|
|
||||||
</a>
|
</a>
|
||||||
|
{if ($clubPinned || $thisUser->getPinnedClubCount() <= 10)}
|
||||||
|
<a style="width: 140px;" class="profile_link" href="/groups_pin?club={$x->getId()}&hash={rawurlencode($csrfToken)}" id="_pinGroup" data-group-name="{$x->getName()}" data-group-url="{$x->getUrl()}">
|
||||||
|
{if $clubPinned}
|
||||||
|
{_remove_from_left_menu}
|
||||||
|
{else}
|
||||||
|
{_add_to_left_menu}
|
||||||
|
{/if}
|
||||||
|
</a>
|
||||||
|
{/if}
|
||||||
|
<form action="/setSub/club" method="post">
|
||||||
|
<input type="hidden" name="act" value="rem" />
|
||||||
|
<input type="hidden" name="id" value="{$x->getId()}" />
|
||||||
|
<input type="hidden" name="hash" value="{$csrfToken}" />
|
||||||
|
<input style="width: 140px; text-transform: lowercase;" type="submit" id="profile_link" value="{_leave_community}" />
|
||||||
|
</form>
|
||||||
|
{/if}
|
||||||
|
{/block}
|
||||||
|
|
||||||
|
{block bottom}
|
||||||
|
{if !is_null($thisUser) && $user->getId() === $thisUser->getId()}
|
||||||
|
<div class="groups_options">
|
||||||
|
<div id="gp_container" style="width: 200px; margin-right: 40px;">
|
||||||
|
<h4>{_open_new_group}</h4>
|
||||||
|
<span>{_open_group_desc}</span>
|
||||||
|
<form action="/groups_create">
|
||||||
|
<button class="button">{_create_group}</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<div id="gp_container" style="width: 344px;">
|
||||||
|
<h4>{_search_group}</h4>
|
||||||
|
<span>{_search_group_desc}</span>
|
||||||
|
<form action="/search">
|
||||||
|
<input name="type" type="hidden" value="groups">
|
||||||
|
<input name="query" class="header_search_input" value="" style="background: none; width: 155px; padding-left: 3px;">
|
||||||
|
<button class="button">{_search_by_groups}</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
{/block}
|
{/block}
|
||||||
|
|
|
@ -316,6 +316,18 @@
|
||||||
</select>
|
</select>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td width="120" valign="top">
|
||||||
|
<span class="nobold">{_privacy_setting_write_messages}</span>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<select name="messages.write", style="width: 164px;">
|
||||||
|
<option value="2" {if $user->getPrivacySetting('messages.write') == 2}selected{/if}>{_privacy_value_anybody}</option>
|
||||||
|
<option value="1" {if $user->getPrivacySetting('messages.write') == 1}selected{/if}>{_privacy_value_friends}</option>
|
||||||
|
<option value="0" {if $user->getPrivacySetting('messages.write') == 0}selected{/if}>{_privacy_value_nobody}</option>
|
||||||
|
</select>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
|
|
||||||
|
@ -450,6 +462,14 @@
|
||||||
</select>
|
</select>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td width="120" valign="top" align="right">
|
||||||
|
<input type="checkbox" name="theme_for_session" value="1">
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{_apply_style_for_this_device}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
|
|
||||||
|
@ -540,6 +560,16 @@
|
||||||
<td>
|
<td>
|
||||||
<span class="nobold">{_additional_links}</span>
|
<span class="nobold">{_additional_links}</span>
|
||||||
</td>
|
</td>
|
||||||
|
</tr><tr n:if="OPENVK_ROOT_CONF['openvk']['preferences']['adPoster']['enable']">
|
||||||
|
<td width="120" valign="top" align="right" align="right">
|
||||||
|
<input
|
||||||
|
n:attr="checked => $user->getLeftMenuItemStatus('poster')"
|
||||||
|
type="checkbox"
|
||||||
|
name="menu_standardo" />
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<span class="nobold">{_ad_poster}</span>
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
{_"two_factor_authentication_settings_1"|noescape}
|
{_"two_factor_authentication_settings_1"|noescape}
|
||||||
<p>{_"two_factor_authentication_settings_2"}</p>
|
<p>{_"two_factor_authentication_settings_2"}</p>
|
||||||
<div style="text-align: center;">
|
<div style="text-align: center;">
|
||||||
<img src="data:image/png;base64,{$qrCode}">
|
<img width="225" height="225" src="data:{$qrCodeType};base64,{$qrCodeData}">
|
||||||
</div>
|
</div>
|
||||||
<p>{tr("two_factor_authentication_settings_3", $secret)|noescape}</p>
|
<p>{tr("two_factor_authentication_settings_3", $secret)|noescape}</p>
|
||||||
<p>{_"two_factor_authentication_settings_4"}</p>
|
<p>{_"two_factor_authentication_settings_4"}</p>
|
||||||
|
|
|
@ -92,6 +92,7 @@
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<a n:if="OPENVK_ROOT_CONF['openvk']['preferences']['commerce'] && $user->getGiftCount() == 0" href="/gifts?act=pick&user={$user->getId()}" class="profile_link">{_send_gift}</a>
|
<a n:if="OPENVK_ROOT_CONF['openvk']['preferences']['commerce'] && $user->getGiftCount() == 0" href="/gifts?act=pick&user={$user->getId()}" class="profile_link">{_send_gift}</a>
|
||||||
|
<a n:if="$user->getPrivacyPermission('messages.write', $thisUser)" href="/im?sel={$user->getId()}" class="profile_link">{_"send_message"}</a>
|
||||||
|
|
||||||
{var subStatus = $user->getSubscriptionStatus($thisUser)}
|
{var subStatus = $user->getSubscriptionStatus($thisUser)}
|
||||||
{if $subStatus === 0}
|
{if $subStatus === 0}
|
||||||
|
@ -116,7 +117,6 @@
|
||||||
<input type="submit" class="profile_link" value="{_"friends_reject"}" />
|
<input type="submit" class="profile_link" value="{_"friends_reject"}" />
|
||||||
</form>
|
</form>
|
||||||
{elseif $subStatus === 3}
|
{elseif $subStatus === 3}
|
||||||
<a href="/im?sel={$user->getId()}" class="profile_link">{_"send_message"}</a>
|
|
||||||
<form action="/setSub/user" method="post" class="profile_link_form">
|
<form action="/setSub/user" method="post" class="profile_link_form">
|
||||||
<input type="hidden" name="act" value="rem" />
|
<input type="hidden" name="act" value="rem" />
|
||||||
<input type="hidden" name="id" value="{$user->getId()}" />
|
<input type="hidden" name="id" value="{$user->getId()}" />
|
||||||
|
@ -313,7 +313,7 @@
|
||||||
|
|
||||||
<div class="right_big_block">
|
<div class="right_big_block">
|
||||||
<div class="page_info">
|
<div class="page_info">
|
||||||
<div n:if="!is_null($alert = $user->getAlert())" class="user-alert">{$alert}</div>
|
<div n:if="!is_null($alert = $user->getAlert())" class="user-alert">{strpos($alert, "@") === 0 ? tr(substr($alert, 1)) : $alert}</div>
|
||||||
{var thatIsThisUser = isset($thisUser) && $user->getId() == $thisUser->getId()}
|
{var thatIsThisUser = isset($thisUser) && $user->getId() == $thisUser->getId()}
|
||||||
<div n:if="$thatIsThisUser" class="page_status_popup" id="status_editor" style="display: none;">
|
<div n:if="$thatIsThisUser" class="page_status_popup" id="status_editor" style="display: none;">
|
||||||
<form name="status_popup_form" onsubmit="changeStatus(); return false;">
|
<form name="status_popup_form" onsubmit="changeStatus(); return false;">
|
||||||
|
@ -507,7 +507,7 @@
|
||||||
(function() {
|
(function() {
|
||||||
res = document.querySelector("#uBanMsgInput").value;
|
res = document.querySelector("#uBanMsgInput").value;
|
||||||
xhr = new XMLHttpRequest();
|
xhr = new XMLHttpRequest();
|
||||||
xhr.open("GET", "/admin/ban.pl/" + {$user->getId()} + "?reason=" + res + "&hash=" + {rawurlencode($csrfToken)}, true);
|
xhr.open("GET", "/admin/ban/" + {$user->getId()} + "?reason=" + res + "&hash=" + {rawurlencode($csrfToken)}, true);
|
||||||
xhr.onload = (function() {
|
xhr.onload = (function() {
|
||||||
if(xhr.responseText.indexOf("reason") === -1)
|
if(xhr.responseText.indexOf("reason") === -1)
|
||||||
MessageBox("Ошибка", "Не удалось забанить пользователя...", ["OK"], [Function.noop]);
|
MessageBox("Ошибка", "Не удалось забанить пользователя...", ["OK"], [Function.noop]);
|
||||||
|
@ -529,7 +529,7 @@
|
||||||
(function() {
|
(function() {
|
||||||
res = document.querySelector("#uWarnMsgInput").value;
|
res = document.querySelector("#uWarnMsgInput").value;
|
||||||
xhr = new XMLHttpRequest();
|
xhr = new XMLHttpRequest();
|
||||||
xhr.open("GET", "/admin/warn.pl/" + {$user->getId()} + "?message=" + res + "&hash=" + {rawurlencode($csrfToken)}, true);
|
xhr.open("GET", "/admin/warn/" + {$user->getId()} + "?message=" + res + "&hash=" + {rawurlencode($csrfToken)}, true);
|
||||||
xhr.onload = (function() {
|
xhr.onload = (function() {
|
||||||
if(xhr.responseText.indexOf("message") === -1)
|
if(xhr.responseText.indexOf("message") === -1)
|
||||||
MessageBox("Ошибка", "Не удалось отправить предупреждение...", ["OK"], [Function.noop]);
|
MessageBox("Ошибка", "Не удалось отправить предупреждение...", ["OK"], [Function.noop]);
|
||||||
|
|
|
@ -8,9 +8,17 @@
|
||||||
{block header}
|
{block header}
|
||||||
<a href="{$user->getURL()}">{$user->getCanonicalName()}</a>
|
<a href="{$user->getURL()}">{$user->getCanonicalName()}</a>
|
||||||
» {_"videos"}
|
» {_"videos"}
|
||||||
|
{/block}
|
||||||
|
|
||||||
<div n:if="isset($thisUser) && $thisUser->getId() == $user->getId()" style="float: right;">
|
{block size}
|
||||||
<a href="/videos/upload">{_"upload_video"}</a>
|
<div style="padding-bottom: 0px;border-bottom: 0; padding-top: 0;" class="summaryBar">
|
||||||
|
<div class="summary">
|
||||||
|
{tr("videos", $count)}
|
||||||
|
<span n:if="isset($thisUser) && $thisUser->getId() == $user->getId()">
|
||||||
|
|
|
||||||
|
<a href="/videos/upload">{_upload_video}</a>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{/block}
|
{/block}
|
||||||
|
|
||||||
|
|
|
@ -4,10 +4,14 @@
|
||||||
{block header}
|
{block header}
|
||||||
{_"feed"}
|
{_"feed"}
|
||||||
|
|
||||||
<div n:if="!isset($globalFeed)" style="float: right;">
|
<div style="float: right;">
|
||||||
<span>
|
<span>
|
||||||
<b>
|
<b>
|
||||||
<a href="/feed/all">{_"all_news"}</a>
|
{if !isset($globalFeed)}
|
||||||
|
<a href="/feed/all">{_"all_news"}</a>
|
||||||
|
{else}
|
||||||
|
<a href="/feed">{_"my_feed"}</a>
|
||||||
|
{/if}
|
||||||
</b>
|
</b>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -7,16 +7,19 @@
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<td width="30" valign="top">
|
<td width="30" valign="top">
|
||||||
<img
|
<a href="{$author->getURL()}">
|
||||||
src="{$author->getAvatarURL()}"
|
<img
|
||||||
width="30"
|
src="{$author->getAvatarURL()}"
|
||||||
class="cCompactAvatars" />
|
width="30"
|
||||||
|
class="cCompactAvatars" />
|
||||||
|
</a>
|
||||||
</td>
|
</td>
|
||||||
<td width="100%" valign="top">
|
<td width="100%" valign="top">
|
||||||
<div class="post-author">
|
<div class="post-author">
|
||||||
<a href="{$author->getURL()}"><b>
|
<a href="{$author->getURL()}"><b>
|
||||||
{$author->getCanonicalName()}
|
{$author->getCanonicalName()}
|
||||||
</b></a><br/>
|
</b></a>
|
||||||
|
{if $author->isVerified()}<img class="name-checkmark" src="/assets/packages/static/openvk/img/checkmark.png">{/if}<br/>
|
||||||
</div>
|
</div>
|
||||||
<div class="post-content" id="{$comment->getId()}">
|
<div class="post-content" id="{$comment->getId()}">
|
||||||
<div class="text" id="text{$comment->getId()}">
|
<div class="text" id="text{$comment->getId()}">
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<h4 n:if="$showTitle ?? true">{_"comments"} ({$count})</h4>
|
<h4 n:if="$showTitle ?? true">{_"comments"} ({$count})</h4>
|
||||||
|
|
||||||
<div n:ifset="$thisUser">
|
<div n:ifset="$thisUser">
|
||||||
{var commentsURL = "/al_comments.pl/create/$model/" . $parent->getId()}
|
{var commentsURL = "/al_comments/create/$model/" . $parent->getId()}
|
||||||
{var club = $parent instanceof \openvk\Web\Models\Entities\Post && $parent->getTargetWall() < 0 ? (new openvk\Web\Models\Repositories\Clubs)->get(abs($parent->getTargetWall())) : $club}
|
{var club = $parent instanceof \openvk\Web\Models\Entities\Post && $parent->getTargetWall() < 0 ? (new openvk\Web\Models\Repositories\Clubs)->get(abs($parent->getTargetWall())) : $club}
|
||||||
{if !$readOnly}
|
{if !$readOnly}
|
||||||
{include "textArea.xml", route => $commentsURL, postOpts => false, graffiti => (bool) ovkGetQuirk("comments.allow-graffiti"), club => $club}
|
{include "textArea.xml", route => $commentsURL, postOpts => false, graffiti => (bool) ovkGetQuirk("comments.allow-graffiti"), club => $club}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
<center>
|
<center style="background: white;border: #DEDEDE solid 1px;">
|
||||||
<img src="/assets/packages/static/openvk/img/error.png" alt="Ошибка" />
|
<span style="color: #707070;margin: 60px 0;display: block;">
|
||||||
<h1>{$title}</h1>
|
<b>{$title}</b><br><br>
|
||||||
<p>
|
|
||||||
{$description}
|
{$description}
|
||||||
</p>
|
</span>
|
||||||
</center>
|
</center>
|
|
@ -1,16 +1,18 @@
|
||||||
{var $space = 2}
|
{var $space = 2}
|
||||||
{var $pageCount = ceil($conf->count / $conf->perPage)}
|
{var $pageCount = ceil($conf->count / $conf->perPage)}
|
||||||
|
|
||||||
<div n:if="!($conf->page === 1 && $conf->count <= $conf->perPage)" n:class="paginator, $conf->atBottom ? paginator-at-bottom">
|
<div n:if="!($conf->page === 1 && $conf->count <= $conf->perPage)" style="padding: 8px;">
|
||||||
{if $conf->page > $space}
|
<div n:class="paginator, ($conf->atBottom ?? false) ? paginator-at-bottom">
|
||||||
<a n:attr="class => ($conf->page === 1 ? 'active')" href="?{http_build_query(array_merge($_GET, ['p' => 1]), 'k', '&', PHP_QUERY_RFC3986)}">«</a>
|
{if $conf->page > $space}
|
||||||
{/if}
|
<a n:attr="class => ($conf->page === 1 ? 'active')" href="?{http_build_query(array_merge($_GET, ['p' => 1]), 'k', '&', PHP_QUERY_RFC3986)}">«</a>
|
||||||
{for $j = $conf->page - ($space-1); $j <= $conf->page + ($space-1); $j++}
|
|
||||||
{if $j > 0 && $j <= $pageCount}
|
|
||||||
<a n:attr="class => ($conf->page === $j ? 'active')" href="?{http_build_query(array_merge($_GET, ['p' => $j]), 'k', '&', PHP_QUERY_RFC3986)}">{$j}</a>
|
|
||||||
{/if}
|
{/if}
|
||||||
{/for}
|
{for $j = $conf->page - ($space-1); $j <= $conf->page + ($space-1); $j++}
|
||||||
{if $conf->page <= $pageCount-$space}
|
{if $j > 0 && $j <= $pageCount}
|
||||||
<a n:attr="class => ($conf->page === $pageCount ? 'active')" href="?{http_build_query(array_merge($_GET, ['p' => $pageCount]), 'k', '&', PHP_QUERY_RFC3986)}">»</a>
|
<a n:attr="class => ($conf->page === $j ? 'active')" href="?{http_build_query(array_merge($_GET, ['p' => $j]), 'k', '&', PHP_QUERY_RFC3986)}">{$j}</a>
|
||||||
{/if}
|
{/if}
|
||||||
|
{/for}
|
||||||
|
{if $conf->page <= $pageCount-$space}
|
||||||
|
<a n:attr="class => ($conf->page === $pageCount ? 'active')" href="?{http_build_query(array_merge($_GET, ['p' => $pageCount]), 'k', '&', PHP_QUERY_RFC3986)}">»</a>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -8,15 +8,17 @@
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<td width="54" valign="top">
|
<td width="54" valign="top">
|
||||||
<img
|
<a href="{$author->getURL()}">
|
||||||
src="{$author->getAvatarURL()}"
|
<img
|
||||||
width="{ifset $compact}25{else}50{/ifset}"
|
src="{$author->getAvatarURL()}"
|
||||||
{ifset $compact}class="cCompactAvatars"{/ifset} />
|
width="{ifset $compact}25{else}50{/ifset}"
|
||||||
{if !$post->isPostedOnBehalfOfGroup() && !$compact}
|
{ifset $compact}class="cCompactAvatars"{/ifset} />
|
||||||
<span n:if="$author->isOnline()" class="post-online">
|
{if !$post->isPostedOnBehalfOfGroup() && !$compact}
|
||||||
{_online}
|
<span n:if="$author->isOnline()" class="post-online">
|
||||||
</span>
|
{_online}
|
||||||
{/if}
|
</span>
|
||||||
|
{/if}
|
||||||
|
</a>
|
||||||
</td>
|
</td>
|
||||||
<td width="100%" valign="top">
|
<td width="100%" valign="top">
|
||||||
<div class="post-author">
|
<div class="post-author">
|
||||||
|
@ -128,8 +130,9 @@
|
||||||
{include "../comment.xml", comment => $comment, $compact => true}
|
{include "../comment.xml", comment => $comment, $compact => true}
|
||||||
{/foreach}
|
{/foreach}
|
||||||
<div n:ifset="$thisUser" id="commentTextArea{$commentTextAreaId}" n:attr="style => ($commentsCount == 0 ? 'display: none;')" class="commentsTextFieldWrap">
|
<div n:ifset="$thisUser" id="commentTextArea{$commentTextAreaId}" n:attr="style => ($commentsCount == 0 ? 'display: none;')" class="commentsTextFieldWrap">
|
||||||
{var commentsURL = "/al_comments.pl/create/posts/" . $post->getId()}
|
{var commentsURL = "/al_comments/create/posts/" . $post->getId()}
|
||||||
{include "../textArea.xml", route => $commentsURL, postOpts => false, graffiti => (bool) ovkGetQuirk("comments.allow-graffiti"), post => $post}
|
{var club = is_null($club) ? ($post->getTargetWall() < 0 ? (new openvk\Web\Models\Repositories\Clubs)->get(abs($post->getTargetWall())) : NULL) : $club}
|
||||||
|
{include "../textArea.xml", route => $commentsURL, postOpts => false, graffiti => (bool) ovkGetQuirk("comments.allow-graffiti"), post => $post, club => $club}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
|
@ -4,14 +4,17 @@
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<td width="54" valign="top">
|
<td width="54" valign="top">
|
||||||
<img
|
<a href="{$author->getURL()}">
|
||||||
src="{$author->getAvatarURL()}"
|
<img
|
||||||
width="50" />
|
src="{$author->getAvatarURL()}"
|
||||||
{if !$post->isPostedOnBehalfOfGroup() && !$compact}
|
width="50" />
|
||||||
|
</a>
|
||||||
|
{if !$post->isPostedOnBehalfOfGroup() && !($compact ?? false)}
|
||||||
<span n:if="$author->isOnline()" class="post-online">
|
<span n:if="$author->isOnline()" class="post-online">
|
||||||
{_online}
|
{_online}
|
||||||
</span>
|
</span>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
<td width="100%" valign="top">
|
<td width="100%" valign="top">
|
||||||
<div class="post-author">
|
<div class="post-author">
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
{var textAreaId = $post === null ? rand(1,300) : $post->getId()}
|
{php if(!isset($GLOBALS["textAreaCtr"])) $GLOBALS["textAreaCtr"] = 10;}
|
||||||
|
{var textAreaId = ($post ?? NULL) === null ? (++$GLOBALS["textAreaCtr"]) : $post->getId()}
|
||||||
|
|
||||||
<div id="write" style="padding: 5px 0;" onfocusin="expand_wall_textarea({$textAreaId});">
|
<div id="write" style="padding: 5px 0;" onfocusin="expand_wall_textarea({$textAreaId});">
|
||||||
<form action="{$route}" method="post" enctype="multipart/form-data" style="margin:0;">
|
<form action="{$route}" method="post" enctype="multipart/form-data" style="margin:0;">
|
||||||
|
|
|
@ -25,17 +25,17 @@ class DateTime
|
||||||
|
|
||||||
if($this->timestamp >= strtotime("midnight")) { # Today
|
if($this->timestamp >= strtotime("midnight")) { # Today
|
||||||
if($diff->h >= 1)
|
if($diff->h >= 1)
|
||||||
return tr("time_today") . tr("time_at_sp") . ovk_strftime_safe("%X", $this->timestamp);
|
return tr("time_today") . tr("time_at_sp") . ovk_strftime_safe(" %R %p", $this->timestamp);
|
||||||
else if($diff->i < 2)
|
else if($diff->i < 2)
|
||||||
return tr("time_just_now");
|
return tr("time_just_now");
|
||||||
else
|
else
|
||||||
return $diff->i === 5 ? tr("time_exactly_five_minutes_ago") : tr("time_minutes_ago", $diff->i);
|
return $diff->i === 5 ? tr("time_exactly_five_minutes_ago") : tr("time_minutes_ago", $diff->i);
|
||||||
} else if($this->timestamp >= strtotime("-1day midnight")) { # Yesterday
|
} else if($this->timestamp >= strtotime("-1day midnight")) { # Yesterday
|
||||||
return tr("time_yesterday") . tr("time_at_sp") . ovk_strftime_safe("%X", $this->timestamp);
|
return tr("time_yesterday") . tr("time_at_sp") . ovk_strftime_safe(" %R %p", $this->timestamp);
|
||||||
} else if(ovk_strftime_safe("%Y", $this->timestamp) === ovk_strftime_safe("%Y")) { # In this year
|
} else if(ovk_strftime_safe("%Y", $this->timestamp) === ovk_strftime_safe("%Y", time())) { # In this year
|
||||||
return ovk_strftime_safe("%e %h ", $this->timestamp) . tr("time_at_sp") . ovk_strftime_safe(" %R %p", $this->timestamp);
|
return ovk_strftime_safe("%e %h ", $this->timestamp) . tr("time_at_sp") . ovk_strftime_safe(" %R %p", $this->timestamp);
|
||||||
} else {
|
} else {
|
||||||
return ovk_strftime_safe("%e %B %Y ", $this->timestamp) . tr("time_at_sp") . ovk_strftime_safe(" %X", $this->timestamp);
|
return ovk_strftime_safe("%e %B %Y ", $this->timestamp) . tr("time_at_sp") . ovk_strftime_safe(" %R %p", $this->timestamp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,7 @@ services:
|
||||||
- openvk\Web\Models\Repositories\Tickets
|
- openvk\Web\Models\Repositories\Tickets
|
||||||
- openvk\Web\Models\Repositories\Messages
|
- openvk\Web\Models\Repositories\Messages
|
||||||
- openvk\Web\Models\Repositories\Restores
|
- openvk\Web\Models\Repositories\Restores
|
||||||
|
- openvk\Web\Models\Repositories\Verifications
|
||||||
- openvk\Web\Models\Repositories\Notifications
|
- openvk\Web\Models\Repositories\Notifications
|
||||||
- openvk\Web\Models\Repositories\TicketComments
|
- openvk\Web\Models\Repositories\TicketComments
|
||||||
- openvk\Web\Models\Repositories\IPs
|
- openvk\Web\Models\Repositories\IPs
|
||||||
|
|
|
@ -9,6 +9,8 @@ routes:
|
||||||
handler: "About->rules"
|
handler: "About->rules"
|
||||||
- url: "/rpc"
|
- url: "/rpc"
|
||||||
handler: "InternalAPI->route"
|
handler: "InternalAPI->route"
|
||||||
|
- url: "/iapi/timezone"
|
||||||
|
handler: "InternalAPI->timezone"
|
||||||
- url: "/support"
|
- url: "/support"
|
||||||
handler: "Support->index"
|
handler: "Support->index"
|
||||||
- url: "/support/tickets"
|
- url: "/support/tickets"
|
||||||
|
@ -19,10 +21,14 @@ routes:
|
||||||
handler: "Support->view"
|
handler: "Support->view"
|
||||||
- url: "/support/comment/{num}/rate/{num}"
|
- url: "/support/comment/{num}/rate/{num}"
|
||||||
handler: "Support->rateAnswer"
|
handler: "Support->rateAnswer"
|
||||||
- url: "/al_comments.pl/create/support/{num}"
|
- url: "/al_comments/create/support/{num}"
|
||||||
handler: "Support->makeComment"
|
handler: "Support->makeComment"
|
||||||
- url: "/al_comments.pl/create/support/reply/{num}"
|
- url: "/al_comments/create/support/reply/{num}"
|
||||||
handler: "Support->AnswerTicketReply"
|
handler: "Support->AnswerTicketReply"
|
||||||
|
- url: "/support/comment/{num}/delete"
|
||||||
|
handler: "Support->deleteComment"
|
||||||
|
- url: "/al_comments/create/{text}/{num}"
|
||||||
|
handler: "Comment->makeComment"
|
||||||
- url: "/support/delete/{num}"
|
- url: "/support/delete/{num}"
|
||||||
handler: "Support->delete"
|
handler: "Support->delete"
|
||||||
- url: "/language"
|
- url: "/language"
|
||||||
|
@ -37,6 +43,8 @@ routes:
|
||||||
handler: "About->version"
|
handler: "About->version"
|
||||||
placeholders:
|
placeholders:
|
||||||
productName: "openvk[2]?|libresoc"
|
productName: "openvk[2]?|libresoc"
|
||||||
|
- url: "/about"
|
||||||
|
handler: "About->aboutInstance"
|
||||||
- url: "/privacy"
|
- url: "/privacy"
|
||||||
handler: "About->Privacy"
|
handler: "About->Privacy"
|
||||||
- url: "/badbrowser.php"
|
- url: "/badbrowser.php"
|
||||||
|
@ -47,10 +55,14 @@ routes:
|
||||||
handler: "Auth->register"
|
handler: "Auth->register"
|
||||||
- url: "/logout"
|
- url: "/logout"
|
||||||
handler: "Auth->logout"
|
handler: "Auth->logout"
|
||||||
- url: "/restore.pl"
|
- url: "/restore"
|
||||||
handler: "Auth->restore"
|
handler: "Auth->restore"
|
||||||
- url: "/restore.pl/internal-finish"
|
- url: "/restore/internal-finish"
|
||||||
handler: "Auth->finishRestoringPassword"
|
handler: "Auth->finishRestoringPassword"
|
||||||
|
- url: "/reg/resend"
|
||||||
|
handler: "Auth->resendEmail"
|
||||||
|
- url: "/regFinish"
|
||||||
|
handler: "Auth->verifyEmail"
|
||||||
- url: "/setSID/{slug}"
|
- url: "/setSID/{slug}"
|
||||||
handler: "Auth->su"
|
handler: "Auth->su"
|
||||||
- url: "/settings"
|
- url: "/settings"
|
||||||
|
@ -67,7 +79,7 @@ routes:
|
||||||
handler: "User->friends"
|
handler: "User->friends"
|
||||||
- url: "/edit"
|
- url: "/edit"
|
||||||
handler: "User->edit"
|
handler: "User->edit"
|
||||||
- url: "/edit/verify_phone.pl"
|
- url: "/edit/verify_phone"
|
||||||
handler: "User->verifyPhone"
|
handler: "User->verifyPhone"
|
||||||
- url: "/setSub/user"
|
- url: "/setSub/user"
|
||||||
handler: "User->sub"
|
handler: "User->sub"
|
||||||
|
@ -75,8 +87,6 @@ routes:
|
||||||
handler: "Group->sub"
|
handler: "Group->sub"
|
||||||
- url: "/setSub/v4/club"
|
- url: "/setSub/v4/club"
|
||||||
handler: "Group->attend"
|
handler: "Group->attend"
|
||||||
- url: "/al_comments.pl/create/{text}/{num}"
|
|
||||||
handler: "Comment->makeComment"
|
|
||||||
- url: "/groups/{num}/setNewOwner/{num}"
|
- url: "/groups/{num}/setNewOwner/{num}"
|
||||||
handler: "Group->changeOwner"
|
handler: "Group->changeOwner"
|
||||||
- url: "/comment{num}/like"
|
- url: "/comment{num}/like"
|
||||||
|
@ -95,6 +105,8 @@ routes:
|
||||||
hashTag: ".++"
|
hashTag: ".++"
|
||||||
- url: "/wall{num}"
|
- url: "/wall{num}"
|
||||||
handler: "Wall->wall"
|
handler: "Wall->wall"
|
||||||
|
- url: "/wall{num}/rss"
|
||||||
|
handler: "Wall->rss"
|
||||||
- url: "/wall{num}/makePost"
|
- url: "/wall{num}/makePost"
|
||||||
handler: "Wall->makePost"
|
handler: "Wall->makePost"
|
||||||
- url: "/wall{num}_{num}"
|
- url: "/wall{num}_{num}"
|
||||||
|
@ -123,9 +135,9 @@ routes:
|
||||||
handler: "Photos->album"
|
handler: "Photos->album"
|
||||||
- url: "/album{num}_{num}/edit"
|
- url: "/album{num}_{num}/edit"
|
||||||
handler: "Photos->editAlbum"
|
handler: "Photos->editAlbum"
|
||||||
- url: "/album{num}_{num}/delete.pl"
|
- url: "/album{num}_{num}/delete"
|
||||||
handler: "Photos->deleteAlbum"
|
handler: "Photos->deleteAlbum"
|
||||||
- url: "/album{num}_{num}/remove_photo.pl/{num}"
|
- url: "/album{num}_{num}/remove_photo/{num}"
|
||||||
handler: "Photos->unlinkPhoto"
|
handler: "Photos->unlinkPhoto"
|
||||||
- url: "/photos/upload"
|
- url: "/photos/upload"
|
||||||
handler: "Photos->uploadPhoto"
|
handler: "Photos->uploadPhoto"
|
||||||
|
@ -137,7 +149,7 @@ routes:
|
||||||
handler: "Photos->editPhoto"
|
handler: "Photos->editPhoto"
|
||||||
- url: "/photo{num}_{num}/delete"
|
- url: "/photo{num}_{num}/delete"
|
||||||
handler: "Photos->deletePhoto"
|
handler: "Photos->deletePhoto"
|
||||||
- url: "/al_avatars.pl"
|
- url: "/al_avatars"
|
||||||
handler: "User->setAvatar"
|
handler: "User->setAvatar"
|
||||||
- url: "/videos{num}"
|
- url: "/videos{num}"
|
||||||
handler: "Videos->list"
|
handler: "Videos->list"
|
||||||
|
@ -161,7 +173,7 @@ routes:
|
||||||
handler: "Group->followers"
|
handler: "Group->followers"
|
||||||
- url: "/club{num}/followers/{num}"
|
- url: "/club{num}/followers/{num}"
|
||||||
handler: "Group->admin"
|
handler: "Group->admin"
|
||||||
- url: "/club{num}/setAdmin.jsp"
|
- url: "/club{num}/setAdmin"
|
||||||
handler: "Group->modifyAdmin"
|
handler: "Group->modifyAdmin"
|
||||||
- url: "/groups{num}"
|
- url: "/groups{num}"
|
||||||
handler: "User->groups"
|
handler: "User->groups"
|
||||||
|
@ -219,6 +231,8 @@ routes:
|
||||||
handler: "Notes->view"
|
handler: "Notes->view"
|
||||||
- url: "/notes/create"
|
- url: "/notes/create"
|
||||||
handler: "Notes->create"
|
handler: "Notes->create"
|
||||||
|
- url: "/note{num}_{num}/edit"
|
||||||
|
handler: "Notes->edit"
|
||||||
- url: "/note{num}_{num}/delete"
|
- url: "/note{num}_{num}/delete"
|
||||||
handler: "Notes->delete"
|
handler: "Notes->delete"
|
||||||
- url: "/invite"
|
- url: "/invite"
|
||||||
|
@ -253,15 +267,15 @@ routes:
|
||||||
handler: "Admin->giftCategory"
|
handler: "Admin->giftCategory"
|
||||||
- url: "/admin/gifts/{slug}.{num}/"
|
- url: "/admin/gifts/{slug}.{num}/"
|
||||||
handler: "Admin->gifts"
|
handler: "Admin->gifts"
|
||||||
- url: "/admin/ban.pl/{num}"
|
- url: "/admin/ban/{num}"
|
||||||
handler: "Admin->quickBan"
|
handler: "Admin->quickBan"
|
||||||
- url: "/admin/warn.pl/{num}"
|
- url: "/admin/warn/{num}"
|
||||||
handler: "Admin->quickWarn"
|
handler: "Admin->quickWarn"
|
||||||
- url: "/method/{text}.{text}"
|
- url: "/method/{text}.{text}"
|
||||||
handler: "VKAPI->route"
|
handler: "VKAPI->route"
|
||||||
- url: "/token"
|
- url: "/token"
|
||||||
handler: "VKAPI->tokenLogin"
|
handler: "VKAPI->tokenLogin"
|
||||||
- url: "/sandbox_cocksex"
|
- url: "/admin/sandbox"
|
||||||
handler: "About->sandbox"
|
handler: "About->sandbox"
|
||||||
- url: "/internal/wall{num}"
|
- url: "/internal/wall{num}"
|
||||||
handler: "Wall->wallEmbedded"
|
handler: "Wall->wallEmbedded"
|
||||||
|
@ -271,6 +285,10 @@ routes:
|
||||||
uri: ".+"
|
uri: ".+"
|
||||||
- url: "/nodeinfo/2.0"
|
- url: "/nodeinfo/2.0"
|
||||||
handler: "ActivityPub->nodeinfo"
|
handler: "ActivityPub->nodeinfo"
|
||||||
|
- url: "/robots.txt"
|
||||||
|
handler: "About->robotsTxt"
|
||||||
|
- url: "/humans.txt"
|
||||||
|
handler: "About->humansTxt"
|
||||||
- url: "/{?shortCode}"
|
- url: "/{?shortCode}"
|
||||||
handler: "UnknownTextRouteStrategy->delegate"
|
handler: "UnknownTextRouteStrategy->delegate"
|
||||||
placeholders:
|
placeholders:
|
||||||
|
|
|
@ -214,7 +214,7 @@ a {
|
||||||
}
|
}
|
||||||
|
|
||||||
.page_yellowheader a {
|
.page_yellowheader a {
|
||||||
color: #C8BF85;
|
color: #696029;
|
||||||
}
|
}
|
||||||
|
|
||||||
.page_content {
|
.page_content {
|
||||||
|
@ -563,6 +563,7 @@ input[type="text"], input[type="password"], input[type~="text"], input[type~="pa
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
font-family: tahoma, verdana, arial, sans-serif;
|
font-family: tahoma, verdana, arial, sans-serif;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
h4 {
|
h4 {
|
||||||
|
@ -794,9 +795,8 @@ table.User {
|
||||||
|
|
||||||
.tabs {
|
.tabs {
|
||||||
border-bottom: 1px solid #707070;
|
border-bottom: 1px solid #707070;
|
||||||
margin-left: -10px;
|
margin-right: -12px;
|
||||||
margin-right: -6px;
|
margin-left: -12px;
|
||||||
width: 627px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#activetabs {
|
#activetabs {
|
||||||
|
@ -889,7 +889,6 @@ table.User {
|
||||||
display: flex;
|
display: flex;
|
||||||
padding: 8px;
|
padding: 8px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
width: 611px;
|
|
||||||
margin-left: 1px;
|
margin-left: 1px;
|
||||||
border-bottom: 1px solid #d6d6d6;
|
border-bottom: 1px solid #d6d6d6;
|
||||||
}
|
}
|
||||||
|
@ -923,10 +922,9 @@ table.User {
|
||||||
}
|
}
|
||||||
|
|
||||||
.crp-entry--message.unread {
|
.crp-entry--message.unread {
|
||||||
background-color: #dcdcdc;
|
background-color: #ededed;
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
width: 346px;
|
width: 346px;
|
||||||
border-radius: 3px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.messenger-app--messages---message.unread {
|
.messenger-app--messages---message.unread {
|
||||||
|
@ -945,8 +943,6 @@ table.User {
|
||||||
}
|
}
|
||||||
|
|
||||||
.messenger-app--messages---message.unread:last-of-type {
|
.messenger-app--messages---message.unread:last-of-type {
|
||||||
border-bottom-left-radius: 3px;
|
|
||||||
border-bottom-right-radius: 3px;
|
|
||||||
padding-bottom: 5px;
|
padding-bottom: 5px;
|
||||||
margin-bottom: 1.2rem;
|
margin-bottom: 1.2rem;
|
||||||
}
|
}
|
||||||
|
@ -1153,6 +1149,7 @@ textarea {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding: 4px;
|
padding: 4px;
|
||||||
resize: none;
|
resize: none;
|
||||||
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
#faqhead {
|
#faqhead {
|
||||||
|
@ -1584,11 +1581,10 @@ body.scrolled .toTop:hover {
|
||||||
}
|
}
|
||||||
|
|
||||||
.postFeedWrapper {
|
.postFeedWrapper {
|
||||||
margin: -10px;
|
|
||||||
width: 611px;
|
|
||||||
padding: 4px 8px;
|
padding: 4px 8px;
|
||||||
background-color: rgb(240, 240, 240);
|
background-color: rgb(240, 240, 240);
|
||||||
border-bottom: 1px solid #ccc;
|
border-bottom: 1px solid #ccc;
|
||||||
|
border-top: 1px solid #ccc;
|
||||||
}
|
}
|
||||||
|
|
||||||
.user-alert {
|
.user-alert {
|
||||||
|
@ -1789,3 +1785,104 @@ body.scrolled .toTop:hover {
|
||||||
.hover-box:hover {
|
.hover-box:hover {
|
||||||
background-color: #C0CAD5;
|
background-color: #C0CAD5;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.summaryBar {
|
||||||
|
border-bottom: 1px solid #DAE2E8;
|
||||||
|
clear: both;
|
||||||
|
padding: 11px 10px;
|
||||||
|
color: black;
|
||||||
|
font-weight: normal;
|
||||||
|
line-height: normal;
|
||||||
|
margin-left: -12px;
|
||||||
|
margin-right: -12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.summaryBar .summary {
|
||||||
|
color: #45688E;
|
||||||
|
font-weight: bold;
|
||||||
|
padding-top: 3px;
|
||||||
|
padding-bottom: 4px;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.note_header {
|
||||||
|
background: #f7f7f7;
|
||||||
|
border-bottom: solid 1px #DAE1E8;
|
||||||
|
border-top: solid 1px #45688E;
|
||||||
|
padding: 4px 6px 5px 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.note_header .note_title {
|
||||||
|
color: #45688E;
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: bold;
|
||||||
|
line-height: 15px;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0 0 1px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.note_footer {
|
||||||
|
border-top: 1px solid #ddd;
|
||||||
|
clear: both;
|
||||||
|
margin-top: 10px;
|
||||||
|
padding: 0px 2px 0px 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.comments_count {
|
||||||
|
padding: 5px 0px 0px 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.groups_options {
|
||||||
|
padding: 10px 20px 20px;
|
||||||
|
border-top: #DEDEDE solid 1px;
|
||||||
|
margin-top: 12px;
|
||||||
|
margin-left: -12px;
|
||||||
|
margin-right: -12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#gp_container {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
#gp_container span {
|
||||||
|
display: block;
|
||||||
|
margin: 10px 0 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#gp_container h4 {
|
||||||
|
font-size: 11px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container_gray .content:last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.group_info {
|
||||||
|
padding: 0 0 0 5px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.group_info .label {
|
||||||
|
width: auto !important;
|
||||||
|
padding-right: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
table td[width="120"] {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile_thumb {
|
||||||
|
padding: 0px 10px 0px 0px;
|
||||||
|
width: 50px;
|
||||||
|
display: inline-block;
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
|
||||||
|
.border-block {
|
||||||
|
box-shadow: inset 0px 0 0px 1px #b6bfca, inset 0px 0 0px 10px #d8dfe7;
|
||||||
|
width: 300px;
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.center {
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
BIN
Web/static/img/flags/su.gif
Normal file
BIN
Web/static/img/flags/su.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 186 B |
BIN
Web/static/img/flags/udm.gif
Normal file
BIN
Web/static/img/flags/udm.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 546 B |
|
@ -5,7 +5,9 @@ u(".comment-reply").on("click", function(e) {
|
||||||
let fromGroup = Boolean(comment.data("from-group"));
|
let fromGroup = Boolean(comment.data("from-group"));
|
||||||
let postId = comment.data("post-id");
|
let postId = comment.data("post-id");
|
||||||
let inputbox = postId == null ? u("#write textarea") : u("#wall-post-input" + (postId || ""));
|
let inputbox = postId == null ? u("#write textarea") : u("#wall-post-input" + (postId || ""));
|
||||||
|
let mention = ("[" + (fromGroup ? "club" : "id") + authorId + "|" + authorNm + "], ");
|
||||||
|
|
||||||
inputbox.text("[" + (fromGroup ? "club" : "id") + authorId + "|" + authorNm + "], ");
|
// Substitute pervious mention if present, prepend otherwise
|
||||||
|
inputbox.nodes[0].value = inputbox.nodes[0].value.replace(/(^\[([A-Za-z0-9]+)\|([\p{L} 0-9@]+)\], |^)/u, mention);
|
||||||
inputbox.trigger("focusin");
|
inputbox.trigger("focusin");
|
||||||
});
|
});
|
||||||
|
|
|
@ -35,6 +35,8 @@ function handleUpload(id) {
|
||||||
u("span", indicator.nodes[0]).text(trim(file.name) + " (" + humanFileSize(file.size, false) + ")");
|
u("span", indicator.nodes[0]).text(trim(file.name) + " (" + humanFileSize(file.size, false) + ")");
|
||||||
indicator.attr("style", "display: block;");
|
indicator.attr("style", "display: block;");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
document.querySelector("#post-buttons" + id + " #wallAttachmentMenu").classList.add("hidden");
|
||||||
}
|
}
|
||||||
|
|
||||||
function initGraffiti(id) {
|
function initGraffiti(id) {
|
||||||
|
@ -108,7 +110,7 @@ function setupWallPostInputHandlers(id) {
|
||||||
var textArea = e.target;
|
var textArea = e.target;
|
||||||
textArea.style.height = "5px";
|
textArea.style.height = "5px";
|
||||||
var newHeight = textArea.scrollHeight;
|
var newHeight = textArea.scrollHeight;
|
||||||
textArea.style.height = newHeight + boost;
|
textArea.style.height = newHeight + boost + "px";
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// revert to original size if it is larger (possibly changed by user)
|
// revert to original size if it is larger (possibly changed by user)
|
||||||
|
|
|
@ -185,7 +185,7 @@ function repostPost(id, hash) {
|
||||||
|
|
||||||
function setClubAdminComment(clubId, adminId, hash) {
|
function setClubAdminComment(clubId, adminId, hash) {
|
||||||
MessageBox("Изменить комментарий к администратору", `
|
MessageBox("Изменить комментарий к администратору", `
|
||||||
<form action="/club${clubId}/setAdmin.jsp" method="post" id="uClubAdminCommentForm_${clubId}_${adminId}">
|
<form action="/club${clubId}/setAdmin" method="post" id="uClubAdminCommentForm_${clubId}_${adminId}">
|
||||||
<input type="hidden" name="user" value="${adminId}">
|
<input type="hidden" name="user" value="${adminId}">
|
||||||
<input type="hidden" name="hash" value="${hash}">
|
<input type="hidden" name="hash" value="${hash}">
|
||||||
<input type="hidden" name="removeComment" id="uClubAdminCommentRemoveCommentInput_${clubId}_${adminId}" value="0">
|
<input type="hidden" name="removeComment" id="uClubAdminCommentRemoveCommentInput_${clubId}_${adminId}" value="0">
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
window.addEventListener("scroll", function(e) {
|
window.addEventListener("scroll", function(e) {
|
||||||
if(document.body.scrollTop < 100) {
|
if(window.scrollY < 100) {
|
||||||
document.body.classList.toggle("scrolled", false);
|
document.body.classList.toggle("scrolled", false);
|
||||||
} else {
|
} else {
|
||||||
document.body.classList.toggle("scrolled", true);
|
document.body.classList.toggle("scrolled", true);
|
||||||
|
|
11
Web/static/js/timezone.js
Executable file
11
Web/static/js/timezone.js
Executable file
|
@ -0,0 +1,11 @@
|
||||||
|
// This file is included only when there is no info about timezone in users's chandler session
|
||||||
|
|
||||||
|
xhr = new XMLHttpRequest();
|
||||||
|
xhr.open("POST", "/iapi/timezone", true);
|
||||||
|
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
|
||||||
|
xhr.onload = (response) => {
|
||||||
|
if(JSON.parse(response.originalTarget.responseText).success == 1) {
|
||||||
|
window.location.reload();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
xhr.send('timezone=' + new Date().getTimezoneOffset());
|
|
@ -167,7 +167,8 @@ function ovk_proc_strtrim(string $string, int $length = 0): string
|
||||||
|
|
||||||
function ovk_strftime_safe(string $format, ?int $timestamp = NULL): string
|
function ovk_strftime_safe(string $format, ?int $timestamp = NULL): string
|
||||||
{
|
{
|
||||||
$str = strftime($format, $timestamp ?? time());
|
$sessionOffset = intval(Session::i()->get("_timezoneOffset"));
|
||||||
|
$str = strftime($format, $timestamp + ($sessionOffset * MINUTE) * -1 ?? time() + ($sessionOffset * MINUTE) * -1);
|
||||||
if(PHP_SHLIB_SUFFIX === "dll") {
|
if(PHP_SHLIB_SUFFIX === "dll") {
|
||||||
$enc = tr("__WinEncoding");
|
$enc = tr("__WinEncoding");
|
||||||
if($enc === "@__WinEncoding")
|
if($enc === "@__WinEncoding")
|
||||||
|
@ -230,7 +231,7 @@ return (function() {
|
||||||
if(is_dir($gitDir = OPENVK_ROOT . "/.git") && $showCommitHash)
|
if(is_dir($gitDir = OPENVK_ROOT . "/.git") && $showCommitHash)
|
||||||
$ver = trim(`git --git-dir="$gitDir" log --pretty="%h" -n1 HEAD` ?? "Unknown version") . "-nightly";
|
$ver = trim(`git --git-dir="$gitDir" log --pretty="%h" -n1 HEAD` ?? "Unknown version") . "-nightly";
|
||||||
else
|
else
|
||||||
$ver = "Build 15";
|
$ver = "Public Technical Preview 3";
|
||||||
|
|
||||||
// Unix time constants
|
// Unix time constants
|
||||||
define('MINUTE', 60);
|
define('MINUTE', 60);
|
||||||
|
|
|
@ -7,13 +7,14 @@
|
||||||
"james-heinrich/getid3": "^1.9@dev",
|
"james-heinrich/getid3": "^1.9@dev",
|
||||||
"rybakit/msgpack": "dev-master",
|
"rybakit/msgpack": "dev-master",
|
||||||
"wapmorgan/binary-stream": "dev-master",
|
"wapmorgan/binary-stream": "dev-master",
|
||||||
"netcarver/textile": "^3.7@dev",
|
|
||||||
"al/emoji-detector": "dev-master",
|
"al/emoji-detector": "dev-master",
|
||||||
"ezyang/htmlpurifier": "dev-master",
|
"ezyang/htmlpurifier": "dev-master",
|
||||||
"scssphp/scssphp": "dev-master",
|
"scssphp/scssphp": "dev-master",
|
||||||
"lfkeitel/phptotp": "dev-master",
|
"lfkeitel/phptotp": "dev-master",
|
||||||
"chillerlan/php-qrcode": "dev-main",
|
"chillerlan/php-qrcode": "dev-main",
|
||||||
"vearutop/php-obscene-censor-rus": "dev-master"
|
"vearutop/php-obscene-censor-rus": "dev-master",
|
||||||
|
"erusev/parsedown": "dev-master",
|
||||||
|
"bhaktaraz/php-rss-generator": "dev-master"
|
||||||
},
|
},
|
||||||
"minimum-stability": "dev"
|
"minimum-stability": "dev"
|
||||||
}
|
}
|
||||||
|
|
274
composer.lock
generated
274
composer.lock
generated
|
@ -4,7 +4,7 @@
|
||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "770bb7b5fdc8074bb03f5c2a762914fe",
|
"content-hash": "2c94032cae911ca438bbcfc46c346961",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "al/emoji-detector",
|
"name": "al/emoji-detector",
|
||||||
|
@ -52,18 +52,67 @@
|
||||||
},
|
},
|
||||||
"time": "2020-06-26T09:10:17+00:00"
|
"time": "2020-06-26T09:10:17+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "bhaktaraz/php-rss-generator",
|
||||||
|
"version": "dev-master",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/bhaktaraz/php-rss-generator.git",
|
||||||
|
"reference": "53cf11db18d87e65973e6df453fb8c1382e5a3bd"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/bhaktaraz/php-rss-generator/zipball/53cf11db18d87e65973e6df453fb8c1382e5a3bd",
|
||||||
|
"reference": "53cf11db18d87e65973e6df453fb8c1382e5a3bd",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": ">=5.3.0"
|
||||||
|
},
|
||||||
|
"default-branch": true,
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Bhaktaraz\\RSSGenerator\\": "Source/Bhaktaraz/RSSGenerator/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Bhaktaraz Bhatta",
|
||||||
|
"email": "bhattabhakta@gmail.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Simple RSS generator library for PHP 5.5 or later.",
|
||||||
|
"homepage": "https://github.com/bhaktaraz/php-rss-generator",
|
||||||
|
"keywords": [
|
||||||
|
"Facebook product feed generator",
|
||||||
|
"feed",
|
||||||
|
"generator",
|
||||||
|
"rss",
|
||||||
|
"writer"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/bhaktaraz/php-rss-generator/issues",
|
||||||
|
"source": "https://github.com/bhaktaraz/php-rss-generator/tree/master"
|
||||||
|
},
|
||||||
|
"time": "2021-03-15T10:59:47+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "chillerlan/php-qrcode",
|
"name": "chillerlan/php-qrcode",
|
||||||
"version": "dev-main",
|
"version": "dev-main",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/chillerlan/php-qrcode.git",
|
"url": "https://github.com/chillerlan/php-qrcode.git",
|
||||||
"reference": "0c1f322476a090b945108e6df960ee381a8c352e"
|
"reference": "06730361508c283a02bbf9cbc9e4b55e7b3bc88b"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/chillerlan/php-qrcode/zipball/0c1f322476a090b945108e6df960ee381a8c352e",
|
"url": "https://api.github.com/repos/chillerlan/php-qrcode/zipball/06730361508c283a02bbf9cbc9e4b55e7b3bc88b",
|
||||||
"reference": "0c1f322476a090b945108e6df960ee381a8c352e",
|
"reference": "06730361508c283a02bbf9cbc9e4b55e7b3bc88b",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
@ -138,7 +187,7 @@
|
||||||
"type": "ko_fi"
|
"type": "ko_fi"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2021-12-12T23:34:10+00:00"
|
"time": "2021-12-14T15:11:20+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "chillerlan/php-settings-container",
|
"name": "chillerlan/php-settings-container",
|
||||||
|
@ -203,26 +252,74 @@
|
||||||
],
|
],
|
||||||
"time": "2021-09-06T15:17:01+00:00"
|
"time": "2021-09-06T15:17:01+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "erusev/parsedown",
|
||||||
|
"version": "dev-master",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/erusev/parsedown.git",
|
||||||
|
"reference": "6598f3860c2698fe2f0f1bc98212fc01d0a1893c"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/erusev/parsedown/zipball/6598f3860c2698fe2f0f1bc98212fc01d0a1893c",
|
||||||
|
"reference": "6598f3860c2698fe2f0f1bc98212fc01d0a1893c",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"ext-mbstring": "*",
|
||||||
|
"php": ">=5.3.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"phpunit/phpunit": "^4.8.35"
|
||||||
|
},
|
||||||
|
"default-branch": true,
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"psr-0": {
|
||||||
|
"Parsedown": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Emanuil Rusev",
|
||||||
|
"email": "hello@erusev.com",
|
||||||
|
"homepage": "http://erusev.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Parser for Markdown.",
|
||||||
|
"homepage": "http://parsedown.org",
|
||||||
|
"keywords": [
|
||||||
|
"markdown",
|
||||||
|
"parser"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/erusev/parsedown/issues",
|
||||||
|
"source": "https://github.com/erusev/parsedown/tree/master"
|
||||||
|
},
|
||||||
|
"time": "2020-08-09T14:12:21+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "ezyang/htmlpurifier",
|
"name": "ezyang/htmlpurifier",
|
||||||
"version": "dev-master",
|
"version": "dev-master",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/ezyang/htmlpurifier.git",
|
"url": "https://github.com/ezyang/htmlpurifier.git",
|
||||||
"reference": "996eaf43310edf1d908bc0030a18b37b8cf6eefd"
|
"reference": "12ab42bd6e742c70c0a52f7b82477fcd44e64b75"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/ezyang/htmlpurifier/zipball/996eaf43310edf1d908bc0030a18b37b8cf6eefd",
|
"url": "https://api.github.com/repos/ezyang/htmlpurifier/zipball/12ab42bd6e742c70c0a52f7b82477fcd44e64b75",
|
||||||
"reference": "996eaf43310edf1d908bc0030a18b37b8cf6eefd",
|
"reference": "12ab42bd6e742c70c0a52f7b82477fcd44e64b75",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"php": ">=5.2"
|
"php": ">=5.2"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
|
||||||
"simpletest/simpletest": "dev-master#72de02a7b80c6bb8864ef9bf66d41d2f58f826bd"
|
|
||||||
},
|
|
||||||
"default-branch": true,
|
"default-branch": true,
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"autoload": {
|
"autoload": {
|
||||||
|
@ -254,9 +351,9 @@
|
||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/ezyang/htmlpurifier/issues",
|
"issues": "https://github.com/ezyang/htmlpurifier/issues",
|
||||||
"source": "https://github.com/ezyang/htmlpurifier/tree/master"
|
"source": "https://github.com/ezyang/htmlpurifier/tree/v4.14.0"
|
||||||
},
|
},
|
||||||
"time": "2021-09-07T18:16:55+00:00"
|
"time": "2021-12-25T01:21:49+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "guzzlehttp/guzzle",
|
"name": "guzzlehttp/guzzle",
|
||||||
|
@ -357,12 +454,12 @@
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/guzzle/promises.git",
|
"url": "https://github.com/guzzle/promises.git",
|
||||||
"reference": "136a635e2b4a49b9d79e9c8fee267ffb257fdba0"
|
"reference": "fe752aedc9fd8fcca3fe7ad05d419d32998a06da"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/guzzle/promises/zipball/136a635e2b4a49b9d79e9c8fee267ffb257fdba0",
|
"url": "https://api.github.com/repos/guzzle/promises/zipball/fe752aedc9fd8fcca3fe7ad05d419d32998a06da",
|
||||||
"reference": "136a635e2b4a49b9d79e9c8fee267ffb257fdba0",
|
"reference": "fe752aedc9fd8fcca3fe7ad05d419d32998a06da",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
@ -418,7 +515,7 @@
|
||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/guzzle/promises/issues",
|
"issues": "https://github.com/guzzle/promises/issues",
|
||||||
"source": "https://github.com/guzzle/promises/tree/1.5.0"
|
"source": "https://github.com/guzzle/promises/tree/1.5.1"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
|
@ -434,7 +531,7 @@
|
||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2021-10-07T13:05:22+00:00"
|
"time": "2021-10-22T20:56:57+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "guzzlehttp/psr7",
|
"name": "guzzlehttp/psr7",
|
||||||
|
@ -472,12 +569,12 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"psr-4": {
|
|
||||||
"GuzzleHttp\\Psr7\\": "src/"
|
|
||||||
},
|
|
||||||
"files": [
|
"files": [
|
||||||
"src/functions_include.php"
|
"src/functions_include.php"
|
||||||
]
|
],
|
||||||
|
"psr-4": {
|
||||||
|
"GuzzleHttp\\Psr7\\": "src/"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"notification-url": "https://packagist.org/downloads/",
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
"license": [
|
"license": [
|
||||||
|
@ -552,12 +649,12 @@
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/JamesHeinrich/getID3.git",
|
"url": "https://github.com/JamesHeinrich/getID3.git",
|
||||||
"reference": "a440175a329a83dbfad991e67b5e5f3a1ff51bd9"
|
"reference": "2279f7caca2d761dfc580dd02b401e7a1ff69dfe"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/JamesHeinrich/getID3/zipball/a440175a329a83dbfad991e67b5e5f3a1ff51bd9",
|
"url": "https://api.github.com/repos/JamesHeinrich/getID3/zipball/2279f7caca2d761dfc580dd02b401e7a1ff69dfe",
|
||||||
"reference": "a440175a329a83dbfad991e67b5e5f3a1ff51bd9",
|
"reference": "2279f7caca2d761dfc580dd02b401e7a1ff69dfe",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
@ -612,7 +709,7 @@
|
||||||
"issues": "https://github.com/JamesHeinrich/getID3/issues",
|
"issues": "https://github.com/JamesHeinrich/getID3/issues",
|
||||||
"source": "https://github.com/JamesHeinrich/getID3/tree/master"
|
"source": "https://github.com/JamesHeinrich/getID3/tree/master"
|
||||||
},
|
},
|
||||||
"time": "2021-10-07T12:08:13+00:00"
|
"time": "2022-02-03T17:07:51+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "komeiji-satori/curl",
|
"name": "komeiji-satori/curl",
|
||||||
|
@ -706,66 +803,6 @@
|
||||||
},
|
},
|
||||||
"time": "2017-02-06T17:46:14+00:00"
|
"time": "2017-02-06T17:46:14+00:00"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "netcarver/textile",
|
|
||||||
"version": "dev-master",
|
|
||||||
"source": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://github.com/textile/php-textile.git",
|
|
||||||
"reference": "d64e1f8424afd600cc2732f4f99f262aef55fca2"
|
|
||||||
},
|
|
||||||
"dist": {
|
|
||||||
"type": "zip",
|
|
||||||
"url": "https://api.github.com/repos/textile/php-textile/zipball/d64e1f8424afd600cc2732f4f99f262aef55fca2",
|
|
||||||
"reference": "d64e1f8424afd600cc2732f4f99f262aef55fca2",
|
|
||||||
"shasum": ""
|
|
||||||
},
|
|
||||||
"require": {
|
|
||||||
"php": ">=5.3.0"
|
|
||||||
},
|
|
||||||
"require-dev": {
|
|
||||||
"php-coveralls/php-coveralls": "2.1.*",
|
|
||||||
"phpunit/phpunit": "5.7.*",
|
|
||||||
"squizlabs/php_codesniffer": "3.*",
|
|
||||||
"symfony/yaml": "2.4.*"
|
|
||||||
},
|
|
||||||
"default-branch": true,
|
|
||||||
"type": "library",
|
|
||||||
"extra": {
|
|
||||||
"branch-alias": {
|
|
||||||
"dev-master": "3.7-dev"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"autoload": {
|
|
||||||
"psr-4": {
|
|
||||||
"Netcarver\\Textile\\": "src/Netcarver/Textile/"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"notification-url": "https://packagist.org/downloads/",
|
|
||||||
"license": [
|
|
||||||
"BSD-3-Clause"
|
|
||||||
],
|
|
||||||
"description": "Textile markup language parser",
|
|
||||||
"homepage": "https://github.com/textile/php-textile",
|
|
||||||
"keywords": [
|
|
||||||
"document",
|
|
||||||
"format",
|
|
||||||
"html",
|
|
||||||
"language",
|
|
||||||
"markup",
|
|
||||||
"parser",
|
|
||||||
"php-textile",
|
|
||||||
"plaintext",
|
|
||||||
"textile"
|
|
||||||
],
|
|
||||||
"support": {
|
|
||||||
"irc": "irc://irc.freenode.net/textile",
|
|
||||||
"issues": "https://github.com/textile/php-textile/issues",
|
|
||||||
"source": "https://github.com/textile/php-textile",
|
|
||||||
"wiki": "https://github.com/textile/php-textile/wiki"
|
|
||||||
},
|
|
||||||
"time": "2020-10-01T18:21:03+00:00"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "psr/cache",
|
"name": "psr/cache",
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
|
@ -919,12 +956,12 @@
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/rybakit/msgpack.php.git",
|
"url": "https://github.com/rybakit/msgpack.php.git",
|
||||||
"reference": "66ca2c3948d72068ca0c8b9a4f599f822a7fe2c3"
|
"reference": "1e9eda511520e7494c241622671816a83a76e149"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/rybakit/msgpack.php/zipball/66ca2c3948d72068ca0c8b9a4f599f822a7fe2c3",
|
"url": "https://api.github.com/repos/rybakit/msgpack.php/zipball/1e9eda511520e7494c241622671816a83a76e149",
|
||||||
"reference": "66ca2c3948d72068ca0c8b9a4f599f822a7fe2c3",
|
"reference": "1e9eda511520e7494c241622671816a83a76e149",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
@ -933,7 +970,8 @@
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"ext-gmp": "*",
|
"ext-gmp": "*",
|
||||||
"friendsofphp/php-cs-fixer": "^2.14",
|
"friendsofphp/php-cs-fixer": "^2.14",
|
||||||
"phpunit/phpunit": "^7.1|^8|^9"
|
"phpunit/phpunit": "^7.1|^8|^9",
|
||||||
|
"vimeo/psalm": "^3.9|^4"
|
||||||
},
|
},
|
||||||
"suggest": {
|
"suggest": {
|
||||||
"ext-decimal": "For converting overflowed integers to Decimal objects",
|
"ext-decimal": "For converting overflowed integers to Decimal objects",
|
||||||
|
@ -973,7 +1011,7 @@
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2021-07-08T19:01:22+00:00"
|
"time": "2021-12-17T22:02:51+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "scssphp/scssphp",
|
"name": "scssphp/scssphp",
|
||||||
|
@ -981,12 +1019,12 @@
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/scssphp/scssphp.git",
|
"url": "https://github.com/scssphp/scssphp.git",
|
||||||
"reference": "fd4fc9edc49f5a4465e11e03b7d6198404adbc22"
|
"reference": "c800975c7408e923309fbb51346b84e83dd05700"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/scssphp/scssphp/zipball/fd4fc9edc49f5a4465e11e03b7d6198404adbc22",
|
"url": "https://api.github.com/repos/scssphp/scssphp/zipball/c800975c7408e923309fbb51346b84e83dd05700",
|
||||||
"reference": "fd4fc9edc49f5a4465e11e03b7d6198404adbc22",
|
"reference": "c800975c7408e923309fbb51346b84e83dd05700",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
@ -1002,7 +1040,7 @@
|
||||||
"symfony/phpunit-bridge": "^5.1",
|
"symfony/phpunit-bridge": "^5.1",
|
||||||
"thoughtbot/bourbon": "^7.0",
|
"thoughtbot/bourbon": "^7.0",
|
||||||
"twbs/bootstrap": "~5.0",
|
"twbs/bootstrap": "~5.0",
|
||||||
"twbs/bootstrap4": "4.6.0",
|
"twbs/bootstrap4": "4.6.1",
|
||||||
"zurb/foundation": "~6.5"
|
"zurb/foundation": "~6.5"
|
||||||
},
|
},
|
||||||
"suggest": {
|
"suggest": {
|
||||||
|
@ -1045,11 +1083,11 @@
|
||||||
"issues": "https://github.com/scssphp/scssphp/issues",
|
"issues": "https://github.com/scssphp/scssphp/issues",
|
||||||
"source": "https://github.com/scssphp/scssphp/tree/master"
|
"source": "https://github.com/scssphp/scssphp/tree/master"
|
||||||
},
|
},
|
||||||
"time": "2021-10-02T12:51:54+00:00"
|
"time": "2022-01-06T19:41:32+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/polyfill-intl-idn",
|
"name": "symfony/polyfill-intl-idn",
|
||||||
"version": "dev-main",
|
"version": "v1.24.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/polyfill-intl-idn.git",
|
"url": "https://github.com/symfony/polyfill-intl-idn.git",
|
||||||
|
@ -1069,7 +1107,6 @@
|
||||||
"suggest": {
|
"suggest": {
|
||||||
"ext-intl": "For best performance"
|
"ext-intl": "For best performance"
|
||||||
},
|
},
|
||||||
"default-branch": true,
|
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"extra": {
|
"extra": {
|
||||||
"branch-alias": {
|
"branch-alias": {
|
||||||
|
@ -1081,12 +1118,12 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"psr-4": {
|
|
||||||
"Symfony\\Polyfill\\Intl\\Idn\\": ""
|
|
||||||
},
|
|
||||||
"files": [
|
"files": [
|
||||||
"bootstrap.php"
|
"bootstrap.php"
|
||||||
]
|
],
|
||||||
|
"psr-4": {
|
||||||
|
"Symfony\\Polyfill\\Intl\\Idn\\": ""
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"notification-url": "https://packagist.org/downloads/",
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
"license": [
|
"license": [
|
||||||
|
@ -1117,7 +1154,7 @@
|
||||||
"shim"
|
"shim"
|
||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"source": "https://github.com/symfony/polyfill-intl-idn/tree/main"
|
"source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.24.0"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
|
@ -1137,7 +1174,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/polyfill-intl-normalizer",
|
"name": "symfony/polyfill-intl-normalizer",
|
||||||
"version": "dev-main",
|
"version": "v1.24.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/polyfill-intl-normalizer.git",
|
"url": "https://github.com/symfony/polyfill-intl-normalizer.git",
|
||||||
|
@ -1155,7 +1192,6 @@
|
||||||
"suggest": {
|
"suggest": {
|
||||||
"ext-intl": "For best performance"
|
"ext-intl": "For best performance"
|
||||||
},
|
},
|
||||||
"default-branch": true,
|
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"extra": {
|
"extra": {
|
||||||
"branch-alias": {
|
"branch-alias": {
|
||||||
|
@ -1167,12 +1203,12 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"psr-4": {
|
|
||||||
"Symfony\\Polyfill\\Intl\\Normalizer\\": ""
|
|
||||||
},
|
|
||||||
"files": [
|
"files": [
|
||||||
"bootstrap.php"
|
"bootstrap.php"
|
||||||
],
|
],
|
||||||
|
"psr-4": {
|
||||||
|
"Symfony\\Polyfill\\Intl\\Normalizer\\": ""
|
||||||
|
},
|
||||||
"classmap": [
|
"classmap": [
|
||||||
"Resources/stubs"
|
"Resources/stubs"
|
||||||
]
|
]
|
||||||
|
@ -1202,7 +1238,7 @@
|
||||||
"shim"
|
"shim"
|
||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.23.0"
|
"source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.24.0"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
|
@ -1222,7 +1258,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/polyfill-php72",
|
"name": "symfony/polyfill-php72",
|
||||||
"version": "dev-main",
|
"version": "v1.24.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/polyfill-php72.git",
|
"url": "https://github.com/symfony/polyfill-php72.git",
|
||||||
|
@ -1237,7 +1273,6 @@
|
||||||
"require": {
|
"require": {
|
||||||
"php": ">=7.1"
|
"php": ">=7.1"
|
||||||
},
|
},
|
||||||
"default-branch": true,
|
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"extra": {
|
"extra": {
|
||||||
"branch-alias": {
|
"branch-alias": {
|
||||||
|
@ -1249,12 +1284,12 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"psr-4": {
|
|
||||||
"Symfony\\Polyfill\\Php72\\": ""
|
|
||||||
},
|
|
||||||
"files": [
|
"files": [
|
||||||
"bootstrap.php"
|
"bootstrap.php"
|
||||||
]
|
],
|
||||||
|
"psr-4": {
|
||||||
|
"Symfony\\Polyfill\\Php72\\": ""
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"notification-url": "https://packagist.org/downloads/",
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
"license": [
|
"license": [
|
||||||
|
@ -1279,7 +1314,7 @@
|
||||||
"shim"
|
"shim"
|
||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"source": "https://github.com/symfony/polyfill-php72/tree/v1.23.0"
|
"source": "https://github.com/symfony/polyfill-php72/tree/v1.24.0"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
|
@ -1520,17 +1555,18 @@
|
||||||
"james-heinrich/getid3": 20,
|
"james-heinrich/getid3": 20,
|
||||||
"rybakit/msgpack": 20,
|
"rybakit/msgpack": 20,
|
||||||
"wapmorgan/binary-stream": 20,
|
"wapmorgan/binary-stream": 20,
|
||||||
"netcarver/textile": 20,
|
|
||||||
"al/emoji-detector": 20,
|
"al/emoji-detector": 20,
|
||||||
"ezyang/htmlpurifier": 20,
|
"ezyang/htmlpurifier": 20,
|
||||||
"scssphp/scssphp": 20,
|
"scssphp/scssphp": 20,
|
||||||
"lfkeitel/phptotp": 20,
|
"lfkeitel/phptotp": 20,
|
||||||
"chillerlan/php-qrcode": 20,
|
"chillerlan/php-qrcode": 20,
|
||||||
"vearutop/php-obscene-censor-rus": 20
|
"vearutop/php-obscene-censor-rus": 20,
|
||||||
|
"erusev/parsedown": 20,
|
||||||
|
"bhaktaraz/php-rss-generator": 20
|
||||||
},
|
},
|
||||||
"prefer-stable": false,
|
"prefer-stable": false,
|
||||||
"prefer-lowest": false,
|
"prefer-lowest": false,
|
||||||
"platform": [],
|
"platform": [],
|
||||||
"platform-dev": [],
|
"platform-dev": [],
|
||||||
"plugin-api-version": "2.1.0"
|
"plugin-api-version": "2.0.0"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
*OpenVK is a universal colleague search tool based on the VKontakte structure.*
|
**OpenVK is a universal colleague search tool based on the VKontakte structure.**
|
||||||
|
|
||||||
We want friends, classmates, classmates, neighbors and colleagues to always be in touch.
|
We want friends, classmates, classmates, neighbors and colleagues to always be in touch.
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
OpenVK-KB-Heading: Добро пожаловать
|
OpenVK-KB-Heading: Добро пожаловать
|
||||||
|
|
||||||
*OpenVK - универсальное средство поиска коллег основанное на структуре ВКонтакте.*
|
**OpenVK - универсальное средство поиска коллег основанное на структуре ВКонтакте.**
|
||||||
|
|
||||||
Мы хотим, чтобы друзья, однокурсники, одноклассники, соседи и коллеги всегда могли быть в контакте.
|
Мы хотим, чтобы друзья, однокурсники, одноклассники, соседи и коллеги всегда могли быть в контакте.
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
OpenVK-KB-Heading: Editing notes
|
OpenVK-KB-Heading: Editing notes
|
||||||
|
|
||||||
OpenVK wiki-markup is basically XHTML1.0 Transitional. The only difference is that we removed tags that are not needed or may harm OpenVK and it's users.
|
OpenVK wiki-markup is basically XHTML1.0 Transitional. The only difference is that we removed tags that are not needed or may harm OpenVK and it's users.
|
||||||
|
|
||||||
Allowed tags:
|
Allowed tags:
|
||||||
* All headers from level 3 to 6 (h3-h6)
|
* All headers from level 3 to 6 (h3-h6)
|
||||||
* Paragraphs (<p>)
|
* Paragraphs (<p>)
|
||||||
|
@ -8,12 +9,13 @@ Allowed tags:
|
||||||
* <sup>, <sub>, <ins>
|
* <sup>, <sub>, <ins>
|
||||||
* Everything related to tables
|
* Everything related to tables
|
||||||
* Links and images (<a>, <img>)
|
* Links and images (<a>, <img>)
|
||||||
* Lists (и <ol> и <ul>)
|
* Lists (and <ol> and <ul>)
|
||||||
* Line feed and horizontal rule (hr)
|
* Line feed and horizontal rule (hr)
|
||||||
* Blockquotes (<blockquote> и <cite>)
|
* Blockquotes (<blockquote> and <cite>)
|
||||||
* <acronym>
|
* <acronym>
|
||||||
|
|
||||||
*Please note*: images can't have sourcemap and their source must be a file that is hosted on this OpenVK instance. This restrictions does not apply to links. Links can link to everything (except for data: and javascript: pseudoprotocols). They will be derefered though.
|
**Please note**: images can't have sourcemap and their source must be a file that is hosted on this OpenVK instance. This restrictions does not apply to links. Links can link to everything (except for data: and javascript: pseudoprotocols). They will be derefered though.
|
||||||
|
|
||||||
You may also have noticed, that <style> is note in the allowlist, however, we do support styling <div> and <img> tags using style attribute. This CSS properties are allowed:
|
You may also have noticed, that <style> is note in the allowlist, however, we do support styling <div> and <img> tags using style attribute. This CSS properties are allowed:
|
||||||
* float
|
* float
|
||||||
* height
|
* height
|
||||||
|
@ -21,4 +23,5 @@ You may also have noticed, that <style> is note in the allowlist, however,
|
||||||
* max-height
|
* max-height
|
||||||
* max-width
|
* max-width
|
||||||
* font-weight
|
* font-weight
|
||||||
|
|
||||||
If property is a size property it can only accept pixels as value (no %, pt, pc, em, rem, vw or vh).
|
If property is a size property it can only accept pixels as value (no %, pt, pc, em, rem, vw or vh).
|
|
@ -1,6 +1,7 @@
|
||||||
OpenVK-KB-Heading: Справка по редактированию заметок
|
OpenVK-KB-Heading: Справка по редактированию заметок
|
||||||
|
|
||||||
Вики-разметка OpenVK это тоже самое, что и XHTML1.0 Transitional. Единственное изменение заключается в том, что мы убрали некоторые теги, которые могут принести вред OpenVK или не нужны.
|
Вики-разметка OpenVK это тоже самое, что и XHTML1.0 Transitional. Единственное изменение заключается в том, что мы убрали некоторые теги, которые могут принести вред OpenVK или не нужны.
|
||||||
|
|
||||||
Список разрешённых тегов:
|
Список разрешённых тегов:
|
||||||
* Все заголовки 3-6 уровней (h3-h6)
|
* Все заголовки 3-6 уровней (h3-h6)
|
||||||
* Параграфы (<p>)
|
* Параграфы (<p>)
|
||||||
|
@ -12,7 +13,9 @@ OpenVK-KB-Heading: Справка по редактированию замето
|
||||||
* Перевод строки и горизонтальная линия (hr)
|
* Перевод строки и горизонтальная линия (hr)
|
||||||
* Цитаты (<blockquote> и <cite>)
|
* Цитаты (<blockquote> и <cite>)
|
||||||
* <acronym>
|
* <acronym>
|
||||||
|
|
||||||
Обратите внимание, источником изображения могут быть только файлы из OpenVK. Это ограничение не распространяется на ссылки, где href может быть любой (в целях безопасности наших пользователей, ссылка будет автоматически заменена на редирект через away.php)
|
Обратите внимание, источником изображения могут быть только файлы из OpenVK. Это ограничение не распространяется на ссылки, где href может быть любой (в целях безопасности наших пользователей, ссылка будет автоматически заменена на редирект через away.php)
|
||||||
|
|
||||||
Вы могли заметить, что в списке разрешённых тегов нету <style>, но ничего страшного, вы можете применять аттрибут style к тегам <div> и <img>. В перечень поддерживаемых свойств CSS входят:
|
Вы могли заметить, что в списке разрешённых тегов нету <style>, но ничего страшного, вы можете применять аттрибут style к тегам <div> и <img>. В перечень поддерживаемых свойств CSS входят:
|
||||||
* float
|
* float
|
||||||
* height
|
* height
|
||||||
|
@ -20,4 +23,5 @@ OpenVK-KB-Heading: Справка по редактированию замето
|
||||||
* max-height
|
* max-height
|
||||||
* max-width
|
* max-width
|
||||||
* font-weight
|
* font-weight
|
||||||
|
|
||||||
Обратите внимание на то, что поддерживаются только значения в пикселях.
|
Обратите внимание на то, что поддерживаются только значения в пикселях.
|
|
@ -1,7 +1,7 @@
|
||||||
OpenVK-KB-Heading: About points
|
OpenVK-KB-Heading: About points
|
||||||
|
|
||||||
h4. What are points?
|
#### What are points?
|
||||||
Points are OpenVK internal currency. You can use it to buy stickers and gifts.
|
Points are OpenVK internal currency. You can use it to buy stickers and gifts.
|
||||||
|
|
||||||
h4. How can I buy points?
|
#### How can I buy points?
|
||||||
This is example knowledgebase article and it does not have the details about this topic. If you are administrator of this social network, please change this article to fit your needs. If you are a user you can ask your admin directly about this.
|
This is example knowledgebase article and it does not have the details about this topic. If you are administrator of this social network, please change this article to fit your needs. If you are a user you can ask your admin directly about this.
|
|
@ -1,7 +1,7 @@
|
||||||
OpenVK-KB-Heading: Про голоса
|
OpenVK-KB-Heading: Про голоса
|
||||||
|
|
||||||
h4. Что такое голоса?
|
#### Что такое голоса?
|
||||||
Голоса это внутреняя валюта OpenVK. За неё можно купить стикеры или подарки другим пользователям.
|
Голоса это внутреняя валюта OpenVK. За неё можно купить стикеры или подарки другим пользователям.
|
||||||
|
|
||||||
h4. Как купить голоса?
|
#### Как купить голоса?
|
||||||
Это пример статьи о голосах и из-за этого в ней нет таких деталей. Если вы администратор этой социальной сети, отредактируйте файл data/knowledgebase/points.ru.textile, чтобы он соответствовал вашим нуждам. Если вы простой пользователь, уведомите администратора о том, что он забыл отредактировать файлы и спросите у него, как же вам купить голоса.
|
Это пример статьи о голосах и из-за этого в ней нет таких деталей. Если вы администратор этой социальной сети, отредактируйте файл data/knowledgebase/points.ru.md, чтобы он соответствовал вашим нуждам. Если вы простой пользователь, уведомите администратора о том, что он забыл отредактировать файлы и спросите у него, как же вам купить голоса.
|
|
@ -1,31 +1,31 @@
|
||||||
OpenVK-KB-Heading: Privacy Policy
|
OpenVK-KB-Heading: Privacy Policy
|
||||||
|
|
||||||
h2. What information do we collect?
|
## What information do we collect?
|
||||||
* _Basic account information_: If you register on this server, you may be asked to enter your real name, last name, an email address, and a password. You may also enter additional profile information such as a nickname, status, biography, interests, etc. Your first name, last name, a nickname, a status, and a profile picture are always listed publicly.
|
* _Basic account information_: If you register on this server, you may be asked to enter your real name, last name, an email address, and a password. You may also enter additional profile information such as a nickname, status, biography, interests, etc. Your first name, last name, a nickname, a status, and a profile picture are always listed publicly.
|
||||||
* _Posts, private messages and other information_: All information is processed and stored on the server. When you submit any content, the date and time are stored with the post, including attachments. Messages may contain media attachments, such as pictures and videos. Posts are available publicly. Personal messages are only delivered to users to whom you have personally sent messages. _Please do not share any dangerous information over OpenVK._
|
* _Posts, private messages and other information_: All information is processed and stored on the server. When you submit any content, the date and time are stored with the post, including attachments. Messages may contain media attachments, such as pictures and videos. Posts are available publicly. Personal messages are only delivered to users to whom you have personally sent messages. _Please do not share any dangerous information over OpenVK._
|
||||||
* _IPs and other metadata_: When you log in, we may record the IP address you log in from, as well as the name of your browser application. We also may retain server logs which include the IP address of every request to our server.
|
* _IPs and other metadata_: When you log in, we may record the IP address you log in from, as well as the name of your browser application. We also may retain server logs which include the IP address of every request to our server.
|
||||||
|
|
||||||
h2. What do we use your information for?
|
## What do we use your information for?
|
||||||
Any of the information we collect from you may be used in the following ways:
|
Any of the information we collect from you may be used in the following ways:
|
||||||
* To provide the core functionality of OpenVK. You can only interact with other people's content and post your own content when you are logged in.
|
* To provide the core functionality of OpenVK. You can only interact with other people's content and post your own content when you are logged in.
|
||||||
* To aid moderation of the community, for example comparing your IP address with other known ones to determine ban evasion or other violations.
|
* To aid moderation of the community, for example comparing your IP address with other known ones to determine ban evasion or other violations.
|
||||||
* The email address you provide may be used to regain access to your account by changing your password.
|
* The email address you provide may be used to regain access to your account by changing your password.
|
||||||
|
|
||||||
h2. How do we protect your information?
|
## How do we protect your information?
|
||||||
We implement a variety of security measures to maintain the safety of your personal information when you enter, submit, or access your personal information. Among other things, your browser session, as well as the traffic between your applications and the API, are secured with SSL, and your password is hashed using a strong one-way algorithm.
|
We implement a variety of security measures to maintain the safety of your personal information when you enter, submit, or access your personal information. Among other things, your browser session, as well as the traffic between your applications and the API, are secured with SSL, and your password is hashed using a strong one-way algorithm.
|
||||||
|
|
||||||
h2. Do we use cookies?
|
## Do we use cookies?
|
||||||
Yes. Cookies are small files that a site or its service provider transfers to your computer's hard drive through your Web browser (if you allow). These cookies enable the site to recognize your browser and, if you have a registered account, associate it with your registered account.
|
Yes. Cookies are small files that a site or its service provider transfers to your computer's hard drive through your Web browser (if you allow). These cookies enable the site to recognize your browser and, if you have a registered account, associate it with your registered account.
|
||||||
|
|
||||||
We use cookies to understand and save your preferences for future visits.
|
We use cookies to understand and save your preferences for future visits.
|
||||||
|
|
||||||
h2. Do we disclose any information to outside parties?
|
## Do we disclose any information to outside parties?
|
||||||
We do not sell, trade, or otherwise transfer to outside parties your personally identifiable information. This does not include trusted third parties who assist us in operating our site, or servicing you, so long as those parties agree to keep this information confidential. We may also release your information when we believe release is appropriate to comply with the law, enforce our site policies, or protect ours or others rights, property, or safety.
|
We do not sell, trade, or otherwise transfer to outside parties your personally identifiable information. This does not include trusted third parties who assist us in operating our site, or servicing you, so long as those parties agree to keep this information confidential. We may also release your information when we believe release is appropriate to comply with the law, enforce our site policies, or protect ours or others rights, property, or safety.
|
||||||
|
|
||||||
h2. Changes to our Privacy Policy
|
## Changes to our Privacy Policy
|
||||||
|
|
||||||
If we decide to change our privacy policy, we will post those changes on this page.
|
If we decide to change our privacy policy, we will post those changes on this page.
|
||||||
|
|
||||||
This document is CC-BY-SA. It was last updated October 8, 2021.
|
This document is CC-BY-SA. It was last updated October 8, 2021.
|
||||||
|
|
||||||
Originally adapted from the "Mastodon privacy policy":https://mastodon.social/terms.
|
Originally adapted from the [Mastodon privacy policy](https://mastodon.social/terms).
|
|
@ -1,31 +1,31 @@
|
||||||
OpenVK-KB-Heading: Политика Конфиденциальности
|
OpenVK-KB-Heading: Политика Конфиденциальности
|
||||||
|
|
||||||
h2. Какую информацию мы собираем?
|
## Какую информацию мы собираем?
|
||||||
* _Основная информация_: Если у вас есть желание зарегистрироваться на данном сайте, вас могут попросить ввести реальное имя, фамилию, адрес электронной почты и пароль. Также вы можете ввести дополнительную информацию профиля, например, псевдоним, статус, биографию, интересы, и т.д. Имя, фамилия, псевдоним, статус и фото профиля будут общедоступными.
|
* _Основная информация_: Если у вас есть желание зарегистрироваться на данном сайте, вас могут попросить ввести реальное имя, фамилию, адрес электронной почты и пароль. Также вы можете ввести дополнительную информацию профиля, например, псевдоним, статус, биографию, интересы, и т.д. Имя, фамилия, псевдоним, статус и фото профиля будут общедоступными.
|
||||||
* _Записи, личные сообщения и другая информация_: Вся информация обрабатывается и хранится на сервере. Когда вы отправляете любой контент, дата и время сохраняются с записью, включая вложения. Сообщения могут включать медиа вложения, к примеру изображения и видео. Записи являются общедоступной информацией. Личные сообщения доставляются только тем пользователями, которым Вы лично отправили сообщения. _Пожалуйста, не делитесь любой вредоносной информации через OpenVK._
|
* _Записи, личные сообщения и другая информация_: Вся информация обрабатывается и хранится на сервере. Когда вы отправляете любой контент, дата и время сохраняются с записью, включая вложения. Сообщения могут включать медиа вложения, к примеру изображения и видео. Записи являются общедоступной информацией. Личные сообщения доставляются только тем пользователями, которым Вы лично отправили сообщения. _Пожалуйста, не делитесь любой вредоносной информации через OpenVK._
|
||||||
* _IP-адреса и другие метаданные_: Когда Вы выполняете вход в свой аккаунт, мы можем записывать IP-адрес, с которого был произведён вход, и название вашего веб-браузера. Мы также можем сохранять журналы сервера, которые включают IP-адрес каждого запроса к серверу.
|
* _IP-адреса и другие метаданные_: Когда Вы выполняете вход в свой аккаунт, мы можем записывать IP-адрес, с которого был произведён вход, и название вашего веб-браузера. Мы также можем сохранять журналы сервера, которые включают IP-адрес каждого запроса к серверу.
|
||||||
|
|
||||||
h2. Для чего мы используем вашу информацию?
|
## Для чего мы используем вашу информацию?
|
||||||
Любую собранную нами информацию мы используем для следующих целей:
|
Любую собранную нами информацию мы используем для следующих целей:
|
||||||
* Для предоставления базового функционала OpenVK. Вы можете взаимодействовать с чужим контентом и размещать собственный контент только тогда, когда Вы вошли в систему.
|
* Для предоставления базового функционала OpenVK. Вы можете взаимодействовать с чужим контентом и размещать собственный контент только тогда, когда Вы вошли в систему.
|
||||||
* Чтобы помочь модерации сообщества, например, сравнить ваш IP-адрес с другими известными адресами, чтобы определить уклонения от блокировки или других нарушений.
|
* Чтобы помочь модерации сообщества, например, сравнить ваш IP-адрес с другими известными адресами, чтобы определить уклонения от блокировки или других нарушений.
|
||||||
* Предоставленный вами адрес электронной почты может быть использован для восстановления доступа к вашему аккаунту при помощи смены пароля.
|
* Предоставленный вами адрес электронной почты может быть использован для восстановления доступа к вашему аккаунту при помощи смены пароля.
|
||||||
|
|
||||||
h2. Как мы защищаем вашу информацию?
|
## Как мы защищаем вашу информацию?
|
||||||
Мы применяем различные меры безопасности для обеспечения сохранности вашей личной информации, когда вы вводите, отправляете или получаете доступ к своей личной информации. Среди прочего, сессия вашего браузера, а также трафик между вашими приложениями и API защищены протоколом SSL, а ваш пароль хэшируется с помощью надежного одностороннего алгоритма.
|
Мы применяем различные меры безопасности для обеспечения сохранности вашей личной информации, когда вы вводите, отправляете или получаете доступ к своей личной информации. Среди прочего, сессия вашего браузера, а также трафик между вашими приложениями и API защищены протоколом SSL, а ваш пароль хэшируется с помощью надежного одностороннего алгоритма.
|
||||||
|
|
||||||
h2. Используем ли мы файлы cookies?
|
## Используем ли мы файлы cookies?
|
||||||
Да. Cookies - это небольшие файлы, которые сайт или его поставщик услуг передает на жесткий диск вашего компьютера через ваш веб-браузер (если вы разрешаете). Эти файлы cookie позволяют сайту распознать ваш браузер и, если у вас есть зарегистрированная учетная запись, связать ее с вашей зарегистрированной учетной записью.
|
Да. Cookies - это небольшие файлы, которые сайт или его поставщик услуг передает на жесткий диск вашего компьютера через ваш веб-браузер (если вы разрешаете). Эти файлы cookie позволяют сайту распознать ваш браузер и, если у вас есть зарегистрированная учетная запись, связать ее с вашей зарегистрированной учетной записью.
|
||||||
|
|
||||||
Мы используем файлы cookies, чтобы понять и сохранить ваши настройки для будущих посещений.
|
Мы используем файлы cookies, чтобы понять и сохранить ваши настройки для будущих посещений.
|
||||||
|
|
||||||
h2. Раскрываем ли мы какую-либо информацию сторонним лицам?
|
## Раскрываем ли мы какую-либо информацию сторонним лицам?
|
||||||
Мы не продаем, не обмениваем и не передаем посторонним лицам вашу личную информацию. Это не относится к доверенным третьим лицам, которые помогают нам управлять нашим сайтом или обслуживать вас, если эти лица согласны сохранять конфиденциальность этой информации. Мы также можем раскрыть вашу информацию, если считаем, что это необходимо для соблюдения закона, исполнения правил нашего сайта или защиты наших или чужих прав, собственности или безопасности.
|
Мы не продаем, не обмениваем и не передаем посторонним лицам вашу личную информацию. Это не относится к доверенным третьим лицам, которые помогают нам управлять нашим сайтом или обслуживать вас, если эти лица согласны сохранять конфиденциальность этой информации. Мы также можем раскрыть вашу информацию, если считаем, что это необходимо для соблюдения закона, исполнения правил нашего сайта или защиты наших или чужих прав, собственности или безопасности.
|
||||||
|
|
||||||
h2. Изменения в нашей Политике конфиденциальности
|
## Изменения в нашей Политике конфиденциальности
|
||||||
|
|
||||||
Если мы решим изменить нашу политику конфиденциальности, мы опубликуем эти изменения на данной странице.
|
Если мы решим изменить нашу политику конфиденциальности, мы опубликуем эти изменения на данной странице.
|
||||||
|
|
||||||
Данный документ лицензирован по CC-BY-SA. В последний раз обновлялся 8 октября 2021.
|
Данный документ лицензирован по CC-BY-SA. В последний раз обновлялся 8 октября 2021.
|
||||||
|
|
||||||
Первоначально адаптировано из "Политики конфиденциальности Mastodon":https://mastodon.social/terms.
|
Первоначально адаптировано из [Политики конфиденциальности Mastodon](https://mastodon.social/terms).
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue