]> git.mxchange.org Git - friendica.git/blob - src/Model/FileTag.php
Move Photo module, update Photo model
[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      */
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      */
232     public static function saveFile($uid, $item_id, $file)
233     {
234         if (!intval($uid))
235         {
236             return false;
237         }
238
239         $item = Item::selectFirst(['file'], ['id' => $item_id, 'uid' => $uid]);
240         if (DBA::isResult($item))
241         {
242             if (!stristr($item['file'], '[' . self::encode($file) . ']'))
243             {
244                 $fields = ['file' => $item['file'] . '[' . self::encode($file) . ']'];
245                 Item::update($fields, ['id' => $item_id]);
246             }
247
248             $saved = PConfig::get($uid, 'system', 'filetags');
249
250             if (!strlen($saved) || !stristr($saved, '[' . self::encode($file) . ']'))
251             {
252                 PConfig::set($uid, 'system', 'filetags', $saved . '[' . self::encode($file) . ']');
253             }
254
255             info(L10n::t('Item filed'));
256         }
257
258         return true;
259     }
260
261     /**
262      * @brief Remove tag from file
263      * 
264      * @param int $uid      Unique identity.
265      * @param int $item_id  Item identity.
266      * @param string $file  File tag.
267      * @param boolean $cat  Optional value indicating the term type (i.e. Category or File)
268      * 
269      * @return boolean      A value indicating success or failure.
270      */
271     public static function unsaveFile($uid, $item_id, $file, $cat = false)
272     {
273         if (!intval($uid))
274         {
275             return false;
276         }
277
278         if ($cat == true) {
279             $pattern = '<' . self::encode($file) . '>';
280             $termtype = TERM_CATEGORY;
281         } else {
282             $pattern = '[' . self::encode($file) . ']';
283             $termtype = TERM_FILE;
284         }
285
286         $item = Item::selectFirst(['file'], ['id' => $item_id, 'uid' => $uid]);
287
288         if (!DBA::isResult($item))
289         {
290             return false;
291         }
292
293         $fields = ['file' => str_replace($pattern, '', $item['file'])];
294
295         Item::update($fields, ['id' => $item_id]);
296
297         $r = q("SELECT `oid` FROM `term` WHERE `term` = '%s' AND `otype` = %d AND `type` = %d AND `uid` = %d",
298             DBA::escape($file),
299             intval(TERM_OBJ_POST),
300             intval($termtype),
301             intval($uid)
302         );
303
304         if (!DBA::isResult($r))
305         {
306             $saved = PConfig::get($uid, 'system', 'filetags');
307             PConfig::set($uid, 'system', 'filetags', str_replace($pattern, '', $saved));
308         }
309
310         return true;
311     }
312 }