]> git.mxchange.org Git - friendica.git/blob - src/Model/Term.php
Merge pull request #4865 from annando/dfrn-reshare
[friendica.git] / src / Model / Term.php
1 <?php
2 /**
3  * @file src/Model/Term
4  */
5 namespace Friendica\Model;
6
7 use Friendica\Core\System;
8 use Friendica\Database\DBM;
9 use dba;
10
11 require_once 'boot.php';
12 require_once 'include/conversation.php';
13 require_once 'include/dba.php';
14
15 class Term
16 {
17         public static function insertFromTagFieldByItemId($itemid)
18         {
19                 $profile_base = System::baseUrl();
20                 $profile_data = parse_url($profile_base);
21                 $profile_path = defaults($profile_data, 'path', '');
22                 $profile_base_friendica = $profile_data['host'] . $profile_path . '/profile/';
23                 $profile_base_diaspora = $profile_data['host'] . $profile_path . '/u/';
24
25                 $fields = ['guid', 'uid', 'id', 'edited', 'deleted', 'created', 'received', 'title', 'body', 'tag', 'parent'];
26                 $message = dba::selectFirst('item', $fields, ['id' => $itemid]);
27                 if (!DBM::is_result($message)) {
28                         return;
29                 }
30
31                 // Clean up all tags
32                 dba::e("DELETE FROM `term` WHERE `otype` = ? AND `oid` = ? AND `type` IN (?, ?)",
33                         TERM_OBJ_POST, $itemid, TERM_HASHTAG, TERM_MENTION);
34
35                 if ($message['deleted']) {
36                         return;
37                 }
38
39                 $taglist = explode(',', $message['tag']);
40
41                 $tags_string = '';
42                 foreach ($taglist as $tag) {
43                         if ((substr(trim($tag), 0, 1) == '#') || (substr(trim($tag), 0, 1) == '@')) {
44                                 $tags_string .= ' ' . trim($tag);
45                         } else {
46                                 $tags_string .= ' #' . trim($tag);
47                         }
48                 }
49
50                 $data = ' ' . $message['title'] . ' ' . $message['body'] . ' ' . $tags_string . ' ';
51
52                 // ignore anything in a code block
53                 $data = preg_replace('/\[code\](.*?)\[\/code\]/sm', '', $data);
54
55                 $tags = [];
56
57                 $pattern = '/\W\#([^\[].*?)[\s\'".,:;\?!\[\]\/]/ism';
58                 if (preg_match_all($pattern, $data, $matches)) {
59                         foreach ($matches[1] as $match) {
60                                 $tags['#' . strtolower($match)] = '';
61                         }
62                 }
63
64                 $pattern = '/\W([\#@])\[url\=(.*?)\](.*?)\[\/url\]/ism';
65                 if (preg_match_all($pattern, $data, $matches, PREG_SET_ORDER)) {
66                         foreach ($matches as $match) {
67                                 $tags[$match[1] . strtolower(trim($match[3], ',.:;[]/\"?!'))] = $match[2];
68                         }
69                 }
70
71                 foreach ($tags as $tag => $link) {
72                         if (substr(trim($tag), 0, 1) == '#') {
73                                 // try to ignore #039 or #1 or anything like that
74                                 if (ctype_digit(substr(trim($tag), 1))) {
75                                         continue;
76                                 }
77
78                                 // try to ignore html hex escapes, e.g. #x2317
79                                 if ((substr(trim($tag), 1, 1) == 'x' || substr(trim($tag), 1, 1) == 'X') && ctype_digit(substr(trim($tag), 2))) {
80                                         continue;
81                                 }
82
83                                 $type = TERM_HASHTAG;
84                                 $term = substr($tag, 1);
85                         } elseif (substr(trim($tag), 0, 1) == '@') {
86                                 $type = TERM_MENTION;
87                                 $term = substr($tag, 1);
88                         } else { // This shouldn't happen
89                                 $type = TERM_HASHTAG;
90                                 $term = $tag;
91                         }
92
93                         if ($message['uid'] == 0) {
94                                 $global = true;
95                                 dba::update('term', ['global' => true], ['otype' => TERM_OBJ_POST, 'guid' => $message['guid']]);
96                         } else {
97                                 $global = dba::exists('term', ['uid' => 0, 'otype' => TERM_OBJ_POST, 'guid' => $message['guid']]);
98                         }
99
100                         dba::insert('term', [
101                                 'uid'      => $message['uid'],
102                                 'oid'      => $itemid,
103                                 'otype'    => TERM_OBJ_POST,
104                                 'type'     => $type,
105                                 'term'     => $term,
106                                 'url'      => $link,
107                                 'guid'     => $message['guid'],
108                                 'created'  => $message['created'],
109                                 'received' => $message['received'],
110                                 'global'   => $global
111                         ]);
112
113                         // Search for mentions
114                         if ((substr($tag, 0, 1) == '@') && (strpos($link, $profile_base_friendica) || strpos($link, $profile_base_diaspora))) {
115                                 $users = q("SELECT `uid` FROM `contact` WHERE self AND (`url` = '%s' OR `nurl` = '%s')", $link, $link);
116                                 foreach ($users AS $user) {
117                                         if ($user['uid'] == $message['uid']) {
118                                                 dba::update('item', ['mention' => true], ['id' => $itemid]);
119                                                 dba::update('thread', ['mention' => true], ['iid' => $message['parent']]);
120                                         }
121                                 }
122                         }
123                 }
124         }
125
126         /**
127          * @param integer $itemid item id
128          * @return void
129          */
130         public static function insertFromFileFieldByItemId($itemid)
131         {
132                 $message = dba::selectFirst('item', ['uid', 'deleted', 'file'], ['id' => $itemid]);
133                 if (!DBM::is_result($message)) {
134                         return;
135                 }
136
137                 // Clean up all tags
138                 q("DELETE FROM `term` WHERE `otype` = %d AND `oid` = %d AND `type` IN (%d, %d)",
139                         intval(TERM_OBJ_POST),
140                         intval($itemid),
141                         intval(TERM_FILE),
142                         intval(TERM_CATEGORY));
143
144                 if ($message["deleted"]) {
145                         return;
146                 }
147
148                 if (preg_match_all("/\[(.*?)\]/ism", $message["file"], $files)) {
149                         foreach ($files[1] as $file) {
150                                 dba::insert('term', [
151                                         'uid' => $message["uid"],
152                                         'oid' => $itemid,
153                                         'otype' => TERM_OBJ_POST,
154                                         'type' => TERM_FILE,
155                                         'term' => $file
156                                 ]);
157                         }
158                 }
159
160                 if (preg_match_all("/\<(.*?)\>/ism", $message["file"], $files)) {
161                         foreach ($files[1] as $file) {
162                                 dba::insert('term', [
163                                         'uid' => $message["uid"],
164                                         'oid' => $itemid,
165                                         'otype' => TERM_OBJ_POST,
166                                         'type' => TERM_CATEGORY,
167                                         'term' => $file
168                                 ]);
169                         }
170                 }
171         }
172
173         /**
174          * Sorts an item's tags into mentions, hashtags and other tags. Generate personalized URLs by user and modify the
175          * provided item's body with them.
176          *
177          * @param array $item
178          * @return array
179          */
180         public static function populateTagsFromItem(&$item)
181         {
182                 $return = [
183                         'tags' => [],
184                         'hashtags' => [],
185                         'mentions' => [],
186                 ];
187
188                 $searchpath = System::baseUrl() . "/search?tag=";
189
190                 $taglist = dba::select(
191                         'term',
192                         ['type', 'term', 'url'],
193                         ["`otype` = ? AND `oid` = ? AND `type` IN (?, ?)", TERM_OBJ_POST, $item['id'], TERM_HASHTAG, TERM_MENTION],
194                         ['order' => ['tid']]
195                 );
196
197                 while ($tag = dba::fetch($taglist)) {
198                         if ($tag["url"] == "") {
199                                 $tag["url"] = $searchpath . strtolower($tag["term"]);
200                         }
201
202                         $orig_tag = $tag["url"];
203
204                         $tag["url"] = best_link_url($item, $sp, $tag["url"]);
205
206                         if ($tag["type"] == TERM_HASHTAG) {
207                                 if ($orig_tag != $tag["url"]) {
208                                         $item['body'] = str_replace($orig_tag, $tag["url"], $item['body']);
209                                 }
210
211                                 $return['hashtags'][] = "#<a href=\"" . $tag["url"] . "\" target=\"_blank\">" . $tag["term"] . "</a>";
212                                 $prefix = "#";
213                         } elseif ($tag["type"] == TERM_MENTION) {
214                                 $return['mentions'][] = "@<a href=\"" . $tag["url"] . "\" target=\"_blank\">" . $tag["term"] . "</a>";
215                                 $prefix = "@";
216                         }
217
218                         $return['tags'][] = $prefix . "<a href=\"" . $tag["url"] . "\" target=\"_blank\">" . $tag["term"] . "</a>";
219                 }
220                 dba::close($taglist);
221
222                 return $return;
223         }
224 }