]> git.mxchange.org Git - friendica.git/blob - src/Model/Term.php
Merge remote-tracking branch 'remotes/origin/develop' into lock_abstraction
[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 Friendica\Model\Item;
10 use dba;
11
12 require_once 'boot.php';
13 require_once 'include/conversation.php';
14 require_once 'include/dba.php';
15
16 class Term
17 {
18         public static function insertFromTagFieldByItemId($itemid)
19         {
20                 $profile_base = System::baseUrl();
21                 $profile_data = parse_url($profile_base);
22                 $profile_path = defaults($profile_data, 'path', '');
23                 $profile_base_friendica = $profile_data['host'] . $profile_path . '/profile/';
24                 $profile_base_diaspora = $profile_data['host'] . $profile_path . '/u/';
25
26                 $fields = ['guid', 'uid', 'id', 'edited', 'deleted', 'created', 'received', 'title', 'body', 'tag', 'parent'];
27                 $message = Item::selectFirst($fields, ['id' => $itemid]);
28                 if (!DBM::is_result($message)) {
29                         return;
30                 }
31
32                 // Clean up all tags
33                 dba::delete('term', ['otype' => TERM_OBJ_POST, 'oid' => $itemid, 'type' => [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                                                 /// @todo This function is called frim Item::update - so we mustn't call that function here
119                                                 dba::update('item', ['mention' => true], ['id' => $itemid]);
120                                                 dba::update('thread', ['mention' => true], ['iid' => $message['parent']]);
121                                         }
122                                 }
123                         }
124                 }
125         }
126
127         /**
128          * @param integer $itemid item id
129          * @return void
130          */
131         public static function insertFromFileFieldByItemId($itemid)
132         {
133                 $message = Item::selectFirst(['uid', 'deleted', 'file'], ['id' => $itemid]);
134                 if (!DBM::is_result($message)) {
135                         return;
136                 }
137
138                 // Clean up all tags
139                 dba::delete('term', ['otype' => TERM_OBJ_POST, 'oid' => $itemid, 'type' => [TERM_FILE, TERM_CATEGORY]]);
140
141                 if ($message["deleted"]) {
142                         return;
143                 }
144
145                 if (preg_match_all("/\[(.*?)\]/ism", $message["file"], $files)) {
146                         foreach ($files[1] as $file) {
147                                 dba::insert('term', [
148                                         'uid' => $message["uid"],
149                                         'oid' => $itemid,
150                                         'otype' => TERM_OBJ_POST,
151                                         'type' => TERM_FILE,
152                                         'term' => $file
153                                 ]);
154                         }
155                 }
156
157                 if (preg_match_all("/\<(.*?)\>/ism", $message["file"], $files)) {
158                         foreach ($files[1] as $file) {
159                                 dba::insert('term', [
160                                         'uid' => $message["uid"],
161                                         'oid' => $itemid,
162                                         'otype' => TERM_OBJ_POST,
163                                         'type' => TERM_CATEGORY,
164                                         'term' => $file
165                                 ]);
166                         }
167                 }
168         }
169
170         /**
171          * Sorts an item's tags into mentions, hashtags and other tags. Generate personalized URLs by user and modify the
172          * provided item's body with them.
173          *
174          * @param array $item
175          * @return array
176          */
177         public static function populateTagsFromItem(&$item)
178         {
179                 $return = [
180                         'tags' => [],
181                         'hashtags' => [],
182                         'mentions' => [],
183                 ];
184
185                 $searchpath = System::baseUrl() . "/search?tag=";
186
187                 $taglist = dba::select(
188                         'term',
189                         ['type', 'term', 'url'],
190                         ["`otype` = ? AND `oid` = ? AND `type` IN (?, ?)", TERM_OBJ_POST, $item['id'], TERM_HASHTAG, TERM_MENTION],
191                         ['order' => ['tid']]
192                 );
193
194                 while ($tag = dba::fetch($taglist)) {
195                         if ($tag["url"] == "") {
196                                 $tag["url"] = $searchpath . strtolower($tag["term"]);
197                         }
198
199                         $orig_tag = $tag["url"];
200
201                         $tag["url"] = Contact::magicLinkById($item['author-id'], $tag['url']);
202
203                         if ($tag["type"] == TERM_HASHTAG) {
204                                 if ($orig_tag != $tag["url"]) {
205                                         $item['body'] = str_replace($orig_tag, $tag["url"], $item['body']);
206                                 }
207
208                                 $return['hashtags'][] = "#<a href=\"" . $tag["url"] . "\" target=\"_blank\">" . $tag["term"] . "</a>";
209                                 $prefix = "#";
210                         } elseif ($tag["type"] == TERM_MENTION) {
211                                 $return['mentions'][] = "@<a href=\"" . $tag["url"] . "\" target=\"_blank\">" . $tag["term"] . "</a>";
212                                 $prefix = "@";
213                         }
214
215                         $return['tags'][] = $prefix . "<a href=\"" . $tag["url"] . "\" target=\"_blank\">" . $tag["term"] . "</a>";
216                 }
217                 dba::close($taglist);
218
219                 return $return;
220         }
221 }