]> git.mxchange.org Git - friendica.git/blob - include/identity.php
Improve dba::selectFirst calls
[friendica.git] / include / identity.php
1 <?php
2
3 /**
4  * @file include/identity.php
5  */
6 use Friendica\App;
7 use Friendica\Content\Feature;
8 use Friendica\Content\ForumManager;
9 use Friendica\Core\Cache;
10 use Friendica\Core\Config;
11 use Friendica\Core\PConfig;
12 use Friendica\Core\System;
13 use Friendica\Core\Worker;
14 use Friendica\Database\DBM;
15 use Friendica\Model\Contact;
16 use Friendica\Protocol\Diaspora;
17
18 require_once 'include/bbcode.php';
19 require_once 'mod/proxy.php';
20
21 /**
22  *
23  * @brief Loads a profile into the page sidebar.
24  *
25  * The function requires a writeable copy of the main App structure, and the nickname
26  * of a registered local account.
27  *
28  * If the viewer is an authenticated remote viewer, the profile displayed is the
29  * one that has been configured for his/her viewing in the Contact manager.
30  * Passing a non-zero profile ID can also allow a preview of a selected profile
31  * by the owner.
32  *
33  * Profile information is placed in the App structure for later retrieval.
34  * Honours the owner's chosen theme for display.
35  *
36  * @attention Should only be run in the _init() functions of a module. That ensures that
37  *      the theme is chosen before the _init() function of a theme is run, which will usually
38  *      load a lot of theme-specific content
39  *
40  * @param object $a           App
41  * @param string $nickname    string
42  * @param int    $profile     int
43  * @param array  $profiledata array
44  * @param boolean $show_connect Show connect link
45  */
46 function profile_load(App $a, $nickname, $profile = 0, $profiledata = array(), $show_connect = true)
47 {
48         $user = q(
49                 "SELECT `uid` FROM `user` WHERE `nickname` = '%s' LIMIT 1",
50                 dbesc($nickname)
51         );
52
53         if (!$user && !count($user) && !count($profiledata)) {
54                 logger('profile error: ' . $a->query_string, LOGGER_DEBUG);
55                 notice(t('Requested account is not available.') . EOL);
56                 $a->error = 404;
57                 return;
58         }
59
60         if (!x($a->page, 'aside')) {
61                 $a->page['aside'] = '';
62         }
63
64         if ($profiledata) {
65                 $a->page['aside'] .= profile_sidebar($profiledata, true, $show_connect);
66
67                 if (!DBM::is_result($user)) {
68                         return;
69                 }
70         }
71
72         $pdata = get_profiledata_by_nick($nickname, $user[0]['uid'], $profile);
73
74         if (empty($pdata) && empty($profiledata)) {
75                 logger('profile error: ' . $a->query_string, LOGGER_DEBUG);
76                 notice(t('Requested profile is not available.') . EOL);
77                 $a->error = 404;
78                 return;
79         }
80
81         // fetch user tags if this isn't the default profile
82
83         if (!$pdata['is-default']) {
84                 $x = q(
85                         "SELECT `pub_keywords` FROM `profile` WHERE `uid` = %d AND `is-default` = 1 LIMIT 1",
86                         intval($pdata['profile_uid'])
87                 );
88                 if ($x && count($x)) {
89                         $pdata['pub_keywords'] = $x[0]['pub_keywords'];
90                 }
91         }
92
93         $a->profile = $pdata;
94         $a->profile_uid = $pdata['profile_uid'];
95
96         $a->profile['mobile-theme'] = PConfig::get($a->profile['profile_uid'], 'system', 'mobile_theme');
97         $a->profile['network'] = NETWORK_DFRN;
98
99         $a->page['title'] = $a->profile['name'] . ' @ ' . $a->config['sitename'];
100
101         if (!$profiledata && !PConfig::get(local_user(), 'system', 'always_my_theme')) {
102                 $_SESSION['theme'] = $a->profile['theme'];
103         }
104
105         $_SESSION['mobile-theme'] = $a->profile['mobile-theme'];
106
107         /*
108          * load/reload current theme info
109          */
110
111         $a->set_template_engine(); // reset the template engine to the default in case the user's theme doesn't specify one
112
113         $theme_info_file = 'view/theme/' . current_theme() . '/theme.php';
114         if (file_exists($theme_info_file)) {
115                 require_once $theme_info_file;
116         }
117
118         if (!x($a->page, 'aside')) {
119                 $a->page['aside'] = '';
120         }
121
122         if (local_user() && local_user() == $a->profile['uid'] && $profiledata) {
123                 $a->page['aside'] .= replace_macros(
124                         get_markup_template('profile_edlink.tpl'), array(
125                                 '$editprofile' => t('Edit profile'),
126                                 '$profid' => $a->profile['id']
127                         )
128                 );
129         }
130
131         $block = ((Config::get('system', 'block_public') && !local_user() && !remote_user()) ? true : false);
132
133         /**
134          * @todo
135          * By now, the contact block isn't shown, when a different profile is given
136          * But: When this profile was on the same server, then we could display the contacts
137          */
138         if (!$profiledata) {
139                 $a->page['aside'] .= profile_sidebar($a->profile, $block, $show_connect);
140         }
141
142         return;
143 }
144
145 /**
146  * @brief Get all profil data of a local user
147  *
148  * If the viewer is an authenticated remote viewer, the profile displayed is the
149  * one that has been configured for his/her viewing in the Contact manager.
150  * Passing a non-zero profile ID can also allow a preview of a selected profile
151  * by the owner
152  *
153  * Includes all available profile data
154  *
155  * @param string $nickname nick
156  * @param int    $uid      uid
157  * @param int    $profile_id  ID of the profile
158  * @returns array
159  */
160 function get_profiledata_by_nick($nickname, $uid = 0, $profile_id = 0)
161 {
162         if (remote_user() && count($_SESSION['remote'])) {
163                 foreach ($_SESSION['remote'] as $visitor) {
164                         if ($visitor['uid'] == $uid) {
165                                 $contact = dba::selectFirst('contact', ['profile-id'], ['id' => $visitor['cid']]);
166                                 if (DBM::is_result($contact)) {
167                                         $profile_id = $contact['profile-id'];
168                                 }
169                                 break;
170                         }
171                 }
172         }
173
174         $profile = null;
175
176         if ($profile_id) {
177                 $profile = dba::fetch_first(
178                         "SELECT `contact`.`id` AS `contact_id`, `contact`.`photo` AS `contact_photo`,
179                                 `contact`.`thumb` AS `contact_thumb`, `contact`.`micro` AS `contact_micro`,
180                                 `profile`.`uid` AS `profile_uid`, `profile`.*,
181                                 `contact`.`avatar-date` AS picdate, `contact`.`addr`, `contact`.`url`, `user`.*
182                         FROM `profile`
183                         INNER JOIN `contact` on `contact`.`uid` = `profile`.`uid` AND `contact`.`self`
184                         INNER JOIN `user` ON `profile`.`uid` = `user`.`uid`
185                         WHERE `user`.`nickname` = ? AND `profile`.`id` = ? LIMIT 1",
186                         $nickname,
187                         intval($profile_id)
188                 );
189         }
190         if (!DBM::is_result($profile)) {
191                 $profile = dba::fetch_first(
192                         "SELECT `contact`.`id` AS `contact_id`, `contact`.`photo` as `contact_photo`,
193                                 `contact`.`thumb` AS `contact_thumb`, `contact`.`micro` AS `contact_micro`,
194                                 `profile`.`uid` AS `profile_uid`, `profile`.*,
195                                 `contact`.`avatar-date` AS picdate, `contact`.`addr`, `contact`.`url`, `user`.*
196                         FROM `profile`
197                         INNER JOIN `contact` ON `contact`.`uid` = `profile`.`uid` AND `contact`.`self`
198                         INNER JOIN `user` ON `profile`.`uid` = `user`.`uid`
199                         WHERE `user`.`nickname` = ? AND `profile`.`is-default` LIMIT 1",
200                         $nickname
201                 );
202         }
203
204         return $profile;
205 }
206
207 /**
208  * @brief Formats a profile for display in the sidebar.
209  *
210  * It is very difficult to templatise the HTML completely
211  * because of all the conditional logic.
212  *
213  * @param array $profile
214  * @param int $block
215  * @param boolean $show_connect Show connect link
216  *
217  * @return HTML string suitable for sidebar inclusion
218  *
219  * @note Returns empty string if passed $profile is wrong type or not populated
220  *
221  * @hooks 'profile_sidebar_enter'
222  *      array $profile - profile data
223  * @hooks 'profile_sidebar'
224  *      array $arr
225  */
226 function profile_sidebar($profile, $block = 0, $show_connect = true)
227 {
228         $a = get_app();
229
230         $o = '';
231         $location = false;
232
233         // This function can also use contact information in $profile
234         $is_contact = x($profile, 'cid');
235
236         if (!is_array($profile) && !count($profile)) {
237                 return $o;
238         }
239
240         $profile['picdate'] = urlencode(defaults($profile, 'picdate', ''));
241
242         if (($profile['network'] != '') && ($profile['network'] != NETWORK_DFRN)) {
243                 $profile['network_name'] = format_network_name($profile['network'], $profile['url']);
244         } else {
245                 $profile['network_name'] = '';
246         }
247
248         call_hooks('profile_sidebar_enter', $profile);
249
250
251         // don't show connect link to yourself
252         $connect = $profile['uid'] != local_user() ? t('Connect') : false;
253
254         // don't show connect link to authenticated visitors either
255         if (remote_user() && count($_SESSION['remote'])) {
256                 foreach ($_SESSION['remote'] as $visitor) {
257                         if ($visitor['uid'] == $profile['uid']) {
258                                 $connect = false;
259                                 break;
260                         }
261                 }
262         }
263
264         if (!$show_connect) {
265                 $connect = false;
266         }
267
268         // Is the local user already connected to that user?
269         if ($connect && local_user()) {
270                 if (isset($profile['url'])) {
271                         $profile_url = normalise_link($profile['url']);
272                 } else {
273                         $profile_url = normalise_link(System::baseUrl() . '/profile/' . $profile['nickname']);
274                 }
275
276                 if (dba::exists('contact', array('pending' => false, 'uid' => local_user(), 'nurl' => $profile_url))) {
277                         $connect = false;
278                 }
279         }
280
281         if ($connect && ($profile['network'] != NETWORK_DFRN) && !isset($profile['remoteconnect'])) {
282                 $connect = false;
283         }
284
285         $remoteconnect = null;
286         if (isset($profile['remoteconnect'])) {
287                 $remoteconnect = $profile['remoteconnect'];
288         }
289
290         if ($connect && ($profile['network'] == NETWORK_DFRN) && !isset($remoteconnect)) {
291                 $subscribe_feed = t('Atom feed');
292         } else {
293                 $subscribe_feed = false;
294         }
295
296         if (remote_user() || (get_my_url() && x($profile, 'unkmail') && ($profile['uid'] != local_user()))) {
297                 $wallmessage = t('Message');
298                 $wallmessage_link = 'wallmessage/' . $profile['nickname'];
299
300                 if (remote_user()) {
301                         $r = q(
302                                 "SELECT `url` FROM `contact` WHERE `uid` = %d AND `id` = '%s' AND `rel` = %d",
303                                 intval($profile['uid']),
304                                 intval(remote_user()),
305                                 intval(CONTACT_IS_FRIEND)
306                         );
307                 } else {
308                         $r = q(
309                                 "SELECT `url` FROM `contact` WHERE `uid` = %d AND `nurl` = '%s' AND `rel` = %d",
310                                 intval($profile['uid']),
311                                 dbesc(normalise_link(get_my_url())),
312                                 intval(CONTACT_IS_FRIEND)
313                         );
314                 }
315                 if ($r) {
316                         $remote_url = $r[0]['url'];
317                         $message_path = preg_replace('=(.*)/profile/(.*)=ism', '$1/message/new/', $remote_url);
318                         $wallmessage_link = $message_path . base64_encode($profile['addr']);
319                 }
320         } else {
321                 $wallmessage = false;
322                 $wallmessage_link = false;
323         }
324
325         // show edit profile to yourself
326         if (!$is_contact && $profile['uid'] == local_user() && Feature::isEnabled(local_user(), 'multi_profiles')) {
327                 $profile['edit'] = array(System::baseUrl() . '/profiles', t('Profiles'), '', t('Manage/edit profiles'));
328                 $r = q(
329                         "SELECT * FROM `profile` WHERE `uid` = %d",
330                         local_user()
331                 );
332
333                 $profile['menu'] = array(
334                         'chg_photo' => t('Change profile photo'),
335                         'cr_new' => t('Create New Profile'),
336                         'entries' => array(),
337                 );
338
339                 if (DBM::is_result($r)) {
340                         foreach ($r as $rr) {
341                                 $profile['menu']['entries'][] = array(
342                                         'photo' => $rr['thumb'],
343                                         'id' => $rr['id'],
344                                         'alt' => t('Profile Image'),
345                                         'profile_name' => $rr['profile-name'],
346                                         'isdefault' => $rr['is-default'],
347                                         'visibile_to_everybody' => t('visible to everybody'),
348                                         'edit_visibility' => t('Edit visibility'),
349                                 );
350                         }
351                 }
352         }
353         if (!$is_contact && $profile['uid'] == local_user() && !Feature::isEnabled(local_user(), 'multi_profiles')) {
354                 $profile['edit'] = array(System::baseUrl() . '/profiles/' . $profile['id'], t('Edit profile'), '', t('Edit profile'));
355                 $profile['menu'] = array(
356                         'chg_photo' => t('Change profile photo'),
357                         'cr_new' => null,
358                         'entries' => array(),
359                 );
360         }
361
362         // Fetch the account type
363         $account_type = Contact::getAccountType($profile);
364
365         if (x($profile, 'address')
366                 || x($profile, 'location')
367                 || x($profile, 'locality')
368                 || x($profile, 'region')
369                 || x($profile, 'postal-code')
370                 || x($profile, 'country-name')
371         ) {
372                 $location = t('Location:');
373         }
374
375         $gender   = x($profile, 'gender')   ? t('Gender:')   : false;
376         $marital  = x($profile, 'marital')  ? t('Status:')   : false;
377         $homepage = x($profile, 'homepage') ? t('Homepage:') : false;
378         $about    = x($profile, 'about')    ? t('About:')    : false;
379         $xmpp     = x($profile, 'xmpp')     ? t('XMPP:')     : false;
380
381         if ((x($profile, 'hidewall') || $block) && !local_user() && !remote_user()) {
382                 $location = $gender = $marital = $homepage = $about = false;
383         }
384
385         $split_name = Diaspora::splitName($profile['name']);
386         $firstname = $split_name['first'];
387         $lastname = $split_name['last'];
388
389         if (x($profile, 'guid')) {
390                 $diaspora = array(
391                         'guid' => $profile['guid'],
392                         'podloc' => System::baseUrl(),
393                         'searchable' => (($profile['publish'] && $profile['net-publish']) ? 'true' : 'false' ),
394                         'nickname' => $profile['nickname'],
395                         'fullname' => $profile['name'],
396                         'firstname' => $firstname,
397                         'lastname' => $lastname,
398                         'photo300' => $profile['contact_photo'],
399                         'photo100' => $profile['contact_thumb'],
400                         'photo50' => $profile['contact_micro'],
401                 );
402         } else {
403                 $diaspora = false;
404         }
405
406         $contact_block = '';
407         $updated = '';
408         $contacts = 0;
409         if (!$block) {
410                 $contact_block = contact_block();
411
412                 if (is_array($a->profile) && !$a->profile['hide-friends']) {
413                         $r = q(
414                                 "SELECT `gcontact`.`updated` FROM `contact` INNER JOIN `gcontact` WHERE `gcontact`.`nurl` = `contact`.`nurl` AND `self` AND `uid` = %d LIMIT 1",
415                                 intval($a->profile['uid'])
416                         );
417                         if (DBM::is_result($r)) {
418                                 $updated = date('c', strtotime($r[0]['updated']));
419                         }
420
421                         $r = q(
422                                 "SELECT COUNT(*) AS `total` FROM `contact`
423                                 WHERE `uid` = %d
424                                         AND NOT `self` AND NOT `blocked` AND NOT `pending`
425                                         AND NOT `hidden` AND NOT `archive`
426                                         AND `network` IN ('%s', '%s', '%s', '')",
427                                 intval($profile['uid']),
428                                 dbesc(NETWORK_DFRN),
429                                 dbesc(NETWORK_DIASPORA),
430                                 dbesc(NETWORK_OSTATUS)
431                         );
432                         if (DBM::is_result($r)) {
433                                 $contacts = intval($r[0]['total']);
434                         }
435                 }
436         }
437
438         $p = array();
439         foreach ($profile as $k => $v) {
440                 $k = str_replace('-', '_', $k);
441                 $p[$k] = $v;
442         }
443
444         if (isset($p['about'])) {
445                 $p['about'] = bbcode($p['about']);
446         }
447
448         if (isset($p['address'])) {
449                 $p['address'] = bbcode($p['address']);
450         } else {
451                 $p['address'] = bbcode($p['location']);
452         }
453
454         if (isset($p['photo'])) {
455                 $p['photo'] = proxy_url($p['photo'], false, PROXY_SIZE_SMALL);
456         }
457
458         $tpl = get_markup_template('profile_vcard.tpl');
459         $o .= replace_macros($tpl, array(
460                 '$profile' => $p,
461                 '$xmpp' => $xmpp,
462                 '$connect' => $connect,
463                 '$remoteconnect' => $remoteconnect,
464                 '$subscribe_feed' => $subscribe_feed,
465                 '$wallmessage' => $wallmessage,
466                 '$wallmessage_link' => $wallmessage_link,
467                 '$account_type' => $account_type,
468                 '$location' => $location,
469                 '$gender' => $gender,
470                 '$marital' => $marital,
471                 '$homepage' => $homepage,
472                 '$about' => $about,
473                 '$network' => t('Network:'),
474                 '$contacts' => $contacts,
475                 '$updated' => $updated,
476                 '$diaspora' => $diaspora,
477                 '$contact_block' => $contact_block,
478         ));
479
480         $arr = array('profile' => &$profile, 'entry' => &$o);
481
482         call_hooks('profile_sidebar', $arr);
483
484         return $o;
485 }
486
487 function get_birthdays()
488 {
489         $a = get_app();
490         $o = '';
491
492         if (!local_user() || $a->is_mobile || $a->is_tablet) {
493                 return $o;
494         }
495
496         /*
497          * $mobile_detect = new Mobile_Detect();
498          * $is_mobile = $mobile_detect->isMobile() || $mobile_detect->isTablet();
499          *              if ($is_mobile)
500          *                      return $o;
501          */
502
503         $bd_format = t('g A l F d'); // 8 AM Friday January 18
504         $bd_short = t('F d');
505
506         $cachekey = 'get_birthdays:' . local_user();
507         $r = Cache::get($cachekey);
508         if (is_null($r)) {
509                 $s = dba::p(
510                         "SELECT `event`.*, `event`.`id` AS `eid`, `contact`.* FROM `event`
511                         INNER JOIN `contact` ON `contact`.`id` = `event`.`cid`
512                         WHERE `event`.`uid` = ? AND `type` = 'birthday' AND `start` < ? AND `finish` > ?
513                         ORDER BY `start` ASC ",
514                         local_user(),
515                         datetime_convert('UTC', 'UTC', 'now + 6 days'),
516                         datetime_convert('UTC', 'UTC', 'now')
517                 );
518                 if (DBM::is_result($s)) {
519                         $r = dba::inArray($s);
520                         Cache::set($cachekey, $r, CACHE_HOUR);
521                 }
522         }
523         if (DBM::is_result($r)) {
524                 $total = 0;
525                 $now = strtotime('now');
526                 $cids = array();
527
528                 $istoday = false;
529                 foreach ($r as $rr) {
530                         if (strlen($rr['name'])) {
531                                 $total ++;
532                         }
533                         if ((strtotime($rr['start'] . ' +00:00') < $now) && (strtotime($rr['finish'] . ' +00:00') > $now)) {
534                                 $istoday = true;
535                         }
536                 }
537                 $classtoday = $istoday ? ' birthday-today ' : '';
538                 if ($total) {
539                         foreach ($r as &$rr) {
540                                 if (!strlen($rr['name'])) {
541                                         continue;
542                                 }
543
544                                 // avoid duplicates
545
546                                 if (in_array($rr['cid'], $cids)) {
547                                         continue;
548                                 }
549                                 $cids[] = $rr['cid'];
550
551                                 $today = (((strtotime($rr['start'] . ' +00:00') < $now) && (strtotime($rr['finish'] . ' +00:00') > $now)) ? true : false);
552                                 $url = $rr['url'];
553                                 if ($rr['network'] === NETWORK_DFRN) {
554                                         $url = System::baseUrl() . '/redir/' . $rr['cid'];
555                                 }
556
557                                 $rr['link'] = $url;
558                                 $rr['title'] = $rr['name'];
559                                 $rr['date'] = day_translate(datetime_convert('UTC', $a->timezone, $rr['start'], $rr['adjust'] ? $bd_format : $bd_short)) . (($today) ? ' ' . t('[today]') : '');
560                                 $rr['startime'] = null;
561                                 $rr['today'] = $today;
562                         }
563                 }
564         }
565         $tpl = get_markup_template('birthdays_reminder.tpl');
566         return replace_macros($tpl, array(
567                 '$baseurl' => System::baseUrl(),
568                 '$classtoday' => $classtoday,
569                 '$count' => $total,
570                 '$event_reminders' => t('Birthday Reminders'),
571                 '$event_title' => t('Birthdays this week:'),
572                 '$events' => $r,
573                 '$lbr' => '{', // raw brackets mess up if/endif macro processing
574                 '$rbr' => '}'
575         ));
576 }
577
578 function get_events()
579 {
580         require_once 'include/bbcode.php';
581
582         $a = get_app();
583
584         if (!local_user() || $a->is_mobile || $a->is_tablet) {
585                 return $o;
586         }
587
588         /*
589          *      $mobile_detect = new Mobile_Detect();
590          *              $is_mobile = $mobile_detect->isMobile() || $mobile_detect->isTablet();
591          *              if ($is_mobile)
592          *                      return $o;
593          */
594
595         $bd_format = t('g A l F d'); // 8 AM Friday January 18
596         $classtoday = '';
597
598         $s = dba::p(
599                 "SELECT `event`.* FROM `event`
600                 WHERE `event`.`uid` = ? AND `type` != 'birthday' AND `start` < ? AND `start` >= ?
601                 ORDER BY `start` ASC ",
602                 local_user(),
603                 datetime_convert('UTC', 'UTC', 'now + 7 days'),
604                 datetime_convert('UTC', 'UTC', 'now - 1 days')
605         );
606
607         $r = array();
608
609         if (DBM::is_result($s)) {
610                 $istoday = false;
611
612                 while ($rr = dba::fetch($s)) {
613                         if (strlen($rr['name'])) {
614                                 $total ++;
615                         }
616
617                         $strt = datetime_convert('UTC', $rr['convert'] ? $a->timezone : 'UTC', $rr['start'], 'Y-m-d');
618                         if ($strt === datetime_convert('UTC', $a->timezone, 'now', 'Y-m-d')) {
619                                 $istoday = true;
620                         }
621
622                         $title = strip_tags(html_entity_decode(bbcode($rr['summary']), ENT_QUOTES, 'UTF-8'));
623
624                         if (strlen($title) > 35) {
625                                 $title = substr($title, 0, 32) . '... ';
626                         }
627
628                         $description = substr(strip_tags(bbcode($rr['desc'])), 0, 32) . '... ';
629                         if (!$description) {
630                                 $description = t('[No description]');
631                         }
632
633                         $strt = datetime_convert('UTC', $rr['convert'] ? $a->timezone : 'UTC', $rr['start']);
634
635                         if (substr($strt, 0, 10) < datetime_convert('UTC', $a->timezone, 'now', 'Y-m-d')) {
636                                 continue;
637                         }
638
639                         $today = ((substr($strt, 0, 10) === datetime_convert('UTC', $a->timezone, 'now', 'Y-m-d')) ? true : false);
640
641                         $rr['title'] = $title;
642                         $rr['description'] = $description;
643                         $rr['date'] = day_translate(datetime_convert('UTC', $rr['adjust'] ? $a->timezone : 'UTC', $rr['start'], $bd_format)) . (($today) ? ' ' . t('[today]') : '');
644                         $rr['startime'] = $strt;
645                         $rr['today'] = $today;
646
647                         $r[] = $rr;
648                 }
649                 dba::close($s);
650                 $classtoday = (($istoday) ? 'event-today' : '');
651         }
652         $tpl = get_markup_template('events_reminder.tpl');
653         return replace_macros($tpl, array(
654                 '$baseurl' => System::baseUrl(),
655                 '$classtoday' => $classtoday,
656                 '$count' => count($r),
657                 '$event_reminders' => t('Event Reminders'),
658                 '$event_title' => t('Events this week:'),
659                 '$events' => $r,
660         ));
661 }
662
663 function advanced_profile(App $a)
664 {
665         $o = '';
666         $uid = $a->profile['uid'];
667
668         $o .= replace_macros(
669                 get_markup_template('section_title.tpl'), array(
670                         '$title' => t('Profile')
671                 )
672         );
673
674         if ($a->profile['name']) {
675                 $tpl = get_markup_template('profile_advanced.tpl');
676
677                 $profile = array();
678
679                 $profile['fullname'] = array(t('Full Name:'), $a->profile['name']);
680
681                 if ($a->profile['gender']) {
682                         $profile['gender'] = array(t('Gender:'), $a->profile['gender']);
683                 }
684
685                 if (($a->profile['dob']) && ($a->profile['dob'] > '0001-01-01')) {
686                         $year_bd_format = t('j F, Y');
687                         $short_bd_format = t('j F');
688
689                         $val = intval($a->profile['dob']) ?
690                                 day_translate(datetime_convert('UTC', 'UTC', $a->profile['dob'] . ' 00:00 +00:00', $year_bd_format))
691                                 : day_translate(datetime_convert('UTC', 'UTC', '2001-' . substr($a->profile['dob'], 5) . ' 00:00 +00:00', $short_bd_format));
692
693                         $profile['birthday'] = array(t('Birthday:'), $val);
694                 }
695
696                 if (!empty($a->profile['dob'])
697                         && $a->profile['dob'] > '0001-01-01'
698                         && $age = age($a->profile['dob'], $a->profile['timezone'], '')
699                 ) {
700                         $profile['age'] = array(t('Age:'), $age);
701                 }
702
703                 if ($a->profile['marital']) {
704                         $profile['marital'] = array(t('Status:'), $a->profile['marital']);
705                 }
706
707                 /// @TODO Maybe use x() here, plus below?
708                 if ($a->profile['with']) {
709                         $profile['marital']['with'] = $a->profile['with'];
710                 }
711
712                 if (strlen($a->profile['howlong']) && $a->profile['howlong'] >= NULL_DATE) {
713                         $profile['howlong'] = relative_date($a->profile['howlong'], t('for %1$d %2$s'));
714                 }
715
716                 if ($a->profile['sexual']) {
717                         $profile['sexual'] = array(t('Sexual Preference:'), $a->profile['sexual']);
718                 }
719
720                 if ($a->profile['homepage']) {
721                         $profile['homepage'] = array(t('Homepage:'), linkify($a->profile['homepage']));
722                 }
723
724                 if ($a->profile['hometown']) {
725                         $profile['hometown'] = array(t('Hometown:'), linkify($a->profile['hometown']));
726                 }
727
728                 if ($a->profile['pub_keywords']) {
729                         $profile['pub_keywords'] = array(t('Tags:'), $a->profile['pub_keywords']);
730                 }
731
732                 if ($a->profile['politic']) {
733                         $profile['politic'] = array(t('Political Views:'), $a->profile['politic']);
734                 }
735
736                 if ($a->profile['religion']) {
737                         $profile['religion'] = array(t('Religion:'), $a->profile['religion']);
738                 }
739
740                 if ($txt = prepare_text($a->profile['about'])) {
741                         $profile['about'] = array(t('About:'), $txt);
742                 }
743
744                 if ($txt = prepare_text($a->profile['interest'])) {
745                         $profile['interest'] = array(t('Hobbies/Interests:'), $txt);
746                 }
747
748                 if ($txt = prepare_text($a->profile['likes'])) {
749                         $profile['likes'] = array(t('Likes:'), $txt);
750                 }
751
752                 if ($txt = prepare_text($a->profile['dislikes'])) {
753                         $profile['dislikes'] = array(t('Dislikes:'), $txt);
754                 }
755
756                 if ($txt = prepare_text($a->profile['contact'])) {
757                         $profile['contact'] = array(t('Contact information and Social Networks:'), $txt);
758                 }
759
760                 if ($txt = prepare_text($a->profile['music'])) {
761                         $profile['music'] = array(t('Musical interests:'), $txt);
762                 }
763
764                 if ($txt = prepare_text($a->profile['book'])) {
765                         $profile['book'] = array(t('Books, literature:'), $txt);
766                 }
767
768                 if ($txt = prepare_text($a->profile['tv'])) {
769                         $profile['tv'] = array(t('Television:'), $txt);
770                 }
771
772                 if ($txt = prepare_text($a->profile['film'])) {
773                         $profile['film'] = array(t('Film/dance/culture/entertainment:'), $txt);
774                 }
775
776                 if ($txt = prepare_text($a->profile['romance'])) {
777                         $profile['romance'] = array(t('Love/Romance:'), $txt);
778                 }
779
780                 if ($txt = prepare_text($a->profile['work'])) {
781                         $profile['work'] = array(t('Work/employment:'), $txt);
782                 }
783
784                 if ($txt = prepare_text($a->profile['education'])) {
785                         $profile['education'] = array(t('School/education:'), $txt);
786                 }
787
788                 //show subcribed forum if it is enabled in the usersettings
789                 if (Feature::isEnabled($uid, 'forumlist_profile')) {
790                         $profile['forumlist'] = array(t('Forums:'), ForumManager::profileAdvanced($uid));
791                 }
792
793                 if ($a->profile['uid'] == local_user()) {
794                         $profile['edit'] = array(System::baseUrl() . '/profiles/' . $a->profile['id'], t('Edit profile'), '', t('Edit profile'));
795                 }
796
797                 return replace_macros($tpl, array(
798                         '$title' => t('Profile'),
799                         '$basic' => t('Basic'),
800                         '$advanced' => t('Advanced'),
801                         '$profile' => $profile
802                 ));
803         }
804
805         return '';
806 }
807
808 function profile_tabs($a, $is_owner = false, $nickname = null)
809 {
810         if (is_null($nickname)) {
811                 $nickname = $a->user['nickname'];
812         }
813
814         $tab = false;
815         if (x($_GET, 'tab')) {
816                 $tab = notags(trim($_GET['tab']));
817         }
818
819         $url = System::baseUrl() . '/profile/' . $nickname;
820
821         $tabs = array(
822                 array(
823                         'label' => t('Status'),
824                         'url'   => $url,
825                         'sel'   => !$tab && $a->argv[0] == 'profile' ? 'active' : '',
826                         'title' => t('Status Messages and Posts'),
827                         'id'    => 'status-tab',
828                         'accesskey' => 'm',
829                 ),
830                 array(
831                         'label' => t('Profile'),
832                         'url'   => $url . '/?tab=profile',
833                         'sel'   => $tab == 'profile' ? 'active' : '',
834                         'title' => t('Profile Details'),
835                         'id'    => 'profile-tab',
836                         'accesskey' => 'r',
837                 ),
838                 array(
839                         'label' => t('Photos'),
840                         'url'   => System::baseUrl() . '/photos/' . $nickname,
841                         'sel'   => !$tab && $a->argv[0] == 'photos' ? 'active' : '',
842                         'title' => t('Photo Albums'),
843                         'id'    => 'photo-tab',
844                         'accesskey' => 'h',
845                 ),
846                 array(
847                         'label' => t('Videos'),
848                         'url'   => System::baseUrl() . '/videos/' . $nickname,
849                         'sel'   => !$tab && $a->argv[0] == 'videos' ? 'active' : '',
850                         'title' => t('Videos'),
851                         'id'    => 'video-tab',
852                         'accesskey' => 'v',
853                 ),
854         );
855
856         // the calendar link for the full featured events calendar
857         if ($is_owner && $a->theme_events_in_profile) {
858                 $tabs[] = array(
859                         'label' => t('Events'),
860                         'url'   => System::baseUrl() . '/events',
861                         'sel'   => !$tab && $a->argv[0] == 'events' ? 'active' : '',
862                         'title' => t('Events and Calendar'),
863                         'id'    => 'events-tab',
864                         'accesskey' => 'e',
865                 );
866                 // if the user is not the owner of the calendar we only show a calendar
867                 // with the public events of the calendar owner
868         } elseif (!$is_owner) {
869                 $tabs[] = array(
870                         'label' => t('Events'),
871                         'url'   => System::baseUrl() . '/cal/' . $nickname,
872                         'sel'   => !$tab && $a->argv[0] == 'cal' ? 'active' : '',
873                         'title' => t('Events and Calendar'),
874                         'id'    => 'events-tab',
875                         'accesskey' => 'e',
876                 );
877         }
878
879         if ($is_owner) {
880                 $tabs[] = array(
881                         'label' => t('Personal Notes'),
882                         'url'   => System::baseUrl() . '/notes',
883                         'sel'   => !$tab && $a->argv[0] == 'notes' ? 'active' : '',
884                         'title' => t('Only You Can See This'),
885                         'id'    => 'notes-tab',
886                         'accesskey' => 't',
887                 );
888         }
889
890         if ((!$is_owner) && ((count($a->profile)) || (!$a->profile['hide-friends']))) {
891                 $tabs[] = array(
892                         'label' => t('Contacts'),
893                         'url'   => System::baseUrl() . '/viewcontacts/' . $nickname,
894                         'sel'   => !$tab && $a->argv[0] == 'viewcontacts' ? 'active' : '',
895                         'title' => t('Contacts'),
896                         'id'    => 'viewcontacts-tab',
897                         'accesskey' => 'k',
898                 );
899         }
900
901         $arr = array('is_owner' => $is_owner, 'nickname' => $nickname, 'tab' => $tab, 'tabs' => $tabs);
902         call_hooks('profile_tabs', $arr);
903
904         $tpl = get_markup_template('common_tabs.tpl');
905
906         return replace_macros($tpl, array('$tabs' => $arr['tabs']));
907 }
908
909 /**
910  * Retrieves the my_url session variable
911  *
912  * @return string
913  */
914 function get_my_url()
915 {
916         if (x($_SESSION, 'my_url')) {
917                 return $_SESSION['my_url'];
918         }
919         return null;
920 }
921
922 function zrl_init(App $a)
923 {
924         $my_url = get_my_url();
925         $my_url = validate_url($my_url);
926         if ($my_url) {
927                 // Is it a DDoS attempt?
928                 // The check fetches the cached value from gprobe to reduce the load for this system
929                 $urlparts = parse_url($my_url);
930
931                 $result = Cache::get('gprobe:' . $urlparts['host']);
932                 if ((!is_null($result)) && (in_array($result['network'], array(NETWORK_FEED, NETWORK_PHANTOM)))) {
933                         logger('DDoS attempt detected for ' . $urlparts['host'] . ' by ' . $_SERVER['REMOTE_ADDR'] . '. server data: ' . print_r($_SERVER, true), LOGGER_DEBUG);
934                         return;
935                 }
936
937                 Worker::add(PRIORITY_LOW, 'GProbe', $my_url);
938                 $arr = array('zrl' => $my_url, 'url' => $a->cmd);
939                 call_hooks('zrl_init', $arr);
940         }
941 }
942
943 function zrl($s, $force = false)
944 {
945         if (!strlen($s)) {
946                 return $s;
947         }
948         if ((!strpos($s, '/profile/')) && (!$force)) {
949                 return $s;
950         }
951         if ($force && substr($s, -1, 1) !== '/') {
952                 $s = $s . '/';
953         }
954         $achar = strpos($s, '?') ? '&' : '?';
955         $mine = get_my_url();
956         if ($mine && !link_compare($mine, $s)) {
957                 return $s . $achar . 'zrl=' . urlencode($mine);
958         }
959         return $s;
960 }
961
962 /**
963  * @brief Get the user ID of the page owner
964  *
965  * Used from within PCSS themes to set theme parameters. If there's a
966  * puid request variable, that is the "page owner" and normally their theme
967  * settings take precedence; unless a local user sets the "always_my_theme"
968  * system pconfig, which means they don't want to see anybody else's theme
969  * settings except their own while on this site.
970  *
971  * @return int user ID
972  *
973  * @note Returns local_user instead of user ID if "always_my_theme"
974  *      is set to true
975  */
976 function get_theme_uid()
977 {
978         $uid = ((!empty($_REQUEST['puid'])) ? intval($_REQUEST['puid']) : 0);
979         if ((local_user()) && ((PConfig::get(local_user(), 'system', 'always_my_theme')) || (!$uid))) {
980                 return local_user();
981         }
982
983         return $uid;
984 }