rev.11 Add subscriptions 1

This commit is contained in:
Visman 2020-09-01 09:49:04 +07:00
parent a5bf19ed7f
commit 6ed8537bd3
17 changed files with 465 additions and 73 deletions

View file

@ -369,6 +369,24 @@ class Routing
'Feed:view',
'Feed'
);
// подписки
if (
! $user->isGuest
&& ! $user->isUnverified
) {
$r->add(
$r::GET,
'/forum/{fid:[1-9]\d*}/{type:subscribe|unsubscribe}/{token}',
'Misc:forumSubscription',
'ForumSubscription'
);
$r->add(
$r::GET,
'/topic/{tid:[1-9]\d*}/{type:subscribe|unsubscribe}/{token}',
'Misc:topicSubscription',
'TopicSubscription'
);
}
}
// админ и модератор

View file

@ -58,6 +58,17 @@ class Model extends DataModel
return ! $this->c->user->isGuest; // ????
}
/**
* Статус возможности использования подписок
*/
protected function getcanSubscription(): bool
{
return '1' == $this->c->config->o_forum_subscriptions
&& $this->id > 0
&& ! $this->c->user->isGuest
&& ! $this->c->user->isUnverified;
}
/**
* Получение массива подразделов
*
@ -195,6 +206,56 @@ class Model extends DataModel
);
}
/**
* Ссылка на подписку
*/
protected function getlinkSubscribe(): ?string
{
if ($this->id < 1) {
return null;
} else {
return $this->c->Router->link(
'ForumSubscription',
[
'fid' => $this->id,
'type' => 'subscribe',
'token' => $this->c->Csrf->create(
'ForumSubscription',
[
'fid' => $this->id,
'type' => 'subscribe',
]
),
]
);
}
}
/**
* Ссылка на отписку
*/
protected function getlinkUnsubscribe(): ?string
{
if ($this->id < 1) {
return null;
} else {
return $this->c->Router->link(
'ForumSubscription',
[
'fid' => $this->id,
'type' => 'unsubscribe',
'token' => $this->c->Csrf->create(
'ForumSubscription',
[
'fid' => $this->id,
'type' => 'unsubscribe',
]
),
]
);
}
}
/**
* Получение массива модераторов
*

View file

@ -600,4 +600,21 @@ class Update extends Admin
return null;
}
/**
* rev.10 to rev.11
*/
protected function stageNumber10(array $args): ?int
{
$coreConfig = new CoreConfig($this->c->DIR_CONFIG . '/' . self::CONFIG_FILE);
$coreConfig->add(
'shared=>subscriptions',
'\\ForkBB\\Models\\Subscription\\Model::class',
'search'
);
$coreConfig->save();
return null;
}
}

View file

@ -4,6 +4,7 @@ namespace ForkBB\Models\Pages;
use ForkBB\Models\Page;
use ForkBB\Models\Forum\Model as Forum;
use ForkBB\Models\Topic\Model as Topic;
class Misc extends Page
{
@ -33,4 +34,62 @@ class Misc extends Page
return $this->c->Redirect->url($forum->link)->message($message);
}
/**
* Подписка на форум и отписка от него
*/
public function forumSubscription(array $args): Page
{
if (! $this->c->Csrf->verify($args['token'], 'ForumSubscription', $args)) {
return $this->c->Message->message('Bad token');
}
$forum = $this->c->forums->get((int) $args['fid']);
if (! $forum instanceof Forum) {
return $this->c->Message->message('Bad request');
}
$this->c->Lang->load('misc');
if ('subscribe' === $args['type']) {
$this->c->subscriptions->subscribe($this->user, $forum);
$message = 'Subscribe redirect';
} else {
$this->c->subscriptions->unsubscribe($this->user, $forum);
$message = 'Unsubscribe redirect';
}
return $this->c->Redirect->url($forum->link)->message($message);
}
/**
* Подписка на топик и отписка от него
*/
public function topicSubscription(array $args): Page
{
if (! $this->c->Csrf->verify($args['token'], 'TopicSubscription', $args)) {
return $this->c->Message->message('Bad token');
}
$topic = $this->c->topics->load((int) $args['tid']);
if (! $topic instanceof Topic) {
return $this->c->Message->message('Bad request');
}
$this->c->Lang->load('misc');
if ('subscribe' === $args['type']) {
$this->c->subscriptions->subscribe($this->user, $topic);
$message = 'Subscribe redirect';
} else {
$this->c->subscriptions->unsubscribe($this->user, $topic);
$message = 'Unsubscribe redirect';
}
return $this->c->Redirect->url($topic->link)->message($message);
}
}

View file

@ -0,0 +1,166 @@
<?php
namespace ForkBB\Models\Subscription;
use ForkBB\Models\Model as ParentModel;
use ForkBB\Models\DataModel;
use ForkBB\Models\Forum\Model as Forum;
use ForkBB\Models\Topic\Model as Topic;
use ForkBB\Models\User\Model as User;
use InvalidArgumentException;
use PDOException;
class Model extends ParentModel
{
/**
* @var array
*/
protected $forums;
/**
* @var array
*/
protected $topics;
/**
* Проверяет список моделей на форумы/темы
* Заполняет $forums и $topics
*/
protected function check(array $models): void
{
$this->forums = [];
$this->topics = [];
if (empty($models)) {
throw new InvalidArgumentException('Expected at least one Forum or Topic');
}
foreach ($models as $model) {
if ($model instanceof Forum) {
$this->forums[$model->id] = $model->id;
} elseif ($model instanceof Topic) {
$this->topics[$model->id] = $model->id;
} else {
throw new InvalidArgumentException('Expected only Forum or Topic');
}
}
}
/**
* Подписывает юзера на форум(ы)/тему(ы)
*/
public function subscribe(User $user, DataModel ...$models): bool
{
if (
$user->isGuest
|| $user->isUnverified
) {
return false;
}
$this->check($models);
$vars = [
':uid' => $user->id,
];
if (! empty($this->forums)) {
$query = 'INSERT INTO ::forum_subscriptions (user_id, forum_id)
SELECT ?i:uid, ?i:id
FROM ::groups
WHERE NOT EXISTS (
SELECT 1
FROM ::forum_subscriptions
WHERE user_id=?i:uid AND forum_id=?i:id
)
LIMIT 1';
foreach ($this->forums as $id) {
$vars[':id'] = $id;
$this->c->DB->exec($query, $vars);
}
}
if (! empty($this->topics)) {
$query = 'INSERT INTO ::topic_subscriptions (user_id, topic_id)
SELECT ?i:uid, ?i:id
FROM ::groups
WHERE NOT EXISTS (
SELECT 1
FROM ::topic_subscriptions
WHERE user_id=?i:uid AND topic_id=?i:id
)
LIMIT 1';
foreach ($this->topics as $id) {
$vars[':id'] = $id;
$this->c->DB->exec($query, $vars);
}
}
return true;
}
/**
* Отписывает юзера/всех юзеров от форума(ов)/тем(ы)
*/
public function unsubscribe(?User $user, DataModel ...$models): bool
{
if ($user instanceof User) {
if (
$user->isGuest
|| $user->isUnverified
) {
return false;
}
$vars = [
':uid' => $user->id,
];
} else {
$vars = [];
}
$this->check($models);
if (! empty($this->forums)) {
if (isset($vars[':uid'])) {
$query = 'DELETE
FROM ::forum_subscriptions
WHERE user_id=?i:uid AND forum_id=?i:id';
} else {
$query = 'DELETE
FROM ::forum_subscriptions
WHERE forum_id=?i:id';
}
foreach ($this->forums as $id) {
$vars[':id'] = $id;
$this->c->DB->exec($query, $vars);
}
}
if (! empty($this->topics)) {
if (isset($vars[':uid'])) {
$query = 'DELETE
FROM ::topic_subscriptions
WHERE user_id=?i:uid AND topic_id=?i:id';
} else {
$query = 'DELETE
FROM ::topic_subscriptions
WHERE topic_id=?i:id';
}
foreach ($this->topics as $id) {
$vars[':id'] = $id;
$this->c->DB->exec($query, $vars);
}
}
return true;
}
}

View file

@ -77,6 +77,17 @@ class Model extends DataModel
}
}
/**
* Статус возможности использования подписок
*/
protected function getcanSubscription(): bool
{
return '1' == $this->c->config->o_topic_subscriptions
&& $this->id > 0
&& ! $this->c->user->isGuest
&& ! $this->c->user->isUnverified;
}
/**
* Ссылка на тему
*
@ -155,6 +166,48 @@ class Model extends DataModel
);
}
/**
* Ссылка на подписку
*/
protected function getlinkSubscribe(): ?string
{
return $this->c->Router->link(
'TopicSubscription',
[
'tid' => $this->id,
'type' => 'subscribe',
'token' => $this->c->Csrf->create(
'TopicSubscription',
[
'tid' => $this->id,
'type' => 'subscribe',
]
),
]
);
}
/**
* Ссылка на отписку
*/
protected function getlinkUnsubscribe(): ?string
{
return $this->c->Router->link(
'TopicSubscription',
[
'tid' => $this->id,
'type' => 'unsubscribe',
'token' => $this->c->Csrf->create(
'TopicSubscription',
[
'tid' => $this->id,
'type' => 'unsubscribe',
]
),
]
);
}
/**
* Статус наличия новых сообщений в теме
*

View file

@ -42,7 +42,7 @@ if (
}
$c->PUBLIC_URL = $c->BASE_URL . $forkPublicPrefix;
$c->FORK_REVISION = 10;
$c->FORK_REVISION = 11;
$c->START = $forkStart;
$c->DIR_APP = __DIR__;
$c->DIR_PUBLIC = $forkPublic;

View file

@ -89,24 +89,25 @@ return [
'Func' => \ForkBB\Core\Func::class,
'NormEmail' => \MioVisman\NormEmail\NormEmail::class,
'config' => '@ConfigModel:init',
'bans' => '@BanListModel:init',
'censorship' => '@CensorshipModel:init',
'stats' => '@StatsModel:init',
'admins' => '@AdminListModel:init',
'smilies' => '@SmileyListModel:init',
'dbMap' => '@DBMapModel:init',
'stopwords' => '@StopwordsModel:init',
'forums' => '@ForumManager:init',
'topics' => \ForkBB\Models\Topic\Manager::class,
'posts' => \ForkBB\Models\Post\Manager::class,
'reports' => \ForkBB\Models\Report\Manager::class,
'user' => '@users:current',
'userRules' => '@UsersRules:init',
'users' => \ForkBB\Models\User\Manager::class,
'groups' => '@GroupManager:init',
'categories' => '@CategoriesManager:init',
'search' => \ForkBB\Models\Search\Model::class,
'config' => '@ConfigModel:init',
'bans' => '@BanListModel:init',
'censorship' => '@CensorshipModel:init',
'stats' => '@StatsModel:init',
'admins' => '@AdminListModel:init',
'smilies' => '@SmileyListModel:init',
'dbMap' => '@DBMapModel:init',
'stopwords' => '@StopwordsModel:init',
'forums' => '@ForumManager:init',
'topics' => \ForkBB\Models\Topic\Manager::class,
'posts' => \ForkBB\Models\Post\Manager::class,
'reports' => \ForkBB\Models\Report\Manager::class,
'user' => '@users:current',
'userRules' => '@UsersRules:init',
'users' => \ForkBB\Models\User\Manager::class,
'groups' => '@GroupManager:init',
'categories' => '@CategoriesManager:init',
'search' => \ForkBB\Models\Search\Model::class,
'subscriptions' => \ForkBB\Models\Subscription\Model::class,
'Csrf' => [
'class' => \ForkBB\Core\Csrf::class,

View file

@ -538,3 +538,9 @@ msgstr "Stick topic"
msgid "User %s"
msgstr "%s"
msgid "Unsubscribe"
msgstr "Unsubscribe"
msgid "Subscribe"
msgstr "Subscribe"

View file

@ -36,17 +36,14 @@ msgstr "Forum is empty."
msgid "Mod controls"
msgstr "Moderator controls"
msgid "Is subscribed"
msgstr "You are currently subscribed to this forum"
msgid "Unsubscribe"
msgstr "Unsubscribe"
msgid "Subscribe"
msgstr "Subscribe to this forum"
msgid "Topic %s was not found in the database"
msgstr "Topic №%s was not found in the database"
msgid "Last post <a href=\"%1$s\">%2$s</a>"
msgstr "<small>Last post </small><a href=\"%1$s\">%2$s</a>"
msgid "Subscribe forum"
msgstr "Receive email notification of new topics"
msgid "Unsubscribe forum"
msgstr "Unsubscribe from email notifications of new topics"

View file

@ -68,15 +68,6 @@ msgstr "Edit"
msgid "Quote"
msgstr "Quote"
msgid "Is subscribed"
msgstr "You are currently subscribed to this topic"
msgid "Unsubscribe"
msgstr "Unsubscribe"
msgid "Subscribe"
msgstr "Subscribe to this topic"
msgid "Quick post"
msgstr "Quick reply"
@ -118,3 +109,9 @@ msgstr "Message №%s was not found in the database"
msgid "Admin note"
msgstr "Admin note"
msgid "Subscribe topic"
msgstr "Receive email notification of new posts"
msgid "Unsubscribe topic"
msgstr "Unsubscribe from email notifications of new posts"

View file

@ -540,3 +540,9 @@ msgstr "Выделить тему"
msgid "User %s"
msgstr "%s"
msgid "Unsubscribe"
msgstr "Отписаться"
msgid "Subscribe"
msgstr "Подписаться"

View file

@ -36,17 +36,14 @@ msgstr "Раздел пуст."
msgid "Mod controls"
msgstr "Инструменты модерирования"
msgid "Is subscribed"
msgstr "Вы подписаны на этот раздел"
msgid "Unsubscribe"
msgstr "Отказаться от подписки"
msgid "Subscribe"
msgstr "Подписаться на этот раздел"
msgid "Topic %s was not found in the database"
msgstr "Тема №%s не найдена в базе данных"
msgid "Last post <a href=\"%1$s\">%2$s</a>"
msgstr "<small>Последнее сообщение </small><a href=\"%1$s\">%2$s</a>"
msgid "Subscribe forum"
msgstr "Получать уведомления о новых темах по электронной почте"
msgid "Unsubscribe forum"
msgstr "Отказаться от получения уведомлений о новых темах"

View file

@ -69,15 +69,6 @@ msgstr "Изменить"
msgid "Quote"
msgstr "Цитировать"
msgid "Is subscribed"
msgstr "Вы подписаны на эту тему"
msgid "Unsubscribe"
msgstr "Отказаться от подписки"
msgid "Subscribe"
msgstr "Подписаться на тему"
msgid "Quick post"
msgstr "Быстрый ответ"
@ -119,3 +110,9 @@ msgstr "Сообщение №%s не найдено в базе данных"
msgid "Admin note"
msgstr "Примечание администрации"
msgid "Subscribe topic"
msgstr "Получать уведомления о новых сообщениях по электронной почте"
msgid "Unsubscribe topic"
msgstr "Отказаться от получения уведомлений о новых сообщениях"

View file

@ -162,13 +162,20 @@
</div>
</section>
<div class="f-nav-links">
@if ($p->model->canCreateTopic || $p->model->pagination || $p->model->canMarkRead)
@if ($p->model->canCreateTopic || $p->model->pagination || $p->model->canMarkRead || $p->model->canSubscription)
<div class="f-nlinks-a">
@if ($p->model->canCreateTopic || $p->model->canMarkRead)
@if ($p->model->canCreateTopic || $p->model->canMarkRead || $p->model->canSubscription)
<div class="f-actions-links">
@if ($p->model->canMarkRead)
<a class="f-btn f-btn-markread f-opacity" title="{!! __('Mark forum read') !!}" href="{!! $p->model->linkMarkRead !!}"><span>{!! __('All is read') !!}</span></a>
@endif
@if ($p->model->canSubscription)
@if ($p->model->is_subscribed)
<a class="f-btn f-btn-unsubscribe f-opacity" title="{!! __('Unsubscribe forum') !!}" href="{!! $p->model->linkUnsubscribe !!}"><span>{!! __('Unsubscribe') !!}</span></a>
@else
<a class="f-btn f-btn-subscribe f-opacity" title="{!! __('Subscribe forum') !!}" href="{!! $p->model->linkSubscribe !!}"><span>{!! __('Subscribe') !!}</span></a>
@endif
@endif
@if ($p->model->canCreateTopic)
<a class="f-btn f-btn-create-topic" title="{!! __('Post topic') !!}" href="{!! $p->model->linkCreateTopic !!}"><span>{!! __('Post topic') !!}</span></a>
@endif

View file

@ -11,18 +11,6 @@
@endforeach
</ul>
@endsection
@section ('linkpost')
@if ($p->model->canReply || $p->model->closed)
<div class="f-actions-links">
@if ($p->model->closed)
<a class="f-btn f-btn-topic-closed" title="{!! __('Topic closed') !!}"><span>{!! __('Topic closed') !!}</span></a>
@endif
@if ($p->model->canReply)
<a class="f-btn f-btn-post-reply" title="{!! __('Post reply') !!}" href="{!! $p->model->linkReply !!}"><span>{!! __('Post reply') !!}</span></a>
@endif
</div>
@endif
@endsection
@section ('pagination')
@if ($p->model->pagination)
<nav class="f-pages">
@ -50,7 +38,16 @@
@if ($p->model->canReply || $p->model->closed || $p->model->pagination)
<div class="f-nlinks-b">
@yield ('pagination')
@yield ('linkpost')
@if ($p->model->canReply || $p->model->closed)
<div class="f-actions-links">
@if ($p->model->closed)
<a class="f-btn f-btn-topic-closed" title="{!! __('Topic closed') !!}"><span>{!! __('Topic closed') !!}</span></a>
@endif
@if ($p->model->canReply)
<a class="f-btn f-btn-post-reply" title="{!! __('Post reply') !!}" href="{!! $p->model->linkReply !!}"><span>{!! __('Post reply') !!}</span></a>
@endif
</div>
@endif
</div>
@endif
</div>
@ -156,9 +153,22 @@
@endforeach
</section>
<div class="f-nav-links">
@if ($p->model->canReply || $p->model->closed || $p->model->pagination)
@if ($p->model->canReply || $p->model->pagination || $p->model->canSubscription)
<div class="f-nlinks-a">
@yield ('linkpost')
@if ($p->model->canReply || $p->model->canSubscription)
<div class="f-actions-links">
@if ($p->model->canSubscription)
@if ($p->model->is_subscribed)
<a class="f-btn f-btn-unsubscribe f-opacity" title="{!! __('Unsubscribe topic') !!}" href="{!! $p->model->linkUnsubscribe !!}"><span>{!! __('Unsubscribe') !!}</span></a>
@else
<a class="f-btn f-btn-subscribe f-opacity" title="{!! __('Subscribe topic') !!}" href="{!! $p->model->linkSubscribe !!}"><span>{!! __('Subscribe') !!}</span></a>
@endif
@endif
@if ($p->model->canReply)
<a class="f-btn f-btn-post-reply" title="{!! __('Post reply') !!}" href="{!! $p->model->linkReply !!}"><span>{!! __('Post reply') !!}</span></a>
@endif
</div>
@endif
@yield ('pagination')
</div>
@endif

View file

@ -1,4 +1,4 @@
# ForkBB rev 9 Pre-Alpha Readme
# ForkBB rev 11 Pre-Alpha Readme
## About