[COMPONENT][Subscription] Start component
This commit is contained in:
parent
5fa8056899
commit
6cfb69d64b
@ -39,6 +39,7 @@ use Component\Collection\Util\ActorControllerTrait;
|
||||
use Component\Collection\Util\Controller\FeedController;
|
||||
use Component\Group\Entity\GroupMember;
|
||||
use Component\Group\Entity\LocalGroup;
|
||||
use Component\Subscription\Entity\Subscription;
|
||||
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
@ -91,7 +92,7 @@ class Group extends FeedController
|
||||
'group_id' => $group->getId(),
|
||||
'nickname' => $nickname,
|
||||
]));
|
||||
DB::persist(E\Subscription::create([
|
||||
DB::persist(Subscription::create([
|
||||
'subscriber' => $group->getId(),
|
||||
'subscribed' => $group->getId(),
|
||||
]));
|
||||
@ -115,7 +116,7 @@ class Group extends FeedController
|
||||
} else {
|
||||
if (!\is_null($actor)
|
||||
&& \is_null(Cache::get(
|
||||
E\Subscription::cacheKeys($actor, $group)['subscribed'],
|
||||
Subscription::cacheKeys($actor, $group)['subscribed'],
|
||||
fn () => DB::findOneBy('subscription', [
|
||||
'subscriber' => $actor->getId(),
|
||||
'subscribed' => $group->getId(),
|
||||
@ -125,14 +126,14 @@ class Group extends FeedController
|
||||
$subscribe_form = Form::create([['subscribe', SubmitType::class, ['label' => _m('Subscribe to this group')]]]);
|
||||
$subscribe_form->handleRequest($request);
|
||||
if ($subscribe_form->isSubmitted() && $subscribe_form->isValid()) {
|
||||
DB::persist(E\Subscription::create([
|
||||
DB::persist(Subscription::create([
|
||||
'subscriber' => $actor->getId(),
|
||||
'subscribed' => $group->getId(),
|
||||
]));
|
||||
DB::flush();
|
||||
Cache::delete(E\Actor::cacheKeys($group->getId())['subscriber']);
|
||||
Cache::delete(E\Actor::cacheKeys($actor->getId())['subscribed']);
|
||||
Cache::delete(E\Subscription::cacheKeys($actor, $group)['subscribed']);
|
||||
Cache::delete(Subscription::cacheKeys($actor, $group)['subscribed']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -21,23 +21,25 @@ declare(strict_types = 1);
|
||||
|
||||
// }}}
|
||||
|
||||
namespace App\Controller;
|
||||
namespace Component\Subscription\Controller;
|
||||
|
||||
use App\Core\Controller\ActorController;
|
||||
use function App\Core\I18n\_m;
|
||||
use Component\Collection\Util\ActorControllerTrait;
|
||||
use Component\Collection\Util\Controller\CircleController;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
/**
|
||||
* Collection of an actor's subscribers
|
||||
*/
|
||||
class Subscribers extends ActorController
|
||||
class Subscribers extends CircleController
|
||||
{
|
||||
use ActorControllerTrait;
|
||||
public function subscribersByActorId(Request $request, int $id)
|
||||
{
|
||||
return $this->handleActorById(
|
||||
$id,
|
||||
fn ($actor) => [
|
||||
'_template' => 'subscribers/view.html.twig',
|
||||
'actor' => $actor,
|
||||
'actor' => $actor,
|
||||
],
|
||||
);
|
||||
}
|
||||
@ -47,8 +49,12 @@ class Subscribers extends ActorController
|
||||
return $this->handleActorByNickname(
|
||||
$nickname,
|
||||
fn ($actor) => [
|
||||
'_template' => 'subscribers/view.html.twig',
|
||||
'actor' => $actor,
|
||||
'_template' => 'collection/actors.html.twig',
|
||||
'title' => _m('Subscribers'),
|
||||
'empty_message' => _m('No subscribers'),
|
||||
'sort_options' => [],
|
||||
'page' => $this->int('page') ?? 1,
|
||||
'actors' => $actor->getSubscribers(),
|
||||
],
|
||||
);
|
||||
}
|
@ -21,23 +21,25 @@ declare(strict_types = 1);
|
||||
|
||||
// }}}
|
||||
|
||||
namespace App\Controller;
|
||||
namespace Component\Subscription\Controller;
|
||||
|
||||
use App\Core\Controller\ActorController;
|
||||
use function App\Core\I18n\_m;
|
||||
use Component\Collection\Util\ActorControllerTrait;
|
||||
use Component\Collection\Util\Controller\CircleController;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
/**
|
||||
* Collection of an actor's subscriptions
|
||||
*/
|
||||
class Subscriptions extends ActorController
|
||||
class Subscriptions extends CircleController
|
||||
{
|
||||
use ActorControllerTrait;
|
||||
public function subscriptionsByActorId(Request $request, int $id)
|
||||
{
|
||||
return $this->handleActorById(
|
||||
$id,
|
||||
fn ($actor) => [
|
||||
'_template' => 'subscriptions/view.html.twig',
|
||||
'actor' => $actor,
|
||||
'actor' => $actor,
|
||||
],
|
||||
);
|
||||
}
|
||||
@ -47,8 +49,12 @@ class Subscriptions extends ActorController
|
||||
return $this->handleActorByNickname(
|
||||
$nickname,
|
||||
fn ($actor) => [
|
||||
'_template' => 'subscriptions/view.html.twig',
|
||||
'actor' => $actor,
|
||||
'_template' => 'collection/actors.html.twig',
|
||||
'title' => _m('Subscribers'),
|
||||
'empty_message' => _m('No subscribers'),
|
||||
'sort_options' => [],
|
||||
'page' => $this->int('page') ?? 1,
|
||||
'actors' => $actor->getSubscribers(),
|
||||
],
|
||||
);
|
||||
}
|
@ -9,10 +9,10 @@ use App\Core\VisibilityScope;
|
||||
use App\Entity\Actor;
|
||||
use App\Entity\LocalUser;
|
||||
use App\Entity\Note;
|
||||
use App\Entity\Subscription;
|
||||
use Component\Group\Entity\GroupInbox;
|
||||
use Component\Group\Entity\GroupMember;
|
||||
use Component\Group\Entity\LocalGroup;
|
||||
use Component\Subscription\Entity\Subscription;
|
||||
use Doctrine\Bundle\FixturesBundle\Fixture;
|
||||
use Doctrine\Persistence\ObjectManager;
|
||||
|
||||
|
@ -37,6 +37,7 @@ use App\Util\Nickname;
|
||||
use Component\Avatar\Avatar;
|
||||
use Component\Language\Entity\ActorLanguage;
|
||||
use Component\Language\Entity\Language;
|
||||
use Component\Subscription\Entity\Subscription;
|
||||
use DateTimeInterface;
|
||||
use Functional as F;
|
||||
|
||||
@ -242,26 +243,26 @@ class Actor extends Entity
|
||||
// @codeCoverageIgnoreEnd
|
||||
// }}} Autocode
|
||||
|
||||
public const PERSON = 1;
|
||||
public const GROUP = 2;
|
||||
public const PERSON = 1;
|
||||
public const GROUP = 2;
|
||||
public const ORGANIZATION = 3;
|
||||
public const BUSINESS = 4;
|
||||
public const BOT = 5;
|
||||
public const BUSINESS = 4;
|
||||
public const BOT = 5;
|
||||
|
||||
public static function cacheKeys(int|self $actor_id, mixed $other = null): array
|
||||
{
|
||||
$actor_id = \is_int($actor_id) ? $actor_id : $actor_id->getId();
|
||||
|
||||
return [
|
||||
'id' => "actor-id-{$actor_id}",
|
||||
'nickname' => "actor-nickname-id-{$actor_id}",
|
||||
'fullname' => "actor-fullname-id-{$actor_id}",
|
||||
'tags' => \is_null($other) ? "actor-tags-{$actor_id}" : "actor-tags-{$actor_id}-by-{$other}", // $other is $context_id
|
||||
'circles' => "actor-circles-{$actor_id}",
|
||||
'subscriber' => "subscriber-{$actor_id}",
|
||||
'subscribed' => "subscribed-{$actor_id}",
|
||||
'id' => "actor-id-{$actor_id}",
|
||||
'nickname' => "actor-nickname-id-{$actor_id}",
|
||||
'fullname' => "actor-fullname-id-{$actor_id}",
|
||||
'tags' => \is_null($other) ? "actor-tags-{$actor_id}" : "actor-tags-{$actor_id}-by-{$other}", // $other is $context_id
|
||||
'circles' => "actor-circles-{$actor_id}",
|
||||
'subscriber' => "subscriber-{$actor_id}",
|
||||
'subscribed' => "subscribed-{$actor_id}",
|
||||
'relative-nickname' => "actor-{$actor_id}-relative-nickname-{$other}", // $other is $nickname
|
||||
'can-admin' => "actor-{$actor_id}-can-admin-{$other}", // $other is an actor id
|
||||
'can-admin' => "actor-{$actor_id}-can-admin-{$other}", // $other is an actor id
|
||||
];
|
||||
}
|
||||
|
||||
@ -286,17 +287,17 @@ class Actor extends Entity
|
||||
|
||||
public static function getById(int $id): ?self
|
||||
{
|
||||
return Cache::get(self::cacheKeys($id)['id'], fn () => DB::find('actor', ['id' => $id]));
|
||||
return Cache::get(self::cacheKeys($id)['id'], fn() => DB::find('actor', ['id' => $id]));
|
||||
}
|
||||
|
||||
public static function getNicknameById(int $id): string
|
||||
{
|
||||
return Cache::get(self::cacheKeys($id)['nickname'], fn () => self::getById($id)->getNickname());
|
||||
return Cache::get(self::cacheKeys($id)['nickname'], fn() => self::getById($id)->getNickname());
|
||||
}
|
||||
|
||||
public static function getFullnameById(int $id): ?string
|
||||
{
|
||||
return Cache::get(self::cacheKeys($id)['fullname'], fn () => self::getById($id)->getFullname());
|
||||
return Cache::get(self::cacheKeys($id)['fullname'], fn() => self::getById($id)->getFullname());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -324,8 +325,8 @@ class Actor extends Entity
|
||||
* - If null = All tags attributed to self by other actors (excludes self tags)
|
||||
* - If self = Same as getSelfTags
|
||||
* - otherwise = Tags that $context attributed to $this
|
||||
* @param null|int $offset Offset from latest
|
||||
* @param null|int $limit Max number to get
|
||||
* @param null|int $offset Offset from latest
|
||||
* @param null|int $limit Max number to get
|
||||
*
|
||||
* @return ActorTag[] resulting lists
|
||||
*/
|
||||
@ -334,7 +335,7 @@ class Actor extends Entity
|
||||
if (\is_null($context)) {
|
||||
return Cache::getList(
|
||||
self::cacheKeys($this->getId())['tags'],
|
||||
fn () => DB::dql(
|
||||
fn() => DB::dql(
|
||||
<<< 'EOQ'
|
||||
SELECT tag
|
||||
FROM actor_tag tag
|
||||
@ -349,7 +350,7 @@ class Actor extends Entity
|
||||
$context_id = \is_int($context) ? $context : $context->getId();
|
||||
return Cache::getList(
|
||||
self::cacheKeys($this->getId(), $context_id)['tags'],
|
||||
fn () => DB::dql(
|
||||
fn() => DB::dql(
|
||||
<<< 'EOQ'
|
||||
SELECT tag
|
||||
FROM actor_tag tag
|
||||
@ -367,7 +368,7 @@ class Actor extends Entity
|
||||
{
|
||||
return Cache::getList(
|
||||
self::cacheKeys($this->getId())['circles'],
|
||||
fn () => DB::findBy('actor_circle', ['tagger' => $this->getId()]),
|
||||
fn() => DB::findBy('actor_circle', ['tagger' => $this->getId()]),
|
||||
);
|
||||
}
|
||||
|
||||
@ -375,10 +376,7 @@ class Actor extends Entity
|
||||
{
|
||||
return Cache::get(
|
||||
self::cacheKeys($this->getId())[$which],
|
||||
fn () => DB::dql(
|
||||
"select count(s) from subscription s where s.{$column} = :{$column}", // Not injecting the parameter value
|
||||
[$column => $this->getId()],
|
||||
)[0][1] - ($this->getIsLocal() ? 1 : 0), // Remove self subscription if local
|
||||
fn() => DB::count(Subscription::class, [$column => $this->getId()]) - ($this->getIsLocal() ? 1 : 0)
|
||||
);
|
||||
}
|
||||
|
||||
@ -387,11 +385,31 @@ class Actor extends Entity
|
||||
return $this->getSubCount(which: 'subscriber', column: 'subscribed_id');
|
||||
}
|
||||
|
||||
public function getSubscribedCount()
|
||||
public function getSubscribedCount(): int
|
||||
{
|
||||
return $this->getSubCount(which: 'subscribed', column: 'subscriber_id');
|
||||
}
|
||||
|
||||
public function getSubscriptions(): array
|
||||
{
|
||||
return DB::dql(<<<EOF
|
||||
SELECT a FROM actor AS a
|
||||
INNER JOIN subscription AS s
|
||||
WITH a.id = s.subscribed_id
|
||||
WHERE s.subscriber_id = :self AND a.id != :self
|
||||
EOF, ['self' => $this->getId()]);
|
||||
}
|
||||
|
||||
public function getSubscribers(): array
|
||||
{
|
||||
return DB::dql(<<<EOF
|
||||
SELECT a FROM actor AS a
|
||||
INNER JOIN subscription AS s
|
||||
WITH a.id = s.subscriber_id
|
||||
WHERE s.subscribed_id = :self AND a.id != :self
|
||||
EOF, ['self' => $this->getId()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve an ambiguous nickname reference, checking in following order:
|
||||
* - Actors that $sender subscribes to
|
||||
|
@ -34,9 +34,9 @@ declare(strict_types = 1);
|
||||
|
||||
namespace App\Routes;
|
||||
|
||||
use App\Controller as C;
|
||||
use App\Core\Router\RouteLoader;
|
||||
use App\Util\Nickname;
|
||||
use Component\Subscription\Controller as C;
|
||||
|
||||
abstract class Subscribers
|
||||
{
|
||||
|
@ -34,9 +34,9 @@ declare(strict_types = 1);
|
||||
|
||||
namespace App\Routes;
|
||||
|
||||
use App\Controller as C;
|
||||
use App\Core\Router\RouteLoader;
|
||||
use App\Util\Nickname;
|
||||
use Component\Subscription\Controller as C;
|
||||
|
||||
abstract class Subscriptions
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user