SHOW:
|
|
- or go back to the newest paste.
1 | <?php | |
2 | ||
3 | /** | |
4 | * ownCloud - User Conversations | |
5 | * | |
6 | * @author Simeon Ackermann | |
7 | * @copyright 2014 Simeon Ackermann amseon@web.de | |
8 | * | |
9 | * This library is free software; you can redistribute it and/or | |
10 | * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE | |
11 | * License as published by the Free Software Foundation; either | |
12 | * version 3 of the License, or any later version. | |
13 | * | |
14 | * This library is distributed in the hope that it will be useful, | |
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
17 | * GNU AFFERO GENERAL PUBLIC LICENSE for more details. | |
18 | * | |
19 | * You should have received a copy of the GNU Affero General Public | |
20 | * License along with this library. If not, see <http://www.gnu.org/licenses/>. | |
21 | * | |
22 | */ | |
23 | ||
24 | class OC_Conversations | |
25 | { | |
26 | ||
27 | // TODO: better arguments! | |
28 | public static function getConversation($room=false, $offset=0, $limit=5, $from_id=null, $from_date=null) | |
29 | { | |
30 | $userId = OC_User::getUser(); | |
31 | $room = ( $room ) ? $room : self::getRoom(); | |
32 | $rtype = explode(":", $room); | |
33 | ||
34 | if ( $rtype[0] == "user" && UC_SINGLE_USER_MSG == true ) { | |
35 | // get user rooms: msgs to user X from me OR to me from user X | |
36 | $and = array( "( ( room = ? AND author = ? ) OR ( room = ? AND author = ? ) )" ); | |
37 | $args = array($room, $userId, 'user:' . $userId, $rtype[1]); | |
38 | } else { | |
39 | // for compatibility with UC <= 0.1.6: get room-msgs without "group:" prefix and default room in every room | |
40 | $and = array( "( room = ? OR room = ? OR room = ? )" ); | |
41 | $args = array($room, $rtype[1], "default"); // rtype[1] and default for compatibilty | |
42 | } | |
43 | ||
44 | if ( $from_id ) { // used in submit new comment, to get only the new comment; TODO: could be done with with $limit | |
45 | $and[] = "id > ?"; | |
46 | $args[] = $from_id; | |
47 | } | |
48 | ||
49 | if ( $from_date ) { // used in polling, to get only newer posts than a date | |
50 | $and[] = "date > ?"; | |
51 | $args[] = $from_date; | |
52 | } | |
53 | ||
54 | $sql = "SELECT * FROM *PREFIX*conversations " . | |
55 | "WHERE " . implode(" AND ", $and) . | |
56 | " ORDER BY id DESC"; | |
57 | ||
58 | $query = OCP\DB::prepare($sql, $limit, $offset); | |
59 | $conversation = $query->execute( $args )->fetchAll(); | |
60 | ||
61 | if ( ! $offset && ! $from_date ) { | |
62 | // last id :http://www.php.net/manual/en/pdo.lastinsertid.php | |
63 | self::setUserRoomTime(); | |
64 | } | |
65 | ||
66 | return $conversation; | |
67 | } | |
68 | ||
69 | public static function newComment( $comment, $attachment ) // TODO optional $room parameter | |
70 | { | |
71 | $room = self::getRoom(); | |
72 | $userId = OC_User::getUser(); | |
73 | ||
74 | if ( USER_CONVERSATIONS_ATTACHMENTS && OCP\Share::isEnabled() && ! empty($attachment) ) { | |
75 | self::shareAttachment($attachment); | |
76 | } | |
77 | ||
78 | $query = OCP\DB::prepare('INSERT INTO *PREFIX*conversations (room,author,date,text,attachment) VALUES (?,?,?,?,?)'); | |
79 | $query->execute( array( | |
80 | $room, | |
81 | $userId, | |
82 | date( 'Y-m-d H:i:s'), | |
83 | trim($comment), | |
84 | $attachment | |
85 | )); | |
86 | self::setRoomTime(); | |
87 | return true; | |
88 | } | |
89 | ||
90 | public static function deleteComment( $id ) { | |
91 | if ( ! USER_CONVERSATIONS_CAN_DELETE ) | |
92 | return false; | |
93 | ||
94 | $query = OCP\DB::prepare('SELECT author FROM *PREFIX*conversations WHERE id = ?'); | |
95 | $result = $query->execute( array($id) )->fetch(); | |
96 | ||
97 | $uid = OC_User::getUser(); | |
98 | if ( $result['author'] == $uid || OC_User::isAdminUser($uid) ) { | |
99 | $query = OCP\DB::prepare('DELETE FROM *PREFIX*conversations WHERE id = ?'); | |
100 | $query->execute( array( $id )); | |
101 | return true; | |
102 | } else { | |
103 | return false; | |
104 | } | |
105 | } | |
106 | ||
107 | public static function getRooms() { | |
108 | $grooms = array(); | |
109 | $urooms = array(); | |
110 | $userId = OC_User::getUser(); | |
111 | $ordering = array(); | |
112 | // add groups the user contains if more than the user himself is in the room | |
113 | foreach (OC_Group::getUserGroups($userId) as $group) { | |
114 | if ( count(OC_Group::usersInGroup($group)) > 1 ) { | |
115 | $grooms["group:".$group] = array( "type" => "group", "name" => $group ); | |
116 | /*if ( UC_ROOM_ONLY_MSGS ) { // TODO: option: maybe private msgs only to users in same rooms ? | |
117 | } */ | |
118 | } | |
119 | } | |
120 | // if no group exist create default; NEW in 0.2: no default room! | |
121 | //if ( empty($grooms) ) | |
122 | // $grooms["group:default"] = array( "type" => "group", "name" => "default" ); | |
123 | ||
124 | // add all other users | |
125 | if ( UC_SINGLE_USER_MSG == true ) { | |
126 | foreach (OC_User::getUsers() as $user) { | |
127 | if ( $userId != $user ) { | |
128 | $urooms["user:".$user] = array( "type" => "user", "name" => $user ); | |
129 | } | |
130 | } | |
131 | } | |
132 | $rooms = $grooms + $urooms; | |
133 | return $rooms; | |
134 | } | |
135 | ||
136 | // return active room from user value. If not exists return first room from rooms-list | |
137 | public static function getRoom() | |
138 | { | |
139 | $room = OCP\Config::getUserValue(OC_User::getUser(), 'conversations', 'activeRoom', false); | |
140 | if ( $room == false ) { | |
141 | foreach (self::getRooms() as $key => $value) break; // get the first key of rooms | |
142 | $room = $key; | |
143 | } | |
144 | // TODO: return type and title array $room = array( "type" => "...", "label" => ... ); | |
145 | return $room; | |
146 | } | |
147 | ||
148 | // write current time to user conf on reading a conversation or after a polling request | |
149 | public static function setUserRoomTime( $room=false ) { | |
150 | $userId = OC_User::getUser(); | |
151 | $room = ( $room ) ? $room : self::getRoom(); | |
152 | ||
153 | $conf = OCP\Config::getUserValue( $userId, 'conversations', 'conf', false ); | |
154 | $conf = ( ! $conf ) ? array() : unserialize( $conf ); | |
155 | $conf['rooms'][$room]['rtime'] = time(); | |
156 | ||
157 | OCP\Config::setUserValue( $userId, 'conversations', 'conf', serialize($conf)); | |
158 | } | |
159 | ||
160 | ||
161 | // write time and new message id on submit new comment | |
162 | public static function setRoomTime( $room=false, $lastmsg=false ) { | |
163 | $userId = OC_User::getUser(); | |
164 | $room = ( $room ) ? $room : self::getRoom(); | |
165 | $time = time(); | |
166 | ||
167 | $rtype = explode(":", $room); | |
168 | $rtype = $rtype[0]; | |
169 | ||
170 | /* | |
171 | if ( ! $lastmsg ) { | |
172 | $query = OCP\DB::prepare("SELECT id FROM *PREFIX*conversations WHERE room = ? ORDER BY id DESC", 1, 0); | |
173 | $lastmsg = $query->execute( array($room) )->fetch(); | |
174 | $lastmsg = ( !$lastmsg ) ? 0 : $lastmsg['id']; | |
175 | } | |
176 | */ | |
177 | ||
178 | $conf = OCP\Config::getUserValue( $userId, 'conversations', 'conf', false ); | |
179 | $conf = ( ! $conf ) ? array() : unserialize( $conf ); | |
180 | //$conf['rooms'][$room]['lastmsg'] = $lastmsg; | |
181 | $conf['rooms'][$room]['wtime'] = $time; | |
182 | ||
183 | OCP\Config::setUserValue( $userId, 'conversations', 'conf', serialize($conf)); | |
184 | ||
185 | if ( $rtype == "group" ) { | |
186 | $gconf = OCP\Config::getAppValue( 'conversations', 'conf', false ); | |
187 | $gconf = ( ! $gconf ) ? array() : unserialize( $gconf ); | |
188 | //$gconf['rooms'][$room]['lastmsg'] = $lastmsg; | |
189 | $gconf['rooms'][$room]['wtime'] = $time; | |
190 | OCP\Config::setAppValue( 'conversations', 'conf', serialize($gconf) ); | |
191 | } | |
192 | } | |
193 | ||
194 | /* | |
195 | Test for new messages in all rooms */ | |
196 | public static function updateCheck() | |
197 | { | |
198 | $userId = OC_User::getUser(); | |
199 | $result = array(); | |
200 | ||
201 | $uconf = OCP\Config::getUserValue( $userId, 'conversations', 'conf', false ); | |
202 | $uconf = ( ! $uconf ) ? array() : unserialize( $uconf ); | |
203 | ||
204 | foreach (self::getRooms() as $rkey => $room) { | |
205 | //$rtype = explode(":", $room); | |
206 | if ( $room['type'] == "group" ) { | |
207 | $conf = OCP\Config::getAppValue( 'conversations', 'conf', false ); | |
208 | $conf = ( ! $conf ) ? array() : unserialize( $conf ); | |
209 | $wtime = @$conf['rooms'][$rkey]['wtime']; | |
210 | //$lastmsg = $conf['rooms'][$rkey]['lastmsg']; | |
211 | } else { | |
212 | $u2conf = OCP\Config::getUserValue( $room['name'], 'conversations', 'conf', false ); | |
213 | $u2conf = ( ! $u2conf ) ? array() : unserialize( $u2conf ); | |
214 | $wtime = @$u2conf['rooms']['user:'.$userId]['wtime']; // @ if user didnt logged in yet -> key rooms not exist | |
215 | } | |
216 | $urtime = @$uconf['rooms'][$rkey]['rtime']; | |
217 | ||
218 | //$ulastmsg = $uconf['rooms'][$rkey]['lastmsg']; | |
219 | if ( $wtime > $urtime ) { | |
220 | // get newer comments than last user room read time | |
221 | $new_comments = self::getConversation( $rkey, null, null, null, date( 'Y-m-d H:i:s', $urtime) ); | |
222 | $result[$rkey] = array( 'newmsgs' => count($new_comments) ); | |
223 | } | |
224 | } | |
225 | return $result; | |
226 | } | |
227 | ||
228 | /* | |
229 | Prepare post before display */ | |
230 | public static function preparePost($post) { | |
231 | $dateTimeObj = new DateTime($post['date']); | |
232 | return array( | |
233 | "id" => $post['id'], | |
234 | "avatar" => self::getUserAvatar($post['author']), | |
235 | "author" => OC_User::getDisplayName($post['author']), | |
236 | "date" => array( | |
237 | 'ISO8601' => $dateTimeObj->format(DateTime::ISO8601), | |
238 | 'datetime'=> date( 'Y-m-d H:i\h', strtotime($post['date']) ) | |
239 | ), | |
240 | "text" => (empty($post['text'])) ? "" : self::formatComment($post['text']), | |
241 | "attachment"=> (empty($post['attachment'])) ? "" : self::getAttachment($post['attachment']), | |
242 | "room" => $post['room'], | |
243 | ); | |
244 | } | |
245 | ||
246 | /* | |
247 | format plaintext of a comment */ | |
248 | private static function formatComment($comment) { | |
249 | $comment = htmlspecialchars($comment); | |
250 | $comment = nl2br($comment); | |
251 | $comment = preg_replace ( | |
252 | "/(?<!a href=\")(?<!src=\")((http|ftp)+(s)?:\/\/[^<>\s]+)/i", | |
253 | "<a href=\"\\0\" target=\"blank\">\\0</a>", | |
254 | $comment | |
255 | ); | |
256 | return $comment; | |
257 | } | |
258 | ||
259 | /* | |
260 | get attachments for printing posts */ | |
261 | private static function getAttachment($attachment) { | |
262 | $attachment = json_decode($attachment, true); | |
263 | switch ($attachment['type']) { | |
264 | case 'internal_file': | |
265 | return self::getInternalFileAttachment($attachment); | |
266 | break; | |
267 | ||
268 | case 'internal_image': | |
269 | return self::getInternalFileAttachment($attachment); | |
270 | break; | |
271 | ||
272 | default: | |
273 | return array(); | |
274 | break; | |
275 | } | |
276 | } | |
277 | ||
278 | /* | |
279 | Get internal file attachments for printing posts */ | |
280 | private static function getInternalFileAttachment($attachment) { | |
281 | $path = urldecode($attachment['path']); | |
282 | $path = substr($path, strpos($path, "/")+1 ); //remove root folder | |
283 | ||
284 | if ( $attachment['owner'] == OC_User::getUser() ) { | |
285 | // file-owner can use own path | |
286 | $path = \OC\Files\Filesystem::getPath($attachment['fileid']); | |
287 | } else { | |
288 | $item_shared = OCP\Share::getItemSharedWithBySource('file', $attachment['fileid']); | |
289 | if ( $item_shared != false ) { // if item is direct shared use shared-file target | |
290 | - | $path = "/Shared" . $item_shared['file_target']; |
290 | + | $path = "" . $item_shared['file_target']; |
291 | } else { | |
292 | // else search shared parent folder | |
293 | - | $path = "/Shared/" . self::getInheritedSharedPath( $attachment['owner'], urldecode($attachment['path']) ); |
293 | + | $path = "/" . self::getInheritedSharedPath( $attachment['owner'], urldecode($attachment['path']) ); |
294 | } | |
295 | } | |
296 | ||
297 | $userId = OC_User::getUser(); | |
298 | $view = new \OC\Files\View('/' . $userId . '/files'); | |
299 | $fileinfo = $view->getFileInfo($path); | |
300 | ||
301 | $download_url = OCP\Util::linkToRoute('download', array('file' => $path)); | |
302 | ||
303 | // File not found | |
304 | if ( \OC\Files\Filesystem::is_file( $path ) == false ) { | |
305 | $fileinfo['name'] = "File not found."; | |
306 | $download_url = "#"; | |
307 | } | |
308 | ||
309 | $result = array( | |
310 | "type" => $attachment['type'], | |
311 | "mimetype" => $fileinfo['mimetype'], | |
312 | "name" => $fileinfo['name'], | |
313 | "path" => $path, | |
314 | "download_url" => $download_url | |
315 | ); | |
316 | return $result; | |
317 | } | |
318 | ||
319 | /* | |
320 | Share item if not already done */ | |
321 | private static function shareAttachment($attachment) { | |
322 | $attachment = json_decode($attachment, true); | |
323 | $room = self::getRoom(); | |
324 | $room = explode(":", $room); | |
325 | ||
326 | $item_shared = self::isItemSharedWithGroup( true, 'file', $attachment['owner'], urldecode($attachment['path']) ); | |
327 | if ( ! $item_shared ) { | |
328 | $share_type = ( $room[0] == "group" ) ? OCP\Share::SHARE_TYPE_GROUP : OCP\Share::SHARE_TYPE_USER; | |
329 | \OCP\Share::shareItem('file', $attachment['fileid'], $share_type, $room[1], 17); | |
330 | } | |
331 | } | |
332 | ||
333 | /* | |
334 | Test if item is shared with a group */ | |
335 | private static function isItemSharedWithGroup($recursiv, $type, $owner, $path) { | |
336 | if ( empty($path) || $path == "files" ) | |
337 | return false; | |
338 | \OC_Util::setupFS($owner); | |
339 | \OC\Files\Filesystem::initMountPoints($owner); | |
340 | $view = new \OC\Files\View('/' . $owner . '/files'); | |
341 | $fileinfo = $view->getFileInfo( substr($path, strpos($path, "/") ) ); //get fileinfo from path (remove root folder) | |
342 | ||
343 | $share_with = self::getRoom(); | |
344 | $share_with = explode(":", $share_with); | |
345 | ||
346 | $share_type = ( $share_with[0] == "group" ) ? OCP\Share::SHARE_TYPE_GROUP : OCP\Share::SHARE_TYPE_USER; | |
347 | ||
348 | $query = \OC_DB::prepare( 'SELECT `file_target`, `permissions`, `expiration` | |
349 | FROM `*PREFIX*share` | |
350 | WHERE `share_type` = ? AND `item_source` = ? AND `item_type` = ? AND `share_with` = ?' ); | |
351 | ||
352 | $result = $query->execute( array($share_type, $fileinfo['fileid'], $type, $share_with[1]) )->fetchAll(); | |
353 | ||
354 | /* | |
355 | if ( count($result) == 0 ) { // item not shared, is parent folder shared? | |
356 | $parent_path = substr($fileinfo['path'], 0, strrpos($fileinfo['path'], "/") ); | |
357 | return self::isItemSharedWithGroup( 'folder', $owner, $parent_path ); | |
358 | } | |
359 | return true; | |
360 | */ | |
361 | if ( count($result) == 0 ) { // item not shared, is parent folder shared? | |
362 | if ( $recursiv ) { | |
363 | $parent_path = substr($fileinfo['path'], 0, strrpos($fileinfo['path'], "/") ); | |
364 | return self::isItemSharedWithGroup(true, 'folder', $owner, $parent_path ); | |
365 | } else { | |
366 | return false; | |
367 | } | |
368 | } | |
369 | return true; | |
370 | } | |
371 | ||
372 | /* | |
373 | Get shared path for inherited shared item */ | |
374 | private static function getInheritedSharedPath($owner, $path) { | |
375 | $shared_path = substr($path, strrpos($path, "/")+1 ); // filename | |
376 | do { | |
377 | $path = substr($path, 0, strrpos($path, "/") ); // parent path | |
378 | $shared_path = substr($path, strrpos($path, "/")+1 ) . "/" . $shared_path; // shared path + parent folder | |
379 | if ( empty($path) || $path == "files" ) break; | |
380 | } while ( ! self::isItemSharedWithGroup(false, 'folder', $owner, $path) ); | |
381 | ||
382 | return $shared_path; | |
383 | } | |
384 | ||
385 | /* | |
386 | Get user avatar from OC */ | |
387 | public static $avatars = array(); | |
388 | public static function getUserAvatar( $user ) | |
389 | { | |
390 | if ( ! array_key_exists($user, self::$avatars) ) { | |
391 | $avatar = New OC_Avatar($user); | |
392 | $image = $avatar->get(32); | |
393 | if ($image instanceof OC_Image) { | |
394 | $imageUrl = OC_Helper::linkToRoute ( 'core_avatar_get', array ('user' => $user, 'size' => 32) ) . '?requesttoken='. OC::$session->get('requesttoken'); | |
395 | self::$avatars[$user] = $imageUrl; | |
396 | } else { | |
397 | self::$avatars[$user] = ''; | |
398 | } | |
399 | } | |
400 | ||
401 | if ( self::$avatars[$user] != '' ) | |
402 | return self::$avatars[$user]; | |
403 | return ''; | |
404 | } | |
405 | ||
406 | /* | |
407 | Hook if a user is added or removed from group to change defualt room */ | |
408 | public static function changeUserGroup( $args ) { | |
409 | $query = OCP\DB::prepare('DELETE FROM *PREFIX*preferences WHERE userid = ? AND appid = "conversations" AND configkey = "activeRoom"'); | |
410 | $query->execute( array( $args['uid'] )); | |
411 | } | |
412 | } |