diff --git a/components/Group/Controller/Group.php b/components/Group/Controller/Group.php index 3b72fda3d4..dda90f653b 100644 --- a/components/Group/Controller/Group.php +++ b/components/Group/Controller/Group.php @@ -29,6 +29,7 @@ use App\Core\DB\DB; use App\Core\Form; use function App\Core\I18n\_m; use App\Core\Log; +use App\Core\UserRoles; use App\Entity\Actor; use App\Entity as E; use App\Util\Common; @@ -36,6 +37,8 @@ use App\Util\Exception\ClientException; use App\Util\Exception\RedirectException; use App\Util\Form\ActorForms; use App\Util\Nickname; +use Component\Group\Entity\GroupMember; +use Component\Group\Entity\LocalGroup; use Symfony\Component\Form\Extension\Core\Type\SubmitType; use Symfony\Component\HttpFoundation\Request; @@ -58,7 +61,7 @@ class Group extends ActorController public function groupViewNickname(Request $request, string $nickname) { Nickname::validate($nickname, which: Nickname::CHECK_LOCAL_GROUP); // throws - $group = Actor::getByNickname($nickname, type: Actor::GROUP); + $group = LocalGroup::getActorByNickname($nickname); if (\is_null($group)) { $actor = Common::actor(); if (!\is_null($actor)) { @@ -75,21 +78,21 @@ class Group extends ActorController ), ); - $group = Actor::create([ + DB::persist($group = Actor::create([ 'nickname' => $nickname, 'type' => Actor::GROUP, 'is_local' => true, - ]); - DB::persist($group); + 'roles' => UserRoles::BOT, + ])); + DB::persist(LocalGroup::create([ + 'group_id' => $group->getId(), + 'nickname' => $nickname, + ])); DB::persist(E\Subscription::create([ 'subscriber' => $group->getId(), 'subscribed' => $group->getId(), ])); - DB::persist(E\Subscription::create([ - 'subscriber' => $actor->getId(), - 'subscribed' => $group->getId(), - ])); - DB::persist(E\GroupMember::create([ + DB::persist(GroupMember::create([ 'group_id' => $group->getId(), 'actor_id' => $actor->getId(), 'is_admin' => true, @@ -97,7 +100,7 @@ class Group extends ActorController DB::flush(); Cache::delete(Actor::cacheKeys($actor->getId())['subscriber']); Cache::delete(Actor::cacheKeys($actor->getId())['subscribed']); - throw new RedirectException; + throw new RedirectException(); } return [ @@ -114,6 +117,7 @@ class Group extends ActorController join activity a with n.id = a.object_id join group_inbox gi with a.id = gi.activity_id where a.object_type = 'note' and gi.group_id = :group_id + order by a.created desc, a.id desc EOF, ['group_id' => $group->getId()], ) : []; @@ -128,7 +132,7 @@ class Group extends ActorController public function groupSettings(Request $request, string $nickname) { - $group = Actor::getByNickname($nickname, type: Actor::GROUP); + $group = LocalGroup::getActorByNickname($nickname); $actor = Common::actor(); if (!\is_null($group) && $actor->canAdmin($group)) { return [ diff --git a/src/Entity/GroupAlias.php b/components/Group/Entity/GroupAlias.php similarity index 91% rename from src/Entity/GroupAlias.php rename to components/Group/Entity/GroupAlias.php index 39b0dedaba..46ffac6dcf 100644 --- a/src/Entity/GroupAlias.php +++ b/components/Group/Entity/GroupAlias.php @@ -1,5 +1,7 @@ . // }}} -namespace App\Entity; +namespace Component\Group\Entity; use App\Core\Entity; use DateTimeInterface; @@ -42,11 +44,11 @@ class GroupAlias extends Entity // @codeCoverageIgnoreStart private string $alias; private int $group_id; - private \DateTimeInterface $modified; + private DateTimeInterface $modified; public function setAlias(string $alias): self { - $this->alias = \mb_substr($alias, 0, 64); + $this->alias = mb_substr($alias, 0, 64); return $this; } @@ -66,13 +68,13 @@ class GroupAlias extends Entity return $this->group_id; } - public function setModified(\DateTimeInterface $modified): self + public function setModified(DateTimeInterface $modified): self { $this->modified = $modified; return $this; } - public function getModified(): \DateTimeInterface + public function getModified(): DateTimeInterface { return $this->modified; } diff --git a/src/Entity/GroupBlock.php b/components/Group/Entity/GroupBlock.php similarity index 93% rename from src/Entity/GroupBlock.php rename to components/Group/Entity/GroupBlock.php index ab8d53ec3c..76bee7e422 100644 --- a/src/Entity/GroupBlock.php +++ b/components/Group/Entity/GroupBlock.php @@ -1,5 +1,7 @@ . // }}} -namespace App\Entity; +namespace Component\Group\Entity; use App\Core\Entity; use DateTimeInterface; @@ -43,7 +45,7 @@ class GroupBlock extends Entity private int $group_id; private int $blocked_actor; private int $blocker_user; - private \DateTimeInterface $modified; + private DateTimeInterface $modified; public function setGroupId(int $group_id): self { @@ -78,13 +80,13 @@ class GroupBlock extends Entity return $this->blocker_user; } - public function setModified(\DateTimeInterface $modified): self + public function setModified(DateTimeInterface $modified): self { $this->modified = $modified; return $this; } - public function getModified(): \DateTimeInterface + public function getModified(): DateTimeInterface { return $this->modified; } diff --git a/src/Entity/GroupInbox.php b/components/Group/Entity/GroupInbox.php similarity index 93% rename from src/Entity/GroupInbox.php rename to components/Group/Entity/GroupInbox.php index 69f32d82f0..f626a8d40e 100644 --- a/src/Entity/GroupInbox.php +++ b/components/Group/Entity/GroupInbox.php @@ -1,5 +1,7 @@ . // }}} -namespace App\Entity; +namespace Component\Group\Entity; use App\Core\Entity; use DateTimeInterface; @@ -42,7 +44,7 @@ class GroupInbox extends Entity // @codeCoverageIgnoreStart private int $group_id; private int $activity_id; - private \DateTimeInterface $created; + private DateTimeInterface $created; public function setGroupId(int $group_id): self { @@ -66,13 +68,13 @@ class GroupInbox extends Entity return $this->activity_id; } - public function setCreated(\DateTimeInterface $created): self + public function setCreated(DateTimeInterface $created): self { $this->created = $created; return $this; } - public function getCreated(): \DateTimeInterface + public function getCreated(): DateTimeInterface { return $this->created; } diff --git a/src/Entity/GroupJoinQueue.php b/components/Group/Entity/GroupJoinQueue.php similarity index 97% rename from src/Entity/GroupJoinQueue.php rename to components/Group/Entity/GroupJoinQueue.php index 50f4748d7a..f9935ab408 100644 --- a/src/Entity/GroupJoinQueue.php +++ b/components/Group/Entity/GroupJoinQueue.php @@ -1,5 +1,7 @@ . // }}} -namespace App\Entity; +namespace Component\Group\Entity; use App\Core\Entity; diff --git a/src/Entity/GroupMember.php b/components/Group/Entity/GroupMember.php similarity index 90% rename from src/Entity/GroupMember.php rename to components/Group/Entity/GroupMember.php index 3b96505547..44ca47a249 100644 --- a/src/Entity/GroupMember.php +++ b/components/Group/Entity/GroupMember.php @@ -19,7 +19,7 @@ declare(strict_types = 1); // along with GNU social. If not, see . // }}} -namespace App\Entity; +namespace Component\Group\Entity; use App\Core\Entity; use DateTimeInterface; @@ -45,9 +45,9 @@ class GroupMember extends Entity private int $group_id; private int $actor_id; private ?bool $is_admin = false; - private ?string $uri = null; - private \DateTimeInterface $created; - private \DateTimeInterface $modified; + private ?string $uri = null; + private DateTimeInterface $created; + private DateTimeInterface $modified; public function setGroupId(int $group_id): self { @@ -84,7 +84,7 @@ class GroupMember extends Entity public function setUri(?string $uri): self { - $this->uri = \is_null($uri) ? null : \mb_substr($uri, 0, 191); + $this->uri = \is_null($uri) ? null : mb_substr($uri, 0, 191); return $this; } @@ -93,24 +93,24 @@ class GroupMember extends Entity return $this->uri; } - public function setCreated(\DateTimeInterface $created): self + public function setCreated(DateTimeInterface $created): self { $this->created = $created; return $this; } - public function getCreated(): \DateTimeInterface + public function getCreated(): DateTimeInterface { return $this->created; } - public function setModified(\DateTimeInterface $modified): self + public function setModified(DateTimeInterface $modified): self { $this->modified = $modified; return $this; } - public function getModified(): \DateTimeInterface + public function getModified(): DateTimeInterface { return $this->modified; } diff --git a/src/Entity/LocalGroup.php b/components/Group/Entity/LocalGroup.php similarity index 78% rename from src/Entity/LocalGroup.php rename to components/Group/Entity/LocalGroup.php index c75186a913..b747def890 100644 --- a/src/Entity/LocalGroup.php +++ b/components/Group/Entity/LocalGroup.php @@ -1,5 +1,7 @@ . // }}} -namespace App\Entity; +namespace Component\Group\Entity; use App\Core\DB\DB; use App\Core\Entity; +use App\Entity\Actor; use DateTimeInterface; /** @@ -44,8 +47,8 @@ class LocalGroup extends Entity // @codeCoverageIgnoreStart private int $group_id; private ?string $nickname = null; - private \DateTimeInterface $created; - private \DateTimeInterface $modified; + private DateTimeInterface $created; + private DateTimeInterface $modified; public function setGroupId(int $group_id): self { @@ -60,7 +63,7 @@ class LocalGroup extends Entity public function setNickname(?string $nickname): self { - $this->nickname = \is_null($nickname) ? null : \mb_substr($nickname, 0, 64); + $this->nickname = \is_null($nickname) ? null : mb_substr($nickname, 0, 64); return $this; } @@ -69,24 +72,24 @@ class LocalGroup extends Entity return $this->nickname; } - public function setCreated(\DateTimeInterface $created): self + public function setCreated(DateTimeInterface $created): self { $this->created = $created; return $this; } - public function getCreated(): \DateTimeInterface + public function getCreated(): DateTimeInterface { return $this->created; } - public function setModified(\DateTimeInterface $modified): self + public function setModified(DateTimeInterface $modified): self { $this->modified = $modified; return $this; } - public function getModified(): \DateTimeInterface + public function getModified(): DateTimeInterface { return $this->modified; } @@ -99,6 +102,18 @@ class LocalGroup extends Entity return DB::find('actor', ['id' => $this->group_id]); } + public static function getByNickname(string $nickname): ?self + { + $res = DB::findBy(self::class, ['nickname' => $nickname]); + return $res === [] ? null : $res[0]; + } + + public static function getActorByNickname(string $nickname): ?Actor + { + $res = DB::findBy(Actor::class, ['nickname' => $nickname, 'type' => Actor::GROUP]); + return $res === [] ? null : $res[0]; + } + public static function schemaDef(): array { return [ diff --git a/components/Group/Group.php b/components/Group/Group.php index e5b70bd6d8..e1a2d15b36 100644 --- a/components/Group/Group.php +++ b/components/Group/Group.php @@ -31,6 +31,7 @@ use App\Util\Common; use App\Util\HTML; use App\Util\Nickname; use Component\Group\Controller as C; +use Component\Group\Entity\LocalGroup; use Component\Tag\Controller\Tag as TagController; use Symfony\Component\HttpFoundation\Request; @@ -62,7 +63,7 @@ class Group extends Component { if ($section === 'profile' && $request->get('_route') === 'group_settings') { $nickname = $request->get('nickname'); - $group = Actor::getByNickname($nickname, type: Actor::GROUP); + $group = LocalGroup::getActorByNickname($nickname); $tabs[] = [ 'title' => 'Self tags', 'desc' => 'Add or remove tags on this group', @@ -82,7 +83,7 @@ class Group extends Component if (!\is_null($id = $request->get('id'))) { return Actor::getById((int) $id); } elseif (!\is_null($nickname = $request->get('nickname'))) { - return Actor::getByNickname($nickname, type: Actor::GROUP); + return LocalGroup::getActorByNickname($nickname); } } return null; diff --git a/components/Posting/Posting.php b/components/Posting/Posting.php index cb01d77cec..bb6fa0d540 100644 --- a/components/Posting/Posting.php +++ b/components/Posting/Posting.php @@ -34,7 +34,6 @@ use App\Core\Security; use App\Core\VisibilityScope; use App\Entity\Activity; use App\Entity\Actor; -use App\Entity\GroupInbox; use App\Entity\Note; use App\Util\Common; use App\Util\Exception\BugFoundException; @@ -47,6 +46,8 @@ use App\Util\Formatting; use Component\Attachment\Entity\ActorToAttachment; use Component\Attachment\Entity\AttachmentToNote; use Component\Conversation\Conversation; +use Component\Group\Entity\GroupInbox; +use Component\Group\Entity\LocalGroup; use Component\Language\Entity\Language; use Functional as F; use Symfony\Component\Form\Extension\Core\Type\ChoiceType; @@ -255,13 +256,13 @@ class Posting extends Component switch ($target[0]) { case '!': $mentions[] = [ - 'mentioned' => [Actor::getByNickname(mb_substr($target, 1), type: Actor::GROUP)], + 'mentioned' => [LocalGroup::getActorByNickname(mb_substr($target, 1))], 'type' => 'group', 'text' => mb_substr($target, 1), ]; break; default: - throw new ClientException(_m('Unkown target type give in \'in\' field: ' . $target)); + throw new ClientException(_m('Unknown target type give in \'In\' field: ' . $target)); } } diff --git a/src/Entity/Actor.php b/src/Entity/Actor.php index d6368cd1e1..aab43a1349 100644 --- a/src/Entity/Actor.php +++ b/src/Entity/Actor.php @@ -274,20 +274,6 @@ class Actor extends Entity } } - /** - * @return ?self - */ - public static function getByNickname(string $nickname, int $type = self::PERSON): ?self - { - try { - return DB::findOneBy(self::class, ['nickname' => $nickname, 'type' => $type]); - } catch (NotFoundException) { - return null; - } catch (DuplicateFoundException $e) { - throw new BugFoundException("Multiple actors with the same nickname '{$nickname}' found", previous: $e); - } - } - public function getAvatarUrl(string $size = 'medium') { return Avatar::getUrl($this->getId(), $size); @@ -560,7 +546,6 @@ class Actor extends Entity } }, ); - break; default: return false; } diff --git a/src/Util/Formatting.php b/src/Util/Formatting.php index b8a40d2aec..8dbc745269 100644 --- a/src/Util/Formatting.php +++ b/src/Util/Formatting.php @@ -38,6 +38,7 @@ use App\Entity\Actor; use App\Entity\Note; use App\Util\Exception\NicknameException; use App\Util\Exception\ServerException; +use Component\Group\Entity\LocalGroup; use Exception; use Functional as F; use InvalidArgumentException; @@ -356,7 +357,7 @@ abstract class Formatting $group_matches = self::findMentionsRaw($text, '!'); foreach ($group_matches as $group_match) { $nickname = Nickname::normalize($group_match[0], check_already_used: false, check_is_allowed: false); - $group = Actor::getByNickname($nickname, Actor::GROUP); + $group = LocalGroup::getActorByNickname($nickname, Actor::GROUP); $mentions[] = [ 'mentioned' => [$group],