Merge branch 'master' into master
3
.gitmodules
vendored
|
@ -1,3 +0,0 @@
|
||||||
[submodule "Web/static/img/oxygen-icons"]
|
|
||||||
path = Web/static/img/oxygen-icons
|
|
||||||
url = https://github.com/KDE/oxygen-icons5.git
|
|
|
@ -130,6 +130,11 @@ class Club extends RowModel
|
||||||
return $this->getRecord()->administrators_list_display;
|
return $this->getRecord()->administrators_list_display;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isEveryoneCanCreateTopics(): bool
|
||||||
|
{
|
||||||
|
return (bool) $this->getRecord()->everyone_can_create_topics;
|
||||||
|
}
|
||||||
|
|
||||||
function getType(): int
|
function getType(): int
|
||||||
{
|
{
|
||||||
return $this->getRecord()->type;
|
return $this->getRecord()->type;
|
||||||
|
|
|
@ -37,8 +37,19 @@ class Comment extends Post
|
||||||
if($honourFlags && $this->isPostedOnBehalfOfGroup()) {
|
if($honourFlags && $this->isPostedOnBehalfOfGroup()) {
|
||||||
if($this->getTarget() instanceof Post)
|
if($this->getTarget() instanceof Post)
|
||||||
return (new Clubs)->get(abs($this->getTarget()->getTargetWall()));
|
return (new Clubs)->get(abs($this->getTarget()->getTargetWall()));
|
||||||
|
|
||||||
|
if($this->getTarget() instanceof Topic)
|
||||||
|
return $this->getTarget()->getClub();
|
||||||
}
|
}
|
||||||
|
|
||||||
return parent::getOwner($honourFlags, $real);
|
return parent::getOwner($honourFlags, $real);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function canBeDeletedBy(User $user): bool
|
||||||
|
{
|
||||||
|
return $this->getOwner()->getId() == $user->getId() ||
|
||||||
|
$this->getTarget()->getOwner()->getId() == $user->getId() ||
|
||||||
|
$this->getTarget() instanceof Post && $this->getTarget()->getTargetWall() < 0 && (new Clubs)->get(abs($this->getTarget()->getTargetWall()))->canBeModifiedBy($user) ||
|
||||||
|
$this->getTarget() instanceof Topic && $this->getTarget()->canBeModifiedBy($user);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
namespace openvk\Web\Models\Entities;
|
namespace openvk\Web\Models\Entities;
|
||||||
use openvk\Web\Util\DateTime;
|
use openvk\Web\Util\DateTime;
|
||||||
use openvk\Web\Models\RowModel;
|
use openvk\Web\Models\RowModel;
|
||||||
use openvk\Web\Models\Repositories\{Users, SupportAliases};
|
use openvk\Web\Models\Repositories\{Users, SupportAliases, Tickets};
|
||||||
|
|
||||||
class TicketComment extends RowModel
|
class TicketComment extends RowModel
|
||||||
{
|
{
|
||||||
|
@ -29,6 +29,11 @@ class TicketComment extends RowModel
|
||||||
{
|
{
|
||||||
return (new Users)->get($this->getRecord()->user_id);
|
return (new Users)->get($this->getRecord()->user_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getTicket(): Ticket
|
||||||
|
{
|
||||||
|
return (new Tickets)->get($this->getRecord()->ticket_id);
|
||||||
|
}
|
||||||
|
|
||||||
function getAuthorName(): string
|
function getAuthorName(): string
|
||||||
{
|
{
|
||||||
|
@ -108,5 +113,19 @@ class TicketComment extends RowModel
|
||||||
return false; # Кооостыыыль!!!
|
return false; # Кооостыыыль!!!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getMark(): ?int
|
||||||
|
{
|
||||||
|
return $this->getRecord()->mark;
|
||||||
|
}
|
||||||
|
|
||||||
|
function isLikedByUser(): ?bool
|
||||||
|
{
|
||||||
|
$mark = $this->getMark();
|
||||||
|
if(is_null($mark))
|
||||||
|
return NULL;
|
||||||
|
else
|
||||||
|
return $mark === 1;
|
||||||
|
}
|
||||||
|
|
||||||
use Traits\TRichText;
|
use Traits\TRichText;
|
||||||
}
|
}
|
||||||
|
|
86
Web/Models/Entities/Topic.php
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
<?php declare(strict_types=1);
|
||||||
|
namespace openvk\Web\Models\Entities;
|
||||||
|
use openvk\Web\Models\RowModel;
|
||||||
|
use openvk\Web\Models\Repositories\Clubs;
|
||||||
|
use openvk\Web\Util\DateTime;
|
||||||
|
|
||||||
|
class Topic extends Postable
|
||||||
|
{
|
||||||
|
protected $tableName = "topics";
|
||||||
|
protected $upperNodeReferenceColumnName = "group";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* May return fake owner (group), if flags are [1, (*)]
|
||||||
|
*
|
||||||
|
* @param bool $honourFlags - check flags
|
||||||
|
*/
|
||||||
|
function getOwner(bool $honourFlags = true, bool $real = false): RowModel
|
||||||
|
{
|
||||||
|
if($honourFlags && $this->isPostedOnBehalfOfGroup())
|
||||||
|
return $this->getClub();
|
||||||
|
|
||||||
|
return parent::getOwner($real);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getClub(): Club
|
||||||
|
{
|
||||||
|
return (new Clubs)->get($this->getRecord()->group);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getTitle(): string
|
||||||
|
{
|
||||||
|
return $this->getRecord()->title;
|
||||||
|
}
|
||||||
|
|
||||||
|
function isClosed(): bool
|
||||||
|
{
|
||||||
|
return (bool) $this->getRecord()->closed;
|
||||||
|
}
|
||||||
|
|
||||||
|
function isPinned(): bool
|
||||||
|
{
|
||||||
|
return (bool) $this->getRecord()->pinned;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getPrettyId(): string
|
||||||
|
{
|
||||||
|
return $this->getRecord()->group . "_" . $this->getVirtualId();
|
||||||
|
}
|
||||||
|
|
||||||
|
function isPostedOnBehalfOfGroup(): bool
|
||||||
|
{
|
||||||
|
return ($this->getRecord()->flags & 0b10000000) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
function isDeleted(): bool
|
||||||
|
{
|
||||||
|
return (bool) $this->getRecord()->deleted;
|
||||||
|
}
|
||||||
|
|
||||||
|
function canBeModifiedBy(User $user): bool
|
||||||
|
{
|
||||||
|
return $this->getOwner(false)->getId() === $user->getId() || $this->getClub()->canBeModifiedBy($user);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getLastComment(): ?Comment
|
||||||
|
{
|
||||||
|
$array = iterator_to_array($this->getLastComments(1));
|
||||||
|
return isset($array[0]) ? $array[0] : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getUpdateTime(): DateTime
|
||||||
|
{
|
||||||
|
$lastComment = $this->getLastComment();
|
||||||
|
if(!is_null($lastComment))
|
||||||
|
return $lastComment->getPublicationTime();
|
||||||
|
else
|
||||||
|
return $this->getEditTime() ?? $this->getPublicationTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
function deleteTopic(): void
|
||||||
|
{
|
||||||
|
$this->setDeleted(1);
|
||||||
|
$this->unwire();
|
||||||
|
$this->save();
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
<?php declare(strict_types=1);
|
<?php declare(strict_types=1);
|
||||||
namespace openvk\Web\Models\Entities\Traits;
|
namespace openvk\Web\Models\Entities\Traits;
|
||||||
|
use Wkhooy\ObsceneCensorRus;
|
||||||
|
|
||||||
trait TRichText
|
trait TRichText
|
||||||
{
|
{
|
||||||
|
@ -58,9 +59,9 @@ trait TRichText
|
||||||
if($proc) {
|
if($proc) {
|
||||||
$rel = $this->isAd() ? "sponsored" : "ugc";
|
$rel = $this->isAd() ? "sponsored" : "ugc";
|
||||||
$text = $this->formatLinks($text);
|
$text = $this->formatLinks($text);
|
||||||
$text = preg_replace("%@(id|club)([0-9]++) \(([\p{L} 0-9]+)\)%Xu", "[$1$2|$3]", $text);
|
$text = preg_replace("%@([A-Za-z0-9]++) \(([\p{L} 0-9]+)\)%Xu", "[$1|$2]", $text);
|
||||||
$text = preg_replace("%@(id|club)([0-9]++)%Xu", "[$1$2|@$1$2]", $text);
|
$text = preg_replace("%@([A-Za-z0-9]++)%Xu", "[$1|@$1]", $text);
|
||||||
$text = preg_replace("%\[(id|club)([0-9]++)\|([\p{L} 0-9@]+)\]%Xu", "<a href='/$1$2'>$3</a>", $text);
|
$text = preg_replace("%\[([A-Za-z0-9]++)\|([\p{L} 0-9@]+)\]%Xu", "<a href='/$1'>$2</a>", $text);
|
||||||
$text = preg_replace("%(#([\p{L}_-]++[0-9]*[\p{L}_-]*))%Xu", "<a href='/feed/hashtag/$2'>$1</a>", $text);
|
$text = preg_replace("%(#([\p{L}_-]++[0-9]*[\p{L}_-]*))%Xu", "<a href='/feed/hashtag/$2'>$1</a>", $text);
|
||||||
$text = $this->formatEmojis($text);
|
$text = $this->formatEmojis($text);
|
||||||
}
|
}
|
||||||
|
@ -69,6 +70,9 @@ trait TRichText
|
||||||
$text = nl2br($text);
|
$text = nl2br($text);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(OPENVK_ROOT_CONF["openvk"]["preferences"]["wall"]["christian"])
|
||||||
|
ObsceneCensorRus::filterText($text);
|
||||||
|
|
||||||
return $text;
|
return $text;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -317,14 +317,14 @@ class User extends RowModel
|
||||||
return $this->getRecord()->notification_offset;
|
return $this->getRecord()->notification_offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getBirthday(): ?int
|
function getBirthday(): ?DateTime
|
||||||
{
|
{
|
||||||
return $this->getRecord()->birthday;
|
return new DateTime($this->getRecord()->birthday);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getAge(): ?int
|
function getAge(): ?int
|
||||||
{
|
{
|
||||||
return (int)floor((time() - $this->getBirthday()) / mktime(0, 0, 0, 1, 1, 1971));
|
return (int)floor((time() - $this->getBirthday()->timestamp()) / mktime(0, 0, 0, 1, 1, 1971));
|
||||||
}
|
}
|
||||||
|
|
||||||
function get2faSecret(): ?string
|
function get2faSecret(): ?string
|
||||||
|
|
|
@ -48,6 +48,15 @@ class TicketComments
|
||||||
// {
|
// {
|
||||||
// return $this->toTicket($this->tickets->get($id));
|
// return $this->toTicket($this->tickets->get($id));
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
function get(int $id): ?TicketComment
|
||||||
|
{
|
||||||
|
$comment = $this->comments->get($id);;
|
||||||
|
if (!is_null($comment))
|
||||||
|
return new TicketComment($comment);
|
||||||
|
else
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
use \Nette\SmartObject;
|
use \Nette\SmartObject;
|
||||||
}
|
}
|
||||||
|
|
73
Web/Models/Repositories/Topics.php
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
<?php declare(strict_types=1);
|
||||||
|
namespace openvk\Web\Models\Repositories;
|
||||||
|
use openvk\Web\Models\Entities\Topic;
|
||||||
|
use openvk\Web\Models\Entities\Club;
|
||||||
|
use Nette\Database\Table\ActiveRow;
|
||||||
|
use Chandler\Database\DatabaseConnection;
|
||||||
|
|
||||||
|
class Topics
|
||||||
|
{
|
||||||
|
private $context;
|
||||||
|
private $topics;
|
||||||
|
|
||||||
|
function __construct()
|
||||||
|
{
|
||||||
|
$this->context = DatabaseConnection::i()->getContext();
|
||||||
|
$this->topics = $this->context->table("topics");
|
||||||
|
}
|
||||||
|
|
||||||
|
private function toTopic(?ActiveRow $ar): ?Topic
|
||||||
|
{
|
||||||
|
return is_null($ar) ? NULL : new Topic($ar);
|
||||||
|
}
|
||||||
|
|
||||||
|
function get(int $id): ?Topic
|
||||||
|
{
|
||||||
|
return $this->toTopic($this->topics->get($id));
|
||||||
|
}
|
||||||
|
|
||||||
|
function getTopicById(int $club, int $topic): ?Topic
|
||||||
|
{
|
||||||
|
return $this->toTopic($this->topics->where(["group" => $club, "virtual_id" => $topic, "deleted" => 0])->fetch());
|
||||||
|
}
|
||||||
|
|
||||||
|
function getClubTopics(Club $club, int $page = 1, ?int $perPage = NULL): \Traversable
|
||||||
|
{
|
||||||
|
$perPage = $perPage ?? OPENVK_DEFAULT_PER_PAGE;
|
||||||
|
|
||||||
|
// Get pinned topics first
|
||||||
|
$query = "SELECT `id` FROM `topics` WHERE `pinned` = 1 AND `group` = ? AND `deleted` = 0 UNION SELECT `id` FROM `topics` WHERE `pinned` = 0 AND `group` = ? AND `deleted` = 0";
|
||||||
|
$query .= " LIMIT " . $perPage . " OFFSET " . ($page - 1) * $perPage;
|
||||||
|
|
||||||
|
foreach(DatabaseConnection::i()->getConnection()->query($query, $club->getId(), $club->getId()) as $topic) {
|
||||||
|
$topic = $this->get($topic->id);
|
||||||
|
if(!$topic) continue;
|
||||||
|
|
||||||
|
yield $topic;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getClubTopicsCount(Club $club): int
|
||||||
|
{
|
||||||
|
return sizeof($this->topics->where([
|
||||||
|
"group" => $club->getId(),
|
||||||
|
"deleted" => false
|
||||||
|
]));
|
||||||
|
}
|
||||||
|
|
||||||
|
function find(Club $club, string $query): \Traversable
|
||||||
|
{
|
||||||
|
return new Util\EntityStream("Topic", $this->topics->where("title LIKE ? AND group = ? AND deleted = 0", "%$query%", $club->getId()));
|
||||||
|
}
|
||||||
|
|
||||||
|
function getLastTopics(Club $club, ?int $count = NULL): \Traversable
|
||||||
|
{
|
||||||
|
$topics = $this->topics->where([
|
||||||
|
"group" => $club->getId(),
|
||||||
|
"deleted" => false
|
||||||
|
])->page(1, $count ?? OPENVK_DEFAULT_PER_PAGE)->order("created DESC");
|
||||||
|
|
||||||
|
foreach($topics as $topic)
|
||||||
|
yield $this->toTopic($topic);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,16 +1,17 @@
|
||||||
<?php declare(strict_types=1);
|
<?php declare(strict_types=1);
|
||||||
namespace openvk\Web\Presenters;
|
namespace openvk\Web\Presenters;
|
||||||
use openvk\Web\Models\Entities\{Comment, Photo, Video, User};
|
use openvk\Web\Models\Entities\{Comment, Photo, Video, User, Topic};
|
||||||
use openvk\Web\Models\Entities\Notifications\CommentNotification;
|
use openvk\Web\Models\Entities\Notifications\CommentNotification;
|
||||||
use openvk\Web\Models\Repositories\Comments;
|
use openvk\Web\Models\Repositories\Comments;
|
||||||
|
|
||||||
final class CommentPresenter extends OpenVKPresenter
|
final class CommentPresenter extends OpenVKPresenter
|
||||||
{
|
{
|
||||||
private $models = [
|
private $models = [
|
||||||
"posts" => "openvk\\Web\\Models\\Repositories\\Posts",
|
"posts" => "openvk\\Web\\Models\\Repositories\\Posts",
|
||||||
"photos" => "openvk\\Web\\Models\\Repositories\\Photos",
|
"photos" => "openvk\\Web\\Models\\Repositories\\Photos",
|
||||||
"videos" => "openvk\\Web\\Models\\Repositories\\Videos",
|
"videos" => "openvk\\Web\\Models\\Repositories\\Videos",
|
||||||
"notes" => "openvk\\Web\\Models\\Repositories\\Notes",
|
"notes" => "openvk\\Web\\Models\\Repositories\\Notes",
|
||||||
|
"topics" => "openvk\\Web\\Models\\Repositories\\Topics",
|
||||||
];
|
];
|
||||||
|
|
||||||
function renderLike(int $id): void
|
function renderLike(int $id): void
|
||||||
|
@ -37,9 +38,17 @@ final class CommentPresenter extends OpenVKPresenter
|
||||||
$repo = new $repoClass;
|
$repo = new $repoClass;
|
||||||
$entity = $repo->get($eId);
|
$entity = $repo->get($eId);
|
||||||
if(!$entity) $this->notFound();
|
if(!$entity) $this->notFound();
|
||||||
|
|
||||||
|
if($entity instanceof Topic && $entity->isClosed())
|
||||||
|
$this->notFound();
|
||||||
|
|
||||||
|
if($entity instanceof Post && $entity->getTargetWall() > 0)
|
||||||
|
$club = (new Clubs)->get(abs($entity->getTargetWall()));
|
||||||
|
else if($entity instanceof Topic)
|
||||||
|
$club = $entity->getClub();
|
||||||
|
|
||||||
$flags = 0;
|
$flags = 0;
|
||||||
if($this->postParam("as_group") === "on")
|
if($this->postParam("as_group") === "on" && !is_null($club) && $club->canBeModifiedBy($this->user->identity))
|
||||||
$flags |= 0b10000000;
|
$flags |= 0b10000000;
|
||||||
|
|
||||||
$photo = NULL;
|
$photo = NULL;
|
||||||
|
@ -106,9 +115,8 @@ final class CommentPresenter extends OpenVKPresenter
|
||||||
|
|
||||||
$comment = (new Comments)->get($id);
|
$comment = (new Comments)->get($id);
|
||||||
if(!$comment) $this->notFound();
|
if(!$comment) $this->notFound();
|
||||||
if($comment->getOwner()->getId() !== $this->user->id)
|
if(!$comment->canBeDeletedBy($this->user->identity))
|
||||||
if($comment->getTarget()->getOwner()->getId() !== $this->user->id)
|
$this->throwError(403, "Forbidden", "У вас недостаточно прав чтобы редактировать этот ресурс.");
|
||||||
$this->throwError(403, "Forbidden", "У вас недостаточно прав чтобы редактировать этот ресурс.");
|
|
||||||
|
|
||||||
$comment->delete();
|
$comment->delete();
|
||||||
$this->flashFail(
|
$this->flashFail(
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
namespace openvk\Web\Presenters;
|
namespace openvk\Web\Presenters;
|
||||||
use openvk\Web\Models\Entities\{Club, Photo};
|
use openvk\Web\Models\Entities\{Club, Photo};
|
||||||
use openvk\Web\Models\Entities\Notifications\ClubModeratorNotification;
|
use openvk\Web\Models\Entities\Notifications\ClubModeratorNotification;
|
||||||
use openvk\Web\Models\Repositories\{Clubs, Users, Albums, Managers};
|
use openvk\Web\Models\Repositories\{Clubs, Users, Albums, Managers, Topics};
|
||||||
use Chandler\Security\Authenticator;
|
use Chandler\Security\Authenticator;
|
||||||
|
|
||||||
final class GroupPresenter extends OpenVKPresenter
|
final class GroupPresenter extends OpenVKPresenter
|
||||||
|
@ -29,6 +29,8 @@ final class GroupPresenter extends OpenVKPresenter
|
||||||
$this->template->club = $club;
|
$this->template->club = $club;
|
||||||
$this->template->albums = (new Albums)->getClubAlbums($club, 1, 3);
|
$this->template->albums = (new Albums)->getClubAlbums($club, 1, 3);
|
||||||
$this->template->albumsCount = (new Albums)->getClubAlbumsCount($club);
|
$this->template->albumsCount = (new Albums)->getClubAlbumsCount($club);
|
||||||
|
$this->template->topics = (new Topics)->getLastTopics($club, 3);
|
||||||
|
$this->template->topicsCount = (new Topics)->getClubTopicsCount($club);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -205,6 +207,7 @@ 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);
|
||||||
|
|
||||||
$website = $this->postParam("website") ?? "";
|
$website = $this->postParam("website") ?? "";
|
||||||
if(empty($website))
|
if(empty($website))
|
||||||
|
|
|
@ -19,6 +19,8 @@ final class NotesPresenter extends OpenVKPresenter
|
||||||
{
|
{
|
||||||
$user = (new Users)->get($owner);
|
$user = (new Users)->get($owner);
|
||||||
if(!$user) $this->notFound();
|
if(!$user) $this->notFound();
|
||||||
|
if(!$user->getPrivacyPermission('notes.read', $this->user->identity ?? NULL))
|
||||||
|
$this->flashFail("err", tr("forbidden"), tr("forbidden_comment"));
|
||||||
|
|
||||||
$this->template->notes = $this->notes->getUserNotes($user, (int)($this->queryParam("p") ?? 1));
|
$this->template->notes = $this->notes->getUserNotes($user, (int)($this->queryParam("p") ?? 1));
|
||||||
$this->template->count = $this->notes->getUserNotesCount($user);
|
$this->template->count = $this->notes->getUserNotesCount($user);
|
||||||
|
@ -36,6 +38,8 @@ final class NotesPresenter extends OpenVKPresenter
|
||||||
$note = $this->notes->getNoteById($owner, $note_id);
|
$note = $this->notes->getNoteById($owner, $note_id);
|
||||||
if(!$note || $note->getOwner()->getId() !== $owner || $note->isDeleted())
|
if(!$note || $note->getOwner()->getId() !== $owner || $note->isDeleted())
|
||||||
$this->notFound();
|
$this->notFound();
|
||||||
|
if(!$note->getOwner()->getPrivacyPermission('notes.read', $this->user->identity ?? NULL))
|
||||||
|
$this->flashFail("err", tr("forbidden"), tr("forbidden_comment"));
|
||||||
|
|
||||||
$this->template->cCount = $note->getCommentsCount();
|
$this->template->cCount = $note->getCommentsCount();
|
||||||
$this->template->cPage = (int) ($this->queryParam("p") ?? 1);
|
$this->template->cPage = (int) ($this->queryParam("p") ?? 1);
|
||||||
|
|
|
@ -34,10 +34,10 @@ abstract class OpenVKPresenter extends SimplePresenter
|
||||||
]));
|
]));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function setTempTheme(string $theme): void
|
protected function setTempTheme(string $theme): void
|
||||||
{
|
{
|
||||||
Session::i()->set("_tempTheme", $theme);
|
Session::i()->set("_tempTheme", $theme);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function flashFail(string $type, string $title, ?string $message = NULL, ?int $code = NULL): void
|
protected function flashFail(string $type, string $title, ?string $message = NULL, ?int $code = NULL): void
|
||||||
{
|
{
|
||||||
|
@ -198,6 +198,7 @@ abstract class OpenVKPresenter extends SimplePresenter
|
||||||
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"],
|
||||||
]);
|
]);
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
|
@ -221,25 +222,23 @@ abstract class OpenVKPresenter extends SimplePresenter
|
||||||
{
|
{
|
||||||
parent::onBeforeRender();
|
parent::onBeforeRender();
|
||||||
|
|
||||||
if(!is_null($this->user)) {
|
$theme = NULL;
|
||||||
$theme = $this->user->identity->getTheme();
|
if(Session::i()->get("_tempTheme")) {
|
||||||
if(!is_null($theme) && $theme->overridesTemplates()) {
|
$theme = Themepacks::i()[Session::i()->get("_tempTheme", "ovk")];
|
||||||
$this->template->_templatePath = $theme->getBaseDir() . "/tpl";
|
Session::i()->set("_tempTheme", NULL);
|
||||||
}
|
} else if($this->requestParam("themePreview")) {
|
||||||
|
$theme = Themepacks::i()[$this->requestParam("themePreview")];
|
||||||
|
} else if($this->user->identity !== null && $this->user->identity->getTheme()) {
|
||||||
|
$theme = $this->user->identity->getTheme();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$this->template->theme = $theme;
|
||||||
|
if(!is_null($theme) && $theme->overridesTemplates())
|
||||||
|
$this->template->_templatePath = $theme->getBaseDir() . "/tpl";
|
||||||
|
|
||||||
if(!is_null(Session::i()->get("_error"))) {
|
if(!is_null(Session::i()->get("_error"))) {
|
||||||
$this->template->flashMessage = json_decode(Session::i()->get("_error"));
|
$this->template->flashMessage = json_decode(Session::i()->get("_error"));
|
||||||
Session::i()->set("_error", NULL);
|
Session::i()->set("_error", NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(Session::i()->get("_tempTheme"))
|
|
||||||
$this->template->theme = Themepacks::i()[Session::i()->get("_tempTheme", "ovk")];
|
|
||||||
else if($this->requestParam("themePreview"))
|
|
||||||
$this->template->theme = Themepacks::i()[$this->requestParam("themePreview")];
|
|
||||||
else if($this->user->identity !== null && $this->user->identity->getTheme())
|
|
||||||
$this->template->theme = $this->user->identity->getTheme();
|
|
||||||
|
|
||||||
// Знаю, каша ебаная, целестора рефактор всё равно сделает :)))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,8 @@ final class PhotosPresenter extends OpenVKPresenter
|
||||||
if($owner > 0) {
|
if($owner > 0) {
|
||||||
$user = $this->users->get($owner);
|
$user = $this->users->get($owner);
|
||||||
if(!$user) $this->notFound();
|
if(!$user) $this->notFound();
|
||||||
|
if (!$user->getPrivacyPermission('photos.read', $this->user->identity ?? NULL))
|
||||||
|
$this->flashFail("err", tr("forbidden"), tr("forbidden_comment"));
|
||||||
$this->template->albums = $this->albums->getUserAlbums($user, $this->queryParam("p") ?? 1);
|
$this->template->albums = $this->albums->getUserAlbums($user, $this->queryParam("p") ?? 1);
|
||||||
$this->template->count = $this->albums->getUserAlbumsCount($user);
|
$this->template->count = $this->albums->getUserAlbumsCount($user);
|
||||||
$this->template->owner = $user;
|
$this->template->owner = $user;
|
||||||
|
@ -129,6 +131,12 @@ final class PhotosPresenter extends OpenVKPresenter
|
||||||
if($album->getPrettyId() !== $owner . "_" . $id || $album->isDeleted())
|
if($album->getPrettyId() !== $owner . "_" . $id || $album->isDeleted())
|
||||||
$this->notFound();
|
$this->notFound();
|
||||||
|
|
||||||
|
if($owner > 0 /* bc we currently don't have perms for clubs */) {
|
||||||
|
$ownerObject = (new Users)->get($owner);
|
||||||
|
if(!$ownerObject->getPrivacyPermission('photos.read', $this->user->identity ?? NULL))
|
||||||
|
$this->flashFail("err", tr("forbidden"), tr("forbidden_comment"));
|
||||||
|
}
|
||||||
|
|
||||||
$this->template->album = $album;
|
$this->template->album = $album;
|
||||||
$this->template->photos = iterator_to_array( $album->getPhotos( (int) ($this->queryParam("p") ?? 1) ) );
|
$this->template->photos = iterator_to_array( $album->getPhotos( (int) ($this->queryParam("p") ?? 1) ) );
|
||||||
$this->template->paginatorConf = (object) [
|
$this->template->paginatorConf = (object) [
|
||||||
|
|
|
@ -31,12 +31,11 @@ final class SupportPresenter extends OpenVKPresenter
|
||||||
$tickets = $this->tickets->getTicketsByuId($this->user->id);
|
$tickets = $this->tickets->getTicketsByuId($this->user->id);
|
||||||
if($tickets)
|
if($tickets)
|
||||||
$this->template->tickets = $tickets;
|
$this->template->tickets = $tickets;
|
||||||
|
|
||||||
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->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);
|
||||||
|
@ -225,4 +224,24 @@ final class SupportPresenter extends OpenVKPresenter
|
||||||
$this->template->heading = $heading;
|
$this->template->heading = $heading;
|
||||||
$this->template->content = $parser->parse($content);
|
$this->template->content = $parser->parse($content);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
function renderRateAnswer(int $id, int $mark): void
|
||||||
|
{
|
||||||
|
$this->willExecuteWriteAction();
|
||||||
|
$this->assertUserLoggedIn();
|
||||||
|
$this->assertNoCSRF();
|
||||||
|
|
||||||
|
$comment = $this->comments->get($id);
|
||||||
|
|
||||||
|
if($this->user->id !== $comment->getTicket()->getUser()->getId())
|
||||||
|
exit(header("HTTP/1.1 403 Forbidden"));
|
||||||
|
|
||||||
|
if($mark !== 1 && $mark !== 2)
|
||||||
|
exit(header("HTTP/1.1 400 Bad Request"));
|
||||||
|
|
||||||
|
$comment->setMark($mark);
|
||||||
|
$comment->save();
|
||||||
|
|
||||||
|
exit(header("HTTP/1.1 200 OK"));
|
||||||
|
}
|
||||||
|
}
|
194
Web/Presenters/TopicsPresenter.php
Normal file
|
@ -0,0 +1,194 @@
|
||||||
|
<?php declare(strict_types=1);
|
||||||
|
namespace openvk\Web\Presenters;
|
||||||
|
use openvk\Web\Models\Entities\{Topic, Club, Comment, Photo, Video};
|
||||||
|
use openvk\Web\Models\Repositories\{Topics, Clubs};
|
||||||
|
|
||||||
|
final class TopicsPresenter extends OpenVKPresenter
|
||||||
|
{
|
||||||
|
private $topics;
|
||||||
|
private $clubs;
|
||||||
|
|
||||||
|
function __construct(Topics $topics, Clubs $clubs)
|
||||||
|
{
|
||||||
|
$this->topics = $topics;
|
||||||
|
$this->clubs = $clubs;
|
||||||
|
|
||||||
|
parent::__construct();
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderBoard(int $id): void
|
||||||
|
{
|
||||||
|
$this->assertUserLoggedIn();
|
||||||
|
|
||||||
|
$club = $this->clubs->get($id);
|
||||||
|
if(!$club)
|
||||||
|
$this->notFound();
|
||||||
|
|
||||||
|
$this->template->club = $club;
|
||||||
|
$page = (int) ($this->queryParam("p") ?? 1);
|
||||||
|
|
||||||
|
$query = $this->queryParam("query");
|
||||||
|
if($query) {
|
||||||
|
$results = $this->topics->find($club, $query);
|
||||||
|
$this->template->topics = $results->page($page);
|
||||||
|
$this->template->count = $results->size();
|
||||||
|
} else {
|
||||||
|
$this->template->topics = $this->topics->getClubTopics($club, $page);
|
||||||
|
$this->template->count = $this->topics->getClubTopicsCount($club);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->template->paginatorConf = (object) [
|
||||||
|
"count" => $this->template->count,
|
||||||
|
"page" => $page,
|
||||||
|
"amount" => NULL,
|
||||||
|
"perPage" => OPENVK_DEFAULT_PER_PAGE,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderTopic(int $clubId, int $topicId): void
|
||||||
|
{
|
||||||
|
$this->assertUserLoggedIn();
|
||||||
|
|
||||||
|
$topic = $this->topics->getTopicById($clubId, $topicId);
|
||||||
|
if(!$topic)
|
||||||
|
$this->notFound();
|
||||||
|
|
||||||
|
$this->template->topic = $topic;
|
||||||
|
$this->template->club = $topic->getClub();
|
||||||
|
$this->template->count = $topic->getCommentsCount();
|
||||||
|
$this->template->page = (int) ($this->queryParam("p") ?? 1);
|
||||||
|
$this->template->comments = iterator_to_array($topic->getComments($this->template->page));
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderCreate(int $clubId): void
|
||||||
|
{
|
||||||
|
$this->assertUserLoggedIn();
|
||||||
|
|
||||||
|
$club = $this->clubs->get($clubId);
|
||||||
|
if(!$club)
|
||||||
|
$this->notFound();
|
||||||
|
|
||||||
|
if(!$club->isEveryoneCanCreateTopics() && !$club->canBeModifiedBy($this->user->identity))
|
||||||
|
$this->notFound();
|
||||||
|
|
||||||
|
|
||||||
|
if($_SERVER["REQUEST_METHOD"] === "POST") {
|
||||||
|
$this->willExecuteWriteAction();
|
||||||
|
$title = $this->postParam("title");
|
||||||
|
|
||||||
|
if(!$title)
|
||||||
|
$this->flashFail("err", tr("failed_to_create_topic"), tr("no_title_specified"));
|
||||||
|
|
||||||
|
$flags = 0;
|
||||||
|
if($this->postParam("as_group") === "on" && $club->canBeModifiedBy($this->user->identity))
|
||||||
|
$flags |= 0b10000000;
|
||||||
|
|
||||||
|
$topic = new Topic;
|
||||||
|
$topic->setGroup($club->getId());
|
||||||
|
$topic->setOwner($this->user->id);
|
||||||
|
$topic->setTitle(ovk_proc_strtr($title, 127));
|
||||||
|
$topic->setCreated(time());
|
||||||
|
$topic->setFlags($flags);
|
||||||
|
$topic->save();
|
||||||
|
|
||||||
|
// TODO move to trait
|
||||||
|
try {
|
||||||
|
$photo = NULL;
|
||||||
|
$video = NULL;
|
||||||
|
if($_FILES["_pic_attachment"]["error"] === UPLOAD_ERR_OK) {
|
||||||
|
$album = NULL;
|
||||||
|
if($wall > 0 && $wall === $this->user->id)
|
||||||
|
$album = (new Albums)->getUserWallAlbum($wallOwner);
|
||||||
|
|
||||||
|
$photo = Photo::fastMake($this->user->id, $this->postParam("text"), $_FILES["_pic_attachment"], $album);
|
||||||
|
}
|
||||||
|
|
||||||
|
if($_FILES["_vid_attachment"]["error"] === UPLOAD_ERR_OK) {
|
||||||
|
$video = Video::fastMake($this->user->id, $this->postParam("text"), $_FILES["_vid_attachment"]);
|
||||||
|
}
|
||||||
|
} catch(ISE $ex) {
|
||||||
|
$this->flash("err", "Не удалось опубликовать комментарий", "Файл медиаконтента повреждён или слишком велик.");
|
||||||
|
$this->redirect("/topic" . $topic->getPrettyId(), static::REDIRECT_TEMPORARY);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!empty($this->postParam("text")) || $photo || $video) {
|
||||||
|
try {
|
||||||
|
$comment = new Comment;
|
||||||
|
$comment->setOwner($this->user->id);
|
||||||
|
$comment->setModel(get_class($topic));
|
||||||
|
$comment->setTarget($topic->getId());
|
||||||
|
$comment->setContent($this->postParam("text"));
|
||||||
|
$comment->setCreated(time());
|
||||||
|
$comment->setFlags($flags);
|
||||||
|
$comment->save();
|
||||||
|
} catch (\LengthException $ex) {
|
||||||
|
$this->flash("err", "Не удалось опубликовать комментарий", "Комментарий слишком большой.");
|
||||||
|
$this->redirect("/topic" . $topic->getPrettyId(), static::REDIRECT_TEMPORARY);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!is_null($photo))
|
||||||
|
$comment->attach($photo);
|
||||||
|
|
||||||
|
if(!is_null($video))
|
||||||
|
$comment->attach($video);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->redirect("/topic" . $topic->getPrettyId(), static::REDIRECT_TEMPORARY);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->template->club = $club;
|
||||||
|
$this->template->graffiti = (bool) ovkGetQuirk("comments.allow-graffiti");
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderEdit(int $clubId, int $topicId): void
|
||||||
|
{
|
||||||
|
$this->assertUserLoggedIn();
|
||||||
|
|
||||||
|
$topic = $this->topics->getTopicById($clubId, $topicId);
|
||||||
|
if(!$topic)
|
||||||
|
$this->notFound();
|
||||||
|
|
||||||
|
if(!$topic->canBeModifiedBy($this->user->identity))
|
||||||
|
$this->notFound();
|
||||||
|
|
||||||
|
if($_SERVER["REQUEST_METHOD"] === "POST") {
|
||||||
|
$this->willExecuteWriteAction();
|
||||||
|
$title = $this->postParam("title");
|
||||||
|
|
||||||
|
if(!$title)
|
||||||
|
$this->flashFail("err", tr("failed_to_change_topic"), tr("no_title_specified"));
|
||||||
|
|
||||||
|
$topic->setTitle(ovk_proc_strtr($title, 127));
|
||||||
|
$topic->setClosed(empty($this->postParam("close")) ? 0 : 1);
|
||||||
|
|
||||||
|
if($topic->getClub()->canBeModifiedBy($this->user->identity))
|
||||||
|
$topic->setPinned(empty($this->postParam("pin")) ? 0 : 1);
|
||||||
|
|
||||||
|
$topic->save();
|
||||||
|
|
||||||
|
$this->flash("succ", tr("changes_saved"), tr("topic_changes_saved_comment"));
|
||||||
|
$this->redirect("/topic" . $topic->getPrettyId(), static::REDIRECT_TEMPORARY);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->template->topic = $topic;
|
||||||
|
$this->template->club = $topic->getClub();
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderDelete(int $clubId, int $topicId): void
|
||||||
|
{
|
||||||
|
$this->assertUserLoggedIn();
|
||||||
|
$this->assertNoCSRF();
|
||||||
|
|
||||||
|
$topic = $this->topics->getTopicById($clubId, $topicId);
|
||||||
|
if(!$topic)
|
||||||
|
$this->notFound();
|
||||||
|
|
||||||
|
if(!$topic->canBeModifiedBy($this->user->identity))
|
||||||
|
$this->notFound();
|
||||||
|
|
||||||
|
$this->willExecuteWriteAction();
|
||||||
|
$topic->deleteTopic();
|
||||||
|
|
||||||
|
$this->redirect("/board" . $topic->getClub()->getId(), static::REDIRECT_TEMPORARY);
|
||||||
|
}
|
||||||
|
}
|
|
@ -54,6 +54,8 @@ final class UserPresenter extends OpenVKPresenter
|
||||||
$page = abs($this->queryParam("p") ?? 1);
|
$page = abs($this->queryParam("p") ?? 1);
|
||||||
if(!$user)
|
if(!$user)
|
||||||
$this->notFound();
|
$this->notFound();
|
||||||
|
elseif (!$user->getPrivacyPermission('friends.read', $this->user->identity ?? NULL))
|
||||||
|
$this->flashFail("err", tr("forbidden"), tr("forbidden_comment"));
|
||||||
else
|
else
|
||||||
$this->template->user = $user;
|
$this->template->user = $user;
|
||||||
|
|
||||||
|
@ -78,9 +80,11 @@ final class UserPresenter extends OpenVKPresenter
|
||||||
$this->assertUserLoggedIn();
|
$this->assertUserLoggedIn();
|
||||||
|
|
||||||
$user = $this->users->get($id);
|
$user = $this->users->get($id);
|
||||||
if(!$user) {
|
if(!$user)
|
||||||
$this->notFound();
|
$this->notFound();
|
||||||
} else {
|
elseif (!$user->getPrivacyPermission('groups.read', $this->user->identity ?? NULL))
|
||||||
|
$this->flashFail("err", tr("forbidden"), tr("forbidden_comment"));
|
||||||
|
else {
|
||||||
$this->template->user = $user;
|
$this->template->user = $user;
|
||||||
$this->template->page = $this->queryParam("p") ?? 1;
|
$this->template->page = $this->queryParam("p") ?? 1;
|
||||||
$this->template->admin = $this->queryParam("act") == "managed";
|
$this->template->admin = $this->queryParam("act") == "managed";
|
||||||
|
@ -128,99 +132,99 @@ final class UserPresenter extends OpenVKPresenter
|
||||||
if(!$id)
|
if(!$id)
|
||||||
$this->notFound();
|
$this->notFound();
|
||||||
|
|
||||||
$user = $this->users->get($id);
|
$user = $this->users->get($id);
|
||||||
if($_SERVER["REQUEST_METHOD"] === "POST") {
|
if($_SERVER["REQUEST_METHOD"] === "POST") {
|
||||||
$this->willExecuteWriteAction();
|
$this->willExecuteWriteAction();
|
||||||
|
|
||||||
|
if($_GET['act'] === "main" || $_GET['act'] == NULL) {
|
||||||
|
$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"));
|
||||||
|
$user->setPseudo(empty($this->postParam("pseudo")) ? NULL : $this->postParam("pseudo"));
|
||||||
|
$user->setStatus(empty($this->postParam("status")) ? NULL : $this->postParam("status"));
|
||||||
|
if (strtotime($this->postParam("birthday")) < time())
|
||||||
|
$user->setBirthday(strtotime($this->postParam("birthday")));
|
||||||
|
|
||||||
|
if ($this->postParam("marialstatus") <= 8 && $this->postParam("marialstatus") >= 0)
|
||||||
|
$user->setMarital_Status($this->postParam("marialstatus"));
|
||||||
|
|
||||||
if($_GET['act'] === "main" || $_GET['act'] == NULL) {
|
if ($this->postParam("politViews") <= 9 && $this->postParam("politViews") >= 0)
|
||||||
$user->setFirst_Name(empty($this->postParam("first_name")) ? $user->getFirstName() : $this->postParam("first_name"));
|
$user->setPolit_Views($this->postParam("politViews"));
|
||||||
$user->setLast_Name(empty($this->postParam("last_name")) ? "" : $this->postParam("last_name"));
|
|
||||||
$user->setPseudo(empty($this->postParam("pseudo")) ? NULL : $this->postParam("pseudo"));
|
if ($this->postParam("gender") <= 1 && $this->postParam("gender") >= 0)
|
||||||
$user->setStatus(empty($this->postParam("status")) ? NULL : $this->postParam("status"));
|
$user->setSex($this->postParam("gender"));
|
||||||
if (strtotime($this->postParam("birthday")) < time())
|
|
||||||
$user->setBirthday(strtotime($this->postParam("birthday")));
|
if(!empty($this->postParam("phone")) && $this->postParam("phone") !== $user->getPhone()) {
|
||||||
|
if(!OPENVK_ROOT_CONF["openvk"]["credentials"]["smsc"]["enable"])
|
||||||
if ($this->postParam("marialstatus") <= 8 && $this->postParam("marialstatus") >= 0)
|
$this->flashFail("err", tr("error_segmentation"), "котлетки");
|
||||||
$user->setMarital_Status($this->postParam("marialstatus"));
|
|
||||||
|
|
||||||
if ($this->postParam("politViews") <= 9 && $this->postParam("politViews") >= 0)
|
$code = $user->setPhoneWithVerification($this->postParam("phone"));
|
||||||
$user->setPolit_Views($this->postParam("politViews"));
|
|
||||||
|
|
||||||
if ($this->postParam("gender") <= 1 && $this->postParam("gender") >= 0)
|
if(!Sms::send($this->postParam("phone"), "OPENVK - Your verification code is: $code"))
|
||||||
$user->setSex($this->postParam("gender"));
|
$this->flashFail("err", tr("error_segmentation"), "котлетки: Remote err!");
|
||||||
|
|
||||||
if(!empty($this->postParam("phone")) && $this->postParam("phone") !== $user->getPhone()) {
|
|
||||||
if(!OPENVK_ROOT_CONF["openvk"]["credentials"]["smsc"]["enable"])
|
|
||||||
$this->flashFail("err", tr("error_segmentation"), "котлетки");
|
|
||||||
|
|
||||||
$code = $user->setPhoneWithVerification($this->postParam("phone"));
|
|
||||||
|
|
||||||
if(!Sms::send($this->postParam("phone"), "OPENVK - Your verification code is: $code"))
|
|
||||||
$this->flashFail("err", tr("error_segmentation"), "котлетки: Remote err!");
|
|
||||||
}
|
|
||||||
} elseif($_GET['act'] === "contacts") {
|
|
||||||
if(empty($this->postParam("email_contact")) || Validator::i()->emailValid($this->postParam("email_contact")))
|
|
||||||
$user->setEmail_Contact(empty($this->postParam("email_contact")) ? NULL : $this->postParam("email_contact"));
|
|
||||||
else
|
|
||||||
$this->flashFail("err", tr("invalid_email_address"), tr("invalid_email_address_comment"));
|
|
||||||
|
|
||||||
$telegram = $this->postParam("telegram");
|
|
||||||
if(empty($telegram) || Validator::i()->telegramValid($telegram))
|
|
||||||
if(strpos($telegram, "t.me/") === 0)
|
|
||||||
$user->setTelegram(empty($telegram) ? NULL : substr($telegram, 5));
|
|
||||||
else
|
|
||||||
$user->setTelegram(empty($telegram) ? NULL : ltrim($telegram, "@"));
|
|
||||||
else
|
|
||||||
$this->flashFail("err", tr("invalid_telegram_name"), tr("invalid_telegram_name_comment"));
|
|
||||||
|
|
||||||
$user->setCity(empty($this->postParam("city")) ? NULL : $this->postParam("city"));
|
|
||||||
$user->setAddress(empty($this->postParam("address")) ? NULL : $this->postParam("address"));
|
|
||||||
|
|
||||||
$website = $this->postParam("website") ?? "";
|
|
||||||
if(empty($website))
|
|
||||||
$user->setWebsite(NULL);
|
|
||||||
else
|
|
||||||
$user->setWebsite((!parse_url($website, PHP_URL_SCHEME) ? "https://" : "") . $website);
|
|
||||||
} elseif($_GET['act'] === "interests") {
|
|
||||||
$user->setInterests(empty($this->postParam("interests")) ? NULL : ovk_proc_strtr($this->postParam("interests"), 300));
|
|
||||||
$user->setFav_Music(empty($this->postParam("fav_music")) ? NULL : ovk_proc_strtr($this->postParam("fav_music"), 300));
|
|
||||||
$user->setFav_Films(empty($this->postParam("fav_films")) ? NULL : ovk_proc_strtr($this->postParam("fav_films"), 300));
|
|
||||||
$user->setFav_Shows(empty($this->postParam("fav_shows")) ? NULL : ovk_proc_strtr($this->postParam("fav_shows"), 300));
|
|
||||||
$user->setFav_Books(empty($this->postParam("fav_books")) ? NULL : ovk_proc_strtr($this->postParam("fav_books"), 300));
|
|
||||||
$user->setFav_Quote(empty($this->postParam("fav_quote")) ? NULL : ovk_proc_strtr($this->postParam("fav_quote"), 300));
|
|
||||||
$user->setAbout(empty($this->postParam("about")) ? NULL : ovk_proc_strtr($this->postParam("about"), 300));
|
|
||||||
} elseif($_GET['act'] === "status") {
|
|
||||||
if(mb_strlen($this->postParam("status")) > 255) {
|
|
||||||
$statusLength = (string) mb_strlen($this->postParam("status"));
|
|
||||||
$this->flashFail("err", "Ошибка", "Статус слишком длинный ($statusLength символов вместо 255 символов)");
|
|
||||||
}
|
|
||||||
|
|
||||||
$user->setStatus(empty($this->postParam("status")) ? NULL : $this->postParam("status"));
|
|
||||||
$user->save();
|
|
||||||
|
|
||||||
header("HTTP/1.1 302 Found");
|
|
||||||
header("Location: /id" . $user->getId());
|
|
||||||
exit;
|
|
||||||
}
|
}
|
||||||
|
} elseif($_GET['act'] === "contacts") {
|
||||||
try {
|
if(empty($this->postParam("email_contact")) || Validator::i()->emailValid($this->postParam("email_contact")))
|
||||||
$user->save();
|
$user->setEmail_Contact(empty($this->postParam("email_contact")) ? NULL : $this->postParam("email_contact"));
|
||||||
} catch(\PDOException $ex) {
|
else
|
||||||
if($ex->getCode() == 23000)
|
$this->flashFail("err", tr("invalid_email_address"), tr("invalid_email_address_comment"));
|
||||||
$this->flashFail("err", tr("error"), tr("error_shorturl"));
|
|
||||||
|
$telegram = $this->postParam("telegram");
|
||||||
|
if(empty($telegram) || Validator::i()->telegramValid($telegram))
|
||||||
|
if(strpos($telegram, "t.me/") === 0)
|
||||||
|
$user->setTelegram(empty($telegram) ? NULL : substr($telegram, 5));
|
||||||
else
|
else
|
||||||
throw $ex;
|
$user->setTelegram(empty($telegram) ? NULL : ltrim($telegram, "@"));
|
||||||
}
|
else
|
||||||
|
$this->flashFail("err", tr("invalid_telegram_name"), tr("invalid_telegram_name_comment"));
|
||||||
|
|
||||||
|
$user->setCity(empty($this->postParam("city")) ? NULL : $this->postParam("city"));
|
||||||
|
$user->setAddress(empty($this->postParam("address")) ? NULL : $this->postParam("address"));
|
||||||
|
|
||||||
$this->flash("succ", tr("changes_saved"), tr("changes_saved_comment"));
|
$website = $this->postParam("website") ?? "";
|
||||||
|
if(empty($website))
|
||||||
|
$user->setWebsite(NULL);
|
||||||
|
else
|
||||||
|
$user->setWebsite((!parse_url($website, PHP_URL_SCHEME) ? "https://" : "") . $website);
|
||||||
|
} elseif($_GET['act'] === "interests") {
|
||||||
|
$user->setInterests(empty($this->postParam("interests")) ? NULL : ovk_proc_strtr($this->postParam("interests"), 300));
|
||||||
|
$user->setFav_Music(empty($this->postParam("fav_music")) ? NULL : ovk_proc_strtr($this->postParam("fav_music"), 300));
|
||||||
|
$user->setFav_Films(empty($this->postParam("fav_films")) ? NULL : ovk_proc_strtr($this->postParam("fav_films"), 300));
|
||||||
|
$user->setFav_Shows(empty($this->postParam("fav_shows")) ? NULL : ovk_proc_strtr($this->postParam("fav_shows"), 300));
|
||||||
|
$user->setFav_Books(empty($this->postParam("fav_books")) ? NULL : ovk_proc_strtr($this->postParam("fav_books"), 300));
|
||||||
|
$user->setFav_Quote(empty($this->postParam("fav_quote")) ? NULL : ovk_proc_strtr($this->postParam("fav_quote"), 300));
|
||||||
|
$user->setAbout(empty($this->postParam("about")) ? NULL : ovk_proc_strtr($this->postParam("about"), 300));
|
||||||
|
} elseif($_GET['act'] === "status") {
|
||||||
|
if(mb_strlen($this->postParam("status")) > 255) {
|
||||||
|
$statusLength = (string) mb_strlen($this->postParam("status"));
|
||||||
|
$this->flashFail("err", "Ошибка", "Статус слишком длинный ($statusLength символов вместо 255 символов)");
|
||||||
|
}
|
||||||
|
|
||||||
|
$user->setStatus(empty($this->postParam("status")) ? NULL : $this->postParam("status"));
|
||||||
|
$user->save();
|
||||||
|
|
||||||
|
header("HTTP/1.1 302 Found");
|
||||||
|
header("Location: /id" . $user->getId());
|
||||||
|
exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->template->mode = in_array($this->queryParam("act"), [
|
try {
|
||||||
"main", "contacts", "interests", "avatar"
|
$user->save();
|
||||||
]) ? $this->queryParam("act")
|
} catch(\PDOException $ex) {
|
||||||
: "main";
|
if($ex->getCode() == 23000)
|
||||||
|
$this->flashFail("err", tr("error"), tr("error_shorturl"));
|
||||||
|
else
|
||||||
|
throw $ex;
|
||||||
|
}
|
||||||
|
|
||||||
$this->template->user = $user;
|
$this->flash("succ", tr("changes_saved"), tr("changes_saved_comment"));
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->template->mode = in_array($this->queryParam("act"), [
|
||||||
|
"main", "contacts", "interests", "avatar"
|
||||||
|
]) ? $this->queryParam("act")
|
||||||
|
: "main";
|
||||||
|
|
||||||
|
$this->template->user = $user;
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderVerifyPhone(): void
|
function renderVerifyPhone(): void
|
||||||
|
|
|
@ -22,6 +22,8 @@ final class VideosPresenter extends OpenVKPresenter
|
||||||
{
|
{
|
||||||
$user = $this->users->get($id);
|
$user = $this->users->get($id);
|
||||||
if(!$user) $this->notFound();
|
if(!$user) $this->notFound();
|
||||||
|
if(!$user->getPrivacyPermission('videos.read', $this->user->identity ?? NULL))
|
||||||
|
$this->flashFail("err", tr("forbidden"), tr("forbidden_comment"));
|
||||||
|
|
||||||
$this->template->user = $user;
|
$this->template->user = $user;
|
||||||
$this->template->videos = $this->videos->getByUser($user, (int) ($this->queryParam("p") ?? 1));
|
$this->template->videos = $this->videos->getByUser($user, (int) ($this->queryParam("p") ?? 1));
|
||||||
|
@ -38,6 +40,8 @@ final class VideosPresenter extends OpenVKPresenter
|
||||||
{
|
{
|
||||||
$user = $this->users->get($owner);
|
$user = $this->users->get($owner);
|
||||||
if(!$user) $this->notFound();
|
if(!$user) $this->notFound();
|
||||||
|
if(!$user->getPrivacyPermission('videos.read', $this->user->identity ?? NULL))
|
||||||
|
$this->flashFail("err", tr("forbidden"), tr("forbidden_comment"));
|
||||||
|
|
||||||
if($this->videos->getByOwnerAndVID($owner, $vId)->isDeleted()) $this->notFound();
|
if($this->videos->getByOwnerAndVID($owner, $vId)->isDeleted()) $this->notFound();
|
||||||
|
|
||||||
|
|
|
@ -197,7 +197,7 @@ final class WallPresenter extends OpenVKPresenter
|
||||||
}
|
}
|
||||||
|
|
||||||
$flags = 0;
|
$flags = 0;
|
||||||
if($this->postParam("as_group") === "on")
|
if($this->postParam("as_group") === "on" && $wallOwner instanceof Club && $wallOwner->canBeModifiedBy($this->user->identity))
|
||||||
$flags |= 0b10000000;
|
$flags |= 0b10000000;
|
||||||
if($this->postParam("force_sign") === "on")
|
if($this->postParam("force_sign") === "on")
|
||||||
$flags |= 0b01000000;
|
$flags |= 0b01000000;
|
||||||
|
|
|
@ -1,22 +1,20 @@
|
||||||
{extends "@layout.xml"}
|
{extends "@layout.xml"}
|
||||||
{block title}Вам бан{/block}
|
{block title}{_"banned_title"}{/block}
|
||||||
|
|
||||||
{block header}
|
{block header}
|
||||||
Вы были верискокнуты
|
{_"banned_header"}
|
||||||
{/block}
|
{/block}
|
||||||
|
|
||||||
{block content}
|
{block content}
|
||||||
<center>
|
<center>
|
||||||
<img src="/assets/packages/static/openvk/img/oof.apng" alt="Пользователь заблокирован." style="width: 20%;" />
|
<img src="/assets/packages/static/openvk/img/oof.apng" alt="{_'banned_alt'}" style="width: 20%;" />
|
||||||
</center>
|
</center>
|
||||||
<p>
|
<p>
|
||||||
Извините, <b>{$thisUser->getCanonicalName()}</b>, но вы были верискокнуты.<br/>
|
{tr("banned_1", htmlentities($thisUser->getCanonicalName()))|noescape}<br/>
|
||||||
А причина этому проста: <b>{$thisUser->getBanReason()}</b>. К сожалению, на этот раз
|
{tr("banned_2", htmlentities($thisUser->getBanReason()))|noescape}
|
||||||
нам пришлось заблокировать вас навсегда.
|
|
||||||
</p>
|
</p>
|
||||||
<hr/>
|
<hr/>
|
||||||
<p>
|
<p>
|
||||||
Вы всё ещё можете <a href="/support?act=new">написать в службу поддержки</a>, если считаете что произошла ошибка
|
{tr("banned_3", urlencode($csrfToken))|noescape}
|
||||||
или <a href="/logout">выйти</a>.
|
|
||||||
</p>
|
</p>
|
||||||
{/block}
|
{/block}
|
||||||
|
|
|
@ -206,8 +206,8 @@
|
||||||
style="max-width: 100%; margin-top: 50px;" />
|
style="max-width: 100%; margin-top: 50px;" />
|
||||||
</a>
|
</a>
|
||||||
{else}
|
{else}
|
||||||
<a href="/support" class="link">Поддержка</a>
|
<a href="/support" class="link">{_"menu_support"}</a>
|
||||||
<a href="/logout" class="link">Выйти</a>
|
<a href="/logout?hash={urlencode($csrfToken)}" class="link">{_"menu_logout"}</a>
|
||||||
{/if}
|
{/if}
|
||||||
{else}
|
{else}
|
||||||
<form id="fastLogin" action="/login" method="POST" enctype="multipart/form-data">
|
<form id="fastLogin" action="/login" method="POST" enctype="multipart/form-data">
|
||||||
|
|
|
@ -69,7 +69,7 @@
|
||||||
<input type="file" name="ava" accept="image/*" />
|
<input type="file" name="ava" accept="image/*" />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td width="120" valign="top">
|
<td width="120" valign="top">
|
||||||
<span class="nobold">{_wall}: </span>
|
<span class="nobold">{_wall}: </span>
|
||||||
</td>
|
</td>
|
||||||
|
@ -77,6 +77,14 @@
|
||||||
<input type="checkbox" name="wall" value="1" {if $club->canPost()}checked{/if}/> {_group_allow_post_for_everyone}
|
<input type="checkbox" name="wall" value="1" {if $club->canPost()}checked{/if}/> {_group_allow_post_for_everyone}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td width="120" valign="top">
|
||||||
|
<span class="nobold">{_discussions}: </span>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<input type="checkbox" name="everyone_can_create_topics" value="1" n:attr="checked => $club->isEveryoneCanCreateTopics()" /> {_everyone_can_create_topics}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td width="120" valign="top">
|
<td width="120" valign="top">
|
||||||
<span class="nobold">{_group_administrators_list}: </span>
|
<span class="nobold">{_group_administrators_list}: </span>
|
||||||
|
|
|
@ -197,12 +197,31 @@
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<b><a href="/album{$album->getPrettyId()}">{$album->getName()}</a></b><br>
|
<b><a href="/album{$album->getPrettyId()}">{$album->getName()}</a></b><br>
|
||||||
<span class="nobold">Обновлён {$album->getEditTime() ?? $album->getCreationTime()}</span>
|
<span class="nobold">{tr("updated_at", $album->getEditTime() ?? $album->getCreationTime())}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div n:if="$topicsCount > 0 || $club->isEveryoneCanCreateTopics() || $club->canBeModifiedBy($thisUser)">
|
||||||
|
<div class="content_title_expanded" onclick="hidePanel(this, {$topicsCount});">
|
||||||
|
{_discussions}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div class="content_subtitle">
|
||||||
|
{tr("topics", $topicsCount)}
|
||||||
|
<div style="float: right;">
|
||||||
|
<a href="/board{$club->getId()}">{_"all_title"}</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div n:foreach="$topics as $topic" class="topic-list-item">
|
||||||
|
<b><a href="/topic{$topic->getPrettyId()}">{$topic->getTitle()}</a></b><br>
|
||||||
|
<span class="nobold">{tr("updated_at", $topic->getUpdateTime())}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/block}
|
{/block}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{extends "../@layout.xml"}
|
{extends "../@layout.xml"}
|
||||||
{block title}{_my_messages}{/block}
|
{block title}{_my_messages}{/block}
|
||||||
|
|
||||||
{block header}{/block}
|
{block header}{_my_messages}{/block}
|
||||||
|
|
||||||
{block content}
|
{block content}
|
||||||
<div class="tabs">
|
<div class="tabs">
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
{/block}
|
{/block}
|
||||||
|
|
||||||
{block header}
|
{block header}
|
||||||
OpenVK »
|
{=OPENVK_ROOT_CONF["openvk"]["appearance"]["name"]} »
|
||||||
{if $type === "users"}
|
{if $type === "users"}
|
||||||
{tr("search_for_people")}
|
{tr("search_for_people")}
|
||||||
{else}
|
{else}
|
||||||
|
@ -17,20 +17,31 @@
|
||||||
{/if}
|
{/if}
|
||||||
{/block}
|
{/block}
|
||||||
|
|
||||||
|
{* BEGIN ELEMENTS DESCRIPTION *}
|
||||||
|
|
||||||
{block tabs}
|
{block tabs}
|
||||||
<form style="margin-left: 12px;">
|
<div {if $type === "users"}id="activetabs"{/if} class="tab">
|
||||||
<input name="type" type="hidden" value="{$_GET['type'] ?? 'users'}" />
|
<a {if $type === "users"}id="act_tab_a"{/if} href="/search?type=users">
|
||||||
<input name="query" type="text" placeholder="{_"header_search"}" value="{$_GET['query'] ?? ''}" style="width: 90%" />
|
{_users}
|
||||||
<input type="submit" class="button" value="{_"search_button"}" style="width: 9%" />
|
</a>
|
||||||
|
</div>
|
||||||
|
<div {if $type === "groups"}id="activetabs"{/if} class="tab">
|
||||||
|
<a {if $type === "groups"}id="act_tab_a"{/if} href="/search?type=groups">
|
||||||
|
{_groups}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<form class="header_search_inputbt">
|
||||||
|
<input name="type" type="hidden" value="{$type ?? 'users'}" />
|
||||||
|
<input name="query" class="header_search_input" placeholder="{_search_placeholder}" value="{$_GET['query'] ?? ''}" />
|
||||||
|
<button class="button_search">{_search_button}</button>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<p style="margin-left: 15px;">
|
<p style="margin-left: 15px; margin-top: 0;">
|
||||||
<b>{tr("results", $count)}</b>
|
<b>{tr("results", $count)}</b>
|
||||||
</p>
|
</p>
|
||||||
{/block}
|
{/block}
|
||||||
|
|
||||||
{* BEGIN ELEMENTS DESCRIPTION *}
|
|
||||||
|
|
||||||
{block link|strip|stripHtml}
|
{block link|strip|stripHtml}
|
||||||
{$x->getURL()}
|
{$x->getURL()}
|
||||||
{/block}
|
{/block}
|
||||||
|
|
|
@ -109,6 +109,18 @@
|
||||||
<a href="/support/comment/{$comment->getId()}/delete">{_delete}</a>
|
<a href="/support/comment/{$comment->getId()}/delete">{_delete}</a>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
|
{if $comment->getUType() === 1}
|
||||||
|
<div class="post-menu">
|
||||||
|
<strong>
|
||||||
|
{if $comment->isLikedByUser()}
|
||||||
|
{_support_good_answer_agent}
|
||||||
|
{else}
|
||||||
|
{_support_bad_answer_agent}
|
||||||
|
{/if}
|
||||||
|
</strong>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
|
@ -6,6 +6,28 @@
|
||||||
{/block}
|
{/block}
|
||||||
|
|
||||||
{block content}
|
{block content}
|
||||||
|
<script>
|
||||||
|
function markAnswer(id, mark) {
|
||||||
|
let url = "/support/comment/" + id + "/rate/" + mark + "?hash=" + {urlencode($csrfToken)};
|
||||||
|
$.ajax(url, {
|
||||||
|
error: errorHandler,
|
||||||
|
success: success(id, mark)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function success(id, mark) {
|
||||||
|
if(mark == 1)
|
||||||
|
document.getElementById("markText-" + id).innerHTML = {_support_good_answer_user};
|
||||||
|
else
|
||||||
|
document.getElementById("markText-" + id).innerHTML = {_support_bad_answer_user};
|
||||||
|
|
||||||
|
document.getElementById("markLinks-" + id).remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
function errorHandler(id, mark) {
|
||||||
|
document.getElementById("markText-" + id).innerHTML = {_error};
|
||||||
|
}
|
||||||
|
</script>
|
||||||
{if $ticket->isDeleted() == 0 }
|
{if $ticket->isDeleted() == 0 }
|
||||||
<div class="post-author">
|
<div class="post-author">
|
||||||
<a href="#" style="font-size:13px;">
|
<a href="#" style="font-size:13px;">
|
||||||
|
@ -90,11 +112,34 @@
|
||||||
{$comment->getText()|noescape}
|
{$comment->getText()|noescape}
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{if $comment->getUType() === 0}
|
{if $comment->getUType() === 0}
|
||||||
<div class="post-menu">
|
<div class="post-menu">
|
||||||
<a href="/support/comment/{$comment->getId()}/delete">{_delete}</a>
|
<a href="/support/comment/{$comment->getId()}/delete">{_delete}</a>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/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>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
61
Web/Presenters/templates/Topics/Board.xml
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
{extends "../@listView.xml"}
|
||||||
|
{var iterator = iterator_to_array($topics)}
|
||||||
|
{var page = $paginatorConf->page}
|
||||||
|
|
||||||
|
{block title}{_discussions} {$club->getCanonicalName()}{/block}
|
||||||
|
|
||||||
|
{block header}
|
||||||
|
<a href="{$club->getURL()}">{$club->getCanonicalName()}</a> » {_discussions}
|
||||||
|
|
||||||
|
<div n:if="$club->isEveryoneCanCreateTopics() || $club->canBeModifiedBy($thisUser)" style="float: right;">
|
||||||
|
<a href="/board{$club->getId()}/create">{_create_topic}</a>
|
||||||
|
</div>
|
||||||
|
{/block}
|
||||||
|
|
||||||
|
{block tabs}
|
||||||
|
<form style="margin-left: 12px;">
|
||||||
|
<input name="query" class="header_search_input" placeholder="{_"header_search"}" value="{$_GET['query'] ?? ''}" style="width: 90%" />
|
||||||
|
<input type="submit" class="button" value="{_"search_button"}" style="width: 7%" />
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<p style="margin-left: 15px;">
|
||||||
|
<b>{tr("results", $count)}</b>
|
||||||
|
</p>
|
||||||
|
{/block}
|
||||||
|
|
||||||
|
{block actions}
|
||||||
|
|
||||||
|
{/block}
|
||||||
|
|
||||||
|
{* BEGIN ELEMENTS DESCRIPTION *}
|
||||||
|
|
||||||
|
{block link|strip|stripHtml}
|
||||||
|
/topic{$x->getPrettyId()}
|
||||||
|
{/block}
|
||||||
|
|
||||||
|
{block preview}
|
||||||
|
|
||||||
|
{/block}
|
||||||
|
|
||||||
|
{block name}
|
||||||
|
{$x->getTitle()}
|
||||||
|
<div n:if="$x->isPinned()" class="pinned-mark"></div>
|
||||||
|
{/block}
|
||||||
|
|
||||||
|
{block description}
|
||||||
|
<div style="float: left;">
|
||||||
|
{tr("messages", $x->getCommentsCount())}
|
||||||
|
</div>
|
||||||
|
{var lastComment = $x->getLastComment()}
|
||||||
|
<div n:if="$lastComment" class="avatar-list-item" style="float: right;">
|
||||||
|
<div class="avatar">
|
||||||
|
<a href="{$lastComment->getOwner()->getURL()}">
|
||||||
|
<img class="ava" src="{$lastComment->getOwner()->getAvatarUrl()}" />
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div class="info">
|
||||||
|
<a href="{$lastComment->getOwner()->getURL()}" class="title">{$lastComment->getOwner()->getCanonicalName()}</a>
|
||||||
|
<div class="subtitle">{_replied} {$lastComment->getPublicationTime()}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/block}
|
96
Web/Presenters/templates/Topics/Create.xml
Normal file
|
@ -0,0 +1,96 @@
|
||||||
|
{extends "../@layout.xml"}
|
||||||
|
{block title}{_new_topic}{/block}
|
||||||
|
|
||||||
|
{block header}
|
||||||
|
<a href="{$club->getURL()}">{$club->getCanonicalName()}</a>
|
||||||
|
»
|
||||||
|
<a href="/board{$club->getId()}">{_discussions}</a>
|
||||||
|
»
|
||||||
|
{_new_topic}
|
||||||
|
{/block}
|
||||||
|
|
||||||
|
{block content}
|
||||||
|
<form method="POST" enctype="multipart/form-data">
|
||||||
|
<table cellspacing="7" cellpadding="0" width="80%" border="0" align="center">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td width="120" valign="top">
|
||||||
|
<span class="nobold">{_title}</span>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<input type="text" name="title" style="width: 100%;" />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td width="120" valign="top">
|
||||||
|
<span class="nobold">{_text}</span>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<textarea id="wall-post-input1" name="text" style="width: 100%; resize: none;"></textarea>
|
||||||
|
<div n:if="$club->canBeModifiedBy($thisUser)" class="post-opts">
|
||||||
|
<label>
|
||||||
|
<input type="checkbox" name="as_group" onchange="onWallAsGroupClick(this)" /> {_post_as_group}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div id="post-buttons1">
|
||||||
|
<div class="post-upload">
|
||||||
|
{_attachment}: <span>(unknown)</span>
|
||||||
|
</div>
|
||||||
|
<input type="file" class="postFileSel" id="postFilePic" name="_pic_attachment" accept="image/*" style="display: none;" />
|
||||||
|
<input type="file" class="postFileSel" id="postFileVid" name="_vid_attachment" accept="video/*" style="display: none;" />
|
||||||
|
<br/>
|
||||||
|
<div style="float: right; display: flex; flex-direction: column;">
|
||||||
|
<a href="javascript:void(u('#post-buttons1 #wallAttachmentMenu').toggleClass('hidden'));">
|
||||||
|
{_attach}
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<div id="wallAttachmentMenu" class="hidden">
|
||||||
|
<a href="javascript:void(document.querySelector('#post-buttons1 input[name=_pic_attachment]').click());">
|
||||||
|
<img src="/assets/packages/static/openvk/img/oxygen-icons/16x16/mimetypes/application-x-egon.png" />
|
||||||
|
{_attach_photo}
|
||||||
|
</a>
|
||||||
|
<a href="javascript:void(document.querySelector('#post-buttons1 input[name=_vid_attachment]').click());">
|
||||||
|
<img src="/assets/packages/static/openvk/img/oxygen-icons/16x16/mimetypes/application-vnd.rn-realmedia.png" />
|
||||||
|
{_attach_video}
|
||||||
|
</a>
|
||||||
|
<a n:if="$graffiti ?? false" href="javascript:initGraffiti(1);">
|
||||||
|
<img src="/assets/packages/static/openvk/img/oxygen-icons/16x16/actions/draw-brush.png" />
|
||||||
|
{_draw_graffiti}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<input type="hidden" name="hash" value="{$csrfToken}" />
|
||||||
|
<input type="submit" value="{_create_topic}" class="button" />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<input type="hidden" name="hash" value="{$csrfToken}" />
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
$(document).ready(() => {
|
||||||
|
u("#post-buttons1 .postFileSel").on("change", function() {
|
||||||
|
handleUpload.bind(this, 1)();
|
||||||
|
});
|
||||||
|
|
||||||
|
setupWallPostInputHandlers(1);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{if $graffiti}
|
||||||
|
{script "js/node_modules/react/dist/react-with-addons.min.js"}
|
||||||
|
{script "js/node_modules/react-dom/dist/react-dom.min.js"}
|
||||||
|
{script "js/vnd_literallycanvas.js"}
|
||||||
|
{css "js/node_modules/literallycanvas/lib/css/literallycanvas.css"}
|
||||||
|
{/if}
|
||||||
|
{/block}
|
55
Web/Presenters/templates/Topics/Edit.xml
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
{extends "../@layout.xml"}
|
||||||
|
{block title}{_edit_topic} "{$topic->getTitle()}"{/block}
|
||||||
|
|
||||||
|
{block header}
|
||||||
|
<a href="{$club->getURL()}">{$club->getCanonicalName()}</a>
|
||||||
|
»
|
||||||
|
<a href="/board{$club->getId()}">{_discussions}</a>
|
||||||
|
»
|
||||||
|
{_edit_topic}
|
||||||
|
{/block}
|
||||||
|
|
||||||
|
{block content}
|
||||||
|
<div class="container_gray">
|
||||||
|
<b>{$topic->getTitle()}</b>
|
||||||
|
<br />
|
||||||
|
<a href="{$topic->getOwner()->getURL()}">{$topic->getOwner()->getCanonicalName()}</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<form method="POST" enctype="multipart/form-data" style="margin-top: 20px;">
|
||||||
|
<table cellspacing="7" cellpadding="0" width="80%" border="0" align="center">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td width="120" valign="top">
|
||||||
|
<span class="nobold">{_title}</span>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<input type="text" name="title" style="width: 100%;" value="{$topic->getTitle()}" />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td width="120" valign="top">
|
||||||
|
<span class="nobold">{_topic_settings}</span>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{if $topic->getClub()->canBeModifiedBy($thisUser)}
|
||||||
|
<input type="checkbox" name="pin" n:attr="checked => $topic->isPinned()" /> {_pin_topic}<br />
|
||||||
|
{/if}
|
||||||
|
<input type="checkbox" name="close" n:attr="checked => $topic->isClosed()" /> {_close_topic}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<a class="button" href="/topic{$topic->getPrettyId()}/delete?hash={urlencode($csrfToken)}">{_delete_topic}</a>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<input type="hidden" name="hash" value="{$csrfToken}" />
|
||||||
|
<input type="submit" value="{_save}" class="button" />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<input type="hidden" name="hash" value="{$csrfToken}" />
|
||||||
|
</form>
|
||||||
|
{/block}
|
29
Web/Presenters/templates/Topics/Topic.xml
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
{extends "../@layout.xml"}
|
||||||
|
{block title}{_view_topic} "{$topic->getTitle()}"{/block}
|
||||||
|
|
||||||
|
{block header}
|
||||||
|
<a href="{$club->getURL()}">{$club->getCanonicalName()}</a>
|
||||||
|
»
|
||||||
|
<a href="/board{$club->getId()}">{_discussions}</a>
|
||||||
|
»
|
||||||
|
{_view_topic}
|
||||||
|
|
||||||
|
<div style="float: right;" n:if="$topic->canBeModifiedBy($thisUser)">
|
||||||
|
<a href="/topic{$club->getId()}_{$topic->getVirtualId()}/edit">{_edit_topic_action}</a>
|
||||||
|
</div>
|
||||||
|
{/block}
|
||||||
|
|
||||||
|
{block content}
|
||||||
|
<div class="container_gray">
|
||||||
|
<b>{$topic->getTitle()}</b>
|
||||||
|
<br />
|
||||||
|
<a href="{$topic->getOwner()->getURL()}">{$topic->getOwner()->getCanonicalName()}</a>
|
||||||
|
<div class="nobold" style="float: right;">
|
||||||
|
{_created} {$topic->getPublicationTime()}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div style="margin-top: 20px;">
|
||||||
|
<h4>{tr("topic_messages_count", $count)}</h4>
|
||||||
|
{include "../components/comments.xml", comments => $comments, count => $count, page => $page, model => "topics", club => $club, readOnly => $topic->isClosed(), showTitle => false, parent => $topic}
|
||||||
|
</div>
|
||||||
|
{/block}
|
|
@ -135,7 +135,7 @@
|
||||||
<span class="nobold">{_"birth_date"}: </span>
|
<span class="nobold">{_"birth_date"}: </span>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<input max={date('Y-m-d')} name="birthday" value={gmdate("Y-m-d", $user->getBirthday())} type="date"/>
|
<input max={date('Y-m-d')} name="birthday" value={$user->getBirthday()->format('%Y-%m-%d')} type="date"/>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
{block title}{$user->getCanonicalName()}{/block}
|
{block title}{$user->getCanonicalName()}{/block}
|
||||||
|
|
||||||
{block headIncludes}
|
{block headIncludes}
|
||||||
|
{if $user->getPrivacyPermission('page.read', $thisUser ?? NULL)}
|
||||||
<!-- openGraph -->
|
<!-- openGraph -->
|
||||||
<meta property="og:title" content="{$user->getCanonicalName()}" />
|
<meta property="og:title" content="{$user->getCanonicalName()}" />
|
||||||
<meta property="og:url" content="http://{$_SERVER['HTTP_HOST']}{$user->getURL()}" />
|
<meta property="og:url" content="http://{$_SERVER['HTTP_HOST']}{$user->getURL()}" />
|
||||||
|
@ -22,6 +23,9 @@
|
||||||
"url": {('http://') . $_SERVER['HTTP_HOST'] . $user->getURL()}
|
"url": {('http://') . $_SERVER['HTTP_HOST'] . $user->getURL()}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
{else}
|
||||||
|
<meta name="robots" content="noindex, noarchive">
|
||||||
|
{/if}
|
||||||
{/block}
|
{/block}
|
||||||
|
|
||||||
{block header}
|
{block header}
|
||||||
|
@ -398,10 +402,10 @@
|
||||||
<td class="label"><span class="nobold">{_"politViews"}:</span></td>
|
<td class="label"><span class="nobold">{_"politViews"}:</span></td>
|
||||||
<td class="data">{var $pviews = $user->getPoliticalViews()}{_"politViews_$pviews"}</td>
|
<td class="data">{var $pviews = $user->getPoliticalViews()}{_"politViews_$pviews"}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{if $user->getBirthday() > 0}
|
{if $user->getBirthday()->timestamp() > 0}
|
||||||
<tr>
|
<tr>
|
||||||
<td class="label"><span class="nobold">{_"birth_date"}:</span></td>
|
<td class="label"><span class="nobold">{_"birth_date"}:</span></td>
|
||||||
<td class="data">{date('d F Y',$user->getBirthday())},
|
<td class="data">{$user->getBirthday()->format('%e %B %Y')},
|
||||||
{tr("years", $user->getAge())}</td>
|
{tr("years", $user->getAge())}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<center>
|
<center>
|
||||||
<img src="/assets/packages/static/openvk/img/oof.apng" alt="Пользователь заблокирован." style="width: 20%;" />
|
<img src="/assets/packages/static/openvk/img/oof.apng" alt="Пользователь заблокирован." style="width: 20%;" />
|
||||||
<p>
|
<p>
|
||||||
К сожалению, нам пришлось заблокировать страницу пользователя <b>{$user->getFirstName()}</b>.<br/>
|
{tr("user_banned", htmlentities($user->getFirstName()))|noescape}<br/>
|
||||||
Комментарий модератора: <b>{$user->getBanReason()}</b>.
|
{_"user_banned_comment"} <b>{$user->getBanReason()}</b>.
|
||||||
</p>
|
</p>
|
||||||
</center>
|
</center>
|
||||||
|
|
|
@ -29,9 +29,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div n:if="isset($thisUser) &&! ($compact ?? false)" class="post-menu">
|
<div n:if="isset($thisUser) &&! ($compact ?? false)" class="post-menu">
|
||||||
<a href="#_comment{$comment->getId()}" class="date">{$comment->getPublicationTime()}</a> |
|
<a href="#_comment{$comment->getId()}" class="date">{$comment->getPublicationTime()}</a> |
|
||||||
{var canDelete = $comment->getOwner()->getId() == $thisUser->getId()}
|
{if $comment->canBeDeletedBy($thisUser)}
|
||||||
{var canDelete = $canDelete || $comment->getTarget()->getOwner()->getId() == $thisUser->getId()}
|
|
||||||
{if $canDelete}
|
|
||||||
<a href="/comment{$comment->getId()}/delete">{_"delete"}</a> |
|
<a href="/comment{$comment->getId()}/delete">{_"delete"}</a> |
|
||||||
{/if}
|
{/if}
|
||||||
<a class="comment-reply">Ответить</a>
|
<a class="comment-reply">Ответить</a>
|
||||||
|
|
|
@ -1,16 +1,20 @@
|
||||||
<h4>{_"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.pl/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())) : NULL}
|
{var club = $parent instanceof \openvk\Web\Models\Entities\Post && $parent->getTargetWall() < 0 ? (new openvk\Web\Models\Repositories\Clubs)->get(abs($parent->getTargetWall())) : $club}
|
||||||
{include "textArea.xml", route => $commentsURL, postOpts => false, graffiti => (bool) ovkGetQuirk("comments.allow-graffiti"), club => $club}
|
{if !$readOnly}
|
||||||
|
{include "textArea.xml", route => $commentsURL, postOpts => false, graffiti => (bool) ovkGetQuirk("comments.allow-graffiti"), club => $club}
|
||||||
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{if sizeof($comments) > 0}
|
{if sizeof($comments) > 0}
|
||||||
{foreach $comments as $comment}
|
{foreach $comments as $comment}
|
||||||
{include "comment.xml", comment => $comment}
|
{include "comment.xml", comment => $comment}
|
||||||
{/foreach}
|
{/foreach}
|
||||||
{include "paginator.xml", conf => (object) ["page" => $page, "count" => $count, "amount" => sizeof($comments), "perPage" => 10]}
|
<div style="margin-top: 11px;">
|
||||||
|
{include "paginator.xml", conf => (object) ["page" => $page, "count" => $count, "amount" => sizeof($comments), "perPage" => 10]}
|
||||||
|
</div>
|
||||||
{else}
|
{else}
|
||||||
<!-- {if $model === "photos"}
|
<!-- {if $model === "photos"}
|
||||||
<p>Будьте первым, кто оставит комментарий к этой фотографии</p>
|
<p>Будьте первым, кто оставит комментарий к этой фотографии</p>
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
{extends "@default.xml"}
|
||||||
|
{var post = $notification->getModel(0)}
|
||||||
|
|
||||||
|
{block under}
|
||||||
|
{_nt_yours_adjective} <a href="/topic{$post->getPrettyId()}">{_nt_topic_instrumental}</a>
|
||||||
|
{/block}
|
|
@ -8,7 +8,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div id="post-buttons{$textAreaId}" style="display: none;">
|
<div id="post-buttons{$textAreaId}" style="display: none;">
|
||||||
<div class="post-upload">
|
<div class="post-upload">
|
||||||
Вложение: <span>(unknown)</span>
|
{_attachment}: <span>(unknown)</span>
|
||||||
</div>
|
</div>
|
||||||
<div n:if="$postOpts ?? true" class="post-opts">
|
<div n:if="$postOpts ?? true" class="post-opts">
|
||||||
{var anonEnabled = OPENVK_ROOT_CONF['openvk']['preferences']['wall']['anonymousPosting']['enable']}
|
{var anonEnabled = OPENVK_ROOT_CONF['openvk']['preferences']['wall']['anonymousPosting']['enable']}
|
||||||
|
@ -35,7 +35,7 @@
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<label n:if="$anonEnabled" id="octoberAnonOpt">
|
<label n:if="$anonEnabled" id="octoberAnonOpt">
|
||||||
<input type="checkbox" name="anon" /> Анонимно
|
<input type="checkbox" name="anon" /> {_"as_anonymous"}
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<label>
|
<label>
|
||||||
|
@ -55,7 +55,7 @@
|
||||||
<input type="submit" value="{_'write'}" class="button" />
|
<input type="submit" value="{_'write'}" class="button" />
|
||||||
<div style="float: right; display: flex; flex-direction: column;">
|
<div style="float: right; display: flex; flex-direction: column;">
|
||||||
<a href="javascript:void(u('#post-buttons{$textAreaId} #wallAttachmentMenu').toggleClass('hidden'));">
|
<a href="javascript:void(u('#post-buttons{$textAreaId} #wallAttachmentMenu').toggleClass('hidden'));">
|
||||||
Прикрепить
|
{_attach}
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<div id="wallAttachmentMenu" class="hidden">
|
<div id="wallAttachmentMenu" class="hidden">
|
||||||
|
@ -65,11 +65,11 @@
|
||||||
</a>
|
</a>
|
||||||
<a href="javascript:void(document.querySelector('#post-buttons{$textAreaId} input[name=_vid_attachment]').click());">
|
<a href="javascript:void(document.querySelector('#post-buttons{$textAreaId} input[name=_vid_attachment]').click());">
|
||||||
<img src="/assets/packages/static/openvk/img/oxygen-icons/16x16/mimetypes/application-vnd.rn-realmedia.png" />
|
<img src="/assets/packages/static/openvk/img/oxygen-icons/16x16/mimetypes/application-vnd.rn-realmedia.png" />
|
||||||
Прикрепить видео
|
{_attach_video}
|
||||||
</a>
|
</a>
|
||||||
<a n:if="$graffiti ?? false" href="javascript:initGraffiti({$textAreaId});">
|
<a n:if="$graffiti ?? false" href="javascript:initGraffiti({$textAreaId});">
|
||||||
<img src="/assets/packages/static/openvk/img/oxygen-icons/16x16/actions/draw-brush.png" />
|
<img src="/assets/packages/static/openvk/img/oxygen-icons/16x16/actions/draw-brush.png" />
|
||||||
Нарисовать граффити
|
{_draw_graffiti}
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -19,6 +19,7 @@ services:
|
||||||
- openvk\Web\Presenters\AdminPresenter
|
- openvk\Web\Presenters\AdminPresenter
|
||||||
- openvk\Web\Presenters\GiftsPresenter
|
- openvk\Web\Presenters\GiftsPresenter
|
||||||
- openvk\Web\Presenters\MessengerPresenter
|
- openvk\Web\Presenters\MessengerPresenter
|
||||||
|
- openvk\Web\Presenters\TopicsPresenter
|
||||||
- openvk\Web\Presenters\ThemepacksPresenter
|
- openvk\Web\Presenters\ThemepacksPresenter
|
||||||
- openvk\Web\Presenters\VKAPIPresenter
|
- openvk\Web\Presenters\VKAPIPresenter
|
||||||
- openvk\Web\Models\Repositories\Users
|
- openvk\Web\Models\Repositories\Users
|
||||||
|
@ -36,4 +37,5 @@ services:
|
||||||
- openvk\Web\Models\Repositories\IPs
|
- openvk\Web\Models\Repositories\IPs
|
||||||
- openvk\Web\Models\Repositories\Vouchers
|
- openvk\Web\Models\Repositories\Vouchers
|
||||||
- openvk\Web\Models\Repositories\Gifts
|
- openvk\Web\Models\Repositories\Gifts
|
||||||
|
- openvk\Web\Models\Repositories\Topics
|
||||||
- openvk\Web\Models\Repositories\ContentSearchRepository
|
- openvk\Web\Models\Repositories\ContentSearchRepository
|
||||||
|
|
|
@ -17,6 +17,8 @@ routes:
|
||||||
handler: "Support->AnswerTicket"
|
handler: "Support->AnswerTicket"
|
||||||
- url: "/support/view/{num}"
|
- url: "/support/view/{num}"
|
||||||
handler: "Support->view"
|
handler: "Support->view"
|
||||||
|
- url: "/support/comment/{num}/rate/{num}"
|
||||||
|
handler: "Support->rateAnswer"
|
||||||
- url: "/al_comments.pl/create/support/{num}"
|
- url: "/al_comments.pl/create/support/{num}"
|
||||||
handler: "Support->makeComment"
|
handler: "Support->makeComment"
|
||||||
- url: "/al_comments.pl/create/support/reply/{num}"
|
- url: "/al_comments.pl/create/support/reply/{num}"
|
||||||
|
@ -165,6 +167,16 @@ routes:
|
||||||
handler: "User->pinClub"
|
handler: "User->pinClub"
|
||||||
- url: "/groups_create"
|
- url: "/groups_create"
|
||||||
handler: "Group->create"
|
handler: "Group->create"
|
||||||
|
- url: "/board{num}"
|
||||||
|
handler: "Topics->board"
|
||||||
|
- url: "/board{num}/create"
|
||||||
|
handler: "Topics->create"
|
||||||
|
- url: "/topic{num}_{num}"
|
||||||
|
handler: "Topics->topic"
|
||||||
|
- url: "/topic{num}_{num}/edit"
|
||||||
|
handler: "Topics->edit"
|
||||||
|
- url: "/topic{num}_{num}/delete"
|
||||||
|
handler: "Topics->delete"
|
||||||
- url: "/audios{num}"
|
- url: "/audios{num}"
|
||||||
handler: "Audios->app"
|
handler: "Audios->app"
|
||||||
- url: "/audios{num}.json"
|
- url: "/audios{num}.json"
|
||||||
|
|
|
@ -19,7 +19,7 @@ span {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
.nobold {
|
.nobold, nobold {
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
color: gray;
|
color: gray;
|
||||||
}
|
}
|
||||||
|
@ -1598,3 +1598,92 @@ body.scrolled .toTop:hover {
|
||||||
margin: 5px;
|
margin: 5px;
|
||||||
border: 1px solid #C0CAD5;
|
border: 1px solid #C0CAD5;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.header_search {
|
||||||
|
background: #f7f7f7;
|
||||||
|
width: 607px;
|
||||||
|
padding: 10px;
|
||||||
|
border-bottom: 1px solid #e1e1e1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header_search_inputbt {
|
||||||
|
padding: 10px;
|
||||||
|
border-top: 1px solid #ebebeb;
|
||||||
|
display: flex;
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header_search_input {
|
||||||
|
border: 1px solid #C0CAD5;
|
||||||
|
padding: 3px;
|
||||||
|
padding-left: 19px;
|
||||||
|
font-size: 11px;
|
||||||
|
font-family: tahoma, verdana, arial, sans-serif;
|
||||||
|
width: 549px;
|
||||||
|
background: #fff url('/assets/packages/static/openvk/img/search_icon.png') no-repeat;
|
||||||
|
background-position-x: 4px;
|
||||||
|
background-position-y: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button_search {
|
||||||
|
border-radius: 2px;
|
||||||
|
border: #595959;
|
||||||
|
font-size: 11px;
|
||||||
|
outline: none;
|
||||||
|
white-space: nowrap;
|
||||||
|
background: #595959;
|
||||||
|
background-position: 0px -16px;
|
||||||
|
color: #fff;
|
||||||
|
padding: 4px 8px 4px;
|
||||||
|
text-shadow: 0 1px 0 #686868;
|
||||||
|
cursor: pointer;
|
||||||
|
text-decoration: none;
|
||||||
|
margin-left: 10px;
|
||||||
|
width: 7.5%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content_search {
|
||||||
|
width: 607px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content_search_list {
|
||||||
|
display: flex;
|
||||||
|
width: 100%;
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content_search_list:hover {
|
||||||
|
background: #f5f5f5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content_search_list_ava img{
|
||||||
|
width: 75px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content_search_list_ava{
|
||||||
|
width: 85px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content_search_list_name_h4 {
|
||||||
|
color: #2b587a;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content_search_list_span {
|
||||||
|
color: #7b7b7b;
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pinned-mark {
|
||||||
|
display: inline-block;
|
||||||
|
height: 16px;
|
||||||
|
width: 16px;
|
||||||
|
overflow: auto;
|
||||||
|
background: url("/assets/packages/static/openvk/img/pin.png") no-repeat 0px 0px;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
.topic-list-item {
|
||||||
|
border-bottom: #e6e6e6 solid 1px;
|
||||||
|
padding: 4px;
|
||||||
|
}
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
Subproject commit 9d4eb793307e7af10c39c9da3b46646d97ad9dc2
|
|
|
@ -0,0 +1 @@
|
||||||
|
system-run.png
|
|
@ -0,0 +1 @@
|
||||||
|
run-build.png
|
|
@ -0,0 +1 @@
|
||||||
|
appointment-new.png
|
BIN
Web/static/img/oxygen-icons/16x16/actions/acrobat.png
Normal file
After Width: | Height: | Size: 615 B |
|
@ -0,0 +1 @@
|
||||||
|
folder-new.png
|
|
@ -0,0 +1 @@
|
||||||
|
fork.png
|
1
Web/static/img/oxygen-icons/16x16/actions/actor.png
Normal file
|
@ -0,0 +1 @@
|
||||||
|
im-user.png
|
|
@ -0,0 +1 @@
|
||||||
|
flag-red.png
|
BIN
Web/static/img/oxygen-icons/16x16/actions/address-book-new.png
Normal file
After Width: | Height: | Size: 797 B |
|
@ -0,0 +1 @@
|
||||||
|
address-book-new.png
|
|
@ -0,0 +1 @@
|
||||||
|
address-book-new.png
|
|
@ -0,0 +1 @@
|
||||||
|
go-home.png
|
|
@ -0,0 +1 @@
|
||||||
|
folder-new.png
|
|
@ -0,0 +1 @@
|
||||||
|
document-import.png
|
|
@ -0,0 +1 @@
|
||||||
|
folder-new.png
|
|
@ -0,0 +1 @@
|
||||||
|
configure.png
|
|
@ -0,0 +1 @@
|
||||||
|
edit-delete.png
|
After Width: | Height: | Size: 384 B |
After Width: | Height: | Size: 441 B |
After Width: | Height: | Size: 454 B |
After Width: | Height: | Size: 456 B |
After Width: | Height: | Size: 444 B |
After Width: | Height: | Size: 457 B |
After Width: | Height: | Size: 418 B |
After Width: | Height: | Size: 445 B |
After Width: | Height: | Size: 399 B |
After Width: | Height: | Size: 452 B |
|
@ -0,0 +1 @@
|
||||||
|
align-vertical-bottom-out.png
|
After Width: | Height: | Size: 451 B |
After Width: | Height: | Size: 484 B |
After Width: | Height: | Size: 457 B |
|
@ -0,0 +1 @@
|
||||||
|
align-horizontal-top-out.png
|
BIN
Web/static/img/oxygen-icons/16x16/actions/align-vertical-top.png
Normal file
After Width: | Height: | Size: 413 B |
|
@ -0,0 +1 @@
|
||||||
|
im-invisible-user.png
|
|
@ -0,0 +1 @@
|
||||||
|
appointment-new.png
|
|
@ -0,0 +1 @@
|
||||||
|
view-media-lyrics.png
|
|
@ -0,0 +1 @@
|
||||||
|
view-statistics.png
|
|
@ -0,0 +1 @@
|
||||||
|
view-media-playlist.png
|
|
@ -0,0 +1 @@
|
||||||
|
view-refresh.png
|
|
@ -0,0 +1 @@
|
||||||
|
dialog-ok-apply.png
|
1
Web/static/img/oxygen-icons/16x16/actions/answer.png
Normal file
|
@ -0,0 +1 @@
|
||||||
|
dialog-ok-apply.png
|
BIN
Web/static/img/oxygen-icons/16x16/actions/application-exit.png
Normal file
After Width: | Height: | Size: 842 B |
|
@ -0,0 +1 @@
|
||||||
|
configure.png
|
|
@ -0,0 +1 @@
|
||||||
|
../places/folder-html.png
|
BIN
Web/static/img/oxygen-icons/16x16/actions/appointment-new.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
Web/static/img/oxygen-icons/16x16/actions/archive-extract.png
Normal file
After Width: | Height: | Size: 626 B |
After Width: | Height: | Size: 762 B |
BIN
Web/static/img/oxygen-icons/16x16/actions/archive-insert.png
Normal file
After Width: | Height: | Size: 433 B |
BIN
Web/static/img/oxygen-icons/16x16/actions/archive-remove.png
Normal file
After Width: | Height: | Size: 516 B |
BIN
Web/static/img/oxygen-icons/16x16/actions/arrow-down-double.png
Normal file
After Width: | Height: | Size: 691 B |
BIN
Web/static/img/oxygen-icons/16x16/actions/arrow-down.png
Normal file
After Width: | Height: | Size: 525 B |
BIN
Web/static/img/oxygen-icons/16x16/actions/arrow-left-double.png
Normal file
After Width: | Height: | Size: 653 B |
BIN
Web/static/img/oxygen-icons/16x16/actions/arrow-left.png
Normal file
After Width: | Height: | Size: 512 B |
BIN
Web/static/img/oxygen-icons/16x16/actions/arrow-right-double.png
Normal file
After Width: | Height: | Size: 666 B |
BIN
Web/static/img/oxygen-icons/16x16/actions/arrow-right.png
Normal file
After Width: | Height: | Size: 527 B |
BIN
Web/static/img/oxygen-icons/16x16/actions/arrow-up-double.png
Normal file
After Width: | Height: | Size: 650 B |
BIN
Web/static/img/oxygen-icons/16x16/actions/arrow-up.png
Normal file
After Width: | Height: | Size: 484 B |
1
Web/static/img/oxygen-icons/16x16/actions/atmosphere.png
Normal file
|
@ -0,0 +1 @@
|
||||||
|
../categories/applications-internet.png
|