Merge pull request #8566 from annando/write-tags
From "term" to "tag" - We are now using "tag" where appropriate
This commit is contained in:
commit
92cf4879e5
25 changed files with 455 additions and 308 deletions
1
boot.php
1
boot.php
|
@ -33,7 +33,6 @@ use Friendica\Database\DBA;
|
||||||
use Friendica\DI;
|
use Friendica\DI;
|
||||||
use Friendica\Model\Contact;
|
use Friendica\Model\Contact;
|
||||||
use Friendica\Model\Notify;
|
use Friendica\Model\Notify;
|
||||||
use Friendica\Model\Term;
|
|
||||||
use Friendica\Util\BasePath;
|
use Friendica\Util\BasePath;
|
||||||
use Friendica\Util\DateTimeFormat;
|
use Friendica\Util\DateTimeFormat;
|
||||||
|
|
||||||
|
|
|
@ -41,7 +41,6 @@ use Friendica\Model\Item;
|
||||||
use Friendica\Model\Mail;
|
use Friendica\Model\Mail;
|
||||||
use Friendica\Model\Notify;
|
use Friendica\Model\Notify;
|
||||||
use Friendica\Model\Photo;
|
use Friendica\Model\Photo;
|
||||||
use Friendica\Model\Term;
|
|
||||||
use Friendica\Model\User;
|
use Friendica\Model\User;
|
||||||
use Friendica\Model\UserItem;
|
use Friendica\Model\UserItem;
|
||||||
use Friendica\Network\FKOAuth1;
|
use Friendica\Network\FKOAuth1;
|
||||||
|
@ -1539,31 +1538,24 @@ function api_search($type)
|
||||||
$params = ['order' => ['id' => true], 'limit' => [$start, $count]];
|
$params = ['order' => ['id' => true], 'limit' => [$start, $count]];
|
||||||
if (preg_match('/^#(\w+)$/', $searchTerm, $matches) === 1 && isset($matches[1])) {
|
if (preg_match('/^#(\w+)$/', $searchTerm, $matches) === 1 && isset($matches[1])) {
|
||||||
$searchTerm = $matches[1];
|
$searchTerm = $matches[1];
|
||||||
$condition = ["`oid` > ?
|
$condition = ["`iid` > ? AND `name` = ? AND (NOT `private` OR (`private` AND `uid` = ?))", $since_id, $searchTerm, local_user()];
|
||||||
AND (`uid` = 0 OR (`uid` = ? AND NOT `global`))
|
$tags = DBA::select('tag-search-view', ['uri-id'], $condition);
|
||||||
AND `otype` = ? AND `type` = ? AND `term` = ?",
|
$uriids = [];
|
||||||
$since_id, local_user(), Term::OBJECT_TYPE_POST, Term::HASHTAG, $searchTerm];
|
while ($tag = DBA::fetch($tags)) {
|
||||||
if ($max_id > 0) {
|
$uriids[] = $tag['uri-id'];
|
||||||
$condition[0] .= ' AND `oid` <= ?';
|
|
||||||
$condition[] = $max_id;
|
|
||||||
}
|
}
|
||||||
$terms = DBA::select('term', ['oid'], $condition, []);
|
DBA::close($tags);
|
||||||
$itemIds = [];
|
|
||||||
while ($term = DBA::fetch($terms)) {
|
|
||||||
$itemIds[] = $term['oid'];
|
|
||||||
}
|
|
||||||
DBA::close($terms);
|
|
||||||
|
|
||||||
if (empty($itemIds)) {
|
if (empty($uriids)) {
|
||||||
return api_format_data('statuses', $type, $data);
|
return api_format_data('statuses', $type, $data);
|
||||||
}
|
}
|
||||||
|
|
||||||
$preCondition = ['`id` IN (' . implode(', ', $itemIds) . ')'];
|
$condition = ['uri-id' => $uriids];
|
||||||
if ($exclude_replies) {
|
if ($exclude_replies) {
|
||||||
$preCondition[] = '`id` = `parent`';
|
$condition['gravity'] = GRAVITY_PARENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
$condition = [implode(' AND ', $preCondition)];
|
$params['group_by'] = ['uri-id'];
|
||||||
} else {
|
} else {
|
||||||
$condition = ["`id` > ?
|
$condition = ["`id` > ?
|
||||||
" . ($exclude_replies ? " AND `id` = `parent` " : ' ') . "
|
" . ($exclude_replies ? " AND `id` = `parent` " : ' ') . "
|
||||||
|
|
|
@ -22,7 +22,6 @@
|
||||||
use Friendica\App;
|
use Friendica\App;
|
||||||
use Friendica\Content\ContactSelector;
|
use Friendica\Content\ContactSelector;
|
||||||
use Friendica\Content\Feature;
|
use Friendica\Content\Feature;
|
||||||
use Friendica\Content\Pager;
|
|
||||||
use Friendica\Content\Text\BBCode;
|
use Friendica\Content\Text\BBCode;
|
||||||
use Friendica\Core\Hook;
|
use Friendica\Core\Hook;
|
||||||
use Friendica\Core\Logger;
|
use Friendica\Core\Logger;
|
||||||
|
@ -34,7 +33,7 @@ use Friendica\DI;
|
||||||
use Friendica\Model\Contact;
|
use Friendica\Model\Contact;
|
||||||
use Friendica\Model\Item;
|
use Friendica\Model\Item;
|
||||||
use Friendica\Model\Profile;
|
use Friendica\Model\Profile;
|
||||||
use Friendica\Model\Term;
|
use Friendica\Model\Tag;
|
||||||
use Friendica\Object\Post;
|
use Friendica\Object\Post;
|
||||||
use Friendica\Object\Thread;
|
use Friendica\Object\Thread;
|
||||||
use Friendica\Protocol\Activity;
|
use Friendica\Protocol\Activity;
|
||||||
|
@ -527,7 +526,7 @@ function conversation(App $a, array $items, $mode, $update, $preview = false, $o
|
||||||
$profile_name = $item['author-link'];
|
$profile_name = $item['author-link'];
|
||||||
}
|
}
|
||||||
|
|
||||||
$tags = Term::populateTagsFromItem($item);
|
$tags = Tag::populateFromItem($item);
|
||||||
|
|
||||||
$author = ['uid' => 0, 'id' => $item['author-id'],
|
$author = ['uid' => 0, 'id' => $item['author-id'],
|
||||||
'network' => $item['author-network'], 'url' => $item['author-link']];
|
'network' => $item['author-network'], 'url' => $item['author-link']];
|
||||||
|
|
28
mod/item.php
28
mod/item.php
|
@ -29,7 +29,6 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use Friendica\App;
|
use Friendica\App;
|
||||||
use Friendica\Content\Pager;
|
|
||||||
use Friendica\Content\Text\BBCode;
|
use Friendica\Content\Text\BBCode;
|
||||||
use Friendica\Core\Hook;
|
use Friendica\Core\Hook;
|
||||||
use Friendica\Core\Logger;
|
use Friendica\Core\Logger;
|
||||||
|
@ -47,7 +46,6 @@ use Friendica\Model\Item;
|
||||||
use Friendica\Model\Notify\Type;
|
use Friendica\Model\Notify\Type;
|
||||||
use Friendica\Model\Photo;
|
use Friendica\Model\Photo;
|
||||||
use Friendica\Model\Tag;
|
use Friendica\Model\Tag;
|
||||||
use Friendica\Model\Term;
|
|
||||||
use Friendica\Network\HTTPException;
|
use Friendica\Network\HTTPException;
|
||||||
use Friendica\Object\EMail\ItemCCEMail;
|
use Friendica\Object\EMail\ItemCCEMail;
|
||||||
use Friendica\Protocol\Activity;
|
use Friendica\Protocol\Activity;
|
||||||
|
@ -102,7 +100,7 @@ function item_post(App $a) {
|
||||||
$toplevel_item_id = intval($_REQUEST['parent'] ?? 0);
|
$toplevel_item_id = intval($_REQUEST['parent'] ?? 0);
|
||||||
$thr_parent_uri = trim($_REQUEST['parent_uri'] ?? '');
|
$thr_parent_uri = trim($_REQUEST['parent_uri'] ?? '');
|
||||||
|
|
||||||
$thread_parent_id = 0;
|
$thread_parent_uriid = 0;
|
||||||
$thread_parent_contact = null;
|
$thread_parent_contact = null;
|
||||||
|
|
||||||
$toplevel_item = null;
|
$toplevel_item = null;
|
||||||
|
@ -124,7 +122,7 @@ function item_post(App $a) {
|
||||||
// if this isn't the top-level parent of the conversation, find it
|
// if this isn't the top-level parent of the conversation, find it
|
||||||
if (DBA::isResult($toplevel_item)) {
|
if (DBA::isResult($toplevel_item)) {
|
||||||
// The URI and the contact is taken from the direct parent which needn't to be the top parent
|
// The URI and the contact is taken from the direct parent which needn't to be the top parent
|
||||||
$thread_parent_id = $toplevel_item['id'];
|
$thread_parent_uriid = $toplevel_item['uri-id'];
|
||||||
$thr_parent_uri = $toplevel_item['uri'];
|
$thr_parent_uri = $toplevel_item['uri'];
|
||||||
$thread_parent_contact = Contact::getDetailsByURL($toplevel_item["author-link"]);
|
$thread_parent_contact = Contact::getDetailsByURL($toplevel_item["author-link"]);
|
||||||
|
|
||||||
|
@ -382,8 +380,8 @@ function item_post(App $a) {
|
||||||
|
|
||||||
$tags = BBCode::getTags($body);
|
$tags = BBCode::getTags($body);
|
||||||
|
|
||||||
if ($thread_parent_id && !\Friendica\Content\Feature::isEnabled($uid, 'explicit_mentions')) {
|
if ($thread_parent_uriid && !\Friendica\Content\Feature::isEnabled($uid, 'explicit_mentions')) {
|
||||||
$tags = item_add_implicit_mentions($tags, $thread_parent_contact, $thread_parent_id);
|
$tags = item_add_implicit_mentions($tags, $thread_parent_contact, $thread_parent_uriid);
|
||||||
}
|
}
|
||||||
|
|
||||||
$tagged = [];
|
$tagged = [];
|
||||||
|
@ -396,7 +394,7 @@ function item_post(App $a) {
|
||||||
foreach ($tags as $tag) {
|
foreach ($tags as $tag) {
|
||||||
$tag_type = substr($tag, 0, 1);
|
$tag_type = substr($tag, 0, 1);
|
||||||
|
|
||||||
if ($tag_type == Term::TAG_CHARACTER[Term::HASHTAG]) {
|
if ($tag_type == Tag::TAG_CHARACTER[Tag::HASHTAG]) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -421,9 +419,9 @@ function item_post(App $a) {
|
||||||
$tagged[] = $tag;
|
$tagged[] = $tag;
|
||||||
}
|
}
|
||||||
// When the forum is private or the forum is addressed with a "!" make the post private
|
// When the forum is private or the forum is addressed with a "!" make the post private
|
||||||
if (is_array($success['contact']) && (!empty($success['contact']['prv']) || ($tag_type == Term::TAG_CHARACTER[Term::EXCLUSIVE_MENTION]))) {
|
if (is_array($success['contact']) && (!empty($success['contact']['prv']) || ($tag_type == Tag::TAG_CHARACTER[Tag::EXCLUSIVE_MENTION]))) {
|
||||||
$private_forum = $success['contact']['prv'];
|
$private_forum = $success['contact']['prv'];
|
||||||
$only_to_forum = ($tag_type == Term::TAG_CHARACTER[Term::EXCLUSIVE_MENTION]);
|
$only_to_forum = ($tag_type == Tag::TAG_CHARACTER[Tag::EXCLUSIVE_MENTION]);
|
||||||
$private_id = $success['contact']['id'];
|
$private_id = $success['contact']['id'];
|
||||||
$forum_contact = $success['contact'];
|
$forum_contact = $success['contact'];
|
||||||
} elseif (is_array($success['contact']) && !empty($success['contact']['forum']) &&
|
} elseif (is_array($success['contact']) && !empty($success['contact']['forum']) &&
|
||||||
|
@ -907,7 +905,7 @@ function handle_tag(&$body, &$inform, &$str_tags, $profile_uid, $tag, $network =
|
||||||
$r = null;
|
$r = null;
|
||||||
|
|
||||||
//is it a person tag?
|
//is it a person tag?
|
||||||
if (Term::isType($tag, Term::MENTION, Term::IMPLICIT_MENTION, Term::EXCLUSIVE_MENTION)) {
|
if (Tag::isType($tag, Tag::MENTION, Tag::IMPLICIT_MENTION, Tag::EXCLUSIVE_MENTION)) {
|
||||||
$tag_type = substr($tag, 0, 1);
|
$tag_type = substr($tag, 0, 1);
|
||||||
//is it already replaced?
|
//is it already replaced?
|
||||||
if (strpos($tag, '[url=')) {
|
if (strpos($tag, '[url=')) {
|
||||||
|
@ -1045,12 +1043,12 @@ function handle_tag(&$body, &$inform, &$str_tags, $profile_uid, $tag, $network =
|
||||||
return ['replaced' => $replaced, 'contact' => $contact];
|
return ['replaced' => $replaced, 'contact' => $contact];
|
||||||
}
|
}
|
||||||
|
|
||||||
function item_add_implicit_mentions(array $tags, array $thread_parent_contact, $thread_parent_id)
|
function item_add_implicit_mentions(array $tags, array $thread_parent_contact, $thread_parent_uriid)
|
||||||
{
|
{
|
||||||
if (DI::config()->get('system', 'disable_implicit_mentions')) {
|
if (DI::config()->get('system', 'disable_implicit_mentions')) {
|
||||||
// Add a tag if the parent contact is from ActivityPub or OStatus (This will notify them)
|
// Add a tag if the parent contact is from ActivityPub or OStatus (This will notify them)
|
||||||
if (in_array($thread_parent_contact['network'], [Protocol::OSTATUS, Protocol::ACTIVITYPUB])) {
|
if (in_array($thread_parent_contact['network'], [Protocol::OSTATUS, Protocol::ACTIVITYPUB])) {
|
||||||
$contact = Term::TAG_CHARACTER[Term::MENTION] . '[url=' . $thread_parent_contact['url'] . ']' . $thread_parent_contact['nick'] . '[/url]';
|
$contact = Tag::TAG_CHARACTER[Tag::MENTION] . '[url=' . $thread_parent_contact['url'] . ']' . $thread_parent_contact['nick'] . '[/url]';
|
||||||
if (!stripos(implode($tags), '[url=' . $thread_parent_contact['url'] . ']')) {
|
if (!stripos(implode($tags), '[url=' . $thread_parent_contact['url'] . ']')) {
|
||||||
$tags[] = $contact;
|
$tags[] = $contact;
|
||||||
}
|
}
|
||||||
|
@ -1060,15 +1058,15 @@ function item_add_implicit_mentions(array $tags, array $thread_parent_contact, $
|
||||||
$thread_parent_contact['url'] => $thread_parent_contact['nick']
|
$thread_parent_contact['url'] => $thread_parent_contact['nick']
|
||||||
];
|
];
|
||||||
|
|
||||||
$parent_terms = Term::tagArrayFromItemId($thread_parent_id, [Term::MENTION, Term::IMPLICIT_MENTION]);
|
$parent_terms = Tag::getByURIId($thread_parent_uriid, [Tag::MENTION, Tag::IMPLICIT_MENTION]);
|
||||||
|
|
||||||
foreach ($parent_terms as $parent_term) {
|
foreach ($parent_terms as $parent_term) {
|
||||||
$implicit_mentions[$parent_term['url']] = $parent_term['term'];
|
$implicit_mentions[$parent_term['url']] = $parent_term['name'];
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($implicit_mentions as $url => $label) {
|
foreach ($implicit_mentions as $url => $label) {
|
||||||
if ($url != \Friendica\Model\Profile::getMyURL() && !stripos(implode($tags), '[url=' . $url . ']')) {
|
if ($url != \Friendica\Model\Profile::getMyURL() && !stripos(implode($tags), '[url=' . $url . ']')) {
|
||||||
$tags[] = Term::TAG_CHARACTER[Term::IMPLICIT_MENTION] . '[url=' . $url . ']' . $label . '[/url]';
|
$tags[] = Tag::TAG_CHARACTER[Tag::IMPLICIT_MENTION] . '[url=' . $url . ']' . $label . '[/url]';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -787,14 +787,13 @@ function networkThreadedView(App $a, $update, $parent)
|
||||||
}
|
}
|
||||||
|
|
||||||
$items = DBA::p("SELECT `item`.`parent-uri` AS `uri`, 0 AS `item_id`, `item`.$ordering AS `order_date`, `author`.`url` AS `author-link` FROM `item`
|
$items = DBA::p("SELECT `item`.`parent-uri` AS `uri`, 0 AS `item_id`, `item`.$ordering AS `order_date`, `author`.`url` AS `author-link` FROM `item`
|
||||||
STRAIGHT_JOIN (SELECT `oid` FROM `term` WHERE `term` IN
|
STRAIGHT_JOIN (SELECT `uri-id` FROM `tag-search-view` WHERE `name` IN
|
||||||
(SELECT SUBSTR(`term`, 2) FROM `search` WHERE `uid` = ? AND `term` LIKE '#%') AND `otype` = ? AND `type` = ? AND `uid` = 0) AS `term`
|
(SELECT SUBSTR(`term`, 2) FROM `search` WHERE `uid` = ? AND `term` LIKE '#%') AND `uid` = 0) AS `tag-search`
|
||||||
ON `item`.`id` = `term`.`oid`
|
ON `item`.`uri-id` = `tag-search`.`uri-id`
|
||||||
STRAIGHT_JOIN `contact` AS `author` ON `author`.`id` = `item`.`author-id`
|
STRAIGHT_JOIN `contact` AS `author` ON `author`.`id` = `item`.`author-id`
|
||||||
WHERE `item`.`uid` = 0 AND `item`.$ordering < ? AND `item`.$ordering > ? AND `item`.`gravity` = ?
|
WHERE `item`.`uid` = 0 AND `item`.$ordering < ? AND `item`.$ordering > ? AND `item`.`gravity` = ?
|
||||||
AND NOT `author`.`hidden` AND NOT `author`.`blocked`" . $sql_tag_nets,
|
AND NOT `author`.`hidden` AND NOT `author`.`blocked`" . $sql_tag_nets,
|
||||||
local_user(), Term::OBJECT_TYPE_POST, Term::HASHTAG,
|
local_user(), $top_limit, $bottom_limit, GRAVITY_PARENT);
|
||||||
$top_limit, $bottom_limit, GRAVITY_PARENT);
|
|
||||||
|
|
||||||
$data = DBA::toArray($items);
|
$data = DBA::toArray($items);
|
||||||
|
|
||||||
|
|
|
@ -183,7 +183,7 @@ EOT;
|
||||||
q("INSERT INTO term (oid, otype, type, term, url, uid) VALUE (%d, %d, %d, '%s', '%s', %d)",
|
q("INSERT INTO term (oid, otype, type, term, url, uid) VALUE (%d, %d, %d, '%s', '%s', %d)",
|
||||||
intval($item['id']),
|
intval($item['id']),
|
||||||
$term_objtype,
|
$term_objtype,
|
||||||
Term::HASHTAG,
|
Tag::HASHTAG,
|
||||||
DBA::escape($term),
|
DBA::escape($term),
|
||||||
'',
|
'',
|
||||||
intval($owner_uid)
|
intval($owner_uid)
|
||||||
|
@ -205,7 +205,7 @@ EOT;
|
||||||
q("INSERT INTO term (`oid`, `otype`, `type`, `term`, `url`, `uid`) VALUE (%d, %d, %d, '%s', '%s', %d)",
|
q("INSERT INTO term (`oid`, `otype`, `type`, `term`, `url`, `uid`) VALUE (%d, %d, %d, '%s', '%s', %d)",
|
||||||
intval($original_item['id']),
|
intval($original_item['id']),
|
||||||
$term_objtype,
|
$term_objtype,
|
||||||
Term::HASHTAG,
|
Tag::HASHTAG,
|
||||||
DBA::escape($term),
|
DBA::escape($term),
|
||||||
'',
|
'',
|
||||||
intval($owner_uid)
|
intval($owner_uid)
|
||||||
|
|
|
@ -25,7 +25,7 @@ use Friendica\Core\Renderer;
|
||||||
use Friendica\Database\DBA;
|
use Friendica\Database\DBA;
|
||||||
use Friendica\DI;
|
use Friendica\DI;
|
||||||
use Friendica\Model\Item;
|
use Friendica\Model\Item;
|
||||||
use Friendica\Model\Term;
|
use Friendica\Model\Tag;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TagCloud widget
|
* TagCloud widget
|
||||||
|
@ -46,7 +46,7 @@ class TagCloud
|
||||||
* @return string HTML formatted output.
|
* @return string HTML formatted output.
|
||||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||||
*/
|
*/
|
||||||
public static function getHTML($uid, $count = 0, $owner_id = 0, $flags = '', $type = Term::HASHTAG)
|
public static function getHTML($uid, $count = 0, $owner_id = 0, $flags = '', $type = Tag::HASHTAG)
|
||||||
{
|
{
|
||||||
$o = '';
|
$o = '';
|
||||||
$r = self::tagadelic($uid, $count, $owner_id, $flags, $type);
|
$r = self::tagadelic($uid, $count, $owner_id, $flags, $type);
|
||||||
|
@ -85,7 +85,7 @@ class TagCloud
|
||||||
* @return array Alphabetical sorted array of used tags of an user.
|
* @return array Alphabetical sorted array of used tags of an user.
|
||||||
* @throws \Exception
|
* @throws \Exception
|
||||||
*/
|
*/
|
||||||
private static function tagadelic($uid, $count = 0, $owner_id = 0, $flags = '', $type = Term::HASHTAG)
|
private static function tagadelic($uid, $count = 0, $owner_id = 0, $flags = '', $type = Tag::HASHTAG)
|
||||||
{
|
{
|
||||||
$sql_options = Item::getPermissionsSQLByUserId($uid);
|
$sql_options = Item::getPermissionsSQLByUserId($uid);
|
||||||
$limit = $count ? sprintf('LIMIT %d', intval($count)) : '';
|
$limit = $count ? sprintf('LIMIT %d', intval($count)) : '';
|
||||||
|
@ -101,16 +101,13 @@ class TagCloud
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fetch tags
|
// Fetch tags
|
||||||
$tag_stmt = DBA::p("SELECT `term`, COUNT(`term`) AS `total` FROM `term`
|
$tag_stmt = DBA::p("SELECT `name`, COUNT(`name`) AS `total` FROM `tag-search-view`
|
||||||
LEFT JOIN `item` ON `term`.`oid` = `item`.`id`
|
LEFT JOIN `item` ON `tag-search-view`.`uri-id` = `item`.`uri-id`
|
||||||
WHERE `term`.`uid` = ? AND `term`.`type` = ?
|
WHERE `tag-search-view`.`uid` = ?
|
||||||
AND `term`.`otype` = ?
|
|
||||||
AND `item`.`visible` AND NOT `item`.`deleted` AND NOT `item`.`moderated`
|
AND `item`.`visible` AND NOT `item`.`deleted` AND NOT `item`.`moderated`
|
||||||
$sql_options
|
$sql_options
|
||||||
GROUP BY `term` ORDER BY `total` DESC $limit",
|
GROUP BY `name` ORDER BY `total` DESC $limit",
|
||||||
$uid,
|
$uid
|
||||||
$type,
|
|
||||||
Term::OBJECT_TYPE_POST
|
|
||||||
);
|
);
|
||||||
if (!DBA::isResult($tag_stmt)) {
|
if (!DBA::isResult($tag_stmt)) {
|
||||||
return [];
|
return [];
|
||||||
|
@ -139,7 +136,7 @@ class TagCloud
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($arr as $rr) {
|
foreach ($arr as $rr) {
|
||||||
$tags[$x][0] = $rr['term'];
|
$tags[$x][0] = $rr['name'];
|
||||||
$tags[$x][1] = log($rr['total']);
|
$tags[$x][1] = log($rr['total']);
|
||||||
$tags[$x][2] = 0;
|
$tags[$x][2] = 0;
|
||||||
$min = min($min, $tags[$x][1]);
|
$min = min($min, $tags[$x][1]);
|
||||||
|
|
|
@ -23,7 +23,7 @@ namespace Friendica\Content\Widget;
|
||||||
|
|
||||||
use Friendica\Core\Renderer;
|
use Friendica\Core\Renderer;
|
||||||
use Friendica\DI;
|
use Friendica\DI;
|
||||||
use Friendica\Model\Term;
|
use Friendica\Model\Tag;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Trending tags aside widget for the community pages, handles both local and global scopes
|
* Trending tags aside widget for the community pages, handles both local and global scopes
|
||||||
|
@ -41,9 +41,9 @@ class TrendingTags
|
||||||
public static function getHTML($content = 'global', int $period = 24)
|
public static function getHTML($content = 'global', int $period = 24)
|
||||||
{
|
{
|
||||||
if ($content == 'local') {
|
if ($content == 'local') {
|
||||||
$tags = Term::getLocalTrendingHashtags($period, 20);
|
$tags = Tag::getLocalTrendingHashtags($period, 20);
|
||||||
} else {
|
} else {
|
||||||
$tags = Term::getGlobalTrendingHashtags($period, 20);
|
$tags = Tag::getGlobalTrendingHashtags($period, 20);
|
||||||
}
|
}
|
||||||
|
|
||||||
$tpl = Renderer::getMarkupTemplate('widget/trending_tags.tpl');
|
$tpl = Renderer::getMarkupTemplate('widget/trending_tags.tpl');
|
||||||
|
|
|
@ -28,7 +28,9 @@ use Friendica\Model\Contact;
|
||||||
use Friendica\Model\Item;
|
use Friendica\Model\Item;
|
||||||
use Friendica\Model\ItemURI;
|
use Friendica\Model\ItemURI;
|
||||||
use Friendica\Model\PermissionSet;
|
use Friendica\Model\PermissionSet;
|
||||||
|
use Friendica\Model\Tag;
|
||||||
use Friendica\Model\UserItem;
|
use Friendica\Model\UserItem;
|
||||||
|
use Friendica\Util\Strings;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* These database-intensive post update routines are meant to be executed in the background by the cronjob.
|
* These database-intensive post update routines are meant to be executed in the background by the cronjob.
|
||||||
|
@ -64,6 +66,12 @@ class PostUpdate
|
||||||
if (!self::update1329()) {
|
if (!self::update1329()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (!self::update1341()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!self::update1342()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -533,4 +541,130 @@ class PostUpdate
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fill the "tag" table with tags and mentions from the body
|
||||||
|
*
|
||||||
|
* @return bool "true" when the job is done
|
||||||
|
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||||
|
*/
|
||||||
|
private static function update1341()
|
||||||
|
{
|
||||||
|
// Was the script completed?
|
||||||
|
if (DI::config()->get('system', 'post_update_version') >= 1341) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
$id = DI::config()->get('system', 'post_update_version_1341_id', 0);
|
||||||
|
|
||||||
|
Logger::info('Start', ['item' => $id]);
|
||||||
|
|
||||||
|
$start_id = $id;
|
||||||
|
$rows = 0;
|
||||||
|
|
||||||
|
$items = DBA::p("SELECT `uri-id`,`body` FROM `item-content` WHERE
|
||||||
|
(`body` LIKE ? OR `body` LIKE ? OR `body` LIKE ?) AND `uri-id` >= ?
|
||||||
|
ORDER BY `uri-id` LIMIT 100000", '%#%', '%@%', '%!%', $id);
|
||||||
|
|
||||||
|
if (DBA::errorNo() != 0) {
|
||||||
|
Logger::error('Database error', ['no' => DBA::errorNo(), 'message' => DBA::errorMessage()]);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
while ($item = DBA::fetch($items)) {
|
||||||
|
Tag::storeFromBody($item['uri-id'], $item['body'], '#!@', false);
|
||||||
|
$id = $item['uri-id'];
|
||||||
|
++$rows;
|
||||||
|
if ($rows % 1000 == 0) {
|
||||||
|
DI::config()->set('system', 'post_update_version_1341_id', $id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DBA::close($items);
|
||||||
|
|
||||||
|
DI::config()->set('system', 'post_update_version_1341_id', $id);
|
||||||
|
|
||||||
|
Logger::info('Processed', ['rows' => $rows, 'last' => $id]);
|
||||||
|
|
||||||
|
// When there are less than 1,000 items processed this means that we reached the end
|
||||||
|
// The other entries will then be processed with the regular functionality
|
||||||
|
if ($rows < 1000) {
|
||||||
|
DI::config()->set('system', 'post_update_version', 1341);
|
||||||
|
Logger::info('Done');
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fill the "tag" table with tags and mentions from the "term" table
|
||||||
|
*
|
||||||
|
* @return bool "true" when the job is done
|
||||||
|
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||||
|
*/
|
||||||
|
private static function update1342()
|
||||||
|
{
|
||||||
|
// Was the script completed?
|
||||||
|
if (DI::config()->get('system', 'post_update_version') >= 1342) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
$id = DI::config()->get('system', 'post_update_version_1342_id', 0);
|
||||||
|
|
||||||
|
Logger::info('Start', ['item' => $id]);
|
||||||
|
|
||||||
|
$start_id = $id;
|
||||||
|
$rows = 0;
|
||||||
|
|
||||||
|
$terms = DBA::p("SELECT `term`.`tid`, `item`.`uri-id`, `term`.`type`, `term`.`term`, `term`.`url`, `item-content`.`body`
|
||||||
|
FROM `term`
|
||||||
|
INNER JOIN `item` ON `item`.`id` = `term`.`oid`
|
||||||
|
INNER JOIN `item-content` ON `item-content`.`uri-id` = `item`.`uri-id`
|
||||||
|
WHERE term.type IN (?, ?, ?, ?) AND `tid` >= ? ORDER BY `tid` LIMIT 100000",
|
||||||
|
Tag::HASHTAG, Tag::MENTION, Tag::EXCLUSIVE_MENTION, Tag::IMPLICIT_MENTION, $id);
|
||||||
|
|
||||||
|
if (DBA::errorNo() != 0) {
|
||||||
|
Logger::error('Database error', ['no' => DBA::errorNo(), 'message' => DBA::errorMessage()]);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
while ($term = DBA::fetch($terms)) {
|
||||||
|
if (($term['type'] == Tag::MENTION) && !empty($term['url']) && !strstr($term['body'], $term['url'])) {
|
||||||
|
$condition = ['nurl' => Strings::normaliseLink($term['url']), 'uid' => 0, 'deleted' => false];
|
||||||
|
$contact = DBA::selectFirst('contact', ['url', 'alias'], $condition, ['order' => ['id']]);
|
||||||
|
if (!DBA::isResult($contact)) {
|
||||||
|
$ssl_url = str_replace('http://', 'https://', $term['url']);
|
||||||
|
$condition = ['`alias` IN (?, ?, ?) AND `uid` = ? AND NOT `deleted`', $term['url'], Strings::normaliseLink($term['url']), $ssl_url, 0];
|
||||||
|
$contact = DBA::selectFirst('contact', ['url', 'alias'], $condition, ['order' => ['id']]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DBA::isResult($contact) && (!strstr($term['body'], $contact['url']) && (empty($contact['alias']) || !strstr($term['body'], $contact['alias'])))) {
|
||||||
|
$term['type'] = Tag::IMPLICIT_MENTION;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Tag::store($term['uri-id'], $term['type'], $term['term'], $term['url'], false);
|
||||||
|
|
||||||
|
$id = $term['tid'];
|
||||||
|
++$rows;
|
||||||
|
if ($rows % 1000 == 0) {
|
||||||
|
DI::config()->set('system', 'post_update_version_1342_id', $id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DBA::close($terms);
|
||||||
|
|
||||||
|
DI::config()->set('system', 'post_update_version_1342_id', $id);
|
||||||
|
|
||||||
|
Logger::info('Processed', ['rows' => $rows, 'last' => $id]);
|
||||||
|
|
||||||
|
// When there are less than 1,000 items processed this means that we reached the end
|
||||||
|
// The other entries will then be processed with the regular functionality
|
||||||
|
if ($rows < 1000) {
|
||||||
|
DI::config()->set('system', 'post_update_version', 1342);
|
||||||
|
Logger::info('Done');
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,7 +61,7 @@ class Item
|
||||||
|
|
||||||
// Field list that is used to display the items
|
// Field list that is used to display the items
|
||||||
const DISPLAY_FIELDLIST = [
|
const DISPLAY_FIELDLIST = [
|
||||||
'uid', 'id', 'parent', 'uri', 'thr-parent', 'parent-uri', 'guid', 'network', 'gravity',
|
'uid', 'id', 'parent', 'uri-id', 'uri', 'thr-parent', 'parent-uri', 'guid', 'network', 'gravity',
|
||||||
'commented', 'created', 'edited', 'received', 'verb', 'object-type', 'postopts', 'plink',
|
'commented', 'created', 'edited', 'received', 'verb', 'object-type', 'postopts', 'plink',
|
||||||
'wall', 'private', 'starred', 'origin', 'title', 'body', 'file', 'attach', 'language',
|
'wall', 'private', 'starred', 'origin', 'title', 'body', 'file', 'attach', 'language',
|
||||||
'content-warning', 'location', 'coord', 'app', 'rendered-hash', 'rendered-html', 'object',
|
'content-warning', 'location', 'coord', 'app', 'rendered-hash', 'rendered-html', 'object',
|
||||||
|
@ -77,7 +77,7 @@ class Item
|
||||||
];
|
];
|
||||||
|
|
||||||
// Field list that is used to deliver items via the protocols
|
// Field list that is used to deliver items via the protocols
|
||||||
const DELIVER_FIELDLIST = ['uid', 'id', 'parent', 'uri', 'thr-parent', 'parent-uri', 'guid',
|
const DELIVER_FIELDLIST = ['uid', 'id', 'parent', 'uri-id', 'uri', 'thr-parent', 'parent-uri', 'guid',
|
||||||
'parent-guid', 'created', 'edited', 'verb', 'object-type', 'object', 'target',
|
'parent-guid', 'created', 'edited', 'verb', 'object-type', 'object', 'target',
|
||||||
'private', 'title', 'body', 'location', 'coord', 'app',
|
'private', 'title', 'body', 'location', 'coord', 'app',
|
||||||
'attach', 'tag', 'deleted', 'extid', 'post-type',
|
'attach', 'tag', 'deleted', 'extid', 'post-type',
|
||||||
|
@ -1674,6 +1674,11 @@ class Item
|
||||||
// Check for hashtags in the body and repair or add hashtag links
|
// Check for hashtags in the body and repair or add hashtag links
|
||||||
self::setHashtags($item);
|
self::setHashtags($item);
|
||||||
|
|
||||||
|
// Store tags from the body if this hadn't been handled previously in the protocol classes
|
||||||
|
if (!Tag::existsForPost($item['uri-id'])) {
|
||||||
|
Tag::storeFromBody($item['uri-id'], $item['body']);
|
||||||
|
}
|
||||||
|
|
||||||
$item['thr-parent'] = $item['parent-uri'];
|
$item['thr-parent'] = $item['parent-uri'];
|
||||||
|
|
||||||
$notify_type = Delivery::POST;
|
$notify_type = Delivery::POST;
|
||||||
|
@ -3558,7 +3563,7 @@ class Item
|
||||||
return $ev;
|
return $ev;
|
||||||
}
|
}
|
||||||
|
|
||||||
$tags = Term::populateTagsFromItem($item);
|
$tags = Tag::populateFromItem($item);
|
||||||
|
|
||||||
$item['tags'] = $tags['tags'];
|
$item['tags'] = $tags['tags'];
|
||||||
$item['hashtags'] = $tags['hashtags'];
|
$item['hashtags'] = $tags['hashtags'];
|
||||||
|
|
|
@ -22,9 +22,11 @@
|
||||||
namespace Friendica\Model;
|
namespace Friendica\Model;
|
||||||
|
|
||||||
use Friendica\Content\Text\BBCode;
|
use Friendica\Content\Text\BBCode;
|
||||||
|
use Friendica\Core\Cache\Duration;
|
||||||
use Friendica\Core\Logger;
|
use Friendica\Core\Logger;
|
||||||
use Friendica\Core\System;
|
use Friendica\Core\System;
|
||||||
use Friendica\Database\DBA;
|
use Friendica\Database\DBA;
|
||||||
|
use Friendica\DI;
|
||||||
use Friendica\Util\Strings;
|
use Friendica\Util\Strings;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -67,7 +69,19 @@ class Tag
|
||||||
*/
|
*/
|
||||||
public static function store(int $uriid, int $type, string $name, string $url = '', $probing = true)
|
public static function store(int $uriid, int $type, string $name, string $url = '', $probing = true)
|
||||||
{
|
{
|
||||||
$name = trim($name, "\x00..\x20\xFF#!@");
|
if ($type == self::HASHTAG) {
|
||||||
|
// Remove some common "garbarge" from tags
|
||||||
|
$name = trim($name, "\x00..\x20\xFF#!@,;.:'/?!^°$%".'"');
|
||||||
|
|
||||||
|
$tags = explode(self::TAG_CHARACTER[self::HASHTAG], $name);
|
||||||
|
if (count($tags) > 1) {
|
||||||
|
foreach ($tags as $tag) {
|
||||||
|
self::store($uriid, $type, $tag, $url, $probing);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (empty($name)) {
|
if (empty($name)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -75,7 +89,7 @@ class Tag
|
||||||
$cid = 0;
|
$cid = 0;
|
||||||
$tagid = 0;
|
$tagid = 0;
|
||||||
|
|
||||||
if (in_array($type, [Tag::MENTION, Tag::EXCLUSIVE_MENTION, Tag::IMPLICIT_MENTION])) {
|
if (in_array($type, [self::MENTION, self::EXCLUSIVE_MENTION, self::IMPLICIT_MENTION])) {
|
||||||
if (empty($url)) {
|
if (empty($url)) {
|
||||||
// No mention without a contact url
|
// No mention without a contact url
|
||||||
return;
|
return;
|
||||||
|
@ -114,7 +128,7 @@ class Tag
|
||||||
if (empty($cid)) {
|
if (empty($cid)) {
|
||||||
$fields = ['name' => substr($name, 0, 96), 'url' => ''];
|
$fields = ['name' => substr($name, 0, 96), 'url' => ''];
|
||||||
|
|
||||||
if (($type != Tag::HASHTAG) && !empty($url) && ($url != $name)) {
|
if (($type != self::HASHTAG) && !empty($url) && ($url != $name)) {
|
||||||
$fields['url'] = strtolower($url);
|
$fields['url'] = strtolower($url);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -134,9 +148,9 @@ class Tag
|
||||||
|
|
||||||
$fields = ['uri-id' => $uriid, 'type' => $type, 'tid' => $tagid, 'cid' => $cid];
|
$fields = ['uri-id' => $uriid, 'type' => $type, 'tid' => $tagid, 'cid' => $cid];
|
||||||
|
|
||||||
if (in_array($type, [Tag::MENTION, Tag::EXCLUSIVE_MENTION, Tag::IMPLICIT_MENTION])) {
|
if (in_array($type, [self::MENTION, self::EXCLUSIVE_MENTION, self::IMPLICIT_MENTION])) {
|
||||||
$condition = $fields;
|
$condition = $fields;
|
||||||
$condition['type'] = [Tag::MENTION, Tag::EXCLUSIVE_MENTION, Tag::IMPLICIT_MENTION];
|
$condition['type'] = [self::MENTION, self::EXCLUSIVE_MENTION, self::IMPLICIT_MENTION];
|
||||||
if (DBA::exists('post-tag', $condition)) {
|
if (DBA::exists('post-tag', $condition)) {
|
||||||
Logger::info('Tag already exists', $fields);
|
Logger::info('Tag already exists', $fields);
|
||||||
return;
|
return;
|
||||||
|
@ -221,6 +235,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
|
* Remove tag/mention
|
||||||
*
|
*
|
||||||
|
@ -282,6 +307,176 @@ class Tag
|
||||||
} else {
|
} else {
|
||||||
return self::UNKNOWN;
|
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 getByURIId(int $uri_id, array $type = [self::HASHTAG, self::MENTION, self::IMPLICIT_MENTION, self::EXCLUSIVE_MENTION])
|
||||||
|
{
|
||||||
|
$condition = ['uri-id' => $uri_id, 'type' => $type];
|
||||||
|
return DBA::selectToArray('tag-view', ['type', 'name', 'url'], $condition);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 populateFromItem(&$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 . '<a href="' . $tag['url'] . '" target="_blank" rel="noopener noreferrer">' . htmlspecialchars($tag['name']) . '</a>';
|
||||||
|
$return['tags'][] = $prefix . '<a href="' . $tag['url'] . '" target="_blank" rel="noopener noreferrer">' . htmlspecialchars($tag['name']) . '</a>';
|
||||||
|
break;
|
||||||
|
case self::MENTION:
|
||||||
|
case self::EXCLUSIVE_MENTION:
|
||||||
|
$tag['url'] = Contact::magicLink($tag['url']);
|
||||||
|
$return['mentions'][] = $prefix . '<a href="' . $tag['url'] . '" target="_blank" rel="noopener noreferrer">' . htmlspecialchars($tag['name']) . '</a>';
|
||||||
|
$return['tags'][] = $prefix . '<a href="' . $tag['url'] . '" target="_blank" rel="noopener noreferrer">' . htmlspecialchars($tag['name']) . '</a>';
|
||||||
|
break;
|
||||||
|
case self::IMPLICIT_MENTION:
|
||||||
|
$return['implicit_mentions'][] = $prefix . $tag['name'];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DBA::close($taglist);
|
||||||
|
|
||||||
|
return $return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Search posts for given tag
|
||||||
|
*
|
||||||
|
* @param string $search
|
||||||
|
* @param integer $uid
|
||||||
|
* @param integer $start
|
||||||
|
* @param integer $limit
|
||||||
|
* @return array with URI-ID
|
||||||
|
*/
|
||||||
|
public static function getURIIdListByTag(string $search, int $uid = 0, int $start = 0, int $limit = 100)
|
||||||
|
{
|
||||||
|
$condition = ["`name` = ? AND (NOT `private` OR (`private` AND `uid` = ?))", $search, $uid];
|
||||||
|
$params = [
|
||||||
|
'order' => ['uri-id' => true],
|
||||||
|
'group_by' => ['uri-id'],
|
||||||
|
'limit' => [$start, $limit]
|
||||||
|
];
|
||||||
|
|
||||||
|
$tags = DBA::select('tag-search-view', ['uri-id'], $condition, $params);
|
||||||
|
|
||||||
|
$uriids = [];
|
||||||
|
while ($tag = DBA::fetch($tags)) {
|
||||||
|
$uriids[] = $tag['uri-id'];
|
||||||
|
}
|
||||||
|
DBA::close($tags);
|
||||||
|
|
||||||
|
return $uriids;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a list of the most frequent global hashtags over the given period
|
||||||
|
*
|
||||||
|
* @param int $period Period in hours to consider posts
|
||||||
|
* @return array
|
||||||
|
* @throws \Exception
|
||||||
|
*/
|
||||||
|
public static function getGlobalTrendingHashtags(int $period, $limit = 10)
|
||||||
|
{
|
||||||
|
$tags = DI::cache()->get('global_trending_tags');
|
||||||
|
|
||||||
|
if (empty($tags)) {
|
||||||
|
$tagsStmt = DBA::p("SELECT `name` AS `term`, COUNT(*) AS `score`
|
||||||
|
FROM `tag-search-view`
|
||||||
|
WHERE `private` = ? AND `received` > DATE_SUB(NOW(), INTERVAL ? HOUR)
|
||||||
|
GROUP BY `term` ORDER BY `score` DESC LIMIT ?",
|
||||||
|
Item::PUBLIC, $period, $limit);
|
||||||
|
|
||||||
|
if (DBA::isResult($tagsStmt)) {
|
||||||
|
$tags = DBA::toArray($tagsStmt);
|
||||||
|
DI::cache()->set('global_trending_tags', $tags, Duration::HOUR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $tags ?: [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a list of the most frequent local hashtags over the given period
|
||||||
|
*
|
||||||
|
* @param int $period Period in hours to consider posts
|
||||||
|
* @return array
|
||||||
|
* @throws \Exception
|
||||||
|
*/
|
||||||
|
public static function getLocalTrendingHashtags(int $period, $limit = 10)
|
||||||
|
{
|
||||||
|
$tags = DI::cache()->get('local_trending_tags');
|
||||||
|
|
||||||
|
if (empty($tags)) {
|
||||||
|
$tagsStmt = DBA::p("SELECT `name` AS `term`, COUNT(*) AS `score`
|
||||||
|
FROM `tag-search-view`
|
||||||
|
WHERE `private` = ? AND `wall` AND `origin` AND `received` > DATE_SUB(NOW(), INTERVAL ? HOUR)
|
||||||
|
GROUP BY `term` ORDER BY `score` DESC LIMIT ?",
|
||||||
|
Item::PUBLIC, $period, $limit);
|
||||||
|
|
||||||
|
if (DBA::isResult($tagsStmt)) {
|
||||||
|
$tags = DBA::toArray($tagsStmt);
|
||||||
|
DI::cache()->set('local_trending_tags', $tags, Duration::HOUR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $tags ?: [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the provided tag is of one of the provided term types.
|
||||||
|
*
|
||||||
|
* @param string $tag
|
||||||
|
* @param int ...$types
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public static function isType($tag, ...$types)
|
||||||
|
{
|
||||||
|
$tag_chars = [];
|
||||||
|
foreach ($types as $type) {
|
||||||
|
if (array_key_exists($type, self::TAG_CHARACTER)) {
|
||||||
|
$tag_chars[] = self::TAG_CHARACTER[$type];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Strings::startsWith($tag, $tag_chars);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,6 @@
|
||||||
|
|
||||||
namespace Friendica\Model;
|
namespace Friendica\Model;
|
||||||
|
|
||||||
use Friendica\Core\Cache\Duration;
|
|
||||||
use Friendica\Core\Logger;
|
use Friendica\Core\Logger;
|
||||||
use Friendica\Database\DBA;
|
use Friendica\Database\DBA;
|
||||||
use Friendica\DI;
|
use Friendica\DI;
|
||||||
|
@ -60,95 +59,6 @@ class Term
|
||||||
const OBJECT_TYPE_POST = 1;
|
const OBJECT_TYPE_POST = 1;
|
||||||
const OBJECT_TYPE_PHOTO = 2;
|
const OBJECT_TYPE_PHOTO = 2;
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a list of the most frequent global hashtags over the given period
|
|
||||||
*
|
|
||||||
* @param int $period Period in hours to consider posts
|
|
||||||
* @return array
|
|
||||||
* @throws \Exception
|
|
||||||
*/
|
|
||||||
public static function getGlobalTrendingHashtags(int $period, $limit = 10)
|
|
||||||
{
|
|
||||||
$tags = DI::cache()->get('global_trending_tags');
|
|
||||||
|
|
||||||
if (!$tags) {
|
|
||||||
$tagsStmt = DBA::p("SELECT t.`term`, COUNT(*) AS `score`
|
|
||||||
FROM `term` t
|
|
||||||
JOIN `item` i ON i.`id` = t.`oid` AND i.`uid` = t.`uid`
|
|
||||||
JOIN `thread` ON `thread`.`iid` = i.`id`
|
|
||||||
WHERE `thread`.`visible`
|
|
||||||
AND NOT `thread`.`deleted`
|
|
||||||
AND NOT `thread`.`moderated`
|
|
||||||
AND `thread`.`private` = ?
|
|
||||||
AND t.`uid` = 0
|
|
||||||
AND t.`otype` = ?
|
|
||||||
AND t.`type` = ?
|
|
||||||
AND t.`term` != ''
|
|
||||||
AND i.`received` > DATE_SUB(NOW(), INTERVAL ? HOUR)
|
|
||||||
GROUP BY `term`
|
|
||||||
ORDER BY `score` DESC
|
|
||||||
LIMIT ?",
|
|
||||||
Item::PUBLIC,
|
|
||||||
Term::OBJECT_TYPE_POST,
|
|
||||||
Term::HASHTAG,
|
|
||||||
$period,
|
|
||||||
$limit
|
|
||||||
);
|
|
||||||
|
|
||||||
if (DBA::isResult($tagsStmt)) {
|
|
||||||
$tags = DBA::toArray($tagsStmt);
|
|
||||||
DI::cache()->set('global_trending_tags', $tags, Duration::HOUR);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $tags ?: [];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a list of the most frequent local hashtags over the given period
|
|
||||||
*
|
|
||||||
* @param int $period Period in hours to consider posts
|
|
||||||
* @return array
|
|
||||||
* @throws \Exception
|
|
||||||
*/
|
|
||||||
public static function getLocalTrendingHashtags(int $period, $limit = 10)
|
|
||||||
{
|
|
||||||
$tags = DI::cache()->get('local_trending_tags');
|
|
||||||
|
|
||||||
if (!$tags) {
|
|
||||||
$tagsStmt = DBA::p("SELECT t.`term`, COUNT(*) AS `score`
|
|
||||||
FROM `term` t
|
|
||||||
JOIN `item` i ON i.`id` = t.`oid` AND i.`uid` = t.`uid`
|
|
||||||
JOIN `thread` ON `thread`.`iid` = i.`id`
|
|
||||||
WHERE `thread`.`visible`
|
|
||||||
AND NOT `thread`.`deleted`
|
|
||||||
AND NOT `thread`.`moderated`
|
|
||||||
AND `thread`.`private` = ?
|
|
||||||
AND `thread`.`wall`
|
|
||||||
AND `thread`.`origin`
|
|
||||||
AND t.`otype` = ?
|
|
||||||
AND t.`type` = ?
|
|
||||||
AND t.`term` != ''
|
|
||||||
AND i.`received` > DATE_SUB(NOW(), INTERVAL ? HOUR)
|
|
||||||
GROUP BY `term`
|
|
||||||
ORDER BY `score` DESC
|
|
||||||
LIMIT ?",
|
|
||||||
Item::PUBLIC,
|
|
||||||
Term::OBJECT_TYPE_POST,
|
|
||||||
Term::HASHTAG,
|
|
||||||
$period,
|
|
||||||
$limit
|
|
||||||
);
|
|
||||||
|
|
||||||
if (DBA::isResult($tagsStmt)) {
|
|
||||||
$tags = DBA::toArray($tagsStmt);
|
|
||||||
DI::cache()->set('local_trending_tags', $tags, Duration::HOUR);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $tags ?: [];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates the legacy item.tag field comma-separated BBCode string from an item ID.
|
* Generates the legacy item.tag field comma-separated BBCode string from an item ID.
|
||||||
* Includes only hashtags, implicit and explicit mentions.
|
* Includes only hashtags, implicit and explicit mentions.
|
||||||
|
@ -160,7 +70,7 @@ class Term
|
||||||
public static function tagTextFromItemId($item_id)
|
public static function tagTextFromItemId($item_id)
|
||||||
{
|
{
|
||||||
$tag_list = [];
|
$tag_list = [];
|
||||||
$tags = self::tagArrayFromItemId($item_id, [self::HASHTAG, self::MENTION, self::IMPLICIT_MENTION]);
|
$tags = self::getByItemId($item_id, [self::HASHTAG, self::MENTION, self::IMPLICIT_MENTION]);
|
||||||
foreach ($tags as $tag) {
|
foreach ($tags as $tag) {
|
||||||
$tag_list[] = self::TAG_CHARACTER[$tag['type']] . '[url=' . $tag['url'] . ']' . $tag['term'] . '[/url]';
|
$tag_list[] = self::TAG_CHARACTER[$tag['type']] . '[url=' . $tag['url'] . ']' . $tag['term'] . '[/url]';
|
||||||
}
|
}
|
||||||
|
@ -176,7 +86,7 @@ class Term
|
||||||
* @return array
|
* @return array
|
||||||
* @throws \Exception
|
* @throws \Exception
|
||||||
*/
|
*/
|
||||||
public static function tagArrayFromItemId($item_id, $type = [self::HASHTAG, self::MENTION])
|
private static function getByItemId($item_id, $type = [self::HASHTAG, self::MENTION])
|
||||||
{
|
{
|
||||||
$condition = ['otype' => self::OBJECT_TYPE_POST, 'oid' => $item_id, 'type' => $type];
|
$condition = ['otype' => self::OBJECT_TYPE_POST, 'oid' => $item_id, 'type' => $type];
|
||||||
$tags = DBA::select('term', ['type', 'term', 'url'], $condition);
|
$tags = DBA::select('term', ['type', 'term', 'url'], $condition);
|
||||||
|
@ -198,7 +108,7 @@ class Term
|
||||||
public static function fileTextFromItemId($item_id)
|
public static function fileTextFromItemId($item_id)
|
||||||
{
|
{
|
||||||
$file_text = '';
|
$file_text = '';
|
||||||
$tags = self::tagArrayFromItemId($item_id, [self::FILE, self::CATEGORY]);
|
$tags = self::getByItemId($item_id, [self::FILE, self::CATEGORY]);
|
||||||
foreach ($tags as $tag) {
|
foreach ($tags as $tag) {
|
||||||
if ($tag['type'] == self::CATEGORY) {
|
if ($tag['type'] == self::CATEGORY) {
|
||||||
$file_text .= '<' . $tag['term'] . '>';
|
$file_text .= '<' . $tag['term'] . '>';
|
||||||
|
@ -291,7 +201,7 @@ class Term
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($tags as $link => $tag) {
|
foreach ($tags as $link => $tag) {
|
||||||
if (self::isType($tag, self::HASHTAG)) {
|
if (Tag::isType($tag, self::HASHTAG)) {
|
||||||
// try to ignore #039 or #1 or anything like that
|
// try to ignore #039 or #1 or anything like that
|
||||||
if (ctype_digit(substr(trim($tag), 1))) {
|
if (ctype_digit(substr(trim($tag), 1))) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -305,8 +215,8 @@ class Term
|
||||||
$type = self::HASHTAG;
|
$type = self::HASHTAG;
|
||||||
$term = substr($tag, 1);
|
$term = substr($tag, 1);
|
||||||
$link = '';
|
$link = '';
|
||||||
} elseif (self::isType($tag, self::MENTION, self::EXCLUSIVE_MENTION, self::IMPLICIT_MENTION)) {
|
} elseif (Tag::isType($tag, self::MENTION, self::EXCLUSIVE_MENTION, self::IMPLICIT_MENTION)) {
|
||||||
if (self::isType($tag, self::MENTION, self::EXCLUSIVE_MENTION)) {
|
if (Tag::isType($tag, self::MENTION, self::EXCLUSIVE_MENTION)) {
|
||||||
$type = self::MENTION;
|
$type = self::MENTION;
|
||||||
} else {
|
} else {
|
||||||
$type = self::IMPLICIT_MENTION;
|
$type = self::IMPLICIT_MENTION;
|
||||||
|
@ -355,7 +265,7 @@ class Term
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// Search for mentions
|
// Search for mentions
|
||||||
if (self::isType($tag, self::MENTION, self::EXCLUSIVE_MENTION)
|
if (Tag::isType($tag, self::MENTION, self::EXCLUSIVE_MENTION)
|
||||||
&& (
|
&& (
|
||||||
strpos($link, $profile_base_friendica) !== false
|
strpos($link, $profile_base_friendica) !== false
|
||||||
|| strpos($link, $profile_base_diaspora) !== false
|
|| strpos($link, $profile_base_diaspora) !== false
|
||||||
|
@ -424,64 +334,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 . '<a href="' . $tag['url'] . '" target="_blank" rel="noopener noreferrer">' . htmlspecialchars($tag['term']) . '</a>';
|
|
||||||
$return['tags'][] = $prefix . '<a href="' . $tag['url'] . '" target="_blank" rel="noopener noreferrer">' . htmlspecialchars($tag['term']) . '</a>';
|
|
||||||
break;
|
|
||||||
case self::MENTION:
|
|
||||||
$tag['url'] = Contact::magicLink($tag['url']);
|
|
||||||
$return['mentions'][] = $prefix . '<a href="' . $tag['url'] . '" target="_blank" rel="noopener noreferrer">' . htmlspecialchars($tag['term']) . '</a>';
|
|
||||||
$return['tags'][] = $prefix . '<a href="' . $tag['url'] . '" target="_blank" rel="noopener noreferrer">' . htmlspecialchars($tag['term']) . '</a>';
|
|
||||||
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
|
* Delete tags of the specific type(s) from an item
|
||||||
*
|
*
|
||||||
|
@ -498,23 +350,4 @@ class Term
|
||||||
// Clean up all tags
|
// Clean up all tags
|
||||||
DBA::delete('term', ['otype' => self::OBJECT_TYPE_POST, 'oid' => $item_id, 'type' => $type]);
|
DBA::delete('term', ['otype' => self::OBJECT_TYPE_POST, 'oid' => $item_id, 'type' => $type]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if the provided tag is of one of the provided term types.
|
|
||||||
*
|
|
||||||
* @param string $tag
|
|
||||||
* @param int ...$types
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public static function isType($tag, ...$types)
|
|
||||||
{
|
|
||||||
$tag_chars = [];
|
|
||||||
foreach ($types as $type) {
|
|
||||||
if (array_key_exists($type, self::TAG_CHARACTER)) {
|
|
||||||
$tag_chars[] = self::TAG_CHARACTER[$type];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return Strings::startsWith($tag, $tag_chars);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@ use Friendica\Core\Hook;
|
||||||
use Friendica\Database\DBA;
|
use Friendica\Database\DBA;
|
||||||
use Friendica\DI;
|
use Friendica\DI;
|
||||||
use Friendica\Util\Strings;
|
use Friendica\Util\Strings;
|
||||||
use Friendica\Model\Term;
|
use Friendica\Model\Tag;
|
||||||
|
|
||||||
class UserItem
|
class UserItem
|
||||||
{
|
{
|
||||||
|
@ -50,7 +50,7 @@ class UserItem
|
||||||
*/
|
*/
|
||||||
public static function setNotification(int $iid)
|
public static function setNotification(int $iid)
|
||||||
{
|
{
|
||||||
$fields = ['id', 'uid', 'body', 'parent', 'gravity', 'tag', 'contact-id', 'thr-parent', 'parent-uri', 'author-id'];
|
$fields = ['id', 'uri-id', 'uid', 'body', 'parent', 'gravity', 'tag', 'contact-id', 'thr-parent', 'parent-uri', 'author-id'];
|
||||||
$item = Item::selectFirst($fields, ['id' => $iid, 'origin' => false]);
|
$item = Item::selectFirst($fields, ['id' => $iid, 'origin' => false]);
|
||||||
if (!DBA::isResult($item)) {
|
if (!DBA::isResult($item)) {
|
||||||
return;
|
return;
|
||||||
|
@ -207,7 +207,7 @@ class UserItem
|
||||||
}
|
}
|
||||||
|
|
||||||
// Or the contact is a mentioned forum
|
// Or the contact is a mentioned forum
|
||||||
$tags = DBA::select('term', ['url'], ['otype' => Term::OBJECT_TYPE_POST, 'oid' => $item['id'], 'type' => Term::MENTION, 'uid' => $uid]);
|
$tags = DBA::select('tag-view', ['url'], ['uri-id' => $item['uri-id'], 'type' => [Tag::MENTION, Tag::EXCLUSIVE_MENTION]]);
|
||||||
while ($tag = DBA::fetch($tags)) {
|
while ($tag = DBA::fetch($tags)) {
|
||||||
$condition = ['nurl' => Strings::normaliseLink($tag['url']), 'uid' => $uid, 'notify_new_posts' => true, 'contact-type' => Contact::TYPE_COMMUNITY];
|
$condition = ['nurl' => Strings::normaliseLink($tag['url']), 'uid' => $uid, 'notify_new_posts' => true, 'contact-type' => Contact::TYPE_COMMUNITY];
|
||||||
if (DBA::exists('contact', $condition)) {
|
if (DBA::exists('contact', $condition)) {
|
||||||
|
|
|
@ -48,14 +48,14 @@ class Source extends BaseAdmin
|
||||||
$item_id = '';
|
$item_id = '';
|
||||||
$terms = [];
|
$terms = [];
|
||||||
if (!empty($guid)) {
|
if (!empty($guid)) {
|
||||||
$item = Model\Item::selectFirst(['id', 'guid', 'uri'], ['guid' => $guid]);
|
$item = Model\Item::selectFirst(['id', 'uri-id', 'guid', 'uri'], ['guid' => $guid]);
|
||||||
|
|
||||||
$conversation = Model\Conversation::getByItemUri($item['uri']);
|
$conversation = Model\Conversation::getByItemUri($item['uri']);
|
||||||
|
|
||||||
$item_id = $item['id'];
|
$item_id = $item['id'];
|
||||||
$item_uri = $item['uri'];
|
$item_uri = $item['uri'];
|
||||||
$source = $conversation['source'];
|
$source = $conversation['source'];
|
||||||
$terms = Model\Term::tagArrayFromItemId($item['id'], [Model\Term::HASHTAG, Model\Term::MENTION, Model\Term::IMPLICIT_MENTION]);
|
$terms = Model\Tag::getByURIId($item['uri-id'], [Model\Tag::HASHTAG, Model\Tag::MENTION, Model\Tag::IMPLICIT_MENTION]);
|
||||||
}
|
}
|
||||||
|
|
||||||
$tpl = Renderer::getMarkupTemplate('admin/item/source.tpl');
|
$tpl = Renderer::getMarkupTemplate('admin/item/source.tpl');
|
||||||
|
|
|
@ -25,14 +25,12 @@ use Friendica\BaseModule;
|
||||||
use Friendica\Core\System;
|
use Friendica\Core\System;
|
||||||
use Friendica\Database\DBA;
|
use Friendica\Database\DBA;
|
||||||
use Friendica\Util\Strings;
|
use Friendica\Util\Strings;
|
||||||
use Friendica\Model\Term;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hashtag module.
|
* Hashtag module.
|
||||||
*/
|
*/
|
||||||
class Hashtag extends BaseModule
|
class Hashtag extends BaseModule
|
||||||
{
|
{
|
||||||
|
|
||||||
public static function content(array $parameters = [])
|
public static function content(array $parameters = [])
|
||||||
{
|
{
|
||||||
$result = [];
|
$result = [];
|
||||||
|
@ -42,12 +40,9 @@ class Hashtag extends BaseModule
|
||||||
System::jsonExit($result);
|
System::jsonExit($result);
|
||||||
}
|
}
|
||||||
|
|
||||||
$taglist = DBA::p("SELECT DISTINCT(`term`) FROM `term` WHERE `term` LIKE ? AND `type` = ? ORDER BY `term`",
|
$taglist = DBA::select('tag', ['name'], ["`name` LIKE ?", $t . "%"], ['order' => ['name'], 'limit' => 100]);
|
||||||
$t . '%',
|
|
||||||
intval(Term::HASHTAG)
|
|
||||||
);
|
|
||||||
while ($tag = DBA::fetch($taglist)) {
|
while ($tag = DBA::fetch($taglist)) {
|
||||||
$result[] = ['text' => $tag['term']];
|
$result[] = ['text' => $tag['name']];
|
||||||
}
|
}
|
||||||
DBA::close($taglist);
|
DBA::close($taglist);
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,7 @@ use Friendica\Database\DBA;
|
||||||
use Friendica\DI;
|
use Friendica\DI;
|
||||||
use Friendica\Model\Contact;
|
use Friendica\Model\Contact;
|
||||||
use Friendica\Model\Profile as ProfileModel;
|
use Friendica\Model\Profile as ProfileModel;
|
||||||
use Friendica\Model\Term;
|
use Friendica\Model\Tag;
|
||||||
use Friendica\Model\User;
|
use Friendica\Model\User;
|
||||||
use Friendica\Module\BaseProfile;
|
use Friendica\Module\BaseProfile;
|
||||||
use Friendica\Module\Security\Login;
|
use Friendica\Module\Security\Login;
|
||||||
|
@ -184,7 +184,7 @@ class Profile extends BaseProfile
|
||||||
foreach (explode(',', $a->profile['pub_keywords']) as $tag_label) {
|
foreach (explode(',', $a->profile['pub_keywords']) as $tag_label) {
|
||||||
$tags[] = [
|
$tags[] = [
|
||||||
'url' => '/search?tag=' . $tag_label,
|
'url' => '/search?tag=' . $tag_label,
|
||||||
'label' => Term::TAG_CHARACTER[Term::HASHTAG] . $tag_label,
|
'label' => Tag::TAG_CHARACTER[Tag::HASHTAG] . $tag_label,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -147,8 +147,8 @@ class Status extends BaseProfile
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!empty($hashtags)) {
|
if (!empty($hashtags)) {
|
||||||
$sql_post_table .= sprintf("INNER JOIN (SELECT `oid` FROM `term` WHERE `term` = '%s' AND `otype` = %d AND `type` = %d AND `uid` = %d ORDER BY `tid` DESC) AS `term` ON `item`.`id` = `term`.`oid` ",
|
$sql_post_table .= sprintf("INNER JOIN (SELECT `uri-id` FROM `tag-search-view` WHERE `name` = '%s' AND `uid` = %d ORDER BY `uri-id` DESC) AS `tag-search` ON `item`.`uri-id` = `tag-search`.`uri-id` ",
|
||||||
DBA::escape(Strings::protectSprintf($hashtags)), intval(Term::OBJECT_TYPE_POST), intval(Term::HASHTAG), intval($a->profile['uid']));
|
DBA::escape(Strings::protectSprintf($hashtags)), intval($a->profile['uid']));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!empty($datequery)) {
|
if (!empty($datequery)) {
|
||||||
|
|
|
@ -33,7 +33,7 @@ use Friendica\Database\DBA;
|
||||||
use Friendica\DI;
|
use Friendica\DI;
|
||||||
use Friendica\Model\Contact;
|
use Friendica\Model\Contact;
|
||||||
use Friendica\Model\Item;
|
use Friendica\Model\Item;
|
||||||
use Friendica\Model\Term;
|
use Friendica\Model\Tag;
|
||||||
use Friendica\Module\BaseSearch;
|
use Friendica\Module\BaseSearch;
|
||||||
use Friendica\Network\HTTPException;
|
use Friendica\Network\HTTPException;
|
||||||
use Friendica\Util\Strings;
|
use Friendica\Util\Strings;
|
||||||
|
@ -149,28 +149,11 @@ class Index extends BaseSearch
|
||||||
|
|
||||||
if ($tag) {
|
if ($tag) {
|
||||||
Logger::info('Start tag search.', ['q' => $search]);
|
Logger::info('Start tag search.', ['q' => $search]);
|
||||||
|
$uriids = Tag::getURIIdListByTag($search, local_user(), $pager->getStart(), $pager->getItemsPerPage());
|
||||||
|
|
||||||
$condition = [
|
if (!empty($uriids)) {
|
||||||
"(`uid` = 0 OR (`uid` = ? AND NOT `global`))
|
$params = ['order' => ['id' => true], 'group_by' => ['uri-id']];
|
||||||
AND `otype` = ? AND `type` = ? AND `term` = ?",
|
$items = Item::selectForUser(local_user(), [], ['uri-id' => $uriids], $params);
|
||||||
local_user(), Term::OBJECT_TYPE_POST, Term::HASHTAG, $search
|
|
||||||
];
|
|
||||||
$params = [
|
|
||||||
'order' => ['received' => true],
|
|
||||||
'limit' => [$pager->getStart(), $pager->getItemsPerPage()]
|
|
||||||
];
|
|
||||||
$terms = DBA::select('term', ['oid'], $condition, $params);
|
|
||||||
|
|
||||||
$itemids = [];
|
|
||||||
while ($term = DBA::fetch($terms)) {
|
|
||||||
$itemids[] = $term['oid'];
|
|
||||||
}
|
|
||||||
|
|
||||||
DBA::close($terms);
|
|
||||||
|
|
||||||
if (!empty($itemids)) {
|
|
||||||
$params = ['order' => ['id' => true]];
|
|
||||||
$items = Item::selectForUser(local_user(), [], ['id' => $itemids], $params);
|
|
||||||
$r = Item::inArray($items);
|
$r = Item::inArray($items);
|
||||||
} else {
|
} else {
|
||||||
$r = [];
|
$r = [];
|
||||||
|
|
|
@ -33,7 +33,7 @@ use Friendica\Database\DBA;
|
||||||
use Friendica\DI;
|
use Friendica\DI;
|
||||||
use Friendica\Model\Contact;
|
use Friendica\Model\Contact;
|
||||||
use Friendica\Model\Item;
|
use Friendica\Model\Item;
|
||||||
use Friendica\Model\Term;
|
use Friendica\Model\Tag;
|
||||||
use Friendica\Model\User;
|
use Friendica\Model\User;
|
||||||
use Friendica\Protocol\Activity;
|
use Friendica\Protocol\Activity;
|
||||||
use Friendica\Util\Crypto;
|
use Friendica\Util\Crypto;
|
||||||
|
@ -390,7 +390,7 @@ class Post
|
||||||
$buttons["like"] = false;
|
$buttons["like"] = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$tags = Term::populateTagsFromItem($item);
|
$tags = Tag::populateFromItem($item);
|
||||||
|
|
||||||
$ago = Temporal::getRelativeDate($item['created']);
|
$ago = Temporal::getRelativeDate($item['created']);
|
||||||
$ago_received = Temporal::getRelativeDate($item['received']);
|
$ago_received = Temporal::getRelativeDate($item['received']);
|
||||||
|
@ -860,7 +860,7 @@ class Post
|
||||||
return '';
|
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'])) {
|
if (!DBA::isResult($item) || empty($item['author-addr'])) {
|
||||||
// Should not happen
|
// Should not happen
|
||||||
return '';
|
return '';
|
||||||
|
@ -872,7 +872,7 @@ class Post
|
||||||
$text = '';
|
$text = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
$terms = Term::tagArrayFromItemId($this->getId(), [Term::MENTION, Term::IMPLICIT_MENTION]);
|
$terms = Tag::getByURIId($item['uri-id'], [Tag::MENTION, Tag::IMPLICIT_MENTION, Tag::EXCLUSIVE_MENTION]);
|
||||||
foreach ($terms as $term) {
|
foreach ($terms as $term) {
|
||||||
$profile = Contact::getDetailsByURL($term['url']);
|
$profile = Contact::getDetailsByURL($term['url']);
|
||||||
if (!empty($profile['addr']) && ((($profile['contact-type'] ?? '') ?: Contact::TYPE_UNKNOWN) != Contact::TYPE_COMMUNITY) &&
|
if (!empty($profile['addr']) && ((($profile['contact-type'] ?? '') ?: Contact::TYPE_UNKNOWN) != Contact::TYPE_COMMUNITY) &&
|
||||||
|
|
|
@ -35,7 +35,6 @@ use Friendica\Model\Item;
|
||||||
use Friendica\Model\ItemURI;
|
use Friendica\Model\ItemURI;
|
||||||
use Friendica\Model\Mail;
|
use Friendica\Model\Mail;
|
||||||
use Friendica\Model\Tag;
|
use Friendica\Model\Tag;
|
||||||
use Friendica\Model\Term;
|
|
||||||
use Friendica\Model\User;
|
use Friendica\Model\User;
|
||||||
use Friendica\Protocol\Activity;
|
use Friendica\Protocol\Activity;
|
||||||
use Friendica\Protocol\ActivityPub;
|
use Friendica\Protocol\ActivityPub;
|
||||||
|
@ -1016,7 +1015,7 @@ class Processor
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
$parent_terms = Term::tagArrayFromItemId($parent['id'], [Term::MENTION, Term::IMPLICIT_MENTION]);
|
$parent_terms = Tag::getByURIId($parent['uri-id'], [Tag::MENTION, Tag::IMPLICIT_MENTION, Tag::EXCLUSIVE_MENTION]);
|
||||||
|
|
||||||
$parent_author = Contact::getDetailsByURL($parent['author-link'], 0);
|
$parent_author = Contact::getDetailsByURL($parent['author-link'], 0);
|
||||||
|
|
||||||
|
@ -1084,8 +1083,8 @@ class Processor
|
||||||
foreach ($activity_tags as $index => $tag) {
|
foreach ($activity_tags as $index => $tag) {
|
||||||
if (in_array($tag['href'], $potential_mentions)) {
|
if (in_array($tag['href'], $potential_mentions)) {
|
||||||
$activity_tags[$index]['name'] = preg_replace(
|
$activity_tags[$index]['name'] = preg_replace(
|
||||||
'/' . preg_quote(Term::TAG_CHARACTER[Term::MENTION], '/') . '/',
|
'/' . preg_quote(Tag::TAG_CHARACTER[Tag::MENTION], '/') . '/',
|
||||||
Term::TAG_CHARACTER[Term::IMPLICIT_MENTION],
|
Tag::TAG_CHARACTER[Tag::IMPLICIT_MENTION],
|
||||||
$activity_tags[$index]['name'],
|
$activity_tags[$index]['name'],
|
||||||
1
|
1
|
||||||
);
|
);
|
||||||
|
|
|
@ -34,9 +34,10 @@ use Friendica\Model\APContact;
|
||||||
use Friendica\Model\Contact;
|
use Friendica\Model\Contact;
|
||||||
use Friendica\Model\Conversation;
|
use Friendica\Model\Conversation;
|
||||||
use Friendica\Model\Item;
|
use Friendica\Model\Item;
|
||||||
|
use Friendica\Model\ItemURI;
|
||||||
use Friendica\Model\Profile;
|
use Friendica\Model\Profile;
|
||||||
use Friendica\Model\Photo;
|
use Friendica\Model\Photo;
|
||||||
use Friendica\Model\Term;
|
use Friendica\Model\Tag;
|
||||||
use Friendica\Model\User;
|
use Friendica\Model\User;
|
||||||
use Friendica\Protocol\Activity;
|
use Friendica\Protocol\Activity;
|
||||||
use Friendica\Protocol\ActivityPub;
|
use Friendica\Protocol\ActivityPub;
|
||||||
|
@ -407,7 +408,7 @@ class Transmitter
|
||||||
$actor_profile = APContact::getByURL($item['author-link']);
|
$actor_profile = APContact::getByURL($item['author-link']);
|
||||||
}
|
}
|
||||||
|
|
||||||
$terms = Term::tagArrayFromItemId($item['id'], [Term::MENTION, Term::IMPLICIT_MENTION]);
|
$terms = Tag::getByURIId($item['uri-id'], [Tag::MENTION, Tag::IMPLICIT_MENTION, Tag::EXCLUSIVE_MENTION]);
|
||||||
|
|
||||||
if ($item['private'] != Item::PRIVATE) {
|
if ($item['private'] != Item::PRIVATE) {
|
||||||
// Directly mention the original author upon a quoted reshare.
|
// Directly mention the original author upon a quoted reshare.
|
||||||
|
@ -701,6 +702,8 @@ class Transmitter
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$mail['uri-id'] = ItemURI::insert(['uri' => $mail['uri'], 'guid' => $mail['guid']]);
|
||||||
|
|
||||||
$reply = DBA::selectFirst('mail', ['uri'], ['parent-uri' => $mail['parent-uri'], 'reply' => false]);
|
$reply = DBA::selectFirst('mail', ['uri'], ['parent-uri' => $mail['parent-uri'], 'reply' => false]);
|
||||||
|
|
||||||
// Making the post more compatible for Mastodon by:
|
// Making the post more compatible for Mastodon by:
|
||||||
|
@ -1009,12 +1012,12 @@ class Transmitter
|
||||||
{
|
{
|
||||||
$tags = [];
|
$tags = [];
|
||||||
|
|
||||||
$terms = Term::tagArrayFromItemId($item['id'], [Term::HASHTAG, Term::MENTION, Term::IMPLICIT_MENTION]);
|
$terms = Tag::getByURIId($item['uri-id'], [Tag::HASHTAG, Tag::MENTION, Tag::IMPLICIT_MENTION, Tag::EXCLUSIVE_MENTION]);
|
||||||
foreach ($terms as $term) {
|
foreach ($terms as $term) {
|
||||||
if ($term['type'] == Term::HASHTAG) {
|
if ($term['type'] == Tag::HASHTAG) {
|
||||||
$url = DI::baseUrl() . '/search?tag=' . urlencode($term['term']);
|
$url = DI::baseUrl() . '/search?tag=' . urlencode($term['name']);
|
||||||
$tags[] = ['type' => 'Hashtag', 'href' => $url, 'name' => '#' . $term['term']];
|
$tags[] = ['type' => 'Hashtag', 'href' => $url, 'name' => '#' . $term['name']];
|
||||||
} elseif ($term['type'] == Term::MENTION || $term['type'] == Term::IMPLICIT_MENTION) {
|
} else {
|
||||||
$contact = Contact::getDetailsByURL($term['url']);
|
$contact = Contact::getDetailsByURL($term['url']);
|
||||||
if (!empty($contact['addr'])) {
|
if (!empty($contact['addr'])) {
|
||||||
$mention = '@' . $contact['addr'];
|
$mention = '@' . $contact['addr'];
|
||||||
|
@ -1213,15 +1216,14 @@ class Transmitter
|
||||||
/**
|
/**
|
||||||
* Returns if the post contains sensitive content ("nsfw")
|
* Returns if the post contains sensitive content ("nsfw")
|
||||||
*
|
*
|
||||||
* @param integer $item_id
|
* @param integer $uri_id
|
||||||
*
|
*
|
||||||
* @return boolean
|
* @return boolean
|
||||||
* @throws \Exception
|
* @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('tag-view', ['uri-id' => $uri_id, 'name' => 'nsfw']);
|
||||||
return DBA::exists('term', $condition);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1303,7 +1305,7 @@ class Transmitter
|
||||||
|
|
||||||
$data['url'] = $item['plink'];
|
$data['url'] = $item['plink'];
|
||||||
$data['attributedTo'] = $item['author-link'];
|
$data['attributedTo'] = $item['author-link'];
|
||||||
$data['sensitive'] = self::isSensitive($item['id']);
|
$data['sensitive'] = self::isSensitive($item['uri-id']);
|
||||||
$data['context'] = self::fetchContextURLForItem($item);
|
$data['context'] = self::fetchContextURLForItem($item);
|
||||||
|
|
||||||
if (!empty($item['title'])) {
|
if (!empty($item['title'])) {
|
||||||
|
|
|
@ -38,9 +38,7 @@ use Friendica\Model\Item;
|
||||||
use Friendica\Model\ItemURI;
|
use Friendica\Model\ItemURI;
|
||||||
use Friendica\Model\ItemDeliveryData;
|
use Friendica\Model\ItemDeliveryData;
|
||||||
use Friendica\Model\Mail;
|
use Friendica\Model\Mail;
|
||||||
use Friendica\Model\Profile;
|
|
||||||
use Friendica\Model\Tag;
|
use Friendica\Model\Tag;
|
||||||
use Friendica\Model\Term;
|
|
||||||
use Friendica\Model\User;
|
use Friendica\Model\User;
|
||||||
use Friendica\Network\Probe;
|
use Friendica\Network\Probe;
|
||||||
use Friendica\Util\Crypto;
|
use Friendica\Util\Crypto;
|
||||||
|
@ -114,7 +112,7 @@ class Diaspora
|
||||||
|
|
||||||
if (DI::config()->get("system", "relay_directly", false)) {
|
if (DI::config()->get("system", "relay_directly", false)) {
|
||||||
// We distribute our stuff based on the parent to ensure that the thread will be complete
|
// 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)) {
|
if (!DBA::isResult($parent)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -127,11 +125,10 @@ class Diaspora
|
||||||
DBA::close($servers);
|
DBA::close($servers);
|
||||||
|
|
||||||
// All tags of the current post
|
// All tags of the current post
|
||||||
$condition = ['otype' => Term::OBJECT_TYPE_POST, 'type' => Term::HASHTAG, 'oid' => $parent['parent']];
|
$tags = DBA::select('tag-view', ['name'], ['uri-id' => $parent['uri-id'], 'type' => Tag::HASHTAG]);
|
||||||
$tags = DBA::select('term', ['term'], $condition);
|
|
||||||
$taglist = [];
|
$taglist = [];
|
||||||
while ($tag = DBA::fetch($tags)) {
|
while ($tag = DBA::fetch($tags)) {
|
||||||
$taglist[] = $tag['term'];
|
$taglist[] = $tag['name'];
|
||||||
}
|
}
|
||||||
DBA::close($tags);
|
DBA::close($tags);
|
||||||
|
|
||||||
|
|
|
@ -51,7 +51,7 @@
|
||||||
use Friendica\Database\DBA;
|
use Friendica\Database\DBA;
|
||||||
|
|
||||||
if (!defined('DB_UPDATE_VERSION')) {
|
if (!defined('DB_UPDATE_VERSION')) {
|
||||||
define('DB_UPDATE_VERSION', 1341);
|
define('DB_UPDATE_VERSION', 1343);
|
||||||
}
|
}
|
||||||
|
|
||||||
return [
|
return [
|
||||||
|
@ -754,6 +754,7 @@ return [
|
||||||
"icid" => ["icid"],
|
"icid" => ["icid"],
|
||||||
"iaid" => ["iaid"],
|
"iaid" => ["iaid"],
|
||||||
"psid_wall" => ["psid", "wall"],
|
"psid_wall" => ["psid", "wall"],
|
||||||
|
"uri-id" => ["uri-id"],
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
"item-activity" => [
|
"item-activity" => [
|
||||||
|
|
|
@ -220,6 +220,25 @@ return [
|
||||||
INNER JOIN `contact` ON `register`.`uid` = `contact`.`uid`
|
INNER JOIN `contact` ON `register`.`uid` = `contact`.`uid`
|
||||||
INNER JOIN `user` ON `register`.`uid` = `user`.`uid`"
|
INNER JOIN `user` ON `register`.`uid` = `user`.`uid`"
|
||||||
],
|
],
|
||||||
|
"tag-search-view" => [
|
||||||
|
"fields" => [
|
||||||
|
"uri-id" => ["post-tag", "uri-id"],
|
||||||
|
"iid" => ["item", "id"],
|
||||||
|
"uri" => ["item", "uri"],
|
||||||
|
"guid" => ["item", "guid"],
|
||||||
|
"uid" => ["item", "uid"],
|
||||||
|
"private" => ["item", "private"],
|
||||||
|
"wall" => ["item", "wall"],
|
||||||
|
"origin" => ["item", "origin"],
|
||||||
|
"gravity" => ["item", "gravity"],
|
||||||
|
"received" => ["item", "received"],
|
||||||
|
"name" => ["tag", "name"],
|
||||||
|
],
|
||||||
|
"query" => "FROM `post-tag`
|
||||||
|
INNER JOIN `tag` ON `tag`.`id` = `post-tag`.`tid`
|
||||||
|
INNER JOIN `item` ON `item`.`uri-id` = `post-tag`.`uri-id`
|
||||||
|
WHERE `post-tag`.`type` = 1"
|
||||||
|
],
|
||||||
"workerqueue-view" => [
|
"workerqueue-view" => [
|
||||||
"fields" => [
|
"fields" => [
|
||||||
"pid" => ["process", "pid"],
|
"pid" => ["process", "pid"],
|
||||||
|
|
|
@ -45,7 +45,7 @@
|
||||||
{{if $term.type == 8}}Implicit Mention{{/if}}
|
{{if $term.type == 8}}Implicit Mention{{/if}}
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
{{$term.term}}
|
{{$term.name}}
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
{{$term.url}}
|
{{$term.url}}
|
||||||
|
|
Loading…
Reference in a new issue