[TAGS] Fix some minor logic issues with Actor Tags and Circles
This commit is contained in:
parent
a9feb79825
commit
ed67da89dc
@ -68,7 +68,7 @@ class RelatedTags extends Plugin
|
|||||||
'related-actor-tags-' . implode('-', $tags),
|
'related-actor-tags-' . implode('-', $tags),
|
||||||
fn () => DB::sql(
|
fn () => DB::sql(
|
||||||
<<<'EOQ'
|
<<<'EOQ'
|
||||||
select distinct on (at.canonical) canonical, at.tagger, at.tagged, at.tag, at.modified
|
select distinct on (at.canonical) canonical, at.tagger, at.tagged, at.tag, at.use_canonical, at.modified
|
||||||
from actor_tag at
|
from actor_tag at
|
||||||
where at.tagged in (select at.tagged from actor_tag at where at.canonical in (:tags))
|
where at.tagged in (select at.tagged from actor_tag at where at.canonical in (:tags))
|
||||||
and not at.canonical in (:tags)
|
and not at.canonical in (:tags)
|
||||||
|
@ -378,16 +378,14 @@ class Actor extends Entity
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param array $tags array of strings to become self tags
|
* @param array $tags array of strings to become self tags
|
||||||
* @param null|array $existing array of existing self tags (ActorTag[])
|
* @param null|array $existing array of existing self tags (ActorTag[])
|
||||||
*
|
*
|
||||||
* @throws \App\Util\Exception\DuplicateFoundException
|
|
||||||
* @throws NotFoundException
|
|
||||||
*
|
|
||||||
* @return $this
|
* @return $this
|
||||||
*/
|
*/
|
||||||
public function setSelfTags(array $tags, ?array $existing = null): self
|
public function setSelfTags(array $tags, ?array $existing = null): self
|
||||||
{
|
{
|
||||||
|
$tags = F\filter($tags, fn ($tag) => Nickname::isCanonical($tag)); // TODO: Have an actual #Tag test
|
||||||
$tags = array_unique($tags);
|
$tags = array_unique($tags);
|
||||||
if (\is_null($existing)) {
|
if (\is_null($existing)) {
|
||||||
[$_, $existing] = $this->getSelfTags();
|
[$_, $existing] = $this->getSelfTags();
|
||||||
@ -398,13 +396,12 @@ class Actor extends Entity
|
|||||||
$actor_tags_to_remove = F\filter($existing, fn ($actor_tag) => \in_array($actor_tag->getTag(), $tags_to_remove));
|
$actor_tags_to_remove = F\filter($existing, fn ($actor_tag) => \in_array($actor_tag->getTag(), $tags_to_remove));
|
||||||
foreach ($tags_to_add as $tag) {
|
foreach ($tags_to_add as $tag) {
|
||||||
$canonical_tag = TagComponent::canonicalTag($tag, $this->getTopLanguage()->getLocale());
|
$canonical_tag = TagComponent::canonicalTag($tag, $this->getTopLanguage()->getLocale());
|
||||||
DB::persist(ActorCircle::create(['tagger' => $this->getId(), 'tag' => $canonical_tag, 'private' => false]));
|
DB::persist(ActorCircle::create(['tagger' => $this->getId(), 'tag' => $tag, 'private' => false]));
|
||||||
DB::persist(ActorTag::create(['tagger' => $this->id, 'tagged' => $this->id, 'tag' => $tag, 'canonical' => $canonical_tag, 'use_canonical' => true])); // TODO make use canonical configurable
|
DB::persist(ActorTag::create(['tagger' => $this->id, 'tagged' => $this->id, 'tag' => $tag, 'canonical' => $canonical_tag, 'use_canonical' => false])); // TODO make use canonical configurable
|
||||||
}
|
}
|
||||||
foreach ($actor_tags_to_remove as $actor_tag) {
|
foreach ($actor_tags_to_remove as $actor_tag) {
|
||||||
$canonical_tag = TagComponent::canonicalTag($actor_tag->getTag(), $this->getTopLanguage()->getLocale());
|
DB::removeBy('actor_tag', ['tagger' => $this->getId(), 'tagged' => $this->getId(), 'tag' => $actor_tag->getTag(), 'use_canonical' => $actor_tag->getUseCanonical()]);
|
||||||
DB::removeBy('actor_tag', ['tagger' => $this->getId(), 'tagged' => $this->getId(), 'canonical' => $canonical_tag]);
|
DB::removeBy('actor_circle', ['tagger' => $this->getId(), 'tag' => $actor_tag->getTag()]); // TODO only remove if unused
|
||||||
DB::removeBy('actor_circle', ['tagger' => $this->getId(), 'tag' => $canonical_tag]); // TODO only remove if unused
|
|
||||||
}
|
}
|
||||||
Cache::delete(self::cacheKeys($this->getId())['tags']);
|
Cache::delete(self::cacheKeys($this->getId())['tags']);
|
||||||
Cache::delete(self::cacheKeys($this->getId(), $this->getId())['tags']);
|
Cache::delete(self::cacheKeys($this->getId(), $this->getId())['tags']);
|
||||||
|
@ -28,6 +28,8 @@ use DateTimeInterface;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Entity for List of actors
|
* Entity for List of actors
|
||||||
|
* This entity only makes sense when considered together with the ActorTag one.
|
||||||
|
* Because, every circle entry will be an ActorTag.
|
||||||
*
|
*
|
||||||
* @category DB
|
* @category DB
|
||||||
* @package GNUsocial
|
* @package GNUsocial
|
||||||
@ -166,8 +168,10 @@ class ActorCircle extends Entity
|
|||||||
'description' => 'a actor can have lists of actors, to separate their feed',
|
'description' => 'a actor can have lists of actors, to separate their feed',
|
||||||
'fields' => [
|
'fields' => [
|
||||||
'id' => ['type' => 'serial', 'not null' => true, 'description' => 'unique identifier'],
|
'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'],
|
'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'],
|
||||||
'tag' => ['type' => 'varchar', 'length' => 64, 'foreign key' => true, 'target' => 'ActorTag.canonical', '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
|
||||||
|
'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'],
|
'description' => ['type' => 'text', 'description' => 'description of the people tag'],
|
||||||
'private' => ['type' => 'bool', 'default' => false, 'description' => 'is this tag private'],
|
'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'],
|
'created' => ['type' => 'datetime', 'not null' => true, 'default' => 'CURRENT_TIMESTAMP', 'description' => 'date this record was created'],
|
||||||
|
@ -24,6 +24,8 @@ use DateTimeInterface;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Entity for actor circle subscriptions
|
* Entity for actor circle subscriptions
|
||||||
|
* This entity only makes sense when considered with the ActorCircle entity.
|
||||||
|
* Because you can only subscribe a Circle that exists.
|
||||||
*
|
*
|
||||||
* @category DB
|
* @category DB
|
||||||
* @package GNUsocial
|
* @package GNUsocial
|
||||||
@ -96,10 +98,11 @@ class ActorCircleSubscription extends Entity
|
|||||||
public static function schemaDef(): array
|
public static function schemaDef(): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'name' => 'actor_tag_subscription',
|
'name' => 'actor_circle_subscription',
|
||||||
'fields' => [
|
'fields' => [
|
||||||
'actor_id' => ['type' => 'int', 'foreign key' => true, 'target' => 'Actor.id', 'multiplicity' => 'one to one', 'name' => 'actor_circle_subscription_actor_id_fkey', 'not null' => true, 'description' => 'foreign key to actor table'],
|
'actor_id' => ['type' => 'int', 'foreign key' => true, 'target' => 'Actor.id', 'multiplicity' => 'one to one', 'name' => 'actor_circle_subscription_actor_id_fkey', 'not null' => true, 'description' => 'foreign key to actor table'],
|
||||||
'circle_id' => ['type' => 'int', 'foreign key' => true, 'target' => 'ActorCircle.id', 'multiplicity' => 'one to one', 'name' => 'actor_circle_subscription_actor_circle_fkey', 'not null' => true, 'description' => 'foreign key to actor_circle'],
|
// An actor subscribes many circles; A Circle is subscribed by many actors.
|
||||||
|
'circle_id' => ['type' => 'int', 'foreign key' => true, 'target' => 'ActorCircle.id', 'multiplicity' => 'one to many', 'name' => 'actor_circle_subscription_actor_circle_fkey', 'not null' => true, 'description' => 'foreign key to actor_circle'],
|
||||||
'created' => ['type' => 'datetime', 'not null' => true, 'default' => 'CURRENT_TIMESTAMP', 'description' => 'date this record was created'],
|
'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'],
|
'modified' => ['type' => 'timestamp', 'not null' => true, 'default' => 'CURRENT_TIMESTAMP', 'description' => 'date this record was modified'],
|
||||||
],
|
],
|
||||||
|
@ -30,6 +30,10 @@ use DateTimeInterface;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Entity for Actor Tag
|
* Entity for Actor Tag
|
||||||
|
* This entity represents the relationship between an Actor and a Tag.
|
||||||
|
* That relationship works as follows:
|
||||||
|
* An Actor A tags an Actor B (which can be A - a self tag).
|
||||||
|
* For every tagging that happens between two actors, a new ActorTag is born.
|
||||||
*
|
*
|
||||||
* @category DB
|
* @category DB
|
||||||
* @package GNUsocial
|
* @package GNUsocial
|
||||||
@ -39,6 +43,7 @@ use DateTimeInterface;
|
|||||||
* @author Mikael Nordfeldth <mmn@hethane.se>
|
* @author Mikael Nordfeldth <mmn@hethane.se>
|
||||||
* @copyright 2009-2014 Free Software Foundation, Inc http://www.fsf.org
|
* @copyright 2009-2014 Free Software Foundation, Inc http://www.fsf.org
|
||||||
* @author Hugo Sales <hugo@hsal.es>
|
* @author Hugo Sales <hugo@hsal.es>
|
||||||
|
* @author Diogo Peralta Cordeiro <@diogo.site>
|
||||||
* @copyright 2020-2021 Free Software Foundation, Inc http://www.fsf.org
|
* @copyright 2020-2021 Free Software Foundation, Inc http://www.fsf.org
|
||||||
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
|
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
|
||||||
*/
|
*/
|
||||||
@ -156,10 +161,10 @@ class ActorTag extends Entity
|
|||||||
'use_canonical' => ['type' => 'bool', 'not null' => true, 'description' => 'whether the user wanted to block canonical tags'],
|
'use_canonical' => ['type' => 'bool', 'not null' => true, 'description' => 'whether the user wanted to block canonical tags'],
|
||||||
'modified' => ['type' => 'timestamp', 'not null' => true, 'default' => 'CURRENT_TIMESTAMP', 'description' => 'date this record was modified'],
|
'modified' => ['type' => 'timestamp', 'not null' => true, 'default' => 'CURRENT_TIMESTAMP', 'description' => 'date this record was modified'],
|
||||||
],
|
],
|
||||||
'primary key' => ['tagger', 'tagged', 'canonical'],
|
'primary key' => ['tagger', 'tagged', 'tag', 'use_canonical'],
|
||||||
'indexes' => [
|
'indexes' => [
|
||||||
'actor_tag_modified_idx' => ['modified'],
|
'actor_tag_modified_idx' => ['modified'],
|
||||||
'actor_tag_tagger_canonical_idx' => ['tagger', 'canonical'], // For Circles
|
'actor_tag_tagger_tag_idx' => ['tagger', 'tag'], // For Circles
|
||||||
'actor_tag_tagged_idx' => ['tagged'],
|
'actor_tag_tagged_idx' => ['tagged'],
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
|
Loading…
Reference in New Issue
Block a user