From 726613cd96d0324de62fbec940f723a8fe9ba6f8 Mon Sep 17 00:00:00 2001 From: Hugo Sales Date: Sun, 26 Dec 2021 15:19:00 +0000 Subject: [PATCH] [ENTITY][ActorCircle][COMPONENT][Tag] Add fields to ActorCircle and add or remove target to actor circle when they add or remove a selftag --- components/Tag/Controller/Tag.php | 50 +++++++++++++++++++++++++++---- src/Entity/ActorCircle.php | 48 +++++++++++++++++++++-------- 2 files changed, 80 insertions(+), 18 deletions(-) diff --git a/components/Tag/Controller/Tag.php b/components/Tag/Controller/Tag.php index c79410c930..49c52224ac 100644 --- a/components/Tag/Controller/Tag.php +++ b/components/Tag/Controller/Tag.php @@ -10,6 +10,7 @@ use App\Core\DB\DB; use function App\Core\I18n\_m; use App\Entity as E; use App\Util\Common; +use App\Util\Exception\BugFoundException; use App\Util\Exception\ClientException; use App\Util\Exception\RedirectException; use App\Util\Formatting; @@ -110,14 +111,40 @@ class Tag extends Controller $language = $target->getTopLanguage()->getLocale(); foreach ($tags as $tag) { $tag = CompTag::ensureValid($tag); - [$at, ] = E\ActorTag::createOrUpdate([ + $canon_tag = CompTag::canonicalTag($tag, language: $language); + $use_canon = $data['new-tags-use-canon']; + + [$actor_tag, $actor_tag_existed] = E\ActorTag::createOrUpdate([ 'tagger' => $target->getId(), 'tagged' => $target->getId(), 'tag' => $tag, - 'canonical' => CompTag::canonicalTag($tag, language: $language), - 'use_canonical' => $data['new-tags-use-canon'], + 'canonical' => $canon_tag, + 'use_canonical' => $use_canon, ]); - DB::persist($at); + DB::persist($actor_tag); + + $actor_circle = DB::findBy( + 'actor_circle', + [ + 'tagger' => null, + 'tagged' => $target->getId(), + 'in' => ['tag' => [$tag, $canon_tag]], + 'use_canonical' => $use_canon, + ], + ); + if (empty($actor_circle)) { + if ($actor_tag_existed) { + throw new BugFoundException('Actor tag existed but generic actor circle did not'); + } + DB::persist(E\ActorCircle::create([ + 'tagger' => null, + 'tagged' => $target->getId(), + 'tag' => $use_canon ? $canon_tag : $tag, + 'use_canonical' => $use_canon, + 'private' => false, + 'description' => null, + ])); + } } DB::flush(); Cache::delete(E\Actor::cacheKeys($target->getId(), $target->getId())['tags']); @@ -129,8 +156,10 @@ class Tag extends Controller function ($form, array $form_definition) use ($request, $target, $details_id) { $data = $form->getData(); $changed = false; + $language = $target->getTopLanguage()->getLocale(); foreach (array_chunk($form_definition, 3) as $entry) { $tag = Formatting::removePrefix($entry[0][2]['data'], '#'); + $canon_tag = CompTag::canonicalTag($tag, language: $language); $use_canon = $entry[1][2]['attr']['data']; /** @var SubmitButton $remove */ @@ -146,13 +175,22 @@ class Tag extends Controller 'use_canonical' => $use_canon, ], ); + DB::removeBy( + 'actor_circle', + [ + 'tagger' => null, + 'tagged' => $target->getId(), + 'tag' => $use_canon ? $canon_tag : $tag, + 'use_canonical' => $use_canon, + ], + ); } /** @var SubmitButton $toggle_canon */ $toggle_canon = $form->get($entry[1][0]); if ($toggle_canon->isSubmitted()) { $changed = true; - $at = DB::find( + $actor_tag = DB::find( 'actor_tag', [ 'tagger' => $target->getId(), @@ -161,7 +199,7 @@ class Tag extends Controller 'use_canonical' => $use_canon, ], ); - DB::persist($at->setUseCanonical(!$use_canon)); + DB::persist($actor_tag->setUseCanonical(!$use_canon)); } } if ($changed) { diff --git a/src/Entity/ActorCircle.php b/src/Entity/ActorCircle.php index 7ceecfd24c..badeeb4c7f 100644 --- a/src/Entity/ActorCircle.php +++ b/src/Entity/ActorCircle.php @@ -48,8 +48,10 @@ class ActorCircle extends Entity // {{{ Autocode // @codeCoverageIgnoreStart private int $id; - private int $tagger; + private ?int $tagger; + private int $tagged; private string $tag; + private bool $use_canonical; private ?string $description; private ?bool $private; private \DateTimeInterface $created; @@ -66,17 +68,28 @@ class ActorCircle extends Entity return $this->id; } - public function setTagger(int $tagger): self + public function setTagger(?int $tagger): self { $this->tagger = $tagger; return $this; } - public function getTagger(): int + public function getTagger(): ?int { return $this->tagger; } + public function setTagged(int $tagged): self + { + $this->tagged = $tagged; + return $this; + } + + public function getTagged(): int + { + return $this->tagged; + } + public function setTag(string $tag): self { $this->tag = \mb_substr($tag, 0, 64); @@ -88,6 +101,17 @@ class ActorCircle extends Entity return $this->tag; } + public function setUseCanonical(bool $use_canonical): self + { + $this->use_canonical = $use_canonical; + return $this; + } + + public function getUseCanonical(): bool + { + return $this->use_canonical; + } + public function setDescription(?string $description): self { $this->description = $description; @@ -167,15 +191,15 @@ class ActorCircle extends Entity 'name' => 'actor_circle', 'description' => 'a actor can have lists of actors, to separate their feed', 'fields' => [ - 'id' => ['type' => 'serial', 'not null' => true, 'description' => 'unique identifier'], - // An actor can be tagged by many actors - 'tagger' => ['type' => 'int', 'foreign key' => true, 'target' => 'Actor.id', 'multiplicity' => 'many to one', 'name' => 'actor_list_tagger_fkey', 'not null' => true, 'description' => 'user making the tag'], - // Many Actor Circles can reference (and probably will) an Actor Tag - 'tag' => ['type' => 'varchar', 'length' => 64, 'foreign key' => true, 'target' => 'ActorTag.tag', 'multiplicity' => 'many to one', 'not null' => true, 'description' => 'actor tag'], // Join with ActorTag // // so, Doctrine doesn't like that the target is not unique, even though the pair is - 'description' => ['type' => 'text', 'description' => 'description of the people tag'], - 'private' => ['type' => 'bool', 'default' => false, 'description' => 'is this tag private'], - 'created' => ['type' => 'datetime', 'not null' => true, 'default' => 'CURRENT_TIMESTAMP', 'description' => 'date this record was created'], - 'modified' => ['type' => 'timestamp', 'not null' => true, 'default' => 'CURRENT_TIMESTAMP', 'description' => 'date this record was modified'], + 'id' => ['type' => 'serial', 'not null' => true, 'description' => 'unique identifier'], // An actor can be tagged by many actors + 'tagger' => ['type' => 'int', 'foreign key' => true, 'target' => 'Actor.id', 'multiplicity' => 'many to one', 'name' => 'actor_list_tagger_fkey', 'description' => 'user making the tag'], + 'tagged' => ['type' => 'int', 'foreign key' => true, 'target' => 'Actor.id', 'multiplicity' => 'one to one', 'name' => 'actor_tag_tagged_fkey', 'not null' => true, 'description' => 'actor tagged'], + 'tag' => ['type' => 'varchar', 'length' => 64, 'foreign key' => true, 'target' => 'ActorTag.tag', 'multiplicity' => 'many to one', 'not null' => true, 'description' => 'actor tag'], // Join with ActorTag // // so, Doctrine doesn't like that the target is not unique, even though the pair is // Many Actor Circles can reference (and probably will) an Actor Tag + 'use_canonical' => ['type' => 'bool', 'not null' => true, 'description' => 'whether the user wanted to block canonical tags'], + 'description' => ['type' => 'text', 'description' => 'description of the people tag'], + 'private' => ['type' => 'bool', 'default' => false, 'description' => 'is this tag private'], + 'created' => ['type' => 'datetime', 'not null' => true, 'default' => 'CURRENT_TIMESTAMP', 'description' => 'date this record was created'], + 'modified' => ['type' => 'timestamp', 'not null' => true, 'default' => 'CURRENT_TIMESTAMP', 'description' => 'date this record was modified'], ], 'primary key' => ['id'], 'indexes' => [