]> git.mxchange.org Git - friendica.git/blob - src/Model/FileTag.php
Fix PHPDoc comments project-wide
[friendica.git] / src / Model / FileTag.php
1 <?php
2 /**
3  * @file src/Model/FileTag.php
4  */
5
6 namespace Friendica\Model;
7
8 use Friendica\Core\L10n;
9 use Friendica\Core\PConfig;
10 use Friendica\Database\DBA;
11 use Friendica\Model\Item;
12
13 /**
14  * @brief This class handles FileTag related functions
15  */
16 class FileTag
17 {
18     // post categories and "save to file" use the same item.file table for storage.
19     // We will differentiate the different uses by wrapping categories in angle brackets
20     // and save to file categories in square brackets.
21     // To do this we need to escape these characters if they appear in our tag.
22
23     /**
24      * @brief URL encode &lt, &gt, left and right brackets
25      * 
26      * @param string $s String to be URL encoded.
27      * 
28      * @return string   The URL encoded string.
29      */
30     public static function encode($s)
31     {
32         return str_replace(['<', '>', '[', ']'], ['%3c', '%3e', '%5b', '%5d'], $s);
33     }
34
35     /**
36      * @brief URL decode &lt, &gt, left and right brackets
37      * 
38      * @param string $s The URL encoded string to be decoded
39      * 
40      * @return string   The decoded string.
41      */
42     public static function decode($s)
43     {
44         return str_replace(['%3c', '%3e', '%5b', '%5d'], ['<', '>', '[', ']'], $s);
45     }
46
47     /**
48      * @brief Query files for tag
49      * 
50      * @param string $table The table to be queired.
51      * @param string $s     The search term
52      * @param string $type  Optional file type.
53      * 
54      * @return string       Query string.
55      */
56     public static function fileQuery($table, $s, $type = 'file')
57     {
58         if ($type == 'file') {
59             $str = preg_quote('[' . str_replace('%', '%%', self::encode($s)) . ']');
60         } else {
61             $str = preg_quote('<' . str_replace('%', '%%', self::encode($s)) . '>');
62         }
63
64         return " AND " . (($table) ? DBA::escape($table) . '.' : '') . "file regexp '" . DBA::escape($str) . "' ";
65     }
66
67     /**
68      * @brief Get file tags from list
69      * 
70      * ex. given music,video return <music><video> or [music][video]
71      * @param string $list  A comma delimited list of tags.
72      * @param string $type  Optional file type.
73      * 
74      * @return string       A list of file tags.
75      */
76     public static function listToFile($list, $type = 'file')
77     {
78         $tag_list = '';
79         if (strlen($list)) {
80             $list_array = explode(",", $list);
81             if ($type == 'file') {
82                 $lbracket = '[';
83                 $rbracket = ']';
84             } else {
85                 $lbracket = '<';
86                 $rbracket = '>';
87             }
88
89             foreach ($list_array as $item)
90             {
91                 if (strlen($item))
92                 {
93                     $tag_list .= $lbracket . self::encode(trim($item))  . $rbracket;
94                 }
95             }
96         }
97
98         return $tag_list;
99     }
100
101     /**
102      * @brief Get list from file tags
103      * 
104      * ex. given <music><video>[friends], return music,video or friends
105      * @param string $file  File tags
106      * @param string $type  Optional file type.
107      * 
108      * @return string       Comma delimited list of tag names.
109      */
110     public static function fileToList($file, $type = 'file')
111     {
112         $matches = false;
113         $list = '';
114
115         if ($type == 'file') {
116             $cnt = preg_match_all('/\[(.*?)\]/', $file, $matches, PREG_SET_ORDER);
117         } else {
118             $cnt = preg_match_all('/<(.*?)>/', $file, $matches, PREG_SET_ORDER);
119         }
120
121         if ($cnt)
122         {
123             foreach ($matches as $mtch)
124             {
125                 if (strlen($list))
126                 {
127                     $list .= ',';
128                 }
129
130                 $list .= self::decode($mtch[1]);
131             }
132         }
133
134         return $list;
135     }
136
137         /**
138          * @brief Update file tags in PConfig
139          *
140          * @param int    $uid      Unique Identity.
141          * @param string $file_old Categories previously associated with an item
142          * @param string $file_new New list of categories for an item
143          * @param string $type     Optional file type.
144          *
145          * @return boolean          A value indicating success or failure.
146          * @throws \Friendica\Network\HTTPException\InternalServerErrorException
147          */
148     public static function updatePconfig($uid, $file_old, $file_new, $type = 'file')
149     {
150         if (!intval($uid)) {
151             return false;
152         } elseif ($file_old == $file_new) {
153             return true;
154         }
155
156         $saved = PConfig::get($uid, 'system', 'filetags');
157
158         if (strlen($saved))
159         {
160             if ($type == 'file') {
161                 $lbracket = '[';
162                 $rbracket = ']';
163                 $termtype = TERM_FILE;
164             } else {
165                 $lbracket = '<';
166                 $rbracket = '>';
167                 $termtype = TERM_CATEGORY;
168             }
169
170             $filetags_updated = $saved;
171
172             // check for new tags to be added as filetags in pconfig
173             $new_tags = [];
174             $check_new_tags = explode(",", self::fileToList($file_new, $type));
175
176             foreach ($check_new_tags as $tag)
177             {
178                 if (!stristr($saved,$lbracket . self::encode($tag) . $rbracket)) {
179                     $new_tags[] = $tag;
180                 }
181             }
182
183             $filetags_updated .= self::listToFile(implode(",", $new_tags), $type);
184
185             // check for deleted tags to be removed from filetags in pconfig
186             $deleted_tags = [];
187             $check_deleted_tags = explode(",", self::fileToList($file_old, $type));
188
189             foreach ($check_deleted_tags as $tag)
190             {
191                 if (!stristr($file_new,$lbracket . self::encode($tag) . $rbracket)) {
192                     $deleted_tags[] = $tag;
193                 }
194             }
195
196             foreach ($deleted_tags as $key => $tag)
197             {
198                 $r = q("SELECT `oid` FROM `term` WHERE `term` = '%s' AND `otype` = %d AND `type` = %d AND `uid` = %d",
199                     DBA::escape($tag),
200                     intval(TERM_OBJ_POST),
201                     intval($termtype),
202                     intval($uid));
203
204                 if (DBA::isResult($r)) {
205                     unset($deleted_tags[$key]);
206                 } else {
207                     $filetags_updated = str_replace($lbracket . self::encode($tag) . $rbracket, '', $filetags_updated);
208                 }
209             }
210
211             if ($saved != $filetags_updated)
212             {
213                 PConfig::set($uid, 'system', 'filetags', $filetags_updated);
214             }
215
216             return true;
217         } elseif (strlen($file_new)) {
218             PConfig::set($uid, 'system', 'filetags', $file_new);
219         }
220
221         return true;
222     }
223
224         /**
225          * @brief Add tag to file
226          *
227          * @param int    $uid     Unique identity.
228          * @param int    $item_id Item identity.
229          * @param string $file    File tag.
230          *
231          * @return boolean      A value indicating success or failure.
232          * @throws \Friendica\Network\HTTPException\InternalServerErrorException
233          */
234     public static function saveFile($uid, $item_id, $file)
235     {
236         if (!intval($uid))
237         {
238             return false;
239         }
240
241         $item = Item::selectFirst(['file'], ['id' => $item_id, 'uid' => $uid]);
242         if (DBA::isResult($item))
243         {
244             if (!stristr($item['file'], '[' . self::encode($file) . ']'))
245             {
246                 $fields = ['file' => $item['file'] . '[' . self::encode($file) . ']'];
247                 Item::update($fields, ['id' => $item_id]);
248             }
249
250             $saved = PConfig::get($uid, 'system', 'filetags');
251
252             if (!strlen($saved) || !stristr($saved, '[' . self::encode($file) . ']'))
253             {
254                 PConfig::set($uid, 'system', 'filetags', $saved . '[' . self::encode($file) . ']');
255             }
256
257             info(L10n::t('Item filed'));
258         }
259
260         return true;
261     }
262
263         /**
264          * @brief Remove tag from file
265          *
266          * @param int     $uid     Unique identity.
267          * @param int     $item_id Item identity.
268          * @param string  $file    File tag.
269          * @param boolean $cat     Optional value indicating the term type (i.e. Category or File)
270          *
271          * @return boolean      A value indicating success or failure.
272          * @throws \Friendica\Network\HTTPException\InternalServerErrorException
273          */
274     public static function unsaveFile($uid, $item_id, $file, $cat = false)
275     {
276         if (!intval($uid))
277         {
278             return false;
279         }
280
281         if ($cat == true) {
282             $pattern = '<' . self::encode($file) . '>';
283             $termtype = TERM_CATEGORY;
284         } else {
285             $pattern = '[' . self::encode($file) . ']';
286             $termtype = TERM_FILE;
287         }
288
289         $item = Item::selectFirst(['file'], ['id' => $item_id, 'uid' => $uid]);
290
291         if (!DBA::isResult($item))
292         {
293             return false;
294         }
295
296         $fields = ['file' => str_replace($pattern, '', $item['file'])];
297
298         Item::update($fields, ['id' => $item_id]);
299
300         $r = q("SELECT `oid` FROM `term` WHERE `term` = '%s' AND `otype` = %d AND `type` = %d AND `uid` = %d",
301             DBA::escape($file),
302             intval(TERM_OBJ_POST),
303             intval($termtype),
304             intval($uid)
305         );
306
307         if (!DBA::isResult($r))
308         {
309             $saved = PConfig::get($uid, 'system', 'filetags');
310             PConfig::set($uid, 'system', 'filetags', str_replace($pattern, '', $saved));
311         }
312
313         return true;
314     }
315 }