]> git.mxchange.org Git - quix0rs-gnu-social.git/blob - classes/Profile.php
Merge branch '0.8.x' into 0.9.x
[quix0rs-gnu-social.git] / classes / Profile.php
1 <?php
2 /*
3  * StatusNet - the distributed open-source microblogging tool
4  * Copyright (C) 2008, 2009, StatusNet, Inc.
5  *
6  * This program is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU Affero General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU Affero General Public License for more details.
15  *
16  * You should have received a copy of the GNU Affero General Public License
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  */
19
20 if (!defined('STATUSNET') && !defined('LACONICA')) { exit(1); }
21
22 /**
23  * Table Definition for profile
24  */
25 require_once INSTALLDIR.'/classes/Memcached_DataObject.php';
26
27 class Profile extends Memcached_DataObject
28 {
29     ###START_AUTOCODE
30     /* the code below is auto generated do not remove the above tag */
31
32     public $__table = 'profile';                         // table name
33     public $id;                              // int(4)  primary_key not_null
34     public $nickname;                        // varchar(64)  multiple_key not_null
35     public $fullname;                        // varchar(255)  multiple_key
36     public $profileurl;                      // varchar(255)
37     public $homepage;                        // varchar(255)  multiple_key
38     public $bio;                             // text()  multiple_key
39     public $location;                        // varchar(255)  multiple_key
40     public $created;                         // datetime()   not_null
41     public $modified;                        // timestamp()   not_null default_CURRENT_TIMESTAMP
42
43     /* Static get */
44     function staticGet($k,$v=NULL) { return Memcached_DataObject::staticGet('Profile',$k,$v); }
45
46     /* the code above is auto generated do not remove the tag below */
47     ###END_AUTOCODE
48
49     function getAvatar($width, $height=null)
50     {
51         if (is_null($height)) {
52             $height = $width;
53         }
54         return Avatar::pkeyGet(array('profile_id' => $this->id,
55                                      'width' => $width,
56                                      'height' => $height));
57     }
58
59     function getOriginalAvatar()
60     {
61         $avatar = DB_DataObject::factory('avatar');
62         $avatar->profile_id = $this->id;
63         $avatar->original = true;
64         if ($avatar->find(true)) {
65             return $avatar;
66         } else {
67             return null;
68         }
69     }
70
71     function setOriginal($filename)
72     {
73         $imagefile = new ImageFile($this->id, Avatar::path($filename));
74
75         $avatar = new Avatar();
76         $avatar->profile_id = $this->id;
77         $avatar->width = $imagefile->width;
78         $avatar->height = $imagefile->height;
79         $avatar->mediatype = image_type_to_mime_type($imagefile->type);
80         $avatar->filename = $filename;
81         $avatar->original = true;
82         $avatar->url = Avatar::url($filename);
83         $avatar->created = DB_DataObject_Cast::dateTime(); # current time
84
85         # XXX: start a transaction here
86
87         if (!$this->delete_avatars() || !$avatar->insert()) {
88             @unlink(Avatar::path($filename));
89             return null;
90         }
91
92         foreach (array(AVATAR_PROFILE_SIZE, AVATAR_STREAM_SIZE, AVATAR_MINI_SIZE) as $size) {
93             # We don't do a scaled one if original is our scaled size
94             if (!($avatar->width == $size && $avatar->height == $size)) {
95
96                 $scaled_filename = $imagefile->resize($size);
97
98                 //$scaled = DB_DataObject::factory('avatar');
99                 $scaled = new Avatar();
100                 $scaled->profile_id = $this->id;
101                 $scaled->width = $size;
102                 $scaled->height = $size;
103                 $scaled->original = false;
104                 $scaled->mediatype = image_type_to_mime_type($imagefile->type);
105                 $scaled->filename = $scaled_filename;
106                 $scaled->url = Avatar::url($scaled_filename);
107                 $scaled->created = DB_DataObject_Cast::dateTime(); # current time
108
109                 if (!$scaled->insert()) {
110                     return null;
111                 }
112             }
113         }
114
115         return $avatar;
116     }
117
118     function delete_avatars($original=true)
119     {
120         $avatar = new Avatar();
121         $avatar->profile_id = $this->id;
122         $avatar->find();
123         while ($avatar->fetch()) {
124             if ($avatar->original) {
125                 if ($original == false) {
126                     continue;
127                 }
128             }
129             $avatar->delete();
130         }
131         return true;
132     }
133
134     function getBestName()
135     {
136         return ($this->fullname) ? $this->fullname : $this->nickname;
137     }
138
139     # Get latest notice on or before date; default now
140     function getCurrentNotice($dt=null)
141     {
142         $notice = new Notice();
143         $notice->profile_id = $this->id;
144         if ($dt) {
145             $notice->whereAdd('created < "' . $dt . '"');
146         }
147         $notice->orderBy('created DESC, notice.id DESC');
148         $notice->limit(1);
149         if ($notice->find(true)) {
150             return $notice;
151         }
152         return null;
153     }
154
155     function getTaggedNotices($tag, $offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $max_id=0, $since=null)
156     {
157         $ids = Notice::stream(array($this, '_streamTaggedDirect'),
158                               array($tag),
159                               'profile:notice_ids_tagged:' . $this->id . ':' . $tag,
160                               $offset, $limit, $since_id, $max_id, $since);
161         return Notice::getStreamByIds($ids);
162     }
163
164     function getNotices($offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $max_id=0, $since=null)
165     {
166         // XXX: I'm not sure this is going to be any faster. It probably isn't.
167         $ids = Notice::stream(array($this, '_streamDirect'),
168                               array(),
169                               'profile:notice_ids:' . $this->id,
170                               $offset, $limit, $since_id, $max_id, $since);
171
172         return Notice::getStreamByIds($ids);
173     }
174
175     function _streamTaggedDirect($tag, $offset, $limit, $since_id, $max_id, $since)
176     {
177         // XXX It would be nice to do this without a join
178
179         $notice = new Notice();
180
181         $query =
182           "select id from notice join notice_tag on id=notice_id where tag='".
183           $notice->escape($tag) .
184           "' and profile_id=" . $notice->escape($this->id);
185
186         if ($since_id != 0) {
187             $query .= " and id > $since_id";
188         }
189
190         if ($max_id != 0) {
191             $query .= " and id < $max_id";
192         }
193
194         if (!is_null($since)) {
195             $query .= " and created > '" . date('Y-m-d H:i:s', $since) . "'";
196         }
197
198         $query .= ' order by id DESC';
199
200         if (!is_null($offset)) {
201             $query .= " LIMIT $limit OFFSET $offset";
202         }
203
204         $notice->query($query);
205
206         $ids = array();
207
208         while ($notice->fetch()) {
209             $ids[] = $notice->id;
210         }
211
212         return $ids;
213     }
214
215     function _streamDirect($offset, $limit, $since_id, $max_id, $since = null)
216     {
217         $notice = new Notice();
218
219         $notice->profile_id = $this->id;
220
221         $notice->selectAdd();
222         $notice->selectAdd('id');
223
224         if ($since_id != 0) {
225             $notice->whereAdd('id > ' . $since_id);
226         }
227
228         if ($max_id != 0) {
229             $notice->whereAdd('id <= ' . $max_id);
230         }
231
232         if (!is_null($since)) {
233             $notice->whereAdd('created > \'' . date('Y-m-d H:i:s', $since) . '\'');
234         }
235
236         $notice->orderBy('id DESC');
237
238         if (!is_null($offset)) {
239             $notice->limit($offset, $limit);
240         }
241
242         $ids = array();
243
244         if ($notice->find()) {
245             while ($notice->fetch()) {
246                 $ids[] = $notice->id;
247             }
248         }
249
250         return $ids;
251     }
252
253     function isMember($group)
254     {
255         $mem = new Group_member();
256
257         $mem->group_id = $group->id;
258         $mem->profile_id = $this->id;
259
260         if ($mem->find()) {
261             return true;
262         } else {
263             return false;
264         }
265     }
266
267     function isAdmin($group)
268     {
269         $mem = new Group_member();
270
271         $mem->group_id = $group->id;
272         $mem->profile_id = $this->id;
273         $mem->is_admin = 1;
274
275         if ($mem->find()) {
276             return true;
277         } else {
278             return false;
279         }
280     }
281
282     function avatarUrl($size=AVATAR_PROFILE_SIZE)
283     {
284         $avatar = $this->getAvatar($size);
285         if ($avatar) {
286             return $avatar->displayUrl();
287         } else {
288             return Avatar::defaultImage($size);
289         }
290     }
291
292     function getSubscriptions($offset=0, $limit=null)
293     {
294         $qry =
295           'SELECT profile.* ' .
296           'FROM profile JOIN subscription ' .
297           'ON profile.id = subscription.subscribed ' .
298           'WHERE subscription.subscriber = %d ' .
299           'AND subscription.subscribed != subscription.subscriber ' .
300           'ORDER BY subscription.created DESC ';
301
302         if (common_config('db','type') == 'pgsql') {
303             $qry .= ' LIMIT ' . $limit . ' OFFSET ' . $offset;
304         } else {
305             $qry .= ' LIMIT ' . $offset . ', ' . $limit;
306         }
307
308         $profile = new Profile();
309
310         $profile->query(sprintf($qry, $this->id));
311
312         return $profile;
313     }
314
315     function getSubscribers($offset=0, $limit=null)
316     {
317         $qry =
318           'SELECT profile.* ' .
319           'FROM profile JOIN subscription ' .
320           'ON profile.id = subscription.subscriber ' .
321           'WHERE subscription.subscribed = %d ' .
322           'AND subscription.subscribed != subscription.subscriber ' .
323           'ORDER BY subscription.created DESC ';
324
325         if ($offset) {
326             if (common_config('db','type') == 'pgsql') {
327                 $qry .= ' LIMIT ' . $limit . ' OFFSET ' . $offset;
328             } else {
329                 $qry .= ' LIMIT ' . $offset . ', ' . $limit;
330             }
331         }
332
333         $profile = new Profile();
334
335         $cnt = $profile->query(sprintf($qry, $this->id));
336
337         return $profile;
338     }
339
340     function subscriptionCount()
341     {
342         $c = common_memcache();
343
344         if (!empty($c)) {
345             $cnt = $c->get(common_cache_key('profile:subscription_count:'.$this->id));
346             if (is_integer($cnt)) {
347                 return (int) $cnt;
348             }
349         }
350
351         $sub = new Subscription();
352         $sub->subscriber = $this->id;
353
354         $cnt = (int) $sub->count('distinct subscribed');
355
356         $cnt = ($cnt > 0) ? $cnt - 1 : $cnt;
357
358         if (!empty($c)) {
359             $c->set(common_cache_key('profile:subscription_count:'.$this->id), $cnt);
360         }
361
362         return $cnt;
363     }
364
365     function subscriberCount()
366     {
367         $c = common_memcache();
368         if (!empty($c)) {
369             $cnt = $c->get(common_cache_key('profile:subscriber_count:'.$this->id));
370             if (is_integer($cnt)) {
371                 return (int) $cnt;
372             }
373         }
374
375         $sub = new Subscription();
376         $sub->subscribed = $this->id;
377
378         $cnt = (int) $sub->count('distinct subscriber');
379
380         $cnt = ($cnt > 0) ? $cnt - 1 : $cnt;
381
382         if (!empty($c)) {
383             $c->set(common_cache_key('profile:subscriber_count:'.$this->id), $cnt);
384         }
385
386         return $cnt;
387     }
388
389     function faveCount()
390     {
391         $c = common_memcache();
392         if (!empty($c)) {
393             $cnt = $c->get(common_cache_key('profile:fave_count:'.$this->id));
394             if (is_integer($cnt)) {
395                 return (int) $cnt;
396             }
397         }
398
399         $faves = new Fave();
400         $faves->user_id = $this->id;
401         $cnt = (int) $faves->count('distinct notice_id');
402
403         if (!empty($c)) {
404             $c->set(common_cache_key('profile:fave_count:'.$this->id), $cnt);
405         }
406
407         return $cnt;
408     }
409
410     function noticeCount()
411     {
412         $c = common_memcache();
413
414         if (!empty($c)) {
415             $cnt = $c->get(common_cache_key('profile:notice_count:'.$this->id));
416             if (is_integer($cnt)) {
417                 return (int) $cnt;
418             }
419         }
420
421         $notices = new Notice();
422         $notices->profile_id = $this->id;
423         $cnt = (int) $notices->count('distinct id');
424
425         if (!empty($c)) {
426             $c->set(common_cache_key('profile:notice_count:'.$this->id), $cnt);
427         }
428
429         return $cnt;
430     }
431
432     function blowSubscriberCount()
433     {
434         $c = common_memcache();
435         if (!empty($c)) {
436             $c->delete(common_cache_key('profile:subscriber_count:'.$this->id));
437         }
438     }
439
440     function blowSubscriptionCount()
441     {
442         $c = common_memcache();
443         if (!empty($c)) {
444             $c->delete(common_cache_key('profile:subscription_count:'.$this->id));
445         }
446     }
447
448     function blowFaveCount()
449     {
450         $c = common_memcache();
451         if (!empty($c)) {
452             $c->delete(common_cache_key('profile:fave_count:'.$this->id));
453         }
454     }
455
456     function blowNoticeCount()
457     {
458         $c = common_memcache();
459         if (!empty($c)) {
460             $c->delete(common_cache_key('profile:notice_count:'.$this->id));
461         }
462     }
463
464     static function maxBio()
465     {
466         $biolimit = common_config('profile', 'biolimit');
467         // null => use global limit (distinct from 0!)
468         if (is_null($biolimit)) {
469             $biolimit = common_config('site', 'textlimit');
470         }
471         return $biolimit;
472     }
473
474     static function bioTooLong($bio)
475     {
476         $biolimit = self::maxBio();
477         return ($biolimit > 0 && !empty($bio) && (mb_strlen($bio) > $biolimit));
478     }
479 }