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