diff --git a/boot.php b/boot.php index 0637ff3fe..a070e103e 100644 --- a/boot.php +++ b/boot.php @@ -33,7 +33,6 @@ use Friendica\Database\DBA; use Friendica\DI; use Friendica\Model\Contact; use Friendica\Model\Notify; -use Friendica\Model\Term; use Friendica\Util\BasePath; use Friendica\Util\DateTimeFormat; diff --git a/include/conversation.php b/include/conversation.php index 43eeb9e41..5d08fd692 100644 --- a/include/conversation.php +++ b/include/conversation.php @@ -22,7 +22,6 @@ use Friendica\App; use Friendica\Content\ContactSelector; use Friendica\Content\Feature; -use Friendica\Content\Pager; use Friendica\Content\Text\BBCode; use Friendica\Core\Hook; use Friendica\Core\Logger; @@ -34,7 +33,7 @@ use Friendica\DI; use Friendica\Model\Contact; use Friendica\Model\Item; use Friendica\Model\Profile; -use Friendica\Model\Term; +use Friendica\Model\Tag; use Friendica\Object\Post; use Friendica\Object\Thread; use Friendica\Protocol\Activity; @@ -527,7 +526,7 @@ function conversation(App $a, array $items, $mode, $update, $preview = false, $o $profile_name = $item['author-link']; } - $tags = Term::populateTagsFromItem($item); + $tags = Tag::populateTagsFromItem($item); $author = ['uid' => 0, 'id' => $item['author-id'], 'network' => $item['author-network'], 'url' => $item['author-link']]; diff --git a/src/Model/Tag.php b/src/Model/Tag.php index cf453f243..1186602f5 100644 --- a/src/Model/Tag.php +++ b/src/Model/Tag.php @@ -25,6 +25,7 @@ use Friendica\Content\Text\BBCode; use Friendica\Core\Logger; use Friendica\Core\System; use Friendica\Database\DBA; +use Friendica\DI; use Friendica\Util\Strings; /** @@ -221,6 +222,17 @@ class Tag } } + /** + * Checks for stored hashtags and mentions for the given post + * + * @param integer $uriid + * @return bool + */ + public static function existsForPost(int $uriid) + { + return DBA::exists('post-tag', ['uri-id' => $uriid, 'type' => [self::HASHTAG, self::MENTION, self::IMPLICIT_MENTION, self::EXCLUSIVE_MENTION]]); + } + /** * Remove tag/mention * @@ -282,6 +294,86 @@ class Tag } else { return self::UNKNOWN; } - } + + /** + * Retrieves the terms from the provided type(s) associated with the provided item ID. + * + * @param int $item_id + * @param int|array $type + * @return array + * @throws \Exception + */ + public static function ArrayFromURIId(int $uri_id, array $type = [self::HASHTAG, self::MENTION, self::IMPLICIT_MENTION, self::EXCLUSIVE_MENTION]) + { + $condition = ['uri-id' => $uri_id, 'type' => $type]; + $tags = DBA::select('tag-view', ['type', 'name', 'url'], $condition); + if (!DBA::isResult($tags)) { + return []; + } + + $tag_list = []; + while ($tag = DBA::fetch($tags)) { + $tag['term'] = $tag['name']; /// @todo Remove this line when all occurrences of "term" had been replaced with "name" + $tag_list[] = $tag; + } + + return $tag_list; + } + + /** + * Sorts an item's tags into mentions, hashtags and other tags. Generate personalized URLs by user and modify the + * provided item's body with them. + * + * @param array $item + * @return array + * @throws \Friendica\Network\HTTPException\InternalServerErrorException + * @throws \ImagickException + */ + public static function populateTagsFromItem(&$item) + { + $return = [ + 'tags' => [], + 'hashtags' => [], + 'mentions' => [], + 'implicit_mentions' => [], + ]; + + $searchpath = DI::baseUrl() . "/search?tag="; + + $taglist = DBA::select('tag-view', ['type', 'name', 'url'], + ['uri-id' => $item['uri-id'], 'type' => [self::HASHTAG, self::MENTION, self::EXCLUSIVE_MENTION, self::IMPLICIT_MENTION]]); + while ($tag = DBA::fetch($taglist)) { + if ($tag['url'] == '') { + $tag['url'] = $searchpath . rawurlencode($tag['name']); + } + + $orig_tag = $tag['url']; + + $prefix = self::TAG_CHARACTER[$tag['type']]; + switch($tag['type']) { + case self::HASHTAG: + if ($orig_tag != $tag['url']) { + $item['body'] = str_replace($orig_tag, $tag['url'], $item['body']); + } + + $return['hashtags'][] = $prefix . '' . htmlspecialchars($tag['name']) . ''; + $return['tags'][] = $prefix . '' . htmlspecialchars($tag['name']) . ''; + break; + case self::MENTION: + case self::EXCLUSIVE_MENTION: + $tag['url'] = Contact::magicLink($tag['url']); + $return['mentions'][] = $prefix . '' . htmlspecialchars($tag['name']) . ''; + $return['tags'][] = $prefix . '' . htmlspecialchars($tag['name']) . ''; + break; + case self::IMPLICIT_MENTION: + $return['implicit_mentions'][] = $prefix . $tag['name']; + break; + } + } + DBA::close($taglist); + + return $return; + } + } diff --git a/src/Model/Term.php b/src/Model/Term.php index 13639f770..a6858d841 100644 --- a/src/Model/Term.php +++ b/src/Model/Term.php @@ -89,8 +89,8 @@ class Term ORDER BY `score` DESC LIMIT ?", Item::PUBLIC, - Term::OBJECT_TYPE_POST, - Term::HASHTAG, + self::OBJECT_TYPE_POST, + self::HASHTAG, $period, $limit ); @@ -134,8 +134,8 @@ class Term ORDER BY `score` DESC LIMIT ?", Item::PUBLIC, - Term::OBJECT_TYPE_POST, - Term::HASHTAG, + self::OBJECT_TYPE_POST, + self::HASHTAG, $period, $limit ); @@ -424,64 +424,6 @@ class Term } } - /** - * Sorts an item's tags into mentions, hashtags and other tags. Generate personalized URLs by user and modify the - * provided item's body with them. - * - * @param array $item - * @return array - * @throws \Friendica\Network\HTTPException\InternalServerErrorException - * @throws \ImagickException - */ - public static function populateTagsFromItem(&$item) - { - $return = [ - 'tags' => [], - 'hashtags' => [], - 'mentions' => [], - 'implicit_mentions' => [], - ]; - - $searchpath = DI::baseUrl() . "/search?tag="; - - $taglist = DBA::select( - 'term', - ['type', 'term', 'url'], - ['otype' => self::OBJECT_TYPE_POST, 'oid' => $item['id'], 'type' => [self::HASHTAG, self::MENTION, self::IMPLICIT_MENTION]], - ['order' => ['tid']] - ); - while ($tag = DBA::fetch($taglist)) { - if ($tag['url'] == '') { - $tag['url'] = $searchpath . rawurlencode($tag['term']); - } - - $orig_tag = $tag['url']; - - $prefix = self::TAG_CHARACTER[$tag['type']]; - switch($tag['type']) { - case self::HASHTAG: - if ($orig_tag != $tag['url']) { - $item['body'] = str_replace($orig_tag, $tag['url'], $item['body']); - } - - $return['hashtags'][] = $prefix . '' . htmlspecialchars($tag['term']) . ''; - $return['tags'][] = $prefix . '' . htmlspecialchars($tag['term']) . ''; - break; - case self::MENTION: - $tag['url'] = Contact::magicLink($tag['url']); - $return['mentions'][] = $prefix . '' . htmlspecialchars($tag['term']) . ''; - $return['tags'][] = $prefix . '' . htmlspecialchars($tag['term']) . ''; - break; - case self::IMPLICIT_MENTION: - $return['implicit_mentions'][] = $prefix . $tag['term']; - break; - } - } - DBA::close($taglist); - - return $return; - } - /** * Delete tags of the specific type(s) from an item * diff --git a/src/Module/Profile/Profile.php b/src/Module/Profile/Profile.php index 6c7f4f14e..c187281d3 100644 --- a/src/Module/Profile/Profile.php +++ b/src/Module/Profile/Profile.php @@ -35,7 +35,7 @@ use Friendica\Database\DBA; use Friendica\DI; use Friendica\Model\Contact; use Friendica\Model\Profile as ProfileModel; -use Friendica\Model\Term; +use Friendica\Model\Tag; use Friendica\Model\User; use Friendica\Module\BaseProfile; use Friendica\Module\Security\Login; @@ -184,7 +184,7 @@ class Profile extends BaseProfile foreach (explode(',', $a->profile['pub_keywords']) as $tag_label) { $tags[] = [ 'url' => '/search?tag=' . $tag_label, - 'label' => Term::TAG_CHARACTER[Term::HASHTAG] . $tag_label, + 'label' => Tag::TAG_CHARACTER[Tag::HASHTAG] . $tag_label, ]; } diff --git a/src/Object/Post.php b/src/Object/Post.php index 76cf6b036..99ab357bc 100644 --- a/src/Object/Post.php +++ b/src/Object/Post.php @@ -33,7 +33,7 @@ use Friendica\Database\DBA; use Friendica\DI; use Friendica\Model\Contact; use Friendica\Model\Item; -use Friendica\Model\Term; +use Friendica\Model\Tag; use Friendica\Model\User; use Friendica\Protocol\Activity; use Friendica\Util\Crypto; @@ -390,7 +390,7 @@ class Post $buttons["like"] = false; } - $tags = Term::populateTagsFromItem($item); + $tags = Tag::populateTagsFromItem($item); $ago = Temporal::getRelativeDate($item['created']); $ago_received = Temporal::getRelativeDate($item['received']); @@ -860,7 +860,7 @@ class Post return ''; } - $item = Item::selectFirst(['author-addr'], ['id' => $this->getId()]); + $item = Item::selectFirst(['author-addr', 'uri-id'], ['id' => $this->getId()]); if (!DBA::isResult($item) || empty($item['author-addr'])) { // Should not happen return ''; @@ -872,7 +872,7 @@ class Post $text = ''; } - $terms = Term::tagArrayFromItemId($this->getId(), [Term::MENTION, Term::IMPLICIT_MENTION]); + $terms = Tag::ArrayFromURIId($item['uri-id'], [Tag::MENTION, Tag::IMPLICIT_MENTION, Tag::EXCLUSIVE_MENTION]); foreach ($terms as $term) { $profile = Contact::getDetailsByURL($term['url']); if (!empty($profile['addr']) && ((($profile['contact-type'] ?? '') ?: Contact::TYPE_UNKNOWN) != Contact::TYPE_COMMUNITY) && diff --git a/src/Protocol/ActivityPub/Processor.php b/src/Protocol/ActivityPub/Processor.php index 786022343..80b2b0dba 100644 --- a/src/Protocol/ActivityPub/Processor.php +++ b/src/Protocol/ActivityPub/Processor.php @@ -35,7 +35,6 @@ use Friendica\Model\Item; use Friendica\Model\ItemURI; use Friendica\Model\Mail; use Friendica\Model\Tag; -use Friendica\Model\Term; use Friendica\Model\User; use Friendica\Protocol\Activity; use Friendica\Protocol\ActivityPub; @@ -1016,7 +1015,7 @@ class Processor return []; } - $parent_terms = Term::tagArrayFromItemId($parent['id'], [Term::MENTION, Term::IMPLICIT_MENTION]); + $parent_terms = Tag::ArrayFromURIId($parent['uri-id'], [Tag::MENTION, Tag::IMPLICIT_MENTION, Tag::EXCLUSIVE_MENTION]); $parent_author = Contact::getDetailsByURL($parent['author-link'], 0); @@ -1084,8 +1083,8 @@ class Processor foreach ($activity_tags as $index => $tag) { if (in_array($tag['href'], $potential_mentions)) { $activity_tags[$index]['name'] = preg_replace( - '/' . preg_quote(Term::TAG_CHARACTER[Term::MENTION], '/') . '/', - Term::TAG_CHARACTER[Term::IMPLICIT_MENTION], + '/' . preg_quote(Tag::TAG_CHARACTER[Tag::MENTION], '/') . '/', + Tag::TAG_CHARACTER[Tag::IMPLICIT_MENTION], $activity_tags[$index]['name'], 1 ); diff --git a/src/Protocol/ActivityPub/Transmitter.php b/src/Protocol/ActivityPub/Transmitter.php index e35d83361..89453735a 100644 --- a/src/Protocol/ActivityPub/Transmitter.php +++ b/src/Protocol/ActivityPub/Transmitter.php @@ -36,7 +36,7 @@ use Friendica\Model\Conversation; use Friendica\Model\Item; use Friendica\Model\Profile; use Friendica\Model\Photo; -use Friendica\Model\Term; +use Friendica\Model\Tag; use Friendica\Model\User; use Friendica\Protocol\Activity; use Friendica\Protocol\ActivityPub; @@ -405,7 +405,7 @@ class Transmitter $actor_profile = APContact::getByURL($item['author-link']); } - $terms = Term::tagArrayFromItemId($item['id'], [Term::MENTION, Term::IMPLICIT_MENTION]); + $terms = Tag::ArrayFromURIId($item['uri-id'], [Tag::MENTION, Tag::IMPLICIT_MENTION, Tag::EXCLUSIVE_MENTION]); if ($item['private'] != Item::PRIVATE) { // Directly mention the original author upon a quoted reshare. @@ -1007,12 +1007,12 @@ class Transmitter { $tags = []; - $terms = Term::tagArrayFromItemId($item['id'], [Term::HASHTAG, Term::MENTION, Term::IMPLICIT_MENTION]); + $terms = Tag::ArrayFromURIId($item['uri-id'], [Tag::HASHTAG, Tag::MENTION, Tag::IMPLICIT_MENTION, Tag::EXCLUSIVE_MENTION]); foreach ($terms as $term) { - if ($term['type'] == Term::HASHTAG) { + if ($term['type'] == Tag::HASHTAG) { $url = DI::baseUrl() . '/search?tag=' . urlencode($term['term']); $tags[] = ['type' => 'Hashtag', 'href' => $url, 'name' => '#' . $term['term']]; - } elseif ($term['type'] == Term::MENTION || $term['type'] == Term::IMPLICIT_MENTION) { + } else { $contact = Contact::getDetailsByURL($term['url']); if (!empty($contact['addr'])) { $mention = '@' . $contact['addr']; @@ -1211,15 +1211,14 @@ class Transmitter /** * Returns if the post contains sensitive content ("nsfw") * - * @param integer $item_id + * @param integer $uri_id * * @return boolean * @throws \Exception */ - private static function isSensitive($item_id) + private static function isSensitive($uri_id) { - $condition = ['otype' => Term::OBJECT_TYPE_POST, 'oid' => $item_id, 'type' => Term::HASHTAG, 'term' => 'nsfw']; - return DBA::exists('term', $condition); + return DBA::exists('tag-view', ['uri-id' => $uri_id, 'name' => 'nsfw']); } /** @@ -1301,7 +1300,7 @@ class Transmitter $data['url'] = $item['plink']; $data['attributedTo'] = $item['author-link']; - $data['sensitive'] = self::isSensitive($item['id']); + $data['sensitive'] = self::isSensitive($item['uri-id']); $data['context'] = self::fetchContextURLForItem($item); if (!empty($item['title'])) { diff --git a/src/Protocol/Diaspora.php b/src/Protocol/Diaspora.php index fe6c328d9..0cefb8def 100644 --- a/src/Protocol/Diaspora.php +++ b/src/Protocol/Diaspora.php @@ -38,9 +38,7 @@ use Friendica\Model\Item; use Friendica\Model\ItemURI; use Friendica\Model\ItemDeliveryData; use Friendica\Model\Mail; -use Friendica\Model\Profile; use Friendica\Model\Tag; -use Friendica\Model\Term; use Friendica\Model\User; use Friendica\Network\Probe; use Friendica\Util\Crypto; @@ -114,7 +112,7 @@ class Diaspora if (DI::config()->get("system", "relay_directly", false)) { // We distribute our stuff based on the parent to ensure that the thread will be complete - $parent = Item::selectFirst(['parent'], ['id' => $item_id]); + $parent = Item::selectFirst(['uri-id'], ['id' => $item_id]); if (!DBA::isResult($parent)) { return; } @@ -126,12 +124,12 @@ class Diaspora } // All tags of the current post - $condition = ['otype' => Term::OBJECT_TYPE_POST, 'type' => Term::HASHTAG, 'oid' => $parent['parent']]; - $tags = DBA::select('term', ['term'], $condition); + $tags = DBA::select('tag-view', ['term'], ['uri-id' => $parent['uri-id'], 'type' => Tag::HASHTAG]); $taglist = []; while ($tag = DBA::fetch($tags)) { - $taglist[] = $tag['term']; + $taglist[] = $tag['name']; } + DBA::close($tags); // All servers who wants content with this tag $tagserverlist = [];